/* Header overflow menu
 *
 * Holds five rows: search, session theme and detach session (session-
 * scoped, on top - search joined 2026-09-23, above theme, see
 * client/js/header-menu.js's HEADER_SESSION_CONTROL_IDS comment), then
 * logout and settings (app-scoped). THE LAST TWO ARE RE-PARENTED BUT NEVER
 * SHOWN: header-actions.css hides #logoutBtn and #settingsBtn by id (the
 * drawer's bottom bar owns them since 2026-09-22) and an id rule beats
 * `.header-menu-panel button`. They stay as nodes because the drawer bar
 * dispatches to their click handlers. It used
 * to be a phone-only fold of the whole six-icon cluster; between
 * 2026-09-17 and #317 (2026-09-20) it was a permanent overflow with the
 * trigger always visible regardless of width, which is the bug #317
 * reports - a door drawn next to every control it would have opened.
 * The fix is narrower than a full revert: the file editor and the
 * archive icon still never fold (see client/js/header-menu.js's
 * HEADER_TOOL_CONTROL_IDS), but session theme/detach/components/
 * logout/settings are foldable again, and `#header-menu-toggle`'s own
 * visibility now tracks whether anything is actually folded - see
 * `.controls--folded` below. See client/js/header-menu.js for why
 * logout/settings are RE-PARENTED rather than mirrored, why session
 * theme/detach are BUILT here instead, and for what is deliberately kept
 * out.
 *
 * COLOUR COMES FROM THE --oc-* PALETTE NOW, NOT FROM THE SESSION THEME.
 * This menu is app chrome, so it reads the same tokens the operations
 * center dashboard does (web/src/opscenter/tokens.css, already on :root
 * through the compiled bundle) rather than the --color-* theme variables
 * it used to. No import and no new file: the tokens are already there.
 */

/* Anchor for the absolutely positioned panel. */
.controls {
    position: relative;
}

/* VISIBLE ONLY WHILE SOMETHING IS ACTUALLY FOLDED INTO THE PANEL.
 * `.controls--folded` is the ONE condition, toggled by
 * client/js/header-menu.js's applyLayout() from a single `matchMedia`
 * check (`FOLD_QUERY`, 768px) - not a second breakpoint written here to
 * agree or disagree with that one. Below the line, search, session theme,
 * detach, components, logout and settings live in the panel and this is
 * the only way to reach them, so the trigger renders; at or above it
 * they are inline (moved there by `_unfold()`) and there is nothing left
 * in the panel that is not ALSO on screen, so the trigger is not in the
 * layout at all. `#configEditorBtn` is never part of
 * this - it stays inline unconditionally and is never in the panel to
 * begin with. flex-shrink:0 so a long session title elides instead of
 * squeezing the trigger when it is showing. */
.header-menu-toggle {
    display: none;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

.controls--folded .header-menu-toggle {
    display: inline-flex;
}

.header-menu-toggle > svg {
    color: var(--oc-orange);
}

/* The panel itself. Right-aligned under the trigger and pulled toward the
 * thumb: on a phone the top-right corner is the worst reach on the screen,
 * so the PANEL drops down the right edge with generous 44px rows rather
 * than making the user stretch for six separate corner targets. */
.header-menu-panel {
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    z-index: 1100;
    display: none;
    flex-direction: column;
    gap: 2px;
    min-width: 200px;
    padding: 6px;
    /* THE ANCHORED-POPOVER LOOK, STATED ONCE AND APPLIED FOUR TIMES.
     * This menu, the sidebar's row-detail menu, the row kebab and the
     * group menu shared one vocabulary of theme variables
     * (--color-bg-elevated / --color-bg-raised, --color-border,
     * --shadow-modal, --radius-md). They now share one mapping onto the
     * military-terminal palette, written out in full at the top of the
     * panel rule in client/css/session-row-menu.css: raised ground, one
     * hairline, the small radius, and NO drop shadow - the reference
     * separates a floating surface by ground-and-line contrast alone.
     * SUPERSEDED 2026-09-23: the ground, edge, glow and sheen now come
     * from the shared `.popup-focus` class (client/css/popup-focus.css),
     * which client/js/header-menu.js puts on this panel. */
    border-radius: var(--oc-radius-sm);
    /* Never let the menu run off the right edge or under the notch. */
    max-width: calc(100vw - 24px);
    /* MEASURED OVERSHOOT. `100vh` is the LARGE viewport, and this app can
     * never collapse the iOS toolbar to earn it: `body` is
     * `overflow: hidden; height: 100dvh`, so the document never scrolls
     * and Safari has no reason to shrink its chrome. On a 390x844 iPhone
     * that made `100vh` 739px against a 699px visible viewport, so this
     * cap resolved to 643px with only 641px of real space below the 58px
     * header - the menu could overflow the screen by ~2px, permanently.
     * `dvh` is the honest unit here precisely BECAUSE the toolbar cannot
     * collapse: it is pinned at the small viewport, so there is no jitter
     * to trade away. The `vh` line above it is the fallback for engines
     * without dynamic viewport units, which drop the second declaration. */
    max-height: calc(100vh - 96px);
    max-height: calc(100dvh - 96px);
    overflow-y: auto;
}

.header-menu-panel--open {
    display: flex;
}

/* Folded controls become full-width rows: icon left, label right. Width
 * and height are overridden off the 36/40/44px square the base `button`
 * rule gives header icons - inside the panel they are list rows. */
.header-menu-panel button {
    display: flex;
    align-items: center;
    /* The base `button` rule centres its single glyph. In a list that
     * pushes every icon to a different x depending on label width, so
     * rows are explicitly left-aligned here. */
    justify-content: flex-start;
    gap: 12px;
    width: 100%;
    height: auto;
    min-height: 44px;
    padding: 0 12px;
    background: transparent;
    border: none;
    border-radius: var(--oc-radius-sm);
    text-align: left;
    /* The base button rule uses transform on hover; inside a list that
     * reads as a wobble, so rows highlight instead. */
    transform: none;
}

.header-menu-panel button:hover,
.header-menu-panel button:focus-visible {
    background: var(--oc-ground-hover);
    transform: none;
}

/* THE ROW GLYPHS ARE NEUTRAL, AND THE SELECTOR IS LONG FOR A REASON.
 * `.header .controls button > svg` in styles.css pins every header glyph
 * to the accent, which is right for the five icon buttons in the header
 * row and wrong inside this panel: five orange glyphs over five orange
 * labels is the accent used as a frame, which is the one thing this look
 * refuses. That rule is (0,3,1), so this one names the same two ancestors
 * to reach (0,4,1) and win on specificity rather than on load order. The
 * trigger's own glyph is left orange, because out in the header row it is
 * one control among its neighbours and has to match them. */
.header-menu-panel button > svg {
    flex-shrink: 0;
}

.header .controls .header-menu-panel button > svg {
    color: var(--oc-text-secondary);
}

.header .controls .header-menu-panel button:hover > svg,
.header .controls .header-menu-panel button:focus-visible > svg {
    color: var(--oc-text-bright);
}

/* Label text. Taken from the button's own `title`, which is already the
 * lowercase house copy ("home", "detach session", "file editor") and is
 * kept current by whatever code owns each button - a control that swaps
 * its title when it flips state gets this label updated for free.
 *
 * Inside the panel the text is a permanent row label, not a hover
 * tooltip: the app's one tooltip (web/src/lib/tooltip/tooltip.ts, issue
 * #981) is switched off in here by the panel's `data-tooltip-off`. */
.header-menu-panel button::after {
    content: attr(title);
    position: static;
    display: inline;
    opacity: 1;
    visibility: visible;
    transform: none;
    margin: 0;
    padding: 0;
    background: none;
    border: none;
    box-shadow: none;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    text-transform: lowercase;
    font-size: 0.9rem;
    /* --color-fg-primary is defined nowhere in this app, so the
     * --color-accent fallback has always won and every row label in
     * this menu has been orange. A menu of five orange labels is the
     * accent used as a frame, which is what this look does not do. */
    color: var(--oc-text-secondary);
    pointer-events: none;
}

/* WHILE THE POINTER IS ON A ROW its `title` is parked in
 * `data-tooltip-title` by the shared tooltip, which is how the browser's
 * own tooltip is kept from firing (issue #981), so the label reads it from
 * there meanwhile. Same specificity as the rule below and before it, so a
 * short panel label still wins. */
.header-menu-panel button[data-tooltip-title]::after {
    content: attr(data-tooltip-title);
}

/* A row that carries a short panel label wears it instead of its title,
 * which stays the inline control's hover tooltip above the fold width.
 * Same specificity as the rule above, so it has to come after it.
 * header-menu.js sets the attribute when it folds. */
.header-menu-panel button[data-menu-label]::after {
    content: attr(data-menu-label);
}

/* The label follows its glyph on hover, which is the row treatment the
 * dashboard's own menus use (`.oc-menu-item:hover` in
 * web/src/opscenter/engine/CellMenu.svelte). It sets only `color`, which
 * none of the label rules above declares, so order does not decide it. */
.header-menu-panel button:hover::after,
.header-menu-panel button:focus-visible::after {
    color: var(--oc-text-bright);
}

/* The trigger has no label row of its own. */
.header-menu-toggle::after {
    content: none;
}

@media (prefers-reduced-motion: reduce) {
    .header-menu-panel button {
        transition: none;
    }
}

/* SESSION THEME AND DETACH ARE SESSION-SCOPED; THE REST OF THIS MENU IS
 * NOT. `.controls` mounts on every screen, including the launchpad and
 * the auth screen, where "session theme" and "detach session" name
 * nothing. This is the same allow-list gate `#sessionEditorBtn` used to
 * carry in the now-deleted session-editor-header.css, moved onto the two
 * rows it held: hidden everywhere by default, on an id selector so it
 * beats `.btn-icon`'s own `display: flex`, and revealed only while
 * `#terminal-screen` is the active screen. */
#headerSessionThemeBtn,
#headerDetachBtn {
    display: none;
}

body.ps-terminal-active #headerSessionThemeBtn,
body.ps-terminal-active #headerDetachBtn {
    display: flex;
}
