Oregami
Repositories/oxedyne/daimond

oxedyne/daimond/www/css/mail.css

20.4 KiB, 1 run

created by r2519314175:1111, which is this file's identity for as long as the history lasts, whatever it is later renamed to

download · who wrote it · its history

1/* mail.css — the Email panel, and one message in the centre.
2 *
3 * Follows the Workspace panel's shape: a head with actions, a card beneath.
4 * Nothing here is new furniture; it is the same furniture, holding mail. */
5
6.mail-actions { display: flex; gap: 4px; align-items: center; }
7
8.mail-card {
9 display: flex; flex-direction: column;
10 flex: 1; min-height: 0;
11 overflow: hidden;
12}
13
14.mail-state {
15 display: flex; flex-direction: column; gap: 8px;
16 padding: 10px;
17 flex: none;
18}
19
20/* The unlock, shown only while the account does not hold the tool. */
21.mail-pitch {
22 border: 1px solid var(--border);
23 border-radius: var(--radius);
24 background: var(--bg-secondary);
25 padding: 12px;
26}
27.mail-pitch p { margin: 0 0 10px; font-size: var(--fs-sm); line-height: 1.5; }
28.mail-fine { font-size: var(--fs-xs); line-height: 1.5; color: var(--text-secondary); }
29.mail-pitch .mail-fine { margin-bottom: 10px; }
30.mail-unlock {
31 width: 100%;
32 background: var(--accent); color: var(--on-fill, #fff);
33 border: 1px solid var(--accent); border-radius: var(--radius-sm);
34 padding: 9px 16px; font-size: var(--fs-base);
35}
36.mail-unlock:hover { filter: brightness(1.08); }
37.mail-unlock:disabled { opacity: 0.6; cursor: default; }
38
39.mail-note, .mail-err {
40 font-size: var(--fs-xs); line-height: 1.45;
41 padding: 7px 9px; border-radius: var(--radius-sm);
42}
43.mail-note { color: var(--text-secondary); background: var(--bg-tertiary); }
44.mail-err { color: var(--accent-text); background: var(--accent-soft); }
45
46/* ── The mailboxes ───────────────────────────────────────────── */
47
48.mail-accounts {
49 display: flex; flex-direction: column; gap: 2px;
50 padding: 0 6px 6px;
51 flex: none;
52}
53.mail-accounts .mail-fine { padding: 4px 4px 0; }
54
55/* One control for all of mail, and the one manual refresh, above the list.
56 Deliberately not dressed as a section heading: the rail found that a row led
57 by a light and set in small caps reads as a section that has lost its
58 alignment (app.css:207). Sentence case, a rule under it, the light leading. */
59.mail-globals {
60 display: flex; align-items: center; gap: 6px;
61 padding: 4px 2px 6px;
62 margin-bottom: 4px;
63 border-bottom: 1px solid var(--border);
64}
65.mail-globals-label {
66 flex: 1; min-width: 0;
67 font-size: var(--fs-sm); font-weight: 500;
68 color: var(--text-secondary);
69 overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
70}
71/* The one manual refresh, at the end of that row. It is a '⟳' rather than a
72 drawn icon, and the rule for it used to live down in the folders block where
73 it was born, sized at the folder head's 13px -- so beside the 20px pause and
74 play it read as a stray character rather than the third control on the row.
75 A 20px box, the same one `.pptw-act` wears two places to the left, and 18px
76 of type in it: the glyph is drawn inside its em box, so the same nominal size
77 as the verbs beside it would still come out smaller than them. */
78.mail-refresh {
79 flex: none;
80 display: flex; align-items: center; justify-content: center;
81 width: 20px; height: 20px; padding: 0;
82 border: 0; border-radius: var(--radius-sm); background: none;
83 color: var(--text-muted);
84 font-size: var(--fs-2xl); line-height: 1;
85 cursor: pointer;
86}
87.mail-refresh:hover:not(:disabled) { color: var(--text-primary); background: var(--bg-hover); }
88.mail-refresh:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
89.mail-refresh:disabled { opacity: 0.5; cursor: default; }
90.mail-acct {
91 display: flex; align-items: center; gap: 6px;
92 padding: 6px 8px;
93 border-radius: var(--radius-sm);
94 cursor: pointer;
95 font-size: var(--fs-sm);
96}
97.mail-acct:hover { background: var(--bg-hover); }
98.mail-acct.on {
99 background: var(--bg-tertiary);
100 box-shadow: inset 2px 0 0 var(--accent);
101}
102.mail-addr {
103 flex: 1; min-width: 0;
104 overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
105}
106.mail-when { font-size: var(--fs-2xs); color: var(--text-muted); white-space: nowrap; }
107.mail-del {
108 border: 0; background: none; color: var(--text-muted);
109 font-size: var(--fs-lg); line-height: 1; padding: 0 2px;
110 opacity: 0;
111}
112.mail-acct:hover .mail-del { opacity: 1; }
113.mail-del:hover { color: var(--danger); }
114
115/* The gear stays visible. `.mail-del` above appears on hover, which on a phone
116 means never; a control the user has been told to press must not be one they
117 cannot find. Muted until hovered, so it does not compete with the address. */
118.mail-gear {
119 flex: none;
120 display: flex; align-items: center; justify-content: center;
121 width: 20px; height: 20px; padding: 0;
122 border: 0; background: none; color: var(--text-muted);
123 cursor: pointer;
124}
125/* 16px, which is what a Diamond tile's cog and the rail status header's cog are
126 drawn at. It is the same path from the same place, and the app was drawing it
127 at three sizes in three panels; 14 in a 20px box also left more air round it
128 than round anything else on the row. */
129.mail-gear .ic { width: 16px; height: 16px; }
130.mail-gear:hover { color: var(--text-primary); }
131.mail-gear:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; border-radius: 50%; }
132
133/* ── The messages ────────────────────────────────────────────── */
134
135.mail-list {
136 flex: 1; min-height: 0; overflow-y: auto;
137 border-top: 1px solid var(--border);
138}
139.mail-list .mail-fine { padding: 10px; }
140
141/* The foot of the list: what the cap held back, and the way to go and get it.
142 * It sits below the last message and belongs to the list, not to the messages,
143 * so it is set apart rather than looking like one more row. */
144.mail-more {
145 display: flex; flex-direction: column; gap: 8px;
146 padding: 12px 10px 14px;
147 border-top: 1px solid var(--border);
148 background: var(--bg-tertiary);
149}
150.mail-more .mail-fine { padding: 0; }
151.mail-more-btns { display: flex; gap: 8px; }
152.mail-more-btns > button { flex: 1; }
153.mail-stop {
154 background: var(--accent-soft); color: var(--accent-text);
155 border: 1px solid var(--accent); border-radius: var(--radius-sm);
156 padding: 8px 14px; font-size: var(--fs-sm);
157}
158.mail-all {
159 background: var(--bg-secondary); color: var(--text-secondary);
160 border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
161 padding: 8px 14px; font-size: var(--fs-sm);
162}
163.mail-all:hover { color: var(--text-primary); }
164.mail-all:disabled { opacity: 0.5; cursor: default; }
165.mail-older {
166 align-self: stretch;
167 background: var(--bg-secondary);
168 color: var(--text-primary);
169 border: 1px solid var(--border-strong);
170 border-radius: var(--radius-sm);
171 padding: 8px 14px;
172 font-size: var(--fs-sm);
173}
174.mail-older:hover { border-color: var(--accent); color: var(--accent-text); }
175.mail-older:disabled { opacity: 0.5; cursor: default; }
176.mail-older:disabled:hover { border-color: var(--border-strong); color: var(--text-primary); }
177.mail-msg {
178 padding: 8px 10px;
179 cursor: pointer;
180 border-bottom: 1px solid var(--border);
181}
182.mail-msg:hover { background: var(--bg-hover); }
183.mail-from {
184 font-size: var(--fs-xs); color: var(--text-secondary);
185 overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
186}
187.mail-subj {
188 font-size: var(--fs-sm); margin: 2px 0;
189 color: var(--text-primary);
190 overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
191}
192.mail-msg.unread .mail-subj { font-weight: 600; }
193.mail-date {
194 font-size: var(--fs-2xs); color: var(--text-muted);
195 overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
196}
197
198/* ── One message, in the centre ──────────────────────────────── */
199
200/* The message is a STAGE panel: it opens beside the chat, not in place of it,
201 so a message can be read and asked about at the same time. */
202/* ── One message ─────────────────────────────────────────────────
203 * A header you can read the sender out of at a glance, then the body. HTML mail
204 * is a stranger's markup, so it is rendered inside a sandboxed frame with its
205 * own white page — not styled into ours, and never able to touch it. */
206.msg-head {
207 flex: none;
208 padding: 12px 16px 10px;
209 border-bottom: 1px solid var(--border);
210}
211.msg-subject { font-size: var(--fs-xl-2xl); font-weight: 600; line-height: 1.35; margin-bottom: 8px; }
212
213.msg-who { display: flex; align-items: baseline; flex-wrap: wrap; gap: 6px; margin-bottom: 4px; }
214.msg-name { font-size: var(--fs-sm-base); font-weight: 600; color: var(--text-primary); }
215.msg-addr { font-size: var(--fs-xs-sm); color: var(--text-muted); font-family: var(--font-mono); }
216.msg-date { font-size: var(--fs-xs-sm); color: var(--text-muted); margin-left: auto; white-space: nowrap; }
217
218.msg-line { display: flex; gap: 8px; font-size: var(--fs-xs-sm); line-height: 1.5; }
219.msg-lbl { flex: none; width: 58px; color: var(--text-muted); }
220.msg-val { color: var(--text-secondary); word-break: break-word; }
221
222/* The files that came with the message. Clicking one writes it into the workspace,
223 * which is the only place a file ever lands. */
224.msg-atts { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
225.msg-att {
226 max-width: 100%;
227 background: var(--bg-tertiary);
228 border: 1px solid var(--border); border-radius: var(--radius-sm);
229 color: var(--text-secondary);
230 padding: 5px 10px; font-size: var(--fs-xs);
231 overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
232}
233.msg-att:hover { border-color: var(--accent); color: var(--text-primary); }
234.msg-att.done { border-color: var(--ok); color: var(--ok); }
235.msg-att:disabled { cursor: default; }
236
237.msg-body { flex: 1; min-height: 0; overflow: auto; display: flex; flex-direction: column; }
238
239/* Plain-text mail: the newlines are the layout, so keep them. */
240.msg-text {
241 padding: 14px 16px 16px;
242 white-space: pre-wrap; word-break: break-word;
243 font-size: var(--fs-base); line-height: 1.6;
244 color: var(--text-primary);
245}
246
247/* HTML mail, in its own document. */
248.msg-frame { flex: 1; min-height: 0; width: 100%; border: 0; background: #fff; }
249.msg-blocked {
250 flex: none;
251 display: flex; align-items: center; gap: 10px;
252 padding: 8px 12px;
253 background: var(--bg-tertiary);
254 border-bottom: 1px solid var(--border);
255 font-size: var(--fs-xs); line-height: 1.45;
256 color: var(--text-secondary);
257}
258.msg-blocked span { flex: 1; }
259.msg-blocked button {
260 flex: none;
261 background: var(--bg-secondary);
262 border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
263 color: var(--text-primary);
264 padding: 5px 10px; font-size: var(--fs-xs);
265}
266.msg-blocked button:hover { border-color: var(--accent); color: var(--accent-text); }
267
268/* The verbs, on the message. They sit under the addresses and above the
269 * attachments — after you know who sent it and before you know what came with it,
270 * which is where the decision to answer is actually made. */
271.msg-acts { display: flex; gap: 6px; margin-top: 10px; }
272.msg-act {
273 background: var(--bg-secondary);
274 border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
275 color: var(--text-primary);
276 padding: 5px 12px; font-size: var(--fs-xs-sm);
277}
278.msg-act:hover { border-color: var(--accent); color: var(--accent-text); }
279
280/* ── Drafts ──────────────────────────────────────────────────────
281 * Above the inbox, because a draft is the only thing in the panel waiting on the
282 * user — and because a draft the daimon wrote for them to check would otherwise
283 * sit in a folder nobody opens. */
284.mail-drafts { border-bottom: 1px solid var(--border-2); background: var(--bg-tertiary); }
285.mail-drafts-head {
286 padding: 6px 10px;
287 font-size: var(--fs-2xs); text-transform: uppercase; letter-spacing: 0.04em;
288 color: var(--text-muted);
289}
290.mail-draft {
291 padding: 7px 10px;
292 cursor: pointer;
293 border-top: 1px solid var(--border);
294}
295.mail-draft:hover { background: var(--bg-hover); }
296.mail-draft .mail-subj { font-weight: 600; }
297
298/* ── Writing one ─────────────────────────────────────────────────
299 * A stage panel, so the daimon stays beside the draft while it is written. The
300 * body takes every pixel the head and the foot do not: a message is mostly the
301 * thing you are typing into it. */
302.compose-head {
303 flex: none;
304 padding: 10px 14px 6px;
305 border-bottom: 1px solid var(--border);
306}
307.compose-row {
308 display: flex; align-items: center; gap: 8px;
309 padding: 3px 0;
310}
311.compose-row > span {
312 flex: none; width: 58px;
313 font-size: var(--fs-xs-sm); color: var(--text-muted);
314}
315.compose-row > input, .compose-row > select {
316 flex: 1; min-width: 0;
317 background: var(--bg-tertiary);
318 border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
319 color: var(--text-primary);
320 padding: 6px 9px; font-size: var(--fs-sm);
321}
322/* THE OLD INDICATOR, MISSED BY THE SWEEP THAT REPLACED THE OTHER TWENTY-ONE.
323 `outline: none; border-color: var(--accent)` makes the focus mark the resting
324 border recoloured, and these rows rest on `--border-strong` -- so the two
325 colours the reader has to tell apart are `--accent` and `--border-strong`,
326 which measure 1.11 (Midnight) to 1.81 (Light) across the eleven palettes.
327 WCAG 2.2 SC 2.4.11 asks 3.0 of a focus indicator. dev/contrast_report.md §5
328 records why every other field in the app was moved to a real outline drawn
329 OUTSIDE the control, where what it contrasts with is the surface: that
330 measures 3.87-6.75 here. The To/Subject row is the same control and gets the
331 same answer.
332 The select half takes `:focus-visible` -- see the note at `.settings-select`
333 in app.css; the input half is `:focus`, which resolves identically. */
334.compose-row > input:focus {
335 outline: 2px solid var(--accent); outline-offset: 1px; border-color: var(--accent);
336}
337.compose-row > select:focus-visible {
338 outline: 2px solid var(--accent); outline-offset: 1px; border-color: var(--accent);
339}
340.compose-text {
341 flex: 1; min-height: 0;
342 width: 100%;
343 resize: none;
344 background: transparent;
345 border: 0; outline: none;
346 color: var(--text-primary);
347 padding: 14px 16px;
348 /* Was `font: 14px/1.6 inherit` -- the one hard pixel size left in the app, so
349 the reading control moved every word on screen EXCEPT the message being
350 written, and the shorthand took "inherit" as a family name besides. */
351 font-size: var(--fs-base);
352 line-height: 1.6;
353}
354.compose-atts { display: flex; flex-wrap: wrap; gap: 6px; padding: 0 14px; }
355.compose-atts:not(:empty) { padding: 8px 14px 2px; }
356.compose-att {
357 max-width: 100%;
358 background: var(--bg-tertiary);
359 border: 1px solid var(--border); border-radius: var(--radius-sm);
360 color: var(--text-secondary);
361 padding: 5px 10px; font-size: var(--fs-xs);
362 overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
363}
364.compose-att:hover { border-color: var(--danger); color: var(--danger); }
365
366/* Wraps, because at 380px it did not: the row ran 22px past the panel and cut
367 "Discard" in half, so the one control that undoes the message was the one the
368 phone hid. A second row of buttons is the right answer here rather than a
369 horizontal scroll — a control a person has to find by swiping is one they will
370 not find. `nowrap` on the buttons themselves stops "Save draft" folding to two
371 lines while its neighbours stay at one, which left the row visibly ragged. */
372.compose-foot {
373 flex: none;
374 display: flex; align-items: center; flex-wrap: wrap; gap: 8px;
375 padding: 10px 14px;
376 border-top: 1px solid var(--border);
377}
378.compose-send, .compose-btn { white-space: nowrap; }
379.compose-send {
380 background: var(--accent); color: var(--on-fill, #fff);
381 border: 1px solid var(--accent); border-radius: var(--radius-sm);
382 padding: 8px 18px; font-size: var(--fs-sm);
383}
384.compose-send:hover { filter: brightness(1.08); }
385.compose-btn {
386 background: var(--bg-secondary); color: var(--text-secondary);
387 border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
388 padding: 8px 12px; font-size: var(--fs-sm);
389}
390.compose-btn:hover { color: var(--text-primary); }
391.compose-btn.danger:hover { border-color: var(--danger); color: var(--danger); }
392.compose-send:disabled, .compose-btn:disabled { opacity: 0.5; cursor: default; }
393.compose-note {
394 margin-left: auto;
395 font-size: var(--fs-xs); color: var(--text-secondary);
396 overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
397}
398.compose-note.err { color: var(--accent-text); }
399
400/* The form dialog's guidance line, under the fields. */
401.dlg-note { font-size: var(--fs-xs); line-height: 1.45; color: var(--text-secondary); margin-top: 8px; }
402.dlg-note.err { color: var(--accent-text); }
403/* The negative bottom margin this was written against has gone: the shared label
404 * now spaces itself 12/6 and only the BYOK form compensates for its flex gap
405 * (app.css). What is left is the extra 2px of top margin, kept deliberately --
406 * a form asking for a credential is read more slowly than a settings row. It
407 * does mean the same built form is 2px looser in the modal than in the rail
408 * drawer, which is the only place the two hosts differ. */
409.dlg-card .cfg-fieldlabel { margin-top: 14px; margin-bottom: 6px; }
410
411/* ── The folder picker ─────────────────────────────────────────
412 One level below the mailbox list: a folder is the same kind of choice as
413 a mailbox, so `.mail-folder` borrows `.mail-acct`'s shape and `.on`; only
414 what differs is stated here. Nesting depth arrives as a CSS variable so
415 the indent needs no inline style. */
416.mail-folders { flex: none; padding: 0 6px 6px; }
417.mail-folders-head {
418 display: flex;
419 align-items: center;
420 gap: 6px;
421 padding: 2px 8px 4px;
422 font-size: var(--fs-2xs);
423 text-transform: uppercase;
424 letter-spacing: 0.04em;
425 color: var(--text-muted);
426}
427/* `.mail-refresh` was declared here, next to the folder head it once sat in.
428 It moved to the globals row above and its rule went with it. */
429.mail-folder-list {
430 display: flex;
431 flex-direction: column;
432 gap: 2px;
433 max-height: 168px;
434 overflow-y: auto;
435}
436.mail-folder { padding-left: calc(8px + var(--folder-depth, 0) * 10px); }
437.mail-folder[aria-disabled="true"] { opacity: 0.55; cursor: default; }
438
439/* How much is in a folder. Tabular figures so a column of counts lines up on
440 its units rather than wandering with the width of a 1; muted, because the
441 folder's name is what the eye is looking for and the number is the answer to
442 a question it has not asked yet. */
443.mail-count {
444 flex: none;
445 min-width: 3ch; text-align: right;
446 font-size: var(--fs-2xs);
447 font-variant-numeric: tabular-nums;
448 color: var(--text-secondary);
449 white-space: nowrap;
450}
451/* A figure that can no longer be trusted on its own. Dimmed rather than
452 coloured: it is not a warning, it is an old number, and the age sits beside
453 it saying how old. */
454.mail-count.stale { color: var(--text-muted); }
455
456/* ── A mailbox's settings ──────────────────────────────────────
457 One tile per folder: its pause control, its name, what it holds, and how
458 often it goes and looks. The tiles are the dialog's whole body — the Delete
459 that belongs at the foot of it is phase C's and is not here yet. */
460.mail-cfg { display: flex; flex-direction: column; gap: 6px; }
461.mail-cfg > .mail-fine { margin-bottom: 4px; }
462.mail-tile {
463 display: flex; align-items: center; gap: 8px;
464 padding: 7px 8px;
465 border: 1px solid var(--border);
466 border-radius: var(--radius-sm);
467 background: var(--bg-tertiary);
468}
469/* The mailbox's own switch governs every tile under it, so it is set apart
470 from them rather than being read as one more folder. */
471.mail-tile-self { background: var(--bg-secondary); border-color: var(--border-strong); }
472.mail-tile-self .mail-fine { flex: none; }
473.mail-tile-name {
474 flex: 1; min-width: 0;
475 font-size: var(--fs-sm);
476 overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
477}
478.mail-every {
479 flex: none; max-width: 46%;
480 background: var(--bg-secondary);
481 border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
482 color: var(--text-primary);
483 padding: 4px 6px; font-size: var(--fs-xs);
484}
485/* A pulldown, so `:focus-visible` -- see the note at `.settings-select`. */
486.mail-every:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; border-color: var(--accent); }
487
488/* At a phone's width a tile cannot hold four things on one line: the folder
489 name ellipsised to nothing so that a pulldown could keep its full width.
490 The pulldown drops to a second line and takes the whole of it. */
491@media (max-width: 460px) {
492 .mail-tile { flex-wrap: wrap; }
493 .mail-every { max-width: none; width: 100%; }
494}