/* ===========================================================
   Thesis A — Portal navigation
   The shared chrome for every brain in The Inventors' Portal:
   a left sidebar (TI symbol · organization · brain switcher ·
   role-gated groups → views) plus a slim top bar (breadcrumb ·
   search · theme · user/settings menu).

   Framework-neutral: ship the markup in Lit / React / plain HTML,
   filter groups by role BEFORE rendering, and include
   shell/portal-nav.js for the interactive polish.

   Rules honoured: one accent per brain — the per-brain identity
   tokens below (--brain-accent-*) are the SINGLE source; the shell
   applies them per active brain via .portal-shell[data-brain], and
   brains.ts points each brain dot at the same token. Status colours
   only on state; no invented values — every value is a token or
   derived from one (color-mix).
   The org/brain switcher dropdown menus draw z-index from the portal's shared
   z-index scale (--z-dropdown, defined in portal/src/styles/z-index.css and
   loaded document-wide by the React app's main.tsx) rather than a raw number.
   =========================================================== */

/* ===========================================================
   One accent per brain (FB 019f5d84, 019f5d86)
   Each tool ran three colour schemes at once: the switcher dot read
   brains.ts, the page/theme accent read the global <body
   class="accent-magenta"> (so every brain's pages looked "red"), and
   the sidebar hover read a per-GROUP --group-color (yellow/blue/…).
   These tokens are now the ONE source per brain. Consumed by:
   (a) the switcher dropdown dot — brains.ts colours reference them;
   (b) the sidebar hover/active — the hover rules below use
       --color-accent instead of the retired per-group colour;
   (c) the brain's own theme — the body:has() rules re-point
       --color-accent(+-readable) while that brain's shell is mounted
       (body-level, so portalled overlays/modals match too; outranks
       the static .accent-magenta body class by specificity).
   =========================================================== */
:root {
  --brain-accent-campaigns:      var(--brand-magenta);
  --brain-accent-grid:           var(--brand-cyan);
  --brain-accent-schools:        var(--brand-cyan);
  /* Finance + Production ride the seven-star teal (same #0e7490 the
     FinanceShell/ProductionShell chrome pins — FB 019f3714 precedent). */
  --brain-accent-finance:        #0e7490;
  --brain-accent-production:     #0e7490;
  --brain-accent-operations:     var(--brand-purple);
  --brain-accent-recruitment:    var(--brand-navy);
  --brain-accent-thinkingmachine:var(--brand-cyan);
  --brain-accent-agent:          var(--brand-cyan);
  /* Video Studio rides the warm ink the brand's own colours make when magenta meets
     yellow — the one temperature no brain had claimed, and the right one for a tool
     that renders film. Derived from brand tokens (as --ink-orchid/--ink-indigo are in
     fable-shell.css), not a fifth invented hex. */
  --brain-accent-videostudio:   color-mix(in srgb, var(--brand-magenta) 62%, var(--brand-yellow));
  --brain-accent-feedback:       var(--brand-green);
  --brain-accent-admin:          var(--brand-slate, #64748b);
}
/* Ink theme: navy/purple are too dark to read as an accent on dark
   surfaces — lighten the SAME token so dot, hover, active and theme
   all stay one colour per brain (derived, not invented). */
html[data-theme='ink'] {
  --brain-accent-operations:  color-mix(in srgb, var(--brand-purple) 55%, #fff);
  --brain-accent-recruitment: color-mix(in srgb, var(--brand-navy) 45%, #fff);
}
/* Theme accent follows the active brain. body-level so React portals
   (modals, ⌘K palette, feedback bubble) inherit it too. */
body:has(.portal-shell[data-brain='campaigns'])      { --color-accent: var(--brain-accent-campaigns);      --color-accent-readable: var(--brain-accent-campaigns); }
body:has(.portal-shell[data-brain='schools'])        { --color-accent: var(--brain-accent-schools);        --color-accent-readable: var(--brain-accent-schools); }
body:has(.portal-shell[data-brain='finance'])        { --color-accent: var(--brain-accent-finance);        --color-accent-readable: var(--brain-accent-finance); }
body:has(.portal-shell[data-brain='production'])     { --color-accent: var(--brain-accent-production);     --color-accent-readable: var(--brain-accent-production); }
body:has(.portal-shell[data-brain='operations'])     { --color-accent: var(--brain-accent-operations);     --color-accent-readable: var(--brain-accent-operations); }
body:has(.portal-shell[data-brain='recruitment'])    { --color-accent: var(--brain-accent-recruitment);    --color-accent-readable: var(--brain-accent-recruitment); }
body:has(.portal-shell[data-brain='thinkingmachine']){ --color-accent: var(--brain-accent-thinkingmachine);--color-accent-readable: var(--brain-accent-thinkingmachine); }
body:has(.portal-shell[data-brain='agent'])          { --color-accent: var(--brain-accent-agent);          --color-accent-readable: var(--brain-accent-agent); }
body:has(.portal-shell[data-brain='videostudio'])    { --color-accent: var(--brain-accent-videostudio);    --color-accent-readable: var(--brain-accent-videostudio); }
body:has(.portal-shell[data-brain='feedback'])       { --color-accent: var(--brain-accent-feedback);       --color-accent-readable: var(--brain-accent-feedback); }
body:has(.portal-shell[data-brain='admin'])          { --color-accent: var(--brain-accent-admin);          --color-accent-readable: var(--brain-accent-admin); }
/* Grid is the one full-bleed brain that mounts the shared PortalNav
   WITHOUT a .portal-shell wrapper — key off exactly that shape. */
body:has([data-portal-nav]):not(:has(.portal-shell)) { --color-accent: var(--brain-accent-grid);           --color-accent-readable: var(--brain-accent-grid); }

/* ---- Shell layout: sidebar column + main column ---- */
.portal-shell {
  display: grid;
  grid-template-columns: auto 1fr;
  height: 100vh;          /* fallback */
  height: 100dvh;         /* dynamic viewport — no reflow when the mobile
                             address bar hides/shows on scroll */
  overflow: hidden;
  background: var(--surface);
}

.portal-main {
  display: flex;
  flex-direction: column;
  min-width: 0;            /* let content shrink instead of pushing the grid */
  min-height: 0;
}

.portal-content {
  flex: 1;
  min-height: 0;
  overflow: auto;
  padding: var(--space-6);
}

/* ===========================================================
   Sidebar
   =========================================================== */
.portal-nav {
  position: relative;
  width: 248px;
  display: flex;
  flex-direction: column;
  min-height: 0;
  /* Chrome (nav labels, breadcrumbs) shouldn't drag-select during click interactions. */
  -webkit-user-select: none;
  user-select: none;
  background: var(--surface-sunken);
  border-right: 1px solid var(--border);
  transition: width var(--motion-panel) var(--ease);
}

/* ---- Org chrome (top) ---- */
.portal-nav__org {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-3) var(--space-2);
}
.portal-nav__symbol {
  flex: 0 0 auto;
  width: 30px; height: 30px;
  display: grid; place-items: center;
  padding: 3px;
  background: #FFFFFF;                 /* white chip so the CMYK mark reads in both themes */
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
}
.portal-nav__symbol img,
.portal-nav__symbol svg { width: 100%; height: 100%; object-fit: contain; }
/* Org name. Just the company — the symbol already says "The Inventors". */
.portal-nav__orgname {
  flex: 1; min-width: 0;
  font: var(--type-body-strong); font-size: 13px;
  color: var(--ink);
  text-align: left;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* Static (non-switchable) org — most users. Just the name, no affordance. */
.portal-nav__orgname--static { padding: 5px 7px; }

/* Switchable org (multi-org users) — a popover trigger, same affordance
   as the brain switcher. */
.portal-nav__orgbtn {
  flex: 1; min-width: 0;
  display: flex; align-items: center; gap: var(--space-2);
  padding: 5px 7px;
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: background var(--motion-standard) var(--ease);
}
.portal-nav__orgbtn:hover,
.portal-nav__orgbtn[aria-expanded="true"] { background: var(--surface-hover); }
.portal-nav__orgchev { width: 14px; height: 14px; color: var(--ink-subtle); flex: 0 0 auto; }

.org-switch__menu {
  position: absolute;
  top: calc(100% - var(--space-1)); left: var(--space-3); right: var(--space-3);
  z-index: var(--z-dropdown);
  padding: var(--space-1);
  background: var(--surface-raised);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  display: none;
}
.org-switch__menu[data-open] { display: block; animation: portal-pop var(--motion-standard) var(--ease); }
/* Org menu items reuse .brain-switch__item; give the leading glyph a size */
.org-switch__menu .brain-switch__item svg:not(.brain-switch__check) {
  width: 16px; height: 16px; flex: 0 0 auto; color: var(--ink-muted);
}

/* ---- Brain switcher ---- */
.brain-switch { position: relative; padding: 0 var(--space-3) var(--space-3); }
.brain-switch__current {
  width: 100%;
  display: flex; align-items: center; gap: var(--space-2);
  padding: 7px 9px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-md);
  background: var(--surface-raised);
  color: var(--ink);
  font: var(--type-body-strong); font-size: 13px;
  cursor: pointer;
  transition: border-color var(--motion-standard) var(--ease),
              box-shadow var(--motion-standard) var(--ease);
}
.brain-switch__current:hover { border-color: var(--ink-muted); }
.brain-switch__current[aria-expanded="true"] {
  border-color: var(--color-accent);
  box-shadow: 0 0 0 1px var(--color-accent);
}
.brain-switch__dot {
  flex: 0 0 auto;
  width: 8px; height: 8px; border-radius: var(--radius-pill);
  /* FB 019f2819: this dot represents the CURRENT brain and must read its own identity colour
     (the same --c the dropdown's .brain-switch__item-dot already honours below) — it was reading
     the ambient page topic-accent instead, so e.g. Schools' dot showed magenta (page accent) here
     but cyan (its real brain colour) in its own dropdown row: two dots, same brain, two colours. */
  background: var(--c, var(--color-accent));
}
.brain-switch__label { flex: 1; min-width: 0; text-align: left; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.brain-switch__chev { width: 15px; height: 15px; color: var(--ink-subtle); flex: 0 0 auto; }

.brain-switch__menu {
  position: absolute;
  top: calc(100% - var(--space-2)); left: var(--space-3); right: var(--space-3);
  z-index: var(--z-dropdown);
  padding: var(--space-1);
  background: var(--surface-raised);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  display: none;
}
.brain-switch__menu[data-open] {
  display: block;
  animation: portal-pop var(--motion-standard) var(--ease);
}
@keyframes portal-pop { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }

.brain-switch__item {
  width: 100%;
  display: flex; align-items: center; gap: var(--space-3);
  padding: 7px 9px;
  border-radius: var(--radius-md);
  font: var(--type-body); font-size: 13px;
  color: var(--ink);
  text-align: left; cursor: pointer;
  transition: background var(--motion-micro) var(--ease);
}
.brain-switch__item:hover,
.brain-switch__item--active-opt { background: var(--surface-hover); }
.brain-switch__item[aria-current="true"] { font-weight: 600; }
.brain-switch__item-dot {
  flex: 0 0 auto;
  width: 8px; height: 8px; border-radius: var(--radius-pill);
  background: var(--c, var(--ink-subtle));   /* per-brain colour set inline via --c */
}
.brain-switch__item-name { flex: 1; min-width: 0; }
/* Band separator between the switcher's groups — Data Grid, the everyday brains, the
   management pair, the tools (founder's "________" lines, FB 019fc766). */
.brain-switch__sep { height: 1px; margin: 5px 4px; background: var(--border); }
.brain-switch__check { width: 15px; height: 15px; color: var(--color-accent); }
.brain-switch__item--soon { color: var(--ink-subtle); cursor: default; }
.brain-switch__item--soon:hover { background: transparent; }
.brain-switch__soon {
  font: var(--type-eyebrow); letter-spacing: var(--letter-eyebrow);
  text-transform: uppercase; color: var(--ink-subtle);
  border: 1px solid var(--border); border-radius: var(--radius-pill);
  padding: 1px 6px;
}

/* ---- Nav body: groups → views ---- */
.portal-nav__body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: var(--space-2) var(--space-3) var(--space-3);
  border-top: 1px solid var(--border);
  scrollbar-width: thin;                                  /* Firefox */
  scrollbar-color: var(--border-strong) transparent;
}
/* Thin, unobtrusive scrollbar shared by the sidebar + popover menus */
.portal-nav__body::-webkit-scrollbar,
.brain-switch__menu::-webkit-scrollbar,
.usermenu__menu::-webkit-scrollbar { width: 6px; }
.portal-nav__body::-webkit-scrollbar-track,
.brain-switch__menu::-webkit-scrollbar-track,
.usermenu__menu::-webkit-scrollbar-track { background: transparent; }
.portal-nav__body::-webkit-scrollbar-thumb,
.brain-switch__menu::-webkit-scrollbar-thumb,
.usermenu__menu::-webkit-scrollbar-thumb {
  background: var(--border-strong);
  border-radius: var(--radius-pill);
}
.portal-nav__body::-webkit-scrollbar-thumb:hover,
.brain-switch__menu::-webkit-scrollbar-thumb:hover,
.usermenu__menu::-webkit-scrollbar-thumb:hover { background: var(--ink-subtle); }

.portal-nav__group { margin-top: var(--space-3); }
.portal-nav__group:first-child { margin-top: var(--space-1); }

/* Collapsible group header. Single-item / standalone groups omit the
   label entirely — see .portal-nav__group--flat. */
.portal-nav__label {
  display: flex; align-items: center; gap: var(--space-2);
  width: 100%;
  font: var(--type-eyebrow);
  letter-spacing: var(--letter-eyebrow);
  text-transform: uppercase;
  color: var(--ink-subtle);
  padding: var(--space-1) var(--space-2);
  margin: 0;
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: color var(--motion-micro) var(--ease);
}
.portal-nav__label > span { flex: 1; text-align: left; }
.portal-nav__label:hover {
  /* One accent per brain (FB 019f5d84/019f5d86): hover reads the brain accent,
     not the retired per-group --group-color. */
  color: color-mix(in srgb, var(--color-accent-readable, var(--ink-muted)) 70%, var(--ink-muted));
}
.portal-nav__label-chev {
  width: 12px; height: 12px; color: var(--ink-subtle);
  transition: transform var(--motion-standard) var(--ease);
}
.portal-nav__views { display: flex; flex-direction: column; }
.portal-nav__group[data-collapsed] .portal-nav__views { display: none; }
.portal-nav__group[data-collapsed] .portal-nav__label-chev { transform: rotate(-90deg); }
.portal-nav__group--flat { margin-top: var(--space-2); }
.portal-nav__view {
  position: relative;
  display: flex; align-items: center; gap: 10px;
  padding: 6px 10px;
  border-radius: var(--radius-md);
  font: var(--type-body-strong); font-size: 13px;
  color: var(--ink-muted);
  transition: color var(--motion-standard) var(--ease),
              background var(--motion-standard) var(--ease);
}
.portal-nav__view svg { width: 16px; height: 16px; flex: 0 0 auto; color: var(--ink-subtle); transition: color var(--motion-standard) var(--ease); }
/* One accent per brain (FB 019f5d84, 019f5d86): hover uses the SAME brain
   accent as the active pill and the switcher dot — the old per-group
   --group-color (yellow/blue/green per section) read as a third colour
   scheme next to the brain theme, so it's retired here (PortalNav still
   sets it inline; nothing consumes it for hover any more). */
.portal-nav__view:hover {
  background: color-mix(in srgb, var(--color-accent) 9%, transparent);
  color: var(--ink);
}
.portal-nav__view:hover svg { color: var(--color-accent-readable, var(--ink-muted)); }
.portal-nav__view[aria-current="page"] {
  background: color-mix(in srgb, var(--color-accent) 12%, transparent);
  color: var(--ink);
}
.portal-nav__view[aria-current="page"] svg { color: var(--color-accent-readable); }
.portal-nav__view[aria-current="page"]::before {
  content: ''; position: absolute; left: -3px; top: 50%; transform: translateY(-50%);
  width: 3px; height: 60%;
  background: var(--color-accent);
  border-radius: 0 var(--radius-pill) var(--radius-pill) 0;
}
.portal-nav__view .badge--count,
.portal-nav__view .portal-nav__count { margin-left: auto; }
.portal-nav__count {
  font: 500 11px/1 var(--font-mono);
  color: var(--ink-subtle);
}

/* ===========================================================
   Rail (collapsed) mode — icon-only, ~64px
   ===========================================================
   The sidebar collapses to a 64px icon rail (flipped by the top-bar
   panel toggle, .portal-bar__rail-collapse, which sits at the
   sidebar's inner edge). Everything a user still needs — org switch,
   brain switch, per-view labels — is preserved as flyouts anchored to
   the rail's right edge, so nothing is crushed into 64px. */
.portal-nav--rail { width: 64px; }

/* Hide only the inline text that can't fit. The per-view label, brain
   label and org name are deliberately NOT hidden here — they become
   right-edge flyouts below, which also keeps their accessible names.
   The GROUP label is hidden, but since FB 019fccf1 its name is not lost
   with it: it leads each destination's flyout (.portal-nav__view-group)
   and it is the group's aria-label in PortalNav.tsx. */
.portal-nav--rail .portal-nav__label,
.portal-nav--rail .brain-switch__chev,
.portal-nav--rail .portal-nav__orgchev,
.portal-nav--rail .portal-nav__orgname,
.portal-nav--rail .portal-nav__count { display: none; }

/* Body keeps its vertical scroll (a super-admin's rail can be taller than a short viewport). The
   per-view label tooltips escape it because they are `position: fixed`, NOT because the clip is
   relaxed — see the FB 019faec7 block at the tooltip rule below. The org/brain flyouts are
   unaffected (they live above this scroll container). */
.portal-nav--rail .portal-nav__body { padding-inline: var(--space-2); }
/* …but the rail must NEVER pan sideways. `.portal-nav__body` only declares `overflow-y: auto`, and
   CSS computes an omitted `overflow-x: visible` to `auto` whenever the other axis is not visible —
   so the rail silently became a HORIZONTAL scroll container too. The per-view tooltips below are
   `position: absolute; left: calc(100% + 8px); width: max-content`, i.e. they sit ~100px past the
   rail's right edge even at rest (they are only `opacity: 0`, still laid out). Measured collapsed,
   Poland, Chrome and Firefox 1536x864: scrollWidth 165 vs clientWidth 63 — 102px of scrollable
   overflow on a 63px icon rail. That is the horizontal scrollbar the founder reported, and its
   ~15px height is what clipped the bottom icon mid-glyph (feedback 019fa840). Pin the axis
   explicitly. Since FB 019faec7 the tooltips are `position: fixed` and so contribute NO scrollable
   overflow at all (measured: scrollWidth 227 → 64 on a 64px rail), which means this declaration is
   now a guard rather than the thing holding the layout together — keep it, it costs nothing and it
   catches the next child that overhangs. */
.portal-nav--rail .portal-nav__body { overflow-x: hidden; }
.portal-nav--rail .portal-nav__view { justify-content: center; padding: 8px; }
.portal-nav--rail .portal-nav__view svg { width: 18px; height: 18px; }

/* Groups keep their identity: a thin divider between rail groups so
   Acquisition / Sales / Business / Admin don't melt into one column. */
.portal-nav--rail .portal-nav__group {
  margin-top: var(--space-2); padding-top: var(--space-2);
  border-top: 1px solid var(--border);
}
.portal-nav--rail .portal-nav__group:first-child { margin-top: 0; padding-top: 0; border-top: 0; }
/* No label to toggle in the rail — always show the icons. */
.portal-nav--rail .portal-nav__group[data-collapsed] .portal-nav__views { display: flex; }

/* ---- Org: the TI logo becomes the org-switch trigger ---- */
.portal-nav--rail .portal-nav__org { justify-content: center; padding-inline: 0; position: relative; }
.portal-nav--rail .portal-nav__orgbtn {          /* was display:none — un-hide as a full-row overlay */
  display: block; position: absolute; inset: 0;
  padding: 0; border: 0; border-radius: var(--radius-md); background: transparent;
}
.portal-nav--rail .portal-nav__orgbtn:hover,
.portal-nav--rail .portal-nav__orgbtn[aria-expanded="true"] { background: var(--surface-hover); }

.portal-nav--rail .brain-switch { padding-inline: var(--space-2); }
.portal-nav--rail .brain-switch__current { justify-content: center; padding: 7px; position: relative; }

/* ---- Right-edge popovers (org + brain): readable menus anchored just
   past the rail instead of being crushed into the 64px column. ---- */
.portal-nav--rail .org-switch__menu,
.portal-nav--rail .brain-switch__menu {
  top: 0; left: calc(100% + var(--space-2)); right: auto;
  min-width: 200px;
}

/* ---- Per-view + brain labels reveal as a hover/focus tooltip on the
   rail's right edge (and stay in the a11y tree as accessible names). */
.portal-nav--rail .portal-nav__view > span:not(.portal-nav__count),
.portal-nav--rail .brain-switch__label {
  display: block; width: max-content; white-space: nowrap; text-align: left; overflow: visible;
  padding: 4px 8px;
  background: var(--surface-raised); color: var(--ink);
  border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
  box-shadow: var(--shadow-md);
  font: var(--type-body-strong); font-size: 12px; letter-spacing: 0;
  opacity: 0; pointer-events: none;
  transition: opacity var(--motion-standard) var(--ease);
  z-index: 65;
}
/* The BRAIN label is not inside the scroller — `.brain-switch` is a sibling of `.portal-nav__body`,
   so nothing clips it. Ordinary absolute positioning off its own trigger, unchanged. */
.portal-nav--rail .brain-switch__label {
  position: absolute; left: calc(100% + 8px); top: 50%; transform: translateY(-50%);
}

/* FB 019faec7 — "the same hover that reveals a tooltip makes the rail stop being a scrollable area."
   TRUE, and reproduced in Chromium against the live stylesheet: with the old
   `.portal-nav--rail .portal-nav__body:hover { overflow: visible }` in place, moving the pointer onto
   the rail flipped the body's computed overflow-x/overflow-y from hidden/auto to visible/visible, so
   it stopped being a scroll container — the parked scrollTop 56 was DISCARDED to 0 and a fresh
   `scrollTop = 120` was refused. On an account with more destinations than fit (a 12-destination
   super-admin needs ~885px in a ~780px column) the pointer could no longer reach the ones below the
   fold, and the rail also jumped back to the top the moment the mouse arrived. Only Tab still got
   there, and nothing on screen said so.

   The conflict is real: a tooltip has to leave the box, a scroll container has to clip it. It cannot
   be settled in CSS on this element. `overflow-x: clip` + `overflow-clip-margin` — the property pair
   built for exactly "clip one axis loosely" — does not compose with a scrolling other axis: CSS
   Overflow 3 computes `clip` to `hidden` whenever the other axis is `auto`/`scroll` (verified in
   Chromium: overflow-x:clip beside overflow-y:auto computes to `hidden`, and the clip margin is
   ignored). Fable's `Popover` is not an answer either — it is `position: absolute` inside its own
   trigger's wrapper, not a portal, so it would be clipped by this same scroller.

   So stop asking the box to overflow: take the tooltip OUT of the scroller's coordinate space.
   `position: fixed` is not clipped by an ancestor's overflow (no ancestor here establishes a
   containing block — no transform/filter/contain on .portal-nav or the shell), and a fixed box adds
   nothing to its ancestor's scrollable overflow. The rail keeps `overflow-y: auto` at ALL times, and
   the tooltip still paints outside it. Because `fixed` resolves percentages against the viewport,
   the anchor coordinates come from the item's own rect, written by the shell as `--rail-tip-x/y` on
   hover, on focus, and again on every scroll of the rail (src/shell/PortalNav.tsx). The var fallback
   is the rail's right edge — a value that is never seen, since both reveal paths set the vars first,
   but one that stays on screen if it ever were. */
.portal-nav--rail .portal-nav__view > span:not(.portal-nav__count) {
  position: fixed;
  left: var(--rail-tip-x, 72px);
  top: var(--rail-tip-y, 50%);
  transform: translateY(-50%);
}

/* FB 019fccf1 — the flyout names the SECTION as well as the destination.
   `.portal-nav--rail .portal-nav__label` is `display: none` above (it cannot fit in 64px), so until
   now the only way to learn which section an icon belonged to was to click it and read the
   breadcrumb: "Cérebro Escolas / Gestor de Contactos (CM) / CM Deals". The name is an eyebrow inside
   the destination's own tooltip rather than a second flyout on a header of its own — the rail's
   header has nothing left to toggle (the rule above keeps a collapsed group's views visible here), so
   a hoverable header would have been a dead affordance, and a new absolutely-placed box inside
   `.portal-nav__body` is exactly what FB 019faec7 had to take out of that scroller. This element adds
   no box: it is a child of a `position: fixed` tooltip. */
.portal-nav--rail .portal-nav__view-group {
  display: block;
  font: var(--type-eyebrow);
  letter-spacing: var(--letter-eyebrow);
  text-transform: uppercase;
  color: var(--ink-subtle);
  margin-bottom: 2px;
}

.portal-nav--rail .portal-nav__view:hover > span:not(.portal-nav__count),
.portal-nav--rail .portal-nav__view:focus-visible > span:not(.portal-nav__count),
.portal-nav--rail .brain-switch__current:hover .brain-switch__label,
.portal-nav--rail .brain-switch__current:focus-visible .brain-switch__label { opacity: 1; }

/* ===========================================================
   Nav-body states (every container ships four)
   =========================================================== */
.portal-nav__state {
  margin: var(--space-2);
  padding: var(--space-4) var(--space-3);
  text-align: center;
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius-lg);
  color: var(--ink-subtle);
  font: var(--type-caption);
}
.portal-nav__state svg { width: 20px; height: 20px; margin: 0 auto var(--space-2); color: var(--ink-subtle); }
.portal-nav__state strong { display: block; color: var(--ink-muted); font: var(--type-body-strong); font-size: 12.5px; margin-bottom: 2px; }
.portal-nav__state .btn { margin-top: var(--space-3); }

/* Loading skeleton group */
.portal-nav__skeleton { padding: var(--space-2) var(--space-3); }
.portal-nav__skeleton-bar {
  height: 10px; margin: var(--space-3) 0;
  border-radius: var(--radius-pill);
  background: linear-gradient(90deg,
    var(--surface-hover) 25%,
    color-mix(in srgb, var(--surface-hover) 60%, var(--surface)) 50%,
    var(--surface-hover) 75%);
  background-size: 200% 100%;
  animation: portal-shimmer 1.2s ease-in-out infinite;
}
.portal-nav__skeleton-bar--sm { width: 40%; height: 8px; }
@keyframes portal-shimmer { from { background-position: 200% 0; } to { background-position: -200% 0; } }
@media (prefers-reduced-motion: reduce) {
  .portal-nav__skeleton-bar { animation: none; }
}

/* ===========================================================
   Slim top bar
   =========================================================== */
.portal-bar {
  flex: 0 0 auto;
  display: flex; align-items: center; gap: var(--space-3);
  height: 48px; padding: 0 var(--space-4);
  background: var(--surface-raised);
  border-bottom: 1px solid var(--border);
}
.portal-bar__rail-toggle {
  display: none;                      /* shown only when sidebar is a drawer */
  flex: 0 0 auto;                     /* never let crowded actions shrink it to 0 (mobile hamburger) */
  width: 32px; height: 32px;
  border-radius: var(--radius-md);
  color: var(--ink-muted);
  align-items: center; justify-content: center;
}
.portal-bar__rail-toggle:hover { background: var(--surface-hover); color: var(--ink); }
.portal-bar__rail-toggle svg { width: 18px; height: 18px; }

/* Desktop sidebar collapse — lives in the top bar so it never sits under
   Chrome's bottom-left URL hover bubble. Hidden on mobile (drawer toggle shows). */
.portal-bar__rail-collapse {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px;
  border-radius: var(--radius-md);
  color: var(--ink-muted);
}
.portal-bar__rail-collapse:hover { background: var(--surface-hover); color: var(--ink); }
.portal-bar__rail-collapse svg { width: 18px; height: 18px; transition: transform var(--motion-standard) var(--ease); }
.portal-bar__rail-collapse[aria-pressed="true"] svg { transform: rotate(180deg); }

/* Breadcrumb (lighter than the catalogue .breadcrumb chip — it's chrome) */
.portal-bar__crumb {
  display: flex; align-items: center; gap: 6px;
  min-width: 0;
  font: var(--type-body); font-size: 13px;
  color: var(--ink-muted);
  -webkit-user-select: none;
  user-select: none;
}
.portal-bar__crumb a { color: var(--ink-muted); transition: color var(--motion-micro) var(--ease); }
.portal-bar__crumb a:hover { color: var(--ink); }
.portal-bar__crumb-sep { width: 14px; height: 14px; color: var(--ink-subtle); opacity: 0.7; flex: 0 0 auto; }
.portal-bar__crumb-current { color: var(--ink); font-weight: 500; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.portal-bar__actions { display: flex; align-items: center; gap: var(--space-2); margin-left: auto; }

/* Search trigger (opens the Ctrl+K palette) */
.portal-bar__search {
  display: inline-flex; align-items: center; gap: 8px;
  min-width: 220px;
  padding: 6px 8px 6px 10px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-md);
  background: var(--surface-sunken);
  color: var(--ink-subtle);
  font: var(--type-body); font-size: 12px;
  cursor: text;
  transition: border-color var(--motion-standard) var(--ease), color var(--motion-standard) var(--ease);
}
.portal-bar__search:hover { border-color: var(--ink-muted); color: var(--ink-muted); }
.portal-bar__search svg { width: 14px; height: 14px; flex: 0 0 auto; }
.portal-bar__search-label { flex: 1; text-align: left; }
.portal-bar__search kbd { font-size: 10px; height: 18px; min-width: auto; padding: 0 5px; }

/* Icon button (theme, notifications) */
.portal-bar__icon {
  position: relative;
  width: 32px; height: 32px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--radius-md);
  color: var(--ink-muted);
  transition: background var(--motion-standard) var(--ease), color var(--motion-standard) var(--ease);
}
.portal-bar__icon:hover { background: var(--surface-hover); color: var(--ink); }
.portal-bar__icon svg { width: 16px; height: 16px; }
.portal-bar__icon .badge--count {
  position: absolute; top: 1px; right: 1px;
}

/* ===========================================================
   User / settings menu
   =========================================================== */
.usermenu { position: relative; }
.usermenu__trigger {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 3px 6px 3px 3px;
  border-radius: var(--radius-pill);
  transition: background var(--motion-standard) var(--ease);
}
.usermenu__trigger:hover { background: var(--surface-hover); }
.usermenu__trigger[aria-expanded="true"] { background: var(--surface-hover); }
.usermenu__chev { width: 14px; height: 14px; color: var(--ink-subtle); }

.usermenu__avatar {
  flex: 0 0 auto;
  width: 28px; height: 28px;
  display: grid; place-items: center;
  border-radius: var(--radius-pill);
  background: var(--color-action-bg);
  color: var(--color-action-fg);
  font: 600 11px/1 var(--font-ui);
  letter-spacing: 0.02em;
  overflow: hidden;
}
.usermenu__avatar img { width: 100%; height: 100%; object-fit: cover; }

.usermenu__menu {
  position: absolute; top: calc(100% + 6px); right: 0;
  z-index: 70;
  width: 264px;
  padding: var(--space-2);
  background: var(--surface-raised);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  display: none;
}
.usermenu__menu[data-open] {
  display: block;
  animation: portal-pop var(--motion-standard) var(--ease);
}

.usermenu__id {
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-2);
}
.usermenu__id .usermenu__avatar { width: 36px; height: 36px; font-size: 13px; }
.usermenu__id-text { min-width: 0; }
.usermenu__id-name { font: var(--type-body-strong); font-size: 13px; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.usermenu__id-mail { font: var(--type-caption); color: var(--ink-subtle); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.usermenu__role {
  display: inline-block; margin-top: 3px;
  font: var(--type-eyebrow); letter-spacing: var(--letter-eyebrow); text-transform: uppercase;
  color: var(--color-accent-readable);
  background: color-mix(in srgb, var(--color-accent) 14%, transparent);
  border-radius: var(--radius-pill);
  padding: 1px 7px;
}

.usermenu__sep { height: 1px; margin: var(--space-1) var(--space-1); background: var(--border); }
.usermenu__sectionlabel {
  font: var(--type-eyebrow); letter-spacing: var(--letter-eyebrow); text-transform: uppercase;
  color: var(--ink-subtle);
  padding: var(--space-2) var(--space-2) var(--space-1);
}

.usermenu__item {
  width: 100%;
  display: flex; align-items: center; gap: var(--space-3);
  padding: 7px 8px;
  border-radius: var(--radius-md);
  font: var(--type-body); font-size: 13px;
  color: var(--ink);
  text-align: left; cursor: pointer;
  transition: background var(--motion-micro) var(--ease);
}
.usermenu__item:hover { background: var(--surface-hover); }
.usermenu__item svg { width: 15px; height: 15px; color: var(--ink-muted); flex: 0 0 auto; }
.usermenu__item-label { flex: 1; min-width: 0; }
.usermenu__item kbd { font-size: 10px; height: 18px; min-width: 18px; padding: 0 4px; }

/* Inline quick-pref row (segmented toggles inside the menu) */
.usermenu__pref {
  display: flex; align-items: center; gap: var(--space-2);
  padding: 6px 8px;
}
.usermenu__pref-label { flex: 1; font: var(--type-body); font-size: 13px; color: var(--ink); }
.usermenu__seg {
  display: inline-flex; padding: 2px; gap: 2px;
  background: var(--surface-sunken);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
}
.usermenu__seg-opt {
  display: inline-flex; align-items: center; justify-content: center; gap: 5px;
  min-width: 30px; padding: 4px 8px;
  border-radius: var(--radius-sm);
  font: var(--type-body-strong); font-size: 11.5px;
  color: var(--ink-muted);
  transition: background var(--motion-standard) var(--ease), color var(--motion-standard) var(--ease);
}
.usermenu__seg-opt svg { width: 13px; height: 13px; color: currentColor; }
.usermenu__seg-opt:hover { color: var(--ink); }
.usermenu__seg-opt[aria-pressed="true"] {
  background: var(--surface-raised); color: var(--ink); box-shadow: var(--shadow-sm);
}

/* Language picker (native select, styled to match the menu chrome) */
.usermenu__lang {
  appearance: none; -webkit-appearance: none;
  padding: 5px 28px 5px 9px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background-color: var(--surface-sunken);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23889' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 8px center;
  color: var(--ink);
  font: var(--type-body-strong); font-size: 11.5px;
  cursor: pointer;
  transition: border-color var(--motion-standard) var(--ease), background-color var(--motion-standard) var(--ease);
}
.usermenu__lang:hover { border-color: var(--ink-muted); background-color: var(--surface-raised); }
.usermenu__lang:focus-visible { outline: none; border-color: var(--color-accent); box-shadow: var(--shadow-focus); }
.usermenu__lang option { color: var(--ink); background: var(--surface-raised); }

.usermenu__item--signout { color: var(--ink-muted); }
.usermenu__item--signout svg { color: var(--ink-muted); }

/* ===========================================================
   Responsive: sidebar becomes an off-canvas drawer
   =========================================================== */
.portal-nav__scrim {
  position: fixed; inset: 0; z-index: 55;
  background: color-mix(in srgb, var(--brand-navy) 50%, transparent);
  backdrop-filter: blur(2px); -webkit-backdrop-filter: blur(2px);
  display: none;
}

@media (max-width: 860px) {
  .portal-shell { grid-template-columns: 1fr; }
  .portal-nav {
    position: fixed; top: 0; left: 0; bottom: 0; z-index: 60;
    width: 264px;
    transform: translateX(-100%);
    /* A closed drawer is OFF-SCREEN, not hidden — so without this it stayed in the tab
       sequence: at 412px a keyboard/switch user tabbed through 7–16 invisible nav controls
       at x=-254…-11 after "Skip to content" before reaching the "Open navigation" button, in
       every brain shell (measured 2026-07-28). `visibility: hidden` takes the drawer out of
       the tab order, the a11y tree and hit-testing in one, and — unlike an `inert` attribute
       set from JS — it lives in the SAME rule as the translate that causes the trap, so the
       two cannot drift apart. It is deferred by the transition below so the slide-OUT still
       plays; opening resets the delay to 0s. */
    visibility: hidden;
    transition: transform var(--motion-panel) var(--ease),
                visibility 0s linear var(--motion-panel);
    box-shadow: var(--shadow-lg);
  }
  .portal-shell[data-drawer-open] .portal-nav {
    transform: none;
    visibility: visible;
    transition: transform var(--motion-panel) var(--ease), visibility 0s;
  }
  .portal-shell[data-drawer-open] .portal-nav__scrim { display: block; }
  .portal-bar__rail-collapse { display: none; } /* desktop-only collapse */
  .portal-bar__rail-toggle { display: inline-flex; }
  .portal-bar__search { min-width: 0; }
  .portal-bar__search-label, .portal-bar__search kbd { display: none; }
  .portal-bar__crumb { flex: 0 1 auto; overflow: hidden; }
}

/* Phones: collapse the breadcrumb to a single element — the leaf view, or the brain
   root on index pages — so a crowded bar never squeezes two labels into orphan
   letters. The leaf already ellipsises via .portal-bar__crumb-current. */
@media (max-width: 640px) {
  .portal-bar__crumb-sep, .portal-bar__crumb-section { display: none; }
  .portal-bar__crumb a:not(:only-child) { display: none; }
}

/* Very small phones: keep the account menu + top-bar chrome on-screen. */
@media (max-width: 380px) {
  .portal-bar { padding: 0 var(--space-2); gap: var(--space-2); }
  .usermenu__menu { width: min(264px, calc(100vw - 20px)); }
}

/* ===========================================================
   Notifications panel — popover from the bell (reuses the popover JS)
   =========================================================== */
.notif-wrap { position: relative; }
.notif {
  position: absolute; top: calc(100% + 6px); right: 0; z-index: 70;
  width: 344px;
  background: var(--surface-raised);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  display: none; overflow: hidden;
}
.notif[data-open] { display: block; animation: portal-pop var(--motion-standard) var(--ease); }
.notif__head {
  display: flex; align-items: center; justify-content: space-between;
  padding: var(--space-3) var(--space-3) var(--space-2);
  border-bottom: 1px solid var(--border);
}
.notif__title { font: var(--type-heading-sm); color: var(--ink); }
.notif__markall { font: var(--type-caption); color: var(--color-accent-readable); }
.notif__markall:hover { text-decoration: underline; }
.notif__body { max-height: 360px; overflow-y: auto; padding: var(--space-1); }
.notif__item {
  width: 100%;
  display: grid; grid-template-columns: 28px 1fr 8px; gap: var(--space-2);
  align-items: center; text-align: left;
  padding: var(--space-2);
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: background var(--motion-micro) var(--ease);
}
.notif__item:hover { background: var(--surface-hover); }
.notif__ic { width: 28px; height: 28px; display: grid; place-items: center; border-radius: var(--radius-pill); background: var(--surface-sunken); color: var(--ink-muted); }
.notif__ic svg { width: 15px; height: 15px; }
.notif__ic--ok      { background: color-mix(in srgb, var(--brand-green) 16%, transparent);  color: #0a7d3b; }
.notif__ic--info    { background: color-mix(in srgb, var(--brand-cyan) 18%, transparent);   color: #0e7490; }
.notif__ic--caution { background: color-mix(in srgb, var(--brand-yellow) 30%, transparent); color: #7a5b00; }
.notif__text { min-width: 0; }
.notif__msg { font: var(--type-body); font-size: 13px; color: var(--ink); }
.notif__msg b { font-weight: 600; }
.notif__time { font: var(--type-caption); color: var(--ink-subtle); margin-top: 1px; }
.notif__dot { width: 7px; height: 7px; border-radius: var(--radius-pill); background: var(--color-accent); }
.notif__item:not(.notif__item--unread) .notif__dot { visibility: hidden; }
.notif__foot { padding: var(--space-2); border-top: 1px solid var(--border); text-align: center; }
.notif__viewall { display: block; padding: var(--space-1); border-radius: var(--radius-sm); font: var(--type-body-strong); font-size: 13px; color: var(--color-accent-readable); }
.notif__viewall:hover { background: var(--surface-hover); }
.notif__empty { padding: var(--space-8) var(--space-4); text-align: center; color: var(--ink-subtle); font: var(--type-caption); }
.notif__empty svg { width: 22px; height: 22px; margin: 0 auto var(--space-2); color: var(--ink-subtle); display: block; }

/* ===========================================================
   Shell modal — keyboard shortcuts, quick profile
   =========================================================== */
.portal-modal { position: fixed; inset: 0; z-index: 90; display: none; }
.portal-modal[aria-hidden="false"] { display: block; }
.portal-modal__backdrop {
  position: absolute; inset: 0;
  background: color-mix(in srgb, var(--brand-navy) 55%, transparent);
  backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px);
}
.portal-modal__card {
  position: relative;
  width: calc(100% - 32px); max-width: 520px;
  margin: 12vh auto 0;
  background: var(--surface-raised);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
  animation: palette-in var(--motion-panel) var(--ease);
}
.portal-modal__head { display: flex; align-items: center; justify-content: space-between; padding: var(--space-4); border-bottom: 1px solid var(--border); }
.portal-modal__title { font: var(--type-heading-md); color: var(--ink); }
.portal-modal__close { width: 28px; height: 28px; display: grid; place-items: center; border-radius: var(--radius-sm); color: var(--ink-subtle); }
.portal-modal__close:hover { background: var(--surface-hover); color: var(--ink); }
.portal-modal__close svg { width: 16px; height: 16px; }
.portal-modal__body { padding: var(--space-4); max-height: 64vh; overflow-y: auto; }
.portal-modal__foot { display: flex; justify-content: flex-end; gap: var(--space-2); padding: var(--space-3) var(--space-4); border-top: 1px solid var(--border); }

/* shortcuts list */
.kbds__group { font: var(--type-eyebrow); letter-spacing: var(--letter-eyebrow); text-transform: uppercase; color: var(--ink-subtle); padding: var(--space-3) 0 var(--space-1); }
.kbds__group:first-child { padding-top: 0; }
.kbds__row { display: flex; align-items: center; justify-content: space-between; padding: var(--space-2) 0; border-bottom: 1px solid color-mix(in srgb, var(--ink) 5%, transparent); }
.kbds__label { font: var(--type-body); font-size: 13px; color: var(--ink); }
.kbds__keys { display: flex; gap: 4px; }

/* quick-profile form */
.qprofile { display: grid; gap: var(--space-3); }
.qprofile__row { display: grid; gap: var(--space-1); }
.qprofile__label { font: var(--type-caption); color: var(--ink-muted); }
.qprofile__input, .qprofile__select { width: 100%; padding: 7px 9px; border: 1px solid var(--border-strong); border-radius: var(--radius-md); background: var(--surface); color: var(--ink); font: var(--type-body); font-size: 13px; }
.qprofile__input[readonly] { color: var(--ink-subtle); background: var(--surface-sunken); }
.qprofile__avatar-row { display: flex; align-items: center; gap: var(--space-3); }
.qprofile__avatar { width: 44px; height: 44px; border-radius: var(--radius-pill); background: var(--color-action-bg); color: var(--color-action-fg); display: grid; place-items: center; font: 600 15px/1 var(--font-ui); }
.qprofile__manage { margin-top: var(--space-1); font: var(--type-body-strong); font-size: 13px; color: var(--color-accent-readable); display: inline-flex; align-items: center; gap: 5px; }
.qprofile__manage:hover { text-decoration: underline; }
.qprofile__manage svg { width: 14px; height: 14px; }
