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-29 15:36:16 +08:00
|
|
|
/* The card's own left inset, holding the run-state dot in a column of its own
|
|
|
|
|
so it never competes with the commands for horizontal space. */
|
2026-07-28 18:48:57 +08:00
|
|
|
--dsl-terminal-gutter: 30px;
|
2026-07-28 14:58:06 +08:00
|
|
|
|
|
|
|
|
position: relative;
|
2026-07-29 15:36:16 +08:00
|
|
|
margin: 16px 0;
|
|
|
|
|
/* The gutter is the card's OWN padding, not a margin: every consumer rewrites
|
|
|
|
|
`margin` wholesale (each render site sets its own indent), which silently
|
|
|
|
|
cancelled the reservation and let the dot fall outside the card into a
|
|
|
|
|
container that clips it. Owning the reservation here keeps the invariant
|
|
|
|
|
with the component that depends on it. */
|
|
|
|
|
padding-left: 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;
|
2026-07-29 16:10:37 +08:00
|
|
|
/* Pulled back across the card's gutter padding so the banner background and
|
|
|
|
|
its top-left radius span the FULL surface, then re-inset by the same amount
|
|
|
|
|
so the prompt text and the dot keep their positions. A plain block child
|
|
|
|
|
only reaches the content box, which left the gutter column painted in the
|
|
|
|
|
body color and drew the card's top-left corner in it — invisible in the
|
|
|
|
|
light theme, where banner and body share a token, and visible in the dark
|
|
|
|
|
one, where they do not. */
|
|
|
|
|
margin-left: calc(-1 * var(--dsl-terminal-gutter));
|
|
|
|
|
padding: 9px 14px 9px var(--dsl-terminal-gutter);
|
2026-07-28 14:58:06 +08:00
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-29 15:36:16 +08:00
|
|
|
/* Out of flow inside the card's own gutter padding, so the reservation and the
|
|
|
|
|
dot move together and no consumer margin can pull them apart; the dot neither
|
|
|
|
|
indents its command nor depends on the command's text metrics to line up.
|
|
|
|
|
Centered against the row's line box, not the code font's baseline. */
|
2026-07-28 16:41:04 +08:00
|
|
|
.runState {
|
2026-07-28 18:48:57 +08:00
|
|
|
position: absolute;
|
2026-07-29 15:36:16 +08:00
|
|
|
left: calc(-1 * var(--dsl-terminal-gutter) + 8px);
|
2026-07-28 18:48:57 +08:00
|
|
|
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 {
|
2026-07-29 15:36:16 +08:00
|
|
|
padding: 12px 14px 12px 0;
|
2026-07-28 14:58:06 +08:00
|
|
|
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 {
|
2026-07-29 15:36:16 +08:00
|
|
|
padding: 12px 14px 12px 0;
|
2026-07-28 14:58:06 +08:00
|
|
|
font: var(--dsw-font-markdown-code-block);
|
|
|
|
|
color: var(--dsw-alias-label-tertiary);
|
|
|
|
|
}
|