agent-office-studio 0.8.0 → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/server/links.js CHANGED
@@ -26,6 +26,9 @@ const MAX_AGENTS = 16;
26
26
  const STATES = new Set(['working', 'idle', 'break', 'meeting', 'away']);
27
27
  const CODE_RE = /^[0-9A-HJKMNP-TV-Z]{8}$/;
28
28
  const ID_RE = /^[A-Za-z0-9_-]{1,64}$/;
29
+ // Ids key plain objects (saved guests, tokens used), so none may name their prototype.
30
+ const NOT_IDS = new Set(['__proto__', 'constructor', 'prototype']);
31
+ const isId = (v) => ID_RE.test(String(v ?? '')) && !NOT_IDS.has(String(v));
29
32
  const HEX_RE = /^#[0-9a-f]{6}$/i;
30
33
  const CLEARANCES = new Set(['plan', 'edit', 'auto']); // MODES in index.js: auto is Full autonomy
31
34
 
@@ -40,13 +43,13 @@ export function normaliseCode(code) {
40
43
  }
41
44
 
42
45
  function cleanLink(l) {
43
- if (!l || !ID_RE.test(String(l.id))) return null;
46
+ if (!l || !isId(l.id)) return null;
44
47
  return {
45
48
  id: String(l.id),
46
49
  peer: text(l.peer, 20),
47
50
  kind: l.kind === 'guest' ? 'guest' : 'link',
48
51
  role: ['host', 'guest'].includes(l.role) ? l.role : 'peer',
49
- invite: ID_RE.test(String(l.invite ?? '')) ? String(l.invite) : null,
52
+ invite: isId(l.invite) ? String(l.invite) : null,
50
53
  createdAt: Number.isFinite(l.createdAt) ? l.createdAt : null,
51
54
  };
52
55
  }
@@ -77,7 +80,11 @@ function cleanPolicy(guest) {
77
80
  const ourAgents = guest?.ourAgents !== false;
78
81
  const theirAgents = ['read', 'edit'].includes(guest?.theirAgents) ? guest.theirAgents : 'off';
79
82
  if (!ourAgents && theirAgents === 'off') throw fail(400, 'Let them use your agents, or let their agents work here, or both.');
80
- return { repos, clearance, tokensPerDay, ourAgents, theirAgents };
83
+ // Which of our agents they may use. Absent (a guest made before this existed)
84
+ // means all of them.
85
+ const agents = ourAgents && Array.isArray(guest?.agents) ? [...new Set(guest.agents.map(String).filter((a) => ID_RE.test(a)))] : null;
86
+ if (agents && !agents.length) throw fail(400, 'Pick at least one of your agents to lend.');
87
+ return { repos, clearance, tokensPerDay, ourAgents, theirAgents, agents };
81
88
  }
82
89
 
83
90
  export class Links {
@@ -145,7 +152,7 @@ export class Links {
145
152
  // A guest link's limits, as the host set them. Null if this isn't one we host.
146
153
  guestPolicy(linkId) {
147
154
  const l = this.links.find((x) => x.id === linkId);
148
- return l?.role === 'host' ? this.saved.guests[l.id] || null : null;
155
+ return l?.role === 'host' && Object.hasOwn(this.saved.guests, l.id) ? this.saved.guests[l.id] : null;
149
156
  }
150
157
 
151
158
  save() {
@@ -0,0 +1,164 @@
1
+ // Keeping the agents from sinking the machine they run on: how hard it is
2
+ // swapping right now, and cleaning up what an agent left running.
3
+
4
+ import os from 'node:os';
5
+ import fs from 'node:fs';
6
+ import { execFile } from 'node:child_process';
7
+ import { ps, tree } from './procstat.js';
8
+
9
+ // ---------- pressure ----------
10
+
11
+ // Swap traffic is the signal that matters: "free memory" on macOS stays near
12
+ // zero by design, and its memory level reads healthy while the disk thrashes.
13
+ // Pages swapped in and out, as running totals.
14
+ function swapPages() {
15
+ if (process.platform === 'linux') {
16
+ try {
17
+ const v = fs.readFileSync('/proc/vmstat', 'utf8');
18
+ const n = (k) => Number(v.match(new RegExp(`^${k} (\\d+)`, 'm'))?.[1] || 0);
19
+ return Promise.resolve({ pages: n('pswpin') + n('pswpout'), pageSize: 4096 });
20
+ } catch { return Promise.resolve(null); }
21
+ }
22
+ if (process.platform !== 'darwin') return Promise.resolve(null);
23
+ return new Promise((resolve) => {
24
+ execFile('/usr/bin/vm_stat', { timeout: 3000 }, (err, out) => {
25
+ if (err) return resolve(null);
26
+ const n = (k) => Number(out.match(new RegExp(`${k}:\\s+(\\d+)`))?.[1] || 0);
27
+ const pageSize = Number(out.match(/page size of (\d+)/)?.[1] || 16384);
28
+ resolve({ pages: n('Swapins') + n('Swapouts'), pageSize });
29
+ });
30
+ });
31
+ }
32
+
33
+ // Readings over the last minute or so; the rate is taken across all of them
34
+ // so one burst doesn't hold the queue.
35
+ const WINDOW_MS = 60_000;
36
+ const readings = [];
37
+
38
+ export async function samplePressure() {
39
+ const r = await swapPages();
40
+ if (!r) return;
41
+ const now = Date.now();
42
+ readings.push({ at: now, ...r });
43
+ while (readings.length > 2 && now - readings[1].at > WINDOW_MS) readings.shift();
44
+ }
45
+
46
+ // MB a second swapped over the window, or null with too little to go on.
47
+ export function swapRate() {
48
+ if (readings.length < 2) return null;
49
+ const a = readings[0], b = readings[readings.length - 1];
50
+ const secs = (b.at - a.at) / 1000;
51
+ if (secs < 5 || b.pages < a.pages) return null;
52
+ return ((b.pages - a.pages) * b.pageSize) / secs / (1 << 20);
53
+ }
54
+
55
+ export function resetPressure() {
56
+ readings.length = 0;
57
+ }
58
+
59
+ // Above these the machine is thrashing: swap traffic of a size that stalls
60
+ // everything, or three times more runnable work than there are cores.
61
+ export const LIMITS = { swapMBs: 100, loadPerCore: 3 };
62
+
63
+ // Why a new agent should not start now, in words for the boss, or null.
64
+ export function overloaded() {
65
+ if (process.env.OFFICE_PRESSURE_CHECK === 'off') return null;
66
+ const swap = swapRate();
67
+ if (swap !== null && swap > LIMITS.swapMBs) return `the machine is swapping memory to disk (about ${Math.round(swap)} MB/s)`;
68
+ const cores = os.cpus().length;
69
+ const load = os.loadavg()[0];
70
+ if (load > cores * LIMITS.loadPerCore) return `the processor is overloaded (load ${load.toFixed(0)} on ${cores} cores)`;
71
+ return null;
72
+ }
73
+
74
+ // ---------- leftovers ----------
75
+
76
+ // What each job's agent has started, from the process samples taken while it
77
+ // works: jobId -> Map(pid -> { cmd, pgid }). Kept across the sessions of one
78
+ // job (a cleared context or a model switch), so a dev server started before
79
+ // the clear is still the job's.
80
+ const started = new Map();
81
+ // And the process groups they ran in: jobId -> Map(pgid -> leader as seen, or
82
+ // null if it wasn't). Each command an
83
+ // agent runs gets a group of its own, and whatever it puts in the background
84
+ // stays in that group after the shell exits, so the group finds those too.
85
+ const groups = new Map();
86
+
87
+ export function remember(jobId, procs, root) {
88
+ let mine = started.get(jobId);
89
+ if (!mine) started.set(jobId, (mine = new Map()));
90
+ let gs = groups.get(jobId);
91
+ if (!gs) groups.set(jobId, (gs = new Map()));
92
+ // The agent's own group is the office's, which is nobody's to clean up.
93
+ const own = procs.find((p) => p.pid === root)?.pgid;
94
+ for (const p of procs) {
95
+ if (p.pid === root) continue;
96
+ if (!mine.has(p.pid)) mine.set(p.pid, { cmd: p.cmd, pgid: p.pgid, start: p.start });
97
+ if (p.pgid > 1 && p.pgid !== own && !gs.get(p.pgid)) gs.set(p.pgid, p.pid === p.pgid ? { cmd: p.cmd, start: p.start } : null);
98
+ }
99
+ }
100
+
101
+ // Whether a process is the job's: seen under it, or in a group it ran.
102
+ export function startedByJob(jobId, p) {
103
+ if (started.get(jobId)?.get(p.pid)?.cmd === p.cmd) return true;
104
+ // A new group leader that merely reuses an old group's number is not.
105
+ return !!groups.get(jobId)?.has(p.pgid) && p.pid !== p.pgid;
106
+ }
107
+
108
+ export function forget(jobId) {
109
+ started.delete(jobId);
110
+ groups.delete(jobId);
111
+ }
112
+
113
+ const name = (cmd) => {
114
+ const words = String(cmd).split(/\s+/);
115
+ const bin = (words[0] || '').split('/').pop();
116
+ // "node .../vite" says less than "vite".
117
+ const script = /^(node|python\d?|ruby|sh|bash|zsh|npm|npx|pnpm|yarn|bun|deno)$/.test(bin) && words.slice(1).find((w) => w && !w.startsWith('-'));
118
+ return (script ? script.split('/').pop() : bin).slice(0, 40) || 'process';
119
+ };
120
+
121
+ // Daemons that any build or tool connects to, whoever started them. Stopping
122
+ // one under another agent's running build fails that build, so they are only
123
+ // stopped when nobody else is working.
124
+ const SHARED = /GradleDaemon|KotlinCompileDaemon|GradleWrapperMain.*--daemon|\bwatchman\b|\badb\b.*(fork-server|server)/;
125
+
126
+ // Stop whatever the job started that is still running, except what the agent
127
+ // asked to keep and anything inside `live` (another agent's process tree).
128
+ // A pid only counts if its command and start are the ones recorded, so a
129
+ // reused pid is left alone. Returns the names of what was stopped.
130
+ const same = (now, was) => !!now && !!was && now.cmd === was.cmd && (now.start == null || was.start == null || Math.abs(now.start - was.start) < 2000);
131
+ export async function reap(jobId, { keep = [], live = [] } = {}) {
132
+ const mine = started.get(jobId);
133
+ const gs = groups.get(jobId) || new Map();
134
+ forget(jobId);
135
+ if (!mine?.size) return [];
136
+ const snap = await ps();
137
+ if (!snap) return [];
138
+ // Never the office itself or what runs it.
139
+ const spare = new Set();
140
+ for (let pid = process.pid; pid > 1 && !spare.has(pid); pid = snap.procs.get(pid)?.ppid) spare.add(pid);
141
+ for (const root of [...live, ...keep]) for (const p of tree(snap, root)) spare.add(p.pid);
142
+ const roots = [];
143
+ for (const [pid, was] of mine) if (same(snap.procs.get(pid), was)) roots.push(pid);
144
+ // A group's number can't be reused while anything is still in it, so one
145
+ // with no leader left is the job's. One with a leader is only if that
146
+ // leader is the one seen while the job worked, not a newcomer with its pid.
147
+ const ours = (g) => !snap.procs.has(g) || same(snap.procs.get(g), gs.get(g));
148
+ for (const p of snap.procs.values()) if (gs.has(p.pgid) && p.pid !== p.pgid && ours(p.pgid)) roots.push(p.pid);
149
+ const doomed = new Map();
150
+ for (const pid of roots) {
151
+ if (spare.has(pid)) continue;
152
+ for (const p of tree(snap, pid)) if (!spare.has(p.pid) && !(live.length && SHARED.test(p.cmd))) doomed.set(p.pid, p);
153
+ }
154
+ if (!doomed.size) return [];
155
+ for (const pid of doomed.keys()) try { process.kill(pid, 'SIGTERM'); } catch {}
156
+ // Whatever ignores a polite stop gets a firm one, if it is still the same process.
157
+ setTimeout(async () => {
158
+ const later = await ps();
159
+ for (const [pid, p] of doomed) if (same(later?.procs.get(pid), p)) try { process.kill(pid, 'SIGKILL'); } catch {}
160
+ }, 5000).unref();
161
+ return [...doomed.values()].map((p) => name(p.cmd));
162
+ }
163
+
164
+ export { name as procName };
@@ -50,6 +50,16 @@ const TOOLS = [
50
50
  description: 'Drop this session\'s history to cut token use, at a natural break between steps. Give notes to yourself: what is done, what is left, what you learned (files, decisions, gotchas). End your turn right after; you resume fresh from the brief and your notes. Not for the end of a job.',
51
51
  inputSchema: obj({ notes: { type: 'string' } }, ['notes']),
52
52
  },
53
+ {
54
+ name: 'heavy_work',
55
+ description: 'One heavy build or test run at a time on this shared laptop (Gradle, Xcode, emulator, jest or vitest across a whole app, docker build). start before it: you either get the slot or are told to end your turn and are messaged when it is yours. done straight after it ends, even if it failed.',
56
+ inputSchema: obj({ action: { type: 'string', enum: ['start', 'done'] }, what: { type: 'string', description: 'What you are running, like "the Android Gradle build"' } }, ['action']),
57
+ },
58
+ {
59
+ name: 'keep_running',
60
+ description: 'Keep a process you started (a dev server the boss needs to look at, say) running after this job ends; everything else you leave running is stopped then. The boss is told what was kept.',
61
+ inputSchema: obj({ pid: { type: 'number' }, why: { type: 'string' } }, ['pid', 'why']),
62
+ },
53
63
  { name: 'office_shop', description: 'Your pay so far, how pay works, and what you can buy for your desk.', inputSchema: NONE },
54
64
  {
55
65
  name: 'buy_item',
@@ -14,26 +14,28 @@ function cpuSeconds(s) {
14
14
  return Number(days) * 86400 + rest.split(':').reduce((a, p) => a * 60 + parseFloat(p), 0);
15
15
  }
16
16
 
17
- function ps() {
17
+ export function ps() {
18
18
  return new Promise((resolve) => {
19
- execFile(PS, ['-axo', 'pid=,ppid=,rss=,cputime='], { timeout: 4000, maxBuffer: 8 << 20 }, (err, out) => {
19
+ execFile(PS, ['-axo', 'pid=,ppid=,pgid=,rss=,cputime=,etime=,command='], { timeout: 4000, maxBuffer: 16 << 20 }, (err, out) => {
20
20
  if (err) return resolve(null);
21
+ const at = Date.now();
21
22
  const procs = new Map();
22
23
  const kids = new Map();
23
24
  for (const line of out.split('\n')) {
24
- const m = line.trim().match(/^(\d+)\s+(\d+)\s+(\d+)\s+(\S+)$/);
25
+ const m = line.trim().match(/^(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\S+)\s+(\S+)\s*(.*)$/);
25
26
  if (!m) continue;
26
27
  const pid = Number(m[1]), ppid = Number(m[2]);
27
- procs.set(pid, { pid, ppid, rss: Number(m[3]) * 1024, cpu: cpuSeconds(m[4]) });
28
+ // start: when it began, to the second, so a reused pid can be told apart.
29
+ procs.set(pid, { pid, ppid, pgid: Number(m[3]), rss: Number(m[4]) * 1024, cpu: cpuSeconds(m[5]), start: at - cpuSeconds(m[6]) * 1000, cmd: m[7] });
28
30
  if (!kids.has(ppid)) kids.set(ppid, []);
29
31
  kids.get(ppid).push(pid);
30
32
  }
31
- resolve({ procs, kids, at: Date.now() });
33
+ resolve({ procs, kids, at });
32
34
  });
33
35
  });
34
36
  }
35
37
 
36
- function tree(snap, root) {
38
+ export function tree(snap, root) {
37
39
  const out = [];
38
40
  const queue = [root];
39
41
  const seen = new Set();
@@ -78,6 +80,10 @@ export async function sampleProcs(roots) {
78
80
  return by;
79
81
  }
80
82
 
83
+ // Every process under `root` as of the last sample, for remembering what an
84
+ // agent started so it can be cleaned up once the agent is gone.
85
+ export const lastTree = (root) => (prev ? tree(prev, root) : []);
86
+
81
87
  // Starting fresh after a quiet spell: the next sample has nothing to diff
82
88
  // against, so don't report a percentage for it.
83
89
  export function resetProcs() {
@@ -14,6 +14,7 @@ export const SETTINGS = [
14
14
 
15
15
  { key: 'tokenLimit', group: 'Agents', label: 'Token limit', kind: 'number', min: 0, max: 10_000_000, step: 10000, unit: 'tokens', hint: 'Past this much context, an agent is nudged to clear it; if it does not, the office clears it. 0 turns this off.', fallback: () => Math.max(0, parseInt(env('AGENT_CLEAR_TOKENS') ?? '150000', 10) || 0) },
16
16
  { key: 'compactPct', group: 'Agents', label: 'Compact at', kind: 'number', min: 10, max: 95, step: 5, unit: '%', hint: 'How full an agent’s context gets before Claude Code compacts it. Applies to jobs that start after you save.', fallback: () => Math.min(95, Math.max(10, parseInt(env('AGENT_COMPACT_PCT') ?? '60', 10) || 60)) },
17
+ { key: 'maxAgents', group: 'Agents', label: 'Agents working at once', kind: 'number', min: 0, max: 50, step: 1, unit: 'agents', hint: 'More jobs than this wait in the queue, and you are told why. Jobs also wait while the machine is swapping or overloaded. 0 turns the limit off.', fallback: () => Math.max(0, parseInt(env('OFFICE_MAX_AGENTS') ?? '4', 10) || 0) },
17
18
  { key: 'chiefModel', group: 'Agents', label: 'Chief of staff model', kind: 'choice', options: ['haiku', 'sonnet', 'opus'], hint: 'Routes your messages and writes the standup.', fallback: () => env('CHIEF_MODEL') || 'sonnet' },
18
19
 
19
20
  { key: 'payPerMinute', group: 'Pay', label: 'Pay per active minute', kind: 'number', min: 0, max: 1_000_000, step: 100, unit: 'naira', hint: 'What an agent earns for each minute the model was working, on Opus. Haiku pays 3×, Sonnet 1.75×. Applies to work paid from now on.', fallback: () => 1000 },
@@ -22,6 +23,7 @@ export const SETTINGS = [
22
23
  { key: 'standupAt', group: 'Standup', label: 'Standup time', kind: 'time', hint: 'Local time, 24-hour. Blank turns the daily standup off.', fallback: () => (env('STANDUP_AT') ?? '09:30') === 'off' ? '' : (env('STANDUP_AT') ?? '09:30') },
23
24
  { key: 'standupWeekends', group: 'Standup', label: 'Hold standups on weekends', kind: 'bool', fallback: () => env('STANDUP_WEEKENDS') === '1' },
24
25
 
26
+ { key: 'breakRoom', group: 'Break room', label: 'Break-room chatter and pool', kind: 'bool', hint: 'Off: idle agents just wait, with no small talk or pool games, and nothing is posted to #chill-room.', fallback: () => env('BREAK_ROOM') === 'on' || env('BREAK_ROOM') === '1' },
25
27
  { key: 'banter', group: 'Break room', label: 'Written break-room talk', kind: 'bool', hint: 'Off: the break room uses canned lines only.', fallback: () => on(env('BANTER')) },
26
28
  { key: 'banterModel', group: 'Break room', label: 'Break-room model', kind: 'choice', options: ['haiku', 'sonnet', 'opus'], fallback: () => env('BANTER_MODEL') || 'haiku' },
27
29
  { key: 'banterGap', group: 'Break room', label: 'Time between conversations', kind: 'number', min: 10, max: 86400, step: 10, unit: 'seconds', hint: 'At most one written conversation per this long.', fallback: () => Math.max(10, Number(env('BANTER_GAP_SECONDS') ?? 120) || 120) },
package/server/visits.js CHANGED
@@ -19,10 +19,11 @@ import fs from 'node:fs';
19
19
  import os from 'node:os';
20
20
  import path from 'node:path';
21
21
  import { execFile, spawn } from 'node:child_process';
22
- import { snapshotTree, summarize, fileDiff } from './changes.js';
22
+ import { snapshotTree, summarize, fileDiff, noFilters } from './changes.js';
23
23
 
24
24
  export const ACCESS = ['off', 'read', 'edit'];
25
25
  const MAX_OPEN = 3; // working visits per guest link
26
+ const MAX_COPIES = 6; // copies on disk per guest link, working or waiting for review
26
27
  const MAX_READ = 24 * 1024; // what one answer carries, under the relay's 64 KB a frame
27
28
  const MAX_WRITE = 40 * 1024; // what one write may carry, likewise
28
29
  const MAX_FILE = 2 * 1024 * 1024; // the most a file may grow to
@@ -112,6 +113,11 @@ export class Visits {
112
113
  this.push(v);
113
114
  return { sid: v.sid, access };
114
115
  }
116
+ // Each new job of theirs is a whole copy of the project, so they can't
117
+ // leave more than a few lying about.
118
+ if (this.list.filter((x) => x.guest.link === link.id && !x.applied && !x.discarded && fs.existsSync(x.dir)).length >= MAX_COPIES) {
119
+ throw fail(429, `You have ${MAX_COPIES} copies of this office’s projects open or waiting for review. Ask the owner to apply or discard some first.`);
120
+ }
115
121
  const src = this.office.repoPath(repo);
116
122
  if (!src) throw fail(404, 'That project folder is gone.');
117
123
  const base = await snapshotTree(src);
@@ -122,7 +128,7 @@ export class Visits {
122
128
  const idx = tmpIndex();
123
129
  try {
124
130
  await git(src, ['read-tree', base], { GIT_INDEX_FILE: idx });
125
- await git(src, [`--work-tree=${dir}`, 'checkout-index', '-a', '-f'], { GIT_INDEX_FILE: idx });
131
+ await git(src, [...await noFilters(src), `--work-tree=${dir}`, 'checkout-index', '-a', '-f'], { GIT_INDEX_FILE: idx });
126
132
  } catch (err) {
127
133
  fs.rmSync(dir, { recursive: true, force: true });
128
134
  throw fail(500, `Could not copy ${repo}: ${String(err.stderr || err.message).slice(0, 200)}`);
@@ -347,6 +353,9 @@ export class Visits {
347
353
  if (summary) this.log(v, summary, 'text');
348
354
  await this.record(v);
349
355
  const n = v.changes?.count || 0;
356
+ // Nothing to review, so nothing to keep: a follow-up gets a fresh copy.
357
+ // (If the copy couldn't be read there is no telling, so it stays.)
358
+ if (v.changes && !n) this.drop(v);
350
359
  const what = v.access !== 'edit' ? '' : n ? ` ${n} file${n === 1 ? '' : 's'} changed in the copy. Review them on the job and apply or discard.` : ' Nothing changed.';
351
360
  this.log(v, `${{ done: 'Finished', failed: 'Hit a wall', stopped: 'Stopped' }[status] || 'Ended'}.${what}`, 'result', { ok: status === 'done' });
352
361
  this.push(v);
@@ -369,8 +378,9 @@ export class Visits {
369
378
  const idx = tmpIndex();
370
379
  try {
371
380
  await git(src, ['read-tree', v.base], { GIT_INDEX_FILE: idx });
372
- await git(src, [`--work-tree=${v.dir}`, 'add', '-A'], { GIT_INDEX_FILE: idx });
373
- return (await git(src, ['write-tree'], { GIT_INDEX_FILE: idx })).trim();
381
+ const nf = await noFilters(src);
382
+ await git(src, [...nf, `--work-tree=${v.dir}`, 'add', '-A'], { GIT_INDEX_FILE: idx });
383
+ return (await git(src, [...nf, `--work-tree=${v.dir}`, 'write-tree'], { GIT_INDEX_FILE: idx })).trim();
374
384
  } finally {
375
385
  fs.rmSync(idx, { force: true });
376
386
  }
package/shared/shop.js CHANGED
@@ -46,7 +46,7 @@ export function split(gross) {
46
46
  // boss buys it for them out of the pot
47
47
  // office somewhere in the room; bought out of the pot
48
48
  // floor / wall the room's finish; bought out of the pot, one in use at a time
49
- // layout a different floor plan; bought out of the pot, one in use at a time
49
+ // layout a different floor plan; free to switch between, one in use at a time
50
50
  export const ITEMS = [
51
51
  // desk
52
52
  { id: 'mug', scope: 'desk', name: 'Coffee mug', price: 2000, icon: '☕' },
@@ -80,9 +80,9 @@ export const ITEMS = [
80
80
  { id: 'wall-blush', scope: 'wall', name: 'Blush walls', price: 35000, color: '#f1d9d2', icon: '🧱' },
81
81
  // layouts
82
82
  { id: 'layout-classic', scope: 'layout', name: 'Classic', price: 0, icon: '🏢', blurb: 'Two rows of desks, the library and server room on the back wall.' },
83
- { id: 'layout-pods', scope: 'layout', name: 'Pods', price: 150000, icon: '🧩', blurb: 'Desks in two back-to-back clusters of four, a table and rug between them.' },
84
- { id: 'layout-studio', scope: 'layout', name: 'Studio', price: 250000, icon: '🎨', blurb: 'One long row of desks along the back, the floor left open for the table and the pool.' },
85
- { id: 'layout-campus', scope: 'layout', name: 'Campus', price: 400000, icon: '🏛️', blurb: 'Desks facing in round a courtyard, with the pool table at its heart.' },
83
+ { id: 'layout-pods', scope: 'layout', name: 'Pods', price: 0, icon: '🧩', blurb: 'Desks in two back-to-back clusters of four, a table and rug between them.' },
84
+ { id: 'layout-studio', scope: 'layout', name: 'Studio', price: 0, icon: '🎨', blurb: 'One long row of desks along the back, the floor left open for the table and the pool.' },
85
+ { id: 'layout-campus', scope: 'layout', name: 'Campus', price: 0, icon: '🏛️', blurb: 'Desks facing in round a courtyard, with the pool table at its heart.' },
86
86
  ];
87
87
 
88
88
  export const itemById = (id) => ITEMS.find((i) => i.id === id);
@@ -101,6 +101,13 @@ export const ACHIEVEMENTS = [
101
101
  { id: 'kudos', name: 'Great work', blurb: 'Got kudos from the boss.', bonus: 5000, test: (s) => s.kudos >= 1 },
102
102
  { id: 'streak-3', name: 'On a roll', blurb: 'Finished jobs three days running.', bonus: 12000, test: (s) => s.streak >= 3 },
103
103
  { id: 'big-earner', name: 'Big earner', blurb: 'Earned ₦200,000 in all.', bonus: 20000, test: (s) => s.earned >= 200000 },
104
+ // Quality over volume: none of these scale with the model, so nobody gains
105
+ // by picking a model for the badge.
106
+ { id: 'straight-through', name: 'Straight through', blurb: 'Got kudos on a job that never needed reopening.', bonus: 4000, test: (s) => s.cleanKudos >= 1 },
107
+ { id: 'second-wind', name: 'Second wind', blurb: 'Finished a job again after it was reopened.', bonus: 3000, test: (s) => s.comebacks >= 1 },
108
+ { id: 'team-player', name: 'Team player', blurb: 'Finished 3 jobs handed over by a colleague.', bonus: 8000, test: (s) => s.handed >= 3 },
109
+ { id: 'second-eyes', name: 'Second pair of eyes', blurb: 'Finished 3 reviews or test passes for a colleague.', bonus: 8000, test: (s) => s.reviews >= 3 },
110
+ { id: 'quick-study', name: 'Quick study', blurb: 'Finished a job in under half your usual time (after 5 jobs).', bonus: 5000, test: (s, j) => !!j?.quick },
104
111
  { id: 'shopper', name: 'Treat yourself', blurb: 'Bought something for the desk.', bonus: 1500, test: (s) => s.bought >= 1 },
105
112
  ];
106
113
 
@@ -1 +0,0 @@
1
- @font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(/assets/inter-cyrillic-ext-wght-normal-BOeWTOD4.woff2) format("woff2-variations");unicode-range:U+0460-052F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(/assets/inter-cyrillic-wght-normal-DqGufNeO.woff2) format("woff2-variations");unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(/assets/inter-greek-ext-wght-normal-DlzME5K_.woff2) format("woff2-variations");unicode-range:U+1F00-1FFF}@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(/assets/inter-greek-wght-normal-CkhJZR-_.woff2) format("woff2-variations");unicode-range:U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF}@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(/assets/inter-vietnamese-wght-normal-CBcvBZtf.woff2) format("woff2-variations");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB}@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(/assets/inter-latin-ext-wght-normal-DO1Apj_S.woff2) format("woff2-variations");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}@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(/assets/inter-latin-wght-normal-Dx4kXJAl.woff2) format("woff2-variations");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:JetBrains Mono;font-style:normal;font-display:swap;font-weight:400;src:url(data:font/woff2;base64,d09GMgABAAAAAASIABAAAAAACQQAAAQuAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGhwbHhwoBmA/U1RBVF4AdBEICoRkhAALIAABNgIkAzoEIAWFAAeBFAwHG2oHKJ6DceNW4lJEFHn9tEOE37LNsvkjHr7f739rn3u+OSrSxLQytE91Dw2PYtNVq3Qaw/vJ7fUBMdOj/u2ImB98cT5WUx9F13ZKt06mU7tG1sAYcM26yCRX4f/0904bmwq8hwkUUMTRX61pa9C3xlpAGYw1vOu8C2SBZZFlld7DAW82RJWmwYMI1AJCKBNCIASqdZGFmtPSNQRhMpR0EKjWTwm6z6sJ+4jqhxjovTinVdRpZaQjaQzAYjI8NgAKDJCokgunCn9oUQE8VZd/F//+v6P4F1U9gLr58yNI/dJX9BAshEoJbTDogz7ocKoUsPvES8UK/aQIUQgpGgECBVLkOEV6iASTYgNAPKdNXayhDPL7IJuAZnEYSZ0eOLc9i5Rv5/+lEi3sW/kfnCf/+fTe0sxS7CKLx5erRJkKOixEqQaoqrvx5HN4iz4VhX0gS6DjFIWUzn/fIXJRVFY1NFRVNVeFt+SYmrK6vCU6eJsnKnJj5HTESMTQZOTI3Y/tzr3rUcOsiRy/ciP50s3Mycgxmhz9GMXhjzVH30ut796NHP0UUa31/Zoa6vCH6iPvdIM0IRANaT60FablmZlZd+UKNFy9NrvnFGxb5NC2CRxR0/rIyF/WNn+35sv9r+tHVhkseuWGKkCPPh96+GXt8Lc/Sh24ujfjf+tNw1lZWreiPuHb/PSpyjdv2rf/++ZE5TSKjFdZxYsBvr1sEHl5STuHZqYR7jGYGvGBBdjcaB5bODY1GAxMjsd0wDMIzXAXODRd74DxNMtO4YuYHclgLQRzp9KlUmxptCwv9bYgvWGD2xBW7r9413fdJu+mxzvzAUYeeONQvZP4kgfqZle4jhH/MWh+UbxgtJdrLdXLymNL53PRU0D3Q6FcXTfGqGcul6vrqhgLGAVSv+IVIfZOHpu+mlLqSlnj903j8mazXDsba/wbxhS/4Oubh1c5/uXDgt4j5KtnGEy5BIJHo0ur+jD+r2qCkuP1aRVM8EpUoRYSJyqNRA38uwDvHBNo0AejO2Z+ZYLLal1QiFyFh1EDQOgSCSCpjwwKU8yDbIjroEwne0G5Qca49cYp4AlqtQNZfWTQoFb1tRpFYAmRD+HXTkV4uQhG2bg4OKmyoypAsUGtWgQXyFxYrkpODeUxvGqIZA61erXo0sFG1UBGuPgpuon8RNUG2DhovAjZCBuZwtXrU3mQGki9+pm0eVZAXoWxLWTQoYHBPrJR4WunNxIFbCHfkTyPK+sqxjxDmGArZvf79JGJ3GwEqjwc7a7NIrl/7bJ7Nzu4+n1Ow6shEPnUrtVo7cnd5Wi5qCUbBIQbNKCP95FMCSZylEV5VCiiMqqiOmrKZ/I/C0gI1fyuulVcM2E1r4MhtcV/fbCD+HwEvVzH1dGNAzFE0FTbKzyQz3gootrNbN2a4PuG0j0JOgE=) format("woff2"),url(data:font/woff;base64,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) format("woff");unicode-range:U+0460-052F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:JetBrains Mono;font-style:normal;font-display:swap;font-weight:400;src:url(/assets/jetbrains-mono-cyrillic-400-normal-BEIGL1Tu.woff2) format("woff2"),url(/assets/jetbrains-mono-cyrillic-400-normal-ugxPyKxw.woff) format("woff");unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:JetBrains Mono;font-style:normal;font-display:swap;font-weight:400;src:url(/assets/jetbrains-mono-greek-400-normal-C190GLew.woff2) format("woff2"),url(/assets/jetbrains-mono-greek-400-normal-B9oWc5Lo.woff) format("woff");unicode-range:U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF}@font-face{font-family:JetBrains Mono;font-style:normal;font-display:swap;font-weight:400;src:url(data:font/woff2;base64,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) format("woff2"),url(/assets/jetbrains-mono-vietnamese-400-normal-CqNFfHCs.woff) format("woff");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB}@font-face{font-family:JetBrains Mono;font-style:normal;font-display:swap;font-weight:400;src:url(/assets/jetbrains-mono-latin-ext-400-normal-Bc8Ftmh3.woff2) format("woff2"),url(/assets/jetbrains-mono-latin-ext-400-normal-fXTG6kC5.woff) format("woff");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}@font-face{font-family:JetBrains Mono;font-style:normal;font-display:swap;font-weight:400;src:url(/assets/jetbrains-mono-latin-400-normal-V6pRDFza.woff2) format("woff2"),url(/assets/jetbrains-mono-latin-400-normal-6-qcROiO.woff) format("woff");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}:root{--ink: #1d1b18;--ink-2: #5d574e;--ink-3: #958d81;--paper: #fbf9f5;--paper-2: #f4f0e9;--line: rgba(29, 27, 24, .09);--good: #2f7d4f;--bad: #b4412f;--work: #2f6fae;--wait: #b9861f;--accent: var(--work);--surface: #fff;--glass: color-mix(in srgb, var(--paper) 88%, transparent);--pane: color-mix(in srgb, var(--paper) 58%, transparent);--pane-edge: color-mix(in srgb, #fff 55%, var(--line));--t1: rgba(29, 27, 24, .05);--t2: rgba(29, 27, 24, .07);--t3: rgba(29, 27, 24, .1);--good-bg: #dcefe2;--good-fg: #25653f;--bad-bg: #f7e0db;--bad-fg: #9a3424;--work-bg: #dde9f6;--work-fg: #24598f;--wait-bg: #fbf0d4;--wait-fg: #8a6312;--view-1: #f6f2ea;--view-2: #ece5da;--view-3: #ddd4c6;--sans: "Inter Variable", Inter, system-ui, sans-serif;--mono: "JetBrains Mono", ui-monospace, monospace;--ease: cubic-bezier(.2, .8, .2, 1);color-scheme:light}html{--h: 80}html[data-theme=ocean]{--h: 235}html[data-theme=forest]{--h: 150}html[data-theme=sunset]{--h: 35}html[data-theme=lavender]{--h: 300}html:is([data-theme=ocean],[data-theme=forest],[data-theme=sunset],[data-theme=lavender]){--ink: oklch(23% .03 var(--h));--ink-2: oklch(44% .03 var(--h));--ink-3: oklch(62% .025 var(--h));--paper: oklch(98.4% .008 var(--h));--paper-2: oklch(95.6% .016 var(--h));--accent: oklch(52% .16 var(--h));--line: color-mix(in srgb, var(--ink) 10%, transparent);--t1: color-mix(in srgb, var(--ink) 5%, transparent);--t2: color-mix(in srgb, var(--ink) 7%, transparent);--t3: color-mix(in srgb, var(--ink) 10%, transparent);--view-1: oklch(96.5% .015 var(--h));--view-2: oklch(92% .02 var(--h));--view-3: oklch(86% .025 var(--h))}html[data-mode=dark]{--ink: oklch(94% .012 var(--h));--ink-2: oklch(78% .016 var(--h));--ink-3: oklch(62% .016 var(--h));--paper: oklch(20% .012 var(--h));--paper-2: oklch(25% .014 var(--h));--surface: oklch(24% .014 var(--h));--pane: color-mix(in srgb, var(--paper) 52%, transparent);--pane-edge: color-mix(in srgb, #fff 14%, transparent);--line: color-mix(in srgb, var(--ink) 12%, transparent);--t1: color-mix(in srgb, var(--ink) 6%, transparent);--t2: color-mix(in srgb, var(--ink) 9%, transparent);--t3: color-mix(in srgb, var(--ink) 13%, transparent);--good: #5fbf85;--bad: #e8806c;--work: #5b9ad8;--wait: #d9a43f;--good-bg: color-mix(in srgb, var(--good) 18%, var(--paper));--good-fg: var(--good);--bad-bg: color-mix(in srgb, var(--bad) 18%, var(--paper));--bad-fg: var(--bad);--work-bg: color-mix(in srgb, var(--work) 18%, var(--paper));--work-fg: #8dbbea;--wait-bg: color-mix(in srgb, var(--wait) 18%, var(--paper));--wait-fg: var(--wait);--view-1: oklch(27% .014 var(--h));--view-2: oklch(22% .013 var(--h));--view-3: oklch(17% .012 var(--h));color-scheme:dark}html[data-mode=dark]:is([data-theme=ocean],[data-theme=forest],[data-theme=sunset],[data-theme=lavender]){--accent: oklch(74% .13 var(--h))}*{box-sizing:border-box}[hidden]{display:none!important}html,body{margin:0;height:100%;overflow:hidden;background:var(--paper)}body{font-family:var(--sans);color:var(--ink);font-size:14px;line-height:1.45;-webkit-font-smoothing:antialiased;font-feature-settings:"cv11","ss01"}button,input,textarea,select{font:inherit;color:inherit}.app{display:grid;grid-template-columns:var(--side-w, 480px) minmax(0,1fr) auto;height:100vh;height:100dvh;background:radial-gradient(40% 36% at 8% 14%,color-mix(in srgb,var(--accent) 22%,transparent) 0%,transparent 100%),radial-gradient(38% 34% at 94% 86%,color-mix(in srgb,var(--accent) 16%,transparent) 0%,transparent 100%),radial-gradient(120% 90% at 50% 38%,var(--view-1) 0%,var(--view-2) 58%,var(--view-3) 100%)}.view{position:relative;overflow:hidden;min-width:0;container-type:inline-size}#stage{position:absolute;top:0;right:0;bottom:0;left:0}#stage canvas{display:block;width:100%;height:100%;touch-action:none}#labels{position:absolute;top:0;right:0;bottom:0;left:0;pointer-events:none;overflow:hidden}.side-grip{position:absolute;z-index:30;top:0;bottom:0;right:-4px;width:9px;cursor:col-resize;touch-action:none}.side-grip:after{content:"";position:absolute;top:0;bottom:0;left:4px;width:2px;background:var(--accent);opacity:0;transition:opacity .15s}.side-grip:hover:after,.side-grip:focus-visible:after,.app.resizing .side-grip:after{opacity:.6}.side-grip:focus-visible{outline:none}.app.resizing{cursor:col-resize;-webkit-user-select:none;user-select:none}.app.resizing #stage{pointer-events:none}.side{position:relative;zoom:var(--side-zoom, 1);display:flex;flex-direction:column;min-height:0;background:var(--pane);border-right:1px solid var(--pane-edge);-webkit-backdrop-filter:blur(24px) saturate(1.5);backdrop-filter:blur(24px) saturate(1.5)}.brand{padding:20px 20px 14px;position:relative}.title-end{display:flex;align-items:center;gap:4px;flex:none}.theme-btn{all:unset;cursor:pointer;flex:none;width:26px;height:26px;display:grid;place-items:center;border-radius:8px;color:var(--ink-3);transition:background .15s,color .15s}.theme-btn:hover,.theme-btn[aria-expanded=true]{background:var(--t2);color:var(--ink)}.theme-btn:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.theme-btn svg{width:17px;height:17px;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}.theme-pop{position:absolute;z-index:40;top:52px;right:14px;width:252px;max-width:calc(100% - 28px);box-sizing:border-box;padding:10px 12px 12px;background:var(--paper);border:1px solid var(--line);border-radius:14px;box-shadow:0 10px 30px #00000029}.theme-pop[hidden]{display:none}.theme-k{margin:4px 2px 6px;font-size:11px;font-weight:620;letter-spacing:.04em;text-transform:uppercase;color:var(--ink-3)}.theme-k:not(:first-child){margin-top:12px}.theme-swatches{display:grid;grid-template-columns:repeat(5,1fr);gap:4px}.theme-swatches button{all:unset;cursor:pointer;display:flex;flex-direction:column;align-items:center;gap:4px;padding:6px 0 5px;border-radius:10px;font-size:10.5px;font-weight:580;color:var(--ink-2)}.theme-swatches button:hover{background:var(--t1)}.theme-swatches button:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}.theme-swatches button[aria-checked=true]{background:var(--t2);color:var(--ink)}.theme-swatches i{width:24px;height:24px;border-radius:50%;box-shadow:inset 0 0 0 1px #0000001f;background:linear-gradient(135deg,oklch(94% .03 var(--sh)) 50%,oklch(55% .15 var(--sh)) 50%)}.theme-swatches [data-t=paper]{--sh: 80}.theme-swatches [data-t=ocean]{--sh: 235}.theme-swatches [data-t=forest]{--sh: 150}.theme-swatches [data-t=sunset]{--sh: 35}.theme-swatches [data-t=lavender]{--sh: 300}.theme-modes{display:grid;grid-template-columns:repeat(3,1fr);gap:2px;padding:2px;border-radius:10px;background:var(--t1)}.theme-modes button{all:unset;cursor:pointer;text-align:center;padding:5px 0;border-radius:8px;font-size:12.5px;font-weight:580;color:var(--ink-2)}.theme-modes button:hover{color:var(--ink)}.theme-modes button:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}.theme-modes button[aria-checked=true]{background:var(--paper);color:var(--ink);box-shadow:0 1px 2px #0000001f}.acct-pop{width:280px}.acct-modes{grid-template-columns:1fr 1fr}.acct-note{margin:10px 2px 0;font-size:12px;line-height:1.45;color:var(--ink-2)}.acct-err{color:var(--bad)}.phone-pop{width:260px}.phone-qr{display:block;width:100%;aspect-ratio:1;margin-top:10px;border-radius:8px;image-rendering:pixelated}.acct-fine{font-size:11px;color:var(--ink-3)}.acct-form{display:flex;gap:6px;margin-top:10px}.acct-form input{flex:1;min-width:0;padding:6px 9px;border-radius:8px;border:1px solid var(--line);background:var(--paper-2);color:var(--ink);font:inherit;font-size:12.5px}.acct-form input:focus-visible{outline:2px solid var(--accent);outline-offset:-1px}.acct-forget{all:unset;cursor:pointer;margin:8px 2px 0;font-size:12px;color:var(--ink-3);text-decoration:underline}.acct-forget:hover{color:var(--ink)}.lb-pop{width:300px}.lb-me{margin:6px 2px 0;font-size:12.5px;line-height:1.4;color:var(--ink-2)}.lb-me strong{color:var(--ink);font-weight:650}.lb-tabs{margin-top:10px}.lb-period{grid-template-columns:1fr 1fr}.lb-metric{margin-top:6px}.lb-board{margin-top:8px}.lb-list{list-style:none;margin:0;padding:0;max-height:232px;overflow-y:auto}.lb-row{display:grid;grid-template-columns:24px 1fr auto;gap:6px;align-items:baseline;padding:5px 6px;border-radius:8px;font-size:12.5px;color:var(--ink-2)}.lb-row:nth-child(-n+3) .lb-rank{color:var(--accent);font-weight:700}.lb-rank{color:var(--ink-3);font-variant-numeric:tabular-nums}.lb-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--ink)}.lb-val{font-variant-numeric:tabular-nums;font-weight:600;color:var(--ink)}.lb-you{background:var(--t2)}.lb-share{display:flex;align-items:center;gap:8px;margin:10px 2px 0;font-size:12.5px;color:var(--ink);cursor:pointer}.lb-share input,.link-repos input,.link-warn input{accent-color:var(--accent);margin:0}.link-pop{width:320px;overflow-x:hidden;max-height:calc(100dvh - 80px);overflow-y:auto;overscroll-behavior:contain}.link-actions{display:grid;gap:8px;margin-top:10px}.link-row{display:flex;align-items:center;gap:6px;flex-wrap:wrap}.link-actions .link-row .ghost{flex:1;background:var(--t1)}.link-actions .link-row .ghost:hover{background:var(--t2)}.link-redeem{margin-top:0}.link-redeem input{font-family:var(--mono);letter-spacing:.04em}.link-redeem input::placeholder{font-family:inherit;letter-spacing:0}.link-code,.link-guest{margin-top:12px;padding:8px 10px 10px;border-radius:12px;background:var(--t1)}.link-code .theme-k,.link-guest .theme-k{margin-top:2px}.link-code-row{display:flex;align-items:center;gap:8px}.link-code-v{flex:1;font-family:var(--mono);font-size:22px;font-weight:600;letter-spacing:.08em;color:var(--ink);font-variant-numeric:tabular-nums;-webkit-user-select:all;user-select:all}.link-repos{border:0;margin:10px 0 0;padding:0;max-height:168px;overflow-y:auto}.link-repos legend,.link-k{padding:0;margin:10px 2px 6px;font-size:12px;font-weight:600;color:var(--ink-2)}.link-repos legend{margin-top:0}.link-repos label{display:flex;align-items:center;gap:8px;padding:4px;border-radius:6px;font-size:12.5px;color:var(--ink);cursor:pointer}.link-repos label:hover{background:var(--t2)}.link-repos span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.link-cap button:disabled{opacity:.45;cursor:default}.link-warn{margin-top:8px;padding:8px 10px;border-radius:10px;font-size:12px;line-height:1.45;background:color-mix(in srgb,var(--bad) 10%,transparent);border:1px solid color-mix(in srgb,var(--bad) 30%,transparent)}.link-warn p{margin:0 0 6px;color:var(--ink)}.link-warn label{display:flex;align-items:center;gap:8px;font-weight:600;color:var(--bad);cursor:pointer}.link-tokens{display:flex;align-items:center;gap:8px}.link-tokens span:first-child{flex:1}.link-tokens input{width:108px;padding:5px 8px;border-radius:8px;border:1px solid var(--line);background:var(--paper-2);color:var(--ink);font:inherit;font-size:12.5px;font-variant-numeric:tabular-nums}.link-tokens input:focus-visible{outline:2px solid var(--accent);outline-offset:-1px}.link-guest>.link-row{margin-top:12px}.link-switch{display:flex;align-items:flex-start;gap:8px;margin:12px 2px 0;font-size:12.5px;color:var(--ink);cursor:pointer}.link-switch input{accent-color:var(--accent);margin:2px 0 0}.link-switch>span{display:grid;gap:1px}.link-switch strong{font-weight:600}.link-ours{border:0;margin:0 0 0 22px;padding:0;min-width:0;transition:opacity .15s}.link-ours.off{opacity:.45}.link-theirs{grid-template-columns:repeat(3,1fr)}.link-who span.link-policy{white-space:normal}.link-ours.off .link-warn label{cursor:default}.link-list{max-height:260px}.link-item{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:7px 6px;border-radius:8px;font-size:12.5px}.link-item+.link-item{border-top:1px solid var(--line)}.link-who{display:grid;min-width:0}.link-who strong{color:var(--ink);font-weight:650;overflow:hidden;text-overflow:ellipsis}.link-who span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.link-item .acct-forget{margin:0}.visit-bar{display:flex;align-items:center;justify-content:space-between;gap:8px;margin:0 14px 8px;padding:7px 10px;border-radius:10px;font-size:12.5px;color:var(--ink);background:color-mix(in srgb,var(--accent) 16%,transparent);border:1px solid color-mix(in srgb,var(--accent) 35%,transparent)}.visit-bar a{color:var(--ink-2);white-space:nowrap}.visit-bar{flex-wrap:wrap}.visit-bar.visit-off{background:color-mix(in srgb,var(--bad) 10%,transparent);border-color:color-mix(in srgb,var(--bad) 30%,transparent)}.app.visit-ended #detail .d-foot{display:none}.job .m .from{font-weight:600;color:var(--accent)}.notice.visit-review{width:100%}.notice.visit-review .link-row{gap:8px}.notice.visit-review .done{color:var(--ink-2)}.notice.visit-review .bad{color:var(--bad)}.visit-note{flex-basis:100%;margin:0;font-size:12px;color:var(--bad)}.app.visiting :is(#attach,#mic,#channels,#detail .reply .attach),.app.visiting :is(#lbBtn,#linkBtn,#acctBtn,#lbPop,#linkPop,#acctPop,#clear,#standup,#away),.app.visiting :is(.tabs [data-tab=team],.mnav [data-m=team],#teamPane){display:none!important}.brand .title{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:10px}.title-start{display:flex;align-items:center;gap:10px;min-width:0}.brand h1{margin:0;font-size:20px;font-weight:720;letter-spacing:-.03em;white-space:nowrap;color:var(--ink);min-width:0;overflow:hidden;text-overflow:ellipsis}.lv svg,.meter .bar{display:block;overflow:visible;transform:rotate(-90deg)}.trk,.arc{fill:none;stroke-width:3}.trk{stroke:var(--t3)}.arc{stroke:var(--ring, var(--bar, var(--accent)));stroke-linecap:round;stroke-dasharray:100;stroke-dashoffset:calc(100 - max(var(--p, 0),.01));filter:drop-shadow(0 0 2px color-mix(in srgb,var(--ring, var(--bar, var(--accent))) 45%,transparent));transition:stroke-dashoffset .9s var(--ease),stroke .3s}.lv{--ring: var(--accent);position:relative;flex:none;width:34px;height:34px;display:grid;place-items:center;cursor:default}.lv svg{position:absolute;top:0;right:0;bottom:0;left:0;width:100%;height:100%}.lv .trk,.lv .arc{stroke-width:2.6}.lv b{position:relative;display:grid;place-items:center;width:24px;height:24px;border-radius:50%;background:linear-gradient(145deg,color-mix(in srgb,var(--accent) 88%,#fff),color-mix(in srgb,var(--accent) 80%,#000));box-shadow:inset 0 1px #ffffff4d,0 2px 6px -2px color-mix(in srgb,var(--accent) 70%,transparent);color:#fff;font-size:11.5px;font-weight:700;font-variant-numeric:tabular-nums;letter-spacing:-.02em}.level,.gauges[hidden]{display:none}.brand h1{cursor:pointer}.fold{all:unset;cursor:pointer;flex:none;display:grid;place-items:center;width:24px;height:24px;border-radius:8px;color:var(--ink-3);transition:color .15s,background .15s}.fold:hover{color:var(--ink);background:var(--t2)}.fold:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.fold svg{width:16px;height:16px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;transition:transform .2s var(--ease)}.fold[aria-expanded=true] svg{transform:rotate(180deg)}@media(prefers-reduced-motion:reduce){.fold svg{transition:none}}.gauges{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px 16px;padding:12px 0 4px;border-top:1px solid var(--line)}.usage,#load{display:contents}.usage[hidden],#load[hidden],.meter[hidden]{display:none}.meter{--bar: var(--work);display:grid;grid-template-columns:auto minmax(0,1fr);grid-template-areas:"ring v" "ring k";column-gap:8px;align-items:center;padding:0;min-width:0;cursor:default;position:relative}.meter .bar{grid-area:ring;width:30px;height:30px}.meter .ico{fill:none;stroke:var(--ink-3);stroke-width:1.3;stroke-linecap:round;stroke-linejoin:round;transform:rotate(90deg);transform-origin:18px 18px}.meter.hot .ico{stroke:var(--bad)}.meter .k{grid-area:k;font-size:9.5px;font-weight:650;color:var(--ink-3);letter-spacing:.07em;text-transform:uppercase;line-height:1.2}.meter .v{grid-area:v;font-size:13.5px;font-weight:700;color:var(--ink);letter-spacing:-.02em;font-variant-numeric:tabular-nums;line-height:1.2;white-space:nowrap}.meter .r{display:none}.meter.warm{--bar: var(--wait)}.meter.hot{--bar: var(--bad)}.meter.hot .v{color:var(--bad)}@media(prefers-reduced-motion:reduce){.arc{transition:none}}.u-err{grid-column:1 / -1;margin:0;font-size:12px;color:var(--ink-3)}.tabs{display:flex;gap:2px;padding:0 12px 8px;border-bottom:1px solid var(--line)}.tabs button{all:unset;cursor:pointer;padding:6px 10px;border-radius:8px;font-weight:600;font-size:13px;color:var(--ink-3);display:inline-flex;gap:6px;align-items:center;transition:color .15s,background .15s}.tabs button:hover{color:var(--ink)}.tabs button.on{color:var(--ink);background:var(--t2)}.tabs #jobCount:not(:empty){font-size:11px;background:var(--accent);color:var(--paper);border-radius:99px;padding:0 6px;line-height:17px}.pane{flex:1;min-height:0;display:flex;flex-direction:column}#jobsPane{padding:8px 12px 12px}.team{flex:1;overflow-y:auto;padding:8px 12px 12px;display:flex;flex-direction:column;gap:2px}.member{border-radius:10px;transition:background .15s}.member:hover,.member.open{background:var(--t1)}.member.later{opacity:.6}.member .head{all:unset;cursor:pointer;display:grid;grid-template-columns:10px 1fr;gap:1px 10px;width:100%;box-sizing:border-box;padding:9px 10px 4px}.member:not(.open) .head:only-child{padding-bottom:9px}.member .head:focus-visible{outline:2px solid var(--accent);outline-offset:-2px;border-radius:10px}.member .head i{grid-row:1 / 3;margin-top:6px;width:8px;height:8px;border-radius:50%}.member .n{font-weight:600}.member .n em{font-style:normal;font-weight:500;font-size:11.5px;color:var(--ink-3);margin-left:4px}.member .r{font-size:12px;color:var(--ink-2)}.member .p{margin:0;padding:2px 10px 9px 30px;font-size:12.5px;color:var(--ink-3);line-height:1.45;text-wrap:pretty;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.member form{display:flex;flex-direction:column;gap:10px;padding:6px 10px 10px 30px}.member label{display:flex;flex-direction:column;gap:4px;font-size:11.5px;font-weight:600;color:var(--ink-3)}.member input,.member textarea{font-size:13.5px;font-weight:400;color:var(--ink);line-height:1.45;resize:vertical;border:1px solid var(--line);border-radius:8px;padding:7px 9px;background:var(--surface);outline:none}.member input:focus,.member textarea:focus{border-color:var(--ink-3)}.member .hint-t{margin:0;font-size:12px;color:var(--ink-3);text-wrap:pretty}.member .row{display:flex;justify-content:flex-end;gap:6px}.viewbar{align-self:flex-end;display:flex;gap:2px;margin:8px 12px 0;padding:2px;border-radius:9px;background:var(--t1)}.viewbar button{all:unset;cursor:pointer;display:grid;place-items:center;width:28px;height:24px;border-radius:7px;color:var(--ink-3);transition:background .15s,color .15s}.viewbar button:hover{color:var(--ink)}.viewbar button[aria-pressed=true]{color:var(--ink);background:var(--surface);box-shadow:0 1px 2px #00000014}.viewbar button:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.viewbar svg{width:15px;height:15px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}#teamPane,#projectsPane{display:flex;flex-direction:column}#teamPane[hidden],#projectsPane[hidden]{display:none}.pico{--s: 1em;display:inline-grid;place-items:center;flex:none;width:var(--s);height:var(--s);border-radius:28%;font-weight:700;line-height:1;background:hsl(var(--h) 50% 55% / .2);color:hsl(var(--h) 45% 34%);position:relative;overflow:hidden}.pico img{position:absolute;top:0;right:0;bottom:0;left:0;width:100%;height:100%;object-fit:contain;border-radius:inherit;background:var(--surface)}.pico:not(.has) img{opacity:0}.pico.has{color:transparent;background:none}.tiles{display:grid;grid-template-columns:repeat(auto-fill,minmax(92px,1fr));gap:6px}.tile{all:unset;cursor:pointer;box-sizing:border-box;display:flex;flex-direction:column;align-items:center;gap:2px;padding:10px 6px 8px;border-radius:12px;text-align:center;min-width:0;transition:background .15s,transform .15s var(--ease)}.tile:hover,.tile.open{background:var(--t1)}.tile:active{transform:scale(.97)}.tile:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}.tile.later{opacity:.6}.tile .art{position:relative;margin-bottom:4px}.tile .pico{--s: 52px;font-size:22px}.tile .face{display:block;width:52px;height:52px;border-radius:50%}.tile .dot{position:absolute;right:-2px;bottom:-2px;width:11px;height:11px;border-radius:50%;background:var(--line);box-shadow:0 0 0 2px var(--paper)}.tile .n{max-width:100%;font-weight:600;font-size:13px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.tile .c{max-width:100%;font-size:11.5px;color:var(--ink-3);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.tiles+.project,.tiles+.member{margin-top:8px}.project .note{margin:0;padding:12px 16px 2px;font-size:12.5px;font-weight:500;color:var(--ink-2);text-wrap:pretty}.team.icons .member.open form{padding-left:10px}@media(prefers-reduced-motion:reduce){.tile{transition:none}.tile:active{transform:none}}.msg .who .ptag{display:inline-flex;margin-left:2px}.msg .who .ptag .pico{--s: 15px;font-size:9px}.projects{flex:1;overflow-y:auto;padding:8px 12px 12px;display:flex;flex-direction:column;gap:2px}.project{border-radius:10px;transition:background .15s}.project:hover,.project.open{background:var(--t1)}.project .head{all:unset;cursor:pointer;display:grid;grid-template-columns:10px 1fr auto;gap:1px 10px;width:100%;box-sizing:border-box;padding:9px 10px}.project .head:focus-visible{outline:2px solid var(--accent);outline-offset:-2px;border-radius:10px}.project .dot{grid-row:1 / 3;margin-top:6px;width:8px;height:8px;border-radius:50%;background:var(--line)}.project .n{font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.project .m{grid-column:2 / 4;font-size:12px;color:var(--ink-3);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.project .c{font-size:11.5px;color:var(--ink-3);align-self:center}.project .sub{display:flex;flex-direction:column;gap:2px;padding:6px 6px 8px}.project .sub .job{padding:8px 10px;align-items:start}.project .sub .job .dot{margin-top:5px}.project .sub .job .t{white-space:normal;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;line-height:1.35;text-wrap:pretty;overflow-wrap:anywhere}.project .sub .job .m{margin-top:2px}.project .sub .job:hover{background:var(--t2)}.project .sub .none{margin:2px 8px 6px;font-size:12px;color:var(--ink-3)}.project .sub .ghost{align-self:stretch;display:flex;align-items:center;justify-content:center;gap:6px;font-size:12.5px;margin:6px 4px 0;padding:8px;border:1px dashed var(--line);border-radius:10px}.project .sub .ghost:hover{border-style:solid}.jobs{flex:1;overflow-y:auto;display:flex;flex-direction:column;gap:2px}.jgroup{display:flex;align-items:center;gap:6px;margin:14px 10px 4px;font-size:11px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;color:var(--ink-3)}.jgroup:first-child{margin-top:4px}.jgroup span{font-variant-numeric:tabular-nums;font-weight:500;letter-spacing:0;opacity:.8}.jobs>.job{grid-template-columns:10px 1fr auto;padding:10px 12px}.jobs>.job .t{white-space:normal;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;font-weight:540;line-height:1.35;text-wrap:pretty;overflow-wrap:anywhere}.jobs>.job .dot{margin-top:6px}.jobs>.job .w{align-self:start;margin-top:2px;font-size:11.5px;color:var(--ink-3);font-variant-numeric:tabular-nums}.jobs>.job .m{grid-column:2 / 4;display:flex;align-items:center;margin-top:3px;white-space:pre}.jobs>.job .m .pico{--s: 14px;font-size:8px;margin-right:6px}.jobs>.job .m .r{overflow:hidden;text-overflow:ellipsis}.job .m .s.working{color:var(--work-fg);font-weight:560}.job .m .s.queued{color:var(--wait-fg);font-weight:560}.job .m .s.failed{color:var(--bad);font-weight:560}.job{all:unset;cursor:pointer;display:grid;grid-template-columns:10px 1fr;gap:1px 10px;padding:9px 10px;border-radius:10px;transition:background .15s}.job:hover{background:var(--t1)}.job.open{background:var(--t2)}.job .dot{grid-row:1 / 3;margin-top:6px;width:8px;height:8px;border-radius:50%}.job .t{font-weight:560;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.job .m{font-size:12px;color:var(--ink-3);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dot.queued{background:var(--wait)}.dot.working{background:var(--work);box-shadow:0 0 0 3px #2f6fae2e;animation:ring 1.6s infinite}.dot.done{background:var(--good)}.dot.failed{background:var(--bad)}.dot.stopped{background:var(--ink-3)}@keyframes ring{50%{box-shadow:0 0 0 6px #2f6fae00}}@media(prefers-reduced-motion:reduce){.dot.working{animation:none}}.empty{margin:12px 4px;color:var(--ink-3);font-size:13px;text-wrap:pretty}#clear{font-size:12.5px;padding:7px;margin-top:6px}.channels{flex:none;display:flex;gap:4px;align-items:center;overflow-x:auto;scrollbar-width:none;padding:8px 12px 6px}.channels::-webkit-scrollbar{display:none}.channel{all:unset;cursor:pointer;flex:none;display:inline-flex;align-items:center;gap:2px;padding:4px 9px;border-radius:99px;font-size:12.5px;font-weight:580;color:var(--ink-3);transition:color .15s,background .15s}.channel:hover{color:var(--ink);background:var(--t1)}.channel.on{color:var(--paper);background:var(--ink)}.channel .hash{opacity:.55}.channel .badge{margin-left:4px;background:var(--accent);color:var(--paper);border-radius:99px;font-size:10.5px;font-weight:700;line-height:15px;padding:0 5px}.channel.add,.channel.close{color:var(--ink-3);font-size:14px;line-height:1;padding:4px 8px}.channel:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.new-channel{flex:none;display:inline-flex;align-items:center;gap:2px;padding:3px 8px;border:1px solid var(--line);border-radius:99px;background:var(--surface)}.new-channel .hash{color:var(--ink-3);font-size:12.5px}.new-channel input{all:unset;width:96px;font-size:12.5px;font-weight:580}.msgs{flex:1;overflow-y:auto;padding:10px 20px 8px;display:flex;flex-direction:column;gap:4px;-webkit-mask-image:linear-gradient(transparent,#000 14px);mask-image:linear-gradient(transparent,#000 14px)}.msg{position:relative;margin:0 -10px;padding:7px 10px;border-radius:12px;transition:background .15s}.msg .who{display:flex;align-items:center;gap:6px;font-size:12.5px;margin-bottom:3px}.msg .av{display:inline-flex;flex:none}.msg .av .face{display:block;width:20px;height:20px;border-radius:50%}.msg .who b{font-weight:640}.msg .who .arrow{color:var(--ink-3)}.msg .who time{color:var(--ink-3);font-size:11.5px;font-variant-numeric:tabular-nums;margin-left:2px}.msg .body{padding-left:26px;overflow-wrap:anywhere}.msg .body p{margin:0 0 6px}.msg .body>:last-child{margin-bottom:0}.msg.from-you .body p{white-space:pre-wrap}.msg.from-chief .body{color:var(--ink-2)}.msg.failed .body{color:var(--bad)}.msg.finished .body{border-left:3px solid var(--line);padding-left:10px;margin-left:4px;color:var(--ink)}.msg.flag .body{border-left:3px solid var(--bad);padding-left:10px;margin-left:4px;color:var(--ink)}.msg.dm .body,.msg.handoff .body,.msg.standup.from-agent .body,.msg.chill .body{border-left:2px solid var(--line);padding-left:10px;margin-left:4px;color:var(--ink-2)}.msg.chill .body{font-style:italic}.msg .kind{font-size:11px;font-weight:620;letter-spacing:.04em;text-transform:uppercase;color:var(--ink-3);margin:0 0 3px 26px}.msg.clamp:not(.full) .body{max-height:190px;overflow:hidden;-webkit-mask-image:linear-gradient(#000 70%,transparent);mask-image:linear-gradient(#000 70%,transparent)}.msg .acts{display:flex;gap:12px;align-items:center;padding-left:26px;margin-top:6px;flex-wrap:wrap}.msg .reacts{display:flex;flex-wrap:wrap;gap:4px;align-items:center;padding-left:26px;margin-top:5px}.msg .reacts:not(.some){position:absolute;top:5px;right:8px;margin:0}.msg .reacts button{all:unset;cursor:pointer;display:inline-flex;align-items:center;gap:4px;font-size:13px;line-height:1}.msg .reacts .pill{padding:3px 7px;border-radius:999px;border:1px solid var(--line);background:var(--paper)}.msg .reacts .pill span{font-size:11.5px;font-weight:620;color:var(--ink-2);font-variant-numeric:tabular-nums}.msg .reacts .pill.mine{border-color:var(--work);background:color-mix(in srgb,var(--work) 10%,transparent)}.msg .reacts .pill:hover{border-color:var(--ink-3)}.msg .reacts .add{padding:3px 7px;border-radius:999px;font-size:12px;color:var(--ink-3);opacity:0;transition:opacity .12s}.msg:hover .reacts .add,.msg .reacts .add:focus-visible{opacity:1}.msg .reacts .add:hover{color:var(--ink);background:var(--line)}.emoji-picker{position:fixed;z-index:50;width:296px;max-height:320px;overflow-y:auto;padding:6px 8px 8px;border-radius:12px;border:1px solid var(--line);background:var(--paper);box-shadow:0 10px 30px #00000029}.emoji-picker[hidden]{display:none}.emoji-picker p{margin:6px 2px 2px;font-size:11px;font-weight:620;letter-spacing:.04em;text-transform:uppercase;color:var(--ink-3)}.emoji-picker .grid{display:grid;grid-template-columns:repeat(8,1fr)}.emoji-picker button{all:unset;cursor:pointer;display:grid;place-items:center;height:32px;border-radius:8px;font-size:19px}.emoji-picker button:hover,.emoji-picker button:focus-visible{background:var(--paper-2)}.msg .acts .icon{all:unset;cursor:pointer;display:inline-flex;padding:3px;margin:-3px;border-radius:6px;color:var(--ink-3)}.msg .acts .icon:hover,.msg .acts .icon:focus-visible{color:var(--ink);background:var(--t2)}.msg .acts .icon svg{width:15px;height:15px;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}.msg .acts .icon.quiet{opacity:0;transition:opacity .12s}.msg:hover .acts .icon.quiet,.msg .acts .icon.quiet:focus-visible{opacity:1}@media(hover:hover){.msg:hover{background:var(--t1)}.msg .acts:not(:has(>:not(.quiet))){position:absolute;top:9px;right:46px;margin:0;padding:0}}.msg .thread-sum{all:unset;cursor:pointer;display:flex;align-items:center;gap:6px;margin:6px 0 0 8px;padding:4px 8px;border-radius:8px;font-size:12.5px;max-width:calc(100% - 24px);box-sizing:border-box}.msg .thread-sum:hover,.msg .thread-sum:focus-visible{background:var(--t1)}.msg .thread-sum .faces{display:flex;flex:none}.msg .thread-sum .faces .av{margin-right:-5px;border-radius:50%;box-shadow:0 0 0 1.5px var(--paper)}.msg .thread-sum .faces .face{width:18px;height:18px}.msg .thread-sum b{flex:none;font-weight:620;color:var(--accent);margin-left:2px}.msg .thread-sum .last{color:var(--ink-3);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.thread-head{flex:none;display:flex;align-items:center;gap:12px;padding:12px 20px 10px;border-bottom:1px solid var(--line);font-size:13px}.thread-count{margin:0;font-size:11.5px;color:var(--ink-3);display:flex;align-items:center;gap:8px}.thread-count:after{content:"";flex:1;height:1px;background:var(--line)}.msg .blocked{margin:6px 0 0 26px;font-size:12.5px;color:var(--bad)}.link{all:unset;cursor:pointer;font-size:12.5px;font-weight:600;color:var(--accent)}.link:hover{text-decoration:underline;text-underline-offset:2px}.msg .acts .link{font-weight:560}.tag{font-weight:600;color:var(--accent)}.typing{flex:none;padding:0 20px 8px 34px;font-size:12px;color:var(--ink-3);display:flex;align-items:center;gap:3px}.typing span{width:4px;height:4px;border-radius:50%;background:var(--ink-3);animation:dot 1.1s infinite}.typing span:nth-child(2){animation-delay:.15s}.typing span:nth-child(3){animation-delay:.3s;margin-right:5px}@keyframes dot{30%{transform:translateY(-3px);opacity:1}0%,60%,to{opacity:.4}}.composer{flex:none;position:relative;margin:0 12px 12px;border:1px solid var(--line);border-radius:14px;background:var(--surface);padding:10px 10px 8px 12px;box-shadow:0 1px 2px #00000008;transition:border-color .15s,box-shadow .15s}.composer:focus-within{border-color:var(--ink-3);box-shadow:0 0 0 4px var(--t1)}.attn{display:flex;flex-direction:column;gap:4px;margin:0 0 8px;max-height:84px;overflow-y:auto}.attn[hidden]{display:none}.attn-item{all:unset;box-sizing:border-box;cursor:pointer;display:flex;align-items:center;gap:8px;padding:4px 8px;border-radius:8px;background:var(--bad-bg);color:var(--bad-fg);font-size:12px;line-height:1.3}.attn-item:hover{filter:brightness(.97)}.attn-item i{flex:none;width:6px;height:6px;border-radius:50%;background:var(--bad);font-size:0;animation:attn-pulse 2s ease-in-out infinite}.attn-item span{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.attn-item b{font-weight:640;margin-right:4px}.attn-item svg{flex:none;width:14px;height:14px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}.attn-item:focus-visible{outline:2px solid var(--bad);outline-offset:1px}@keyframes attn-pulse{50%{box-shadow:0 0 0 4px color-mix(in srgb,var(--bad) 25%,transparent)}}@media(prefers-reduced-motion:reduce){.attn-item i{animation:none}}.msg.ping{animation:ping 1.8s ease-out}@keyframes ping{0%,40%{background:var(--bad-bg)}}.composer textarea{all:unset;display:block;width:100%;font-size:14px;line-height:1.45;min-height:20px;white-space:pre-wrap;overflow-y:auto}.composer textarea::placeholder{color:var(--ink-3)}.composer .controls{display:flex;align-items:center;gap:3px;margin-top:8px}.composer .controls>button{flex:none}.composer .controls select{border:0;background:var(--t1);font-size:12px;padding:4px 18px 4px 6px;border-radius:7px;color:var(--ink-2);flex:0 1 auto;min-width:72px;text-overflow:ellipsis;outline:none;-moz-appearance:none;appearance:none;-webkit-appearance:none;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 6' fill='none' stroke='%23958d81' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1 1l4 4 4-4'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 6px center;background-size:9px 6px}.composer .controls select:hover{background-color:var(--t2)}.composer .controls #model{flex:0 1 160px}.composer .controls button[type=submit]{margin-left:auto}.ac{position:absolute;left:0;right:0;bottom:calc(100% + 6px);background:var(--surface);border:1px solid var(--line);border-radius:12px;box-shadow:0 10px 30px #281e0f24;padding:4px;max-height:280px;overflow-y:auto;z-index:5}.ac .item{display:flex;align-items:center;gap:8px;padding:7px 9px;border-radius:8px;cursor:pointer;font-size:13.5px}.ac .item.on{background:var(--t2)}.ac .item i{width:8px;height:8px;border-radius:50%;flex:none}.ac .item i.hash{width:auto;height:auto;font-style:normal;color:var(--ink-3);font-weight:600}.ac .item span{font-weight:560}.ac .item em{margin-left:auto;font-style:normal;font-size:12px;color:var(--ink-3)}.ac:not(.faces) .item span small{font-size:inherit;font-weight:500;color:var(--ink-3)}.ac.faces{display:flex;flex-wrap:wrap;gap:2px;padding:6px}.ac.faces .item{position:relative;flex-direction:column;gap:4px;width:64px;padding:6px 2px;text-align:center;font-size:12px}.ac.faces .item .av{display:inline-flex}.ac.faces .item .av .face{display:block;width:36px;height:36px;border-radius:50%}.ac.faces .item span{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ac.faces .item em{position:absolute;top:6px;right:10px;margin:0;width:9px;height:9px;border-radius:50%;box-shadow:0 0 0 2px var(--surface)}.ac.faces .item em.free{background:#4caf7d}.ac.faces .item em.busy{background:#e0a43a}.ac.faces .item .av.away .face{box-shadow:0 0 0 2px var(--surface),0 0 0 3.5px var(--ink-3)}.ac.faces .item small{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;padding:1px 6px;border-radius:99px;background:var(--t2);color:var(--ink-3);font-size:10px;font-weight:600}.primary,.ghost{border:0;cursor:pointer;border-radius:10px;padding:10px 14px;font-weight:600;display:inline-flex;align-items:center;justify-content:center;gap:8px;transition:transform .12s,background .15s,opacity .15s}.primary{background:var(--ink);color:var(--paper)}.primary:hover{background:color-mix(in srgb,var(--ink) 85%,var(--paper))}.primary:active,.ghost:active{transform:scale(.97)}.ghost{background:transparent;color:var(--ink-2)}.ghost:hover{background:var(--t2);color:var(--ink)}.ghost.danger{color:var(--bad)}.small{padding:7px 12px;font-size:13px}select{border:1px solid var(--line);border-radius:8px;padding:6px 8px;background:var(--surface)}.hud{position:absolute;top:14px;right:14px;display:flex;gap:8px;pointer-events:none}.chip{pointer-events:auto;display:flex;align-items:center;height:38px;padding:0 14px;gap:16px;background:var(--glass);backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);border:1px solid var(--line);border-radius:12px;font-size:13px;color:var(--ink-2);box-shadow:0 1px 2px #0000000a,0 6px 18px #3c2d190f}#stats span{white-space:nowrap}#stats b{color:var(--ink);font-weight:650;font-variant-numeric:tabular-nums;margin-right:3px}.chip.tools{padding:0 4px;gap:2px}.chip.tools button{all:unset;cursor:pointer;width:30px;height:30px;display:grid;place-items:center;border-radius:8px;color:var(--ink-2);transition:background .15s,color .15s,transform .12s}.chip.tools button:hover{background:var(--t2);color:var(--ink)}.chip.tools button:active{transform:scale(.92)}.chip.tools button:disabled{opacity:.4;pointer-events:none}.chip.tools svg{width:17px;height:17px;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}.chip .sep{width:1px;height:18px;background:var(--line);margin:0 3px}.hint{position:absolute;bottom:14px;left:50%;transform:translate(-50%);margin:0;font-size:12px;color:var(--ink-3);white-space:nowrap;pointer-events:none;transition:opacity .6s}.hint.gone{opacity:0}.detail{width:440px;display:flex;flex-direction:column;min-height:0;padding-top:18px;background:var(--pane);border-left:1px solid var(--pane-edge);-webkit-backdrop-filter:blur(24px) saturate(1.5);backdrop-filter:blur(24px) saturate(1.5);animation:open .3s var(--ease)}@keyframes open{0%{opacity:0;transform:translate(12px)}}.d-head{display:flex;justify-content:space-between;align-items:center;padding:0 20px}.x{all:unset;cursor:pointer;font-size:22px;line-height:1;color:var(--ink-3);padding:2px 6px;border-radius:6px}.x:hover{color:var(--ink);background:var(--t2)}.pill{font-size:11.5px;font-weight:620;letter-spacing:.02em;text-transform:uppercase;padding:3px 8px;border-radius:6px}.pill.queued{background:var(--wait-bg);color:var(--wait-fg)}.pill.working{background:var(--work-bg);color:var(--work-fg)}.pill.done{background:var(--good-bg);color:var(--good-fg)}.pill.failed{background:var(--bad-bg);color:var(--bad-fg)}.pill.stopped{background:var(--t2);color:var(--ink-2)}.detail h2{margin:12px 20px;font-size:18px;font-weight:650;letter-spacing:-.015em;line-height:1.3;text-wrap:balance}.meta{margin:0 20px 14px;display:grid;grid-template-columns:repeat(3,1fr);gap:10px 12px}.meta dt{font-size:11px;color:var(--ink-3);margin-bottom:1px}.meta dd{margin:0;font-size:13px;font-weight:550;font-variant-numeric:tabular-nums;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.log{flex:1;overflow-y:auto;padding:14px 20px 16px;border-top:1px solid var(--line)}.e{margin:0 0 6px}.e p{margin:0;white-space:pre-wrap;overflow-wrap:anywhere}.e .who{display:block;font-size:11px;font-weight:620;letter-spacing:.04em;text-transform:uppercase;color:var(--ink-3);margin-bottom:3px}.e.user{margin:4px 0 14px;padding:10px 12px;background:var(--t1);border-radius:10px}.e.text{margin:10px 0 12px}.e.sys{font-size:12px;color:var(--ink-3)}.e.tool{font-family:var(--mono);font-size:12px;color:var(--ink-2);display:flex;align-items:center;gap:8px}.e.err{font-family:var(--mono);font-size:12px;color:var(--bad);white-space:pre-wrap;overflow-wrap:anywhere}.e.result{margin:14px 0 6px;padding:12px;border-radius:10px;background:var(--good-bg)}.e.result.bad{background:var(--bad-bg)}.st{flex:none;width:7px;height:7px;border-radius:2px;background:var(--ink-3)}.st.library{background:#3d7ea6}.st.servers{background:#2b2f38}.st.window{background:#4f8fc0;border-radius:50%}.st.whiteboard{background:#e07a5f}.st.desk{background:#c39a6b}code{font-family:var(--mono);font-size:.88em;background:var(--t2);padding:1px 4px;border-radius:4px}.d-foot{border-top:1px solid var(--line);padding:12px 20px 16px;display:flex;flex-direction:column;gap:10px}.notice{font-size:13px;color:var(--ink-2);display:flex;flex-direction:column;align-items:flex-start;gap:8px}.reply textarea{width:100%;resize:none;border:1px solid var(--line);border-radius:10px;padding:9px 11px;background:var(--surface);outline:none}.reply textarea:focus{border-color:var(--ink-3)}.reply .row{display:flex;justify-content:space-between;gap:8px;margin-top:8px}.md>:first-child{margin-top:0}.md>:last-child{margin-bottom:0}.md p{margin:0 0 8px;white-space:normal}.md h1,.md h2,.md h3,.md h4{font-size:14px;font-weight:650;margin:12px 0 6px;letter-spacing:-.01em}.md ul,.md ol{margin:0 0 8px;padding-left:20px}.md li{margin:2px 0}.md a{color:var(--accent)}.md pre{font-family:var(--mono);font-size:12px;background:var(--t1);padding:10px 12px;border-radius:8px;overflow-x:auto;margin:0 0 8px}.md pre code{background:none;padding:0}.md table{border-collapse:collapse;width:100%;font-size:12.5px;margin:4px 0 10px;display:block;overflow-x:auto}.md th,.md td{text-align:left;padding:5px 10px 5px 0;border-bottom:1px solid var(--line);vertical-align:top}.md th{font-weight:620;color:var(--ink-2)}.md td{font-variant-numeric:tabular-nums}.md blockquote{margin:0 0 8px;padding-left:10px;border-left:2px solid var(--line);color:var(--ink-2)}.agent-label{position:absolute;left:0;top:0;display:flex;flex-direction:column;align-items:center;gap:5px;will-change:transform}.agent-label .name{display:flex;align-items:center;gap:5px;font-size:11.5px;font-weight:620;background:var(--glass);padding:2px 8px 2px 6px;border-radius:99px;color:var(--ink);box-shadow:0 1px 3px #0000001a}.agent-label .name i{width:7px;height:7px;border-radius:50%}.agent-label.richest .name:after{content:"👑";margin-left:2px;font-size:13px;line-height:1}.agent-label.selected .name{background:var(--ink);color:var(--paper)}.agent-label.far .bubble,.agent-label.crowded .bubble{display:none!important}.agent-label.buried{visibility:hidden}.bubble{max-width:170px;font-size:12px;font-weight:500;line-height:1.3;padding:5px 9px;border-radius:11px;background:var(--surface);color:var(--ink);box-shadow:0 2px 10px #281e0f24;text-align:center;overflow:hidden;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;animation:bub .2s ease-out}@keyframes bub{0%{opacity:0;transform:translateY(4px) scale(.96)}}.bubble.thinking{color:var(--ink-3);font-style:italic}.bubble.idle{color:var(--ink-2)}.bubble.warn{background:var(--bad-bg);color:var(--bad-fg)}.bubble.good{background:var(--good-bg);color:var(--good-fg)}.bubble.talk{background:var(--work-bg);color:var(--work-fg)}.agent-chat{position:absolute;left:0;top:0;width:264px;z-index:20000;pointer-events:auto;will-change:transform;background:var(--surface);color:var(--ink);border-radius:14px;box-shadow:0 8px 28px #281e0f3d,0 0 0 1px var(--line);display:flex;flex-direction:column;animation:bub .18s ease-out}.agent-chat[hidden]{display:none}.ac-head{display:flex;align-items:center;gap:6px;padding:8px 8px 6px 11px;font-size:12.5px}.ac-head i{width:8px;height:8px;border-radius:50%;background:var(--ink-3);flex:none}.ac-head b{font-weight:650}.ac-sub{color:var(--ink-3);font-size:11.5px;flex:1}.ac-open,.ac-x{border:0;background:transparent;color:var(--ink-2);cursor:pointer;font:inherit;font-size:11.5px;border-radius:7px;padding:2px 6px}.ac-x{font-size:17px;line-height:1;padding:0 6px}.ac-open:hover,.ac-x:hover{background:var(--line);color:var(--ink)}.ac-log{max-height:150px;overflow-y:auto;padding:2px 10px 6px;display:flex;flex-direction:column;gap:5px}.ac-msg{margin:0;font-size:12.5px;line-height:1.35;padding:5px 9px;border-radius:11px;max-width:88%;overflow-wrap:anywhere}.ac-msg.them{background:var(--work-bg);color:var(--work-fg);align-self:flex-start}.ac-msg.you{background:var(--ink);color:var(--paper);align-self:flex-end}.ac-msg.wait{color:var(--ink-3);animation:acpulse 1s ease-in-out infinite}.ac-msg.bad{background:var(--bad-bg);color:var(--bad-fg);align-self:flex-start}@keyframes acpulse{50%{opacity:.4}}.ac-form{display:flex;gap:6px;padding:6px 8px 8px;border-top:1px solid var(--line)}.ac-form input{flex:1;min-width:0;font:inherit;font-size:16px;padding:5px 10px;border-radius:99px;border:1px solid var(--line);background:var(--paper);color:var(--ink)}.ac-send{width:30px;height:30px;flex:none;border:0;border-radius:50%;background:var(--ink);color:var(--paper);cursor:pointer;font-size:15px}.ac-tail{position:absolute;bottom:-6px;width:12px;height:12px;margin-left:-6px;background:var(--surface);transform:rotate(45deg);box-shadow:2px 2px 3px #281e0f1a}@media(prefers-reduced-motion:reduce){.agent-chat,.ac-msg.wait{animation:none}}.xpfloat{position:absolute;top:-10px;font-size:14px;font-weight:720;color:var(--good-fg);animation:float 1.8s ease-out forwards;text-shadow:0 1px 0 var(--paper)}@keyframes float{0%{opacity:0;transform:translateY(8px)}15%{opacity:1}to{opacity:0;transform:translateY(-36px)}}.toast{position:absolute;left:50%;bottom:44px;transform:translate(-50%,12px);opacity:0;background:var(--ink);color:var(--paper);padding:10px 16px;border-radius:12px;font-weight:500;transition:opacity .2s,transform .25s var(--ease);pointer-events:none;max-width:calc(100% - 32px)}.toast.show{opacity:1;transform:translate(-50%)}.toast.good{background:#22603b;color:#fff}.toast.bad{background:#8f3121;color:#fff}.toast.act{pointer-events:auto}.toast button{all:unset;cursor:pointer;margin-left:10px;font-weight:650;text-decoration:underline;text-underline-offset:3px}.chip.away{gap:4px;padding:0 6px 0 12px}.chip.away span{margin-right:4px;color:var(--ink-3);white-space:nowrap}.chip.away button{all:unset;cursor:pointer;display:flex;align-items:center;gap:6px;height:28px;padding:0 9px;border-radius:8px;color:var(--ink);font-weight:550;transition:background .15s}.chip.away button:hover{background:var(--t2)}.chip.away i{width:8px;height:8px;border-radius:50%}.banner{position:absolute;left:50%;top:32%;transform:translate(-50%,-50%);text-align:center;pointer-events:none;opacity:0;display:flex;flex-direction:column;gap:4px}.banner b{font-size:56px;font-weight:760;letter-spacing:-.04em;line-height:1;text-shadow:0 2px 30px var(--paper)}.banner span{font-size:16px;color:var(--ink-2);font-weight:520}.banner.show{animation:banner 3.4s var(--ease) forwards}@keyframes banner{0%{opacity:0;transform:translate(-50%,-40%) scale(.94)}12%,78%{opacity:1;transform:translate(-50%,-50%) scale(1)}to{opacity:0;transform:translate(-50%,-56%)}}@media(max-width:1180px){.app{grid-template-columns:min(var(--side-w, 320px),320px) minmax(0,1fr) auto}.detail{width:380px}}@container (max-width: 820px){#stats span:nth-child(n+3){display:none}.hint{display:none}}@container (max-width: 520px){#stats{display:none}}.mnav{display:none}@media(max-width:860px){.app{grid-template-columns:minmax(0,1fr);grid-template-rows:minmax(0,1fr) auto}.view,.side{grid-area:1 / 1;min-width:0}.side-grip{display:none}.app[data-m=office] .side,.app[data-m=side] .view{visibility:hidden;pointer-events:none}.side{border-right:0;padding-top:env(safe-area-inset-top)}.brand{display:block;padding:12px 16px 8px}.brand .title{margin-bottom:6px}.brand h1{font-size:18px}.tabs{display:none}.msgs{padding:12px 14px 8px}.channels{padding:8px 10px 0}.channel{padding:7px 12px;font-size:13.5px}.composer{margin:0 10px 10px}.composer textarea,.new-channel input,input,select,textarea{font-size:16px}.composer .controls{gap:6px}.composer .controls>button{min-width:38px;min-height:38px;justify-content:center;align-items:center}.composer .controls select{font-size:13px;min-height:36px;padding-right:22px}.composer .controls button[type=submit]{min-height:38px;padding:0 18px}#jobsPane,.team,.projects{padding-bottom:12px}.hud{top:calc(10px + env(safe-area-inset-top));left:10px;right:10px;flex-direction:column;align-items:flex-end}.chip.tools button{width:36px;height:36px}.chip.away{max-width:100%;height:auto;min-height:38px;flex-wrap:wrap;padding:4px 6px 4px 12px}.hint,#stats{display:none}.toast{max-width:calc(100% - 24px);bottom:18px}.banner b{font-size:40px}.detail{position:fixed;top:0;right:0;bottom:0;left:0;width:auto;z-index:30;padding-top:calc(14px + env(safe-area-inset-top));padding-bottom:env(safe-area-inset-bottom);border-left:0}.meta{margin:0 16px 14px}.detail h2{margin:12px 16px}.d-head{padding:0 16px}.x{font-size:28px;padding:4px 12px}.mnav{display:grid;grid-template-columns:repeat(5,1fr);grid-row:2;z-index:25;background:color-mix(in srgb,var(--paper) 96%,transparent);border-top:1px solid var(--line);padding-bottom:env(safe-area-inset-bottom)}.mnav button{all:unset;cursor:pointer;position:relative;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;min-height:54px;font-size:11px;font-weight:600;color:var(--ink-3);-webkit-tap-highlight-color:transparent;transition:color .15s}.mnav button.on{color:var(--ink)}.mnav button:active svg{transform:scale(.88)}.mnav button:focus-visible{outline:2px solid var(--accent);outline-offset:-4px;border-radius:10px}.mnav svg{width:22px;height:22px;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round;transition:transform .12s}.mnav b:not(:empty){position:absolute;top:5px;left:calc(50% + 6px);font-size:10.5px;background:var(--accent);color:var(--paper);border-radius:99px;padding:0 5px;line-height:15px;font-weight:700}.mnav .dot{position:absolute;top:8px;left:calc(50% + 8px);width:8px;height:8px;border-radius:50%;background:var(--accent)}}@media(hover:none){.chip.tools button:hover,.channel:hover{background:none}}body{overscroll-behavior:none;-webkit-tap-highlight-color:transparent}@media(prefers-reduced-motion:reduce){*,*:before,*:after{animation-duration:.01ms!important;transition-duration:.01ms!important}}.attach{border:0;background:none;cursor:pointer;padding:4px;border-radius:7px;color:var(--ink-3);display:inline-flex}.attach:hover{background:var(--t1);color:var(--ink-2)}.attach svg{width:16px;height:16px;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}.composer.dropping,.reply.dropping{border-color:var(--work);box-shadow:0 0 0 4px var(--t2)}.reply.dropping textarea{border-color:var(--work)}.tray{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:8px}.tray .file,.files .file{display:inline-flex;align-items:center;gap:6px;max-width:200px;padding:3px 4px 3px 3px;border-radius:8px;background:var(--t1);font-size:12px;color:var(--ink-2);text-decoration:none}.tray .file.loading{opacity:.55}.tray .file img{width:28px;height:28px;object-fit:cover;border-radius:6px;flex:none}.tray .file b,.files .file b{font-size:9px;font-weight:700;letter-spacing:.04em;color:var(--ink-3);background:var(--surface);border-radius:5px;padding:5px 4px;flex:none}.tray .file span,.files .file span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.tray .file button{border:0;background:none;cursor:pointer;color:var(--ink-3);font-size:15px;line-height:1;padding:0 3px}.tray .file button:hover{color:var(--ink)}.msg .files{display:flex;flex-wrap:wrap;gap:6px;padding-left:14px;margin-top:4px}.msg .files .thumb img{display:block;max-width:160px;max-height:120px;border-radius:8px;border:1px solid var(--line)}.reply .row .attach{margin-left:auto}.mic{border:0;background:none;cursor:pointer;padding:4px;border-radius:7px;color:var(--ink-3);display:inline-flex}.mic:hover{background:var(--t1);color:var(--ink-2)}.mic:disabled{opacity:.45;pointer-events:none}.mic svg{width:16px;height:16px;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}.mic.on{color:#fff;background:var(--bad)}.mic.on:hover{background:var(--bad);color:#fff}.rec{display:flex;align-items:center;gap:8px;margin-bottom:8px;font-size:12.5px;color:var(--ink-2)}.rec i{width:8px;height:8px;border-radius:50%;background:var(--bad);flex:none;animation:pulse 1.1s ease-in-out infinite}.rec span{font-variant-numeric:tabular-nums}.rec .link{margin-left:auto;color:var(--ink-3)}.rec .link+.link{margin-left:0}.rec.working i{background:var(--work)}@keyframes pulse{0%,to{opacity:1;transform:scale(1)}50%{opacity:.35;transform:scale(.8)}}@media(prefers-reduced-motion:reduce){.rec i{animation:none}}audio.voice{width:100%;max-width:260px;height:32px}.msg .files audio.voice{margin-top:2px}.tray .file b{white-space:nowrap}.chip.tools button.on{color:var(--accent);background:color-mix(in srgb,var(--accent) 14%,transparent)}.changes{margin:0 20px 14px;border:1px solid var(--line);border-radius:10px;background:var(--paper);overflow:hidden}.changes.none{padding:9px 12px;font-size:12.5px;color:var(--ink-3)}.c-head{all:unset;box-sizing:border-box;width:100%;display:flex;align-items:center;gap:10px;padding:9px 12px;cursor:pointer;font-size:13px}.c-head:hover{background:color-mix(in srgb,var(--ink) 4%,transparent)}.c-head:focus-visible,.c-file:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}.c-title{font-weight:620}.c-sum{flex:1;color:var(--ink-2);font-variant-numeric:tabular-nums}.c-caret{color:var(--ink-3)}.changes .add{color:var(--good-fg);font-weight:600}.changes .del{color:var(--bad-fg);font-weight:600}.c-files{list-style:none;margin:0;padding:0;border-top:1px solid var(--line);max-height:240px;overflow-y:auto}.c-files li{border-bottom:1px solid var(--line)}.c-files li:last-child{border-bottom:0}.c-files .more{padding:7px 12px;font-size:12px;color:var(--ink-3)}.c-file{all:unset;box-sizing:border-box;width:100%;display:flex;align-items:center;gap:8px;padding:6px 12px;cursor:pointer;font-size:12.5px}.c-file:hover{background:color-mix(in srgb,var(--ink) 4%,transparent)}.c-file .st{font:700 10.5px/1 ui-monospace,monospace;width:16px;text-align:center;padding:3px 0;border-radius:4px;background:var(--t2);color:var(--ink-2)}.c-file .st.added{background:var(--good-bg);color:var(--good-fg)}.c-file .st.deleted{background:var(--bad-bg);color:var(--bad-fg)}.c-file .p{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;direction:rtl;text-align:left;font-family:ui-monospace,monospace}.c-file .n{color:var(--ink-3);font-variant-numeric:tabular-nums}.c-diff{margin:0;padding:8px 12px;max-height:320px;overflow:auto;font:11.5px/1.5 ui-monospace,monospace;background:color-mix(in srgb,var(--ink) 3%,transparent);white-space:pre}.c-diff .add{color:var(--good-fg);background:var(--good-bg);display:inline-block;min-width:100%;font-weight:400}.c-diff .del{color:var(--bad-fg);background:var(--bad-bg);display:inline-block;min-width:100%;font-weight:400}.c-diff .hunk{color:var(--ink-3)}.name-ask{border:1px solid var(--line);border-radius:16px;padding:22px;max-width:380px;width:calc(100vw - 48px);background:var(--paper);color:inherit;box-shadow:0 24px 60px #00000040}.name-ask::backdrop{background:#00000059}.name-ask h2{margin:0 0 8px;font-size:18px}.name-ask .acct-forget{display:block;margin:12px 0 0}.meet{max-width:420px}.meet-list{display:grid;gap:6px;margin-top:14px;max-height:min(420px,55dvh);overflow-y:auto;padding:2px}.meet-row{display:grid;grid-template-columns:10px minmax(0,1fr) auto;align-items:center;gap:10px}.meet-row i{width:10px;height:10px;border-radius:50%}.meet-row input{min-width:0;padding:6px 9px;border-radius:8px;border:1px solid var(--line);background:var(--paper-2);color:var(--ink);font:inherit;font-size:13px;font-weight:550}.meet-row input:focus-visible{outline:2px solid var(--accent);outline-offset:-1px}.meet-row input:invalid{border-color:var(--bad)}.meet-role{font-size:12px;color:var(--ink-3);text-align:right;white-space:nowrap}.meet-foot{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-top:14px}.meet .meet-foot .acct-forget{margin:0}.settings{width:min(640px,calc(100vw - 24px));max-height:min(720px,calc(100dvh - 24px));padding:0;margin:auto;display:none;flex-direction:column;overflow:hidden;box-sizing:border-box;color:var(--ink);background:var(--paper);border:1px solid var(--line);border-radius:16px;box-shadow:0 24px 60px #00000047}.settings[open]{display:flex}.settings::backdrop{background:#00000052;-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px)}.set-head,.set-foot{flex:none}.set-head{display:flex;align-items:center;justify-content:space-between;padding:16px 18px 12px 22px;border-bottom:1px solid var(--line)}.set-head h2{margin:0;font-size:17px;font-weight:650;letter-spacing:-.01em}.set-x{width:30px;height:30px}.set-body{flex:1 1 auto;min-height:0;overflow-y:auto;padding:4px 22px 8px;overscroll-behavior:contain}.set-group{padding:8px 0 4px}.set-group+.set-group{border-top:1px solid var(--line)}.set-group .theme-k{margin:10px 0 4px}.set-row{display:grid;grid-template-columns:minmax(0,1fr) minmax(150px,220px);gap:8px 18px;align-items:center;padding:10px 0;position:relative}.set-row.set-changed:before{content:"";position:absolute;left:-12px;top:12px;bottom:12px;width:2px;border-radius:2px;background:var(--accent)}.set-label{font-size:13.5px;font-weight:580;color:var(--ink)}.set-fine{margin:2px 0 0}.set-reset{display:inline;margin:0;font-size:inherit}.set-input{width:100%;box-sizing:border-box;padding:7px 10px;border-radius:9px;border:1px solid var(--line);background:var(--paper-2);color:var(--ink);font:inherit;font-size:13px;font-variant-numeric:tabular-nums}.set-input:focus-visible{outline:2px solid var(--accent);outline-offset:-1px}.set-choice{width:100%;box-sizing:border-box}.set-choice button{text-transform:capitalize}.set-switch{all:unset;cursor:pointer;justify-self:end;position:relative;width:38px;height:22px;border-radius:11px;background:var(--t3);transition:background .18s}.set-switch:after{content:"";position:absolute;top:2px;left:2px;width:18px;height:18px;border-radius:50%;background:#fff;box-shadow:0 1px 3px #0000004d;transition:transform .18s cubic-bezier(.2,.8,.2,1)}.set-switch[aria-checked=true]{background:var(--accent)}.set-switch[aria-checked=true]:after{transform:translate(16px)}.set-switch:focus-visible{outline:2px solid var(--accent);outline-offset:2px}.set-foot{display:flex;align-items:center;gap:12px;padding:12px 22px 14px;border-top:1px solid var(--line);background:var(--paper-2)}.set-msg{flex:1;font-size:12px;color:var(--ink-3)}.set-foot .acct-forget{margin:0}@media(max-width:520px){.set-row{grid-template-columns:1fr}.set-switch{justify-self:start}}@media(prefers-reduced-motion:reduce){.set-switch,.set-switch:after{transition:none}}.model-pick{font:inherit;font-weight:550;max-width:100%;padding:1px 4px;margin-left:-5px;border:1px solid transparent;border-radius:6px;background:transparent;color:inherit;cursor:pointer}.model-pick:hover,.model-pick:focus-visible{border-color:var(--line, rgba(0,0,0,.15));background:#fff9}.model-pick:disabled{opacity:.5;cursor:progress}.model-note{display:block;font-size:11px;font-weight:400;color:var(--ink-3)}.meta-wrap{margin:0 0 14px}.meta-wrap .meta{margin-top:8px}.meta-wrap.shut .meta{display:none}.meta-fold{display:flex;align-items:center;gap:6px;margin:0 20px;padding:4px 0;border:0;background:none;font:inherit;font-size:12px;font-weight:600;color:var(--ink-3);cursor:pointer;min-height:28px}.meta-fold:hover{color:var(--ink)}.meta-fold .chev{display:inline-block;transition:transform .15s ease}.meta-wrap.shut .chev{transform:rotate(-90deg)}.meta-sum{display:none;font-weight:400}.meta-wrap.shut .meta-sum{display:inline}@media(max-width:700px){.meta-fold{margin:0 16px}}.coin{display:inline-block;flex:none;width:.95em;height:.95em;border-radius:50%;vertical-align:-.12em;background:radial-gradient(circle at 35% 30%,#fff1b8 0,#fff1b8 18%,#f2c14e 40%,#c98f1c);box-shadow:inset 0 0 0 1px #96640a73}.coins{display:inline-flex;align-items:center;gap:4px;font-weight:650;font-variant-numeric:tabular-nums;color:var(--ink);white-space:nowrap}.chip.pot{all:unset;pointer-events:auto;cursor:pointer;box-sizing:border-box;display:flex;align-items:center;gap:6px;height:38px;padding:0 12px;background:var(--glass);backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);border:1px solid var(--line);border-radius:12px;box-shadow:0 1px 2px #0000000a,0 6px 18px #3c2d190f;font-size:13px;color:var(--ink-2);-webkit-tap-highlight-color:transparent;transition:background .15s,transform .12s}.chip.pot[hidden]{display:none}.chip.pot b{color:var(--ink);font-weight:680;font-variant-numeric:tabular-nums}.chip.pot span{padding-left:8px;margin-left:2px;border-left:1px solid var(--line);font-weight:600}.chip.pot.shop-door span{padding-left:0;margin-left:0;border-left:0;white-space:nowrap}.chip.pot.shop-door i{font-style:normal}.chip.pot:active{transform:scale(.96)}.chip.pot:focus-visible{outline:2px solid var(--accent);outline-offset:2px}@media(hover:hover){.chip.pot:hover{background:var(--paper);color:var(--ink)}}.chip.pot.bump b{display:inline-block;animation:coinhop .6s var(--ease)}@keyframes coinhop{30%{transform:translateY(-5px) rotateY(180deg)}to{transform:none}}.xpfloat.coinfloat{top:-34px;color:#a8740f;white-space:nowrap;animation-duration:2.3s;animation-delay:.35s;opacity:0;animation-fill-mode:forwards}.xpfloat.coinfloat.win{color:var(--work-fg);top:-56px;animation-delay:.8s}.xpfloat.coinfloat.gift{font-size:22px}[data-mode=dark] .xpfloat.coinfloat{color:#f2c14e}.tile .tile-coins{font-size:11.5px;font-weight:620;color:var(--ink-2);margin-top:1px}.member .n .tile-coins{float:right;font-size:12px;font-weight:620;color:var(--ink-2);margin-top:1px}.notice.kudos{display:flex;flex-direction:row;align-items:center;justify-content:space-between;gap:10px;flex-wrap:wrap}.notice.kudos:empty{display:none}.notice.kudos .coins{font-size:inherit}.notice.kudos button{background:var(--t1);color:var(--ink);padding:7px 12px}.notice.kudos button:hover{background:var(--t2)}.kudos-amt{color:#a8740f;font-variant-numeric:tabular-nums}[data-mode=dark] .kudos-amt{color:#f2c14e}.shop{width:min(760px,calc(100vw - 24px));height:min(760px,calc(100dvh - 24px))}.shop-head{flex:none;display:flex;align-items:center;gap:12px;padding:14px 14px 10px 22px}.shop-head h2{margin:0;font-size:17px;font-weight:650;letter-spacing:-.01em}.shop-pot{margin-left:auto;display:flex;align-items:baseline;gap:6px}.shop-pot .coins{font-size:17px}.shop-pot small{font-size:12px;color:var(--ink-3)}.shop-x{width:32px;height:32px}.shop-tabs{flex:none;display:flex;gap:2px;margin:0 22px;padding:2px;border-radius:10px;background:var(--t1);overflow-x:auto;scrollbar-width:none;overscroll-behavior-x:contain}.shop-tabs::-webkit-scrollbar{display:none}.shop-tabs button{all:unset;cursor:pointer;flex:1 0 auto;text-align:center;padding:7px 12px;border-radius:8px;font-size:13px;font-weight:600;color:var(--ink-3);white-space:nowrap;-webkit-tap-highlight-color:transparent;transition:background .15s,color .15s}.shop-tabs button[aria-selected=true]{color:var(--ink);background:var(--surface);box-shadow:0 1px 2px #00000014}.shop-tabs button:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}.shop-body{flex:1 1 auto;min-height:0;overflow-y:auto;padding:6px 22px 22px;overscroll-behavior:contain;-webkit-overflow-scrolling:touch}.shop-lede{margin:12px 0 10px;font-size:12.5px;color:var(--ink-3);line-height:1.45;text-wrap:pretty}.shop-h{margin:18px 0 0;font-size:13px;font-weight:650;color:var(--ink)}.shop-h+.shop-grid{margin-top:10px}.shop-empty{margin:40px 0;text-align:center;color:var(--ink-3);font-size:13px}.shop-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(132px,1fr));gap:8px}.shop-grid.wide{grid-template-columns:repeat(auto-fill,minmax(200px,1fr))}.shop-card{display:flex;flex-direction:column;gap:4px;min-width:0;padding:12px;border-radius:12px;background:var(--surface);border:1px solid var(--line)}.shop-card.using{border-color:var(--accent);box-shadow:inset 0 0 0 1px var(--accent)}.sc-art{display:flex;height:38px;align-items:center}.sc-icon{font-size:28px;line-height:1}.sc-swatch{width:38px;height:38px;border-radius:10px;box-shadow:inset 0 0 0 1px #0000001f}.sc-name{font-size:13px;font-weight:620;color:var(--ink);line-height:1.3}.sc-blurb{font-size:12px;color:var(--ink-3);line-height:1.4;text-wrap:pretty}.sc-foot{margin-top:auto;padding-top:6px;display:flex;align-items:center;justify-content:space-between;gap:6px;min-height:32px}.sc-price{font-size:12.5px}.sc-free{font-size:12px;color:var(--ink-3);font-weight:600}.sc-btn{all:unset;cursor:pointer;box-sizing:border-box;min-height:30px;padding:0 12px;border-radius:8px;display:grid;place-items:center;font-size:12.5px;font-weight:650;background:var(--t2);color:var(--ink);white-space:nowrap;-webkit-tap-highlight-color:transparent;transition:background .15s,transform .12s}.sc-btn.buy{background:var(--ink);color:var(--paper)}.sc-btn.armed{background:#c98f1c;color:#fff}.sc-btn:active{transform:scale(.95)}.sc-btn:focus-visible{outline:2px solid var(--accent);outline-offset:2px}@media(hover:hover){.sc-btn:hover{background:var(--t3)}.sc-btn.buy:hover{background:color-mix(in srgb,var(--ink) 85%,var(--paper))}.sc-btn.armed:hover{background:#b07c14}}.sc-state{font-size:12px;font-weight:600;color:var(--ink-3)}.sc-state.on{color:var(--accent)}.sc-state.short{color:var(--ink-3);font-weight:500;font-variant-numeric:tabular-nums}.shop-people{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:8px}.shop-person{padding:12px;border-radius:12px;background:var(--surface);border:1px solid var(--line)}.sp-head{display:flex;align-items:center;gap:10px}.sp-face .face{display:block;width:36px;height:36px;border-radius:50%}.sp-who{flex:1;min-width:0;display:flex;flex-direction:column}.sp-who b{font-size:14px;font-weight:640}.sp-who small{font-size:12px;color:var(--ink-3);font-variant-numeric:tabular-nums}.sp-wallet{font-size:15px}.sp-items{display:flex;flex-wrap:wrap;align-items:center;gap:4px;margin-top:10px;min-height:32px}.sp-item{display:grid;place-items:center;width:30px;height:30px;border-radius:8px;background:var(--t1);font-size:17px}.sp-none{font-size:12.5px;color:var(--ink-3)}.sp-treat{all:unset;cursor:pointer;margin-left:auto;min-height:32px;padding:0 12px;border-radius:8px;font-size:12.5px;font-weight:650;color:var(--ink);background:var(--t1);-webkit-tap-highlight-color:transparent}.sp-treat:focus-visible{outline:2px solid var(--accent);outline-offset:2px}@media(hover:hover){.sp-treat:hover{background:var(--t2)}}.sp-shelf{margin-top:10px;padding-top:10px;border-top:1px solid var(--line)}.sp-shelf .shop-card{background:var(--paper-2)}.shop-wins{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:6px}.shop-wins li{display:flex;align-items:center;gap:12px;padding:10px 12px;border-radius:12px;background:var(--surface);border:1px solid var(--line)}.shop-wins li:not(.won){opacity:.7}.sw-badge{flex:none;width:30px;height:30px;display:grid;place-items:center;border-radius:50%;background:var(--t1);color:var(--ink-3);font-size:15px}.won .sw-badge{background:#f6e3ae;color:#a8740f}.sw-text{flex:1;min-width:0;display:flex;flex-direction:column}.sw-text b{font-size:13.5px;font-weight:620}.sw-text small{font-size:12px;color:var(--ink-3)}.sw-who{display:flex}.sw-face .face{display:block;width:22px;height:22px;border-radius:50%;box-shadow:0 0 0 2px var(--surface)}.sw-face+.sw-face{margin-left:-6px}.sw-bonus{font-size:12.5px;color:var(--ink-2)}.shop-rich{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:6px}.shop-rich li{display:flex;align-items:center;gap:12px;padding:10px 12px;border-radius:12px;background:var(--surface);border:1px solid var(--line)}.shop-rich li.top{border-color:#f2c14e;box-shadow:0 0 0 1px #f2c14e33}.sr-rank{flex:none;width:24px;text-align:center;font-weight:700;color:var(--ink-3);font-variant-numeric:tabular-nums}.sr-move{flex:none;min-width:28px;text-align:center;font-size:12px;font-weight:700;color:var(--ink-3);font-variant-numeric:tabular-nums}.sr-move.up{color:#2f9e5b}.sr-move.down{color:#d6453d}.sr-rival{display:block;font-style:italic}.sr-comeback{flex:none;padding:2px 8px;border-radius:999px;font-size:11px;font-weight:700;background:#f2c14e33;color:#8a6200;border:1px solid #f2c14e}.sr-worth{margin-left:auto;font-weight:700;font-variant-numeric:tabular-nums}.shop-ledger{list-style:none;margin:0;padding:0}.shop-ledger li{display:flex;align-items:baseline;gap:12px;padding:9px 0;border-bottom:1px solid var(--line)}.sl-text{flex:1;min-width:0;font-size:13px;color:var(--ink-2);line-height:1.4}.sl-text b{color:var(--ink);font-weight:620}.sl-text small{display:block;font-size:11.5px;color:var(--ink-3)}.sl-amt{flex:none;font-weight:650;font-variant-numeric:tabular-nums;font-size:13px}.sl-amt.in{color:var(--good-fg)}.sl-amt.out{color:var(--ink-2)}@media(max-width:600px){.shop{width:100vw;max-width:100vw;height:100dvh;max-height:100dvh;border-radius:0;border:0;padding-top:env(safe-area-inset-top);padding-bottom:env(safe-area-inset-bottom)}.shop-head{padding:10px 8px 8px 16px}.shop-x{width:44px;height:44px}.shop-tabs{margin:0 12px}.shop-tabs button{padding:9px 14px;font-size:14px}.shop-body{padding:4px 12px 24px}.shop-grid{grid-template-columns:repeat(2,minmax(0,1fr))}.shop-grid.wide{grid-template-columns:minmax(0,1fr)}.sc-btn,.sp-treat{min-height:40px;padding:0 14px;font-size:13.5px}.shop-pot small{display:none}.chip.pot{height:40px}.chip.pot span{display:none}}@media(prefers-reduced-motion:reduce){.chip.pot.bump b{animation:none}.sc-btn,.shop-tabs button,.chip.pot{transition:none}}.project .sub .map{all:unset;cursor:pointer;display:flex;align-items:center;gap:10px;margin:0 4px 4px;padding:10px 12px;border-radius:10px;background:var(--surface);box-shadow:0 0 0 1px var(--line);font-size:13px;font-weight:600;transition:box-shadow .15s,transform .12s}.project .sub .map:hover{box-shadow:0 0 0 1px color-mix(in srgb,var(--accent) 45%,transparent),0 2px 10px -4px color-mix(in srgb,var(--accent) 40%,transparent)}.project .sub .map:active{transform:scale(.985)}.project .sub .map:focus-visible{outline:2px solid var(--accent);outline-offset:2px}.project .sub .map svg{width:18px;height:18px;fill:none;stroke:var(--accent);stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round}.project .sub .map span:first-of-type{flex:1}.project .sub .map .go{color:var(--ink-3);transition:transform .15s var(--ease)}.project .sub .map:hover .go{transform:translate(2px);color:var(--accent)}.jmap{position:absolute;top:0;right:0;bottom:0;left:0;z-index:20;display:flex;flex-direction:column;background:var(--paper);animation:jm-in .22s var(--ease)}@keyframes jm-in{0%{opacity:0;transform:scale(.99)}}.jm-bar{display:flex;align-items:center;gap:12px;padding:10px 14px;min-height:58px;border-bottom:1px solid var(--line);background:var(--glass);-webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px);position:relative;z-index:2}.jm-x{all:unset;cursor:pointer;display:grid;place-items:center;width:34px;height:34px;border-radius:9px;color:var(--ink-2);flex:none}.jm-x:hover{background:var(--t2);color:var(--ink)}.jm-x:focus-visible{outline:2px solid var(--accent)}.jm-x svg{width:18px;height:18px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}.jm-title{display:flex;flex-direction:column;min-width:0;flex:none;max-width:30%}.jm-title b{font-size:15px;font-weight:650;letter-spacing:-.01em;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.jm-title span{font-size:12px;color:var(--ink-3);white-space:nowrap}.jm-fill{flex:1}.jm-picks{flex:1;display:flex;gap:4px;overflow-x:auto;scrollbar-width:none;padding:2px;-webkit-mask-image:linear-gradient(90deg,#000 calc(100% - 24px),transparent);mask-image:linear-gradient(90deg,#000 calc(100% - 24px),transparent)}.jm-picks::-webkit-scrollbar{display:none}.jm-picks button{all:unset;cursor:pointer;white-space:nowrap;padding:6px 10px;border-radius:8px;font-size:13px;font-weight:560;color:var(--ink-2);display:inline-flex;align-items:center;gap:6px;transition:background .15s,color .15s}.jm-picks button:hover{background:var(--t1);color:var(--ink)}.jm-picks button[aria-selected=true]{background:var(--ink);color:var(--paper)}.jm-picks button:focus-visible{outline:2px solid var(--accent)}.jm-picks i{font-style:normal;font-size:11px;font-variant-numeric:tabular-nums;opacity:.6}.jm-body{position:relative;flex:1;min-height:0}.jm-canvas{position:absolute;top:0;right:0;bottom:0;left:0;overflow:hidden;cursor:grab;touch-action:none;outline:none;background-color:var(--paper-2);background-image:radial-gradient(circle,color-mix(in srgb,var(--ink) 16%,transparent) 1px,transparent 1.2px)}.jm-canvas.grab{cursor:grabbing}.jm-world{position:absolute;left:0;top:0;transform-origin:0 0;will-change:transform}.jm-wires{position:absolute;overflow:visible;pointer-events:none}.jm-wires path{fill:none;stroke:color-mix(in srgb,var(--ink) 32%,transparent);stroke-width:1.6;transition:stroke .15s,opacity .15s}.jm-wires marker path{fill:none;stroke:color-mix(in srgb,var(--ink) 45%,transparent);stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round}.jm-wires path.lit{stroke:var(--accent);stroke-width:2.2}.jm-wires .dim{opacity:.25}.jm-tag{display:block;width:max-content;max-width:120px;margin:0 auto;padding:2px 8px;border-radius:99px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font:600 11px/16px var(--sans);color:var(--ink-2);background:var(--surface);box-shadow:0 0 0 1px var(--line)}.jm-step{all:unset;box-sizing:border-box;position:absolute;width:208px;height:64px;cursor:pointer;display:flex;align-items:center;gap:11px;padding:0 12px 0 10px;background:var(--surface);border-radius:12px;box-shadow:0 0 0 1px var(--line),0 1px 2px #0000000a,0 4px 14px -6px #0000001f;transition:box-shadow .15s,opacity .15s,transform .12s var(--ease);--c: var(--work)}.jm-step.entry{--c: var(--good)}.jm-step.action{--c: oklch(60% .15 300)}.jm-step.decision{--c: var(--wait)}.jm-step.system{--c: var(--ink-3)}.jm-step.end{--c: var(--bad)}.jm-step:before,.jm-step:after{content:"";position:absolute;top:50%;width:8px;height:8px;margin-top:-4px;border-radius:50%;background:var(--surface);box-shadow:0 0 0 1.5px color-mix(in srgb,var(--ink) 30%,transparent)}.jm-step:before{left:-4px}.jm-step:after{right:-4px}.jm-step.entry:before,.jm-step.end:after{display:none}.jm-step:hover{box-shadow:0 0 0 1px color-mix(in srgb,var(--c) 55%,transparent),0 6px 20px -8px color-mix(in srgb,var(--c) 50%,transparent)}.jm-step:active{transform:scale(.98)}.jm-step:focus-visible{outline:2px solid var(--accent);outline-offset:3px}.jm-step.on{box-shadow:0 0 0 2px var(--c),0 8px 24px -8px color-mix(in srgb,var(--c) 55%,transparent)}.jm-step.dim{opacity:.4}.jm-step .k{flex:none;display:grid;place-items:center;width:38px;height:38px;border-radius:9px;background:color-mix(in srgb,var(--c) 14%,var(--surface));color:var(--c)}.jm-step.decision .k{border-radius:50%}.jm-step .k svg{width:19px;height:19px;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}.jm-step .t{display:flex;flex-direction:column;min-width:0}.jm-step b{font-size:13px;font-weight:600;line-height:1.25;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.jm-step small{font-size:10.5px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;color:var(--ink-3);margin-top:2px}.jm-sum{position:absolute;left:16px;bottom:16px;max-width:min(420px,calc(100% - 180px));margin:0;padding:8px 12px;font-size:12.5px;color:var(--ink-2);background:var(--glass);border-radius:10px;box-shadow:0 0 0 1px var(--line);-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);text-wrap:pretty;pointer-events:none}.jm-zoom{position:absolute;right:16px;bottom:16px}.jm-card{position:absolute;top:14px;right:14px;width:300px;max-height:calc(100% - 90px);overflow-y:auto;padding:14px 16px 16px;background:var(--surface);border-radius:14px;box-shadow:0 0 0 1px var(--line),0 12px 32px -12px #00000040;animation:jm-card .18s var(--ease)}@keyframes jm-card{0%{opacity:0;transform:translateY(-4px)}}.jm-card header{display:flex;align-items:center;justify-content:space-between}.jm-card .x{all:unset;cursor:pointer;font-size:20px;line-height:1;padding:2px 6px;border-radius:6px;color:var(--ink-3)}.jm-card .x:hover{background:var(--t2);color:var(--ink)}.jm-kind{font-size:10.5px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;padding:2px 8px;border-radius:99px;background:var(--work-bg);color:var(--work-fg)}.jm-kind.entry{background:var(--good-bg);color:var(--good-fg)}.jm-kind.decision{background:var(--wait-bg);color:var(--wait-fg)}.jm-kind.end{background:var(--bad-bg);color:var(--bad-fg)}.jm-kind.system{background:var(--t2);color:var(--ink-2)}.jm-kind.action{background:color-mix(in srgb,oklch(60% .15 300) 16%,var(--surface));color:#7750b1}.jm-card h4{margin:10px 0 6px;font-size:16px;font-weight:650;letter-spacing:-.01em;text-wrap:balance}.jm-card p{margin:0 0 10px;font-size:13px;color:var(--ink-2);text-wrap:pretty}.jm-card code{display:block;font:12px/1.4 var(--mono);padding:6px 8px;border-radius:7px;background:var(--t1);color:var(--ink-2);overflow-wrap:anywhere}.jm-card h5{margin:14px 0 4px;font-size:11px;font-weight:650;letter-spacing:.04em;text-transform:uppercase;color:var(--ink-3)}.jm-card ul{margin:0;padding:0;list-style:none;display:grid;gap:4px}.jm-card li{font-size:13px}.jm-card li small{color:var(--ink-3)}.jm-empty,.jm-skel{position:absolute;top:0;right:0;bottom:0;left:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;padding:24px;text-align:center;background-color:var(--paper-2);background-image:radial-gradient(circle,color-mix(in srgb,var(--ink) 12%,transparent) 1px,transparent 1.2px);background-size:22px 22px}.jm-empty svg{width:76px;height:48px;margin-bottom:10px;fill:var(--surface);stroke:var(--accent);stroke-width:1.6}.jm-empty svg path{fill:none}.jm-empty h3{margin:0;font-size:17px;font-weight:650;letter-spacing:-.01em;text-wrap:balance}.jm-empty p{margin:4px 0 14px;max-width:400px;font-size:13.5px;color:var(--ink-2);text-wrap:pretty}.jm-empty .jm-err{color:var(--bad);margin-top:-6px}.jm-skel p{margin:18px 0 8px;font-size:13.5px;color:var(--ink-2);max-width:380px;text-wrap:pretty}.jm-ghosts{display:flex;align-items:center}.jm-ghosts i{width:92px;height:44px;border-radius:10px;background:var(--surface);box-shadow:0 0 0 1px var(--line);animation:jm-ghost 1.6s var(--ease) infinite;animation-delay:calc(var(--i) * .2s)}.jm-ghosts b{width:26px;height:1.6px;background:color-mix(in srgb,var(--ink) 22%,transparent)}@keyframes jm-ghost{0%,to{box-shadow:0 0 0 1px var(--line);transform:none}30%{box-shadow:0 0 0 1.5px color-mix(in srgb,var(--accent) 60%,transparent),0 6px 16px -8px var(--accent);transform:translateY(-2px)}}@media(max-width:860px){.jm-bar{flex-wrap:wrap;padding-top:calc(8px + env(safe-area-inset-top))}.jm-title{max-width:none;flex:1}.jm-picks{order:3;flex-basis:100%}.jm-card{left:10px;right:10px;top:auto;bottom:10px;width:auto;max-height:55%}.jm-sum{display:none}.jm-ghosts i{width:54px}.jm-ghosts b{width:14px}}@media(prefers-reduced-motion:reduce){.jmap,.jm-card,.jm-ghosts i{animation:none}}.view.jm-open :is(#labels,.hud,.hint,#stage){visibility:hidden}.jm-wires path.loop{stroke-dasharray:5 4}.viewer{position:fixed;top:0;right:0;bottom:0;left:0;z-index:100;display:grid;grid-template-columns:auto 1fr auto;grid-template-rows:auto 1fr;background:#0e0d0be0;-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);color:#fff}.viewer[hidden]{display:none}.viewer-bar{grid-column:1 / -1;display:flex;align-items:center;gap:12px;padding:calc(10px + env(safe-area-inset-top)) 14px 10px;font-size:13px}.viewer-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.viewer-count{opacity:.6;font-variant-numeric:tabular-nums}.viewer-tab{color:inherit;opacity:.75;text-decoration:none;font-size:12px}.viewer-tab:hover{opacity:1;text-decoration:underline}.viewer button{-webkit-appearance:none;-moz-appearance:none;appearance:none;border:0;background:#ffffff1f;color:#fff;cursor:pointer;border-radius:50%;width:36px;height:36px;font-size:22px;line-height:1}.viewer button:hover{background:#ffffff38}.viewer-nav{align-self:center;margin:0 12px}.viewer.single .viewer-nav{visibility:hidden}.viewer-stage{grid-column:2;min-width:0;min-height:0;display:flex;overflow:auto;padding:0 0 calc(14px + env(safe-area-inset-bottom))}.viewer-stage img{margin:auto;max-width:100%;max-height:100%;object-fit:contain;border-radius:6px;cursor:zoom-in}.viewer.actual .viewer-stage img{max-width:none;max-height:none;cursor:zoom-out}body.viewing{overflow:hidden}@media(max-width:700px){.viewer-nav{margin:0 4px;width:32px;height:32px}}.agent-label .perk{margin-left:5px;font-size:10px;font-weight:600;opacity:.75;white-space:nowrap}.ac-tips{display:flex;align-items:center;gap:5px;padding:5px 8px 0;border-top:1px solid var(--line);font-size:11px;color:var(--ink-3)}.ac-tips span{margin-right:auto}.ac-tip{border:1px solid var(--line);background:transparent;color:inherit;border-radius:10px;padding:2px 7px;font-size:11px;cursor:pointer}.ac-tip:hover{background:var(--line)}.ac-tips+.ac-form{border-top:0}.agent-label.visitor .name{box-shadow:0 0 0 1.5px var(--tint),0 1px 3px #0000001a}.agent-label.visitor .name .handle{color:var(--ink-2);font-weight:520;white-space:pre}.door-sign{position:absolute;left:0;top:0;will-change:transform;display:flex;flex-direction:column;gap:2px;align-items:center;font-size:11.5px;font-weight:620;color:var(--ink);background:var(--glass);padding:4px 10px;border-radius:8px;box-shadow:0 1px 3px #0000001f}.visitor-card{position:absolute;left:0;top:0;z-index:20000;width:max-content;max-width:260px;display:flex;flex-direction:column;gap:3px;font-size:12px;line-height:1.35;color:var(--ink);background:var(--surface);padding:8px 11px;border-radius:10px;border-left:3px solid var(--tint);box-shadow:0 4px 16px #281e0f29}.visitor-card .vc-who{font-weight:650}.visitor-card .vc-role,.visitor-card .vc-state{color:var(--ink-2)}.visitor-card .vc-job{font-weight:520}.visitor-card .vc-state{font-size:11px}.chip.pot.goal-chip{gap:8px}.goal-chip i{font-style:normal}.chip.pot.goal-chip .goal-name{padding-left:0;margin-left:0;border-left:0;max-width:11ch;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.goal-bar{display:inline-block;position:relative;width:64px;height:6px;border-radius:3px;background:var(--t2);overflow:hidden;vertical-align:middle}.chip.pot.goal-chip .goal-bar{padding:0;margin:0;border-left:0}.goal-bar u{position:absolute;inset:0 auto 0 0;background:var(--good);border-radius:inherit;text-decoration:none;transition:width .6s var(--ease)}.goal-chip.done .goal-bar u{background:var(--wait)}.goal-bar.big{display:block;width:100%;height:10px;margin-top:8px;border-radius:5px}@media(max-width:720px){.goal-chip .goal-bar{width:40px}.goal-chip .goal-name{display:none}}.goal-dialog{border:1px solid var(--line);border-radius:14px;padding:20px;background:var(--paper);color:var(--ink);width:min(420px,calc(100vw - 32px))}.goal-dialog::backdrop{background:#1d1b1859}.goal-form{display:grid;gap:12px}.goal-form h2,.goal-form h3{margin:0;font-size:16px}.goal-form h3{font-size:13px;color:var(--ink-2);margin-top:6px}.goal-form label{display:grid;gap:4px;font-size:12px;color:var(--ink-2)}.goal-form input{font:inherit;padding:8px 10px;border:1px solid var(--line);border-radius:8px;background:var(--surface);color:var(--ink)}.goal-form .row{display:flex;gap:8px;justify-content:flex-end}.goal-now{font-size:13px}.goal-error{margin:0;color:var(--bad);font-size:12px}.bets{list-style:none;margin:0;padding:0;display:grid;gap:6px;font-size:12px}.bet{display:grid;grid-template-columns:1fr auto auto;gap:8px;align-items:center;padding:6px 8px;border-radius:8px;background:var(--t1)}.bet em{font-style:normal;color:var(--ink-2)}.bet.won em{color:var(--good)}.bet.void{opacity:.7}.bet.empty{display:block;color:var(--ink-3)}.goal-confetti{position:fixed;top:0;right:0;bottom:0;left:0;pointer-events:none;overflow:hidden;z-index:9999}.goal-confetti i{position:absolute;top:-12px;left:var(--x);width:8px;height:12px;border-radius:2px;animation:goal-fall var(--d) var(--w) cubic-bezier(.3,.4,.6,1) forwards}@keyframes goal-fall{to{transform:translate(var(--dx),110vh) rotate(720deg);opacity:.9}}@media(prefers-reduced-motion:reduce){.goal-bar u{transition:none}.goal-confetti{display:none}}