.board-navigation[hidden] { display:none }
.board-navigation { position:fixed; top:3.3rem; bottom:0; left:0; width:var(--board-nav-width,20rem); max-width:90vw; z-index:1000; box-sizing:border-box; display:flex; flex-direction:column; overflow:hidden; padding:.7rem; color:var(--fg); background:var(--panel); border-right:1px solid var(--line); box-shadow:6px 0 24px #0002; font-size:.85rem }
/* Only the TREE scrolls. The order menu and the search box are how you get back out of a long
   tree, so scrolling them off the top takes the controls away at exactly the moment they are
   wanted. (The embedded panel has always worked this way; this is the same layout, once.) */
.board-navigation > :not(.bn-tree) { flex-shrink:0 }
.bn-toolbar { display:flex; gap:.4rem; align-items:center; margin-bottom:.35rem }
.bn-toolbar > button { flex:none }
.board-navigation button { color:inherit; background:transparent; border:1px solid var(--line); border-radius:5px; padding:.3rem .45rem; cursor:pointer; font:inherit }
.board-navigation input, .board-navigation select { box-sizing:border-box; width:100%; margin:0; padding:.55rem; background:var(--bg); color:var(--fg); border:1px solid var(--line); border-radius:6px; font:inherit }
/* Chrome draws the clear button only while the field has focus, so a search you had typed
   looked like a filter with no way off it the moment you clicked into the tree. It is only
   ever rendered when the field is non-empty, so forcing it visible adds nothing to an empty
   box. */
.board-navigation input[type=search]::-webkit-search-cancel-button { opacity:1 }
.bn-toolbar input[type=search] { flex:1; min-width:0; width:0; padding:.35rem .5rem }
.bn-status { color:var(--dim); font-size:.75rem; margin:.65rem 0 }
.bn-status:empty { display:none }
/* Two panes: Recent on top at a height you can drag, the board tree taking the rest. Both scroll
   on their own so neither pushes the other off; the header above them stays put either way. */
.bn-tree { margin-top:.5rem; overflow:auto; min-height:0; flex:1 }
.bn-recent { flex:0 0 var(--bn-recent-height,16rem); margin-top:.25rem }
/* Nothing in Recent has children, so nothing there has a caret — the gutter the tree needs for one
   is dead space at the head of every row. The rail clearance above is a TREE concern for the same
   reason: with no caret to collide with it, the label simply starts after the rail. */
.bn-recent .bn-line { grid-template-columns:0 minmax(0,1fr) var(--bn-badge-width,.95rem); padding-left:.3rem }
.bn-recent-title { color:var(--dim); font-size:.68rem; letter-spacing:.08em; text-transform:uppercase; margin:.5rem 0 0 }
.bn-empty { color:var(--dim); font-size:.75rem; padding:.3rem .15rem }
/* The divider between them. `.pane-resize` is a column handle by default (the nav's own width
   handle is one); this one splits rows, so it takes the height and the row cursor. */
.board-navigation > .pane-resize.bn-split { width:auto; height:9px; cursor:row-resize; flex:0 0 auto; margin:.1rem 0; position:static;
	background:linear-gradient(var(--line),var(--line)) center/100% 1px no-repeat }
.board-navigation > .pane-resize.bn-split:hover, .board-navigation > .pane-resize.bn-split:focus-visible {
	background:linear-gradient(var(--blue),var(--blue)) center/100% 3px no-repeat }
.bn-refresh { display:inline-flex; align-items:center; gap:.3rem }
.bn-refresh-icon { display:inline-block; line-height:1; width:1em; text-align:center }
.bn-refresh[aria-busy=true] .bn-refresh-icon { animation:bn-refresh-spin .8s linear infinite }
@keyframes bn-refresh-spin { to { transform:rotate(360deg) } }
@media(prefers-reduced-motion:reduce) { .bn-refresh[aria-busy=true] .bn-refresh-icon { animation:none; opacity:.5 } }
.bn-line { padding:.3rem 0; cursor:pointer }
.bn-line button { border:0; text-align:left; padding:.2rem; max-width:85%; vertical-align:middle }
/* Composited on the pane's own background rather than left transparent: a hovered row can be a
   PINNED one, and a see-through row with the tree sliding under it is unreadable. The pane is
   --panel, so this is the same colour it always was. */
.bn-line:hover { background:color-mix(in srgb,var(--fg) 5%,var(--panel)) }
.bn-line small { color:var(--dim); font-size:.65rem; margin-left:.3rem }
.bn-children { padding-left:0; margin-left:calc(.15rem + .8rem / 2 - .5px); border-left:1px solid transparent }
.board-navigation:hover .bn-children { border-left-color:var(--line) }
.board-navigation :focus-visible { outline:1px solid var(--blue); outline-offset:1px }
@media(min-width:801px) {
	body.board-nav-open #shell { margin-left:var(--board-nav-width,20rem) }
	body.board-nav-open #side { display:none!important }
}

.bn-line { position:relative; padding-right:1.5rem }
.bn-line button { max-width:100% }
.bn-badge { position:absolute; right:.15rem; top:.5rem; width:1.1rem; text-align:center; white-space:nowrap; font-size:.85rem!important }
.pane-resize { width:8px; cursor:col-resize; touch-action:none; outline-offset:-2px }
.pane-resize:hover, .pane-resize:focus-visible { background:color-mix(in srgb,var(--blue) 40%,transparent) }
.board-navigation > .pane-resize { position:fixed; top:3.3rem; bottom:0; left:calc(min(var(--board-nav-width,20rem),90vw) - 8px) }

/* Tight. Every row costs a row, and the pane's value is how many fit. Vertical padding is .1rem
   and the gutters are a quarter narrower than they were.
   The LEFT padding is the one number here that is not taste: the selected row paints a 3px rail
   down its edge, and the caret is centred in its gutter, so `paddingLeft + (gutter - caret)/2`
   has to clear that rail or the chevron sits on top of it. navComposer.browser.mjs asserts it. */
/* One line box, three cells. The caret, the label and the badge are three grid items that all
   have to read as sitting on the SAME line, and each used to be placed by its own hand-tuned
   margin against its own line-height — so the digits in a badge and the capitals in a title never
   quite shared a baseline. `--bn-row` is that shared line box: every cell starts at the row's
   padding edge and is 1.3em tall, so identical font sizes land on an identical baseline, and the
   caret is centred in the same band rather than guessed at. */
.bn-line { --bn-row:1.3em; display:grid; grid-template-columns:.8rem minmax(0,1fr) var(--bn-badge-width,.95rem); align-items:start; gap:.2rem; padding:.2rem .25rem .2rem .15rem; list-style:none }
.bn-line::-webkit-details-marker { display:none }
summary.bn-line::before { content:''; color:var(--dim); width:.35rem; height:.35rem; border-right:2px solid; border-bottom:2px solid; margin:calc((var(--bn-row) - .35rem) / 2) auto 0; grid-column:1; transform:rotate(-45deg) }
/* The box is centred on the line; the INK is only centred in one of the two states. The chevron
   is the right and bottom borders of a square: rotated -45° that L lands symmetrically about the
   box's horizontal midline (it leans right instead), but rotated +45° it lands entirely BELOW it,
   its own centre a further s/(2√2) down for a box of side s. So the open state — and only the
   open state — lifts the ink back by that much. */
.bn-node[open] > summary.bn-line::before { transform:translateY(calc(-.35rem / 2.828)) rotate(45deg) }
/* One row, one line. A PR title that wraps to two or three lines turns a list you SCAN into one
   you read, and the pane is the one place where the number of rows on screen is the whole point.
   Nothing is lost: `title` already carries the full text for the tooltip, and the pane is
   resizable when a name really needs the room. */
/* Two lines for an item — its title, then which PR it is and what state it is in — and ONE line
   each. A title that wraps turns a list you scan into one you read; a fixed two-line row keeps
   every row the same height, which is what makes the list scannable at all. Nothing is lost: the
   full identity is the row's tooltip and its accessible name. */
.bn-line .bn-label { grid-column:2; min-width:0; margin:0; padding:0; line-height:var(--bn-row);
	display:block; white-space:nowrap; overflow:hidden; text-overflow:ellipsis }
.bn-label .bn-title, .bn-label .bn-sub { display:block; white-space:nowrap; overflow:hidden; text-overflow:ellipsis }
/* The second line sets its own, tighter line box. `--bn-row` is inherited as a LENGTH, so left
   alone the smaller type would still reserve the title's full line. */
.bn-label .bn-sub { color:var(--dim); font-size:.66rem; font-weight:400; letter-spacing:.01em; margin:0; line-height:1.35 }
.bn-line .bn-badge { grid-column:3; position:static; margin:0; width:auto; line-height:var(--bn-row) }

.bn-unread > .bn-line > .bn-label { font-weight:650; color:var(--fg) }
.bn-node:not(.bn-unread) > .bn-line > .bn-label { color:var(--dim) }
.bn-unread > .bn-line > .bn-badge { color:var(--unread,var(--blue)) }
.bn-line:has(> .bn-label[aria-current]) { background:color-mix(in srgb,var(--blue) 22%,var(--panel)); border-radius:4px }
.bn-line:has(> .bn-label[aria-current])::after { content:''; position:absolute; inset:0; border-radius:inherit; pointer-events:none; background:linear-gradient(to right,var(--blue) 3px,transparent 3px) }
/* Selection is the tinted row plus the blue rail (the rules above); it deliberately does NOT
   bold, because bold is what `.bn-unread` means in this tree — a selected read item drawn
   bold reads as unread. Only the dim colour is lifted, so the current row still reads as
   foreground text. */
.bn-node > .bn-line > .bn-label[aria-current] { color:var(--fg); background:transparent }
.bn-line:has(> .bn-label[aria-current])::before { color:var(--blue) }
.bn-line.bn-working { --bn-badge-width:2.4rem }
/* The ancestor chain stays on screen. A group's row stops at the bottom of its parent's instead
   of scrolling away, so at the bottom of a long board you can still read which board you are in.
   Board tree only — Recent is flat, so it has no chain to keep. `top` and `z-index` are set from
   JS (see pinAncestors): the resting offset is the measured height of the rows above it in its
   own chain, which a stylesheet cannot know because row heights differ by one line.
   The background falls back to `Canvas` rather than to nothing: a pinned row is the one row the
   tree scrolls UNDER, so a host that does not define --panel would get an unreadable one. */
.bn-board summary.bn-line { position:sticky; top:0; z-index:3; background:var(--panel,Canvas) }
.bn-working .bn-badge { display:flex; align-items:center; justify-content:flex-end; gap:.3rem }
.bn-activity { display:inline-block; flex:0 0 .65rem; width:.65rem; height:.65rem; border:2px solid color-mix(in srgb,var(--blue) 25%,transparent); border-top-color:var(--blue); border-radius:50%; animation:bn-refresh-spin .8s linear infinite }
@media(prefers-reduced-motion:reduce) { .bn-activity { animation:none } }
