/* ldu/chrome.css: the app chrome in the LDU look (slice 2), on main's own markup (layouts/application, shared/_sidebar,
   shared/_profile_button, notifications/_menu, notes_shared/_bar).

   The LDU client app's frame (ldu_ui gem, layouts/design_system): an ink-900 top bar (56px) and rail (240px) in BOTH themes
   around the content well, which has a line-dark hairline and a rounded top-left corner where it meets the rail.
   How the bar stays dark in the light theme: the parts that sit on it are wrapped in .hdr__ink / .rail__ink (display: contents)
   or carry a .hdr__face, each pinned data-theme="dark", so fraction-ds redeclares the dark tokens for them. The menus that
   open from the bar (account, tab menu, invitations) sit outside those wrappers and keep the page's theme. The bar and the
   rail themselves paint --chrome-bg, which is ink-900 in both themes.

   Loaded last (after comms/* and the notes sheets), so at equal weight these rules win; every selector is scoped to the
   chrome (.shell > .hdr, .shell > .nav-rail, .notesbar), so the notes pages' own .hdr.page-bar and the Notebooks menu's
   .rail are untouched. Narrow screens keep main's pattern (tabs become the menu under 1100px, the rail an overlay under
   860px), restyled only. Hover: colour, wash or border, 150ms; never a lift or a shadow. Colours are tokens only. */

/* ── the frame ─────────────────────────────────────────────────── */
.shell { background: var(--chrome-bg); }
.hdr__ink, .rail__ink { display: contents; color: var(--ink); }

/* brand | bell and account. The right cluster never wraps or shrinks. The navigation is the rail on the left, not the bar. */
.shell > .hdr {
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 16px;
  height: var(--h-bar);
  padding: 0 20px 0 16px;
  border-bottom: 0;
  background: var(--chrome-bg);
}
.shell > .hdr .hdr__left { gap: 12px; min-width: 0; }

/* The page's way back in the bar (Milan, 19 Oct 2026): brand | trail | bell and account. The brand's column is as wide as the rail, so the trail
   starts on the content's left edge. The trail is a page's breadcrumb (.crumbs, as spans or an <ol>) or the back link, in the bar's dark tokens;
   the in-page copy ([data-topbar-trail]) hides on a wide screen. Under 860px the bar has no trail and the page keeps its own (see the end). */
@media (min-width: 861px) {
  .shell > .hdr { grid-template-columns: minmax(calc(var(--w-rail) - 16px), max-content) minmax(0, 1fr) auto; }
  .shell > .main [data-topbar-trail] { display: none; }
  .shell > .main .page-bar > .hdr__right { grid-column: 3; }   /* a notes page bar (history, graph) keeps its actions at the right */
}
.shell > .hdr .hdr__trail { display: flex; align-items: center; gap: 8px; min-width: 0; padding-left: 16px; color: var(--ink-3); font-size: var(--fs-ui); white-space: nowrap; }
.shell > .hdr .hdr__trail:empty { display: none; }
.shell > .hdr .hdr__trail nav { display: flex; align-items: center; justify-content: flex-start; gap: 8px; min-width: 0; margin: 0; overflow: hidden; font-size: var(--fs-ui); color: var(--ink-3); }
.shell > .hdr .hdr__trail .note-head__trail { display: flex; align-items: center; gap: 12px; min-width: 0; }
.shell > .hdr .hdr__trail ol { display: flex; align-items: center; gap: 8px; min-width: 0; margin: 0; padding: 0; list-style: none; font-size: var(--fs-ui); }
.shell > .hdr .hdr__trail li { display: flex; min-width: 0; }
.shell > .hdr .hdr__trail li + li::before { content: "/"; margin-right: 8px; color: var(--ink-3); }
.shell > .hdr .hdr__trail a { display: inline-flex; align-items: center; gap: 6px; overflow: hidden; color: var(--ink-2); text-decoration: none; text-overflow: ellipsis; transition: color var(--dur); }
.shell > .hdr .hdr__trail a:hover { color: var(--ink); text-decoration: none; }
.shell > .hdr .hdr__trail [aria-current], .shell > .hdr .hdr__trail .crumbs__here,
.shell > .hdr .hdr__trail .room__name, .shell > .hdr .hdr__trail .mono { overflow: hidden; color: var(--ink); font-weight: 500; text-overflow: ellipsis; }
.shell > .hdr .hdr__trail .crumbs__sep { flex: none; color: var(--ink-3); }
.shell > .hdr .hdr__trail .page-no { flex: none; height: 24px; padding: 0 8px; border: 1px solid var(--line); border-radius: var(--r-1); background: none; color: var(--ink-3); font-size: var(--fs-meta); cursor: pointer; transition: color var(--dur), border-color var(--dur); }
.shell > .hdr .hdr__trail .page-no:hover { border-color: var(--line-2); color: var(--ink); }
.shell > .hdr .hdr__trail .backlink { font-size: var(--fs-ui); }
.shell > .hdr .hdr__right { flex: none; flex-wrap: nowrap; gap: 8px; }

.shell > .hdr .brand { padding: 4px 6px; margin-left: -6px; border-radius: var(--r-1); }
.shell > .hdr .brand__words { display: flex; align-items: baseline; gap: 10px; }
.shell > .hdr .brand__wordmark { display: block; width: auto; height: 24px; }
.shell > .hdr .brand__product { color: var(--ink-3); transition: color var(--dur); }
.shell > .hdr .brand:hover .brand__product { color: var(--ink); }

/* ── the bar's buttons: one 36px box, line ring, --r-2 corners ───────
   The bell and the rail button are themselves pinned dark (inside .hdr__ink). A <summary> (the account, the tab menu)
   cannot be wrapped, so its visible box is the .hdr__face inside it and the summary itself is reset to nothing. */
.shell > .hdr .hdr__face {
  box-sizing: border-box;
  align-items: center;
  justify-content: center;
  height: 36px;
  border: 1px solid var(--line);
  border-radius: var(--r-2);
  background: transparent;
  color: var(--ink-2);
  transition: color var(--dur), background-color var(--dur), border-color var(--dur);
}
.shell > .hdr .hdr__face { display: inline-flex; }   /* not .hdr__section: comms/nav.css shows it only under 860px */
.shell > .hdr .hdr__face--bell { position: relative; width: 36px; }
.shell > .hdr .hdr__face--bell .icon { width: 16px; height: 16px; }
.shell > .hdr summary:hover > .hdr__face,
.shell > .hdr details[open] > summary > .hdr__face { background: var(--ldu-wash); border-color: var(--line-2); color: var(--ink); }
/* the unread count: an accent dot on the bell's corner, ringed in the bar's colour so it reads on the dark bar */
.shell > .hdr .notif__badge { top: -5px; right: -6px; z-index: 1; pointer-events: none; box-shadow: 0 0 0 2px var(--chrome-bg); }

.shell > .hdr .notif__bell,
.shell > .hdr .avatar-btn,
.shell > .hdr .notif__bell:hover,
.shell > .hdr .avatar-btn:hover { height: auto; margin: 0; padding: 0; border: 0; border-radius: var(--r-2); background: transparent; box-shadow: none; }
.shell > .hdr summary:focus-visible { outline: none; }
.shell > .hdr summary:focus-visible > .hdr__face { outline: var(--ring-w) solid var(--ring); outline-offset: var(--ring-offset); }


/* the account: the photo or the initials filling the same box */
.shell > .hdr .hdr__face--avatar { width: 36px; overflow: hidden; }
.shell > .hdr .hdr__face--avatar .avatar,
.shell > .hdr .avatar-btn:hover .hdr__face--avatar .avatar {
  width: 100%;
  height: 100%;
  border: 0;
  border-radius: 0;
  background: var(--ldu-wash);
  color: var(--ink);
  font-family: var(--sans);
  font-size: var(--fs-meta);
  font-weight: 600;
  letter-spacing: .02em;
  transform: none;
  transition: background-color var(--dur);
}
.shell > .hdr .avatar-btn:hover .hdr__face--avatar .avatar { background: color-mix(in srgb, var(--ink) 12%, transparent); }

/* the theme switch (in the account menu, and in the bar when signed out): the LDU small segmented control */
.shell > .hdr .theme-switch { gap: 2px; padding: 2px; border: 1px solid var(--line); border-radius: var(--r-2); background: var(--bg-2); }
.shell > .hdr .theme-switch .tab {
  width: 28px;
  height: 28px;
  padding: 0;
  border: 0;
  border-radius: var(--r-1);
  color: var(--ink-2);
  box-shadow: none;
  transition: color var(--dur), background-color var(--dur);
}
.shell > .hdr .theme-switch .tab:hover { background: var(--ldu-wash); color: var(--ink); }
:root[data-theme="dark"] .shell > .hdr .theme-switch .tab[data-fr-theme="dark"],
:root[data-theme="light"] .shell > .hdr .theme-switch .tab[data-fr-theme="light"],
:root:not([data-theme]) .shell > .hdr .theme-switch .tab[data-fr-theme="auto"] { background: var(--ldu-seg-on); color: var(--ldu-seg-on-ink); box-shadow: none; }
/* a tooltip from the dark bar is the bar's own ink box, so it reads on a light page as on a dark one */
.shell > .hdr .hdr__ink [data-tip]:hover::after { background: var(--chrome-bg); color: var(--ink); box-shadow: 0 0 0 1px var(--chrome-line); }

/* ── the menus that open from the bar: the LDU menu, in the page's theme ── */
.shell > .hdr .acct__menu,
.shell > .hdr .notif__panel {
  box-sizing: border-box;
  top: calc(100% + 8px);
  min-width: 0;
  gap: 2px;
  padding: 6px;
  border: 1px solid var(--line);
  border-radius: var(--ldu-r-xl);
  background: var(--bg-2);
  box-shadow: var(--shadow-menu);
}
.shell > .hdr .acct__menu { width: 240px; }
.shell > .hdr .acct__item {
  box-sizing: border-box;
  min-height: 36px;
  gap: 8px;
  padding: 6px 10px;
  border-radius: var(--r-1);
  color: var(--ink);
  font-family: var(--sans);
  font-size: var(--fs-ui);
  line-height: 1.4;
  transition: color var(--dur), background-color var(--dur);
}
.shell > .hdr .acct__item .icon { flex: none; }
.shell > .hdr .acct__item:hover { background: var(--ldu-wash); color: var(--ink); }
.shell > .hdr .acct__item:focus-visible { background: var(--ldu-wash); outline: var(--ring-w) solid var(--ring); outline-offset: -2px; }
.shell > .hdr .acct__item--static,
.shell > .hdr .acct__item--static:hover { padding: 4px 4px 4px 10px; background: transparent; color: var(--ink-2); }
.shell > .hdr .acct__rule { margin: 4px 0; border-top-color: var(--line); }

/* ── the content well ──────────────────────────────────────────── */
.shell > .main { border-top: 1px solid var(--chrome-line); }
/* the side nav stays put and the page scrolls inside this panel, without a second scrollbar drawn inside the rounded panel (Sam) */
.shell > .main { scrollbar-width: none; }
.shell > .main::-webkit-scrollbar { display: none; }
.shell:has(> .nav-rail) > .main { border-left: 1px solid var(--chrome-line); border-top-left-radius: var(--r-well); }

/* ── the rail: the ONE navigation, 240px of ink, always on the left. Each page is a row (its name is a link); a page with sub-pages has a chevron button that
   alone opens and closes its accordion. Hover and focus: colour, wash or border over --dur, never a lift or a shadow. ── */
.shell > .nav-rail { --w-rail: 240px; border-right: 0; background: var(--chrome-bg); }   /* 240 = --w-rail; comms/nav.css pins 232 on .nav-rail */
.shell > .nav-rail .rail__body { display: flex; flex-direction: column; gap: 2px; padding: 12px; overflow-y: auto; }
.shell > .nav-rail .navgrp__head { display: flex; align-items: stretch; gap: 4px; }
.shell > .nav-rail .navgrp__link { flex: 1 1 auto; min-width: 0; }
.shell > .nav-rail .rail__row {
  min-height: 36px;
  padding: 6px 10px;
  border-radius: var(--r-1);
  color: var(--ink-2);
  font-size: var(--fs-ui);
  line-height: 1.4;
  transition: color var(--dur), background-color var(--dur);
}
.shell > .nav-rail .rail__row .icon { flex: none; }
.shell > .nav-rail .rail__row:hover { background: var(--ldu-wash); color: var(--ink); }
.shell > .nav-rail .rail__row--on,
.shell > .nav-rail .rail__row--on:hover { background: var(--accent-soft); color: var(--ink); font-weight: 500; }
.shell > .nav-rail .rail__row--on:hover { background: var(--ldu-on-hover); }
.shell > .nav-rail .rail__row--on .icon { color: var(--accent); }
.shell > .nav-rail .rail__row__meta { font-family: var(--sans); font-variant-numeric: tabular-nums; line-height: 1; color: var(--ink-3); }
.shell > .nav-rail .nav-soon { color: var(--ink-3); }   /* ink-4 is 2:1 on the rail */

/* an accordion row: the whole row is the button (also a .rail__row, so it takes the link rows' hover: the wash and colour, no border); its chevron turns when open. */
.shell > .nav-rail .navgrp__toggle {
  all: unset;
  box-sizing: border-box;
  flex: 1 1 auto;
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 36px;
  padding: 6px 10px;
  border: 1px solid transparent;
  border-radius: var(--r-1);
  color: var(--ink-2);
  font-size: var(--fs-ui);
  line-height: 1.4;
  cursor: pointer;
  transition: color var(--dur), background-color var(--dur), border-color var(--dur);
}
.shell > .nav-rail .navgrp__toggle .rail__row__name { flex: 1 1 auto; }
.shell > .nav-rail .navgrp__toggle:focus-visible { outline: var(--ring-w) solid var(--ring); outline-offset: -2px; }
.shell > .nav-rail .navgrp__toggle[aria-expanded="true"] { color: var(--ink); }
.shell > .nav-rail .navgrp__chev { flex: none; display: inline-flex; color: var(--ink-3); }
.shell > .nav-rail .navgrp__chev .icon { transition: transform var(--dur); }
.shell > .nav-rail .navgrp__toggle:hover .navgrp__chev { color: var(--ink); }
.shell > .nav-rail .navgrp__toggle[aria-expanded="true"] .navgrp__chev .icon { transform: rotate(180deg); }
.shell > .nav-rail .navgrp__items { display: flex; flex-direction: column; gap: 2px; margin: 2px 0 6px 18px; padding-left: 8px; border-left: 1px solid var(--chrome-line); }
.shell > .nav-rail .navgrp__items[hidden] { display: none; }

/* ── the rail's fold button (shared/_sidebar, nav_menu.js; Sam, 30 Oct): folds the rail to 64px of icons. Wide screens only: under 860px the rail is the Menu
   sheet. Folded, the names stay for screen readers (clipped, not removed) and each row's title shows on hover; an open group's pages show as icons too. ── */
.shell > .nav-rail { transition: width var(--dur); }
.shell > .nav-rail .rail__foot { display: none; padding: 8px 12px 12px; border-top: 0; }
.shell > .nav-rail .rail__fold {
  all: unset;
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  justify-content: flex-start;
  gap: 10px;
  min-width: 40px;
  height: 36px;
  padding-inline: 11px 12px;
  border-radius: var(--r-1);
  color: var(--ink-3);
  font-size: var(--fs-ui);
  cursor: pointer;
  transition: color var(--dur), background-color var(--dur);
}
.shell > .nav-rail .rail__fold:hover { background: var(--ldu-wash); color: var(--ink); }
.shell > .nav-rail .rail__fold:focus-visible { outline: var(--ring-w) solid var(--ring); outline-offset: -2px; }
@media (min-width: 861px) {
  .shell > .nav-rail .rail__foot { display: flex; flex-direction: column; align-items: stretch; gap: 2px; } /* Connect your device, then the fold */
  .shell--rail-mini > .nav-rail { --w-rail: 64px; }
  .shell--rail-mini > .nav-rail .rail__body { padding-inline: 8px; overflow-x: hidden; }
  .shell--rail-mini > .nav-rail .rail__row,
  .shell--rail-mini > .nav-rail .navgrp__toggle { justify-content: center; padding-inline: 0; }
  .shell--rail-mini > .nav-rail .navgrp__items { margin-left: 0; padding-left: 0; border-left: 0; }
  .shell--rail-mini > .nav-rail .rail__row__name,
  .shell--rail-mini > .nav-rail .rail__row__meta,
  .shell--rail-mini > .nav-rail .navgrp__chev { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  .shell--rail-mini > .nav-rail .rail__foot { justify-content: center; align-items: center; padding-inline: 8px; }
  .shell--rail-mini > .nav-rail .rail__fold { justify-content: center; padding-inline: 0; }
  .shell--rail-mini > .nav-rail .rail__fold-label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
}
@media (prefers-reduced-motion: reduce) {
  .shell > .nav-rail .navgrp__chev .icon { transition: none; }
}

/* ── the notes bar (Notes in the shell): LDU ghost buttons, Capture outline, the current place accent-soft ── */
.notesbar { box-sizing: border-box; min-height: 56px; gap: 12px; padding: 8px var(--pad-main); border-bottom-color: var(--line); }
.notesbar__places { flex: 1 1 auto; gap: 4px; }
.notesbar .bar__sep { margin: 0 4px; background: var(--line); }
.notesbar__places > turbo-frame > .btn,
.notesbar__places .nbmenu > summary.btn,
.notesbar > .btn--capture {
  box-sizing: border-box;
  height: 36px;
  gap: 6px;
  padding: 0 8px;
  border: 1px solid transparent;
  border-radius: var(--r-2);
  background: transparent;
  color: var(--ink-2);
  font-family: var(--sans);
  font-size: var(--fs-ui);
  font-weight: 500;
  box-shadow: none;
  filter: none;
  transition: color var(--dur), background-color var(--dur), border-color var(--dur);
}
.notesbar__places > turbo-frame > .btn--icon { width: 36px; padding: 0; justify-content: center; }
.notesbar__places > turbo-frame > .btn:hover,
.notesbar__places .nbmenu > summary.btn:hover,
.notesbar__places .nbmenu[open] > summary.btn { background: var(--ldu-wash); color: var(--ink); }
.notesbar__places > turbo-frame > .btn--on,
.notesbar__places > turbo-frame > .btn[aria-current="page"] { background: var(--accent-soft); color: var(--ink); }
.notesbar__places > turbo-frame > .btn--on:hover,
.notesbar__places > turbo-frame > .btn[aria-current="page"]:hover { background: var(--ldu-on-hover); }
/* Capture is outline, like the other chrome actions, so a notes page's own primary (New page) stays the one filled button */
.notesbar > .btn--capture { flex: none; border-color: var(--line); color: var(--ink); }
.notesbar > .btn--capture:hover { background: var(--ldu-wash); border-color: var(--ink-4); color: var(--ink); }
.notesbar .nbmenu__panel { top: calc(100% + 8px); border-color: var(--line); border-radius: var(--ldu-r-xl); background: var(--bg-2); }

/* ── under 860px: the rail is a sheet the bar's Menu button opens; the well is a sheet with both top corners round ── */
@media (max-width: 860px) {
  .shell > .hdr { gap: 8px; padding: 0 12px; }
  .shell > .main,
  .shell:has(> .nav-rail) > .main {
    border-right: 1px solid var(--chrome-line);
    border-left: 1px solid var(--chrome-line);
    border-radius: var(--r-well) var(--r-well) 0 0;
  }
  /* the rail is a dropdown that opens upward out of the floating Menu bar: it fades and rises in, it does not just appear */
  .shell > .nav-rail {
    --w-rail: auto;
    position: fixed;
    inset: auto 12px calc(12px + 48px + 8px + env(safe-area-inset-bottom));
    z-index: 90;
    display: flex;
    width: auto;
    max-height: min(70dvh, 560px);
    border: 1px solid var(--chrome-line);
    border-radius: var(--ldu-r-xl);
    box-shadow: var(--shadow-menu);
    overflow: hidden;
    visibility: hidden;
    opacity: 0;
    transform: translateY(12px) scale(.98);
    transform-origin: bottom center;
    pointer-events: none;
    transition: opacity 200ms ease, transform 200ms ease, visibility 0s linear 200ms;
  }
  body.nav-open .shell > .nav-rail { visibility: visible; opacity: 1; transform: none; pointer-events: auto; transition: opacity 200ms ease, transform 200ms ease, visibility 0s; }
  body.nav-open .shell::after { content: ""; position: fixed; inset: 0; z-index: 85; background: var(--scrim); }
  @media (prefers-reduced-motion: reduce) { .shell > .nav-rail, body.nav-open .shell > .nav-rail { transition: none; transform: none; } }
  body.nav-open { overflow: hidden; }

  /* the notes bar is one row that scrolls sideways; the Notebooks menu hangs from the whole bar, so the scroller cannot clip it */
  .notesbar { padding-inline: 12px; }
  .notesbar__places { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; }
  .notesbar__places > turbo-frame > .btn,
  .notesbar__places .nbmenu > summary.btn { flex: none; }
  .notesbar .nbmenu { position: static; }
  .notesbar .nbmenu__panel { top: calc(100% + 4px); right: 12px; left: 12px; width: auto; }
}

/* ── phones: touch-sized bar controls; Today, Search and Capture are icons (their names stay for screen readers) ── */
@media (max-width: 720px) {
  .shell > .hdr .hdr__face { height: 40px; }
  .shell > .hdr .hdr__face--bell,
  .shell > .hdr .hdr__face--avatar { width: 40px; }
}
/* ── a mid-size window (the rail beside a narrow content well) and phones: Today, Search and Capture fold to icons, so the bar stays one row ── */
@media (max-width: 1180px) {
  .notesbar .btn .kbds { display: none; }
  .notesbar__places > turbo-frame > .btn:has(> .notesbar__label), .notesbar > .btn--capture { position: relative; gap: 0; }
  .notesbar__places > turbo-frame > .btn:has(> .notesbar__label),
  .notesbar > .btn--capture { width: 36px; padding: 0; justify-content: center; }
  .notesbar__label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
}

/* ── the bell's dropdown: work notices and invitations as framed rows ── */
.shell > .hdr .notif__panel { width: 380px; max-height: min(70vh, 560px); overflow-y: auto; padding: 12px; }
@media (max-width: 720px) {   /* a phone: the dropdown hangs from the bar across the screen */
  .shell > .hdr .notif__panel { position: fixed; top: calc(var(--h-bar) + 8px); right: 12px; left: 12px; width: auto; }
}
.notif__head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.notif__title { margin: 0; font-size: var(--fs-ui); font-weight: 600; color: var(--ink); }
.notif__form { display: contents; }
.notif__panel .notif__readall { margin: 0; }
.notif__panel .notif__h { margin: 16px 0 0; font-size: var(--fs-meta); font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: var(--ink-2); }
.notif__panel .notif__list { gap: 8px; margin: 12px 0 0; }
.notif__panel .notif__item { gap: 12px; padding: 10px 12px; border: 1px solid var(--line); border-radius: var(--r-2); background: var(--bg-2); }
.notif__panel .notif__item--new { background: var(--accent-soft); border-color: color-mix(in srgb, var(--accent) 30%, var(--line)); }
.notif__panel .notif__item .btn { flex: none; }
.notif__panel .notif__when { font-size: var(--fs-meta); color: var(--ink-3); }
.notif__panel .pairing__hint { margin: 12px 0 0; }

/* ── very narrow phones: the bar's buttons stay 36px ── */
@media (max-width: 420px) {
  .shell > .hdr .hdr__face--bell,
  .shell > .hdr .hdr__face--avatar { width: 36px; height: 36px; }
}

/* ── phones (under 860px): logo left; bell, theme and account right; the bottom bar with Back (deeper pages) and Menu ── */
.shell > .hdr .hdr__left { display: none; }   /* the shell bar's only: an unscoped rule hid the note page's breadcrumb */
.menubar { display: none; }
@media (max-width: 860px) {
  /* logo top left, the bell, theme and account at the right */
  .shell > .hdr { grid-template-columns: auto minmax(0, 1fr) auto; }
  .shell > .hdr .brand { grid-column: 1; grid-row: 1; }
  .shell > .hdr .hdr__left { display: flex; grid-column: 2; grid-row: 1; justify-self: start; }
  .shell > .hdr .hdr__right { grid-column: 3; grid-row: 1; justify-self: end; }
  .shell > .hdr .brand { margin-left: 0; }
  .shell > .hdr .brand__name { display: inline; }
  .shell > .hdr .brand__product { display: none; }   /* no product name on a phone: the wordmark alone */
  .shell > .hdr .hdr__trail { display: none; }   /* a phone keeps the page's own trail, and the bottom bar's Back; the client portal's in-page back link shows as it is */

  /* one floating pill: the wrapper has no background, border or shadow of its own and lets the page show through and scroll under it */
  .menubar {
    position: fixed;
    inset: auto 0 calc(12px + env(safe-area-inset-bottom));
    z-index: 100;
    display: flex;
    justify-content: center;
    padding: 0;
    pointer-events: none;
  }
  .menubar__btn {
    all: unset;
    box-sizing: border-box;
    pointer-events: auto;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    min-width: 160px;
    min-height: 48px;
    padding: 0 20px;
    border: 1px solid var(--chrome-line);
    border-radius: 999px;
    background: var(--chrome-bg);
    box-shadow: var(--shadow-menu);
    color: var(--ink);
    font-family: var(--sans);
    font-size: var(--fs-ui);
    font-weight: 600;
    cursor: pointer;
    transition: color var(--dur), background-color var(--dur), border-color var(--dur);
  }
  .menubar__btn:hover,
  .menubar__btn:active { background: color-mix(in srgb, var(--chrome-bg) 88%, var(--ink)); border-color: var(--line-2); }
  .menubar__btn:focus-visible { outline: var(--ring-w) solid var(--ring); outline-offset: 2px; }
  .menubar__btn .menubar__open,
  .menubar__btn .menubar__close { align-items: center; gap: 8px; }
  .menubar__btn .menubar__open { display: inline-flex; }
  .menubar__btn .menubar__close { display: none; }
  .menubar__btn[aria-expanded="true"] .menubar__open { display: none; }
  .menubar__btn[aria-expanded="true"] .menubar__close { display: inline-flex; }
  .shell > .main { padding-bottom: calc(72px + env(safe-area-inset-bottom)); box-sizing: border-box; }

  /* Back, on a page deeper than a main page: a round button left of Menu, the same chrome. The slot widens (so the centred Menu
     button slides right) while the button rises in from below; nav_menu.js skips it when the page before had one too. */
  .menubar__slot { display: flex; flex: none; width: 48px; margin-right: 8px; animation: menubar-slot 360ms cubic-bezier(.22, 1, .36, 1) both; }
  .menubar__back {
    box-sizing: border-box;
    pointer-events: auto;
    display: inline-flex;
    flex: none;
    align-items: center;
    justify-content: center;
    width: 48px;
    height: 48px;
    border: 1px solid var(--chrome-line);
    border-radius: 999px;
    background: var(--chrome-bg);
    box-shadow: var(--shadow-menu);
    color: var(--ink);
    transition: background-color var(--dur), border-color var(--dur);
    animation: menubar-back 360ms cubic-bezier(.22, 1, .36, 1) 80ms both;
  }
  .menubar__back:hover,
  .menubar__back:active { background: color-mix(in srgb, var(--chrome-bg) 88%, var(--ink)); border-color: var(--line-2); }
  .menubar__back:focus-visible { outline: var(--ring-w) solid var(--ring); outline-offset: 2px; }
  .menubar--settled .menubar__slot,
  .menubar--settled .menubar__back { animation: none; }
  @media (prefers-reduced-motion: reduce) { .menubar__slot, .menubar__back { animation: none; } }
}
@keyframes menubar-slot { from { width: 0; margin-right: 0; } }
@keyframes menubar-back { from { opacity: 0; transform: translateY(72px); } }

/* the bar is pinned dark for its tokens, and base.css paints every [data-theme] subtree: the wrapper spans the screen, so it stays clear */
body > .menubar[data-theme] { background: none; }

/* ── the agent panel (agent_sessions/_panel): your agent's voice over your chat with it, in the shell's drawer column on every page. The well
   rounds its right corner too, so the panel sits on the chrome like the rail. Above the phone layout only; it narrows with the window down to 320px. ── */
.shell > .agentpanel { display: none; }
@media (min-width: 1024px) {
  .shell > .agentpanel { grid-area: drawer; display: flex; width: clamp(320px, 28vw, 400px); min-height: 0; padding: 0 12px 12px; } /* off the window's right and bottom edges (Sam, 30 Oct) */
  .shell:has(> .agentpanel) > .main { border-right: 1px solid var(--chrome-line); border-top-right-radius: var(--r-well); }
  /* the dashboard's setup helper button: not with the panel (Sam, 30 Oct: "no need this") */
  body:has(.shell > .agentpanel) .fabwrap { display: none; }
  /* folded away (the top bar's panel button, nav_menu.js): the page takes the width, as if there were no panel */
  .shell.shell--panel-closed > .agentpanel { display: none; }
  .shell.shell--panel-closed > .main { border-right: 0; border-top-right-radius: 0; }
}
.hdr__panel-fold { display: none; } /* only where the panel shows */
@media (min-width: 1024px) { .hdr__panel-fold { display: contents; } }
/* a client's Chat for 861 to 1023 px, where the chat is a sheet and the phone bar (under 860) is not there yet: it opens the sheet (Milan, 4 Nov) */
.hdr__chat-sheet { display: none; }
@media (min-width: 861px) and (max-width: 1023px) { .hdr__chat-sheet { display: contents; } }
.agentpanel__card { flex: 1; border-radius: var(--r-well); display: flex; flex-direction: column; gap: 10px; min-height: 0; }
/* the voice card: a portrait beside seven rows of dots (Agency, live/_room_panel_styles); the dots go accent while it speaks or hears you */
.agentpanel__voice { display: flex; align-items: center; gap: 12px; padding: 10px 12px; border: 1px solid var(--line); border-radius: 10px; background: var(--bg); transition: border-color var(--dur); }
.agentpanel__voice--on { border-color: var(--accent); }
.agentpanel__voice .avatar { flex: none; width: 40px; height: 40px; font-size: 14px; }
.agentpanel__stage { flex: 1; min-width: 0; }
.agentpanel__stage .gridviz { gap: 5px; color: var(--ink-3); }
.agentpanel__voice--on .gridviz { color: var(--accent); }
.agentpanel__stage .gridviz__cell { width: 5px; height: 5px; }
/* name, then mic, sound, Call and the phone; the call's problem line wraps under the row */
.agentpanel__bar { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.agentpanel__name { flex: 1; min-width: 0; overflow: hidden; color: inherit; font-weight: 600; text-decoration: none; text-overflow: ellipsis; white-space: nowrap; }
.agentpanel__call { display: contents; }
.agentpanel__call .agentshow__problem { flex-basis: 100%; margin: 0; }
.agentpanel__chat { flex: 1 1 0; display: grid; height: auto; margin: 4px -20px -20px; border-top: 1px solid var(--line); }
/* no lines yet: the empty note sits in the middle of the chat instead of under an empty list */
.agentpanel__chat .transcript:empty { display: none; }
/* the empty chat: a still skeleton of a conversation (agent_sessions/_panel), centred in the frame, with one quiet line under it */
.agentpanel__chat .chatskel { display: grid; gap: 16px; width: 100%; box-sizing: border-box; margin: auto 0; padding: 16px 20px; }
.chatskel__row { display: flex; align-items: flex-start; gap: 10px; }
.chatskel__row--me { justify-content: flex-end; }
.chatskel__face { flex: none; width: 24px; height: 24px; border-radius: 50%; }
.chatskel__lines { flex: 1; display: grid; gap: 8px; padding-top: 4px; }
.chatskel__lines > :nth-child(1) { width: 84%; }
.chatskel__lines > :nth-child(2) { width: 58%; }
.chatskel__lines > :nth-child(3) { width: 36%; }
.chatskel__bubble { width: 52%; height: 30px; border-radius: 12px; }
.chatskel__note { margin: 4px 0 0; text-align: center; }
/* the composer sits on the panel's bottom edge: the agent page's sticky composer stopped 20px short of it (the card's padding) */
.agentpanel__chat .composer { position: static; }
/* the chat as a drop zone (context_drop_controller.js): an accent outline and a wash while a tracker card is over it; the dropped cards wait as chips
   above the box until the next message carries them */
.agentpanel__chat { position: relative; }
.agentpanel__chat.is-drop::after { content: "Drop to add as context"; position: absolute; inset: 8px; display: grid; place-items: center; border: 2px dashed var(--accent);
  border-radius: 12px; background: color-mix(in srgb, var(--accent) 8%, transparent); color: var(--accent); font-weight: 600; pointer-events: none; }
/* in the chat box (agent_sessions/_composer): a full-width row above the field and Send, on the box's own surface */
.agentpanel__chat .composer { flex-wrap: wrap; }
/* a dropped card waits inside the box (Sam, 3 Nov: "a big pill inside the chat, not floating underneath"): with a card in it, the field is the box
   (its border and focus ring), the pills sit above the line being typed, and the textarea inside loses its own border */
.ctxchips { display: grid; gap: 6px; }
.ctxchips[hidden] { display: none; }
.composer__field:has(.ctxchips:not([hidden])) { flex: 1 1 0; flex-direction: column; gap: 6px; padding: 6px; border: 1px solid var(--line-2); border-radius: var(--r-2); background: var(--bg); }
.composer__field:has(.ctxchips:not([hidden])):focus-within { border-color: var(--accent); box-shadow: 0 0 0 var(--ring-w) var(--ring); }
.composer__field:has(.ctxchips:not([hidden])) .composer__input { border: 0; background: transparent; box-shadow: none; outline: none; }
/* a dropped card: a pill with a document mark, its text cut with an ellipsis, its x always showing */
.ctxchip { position: relative; display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: 8px; min-height: 40px; box-sizing: border-box;
  padding: 6px 6px 6px 12px; border-radius: 999px; background: var(--ldu-wash); color: var(--ink); font-size: var(--fs-ui); font-weight: 500; }
.ctxchip::before { content: ""; width: 16px; height: 16px; background: var(--accent);
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z'/%3E%3Cpath d='M14 2v4a2 2 0 0 0 2 2h4'/%3E%3Cpath d='M10 9H8M16 13H8M16 17H8'/%3E%3C/svg%3E") center / contain no-repeat; }
.ctxchip__text { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ctxchip__x { all: unset; display: grid; place-items: center; width: 24px; height: 24px; border-radius: 50%; color: var(--ink-3); font-size: 15px; line-height: 1; cursor: pointer; }
.ctxchip__x:hover { background: var(--bg-2); color: var(--ink); }
.ctxchip__x:focus-visible { outline: var(--ring-w) solid var(--ring); }
/* your line before the server has it (send_echo_controller.js): faded while "Sending…", a dashed danger edge if it did not go */
.agentpanel__chat .msg--pending { opacity: .55; }
.agentpanel__chat .msg--failed .msg__bubble { outline: 1px dashed var(--danger); outline-offset: 2px; }
.agentpanel__chat .msg--failed .msg__who { color: var(--danger); }
/* the main frame (layouts/_main_frame) is only a swap target: it draws no box, so a page that fills the well (the Activity Tracker, a data room)
   still measures 100% against main, as it did before the frame */
.shell > .main > turbo-frame#main { display: contents; }
.agentpanel > turbo-frame#client_panel { display: contents; }
/* one-tap questions for Lia, a row above the chat box (agent_sessions/_panel) */
.agentpanel__asks { display: flex; flex-wrap: wrap; gap: 6px; padding: 8px 12px 0; border-top: 1px solid var(--line); }
.agentpanel__asks + .composer { border-top: 0; }
.shell > .nav-rail .rail__row--soon { opacity: .5; cursor: default; flex-wrap: wrap; row-gap: 0; height: auto; padding-block: 6px; } /* a place on the way: greyed, not a link (Sam, 3 Nov) */
.shell > .nav-rail .rail__row--soon .nav-soon { flex-basis: 100%; margin-left: 24px; font-size: var(--fs-meta); } /* "coming soon" under the name, so a long name is never cut */
/* the client's voice card (Dan, 3 Nov: "make this bigger, my picture centred, the dots beneath it") */
.agentpanel__voice--stacked { flex-direction: column; gap: 14px; padding: 18px 12px 14px; }
.agentpanel__voice--stacked .avatar { width: 96px; height: 96px; font-size: 30px; }
.agentpanel__voice--stacked .agentpanel__stage { width: 100%; flex: none; }
/* the client portal's well floats like Lia's card beside it (Milan, 3 Nov): the same hairline, radius and 12px off the window's edges. It stays the
   height of the window and its page scrolls inside it. A phone keeps the sheet above the bottom bar. */
@media (min-width: 861px) {
  .shell:has(> .agentpanel #client_panel) > .main { margin: 0 12px 12px 0; border: 1px solid var(--line); border-radius: var(--r-well); }
}
@media (min-width: 1024px) {
  .shell:not(.shell--panel-closed):has(> .agentpanel #client_panel) > .main { margin-right: 0; } /* the panel's own 12px sits between the two */
}
/* the bar's buttons are full squares of one size (Milan, 3 Nov): the bell's summary kept the 32px width comms/app.css gives .notif__bell */
.shell > .hdr .notif__bell { width: auto; }
/* the chat toggle (shared/_topbar): the same 36px box with its name beside the icon; pressed, the chat is showing, so it reads as on */
.shell > .hdr .hdr__chat { gap: 8px; padding: 0 12px; font: inherit; font-size: var(--fs-ui); font-weight: 500; cursor: pointer; }
.shell > .hdr .hdr__chat:hover,
.shell > .hdr .hdr__chat[aria-pressed="true"],
.shell > .hdr .hdr__chat[aria-expanded="true"] { background: var(--ldu-wash); border-color: var(--line-2); color: var(--ink); }
.shell > .hdr .hdr__chat:focus-visible { outline: var(--ring-w) solid var(--ring); outline-offset: var(--ring-offset); }
/* a page that scrolls inside the card shows it (Milan, 3 Nov: "a visible indicator when scrolling down"): the platform's quiet bar (ldu/base.css)
   in place of the hidden one above, its track kept clear of the card's rounded corners. Only a page taller than the card has one. */
@media (min-width: 861px) {
  .shell:has(> .agentpanel #client_panel) > .main { scrollbar-width: auto; }
  .shell:has(> .agentpanel #client_panel) > .main::-webkit-scrollbar { display: block; }
  .shell:has(> .agentpanel #client_panel) > .main::-webkit-scrollbar-track { margin: calc(var(--r-well) + 12px) 0; }
  @supports not selector(::-webkit-scrollbar) {
    .shell:has(> .agentpanel #client_panel) > .main { scrollbar-width: thin; }
  }
}
