/* ============================================================
   Self-hosted webfont — Baloo 2 (the display/brand face).
   Was loaded from Google Fonts (fonts.googleapis.com CSS + gstatic woff2);
   self-hosted now so no third-party CDN sees our users' IP/referrer on every
   pageload, and the CSP can drop Google entirely. Baloo 2 ships as a VARIABLE
   font — one woff2 per subset covers weights 500–700, so a single @font-face
   with a weight range is correct (and we only ship latin + latin-ext; the
   devanagari/vietnamese subsets Google served are dropped — unused here).
   Body copy stays system-ui (no webfont). SIL OFL 1.1 (Ek Type).
============================================================ */
@font-face {
  font-family: "Baloo 2";
  font-style: normal;
  font-weight: 500 700;
  font-display: swap;
  src: url("/fonts/baloo2-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Baloo 2";
  font-style: normal;
  font-weight: 500 700;
  font-display: swap;
  src: url("/fonts/baloo2-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* Icons — self-hosted inline SVG (lib/icons.js via the {{{icon}}} helper); size with
   font-size or width/height, color via currentColor. Replaced Font Awesome. */
.icon { display: inline-block; width: 1em; height: 1em; vertical-align: -0.125em; flex: none; }

/* ============================================================
   Design tokens — cool slate palette, light + dark.
   :root is the light theme (also the no-JS fallback); [data-theme="dark"]
   overrides. theme.js resolves "auto" → light|dark before paint, so the html
   element always carries a concrete data-theme. Components consume tokens only,
   never raw hex — the palette is the single knob.
   The neutrals are slate (the raven's cool grey); the brand accent is royal blue.
============================================================ */
:root {
  --bg: #f4f6f9;          /* cool slate off-white — calm, not clinical */
  --surface: #ffffff;     /* cards, bubbles, raised UI */
  --panel: var(--surface); /* legacy alias */
  --ink: #182130;         /* cool slate near-black text */
  --text: var(--ink);     /* legacy alias (inputs, chips) */
  --muted: #667085;       /* slate grey */
  --accent: #3457e0;      /* royal blue — the brand */
  --accent-ink: #ffffff;  /* text/icon on an accent fill */
  --border: #e3e8ef;      /* cool slate hairline */
  --error: #d64545;

  --font-display: "Baloo 2", system-ui, sans-serif;
  --font-body: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;

  /* App-shell geometry — a messaging client. Desktop: a fixed left nav rail +
     a full-width pane. Mobile (< 880px): the rail is replaced by a fixed top bar
     + bottom tab bar. --content-max caps reading width WITHIN the pane (chat,
     prose) so full-width text stays legible. The 880px breakpoint is hardcoded in
     media queries (custom props can't be used in media conditions). */
  --rail-w: 248px;        /* desktop nav rail */
  --content-max: 760px;   /* readable cap inside the pane */
  --chat-max: 1080px;     /* wider cap for the chat thread (full-width, left-aligned msgs) */
  --mtop-h: 54px;         /* mobile fixed top bar */
  --tabbar-h: 64px;       /* mobile fixed bottom nav */
}
[data-theme="dark"] {
  --bg: #10141c;          /* cool slate charcoal, not warm black */
  --surface: #191f2a;
  --ink: #e8ecf3;
  --muted: #8b95a7;
  --accent: #6b8aff;      /* brighter royal for dark contrast */
  --accent-ink: #ffffff;
  --border: #262d3a;
  --error: #ff6b6b;
}

/* ── Accent skins ("skins" in the UI) ────────────────────────────────────────
   The accent color is independent of light/dark — data-accent on <html> swaps
   the --accent token, mirroring how data-theme swaps the palette. Server-rendered
   before paint (layouts) so there's no flash; persisted on the User (POST /api/accent).
   "royal" is the default — it's the :root/[data-theme] values above. Every skin
   keeps white ink (--accent-ink stays #fff), at parity with royal, so the hardcoded
   white-on-accent fills (buttons, chips) stay legible. Each skin declares a LIGHT
   value and a (slightly brighter) DARK value; the two-attribute dark selector
   outranks the single-attribute [data-theme="dark"] base, so dark mode picks the
   dark value. The swatch list in lib/skins.js must stay in sync with the keys here
   (the route validates against it).

   Royal IS the default (the :root/[data-theme] values), but it gets an explicit
   block too so a royal SWATCH (a button carrying its own data-accent="royal") can
   paint itself from --accent regardless of the page's current skin. Coral/blue are
   kept as pickable options (and so any pre-rebrand stored value still resolves). */
[data-accent="royal"]  { --accent: #3457e0; }
[data-theme="dark"][data-accent="royal"]  { --accent: #6b8aff; }
[data-accent="teal"]   { --accent: #14b8a6; }
[data-theme="dark"][data-accent="teal"]   { --accent: #2dd4bf; }
[data-accent="violet"] { --accent: #8b5cf6; }
[data-theme="dark"][data-accent="violet"] { --accent: #a78bfa; }
[data-accent="blue"]   { --accent: #3b82f6; }
[data-theme="dark"][data-accent="blue"]   { --accent: #5b9bff; }
[data-accent="amber"]  { --accent: #f59e0b; }
[data-theme="dark"][data-accent="amber"]  { --accent: #fbb024; }
[data-accent="rose"]   { --accent: #f43f6b; }
[data-theme="dark"][data-accent="rose"]   { --accent: #ff5c81; }
[data-accent="coral"]  { --accent: #ff6a3d; }
[data-theme="dark"][data-accent="coral"]  { --accent: #ff7a52; }

* { box-sizing: border-box; }
body {
  margin: 0;
  font: 16px/1.5 var(--font-body);
  background: var(--bg);
  color: var(--ink);
}
h1, h2, h3, .brand-wordmark { font-family: var(--font-display); }
/* .wrap is the NON-dashboard page frame (landing, auth, onboarding). The
   dashboard uses the app-shell (rail + pane) instead — see .app-shell below. */
.wrap { max-width: 980px; margin: 0 auto; padding: 24px; }
a { color: var(--accent); }
.muted { color: var(--muted); }
/* The HTML `hidden` attribute must win — any component that sets its own `display`
   (flex/grid/inline-flex) otherwise overrides it, so a JS/template `hidden` toggle
   silently does nothing (this was the storefront's "everything looks installed" bug:
   .skill-installed { display: inline-flex } beat [hidden]). One global rule fixes it
   everywhere and lets the per-component [hidden] overrides retire. */
[hidden] { display: none !important; }
.error { color: var(--error); }
/* Utility: hide regardless of a component's own display rule (the onboarding
   chat box, error lines, etc. carry class="hidden" until JS reveals them). */
.hidden { display: none !important; }
code, pre { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
pre { background: var(--panel); padding: 12px 14px; border-radius: 8px; overflow:auto; }

.hero { text-align: center; padding: 64px 0; }
.hero h1 { font-size: 56px; margin: 0; }
.tagline { font-size: 22px; }
.sub { color: var(--muted); }
.cta-row { margin-top: 28px; display: flex; gap: 12px; justify-content: center; }

.btn {
  display: inline-block; padding: 10px 18px; border-radius: 10px;
  border: 1px solid var(--border); background: var(--panel); color: var(--ink);
  text-decoration: none; cursor: pointer; font-size: 15px;
}
.btn-primary { background: var(--accent); border-color: var(--accent); color: #fff; }
/* Secondary button: a real raised surface (not a transparent outline that vanishes on the
   warm bg), with a defined border + subtle lift, and a coral accent on hover. */
.btn-ghost { background: var(--panel); border-color: color-mix(in srgb, var(--ink) 25%, transparent); box-shadow: 0 2px 6px rgba(0, 0, 0, 0.07); }
.btn-ghost:hover { border-color: var(--accent); color: var(--accent); }
.btn-danger { background: transparent; border-color: var(--error); color: var(--error); }
.btn-danger:hover { background: var(--error); color: #fff; }
/* Disabled buttons: dimmed, no pointer, and hover styles neutralized. */
.btn:disabled, .btn[disabled] { opacity: 0.45; cursor: not-allowed; }
.btn-danger:disabled:hover, .btn-danger[disabled]:hover { background: transparent; color: var(--error); }

/* ── Free-tier paywall modal (platform chrome; the agent never triggers it) ── */
.paywall { display: none; position: fixed; inset: 0; z-index: 1000; align-items: center; justify-content: center; padding: 20px; }
.paywall.is-open { display: flex; }
.paywall__backdrop { position: absolute; inset: 0; background: rgba(0, 0, 0, 0.45); }
.paywall__card {
  position: relative; background: var(--surface); border: 1px solid var(--border);
  border-radius: 20px; padding: 28px 24px; max-width: 380px; width: 100%; text-align: center;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.25); display: flex; flex-direction: column; gap: 14px;
}
.paywall__face { font-size: 40px; line-height: 1; }
img.paywall__face { width: 40px; height: 40px; object-fit: contain; display: block; margin: 0 auto; }
.paywall__title { font-family: "Baloo 2", system-ui, sans-serif; font-size: 22px; margin: 0; color: var(--ink); }
.paywall__body { margin: 0; color: var(--text); opacity: 0.85; font-size: 15px; line-height: 1.5; }
.paywall__actions { display: flex; flex-direction: column; gap: 10px; margin-top: 4px; }
.paywall__actions .btn { width: 100%; justify-content: center; }

/* Kill iOS Safari's double-tap-to-zoom on tappable controls (e.g. the chat
   jump-to-latest arrow read as a double-tap → the view zoomed in). Pinch-zoom
   is untouched, so accessibility zoom still works. */
button, a, textarea, .btn { touch-action: manipulation; }

/* ── Account / Settings (the human's profile) ─────────────────────────────── */
.settings { display: flex; flex-direction: column; gap: 16px; max-width: 540px; margin: 0 auto; }
.settings-head { display: flex; align-items: center; gap: 14px; }
.settings-title { margin: 0; font-size: 22px; }
.settings-sub { margin: 2px 0 0; font-size: 14px; }
.settings-section { background: var(--surface); border: 1px solid var(--border); border-radius: 16px; padding: 20px; display: flex; flex-direction: column; gap: 14px; }
.settings-section > h2 { margin: 0; font-size: 16px; }
.settings-section > h3 { margin: 0; }
.settings-section > .sub { margin: -8px 0 2px; font-size: 13px; }
.settings-section .field { gap: 6px; }
.settings-row { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.ff-input:disabled { opacity: 0.65; cursor: not-allowed; }
/* Notifications toggle: label left, switch right. */
.settings-toggle { justify-content: space-between; flex-wrap: nowrap; cursor: pointer; gap: 16px; }
.settings-toggle > span:first-child { font-size: 14px; line-height: 1.45; }
.ff-switch { flex: none; -webkit-appearance: none; appearance: none; width: 44px; height: 26px; border-radius: 999px; background: var(--border); position: relative; cursor: pointer; transition: background 0.15s ease; }
.ff-switch::after { content: ""; position: absolute; top: 3px; left: 3px; width: 20px; height: 20px; border-radius: 50%; background: #fff; transition: transform 0.15s ease; box-shadow: 0 1px 2px rgba(0,0,0,0.25); }
.ff-switch:checked { background: var(--accent); }
.ff-switch:checked::after { transform: translateX(18px); }
.ff-switch:disabled { opacity: 0.6; cursor: wait; }
/* Standalone notice page (unsubscribe confirmation). */
.notice { max-width: 480px; margin: 12vh auto 0; text-align: center; display: flex; flex-direction: column; gap: 14px; align-items: center; }
.notice-heading { margin: 0; }
.notice-message { margin: 0; line-height: 1.55; }

.key-status { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: 0; font-size: 14px; }
.key-status .ok { color: var(--accent); font-weight: 600; }
.key-status .warn { color: var(--error); font-weight: 600; }
.key-status .ok .icon, .key-status .warn .icon { margin-right: 4px; }
.key-rotate { display: flex; gap: 8px; }
.key-rotate .ff-input { flex: 1; }
.key-remove { margin: 10px 0 0; }
/* Inline text button (no chrome) — used for the quiet "Remove key" disconnect. */
.btn-link { background: none; border: 0; padding: 0; font: inherit; cursor: pointer; text-decoration: underline; color: var(--accent); }
.btn-link.danger { color: var(--error); }
.btn-link:disabled { opacity: 0.5; cursor: default; }

.plan-badge { display: inline-block; padding: 5px 14px; border-radius: 999px; border: 1px solid var(--border); background: var(--bg); font-size: 13px; text-transform: capitalize; font-weight: 600; }

/* Danger zone (Profile tab) — the data-custody delete affordance. */
/* The danger zone is a .settings-section card like the others — it sits in the
   same flex gap, so it needs NO extra top margin/padding (that double-spaced it).
   A faint error-tinted border keeps it distinct without shouting. */
.danger-zone { border-color: color-mix(in srgb, var(--error) 35%, var(--border)); }
.danger-zone h3 { margin: 0 0 6px; color: var(--error); font-size: 15px; }
.danger-zone .muted { margin: 0 0 12px; }
.acct-delete-confirm { margin-top: 14px; display: flex; flex-direction: column; gap: 8px; max-width: 360px; }
.acct-delete-actions { display: flex; gap: 8px; }

/* Inputs (shared by onboarding + the profile knobs) */
.ff-input {
  width: 100%;
  background: var(--bg);
  border: 1px solid var(--border);
  color: var(--text);
  padding: 10px 12px;
  border-radius: 10px;
  font-size: 16px; /* 16px keeps iOS from auto-zooming on focus */
  font-family: inherit;
}
.ff-input:focus { outline: none; border-color: var(--accent); }

/* Form fields + chips — shared by the account/settings page. */
.field { display: flex; flex-direction: column; gap: 8px; }
.field > label { font-size: 13px; color: var(--text); font-weight: 600; }
.field > label .muted { font-weight: 400; }
.chipset { display: flex; gap: 8px; flex-wrap: wrap; }
.chip {
  background: var(--bg);
  border: 1px solid var(--border);
  color: var(--text);
  padding: 8px 16px;
  border-radius: 999px;
  cursor: pointer;
  font-size: 14px;
  transition: border-color 0.12s, background 0.12s;
}
.chip:hover { border-color: var(--accent); }
.chip.active { background: var(--accent); border-color: var(--accent); color: #fff; }

/* Accent skin picker — a row of color swatches. Each swatch carries its OWN
   data-accent="<key>", so the [data-accent] blocks above re-set --accent on that
   button and it paints itself (no inline styles — the CSP forbids them, and this
   reuses the one accent palette so the preview can't drift from the applied color).
   The selected one gets a ring. Same data-field wiring shape as the theme chipset. */
.swatchset { display: flex; gap: 12px; flex-wrap: wrap; }
.swatch {
  width: 34px; height: 34px; border-radius: 50%; padding: 0; cursor: pointer;
  background: var(--accent); border: 2px solid var(--surface);
  box-shadow: 0 0 0 1px var(--border);
  transition: box-shadow 0.12s, transform 0.08s;
}
.swatch:hover { transform: scale(1.06); }
.swatch.active { box-shadow: 0 0 0 2px var(--surface), 0 0 0 4px var(--accent); }
.swatch:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--surface), 0 0 0 4px var(--accent); }

.pf-status { min-height: 18px; font-size: 13px; margin: 0; }
.pf-status.err { color: var(--error); }

/* (The .about-* read-only profile page was retired 2026-06-15 — Delete moved into
   Settings → Agents; its styles were removed with it.) */

.card { background: var(--panel); border: 1px solid var(--border); border-radius: 14px; padding: 28px; }
.card.narrow { max-width: 420px; margin: 48px auto; }
.stack { display: flex; flex-direction: column; gap: 14px; }
.stack label { display: flex; flex-direction: column; gap: 6px; font-size: 14px; }
.stack input {
  padding: 10px 12px; border-radius: 8px; border: 1px solid var(--border);
  background: var(--bg); color: var(--ink); font-size: 15px;
}

/* ── Auth (sign-in / check-email) — the one door. Same warm chrome as the
   landing (pub-header/footer wrap these pages), one centered card. ── */
.auth { display: flex; justify-content: center; padding: 40px 0 64px; }
.auth__card {
  width: 100%; max-width: 470px; background: var(--surface);
  border: 1px solid var(--border); border-radius: 20px; padding: 36px 32px;
  box-shadow: 0 16px 42px rgba(0,0,0,0.06);
}
.auth__face {
  display: grid; place-items: center; width: 52px; height: 52px; border-radius: 15px;
  background: color-mix(in srgb, var(--accent) 12%, var(--surface));
  font-size: 28px; line-height: 1; margin-bottom: 16px;
}
.auth__title { margin: 0 0 10px; font-size: 30px; letter-spacing: -0.01em; }
.auth__lede { margin: 0 0 22px; color: var(--muted); line-height: 1.55; font-size: 15.5px; }
.auth__lede strong { color: var(--ink); }
.auth__form { display: flex; flex-direction: column; gap: 9px; }
.auth__label { font-size: 13px; font-weight: 700; color: var(--ink); }
.auth__input {
  width: 100%; padding: 12px 14px; border-radius: 10px; border: 1px solid var(--border);
  background: var(--bg); color: var(--ink); font-size: 15px;
}
.auth__input:focus {
  outline: none; border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent);
}
.auth__submit { width: 100%; margin-top: 4px; }
.auth__steps {
  list-style: none; margin: 22px 0 0; padding: 18px 0 0; border-top: 1px solid var(--border);
  display: flex; flex-direction: column; gap: 11px;
}
.auth__steps li { display: flex; align-items: center; gap: 11px; font-size: 14.5px; color: var(--muted); }
.auth__stepE { flex: none; width: 1.5em; text-align: center; font-size: 16px; }
.auth__fine { margin: 18px 0 0; }
.auth__fine a, .auth__lede a { color: var(--accent); }
/* check-email variant: centered, no form */
.auth__card--center { text-align: center; }
.auth__card--center .auth__face { margin-left: auto; margin-right: auto; }
.auth__card--center .auth__submit { margin-top: 8px; }

/* The /join profile picker — a real "pick a face" list: uniform full-width, left-aligned
   tiles (not content-width buttons) with a fixed emoji column so the names line up. An
   "or" divider sets the returning members apart from the new-person tile, which reads as
   a distinct, lighter action. */
.join-who { display: flex; flex-direction: column; gap: 10px; margin-top: 6px; }
.join-who__list { display: flex; flex-direction: column; gap: 10px; }
.join-who form { margin: 0; }
.join-who__btn {
  display: flex; align-items: center; gap: 12px; width: 100%;
  justify-content: flex-start; text-align: left;
  padding: 14px 16px; font-size: 16px; font-weight: 600;
}
.join-who__btn:hover { border-color: var(--accent); color: var(--ink); }
.join-who__emoji { flex: none; width: 1.6em; text-align: center; font-size: 22px; line-height: 1; }
.join-who__or {
  display: flex; align-items: center; gap: 12px; margin: 2px 2px;
  color: var(--muted); font-size: 13px;
}
.join-who__or::before, .join-who__or::after { content: ""; flex: 1; height: 1px; background: var(--border); }
.join-who__btn--new { border-style: dashed; color: var(--muted); }
.join-who__btn--new:hover { border-color: var(--accent); color: var(--ink); }

/* ════════════════════════════════════════════════════════════════════════════
   APP SHELL — a messaging client. Desktop (≥880px): a fixed left nav rail + a
   scrolling pane. Mobile (<880px): the rail is hidden; a fixed top bar (.mtop) +
   bottom tab bar (.tabbar) take over. The 880px breakpoint is hardcoded (custom
   props can't drive media queries).
   ════════════════════════════════════════════════════════════════════════════ */
.app-shell { display: flex; min-height: 100dvh; }
.pane { flex: 1; min-width: 0; }

.brand { display: inline-flex; align-items: center; gap: 8px; text-decoration: none; }
.brand .icon { width: 24px; height: 24px; color: var(--accent); }
/* Brand mark = an <img> of the 🐦‍⬛ Fluent emoji (public/brand-mark.png), so the wordmark
   face is identical on every platform — Safari/Firefox don't substitute their own emoji font. */
.brand-face { width: 24px; height: 24px; flex: none; object-fit: contain; }
/* Other brand-face images (the same Fluent-emoji brand mark), each sized to match the glyph it
   replaced. Nested forms sit INSIDE their tinted container; standalone forms are the img itself. */
.auth__face img { width: 30px; height: 30px; object-fit: contain; }
.land-badge__face img { width: 15px; height: 15px; object-fit: contain; }
.lchat-av--agent img { width: 20px; height: 20px; object-fit: contain; }
img.onb-choose__face { width: 40px; height: 40px; object-fit: contain; }
img.onb-choose__emoji { width: 30px; height: 30px; object-fit: contain; }
.brand-wordmark { font-weight: 700; font-size: 22px; letter-spacing: -0.02em; color: var(--ink); }
.brand-dot { color: var(--accent); }

/* ── The rail (desktop) ─────────────────────────────────────────────────────── */
.rail {
  position: sticky; top: 0; align-self: flex-start; flex: none;
  width: var(--rail-w); height: 100dvh;
  display: flex; flex-direction: column; gap: 6px;
  padding: 18px 14px; background: var(--bg); border-right: 1px solid var(--border);
}
.rail__brand { padding: 4px 10px 12px; }

.rail__nav { display: flex; flex-direction: column; gap: 2px; margin-top: 6px; }
.rail__item {
  display: flex; align-items: center; gap: 12px; padding: 10px 12px;
  border-radius: 10px; color: var(--muted); text-decoration: none; font-size: 15px;
}
.rail__item .icon { width: 20px; height: 20px; }
.rail__item:hover { background: var(--surface); color: var(--ink); }
.rail__item.is-active { background: var(--surface); color: var(--ink); font-weight: 600; }
.rail__item.is-active .icon { color: var(--accent); }
.rail__count {
  margin-left: auto; font-size: 12px; color: var(--muted);
  background: var(--bg); border: 1px solid var(--border); border-radius: 999px; padding: 0 7px;
  /* Always 600 so the active state's font-weight bump (.rail__item.is-active) doesn't
     re-weight the digits and jiggle the pill's width when you click between sections. */
  font-weight: 600;
}
.rail__foot { margin-top: auto; }

/* ── Mobile top bar (.mtop) — brand left, agent + account right. Hidden ≥880px. ── */
.mtop {
  display: none; position: fixed; top: 0; left: 0; right: 0; z-index: 50;
  align-items: center; justify-content: space-between; gap: 10px;
  height: var(--mtop-h); padding: 0 14px;
  background: var(--bg); border-bottom: 1px solid var(--border);
}
.mtop__brand { flex: none; }
.mtop__right { display: flex; align-items: center; gap: 8px; }

/* ── Agent switcher (.bswitch) — rail row by default; avatar circle in the mtop.
      The menu (switch / new / About) is identical in both. ───────────────────── */
.bswitch { position: relative; }
.bswitch-btn {
  display: flex; align-items: center; gap: 10px; width: 100%; padding: 10px;
  border: 1px solid transparent; border-radius: 12px; background: none;
  color: var(--ink); font-family: inherit; text-align: left; cursor: pointer;
}
.bswitch-btn:hover { background: var(--surface); }
/* Mid-birth: a non-interactive switcher (no menu, no caret) — just the newborn's
   ✨+name, filling in live. Mirrors .bswitch-btn padding so it sits identically. */
.bswitch--newborn { display: flex; align-items: center; gap: 10px; width: 100%; padding: 10px; }
.bswitch-avatar { font-size: 28px; line-height: 1; flex: none; }
.bswitch-label { display: flex; flex-direction: column; min-width: 0; }
.bswitch-name { font-family: var(--font-display); font-weight: 700; font-size: 17px; }
.bswitch-sub { font-size: 12px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bswitch-caret { margin-left: auto; flex: none; font-size: 12px; color: var(--muted); }
/* Mobile top bar: avatar-only circular trigger. */
.mtop .bswitch-btn { width: 38px; height: 38px; padding: 0; justify-content: center; border-color: var(--border); border-radius: 999px; background: var(--surface); }
.mtop .bswitch-avatar { font-size: 22px; }
.mtop .bswitch-label, .mtop .bswitch-caret { display: none; }

.bswitch-menu {
  position: absolute; left: 0; top: calc(100% + 8px); z-index: 60;
  min-width: 220px; padding: 8px;
  background: var(--surface); border: 1px solid var(--border); border-radius: 14px;
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.18);
}
.bswitch-menu[hidden] { display: none; }
.mtop .bswitch-menu { left: auto; right: 0; }
.bswitch-menu__label { font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); padding: 6px 10px 4px; }
.bswitch-menu__sep { height: 1px; background: var(--border); margin: 6px 4px; }
.bswitch-item {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 8px 10px; border-radius: 10px; text-decoration: none; color: var(--ink); font-size: 15px;
}
.bswitch-item:hover { background: var(--bg); }
.bswitch-item.is-active { font-weight: 600; }
.bswitch-item__avatar { display: grid; place-items: center; flex: none; width: 28px; height: 28px; border-radius: 999px; background: var(--bg); font-size: 16px; }
.bswitch-item__avatar--new, .bswitch-item__avatar--ghost { color: var(--muted); font-size: 12px; }
.bswitch-item__name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bswitch-item__check { margin-left: auto; color: var(--accent); font-size: 12px; }

/* ── Account cluster (shared: rail foot + mobile top bar) ───────────────────── */
.acct { position: relative; }
.acct-btn {
  display: flex; align-items: center; gap: 10px; width: 100%; padding: 8px 10px;
  border-radius: 12px; border: 1px solid transparent; background: none;
  color: var(--ink); font-family: inherit; text-align: left; cursor: pointer; line-height: 1.2;
}
.acct-btn:hover { background: var(--surface); }
.acct-avatar { font-size: 22px; line-height: 1; flex: none; }
.acct-avatar--lg { font-size: 26px; }
/* Both account + member avatars are now the .acct-avatar SPAN with their own emoji (the face
   Dustav set for the person — NOT the brand raven). The img form is kept sized in case any
   surface still points at a raster mark. */
img.acct-avatar { width: 22px; height: 22px; object-fit: contain; flex: none; }
img.acct-avatar--lg { width: 26px; height: 26px; }
.acct-btn__label { display: flex; flex-direction: column; min-width: 0; }
.acct-btn__name { font-size: 14px; font-weight: 600; }
.acct-btn__email { font-size: 12px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 150px; }
/* Mobile top bar: avatar-only circular trigger (no label row). */
.mtop .acct-btn { width: 38px; height: 38px; padding: 0; justify-content: center; border-color: var(--border); border-radius: 999px; background: var(--surface); }
.mtop .acct-btn__label { display: none; }

.acct-menu {
  position: absolute; right: 0; top: calc(100% + 8px); z-index: 60;
  min-width: 210px; padding: 8px;
  background: var(--surface); border: 1px solid var(--border); border-radius: 14px;
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.18);
}
/* Rail foot opens UPWARD and stretches to the rail width. */
.acct--up .acct-menu { top: auto; bottom: calc(100% + 8px); left: 0; right: 0; }
.acct-menu[hidden] { display: none; }
.acct-menu__head {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 10px 12px; margin-bottom: 6px; border-bottom: 1px solid var(--border);
}
.acct-email { font-size: 13px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.acct-menu__form { margin: 0; }
.acct-menu__item {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 10px; border: none; background: none; border-radius: 10px;
  color: var(--ink); font-size: 15px; font-family: inherit; text-align: left;
  text-decoration: none; cursor: pointer;
}
.acct-menu__item:hover { background: var(--bg); }
.acct-menu__item .icon { width: 18px; height: 18px; color: var(--muted); }
.acct-menu__item--dev { color: var(--muted); }

/* ── Bottom tab bar (mobile only, full width) ──────────────────────────────── */
.tabbar {
  display: none; position: fixed; left: 0; right: 0; bottom: 0; z-index: 50;
  /* Pin to the geometry token so the copilot peek bar (bottom: --tabbar-h) sits FLUSH on top of it —
     without this the bar's content only added up to ~58px, leaving a ~6px strip of calendar showing. */
  min-height: calc(var(--tabbar-h) + env(safe-area-inset-bottom));
  align-items: center;
  background: var(--surface); border-top: 1px solid var(--border);
  box-shadow: 0 -6px 20px rgba(0, 0, 0, 0.12);
  padding: 6px 6px calc(6px + env(safe-area-inset-bottom));
}
.tabbar__item {
  flex: 1; display: flex; flex-direction: column; align-items: center;
  justify-content: center; gap: 2px; padding: 6px 0; border-radius: 10px;
  color: var(--muted); text-decoration: none; font-size: 11px;
}
.tabbar__item .icon { width: 18px; height: 18px; }
.tabbar__item:hover { color: var(--ink); }
.tabbar__item.is-active { color: var(--accent); }

/* Section-nav loading state (public/js/nav-loading.js): on click, hide the icon and
   show a small spinner in its place, so a full-page navigation reads as "loading", not
   a dead click. Same ring as the files reader (.glass-spinner / glass-spin), sized to
   the nav icon — 20px on the rail, 18px in the tab bar. */
.rail__item.is-loading .icon,
.tabbar__item.is-loading .icon { display: none; }
.rail__item.is-loading::before,
.tabbar__item.is-loading::before {
  content: ""; flex: none; box-sizing: border-box;
  border: 2px solid var(--border); border-top-color: var(--accent);
  border-radius: 50%; animation: glass-spin 0.7s linear infinite;
}
.rail__item.is-loading::before { width: 20px; height: 20px; }
.tabbar__item.is-loading::before { width: 18px; height: 18px; }
@media (prefers-reduced-motion: reduce) {
  .rail__item.is-loading::before,
  .tabbar__item.is-loading::before { animation: none; } /* static ring still reads as a status indicator */
}

/* ── The pane content: a readable column, centered. Files/Skills opt wider. ─── */
.tabpane { max-width: var(--content-max); margin: 0 auto; padding: 28px 24px 56px; }
.tabpane.hidden { display: none; }
#tab-context, #tab-skills { max-width: 1080px; }

/* ── Mobile: hide the rail, show the bars, pad the pane clear of both. ──────── */
@media (max-width: 879px) {
  .rail { display: none; }
  .mtop { display: flex; }
  .tabbar { display: flex; }
  .tabpane { max-width: 640px; padding: calc(var(--mtop-h) + 16px) 16px calc(var(--tabbar-h) + env(safe-area-inset-bottom) + 16px); }
  #tab-context, #tab-skills { max-width: 640px; }
  /* Re-match the pane's mobile padding so the hero still bleeds to the column edges + the top bar. */
  .fam-hero { margin: calc(-1 * (var(--mtop-h) + 16px)) -16px 24px; padding: 32px 16px 28px; }
}

/* ── Chat — a native thread filling the WHOLE pane: full-width header + scroller
      + composer, each with its inner content centered to reading width. The
      scrollbar rides the panel edge; the text stays in a tidy column. ───────── */
#tab-chat {
  max-width: none; margin: 0;            /* fill the pane, edge to edge */
  display: flex; flex-direction: column;
  height: 100dvh; padding: 0;            /* the three bars own their padding */
}

/* Fixed header bar — spans the pane, content centered. */
.chat-head { flex: none; border-bottom: 1px solid var(--border); padding: 12px 24px; }
.agent-strip { display: flex; align-items: center; gap: 8px; max-width: var(--chat-max); margin: 0 auto; }
.agent-strip__avatar { font-size: 22px; }
.agent-strip__name { font-weight: 600; }
.agent-strip__copy { margin-left: auto; font-size: 15px; padding: 5px 12px; }
.agent-strip__restart { font-size: 15px; padding: 5px 12px; color: var(--muted); }
.agent-strip__restart:hover { color: var(--error); }
.onb-restart-msg { margin: 0; color: var(--muted); font-size: 14px; line-height: 1.5; }

/* The scroller IS the panel; each row centers itself to the (wide) chat width. */
.messages { position: relative; flex: 1; min-height: 0; display: flex; flex-direction: column; overflow-y: auto; padding: 16px 24px; }
.messages > .ce-row { width: 100%; max-width: var(--chat-max); margin-left: auto; margin-right: auto; }
.note { align-self: center; font-size: 12px; color: var(--muted); }

/* Composer docked at the foot — full-width bar, content centered. The input is a
   <textarea> so long messages word-wrap; it auto-grows one line at a time (chat-core)
   up to max-height, then scrolls. align-items:flex-end keeps the send button on the
   last line as it grows. */
.chat-form { flex: none; border-top: 1px solid var(--border); padding: 12px 24px; }
.chat-form__inner { display: flex; gap: 10px; align-items: flex-end; max-width: var(--chat-max); margin: 0 auto; }
/* Per-turn cost readout — a quiet line BELOW the composer, bottom-left of its column
   (config.showTurnCost). Tabular figures so the dollar amounts don't jitter as they update;
   help cursor on hover (the title carries the token/cache/tool breakdown). */
.chat-cost {
  max-width: var(--chat-max); margin: 6px auto 0; padding: 0 6px;
  font-size: 12px; color: var(--muted); text-align: left;
  font-variant-numeric: tabular-nums; cursor: help; user-select: none;
}
.chat-form textarea {
  flex: 1; padding: 11px 18px; border-radius: 14px;
  border: 1px solid var(--border); background: var(--surface); color: var(--ink);
  font-size: 16px; font-family: inherit; line-height: 1.4; box-sizing: border-box;
  resize: none; min-height: calc(1.4em + 24px); max-height: 160px; overflow-y: hidden;
}
.chat-form textarea:focus { outline: none; border-color: var(--accent); }
.chat-form button[type="submit"] {
  flex: none; width: 44px; height: 44px; padding: 0; border-radius: 999px;
  display: grid; place-items: center; font-size: 16px;
}
.chat-tip {
  max-width: var(--content-max); margin: 8px auto 0; padding: 0 6px;
  font-size: 12px; color: var(--muted); text-align: center;
}
.chat-tip kbd {
  font: inherit; background: var(--surface); border: 1px solid var(--border);
  border-radius: 5px; padding: 1px 6px; color: var(--ink);
}

/* ── Timeline home — the chat thread wrapped as a calendar+notes agenda feed
      (TEARDOWN.md). Header + agenda pills + empty-state sit above the existing
      thread; the quick-action chips sit inside the composer. All reuse the chat column. ─ */
.tl-head__inner { display: flex; align-items: center; gap: 12px; max-width: var(--chat-max); margin: 0 auto; }
.tl-head__title { font-weight: 700; font-size: 18px; }
.tl-head__cal { margin-left: auto; display: inline-flex; align-items: center; gap: 6px; font-size: 14px; color: var(--muted); }
.tl-head__cal svg { width: 16px; height: 16px; }
.tl-head__cal:hover { color: var(--accent); }

.tl-keynudge {
  flex: none; display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  max-width: var(--chat-max); margin: 12px auto 0; padding: 12px 16px; box-sizing: border-box;
  border: 1px solid var(--accent); border-radius: 12px; background: var(--surface); font-size: 14px;
}
.tl-keynudge > span { flex: 1; min-width: 180px; }
.btn-sm { padding: 6px 14px; font-size: 14px; }

.tl-agenda {
  flex: none; display: flex; gap: 8px; overflow-x: auto; scrollbar-width: thin;
  max-width: var(--chat-max); width: 100%; margin: 12px auto 0; padding: 4px 24px; box-sizing: border-box;
}
.tl-event {
  flex: none; display: flex; flex-direction: column; gap: 2px; padding: 8px 12px;
  border: 1px solid var(--border); border-radius: 12px; background: var(--surface);
  min-width: 128px; max-width: 220px;
}
.tl-event:hover { border-color: var(--accent); }
.tl-event__when { font-size: 12px; color: var(--accent); font-weight: 600; white-space: nowrap; }
.tl-event__title { font-size: 14px; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.tl-empty { flex: none; max-width: var(--chat-max); margin: 24px auto; padding: 0 24px; box-sizing: border-box; text-align: center; }
.tl-empty__lead { margin: 0 0 6px; font-weight: 600; font-size: 16px; }
.tl-empty__sub { margin: 0; color: var(--muted); font-size: 14px; line-height: 1.5; }

.tl-quick {
  display: flex; gap: 8px; overflow-x: auto; scrollbar-width: thin;
  max-width: var(--chat-max); margin: 0 auto 10px; padding-bottom: 2px;
}
.tl-chip {
  flex: none; display: inline-flex; align-items: center; gap: 6px; padding: 7px 13px;
  border: 1px solid var(--border); border-radius: 999px; background: var(--surface);
  color: var(--ink); font-size: 13px; font-family: inherit; cursor: pointer; white-space: nowrap;
}
.tl-chip:hover { border-color: var(--accent); color: var(--accent); }
.tl-chip svg { width: 15px; height: 15px; }

/* ── Suite copilot panel (views/partials/copilot-panel.hbs) — a REUSABLE side panel (calendar
      today, notes next) that mounts the shared chat component (chat-core.js). Desktop: a thin,
      collapsible right rail beside the suite (default open; collapses to a 46px icon rail, saved).
      Mobile: a bottom DRAWER — a peek bar above the tab bar that taps up into a full-height sheet.
      One class drives each mode: .is-collapsed (desktop rail) and .is-open (mobile drawer), each
      scoped to its breakpoint so they never fight. ── */
.copilot {
  flex: none; width: 340px; align-self: stretch;
  display: flex; flex-direction: column; min-height: 0;
  border-left: 1px solid var(--border); background: var(--bg);
  overflow: hidden; /* clip the body while it slides, so nothing spills during the width animation */
}
.copilot.is-collapsed { width: 46px; }
/* Cheeky slide when you click "Ask Dustav" — the panel width springs open/closed with a little
   overshoot. Gated on .copilot--anim (added by copilot.js AFTER the initial collapsed state is set)
   so a restored-collapsed panel doesn't animate itself open→shut on page load. The body is pinned to
   full width (below) so the chat text is REVEALED by the slide rather than reflowing mid-animation. */
.copilot.copilot--anim { transition: width 0.32s cubic-bezier(0.34, 1.15, 0.64, 1), top 0.32s cubic-bezier(0.34, 1.15, 0.64, 1); }
@media (prefers-reduced-motion: reduce) { .copilot.copilot--anim { transition: none; } }

/* The handle: desktop = a header row (icon · label · collapse chevron); collapsed = just the icon.
   Mobile = the peek bar / drawer header (see the media query). */
.copilot__handle {
  flex: none; display: flex; align-items: center; gap: 8px; width: 100%;
  padding: 11px 14px; border: none; border-bottom: 1px solid var(--border);
  background: var(--bg); color: var(--ink); font: inherit; font-size: 13px; font-weight: 600; cursor: pointer;
}
.copilot__handle:hover { color: var(--accent); }
.copilot__handle-icon { display: inline-flex; }
.copilot__handle-icon svg { width: 18px; height: 18px; }
.copilot__handle-icon img { width: 20px; height: 20px; object-fit: contain; display: block; } /* the 🐦‍⬛ brand mark */
.copilot__handle-label { flex: 1; text-align: left; white-space: nowrap; overflow: hidden; }
.copilot__handle-chev { display: inline-flex; color: var(--muted); }
.copilot__handle-chev svg { width: 16px; height: 16px; transition: transform .15s; }
.copilot:not(.is-collapsed) .copilot__handle-chev svg { transform: rotate(-90deg); } /* points right = collapse */
.copilot.is-collapsed .copilot__handle { flex-direction: column; gap: 0; padding: 12px 0; border-bottom: none; }
.copilot.is-collapsed .copilot__handle-label,
.copilot.is-collapsed .copilot__handle-chev { display: none; }

/* justify-end pins the composer to the bottom even if the message list doesn't grow to fill (few
   messages) — no dead band below the composer — and hugs a short thread to the composer, chat-style. */
.copilot__body { flex: 1; min-height: 0; min-width: 340px; display: flex; flex-direction: column; justify-content: flex-end; }
.copilot.is-collapsed .copilot__body { display: none; }
.copilot__keynudge { flex: none; font-size: 13px; color: var(--muted); padding: 10px 14px; border-bottom: 1px solid var(--border); }
.copilot__keynudge a { color: var(--accent); }

.copilot__messages { flex: 1; min-height: 0; overflow-y: auto; padding: 8px 12px; display: flex; flex-direction: column; }
/* The composer reuses .chat-form's inner row/controls but supplies its own frame (chat-form's
   default border/padding is tuned for the full-width chat page). */
.copilot__composer.chat-form { flex: none; border-top: 1px solid var(--border); padding: 10px 12px calc(10px + env(safe-area-inset-bottom)); }
.copilot__composer .chat-form__inner { max-width: none; }
.copilot__composer .chat-cost { max-width: none; margin-top: 8px; padding: 0 2px; }

/* Compact chat inside the panel — smaller avatars/type, tighter rows, inline name + time, and no
   per-row copy actions (too much chrome for a narrow panel). */
.copilot .ce-row { gap: 8px; margin: 8px 0; }
.copilot .ce-avatar { width: 26px; height: 14px; font-size: 21px; } /* bigger glyph, box ~ the name line so it centers on it */
.copilot .ce-meta { font-size: 11px; gap: 6px; }
.copilot .ce-text { font-size: 13px; line-height: 1.45; }
.copilot .ce-row.user .ce-text { padding: 7px 11px; }
.copilot .chat-form textarea { font-size: 14px; min-height: calc(1.4em + 20px); }
.copilot .ce-actions { display: none; }
/* Session boundary — sits below the hydrated (display-only) history; anything below it is the
   fresh session the model actually sees. A centered hairline with a quiet label. */
.copilot__divider {
  flex: none; display: flex; align-items: center; gap: 10px;
  margin: 12px 2px 6px; color: var(--muted); font-size: 11px; user-select: none;
}
.copilot__divider::before, .copilot__divider::after { content: ""; flex: 1; height: 1px; background: var(--border); }

@media (max-width: 879px) {
  /* The panel becomes a bottom drawer: closed = the peek-bar handle above the tab bar; open = a
     full-height sheet (from the content top to just above the tab bar). */
  .copilot {
    --copilot-peek: 46px;                  /* closed drawer height = just the handle bar */
    /* z-index 45 = a CONTENT-overlay layer: above the page/calendar, but BELOW the fixed chrome
       (.mtop + .tabbar at z-50). The account/settings menu drops out of .mtop's own stacking context,
       so the drawer must sit under that layer or it covers the menu. The drawer never overlaps the top
       bar or tab bar anyway (it's anchored between mtop-h and the tab bar), so nothing is lost. */
    position: fixed; left: 0; right: 0; z-index: 45;
    background: var(--surface); /* a raised shade, distinct from the page bg, so the bar reads as a bar */
    bottom: calc(var(--tabbar-h) + env(safe-area-inset-bottom));
    /* Explicit CLOSED top (peek height above the tab bar) so `top` has a concrete value to animate
       FROM — a bare `bottom` with auto height can't transition (top:auto → mtop-h won't tween). The
       base overflow:hidden clips the body to this height, so the drawer slides open to reveal it. */
    top: calc(100dvh - var(--tabbar-h) - env(safe-area-inset-bottom) - var(--copilot-peek));
    width: auto; align-self: auto; border-left: none; border-top: 1px solid var(--border);
    box-shadow: 0 -6px 24px rgba(0, 0, 0, 0.14);
    display: flex; flex-direction: column; /* re-assert: the drawer must be a flex column so the
      body fills top→bottom and the composer pins to the bottom (never inherit-only from desktop). */
  }
  .copilot.is-collapsed { width: auto; } /* neutralize the desktop rail width */
  .copilot__handle { border-bottom: none; background: var(--surface); } /* match the raised drawer shade */
  .copilot__handle-chev { display: inline-flex; }
  .copilot__handle-chev svg { transform: rotate(180deg); } /* points up = tap to open */
  .copilot__body { display: none; min-width: 0; } /* min-width:0 — the desktop full-width pin would clip a narrow drawer */
  .copilot.is-open { top: var(--mtop-h); border-top: none; }
  .copilot.is-open .copilot__handle { border-bottom: 1px solid var(--border); }
  .copilot.is-open .copilot__handle-chev svg { transform: rotate(0); } /* points down = tap to close */
  .copilot.is-open .copilot__body { display: flex; flex: 1; min-height: 0; }
  /* The drawer already clears the tab bar via its own `bottom` above, so the composer must NOT add
     the chat page's tab-bar clearance again: the mobile `.chat-form` rule sets margin-bottom:
     calc(--tabbar-h + safe) (for the bottom-docked #tab-chat composer), which we inherit via the
     shared `chat-form` class — that was the ~64px dead band below the composer. Zero it here, and
     drop the double-counted safe-area padding too. */
  .copilot__composer.chat-form { margin-bottom: 0; padding-bottom: 12px; }
}

/* ── /files Context tab — reuses the glass box (list → reader). Each section renders as markdown
      prose in the shared .md column (glassbox.renderMd), exactly like the dustav.com glass box. `.is-live`
      accents the volatile section (the live calendar, re-read every turn). ── */
.glass-item.is-live .glass-item__icon { color: var(--accent); }

/* ── Image attachments in chat (docs/IMAGE_INPUT.md) ───────────────────────── */
/* Photo button — a secondary round control matching the send button's footprint. */
.chat-photo {
  flex: none; width: 44px; height: 44px; padding: 0; border-radius: 999px;
  display: grid; place-items: center; cursor: pointer;
  border: 1px solid var(--border); background: var(--panel); color: var(--ink);
}
.chat-photo .icon { width: 23px; height: 23px; }
.chat-photo:hover { color: var(--accent); border-color: var(--accent); }
.chat-photo:active { transform: scale(0.96); }
.chat-photo:disabled { opacity: 0.45; cursor: default; }
/* Pending-attachment strip — small thumbnails above the composer row. */
.chat-attachments {
  display: flex; flex-wrap: wrap; gap: 8px;
  max-width: var(--chat-max); margin: 0 auto 8px; padding: 0 6px;
}
.chat-att { position: relative; width: 56px; height: 56px; border-radius: 10px; overflow: hidden; border: 1px solid var(--border); background: var(--panel); }
.chat-att img { width: 100%; height: 100%; object-fit: cover; display: block; }
.chat-att.uploading { opacity: 0.5; }
.chat-att__x {
  position: absolute; top: 2px; right: 2px; width: 18px; height: 18px;
  padding: 0; border: none; border-radius: 999px; cursor: pointer;
  background: rgba(0, 0, 0, 0.6); color: #fff; font-size: 14px; line-height: 1;
  display: grid; place-items: center;
}
/* Quiet, auto-dismissing note above the composer (a non-image file, >4 photos, or an upload
   error) — replaces window.alert so the feedback is in-place and non-blocking. */
.chat-note {
  max-width: var(--chat-max); margin: 0 auto 8px; padding: 8px 12px;
  font-size: 13px; line-height: 1.35; color: var(--ink);
  background: color-mix(in srgb, var(--accent) 9%, var(--surface));
  border: 1px solid var(--accent); border-radius: 10px;
}
/* Drag-over cue — highlight the composer while a file is dragged over the chat tab. */
.chat-form.chat-dragover {
  border-top-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 7%, transparent);
}
/* Shared photos inside a message bubble. Hidden container when empty so text-only rows are
   unaffected. Left-aligned for everyone (user + agent); a modest thumbnail — click opens the full image. */
.ce-media { display: flex; flex-wrap: wrap; gap: 6px; justify-content: flex-start; }
.ce-media:empty { display: none; }
.ce-img { display: block; max-width: 170px; border-radius: 12px; overflow: hidden; border: 1px solid var(--border); }
.ce-img img { display: block; width: 100%; max-height: 220px; object-fit: cover; }
/* An image-only turn has no caption — hide the empty text pill so there's no stray bubble. */
.ce-text:empty { display: none; }
.ce-img { cursor: zoom-in; }

/* Full-screen image lightbox (chat-core.js). Opens a shared photo inspectable in place instead
   of navigating away. Fits the viewport by default; .is-zoomed shows it at natural size and the
   overlay scrolls so you can pan. The page behind is scroll-locked via .ce-lb-open. */
html.ce-lb-open { overflow: hidden; }
.ce-lightbox {
  position: fixed; inset: 0; z-index: 1000;
  display: flex; align-items: center; justify-content: center;
  background: rgba(0, 0, 0, .92); padding: 24px;
  overflow: auto; overscroll-behavior: contain;
}
.ce-lightbox[hidden] { display: none; } /* flex would otherwise override the hidden attribute */
.ce-lightbox__img {
  max-width: 100%; max-height: 100%; object-fit: contain;
  border-radius: 8px; cursor: zoom-in;
}
.ce-lightbox.is-zoomed { align-items: flex-start; justify-content: flex-start; }
.ce-lightbox.is-zoomed .ce-lightbox__img {
  max-width: none; max-height: none; width: auto; height: auto;
  border-radius: 0; cursor: zoom-out;
}
.ce-lightbox__x {
  position: fixed; top: 14px; right: 16px;
  width: 40px; height: 40px; border-radius: 50%; border: none; cursor: pointer;
  background: rgba(255, 255, 255, .14); color: #fff; font-size: 26px; line-height: 1;
  display: grid; place-items: center;
}
.ce-lightbox__x:hover { background: rgba(255, 255, 255, .26); }

@media (max-width: 879px) {
  /* The mobile top bar already shows the active agent (avatar + name), so the
     in-pane agent header is redundant here — drop it to give chat breathing room.
     Scoped to the dashboard pane: the onboarding ceremony's .chat-head carries the
     Copy / Start-over controls and must stay. */
  #tab-chat .chat-head { display: none; }
  #tab-chat { height: 100dvh; padding: var(--mtop-h) 0 0; }
  .messages { padding: 8px 16px; }
  .messages > .ce-row { max-width: 640px; }
  .chat-form { padding: 8px 16px; margin-bottom: calc(var(--tabbar-h) + env(safe-area-inset-bottom)); }
  .chat-form__inner { max-width: 640px; }
  /* Timeline home: the in-pane header is hidden on mobile (rule above), so the agenda + nudge get
     top breathing room under the fixed bar; align their side padding to .messages (16px). */
  .tl-agenda, .tl-empty { padding-left: 16px; padding-right: 16px; }
  .tl-keynudge { margin-left: 16px; margin-right: 16px; }
  .tl-agenda, .tl-keynudge { margin-top: 16px; }
}

/* ── Glass box (Files) — legible, grouped, read-only ──────────────────────── */
.glass-intro { margin: 0 0 16px; font-size: 14px; }
.glass-group { margin-bottom: 24px; }
.glass-group__label {
  font-family: var(--font-body); font-weight: 600; font-size: 12px;
  text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); margin: 0 0 10px;
}

.glass-item {
  display: flex; align-items: center; gap: 12px; width: 100%; text-align: left;
  padding: 12px 14px; margin-bottom: 8px;
  background: var(--surface); border: 1px solid var(--border); border-radius: 14px;
  color: var(--ink); font-family: inherit; cursor: pointer;
  transition: border-color 0.12s, transform 0.04s;
}
.glass-item:hover { border-color: var(--accent); }
.glass-item:active { transform: scale(0.995); }
.glass-item.is-active { border-color: var(--accent); }
.glass-item__icon {
  display: grid; place-items: center; flex: none; width: 38px; height: 38px;
  border-radius: 10px; background: var(--bg); color: var(--accent); font-size: 16px;
}
.glass-item__text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.glass-item__title { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; font-weight: 600; font-size: 15px; }
.glass-item__file { background: none; padding: 0; font-size: 11px; font-weight: 400; color: var(--muted); }
.glass-item__blurb { font-size: 13px; color: var(--muted); }
.glass-item__chev { margin-left: auto; flex: none; font-size: 12px; color: var(--muted); }

.glass-timeline {
  margin-top: 4px; padding: 8px 14px 6px;
  background: var(--surface); border: 1px solid var(--border); border-radius: 14px;
}
.glass-timeline__head { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--muted); padding: 6px 0; }
.glass-timeline__head .icon { color: var(--accent); }
.glass-timeline__empty { font-size: 13px; padding: 4px 0 8px; }
.glass-day {
  display: flex; align-items: baseline; gap: 10px; width: 100%; text-align: left;
  padding: 10px 6px; border: none; border-bottom: 1px solid var(--border);
  background: none; color: var(--ink); font-family: inherit; cursor: pointer; border-radius: 8px;
}
.glass-day:last-child { border-bottom: none; }
.glass-day:hover { background: var(--bg); }
.glass-day.is-active { color: var(--accent); }
.glass-day__label { font-weight: 600; font-size: 14px; }
.glass-day__date { margin-left: auto; font-size: 12px; }

/* Reader — BASE = mobile: a full-screen slide-in overlay ("like turning a page").
   files.js toggles .is-open on click / Back. The desktop master-detail override
   follows below (source order: base first, so the media query wins ≥880px). */
.glass-reader {
  position: fixed; inset: 0; z-index: 60; overflow: auto;
  background: var(--bg);
  transform: translateX(100%); transition: transform 0.22s ease;
}
.glass-reader.is-open { transform: translateX(0); }
.glass-reader__inner {
  max-width: 640px; margin: 0 auto;
  padding: calc(var(--mtop-h) + 12px) 16px calc(var(--tabbar-h) + env(safe-area-inset-bottom) + 16px);
}
.glass-reader__back {
  display: inline-flex; align-items: center; gap: 6px; margin-bottom: 14px;
  background: var(--surface); border: 1px solid var(--border); border-radius: 999px;
  padding: 8px 14px; color: var(--ink); font-family: inherit; font-size: 15px; cursor: pointer;
}
.glass-reader__back:hover { border-color: var(--accent); }
.glass-reader__head { border-bottom: 1px solid var(--border); padding-bottom: 10px; margin-bottom: 14px; }
.glass-reader__title { margin: 0 0 2px; font-size: 20px; }
.glass-reader__path { background: none; padding: 0; font-size: 12px; color: var(--muted); }
.glass-reader__empty { padding: 8px 0; }

/* Desktop (≥880px): Files fills the whole pane like Chat. A fixed file-nav column
   sits flush against the rail (its own scroll — an "expanded menu" off the sidebar);
   the reader fills the rest and behaves like the chat thread — a full-height scroller
   with the bar at the pane edge and the TEXT centered to reading width. The mobile
   slide-in overlay above is untouched (it's the base style; this media query wins). */
@media (min-width: 880px) {
  #tab-context {
    max-width: none; margin: 0; padding: 0;   /* fill the pane, like #tab-chat */
    height: 100dvh;
    display: grid; grid-template-columns: 480px minmax(0, 1fr);
  }
  /* The file nav — an expanded menu against the rail, with its own scroll. */
  .glass-list {
    height: 100dvh; overflow-y: auto;
    padding: 28px 20px 56px;
    border-right: 1px solid var(--border);
  }
  /* The reader — a chat-style full-height scroller. Neutralize the mobile slide-in
     (fixed/transform), let the text center itself like .messages rows do. */
  .glass-reader {
    position: static; inset: auto; z-index: auto; transform: none;
    height: 100dvh; max-height: none; overflow-y: auto;
    background: var(--bg); border: none; border-radius: 0;
  }
  .glass-reader__inner { max-width: none; margin: 0; padding: 0; }   /* full-bleed; head + body self-center */
  /* Match the chat header (.chat-head + .agent-strip): a full-width, bottom-bordered
     bar pinned to the top, its content LEFT-aligned in the same centered reading
     column — title + filename inline, exactly like a menu row / the agent name. */
  .glass-reader__head {
    position: sticky; top: 0; z-index: 1; background: var(--bg);
    border-bottom: 1px solid var(--border);
    padding: 14px 0; margin: 0; display: flex;   /* border full-width; sides padded on the inner */
  }
  .glass-reader__headinner {
    max-width: var(--content-max); width: 100%; margin: 0 auto;
    padding: 0 24px;   /* same 24px side inset as the doc body → title aligns with the text */
    display: flex; align-items: baseline; gap: 10px;
  }
  .glass-reader__title { margin: 0; font-size: 18px; font-weight: 700; }
  .glass-reader__path { font-size: 12px; font-weight: 400; color: var(--muted); background: none; padding: 0; }
  /* The doc body + empty/loading states share the centered reading column. */
  .glass-reader__body .md { max-width: var(--content-max); margin: 0 auto; padding: 28px 24px 56px; }
  .glass-reader__empty { max-width: var(--content-max); margin: 0 auto; padding: 28px 24px; }
  .glass-reader__back { display: none; }
}

/* Reader loading spinner — sits in the body while the doc fetches, so the header
   (the file name) renders instantly and never flickers. Centered in either layout. */
.glass-spinner {
  width: 22px; height: 22px; margin: 56px auto;
  border: 2px solid var(--border); border-top-color: var(--accent);
  border-radius: 50%; animation: glass-spin 0.7s linear infinite;
}
@keyframes glass-spin { to { transform: rotate(360deg); } }

/* Reader take-it-with-you action — "Download .md" in the reader header. Quiet pill with the
   download glyph; below the title on mobile, pushed to the right of the head row on desktop. */
.glass-reader__actions { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 8px; }
.reader-action {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--surface); border: 1px solid var(--border); border-radius: 999px;
  padding: 5px 12px; color: var(--ink); font-family: inherit; font-size: 15px; font-weight: 600;
  text-decoration: none; cursor: pointer; white-space: nowrap;
}
.reader-action:hover { border-color: var(--accent); color: var(--accent); }
.reader-action .icon { width: 15px; height: 15px; }
@media (min-width: 880px) {
  .glass-reader__actions { margin-top: 0; margin-left: auto; align-self: center; }
}

/* Rendered markdown body (shared by the reader). */
.md { line-height: 1.6; }
.md h1, .md h2, .md h3 { margin: 0.8em 0 0.3em; }
.md code { background: var(--bg); padding: 1px 5px; border-radius: 4px; }
/* Code blocks (e.g. a tool's JSON schema in the Context tab): a distinct accent-tinted panel with a
   left rule, and WORD-WRAPPED — pre-wrap keeps the JSON indentation but lets long descriptions wrap
   instead of scrolling off the right edge. */
.md pre {
  background: color-mix(in srgb, var(--accent) 6%, var(--surface));
  border: 1px solid var(--border); border-left: 3px solid var(--accent);
  border-radius: 8px; padding: 12px 14px; margin: 10px 0;
  font-size: 12px; line-height: 1.55; tab-size: 2;
  white-space: pre-wrap; overflow-wrap: break-word;
}
.md pre code {
  background: none; padding: 0; color: var(--ink);
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
}
.md ul { padding-left: 20px; }

/* ── Skills (marketplace placeholder) ──────────────────────────────────────── */
.skills-head { margin-bottom: 22px; }
.skills-title { margin: 0 0 6px; }
.skills-soon {
  text-align: center; padding: 48px 28px;
  background: var(--surface); border: 1px solid var(--border); border-radius: 18px;
}
.skills-soon__icon {
  display: inline-grid; place-items: center; width: 64px; height: 64px; margin-bottom: 14px;
  border-radius: 16px; background: var(--bg); color: var(--accent); font-size: 28px;
}
.skills-soon__title { margin: 0 0 6px; }

/* Storefront grid */
.skill-grid { display: grid; gap: 16px; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); }
.skill-card { background: var(--surface); border: 1px solid var(--border); border-radius: 16px; padding: 20px; display: flex; flex-direction: column; gap: 12px; }
.skill-card__top { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.skill-card__name { margin: 0; font-size: 18px; display: flex; align-items: center; gap: 10px; }
.skill-card__icon { display: grid; place-items: center; flex: none; width: 38px; height: 38px; border-radius: 11px; background: var(--bg); color: var(--accent); font-size: 17px; }
.skill-card__price { font-size: 13px; font-weight: 600; color: var(--accent); flex: none; }
.skill-card__blurb { margin: 0; font-size: 14px; line-height: 1.5; }
.skill-card__action { margin-top: auto; display: flex; flex-direction: column; gap: 6px; }
.skill-installed { display: inline-flex; align-items: center; gap: 10px; color: var(--accent); font-weight: 600; font-size: 14px; }
.skill-installed .btn { font-weight: 400; }

/* Skill tag (Free / Plus) — replaces the old per-skill price chip. */
.skill-card__tag { font-size: 12px; font-weight: 600; color: var(--muted); flex: none; border: 1px solid var(--border); border-radius: 999px; padding: 2px 10px; }
.skill-card__tag--plus { color: var(--accent); border-color: var(--accent); }
.skill-card--locked { opacity: 0.92; }
.skill-card--locked .skill-card__icon { color: var(--muted); }
.skill-unlock { display: inline-flex; align-items: center; gap: 8px; }
.skill-unlock .icon { width: 15px; height: 15px; }

/* Marketplace "unlock with Plus" banner (storefront, when locked). */
.skills-unlock {
  display: flex; align-items: center; gap: 16px; margin-bottom: 20px;
  background: var(--surface); border: 1px solid var(--accent); border-radius: 14px; padding: 16px 18px;
}
.skills-unlock__icon { display: grid; place-items: center; flex: none; width: 42px; height: 42px; border-radius: 11px; background: var(--bg); color: var(--accent); }
.skills-unlock__icon .icon { width: 21px; height: 21px; }
.skills-unlock__copy { display: flex; flex-direction: column; gap: 2px; }
.skills-unlock .btn { margin-left: auto; flex: none; }

/* Billing card (Settings → dustav.com Plus). */
.plan-badge--plus { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }
.billing-plans { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 4px; }
.billing-banner { display: flex; align-items: center; gap: 8px; border-radius: 10px; padding: 10px 14px; font-size: 14px; margin: 0 0 12px; }
.billing-banner .icon { width: 17px; height: 17px; flex: none; }
.billing-banner--ok { background: color-mix(in srgb, var(--accent) 10%, transparent); color: var(--ink); border: 1px solid var(--accent); }
.billing-banner--cancel { background: var(--bg); color: var(--muted); border: 1px solid var(--border); }

/* Calendar — co-owned month grid + agenda. Events + days are clickable; edits go
   through a modal (cal-modal). The agent writes the same events via chat. */
.cal-empty { text-align: center; padding: 48px 28px; background: var(--surface); border: 1px solid var(--border); border-radius: 18px; display: flex; flex-direction: column; align-items: center; gap: 10px; }
.cal-empty__icon { display: inline-grid; place-items: center; width: 64px; height: 64px; border-radius: 16px; background: var(--bg); color: var(--accent); font-size: 28px; }
.cal-empty h1 { margin: 6px 0 0; }
.cal-empty p { max-width: 420px; }
/* Header = TWO rows, each a left item + a right cluster (space-between):
   Row 1 — back + date · prev/next arrows.   Row 2 — Categories · search + Clear + add.
   No Day/Month/Year switcher and no list toggle — the calendar IS the navigation (drill + back). */
.cal-head { display: flex; flex-direction: column; align-items: stretch; gap: 12px; margin-bottom: 16px; }
.cal-headrow { display: flex; align-items: center; justify-content: space-between; gap: 14px; flex-wrap: wrap; }
.cal-title { margin: 0; font-size: 22px; }
.cal-titlewrap { display: flex; align-items: center; gap: 8px; min-width: 0; }
/* Back / zoom-out (Day → Month → Year). Hidden at the top level; calendar.js sets its label. */
.cal-back { display: inline-flex; align-items: center; gap: 1px; font-family: inherit; font-size: 14px; font-weight: 600; color: var(--accent); background: none; border: none; cursor: pointer; padding: 4px 8px 4px 2px; border-radius: 8px; flex: none; }
.cal-back:hover { background: color-mix(in srgb, var(--accent) 12%, transparent); }
.cal-back .icon { width: 16px; height: 16px; }
.cal-tools { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; justify-content: flex-end; }  /* arrows · search · grid/list · + */
/* Every header control shares the same slim, pill-round "grain". */
.cal-head .btn { padding: 8px 15px; border-radius: 999px; font-size: 14px; }
#cal-new { padding: 8px 12px; }                                    /* New event = icon-only "+", squared, stays primary/purple */
/* Nav = a pill GROUP like the switcher: one surface container, borderless segments. */
.cal-nav { display: inline-flex; align-items: center; gap: 2px; background: var(--surface); border: 1px solid var(--border); border-radius: 999px; padding: 2px; }
.cal-nav .btn { border: none; background: none; padding: 6px 14px; }
.cal-nav .btn:hover { background: var(--panel); }
/* Month = iCal's shape: a DOT grid (a coloured dot per event, NOT titles) + the selected day's
   events listed in a panel below. cal-monthwrap stacks the two; the grid is no longer full-height. */
.cal-monthwrap { display: flex; flex-direction: column; gap: 18px; }
.cal-grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 1px; background: var(--border); border: 1px solid var(--border); border-radius: 12px; overflow: hidden; }
.cal-dow { background: var(--surface); text-align: center; font-size: 12px; color: var(--muted); padding: 8px 0; font-weight: 600; }
.cal-day { background: var(--panel); min-height: 70px; min-width: 0; padding: 7px 4px 6px; display: flex; flex-direction: column; align-items: center; gap: 5px; cursor: pointer; transition: background 0.1s; }
.cal-day:hover { background: var(--bg); }
.cal-day--out { background: var(--surface); }
.cal-day--out .cal-day__num { color: var(--muted); opacity: 0.55; }
.cal-day--today .cal-day__num { background: var(--accent); color: #fff; }
/* The day the panel below is showing — a ring so it reads as "selected", distinct from today. */
.cal-day--selected { background: color-mix(in srgb, var(--accent) 9%, var(--panel)); box-shadow: inset 0 0 0 2px var(--accent); }
.cal-day--selected:hover { background: color-mix(in srgb, var(--accent) 13%, var(--panel)); }
.cal-day__num { font-size: 13px; color: var(--ink); width: 24px; height: 24px; display: inline-grid; place-items: center; border-radius: 50%; }
.cal-day__dots { display: flex; flex-wrap: wrap; justify-content: center; gap: 3px; min-height: 6px; }
.cal-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--cat, var(--accent)); }
.cal-dot.is-hidden { display: none; }

/* The selected day's events, listed under the Month grid (iCal's month layout). */
.cal-daypanel { display: flex; flex-direction: column; gap: 8px; }
/* The date header is the drill INTO the Day view — it's navigation, so it's the SAME element as the
   .cal-back zoom-out chevron: accent text + a plain chevron, no pill. Just mirrored (chevron trails
   the label, pointing forward, vs .cal-back's leading back-chevron). */
.cal-daypanel__date {
  align-self: flex-start; display: inline-flex; align-items: center; gap: 2px;
  font-family: inherit; font-size: 14px; font-weight: 600; color: var(--accent); cursor: pointer;
  background: none; border: none; padding: 4px 6px 4px 2px; border-radius: 8px;
}
.cal-daypanel__date:hover { background: color-mix(in srgb, var(--accent) 12%, transparent); }
.cal-daypanel__date .icon { width: 16px; height: 16px; }
.cal-daypanel__none { margin: 2px 0 6px; font-size: 14px; opacity: 0.75; }

/* The Month "no day selected" agenda (after Clear): a small label + the whole month's events. */
.cal-monthagenda { display: flex; flex-direction: column; gap: 8px; }
.cal-monthagenda__head { margin: 0 0 2px; font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em; }

/* ── Calendar category palette + filter bar ──────────────────────────────────── */
/* Named hues (services/eventCategories.PALETTE). Each sets --cat; chips/agenda/filters read it. */
.cat--coral  { --cat: #ff6a3d; }
.cat--amber  { --cat: #f59e0b; }
.cat--rose   { --cat: #f43f6b; }
.cat--violet { --cat: #8b5cf6; }
.cat--teal   { --cat: #14b8a6; }
.cat--blue   { --cat: #3b82f6; }
.cat--green  { --cat: #22c55e; }
.cat--slate  { --cat: #94a3b8; }

/* ── Categories — a multi-select dropdown (replaces the always-on chip bar) ─────── */
.cal-catwrap { position: relative; display: inline-block; }   /* hugs the button so the popover aligns under it */
.cal-catbtn { display: inline-flex; align-items: center; gap: 8px; font-family: inherit; font-size: 14px; font-weight: 600; color: var(--ink); cursor: pointer; background: var(--surface); border: 1px solid var(--border); border-radius: 999px; padding: 8px 14px; }
.cal-catbtn:hover { border-color: var(--accent); }
.cal-catbtn .icon { width: 15px; height: 15px; color: var(--muted); }
.cal-catbtn.is-active { border-color: var(--accent); color: var(--accent); }   /* a filter is on */
.cal-catbtn__count { display: inline-grid; place-items: center; min-width: 20px; height: 20px; padding: 0 6px; border-radius: 999px; background: var(--accent); color: #fff; font-size: 12px; font-weight: 700; }

/* The popover panel under the button. */
.cal-catmenu { position: absolute; z-index: 40; top: calc(100% + 8px); left: 0; width: min(320px, calc(100vw - 32px)); background: var(--surface); border: 1px solid var(--border); border-radius: 14px; box-shadow: 0 16px 40px rgba(0,0,0,0.32); padding: 8px; }
.cal-catmenu[hidden] { display: none; }
.cal-catmenu__head { display: flex; align-items: center; justify-content: space-between; padding: 6px 8px 8px; border-bottom: 1px solid var(--border); margin-bottom: 6px; }
.cal-catmenu__title { font-size: 12px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.04em; }
.cal-catmenu__x { display: inline-grid; place-items: center; background: none; border: none; cursor: pointer; color: var(--muted); padding: 2px; border-radius: 6px; margin: -2px -2px -2px 0; }
.cal-catmenu__x:hover { color: var(--ink); }
.cal-catmenu__x .icon { width: 16px; height: 16px; }
.cal-catmenu__clear { font-family: inherit; font-size: 13px; font-weight: 600; color: var(--accent); background: none; border: none; cursor: pointer; padding: 2px 4px; border-radius: 6px; }
.cal-catmenu__clear:hover { background: color-mix(in srgb, var(--accent) 12%, transparent); }
.cal-catmenu__clear:disabled { color: var(--muted); cursor: default; background: none; }   /* nothing selected → nothing to clear */
.cal-catmenu__list { display: flex; flex-direction: column; gap: 2px; max-height: min(420px, 56vh); overflow-y: auto; }  /* this scroll is INSIDE the popover, not the page body */
.cal-catopt { display: flex; align-items: center; gap: 11px; width: 100%; text-align: left; font-family: inherit; font-size: 15px; color: var(--ink); cursor: pointer; background: none; border: none; border-radius: 9px; padding: 11px 10px; }
.cal-catopt:hover { background: var(--bg); }
.cal-catopt__dot { width: 11px; height: 11px; border-radius: 50%; background: var(--cat, var(--accent)); flex: none; }
.cal-catopt__name { flex: 1; min-width: 0; }
.cal-catopt__check { display: none; color: var(--accent); flex: none; }
.cal-catopt__check .icon { width: 18px; height: 18px; }
.cal-catopt.is-on { background: color-mix(in srgb, var(--accent) 8%, transparent); }
.cal-catopt.is-on .cal-catopt__check { display: inline-flex; }
/* Today + search sit together at the right of header row 2 (Today used to float over the composer). */
.cal-headright { display: flex; align-items: center; gap: 8px; }
.cal-todaybtn.btn { background: var(--surface); font-weight: 600; padding: 8px 16px; }
.cal-todaybtn.btn:hover { border-color: var(--accent); color: var(--accent); }

/* Categories area (row 2): the dropdown with "Clear" hanging right beside it. */
.cal-catarea { display: flex; align-items: center; gap: 4px; }
/* Clear — a small, borderless text link (not a pill), beside the categories filter. Resets the
   category filter AND (in Month) deselects the day → the panel falls back to the whole month. */
.cal-clearlink { font-family: inherit; font-size: 13px; color: var(--muted); background: none; border: none; cursor: pointer; padding: 6px 8px; border-radius: 7px; }
.cal-clearlink:hover { color: var(--accent); }

/* ── The chronological list (Month's "no day selected" agenda) ─────────────────── */
.cal-list { display: flex; flex-direction: column; gap: 1px; background: var(--border); border: 1px solid var(--border); border-radius: 12px; overflow: hidden; }
.cal-list__row { display: flex; gap: 16px; align-items: baseline; width: 100%; text-align: left; font-family: inherit; background: var(--panel); border: none; cursor: pointer; padding: 11px 14px; color: var(--ink); }
.cal-list__row:hover { background: var(--bg); }
.cal-list__row.is-hidden { display: none; }
.cal-list__when { flex: none; width: 210px; font-size: 13px; color: var(--muted); white-space: nowrap; } /* wide enough for a date/time RANGE */
.cal-list__row[class*="cat--"] .cal-list__when::before { content: ""; display: inline-block; width: 8px; height: 8px; border-radius: 50%; background: var(--cat); margin-right: 8px; vertical-align: middle; }
.cal-list__title { font-size: 14px; min-width: 0; line-height: 1.4; }
.cal-list__empty { background: var(--panel); margin: 0; padding: 16px 14px; font-size: 14px; }

/* ── Full-height layout: header + filters pinned; the grid fills + scrolls inside ──
   "Full screen where we can" (docs/CALENDAR.md). The calendar grid is FULL-WIDTH; there's no
   side panel — search + a day's detail live in modals. */
/* Desktop: the calendar column and the copilot panel sit side by side (row); .cal-main is the
   column (header + scrolling grid), the panel is a fixed-width flex child to its right. */
/* Fill the pane (override the base .tabpane max-width:760 + margin:auto — else the calendar
   gets squeezed to the reading column and floats centered with big side gaps). */
#tab-calendar.calendar { max-width: none; margin: 0; height: 100dvh; padding: 0; display: flex; flex-direction: row; }
.cal-main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }

/* Drafts — the FILES master-detail (a persistent list column | the reader), plus the reused copilot
   rail. The list stays visible, so you navigate by clicking a draft — never the browser Back button
   (which would leave the section: that's the bug this replaced). The global .glass-list / .glass-reader
   rules do the column work — on desktop each is its OWN scrolling column (siblings, not nested, so no
   double scrollbar; the reader's sticky head + the list's rail border come for free). On mobile the
   list is full-width and the reader is the fixed slide-in overlay (drafts.js toggles .is-open), with
   its Back button — the global rules already handle both, so we only supply the desktop grid. */
#tab-drafts.drafts { max-width: none; margin: 0; height: 100dvh; padding: 0; display: flex; flex-direction: row; }
.drafts-main { flex: 1 1 auto; min-width: 0; }
@media (min-width: 880px) {
  .drafts-main { display: grid; grid-template-columns: 300px minmax(0, 1fr); height: 100dvh; min-height: 0; }
}
@media (max-width: 879px) {
  #tab-drafts.drafts { flex-direction: column; padding: var(--mtop-h) 0 0; }  /* clear the fixed top bar (the reader overlay clears it itself) */
  /* The list has no padding on mobile (the ≥880 rule that pads it doesn't apply), so cards sit flush
     to the edge. Pad it in, and clear the bottom for the fixed tab bar + the copilot peek bar. */
  #tab-drafts .drafts-browser { padding: 8px 16px calc(var(--tabbar-h) + 62px + env(safe-area-inset-bottom)); }
}
@keyframes draftFlash { from { background: var(--accent-weak, rgba(255,106,61,0.14)); } to { background: transparent; } }
.draft-flash { animation: draftFlash 0.9s ease-out; border-radius: 8px; }
@keyframes draftFlash { from { background: var(--accent-weak, rgba(255,106,61,0.14)); } to { background: transparent; } }
.draft-flash { animation: draftFlash 0.9s ease-out; border-radius: 8px; }
.cal-head { padding: 24px 24px 0; margin: 0 0 14px; }
.cal-body { position: relative; flex: 1; min-height: 0; overflow-y: auto; padding: 0 24px 80px; } /* relative: the Day grid scrolls itself into view via offsetTop; big bottom pad clears the floating Today FAB */
.cal-view { min-width: 0; }
/* Search = a matching single pill on the same surface as the nav group + switcher. */
.cal-iconbtn.btn { background: var(--surface); padding: 8px 12px; }
.cal-iconbtn.btn:hover { background: var(--panel); }

/* ── Schedule card (week/day columns) ─────────────────────────────────────────── */
.cal-card { display: flex; gap: 12px; align-items: baseline; width: 100%; text-align: left; font-family: inherit; background: none; border: none; cursor: pointer; padding: 6px 8px; border-radius: 8px; color: var(--ink); }
/* A distinct accent-tinted hover so a card stands out on ANY row background — including the
   tinted today-row (the plain page-bg hover used to vanish into the row's own hover). */
.cal-card:hover { background: color-mix(in srgb, var(--accent) 16%, transparent); }
.cal-card.is-hidden { display: none; }
.cal-card__when { flex: none; width: 62px; font-size: 13px; color: var(--muted); }
.cal-card[class*="cat--"] .cal-card__when::before { content: ""; display: inline-block; width: 8px; height: 8px; border-radius: 50%; background: var(--cat); margin-right: 7px; vertical-align: middle; }
.cal-card__title { font-size: 14px; min-width: 0; line-height: 1.4; }
/* Inside a cal-list (the selected-day panel), a card takes the SAME chrome as a Month-agenda row:
   a solid panel row, separated by the container's 1px --border gaps, with the roomier list padding —
   so the "day selected" list and the "all of month" list look identical. (The all-day strip's cards
   aren't in a cal-list, so they keep the compact schedule-card look.) */
.cal-list .cal-card { background: var(--panel); border-radius: 0; padding: 11px 14px; gap: 16px; }
.cal-list .cal-card:hover { background: var(--bg); }

/* ── Day: a REAL hour-grid timeline (iCal's day view) ──────────────────────────
   A 24-hour ruler; each event is an absolutely-positioned block whose HEIGHT = its
   duration, overlapping events split into side-by-side lanes, a red "now" line. The
   block top/height (px = time/duration) + left/width (% = lane) are set inline by
   calendar.js; this just styles the ruler + the blocks. */
.cal-daygrid { display: flex; flex-direction: column; padding: 12px 0 28px; } /* breathing room at the top (clears the filter bar) + bottom of the scroll */
.cal-daygrid__allday { display: flex; flex-direction: column; gap: 2px; padding: 2px 0 10px; border-bottom: 1px solid var(--border); margin-bottom: 6px; } /* all-day events pinned on top, off the ruler */
.cal-hours { position: relative; padding-left: 58px; } /* relative box: blocks position against it; gutter holds hour labels */
.cal-hourrow { position: relative; border-top: 1px solid var(--border); }
.cal-hourrow:first-child { border-top: none; }
/* The hour label lives in the GUTTER, LEFT of where the line starts (the row's content begins at
   x=58 due to the parent's padding, so left:-58 places the label at x=0; the 8px short of the gutter
   keeps it clear of the line). top:-7 vertically straddles the line. */
.cal-hourrow__label { position: absolute; left: -58px; top: -7px; width: 50px; text-align: right; font-size: 11px; color: var(--muted); }
.cal-blocks { position: absolute; top: 0; left: 58px; right: 6px; bottom: 0; } /* the event layer, inset past the gutter (matches cal-hours padding) */
.cal-block { position: absolute; overflow: hidden; display: flex; flex-direction: column; gap: 1px; text-align: left; font-family: inherit; cursor: pointer; border: none; border-left: 3px solid var(--cat, var(--accent)); border-radius: 5px; padding: 2px 6px; background: color-mix(in srgb, var(--cat, var(--accent)) 18%, var(--panel)); color: var(--ink); }
.cal-block:hover { background: color-mix(in srgb, var(--cat, var(--accent)) 30%, var(--panel)); }
.cal-block.is-hidden { display: none; }
.cal-block__time { font-size: 10px; color: var(--muted); white-space: nowrap; }
.cal-block__title { font-size: 12px; font-weight: 600; line-height: 1.2; }
.cal-now { position: absolute; left: 0; right: 0; height: 0; border-top: 2px solid var(--error); z-index: 2; }
.cal-now::before { content: ""; position: absolute; left: -4px; top: -4px; width: 7px; height: 7px; border-radius: 50%; background: var(--error); }

/* ── Year navigator: 12 mini-months, a dot on any day that has an event ────────── */
.cal-year { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 16px; }
/* The WHOLE month is one clickable card → drills into Month (never a day). Days are inert. */
.cal-yr { display: block; width: 100%; text-align: left; font-family: inherit; cursor: pointer; background: var(--panel); border: 1px solid var(--border); border-radius: 12px; padding: 10px 12px; color: var(--ink); transition: border-color 0.12s, background 0.12s; }
.cal-yr:hover { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 6%, var(--panel)); }
.cal-yr__name { display: block; font-weight: 600; font-size: 14px; color: var(--ink); padding: 0 0 6px; }
.cal-yr:hover .cal-yr__name { color: var(--accent); }
.cal-yr__grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 1px; }
.cal-yr__dow { text-align: center; font-size: 9px; color: var(--muted); padding: 2px 0; }
.cal-yr__day { font-size: 11px; color: var(--ink); aspect-ratio: 1; display: grid; place-items: center; border-radius: 50%; position: relative; }
.cal-yr__day--out { visibility: hidden; }
.cal-yr__day--today { background: var(--accent); color: #fff; }
.cal-yr__day--has::after { content: ""; position: absolute; bottom: 1px; left: 50%; transform: translateX(-50%); width: 4px; height: 4px; border-radius: 50%; background: var(--cat, var(--accent)); }
.cal-yr__day--today.cal-yr__day--has::after { background: #fff; }

.cal-searchmodal::backdrop { background: rgba(0,0,0,0.45); }

/* ── Search modal (the search button / "/") — a FIXED-height palette (cmd-K style) so it doesn't
   grow/shrink as you type; the results scroll inside a constant box. ───────────────────────────── */
.cal-searchmodal { width: min(560px, calc(100vw - 32px)); height: min(520px, calc(100dvh - 80px)); border: 1px solid var(--border); border-radius: 16px; padding: 0; background: var(--surface); color: var(--ink); box-shadow: 0 18px 50px rgba(0,0,0,0.28); }
.cal-searchmodal__inner { height: 100%; box-sizing: border-box; padding: 14px 16px 16px; display: flex; flex-direction: column; gap: 10px; }
.cal-searchmodal__bar { display: flex; align-items: center; gap: 10px; flex: none; }
.cal-searchmodal__icon { display: inline-flex; color: var(--muted); flex: none; }
.cal-searchmodal__icon svg { width: 18px; height: 18px; }
.cal-searchmodal__bar input { flex: 1; min-width: 0; font-family: inherit; font-size: 16px; color: var(--ink); background: var(--bg); border: 1px solid var(--border); border-radius: 9px; padding: 9px 11px; }
.cal-searchmodal__bar input:focus { outline: none; border-color: var(--accent); }
.cal-searchmodal__empty { padding: 6px 4px; font-size: 13px; flex: none; }
.cal-searchmodal__list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; flex: 1; min-height: 0; overflow-y: auto; }
.cal-searchmodal__btn { display: flex; flex-direction: column; gap: 1px; width: 100%; text-align: left; font-family: inherit; background: none; border: none; border-bottom: 1px solid var(--border); cursor: pointer; padding: 9px 4px; color: var(--ink); border-radius: 6px; }
.cal-searchmodal__btn:hover { background: var(--bg); }
.cal-searchmodal__when { font-size: 12px; color: var(--muted); }
.cal-searchmodal__btn[class*="cat--"] .cal-searchmodal__when::before { content: ""; display: inline-block; width: 8px; height: 8px; border-radius: 50%; background: var(--cat); margin-right: 7px; vertical-align: middle; }
.cal-searchmodal__title { font-size: 14px; }

/* Edit/create modal (native <dialog>). */
.cal-modal { width: min(480px, calc(100vw - 32px)); border: 1px solid var(--border); border-radius: 16px; padding: 0; background: var(--surface); color: var(--ink); box-shadow: 0 18px 50px rgba(0,0,0,0.28); }
.cal-modal::backdrop { background: rgba(0,0,0,0.45); }
.cal-modal form { padding: 18px 20px 20px; display: flex; flex-direction: column; gap: 12px; }
.cal-modal__head { display: flex; align-items: center; justify-content: space-between; }
.cal-modal__title { margin: 0; font-size: 18px; }
.cal-modal__x { background: none; border: none; cursor: pointer; color: var(--muted); font-size: 18px; padding: 4px; line-height: 1; }
.cal-modal__x:hover { color: var(--ink); }
.cal-modal__err { margin: 0; color: var(--error); font-size: 13px; }
.cal-field { display: flex; flex-direction: column; gap: 4px; font-size: 13px; }
.cal-field > span { color: var(--muted); }
.cal-field input, .cal-field select, .cal-field textarea {
  font-family: inherit; font-size: 14px; color: var(--ink); background: var(--bg);
  border: 1px solid var(--border); border-radius: 9px; padding: 8px 10px; width: 100%;
}
.cal-field textarea { resize: vertical; }
.cal-field input:focus, .cal-field select:focus, .cal-field textarea:focus { outline: none; border-color: var(--accent); }
.cal-field-row { display: flex; gap: 12px; flex-wrap: wrap; }
.cal-field-row > .cal-field { flex: 1; min-width: 120px; }
.cal-times { display: flex; gap: 12px; flex: 2; min-width: 180px; }
.cal-times > .cal-field { flex: 1; }
.cal-check { display: flex; align-items: center; gap: 8px; font-size: 14px; cursor: pointer; }
.cal-check input { width: auto; }
.cal-modal__actions { display: flex; align-items: center; gap: 10px; margin-top: 4px; }
.cal-modal__spacer { flex: 1; }
.btn-danger-ghost { background: transparent; border: 1px solid transparent; color: var(--error); cursor: pointer; font-family: inherit; padding: 8px 12px; border-radius: 9px; }
.btn-danger-ghost:hover { border-color: var(--error); }

/* ── Calendar mobile (<880px): single-row header, dot grid + panel, floating Today above the tabbar ── */
@media (max-width: 879px) {
  /* Mobile: back to a plain column — the copilot is a fixed bottom drawer (overlay), not a flex
     child, so the calendar column owns the full width. */
  #tab-calendar.calendar { height: 100dvh; max-width: none; padding: var(--mtop-h) 0 0; flex-direction: column; }
  .cal-head { padding: 14px 16px 0; gap: 10px; } /* (column + stretch inherited from the base rule) */
  .cal-title { font-size: 18px; } /* a touch smaller so the date + tools share the top row without wrapping */
  .cal-body { padding: 0 16px calc(var(--tabbar-h) + env(safe-area-inset-bottom) + 64px); } /* extra: clear the floating Today FAB above the tab bar */
  /* Stack the row on phones so a long date/time range isn't cramped beside the title. */
  .cal-list__row { flex-direction: column; gap: 3px; }
  .cal-list__when { width: auto; }
  /* Day hour-grid: tighten the label gutter on narrow screens (label stays left of the line). */
  .cal-hours { padding-left: 48px; }
  .cal-blocks { left: 48px; }
  .cal-hourrow__label { left: -48px; width: 40px; }
  /* Year: 3 mini-months per row on mobile (iCal's default), shrunk to fit. */
  .cal-year { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
  .cal-yr { padding: 8px 7px; }
  .cal-yr__name { font-size: 12px; padding-bottom: 4px; }
  .cal-yr__dow { font-size: 7px; padding: 1px 0; }
  .cal-yr__day { font-size: 9px; }
  .cal-yr__day--has::after { width: 3px; height: 3px; bottom: 0; }
}

@media (max-width: 620px) {
  .cal-day { min-height: 56px; }
  /* Year stays 3-up even on the smallest screens (the <880px rule's repeat(3,...) carries through). */

  /* Full-screen edit modal on phones — a centered 480px card is cramped to fill in on a
     small screen. Fill the viewport, pin the header, let the fields scroll under it. */
  .cal-modal { width: 100vw; max-width: none; height: 100dvh; max-height: none; margin: 0; border: none; border-radius: 0; }
  .cal-modal form { height: 100%; box-sizing: border-box; overflow-y: auto; gap: 14px; padding: 16px 18px calc(18px + env(safe-area-inset-bottom)); }
  .cal-modal__head { position: sticky; top: 0; z-index: 1; margin: -16px -18px 2px; padding: 14px 18px; background: var(--surface); border-bottom: 1px solid var(--border); }
  .cal-modal__title { font-size: 20px; }
  /* Comfortable tap targets for the on-screen-keyboard fields. */
  .cal-field input, .cal-field select, .cal-field textarea { padding: 11px 12px; font-size: 16px; }
  .cal-modal__actions { position: sticky; bottom: 0; background: var(--surface); padding-top: 10px; margin-top: auto; }
  .cal-save, .cal-modal__actions .btn-primary { min-height: 44px; }
}

/* Recipe/artifact DETAIL body styles — used by the artifact-doc partial injected into the
   shared glass-box reader. The Library list itself reuses the Files glass-box classes
   (.glass-list / .glass-group / .glass-item) for true parity — see the Library block further down. */
.rec-tag { font-size: 11px; background: var(--bg); border: 1px solid var(--border); color: var(--muted); border-radius: 6px; padding: 1px 7px; }

/* The rendered recipe body (injected into the shared reader). */
.rec-recipe__tags { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 6px; }
.rec-recipe h3 { font-size: 14px; text-transform: uppercase; letter-spacing: 0.05em; color: var(--muted); margin: 20px 0 8px; }
.rec-ingredients { margin: 0; padding-left: 20px; display: flex; flex-direction: column; gap: 4px; }
.rec-method { margin: 0; padding-left: 22px; display: flex; flex-direction: column; gap: 8px; line-height: 1.5; }
.rec-recipe__notes { margin: 0; line-height: 1.55; }
.rec-recipe__source { margin: 18px 0 0; font-size: 12px; font-style: italic; }

/* Desktop (≥880px): the rendered artifact body shares the centered reading column (the
   parallel of .glass-reader__body .md). The Library list's master-detail grid lives in the
   Library block below; the .glass-list / .glass-reader desktop rules are global, so they
   already style both columns. */
@media (min-width: 880px) {
  .glass-reader__body .rec-recipe { max-width: var(--content-max); margin: 0 auto; padding: 28px 24px 56px; }
}

/* onboarding ceremony — centering/width come from .tabpane (it's pane content now) */
.stage .step { background: var(--panel); border: 1px solid var(--border); border-radius: 16px; padding: 36px; text-align: center; }
.stage h1 { font-size: 34px; margin: 0 0 8px; }
.stage .q { font-size: 24px; margin: 0 0 22px; font-weight: 600; }
.stage .answer { margin: 0 auto 8px; max-width: 460px; }
.step-actions { margin-top: 18px; }
/* The "← Just me or my family?" retreat link under a ceremony step's primary action. */
.onb-back { display: block; margin-top: 16px; text-decoration: none; }
.onb-back:hover { color: var(--accent); }
.small { font-size: 13px; }

/* Provider picker (the Awakening) — "works with Claude or ChatGPT" as a segmented
   choice. Selected option is .btn-primary; the other a plain .btn. */
/* Per-agent settings (account settings): ONE table — a row per agent, a dropdown for the
   model (Opus/Sonnet). Agents down the left, dropdown cells across. */
.agent-table { width: 100%; border-collapse: collapse; }
.agent-table th, .agent-table td { text-align: left; padding: 8px 10px; vertical-align: middle; }
.agent-table thead th { font-size: 12px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.03em; border-bottom: 1px solid var(--border); }
.agent-table tbody tr + tr { border-top: 1px solid var(--border); }
.agent-table th[scope="row"] { font-weight: 600; }
/* Keep the <th> a real table-cell (so it honors the row's vertical-align:middle) and put
   the avatar+name in an inline-flex INNER wrapper — making the cell itself flex drops it
   out of table layout and mis-aligns it against the dropdown cells. */
.agent-who { display: inline-flex; align-items: center; gap: 10px; min-width: 0; vertical-align: middle; }
.agent-avatar { font-size: 20px; line-height: 1; flex: none; }
.agent-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Delete column — a quiet trash icon that warms to danger on hover. */
.agent-th-del, .agent-cell-del { width: 1%; text-align: right; white-space: nowrap; }
.agent-del-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; padding: 0; border: 1px solid transparent;
  border-radius: 8px; background: none; color: var(--muted); cursor: pointer;
}
.agent-del-btn:hover { color: var(--error); background: color-mix(in srgb, var(--error) 12%, transparent); }
.agent-del-btn:focus-visible { outline: none; border-color: var(--error); }
.agent-del-btn .icon { width: 18px; height: 18px; }
/* Confirm modal reuses .paywall chrome but left-aligns the form. */
.paywall__card--confirm { text-align: left; }
.agent-select {
  font: inherit; color: var(--text); background: var(--bg);
  border: 1px solid var(--border); border-radius: 8px; padding: 6px 10px; cursor: pointer;
}
.agent-select:focus-visible { outline: none; border-color: var(--accent); box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 35%, transparent); }
.agent-select:disabled { opacity: 0.65; cursor: not-allowed; }


/* Onboarding bootstrap chat — the agent wakes up and interviews you. It uses the
   EXACT same chrome as the dashboard chat: when the ceremony enters its chat phase
   (.chatting, set by onboarding.js) the section drops its .tabpane centering and
   becomes a full-pane native thread — full-width header + scroller + docked pill
   composer — driven by the shared .chat-head/.messages/.chat-form rules below. The
   bubbles were already shared (.ce-* rows, incl. the in-bubble working spinner). */
.ceremony.chatting { max-width: none; margin: 0; padding: 0; height: 100dvh; display: flex; flex-direction: column; }
.ceremony.chatting #stage { display: none; }
.onb-chat { flex: 1; min-height: 0; display: flex; flex-direction: column; }

@media (max-width: 879px) {
  /* Match #tab-chat on mobile: fill the viewport, clear the fixed top bar. */
  .ceremony.chatting { height: 100dvh; padding: var(--mtop-h) 0 0; }
  /* The bottom tab bar only exists once you have an agent (adding another) — on the
     first-ever onboarding there's none, so don't reserve space for it. */
  .ceremony.chatting .chat-form { margin-bottom: env(safe-area-inset-bottom); }
  .ceremony.chatting.with-tabbar .chat-form { margin-bottom: calc(var(--tabbar-h) + env(safe-area-inset-bottom)); }
}

/* ── The chat component (public/js/chat-core.js) ───────────────────────────── */

/* A messaging-client thread, but laid out like Claude Code: BOTH senders start at
   the left margin (avatar → name → text), and the text fills the full column width
   instead of a narrow 78% bubble — so long replies read horizontally, not as a tall
   vertical ribbon. The user is distinguished by a subtle card; the agent is plain
   page text. */
.ce-row { position: relative; display: flex; gap: 10px; align-items: flex-start; margin: 14px 0; }
.ce-row.grouped { margin-top: 4px; }

/* Per-message hover actions (copy this / copy to end) — a floating pill toolbar at
   the row's top-right. Hidden until you hover the row (or focus a button); on touch
   (no hover) it sits faintly visible since there's no hover to reveal it. A surface
   background keeps it legible where it overlaps the start of a full-width reply. */
.ce-actions {
  position: absolute; top: -6px; right: 0; display: flex; gap: 4px; padding: 3px;
  background: var(--surface); border: 1px solid var(--border); border-radius: 10px;
  box-shadow: 0 2px 8px rgba(0,0,0,0.10); opacity: 0; pointer-events: none;
  transition: opacity 0.12s; z-index: 2;
}
.ce-row:hover > .ce-actions, .ce-actions:focus-within,
.ce-row.actions-open > .ce-actions { opacity: 1; pointer-events: auto; }
.ce-act {
  border: none; background: none; color: var(--muted); cursor: pointer;
  font-family: inherit; font-size: 12px; padding: 3px 8px; border-radius: 7px; white-space: nowrap;
}
.ce-act:hover { background: var(--bg); color: var(--ink); }

/* "Loading older messages" spinner — absolute (out of flow, so toggling it never
   shifts the scroll-position math) at the top of the thread during a scroll-up load. */
.ce-top-loader { position: absolute; top: 8px; left: 50%; transform: translateX(-50%); z-index: 3; }

/* Jump-to-latest — a floating round button anchored to the chat pane (NOT the
   scroller, so it stays put while you scroll). The host gets position:relative; the
   button's `bottom` is set by JS to sit just above the composer at any height. */
.ce-has-jump { position: relative; }
.ce-jump {
  position: absolute; right: 24px; /* bottom set inline by chat-core.js */
  width: 38px; height: 38px; border-radius: 50%; display: grid; place-items: center;
  background: var(--surface); color: var(--ink); border: 1px solid var(--border);
  box-shadow: 0 3px 12px rgba(0,0,0,0.16); cursor: pointer; z-index: 5;
  transition: border-color 0.12s, color 0.12s, transform 0.08s;
}
.ce-jump:hover { border-color: var(--accent); color: var(--accent); transform: translateY(1px); }
.ce-jump svg { width: 20px; height: 20px; }
@media (max-width: 879px) { .ce-jump { right: 16px; } }

/* No bubble — just the emoji. Height is pinned to ~the name's line box (not the glyph), with the row
   top-aligned (align-items:flex-start), so the emoji CENTERS on the name row; the larger glyph simply
   overflows the short box symmetrically. */
.ce-avatar { flex: 0 0 auto; width: 30px; height: 16px; display: grid; place-items: center; font-size: 24px; line-height: 1; overflow: visible; }
.ce-row.grouped .ce-avatar { visibility: hidden; }

/* Fill the row so text uses the full width (both senders left-aligned). */
.ce-body { display: flex; flex-direction: column; gap: 4px; flex: 1 1 auto; min-width: 0; }

.ce-meta { display: flex; gap: 8px; align-items: baseline; font-size: 12px; color: var(--muted); }
.ce-name { font-weight: 600; color: var(--ink); }
.ce-row.grouped .ce-meta { display: none; }
/* Unprompted (task-woken) message: a soft accent edge on the bubble, so it feels
   like the agent reached out without shouting it. */
.ce-row.proactive .ce-text { border-left: 2px solid var(--accent); padding-left: 12px; }

/* Agent: plain text on the canvas (no bubble), so it reads full-width like a doc. */
.ce-text { padding: 2px 0; word-wrap: break-word; overflow-wrap: anywhere; }
/* User: a subtle card so the alternation stays legible at full width. */
.ce-row.user .ce-text { padding: 10px 14px; border-radius: 14px; background: var(--panel); border: 1px solid var(--border); }
.ce-caret::after { content: "▍"; opacity: 0.5; margin-left: 1px; }
.ce-text.err { color: var(--error); }
.ce-text p { margin: 0 0 8px; }
.ce-text p:last-child { margin-bottom: 0; }
.ce-text ul, .ce-text ol { margin: 4px 0; padding-left: 20px; }
.ce-text code { font-family: ui-monospace, Menlo, monospace; font-size: 0.92em; background: rgba(127,127,127,0.18); padding: 1px 5px; border-radius: 5px; }
.ce-text pre { background: rgba(127,127,127,0.14); border: 1px solid var(--border); border-radius: 10px; padding: 10px 12px; overflow-x: auto; }
.ce-text pre code { background: none; padding: 0; }
.ce-text a { color: var(--accent); text-decoration: underline; }

.ce-events { display: flex; flex-direction: column; gap: 2px; }
.ce-note { font-size: 12px; color: var(--muted); }
/* Retry — the recovery affordance under a dropped turn. align-self:flex-start so it
   hugs the text, not the full row width. */
.ce-retry {
  align-self: flex-start; margin-top: 4px; padding: 4px 12px; border-radius: 999px;
  border: 1px solid var(--border); background: transparent; color: var(--muted);
  font-size: 15px; font-family: inherit; cursor: pointer; transition: border-color 0.12s, color 0.12s;
}
.ce-retry:hover { border-color: var(--accent); color: var(--accent); }

/* "Working" status — sits at the BOTTOM of the pending agent bubble (inside .ce-text)
   while the turn is in flight, so the bubble is never an empty panel and a long tool op
   never reads as a dead stall. Spinner + a verb, gently breathing. The :only-child rule
   tightens the gap when the bubble is still empty (spinner alone, pre-first-token). */
.ce-working {
  display: flex; align-items: center; gap: 8px; margin-top: 6px;
  font-size: 13px; color: var(--muted);
  animation: ce-working-pulse 1.6s ease-in-out infinite;
}
.ce-text > .ce-working:only-child { margin-top: 0; }
.ce-spinner {
  flex: none; width: 13px; height: 13px; border-radius: 50%;
  border: 2px solid var(--border); border-top-color: var(--accent);
  animation: glass-spin 0.7s linear infinite;
}
.ce-working__label { font-style: italic; }
@keyframes ce-working-pulse { 0%, 100% { opacity: 0.6; } 50% { opacity: 1; } }
@media (prefers-reduced-motion: reduce) {
  .ce-spinner, .ce-working { animation: none; }
  .ce-spinner { border-top-color: var(--accent); } /* still reads as a status dot */
}

.ce-choices { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 2px; }
.ce-choice { padding: 7px 13px; border-radius: 999px; border: 1px solid var(--accent); background: transparent; color: var(--accent); font-size: 15px; font-family: inherit; cursor: pointer; }
.ce-choice:hover:not(:disabled) { background: var(--accent); color: #fff; }
.ce-choice:disabled { cursor: default; opacity: 0.55; }
.ce-choice.picked { background: var(--accent); color: #fff; opacity: 1; }

/* ── Library — the Files glass-box shape, one tier deeper: each collection is a
   .glass-group heading with its artifacts as .glass-items beneath. Reuses the glass-box
   classes wholesale; only the per-collection profile peek + empty line are bespoke. ── */

/* Desktop (≥880px): the same master-detail grid as #tab-context. The global .glass-list /
   .glass-reader desktop rules style the two columns; we only need the grid container. */
@media (min-width: 880px) {
  #tab-library.glass--cols {
    max-width: none; margin: 0; padding: 0; height: 100dvh;
    display: grid; grid-template-columns: 480px minmax(0, 1fr);
  }
}

.lib-empty { font-size: 13px; padding: 4px 2px 8px; }

/* ── In-place editor — the docked composer on the Library reader (public/js/dashboard/library.js).
   The reader becomes a flex column: the doc scrolls, the composer stays pinned at the foot, and a
   agent edit re-renders the body live (.lib-flash). Scoped to #lib-viewer so the Files reader (no
   composer) is untouched — both share the .glass-reader classes. ── */
#lib-viewer { display: flex; flex-direction: column; overflow: hidden; }
#lib-viewer .glass-reader__inner { flex: 1 1 auto; min-height: 0; overflow-y: auto; }

.lib-chat { flex: none; border-top: 1px solid var(--border); background: var(--bg); padding: 10px 16px; }
#lib-viewer:not(.has-artifact) .lib-chat { display: none; }   /* nothing open → no composer */

.lib-chat__form { display: flex; gap: 8px; align-items: flex-end; max-width: var(--content-max); margin: 0 auto; }
.lib-chat__form textarea {
  flex: 1; padding: 10px 14px; border-radius: 13px;
  border: 1px solid var(--border); background: var(--surface); color: var(--ink);
  font-size: 16px; font-family: inherit; line-height: 1.4; box-sizing: border-box;
  resize: none; min-height: calc(1.4em + 22px); max-height: 120px; overflow-y: auto;
}
.lib-chat__form textarea:focus { outline: none; border-color: var(--accent); }
.lib-chat__send { flex: none; width: 42px; height: 42px; padding: 0; border-radius: 999px; display: grid; place-items: center; font-size: 16px; }

/* The agent's ephemeral reply — ONE bubble above the input (doc-first, not a thread). */
.lib-chat__reply { position: relative; display: flex; gap: 8px; align-items: flex-start; max-width: var(--content-max); margin: 0 auto 8px; padding-right: 22px; }
.lib-chat__avatar { font-size: 20px; line-height: 1.4; flex: none; }
.lib-chat__bubble { min-width: 0; flex: 1; }
.lib-chat__text { font-size: 14px; line-height: 1.5; color: var(--ink); }
.lib-chat__text p { margin: 0 0 6px; }
.lib-chat__text p:last-child { margin-bottom: 0; }
.lib-chat__text.is-streaming::after { content: "▋"; color: var(--accent); animation: lib-caret 1s steps(1) infinite; }
@keyframes lib-caret { 50% { opacity: 0; } }
.lib-chat__events { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.lib-chat__events:empty { display: none; }
.lib-chat__chip { font-size: 12px; color: var(--muted); background: var(--surface); border: 1px solid var(--border); border-radius: 999px; padding: 2px 9px; }
.lib-chat__dismiss { position: absolute; top: -2px; right: 0; background: none; border: none; color: var(--muted); font-size: 18px; line-height: 1; cursor: pointer; padding: 2px 4px; }
.lib-chat__dismiss:hover { color: var(--ink); }
.lib-chat__spinner { display: inline-block; width: 13px; height: 13px; border: 2px solid var(--border); border-top-color: var(--accent); border-radius: 50%; animation: lib-spin 0.7s linear infinite; vertical-align: middle; }
@keyframes lib-spin { to { transform: rotate(360deg); } }

/* The live-edit highlight — a soft accent wash on the doc body that fades as it re-renders. */
.lib-flash { animation: lib-flash 1.1s ease-out; }
@keyframes lib-flash { 0% { background: color-mix(in srgb, var(--accent) 16%, transparent); } 100% { background: transparent; } }

@media (max-width: 879px) {
  /* The reader overlay (z-60) covers the bottom tab bar (z-50) while reading, so the composer
     sits at the very bottom — just clear the home-bar safe area, no tab-bar offset. */
  .lib-chat { padding-bottom: calc(10px + env(safe-area-inset-bottom)); }
}

/* ============================================================
   Public pages — marketing landing + legal/contact. These render
   through the main layout (.wrap, max-width 980px); the header and
   footer partials (pub-head / pub-foot) frame every public page.
============================================================ */

/* Larger CTA button used on the landing page. */
.btn-lg { padding: 13px 26px; font-size: 17px; border-radius: 12px; }

/* ── Public header ── */
.pub-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; padding: 6px 0 28px;
}
.pub-head__brand { display: inline-flex; align-items: center; gap: 9px; text-decoration: none; color: var(--ink); }
.pub-head__brand .brand-face { width: 22px; height: 22px; }
.pub-head__brand .brand-wordmark { font-family: var(--font-display); font-weight: 700; font-size: 22px; }
/* flex-wrap + nowrap items: if space runs out, whole controls drop to a second
   row right-aligned — never the broken "Log in" / "Get / started" text wrap. */
.pub-head__nav { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 10px 16px; }
.pub-head__link { color: var(--ink); text-decoration: none; font-size: 15px; white-space: nowrap; }
.pub-head__link:hover { color: var(--accent); }
.pub-head__nav .btn { white-space: nowrap; }
/* The light/dark toggle on the minimal auth/join shell (where the nav doors are dropped).
   Same .theme-toggle behavior as the account menu (app-header.js flips the label). */
.pub-head__theme {
  display: inline-flex; align-items: center; gap: 8px; white-space: nowrap;
  background: var(--surface); border: 1px solid var(--border); color: var(--ink);
  border-radius: 999px; padding: 7px 14px; font-size: 14px; cursor: pointer;
}
.pub-head__theme:hover { border-color: var(--accent); color: var(--accent); }
.pub-head__theme .icon { width: 16px; height: 16px; }
@media (max-width: 560px) {
  .pub-head { gap: 12px; padding-bottom: 22px; }
  .pub-head__nav { gap: 8px 14px; }
  .pub-head__link { font-size: 14px; }
}

/* ── Landing ── */
.land { display: flex; flex-direction: column; gap: 8px; }

/* Hero is a two-column stage: the pitch (left) beside a real agent's insides (right).
   The glass box IS the hero, not an illustration tucked below it. Stacks on mobile. */
.land-hero {
  display: grid; grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
  gap: 46px; align-items: center; text-align: left; padding: 38px 0 60px;
}
.land-hero__title { font-size: 50px; line-height: 1.04; margin: 0 0 16px; letter-spacing: -0.02em; }
.land-hero__title em { color: var(--accent); font-style: normal; white-space: nowrap; }
.land-hero__lede { max-width: 32em; margin: 0; font-size: 19px; line-height: 1.55; color: var(--ink); }
.land-hero__cta { margin-top: 26px; }
.land-hero__note { margin-top: 14px; font-size: 13.5px; }


/* Content sections */
.land-section { padding: 48px 0; border-top: 1px solid var(--border); }
.land-section--alt {
  background: var(--panel); border: 1px solid var(--border); border-radius: 20px;
  padding: 44px 36px; margin: 16px 0;
}
.land-eyebrow {
  margin: 0 0 6px; font-size: 12px; font-weight: 700; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--accent);
}
.land-section h2 { font-size: 30px; margin: 0 0 16px; letter-spacing: -0.01em; }
.land-lead { font-size: 17px; line-height: 1.6; margin: 0; }

/* Steps */
.land-steps { list-style: none; margin: 24px 0 0; padding: 0; display: flex; flex-direction: column; gap: 22px; }
.land-steps li { display: flex; gap: 16px; align-items: flex-start; }
.land-steps__n {
  flex: none; display: grid; place-items: center; width: 34px; height: 34px;
  border-radius: 50%; background: var(--accent); color: var(--accent-ink);
  font-family: var(--font-display); font-weight: 700; font-size: 16px;
}
.land-steps h4 { margin: 4px 0 4px; font-size: 18px; }
.land-steps p { margin: 0; line-height: 1.5; }

/* Glass-box checklist */
.land-checks { list-style: none; margin: 22px 0 0; padding: 0; display: flex; flex-direction: column; gap: 12px; }
.land-checks li { display: flex; align-items: center; gap: 12px; font-size: 16px; }
.land-checks .icon { color: var(--accent); width: 18px; height: 18px; flex: none; }
/* A paragraph right after a checklist needs air — the list has only a top margin. */
.land-checks + .land-lead { margin-top: 22px; }

/* Final CTA */
.land-final { text-align: center; padding: 60px 0 48px; border-top: 1px solid var(--border); }
.land-final h2 { font-size: 32px; margin: 0 0 8px; }

/* ── Landing spice (emoji-forward + warmth) ─────────────────────────────────
   Layered on top of the base rules above: a soft hero glow, an emoji badge,
   multi-hue icon chips (coral/teal/violet etc — the accent palette), card
   hover-lift, gradient accents, and CTA polish. The brand leans on emoji as a
   first-class affordance, so they carry the colour and these styles add depth. */

/* Hero: relative + a warm radial glow behind the title */
.land-hero { position: relative; }
.land-hero::before {
  content: ""; position: absolute; z-index: -1; pointer-events: none;
  left: 50%; top: -30px; transform: translateX(-50%);
  width: min(720px, 92%); height: 360px;
  background: radial-gradient(58% 60% at 50% 38%,
    color-mix(in srgb, var(--accent) 24%, transparent), transparent 72%);
  filter: blur(6px);
}

/* Emoji badge above the title */
.land-badge {
  display: inline-flex; align-items: center; gap: 8px; margin: 0 0 18px;
  padding: 6px 14px 6px 7px; border-radius: 999px;
  background: color-mix(in srgb, var(--accent) 11%, var(--surface));
  border: 1px solid color-mix(in srgb, var(--accent) 26%, var(--border));
  font-size: 13.5px; font-weight: 600; color: var(--ink); letter-spacing: -0.01em;
}
.land-badge__face {
  display: grid; place-items: center; width: 22px; height: 22px; border-radius: 50%;
  background: var(--surface); font-size: 14px; line-height: 1;
  box-shadow: 0 1px 3px rgba(0,0,0,0.10);
}

/* "see into" reads as a royal→violet gradient; the 👀 gives a gentle bob */
.land-hero__title em {
  color: var(--accent);
  background: linear-gradient(120deg, var(--accent), color-mix(in srgb, var(--accent) 55%, #7b61ff));
  -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent;
}
.land-hero__eye { display: inline-block; animation: land-eye-bob 3.2s ease-in-out infinite; }
@keyframes land-eye-bob { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-4px); } }

/* Eyebrows become little accent pills (the emoji rides inside) */
.land-eyebrow {
  display: inline-flex; align-items: center; gap: 6px;
  margin: 0 0 12px; padding: 5px 11px; border-radius: 999px;
  background: color-mix(in srgb, var(--accent) 10%, var(--surface));
}

/* Step number chips: gradient fill + a soft accent shadow */
.land-steps__n {
  background: linear-gradient(135deg, var(--accent), color-mix(in srgb, var(--accent) 68%, #ff3d6a));
  box-shadow: 0 4px 12px color-mix(in srgb, var(--accent) 30%, transparent);
}

/* The emoji that rides each glass-box check */
.land-checks__e { font-size: 15px; line-height: 1; }

/* ── Family "two ways in" visual ─────────────────────────────────────────────
   The two join routes made literal: a big code + PIN on a shared device, or an
   email-invite mock. Echoes the friendrot teachers code/PIN card. */
.land-join__head {
  margin: 28px 0 0; font-family: var(--font-display); font-weight: 700;
  font-size: 18px; color: var(--ink);
}
.land-join {
  display: grid; grid-template-columns: 1fr auto 1fr; gap: 16px;
  align-items: stretch; margin: 14px 0 6px;
}
.land-join__route {
  display: flex; flex-direction: column;
  background: var(--surface); border: 1px solid var(--border); border-radius: 16px;
  padding: 20px; box-shadow: 0 1px 2px rgba(0,0,0,0.03);
}
.land-join__rlabel {
  display: flex; align-items: center; gap: 8px; margin: 0 0 14px;
  font-family: var(--font-display); font-weight: 700; font-size: 15.5px;
}
.land-join__re { font-size: 18px; line-height: 1; }

/* The big code + PIN */
.land-join__creds {
  flex: 1; display: flex; flex-direction: column; justify-content: center; gap: 10px;
}
.land-join__cred {
  text-align: center; padding: 12px 10px; border-radius: 12px;
  background: color-mix(in srgb, var(--accent) 7%, var(--surface));
  border: 1px solid color-mix(in srgb, var(--accent) 18%, var(--border));
}
.land-join__credlabel {
  display: block; margin-bottom: 3px; font-size: 10px; font-weight: 800;
  letter-spacing: 0.22em; text-transform: uppercase; color: var(--muted);
}
.land-join__credval {
  display: block; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-weight: 800; font-size: clamp(30px, 5.2vw, 44px); line-height: 1.05;
  letter-spacing: 0.12em; color: var(--accent);
}

/* The "or" hinge between the two routes */
.land-join__or {
  display: grid; place-items: center; color: var(--muted);
  font-family: var(--font-display); font-weight: 700; font-size: 12px;
  text-transform: uppercase; letter-spacing: 0.1em;
}
.land-join__or span {
  display: grid; place-items: center; width: 34px; height: 34px; border-radius: 50%;
  background: var(--bg); border: 1px solid var(--border);
}

/* Email-invite mock */
.land-join__mail {
  flex: 1; display: flex; flex-direction: column; gap: 7px;
  background: var(--bg); border: 1px solid var(--border); border-radius: 12px; padding: 14px 16px;
}
.land-join__mailto {
  margin: 0; font-size: 12.5px; color: var(--muted);
  font-family: ui-monospace, SFMono-Regular, monospace;
}
.land-join__mailto span { color: var(--ink); }
.land-join__mailsub { margin: 2px 0 0; font-size: 16px; font-weight: 700; line-height: 1.3; color: var(--ink); }
.land-join__mailbtn {
  align-self: flex-start; margin-top: auto;
  padding: 8px 14px; border-radius: 9px;
  background: var(--accent); color: #fff; font-size: 13px; font-weight: 700;
  box-shadow: 0 4px 12px color-mix(in srgb, var(--accent) 28%, transparent);
}
.land-join__cap { margin: 12px 0 0; font-size: 12.5px; line-height: 1.45; color: var(--muted); }

@media (max-width: 720px) {
  .land-join { grid-template-columns: 1fr; gap: 12px; }
  .land-join__or { padding: 2px 0; }
  .land-join__or span { width: 30px; height: 30px; }
}

/* Alt sections get a barely-there accent wash */
.land-section--alt {
  background: linear-gradient(180deg, color-mix(in srgb, var(--accent) 5%, var(--surface)), var(--surface));
}

/* CTA buttons: an accent glow + a small lift on hover */
.land-hero__cta .btn, .land-final .btn { transition: transform .15s ease, box-shadow .15s ease; }
.land-hero__cta .btn-primary, .land-final .btn-primary {
  box-shadow: 0 6px 18px color-mix(in srgb, var(--accent) 34%, transparent);
}
.land-hero__cta .btn:hover, .land-final .btn:hover { transform: translateY(-2px); }
.land-hero__cta .btn-primary:hover, .land-final .btn-primary:hover {
  box-shadow: 0 10px 26px color-mix(in srgb, var(--accent) 46%, transparent);
}

@media (prefers-reduced-motion: reduce) {
  .land-hero__eye { animation: none; }
  .land-hero__cta .btn, .land-final .btn { transition: none; }
}

/* ── Landing pricing (two tiers) + FAQ ──────────────────────────────────── */
.land-plans {
  display: grid; grid-template-columns: repeat(2, 1fr); gap: 18px; margin-top: 26px;
  align-items: stretch;
}
.land-plan {
  position: relative; display: flex; flex-direction: column;
  background: var(--surface); border: 1px solid var(--border); border-radius: 18px;
  padding: 26px 24px; box-shadow: 0 1px 2px rgba(0,0,0,0.03);
}
.land-plan--featured {
  border-color: color-mix(in srgb, var(--accent) 45%, var(--border));
  box-shadow: 0 16px 36px color-mix(in srgb, var(--accent) 16%, transparent);
}
.land-plan--soon { border-style: dashed; }
.land-plan__badge {
  position: absolute; top: -11px; left: 24px;
  display: inline-flex; align-items: center; padding: 4px 11px; border-radius: 999px;
  font-size: 12px; font-weight: 700; letter-spacing: -0.01em;
  background: var(--accent); color: #fff;
}
.land-plan--soon .land-plan__badge { background: var(--muted); }
.land-plan__name { margin: 2px 0 6px; font-size: 20px; }
.land-plan__price { margin: 0 0 6px; display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.land-plan__amt { font-family: var(--font-display); font-weight: 800; font-size: 34px; letter-spacing: -0.02em; }
.land-plan__per { color: var(--muted); font-size: 15px; }
.land-plan__tag { margin: 0 0 16px; color: var(--muted); font-size: 14.5px; line-height: 1.45; }
.land-plan__list { list-style: none; margin: 0 0 20px; padding: 0; display: flex; flex-direction: column; gap: 10px; }
.land-plan__list li { display: flex; align-items: flex-start; gap: 10px; font-size: 15px; line-height: 1.4; }
.land-plan__e { flex: none; width: 1.35em; text-align: center; font-size: 15px; line-height: 1.4; }
.land-plan--featured .land-plan__list li:first-child .land-plan__e { color: var(--accent); font-weight: 800; }
.land-plan__cta { margin-top: auto; align-self: flex-start; }

/* BYOK section — the "get a key" CTA row (steps reuse .land-steps) */
.land-byok__cta { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; margin-top: 24px; }
.land-byok__cta code, .land-steps code, .land-twocosts code {
  background: color-mix(in srgb, var(--accent) 10%, var(--surface));
  border: 1px solid var(--border); border-radius: 6px; padding: 1px 6px; font-size: 0.9em;
}

/* "Two costs, plainly" honesty note */
.land-twocosts {
  display: flex; gap: 14px; align-items: flex-start; margin-top: 24px;
  background: color-mix(in srgb, var(--accent) 7%, var(--surface));
  border: 1px solid color-mix(in srgb, var(--accent) 20%, var(--border));
  border-radius: 14px; padding: 18px 20px;
}
.land-twocosts__icon { font-size: 22px; line-height: 1.3; flex: none; }
.land-twocosts p { margin: 0; font-size: 15px; line-height: 1.55; }

/* FAQ — native details/summary, no JS */
.land-faq { display: flex; flex-direction: column; gap: 10px; margin-top: 24px; }
.land-faq__item {
  background: var(--surface); border: 1px solid var(--border); border-radius: 14px; padding: 0 18px;
  transition: border-color .18s ease;
}
.land-faq__item[open] { border-color: color-mix(in srgb, var(--accent) 30%, var(--border)); }
.land-faq__q {
  cursor: pointer; list-style: none; padding: 16px 0; font-weight: 700; font-size: 16.5px;
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
}
.land-faq__q::-webkit-details-marker { display: none; }
.land-faq__q::after {
  content: "+"; flex: none; color: var(--accent); font-size: 22px; font-weight: 700; line-height: 1;
}
.land-faq__item[open] .land-faq__q::after { content: "\2212"; }
.land-faq__a { margin: 0; padding: 0 0 18px; color: var(--muted); line-height: 1.6; font-size: 15px; }

/* Decorative emoji marquee — CSS-only infinite loop, edges faded out. The track
   holds the (server-shuffled) set TWICE; translateX(-50%) scrolls exactly one
   copy so the wrap is seamless. Uniform size on purpose — varying per-item would
   break the seam, since the two copies must match. */
.land-marquee {
  overflow: hidden; margin: 6px 0 2px; padding: 8px 0;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent);
}
.land-marquee__track { display: flex; width: max-content; animation: land-marquee 46s linear infinite; }
.land-marquee:hover .land-marquee__track { animation-play-state: paused; }
.land-marquee__e { flex: none; padding: 6px 16px; font-size: 26px; line-height: 1; user-select: none; }
@keyframes land-marquee { from { transform: translateX(0); } to { transform: translateX(-50%); } }
@media (prefers-reduced-motion: reduce) { .land-marquee__track { animation: none; } }

/* ── Landing: glass-box hero visual, voice bubbles, "built in the open" ──────── */

/* The money shot — a CSS-only glass box (file tree + a rendered identity page) */
/* ── The hero glass box — the money shot ────────────────────────────────────
   A real agent's insides: a file tree beside a SOUL.md page the agent wrote about
   itself. The schematic pins (coral pill tags) annotate the transparency; the
   blink caret implies the live self-authoring. Warm paper + ink, gently tilted —
   the deliberate opposite of the dark-glass-gradient cliché every other AI ships. */
/* Left-align always — the hero centers its text on mobile, which must NOT leak into
   the glass box (it would centre the tree headings + page prose). */
.glass { position: relative; text-align: left; }
.glass__win {
  background: var(--surface); border: 1px solid var(--border); border-radius: 16px;
  overflow: hidden; transform: rotate(-0.6deg);
  box-shadow: 0 1.5px 0 color-mix(in srgb, var(--accent) 28%, transparent),
              0 30px 60px -20px rgba(0,0,0,0.30);
}
.glass__bar {
  display: flex; align-items: center; gap: 12px; padding: 10px 15px;
  background: color-mix(in srgb, var(--panel) 60%, var(--accent) 5%);
  border-bottom: 1px solid var(--border);
}
.glass__dots { display: inline-flex; gap: 6px; }
.glass__dots i { width: 10px; height: 10px; border-radius: 50%; background: color-mix(in srgb, var(--muted) 40%, var(--border)); }
.glass__crumb {
  font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: 12.5px; color: var(--muted); font-weight: 600;
}
.glass__crumb .glass__sep { opacity: 0.45; margin: 0 3px; }
/* minmax(0, 1fr) on the page track: without the 0 min, the track sizes to its widest
   panel's content, so the whole box would resize each time you switch files. */
.glass__body { display: grid; grid-template-columns: 188px minmax(0, 1fr); }
.glass__tree {
  border-right: 1px solid var(--border); padding: 15px 13px;
  background: color-mix(in srgb, var(--panel) 45%, var(--surface));
}
.glass__group {
  margin: 14px 0 6px; font-size: 10.5px; font-weight: 700; letter-spacing: 0.07em;
  text-transform: uppercase; color: var(--muted);
}
.glass__group:first-child { margin-top: 0; }
/* Each file is a real button (a tab) — click to open it in the page panel. */
.glass__file {
  display: flex; align-items: center; gap: 8px; width: 100%; text-align: left;
  font-size: 13.5px; padding: 6px 9px; margin: 1px 0; border-radius: 7px;
  color: var(--ink); background: none; border: 0; cursor: pointer;
  font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  transition: background-color .12s ease, color .12s ease;
}
.glass__file:hover { background: color-mix(in srgb, var(--ink) 6%, transparent); }
.glass__file.is-active {
  background: color-mix(in srgb, var(--accent) 15%, var(--surface));
  color: var(--accent); font-weight: 600;
}
.glass__file:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.glass__page { padding: 20px 22px; min-width: 0; }
.glass__panel[hidden] { display: none; }
.glass__panel:focus { outline: none; }
/* IDENTITY.md — the spine, as key/value rows */
.glass__spine { margin: 0; display: flex; flex-direction: column; gap: 9px; }
.glass__spine > div { display: flex; gap: 12px; align-items: baseline; }
.glass__spine dt { flex: none; width: 86px; color: var(--muted); font-size: 12.5px; }
.glass__spine dd { margin: 0; font-size: 14.5px; line-height: 1.4; }
/* MEMORY.md — two bands + notes */
.glass__band {
  margin: 2px 0 7px; font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: 12.5px; font-weight: 600; color: var(--accent);
}
.glass__notes, .glass__agenda, .glass__lib {
  list-style: none; margin: 0 0 14px; padding: 0; display: flex; flex-direction: column; gap: 7px;
}
.glass__notes:last-child, .glass__agenda:last-child, .glass__lib:last-child { margin-bottom: 0; }
.glass__notes li, .glass__lib li { font-size: 14px; line-height: 1.45; }
.glass__notes li { display: flex; gap: 8px; }
.glass__notes li::before { content: "•"; color: var(--accent); flex: none; }
/* Calendar — a mini agenda */
.glass__agenda li { display: flex; gap: 12px; font-size: 14px; line-height: 1.4; align-items: baseline; }
.glass__when {
  flex: none; width: 54px; color: var(--accent); font-weight: 600;
  font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace); font-size: 12.5px;
}
.glass__fname {
  font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: 12px; color: var(--muted); margin: 0 0 13px;
  padding-bottom: 10px; border-bottom: 1px solid var(--border);
}
.glass__fname span { opacity: 0.8; }
.glass__panel > p:not(.glass__fname) { margin: 0 0 11px; font-size: 14.5px; line-height: 1.6; }
.glass__panel > p:last-child { margin-bottom: 0; }
.glass__caret {
  display: inline-block; width: 2px; height: 1.05em; vertical-align: -0.18em;
  margin-left: 2px; background: var(--accent); animation: glass-blink 1.1s steps(1) infinite;
}
@keyframes glass-blink { 50% { opacity: 0; } }
/* Schematic call-outs — the transparency, annotated. Hidden when the box stacks. */
.glass__pin {
  position: absolute; z-index: 1; white-space: nowrap;
  font-family: var(--font-display); font-size: 12px; font-weight: 700;
  color: var(--accent-ink); background: var(--accent); padding: 4px 11px; border-radius: 999px;
  box-shadow: 0 8px 20px -6px color-mix(in srgb, var(--accent) 65%, transparent);
}
.glass__pin--tree { left: 12px; top: -13px; transform: rotate(-1.6deg); }
.glass__pin--page { right: 12px; bottom: -13px; transform: rotate(1.6deg); }
@media (prefers-reduced-motion: reduce) { .glass__caret { animation: none; } }

/* Voice — a real thread: left-aligned messages with avatar, name, and time (matches the
   app's chat, where BOTH speakers are left-aligned — not opposing bubbles). */
.land-voice { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; margin-top: 26px; }
.land-chat {
  background: var(--surface); border: 1px solid var(--border); border-radius: 16px;
  padding: 16px; display: flex; flex-direction: column; gap: 15px;
}
.lchat-msg { display: flex; gap: 11px; align-items: flex-start; }
.lchat-av {
  flex: none; width: 32px; height: 32px; border-radius: 50%;
  display: grid; place-items: center; font-size: 16px; line-height: 1;
  background: var(--bg); border: 1px solid var(--border);
}
.lchat-av--agent {
  background: color-mix(in srgb, var(--accent) 14%, var(--surface));
  border-color: color-mix(in srgb, var(--accent) 24%, var(--border));
}
.lchat-body { min-width: 0; }
.lchat-meta { margin: 2px 0 3px; font-size: 12.5px; color: var(--muted); }
.lchat-meta b { color: var(--ink); font-weight: 700; font-family: var(--font-display); font-size: 13.5px; margin-right: 2px; }
.lchat-text { margin: 0; font-size: 14.5px; line-height: 1.5; }

/* Built in the open — essay cards */
.land-essays { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; margin-top: 26px; }
.land-essaycard {
  display: flex; flex-direction: column; gap: 8px; text-decoration: none; color: inherit;
  background: var(--surface); border: 1px solid var(--border); border-radius: 14px; padding: 20px;
  box-shadow: 0 1px 2px rgba(0,0,0,0.03);
  transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease;
}
.land-essaycard:hover {
  transform: translateY(-4px); box-shadow: 0 14px 32px rgba(0,0,0,0.09);
  border-color: color-mix(in srgb, var(--accent) 30%, var(--border));
}
.land-essaycard__meta { font-size: 12px; color: var(--muted); font-weight: 600; }
.land-essaycard h4 { margin: 0; font-size: 17px; line-height: 1.3; }
.land-essaycard p { margin: 0; font-size: 14px; line-height: 1.5; color: var(--muted); flex: 1; }
.land-essaycard__more { font-size: 14px; font-weight: 700; color: var(--accent); }
.land-openlinks { margin-top: 22px; }

/* BYOK "how to get a key" — collapsed by default to cut mid-page friction */
.land-byok__how { margin-top: 16px; }
.land-byok__how > summary {
  cursor: pointer; list-style: none; font-weight: 700; font-size: 15.5px; color: var(--accent);
  display: inline-flex; align-items: center; gap: 8px;
}
.land-byok__how > summary::-webkit-details-marker { display: none; }
.land-byok__how > summary::before { content: "+"; font-size: 18px; line-height: 1; }
.land-byok__how[open] > summary::before { content: "\2212"; }
.land-byok__how[open] > summary { margin-bottom: 4px; }

/* Hero stacks before the rest — the two-column stage needs width to breathe. */
@media (max-width: 880px) {
  .land-hero { grid-template-columns: 1fr; gap: 30px; text-align: center; padding-top: 22px; }
  .land-hero__lede { margin-left: auto; margin-right: auto; }
  .land-hero__cta { justify-content: center; }
  /* width:100% makes the width DEFINITE (viewport-driven, capped at 540). Without it,
     the auto side-margins de-stretch the grid item → it shrinks to content and the box
     resizes every time you open a different file. */
  .glass { width: 100%; max-width: 540px; margin: 18px auto 0; }
  .glass__win { transform: none; }
}
@media (max-width: 760px) {
  .glass__body { grid-template-columns: minmax(0, 1fr); }
  .glass__tree { border-right: none; border-bottom: 1px solid var(--border); }
  .land-voice, .land-essays { grid-template-columns: 1fr; }
}

/* ── Public footer ── */
.pub-foot { margin-top: 40px; padding: 28px 0 12px; border-top: 1px solid var(--border); }
.pub-foot__inner { display: flex; align-items: flex-start; justify-content: space-between; gap: 24px; flex-wrap: wrap; }
.pub-foot__brand .brand-wordmark { font-family: var(--font-display); font-weight: 700; font-size: 18px; }
.pub-foot__tag { margin: 4px 0 0; font-size: 14px; }
.pub-foot__links { display: flex; flex-wrap: wrap; gap: 16px; }
.pub-foot__links a { color: var(--muted); text-decoration: none; font-size: 14px; }
.pub-foot__links a:hover { color: var(--accent); }

/* ============================================================
   Public docs site (/docs) — views/docs/page.hbs + services/docs.js.
   A three-column shell (sidebar nav · article · on-page TOC) inside the shared
   `main` layout. The docs need more room than the 980px reading frame, so we
   widen the .wrap ONLY when it contains .docs (header/footer stay aligned because
   they live in the same .wrap). :has() is universally supported now; if it ever
   isn't, docs just render in the narrower frame — cramped but functional.
============================================================ */
.wrap:has(.docs) { max-width: 1180px; }

.docs {
  display: grid;
  grid-template-columns: 232px minmax(0, 1fr) 196px;
  gap: 40px;
  align-items: start;
}
/* Below ~1080px the TOC is the first thing to go (it's a convenience, not nav). */
@media (max-width: 1080px) {
  .docs { grid-template-columns: 232px minmax(0, 1fr); gap: 32px; }
  .docs__toc { display: none; }
}

/* ── Sidebar (sticky on desktop) ─────────────────────────────────────────── */
.docs__rail {
  position: sticky; top: 16px;
  max-height: calc(100vh - 32px); overflow-y: auto;
  padding-right: 4px;
}
.docs__search { position: relative; margin-bottom: 20px; }
.docs__search-field {
  display: flex; align-items: center; gap: 8px;
  border: 1px solid var(--border); border-radius: 10px;
  background: var(--surface); padding: 8px 11px;
}
.docs__search-field:focus-within { border-color: var(--accent); }
.docs__search-ic { color: var(--muted); font-size: 16px; }
.docs__search-input {
  border: 0; background: transparent; color: var(--ink);
  font: inherit; font-size: 14px; width: 100%; outline: none;
}
.docs__results {
  position: absolute; left: 0; right: 0; top: calc(100% + 6px); z-index: 30;
  background: var(--surface); border: 1px solid var(--border); border-radius: 12px;
  box-shadow: 0 16px 40px rgba(0, 0, 0, 0.18); padding: 6px; max-height: 60vh; overflow-y: auto;
}
.docs__result {
  display: block; padding: 9px 11px; border-radius: 8px;
  text-decoration: none; color: var(--ink);
}
.docs__result:hover, .docs__result.is-active { background: var(--bg); }
.docs__result-title { display: block; font-size: 14px; font-weight: 600; }
.docs__result-sub { display: block; font-size: 12px; color: var(--muted); margin-top: 2px; }
.docs__result-title em { font-style: normal; color: var(--accent); }
.docs__results-empty { padding: 12px; font-size: 13px; color: var(--muted); }

.docs__nav-section { margin-bottom: 18px; }
.docs__nav-label {
  margin: 0 0 7px; font-size: 12px; font-weight: 700; letter-spacing: 0.04em;
  text-transform: uppercase; color: var(--muted);
}
.docs__nav-list { list-style: none; margin: 0; padding: 0; }
.docs__nav-link {
  display: block; padding: 5px 10px; border-radius: 7px; margin-left: -10px;
  font-size: 14px; color: var(--ink); text-decoration: none; line-height: 1.35;
  border-left: 2px solid transparent;
}
.docs__nav-link:hover { background: var(--bg); }
.docs__nav-link.is-current {
  color: var(--accent); font-weight: 600;
  border-left-color: var(--accent); border-radius: 0 7px 7px 0; background: var(--bg);
}

/* Mobile nav toggle — revealed by docs.js on small screens (hidden otherwise). */
.docs__navtoggle {
  display: none; width: 100%; align-items: center; justify-content: space-between;
  gap: 8px; padding: 10px 12px; margin-bottom: 14px;
  border: 1px solid var(--border); border-radius: 10px;
  background: var(--surface); color: var(--ink); font: inherit; font-size: 14px; cursor: pointer;
}
.docs__navtoggle-ic { transition: transform 0.15s ease; }
.docs__navtoggle[aria-expanded="true"] .docs__navtoggle-ic { transform: rotate(180deg); }

/* ── Article ─────────────────────────────────────────────────────────────── */
.docs__article { min-width: 0; max-width: 760px; padding-bottom: 8px; }
.docs__crumb { margin: 0 0 6px; font-size: 13px; font-weight: 600; }
.docs__title { font-size: 36px; line-height: 1.12; margin: 0 0 10px; letter-spacing: -0.015em; }
.docs__lede { margin: 0 0 8px; font-size: 18px; color: var(--muted); line-height: 1.5; }

/* ── Prose (rendered markdown) ───────────────────────────────────────────── */
.prose { line-height: 1.68; font-size: 16px; }
.prose > :first-child { margin-top: 0; }
/* No divider rule above section headings — it made one continuous essay/doc read
   like separate stacked sections. Spacing alone (the top margin) signals a new
   section; the page stays visibly continuous. */
.prose h2 {
  font-size: 25px; line-height: 1.25; margin: 44px 0 12px; scroll-margin-top: 24px;
}
.prose h3 { font-size: 19px; margin: 28px 0 8px; scroll-margin-top: 24px; }
.prose h4 { font-size: 16px; margin: 22px 0 6px; scroll-margin-top: 24px; }
.prose p { margin: 0 0 16px; }
.prose ul, .prose ol { margin: 0 0 16px; padding-left: 22px; }
.prose li { margin: 6px 0; }
.prose li > ul, .prose li > ol { margin: 6px 0; }
.prose a { color: var(--accent); text-decoration: none; }
.prose a:hover { text-decoration: underline; }
.prose strong { font-weight: 700; }
.prose code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.88em;
  background: var(--bg); border: 1px solid var(--border); border-radius: 5px; padding: 1px 5px;
}
.prose pre {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 10px; padding: 14px 16px; overflow-x: auto; margin: 0 0 16px;
}
.prose pre code { background: none; border: 0; padding: 0; font-size: 13.5px; }
.prose hr { border: 0; border-top: 1px solid var(--border); margin: 32px 0; }
/* Blockquotes double as status callouts (e.g. "designed, not yet shipped"). */
.prose blockquote {
  margin: 0 0 16px; padding: 12px 16px;
  border-left: 3px solid var(--accent); border-radius: 0 8px 8px 0;
  background: var(--bg); color: var(--ink);
}
.prose blockquote p { margin: 0 0 6px; }
.prose blockquote p:last-child { margin-bottom: 0; }
.prose table {
  width: 100%; border-collapse: collapse; margin: 0 0 16px; font-size: 14.5px;
}
.prose th, .prose td { text-align: left; padding: 8px 12px; border: 1px solid var(--border); }
.prose th { background: var(--bg); font-weight: 700; }

/* ── Prev / next pager ───────────────────────────────────────────────────── */
.docs__pager {
  display: flex; justify-content: space-between; gap: 16px;
  margin-top: 40px; padding-top: 20px; border-top: 1px solid var(--border);
}
.docs__pager-link {
  display: inline-flex; align-items: center; gap: 10px;
  padding: 12px 16px; border: 1px solid var(--border); border-radius: 12px;
  text-decoration: none; color: var(--ink); max-width: 48%;
}
.docs__pager-link:hover { border-color: var(--accent); }
.docs__pager-next { margin-left: auto; text-align: right; }
.docs__pager-text { display: flex; flex-direction: column; }
.docs__pager-dir { font-size: 12px; color: var(--muted); }
.docs__pager-title { font-size: 15px; font-weight: 600; }
.docs__pager-ic { color: var(--muted); font-size: 18px; flex: none; }

/* ── On-page TOC (sticky, scroll-spied) ──────────────────────────────────── */
.docs__toc { position: sticky; top: 16px; max-height: calc(100vh - 32px); overflow-y: auto; }
.docs__toc-label {
  margin: 0 0 8px; font-size: 12px; font-weight: 700; letter-spacing: 0.04em;
  text-transform: uppercase; color: var(--muted);
}
.docs__toc-list { list-style: none; margin: 0; padding: 0; }
.docs__toc-item--h3 { padding-left: 12px; }
.docs__toc-link {
  display: block; padding: 4px 0; font-size: 13px; line-height: 1.4;
  color: var(--muted); text-decoration: none;
}
.docs__toc-link:hover { color: var(--ink); }
.docs__toc-link.is-active { color: var(--accent); font-weight: 600; }

/* ── Mobile (< 880px) ────────────────────────────────────────────────────── */
@media (max-width: 880px) {
  .docs { display: block; }
  .docs__rail {
    position: static; max-height: none; overflow: visible;
    margin-bottom: 24px; padding-bottom: 20px; border-bottom: 1px solid var(--border);
  }
  .docs__title { font-size: 30px; }
  .docs__pager-link { max-width: 49%; }
  /* The nav toggle is desktop-hidden by its base rule; show it on mobile. docs.js
     collapses .docs__nav and wires the toggle to open/close it. Without JS the nav
     just stays visible below the (inert) toggle, so it still degrades gracefully. */
  .docs__navtoggle { display: flex; }
}
.pub-foot__copy { margin: 20px 0 0; font-size: 13px; }

/* ── Post library (/posts) — private builder tool: an X posting schedule with copy
      buttons + live char counts. ── */
.pl { max-width: 760px; margin: 0 auto; }
.pl-head { padding: 4px 0 24px; border-bottom: 1px solid var(--border); margin-bottom: 8px; }
.pl-back {
  display: inline-flex; align-items: center; gap: 4px; font-size: 13px; font-weight: 600;
  color: var(--muted); text-decoration: none; margin-bottom: 10px;
}
.pl-back:hover { color: var(--accent); }
.pl-back__ic { width: 14px; height: 14px; }
.pl-head__title { font-size: 34px; margin: 0 0 6px; }
.pl-head__sub { font-size: 15px; margin: 0 0 12px; }
.pl-rules { font-size: 13.5px; line-height: 1.5; margin: 0; padding-left: 18px; }
.pl-rules li { margin: 3px 0; }

.pl-week { margin: 28px 0 0; }
.pl-week__label {
  font-size: 13px; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--muted); margin: 0 0 12px; font-weight: 700;
}

.pl-card {
  border: 1px solid var(--border); border-radius: 14px; background: var(--panel);
  padding: 16px 16px 18px; margin: 0 0 16px;
}
.pl-card--over { border-color: var(--accent); }
.pl-card.is-posted { opacity: 0.5; }
.pl-card__head { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; }
.pl-day {
  font-size: 12px; font-weight: 700; color: var(--accent);
  background: var(--bg); border: 1px solid var(--border); border-radius: 999px; padding: 2px 9px;
}
.pl-type {
  font-size: 12px; font-weight: 600; color: var(--muted);
  border: 1px solid var(--border); border-radius: 999px; padding: 2px 9px; white-space: nowrap;
}
.pl-type--thread { color: var(--accent); }
.pl-card__topic { font-size: 17px; margin: 0; flex: 1 1 auto; min-width: 0; }
.pl-done { display: inline-flex; align-items: center; gap: 5px; font-size: 13px; color: var(--muted); cursor: pointer; user-select: none; }
.pl-done__cb { accent-color: var(--accent); }
.pl-note {
  font-size: 13.5px; line-height: 1.5; color: var(--ink); margin: 10px 0 0;
  padding: 9px 12px; background: var(--bg); border-left: 3px solid var(--accent); border-radius: 0 8px 8px 0;
}
.pl-card__actions { margin: 12px 0 0; }

.pl-tweets { list-style: none; margin: 12px 0 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }
.pl-tweet { border: 1px solid var(--border); border-radius: 10px; background: var(--bg); overflow: hidden; }
.pl-tweet.is-over { border-color: var(--accent); }
.pl-tweet__text {
  white-space: pre-wrap; word-break: break-word; font-size: 14.5px; line-height: 1.5;
  padding: 12px 13px; margin: 0;
}
.pl-tweet__foot {
  display: flex; align-items: center; gap: 8px; padding: 7px 10px;
  border-top: 1px solid var(--border); background: var(--surface);
}
.pl-tweet__count { font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; }
.pl-tweet.is-over .pl-tweet__count { color: var(--accent); font-weight: 700; }
.pl-tweet__spacer { flex: 1 1 auto; }

.pl-btn {
  font: inherit; font-size: 13px; font-weight: 600; cursor: pointer;
  border: 1px solid var(--border); border-radius: 8px; padding: 5px 11px;
  background: var(--bg); color: var(--ink); text-decoration: none; white-space: nowrap;
}
.pl-btn:hover { border-color: var(--accent); color: var(--accent); }
.pl-btn--ghost { background: transparent; color: var(--muted); }
.pl-btn.is-flash { border-color: var(--accent); color: var(--accent); }
.pl-copyall { background: var(--bg); }

@media (max-width: 560px) {
  .pl-head__title { font-size: 27px; }
  .pl-card__topic { flex-basis: 100%; order: 3; }
}

/* ── Essays (/essays) — reuses the docs three-column shell; only the dated byline
      under the title is essay-specific. ── */
.esy-byline { font-size: 13.5px; margin: 0 0 14px; letter-spacing: 0.01em; }
.esy-byline time { white-space: nowrap; }

/* ── Legal / contact pages ── */
.legal { max-width: 760px; margin: 0 auto; line-height: 1.65; }
.legal--narrow { max-width: 620px; }
.legal__head { padding: 8px 0 28px; border-bottom: 1px solid var(--border); margin-bottom: 24px; }
.legal__head h1 { font-size: 38px; margin: 0 0 6px; }
.legal__intro { font-size: 17px; }
.legal__section { margin: 28px 0; }
.legal__section h2 { font-size: 21px; margin: 0 0 10px; }
.legal__section ul { padding-left: 22px; display: flex; flex-direction: column; gap: 7px; }
.legal__section li { line-height: 1.55; }
.contact-email {
  display: flex; align-items: center; gap: 10px; font-size: 20px; margin: 18px 0 28px;
}
.contact-email .icon { color: var(--accent); width: 22px; height: 22px; }

/* ── Public responsive ── */
@media (max-width: 760px) {
  .land-hero__title { font-size: 38px; }
  .land-hero__lede { font-size: 18px; }
  .land-plans { grid-template-columns: 1fr; }
  .land-section { padding: 36px 0; }
  .land-section--alt { padding: 32px 22px; }
  .land-section h2 { font-size: 25px; }
  .legal__head h1 { font-size: 30px; }
}

/* ── Admin / ops dashboard (/admin) ── */
.adm { max-width: 980px; margin: 0 auto; padding: 8px 0 40px; }
.adm-head { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; margin-bottom: 24px; }
.adm-head h1 { font-family: var(--font-display); font-weight: 800; font-size: 26px; margin: 0; }
.adm-back { color: var(--muted); text-decoration: none; font-size: 14px; }
.adm-back:hover { color: var(--accent); }
.adm-counts { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; margin-bottom: 22px; }
.adm-stat {
  background: var(--surface); border: 1px solid var(--border); border-radius: 14px;
  padding: 16px 18px; display: flex; flex-direction: column; gap: 2px;
}
.adm-num { font-family: var(--font-display); font-weight: 800; font-size: 28px; letter-spacing: -0.02em; }
.adm-lbl { color: var(--muted); font-size: 13px; }
.adm-note {
  background: color-mix(in srgb, var(--accent) 7%, var(--surface));
  border: 1px solid color-mix(in srgb, var(--accent) 20%, var(--border));
  border-radius: 12px; padding: 14px 16px; font-size: 14px; line-height: 1.55; color: var(--muted);
  margin: 0 0 26px;
}
.adm-note strong { color: var(--ink); }
.adm-window { margin-bottom: 28px; }
.adm-window-head { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; flex-wrap: wrap; margin-bottom: 10px; }
.adm-window-head h2 { font-size: 18px; margin: 0; }
.adm-headline { display: flex; gap: 16px; align-items: baseline; flex-wrap: wrap; }
.adm-cost { font-family: var(--font-display); font-weight: 800; font-size: 22px; color: var(--accent); }
.adm-hit { font-weight: 700; font-size: 14px; }
.adm-turns { color: var(--muted); font-size: 14px; }
.adm-table { width: 100%; border-collapse: collapse; font-size: 13.5px; }
.adm-table th, .adm-table td {
  text-align: right; padding: 8px 10px; border-bottom: 1px solid var(--border); white-space: nowrap;
}
.adm-table th { color: var(--muted); font-weight: 600; font-size: 12px; }
.adm-table th:first-child, .adm-table td:first-child { text-align: left; }
.adm-model { font-family: var(--font-mono, ui-monospace, monospace); }
.adm-tools-cell {
  font-family: var(--font-mono, ui-monospace, monospace); font-size: 12px; color: var(--muted); text-align: left;
  /* Cap the width so a tool-heavy turn can't blow the table wide; overflow ellipsizes
     (the cell still inherits white-space:nowrap), full list on hover via the title attr. */
  max-width: 240px; overflow: hidden; text-overflow: ellipsis;
}
.adm-cell-cost { font-weight: 700; }
.adm-empty { color: var(--muted); font-size: 14px; }
@media (max-width: 760px) {
  .adm-counts { grid-template-columns: repeat(2, 1fr); }
  .adm-table { display: block; overflow-x: auto; }
}

/* ── Private context inspector (admin-only; routes/admin.js → views/admin/context.hbs) ── */
.adm-nav { display: flex; gap: 4px; margin-bottom: 18px; border-bottom: 1px solid var(--border); }
.adm-nav-link {
  text-decoration: none; color: var(--muted); font-size: 14px; font-weight: 600;
  padding: 8px 14px; border-bottom: 2px solid transparent; margin-bottom: -1px;
}
.adm-nav-link:hover { color: var(--ink); }
.adm-nav-link.is-active { color: var(--accent); border-bottom-color: var(--accent); }
.ictx-picker { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 22px; }
/* The family member sub-picker — a tier below the agent picker, set off with an accent rail. */
.ictx-members { margin-top: -10px; margin-bottom: 14px; padding-left: 12px; border-left: 3px solid color-mix(in srgb, var(--accent) 45%, var(--border)); }
.ictx-members .ictx-pick { padding: 6px 10px; font-size: 13px; }
.ictx-pick {
  display: flex; flex-direction: column; gap: 1px; text-decoration: none;
  background: var(--surface); border: 1px solid var(--border); border-radius: 10px;
  padding: 8px 12px; color: var(--ink); font-size: 14px;
}
.ictx-pick:hover { border-color: var(--accent); }
.ictx-pick.is-active { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 9%, var(--surface)); }
.ictx-pick-name { font-weight: 700; }
.ictx-pick-meta { color: var(--muted); font-size: 12px; font-family: var(--font-mono, ui-monospace, monospace); }
.ictx-stats { display: grid; grid-template-columns: repeat(5, 1fr); gap: 12px; margin-bottom: 22px; }
.ictx-stats .adm-num { font-size: 18px; }
.ictx-block { margin-bottom: 28px; }
.ictx-block > h2 { font-size: 18px; margin: 0 0 4px; }
.ictx-hint { color: var(--muted); font-size: 13px; line-height: 1.5; margin: 0 0 12px; }
.ictx-chars { color: var(--muted); font-size: 12px; font-weight: 400; font-family: var(--font-mono, ui-monospace, monospace); }
.ictx-sec {
  border: 1px solid var(--border); border-radius: 10px; margin-bottom: 8px; background: var(--surface);
}
.ictx-sec > summary {
  cursor: pointer; padding: 10px 14px; font-weight: 600; list-style: none;
  display: flex; justify-content: space-between; align-items: baseline; gap: 12px;
}
.ictx-sec > summary::-webkit-details-marker { display: none; }
.ictx-sec[open] > summary { border-bottom: 1px solid var(--border); }
.ictx-sec .ictx-hint { padding: 10px 14px 0; }
.ictx-pre {
  margin: 0; padding: 12px 14px; white-space: pre-wrap; word-break: break-word;
  font-family: var(--font-mono, ui-monospace, monospace); font-size: 12.5px; line-height: 1.5;
  color: var(--ink); overflow-x: auto;
}
.ictx-msg { border: 1px solid var(--border); border-radius: 10px; margin-bottom: 8px; background: var(--surface); }
.ictx-msg-role {
  padding: 6px 14px; font-size: 12px; font-weight: 700; color: var(--muted);
  text-transform: uppercase; letter-spacing: 0.04em; border-bottom: 1px solid var(--border);
}
.ictx-msg-user .ictx-msg-role { color: var(--accent); }
.ictx-recon { border: 1px solid var(--border); border-radius: 12px; background: var(--surface); padding: 16px 18px; }
.ictx-recon-tbl { width: 100%; border-collapse: collapse; font-size: 14px; }
.ictx-recon-tbl td { padding: 9px 4px; border-bottom: 1px solid var(--border); color: var(--ink); }
.ictx-recon-tbl tbody tr:last-child td { border-bottom: 0; }
.ictx-recon-tbl tfoot td { padding-top: 12px; border-top: 2px solid var(--border); border-bottom: 0; font-size: 15px; }
.ictx-recon-tbl .ictx-num {
  text-align: right; font-family: var(--font-mono, ui-monospace, monospace);
  font-variant-numeric: tabular-nums; white-space: nowrap; width: 1%;
}
@media (max-width: 760px) { .ictx-stats { grid-template-columns: repeat(2, 1fr); } }

/* ── Usage & cost (/app/usage) — the human-facing cost report ──────────────────
   Reuses the .settings shell (container width, .settings-section cards, .settings-head).
   Tabular figures everywhere so dollar amounts align and don't jitter. */
.usage { display: flex; flex-direction: column; gap: 18px; }

/* Hero — the lifetime headline. A soft accent-tinted card so the big number sings. */
.usage-hero {
  background: linear-gradient(135deg,
    color-mix(in srgb, var(--accent) 10%, var(--surface)),
    var(--surface) 70%);
  border: 1px solid color-mix(in srgb, var(--accent) 22%, var(--border));
  border-radius: 20px; padding: 28px 24px;
  display: flex; flex-direction: column; gap: 10px;
}
.usage-hero__num {
  font-family: "Baloo 2", system-ui, sans-serif; font-weight: 700;
  font-size: clamp(40px, 9vw, 56px); line-height: 1; color: var(--ink);
  font-variant-numeric: tabular-nums; letter-spacing: -0.02em;
}
.usage-hero__meta {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
  font-size: 15px; color: var(--muted);
}
.usage-hero__meta strong { color: var(--ink); font-variant-numeric: tabular-nums; }
.usage-hero__dot { opacity: 0.5; }
.usage-hero__note {
  display: flex; align-items: flex-start; gap: 8px; margin: 6px 0 0;
  font-size: 13px; color: var(--muted); line-height: 1.5;
}
.usage-hero__note .icon { flex: none; width: 16px; height: 16px; margin-top: 1px; opacity: 0.8; }
.usage-hero--empty { align-items: flex-start; }
.usage-empty { margin: 4px 0 0; color: var(--muted); font-size: 15px; line-height: 1.55; max-width: 52ch; }

/* Rolling windows — three equal stat cards (24h / 7d / 30d). */
.usage-windows { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
.usage-stat {
  background: var(--surface); border: 1px solid var(--border); border-radius: 16px;
  padding: 16px 18px; display: flex; flex-direction: column; gap: 4px;
}
.usage-stat__label { font-size: 12px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.04em; }
.usage-stat__cost { font-size: 26px; font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums; letter-spacing: -0.01em; }
.usage-stat__sub { font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; }
.usage-stat--empty .usage-stat__cost { color: var(--muted); opacity: 0.6; }

/* By agent — a row per agent: face · name+model · total+per-message. */
.usage-agents { display: flex; flex-direction: column; gap: 8px; }
.usage-agent {
  display: flex; align-items: center; gap: 14px;
  padding: 12px 14px; border: 1px solid var(--border); border-radius: 14px; background: var(--bg);
}
.usage-agent__face { font-size: 26px; line-height: 1; flex: none; }
.usage-agent__id { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1; }
.usage-agent__name { font-weight: 600; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.usage-agent__model {
  align-self: flex-start; font-size: 11px; font-weight: 600; color: var(--muted);
  background: var(--surface); border: 1px solid var(--border); border-radius: 999px; padding: 1px 9px;
}
.usage-agent__nums { display: flex; flex-direction: column; align-items: flex-end; gap: 2px; flex: none; text-align: right; }
.usage-agent__total { font-size: 18px; font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums; }
.usage-agent__sub { font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; }

/* Recent feed — one slim row per turn: when · model · activity tags · cost. */
.usage-feed { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.usage-feed__row {
  display: grid; grid-template-columns: 72px auto 1fr auto; align-items: center; gap: 12px;
  padding: 11px 4px; border-bottom: 1px solid var(--border); font-size: 14px;
}
.usage-feed__row:last-child { border-bottom: none; }
.usage-feed__when { color: var(--muted); font-size: 12px; font-variant-numeric: tabular-nums; }
.usage-feed__agent { display: flex; align-items: center; gap: 6px; min-width: 0; }
.usage-feed__face { font-size: 18px; line-height: 1; }
.usage-feed__model { font-size: 12px; color: var(--muted); font-weight: 600; }
.usage-feed__act { display: flex; flex-wrap: wrap; gap: 5px; min-width: 0; }
.usage-feed__chat { color: var(--muted); font-size: 12px; font-style: italic; opacity: 0.7; }
.usage-feed__cost { font-weight: 600; color: var(--ink); font-variant-numeric: tabular-nums; text-align: right; }
.usage-tag {
  font-size: 11px; font-weight: 600; color: var(--accent);
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  border-radius: 999px; padding: 2px 9px; white-space: nowrap;
}
.usage-tag--reach { color: var(--muted); background: var(--border); }

/* By-agent filter chips — scope the hero/windows/feed to one agent. */
.usage-filter { display: flex; flex-wrap: wrap; gap: 8px; }
.usage-chip {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 13px; font-weight: 600; color: var(--muted); text-decoration: none;
  background: var(--surface); border: 1px solid var(--border); border-radius: 999px; padding: 6px 13px;
  transition: background 0.12s, color 0.12s, border-color 0.12s;
}
.usage-chip:hover { color: var(--ink); border-color: color-mix(in srgb, var(--accent) 40%, var(--border)); }
.usage-chip--on {
  color: var(--accent); border-color: color-mix(in srgb, var(--accent) 45%, var(--border));
  background: color-mix(in srgb, var(--accent) 12%, transparent);
}

/* Feed row as a link → the per-turn drill-down. A trailing chevron + hover wash; the grid gains
   a chevron column on top of the base .usage-feed__row layout. */
.usage-feed__row--link {
  text-decoration: none; color: inherit; border-radius: 10px;
  grid-template-columns: 72px auto 1fr auto 16px;
  transition: background 0.12s;
}
.usage-feed__row--link:hover { background: color-mix(in srgb, var(--accent) 7%, transparent); }
.usage-feed__chev { color: var(--muted); opacity: 0.5; display: inline-flex; }
.usage-feed__chev .icon { width: 16px; height: 16px; }

/* ── Per-turn drill-down (usage-turn.hbs) ─────────────────────────────────────── */
.usage-back {
  display: inline-flex; align-items: center; gap: 7px; align-self: flex-start;
  font-size: 14px; font-weight: 600; color: var(--muted); text-decoration: none;
}
.usage-back:hover { color: var(--ink); }
.usage-back .icon { width: 16px; height: 16px; }

.usage-turn-head { display: flex; align-items: center; gap: 14px; }
.usage-turn-head__id { min-width: 0; }
.usage-turn-head .settings-title {
  display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap;
  font-variant-numeric: tabular-nums;
}
.usage-turn-head__model {
  font-family: system-ui, sans-serif; font-size: 12px; font-weight: 600; color: var(--muted);
  background: var(--surface); border: 1px solid var(--border); border-radius: 999px; padding: 2px 10px;
  letter-spacing: 0;
}

.usage-why {
  display: flex; align-items: flex-start; gap: 9px; margin: 0;
  background: color-mix(in srgb, var(--accent) 8%, var(--surface));
  border: 1px solid color-mix(in srgb, var(--accent) 20%, var(--border)); border-radius: 14px;
  padding: 13px 15px; font-size: 14px; color: var(--ink); line-height: 1.5;
}
.usage-why .icon { flex: none; width: 17px; height: 17px; margin-top: 1px; color: var(--accent); }

/* Cost breakdown — one row per priced component: label · bar · tokens · cost. */
.usage-bd { list-style: none; margin: 6px 0 0; padding: 0; display: flex; flex-direction: column; gap: 16px; }
/* Stacked: the full label sits on its own line (no truncation), with the bar · tokens · cost
   beneath it. */
.usage-bd__row {
  display: grid; grid-template-columns: 1fr auto auto;
  grid-template-areas:
    "label label label"
    "bar   tok   cost";
  align-items: center; gap: 7px 14px; font-size: 14px;
}
.usage-bd__label { grid-area: label; color: var(--ink); line-height: 1.35; }
.usage-bd__row--top .usage-bd__label { font-weight: 700; }
.usage-bd__bar { grid-area: bar; height: 8px; background: var(--border); border-radius: 999px; overflow: hidden; }
.usage-bd__fill { display: block; height: 100%; background: color-mix(in srgb, var(--accent) 55%, var(--surface)); border-radius: 999px; }
.usage-bd__row--top .usage-bd__fill { background: var(--accent); }
.usage-bd__tok { grid-area: tok; color: var(--muted); font-size: 12px; font-variant-numeric: tabular-nums; text-align: right; }
.usage-bd__cost { grid-area: cost; color: var(--ink); font-weight: 600; font-variant-numeric: tabular-nums; text-align: right; }
/* Bucketed widths (CSP forbids inline style="width:…"; the route picks .uw-N). */
.uw-0 { width: 0; } .uw-10 { width: 10%; } .uw-20 { width: 20%; } .uw-30 { width: 30%; }
.uw-40 { width: 40%; } .uw-50 { width: 50%; } .uw-60 { width: 60%; } .uw-70 { width: 70%; }
.uw-80 { width: 80%; } .uw-90 { width: 90%; } .uw-100 { width: 100%; }

/* Hop ledger — each API round-trip: number · label+activity+tokens · cost. */
.usage-hops { list-style: none; margin: 6px 0 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.usage-hop {
  display: grid; grid-template-columns: 26px 1fr auto; align-items: start; gap: 12px;
  padding: 12px 14px; border: 1px solid var(--border); border-radius: 14px; background: var(--bg);
}
.usage-hop__n {
  width: 24px; height: 24px; border-radius: 999px; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 12px; font-weight: 700; color: var(--muted);
  background: var(--surface); border: 1px solid var(--border); font-variant-numeric: tabular-nums;
}
.usage-hop__body { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.usage-hop__label { font-weight: 600; color: var(--ink); font-size: 14px; }
.usage-hop__act { display: flex; flex-wrap: wrap; gap: 5px; }
.usage-hop__tok { font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; }
.usage-hop__note {
  display: flex; align-items: flex-start; gap: 7px; margin-top: 3px;
  font-size: 12.5px; color: var(--muted); line-height: 1.45;
  border-left: 2px solid color-mix(in srgb, var(--accent) 35%, var(--border)); padding-left: 9px;
}
.usage-hop__note .icon { flex: none; width: 14px; height: 14px; margin-top: 2px; color: var(--accent); }
.usage-hop__cost { font-weight: 600; color: var(--ink); font-variant-numeric: tabular-nums; }
.usage-hop--corrective .usage-hop__label { color: var(--muted); }

/* Action-timeline fallback (turns without a hop ledger). */
.usage-timeline { list-style: none; margin: 6px 0 0; padding: 0; display: flex; flex-direction: column; gap: 7px; }
.usage-timeline li {
  font-size: 14px; color: var(--ink); padding: 9px 13px;
  border: 1px solid var(--border); border-radius: 12px; background: var(--bg);
}

@media (max-width: 760px) {
  .usage-windows { grid-template-columns: 1fr; }
  /* Feed row → two lines: [when | model | cost] on top, the activity chips below. Every cell is
     placed EXPLICITLY so the cost stays top-right — relying on auto-flow (with act spanning 2/-1)
     bumped the cost onto its own left-aligned line. */
  .usage-feed__row, .usage-feed__row--link {
    grid-template-columns: 56px 1fr auto; column-gap: 10px; row-gap: 2px;
  }
  .usage-feed__when { grid-column: 1; grid-row: 1; }
  .usage-feed__agent  { grid-column: 2; grid-row: 1; }
  .usage-feed__cost { grid-column: 3; grid-row: 1; }
  .usage-feed__act  { grid-column: 2 / -1; grid-row: 2; }
  .usage-feed__chev { display: none; }
  /* Agents table: tighten cell + control padding and pull the edge columns flush so all
     columns (incl. the trash) fit INSIDE the card instead of spilling past its right border. */
  .agent-table th, .agent-table td { padding: 10px 5px; }
  .agent-table th:first-child, .agent-table td:first-child { padding-left: 0; }
  .agent-th-del, .agent-cell-del { padding-right: 0; }
  .agent-select { padding: 6px 7px; }
}

/* Narrow phones: a 4-column table can't fit, so STACK each agent into its own card — nothing
   can spill past the section border. Headers are hidden, so each control cell shows its label
   via data-label (set in account.hbs), and the trash tucks into the card's top-right. */
@media (max-width: 600px) {
  .agent-table, .agent-table tbody { display: block; }
  .agent-table thead { display: none; }
  /* Each agent is a card, laid out as a 2-col grid: [name | trash] on the first row, then each
     labeled control spanning the full width below. The trash lives in a real grid column, so
     it stays INSIDE the card (the earlier absolute-positioned version escaped to the right). */
  .agent-table tr {
    display: grid; grid-template-columns: 1fr auto; align-items: center; column-gap: 10px;
    border: 1px solid var(--border); border-radius: 12px; padding: 12px 14px; margin-bottom: 10px;
  }
  .agent-table th, .agent-table td { display: block; padding: 0; }
  .agent-table th[scope="row"] { grid-column: 1; grid-row: 1; }
  /* width:auto undoes the base `.agent-cell-del { width: 1% }` table-shrink trick — as a grid
     item that 1% meant ~3px, so the 34px trash button overflowed its cell past the card. */
  .agent-cell-del { grid-column: 2; grid-row: 1; justify-self: end; width: auto; }
  .agent-who { font-size: 16px; }
  .agent-table td[data-label] {
    grid-column: 1 / -1; display: flex; align-items: center; justify-content: space-between;
    gap: 12px; margin-top: 10px;
  }
  .agent-table td[data-label]::before {
    content: attr(data-label); font-size: 13px; font-weight: 600; color: var(--muted);
  }
  .agent-table td[data-label] .agent-select { min-width: 140px; }
}

/* ── The family channel feed (FAMILY.md Phase 4/7) ───────────────────────────── */
.channel-wrap { max-width: 720px; margin: 0 auto; width: 100%; padding: 8px 16px 40px; }
.channel-lede { margin: 4px 0 16px; }
.ff-feed { display: flex; flex-direction: column; gap: 10px; }
.ff-post {
  display: flex; align-items: flex-start; gap: 12px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 14px; padding: 14px 16px; line-height: 1.5;
}
.ff-post__emoji { font-size: 20px; line-height: 1.2; flex: 0 0 auto; }
.ff-post__body { flex: 1 1 auto; }
.ff-post--new { animation: ff-post-in .35s ease; }
@keyframes ff-post-in { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
.ff-feed__empty { padding: 24px 4px; }

/* ── The Family dashboard (the household at a glance) ─────────────────────────── */
/* The agent hero — large, full-width, the family's Someone front and centre. It breaks OUT of
   the .tabpane's padding (negative margins matched to it) so the wash bleeds to the column
   edges; the mobile rule re-matches the pane's mobile padding. */
.fam-hero {
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  margin: -28px -24px 28px; padding: 48px 24px 40px; text-align: center;
  background: linear-gradient(180deg, color-mix(in srgb, var(--accent) 9%, var(--bg)), var(--bg));
  border-bottom: 1px solid var(--border);
}
.fam-hero__avatar {
  width: 124px; height: 124px; display: grid; place-items: center;
  font-size: 66px; line-height: 1; border-radius: 50%;
  background: var(--surface); border: 1px solid var(--border);
  box-shadow: 0 6px 22px rgba(0, 0, 0, .06);
}
.fam-hero__name {
  font-family: "Baloo 2", system-ui, sans-serif; font-weight: 700;
  font-size: 32px; line-height: 1.1; margin: 6px 0 0;
}
.fam-hero__sub { margin: 0; font-size: 15px; }

.fam-wrap { width: 100%; }

/* ── Memory tab layout ─────────────────────────────────────────────────────────
   Like the Calendar, a flex ROW: the scrolling content column + the copilot (a bottom drawer on
   mobile). Overrides the base .tabpane max-width/centering the same way #tab-calendar does. */
#tab-memory.memory-page { max-width: none; margin: 0; height: 100dvh; padding: 0; display: flex; flex-direction: row; }
.mem-main { flex: 1 1 auto; min-width: 0; overflow-y: auto; padding: 28px 24px 56px; }
.mem-head { margin: 0 0 22px; }
.mem-title { font-family: "Baloo 2", system-ui, sans-serif; font-weight: 700; font-size: 24px; margin: 0 0 6px; }
.mem-sub { margin: 0; line-height: 1.55; max-width: 62ch; font-size: 14.5px; }
/* "+ Add info" — a quiet accent action (a <button>, so it needs its own reset; .fam-more is an <a>). */
.fam-addbtn {
  background: none; border: 0; padding: 0; cursor: pointer; font-family: inherit;
  font-size: 13px; font-weight: 600; color: var(--accent); white-space: nowrap;
}
.fam-addbtn:hover { text-decoration: underline; }
@media (max-width: 879px) {
  #tab-memory.memory-page { height: 100dvh; padding: var(--mtop-h) 0 0; flex-direction: column; }
  .mem-main { padding: 16px 16px calc(var(--tabbar-h) + 72px + env(safe-area-inset-bottom)); }
}

/* The scoreboard — a fun row of deterministic counters. */
.fam-stats {
  display: grid; gap: 10px;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  margin-bottom: 28px;
}
.fam-stat {
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 16px; padding: 16px 10px; text-align: center;
}
.fam-stat__emoji { font-size: 22px; line-height: 1; margin-bottom: 4px; }
.fam-stat__value {
  font-family: "Baloo 2", system-ui, sans-serif; font-weight: 700;
  font-size: 28px; line-height: 1; color: var(--accent);
}
.fam-stat__label { font-size: 12px; color: var(--muted); letter-spacing: .01em; }

.fam-section { margin-bottom: 28px; }
.fam-h {
  font-family: "Baloo 2", system-ui, sans-serif; font-weight: 600;
  font-size: 17px; margin: 0 0 12px;
}
.fam-h-row { display: flex; align-items: baseline; justify-content: space-between; margin-bottom: 12px; }
.fam-h-row .fam-h { margin: 0; }
.fam-more { font-size: 13px; color: var(--accent); font-weight: 600; white-space: nowrap; }

/* Who's here — the roster. */
.fam-roster {
  display: grid; gap: 10px;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
}
.fam-member {
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 16px; padding: 18px 12px; text-align: center;
}
.fam-member--owner { border-color: var(--accent); }
.fam-member__avatar { font-size: 34px; line-height: 1; }
.fam-member__name { font-weight: 600; }
.fam-member__role { line-height: 1.3; }

/* Coming up / Made together — list rows (share the ff-post look). NOTE: named .fam-item* NOT
   .fam-row* — the Settings "Family agents" disclosure already owns .fam-row (a <details>), and a
   shared name leaked this card's display:flex onto it. Keep the two surfaces' classes disjoint. */
.fam-list { display: flex; flex-direction: column; gap: 10px; }
.fam-item {
  display: flex; align-items: flex-start; gap: 12px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 14px; padding: 14px 16px; line-height: 1.5;
}
.fam-item__emoji { font-size: 20px; line-height: 1.2; flex: 0 0 auto; }
.fam-item__main { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.fam-item__title { font-weight: 500; }
.fam-item__meta { line-height: 1.3; }
.fam-item--link { text-decoration: none; color: inherit; transition: border-color .15s ease, transform .1s ease; }
.fam-item--link:hover { border-color: var(--accent); transform: translateY(-1px); }
.fam-empty { padding: 8px 2px; }

/* What Dustav knows — the household facts KB, read-only with an owner-only ✕ forget. */
.fam-facts { display: flex; flex-direction: column; gap: 8px; }
.fam-fact {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 12px; border: 1px solid var(--border); border-radius: 12px; background: var(--surface);
}
.fam-fact__text { flex: 1; font-size: 14px; line-height: 1.45; color: var(--ink); }
.fam-fact__forget {
  flex: none; display: grid; place-items: center; width: 28px; height: 28px; padding: 0;
  border: none; border-radius: 999px; background: transparent; color: var(--muted); cursor: pointer;
}
.fam-fact__forget:hover { background: color-mix(in srgb, var(--error) 12%, transparent); color: var(--error); }
.fam-fact__forget svg { width: 15px; height: 15px; }
.fam-fact__forget:disabled { opacity: .4; cursor: default; }
.fam-facts__note { margin-top: 10px; }

/* ── Onboarding mode knob ([Just me] / [My family]) ──────────────────────────── */
.onb-choose { max-width: 540px; margin: 0 auto; padding: 32px 16px; text-align: center; }
.onb-choose__face { font-size: 40px; line-height: 1; }
.onb-choose__title { margin: 14px 0 4px; }
.onb-choose__lede { margin: 0 0 26px; }
.onb-choose__opts { display: flex; gap: 14px; justify-content: center; flex-wrap: wrap; }
.onb-choose__opt {
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  flex: 1 1 180px; max-width: 220px; padding: 22px 18px; text-decoration: none;
  background: var(--surface); border: 1px solid var(--border); border-radius: 16px; color: var(--ink);
  transition: border-color .15s ease, transform .1s ease;
}
.onb-choose__opt:hover { border-color: var(--accent); transform: translateY(-2px); }
.onb-choose__emoji { font-size: 30px; line-height: 1; }
.onb-choose__label { font-weight: 700; font-size: 17px; }

/* ── Family settings (code + PINs + add/invite) ──────────────────────────────── */
.fam-code { display: flex; align-items: center; gap: 12px; margin: 6px 0 16px; }
.fam-code__label { font-weight: 600; color: var(--muted); font-size: 14px; }
.fam-code__value { font-size: 20px; font-weight: 700; letter-spacing: 2px; background: var(--surface); border: 1px solid var(--border); border-radius: 8px; padding: 6px 12px; }
.fam-form { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 12px; align-items: center; }
.fam-form .ff-input { flex: 1 1 160px; min-width: 0; }
.fam-form__pin { flex: 0 1 130px; }

/* Family agents — one expandable <details> row per household (multi-family). */
.fam-row { border: 1px solid var(--border); border-radius: 12px; margin: 10px 0; background: var(--surface); overflow: hidden; }
.fam-row__head { display: flex; align-items: center; gap: 10px; padding: 12px 14px; cursor: pointer; list-style: none; }
.fam-row__head::-webkit-details-marker { display: none; }
.fam-row__head::after { content: "\203A"; margin-left: auto; transform: rotate(90deg); transition: transform .15s ease; color: var(--muted); font-size: 20px; line-height: 1; }
.fam-row[open] > .fam-row__head::after { transform: rotate(270deg); }
.fam-row__name { font-weight: 700; }
.fam-row__body { padding: 0 14px 14px; }
