2026-07-28 14:58:06 +08:00
|
|
|
/* Geometry mirrors CodeBlock (12px radius, code-block surface + banner rows,
|
|
|
|
|
markdown code-block font) so a terminal card and a fenced code block read as
|
|
|
|
|
one family. The one deliberate divergence: output keeps `white-space: pre`
|
|
|
|
|
and scrolls horizontally, because folding a column-aligned command's output
|
|
|
|
|
destroys its alignment. */
|
|
|
|
|
|
|
|
|
|
.block {
|
|
|
|
|
--dsl-terminal-radius: 12px;
|
|
|
|
|
--dsl-terminal-line-height: 22px;
|
2026-07-28 18:48:57 +08:00
|
|
|
/* Reserved strip to the left of the card for the per-line run-state dots.
|
|
|
|
|
The dots sit outside the card surface, so a reader scans command state
|
|
|
|
|
down one column without the dots competing with the commands themselves. */
|
|
|
|
|
--dsl-terminal-gutter: 30px;
|
2026-07-28 14:58:06 +08:00
|
|
|
|
|
|
|
|
position: relative;
|
2026-07-28 18:48:57 +08:00
|
|
|
margin: 16px 0 16px var(--dsl-terminal-gutter);
|
2026-07-28 14:58:06 +08:00
|
|
|
color: var(--dsw-alias-label-primary);
|
|
|
|
|
background: var(--dsw-alias-markdown-code-block);
|
|
|
|
|
border-radius: var(--dsl-terminal-radius);
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-28 18:48:57 +08:00
|
|
|
/* Top-aligned: the status pill and copy control stay on the first prompt row
|
|
|
|
|
however many command lines the card carries. */
|
2026-07-28 14:58:06 +08:00
|
|
|
.header {
|
|
|
|
|
display: flex;
|
2026-07-28 18:48:57 +08:00
|
|
|
align-items: flex-start;
|
2026-07-28 14:58:06 +08:00
|
|
|
gap: 12px;
|
|
|
|
|
padding: 9px 14px;
|
|
|
|
|
background: var(--dsw-alias-markdown-code-block-banner);
|
|
|
|
|
border-top-left-radius: var(--dsl-terminal-radius);
|
|
|
|
|
border-top-right-radius: var(--dsl-terminal-radius);
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-28 18:48:57 +08:00
|
|
|
/* One row per command line. The prompt column is the only element allowed to
|
|
|
|
|
shrink; the status pill and the copy control keep their intrinsic width. */
|
2026-07-28 14:58:06 +08:00
|
|
|
.prompt {
|
|
|
|
|
display: flex;
|
2026-07-28 18:48:57 +08:00
|
|
|
flex-direction: column;
|
2026-07-28 14:58:06 +08:00
|
|
|
min-width: 0;
|
|
|
|
|
flex: 1;
|
|
|
|
|
font: var(--dsw-font-markdown-code-block);
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-28 18:48:57 +08:00
|
|
|
.promptLine {
|
|
|
|
|
position: relative;
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: baseline;
|
|
|
|
|
gap: 8px;
|
|
|
|
|
min-width: 0;
|
|
|
|
|
line-height: var(--dsl-terminal-line-height);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Out of flow in the gutter, so a dot neither indents its command nor depends
|
|
|
|
|
on the command's own text metrics to line up with it. Centered against the
|
|
|
|
|
row's line box rather than sitting on the code font's baseline. */
|
2026-07-28 16:41:04 +08:00
|
|
|
.runState {
|
2026-07-28 18:48:57 +08:00
|
|
|
position: absolute;
|
|
|
|
|
left: calc(-1 * var(--dsl-terminal-gutter));
|
|
|
|
|
top: 50%;
|
|
|
|
|
transform: translateY(-50%);
|
2026-07-28 16:41:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* The dot is aria-hidden; this is its text label for assistive technology. */
|
|
|
|
|
.runStateLabel {
|
|
|
|
|
position: absolute;
|
|
|
|
|
width: 1px;
|
|
|
|
|
height: 1px;
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
clip-path: inset(50%);
|
|
|
|
|
white-space: nowrap;
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-28 14:58:06 +08:00
|
|
|
.cwd {
|
|
|
|
|
flex: none;
|
|
|
|
|
color: var(--dsw-alias-label-tertiary);
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-28 21:03:26 +08:00
|
|
|
/* `pre`, not `nowrap`: the prompt row renders the command verbatim, and
|
|
|
|
|
`nowrap` collapses the repeated spaces, tabs, and alignment of an indented
|
|
|
|
|
continuation. Both hold the single row and the ellipsis. */
|
2026-07-28 14:58:06 +08:00
|
|
|
.command {
|
|
|
|
|
min-width: 0;
|
|
|
|
|
color: var(--dsw-alias-label-primary);
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
text-overflow: ellipsis;
|
2026-07-28 21:03:26 +08:00
|
|
|
white-space: pre;
|
2026-07-28 14:58:06 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.status {
|
|
|
|
|
flex: none;
|
|
|
|
|
color: var(--dsw-alias-state-error-primary);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.copyButton {
|
|
|
|
|
flex: none;
|
|
|
|
|
background-color: transparent;
|
|
|
|
|
border: none;
|
|
|
|
|
padding: 0;
|
|
|
|
|
margin: 0;
|
|
|
|
|
color: var(--dsw-alias-label-secondary);
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
font: var(--dsw-font-xs-13);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.output {
|
|
|
|
|
padding: 12px 14px;
|
|
|
|
|
font: var(--dsw-font-markdown-code-block);
|
|
|
|
|
overflow-x: auto;
|
|
|
|
|
overflow-y: hidden;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* No wrapping, no word-break: alignment is the payload of terminal output. */
|
|
|
|
|
.line {
|
|
|
|
|
min-height: var(--dsl-terminal-line-height);
|
|
|
|
|
white-space: pre;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.expand {
|
|
|
|
|
display: block;
|
|
|
|
|
width: 100%;
|
|
|
|
|
padding: 0;
|
|
|
|
|
border: none;
|
|
|
|
|
background-color: transparent;
|
|
|
|
|
color: var(--dsw-alias-label-tertiary);
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
font: inherit;
|
|
|
|
|
text-align: left;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.expand:hover {
|
|
|
|
|
color: var(--dsw-alias-label-secondary);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.empty {
|
|
|
|
|
padding: 12px 14px;
|
|
|
|
|
font: var(--dsw-font-markdown-code-block);
|
|
|
|
|
color: var(--dsw-alias-label-tertiary);
|
|
|
|
|
}
|