1/* @clo/terminal DOM renderer. Effective VT defaults occupy renderer-owned
2 custom properties; host theme properties remain the fallback seams. */
3
4@font-face {
5 font-family: "__clo_terminal_primary_34_8_1";
6 src: url("../../fonts/__clo_terminal_primary_34_8_1-Regular.woff2") format("woff2");
7 font-style: normal;
8 font-weight: 400;
9}
10
11@font-face {
12 font-family: "__clo_terminal_primary_34_8_1";
13 src: url("../../fonts/__clo_terminal_primary_34_8_1-SemiBold.woff2") format("woff2");
14 font-style: normal;
15 font-weight: 600;
16}
17
18@font-face {
19 font-family: "__clo_terminal_primary_34_8_1";
20 src: url("../../fonts/__clo_terminal_primary_34_8_1-Italic.woff2") format("woff2");
21 font-style: italic;
22 font-weight: 400;
23}
24
25@font-face {
26 font-family: "__clo_terminal_primary_34_8_1";
27 src: url("../../fonts/__clo_terminal_primary_34_8_1-SemiBoldItalic.woff2") format("woff2");
28 font-style: italic;
29 font-weight: 600;
30}
31
32@font-face {
33 font-family: "__clo_terminal_symbols_3_4_0";
34 src: url("../../fonts/__clo_terminal_symbols_3_4_0-Regular.woff2") format("woff2");
35 font-style: normal;
36 font-weight: 400;
37}
38
39@font-face {
40 font-family: "__clo_terminal_symbols_3_4_0";
41 src: url("../../fonts/__clo_terminal_symbols_3_4_0-Regular.woff2") format("woff2");
42 font-style: normal;
43 font-weight: 600;
44}
45
46@font-face {
47 font-family: "__clo_terminal_symbols_3_4_0";
48 src: url("../../fonts/__clo_terminal_symbols_3_4_0-Regular.woff2") format("woff2");
49 font-style: italic;
50 font-weight: 400;
51}
52
53@font-face {
54 font-family: "__clo_terminal_symbols_3_4_0";
55 src: url("../../fonts/__clo_terminal_symbols_3_4_0-Regular.woff2") format("woff2");
56 font-style: italic;
57 font-weight: 600;
58}
59
60.clo-term-mount,
61.clo-term {
62 /* `--clo-term-font` replaces the TEXT face and nothing else. It resolves to an
63 undefined family when unset, which a stack skips, so the bundled faces stay
64 behind whatever a consumer names — a product font with no box drawing in it
65 still draws boxes. */
66 font-family:
67 var(--clo-term-font, __clo_terminal_consumer_unset), "__clo_terminal_primary_34_8_1",
68 "__clo_terminal_symbols_3_4_0", ui-monospace, "SF Mono", Menlo, monospace;
69 font-size: var(--clo-term-font-size, 13px);
70 line-height: var(--clo-term-line-height, 1.3);
71}
72
73.clo-term {
74 position: relative;
75 overflow: hidden;
76 background: var(--clo-term-effective-bg, var(--clo-term-bg, #1e1e2e));
77 color: var(--clo-term-effective-fg, var(--clo-term-fg, #cdd6f4));
78 font-synthesis: none;
79 user-select: text;
80 cursor: text;
81}
82
83.clo-term:focus {
84 outline: none;
85}
86
87.clo-term.clo-term-font-loading > :not(.clo-term-input) {
88 visibility: hidden;
89}
90
91.clo-term-viewport {
92 position: relative;
93 overflow: hidden;
94}
95
96.clo-term-rows {
97 position: absolute;
98 inset: 0 auto auto 0;
99 white-space: pre;
100 will-change: transform;
101}
102
103.clo-term-row {
104 height: var(--clo-term-cell-h, 1.3em);
105 direction: ltr;
106}
107
108.clo-term-cell {
109 display: inline-block;
110 width: calc(var(--clo-term-cell-columns, 1) * var(--clo-term-cell-w, 1ch));
111 height: var(--clo-term-cell-h, 1.3em);
112 box-sizing: border-box;
113 overflow: hidden;
114 font-kerning: none;
115 font-variant-ligatures: none;
116 line-height: var(--clo-term-cell-h, 1.3em);
117 vertical-align: top;
118}
119
120.clo-term-spacer-head {
121 user-select: none;
122}
123
124/* Browser fallback fonts size CJK and color emoji at one em, which is often
125 only ~1.5 primary-monospace cells. Ghostty says these graphemes occupy two
126 columns, so size their square em to the exact two-cell advance. A compact run
127 carries the same class with `data-columns` counting its ASCII cells, not one
128 grapheme's width, so a two-column run must never be resized. */
129.clo-term-cell[data-columns="2"]:not(.clo-term-compact) {
130 font-size: min(calc(var(--clo-term-cell-w, 1ch) * 2), var(--clo-term-cell-h, 1.3em));
131}
132
133.clo-term-glyph {
134 display: inline-block;
135 transform-origin: center;
136}
137
138/* Filled Powerline separators own the exact cell rectangle instead of using a
139 square fallback-font advance. The text node remains for selection and a11y. */
140.clo-term-powerline {
141 position: relative;
142 width: 100%;
143 height: 100%;
144 vertical-align: top;
145}
146
147.clo-term-powerline > .clo-term-ink {
148 position: absolute;
149 inset: 0;
150 overflow: hidden;
151 text-decoration-color: inherit;
152 -webkit-text-fill-color: transparent;
153}
154
155.clo-term-powerline::before {
156 position: absolute;
157 inset: -0.5px;
158 background: currentColor;
159 content: "";
160}
161
162.clo-term-run.overline > .clo-term-cell > .clo-term-powerline::after,
163.clo-term-run.strikethrough > .clo-term-cell > .clo-term-powerline > .clo-term-ink::before,
164.clo-term-run[class*="underline-"] > .clo-term-cell > .clo-term-powerline > .clo-term-ink::after,
165.clo-term-link:hover > .clo-term-cell > .clo-term-powerline > .clo-term-ink::after {
166 position: absolute;
167 right: 0;
168 left: 0;
169 content: "";
170}
171
172.clo-term-run.overline > .clo-term-cell > .clo-term-powerline::after {
173 top: 0;
174 height: 1px;
175 background: currentColor;
176}
177
178.clo-term-run.strikethrough > .clo-term-cell > .clo-term-powerline > .clo-term-ink::before {
179 top: 50%;
180 height: 1px;
181 background: currentColor;
182}
183
184.clo-term-link:hover > .clo-term-cell > .clo-term-powerline > .clo-term-ink::after {
185 bottom: 0;
186 height: 1px;
187 background: currentColor;
188}
189
190.clo-term-run[class*="underline-"] > .clo-term-cell > .clo-term-powerline > .clo-term-ink::after {
191 bottom: 0;
192 height: 1px;
193 background: var(--clo-term-decoration-color, currentColor);
194}
195
196.clo-term-run.underline-2 > .clo-term-cell > .clo-term-powerline > .clo-term-ink::after {
197 height: 3px;
198 background: linear-gradient(
199 to bottom,
200 var(--clo-term-decoration-color, currentColor) 0 1px,
201 transparent 1px 2px,
202 var(--clo-term-decoration-color, currentColor) 2px 3px
203 );
204}
205
206.clo-term-run.underline-3 > .clo-term-cell > .clo-term-powerline > .clo-term-ink::after {
207 height: 3px;
208 background: var(--clo-term-decoration-color, currentColor);
209 mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='6' height='3'%3E%3Cpath d='M0 2 Q1.5 0 3 2 T6 2' fill='none' stroke='black' stroke-width='1'/%3E%3C/svg%3E")
210 repeat-x bottom / 6px 3px;
211}
212
213.clo-term-run.underline-4 > .clo-term-cell > .clo-term-powerline > .clo-term-ink::after {
214 background: repeating-linear-gradient(
215 to right,
216 var(--clo-term-decoration-color, currentColor) 0 1px,
217 transparent 1px 3px
218 );
219}
220
221.clo-term-run.underline-5 > .clo-term-cell > .clo-term-powerline > .clo-term-ink::after {
222 background: repeating-linear-gradient(
223 to right,
224 var(--clo-term-decoration-color, currentColor) 0 3px,
225 transparent 3px 5px
226 );
227}
228
229.clo-term-powerline-right-arrow::before {
230 clip-path: polygon(0 0, 100% 50%, 0 100%);
231}
232
233.clo-term-powerline-left-arrow::before {
234 clip-path: polygon(100% 0, 0 50%, 100% 100%);
235}
236
237.clo-term-powerline-right-round::before {
238 border-radius: 0 999px 999px 0;
239}
240
241.clo-term-powerline-left-round::before {
242 border-radius: 999px 0 0 999px;
243}
244
245.clo-term-powerline-lower-left::before {
246 clip-path: polygon(0 0, 100% 100%, 0 100%);
247}
248
249.clo-term-powerline-lower-right::before {
250 clip-path: polygon(100% 0, 100% 100%, 0 100%);
251}
252
253.clo-term-powerline-upper-left::before {
254 clip-path: polygon(0 0, 100% 0, 0 100%);
255}
256
257.clo-term-powerline-upper-right::before {
258 clip-path: polygon(0 0, 100% 0, 100% 100%);
259}
260
261/*
262 * Predictive local echo. A prediction is a claim about what the far end will
263 * echo, so it is drawn as a claim: dimmed, and underlined unless the embedder
264 * turns that off. Theming stays custom-property-only like every other color
265 * here, so a host can make speculation invisible without patching the renderer.
266 */
267.clo-term-run.predicted > .clo-term-cell > .clo-term-glyph {
268 opacity: var(--clo-term-predicted-opacity, 0.75);
269}
270.clo-term-run.predicted.underlined > .clo-term-cell > .clo-term-glyph > .clo-term-ink {
271 text-decoration-line: underline;
272 text-decoration-style: dotted;
273 text-decoration-color: var(--clo-term-predicted-underline, currentColor);
274}
275
276.clo-term-run.bold {
277 font-weight: 600;
278}
279.clo-term-run.italic {
280 font-style: italic;
281}
282.clo-term-run.faint > .clo-term-cell > .clo-term-glyph {
283 color: color-mix(in srgb, currentColor 55%, transparent);
284}
285.clo-term-run.invisible {
286 --clo-term-decoration-color: transparent !important;
287 color: transparent;
288}
289.clo-term-run.inverse {
290 color: var(--clo-term-effective-bg, var(--clo-term-bg, #1e1e2e));
291}
292.clo-term-run.inverse > .clo-term-cell {
293 background: var(--clo-term-effective-fg, var(--clo-term-fg, #cdd6f4));
294}
295.clo-term-run.strikethrough {
296 --clo-term-decoration-strike: line-through;
297}
298.clo-term-run.overline {
299 --clo-term-decoration-overline: overline;
300}
301.clo-term-run.strikethrough > .clo-term-cell > .clo-term-glyph,
302.clo-term-run.overline > .clo-term-cell > .clo-term-glyph {
303 text-decoration-line: var(--clo-term-decoration-overline,) var(--clo-term-decoration-strike,);
304 text-decoration-color: currentColor;
305}
306.clo-term-run[class*="underline-"] > .clo-term-cell > .clo-term-glyph > .clo-term-ink {
307 text-decoration-line: underline;
308 text-decoration-color: var(--clo-term-decoration-color, currentColor);
309}
310.clo-term-run.underline-3 > .clo-term-cell > .clo-term-glyph > .clo-term-ink {
311 text-decoration-style: wavy;
312}
313.clo-term-run.underline-4 > .clo-term-cell > .clo-term-glyph > .clo-term-ink {
314 text-decoration-style: dotted;
315}
316.clo-term-run.underline-5 > .clo-term-cell > .clo-term-glyph > .clo-term-ink {
317 text-decoration-style: dashed;
318}
319.clo-term-run.underline-2 > .clo-term-cell > .clo-term-glyph > .clo-term-ink {
320 text-decoration-style: double;
321}
322
323/* One terminal blink clock: ink is visible for the first half-second and
324 hidden for the second. Cell boxes never participate, so backgrounds hold. */
325@keyframes clo-term-blink {
326 0%,
327 49.999% {
328 --clo-term-blink-visibility: visible;
329 }
330 50%,
331 99.999% {
332 --clo-term-blink-visibility: hidden;
333 }
334 100% {
335 --clo-term-blink-visibility: visible;
336 }
337}
338
339.clo-term.clo-term-has-blink {
340 animation: clo-term-blink 1000ms linear infinite;
341}
342
343.clo-term-run.blink > .clo-term-cell > .clo-term-glyph,
344.clo-term-cursor.blinking:not(.blurred) {
345 visibility: var(--clo-term-blink-visibility, visible);
346}
347
348/* Sticky scroll: the command whose output you are scrolled inside, pinned at
349 the top. It overlays row 0 — the standard trade, same as VS Code's. */
350.clo-term-sticky {
351 position: absolute;
352 top: 0;
353 left: 0;
354 right: 0;
355 z-index: 2;
356 white-space: pre;
357 overflow: hidden;
358 text-overflow: ellipsis;
359 cursor: pointer;
360 padding: 0 4px;
361 background: var(--clo-term-sticky-bg, var(--clo-term-bg, #1e1e2e));
362 color: var(--clo-term-sticky-fg, var(--clo-term-fg, #cdd6f4));
363 box-shadow: 0 1px 0 var(--clo-term-sticky-border, rgba(205, 214, 244, 0.18));
364 opacity: 0.95;
365}
366
367.clo-term-has-scrollbar > .clo-term-sticky {
368 right: 13px;
369}
370
371.clo-term-sticky.failed {
372 color: var(--clo-term-sticky-failed, #f38ba8);
373}
374
375/* Links are detected per row; the underline only appears on hover so ordinary
376 output does not read as a wall of links. */
377.clo-term-link:hover > .clo-term-cell > .clo-term-glyph > .clo-term-ink {
378 text-decoration-line: underline;
379 cursor: pointer;
380}
381.clo-term-cursor {
382 position: absolute;
383 z-index: 1;
384 pointer-events: none;
385 background: var(--clo-term-effective-cursor, var(--clo-term-cursor, #f5e0dc));
386 mix-blend-mode: difference;
387}
388
389.clo-term-cursor.style-bar {
390 width: 2px !important;
391}
392
393.clo-term-cursor.style-underline {
394 height: 2px !important;
395}
396
397.clo-term-cursor.style-hollow {
398 background: transparent;
399 box-shadow: inset 0 0 0 1px var(--clo-term-effective-cursor, var(--clo-term-cursor, #f5e0dc));
400}
401
402.clo-term-cursor.blurred {
403 background: transparent;
404 box-shadow: inset 0 0 0 1px var(--clo-term-effective-cursor, var(--clo-term-cursor, #f5e0dc));
405}
406
407@media (prefers-reduced-motion: reduce) {
408 .clo-term.clo-term-has-blink {
409 --clo-term-blink-visibility: visible;
410 animation: none;
411 }
412}
413
414.clo-term-measure {
415 position: absolute;
416 visibility: hidden;
417 top: -9999px;
418 white-space: pre;
419}
420
421.clo-term-scrollbar {
422 position: absolute;
423 top: 3px;
424 right: 3px;
425 bottom: 3px;
426 z-index: 3;
427 width: 10px;
428 border-radius: 999px;
429 background: var(--clo-term-scrollbar-track, transparent);
430 opacity: 0;
431 transition: opacity 120ms ease-out;
432 touch-action: none;
433}
434
435.clo-term:hover > .clo-term-scrollbar,
436.clo-term-scrollbar:focus,
437.clo-term-scrollbar:focus-within {
438 opacity: 1;
439}
440
441.clo-term-scrollbar[hidden] {
442 display: none;
443}
444
445.clo-term-scrollbar-thumb {
446 width: 100%;
447 min-height: 24px;
448 border-radius: inherit;
449 background: var(--clo-term-scrollbar-thumb, rgb(205 214 244 / 28%));
450 transition: background-color 100ms ease-out;
451 will-change: transform;
452}
453
454.clo-term-scrollbar:hover .clo-term-scrollbar-thumb,
455.clo-term-scrollbar:focus .clo-term-scrollbar-thumb {
456 background: var(--clo-term-scrollbar-thumb-hover, rgb(205 214 244 / 48%));
457}
458
459.clo-term-input {
460 position: absolute;
461 width: 1px;
462 height: 1em;
463 padding: 0;
464 border: 0;
465 opacity: 0;
466 font: inherit;
467 resize: none;
468 overflow: hidden;
469}
470
471.clo-term ::selection {
472 background: var(--clo-term-selection, Highlight);
473}
474
475.clo-term-input.composing {
476 width: 20ch;
477 max-width: 100%;
478 opacity: 1;
479 color: inherit;
480 background: var(--clo-term-effective-bg, var(--clo-term-bg, #1e1e2e));
481 caret-color: var(--clo-term-cursor, currentColor);
482}