:root {
  --bg: #14151a;
  --bg-elevated: #1b1d24;
  --bg-hover: #262932;
  --border: #2a2d37;
  --text: #e7e9ee;
  --text-muted: #9298a6;
  --accent: #5b8cff;
  --accent-text: #0b1020;
  --radius: 10px;
  --sidebar-w: 260px;
  --sidebar-w-collapsed: 64px;
}

:root[data-theme="light"] {
  --bg: #f5f6f8;
  --bg-elevated: #ffffff;
  --bg-hover: #eceef2;
  --border: #dfe2e8;
  --text: #1a1d24;
  --text-muted: #6b7280;
  --accent: #3462e0;
  --accent-text: #ffffff;
}

* { box-sizing: border-box; }

html, body {
  height: 100%;
  margin: 0;
}

body {
  background: var(--bg);
  color: var(--text);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  font-size: 14px;
}

.app {
  display: flex;
  height: 100vh;
  overflow: hidden;
}

/* ---------- Sidebar ---------- */

.sidebar {
  width: var(--sidebar-w);
  min-width: var(--sidebar-w);
  background: var(--bg-elevated);
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  transition: width .18s ease, min-width .18s ease;
  overflow: hidden;
}

.sidebar.collapsed {
  width: var(--sidebar-w-collapsed);
  min-width: var(--sidebar-w-collapsed);
}

.sidebar-header {
  display: flex;
  align-items: center;
  gap: 10px;
  /* Same vertical padding as .content-header so both header rows are the
     same height and their border-bottom lines land flush across the
     sidebar/content boundary instead of stepping. */
  padding: 10px 12px;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}

.brand {
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.sidebar.collapsed .brand,
.sidebar.collapsed .sidebar-search {
  display: none;
}

/* Keep the theme toggle reachable when folded — only the Foyer link/year
   (which need room to read) hide; the button itself stays, centered like
   the rest of the icon rail, instead of the whole footer vanishing and
   taking the toggle down with it. */
.sidebar.collapsed .sidebar-footer {
  justify-content: center;
  padding: 10px 0;
}

.sidebar.collapsed .sidebar-footer > .footer-left {
  display: none;
}

.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border-radius: 8px;
  border: 1px solid var(--border);
  background: var(--bg-hover);
  color: var(--text-muted);
  cursor: pointer;
  flex-shrink: 0;
}

.icon-btn:hover {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-text);
}

.icon-btn svg {
  width: 18px;
  height: 18px;
}

.sidebar-search {
  padding: 10px 12px;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}

.sidebar-search input {
  width: 100%;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 7px 10px;
  color: var(--text);
  font-size: 13px;
}

.sidebar-search input:focus {
  outline: 2px solid var(--accent);
  outline-offset: -1px;
}

.nav-groups {
  flex: 1;
  overflow-y: auto;
  overflow-x: hidden;
  padding: 8px 0;
  scrollbar-width: thin;
  scrollbar-color: var(--border) transparent;
}

.nav-groups::-webkit-scrollbar {
  width: 8px;
}

.nav-groups::-webkit-scrollbar-track {
  background: transparent;
}

.nav-groups::-webkit-scrollbar-thumb {
  background: var(--border);
  border-radius: 4px;
}

.nav-groups::-webkit-scrollbar-thumb:hover {
  background: var(--text-muted);
}

.group {
  margin-bottom: 4px;
}

/* "Level 0" groups (show_as_group: false in config) — items show directly,
   no header, no folded-mode flyout. Thin dividers separate them from
   whichever named groups actually border them — only on sides where a
   neighbor exists (:not(:first-child)/:not(:last-child) — disabled groups
   never enter the DOM at all, so these correctly reflect real neighbors,
   not config positions), since an ungrouped group can trail the last group
   (only needs a top divider), lead the first (only bottom), or sit
   sandwiched between two (both).

   Expanded-mode only (.sidebar:not(.collapsed)) — folded mode draws its
   own dividers as ::before/::after pseudo-elements further down instead
   of a real border, because margin/border on the group itself would also
   narrow the icon buttons' box and throw off their centering in the rail.
   This rule used to have no such scope and stayed active when folded too,
   stacking directly on top of the pseudo-element divider — that doubled
   line was a real, reproducible bug (confirmed via computed styles:
   border-top-width and the ::before pseudo were both 1px at once on the
   same folded element), not a misread screenshot. */
.sidebar:not(.collapsed) .group.ungrouped:not(:first-child) {
  border-top: 1px solid var(--border);
  margin-top: 8px;
  padding-top: 4px;
}

.sidebar:not(.collapsed) .group.ungrouped:not(:last-child) {
  border-bottom: 1px solid var(--border);
  margin-bottom: 8px;
  padding-bottom: 4px;
}

.group-title {
  display: flex;
  align-items: center;
  gap: 6px;
  width: 100%;
  background: none;
  border: none;
  color: var(--text-muted);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  padding: 8px 14px;
  cursor: pointer;
  text-align: left;
}

.group-title:hover {
  color: var(--text);
}

.group-title .chevron {
  width: 12px;
  height: 12px;
  transition: transform .15s ease;
  flex-shrink: 0;
}

.group.collapsed .chevron {
  transform: rotate(-90deg);
}

.group.collapsed .item-list {
  display: none;
}

/* ---------- Folded sidebar: per-group flyout ---------- */
/* Folded mode shows one representative icon per group (group-icon-btn)
   instead of the group header + inline item list. Hovering/tapping it
   pops the group's item list open as a floating panel next to it — same
   items, same click behavior as expanded mode, just reached differently.
   JS reparents the real <ul class="item-list"> to <body> (position:fixed,
   .flyout-active) while it's open, because overflow clipping from the
   sidebar/.nav-groups scroll containers applies to descendants regardless
   of position:absolute/fixed — only actually leaving that DOM subtree
   escapes it. It's moved back into its .group on close. */

.group-icon-btn {
  display: none;
}

.sidebar.collapsed .group-title {
  display: none;
}

/* Hides the inline item list for groups that were left expanded before
   folding — while a list is showing as a flyout it's been reparented to
   <body> (see above), so it's no longer a descendant of .sidebar and this
   rule doesn't touch it. */
.sidebar.collapsed .item-list {
  display: none;
}

/* Ungrouped ("level 0") items have no group-icon-btn/flyout to hide behind
   — they need to stay directly visible in the folded rail, same as the
   flat all-icons rail this app used before the flyout redesign. Icon-only,
   centered, label/new-tab-arrow hidden (no room in a 64px rail; the title
   tooltip covers both). */
.sidebar.collapsed .group.ungrouped {
  position: relative;
  margin: 8px 0;
  padding: 8px 0;
}

/* Inset dividers drawn as pseudo-elements rather than margin/border on the
   group itself — margin here would also narrow the icon buttons' own box,
   throwing off their centering in the rail. Only on sides that actually
   border another group (same :not(:first-child)/:not(:last-child) logic
   as the expanded-mode version above) — otherwise a trailing group (like
   the public demo's, which is last) gets an orphaned line after it with
   nothing left to divide from. */
.sidebar.collapsed .group.ungrouped:not(:first-child)::before,
.sidebar.collapsed .group.ungrouped:not(:last-child)::after {
  content: "";
  position: absolute;
  left: 16px;
  right: 16px;
  height: 1px;
  background: var(--border);
}

.sidebar.collapsed .group.ungrouped:not(:first-child)::before {
  top: 0;
}

.sidebar.collapsed .group.ungrouped:not(:last-child)::after {
  bottom: 0;
}

.sidebar.collapsed .group.ungrouped .item-list {
  display: block;
}

.sidebar.collapsed .group.ungrouped .item {
  justify-content: center;
  padding: 7px 0;
  margin: 1px 0;
}

.sidebar.collapsed .group.ungrouped .item-label {
  display: none;
}

.sidebar.collapsed .group.ungrouped .item.new-tab-hint::after {
  display: none;
}

.sidebar.collapsed .group-icon-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  padding: 7px 0;
  margin: 1px 0;
  background: none;
  border: none;
  cursor: pointer;
  border-radius: 8px;
}

.sidebar.collapsed .group-icon-btn:hover {
  background: var(--bg-hover);
}

.item-list.flyout-active {
  position: fixed;
  width: max-content;
  min-width: 200px;
  max-width: 280px;
  max-height: calc(100vh - 24px);
  overflow-y: auto;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 6px;
  box-shadow: 0 12px 28px rgba(0, 0, 0, .35);
  z-index: 1000;
}

.flyout-header {
  display: none;
}

.item-list.flyout-active .flyout-header {
  display: block;
  padding: 6px 10px 8px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.item-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 14px;
  margin: 1px 6px;
  border-radius: 8px;
  cursor: pointer;
  color: var(--text);
  text-decoration: none;
  white-space: nowrap;
}

.item:hover {
  background: var(--bg-hover);
}

.item.active {
  background: var(--accent);
  color: var(--accent-text);
}

.item.active .item-label {
  color: var(--accent-text);
}

.item-icon-wrap {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  flex-shrink: 0;
  border-radius: 6px;
  overflow: hidden;
}

/* Applied only to icons whose own colors are too close to the current
   page background (checked at runtime) — gives them a contrasting chip
   so they don't disappear. Icons that already contrast fine get no chip. */
.item-icon-wrap.icon-needs-backing {
  background: #16171c;
}

.item-icon-wrap.icon-needs-backing.icon-backing-light {
  background: #ffffff;
}

.item-icon-wrap.icon-needs-backing .item-icon {
  padding: 3px;
}

.item-icon {
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  object-fit: contain;
}

.item-label {
  overflow: hidden;
  text-overflow: ellipsis;
  font-size: 13.5px;
}

.item.new-tab-hint::after {
  content: "↗";
  margin-left: auto;
  font-size: 11px;
  color: var(--text-muted);
  flex-shrink: 0;
}

.item.active.new-tab-hint::after {
  color: var(--accent-text);
  opacity: .8;
}

.item.hidden-by-search {
  display: none;
}

.sidebar-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 10px 10px 14px;
  border-top: 1px solid var(--border);
  color: var(--text-muted);
  font-size: 12px;
  flex-shrink: 0;
}

.theme-toggle svg {
  width: 16px;
  height: 16px;
}

.footer-left {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
  overflow: hidden;
}

.footer-link {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  color: var(--text-muted);
  text-decoration: none;
  font-weight: 600;
  white-space: nowrap;
  flex-shrink: 0;
}

.footer-link:hover {
  color: var(--text);
}

/* ---------- Main content ---------- */

.content {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.content-header {
  position: relative;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 10px 16px;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}

/* Centered on the header as a whole (not just the flex gap between the home
   button and clock, which would skew off-center since those two are
   different widths) — taken out of flow and centered independently via
   absolute positioning, with max-width so it can't run under either
   sibling on a narrow window. */
.pane-title {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  max-width: 50%;
  font-weight: 600;
  font-size: 14px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.clock {
  margin-left: auto;
  color: var(--text-muted);
  font-size: 12.5px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  flex-shrink: 0;
}

@media (max-width: 480px) {
  .clock {
    display: none;
  }
}

.pane-body {
  flex: 1;
  position: relative;
  overflow: hidden;
}

.placeholder {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-muted);
}

.pane-frame {
  width: 100%;
  height: 100%;
  border: none;
  background: #fff;
}

.dashboard-grid {
  position: absolute;
  inset: 0;
  overflow-y: auto;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
  gap: 16px;
  align-content: start;
  padding: 28px;
}

.dashboard-card {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  padding: 20px 12px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: 14px;
  cursor: pointer;
  color: var(--text);
  font: inherit;
}

.dashboard-card.new-tab-hint::after {
  content: "↗";
  position: absolute;
  top: 8px;
  right: 10px;
  font-size: 12px;
  color: var(--text-muted);
}

.dashboard-card:hover {
  border-color: var(--accent);
  transform: translateY(-2px);
}

.dashboard-card .item-icon-wrap {
  width: 44px;
  height: 44px;
  border-radius: 12px;
}

.dashboard-card .item-icon {
  width: 26px;
  height: 26px;
}

.dashboard-card-label {
  font-size: 13px;
  font-weight: 500;
  text-align: center;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 100%;
}

.hidden {
  display: none !important;
}

.sidebar-backdrop {
  display: none;
}

@media (max-width: 720px) {
  .sidebar {
    position: fixed;
    z-index: 10;
    height: 100%;
  }
  .sidebar:not(.collapsed) {
    width: 82vw;
    min-width: 220px;
  }

  /* Because .sidebar is position:fixed here, it's out of normal flow and
     .content doesn't automatically reflow around it the way it does on
     desktop — without this, the folded icon rail permanently sits on top
     of the content-header (home button, title) and the left edge of the
     grid/iframe underneath, since nothing shifts to make room for it. The
     expanded (82vw) drawer is still fine overlapping this margin — it's a
     temporary overlay meant to cover content while open, dismissed via the
     backdrop below, not something content should permanently reflow for. */
  .content {
    margin-left: var(--sidebar-w-collapsed);
  }

  /* On desktop, folding the sidebar shrinks it in-flow so .content just
     reflows into the freed space. On mobile the sidebar is taken out of
     flow (position:fixed) so it can overlay content instead of squeezing
     it into a sliver — but that means an "open" (not collapsed) sidebar
     here is a full drawer sitting on top of everything, with nothing
     underneath to tap to dismiss it. This backdrop is that tap target: a
     dimmed scrim behind the open drawer, closing it on click, so content
     un-covers itself instead of being permanently blocked. */
  .sidebar-backdrop {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 9;
    background: rgba(0, 0, 0, .45);
    opacity: 0;
    pointer-events: none;
    transition: opacity .18s ease;
  }

  .sidebar-backdrop.visible {
    opacity: 1;
    pointer-events: auto;
  }
}
