carlos / contra Public

Clone
git clone https://amadan.net/carlos/contra

Plain git — no account needed to clone.

Download

Download this file

1/* contra.css — the grammar of the ticket.
2
3 theme.css is colour, type and shape: the tokens tokens.css consumes.
4 This file is CONTRA's own, and it exists because the app's templates
5 write bare HTML — <h1>, <form>, <input>, <ul> — rather than
6 rastrillo's component classes. Without it the world stops at the
7 palette and every control on the page is a browser default, which is
8 the visual equivalent of shipping the crypto and skipping the UI.
9
10 Loaded after theme.css, last of the three, so it wins.
11
12 ── The five devices, and where each may appear ───────────────────────
13 1. THE FIELD BOX. A small letterspaced cap label, a rule, and the
14 value sitting on the rule. Every input in the app is this; there
15 are no boxed text fields, because a ticket has ruled fields.
16 2. THE NUMBERING. Anything counted prints large, tabular, in the
17 second colour. Item counts, versions, epochs, the handoff code.
18 Large only — theme.css measures why.
19 3. THE TEAR-LINE. Exactly one per screen, on the real boundary:
20 above it what the server holds, below it what only this browser
21 knows. Never decoration, never twice.
22 4. THE STAMP. Status pills, and the notices that state a cost.
23 5. THE STOCK CODE. Manila for a vault shared with you, the way a
24 cloakroom prints luggage tickets on different stock from coats.
25
26 ── What this file refuses ────────────────────────────────────────────
27 No cards. No rounded corners. No texture, no distress, no torn-paper
28 shadows, no rotated stamps, no fake staples or perforated GIFs
29 scattered as decoration. Ticket printing turns twee the moment it
30 gets grain; what keeps it institutional is that every mark is doing a
31 job. This is a station cloakroom, not a fairground.
32 ──────────────────────────────────────────────────────────────────── */
33
34/* The display voice: League Gothic, an Alternate Gothic revival and the
35 condensed face poster and ticket printing has been set in for a
36 century. Self-hosted, same-origin, 10KB — this app fetches nothing
37 from anywhere, and a webfont from a CDN would be one more party the
38 browser trusts on a page that holds vault keys.
39
40 OFL 1.1; the licence ships beside the file at static/fonts/OFL.txt.
41 swap, because a display face that blocks the first paint of an
42 unlock screen has its priorities wrong. */
43@font-face {
44 font-family: "League Gothic";
45 font-style: normal;
46 font-weight: 400;
47 font-display: swap;
48 src: url("/static/fonts/leaguegothic-latin.woff2") format("woff2");
49}
50
51:root {
52 --contra-display: "League Gothic", "Oswald", "Archivo Narrow", var(--rst-font);
53
54 /* The numbering machine's ink. LARGE ONLY — 24px up, or 18.66px bold.
55 theme.css carries the measurement and the reason. */
56 --contra-ink-2: light-dark(#b3301a, #ff7a5c);
57
58 /* Manila: the category code, and it codes one thing. */
59 --contra-stock-2: light-dark(#ddc78d, #3a3018);
60
61 /* The perforation's pitch. One place, so every tear-line in the app
62 is the same machine. */
63 --contra-perf: 12px;
64}
65
66/* ── Browser surfaces ─────────────────────────────────────────────────
67 The parts we did not draw still carry the design. Left alone these
68 ship with defaults that belong to no design system, and on a page
69 whose whole argument is deliberateness that shows. */
70
71::selection {
72 background: var(--contra-stock-2);
73 color: var(--rst-text);
74}
75
76:root {
77 scrollbar-color: var(--rst-line-strong) var(--rst-surface-2);
78 scrollbar-width: thin;
79}
80
81input,
82textarea,
83select {
84 caret-color: var(--contra-ink-2);
85}
86
87/* Links are text that underlines, printed rather than coloured. The
88 offset and thickness are set because the defaults are a browser's
89 guess at a font we did not pick. */
90a {
91 color: var(--rst-accent);
92 text-decoration-thickness: 1px;
93 text-underline-offset: 0.18em;
94}
95
96a:hover {
97 text-decoration-thickness: 2px;
98}
99
100/* ── The sheet ────────────────────────────────────────────────────── */
101
102/* The page is one piece of stock. tokens.css already centres the column;
103 this gives it the ticket's cut edge on the wide layout, where there is
104 ground either side to cut it out of. */
105/* The page is one piece of stock, printed edge to edge.
106
107 It had cut edges of its own for one round. They were wrong: the console
108 shell already draws a rule down the side of the rail, and the page's
109 own border landed about 55px inboard of it, so every wide screen showed
110 two competing sheet edges with a dead strip between them. The rail's
111 rule is the structural one and it stays; the sheet is defined by its
112 ground and its rules, which is how a ticket is actually printed. */
113[rst-page] {
114 max-width: 60rem;
115 min-block-size: calc(100vh - 8rem);
116}
117
118/* The brand is the ticket's overprint: the issuing office's name, set
119 in the display face, letterspaced, small. */
120[rst-shell-brand] {
121 font-family: var(--contra-display);
122 font-size: 1.5rem;
123 letter-spacing: 0.14em;
124 line-height: 1;
125 text-decoration: none;
126 text-transform: uppercase;
127}
128
129/* Headings are set like a ticket's title: condensed, uppercase, tight,
130 and the h1 carries the heaviest rule on the sheet under it. More
131 space above a heading than below it, throughout. */
132h1,
133h2,
134h3 {
135 font-family: var(--contra-display);
136 font-weight: 400;
137 letter-spacing: 0.04em;
138 line-height: 1;
139 text-transform: uppercase;
140 text-wrap: balance;
141}
142
143/* Caps are for labels, not for sentences. A ticket prints its field
144 names in capitals and its title in the display face, and this app's
145 h1 is sometimes a whole sentence — "A password manager where the
146 server knows nothing about you" — which in condensed capitals is a
147 poster nobody reads and a screen reader may spell out. So the title
148 keeps its sentence case and gets its character from the face and the
149 rule under it; h2 and h3 are section labels and stay capitalised. */
150h1 {
151 border-bottom: 3px solid var(--rst-header-rule);
152 font-size: clamp(2.4rem, 6vw, 3.6rem);
153 letter-spacing: 0.01em;
154 margin: 0 0 var(--rst-sp-5);
155 padding-bottom: var(--rst-sp-2);
156 text-transform: none;
157}
158
159h2 {
160 font-size: 1.9rem;
161 margin: var(--rst-sp-6) 0 var(--rst-sp-3);
162}
163
164h3 {
165 font-size: 1.35rem;
166 margin: var(--rst-sp-5) 0 var(--rst-sp-2);
167}
168
169/* A reading measure for prose, because this product explains itself
170 constantly and the column is sized for forms and lists. */
171[rst-page] > p,
172[rst-page] > section > p,
173form > p:not(:has(input, textarea, select, button)) {
174 max-width: 68ch;
175}
176
177/* ── Device 1: the field box ──────────────────────────────────────────
178 A label printed in small letterspaced caps, a rule, and the value
179 sitting on the rule. No boxes: a ticket rules its fields, it does not
180 draw containers round them.
181
182 The rule is the ink rather than the hairline, which is what makes it
183 a control boundary rather than a divider — 12.6:1 in light, well past
184 1.4.11's 3:1. */
185
186/* The caps furniture — labels, buttons, nav, status, the overprint — is
187 set in the machine's own UI stack rather than in the display face, and
188 that is a decision rather than an omission. League Gothic is a poster
189 face: at 11.5px with 0.12em tracking it goes spindly and its condensed
190 forms stop being legible, which is the opposite of what a field label
191 is for. A workhorse UI sans is what an Operate surface wants at that
192 size, so the ticket's character comes from case, tracking, weight and
193 the rules the caps sit on, not from a second self-hosted face. The
194 cost, accepted: the small caps render in a different typeface per
195 operating system while the display line does not. */
196label {
197 color: var(--rst-text-muted);
198 display: block;
199 font-size: var(--rst-fs-xs);
200 font-weight: 600;
201 letter-spacing: 0.12em;
202 line-height: 1.2;
203 margin-bottom: 0;
204 text-transform: uppercase;
205}
206
207/* A checkbox's label is a sentence, not a field name, so it opts out of
208 the caps entirely. */
209label:has(input[type="checkbox"]),
210label:has(input[type="radio"]) {
211 color: var(--rst-text);
212 display: flex;
213 font-size: var(--rst-fs-base);
214 font-weight: 400;
215 gap: var(--rst-sp-2);
216 letter-spacing: normal;
217 line-height: 1.5;
218 max-width: 68ch;
219 text-transform: none;
220}
221
222input[type="text"],
223input[type="email"],
224input[type="password"],
225input[type="file"],
226input:not([type]),
227textarea,
228select {
229 background: transparent;
230 border: 0;
231 border-bottom: 2px solid var(--rst-line-strong);
232 border-radius: 0;
233 color: var(--rst-text);
234 font: inherit;
235 inline-size: 100%;
236 max-inline-size: 32rem;
237 /* The value sits ON the rule, close under its label: a printed field
238 is one mark, and two rounds running the label read as a heading over
239 an empty line rather than as the name of the rule beneath it. The
240 distance is the input's own text box, so closing it means shortening
241 that box rather than removing margin there never was. */
242 line-height: 1.2;
243 padding: 0 0 0.1rem;
244}
245
246textarea {
247 min-block-size: 6rem;
248 resize: vertical;
249}
250
251input:focus,
252textarea:focus,
253select:focus {
254 border-bottom-color: var(--contra-ink-2);
255 outline: 2px solid var(--rst-accent);
256 outline-offset: 3px;
257}
258
259input::placeholder,
260textarea::placeholder {
261 color: var(--rst-text-faint);
262}
263
264input[type="checkbox"],
265input[type="radio"] {
266 accent-color: var(--contra-ink-2);
267 block-size: 1.1rem;
268 flex: none;
269 inline-size: 1.1rem;
270 margin-block-start: 0.15rem;
271}
272
273/* Form paragraphs are the ticket's field rows. */
274form > p {
275 margin: 0 0 var(--rst-sp-4);
276}
277
278/* ── Buttons ──────────────────────────────────────────────────────────
279 The primary is a solid rectangle of ink with letterspaced caps: what
280 a ticket office rubber-stamps. Everything else is the same rectangle
281 ruled rather than filled. */
282
283button,
284[rst-btn] {
285 background: var(--rst-accent);
286 border: 2px solid var(--rst-accent);
287 border-radius: 0;
288 color: var(--rst-on-accent);
289 cursor: pointer;
290 font: inherit;
291 font-size: var(--rst-fs-sm);
292 font-weight: 700;
293 letter-spacing: 0.14em;
294 padding: var(--rst-sp-2) var(--rst-sp-5);
295 text-transform: uppercase;
296}
297
298button:hover {
299 background: var(--rst-accent-strong);
300 border-color: var(--rst-accent-strong);
301}
302
303button:focus-visible {
304 outline: 2px solid var(--rst-accent);
305 outline-offset: 3px;
306}
307
308button[type="button"],
309button[data-cancel],
310button[data-edit],
311button[data-delete] {
312 background: transparent;
313 color: var(--rst-accent);
314}
315
316button[type="button"]:hover,
317button[data-cancel]:hover,
318button[data-edit]:hover,
319button[data-delete]:hover {
320 background: var(--rst-accent-soft);
321 border-color: var(--rst-accent);
322}
323
324/* The row buttons on an item are marginal notes, not stamps. */
325button[data-edit],
326button[data-delete] {
327 border-width: 1px;
328 padding: 0.15rem var(--rst-sp-2);
329}
330
331button:disabled {
332 border-color: var(--rst-line-strong);
333 background: var(--rst-surface-2);
334 color: var(--rst-text-faint);
335 cursor: not-allowed;
336}
337
338/* ── Device 2: the numbering ──────────────────────────────────────────
339 Anything counted prints large, tabular, in the second colour. The
340 numbering machine only ever counts up, which is the same promise the
341 vault epoch and the item version make. */
342
343/* The step overprint: signup's sequence marker, set as a ticket prints
344 one — small, letterspaced, tight under the title rule.
345
346 It is NOT device 2, and it spent one build wrongly claiming to be. The
347 numbering is the second colour, and the second colour is reserved for
348 two things: a count, and something that cannot be undone. A routine
349 "step 1 of 3" is neither, and printing it in the negative ink diluted
350 the one signal this design has for consequence — the review caught
351 exactly that, and it was right.
352
353 So the marker is neutral ink, and the public pages simply do not carry
354 the numbering device, because this product counts nothing on them.
355 Inventing a figure to give the page a red number would be worse than
356 the absence. */
357[rst-steps] {
358 color: var(--rst-text-muted);
359 font-size: var(--rst-fs-xs);
360 font-variant-numeric: tabular-nums;
361 font-weight: 700;
362 letter-spacing: 0.14em;
363 margin: calc(-1 * var(--rst-sp-3)) 0 var(--rst-sp-4);
364 text-transform: uppercase;
365}
366
367/* The handoff code IS a claim check: eight symbols, ten minutes, and the
368 only thing that gets the Account Key across. It prints at the size a
369 cloakroom prints a stub number, because a person is reading it off one
370 screen and typing it into another. */
371[data-code] {
372 color: var(--contra-ink-2);
373 display: block;
374 font-family: var(--contra-display);
375 font-size: clamp(3rem, 12vw, 5rem);
376 font-variant-numeric: tabular-nums;
377 letter-spacing: 0.14em;
378 line-height: 1;
379 margin: var(--rst-sp-3) 0;
380}
381
382/* The three-rung ladder, numbered by the machine. Section numbers are
383 usually decoration; these are not. The rungs are in order of what
384 works with the least, and the last one always works — which is the
385 whole promise of the screen, and it is carried by the order. */
386[data-rungs] {
387 counter-reset: rung;
388 list-style: none;
389 margin: var(--rst-sp-5) 0;
390 padding: 0;
391}
392
393[data-rungs] > li {
394 border-top: 1px solid var(--rst-line);
395 counter-increment: rung;
396 padding: var(--rst-sp-4) 0 var(--rst-sp-4) 3.5rem;
397 position: relative;
398}
399
400[data-rungs] > li::before {
401 color: var(--contra-ink-2);
402 content: counter(rung);
403 font-family: var(--contra-display);
404 font-size: 2.6rem;
405 font-variant-numeric: tabular-nums;
406 inset-block-start: var(--rst-sp-4);
407 inset-inline-start: 0;
408 line-height: 0.8;
409 position: absolute;
410}
411
412[data-rungs] > li > h3 {
413 margin-block-start: 0;
414}
415
416/* Opaque identifiers are machine-printed serials: the account id you
417 hand somebody, the build stamp, a handoff code. Monospace here is
418 measurement, not costume — these are hex and Crockford Base32, and
419 the reader has to transcribe them by hand.
420
421 A serial is printed on a ruled line, not in a grey box. The box also
422 stranded the full stop after "Build 3a8ba10." half a space away from
423 it, which is the kind of thing a chip does to a sentence. */
424code {
425 border-bottom: 1px solid var(--rst-line-strong);
426 font-family: ui-monospace, "SF Mono", "Cascadia Mono", Menlo, Consolas, monospace;
427 font-size: 0.95em;
428 font-variant-numeric: tabular-nums;
429 letter-spacing: 0.06em;
430 word-break: break-all;
431}
432
433/* ── Device 3: the tear-line ──────────────────────────────────────────
434 Exactly one per screen, and only on the real boundary. Above it is
435 what this server holds — opaque ids, counts, times. Below it is what
436 only this browser can read.
437
438 Every product in this category has this line. Most of them would find
439 it embarrassing to draw honestly, which is the reason to draw it.
440
441 A real perforation, not a dashed border: round holes at a fixed pitch
442 with the stock showing through. The caption sits on the line the way
443 a printed instruction does.
444
445 NARROW FIRST, and that is not a stylistic preference. The first version
446 of this was a three-part flex row — dots, caption, dots — with the
447 caption set flex: none. At 390px the caption is wider than the sheet,
448 so both dot segments collapsed to zero width and the text clipped
449 mid-word: on a phone, the app's signature device rendered as neither a
450 perforation nor a sentence, and sat inside the field group breaking the
451 label-over-rule pairing beside it.
452
453 So the default is stacked — a full-width perforation with the caption
454 under it, free to wrap — and the row is the enhancement, taken only
455 once there is room for it. A tear that only works on a desktop is not a
456 tear; it is a decoration that happens to line up. */
457
458[data-tear] {
459 display: grid;
460 gap: var(--rst-sp-2);
461 justify-items: center;
462 margin: var(--rst-sp-6) 0 var(--rst-sp-5);
463}
464
465[data-tear]::before {
466 background-image: radial-gradient(
467 circle at calc(var(--contra-perf) / 2) 50%,
468 var(--rst-line-strong) 1.7px,
469 transparent 1.8px
470 );
471 background-repeat: repeat-x;
472 background-size: var(--contra-perf) 100%;
473 block-size: 9px;
474 content: "";
475 inline-size: 100%;
476}
477
478[data-tear] span {
479 color: var(--rst-text-faint);
480 font-size: var(--rst-fs-xs);
481 font-weight: 600;
482 letter-spacing: 0.12em;
483 text-align: center;
484 text-transform: uppercase;
485 text-wrap: balance;
486}
487
488/* Wide enough for the caption to sit on the line it names. */
489@media (min-width: 48rem) {
490 [data-tear] {
491 align-items: center;
492 display: flex;
493 gap: var(--rst-sp-3);
494 }
495
496 [data-tear]::before,
497 [data-tear]::after {
498 background-image: radial-gradient(
499 circle at calc(var(--contra-perf) / 2) 50%,
500 var(--rst-line-strong) 1.7px,
501 transparent 1.8px
502 );
503 background-repeat: repeat-x;
504 background-size: var(--contra-perf) 100%;
505 block-size: 9px;
506 content: "";
507 flex: 1 1 0;
508 inline-size: auto;
509 min-inline-size: 0;
510 }
511
512 [data-tear] span {
513 flex: 0 1 auto;
514 min-inline-size: 0;
515 }
516
517 /* The separator exists only where the caption is one line. Stacked, the
518 two halves are already two lines and a dot between them would be a
519 mark with nothing to separate — which is how it came to strand at the
520 end of the first line when the caption was a single string. */
521 [data-tear] span + span::before {
522 content: "·";
523 margin-inline: 0.7em;
524 }
525}
526
527/* ── Device 4: the stamp ──────────────────────────────────────────────
528 A notice that states a cost. Not a coloured left border — a stamped
529 block with a rule across the top, which is how a ticket prints a
530 condition of carriage. */
531
532[data-kind="warning"],
533[data-notice] {
534 background: var(--rst-tone-negative-bg);
535 border-top: 3px solid var(--rst-tone-negative-fg);
536 color: var(--rst-text);
537 margin: var(--rst-sp-5) 0;
538 max-width: 68ch;
539 padding: var(--rst-sp-4);
540}
541
542[data-kind="warning"] strong,
543[data-notice] strong {
544 color: var(--rst-tone-negative-fg);
545}
546
547[data-notice] > :first-child,
548[data-kind="warning"] > :first-child {
549 margin-block-start: 0;
550}
551
552[data-notice] > :last-child,
553[data-kind="warning"] > :last-child {
554 margin-block-end: 0;
555}
556
557/* ── Device 5: the stock code ─────────────────────────────────────────
558 Manila, and it means one thing: this vault belongs to somebody else
559 and you are on the list. Colour as a category, never as decoration.
560
561 It is set on the open vault's root by vault.js, so a vault that belongs
562 to somebody else prints its whole contents on different stock — which
563 is the actual cloakroom rule, not a badge saying "shared". A person can
564 tell at a glance whose sheet they are writing on. */
565
566[data-vault][data-shared] {
567 background: var(--contra-stock-2);
568 padding: var(--rst-sp-4);
569}
570
571/* ── Lists: the ticket's line items ───────────────────────────────────
572 Ruled rows, not cards. A card would be a second sheet of paper. */
573
574[data-items],
575[data-members] {
576 border-top: 1px solid var(--rst-accent);
577 list-style: none;
578 margin: var(--rst-sp-4) 0;
579 max-width: 100%;
580 padding: 0;
581}
582
583[data-items] > li,
584[data-members] > li {
585 align-items: baseline;
586 border-bottom: 1px solid var(--rst-line);
587 display: flex;
588 flex-wrap: wrap;
589 gap: var(--rst-sp-2);
590 padding: var(--rst-sp-3) 0;
591}
592
593[data-items] > li > strong {
594 flex: 1 1 12rem;
595 font-weight: 700;
596}
597
598[data-items] > li > span {
599 color: var(--rst-text-muted);
600 flex: 1 1 12rem;
601}
602
603/* ── Status ───────────────────────────────────────────────────────────
604 A live region that reports what just happened. Set like a printed
605 endorsement rather than a toast: it belongs to the sheet. */
606
607[data-status],
608[data-share-status] {
609 color: var(--rst-text-muted);
610 font-size: var(--rst-fs-sm);
611 letter-spacing: 0.06em;
612 min-block-size: 1.4em;
613 text-transform: uppercase;
614}
615
616/* ── Navigation ───────────────────────────────────────────────────── */
617
618[rst-shell-nav] a {
619 display: block;
620 font-size: var(--rst-fs-sm);
621 font-weight: 600;
622 letter-spacing: 0.08em;
623 padding: var(--rst-sp-2) 0;
624 text-decoration: none;
625 text-transform: uppercase;
626}
627
628[rst-shell-nav] a:hover {
629 text-decoration: underline;
630}
631
632/* The disclosures are controls, so they speak the same vocabulary as
633 every other control rather than arriving in title case from the
634 framework's defaults. */
635[rst-shell-menu] > summary,
636[rst-shell-account] > summary {
637 border-radius: 0;
638 font-size: var(--rst-fs-xs);
639 font-weight: 700;
640 letter-spacing: 0.12em;
641 text-transform: uppercase;
642}
643
644/* The overprint that ends the ticket: small, faint, letterspaced, under a
645 hairline. A sheet with nothing at the foot is a sheet that just stops. */
646[data-overprint] {
647 border-top: 1px solid var(--rst-line);
648 color: var(--rst-text-faint);
649 font-size: var(--rst-fs-xs);
650 letter-spacing: 0.12em;
651 margin: 0;
652 padding: var(--rst-sp-3) 0;
653 text-align: start;
654 text-transform: uppercase;
655}
656
657/* The caps stop at the serial. A build hash is an identifier somebody
658 copies, pastes and compares against `carlos channels`; printing it
659 uppercase when it is lowercase everywhere else makes the page lie
660 about a value in the one place the page exists to report it. */
661[data-overprint] code {
662 text-transform: none;
663}
664
665[rst-shell-foot] {
666 margin: 0 auto;
667 max-width: 60rem;
668 padding: 0 var(--rst-sp-4) var(--rst-sp-5);
669 width: 100%;
670}
671
672/* ── The counterfoil ──────────────────────────────────────────────────
673 The server's half of the ticket: everything above the tear, printed on
674 the tint block the way a counterfoil is. It is the only place in the
675 app that changes colour without changing meaning, and the meaning it
676 carries is "this side is theirs". */
677
678[data-counterfoil] {
679 background: var(--rst-surface-2);
680 padding: var(--rst-sp-4);
681}
682
683[data-counterfoil] > :first-child {
684 margin-block-start: 0;
685}
686
687[data-counterfoil] > :last-child {
688 margin-block-end: 0;
689}
690
691/* ── The one authored moment ──────────────────────────────────────────
692 The world's native motion is the tear. So the single piece of motion
693 in this app is the vault opening: the sealed half below the line is
694 revealed once, on unlock, easing out the way paper separates — fast
695 at the start, settling at the end.
696
697 Nothing else animates. Scattered hover transitions would make this
698 read as an effect rather than as the moment it is.
699
700 The default is visible: an engine that ignores the animation, or a
701 reader who asked for less motion, gets the content immediately. */
702
703@keyframes contra-tear {
704 from {
705 clip-path: inset(0 0 100% 0);
706 opacity: 0;
707 }
708 to {
709 clip-path: inset(0 0 0 0);
710 opacity: 1;
711 }
712}
713
714[data-vault]:not([hidden]) {
715 animation: contra-tear 620ms cubic-bezier(0.16, 1, 0.3, 1) both;
716}
717
718@media (prefers-reduced-motion: reduce) {
719 [data-vault]:not([hidden]) {
720 animation: none;
721 }
722}
723
724/* ── Print ────────────────────────────────────────────────────────────
725 The kit is generated as a PDF in the browser and does not come
726 through here, but a person who prints a screen should still get
727 something a cloakroom would recognise: black on white, no chrome. */
728
729@media print {
730 [rst-shell-bar],
731 [rst-shell-rail],
732 [rst-shell-foot],
733 [rst-skip] {
734 display: none;
735 }
736
737 [rst-page] {
738 border: 0;
739 max-width: none;
740 }
741}
742