/* ==========================================================================
   roam.css — shared design system for the Roam virtual office
   Canonical tokens + base + reusable components, extracted from the office page.
   Every page links this first, then adds only its page-specific layout.
   ========================================================================== */

:root {
  color-scheme: light;

  /* surfaces — light theme */
  --bg: #f6f7fb;
  --bg-2: #eef1f7;
  --panel: rgba(255, 255, 255, 0.74);
  --panel-solid: #ffffff;
  --stroke: rgba(23, 33, 61, 0.10);
  --stroke-strong: rgba(23, 33, 61, 0.18);
  /* subtle grey wash for hovers / inset wells (replaces old white overlays) */
  --wash: rgba(23, 33, 61, 0.05);
  --wash-2: rgba(23, 33, 61, 0.08);

  /* text */
  --text: #1f2430;
  --muted: #6b7385;

  /* accents — brand blue/purple kept to match the 3D office */
  --accent: #6c8cff;
  --accent-2: #9b6bff;
  /* semantic colours darkened so they read as text on white while still
     working as dots / fills */
  --green: #16a34a;
  --amber: #b45309;
  --red: #dc2626;
  --cyan: #0e7490;
  --gray: #94a3b8;

  --radius: 18px;
  font-synthesis: none;
}

/* ---------- base ---------- */
* { box-sizing: border-box; }
html, body { margin: 0; }

body {
  font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  color: var(--text);
  background:
    radial-gradient(900px 600px at 12% -10%, rgba(108, 140, 255, 0.10), transparent 55%),
    radial-gradient(800px 600px at 100% 0%, rgba(155, 107, 255, 0.09), transparent 50%),
    linear-gradient(180deg, #f6f7fb 0%, #eef1f7 100%);
  -webkit-font-smoothing: antialiased;
}

/* thin light scrollbars */
* { scrollbar-width: thin; scrollbar-color: rgba(23,33,61,0.22) transparent; }
*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-thumb { background: rgba(23,33,61,0.18); border-radius: 8px; }
*::-webkit-scrollbar-thumb:hover { background: rgba(23,33,61,0.30); }

/* ==========================================================================
   Reusable components (rm- prefix). Pages can adopt these to stay consistent.
   ========================================================================== */

/* brand + logo */
.rm-logo {
  width: 34px; height: 34px; border-radius: 9px;
  display: grid; place-items: center; font-size: 14px; font-weight: 800; letter-spacing: -0.3px; color: #fff;
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  box-shadow: 0 6px 18px rgba(108, 140, 255, 0.45);
}

/* top nav pills */
.rm-nav { display: flex; gap: 8px; align-items: center; }
.rm-nav a {
  text-decoration: none; color: var(--muted); font-size: 14px; font-weight: 600;
  padding: 7px 13px; border-radius: 999px; border: 1px solid var(--stroke); background: var(--panel);
}
.rm-nav a:hover { color: var(--text); border-color: var(--stroke-strong); background: var(--panel-solid); }
.rm-nav a.active {
  color: #fff; border-color: transparent;
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  box-shadow: 0 4px 12px rgba(108,140,255,0.32);
}

/* surfaces */
.rm-card, .rm-panel {
  border: 1px solid var(--stroke); background: var(--panel); border-radius: var(--radius);
  backdrop-filter: blur(8px);
}
.rm-card { padding: 16px 18px; }

/* buttons */
.rm-btn {
  border: none; cursor: pointer; font-family: inherit; font-weight: 700; font-size: 14px; color: #fff;
  padding: 11px 18px; border-radius: 12px;
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  box-shadow: 0 8px 22px rgba(108,140,255,0.35);
}
.rm-btn:hover { filter: brightness(1.07); }
.rm-btn.ghost {
  background: var(--panel); color: var(--muted); box-shadow: none; border: 1px solid var(--stroke);
}
.rm-btn.ghost:hover { color: var(--text); border-color: var(--stroke-strong); }

/* form controls */
.rm-input, .rm-select {
  width: 100%; padding: 10px 12px; border-radius: 10px; font-size: 14px; font-family: inherit; color: var(--text);
  background: #ffffff; border: 1px solid var(--stroke-strong);
}
.rm-input::placeholder, .rm-select::placeholder { color: var(--muted); }
.rm-input:focus, .rm-select:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px rgba(108,140,255,0.15); }

/* badges + status */
.rm-badge {
  font-size: 10px; font-weight: 700; padding: 4px 10px; border-radius: 999px;
  text-transform: capitalize; letter-spacing: 0.02em;
}
.rm-badge.accent { color: var(--accent); background: rgba(108,140,255,0.16); }
.rm-badge.green  { color: var(--green);  background: rgba(54,211,153,0.14); }
.rm-badge.amber  { color: var(--amber);  background: rgba(251,191,36,0.14); }
.rm-badge.muted  { color: var(--muted);  background: var(--wash-2); }

.rm-pill {
  display: inline-flex; align-items: center; gap: 7px; font-size: 14px; color: var(--muted);
  padding: 6px 12px; border-radius: 999px; background: var(--panel); border: 1px solid var(--stroke);
}
.rm-dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; background: var(--gray); }
.rm-dot.online { background: var(--green); }
.rm-dot.away { background: var(--amber); }
.rm-dot.busy { background: var(--red); }

/* avatar */
.rm-avatar {
  width: 40px; height: 40px; border-radius: 50%;
  display: grid; place-items: center; font-size: 14px; font-weight: 700; color: #fff;
  box-shadow: 0 4px 12px rgba(23,33,61,0.16);
}

/* ==========================================================================
   Unified top header — injected by roam-header.js on every app page.
   One implementation so all pages share the exact same menu + behaviour.
   ========================================================================== */
.rm-top {
  grid-area: topbar;              /* slots into the office grid; ignored elsewhere */
  position: relative; z-index: 40;
  display: flex; align-items: center; gap: 14px;
  height: 60px; padding: 0 18px;
  border-bottom: 1px solid var(--stroke);
  background: rgba(255, 255, 255, 0.72); backdrop-filter: blur(14px);
}
.rm-top .rm-brand {
  display: flex; align-items: center; gap: 10px;
  font-weight: 700; letter-spacing: -0.02em; white-space: nowrap;
}
.rm-top .rm-brand small { color: var(--muted); font-weight: 500; font-size: 12px; }

.rm-top .rm-menu { display: flex; align-items: center; gap: 8px; margin-left: auto; }
.rm-top .rm-menu a {
  text-decoration: none; color: var(--muted); font-size: 14px; font-weight: 600;
  padding: 8px 14px; border-radius: 999px; border: 1px solid var(--stroke); background: var(--panel);
  display: inline-flex; align-items: center; gap: 8px; line-height: 1;
}
.rm-top .rm-menu a:hover { color: var(--text); border-color: var(--stroke-strong); background: var(--panel-solid); }
.rm-top .rm-menu a.active {
  color: #fff; border-color: transparent;
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  box-shadow: 0 4px 12px rgba(108,140,255,0.32);
}

/* "Chat" nav pill: a distinct accent-tinted treatment (same tint recipe as
   `.rm-badge.accent` above) so it reads as visually different from the other
   plain-text nav words at a glance, not just a subtle color shift. Scoped
   with `:not(.active)` so the normal `.rm-top .rm-menu a.active` rule above
   still wins outright (full accent gradient + white text) when chat.html is
   the current page -- same "you are here" affordance every other nav item
   gets, rather than a permanently-different active state just for Chat. */
.rm-top .rm-menu a.rm-chat-pill:not(.active) {
  color: var(--accent); border-color: rgba(108,140,255,0.35);
  background: rgba(108,140,255,0.16);
}
.rm-top .rm-menu a.rm-chat-pill:not(.active):hover {
  color: var(--accent); background: rgba(108,140,255,0.26); border-color: rgba(108,140,255,0.5);
}

/* grouped dropdown menus (Office ▾ / Projects ▾ / System ▾).
   NOTE: `.rm-group` deliberately does NOT set `position: relative` (it used
   to, back when `.rm-dropdown` was a narrow flyout anchored under just this
   trigger). Now that the dropdown is a full-width mega-menu anchored to the
   bottom of the whole header bar (see `.rm-dropdown` below), its absolute
   positioning needs `.rm-top` (which IS `position: relative`) as its
   containing block, not this narrow inline-flex box -- so this rule must
   stay un-positioned for that to resolve correctly. `.rm-dropdown` remains a
   DOM child of `.rm-group` (unchanged), which is what keeps hover/mouseenter
   working even though the rendered panel visually extends far outside this
   element's own box. */
.rm-top .rm-menu .rm-group { display: inline-flex; }
.rm-top .rm-menu .rm-grouptrigger {
  cursor: pointer; font-family: inherit;
  color: var(--muted); font-size: 14px; font-weight: 600;
  padding: 8px 12px 8px 14px; border-radius: 999px;
  border: 1px solid var(--stroke); background: var(--panel);
  display: inline-flex; align-items: center; gap: 6px; line-height: 1;
}
.rm-top .rm-menu .rm-grouptrigger:hover { color: var(--text); border-color: var(--stroke-strong); background: var(--panel-solid); }
.rm-top .rm-menu .rm-grouptrigger.active {
  color: #fff; border-color: transparent;
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  box-shadow: 0 4px 12px rgba(108,140,255,0.32);
}
.rm-top .rm-menu .rm-grouptrigger .rm-chev { width: 14px; height: 14px; transition: transform 0.15s ease; }
.rm-top .rm-menu .rm-group.open .rm-grouptrigger .rm-chev { transform: rotate(180deg); }

/* Full-width mega-menu panel: anchored to the bottom of the WHOLE header bar
   (`top: 100%` of `.rm-top`, the containing block -- see the note on
   `.rm-group` above), not to the individual trigger. `left: 0; right: 0`
   against that ancestor spans it edge-to-edge, matching `.rm-top`'s own
   full-bleed width, without the `100vw` scrollbar pitfall (`.rm-top` never
   has its own horizontal scrollbar to worry about, and this stays inside
   whatever box `.rm-top` already occupies).
   This used to be a narrow, anchored flyout with a left/right viewport-edge
   flip (`.rm-dropdown--right`, sized by roam-header.js's `positionDropdown()`
   / `layoutGroup()`); that measurement + flip is gone now that the panel is
   always full width regardless of which trigger opened it -- there is
   nothing left to overflow.
   Sits flush at top:100% (no gap in the `top` offset) so the hoverable box
   of .rm-group is unbroken from trigger to panel. No padding-top here either
   (removed the earlier ~8px breathing-room padding by request) -- the panel
   now sits flush against the bottom of the header bar with zero visible gap.
   Zero gap was always the safe case for the hover-continuity concern above
   (padding-top was a look, never load-bearing for hover), and re-verified
   with Playwright hover-chaining after removing it: the group stays open
   moving the pointer straight from trigger into panel with no flicker. */
.rm-top .rm-menu .rm-dropdown {
  position: absolute; top: 100%; left: 0; right: 0; margin-top: 0;
  display: none; flex-direction: column; z-index: 50;
  /* This box is full viewport width, but only its centered `.rm-dd-inner`
     child is visually a card -- the rest is transparent margin that shows
     whatever is underneath (e.g. the left rail, or page content further
     down). Without `pointer-events: none` here, that transparent margin
     still hit-tests as `.rm-dropdown` and silently swallows clicks/hover on
     the rail/page content it visually reveals (confirmed with Playwright:
     `elementFromPoint` over a visible rail icon returned this div, not the
     icon). `.rm-dd-inner` re-enables pointer events for the actual card. */
  pointer-events: none;
}
/* The visible panel is a nested box so the box-shadow/border only wraps the
   solid card, not the (now zero-height) padding bridge above it -- kept as a
   separate element from `.rm-dropdown` for that reason even though both are
   full width now. By request, the card itself now spans the full width of
   `.rm-dropdown` (and thus the header bar) instead of being capped at
   `max-width: 1200px` and centered -- `max-width`/`margin: 0 auto` are
   removed rather than just widened, since nothing needs centering once the
   card and its container are the same width. This still lays out as a
   centered, wrapping ROW of item cards, not one column stretched
   edge-to-edge: `justify-content: center` + `flex-wrap: wrap` remain, and
   `.rm-dditem` below caps each card at `max-width: 300px` (flex-basis
   240px), so on very wide panels (1600px+) the cards wrap into a centered
   cluster of comfortably-sized cards with visible panel background on
   either side of the cluster, not stretched-thin or stretched-wide
   individual cards -- confirmed with Playwright at 1600px viewport. */
.rm-top .rm-menu .rm-dropdown .rm-dd-inner {
  display: flex; flex-direction: row; flex-wrap: wrap; justify-content: center;
  gap: 10px; padding: 16px 18px; width: 100%;
  box-sizing: border-box;
  background: var(--panel-solid); border: 1px solid var(--stroke); border-top: none;
  box-shadow: 0 18px 44px rgba(23,33,61,0.16);
  pointer-events: auto;
}
.rm-top .rm-menu .rm-group.open > .rm-dropdown { display: flex; }
@media (hover: hover) and (min-width: 821px) {
  /* :hover is the no-JS fallback; .hover-open is set/cleared by
     roam-header.js with a short close delay (see HOVER_CLOSE_DELAY).
     NOTE: this CSS-only fallback only ever opens ITS OWN group -- it has no
     way to close a sibling the way roam-header.js's JS mouseenter handler
     now does (closeAllGroups(g) on every hover, not just on click). In the
     narrow window before roam-header.js finishes attaching its listeners,
     rapidly hovering across two triggers could in theory show two panels
     briefly via :hover alone. Left as a known, accepted edge case (it heals
     itself the instant JS attaches, and mouseleave still clears each panel
     independently) rather than reintroducing per-group JS complexity here;
     the primary, reliable fix is the JS-level immediate-close-of-siblings
     in roam-header.js's mouseenter handler. */
  .rm-top .rm-menu .rm-group:hover > .rm-dropdown,
  .rm-top .rm-menu .rm-group.hover-open > .rm-dropdown { display: flex; }
}

/* The old `.rm-dd-bridge` invisible hover-bridge element (and its
   `sizeBridge()`/`sizeBridges()` JS) existed only to patch a dead corner
   between a NARROW trigger and a WIDER anchored flyout panel. Now that the
   panel is a full-width bar directly adjacent to the entire header (not
   just one trigger), that corner no longer exists -- verified with
   Playwright that hovering straight down from a trigger into the panel
   keeps the group open with the bridge removed, so it was deleted rather
   than kept as dead code. */

/* mega-menu item card: icon + title + one-line description. Flex-sized
   (not `width: 100%`) so cards sit in a centered, wrapping row inside the
   full-width panel instead of stacking as one narrow column. */
.rm-top .rm-menu .rm-dropdown a.rm-dditem {
  display: flex; align-items: flex-start; gap: 10px;
  flex: 1 1 240px; max-width: 300px; width: auto;
  padding: 10px 11px; border-radius: 10px;
  border: 1px solid transparent; background: transparent; text-align: left;
}
.rm-top .rm-menu .rm-dropdown a.rm-dditem:hover { background: var(--wash); border-color: transparent; box-shadow: none; }
.rm-top .rm-menu .rm-dropdown a.rm-dditem.active { background: var(--wash-2); border-color: transparent; box-shadow: none; }
.rm-top .rm-menu .rm-dropdown a.rm-dditem .rm-dd-icon {
  flex: 0 0 auto; width: 30px; height: 30px; margin-top: 1px; border-radius: 9px;
  display: grid; place-items: center; font-size: 15px; line-height: 1;
  background: var(--wash); color: var(--accent);
}
.rm-top .rm-menu .rm-dropdown a.rm-dditem.active .rm-dd-icon {
  background: linear-gradient(135deg, var(--accent), var(--accent-2)); color: #fff;
}
.rm-top .rm-menu .rm-dropdown a.rm-dditem .rm-dd-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.rm-top .rm-menu .rm-dropdown a.rm-dditem .rm-dd-title {
  color: var(--text); font-size: 14px; font-weight: 700; white-space: nowrap;
}
.rm-top .rm-menu .rm-dropdown a.rm-dditem.active .rm-dd-title { color: var(--accent); }
.rm-top .rm-menu .rm-dropdown a.rm-dditem .rm-dd-desc {
  color: var(--muted); font-size: 12px; font-weight: 500; line-height: 1.35;
  white-space: normal;
}

/* Generic icon-only control style. Historically used for the Admin gear,
   Settings, and Sign out buttons that used to sit at the right end of the
   header nav -- all three have since moved (Admin/Settings are now plain
   NAV word-links -- see roam-header.js's "Team" and "Profile" entries --
   and Sign out lives on the Profile/Settings page itself), so no header
   markup currently renders `.rm-iconbtn`. Kept as a shared utility class in
   case a future icon-only control needs it. Sized to match the pill nav
   buttons' height exactly (32px: 14px line-height + 8px top/bottom padding +
   1px top/bottom border, same box model as .rm-menu a / .rm-grouptrigger
   above) so anything using it sits on the same visual baseline as the word
   pills instead of reading taller. Do NOT change this 32px circle size --
   it's the height-alignment fix described above. The glyph inside is sized
   independently (22px) for legibility -- see note below. */
/* Compound selector (not just .rm-iconbtn alone) is required here: the
   Settings/Admin buttons are <a> tags inside .rm-menu, so the general
   `.rm-top .rm-menu a` rule above (specificity 0,2,1, padding: 8px 14px)
   would otherwise beat a bare `.rm-iconbtn` (0,1,0) and crush the circle's
   content box down to ~2px -- exactly what was making those two glyphs
   unreadable regardless of the svg size below. Sign-out is a <button> so it
   never matched `.rm-top .rm-menu a` and rendered fine, which is why only
   Settings/Admin looked like indistinct dots. */
.rm-iconbtn,
.rm-top .rm-menu .rm-iconbtn {
  width: 32px; height: 32px; padding: 0; border-radius: 999px; box-sizing: border-box;
  display: inline-grid; place-items: center; cursor: pointer;
  color: var(--muted); background: var(--panel); border: 1px solid var(--stroke);
  font-family: inherit;
}
.rm-iconbtn:hover { color: var(--text); border-color: var(--stroke-strong); background: var(--panel-solid); }
.rm-iconbtn.active {
  color: #fff; border-color: transparent;
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  box-shadow: 0 4px 12px rgba(108,140,255,0.32);
}
/* Glyph size independent of the 32px circle above (do not resize the circle
   to fix icon legibility -- that's a separate, deliberate fix). 18px read as
   an indistinct dot; 22px leaves 5px of padding on each side inside the 32px
   circle -- clearly larger and legible without crowding the border. */
.rm-iconbtn svg { width: 22px; height: 22px; }
.rm-iconbtn .rm-lbl { display: none; }   /* label only appears in the mobile menu */

/* avatar with presence dot (replaces the old status pill / "Available" text) */
.rm-top .rm-ava {
  position: relative; width: 34px; height: 34px; border-radius: 50%; flex: 0 0 auto;
  display: grid; place-items: center; font-size: 12px; font-weight: 700; color: #fff;
  background: linear-gradient(135deg, #6c8cff, #9b6bff);
}
.rm-top .rm-ava .rm-adot {
  position: absolute; right: -1px; bottom: -1px;
  width: 11px; height: 11px; border-radius: 50%;
  background: var(--gray); border: 2px solid #ffffff;
}
.rm-top .rm-ava .rm-adot.online { background: var(--green); }
.rm-top .rm-ava .rm-adot.busy   { background: var(--red); }
.rm-top .rm-ava .rm-adot.offline{ background: var(--gray); }

/* hamburger — desktop hidden */
.rm-burger { display: none; }

@media (max-width: 820px) {
  .rm-top { height: 56px; gap: 10px; padding: 0 12px; }
  .rm-top .rm-brand small { display: none; }
  .rm-burger {
    display: inline-grid; place-items: center; margin-left: auto; order: 3;
    width: 38px; height: 38px; border-radius: 11px; cursor: pointer;
    color: var(--text); background: var(--panel); border: 1px solid var(--stroke);
  }
  .rm-burger svg { width: 20px; height: 20px; }
  .rm-top .rm-ava { order: 2; margin-left: auto; }
  .rm-top .rm-menu {
    position: absolute; top: calc(100% + 8px); right: 10px; left: 10px; margin-left: 0;
    flex-direction: column; align-items: stretch; gap: 6px; padding: 8px;
    border-radius: 14px; background: var(--panel-solid); border: 1px solid var(--stroke-strong);
    box-shadow: 0 18px 44px rgba(23,33,61,0.16); display: none;
  }
  .rm-top.open .rm-menu { display: flex; }
  .rm-top .rm-menu a,
  .rm-top .rm-menu .rm-iconbtn {
    width: 100%; justify-content: flex-start; height: auto; border-radius: 10px; padding: 12px 14px;
  }
  .rm-top .rm-menu .rm-iconbtn { gap: 12px; }
  .rm-top .rm-menu .rm-iconbtn .rm-lbl { display: inline; font-size: 14px; font-weight: 600; }

  /* grouped dropdowns collapse into expandable accordion sections */
  .rm-top .rm-menu .rm-group { width: 100%; flex-direction: column; align-items: stretch; }
  .rm-top .rm-menu .rm-grouptrigger {
    width: 100%; justify-content: space-between; border-radius: 10px; padding: 12px 14px;
  }
  .rm-top .rm-menu .rm-dropdown {
    position: static; display: none;
    padding-top: 2px; margin: 2px 0 0 10px;
    /* The desktop `pointer-events: none` above exists only to let a
       full-width overlay's transparent margin click through to whatever's
       underneath it. In the mobile accordion this is a normal in-flow block
       (nothing behind it to reveal), so restore normal click handling --
       otherwise every link/icon inside it would silently stop working. */
    pointer-events: auto;
  }
  .rm-top .rm-menu .rm-dropdown .rm-dd-inner {
    /* Override the desktop mega-menu's centered wrapping ROW back to the
       mobile accordion's simple stacked COLUMN -- the desktop full-width
       rules above are additive on top of this breakpoint's cascade, so they
       must be explicitly undone here rather than relying on them not
       applying. */
    display: flex; flex-direction: column; flex-wrap: nowrap; justify-content: flex-start;
    padding: 4px 0 4px 10px; max-width: none; width: auto; margin: 0;
    border: none; border-radius: 0; background: transparent; box-shadow: none;
  }
  .rm-top .rm-menu .rm-group.open > .rm-dropdown { display: flex; }
  /* Mobile accordion stays a simple list: icon + title only, no description,
     to keep each row compact on small screens. */
  .rm-top .rm-menu .rm-dropdown a.rm-dditem { padding: 11px 12px; align-items: center; width: 100%; max-width: none; flex: 1 1 auto; }
  .rm-top .rm-menu .rm-dropdown a.rm-dditem .rm-dd-icon { width: 26px; height: 26px; font-size: 13px; }
  .rm-top .rm-menu .rm-dropdown a.rm-dditem .rm-dd-desc { display: none; }
}

/* ==========================================================================
   Left rail — injected by roam-header.js right after the top header, on
   every page. One implementation so the quick-access icons (and the
   "coming soon" popover for items with no page yet) match everywhere.
   ========================================================================== */
.rail {
  grid-area: rail;
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  padding: 14px 0; border-right: 1px solid var(--stroke);
  background: rgba(255, 255, 255, 0.55);
  position: relative; z-index: 30;
}
.rail .floor {
  width: 42px; height: 42px; border-radius: 13px; cursor: pointer;
  display: grid; place-items: center; font-size: 18px; color: var(--muted);
  border: 1px solid transparent; transition: 0.15s;
  appearance: none; -webkit-appearance: none;
  background: none; font-family: inherit; text-decoration: none; padding: 0;
}
.rail .floor:hover { background: var(--wash); color: var(--text); }
.rail .floor.active {
  color: #fff; background: linear-gradient(135deg, var(--accent), var(--accent-2));
  border-color: transparent; box-shadow: 0 4px 12px rgba(108,140,255,0.32);
}
.rail .floor:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.rail .spacer { flex: 1; }

/* "coming soon" popover shown next to a rail icon that has no page yet */
.rail-pop {
  position: fixed; z-index: 60; transform: translateY(-50%);
  padding: 7px 12px; border-radius: 10px; font-size: 12px; font-weight: 600; white-space: nowrap;
  color: var(--text); background: var(--panel-solid);
  border: 1px solid var(--stroke-strong); box-shadow: 0 12px 30px rgba(23,33,61,0.16);
  animation: railpop 0.14s ease-out; pointer-events: none;
}
@keyframes railpop { from { opacity: 0; transform: translateY(-50%) translateX(-4px); } }

@media (max-width: 820px) {
  .rail { display: none; }
}

/* ==========================================================================
   Shared page shell — header + rail + content. Every app page opts in with
   <body class="rm-shell"> and wraps its content in <main class="rm-stage">,
   so Settings, Admin, Leave, Org chart, Activity, Business, Projects,
   Launches, Roadmap, Chat and Games all share the exact same chrome as the
   office's Main Floor. A page needing extra columns (e.g. a right-hand
   panel) adds its own modifier on top — the header/rail stay shared either way.
   ========================================================================== */
/* Site-wide 20% density reduction. Scoped to `.rm-shell` (present on every
   authenticated app page's <body>) rather than `html`/`body` globally, for
   two reasons:
     1. This codebase's spacing/type is almost entirely hardcoded `px`
        (roam.css has zero `rem`/`em` usage), so a root `font-size` trick
        would do nothing here — only `zoom` (or `transform: scale`) actually
        shrinks px-based layouts uniformly. `zoom` is used over `transform`
        because it participates in normal layout (no manual width/height
        compensation needed) and is now supported unprefixed in all
        evergreen engines, Firefox included (since FF 126).
     2. office3d.html, login.html and accept-invite.html all render a plain
        `<body>` with no `.rm-shell` class, so scoping to `.rm-shell` shrinks
        every app page (Office, Admin, Chat, Projects, Dashboard, etc.)
        while automatically leaving the Three.js 3D scene's canvas/camera
        sizing (which reads `window.innerWidth/innerHeight` directly)
        completely untouched, with no edits to office3d.html required. */
body.rm-shell {
  display: grid;
  grid-template-rows: 60px 1fr;
  grid-template-columns: 64px 1fr;
  grid-template-areas:
    "topbar topbar"
    "rail   stage";
  /* `zoom: 0.8` scales this shell to 80%, but viewport units (vh/vw) still
     resolve against the REAL (un-zoomed) viewport — so plain `100vh`/`100vw`
     would render at only ~80% of the physical screen, leaving a ~20% empty
     strip at the bottom AND on the right. Dividing by the zoom factor (0.8)
     makes the box 125vh × 125vw in the zoomed coordinate space, which — after
     the 0.8 scale — lands at exactly 100vh × 100vw of physical screen. Keep
     both `/ 0.8` values in sync with the `zoom` below. */
  height: calc(100vh / 0.8); width: calc(100vw / 0.8); overflow: hidden;
  zoom: 0.8;
}
body.rm-shell > .rm-top { grid-area: topbar; }
body.rm-shell > .rail { grid-area: rail; }
body.rm-shell > .rm-stage { grid-area: stage; overflow-y: auto; min-height: 0; }

@media (max-width: 820px) {
  body.rm-shell {
    grid-template-columns: 1fr;
    grid-template-rows: auto 1fr;
    grid-template-areas: "topbar" "stage";
    /* This block does NOT reset `zoom`, so the base `zoom: 0.8` still applies
       here — compensate the fill height by `/ 0.8` for the same reason as the
       desktop shell above (100vh resolves pre-zoom, so plain 100vh under-fills
       by ~20%). */
    height: auto; min-height: calc(100vh / 0.8); overflow: visible;
  }
}

/* ==========================================================================
   Shared floating chat widget — injected by roam-header.js on every page
   except chat.html itself (the full experience) and the unauthenticated
   login/accept-invite pages. `position: fixed` keeps it viewport-anchored
   regardless of a page's own `rm-shell`/`rm-shell--aside` grid.
   ========================================================================== */
.rm-cw-toggle {
  position: fixed; right: 22px; bottom: 22px; z-index: 70;
  width: 54px; height: 54px; border-radius: 50%; border: none; cursor: pointer;
  display: grid; place-items: center; font-size: 23px; line-height: 1;
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  box-shadow: 0 10px 28px rgba(108,140,255,0.42);
  transition: transform 0.15s ease;
}
.rm-cw-toggle:hover { transform: translateY(-2px); }
.rm-cw-badge {
  position: absolute; top: -3px; right: -3px; min-width: 19px; height: 19px; padding: 0 5px;
  border-radius: 999px; background: var(--red); color: #fff; font-size: 10px; font-weight: 800;
  display: grid; place-items: center; border: 2px solid var(--panel-solid);
}

.rm-cw-panel {
  position: fixed; right: 22px; bottom: 86px; z-index: 70;
  width: 340px; max-width: calc(100vw - 28px);
  height: min(520px, calc(100vh - 130px));
  display: none; flex-direction: column; overflow: hidden;
  background: var(--panel-solid); border: 1px solid var(--stroke); border-radius: 16px;
  box-shadow: 0 20px 50px rgba(23,33,61,0.22);
}
.rm-cw-panel.open { display: flex; }

.rm-cw-head {
  display: flex; align-items: center; gap: 10px; padding: 12px 14px;
  border-bottom: 1px solid var(--stroke); flex: none;
}
.rm-cw-head .rm-cw-title { font-size: 14px; font-weight: 700; }
.rm-cw-head .rm-cw-full {
  margin-left: auto; font-size: 12px; font-weight: 600; color: var(--accent); text-decoration: none;
  white-space: nowrap;
}
.rm-cw-head .rm-cw-full:hover { text-decoration: underline; }
.rm-cw-close {
  border: none; background: none; color: var(--muted); font-size: 18px; line-height: 1;
  cursor: pointer; padding: 0 2px;
}
.rm-cw-close:hover { color: var(--text); }

.rm-cw-body { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.rm-cw-list { flex: 1; min-height: 0; overflow-y: auto; }
.rm-cw-empty { padding: 22px 16px; font-size: 12px; color: var(--muted); text-align: center; }

.rm-cw-convo { display: flex; align-items: center; gap: 10px; padding: 10px 14px; cursor: pointer; }
.rm-cw-convo:hover { background: var(--wash); }
.rm-cw-av {
  width: 32px; height: 32px; border-radius: 10px; flex: none;
  display: grid; place-items: center; font-size: 11px; font-weight: 700; color: #fff;
}
.rm-cw-meta { min-width: 0; flex: 1; }
.rm-cw-row { display: flex; align-items: center; gap: 6px; }
.rm-cw-name { font-size: 12px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rm-cw-when { margin-left: auto; font-size: 10px; color: var(--muted); flex: none; }
.rm-cw-preview { font-size: 11px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rm-cw-unread {
  flex: none; min-width: 17px; height: 17px; padding: 0 5px; border-radius: 999px;
  background: var(--accent); color: #fff; font-size: 10px; font-weight: 700;
  display: inline-flex; align-items: center; justify-content: center;
}

.rm-cw-thread { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.rm-cw-thread-head {
  display: flex; align-items: center; gap: 8px; padding: 10px 14px;
  border-bottom: 1px solid var(--stroke); font-size: 12px; font-weight: 700; flex: none;
}
.rm-cw-back { border: none; background: none; color: var(--muted); font-size: 15px; cursor: pointer; padding: 0 4px; }
.rm-cw-back:hover { color: var(--text); }
.rm-cw-messages { flex: 1; min-height: 0; overflow-y: auto; padding: 12px 14px; display: flex; flex-direction: column; gap: 9px; }
.rm-cw-msg { display: flex; }
.rm-cw-msg.me { justify-content: flex-end; }
.rm-cw-bubble {
  max-width: 82%; background: var(--wash); border: 1px solid var(--stroke);
  padding: 7px 10px; border-radius: 12px;
}
.rm-cw-msg.me .rm-cw-bubble { background: linear-gradient(135deg, rgba(108,140,255,0.18), rgba(155,107,255,0.18)); border-color: rgba(108,140,255,0.3); }
.rm-cw-who { font-size: 10px; color: var(--muted); margin-bottom: 2px; }
.rm-cw-mtext { font-size: 12px; line-height: 1.4; word-break: break-word; }

.rm-cw-composer { display: flex; gap: 8px; padding: 10px 14px; border-top: 1px solid var(--stroke); flex: none; }
.rm-cw-composer input {
  flex: 1; padding: 8px 10px; border-radius: 10px; border: 1px solid var(--stroke-strong);
  background: #fff; font-family: inherit; font-size: 12px; color: var(--text);
}
.rm-cw-composer input::placeholder { color: var(--muted); }
.rm-cw-composer input:focus { outline: none; border-color: var(--accent); }
.rm-cw-composer button {
  padding: 8px 14px; border: none; border-radius: 10px; cursor: pointer; font-weight: 700; font-size: 12px;
  color: #fff; background: linear-gradient(135deg, var(--accent), var(--accent-2));
}
.rm-cw-composer button:hover { filter: brightness(1.07); }

@media (max-width: 480px) {
  .rm-cw-toggle { right: 14px; bottom: 14px; }
  .rm-cw-panel { right: 10px; bottom: 76px; width: calc(100vw - 20px); }
}
