/* THE TERMINAL PAGE'S GRID WRAPPER, AND THE THREE BOXES BETWEEN IT AND THE
 * PANE.
 * ---------------------------------------------------------------------------
 * A terminal is a grid of character cells, so its box is not a style question:
 * every pixel this file adds between `#terminal-screen` and `.terminal-container`
 * is a column or a row taken away from the session, shipped to tmux as a
 * `pty_resize`, answered with SIGWINCH, and answered by claude with `ESC[2J`,
 * which on the alternate screen erases the conversation the user was reading.
 * So the whole of this file is a chain of boxes that add NOTHING: no padding,
 * no border, no gap and no overflow of their own.
 *
 * `styles.css` IS NOT TOUCHED. It owns `.terminal-container` and it is one of
 * the four files CLAUDE.md pins at the 500 line guideline; `#terminal-grid` is
 * new and belongs in a new focused file. Loaded AFTER it, so a later rule wins
 * where both name the same element, which today is nowhere.
 *
 * THE WRAPPER EXISTS AT EVERY WIDTH; THE GRID INSIDE IT DOES NOT. Below 1024
 * `client/js/terminal-grid-host.js` mounts nothing and the wrapper holds the
 * pane directly, so the pane is full bleed exactly as it was before the wrapper
 * existed. Above 1024 the wrapper holds one `.oc-surface` and the pane is a
 * descendant of the primary cell's body. Both states are the same three
 * declarations, which is why there is no media query here.
 */

/* Takes `.terminal-container`'s own place in `#terminal-screen`'s flex column:
 * `flex: 1` for the space between the header and `.info`, `min-height: 0` so a
 * tall child cannot ratchet the shell past one viewport. */
#terminal-grid {
    flex: 1;
    display: flex;
    flex-direction: column;
    min-width: 0;
    min-height: 0;
}

/* `.oc-surface` is `height: 100%`, which resolves against this wrapper because
 * the wrapper's own height is resolved by the flex column above it. */
#terminal-grid > .oc-surface {
    flex: 1;
    min-height: 0;
}

/* THE SESSION VIEW'S WIDGET RAILS (issue #1472) SIT BESIDE AND UNDER THE GRID, NOT IN IT.
 * While the surface is mounted (above 1024 only) the wrapper is a grid: the
 * surface takes the first column and first row, the SIDE rail
 * (`[data-session-rail][data-rail-edge="side"]`,
 * web/src/lib/session-rail/SessionRail.svelte) the second column at its own
 * fixed width and the FULL HEIGHT of the wrapper (Joe (ccsliinc), 2026-10-10:
 * "the right bar has full height always and the bottom bar is inside the two
 * side bars"), the BOTTOM rail (`[data-rail-edge="bottom"]`, the same
 * component laid out horizontally) the first column's row under the surface,
 * so it ends at the left sidebar and at the side rail, at its own fixed height,
 * each rail's slide-out independent of the other's, and anything else the surface renders in flow (the placement refusal
 * notice) a full-width row after those. A rail with nothing in it is not
 * rendered at all outside edit layout, so it takes no space. A rail's
 * strip is constant; a slide-out PUSHES the grid (Joe (ccsliinc), 2026-10-09:
 * "on sidebar it should resize the main window like the old changes did", and
 * "push up. exactly." for the bottom rail): the side strip takes a left margin
 * of the panel's width and the bottom strip a top margin of its height, so the
 * auto track grows, the pane track shrinks, and the terminals refit through
 * the normal path.
 * Below 1024 nothing here matches and the wrapper stays the flex column above.
 * `.ps-grid-surface` (and `.ps-grid-focus` below) are page flags raised by AbsSurface.svelte, not
 * `:has(> .oc-surface)` / `:has([data-oc-focus])`: a :has() on this wrapper re-ran on every DOM insert
 * in the terminal page (#1940). */
#terminal-grid.ps-grid-surface {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-rows: minmax(0, 1fr);
    grid-auto-rows: auto;
}

#terminal-grid.ps-grid-surface > .oc-surface {
    grid-row: 1;
    grid-column: 1;
    min-width: 0;
}

#terminal-grid.ps-grid-surface > [data-session-rail][data-rail-edge="side"] {
    grid-row: 1 / span 2;
    grid-column: 2;
}

#terminal-grid.ps-grid-surface > [data-session-rail][data-rail-edge="bottom"] {
    grid-row: 2;
    grid-column: 1;
}

#terminal-grid.ps-grid-surface > :not(.oc-surface, [data-session-rail]) {
    grid-row: 3;
    grid-column: 1 / -1;
}

/* THE PAGE'S OWN PANE IS NEVER A ROW OF THIS GRID. While the surface is up the
 * pane belongs in the primary cell (`web/src/opscenter/cells/terminal/adopt.ts`);
 * it is a direct child of this wrapper only before that cell adopts it or after
 * it gives it back. As a row-3 item it was an auto track as tall as its xterm,
 * which left the surface a sliver: below the terminal's size floor, so the frame
 * swapped its body for the misfit plate, the primary cell unmounted and never
 * adopted again, and the page stayed collapsed until a reload (staging
 * 7551821d7, 2026-10-20). Not drawn, it takes no track, the surface keeps its
 * row, and the cell adopts it on the next pass. `display: none` and not an
 * out-of-flow box: a pane measuring zero is refused by the guarded fit, so no
 * wrong grid reaches tmux (the primary cell's `strip` state relies on the same).
 * Measured: tests/python/terminal_grid/test_unadopted_pane_takes_no_room.py. */
#terminal-grid.ps-grid-surface > .terminal-container {
    display: none;
}

/* THE PRIMARY CELL'S BODY, AND THE THREE THINGS IT MUST GIVE UP.
 *
 * `overflow-y: auto` would let the pane scroll inside the cell instead of
 * being fitted to it, so the fit would read a box the user cannot see all of.
 * `contain: layout paint` would make this element a containing block and clip
 * the find panel and the prompt rail at its edges. And the body is a grid item
 * by default, where the pane needs a flex column to stretch into: it is
 * `.terminal-container` itself that carries `flex: 1`, `position: relative` and
 * the padding, and that declaration is the one every overlay on the terminal
 * positions against.
 *
 * Scoped to the primary. A viewer cell in a later slice is an ordinary card and
 * keeps its scrolling body. */
#terminal-grid [data-cell="terminal:@primary"] .oc-frame-body {
    display: flex;
    flex-direction: column;
    min-height: 0;
    overflow: visible;
    contain: none;
}

/* THE COMPONENTS LIST'S CONTAINER, AND THE ROW THAT OPENS IT.
 * ---------------------------------------------------------------------------
 * The container is OUT OF FLOW AND ZERO SIZED. The popover inside it is
 * `position: fixed` and places itself against whatever control opened it, so
 * this box only has to exist somewhere in the document; anything it took up
 * would come out of the pane. It is pinned under the header's right hand
 * cluster so that a browser with no support for the popover's own positioning
 * still opens the list where the control that asked for it is.
 *
 * `overflow: visible` is stated rather than assumed: `#terminal-screen` is
 * `overflow: hidden`, and while a fixed child escapes an overflow ancestor,
 * saying so here is what stops a later `contain` or `transform` on this
 * element turning the popover into a clipped box with no error anywhere. */
#terminal-components {
    position: absolute;
    top: 0;
    right: 0;
    width: 0;
    height: 0;
    overflow: visible;
}

/* THE ENGINE PLACES THE LIST AGAINST THE BUTTON THAT OPENED IT.
 * ---------------------------------------------------------------------------
 * Its one control is the grid button in the agents tab's quick actions, in
 * the drawer's button row (owner, 2026-09-22; it was in the drawer's bottom
 * bar earlier that day). That popover renders inside the drawer and opens
 * below its button (`placement="below"`, web/src/lib/drawer-tabs/), so
 * nothing here re-anchors it. An `!important` override used to pin it under
 * the header; it would drag the list away from the button that asked for it. */

/* The header's own layout button is hidden unless the grid is mounted (next rule): the control
 * moved to the agents drawer's button row (web/src/lib/drawer-tabs/,
 * drawn only while the terminal page's grid is mounted). An id selector,
 * because it has to beat `.btn-icon`'s own `display: flex`. */
#headerComponentsBtn {
    display: none;
}

/* WHILE THE TERMINAL PAGE'S GRID IS MOUNTED the header's layout button is back on screen: it is the page's "+" (arrange this
 * page, add widget) and the motion core's surfaces have no edit mode to find it in. Specificity beats the hide rules above and
 * in header-actions.css; below the header fold the button lives in the kebab panel, which shows it as a menu row. */
body.ps-grid-surface #headerComponentsBtn {
    display: flex;
}

/* NO `.info` HIDING RULE ANY MORE. `.info` (the legacy bottom bar) is
   deleted outright, not merely hidden while the grid is mounted - the
   `:has()` rule that used to suppress it here targeted an element that
   no longer exists. Grid cells provide their own bound controls. */
body.ps-grid-surface .header :is(
    #configEditorBtn, #terminalSearchBtn, #headerSessionThemeBtn, #headerDetachBtn,
    #sessionNotesBtn
) { display: none; }
/* Slightly quiet the inactive pane, without a filter, per-frame JS or changing
   its actual palette. Apply only while another cell owns keyboard input. */
#terminal-grid.ps-grid-focus [data-cell^="terminal:"]:not([data-oc-focus]) .oc-frame-body {
    opacity: 0.88;
}
/* Contain prompt/search overlays inside the pane, clear of the frame edge. */
#terminal-grid [data-cell^="terminal:"] .terminal-container {
    border: 0;
    border-radius: 0;
    min-width: 0;
    overflow: hidden;
}

/* THE LEGACY PANE'S OWN COPY OF THE TOKEN-USAGE BAR (web/src/lib/terminal-
 * foot-bar/). `flex: 0 0 auto` takes it OUT of `#terminal-screen`'s flex
 * column so it never competes with `#terminal-grid`'s `flex: 1` above -
 * `#terminal-grid` shrinks by exactly this bar's own height, the same way
 * it already shrinks for the header above it, and the existing fit pipeline
 * (`client/js/terminal-layout.js`) picks the change up through its
 * ResizeObserver on `#terminal` plus this module's own explicit
 * `requestFit('terminal-foot-bar')` call. Empty and zero height whenever
 * the module blanks it - no session bound, or the grid has taken over and
 * the primary cell's own bar is showing instead - so it never reserves a
 * row of dead space. */
#terminal-foot-bar {
    flex: 0 0 auto;
    min-width: 0;
}

/* ---- The top bar becomes the tab row (issue #452) ---------------------
 *
 * Owner, 2026-09-25: on the terminal page at 1024px and up, each
 * component's tab strip takes the place of the app's top bar and the
 * components run to the top of the screen. The strip is drawn and sized by
 * the component (web/src/opscenter/shell/CellFrame.svelte): it is as tall as
 * the component's title row under it (#514, which replaced the earlier
 * "as tall as the top bar" rule; measured by scripts/verify_terminal_tabs.py).
 * This file only takes the bar away. */

/* THE BAR GOES ONLY WHEN NOTHING IN IT IS STILL NEEDED. At this width the
 * bar's settings and logout are already hidden (the drawer's bottom bar
 * carries both), the kebab shows only when the bar folds, and the search
 * icon is being retired by its own issue. One thing there has no other
 * door, so the bar stays while it is live: the drawer toggle, while the
 * drawer is closed. The message archive button that used to be a second
 * such door is gone (issue #729, the owner, 2026-09-26); it never
 * needs a home in this bar any more, so its `[hidden]` condition was
 * removed rather than kept as a clause that can never be false. */
@media (min-width: 1024px) {
    body.ps-grid-surface.ps-drawer-open .header {
        display: none;
    }
}

/* A PAGE OR REMOTE BROWSER FILLS THE MAIN SECTION, AND ONLY IT (task manager item 439).
 * ---------------------------------------------------------------------------
 * `#browser-screen` sits inside `#terminal-grid`, the wrapper a session's terminal (or the dashboard grid) occupies
 * between the app header and the bottom bar. It is placed over the wrapper's FIRST grid area, so the side rail, the
 * bottom rail and their slide-outs (siblings in the same wrapper) stay visible and usable around it, exactly as they do
 * for a session. Below 1024 the wrapper is a flex column with no rails, and the same box covers it whole.
 * Nothing here sizes the page to dodge anything: the grid area IS the main section.
 *
 * The container is always in the document and EMPTY while nothing shows, so it takes no pointer events itself; the
 * mounted screen (BrowserScreen.svelte) turns them back on. While a page shows, the terminal or grid underneath is
 * hidden (`data-center-page`, set by web/src/lib/browser/center-nav.ts) so no key reaches it. */
#terminal-grid {
    position: relative;
}

/* ONE PIXEL IN FROM EVERY EDGE (Joe (ccsliinc), 2026-10-12, task manager item 551: "a 1px padding on this"): the page or
 * proxy browser sits 1px inside the main section on all four sides. `border-box` keeps the padding inside the inset
 * box, so the mounted `.bscreen` (`height: 100%` of this content box, BrowserScreen.svelte) never overflows or scrolls,
 * in the grid area above 1024 and in the flex column below it. */
#terminal-grid > #browser-screen {
    position: absolute;
    inset: 0;
    box-sizing: border-box;
    padding: 1px;
    z-index: 30;
    pointer-events: none;
}

/* BOTH LINES OF EACH SPAN: an absolutely positioned item's `auto` end line is the grid's padding edge, so `1` alone
 * would run under the rails. `1 / 2` is exactly the surface's own area. */
#terminal-grid.ps-grid-surface > #browser-screen {
    grid-row: 1 / 2;
    grid-column: 1 / 2;
}

#terminal-grid[data-center-page] > .oc-surface,
#terminal-grid[data-center-page] > .terminal-container {
    visibility: hidden;
}
