clavarium 0.0.2 → 0.1.0-next.2
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/LICENSE +21 -0
- package/README.md +265 -6
- package/config/tools.json +172 -0
- package/deploy/appliance.sh +83 -0
- package/deploy/backup.sh +97 -0
- package/deploy/clavarium-host +720 -0
- package/deploy/clavarium.mjs +30 -0
- package/deploy/git-read +85 -0
- package/deploy/install.sh +659 -0
- package/deploy/move-to-mnt.sh +142 -0
- package/deploy/parley-archive.mjs +47 -0
- package/deploy/relay.sh +156 -0
- package/deploy/restore.sh +147 -0
- package/deploy/updater.mjs +600 -0
- package/npm-shrinkwrap.json +1951 -0
- package/package.json +53 -8
- package/server/alerts.mjs +83 -0
- package/server/answerer.mjs +326 -0
- package/server/api.mjs +458 -0
- package/server/bridge.mjs +271 -0
- package/server/capacity.mjs +220 -0
- package/server/conversations.mjs +895 -0
- package/server/dataformat.mjs +59 -0
- package/server/devices.mjs +257 -0
- package/server/door.mjs +235 -0
- package/server/files.mjs +455 -0
- package/server/gate.mjs +54 -0
- package/server/gitaccess.mjs +295 -0
- package/server/gitchecks.mjs +126 -0
- package/server/gitkeeper.mjs +719 -0
- package/server/gitpush.mjs +585 -0
- package/server/gitrunner.mjs +540 -0
- package/server/grants.mjs +110 -0
- package/server/guide.mjs +278 -0
- package/server/health.mjs +207 -0
- package/server/imap.mjs +75 -0
- package/server/mailbox.mjs +165 -0
- package/server/main.mjs +420 -0
- package/server/names.mjs +10 -0
- package/server/network.mjs +85 -0
- package/server/parley.mjs +62 -0
- package/server/resources.mjs +396 -0
- package/server/seats.mjs +24 -0
- package/server/secrets.mjs +118 -0
- package/server/setup.mjs +768 -0
- package/server/shelf.mjs +260 -0
- package/server/shortcuts.mjs +62 -0
- package/server/signin.mjs +185 -0
- package/server/smoke.mjs +26 -0
- package/server/store.mjs +48 -0
- package/server/talk.mjs +514 -0
- package/server/tmux.mjs +54 -0
- package/server/toolbox.mjs +168 -0
- package/server/tools.mjs +109 -0
- package/server/updates.mjs +116 -0
- package/server/vault.mjs +37 -0
- package/server/vm.mjs +139 -0
- package/server/voice.mjs +90 -0
- package/server/wakeups.mjs +320 -0
- package/web/app.js +4779 -0
- package/web/device.html +149 -0
- package/web/device.js +152 -0
- package/web/icon-192.png +0 -0
- package/web/icon-512.png +0 -0
- package/web/icon.svg +1 -0
- package/web/icons.js +9 -0
- package/web/index.html +784 -0
- package/web/links.js +995 -0
- package/web/manifest.webmanifest +30 -0
- package/web/prism-manual.js +3 -0
- package/web/style.css +1006 -0
- package/web/sw.js +26 -0
- package/web/voice-core.js +107 -0
- package/web/voice.js +56 -0
- package/keep.mjs +0 -8
package/web/style.css
ADDED
|
@@ -0,0 +1,1006 @@
|
|
|
1
|
+
/* The terminal owns the screen. On a wide screen the list sits beside it; on
|
|
2
|
+
a narrow one, the list and the conversation are two screens. */
|
|
3
|
+
:root {
|
|
4
|
+
--bg: #0f141a; --bar: #161d26; --panel: #131a22; --line: #2b3745; --ink: #e7edf4; --ink2: #a3b1c2;
|
|
5
|
+
--brass: #d2a94e; --on-brass: #1b1405; --ok: #5fc39d; --warn: #e39a5c; --danger: #ee7f79;
|
|
6
|
+
--sans: system-ui, -apple-system, "Segoe UI", sans-serif;
|
|
7
|
+
}
|
|
8
|
+
/* A light screen, for whoever reads better dark on light. The terminal gets
|
|
9
|
+
colours of its own for it (app.js): a tool's "white" must stay readable. */
|
|
10
|
+
:root[data-theme="light"] {
|
|
11
|
+
--bg: #fbfbfa; --bar: #eef0f3; --panel: #ffffff; --line: #c5cdd8; --ink: #17202b; --ink2: #4f5d6d;
|
|
12
|
+
--brass: #c79a3a; --on-brass: #1b1405; --ok: #1f7a5a; --warn: #a3581a; --danger: #b3261e; --button: #e6eaef;
|
|
13
|
+
}
|
|
14
|
+
* { box-sizing: border-box; }
|
|
15
|
+
/* TEXT IS IN rem: one size at the root (set per device by app.js, as a
|
|
16
|
+
share of the browser's own text size) scales every text of the page. */
|
|
17
|
+
html { font-size: 100%; touch-action: pan-x pan-y; -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
|
|
18
|
+
html, body { margin: 0; height: 100%; background: var(--bg); color: var(--ink); }
|
|
19
|
+
body { font: .875rem var(--sans); }
|
|
20
|
+
body { height: 100dvh; padding: env(safe-area-inset-top, 0) 0 env(safe-area-inset-bottom, 0); }
|
|
21
|
+
[hidden] { display: none !important; }
|
|
22
|
+
button { font: 600 .8125rem var(--sans); color: var(--ink); background: var(--button, #222c38); border: 1px solid var(--line); border-radius: 7px; padding: 7px 11px; cursor: pointer; }
|
|
23
|
+
button.primary { background: var(--brass); border-color: var(--brass); color: var(--on-brass); }
|
|
24
|
+
button:focus-visible, input:focus-visible { outline: 2px solid var(--brass); outline-offset: 2px; }
|
|
25
|
+
/* The list on the left, the three places under it, the conversation beside them. */
|
|
26
|
+
#app { display: grid; grid-template-columns: 260px minmax(0, 1fr); grid-template-rows: minmax(0, 1fr) auto; height: 100%; }
|
|
27
|
+
#app:has(> #list[hidden]) #room { grid-column: 1 / -1; }
|
|
28
|
+
#list { grid-column: 1; grid-row: 1; min-height: 0; display: flex; flex-direction: column; gap: 8px; padding: 10px; background: var(--panel); border-right: 1px solid var(--line); overflow-y: auto; }
|
|
29
|
+
#list .top { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
|
|
30
|
+
#items { display: flex; flex-direction: column; gap: 6px; }
|
|
31
|
+
.item { display: block; width: 100%; text-align: left; padding: 9px 10px; background: var(--bar); font-weight: 400; }
|
|
32
|
+
.item[aria-current="true"] { border-color: var(--brass); box-shadow: 0 0 0 1px var(--brass); }
|
|
33
|
+
.item b { display: block; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
34
|
+
.item small { color: var(--ink2); }
|
|
35
|
+
.item .dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; margin-right: 6px; background: var(--ink2); }
|
|
36
|
+
.item[data-phase="ready"] .dot { background: var(--ok); }
|
|
37
|
+
.item[data-phase="building"] .dot, .item[data-phase="restarting"] .dot, .item[data-busy="true"] .dot { background: var(--warn); animation: pulse 1.2s ease-in-out infinite; }
|
|
38
|
+
.item[data-phase="failed"] .dot { background: var(--danger); }
|
|
39
|
+
@keyframes pulse { 50% { opacity: .25; } }
|
|
40
|
+
@media (prefers-reduced-motion: reduce) { .item .dot { animation: none !important; } }
|
|
41
|
+
#create { display: flex; flex-direction: column; gap: 6px; padding: 10px; background: var(--bar); border: 1px solid var(--line); border-radius: 8px; }
|
|
42
|
+
#create label, #create .legend { font-size: .75rem; color: var(--ink2); }
|
|
43
|
+
#create input { font: .875rem var(--sans); color: var(--ink); background: var(--bg); border: 1px solid var(--line); border-radius: 7px; padding: 7px 9px; min-width: 0; }
|
|
44
|
+
.choices { display: flex; flex-wrap: wrap; gap: 6px; }
|
|
45
|
+
.choices button[aria-checked="true"] { border-color: var(--brass); background: rgba(210, 169, 78, .16); }
|
|
46
|
+
.row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
|
|
47
|
+
.hint { color: var(--ink2); font-size: .75rem; margin: 0; }
|
|
48
|
+
.error { color: var(--danger); font-size: .8125rem; margin: 0; }
|
|
49
|
+
#room { grid-column: 2; grid-row: 1 / span 2; min-width: 0; min-height: 0; display: flex; flex-direction: column; }
|
|
50
|
+
/* The bar wraps onto a second line rather than squeeze the name away or break a button's label in two. */
|
|
51
|
+
header { display: flex; align-items: center; flex-wrap: wrap; gap: 6px 8px; padding: 6px 10px; background: var(--bar); border-bottom: 1px solid var(--line); min-height: 44px; }
|
|
52
|
+
header b { flex: 1 0 auto; min-width: 6ch; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
53
|
+
header button { padding: 5px 9px; white-space: nowrap; }
|
|
54
|
+
#back { font-size: 1.25rem; line-height: 1; padding: 2px 10px; }
|
|
55
|
+
.tag { font-size: .6875rem; font-weight: 600; padding: 2px 8px; border-radius: 999px; border: 1px solid var(--brass); color: var(--brass); white-space: nowrap; }
|
|
56
|
+
#state { font-size: .75rem; color: var(--ink2); white-space: nowrap; }
|
|
57
|
+
#state::before { content: ""; display: inline-block; width: 8px; height: 8px; border-radius: 50%; margin-right: 6px; background: var(--ink2); }
|
|
58
|
+
#state[data-state="live"]::before { background: var(--ok); }
|
|
59
|
+
#state[data-state="waiting"]::before, #state[data-state="ended"]::before { background: var(--warn); }
|
|
60
|
+
/* Running, but its machine is not well: not green. */
|
|
61
|
+
#state[data-state="live"][data-health="warn"]::before { background: var(--warn); }
|
|
62
|
+
#state[data-state="live"][data-health="bad"]::before { background: var(--danger); }
|
|
63
|
+
main { position: relative; flex: 1; min-height: 0; }
|
|
64
|
+
#terminal { position: absolute; inset: 0; padding: 4px; }
|
|
65
|
+
/* Over the chat screen (a question asked must be seen), under a sheet the person opened (which is shut before any question is asked). */
|
|
66
|
+
#notice { position: absolute; inset: 0; z-index: 2; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 14px; padding: 24px; text-align: center; background: rgba(15, 20, 26, .92); }
|
|
67
|
+
/* On a light screen the veil is light too: dark text on the dark veil could not be read (seen on the welcome of a device). */
|
|
68
|
+
:root[data-theme="light"] #notice { background: rgba(251, 251, 250, .94); }
|
|
69
|
+
#notice p { margin: 0; max-width: 36ch; font-size: 1rem; }
|
|
70
|
+
/* The wheel while a machine is built or its work moved; still for those who ask for less motion. */
|
|
71
|
+
#notice .spin { width: 34px; height: 34px; border-radius: 50%; border: 3px solid rgba(255, 255, 255, .18); border-top-color: #d2a94e; }
|
|
72
|
+
@media (prefers-reduced-motion: no-preference) { #notice .spin { animation: notice-spin .9s linear infinite; } @keyframes notice-spin { to { transform: rotate(360deg); } } }
|
|
73
|
+
/* A START TOLD STEP BY STEP (app.js, progressPanel): what it is and "Step 3
|
|
74
|
+
of 6" with its clock; the step under way large, with its wheel; those
|
|
75
|
+
passed on one small line of checks; those to come dimmed. */
|
|
76
|
+
#notice-head { display: grid; gap: 2px; }
|
|
77
|
+
#notice #notice-title { font-size: .8125rem; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--brass); }
|
|
78
|
+
#notice #notice-count { font-size: .9375rem; color: var(--ink2); font-variant-numeric: tabular-nums; }
|
|
79
|
+
#notice-steps { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; justify-content: center; gap: 4px 12px; max-width: 34rem; font-size: .9375rem; }
|
|
80
|
+
#notice-steps li { color: var(--ink2); }
|
|
81
|
+
#notice-steps li[data-state="done"] { font-size: .75rem; color: var(--ok); opacity: .85; }
|
|
82
|
+
#notice-steps li[data-state="done"]::before { content: "\2713\00a0"; }
|
|
83
|
+
#notice-steps li[data-state="now"] { flex-basis: 100%; order: 1; display: flex; flex-direction: column; align-items: center; gap: 10px; margin: 14px 0 12px; font-size: 1.375rem; font-weight: 600; color: var(--ink); }
|
|
84
|
+
#notice-steps li[data-state="now"] small { font-size: .8125rem; font-weight: 400; color: var(--ink2); }
|
|
85
|
+
#notice-steps li[data-state="later"] { flex-basis: 100%; order: 2; font-size: .875rem; opacity: .7; }
|
|
86
|
+
#notice-steps li[data-state="later"]::before { content: "\25CB\00a0"; }
|
|
87
|
+
#notice-steps li[data-state="now"] small { display: inline-flex; align-items: center; gap: 8px; font-variant-numeric: tabular-nums; }
|
|
88
|
+
#notice-steps li[data-state="now"] progress { width: 7rem; height: 6px; border: 0; border-radius: 3px; background: var(--line); accent-color: var(--brass); overflow: hidden; }
|
|
89
|
+
#notice-steps li[data-state="now"] progress::-webkit-progress-bar { background: var(--line); border-radius: 3px; }
|
|
90
|
+
#notice-steps li[data-state="now"] progress::-webkit-progress-value { background: var(--brass); border-radius: 3px; }
|
|
91
|
+
#notice-steps li[data-state="now"] progress::-moz-progress-bar { background: var(--brass); border-radius: 3px; }
|
|
92
|
+
#notice-steps li[data-state="later"]::before { content: "\25CB\00a0"; }
|
|
93
|
+
:root[data-theme="light"] #notice .spin { border-color: rgba(23, 32, 43, .14); border-top-color: var(--brass); }
|
|
94
|
+
#notice button { padding: 10px 18px; font-size: .9375rem; }
|
|
95
|
+
footer { display: flex; gap: 6px; padding: 6px 8px; background: var(--bar); border-top: 1px solid var(--line); overflow-x: auto; }
|
|
96
|
+
footer button { flex: 0 0 auto; min-width: 44px; padding: 9px 12px; }
|
|
97
|
+
footer button.wide { flex: 1 0 auto; background: var(--brass); border-color: var(--brass); color: var(--on-brass); }
|
|
98
|
+
@media (max-width: 700px) {
|
|
99
|
+
#app { grid-template-columns: minmax(0, 1fr); }
|
|
100
|
+
#list, #room { grid-column: 1; grid-row: 1; border-right: 0; }
|
|
101
|
+
#app[data-view="room"] #list, #app[data-view="list"] #room { display: none; }
|
|
102
|
+
}
|
|
103
|
+
@media (min-width: 701px) { #back { display: none; } }
|
|
104
|
+
/* The list folded away with one click, on a wide screen: the terminal takes the room. */
|
|
105
|
+
@media (min-width: 701px) { #app[data-list="folded"] #list, #app[data-list="folded"] #nav { display: none; } #app[data-list="folded"] #room { grid-column: 1 / -1; } }
|
|
106
|
+
@media (max-width: 700px) { #fold { display: none; } }
|
|
107
|
+
#fold { font-size: 1rem; line-height: 1; padding: 4px 9px; }
|
|
108
|
+
.chips { display: flex; gap: 5px; min-width: 0; overflow: hidden; }
|
|
109
|
+
.chip { font-size: .6875rem; padding: 2px 8px; border-radius: 999px; border: 1px solid var(--line); color: var(--ink2); white-space: nowrap; }
|
|
110
|
+
.chip[data-access="write"] { color: var(--ok); border-color: var(--ok); }
|
|
111
|
+
.sheet { position: absolute; inset: 0; z-index: 3; display: flex; flex-direction: column; gap: 10px; padding: 14px; background: var(--panel); overflow-y: auto; }
|
|
112
|
+
.panel-top { display: flex; align-items: center; justify-content: space-between; }
|
|
113
|
+
#panel-rows { display: flex; flex-direction: column; }
|
|
114
|
+
.folder { display: flex; align-items: center; gap: 8px; padding: 8px 0; border-top: 1px solid var(--line); flex-wrap: wrap; }
|
|
115
|
+
.folder b { flex: 1; min-width: 100px; overflow: hidden; text-overflow: ellipsis; }
|
|
116
|
+
.levels { display: flex; }
|
|
117
|
+
.levels button { border-radius: 0; margin-left: -1px; }
|
|
118
|
+
.levels button:first-child { border-radius: 7px 0 0 7px; margin-left: 0; }
|
|
119
|
+
.levels button:last-child { border-radius: 0 7px 7px 0; }
|
|
120
|
+
.levels button[aria-pressed="true"] { background: rgba(210, 169, 78, .18); border-color: var(--brass); position: relative; }
|
|
121
|
+
#folder-new { display: flex; flex-direction: column; gap: 6px; max-width: 420px; }
|
|
122
|
+
#folder-new label { font-size: .75rem; color: var(--ink2); }
|
|
123
|
+
#folder-new input { flex: 1; min-width: 0; font: .875rem var(--sans); color: var(--ink); background: var(--bg); border: 1px solid var(--line); border-radius: 7px; padding: 7px 9px; }
|
|
124
|
+
code { font-family: ui-monospace, Menlo, Consolas, monospace; }
|
|
125
|
+
@media (max-width: 700px) { #chips { display: none; } }
|
|
126
|
+
.path { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; font-size: .8125rem; color: var(--ink2); }
|
|
127
|
+
.path button { padding: 3px 8px; font-weight: 400; }
|
|
128
|
+
#files-rows { display: flex; flex-direction: column; }
|
|
129
|
+
.file { display: flex; align-items: center; gap: 10px; padding: 8px 0; border-top: 1px solid var(--line); color: var(--ink); text-decoration: none; background: none; border-left: 0; border-right: 0; border-bottom: 0; border-radius: 0; text-align: left; font-weight: 400; width: 100%; }
|
|
130
|
+
.file .kind { flex: 0 0 34px; font-size: .625rem; font-weight: 700; text-align: center; padding: 3px 0; border: 1px solid var(--line); border-radius: 5px; color: var(--ink2); }
|
|
131
|
+
.file[data-folder="true"] .kind { color: var(--brass); border-color: var(--brass); }
|
|
132
|
+
.file .label { flex: 1; min-width: 0; overflow-wrap: anywhere; }
|
|
133
|
+
.file small { color: var(--ink2); white-space: nowrap; }
|
|
134
|
+
.choices button[aria-selected="true"] { border-color: var(--brass); background: rgba(210, 169, 78, .16); }
|
|
135
|
+
#shortcuts { background: var(--bar); border-top: 1px solid var(--line); padding: 6px 8px 0; }
|
|
136
|
+
.chips-row { display: flex; gap: 6px; overflow-x: auto; padding-bottom: 6px; }
|
|
137
|
+
.chips-row button { flex: 0 0 auto; border-radius: 999px; padding: 6px 12px; font-weight: 500; }
|
|
138
|
+
.chips-row button.saved { border-color: var(--brass); background: rgba(210, 169, 78, .14); }
|
|
139
|
+
.chips-row button.saved[data-enter="false"] { border-style: dashed; }
|
|
140
|
+
.chips-row button.removing { border-color: var(--danger); color: var(--danger); }
|
|
141
|
+
.chips-row button.quiet { color: var(--ink2); }
|
|
142
|
+
#shortcut-new { display: flex; flex-direction: column; gap: 6px; padding: 4px 0 8px; max-width: 520px; }
|
|
143
|
+
#shortcut-new input:not([type]) , #shortcut-new input[maxlength] { font: .875rem var(--sans); color: var(--ink); background: var(--bg); border: 1px solid var(--line); border-radius: 7px; padding: 7px 9px; min-width: 0; }
|
|
144
|
+
.check { font-size: .8125rem; color: var(--ink2); display: flex; align-items: center; gap: 6px; }
|
|
145
|
+
footer#keys { border-top: 0; }
|
|
146
|
+
#voice-line { margin: 0; padding: 5px 12px; font-size: .8125rem; color: var(--ink2); background: var(--bar); border-top: 1px solid var(--line); overflow-wrap: anywhere; }
|
|
147
|
+
#voice-line::before { content: ""; display: inline-block; width: 8px; height: 8px; border-radius: 50%; margin-right: 8px; background: var(--ok); }
|
|
148
|
+
#voice-line[data-state="hearing"]::before { background: var(--danger); }
|
|
149
|
+
#voice-line[data-state="transcribing"]::before, #voice-line[data-state="calibrating"]::before { background: var(--warn); }
|
|
150
|
+
#mic[aria-pressed="true"] { background: var(--danger); border-color: var(--danger); color: #1b0606; }
|
|
151
|
+
#auto[aria-pressed="true"] { border-color: var(--brass); color: var(--brass); }
|
|
152
|
+
#sharing-qr { width: 220px; max-width: 70%; background: #fff; padding: 10px; border-radius: 10px; }
|
|
153
|
+
.link { overflow-wrap: anywhere; user-select: all; font-family: ui-monospace, Menlo, Consolas, monospace; }
|
|
154
|
+
.device { display: flex; align-items: center; gap: 10px; padding: 8px 0; border-top: 1px solid var(--line); flex-wrap: wrap; }
|
|
155
|
+
.device b { flex: 1; min-width: 120px; } .device small { color: var(--ink2); }
|
|
156
|
+
button.danger { border-color: var(--danger); color: var(--danger); }
|
|
157
|
+
html[data-door="device"] #app { display: block; }
|
|
158
|
+
html[data-door="device"] #room { height: 100%; }
|
|
159
|
+
#secret-rows { display: flex; flex-direction: column; }
|
|
160
|
+
#secret-new { display: flex; flex-direction: column; gap: 6px; max-width: 560px; }
|
|
161
|
+
#secret-new label { font-size: .75rem; color: var(--ink2); }
|
|
162
|
+
#secret-new input { flex: 1; min-width: 120px; font: .875rem var(--sans); color: var(--ink); background: var(--bg); border: 1px solid var(--line); border-radius: 7px; padding: 7px 9px; }
|
|
163
|
+
.chip[data-access="offline"] { color: var(--warn); border-color: var(--warn); }
|
|
164
|
+
#signin-strip { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; padding: 8px 12px; background: rgba(210, 169, 78, .14); border-bottom: 1px solid var(--brass); font-size: .8125rem; }
|
|
165
|
+
#signin-text { flex: 1; min-width: 160px; }
|
|
166
|
+
a.button { font: 600 .8125rem var(--sans); text-decoration: none; border-radius: 7px; padding: 7px 11px; background: var(--brass); color: var(--on-brass); }
|
|
167
|
+
#signin-form input { flex: 1; min-width: 130px; font: .875rem var(--sans); color: var(--ink); background: var(--bg); border: 1px solid var(--line); border-radius: 7px; padding: 7px 9px; }
|
|
168
|
+
/* On a narrow screen the key row wraps instead of hiding its end, and
|
|
169
|
+
dictation comes first: by voice is how a phone is used. */
|
|
170
|
+
@media (max-width: 700px) {
|
|
171
|
+
footer#keys { flex-wrap: wrap; overflow-x: visible; }
|
|
172
|
+
#mic, #auto { order: -1; flex: 1 0 auto; }
|
|
173
|
+
#mic { flex-basis: 55%; padding-block: 12px; }
|
|
174
|
+
}
|
|
175
|
+
.item[data-asleep="true"] .dot { background: var(--ink2); }
|
|
176
|
+
footer button.careful { border-style: dashed; color: var(--ink2); }
|
|
177
|
+
/* On a touch screen every control is at least a fingertip high. */
|
|
178
|
+
@media (max-width: 700px) {
|
|
179
|
+
button, a.button, .file { min-height: 44px; }
|
|
180
|
+
.chips-row button { padding-block: 10px; }
|
|
181
|
+
#state, .tag { font-size: .8125rem; }
|
|
182
|
+
footer button.careful { order: 5; }
|
|
183
|
+
}
|
|
184
|
+
#copy-text { flex: 2; min-height: 160px; width: 100%; resize: none; font: .8125rem/1.4 ui-monospace, Menlo, Consolas, monospace; color: var(--ink); background: var(--bg); border: 1px solid var(--line); border-radius: 7px; padding: 10px; white-space: pre; overflow: auto; }
|
|
185
|
+
#paste-text { flex: 1; min-height: 70px; width: 100%; resize: none; font: .8125rem/1.4 ui-monospace, Menlo, Consolas, monospace; color: var(--ink); background: var(--bg); border: 1px solid var(--line); border-radius: 7px; padding: 10px; }
|
|
186
|
+
/* The page never scrolls or zooms under a finger on the terminal: the drag is for the terminal. */
|
|
187
|
+
#terminal { touch-action: none; }
|
|
188
|
+
|
|
189
|
+
/* Adding a mailbox: folded away until asked for. */
|
|
190
|
+
#mailbox-box, #git-box { margin: 12px 0; }
|
|
191
|
+
#mailbox-box summary, #git-box summary { cursor: pointer; min-height: 44px; display: flex; align-items: center; }
|
|
192
|
+
#mailbox-new, #git-new { display: grid; gap: 6px; }
|
|
193
|
+
.folder small.hint { font-weight: normal; }
|
|
194
|
+
/* Under the access buttons of a repository, across the whole row. */
|
|
195
|
+
.folder .auto-send { flex-basis: 100%; }
|
|
196
|
+
.auto-send fieldset { display: flex; flex-direction: column; gap: 6px; margin: 6px 0 0; padding: 0; border: 0; min-width: 0; }
|
|
197
|
+
.auto-send label:not(.check) { display: flex; flex-direction: column; gap: 4px; }
|
|
198
|
+
#mailbox-new input, #git-new input { min-width: 0; min-height: 40px; font: .875rem var(--sans); color: var(--ink); background: var(--bg); border: 1px solid var(--line); border-radius: 7px; padding: 7px 9px; }
|
|
199
|
+
#mailbox-new .row input, #git-new .row input { flex: 1; }
|
|
200
|
+
#mailbox-new #mailbox-port { flex: 0 0 90px; }
|
|
201
|
+
#mailbox-new label, #git-new label { font-size: .8125rem; color: var(--muted, inherit); margin-top: 4px; }
|
|
202
|
+
|
|
203
|
+
/* A file, shown in a window over the screen. */
|
|
204
|
+
#viewer { position: absolute; inset: 0; z-index: 6; display: flex; align-items: stretch; justify-content: center; padding: 10px; background: rgba(8, 11, 15, 0.72); }
|
|
205
|
+
#viewer-card { display: flex; flex-direction: column; gap: 8px; width: min(1100px, 100%); background: var(--panel); border: 1px solid var(--line); border-radius: 10px; padding: 10px 12px; min-height: 0; }
|
|
206
|
+
#viewer .row { align-items: center; gap: 8px; flex-wrap: wrap; }
|
|
207
|
+
#viewer .sp { flex: 1; }
|
|
208
|
+
#viewer #preview-name { overflow-wrap: anywhere; }
|
|
209
|
+
#viewer a.button { display: inline-flex; align-items: center; min-height: 40px; padding: 0 14px; border-radius: 8px; background: var(--brass); color: var(--on-brass); font-weight: 600; text-decoration: none; }
|
|
210
|
+
#viewer button { min-height: 40px; }
|
|
211
|
+
#viewer p { margin: 0; }
|
|
212
|
+
#preview-body { overflow: auto; flex: 1; min-height: 0; }
|
|
213
|
+
#preview-body img, #preview-body canvas { display: block; max-width: 100%; height: auto; margin: 0 auto 10px; background: #fff; border-radius: 4px; }
|
|
214
|
+
#preview-body pre { white-space: pre-wrap; overflow-wrap: anywhere; font: .8125rem/1.45 ui-monospace, Menlo, Consolas, monospace; color: var(--ink); margin: 0; }
|
|
215
|
+
|
|
216
|
+
#others-add { display: grid; gap: 6px; margin-top: 12px; }
|
|
217
|
+
#others-add input { flex: 1; min-width: 0; min-height: 40px; font: .875rem var(--sans); color: var(--ink); background: var(--bg); border: 1px solid var(--line); border-radius: 7px; padding: 7px 9px; }
|
|
218
|
+
|
|
219
|
+
/* A word said for a moment (text copied). */
|
|
220
|
+
#flash { position: absolute; left: 50%; bottom: 14px; transform: translateX(-50%); z-index: 7; display: flex; align-items: center; gap: 10px; max-width: calc(100% - 24px); padding: 8px 14px; border-radius: 999px; background: var(--panel); color: var(--ink); border: 1px solid var(--brass); font-weight: 600; font-size: .8125rem; pointer-events: none; box-shadow: 0 6px 20px rgba(0, 0, 0, 0.35); }
|
|
221
|
+
#flash[data-menu="true"] { pointer-events: auto; }
|
|
222
|
+
#flash-act { min-height: 40px; max-width: 60vw; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
223
|
+
|
|
224
|
+
/* What a device was given, thing by thing. */
|
|
225
|
+
.device .given { flex-basis: 100%; display: flex; flex-wrap: wrap; gap: 6px; }
|
|
226
|
+
.device .given .chip { display: inline-flex; align-items: center; gap: 6px; }
|
|
227
|
+
.device .given .chip button { min-height: 0; padding: 0 7px; border-radius: 999px; font-size: .75rem; }
|
|
228
|
+
#sharing-what { display: flex; flex-direction: column; }
|
|
229
|
+
|
|
230
|
+
/* What can be unfolded looks like it can. */
|
|
231
|
+
#panel details > summary { list-style: none; cursor: pointer; padding: 8px 12px; border: 1px solid var(--line); border-radius: 8px; background: var(--button, #222c38); font-weight: 600; }
|
|
232
|
+
#panel details > summary::before { content: '+ '; }
|
|
233
|
+
#panel details[open] > summary::before { content: '- '; }
|
|
234
|
+
#sharing-label { min-height: 40px; font: .875rem var(--sans); color: var(--ink); background: var(--bg); border: 1px solid var(--line); border-radius: 7px; padding: 7px 9px; }
|
|
235
|
+
#sharing label { font-size: .8125rem; }
|
|
236
|
+
|
|
237
|
+
/* A repository: what would go out. */
|
|
238
|
+
#gitview pre { margin: 0; white-space: pre-wrap; overflow-wrap: anywhere; font: .75rem/1.45 ui-monospace, Menlo, Consolas, monospace; color: var(--ink); background: var(--bg); border: 1px solid var(--line); border-radius: 8px; padding: 8px 10px; }
|
|
239
|
+
#gitview pre:empty { display: none; }
|
|
240
|
+
#gitview .commit { display: flex; flex-wrap: wrap; gap: 4px 10px; align-items: baseline; padding: 6px 0; border-top: 1px solid var(--line); }
|
|
241
|
+
#gitview .commit code { color: var(--ink2); }
|
|
242
|
+
#gitview .commit small { color: var(--ink2); }
|
|
243
|
+
#gitview-remote, #gitview-keep { display: grid; gap: 6px; margin-top: 8px; }
|
|
244
|
+
#gitview-keep input:not([type=checkbox]), #gitview-keep textarea, #gitview-target, #gitview-newbranch { min-width: 0; min-height: 40px; font: .875rem var(--sans); color: var(--ink); background: var(--bg); border: 1px solid var(--line); border-radius: 7px; padding: 7px 9px; }
|
|
245
|
+
#gitview-target { max-width: 100%; }
|
|
246
|
+
#gitview-origin code { overflow-wrap: anywhere; font: .75rem/1.45 ui-monospace, Menlo, Consolas, monospace; }
|
|
247
|
+
#gitview-checks-state.passed { color: var(--ok); }
|
|
248
|
+
#gitview-checks-state.failed { color: var(--danger); }
|
|
249
|
+
#gitview-log .logline { padding: 4px 0; border-top: 1px solid var(--line); font-size: .8125rem; overflow-wrap: anywhere; }
|
|
250
|
+
#gitview-log .logline.bad { color: var(--ink2); }
|
|
251
|
+
#gitview-remote input { flex: 1; min-width: 0; min-height: 40px; font: .875rem var(--sans); color: var(--ink); background: var(--bg); border: 1px solid var(--line); border-radius: 7px; padding: 7px 9px; }
|
|
252
|
+
#gitview details > summary { cursor: pointer; padding: 8px 12px; border: 1px solid var(--line); border-radius: 8px; background: var(--button, #222c38); font-weight: 600; list-style: none; }
|
|
253
|
+
|
|
254
|
+
/* Sharing: a basket, the code, and who has what. */
|
|
255
|
+
#sharing { gap: 12px; }
|
|
256
|
+
#share-compose, #share-code, #share-manage { display: flex; flex-direction: column; gap: 10px; }
|
|
257
|
+
#share-name-row { display: flex; flex-direction: column; gap: 6px; }
|
|
258
|
+
#sharing-label, #share-search, .device input { min-height: 40px; font: .875rem var(--sans); color: var(--ink); background: var(--bg); border: 1px solid var(--line); border-radius: 7px; padding: 7px 9px; }
|
|
259
|
+
.share-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; align-items: start; }
|
|
260
|
+
.share-col { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
|
|
261
|
+
@media (max-width: 900px) { .share-cols { grid-template-columns: 1fr; } }
|
|
262
|
+
#share-basket .folder, #share-add .folder { align-items: center; }
|
|
263
|
+
#share-add button, #share-basket button, .given-row button, .device button { min-height: 40px; }
|
|
264
|
+
.share-foot { position: sticky; bottom: -14px; display: flex; flex-wrap: wrap; align-items: center; gap: 10px; padding: 10px 0; background: var(--panel); border-top: 1px solid var(--line); }
|
|
265
|
+
.share-foot p { flex: 1 1 260px; margin: 0; }
|
|
266
|
+
#share-who button[aria-checked="true"], #share-filters button[aria-pressed="true"], #share-manage .choices button[aria-pressed="true"] { border-color: var(--brass); color: var(--brass); }
|
|
267
|
+
#sharing .levels button[data-rights="rw"][aria-pressed="true"] { border-color: var(--warn); color: var(--warn); }
|
|
268
|
+
#sharing-qr { width: min(280px, 70vw); background: #fff; padding: 10px; border-radius: 8px; }
|
|
269
|
+
#share-waiting { font-size: 1rem; font-weight: 600; margin: 0; }
|
|
270
|
+
.device { flex-direction: column; align-items: stretch; }
|
|
271
|
+
.device-head { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
|
|
272
|
+
.device-head small { flex: 1; color: var(--ink2); }
|
|
273
|
+
.device-head small.warn { color: var(--warn); }
|
|
274
|
+
.given-row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding: 6px 0 6px 12px; border-top: 1px dashed var(--line); }
|
|
275
|
+
.given-row > span:first-child { flex: 1 1 160px; min-width: 0; }
|
|
276
|
+
.thing { border-top: 1px solid var(--line); padding: 6px 0; }
|
|
277
|
+
.thing > summary { cursor: pointer; font-weight: 600; min-height: 40px; display: flex; align-items: center; }
|
|
278
|
+
.item .shared-mark { display: block; color: var(--brass); }
|
|
279
|
+
/* A sheet is open on a small screen: the keys of the terminal are not for it, and would take half the
|
|
280
|
+
screen from it. On a wide screen they stay: taking them away would resize the terminal under the
|
|
281
|
+
sheet each time, and the tool would redraw for nothing (a test caught the screen moving). */
|
|
282
|
+
@media (max-width: 900px) { #room:has(.sheet:not([hidden])) #keys, #room:has(.sheet:not([hidden])) #shortcuts { display: none; } }
|
|
283
|
+
/* A device's card: one full-width line per thing it has. */
|
|
284
|
+
.device .given { display: block; flex-basis: auto; }
|
|
285
|
+
.device > button { align-self: flex-start; }
|
|
286
|
+
.given-row > .hint, .given-row > .levels { flex: 0 0 auto; }
|
|
287
|
+
/* A conversation given in parts: Terminal, Chat -- two boxes to tick, at least one. */
|
|
288
|
+
.parts { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 14px; flex: 0 1 auto; }
|
|
289
|
+
.parts label.check { min-height: 40px; font-size: .875rem; color: var(--ink); cursor: pointer; }
|
|
290
|
+
.parts input { width: 18px; height: 18px; accent-color: var(--brass); }
|
|
291
|
+
.parts label.check:has(input[aria-disabled="true"]) { cursor: default; }
|
|
292
|
+
.parts .parts-need { flex-basis: 100%; }
|
|
293
|
+
.parts .parts-off { flex-basis: 100%; color: var(--warn); }
|
|
294
|
+
.given > .parts-off { color: var(--warn); margin: 6px 0 2px; font-size: .8125rem; }
|
|
295
|
+
|
|
296
|
+
/* The left column: conversations, then the platform's three entries, always in sight. */
|
|
297
|
+
#list #items { flex: 1 1 auto; overflow-y: auto; min-height: 0; display: flex; flex-direction: column; gap: 8px; }
|
|
298
|
+
/* Assets: one row per thing; opened, it says who may do what with it. */
|
|
299
|
+
#assets section { display: flex; flex-direction: column; gap: 6px; margin-top: 6px; }
|
|
300
|
+
#assets section .panel-top small { margin-left: 8px; }
|
|
301
|
+
.asset { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; border-top: 1px solid var(--line); padding: 4px 0; }
|
|
302
|
+
.asset-head { flex: 1 1 320px; display: grid; grid-template-columns: minmax(120px, 1fr) minmax(140px, 1.4fr) minmax(120px, 1.4fr); gap: 10px; align-items: center; text-align: left; background: transparent; border: 0; padding: 8px 4px; min-height: 44px; font-weight: 400; }
|
|
303
|
+
.asset-head b { overflow-wrap: anywhere; }
|
|
304
|
+
.asset-head[aria-expanded="true"] b { color: var(--brass); }
|
|
305
|
+
/* A card opens: a small arrow says so, turned down when it is open. */
|
|
306
|
+
.asset-head b::before { content: "\25B8"; display: inline-block; width: 1.1em; color: var(--dim); transition: transform .15s; }
|
|
307
|
+
.asset-head[aria-expanded="true"] b::before { transform: rotate(90deg); color: var(--brass); }
|
|
308
|
+
@media (prefers-reduced-motion: reduce) { .asset-head b::before { transition: none; } }
|
|
309
|
+
.asset-inside { flex-basis: 100%; padding: 0 0 8px 12px; display: flex; flex-direction: column; gap: 4px; }
|
|
310
|
+
@media (max-width: 700px) { .asset-head { grid-template-columns: 1fr; gap: 2px; } }
|
|
311
|
+
#assets details > summary, #access-advanced > summary, #settings-advanced > summary { cursor: pointer; padding: 8px 12px; border: 1px solid var(--line); border-radius: 8px; background: var(--button, #222c38); font-weight: 600; list-style: none; align-self: flex-start; }
|
|
312
|
+
#assets details > summary::before, #access-advanced > summary::before, #settings-advanced > summary::before { content: '+ '; }
|
|
313
|
+
#assets details[open] > summary::before, #access-advanced[open] > summary::before, #settings-advanced[open] > summary::before { content: '- '; }
|
|
314
|
+
#assets details form, #access-advanced > div, #settings-advanced > div { margin-top: 8px; }
|
|
315
|
+
#attach-picker { border: 1px solid var(--brass); border-radius: 10px; padding: 10px 12px; display: flex; flex-direction: column; gap: 6px; }
|
|
316
|
+
#chips { cursor: pointer; }
|
|
317
|
+
#settings .row { align-items: center; gap: 10px; }
|
|
318
|
+
/* One kind of event a line: its name, then its level, wrapped under it on a narrow screen. */
|
|
319
|
+
.thread-levels { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 6px 12px; align-items: center; }
|
|
320
|
+
.thread-levels label { min-width: 0; }
|
|
321
|
+
.thread-levels small { display: block; color: var(--ink2); font-size: .8125rem; }
|
|
322
|
+
.thread-levels select { min-height: 40px; min-width: 10rem; font: .875rem var(--sans); color: var(--ink); background: var(--bg); border: 1px solid var(--line); border-radius: 7px; padding: 7px 9px; }
|
|
323
|
+
@media (max-width: 420px) { .thread-levels { grid-template-columns: minmax(0, 1fr); } .thread-levels select { justify-self: start; margin-bottom: 6px; } }
|
|
324
|
+
|
|
325
|
+
/* What is done to the conversation itself sits at the foot of its own sheet. */
|
|
326
|
+
#conversation-actions { align-items: center; gap: 8px; }
|
|
327
|
+
#conversation-actions .sp { flex: 1; }
|
|
328
|
+
#conversation-actions button { min-height: 40px; }
|
|
329
|
+
|
|
330
|
+
/* A page written by the tool: a frame with a visible edge, so it never passes for this site. */
|
|
331
|
+
#preview-body iframe { display: block; width: 100%; height: min(70vh, 900px); border: 2px solid var(--brass); border-radius: 8px; background: #fff; }
|
|
332
|
+
#preview-body > button { margin-bottom: 8px; min-height: 40px; }
|
|
333
|
+
|
|
334
|
+
/* Answers in the owner's place. */
|
|
335
|
+
#answerer-fields textarea { width: 100%; min-height: 4.5rem; resize: vertical; font: inherit; padding: .5rem .6rem; border-radius: 8px; border: 1px solid var(--line); background: var(--bg); color: var(--ink); }
|
|
336
|
+
#answerer-fields label { display: block; margin: .7rem 0 .25rem; }
|
|
337
|
+
#answerer-limit { width: 8rem; }
|
|
338
|
+
#answerer-fields .row { margin-top: .8rem; }
|
|
339
|
+
.needs-mark { display: block; color: var(--brass); font-weight: 700; }
|
|
340
|
+
.answered { border-top: 1px solid var(--line); padding: .4rem 0; }
|
|
341
|
+
.answered[data-outcome="human"] > summary { color: var(--brass); }
|
|
342
|
+
.answered pre { max-height: 14rem; overflow: auto; font-size: .78rem; }
|
|
343
|
+
|
|
344
|
+
/* Wake-ups. */
|
|
345
|
+
.wakeup { border-top: 1px solid var(--line); padding: .6rem 0; }
|
|
346
|
+
.wakeup .hint { margin: .15rem 0; }
|
|
347
|
+
#wakeups-new label, #wakeups-box > label { display: block; margin: .7rem 0 .25rem; }
|
|
348
|
+
#wakeups-new textarea { width: 100%; min-height: 4.5rem; resize: vertical; font: inherit; padding: .5rem .6rem; border-radius: 8px; border: 1px solid var(--line); background: var(--bg); color: var(--ink); }
|
|
349
|
+
#wakeups-new label.check { display: flex; gap: .5rem; align-items: center; }
|
|
350
|
+
#wakeups-limit { width: 8rem; }
|
|
351
|
+
|
|
352
|
+
.notice-box { border: 1px solid var(--brass); border-radius: 10px; padding: .7rem .8rem; margin: .6rem 0; }
|
|
353
|
+
.notice-box input { width: 100%; font-family: ui-monospace, monospace; font-size: .82rem; margin: .4rem 0; }
|
|
354
|
+
|
|
355
|
+
/* The simple screen lies over the terminal, which stays laid out underneath. */
|
|
356
|
+
#simple { position: absolute; inset: 0; z-index: 1; overflow: auto; background: var(--bg); padding: 14px 16px 24px; }
|
|
357
|
+
#simple-state { margin: 0 0 12px; font-size: 1.05rem; font-weight: 600; }
|
|
358
|
+
#simple-state[data-needs="true"] { color: var(--brass); }
|
|
359
|
+
#simple-say label { display: block; font-weight: 700; margin-bottom: 6px; }
|
|
360
|
+
#simple-text { width: 100%; min-height: 4.2rem; resize: vertical; font: inherit; font-size: 1.05rem; padding: .6rem .7rem; border-radius: 10px; border: 1px solid var(--line); background: var(--panel); color: var(--ink); }
|
|
361
|
+
#simple-say .row { margin-top: 8px; }
|
|
362
|
+
#simple-say button.primary { min-height: 46px; padding: 0 1.6rem; font-size: 1.05rem; }
|
|
363
|
+
#simple-files { display: grid; gap: 6px; }
|
|
364
|
+
#simple-files .file { display: flex; justify-content: space-between; gap: 1rem; align-items: baseline; width: 100%; text-align: left; min-height: 46px; padding: .5rem .8rem; }
|
|
365
|
+
#simple-says { margin: 0; white-space: pre-wrap; overflow-wrap: anywhere; font-size: .86rem; line-height: 1.45; border: 1px solid var(--line); border-radius: 10px; padding: .6rem .7rem; background: var(--panel); color: var(--ink2); max-height: 22rem; overflow: auto; }
|
|
366
|
+
#simple .panel-top { margin-top: 16px; }
|
|
367
|
+
/* Without its terminal, the keys of a terminal are of no use; ready answers and the voice stay. */
|
|
368
|
+
#room[data-simple] #keys > button:not(#mic):not(#auto) { display: none; }
|
|
369
|
+
/* Under the chat, its own box has dictation and the ready answers: the bar's, which type into the terminal, are not shown. */
|
|
370
|
+
#room[data-chat] #shortcuts, #room[data-chat] #keys, #room[data-chat] #voice-line { display: none !important; }
|
|
371
|
+
|
|
372
|
+
/* The conversation with the tool is drawn by Parley; here, only where it sits and this page's colours. */
|
|
373
|
+
/* The chat takes the whole screen: its box stays at the bottom, the messages scroll above it. */
|
|
374
|
+
/* On a light screen, brass text is too pale to read: the words in that colour are darker; the buttons keep it. */
|
|
375
|
+
:root[data-theme="light"] #simple-thread { --parley-ask: #8a5d00; }
|
|
376
|
+
#chat-off { margin: auto; max-width: 36ch; text-align: center; padding: 24px 8px; }
|
|
377
|
+
#chat-off p { margin: 0 0 10px; font-size: 1rem; }
|
|
378
|
+
#chat-off p + p { color: var(--ink2); }
|
|
379
|
+
#simple[data-chat] { display: flex; flex-direction: column; overflow: hidden; padding: 10px 14px 12px; }
|
|
380
|
+
#simple-thread { flex: 1; min-height: 0; --parley-bg: var(--bg); --parley-text: var(--ink); --parley-dim: var(--ink2); --parley-line: var(--line); --parley-agent: var(--panel); --parley-person: var(--bar); --parley-ask: var(--brass); --parley-action: var(--brass); --parley-on-action: #1b1405; --parley-live: var(--danger); }
|
|
381
|
+
|
|
382
|
+
|
|
383
|
+
/* Private repositories: how the server gets in, and the keys made here. */
|
|
384
|
+
#git-via { border: 1px solid var(--line); border-radius: 8px; padding: 6px 10px; display: flex; flex-direction: column; gap: 4px; margin: 6px 0; }
|
|
385
|
+
#git-via label { display: flex; gap: 6px; align-items: baseline; flex-wrap: wrap; font-weight: 400; }
|
|
386
|
+
.git-via-part { display: flex; flex-direction: column; gap: 4px; }
|
|
387
|
+
.warn { color: var(--warn); }
|
|
388
|
+
p.warn { margin: 0; font-size: .75rem; }
|
|
389
|
+
textarea.public-key { flex: 1 1 260px; min-width: 0; font: .75rem ui-monospace, Menlo, Consolas, monospace; padding: .4rem .5rem; border-radius: 8px; border: 1px solid var(--line); background: var(--bg); color: var(--ink); resize: vertical; overflow-wrap: anywhere; }
|
|
390
|
+
.git-key { flex-direction: column; align-items: stretch; }
|
|
391
|
+
.git-key .row { flex-wrap: wrap; }
|
|
392
|
+
#git-new input[type="radio"] { min-height: 0; padding: 0; margin: 0; }
|
|
393
|
+
#git-new select, #gitview-sshkey { min-height: 40px; min-width: 10rem; font: .875rem var(--sans); color: var(--ink); background: var(--bg); border: 1px solid var(--line); border-radius: 7px; padding: 7px 9px; }
|
|
394
|
+
|
|
395
|
+
#settings-advanced > div { display: grid; gap: 6px; }
|
|
396
|
+
#git-hosts .folder code { overflow-wrap: anywhere; font: .75rem/1.45 ui-monospace, Menlo, Consolas, monospace; }
|
|
397
|
+
#gitview .commit pre { flex-basis: 100%; margin: 2px 0 0; white-space: pre-wrap; color: var(--ink2); font-size: 0.85em; }
|
|
398
|
+
#gitview #gitview-guards ul { margin: 4px 0 8px; padding-left: 20px; }
|
|
399
|
+
#gitview #gitview-guards li { overflow-wrap: anywhere; }
|
|
400
|
+
|
|
401
|
+
/* ---------- this conversation: chapters that fold, as a project's settings ---------- */
|
|
402
|
+
#panel { gap: 12px; }
|
|
403
|
+
#panel details.chapter { border: 1px solid var(--line); border-radius: 10px; background: var(--bar); }
|
|
404
|
+
#panel details.chapter > summary { list-style: none; cursor: pointer; display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 12px; padding: 12px 14px; border: 0; background: none; border-radius: 10px; min-height: 48px; }
|
|
405
|
+
#panel details.chapter > summary::-webkit-details-marker { display: none; }
|
|
406
|
+
#panel details.chapter > summary::before { content: none; }
|
|
407
|
+
#panel details.chapter > summary::after { content: "Expand"; margin-left: auto; font-size: .75rem; font-weight: 600; color: var(--ink2); border: 1px solid var(--line); border-radius: 7px; padding: 3px 9px; }
|
|
408
|
+
#panel details.chapter[open] > summary::after { content: "Collapse"; }
|
|
409
|
+
#panel details.chapter[open] > summary { border-bottom: 1px solid var(--line); border-radius: 10px 10px 0 0; }
|
|
410
|
+
.chapter-title { font-size: 1.0625rem; font-weight: 700; color: var(--ink); }
|
|
411
|
+
.chapter-about { font-size: .8125rem; font-weight: 400; color: var(--ink2); flex: 1 1 14rem; }
|
|
412
|
+
.chapter-body { display: flex; flex-direction: column; gap: 10px; padding: 12px 14px 14px; background: var(--panel); border-radius: 0 0 10px 10px; }
|
|
413
|
+
.facts { display: grid; grid-template-columns: max-content 1fr; gap: 4px 14px; margin: 0; }
|
|
414
|
+
.facts dt { color: var(--ink2); }
|
|
415
|
+
.facts dd { margin: 0; overflow-wrap: anywhere; }
|
|
416
|
+
#machine-size { display: flex; flex-direction: column; gap: 6px; max-width: 30rem; }
|
|
417
|
+
#machine-size label { font-size: .8125rem; color: var(--ink2); }
|
|
418
|
+
#machine-size select { width: 100%; min-height: 40px; font: .875rem var(--sans); color: var(--ink); background: var(--bg); border: 1px solid var(--line); border-radius: 7px; padding: 6px 8px; }
|
|
419
|
+
.health-lines { list-style: none; margin: 0; padding: 0; display: grid; gap: 4px; }
|
|
420
|
+
.health-lines li { padding-left: 1.3em; position: relative; }
|
|
421
|
+
.health-lines li::before { content: ""; position: absolute; left: .2em; top: .45em; width: .55em; height: .55em; border-radius: 50%; background: var(--ok); }
|
|
422
|
+
.health-lines li[data-level="info"]::before { background: var(--ink2); }
|
|
423
|
+
.health-lines li[data-level="warn"]::before { background: var(--warn); }
|
|
424
|
+
.health-lines li[data-level="bad"]::before { background: var(--danger); }
|
|
425
|
+
.health-lines li[data-level="bad"] { color: var(--danger); }
|
|
426
|
+
|
|
427
|
+
/* The machine is not well: said over the terminal, with what can be done. */
|
|
428
|
+
#health-strip { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; padding: 8px 12px; background: rgba(227, 154, 92, .14); border-bottom: 1px solid var(--warn); font-size: .8125rem; }
|
|
429
|
+
#health-strip[data-level="bad"] { background: rgba(238, 127, 121, .14); border-color: var(--danger); }
|
|
430
|
+
#health-text { flex: 1 1 14rem; min-width: 0; overflow-wrap: anywhere; }
|
|
431
|
+
.health-actions { display: flex; flex-wrap: wrap; gap: 6px; }
|
|
432
|
+
.health-actions button[hidden] { display: none; }
|
|
433
|
+
#notice .health-lines { text-align: left; max-width: 36rem; }
|
|
434
|
+
|
|
435
|
+
/* ---------- text size: one setting of this device ---------- */
|
|
436
|
+
.text-size { display: inline-flex; }
|
|
437
|
+
.text-size button { border-radius: 0; margin-left: -1px; min-width: 44px; }
|
|
438
|
+
.text-size button:first-child { border-radius: 7px 0 0 7px; margin-left: 0; }
|
|
439
|
+
.text-size button:last-child { border-radius: 0 7px 7px 0; }
|
|
440
|
+
header .text-size { display: none; }
|
|
441
|
+
#menu { display: none; font-size: 1.25rem; line-height: 1; padding: 2px 12px; }
|
|
442
|
+
#menu-items { display: contents; }
|
|
443
|
+
#keys-more { display: none; }
|
|
444
|
+
footer button[data-keys="backspace"] { display: none; }
|
|
445
|
+
|
|
446
|
+
/* ---------- a phone: the terminal first ---------- */
|
|
447
|
+
@media (max-width: 700px) {
|
|
448
|
+
/* The bar is one line: what does not fit is behind "...", which opens over the terminal. */
|
|
449
|
+
header { flex-wrap: nowrap; position: relative; padding: 4px 8px; gap: 6px; min-height: 44px; }
|
|
450
|
+
header b { flex: 1 1 auto; min-width: 0; }
|
|
451
|
+
#chips, header #tool { display: none; }
|
|
452
|
+
#menu { display: inline-block; flex: 0 0 auto; }
|
|
453
|
+
#state { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
|
|
454
|
+
#menu-items { display: none; }
|
|
455
|
+
header[data-menu="open"] #menu-items { display: flex; flex-direction: column; gap: 6px; position: absolute; z-index: 8; top: 100%; right: 6px; min-width: 14rem; max-width: calc(100vw - 12px); padding: 8px; background: var(--panel); border: 1px solid var(--line); border-radius: 10px; box-shadow: 0 8px 24px rgba(0, 0, 0, .4); }
|
|
456
|
+
header[data-menu="open"] #menu-items > button { text-align: left; }
|
|
457
|
+
header[data-menu="open"] .text-size { display: flex; }
|
|
458
|
+
header[data-menu="open"] .text-size button { flex: 1 1 0; }
|
|
459
|
+
/* The keys: one line, and the rest behind "More". */
|
|
460
|
+
footer#keys { flex-wrap: wrap; overflow: visible; gap: 3px; padding: 4px; }
|
|
461
|
+
footer#keys > button { flex: 1 1 0; min-width: 0; padding: 6px 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
462
|
+
footer#keys > button.wide { flex: 1.4 1 0; }
|
|
463
|
+
footer#keys > #keys-more { flex: 1.3 1 0; }
|
|
464
|
+
footer#keys > button.extra { display: none; }
|
|
465
|
+
footer#keys[data-more="true"] > button.extra:not([hidden]) { display: block; order: 10; flex: 1 1 22%; }
|
|
466
|
+
/* The extra keys start a line of their own. */
|
|
467
|
+
footer#keys[data-more="true"]::after { content: ""; order: 9; flex: 0 0 100%; height: 0; }
|
|
468
|
+
/* The row is as wide as the screen: its labels grow with the text only as far as they fit. */
|
|
469
|
+
footer#keys > button { font-size: min(.8125rem, 3.4vw); }
|
|
470
|
+
/* What is wrong with the machine: two lines at most, its buttons beside. */
|
|
471
|
+
#health-strip { flex-wrap: wrap; padding: 6px 8px; gap: 4px 6px; }
|
|
472
|
+
#health-text { flex-basis: 100%; -webkit-line-clamp: 2; }
|
|
473
|
+
/* Its buttons on one line. */
|
|
474
|
+
.health-actions { flex-wrap: nowrap; gap: 4px; min-width: 0; }
|
|
475
|
+
#health-strip .health-actions button { padding: 4px 7px; white-space: nowrap; }
|
|
476
|
+
#health-text { display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; font-size: .75rem; }
|
|
477
|
+
#health-strip button { min-height: 36px; padding: 4px 8px; font-size: .75rem; }
|
|
478
|
+
footer#keys > button[data-keys="backspace"] { display: none; }
|
|
479
|
+
footer#keys[data-more="true"] > button[data-keys="backspace"] { display: block; }
|
|
480
|
+
#keys-more { display: block; }
|
|
481
|
+
#mic, #auto { order: 0; flex: 1 1 0; padding-block: 6px; }
|
|
482
|
+
#mic { flex-basis: 0; padding-block: 6px; }
|
|
483
|
+
/* Short labels for two of them; the words stay for whoever reads them aloud. */
|
|
484
|
+
footer#keys > #kbd, footer#keys > #mic { font-size: 0; }
|
|
485
|
+
#kbd::before, #mic::before { content: attr(data-short); font-size: min(.8125rem, 3.4vw); }
|
|
486
|
+
footer button.careful { order: 10; }
|
|
487
|
+
/* Ready-made answers: when the tool asks, or when asked for. */
|
|
488
|
+
#room:not([data-asking]):has(#keys[data-more="false"]) #shortcuts { display: none; }
|
|
489
|
+
}
|
|
490
|
+
#words-lang { min-height: 40px; min-width: 12rem; max-width: 100%; font: .875rem var(--sans); color: var(--ink); background: var(--bg); border: 1px solid var(--line); border-radius: 7px; padding: 6px 8px; }
|
|
491
|
+
#words-own { width: 100%; font: .8125rem ui-monospace, Menlo, Consolas, monospace; color: var(--ink); background: var(--bg); border: 1px solid var(--line); border-radius: 7px; padding: 8px; }
|
|
492
|
+
#words-all { white-space: pre-wrap; max-height: 16rem; overflow: auto; }
|
|
493
|
+
|
|
494
|
+
/* WHO GETS WHAT and FLOWS (links.js). A link's colour says what it gives;
|
|
495
|
+
the colour of a box's mark says what it is. */
|
|
496
|
+
:root {
|
|
497
|
+
--k-term: #f59e0b; --k-chat: #60a5fa; --k-both: #a78bfa; --k-read: #4ade80; --k-write: #fb7185; --k-use: #22d3ee;
|
|
498
|
+
--k-device: #7fb6e0; --k-device-bg: #172634; --k-conv: #e2b56a; --k-conv-bg: #2e2416; --k-asset: #84c99a; --k-asset-bg: #16291d; --k-pick: #fb923c;
|
|
499
|
+
}
|
|
500
|
+
:root[data-theme="light"] {
|
|
501
|
+
--k-term: #b45309; --k-chat: #2563eb; --k-both: #7c3aed; --k-read: #15803d; --k-write: #be123c; --k-use: #0e7490;
|
|
502
|
+
--k-device: #2f6f9f; --k-device-bg: #e6f0f7; --k-conv: #8a5a14; --k-conv-bg: #f8eedc; --k-asset: #3d7a4f; --k-asset-bg: #e4f2e8; --k-pick: #c2410c;
|
|
503
|
+
}
|
|
504
|
+
#links, #flows { gap: 8px; }
|
|
505
|
+
#links .panel-top .row, #flows .panel-top .row { flex-wrap: nowrap; }
|
|
506
|
+
.lk-tabs { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
|
|
507
|
+
.lk-tabs button { border-radius: 999px; padding: 5px 13px; }
|
|
508
|
+
.lk-tabs button[aria-selected="true"] { background: var(--ink); color: var(--bg); border-color: var(--ink); }
|
|
509
|
+
.lk-switch { display: inline-flex; align-items: center; gap: 6px; margin-left: auto; font-size: .8125rem; color: var(--ink2); cursor: pointer; }
|
|
510
|
+
.lk-legend { display: flex; flex-wrap: wrap; gap: 4px 14px; font-size: .75rem; color: var(--ink2); }
|
|
511
|
+
.lk-key { display: inline-flex; align-items: center; gap: 6px; }
|
|
512
|
+
.lk-key i { display: inline-block; width: 22px; border-top: 3px solid currentColor; }
|
|
513
|
+
#links .lk-legend:empty { display: none; }
|
|
514
|
+
@media (max-width: 600px) { #links .lk-legend { margin: 0 0 10px; } .lk-key i { width: 9px; height: 9px; border: 0; border-radius: 50%; background: currentColor; } }
|
|
515
|
+
.lk-key i.dash { border-top-style: dashed; }
|
|
516
|
+
.lk-key-w { color: var(--ink2); }
|
|
517
|
+
.lk-dim { color: var(--ink2); }
|
|
518
|
+
.lk-pending-key { display: inline-block; width: 18px; height: 12px; border: 1.5px dashed var(--ink2); border-radius: 4px; }
|
|
519
|
+
.lk-scroller { container-type: inline-size; overflow-x: auto; border: 1px solid var(--line); border-radius: 12px; background: var(--bg); flex: none; }
|
|
520
|
+
/* One screen high, whatever the lists: each column scrolls on its own, so both ends of a link can be in sight. */
|
|
521
|
+
.lk-board { position: relative; display: grid; gap: 0 clamp(56px, 10vw, 150px); padding: 0 14px 30px; height: clamp(320px, calc(100dvh - 250px), 900px); }
|
|
522
|
+
.lk-board.two { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
|
|
523
|
+
.lk-board.three { grid-template-columns: repeat(3, minmax(0, 1fr)); }
|
|
524
|
+
.lk-col { display: flex; flex-direction: column; gap: 10px; min-width: 0; overflow-y: auto; overflow-x: hidden; overscroll-behavior: contain; padding: 0 18px 14px 0; margin-right: -18px; scrollbar-width: thin; position: relative; z-index: 2; }
|
|
525
|
+
.lk-col h3 { position: sticky; top: 0; z-index: 3; margin: 0; padding: 10px 0 6px; font-size: .6875rem; letter-spacing: .08em; text-transform: uppercase; color: var(--ink2); background: var(--bg); }
|
|
526
|
+
.lk-gap { height: 12px; flex: none; }
|
|
527
|
+
.lk-node { position: relative; flex: none; display: flex; align-items: center; gap: 8px; border: 1.5px solid var(--line); border-radius: 10px; padding: 7px 10px; background: var(--panel); cursor: pointer; user-select: none; min-width: 0; }
|
|
528
|
+
.lk-node.pending { border-style: dashed; }
|
|
529
|
+
.lk-ic { font: 600 .75rem ui-monospace, Menlo, monospace; width: 1.9em; height: 1.9em; border-radius: 6px; display: grid; place-items: center; flex: none; }
|
|
530
|
+
.lk-node.lk-c-device .lk-ic { background: var(--k-device-bg); color: var(--k-device); }
|
|
531
|
+
.lk-node.lk-c-conversation .lk-ic { background: var(--k-conv-bg); color: var(--k-conv); }
|
|
532
|
+
.lk-node.lk-c-asset .lk-ic { background: var(--k-asset-bg); color: var(--k-asset); }
|
|
533
|
+
.lk-tx { min-width: 0; display: flex; flex-direction: column; }
|
|
534
|
+
.lk-nm { font-weight: 700; overflow-wrap: anywhere; line-height: 1.25; }
|
|
535
|
+
.lk-sb { font-size: .75rem; color: var(--ink2); }
|
|
536
|
+
@media (hover: hover) { .lk-node:hover { border-color: var(--ink2); } .lk-node.can:hover { border-color: var(--k-pick); } }
|
|
537
|
+
.lk-node.picked { border-color: var(--k-pick); box-shadow: 0 0 0 3px color-mix(in srgb, var(--k-pick) 25%, transparent); }
|
|
538
|
+
.lk-node.can { border-style: dashed; border-color: var(--ink2); }
|
|
539
|
+
.lk-node.faded { opacity: .3; }
|
|
540
|
+
.lk-cnt { margin-left: auto; flex: none; font: 700 .6875rem var(--sans); color: var(--ink2); border: 1px solid var(--line); border-radius: 999px; padding: 2px 6px; display: none; }
|
|
541
|
+
.lk-board.simple .lk-cnt { display: inline-block; }
|
|
542
|
+
/* The dot to drag from: 28px to touch, drawn 14px. */
|
|
543
|
+
.lk-handle { position: absolute; right: -14px; top: 50%; width: 28px; height: 28px; margin-top: -14px; border-radius: 50%; cursor: crosshair; touch-action: none; display: grid; place-items: center; z-index: 4; }
|
|
544
|
+
.lk-handle::after { content: ""; width: 14px; height: 14px; border-radius: 50%; background: var(--panel); border: 2px solid var(--ink2); }
|
|
545
|
+
.lk-handle:hover::after { border-color: var(--k-pick); background: var(--k-pick); }
|
|
546
|
+
.lk-edge { position: absolute; z-index: 4; transform: translateX(-50%); font: 700 .6875rem/1 var(--sans); padding: 5px 10px; border-radius: 999px; background: var(--bar); color: var(--ink2); border: 1px solid var(--line); white-space: nowrap; }
|
|
547
|
+
.lk-edge:hover { color: var(--ink); border-color: var(--ink2); }
|
|
548
|
+
.lk-edge.up { transform: translateX(-100%); }
|
|
549
|
+
/* Where the links of a box go, out of sight: named small, at the end of their hook. */
|
|
550
|
+
.lk-hook { position: absolute; z-index: 3; transform: translateY(-50%); font: 600 .6875rem/1.2 var(--sans); padding: 2px 7px; border-radius: 999px; background: var(--bar); color: var(--ink2); border: 1px solid var(--line); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
551
|
+
.lk-hook.in { transform: translate(-100%, -50%); }
|
|
552
|
+
.lk-hook.inbox { transform: translate(-100%, -50%); z-index: 4; }
|
|
553
|
+
.lk-start { display: flex; flex-direction: column; gap: 14px; }
|
|
554
|
+
.lk-hook:hover { color: var(--ink); border-color: var(--ink2); }
|
|
555
|
+
.lk-empty { display: flex; flex-direction: column; align-items: flex-start; gap: 8px; }
|
|
556
|
+
svg.lk-links { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 1; overflow: hidden; pointer-events: none; }
|
|
557
|
+
svg.lk-links path { fill: none; stroke-width: 2.6; stroke-linecap: round; }
|
|
558
|
+
svg.lk-links path.hit { stroke: transparent !important; stroke-width: 18; pointer-events: stroke; cursor: pointer; }
|
|
559
|
+
svg.lk-links path.dash { stroke-dasharray: 7 5; }
|
|
560
|
+
svg.lk-links path.later { stroke-dasharray: 2 4; opacity: .7; }
|
|
561
|
+
svg.lk-links path.away { opacity: .35; stroke-dasharray: 2 5; }
|
|
562
|
+
svg.lk-links path.dim { opacity: .12; }
|
|
563
|
+
/* Many links: all drawn, thin and pale, gathered in trunks; those of the box touched in full over them. */
|
|
564
|
+
svg.lk-links path.pale { stroke-width: 1.4; opacity: .5; }
|
|
565
|
+
svg.lk-links path.pale.dim { opacity: .14; }
|
|
566
|
+
svg.lk-links path.pale.dash { stroke-dasharray: 4 4; }
|
|
567
|
+
svg.lk-links path.pale.hook { opacity: .55; }
|
|
568
|
+
svg.lk-links path.temp { stroke: var(--k-pick); stroke-dasharray: 4 4; }
|
|
569
|
+
/* At rest: no line, each box says how many links it has; a tapped box shows its own. */
|
|
570
|
+
.lk-board.simple svg.lk-links path:not(.on):not(.temp), .lk-board.simple .lk-knob:not(.on), .lk-board.simple .lk-edge { display: none; }
|
|
571
|
+
.lk-knob { position: absolute; z-index: 3; width: 22px; height: 22px; margin: -11px 0 0 -11px; border-radius: 50%; border: 3px solid var(--bg); cursor: pointer; padding: 0; box-shadow: 0 0 0 1px var(--line); }
|
|
572
|
+
.lk-knob.dim { opacity: .2; }
|
|
573
|
+
.lk-pop { position: absolute; z-index: 6; width: min(330px, calc(100vw - 48px)); max-height: calc(100% - 16px); overflow-y: auto; background: var(--panel); border: 1px solid var(--line); border-radius: 12px; box-shadow: 0 8px 24px rgba(0, 0, 0, .35); padding: 12px 14px; display: flex; flex-direction: column; gap: 4px; }
|
|
574
|
+
.lk-pop h4 { margin: 0 0 6px; font-size: .9375rem; overflow-wrap: anywhere; }
|
|
575
|
+
.lk-pop h4 small { display: block; font-weight: 400; color: var(--ink2); font-size: .75rem; }
|
|
576
|
+
.lk-pop label { display: flex; gap: 8px; align-items: flex-start; padding: 4px 0; cursor: pointer; }
|
|
577
|
+
.lk-pop label small { display: block; color: var(--ink2); font-size: .75rem; }
|
|
578
|
+
.lk-sw { display: inline-block; width: 10px; height: 10px; border-radius: 50%; flex: none; margin: 4px 6px 0 0; }
|
|
579
|
+
.lk-note { margin: 4px 0 0; font-size: .75rem; color: var(--ink2); }
|
|
580
|
+
.lk-pop .lk-note[role="alert"] { color: var(--danger); }
|
|
581
|
+
.lk-row { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
|
|
582
|
+
.lk-pop .lk-row { justify-content: space-between; margin-top: 8px; }
|
|
583
|
+
.lk-ask { margin: 10px 0 0; font-weight: 600; }
|
|
584
|
+
.lk-rm { color: var(--danger); }
|
|
585
|
+
.lk-pop .auto-send { margin-top: 6px; }
|
|
586
|
+
.lk-card { flex: none; max-height: 32vh; overflow-y: auto; padding: 10px 12px; border: 1px solid var(--line); border-radius: 10px; background: var(--bar); font-size: .8125rem; }
|
|
587
|
+
.lk-card h3 { margin: 0 0 6px; font-size: .9375rem; display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
|
|
588
|
+
.lk-card h3 small { font-weight: 400; color: var(--ink2); }
|
|
589
|
+
.lk-card-actions { margin-left: auto; display: flex; gap: 6px; flex-wrap: wrap; }
|
|
590
|
+
.lk-card-actions button { border-radius: 999px; padding: 3px 11px; }
|
|
591
|
+
.lk-card ul { margin: 0; padding-left: 1.1rem; }
|
|
592
|
+
.lk-card li { margin: 2px 0; }
|
|
593
|
+
.lk-via { color: var(--ink2); }
|
|
594
|
+
.lk-none { color: var(--ink2); font-size: .8125rem; margin: 0; }
|
|
595
|
+
/* On a phone: no drawing. A list, then one box and its links as rows. */
|
|
596
|
+
.lk-phone { display: none; }
|
|
597
|
+
@media (max-width: 600px) {
|
|
598
|
+
#links .lk-scroller, #links-hint, #links-card, #links-tabs, .map-bar .lk-switch { display: none !important; }
|
|
599
|
+
.lk-phone { display: block; }
|
|
600
|
+
}
|
|
601
|
+
.lk-kinds { display: flex; align-items: center; gap: 6px; margin: 4px 0 12px; }
|
|
602
|
+
.lk-kinds button { flex: 1; border-radius: 999px; padding: 8px 4px; }
|
|
603
|
+
.lk-kinds button[aria-pressed="true"] { background: var(--ink); color: var(--bg); border-color: var(--ink); }
|
|
604
|
+
.lk-plist { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
|
|
605
|
+
.lk-item { display: flex; align-items: center; gap: 10px; width: 100%; text-align: left; font-weight: 400; background: var(--bar); border-radius: 12px; padding: 12px; }
|
|
606
|
+
.lk-item.pending { border-style: dashed; }
|
|
607
|
+
.lk-item .lk-tx { flex: 1; }
|
|
608
|
+
.lk-dots { display: flex; gap: 3px; flex: none; }
|
|
609
|
+
.lk-dots i { width: 9px; height: 9px; border-radius: 50%; display: block; }
|
|
610
|
+
.lk-chev { color: var(--ink2); flex: none; font-size: 1.1rem; }
|
|
611
|
+
/* The icons of the map: the chat's set (Lucide), drawn the same whatever the fonts. */
|
|
612
|
+
.lk-ic .lk-svg { width: 1.05rem; height: 1.05rem; }
|
|
613
|
+
.lk-chev .lk-svg { width: 1.1rem; height: 1.1rem; display: block; }
|
|
614
|
+
.lk-hook, .lk-edge { display: inline-flex; align-items: center; gap: 3px; }
|
|
615
|
+
.lk-arrow { width: 1em; height: 1em; flex: none; }
|
|
616
|
+
.lk-bar { margin: 4px 0; }
|
|
617
|
+
.lk-bar button { border-radius: 999px; }
|
|
618
|
+
.lk-ptitle { margin: 6px 0 0; font-size: 1.25rem; overflow-wrap: anywhere; }
|
|
619
|
+
.lk-phone h4 { margin: 16px 0 8px; font-size: .6875rem; letter-spacing: .08em; text-transform: uppercase; color: var(--ink2); }
|
|
620
|
+
.lk-phone p.lk-sb { margin: 0 0 8px; }
|
|
621
|
+
.lk-rows { display: flex; flex-direction: column; gap: 8px; }
|
|
622
|
+
.lk-prow { background: var(--bar); border: 1px solid var(--line); border-radius: 12px; padding: 10px 12px; display: flex; flex-direction: column; gap: 8px; }
|
|
623
|
+
.lk-top { display: flex; align-items: center; gap: 8px; }
|
|
624
|
+
.lk-top i { width: 10px; height: 10px; border-radius: 50%; flex: none; }
|
|
625
|
+
.lk-top b { flex: 1; min-width: 0; overflow-wrap: anywhere; }
|
|
626
|
+
.lk-x { border: 0; background: none; color: var(--ink2); font-size: 1.3rem; line-height: 1; padding: 0 6px; }
|
|
627
|
+
.lk-seg { display: flex; gap: 6px; }
|
|
628
|
+
.lk-seg button { flex: 1; padding: 8px 4px; border-width: 1.5px; color: var(--ink2); background: var(--panel); }
|
|
629
|
+
.lk-seg button[aria-pressed="true"] { border-color: currentColor; }
|
|
630
|
+
.lk-add { width: 100%; margin-top: 12px; border: 1.5px dashed var(--line); background: none; border-radius: 12px; padding: 12px; }
|
|
631
|
+
/* Flows. */
|
|
632
|
+
.lk-files { gap: 8px; }
|
|
633
|
+
.lk-tpick select { font: inherit; color: var(--ink); background: var(--bg); border: 1px solid var(--line); border-radius: 7px; padding: 5px 8px; max-width: 100%; }
|
|
634
|
+
.lk-tscroll { overflow-x: auto; border: 1px solid var(--line); border-radius: 12px; background: var(--bg); }
|
|
635
|
+
.lk-tboard { position: relative; display: grid; grid-auto-flow: column; grid-auto-columns: minmax(118px, 150px); gap: 0 34px; padding: 16px 18px 20px; width: max-content; min-width: 100%; justify-content: center; }
|
|
636
|
+
.lk-tcol { display: flex; flex-direction: column; justify-content: center; gap: 12px; position: relative; z-index: 2; }
|
|
637
|
+
.lk-tcol h5 { margin: 0 0 2px; font-size: .6875rem; letter-spacing: .08em; text-transform: uppercase; color: var(--ink2); text-align: center; }
|
|
638
|
+
.lk-tnode { display: block; border: 1.5px solid var(--line); border-radius: 10px; padding: 8px 10px; background: var(--panel); text-align: left; font-weight: 400; }
|
|
639
|
+
.lk-tnode b { display: block; overflow-wrap: anywhere; }
|
|
640
|
+
.lk-tnode small { color: var(--ink2); font-size: .75rem; }
|
|
641
|
+
.lk-tnode.lk-c-device { border-left: 4px solid var(--k-device); } .lk-tnode.lk-c-conversation { border-left: 4px solid var(--k-conv); } .lk-tnode.lk-c-asset { border-left: 4px solid var(--k-asset); }
|
|
642
|
+
.lk-tnode.pending { border-style: dashed; }
|
|
643
|
+
.lk-tnode.me { border-color: var(--k-pick); box-shadow: 0 0 0 3px color-mix(in srgb, var(--k-pick) 25%, transparent); }
|
|
644
|
+
.lk-tboard svg.lk-links path { stroke-width: 2.2; }
|
|
645
|
+
.lk-words { margin: 6px 0 0; font-size: .8125rem; }
|
|
646
|
+
.lk-words summary { cursor: pointer; color: var(--ink2); }
|
|
647
|
+
.lk-steps { margin: 6px 0 0; padding-left: 1.2rem; }
|
|
648
|
+
.lk-steps ul { padding-left: 0; list-style: none; }
|
|
649
|
+
.lk-steps li { margin: 3px 0; }
|
|
650
|
+
.lk-step { display: block; font-size: .6875rem; letter-spacing: .06em; text-transform: uppercase; color: var(--ink2); margin-top: 6px; }
|
|
651
|
+
.lk-island { margin: 0 0 16px; }
|
|
652
|
+
.lk-island h4 { margin: 0 0 6px; font-size: .9375rem; display: flex; gap: 8px; align-items: baseline; flex-wrap: wrap; }
|
|
653
|
+
.lk-island h4 small { font-weight: 400; color: var(--ink2); font-size: .75rem; }
|
|
654
|
+
.lk-island h4 .lk-row { margin-left: auto; }
|
|
655
|
+
.lk-island h4 input { font: inherit; color: var(--ink); background: var(--bg); border: 1px solid var(--line); border-radius: 7px; padding: 4px 8px; }
|
|
656
|
+
.lk-alone { margin: 4px 0 0; font-size: .8125rem; color: var(--ink2); }
|
|
657
|
+
@media (max-width: 600px) { .lk-tscroll { display: none; } .lk-words summary { display: none; } }
|
|
658
|
+
/* An import, shown whole before anything is made. */
|
|
659
|
+
.lk-preview { border: 1px solid var(--line); border-radius: 12px; padding: 12px 14px; background: var(--bar); display: flex; flex-direction: column; gap: 6px; }
|
|
660
|
+
.lk-preview h3 { margin: 0; font-size: 1rem; overflow-wrap: anywhere; }
|
|
661
|
+
.lk-preview h3 small { display: block; font-weight: 400; color: var(--ink2); font-size: .75rem; }
|
|
662
|
+
.lk-preview h4 { margin: 8px 0 0; font-size: .6875rem; letter-spacing: .08em; text-transform: uppercase; color: var(--ink2); }
|
|
663
|
+
.lk-preview select, .lk-preview input:not([type]) { font: inherit; color: var(--ink); background: var(--bg); border: 1px solid var(--line); border-radius: 7px; padding: 4px 8px; }
|
|
664
|
+
.lk-said { margin: 0; font-weight: 600; }
|
|
665
|
+
.lk-plan { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
|
|
666
|
+
.lk-plan li { padding: 6px 0; border-top: 1px solid var(--line); overflow-wrap: anywhere; }
|
|
667
|
+
.lk-plan li[data-status="refused"] { color: var(--ink2); }
|
|
668
|
+
.lk-plan p { margin: 2px 0 0; font-size: .75rem; }
|
|
669
|
+
.lk-plan .lk-row { margin-top: 4px; }
|
|
670
|
+
.lk-tag { display: inline-block; font-size: .6875rem; border-radius: 999px; padding: 1px 8px; margin-right: 6px; border: 1px solid var(--line); color: var(--ink2); }
|
|
671
|
+
.lk-tag.lk-c-device { color: var(--k-device); } .lk-tag.lk-c-conversation { color: var(--k-conv); } .lk-tag.lk-c-asset { color: var(--k-asset); }
|
|
672
|
+
.lk-text { margin-top: 4px; }
|
|
673
|
+
.lk-text small { color: var(--ink2); }
|
|
674
|
+
.lk-text pre { margin: 2px 0 0; white-space: pre-wrap; overflow-wrap: anywhere; font: .8125rem ui-monospace, Menlo, monospace; background: var(--bg); border: 1px solid var(--line); border-radius: 6px; padding: 6px 8px; max-height: 14rem; overflow: auto; }
|
|
675
|
+
.lk-plan pre { white-space: pre-wrap; overflow-wrap: anywhere; font: .75rem ui-monospace, Menlo, monospace; margin: 2px 0 0; }
|
|
676
|
+
.lk-confirm { display: flex; gap: 6px; align-items: flex-start; margin-top: 4px; font-size: .75rem; }
|
|
677
|
+
.lk-sticky { position: sticky; bottom: -14px; background: var(--bar); padding: 8px 0; }
|
|
678
|
+
.lk-job { margin: 0; padding-left: 1.2rem; font-size: .8125rem; }
|
|
679
|
+
.lk-job li[data-state="failed"] { color: var(--danger); }
|
|
680
|
+
.lk-job li[data-state="skipped"] { color: var(--ink2); }
|
|
681
|
+
.lk-job li[data-state="doing"]::marker { color: var(--brass); }
|
|
682
|
+
/* Where the board is narrow (a phone across, a tablet beside the list), the three columns still fit: names only. */
|
|
683
|
+
@container (max-width: 700px) {
|
|
684
|
+
.lk-board.three { gap: 0 40px; padding: 0 8px 30px; }
|
|
685
|
+
.lk-board.three .lk-node { padding: 5px 6px; gap: 0; flex-direction: column; align-items: flex-start; }
|
|
686
|
+
.lk-board.three .lk-ic, .lk-board.three .lk-sb { display: none; }
|
|
687
|
+
.lk-board.three .lk-node.lk-c-device { border-left: 4px solid var(--k-device); } .lk-board.three .lk-node.lk-c-conversation { border-left: 4px solid var(--k-conv); } .lk-board.three .lk-node.lk-c-asset { border-left: 4px solid var(--k-asset); }
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
.lk-shared { font-size: .75rem; font-weight: 600; color: var(--k-pick); border: 1px solid currentColor; border-radius: 999px; padding: 1px 8px; }
|
|
691
|
+
.lk-check { margin: 0; padding-left: 1.1rem; font-size: .875rem; }
|
|
692
|
+
.lk-check li[data-line="Refused"] b { color: var(--danger); }
|
|
693
|
+
.lk-own { font-size: .6875rem; font-weight: 700; letter-spacing: .04em; color: #fff; background: var(--danger); border-radius: 999px; padding: 2px 8px; margin-right: 6px; }
|
|
694
|
+
.lk-more summary { cursor: pointer; color: var(--ink2); margin-top: 6px; }
|
|
695
|
+
|
|
696
|
+
/* ---------- the three places: Conversations, Access, Settings ---------- */
|
|
697
|
+
#nav { grid-column: 1; grid-row: 2; display: flex; flex-direction: column; gap: 4px; padding: 8px 10px 10px; background: var(--panel); border-right: 1px solid var(--line); border-top: 1px solid var(--line); }
|
|
698
|
+
#nav button { display: flex; align-items: center; gap: 10px; min-height: 40px; text-align: left; background: transparent; border-color: transparent; font-weight: 600; color: var(--ink2); }
|
|
699
|
+
#nav button:hover { color: var(--ink); border-color: var(--line); }
|
|
700
|
+
#nav button[aria-current="page"] { color: var(--ink); background: var(--bar); border-color: var(--line); box-shadow: inset 3px 0 0 var(--brass); }
|
|
701
|
+
.nav-ic { width: 20px; height: 20px; flex: none; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
|
|
702
|
+
#nav button[aria-current="page"] .nav-ic { stroke: var(--brass); }
|
|
703
|
+
/* On a wide screen the list above is the menu, always there (the « button shows it when folded): the bar holds only the places of the whole. A phone keeps it: there the list is a screen of its own. */
|
|
704
|
+
@media (min-width: 701px) { #nav #nav-conversations { display: none; } }
|
|
705
|
+
@media (max-width: 700px) {
|
|
706
|
+
/* A phone: a bar along the bottom, above the system's own strip; gone inside a conversation and while typing. */
|
|
707
|
+
#nav { grid-row: 2; flex-direction: row; gap: 0; padding: 4px 6px calc(4px + env(safe-area-inset-bottom, 0)); border-right: 0; }
|
|
708
|
+
/* The bar takes the system's strip at the bottom; where it is not shown, the page keeps it clear. */
|
|
709
|
+
html:has(#nav:not([hidden])):has(#app:is([data-view="list"], [data-place="access"], [data-place="settings"])) body { padding-bottom: 0; }
|
|
710
|
+
#nav button { flex: 1 1 0; flex-direction: column; gap: 2px; min-height: 52px; padding: 4px 2px; font-size: .75rem; text-align: center; justify-content: center; border-radius: 10px; }
|
|
711
|
+
#nav button[aria-current="page"] { box-shadow: none; background: transparent; border-color: transparent; color: var(--brass); }
|
|
712
|
+
#nav .nav-ic { width: 24px; height: 24px; }
|
|
713
|
+
#app[data-view="room"][data-place="conversations"] #nav { display: none; }
|
|
714
|
+
#app:has(input:not([type=checkbox]):not([type=radio]):not([type=file]):focus, textarea:not(.xterm-helper-textarea):focus) #nav { display: none; }
|
|
715
|
+
/* Access and Settings take the whole screen: the bar of the conversation behind them is not theirs. */
|
|
716
|
+
#app:is([data-place="access"], [data-place="settings"]) #room > :is(header, #health-strip, #signin-strip, #voice-line, #shortcuts, #keys) { display: none !important; }
|
|
717
|
+
#access-close, #settings-close { display: none; }
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
/* ---------- Access: one page, three tabs ---------- */
|
|
721
|
+
#access { gap: 10px; }
|
|
722
|
+
.access-top { gap: 8px; flex-wrap: wrap; }
|
|
723
|
+
.access-top > b { font-size: 1.0625rem; }
|
|
724
|
+
.access-files { margin-left: auto; flex-wrap: nowrap; gap: 6px; }
|
|
725
|
+
/* Said where it is decided: next to Export, never in a tooltip only. */
|
|
726
|
+
#export-note { font-size: .75rem; line-height: 1.25; max-width: 13.5em; text-align: right; margin-left: auto; }
|
|
727
|
+
#export-note + .access-files { margin-left: 0; }
|
|
728
|
+
.for-badge { display: inline-flex; align-items: center; gap: 4px; padding: 2px 4px 2px 10px; border: 1px solid var(--brass); border-radius: 999px; background: rgba(210, 169, 78, .14); max-width: 100%; min-width: 0; }
|
|
729
|
+
.for-badge b { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
|
|
730
|
+
.for-badge button { border: 0; background: none; padding: 2px 8px; min-height: 28px; font-size: 1rem; line-height: 1; border-radius: 999px; color: var(--ink2); }
|
|
731
|
+
.for-badge button:hover { color: var(--ink); }
|
|
732
|
+
#flows-said:empty { display: none; }
|
|
733
|
+
/* Segmented: three tabs of one width. */
|
|
734
|
+
.seg { display: flex; padding: 3px; gap: 3px; border: 1px solid var(--line); border-radius: 10px; background: var(--bg); max-width: 32rem; flex: none; }
|
|
735
|
+
.seg button { flex: 1 1 0; border: 0; background: transparent; border-radius: 7px; min-height: 36px; color: var(--ink2); }
|
|
736
|
+
.seg button[aria-selected="true"] { background: var(--panel); color: var(--ink); box-shadow: 0 0 0 1px var(--line), 0 1px 3px rgba(0, 0, 0, .25); }
|
|
737
|
+
.pane { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
|
|
738
|
+
#access-map { gap: 8px; }
|
|
739
|
+
.map-mode { align-self: flex-start; }
|
|
740
|
+
.map-mode button { min-height: 32px; padding: 4px 14px; }
|
|
741
|
+
#access-map .lk-board { height: clamp(300px, calc(100dvh - 330px), 900px); }
|
|
742
|
+
#sharing-top { gap: 8px; }
|
|
743
|
+
#sharing-top b { font-size: 1rem; }
|
|
744
|
+
.to-access { margin-top: 2px; }
|
|
745
|
+
.to-access .hint { flex: 1 1 14rem; }
|
|
746
|
+
@media (max-width: 700px) {
|
|
747
|
+
#access { padding: 10px 12px 16px; }
|
|
748
|
+
.seg { max-width: none; }
|
|
749
|
+
.seg button { min-height: 40px; }
|
|
750
|
+
.access-top > b { font-size: 1.25rem; }
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
/* Asset and device cards fold as the chapters of a conversation do. */
|
|
754
|
+
.asset, .device.card { border: 1px solid var(--line); border-radius: 10px; background: var(--bar); padding: 0 8px 0 0; margin-top: 6px; gap: 0 8px; }
|
|
755
|
+
.asset-head { position: relative; padding: 8px 6.5rem 8px 12px; border-radius: 10px; }
|
|
756
|
+
.asset-head::after { content: "Expand"; position: absolute; right: 8px; top: 50%; transform: translateY(-50%); font-size: .75rem; font-weight: 600; color: var(--ink2); border: 1px solid var(--line); border-radius: 7px; padding: 3px 9px; }
|
|
757
|
+
.asset-head[aria-expanded="true"]::after { content: "Collapse"; }
|
|
758
|
+
.asset-head b::before { content: none; }
|
|
759
|
+
.asset > .given-row.for-row { flex-basis: 100%; margin: 0 0 0 12px; padding: 8px 0 10px; border-top: 1px dashed var(--line); }
|
|
760
|
+
.asset-inside { background: var(--panel); border-top: 1px solid var(--line); border-radius: 0 0 10px 10px; padding: 8px 12px 10px; margin-right: -8px; }
|
|
761
|
+
.asset > button:not(.asset-head) { margin: 6px 0; }
|
|
762
|
+
.git-key { padding: 8px 12px; }
|
|
763
|
+
.device.card { display: block; padding: 0; }
|
|
764
|
+
.device.card .device-head { padding: 10px 12px; min-height: 48px; }
|
|
765
|
+
.device.card .device-head b { font-size: 1rem; flex: 0 1 auto; min-width: 0; overflow-wrap: anywhere; }
|
|
766
|
+
.device-sub { flex: 1 1 12rem; font-size: .75rem; }
|
|
767
|
+
.device.card .device-head small.device-count { color: var(--brass); }
|
|
768
|
+
.card-fold { margin-left: auto; min-height: 32px !important; padding: 3px 9px; font-size: .75rem; color: var(--ink2); background: transparent; }
|
|
769
|
+
.device.card .card-body { background: var(--panel); border-top: 1px solid var(--line); border-radius: 0 0 10px 10px; padding: 4px 12px 10px; display: flex; flex-direction: column; gap: 6px; }
|
|
770
|
+
.device.card .given-row { padding-left: 0; }
|
|
771
|
+
.device-acts { padding-top: 6px; }
|
|
772
|
+
|
|
773
|
+
/* On a phone, a box of the map touched: its links rise from the bottom. */
|
|
774
|
+
.lk-sheet-wrap { position: fixed; inset: 0; z-index: 20; display: flex; align-items: flex-end; background: rgba(8, 11, 15, .55); }
|
|
775
|
+
.lk-sheet { width: 100%; max-height: 75dvh; overflow-y: auto; background: var(--panel); border-top: 1px solid var(--line); border-radius: 16px 16px 0 0; padding: 8px 16px calc(16px + env(safe-area-inset-bottom, 0)); display: flex; flex-direction: column; gap: 10px; box-shadow: 0 -8px 24px rgba(0, 0, 0, .35); }
|
|
776
|
+
.lk-sheet::before { content: ""; align-self: center; width: 40px; height: 4px; border-radius: 2px; background: var(--line); margin-bottom: 4px; }
|
|
777
|
+
.lk-sheet-top { display: flex; align-items: center; gap: 10px; }
|
|
778
|
+
.lk-sheet-top .lk-tx { flex: 1; }
|
|
779
|
+
.lk-sheet.lk-c-device .lk-ic { background: var(--k-device-bg); color: var(--k-device); }
|
|
780
|
+
.lk-sheet.lk-c-conversation .lk-ic { background: var(--k-conv-bg); color: var(--k-conv); }
|
|
781
|
+
.lk-sheet.lk-c-asset .lk-ic { background: var(--k-asset-bg); color: var(--k-asset); }
|
|
782
|
+
.lk-sheet-links { margin: 0; padding-left: 1.1rem; font-size: .875rem; display: flex; flex-direction: column; gap: 4px; }
|
|
783
|
+
.lk-sheet-acts button { flex: 1 1 0; min-height: 44px; }
|
|
784
|
+
|
|
785
|
+
/* The map's own bar: Map or Flows, then (the map only) what it shows. */
|
|
786
|
+
.map-bar { gap: 8px 14px; }
|
|
787
|
+
#access-map:has(#flows:not([hidden])) :is(#links-tabs, .map-bar .lk-switch) { display: none; }
|
|
788
|
+
.lk-show { margin-right: 2px; }
|
|
789
|
+
.lk-tabs button { min-height: 32px; padding: 4px 12px; }
|
|
790
|
+
.seg button[aria-selected="true"] { font-weight: 700; background: var(--button, #222c38); box-shadow: inset 0 -2px 0 var(--brass), 0 0 0 1px var(--line); }
|
|
791
|
+
.for-row > span:first-child { color: var(--ink2); font-size: .8125rem; }
|
|
792
|
+
.lk-kinds button { min-height: 36px; padding: 4px; }
|
|
793
|
+
@media (max-width: 700px) {
|
|
794
|
+
.access-top .access-files { order: 2; margin-left: auto; }
|
|
795
|
+
#export-note { order: 4; flex: 1 0 100%; max-width: none; margin: -4px 0 0; }
|
|
796
|
+
.access-top .for-badge { order: 3; }
|
|
797
|
+
}
|
|
798
|
+
/* On a light screen, brass words are too pale: the place shown is said in a darker brass. */
|
|
799
|
+
:root[data-theme="light"] #nav button[aria-current="page"] { color: #8a5d00; }
|
|
800
|
+
:root[data-theme="light"] #nav button[aria-current="page"] .nav-ic { stroke: #8a5d00; }
|
|
801
|
+
/* A device's card: its name and the fold on the first line, what it has and when it was seen under them. */
|
|
802
|
+
.device.card .device-head { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 2px 8px; align-items: center; }
|
|
803
|
+
.device.card .device-head > :first-child { grid-column: 1; grid-row: 1; justify-self: start; max-width: 100%; }
|
|
804
|
+
.device.card .card-fold { grid-column: 2; grid-row: 1; }
|
|
805
|
+
.device.card .device-sub { grid-column: 1 / -1; }
|
|
806
|
+
/* Access or Settings open over a conversation on a wide screen: its keys keep their room (the terminal is not
|
|
807
|
+
resized under the page) but cannot be touched by mistake. With no conversation, its bar says nothing: gone. */
|
|
808
|
+
#app:is([data-place="access"], [data-place="settings"]) #room > :is(#keys, #shortcuts) { visibility: hidden; }
|
|
809
|
+
#app[data-current=""]:is([data-place="access"], [data-place="settings"]) #room > header { display: none; }
|
|
810
|
+
|
|
811
|
+
/* The form that makes a conversation keeps its height, and the conversations
|
|
812
|
+
under it keep theirs: on a phone the whole column scrolls (seen: rows
|
|
813
|
+
squashed under the open form). */
|
|
814
|
+
#create { flex: 0 0 auto; }
|
|
815
|
+
.item { flex-shrink: 0; }
|
|
816
|
+
#list:has(> #create:not([hidden])) #items { flex: 0 0 auto; overflow: visible; }
|
|
817
|
+
|
|
818
|
+
/* ---------- Files: list or icons, changes by hand, uploads, the editor ---------- */
|
|
819
|
+
#files { --t: var(--ink2); }
|
|
820
|
+
.files-bar { display: flex; align-items: center; justify-content: space-between; gap: 8px; flex-wrap: wrap; }
|
|
821
|
+
.files-bar .path { flex: 1 1 200px; min-width: 0; }
|
|
822
|
+
.path button { overflow-wrap: anywhere; text-align: left; }
|
|
823
|
+
#files-views button { padding: 5px 12px; font-weight: 600; }
|
|
824
|
+
#files-actions { gap: 6px; }
|
|
825
|
+
#files-status { flex-basis: 100%; }
|
|
826
|
+
#files-status:empty { display: none; }
|
|
827
|
+
.files-card { display: flex; flex-direction: column; gap: 8px; padding: 10px 12px; background: var(--bar); border: 1px solid var(--line); border-radius: 10px; }
|
|
828
|
+
.files-card .sp { flex: 1; }
|
|
829
|
+
.files-card b { overflow-wrap: anywhere; }
|
|
830
|
+
#files-ask, #files-progress { position: sticky; top: 0; z-index: 2; box-shadow: 0 6px 18px rgba(0, 0, 0, .25); }
|
|
831
|
+
#files-ask { border-color: var(--brass); }
|
|
832
|
+
#files-name input { font: .875rem var(--sans); color: var(--ink); background: var(--bg); border: 1px solid var(--line); border-radius: 7px; padding: 8px 10px; min-width: 0; width: min(100%, 420px); }
|
|
833
|
+
#files-name label { font-size: .75rem; color: var(--ink2); }
|
|
834
|
+
.bar { height: 8px; border-radius: 999px; background: var(--line); overflow: hidden; }
|
|
835
|
+
.bar > span { display: block; height: 100%; width: 0; background: var(--brass); transition: width .2s; }
|
|
836
|
+
@media (prefers-reduced-motion: reduce) { .bar > span { transition: none; } }
|
|
837
|
+
|
|
838
|
+
/* One entry: its row (or tile), its "..." button, and its actions when opened. */
|
|
839
|
+
.entry { position: relative; display: flex; flex-wrap: wrap; align-items: center; min-width: 0; }
|
|
840
|
+
#files-rows[data-view="list"] .entry { border-top: 1px solid var(--line); }
|
|
841
|
+
#files-rows[data-view="list"] .entry .file { flex: 1 1 0; border-top: 0; }
|
|
842
|
+
.entry .more { flex: 0 0 auto; min-width: 40px; padding: 4px 8px; font-size: 1.125rem; line-height: 1; background: transparent; border-color: transparent; color: var(--ink2); }
|
|
843
|
+
.entry .more:hover, .entry .more[aria-expanded="true"] { border-color: var(--line); background: var(--button, #222c38); color: var(--ink); }
|
|
844
|
+
.entry .acts { flex-basis: 100%; display: flex; flex-wrap: wrap; align-items: center; gap: 6px; padding: 4px 0 10px 44px; }
|
|
845
|
+
.entry .acts label { font-size: .75rem; color: var(--ink2); flex-basis: 100%; }
|
|
846
|
+
.entry .acts select { font: .875rem var(--sans); color: var(--ink); background: var(--bg); border: 1px solid var(--line); border-radius: 7px; padding: 7px 9px; min-height: 36px; max-width: 100%; }
|
|
847
|
+
.entry .acts .sure { margin: 0; flex-basis: 100%; color: var(--ink); font-weight: 600; }
|
|
848
|
+
.entry .acts .hint { flex-basis: 100%; }
|
|
849
|
+
.entry.dragging { opacity: .45; }
|
|
850
|
+
.drop-on, .path button.drop-on { outline: 2px dashed var(--brass); outline-offset: -2px; background: rgba(210, 169, 78, .16) !important; }
|
|
851
|
+
#files-rows > form { flex-basis: 100%; }
|
|
852
|
+
|
|
853
|
+
/* ICONS: a grid of tiles; a picture is its own thumbnail. */
|
|
854
|
+
#files-rows[data-view="icons"] { display: grid; grid-template-columns: repeat(auto-fill, minmax(118px, 1fr)); gap: 10px; align-items: start; }
|
|
855
|
+
#files-rows[data-view="icons"] > form { grid-column: 1 / -1; }
|
|
856
|
+
#files-rows[data-view="icons"] .entry { display: block; }
|
|
857
|
+
#files-rows[data-view="icons"] .entry.open { z-index: 3; }
|
|
858
|
+
#files-rows[data-view="icons"] .entry .acts { position: absolute; top: calc(100% - 4px); left: 0; z-index: 3; width: 240px; padding: 8px; flex-direction: column; align-items: stretch; background: var(--panel); border: 1px solid var(--line); border-radius: 10px; box-shadow: 0 10px 28px rgba(0, 0, 0, .35); }
|
|
859
|
+
#files-rows[data-view="icons"] .entry .acts.toward-left { left: auto; right: 0; }
|
|
860
|
+
#files-rows[data-view="icons"] .entry .acts button { text-align: left; }
|
|
861
|
+
/* A mouse: the "..." of a tile shows on the tile pointed at, or when it has the focus. */
|
|
862
|
+
@media (pointer: fine) {
|
|
863
|
+
#files-rows[data-view="icons"] .entry:not(:hover):not(:focus-within):not(.open) > .more { opacity: 0; }
|
|
864
|
+
}
|
|
865
|
+
#files-rows[data-view="icons"] .file { display: flex; flex-direction: column; align-items: center; gap: 4px; width: 100%; padding: 8px 6px; border: 1px solid transparent; border-radius: 10px; text-align: center; min-height: 0; }
|
|
866
|
+
#files-rows[data-view="icons"] .file:hover, #files-rows[data-view="icons"] .file:focus-visible { border-color: var(--line); background: var(--bar); }
|
|
867
|
+
#files-rows[data-view="icons"] .look { display: flex; align-items: center; justify-content: center; width: 100%; height: 92px; border-radius: 8px; overflow: hidden; }
|
|
868
|
+
#files-rows[data-view="icons"] .look img { max-width: 100%; max-height: 100%; object-fit: contain; border-radius: 6px; background: repeating-conic-gradient(var(--bar) 0 25%, var(--panel) 0 50%) 0 0 / 14px 14px; }
|
|
869
|
+
#files-rows[data-view="icons"] .label { display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; overflow-wrap: anywhere; font-size: .8125rem; line-height: 1.3; width: 100%; }
|
|
870
|
+
#files-rows[data-view="icons"] .file small { font-size: .6875rem; }
|
|
871
|
+
#files-rows[data-view="icons"] .entry > .more { position: absolute; top: 4px; right: 4px; min-width: 34px; min-height: 34px; padding: 2px 6px; background: var(--panel); border-color: var(--line); }
|
|
872
|
+
.icon { position: relative; display: inline-flex; align-items: center; justify-content: center; width: 58px; height: 68px; color: var(--t); }
|
|
873
|
+
.file[data-folder="true"] .icon { width: 72px; height: 60px; }
|
|
874
|
+
.icon svg { width: 100%; height: 100%; overflow: visible; }
|
|
875
|
+
.icon .body { fill: color-mix(in srgb, currentColor 16%, var(--panel)); stroke: currentColor; stroke-width: 1.6; stroke-linejoin: round; }
|
|
876
|
+
.icon .line { fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linejoin: round; }
|
|
877
|
+
.icon .ext { position: absolute; left: 0; right: 0; bottom: 12px; font: 700 .625rem var(--sans); letter-spacing: .04em; text-align: center; color: currentColor; }
|
|
878
|
+
/* Drawn with the chat's icons (Lucide): the icon, its kind written under it. */
|
|
879
|
+
.icon[data-drawn="lucide"] { flex-direction: column; gap: 2px; }
|
|
880
|
+
.icon[data-drawn="lucide"] svg { width: 46px; height: 46px; stroke-width: 1.5; fill: color-mix(in srgb, currentColor 10%, transparent); }
|
|
881
|
+
.file[data-folder="true"] .icon[data-drawn="lucide"] svg { width: 60px; height: 52px; }
|
|
882
|
+
.icon[data-drawn="lucide"] .ext { position: static; }
|
|
883
|
+
.icon.file-ic { width: 22px; height: 22px; flex: none; }
|
|
884
|
+
.icon.file-ic svg { width: 22px; height: 22px; stroke-width: 1.8; fill: none; }
|
|
885
|
+
.icon[data-type="folder"] { color: var(--brass); }
|
|
886
|
+
.icon[data-type="image"] { color: #4fa3e0; }
|
|
887
|
+
.icon[data-type="pdf"] { color: #e5605a; }
|
|
888
|
+
.icon[data-type="code"] { color: #9a86f0; }
|
|
889
|
+
.icon[data-type="sheet"] { color: #3fb27f; }
|
|
890
|
+
.icon[data-type="doc"] { color: #5b8ff0; }
|
|
891
|
+
.icon[data-type="archive"] { color: #c9a227; }
|
|
892
|
+
.icon[data-type="audio"] { color: #de7fb7; }
|
|
893
|
+
.icon[data-type="video"] { color: #e08a4f; }
|
|
894
|
+
:root[data-theme="light"] .icon[data-type="image"] { color: #1f6fb2; }
|
|
895
|
+
:root[data-theme="light"] .icon[data-type="pdf"] { color: #b3261e; }
|
|
896
|
+
:root[data-theme="light"] .icon[data-type="code"] { color: #6247c9; }
|
|
897
|
+
:root[data-theme="light"] .icon[data-type="sheet"] { color: #1f7a5a; }
|
|
898
|
+
:root[data-theme="light"] .icon[data-type="doc"] { color: #2a5fc9; }
|
|
899
|
+
:root[data-theme="light"] .icon[data-type="archive"] { color: #8a6d0b; }
|
|
900
|
+
:root[data-theme="light"] .icon[data-type="audio"] { color: #a83c7a; }
|
|
901
|
+
:root[data-theme="light"] .icon[data-type="video"] { color: #a3581a; }
|
|
902
|
+
:root[data-theme="light"] .icon[data-type="folder"] { color: #9a7220; }
|
|
903
|
+
|
|
904
|
+
/* Dropped from the computer: the whole sheet says where it goes. */
|
|
905
|
+
#files-drop { position: absolute; left: 8px; right: 8px; z-index: 4; display: flex; align-items: center; justify-content: center; padding: 20px; border: 3px dashed var(--brass); border-radius: 14px; background: color-mix(in srgb, var(--panel) 82%, transparent); pointer-events: none; }
|
|
906
|
+
#files-drop[data-allowed="false"] { border-color: var(--ink2); }
|
|
907
|
+
#files-drop p { margin: 0; font-size: 1.125rem; font-weight: 600; text-align: center; overflow-wrap: anywhere; max-width: 32ch; }
|
|
908
|
+
|
|
909
|
+
/* The editor: the text, its lines, Save and Cancel. */
|
|
910
|
+
#preview-body:has(> .editor) { display: flex; flex-direction: column; gap: 8px; overflow: hidden; }
|
|
911
|
+
.editor { flex: 1 1 auto; min-height: 200px; width: 100%; resize: none; font: .8125rem/1.5 ui-monospace, Menlo, Consolas, monospace; tab-size: 4; color: var(--ink); background: var(--bg); border: 1px solid var(--line); border-radius: 8px; padding: 10px 12px; white-space: pre; overflow: auto; }
|
|
912
|
+
.editor:focus-visible { outline: 2px solid var(--brass); outline-offset: 0; }
|
|
913
|
+
.edit-bar { gap: 8px; }
|
|
914
|
+
.edit-bar small { flex: 1 1 160px; }
|
|
915
|
+
.edit-ask { border-color: var(--warn); }
|
|
916
|
+
@media (max-width: 700px) {
|
|
917
|
+
#files-rows[data-view="icons"] { grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)); gap: 6px; }
|
|
918
|
+
#files-rows[data-view="icons"] .look { height: 78px; }
|
|
919
|
+
#files-rows[data-view="icons"] .entry .acts { width: min(240px, calc(100vw - 40px)); }
|
|
920
|
+
.entry .acts { padding-left: 0; }
|
|
921
|
+
.entry .more { min-height: 44px; min-width: 44px; }
|
|
922
|
+
#files-actions { gap: 6px 6px; }
|
|
923
|
+
}
|
|
924
|
+
|
|
925
|
+
.entry .acts .acts-name { display: none; overflow-wrap: anywhere; font-size: .8125rem; }
|
|
926
|
+
#files-rows[data-view="icons"] .entry .acts .acts-name { display: block; padding: 2px 4px 4px; }
|
|
927
|
+
#files-actions .short { display: none; }
|
|
928
|
+
@media (max-width: 700px) {
|
|
929
|
+
/* One row of short labels on a phone: the files come first. */
|
|
930
|
+
#files-actions button { flex: 1 1 0; min-width: 0; padding-inline: 6px; }
|
|
931
|
+
#files-actions .long { display: none; }
|
|
932
|
+
#files-actions .short { display: inline; }
|
|
933
|
+
}
|
|
934
|
+
.diff { margin: 0; max-height: 40vh; overflow: auto; font: .75rem/1.45 ui-monospace, Menlo, Consolas, monospace; background: var(--bg); border: 1px solid var(--line); border-radius: 8px; padding: 8px 0; white-space: pre-wrap; overflow-wrap: anywhere; }
|
|
935
|
+
.diff span { display: block; padding: 0 10px; }
|
|
936
|
+
.diff .add { background: color-mix(in srgb, var(--ok) 18%, transparent); }
|
|
937
|
+
.diff .del { background: color-mix(in srgb, var(--danger) 18%, transparent); }
|
|
938
|
+
.diff .gap { color: var(--ink2); }
|
|
939
|
+
/* While a text is edited, Save is the main action: Download steps back. */
|
|
940
|
+
/* What is being edited is not what was read: no copy of the old text then. */
|
|
941
|
+
#viewer[data-editing="true"] #preview-copy { display: none; }
|
|
942
|
+
#viewer[data-editing="true"] #preview-download { background: var(--button, #222c38); color: var(--ink); border: 1px solid var(--line); }
|
|
943
|
+
/* Read-only said plainly, where the buttons would be. */
|
|
944
|
+
#files-readonly { padding: 8px 10px; border: 1px dashed var(--line); border-radius: 8px; background: var(--bar); color: var(--ink); font-size: .8125rem; }
|
|
945
|
+
/* What its tool is told about where it is: one quiet line, the text behind "see". */
|
|
946
|
+
#guide-box { margin: 8px 0 4px; }
|
|
947
|
+
.guide-line { margin: 0; color: var(--ink2); font-size: .8125rem; }
|
|
948
|
+
button.inline { background: none; border: 0; padding: 4px 2px; min-height: 0; color: var(--ink); font: inherit; font-weight: 600; text-decoration: underline; text-underline-offset: 3px; }
|
|
949
|
+
button.inline:hover { color: var(--brass); }
|
|
950
|
+
#guide-shown { display: flex; flex-direction: column; gap: 6px; margin-top: 6px; }
|
|
951
|
+
#guide-text { margin: 0; white-space: pre-wrap; overflow-wrap: anywhere; font: .75rem/1.5 ui-monospace, Menlo, Consolas, monospace; color: var(--ink); background: var(--bg); border: 1px solid var(--line); border-radius: 8px; padding: 8px 10px; max-height: 22rem; overflow: auto; }
|
|
952
|
+
#guide-shown label { font-size: .75rem; color: var(--ink2); }
|
|
953
|
+
#guide-lines { width: 100%; min-height: 4.5rem; resize: vertical; font: inherit; padding: .5rem .6rem; border-radius: 8px; border: 1px solid var(--line); background: var(--bg); color: var(--ink); }
|
|
954
|
+
#guide-said:empty { display: none; }
|
|
955
|
+
|
|
956
|
+
/* THIS SERVER (Settings): a meter per resource, the reserve marked on it,
|
|
957
|
+
what takes the room under it. Status colours carry a word too ("Short"). */
|
|
958
|
+
#settings-server, #server-disks { display: grid; gap: 14px; outline: none; }
|
|
959
|
+
.server-block { display: grid; gap: 6px; }
|
|
960
|
+
.server-head { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
|
|
961
|
+
.server-figures { color: var(--ink2); font-size: .8125rem; margin-left: auto; font-variant-numeric: tabular-nums; }
|
|
962
|
+
.server-state { font-size: .75rem; font-weight: 700; color: var(--warn); border: 1px solid currentColor; border-radius: 999px; padding: 0 7px; }
|
|
963
|
+
.server-meter { position: relative; height: 10px; border-radius: 5px; background: var(--bar); border: 1px solid var(--line); overflow: hidden; }
|
|
964
|
+
.server-meter .fill { position: absolute; inset: 0 auto 0 0; border-radius: 4px; background: var(--ok); }
|
|
965
|
+
.server-meter[data-level="warn"] .fill { background: var(--warn); }
|
|
966
|
+
.server-meter[data-level="bad"] .fill { background: var(--danger); }
|
|
967
|
+
.server-meter .zone { position: absolute; top: 0; bottom: 0; right: 0; background: repeating-linear-gradient(135deg, transparent 0 3px, color-mix(in srgb, var(--ink2) 45%, transparent) 3px 5px); }
|
|
968
|
+
.server-meter .mark { position: absolute; top: -1px; bottom: -1px; width: 2px; margin-left: -1px; background: var(--ink); opacity: .7; }
|
|
969
|
+
.server-note { margin: 0; font-size: .75rem; color: var(--ink2); }
|
|
970
|
+
.server-parts { display: grid; grid-template-columns: 1fr auto; gap: 2px 16px; margin: 2px 0 0; font-size: .8125rem; max-width: 30rem; }
|
|
971
|
+
.server-parts dt { margin: 0; font-weight: 600; min-width: 0; overflow-wrap: anywhere; }
|
|
972
|
+
.server-parts dd { margin: 0; text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
|
|
973
|
+
.server-parts .sub { font-weight: normal; color: var(--ink2); }
|
|
974
|
+
.server-parts dt.sub { padding-left: 14px; }
|
|
975
|
+
.reserve-row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px; }
|
|
976
|
+
.reserve-row label { display: inline-flex; align-items: center; gap: 6px; }
|
|
977
|
+
.reserve-row input { width: 5.5em; min-height: 40px; font: .875rem var(--sans); color: var(--ink); background: var(--bg); border: 1px solid var(--line); border-radius: 7px; padding: 7px 9px; }
|
|
978
|
+
|
|
979
|
+
/* UPDATES (Settings): the version, one line of state, three settings, the way back. */
|
|
980
|
+
#updates { display: grid; gap: 10px; outline: none; }
|
|
981
|
+
.updates-head { display: flex; align-items: center; flex-wrap: wrap; gap: 6px 12px; }
|
|
982
|
+
#updates-state { color: var(--ink2); font-size: .8125rem; flex: 1 1 10rem; min-width: 0; overflow-wrap: anywhere; }
|
|
983
|
+
.updates-news { margin: 0; font-size: .8125rem; padding: 8px 10px; border-radius: 8px; border: 1px solid var(--warn); background: var(--bar); overflow-wrap: anywhere; }
|
|
984
|
+
.updates-grid { display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: center; gap: 8px 14px; max-width: 30rem; }
|
|
985
|
+
.updates-grid select, .updates-window input { min-height: 40px; font: .875rem var(--sans); color: var(--ink); background: var(--bg); border: 1px solid var(--line); border-radius: 7px; padding: 6px 8px; max-width: 100%; }
|
|
986
|
+
.updates-window { display: inline-flex; align-items: center; flex-wrap: wrap; gap: 6px; color: var(--ink2); font-size: .8125rem; }
|
|
987
|
+
#updates-back { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
|
|
988
|
+
#updates-back .hint { margin: 0; }
|
|
989
|
+
.updates-history { list-style: none; margin: 6px 0 0; padding: 0; display: grid; gap: 6px; font-size: .8125rem; }
|
|
990
|
+
.updates-history li { display: grid; grid-template-columns: auto 1fr; gap: 0 10px; }
|
|
991
|
+
.updates-history time { color: var(--ink2); font-variant-numeric: tabular-nums; white-space: nowrap; }
|
|
992
|
+
.updates-history small { grid-column: 2; color: var(--ink2); overflow-wrap: anywhere; }
|
|
993
|
+
.updates-history [data-result="rolled-back"], .updates-history [data-result="failed"] { color: var(--danger); }
|
|
994
|
+
|
|
995
|
+
/* The small gauge at the bottom of the list, only when the server is short of room. */
|
|
996
|
+
#server-gauge { flex: 0 0 auto; cursor: pointer; display: grid; gap: 4px; width: 100%; padding: 8px 10px; text-align: left; font-size: .75rem; background: var(--bar); border: 1px solid var(--warn); border-radius: 8px; color: var(--ink); }
|
|
997
|
+
#server-gauge .gauge-title { font-weight: 700; color: var(--warn); }
|
|
998
|
+
#server-gauge .gauge-line { display: grid; grid-template-columns: 4.2em 1fr auto; align-items: center; gap: 8px; }
|
|
999
|
+
#server-gauge .gauge-bar { height: 6px; border-radius: 3px; background: color-mix(in srgb, var(--ink2) 35%, var(--panel)); overflow: hidden; }
|
|
1000
|
+
#server-gauge .gauge-more { color: var(--ink2); font-weight: 600; }
|
|
1001
|
+
#server-gauge:hover .gauge-more { color: var(--ink); }
|
|
1002
|
+
#server-gauge .gauge-bar > span { display: block; height: 100%; background: var(--ok); }
|
|
1003
|
+
#server-gauge [data-level="warn"] .gauge-bar > span { background: var(--warn); }
|
|
1004
|
+
#server-gauge [data-level="bad"] .gauge-bar > span { background: var(--danger); }
|
|
1005
|
+
#server-gauge .gauge-n { color: var(--ink2); font-variant-numeric: tabular-nums; white-space: nowrap; }
|
|
1006
|
+
#server-gauge [data-level="ok"] .gauge-word { color: var(--ink2); }
|