@lovek4d/kickflip 0.5.0 → 0.6.0
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/CONTEXT.md +105 -68
- package/README.md +1 -1
- package/SKILL.md +27 -21
- package/bin/kickflip.mjs +27 -18
- package/bin/wait-events.mjs +2 -2
- package/board/agents.mjs +2 -0
- package/board/arch-review.mjs +4 -4
- package/board/bin/board.mjs +199 -79
- package/board/build-script.mjs +2 -1
- package/board/domain.mjs +9 -7
- package/board/finish.mjs +4 -4
- package/board/headless.mjs +9 -4
- package/board/on-host.mjs +1 -1
- package/board/onboarding.mjs +11 -0
- package/board/prototype-base.mjs +1 -0
- package/board/prototype-page.mjs +1 -0
- package/board/public/app-arch.js +1 -1
- package/board/public/app-asks.js +6 -6
- package/board/public/app-banner.js +7 -13
- package/board/public/app-cards.js +75 -37
- package/board/public/app-core.js +26 -8
- package/board/public/app-header.js +8 -8
- package/board/public/app-lanes.js +67 -58
- package/board/public/app-needs.js +140 -10
- package/board/public/app-reader.js +1 -1
- package/board/public/app-snapshot.js +46 -72
- package/board/public/app-threads.js +78 -75
- package/board/public/app.html +9 -4
- package/board/public/app.js +114 -38
- package/board/public/attach.js +2 -2
- package/board/public/dialogs.js +9 -39
- package/board/public/hub-kit.js +66 -4
- package/board/public/hub.css +2 -0
- package/board/public/linear-key.js +46 -35
- package/board/public/new-task.js +20 -39
- package/board/public/progress-review.html +46 -0
- package/board/public/progress-review.js +158 -0
- package/board/public/prototype-kit.js +137 -7
- package/board/public/prototype-switcher.js +152 -123
- package/board/public/prototype.html +57 -3
- package/board/public/router.js +7 -6
- package/board/public/shell.js +68 -26
- package/board/public/sidebar.css +1 -0
- package/board/public/sidebar.js +16 -30
- package/board/public/style.css +205 -83
- package/board/public/ui-cards.js +91 -65
- package/board/public/ui-enums.js +1 -1
- package/board/public/ui-header.js +27 -18
- package/board/public/ui-hub.js +12 -1
- package/board/public/ui-links.js +7 -7
- package/board/public/ui-order.js +12 -10
- package/board/public/ui-page-header.js +19 -7
- package/board/public/ui-patch.js +7 -33
- package/board/public/ui-progress-bar.js +28 -0
- package/board/public/ui-questions.js +47 -52
- package/board/public/ui-sidebar.js +34 -26
- package/board/public/ui-snapshot.js +43 -52
- package/board/public/ui-threads.js +59 -30
- package/board/public/ui.js +125 -18
- package/board/public/view-hub-settings.js +22 -67
- package/board/public/view-hub.js +19 -4
- package/board/public/view-notes.js +27 -7
- package/board/public/view-questions.js +205 -240
- package/board/public/view-settings.js +313 -76
- package/board/render-check.mjs +10 -0
- package/board/review.mjs +1 -1
- package/board/server.mjs +19 -20
- package/board/stop.mjs +1 -0
- package/board/store.mjs +29 -15
- package/board/sync.mjs +2 -0
- package/board/tickets.mjs +3 -3
- package/board/transcript.mjs +2 -0
- package/board/worktree.mjs +25 -20
- package/hooks-plugin/hooks/board-data-gate.mjs +50 -0
- package/hooks-plugin/hooks/hooks.json +9 -0
- package/hooks-plugin/hooks/usage-gate.mjs +20 -3
- package/hub/board-repo.mjs +1 -1
- package/hub/boards.mjs +4 -4
- package/hub/front-door.mjs +5 -5
- package/hub/github.mjs +3 -3
- package/hub/hub.mjs +11 -11
- package/hub/incoming.mjs +2 -2
- package/hub/linear.mjs +1 -2
- package/hub/live.mjs +2 -2
- package/hub/locks.mjs +1 -1
- package/hub/owner-checks.mjs +1 -1
- package/hub/pr-report.mjs +2 -2
- package/hub/presence.mjs +1 -1
- package/hub/push.mjs +2 -2
- package/hub/readiness.mjs +1 -2
- package/hub/review-send.mjs +1 -0
- package/hub/secrets.mjs +2 -0
- package/hub/self-restart.mjs +2 -0
- package/hub/sessions.mjs +2 -2
- package/hub/share.mjs +1 -0
- package/hub/slack.mjs +2 -2
- package/hub/stream.mjs +10 -13
- package/hub/try.mjs +7 -7
- package/hub/upgrade.mjs +1 -1
- package/hub/usage.mjs +3 -3
- package/hub/views.mjs +1 -1
- package/package.json +2 -1
- package/shared/audit.mjs +4 -0
- package/shared/card-prs.mjs +1 -1
- package/shared/fake-gh.mjs +17 -4
- package/shared/machine-gate.mjs +2 -0
- package/shared/prototype-frame.js +1 -0
- package/shared/service.mjs +4 -4
- package/shared/usage-gate.mjs +1 -1
- package/board/public/ui-phase-bars.js +0 -17
package/board/public/style.css
CHANGED
|
@@ -82,8 +82,10 @@ button.chip { border: 0; }
|
|
|
82
82
|
.status.review { border-color: var(--color-info); background: conic-gradient(var(--color-info) 0 75%, transparent 75% 100%); }
|
|
83
83
|
.sub.agent { color: var(--color-notice); }
|
|
84
84
|
.sub.next { color: var(--color-notice); }
|
|
85
|
-
.card-hold
|
|
85
|
+
.card-hold { color: var(--color-quiet); }
|
|
86
|
+
.card-blocked, .card-action { color: var(--color-notice); }
|
|
86
87
|
.card-ready { color: var(--color-success); }
|
|
88
|
+
.card-staging { color: var(--color-notice); }
|
|
87
89
|
.sub.next.idle { color: var(--muted); }
|
|
88
90
|
.sub.refused { color: var(--color-danger); }
|
|
89
91
|
.toast-stack { position: fixed; left: 50%; bottom: calc(var(--app-bottom, 0px) + 12px + env(safe-area-inset-bottom));
|
|
@@ -163,6 +165,14 @@ button.link { background: none; border: 0; color: var(--accent); padding: 8px 12
|
|
|
163
165
|
.wb-done { padding: 8px 12px; font-size: 12.5px; color: var(--muted); }
|
|
164
166
|
.wb-done a { color: inherit; text-decoration: underline; text-underline-offset: 2px; }
|
|
165
167
|
.wb-loosehead { cursor: default; }
|
|
168
|
+
.wb-counts { position: relative; border: 0; background: none; padding: 4px 0; font: inherit; cursor: help; color: var(--muted); font-weight: 400; font-variant-numeric: tabular-nums; white-space: nowrap; }
|
|
169
|
+
.wb-tip { display: none; position: absolute; right: 0; top: 100%; z-index: 6; margin-top: 2px; padding: 8px 10px; border: 1px solid var(--line); border-radius: 8px; background: var(--panel); box-shadow: 0 6px 18px rgba(0,0,0,.18); color: var(--text); font-weight: 400; text-align: left; }
|
|
170
|
+
.wb-counts:hover .wb-tip, .wb-counts.open .wb-tip { display: block; }
|
|
171
|
+
.wb-counts .wv-cur { font-weight: 700; }
|
|
172
|
+
.wb-counts .wv-review { color: var(--color-info); }
|
|
173
|
+
.wb-counts .wv-progress { color: var(--color-notice); }
|
|
174
|
+
.wb-counts .wv-todo, .wb-counts .wv-done { color: var(--color-quiet); }
|
|
175
|
+
.wb-lane + .wb-lane, .wb-lane + .wb-loose { border-top: 1px solid var(--line); }
|
|
166
176
|
.wb-loosehead:hover { background: var(--band); }
|
|
167
177
|
/* A wave card's step number, inside its id chip, and its ⋯ menu. */
|
|
168
178
|
.wn { color: var(--muted); font-variant-numeric: tabular-nums; padding-right: 5px; margin-right: 4px; border-right: 1px solid var(--line); }
|
|
@@ -181,8 +191,9 @@ button.link { background: none; border: 0; color: var(--accent); padding: 8px 12
|
|
|
181
191
|
.refresh #refresh { padding: 4px; margin-left: -4px; flex: none; }
|
|
182
192
|
.refresh #status { font-size: 12px; min-width: 0; }
|
|
183
193
|
.refresh .late { color: var(--color-notice); font-weight: 600; }
|
|
184
|
-
|
|
185
|
-
.refresh .
|
|
194
|
+
/* The header's time keeps its text; a stopped or offline board turns it and the refresh arrow red, paused usage orange. */
|
|
195
|
+
.refresh .down, .refresh:has(.down) #refresh { color: var(--color-danger); }
|
|
196
|
+
.refresh .hold, .refresh:has(.hold) #refresh { color: var(--color-notice); }
|
|
186
197
|
.lane-github { margin-left: auto; font-size: 12px; font-weight: 400; color: var(--muted); text-align: right; }
|
|
187
198
|
.lane-github .late { color: var(--color-notice); }
|
|
188
199
|
.msg.other { background: transparent; border: 1px solid var(--line); }
|
|
@@ -202,10 +213,12 @@ code { overflow-wrap: anywhere; }
|
|
|
202
213
|
/* The ⌘↵ / Ctrl+↵ hint left of Send: only where there is a keyboard to press it on. */
|
|
203
214
|
.send-hint { display: none; color: var(--muted); font-size: 12px; white-space: nowrap; }
|
|
204
215
|
@media (hover: hover) and (pointer: fine) { .send-hint { display: inline; } }
|
|
205
|
-
/* A composer's text box (BoardUI.dropZone)
|
|
206
|
-
the
|
|
216
|
+
/* A composer's text box (BoardUI.dropZone), its attach button inside at the bottom right with the text kept clear of it:
|
|
217
|
+
while files are dragged over the composer, attach.js marks it .dragging and the box gets a dashed accent outline
|
|
218
|
+
with Drop to attach over it. */
|
|
207
219
|
.dz { position: relative; clear: both; border-radius: 8px; }
|
|
208
|
-
.dz > textarea { display: block; }
|
|
220
|
+
.dz > textarea { display: block; padding-bottom: 40px; }
|
|
221
|
+
.dz > .attach { position: absolute; right: 6px; bottom: 6px; width: 32px; height: 32px; z-index: 1; }
|
|
209
222
|
.dz-hint { display: none; position: absolute; inset: 0; align-items: center; justify-content: center; border-radius: 8px; pointer-events: none;
|
|
210
223
|
background: color-mix(in srgb, var(--panel) 80%, transparent); color: var(--accent); font-weight: 600; font-size: 15px; }
|
|
211
224
|
[data-composer].dragging .dz { outline: 2px dashed var(--accent); outline-offset: 3px; }
|
|
@@ -232,7 +245,6 @@ code { overflow-wrap: anywhere; }
|
|
|
232
245
|
.msg .body:empty { display: none; }
|
|
233
246
|
.note-tools { display: flex; align-items: flex-start; gap: 6px; }
|
|
234
247
|
.note-tools .pending-files { flex: 1; margin-top: 4px; }
|
|
235
|
-
.note-tools .attach { margin-top: 2px; }
|
|
236
248
|
|
|
237
249
|
/* Compose button and sheet */
|
|
238
250
|
main { padding-bottom: calc(110px + env(safe-area-inset-bottom)); }
|
|
@@ -322,9 +334,24 @@ main { padding-bottom: calc(110px + env(safe-area-inset-bottom)); }
|
|
|
322
334
|
}
|
|
323
335
|
.working-dot { display: inline-block; width: 7px; height: 7px; border-radius: 50%; background: var(--color-notice); margin-right: 5px; vertical-align: 1px; }
|
|
324
336
|
@media (prefers-reduced-motion: no-preference) { .working-dot { animation: pulse 1.4s ease-in-out infinite; } }
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
.
|
|
337
|
+
/* A thread box's row: What's left? at the left, the eye, fire and attach at the right, then Send, or a pair below
|
|
338
|
+
(docs/adr/2026-11-05-1918-done-shows-only-in-in-review-beside-reply.md). */
|
|
339
|
+
form[data-reply] .row .quick { margin: 0; }
|
|
340
|
+
form[data-reply] .icons { display: inline-flex; flex: none; margin-left: auto; }
|
|
341
|
+
.dz.bare > textarea { padding-bottom: 12px; }
|
|
342
|
+
/* A composer's send buttons (ui.js sendButton), each with its key as a small gray hint where there is a keyboard and
|
|
343
|
+
room. A pair takes a row of two halves; a Todo card's reply box wraps its pair under the row. */
|
|
344
|
+
.send-actions { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; margin-top: 10px; }
|
|
345
|
+
.send-actions button, [data-sends] button { display: inline-flex; align-items: center; justify-content: center; gap: 6px; }
|
|
346
|
+
.send-actions button { min-height: 44px; }
|
|
347
|
+
form[data-reply] .row { flex-wrap: wrap; gap: 6px; }
|
|
348
|
+
form[data-reply] .row > .send-actions { flex: 0 0 100%; margin-top: 4px; }
|
|
349
|
+
.key-hint { display: none; font-size: 11px; font-weight: 400; color: var(--muted); white-space: nowrap; }
|
|
350
|
+
button.primary .key-hint { color: color-mix(in srgb, var(--on-accent) 62%, transparent); }
|
|
351
|
+
@media (hover: hover) and (pointer: fine) and (min-width: 600px) { .key-hint { display: inline; } }
|
|
352
|
+
#askStatus { margin: 6px 2px 0; }
|
|
353
|
+
#askStatus:empty { display: none; }
|
|
354
|
+
.q .proto-view { display: inline-block; margin: 0 0 10px; color: var(--accent); }
|
|
328
355
|
.msg .ask-actions { margin: -4px -6px 0 8px; }
|
|
329
356
|
button.attach { border: 0; background: transparent; padding: 0; }
|
|
330
357
|
button.attach:disabled { opacity: .35; }
|
|
@@ -337,21 +364,31 @@ button.attach:disabled { opacity: .35; }
|
|
|
337
364
|
pixel off its siblings (docs/adr/2026-11-03-1519-a-building-cards-phase-bars-end-its-time-row.md). */
|
|
338
365
|
.card-time .phase-bars { display: inline-flex; gap: 2px; vertical-align: middle; position: relative; top: -1px; }
|
|
339
366
|
.phase-bars i { width: 9px; height: 4px; border-radius: 2px; background: var(--line); }
|
|
340
|
-
/* A strip dims
|
|
341
|
-
(docs/adr/2026-11-03-2024-every-in-progress-card-shows-its-phase-bars.md). app-cards.js
|
|
367
|
+
/* A strip dims while the card waits on something other than a builder; ui-progress-bar.js then writes its running bar
|
|
368
|
+
as done, so it stops blinking (docs/adr/2026-11-03-2024-every-in-progress-card-shows-its-phase-bars.md). app-cards.js
|
|
369
|
+
sweeps bars in --bar-fill. */
|
|
342
370
|
.phase-bars { --bar-fill: var(--color-notice); }
|
|
343
371
|
.phase-bars.dim { --bar-fill: color-mix(in srgb, var(--muted) 55%, transparent); }
|
|
344
372
|
.phase-bars i.done, .phase-bars i.now { background: var(--bar-fill); }
|
|
345
373
|
/* A bar part way, to --p: a starting board's clone (ui-sidebar.js). */
|
|
346
374
|
.phase-bars i.fill { background: linear-gradient(to right, var(--bar-fill) var(--p), var(--line) var(--p)); }
|
|
347
|
-
|
|
348
|
-
@
|
|
375
|
+
/* The pulse dims the bar's own fill, so it pulses in its lane's colour. */
|
|
376
|
+
@keyframes pulse-fill { 50% { background-color: color-mix(in srgb, var(--bar-fill) 35%, transparent); } }
|
|
377
|
+
/* Every pulse beats on one clock (ui-progress-bar.js onePulse), so a card's running bar and its status dot blink together. */
|
|
378
|
+
@media (prefers-reduced-motion: no-preference) { .phase-bars i.now { animation: pulse-fill 1.4s ease-in-out infinite; } }
|
|
349
379
|
/* A stale build's status line, dot included, is the needs-you red, and a tap on it nudges Claude (ui-cards.js builderStatus). */
|
|
350
380
|
/* A status line that is a button is drawn as the div it replaces: this one reset, then only a colour per state. The font
|
|
351
|
-
shorthand stays out so .sub's 12px wins.
|
|
352
|
-
|
|
381
|
+
shorthand stays out so .sub's 12px wins. It sets no width: a button is its own block formatting context, so a full-width one
|
|
382
|
+
drops below the bump icons' float instead of sitting beside it as the div's line box does (board/layout.test.mjs). */
|
|
383
|
+
button.sub { display: block; margin-inline: 0; margin-bottom: 0; padding: 0; min-height: 0; border: 0; border-radius: 0; background: none;
|
|
353
384
|
font-family: inherit; font-weight: inherit; letter-spacing: inherit; line-height: inherit; text-align: left; appearance: none; -webkit-appearance: none; }
|
|
354
385
|
button.sub.agent.stalled { color: var(--color-danger); }
|
|
386
|
+
/* A tap on it calms the line to the in-progress orange, its dot sending a ripple, until the card's next status line (app-cards.js nudge). */
|
|
387
|
+
button.sub.agent.stalled.nudging { color: var(--color-notice); cursor: default; }
|
|
388
|
+
.nudging .working-dot { position: relative; }
|
|
389
|
+
.nudging .working-dot::after { content: ''; position: absolute; inset: -1px; border-radius: 50%; border: 1.5px solid currentColor; opacity: 0; }
|
|
390
|
+
@keyframes nudge-ping { from { transform: scale(1); opacity: .9; } to { transform: scale(2.6); opacity: 0; } }
|
|
391
|
+
@media (prefers-reduced-motion: no-preference) { .nudging .working-dot::after { animation: nudge-ping 1.1s ease-out infinite; } }
|
|
355
392
|
.stalled .working-dot { background: currentColor; }
|
|
356
393
|
.brand { display: grid; grid-template-columns: auto auto minmax(0, 1fr); column-gap: 10px; row-gap: 2px; }
|
|
357
394
|
.brand .hub { grid-row: 1 / span 2; align-self: center; }
|
|
@@ -365,23 +402,33 @@ button.sub.agent.stalled { color: var(--color-danger); }
|
|
|
365
402
|
.msg.agent { padding: 0 10px; margin: 4px 0; font-size: 12px; font-weight: 600; overflow-wrap: anywhere; }
|
|
366
403
|
.msg.agent.started { color: var(--color-notice); } .msg.agent.finished { color: var(--color-success); }
|
|
367
404
|
.msg.agent .muted { font-weight: 400; }
|
|
368
|
-
/* A planner's line, dot included, is the owner's blue
|
|
369
|
-
(docs/adr/2026-11-03-1551-planners-and-implementers-are-two-kinds-of-agent.md). */
|
|
370
|
-
.
|
|
405
|
+
/* A planner's line in the thread, dot included, is the owner's blue; its finish stays green
|
|
406
|
+
(docs/adr/2026-11-03-1551-planners-and-implementers-are-two-kinds-of-agent.md). On the card it takes the lane's colour below. */
|
|
407
|
+
.msg.builder-status.planner, .msg.agent.started.planner { color: var(--accent); }
|
|
371
408
|
.planner .working-dot { background: currentColor; }
|
|
372
|
-
/*
|
|
373
|
-
|
|
374
|
-
(docs/adr/2026-11-
|
|
409
|
+
/* A run's status line, dot included, takes its card's lane colour, a planner's too: grey in Todo, the phase-bar orange in
|
|
410
|
+
In Progress, blue in In Review; a Todo card's planner dashes are its grey, the running one pulsing
|
|
411
|
+
(docs/adr/2026-11-06-0145-every-run-takes-its-lanes-colour.md). */
|
|
412
|
+
.sub.agent.in-todo { color: var(--muted); }
|
|
375
413
|
.sub.agent.in-progress { color: var(--color-notice); }
|
|
376
|
-
.sub.agent.in-
|
|
377
|
-
.sub.agent.in-progress .working-dot, .sub.agent.in-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
414
|
+
.sub.agent.in-review { color: var(--color-info); }
|
|
415
|
+
.sub.agent.in-todo .working-dot, .sub.agent.in-progress .working-dot, .sub.agent.in-review .working-dot { background: currentColor; }
|
|
416
|
+
/* docs/adr/2026-11-05-0410-a-card-status-word-comes-from-a-signal-the-board-checks.md: a quiet builder and a request no planner
|
|
417
|
+
has picked up are grey, after the lane colours so they win. */
|
|
418
|
+
.sub.agent.quiet, .sub.asked { color: var(--muted); }
|
|
419
|
+
.sub.agent.waiting-gray { color: var(--muted); }
|
|
420
|
+
/* The one class every paused status takes, gray: the card and thread line, the header, the hub banner. */
|
|
421
|
+
.paused { color: var(--muted); font-weight: 600; }
|
|
422
|
+
.phase-bars.in-todo { --bar-fill: var(--muted); }
|
|
381
423
|
.msg.calls { padding: 0 10px; margin: 4px 0; font-size: 12px; overflow-wrap: anywhere; }
|
|
382
424
|
.msg.calls summary { cursor: pointer; color: var(--muted); list-style: none; }
|
|
383
425
|
.msg.calls summary::-webkit-details-marker { display: none; }
|
|
384
426
|
.msg.calls[open] summary .mark-icon { transform: rotate(90deg); }
|
|
427
|
+
.msg.calls.status-fold summary { color: var(--color-notice); overflow-wrap: anywhere; }
|
|
428
|
+
.msg.calls.status-fold.planner summary { color: var(--accent); }
|
|
429
|
+
/* Only a run's finished line is green: the fold's summary mirrors its last line, green once the run has finished, else the
|
|
430
|
+
started and status lines' orange or a planner's blue (docs/adr/2026-11-07-1600-only-a-runs-finished-line-is-green.md). */
|
|
431
|
+
.msg.calls.status-fold summary.finished { color: var(--color-success); }
|
|
385
432
|
.msg.calls ol { margin: 4px 0; padding-left: 23px; }
|
|
386
433
|
.agent-dot { display: inline-block; width: 7px; height: 7px; border-radius: 50%; background: currentColor; margin-right: 5px; vertical-align: 1px; }
|
|
387
434
|
/* Every thread status line's leading mark, icon or dot, sits centred in one 18px box, so the text after it always starts
|
|
@@ -398,10 +445,7 @@ button.sub.agent.stalled { color: var(--color-danger); }
|
|
|
398
445
|
.msg .reply { display: flex; flex-wrap: wrap; align-items: center; column-gap: 12px; row-gap: 2px; }
|
|
399
446
|
.msg-foot .foot-status { display: inline-flex; align-items: center; }
|
|
400
447
|
/* The thread's eye and fire are toggles: pressed reads as chosen, and the hint under the box says what Send posts. */
|
|
401
|
-
form[data-reply] .tools { display: inline-flex; flex: none; }
|
|
402
448
|
button.attach[aria-pressed="true"] { color: var(--accent); background: var(--chip); }
|
|
403
|
-
.flag-hint { margin: 4px 2px 0; min-height: 1.2em; color: var(--muted); font-size: 12px; }
|
|
404
|
-
.flag-hint.on { color: var(--accent); }
|
|
405
449
|
/* INT-30: card line order */
|
|
406
450
|
.line6 { margin-top: 4px; }
|
|
407
451
|
.card-time time { font-variant-numeric: tabular-nums; }
|
|
@@ -418,10 +462,25 @@ button.attach[aria-pressed="true"] { color: var(--accent); background: var(--chi
|
|
|
418
462
|
.lane[open] > .list { border-radius: 0 0 10px 10px; }
|
|
419
463
|
.lane > summary .count { color: var(--muted); font-weight: 400; }
|
|
420
464
|
/* Each lane's sort icon and its menu, grey (docs/adr/2026-11-01-1817-colour-says-whos-waiting.md) */
|
|
421
|
-
/*
|
|
422
|
-
.view
|
|
423
|
-
|
|
424
|
-
|
|
465
|
+
/* A board shared with someone else (docs/adr/2026-11-05-2215-a-board-is-shared-view-only-with-a-tailscale-login.md):
|
|
466
|
+
shell.js marks the page .shared-view, which hides Board settings and the architecture review, and, unless the person
|
|
467
|
+
has Full on this board (.shared-full; docs/adr/2026-11-05-1912-a-shared-person-is-view-or-full.md), the +, every
|
|
468
|
+
composer and a card's buttons, keeping its links (Visit, Notes, Open questions). Merge shows disabled under Full. */
|
|
469
|
+
.shared-view :is(#settingsLink, #archBulb) { display: none !important; }
|
|
470
|
+
.shared-view:not(.shared-full) :is(#compose, [data-composer], .actions button, button[data-confirm]) { display: none !important; }
|
|
471
|
+
.shared-full button[data-confirm="merge"] { opacity: .45; pointer-events: none; }
|
|
472
|
+
.view-only-strip { margin: 8px 0; padding: 8px 12px; border-radius: 10px; background: var(--accent-soft); font-size: 13px; }
|
|
473
|
+
.view-only-strip b { color: var(--accent); }
|
|
474
|
+
/* A board out of reach (docs/adr/2026-11-06-0135-a-board-out-of-reach-keeps-its-copy-or-shows-a-landing.md): it reads as before,
|
|
475
|
+
undimmed, and only the buttons that send, ui.js SENDS, are held, the labelled ones saying why; app-header.js stops their taps. */
|
|
476
|
+
.offline :is(form button[type="submit"], .actions button, button[data-confirm], button[data-deck-pick], button[data-review-answer], button[data-prompt-send], button[data-prompt-choice], button[data-quick], button[data-card-bump], button[data-bump], button[data-withdraw], button[data-band-move], button[data-grill], button[data-proto], button[data-visual], button[data-plan], button[data-main-pull], button[data-arch-run], button[data-try], button[data-reopen]) { opacity: .55; cursor: not-allowed; }
|
|
477
|
+
/* With no copy to show, the landing takes the board's place: the kickflip mark and two lines, as hub/front-door.mjs's page has them. */
|
|
478
|
+
.down-landing { min-height: 60vh; display: grid; place-content: center; justify-items: center; gap: 10px; padding: 32px 24px; text-align: center; }
|
|
479
|
+
.down-landing-mark { display: block; margin-bottom: 8px; width: 70px; height: 60px; object-fit: contain; }
|
|
480
|
+
.down-landing-line { margin: 0; font-size: 20px; font-weight: 600; line-height: 1.3; text-wrap: balance; }
|
|
481
|
+
.down-landing-hint { margin: 0; font-size: 14px; color: var(--muted); }
|
|
482
|
+
.view-board.down main > :not(#downLanding), .view-board.down :is(#needsPane, #compose) { display: none; }
|
|
483
|
+
.view-settings.down .settings-body > :not(.down-landing) { display: none; }
|
|
425
484
|
/* INT-28: answer banner */
|
|
426
485
|
.answer-banner { display: flex; align-items: center; gap: 4px; background: var(--accent-soft); border: 1px solid color-mix(in srgb, var(--accent) 30%, transparent);
|
|
427
486
|
border-radius: 10px; padding: 2px 4px 2px 0; margin-bottom: 12px; }
|
|
@@ -467,11 +526,21 @@ button.attach[aria-pressed="true"] { color: var(--accent); background: var(--chi
|
|
|
467
526
|
.top .nav #refresh, .top .nav a.icon { display: inline-flex; align-items: center; justify-content: center; margin: 0; padding: 4px; border: 0; line-height: 1; }
|
|
468
527
|
.top .nav #status { line-height: 1.1; white-space: nowrap; }
|
|
469
528
|
.top .nav #refresh:disabled, .top .nav a.icon[aria-disabled="true"] { opacity: .35; pointer-events: none; }
|
|
470
|
-
/*
|
|
471
|
-
|
|
472
|
-
.
|
|
473
|
-
.
|
|
474
|
-
.
|
|
529
|
+
/* The foot of the board (docs/adr/2026-11-07-1300-board-and-open-questions-are-two-pages.md): the bulb and the gear, centred under the lanes.
|
|
530
|
+
[the bulb runs an architecture review of the board's repo](docs/adr/2026-11-02-1813-the-bulb-runs-an-architecture-review-of-the-boards-repo.md): it glows orange while an architecture review runs */
|
|
531
|
+
.board-foot { display: flex; justify-content: center; gap: 8px; margin: 20px 0 0; }
|
|
532
|
+
.board-foot .arch-bulb, .board-foot a.icon { display: inline-flex; align-items: center; justify-content: center; min-width: 44px; min-height: 44px; margin: 0; padding: 4px; border: 0; line-height: 1; color: var(--muted); }
|
|
533
|
+
.board-foot :is(.arch-bulb, a.icon):hover { color: var(--text); }
|
|
534
|
+
.board-foot .arch-bulb[hidden] { display: none; }
|
|
535
|
+
.board-foot .arch-bulb.running { color: var(--color-notice); }
|
|
536
|
+
.board-foot a.icon[aria-disabled="true"] { opacity: .35; pointer-events: none; }
|
|
537
|
+
/* The pages switch below 900px: the board header's ? with the open-question count on its corner, and Waiting on you's check back to the board. */
|
|
538
|
+
.top .pages-switch { position: relative; display: inline-flex; align-items: center; justify-content: center; flex: none; width: auto; height: auto; margin: 0; padding: 4px; border: 0; border-radius: 0; line-height: 1; color: var(--muted); }
|
|
539
|
+
.top .pages-switch:hover { color: var(--text); }
|
|
540
|
+
.top .pages-switch:active { background: none; }
|
|
541
|
+
.pages-switch .q-badge { position: absolute; top: 0; right: -2px; min-width: 16px; height: 16px; padding: 0 4px; border-radius: 999px; background: var(--color-notice); color: #1c1407;
|
|
542
|
+
font-size: 11px; font-weight: 700; line-height: 16px; text-align: center; box-shadow: 0 0 0 1.5px var(--bg); }
|
|
543
|
+
.pages-switch .q-badge[hidden] { display: none; }
|
|
475
544
|
.arch-bulb.running svg { filter: drop-shadow(0 0 4px currentColor); }
|
|
476
545
|
@media (prefers-reduced-motion: no-preference) { .arch-bulb.running svg { animation: arch-glow 1.4s ease-in-out infinite; } }
|
|
477
546
|
@keyframes arch-glow { 50% { filter: drop-shadow(0 0 1px currentColor); opacity: .55; } }
|
|
@@ -481,8 +550,6 @@ button.attach[aria-pressed="true"] { color: var(--accent); background: var(--chi
|
|
|
481
550
|
.arch-last .muted { font-size: 12.5px; }
|
|
482
551
|
.arch-body .arch-waits { color: var(--color-notice); }
|
|
483
552
|
.arch-body .arch-run { width: 100%; min-height: 44px; font-size: 15px; }
|
|
484
|
-
/* INT-64: offline, the header's time and refresh turn red */
|
|
485
|
-
.view-board.offline .refresh #refresh, .refresh .link-state.offline { color: var(--color-danger); }
|
|
486
553
|
.back { display: inline-flex; align-items: center; justify-content: center; flex: none; width: 32px; height: 32px; color: var(--accent); text-decoration: none; }
|
|
487
554
|
/* The lead slot, logo or back, is one 44px tap box on the page's left edge, so every page's header lines up the same
|
|
488
555
|
(docs/adr/2026-10-29-1639-a-questions-takes-show-inline.md). The brand keeps that height when the rail hides the logo, so the
|
|
@@ -493,15 +560,10 @@ button.attach[aria-pressed="true"] { color: var(--accent); background: var(--chi
|
|
|
493
560
|
.top .hub + .back { margin-left: 0; }
|
|
494
561
|
.top .back:active { background: var(--accent-soft); }
|
|
495
562
|
.top .brand :is(h1, h2) { font-size: 17px; font-weight: 600; line-height: 22px; }
|
|
496
|
-
/*
|
|
497
|
-
|
|
498
|
-
a blue tint that fades (app-snapshot.js, whose SIGNS holds each animation's length). */
|
|
563
|
+
/* Every change, a line, a moved card or an updated card, open body included, takes the one blue tint that fades
|
|
564
|
+
(app-snapshot.js highlight, whose TINT_MS is its length). */
|
|
499
565
|
main > * { transition: opacity .25s ease; }
|
|
500
|
-
.
|
|
501
|
-
.view-board[data-board="snapshot"] :is(.actions button, button[data-plan], button[data-bump], button[data-confirm="bump"], button[data-edit], button[data-withdraw], button[data-check-github], form[data-reply] button[type=submit], form[data-reply] button[data-quick], form[data-reply] button[data-proto], form[data-reply] button[data-confirm], .prompt button) { opacity: .45; pointer-events: none; }
|
|
502
|
-
.flash { animation: snapshot-flash 1.6s ease-out var(--sign-delay, 0s) 1; border-radius: 6px; }
|
|
503
|
-
@keyframes snapshot-flash { from { box-shadow: inset 0 0 0 2px var(--color-info); } to { box-shadow: inset 0 0 0 2px transparent; } }
|
|
504
|
-
.item.tint { animation: card-tint 2.4s ease-out var(--sign-delay, 0s) 1; border-radius: 6px; }
|
|
566
|
+
.tint { animation: card-tint 2.4s ease-out var(--sign-delay, 0s) 1; border-radius: 6px; }
|
|
505
567
|
@keyframes card-tint { 0%, 25% { background: var(--accent-soft); } 100% { background: transparent; } }
|
|
506
568
|
.msg .quote { margin: 4px 0 6px; padding: 2px 0 2px 8px; border-left: 2px solid var(--line); color: var(--muted); white-space: pre-wrap; overflow-wrap: anywhere; }
|
|
507
569
|
/* [one board registry for every hub feature](docs/adr/2026-10-29-1639-one-board-registry-for-every-hub-feature.md): the GitHub mark opens the Hub links sheet, with a red dot while a link is broken; a new board's setup checklist */
|
|
@@ -530,11 +592,26 @@ main > * { transition: opacity .25s ease; }
|
|
|
530
592
|
.view-settings .who.new { border-color: var(--accent); }
|
|
531
593
|
.view-settings .add { display: flex; gap: 6px; margin-top: 8px; }
|
|
532
594
|
.view-settings .add input { flex: 1; min-width: 0; }
|
|
595
|
+
.view-settings .add.pick { flex-wrap: wrap; }
|
|
596
|
+
.view-settings .share-now { color: var(--ok); font-weight: 600; }
|
|
597
|
+
.view-settings .share-level { display: flex; gap: 4px; margin-top: 6px; }
|
|
598
|
+
.view-settings .share-level button { min-height: 32px; padding: 4px 12px; font-size: 13px; }
|
|
599
|
+
.view-settings .share-level button[aria-pressed="true"] { border-color: var(--accent); background: var(--accent-soft); color: var(--accent); font-weight: 600; }
|
|
600
|
+
.view-settings .share-now::before { content: ""; display: inline-block; width: 7px; height: 7px; margin-right: 5px; border-radius: 50%; background: currentColor; vertical-align: 1px; }
|
|
601
|
+
.view-settings .share-reach { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: 10px 0 4px; }
|
|
602
|
+
.view-settings .share-reach p { flex: 1 1 220px; margin: 0; }
|
|
603
|
+
.view-settings .share-reach button { flex: none; }
|
|
604
|
+
.view-settings .pick-col { flex: 1 1 140px; min-width: 0; display: flex; flex-direction: column; gap: 6px; }
|
|
605
|
+
.view-settings .pick-list { max-height: 160px; overflow-y: auto; display: flex; flex-direction: column; gap: 4px; }
|
|
606
|
+
.view-settings .pick-list button { text-align: left; }
|
|
607
|
+
.view-settings .pick-list button[aria-pressed="true"] { border-color: var(--accent); }
|
|
608
|
+
.view-settings .who .sub { display: block; margin-top: 2px; }
|
|
533
609
|
.view-settings .replies .reply { margin-top: 8px; }
|
|
534
610
|
.view-settings label.who { gap: 12px; cursor: pointer; }
|
|
535
611
|
.view-settings label.who .sub { display: block; margin-top: 2px; }
|
|
536
612
|
.view-settings input.toggle { flex: none; width: 1.4rem; height: 1.4rem; margin: 0; accent-color: var(--accent); }
|
|
537
613
|
.view-settings input.count { flex: none; width: 4.5em; text-align: center; }
|
|
614
|
+
.view-settings label.who select { flex: none; max-width: 45%; min-height: 36px; }
|
|
538
615
|
/* A settings switch waiting on the server (ui.js waitOn) keeps its face, disabled, with a spinner beside it
|
|
539
616
|
(docs/adr/2026-11-03-1921-board-settings-grant-a-boards-session-permissions.md) */
|
|
540
617
|
.view-settings .toggle-slot { flex: none; display: inline-flex; align-items: center; gap: 8px; }
|
|
@@ -555,6 +632,14 @@ main > * { transition: opacity .25s ease; }
|
|
|
555
632
|
.view-settings .close-board-warning:has(li) { border: 1px solid var(--color-danger); padding: 0 12px; border-radius: 10px; margin-bottom: 14px; }
|
|
556
633
|
.view-questions .q { background: var(--panel); border: 1px solid var(--line); border-radius: 12px; padding: 12px; margin: 12px 0; }
|
|
557
634
|
.view-questions .q.urgent { border-color: var(--color-notice); }
|
|
635
|
+
/* docs/adr/2026-11-05-2331-a-sent-answer-is-resolved-in-place-until-the-page-reloads.md
|
|
636
|
+
A requested question takes an accent tint and a sent or resolved one a green tint, each with its border drawn inside
|
|
637
|
+
the card as well, so the card keeps its size. */
|
|
638
|
+
.view-questions .q.pr-busy { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 9%, var(--panel)); box-shadow: inset 0 0 0 1px var(--accent); }
|
|
639
|
+
.view-questions .q.pr-busy .opt { opacity: .55; cursor: default; }
|
|
640
|
+
.view-questions .q.pr-busy .opt:has(input:checked) { opacity: 1; }
|
|
641
|
+
.view-questions .q.resolved { border-color: var(--color-success); background: color-mix(in srgb, var(--color-success) 9%, var(--panel)); box-shadow: inset 0 0 0 1px var(--color-success); }
|
|
642
|
+
.view-questions .q.resolved .sent-line { margin: 6px 0; font-size: 13px; color: var(--color-success); }
|
|
558
643
|
.view-questions .q h3 { font-size: 15px; margin: 6px 0 4px; line-height: 1.3; }
|
|
559
644
|
.view-questions .ctx { color: var(--muted); font-size: 13px; margin-bottom: 8px; }
|
|
560
645
|
.view-questions .opt { display: grid; grid-template-columns: 22px 1fr; gap: 6px; padding: 8px; border: 1px solid var(--line);
|
|
@@ -576,18 +661,17 @@ main > * { transition: opacity .25s ease; }
|
|
|
576
661
|
.view-questions .topics button { min-width: 0; border: 1px solid var(--line); border-radius: 999px; padding: 4px 11px; font-size: 13px;
|
|
577
662
|
background: var(--panel); color: var(--text); white-space: normal; text-align: left; overflow-wrap: anywhere; }
|
|
578
663
|
.view-questions .topics button[aria-pressed="true"] { border-color: var(--accent); background: var(--accent-soft); }
|
|
664
|
+
.view-questions .topics button.progress { border-color: var(--line); background: color-mix(in srgb, var(--color-notice) 12%, var(--panel)); }
|
|
665
|
+
.view-questions .topics button.progress[aria-pressed="true"] { border-color: var(--accent); background: color-mix(in srgb, var(--color-notice) 12%, var(--accent-soft)); }
|
|
666
|
+
@keyframes pill-arrive { from { opacity: 0; transform: translateX(-12px); box-shadow: 0 0 0 3px var(--accent); } to { opacity: 1; transform: none; box-shadow: 0 0 0 0 transparent; } }
|
|
667
|
+
@media (prefers-reduced-motion: no-preference) { .view-questions .topics button.arrived { animation: pill-arrive .6s ease-out; } }
|
|
579
668
|
.view-questions .topics .n { color: var(--muted); margin-left: 4px; }
|
|
580
669
|
.view-questions .topichead { margin: 2px 0 6px; }
|
|
581
670
|
.view-questions details.done > summary { cursor: pointer; color: var(--muted); font-size: 13px; margin: 16px 0 4px; }
|
|
582
|
-
.view-questions details.done .trow { display: flex; justify-content: space-between; align-items: center; gap: 8px; }
|
|
583
|
-
.view-questions details.done button.ghost { font-size: 14px; text-align: left; padding: 6px 2px; }
|
|
584
|
-
.view-questions details.done .trow button { min-width: 0; }
|
|
585
|
-
.view-questions details.done .trow span { flex: none; }
|
|
586
671
|
.view-questions details.resolved-group > summary { list-style: none; min-height: 44px; display: flex; align-items: center; gap: 8px; font-size: 14px; margin: 12px 0; }
|
|
587
672
|
.view-questions details.resolved-group > summary::-webkit-details-marker { display: none; }
|
|
588
673
|
.view-questions details.resolved-group > summary .caret { transition: transform .15s; }
|
|
589
674
|
.view-questions details.resolved-group[open] > summary .caret { transform: rotate(90deg); }
|
|
590
|
-
.view-questions details.resolved-group > summary .names { font-size: 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
|
|
591
675
|
.view-questions .q.resolved button.chip { cursor: pointer; font: inherit; font-size: 12px; min-height: 28px; }
|
|
592
676
|
.view-questions .q.resolved button.chip:disabled { cursor: default; }
|
|
593
677
|
.view-questions .q.resolved .resolved-line { margin: 8px 0; }
|
|
@@ -600,39 +684,26 @@ main > * { transition: opacity .25s ease; }
|
|
|
600
684
|
display: flex; justify-content: space-between; align-items: center; gap: 8px; border-top: 1px solid var(--line); }
|
|
601
685
|
.view-questions .bar .send-hint { margin-left: auto; }
|
|
602
686
|
/* The + rides above the sticky Send bar rather than over its Send. */
|
|
603
|
-
.view-questions:has(.bar) .fab { bottom: calc(var(--app-bottom, 0px) + var(--fab-edge) + 72px); }
|
|
604
687
|
.view-questions .bar #qstatus { min-width: 0; }
|
|
605
688
|
.view-questions .bar #qstatus.sent { color: var(--color-success); font-weight: 600; }
|
|
689
|
+
/* With no open question, the moon and its line sit at the centre of what the page shows between its top and the nav,
|
|
690
|
+
or of what the desktop pane has left under its Needs you lines. */
|
|
691
|
+
.view-questions .q-empty { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px; color: var(--muted); text-align: center;
|
|
692
|
+
min-height: calc(var(--vh, 100dvh) - var(--app-bottom, 0px) - max(16px, env(safe-area-inset-top))); }
|
|
693
|
+
.view-questions .q-empty p { margin: 0; font-size: 15px; }
|
|
606
694
|
.view-questions .solo { display: flex; justify-content: space-between; align-items: center; gap: 8px; margin: 4px 0; }
|
|
607
695
|
/* docs/adr/2026-11-02-1332-a-prototype-round-ends-with-a-one-take-confirm.md */
|
|
608
696
|
.view-questions .topichead { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; }
|
|
609
697
|
.view-questions .topichead .try-spin { width: 9px; height: 9px; margin-right: 5px; vertical-align: -1px; }
|
|
610
|
-
.view-questions .q .pr-open { display: inline-block; margin: 0 0 8px; }
|
|
611
698
|
.view-questions .pr-rule { display: flex; align-items: center; gap: 6px; margin: 0 0 6px; font-size: 12.5px; color: var(--muted); }
|
|
612
699
|
.view-questions .pr-rule svg { flex: none; }
|
|
613
700
|
|
|
614
|
-
/* A question's takes sit in as many columns as keep each at least 380px wide, one on a phone; each its option above
|
|
615
|
-
|
|
701
|
+
/* A question's drawn takes sit in as many columns as keep each at least 380px wide, one on a phone; each its option above
|
|
702
|
+
its diagram, and each row's takes top-aligned. */
|
|
616
703
|
.view-questions .takes { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 380px), 1fr)); gap: 10px; align-items: start; margin: 6px 0; }
|
|
617
704
|
.view-questions .take { min-width: 0; border: 1px solid var(--line); border-radius: 12px; background: var(--bg); padding: 10px; }
|
|
618
705
|
.view-questions .take:has(input:checked) { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
|
|
619
706
|
.view-questions .take .opt, .view-questions .take .opt:has(input:checked) { border: 0; padding: 0; margin: 0; background: none; }
|
|
620
|
-
/* view-questions.js sets a frame's height to its page's once measured; until then it shows nothing, so a take that turns
|
|
621
|
-
its question into the full-width layout never flashes cut off. */
|
|
622
|
-
.view-questions .take-shot { position: relative; display: block; margin-top: 8px; height: 360px; border: 1px solid var(--line); border-radius: 10px;
|
|
623
|
-
overflow: hidden; transition: height .15s ease; }
|
|
624
|
-
.view-questions .take-shot iframe { width: 100%; height: 100%; border: 0; background: var(--bg); }
|
|
625
|
-
.view-questions .take-shot.measuring { transition: none; }
|
|
626
|
-
.view-questions .take-shot.measuring iframe { visibility: hidden; }
|
|
627
|
-
.view-questions .take-shot.measuring::before { content: 'Loading take…'; position: absolute; inset: 0; display: grid; place-items: center;
|
|
628
|
-
color: var(--muted); font-size: 12.5px; }
|
|
629
|
-
.view-questions:has(.takes-full) main { max-width: none; }
|
|
630
|
-
.view-questions .takes-full { grid-template-columns: minmax(0, 1fr); }
|
|
631
|
-
.view-questions .take-choices { display: flex; flex-wrap: wrap; gap: 8px; }
|
|
632
|
-
.view-questions .take-choices .opt { flex: 1 1 160px; margin: 0; }
|
|
633
|
-
.view-questions .take-choices .opt[aria-current="true"] { border-color: var(--accent); }
|
|
634
|
-
.view-questions .takes-full .take { padding: 0; border: 0; }
|
|
635
|
-
.view-questions .takes-full .take-shot { margin-top: 0; transition: none; }
|
|
636
707
|
|
|
637
708
|
/* A take with nothing to see: boxes and arrows, then what it means in practice. */
|
|
638
709
|
.view-questions .flow { margin: 10px 0 4px; }
|
|
@@ -683,15 +754,15 @@ main > * { transition: opacity .25s ease; }
|
|
|
683
754
|
.view-frame .alone { white-space: nowrap; font-size: 13px; }
|
|
684
755
|
|
|
685
756
|
@media (max-width: 899px) {
|
|
686
|
-
:root:has(body > .top, body.has-sidebar > :not(.sidebar) > .top)
|
|
757
|
+
:root:has(body > .top, body.has-sidebar > :not(.sidebar) > .top) {
|
|
687
758
|
--app-bottom: calc(49px + max(4px, env(safe-area-inset-bottom)));
|
|
688
759
|
}
|
|
689
760
|
body > .top, body.has-sidebar > :not(.sidebar) > .top {
|
|
690
761
|
position: fixed; top: auto; bottom: 0; left: 0; right: 0; z-index: 7;
|
|
691
762
|
border-bottom: 0; border-top: 1px solid var(--line); padding-top: 4px; padding-bottom: max(4px, env(safe-area-inset-bottom));
|
|
692
763
|
}
|
|
693
|
-
.top .nav #refresh, .top .nav a.icon, .top .
|
|
694
|
-
body > main, body.has-sidebar > :not(.sidebar) > main { padding-top: max(16px, env(safe-area-inset-top)); padding-bottom: calc(96px + var(--app-bottom, 0px) + env(safe-area-inset-bottom)); }
|
|
764
|
+
.top .nav #refresh, .top .nav a.icon, .top .pages-switch { min-width: 44px; min-height: 44px; }
|
|
765
|
+
body > main, body.has-sidebar > :not(.sidebar) > main, body.has-sidebar > :not(.sidebar) > .split > main { padding-top: max(16px, env(safe-area-inset-top)); padding-bottom: calc(96px + var(--app-bottom, 0px) + env(safe-area-inset-bottom)); }
|
|
695
766
|
.view-frame:not(.own-header) { padding-bottom: var(--app-bottom, 0px); }
|
|
696
767
|
.sheet { bottom: max(0px, calc(var(--app-bottom, 0px) - var(--kb, 0px)));
|
|
697
768
|
max-height: calc(var(--vh, 100dvh) + var(--kb, 0px) - max(var(--app-bottom, 0px), var(--kb, 0px)) - env(safe-area-inset-top) - 12px); }
|
|
@@ -699,6 +770,9 @@ main > * { transition: opacity .25s ease; }
|
|
|
699
770
|
.sheet.keyboard-sheet { --sheet-limit: max(80px, calc(var(--vh, 100dvh) + var(--kb, 0px) - max(0px, calc(var(--app-bottom, 0px) - var(--kb, 0px))) - max(12px, env(safe-area-inset-top)))); }
|
|
700
771
|
}
|
|
701
772
|
|
|
773
|
+
/* Typing, a text field focused (shell.js sets :root.typing): the floating + is disabled and the page stays as it is. */
|
|
774
|
+
:root.typing .fab { opacity: .35; pointer-events: none; }
|
|
775
|
+
|
|
702
776
|
.settings-modal { position: fixed; inset: max(12px, env(safe-area-inset-top)) 0 calc(12px + max(var(--kb, 0px), var(--app-bottom, 0px))); margin: auto; width: min(680px, calc(100% - 24px));
|
|
703
777
|
height: fit-content; max-width: none; max-height: max(120px, calc(var(--vh, 100dvh) - max(0px, calc(var(--app-bottom, 0px) - var(--kb, 0px))) - 24px - env(safe-area-inset-top)));
|
|
704
778
|
padding: 0; border: 1px solid var(--line); border-radius: 18px; background: var(--panel); color: var(--text);
|
|
@@ -716,21 +790,18 @@ main > * { transition: opacity .25s ease; }
|
|
|
716
790
|
.lk-over, .lk-over > main { display: contents; }
|
|
717
791
|
|
|
718
792
|
.tk-section { margin: 10px 0; }
|
|
719
|
-
/* The Tickets source row's live state
|
|
793
|
+
/* The Tickets source row's live state (dialogs.js ticketsControl keyState). */
|
|
720
794
|
.tk-status { display: flex; align-items: center; gap: 8px; margin: 8px 0 0; font-size: 13px; color: var(--muted); }
|
|
721
795
|
.tk-status b { font-weight: 600; color: var(--text); }
|
|
722
796
|
.tk-status .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--line); flex: none; }
|
|
723
797
|
.tk-status.on .dot { background: var(--accent); }
|
|
724
798
|
.tk-status.on b { color: var(--accent); }
|
|
725
|
-
.tk-inline { margin: 6px 0 10px; border: 1px solid var(--accent); border-radius: 10px; padding: 8px 10px; background: var(--accent-soft); }
|
|
726
|
-
.tk-inline .tk-ask { margin: 2px 0 6px; font-size: 13px; }
|
|
727
|
-
.tk-inline .hub-view main { padding: 0; }
|
|
728
799
|
.tk-seg { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 4px; padding: 4px; margin: 8px 0; border: 1px solid var(--line); border-radius: 9px; background: var(--chip); }
|
|
729
800
|
.tk-seg button { min-width: 0; min-height: 44px; padding: 6px 4px; border: 1px solid transparent; border-radius: 6px; background: transparent; color: var(--muted); font: inherit; font-size: 13px; cursor: pointer; }
|
|
730
801
|
.tk-seg button[aria-pressed="true"] { border-color: var(--accent); background: var(--accent-soft); color: var(--accent); font-weight: 600; }
|
|
731
|
-
.ask-seg { grid-template-columns: repeat(2, minmax(0, 1fr)); margin: 10px 0 0; }
|
|
732
|
-
.ask-choice-help { margin: 4px 2px 0; }
|
|
733
802
|
.tk-seg button:focus-visible { outline: 2px solid var(--accent); outline-offset: -3px; }
|
|
803
|
+
.landing-seg button { display: flex; flex-direction: column; align-items: center; gap: 4px; padding: 8px 6px; text-align: center; }
|
|
804
|
+
.landing-seg .sub { font-weight: 400; opacity: .8; line-height: 1.25; }
|
|
734
805
|
.tk-grid { display: grid; gap: 8px; grid-template-columns: minmax(0, 1fr); }
|
|
735
806
|
@media (min-width: 560px) { .tk-grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr); } }
|
|
736
807
|
.tk-field { display: block; min-width: 0; }
|
|
@@ -844,3 +915,54 @@ button[aria-busy="true"]:is([data-card-bump], [data-bump]) svg { fill: currentCo
|
|
|
844
915
|
.rv-links a { color: var(--accent); text-decoration: none; }
|
|
845
916
|
.rv-acts { display: flex; flex-wrap: wrap; gap: 8px; }
|
|
846
917
|
.view-questions .bar #qstatus .try-spin { color: var(--accent); margin-right: 6px; }
|
|
918
|
+
|
|
919
|
+
/* Needs you (app-needs.js): a deck at the top of the board on a phone; from 900px a pane beside the lanes, its lines over
|
|
920
|
+
Waiting on you (docs/adr/2026-11-05-0408-needs-you-is-a-deck-on-a-phone-and-a-pane-on-a-desktop.md). */
|
|
921
|
+
.needs-pane { display: none; }
|
|
922
|
+
.needs-deck { margin: 0 0 12px; border: 1px solid color-mix(in srgb, var(--color-notice) 45%, var(--line)); border-radius: 14px;
|
|
923
|
+
background: color-mix(in srgb, var(--color-notice) 7%, var(--panel)); overflow: hidden; }
|
|
924
|
+
.deck-head { display: flex; align-items: center; gap: 8px; padding: 10px 14px 4px; }
|
|
925
|
+
.deck-head h2 { margin: 0; flex: 1; font-size: 12px; text-transform: uppercase; letter-spacing: .05em; color: var(--color-notice); }
|
|
926
|
+
.deck-n { min-width: 20px; padding: 1px 7px; border-radius: 999px; background: var(--color-notice); color: #1c1407; font-size: 12px; font-weight: 700; text-align: center; }
|
|
927
|
+
.deck-card { padding: 2px 14px 12px; min-width: 0; overflow-wrap: anywhere; }
|
|
928
|
+
.deck-what { margin: 0 0 2px; font-size: 12px; color: var(--muted); }
|
|
929
|
+
.deck-card h3 { margin: 0 0 4px; font-size: 15px; line-height: 1.3; }
|
|
930
|
+
.deck-card h3 a { color: inherit; text-decoration: none; }
|
|
931
|
+
.deck-card .ctx { margin: 0 0 10px; font-size: 13px; color: var(--muted); }
|
|
932
|
+
.deck-proto { margin: 0 0 10px; color: var(--accent); }
|
|
933
|
+
.deck-opts { display: flex; flex-direction: column; gap: 6px; }
|
|
934
|
+
.deck-opts button { text-align: left; border-radius: 10px; padding: 10px 12px; font-size: 14px; }
|
|
935
|
+
.deck-opts button.rec { border-color: var(--accent); }
|
|
936
|
+
.deck-opts .rec-word { color: var(--accent); font-weight: 500; font-size: 12px; margin-left: 4px; }
|
|
937
|
+
.deck-opts small { display: block; color: var(--muted); font-size: 12.5px; }
|
|
938
|
+
.deck-prompt { margin: 0; padding: 0; list-style: none; }
|
|
939
|
+
.deck-prompt li.prompt { padding: 8px 10px; background: var(--panel); border: 1px solid var(--line); border-radius: 8px; }
|
|
940
|
+
.deck-acts { display: flex; flex-wrap: wrap; gap: 8px; }
|
|
941
|
+
.deck-bar { display: flex; align-items: center; gap: 10px; padding: 0 14px 10px; }
|
|
942
|
+
.deck-dots { flex: 1; display: flex; flex-wrap: wrap; gap: 5px; }
|
|
943
|
+
.deck-dots i { width: 7px; height: 7px; border-radius: 50%; background: var(--line); }
|
|
944
|
+
.deck-dots i.on { background: var(--color-notice); }
|
|
945
|
+
.deck-bar button { border-radius: 999px; padding: 5px 12px; font-size: 13px; }
|
|
946
|
+
.deck-more { display: flex; align-items: center; justify-content: space-between; min-height: 46px; padding: 10px 14px; border-top: 1px solid color-mix(in srgb, var(--color-notice) 28%, var(--line));
|
|
947
|
+
background: color-mix(in srgb, var(--color-notice) 14%, var(--panel)); color: var(--text); font-weight: 600; font-size: 14px; text-decoration: none; }
|
|
948
|
+
.deck-more::after { content: '›'; color: var(--accent); font-size: 18px; }
|
|
949
|
+
.deck-more:hover { text-decoration: none; }
|
|
950
|
+
@media (min-width: 900px) {
|
|
951
|
+
.split { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); align-items: start; }
|
|
952
|
+
.split > main { max-width: none; margin: 0; }
|
|
953
|
+
.needs-deck { display: none; }
|
|
954
|
+
/* Waiting on you is the board's pane here, so neither page shows the switch to the other. */
|
|
955
|
+
.top .pages-switch { display: none; }
|
|
956
|
+
/* The board's + sits at the bottom right of the left pane: the pane ends at the middle of the space right of the sidebar. */
|
|
957
|
+
.view-board .fab { right: calc(50% - var(--sidebar-w, 0px) / 2 + var(--fab-edge)); }
|
|
958
|
+
body.has-sidebar { --sidebar-w: 272px; }
|
|
959
|
+
html.sb-collapsed body.has-sidebar { --sidebar-w: 0px; }
|
|
960
|
+
.needs-pane { display: block; position: sticky; top: 56px; height: calc(100vh - 56px); overflow-y: auto; overscroll-behavior: contain; padding: 12px 16px 0; border-left: 1px solid var(--line); }
|
|
961
|
+
.needs-pane .needs-questions main { padding: 0; max-width: none; }
|
|
962
|
+
.needs-pane:has(.q-empty), .needs-pane .needs-questions:has(.q-empty), .needs-pane .needs-questions:has(.q-empty) main, .needs-pane #page:has(.q-empty) { display: flex; flex-direction: column; }
|
|
963
|
+
.needs-pane .needs-questions:has(.q-empty), .needs-pane .needs-questions:has(.q-empty) main, .needs-pane #page:has(.q-empty), .needs-pane .q-empty { flex: 1; min-height: 0; }
|
|
964
|
+
.needs-pane .waiting { margin: 0 0 12px; }
|
|
965
|
+
}
|
|
966
|
+
/* The Send bar is the last thing on its page: only the phone nav under it is left clear, so its background runs to the edge. */
|
|
967
|
+
body .view-questions main { padding-bottom: var(--app-bottom, 0px); }
|
|
968
|
+
.msg.calls.status-fold summary .fold-log { margin-left: 6px; color: var(--accent); text-decoration: underline; }
|