/* Coreidon hub shell.
 *
 * The full-page chat is the main app and owns the sidebar (its own workspace
 * rail, extended with the hub's Settings item and per-app unread counts). This
 * file only styles what wraps it:
 *
 *   Settings — an overlay that covers the chat's list + thread columns but
 *              stops at the rail, so the sidebar stays usable. Notifications
 *              have no overlay: each app's rail panel lists its own.
 *   app mode — a hosted app fills the window below a 26px strip naming it; the
 *              rail is gone. Tapping the strip expands the controls (back,
 *              switcher, close), which re-collapse on a timer. The app must
 *              look like it IS the installed webapp, because to the user it is
 *              — hence a strip rather than a permanent 46px bar.
 */

/* Rail width, mirrored from widget.js's `.wrap` grid — the overlays start
   exactly where the chat's rail ends. */
:root { --rail-w: 76px; }

/* COREIDON.AI brand palette. Navy #091C3A is the dominant action colour (CTAs
   = --cta); cyan is the expressive accent (--accent) reserved for active/links/
   focus/progress — never for primary CTAs. Fonts: Space Grotesk 700 for
   headings/brand/buttons, Inter for body/data (imported in index.html). */
:root {
  color-scheme: light dark;
  --font-head: 'Space Grotesk', system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --font-body: 'Inter', system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;

  --bar-bg: #ffffff; --bar-fg: #000000; --bar-line: #e7e2d9; --bar-muted: #2b303b;
  --surface: #f8f5f0; --surface-2: #ffffff; --rail-bg: #f8f5f0; --hover: #efeae1;
  --brand1: #091c3a; --brand2: #0284c7;
  --cta: #091c3a; --cta-fg: #ffffff;                       /* navy — buttons/CTAs */
  --accent: #0284c7; --accent-weak: rgba(2, 132, 199, 0.12);  /* cyan — accents */
  --success: #16a34a; --danger: #dc2626;
}
:root[data-theme="dark"] {
  --bar-bg: #2b303b; --bar-fg: #ffffff; --bar-line: #1f2a3c; --bar-muted: rgba(248, 245, 240, 0.75);
  --surface: #0a1220; --surface-2: #121b2a; --rail-bg: #2b303b; --hover: #1a2536;
  --brand1: #091c3a; --brand2: #38bdf8;
  --cta: #091c3a; --cta-fg: #ffffff;
  --accent: #38bdf8; --accent-weak: rgba(56, 189, 248, 0.16);
  --success: #34d399; --danger: #fb7185;
}

* { box-sizing: border-box; }
html, body { height: 100%; }
body {
  margin: 0;
  height: 100vh; height: 100dvh;   /* dvh so mobile browser chrome can't cut it off */
  overflow: hidden;
  font-family: var(--font-body);
  background: var(--surface); color: var(--bar-fg);
  -webkit-text-size-adjust: 100%;
}

/* Space Grotesk (700) for headings, brand marks and buttons. */
h1, h2, h3, h4, .view-head h2, .section-title, .card h3, .btn, .forms-item .fi-label, .ai-name {
  font-family: var(--font-head);
}

#hub { display: flex; height: 100%; }

/* ── view stack ──────────────────────────────────────────────────────────── */
#views { position: relative; flex: 1 1 auto; min-width: 0; min-height: 0; }

/* The chat is always mounted and always the bottom layer: it owns the rail,
   which must stay visible and clickable underneath the overlays. */
.view[data-view="chat"] { position: absolute; inset: 0; display: flex; flex-direction: column; }
coreidon-chatable[full] { flex: 1 1 auto; min-height: 0; }

/* Settings: covers the chat list + thread, stops at the rail. */
.view.overlay {
  position: absolute; top: 0; right: 0; bottom: 0; left: var(--rail-w);
  overflow-y: auto; -webkit-overflow-scrolling: touch;
  background: var(--surface); padding: 16px; display: none; z-index: 5;
}
.view.overlay.active { display: block; }

/* The dashboard brings its own header and padding, so drop the overlay's 16px
   inset. The board follows the hub's data-theme (it themes off [data-theme=dark]
   on <html>, which the hub sets), so the surface behind it must track the theme
   too — var(--surface) is warm-white in light, navy-ink in dark. Hardcoding it
   light was what left the board sitting on a light halo in dark mode. */
.view.overlay[data-view="dashboard"] { padding: 0; background: var(--surface); }
#dashboard-host { min-height: 100%; }
/* The board's own root asks for 100vh. Here the overlay is already the scroll
   container with a fixed height, and on a phone 100vh exceeds the VISUAL
   viewport — so that would hang a screenful of empty surface off the bottom of
   every board. Two ids, so it outranks the component's own rule. */
#dashboard-host #dashboard-root { min-height: 100%; }

/* The dashboard's back arrow exists for phones only — see the wide-screen rule
   at the bottom of this block. It needs its own inset (the dashboard overlay has
   none) and must track the theme, since the board underneath is now dark in dark
   mode. */
#dashboard-head { padding: 10px 12px 0; background: var(--surface); color: var(--bar-fg); }
#dashboard-head .view-head { margin-bottom: 8px; }
#dashboard-head .back { border-color: var(--bar-line); color: var(--bar-muted); }
@media (min-width: 721px) { #dashboard-head { display: none; } }

.view-head { display: flex; align-items: center; gap: 12px; margin-bottom: 12px; }
.view-head h2 { margin: 0; font-size: 17px; flex: 1; }
.view-head .back {
  border: 1px solid var(--bar-line); background: transparent; color: var(--bar-muted);
  width: 34px; height: 34px; border-radius: 10px; cursor: pointer; font-size: 16px; flex: none;
}
.view-head .back:hover { color: var(--bar-fg); border-color: var(--accent); }

/* Phones: the chat hides its rail once a thread is open, so an overlay that
   stopped at the rail would leave a dead strip — go full width and rely on the
   overlay's own back button. */
@media (max-width: 720px) {
  .view.overlay { left: 0; }
}

/* ── hosted apps ─────────────────────────────────────────────────────────── */
/* One frame per open app, stacked; only the active one is visible. Frames are
   kept mounted so switching preserves each app's scroll position and state. */
#frames { position: absolute; inset: 0; display: none; }
#hub.app-mode #frames { display: block; }
#frames iframe {
  position: absolute; inset: 0; width: 100%; height: 100%;
  border: 0; display: none; background: var(--bar-bg);
}
#frames iframe.active { display: block; }

/* In app mode every piece of hub chrome gets out of the way — the chat (and
   with it the rail) included. */
#hub.app-mode .view { display: none; }

/* ── chat over an app (drawer) ───────────────────────────────────────────── */
/* Reading and answering a message shouldn't cost you the app you're in. The
   chat view is NOT moved into an overlay — reparenting the custom element would
   fire disconnectedCallback, re-run boot() and drop its SSE stream. Instead the
   view it already lives in becomes a drawer, so the widget never notices.
   The frame keeps rendering behind it and holds all its state.
   z-index sits BELOW #appbar (45) on purpose: the bar stays reachable, so the
   same chat button that opened the drawer closes it. */
#hub.app-mode.chat-open .view[data-view="chat"] {
  display: flex;
  position: fixed; right: 0; bottom: 0; left: auto;
  top: calc(var(--ab-peek-h) + var(--ab-safe));
  /* Wide enough for the widget's own three columns (76 rail + 268 list +
     thread) — it decides its layout from window width, not container width, so
     a narrow drawer on a desktop would render the 3-column grid into 420px. */
  width: min(980px, 100vw);
  z-index: 44;
  border-left: 1px solid var(--bar-line);
  box-shadow: -18px 0 48px rgba(10, 12, 20, 0.22);
  background: var(--surface);
}

/* Phones: the widget is already in its single-column mode, so take the width. */
@media (max-width: 720px) {
  #hub.app-mode.chat-open .view[data-view="chat"] { width: 100vw; border-left: 0; }

  /* A 26px strip is a fine hover target and a poor thumb target. Give it real
     height on touch screens so the app name AND the chat button are tappable
     without magnifying — this is the one piece of chrome that is always there. */
  :root { --ab-peek-h: 40px; }
  #appbar .ab-peek { padding-right: 4px; }
  #appbar .ab-peek .ab-chat { height: 34px; min-width: 44px; padding: 0 10px; }
  #appbar .ab-peek .ab-chat svg { width: 17px; height: 17px; }
  #appbar .ab-peek-main { font-size: 13px; }
}

/* ── app-mode chrome (auto-hiding top bar) ───────────────────────────────── */
/* Replaces the old bottom "handle": a 46x5px pill at 45% opacity, unlabelled,
   pinned to exactly the edge where mobile apps put their own nav — it collided
   with projex's bottom bar and was well under the 44px minimum tap target.
   The top edge instead: the hub can't see inside a cross-origin frame, so it
   can't dodge an app's chrome — the only safe move is to own an edge apps
   don't use, and to reserve that space rather than float above it. */
/* --ab-safe: this is an INSTALLED webapp, so in standalone mode a top-anchored
   bar runs under the status bar / notch. The old chrome was bottom-anchored and
   paid the same tax with safe-area-inset-bottom. */
:root { --ab-peek-h: 26px; --ab-full-h: 46px; --ab-safe: env(safe-area-inset-top, 0px); }

/* The frame is inset by the COLLAPSED height only; expanding overlays the app
   instead of resizing it, because reflowing a cross-origin iframe on every
   toggle is both slow and visibly janky. */
#hub.app-mode #frames { top: calc(var(--ab-peek-h) + var(--ab-safe)); }

#appbar {
  position: fixed; top: 0; left: 0; right: 0; z-index: 45;
  height: calc(var(--ab-peek-h) + var(--ab-safe));
  padding-top: var(--ab-safe);
  overflow: hidden;
  background: var(--bar-bg); border-bottom: 1px solid var(--bar-line);
  transition: height 0.16s cubic-bezier(0.2, 0.8, 0.2, 1);
}
#appbar[hidden] { display: none; }
#appbar.open { height: calc(var(--ab-full-h) + var(--ab-safe)); }

/* Collapsed strip: a row, not one button — it carries its own chat control so
   chat is ONE tap from here, not expand-then-tap. (A button can't nest a
   button, hence the container.) */
#appbar .ab-peek {
  display: flex; align-items: center; gap: 6px;
  width: 100%; height: var(--ab-peek-h); padding: 0 6px 0 12px;
  color: var(--bar-muted);
}
#appbar.open .ab-peek { display: none; }
#appbar .ab-peek-main {
  display: flex; align-items: center; gap: 8px;
  flex: 1; min-width: 0; height: 100%; padding: 0;
  border: 0; background: transparent; color: inherit;
  font: inherit; font-size: 11.5px; font-weight: 650; cursor: pointer;
  text-align: left;
}
#appbar .ab-peek-main:hover { color: var(--bar-fg); }
#appbar .ab-peek-main svg { width: 13px; height: 13px; flex: none; opacity: 0.8; }
#appbar .ab-peek .ab-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Compact inside the strip; the expanded bar keeps the roomier .ab-btn size. */
#appbar .ab-peek .ab-chat { min-width: 0; height: calc(var(--ab-peek-h) - 4px); padding: 0 8px; }
#appbar .ab-peek .ab-chat svg { width: 14px; height: 14px; }

#appbar .ab-full {
  display: none; align-items: center; gap: 6px;
  height: var(--ab-full-h); padding: 0 8px;
}
#appbar.open .ab-full { display: flex; }
/* Every open app, inline — switching is one tap, with no menu in between. The
   strip scrolls sideways rather than wrapping, so the bar keeps its height no
   matter how many apps are open. */
#appbar .ab-tabs {
  flex: 1; min-width: 0; display: flex; align-items: center; gap: 4px;
  overflow-x: auto; overflow-y: hidden;
  scrollbar-width: none;                     /* the tabs are the affordance */
}
#appbar .ab-tabs::-webkit-scrollbar { display: none; }

#appbar .ab-tab {
  display: inline-flex; align-items: center; gap: 2px; flex: none;
  height: 32px; padding: 0 4px 0 10px;
  border: 1px solid var(--bar-line); border-radius: 10px;
  background: transparent; color: var(--bar-muted);
  max-width: 46vw;
}
#appbar .ab-tab.on {
  background: var(--accent-weak); border-color: var(--accent); color: var(--accent);
}
#appbar .ab-tab-open {
  border: 0; background: transparent; color: inherit; cursor: pointer;
  font: inherit; font-size: 13px; font-weight: 650; padding: 0; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
#appbar .ab-tab-x {
  border: 0; background: transparent; color: inherit; cursor: pointer;
  width: 22px; height: 22px; border-radius: 7px; flex: none;
  display: grid; place-items: center; opacity: 0.55; padding: 0;
}
#appbar .ab-tab-x:hover { opacity: 1; background: var(--hover); color: var(--danger); }
#appbar .ab-tab-x svg { width: 12px; height: 12px; }
/* Per-tab unread — distinct from .ab-badge, which counts everything else. */
#appbar .ab-dot {
  min-width: 16px; height: 16px; padding: 0 4px; flex: none;
  border-radius: 8px; background: var(--danger); color: #fff;
  font-size: 9.5px; font-weight: 800; display: grid; place-items: center;
}
#appbar .ab-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  min-width: 40px; height: 34px; padding: 0 10px; flex: none;
  border: 1px solid transparent; border-radius: 10px;
  background: transparent; color: var(--bar-muted);
  font: inherit; font-size: 13px; font-weight: 600; cursor: pointer;
}
#appbar .ab-btn:hover { background: var(--surface-2); color: var(--bar-fg); }
#appbar .ab-btn svg { width: 16px; height: 16px; flex: none; }
#appbar .ab-btn.danger:hover { color: var(--danger); }

/* Chat. Its own control, because chat is not an app tab and its messages never
   reach the notifications service — the count arrives from the widget. */
#appbar .ab-chat.has { color: var(--accent); }
#appbar .ab-chat-n {
  min-width: 16px; height: 16px; padding: 0 4px;
  border-radius: 8px; background: var(--accent); color: #fff;
  font-size: 9.5px; font-weight: 800; display: grid; place-items: center;
}
#appbar .ab-chat-n[hidden] { display: none; }

/* Unread count — shown in both states so collapsing never hides it. */
#appbar .ab-badge {
  min-width: 18px; height: 18px; padding: 0 5px; flex: none;
  border-radius: 9px; background: var(--accent); color: #fff;
  font-size: 10.5px; font-weight: 800; display: grid; place-items: center;
}
#appbar .ab-badge[hidden] { display: none; }

/* Notifications have no view here: each app's rail panel lists its own (see
   widget.js `_renderAppNotifications`), and the rail item carries the count. */

/* ── settings ────────────────────────────────────────────────────────────── */
.section-title { font-size: 12px; font-weight: 700; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--bar-muted); margin: 4px 0 12px; }
.card {
  background: var(--surface-2); border: 1px solid var(--bar-line);
  border-radius: 16px; padding: 14px; margin-bottom: 14px;
}
.card h3 { margin: 0 0 4px; font-size: 15px; }
.card p.hint { margin: 0 0 12px; font-size: 12px; color: var(--bar-muted); line-height: 1.45; }
.row { display: flex; align-items: center; gap: 12px; padding: 10px 0; border-bottom: 1px solid var(--bar-line); }
.row:last-child { border-bottom: 0; }
.row .grow { flex: 1; min-width: 0; }
.row .label { font-size: 13px; }
.row .label small { display: block; color: var(--bar-muted); font-size: 11px; margin-top: 2px; }
.btn {
  font: inherit; font-size: 13px; font-weight: 600; cursor: pointer;
  border: 1px solid var(--bar-line); background: transparent; color: var(--bar-fg);
  border-radius: 10px; padding: 9px 14px;
}
/* Secondary button: transparent, subtle border; hover to cyan border + text. */
.btn:hover { border-color: var(--accent); color: var(--accent); }
/* Primary CTA: navy fill, white text, snappy hover lift (never cyan). */
.btn.primary { background: var(--cta); border-color: var(--cta); color: var(--cta-fg); }
.btn.primary:hover { border-color: var(--cta); color: var(--cta-fg); opacity: 0.92; }
.btn:disabled { opacity: 0.5; cursor: default; }
/* The app filter reuses .btn so it matches the buttons beside it. */
select.btn { padding: 8px 10px; max-width: 55%; background: var(--surface-2); color: var(--bar-fg); }

/* Event matrix: label + two checkbox columns, header aligned with the rows. */
.events-head, .event-row {
  display: grid; grid-template-columns: 1fr 56px 56px; gap: 8px; align-items: center;
  border-bottom: 1px solid var(--bar-line);
}
.events-head { padding: 4px 0 10px; }
.events-head .col {
  font-size: 10px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--bar-muted); text-align: center;
}
.event-row { padding: 12px 0; }
.event-row:last-child { border-bottom: 0; }
.event-row .label { font-size: 13px; line-height: 1.35; }
.event-row .label small { display: block; color: var(--bar-muted); font-size: 11px; margin-top: 2px; }

input[type="checkbox"].ch {
  -webkit-appearance: none; appearance: none; margin: 0; justify-self: center;
  width: 20px; height: 20px; border: 1.5px solid var(--bar-line); border-radius: 6px;
  background: transparent; cursor: pointer; display: grid; place-content: center;
}
input[type="checkbox"].ch::before {
  content: ""; width: 11px; height: 11px; transform: scale(0);
  transition: transform 0.12s ease; box-shadow: inset 0 0 0 11px #fff;
  clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%);
}
input[type="checkbox"].ch:checked { background: var(--accent); border-color: var(--accent); }
input[type="checkbox"].ch:checked::before { transform: scale(1); }

/* iOS-style switch for the single master toggles. */
.switch { position: relative; width: 46px; height: 27px; flex: none; }
.switch input { position: absolute; opacity: 0; width: 100%; height: 100%; margin: 0; cursor: pointer; }
.switch span {
  position: absolute; inset: 0; border-radius: 14px; background: var(--bar-line);
  transition: background 0.15s ease; pointer-events: none;
}
.switch span::after {
  content: ""; position: absolute; top: 3px; left: 3px; width: 21px; height: 21px;
  border-radius: 50%; background: #fff; transition: transform 0.15s ease;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25);
}
.switch input:checked + span { background: var(--accent); }
.switch input:checked + span::after { transform: translateX(19px); }

/* ── forms ───────────────────────────────────────────────────────────────── */
.forms-wrap { max-width: 640px; }
.forms-wrap > .hint { margin: 0 0 16px; font-size: 12px; color: var(--bar-muted); line-height: 1.45; }
.forms-group { margin-bottom: 18px; }
.forms-list { display: flex; flex-direction: column; gap: 8px; }
.forms-item {
  display: flex; align-items: center; gap: 12px; width: 100%; text-align: left;
  font: inherit; cursor: pointer; color: var(--bar-fg);
  background: var(--surface-2); border: 1px solid var(--bar-line);
  border-radius: 14px; padding: 12px 14px;
}
.forms-item:hover { border-color: var(--accent); background: var(--accent-weak); }
.forms-item .fi-glyph {
  flex: none; width: 32px; height: 32px; border-radius: 9px;
  display: grid; place-items: center; font-size: 17px; line-height: 1;
  background: var(--accent-weak); color: var(--accent);
}
.forms-item .fi-body { flex: 1; min-width: 0; }
.forms-item .fi-label { display: block; font-size: 14px; font-weight: 600; }
.forms-item .fi-desc { display: block; color: var(--bar-muted); font-size: 12px; margin-top: 2px; }
.forms-item .fi-open { flex: none; color: var(--bar-muted); font-size: 18px; }
.forms-item:hover .fi-open { color: var(--accent); }

/* ── admin: AI access ──────────────────────────────────────────────────────── */
.ai-search {
  width: 100%; box-sizing: border-box; margin: 0 0 12px;
  font: inherit; font-size: 13px; color: var(--bar-fg);
  background: var(--surface-2); border: 1px solid var(--bar-line);
  border-radius: 12px; padding: 10px 12px;
}
.ai-search:focus { outline: none; border-color: var(--accent); }
.ai-list { display: flex; flex-direction: column; }
.ai-row {
  display: flex; align-items: center; gap: 12px;
  padding: 11px 2px; border-bottom: 1px solid var(--bar-line);
}
.ai-row:last-child { border-bottom: 0; }
.ai-row .grow { flex: 1; min-width: 0; }
.ai-name { font-size: 14px; }
.ai-email { display: block; color: var(--bar-muted); font-size: 12px; margin-top: 2px; }

/* ── misc ────────────────────────────────────────────────────────────────── */
.empty, .error { font-size: 13px; color: var(--bar-muted); padding: 24px 8px; text-align: center; }
.error { color: var(--danger); }
.toast {
  position: fixed; left: 50%; transform: translateX(-50%);
  bottom: calc(env(safe-area-inset-bottom) + 78px); z-index: 60;
  background: var(--bar-fg); color: var(--bar-bg);
  font-size: 13px; padding: 10px 16px; border-radius: 12px; max-width: 90vw;
}
/* "New version ready" — stays until acted on, so it also needs to sit above a
   full-bleed app frame. */
.toast.update { display: flex; align-items: center; gap: 12px; padding: 10px 10px 10px 16px; }
.toast.update .btn { padding: 6px 12px; }
