/* /terminal: the site as a shell. Page layout only (.tm-*); cards and labels reuse code.css rules
   as-is (.pc-label look, .t-card). The --t-* card palette is shared with .pc-term via code.css:569. */

html[data-pg="terminal"] { height: 100%; }

/* body carries .pc too so code.css's base, focus and reduced-motion rules apply; .tm is declared later, so its
   font and overflow win. */
body.tm {
    display: grid;
    grid-template-columns: 13.5rem 1fr;
    grid-template-rows: minmax(0, 1fr);
    height: 100dvh;
    overflow: hidden;
    font: 400 15px/1.5 var(--mono);
}

/* ---------- Sidebar ---------- */

.tm-side {
    display: flex;
    flex-direction: column;
    min-height: 0;
    border-right: 1px solid var(--line);
    padding: var(--gutter);
}

.tm-side__mark {
    display: inline-flex;
    align-items: center;
    gap: 12px;
    width: fit-content;
    font: 400 15.75px/1 var(--mono);
    text-decoration: none;
}

.tm-side__mark .puqqy--nav { width: 36px; height: auto; }
.tm-side__mark i { font-style: normal; color: var(--accent); }

.tm-menu {
    margin-top: auto;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 16px;
    font: 400 13.5px/1.5 var(--mono);
}

.tm-menu a {
    display: flex;
    align-items: center;
    gap: 8px;
    color: var(--ink-2);
    text-decoration: none;
    transition: color 0.2s var(--ease), transform 0.2s var(--ease);
}

.tm-menu a .pc-key { color: var(--ink-3); }
.tm-menu a[aria-current="page"] { color: var(--ink); }
@media (hover: hover) { .tm-menu a:hover { color: var(--ink); transform: translateX(4px); } }

/* Qualified with .tm-menu a: the CTA is a menu link, so it has to outrank `.tm-menu a` and its hover nudge. */
.tm-menu a.tm-side__cta {
    margin-top: 4px;
    padding: 10px 16px;
    background: var(--ink);
    color: var(--bg);
    font: 400 14px/1 var(--sans);
    transition: background-color 0.2s ease;
}
@media (hover: hover) { .tm-menu a.tm-side__cta:hover { background: var(--ink-2); color: var(--bg); transform: none; } }

.tm-menu a:focus-visible,
.tm-side__mark:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 3px;
}

/* ---------- Scrollback ---------- */

.tm-main {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: minmax(0, 1fr) auto;
    min-width: 0;
}

/* The log is the scroll container across the whole column; its children run the full width. */
.tm-log {
    container-type: inline-size;
    overflow-y: auto;
    padding: var(--gutter);
    font: 400 15px/1.65 var(--mono);
}

/* The harness "puq" logo (terminal.php draws it): 24 cells at 12px a cell, never wider than the column. */
.tm-banner {
    display: block;
    width: min(288px, 100%);
    height: auto;
    margin: 0 0 22px;
}

.tm-sub { margin: 0 0 26px; color: var(--ink-3); }
.tm-sub b { color: var(--ink); font-weight: 400; }

.tm-block {
    display: grid;
    grid-template-columns: 12ch minmax(0, 1fr);
    row-gap: 8px;
    padding: 14px 0;
    border-top: 1px solid var(--line);
}

.tm-block:first-of-type { border-top: 0; }
.tm-block__label { grid-column: 1; }
.tm-block > :not(.tm-block__label) { grid-column: 2; min-width: 0; }

.tm-block__label {
    margin: 0;
    font: 400 13.5px/1.5 var(--mono);
    letter-spacing: 0.02em;
    text-transform: lowercase;
    color: var(--ink-3);
}

.tm-dim { margin: 0; color: var(--ink-3); }

.tm-row {
    display: grid;
    grid-template-columns: 4ch minmax(0, 1fr) auto;
    align-items: baseline;
    gap: 0 2ch;
    padding: 2px 0;
    color: var(--ink-2);
}

.tm-row__n,
.tm-row__s { color: var(--ink-3); }
.tm-row__t { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.tm-links {
    margin: 0;
    color: var(--ink-2);
    line-height: 1.8;
}

.tm-links i { font-style: normal; color: var(--ink-3); }

/* The install command as plain shell text, in the boot block and from /install. */
.tm-cmd {
    margin: 0;
    color: var(--ink);
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

.tm-cmd span { color: var(--accent); }

/* ---------- Dock ---------- */

/* The prompt runs the full column, ruled above and below like the scrollback's blocks.
   Stacked above the cookie notice (z-index 90 in code.css) so the autocomplete list paints over it. */
.tm-dock {
    position: relative;
    z-index: 91;
    min-width: 0;
    padding: 0 var(--gutter) max(var(--gutter), env(safe-area-inset-bottom));
    font: 400 15px/1.65 var(--mono);
}

/* .pc-consent (code.css) is position:fixed with its own bottom; sit it above the dock instead,
   using the dock's real height (set by terminal.js) so it never covers the prompt on short
   viewports. The log keeps its newest lines clear of the notice. */
body.tm .pc-consent { bottom: calc(var(--tm-dock-h, 96px) + 12px); }
body.tm .tm-log { padding-bottom: calc(var(--gutter) + var(--tm-consent-h, 0px)); }

.tm-line {
    position: relative;
    display: flex;
    align-items: baseline;
    padding: 14px 0;
    border-block: 1px solid var(--line);
}

/* Opens upward from the prompt's top rule, over the log; exactly eight whole rows tall (+1px for
   the rule), then it scrolls. Rows are a fixed --tm-row so the cap never lands mid-row. */
.tm-suggest {
    --tm-row: 33px;
    position: absolute;
    left: 0;
    right: 0;
    bottom: calc(100% + 1px);
    max-height: calc(8 * var(--tm-row) + 1px);
    overflow-y: auto;
    background: var(--bg);
    border-top: 1px solid var(--line);
    scrollbar-width: none;
}

.tm-suggest__item {
    display: flex;
    justify-content: space-between;
    gap: 3ch;
    height: var(--tm-row);
    padding: 4px 1ch;
    color: var(--ink);
    white-space: pre;
}

.tm-suggest__desc { min-width: 0; overflow: hidden; text-overflow: ellipsis; color: var(--ink-3); }

.tm-suggest__item.is-on,
.tm-suggest__item.is-on .tm-suggest__desc { background: var(--ink); color: var(--bg); }

.tm-line__prompt { flex: none; color: var(--ink); white-space: pre; }
.tm-line__prompt i { font-style: normal; color: var(--ink-3); }
.tm-line__prompt::after { content: ' '; }

.tm-line__wrap {
    position: relative;
    flex: 1 1 auto;
    min-width: 0;
}

.tm-input {
    display: block;
    width: 100%;
    background: none;
    border: 0;
    outline: none;
    padding: 0;
    color: var(--ink);
    font: inherit;
    caret-color: var(--ink);
}

.tm-input::placeholder { color: var(--ink-3); opacity: 1; }

.tm-ghost {
    position: absolute;
    left: 0;
    top: 0;
    color: var(--ink-3);
    opacity: 0.4;
    pointer-events: none;
    white-space: pre;
}

/* ---------- Output ---------- */

/* Every run() prints an echo pill, then zero or more out()/card()/list() rows with no gap between
   them; the next command's echo carries all the vertical rhythm, on the same 14px beat as .tm-block. */
.tm-echo {
    display: block;
    width: fit-content;
    margin: 14px 0 0;
    padding: 3px 10px;
    background: var(--raised);
    color: var(--ink);
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

.tm-echo::before { content: '> '; color: var(--ink-3); }

.tm-out {
    color: var(--ink-3);
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

.tm-out.is-bright { color: var(--ink); }

/* card() reuses .t-card from code.css for the ╭─ title ─╮ frame; its --t-* palette (code.css:569)
   and --t-row only resolve inside .pc-term/.tm-dock/.tm-log, so the row height, font scale and fill
   are set here. Lines are plain <p> tags, unlike the replay's <div class="t-row">, so they need
   their own margin reset. */
.tm-log .t-card {
    --t-row: 1.65em;
    --t-fill: var(--panel);
    font-size: inherit;
}

.tm-log .t-card p { margin: 0; }

/* list(): name and hint columns, plain text. */
.tm-list {
    display: grid;
    grid-template-columns: max-content minmax(0, 1fr);
    gap: 0 3ch;
    white-space: pre-wrap;
}

.tm-list__row { display: contents; }
.tm-list__row > span:first-child { color: var(--ink); }
.tm-list__hint { color: var(--ink-3); overflow-wrap: anywhere; }

.tm-accent { color: var(--accent); }

/* Everything a command prints, echo excluded, lands with the same stagger as .pc-reveal
   elsewhere on the site: terminal.js sets --i to each node's position in the run and flips
   .is-in on next frame; it never adds .tm-in at all under reduced motion. */
.js .tm-in {
    opacity: 0;
    transform: translateY(4px);
    transition: opacity 0.25s var(--ease), transform 0.25s var(--ease);
    transition-delay: calc(var(--i, 0) * 30ms);
}

.js .tm-in.is-in { opacity: 1; transform: none; }

/* ---------- Breakpoints ---------- */

@media (min-width: 901px) {
    .pc-nav { display: none; }
}

@media (max-width: 900px) {
    body.tm { grid-template-columns: 1fr; grid-template-rows: auto minmax(0, 1fr); }
    .tm-side { display: none; }
    .pc-nav { position: static; }
    .tm-dock { position: sticky; bottom: 0; }
}

@media (max-width: 640px) {
    .tm-row__s { display: none; }
    .tm-block { grid-template-columns: 1fr; gap: 6px; }
    .tm-block__label,
    .tm-block > :not(.tm-block__label) { grid-column: 1; }
    .tm-banner { margin-bottom: 14px; }
}
