@bongos/core 1.19.420 → 1.19.422

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/.bongos-core.json +68 -33
  2. package/docs/copy-inventory.md +282 -281
  3. package/docs/copy-registry.json +375 -366
  4. package/docs/design/mocks/hub/mine.html +377 -0
  5. package/docs/design/projects-hub-direction-v2.md +25 -1
  6. package/docs/file-map.md +1 -0
  7. package/docs/module-api-changelog.md +4 -0
  8. package/modules/hall-ui/public/settings.html +3 -2
  9. package/modules/hall-ui/public/settings.js +10 -6
  10. package/modules/platform-identity/account-visibility.js +94 -3
  11. package/modules/platform-identity/platform-identity.js +45 -50
  12. package/modules/platform-identity/routes/connections.js +3 -3
  13. package/modules/ui-design/kit/fixtures/featured-hub.json +1 -0
  14. package/modules/ui-design/kit/fixtures/provisioning-instances-empty.json +4 -0
  15. package/modules/ui-design/kit/fixtures/provisioning-instances.json +99 -0
  16. package/modules/ui-design/kit/lib.js +6 -2
  17. package/modules/ui-design/kit/probe.js +1 -1
  18. package/modules/ui-design/kit/render.js +1 -1
  19. package/modules/ui-design/kit/serve.js +63 -2
  20. package/package-lock.json +2 -2
  21. package/package.json +1 -1
  22. package/public-landing/assets/cosmos.css +246 -26
  23. package/public-landing/projects-empty.states.json +49 -0
  24. package/public-landing/projects-floor.states.json +63 -0
  25. package/public-landing/projects.html +113 -52
  26. package/public-landing/projects.probes.json +32 -7
  27. package/public-landing/projects.states.json +10 -6
  28. package/src/module-api.js +1 -1
  29. package/tests/account_privacy_flags.mjs +17 -10
  30. package/tests/effective_visibility_predicate.mjs +891 -0
  31. package/tests/profile_route.mjs +22 -11
  32. package/tests/projects_hub.mjs +54 -5
  33. package/tests/projects_hub_pre_uat.mjs +19 -7
  34. package/tests/ui_design_kit.mjs +32 -2
@@ -377,22 +377,6 @@ h1{font-family:var(--font-display);font-weight:700;font-size:clamp(24px,3.4vw,32
377
377
  .chip.calm .cdot{background:var(--ink-faint);}
378
378
  @keyframes chipPulse{0%,100%{box-shadow:0 0 0 0 color-mix(in srgb,var(--accent) 35%,transparent)}50%{box-shadow:0 0 0 5px transparent}}
379
379
 
380
- /* ── the orb: the gate's project sphere, docked onto a card. Glow follows
381
- verification — warm when verified live, amber-dim when stale, ashen when
382
- it failed its check, ghosted when torn down. Born for the dark sky; on
383
- light cards the inset ring keeps it grounded. ── */
384
- .orb{flex:0 0 54px;width:54px;height:54px;border-radius:50%;position:relative;overflow:visible;border:none;padding:0;
385
- background:radial-gradient(120% 120% at 50% 50%, var(--acc,#fb923c), color-mix(in srgb, var(--acc,#fb923c) 55%, #1b2b52) 100%);
386
- box-shadow:0 0 0 1.5px rgba(255,255,255,.35) inset, 0 6px 18px rgba(20,16,40,.28), 0 0 26px var(--glow, rgba(251,146,60,.5));}
387
- .orb::after{content:'';position:absolute;inset:0;border-radius:50%;pointer-events:none;
388
- background:radial-gradient(38% 34% at 34% 28%, rgba(255,255,255,.9), rgba(255,255,255,0) 60%);}
389
- .orb.dim{filter:saturate(.55) brightness(.92);--glow:rgba(217,119,6,.35);}
390
- .orb.ashen{filter:saturate(.3) brightness(.78);--glow:rgba(220,38,38,.22);}
391
- .orb.ghost{opacity:.4;box-shadow:0 0 0 1.5px rgba(255,255,255,.25) inset;filter:saturate(.2);}
392
- /* only the LINKED orb is clickable: orbFor() emits a <span class="orb"> for
393
- every non-navigable state, and index.html's .conItem .orb takes cursor:inherit
394
- from the <a> it sits inside — so .orb.ghost's cursor reset is redundant. */
395
- a.orb{cursor:pointer;}
396
380
 
397
381
  /* ── project cards ── */
398
382
  .projects{list-style:none;display:flex;flex-direction:column;gap:18px;}
@@ -919,17 +903,30 @@ p.sec-p{font-size:var(--fs-lede);font-weight:500;color:var(--ink-soft);line-heig
919
903
  .tbl td.right{text-align:right;}
920
904
  /* Nothing in an action or status cell may wrap: "Manage →" breaking after the
921
905
  space and the chip's recency dropping to a second line both read as a broken
922
- control rather than a tight column. Those two cells claim their width and the
923
- name cell absorbs the slack. */
906
+ control rather than a tight column. */
924
907
  .tbl .btn,.tbl .chip{white-space:nowrap;}
925
- .tbl .colStatus{width:1%;white-space:nowrap;}
926
- .tbl .colGo{width:1%;white-space:nowrap;padding-left:8px;}
927
- .tbl .colName{width:auto;}
928
- .tbl .colType{width:1%;white-space:nowrap;}
908
+ .tbl .colStatus,.tbl .colGo,.tbl .colType{white-space:nowrap;}
909
+ .tbl .colGo{padding-left:8px;}
910
+ /* ── FIXED tracks (task 1003348; the owner: "the columns don't look aligned").
911
+ An auto table sized every column by its content, so the status column hugged
912
+ its widest chip and the headers drifted off their cells. table-layout:fixed
913
+ takes the widths from the header row — one set of tracks for every row, each
914
+ column edge one vertical line — and the name column absorbs the slack. The
915
+ Project header sits over the NAME (past the 10px dot and its 12px gap), and a
916
+ right-aligned column's header is right-aligned too. Below the table's minimum
917
+ the wrap scrolls (#sub-table-body), never the page. ── */
918
+ .tbl{table-layout:fixed;min-width:860px;}
919
+ .tbl th.colName{padding-left:22px;}
920
+ .tbl th.right{text-align:right;}
921
+ .tbl th.colType{width:88px;}
922
+ .tbl th.colBuilders{width:96px;}
923
+ .tbl th.colTags{width:168px;}
924
+ .tbl th.colStatus{width:224px;}
925
+ .tbl th.colGo{width:112px;}
929
926
  /* the declared-type tag (task 1002772) — its own vocabulary: not the relationship
930
927
  .pill, not the liveness .chip. Two different facts never wear the same chrome. */
931
928
  .typeTag{font-family:var(--font-mono);font-size:10.5px;font-weight:500;color:var(--ink-soft);border:1px solid var(--rule);border-radius:999px;padding:2px 9px;white-space:nowrap;}
932
- @media (max-width:780px){.tbl .colTags,.tbl .colType{display:none;}}
929
+ @media (max-width:780px){.tbl .colTags,.tbl .colType{display:none;}.tbl{min-width:600px;}}
933
930
  @media (max-width:900px){
934
931
  .tblMast{gap:16px;padding:22px 0 20px;}
935
932
  .tblTitle{font-size:clamp(28px,7.4vw,34px);}
@@ -1081,7 +1078,6 @@ p.sec-p{font-size:var(--fs-lede);font-weight:500;color:var(--ink-soft);line-heig
1081
1078
  .rowHall{display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;margin-left:10px;
1082
1079
  vertical-align:middle;color:var(--accent-deep);border-radius:var(--radius-pill);}
1083
1080
  .rowHall:hover{background:var(--glass);}
1084
- .tbl .colGo{white-space:nowrap;}
1085
1081
  @media (max-width:640px){
1086
1082
  .projCard h3{font-size:26px;padding:0 20px;}
1087
1083
  .projCard .cardTag,.projCard .cardRel,.projCard .cardFaces,.projCard .cardFigs,.projCard .cardMeta,
@@ -1152,8 +1148,6 @@ p.sec-p{font-size:var(--fs-lede);font-weight:500;color:var(--ink-soft);line-heig
1152
1148
  @media (max-width:640px){
1153
1149
  .projHead{gap:8px;}
1154
1150
  .actions{flex-direction:column;align-items:stretch;}
1155
- .proj{flex-direction:column;}
1156
- .orb{width:44px;height:44px;flex-basis:44px;}
1157
1151
  .mineBar .search .count{display:none;} /* the "All 16" pill already carries the number */
1158
1152
  }
1159
1153
  /* the carried surfaces: only the hit-area floors the world asks for (direction
@@ -1162,7 +1156,233 @@ p.sec-p{font-size:var(--fs-lede);font-weight:500;color:var(--ink-soft);line-heig
1162
1156
  on a phone instead of pushing the page sideways */
1163
1157
  #sub-table-body{overflow-x:auto;}
1164
1158
  .tbl th button{min-height:24px;display:inline-flex;align-items:center;}
1159
+ .tbl a.ptitle{display:inline-flex;align-items:center;min-height:24px;}
1165
1160
  .foot a,.finePrint a{display:inline-block;padding:3px 0;min-height:24px;}
1161
+ /* ═══════════════════════════════════════════════════════════════════════
1162
+ YOUR PROJECTS + THE MANAGE PAGE, IN THE WORLD (task 1003345; direction
1163
+ record §14, the owner's pick: v1 the ledger row). Both views keep the
1164
+ markup the truth rules pin (renderCard / orbFor / stripMarkup, the manage
1165
+ ids) and take the world's grammar by SCOPE: no card ground, hairlines for
1166
+ structure, the project's own planet as the row's object, the strip drawn
1167
+ as the lifecycle rail, the doors as hairline pills with the accent only on
1168
+ the one that acts. One set of FIXED tracks across every row, so the list
1169
+ reads as one ledger — the same column grammar the every-project table takes
1170
+ in its `.tbl` rules (table-layout:fixed, the header row's widths; task
1171
+ 1003348, both halves pinned together in tests/projects_hub.mjs). Dark only
1172
+ (ADR 0204); every colour a token; halos are outlines, never box-shadow.
1173
+ ═══════════════════════════════════════════════════════════════════════ */
1174
+ #view-mine .wrap,#view-manage .wrap{max-width:1180px;}
1175
+ #view-mine .card,#view-manage .card{background:none;border-radius:0;box-shadow:none;padding:0;margin:0;}
1176
+ /* the view title in the display voice, lowercase; the lede stays one clause */
1177
+ #view-mine .hero,#view-manage .hero{padding-top:34px;padding-bottom:22px;}
1178
+ #view-mine .hero h1,#view-manage .hero h1{font-weight:300;font-size:clamp(28px,3.4vw,44px);letter-spacing:-.035em;line-height:1.04;text-transform:lowercase;color:var(--ink);text-shadow:none;}
1179
+ #view-mine .hero .lede,#view-manage .hero .lede{color:var(--ink-soft);font-weight:400;text-shadow:none;margin:8px 0 0;}
1180
+ #view-mine .hero .lede b,#view-manage .hero .lede b{color:var(--ink);font-weight:500;}
1181
+ #view-mine .finePrint,#view-manage .finePrint{font-weight:400;font-size:13.5px;line-height:1.5;}
1182
+ #view-mine .loading,#view-manage .loading{font-weight:400;}
1183
+
1184
+ /* ── the planet, docked: the sky's object, relative instead of absolute; its
1185
+ state reads on the object (ghost = torn down, ashen = failed its check,
1186
+ dim = a stale probe), and only the live one is a link ── */
1187
+ #view-mine .worldOrb,#view-manage .worldOrb{position:relative;left:auto;top:auto;transform:none;display:block;cursor:default;opacity:1;pointer-events:auto;}
1188
+ #view-mine a.worldOrb,#view-manage a.worldOrb{cursor:pointer;}
1189
+ #view-mine .worldOrb .disc,#view-manage .worldOrb .disc{display:block;margin:0;}
1190
+ #view-mine span.worldOrb:hover .disc,#view-manage span.worldOrb:hover .disc{translate:none;}
1191
+ #view-mine .worldOrb.ghost,#view-manage .worldOrb.ghost{opacity:.4;filter:saturate(.2);}
1192
+ #view-mine .worldOrb.ashen,#view-manage .worldOrb.ashen{filter:saturate(.3) brightness(.78);}
1193
+ #view-mine .worldOrb.dim,#view-manage .worldOrb.dim{opacity:1;filter:saturate(.55) brightness(.92);}
1194
+
1195
+ /* ── the search: one hairline field, the count in the label face; the
1196
+ filters: hairline pills, the pressed one inverted to ink ── */
1197
+ #view-mine .mineBar{gap:18px;margin:0 0 8px;justify-content:space-between;}
1198
+ #view-mine .mineBar .search{max-width:520px;gap:12px;background:none;border:0;border-bottom:1px solid var(--rule);border-radius:0;padding:10px 0;backdrop-filter:none;}
1199
+ #view-mine .mineBar .search:focus-within{box-shadow:none;border-bottom-color:var(--ink);}
1200
+ #view-mine .mineBar .search svg{width:18px;height:18px;stroke-width:1.6;}
1201
+ #view-mine .mineBar .search input{font-family:var(--font-body);font-size:15.5px;min-height:28px;padding:0;}
1202
+ #view-mine .mineBar .search .count{font-family:var(--label-face);font-size:var(--label-size);letter-spacing:var(--label-space);text-transform:uppercase;}
1203
+ #view-mine .filters{gap:8px;}
1204
+ #view-mine .filters button{min-height:36px;padding:0 15px;gap:8px;font-family:var(--font-body);font-weight:400;font-size:14.5px;text-transform:lowercase;color:var(--ink-soft);background:none;border:1px solid var(--rule);}
1205
+ #view-mine .filters button:hover{border-color:var(--ink-faint);color:var(--ink);}
1206
+ #view-mine .filters button[aria-pressed="true"]{background:var(--ink);border-color:var(--ink);color:var(--bg);}
1207
+ #view-mine .filters .n{font-family:var(--label-face);font-size:var(--label-size);letter-spacing:var(--label-space);font-weight:400;}
1208
+ #view-mine .mineEmpty{font-weight:400;color:var(--ink-soft);}
1209
+ #view-mine .linklike,#view-manage .linklike{font-weight:400;color:var(--ink-soft);}
1210
+
1211
+ /* ── the ledger row: planet · name and chip · the facts · the rail · the
1212
+ doors. The planet and the doors are fixed widths; the three middle tracks
1213
+ share the rest by ratio with NO content minimum, so every row lays its
1214
+ columns on the same lines (task 1003348). The body is its own grid on the
1215
+ same four tracks, so renderCard's markup stands as pinned. ── */
1216
+ #view-mine .projects{gap:0;margin-top:8px;}
1217
+ #view-mine .proj{display:grid;grid-template-columns:72px minmax(0,1fr);gap:0 22px;align-items:center;padding:22px 0;border:0;border-top:1px solid var(--rule-soft);border-radius:0;background:none;}
1218
+ #view-mine .projects .proj:last-child{border-bottom:1px solid var(--rule-soft);}
1219
+ #view-mine .projBody{display:grid;grid-template-columns:minmax(0,1.1fr) minmax(0,1.3fr) minmax(0,1fr) 232px;grid-template-areas:"who facts rail doors" "who addr rail doors";gap:0 22px;align-items:center;min-width:0;}
1220
+ #view-mine .projHead{grid-area:who;display:grid;gap:8px;justify-items:start;align-content:center;}
1221
+ #view-mine .projMeta{grid-area:facts;align-self:end;}
1222
+ #view-mine .addr{grid-area:addr;align-self:start;}
1223
+ #view-mine .strip{grid-area:rail;}
1224
+ #view-mine .actions{grid-area:doors;}
1225
+ /* everything else on a card (a snag, a status line, the torn-down note, the
1226
+ address fold) is a full row under the ledger line */
1227
+ #view-mine .projBody>.projMsg,#view-mine .projBody>.attachFold{grid-column:1/-1;}
1228
+ #view-mine .projMsg{min-height:0;margin:0;font-weight:400;}
1229
+ #view-mine .projMsg:not(:empty){margin-top:10px;}
1230
+ #view-mine .projMsg.err{margin-top:12px;}
1231
+ #view-mine .attachFold{margin-top:10px;}
1232
+ #view-mine .actions:has(.confirmRow){grid-area:auto;grid-column:1/-1;justify-content:flex-start;margin-top:12px;}
1233
+ /* the name in the body face; the chip beneath it, allowed to wrap */
1234
+ #view-mine .projName{font-family:var(--font-body);font-weight:500;font-size:17px;letter-spacing:-.015em;color:var(--ink);}
1235
+ #view-mine .proj.gone .projName{color:var(--ink-soft);}
1236
+ #view-mine .projHead .chip{white-space:normal;line-height:1.3;}
1237
+ /* the facts: label-face lines; the repo in mono with no plate */
1238
+ #view-mine .projMeta{display:grid;gap:5px;margin:0;font-family:var(--label-face);font-size:var(--label-size);font-weight:400;letter-spacing:var(--label-space);text-transform:uppercase;color:var(--ink-faint);}
1239
+ #view-mine .projMeta>span+span::before{content:none;margin:0;}
1240
+ #view-mine .projMeta code,#view-mine .addr code{font-family:var(--font-mono);font-size:12.5px;letter-spacing:0;text-transform:none;color:var(--ink-soft);background:none;border-radius:0;padding:0;}
1241
+ /* the address: the honest clause in the body face */
1242
+ #view-mine .addr{margin:5px 0 0;font-size:13.5px;font-weight:400;line-height:1.45;color:var(--ink-soft);}
1243
+ #view-mine .addr .none{font-style:normal;color:var(--ink-faint);}
1244
+ /* every inline link on these views clears the 24px hit floor: a short link as a
1245
+ box; the address clause's mono link may run long and must wrap inside the
1246
+ prose, so it stays inline and takes the floor as vertical padding (an inline's
1247
+ rect is its content box plus padding, never the line box) */
1248
+ #view-mine .projMsg a,#view-mine .attachNote a,#view-manage .ledger a,#view-manage .backRow a,#view-manage .mSec a{display:inline-block;padding:3px 0;min-height:24px;line-height:18px;font-weight:400;text-decoration:none;}
1249
+ #view-mine .addr{line-height:1.6;}
1250
+ #view-mine .addr a{display:inline;padding:4px 0;font-weight:400;text-decoration:none;}
1251
+ #view-mine .addr a,#view-manage .ledger a{font-family:var(--font-mono);font-size:12.5px;color:var(--ink-soft);}
1252
+ #view-mine .addr a:hover,#view-manage .ledger a:hover{color:var(--ink);text-decoration:underline;}
1253
+ #view-mine .projMsg a,#view-manage .mSec a{color:var(--ink);text-decoration:underline;}
1254
+ #view-mine .attachFold summary{display:inline-flex;align-items:center;min-height:24px;font-weight:400;font-size:13.5px;color:var(--ink-soft);}
1255
+ #view-mine .attachFold summary:hover,#view-mine .attachFold[open] summary{color:var(--ink);}
1256
+
1257
+ /* ── the lifecycle rail (DESIGN.md): stripMarkup's markup, drawn as three
1258
+ hairlines with a 7px dot and one lit step — no plate, no connector, no
1259
+ pulse. Live keeps the world's green; a wind-down stays neutral. ── */
1260
+ #view-mine .strip,#view-manage .strip{border:0;border-radius:0;padding:0;background:none;margin:0;}
1261
+ #view-mine .strip .stages,#view-manage .strip .stages{display:grid;grid-template-columns:repeat(3,1fr);gap:0 10px;margin:0;}
1262
+ #view-mine .strip .stages li,#view-manage .strip .stages li{display:block;position:relative;border-top:1px solid var(--rule);padding:12px 0 0;}
1263
+ #view-mine .strip .stages li::before,#view-manage .strip .stages li::before{content:none;}
1264
+ #view-mine .strip .sdot,#view-manage .strip .sdot{position:absolute;top:-4px;left:0;width:7px;height:7px;border:1px solid var(--rule);border-radius:50%;background:var(--bg);display:block;}
1265
+ #view-mine .strip .sdot::after,#view-manage .strip .sdot::after{content:none;}
1266
+ #view-mine .strip .slbl,#view-manage .strip .slbl{display:block;font-family:var(--label-face);font-size:var(--label-size);font-weight:400;letter-spacing:var(--label-space);text-transform:uppercase;line-height:1.3;color:var(--ink-faint);}
1267
+ #view-mine .strip .stages li.done,#view-manage .strip .stages li.done{border-top-color:var(--ink-soft);}
1268
+ #view-mine .strip .stages li.done .sdot,#view-manage .strip .stages li.done .sdot{background:var(--ink-soft);border-color:var(--ink-soft);}
1269
+ #view-mine .strip .stages li.done .slbl,#view-manage .strip .stages li.done .slbl{color:var(--ink-soft);}
1270
+ #view-mine .strip .stages li.now,#view-manage .strip .stages li.now{border-top-color:var(--accent);}
1271
+ #view-mine .strip .stages li.now .sdot,#view-manage .strip .stages li.now .sdot{background:var(--accent);border-color:var(--accent);outline:4px solid color-mix(in srgb,var(--accent) 22%,transparent);}
1272
+ #view-mine .strip .stages li.now .slbl,#view-manage .strip .stages li.now .slbl{color:var(--ink);}
1273
+ #view-mine .strip.isLive .stages li.done,#view-manage .strip.isLive .stages li.done{border-top-color:var(--ok);}
1274
+ #view-mine .strip.isLive .stages li.done .sdot,#view-manage .strip.isLive .stages li.done .sdot{background:var(--ok);border-color:var(--ok);}
1275
+ #view-mine .strip.isLive .stages li.done .slbl,#view-manage .strip.isLive .stages li.done .slbl{color:var(--ok);}
1276
+ #view-mine .strip.flowDown .stages li.now,#view-manage .strip.flowDown .stages li.now{border-top-color:var(--ink-soft);}
1277
+ #view-mine .strip.flowDown .stages li.now .sdot,#view-manage .strip.flowDown .stages li.now .sdot{background:var(--ink-soft);border-color:var(--ink-soft);outline:none;}
1278
+ #view-mine .strip.flowDown .stages li.now .slbl,#view-manage .strip.flowDown .stages li.now .slbl{color:var(--ink-soft);}
1279
+ #view-mine .strip .pnote,#view-manage .strip .pnote{text-align:left;font-size:13px;font-weight:400;line-height:1.45;color:var(--ink-soft);margin:8px 0 0;min-height:0;}
1280
+ #view-mine .strip.isLive .pnote,#view-manage .strip.isLive .pnote{color:var(--ok);}
1281
+
1282
+ /* ── the doors: hairline pills, lowercase; the accent only on the one that
1283
+ acts (the plain .btn.small: try again, bring it back, restart, save); the
1284
+ ender on the error ink; no lift, no shadow ── */
1285
+ #view-mine .actions,#view-manage .actions{gap:8px;margin:0;}
1286
+ #view-mine .actions{justify-content:flex-end;}
1287
+ #view-mine .btn,#view-manage .btn{min-height:44px;padding:0 22px;font-family:var(--font-body);font-weight:500;font-size:15px;text-transform:lowercase;white-space:nowrap;box-shadow:none;transition:border-color .15s ease,background .15s ease;}
1288
+ #view-mine .btn:hover,#view-manage .btn:hover{transform:none;box-shadow:none;}
1289
+ #view-mine .btn:active,#view-manage .btn:active{transform:none;}
1290
+ #view-mine .btn.small,#view-manage .btn.small{min-height:40px;padding:0 18px;font-weight:400;font-size:14.5px;color:var(--ink);background:none;border:1px solid var(--rule);}
1291
+ #view-mine .btn.small:hover,#view-manage .btn.small:hover{border-color:var(--ink-faint);color:var(--ink);}
1292
+ #view-mine .btn.small:not(.ghost):not(.danger),#view-manage .btn.small:not(.ghost):not(.danger){background:var(--accent);border-color:var(--accent);color:var(--accent-on);font-weight:500;}
1293
+ #view-mine .btn.small:not(.ghost):not(.danger):hover,#view-manage .btn.small:not(.ghost):not(.danger):hover{background:color-mix(in srgb,var(--accent) 88%,var(--ink));border-color:color-mix(in srgb,var(--accent) 88%,var(--ink));color:var(--accent-on);}
1294
+ #view-mine .btn.small.danger,#view-manage .btn.small.danger{border-color:color-mix(in srgb,var(--err) 45%,transparent);color:var(--err);}
1295
+ #view-mine .btn.small.danger:hover,#view-manage .btn.small.danger:hover{background:none;border-color:var(--err);color:var(--err);}
1296
+ #view-mine .btn.small:disabled,#view-manage .btn.small:disabled{background:none;border-color:var(--rule-soft);color:var(--ink-faint);}
1297
+ /* the fold's field and the ender's typed-back name: a hairline field */
1298
+ #view-mine .attach,#view-manage .attach{gap:10px 14px;margin-top:12px;align-items:center;}
1299
+ #view-mine .attach input[type=text],#view-manage .attach input[type=text]{min-width:220px;min-height:40px;font-family:var(--font-body);font-size:15.5px;font-weight:400;color:var(--ink);background:none;border:0;border-bottom:1px solid var(--rule);border-radius:0;padding:8px 0;}
1300
+ #view-mine .attach input[type=text]::placeholder,#view-manage .attach input[type=text]::placeholder{font-weight:400;}
1301
+ #view-mine .attach input[type=text]:focus,#view-manage .attach input[type=text]:focus{border-bottom-color:var(--ink);box-shadow:none;}
1302
+ #view-mine .confirmRow,#view-manage .confirmRow{font-weight:400;}
1303
+ #view-mine .confirmRow .plain,#view-manage .confirmRow .plain{font-weight:400;font-size:14.5px;line-height:1.5;}
1304
+
1305
+ /* ── the empty state: a band of the Projects band's grammar, one door ── */
1306
+ #view-mine .empty{display:grid;gap:14px;justify-items:start;text-align:left;background:var(--bg-card);border:0;border-top:1px solid var(--rule);border-bottom:1px solid var(--rule);border-radius:0;padding:58px var(--gutter) 62px;}
1307
+ #view-mine .empty h2{font-family:var(--font-display);font-weight:300;font-size:clamp(30px,4vw,48px);letter-spacing:-.035em;line-height:1.02;text-transform:lowercase;color:var(--ink);margin:0;max-width:16ch;}
1308
+ #view-mine .empty p{margin:0 0 8px;font-size:16px;font-weight:400;line-height:1.5;color:var(--ink-soft);max-width:52ch;}
1309
+
1310
+ /* ── the manage page: the back link in the label face; the head with the
1311
+ planet, the name in the display voice and its chip; the ledger of facts on
1312
+ hairlines; the settings as hairline sections, the title and its clause
1313
+ left, the choice as hairline cells right ── */
1314
+ #view-manage .backRow{margin:26px 0 0;font-family:var(--label-face);font-size:var(--label-size);letter-spacing:var(--label-space);text-transform:uppercase;font-weight:400;}
1315
+ #view-manage .backRow a{color:var(--ink-faint);}
1316
+ #view-manage .backRow a:hover{color:var(--ink);}
1317
+ #view-manage .mHead{display:flex;align-items:center;gap:26px;padding-top:22px;padding-bottom:8px;}
1318
+ #view-manage .mHead .titleRow{display:flex;align-items:baseline;gap:16px;flex-wrap:wrap;}
1319
+ #view-manage #mOrb:empty{display:none;}
1320
+ #view-manage #mOrb .worldOrb{--orb-scale:1.5;}
1321
+ /* the page's clause belongs to a project that rendered — the signed-out and
1322
+ not-found states keep the heading and drop the clause */
1323
+ #view-manage .mHead:has(~ #mMain[hidden]) .lede{display:none;}
1324
+ #view-manage .ledger{display:grid;grid-template-columns:172px 1fr;gap:0 22px;margin:14px 0 0;}
1325
+ #view-manage .ledger>*:not([hidden]){display:contents;}
1326
+ #view-manage .ledger .k,#view-manage .ledger .v{border-top:1px solid var(--rule-soft);padding:13px 0;min-width:0;}
1327
+ #view-manage .ledger .k{font-family:var(--label-face);font-size:var(--label-size);letter-spacing:var(--label-space);text-transform:uppercase;color:var(--ink-faint);padding-top:16px;}
1328
+ #view-manage .ledger .v{font-size:15px;line-height:1.5;color:var(--ink);overflow-wrap:anywhere;}
1329
+ #view-manage .ledger .v code{font-family:var(--font-mono);font-size:13.5px;color:var(--ink-soft);background:none;border-radius:0;padding:0;}
1330
+ #view-manage .ledger .v small{display:block;font-size:13px;color:var(--ink-soft);}
1331
+ #view-manage .ledger .v .none{color:var(--ink-faint);font-style:normal;}
1332
+ #view-manage .swDot{display:inline-block;width:11px;height:11px;border-radius:50%;background:var(--sw);border:1px solid var(--rule);vertical-align:-1px;margin-right:8px;}
1333
+ #view-manage #mStrip{max-width:520px;margin:22px 0 0;}
1334
+ #view-manage #mFacts .projMsg{font-weight:400;}
1335
+ #view-manage #mActs{justify-content:flex-start;margin-top:22px;}
1336
+ #view-manage #mFacts{padding-bottom:34px;}
1337
+ #view-manage .mSec{display:grid;grid-template-columns:minmax(200px,300px) 1fr;grid-template-rows:auto 1fr;gap:6px 40px;border-top:1px solid var(--rule);padding:30px 0 34px;}
1338
+ #view-manage .mSec h2{grid-column:1;grid-row:1;font-family:var(--font-display);font-weight:300;font-size:clamp(22px,2.4vw,28px);letter-spacing:-.03em;line-height:1.08;text-transform:lowercase;color:var(--ink);margin:0;}
1339
+ #view-manage .mSec>details{grid-column:1;grid-row:2;align-self:start;margin:0;max-width:34ch;color:var(--ink-faint);}
1340
+ #view-manage .mSec>details summary{cursor:pointer;display:inline-flex;align-items:center;min-height:24px;color:var(--ink-soft);}
1341
+ #view-manage .mSec>details summary:hover{color:var(--ink);}
1342
+ #view-manage .mSec>details p{margin-top:8px;}
1343
+ #view-manage .mSec>div{grid-column:2;grid-row:1/span 2;display:grid;gap:16px;align-content:start;min-width:0;}
1344
+ #view-manage .mSec .addr,#view-manage .mSec .plain{margin:0;font-size:15px;font-weight:400;line-height:1.5;color:var(--ink-soft);}
1345
+ #view-manage .mSec .addr b{color:var(--ink);font-weight:500;}
1346
+ #view-manage .mSec .finePrint{margin:0;}
1347
+ #view-manage .mSec .projMsg{margin:0;min-height:0;font-weight:400;}
1348
+ #view-manage .mSec .projMsg:not(:empty){margin-top:2px;}
1349
+ /* a choice: hairline-separated cells; the chosen one carries the dot and the ink */
1350
+ #view-manage [role="radiogroup"]{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));border-top:1px solid var(--rule);border-bottom:1px solid var(--rule);}
1351
+ #view-manage .visOpt{position:relative;display:block;margin:0;padding:16px 18px 18px;border:0;border-left:1px solid var(--rule-soft);border-radius:0;cursor:pointer;}
1352
+ #view-manage .visOpt:first-child{border-left:0;padding-left:0;}
1353
+ #view-manage .visOpt input{position:absolute;width:1px;height:1px;margin:0;overflow:hidden;clip-path:inset(50%);}
1354
+ #view-manage .visOpt>span{display:block;font-size:13px;line-height:1.45;color:var(--ink-faint);}
1355
+ #view-manage .visOpt b{display:flex;align-items:center;gap:10px;margin-bottom:6px;font-family:var(--font-body);font-weight:500;font-size:15px;color:var(--ink);}
1356
+ #view-manage .visOpt b::before{content:"";width:7px;height:7px;border-radius:50%;border:1px solid var(--rule);background:var(--bg);flex:none;}
1357
+ #view-manage .visOpt:has(input:checked) b::before{background:var(--accent);border-color:var(--accent);outline:4px solid color-mix(in srgb,var(--accent) 22%,transparent);}
1358
+ #view-manage .visOpt:focus-within{outline:2px solid var(--accent);outline-offset:3px;}
1359
+ #view-manage #mVisRuns b,#view-manage #mJoinRuns b{color:var(--ok);font-weight:500;}
1360
+
1361
+ /* this block stays HERE, after the rules it narrows: a same-specificity mobile
1362
+ override only wins by source order, so folding it into the hub's earlier
1363
+ 900px block would put every stack rule before the grid it undoes */
1364
+ @media (max-width:900px){
1365
+ /* the row stacks: planet and name, then the facts, the rail and the doors —
1366
+ the body dissolves into the row's grid (display:contents) so the planet
1367
+ sits beside the name alone */
1368
+ #view-mine .proj{grid-template-columns:56px minmax(0,1fr);gap:0 16px;padding:20px 0;}
1369
+ #view-mine .proj .worldOrb{--orb-scale:.875;grid-column:1;grid-row:1;}
1370
+ #view-mine .projBody{display:contents;}
1371
+ #view-mine .projHead{grid-area:auto;grid-column:2;grid-row:1;}
1372
+ #view-mine .projMeta,#view-mine .addr,#view-mine .strip,#view-mine .actions,#view-mine .projBody>.projMsg,#view-mine .projBody>.attachFold{grid-area:auto;grid-column:1/-1;}
1373
+ #view-mine .projMeta{margin-top:14px;}
1374
+ #view-mine .strip{margin-top:16px;}
1375
+ #view-mine .actions{margin-top:16px;justify-content:flex-start;flex-direction:row;align-items:center;}
1376
+ #view-manage .mHead{flex-wrap:wrap;gap:14px;}
1377
+ #view-manage .ledger{grid-template-columns:1fr;}
1378
+ #view-manage .ledger .k{padding-bottom:0;}
1379
+ #view-manage .ledger .v{border-top:0;padding-top:6px;}
1380
+ #view-manage .mSec{grid-template-columns:1fr;grid-template-rows:auto;gap:14px;}
1381
+ #view-manage .mSec h2,#view-manage .mSec>details,#view-manage .mSec>div{grid-column:1;grid-row:auto;}
1382
+ #view-manage [role="radiogroup"]{grid-template-columns:1fr;}
1383
+ #view-manage .visOpt{border-left:0;padding-left:0;border-top:1px solid var(--rule-soft);}
1384
+ #view-manage .visOpt:first-child{border-top:0;}
1385
+ }
1166
1386
  @media (prefers-reduced-motion:reduce){
1167
1387
  *,*::before,*::after{animation:none !important;transition:none !important;}
1168
1388
  }
@@ -0,0 +1,49 @@
1
+ {
2
+ "_": "The mine view with no projects (task 1003345): the same page, the same stub, one fixture aliased to the empty list. Rendered by name: node modules/ui-design/kit/render.js --states public-landing/projects-empty.states.json",
3
+ "page": "/projects",
4
+ "surface": "public-landing",
5
+ "modes": [
6
+ "dark"
7
+ ],
8
+ "modeQuery": false,
9
+ "stub": {
10
+ "fixtures": {
11
+ "provisioning-instances": "provisioning-instances-empty"
12
+ }
13
+ },
14
+ "ignoreRequests": [
15
+ "/api/(gds|bongos)/me$",
16
+ "/my-projects"
17
+ ],
18
+ "ignoreConsole": [
19
+ "/api/(gds|bongos)/me",
20
+ "\\b401\\b",
21
+ "Unauthorized"
22
+ ],
23
+ "ignoreControls": [
24
+ ".skip",
25
+ ".vh"
26
+ ],
27
+ "states": {
28
+ "in-mine-empty": {
29
+ "auth": true,
30
+ "url": "/projects?view=mine",
31
+ "expect": {
32
+ "visible": [
33
+ "#empty",
34
+ "#empty a[data-nav-to=\"new\"]"
35
+ ],
36
+ "hidden": [
37
+ "#mineBar",
38
+ "#qWrap"
39
+ ],
40
+ "count": [
41
+ [
42
+ "#projectsList .proj",
43
+ 0
44
+ ]
45
+ ]
46
+ }
47
+ }
48
+ }
49
+ }
@@ -0,0 +1,63 @@
1
+ {
2
+ "_": "The all-null floor card (task 1003301) on the hub's own catalog (task 1003345): the same page, the same stub, the catalog aliased to featured-hub.json — the landing's three plus Tidewater, a null row nobody owns. Demo, the landing catalog's floor row, is owned by the signed-in stub, and an owned orb's plain click opens its manage view, never its card. Rendered by name: node modules/ui-design/kit/render.js --states public-landing/projects-floor.states.json",
3
+ "page": "/projects",
4
+ "surface": "public-landing",
5
+ "modes": [
6
+ "dark"
7
+ ],
8
+ "modeQuery": false,
9
+ "stub": {
10
+ "fixtures": {
11
+ "featured": "featured-hub"
12
+ }
13
+ },
14
+ "ignoreRequests": [
15
+ "/api/(gds|bongos)/me$",
16
+ "/my-projects",
17
+ "/provisioning/instances/999",
18
+ "/provisioning/instances/101$",
19
+ "/api/gds/instance$"
20
+ ],
21
+ "ignoreConsole": [
22
+ "/api/(gds|bongos)/me",
23
+ "\\b401\\b",
24
+ "\\b404\\b",
25
+ "Unauthorized"
26
+ ],
27
+ "ignoreControls": [
28
+ ".skip",
29
+ ".vh"
30
+ ],
31
+ "states": {
32
+ "card-floor": {
33
+ "auth": true,
34
+ "actions": [
35
+ [
36
+ "dispatchClick",
37
+ "#orbField a.worldOrb[data-origin=\"https://tidewater.cloudbongos.com\"]"
38
+ ],
39
+ [
40
+ "wait",
41
+ 600
42
+ ]
43
+ ],
44
+ "expect": {
45
+ "dialog": true,
46
+ "hidden": [
47
+ "#cardArt",
48
+ "#cardFaces",
49
+ "#cardFigs",
50
+ "#cardHall",
51
+ "#cardRel",
52
+ "#cardTypeL",
53
+ "#cardOwnerL"
54
+ ],
55
+ "visible": [
56
+ "#cardOpen",
57
+ "#cardRuns",
58
+ "#cardListed"
59
+ ]
60
+ }
61
+ }
62
+ }
63
+ }