/* Homestead web client. One file, no build step. Sections: tokens · base · controls · layout ·
 * sidebar · thread · composer · cards · settings · preview · phones. */

/* ---- Tokens ------------------------------------------------------------- */
/* Two themes share every rule below; only the colour roles differ. <html data-theme> is set by
 * theme.js before first paint (saved choice, else the system preference) and by the sidebar toggle. */
:root {
  color-scheme: light;
  --bg: #f6f5f1;
  --surface: #ffffff;
  --surface-2: #efede7;
  --border: #e3e1da;
  --text: #1d1d1b;
  --text-2: #6b6a66;
  --primary: #2b5bd7;
  --primary-hover: #2450c0;
  --primary-dim: rgba(43,91,215,0.07);
  --on-primary: #ffffff;
  --attention: #8f5d12;
  --attention-bg: #fdf6e7;
  --attention-glow: 0 0 0 transparent;
  --danger: #b4231f;
  --danger-bg: #fdf2f1;
  --danger-border: #f1cfcd;
  --hover: rgba(0,0,0,0.04);
  --border-strong: #d3d0c7;
  --control-shadow: 0 1px 1px rgba(60,50,30,0.06);
  --code-bg: rgba(0,0,0,0.04);
  --skeleton-a: #ebe8e1;
  --skeleton-b: #f3f1ec;
  --scrim: rgba(0,0,0,0.35);
  /* Raised surfaces: a soft ambient shadow in light; in dark, a hairline of light along the top edge instead. */
  --elevation: 0 1px 2px rgba(60,50,30,0.05), 0 12px 32px -16px rgba(60,50,30,0.12);

  --fs-1: 0.75rem;
  --fs-2: 0.8rem;
  --fs-3: 0.875rem;
  --fs-4: 1rem;
  --fs-5: 1.05rem;

  --s-1: 0.25rem;
  --s-2: 0.5rem;
  --s-3: 0.75rem;
  --s-4: 1rem;
  --s-5: 1.25rem;
  --s-6: 2rem;

  --r-s: 3px;
  --r-m: 4px;
  --r-l: 5px;
  --r-pill: 999px;

  --font-mono: ui-monospace, "SF Mono", Menlo, "JetBrains Mono", Consolas, monospace;
  /* Built-in easings are too soft; these two start fast and settle firmly. */
  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);
  --ease-drawer: cubic-bezier(0.32, 0.72, 0, 1);
  font-family: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  font-size: 15px;
  line-height: 1.45;
  color: var(--text);
}
/* Dark: a quiet console. Near-black layers, one phosphor-green accent; amber and red keep their jobs. */
[data-theme="dark"] {
  color-scheme: dark;
  --bg: #0c0e12;
  --surface: #12151b;
  --surface-2: #1a1e26;
  --border: rgba(255,255,255,0.09);
  --text: #e6e8ec;
  --text-2: #8b93a1;
  --primary: #3ddc97;
  --primary-hover: #5ae8ab;
  --primary-dim: rgba(61,220,151,0.10);
  --on-primary: #06210f;
  --attention: #f2b134;
  --attention-bg: rgba(242,177,52,0.10);
  --attention-glow: 0 0 24px -8px var(--attention);
  --danger: #ff5d5d;
  --danger-bg: rgba(255,93,93,0.10);
  --danger-border: rgba(255,93,93,0.35);
  --hover: rgba(255,255,255,0.05);
  --border-strong: rgba(255,255,255,0.16);
  --control-shadow: inset 0 1px 0 rgba(255,255,255,0.08);
  --code-bg: #0c0e12;
  --skeleton-a: #1a1e26;
  --skeleton-b: #22272f;
  --scrim: rgba(0,0,0,0.6);
  --elevation: inset 0 1px 0 rgba(255,255,255,0.04);
}

/* ---- Base ---------------------------------------------------------------- */
* { box-sizing: border-box; }
:root { font-variant-numeric: tabular-nums; }
h1, h2, legend, p, .msg .text, summary { text-wrap: pretty; }
html, body { margin: 0; height: 100%; background: var(--bg); }
/* While a theme change lands (app.js sets .theming for 200 ms), colours cross-fade instead of jumping. */
html.theming, html.theming * { transition: background-color 200ms ease, color 200ms ease, border-color 200ms ease; }
.hidden { display: none !important; }
.muted { color: var(--text-2); }
.small { font-size: var(--fs-2); }
.error { color: var(--danger); min-height: 1.2em; margin: var(--s-2) 0 0; font-size: 0.9rem; }
.row { display: flex; gap: var(--s-2); align-items: center; margin-top: 0.6rem; }
.spacer { flex: 1; }
.card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-l); padding: var(--s-5); box-shadow: var(--elevation); }
/* Machine text — what the Bot's computer produced or the system recorded — is monospace; what a person
 * reads as prose stays in the sans. Badges carry a state glyph: ○ idle, ● active, ◆ needs you. */
.badge { font-family: var(--font-mono); font-size: var(--fs-1); padding: 0.15rem var(--s-2); border-radius: var(--r-s); border: 1px solid var(--border); color: var(--text-2); white-space: nowrap; }
.badge::before { content: "○ "; }
.badge.active::before { content: "● "; }
.badge.needs::before { content: "◆ "; }
.badge.active { border-color: var(--primary); color: var(--primary); }
.badge.bad { border-color: var(--danger); color: var(--danger); }
.badge.needs { border-color: var(--attention); color: var(--attention); background: var(--attention-bg); font-weight: 600; }

/* ---- Controls ------------------------------------------------------------ */
/* Three weights: primary (filled with the accent; the one action that moves the thread forward — Send, Create,
 * Save, Approve), secondary (neutral, on a surface with a firm border; alternatives and navigation), tertiary
 * (text; dismiss, back, housekeeping). The accent is spent on primary only, so it still means something. */
button, .file-label, .button-link {
  font: inherit; font-size: var(--fs-3); font-weight: 500; line-height: 1.25; border: 1px solid var(--primary); background: var(--primary); color: var(--on-primary);
  border-radius: var(--r-m); padding: 0.45rem 0.85rem; cursor: pointer; text-decoration: none; box-shadow: var(--control-shadow);
}
button.secondary, .file-label, .button-link { background: var(--surface); color: var(--text); border-color: var(--border-strong); }
.button-link.primary { background: var(--primary); color: var(--on-primary); border-color: var(--primary); display: inline-block; }
button.tertiary { background: transparent; color: var(--text-2); border-color: transparent; box-shadow: none; }
button.danger { color: var(--danger); border-color: var(--danger-border); }
button.tertiary.danger { border-color: transparent; }
button.small, .button-link.small { padding: 0.25rem 0.6rem; font-size: var(--fs-2); }
button:disabled { opacity: 0.5; cursor: default; box-shadow: none; }
/* Feedback lives on the press, not on the server's reply. */
button, .file-label, .button-link { transition: transform 120ms var(--ease-out), background-color 120ms ease, border-color 120ms ease, color 120ms ease; }
button:active:not(:disabled), .file-label:active, .button-link:active { transform: scale(0.97); }
.bot-list button:active, .msg.examples .example:active { transform: none; background: var(--surface-2); } /* full-width rows darken instead of shrinking */
/* Hover only where a pointer can hover; on touch it would stick to whatever was last tapped. */
@media (hover: hover) and (pointer: fine) {
  button.tertiary:hover { color: var(--text); background: var(--hover); }
  button:not(.secondary):not(.tertiary):not(:disabled):hover { background: var(--primary-hover); border-color: var(--primary-hover); }
  button.secondary:not(:disabled):hover, .file-label:hover, .button-link:not(.primary):hover { background: var(--surface-2); border-color: var(--text-2); }
  .button-link.primary:hover { background: var(--primary-hover); border-color: var(--primary-hover); }
  button.danger:not(:disabled):hover { background: var(--danger-bg); border-color: var(--danger); }
  .bot-list button:hover { background: var(--hover); }
  .menu-item:not(:disabled):hover, .icon-button:hover { background: var(--hover); color: var(--text); }
  .msg.examples .example:hover { border-color: var(--primary); background: var(--surface); }
}
:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }
input:focus-visible, textarea:focus-visible, select:focus-visible { outline-offset: 0; border-color: var(--primary); }
.composer textarea { transition: opacity 150ms ease; }
.composer.sending textarea { opacity: 0.6; }
.button-link { display: inline-block; }
/* Inputs sit on the page colour, a step below the surface that holds them; the border alone was too faint in dark. */
input, textarea, select { font: inherit; width: 100%; padding: var(--s-2) 0.6rem; border: 1px solid var(--border); border-radius: var(--r-m); background: var(--bg); color: var(--text); }
input[type=checkbox] { width: auto; margin: 0 0.35rem 0 0; vertical-align: -0.1em; }
label { display: block; margin: 0.6rem 0 0; font-size: 0.9rem; }
label > input, label > select, label > textarea { margin-top: var(--s-1); }

/* ---- Layout -------------------------------------------------------------- */
.app { display: grid; grid-template-columns: 260px 1fr; height: 100%; }
.main { display: flex; flex-direction: column; min-height: 0; min-width: 0; }
.topbar { display: none; }
.empty { display: grid; place-items: center; flex: 1; color: var(--text-2); }
/* The scrim shares the sidebar's timeline: it fades in and out with the panel instead of popping. */
.backdrop { position: fixed; inset: 0; background: var(--scrim); z-index: 9; opacity: 0; visibility: hidden; transition: opacity 160ms var(--ease-drawer), visibility 160ms; }
.backdrop.open { opacity: 1; visibility: visible; transition-duration: 220ms; }

/* Sign-in. */
/* The one low-density screen: a faint glow behind the card, and the card sits in a tray (the ring shadows draw
 * the shell's fill and hairline concentric with the card's radius, no extra element). */
.login { grid-column: 1 / -1; display: grid; place-items: center; padding: var(--s-4); background: radial-gradient(60% 50% at 50% 40%, var(--primary-dim), transparent 70%); }
.login .card { width: min(420px, 100%); box-shadow: 0 0 0 6px var(--surface-2), 0 0 0 7px var(--border), 0 32px 64px -40px rgba(0,0,0,0.35); }
.login h1 { margin: 0 0 var(--s-2); font-family: var(--font-mono); font-size: 2.4rem; line-height: 1.1; letter-spacing: -0.03em; }
/* The login wordmark ends in a blinking cursor; the phone topbar's stays still (it is on screen all day). */
.login h1::after, .topbar .wordmark::after { content: "_"; color: var(--primary); }
.login h1::after { animation: blink 1.1s steps(1) infinite; }
@keyframes blink { 50% { opacity: 0; } }
.login #login-lead { margin: var(--s-1) 0 0; }
.operator-signin { margin-top: var(--s-4); border-top: 1px solid var(--border); padding-top: var(--s-3); }
.operator-signin summary { cursor: pointer; color: var(--text-2); font-size: 0.9rem; }
.operator-signin button { margin-top: var(--s-3); }

/* ---- Sidebar ------------------------------------------------------------- */
.sidebar { border-right: 1px solid var(--border); background: var(--surface); display: flex; flex-direction: column; min-height: 0; }
.sidebar-head { display: flex; justify-content: space-between; align-items: center; padding: 0.7rem var(--s-4); border-bottom: 1px solid var(--border); }
.sidebar-head .row { margin: 0; }
/* The account-and-display menu: a ⋯ button in the sidebar head opens a small panel anchored to it (native <details>;
 * app.js closes it on an outside click). Housekeeping lives here rather than in a footer of loose text links. */
.icon-button { display: grid; place-items: center; width: 28px; height: 28px; border-radius: var(--r-m); color: var(--text-2); cursor: pointer; list-style: none; font-size: 1.1rem; line-height: 1; user-select: none; }
.icon-button::-webkit-details-marker { display: none; }
.menu { position: relative; }
.menu[open] > .icon-button { background: var(--surface-2); color: var(--text); }
.menu-panel { position: absolute; right: 0; top: calc(100% + 4px); z-index: 8; min-width: 200px; padding: var(--s-1); background: var(--surface); border: 1px solid var(--border-strong); border-radius: var(--r-l); box-shadow: var(--elevation), 0 12px 32px -12px rgba(0,0,0,0.25); display: flex; flex-direction: column; transform-origin: top right; }
.menu[open] .menu-panel { opacity: 1; transform: scale(1); transition: opacity 150ms var(--ease-out), transform 150ms var(--ease-out); }
@starting-style { .menu[open] .menu-panel { opacity: 0; transform: scale(0.96); } }
.menu-panel hr { border: 0; border-top: 1px solid var(--border); margin: var(--s-1) 0; }
.menu-item { display: flex; align-items: center; gap: var(--s-2); width: 100%; margin: 0; padding: 0.45rem 0.6rem; text-align: left; font-size: var(--fs-3); font-weight: 400; color: var(--text); background: transparent; border: 0; border-radius: var(--r-s); box-shadow: none; cursor: pointer; }
.menu-item:disabled { color: var(--text-2); opacity: 1; }
.menu-item input[type=checkbox] { margin: 0; }
.sidebar h1 { font-family: var(--font-mono); font-size: var(--fs-3); text-transform: uppercase; letter-spacing: 0.08em; color: var(--text-2); margin: 0; }
/* A Bot row: monogram · name over a mono sub-line · a badge only when there is something to say. */
.bot-list { list-style: none; margin: 0; padding: var(--s-2); overflow-y: auto; display: flex; flex-direction: column; gap: 2px; }
.bot-list button { width: 100%; text-align: left; background: transparent; color: var(--text); border: 0; box-shadow: none; font-size: var(--fs-4); font-weight: 400; padding: 0.45rem 0.6rem; display: grid; grid-auto-flow: dense; grid-template-columns: 28px minmax(0, 1fr) auto; column-gap: var(--s-3); align-items: center; }
.bot-list .mark { grid-column: 1; width: 28px; height: 28px; display: grid; place-items: center; border-radius: var(--r-s); background: var(--surface-2); border: 1px solid var(--border); font-family: var(--font-mono); font-size: var(--fs-1); font-weight: 600; color: var(--text-2); text-transform: uppercase; }
.bot-list .name { grid-column: 2; min-width: 0; }
.bot-list .name, .bot-list .sub { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bot-list .name > .title { display: block; font-weight: 500; }
.bot-list .sub { display: block; font-family: var(--font-mono); font-size: var(--fs-1); color: var(--text-2); margin-top: 0.1rem; }
.bot-list .badge { grid-column: 3; }
.bot-list li.selected button { background: var(--surface-2); }
.bot-list li.selected .mark { background: var(--primary-dim); border-color: transparent; color: var(--primary); }
.bot-list li.archived { opacity: 0.6; }
.bot-list .badge.new { border-color: var(--primary); color: var(--primary); }

/* ---- Thread -------------------------------------------------------------- */
.bot-view { display: flex; flex-direction: column; flex: 1; min-height: 0; }
.bot-head { flex: none; background: var(--surface); border-bottom: 1px solid var(--border); }
.bot-tabs { display: flex; gap: var(--s-3); padding: 0 var(--s-5); overflow-x: auto; }
.bot-tabs button { flex: none; min-height: 44px; border-radius: 0; border: 0; border-bottom: 2px solid transparent; padding: 0 var(--s-3); }
.bot-tabs button[aria-selected=true] { color: var(--text); border-bottom-color: var(--primary); }
.bot-tabs button:active { transform: none; }
.bot-tabs button:focus-visible { outline-offset: -3px; }
.bot-panel { flex: 1; min-height: 0; }
.bot-panel .card { margin: 0 auto; }
.bot-panel .card > :first-child { margin-top: 0; } /* the tab names the panel; no repeated heading */
.bot-panel h3 { margin: 0 0 var(--s-2); font-size: var(--fs-4); }
.thread-view { display: flex; flex-direction: column; flex: 1; min-height: 0; }
.thread-head { display: flex; justify-content: space-between; align-items: center; gap: var(--s-4); padding: 0.9rem var(--s-5); background: var(--surface); }
.thread-head h2 { margin: 0; font-size: var(--fs-5); }
.thread-head p { margin: 0; font-family: var(--font-mono); font-size: var(--fs-2); }
.takeover { margin: var(--s-2) var(--s-4); padding: var(--s-3) var(--s-4); border: 1px solid var(--primary); border-radius: var(--r-l); background: var(--surface); display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-3); }
.takeover p { margin: 0; flex: 1 1 24ch; }
.takeover .actions { display: flex; gap: var(--s-2); }
/* The one-click desktop page (desktop.html): a status bar and the Bot's screen scaled into the rest of the window. Always dark: it frames a screen. */
.desktop-page { display: flex; flex-direction: column; height: 100dvh; background: #0c0e12; color: #e6e8ec; }
.desktop-bar { display: flex; justify-content: space-between; align-items: baseline; gap: var(--s-4); padding: var(--s-2) var(--s-4); font-family: var(--font-mono); font-size: var(--fs-2); border-bottom: 1px solid #262a33; }
.desktop-title { font-weight: 600; }
.desktop-status { color: #8b93a1; }
.desktop-ended .desktop-status { color: #e6e8ec; }
.desktop-screen { flex: 1; min-height: 0; position: relative; }
.desktop-ended .desktop-screen { opacity: 0.35; }

/* On wide screens the thread and composer keep to a centred column (~96ch) instead of stretching edge to edge. */
.messages { list-style: none; margin: 0; padding: var(--s-4) max(var(--s-5), calc((100% - 96ch) / 2)); overflow-y: auto; flex: 1; display: flex; flex-direction: column; gap: var(--s-2); }
.msg { max-width: 72ch; }
/* A message that arrived while the thread was open settles in from 6px below (app.js marks only those). */
.msg.enter { opacity: 1; transform: none; transition: opacity 200ms var(--ease-out), transform 200ms var(--ease-out); }
@starting-style { .msg.enter { opacity: 0; transform: translateY(6px); } }
.msg .text { white-space: pre-wrap; word-wrap: break-word; margin: 0; line-height: 1.5; }
.msg time { display: block; font-family: var(--font-mono); font-size: var(--fs-1); color: var(--text-2); margin-top: 0.3rem; }
.msg .effort { font-family: var(--font-mono); font-size: var(--fs-1); color: var(--text-2); margin: 0.35rem 0 0; }

/* The person's request: a plain block with the accent as a rule on its outer edge, not a filled bubble. */
.msg.request { align-self: flex-end; background: var(--surface-2); border: 1px solid var(--border); border-right: 2px solid var(--primary); border-radius: var(--r-m); padding: 0.6rem 0.85rem; }
.msg.request .chips, .msg.delegation .chips { margin-top: 0.35rem; display: flex; flex-wrap: wrap; gap: 0.3rem; }
.msg.request .chip, .msg.delegation .chip { font-family: var(--font-mono); font-size: var(--fs-1); background: var(--hover); border: 1px solid var(--border); border-radius: var(--r-s); padding: 0.05rem var(--s-2); }
.msg.request time button.small { margin-left: var(--s-2); padding: 0 0.4rem; font-size: var(--fs-1); }

/* A steer: the person's aside to a working Bot; same side as requests, lighter weight. */
.msg.steer { align-self: flex-end; background: transparent; border: 1px dashed var(--border-strong); border-radius: var(--r-m); padding: 0.5rem 0.85rem; }
.msg.bot_text { align-self: flex-start; background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-m); padding: 0.6rem 0.85rem; box-shadow: var(--elevation); }

.msg.examples { align-self: stretch; width: min(60ch, 100%); margin: auto 0; display: flex; flex-direction: column; gap: 0.4rem; color: var(--text-2); } /* centred in the empty thread */
.msg.examples .lead { margin: 0 0 var(--s-1); }
.msg.examples .example { text-align: left; white-space: normal; font-size: 0.9rem; font-weight: 400; background: var(--surface); color: var(--text); border-color: var(--border); padding: 0.6rem 0.85rem; }

/* Rendered Markdown (Bot replies, results, .md previews): normal wrapping, tight vertical rhythm, mono code. */
.md { white-space: normal; line-height: 1.5; }
.md > :first-child { margin-top: 0; }
.md > :last-child { margin-bottom: 0; }
.md p, .md ul, .md ol, .md pre, .md blockquote, .md table { margin: 0.45rem 0; }
.md h3, .md h4, .md h5, .md h6 { margin: 0.8rem 0 0.3rem; line-height: 1.3; letter-spacing: -0.01em; }
.md h3 { font-size: var(--fs-5); } .md h4 { font-size: var(--fs-4); } .md h5, .md h6 { font-size: var(--fs-3); }
.md ul, .md ol { padding-left: 1.4rem; }
.md li + li { margin-top: 0.15rem; }
.md code { font-family: var(--font-mono); font-size: 0.9em; background: var(--code-bg); border: 1px solid var(--border); border-radius: var(--r-s); padding: 0.05rem 0.3rem; }
.md pre { font-family: var(--font-mono); font-size: var(--fs-2); background: var(--code-bg); border: 1px solid var(--border); border-radius: var(--r-s); padding: var(--s-2) var(--s-3); overflow-x: auto; white-space: pre; }
.md pre code { background: none; border: 0; padding: 0; font-size: inherit; }
.md blockquote { border-left: 2px solid var(--border-strong); padding: 0 0 0 var(--s-3); color: var(--text-2); }
.md hr { border: 0; border-top: 1px solid var(--border); margin: var(--s-3) 0; }
.md a { color: var(--primary); text-decoration: underline; text-decoration-color: color-mix(in srgb, var(--primary) 40%, transparent); }
.md table { border-collapse: collapse; font-size: var(--fs-3); display: block; overflow-x: auto; }
.md th, .md td { border: 1px solid var(--border); padding: 0.2rem var(--s-2); text-align: left; }
.md th { background: var(--surface-2); font-weight: 600; }
/* Image deliverables as thumbnails above the download links; a click opens the preview. */
.thumbs { display: flex; flex-wrap: wrap; gap: var(--s-2); margin-top: 0.6rem; }
.thumb { padding: 0; border: 1px solid var(--border-strong); border-radius: var(--r-m); background: var(--code-bg); box-shadow: var(--control-shadow); overflow: hidden; line-height: 0; max-width: 100%; }
.thumb img { display: block; height: 160px; width: auto; max-width: min(320px, 80vw); object-fit: contain; }

/* Skeletons: a list's shape before its first fetch returns. */
.skeleton { background: linear-gradient(90deg, var(--skeleton-a) 25%, var(--skeleton-b) 50%, var(--skeleton-a) 75%); background-size: 200% 100%; animation: shimmer 1.4s linear infinite; border-radius: var(--r-m); list-style: none; }
.skeleton.bot { height: 48px; margin: var(--s-1) 0; }
.skeleton.line { height: 2.4rem; }
.skeleton.line.right { align-self: flex-end; }
.skeleton.block { height: 5rem; }
@keyframes shimmer { from { background-position: 200% 0; } to { background-position: -200% 0; } }

/* Activity: what the Bot's computer did, as a log. Each step is a `$` line in a mono panel. */
.msg.activity { align-self: stretch; max-width: 72ch; font-family: var(--font-mono); color: var(--text-2); font-size: var(--fs-2); padding: 0 var(--s-1); }
.msg.activity summary { cursor: pointer; user-select: none; }
.msg.activity .steps { list-style: none; margin: var(--s-1) 0 0; padding: var(--s-2) var(--s-3); display: flex; flex-direction: column; gap: 0.2rem; background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-s); }
.msg.activity .status::before { content: "$ "; color: var(--primary); }
.msg.activity .status.failed::before { content: "✗ "; color: var(--danger); }
.msg.activity .status.failed .outcome { color: var(--danger); }

.msg.working { align-self: flex-start; display: flex; gap: var(--s-2); align-items: center; color: var(--text-2); font-size: var(--fs-3); padding: var(--s-1) var(--s-1); }
.msg.working .dot, .msg.delegation .dot { flex: none; width: 0.5em; height: 1em; background: var(--primary); animation: blink 1.1s steps(1) infinite; }

.msg.notice { align-self: stretch; color: var(--danger); background: var(--danger-bg); border: 1px solid var(--danger-border); border-radius: var(--r-m); padding: 0.45rem 0.7rem; font-size: var(--fs-3); }
.msg.conversation { align-self: stretch; display: flex; align-items: center; gap: var(--s-3); color: var(--text-2); font-size: var(--fs-2); margin: var(--s-3) 0; }
.msg.conversation::before, .msg.conversation::after { content: ""; flex: 1; border-top: 1px solid var(--border-strong); }
.msg.notice.info { color: var(--text-2); background: var(--surface); border-color: var(--border); }

.msg.result { align-self: flex-start; background: var(--surface); border: 1px solid var(--border); border-left: 2px solid var(--primary); border-radius: var(--r-l); padding: 0.8rem var(--s-4); box-shadow: var(--elevation); }
/* An answer without files reads as the Bot's reply, like its other text; the boxed card is for delivered files. */
.msg.result.plain { border-left: 1px solid var(--border); border-radius: var(--r-m); padding: 0.6rem 0.85rem; }
.msg.activity .narration { color: var(--text); font-family: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; font-size: var(--fs-2); padding-left: 1.1ch; }
.msg.activity .narration .md > :first-child { margin-top: 0; }
.msg.activity .narration .md > :last-child { margin-bottom: 0; }
.msg.result .label { font-family: var(--font-mono); font-size: var(--fs-1); text-transform: uppercase; letter-spacing: 0.08em; color: var(--primary); margin-bottom: 0.3rem; }
.msg .artifacts { list-style: none; margin: 0.6rem 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: 0.4rem; }
.msg .artifacts li { display: inline-flex; gap: 0.3rem; align-items: center; }
.msg.notice .hint { margin: var(--s-2) 0 0; font-size: var(--fs-2); color: var(--text-2); }
.msg.notice .artifacts { margin-top: var(--s-1); }
.msg .artifacts a { display: inline-block; font-family: var(--font-mono); background: var(--surface); border: 1px solid var(--border-strong); color: var(--primary); border-radius: var(--r-m); padding: var(--s-1) 0.6rem; text-decoration: none; font-size: var(--fs-2); box-shadow: var(--control-shadow); }
.msg .artifacts .size { color: var(--text-2); font-size: var(--fs-1); margin-left: 0.3rem; }
.msg .artifacts button.small { padding: 0.2rem var(--s-2); font-size: var(--fs-2); min-height: 0; }

/* ---- Cards (the Bot asks) ------------------------------------------------ */
/* A card is the one message that asks the person to act: it wears the attention colour while open, and settles into the panel once decided. */
.msg.card { align-self: stretch; border: 1px solid var(--border); border-radius: var(--r-l); padding: var(--s-3) var(--s-4); background: var(--surface); box-shadow: var(--elevation); }
.msg.card .label { font-family: var(--font-mono); font-size: var(--fs-1); text-transform: uppercase; letter-spacing: 0.08em; color: var(--text-2); margin-bottom: var(--s-1); }
.msg.card.open { border-color: var(--attention); background: var(--attention-bg); box-shadow: var(--elevation), var(--attention-glow); }
.msg.card.open .label { color: var(--attention); font-weight: 600; }
.msg.card.open .label::before { content: "◆"; margin-right: 0.4rem; }
.msg.card .proposal { white-space: pre-wrap; font-family: var(--font-mono); font-size: var(--fs-2); background: var(--code-bg); border: 1px solid var(--border); padding: var(--s-2) var(--s-3); border-radius: var(--r-s); }
.msg.card .decision { font-weight: 600; }
/* A proposed routine: the schedule line, then the exact request the Bot would re-send, in the proposal panel. */
.schedule { margin-top: var(--s-2); }
.schedule .text { margin: 0 0 var(--s-1); }
.decision-list .schedule .text { font-size: var(--fs-2); }
.decision-list .schedule .proposal { white-space: pre-wrap; font-family: var(--font-mono); font-size: var(--fs-1); background: var(--code-bg); border: 1px solid var(--border); padding: var(--s-1) var(--s-2); border-radius: var(--r-s); margin: 0; }
.msg.card .hint { font-size: var(--fs-2); color: var(--text-2); margin: var(--s-1) 0 0; }
.msg.card .card-form .row { display: flex; gap: var(--s-2); align-items: flex-start; margin-top: var(--s-2); }
.msg.card .card-form .attachments { margin-top: var(--s-2); }
.msg.card .card-form .file-label { display: inline-block; margin-top: var(--s-2); }
.msg.card .chips { margin-top: 0.35rem; display: flex; flex-wrap: wrap; gap: 0.3rem; }
.msg.card .chip { font-family: var(--font-mono); font-size: var(--fs-1); background: var(--hover); border: 1px solid var(--border); border-radius: var(--r-s); padding: 0.05rem var(--s-2); }
.msg.card .sign-in-origin { font-weight: 600; overflow-wrap: anywhere; margin: 0 0 var(--s-3); }
.msg.card .sign-in-form { max-width: 42rem; }
.msg.card .sign-in-actions { flex-wrap: wrap; }
.msg.card .card-form textarea, .msg.card .card-form input { flex: 1; }

/* A delegation: work this Bot asked another Bot for. Open, it follows the other Bot with the working dot; amber only while that
 * Bot needs the person (its question or interruption sits in its own thread); settled, it reads like a closed card. */
.msg.delegation { align-self: stretch; border: 1px solid var(--border); border-radius: var(--r-l); padding: var(--s-3) var(--s-4); background: var(--surface); box-shadow: var(--elevation); }
.msg.delegation .label { display: flex; align-items: center; gap: var(--s-2); font-weight: 600; font-size: var(--fs-3); color: var(--text-2); margin-bottom: var(--s-1); }
.msg.delegation.open .label { color: var(--text); }
.msg.delegation.needs { border-color: var(--attention); background: var(--attention-bg); box-shadow: var(--elevation), var(--attention-glow); }
.msg.delegation.needs .label { color: var(--attention); }
.msg.delegation.needs .label::before { content: "\25c6"; }
.msg.delegation .brief { color: var(--text-2); font-size: var(--fs-3); }
.msg.delegation .brief-rest { font-size: var(--fs-3); color: var(--text-2); }
.msg.delegation .brief-rest summary { cursor: pointer; user-select: none; font-family: var(--font-mono); font-size: var(--fs-1); }
.msg.delegation .hint { font-size: var(--fs-2); color: var(--text-2); margin: 0 0 var(--s-1); }
.msg.delegation .md { margin-top: var(--s-2); font-size: var(--fs-3); }
.msg.delegation a.chip { color: var(--primary); text-decoration: none; background: var(--surface); border-color: var(--border-strong); }
.msg.delegation time button.small { margin-left: var(--s-2); padding: 0 0.4rem; font-size: var(--fs-1); }

/* ---- Composer ------------------------------------------------------------ */
/* The composer is one box: attachments, a textarea that grows with its text (app.js), and the actions along its
 * bottom edge. It floats on the page colour under the thread; the box, not the textarea, shows focus. */
.composer { padding: 0 max(var(--s-5), calc((100% - 96ch) / 2)) var(--s-4); }
.composer-box { display: flex; flex-direction: column; gap: var(--s-1); padding: var(--s-2) var(--s-2) var(--s-2) var(--s-3); background: var(--surface); border: 1px solid var(--border-strong); border-radius: var(--r-l); box-shadow: var(--elevation); transition: border-color 120ms ease; }
.composer-box:focus-within { border-color: var(--primary); }
.composer textarea { resize: none; border: 0; background: transparent; padding: var(--s-2) 0; max-height: 40vh; overflow-y: auto; }
.composer textarea:focus-visible { outline: none; }
.composer-actions { display: flex; gap: var(--s-2); align-items: center; }
.attachments { display: flex; flex-wrap: wrap; gap: 0.3rem; }
.attachments:empty { display: none; }
.attachments .chip { font-family: var(--font-mono); font-size: var(--fs-1); border: 1px solid var(--border); border-radius: var(--r-s); padding: 0.05rem 0.55rem; display: inline-flex; gap: 0.4rem; align-items: center; }
.attachments .chip button { border: 0; background: transparent; color: var(--text-2); padding: 0; font-size: 0.9rem; }

.files-list { list-style: none; padding: 0; margin: 0; max-width: 60rem; }
.file-row { padding: var(--s-4) 0; border-bottom: 1px solid var(--border); overflow-wrap: anywhere; }
.file-row .artifacts { list-style: none; margin: 0 0 var(--s-2); padding: 0; }
.file-row .artifacts li { display: flex; flex-wrap: wrap; gap: var(--s-2); align-items: center; }
.file-row .artifacts a { font-family: var(--font-mono); }
.file-row .size { margin-left: var(--s-2); color: var(--text-2); font-size: var(--fs-2); }
.file-request { display: block; margin-bottom: var(--s-1); color: var(--text-2); }

/* ---- Create and settings ------------------------------------------------- */
.create { padding: var(--s-5); overflow-y: auto; }
.create .card { max-width: 560px; }
.create h2 { margin-top: 0; font-size: 1.25rem; }
.create .describe { margin-bottom: var(--s-4); }
.msg.card .bot-name { font-weight: 600; margin: 0 0 var(--s-1); }
.msg.card .bot-capabilities { margin: var(--s-2) 0; padding: 0; list-style: none; }
.msg.card .bot-capabilities li { margin: 0.2rem 0; }
.msg.card details.instructions summary { cursor: pointer; font-size: var(--fs-2); color: var(--text-2); }
.msg.card .bot-examples { margin: var(--s-2) 0 0; padding-left: 1.2rem; }
/* Settings sections: a heading row over a rule, not a boxed fieldset. */
.section { border: 0; border-top: 1px solid var(--border); border-radius: 0; margin: var(--s-5) 0 0; padding: var(--s-4) 0 0; min-width: 0; }
.section legend { float: left; width: 100%; margin: 0 0 var(--s-2); padding: 0; font-family: var(--font-mono); font-weight: 600; font-size: var(--fs-2); text-transform: uppercase; letter-spacing: 0.08em; color: var(--text-2); }
.section legend .muted { display: block; font-family: ui-sans-serif, system-ui, sans-serif; font-weight: 400; font-size: var(--fs-2); text-transform: none; letter-spacing: 0; margin-top: 0.1rem; }
.section > legend + * { clear: both; }
.section > label { margin-top: var(--s-2); }
.section > p { margin: var(--s-2) 0 0; }
.section > button { margin-top: var(--s-2); }
.section > p.small + label { margin-top: var(--s-3); }
.notes { max-height: 16rem; overflow-y: auto; padding: var(--s-2) var(--s-3); background: var(--code-bg); border: 1px solid var(--border); border-radius: var(--r-s); }
.notes.muted { background: transparent; border: 0; padding: 0; }
.skills-lead { margin-top: var(--s-3); }
.skill-list { list-style: none; margin: var(--s-1) 0 0; padding: 0; display: flex; flex-direction: column; gap: 0.2rem; font-size: var(--fs-3); }
.skill-list .name { font-family: var(--font-mono); }
.decision-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--s-2); }
.decision-list li p { margin: 0.15rem 0 0; white-space: pre-wrap; }
.decision-list li.declined strong { color: var(--text-2); }
.routines { margin-top: var(--s-4); }
.routine-list { list-style: none; margin: var(--s-2) 0; padding: 0; }
.routine-list li { display: flex; flex-wrap: wrap; gap: var(--s-2); align-items: baseline; padding: var(--s-3) 0; border-top: 1px solid var(--border); font-size: 0.9rem; }
.routine-list li .name { font-weight: 600; }
.routine-list li .prompt { color: var(--text-2); flex-basis: 100%; white-space: pre-wrap; overflow-wrap: anywhere; }

/* ---- Artifact preview ---------------------------------------------------- */
/* The preview is the one modal: it scales in from 0.97 (nothing appears from nothing), centred, 200 ms; it leaves
 * faster (150 ms). `display` and `overlay` transition discretely so the closing frames still render. */
.preview { border: 1px solid var(--border); border-radius: var(--r-l); padding: 0; width: min(920px, 94vw); max-height: 90vh; background: var(--surface); color: var(--text); box-shadow: var(--elevation);
  opacity: 0; transform: scale(0.97); transition: opacity 150ms var(--ease-out), transform 150ms var(--ease-out), overlay 150ms allow-discrete, display 150ms allow-discrete; }
.preview[open] { opacity: 1; transform: scale(1); transition-duration: 200ms; }
@starting-style { .preview[open] { opacity: 0; transform: scale(0.97); } }
.preview::backdrop { background: var(--scrim); opacity: 0; transition: opacity 150ms ease, overlay 150ms allow-discrete, display 150ms allow-discrete; }
.preview[open]::backdrop { opacity: 1; transition-duration: 200ms; }
@starting-style { .preview[open]::backdrop { opacity: 0; } }
.preview header { margin: 0; padding: 0.6rem 0.9rem; border-bottom: 1px solid var(--border); }
.preview-body { padding: 0.9rem; overflow: auto; max-height: calc(90vh - 3.5rem); }
.preview-body pre { margin: 0; white-space: pre-wrap; word-wrap: break-word; font-size: var(--fs-3); }
.preview-body img { max-width: 100%; display: block; }
.preview-body table { border-collapse: collapse; font-size: var(--fs-3); }
.preview-body td, .preview-body th { border: 1px solid var(--border); padding: 0.2rem var(--s-2); text-align: left; white-space: nowrap; }
.preview-body th { background: var(--surface-2); position: sticky; top: 0; }
.use-artifact { width: min(420px, 94vw); }
.use-artifact .hint { margin: var(--s-2) 0 0; font-size: var(--fs-2); color: var(--text-2); }
.use-artifact footer { padding: 0.6rem 0.9rem; border-top: 1px solid var(--border); }
.attachments .chip.artifact { border-style: dashed; }

/* ---- Phones: one column; the Bot list slides over from the left; controls sized for touch. ---- */
@media (max-width: 720px) {
  :root { font-size: 16px; }
  /* iOS Safari zooms the page when a focused field renders below 16px and keeps that zoom after reload. */
  input, textarea, select { font-size: 16px; }
  .app { grid-template-columns: 1fr; }
  /* Enter 220 ms on the drawer curve; leaving is quicker (160 ms) — the person has already decided. */
  .sidebar { position: fixed; inset: 0 22% 0 0; z-index: 10; transform: translateX(-100%); transition: transform 160ms var(--ease-drawer); box-shadow: 0 0 48px -12px rgba(0,0,0,0.25); }
  .sidebar.open { transform: none; transition-duration: 220ms; }
  .topbar { display: flex; align-items: center; gap: var(--s-3); padding: 0.4rem var(--s-3); border-bottom: 1px solid var(--border); background: var(--surface); }
  .topbar .wordmark { font-family: var(--font-mono); font-weight: 600; color: var(--text); }
  .msg { max-width: 100%; }
  .thread-head { padding: 0.6rem var(--s-3); gap: var(--s-2); flex-wrap: wrap; }
  .bot-tabs { padding: 0 var(--s-3); gap: var(--s-2); }
  .bot-panel button.small { min-height: 44px; }
  .thread-head > div { flex: 1; min-width: 0; }
  .thread-head p { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  /* Name and status on the first line; the action buttons wrap onto their own line instead of squeezing the name out. */
  .thread-head .row { margin-top: 0; flex: 1 1 100%; flex-wrap: wrap; }
  .thread-head .row .badge { order: -1; margin-right: auto; }
  .thread-head .row button { min-height: 36px; padding: 0.3rem 0.7rem; }
  .messages { padding: var(--s-3); }
  .composer { padding: 0 var(--s-3) 0.8rem; }
  .composer-actions { flex-wrap: wrap; }
  .composer textarea { min-height: 0; }
  .create { padding: var(--s-3); }
  button, .file-label, input, select, textarea { min-height: 44px; }
  input[type=checkbox] { min-height: 0; width: 1.1rem; height: 1.1rem; }
  .bot-list button { min-height: 52px; }
  .icon-button { width: 44px; height: 44px; }
  .menu-item { min-height: 44px; }
  .bot-list .mark { width: 32px; height: 32px; }
  .bot-list button { grid-template-columns: 32px minmax(0, 1fr) auto; }
  .badge.small, button.small { min-height: 32px; }
  .takeover { margin: var(--s-2) var(--s-3); }
  .msg.card .card-form .row { flex-wrap: wrap; }
  .msg.card .card-form input, .msg.card .card-form textarea { flex: 1 1 100%; }
  /* Deliverables as full-width rows the thumb can hit; the download link fills the row, Preview sits at its end. */
  .msg .artifacts { flex-direction: column; gap: 0.35rem; }
  .msg .artifacts li { display: flex; gap: 0.35rem; }
  .msg .artifacts a { flex: 1; display: flex; align-items: center; justify-content: space-between; min-height: 44px; padding: 0.4rem var(--s-3); }
  .msg .artifacts button.small { min-height: 44px; padding: 0.4rem var(--s-3); font-size: var(--fs-3); }
}

@media (prefers-reduced-motion: reduce) {
  html.theming, html.theming * { transition: none; }
  .msg.working .dot, .msg.delegation .dot, .login h1::after { animation: none; }
  .skeleton { animation: none; }
  .sidebar, .backdrop { transition: none; }
  .preview, .preview[open] { transition: opacity 150ms ease, overlay 150ms allow-discrete, display 150ms allow-discrete; transform: none; }
  @starting-style { .preview[open] { transform: none; } }
  .msg.enter { transition: opacity 200ms ease; transform: none; }
  .menu[open] .menu-panel { transition: opacity 150ms ease; transform: none; }
  @starting-style { .menu[open] .menu-panel { transform: none; } }
  @starting-style { .msg.enter { transform: none; } }
}
