:root {
  --bg: #f6f6f8; --fg: #16161a; --mute: #6b6b76; --card: #fff; --line: #e4e4ea; --acc: #0a7c6c; --acc-fg: #fff;
  --user: #e8f4f1; --tool: #f0f0f4; --danger: #b3261e;
  --sat: env(safe-area-inset-top, 0px); --sab: env(safe-area-inset-bottom, 0px);
}
/* Theme: html[data-theme] = light | dark; absent = follow the system. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) { --bg: #111114; --fg: #ececf1; --mute: #9a9aa6; --card: #1b1b20; --line: #2a2a31; --acc: #35b39d; --acc-fg: #06110f; --user: #17302b; --tool: #202026; color-scheme: dark; }
}
:root[data-theme="dark"] { --bg: #111114; --fg: #ececf1; --mute: #9a9aa6; --card: #1b1b20; --line: #2a2a31; --acc: #35b39d; --acc-fg: #06110f; --user: #17302b; --tool: #202026; color-scheme: dark; }
:root[data-theme="light"] { color-scheme: light; }
* { box-sizing: border-box; }
/* App shell: the document never scrolls — only `main` does. 100% (not 100vh/dvh) is the visible area on every mobile browser. */
html, body { height: 100%; overflow: hidden; overscroll-behavior: none; }
/* iOS: the keyboard does not resize the layout viewport, it scrolls the page and often leaves it scrolled
   when it closes (a blank band at the bottom). The shell is pinned and sized to the visual viewport instead. */
body { position: fixed; inset: 0; width: 100%; height: var(--vvh, 100%); }
body { margin: 0; background: var(--bg); color: var(--fg); font: 16px/1.45 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; display: flex; flex-direction: column; -webkit-tap-highlight-color: transparent; }
button, input, select, textarea { font: inherit; color: inherit; }
button { border: 0; border-radius: 12px; padding: 10px 14px; background: var(--acc); color: var(--acc-fg); cursor: pointer; }
button.ghost { background: var(--card); color: var(--fg); box-shadow: inset 0 0 0 1px var(--line); }
button.danger { color: var(--danger); }
button:disabled { opacity: .5; cursor: default; }
input, select, textarea { background: var(--card); border: 1px solid var(--line); border-radius: 12px; padding: 10px 12px; min-width: 0; }
code, .mono { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 13px; }
a { color: var(--acc); }
[hidden] { display: none !important; }

#top { display: flex; align-items: center; justify-content: space-between; padding: calc(10px + var(--sat)) 16px 10px; }
.brand { font-size: 18px; } .logo { font-size: 22px; vertical-align: -2px; }
.pill { background: var(--card); color: var(--mute); box-shadow: inset 0 0 0 1px var(--line); padding: 6px 12px; border-radius: 999px; font-size: 13px; }
.pill.ok { color: var(--acc); } .pill.bad { color: var(--danger); }

main { flex: 1; min-height: 0; overflow: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; padding: 0 16px; }   /* the tab bar is a flex row below it, not an overlay */
.tab { min-height: 100%; display: flex; flex-direction: column; }
.hint { color: var(--mute); font-size: 14px; } .center { text-align: center; }
.notice { background: var(--user); border-radius: 12px; padding: 12px 14px; margin: 8px 0; }

.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); gap: 14px; padding: 8px 0 20px; }
.tile { background: var(--card); border-radius: 18px; padding: 14px 8px 10px; text-align: center; box-shadow: inset 0 0 0 1px var(--line); cursor: pointer; user-select: none; }
.tile:active { transform: scale(.97); }
.group.local .group-h { margin-top: 6px; }
.group.local > .hint { margin: -2px 0 8px; }
.tile.localapp .localmark { position: absolute; bottom: 6px; right: 7px; font-style: normal; font-size: 11px; opacity: .65; }
.tile.running { box-shadow: inset 0 0 0 2px var(--acc); }
.tile.running::after { content: ''; position: absolute; top: 8px; right: 8px; width: 7px; height: 7px; border-radius: 50%; background: var(--acc); }
.tile { position: relative; }
.tile .icon { font-size: 36px; line-height: 1; } .tile .name { font-size: 13px; margin-top: 8px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.chips { display: flex; gap: 8px; overflow-x: auto; padding: 6px 0 10px; scrollbar-width: none; }
.chips::-webkit-scrollbar { display: none; }
.chip { flex: 0 0 auto; background: var(--card); color: var(--fg); box-shadow: inset 0 0 0 1px var(--line); padding: 7px 12px; border-radius: 999px; font-size: 14px; }
.chip.on { background: var(--acc); color: var(--acc-fg); box-shadow: none; }

.transcript { flex: 1; display: flex; flex-direction: column; gap: 8px; padding-bottom: 8px; }
.msg { max-width: 92%; padding: 10px 14px; border-radius: 16px; white-space: pre-wrap; word-break: break-word; }
.msg.user { align-self: flex-end; background: var(--user); }
.msg.assistant { align-self: flex-start; background: var(--card); box-shadow: inset 0 0 0 1px var(--line); }
.msg.tool { align-self: flex-start; background: none; color: var(--mute); font-size: 13px; padding: 2px 6px; }
.msg.error { align-self: stretch; background: var(--card); color: var(--danger); box-shadow: inset 0 0 0 1px var(--danger); }
.hint.held { color: var(--fg); box-shadow: inset 0 0 0 1px var(--line); border-radius: 10px; padding: 8px 10px; }

/* the pattern picker, shown in "+ New" before the first message */
.patterns { align-self: stretch; margin: 2px 0 6px; }
.patterns .hint { margin: 0 2px 8px; }
.pat-row { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-bottom: 10px; }
.pat-row.three { grid-template-columns: repeat(3, 1fr); }
/* chips are small enough to pair up, rather than stacking three deep */
@media (max-width: 420px) { .pat-row.three { grid-template-columns: 1fr 1fr; } }
.patterns .hint { margin: 2px 2px 8px; }
/* A phone gets chips — icon and name, two across — because seven cards with a line of
   explanation each is a wall of text in front of the box you came here to type in. The
   full cards are for a window that has room for them. */
.pat { display: flex; align-items: center; gap: 8px; text-align: left;
  background: var(--card); color: var(--fg); box-shadow: inset 0 0 0 1px var(--line); padding: 9px 11px; border-radius: 12px; }
.pat small { display: none; }
.patterns .hint .long { display: none; }
html[data-layout="wide"] .patterns .hint .long { display: inline; }
html[data-layout="wide"] .patterns .hint .short { display: none; }
html[data-layout="wide"] .pat { flex-direction: column; align-items: flex-start; gap: 2px; padding: 10px 12px; border-radius: 14px; }
html[data-layout="wide"] .pat small { display: block; }
.pat.on { box-shadow: inset 0 0 0 2px var(--acc); }
.pat .pat-icon { font-size: 18px; line-height: 1.2; }
html[data-layout="wide"] .pat .pat-icon { font-size: 20px; }
.pat b { font-size: 14px; }
.pat small { color: var(--mute); font-size: 12px; line-height: 1.35; }
.pat.on small { color: var(--fg); }

.transcript, .msg { user-select: text; -webkit-user-select: text; -webkit-touch-callout: default; }   /* copy/paste from the build window */
.msg .copy { display: block; margin: 4px -8px -6px auto; background: none; color: var(--mute); padding: 2px 8px; font-size: 15px; line-height: 1; border-radius: 8px; user-select: none; -webkit-user-select: none; }
.msg .copy:active { color: var(--acc); }
.msg.busy::after { content: ''; display: inline-block; width: 8px; height: 8px; margin-left: 6px; border-radius: 50%; background: var(--acc); animation: blink 1s infinite; }
@keyframes blink { 50% { opacity: .2; } }

.composer { position: sticky; bottom: 0; display: flex; gap: 8px; align-items: flex-end; padding: 8px 0 10px; background: var(--bg); }
.composer textarea { flex: 1; resize: none; max-height: 160px; }
.composer button { width: 44px; height: 44px; border-radius: 50%; padding: 0; font-size: 20px; }

.card { background: var(--card); border-radius: 16px; padding: 14px 16px; margin: 10px 0; box-shadow: inset 0 0 0 1px var(--line); }
.card h2 { font-size: 15px; margin: 0 0 10px; color: var(--mute); text-transform: uppercase; letter-spacing: .04em; }
.row { display: flex; gap: 8px; align-items: center; margin: 8px 0; flex-wrap: wrap; }
.row input { flex: 1; }
.kv { font-size: 14px; } .kv div { display: flex; justify-content: space-between; gap: 12px; padding: 3px 0; } .kv span:last-child { color: var(--mute); text-align: right; word-break: break-all; }
#log { max-height: 240px; overflow: auto; white-space: pre-wrap; margin: 0; color: var(--mute); }

#tabs { flex: none; display: flex; background: var(--card); border-top: 1px solid var(--line); padding-bottom: var(--sab); }
#tabs button { flex: 1; background: none; color: var(--mute); border-radius: 0; padding: 8px 0 6px; font-size: 20px; display: flex; flex-direction: column; align-items: center; gap: 2px; }
#tabs button span { font-size: 11px; } #tabs button.on { color: var(--acc); }

#runner { position: fixed; inset: 0; background: var(--bg); display: flex; flex-direction: column; z-index: 10; }
.runbar { display: flex; align-items: center; gap: 6px; padding: calc(6px + var(--sat)) 8px 6px; background: var(--card); border-bottom: 1px solid var(--line); }
.runbar span { flex: 1; text-align: center; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.runbar button { background: none; color: var(--fg); font-size: 20px; width: 40px; height: 36px; padding: 0; }
/* The frame paints Palmtop's own background while the app loads — never white on a dark Palmtop. */
#run-frame { flex: 1; border: 0; width: 100%; background: var(--bg); }

#toast { position: fixed; left: 50%; bottom: calc(84px + var(--sab)); transform: translateX(-50%); background: #333; color: #fff; padding: 10px 16px; border-radius: 20px; font-size: 14px; z-index: 20; box-shadow: 0 4px 20px rgba(0,0,0,.4); }

dialog.sheet { border: 0; padding: 0; background: transparent; color: var(--fg); max-width: 420px; width: calc(100% - 32px); }
dialog.sheet::backdrop { background: rgba(0,0,0,.5); }
dialog.sheet .card { margin: 0; }
.app-head { display: flex; gap: 12px; align-items: center; margin: 6px 0 10px; } .app-head .icon { font-size: 40px; line-height: 1; }
.linkbox { word-break: break-all; user-select: all; -webkit-user-select: all; }

.bar { display: flex; align-items: center; gap: 8px; padding: 8px 0 0; } .grow { flex: 1; }
button.small { padding: 6px 12px; font-size: 13px; }
.actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin: 8px 0; }
.group-h { display: flex; justify-content: space-between; align-items: baseline; margin: 10px 0 0; font-size: 14px; color: var(--mute); }
.gname { font-weight: 600; color: var(--fg); } .gname.edit { text-decoration: underline dotted; cursor: pointer; }
.tile { position: relative; }
.arrange .tile { touch-action: none; cursor: grab; }
.tile.drag { opacity: .75; transform: scale(1.06); box-shadow: 0 6px 20px rgba(0,0,0,.25); z-index: 2; }
.tile .del { position: absolute; top: -7px; left: -7px; width: 24px; height: 24px; border-radius: 50%; padding: 0; font-size: 12px; line-height: 24px; background: var(--danger); color: #fff; }
.arrange .grid:empty { min-height: 60px; border: 1px dashed var(--line); border-radius: 14px; }
.row.check { gap: 10px; font-weight: 600; } .row.check input { flex: none; width: 22px; height: 22px; margin: 0; accent-color: var(--acc); }
.dtoast { margin-top: 10px; background: #333; color: #fff; padding: 8px 12px; border-radius: 12px; font-size: 14px; text-align: center; }
#inst-link { width: 100%; font-size: 12px; margin-top: 8px; }

.badge { position: absolute; top: 6px; right: 22%; min-width: 16px; height: 16px; padding: 0 4px; border-radius: 8px; background: var(--danger); color: #fff; font-size: 11px; font-style: normal; line-height: 16px; text-align: center; }
#tabs button { position: relative; }
.ellip { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ccard { display: flex; align-items: center; gap: 12px; cursor: pointer; } .ccard .cicon { font-size: 28px; } .ccard .cname { font-weight: 600; } .ccard .cmeta { font-size: 13px; color: var(--mute); }
.ccard .unread { margin-left: auto; background: var(--acc); color: var(--acc-fg); border-radius: 999px; padding: 2px 9px; font-size: 12px; }
.feed { flex: 1; display: flex; flex-direction: column; gap: 10px; padding: 8px 0; }
.post { background: var(--card); border-radius: 14px; padding: 10px 12px; box-shadow: inset 0 0 0 1px var(--line); user-select: text; -webkit-user-select: text; }
.post.mine { background: var(--user); }
.post .who { font-size: 12px; color: var(--mute); margin-bottom: 4px; display: flex; gap: 8px; } .post .who span:nth-child(2) { flex: 1; }
.post .who .rm { margin-left: 8px; background: none; color: var(--mute); padding: 0 4px; font-size: 12px; }
.post.app .body { display: flex; gap: 12px; align-items: center; } .post.app .icon { font-size: 34px; line-height: 1; } .post.app .body > div { flex: 1; min-width: 0; }
.post.app .desc { font-size: 13px; color: var(--mute); } .post.app button.get { padding: 8px 12px; font-size: 14px; }
.post.note .text { white-space: pre-wrap; word-break: break-word; }
.round { width: 44px; height: 44px; border-radius: 50%; padding: 0; font-size: 22px; }
#circle-view { display: flex; flex-direction: column; min-height: 100%; }

.reply .sender { background: none; color: var(--mute); box-shadow: inset 0 0 0 1px var(--line); font-size: 11px; padding: 2px 8px; border-radius: 999px; margin-left: 6px; }
.reply .sender:active { color: var(--fg); }
.iblist { max-height: 45vh; overflow: auto; display: flex; flex-direction: column; gap: 8px; margin: 6px 0; }
.reply { background: var(--bg); border-radius: 12px; padding: 8px 10px; font-size: 14px; }
.reply .who { font-size: 12px; color: var(--mute); display: flex; gap: 8px; } .reply .who .rm { margin-left: auto; background: none; color: var(--mute); padding: 0 4px; font-size: 12px; }
.reply .kv div { display: flex; gap: 10px; } .reply .kv span:first-child { color: var(--mute); min-width: 30%; }

.galgroup { padding: 6px 2px 0; }
.galgroup b { display: block; font-size: 13px; text-transform: uppercase; letter-spacing: .04em; color: var(--mute); }
.galgroup small { color: var(--mute); font-size: 12.5px; }
.galgroup:first-child { padding-top: 0; }
.gitem { display: flex; gap: 12px; align-items: center; background: var(--bg); border-radius: 12px; padding: 10px; } .gitem .icon { font-size: 32px; line-height: 1; } .gitem > div { flex: 1; min-width: 0; } .gitem .desc { font-size: 13px; color: var(--mute); } .gitem .tags { font-size: 11px; color: var(--mute); } .gitem button { padding: 8px 12px; font-size: 14px; }
#log { user-select: text; -webkit-user-select: text; }

.pick { display: flex; flex-direction: column; gap: 8px; margin-top: 8px; }
.pick .opt { display: flex; align-items: center; gap: 12px; padding: 10px 12px; border-radius: 12px; background: var(--bg); box-shadow: inset 0 0 0 1px var(--line); cursor: pointer; }
.pick .opt input { width: 20px; height: 20px; margin: 0; accent-color: var(--acc); flex: none; }
.pick .opt span { flex: 1; display: flex; flex-direction: column; } .pick .opt small { color: var(--mute); font-size: 12px; }
.pick .opt.on { box-shadow: inset 0 0 0 2px var(--acc); } .pick .opt.off { opacity: .6; } .pick .chev { color: var(--mute); font-style: normal; }
.row select { flex: 1; min-width: 0; } #gmodels-refresh { flex: none; padding: 6px 10px; }

.seg { display: flex; background: var(--bg); border-radius: 12px; padding: 3px; box-shadow: inset 0 0 0 1px var(--line); margin-top: 6px; }
.seg button { flex: 1; background: none; color: var(--mute); border-radius: 9px; padding: 8px 0; font-size: 14px; }
.seg button.on { background: var(--card); color: var(--fg); box-shadow: 0 1px 3px rgba(0,0,0,.15); }

/* Laptop / desktop: the layout is a phone's, so on a wide screen the shell becomes a phone-width column in the middle of the
   page instead of stretching across it. body keeps its fixed positioning; the transform also makes the fixed overlays
   (#runner, #toast) position against the column rather than the whole window. */
@media (min-width: 760px) and (min-height: 480px) {
  html:not([data-layout="wide"]) { background: #e6e6eb; }
  html:not([data-layout="wide"]) body { width: 560px; left: 50%; right: auto; transform: translateX(-50%); box-shadow: 0 0 0 1px var(--line), 0 24px 60px -32px rgba(0, 0, 0, .55); }
}
@media (min-width: 760px) and (min-height: 480px) and (prefers-color-scheme: dark) { html:not([data-layout="wide"]):not([data-theme="light"]) { background: #08080a; } }
@media (min-width: 760px) and (min-height: 480px) { html[data-theme="dark"]:not([data-layout="wide"]) { background: #08080a; } html[data-theme="light"]:not([data-layout="wide"]) { background: #e6e6eb; } }

/* ── Wide window: the whole window, with the tabs as a left rail. The choice lives in
   Settings → Appearance; app.js resolves Automatic against the window width and sets
   html[data-layout], the way it sets html[data-theme], so there is no media query here. */
html[data-layout="wide"] body {
  width: 100%; left: 0; right: 0; transform: none; box-shadow: none;
  display: grid; grid-template-columns: 240px minmax(0, 1fr); grid-template-rows: auto minmax(0, 1fr);
  grid-template-areas: "head head" "rail main";
}
html[data-layout="wide"] #top { grid-area: head; background: var(--card); border-bottom: 1px solid var(--line); padding-left: 20px; padding-right: 20px; }
html[data-layout="wide"] main { grid-area: main; padding: 0 28px; }
html[data-layout="wide"] .tab { max-width: 1000px; margin: 0 auto; width: 100%; }
html[data-layout="wide"] #tabs {
  grid-area: rail; flex-direction: column; justify-content: flex-start; gap: 4px;
  border-top: 0; border-right: 1px solid var(--line); padding: 14px 10px calc(14px + var(--sab));
}
html[data-layout="wide"] #tabs button {
  flex: none; width: 100%; flex-direction: row; justify-content: flex-start; align-items: center;
  gap: 12px; padding: 11px 13px; border-radius: 12px; font-size: 19px;
}
html[data-layout="wide"] #tabs button span { font-size: 15px; }
html[data-layout="wide"] #tabs button.on { background: var(--bg); }
html[data-layout="wide"] #tabs .badge { position: static; margin-left: auto; }
/* the app that is still running, kept in the rail below the four tabs */
html[data-layout="wide"] #tab-app { margin-top: auto; border-top: 1px solid var(--line); border-radius: 12px; padding-top: 12px; }
html[data-layout="wide"] #tab-app span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
html[data-layout="wide"] #tab-app .railx { margin-left: auto; font-style: normal; font-size: 13px; color: var(--mute); padding: 0 2px; }
html[data-layout="wide"] #tab-app .railx:hover { color: var(--fg); }
#run-close { display: none; }                       /* on a phone ‹ is the way out */
html[data-layout="wide"] #run-close { display: block; }

/* A sheet is phone-width because a phone is narrow. The Gallery is a catalogue,
   so on a desk it gets room to be one: wider, two or three across, and taller
   before it starts scrolling. */
html[data-layout="wide"] dialog#gallery { max-width: 960px; }
html[data-layout="wide"] #gal-list { max-height: 72vh; display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 10px; }
html[data-layout="wide"] #gal-list .gitem { align-items: flex-start; padding: 12px; }
html[data-layout="wide"] #gal-list .galgroup { grid-column: 1 / -1; }
html[data-layout="wide"] #gal-list .gitem button { align-self: center; }
/* the Inbox is a list of replies, and reads better with the same room */
html[data-layout="wide"] dialog#inboxdlg { max-width: 760px; }
html[data-layout="wide"] dialog#inboxdlg .iblist { max-height: 60vh; }
/* A mini-app is written for a phone, so it keeps a phone's width in the middle of the pane
   rather than being stretched across a monitor. The rail stays visible beside it. */
html[data-layout="wide"] #runner { position: static; grid-area: main; padding-bottom: 20px; }
html[data-layout="wide"] .grid { grid-template-columns: repeat(auto-fill, minmax(124px, 1fr)); }
html[data-layout="wide"] .runbar { border-radius: 14px 14px 0 0; max-width: 480px; width: 100%; margin: 14px auto 0; box-shadow: 0 0 0 1px var(--line); }
html[data-layout="wide"] #run-frame { max-width: 480px; width: 100%; margin: 0 auto; border-radius: 0 0 18px 18px; box-shadow: 0 0 0 1px var(--line), 0 24px 60px -34px rgba(0,0,0,.55); }
/* An app built for a desk — a table, a rota, a board — takes the pane instead.
   plugin.json "wide": true, or the ⤢ button, which the person's choice remembers. */
html[data-layout="wide"] #runner[data-wide="1"] { padding-bottom: 0; }
html[data-layout="wide"] #runner[data-wide="1"] .runbar { max-width: none; margin: 0; border-radius: 0; box-shadow: none; border-bottom: 1px solid var(--line); }
html[data-layout="wide"] #runner[data-wide="1"] #run-frame { max-width: none; margin: 0; border-radius: 0; box-shadow: none; }
/* On a phone the runner is full-bleed either way, so the toggle has nothing to offer. */
#run-wide { display: none; }
html[data-layout="wide"] #run-wide { display: block; }
