@augurworks/augur 0.15.1
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.
- package/CANVAS.md +858 -0
- package/INSTALL.md +603 -0
- package/LICENSE +27 -0
- package/README.md +150 -0
- package/TRADEMARKS.md +72 -0
- package/agents/README.md +65 -0
- package/agents/canon-extract.md +117 -0
- package/agents/canon.md +151 -0
- package/agents/canvas.md +88 -0
- package/agents/currency.md +74 -0
- package/agents/drafts.md +92 -0
- package/agents/identity.md +148 -0
- package/agents/prototype-contract.md +69 -0
- package/agents/publishing.md +324 -0
- package/agents/review-feedback.md +76 -0
- package/agents/space-json.md +132 -0
- package/agents/ui-skill.md +101 -0
- package/agents/working-marks.md +86 -0
- package/brand/augur-eye.svg +3 -0
- package/brand/augur-icon.svg +41 -0
- package/brand/augur-mark.svg +5 -0
- package/brand/lentianova-bulky.otf +0 -0
- package/brand/lentianova-median.otf +0 -0
- package/brand/lentianova.woff2 +0 -0
- package/build.js +8409 -0
- package/changelog.md +133 -0
- package/fonts/inter-latin-wght-normal.woff2 +0 -0
- package/package.json +57 -0
- package/pitis/PETS.md +121 -0
- package/pitis/README.md +117 -0
- package/pitis/index.html +266 -0
- package/pitis/piti.build.js +81 -0
- package/pitis/piti.js +929 -0
- package/pitis/roast-agent.md +185 -0
- package/realtime/src/index.js +119 -0
- package/realtime/wrangler.example.toml +44 -0
- package/scripts/adopt.mjs +106 -0
- package/scripts/board-snapshot.mjs +197 -0
- package/scripts/build-seed-pack.mjs +33 -0
- package/scripts/bundle-rekey.mjs +112 -0
- package/scripts/bundle-tenancy-rehearsal.mjs +781 -0
- package/scripts/canon-extract.mjs +578 -0
- package/scripts/canon.mjs +599 -0
- package/scripts/canvas-screen.mjs +333 -0
- package/scripts/check-local.mjs +136 -0
- package/scripts/clawd-art.mjs +75 -0
- package/scripts/clawd-canvas.mjs +741 -0
- package/scripts/cli.mjs +100 -0
- package/scripts/clone.mjs +422 -0
- package/scripts/close.mjs +30 -0
- package/scripts/connect.mjs +103 -0
- package/scripts/deploy.mjs +157 -0
- package/scripts/dev.mjs +54 -0
- package/scripts/doc-lint.mjs +143 -0
- package/scripts/export.mjs +300 -0
- package/scripts/fork.mjs +64 -0
- package/scripts/freeze.mjs +74 -0
- package/scripts/frontdoor-parity.mjs +180 -0
- package/scripts/hook.mjs +67 -0
- package/scripts/identity-rekey.mjs +112 -0
- package/scripts/init.mjs +122 -0
- package/scripts/land.mjs +40 -0
- package/scripts/lib/adapters.mjs +156 -0
- package/scripts/lib/board-snapshot.mjs +511 -0
- package/scripts/lib/draft.mjs +385 -0
- package/scripts/lib/graduate.mjs +276 -0
- package/scripts/lib/instance.mjs +74 -0
- package/scripts/lib/marks.mjs +107 -0
- package/scripts/lib/materialize.mjs +138 -0
- package/scripts/lib/merge3.mjs +124 -0
- package/scripts/lib/offline-posture.mjs +120 -0
- package/scripts/lib/offline-respawn.mjs +18 -0
- package/scripts/lib/offline-wrangler.mjs +78 -0
- package/scripts/lib/publish-compose.mjs +12 -0
- package/scripts/lib/publish-conflict.mjs +78 -0
- package/scripts/lib/publish-evidence.mjs +144 -0
- package/scripts/lib/refine-compare.mjs +140 -0
- package/scripts/lib/refine-ledger.mjs +150 -0
- package/scripts/lib/refine-png.mjs +149 -0
- package/scripts/lib/seed-pack-build.mjs +141 -0
- package/scripts/lib/state-compare.mjs +68 -0
- package/scripts/lib/store.mjs +122 -0
- package/scripts/login.mjs +84 -0
- package/scripts/mark.mjs +112 -0
- package/scripts/migrate-board-keys.mjs +164 -0
- package/scripts/migrate.mjs +265 -0
- package/scripts/no-foreign-vocabulary.mjs +216 -0
- package/scripts/no-product-names.mjs +157 -0
- package/scripts/no-tenant-globals.mjs +1134 -0
- package/scripts/offline.mjs +247 -0
- package/scripts/og.mjs +170 -0
- package/scripts/one-tenant-resolver.mjs +146 -0
- package/scripts/open.mjs +63 -0
- package/scripts/publish.mjs +1041 -0
- package/scripts/read.mjs +31 -0
- package/scripts/refine.mjs +455 -0
- package/scripts/release-drift.mjs +138 -0
- package/scripts/restore.mjs +322 -0
- package/scripts/review.mjs +125 -0
- package/scripts/save.mjs +21 -0
- package/scripts/shell-lint.mjs +189 -0
- package/scripts/ship.mjs +460 -0
- package/scripts/shoot.mjs +264 -0
- package/scripts/smoke-invite.mjs +113 -0
- package/scripts/state-inventory.mjs +223 -0
- package/scripts/status.mjs +177 -0
- package/scripts/sync.mjs +27 -0
- package/scripts/tenant-do-rehearsal.mjs +1314 -0
- package/scripts/ui-copy-lint.mjs +202 -0
- package/scripts/watch.mjs +32 -0
- package/scripts/wrangler-preflight.mjs +246 -0
- package/seed/CANON.md +43 -0
- package/seed/README.md +119 -0
- package/seed/prototype-status.json +9 -0
- package/seed/registry.json +88 -0
- package/seed/skills/starter-ui/SKILL.md +52 -0
- package/seed/skills/starter-ui/skill.json +11 -0
- package/seed/skills/starter-ui/starter-tokens.css +73 -0
- package/seed/skills/starter-ui/starter-ui.css +318 -0
- package/seed/skills/starter-ui/starter-ui.js +50 -0
- package/seed/space.json +5 -0
- package/seed/start-here/prototypes/connect-your-terminal/index.html +428 -0
- package/seed/start-here/prototypes/connect-your-terminal/preview.webp +0 -0
- package/seed/start-here/prototypes/sample-with-comments/index.html +172 -0
- package/seed/start-here/prototypes/sample-with-comments/preview.webp +0 -0
- package/seed/start-here/prototypes/set-up-your-design-system/index.html +353 -0
- package/seed/start-here/prototypes/set-up-your-design-system/preview.webp +0 -0
- package/seed/threads.json +52 -0
- package/seed/worked-examples/prototypes/field-readings/index.html +273 -0
- package/seed/worked-examples/prototypes/field-readings/preview.webp +0 -0
- package/seed/worked-examples/prototypes/slide-deck/index.html +214 -0
- package/seed/worked-examples/prototypes/slide-deck/preview.webp +0 -0
- package/seed/worked-examples/prototypes/specimen-viewer/index.html +203 -0
- package/seed/worked-examples/prototypes/specimen-viewer/preview.webp +0 -0
- package/src/_worker.js +12668 -0
- package/src/board-key.mjs +57 -0
- package/src/board-room.mjs +881 -0
- package/src/bundle-keys.mjs +138 -0
- package/src/canon/collect-in-browser.js +215 -0
- package/src/canon/emit.mjs +232 -0
- package/src/canon/observe.mjs +260 -0
- package/src/canon/schema.mjs +451 -0
- package/src/canvas/DSEG-LICENSE.txt +95 -0
- package/src/canvas/DSEG7Classic-Bold.woff2 +0 -0
- package/src/canvas/canvas.css +885 -0
- package/src/canvas/canvas.js +5780 -0
- package/src/canvas/capture.js +485 -0
- package/src/chrome/appchrome.mjs +568 -0
- package/src/currency.mjs +203 -0
- package/src/delete-confirmation.mjs +254 -0
- package/src/drafts/drafts.js +326 -0
- package/src/entry.js +58 -0
- package/src/galleries.mjs +400 -0
- package/src/health-cron.mjs +173 -0
- package/src/identity.json +1 -0
- package/src/kv-codec.mjs +135 -0
- package/src/kv-identity.mjs +259 -0
- package/src/mail.mjs +599 -0
- package/src/provenance.mjs +74 -0
- package/src/publish-compose.mjs +363 -0
- package/src/publish-fork.mjs +221 -0
- package/src/publish-units.mjs +44 -0
- package/src/purge.mjs +81 -0
- package/src/review/COMMENTING-UX.md +306 -0
- package/src/review/cat.png +0 -0
- package/src/review/comment-cursor.svg +7 -0
- package/src/review/comments.js +1738 -0
- package/src/room-ticket.mjs +96 -0
- package/src/roster-chip.mjs +32 -0
- package/src/seed-pack.mjs +261 -0
- package/src/state-inventory.mjs +249 -0
- package/src/sw-logic.mjs +48 -0
- package/src/tenant-cache.mjs +141 -0
- package/src/tenant-context.mjs +386 -0
- package/src/tenant-do.js +2940 -0
- package/src/tenant-host.mjs +144 -0
- package/src/tenant-quotas.mjs +140 -0
- package/src/unit-core.mjs +103 -0
- package/src/unit-object.mjs +338 -0
- package/templates/README.md +67 -0
- package/templates/shell/deploy.yml +145 -0
- package/templates/shell/engine-bump.yml +142 -0
- package/templates/shell/health.yml +233 -0
- package/templates/shell/kv-backup.yml +201 -0
- package/templates/shell/roster-update.yml +110 -0
- package/templates/shell/space-preflight.yml +35 -0
- package/templates/shell/space-rebake.yml +79 -0
- package/templates/shell/store-backup.yml +152 -0
- package/templates/shell/wrangler.example.toml +266 -0
- package/templates/space/publish.yml +91 -0
package/pitis/index.html
ADDED
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>Your Piti 🐾</title>
|
|
7
|
+
<style>
|
|
8
|
+
:root { --ink:#2B2330; --muted:#8b7e96; --card:#fff; --line:#ece3f0; --accent:#7C5CFC;
|
|
9
|
+
--stage:#DCE6C4; --grass:#46B14A; --chev:#6f6780; }
|
|
10
|
+
* { box-sizing:border-box; }
|
|
11
|
+
html,body { margin:0; min-height:100%; }
|
|
12
|
+
/* dimmed backdrop — the customizer floats as a modal on top */
|
|
13
|
+
body {
|
|
14
|
+
min-height:100vh;
|
|
15
|
+
font-family: ui-rounded, "SF Pro Rounded", "Segoe UI", system-ui, sans-serif;
|
|
16
|
+
color: var(--ink);
|
|
17
|
+
background: rgba(43,35,48,.55);
|
|
18
|
+
display:grid; place-items:center; padding:24px;
|
|
19
|
+
}
|
|
20
|
+
/* the modal dialog */
|
|
21
|
+
.modal {
|
|
22
|
+
background: var(--card); border-radius:20px; width:100%; max-width:460px;
|
|
23
|
+
box-shadow: 0 40px 90px -30px rgba(0,0,0,.55), 0 2px 0 #fff inset;
|
|
24
|
+
animation: modal-in .26s cubic-bezier(.2,.9,.3,1.25) both;
|
|
25
|
+
overflow:hidden;
|
|
26
|
+
}
|
|
27
|
+
@keyframes modal-in { 0%{opacity:0;transform:translateY(10px) scale(.97)} 100%{opacity:1;transform:none} }
|
|
28
|
+
.modal-head {
|
|
29
|
+
display:flex; align-items:center; justify-content:flex-end;
|
|
30
|
+
padding:12px 14px;
|
|
31
|
+
}
|
|
32
|
+
.modal-x {
|
|
33
|
+
width:32px; height:32px; border:none; background:transparent; border-radius:9px;
|
|
34
|
+
font-size:21px; line-height:1; color:var(--muted); cursor:pointer;
|
|
35
|
+
display:grid; place-items:center; transition:background .12s, color .12s;
|
|
36
|
+
}
|
|
37
|
+
.modal-x:hover { background:#f3eef9; color:var(--ink); }
|
|
38
|
+
.modal-body { padding:24px 24px 24px; }
|
|
39
|
+
|
|
40
|
+
/* top pill — SPECIES tabs (cat / mastiff), small, selected = white/raised */
|
|
41
|
+
.species {
|
|
42
|
+
display:flex; gap:3px; justify-content:center; align-items:center;
|
|
43
|
+
background:#f3eef9; border:1px solid var(--line); border-radius:13px;
|
|
44
|
+
padding:3px; width:max-content; margin:0 auto 14px;
|
|
45
|
+
}
|
|
46
|
+
.species button {
|
|
47
|
+
width:44px; height:34px; border:none; background:transparent; border-radius:10px;
|
|
48
|
+
cursor:pointer; display:grid; place-items:center; color:#9a8fb0;
|
|
49
|
+
transition:background .14s, box-shadow .14s, transform .12s, color .14s;
|
|
50
|
+
}
|
|
51
|
+
.species button svg { width:21px; height:21px; display:block; }
|
|
52
|
+
.species button:hover { transform:translateY(-1px); }
|
|
53
|
+
.species button.sel { background:#fff; box-shadow:0 2px 7px -2px rgba(40,30,60,.28); color:var(--ink); }
|
|
54
|
+
|
|
55
|
+
/* stage — green panel + grass oval, with four chevrons */
|
|
56
|
+
.stage {
|
|
57
|
+
position:relative; background:var(--stage); border-radius:20px;
|
|
58
|
+
height:248px; margin-bottom:18px; overflow:hidden;
|
|
59
|
+
}
|
|
60
|
+
.grass { position:absolute; bottom:46px; left:50%; transform:translateX(-50%);
|
|
61
|
+
width:200px; height:42px; border-radius:50%; background:var(--grass);
|
|
62
|
+
box-shadow:0 6px 0 -2px rgba(0,0,0,.06); }
|
|
63
|
+
.pet { position:absolute; left:50%; top:50%; transform:translate(-50%,-54%);
|
|
64
|
+
width:182px; height:182px; }
|
|
65
|
+
.pet svg { width:100%; height:100%; display:block; }
|
|
66
|
+
|
|
67
|
+
/* four chevron buttons — top pair = HAT, bottom pair = COLOUR.
|
|
68
|
+
Simple flat light-grey squares. */
|
|
69
|
+
.chev {
|
|
70
|
+
position:absolute; width:48px; height:46px; border:none; cursor:pointer;
|
|
71
|
+
background:#ececef; border-radius:13px; display:grid; place-items:center;
|
|
72
|
+
color:#2B2330; box-shadow:0 1px 2px rgba(40,30,60,.12);
|
|
73
|
+
transition:background .12s, transform .1s;
|
|
74
|
+
}
|
|
75
|
+
.chev:hover { background:#e2e2e8; }
|
|
76
|
+
.chev:active { transform:scale(.94); }
|
|
77
|
+
.chev svg { width:24px; height:24px; display:block; }
|
|
78
|
+
.chev.tl { left:14px; top:34px; }
|
|
79
|
+
.chev.tr { right:14px; top:34px; }
|
|
80
|
+
.chev.bl { left:14px; bottom:34px; }
|
|
81
|
+
.chev.br { right:14px; bottom:34px; }
|
|
82
|
+
.chev-label { position:absolute; left:50%; transform:translateX(-50%); font-size:10.5px;
|
|
83
|
+
font-weight:700; letter-spacing:.04em; text-transform:uppercase;
|
|
84
|
+
color:rgba(43,35,48,.4); pointer-events:none; }
|
|
85
|
+
.chev-label.top { top:18px; }
|
|
86
|
+
.chev-label.bot { bottom:16px; }
|
|
87
|
+
|
|
88
|
+
/* colour swatch row — direct pick; selected = purple ring */
|
|
89
|
+
.swatches { display:flex; gap:10px; flex-wrap:wrap; justify-content:center; margin-bottom:8px; }
|
|
90
|
+
.sw { width:34px; height:34px; border-radius:50%; border:3px solid #fff; cursor:pointer; padding:0;
|
|
91
|
+
box-shadow:0 0 0 1px var(--line), 0 3px 7px -3px rgba(0,0,0,.3); transition:transform .12s; }
|
|
92
|
+
.sw:hover { transform:scale(1.1); }
|
|
93
|
+
.sw.sel { box-shadow:0 0 0 3px var(--accent); transform:scale(1.1); }
|
|
94
|
+
.swatches.second { margin-bottom:16px; }
|
|
95
|
+
|
|
96
|
+
/* name box */
|
|
97
|
+
.namebox { width:100%; font:inherit; font-size:16px; font-weight:600; text-align:center;
|
|
98
|
+
padding:12px 14px; border:1px solid var(--line); border-radius:13px; outline:none;
|
|
99
|
+
color:var(--ink); background:#faf8fd; transition:border-color .15s, box-shadow .15s; }
|
|
100
|
+
.namebox::placeholder { color:#b6acc2; font-weight:500; }
|
|
101
|
+
.namebox:focus { border-color:var(--accent); box-shadow:0 0 0 4px rgba(124,92,252,.15); background:#fff; }
|
|
102
|
+
|
|
103
|
+
</style>
|
|
104
|
+
</head>
|
|
105
|
+
<body>
|
|
106
|
+
<div class="modal" role="dialog" aria-modal="true" aria-label="Customize your Piti">
|
|
107
|
+
<div class="modal-body">
|
|
108
|
+
|
|
109
|
+
<!-- SPECIES tabs -->
|
|
110
|
+
<div class="species" id="species" role="group" aria-label="Species"></div>
|
|
111
|
+
|
|
112
|
+
<!-- STAGE: pet on grass + four chevrons (top=hat, bottom=colour) -->
|
|
113
|
+
<div class="stage">
|
|
114
|
+
<div class="grass"></div>
|
|
115
|
+
<div class="pet" id="pet"></div>
|
|
116
|
+
|
|
117
|
+
<button class="chev tl" id="hatPrev" aria-label="Previous hat" title="Previous hat"></button>
|
|
118
|
+
<button class="chev tr" id="hatNext" aria-label="Next hat" title="Next hat"></button>
|
|
119
|
+
<button class="chev bl" id="colPrev" aria-label="Previous colour" title="Previous colour"></button>
|
|
120
|
+
<button class="chev br" id="colNext" aria-label="Next colour" title="Next colour"></button>
|
|
121
|
+
</div>
|
|
122
|
+
|
|
123
|
+
<!-- COLOUR swatch row -->
|
|
124
|
+
<div class="swatches" id="swatches" role="group" aria-label="Colour"></div>
|
|
125
|
+
|
|
126
|
+
<input type="text" id="name" class="namebox" maxlength="18" placeholder="Name your pal" autocomplete="off" />
|
|
127
|
+
</div>
|
|
128
|
+
</div>
|
|
129
|
+
|
|
130
|
+
<script src="piti.js"></script>
|
|
131
|
+
<script>
|
|
132
|
+
const cfg = Piti.loadConfig();
|
|
133
|
+
const petEl = document.getElementById('pet');
|
|
134
|
+
const nameInput = document.getElementById('name');
|
|
135
|
+
nameInput.value = cfg.name === 'Pal' ? '' : cfg.name;
|
|
136
|
+
|
|
137
|
+
// simple chevron glyphs (left / right)
|
|
138
|
+
const CHEV_L = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><path d="M15 5 L8 12 L15 19"/></svg>';
|
|
139
|
+
const CHEV_R = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><path d="M9 5 L16 12 L9 19"/></svg>';
|
|
140
|
+
document.getElementById('hatPrev').innerHTML = CHEV_L;
|
|
141
|
+
document.getElementById('hatNext').innerHTML = CHEV_R;
|
|
142
|
+
document.getElementById('colPrev').innerHTML = CHEV_L;
|
|
143
|
+
document.getElementById('colNext').innerHTML = CHEV_R;
|
|
144
|
+
|
|
145
|
+
// species tab icons (Lucide cat + a hand-drawn droopy-eared mastiff face)
|
|
146
|
+
const FACE = {
|
|
147
|
+
cat: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5c.67 0 1.35.09 2 .26 1.78-2 5.03-2.84 6.42-2.26 1.4.58-.42 7-.42 7 .57 1.07 1 2.24 1 3.44C21 17.9 16.97 21 12 21s-9-3.1-9-7.56c0-1.25.5-2.4 1-3.44 0 0-1.89-6.42-.5-7 1.39-.58 4.72.23 6.5 2.23A9.04 9.04 0 0 1 12 5Z"/><path d="M8 14v.5"/><path d="M16 14v.5"/><path d="M11.25 16.25h1.5L12 17l-.75-.75Z"/></svg>',
|
|
148
|
+
// mastiff: a broad jowly head with long droopy ears hanging down the sides
|
|
149
|
+
mastiff: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M6 5c-1.6 0-2.6 1.4-2.6 3.4 0 3 .8 6.4 2.4 8.2M18 5c1.6 0 2.6 1.4 2.6 3.4 0 3-.8 6.4-2.4 8.2"/><path d="M6.4 7.5C7.4 6 9.4 5 12 5s4.6 1 5.6 2.5c1 1.5 1.4 3.4 1.4 5.5 0 4-3 7-7 7s-7-3-7-7c0-2.1.4-4 1.4-5.5Z"/><path d="M9.5 12.5v.5M14.5 12.5v.5"/><path d="M10.5 16h3l-1.5 1.5z"/></svg>',
|
|
150
|
+
};
|
|
151
|
+
const SPECIES = [ { id:'cat', label:'Cat' }, { id:'mastiff', label:'Mastiff' } ];
|
|
152
|
+
|
|
153
|
+
// Per-species swatch sets, explicit and ordered:
|
|
154
|
+
// • cat → Ginger & white FIRST, then the tabby.
|
|
155
|
+
// • mastiff → a single fixed "Fawn" look (fawn + black mask) — no recolour.
|
|
156
|
+
const CAT_COLOURS = ['Ginger & white', 'Tabby'];
|
|
157
|
+
const MASTIFF_COLOURS = ['Fawn'];
|
|
158
|
+
|
|
159
|
+
function draw() { petEl.innerHTML = Piti.svg(cfg, {}); }
|
|
160
|
+
|
|
161
|
+
// map the current species to its ordered list of palette indices
|
|
162
|
+
function colourIndices() {
|
|
163
|
+
const names = cfg.species === 'mastiff' ? MASTIFF_COLOURS : CAT_COLOURS;
|
|
164
|
+
return names
|
|
165
|
+
.map(n => Piti.PALETTE.findIndex(p => p.name === n))
|
|
166
|
+
.filter(i => i >= 0);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// SPECIES tabs
|
|
170
|
+
const speciesEl = document.getElementById('species');
|
|
171
|
+
SPECIES.forEach(s => {
|
|
172
|
+
const b = document.createElement('button');
|
|
173
|
+
b.className = (s.id === cfg.species) ? 'sel' : '';
|
|
174
|
+
b.innerHTML = FACE[s.id];
|
|
175
|
+
b.title = s.label; b.setAttribute('aria-label', s.label);
|
|
176
|
+
b.dataset.species = s.id;
|
|
177
|
+
b.onclick = () => {
|
|
178
|
+
cfg.species = s.id;
|
|
179
|
+
// if the current colour is now invalid (a cat pattern on the mastiff), snap to the first valid one
|
|
180
|
+
if (!colourIndices().includes(cfg.furIdx)) cfg.furIdx = colourIndices()[0];
|
|
181
|
+
buildSwatches();
|
|
182
|
+
sync();
|
|
183
|
+
};
|
|
184
|
+
speciesEl.appendChild(b);
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
// COLOUR swatch row (rebuilt when species changes — each species has its own list)
|
|
188
|
+
const swatchesEl = document.getElementById('swatches');
|
|
189
|
+
function buildSwatches() {
|
|
190
|
+
swatchesEl.innerHTML = '';
|
|
191
|
+
colourIndices().forEach(i => {
|
|
192
|
+
const p = Piti.PALETTE[i];
|
|
193
|
+
const b = document.createElement('button');
|
|
194
|
+
b.className = 'sw' + (i === cfg.furIdx ? ' sel' : '');
|
|
195
|
+
b.style.background = p.swatch || p.fur;
|
|
196
|
+
b.title = p.name; b.setAttribute('aria-label', p.name);
|
|
197
|
+
b.dataset.idx = i;
|
|
198
|
+
b.onclick = () => { cfg.furIdx = i; sync(); };
|
|
199
|
+
swatchesEl.appendChild(b);
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// chevrons: top pair cycles HAT, bottom pair cycles COLOUR (wrap-around)
|
|
204
|
+
function cycleHat(dir) {
|
|
205
|
+
const n = Piti.HATS.length;
|
|
206
|
+
let cur = Piti.HATS.findIndex(h => h.id === (cfg.hat || 'none'));
|
|
207
|
+
if (cur < 0) cur = 0;
|
|
208
|
+
cfg.hat = Piti.HATS[(cur + dir + n) % n].id;
|
|
209
|
+
sync();
|
|
210
|
+
}
|
|
211
|
+
function cycleColour(dir) {
|
|
212
|
+
const idxs = colourIndices();
|
|
213
|
+
let pos = idxs.indexOf(cfg.furIdx);
|
|
214
|
+
if (pos < 0) pos = 0;
|
|
215
|
+
cfg.furIdx = idxs[(pos + dir + idxs.length) % idxs.length];
|
|
216
|
+
sync();
|
|
217
|
+
}
|
|
218
|
+
document.getElementById('hatPrev').onclick = () => cycleHat(-1);
|
|
219
|
+
document.getElementById('hatNext').onclick = () => cycleHat(1);
|
|
220
|
+
document.getElementById('colPrev').onclick = () => cycleColour(-1);
|
|
221
|
+
document.getElementById('colNext').onclick = () => cycleColour(1);
|
|
222
|
+
|
|
223
|
+
// when shown inside the overlay iframe, the parent paints the dim backdrop, so the
|
|
224
|
+
// page itself is transparent and the parent owns close/refresh via postMessage.
|
|
225
|
+
const inFrame = (function(){ try { return window.top !== window.self; } catch(e){ return true; } })();
|
|
226
|
+
if (inFrame) document.documentElement.style.background = document.body.style.background = 'transparent';
|
|
227
|
+
function notify(msg) { if (inFrame) { try { parent.postMessage({ piti: msg }, '*'); } catch (e) {} } }
|
|
228
|
+
|
|
229
|
+
// No Save button — every change persists automatically and summons the piti.
|
|
230
|
+
function persist() {
|
|
231
|
+
cfg.name = (nameInput.value || 'Pal').trim().slice(0, 18);
|
|
232
|
+
Piti.saveConfig(cfg);
|
|
233
|
+
try { localStorage.setItem('piti-revealed', '1'); } catch (e) {}
|
|
234
|
+
Piti.auto(); // ensure the companion is live (standalone view)
|
|
235
|
+
Piti.refreshLive(cfg); // …wearing the latest look
|
|
236
|
+
notify('saved'); // …and tell the parent page to update its companion
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
function sync() {
|
|
240
|
+
[...speciesEl.children].forEach(b => b.classList.toggle('sel', b.dataset.species === cfg.species));
|
|
241
|
+
[...swatchesEl.children].forEach(b => b.classList.toggle('sel', +b.dataset.idx === cfg.furIdx));
|
|
242
|
+
draw();
|
|
243
|
+
persist();
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// if the saved colour was dropped from the picker, snap to the first visible one
|
|
247
|
+
if (!colourIndices().includes(cfg.furIdx)) cfg.furIdx = colourIndices()[0];
|
|
248
|
+
buildSwatches();
|
|
249
|
+
draw();
|
|
250
|
+
nameInput.addEventListener('input', persist);
|
|
251
|
+
|
|
252
|
+
// keep the companion consistent on this page too (mounts if already revealed; no-op in iframe)
|
|
253
|
+
Piti.auto();
|
|
254
|
+
|
|
255
|
+
// close — only by clicking outside the card (or Esc). Tells the parent to dismiss
|
|
256
|
+
// the overlay; standalone visits fall back to going back / home.
|
|
257
|
+
function closeModal() {
|
|
258
|
+
if (inFrame) notify('close');
|
|
259
|
+
else if (history.length > 1) history.back();
|
|
260
|
+
else location.href = '/';
|
|
261
|
+
}
|
|
262
|
+
addEventListener('click', e => { if (!e.target.closest('.modal')) closeModal(); });
|
|
263
|
+
addEventListener('keydown', e => { if (e.key === 'Escape') closeModal(); });
|
|
264
|
+
</script>
|
|
265
|
+
</body>
|
|
266
|
+
</html>
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/* ============================================================
|
|
2
|
+
Piti build addon — the ENTIRE build-time footprint of the
|
|
3
|
+
Piti companion lives here, so build.js stays Piti-agnostic.
|
|
4
|
+
|
|
5
|
+
build.js loads this as an optional addon (one try/import) and
|
|
6
|
+
calls these generic hooks; if this file is absent the site
|
|
7
|
+
builds exactly the same, just without the companion.
|
|
8
|
+
|
|
9
|
+
Hooks:
|
|
10
|
+
css() -> extra <style> appended to every shell page
|
|
11
|
+
cornerHtml() -> markup appended before </body> on shell pages (fixed paw)
|
|
12
|
+
bodyScripts() -> <script> appended before </body> on shell pages
|
|
13
|
+
transformHtml(h, v) -> post-process for every COPIED prototype/page/demo
|
|
14
|
+
emit(ctx) -> copy the companion's own files into /dist
|
|
15
|
+
============================================================ */
|
|
16
|
+
|
|
17
|
+
// Loader injected into every copied prototype/page/demo so the pal follows the
|
|
18
|
+
// cursor INSIDE prototypes too — not just the nav shell. auto() skips inside
|
|
19
|
+
// iframes, so previews never spawn a pal. Absolute /piti.js => served from root.
|
|
20
|
+
export function transformHtml(html, version) {
|
|
21
|
+
if (html.includes("gv-piti-start") || html.includes("piti.js")) return html; // already has it / is the customizer
|
|
22
|
+
const tag =
|
|
23
|
+
'<!--gv-piti-start--><script src="/piti.js?v=' + (version || "") +
|
|
24
|
+
'" defer></script><script>addEventListener("DOMContentLoaded",function(){try{window.Piti&&window.Piti.auto()}catch(e){}})</script><!--gv-piti-end-->';
|
|
25
|
+
const i = html.toLowerCase().lastIndexOf("</body>");
|
|
26
|
+
return i === -1 ? html + tag : html.slice(0, i) + tag + html.slice(i);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Scripts for the generated shell pages (which aren't passed through transformHtml).
|
|
30
|
+
export function bodyScripts(version) {
|
|
31
|
+
const v = version ? "?v=" + version : "";
|
|
32
|
+
return '<script src="/piti.js' + v + '" defer></script>' +
|
|
33
|
+
'<script>addEventListener("DOMContentLoaded",function(){try{window.Piti&&window.Piti.auto();}catch(e){}});</script>';
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// A quiet paw tucked into the bottom-right corner → opens the customizer. Kept
|
|
37
|
+
// barely-there until hover so it reads as an easter egg, not chrome.
|
|
38
|
+
// (The companion itself is summoned/dismissed with Shift+Ñ, handled in piti.js.)
|
|
39
|
+
export function cornerHtml() {
|
|
40
|
+
return '<a class="piti-paw" href="/pitis/" aria-label="Piti" title="Piti">' +
|
|
41
|
+
'<svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">' +
|
|
42
|
+
'<ellipse cx="12" cy="16.5" rx="5" ry="4.2"/>' +
|
|
43
|
+
'<ellipse cx="5.6" cy="11.2" rx="2" ry="2.7"/>' +
|
|
44
|
+
'<ellipse cx="9.8" cy="8.2" rx="2.1" ry="2.9"/>' +
|
|
45
|
+
'<ellipse cx="14.2" cy="8.2" rx="2.1" ry="2.9"/>' +
|
|
46
|
+
'<ellipse cx="18.4" cy="11.2" rx="2" ry="2.7"/>' +
|
|
47
|
+
'</svg></a>';
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function css() {
|
|
51
|
+
return `
|
|
52
|
+
/* Pitis is an admin-only toy: hidden by default, revealed only when the profile
|
|
53
|
+
script marks the page as admin (html.gv-admin — set by PROFILE_JS from /__me).
|
|
54
|
+
Default-hidden (not JS-hidden) so users never see a flash of the paw. */
|
|
55
|
+
.piti-paw { display: none; }
|
|
56
|
+
html.gv-admin .piti-paw {
|
|
57
|
+
position: fixed; right: 14px; bottom: 12px; z-index: 50;
|
|
58
|
+
display: inline-flex; align-items: center; justify-content: center;
|
|
59
|
+
width: 28px; height: 28px; border-radius: 8px;
|
|
60
|
+
color: var(--faint); opacity: .28;
|
|
61
|
+
transition: color .15s ease, opacity .15s ease, transform .15s ease;
|
|
62
|
+
}
|
|
63
|
+
.piti-paw svg { width: 15px; height: 15px; display: block; }
|
|
64
|
+
.piti-paw:hover { color: var(--accent); opacity: 1; transform: translateY(-1px); }
|
|
65
|
+
.piti-paw:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; opacity: 1; }
|
|
66
|
+
@media print { .piti-paw { display: none; } }`;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Copy the companion's own files into /dist. ctx provides build.js helpers so we
|
|
70
|
+
// don't duplicate them: { ROOT, DIST, fs, path, copyDir, isInternalOnly, exists }.
|
|
71
|
+
export async function emit({ ROOT, DIST, fs, path, copyDir, isInternalOnly, exists }) {
|
|
72
|
+
const src = path.join(ROOT, "pitis");
|
|
73
|
+
if (!(await exists(src))) return;
|
|
74
|
+
// Ship ONLY the playable app — never the internal docs (*.md) or the gitignored
|
|
75
|
+
// research imagery in reference/ (third-party reference assets, kept on-machine only).
|
|
76
|
+
const skip = (name) => isInternalOnly(name) || name.endsWith(".md") || name === "reference";
|
|
77
|
+
await copyDir(src, path.join(DIST, "pitis"), skip);
|
|
78
|
+
// Also expose the engine at the dist root so any page can load it by absolute path.
|
|
79
|
+
const engine = path.join(src, "piti.js");
|
|
80
|
+
if (await exists(engine)) await fs.copyFile(engine, path.join(DIST, "piti.js"));
|
|
81
|
+
}
|