Repository navigation
Expand file tree
/
Copy pathchat.css
More file actions
307 lines (307 loc) · 26.7 KB
/
Copy pathchat.css
File metadata and controls
307 lines (307 loc) · 26.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
/* The chat: a button at the foot of the page and the panel it opens. The button's colors and
face are the tokens', so it follows the theme where an image could not; the accent is --c-mid,
what every control in the family is. The panel is the tooling's terminal, below, a sheet on a
phone and a card on a desk. */
.rbchat-open{position:fixed;right:max(1rem,env(safe-area-inset-right));bottom:max(1rem,env(safe-area-inset-bottom));z-index:60;
display:inline-flex;align-items:center;gap:.5rem;padding:.6rem .95rem;border-radius:999px;
border:1px solid var(--rule);background:var(--raise);color:var(--ink);cursor:pointer;
font:inherit;font-size:.92rem;box-shadow:0 6px 24px var(--deck-drop)}
.rbchat-open svg{color:var(--c-mid)}
.rbchat-open:hover,.rbchat-open:focus-visible{border-color:var(--c-mid);outline:none}
.rbchat-open:focus-visible{box-shadow:0 0 0 3px var(--press)}
/* The chat is the tooling's terminal, as companygraph.io's /cli/ draws its .term. Its colors are
the terminal's own, the `--t-*` tokens, which the one modal reads too. The page's tokens are
defined again inside the panel from the terminal's, so every rule below that reads a token,
and Mermaid, which reads them from the figure, draws in the terminal's colors with no second
copy of each rule. Dark by default and light where the page is, as the tokens are. */
.rbchat{--ground:var(--t-bg);--raise:var(--t-top);--rule:var(--t-line);--ink:var(--t-ink);--dim:var(--t-dim);--c-mid:var(--t-accent);--c-firm:var(--t-strong);--press:var(--t-sel);
position:fixed;right:max(1rem,env(safe-area-inset-right));bottom:max(1rem,env(safe-area-inset-bottom));z-index:61;
width:min(31rem,calc(100vw - 2rem));height:min(46rem,calc(100vh - 2rem));display:flex;flex-direction:column;
background:var(--t-bg);color:var(--t-ink);border:1.5px solid var(--t-edge);border-radius:12px;
box-shadow:0 18px 60px var(--deck-drop);overflow:hidden;
font-family:"Plex Mono",ui-monospace,Menlo,monospace;font-size:.8rem;line-height:1.55}
.rbchat[hidden]{display:none}
/* The panel's empty frame, painted from the first frame of a page the visitor arrives at with the
chat open, until chat.js has built the panel over it: theme boot sets `data-chat-waiting` to the
host, and a stored size, before anything paints. The same place and size as the panel, its
title bar band and its title where the panel's head puts them — the band 40px, as measured on
the built panel, and the title the head's padding in and where the built head's title stands,
measured, 2px below the band's middle — so the page never shows a frame without the panel and
nothing in the bar moves when the panel arrives. A page whose chat.js never comes lets it go
after four seconds rather than holding an empty frame over the page. */
html[data-chat-waiting]::after{content:"ask \00b7 " attr(data-chat-waiting);position:fixed;z-index:61;box-sizing:border-box;
right:max(1rem,env(safe-area-inset-right));bottom:max(1rem,env(safe-area-inset-bottom));
width:min(var(--rbchat-kept-w,31rem),calc(100vw - 2rem));height:min(var(--rbchat-kept-h,46rem),calc(100vh - 2rem));
padding:2px 1rem 0 1.2rem;border:1.5px solid var(--t-edge);border-radius:12px;box-shadow:0 18px 60px var(--deck-drop);
background:linear-gradient(var(--t-top),var(--t-top)) 0 0/100% 40px no-repeat,var(--t-bg);
font:400 .8rem/40px "Plex Mono",ui-monospace,Menlo,monospace;color:var(--t-dim);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
pointer-events:none;animation:rbchat-waited 0s linear 4s forwards}
@keyframes rbchat-waited{to{visibility:hidden}}
/* The corner that sizes the panel: the top left, the one corner that can move while the panel
stays pinned to the bottom right. Drag, arrow keys when focused, double-click back to the default. */
.rbchat-grip{position:absolute;top:0;left:0;width:18px;height:18px;z-index:2;cursor:nwse-resize;
border-top:2px solid var(--t-dot);border-left:2px solid var(--t-dot);border-top-left-radius:12px;background:none;touch-action:none}
.rbchat-grip:hover,.rbchat-grip.dragging{border-color:var(--t-accent)}
.rbchat-grip:focus-visible{outline:2px solid var(--t-accent);outline-offset:2px}
.rbchat-head{display:flex;align-items:center;gap:.45rem;padding:.6rem .8rem .6rem 1.2rem;background:var(--t-top)}
.rbchat-head h2{margin:0 auto 0 0;font:inherit;font-weight:400;color:var(--t-dim);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.rbchat-close{border:0;background:none;color:var(--t-dim);font:inherit;font-size:1rem;line-height:1;cursor:pointer;padding:.15rem .4rem;border-radius:5px}
.rbchat-new{border:0;background:none;color:var(--t-dim);line-height:0;cursor:pointer;padding:.3rem;border-radius:5px;margin-left:auto;margin-right:.2rem}
.rbchat-new[hidden]{display:none}
.rbchat-new:hover,.rbchat-new:focus-visible,.rbchat-close:hover,.rbchat-close:focus-visible{color:var(--t-ink);outline:1.5px solid var(--t-accent);outline-offset:1px}
/* The command line: the prompt, the field in the terminal's strong ink, and the keys under it. */
.rbchat-form{display:flex;align-items:flex-start;gap:.6em;padding:.55rem 1.1rem .1rem;border-top:1px solid var(--t-line)}
.rbchat-p{color:var(--t-accent);font-weight:600;line-height:1.55;padding-top:.05rem}
.rbchat-form textarea{flex:1;min-width:0;resize:none;border:0;background:none;padding:0;margin:0;outline:none;
font:inherit;font-size:.85rem;line-height:1.55;color:var(--t-strong);caret-color:var(--t-accent)}
.rbchat-form textarea::placeholder{color:var(--t-dim)}
.rbchat-form textarea:disabled{opacity:.6}
.rbchat-keys{margin:0;padding:.2rem 1.1rem .55rem;font-size:.72rem;color:var(--t-dim);white-space:pre-wrap}
/* The note under a header control: what the family's .tip says on a chip, in the same box, drawn
by the stylesheet because card.js is not on every page the chat is. It hangs below and to the
left of its button, since the panel clips above its header and the buttons sit at its right
edge. It shows on hover and on keyboard focus, never on a tap's focus. */
.rbchat-new,.rbchat-close{position:relative}
.rbchat-new[data-tip]::after,.rbchat-close[data-tip]::after{content:attr(data-tip);top:calc(100% + .45rem);right:0;white-space:nowrap}
.rbchat-new[data-tip]::after,.rbchat-close[data-tip]::after,.rbchat-note{position:absolute;z-index:3;
pointer-events:none;opacity:0;transform:translateY(-2px);transition:opacity .12s ease,transform .12s ease;
background:var(--raise);border:1px solid var(--rule);border-radius:6px;padding:.42rem .62rem;
box-shadow:0 6px 18px var(--deck-drop);font-family:inherit;font-size:.8rem;font-weight:400;line-height:1.35;letter-spacing:0;color:var(--ink)}
.rbchat-new:hover::after,.rbchat-new:focus-visible::after,.rbchat-close:hover::after,.rbchat-close:focus-visible::after{opacity:1;transform:none}
@media (hover:none){.rbchat-new[data-tip]::after,.rbchat-close[data-tip]::after{display:none}}
@media (prefers-reduced-motion:reduce){.rbchat-new[data-tip]::after,.rbchat-close[data-tip]::after,.rbchat-note{transition:none}}
/* The same box as a claim's note: one element, placed by chat.js under the claim it describes,
in the panel, so it wraps where the header's note keeps one line. */
.rbchat-note{max-width:min(20rem,calc(100% - 1.5rem))}
.rbchat-note.show{opacity:1;transform:none}
.rbchat-note .n{font-weight:600}
/* A claim the evidence does not carry: a dotted underline, tinted while it is hovered or focused.
--t-part is a partly backed claim's and never text's; every other mark is --t-bad. */
.rbchat-claim{text-decoration:underline dotted 1.5px;text-underline-offset:3px;cursor:help;border-radius:2px}
.rbchat-claim.part{text-decoration-color:var(--t-part)}.rbchat-claim.off{text-decoration-color:var(--t-bad)}
.rbchat-claim.part.on{background:color-mix(in srgb,var(--t-part) 14%,transparent)}.rbchat-claim.off.on{background:color-mix(in srgb,var(--t-bad) 14%,transparent)}
.rbchat-claim:focus-visible{outline:1px solid var(--t-accent);outline-offset:1px}
.rbchat-claims{margin:.45rem 0 0;padding-top:.4rem;border-top:1px dashed var(--t-line);font-size:.74rem;color:var(--t-dim)}
.rbchat-notice code{font-family:"Plex Mono",ui-monospace,Menlo,monospace;font-size:.95em;color:var(--ink)}
.rbchat-log{flex:1;overflow-y:auto;padding:1rem 1.1rem .5rem;display:flex;flex-direction:column;gap:.15rem}
.rbchat-msg{overflow-wrap:anywhere}
/* A question is a prompt line, in the terminal's strong ink. */
.rbchat-user{margin-top:1rem;color:var(--t-strong);white-space:pre-wrap}
.rbchat-user::before{content:"\203a ";color:var(--t-accent)}
.rbchat-spin{margin:.3rem 0 0;color:var(--t-dim)}
.rbchat-frame{display:inline-block;width:1ch;color:var(--t-accent)}
/* A finished answer, as the tooling prints a finished step: a rail in the terminal's green and a
head line with the tick, on a card a step lighter than the terminal, so the one thing the model
wrote stands apart from the question and the menus around it. It has no animation of any kind. */
/* A question a link carries, waiting for the visitor: a card framed as an answer is, its edge the
accent at 3px where an answer's is the state color at 1.5px, its line in the accent as a thing
to act on, and one ring as it arrives. The accent is what every control is; --t-part is not
used, since in this panel it underlines a claim the evidence carries only in part. */
.rbchat-ask{margin:.2rem 0 1rem;display:grid;gap:.55rem;padding:.7rem .9rem .8rem;background:var(--t-card);border:1px solid var(--t-edge);border-left:3px solid var(--t-accent);border-radius:0 8px 8px 0}
.rbchat-ask p{margin:0}
.rbchat-ask-from{color:var(--t-accent)}
.rbchat-ask-q{color:var(--t-strong);white-space:pre-wrap;overflow-wrap:anywhere;background:var(--t-sel);padding:.45rem .7rem;border-radius:6px}
.rbchat-ask-q::before{content:"\203a ";color:var(--t-accent)}
.rbchat-ask-row{display:flex;gap:.45rem;flex-wrap:wrap}
.rbchat-ask-row button{font:inherit;font-size:.95em;padding:.3rem .65rem;border-radius:6px;border:1px solid var(--t-line);background:transparent;color:var(--t-ink);cursor:pointer}
.rbchat-ask-row button:hover{border-color:var(--t-accent)}
.rbchat-ask-row button:focus-visible{outline:2px solid var(--t-accent);outline-offset:2px}
.rbchat-ask-row .rbchat-ask-go{background:var(--t-accent);border-color:var(--t-accent);color:var(--t-bg);font-weight:600}
@media (prefers-reduced-motion:no-preference){
.rbchat-ask{animation:rbchat-ask-ring 1.6s ease-out .3s 1 both}
@keyframes rbchat-ask-ring{0%{box-shadow:0 0 0 0 color-mix(in srgb,var(--t-accent) 55%,transparent)}100%{box-shadow:0 0 0 10px color-mix(in srgb,var(--t-accent) 0%,transparent)}}
}
.rbchat-assistant{margin:.4rem 0 0 .35rem;padding:.55rem .9rem .55rem .95rem;border-left:1.5px solid var(--t-good);background:var(--t-card);border-radius:0 8px 8px 0}
.rbchat-done{margin:0 0 .35rem;color:var(--t-dim)}
.rbchat-tick{color:var(--t-good)}
/* The answer's text reads as it always has: the page's own face, dim as every page's prose is,
a bold run in the strong ink and a link in the accent. Everything around it is mono. */
.rbchat-body{font-family:"Instrument Sans",ui-sans-serif,system-ui,-apple-system,sans-serif;font-size:.95rem;line-height:1.5;color:var(--t-dim)}
.rbchat-body p{margin:0 0 .6rem}.rbchat-body p:last-child{margin-bottom:0}
.rbchat-body strong{color:var(--t-strong)}
.rbchat-body code{font-family:"Plex Mono",ui-monospace,Menlo,monospace;font-size:.88em;background:var(--t-sel);padding:.05em .3em;border-radius:4px;color:var(--t-ink)}
/* A list's marker is dim, never the accent: in the terminal an accent number is a row to pick. */
.rbchat-body ul,.rbchat-body ol{list-style:none;margin:0 0 .6rem;padding:0}
.rbchat-body ol{counter-reset:rbchat-n}
.rbchat-body li{position:relative;padding-left:2.2ch;margin:.12rem 0}
.rbchat-body ul > li::before{position:absolute;left:0;content:"\00b7";color:var(--t-dim);font-family:"Plex Mono",ui-monospace,Menlo,monospace;font-weight:600}
.rbchat-body ol > li{counter-increment:rbchat-n}
.rbchat-body ol > li::before{position:absolute;left:0;content:counter(rbchat-n) ".";color:var(--t-dim);font-family:"Plex Mono",ui-monospace,Menlo,monospace}
/* A table stays in mono whatever the answer's face: columns are what a terminal draws best. */
.rbchat-body table{border-collapse:collapse;margin:.2rem 0 .6rem;display:block;overflow-x:auto;max-width:100%;
font-family:"Plex Mono",ui-monospace,Menlo,monospace;font-size:.78rem;color:var(--t-ink)}
.rbchat-body th{color:var(--t-dim);font-weight:400;text-align:left;border-bottom:1px solid var(--t-line);padding:.15rem .8rem .25rem 0;vertical-align:top}
/* A cell breaks a word only where the word cannot fit: `anywhere` would let a column shrink to
a letter's width; `break-word` leaves a column as wide as its longest word. */
.rbchat-body td{padding:.2rem .8rem .2rem 0;vertical-align:top;border-bottom:1px dotted var(--t-line);overflow-wrap:break-word}
.rbchat-body tbody tr:hover td{background:var(--t-sel)}
.rbchat-body td:first-child a{white-space:nowrap}
.rbchat-body td br ~ *,.rbchat-body td li + li{color:var(--t-dim)}
.rbchat-body td ul,.rbchat-body td ol{margin:0;padding:0}
/* A refusal wears the answer's rail in the terminal's red, so an error reads as the step that
failed where an answer reads as the step that finished. */
.rbchat-refusal{margin:.4rem 0 0 .35rem;padding:.55rem .9rem .55rem .95rem;border-left:1.5px solid var(--t-bad);background:var(--t-card);border-radius:0 8px 8px 0;color:var(--t-bad)}
.rbchat-model{margin:.1rem 0 0;font-size:.74rem;color:var(--t-dim)}
.rbchat-body .rbchat-num{text-align:right;font-variant-numeric:tabular-nums}
/* One link style, the family's: a link in the answer or the notice has no class, so the page's
`link` block draws it. A cited title carries one, so it takes the same treatment here by
hand, the interactive blue and a line only under the pointer. */
.rbchat-cites a.rbchat-cite{color:var(--c-mid);text-decoration:none;border-bottom:1px solid transparent}
.rbchat-cites a.rbchat-cite:hover,.rbchat-cites a.rbchat-cite:focus-visible{border-bottom-color:var(--c-mid)}
.rbchat-cites{margin:.5rem 0 0;font-size:.78rem;line-height:1.7;color:var(--t-dim)}
/* The site's icon at the head of the line, once, and GitHub's mark after each title: quiet
until pointed at, and both sized so the line stays one line on a phone. */
.rbchat-from{width:16px;height:16px;vertical-align:-3px;margin-right:.4rem}
.rbchat-gh{color:var(--dim);margin-left:.25rem;text-decoration:none;border:0}
.rbchat-gh svg{width:14px;height:14px;vertical-align:-2px}
.rbchat-gh:hover,.rbchat-gh:focus-visible{color:var(--ink);outline:none}
.rbchat-gh:focus-visible{box-shadow:0 0 0 2px var(--press)}
@media (max-width:600px){
/* A phone's panel is the screen, so there is nothing to size and no corner to do it with;
the width and height the grip may have written are overridden here rather than cleared,
because a window that grows past this breakpoint should find the size still remembered.
It is pinned to the visible area, which chat.js measures, so the title bar stays at the
top of the screen with the keyboard open rather than riding up with the page. The panel
is a `<section>`, and a page's own margin on its sections would push a top-anchored panel
down by that much. */
.rbchat{top:var(--rbchat-top,0);right:0;bottom:auto;margin:0;width:100vw!important;height:var(--rbchat-h,100dvh)!important;border-radius:0;border:0}
html[data-chat-waiting]::after{top:0;right:0;bottom:auto;width:100vw;height:100dvh;border:0;border-radius:0}
.rbchat-grip{display:none}
/* The page under a full-screen panel holds still, so a swipe in the panel moves only the
conversation. */
html:has(.rbchat:not([hidden])), html:has(.rbchat:not([hidden])) body{overflow:hidden}
}
/* A picture the host drew, under the answer and above the cite line: at its own size in a box
that scrolls, captioned in the page's language, each node a link. Expand moves the box into
the dialog below, the stage's own pattern, and the panel stays open behind it. */
.rbchat-diagram{margin:.6rem 0 0;padding:.5rem 0 0;border-top:1px solid var(--rule)}
.rbchat-diagram figcaption{display:flex;align-items:center;gap:.5rem;margin:0 0 .4rem;font-size:.8rem;color:var(--dim)}
.rbchat-diagram figcaption span{margin-right:auto}
.rbchat-diagram-full{position:relative;border:0;background:none;color:var(--dim);font:inherit;font-size:1rem;line-height:1;cursor:pointer;padding:.2rem .35rem;border-radius:6px}
.rbchat-diagram-full:hover,.rbchat-diagram-full:focus-visible{color:var(--ink);outline:2px solid var(--c-mid);outline-offset:2px}
.rbchat-diagram-full[data-tip]::after{content:attr(data-tip);position:absolute;top:calc(100% + .45rem);right:0;z-index:3;
white-space:nowrap;pointer-events:none;opacity:0;transform:translateY(-2px);transition:opacity .12s ease,transform .12s ease;
background:var(--raise);border:1px solid var(--rule);border-radius:6px;padding:.42rem .62rem;
box-shadow:0 6px 18px var(--deck-drop);font-size:.8rem;line-height:1.35;color:var(--ink)}
.rbchat-diagram-full:hover::after,.rbchat-diagram-full:focus-visible::after{opacity:1;transform:none}
@media (hover:none){.rbchat-diagram-full[data-tip]::after{display:none}}
@media (prefers-reduced-motion:reduce){.rbchat-diagram-full[data-tip]::after{transition:none}}
.rbchat-diagram-box{overflow:auto;max-width:100%}
.rbchat-diagram-box svg{display:block;max-width:none;height:auto}
.rbchat-diagram-box a{cursor:pointer}
.rbchat-diagram-box a:hover :is(rect,polygon,path),.rbchat-diagram-box a:focus-visible :is(rect,polygon,path){stroke-width:2px}
/* A node is a link, so its name reads as one: the family's link color, underlined on hover and
keyboard focus. Mermaid writes its own per-render <style> with id-scoped selectors, which beats
a class rule on specificity alone, so the color needs !important, and it paints a span inside
a label with --ink directly, so the name's span is named here rather than left to inherit; the underline competes with
nothing Mermaid draws and needs none. A class diagram's title is the same .nodeLabel span. The
whole box stays the link's target, but the underline is scoped to .rbchat-node-name, the span
chat.js wraps around the name alone: a text-decoration set on .nodeLabel itself would propagate
into the host's own quieter line below it (a neighborhood's «type», a phase's seats), which
never reads as the link. */
.rbchat-diagram-box svg a .nodeLabel,.rbchat-diagram-box svg a .nodeLabel p,.rbchat-diagram-box svg a .rbchat-node-name,.rbchat-diagram-box svg a text{color:var(--c-mid)!important;fill:var(--c-mid)!important}
.rbchat-diagram-box svg a:hover .rbchat-node-name,.rbchat-diagram-box svg a:focus-visible .rbchat-node-name{text-decoration-line:underline;text-underline-offset:2px}
/* The host's own line under a node's name — a neighborhood's stereotype, a phase's seats — reads
quieter than the title above it. */
.rbchat-diagram-box svg small{color:var(--dim);font-size:.78em;font-weight:400}
/* An edge's label shares Mermaid's one text-color variable with a node's label, so its own color
needs the same !important; its background is the panel's own raise, reached through
mermaidConfig's edgeLabelBackground instead of fought over here. */
.rbchat-diagram-box svg .edgeLabel,.rbchat-diagram-box svg .edgeLabel p,.rbchat-diagram-box svg .edgeLabel text{color:var(--dim)!important;fill:var(--dim)!important}
.rbchat-diagram-failed{margin:0;font-size:.85rem}
/* An org chart's marks: Mermaid sets the host's token as an svg.label-icon before a person's name,
sized to the text; a person's mark is the firm brightness and an agent's the mid, as the
Processes page draws them, and both beat the linked label's own color; a system's element mark
is the firm brightness too, since a system is a thing and not an agent. An open position is a
dashed box with no fill, and the frame the agents of a group stand in is shaded. */
.rbchat-diagram-box svg .label-icon{width:1.15em;height:1.15em;vertical-align:-.2em;margin-right:.3em}
.rbchat-diagram-box svg .rbchat-mark.human{color:var(--c-firm,var(--ink))!important}
.rbchat-diagram-box svg .rbchat-mark.agent{color:var(--c-mid)!important}
.rbchat-diagram-box svg .rbchat-mark.element{color:var(--c-firm,var(--ink))!important}
.rbchat-diagram-box svg .node.open rect{fill:none!important}
.rbchat-diagram-box svg .cluster.agents rect{fill:var(--press)!important}
.rbchat-diagram-reading{margin:.35rem .1rem 0;font-size:.8rem;line-height:1.4;color:var(--dim)}
/* A page's own picture is a preview: fitted to the column, never past its own size, and
opened by a click to be read; chat.js marks it. The rule reaches the box only while it is in
its figure, so in the dialog the zoom has it whole. */
figure.rbchat-diagram[data-diagram]{border-top:0;padding-top:0;margin:1.1rem 0 1.4rem}
.rbchat-diagram-fit .rbchat-diagram-box{overflow:hidden; cursor:zoom-in}
.rbchat-diagram-fit .rbchat-diagram-box svg{max-width:100%; height:auto; margin:0 auto}
.rbchat-diagram-box pre{margin:.3rem 0 0;white-space:pre-wrap;font-family:"Plex Mono",ui-monospace,Menlo,monospace;font-size:.78rem;color:var(--ink)}
/* A picture's full screen is the family's one modal (modal.css). What the picture brings to it:
the zoom controls in the modal's head, and its box filling the modal's body. */
/* −, + and Fit: quiet until pointed at, as the modal's × is, with an edge so three read as a
group, each with a note naming its key, drawn here because card.js is not on every page. */
.rbchat-modal-zoom{flex:0 0 auto; display:flex; gap:.3rem}
.rbchat-modal-zoom button{position:relative; min-width:2rem; height:2rem; padding:0 .55rem;
font:inherit; font-size:.9rem; line-height:1; background:none; border:1px solid var(--rule);
border-radius:6px; color:var(--dim); cursor:pointer}
.rbchat-modal-zoom button:hover, .rbchat-modal-zoom button:focus-visible{color:var(--c-mid); border-color:var(--c-mid); outline:none}
.rbchat-modal-zoom button[data-tip]::after{content:attr(data-tip);position:absolute;top:calc(100% + .45rem);right:0;z-index:3;
white-space:nowrap;pointer-events:none;opacity:0;transform:translateY(-2px);transition:opacity .12s ease,transform .12s ease;
background:var(--raise);border:1px solid var(--rule);border-radius:6px;padding:.42rem .62rem;
box-shadow:0 6px 18px var(--deck-drop);font-family:inherit;font-size:.8rem;font-weight:400;line-height:1.35;letter-spacing:0;color:var(--ink)}
.rbchat-modal-zoom button:hover::after,.rbchat-modal-zoom button:focus-visible::after{opacity:1;transform:none}
@media (hover:none){.rbchat-modal-zoom button[data-tip]::after{display:none}}
@media (prefers-reduced-motion:reduce){.rbchat-modal-zoom button[data-tip]::after{transition:none}}
/* The box takes whatever the head leaves, inset as the model page's stage is. In the modal it is
a viewport the picture is moved in by chat.js's zoom, not a box that scrolls: the browser's
own scrolling and pinching would fight the gestures. */
.rbmodal-body > .rbchat-diagram-box{flex:1 1 auto; min-height:0; margin:1rem 1.2rem 1.2rem}
.rbmodal-body .rbchat-diagram-box.rbchat-zoom{overflow:hidden; touch-action:none; cursor:grab;
user-select:none; -webkit-user-select:none}
.rbmodal-body .rbchat-diagram-box.rbchat-panning{cursor:grabbing}
.rbmodal-body .rbchat-diagram-box.rbchat-panning a{cursor:grabbing}
@media (max-width: 860px){ .rbmodal-body > .rbchat-diagram-box{margin:.5rem} }
/* The intro: the lockup as /cli/ prints its banner, a hello, the notice as a comment, and the menus. */
.rbchat-intro{display:flex;flex-direction:column}
.rbchat-lock{display:flex;align-items:center;gap:1rem;margin:.2rem 0 .9rem .2rem}
.rbchat-lock svg{width:4em;height:4em;flex:0 0 auto;color:var(--t-accent)}
/* blust.ch's mark draws its plate and letters by class, as the header's own rules do. */
.rbchat-lock .plate{fill:var(--raise);stroke:var(--rule);stroke-width:1.5}
.rbchat-lock .rb{fill:var(--c-mid)}
.rbchat-word{display:flex;flex-direction:column;font-size:1.05rem;line-height:1.35}
.rbchat-first{color:var(--t-strong);font-weight:600}
.rbchat-accent{color:var(--t-accent);font-weight:600}
.rbchat-sub{font-size:.8rem;color:var(--t-dim)}
.rbchat-hello{margin:0 0 .5rem}
.rbchat-h2{color:var(--t-dim)}
/* The notice carries a rail in the terminal's amber, as an answer carries one in its green, and the
one sentence the law asks for, that an AI answers, stands first in the panel's ink; the rest stays
dim. The rail is a frame and not a verdict on the words, which is what the same amber under a
claim is. */
.rbchat-notice{margin:0 0 .9rem;padding-left:.7rem;border-left:2px solid var(--t-part);color:var(--t-dim)}
.rbchat-ai{font-weight:400;color:var(--t-ink)}
.rbchat-label{margin:.5rem 0 0;color:var(--t-dim)}
.rbchat-prompt-line{margin:.6rem 0 0;color:var(--t-strong)}
.rbchat-menu{display:flex;flex-direction:column}
.rbchat-row{all:unset;display:grid;grid-template-columns:1.6em 1fr;padding:.22rem .45rem;margin:0 -.45rem;border-radius:5px;cursor:pointer;overflow-wrap:anywhere}
.rbchat-row .rbchat-n{color:var(--t-accent)}
.rbchat-row .rbchat-q{color:var(--t-ink)}
.rbchat-row .rbchat-g{grid-column:2;color:var(--t-dim)}
.rbchat-row:hover,.rbchat-row:focus-visible{background:var(--t-sel)}
.rbchat-row:hover .rbchat-q{color:var(--t-accent)}
.rbchat-row:focus-visible{outline:1.5px solid var(--t-accent)}
.rbchat-spent .rbchat-row{opacity:.55}
/* Played: each piece stands still until its moment. Finished, or for reduced motion, all stand. */
.rbchat-intro:not(.rbchat-still) :is(.rbchat-sub,.rbchat-h1,.rbchat-h2,.rbchat-notice,.rbchat-label,.rbchat-row,.rbchat-prompt-line):not(.rbchat-on){opacity:0}
.rbchat-intro:not(.rbchat-still) .rbchat-lock svg > :not(.rbchat-on){opacity:0}
.rbchat-intro .rbchat-on{transition:opacity .2s ease}
/* Reduced motion draws the intro finished at once, so nothing waits to fade in; a spent menu
still dims. */
@media (prefers-reduced-motion:reduce){.rbchat-intro *{transition:none!important}}
.rbchat-cur{display:inline-block;width:.6em;height:1.1em;vertical-align:-.2em;background:var(--t-ink);animation:rbchat-blink 1.1s steps(1) infinite}
@keyframes rbchat-blink{50%{opacity:0}}
@media (prefers-reduced-motion:reduce){.rbchat-cur{animation:none}}
.rbchat-help{margin:.4rem 0 0;color:var(--t-dim)}
.rbchat-help p{margin:0;display:grid;grid-template-columns:7ch 1fr}
.rbchat-help-k{color:var(--t-accent)}
/* Heard, not seen: the finished answer, said once to a screen reader. */
.rbchat-say,.rbchat-sr{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
/* What the chat answers from, dim as the host line above it; its links are the page's own. */
.rbchat-versions{display:block;font-size:.8rem;color:var(--t-dim)}
/* The graph, over the page as a picture's full screen is: the model page's own stage, embedded, in
a dialog of the terminal's colors, a sheet on a phone. */
.rbchat-graph{flex:1 1 auto;min-height:0;display:flex;flex-direction:column}
.rbchat-graph-frame{flex:1;width:100%;border:0;background:var(--t-bg)}
.rbchat-graph-failed{margin:0;padding:.8rem 1.2rem;color:var(--t-dim);border-bottom:1px solid var(--t-line)}