/* =====================================================================
 * Session sidebar + status lights
 * ---------------------------------------------------------------------
 * New CSS file (not appended to the already-oversized styles.css) so
 * this feature's rules stay in one place under the 500-line project
 * convention. Uses the same design tokens defined in styles.css's
 * :root block (colors, radius, font). One token is introduced here,
 * --sidebar-dock-w, because the panel's width and the offset the app
 * makes for it when docked are the same number in two places and drifted
 * apart the moment the docked offset needed arithmetic doing to it.
 * ===================================================================== */

@layer components {
:root {
    /* Width of the sliding panel, and therefore the horizontal space the
     * app gives up when the panel is DOCKED (pinned). Single source of
     * truth for both - see .session-sidebar-panel and the pinned block. */
    --sidebar-dock-w: min(320px, 85vw);
    /* THE PHONE DRAWER'S ONE BAR HEIGHT: the filter field's height, and the
     * whole search row (field, its padding, its hairline). The deep search
     * button and the folded providers bar are both sized from these so the
     * three read as one height (web/src/lib/drawer-tabs/DrawerSearch.svelte,
     * web/src/lib/ledger-drawer/DrawerLedger.svelte). */
    --drawer-field-h: 24px;
    --drawer-bar-h: calc(var(--drawer-field-h) + 2 * var(--oc-space-1) + var(--oc-border));
}

/* PHONE OVERLAY: the drawer reaches to a 36px strip at the right edge (the other
 * operator, 2026-10-10, ask 4: "expand the drawr out to the yellow line";
 * the strip is measured from his screenshot). Overlay mode is
 * innerWidth <= 700 (web/src/lib/drawer/pin.ts MOBILE_MAX_PX); above it the
 * drawer docks at its stored width and this never applies. The strip is the
 * backdrop, so tapping it still closes the drawer. !important is REQUIRED:
 * web/src/lib/drawer/resize.ts writes --sidebar-dock-w inline on <html> at
 * boot, and an inline style beats a normal rule. */
@media (max-width: 700px) {
    :root {
        --sidebar-dock-w: min(calc(100vw - 36px), 480px) !important;
    }
}

/* ---- Hamburger toggle (top-left of the terminal screen header) ----
 *
 * THE CLAW MARK, NO BOX, IN EVERY STATE. Owner's later ruling: put the
 * brand mark back, bare (the transparent glyph, not the boxed app icon),
 * no border, no fill, no rounded plate - open or closed, hovered or not.
 *
 * THE 32px BOX STAYS, and it is not decoration: `--home-header-toggle-w`
 * in styles.css mirrors this width plus the 4px margin, and
 * client/js/header-title-fit.js subtracts this element's outer width from
 * the title's elision budget. Shrinking it would move the header's
 * arithmetic, not just its paint. Everything here is `box-sizing:
 * border-box` (styles.css), so dropping the 1px border changed the ink
 * drawn, never the 32px the layout measures. */

.session-sidebar-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    padding: 0;
    margin-right: var(--oc-space-1);
    background: transparent;
    border: none;
    /* Nothing painted is rounded any more, but the browser's default
     * focus ring follows this radius, so keeping it keeps the keyboard
     * affordance the shape it always had. */
    border-radius: var(--oc-radius-sm);
    cursor: pointer;
    flex-shrink: 0;
    /* The alert center's severity dot (#headerAlertDot) rides this corner. */
    position: relative;
}

.session-sidebar-toggle-mark {
    display: block;
    width: 20px;
    height: 20px;
    object-fit: contain;
    /* Feedback is opacity, not currentColor: the mark is full-colour
     * artwork (a glowing red claw), not a strokeable line icon, so the
     * old ink-colour swap on hover/open has no raster equivalent. Resting
     * state reads as muted; hover or open brings it to full strength -
     * same INTENT as the old rule (something visibly changes), different
     * mechanism. */
    opacity: 0.72;
    transition: opacity 120ms ease;
}

.session-sidebar-toggle:hover .session-sidebar-toggle-mark,
.session-sidebar-toggle[aria-expanded="true"] .session-sidebar-toggle-mark {
    opacity: 1;
}

/* ---- Backdrop --------------------------------------------------- */

.session-sidebar-backdrop {
    position: fixed;
    inset: 0;
    background: var(--oc-backdrop);
    z-index: 1090;
}

.session-sidebar-backdrop[hidden] {
    display: none;
}

/* ---- Sliding panel ------------------------------------------------ */

.session-sidebar-panel {
    position: fixed;
    /* Below the desktop app's title strip (client/css/desktop-chrome.css); 0 in a browser tab. */
    top: var(--desktop-inset-top, 0px);
    left: 0;
    bottom: 0;
    width: var(--sidebar-dock-w);
    /* The drawer is chrome, not a popover: it takes the chrome ground
     * rather than the raised tier, and it is separated by the chrome line
     * on its open edge. client/css/terminal-carnivore.css already paints
     * this panel `--cv-ground-chrome` on the terminal page and loads
     * after this file, so naming the same tier here is what keeps the
     * two from disagreeing anywhere else the panel is drawn. The drop
     * shadow is gone for the reason the popovers' is: the reference
     * separates a sliding surface with a line, never a glow. */
    background: var(--oc-ground-chrome);
    border-right: var(--oc-border) solid var(--oc-line-chrome);
    z-index: 1100;
    display: flex;
    flex-direction: column;
    transform: translateX(-100%);
    /* VISIBILITY IS HALF A BUG FIX, NOT STYLING - do not "simplify" it out.
     * A panel taken off screen by a transform alone is still in the tab
     * order and can still hold document.activeElement, so the sidebar row
     * the user just clicked kept focus while invisible and its keydown
     * handler went on eating ArrowUp/Down, Home/End, Space, Enter and `p`
     * (which silently pins a session). `visibility: hidden` takes the whole
     * subtree out of focus; see SessionSidebarController._releaseFocus().
     *
     * The animation is unchanged, and the two transition lines are what
     * makes that true. Closing: visibility is delayed by 160ms, so it holds
     * `visible` for exactly the length of the slide-out and only then goes
     * hidden. Opening: the delay is 0s, so the panel is visible before the
     * slide-in starts. `visibility` is animatable in discrete steps, which
     * is why this works at all where `display: none` would kill both. */
    visibility: hidden;
    transition: transform 160ms ease, visibility 0s linear 160ms;
}

.session-sidebar-panel--open {
    transform: translateX(0);
    visibility: visible;
    transition: transform 160ms ease, visibility 0s linear 0s;
}

/* ---- PINNED (docked) -------------------------------------------------
 * See web/src/lib/drawer/pin.ts. `.session-sidebar-pinned` lands on
 * <body> only while the bar is pinned AND the viewport is wider than
 * 700px, so the mobile case needs no override here at all - the class is
 * simply never applied. Docked means the bar stops overlaying the app and
 * the app makes room for it instead; the terminal refits itself via its
 * own ResizeObserver (terminal.js), so nothing has to be told about this.
 */

/* ONE TOKEN CARRIES THE DOCK OFFSET, and the surfaces that need it read it.
 * `--dock-offset` is the width the app must leave clear on the left: the
 * drawer's width when docked (here), the icon rail's when railed
 * (session-sidebar-rail.css), nothing otherwise.
 *
 * WHY A TOKEN AND NOT ONE PADDING RULE PER SURFACE. This file sits in
 * `@layer components`, and an unlayered rule beats every layered rule
 * whatever its specificity. `#launchpad-screen { padding: 0 }`
 * (home-bar.css) and `.header { padding-left }` (ios-chrome.css) are still
 * unlayered, so the docked `padding-left` written here for those two
 * selectors LOST to them after design system slice 5 wrapped this file: the
 * home screen and its drawer-side content slid under the docked drawer
 * (Joe (ccsliinc), 2026-09-29: "the homepage is not resizing. its falling
 * under the drawer"). A custom property is not a property those rules set,
 * so it cannot lose; home-bar.css and ios-chrome.css read it inside their
 * own padding declarations. tests/python/design_system/test_dock_offset_
 * reaches_surfaces.py holds that every consumer reads the token.
 *
 * NO TRANSITION HERE, ON PURPOSE. This box is what web/src/lib/drawer/pin.ts
 * measures to refit the terminal, and an animated padding-left used to
 * make that measurement wait out a 160ms transition (transitionend, or a
 * fallback timer if reduced motion dropped it) before the terminal could
 * be told its real size. The final geometry lands in the same frame the
 * class toggles, so the refit can read it immediately; only requestFit's
 * own short debounce (unchanged, see terminal-layout.js) still coalesces a
 * rapid pin/unpin sequence into one resize.
 *
 * THE HOME SCREEN PAYS THE DOCK WIDTH ALONE, NO CONTENT GUTTER (issue
 * #809): the dashboard's `.oc-content` brings its own padding, so an extra
 * gutter only moved its top bar 20px short of the drawer's border.
 * `.header` pays the dock width PLUS --header-pad-x so the toggle does not
 * sit flush against the drawer's border. Only ever active above 700px
 * (pin.ts never applies the body class below that). */
body.session-sidebar-pinned {
    --dock-offset: var(--sidebar-dock-w);
}

.screen {
    padding-left: var(--dock-offset, 0);
}

body.session-sidebar-pinned .session-sidebar-panel {
    /* No drop shadow when docked - a shadow says "floating above", and
     * this is now part of the layout. */
    box-shadow: none;
}

/* ---- Collapse control (sidebar header) ------------------------------
 *
 * One control hides the drawer (the pin and the "x" went on 2026-09-22; docking is decided by viewport width,
 * web/src/lib/drawer/pin.ts). It is drawn by web/src/lib/drawer/DrawerHeader.svelte as the shared bare icon button at the
 * 28px square its neighbours wear, so this file carries no rule of its own for it any more. */

.session-sidebar-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    /* Owner, 2026-09-22: less vertical padding around the wordmark. */
    padding: var(--oc-space-1) var(--oc-space-4);
    border-bottom: 1px solid var(--oc-line-faint);
    flex-shrink: 0;
}

/* THE FILTER BOX (web/src/lib/drawer-tabs/DrawerSearch.svelte) and the
 * stats strip. Never shrink: they sit above the list in the same column, and
 * a scrolling list must be what gives, not these. */
.session-sidebar-search,
.session-sidebar-stats {
    flex-shrink: 0;
}

/* THE SCROLLING PART OF THE DRAWER. Wraps the filter box and the list
 * (client/index.html). Above 1023px it is invisible to layout
 * (`display: contents`), so the list stays the pane's scroller with the box
 * pinned over it. Below 1024 it is the scroller, the list stops scrolling on
 * its own, and the filter box moves away with the rows so a phone gives the
 * height back. */
.session-sidebar-scroll {
    display: contents;
}

@media (max-width: 1023px) {
    .session-sidebar-scroll {
        display: flex;
        flex-direction: column;
        flex: 1 1 auto;
        min-height: 0;
        overflow-y: auto;
        overflow-x: hidden;
    }

    .session-sidebar-scroll > .session-sidebar-list {
        flex: 0 0 auto;
        overflow-y: visible;
    }

    /* While another tab's body shows (edit layout) the list is hidden and this wrapper must not keep its share of
     * the column, or the tab's body sits at the bottom with an empty band above it. */
    .session-sidebar-scroll:has(> .session-sidebar-list[hidden]) {
        display: none;
    }
}

/* `display: flex` on the list, the filter box and the stats would otherwise
 * beat the user agent's `[hidden] { display: none }`, so the `[hidden]` rule
 * here is load bearing: `applyDrawerTab` hides them while another drawer
 * tab's body (edit layout) shows. */
.session-sidebar-list[hidden],
.session-sidebar-search[hidden],
.session-sidebar-stats[hidden] {
    display: none;
}

/* THE BRAND, WHICH IS ALSO THE WAY HOME. It replaced the word "agents"
 * on 2026-09-22.
 *
 * THE HEIGHT IS THE POINT AND IT IS SET HERE, NOT BY THE FILE. Owner:
 * "height of carnivore logo should be a bit taller than the 'agents' is
 * now", then "twice as big" the same day, so 52px, drawing about 156px wide.
 * The artwork is 3:1 (324x108 at 2x, sharp at this size on a retina
 * screen); `width: auto` lets its own ratio decide
 * the width so it is never squashed, and `srcset` in the markup only
 * chooses WHICH file to download, so a retina screen gets the sharp one
 * at this same drawn height rather than one twice as big.
 *
 * Larger than the app header's brand (client/css/header-actions.css) -
 * this is the drawer's title, and it is allowed to be the larger of the
 * two because only one of them is ever on screen at a time. */
.session-sidebar-brand {
    display: inline-flex;
    align-items: center;
    padding: 0;
    background: transparent;
    border: none;
    /* A button that looks like a logo still has to say it is clickable. */
    cursor: pointer;
    flex-shrink: 0;
    border-radius: var(--oc-radius-sm);
    transition: opacity 120ms ease;
}

.session-sidebar-brand img {
    display: block;
    width: auto;
    height: 52px;
    object-fit: contain;
}

.session-sidebar-brand:hover {
    opacity: 0.82;
}

/* THE ALERT CENTER'S BELL SITS BESIDE THE MARK (docs/save-pipeline.md
 * section 4). At the drawer's narrowest (240px) the 156px mark, the bell
 * and the collapse control do not all fit, so the MARK gives way, not the
 * bell: the button may shrink and the image keeps its ratio inside it
 * (`object-fit: contain` above). */
.session-sidebar-heading .session-sidebar-brand {
    flex-shrink: 1;
    min-width: 0;
}

.session-sidebar-heading .session-sidebar-brand img {
    max-width: 100%;
}

.session-sidebar-alerts {
    display: inline-flex;
    align-items: center;
    flex: 0 0 auto;
}

.session-sidebar-alerts:empty {
    display: none;
}

/* THE HOME HEADER'S READOUTS IN THE DRAWER HEADER (Joe (ccsliinc), 2026-09-30, #1157):
 * the inbox door left of the bell and the small clock right of it
 * (web/src/lib/drawer-hud/). The mark takes the spare room, so the three
 * sit together at the header's right, ahead of the collapse control. */
.session-sidebar-heading .session-sidebar-brand {
    margin-right: auto;
}

/* A FLEX COLUMN. The list is the pane's scroller. It once pinned a
 * footer block to its own bottom edge with `margin-top: auto`; nothing is
 * pinned inside it any more, since the ledger panel and the bottom bar
 * each have their own container below it.
 *
 * `flex: 0 0 auto` on the children is NOT decoration. A flex item's
 * default `flex-shrink: 1` would squeeze every row when the list
 * overflows, which is the one thing a scroller must never do. */
.session-sidebar-list {
    flex: 1;
    display: flex;
    flex-direction: column;
    overflow-y: auto;
    /* Explicit, not left to the CSS overflow computed-value rule: setting
     * only overflow-y would compute overflow-x to auto too (the two
     * longhands are not independent once either is non-`visible`), which
     * is how this panel grew a sideways scrollbar nobody asked for (O17). */
    overflow-x: hidden;
    padding: var(--oc-space-2);
}

.session-sidebar-list > * {
    flex: 0 0 auto;
    /* A flex item's default min-width is its own content size, not 0, so
     * a row with a long name refused to shrink below that width even
     * though the list stretches every child to its own width (the default
     * cross-axis `align-items: stretch`). That fought the row's own
     * `overflow: hidden; text-overflow: ellipsis` (session-sidebar-rows.css)
     * and pushed this list wider than the panel (O17). This is what lets
     * the row shrink to the panel's width - the resize handle's own
     * 240-480px range included - so the ellipsis can do its job. */
    min-width: 0;
}

/* THE PROVIDER LEDGER PANEL (web/src/lib/ledger-drawer/DrawerLedger.svelte),
 * pinned under the list in its own container since 2026-09-24 (issue
 * #431). It never grows, so the list above keeps every spare pixel, and
 * it scrolls inside itself past a cap so an expanded panel with many
 * accounts cannot push the list off the pane. The cap is lower on a
 * phone, where the drawer is shorter. */
.session-sidebar-ledger {
    flex: 0 0 auto;
    max-height: 45vh;
    max-height: 45dvh;
    overflow-y: auto;
}

/* THE DYNAMIC TAB BODY REGION (web/src/lib/dynamic-tabs/DynamicTabBody.svelte): a component-body
 * tab (edit layout) takes the column's spare height the way the menu does. */
.session-sidebar-tabbody {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    min-height: 0;
    overflow: hidden;
}

.session-sidebar-tabbody[hidden] {
    display: none;
}

.session-sidebar-area-bar {
    flex: 0 0 auto;
}

/* WHILE EDIT LAYOUT IS ON THE WIDGET DRAWER LIVES IN THIS PANEL, and a card carried out of it draws a
 * position: fixed ghost. A transform (even translateX(0)) makes the panel the containing block of
 * that ghost, so the open panel drops its transform while editing. */
body.oc-layout-editing .session-sidebar-panel--open {
    transform: none;
}

.session-sidebar-ledger[hidden] {
    display: none;
}

@media (max-width: 640px) {
    .session-sidebar-ledger {
        max-height: 38vh;
        max-height: 38dvh;
    }
}

/* NO RESERVATION FOR THE FLOATING BUTTONS UNDER THE BAR, ON PURPOSE.
 * Until 2026-09-22 a phone rule (<=768px) padded the bottom of the bar
 * slot by `--fab-edge + --fab-size + 12px + env(safe-area-inset-bottom)`,
 * about 77px, to keep the terminal's round floating buttons off the
 * drawer's bottom row. It left a dead band under the bar that the owner
 * reported ("a ton of empty space at the bottom of the drawer on
 * mobile"), and it could not clear anything:
 *
 * 1. The drawer paints ABOVE every floating button. The panel is
 *    z-index 1100 and its backdrop 1090; the one floating button left on
 *    the terminal screen, `.fab-menu-btn` (client/css/terminal-tools.css),
 *    is z-index 60. The d-pad and slash buttons the rule was written for
 *    are deleted. Measured at 375x812 with the drawer open: the menu
 *    button's box (x 310-355) lies partly under the 319px drawer, and the
 *    point at its centre hits the backdrop, not the button.
 * 2. The home indicator is ALREADY cleared once. client/css/ios-chrome.css
 *    pads `.session-sidebar-panel` by env(safe-area-inset-bottom), so the
 *    inset this rule added was a second copy of it.
 *
 * So the slot takes only the bar's own height, and the panel's single
 * safe-area padding is the only bottom clearance. Locked by
 * tests/test_drawer_bottom_clearance.node.mjs.
 *
 * Since 2026-09-22 (the mobile paste change) `.fab-menu-btn` is deleted
 * too: its tools menu opens from the clipboard key in the in-flow key row
 * under the pane, so no floating button is left on the terminal screen. */

.session-sidebar-empty {
    padding: var(--oc-space-5) var(--oc-space-3);
    text-align: center;
    color: var(--oc-text-secondary);
    font-size: 0.85em;
}

/* ---- The drawer's bottom bar ----------------------------------------
 *
 * Owner, 2026-09-22: "move the settings and logout and gridview buttons
 * in the top right of the header to the bottom of the drawer: in it's own
 * bottom bar", laid out "[Settings] [grid] [version] [logout]".
 *
 * The grid button moved to the drawer's quick actions the same day (it is
 * edit layout's job now).
 *
 * Since 2026-09-30 (Joe (ccsliinc), the account chip) the bar is two
 * parts, not three columns: the account chip on the left, whose menu holds
 * settings, help, edit layout, master all and log out, and the light and
 * the version on the right. */

/* The bar's own slot below the list (client/index.html): it takes its
 * height and never grows, so the list above keeps every spare pixel. */
.session-sidebar-bar-slot {
    flex: 0 0 auto;
}

.session-sidebar-bar {
    /* THE CHIP LEFT, THE VERSION RIGHT (Joe (ccsliinc), 2026-09-30: "we can
     * move the version to the right"). A flex row, not the old three column
     * grid: the account chip (client/css/session-sidebar-account-chip.css)
     * takes the room and truncates its name; the version group is pushed to
     * the end and may shrink too, capped at half the bar, so a long preview
     * build string ("1.12.20-preview.130.ge449555") truncates instead of
     * squeezing the chip to nothing or painting over it. */
    display: flex;
    align-items: center;
    gap: var(--oc-space-2);
    padding: 6px var(--oc-space-2);
    border-top: 1px solid var(--oc-line-faint);
}

.session-sidebar-bar__group {
    display: flex;
    flex: 1 1 auto;
    align-items: center;
    gap: 2px;
    min-width: 0;
}

.session-sidebar-bar__version {
    /* THE VERSION NEVER TRUNCATES: it is the short form (v1.12.21, plus a tiny
     * preview marker), it keeps its width, and the account chip's name gives
     * way instead. */
    flex: 0 0 auto;
    margin-left: auto;
    /* The lit crown (master all on), the live-channel light, then the
     * version, at the bar's right end. */
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 0;
    text-align: right;
    /* The version chip brings its own type from
     * client/css/version-footer.css; this only places it. */
    white-space: nowrap;
}

/* The bar's buttons are the base IconButton, variant quiet (web/src/lib/base/icon-button.css),
 * 28px square through its size token, with the bar's own accent on hover. */
.session-sidebar-bar__version > [data-bar-action] {
    --oc-ibtn-size: 28px;
    flex-shrink: 0;
    border-radius: var(--oc-radius-sm);
    color: var(--oc-text-secondary);
}

.session-sidebar-bar__version > [data-bar-action]:hover:not(:disabled),
.session-sidebar-bar__version > [data-bar-action]:focus-visible {
    color: var(--oc-orange);
}

/* A LIT INDICATOR (the armed beast bolt, client/css/session-sidebar-account-chip.css) draws in the danger token: the rule above
 * paints every bar button secondary ink and would win over the indicator's own color, so this one is a step stronger. The QUIET
 * one is left out on purpose and keeps the secondary ink, dimmed. Hover still takes the accent (its rule is stronger again). The
 * indicator sits close to the crown so the two read as one group. */
.session-sidebar-bar__version > [data-bar-indicator]:not([data-bar-indicator-quiet]) {
    color: var(--oc-coral);
}

/* ONE GROUP (#2701, Joe (ccsliinc), 2026-10-29: "pull the master and Beast Mode icons together, next to the version"): the bar
 * buttons are 28px boxes around a 15px glyph, so each next one pulls in by one space step and the glyphs sit a few px apart; the
 * version then follows at the same tight distance. Desktop only: from 1023px down the base icon button is the 44px touch box
 * (web/src/lib/base/icon-button.css) and must not overlap, so the same breakpoint gates this pull-in. */
@media (min-width: 1024px) {
    .session-sidebar-bar__version > [data-bar-action] + [data-bar-action] {
        margin-left: calc(-1 * var(--oc-space-1));
    }
}

.session-sidebar-bar__version > [data-bar-action] + .version-footer {
    margin-left: var(--oc-space-1);
}

/* A PREVIEW BUILD'S MARKER (drawn by client/js/version-footer.js): the word
 * "preview" after the short version, tiny tracked capitals in the dim ink, so
 * the build still reads as one quiet fact. */
.session-sidebar-bar__version .version-footer__preview {
    margin-left: var(--oc-space-1);
    color: var(--oc-text-dim);
    font-size: var(--oc-fs-micro);
    letter-spacing: var(--oc-tracking-label);
    text-transform: uppercase;
}

.session-sidebar-bar__version .version-footer {
    min-width: 0;
    margin: 0;
}

/* A FINGER NEEDS MORE THAN 28px. Same reasoning as the row menu's
 * coarse-pointer rule in client/css/session-row-menu.css; the account chip's
 * own rule is in client/css/session-sidebar-account-chip.css. */
@media (pointer: coarse) {
    .session-sidebar-bar__version > [data-bar-action] {
        --oc-ibtn-size: 40px;
    }
}
}
