/* Arkio web app shell. Utilitarian, calm, out of the way of the 3D scene. Dark by default (the scene reads
   better against dark chrome); a light scheme is provided for completeness. The colours are the 3.0 website's
   (Website/prototype-3.0/handoff/web-app-colors.md, 2026-10-04): neutrals do the work and teal means Arkio and
   action. Teal is a fill or a 2 px line; anything teal that has to be read (text, links, icons, focus rings,
   1 px state borders) uses --accent-text, because Arkio teal is 2.2:1 on white. One teal button per view:
   --accent-ink on --accent, --accent-hover under the pointer. Status colours keep the app's own amber and red,
   darkened in the light theme to pass 4.5:1. */
:root {
  color-scheme: dark;       /* native controls - select lists, scrollbars, date pickers - follow the theme; light below */
  --bg: #0E1A19;            /* deepest surface: app background, sunken inputs (the site's ink on teal) */
  --panel: #152021;         /* panes and toolbars (the site's dark sections) */
  --panel-2: #1B2526;       /* raised surfaces: composer, rails, cards */
  --line: #2E393A;          /* borders and dividers */
  --ink: #E8EEEC;           /* primary text */
  --muted: #B5C3C1;         /* secondary text */
  --accent: #4CC1B8;        /* Arkio teal: primary buttons, selection, the active-tool line. Fills and lines, not text */
  --accent-hover: #3DB3AA;  /* primary button under the pointer */
  --accent-pressed: #34A198;/* primary button pressed */
  --accent-ink: #0E1A19;    /* text and icons on --accent (8.2:1) */
  --accent-text: #7ED8CE;   /* teal that has to be read: text, links, icons, focus rings, 1 px state borders */
  --accent-soft: #1D3F3B;   /* toggles that are on, tints, highlights */
  --range-accent: var(--accent); /* native slider fill and thumb; the light theme needs a darker teal to keep its track gray */
  --amber: #D9A441;         /* warnings and low credits */
  --danger: #E07A6A;        /* errors and destructive actions */
  --user-bubble: #EEF1EF;   /* light bubble on dark chrome */
  --user-ink: #1B2526;
  --divider-w: 6px;
  --app-height: 100vh; /* fallback before JS measures the visible viewport */
  --app-top: 0px;
  /* ---- the player's toolbar, in one place: the line under the active tool (and the tabs to come), inks, sizes ---- */
  --tool-line: var(--accent);      /* 2px line under the active tool and tab */
  --tool-ink: var(--ink);          /* tool icon colour */
  --tool-ink-off: #6F807D;         /* disabled tool icon colour, the same in both themes */
  --toolbar-h: 48px;               /* scene header height, the line the other pane headers align to */
  --tool-w: 36px;                  /* palette button width; a tool is as tall as the toolbar so its line sits on its bottom edge */
  --tool-icon: 20px;               /* glyph size */
  --rail-w: 48px;                 /* the side panel's rail of tabs at the right edge */
}
@media (prefers-color-scheme: light) {
  :root {
    color-scheme: light;
    --bg: #EEF1EF; --panel: #FFFFFF; --panel-2: #EEF1EF; --line: #E6E4DD;   /* --panel-2 = --bg on purpose: --line separates them */
    --ink: #1B2526; --muted: #5E6869;
    --accent-text: #1F6F66; --accent-soft: #DDF5F1; --amber: #8B641C; --danger: #C13D28;
    --range-accent: var(--accent-text); /* Chromium gives a light accent a dark contrasting track, even on white panels */
    --user-bubble: #EEF1EF; --user-ink: #1B2526;
    /* --accent, --accent-hover, --accent-pressed, --accent-ink and --tool-ink-off are the same in both themes */
  }
}

@supports (height: 100dvh) { :root { --app-height: 100dvh; } }
* { box-sizing: border-box; }
html, body { margin: 0; height: 100%; overflow: hidden; }
/* Safari browser chrome and the keyboard can shrink/pan the visible viewport without changing 100vh.
   app.js maintains its height/top; safe-area padding keeps every pane above the home indicator. */
body {
  position: fixed; top: var(--app-top); left: 0; width: 100%; height: var(--app-height);
  padding: env(safe-area-inset-top, 0px) env(safe-area-inset-right, 0px) env(safe-area-inset-bottom, 0px) env(safe-area-inset-left, 0px);
  background: var(--bg); color: var(--ink);
  font-family: "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
  font-size: 15px; line-height: 1.5;
}

#split { position: relative; display: flex; width: 100%; height: 100%; } /* positioned: the chats list's drawer and its scrim lie over it */
/* The chats list as a drawer (app.js showList): where the width will not hold the pane beside the chat and the scene
   it slides in over the split at the left, behind a scrim, every part of the pane with it. */
#sessions.drawer { position: absolute; left: 0; top: 0; bottom: 0; z-index: 7; width: min(320px, 85%); box-shadow: 8px 0 28px rgba(0, 0, 0, .28); animation: drawer-in .18s ease; }
#list-scrim { position: absolute; inset: 0; z-index: 6; background: rgba(4, 8, 6, .4); }
#list-scrim[hidden] { display: none; }
@keyframes drawer-in { from { transform: translateX(-100%); } }
@media (prefers-reduced-motion: reduce) { #sessions.drawer { animation: none; } }
/* Browse tutorials: the chooser's door to the folded list, under its words in the chat pane, in the chips' chrome
   rather than the accent, since it is a way to the list and not the chat's own action; app.js hides it while the
   list stands beside the chat. */
.tutorials-door {
  align-self: center; margin-top: 14px; padding: 6px 12px; border: 1px solid var(--line); border-radius: 7px; background: var(--panel); color: var(--ink);
  font: inherit; font-size: 12.5px; cursor: pointer; transition: border-color .15s ease;
}
.tutorials-door:hover, .tutorials-door:focus-visible { border-color: var(--accent-text); outline: none; }
.tutorials-door[hidden] { display: none; }

/* ---- sessions sidebar (leftmost) ---- */
#sessions {
  height: 100%; min-width: 150px; display: flex; flex-direction: column; overflow: hidden;
  background: var(--panel-2); border-right: 1px solid var(--line);
}
/* New chat across the pane's head (.sessions-head, collapsible panes below): one line down to the pane's floor, which
   leaves it 106px for its 98px of words. */
#new-chat {
  flex: 1 1 auto; min-width: 0; margin: 0; padding: 9px 12px; text-align: left; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  border: 1px solid var(--line); border-radius: 9px; background: var(--panel);
  color: var(--ink); font: inherit; font-size: 13.5px; font-weight: 600; cursor: pointer;
  transition: border-color .15s ease;
}
#new-chat:hover { border-color: var(--accent-text); }
/* ---- the chats list (design canvas page 27; app.js "sessions UI") ---- */
/* #chats is the list: the places, a hairline, the chats' head, the scrolling rows and the status line. #place is a
   place drilled into the column in its stead (Media, Samples); New chat above and the account footer below stay. */
#chats, #place { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
#chats[hidden], #place[hidden] { display: none; }
/* The two places, Media and Samples: a glyph tile, two lines and the chevron that says "this opens in the column".
   Buttons, never selected: a place is not a chat. */
.places { flex: 0 0 auto; display: flex; flex-direction: column; gap: 2px; padding: 0 8px 2px; }
/* A place is one line at the chat rows' height: a glyph, the name, the chevron that says it opens in the column. Counts
   and progress belong to the place itself, not to the list. */
.place-row {
  display: flex; align-items: center; gap: 8px; width: 100%; padding: 6px 4px 6px 10px;
  border: 0; border-radius: 8px; background: transparent; color: var(--ink); font: inherit; font-size: 13px; line-height: 1.35; text-align: left; cursor: pointer;
}
.place-row:hover, .place-row:focus-visible { background: var(--chat-hover, rgba(127,127,127,.08)); outline: none; }
.place-glyph { flex: 0 0 auto; display: inline-flex; color: var(--muted); }
.place-glyph svg { width: 15px; height: 15px; }
.place-name { flex: 1 1 auto; min-width: 0; padding: 2px 0; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.place-chevron { flex: 0 0 auto; display: inline-flex; color: var(--muted); }
.place-chevron svg { width: 13px; height: 13px; }
.chats-rule { flex: 0 0 1px; margin: 4px 16px; background: var(--line); }
/* The chats' head: the caption and the List | Cards toggle, the picked view pressed. */
.chats-head { flex: 0 0 auto; display: flex; align-items: center; gap: 8px; padding: 6px 10px 4px 18px; }
.chats-caption { flex: 1 1 auto; font-size: 11px; font-weight: 600; letter-spacing: .07em; text-transform: uppercase; color: var(--muted); }
.view-toggle { display: inline-flex; border: 1px solid var(--line); border-radius: 6px; overflow: hidden; background: var(--panel); }
.view-btn { width: 26px; height: 22px; display: grid; place-items: center; padding: 0; border: 0; background: transparent; color: var(--muted); cursor: pointer; }
.view-btn svg { width: 13px; height: 13px; }
.view-btn:hover, .view-btn:focus-visible { color: var(--ink); outline: none; }
.view-btn[aria-pressed="true"] { color: var(--ink); background: var(--active-item, rgba(127,127,127,.14)); }
/* The rows scroll together: the chats, then Archived and, open, its chats. In the card view the two listboxes are
   grids, two cards to a row, one once the list is narrower than 200px (the column dragged towards its 150px floor),
   where two cards would be too small to read their names. */
#session-list { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 0 8px 12px; display: flex; flex-direction: column; container-type: inline-size; }
#chat-rows, #archived-rows, #shared-rows { display: flex; flex-direction: column; gap: 1px; }
#chat-rows.cards, #archived-rows.cards, #shared-rows.cards { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 2px; align-content: start; }
@container (max-width: 200px) { #chat-rows.cards, #archived-rows.cards, #shared-rows.cards { grid-template-columns: minmax(0, 1fr); } }
/* List children sit beneath the Archived label; the guide aligns with its glyph and ends at the last row. */
#archived-rows:not(.cards), #shared-rows:not(.cards) { margin-inline-start: 19px; padding-inline-start: 4px; border-inline-start: 1px solid var(--line); }
#archived-rows[hidden], #shared-rows[hidden], #archived-empty[hidden], .archived-foot[hidden] { display: none; }
/* Archived at the foot of the same list: a quiet row with the archive glyph, the word, the count and a chevron that
   turns down while the section is open. Match the 34px chat row and prevent the scrolling flex list from shrinking its click target. */
.archived-foot {
  display: flex; flex: 0 0 auto; align-items: center; gap: 8px; width: 100%; margin: 4px 0 0; height: 34px; padding: 0 12px;
  border: 0; border-radius: 8px; background: transparent; color: var(--muted); font: inherit; font-size: 13px; line-height: 1.35; text-align: left; cursor: pointer;
}
.archived-foot:hover, .archived-foot:focus-visible { background: var(--chat-hover, rgba(127,127,127,.08)); color: var(--ink); outline: none; }
.archived-foot svg { flex: 0 0 auto; width: 14px; height: 14px; }
.archived-foot .archived-chevron { width: 12px; height: 12px; transition: transform .15s ease; }
.archived-foot[aria-expanded="true"] .archived-chevron { transform: rotate(90deg); }
.archived-word { flex: 1 1 auto; }
#archived-empty { margin: 6px 10px 4px; font-size: 12px; line-height: 1.4; color: var(--muted); }
#archived-empty strong { display: block; color: var(--ink); font-weight: 600; }
#archived-empty p { margin: 2px 0 0; }
/* An archived chat: muted, its title still readable, Restore under the pointer (and in its menu) and nothing else;
   clicking the row does not open it. */
.session-item.archived { color: var(--muted); }
.session-item.archived:hover, .session-item.archived.menu-open { color: var(--ink); }
.session-item[data-open-disabled="true"], .session-item[data-open-disabled="true"] .session-title { cursor: default; }
.session-restore {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: 5px; height: 22px; padding: 0 8px;
  border: 1px solid var(--line); border-radius: 6px; background: var(--panel); color: var(--ink);
  font: inherit; font-size: 11px; font-weight: 600; line-height: 1; white-space: nowrap; cursor: pointer; opacity: 0; transition: opacity .12s ease, border-color .15s ease;
}
.session-restore svg { width: 12px; height: 12px; }
/* In a row the pill leaves the layout while unseen, so the title keeps its width; on a card it sits over the still. */
.session-item .session-restore { display: none; }
.session-item:hover .session-restore, .session-item:focus-within .session-restore, .session-item.menu-open .session-restore { display: inline-flex; }
.session-item:hover .session-restore, .session-item:focus-within .session-restore, .session-item.menu-open .session-restore,
.lib-card:hover .session-restore, .lib-card:focus-within .session-restore, .lib-card.menu-open .session-restore { opacity: 1; }
.session-restore:hover, .session-restore:focus-visible { border-color: var(--accent-text); outline: none; }
.session-restore:disabled { opacity: .45; cursor: default; }
/* The list's one feedback line, at the foot above the account footer: what the last archive or restore did, naming
   the chat, with its one action (Show in Archived, Show in Chats, Retry) and a detail line while the cloud side waits. */
#chats-status { flex: 0 0 auto; margin: 0 10px 8px; padding: 8px 10px; border: 1px solid var(--line); border-radius: 8px; background: var(--panel); font-size: 12px; line-height: 1.4; color: var(--ink); }
#chats-status[hidden] { display: none; }
#chats-status[data-kind="error"] { border-color: var(--amber); }
.cs-line { display: flex; align-items: baseline; gap: 6px; min-width: 0; flex-wrap: wrap; }
.cs-text { font-weight: 600; }
.cs-name { flex: 1 1 auto; min-width: 0; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cs-action { flex: 0 0 auto; padding: 0; border: 0; background: transparent; color: var(--accent-text); font: inherit; font-size: 12px; font-weight: 600; cursor: pointer; }
.cs-action:hover, .cs-action:focus-visible { text-decoration: underline; outline: none; }
.cs-detail { display: block; margin-top: 2px; color: var(--muted); }
/* A row the status line points at (Show in Archived, Show in Chats) wears the ring for a moment. */
.session-item.highlight, .lib-card.highlight { box-shadow: inset 0 0 0 2px var(--accent); }
.session-item, .lib-card { transition: box-shadow .6s ease; }
/* A place drilled into the column: the back chevron, the name, what it holds at the right, and the body under them.
   The Saved media fixture's one action (Delete saved media) keeps its ⋮ in the Media header while the fixture exists. */
/* The place head stands in for the pane's head band while a place is open: New chat is not for a place and the fold
   glyph is off, so the band would be empty; at the band's height the place's Back and name sit level with the chat
   header. */
.place-head { flex: 0 0 var(--toolbar-h); display: flex; align-items: center; gap: 6px; padding: 0 12px 0 6px; }
#sessions:has(#place:not([hidden])) .sessions-head { display: none; }
#place-back { flex: 0 0 auto; width: 26px; height: 26px; display: grid; place-items: center; padding: 0; border: 0; border-radius: 6px; background: transparent; color: var(--muted); cursor: pointer; }
#place-back svg { width: 15px; height: 15px; }
#place-back:hover, #place-back:focus-visible { color: var(--ink); background: var(--chat-hover, rgba(127,127,127,.08)); outline: none; }
#place-title { flex: 1 0 auto; min-width: 0; font-size: 13.5px; font-weight: 600; color: var(--ink); white-space: nowrap; }
#place-meta { flex: 0 1 auto; min-width: 0; font-size: 11.5px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#place-menu-btn { opacity: 1; }
#place-menu-btn[hidden] { display: none; }
#place-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; container-type: inline-size; } /* the samples grid folds by its width, as the chats' cards do by #session-list's */
/* Cards: the chats in the card view and the samples, two to a row: a still (or a placeholder with a glyph), the name and
   a meta line. A card opens its chat as a row does; the selected chat wears the ring; an empty chat is a blank card. */
.lib-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 2px; padding: 0 8px; align-content: start; }
/* One column at the pane width where the chats' card view folds (above, #session-list at 200px): that list carries the
   8px side padding the grid carries here, so its container is 16px narrower than #place-body at the same pane width. */
@container (max-width: 216px) { .lib-grid { grid-template-columns: minmax(0, 1fr); } }
.lib-card { min-width: 0; display: flex; flex-direction: column; gap: 5px; padding: 6px; border-radius: 9px; color: var(--ink); cursor: pointer; user-select: none; }
.lib-card.sample { border: 0; background: transparent; font: inherit; text-align: left; }
.lib-card.sample:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.lib-card:hover, .lib-card.menu-open { background: var(--chat-hover, rgba(127,127,127,.08)); }
.lib-card.active { box-shadow: inset 0 0 0 2px var(--accent); }
.lib-card[data-open-disabled="true"] { cursor: default; }
.lib-still { position: relative; height: 76px; border-radius: 6px; overflow: hidden; border: 1px solid var(--line); background: var(--panel); }
.lib-still img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; }
.lib-still-empty { position: absolute; inset: 0; display: grid; place-items: center; background: var(--panel-2); color: var(--muted); }
.lib-still-empty svg { width: 18px; height: 18px; }
.lib-title-row { display: flex; align-items: center; gap: 6px; min-width: 0; }
.lib-dot { flex: 0 0 7px; width: 7px; height: 7px; border-radius: 50%; background: var(--accent); }
.lib-dot[hidden] { display: none; }
.lib-card .session-title { padding: 0; font-size: 12px; font-weight: 600; line-height: 1.25; }
.lib-card .session-meta { margin-top: -3px; }
.lib-card.empty .session-title, .lib-card.archived .session-title { color: var(--muted); }
.lib-card .session-menu-btn { position: absolute; right: 5px; top: 5px; background: var(--panel); border: 1px solid var(--line); }
.lib-card:hover .session-menu-btn, .lib-card.active .session-menu-btn, .lib-card.menu-open .session-menu-btn { opacity: 1; }
.lib-card .session-open { position: absolute; right: 5px; bottom: 5px; display: inline-flex; align-items: center; height: 16px; padding: 0 5px; border-radius: 4px; background: rgba(21, 32, 33, .72); color: #fff; font-size: 10px; font-weight: 600; }
.lib-card .session-restore, .lib-pill { position: absolute; left: 5px; bottom: 5px; }
.lib-pill {
  display: inline-flex; align-items: center; gap: 5px; height: 22px; padding: 0 8px; border: 1px solid var(--line); border-radius: 6px;
  background: var(--panel); color: var(--ink); font: inherit; font-size: 11px; font-weight: 600; line-height: 1; white-space: nowrap; cursor: pointer; opacity: 0; transition: opacity .12s ease, border-color .15s ease;
}
.lib-pill svg { width: 12px; height: 12px; }
.lib-card:hover .lib-pill, .lib-card:focus-within .lib-pill, .lib-pill:focus-visible { opacity: 1; }
.lib-pill:hover, .lib-pill:focus-visible { border-color: var(--accent-text); outline: none; }
.lib-card .session-rename { margin: 0; }
/* The account footer (account.js): Log in, which grows into the email and code steps; signed in, the credits ring,
   the email and Log out. The buttons keep the pane's big-button look (New chat's). */
/* 8px of the pane's ground above the card: a row scrolling out ends in that ground, not on the card's edge. No line and
   no fade, both tried and declined (2026-10-14). */
#account { flex: 0 0 auto; display: flex; flex-direction: column; margin: 8px 10px 12px; }
#account [hidden], .ac-form[hidden], .ac-form [hidden] { display: none; } /* the form keeps it when it opens in the chat */
.ac-login {
  width: 100%; padding: 9px 12px; text-align: left;
  border: 1px solid var(--line); border-radius: 9px; background: var(--panel);
  color: var(--muted); font: inherit; font-size: 13.5px; font-weight: 600; cursor: pointer;
  transition: border-color .15s ease, color .15s ease;
}
.ac-login:hover:not(:disabled) { border-color: var(--accent-text); color: var(--ink); }
.ac-login:disabled { opacity: .5; cursor: default; }
.ac-status { margin: 6px 2px 0; font-size: 11px; line-height: 1.4; color: var(--muted); }
.ac-form, .ac-in { display: flex; flex-direction: column; gap: 8px; padding: 10px; border: 1px solid var(--line); border-radius: 9px; background: var(--panel); }
.ac-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.ac-title { font-size: 13px; font-weight: 600; color: var(--ink); }
.ac-close { display: inline-grid; place-items: center; width: 22px; height: 22px; padding: 0; border: 0; border-radius: 5px; background: transparent; color: var(--muted); cursor: pointer; }
.ac-close:hover { color: var(--ink); background: var(--active-item, rgba(127, 127, 127, .14)); }
.ac-close svg { width: 12px; height: 12px; }
.ac-note { margin: 0; font-size: 11.5px; line-height: 1.4; color: var(--muted); overflow-wrap: anywhere; }
.ac-email, .ac-code { width: 100%; height: 30px; padding: 0 10px; border: 1px solid var(--line); border-radius: 7px; background: var(--bg); color: var(--ink); font: inherit; font-size: 13px; }
.ac-email:focus, .ac-code:focus { outline: none; border-color: var(--accent-text); }
.ac-email::placeholder, .ac-code::placeholder { color: var(--muted); font-weight: 400; letter-spacing: normal; }
.ac-code { text-align: center; letter-spacing: .2em; text-transform: uppercase; font-weight: 600; }
.ac-error { margin: 0; font-size: 11.5px; line-height: 1.4; color: var(--danger); }
.ac-submit { width: 100%; height: 30px; border: 0; border-radius: 7px; background: var(--accent); color: var(--accent-ink); font: inherit; font-size: 13px; font-weight: 600; cursor: pointer; }
.ac-submit:hover:not(:disabled) { background: var(--accent-hover); }
.ac-submit:disabled { opacity: .5; cursor: default; }
.ac-links { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; font-size: 11px; color: var(--muted); }
.ac-link { padding: 0; border: 0; background: transparent; color: var(--accent-text); font: inherit; font-size: 11px; cursor: pointer; }
.ac-link:hover:not(:disabled) { text-decoration: underline; }
.ac-link:disabled { color: var(--muted); cursor: default; }
.ac-credits { display: flex; align-items: center; gap: 10px; }
.ac-ring { width: 28px; height: 28px; flex: 0 0 auto; transform: rotate(-90deg); }
.ac-ring-track { fill: none; stroke: var(--line); stroke-width: 3; }
.ac-ring-value { fill: none; stroke: var(--accent); stroke-width: 3; stroke-linecap: round; transition: stroke-dasharray .3s ease; }
#account[data-low="true"] .ac-ring-value { stroke: var(--amber); }
#account[data-low="empty"] .ac-ring-value { stroke: var(--danger); }
.ac-credits-text { display: flex; flex-direction: column; min-width: 0; }
.ac-credits-count { font-size: 13px; font-weight: 600; color: var(--ink); font-variant-numeric: tabular-nums; }
.ac-credits-label { font-size: 11px; color: var(--muted); }
.ac-email-line { font-size: 11px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* One row per chat: the title, and a ⋮ that opens the row's menu (Open scene in new chat, Delete chat). The whole
   row is the click target for switching; the ⋮ shows on hover, on the active row, while its menu is open and when
   focused, so the list stays quiet until a row is looked at. */
.session-item {
  display: flex; align-items: center; gap: 6px;
  padding: 6px 4px 6px 10px; border-radius: 8px; cursor: pointer; user-select: none;
  color: var(--muted); font-size: 13px; line-height: 1.35;
}
.session-item:hover, .session-item.menu-open { background: var(--chat-hover, rgba(127,127,127,.08)); color: var(--ink); }
.session-item.active { background: var(--agent-bubble, rgba(127,127,127,.14)); color: var(--ink); font-weight: 550; }
.session-title { flex: 1 1 auto; min-width: 0; padding: 2px 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* The name as a field, in place (Rename chat, app.js renameField): the text stays where it stood, the frame's border and
   padding pulled back by the 7 px they add; white on the column, framed in the accent as every focused field is; the
   whole name selected in the accent's tint; the ⋮ and the Open elsewhere badge step aside while it is open. */
.session-rename {
  flex: 1 1 auto; min-width: 0; height: 22px; margin: 0 0 0 -7px; padding: 0 6px;
  border: 1px solid var(--accent-text); border-radius: 5px; background: var(--panel); color: var(--ink);
  font: inherit; outline: none;
}
.session-rename::selection { background: color-mix(in srgb, var(--accent) 22%, transparent); }
.session-rename::placeholder { color: var(--muted); font-weight: 400; }
.session-menu-btn {
  flex: 0 0 auto; width: 22px; height: 22px; display: grid; place-items: center; padding: 0 0 2px;
  border: none; border-radius: 6px; background: transparent; color: var(--muted);
  font: inherit; font-size: 16px; line-height: 1; cursor: pointer; opacity: 0;
  transition: opacity .12s ease, background .15s ease, color .15s ease;
}
.session-item:hover .session-menu-btn, .session-item.active .session-menu-btn, .session-item.menu-open .session-menu-btn,
.session-menu-btn:focus-visible { opacity: 1; }
.session-menu-btn:hover, .session-menu-btn:focus-visible, .session-item.menu-open .session-menu-btn {
  background: var(--line); color: var(--ink); outline: none;
}
/* The tutorial sits below Samples, above the Chats divider. Its green dot marks unfinished lessons. */
#tutorial-entry-status { flex: 0 0 auto; color: var(--accent-text); font-size: 11px; }
#tutorial-entry.in-progress { box-shadow: inset 0 0 0 1px var(--line); background: var(--panel); }
.tutorial-library-card { display: flex; align-items: center; width: 100%; padding: 0; border: 1px solid transparent; border-radius: 7px; background: transparent; color: var(--ink); text-align: left; font: inherit; cursor: pointer; }
.tutorial-library-card:hover, .tutorial-library-card.active { border-color: var(--line); background: var(--panel); }
.tutorial-library-open { display: flex; flex: 1; min-width: 0; align-items: center; gap: 10px; padding: 10px; border: 0; border-radius: 7px; background: transparent; color: inherit; text-align: left; font: inherit; cursor: pointer; }
.tutorial-library-open:focus-visible { outline: 2px solid var(--accent-text); outline-offset: -2px; }
.tutorial-library-card.disabled { opacity: .5; }
.tutorial-library-open:disabled { cursor: default; }
.tutorial-library-card .session-menu-btn { margin-right: 8px; }
.tutorial-library-card:hover .session-menu-btn, .tutorial-library-card:focus-within .session-menu-btn,
.tutorial-library-card.active .session-menu-btn, .tutorial-library-card.menu-open .session-menu-btn { opacity: 1; }
.tutorial-library-card .session-menu-btn[hidden] { display: none; }
.tutorial-library-glyph { display: grid; place-items: center; flex: 0 0 30px; height: 30px; border-radius: 7px; color: var(--accent-text); background: color-mix(in srgb, var(--accent-text) 12%, transparent); }
.tutorial-library-glyph svg { width: 16px; height: 16px; }
.tutorial-library-body { display: flex; flex: 1; min-width: 0; flex-direction: column; gap: 2px; }
.tutorial-library-body strong { font-size: 13px; font-weight: 600; }
.tutorial-library-status { color: var(--muted); font-size: 11px; }
.tutorial-library-bar { height: 3px; margin-top: 3px; background: var(--line); }
.tutorial-library-bar > span { display: block; height: 100%; background: var(--accent-text); }
.session-item.tutorial { gap: 10px; color: var(--ink); } /* one line like every row: its progress lives in the tutorial itself */
.session-item.tutorial::before {
  content: ""; flex: 0 0 8px; width: 8px; height: 8px; border-radius: 50%; background: #339926;
  box-shadow: 0 0 0 3px color-mix(in srgb, #339926 22%, transparent);
}
.session-item.tutorial.done::before { display: none; }
.session-item.tutorial .session-title { font-weight: 600; }
.session-meta { font-size: 11px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* A scene the cloud device group sent (chat-list.js unseenDot): a plain accent dot before the name, no halo and no
   bold, on the row and in the card's title row, until the chat is first opened. */
.session-dot { flex: 0 0 7px; width: 7px; height: 7px; border-radius: 50%; background: var(--accent); }
.sessions-locked #new-chat, .sessions-locked .session-item, .sessions-locked .lib-card { opacity: .45; pointer-events: none; }

/* The chat menu popover. Same chrome as the viewer and the tutorial label: panel surface, hairline, soft shadow.
   Fixed at body level and above everything in the shell (the viewer is z 5 inside the scene pane). */
#session-menu {
  position: fixed; z-index: 20; min-width: 210px; padding: 4px;
  background: var(--panel); color: var(--ink); border: 1px solid var(--line); border-radius: 10px;
  box-shadow: 0 12px 32px rgba(0, 0, 0, .45);
}
#session-menu[hidden] { display: none; }
.session-menu-item {
  display: block; width: 100%; padding: 7px 12px; text-align: left;
  border: none; border-radius: 7px; background: transparent; color: var(--ink);
  font: inherit; font-size: 13px; line-height: 1.4; cursor: pointer; white-space: nowrap;
}
.session-menu-item:hover:not(:disabled), .session-menu-item:focus-visible { background: var(--chat-hover, rgba(127,127,127,.1)); outline: none; }
.session-menu-item:disabled { opacity: .45; cursor: default; }
.session-menu-item.danger { color: var(--danger); }

/* ---- scene (rightmost) ---- */
#scene { position: relative; height: 100%; min-width: 320px; flex: 1 1 auto; background: #000; overflow: hidden; }
/* The scene owns touch navigation. Safari ignores user-scalable=no, so the viewport meta alone
   cannot keep a pinch inside Unity. Leave browser gestures available on the surrounding shell. */
#unity-canvas { width: 100%; height: 100%; display: block; touch-action: none; }
.tutorial-scene-transition { position: absolute; inset: 0; width: 100%; height: 100%; background: #152021; opacity: 0; pointer-events: none; z-index: 1; }

#loading {
  position: absolute; inset: 0; display: grid; place-items: center;
  background: radial-gradient(120% 120% at 50% 40%, #112A27 0%, #0A1213 100%);
  transition: opacity .4s ease; z-index: 2;
}
#loading.hidden { opacity: 0; pointer-events: none; }
#loading-inner { display: flex; flex-direction: column; align-items: center; gap: 18px; }
.spinner {
  width: 34px; height: 34px; border-radius: 50%;
  border: 3px solid rgba(255,255,255,.12); border-top-color: var(--accent);
  animation: spin 900ms linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .spinner { animation: none; } }
#loading-text { color: #B5C3C1; /* on the dark veil in both themes */ font-size: 14px; letter-spacing: .02em; }
#progress-track { width: 200px; height: 3px; border-radius: 3px; background: rgba(255,255,255,.1); overflow: hidden; }
#progress-fill { height: 100%; width: 0%; background: var(--accent); transition: width .2s ease; }

/* ---- dividers ---- */
/* A pane squeezing under its floor while its divider is dragged (app.js applyLayout): its content is clipped, not
   reflowed, so the fold reads as the pane sliding away, and it fades as the fold nears (--squeeze, 0 at the floor
   to 1 at the fold). Beside the divider a label says what dragging on does, as faint or plain as the fade.
   The clip needs the content to keep its width: the children are flex items that would stretch to the pane and
   rewrap, so each holds the pane's floor (--floor, from applyLayout) and the pane cuts it. The chats list and the
   chat, with the divider on their right, lose their content under it; the panel, with the divider on its left,
   aligns its content to its right so it slides out leftward the same way. The fade runs to nothing, eased so the
   first part of the drag barely touches the words and the last part takes them. */
#sessions.squeezing, #chat.squeezing, #panel.squeezing { min-width: 0; overflow: hidden; }
#sessions.squeezing > *, #chat.squeezing > *, #panel.squeezing > * {
  min-width: var(--floor, 0); max-width: var(--floor, none); /* the cross axis: flex-shrink would stop the transcript giving height */
  opacity: calc(1 - var(--squeeze, 0) * var(--squeeze, 0));
}
#panel.squeezing { align-items: flex-end; }
.fold-hint {
  position: absolute; top: 50%; left: 100%; z-index: 5; transform: translateY(-50%); margin-left: 10px; padding: 5px 9px;
  border: 1px solid var(--line); border-radius: 6px; background: var(--panel); color: var(--ink); font-size: 11.5px; white-space: nowrap;
  box-shadow: 0 4px 14px rgba(0, 0, 0, .25); pointer-events: none; opacity: var(--squeeze, 0);
}
#divider-c .fold-hint { left: auto; right: 100%; margin: 0 10px 0 0; }
/* The tooltips (tooltip.js, design canvas page 33): every title in the fold hint's chrome, above everything (menus at 60),
   never taking the pointer. The name, a keycap for a shortcut beside it, a muted second line for a description; long
   text wraps at 260 px. tooltip.js places it and says the side it took in data-side. */
.sh-tooltip {
  position: fixed; left: 0; top: 0; z-index: 100; display: flex; flex-direction: column; gap: 2px; width: max-content; max-width: 260px;
  padding: 5px 9px; border: 1px solid var(--line); border-radius: 6px; background: var(--panel); color: var(--ink);
  font-size: 12px; font-weight: 500; line-height: 1.35; overflow-wrap: anywhere; box-shadow: 0 6px 18px rgba(0, 0, 0, .40); pointer-events: none;
}
.sh-tooltip[hidden] { display: none; }
.sh-tooltip .tt-name { display: flex; align-items: center; gap: 10px; }
.sh-tooltip .tt-name:has(kbd) { white-space: nowrap; }
.sh-tooltip kbd { padding: 0 5px; border: 1px solid var(--line); border-radius: 4px; background: var(--panel-2); color: var(--muted); font: inherit; font-size: 11px; line-height: 17px; }
.sh-tooltip .tt-sub { color: var(--muted); font-size: 11.5px; font-weight: 400; }
@media (prefers-color-scheme: light) { .sh-tooltip { box-shadow: 0 6px 18px rgba(0, 0, 0, .12); } }
.divider {
  flex: 0 0 var(--divider-w); cursor: col-resize; background: var(--line);
  position: relative; transition: background .15s ease;
  touch-action: none; user-select: none; -webkit-user-select: none; /* own the drag instead of starting Safari pan/zoom */
}
.divider::after {
  content: ""; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
  width: 2px; height: 34px; border-radius: 2px; background: var(--muted); opacity: .5;
}
.divider:hover, .divider.dragging, .divider:focus-visible { background: var(--accent); outline: none; }
/* The live video divider runs across the scene pane and drags up/down: same thickness, the grip turned on its side. */
.divider.horizontal { cursor: row-resize; width: 100%; }
.divider.horizontal::after { width: 34px; height: 2px; }
/* A finger needs more than the 6px line: on touch the horizontal dividers (the dock's and the live pane's) take 10px either side. */
@media (pointer: coarse) { .divider.horizontal::before { content: ""; position: absolute; left: 0; right: 0; top: -10px; bottom: -10px; } }

/* ---- collapsible panes (app.js "collapsible panes") ---- */
/* The chats list and the chat fold away as the side panel does, so a small screen can give the player the room. The
   fold controls follow two rules. The glyph: the shell's frame with the pane marked off as a region, and a small arrow
   inside the frame pointing the way the pane goes, into its edge to close, out of it to open; the region says which
   pane, the arrow says which way, and an arrow inside a frame is never read as Back, which is what the place head's
   own bare chevron is (#place-back). The place: a pane folds and unfolds at its edge, never from a header, which keeps
   its content. Folding is a tab that appears on the divider when it is hovered (.fold-tab, app.js wires one per
   vertical divider). Unfolding is where the pane went: the chats list leaves nothing on screen, so its open glyph
   stands at the chat header's left only while it is folded (#list-open), a plain button inset from the screen's edge
   for a finger or a stylus; the chat folds into the dock, a visible strip, so its way back is the same kind of button
   in the dock's lead line (#chat-expand), and #list-open then moves up to the scene header's left, level with the
   rail toggle at its right, so the two ways back frame the toolbar; the side panel's toggle is the
   rail band at the shell's right edge (#rail-toggle). aria-expanded picks a glyph's arrow. Folded panes and their
   dividers are display:none, so the split sees the right number of panes. */
.sessions-head { flex: 0 0 auto; display: flex; align-items: center; gap: 2px; margin: 12px 10px 8px; }
/* The fold tab: on the divider's line, shown while the divider is armed (app.js: the pointer has rested on the line,
   and has not yet left it for good) or holds keyboard focus, and not while it drags; the glyph of the pane it folds,
   and a click folds it, as the divider's double-click also does. app.js sets its top to sit just above the pointer
   where it reached the line; the 10px here is only its place under keyboard focus. */
.fold-tab {
  position: absolute; left: 50%; top: 10px; transform: translateX(-50%); width: 34px; height: 28px; display: grid; place-items: center;
  padding: 0; border: 1px solid var(--line); border-radius: 7px; background: var(--panel); color: var(--ink); cursor: pointer;
  opacity: 0; pointer-events: none; transition: opacity .15s ease, border-color .15s ease; z-index: 3;
}
.divider.armed .fold-tab, .divider:focus-within .fold-tab { opacity: 1; pointer-events: auto; }
.divider.dragging .fold-tab, .fold-tab[hidden] { display: none; }
.fold-tab svg { width: 16px; height: 16px; }
.fold-tab:hover, .fold-tab:focus-visible { border-color: var(--accent-text); outline: none; }
/* The list's way back: its open glyph as a plain .pane-glyph button, first in the chat header while the list is
   folded, or in the dock's open group when the chat is folded too. The header's own padding insets it from the
   screen's edge, where an iPad's edge swipes and a stylus's hover zone live, so no control sits flush with the glass. */
#chat-header #list-open { margin: 0 6px 0 -6px; } /* clear of the dot, and pulled 6px into the header's padding */
#scene-header #list-open { margin-left: -4px; } /* pulled into the toolbar's padding, where the rail toggle sits at the other end */
.pane-glyph {
  flex: 0 0 auto; width: 28px; height: 28px; display: grid; place-items: center; padding: 0; border: 0; border-radius: 7px;
  background: transparent; color: var(--muted); cursor: pointer; transition: color .15s ease;
}
.pane-glyph:hover, .pane-glyph:focus-visible { color: var(--ink); outline: none; }
.pane-glyph[hidden] { display: none; }
.pane-glyph svg { width: 16px; height: 16px; }
.pane-glyph[aria-expanded="true"] .pg-open, .pane-glyph[aria-expanded="false"] .pg-close { display: none; }
#sessions[hidden], #divider-a[hidden], #chat[hidden], #divider-b[hidden] { display: none; }
/* The chats as a popover under the chat's title while the list is hidden: New chat, the chats with the open one
   marked, and the way back to the list, which is where Archived lives. The chat menu's chrome, fixed at body level. */
#chats-popover {
  position: fixed; z-index: 20; min-width: 220px; max-width: 320px; padding: 4px; display: flex; flex-direction: column;
  background: var(--panel); color: var(--ink); border: 1px solid var(--line); border-radius: 10px;
  box-shadow: 0 12px 32px rgba(0, 0, 0, .45);
}
#chats-popover[hidden] { display: none; }
.cp-rows { max-height: 50vh; overflow-y: auto; }
.cp-rule { flex: 0 0 1px; margin: 4px 8px; background: var(--line); }
.cp-row {
  display: flex; align-items: center; gap: 8px; width: 100%; padding: 7px 12px; border: 0; border-radius: 7px;
  background: transparent; color: var(--ink); font: inherit; font-size: 13px; line-height: 1.4; text-align: left; cursor: pointer;
}
.cp-row:hover:not(:disabled), .cp-row:focus-visible { background: var(--chat-hover, rgba(127,127,127,.1)); outline: none; }
.cp-row:disabled { opacity: .45; cursor: default; }
.cp-row.active { background: var(--agent-bubble, rgba(127,127,127,.14)); font-weight: 550; }
.cp-row.muted { color: var(--muted); }
.cp-title { flex: 1 1 auto; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cp-check { flex: 0 0 auto; width: 14px; height: 14px; }
/* The dock: the scene pane's last row, under the player and a docked Live render pane, behind the dock divider (the
   live divider's twin: app.js fracs.dock). Closed, it is the lead line and the composer and takes its own height.
   Dragged open (.expanded) it takes the height the drag gave it and the transcript, moved here with the composer,
   fills the room between the two; the lead line then drops its words, since the replies are in view, and keeps the
   way back, the name and the save state. */
#divider-dock[hidden] { display: none; }
#composer-dock { flex: 0 0 auto; display: flex; flex-direction: column; min-height: 0; background: var(--panel-2); container-type: inline-size; } /* the lead line's extras come and go with the dock's width */
#composer-dock[hidden] { display: none; }
#composer-dock #composer { border-top: 0; padding-top: 0; }
/* Wide, the dock's composer is one line (design canvas Lower collapsed dock, A): the field at the left, then the chips,
   the squares and the arrow, on one row of the box, the row's own box dissolved into it (display: contents) so its
   children stand beside the field. The reasoning and speed chips keep to their squares here (composer-chips.js fit),
   the width being the field's. A longer draft lifts the field line by line against the bottom-aligned row and scrolls
   inside past six lines. The chat pane's composer keeps its two-line field over its row. */
@container (min-width: 760px) {
  #composer-dock #composer-box { flex-direction: row; align-items: flex-end; gap: 6px; padding: 8px 10px; }
  #composer-dock #composer-row { display: contents; }
  #composer-dock #composer-options { flex: 0 0 auto; }
  /* The spacer that parts the settings from the message's own buttons across the pane's row is a hairline here, since
     the row no longer has a width to part them with: the settings persist, the squares act on this message. */
  #composer-dock .composer-spacer { flex: 0 0 1px; width: 1px; height: 16px; margin: 0 2px 7px; background: var(--line); }
  #composer-dock #input { min-height: 30px; max-height: 130px; padding: 5px 4px 5px 6px; overflow-y: auto; }
}
#composer-dock #messages, #composer-dock #prompt-queue { display: none; }
#composer-dock.expanded #messages { display: flex; padding: 12px 18px; background: var(--panel); }
#composer-dock.expanded #prompt-queue:not([hidden]) { display: block; }
#composer-dock.expanded #dock-lead { border-bottom: 1px solid var(--line); }
#composer-dock.expanded .dock-line, #composer-dock.expanded #dock-then, #composer-dock.expanded #dock-thumbs { display: none; } /* the transcript is in view: it has all of it */
#composer-dock.expanded #composer { padding-top: 10px; border-top: 1px solid var(--line); }
/* The tutorial's intro and lesson card dock with the chat (app.js dockMovers, for the portrait layout) and keep their
   own display there, open or closed: a closed dock is the lead line and the composer, and the lesson's instructions
   stand above the composer as they do in the pane (Embla, 2026-10-14), since a tutorial without its card is unusable;
   only the transcript waits for the drag. An open dock grows to hold its rows (app.js applyLayout, dockRows); where
   even the player's floor leaves too little, the card is the row that gives, shrinking to a few lines and scrolling,
   so the composer never leaves the pane. */
#composer-dock.expanded #tutorial-panel:not([hidden]) { flex: 0 1 auto; min-height: 72px; overflow-y: auto; } /* the eyebrow, the title and a line; the transcript's 24px of padding stays below it at the cap */
/* The transcript's basis is nothing here, so it takes only what the rows leave and never makes the card give way first:
   flex-shrink spreads the squeeze by basis, and the transcript's own content would otherwise be the larger basis. */
#composer-dock.expanded #messages { flex: 1 1 0; }
/* The lead line keeps the composer's 14 px inset, so the open button starts on the box's left edge and the save state ends
   on its right edge (the badge's own padding pulled back). */
/* A grid, so the one-line row stays the one-line row (the open button, the dot, the name, the line, the thumbnails, the
   save state, each centred on the 28 px button) and the second line, when there is one, hangs under the line's own
   column, left-aligned with it, rather than the two lines being centred as a block against the row. */
#dock-lead {
  flex: 0 0 auto; display: grid; grid-template-columns: auto auto fit-content(40%) minmax(0, 1fr) auto auto fit-content(220px); align-items: center; /* the name and the save state take their own width up to a cap; a cap on the item itself would resolve against its own column, and a minmax track would stretch to it */
  column-gap: 8px; min-width: 0; padding: 6px 14px; font-size: 12.5px; color: var(--muted);
}
#chat-expand { grid-column: 1; margin-right: 6px; } /* clear of the dot and name, as the list's button is in the chat header */ #dock-dot { grid-column: 2; } #dock-title { grid-column: 3; } .dock-line { grid-column: 4; }
#dock-thumbs { grid-column: 5; }
/* The save state's words end on the arrow's right edge below (the box's border, then its 10 px of padding), the edge the
   eye matches, rather than on the border line. */
#dock-lead .cloud-save-state { grid-column: 7; max-width: none; margin-right: 5px; }
#dock-lead .cloud-save-state[data-state="conflict"], #dock-lead .cloud-save-state[data-state="remote"] { border-radius: 7px; } /* the pill (below) rounds like the lead line's chrome */
/* The cloud card in the dock (app.js paneHooks): one row under the lead line, over the composer; the heading, the
   sentence cut to one line, the buttons at the right. */
#composer-dock #cloud-card { flex-direction: row; align-items: center; gap: 12px; margin: 0 14px 8px; padding: 8px 12px; }
#composer-dock #cloud-card .cloud-card-head { flex: none; white-space: nowrap; }
#composer-dock #cloud-card .cloud-card-text { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#composer-dock #cloud-card .cloud-card-actions { flex: none; margin: 0 0 0 auto; }
@container (max-width: 700px) { #composer-dock #cloud-card .cloud-card-text { display: none; } } /* a narrow dock keeps the heading and the choice */
/* The sample panel in the dock (app.js paneHooks): the cloud card's row, the heading, the sentence cut to one line and
   Continue Designing at the right, where the collapsed sample chat would otherwise offer nothing. :not([hidden]) keeps
   the panel's own [hidden] rule (below) in charge of whether it shows. */
#composer-dock #sample-panel:not([hidden]) {
  display: flex; align-items: center; gap: 12px; margin: 0 14px 8px; padding: 8px 12px;
  border: 1px solid var(--line); border-top: 1px solid var(--line); border-radius: 10px; font-size: 12.5px;
}
/* The words give way, never the button, and the heading stays whole: with the sentence on the row (a wide dock) only
   the sentence shrinks, cut with an ellipsis, and the heading keeps its line (flex: none). Below 700px the container
   rule at the foot drops the sentence and lets the heading wrap instead, so it still reads in full beside the button
   on the narrowest dock (MIN_SCENE), on two lines when one is not enough. The button is flex: none throughout. */
#composer-dock #sample-panel strong { flex: none; white-space: nowrap; font-size: 12.5px; font-weight: 500; line-height: 1.3; color: var(--ink); }
#composer-dock #sample-panel p { flex: 1 1 auto; min-width: 0; margin: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* The button in the strip's own idiom (.header-btn): the line border at rest, the accent on hover, no fill.
   The pane's filled accent button is a card's call to action; in the dock it shouts over the lead line. */
#composer-dock #sample-panel .continue-designing {
  flex: none; height: 30px; margin-left: auto; padding: 0 12px; border-color: var(--line); border-radius: 8px;
  background: var(--panel); color: var(--ink); font-size: 12.5px; font-weight: 500;
}
#composer-dock #sample-panel .continue-designing:hover:not(:disabled), #composer-dock #sample-panel .continue-designing:focus-visible { background: var(--panel); border-color: var(--accent-text); color: var(--ink); }
@container (max-width: 700px) { /* a narrow dock keeps the heading, wrapping, and the button */
  #composer-dock #sample-panel p { display: none; }
  #composer-dock #sample-panel strong { flex: 1 1 auto; min-width: 0; white-space: normal; }
}
#dock-then { grid-column: 4; grid-row: 2; }
#dock-title { max-width: none; margin: 0; font-size: 12.5px; font-weight: 600; color: var(--ink); }
.dock-line {
  min-width: 0; padding: 0; border: 0; background: transparent; color: inherit; font: inherit; text-align: left;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; cursor: pointer; transition: color .15s ease;
}
.dock-line:hover, .dock-line:focus-visible { color: var(--ink); outline: none; }
/* The second line and the thumbnails show only on a wide dock (a landscape player of some size), where the lead
   line has the room for them; a narrow dock keeps to its one line. */
#dock-then { display: none; min-width: 0; margin-top: -2px; font-size: 11.5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#dock-now.current, #dock-then.current { animation: pulse 1.6s ease-in-out infinite; } /* the agent's activity line, as in the transcript */
@media (prefers-reduced-motion: reduce) { #dock-now.current, #dock-then.current { animation: none; } }
#dock-thumbs { display: none; flex: 0 0 auto; align-items: center; gap: 6px; }
@container (min-width: 760px) {
  #dock-then:not([hidden]) { display: block; }
  #dock-thumbs:not([hidden]) { display: flex; }
}
/* One tile is a render's 4:3 at 40 by 30 with the transcript frame's line, corners and sunken ground; the spinner
   tile carries the cards' own spinner, small. The latest finished one sits on a stack (two edges stepping back
   behind it) when there are more, with how many in the corner chip the duration label uses. */
.dock-thumb {
  position: relative; box-sizing: border-box; width: 40px; height: 30px; padding: 0; border: 1px solid var(--line); border-radius: 5px;
  background: var(--bg); color: var(--muted); overflow: hidden; cursor: pointer; transition: border-color .15s ease;
}
.dock-thumb img, .dock-thumb video { display: block; width: 100%; height: 100%; object-fit: cover; }
.dock-thumb.pending { display: grid; place-items: center; cursor: default; }
.dock-thumb.pending .spinner { width: 14px; height: 14px; border-width: 2px; }
button.dock-thumb:hover, button.dock-thumb:focus-visible { border-color: var(--accent-text); outline: none; }
.dock-play { position: absolute; inset: 0; display: grid; place-items: center; pointer-events: none; }
.dock-play span { width: 12px; height: 12px; display: grid; place-items: center; border-radius: 50%; background: rgba(0, 0, 0, .55); color: #fff; }
.dock-play svg { width: 6px; height: 6px; fill: currentColor; margin-left: 1px; }
.dock-stack { position: relative; display: block; width: 40px; height: 30px; }
.dock-stack.many { width: 48px; }
.dock-stack.many::before, .dock-stack.many::after { content: ""; position: absolute; box-sizing: border-box; border: 1px solid var(--line); border-radius: 5px; }
.dock-stack.many::before { left: 6px; top: 3px; width: 40px; height: 24px; background: var(--panel); }
.dock-stack.many::after { left: 3px; top: 1.5px; width: 40px; height: 27px; background: var(--panel-2); }
.dock-stack .dock-thumb { position: absolute; left: 0; top: 0; z-index: 1; }
.dock-more {
  position: absolute; right: 0; bottom: -4px; z-index: 2; padding: 1px 4px; border-radius: 5px; pointer-events: none;
  background: rgba(0, 0, 0, .72); color: #fff; font-size: 10px; font-weight: 600; line-height: 12px; font-variant-numeric: tabular-nums;
}

/* ---- chat (middle) ---- */
#chat {
  height: 100%; min-width: 290px; /* app.js MIN_CHAT: the composer's one-line width */
  display: flex; flex-direction: column; background: var(--panel);
}
#chat-header {
  display: flex; align-items: center; gap: 8px;
  min-height: var(--toolbar-h); padding: 0 18px; border-bottom: 1px solid var(--line); /* as tall as the player toolbar */
  font-weight: 600; font-size: 14px; letter-spacing: .01em;
}
#chat-header .dot, #dock-lead .dot { flex: 0 0 auto; width: 8px; height: 8px; border-radius: 50%; /* never squeezed by a long name or a narrow pane */ background: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 25%, transparent); }
#chat-header .dot[data-busy="true"], #dock-lead .dot[data-busy="true"] { animation: pulse 1.6s ease-in-out infinite; } /* the agent is working: the chat's activity line has the words */
/* The header names the open chat (app.js syncChatTitle) and never wraps: the name takes the room there is and is cut
   short; the Logs button and the save state keep their width at its right (design canvas page 28). It is a button
   that only works while the chats list is hidden (collapsible panes, below): the chats then drop down under it, and
   a chevron says so; disabled, it is the plain label. */
.title-menu {
  flex: 1 1 auto; min-width: 0; position: relative; margin: 0 0 0 -6px; padding: 2px 6px; border: 0; border-radius: 6px;
  background: transparent; color: inherit; font: inherit; text-align: left; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; cursor: default;
}
.title-menu:not(:disabled) { padding-right: 24px; cursor: pointer; transition: background .15s ease; }
#chat-title { min-width: 56px; } /* a narrow pane keeps a few letters of the name; the save state gives way first */
.title-menu:not(:disabled)::after {
  content: ''; position: absolute; right: 6px; top: 50%; width: 14px; height: 14px; margin-top: -7px; background: currentColor;
  -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M6 9l6 6 6-6'/></svg>") center / contain no-repeat;
  mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M6 9l6 6 6-6'/></svg>") center / contain no-repeat;
}
.title-menu:not(:disabled):hover, .title-menu:not(:disabled):focus-visible, .title-menu[aria-expanded="true"] { background: var(--line); outline: none; }
/* With no bound scene, the tutorial chooser replaces the unstarted chat's controls. Browsing the folder
   with an existing scene leaves its chat and controls visible and active. */
#chat.tutorial-chooser > :not(#chat-header):not(#tutorial-browser-intro),
#chat.tutorial-chooser #chat-header > :not(#chat-title):not(#list-open) { display: none; }
#tutorial-browser-intro { flex: 1; display: flex; flex-direction: column; justify-content: center; text-align: center; padding: 24px; }
#tutorial-browser-intro[hidden] { display: none; }
#tutorial-browser-intro h2 { font-size: 15px; font-weight: 600; margin: 0 0 8px; }
#tutorial-browser-intro p { color: var(--muted); font-size: 13px; line-height: 1.5; margin: 0; }
#chat-metrics {
  padding: 8px 18px; border-bottom: 1px solid var(--line);
  color: var(--muted); font-size: 12px; line-height: 1.35;
}

/* ---- tutorial lesson card (above the composer, outside the scrolling transcript) ---- */
#tutorial-panel {
  flex: 0 0 auto; display: flex; flex-direction: column; gap: 6px; padding: 12px 18px 12px;
  border-top: 1px solid var(--line); background: var(--panel-2);
}
#tutorial-panel[hidden] { display: none; }
#tutorial-panel.placeholder #tutorial-eyebrow { display: none; }
#tutorial-panel.placeholder #tutorial-demo-note { font-style: italic; }
#tutorial-guide { text-decoration: none; }
#tutorial-guide[hidden], .tutorial-library-bar[hidden] { display: none; }
#tutorial-chapter-nav { display: flex; flex-direction: column; gap: 10px; }
#tutorial-chapter-nav[hidden] { display: none; }
#tutorial-chapters { flex: 1; min-width: 0; display: flex; gap: 6px; list-style: none; margin: 0 0 5px; padding: 0; font-size: 11px; line-height: 1.4; color: var(--muted); }
/* Keep equal columns in one row; the button owns the bar so its entire area selects the chapter. */
#tutorial-chapters li { flex: 1 1 0; min-width: 0; display: flex; --chapter-line: var(--line); }
#tutorial-chapters li[aria-current="step"] { --chapter-line: var(--accent-text); color: var(--ink); font-weight: 600; }
#tutorial-chapters li.done { --chapter-line: var(--accent-text); }
#tutorial-chapters button, #tutorial-chapters li > span { flex: 1; min-width: 0; padding: 6px 0 2px; border: 0; border-top: 3px solid var(--chapter-line); border-radius: 0; background: transparent; color: inherit; font: inherit; text-align: left; white-space: normal; overflow-wrap: anywhere; }
#tutorial-chapters button { cursor: pointer; }
#tutorial-chapters button:hover:not(:disabled) { color: var(--accent-text); text-decoration: underline; }
#tutorial-chapters button:focus-visible { outline: 2px solid var(--accent-text); outline-offset: 3px; }
#tutorial-chapters button:disabled { cursor: default; opacity: .6; }
#tutorial-files { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 8px; }
#tutorial-files[hidden] { display: none; }
.im-root #tutorial-files { margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--line); }
.tutorial-practice-note { flex-basis: 100%; color: var(--muted); font-size: 12px; line-height: 1.5; }
.tutorial-screenshot-placeholder { min-height: 150px; display: flex; flex-direction: column; justify-content: center; gap: 8px; padding: 20px; margin-bottom: 12px; border: 1px dashed var(--line); border-radius: 8px; background: var(--panel-2); text-align: center; }
.tutorial-screenshot-placeholder span { color: var(--muted); font-size: 12px; }
#tutorial-chapters[hidden], #tutorial-auto[hidden] { display: none; }
#tutorial-demo-note { color: var(--muted); font-size: 11.5px; line-height: 1.4; }
#tutorial-demo-note:empty, #tutorial-error:empty { display: none; }
#tutorial-error { color: var(--ink); font-size: 12.5px; line-height: 1.4; }
#composer-request { display: flex; flex-direction: column; gap: 5px; }
/* The suggested request's chrome lands on the box itself - one border, not a second one around the label and the row:
   the accent border while a suggestion stands, and the slow pulse of the box's shadow while it waits for Send. app.js
   keeps the classes on #composer-request, which tutorial-anchors.js's chat.prompt anchor reads. */
#composer-request.suggested-request .composer-box { border-color: var(--accent-text); }
#tutorial-prompt-label { font-size: 11.5px; line-height: 1.4; color: var(--muted); }
#composer-request.needs-action .composer-box { box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent) 28%, transparent); animation: tutorial-request-attention 2.4s ease-in-out infinite; }
/* The next action uses the same green as tool guidance, distinct from the teal Send button. */
#composer-request.needs-action #send:not(:disabled):not([hidden]) { outline: 3px solid #339926; outline-offset: 3px; }
@keyframes tutorial-request-attention { 50% { box-shadow: 0 0 0 9px color-mix(in srgb, var(--accent) 10%, transparent); } }
@media (prefers-reduced-motion: reduce) { #composer-request.needs-action .composer-box { animation: none; } }
#tutorial-prompt-label[hidden] { display: none; }
.guided-reply::before { content: 'Guided example'; display: block; margin-bottom: 5px; color: var(--muted); font-size: 11px; }
.guided-reply.tutorial-guide::before { content: 'Tutorial guide'; }
.tutorial-guide-title { display: block; margin-bottom: 8px; }
.tutorial-guide .guided-gallery { grid-template-columns: minmax(0, 1fr); }
#tutorial-eyebrow { display: flex; align-items: center; gap: 10px; font-size: 11.5px; letter-spacing: .07em; text-transform: uppercase; color: var(--muted); font-weight: 600; }
#tutorial-verdict { margin-left: auto; text-transform: none; letter-spacing: 0; font-size: 12px; font-weight: 600; color: var(--muted); }
#tutorial-verdict.met { color: var(--accent-text); }
#tutorial-title { font-size: 15px; font-weight: 600; color: var(--ink); line-height: 1.3; }
#tutorial-actions { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 8px; margin-top: 4px; }
#tutorial-actions button, #tutorial-guide {
  padding: 6px 12px; border: 1px solid var(--line); border-radius: 8px; background: var(--panel); color: var(--ink);
  font: inherit; font-size: 13px; font-weight: 600; cursor: pointer; transition: border-color .15s ease, opacity .15s ease;
}
#tutorial-actions button:hover:not(:disabled), #tutorial-actions button:focus-visible,
#tutorial-guide:hover, #tutorial-guide:focus-visible { border-color: var(--accent-text); outline: none; }
#tutorial-actions button:disabled { opacity: .45; cursor: default; }
#tutorial-actions #tutorial-continue { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); }
#tutorial-actions .continue-designing, .continue-designing {
  padding: 8px 14px; border: 1px solid var(--accent); border-radius: 8px; background: var(--accent); color: var(--accent-ink);
  font: inherit; font-size: 13px; font-weight: 600; cursor: pointer;
}
#tutorial-actions .continue-designing { padding: 6px 12px; }
#tutorial-actions .continue-designing:hover:not(:disabled), .continue-designing:hover:not(:disabled) { background: var(--accent-hover); border-color: var(--accent-hover); }
#tutorial-actions .continue-designing:focus-visible, .continue-designing:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }
.continue-designing:disabled { opacity: .45; cursor: default; }
#sample-panel { padding: 16px 18px; border-top: 1px solid var(--line); background: var(--panel-2); }
#sample-panel[hidden] { display: none; }
#sample-panel p { margin: 6px 0 12px; color: var(--muted); font-size: 13px; line-height: 1.5; }
#tutorial-auto { margin-left: auto; display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--muted); cursor: pointer; white-space: nowrap; }
#tutorial-auto input { accent-color: var(--accent); margin: 0; }

/* The transcript flows bottom-up: the column is bottom-anchored (margin-top:auto on the first child), so the
   first user bubble sits just above the composer and everything shifts upward as replies stream in. */
#messages {
  flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 20px 18px;
  display: flex; flex-direction: column; gap: 14px; scroll-behavior: smooth;
}
#messages > :first-child { margin-top: auto; }

.msg { white-space: pre-wrap; word-wrap: break-word; }
/* user: grey chat bubble, right-aligned (light bubble on dark chrome, like the reference) */
.msg.user {
  align-self: flex-end; max-width: 84%;
  background: var(--user-bubble); color: var(--user-ink);
  padding: 11px 15px; border-radius: 16px; border-bottom-right-radius: 6px;
}
/* agent: no bubble - plain left-aligned prose */
.msg.agent { align-self: stretch; color: var(--ink); padding: 0 2px; }
/* Markdown owns prose spacing; tutorial media, titles and share controls remain outside this wrapper. */
.agent-markdown { white-space: normal; overflow-wrap: anywhere; min-width: 0; }
.agent-markdown > :first-child { margin-top: 0; }
.agent-markdown > :last-child { margin-bottom: 0; }
.agent-markdown p, .agent-markdown ul, .agent-markdown ol, .agent-markdown blockquote, .agent-markdown pre { margin: 0 0 10px; }
.agent-markdown ul, .agent-markdown ol { padding-left: 24px; }
.agent-markdown li > ul, .agent-markdown li > ol { margin-bottom: 0; }
.agent-markdown h1, .agent-markdown h2, .agent-markdown h3, .agent-markdown h4, .agent-markdown h5, .agent-markdown h6 { font-size: 1em; line-height: 1.4; margin: 14px 0 6px; }
.agent-markdown blockquote { border-left: 3px solid var(--line); padding-left: 12px; color: var(--muted); }
.agent-markdown code { font-size: .9em; background: var(--panel-2); border-radius: 3px; padding: 1px 4px; }
.agent-markdown pre { white-space: pre; overflow-x: auto; padding: 10px; border: 1px solid var(--line); border-radius: 6px; background: var(--panel-2); }
.agent-markdown pre code { padding: 0; background: none; }
.agent-markdown table { display: block; overflow-x: auto; border-collapse: collapse; margin-bottom: 10px; }
.agent-markdown th, .agent-markdown td { border: 1px solid var(--line); padding: 5px 8px; text-align: left; }
/* URLs the agent writes (help-center articles, web sources) open in a new tab; the accent keeps them visible
   against the plain prose without turning the whole message into a link list. */
.msg a { color: var(--accent-text); text-decoration: none; border-bottom: 1px solid color-mix(in srgb, var(--accent-text) 45%, transparent); word-break: break-all; }
.msg a:hover, .msg a:focus-visible { border-bottom-color: var(--accent-text); outline: none; }

/* ---- tutorial video cards (a [video:id] line in a tutor message) ---- */
.video-card {
  align-self: stretch; display: flex; flex-direction: column; overflow: hidden;
  border: 1px solid var(--line); border-radius: 10px; background: var(--panel-2);
}
.video-card video { display: block; width: 100%; aspect-ratio: 16 / 9; background: #000; }
.video-caption { display: flex; align-items: center; gap: 10px; padding: 8px 10px 8px 12px; font-size: 12.5px; color: var(--muted); }
.video-caption span { flex: 1 1 auto; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: var(--ink); }
.video-caption button {
  flex: 0 0 auto; padding: 4px 10px; border: 1px solid var(--line); border-radius: 7px; background: var(--panel);
  color: var(--ink); font: inherit; font-size: 12px; cursor: pointer; transition: border-color .15s ease;
}
.video-caption button:hover, .video-caption button:focus-visible { border-color: var(--accent-text); outline: none; }
/* Errors stay readable without overpowering the completed work; raw technical detail belongs in the export. */
.msg.error { align-self: stretch; color: var(--muted); font-size: 13px; font-weight: 400; padding: 0 2px; }
/* model reasoning summaries: muted, smaller - "what the agent is thinking" between tool calls */
.msg.thought { align-self: stretch; color: var(--muted); font-size: 13.5px; padding: 0 2px; }

/* streamed activity lines while the agent works ("Thinking…", "Using Arkio tool: …") */
.activity { align-self: stretch; color: var(--muted); font-size: 13px; padding: 0 2px; }
.activity.current { animation: pulse 1.6s ease-in-out infinite; }
@keyframes pulse { 0%, 100% { opacity: .45; } 50% { opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .activity.current { animation: none; } }

/* collapsed per-turn summary once the turn completes (the "Worked for Xs" row) */
.worked {
  align-self: stretch; color: var(--muted); font-size: 13px;
  border-top: 1px solid var(--line); padding: 10px 2px 0;
}
/* Section line in Saved media: which deleted chat the media below came from, and when. */
.history-label {
  align-self: stretch; color: var(--muted); font-size: 12.5px;
  border-top: 1px solid var(--line); padding: 12px 2px 0;
}
.history-label:first-child { border-top: none; padding-top: 0; }

/* Task model labels and development accounting stay visually subordinate to the conversation. */
.usage, .model-selection {
  align-self: stretch; color: var(--muted); font-size: 12px; line-height: 1.45;
  padding: 0 2px;
}

#empty { margin: auto; text-align: center; color: var(--muted); max-width: 260px; }
#empty h2 { font-size: 15px; font-weight: 600; color: var(--ink); margin: 0 0 6px; }
#empty p { margin: 0; font-size: 13px; }

/* ---- composer ---- */
/* Drafts and attachments grow to their own scroll limits, leaving the action row and transcript reachable. */
#composer { flex: 0 0 auto; display: flex; flex-direction: column; gap: 8px; padding: 14px; border-top: 1px solid var(--line); background: var(--panel-2); }
#composer[hidden] { display: none; } /* Saved media has no one to talk to */
/* The box (design canvas page 30): the field across it, then one line inside its bottom edge with the settings' chips at
   the left and the squares and the arrow at the right. The agent composer (#composer-box) and the group chat's
   (.gc-composer) are built from these classes so the two cannot drift; what only one of them has is under its id. */
.composer-box {
  display: flex; flex-direction: column; gap: 8px; padding: 10px 10px 8px;
  border: 1px solid var(--line); border-radius: 12px; background: var(--bg); transition: border-color .15s ease;
}
.composer-box:focus-within { border-color: var(--accent-text); }
/* The Arkio AI terms notice under the box (agent-terms.js, index.html #ai-notice): one muted line behind a chevron, the
   full text and the Terms link once opened. The same muted size as the Export tab's line (.tx-legal). */
.ai-notice { margin: -2px 2px 0; font-size: 11px; line-height: 1.4; color: var(--muted); }
.ai-notice > summary { display: flex; align-items: center; gap: 5px; list-style: none; cursor: pointer; border-radius: 4px; }
.ai-notice > summary::-webkit-details-marker { display: none; }
.ai-notice > summary svg { flex: 0 0 auto; width: 11px; height: 11px; transition: transform .15s ease; }
.ai-notice[open] > summary svg { transform: rotate(90deg); }
.ai-notice > summary:hover { color: var(--ink); }
.ai-notice > summary:focus-visible { outline: 2px solid var(--accent-text); outline-offset: 2px; }
.ai-notice p { margin: 4px 0 0 16px; }
#composer-dock .ai-notice { margin: 0 12px 6px; }
/* The line under the box while the account has no AI credits (index.html #credits-needed): the notice's muted size, its
   button a link in the accent's text colour. */
.composer-credits { margin: -2px 2px 0; font-size: 11px; line-height: 1.4; color: var(--muted); }
.composer-credits[hidden] { display: none; }
.composer-credits button { padding: 0; border: 0; background: none; font: inherit; color: var(--accent-text); cursor: pointer; border-radius: 4px; }
.composer-credits button:hover { text-decoration: underline; }
.composer-credits button:focus-visible { outline: 2px solid var(--accent-text); outline-offset: 2px; }
#composer-dock .composer-credits { margin: 0 12px 6px; }
.composer-row { display: flex; align-items: center; gap: 6px; min-width: 0; }
/* Under about 300 px of pane the line cannot hold even the icon chips, the three squares and the arrow (composer-chips.js
   fit sets data-wrap): the chips take the first line and the spacer pushes the buttons to the right of the next. */
.composer-row[data-wrap="true"] { flex-wrap: wrap; }
.composer-row[data-wrap="true"] > #composer-options { flex: 0 0 100%; }
.composer-spacer { flex: 1 1 auto; min-width: 0; }
/* the squares: the camera, the paperclip and the mic (and the group chat's paperclip), 28 px in the chips' chrome */
.composer-square {
  flex: 0 0 auto; width: 28px; height: 28px; display: inline-flex; align-items: center; justify-content: center; padding: 0;
  border: 1px solid var(--line); border-radius: 7px; background: var(--panel); color: var(--ink); cursor: pointer; transition: border-color .15s ease;
}
.composer-square svg { width: 15px; height: 15px; }
.composer-square:hover:not(:disabled), .composer-square:focus-visible { border-color: var(--accent-text); outline: none; }
.composer-square:disabled { opacity: .4; cursor: default; }
/* the arrow: Send, in the filled accent the shell reserves for it, 30 px at the line's end; the group chat's too */
.composer-send {
  flex: 0 0 auto; width: 30px; height: 30px; display: inline-flex; align-items: center; justify-content: center; padding: 0;
  border: none; border-radius: 8px; background: var(--accent); color: var(--accent-ink); cursor: pointer; transition: opacity .15s ease;
}
.composer-send svg { width: 16px; height: 16px; }
.composer-send:hover:not(:disabled) { background: var(--accent-hover); }
.composer-send:focus-visible { outline: 2px solid var(--accent-text); outline-offset: 2px; }
.composer-send:disabled { opacity: .4; cursor: not-allowed; }
/* Stop takes the arrow's place while the agent works and nothing is drafted (app.js syncSendControls): a square in the
   chips' chrome, red only under the pointer, so the line stays about the next message rather than about stopping. */
#stop {
  flex: 0 0 auto; width: 30px; height: 30px; display: inline-flex; align-items: center; justify-content: center; padding: 0;
  border: 1px solid var(--line); border-radius: 8px; background: var(--panel); color: var(--ink); cursor: pointer;
}
#stop svg { width: 15px; height: 15px; }
#stop:hover { border-color: var(--danger); color: var(--danger); }
#send[hidden], #stop[hidden] { display: none; } /* the hidden attribute has to beat the display above: one of the two stands at the line's end */
/* The field has the whole box: no frame of its own, two lines tall at rest, growing with the words (app.js autosize,
   group-chat.js autosize), then scrolling inside the viewport-relative cap. */
#input, #group-input {
  flex: 1 1 auto; width: 100%; min-width: 0; min-height: 40px; max-height: min(240px, 25dvh); resize: none; overflow-y: auto; overscroll-behavior-y: contain; padding: 0;
  border: 0; border-radius: 0; background: transparent; color: var(--ink);
  font: inherit; line-height: 20px;
}
#input:focus, #group-input:focus { outline: none; }
#input::placeholder, #group-input::placeholder { color: var(--muted); }
/* The settings as chips (composer-chips.js): Model, Reasoning and Speed, each a button with the setting's icon, the
   chosen value and a chevron, its menu above it. The native selects stay in the DOM as the state app.js reads and
   writes: display:none, not the hidden attribute, which app.js toggles on the groups. data-values says which chips
   show their values (the fit): all, the model's only, or none, each then a 28 px square like the buttons. */
#composer-options { flex: 0 0 auto; min-width: 0; display: flex; align-items: center; gap: 6px; }
#composer-options select { display: none; }
.opt-group { position: relative; display: inline-flex; align-items: center; }
.opt-group[hidden] { display: none; }
.chip {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: 5px; height: 28px; padding: 0 8px;
  border: 1px solid var(--line); border-radius: 7px; background: var(--panel); color: var(--ink);
  font: inherit; font-size: 12px; white-space: nowrap; cursor: pointer; transition: border-color .15s ease;
}
.chip:hover:not(:disabled), .chip:focus-visible { border-color: var(--accent-text); outline: none; }
.chip[aria-expanded="true"] { border-color: var(--accent-text); background: var(--accent-soft); color: var(--accent-text); }
.chip:disabled { opacity: .55; cursor: default; }
.chip-icon, .chip-chevron { display: inline-flex; flex: 0 0 auto; }
.chip-icon svg { width: 15px; height: 15px; }
.opt-group[data-setting="reasoning"] .chip-icon svg { width: 17px; height: 17px; } /* the dial a size up: its needle has to read */
.chip-chevron svg { width: 10px; height: 10px; color: var(--muted); }
.chip-value { min-width: 0; max-width: 150px; overflow: hidden; text-overflow: ellipsis; } /* unknown catalog ids may be long */
#composer-options[data-values="none"] .chip, #composer-options[data-values="model"] .opt-group:not([data-setting="model"]) .chip { width: 28px; padding: 0; justify-content: center; }
#composer-options[data-values="none"] .chip-value, #composer-options[data-values="none"] .chip-chevron,
#composer-options[data-values="model"] .opt-group:not([data-setting="model"]) .chip-value, #composer-options[data-values="model"] .opt-group:not([data-setting="model"]) .chip-chevron { display: none; }
/* the menu is the voice bar's picker (.vb-picker below), opening above the chip from its left edge; a long model list
   scrolls. While fit measures the line the menu leaves it: an open menu is not the line's width. */
.vb-picker.chip-menu { left: 0; right: auto; bottom: calc(100% + 6px); min-width: 160px; max-height: 50vh; overflow: auto; }
.composer-row.is-fitting .chip-menu { display: none; }
/* The render bar's selects (render-chip.js) keep the chrome the composer's settings wore before they became chips. */
#render-request select {
  padding: 4px 8px; border: 1px solid var(--line); border-radius: 7px;
  background: var(--bg); color: var(--ink); font: inherit; font-size: 12.5px; cursor: pointer;
}
#render-request select:focus { outline: none; border-color: var(--accent-text); }
#render-request select:disabled { opacity: .55; cursor: default; }

/* ---- AI render cards (in the transcript) ---- */
/* One grid per run of consecutive renders, so a multi-view request reads as one set. auto-fill against the pane
   width: two-up on a typical chat pane, one-up when the pane is dragged narrow - never a postage stamp. */
.renders {
  align-self: stretch; display: grid; gap: 10px; padding: 0 2px;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
}
.render-card { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
/* The frame is a real <button> so the thumbnail is keyboard-reachable; it is disabled until the image exists. */
.render-frame {
  position: relative; display: block; width: 100%; aspect-ratio: 4 / 3; padding: 0; margin: 0; overflow: hidden;
  border: 1px solid var(--line); border-radius: 10px; background: var(--panel-2); color: var(--muted);
  font: inherit; cursor: pointer; text-align: center;
  transition: border-color .15s ease;
}
.render-frame:hover:not(:disabled), .render-frame:focus-visible { border-color: var(--accent-text); outline: none; }
.render-frame:disabled { cursor: default; }
.render-frame img, .render-frame video { display: block; width: 100%; height: 100%; object-fit: cover; }
/* Video cards: the first frame with a play badge and the clip length, so a clip is told apart from a still at a glance. */
.render-play { position: absolute; inset: 0; display: grid; place-items: center; pointer-events: none; }
.render-play span {
  width: 44px; height: 44px; display: grid; place-items: center; border-radius: 50%;
  background: rgba(0, 0, 0, .55); color: #fff; box-shadow: 0 2px 10px rgba(0, 0, 0, .35);
}
.render-play svg { width: 18px; height: 18px; fill: currentColor; margin-left: 2px; }
.render-duration {
  position: absolute; right: 8px; bottom: 8px; padding: 1px 6px; border-radius: 6px; pointer-events: none;
  background: rgba(0, 0, 0, .6); color: #fff; font-size: 11px; font-variant-numeric: tabular-nums;
}
.render-placeholder {
  position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 8px; padding: 12px; font-size: 12.5px; line-height: 1.35;
}
.render-placeholder .spinner { width: 22px; height: 22px; border-width: 2px; }
.render-placeholder .detail { font-size: 11.5px; opacity: .8; max-height: 4.2em; overflow: hidden; }
.render-card.failed .render-frame, .render-card.interrupted .render-frame { color: var(--danger); }
.render-caption { display: flex; align-items: center; gap: 6px; padding: 0 2px; font-size: 12px; color: var(--muted); }
/* An idea (purpose Explore; design canvas page 34): its number on the picture, the badge the video bar gives its frames, and its
   name as the caption's first line in ink, the quality and time (or what it came from) under it; a failed one keeps its number. */
.render-option-n { position: absolute; left: 6px; top: 6px; min-width: 18px; height: 18px; padding: 0 5px; display: inline-flex; align-items: center; justify-content: center; border-radius: 4px; background: var(--accent); color: var(--accent-ink); font-size: 11px; font-weight: 700; pointer-events: none; }
.render-caption.is-idea { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; row-gap: 1px; }
.render-caption.is-idea .render-caption-text { grid-column: 1 / -1; color: var(--ink); font-size: 12.5px; }
.render-caption-meta { min-width: 0; font-size: 11.5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.render-card.failed .render-caption-meta, .render-card.interrupted .render-caption-meta { color: var(--danger); }
.render-caption-text { flex: 1 1 auto; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Retry for one failed image or clip (app.js mediaRetryButton), at the caption's end like the share glyph; the viewer's
   header carries the same word as a hairline action while the open original is unavailable. */
.render-caption .render-retry { flex: 0 0 auto; margin-left: auto; border: 0; padding: 0 2px; background: transparent; color: var(--accent-text); font: inherit; font-size: 12px; cursor: pointer; }
.render-caption .render-retry:hover, .render-caption .render-retry:focus-visible { text-decoration: underline; outline: none; }
.viewer-retry.viewer-action { width: auto; padding: 0 10px; font-size: 12px; }
/* Build in 3D: the viewer's one action for an idea, a filled word button among the hairline glyphs; greyed where the scene
   cannot be edited, and "Open its chat" (hairline) for another chat's idea from the Media library. A flex row, not the
   glyph buttons' one-cell grid: that would stack the cube over the words and overflow the 32 px box. */
.viewer-action.viewer-build { display: inline-flex; align-items: center; justify-content: center; width: auto; padding: 0 12px; gap: 6px; white-space: nowrap; border-color: var(--accent); background: var(--accent); color: var(--accent-ink); font-size: 12.5px; font-weight: 600; }
.viewer-action.viewer-build svg { width: 14px; height: 14px; }
.viewer-action.viewer-build:hover:not(:disabled) { filter: brightness(1.06); }
.viewer-action.viewer-build:disabled { opacity: .5; cursor: default; }
.viewer-action.viewer-build[data-mode="open"] { border-color: var(--line); background: var(--panel-2); color: var(--ink); font-weight: 500; }

/* ---- AI render viewer (modal over the scene pane) ---- */
/* Same chrome as the rest of the shell: panel surface, hairline border, slightly rounded corners. Sits inside
   #scene so it covers the Arkio canvas only and the chat stays readable beside it. z-index clears #loading. */
#render-viewer {
  position: absolute; inset: 0; z-index: 5; display: grid; place-items: center; padding: 24px;
  background: rgba(4, 8, 6, .72); backdrop-filter: blur(3px);
}
#render-viewer[hidden] { display: none; }
#render-viewer-panel {
  display: flex; flex-direction: column; width: min(100%, 1400px); max-height: 100%;
  background: var(--panel); color: var(--ink); border: 1px solid var(--line); border-radius: 12px;
  box-shadow: 0 24px 64px rgba(0, 0, 0, .5); overflow: hidden;
}
#render-viewer-header {
  display: flex; align-items: center; gap: 10px; padding: 12px 12px 12px 18px;
  border-bottom: 1px solid var(--line); font-weight: 600; font-size: 14px; letter-spacing: .01em;
}
#render-viewer-count { color: var(--muted); font-weight: 400; font-size: 12.5px; }
#render-viewer-actions { margin-left: auto; display: flex; gap: 10px; }
.viewer-action {
  flex: 0 0 auto; width: 32px; height: 32px; display: grid; place-items: center; padding: 0;
  border: 1px solid var(--line); border-radius: 8px; background: var(--panel-2); color: var(--ink);
  font: inherit; font-size: 14px; line-height: 1; text-decoration: none; cursor: pointer;
  transition: border-color .15s ease;
}
.viewer-action[hidden] { display: none; }
.viewer-action:hover, .viewer-action:focus-visible { border-color: var(--accent-text); outline: none; }
#render-viewer-stage {
  position: relative; flex: 1 1 auto; min-height: 120px; display: grid; place-items: center; background: var(--bg);
}
/* Bounded by a measured height rather than the panel: a grid cell with an indefinite height cannot cap an image's
   max-height reliably. --viewer-stage-max is the stage's room as app.js measures it (the viewer's box less its
   padding, header and footer); the stage clips so nothing can paint over the footer either way. */
#render-viewer-stage { min-height: 0; overflow: hidden; }
#render-viewer-img { display: block; max-width: 100%; max-height: var(--viewer-stage-max, calc(var(--app-height) - 278px)); object-fit: contain; }
#render-viewer-img[hidden] { display: none; }
/* Video mode: the clip plus a small custom control bar. Native controls were dropped so the bar matches the shell and
   so the defaults are ours (muted on open, Space/M keys). The player shares the stage with the image and only one of
   them is visible at a time. */
#render-viewer-player { position: relative; display: flex; flex-direction: column; width: min(100%, 1280px); max-height: var(--viewer-stage-max, calc(var(--app-height) - 278px)); }
#render-viewer-player[hidden] { display: none; }
/* The player's pause for data, over the picture: not the download, which the header names while the stage is empty. */
#video-buffering { position: absolute; left: 50%; top: calc(50% - 24px); transform: translate(-50%, -50%); display: inline-flex; align-items: center; gap: 8px; padding: 6px 12px; border-radius: 999px; background: rgba(21, 32, 33, .72); color: #fff; font-size: 12px; pointer-events: none; }
#video-buffering[hidden] { display: none; }
#video-buffering .spinner { width: 14px; height: 14px; border-width: 2px; }
#render-viewer-video { display: block; width: 100%; max-height: calc(var(--viewer-stage-max, calc(var(--app-height) - 278px)) - 50px); background: #000; object-fit: contain; cursor: pointer; } /* less the control bar */
#video-controls {
  display: flex; align-items: center; gap: 10px; padding: 8px 10px;
  background: var(--panel); border-top: 1px solid var(--line);
}
#video-controls button {
  flex: 0 0 auto; width: 32px; height: 32px; display: grid; place-items: center; padding: 0;
  border: 1px solid var(--line); border-radius: 8px; background: var(--panel-2); color: var(--ink);
  font: inherit; cursor: pointer; transition: border-color .15s ease;
}
#video-controls button:hover, #video-controls button:focus-visible { border-color: var(--accent-text); outline: none; }
#video-controls button svg { width: 16px; height: 16px; fill: currentColor; }
#video-seek { flex: 1 1 auto; min-width: 60px; margin: 0; accent-color: var(--range-accent); cursor: pointer; }
#video-time, #video-duration { flex: 0 0 auto; min-width: 3.6ch; font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; }
#video-duration { text-align: right; }

/* ---- tutorial highlight over the shell ---- */
/* Body-level so the scene cannot clip toolbar/drawer anchors; ordinary popup menus stay above it (z 20+).
   The SVG is inert to the pointer; only the label and its Dismiss take clicks. */
#tutorial-overlay { position: fixed; inset: 0; z-index: 10; pointer-events: none; }
#tutorial-overlay[hidden] { display: none; }
#tutorial-svg { display: block; width: 100%; height: 100%; }
#tutorial-dim { fill: none; } /* Keep the scene readable while the animated boundary teaches a control. */
/* CreateViz cage green distinguishes the instruction target from teal selected tools. */
#tutorial-ring, .tutorial-extra-ring { fill: none; stroke: #339926; stroke-width: 3; animation: tutorial-pulse 1.6s ease-in-out infinite; }
@keyframes tutorial-pulse { 0%, 100% { stroke-opacity: .55; } 50% { stroke-opacity: 1; } }
@media (prefers-reduced-motion: reduce) { #tutorial-ring, .tutorial-extra-ring { animation: none; } }
#tutorial-label {
  position: absolute; left: 8px; top: 8px; pointer-events: auto; display: flex; align-items: center; gap: 10px;
  max-width: min(340px, calc(100vw - 16px)); padding: 8px 8px 8px 12px; background: var(--panel); color: var(--ink);
  border: 1px solid var(--accent-text); border-radius: 10px; font-size: 13.5px; line-height: 1.35;
  box-shadow: 0 12px 32px rgba(0, 0, 0, .45);
}
#tutorial-dismiss {
  flex: 0 0 auto; padding: 4px 9px; border: 1px solid var(--line); border-radius: 7px; background: var(--panel-2);
  color: var(--muted); font: inherit; font-size: 12px; cursor: pointer; transition: border-color .15s ease, color .15s ease;
}
#tutorial-dismiss:hover, #tutorial-dismiss:focus-visible { border-color: var(--accent-text); color: var(--ink); outline: none; }
.viewer-nav {
  position: absolute; top: 50%; transform: translateY(-50%); width: 40px; height: 56px;
  display: grid; place-items: center; padding: 0 0 4px;
  border: 1px solid var(--line); border-radius: 10px;
  background: color-mix(in srgb, var(--panel) 88%, transparent); color: var(--ink);
  font: inherit; font-size: 28px; line-height: 1; cursor: pointer;
  transition: border-color .15s ease, opacity .15s ease;
}
.viewer-nav:hover:not(:disabled), .viewer-nav:focus-visible { border-color: var(--accent-text); outline: none; }
.viewer-nav:disabled { opacity: .3; cursor: default; }
#render-prev { left: 12px; }
#render-next { right: 12px; }
#render-viewer-footer { padding: 10px 18px 14px; border-top: 1px solid var(--line); }
#render-viewer-caption { font-size: 12.5px; color: var(--muted); }
#render-viewer-desc {
  margin-top: 4px; font-size: 13px; color: var(--ink); line-height: 1.4;
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;
}
#render-viewer-desc:empty { display: none; }

/* ---- attachments (files staged for the next message) ---- */
/* The paperclip (#attach) in the composer row and the chips above the input are the group composer's: their rules sit
   with the group chat's at the end of this file (#attach, #group-attach; .gc-chip). A refused pick is one line below. */
#attachments { display: flex; flex-wrap: wrap; gap: 6px; }
#reference-chip { display: flex; flex-wrap: wrap; gap: 6px; }
#reference-chip[hidden] { display: none; }
#attachments[hidden] { display: none; }
/* Keep every staged file reachable without letting a large image batch displace the prompt or Send. */
#attachments, .gc-staged { max-height: min(132px, 18dvh); overflow-y: auto; overscroll-behavior-y: contain; }
.attachment-note { flex-basis: 100%; color: var(--danger); font-size: 12px; }
/* The render request bar over the chips (render-chip.js; the camera #render-btn in the composer row wears the paperclip's
   chrome, below with it, and hides while the bar is up). It spans the composer like the voice bar and borrows its parts
   from elsewhere in the shell: the Review tab's strip for Render | Video (.rv-strip .sh-seg) and the composer options'
   selects for what to render, the style, the count and the length (their lists follow the theme through the root's
   color-scheme, as every native control does). Its own rules are the layout, the frame tiles a video is cut from, and
   the note. */
#render-request { position: relative; display: flex; flex-direction: column; }
#render-request[hidden] { display: none; }
.rr-bar { display: flex; align-items: flex-start; gap: 10px; padding: 8px; border: 1px solid var(--line); border-radius: 10px; background: var(--panel); color: var(--ink); font-size: 12px; }
.rr-main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 6px; }
#render-request select { background: var(--panel); } /* the bar's surface, as the chip beside them shows it; the options row below sits on --panel-2 */
.rr-row { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.rr-kind { flex: 0 0 auto; }
/* the id outranks the strip's and the share sheet's own sizes: 28px, the selects' height, for every opener in the bar */
#render-request .rr-kind button { flex: 0 0 auto; height: 22px; padding: 0 10px; }
#render-request .rr-kind button:disabled { cursor: default; }
.rr-field { display: inline-flex; min-width: 0; }
#render-request select { max-width: 100%; }
.rr-frames { display: flex; flex-wrap: wrap; gap: 6px; }
.rr-frame { position: relative; width: 64px; height: 40px; padding: 0; display: grid; place-items: center; border: 1px solid var(--line); border-radius: 6px; background: var(--panel-2); color: var(--accent-text); overflow: hidden; cursor: pointer; }
.rr-frame img { display: block; width: 100%; height: 100%; object-fit: cover; }
.rr-frame svg { width: 16px; height: 16px; }
.rr-frame:hover:not(:disabled), .rr-frame:focus-visible { border-color: var(--accent-text); outline: none; }
.rr-frame[aria-pressed="true"] { border-color: var(--accent-text); box-shadow: inset 0 0 0 1px var(--accent-text); } /* the library tile's selected ring */
.rr-frame:disabled { cursor: default; opacity: .6; }
.rr-frame-n { position: absolute; left: 3px; top: 3px; min-width: 16px; height: 16px; padding: 0 4px; display: inline-flex; align-items: center; justify-content: center; border-radius: 4px; background: var(--accent); color: var(--accent-ink); font-size: 10px; font-weight: 700; pointer-events: none; }
.rr-note { margin: 0; font-size: 11.5px; line-height: 1.35; color: var(--muted); }
.rr-note.is-warn { color: var(--danger); }
.rr-remove { margin-top: 3px; } /* centred on the first row's 28px controls */

/* Local/dev conversation export stays available during generation; release hosts hide the shortcut and its toggle. */
#save-conversation { flex: 0 0 auto; }
#save-conversation[hidden], #show-save-conversation-field[hidden] { display: none; }
#save-conversation:disabled { cursor: wait; }
/* The header action: one small hairline button for every pane header (Save conversation, the scene actions,
   the Live render pane's Start/Stop). A toggle carries aria-pressed and borrows the accent while on, so its active
   state is legible from the button. */
.header-btn {
  flex-shrink: 0; padding: 5px 8px; border: 1px solid var(--line); border-radius: 5px;
  background: transparent; color: var(--ink); font: inherit; font-size: 11px; cursor: pointer;
  transition: border-color .15s ease, background .15s ease;
}
.header-btn:hover:not(:disabled), .header-btn:focus-visible { border-color: var(--accent-text); outline: none; }
.header-btn:disabled { opacity: .5; cursor: default; }
.header-btn[aria-pressed="true"] { border-color: var(--accent-text); background: var(--accent-soft); }
#diagnostic-status { padding: 0 16px 8px; font-size: 12px; color: var(--muted); }
#session-open-error { flex: 0 0 auto; margin: 0 16px 8px; padding: 8px; border: 1px solid var(--amber); border-radius: 6px; font-size: 12px; line-height: 1.4; overflow-wrap: anywhere; }
#session-open-error[hidden] { display: none; }
/* The cloud card (canvas page 31): a raised card like the share and history cards (.sh-card), a heading, one sentence
   and the choice as two of the shell's bordered buttons (.header-btn's idiom), the action first. The cards' gray, no
   warning colour: the words say what is at stake, and the glyph and the words stay in the ink. It sits where the
   opening alert sits, above the messages. */
#cloud-card { flex: 0 0 auto; display: flex; flex-direction: column; gap: 6px; margin: 12px 16px 8px; padding: 12px 14px; border: 1px solid var(--line); border-radius: 10px; background: var(--panel-2); color: var(--ink); font-size: 12.5px; line-height: 1.45; overflow-wrap: anywhere; }
#cloud-card[hidden] { display: none; }
.cloud-card-head { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; }
.cloud-card-head svg { flex: none; color: inherit; }
.cloud-card-text { color: var(--muted); }
.cloud-card-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 4px; }
.cloud-card-go, .cloud-card-later {
  height: 30px; padding: 0 12px; border: 1px solid var(--line); border-radius: 8px; background: var(--panel); color: var(--ink);
  font: inherit; font-size: 12.5px; font-weight: 600; white-space: nowrap; cursor: pointer; transition: border-color .15s ease;
}
.cloud-card-go { border-color: var(--accent-text); }
.cloud-card-later { font-weight: 400; color: var(--muted); }
.cloud-card-go:hover, .cloud-card-go:focus-visible, .cloud-card-later:hover, .cloud-card-later:focus-visible { border-color: var(--accent-text); color: var(--ink); outline: none; }
/* A chat whose work is not in the cloud (a conflict waiting for its decision) carries the mark on its row and card. */
.session-cloud-off { flex: none; display: inline-flex; color: var(--muted); }
.lib-card .session-cloud-off { position: absolute; left: 5px; bottom: 5px; padding: 3px; border-radius: 4px; background: rgba(21, 32, 33, .72); }

/* A chat reviewed from another tab must never expose this instance’s unrelated editable canvas. */
#session-state { position: absolute; inset: 0; z-index: 4; background: var(--bg); color: var(--ink); display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 32px; text-align: center; gap: 16px; }
#session-state[hidden] { display: none; }
#session-state p { max-width: 420px; line-height: 1.5; }
/* Same surface as the tool controls, centred over the player. Recovery never covers the chat or drawer. */
#session-state.engine-recovery { inset: 50% auto auto 50%; transform: translate(-50%, -50%); width: min(460px, calc(100% - 32px));
  box-sizing: border-box; padding: 20px; background: var(--panel); border: 1px solid var(--line); border-radius: 9px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, .18); font-size: 13px; gap: 10px; }
#session-state.engine-recovery button { font: inherit; padding: 7px 12px; border: 1px solid var(--line); border-radius: 6px;
  background: var(--panel); color: var(--ink); cursor: pointer; }
#session-state.engine-recovery #restart-engine,
#session-state.engine-recovery #continue-here { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); }
#session-state.engine-recovery #recovery-report-issue { margin-top: 4px; padding: 4px 8px; border-color: transparent;
  background: transparent; color: var(--muted); font-size: 12px; }
#session-state.engine-recovery #recovery-report-issue:hover { color: var(--ink); text-decoration: underline; }
#session-state.engine-recovery button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
#continue-here, #continue-local { border: 1px solid var(--accent); border-radius: 6px; padding: 10px 18px; background: var(--accent); color: var(--accent-ink); cursor: pointer; }
#continue-here:hover, #continue-here:focus-visible { background: var(--accent-hover); border-color: var(--accent-hover); outline: none; }
#continue-local { border-color: var(--line); background: var(--panel); color: var(--ink); } /* the way out beside the primary action is the secondary button */
#continue-local:hover, #continue-local:focus-visible { border-color: var(--accent-text); outline: none; }
.session-open { font-size: 10px; color: var(--muted, #9ca8ae); flex: none; }

/* ---- the side panel and its rail (rightmost) ---- */
/* The rail is the panel's permanent tab strip at the shell's right edge, open or closed, so nothing moves between the
   two states. Its band is level with the other headers and holds the one open/close chevron; the open tab carries
   the toolbar's accent line turned vertical, on the edge that faces the body. The body opens to the rail's left in
   the same flex split as the other panes (divider C resizes it) with a header row for the tab's title and, per
   drawer, a row of icon-only sub-tabs in the Chats / Media / Scenes style. Both hide with display:none so the split
   sees the right number of panes. The look comes from the :root toolbar variables. */
#rail {
  flex: 0 0 var(--rail-w); height: 100%; display: flex; flex-direction: column; align-items: center;
  background: var(--panel); border-left: 1px solid var(--line);
}
#rail-band { flex: 0 0 var(--toolbar-h); width: 100%; display: grid; place-items: center; border-bottom: 1px solid var(--line); }
/* #rail-toggle is a .pane-glyph (collapsible panes): the frame with the panel's column, the arrow in from the edge to
   open it, out to close; app.js setPanel keeps its aria-expanded, title and label. */
#rail-tabs { flex: 1 1 auto; min-height: 0; width: 100%; display: flex; flex-direction: column; align-items: center; gap: 4px; padding: 6px 0 8px; }
.rail-tab {
  width: 100%; height: 36px; display: grid; place-items: center; padding: 0 2px 0 0;
  border: 0; border-left: 3px solid transparent; background: transparent; color: var(--tool-ink-off); cursor: pointer;
  transition: color .15s ease;
}
.rail-tab[aria-pressed="true"] { border-left-color: var(--tool-line); color: var(--tool-ink); }
.rail-tab[hidden] { display: none; } /* license-gated tabs must override the rail's grid display */
.rail-tab:hover, .rail-tab:focus-visible { color: var(--tool-ink); outline: none; }
.rail-foot { margin-top: auto; }
/* The account on the rail's foot while the chats list is folded (design canvas Account on the rail): signed out the
   person glyph in the rail's own grey, signed in the footer's 28 px credits ring with the count inside, amber when low. */
.rail-account {
  width: 100%; height: 36px; display: grid; place-items: center; padding: 0 2px 0 0; border: 0; border-left: 3px solid transparent;
  background: transparent; color: var(--tool-ink-off); cursor: pointer; transition: color .15s ease;
}
/* One face at a time, by the button's data-account (an SVG element pays the hidden property no mind). */
.rail-account[hidden], .rail-account[data-account="in"] .ra-person, .rail-account:not([data-account="in"]) .ra-ring { display: none; }
.rail-account:hover, .rail-account:focus-visible { color: var(--tool-ink); outline: none; }
.ra-ring { position: relative; width: 28px; height: 28px; display: grid; place-items: center; }
.ra-ring svg { position: absolute; inset: 0; width: 28px; height: 28px; transform: rotate(-90deg); }
.ra-track { fill: none; stroke: var(--line); stroke-width: 3; }
.ra-value { fill: none; stroke: var(--accent); stroke-width: 3; stroke-linecap: round; transition: stroke-dasharray .3s ease; }
.ra-count { position: relative; font-size: 9px; font-weight: 600; letter-spacing: -.01em; color: var(--ink); font-variant-numeric: tabular-nums; }
.rail-account[data-low="true"] .ra-value, .rail-account[data-low="empty"] .ra-value { stroke: var(--amber); }
.rail-account[data-low="true"] .ra-count, .rail-account[data-low="empty"] .ra-count { color: var(--amber); }
/* The first foot entry that shows (Debug, the Report flag or Settings) owns the bottom gap; the ones after it sit under it.
   A general sibling, not an adjacent one: a hidden entry between two shown ones must not hand the gap to both. */
.rail-foot:not([hidden]) ~ .rail-foot { margin-top: 0; }
.rail-svg { width: var(--tool-icon); height: var(--tool-icon); }
/* Create and Paint show the current item and material rather than a glyph: a framed tile and a swatch. */
.rail-current { width: 26px; height: 26px; display: grid; place-items: center; border: 1px solid var(--line); border-radius: 6px; background: var(--panel-2); }
.rail-current svg { display: block; }
.rail-swatch { width: 22px; height: 22px; border-radius: 50%; }
#panel {
  height: 100%; min-width: 220px; display: flex; flex-direction: column;
  background: var(--panel); border-left: 1px solid var(--line);
}
#panel[hidden], #divider-c[hidden] { display: none; }
#panel-header {
  flex: 0 0 var(--toolbar-h); display: flex; align-items: center; gap: 8px; padding: 0 18px;
  border-bottom: 1px solid var(--line); font-weight: 600; font-size: 14px; letter-spacing: .01em;
}
.tab-body { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; overflow: hidden auto; }
#panel .tab-body[hidden] { display: none; } /* outranks #debug-body's own display */
.subtabs { flex: 0 0 auto; display: flex; padding: 0 12px; border-bottom: 1px solid var(--line); }
.subtab {
  flex: 1 1 0; min-width: 0; height: 40px; display: grid; place-items: center; padding: 0; margin-bottom: -1px;
  border: 0; border-bottom: 2px solid transparent; background: transparent; color: var(--muted); cursor: pointer; transition: color .15s ease;
}
.subtab-svg { width: var(--tool-icon); height: var(--tool-icon); }
.subtab:hover, .subtab:focus-visible { color: var(--ink); outline: none; }
.subtab[aria-selected="true"] { color: var(--ink); border-bottom-color: var(--tool-line); }
.drawer-heading { margin: 14px 18px 0; font-size: 11.5px; font-weight: 600; letter-spacing: .07em; text-transform: uppercase; color: var(--muted); }
/* The Create drawer (library.js): search, the heading row, and tiles that refill as the panel is resized. */
.drawer { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; gap: 12px; padding: 12px 18px 16px; }
.drawer-search { display: flex; align-items: center; gap: 8px; height: 32px; padding: 0 10px; border: 1px solid var(--line); border-radius: 8px; background: var(--bg); color: var(--muted); }
.drawer-search svg { flex: 0 0 auto; width: 14px; height: 14px; }
.drawer-search input { flex: 1 1 auto; min-width: 0; border: 0; padding: 0; background: transparent; color: var(--ink); font: inherit; font-size: 12.5px; outline: none; }
.drawer-search input::placeholder { color: var(--muted); }
.drawer-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-height: 24px; }
.drawer-head .drawer-heading { margin: 0; }
.drawer-count { font-size: 11.5px; color: var(--muted); }
.tile-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(84px, 1fr)); gap: 12px 8px; }
.tile {
  display: flex; flex-direction: column; align-items: center; gap: 5px; min-width: 0; padding: 0; border: 0; background: transparent;
  color: var(--muted); font: inherit; font-size: 11.5px; line-height: 1.3; cursor: pointer;
}
.tile-thumb { width: 84px; height: 84px; display: grid; place-items: center; border-radius: 10px; background: var(--panel-2); transition: background .15s ease; }
.tile-thumb svg { display: block; overflow: visible; }
.tile:hover .tile-thumb, .tile:focus-visible .tile-thumb { background: color-mix(in srgb, var(--muted) 18%, var(--panel-2)); }
.tile:focus-visible { outline: none; }
.tile[aria-selected="true"] { color: var(--ink); font-weight: 600; }
.tile[aria-selected="true"] .tile-thumb { background: var(--accent-soft); box-shadow: inset 0 0 0 1px var(--accent-text); }
.tile-name { max-width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tile-id { max-width: 100%; font: 10px/1.35 ui-monospace, Consolas, monospace; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } /* debug: source and id */
.drawer-empty { margin: 24px 0; text-align: center; font-size: 12.5px; color: var(--muted); }
/* Colours are discs, Arkio's own convention, six to a row; selected takes the accent ring with a gap of panel colour so it
   holds on dark colours. Materials keep the tile. The rail's Paint entry is a disc too, so it never reads as a primitive. */
.tile-grid.swatch-grid { grid-template-columns: repeat(auto-fill, 32px); justify-content: space-between; gap: 10px; }
.swatch { width: 32px; height: 32px; padding: 0; border: 0; border-radius: 50%; cursor: pointer; box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .14); transition: transform .12s ease, box-shadow .12s ease; }
.swatch:hover, .swatch:focus-visible { transform: scale(1.12); outline: none; }
.swatch[aria-selected="true"] { box-shadow: 0 0 0 2px var(--panel), 0 0 0 4px var(--accent); }
.disc { display: block; border-radius: 50%; box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .14); }
.rail-swatch { overflow: hidden; background: none; box-shadow: none; }
.rail-swatch .disc, .rail-swatch img { width: 22px; height: 22px; display: block; border-radius: 50%; }
.rail-swatch img { box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .14); }
#debug-body { flex: 1 1 auto; overflow-y: auto; padding: 16px 18px; display: flex; flex-direction: column; gap: 4px; }
/* Native details own folding and keyboard access. Scope the arrow to category headers so nested diagnostics
   retain their own disclosure markers; expanding a category never changes the settings it contains. */
.debug-section { flex: 0 0 auto; }
.debug-section[open] { padding-bottom: 12px; }
.debug-section > summary {
  display: flex; align-items: center; gap: 10px; padding: 10px 0; list-style: none; cursor: pointer; color: var(--muted);
}
.debug-section > summary::-webkit-details-marker { display: none; }
.debug-section > summary::before {
  content: ''; flex: 0 0 auto; width: 6px; height: 6px; margin: 0 2px;
  border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor; transform: rotate(-45deg);
}
.debug-section[open] > summary::before { transform: rotate(45deg); }
.debug-section > summary:hover { color: var(--ink); }
.debug-section > summary:focus-visible { outline: 2px solid var(--accent-text); outline-offset: 2px; border-radius: 3px; }
.debug-section > summary > h2 {
  margin: 0; font-size: 11.5px; font-weight: 600; letter-spacing: .07em; text-transform: uppercase; color: inherit;
}
/* Big tabular figures so a changing fps does not make the row jitter, with the unit underneath in the muted ink. */
.debug-stats { display: flex; flex-wrap: wrap; gap: 10px 22px; } .debug-mem { margin-top: 14px; }
.debug-stat { display: flex; flex-direction: column; min-width: 64px; }
.debug-stat-value { font-size: 26px; font-weight: 600; line-height: 1.15; color: var(--ink); font-variant-numeric: tabular-nums; }
.debug-stat-label { font-size: 11.5px; color: var(--muted); white-space: nowrap; }
/* Frame-time graph: one point per frame, newest at the right, 60 and 30 fps guide lines (drawn by app.js). The CSS
   height is the whole size contract; app.js sizes the backing store from it at devicePixelRatio. */
#debug-frame-graph {
  display: block; width: 100%; height: 64px; margin-top: 12px;
  border: 1px solid var(--line); border-radius: 8px; background: var(--bg);
}
.debug-note { margin-top: 8px; font-size: 12px; line-height: 1.4; color: var(--muted); }
/* Commands keep a usable input in the narrow drawer; long replies wrap inside a bounded, scrollable transcript. */
.debug-console-entry { display: flex; gap: 8px; margin-top: 6px; }
#debug-console-input {
  flex: 1; min-width: 0; width: 0; padding: 7px 8px; border: 1px solid var(--line); border-radius: 7px;
  background: var(--bg); color: var(--ink); font: 12px/1.4 ui-monospace, Consolas, monospace;
}
#debug-console-input:focus { outline: none; border-color: var(--accent-text); }
#debug-console-output {
  max-height: 200px; overflow: auto; white-space: pre-wrap; overflow-wrap: anywhere; padding: 8px;
  border: 1px solid var(--line); border-radius: 7px; background: var(--bg); color: var(--ink);
  font: 12px/1.4 ui-monospace, Consolas, monospace;
}
#debug-console-clear { margin-top: 8px; }
/* Raw logging config stays readable in the narrow developer drawer and can grow vertically. */
#debug-log-config-text {
  display: block; width: 100%; box-sizing: border-box; resize: vertical; margin-top: 6px; padding: 8px;
  border: 1px solid var(--line); border-radius: 7px; background: var(--bg); color: var(--ink);
  font: 12px/1.4 ui-monospace, Consolas, monospace;
}
#debug-log-config-text:focus { outline: none; border-color: var(--accent-text); }
#debug-log-config-save { margin-top: 8px; }
/* Move gizmo switches (app.js "move gizmo experiments"): one labelled control per row, label left and control right;
   ranges carry their value beside them and the selects borrow the options-row look. */
.debug-intro { margin: 0 0 4px; }
.debug-field { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-top: 8px; font-size: 12.5px; color: var(--ink); }
.debug-field:not(.debug-check) { white-space: nowrap; } /* "Ring radius" stays on one line; the slider gives way instead */
/* File categories can be long; keep the diagnostic values aligned without widening the drawer. */
.storage-report .debug-field { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); align-items: start; white-space: normal; }
.storage-report .debug-field > :last-child { text-align: right; font-variant-numeric: tabular-nums; }
.debug-field select {
  font: inherit; font-size: 12.5px; padding: 4px 8px; border: 1px solid var(--line); border-radius: 7px;
  background: var(--bg); color: var(--ink); cursor: pointer;
}
.debug-field select:focus { outline: none; border-color: var(--accent-text); }
.debug-range { display: flex; align-items: center; gap: 8px; flex: 0 1 60%; }
.debug-range input[type=range] { flex: 1 1 auto; min-width: 0; accent-color: var(--range-accent); margin: 0; }
.debug-value { min-width: 3.2em; text-align: right; font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; }
/* Give fine budget adjustments the drawer's full width, including at its narrowest size. */
#debug-hlod-budgets .debug-field { display: block; }
#debug-hlod-budgets .debug-range { margin-top: 4px; }
#debug-hlod-budgets .debug-value { min-width: 5.5em; }
.debug-check { justify-content: flex-start; gap: 8px; cursor: pointer; }
.debug-check input[type=checkbox] { accent-color: var(--accent); margin: 0; }

/* ---- scene header (the player's toolbar) and body ---- */
/* The scene pane is a column: its header, then #scene-body with everything else. The header is the player's toolbar,
   standing in for Arkio's VRLess toolbar that the Web build hides: undo/redo left, the palette centred over the player,
   the scene's switches right. Its look is set once in the :root toolbar variables. The palette is centred by absolute
   positioning and falls back into the row on a narrow pane, where centring would run it into the actions. #scene-body
   is the box the overlays (#session-state, #loading, #render-viewer) cover and the live divider splits. */
#scene { display: flex; flex-direction: column; }
#scene-header {
  flex: 0 0 auto; min-height: var(--toolbar-h); position: relative; container-type: inline-size;
  display: flex; flex-wrap: wrap; align-items: center; gap: 0 8px; padding: 0 12px; /* one row of --toolbar-h until the narrow rule below makes the palette a second; no row gap, the rows meet at a hairline */
  border-bottom: 1px solid var(--line); background: var(--panel); color: var(--ink);
}
.tool-group { display: flex; align-items: stretch; gap: 2px; }
/* The palette sits over the header's centre as long as it can (Embla, 2026-10-13, design canvas, Arkio Web top bar,
   narrow). The steps, by the mode, since the row holds neither history nor the edit tools while Viewing (told apart by
   the hidden history group, app.js renderEditMode): first, where the centred palette would meet the chip, history and
   navigate cluster with its words (1000px Editing, 660px Viewing), the three with words give theirs up: the mode chip
   keeps its glyph and chevron, Follow agent and Live render keep a glyph each in the same pill, 32px wide, the titles
   naming them; that cluster is then about 290px, so the palette stays centred another 100px; where it would meet it
   again (900px Editing, 550px Viewing) the palette moves to the right beside the switches. bottom / margin-bottom -1px:
   the group reaches over the header's hairline, so the active tool's line covers it. */
#tools { position: absolute; left: 50%; top: 0; bottom: -1px; transform: translateX(-50%); }
@container (max-width: 1000px) {
  #scene-header:not(:has(#history[hidden])) #edit-mode-btn .em-text { display: none; }
  #scene-header:not(:has(#history[hidden])) #scene-actions .mode-toggle { width: 32px; padding: 0; display: inline-flex; align-items: center; justify-content: center; }
  #scene-header:not(:has(#history[hidden])) #scene-actions .mt-text { display: none; }
  #scene-header:not(:has(#history[hidden])) #scene-actions .mode-toggle .mt-glyph { display: block; } /* outranks the wide rule below, which comes later */
}
@container (max-width: 900px) {
  #scene-header:not(:has(#history[hidden])) #tools { position: static; transform: none; align-self: stretch; margin: 0 4px -1px auto; }
  #scene-header:not(:has(#history[hidden])) #scene-actions { margin-left: 0; } /* the palette's auto margin pushes right; two would split the space */
}
@container (max-width: 660px) {
  #scene-header:has(#history[hidden]) #edit-mode-btn .em-text { display: none; }
  #scene-header:has(#history[hidden]) #scene-actions .mode-toggle { width: 32px; padding: 0; display: inline-flex; align-items: center; justify-content: center; }
  #scene-header:has(#history[hidden]) #scene-actions .mt-text { display: none; }
  #scene-header:has(#history[hidden]) #scene-actions .mode-toggle .mt-glyph { display: block; }
}
@container (max-width: 550px) {
  #scene-header:has(#history[hidden]) #tools { position: static; transform: none; align-self: stretch; margin: 0 4px -1px auto; }
  #scene-header:has(#history[hidden]) #scene-actions { margin-left: 0; }
}
/* Under 670px (the one row with its words gone needs 667px) the row would overflow, so the header becomes two rows,
   each 40px rather than the single row's 48 so the pair costs 80px of the player, not 96: the chip, history, navigate
   and the two switches on the first, the palette alone on a second strip the whole header wide, set to the right under
   the switches (4px of padding, so the last glyph's edge, 8px inside its 36px cell, meets the switches' edge at the
   header's 12px; Embla, 2026-10-14), behind a hairline (the header wraps; a query cannot style its own container, so that is in its base
   rule). Navigate reaches one pixel over that hairline so its active line lies on it, as the palette's lies on the
   header's edge. The first row needs about 370px, so a phone held upright still fits. The widths are the container's
   content box, 24px less than the header. */
@container (max-width: 670px) {
  #scene-header:not(:has(#history[hidden])) #edit-mode-sep { display: none; } /* the chip is a pill already; its hairline's 9px are what a 375px phone lacks */
  #scene-header:not(:has(#history[hidden])) #navigate { height: 41px; margin-bottom: -1px; position: relative; z-index: 1; }
  #scene-header:not(:has(#history[hidden])) #tools { order: 1; flex: 1 0 calc(100% + 24px); height: 40px; margin: 0 -12px -1px; padding-right: 4px; justify-content: flex-end; border-top: 1px solid var(--line); }
  #scene-header:not(:has(#history[hidden])) #scene-actions { margin-left: auto; }
}
/* While Viewing, undo, redo and the five edit tools are gone (history is hidden exactly then, app.js renderEditMode),
   so the one row needs only about 395px and wraps under 400px, the same way. */
@container (max-width: 400px) {
  #scene-header:has(#history[hidden]) #edit-mode-sep { display: none; }
  #scene-header:has(#history[hidden]) #navigate { height: 41px; margin-bottom: -1px; position: relative; z-index: 1; }
  #scene-header:has(#history[hidden]) #tools { order: 1; flex: 1 0 calc(100% + 24px); height: 40px; margin: 0 -12px -1px; padding-right: 4px; justify-content: flex-end; border-top: 1px solid var(--line); }
  #scene-header:has(#history[hidden]) #scene-actions { margin-left: auto; }
}
/* Under 350px the first row (about 351px with everything) would push the two switches onto a row of their own, so its
   buttons sit tighter instead, as the rail's do on a short window: history's and navigate's cells 26px wide (the glyph
   stays 20px), no gap between them, and no hairline between history and navigate. That frees 69px, so a phone held
   upright (375px, the scene pane 327px) and the scene pane at its 320px floor keep every control, Front view and its
   menu included, on the row. */
@container (max-width: 350px) {
  #history, #navigate { gap: 0; }
  #history .tool, #navigate .tool { width: 26px; }
  #navigate .tool-chevron { width: 16px; }
  #history-sep { display: none; }
}
/* While the chat is under the player and the chats list is folded, the list's way back stands in the row too (app.js
   applyPaneChrome: #list-open, 28px less its 4px pull, and a gap), so every step above comes 32px sooner, or the row
   overflows at the old widths and wraps the two switches, the row's last items, under it with the palette still on
   the first (Embla, 2026-10-14). The same rules at the shifted widths: the strip at 702px Editing and 430px Viewing, the
   tight row under 386px, and under 300px, where the scene pane is at its 320px floor and the tight row (314px) is
   still 18px over, the row's gaps halve. The :has() outranks the plain rules, so these win where both match. */
@container (max-width: 702px) {
  #scene-header:has(> #list-open:not([hidden])):not(:has(#history[hidden])) #edit-mode-sep { display: none; }
  #scene-header:has(> #list-open:not([hidden])):not(:has(#history[hidden])) #navigate { height: 41px; margin-bottom: -1px; position: relative; z-index: 1; }
  #scene-header:has(> #list-open:not([hidden])):not(:has(#history[hidden])) #tools { order: 1; flex: 1 0 calc(100% + 24px); height: 40px; margin: 0 -12px -1px; padding-right: 4px; justify-content: flex-end; border-top: 1px solid var(--line); }
  #scene-header:has(> #list-open:not([hidden])):not(:has(#history[hidden])) #scene-actions { margin-left: auto; }
}
@container (max-width: 430px) {
  #scene-header:has(> #list-open:not([hidden])):has(#history[hidden]) #edit-mode-sep { display: none; }
  #scene-header:has(> #list-open:not([hidden])):has(#history[hidden]) #navigate { height: 41px; margin-bottom: -1px; position: relative; z-index: 1; }
  #scene-header:has(> #list-open:not([hidden])):has(#history[hidden]) #tools { order: 1; flex: 1 0 calc(100% + 24px); height: 40px; margin: 0 -12px -1px; padding-right: 4px; justify-content: flex-end; border-top: 1px solid var(--line); }
  #scene-header:has(> #list-open:not([hidden])):has(#history[hidden]) #scene-actions { margin-left: auto; }
}
@container (max-width: 386px) {
  #scene-header:has(> #list-open:not([hidden])) #history, #scene-header:has(> #list-open:not([hidden])) #navigate { gap: 0; }
  #scene-header:has(> #list-open:not([hidden])) #history .tool, #scene-header:has(> #list-open:not([hidden])) #navigate .tool { width: 26px; }
  #scene-header:has(> #list-open:not([hidden])) #navigate .tool-chevron { width: 16px; }
  #scene-header:has(> #list-open:not([hidden])) #history-sep { display: none; }
}
@container (max-width: 300px) {
  #scene-header:has(> #list-open:not([hidden])) > * + * { margin-left: -4px; } /* halves the 8px gap: a query cannot set its own container's gap */
}
/* A tool is a plain glyph on the header, as tall as the header so the active line lies on its bottom edge. Clicking the
   active tool deselects it, as in Arkio. */
.tool {
  width: var(--tool-w); height: 100%; display: grid; place-items: center; padding: 0;
  border: 0; border-bottom: 3px solid transparent; background: transparent; color: var(--tool-ink); cursor: pointer;
  transition: color .15s ease;
}
.tool[aria-pressed="true"] { border-bottom-color: var(--tool-line); }
.tool:hover:not(:disabled), .tool:focus-visible { color: var(--accent-text); outline: none; }
.tool:disabled { color: var(--tool-ink-off); cursor: default; }
#history .tool { height: 30px; border-bottom: 0; border-radius: 6px; }
/* Navigate (Orbit, Walk) stands beside history behind a hairline. Like #tools it reaches over the header's hairline so
   its active line lies on the header's bottom edge; being in the row rather than centred, it stretches itself. */
.tool-sep { flex: 0 0 1px; width: 1px; height: 20px; background: var(--line); }
#navigate { align-self: stretch; margin-bottom: -1px; }
/* The palette's glyphs are inline SVG (index.html), sized here; the rail and sub-tab glyphs share the size. */
.tool-svg { width: var(--tool-icon); height: var(--tool-icon); }
/* Follow agent and Live render: the scene's two switches, flipped all day, so on and off must read at a glance. On is
   the .header-btn pressed look at this size; the filled accent stays reserved for Send. aria-pressed drives it. */
.mode-toggle {
  height: 28px; padding: 0 12px; /* the height of the composer's chips: one opener height for the shell's dropdowns */ border: 1px solid var(--line); border-radius: 7px; background: transparent;
  color: var(--ink); font: inherit; font-size: 12.5px; font-weight: 600; white-space: nowrap; cursor: pointer;
  transition: border-color .15s ease, background .15s ease, color .15s ease;
}
.mode-toggle:hover:not(:disabled), .mode-toggle:focus-visible { border-color: var(--accent-text); outline: none; }
.mode-toggle:disabled { opacity: .5; cursor: default; }
.mode-toggle[aria-pressed="true"] { border-color: var(--accent-text); background: var(--accent-soft); color: var(--accent-text); }
#scene-actions { margin-left: auto; display: flex; gap: 6px; }
#scene-actions .mt-glyph { display: none; width: 18px; height: 18px; } /* the glyph stands in for the word under 900px only */
#scene-body { position: relative; flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; overflow: hidden; background: #000; }

/* ---- live video (the scene body split: player above, divider, live AI video below) ---- */
/* #scene-body is a column so #scene-view (top) and #live-pane (bottom) share its height; #session-state, #loading
   and #render-viewer are absolutely positioned against it and keep covering both parts. #scene-view is the player's
   box: syncRenderTarget and legacy player-space tutorial pointers measure it, and #unity-canvas fills it. */
#scene-view { position: relative; flex: 1 1 auto; min-height: 0; width: 100%; overflow: hidden; background: #000; }
/* Same chrome as the debug pane (panel surface, hairline header, a status dot); both it and its divider are display:none
   while hidden, so the scene pane sees only the player again. The dot: muted off, amber while connecting/paused,
   accent while streaming, red when stopped by an error. */
#live-pane { width: 100%; min-height: 0; display: flex; flex-direction: column; background: var(--panel); border-top: 1px solid var(--line); }
#live-pane[hidden], #divider-live[hidden] { display: none; }
#live-header { display: flex; flex-direction: column; gap: 8px; padding: 12px 14px; border-bottom: 1px solid var(--line); }
#live-title-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; font-weight: 600; font-size: 14px; letter-spacing: .01em; }
#live-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--muted); flex: 0 0 auto; }
#live-dot[data-state="live"] { background: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 25%, transparent); }
#live-dot[data-state="busy"] { background: var(--amber); }
#live-dot[data-state="error"] { background: var(--danger); }
#live-state { flex: 1 1 auto; min-width: 0; font-weight: 400; font-size: 12.5px; color: var(--muted); }
#live-action, #live-orient {
  flex: 0 0 auto; padding: 5px 10px; border: 1px solid var(--line); border-radius: 7px; background: var(--panel-2);
  color: var(--ink); font: inherit; font-size: 12px; font-weight: 600; cursor: pointer; transition: border-color .15s ease;
}
#live-action:hover, #live-action:focus-visible, #live-orient:hover, #live-orient:focus-visible { border-color: var(--accent-text); outline: none; }
#live-action[hidden], #live-orient[hidden], #live-note[hidden] { display: none; }
/* Two tiles of the .debug-stat family (Cost, Lag), a touch smaller than the debug pane's, then one muted metrics line. */
.live-tiles .debug-stat-value { font-size: 22px; }
.live-metrics { font-size: 12px; line-height: 1.4; color: var(--muted); }
.live-metrics:empty { display: none; }
/* The stream, letterboxed: Lucy returns 1280x720 or 720x1280 whatever the pane's shape. The still (the last frame,
   snapshotted at disconnect) sits over it until the next remote frame arrives. */
#live-stage { position: relative; flex: 1 1 auto; min-height: 0; background: #000; }
#live-out, #live-still { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; display: block; background: #000; }
#live-out[hidden], #live-still[hidden] { display: none; }
#live-capture { position: fixed; left: -20000px; top: 0; width: 8px; height: 8px; pointer-events: none; }
/* The prompt row under the composer: one line (label, text, Apply, Send as typed), the editable prompt in effect, and a
   status/counter foot. Same surface as the composer so it reads as part of it. */
#live-prompt-row { display: flex; flex-direction: column; gap: 6px; padding: 10px 14px 12px; border-top: 1px solid var(--line); background: var(--panel-2); }
#live-prompt-row[hidden] { display: none; }
#live-prompt-line { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; font-size: 12.5px; color: var(--muted); }
.live-prompt-label { letter-spacing: .02em; white-space: nowrap; }
#live-prompt {
  flex: 1 1 160px; min-width: 120px; padding: 6px 10px; border: 1px solid var(--line); border-radius: 8px;
  background: var(--bg); color: var(--ink); font: inherit; font-size: 13px;
}
#live-prompt:focus { outline: none; border-color: var(--accent-text); }
#live-prompt::placeholder { color: var(--muted); }
#live-prompt-apply {
  padding: 5px 10px; border: 1px solid var(--line); border-radius: 7px; background: var(--panel); color: var(--ink);
  font: inherit; font-size: 12.5px; font-weight: 600; cursor: pointer; transition: border-color .15s ease;
}
#live-prompt-apply:hover, #live-prompt-apply:focus-visible { border-color: var(--accent-text); outline: none; }
.live-prompt-raw { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; cursor: pointer; }
.live-prompt-raw input { accent-color: var(--accent); margin: 0; }
#live-prompt-enhanced {
  width: 100%; resize: vertical; min-height: 44px; max-height: 160px; padding: 6px 10px; border: 1px solid var(--line);
  border-radius: 8px; background: var(--bg); color: var(--ink); font: inherit; font-size: 12.5px; line-height: 1.4;
}
#live-prompt-enhanced:focus { outline: none; border-color: var(--accent-text); }
#live-prompt-foot { display: flex; justify-content: space-between; gap: 10px; font-size: 11.5px; color: var(--muted); }

/* Live render shares the player split with video, while keeping still-image status and output separate. Its header is
   the pane-header family in two rows (index.html): the title row with the status dot, the run's current state, the
   interval slider and Start/Stop, then one muted info line. Padding is a touch tighter than the chat and debug headers
   because the image below is what the pane is for. The dot: muted stopped, amber while the agent writes the prompt,
   accent while running, red when a failure stopped the run. */
#live-render-pane { width: 100%; min-height: 0; display: flex; flex-direction: column; background: var(--panel); border-top: 1px solid var(--line); }
#live-render-pane[hidden] { display: none; }
.live-render-header { display: flex; flex-direction: column; gap: 5px; padding: 9px 14px 8px; border-bottom: 1px solid var(--line); }
.live-render-title { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; font-weight: 600; font-size: 14px; letter-spacing: .01em; }
#live-render-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--muted); flex: 0 0 auto; }
#live-render-dot[data-state="live"] { background: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 25%, transparent); }
#live-render-dot[data-state="busy"] { background: var(--amber); }
#live-render-dot[data-state="error"] { background: var(--danger); }
#live-render-state { flex: 1 1 auto; min-width: 0; font-weight: 400; font-size: 12.5px; color: var(--muted); }
.live-render-interval { display: inline-flex; align-items: center; gap: 6px; font-weight: 400; font-size: 11.5px; color: var(--muted); white-space: nowrap; cursor: pointer; }
.live-render-interval input[type=range] { width: 88px; margin: 0; accent-color: var(--range-accent); }
#live-render-interval-value { min-width: 2.6em; text-align: right; font-variant-numeric: tabular-nums; }
.live-render-info { display: flex; flex-wrap: wrap; gap: 2px 14px; font-size: 12px; line-height: 1.4; color: var(--muted); }
.live-render-info b { font-weight: 600; color: var(--ink); font-variant-numeric: tabular-nums; }
.live-render-info span:empty { display: none; }
.live-render-note { font-size: 12px; line-height: 1.4; color: var(--danger); }
.live-render-note:empty { display: none; }
.live-render-stage { flex: 1; position: relative; min-height: 0; display: grid; place-items: center; background: var(--bg); color: var(--muted); font-size: 13px; }
#live-render-image { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; }
#live-render-image[hidden], #live-render-empty[hidden] { display: none; }
#live-render-prompt { width: 100%; background: var(--bg); color: var(--ink); border: 1px solid var(--line); border-radius: 6px; padding: 6px; font: inherit; }
.live-render-details { margin-top: 10px; font-size: 12px; line-height: 1.5; }
.live-render-details summary { cursor: pointer; }
#live-render-prompt { resize: vertical; }
#live-render-source-link { display: block; }
#live-render-source-link[hidden] { display: none; }
#live-render-source-image { display: block; width: 100%; height: auto; border: 1px solid var(--line); border-radius: 6px; }

/* ---- floating Live render (the pane as a window over the player) ---- */
/* data-mode="floating" lifts the pane out of the split: absolutely positioned in #scene-body (live-float.js sets left,
   top, width and height), under the overlays that must keep covering it (#loading z 2, #session-state z 4, the viewer
   z 5). The header collapses to one row - dot, state, Start/Stop, dock - and is the drag handle; the four corners
   resize with the aspect locked. The icon buttons are .header-btn at a square size. */
.header-btn.icon-btn { width: 28px; padding: 0; display: inline-grid; place-items: center; align-self: stretch; }
.header-btn.icon-btn svg { width: 15px; height: 15px; }
#live-render-pane[data-mode="floating"] {
  position: absolute; z-index: 3; width: auto; border: 1px solid var(--line); border-radius: 10px; /* above the joysticks (z 2): a window may sit over them */
  box-shadow: 0 14px 40px rgba(0, 0, 0, .45); overflow: hidden; touch-action: none; cursor: grab; /* the whole window drags */
}
#live-render-pane[data-mode="floating"] .live-render-header { gap: 2px; padding: 6px 12px 5px; user-select: none; -webkit-user-select: none; }
#live-render-pane.dragging, #live-render-pane.dragging * { cursor: grabbing; }
#live-render-pane[data-mode="floating"] .live-render-title { flex-wrap: nowrap; }
#live-render-pane[data-mode="floating"] .header-btn { line-height: 1.25; padding-top: 4px; padding-bottom: 4px; }
#live-render-once[hidden] { display: none; } /* a stream running shows Stop alone */
#live-render-pane[data-mode="floating"] #live-render-title, #live-render-pane[data-mode="floating"] .live-render-interval,
#live-render-pane[data-mode="floating"] .live-render-info, #live-render-pane[data-mode="floating"] #live-render-float { display: none; }
#live-render-pane[data-mode="floating"] #live-render-state { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: var(--ink); font-weight: 500; }
#live-render-pane[data-mode="floating"] .live-render-stage { background: #000; }
#live-render-pane[data-mode="floating"] #live-render-image { pointer-events: none; }
#live-render-pane:not([data-mode="floating"]) #live-render-dock, #live-render-pane:not([data-mode="floating"]) .live-render-corner { display: none; }
/* Resize handles: the bottom corners are 22px squares (nothing else lives there); the top corners are an L along the
   two edges, kept inside the header's padding so the dot and the buttons stay clickable. Each corner shows a tick:
   the lower right always, all four while the pointer is over the window or a gesture is under way. */
.live-render-corner { position: absolute; width: 22px; height: 22px; z-index: 2; }
.live-render-corner[data-corner="nw"] { left: 0; top: 0; cursor: nwse-resize; clip-path: polygon(0 0, 100% 0, 100% 6px, 11px 6px, 11px 100%, 0 100%); }
.live-render-corner[data-corner="ne"] { right: 0; top: 0; cursor: nesw-resize; clip-path: polygon(0 0, 100% 0, 100% 100%, 11px 100%, 11px 6px, 0 6px); }
.live-render-corner[data-corner="sw"] { left: 0; bottom: 0; cursor: nesw-resize; }
.live-render-corner[data-corner="se"] { right: 0; bottom: 0; cursor: nwse-resize; }
.live-render-corner::after { content: ""; position: absolute; width: 8px; height: 8px; border: 0 solid var(--muted); opacity: 0; transition: opacity .15s ease; }
.live-render-corner[data-corner="nw"]::after { left: 4px; top: 4px; border-width: 2px 0 0 2px; }
.live-render-corner[data-corner="ne"]::after { right: 4px; top: 4px; border-width: 2px 2px 0 0; }
.live-render-corner[data-corner="sw"]::after { left: 4px; bottom: 4px; border-width: 0 0 2px 2px; border-color: rgba(255, 255, 255, .75); filter: drop-shadow(0 0 1px rgba(0, 0, 0, .6)); }
.live-render-corner[data-corner="se"]::after { right: 4px; bottom: 4px; border-width: 0 2px 2px 0; border-color: rgba(255, 255, 255, .75); filter: drop-shadow(0 0 1px rgba(0, 0, 0, .6)); opacity: 1; }
#live-render-pane[data-mode="floating"]:hover .live-render-corner::after, #live-render-pane.resizing .live-render-corner::after,
#live-render-pane.dragging .live-render-corner::after { opacity: 1; }

/* ---- virtual joysticks over the player (joysticks.js) ---- */
/* Move at the lower left and Look at the lower right of the player, above the floating Live render window (z 1) and
   under #loading and #session-state. They keep their own inks, white on a dark fill, since the player behind them is dark
   whatever the shell theme, and take no accent. Shown whatever the input device, unless the Settings page's Joysticks
   option hides them (data-joysticks="off" on <body>). A phone gets the larger size. The thumb springs back over 120ms on release
   and follows the finger without a transition while held. */
#joysticks { position: absolute; inset: 0; z-index: 2; display: block; pointer-events: none; --stick: 96px; --thumb: 36px; --stick-inset-x: 20px; --stick-inset-y: 28px; }
@media (pointer: coarse) and (max-width: 640px) { #joysticks { --stick: 120px; --thumb: 44px; } }
body[data-joysticks="off"] #joysticks { display: none; }
.stick { position: absolute; bottom: var(--stick-inset-y); width: var(--stick); height: var(--stick); pointer-events: auto; touch-action: none; user-select: none; -webkit-user-select: none; cursor: grab; }
.stick[data-name="move"] { left: var(--stick-inset-x); }
.stick[data-name="look"] { right: var(--stick-inset-x); }
.stick[data-active="true"] { cursor: grabbing; }
.stick-ring { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.stick-base { fill: rgba(14, 26, 25, .42); stroke: rgba(255, 255, 255, .28); stroke-width: 1; transition: stroke .15s ease, stroke-width .15s ease; }
.stick[data-active="true"] .stick-base { stroke: rgba(255, 255, 255, .6); stroke-width: 1.5; }
.stick-marks, .stick-horizon { fill: none; stroke: rgba(255, 255, 255, .5); stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.stick-horizon { stroke: rgba(255, 255, 255, .28); stroke-width: 1.5; stroke-dasharray: 3 4; }
/* pathLength 100 makes the dash array a percentage: --sprint is the ramp's progress, 0..100, set by joysticks.js. */
.stick-progress { fill: none; stroke: rgba(255, 255, 255, .85); stroke-width: 3; stroke-linecap: round; stroke-dasharray: var(--sprint, 0) 100; transform: rotate(-90deg); transform-origin: 50% 50%; opacity: 0; transition: opacity .15s ease; }
.stick[data-sprint="true"] .stick-progress { opacity: 1; }
.stick-thumb { position: absolute; left: 50%; top: 50%; width: var(--thumb); height: var(--thumb); margin: calc(var(--thumb) / -2) 0 0 calc(var(--thumb) / -2); box-sizing: border-box; border-radius: 50%; background: rgba(232, 238, 236, .94); box-shadow: 0 1px 2px rgba(0, 0, 0, .18); transform: translate(var(--tx, 0px), var(--ty, 0px)); transition: transform .12s ease; }
.stick[data-active="true"] .stick-thumb { transition: none; } /* follows the finger; the spring-back is for the release */
#joysticks[data-unavailable="true"] .stick { opacity: .4; }

/* ---- dimension numpad (numpad.js): a floating window over the player ---- */
/* The Live render window's family - hairline, 10px radius, the same shadow, the header as the drag handle - at a fixed
   236px with no corners; live-float.js places it (its fixed-size mode). Above the sticks (z 2), under #session-state
   (z 4); #loading never shows while it is open. The seeded value is highlighted until the first key replaces it. */
.numpad { position: absolute; z-index: 3; width: 236px; display: flex; flex-direction: column; background: var(--panel); border: 1px solid var(--line); border-radius: 10px; box-shadow: 0 14px 40px rgba(0, 0, 0, .45); overflow: hidden; color: var(--ink); touch-action: none; outline: none; }
.numpad[hidden] { display: none; }
.numpad.dragging, .numpad.dragging * { cursor: grabbing; }
.numpad-header { display: flex; align-items: center; gap: 8px; padding: 8px 8px 8px 12px; border-bottom: 1px solid var(--line); cursor: grab; user-select: none; -webkit-user-select: none; }
.numpad-titles { display: flex; flex-direction: column; gap: 1px; flex: 1 1 auto; min-width: 0; }
.numpad-title { font-size: 12.5px; font-weight: 600; letter-spacing: .01em; line-height: 1.3; }
.numpad-subtitle { font-size: 11px; line-height: 1.3; color: var(--muted); }
.numpad-subtitle:empty { display: none; }
.numpad-value { display: flex; align-items: baseline; justify-content: flex-end; gap: 6px; padding: 14px 14px 4px; font-variant-numeric: tabular-nums; }
#numpad-text { font-size: 28px; font-weight: 600; line-height: 1; padding: 2px 4px; border-radius: 4px; }
#numpad-text[data-fresh="true"] { background: color-mix(in srgb, var(--accent) 18%, transparent); }
.numpad-unit { font-size: 13px; color: var(--muted); }
.numpad-status { min-height: 16px; padding: 0 14px 6px; text-align: right; font-size: 11px; line-height: 1.4; color: var(--danger); }
.numpad-keys { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; padding: 4px 12px 8px; }
.numpad-key { height: 40px; display: grid; place-items: center; padding: 0; border: 1px solid var(--line); border-radius: 7px; background: var(--panel-2); color: var(--ink); font: inherit; font-size: 15px; font-weight: 600; cursor: pointer; transition: border-color .15s ease, background .15s ease; }
.numpad-key svg { width: 18px; height: 18px; }
.numpad-key:hover, .numpad-key:focus-visible { border-color: var(--accent-text); outline: none; }
.numpad-key:active { background: color-mix(in srgb, var(--accent) 18%, var(--panel-2)); }
.numpad-actions { display: flex; gap: 6px; padding: 0 12px 12px; }
.numpad-reset { flex: 1 1 0; height: 30px; padding: 0; border-radius: 7px; font-size: 12.5px; font-weight: 600; }
.numpad-apply { flex: 1.5 1 0; height: 30px; display: inline-flex; align-items: center; justify-content: center; gap: 6px; border: 0; border-radius: 7px; background: var(--accent); color: var(--accent-ink); font: inherit; font-size: 12.5px; font-weight: 600; cursor: pointer; }
.numpad-apply svg { width: 14px; height: 14px; }
.numpad-apply:hover, .numpad-apply:focus-visible { background: var(--accent-hover); outline: none; }

/* ---- API cost: development accounting, shown only while Show API cost is on in the debug panel (app.js) ---- */
/* The usage line under the chat header, each turn's usage and the Live render and video rows (.usage), and the Live
   render pane's figures. The switch adds or removes body.costs-hidden; nothing else needs to know. */
body.costs-hidden #chat-metrics, body.costs-hidden .usage, body.costs-hidden .live-render-info { display: none; }
/* ---- AI credit spending (credit-spending.js; design canvas page 32) ----
   The area over the composer's box, on the composer's own ground: the line (the count, the chip) or, while a request
   waits at the limit, the band. The chip is a composer chip (.chip) with the allowance's ring for its icon; its panel
   opens above it like a chip's menu. In the dock the chip and the band are appended to #dock-lead (app.js paneHooks). */
#credit-area { flex: 0 0 auto; display: flex; flex-direction: column; gap: 8px; padding: 10px 14px 0; border-top: 1px solid var(--line); background: var(--panel-2); }
#credit-area[hidden] { display: none; }
/* the form's own top border goes while the line shows: the two share one ground. A general sibling, not the next one,
   since the shell parks the hidden sample panel between them (app.js paneHooks). */
#credit-area:not([hidden]) ~ #composer { border-top: 0; padding-top: 8px; }
#chat.group-chat-active > #credit-area { display: none; }
#credit-line { display: flex; align-items: center; gap: 8px; min-height: 28px; font-size: 12px; color: var(--muted); }
#credit-line[hidden] { display: none; }
/* while the band stands in the line's place the line keeps only the chip's anchor, at no height and at the right, so
   the panel Custom… opens still has its place above the band */
#credit-area.is-paused #credit-line { min-height: 0; height: 0; margin-bottom: -8px; justify-content: flex-end; overflow: visible; }
#credit-area.is-paused #credit-line > .credit-text, #credit-area.is-paused #credit-chip { display: none; }
.credit-text { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; line-height: 1.3; }
.credit-count, .credit-sub { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.credit-sub { font-size: 11px; color: var(--muted); }
.credit-sub:empty { display: none; }
#credit-line[data-tone="accent"] .credit-count { color: var(--accent-text); }
#credit-line[data-tone="amber"] .credit-count { color: var(--amber); }
.credit-anchor { position: relative; display: inline-flex; flex: 0 0 auto; }
#credit-chip .chip-value { font-variant-numeric: tabular-nums; }
#credit-chip .chip-icon:empty { display: none; }
#credit-chip .chip-icon svg { width: 16px; height: 16px; }
#credit-chip[data-tone="amber"] { border-color: var(--amber); color: var(--amber); background: color-mix(in srgb, var(--amber) 14%, transparent); }
/* the panel: the chip's menu, 272 px (the composer's inner width at the usual pane), above the chip from its right
   edge, its own scroll when the pane is short */
.credit-panel {
  position: absolute; right: 0; bottom: calc(100% + 6px); z-index: 5; width: 272px; max-width: calc(100vw - 28px); max-height: min(60vh, 460px); overflow: auto;
  display: flex; flex-direction: column; gap: 8px; padding: 8px 0 6px; border: 1px solid var(--line); border-radius: 8px;
  background: var(--panel); color: var(--ink); box-shadow: 0 10px 30px rgba(0, 0, 0, .35); font-size: 12px; text-align: left;
}
.credit-panel[hidden] { display: none; }
.credit-panel-head { padding: 0 10px; font-size: 10.5px; font-weight: 600; letter-spacing: .07em; text-transform: uppercase; color: var(--muted); }
.credit-panel-text, .credit-note, .credit-error { margin: 0; padding: 0 10px; font-size: 12px; line-height: 1.45; color: var(--muted); }
.credit-panel-text[hidden], .credit-note[hidden], .credit-error[hidden], .credit-allowance[hidden], .credit-presets[hidden], .credit-steps[hidden], .credit-fresh[hidden] { display: none; }
.credit-note { color: var(--accent-text); }
.credit-error { color: var(--amber); }
.credit-allowance { display: flex; align-items: center; gap: 8px; padding: 0 10px; }
.credit-allowance-ring { display: inline-flex; flex: 0 0 auto; }
.credit-allowance-text { display: flex; flex-direction: column; min-width: 0; line-height: 1.3; }
.credit-allowance-text b { font-size: 13px; font-weight: 600; color: var(--ink); font-variant-numeric: tabular-nums; }
.credit-allowance-text span { font-size: 11px; color: var(--muted); }
.credit-presets { display: flex; gap: 6px; padding: 0 10px; }
.credit-preset, .credit-secondary, .credit-primary {
  display: inline-flex; align-items: center; justify-content: center; height: 28px; padding: 0 10px; border: 1px solid var(--line); border-radius: 7px;
  background: var(--panel); color: var(--ink); font: inherit; font-size: 12px; font-weight: 500; white-space: nowrap; cursor: pointer; font-variant-numeric: tabular-nums;
}
.credit-preset { flex: 1 1 0; min-width: 0; padding: 0; }
.credit-preset[aria-pressed="true"] { border-color: var(--accent-text); background: var(--accent-soft); color: var(--accent-text); font-weight: 600; }
.credit-preset:hover:not(:disabled), .credit-secondary:hover:not(:disabled) { border-color: var(--accent-text); }
.credit-primary { border-color: var(--accent); background: var(--accent); color: var(--accent-ink, #fff); font-weight: 600; }
.credit-primary:hover:not(:disabled) { filter: brightness(1.06); }
.credit-preset:disabled, .credit-secondary:disabled, .credit-primary:disabled, .credit-textbtn:disabled { opacity: .55; cursor: default; }
.credit-form { display: flex; align-items: center; gap: 8px; padding: 0 10px; }
.credit-field { flex: 1 1 auto; min-width: 0; display: inline-flex; align-items: center; gap: 6px; height: 30px; padding: 0 10px; border: 1px solid var(--line); border-radius: 7px; background: var(--panel-2); }
.credit-field:focus-within { border-color: var(--accent-text); box-shadow: 0 0 0 2px var(--accent-soft); }
.credit-field input { flex: 1 1 auto; min-width: 0; width: 100%; border: 0; padding: 0; background: transparent; color: var(--ink); font: inherit; font-size: 12.5px; font-variant-numeric: tabular-nums; outline: none; -moz-appearance: textfield; }
.credit-field input::-webkit-outer-spin-button, .credit-field input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.credit-field span { flex: 0 0 auto; font-size: 11.5px; color: var(--muted); }
.credit-steps { display: flex; align-items: center; gap: 6px; padding: 0 10px; }
.credit-steps-end { margin-left: auto; }
.credit-textbtn { display: inline-flex; align-items: center; gap: 2px; padding: 0; border: 0; background: transparent; color: var(--accent-text); font: inherit; font-size: 12px; font-weight: 500; white-space: nowrap; cursor: pointer; }
.credit-textbtn:hover:not(:disabled) { text-decoration: underline; }
.credit-textbtn svg { width: 11px; height: 11px; }
.credit-rule { height: 1px; margin: 0 10px; background: var(--line); }
.credit-fresh { display: flex; align-items: center; gap: 8px; padding: 0 10px; }
.credit-fresh-note { margin-left: auto; font-size: 11px; color: var(--muted); }
.credit-fresh-note:empty { display: none; }
.credit-foot { display: flex; align-items: center; gap: 8px; padding: 0 10px; font-size: 11.5px; color: var(--muted); }
.credit-foot span { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* the band: an amber card in the line's place while a request waits at the limit */
#credit-band { display: flex; flex-direction: column; gap: 8px; padding: 10px 12px; border: 1px solid var(--amber); border-radius: 10px; background: color-mix(in srgb, var(--amber) 10%, transparent); font-size: 12px; color: var(--muted); }
#credit-band[hidden] { display: none; }
.credit-band-head { display: flex; align-items: center; gap: 8px; font-size: 12.5px; }
.credit-band-dot { flex: 0 0 8px; width: 8px; height: 8px; border-radius: 50%; background: var(--amber); box-shadow: 0 0 0 4px color-mix(in srgb, var(--amber) 28%, transparent); }
.credit-band-title { flex: 1 1 auto; min-width: 0; font-weight: 600; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.credit-band-figures { flex: 0 0 auto; color: var(--amber); font-variant-numeric: tabular-nums; }
.credit-band-text { margin: 0; line-height: 1.4; }
.credit-band-actions { display: flex; align-items: center; gap: 6px; }
.credit-band-foot { display: flex; align-items: center; }
/* a finished task's row: the Worked-for row carries the task's charges; the chevron opens the accounting. The row
   standing alone (.credit-usage) is a task that ended without a Worked-for row in this browser. */
.credit-receipt > summary { display: flex; align-items: center; gap: 6px; list-style: none; cursor: pointer; }
.credit-receipt > summary::-webkit-details-marker { display: none; }
.credit-receipt-text { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.credit-receipt-sub { flex: 1 1 100%; order: 3; font-size: 11.5px; color: var(--muted); }
.credit-receipt-sub:empty { display: none; }
.credit-receipt-chevron { flex: 0 0 auto; display: inline-flex; color: var(--muted); transition: transform .15s ease; }
.credit-receipt-chevron svg { width: 12px; height: 12px; }
.credit-receipt[open] > .credit-receipt-chevron, .credit-receipt[open] > summary .credit-receipt-chevron { transform: rotate(90deg); }
.credit-receipt > summary:hover .credit-receipt-text, .credit-receipt > summary:focus-visible .credit-receipt-text { color: var(--ink); }
.credit-receipt > summary:focus-visible { outline: 2px solid var(--accent-text); outline-offset: 2px; border-radius: 4px; }
.credit-rows { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: 4px 14px; padding: 8px 2px 2px; font-size: 12px; line-height: 1.4; color: var(--ink); font-variant-numeric: tabular-nums; }
.credit-row-key { color: var(--muted); }
.credit-rows-note { grid-column: 1 / -1; margin-top: 2px; font-size: 11px; line-height: 1.4; color: var(--muted); }
.credit-usage { margin: 4px 0 12px; font-size: 12px; color: var(--muted); }
/* the dock: the chip before the save state on the lead line, the band as the lead line's own row under the words */
#dock-lead > .credit-anchor { grid-column: 6; }
/* in the dock the lead line already says what happened (its words) and the figures (the chip), so the band is its
   row of ways on alone, under the words */
#dock-lead > #credit-band { grid-column: 3 / -1; grid-row: 3; margin: 2px 0 4px; padding: 0; border: 0; background: transparent; gap: 6px; flex-direction: row; align-items: center; flex-wrap: wrap; }
#dock-lead > #credit-band .credit-band-head, #dock-lead > #credit-band .credit-band-text { display: none; }
#dock-lead > #credit-band .credit-band-foot { margin-left: 4px; }
#dock-credits:empty { display: none; }
/* Auto's model label remains public; only the optional routing details follow the debug preference. */
body.model-selection-details-hidden .model-selection-details { display: none; }

/* ---- Review drawer (review.js): Views, Layers, BIM data ---- */
/* Rows are the sessions column's: 6px radius, hover grey; every Views row leads with the same 44x28 slot (a still, a
   note's colour card, a frame's card) so the three kinds' names line up. The chips take the header buttons' corners. */
.rv-tab { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
.rv-tab[hidden] { display: none; }
.rv-tab .drawer { gap: 10px; }
.rv-tab .drawer[hidden] { display: none; }
.rv-list { flex: 1 1 auto; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; gap: 2px; margin: 0 -8px; padding: 0 8px; }
.rv-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-height: 24px; flex: 0 0 auto; }
.rv-list .rv-head { padding: 6px 8px 2px; }
.rv-heading { font-size: 11.5px; font-weight: 600; letter-spacing: .07em; text-transform: uppercase; color: var(--muted); white-space: nowrap; }
.rv-count, .rv-meta { font-size: 11px; color: var(--muted); white-space: nowrap; }
.rv-head-actions { display: flex; gap: 6px; }
.rv-head-actions .header-btn { height: 24px; padding: 0 8px; }
.rv-strip { display: flex; gap: 2px; padding: 2px; border: 1px solid var(--line); border-radius: 7px; background: var(--panel-2); flex: 0 0 auto; }
.rv-strip button { flex: 1 1 0; padding: 4px 0; border: 0; border-radius: 5px; background: transparent; color: var(--ink); font: inherit; font-size: 11.5px; line-height: 1.5; cursor: pointer; }
.rv-strip button:hover { background: var(--panel); }
.rv-row { display: flex; align-items: center; gap: 8px; min-height: 36px; padding: 0 6px 0 8px; border-radius: 6px; cursor: pointer; }
.rv-row:hover, .rv-row.menu-open { background: var(--active-item, rgba(127, 127, 127, .14)); }
.rv-view { min-height: 40px; }
.rv-name { flex: 1 1 auto; min-width: 0; font-size: 12.5px; line-height: 1.3; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.rv-name.strong { font-weight: 600; }
.rv-name.muted { color: var(--muted); }
.rv-still { flex: 0 0 auto; width: 44px; height: 28px; border-radius: 4px; object-fit: cover; display: block; box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .10); }
.rv-still-empty, .rv-card { flex: 0 0 auto; width: 44px; height: 28px; display: grid; place-items: center; border-radius: 4px; background: var(--panel-2); color: var(--muted); box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .08); }
.rv-act, .rv-eye, .rv-caret { flex: 0 0 auto; width: 24px; height: 24px; display: grid; place-items: center; padding: 0; border: 0; border-radius: 5px; background: transparent; color: var(--muted); cursor: pointer; }
.rv-act:hover, .rv-eye:hover:not(:disabled), .rv-caret:hover { color: var(--ink); background: var(--panel-2); }
/* the ⋮ is always there, faint, so touch has it; a hovered row and its menu bring it up */
.rv-more { color: var(--line); }
.rv-row:hover .rv-more, .rv-row.menu-open .rv-more, .rv-more:focus-visible { color: var(--ink); }
.rv-update { display: none; }
.rv-row:hover .rv-update, .rv-update:focus-visible { display: grid; }
.rv-rename { flex: 1 1 auto; min-width: 0; height: 26px; padding: 0 6px; border: 1px solid var(--accent-text); border-radius: 5px; background: var(--panel); color: var(--ink); font: inherit; font-size: 12.5px; outline: none; }
.rv-foot { flex: 0 0 auto; display: flex; flex-direction: column; gap: 6px; padding-top: 4px; }
.rv-wide { display: flex; align-items: center; justify-content: center; gap: 6px; height: 32px; border: 1px solid var(--line); border-radius: 8px; background: transparent; color: var(--ink); font: inherit; font-size: 12.5px; font-weight: 600; cursor: pointer; }
.rv-wide:hover:not(:disabled) { border-color: var(--accent-text); }
.rv-wide:disabled { color: var(--muted); opacity: .6; cursor: default; }
.rv-status { margin: 0; font-size: 11.5px; color: var(--muted); text-align: center; }
.rv-status.failed { color: var(--danger); }
#rv-menu { position: fixed; z-index: 60; min-width: 180px; padding: 4px; border: 1px solid var(--line); border-radius: 8px; background: var(--panel); box-shadow: 0 10px 30px rgba(0, 0, 0, .14); }
#rv-menu[hidden] { display: none; }
/* Layers */
.rv-layer, .rv-model { min-height: 32px; padding-right: 4px; }
.rv-layer.child { padding-left: 26px; }
.rv-layer.disabled .rv-name { color: var(--muted); }
.rv-indent { flex: 0 0 16px; }
.rv-caret { width: 16px; height: 16px; }
.rv-caret svg { transition: transform .12s ease; }
.rv-caret[aria-expanded="false"] svg { transform: rotate(-90deg); }
.rv-badge { flex: 0 0 auto; padding: 1px 5px; border: 1px solid var(--line); border-radius: 4px; background: var(--panel-2); font-size: 10px; font-weight: 600; letter-spacing: .04em; color: var(--muted); }
.rv-eye[aria-pressed="true"] { color: var(--ink); }
.rv-eye.mixed { opacity: .5; }
.rv-eye:disabled { opacity: .5; cursor: default; }
.rv-solo { display: none; flex: 0 0 auto; height: 24px; padding: 0 8px; border: 1px solid var(--line); border-radius: 5px; background: transparent; color: var(--ink); font: inherit; font-size: 11.5px; line-height: 1; cursor: pointer; }
.rv-row:hover .rv-solo, .rv-solo:focus-visible { display: inline-flex; align-items: center; }
/* BIM data */
.rv-select { height: 24px; padding: 0 8px; display: inline-flex; align-items: center; gap: 5px; }
.rv-select svg { width: 13px; height: 13px; }
.rv-element { display: flex; align-items: center; gap: 10px; padding: 10px 12px; border: 1px solid var(--line); border-radius: 8px; background: var(--panel-2); flex: 0 0 auto; }
.rv-element[hidden], .rv-sheet[hidden], .rv-bim-empty[hidden], .rv-bim .drawer-search[hidden] { display: none; }
.rv-element-glyph { flex: 0 0 auto; width: 36px; height: 36px; display: grid; place-items: center; border-radius: 7px; background: var(--panel); box-shadow: inset 0 0 0 1px var(--line); color: var(--ink); }
.rv-element-text { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.rv-element-name { font-size: 13px; font-weight: 600; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.rv-element-sub { font-size: 11.5px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.rv-element-model { display: flex; align-items: center; gap: 6px; font-size: 11px; color: var(--muted); white-space: nowrap; overflow: hidden; }
.rv-element-model > span:last-child { overflow: hidden; text-overflow: ellipsis; }
.rv-sheet { flex: 1 1 auto; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; gap: 6px; margin: 0 -8px; padding: 0 8px; }
.rv-group { display: flex; flex-direction: column; gap: 1px; flex: 0 0 auto; }
.rv-group-head { display: flex; align-items: center; gap: 6px; height: 28px; }
.rv-prop { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr) 20px; align-items: center; gap: 8px; min-height: 26px; padding: 0 4px 0 8px; border-radius: 5px; cursor: copy; }
.rv-prop:hover { background: var(--active-item, rgba(127, 127, 127, .14)); }
.rv-key { font-size: 12px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.rv-val { font-size: 12.5px; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-variant-numeric: tabular-nums; }
.rv-copy { display: none; color: var(--muted); }
.rv-prop:hover .rv-copy { display: grid; place-items: center; }
.rv-prop.copied .rv-val { color: var(--accent-text); }
/* the empty and locked states, the same anatomy */
.rv-bim-empty, .rv-locked { flex: 1 1 auto; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px; padding: 12px 32px 40px; text-align: center; }
.rv-locked[hidden] { display: none; }
.rv-empty-glyph { width: 44px; height: 44px; display: grid; place-items: center; border-radius: 12px; background: var(--panel-2); color: var(--muted); }
.rv-empty-glyph svg { width: 22px; height: 22px; }
.rv-empty-title { font-size: 13px; font-weight: 600; color: var(--ink); }
.rv-empty-text { font-size: 12px; line-height: 1.45; color: var(--muted); }

/* ---- Scene settings (scene-settings.js): one page of sections ---- */
.sc-page { overflow-y: auto; gap: 10px; container-type: inline-size; } /* the stats row and the field widths follow the panel's width */
.sc-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-height: 24px; flex: 0 0 auto; }
.sc-heading { margin: 0; font-size: 11.5px; font-weight: 600; letter-spacing: .07em; text-transform: uppercase; color: var(--muted); }
.sc-head .header-btn { height: 24px; padding: 0 8px; display: inline-flex; align-items: center; gap: 5px; }
.sc-head .header-btn svg { width: 12px; height: 12px; color: var(--muted); }
.sc-rule { border: 0; height: 1px; margin: 4px 0; background: var(--line); flex: 0 0 auto; }
.sc-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; min-height: 30px; flex: 0 0 auto; }
.sc-row[hidden] { display: none; }
.sc-label { display: flex; flex-direction: column; gap: 1px; min-width: 0; font-size: 12.5px; color: var(--ink); }
.sc-sub { font-size: 11px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sc-sub[hidden] { display: none; }
.sc-shadows-sub.forced, .sc-ao-sub.forced { color: var(--amber); }
/* Render help stays readable in a narrow drawer, including the performance guard's explanation. */
#sc-reflections-help, #sc-lines-help, #sc-shadows-help, #sc-ao-help, #sc-pbr-help, #sc-detail-help, #us-floor-help, #us-wall-help,
.sc-site, .sc-section-sub, .sc-section-offset-sub { white-space: normal; } /* notes that wrap in a narrow panel instead of clipping */
.muted-row .sc-label > span:first-child { color: var(--muted); }
.sc-sun-row { display: flex; align-items: center; gap: 10px; flex: 0 0 auto; }
.sc-sun-glyph { display: inline-flex; color: var(--muted); } .sc-sun-glyph svg { width: 16px; height: 16px; }
.sc-time-range, .sc-transparency { flex: 1 1 auto; min-width: 0; height: 18px; margin: 0; accent-color: var(--range-accent); cursor: pointer; }
.sc-time, .sc-day, .sc-month, .sc-reflections, .us-page select { height: 28px; padding: 0 8px; border: 1px solid var(--line); border-radius: 7px; background: var(--bg); color: var(--ink); font: inherit; font-size: 12.5px; font-variant-numeric: tabular-nums; }
.sc-time { width: 84px; text-align: center; }
.sc-time::-webkit-calendar-picker-indicator { display: none; } .sc-day { width: 48px; text-align: center; } .sc-month { width: 108px; } .sc-reflections { width: 124px; }
.sc-time:disabled, .sc-day:disabled, .sc-month:disabled, .sc-reflections:disabled, .sc-time-range:disabled, .sc-transparency:disabled { opacity: .55; cursor: default; }
.sc-date { display: inline-flex; gap: 6px; flex: 0 0 auto; } /* the fields keep their width */
.sc-site { margin-top: -6px; } /* the site, its own line tucked under the Date row at every width */
.sc-page > .sc-sub { flex: 0 0 auto; } /* a note that is the page's own flex item keeps its height when the page scrolls (overflow: hidden lets it shrink to nothing otherwise) */
.sc-transparency-row { display: flex; align-items: center; gap: 10px; flex: 0 0 auto; padding-top: 2px; }
.sc-transparency-row[hidden] { display: none; }
.sc-transparency-row .sc-sub { flex: 0 0 auto; font-size: 12px; }
.sc-transparency-value { flex: 0 0 auto; min-width: 3em; text-align: right; font-size: 11.5px; color: var(--muted); font-variant-numeric: tabular-nums; }
.sc-modes button[aria-pressed="true"], .sc-section button[aria-pressed="true"], .sc-section-controls .rv-strip button[aria-pressed="true"] { background: var(--accent-soft); color: var(--accent-text); box-shadow: inset 0 0 0 1px var(--accent-text); }
.sc-modes button:disabled, .sc-section button:disabled, .sc-section-controls .rv-strip button:disabled { color: var(--muted); cursor: default; }
/* the switch: a checkbox drawn as the shell's 34x18 track, the accent when on; dimmed while the guard forces it off */
.sc-switch { position: relative; display: inline-flex; flex: 0 0 auto; width: 34px; height: 18px; cursor: pointer; }
.sc-switch input { position: absolute; inset: 0; margin: 0; opacity: 0; cursor: pointer; }
.sc-track { position: absolute; inset: 0; border-radius: 9px; background: var(--line); transition: background .15s; }
.sc-track::after { content: ''; position: absolute; top: 2px; left: 2px; width: 14px; height: 14px; border-radius: 50%; background: var(--panel); box-shadow: 0 1px 2px rgba(0, 0, 0, .18); transition: left .15s; }
.sc-switch input:checked + .sc-track { background: var(--accent); }
.sc-switch input:checked + .sc-track::after { left: 18px; }
.sc-switch input:focus-visible + .sc-track { outline: 2px solid var(--accent-text); outline-offset: 2px; }
.sc-switch input:disabled + .sc-track { opacity: .5; } .sc-switch input:disabled { cursor: default; }
.sc-switch input.forced + .sc-track { opacity: .5; }
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.sc-stats { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; flex: 0 0 auto; padding: 0 2px; }
.sc-stat { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.sc-stat-top { display: flex; align-items: center; gap: 6px; color: var(--ink); font-size: 13px; font-weight: 600; font-variant-numeric: tabular-nums; white-space: nowrap; }
.sc-stat-top svg { width: 15px; height: 15px; color: var(--muted); flex: 0 0 auto; }
.sc-stat-of { font-weight: 400; color: var(--muted); }
.sc-stat-caption { font-size: 10.5px; color: var(--muted); white-space: nowrap; }
/* A narrow panel (the page is its own container): one stat per line, the glyph, the name and the number on the right,
   reading like the rows above (the pair's box dissolves so its glyph and number sit in the line's grid), and the
   month and reflections fields a little narrower so the Date and Reflections rows keep room for their words. */
@container (max-width: 330px) {
  .sc-stats { display: flex; flex-direction: column; align-items: stretch; gap: 6px; padding: 0; }
  .sc-stat { display: grid; grid-template-columns: 15px minmax(0, 1fr) auto; align-items: center; gap: 0 8px; min-height: 24px; }
  .sc-stat-top { display: contents; }
  .sc-stat-top svg { order: 1; }
  .sc-stat-caption { order: 2; font-size: 12.5px; color: var(--ink); white-space: normal; }
  .sc-stat-value { order: 3; }
  .sc-month { width: 96px; } .sc-reflections { width: 108px; }
  /* X-ray's Transparency: the word and the percentage on one line, the range at full width under them, as Model detail is */
  .sc-transparency-row { flex-wrap: wrap; gap: 4px 10px; }
  .sc-transparency-row .sc-sub { order: 1; flex: 1 1 auto; }
  .sc-transparency-value { order: 2; }
  .sc-transparency { order: 3; flex: 1 0 100%; }
}

/* ---- Voice (voice-bar.js over agent-voice.js): the mic square at rest (.composer-square), the bar while voice is on, spoken turns ---- */
#voice-start[hidden], #voice-start[aria-pressed="true"], #voice-panel[hidden] { display: none; } /* the bar stands in for the button while voice is on */
#voice-panel {
  display: flex; align-items: center; gap: 6px; min-height: 42px; padding: 5px 6px 5px 12px;
  border: 1px solid var(--line); border-radius: 10px; background: var(--panel);
}
#voice-panel[data-state="idle"] { border-color: var(--amber); }
#voice-panel[data-state="error"] { border-color: var(--danger); }
.vb-pill { display: flex; align-items: center; gap: 7px; flex: 1 1 auto; min-width: 0; font-size: 12.5px; font-weight: 600; color: var(--ink); white-space: nowrap; }
#voice-panel[data-state="error"] .vb-pill { white-space: normal; font-weight: 500; line-height: 1.35; }
#voice-panel[data-state="muted"] .vb-pill, #voice-panel[data-state="connecting"] .vb-pill, #voice-panel[data-state="ending"] .vb-pill { color: var(--muted); }
#voice-panel[data-state="idle"] .vb-pill { color: var(--amber); }
.vb-lead { display: inline-flex; align-items: center; flex: 0 0 auto; color: var(--accent-text); }
.vb-lead svg { width: 15px; height: 15px; }
#voice-panel[data-state="muted"] .vb-lead, #voice-panel[data-state="blocked"] .vb-lead { color: var(--muted); }
.vb-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.vb-time { font-weight: 400; color: var(--muted); font-variant-numeric: tabular-nums; }
.vb-time[hidden] { display: none; }
#voice-panel[data-state="idle"] .vb-time { color: inherit; }
.vb-meter { display: inline-flex; align-items: center; gap: 2px; height: 16px; }
.vb-meter span { width: 2px; height: 3px; border-radius: 1px; background: currentColor; transition: height .08s linear; }
#voice-panel[data-state="speaking"] .vb-meter span { animation: vb-pulse .8s ease-in-out infinite alternate; }
#voice-panel[data-state="speaking"] .vb-meter span:nth-child(2) { animation-delay: .12s; }
#voice-panel[data-state="speaking"] .vb-meter span:nth-child(3) { animation-delay: .24s; }
#voice-panel[data-state="speaking"] .vb-meter span:nth-child(4) { animation-delay: .36s; }
#voice-panel[data-state="speaking"] .vb-meter span:nth-child(5) { animation-delay: .48s; }
@keyframes vb-pulse { from { height: 4px; } to { height: 14px; } }
/* The app's one progress ring (ring.js): the credits ring's drawing at every size - the track in the line colour, the
   arc in the accent with round caps, started at the top; turning with a 30 % arc while the share is unknown. The rail's
   importing state, the Import rows, the export status line and the share and voice bubbles all draw this one. */
.ring { display: inline-block; flex: 0 0 auto; transform: rotate(-90deg); vertical-align: middle; }
.ring-track { fill: none; stroke: var(--line); }
.ring-value { fill: none; stroke: var(--accent); stroke-linecap: round; transition: stroke-dasharray .3s ease; }
.ring.is-turning { animation: ring-turn 1s linear infinite; }
.ring.is-turning .ring-value { transition: none; }
.ring[data-tone="amber"] .ring-value { stroke: var(--amber); }
.ring[data-tone="danger"] .ring-value { stroke: var(--danger); }
.ring[data-tone="muted"] .ring-value { stroke: var(--muted); }
.ring[data-tone="white"] .ring-track { stroke: rgba(255, 255, 255, .35); }
.ring[data-tone="white"] .ring-value { stroke: #fff; }
@keyframes ring-turn { from { transform: rotate(-90deg); } to { transform: rotate(270deg); } }
#voice-panel[data-state="ending"] .ring-value, #voice-panel[data-state="connecting"] .ring-value { stroke: var(--muted); }
.vb-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--amber); }
#voice-panel[data-state="error"] .vb-dot { background: var(--danger); }
.vb-mic { position: relative; display: inline-flex; align-items: stretch; height: 30px; border: 1px solid var(--line); border-radius: 7px; flex: 0 0 auto; }
.vb-mic[hidden] { display: none; }
.vb-mic > button { display: inline-flex; align-items: center; padding: 0 7px; border: 0; border-radius: 6px 0 0 6px; background: transparent; color: var(--ink); font: inherit; cursor: pointer; }
.vb-mic > button + button { border-left: 1px solid var(--line); border-radius: 0 6px 6px 0; padding: 0 5px; color: var(--muted); }
.vb-mic > button svg { width: 15px; height: 15px; }
.vb-mic > button:hover:not(:disabled) { background: var(--active-item, rgba(127, 127, 127, .14)); }
.vb-mic > button:disabled { cursor: default; opacity: .5; }
#voice-mute[data-muted="true"] { background: var(--accent-soft); color: var(--accent-text); }
#voice-panel .mode-toggle { flex: 0 0 auto; }
#voice-keep[hidden], #voice-play[hidden], #voice-retry[hidden], #voice-end[hidden], #voice-close[hidden] { display: none; }
#voice-mic, #voice-captions, #voice-cost { display: none; } /* agent-voice.js writes them; the bar reads them */
.vb-picker {
  position: absolute; right: -1px; bottom: calc(100% + 6px); z-index: 5; min-width: 220px; max-width: 280px;
  display: flex; flex-direction: column; gap: 1px; padding: 4px; border: 1px solid var(--line); border-radius: 8px;
  background: var(--panel); box-shadow: 0 10px 30px rgba(0, 0, 0, .35);
}
.vb-picker[hidden] { display: none; }
.vb-picker-head { padding: 6px 8px 2px; font-size: 11px; color: var(--muted); }
.vb-picker button { display: flex; align-items: center; gap: 10px; min-height: 34px; padding: 4px 8px; border: 0; border-radius: 6px; background: transparent; color: var(--ink); font: inherit; font-size: 12.5px; text-align: left; cursor: pointer; }
.vb-picker button:hover { background: var(--active-item, rgba(127, 127, 127, .14)); }
.vb-picker button > span { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vb-picker button svg { width: 14px; height: 14px; flex: 0 0 auto; color: var(--muted); }
.vb-picker button .vb-check svg { color: var(--accent-text); }
/* spoken turns: the same bubbles, a mic or a speaker glyph at their start; the one still being spoken keeps the
   accent ring and a caret until the captions rest */
.msg.voice { display: flex; gap: 8px; align-items: flex-start; }
.msg.voice > svg { flex: 0 0 auto; width: 14px; height: 14px; margin-top: 4px; color: var(--muted); }
.msg.voice > span { min-width: 0; }
.msg.user.voice.live { box-shadow: 0 0 0 1px var(--accent-text); }
.msg.voice.live > span::after { content: ''; display: inline-block; width: 2px; height: 14px; margin-left: 3px; vertical-align: -2px; background: var(--accent); animation: vb-caret 1s steps(2) infinite; }
@keyframes vb-caret { to { opacity: 0; } }

/* Map page (map.js): the search with its results dropping over the page, the location card with its static map, the tool rows */
.mp-page { position: relative; display: flex; flex-direction: column; gap: 10px; }
.mp-page[hidden] { display: none; }
.mp-table-distance { display: flex; align-items: center; gap: 8px; color: var(--muted); font-size: 12px; }
.mp-table-distance input { width: 88px; height: 28px; padding: 0 8px; border: 1px solid var(--line); border-radius: 7px; background: var(--bg); color: var(--ink); font: inherit; font-size: 12.5px; font-variant-numeric: tabular-nums; }
.mp-table-distance input:disabled { opacity: .55; }
.mp-search-wrap { position: relative; flex: 0 0 auto; }
.mp-search { display: flex; align-items: center; gap: 8px; height: 32px; padding: 0 10px; border: 1px solid var(--line); border-radius: 8px; background: var(--bg); color: var(--muted); cursor: text; }
.mp-search:focus-within { border-color: var(--accent-text); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 25%, transparent); }
.mp-search svg { width: 14px; height: 14px; flex: 0 0 auto; }
.mp-query { flex: 1 1 auto; min-width: 0; border: 0; padding: 0; background: transparent; color: var(--ink); font: inherit; font-size: 12.5px; outline: none; }
.mp-query::placeholder { color: var(--muted); }
.mp-query:disabled { cursor: default; }
.mp-results { position: absolute; left: 0; right: 0; top: 36px; z-index: 3; display: flex; flex-direction: column; gap: 1px; padding: 4px; border: 1px solid var(--line); border-radius: 8px; background: var(--panel); box-shadow: 0 10px 30px rgba(0, 0, 0, .14); }
.mp-results[hidden] { display: none; }
.mp-result { display: flex; align-items: center; gap: 10px; min-height: 40px; padding: 4px 8px; border: 0; border-radius: 6px; background: transparent; color: var(--ink); font: inherit; text-align: left; cursor: pointer; }
.mp-result:hover, .mp-result[aria-selected="true"] { background: var(--active-item, rgba(127, 127, 127, .14)); }
.mp-result-pin { flex: 0 0 auto; width: 26px; height: 26px; display: grid; place-items: center; border-radius: 6px; background: var(--panel-2, var(--bg)); color: var(--muted); }
.mp-result-pin svg { width: 15px; height: 15px; }
.mp-result-text { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.mp-result-name { font-size: 12.5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mp-result-where { font-size: 11px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mp-results-note { padding: 8px 8px 6px; font-size: 12px; line-height: 1.4; color: var(--muted); }
.mp-link { border: 0; padding: 0; background: transparent; color: var(--accent-text); font: inherit; font-size: 12px; cursor: pointer; }
.mp-locate { display: flex; align-items: center; gap: 6px; padding: 6px 8px 4px; border: 0; background: transparent; color: var(--muted); font: inherit; font-size: 11px; text-align: left; cursor: pointer; }
.mp-locate svg { width: 12px; height: 12px; }
.mp-locate:hover:not(:disabled) { color: var(--ink); }
.mp-locate:disabled { cursor: default; }
.mp-card { display: flex; flex-direction: column; border: 1px solid var(--line); border-radius: 8px; background: var(--panel-2, var(--bg)); overflow: hidden; flex: 0 0 auto; }
.mp-map { display: block; width: 100%; height: 96px; object-fit: cover; background: var(--line); }
.mp-map[hidden] { display: none; }
.mp-place { display: flex; align-items: center; gap: 10px; padding: 9px 12px; }
.mp-pin { flex: 0 0 auto; width: 28px; height: 28px; display: grid; place-items: center; border-radius: 7px; background: var(--panel); box-shadow: inset 0 0 0 1px var(--line); color: var(--accent-text); }
.mp-pin svg { width: 16px; height: 16px; }
.mp-card.is-default .mp-pin { color: var(--muted); }
.mp-place-text { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.mp-address { font-size: 13px; font-weight: 600; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mp-card.is-default .mp-address { color: var(--muted); }
.mp-coords { font-size: 11.5px; color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mp-hint { padding: 0 12px 10px; font-size: 11.5px; line-height: 1.4; color: var(--muted); }
.mp-hint[hidden] { display: none; }
.mp-tool { height: 24px; padding: 0 8px; display: inline-flex; align-items: center; gap: 5px; font-size: 11.5px; white-space: nowrap; }
.mp-tool svg { width: 12px; height: 12px; color: var(--muted); }
.mp-tool[aria-pressed="true"], .mp-tool[aria-pressed="true"] svg { color: var(--accent-text); }
.mp-spacer { flex: 1 1 auto; min-height: 8px; }
.mp-attribution { flex: 0 0 auto; font-size: 10.5px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mp-attribution a { color: inherit; text-decoration: none; }
.mp-attribution a.mp-improve, .mp-attribution a:hover { text-decoration: underline; }

/* History page (history.js): the versions by local day in five-minute blocks, the row being previewed or loaded, and
   the preview window over the player. The window borrows the media viewer's chrome (#render-viewer: the same scrim,
   panel surface, hairline border, 12px corners, 32px actions) at a 640px width, so a still of a version reads like an
   opened render rather than a second player. The page is a container so a narrow drawer (300px, down to the panel's
   220px) can drop the hover hint and let a row's time and its Latest save marker wrap. */
.hy-page { gap: 2px; padding: 10px 12px 12px; overflow-y: auto; container-type: inline-size; }
.hy-head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; min-height: 22px; padding: 0 2px; font-size: 11.5px; font-weight: 600; letter-spacing: .07em; text-transform: uppercase; color: var(--muted); flex: 0 0 auto; }
.hy-row + .hy-head, .hy-group + .hy-head { margin-top: 8px; }
.hy-count { font-size: 11.5px; font-weight: 400; letter-spacing: 0; text-transform: none; white-space: nowrap; }
.hy-row { display: flex; width: 100%; background: transparent; text-align: left; font: inherit; align-items: center; gap: 8px; min-height: 32px; padding: 0 6px; border: 1px solid transparent; border-radius: 6px; color: var(--ink); cursor: pointer; flex: 0 0 auto; }
.hy-row:hover, .hy-row:focus-visible { background: var(--active-item, rgba(127, 127, 127, .14)); outline: none; }
.hy-row[aria-pressed="true"] { border-color: var(--accent-text); background: var(--accent-soft); }
.hy-row[aria-disabled="true"] { cursor: default; opacity: .6; }
/* The row whose version is downloading and the one in the window stay legible while every row waits. */
.hy-row[aria-disabled="true"][data-status="loading"], .hy-row[aria-disabled="true"][aria-pressed="true"] { opacity: 1; }
.hy-tile { flex: 0 0 auto; width: 22px; height: 22px; display: grid; place-items: center; border-radius: 6px; background: var(--panel-2, var(--bg)); color: var(--muted); }
.hy-tile svg { width: 13px; height: 13px; }
.hy-tile .spinner { width: 13px; height: 13px; border-width: 2px; }
.hy-row[aria-pressed="true"] .hy-tile { background: var(--panel); box-shadow: inset 0 0 0 1px var(--accent-text); color: var(--accent-text); }
.hy-time { flex: 1 1 auto; min-width: 0; display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 8px; font-size: 12.5px; font-weight: 600; font-variant-numeric: tabular-nums; }
.hy-latest { font-size: 10.5px; font-weight: 500; color: var(--muted); white-space: nowrap; }
.hy-hint { display: none; font-size: 11px; color: var(--muted); white-space: nowrap; }
.hy-row:hover .hy-hint, .hy-row:focus-visible .hy-hint { display: inline; }
.hy-row[aria-disabled="true"] .hy-hint { display: none; }
.hy-tag { font-size: 10.5px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: var(--accent-text); white-space: nowrap; }
.hy-tag.hy-loading { color: var(--muted); }
/* A five-minute block: its header row discloses the exact versions behind the newest, which stays in view. */
.hy-group { margin: 2px 0 6px; padding: 2px; border: 1px solid var(--line); border-radius: 7px; flex: 0 0 auto; }
.hy-expand { display: flex; align-items: center; gap: 6px; width: 100%; min-height: 28px; padding: 2px 6px 2px 4px; border: 0; border-radius: 5px; color: var(--muted); background: transparent; font: inherit; font-size: 11.5px; text-align: left; cursor: pointer; }
.hy-expand:hover { background: var(--panel-2); color: var(--ink); }
.hy-expand:focus-visible, .hy-row:focus-visible { outline: 2px solid var(--accent-text); outline-offset: -2px; }
.hy-chev { flex: 0 0 auto; display: inline-grid; place-items: center; width: 14px; height: 14px; transition: transform .15s ease; }
.hy-chev svg { width: 14px; height: 14px; }
.hy-expand[aria-expanded="true"] .hy-chev { transform: rotate(90deg); }
@media (prefers-reduced-motion: reduce) { .hy-chev { transition: none; } }
.hy-range { font-weight: 600; font-variant-numeric: tabular-nums; color: var(--ink); }
.hy-group-count { margin-left: auto; white-space: nowrap; }
.hy-group-mark { color: var(--accent-text); font-weight: 600; }
.hy-group-rows { margin: 2px 0 0 10px; padding-left: 6px; border-left: 1px solid var(--line); }
.hy-group-rows[hidden] { display: none; }
.hy-row.hy-sub { min-height: 30px; }
.hy-row.hy-sub .hy-tile { width: 20px; height: 20px; }
@container (max-width: 250px) { .hy-row .hy-hint { display: none; } .hy-group-count { white-space: normal; text-align: right; } }
/* A failure line: a sentence, and Refresh history when the list has to be read again before another try. */
.hy-error { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; padding: 6px 8px; border: 1px solid var(--amber); border-radius: 6px; font-size: 11.5px; line-height: 1.4; color: var(--ink); flex: 0 0 auto; }
.hy-error[hidden] { display: none; }
.hy-error .hy-error-text { flex: 1 1 160px; min-width: 0; }
.hy-error .header-btn { height: 26px; padding: 0 9px; }
.hy-error .header-btn[hidden] { display: none; }
.hy-empty { flex: 1 1 auto; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px; padding: 0 14px 40px; text-align: center; }
.hy-empty[hidden] { display: none; }
.hy-spacer { flex: 1 1 auto; }
.hy-foot { flex: 0 0 auto; padding-top: 8px; font-size: 10.5px; line-height: 1.4; color: var(--muted); }
.hy-foot[hidden] { display: none; }
/* Load older cloud versions (shared-scenes.js appends it under the page while a shared history has more). */
.hy-more { margin: 0 12px 12px; height: 30px; font-size: 12px; }
.hy-more[hidden] { display: none; }
/* ---- the preview window over the player ---- */
#history-banner { position: absolute; inset: 0; z-index: 4; display: grid; place-items: center; padding: 12px; background: rgba(4, 8, 6, .72); backdrop-filter: blur(3px); color: var(--ink); font-size: 13px; line-height: 1.4; }
#history-banner[hidden] { display: none; }
/* A flex column capped at the player's height: in a short player the stage gives way (down to 96px, the still
   letterboxed) before the header, its actions and the note do, and the window scrolls only after that. */
.hy-dialog { display: flex; flex-direction: column; width: min(640px, 100%); max-height: 100%; min-height: 0; overflow: auto; background: var(--panel); color: var(--ink); border: 1px solid var(--line); border-radius: 12px; box-shadow: 0 24px 64px rgba(0, 0, 0, .5); outline: none; }
/* Sticky, so the actions stay reachable in the one case the window still scrolls: a player too short for the stage's
   96px minimum, the header and the note together. */
.hy-preview-header { position: sticky; top: 0; z-index: 1; flex: 0 0 auto; display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; padding: 10px 12px 10px 16px; background: var(--panel); border-bottom: 1px solid var(--line); }
.hy-when { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 8px; min-width: 0; font-weight: 600; font-size: 14px; letter-spacing: .01em; }
.hy-when-label { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; } /* the label gives way first in a narrow player; the time stays whole */
.hy-when-time { flex: 0 0 auto; font-size: 13px; font-variant-numeric: tabular-nums; }
.hy-preview-details { flex: 1 0 100%; order: 3; font-size: 11.5px; color: var(--muted); overflow-wrap: anywhere; }
.hy-preview-details:empty { display: none; }
/* The actions take what is left of the title row and, on a narrow player, the whole next row; they keep to the right
   like the viewer's, Dismiss last, and wrap among themselves only when even a row of their own is too narrow. */
.hy-actions { flex: 1 1 auto; display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 8px; }
.hy-action { flex: 0 0 auto; height: 32px; padding: 0 12px; border: 1px solid var(--line); border-radius: 8px; background: var(--panel-2); color: var(--ink); font: inherit; font-size: 12.5px; font-weight: 600; white-space: nowrap; cursor: pointer; transition: border-color .15s ease; }
.hy-action:hover:not(:disabled), .hy-action:focus-visible { border-color: var(--accent-text); outline: none; }
.hy-action:disabled { opacity: .5; cursor: default; }
.hy-action[hidden] { display: none; }
.hy-preview-stage { position: relative; flex: 1 1 auto; min-height: 96px; aspect-ratio: 8 / 5; display: grid; place-items: center; background: var(--bg); color: var(--ink); }
/* The still is the stage's box, whatever the stage was shrunk to; as a grid item its intrinsic height would hold the
   stage open and push the note out of view. */
.hy-preview-image { position: absolute; inset: 0; display: block; width: 100%; height: 100%; object-fit: contain; user-select: none; }
.hy-preview-image[hidden], .hy-preview-status[hidden] { display: none; }
.hy-preview-status { display: flex; flex-direction: column; align-items: center; gap: 8px; max-width: 400px; padding: 16px; text-align: center; font-size: 12.5px; line-height: 1.4; }
.hy-status-glyph { display: grid; place-items: center; }
.hy-status-glyph .spinner { width: 22px; height: 22px; border-width: 2px; }
.hy-status-glyph svg { width: 22px; height: 22px; color: var(--muted); }
.hy-status-title { font-weight: 600; }
.hy-status-detail { font-size: 11.5px; color: var(--muted); }
.hy-status-detail:empty { display: none; }
.hy-preview-error { margin: 8px 16px 0; }
.hy-preview-foot { flex: 0 0 auto; display: flex; flex-direction: column; gap: 2px; padding: 8px 16px 10px; border-top: 1px solid var(--line); font-size: 11.5px; line-height: 1.4; color: var(--muted); }
.hy-preview-warnings:empty { display: none; }
/* Fingers get the taller targets of the rest of the shell's touch chrome. */
@media (pointer: coarse) { .hy-action { height: 36px; } .hy-row, .hy-row.hy-sub { min-height: 36px; } .hy-expand { min-height: 32px; } }

/* Initial queue layout: the runtime owns the order; this small surface can be restyled independently. */
/* The queued prompts (agent-prompt-queue.js), at the foot of the transcript and continuing its column: an eyebrow, then
   each waiting message as the user bubble's shape hollow - a hairline on the panel's second surface, the words in ink -
   with Send now and Discard as two quiet words under its right edge; a notice as one muted line. The block scrolls
   past two fifths of the pane so a long queue never squeezes the transcript away. */
#prompt-queue { flex: 0 0 auto; display: flex; flex-wrap: wrap; justify-content: flex-end; align-items: center; column-gap: 10px; row-gap: 10px; max-height: 40vh; overflow-y: auto; padding: 0 18px 14px; background: var(--panel); }
#prompt-queue[hidden] { display: none; }
/* a wrapping row: the eyebrow and Continue queue (ordered before the messages, whatever their place in the markup) share
   the first line at the right; every waiting message and the notice take a full line of their own */
.pq-eyebrow { order: -2; font-size: 11.5px; font-weight: 600; letter-spacing: .07em; text-transform: uppercase; color: var(--muted); }
.pq-resume { order: -1; padding: 0; }
.pq-item, .pq-notice { flex: 0 0 100%; }
/* The first track soaks up the row, so the bubble's percentage cap resolves against the chat column as the transcript's does;
   the two actions are placed under the bubble's right edge rather than sliding into that track. */
.pq-item { display: grid; grid-template-columns: minmax(0, 1fr) auto auto; justify-content: end; column-gap: 12px; row-gap: 5px; }
.pq-item > .pq-act:nth-of-type(1) { grid-column: 2; }
.pq-item > .pq-act:nth-of-type(2) { grid-column: 3; }
.pq-bubble { grid-column: 1 / -1; justify-self: end; max-width: 84%; padding: 10px 14px; border: 1px solid var(--line); border-radius: 16px; border-bottom-right-radius: 6px; background: var(--panel-2); color: var(--ink); white-space: pre-wrap; overflow-wrap: anywhere; font-size: 15px; line-height: 1.5; }
.pq-item:hover .pq-bubble { border-color: var(--muted); }
.pq-bubble[data-files]::after { content: ''; display: inline-block; width: 13px; height: 13px; margin-left: 6px; vertical-align: -2px; background: currentColor; opacity: .6; -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M21 11.5 12.3 20.2a5 5 0 0 1-7.1-7.1l9-9a3.3 3.3 0 0 1 4.7 4.7l-9 9a1.7 1.7 0 0 1-2.4-2.4l8.3-8.3'/%3E%3C/svg%3E") center / contain no-repeat; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M21 11.5 12.3 20.2a5 5 0 0 1-7.1-7.1l9-9a3.3 3.3 0 0 1 4.7 4.7l-9 9a1.7 1.7 0 0 1-2.4-2.4l8.3-8.3'/%3E%3C/svg%3E") center / contain no-repeat; }
.pq-act { padding: 0 6px 0 0; border: 0; background: transparent; color: var(--accent-text); font: inherit; font-size: 12px; font-weight: 600; cursor: pointer; white-space: nowrap; }
.pq-act.pq-discard { color: var(--muted); }
.pq-act:hover:not(:disabled) { text-decoration: underline; }
.pq-act:disabled { opacity: .5; cursor: default; }
.pq-notice { padding-right: 6px; font-size: 12px; color: var(--muted); text-align: right; }

/* ---- Settings page: the units strip, the create settings as sc-rows with a number field, and browser scroll controls ---- */
.us-page { gap: 10px; }
.us-page select { cursor: pointer; }
#scroll-controls, #joystick-controls { width: 110px; flex: 0 0 110px; }
#scroll-controls-status:empty { display: none; }
.us-units button[aria-pressed="true"] { background: var(--accent-soft); color: var(--accent-text); }
.us-number-control { display: flex; align-items: center; gap: 8px; flex: 0 0 auto; }
.us-number-unit { min-width: 12px; color: var(--muted); font-size: 12px; }
.us-number-control input { width: 82px; height: 26px; padding: 0 8px; border: 1px solid var(--line); border-radius: 7px; background: var(--bg); color: var(--ink); font: inherit; font-size: 12px; font-variant-numeric: tabular-nums; }
.us-number-control input:focus { outline: none; border-color: var(--accent-text); }
.us-sub { font-size: 11px; line-height: 1.4; color: var(--muted); }
/* Model detail (settings.js) on the View settings page's Render section: the row carries the name and the note, the
   range under it at full width whatever the panel's width, its ends as words under the track, in the section sweep's look. */
.sc-detail-row { min-height: 24px; }
.sc-detail-control { display: flex; flex-direction: column; gap: 2px; margin-top: -4px; flex: 0 0 auto; }
.sc-detail-ends { display: flex; justify-content: space-between; gap: 8px; font-size: 10.5px; color: var(--muted); }
.sc-detail { width: 100%; height: 18px; margin: 0; accent-color: var(--range-accent); cursor: pointer; }
.sc-detail:disabled { cursor: default; opacity: .55; }

/* ---- Cloud tab (cloud-group.js): the device group's invite code and Join, the group's card, what arrived ---- */
.cg-page { gap: 12px; }
.cg-note, .cg-text { font-size: 12.5px; line-height: 1.45; color: var(--muted); }
.cg-heading { font-size: 13px; font-weight: 600; color: var(--ink); }
.cg-field { display: flex; flex-direction: column; gap: 5px; }
.cg-label { font-size: 12px; color: var(--muted); }
.cg-code { height: 34px; padding: 0 10px; border: 1px solid var(--line); border-radius: 7px; background: var(--panel); color: var(--ink); font: inherit; font-size: 13.5px; letter-spacing: .12em; text-transform: uppercase; }
.cg-code::placeholder { color: var(--muted); letter-spacing: 0; text-transform: none; }
.cg-code:focus { outline: none; border-color: var(--accent-text); }
.cg-error { font-size: 12.5px; line-height: 1.45; color: var(--amber); }
.cg-primary { display: inline-flex; align-items: center; justify-content: center; height: 32px; padding: 0 16px; border: 1px solid var(--accent); border-radius: 7px; background: var(--accent); color: #fff; font: inherit; font-size: 13px; font-weight: 600; cursor: pointer; transition: filter .15s ease, opacity .15s ease; }
.cg-primary:hover:not(:disabled), .cg-primary:focus-visible { filter: brightness(1.06); outline: none; }
.cg-primary:disabled { opacity: .5; cursor: default; }
.cg-manage { font-size: 11.5px; color: var(--muted); }
.cg-manage a { color: var(--accent-text); }
.cg-card { display: flex; align-items: center; gap: 12px; padding: 10px 12px; border: 1px solid var(--line); border-radius: 9px; background: var(--panel-2); }
.cg-card-glyph { flex: 0 0 auto; width: 36px; height: 36px; display: grid; place-items: center; border-radius: 9px; border: 1px solid var(--line); background: var(--panel); color: var(--accent-text); }
.cg-card-glyph svg { width: 20px; height: 20px; }
.cg-card-name { flex: 1 1 auto; min-width: 0; font-size: 14px; font-weight: 600; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cg-caption-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.cg-caption { font-size: 11px; font-weight: 600; letter-spacing: .07em; text-transform: uppercase; color: var(--muted); }
.cg-caption-row .sh-textbtn { font-size: 12px; }
.cg-checking { font-size: 12px; color: var(--muted); }
.cg-arrivals { display: flex; flex-direction: column; gap: 1px; margin: -4px -8px 0; }
.cg-arrival { display: flex; align-items: center; gap: 10px; min-height: 44px; padding: 4px 8px; border-radius: 7px; }
.cg-arrival:hover { background: var(--chat-hover, rgba(127,127,127,.08)); }
.cg-arrival-glyph { flex: 0 0 auto; width: 32px; height: 32px; display: grid; place-items: center; border-radius: 7px; border: 1px solid var(--line); background: var(--panel-2); color: var(--muted); }
.cg-arrival-glyph svg { width: 16px; height: 16px; }
.cg-arrival-who { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.cg-arrival-name { font-size: 13px; font-weight: 500; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cg-arrival-meta { font-size: 11.5px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cg-arrival .sh-textbtn { flex: 0 0 auto; font-size: 12px; }
.cg-empty { font-size: 12.5px; color: var(--muted); }
.cg-foot { margin-top: auto; display: flex; flex-direction: column; gap: 12px; }
.cg-leave { display: inline-flex; align-items: center; gap: 6px; height: 30px; padding: 0 12px; font-size: 12.5px; }
.cg-leave svg { width: 14px; height: 14px; }

/* ---- Share tab (share.js): Collaborate with people, the temporary meeting form, the link, the people rows ---- */
.sh-page { gap: 10px; }
.sh-page [hidden] { display: none; }
.sh-empty { display: flex; flex-direction: column; gap: 14px; }
.sh-intro { display: flex; flex-direction: column; align-items: center; gap: 10px; padding: 26px 14px 6px; text-align: center; }
.sh-intro .header-btn { display: inline-flex; align-items: center; gap: 6px; height: 28px; padding: 0 10px; margin-top: 4px; border-color: var(--accent); background: var(--accent); color: var(--accent-ink); font-size: 12px; font-weight: 600; }
.sh-intro .header-btn svg { width: 13px; height: 13px; }
.sh-form { display: flex; flex-direction: column; gap: 6px; padding: 10px; border: 1px dashed var(--line); border-radius: 9px; }
.sh-temp { font-size: 10.5px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--amber); }
.sh-form input { height: 30px; padding: 0 10px; border: 1px solid var(--line); border-radius: 7px; background: var(--bg); color: var(--ink); font: inherit; font-size: 13px; }
.sh-form input:focus { outline: none; border-color: var(--accent-text); }
.sh-form input::placeholder { color: var(--muted); }
.sh-form .header-btn { height: 30px; font-size: 12.5px; font-weight: 600; }
.sh-connecting { display: flex; align-items: center; gap: 10px; padding: 12px 4px; font-size: 12.5px; color: var(--muted); }
.sh-connecting .header-btn { margin-left: auto; }
.sh-shared { display: flex; flex-direction: column; gap: 8px; flex: 1 1 auto; min-height: 0; }
.sh-link { display: flex; align-items: center; gap: 6px; }
.sh-link-field { flex: 1 1 auto; min-width: 0; display: flex; align-items: center; gap: 8px; height: 30px; padding: 0 10px; border: 1px solid var(--line); border-radius: 7px; background: var(--bg); color: var(--ink); font-size: 12.5px; }
.sh-link-field svg { width: 13px; height: 13px; color: var(--muted); flex: 0 0 auto; }
.sh-link-text { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sh-copy { display: inline-flex; align-items: center; gap: 5px; height: 30px; padding: 0 10px; font-size: 12.5px; font-weight: 600; }
.sh-copy svg { width: 13px; height: 13px; color: var(--muted); }
.sh-copy.is-copied { border-color: var(--accent-text); color: var(--accent-text); background: var(--accent-soft); }
.sh-copy.is-copied svg { color: var(--accent-text); }
.sh-sub { font-size: 11px; line-height: 1.4; color: var(--muted); }
.sh-reconnecting { display: flex; align-items: center; gap: 8px; padding: 6px 8px; border: 1px solid var(--amber); border-radius: 7px; font-size: 12px; color: var(--ink); }
.sh-list { display: flex; flex-direction: column; gap: 2px; min-height: 0; overflow-y: auto; }
.sh-row { display: flex; align-items: center; gap: 10px; min-height: 38px; padding: 4px 4px 4px 6px; border-radius: 6px; flex: 0 0 auto; }
.sh-row:hover { background: var(--active-item, rgba(127, 127, 127, .14)); }
.sh-avatar { flex: 0 0 auto; width: 26px; height: 26px; display: grid; place-items: center; border-radius: 50%; color: #fff; }
.sh-avatar svg { width: 14px; height: 14px; }
.sh-who { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.sh-name-line { font-size: 13px; font-weight: 500; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sh-row[data-me] .sh-name-line { font-weight: 600; }
.sh-you { font-weight: 400; color: var(--muted); }
.sh-role { font-size: 11px; color: var(--muted); }
.sh-icon { display: inline-grid; place-items: center; width: 24px; height: 24px; padding: 0; border: 0; border-radius: 5px; background: transparent; color: var(--muted); cursor: pointer; }
.sh-icon svg { width: 15px; height: 15px; }
.sh-row:hover button.sh-icon, .sh-icon:focus-visible { color: var(--ink); outline: none; }
button.sh-icon:hover { background: var(--panel); }
.sh-gather { display: inline-flex; align-items: center; gap: 5px; height: 24px; padding: 0 8px; font-size: 11.5px; }
.sh-gather svg { width: 12px; height: 12px; color: var(--muted); }
.sh-spacer { flex: 1 1 auto; }
.sh-leave { display: flex; align-items: center; justify-content: center; gap: 8px; }
.sh-leave svg { width: 15px; height: 15px; }
.rail-tab { position: relative; }
.rail-dot { position: absolute; right: 7px; top: 6px; width: 7px; height: 7px; border-radius: 50%; background: var(--accent); box-shadow: 0 0 0 2px var(--panel); }
.rail-dot[data-state="connecting"], .rail-dot[data-state="failed"] { background: var(--amber); }
.rail-dot[hidden] { display: none; }
/* The Import & export entry's importing state: the app's ring, 30 px, turning around the glyph itself (imports.js). */
.rail-ring { position: absolute; left: 50%; top: 50%; width: 30px; height: 30px; margin: -15px 0 0 -14px; pointer-events: none; }
.rail-ring[hidden] { display: none; }
.rail-ring .ring { display: block; }

/* Resource reports remain readable on narrow drawers; status text never replaces the retained evidence. */
.storage-actions, .resource-diagnostics-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.resource-diagnostic { margin-top: 10px; border-top: 1px solid var(--line); padding-top: 8px; }
.resource-diagnostic summary { cursor: pointer; font-size: 12px; overflow-wrap: anywhere; }
.resource-diagnostic summary > div { color: var(--muted); font-size: 11px; margin-top: 3px; }
.resource-diagnostic pre { font: 11px/1.5 ui-monospace, Consolas, monospace; white-space: pre-wrap; overflow-wrap: anywhere; }
.resource-diagnostic.has-error summary { color: var(--danger); }
#resource-diagnostics-result:empty { display: none; }

/* ---- Share tab, voice and the link (share.js): the card, the access chip and its menu, the cloud and voice lines, the mics ---- */
.sh-textbtn { padding: 0; border: 0; background: transparent; color: var(--accent-text); font: inherit; font-size: inherit; font-weight: 600; cursor: pointer; white-space: nowrap; }
.sh-textbtn:hover { text-decoration: underline; }
.sh-intro .sh-share:disabled { border-color: var(--line); background: transparent; color: var(--muted); cursor: default; }
.sh-signin { font-size: 11.5px; color: var(--muted); }
.sh-notice { padding: 6px 8px; border: 1px solid var(--amber); border-radius: 7px; font-size: 11.5px; line-height: 1.4; color: var(--ink); overflow-wrap: anywhere; }
.sh-card { display: flex; flex-direction: column; gap: 10px; padding: 12px; border: 1px solid var(--line); border-radius: 10px; background: var(--panel-2); }
.sh-card-head { display: flex; align-items: center; justify-content: space-between; }
.sh-card-title { font-size: 13px; font-weight: 600; color: var(--ink); }
.sh-card-close { color: var(--muted); }
.sh-card-close:hover { color: var(--ink); }
.sh-card-q { font-size: 12px; color: var(--ink); }
.sh-seg button { display: flex; align-items: center; justify-content: center; gap: 6px; height: 26px; padding: 0; color: var(--muted); font-size: 12px; font-weight: 500; }
.sh-seg button svg { width: 12px; height: 12px; }
.sh-seg button[aria-pressed="true"] { background: var(--accent-soft); color: var(--accent-text); font-weight: 600; }
.sh-card-text { font-size: 11px; line-height: 1.4; color: var(--muted); }
.sh-card-foot { display: flex; justify-content: flex-end; padding-top: 2px; }
.sh-card-foot .header-btn { display: inline-flex; align-items: center; gap: 6px; height: 26px; padding: 0 10px; border-color: var(--accent); background: var(--accent); color: var(--accent-ink); font-size: 12px; font-weight: 600; }
.sh-card-foot .header-btn svg { width: 12px; height: 12px; }
.sh-access { position: relative; display: flex; align-items: center; }
.sh-chip { display: inline-flex; align-items: center; gap: 6px; max-width: 100%; height: 26px; padding: 0 6px 0 8px; border: 1px solid var(--line); border-radius: 6px; background: transparent; color: var(--ink); font: inherit; font-size: 12px; white-space: nowrap; cursor: pointer; }
.sh-chip:hover:not(:disabled) { background: var(--active-item, rgba(127, 127, 127, .14)); }
.sh-chip:disabled { cursor: default; padding-right: 9px; }
.sh-chip:disabled .sh-chip-chevron { display: none; }
.sh-chip[aria-expanded="true"] { border-color: var(--accent-text); background: var(--accent-soft); }
.sh-chip-glyph, .sh-chip-chevron { display: inline-flex; color: var(--muted); }
.sh-chip-glyph svg { width: 13px; height: 13px; }
.sh-chip-chevron svg { width: 11px; height: 11px; }
.sh-chip-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.sh-menu { right: auto; left: 0; bottom: auto; top: calc(100% + 6px); min-width: 260px; max-width: 292px; }
.sh-menu button { align-items: flex-start; padding: 7px 8px; }
.sh-menu button > svg { margin-top: 2px; }
/* a two-line row (title, then its line in muted) lands at about 40px, the picker's one-line rows at 34px */
.sh-menu button { padding: 3px 8px; }
.sh-menu-body { display: flex; flex-direction: column; gap: 0; white-space: normal; }
.sh-menu-title { font-size: 12.5px; line-height: 1.4; color: var(--ink); }
.sh-menu-text { font-size: 11px; line-height: 1.3; color: var(--muted); }
.sh-menu .vb-check { margin-top: 2px; }
.sh-cloud, .sh-viewing, .sh-voice { display: flex; align-items: center; gap: 6px; min-height: 20px; font-size: 11.5px; line-height: 1.35; color: var(--muted); white-space: nowrap; overflow: hidden; }
.sh-cloud-glyph, .sh-voice-lead { display: inline-flex; flex: 0 0 auto; }
.sh-cloud-glyph svg, .sh-voice-lead svg { width: 13px; height: 13px; }
.sh-cloud-text, .sh-voice-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.sh-cloud[data-kind="failed"] .sh-cloud-glyph, .sh-cloud[data-kind="failed"] .sh-cloud-text { color: var(--amber); }
.sh-voice { padding: 0 6px; flex: 0 0 auto; }
.sh-voice[data-kind="unsupported"] { white-space: normal; }
.sh-voice[data-kind="unsupported"] .sh-voice-text { white-space: normal; }
.sh-voice[data-kind="error"] .sh-voice-text { color: var(--ink); }
.sh-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--amber); margin: 0 2px; flex: 0 0 auto; }
.sh-people { position: relative; display: flex; flex-direction: column; gap: 2px; min-height: 0; }
.sh-mic svg { width: 15px; height: 15px; }
.sh-mic[data-mic="speaking"], .sh-mic-btn[data-mic="speaking"] { color: var(--accent-text); }
span.sh-mic { cursor: default; }
.sh-micsplit { height: 28px; }
.sh-micsplit > button { position: relative; }
.sh-mic-btn[aria-pressed="true"] { background: var(--accent-soft); color: var(--accent-text); }
.sh-mic-btn[aria-pressed="true"]:hover:not(:disabled) { background: color-mix(in srgb, var(--accent) 24%, transparent); }
.sh-warn { position: absolute; right: 1px; bottom: 1px; width: 11px; height: 11px; line-height: 0; }
.sh-warn svg { width: 11px; height: 11px; }
.sh-role.is-warn { color: var(--amber); }
.sh-picker { right: 4px; left: auto; bottom: auto; top: 0; }
.sh-picker-note { padding: 6px 8px 8px; font-size: 11px; line-height: 1.4; color: var(--muted); white-space: normal; }

/* ---- Front view and its views menu (the Navigate group): two buttons in the palette's manner, no box, no hairline, no
   line - the glyph's hit area is 32px with the drawing three units right of centre, the chevron's 12px, so the pair reads
   as one control with two halves. The menu is the voice bar's picker opening downward, its glyphs in ink at 18px. ---- */
.tool-split { position: relative; display: flex; align-items: stretch; }
.tool-split .tool-front { width: 32px; padding-left: 6px; }
.tool-split .tool-chevron { width: 12px; }
.tool-split .tool-chevron .tool-svg { width: 12px; height: 12px; }
#views-menu { left: 0; right: auto; bottom: auto; top: calc(100% + 4px); min-width: 180px; }
#views-menu button svg { width: 18px; height: 18px; color: var(--ink); }
#views-menu .views-rule { height: 1px; margin: 3px 4px; background: var(--line); }
#views-saved { display: flex; flex-direction: column; gap: 1px; } /* the saved viewpoints: a rule, then a camera glyph and the name per row */
#views-menu .views-go { flex: 0 0 auto; display: inline-flex; transform: rotate(-90deg); }
#views-menu .views-go svg { width: 11px; height: 11px; color: var(--muted); }

/* ---- Import & export (transfer.js): the two panes, the format rows with their mono chips, the status line ---- */
.tx-pane { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
.tx-pane[hidden] { display: none; }
.tx-empty { flex: 1 1 auto; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px; padding: 0 24px 40px; text-align: center; }
.tx-list { display: flex; flex-direction: column; gap: 2px; padding: 6px 8px 0; }
.tx-row { display: flex; align-items: center; gap: 10px; min-height: 44px; padding: 6px 8px 6px 10px; border-radius: 6px; }
.tx-row:hover { background: var(--active-item, rgba(127, 127, 127, .14)); }
.tx-row.is-soon:hover { background: transparent; }
.tx-tag { flex: 0 0 auto; display: inline-grid; place-items: center; width: 38px; height: 22px; border: 1px solid var(--line); border-radius: 5px; font: 600 10.5px/1 ui-monospace, Consolas, monospace; letter-spacing: .04em; color: var(--ink); }
.tx-who { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.tx-name { font-size: 13px; font-weight: 500; color: var(--ink); }
.tx-text { font-size: 11px; line-height: 1.35; color: var(--muted); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.tx-row.is-soon .tx-name, .tx-row.is-soon .tx-tag { color: var(--muted); }
.tx-row.is-soon .tx-tag { opacity: .6; }
.tx-export { height: 26px; padding: 0 10px; border-radius: 6px; font-size: 12px; font-weight: 600; }
.tx-status { display: flex; align-items: center; gap: 6px; min-height: 22px; margin: 8px 18px 0; font-size: 11.5px; line-height: 1.35; color: var(--muted); white-space: nowrap; overflow: hidden; }
.tx-status-lead { display: inline-flex; flex: 0 0 auto; }
.tx-status-lead svg { width: 13px; height: 13px; }
.tx-status-text { flex: 0 0 auto; }
.tx-status-sub { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.tx-status[data-kind="running"] .tx-status-text, .tx-status[data-kind="done"] .tx-status-text { color: var(--ink); }
.tx-status[data-kind="done"] .tx-status-lead { color: var(--accent-text); }
.tx-status[data-kind="failed"] .tx-status-text { color: var(--amber); }
/* Failure details must remain readable at narrow drawer widths, including long filenames or URLs. */
.tx-status[data-kind="failed"] { display: block; white-space: normal; overflow: visible; overflow-wrap: anywhere; }
.tx-status[data-kind="failed"] .tx-status-lead, .tx-status[data-kind="failed"] .tx-status-text { margin-right: 6px; }
.tx-status[data-kind="failed"] .tx-status-sub { overflow: visible; text-overflow: clip; }
.tx-status[data-kind="failed"] .tx-status-action { margin-left: 6px; }
/* what an export is, legally (agent-terms.js EXPORT_NOTICE): a muted paragraph under the status line, the Terms link in it */
.tx-legal { margin: 10px 18px 0; font-size: 11px; line-height: 1.4; color: var(--muted); }
.tx-legal a, .ai-notice a { color: var(--accent-text); font-weight: 600; text-decoration: none; }
.tx-legal a:hover, .ai-notice a:hover { text-decoration: underline; }

/* ---- the Import pane (imports.js): the list, a file's details, the drop zone, the placing banner ----
   The list: heading row with the count and the sort choice, the search field and the kind choice, then the rows -
   thumbnail, name with its kind chip, one line of facts, the mark at the right (a dot until opened, "in scene", a
   failure), the chevron on hover. Past about 480 px of pane the rows flow into two columns (a container query on the
   pane). The details keep one column: back, name, delete; the preview; the facts on two fixed lines; the controls with
   their labels beside them; the two placement blocks, a rule between them. The choices are native selects in the
   composer's chrome. */
.tx-pane[data-pane="import"] { container-type: inline-size; overflow: hidden auto; }
.im-list, .im-details { display: flex; flex-direction: column; min-width: 0; padding: 12px 18px 16px; }
.im-head { display: flex; align-items: center; gap: 8px; min-height: 26px; min-width: 0; }
.im-head .drawer-heading { margin: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.im-count { flex: 1 1 auto; min-width: 0; font-size: 11.5px; color: var(--muted); white-space: nowrap; }
.im-sort { flex: 0 1 auto; min-width: 0; max-width: 55%; }
.im-sort, .im-kind, .im-version, .im-units, .im-axis {
  height: 26px; padding: 0 24px 0 8px; border: 1px solid var(--line); border-radius: 7px; background: var(--bg); color: var(--ink);
  font: inherit; font-size: 12px; cursor: pointer; appearance: none; -webkit-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%235c6d66' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 7px center; background-size: 11px;
}
.im-sort:focus, .im-kind:focus, .im-version:focus, .im-units:focus, .im-axis:focus { outline: none; border-color: var(--accent-text); }
.im-sort:disabled, .im-kind:disabled, .im-version:disabled, .im-units:disabled, .im-axis:disabled { opacity: .55; cursor: default; }
.im-tools { display: flex; align-items: center; gap: 8px; margin-top: 10px; }
.im-search { flex: 1 1 auto; min-width: 0; height: 28px; }
.im-rows { display: grid; grid-template-columns: 1fr; gap: 2px; margin: 10px -8px 0; }
@container (min-width: 480px) { .im-rows { grid-template-columns: 1fr 1fr; column-gap: 8px; } }
.im-row { display: flex; align-items: center; gap: 10px; min-width: 0; min-height: 56px; padding: 6px 8px; border-radius: 7px; overflow: hidden; cursor: pointer; }
.im-row:hover, .im-row:focus-visible { background: var(--active-item, rgba(127, 127, 127, .14)); outline: none; }
.im-thumb { position: relative; flex: 0 0 auto; width: 44px; height: 44px; display: grid; place-items: center; border-radius: 6px; background: var(--panel-2, var(--bg)); overflow: hidden; }
.im-thumb .im-pic { width: 100%; height: 100%; object-fit: cover; }
.im-glyph { display: inline-flex; color: var(--muted); }
.im-glyph svg { width: 20px; height: 20px; }
.im-thumb-ring { position: absolute; inset: 0; display: grid; place-items: center; }
.im-thumb-ring .ring { display: block; width: 30px; height: 30px; }
.im-who { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.im-name { display: flex; align-items: center; gap: 6px; min-width: 0; }
.im-title { font-size: 13px; font-weight: 500; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.im-name .tx-tag, .im-dname .tx-tag { width: auto; min-width: 34px; height: 18px; padding: 0 5px; font-size: 10px; }
.im-facts { font-size: 11px; line-height: 1.35; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.im-facts.is-failed, .im-failed { color: var(--amber); }
.im-mark { flex: 0 0 auto; display: inline-flex; align-items: center; gap: 6px; font-size: 11px; color: var(--muted); }
.im-inscene { display: inline-flex; align-items: center; gap: 3px; color: var(--accent-text); }
.im-inscene svg { width: 12px; height: 12px; }
.im-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--accent); }
.im-chev { flex: 0 0 auto; display: inline-flex; color: var(--muted); opacity: 0; transition: opacity .15s ease; }
.im-chev svg { width: 14px; height: 14px; }
.im-row:hover .im-chev, .im-row:focus-visible .im-chev { opacity: 1; }
.im-note { margin-top: 10px; font-size: 11.5px; color: var(--muted); }
.im-empty { display: flex; flex-direction: column; align-items: center; gap: 8px; padding: 32px 12px 24px; text-align: center; font-size: 13px; color: var(--muted); }
.im-empty-sub { font-size: 11.5px; line-height: 1.4; max-width: 300px; }
.im-drop { display: flex; flex-direction: column; align-items: center; gap: 4px; margin-top: 14px; padding: 14px 12px; border: 1px dashed var(--line); border-radius: 9px; color: var(--muted); font-size: 12px; text-align: center; cursor: pointer; transition: border-color .15s ease, background .15s ease; }
.im-drop svg { width: 18px; height: 18px; margin-bottom: 2px; }
.im-drop:hover, .im-drop.is-lit { border-color: var(--accent-text); color: var(--accent-text); background: color-mix(in srgb, var(--accent) 8%, transparent); }
.im-drop-sub { font-size: 11px; color: var(--muted); }
.im-dhead { display: flex; align-items: center; gap: 8px; min-height: 28px; }
.im-back { display: inline-flex; align-items: center; gap: 4px; padding: 4px 8px 4px 5px; }
.im-back svg { width: 13px; height: 13px; }
.im-dname { flex: 1 1 auto; min-width: 0; display: flex; align-items: center; gap: 6px; }
.im-dname .im-title { font-size: 14px; font-weight: 600; }
.im-delete { flex: 0 0 auto; display: inline-grid; place-items: center; width: 26px; height: 26px; border: 0; border-radius: 6px; background: transparent; color: var(--muted); cursor: pointer; }
.im-delete:hover, .im-delete:focus-visible { color: var(--danger); background: var(--active-item, rgba(127, 127, 127, .14)); outline: none; }
.im-delete svg { width: 15px; height: 15px; }
.im-confirm { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 8px; padding: 8px 10px; border: 1px solid var(--amber); border-radius: 7px; font-size: 12px; line-height: 1.4; }
.im-confirm span { display: inline-flex; align-items: center; gap: 10px; margin-left: auto; }
.im-preview { position: relative; display: grid; place-items: center; width: 100%; max-width: 320px; aspect-ratio: 4 / 3; margin: 12px auto 0; border-radius: 8px; background: var(--panel-2, var(--bg)); overflow: hidden; }
.im-preview .im-pic { width: 100%; height: 100%; object-fit: contain; }
.im-preview .im-glyph svg { width: 40px; height: 40px; }
.im-dfacts { display: flex; flex-direction: column; gap: 2px; margin-top: 10px; font-size: 12px; line-height: 1.4; color: var(--muted); }
.im-dfacts div { min-height: 17px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.im-dfacts div:first-child { color: var(--ink); font-weight: 500; }
.im-rule { width: 100%; height: 0; margin: 12px 0; border: 0; border-top: 1px solid var(--line); }
.im-ctrl { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; margin-top: 8px; font-size: 12px; } /* a very narrow pane wraps Up axis under Units */
.im-ctrl label { flex: 0 0 auto; width: 56px; color: var(--muted); text-align: right; }
.im-ctrl label + label { width: auto; margin-left: 6px; }
.im-ctrl select { flex: 0 1 auto; min-width: 0; }
.im-ctrl .im-units, .im-ctrl .im-axis { flex: 1 1 0; min-width: 58px; max-width: 120px; } /* outranks .im-ctrl select: never so narrow that the chosen unit is hidden */
.im-version { width: 100%; }
.im-width { width: 82px; height: 26px; padding: 0 8px; border: 1px solid var(--line); border-radius: 7px; background: var(--bg); color: var(--ink); font: inherit; font-size: 12px; }
.im-width:focus { outline: none; border-color: var(--accent-text); }
.im-unit { color: var(--muted); }
.im-tall { color: var(--muted); }
.im-update-row { margin: 8px 0 0 64px; font-size: 12px; }
.im-update-row .sh-textbtn { white-space: normal; text-align: left; }
.im-warning { margin: 8px 0 0 64px; font-size: 11.5px; line-height: 1.4; color: var(--amber); }
.im-failed-box { margin-top: 8px; font-size: 12px; line-height: 1.5; }
.im-failed-box > div { margin-top: 6px; }
.im-muted { color: var(--muted); }
.im-block { display: flex; flex-direction: column; gap: 6px; }
.im-block-head { font-size: 12.5px; font-weight: 600; color: var(--ink); }
.im-block-text { font-size: 11.5px; line-height: 1.4; color: var(--muted); }
.im-block-row { display: flex; gap: 8px; margin-top: 2px; }
.im-block-row .header-btn { flex: 1 1 0; height: 30px; font-size: 12px; font-weight: 600; }
.im-primary { display: inline-flex; align-items: center; justify-content: center; gap: 8px; width: 100%; height: 30px; margin-top: 2px; padding: 0 14px; border: 1px solid var(--accent); border-radius: 7px; background: var(--accent); color: #fff; font: inherit; font-size: 12.5px; font-weight: 600; cursor: pointer; transition: background .15s ease, color .15s ease; }
.im-primary svg { width: 14px; height: 14px; }
.im-primary:hover:not(:disabled), .im-primary:focus-visible { filter: brightness(1.06); outline: none; }
.im-primary:disabled { border-color: var(--line); background: var(--panel-2, var(--bg)); color: var(--muted); cursor: default; }
.im-primary[aria-pressed="true"] { background: var(--accent-soft); color: var(--accent-text); }
#placing-banner { position: absolute; top: 10px; left: 50%; transform: translateX(-50%); z-index: 3; display: flex; align-items: center; gap: 10px; max-width: calc(100% - 20px); padding: 5px 5px 5px 12px; background: var(--panel); color: var(--ink); border: 1px solid var(--accent-text); border-radius: 9px; box-shadow: 0 8px 24px rgba(0, 0, 0, .18); font-size: 12.5px; white-space: nowrap; }
#placing-banner[hidden] { display: none; }
.pb-glyph { display: inline-flex; flex: 0 0 auto; color: var(--accent-text); }
.pb-glyph svg { width: 16px; height: 16px; }
.pb-text { font-weight: 600; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.pb-hint { color: var(--muted); }

/* ---- Group chat (group-chat.js) ---- */
/* The two tabs under the chat header, in the idiom of the chats list's former Chats | Scenes tabs: the open one in ink
   with the accent line, a 6px dot on the other when it has messages you have not seen. */
#chat-tabs { flex: 0 0 auto; display: flex; margin: 0 18px; border-bottom: 1px solid var(--line); }
#chat-tabs[hidden] { display: none; }
.chat-tab {
  flex: 1 1 0; display: inline-flex; align-items: center; justify-content: center; gap: 6px; padding: 6px 0 7px; margin-bottom: -1px;
  border: 0; border-bottom: 2px solid transparent; background: transparent; color: var(--muted); font: inherit; font-size: 12.5px; line-height: 1.3;
  cursor: pointer; transition: color .15s ease;
}
.chat-tab:hover, .chat-tab:focus-visible { color: var(--ink); outline: none; }
.chat-tab[aria-selected="true"] { color: var(--ink); font-weight: 600; border-bottom-color: var(--tool-line); }
.tab-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--accent); }
.tab-dot[hidden] { display: none; }
/* The group pane takes the agent transcript's and composer's place while its tab is open. */
#group-chat { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
#group-chat[hidden] { display: none; }
#chat.group-chat-active > #chat-metrics, #chat.group-chat-active > #diagnostic-status, #chat.group-chat-active > #tutorial-panel,
#chat.group-chat-active > #messages, #chat.group-chat-active > #prompt-queue, #chat.group-chat-active > #composer { display: none; }
/* the transcript: the agent transcript's column, bottom-anchored; a day label opens each day */
.gc-log { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 20px 18px; display: flex; flex-direction: column; gap: 14px; }
.gc-log > :first-child { margin-top: auto; }
.gc-day { align-self: stretch; color: var(--muted); font-size: 12.5px; border-top: 1px solid var(--line); padding: 12px 2px 0; }
.gc-day:first-child { border-top: 0; padding-top: 0; }
/* a run: one sender's consecutive messages under one sender line; mine right-aligned with no line */
.gc-run { display: flex; flex-direction: column; gap: 6px; max-width: 84%; }
.gc-run.other { align-self: flex-start; align-items: flex-start; }
.gc-run.me { align-self: flex-end; align-items: flex-end; }
.gc-who { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--muted); }
.gc-avatar { flex: 0 0 auto; width: 18px; height: 18px; display: grid; place-items: center; border-radius: 50%; color: #fff; font-size: 10px; font-weight: 600; line-height: 1; }
.gc-name { font-weight: 600; color: var(--ink); }
.gc-msg { position: relative; display: flex; flex-direction: column; gap: 6px; max-width: 100%; outline: none; }
.gc-run.me .gc-msg { align-items: flex-end; }
/* someone else's bubble is the agent transcript's second surface with a hairline, squared at the bottom left; mine is the
   user bubble squared at the bottom right, as in the agent chat */
.gc-bubble { position: relative; max-width: 100%; padding: 11px 15px; border-radius: 16px; white-space: pre-wrap; overflow-wrap: anywhere; transition: border-color .15s ease; }
.gc-run.other .gc-bubble { border: 1px solid var(--line); border-bottom-left-radius: 6px; background: var(--panel-2); color: var(--ink); }
.gc-run.other .gc-msg:hover .gc-bubble, .gc-run.other .gc-msg.is-open .gc-bubble { border-color: var(--muted); }
.gc-run.me .gc-bubble { border-bottom-right-radius: 6px; background: var(--user-bubble); color: var(--user-ink); }
.gc-msg.is-dim .gc-bubble { opacity: .55; }
.gc-edited { margin-left: 6px; font-size: 11px; color: var(--muted); }
.gc-text a { color: var(--accent-text); text-decoration: none; border-bottom: 1px solid color-mix(in srgb, var(--accent-text) 45%, transparent); word-break: break-all; }
/* the actions at the bubble's top edge under the pointer (or keyboard focus): React on theirs, Edit and Unsend on mine */
.gc-actions {
  position: absolute; top: -15px; right: 10px; z-index: 2; display: none; gap: 2px; padding: 2px;
  border: 1px solid var(--line); border-radius: 8px; background: var(--panel); box-shadow: 0 4px 14px rgba(0, 0, 0, .10);
}
.gc-run.me .gc-actions { right: auto; left: 10px; }
.gc-msg:hover .gc-actions, .gc-msg:focus-within .gc-actions, .gc-msg.is-open .gc-actions { display: flex; }
.gc-act { width: 26px; height: 26px; display: grid; place-items: center; padding: 0; border: 0; border-radius: 6px; background: transparent; color: var(--muted); cursor: pointer; }
.gc-act:hover, .gc-act:focus-visible, .gc-act[aria-expanded="true"] { background: var(--active-item, rgba(127, 127, 127, .14)); color: var(--ink); outline: none; }
.gc-act svg { width: 15px; height: 15px; }
/* the reaction picker above the strip, in the mic picker's chrome; the chips under the bubble, mine in the accent */
.gc-picker {
  position: absolute; top: -48px; right: 10px; z-index: 3; display: flex; gap: 2px; padding: 4px;
  border: 1px solid var(--line); border-radius: 8px; background: var(--panel); box-shadow: 0 10px 30px rgba(0, 0, 0, .18);
}
.gc-picker button { width: 32px; height: 32px; padding: 0; border: 0; border-radius: 6px; background: transparent; font-size: 18px; line-height: 1; cursor: pointer; }
.gc-picker button:hover, .gc-picker button:focus-visible, .gc-picker button[aria-pressed="true"] { background: var(--active-item, rgba(127, 127, 127, .14)); outline: none; }
.gc-reactions { display: flex; flex-wrap: wrap; gap: 6px; }
.gc-run.me .gc-reactions { justify-content: flex-end; }
.gc-react {
  display: inline-flex; align-items: center; gap: 5px; height: 24px; padding: 0 8px 0 7px; border: 1px solid var(--line); border-radius: 12px;
  background: var(--panel); color: var(--ink); font: inherit; font-size: 12px; cursor: pointer; transition: border-color .15s ease;
}
.gc-react > span:first-child { font-size: 13px; line-height: 1; }
.gc-react:hover:not(.is-static), .gc-react:focus-visible { border-color: var(--muted); outline: none; }
.gc-react[aria-pressed="true"] { border-color: var(--accent-text); background: var(--accent-soft); }
.gc-react.is-static { cursor: default; }
/* what a message carries: a render or a clip as the agent chat's frame, an agent message as a quote */
.gc-card {
  position: relative; display: block; width: 220px; max-width: 100%; margin: 0 0 8px; padding: 0; overflow: hidden;
  border: 1px solid var(--line); border-radius: 10px; background: var(--panel-2); color: var(--muted); font: inherit; cursor: pointer; transition: border-color .15s ease;
}
.gc-card img, .gc-card video { display: block; width: 100%; height: 100%; object-fit: cover; }
.gc-card:hover:not(:disabled), .gc-card:focus-visible { border-color: var(--accent-text); outline: none; }
.gc-card:disabled { cursor: default; }
.gc-card-empty { position: absolute; inset: 0; display: grid; place-items: center; font-size: 12.5px; }
.gc-quote { margin: 0 0 8px; padding: 2px 0 2px 10px; border-left: 2px solid var(--accent); }
.gc-quote-from { margin-bottom: 3px; font-size: 11px; font-weight: 600; letter-spacing: .07em; text-transform: uppercase; color: var(--muted); }
.gc-quote-text { font-size: 14px; line-height: 1.45; }
/* editing in place: the bubble becomes the input; the two quiet words under a bubble (Save · Cancel, Unsend · Keep) */
.gc-edit {
  width: 100%; min-width: 220px; resize: none; overflow: hidden; padding: 10px 14px; border: 1px solid var(--accent-text); border-radius: 16px; border-bottom-right-radius: 6px;
  background: var(--bg); color: var(--ink); font: inherit; line-height: 1.5;
}
.gc-edit:focus { outline: none; }
.gc-words { display: flex; gap: 12px; padding: 0 6px; font-size: 12px; color: var(--muted); }
.gc-words button { padding: 0; border: 0; background: transparent; color: var(--accent-text); font: inherit; font-size: 12px; font-weight: 600; cursor: pointer; white-space: nowrap; }
.gc-words button:hover, .gc-words button:focus-visible { text-decoration: underline; outline: none; }
.gc-words button.is-muted { color: var(--muted); }
.gc-words button.is-danger { color: var(--danger); }
/* before anyone has written; a notice from the relay over the composer */
.gc-empty { margin: auto; text-align: center; color: var(--muted); max-width: 260px; }
.gc-empty h2 { font-size: 15px; font-weight: 600; color: var(--ink); margin: 0 0 6px; }
.gc-empty p { margin: 0; font-size: 13px; }
.gc-notice { flex: 0 0 auto; padding: 0 18px 8px; font-size: 12px; color: var(--muted); }
.gc-notice[hidden] { display: none; }
/* the composer: the agent composer's chrome and box (.composer-box; #group-input shares #input's rules, the paperclip is a
   .composer-square and the arrow a .composer-send) */
.gc-composer { flex: 0 0 auto; display: flex; flex-direction: column; gap: 8px; padding: 14px; border-top: 1px solid var(--line); background: var(--panel-2); }
/* what was shared, waiting above the input as chips - a render with its thumbnail, an agent message as a quote chip */
.gc-staged { display: flex; flex-wrap: wrap; gap: 6px; }
.gc-staged[hidden] { display: none; }
.gc-chip { display: inline-flex; align-items: center; gap: 8px; max-width: 100%; height: 40px; padding: 0 6px 0 4px; border: 1px solid var(--line); border-radius: 8px; background: var(--panel); font-size: 12px; color: var(--ink); }
.gc-chip-thumb { flex: 0 0 auto; width: 32px; height: 32px; display: grid; place-items: center; border-radius: 5px; overflow: hidden; background: var(--panel-2); color: var(--accent-text); }
.gc-chip-thumb img { display: block; width: 100%; height: 100%; object-fit: cover; }
.gc-chip-thumb.is-quote { background: color-mix(in srgb, var(--accent) 16%, transparent); }
.gc-chip-thumb svg { width: 15px; height: 15px; }
.gc-chip-label { min-width: 0; max-width: 210px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.gc-chip-remove { width: 20px; height: 20px; display: grid; place-items: center; padding: 0; border: 0; border-radius: 5px; background: transparent; color: var(--muted); cursor: pointer; }
.gc-chip-remove:hover, .gc-chip-remove:focus-visible { background: var(--line); color: var(--ink); outline: none; }
.gc-chip-remove svg { width: 11px; height: 11px; }
/* the way in from the agent chat: the share glyph at a render card's caption end and at an agent message's top right,
   shown when the pointer is on the card or the message */
.gc-share-btn { flex: 0 0 auto; width: 22px; height: 22px; display: grid; place-items: center; padding: 0; border: 0; border-radius: 5px; background: transparent; color: var(--muted); cursor: pointer; opacity: 0; transition: opacity .15s ease; }
.gc-share-btn svg { width: 14px; height: 14px; }
.render-card:hover .gc-share-btn, .msg.agent:hover .gc-share-btn, .gc-share-btn:focus-visible, .gc-share-btn:hover { opacity: 1; }
.gc-share-btn:hover, .gc-share-btn:focus-visible { background: var(--active-item, rgba(127, 127, 127, .14)); color: var(--ink); outline: none; }
.msg.agent.has-share { position: relative; padding-right: 30px; }
.msg.agent .gc-share-btn { position: absolute; top: -2px; right: 0; }

/* History pages preserve the transcript anchor; media fetches are triggered only near the viewport. */
.gc-history { flex: 0 0 auto; align-self: center; margin: 8px; }
.gc-history[hidden] { display: none; }

/* ---- Group chat files (group-chat.js addFiles, chipHtml, renderSending) ---- */
/* the paperclip and the camera are .composer-square (the composer section); the pane rings its composer while files are
   dragged over it */
#render-btn[hidden] { display: none; } /* the hidden attribute has to beat the square's display, as it does for the mic button */
#render-btn[aria-pressed="true"] { border-color: var(--accent); background: var(--accent-soft); color: var(--accent-text); } /* a render request is staged */
#group-chat.is-drop .gc-composer, #chat.is-drop #composer { box-shadow: inset 0 0 0 2px var(--accent); } /* a file drag over the pane */
/* a chip's body: the name (with the size in muted for a file) and, while on its way, the bar under it */
.gc-sending { display: flex; flex-wrap: wrap; gap: 6px; }
.gc-sending[hidden] { display: none; }
.gc-chip.is-sending { height: 44px; padding-right: 10px; }
.gc-chip-body { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.gc-chip-size { color: var(--muted); }
.gc-bar { display: block; height: 3px; border-radius: 2px; background: var(--line); overflow: hidden; }
.gc-bar > span { display: block; height: 100%; border-radius: 2px; background: var(--accent); transition: width .2s ease; }
/* a file in a bubble: the glyph, the name and the size, a download arrow; pressing it saves the file */
.gc-file {
  display: flex; align-items: center; gap: 10px; width: 240px; max-width: 100%; margin: 0 0 8px; padding: 7px 10px 7px 7px;
  border: 1px solid var(--line); border-radius: 10px; background: var(--panel); color: var(--ink); font: inherit; text-align: left; cursor: pointer; transition: border-color .15s ease;
}
.gc-file:hover, .gc-file:focus-visible { border-color: var(--accent-text); outline: none; }
.gc-file:hover .gc-file-dl { color: var(--ink); }
.gc-file.is-busy { cursor: progress; }
.gc-file-glyph { flex: 0 0 auto; width: 32px; height: 32px; display: grid; place-items: center; border-radius: 6px; background: var(--panel-2); color: var(--muted); }
.gc-file-glyph svg { width: 16px; height: 16px; }
.gc-file-body { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.gc-file-name { font-size: 13px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.gc-file-size { font-size: 11.5px; color: var(--muted); }
.gc-file-dl { flex: 0 0 auto; color: var(--muted); }
.gc-file-dl svg { width: 15px; height: 15px; }
/* my run's time, where other people's sender line is */
.gc-run.me .gc-who { justify-content: flex-end; }
/* a message of mine still on its way after a moment: Sending… after its words, as the edited mark sits; it appears only
   once the store has taken longer than the eye expects, so a quick save never flashes it */
.gc-pending { margin-left: 6px; font-size: 11px; color: var(--muted); opacity: 0; animation: gc-pending-in .2s ease .8s forwards; }
@keyframes gc-pending-in { to { opacity: 1; } }

/* ---- Attachments in the agent chat (attachment-thumbs.js, app.js addUserMessage, agent-prompt-queue.js stage) ---- */
/* the files of a sent message: the group chat's chips under my bubble, on its side */
.msg-files { align-self: flex-end; max-width: 84%; display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 6px; margin-top: -8px; }
/* a queued message's chips inside its waiting bubble; a message on its way to the queue and the muted word under it */
.pq-files { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.pq-item.is-staging { grid-template-columns: minmax(0, 1fr); }
.pq-staging { justify-self: end; padding-right: 6px; font-size: 12px; color: var(--muted); }

/* Web section controls inherit the Scene panel's density. Hidden groups must not retain flex layout. */
/* Section card (scene-settings.js): the placement and direction strips, the horizontal/Face position field, the range through
   the model, Removes with Flip beside it, Place again, the picking hint; and the banner over the player (#section-banner),
   the History banner's place and shape, lighter, accent-bordered while the plane is live. */
.sc-section-controls { display: flex; flex-direction: column; gap: 10px; }
.sc-section-controls[hidden], .sc-section-directions[hidden], .sc-head .sc-section-adjust[hidden], .sc-section-sweep[hidden], .sc-section-removes-row[hidden], .sc-section-again-row[hidden], .sc-section-hint[hidden] { display: none; }
.sc-section-distance { display: flex; align-items: center; gap: 8px; color: var(--muted); font-size: 12px; }
.sc-section-offset { width: 88px; height: 28px; padding: 0 8px; border: 1px solid var(--line); border-radius: 7px; background: var(--bg); color: var(--ink); font: inherit; font-size: 12.5px; font-variant-numeric: tabular-nums; }
.sc-section-offset:disabled, .sc-section-range:disabled { opacity: .55; }
.sc-section-sweep { display: flex; flex-direction: column; gap: 2px; margin-top: -4px; }
.sc-section-range { width: 100%; height: 18px; margin: 0; accent-color: var(--range-accent); cursor: pointer; }
.sc-section-range:disabled { cursor: default; }
.sc-section-ends { display: flex; justify-content: space-between; font-size: 10.5px; color: var(--muted); }
.sc-section-removes { display: inline-flex; align-items: center; gap: 8px; font-size: 12.5px; color: var(--ink); white-space: nowrap; }
.sc-section-hint { padding: 8px 10px; border-radius: 7px; background: var(--panel-2); font-size: 11.5px; line-height: 1.4; color: var(--muted); }
.sc-section-controls .rv-strip button:focus-visible { outline: 2px solid var(--accent-text); outline-offset: 1px; }
#section-banner { position: absolute; top: 10px; left: 50%; transform: translateX(-50%); z-index: 3; display: flex; align-items: center; gap: 12px; max-width: calc(100% - 20px); padding: 5px 5px 5px 12px; background: var(--panel); color: var(--ink); border: 1px solid var(--line); border-radius: 9px; box-shadow: 0 8px 24px rgba(0, 0, 0, .18); font-size: 12.5px; line-height: 1.3; white-space: nowrap; }
#section-banner[hidden] { display: none; }
#section-banner.is-live { border-color: var(--accent-text); }
.sb-glyph { display: inline-flex; color: var(--muted); flex: 0 0 auto; }
#section-banner.is-live .sb-glyph { color: var(--accent-text); }
.sb-glyph svg { width: 16px; height: 16px; }
.sb-text { font-weight: 600; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
#unity-canvas.section-picking { cursor: crosshair; }

/* ---- first run: the welcome and shared-scene cards, the login card, the refusal ---- */
/* The first-visit welcome and the shared-scene card replace the centred placeholder and take the pane's width; the
   login card joins the transcript at its foot. Buttons are real buttons, disabled until the editor is writable. */
#empty.welcome, #empty.shared { max-width: none; width: 100%; margin: auto 0; text-align: left; display: flex; flex-direction: column; gap: 20px; color: var(--muted); }
#empty.welcome h2, #empty.shared h2 { font-size: 18px; line-height: 1.3; margin: 0 0 6px; }
#empty.welcome p, #empty.shared p { font-size: 13.5px; line-height: 1.5; }
/* Anchor the compact welcome near the top instead of centering it in the whole empty transcript. */
#empty.welcome { margin: 4px 0 auto; gap: 16px; flex: 0 0 auto; }
#empty.welcome h2 { font-size: 15px; margin-bottom: 6px; }
#empty.welcome p { font-size: 13px; }
.fr-welcome-options { border: 1px solid var(--line); border-radius: 9px; background: var(--panel-2); }
.fr-welcome-options > .fr-card { border: 0; }
.fr-login, .fr-welcome-options .fr-card .fr-btn { width: 100%; } /* one width for the rows of the welcome: Log in the box's, the demo the card's, as the samples' rows */
/* The welcome's Log in row holds the footer's own form once its button is pressed (app.js welcomeLogin): the form in
   place of the button, at the box's width, with the footer's type sizes over the welcome's paragraph rule. */
.fr-login-slot { display: flex; flex-direction: column; }
.fr-login-slot:has(> .ac-form:not([hidden])) > .fr-login { display: none; }
#empty .fr-login-slot p.ac-note, #empty .fr-login-slot p.ac-error { font-size: 11.5px; line-height: 1.4; }
/* The actual welcome node controls visibility, including transcript-only updates after a first send. */
#chat:has(#empty.welcome) #save-conversation { display: none; }
/* Demo and samples share one surface and heading inset; only the primary action carries the accent fill. */
.fr-samples { border-top: 1px solid var(--line); }
.fr-samples > summary { display: flex; align-items: center; gap: 10px; min-height: 44px; padding: 10px 12px; list-style: none; color: var(--ink); font-size: 13.5px; font-weight: 600; cursor: pointer; border-radius: 0 0 9px 9px; }
.fr-samples > summary span { flex: 1; }
.fr-samples > summary svg { flex: 0 0 auto; width: 14px; height: 14px; color: var(--muted); }
.fr-samples > summary:hover { background: var(--chat-hover, rgba(127,127,127,.08)); }
.fr-samples > summary:focus-visible { outline: 2px solid var(--accent-text); outline-offset: -2px; }
.fr-samples > summary::-webkit-details-marker { display: none; }
.fr-samples[open] > summary { border-radius: 0; }
.fr-samples[open] > summary svg { transform: rotate(90deg); }
.fr-samples > .fr-section { padding: 0 12px 12px; gap: 6px; }
.fr-samples .fr-starter { min-height: 36px; padding: 8px 10px; border-radius: 7px; background: var(--panel); font-size: 13px; }
.fr-section { display: flex; flex-direction: column; gap: 8px; }
.fr-starter { display: flex; align-items: center; gap: 10px; min-height: 44px; padding: 10px 12px; border: 1px solid var(--line); border-radius: 9px; background: var(--panel-2); color: var(--ink); font: inherit; font-size: 13.5px; line-height: 1.35; text-align: left; cursor: pointer; transition: border-color .15s ease; }
.fr-starter span { flex: 1 1 auto; }
.fr-starter svg { flex: 0 0 auto; width: 16px; height: 16px; color: var(--muted); }
.fr-starter:hover:not(:disabled), .fr-starter:focus-visible { border-color: var(--accent-text); outline: none; }
.fr-card { display: flex; flex-direction: column; gap: 10px; padding: 12px; border: 1px solid var(--line); border-radius: 9px; }
.fr-card.login { flex: 0 0 auto; border-color: var(--accent-text); background: var(--panel-2); box-shadow: 0 12px 32px rgba(0, 0, 0, .35); }
.fr-card-title { display: flex; align-items: center; gap: 8px; font-size: 13.5px; font-weight: 600; color: var(--ink); }
.fr-dot { flex: 0 0 auto; width: 7px; height: 7px; border-radius: 50%; background: var(--accent); }
.fr-meta { margin-left: auto; font-size: 12px; font-weight: 400; color: var(--muted); white-space: nowrap; }
.fr-card p { margin: 0; font-size: 13px; line-height: 1.5; color: var(--muted); }
.fr-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.fr-btn { display: inline-flex; align-items: center; justify-content: center; height: 32px; padding: 0 12px; border: 1px solid var(--line); border-radius: 7px; background: transparent; color: var(--ink); font: inherit; font-size: 12.5px; font-weight: 600; cursor: pointer; transition: border-color .15s ease, color .15s ease; }
.fr-btn:hover:not(:disabled), .fr-btn:focus-visible { border-color: var(--accent-text); outline: none; }
.fr-btn.primary { border-color: var(--accent); background: var(--accent); color: var(--accent-ink); }
.fr-btn.primary:hover:not(:disabled) { opacity: .9; }
.fr-starter:disabled, .fr-btn:disabled { opacity: .45; cursor: default; }
.fr-note { font-size: 12px; line-height: 1.45; color: var(--muted); }
.fr-live { font-size: 12.5px; color: var(--accent-text); }


/* The refusal card: the capability gate's verdict in place of the storage-error sentence. The loading veil behind it,
   #session-state's z so nothing paints over it; the address field shows only when the clipboard is unavailable. */
#boot-refused { position: absolute; inset: 0; z-index: 4; display: grid; place-items: center; padding: 32px; background: radial-gradient(120% 120% at 50% 40%, #112A27 0%, #0A1213 100%); color: #E8EEEC; } /* the veil stays dark in both themes, so its text is fixed light */
#boot-refused[hidden] { display: none; }
.br-card { display: flex; flex-direction: column; gap: 14px; width: min(480px, 100%); padding: 24px; border: 1px solid var(--line); border-radius: 12px; background: var(--panel); color: var(--ink); }
.br-glyph { width: 28px; height: 28px; color: var(--muted); }
.br-card h2 { margin: 0; font-size: 18px; font-weight: 600; line-height: 1.3; }
.br-card p { margin: 0; font-size: 13.5px; line-height: 1.5; color: var(--muted); }
#boot-refused-list { display: flex; flex-direction: column; gap: 10px; margin: 0; padding: 0; list-style: none; font-size: 13px; line-height: 1.45; color: var(--muted); }
#boot-refused-list[hidden] { display: none; }
#boot-refused-list li { display: flex; gap: 10px; align-items: flex-start; }
#boot-refused-list svg { flex: 0 0 auto; width: 18px; height: 18px; margin-top: 1px; color: var(--muted); }
#boot-refused-list li:first-child svg { color: var(--accent-text); }
#boot-refused-list strong { font-weight: 600; color: var(--ink); }
.br-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.br-actions .header-btn { display: inline-flex; align-items: center; height: 32px; padding: 0 12px; font-size: 12.5px; font-weight: 600; text-decoration: none; }
#boot-copy-status { font-size: 12px; color: var(--muted); }
#boot-link { width: 100%; height: 32px; padding: 0 10px; border: 1px solid var(--line); border-radius: 7px; background: var(--bg); color: var(--ink); font: inherit; font-size: 12.5px; }
#boot-link[hidden] { display: none; }
/* Selection bar (selection-bar.js): the verbs that apply to the Select tool's selection, over the player in the Section
   banner's shape; under it when both show. A refusal line wraps onto a second row inside the pill. */
#selection-bar { position: absolute; top: 10px; left: 50%; transform: translateX(-50%); z-index: 3; display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 4px 10px; max-width: calc(100% - 20px); padding: 5px 6px 5px 12px; background: var(--panel); color: var(--ink); border: 1px solid var(--line); border-radius: 9px; box-shadow: 0 8px 24px rgba(0, 0, 0, .18); font-size: 12.5px; line-height: 1.3; white-space: nowrap; }
#selection-bar[hidden] { display: none; }
/* Tool modes use the panels' two-option strips. Keep each pair together when a narrow player wraps the pill. */
.tool-mode-bar { position: absolute; top: 10px; left: 50%; transform: translateX(-50%); z-index: 3; display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 6px 8px; width: max-content; max-width: calc(100% - 20px); padding: 5px 6px 5px 12px; background: var(--panel); color: var(--ink); border: 1px solid var(--line); border-radius: 9px; box-shadow: 0 8px 24px rgba(0, 0, 0, .18); }
.tool-mode-bar[hidden] { display: none; }
.tool-mode-options[hidden] { display: none; }
.tool-mode-options button { flex: 1 0 auto; padding: 3px 9px; white-space: nowrap; }
.tool-mode-options button[aria-pressed="true"] { background: var(--accent-soft); color: var(--accent-text); box-shadow: inset 0 0 0 1px var(--accent-text); }
.tool-mode-options button:disabled { opacity: .5; cursor: default; }
.tool-mode-options button:focus-visible { outline: 2px solid var(--accent-text); outline-offset: 1px; }
.tool-mode-bar .tool-preference-rule { align-self: stretch; flex: 0 0 1px; background: var(--line); margin: 2px 0; }
.tool-mode-bar [data-tool-snap] { display: inline-flex; align-items: center; gap: 5px; }
.tool-mode-bar [data-tool-snap] svg { width: 14px; height: 14px; flex: 0 0 auto; }
/* Follow confirmed effective snapping, including the temporary Shift override. */
.tool-mode-bar [data-tool-snap][aria-pressed="true"] [data-snap-icon="off"],
.tool-mode-bar [data-tool-snap][aria-pressed="false"] [data-snap-icon="on"] { display: none; }
.tool-mode-bar [data-tool-snap][aria-pressed="true"] { background: var(--accent-soft); color: var(--accent-text); }
#section-banner:not([hidden]) ~ .tool-mode-bar, #placing-banner:not([hidden]) ~ .tool-mode-bar { top: 54px; }
#section-banner:not([hidden]) ~ #selection-bar, #placing-banner:not([hidden]) ~ #selection-bar { top: 54px; }
.sl-glyph { display: inline-flex; color: var(--muted); flex: 0 0 auto; }
.sl-glyph svg { width: 16px; height: 16px; }
.sl-verbs { display: flex; align-items: center; gap: 6px; }
.sl-note { flex: 0 0 100%; padding: 0 4px 2px; text-align: center; font-size: 11.5px; color: var(--muted); white-space: normal; }
.sl-note[hidden] { display: none; }
/* Sketch bar (sketch-bar.js): the Sketch tool's pill in the selection bar's shape: On screen and In scene as the bar's verbs
   with the chosen one pressed, a rule, the six inks as dots with the chosen one ringed, and with On screen pressed a rule,
   Straight line, the eraser and Send to agent, the last two quiet until there are marks. #sketch-bar is a click-through
   layer over the whole player and the container the queries below measure, so its width is the player's less the 10 px edges; .sk-pill is the pill,
   centred by auto margins. Under a banner it drops as the selection bar does. A narrow player (the panel open on a
   desktop, a phone) gets no room for one row, and a pill stacked two rows high is a large white block over the top of
   the sheet, so the paper's group leaves the pill instead for a small pill of its own at the player's bottom edge, where
   the joysticks would be (they go while the sheet is down). A phone also loses the glyph and a little spacing, so the
   modes and the inks keep to one row at 375 px; from 340 px the lock and a little more spacing go too, one row down to
   316 px. Narrower still, the pill wraps; the bar (sketch-bar.js, sk-wrap-inks)
   then hides the rule orphaned at the first row's end and nudges the row half a rule-and-gap to recentre it - visibility
   and a relative shift only, nothing that moves layout, so the check cannot oscillate at the boundary. The queried rules
   name .sk-pill as well, since the groups' own rules follow below and would otherwise outrank them. */
#sketch-bar { position: absolute; top: 10px; right: 10px; bottom: 10px; left: 10px; z-index: 3; pointer-events: none; container-type: inline-size; color: var(--ink); font-size: 12.5px; line-height: 1.3; white-space: nowrap; }
#sketch-bar[hidden] { display: none; }
#section-banner:not([hidden]) ~ #sketch-bar, #placing-banner:not([hidden]) ~ #sketch-bar { top: 54px; }
.sk-pill { pointer-events: auto; width: fit-content; max-width: 100%; margin: 0 auto; display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 4px 10px; padding: 5px 12px; background: var(--panel); border: 1px solid var(--line); border-radius: 9px; box-shadow: 0 8px 24px rgba(0, 0, 0, .18); }
.sk-wrap-inks > .sk-pill > .sk-rule { visibility: hidden; }
.sk-wrap-inks .sk-pill .sk-glyph, .sk-wrap-inks .sk-pill .sk-modes { position: relative; left: calc((1px + 10px) / 2); }
@container (max-width: 600px) { /* the paper's group as a pill of its own at the player's bottom edge */
  .sk-pill .sk-paper { position: absolute; bottom: 0; left: 50%; transform: translateX(-50%); padding: 5px 12px; background: var(--panel); border: 1px solid var(--line); border-radius: 9px; box-shadow: 0 8px 24px rgba(0, 0, 0, .18); }
  .sk-pill .sk-paper > .sk-rule { display: none; }
}
@container (max-width: 400px) { /* a phone: the modes and the inks on one row */
  .sk-pill .sk-glyph { display: none; }
  .sk-pill { gap: 4px 8px; padding: 5px 10px; }
  .sk-pill .sk-mode { padding: 0 7px; }
  .sk-pill .sk-inks { gap: 8px; }
}
@container (max-width: 340px) { /* narrower than the one-row pill's 327 px: the lock goes (its tooltip stays) and the spacing closes up a little more, one row down to a 316 px player */
  .sk-pill .sk-mode svg { display: none; }
  .sk-pill .sk-mode { gap: 0; padding: 0 6px; }
  .sk-pill .sk-inks { gap: 6px; }
}
.sk-glyph { display: inline-flex; color: var(--muted); flex: 0 0 auto; }
.sk-glyph svg { width: 16px; height: 16px; }
.sk-modes, .sk-paper { display: flex; align-items: center; gap: 6px; }
.sk-paper { gap: 10px; }
.sk-paper[hidden] { display: none; }
.sk-rule { flex: 0 0 1px; width: 1px; height: 18px; background: var(--line); }
.sk-mode { display: inline-flex; align-items: center; gap: 5px; height: 26px; padding: 0 9px; font-size: 11.5px; }
.sk-mode[aria-pressed="true"] { color: var(--accent-text); font-weight: 600; }
.sk-mode svg { width: 12px; height: 12px; }
.sk-inks { display: flex; align-items: center; gap: 10px; padding: 0 2px; }
.sk-ink { width: 16px; height: 16px; padding: 0; border: 0; border-radius: 50%; background: var(--ink-hex); box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .14); cursor: pointer; }
.sk-ink:hover, .sk-ink:focus-visible { box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .14), 0 0 0 2px var(--panel), 0 0 0 4px var(--muted); outline: none; }
.sk-ink[aria-checked="true"] { box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .14), 0 0 0 2px var(--panel), 0 0 0 4px var(--accent); }
.sk-straight, .sk-clear { width: 26px; height: 26px; padding: 0; display: grid; place-items: center; }
.sk-straight svg, .sk-clear svg { width: 15px; height: 15px; }
/* Straight line: pressed while on (.header-btn[aria-pressed]), and lit the same way while Shift is held (sketch-bar.js
   sk-shift), so the shortcut its hover name gives shows itself the first time it is used */
.sk-straight[aria-pressed="true"], .sk-straight.sk-shift { color: var(--accent-text); }
.sk-straight.sk-shift { border-color: var(--accent-text); background: var(--accent-soft); }
.sk-send { height: 26px; padding: 0 10px; border: 1px solid var(--accent); border-radius: 5px; background: var(--accent); color: var(--accent-ink); font: inherit; font-size: 11.5px; font-weight: 600; cursor: pointer; transition: background .15s ease, border-color .15s ease; }
.sk-send:hover:not(:disabled), .sk-send:focus-visible { background: var(--accent-hover); border-color: var(--accent-hover); outline: none; }
.sk-send:disabled { background: transparent; color: var(--muted); border-color: var(--line); opacity: .6; cursor: default; }
/* The tracing paper (tracing-paper.js): the layer takes the player's box and the pointer; the sheet is inset from the
   edges so it reads as a sheet laid on the view, slightly white and see-through, a hairline edge, a shadow; the ink
   canvas covers the layer; the × sits in the sheet's corner. While it is down the joysticks go and the header's
   navigation buttons sleep, since the camera is held. */
#paper { position: absolute; inset: 0; z-index: 2; cursor: crosshair; touch-action: none; }
#paper[hidden] { display: none; }
.paper-sheet { position: absolute; inset: 24px; border-radius: 3px; background: rgba(255, 255, 255, .18); border: 1px solid rgba(255, 255, 255, .6); box-shadow: 0 12px 40px rgba(0, 0, 0, .28); pointer-events: none; }
.paper-ink { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.paper-lift { position: absolute; right: 32px; top: 32px; width: 26px; height: 26px; padding: 0; border: 0; border-radius: 50%; background: rgba(255, 255, 255, .94); color: #1B2526; box-shadow: 0 2px 8px rgba(0, 0, 0, .25); display: grid; place-items: center; cursor: pointer; }
.paper-lift:hover, .paper-lift:focus-visible { background: #EEF1EF; outline: none; }
.paper-lift svg { width: 13px; height: 13px; }
body.paper-down #joysticks { display: none; }
body.paper-down #navigate .tool { color: var(--tool-ink-off); pointer-events: none; }
/* Dimension pills (dimensions.js) over the player: the shell's type where Unity measured, an editable one a button; the
   active (being edited) one takes the accent; the drag readout follows the pointer. The hint strip (hints.js) at the foot. */
#dimension-layer { position: absolute; inset: 0; z-index: 2; overflow: hidden; pointer-events: none; }
#dimension-layer[hidden] { display: none; }
.dim-pill { position: absolute; left: 0; top: 0; padding: 3px 8px; border: 1px solid var(--line); border-radius: 6px; background: var(--panel); color: var(--ink); box-shadow: 0 2px 8px rgba(0, 0, 0, .18); font: inherit; font-size: 12.5px; font-variant-numeric: tabular-nums; line-height: 1.3; white-space: nowrap; pointer-events: auto; cursor: pointer; }
.dim-pill.is-static, .dim-pill.is-readout { pointer-events: none; cursor: default; }
.dim-pill.is-area, .dim-pill.is-line { color: var(--muted); }
.dim-pill.is-readout { font-weight: 600; }
.dim-pill:hover, .dim-pill.is-active { border-color: var(--accent-text); }
.dim-pill.is-active { background: var(--accent-soft); }
.dim-pill.is-along { transform-origin: 0 0; border-color: transparent; box-shadow: none; padding: 1px 6px; background: color-mix(in srgb, var(--panel) 85%, transparent); } /* along its line (labelPose): origin 0 0, so the transform's translate(-50%, -50%) puts the centre on the point it turns about */
.dim-pill.is-along.is-active, .dim-pill.is-along:hover { border-color: var(--accent-text); }
.dim-pill.is-along.is-active { background: var(--accent-soft); }
.dim-pill[hidden] { display: none; } /* a line too short on screen to carry its label hides it */
/* The hint at the foot of the player in the banners' pill, 10 px in like the pills at the top: the words muted as
   the Placing banner's hint is, the keycaps in ink. The words wrap to a second line rather than being cut; the pill
   is capped so it reads as a line, not a paragraph, and on touch it stops short of the joysticks in the foot's
   corners. Nothing in it is for the pointer. */
#hint-pill { /* centred by auto margins, not left: 50%, which would give the box only half the player to wrap in */
  position: absolute; left: 0; right: 0; bottom: 10px; width: fit-content; margin: 0 auto; z-index: 3; max-width: min(640px, calc(100% - 20px));
  padding: 5px 12px; background: var(--panel); color: var(--muted);
  border: 1px solid var(--line); border-radius: 9px; box-shadow: 0 8px 24px rgba(0, 0, 0, .18); font-size: 12.5px; line-height: 1.4; text-align: center; pointer-events: none;
}
#hint-pill:has(> #hint-strip[hidden]) { display: none; }
@media (pointer: coarse) { #hint-pill { max-width: min(640px, calc(100% - 2 * 116px - 16px)); } } /* the sticks: 96 px at 20 px from the edges */
@media (pointer: coarse) and (max-width: 640px) { #hint-pill { max-width: calc(100% - 2 * 140px - 16px); } } /* 120 px sticks */
#hint-strip[hidden] { display: none; }
#hint-strip kbd { display: inline-block; min-width: 18px; margin: 0 1px; padding: 0 5px; border: 1px solid var(--line); border-bottom-width: 2px; border-radius: 4px; background: var(--panel-2); color: var(--ink); font: inherit; font-size: 11px; line-height: 16px; text-align: center; vertical-align: 1px; }
/* A first-run hint card steps under the selection bar or the sketch bar when both are up at the top of the player. */
/* The login card in the chat points at the footer form; openLogin rings the form for a moment so the eye finds it (in
   the welcome's Log in row too, when a Send opens it there, above the composer). */
#account.ac-attention .ac-form, #account.ac-attention .ac-login, .fr-login-slot.ac-attention .ac-form { border-color: var(--accent-text); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 45%, transparent); animation: ac-attention 1.2s ease-in-out 3; }
@keyframes ac-attention { 0%, 100% { box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 45%, transparent); } 50% { box-shadow: 0 0 0 6px color-mix(in srgb, var(--accent) 20%, transparent); } }
@media (prefers-reduced-motion: reduce) { #account.ac-attention .ac-form, #account.ac-attention .ac-login, .fr-login-slot.ac-attention .ac-form { animation: none; } }
/* The lesson card's own text when the player runs lessons itself (tutorial-card.js); empty on the tutor's player. */
#tutorial-text { font-size: 13px; line-height: 1.45; color: var(--ink); }
#tutorial-text:empty { display: none; }
#tutorial-actions #tutorial-new-chat[hidden], #tutorial-actions #tutorial-render[hidden], #tutorial-actions #tutorial-continue[hidden], #tutorial-actions #tutorial-skip[hidden] { display: none; }
/* The lesson card's checklist (one criteria term per line, ticked live) and its how-to behind Show steps. */
#tutorial-checks { margin: 0; padding: 0; list-style: none; display: grid; gap: 3px; font-size: 12.5px; color: var(--muted); }
#tutorial-checks:empty { display: none; }
#tutorial-checks li { display: flex; align-items: baseline; gap: 7px; }
#tutorial-checks li::before { content: "\25CB"; flex: none; font-size: 11px; color: var(--muted); }
#tutorial-checks li.done { color: var(--ink); }
#tutorial-checks li.done::before { content: "\2713"; color: var(--accent-text); font-weight: 700; }
#tutorial-steps-toggle { align-self: flex-start; padding: 0; border: 0; background: none; font: inherit; font-size: 12.5px; color: var(--accent-text); cursor: pointer; }
#tutorial-steps-toggle:hover, #tutorial-steps-toggle:focus-visible { text-decoration: underline; outline: none; }
#tutorial-steps-toggle[hidden] { display: none; }
#tutorial-steps { margin: 0; padding-left: 18px; display: grid; gap: 3px; font-size: 12.5px; line-height: 1.4; color: var(--ink); }
#tutorial-steps[hidden] { display: none; }

/* ---- the account footer as one button, and the Account sheet (account-sheet.js) ----
   The signed-in card keeps the ring, the count and the email and becomes the button that opens the sheet: a chevron
   at the end of the email says so, a tint marks hover, the pressed state stays while the sheet is open. The sheet is
   centred over the dimmed shell, in the render viewer's chrome; under 720 px it fills the window and the tabs move
   under the title. Cards on the panel background; the ring is ring.js's. */
.ac-in { width: 100%; text-align: left; font: inherit; color: var(--ink); cursor: pointer; transition: border-color .15s ease, background .15s ease; }
.ac-in:hover:not(:disabled), .ac-in:focus-visible { background: var(--panel-2); border-color: var(--accent-text); outline: none; }
.ac-in[aria-expanded="true"] { border-color: var(--accent-text); background: var(--accent-soft); }
.ac-in:disabled { opacity: .6; cursor: default; }
.ac-email-row { display: flex; align-items: center; gap: 6px; min-width: 0; }
.ac-email-row .ac-email-line { flex: 1 1 auto; min-width: 0; }
.ac-chevron { flex: 0 0 auto; width: 12px; height: 12px; color: var(--muted); }
/* the way into the Account sheet, said: the word in the link colour with the chevron, at the email row's end (Hilmar,
   2026-10-18: the chevron alone did not say where the card leads) */
.ac-account-link { flex: 0 0 auto; display: inline-flex; align-items: center; gap: 1px; font-size: 11px; font-weight: 500; color: var(--accent-text); white-space: nowrap; }
.ac-account-link .ac-chevron { width: 11px; height: 11px; color: inherit; }
.ac-in:hover:not(:disabled) .ac-account-link { text-decoration: underline; }
#account-sheet, #report-sheet { position: fixed; inset: 0; z-index: 24; display: grid; place-items: center; padding: 24px; }
#account-sheet[hidden], #report-sheet[hidden] { display: none; }
.as-scrim { position: absolute; inset: 0; background: rgba(4, 8, 6, .5); backdrop-filter: blur(2px); }
.as-panel { position: relative; display: flex; flex-direction: column; width: min(880px, 100%); max-height: 100%; background: var(--panel); color: var(--ink); border: 1px solid var(--line); border-radius: 12px; box-shadow: 0 24px 64px rgba(0, 0, 0, .5); overflow: hidden; }
.as-head { display: flex; align-items: center; gap: 14px; flex: 0 0 auto; height: 52px; padding: 0 12px 0 22px; border-bottom: 1px solid var(--line); }
.as-title { font-size: 15px; font-weight: 600; }
.as-tabs { display: flex; align-self: stretch; gap: 2px; margin-left: 4px; }
.as-tab { padding: 0 10px; border: 0; border-bottom: 2px solid transparent; margin-bottom: -1px; background: transparent; color: var(--muted); font: inherit; font-size: 13px; font-weight: 500; cursor: pointer; }
.as-tab[aria-selected="true"] { color: var(--ink); font-weight: 600; border-bottom-color: var(--accent); }
.as-tab[hidden] { display: none; }
.as-tab:hover, .as-tab:focus-visible { color: var(--ink); outline: none; }
.as-esc { margin-left: auto; font-size: 11px; color: var(--muted); }
.as-close { display: inline-grid; place-items: center; width: 28px; height: 28px; padding: 0; border: 0; border-radius: 6px; background: transparent; color: var(--muted); cursor: pointer; }
.as-close:hover, .as-close:focus-visible { color: var(--ink); background: var(--active-item, rgba(127, 127, 127, .14)); outline: none; }
.as-close svg { width: 15px; height: 15px; }
.as-body { flex: 1 1 auto; min-height: 0; overflow: auto; display: flex; flex-direction: column; gap: 14px; padding: 20px 22px 22px; background: var(--bg); }
.as-card { display: flex; flex-direction: column; gap: 10px; padding: 14px 16px; border: 1px solid var(--line); border-radius: 10px; background: var(--panel); }
.as-cap { display: flex; align-items: center; gap: 8px; font-size: 11.5px; font-weight: 600; letter-spacing: .07em; text-transform: uppercase; color: var(--muted); }
.as-beta { padding: 1px 6px; border-radius: 4px; background: var(--panel-2); color: var(--muted); font-size: 10px; letter-spacing: .04em; }
.as-grid { display: grid; grid-template-columns: 320px 1fr; gap: 14px; align-items: start; }
.as-you { flex-direction: row; align-items: center; gap: 12px; }
.as-avatar { flex: 0 0 auto; display: grid; place-items: center; width: var(--size, 38px); height: var(--size, 38px); border-radius: 50%; background: var(--tone, var(--accent)); color: #fff; font-size: calc(var(--size, 38px) * .42); font-weight: 600; }
.as-you-text { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.as-you-heading { display: flex; align-items: center; gap: 6px; min-width: 0; }
.as-you-heading .as-textglyph { flex-shrink: 0; }
.as-you-name { font-size: 14px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.as-you-line { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.as-textglyph { display: inline-grid; place-items: center; width: 20px; height: 20px; padding: 0; border: 0; border-radius: 5px; background: transparent; color: var(--muted); cursor: pointer; }
.as-textglyph:hover, .as-textglyph:focus-visible { color: var(--ink); background: var(--active-item, rgba(127, 127, 127, .14)); outline: none; }
.as-textglyph svg { width: 12px; height: 12px; }
.as-logout { display: inline-flex; align-items: center; gap: 6px; height: 28px; padding: 0 10px; font-size: 12px; font-weight: 600; }
.as-logout svg { width: 13px; height: 13px; }
.as-rename { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 4px; }
.as-rename-input, .as-input { flex: 1 1 200px; min-width: 0; height: 28px; padding: 0 10px; border: 1px solid var(--line); border-radius: 7px; background: var(--bg); color: var(--ink); font: inherit; font-size: 12.5px; }
.as-rename-input:focus, .as-input:focus { outline: none; border-color: var(--accent-text); }
.as-field-error, .as-error { font-size: 11.5px; color: var(--amber); }
.as-error { display: flex; align-items: center; gap: 10px; padding: 8px 12px; border: 1px solid var(--amber); border-radius: 8px; }
.as-plan-name { font-size: 20px; font-weight: 600; line-height: 1.2; }
.as-line { font-size: 12.5px; }
.as-sub { font-size: 11.5px; line-height: 1.4; color: var(--muted); }
.as-note { padding: 2px 4px; }
.as-actions { display: flex; align-items: center; gap: 12px; margin-top: 2px; }
.as-link { display: inline-flex; align-items: center; gap: 4px; color: var(--accent-text); font-size: 12px; font-weight: 600; text-decoration: none; white-space: nowrap; }
.as-link:hover { text-decoration: underline; }
.as-link svg { width: 12px; height: 12px; }
.as-row { display: flex; align-items: center; gap: 14px; }
.as-row .ring { flex: 0 0 auto; }
.as-row-text { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.as-big { font-size: 14px; font-weight: 600; font-variant-numeric: tabular-nums; }
.as-big.is-muted, .is-muted { color: var(--muted); font-weight: 500; }
.as-glyph { display: inline-grid; place-items: center; flex: 0 0 auto; width: 28px; height: 28px; border-radius: 50%; background: var(--panel-2); color: var(--accent-text); }
.as-glyph svg { width: 15px; height: 15px; }
.as-bar { display: flex; height: 8px; border-radius: 8px; overflow: hidden; background: var(--line); }
.as-bar span { display: block; height: 100%; background: var(--accent); }
.as-rule { height: 1px; margin: 2px 0; background: var(--line); }
.as-primary { display: inline-flex; align-items: center; justify-content: center; gap: 7px; height: 30px; padding: 0 14px; border: 1px solid var(--accent); border-radius: 7px; background: var(--accent); color: var(--accent-ink); font: inherit; font-size: 12.5px; font-weight: 600; white-space: nowrap; cursor: pointer; }
.as-primary svg { width: 14px; height: 14px; }
.as-primary:hover:not(:disabled), .as-primary:focus-visible { filter: brightness(1.06); outline: none; }
.as-primary:disabled { border-color: var(--line); background: var(--panel-2); color: var(--muted); cursor: default; }
.as-foot-line { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--muted); }
.as-foot-line svg { width: 14px; height: 14px; }
.as-loading { padding: 24px 0; text-align: center; font-size: 12.5px; color: var(--muted); }
/* A hosted plan change's note: a card across the body's top, Refresh account at its end. */
.as-status { flex-direction: row; align-items: center; gap: 10px; padding: 10px 14px; font-size: 12.5px; }
.as-status > span { flex: 1 1 auto; }
.as-status > .as-glyph { flex: 0 0 auto; } /* the disc keeps its size; the text takes the room */
/* Buy AI credits: the packs to choose from (one selected, the accent's 2 px line), Continue to payment, an attempt's card. */
.as-packs { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px; }
.as-pack { display: flex; flex-direction: column; align-items: flex-start; gap: 3px; padding: 12px 14px; border: 1px solid var(--line); border-radius: 10px; background: var(--panel); color: var(--ink); font: inherit; text-align: left; cursor: pointer; }
.as-pack:hover:not(:disabled), .as-pack:focus-visible { border-color: var(--accent-text); outline: none; }
.as-pack.is-selected { padding: 11px 13px; border: 2px solid var(--accent); }
.as-pack:disabled { cursor: default; opacity: .7; }
.as-pack-credits { font-size: 20px; font-weight: 600; font-variant-numeric: tabular-nums; }
.as-checkout { gap: 6px; }
.as-done { border-color: var(--accent); }
.as-done .as-glyph { background: var(--accent); color: var(--accent-ink); }
/* the confirmation's ×: the head's close button in size and colour, but it dismisses only the card */
.as-dismiss { flex: 0 0 auto; display: inline-grid; place-items: center; width: 28px; height: 28px; padding: 0; border: 0; border-radius: 6px; background: transparent; color: var(--muted); cursor: pointer; }
.as-dismiss:hover, .as-dismiss:focus-visible { color: var(--ink); background: var(--active-item, rgba(127, 127, 127, .14)); outline: none; }
.as-dismiss svg { width: 15px; height: 15px; }
.as-checkout-pack { font-size: 13px; font-weight: 600; }
.as-actions .as-sub { flex: 1 1 auto; }
/* Members: the three tiles (the pool, the packs, the seats), the one limit, the invitations with their pending list, the table. */
.as-limit-form { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.as-limit-line { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 6px; font-size: 12.5px; }
.as-number { width: 64px; height: 28px; padding: 0 8px; border: 1px solid var(--line); border-radius: 7px; background: var(--bg); color: var(--ink); font: inherit; font-size: 12.5px; font-variant-numeric: tabular-nums; text-align: right; }
.as-number:focus { outline: none; border-color: var(--accent-text); }
.as-number:disabled { opacity: .6; }
.as-limit-value { font-weight: 600; font-variant-numeric: tabular-nums; }
.as-invite { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.as-invite-full { color: var(--amber); }
.as-ok { color: var(--ink); }
.as-pending-list { display: flex; flex-direction: column; gap: 6px; }
.as-pending { display: flex; align-items: center; gap: 10px; padding: 6px 8px; border: 1px solid var(--line); border-radius: 8px; font-size: 12px; }
.as-pending .as-glyph { width: 24px; height: 24px; }
.as-pending .as-glyph svg { width: 13px; height: 13px; }
.as-pending-email { font-size: 12.5px; font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.as-pending-unconfirmed { color: var(--amber); }
.as-chip { display: inline-flex; align-items: center; gap: 4px; height: 20px; padding: 0 7px; border: 1px solid var(--line); border-radius: 5px; background: var(--panel-2); color: var(--muted); font-size: 10.5px; font-weight: 600; white-space: nowrap; }
.as-chip svg { width: 10px; height: 10px; }
.as-members { display: flex; flex-direction: column; padding: 8px 8px 4px; border: 1px solid var(--line); border-radius: 10px; background: var(--panel); }
/* Member, Role, Used (with its reserved line), Limit, the state chip, Remove */
.as-members-head, .as-member { display: grid; grid-template-columns: 1fr 92px 130px 120px 72px 70px; align-items: center; gap: 12px; padding: 5px 8px; }
.as-members-head { padding-bottom: 6px; border-bottom: 1px solid var(--line); font-size: 10.5px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.as-member { min-height: 44px; border-radius: 7px; font-size: 11.5px; }
.as-member:hover { background: var(--active-item, rgba(127, 127, 127, .14)); }
.as-member-who { display: flex; align-items: center; gap: 10px; min-width: 0; }
.as-member-text { display: flex; flex-direction: column; min-width: 0; }
.as-member-name { font-size: 12.5px; font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.as-member-email { font-size: 11px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.as-member-used { display: flex; flex-direction: column; gap: 1px; font-variant-numeric: tabular-nums; }
.as-member-actions { text-align: right; }
.as-remove { color: var(--danger); }
/* Remove's question, in the member's row across the table: the alert, who and what it means, Cancel and Remove */
.as-member-confirm { grid-column: 1 / -1; display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin: 4px 0 2px; padding: 10px 12px; border: 1px solid var(--danger); border-radius: 8px; background: var(--panel); }
.as-member-confirm .as-glyph { color: var(--danger); }
.as-member-confirm .as-glyph svg { width: 14px; height: 14px; }
.as-member-confirm .as-row-text { flex: 1 1 260px; }
/* ---- the commercial portal (canvas page 31, Plans & billing): the head's way back, the plan chooser, the AI credits
   tab's balance, levels, packs and purchases, Team's seats, the change review, cancelling, the signed-out entry ---- */
.as-back { display: inline-flex; align-items: center; gap: 4px; height: 28px; margin-left: -8px; padding: 0 8px 0 4px; border: 0; border-radius: 6px; background: transparent; color: var(--muted); font: inherit; font-size: 12.5px; font-weight: 600; cursor: pointer; }
.as-back:hover, .as-back:focus-visible { color: var(--ink); background: var(--active-item, rgba(127, 127, 127, .14)); outline: none; }
.as-back svg { width: 15px; height: 15px; }
.as-back:not([hidden]) + .as-title { padding-left: 14px; border-left: 1px solid var(--line); }
.as-back[hidden] { display: none; }
.as-chip.is-amber { border-color: var(--amber); background: transparent; color: var(--amber); }
.as-chip.is-danger { border-color: var(--danger); background: transparent; color: var(--danger); }
.as-chip.is-accent { border-color: var(--accent-text); background: var(--accent-soft); color: var(--accent-text); }
.as-plan-head { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.as-sub.is-danger { color: var(--danger); }
.as-seats-line { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.as-seats-line .sh-textbtn, .as-linkbtn { display: inline-flex; align-items: center; gap: 3px; font-size: 12px; }
.as-seats-line svg { width: 12px; height: 12px; }
.as-linkbtn { padding: 0; border: 0; background: transparent; font-family: inherit; cursor: pointer; }
.as-linkbtn:disabled { color: var(--muted); cursor: default; text-decoration: none; }
.as-link.is-quiet { color: var(--muted); }
.as-links { flex-wrap: wrap; gap: 6px 16px; }
.as-actions { flex-wrap: wrap; }
.as-grow { flex: 1 1 auto; }
.as-right { text-align: right; }
.as-num { font-variant-numeric: tabular-nums; }
.as-primary.is-big { height: 36px; padding: 0 18px; border-radius: 8px; font-size: 13.5px; }
.as-primary.is-full { width: 100%; }
.header-btn.as-danger { border-color: var(--danger); color: var(--danger); font-weight: 600; }
.as-status .as-glyph svg, .as-scheduled .as-cap svg { width: 14px; height: 14px; }
.as-scheduled { border-color: var(--accent-text); background: var(--accent-soft); }
.as-warn { display: flex; align-items: flex-start; gap: 8px; padding: 8px 12px; border: 1px solid var(--amber); border-radius: 8px; font-size: 12px; line-height: 1.45; }
.as-warn svg { flex: 0 0 auto; width: 14px; height: 14px; margin-top: 1px; color: var(--amber); }
.as-warn-card { border-color: var(--amber); }
.as-mail { display: inline-flex; align-items: center; gap: 6px; padding: 6px 10px; font-size: 12px; font-weight: 600; text-decoration: none; }
.as-mail svg { width: 13px; height: 13px; }

/* the Plan tab: your plan, Monthly | Annual, the plans as cards, the chosen one open on its levels, the summary */
.as-chooser-head { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; }
.as-line.is-soft { color: var(--muted); }
.as-line.is-soft b { color: var(--ink); font-weight: 600; }
.as-vrule { width: 1px; height: 18px; background: var(--line); }
.as-seg { display: inline-flex; padding: 2px; border: 1px solid var(--line); border-radius: 8px; background: var(--panel); }
.as-seg button { height: 28px; padding: 0 14px; border: 0; border-radius: 6px; background: transparent; color: var(--ink); font: inherit; font-size: 12.5px; font-weight: 600; cursor: pointer; }
.as-seg button[aria-pressed="true"] { background: var(--ink); color: var(--panel); }
.as-seg button:focus-visible { outline: 2px solid var(--accent-text); outline-offset: 1px; }
.as-plan-cards { display: grid; grid-template-columns: repeat(var(--cols, 3), minmax(0, 1fr)); gap: 12px; align-items: stretch; }
.as-plan-card { position: relative; display: flex; flex-direction: column; gap: 6px; min-width: 0; padding: 14px 16px; border: 1px solid var(--line); border-radius: 10px; background: var(--panel); }
.as-plan-card.is-chosen { padding: 13px 15px; border: 2px solid var(--accent); }
.as-plan-badge { position: absolute; top: -10px; left: 14px; height: 20px; padding: 0 8px; border-radius: 5px; background: var(--ink); color: var(--panel); font-size: 10.5px; font-weight: 600; line-height: 20px; }
.as-plan-title { font-size: 17px; font-weight: 600; }
.as-plan-price { display: flex; align-items: baseline; gap: 4px; margin-top: 2px; }
.as-plan-amount { font-size: 26px; font-weight: 600; letter-spacing: -.01em; font-variant-numeric: tabular-nums; }
.as-plan-was { margin-right: 2px; font-size: 17px; font-weight: 600; color: var(--muted); font-variant-numeric: tabular-nums; } /* the regular price under an introduction, struck through as on the pricing page */
.as-features { display: flex; flex-direction: column; gap: 3px; font-size: 11.5px; line-height: 1.4; color: var(--muted); }
.as-features > span { display: flex; align-items: flex-start; gap: 6px; }
.as-features svg { flex: 0 0 auto; width: 12px; height: 12px; margin-top: 2px; color: var(--accent-text); stroke-width: 2.2; }
.as-includes { margin-top: 4px; font-size: 10.5px; } /* "Everything in Plus, plus" over the list, as on the pricing page */
.as-features .as-soon { display: inline-block; margin-left: 4px; padding: 0 6px; border-radius: 4px; background: var(--line); color: var(--muted); font-size: 9.5px; font-weight: 600; letter-spacing: .06em; line-height: 16px; text-transform: uppercase; vertical-align: 1px; }
.as-pick { align-self: flex-start; margin-top: auto; }
.as-levels { display: flex; gap: 6px; }
.as-levels:has(.as-level-now) { margin-top: 4px; } /* room for the tag above the row */
.as-levels:has(.as-level-now) .as-level { padding-top: 10px; } /* and under it, before the credits */
.as-levels:has(.as-level-now) .as-level.is-selected { padding-top: 9px; }
.as-level { position: relative; flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; align-items: center; gap: 1px; padding: 6px 4px; border: 1px solid var(--line); border-radius: 8px; background: var(--panel); color: var(--ink); font: inherit; cursor: pointer; }
.as-level:hover:not(:disabled), .as-level:focus-visible { border-color: var(--accent-text); outline: none; }
.as-level.is-selected { padding: 5px 3px; border: 2px solid var(--accent); }
.as-level:disabled { opacity: .6; cursor: default; }
.as-level-top { font-size: 12.5px; font-weight: 600; font-variant-numeric: tabular-nums; white-space: nowrap; }
.as-level-sub { max-width: 100%; font-size: 10.5px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* the plan's current level: a tag on the top edge, like the card's Your plan badge, so no price line grows */
.as-level-now { position: absolute; top: -8px; left: 50%; transform: translateX(-50%); height: 16px; padding: 0 6px; border-radius: 4px; background: var(--ink); color: var(--panel); font-size: 9.5px; font-weight: 600; line-height: 16px; white-space: nowrap; pointer-events: none; }
.as-seat-row { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.as-stepper { display: inline-flex; align-items: center; border: 1px solid var(--line); border-radius: 7px; background: var(--panel); overflow: hidden; }
.as-stepper button { display: grid; place-items: center; width: 30px; height: 28px; padding: 0; border: 0; background: transparent; color: var(--ink); cursor: pointer; }
.as-stepper button:hover:not(:disabled), .as-stepper button:focus-visible { background: var(--active-item, rgba(127, 127, 127, .14)); outline: none; }
.as-stepper button:disabled { color: var(--muted); opacity: .5; cursor: default; }
.as-stepper svg { width: 13px; height: 13px; stroke-width: 2; }
.as-stepper-value { display: grid; place-items: center; min-width: 34px; height: 28px; border-left: 1px solid var(--line); border-right: 1px solid var(--line); font-size: 13px; font-weight: 600; font-variant-numeric: tabular-nums; }
.as-summary { padding: 12px 16px; }
.as-summary-what { font-size: 13.5px; font-weight: 600; }

/* AI credits: the balance in three columns, the packs with the launch offer, the purchases */
.as-balance { display: flex; align-items: stretch; padding: 16px 0; border: 1px solid var(--line); border-radius: 10px; background: var(--panel); }
.as-balance-col { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; gap: 8px; padding: 0 20px; }
.as-balance-col + .as-balance-col { border-left: 1px solid var(--line); }
.as-balance-total { display: flex; align-items: baseline; gap: 8px; }
.as-balance-num { font-size: 30px; font-weight: 600; line-height: 34px; letter-spacing: -.01em; font-variant-numeric: tabular-nums; }
.as-figure { gap: 10px; }
.as-figure .as-big, .as-figure .as-sub { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.as-ring-bought { display: inline-flex; }
.as-ring-bought .ring-value { stroke: var(--accent-text); }
.as-pack { position: relative; }
.as-pack-offer { position: absolute; top: -10px; left: 12px; height: 20px; padding: 0 7px; border: 1px solid var(--accent-text); border-radius: 5px; background: var(--accent-soft); color: var(--accent-text); font-size: 10.5px; font-weight: 600; line-height: 18px; white-space: nowrap; }
.as-pack-price { display: flex; align-items: baseline; gap: 6px; margin-top: 4px; font-size: 14px; font-weight: 600; }
.as-pack-price s { font-size: 11.5px; font-weight: 500; color: var(--muted); }
.as-packs { margin-top: 6px; }
.as-pack-go { gap: 12px; }
.as-history { display: flex; flex-direction: column; padding: 12px 8px 4px; border: 1px solid var(--line); border-radius: 10px; background: var(--panel); }
.as-history-head { display: flex; align-items: center; padding: 0 8px 8px; }
.as-history-row { display: grid; grid-template-columns: 110px minmax(0, 1fr) 120px 110px; align-items: center; gap: 12px; min-height: 34px; padding: 2px 8px; font-size: 12.5px; }
.as-history-row.is-head { min-height: 0; padding-bottom: 6px; border-bottom: 1px solid var(--line); font-size: 10.5px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.as-history-row.is-spent { color: var(--muted); }
.as-history-empty { padding: 6px 8px 10px; }

/* the change review: now and new side by side, what happens as the quote says it, Confirm */
.as-review-pair { display: flex; align-items: stretch; gap: 12px; }
.as-review-side { flex: 1 1 0; gap: 4px; }
.as-review-side.is-chosen { border-color: var(--accent); }
.as-review-name { font-size: 17px; font-weight: 600; }
.as-review-arrow { display: grid; place-items: center; color: var(--muted); }
.as-review-arrow svg { width: 18px; height: 18px; }
.as-kv { display: grid; grid-template-columns: 150px minmax(0, 1fr); gap: 9px 16px; font-size: 12.5px; line-height: 1.45; }
.as-kv-key { color: var(--muted); }
.as-due { font-size: 15px; font-weight: 600; }
.as-review-actions { gap: 10px; }
.as-review-actions .as-sub { flex: 0 1 auto; max-width: 320px; margin-left: auto; text-align: right; }

/* the entry from the pricing page, signed out: one email field, then the code */
#account-sheet:has(.as-entry) .as-panel { width: min(520px, 100%); }
.as-entry { gap: 12px; }
.as-entry-field { position: relative; display: flex; align-items: center; }
.as-entry-field svg { position: absolute; left: 10px; width: 14px; height: 14px; color: var(--muted); pointer-events: none; }
.as-entry-field .as-input { height: 36px; padding-left: 32px; }
.as-entry .as-input { flex: 0 0 auto; width: 100%; height: 36px; } /* full width: long addresses fit, the code field too */
.as-entry-code { font-size: 15px; font-weight: 600; letter-spacing: .32em; text-transform: uppercase; }
.as-entry-links { display: flex; align-items: center; gap: 8px; font-size: 12px; }
.as-entry-links .sh-textbtn:disabled { color: var(--muted); font-weight: 500; cursor: default; text-decoration: none; }
@media (max-width: 720px) {
  #account-sheet, #report-sheet { padding: 0; }
  .as-panel { width: 100%; height: 100%; max-height: none; border: 0; border-radius: 0; }
  .as-head { flex-wrap: wrap; height: auto; padding: 10px 10px 0 16px; gap: 8px 12px; }
  .as-tabs { order: 3; flex: 1 0 100%; margin: 4px 0 0 -10px; }
  .as-esc { display: none; }
  .as-close { margin-left: auto; } /* the Esc hint that pushed it right is hidden here */
  .as-body { padding: 14px; }
  .as-grid, .as-plan-cards { grid-template-columns: 1fr; }
  .as-balance { flex-direction: column; gap: 14px; }
  .as-balance-col + .as-balance-col { border-left: 0; border-top: 1px solid var(--line); padding-top: 14px; }
  .as-history-row { grid-template-columns: 84px minmax(0, 1fr) 90px; }
  .as-history-row > :nth-child(4) { display: none; }
  .as-review-pair { flex-direction: column; }
  .as-review-arrow { transform: rotate(90deg); }
  .as-kv { grid-template-columns: 1fr; gap: 2px 0; }
  .as-kv-key { margin-top: 6px; }
  .as-levels { flex-wrap: wrap; }
  .as-level { flex-basis: calc(50% - 3px); }
  .as-back:not([hidden]) + .as-title { padding-left: 8px; }
  .as-members-head { display: none; }
  .as-member { grid-template-columns: 1fr 84px 64px; }
  .as-member > :nth-child(3), .as-member > :nth-child(4), .as-member > :nth-child(5) { display: none; }
}

/* ---- the Report an issue sheet (report-sheet.js, canvas page 28) ----
   In the Account sheet's chrome (the scrim, the panel, the head, the cards on the body's background) so the two sheets
   read as one family. The way in is the flag at the foot of the rail: a button, not a tab, so pressed is the tint on
   its glyph rather than the tab's edge, and the side panel stays as it was. Two columns: the kind, the summary and
   what happened; the screenshot and what is sent with it. Under 720 px the columns stack. The sent page is narrower. */
.rail-action {
  width: 100%; height: 36px; display: grid; place-items: center; padding: 0 2px 0 0;
  border: 0; border-left: 2px solid transparent; background: transparent; color: var(--tool-ink-off); cursor: pointer;
  transition: color .15s ease;
}
.rail-action[hidden] { display: none; }
.rail-action span { display: grid; place-items: center; width: 32px; height: 30px; border-radius: 7px; transition: background .15s ease; }
.rail-action:hover, .rail-action:focus-visible { color: var(--tool-ink); outline: none; }
.rail-action:hover span, .rail-action:focus-visible span { background: var(--active-item, rgba(127, 127, 127, .14)); }
.rail-action[aria-pressed="true"] { color: var(--accent-text); }
.rail-action[aria-pressed="true"] span { background: var(--accent-soft); }
#report-sheet.is-sent .as-panel { width: min(640px, 100%); }
.rs-grid { display: grid; grid-template-columns: 1fr 300px; gap: 14px; align-items: start; }
.rs-cap { margin-top: 6px; }
.rs-kinds { display: flex; flex-wrap: wrap; gap: 6px; }
.rs-chip {
  display: inline-flex; align-items: center; gap: 5px; height: 28px; padding: 0 11px; border: 1px solid var(--line); border-radius: 14px;
  background: var(--panel); color: var(--ink); font: inherit; font-size: 12px; font-weight: 500; white-space: nowrap; cursor: pointer;
  transition: border-color .15s ease, background .15s ease, color .15s ease;
}
.rs-chip:hover:not(:disabled), .rs-chip:focus-visible { border-color: var(--accent-text); outline: none; }
.rs-chip:disabled { cursor: default; }
.rs-chip[aria-checked="true"] { border-color: var(--accent-text); background: var(--accent-soft); color: var(--accent-text); font-weight: 600; }
.rs-chip svg { width: 12px; height: 12px; }
.rs-input { height: 30px; padding: 0 10px; border: 1px solid var(--line); border-radius: 7px; background: var(--bg); color: var(--ink); font: inherit; font-size: 12.5px; }
.rs-input::placeholder, .rs-area::placeholder { color: var(--muted); }
.rs-input:focus { outline: none; border-color: var(--accent-text); box-shadow: 0 0 0 3px var(--accent-soft); }
.rs-input[aria-invalid="true"] { border-color: var(--danger); }
.rs-input:disabled, .rs-area:disabled { opacity: .6; }
/* What happened: the field is the bordered box so a quoted agent error can sit above the words typed, inside the border */
.rs-field-area { display: flex; flex-direction: column; min-height: 196px; padding: 8px 10px; border: 1px solid var(--line); border-radius: 7px; background: var(--bg); }
.rs-field-area:focus-within { border-color: var(--accent-text); box-shadow: 0 0 0 3px var(--accent-soft); }
.rs-area { flex: 1 1 auto; min-height: 120px; padding: 0; border: 0; background: transparent; color: var(--ink); font: inherit; font-size: 12.5px; line-height: 1.5; resize: none; }
.rs-area:focus { outline: none; }
.rs-quote { margin-bottom: 8px; padding: 7px 10px; border-radius: 6px; background: var(--panel-2); color: var(--muted); font-size: 11.5px; line-height: 1.45; }
.rs-quote-who { font-weight: 600; color: var(--ink); }
/* the screenshot: the chat's scene still as the preview, the remove button and the caption over it; removed, a dashed box */
.rs-shot { position: relative; height: 118px; border: 1px solid var(--line); border-radius: 8px; overflow: hidden; background: var(--panel-2); }
.rs-shot-img { display: block; width: 100%; height: 100%; object-fit: cover; }
.rs-shot-blank, .rs-shot.is-removed { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px; height: 100%; color: var(--muted); font-size: 11.5px; }
.rs-shot.is-removed { border-style: dashed; }
.rs-shot-blank > svg, .rs-shot.is-removed > svg { width: 18px; height: 18px; }
.rs-shot-remove { position: absolute; top: 6px; right: 6px; display: inline-grid; place-items: center; width: 24px; height: 24px; padding: 0; border: 0; border-radius: 6px; background: rgba(16, 18, 17, .6); color: #fff; cursor: pointer; }
.rs-shot-remove:hover:not(:disabled), .rs-shot-remove:focus-visible { background: rgba(16, 18, 17, .8); outline: none; }
.rs-shot-remove svg { width: 13px; height: 13px; }
.rs-shot-tag { position: absolute; left: 6px; bottom: 6px; display: inline-flex; align-items: center; gap: 5px; height: 20px; padding: 0 7px; border-radius: 5px; background: rgba(16, 18, 17, .6); color: #fff; font-size: 10.5px; font-weight: 500; }
.rs-shot-tag svg { width: 11px; height: 11px; }
.rs-retake { display: inline-flex; align-items: center; gap: 4px; font-size: 12px; }
.rs-retake svg { width: 12px; height: 12px; }
/* what is sent with it: one row per part, the glyph, the title, what it holds, the switch (or Always for the diagnostics) */
.rs-includes { display: flex; flex-direction: column; }
.rs-include { display: flex; align-items: flex-start; gap: 10px; padding: 8px 0; }
.rs-include-glyph { flex: 0 0 auto; display: inline-grid; place-items: center; width: 26px; height: 26px; border-radius: 6px; background: var(--panel-2); color: var(--accent-text); }
.rs-include-glyph svg { width: 14px; height: 14px; }
.rs-include-text { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.rs-include-title { font-size: 12.5px; font-weight: 600; }
.rs-include-line { font-size: 11px; line-height: 1.4; color: var(--muted); }
.rs-switch { margin-top: 4px; }
/* a part the email way out cannot carry (the scene needs the player): dimmed, its switch off and locked */
.rs-include.is-off { opacity: .55; }
.rs-always { flex: 0 0 auto; margin-top: 5px; padding: 1px 6px; border-radius: 4px; background: var(--panel-2); color: var(--muted); font-size: 10.5px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; }
/* under both columns: who we reply to (or the address to type), Cancel, Send; then the note or the failure */
.rs-foot { display: flex; align-items: center; gap: 10px; }
.rs-reply { flex: 1 1 auto; min-width: 0; font-size: 12px; color: var(--muted); }
.rs-reply b { color: var(--ink); font-weight: 600; }
.rs-reply-field { display: flex; align-items: center; gap: 10px; }
.rs-email { width: min(280px, 100%); }
.rs-foot-actions { display: flex; align-items: center; gap: 10px; }
.rs-cancel, .rs-another { height: 30px; padding: 0 12px; border-radius: 7px; font-size: 12.5px; font-weight: 600; }
.rs-send.is-sending:disabled { border-color: var(--accent); background: var(--accent); color: var(--accent-ink); cursor: progress; }
.rs-send .ring-track { stroke: currentColor; opacity: .35; }
.rs-send .ring-value { stroke: currentColor; }
.rs-note[hidden] { display: none; }
/* sent: the mark, the reference copied with one click, what happens next, Report another or Done */
.rs-sent { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px; padding: 36px 0 28px; text-align: center; }
.rs-sent-mark { display: inline-grid; place-items: center; width: 44px; height: 44px; border-radius: 50%; background: var(--accent-soft); color: var(--accent-text); }
.rs-sent-mark svg { width: 22px; height: 22px; }
.rs-sent-title { font-size: 18px; font-weight: 600; }
.rs-ref { display: inline-flex; align-items: center; gap: 8px; height: 28px; padding: 0 6px 0 10px; border: 1px solid var(--line); border-radius: 7px; background: var(--panel); font-size: 12.5px; font-variant-numeric: tabular-nums; }
.rs-ref-label { color: var(--muted); }
.rs-ref-code { font-weight: 600; }
.rs-copy { width: 22px; height: 22px; }
.rs-sent-text .rs-copy { display: inline-grid; place-items: center; vertical-align: middle; }
.rs-sent-actions .header-btn svg { width: 13px; height: 13px; }
.rs-copy svg { width: 13px; height: 13px; }
.rs-copy.is-copied { color: var(--accent-text); }
.rs-sent-text { max-width: 420px; font-size: 12.5px; }
.rs-sent-actions { display: flex; gap: 10px; margin-top: 6px; }
/* Report this, beside an agent error in the chat (app.js addErrorMessage): the way into the sheet from the error itself */
.msg.error .msg-report { margin-left: 8px; font-size: 12px; }
@media (max-width: 720px) {
  .rs-grid { grid-template-columns: 1fr; }
  .rs-foot { flex-wrap: wrap; }
}

/* Guided-tutorial pictures: the plan on the request bubble and a replayed render in the reply (app.js guidedPicture) */
.guided-image { margin: 8px 0 0; }
.guided-image img { display: block; max-width: 100%; max-height: 320px; border-radius: 8px; }
.guided-image.attachment img { max-height: 160px; }
.guided-gallery { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
.guided-gallery .guided-image:has(.guided-video-preview) { grid-column: 1 / -1; }
.guided-image video { display: block; width: 100%; max-height: 360px; border-radius: 8px; }
.guided-image figcaption { margin-top: 4px; color: var(--muted); font-size: 11px; }
.guided-preview { display: block; padding: 0; border: 0; border-radius: 8px; background: transparent; cursor: pointer; width: 100%; }
.guided-preview:focus-visible { outline: 2px solid var(--accent-text); outline-offset: 3px; }
.guided-video-preview { position: relative; overflow: hidden; aspect-ratio: 16 / 9; display: grid; place-items: center; color: white; background: var(--panel-2); border: 1px solid var(--line); }
.guided-video-preview img { position: absolute; inset: 0; width: 100%; height: 100%; max-height: none; object-fit: cover; }
.guided-video-preview svg { fill: currentColor; position: relative; width: 44px; height: 44px; padding: 10px; border-radius: 50%; background: rgb(0 0 0 / 55%); }
#tutorial-prompt-images[hidden] { display: none; }
#tutorial-prompt-images .guided-image { margin: 0; }
#tutorial-prompt-images img { width: 100%; height: 64px; object-fit: cover; }

.tutorial-prompt-thumb { width: 28px; height: 22px; object-fit: cover; border-radius: 4px; margin-right: 6px; vertical-align: middle; }
/* ---- Cloud scenes (app.js renderCloudState; words in cloud-messages.js) ---- */
/* The status beside the chat name: the label alone in a hairline-less button, muted by default, the alert's amber for
   anything that wants a decision or a retry, the accent while checking or downloading. A click or Enter opens its
   popover, so the sentence behind the label is not hover-only. */
.cloud-save-state {
  border: 0; border-radius: 6px; background: transparent; color: var(--muted); font: inherit; font-size: 11px; padding: 4px 6px;
  flex: 0 1 auto; min-width: 0; max-width: min(220px, 50%); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; cursor: pointer; /* a long state gives way before the name does */
  transition: background .15s ease, color .15s ease;
}
.cloud-save-state:hover, .cloud-save-state:focus-visible, .cloud-save-state[aria-expanded="true"] { background: var(--line); color: var(--ink); outline: none; }
.cloud-save-state[data-state="conflict"], .cloud-save-state[data-state="error"], .cloud-save-state[data-state="remote"],
.cloud-save-state[data-state="shared"], .cloud-save-state[data-state="restore"] { color: var(--amber); }
.cloud-save-state[data-state="checking"], .cloud-save-state[data-state="downloading"] { color: var(--accent-text); }
/* The two states whose click is the choice itself (a conflict, a newer cloud version) read as a button wherever the
   badge lives: the Logs button's bordered look in the ink on the raised gray the cards use (the amber and an orange wash
   were drawn and tried, design canvas page 31; the gray was chosen on 2026-10-13), the teal edge on hover. */
.cloud-save-state[data-state="conflict"], .cloud-save-state[data-state="remote"] {
  padding: 5px 8px; border: 1px solid var(--line); border-radius: 5px; background: var(--panel-2); color: var(--ink);
  transition: border-color .15s ease, background .15s ease;
}
.cloud-save-state[data-state="conflict"]:hover, .cloud-save-state[data-state="conflict"]:focus-visible, .cloud-save-state[data-state="conflict"][aria-expanded="true"],
.cloud-save-state[data-state="remote"]:hover, .cloud-save-state[data-state="remote"]:focus-visible, .cloud-save-state[data-state="remote"][aria-expanded="true"] { border-color: var(--accent-text); background: var(--panel-2); color: var(--ink); }
/* Its popover: the label, the sentence and the actions, fixed at body level like the chat menu so the header cannot
   clip it; Escape, a click elsewhere, a resize or a choice closes it. */
#cloud-save-popover {
  position: fixed; z-index: 20; width: min(340px, calc(100vw - 16px)); padding: 12px 14px;
  background: var(--panel); color: var(--ink); border: 1px solid var(--line); border-radius: 10px;
  box-shadow: 0 12px 32px rgba(0, 0, 0, .45); font-size: 12.5px; line-height: 1.45;
}
#cloud-save-popover[hidden] { display: none; }
#cloud-save-popover:focus { outline: none; }
.cloud-pop-title { margin: 0 0 4px; font-weight: 600; font-size: 13px; }
.cloud-pop-detail { margin: 0 0 10px; }
.cloud-pop-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.cloud-pop-action {
  padding: 5px 10px; border: 1px solid var(--line); border-radius: 6px; background: var(--panel-2); color: var(--ink);
  font: inherit; font-size: 12px; cursor: pointer; transition: border-color .15s ease;
}
.cloud-pop-action:hover, .cloud-pop-action:focus-visible { border-color: var(--accent-text); outline: none; }
.cloud-pop-close { margin-left: auto; border-color: transparent; background: transparent; color: var(--muted); }
/* The conflict and join decisions (app.js cloudConflict, cloudJoin): one choice per row with its consequence under
   it; the choice that replaces local work in the danger ink the chat menu uses; the failure line in the alert's amber. */
.cloud-conflict { width: min(552px, calc(100vw - 32px)); padding: 22px 30px 20px; border: 1px solid var(--line); border-radius: 12px; background: var(--panel); color: var(--ink); font-size: 13.5px; }
.cloud-conflict::backdrop { background: #0009; }
.cloud-conflict h2 { font-size: 17px; margin: 0 0 8px; }
.cloud-conflict p { line-height: 1.5; margin: 0 0 14px; color: var(--muted); font-size: 13px; }
.cloud-conflict-error { color: var(--amber); }
.cloud-conflict-error:empty { display: none; }
/* Each choice is one card: the label and its consequence together, the whole card clickable (app.js buildChoiceDialog
   forwards the click) and lit on hover or focus; the discarding one in the danger ink. Decide later, the least
   destructive, is a quiet row at the foot with its note beside it. The cards hang 12 px outside the text column on
   both sides (their padding), so every line of text, the heading's, the body's, the labels' and the notes', starts on
   one edge, and the Decide later button ends on the cards' edge. */
.cloud-choices { display: flex; flex-direction: column; gap: 8px; margin: 0 -12px; }
.cloud-choice {
  display: flex; flex-direction: column; align-items: flex-start; gap: 3px; padding: 10px 11px; /* 11 px plus the 1 px border: the text on the column exactly */
  border: 1px solid var(--line); border-radius: 10px; background: var(--panel-2); cursor: pointer; transition: border-color .15s ease;
}
.cloud-choice:hover, .cloud-choice:has(button:focus-visible) { border-color: var(--accent-text); }
.cloud-choice:has(button:disabled) { opacity: .5; cursor: default; }
.cloud-choice button { padding: 0; border: 0; background: transparent; color: var(--ink); font: inherit; font-size: 13.5px; font-weight: 600; text-align: left; cursor: inherit; }
.cloud-choice button:focus-visible { outline: none; } /* the card shows the focus */
.cloud-choice.discards button { color: var(--danger); }
.cloud-choice-note { font-size: 12px; line-height: 1.4; color: var(--muted); }
.cloud-choice.later { flex-direction: row-reverse; align-items: center; gap: 14px; margin-top: 6px; padding: 0 0 0 12px; border: 0; background: transparent; cursor: default; } /* the note on the text column's edge, the button on the cards' */
.cloud-choice.later button {
  flex: none; height: 30px; padding: 0 12px; border: 1px solid var(--line); border-radius: 8px; background: var(--panel);
  color: var(--muted); font-weight: 500; cursor: pointer; transition: border-color .15s ease, color .15s ease;
}
.cloud-choice.later:hover button, .cloud-choice.later button:focus-visible { border-color: var(--accent-text); color: var(--ink); }
.cloud-choice.later .cloud-choice-note { flex: 1 1 auto; }
/* The Arkio AI terms acknowledgment (app.js openAgentTerms, agent-terms.js DIALOG) in the cloud dialogs' chrome: the full
   notice, one checkbox with the Terms link in its sentence, Not now and Agree and continue at the right (the welcome's
   buttons, .fr-btn). Agree stays disabled until the box is ticked. */
.agent-terms-check { display: flex; align-items: flex-start; gap: 10px; margin: 0 0 14px; font-size: 13px; line-height: 1.5; color: var(--ink); cursor: pointer; }
.agent-terms-check input { flex: 0 0 auto; width: 16px; height: 16px; margin: 3px 0 0; accent-color: var(--accent); cursor: pointer; }
.agent-terms-check a { color: var(--accent-text); font-weight: 600; text-decoration: none; }
.agent-terms-check a:hover { text-decoration: underline; }
.agent-terms-actions { display: flex; justify-content: flex-end; gap: 10px; }
.agent-terms-actions .fr-btn:disabled { opacity: .5; cursor: default; }

/* ---- Notes tab (notes.js) ---- */
/* The list: the search, one row of controls (the Import tab's select chrome), the rows; Add note and Export at the foot. */
.nt-root { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
.nt-list { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; gap: 10px; padding: 12px 18px 16px; }
.nt-controls { display: flex; align-items: center; gap: 6px; flex: 0 0 auto; }
.nt-sort, .nt-filter { height: 26px; padding: 0 24px 0 8px; border: 1px solid var(--line); border-radius: 6px; background: var(--panel) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%235c6d66' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E") no-repeat right 6px center / 11px; color: var(--ink); font: inherit; font-size: 11.5px; appearance: none; -webkit-appearance: none; cursor: pointer; }
.nt-sort { flex: 1 1 124px; min-width: 0; } .nt-filter { flex: 1 1 118px; min-width: 0; } /* they give way, so the scene's toggle keeps its place */
.nt-spacer { flex: 1 1 auto; }
.nt-rows { flex: 1 1 auto; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; gap: 2px; margin: 0 -8px; padding: 0 8px; }
/* a row: the colour card the Review rows lead with, the words on one line, who, whom and when; the count at the right,
   Jump and the ⋮ under the pointer */
.nt-row { display: flex; align-items: center; gap: 10px; min-height: 54px; padding: 6px 6px 6px 8px; border-radius: 7px; cursor: pointer; }
.nt-row:hover, .nt-row.menu-open, .nt-row:focus-visible { background: var(--active-item, rgba(127, 127, 127, .14)); outline: none; }
.nt-row.is-open { background: var(--active-item, rgba(127, 127, 127, .14)); box-shadow: inset 2px 0 0 var(--accent); }
.nt-card { flex: 0 0 auto; width: 44px; height: 28px; display: grid; place-items: center; border-radius: 4px; color: var(--ink); box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .08); }
.nt-card.resolved { opacity: .8; }
.nt-main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.nt-text { font-size: 12.5px; line-height: 1.3; color: var(--ink); font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.nt-text.muted { color: var(--muted); text-decoration: line-through; text-decoration-color: rgba(94, 104, 105, .5); }
.nt-meta { display: flex; align-items: center; gap: 5px; font-size: 11px; color: var(--muted); white-space: nowrap; overflow: hidden; min-width: 0; }
.nt-meta > span { overflow: hidden; text-overflow: ellipsis; }
.nt-faint { opacity: .75; }
.nt-avatar { flex: 0 0 auto; display: grid; place-items: center; border-radius: 50%; color: #fff; font-size: 8px; font-weight: 600; line-height: 1; }
.nt-right { flex: 0 0 auto; display: inline-flex; align-items: center; gap: 4px; }
.nt-badge { display: inline-flex; align-items: center; gap: 3px; height: 18px; padding: 0 6px 0 5px; border-radius: 9px; background: var(--panel-2); color: var(--muted); font-size: 11px; font-weight: 600; }
.nt-row:hover .nt-badge, .nt-row.menu-open .nt-badge { display: none; }
.nt-act { flex: 0 0 auto; width: 24px; height: 24px; display: grid; place-items: center; padding: 0; border: 0; border-radius: 5px; background: transparent; color: var(--muted); cursor: pointer; }
.nt-act:hover:not(:disabled), .nt-act:focus-visible { color: var(--ink); background: var(--panel-2); outline: none; }
.nt-act:disabled { opacity: .5; cursor: default; }
.nt-jump, .nt-more { display: none; }
.nt-row:hover .nt-jump, .nt-row:hover .nt-more, .nt-row.menu-open .nt-more, .nt-row:focus-within .nt-jump, .nt-row:focus-within .nt-more { display: grid; }
.nt-menu { position: fixed; z-index: 60; min-width: 160px; padding: 4px; border: 1px solid var(--line); border-radius: 8px; background: var(--panel); box-shadow: 0 10px 30px rgba(0, 0, 0, .14); }
.nt-menu[hidden] { display: none; }
.nt-foot { flex: 0 0 auto; display: flex; gap: 8px; padding-top: 4px; }
.nt-primary { flex: 1 1 auto; display: flex; align-items: center; justify-content: center; gap: 6px; height: 32px; border: 1px solid var(--accent); border-radius: 8px; background: var(--accent); color: #fff; font: inherit; font-size: 12.5px; font-weight: 600; cursor: pointer; }
.nt-primary:hover:not(:disabled) { filter: brightness(1.05); }
.nt-primary:disabled { opacity: .5; cursor: default; }
.nt-foot .rv-wide { flex: 0 0 auto; padding: 0 12px; }
.nt-empty { display: flex; flex-direction: column; align-items: center; gap: 8px; text-align: center; padding: 30px 12px; }
.nt-empty-glyph { width: 44px; height: 44px; display: grid; place-items: center; border-radius: 12px; background: var(--panel-2); color: var(--muted); }
.nt-empty-title { font-size: 13px; font-weight: 600; color: var(--ink); }
/* A note open: the still, its row, the words in the composer's field, the colours and Resolved, Assigned to, the facts, the comments. */
.nt-note { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
.nt-head { flex: 0 0 auto; display: flex; align-items: center; gap: 6px; padding: 8px 10px 8px 8px; border-bottom: 1px solid var(--line); }
.nt-head .nt-act { width: 28px; height: 28px; }
.nt-title { flex: 1 1 auto; font-size: 13px; font-weight: 600; color: var(--ink); }
.nt-pill { display: inline-flex; align-items: center; gap: 3px; height: 18px; padding: 0 6px 0 5px; border-radius: 9px; background: var(--panel-2); color: var(--muted); font-size: 11px; font-weight: 600; }
.nt-pill.is-accent { background: var(--accent-soft); color: var(--accent-text); }
.nt-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; gap: 12px; padding: 12px 14px 10px; }
.nt-still { flex: 0 0 auto; aspect-ratio: 292 / 150; border-radius: 8px; overflow: hidden; border: 1px solid var(--line); background: var(--panel-2); display: grid; place-items: center; color: var(--muted); }
.nt-still img { display: block; width: 100%; height: 100%; object-fit: cover; }
.nt-viewrow { display: flex; align-items: center; gap: 8px; margin-top: -4px; }
.nt-viewrow .header-btn { display: inline-flex; align-items: center; gap: 6px; height: 26px; padding: 0 9px; border-radius: 7px; font-size: 11.5px; font-weight: 500; }
.nt-words { width: 100%; min-height: 60px; resize: none; overflow: hidden; padding: 10px 12px; border: 1px solid var(--line); border-radius: 10px; background: var(--bg); color: var(--ink); font: inherit; font-size: 14px; line-height: 1.45; }
.nt-words:focus { border-color: var(--accent-text); outline: none; }
.nt-words[readonly] { color: var(--muted); }
.nt-counter { margin-top: -8px; text-align: right; font-size: 10.5px; color: var(--muted); }
.nt-counter[hidden] { display: none; }
.nt-rowline { display: flex; align-items: center; justify-content: space-between; gap: 12px; min-height: 30px; }
.nt-label { font-size: 12.5px; color: var(--ink); }
.nt-swatches { display: flex; align-items: center; gap: 8px; }
.nt-swatch { width: 24px; height: 24px; display: grid; place-items: center; padding: 0; border: 0; border-radius: 50%; background: transparent; cursor: pointer; }
.nt-swatch > span { width: 18px; height: 18px; border-radius: 50%; box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .10); }
.nt-swatch[aria-pressed="true"] > span { box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .10), 0 0 0 2px var(--panel), 0 0 0 4px var(--accent); }
.nt-swatch:disabled { cursor: default; opacity: .6; }
.nt-swatch-yellow { background: #fbe9a6; } .nt-swatch-red { background: #f7c9c2; } .nt-swatch-green { background: #cfe8c9; } .nt-swatch-blue { background: #cfe3ee; }
.nt-resolved { display: inline-flex; align-items: center; gap: 10px; font-size: 12.5px; color: var(--ink); cursor: pointer; }
.nt-resolved input { appearance: none; -webkit-appearance: none; width: 34px; height: 18px; margin: 0; border-radius: 9px; background: var(--line); position: relative; cursor: pointer; transition: background .15s ease; }
.nt-resolved input::after { content: ''; position: absolute; top: 2px; left: 2px; width: 14px; height: 14px; border-radius: 50%; background: #fff; box-shadow: 0 1px 2px rgba(0, 0, 0, .25); transition: left .15s ease; }
.nt-resolved input:checked { background: var(--accent); }
.nt-resolved input:checked::after { left: 18px; }
.nt-resolved input:disabled { opacity: .5; cursor: default; }
.nt-assignee { width: 150px; height: 24px; padding: 0 8px; border: 1px solid var(--line); border-radius: 6px; background: var(--panel); color: var(--ink); font: inherit; font-size: 11.5px; }
.nt-assignee:focus { border-color: var(--accent-text); outline: none; }
.nt-rule { width: 100%; height: 1px; margin: 0; border: 0; background: var(--line); flex: 0 0 auto; }
.nt-facts { display: flex; flex-direction: column; gap: 5px; font-size: 11.5px; color: var(--muted); }
.nt-facts > span { display: flex; align-items: center; gap: 6px; }
.nt-section { display: flex; flex-direction: column; gap: 4px; }
.nt-cap { font-size: 11.5px; font-weight: 600; letter-spacing: .07em; text-transform: uppercase; color: var(--muted); }
.nt-hint { margin: 0; font-size: 11.5px; line-height: 1.45; color: var(--muted); }
.nt-comment { position: relative; display: flex; gap: 8px; padding: 6px; border-radius: 7px; }
.nt-comment:hover, .nt-comment.is-open { background: var(--active-item, rgba(127, 127, 127, .14)); }
.nt-comment-body { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.nt-comment-who { display: flex; align-items: center; gap: 6px; font-size: 11.5px; color: var(--muted); }
.nt-comment-who > span:first-child { font-weight: 600; color: var(--ink); }
.nt-comment-text { font-size: 12.5px; line-height: 1.45; color: var(--ink); white-space: pre-wrap; overflow-wrap: anywhere; }
.nt-composer { display: flex; align-items: flex-end; gap: 8px; padding-top: 6px; }
.nt-composer .nt-avatar { align-self: center; }
.nt-comment-input { flex: 1 1 auto; min-width: 0; min-height: 30px; resize: none; overflow: hidden; padding: 6px 10px; border: 1px solid var(--line); border-radius: 8px; background: var(--bg); color: var(--ink); font: inherit; font-size: 12.5px; line-height: 1.4; }
.nt-comment-input:focus { border-color: var(--accent-text); outline: none; }
.nt-send { width: 30px; height: 30px; color: var(--accent-text); }
.nt-note .nt-foot { padding: 10px 14px 14px; border-top: 1px solid var(--line); }
.nt-danger { color: var(--danger); }
/* The scene's toggle at the end of the controls row, the selects' height: Collapse all in scene, or Expand all, pressed,
   once nothing is expanded. */
.nt-scene-toggle { flex: 0 0 auto; width: 26px; height: 26px; display: grid; place-items: center; padding: 0; border: 1px solid var(--line); border-radius: 6px; background: var(--panel); color: var(--muted); cursor: pointer; }
.nt-scene-toggle:hover:not(:disabled), .nt-scene-toggle:focus-visible { border-color: var(--accent-text); color: var(--ink); outline: none; }
.nt-scene-toggle.is-on { background: var(--active-item, rgba(127, 127, 127, .14)); color: var(--ink); }
.nt-scene-toggle:disabled { opacity: .5; cursor: default; }
/* The mic at the view row's end, the composer's square button at the row's one height: the accent while Unity records,
   the app's ring while it transcribes, and a line under the field that says which. */
.nt-mic { flex: 0 0 auto; width: 26px; height: 26px; display: grid; place-items: center; padding: 0; border: 1px solid var(--line); border-radius: 7px; background: var(--panel); color: var(--ink); cursor: pointer; transition: border-color .15s ease, background .15s ease; }
.nt-mic:hover:not(:disabled), .nt-mic:focus-visible { border-color: var(--accent-text); outline: none; }
.nt-mic.is-recording { border-color: var(--accent); background: var(--accent); color: var(--accent-ink); }
.nt-mic.is-busy { cursor: progress; }
.nt-mic:disabled:not(.is-busy) { opacity: .5; cursor: default; }
.nt-dictation { display: flex; align-items: center; gap: 6px; margin-top: -6px; font-size: 11px; color: var(--accent-text); }
.nt-dictation.is-busy { color: var(--muted); }
.nt-rec { flex: 0 0 auto; width: 7px; height: 7px; border-radius: 50%; background: var(--accent); }
/* The element line of the facts: the link, the element's name and category cut to the line, the unlink. */
.nt-element { min-width: 0; }
.nt-element > svg { flex: 0 0 auto; margin: 0 1px; }
.nt-element-name { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.nt-unlink { flex: 0 0 auto; width: 18px; height: 18px; display: grid; place-items: center; padding: 0; border: 0; border-radius: 4px; background: transparent; color: var(--muted); opacity: .7; cursor: pointer; }
.nt-unlink:hover, .nt-unlink:focus-visible { opacity: 1; color: var(--ink); background: var(--panel-2); outline: none; }
/* A comment's reactions: the group chat's chips under the words and its picker over the row (.gc-reactions, .gc-picker);
   React at the end of the who line under the pointer, on someone else's comment only. */
.nt-react { margin-left: auto; display: none; padding: 0; border: 0; background: transparent; color: var(--accent-text); font: inherit; font-size: 11.5px; font-weight: 600; cursor: pointer; }
.nt-comment:hover .nt-react, .nt-comment:focus-within .nt-react, .nt-comment.is-open .nt-react { display: inline; }
.nt-react:hover, .nt-react:focus-visible { text-decoration: underline; outline: none; }
.nt-comment .gc-reactions { margin-top: 3px; }
.nt-comment .gc-picker { top: -40px; right: 6px; }
/* The comment badge over the player (notes.js createNoteBadges): the list's comment pill in the dimension pills' dress,
   on the note's top-right shoulder, fading with the note's line of sight. */
#note-badge-layer { position: absolute; inset: 0; z-index: 2; overflow: hidden; pointer-events: none; }
#note-badge-layer[hidden] { display: none; }
.note-badge { position: absolute; left: 0; top: 0; display: inline-flex; align-items: center; gap: 3px; height: 18px; padding: 0 6px 0 5px; border: 1px solid var(--line); border-radius: 9px; background: var(--panel); color: var(--muted); box-shadow: 0 2px 8px rgba(0, 0, 0, .18); font: inherit; font-size: 11px; font-weight: 600; line-height: 1; cursor: pointer; pointer-events: auto; opacity: 1; transition: opacity .15s ease; }
.note-badge:hover, .note-badge:focus-visible { border-color: var(--accent-text); color: var(--ink); outline: none; }
.note-badge.is-hidden { opacity: 0; pointer-events: none; }
/* The element under the pointer while a note is placed or moved (notes.js createNoteHover): a pill in the dimension
   pills' dress beside the pointer, as the drag readout follows it, with the element line's link. */
#note-hover-layer { position: absolute; inset: 0; z-index: 2; overflow: hidden; pointer-events: none; }
#note-hover-layer[hidden] { display: none; }
.note-hover { position: absolute; left: 0; top: 0; display: inline-flex; align-items: center; gap: 5px; padding: 3px 8px 3px 7px; border: 1px solid var(--line); border-radius: 6px; background: var(--panel); color: var(--ink); box-shadow: 0 2px 8px rgba(0, 0, 0, .18); font-size: 12px; line-height: 1.3; white-space: nowrap; pointer-events: none; }
.note-hover svg { flex: 0 0 auto; color: var(--accent-text); }
/* The group chat's thread cards and note events (group-chat.js): a note's messages gathered under the note; who added or
   resolved a note, with Jump to note; the note on the composer as a chip while a reply is written. */
.gc-thread { align-self: stretch; display: flex; flex-direction: column; gap: 8px; padding: 8px 10px 10px 12px; border: 1px solid var(--line); border-left: 4px solid var(--note-color, var(--line)); border-radius: 8px; background: var(--panel-2); }
.gc-thread-head { display: flex; align-items: center; gap: 8px; }
.gc-thread-from { flex: 1 1 auto; min-width: 0; font-size: 11px; font-weight: 600; letter-spacing: .07em; text-transform: uppercase; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.gc-thread-words { font-size: 12.5px; line-height: 1.4; color: var(--ink); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.gc-thread-runs { display: flex; flex-direction: column; gap: 10px; }
.gc-thread .gc-run.other .gc-bubble { background: var(--panel); }
.gc-thread-foot { display: flex; align-items: center; gap: 10px; font-size: 12px; color: var(--muted); }
.gc-thread-foot button, .gc-jump { display: inline-flex; align-items: center; gap: 5px; padding: 0; border: 0; background: transparent; color: var(--accent-text); font: inherit; font-size: 12px; font-weight: 600; cursor: pointer; white-space: nowrap; }
.gc-thread-foot button:hover, .gc-jump:hover, .gc-thread-foot button:focus-visible, .gc-jump:focus-visible { text-decoration: underline; outline: none; }
.gc-jump svg { width: 13px; height: 13px; }
.gc-jump.header-btn { height: 26px; padding: 0 9px; border: 1px solid var(--line); border-radius: 7px; color: var(--ink); font-weight: 500; text-decoration: none; }
.gc-jump.header-btn:hover { border-color: var(--accent-text); }
.gc-event { align-self: stretch; display: flex; flex-direction: column; gap: 6px; }
.gc-event-who { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--muted); }
.gc-event-who .gc-name { font-weight: 600; color: var(--ink); }
.gc-event-card { display: flex; align-items: center; gap: 10px; padding: 8px 10px 8px 12px; border: 1px solid var(--line); border-left: 4px solid var(--note-color, var(--line)); border-radius: 8px; background: var(--panel-2); }
.gc-event-card .gc-thread-words { flex: 1 1 auto; min-width: 0; }
.gc-chip-thumb.is-note { color: var(--ink); }
.gc-chip-thumb.is-note svg { width: 15px; height: 15px; }

/* Cloud-library controls are provisional; retain the existing row/menu focus and contrast behavior. */

/* ---- the Media place (media-place.js, canvas page 27): every AI render and video of this browser's chats, drilled into
   the left column under the column's own header. The filters and the sort on one row (the sort wraps under them in a
   narrow column), then 16:9 tiles that share the column's width: two to a row at the design's 300 px, one in a column
   too narrow for two to stay legible, three once it is dragged wide, as the design note has it; a track never takes
   its width from a caption, which ellipsizes. A tile's Open chat and ⋮ sit over its picture and show under the
   pointer, with the keyboard on the tile and while its menu is open; a touch screen, which has no pointer to hover,
   shows them always. The place scrolls its own tiles. ---- */
.mp { flex: 1 1 auto; height: 100%; min-height: 0; display: flex; flex-direction: column; }
.mp-bar { flex: 0 0 auto; display: flex; flex-wrap: wrap; align-items: center; gap: 6px 5px; padding: 2px 10px 8px; }
.mp-filters { flex: 0 0 auto; display: flex; gap: 5px; }
.mp-chip { height: 22px; padding: 0 9px; border: 1px solid var(--line); border-radius: 6px; background: transparent; color: var(--muted); font: inherit; font-size: 11.5px; font-weight: 600; line-height: 1; cursor: pointer; transition: border-color .15s ease, color .15s ease; }
.mp-chip:hover, .mp-chip:focus-visible { color: var(--ink); border-color: var(--accent-text); outline: none; }
.mp-chip[aria-pressed="true"] { border-color: var(--accent-text); background: var(--accent-soft); color: var(--ink); }
.mp-sort { margin-left: auto; flex: 0 1 auto; min-width: 0; height: 22px; padding: 0 22px 0 7px; border: 1px solid var(--line); border-radius: 6px; background: var(--panel) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%235c6d66' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E") no-repeat right 6px center / 11px; color: var(--ink); font: inherit; font-size: 11.5px; appearance: none; -webkit-appearance: none; cursor: pointer; }
.mp-sort:hover, .mp-sort:focus-visible { border-color: var(--accent-text); outline: none; }
/* the status line under the filters (a word on Open chat, a Download from Downloading… to Download started, a failure's
   reason): a live region that stays in the tree, taking no room while it is empty, so a word arriving is announced */
.mp-notice { flex: 0 0 auto; margin: -2px 12px 6px; font-size: 11.5px; line-height: 1.35; color: var(--muted); }
.mp-notice:empty { margin: 0; }
.mp-scroll { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 0 5px 10px; }
.mp-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 105px), 1fr)); gap: 4px 2px; align-content: start; }
.mp-tile { min-width: 0; display: flex; flex-direction: column; gap: 5px; padding: 5px; border-radius: 9px; transition: background .15s ease; }
.mp-tile:hover, .mp-tile:focus-within, .mp-tile.menu-open { background: var(--chat-hover, rgba(127,127,127,.08)); }
.mp-thumb { position: relative; aspect-ratio: 16 / 9; border: 1px solid var(--line); border-radius: 6px; overflow: hidden; background: var(--panel); container-type: inline-size; }
/* the picture is a real button so the keyboard reaches it; Open chat and the ⋮ are its siblings, over it */
.mp-frame { position: absolute; inset: 0; display: block; width: 100%; height: 100%; padding: 0; margin: 0; border: 0; border-radius: 0; background: transparent; color: var(--muted); font: inherit; cursor: pointer; }
.mp-frame:focus-visible { outline: 2px solid var(--accent-text); outline-offset: -2px; }
.mp-pic { display: block; width: 100%; height: 100%; object-fit: cover; }
.mp-placeholder { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px; padding: 6px; font-size: 11px; line-height: 1.25; text-align: center; }
.mp-placeholder .spinner { width: 18px; height: 18px; border-width: 2px; }
.mp-placeholder.is-failed { color: var(--danger); }
.mp-detail { color: var(--muted); font-size: 10.5px; }
.mp-placeholder.is-failed .mp-detail { color: inherit; font-weight: 600; text-decoration: underline; }
.mp-play { position: absolute; left: 50%; top: 50%; width: 28px; height: 28px; transform: translate(-50%, -50%); display: grid; place-items: center; border-radius: 50%; background: rgba(21, 32, 33, .62); color: #fff; pointer-events: none; }
.mp-play svg { width: 15px; height: 15px; fill: currentColor; margin-left: 2px; }
.mp-length { position: absolute; right: 5px; bottom: 5px; height: 16px; padding: 0 5px; display: inline-flex; align-items: center; border-radius: 4px; background: rgba(21, 32, 33, .72); color: #fff; font-size: 10px; font-weight: 600; font-variant-numeric: tabular-nums; pointer-events: none; }
.mp-chat, .mp-more { position: absolute; display: inline-flex; align-items: center; justify-content: center; height: 22px; border: 1px solid var(--line); border-radius: 6px; background: var(--panel); font: inherit; cursor: pointer; opacity: 0; transition: opacity .12s ease, border-color .15s ease, color .15s ease; }
.mp-chat { left: 5px; bottom: 5px; gap: 5px; padding: 0 8px; color: var(--ink); font-size: 11px; font-weight: 600; white-space: nowrap; }
.mp-more { right: 5px; top: 5px; width: 22px; padding: 0; color: var(--muted); }
.mp-tile:hover .mp-chat, .mp-tile:hover .mp-more, .mp-tile:focus-within .mp-chat, .mp-tile:focus-within .mp-more,
.mp-tile.menu-open .mp-chat, .mp-tile.menu-open .mp-more { opacity: 1; }
@media (hover: none) { .mp-chat, .mp-more { opacity: 1; } }
/* a picture too narrow for the words keeps Open chat as its glyph (named by its tooltip), clear of a video's length */
@container (max-width: 123px) { .mp-chat { width: 22px; padding: 0; } .mp-chat-label { display: none; } }
.mp-chat:hover, .mp-chat:focus-visible, .mp-more:hover, .mp-more:focus-visible, .mp-tile.menu-open .mp-more { border-color: var(--accent-text); color: var(--ink); outline: none; }
.mp-caption { font-size: 12px; line-height: 1.25; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mp-meta { margin-top: -3px; font-size: 11px; line-height: 1.3; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mp-foot:empty { display: none; }
/* the foot under the tiles: the gathering with its quiet spinner and the agent's pause, or the chats that could not be
   checked with their one action (Retry, Log in), wrapping in the narrow column; the line takes focus when its action
   went with it, so the status that follows is read */
.mp-line { margin: 14px 8px; text-align: center; font-size: 12px; line-height: 1.4; color: var(--muted); overflow-wrap: anywhere; }
.mp-line:focus { outline: none; }
.mp-line:focus-visible { outline: 2px solid var(--accent-text); outline-offset: 2px; border-radius: 4px; }
.mp-line .spinner { display: inline-block; width: 12px; height: 12px; margin: 0 6px -2px 0; border-width: 2px; border-color: var(--line); border-top-color: var(--accent); }
.mp-line-detail { display: block; margin-top: 2px; }
.mp-line-action { border: 0; padding: 0 2px; background: transparent; color: var(--accent-text); font: inherit; font-size: 12px; font-weight: 600; cursor: pointer; }
.mp-line-action:hover, .mp-line-action:focus-visible { text-decoration: underline; outline: none; }
.mp-note { margin: 4px 10px 10px; text-align: center; font-size: 11px; line-height: 1.4; color: var(--muted); }
.mp-empty { display: flex; flex-direction: column; align-items: center; gap: 8px; padding: 30px 14px; text-align: center; font-size: 12px; line-height: 1.45; color: var(--muted); }
.mp-empty-glyph { width: 44px; height: 44px; display: grid; place-items: center; border-radius: 12px; background: var(--panel); color: var(--muted); }
.mp-empty-title { font-size: 13px; font-weight: 600; color: var(--ink); }
/* the ⋮'s menu: at the body's level, above the column, with the chat menu's items (.session-menu-item); a failed
   preview's reason at its top, where touch reaches it */
.mp-menu { position: fixed; z-index: 60; min-width: 170px; max-width: min(300px, calc(100vw - 16px)); padding: 4px; border: 1px solid var(--line); border-radius: 8px; background: var(--panel); color: var(--ink); box-shadow: 0 10px 30px rgba(0, 0, 0, .14); }
.mp-menu-note { margin: 4px 8px 6px; padding-bottom: 6px; border-bottom: 1px solid var(--line); font-size: 11.5px; line-height: 1.4; color: var(--muted); }

/* ---- the mode chip (index.html #edit-mode, app.js renderEditMode): Viewing in the header's plain pill with the muted ink,
   Editing in the pressed look of the header's two switches; the Share tab's eye or pencil before the word, a chevron
   after. Its menu is the Share tab's access menu (.sh-menu) under the chip: the two modes to pick from when the choice
   is the user's, else the reason in one line (.em-reason) and, for an editor link signed out, Sign in to edit. While
   Viewing, the tools that change the model and the History group hide; a tool or a group is display-set, so [hidden]
   needs saying. ---- */
#edit-mode { align-self: center; }
#edit-mode-btn { display: inline-flex; align-items: center; gap: 6px; padding: 0 8px 0 10px; }
#edit-mode-btn[hidden] { display: none; }
#edit-mode-btn[data-mode="view"] { color: var(--muted); }
#edit-mode-btn[data-mode="edit"], #edit-mode-btn[aria-expanded="true"] { border-color: var(--accent-text); }
#edit-mode-btn[data-mode="edit"] { background: var(--accent-soft); color: var(--accent-text); }
.em-glyph, .em-chevron { display: inline-flex; }
.em-glyph svg { width: 14px; height: 14px; }
.em-chevron svg { width: 11px; height: 11px; }
#edit-mode-menu .em-reason { margin: 0; padding: 2px 8px 8px; font-size: 11.5px; line-height: 1.4; color: var(--muted); white-space: normal; }
/* the Sign in button is a header button inside the Share tab's menu, whose option rules (.vb-picker button, .sh-menu
   button) outrank .header-btn and would make it an option row: restate the button at the menu's size */
#edit-mode-menu .em-action { display: inline-flex; align-items: center; justify-content: center; min-height: 0; height: 26px; margin: 0 8px 6px; padding: 0 10px; border: 1px solid var(--line); border-radius: 6px; background: transparent; color: var(--ink); font-size: 11.5px; font-weight: 600; text-align: center; align-self: flex-start; }
#edit-mode-menu .em-action:hover, #edit-mode-menu .em-action:focus-visible { border-color: var(--accent-text); background: transparent; outline: none; }
/* the option's body is a picker span, which the picker keeps on one line with an ellipsis (.vb-picker button > span); these
   two lines of explanation wrap instead */
#edit-mode-menu .sh-menu-body { white-space: normal; overflow: visible; }
.tool[hidden], .tool-group[hidden], .tool-sep[hidden] { display: none; }

/* ---- the portrait layout (app.js syncLayoutMode): a phone held upright, told by the viewport, the same build everywhere ---- */
/* The chats list is the drawer and the chat is always the dock under the player, open by default (app.js resolvePanes and
   the collapsed chat's own fraction). The rail and the panel are moved into the scene body and float over the player,
   below the toolbar and above the dock, so neither takes width from a 390px scene: the rail a translucent strip at the
   right edge, the panel sliding in over the player to its left behind a scrim, as the chats drawer does at the left.
   They sit under the scene's own overlays (#session-state at 4, #render-viewer at 5), which keep covering the body. */
body[data-layout="portrait"] #rail {
  position: absolute; top: 0; right: 0; bottom: 0; z-index: 3; width: var(--rail-w); height: auto; /* out of the flex, the width is set here */
  background: var(--panel); background: color-mix(in srgb, var(--panel) 88%, transparent);
}
/* The panel leaves a thumb's width of the player beside it, so the scrim can be tapped on a 375px phone, where it would
   otherwise reach the left edge. */
body[data-layout="portrait"] #panel {
  position: absolute; top: 0; right: var(--rail-w); bottom: 0; z-index: 3; height: auto; min-width: 0; width: min(360px, calc(100% - var(--rail-w) - 44px));
  box-shadow: -8px 0 28px rgba(0, 0, 0, .28); animation: panel-in .18s ease;
}
/* No virtual joysticks on a phone held upright (Embla, 2026-10-14): two 120px sticks would cover most of a 327px-wide player
   that is already down to a few hundred pixels of height, and touch navigation on the scene itself does the job. The
   hint pill, which keeps clear of the sticks on touch, gets the player's width back. */
body[data-layout="portrait"] #joysticks { display: none; }
body[data-layout="portrait"] #hint-pill { max-width: calc(100% - 20px); }
@keyframes panel-in { from { transform: translateX(100%); } }
@media (prefers-reduced-motion: reduce) { body[data-layout="portrait"] #panel { animation: none; } }
#panel-scrim { position: absolute; inset: 0; z-index: 3; background: rgba(4, 8, 6, .4); }
#panel-scrim[hidden] { display: none; }
/* The rail docked away (app.js setRail, applyPanelChrome): the player has the whole width, and the way back is #rail-open at
   the toolbar's right end, pulled into the toolbar's padding as the list's way back is at the left. */
#rail[hidden] { display: none; }
#scene-header #rail-open { margin-right: -4px; }
/* The portrait layout's toolbar is always two rows, the palette its own strip: under 640px the row never holds it, in
   Editing (702px) nor, once the rail's way back joins the row, in Viewing (430px + 32px). The same strip rules as the
   steps above; :has(#tools) only lifts them over the 900px / 550px rules, which carry an id in their :has(). */
body[data-layout="portrait"] #scene-header:has(#tools) #edit-mode-sep { display: none; }
body[data-layout="portrait"] #scene-header:has(#tools) #navigate { height: 41px; margin-bottom: -1px; position: relative; z-index: 1; }
body[data-layout="portrait"] #scene-header:has(#tools) #tools { position: static; transform: none; order: 1; flex: 1 0 calc(100% + 24px); height: 40px; margin: 0 -12px -1px; padding-right: 4px; justify-content: flex-end; border-top: 1px solid var(--line); }
body[data-layout="portrait"] #scene-header:has(#tools) #scene-actions { margin-left: auto; }
/* With both ways back in the row (the list's and the rail's, 32px each) the tight row comes 32px sooner again than with
   the list's alone (386px), and the halved gaps likewise (300px): a 375px phone has 1px to spare, a 360px one is 14px
   over until the gaps halve. */
@container (max-width: 418px) {
  body[data-layout="portrait"] #scene-header:has(#rail-open:not([hidden])) #history, body[data-layout="portrait"] #scene-header:has(#rail-open:not([hidden])) #navigate { gap: 0; }
  body[data-layout="portrait"] #scene-header:has(#rail-open:not([hidden])) #history .tool, body[data-layout="portrait"] #scene-header:has(#rail-open:not([hidden])) #navigate .tool { width: 26px; }
  body[data-layout="portrait"] #scene-header:has(#rail-open:not([hidden])) #navigate .tool-chevron { width: 16px; }
  body[data-layout="portrait"] #scene-header:has(#rail-open:not([hidden])) #history-sep { display: none; }
}
@container (max-width: 340px) {
  body[data-layout="portrait"] #scene-header:has(#rail-open:not([hidden])) > * + * { margin-left: -4px; } /* the same halving; the strip's own margin rule outranks this */
}
/* Viewing on a phone at least 390px wide (content 366px) keeps the one row (Embla, 2026-10-14): with the row's four
   items and both ways back at 295px it has 71px over, and the three tools come down to that from 120px by taking
   navigate's 26px cells with no gap (78px) and the row's gaps halving (-20), the same moves as the steps above: 365px
   of 366. The mode chip keeps its chevron, as in Editing, which is why the floor is 390px and not 375px (the chevron's
   15px). Under that, and in Editing at any width (undo, redo and five more tools, about 260px), the palette keeps its
   strip. The tools reach over the header's hairline as navigate does, so the active tool's line lies on it.
   :has(#tools) lifts this over the strip rules above. */
@container (min-width: 365px) {
  body[data-layout="portrait"] #scene-header:has(#history[hidden]):has(#tools) #tools {
    position: relative; left: auto; top: auto; bottom: auto; transform: none; z-index: 1; /* in the row, over the hairline like navigate; the centred rule's left: 50% would still shift a relative box */
    order: 0; flex: 0 0 auto; height: 48px; margin: 0 auto -1px -4px; padding: 0; gap: 0; /* the auto margin pushes the switches right; the -4px is the halved gap, which this shorthand would otherwise undo */
    justify-content: flex-start; border-top: 0;
  }
  /* The one row is the 48px header, not the 40px strip row the tight step sizes navigate for: both groups take 49px here,
     over the hairline (48px, since the header's 48px includes that hairline), so their glyphs centre with the chip and the
     switches within the 1px their 3px line costs (a 41px group sat 4.5px high). */
  body[data-layout="portrait"] #scene-header:has(#history[hidden]):has(#tools) #navigate { height: 48px; }
  body[data-layout="portrait"] #scene-header:has(#history[hidden]):has(#tools) #tools .tool { width: 26px; }
  body[data-layout="portrait"] #scene-header:has(#history[hidden]):has(#tools) #scene-actions { margin-left: -4px; } /* the halved gap again, over the strip rule's auto */
  body[data-layout="portrait"] #scene-header:has(#history[hidden]):has(#tools) > * + * { margin-left: -4px; }
}
