/*
 * Design tokens for Askaboard. Dark only.
 * Every colour, size, radius and shadow in the app comes from this file.
 */
:root {
  color-scheme: dark;

  /* Surfaces, from back to front */
  --bg-app: #111113;
  --bg-sidebar: #111113;
  --bg-canvas: #161618;
  --bg-elevated: #1c1c1f;
  --bg-elevated-2: #232327;
  --bg-hover: rgba(255, 255, 255, 0.05);
  --bg-active: rgba(255, 255, 255, 0.08);

  /* Lines */
  --border-subtle: rgba(255, 255, 255, 0.08);
  --border-strong: rgba(255, 255, 255, 0.13);
  --canvas-dot: rgba(255, 255, 255, 0.07);
  --canvas-dot-pitch: 24px;
  /* The board dot grid's opaque colour; Board.tsx fades it with --grid-alpha per zoom. */
  --canvas-dot-solid: #ffffff;
  --preview-checker: #222226; /* second checker square behind image previews (first: --bg-elevated) */

  /* Text */
  --text-primary: #ececef;
  --text-secondary: #a0a0a8;
  --text-tertiary: #6b6b73;
  --text-on-accent: #0d0f1a;

  /* Accent */
  --accent: #6e8bff;
  --accent-hover: #8299ff;
  --accent-soft: rgba(110, 139, 255, 0.14);
  --accent-ring: rgba(110, 139, 255, 0.45);
  --accent-tile-from: rgba(110, 139, 255, 0.28); /* empty-state icon tile gradient */
  --accent-tile-to: rgba(110, 139, 255, 0.08);
  --accent-tile-border: rgba(110, 139, 255, 0.35);

  /* Status */
  --status-idle: #5c5c64;
  --status-live: #4ade80;
  --status-warn: #fbbf24;
  --status-bad: #f87171;
  /* The halo around a status dot, and the peak of the live pulse */
  --status-idle-ring: rgba(92, 92, 100, 0.18);
  --status-live-ring: rgba(74, 222, 128, 0.18);
  --status-live-pulse: rgba(74, 222, 128, 0.35);
  --status-error-ring: rgba(255, 107, 139, 0.18);
  --status-warn-ring: rgba(251, 191, 36, 0.18);
  --status-bad-ring: rgba(248, 113, 113, 0.18);
  /* A playing scene's dot (the scene pill): the accent with a soft ring */
  --status-play: var(--accent);
  --status-play-ring: var(--accent-soft);

  /* Canvas tools: selection, lasso, eraser */
  --selection-fill: rgba(110, 139, 255, 0.05);
  --lasso-fill: rgba(110, 139, 255, 0.08);
  --eraser-ring: rgba(255, 255, 255, 0.6);
  --eraser-halo: rgba(0, 0, 0, 0.5);

  --selection-border: 1.5px;
  /* The rotate handle of a selected text */
  --handle-rotate-size: 11px; /* the circle */
  --handle-rotate-reach: 24px; /* its centre above the top edge of the selection */
  --handle-rotate-stem: 20px; /* the stem up from the top edge */
  --handle-rotate-stem-width: 1px;
  --handle-rotate-hit: 8px; /* the stem and the circle take a press this far around them: one handle */

  /* Snapshot: the grid, labels and tags drawn into the image agents see */
  --snapshot-grid: rgba(255, 255, 255, 0.14);
  --snapshot-axis: rgba(255, 255, 255, 0.32);
  --snapshot-label: rgba(255, 255, 255, 0.75);
  --snapshot-label-outline: #000000;
  --snapshot-tag-outline: rgba(0, 0, 0, 0.55);
  /* preview_scene marks: the learner's view, the parts app UI covers, and their tags */
  --snapshot-view: rgba(255, 255, 255, 0.6);
  --snapshot-covered-fill: rgba(0, 0, 0, 0.38);
  --snapshot-covered-edge: rgba(255, 255, 255, 0.45);
  --snapshot-mark-bg: rgba(0, 0, 0, 0.78);
  --snapshot-mark-text: rgba(255, 255, 255, 0.92);
  --snapshot-mark-ring: rgba(255, 255, 255, 0.35);

  /* Ink colours, tuned for the dark canvas */
  --ink-white: #ececef;
  --ink-yellow: #f5d76e;
  --ink-blue: #6e8bff; /* the agents' accent blue */
  --ink-purple: #b58cff;
  --ink-green: #5fd38d;
  --ink-pink: #ff6b8b;
  --ink-orange: #ff9f45;

  /* Type */
  --font-ui: -apple-system, BlinkMacSystemFont, 'SF Pro Text', 'Inter', sans-serif;
  --font-mono: ui-monospace, 'SF Mono', Menlo, monospace;
  --text-xs: 11px;
  --text-sm: 12px;
  --text-base: 13px;
  --text-lg: 15px;
  --text-xl: 20px;
  --leading: 1.45;

  /* Spacing (4px grid) */
  --space-half: 2px; /* the half step: stacked lines of one text block */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 20px;
  --space-6: 24px;
  --space-8: 32px;

  /* Radii (U16: one notch rounder). An inner fill's radius is its outer radius less the padding between them. */
  --radius-sm: 6px;
  --radius-md: 9px;
  --radius-lg: 12px;
  --radius-xl: 16px;
  --radius-pill: 999px;
  --popup-radius: 14px; /* a popup surface: a menu, a popover, the dropdown list, the script panel (its rows: this less its 6 px padding) */
  /* By size (U17): a 22–26 px fill (an icon button, a title-row pill, a tooltip, a key cap) takes --radius-md; a 28–34 px
     row or button takes --row-radius; a surface with content inside (a toast, a code block) --radius-lg. */
  --row-radius: var(--control-radius); /* a sidebar row, the folder row, a title-row button, a welcome row or button */
  --handle-radius: 3px; /* a 9 px selection handle on the board */

  /* Shadows (U16): soft and wide, low contrast; a light inner line at the top, a wide blur, a small close shadow */
  --shadow-float: 0 1px 0 rgba(255, 255, 255, 0.05) inset, 0 12px 40px rgba(0, 0, 0, 0.24),
    0 2px 8px rgba(0, 0, 0, 0.14);
  --shadow-card: 0 1px 0 rgba(255, 255, 255, 0.05) inset, 0 24px 80px rgba(0, 0, 0, 0.3),
    0 4px 16px rgba(0, 0, 0, 0.16);

  /* Glass (U16): a popup surface lets a little of the board through. Menus, popovers, the dropdown list; never a modal panel or a tooltip. */
  --bg-glass: rgba(28, 28, 31, 0.93); /* --bg-elevated */
  --bg-glass-2: rgba(35, 35, 39, 0.93); /* --bg-elevated-2 */
  --glass-filter: blur(24px) saturate(140%);

  /* Layout */
  --sidebar-width: 248px;
  --topbar-height: 44px;
  --titlebar-height: 44px;
  /*
   * The title row: the 44 px row across the window (the sidebar strip and the top bar). The macOS window buttons
   * are three 14 px circles at a 23 px pitch: x 16 to 76 window px, centre line on the row's centre (measured in a
   * window capture, 2026-11-06). Main places them for the Interface Size factor f (main/interface-size.ts) and sets
   * --window-buttons-end on .shell to 76 / f; the value here is the 100% one.
   */
  --window-buttons-end: 76px; /* the right edge of the macOS window buttons at 100% */
  --window-buttons-gap: 16px; /* from that edge to the first title-row button */
  --title-row-inset: var(--space-3); /* the first button's left edge in full screen, on Linux and on Windows */
  --title-button-size: 28px; /* a title-row icon button's hit area (16 px icon; Back and Forward 20 px chevrons): Back, Forward, the sidebar button, New board */
  --title-button-gap: var(--space-1); /* between neighbouring title-row buttons */
  --disabled-opacity: 0.5; /* a disabled control: Back or Forward with nowhere to go, a disabled small button */
  --tooltip-gap: 6px; /* from a control to its tooltip (below it, or above it when there is no room) */
  --tooltip-margin: var(--space-2); /* a tooltip keeps this far inside the window */
  --sidebar-row-height: 30px; /* every sidebar row: New board, Search boards, a board */
  --folder-row-height: 32px; /* the folder button in the sidebar footer (one line): --space-1 under the footer's line, --space-2 on the other sides */
  --topbar-rename-width: 240px; /* the board name's rename field in the top bar (sidebar hidden) */
  /* The board controls (U10, U13): three quiet pills over the canvas bottom */
  --tools-pill-height: 40px; /* the tool pill */
  --tool-size: 30px; /* a tool button */
  --tool-icon-size: 17px; /* its lucide icon (stroke 1.75) */
  --corner-button-size: 28px; /* a bare corner button (zoom out, zoom in, undo, redo) */
  --corner-icon-size: 15px;
  --corner-group-gap: 8px; /* between undo and zoom */
  --style-pill-height: 40px; /* the style pill: as tall as the tool pill */
  --swatch-size: 28px; /* a colour swatch's hit area */
  --swatch-dot: 15px; /* the pen ring inside it (InkGlyph.tsx PenRing) */
  --option-size: 26px; /* a style option (width, pen or marker, fill, line, heads, size, font, align) */
  --option-icon-size: 15px; /* an option's lucide icon */
  --option-text-pad: 9px; /* the side padding of a text option (S, M, L, XL) */
  --option-bar-width: 12px; /* the bar of a width or line option */
  --option-fill-size: 12px; /* the square of a fill option (none, light, solid) */
  --pill-bar-pad: var(--space-1); /* a pill's side padding */
  --pill-divider-height: 16px; /* the line between groups in a pill */
  --pill-divider-gap: 5px; /* on each side of that line */
  --zoom-label-min: 42px; /* the zoom % label */
  /* A toast shows above the tool pill and the style pill */
  --toast-bottom: calc(var(--space-3) + var(--tools-pill-height) + var(--space-2) + var(--style-pill-height) + var(--space-3));
  --pill-height: 26px;
  --pill-gap: 7px; /* between a pill's dot, label and parts */
  --pill-action-size: 20px; /* the one icon button inside a pill (scene pill: pause / resume) */
  --pill-label-max: 160px; /* a pill label longer than this ends with an ellipsis */
  --icon-button-size: 24px;
  --status-dot-size: 7px;
  --status-dot-size-small: 6px; /* a status dot in a panel header */
  --status-dot-ring: 2px; /* the halo width around a status dot */
  /* The chat panel (web only, design A): a column right of the board, as the sidebar is on the left */
  --chat-panel-width: 320px;
  --chat-header-pad: 0 var(--space-3) 0 var(--space-4); /* the header is --topbar-height high */
  --chat-messages-pad: var(--space-4) var(--space-4) var(--space-1);
  --chat-bubble-max: 85%; /* a learner message's widest */
  --chat-bubble-pad: var(--space-2) var(--space-3);
  --chat-user-gap: var(--space-4); /* below a learner message */
  --chat-line-gap: var(--space-3); /* below the agent's text and below an activity line */
  --chat-activity-gap: 6px; /* between an activity line's icon and its words */
  --chat-activity-icon: 14px;
  --chat-composer-margin: 0 var(--space-3) var(--space-3);
  --chat-input-pad-top: 10px;
  --chat-input-pad-bottom: var(--space-1);
  --chat-input-pad-x: var(--space-3);
  --chat-input-lines: 8; /* the field grows to this many lines, then scrolls */
  --chat-row-pad: var(--space-1) 6px 6px var(--space-3); /* the composer's bottom row */
  --chat-button-size: 28px; /* Send and Stop */
  --chat-detail-indent: calc(var(--chat-activity-icon) + var(--chat-activity-gap)); /* an activity line's details start under its words */
  --chat-detail-gap: var(--space-2); /* between the tool calls of the details */
  --chat-detail-pad: var(--space-1) var(--space-2); /* inside an input or result block */
  --chat-chevron-size: 12px; /* the chevron of an expandable activity line */
  --chat-footer-pad: 0 var(--space-4) 10px; /* the web app's footer under the composer: the credit, the account */
  --chat-footer-font: var(--text-xs);

  /* The web app's sign-in screen (decision P30; mockup approved 2026-11-09) */
  --sign-in-width: 320px; /* the card */
  --sign-in-pad: var(--space-6);
  --sign-in-tile: 36px; /* the logo tile */
  --sign-in-mark: 22px; /* the mark inside it */
  --sign-in-title-font: 16px;
  --sign-in-title-weight: 560;
  --sign-in-lede-font: var(--text-sm);
  --sign-in-divider-font: var(--text-xs);
  --sign-in-gap: var(--space-3); /* above Sign in, Use another email and an error line */
  --sign-in-tile-gap: 14px; /* below the logo tile */
  --sign-in-title-gap: var(--space-1); /* between the title and its line */
  --sign-in-head-gap: var(--space-5); /* below the line */
  --sign-in-divider-gap: var(--space-4); /* above and below the "or" divider */
  --sign-in-email-gap: var(--space-2); /* between the email field and Email me a code */
  --sign-in-digit-width: 36px; /* one box of the 6-digit code */
  --sign-in-digit-height: 42px;
  --sign-in-digit-font: 18px;
  --sign-in-digit-gap: 6px;

  /* The script panel floating over the board */
  --script-panel-width: 296px;
  --script-panel-header: 34px;
  --script-panel-footer-pad: 4px 5px 6px 11px;
  --step-bar-height: 3px; /* the reading panel's step bar: one segment per step */
  --step-bar-gap: 3px;
  --step-bar-radius: var(--radius-pill);
  --step-bar-hit: 12px; /* the step bar's click and hover band (it looks 3 px high) */
  /* The reading view: the scene's lines scroll past a light that follows the reading point */
  --reading-view-height: 176px; /* fixed, so the footer never moves */
  --reading-view-gap: 8px; /* between the step bar and the view */
  --reading-para-gap: 10px; /* between two lines (paragraphs) */
  --reading-said: 0.22; /* the alpha of the text above the light (said) */
  --reading-next: 0.5; /* the alpha of the text below the light (next) */
  --reading-light: 14px; /* full brightness this far above and below the reading point */
  --reading-light-ramp: 60px; /* the light fades out until this far from the reading point */
  --reading-band-offset: 4px; /* a selected item's step: its first line starts this far below the top of the bright band */
  --leading-current: 1.6; /* the reading view's lines */
  /* The search panel (⌘K): a modal panel over the whole window */
  --backdrop: rgba(0, 0, 0, 0.4); /* behind a modal panel, over the whole window */
  --search-panel-width: 520px; /* at most the window width − 2 × --panel-margin-x */
  --search-panel-height: 460px; /* fixed (the list scrolls; short results leave space under them); at most the window height − 2 × --panel-margin-y */
  --panel-margin-x: 16px; /* the least space between a modal panel and the window's sides */
  --panel-margin-y: 32px; /* the least space between a modal panel and the window's top and bottom */
  /* The Settings dialog (U12): a modal panel with a section list and a pane; it shrinks to the window within the margins above */
  --settings-dialog-width: 760px;
  --settings-dialog-height: 600px; /* the key sheet's two columns fit without scrolling (U15) */
  --panel-nav-width: 208px; /* a split panel's section list (.menu__nav) */
  --trust-dialog-width: 300px; /* the trust question (U19): a title, one line and a footer; at most the window width − 2 × --panel-margin-x */
  --setting-field-width: 200px; /* a text field as a setting's control (the Gemini key) */
  --radio-size: 14px; /* a choice's radio mark (.menu__radio) */
  --radio-dot: 6px; /* its dot when chosen */
  --panel-field-height: 46px; /* a modal panel's field (.menu--panel .menu__field) */
  --panel-row-height: 32px; /* a modal panel's rows (.menu--panel .menu__item) */
  /* The splash (U20): the start screen with no folder, over the whole window (components/splash) */
  --splash-width: 700px; /* at most the window width − 2 × --panel-margin-x */
  --splash-band-height: 350px; /* the drawing band; at most the card width ÷ --splash-band-aspect, and it shrinks first in a short window; the drawing scales with it */
  --splash-band-aspect: 2; /* the band's width ÷ its height at most */
  --splash-band-min-height: 160px;
  --splash-dot-pitch: 20px; /* the breathing grid's pitch in the 680 × 340 mockup units (art.ts reads it and scales it with the band) */
  --splash-tree-bark: rgb(62, 52, 52); /* "Blossom tree" (tree.ts): the branches, a warm grey that reads on --bg-canvas */
  --splash-tree-core: rgb(20, 17, 18); /* the dark ink core of the trunk and thick limbs */
  --splash-tree-rim: rgb(226, 208, 196); /* the lit rim and dry-brush streaks of the bark, the wash at the base */
  --splash-moon: rgb(255, 242, 226); /* the pale disc behind the tree, drawn at a very low alpha */
  --splash-blossom-crimson: rgb(204, 30, 58);
  --splash-blossom-rose: rgb(230, 72, 104);
  --splash-blossom-pink: rgb(242, 134, 164);
  --splash-blossom-pale: rgb(250, 198, 212);
  --splash-blossom-white: rgb(253, 243, 238);
  --splash-name-font: 17px;
  --splash-name-left: 18px;
  --splash-name-bottom: 14px;
  --splash-panel-gap: 14px;
  --splash-panel-pad: 14px 12px 12px;
  --splash-heading-pad: 2px 9px 6px;
  --splash-row-height: 30px;
  --splash-row-pad-x: 9px;
  --splash-footer-pad: 9px 21px 12px;

  /* Motion */
  --fade: 220ms ease; /* quiet fade in and out (scene pill, script panel) */
  --into-pill: 260ms ease; /* the panel shrinks into the scene pill (and grows out of it) */
  --into-pill-scale: 0.06;
  --reading-ease: 120ms; /* the reading view's focus and scroll follow their targets with this time constant (exponential) */
  --reading-return: 3000ms; /* while a scene plays, the focus glides back to the reading point this long after the last wheel input */
  --pill-flash: 450ms ease; /* the scene pill lights up once when the panel went into it */
  --ease-out-soft: cubic-bezier(0.16, 1, 0.3, 1); /* a calm arrival: fast at first, a long soft stop */
  --splash-rise: 520ms var(--ease-out-soft); /* the splash card rises into place */
  --splash-rise-offset: 12px;
  --splash-rise-scale: 0.98;
  --splash-item: 420ms var(--ease-out-soft); /* the splash's title, rows and footer come in one after the other */
  --splash-item-offset: 6px;
  --splash-item-delay: 260ms; /* the first item, after the card starts to rise */
  --splash-stagger: 45ms;

  /* The select (U14): the app's own dropdown (components/Select.tsx, .menu__select and .menu--select in app.css) */
  --bg-field: rgba(255, 255, 255, 0.06); /* a control's soft fill: the select's trigger */
  --bg-field-hover: rgba(255, 255, 255, 0.09);
  --select-chevron-pad: 10px; /* the trigger's chevron side is a little tighter than --control-pad-x */
  --select-list-min-width: 200px; /* at least the trigger's width too */
  --select-list-radius: var(--popup-radius); /* no max height: the list shows every row, up to the room in the window (Select.tsx) */
  --select-list-pad: 6px;
  --select-option-height: 28px;
  --select-option-pad: 0 10px;

  /* The small control (U15): one look for the select's trigger and the small button (.btn-sm), one CSS rule in app.css */
  --control-height: 30px;
  --control-height-menu: 24px; /* the same in a popup menu's compact rows (the agent popover, the setup flyout): the rows' 24 px */
  --control-pad-x: 12px;
  --control-radius: 10px;
  /* The switch (U17): in a setting row beside 30 px controls; a popup menu (the performance popover) takes the menu size */
  --switch-width: 36px;
  --switch-height: 20px;
  --switch-knob: 16px;
  --switch-width-menu: 26px;
  --switch-height-menu: 14px;
  --switch-knob-menu: 10px;
  --switch-inset: 2px; /* the knob's inset from the track's edge */

  /* Settings spacing (U15): the rules every Settings section uses, named for their role, on the 4 px scale */
  --settings-pane-pad-y: var(--space-6); /* the pane's top and bottom, and the section list's */
  --settings-pane-pad-x: calc(var(--space-6) + var(--space-1)); /* 28 px: the pane's sides */
  --settings-title-size: 16px; /* the section title */
  --settings-title-gap: var(--space-2); /* under the title row */
  --setting-row-pad-y: var(--space-4); /* above and below a setting's text */
  --setting-row-gap: var(--space-4); /* between a setting's text and its control */
  --setting-desc-gap: var(--space-1); /* from a setting's name to its description */
  --setting-desc-leading: 1.4;
  --settings-group-gap: var(--space-5); /* above a group heading */
  --settings-heading-gap: var(--space-1); /* under a group heading */
  /* The keyboard shortcut sheet (Settings > Keyboard shortcuts) */
  --keys-line-height: 30px;
  --keys-column-min: 220px; /* one column when the pane has no room for two of these */
  --keys-column-gap: var(--space-8);
  --keys-caps-width: 80px; /* the caps' column, so the names line up (the widest macOS keys, ⌘ ⇧ ] and Space drag, U17; a longer one pushes its name) */
  --keys-name-gap: var(--space-3); /* from the caps to the name */
  --keycap-size: 24px; /* a key cap's least width and its height (U17) */
  --keycap-pad: 0 6px;
  --keycap-font: 12px; /* a cap's text, and the "or" and "drag" words */
  --keycap-symbol-font: 13px; /* a modifier glyph (⌘ ⇧ ⌥ ⌃), so it reads as large as a letter */
  --keycap-radius: var(--radius-md);
  --keycap-gap: 3px; /* between the caps of one combo */

  /* Scrollbars (U14): one style for every scroll area (app.css, "Scrollbars"): a 6 px thumb, no track, shown on hover and scroll */
  --scrollbar-size: 6px; /* the thumb's width, and the gutter a .scroll-area takes out of its right padding */
  --scrollbar-thumb: rgba(255, 255, 255, 0.18);
  --scrollbar-thumb-hover: rgba(255, 255, 255, 0.3);
}

/* The hand as a font: scripts/lab/make-hand-webfont.mjs makes both files. main.tsx loads both before the first render. */
@font-face {
  font-family: 'Learning Hand';
  src: url('./hand-De1twFhN.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: block;
}
/* The same hand with a wider line and the same metrics, for screens of low pixel density (board/content.css). */
@font-face {
  font-family: 'Learning Hand Heavy';
  src: url('./hand-heavy-I99Ja_K3.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: block;
}
*,
*::before,
*::after {
  box-sizing: border-box;
}

html,
body,
#root {
  height: 100%;
  margin: 0;
}

body {
  background: var(--bg-app);
  color: var(--text-primary);
  font-family: var(--font-ui);
  font-size: var(--text-base);
  line-height: var(--leading);
  -webkit-font-smoothing: antialiased;
  user-select: none;
  overflow: hidden;
}

button {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  padding: 0;
  cursor: default;
}

button:focus-visible {
  outline: 2px solid var(--accent-ring);
  outline-offset: 1px;
}

.mono {
  font-family: var(--font-mono);
}

/* ---------- Shell ---------- */

.shell {
  /* The first title-row button's left edge: after the macOS window buttons in a window; --title-row-inset in full screen and off macOS. */
  --chrome-reserve: var(--title-row-inset);
  display: grid;
  grid-template-columns: var(--sidebar-width) 1fr;
  height: 100%;
}

.shell[data-window-buttons] {
  --chrome-reserve: calc(var(--window-buttons-end) + var(--window-buttons-gap));
}

/* View > Hide Sidebar: one column, at once (no width animation: the board would repaint each frame). */
.shell[data-sidebar-hidden] {
  grid-template-columns: 1fr;
}

.main {
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
  background: var(--bg-canvas);
}

.workspace {
  display: flex;
  flex: 1;
  min-height: 0;
}

/* ---------- Sidebar ---------- */

.sidebar {
  display: flex;
  flex-direction: column;
  min-height: 0;
  background: var(--bg-sidebar);
  border-right: 1px solid var(--border-subtle);
}

.sidebar[hidden] {
  display: none;
}

/*
 * The top strip, in every state where the sidebar shows, level with the top bar (one 44 px title row, one centre line
 * with the window buttons). It holds the title lead (.title-lead: Back, Forward, the sidebar button) from --chrome-reserve,
 * the same x as in the top bar with the sidebar hidden: a click on the sidebar button never moves it. 4 px above the first row.
 */
.sidebar__strip {
  display: flex;
  align-items: center;
  height: var(--titlebar-height);
  flex-shrink: 0;
  margin-bottom: var(--space-1);
  padding-left: var(--chrome-reserve);
  -webkit-app-region: drag;
}

.sidebar__strip button {
  -webkit-app-region: no-drag;
}

/* The title lead (components/TitleLead.tsx): one group in the strip and in the top bar, so its buttons keep their x. */
.title-lead {
  display: flex;
  align-items: center;
  flex-shrink: 0;
  gap: var(--title-button-gap);
}

/* New board, Search boards, Set up for learning: sidebar rows above the boards. */
.sidebar__actions {
  display: flex;
  flex-direction: column;
  flex-shrink: 0;
  padding: 0 var(--space-2) var(--space-2);
}

.sidebar__scroll {
  --scroll-pad-end: var(--space-2); /* a .scroll-area */
  flex: 1;
  padding: 0 var(--space-2) var(--space-4);
}

.section + .section {
  margin-top: var(--space-4);
}

.section__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 28px;
  padding: 0 var(--space-1) 0 var(--space-2);
}

.section__title {
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-tertiary);
}

.section__empty {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-1) var(--space-2);
  font-size: var(--text-sm);
  color: var(--text-tertiary);
}

.sidebar__footer {
  display: flex;
  align-items: center;
  flex-shrink: 0;
  /* 4 px under the hairline; 8 px from the sidebar's edges and the window bottom */
  padding: var(--space-1) var(--space-2) var(--space-2);
  border-top: 1px solid var(--border-subtle);
}

/* The folder row: one line, the folder icon, its name and the chevrons; a click opens the folder menu above it. */
.folder-row {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  width: 100%;
  height: var(--folder-row-height);
  padding: 0 var(--space-2);
  border-radius: var(--row-radius);
  text-align: left;
  transition: background 120ms ease;
}

.folder-row:hover,
.folder-row[aria-expanded='true'] {
  background: var(--bg-hover);
}

.folder-row__icon {
  flex-shrink: 0;
  color: var(--text-secondary);
}

.folder-row__name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  color: var(--text-primary);
  font-size: var(--text-base);
  white-space: nowrap;
  text-overflow: ellipsis;
}

.folder-row__chevron {
  flex-shrink: 0;
  color: var(--text-tertiary);
}

/* ---------- Generic icon button ---------- */

.icon-button {
  display: grid;
  place-items: center;
  flex-shrink: 0;
  width: var(--icon-button-size);
  height: var(--icon-button-size);
  border-radius: var(--radius-md);
  color: var(--text-tertiary);
  transition: background 120ms ease, color 120ms ease;
}

.icon-button:hover:not(:disabled) {
  background: var(--bg-hover);
  color: var(--text-primary);
}

/* Nothing to do now (Back with no board before): tertiary and faded, no hover fill. The shared tooltip still names it. */
.icon-button:disabled {
  color: var(--text-tertiary);
  opacity: var(--disabled-opacity);
  cursor: default;
}

/* A panel's header controls: secondary text colour, primary on hover. */
.icon-button--strong {
  color: var(--text-secondary);
}

/* A title-row button (the sidebar button, New board): a larger hit area, the same 16 px icon. */
.icon-button--title {
  width: var(--title-button-size);
  height: var(--title-button-size);
  border-radius: var(--row-radius);
}

/* ---------- Tooltip ---------- */

/*
 * The one tooltip (components/Tooltip.tsx; design-system.md, "Tooltips"). A control asks for it with
 * {...tip(label, shortcut)}; no native `title` in app UI. It names an icon-only control or a shortcut, never
 * internal data (a path, an id) and never the visible label again.
 *
 *   .tooltip        a small label in a portal: after 500 ms of hover (at once from one tooltip control to the
 *                   next within 300 ms), and on :focus-visible; never on a press; hidden on leave, a key, a
 *                   click, a scroll; below the control (--tooltip-gap), above it when there is no room
 *   .tooltip__key   the shortcut after the label, tertiary
 */
.tooltip {
  position: fixed;
  z-index: 1000;
  left: 0;
  top: 0;
  visibility: hidden;
  padding: var(--space-1) var(--space-2);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-md);
  background: var(--bg-elevated-2);
  box-shadow: var(--shadow-float);
  color: var(--text-primary);
  font-size: var(--text-xs);
  line-height: var(--leading);
  white-space: nowrap;
  pointer-events: none;
}

.tooltip__key {
  margin-left: var(--space-2);
  color: var(--text-tertiary);
}

/* ---------- Top bar ---------- */

.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  height: var(--topbar-height);
  flex-shrink: 0;
  padding: 0 var(--space-3) 0 var(--space-4);
  background: var(--bg-app);
  /* The line under the bar is drawn inside it, not as a border: the content box stays 44 px, so the bar's centre line is the title row's (22 px). */
  box-shadow: inset 0 -1px 0 var(--border-subtle);
  -webkit-app-region: drag;
  container: topbar / inline-size;
}

/* The bar drags the window; every control in it takes clicks, selections and focus instead. */
.topbar :is(button, input, textarea, select, a, [role='button'], [tabindex]) {
  -webkit-app-region: no-drag;
}

/* While a menu is open the strips take clicks (lib/dismiss.ts, useDragStripsOff): a press there closes the menu, as on macOS. */
:root[data-menu-open] :is(.topbar, .sidebar__strip) {
  -webkit-app-region: no-drag;
}

.topbar__title {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-width: 0;
  overflow: hidden;
  color: var(--text-secondary);
}

/* With the sidebar hidden: the title lead and New board from --chrome-reserve (as in the strip), then the board name. */
.shell[data-sidebar-hidden] .topbar {
  padding-left: var(--chrome-reserve);
}

/* The title's own gap (8 px) and this margin put the board name 12 px after the last button. */
.topbar .title-lead {
  margin-right: calc(var(--space-3) - var(--space-2));
}

/* No board open: the folder name, or "Askaboard" without a folder. */
.topbar__folder {
  overflow: hidden;
  color: var(--text-secondary);
  white-space: nowrap;
  text-overflow: ellipsis;
}

.topbar__rename {
  flex: 0 1 var(--topbar-rename-width);
}

.topbar__board {
  color: var(--text-primary);
  font-weight: 560;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.topbar__right {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

/* A title-row status item (agent, scene, performance): no border or capsule; a hover and an open state. */
.pill {
  display: inline-flex;
  align-items: center;
  gap: var(--pill-gap);
  flex-shrink: 0;
  height: var(--pill-height);
  padding: 0 var(--space-2);
  white-space: nowrap;
  border-radius: var(--radius-md);
  font-size: var(--text-sm);
  color: var(--text-secondary);
  transition: background 120ms ease;
}

.pill:hover {
  background: var(--bg-hover);
}

/*
 * Pill parts (a "pill" is the title row's status item; it has no capsule shape). A pill is a button (the agent pill) or, with --static, a plain
 * holder of one control (the scene pill):
 *   .pill__label   the main text; long text ends with an ellipsis
 *   .pill__count   a count after the label ("· 2/5"); its .pill__sep is the "· "
 *   .pill__time    a time or number in mono, tabular figures
 *   .pill__action  the one small icon button, at the right end
 *   .pill__toggle  a plain button around the dot and text of a static pill (the scene
 *                  pill: shows or collapses the script panel); the pill hovers with it
 *   .pill--flash   the pill lights up once (the scene pill, when the reading panel went into it,
 *                  or when it wakes up for a selected item)
 *   .pill--selected the pill speaks of what the learner selected: its text in --text-primary
 */
.pill--static:hover {
  background: none;
}

.pill--static:has(.pill__toggle:hover) {
  background: var(--bg-hover);
}

.pill__toggle {
  display: inline-flex;
  align-items: center;
  gap: var(--pill-gap);
  min-width: 0;
  height: 100%;
  color: inherit;
}

.pill--static:has(.pill__toggle) {
  /* the toggle reaches the pill's left edge, so the whole left part is the button */
  padding-left: 0;
}

.pill--static:has(.pill__toggle) .pill__toggle {
  padding-left: var(--space-2);
}

.pill--static:has(.pill__action) {
  /* the button sits evenly inside the pill's hover area */
  padding-right: calc((var(--pill-height) - var(--pill-action-size)) / 2);
}

.pill__label {
  min-width: 0;
  max-width: var(--pill-label-max);
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.pill__count {
  flex-shrink: 0;
  margin-left: calc(var(--space-1) - var(--pill-gap));
  white-space: nowrap;
}

.pill__time {
  flex-shrink: 0;
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  color: var(--text-tertiary);
}

.pill__action {
  display: grid;
  flex-shrink: 0;
  place-items: center;
  width: var(--pill-action-size);
  height: var(--pill-action-size);
  border-radius: var(--radius-pill);
  color: var(--text-secondary);
  transition: background 120ms ease, color 120ms ease;
}

.pill__action:hover:not(:disabled) {
  background: var(--bg-hover);
  color: var(--text-primary);
}

.status-dot {
  flex-shrink: 0;
  width: var(--status-dot-size);
  height: var(--status-dot-size);
  border-radius: 50%;
  background: var(--status-idle);
  box-shadow: 0 0 0 var(--status-dot-ring) var(--status-idle-ring);
}

.status-dot--small {
  width: var(--status-dot-size-small);
  height: var(--status-dot-size-small);
}

.pill--selected {
  color: var(--text-primary);
}

.pill--open,
.pill--static.pill--open {
  background: var(--bg-active);
  color: var(--text-primary);
}

.pill--flash {
  animation: pill-flash var(--pill-flash);
}

@keyframes pill-flash {
  0%,
  100% {
    background: transparent;
  }
  30% {
    background: var(--accent-soft);
  }
}

.status-dot--live {
  background: var(--status-live);
  box-shadow: 0 0 0 var(--status-dot-ring) var(--status-live-ring);
}

.status-dot--play {
  background: var(--status-play);
  box-shadow: 0 0 0 var(--status-dot-ring) var(--status-play-ring);
}

.status-dot--error {
  background: var(--ink-pink);
  box-shadow: 0 0 0 var(--status-dot-ring) var(--status-error-ring);
}

.status-dot--warn {
  background: var(--status-warn);
  box-shadow: 0 0 0 var(--status-dot-ring) var(--status-warn-ring);
}

.status-dot--bad {
  background: var(--status-bad);
  box-shadow: 0 0 0 var(--status-dot-ring) var(--status-bad-ring);
}

/* One pulse per agent tool call. */
.status-dot--pulse {
  animation: status-pulse 900ms ease-out;
}

@keyframes status-pulse {
  0% {
    box-shadow: 0 0 0 2px var(--status-live-ring);
  }
  35% {
    box-shadow: 0 0 0 6px var(--status-live-pulse);
  }
  100% {
    box-shadow: 0 0 0 2px var(--status-live-ring);
  }
}

/* ---------- Connect an agent ---------- */

.agent-pill {
  position: relative;
}

/* The agent popover: layout only (position and width); the content is shared .menu parts. */
.menu.agent-pop {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  width: 300px;
  max-height: calc(100vh - var(--topbar-height) - 24px);
  overflow-y: auto;
  -webkit-app-region: no-drag;
}


/* ---------- Scene pill ---------- */

/* The scene pill: shrinks before the agent pill; fades in and out (usePresence). Its menu is the shared menu below it. */
.scene-pill {
  position: relative;
  opacity: 0;
  transition: opacity var(--fade);
}

.scene-pill.is-shown {
  opacity: 1;
}

/* The scene pill's menu: layout only (position and width); the content is shared .menu parts. */
.menu.scene-pop {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  width: 300px;
  max-height: calc(100vh - var(--topbar-height) - 24px);
  overflow-y: auto;
  -webkit-app-region: no-drag;
}

/* ---------- Performance pill ---------- */

.perf-pill {
  position: relative;
}

/* A modal panel's backdrop: over the whole window, the native window buttons stay above it. It is no drag region, so a press on it closes the panel and never moves the window. */
.backdrop {
  position: fixed;
  inset: 0;
  z-index: 200;
  background: var(--backdrop);
  -webkit-app-region: no-drag;
}

/* The search panel (⌘K): layout only (centred in the window both ways, a fixed width and height); the content is shared .menu parts. */
.menu.search-panel {
  inset: 0;
  width: min(var(--search-panel-width), calc(100vw - 2 * var(--panel-margin-x)));
  height: min(var(--search-panel-height), calc(100vh - 2 * var(--panel-margin-y)));
  margin: auto;
}

/* The Settings dialog (⌘,, U12): layout only (centred in the window both ways, a fixed width and height that shrink to the window); the content is shared .menu parts. */
.menu.settings-dialog {
  inset: 0;
  width: min(var(--settings-dialog-width), calc(100vw - 2 * var(--panel-margin-x)));
  height: min(var(--settings-dialog-height), calc(100vh - 2 * var(--panel-margin-y)));
  margin: auto;
}

/* The trust question (U19): layout only (centred in the window both ways, a fixed width, the height of its content); the content is shared .menu parts. */
.menu.trust-dialog {
  inset: 0;
  width: min(var(--trust-dialog-width), calc(100vw - 2 * var(--panel-margin-x)));
  height: fit-content;
  margin: auto;
}

/* The performance pill's menu: layout only (position and width); the content is shared .menu parts. */
.menu.perf-pop {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  width: 264px;
  max-height: calc(100vh - var(--topbar-height) - 24px);
  overflow-y: auto;
  -webkit-app-region: no-drag;
}

/* ---------- Script panel ---------- */

/*
 * The reading panel (ScriptPanel.tsx, decision B19): one scene in a small frame over the board;
 * the one exception to "UI does not cover the board". The learner drags it by its header;
 * ScriptPanel sets left, top and max-height.
 *   .script-panel__header    34 px: small status dot, the scene name, one hide button
 *   .script-panel__bar       the step bar: one .script-panel__segment per step (flex = its length, a 12 px hit band)
 *                            around its 3 px __track and __fill
 *   .script-panel__view      the reading view: fixed height, its __text (the scene's lines, one __para each) moves
 *                            up (translateY); a mask lights the reading point (--reading-at) and dims the rest
 *   .script-panel__footer    one __status, then the icon buttons
 *   .is-into-pill            shrunk toward the scene pill (hide); with .is-at-pill at once (the start of an open from the pill)
 */
.script-panel {
  position: absolute;
  z-index: 5;
  display: flex;
  flex-direction: column;
  width: min(var(--script-panel-width), calc(100% - 2 * var(--space-3)));
  overflow: hidden;
  background: var(--bg-elevated);
  border: 1px solid var(--border-strong);
  border-radius: var(--popup-radius);
  box-shadow: var(--shadow-float);
  opacity: 0;
  transition: opacity var(--fade), transform var(--into-pill);
}

.script-panel.is-shown {
  opacity: 1;
}

.script-panel.is-into-pill {
  opacity: 0;
  transform: scale(var(--into-pill-scale));
  transition: opacity var(--into-pill), transform var(--into-pill);
}

/* An open from the pill starts there at once, then grows to its place. */
.script-panel.is-into-pill.is-at-pill {
  transition: none;
}

.script-panel__header {
  display: flex;
  flex-shrink: 0;
  align-items: center;
  gap: var(--space-2);
  height: var(--script-panel-header);
  padding: 0 calc((var(--script-panel-header) - var(--icon-button-size)) / 2) 0 var(--space-3);
  cursor: grab;
  user-select: none;
  touch-action: none;
}

.script-panel__header:active {
  cursor: grabbing;
}

.script-panel__title {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  font-size: var(--text-sm);
  color: var(--text-secondary);
}

.script-panel__header .icon-button,
.script-panel__footer .icon-button {
  flex-shrink: 0;
  cursor: default;
}

.script-panel__bar {
  position: relative;
  z-index: 1; /* its hit band reaches over the header's bottom edge */
  display: flex;
  flex-shrink: 0;
  gap: var(--step-bar-gap);
  /* it takes the room of the 3 px track; the hit band goes past it on both sides */
  margin: calc((var(--step-bar-height) - var(--step-bar-hit)) / 2) 0;
  padding: 0 var(--space-3);
}

.script-panel__segment {
  display: flex;
  flex: 1 1 0;
  align-items: center;
  min-width: 0;
  height: var(--step-bar-hit);
}

.script-panel__track {
  position: relative;
  width: 100%;
  height: var(--step-bar-height);
  overflow: hidden;
  border-radius: var(--step-bar-radius);
  background: var(--border-subtle);
}

.script-panel__fill {
  position: absolute;
  inset: 0 auto 0 0;
  background: var(--text-tertiary);
}

.script-panel.is-playing .script-panel__fill {
  background: var(--accent);
}

.script-panel__view {
  --reading-at: 50%; /* the focus in the view (the reading point, or where the wheel or a selection put it); ScriptPanel sets it each frame */
  position: relative;
  flex: 0 1 auto;
  height: var(--reading-view-height);
  min-height: 0;
  margin-top: var(--reading-view-gap);
  overflow: hidden;
  -webkit-mask-image: linear-gradient(
    to bottom,
    rgb(0 0 0 / var(--reading-said)) calc(var(--reading-at) - var(--reading-light-ramp)),
    rgb(0 0 0 / 1) calc(var(--reading-at) - var(--reading-light)),
    rgb(0 0 0 / 1) calc(var(--reading-at) + var(--reading-light)),
    rgb(0 0 0 / var(--reading-next)) calc(var(--reading-at) + var(--reading-light-ramp))
  );
  mask-image: linear-gradient(
    to bottom,
    rgb(0 0 0 / var(--reading-said)) calc(var(--reading-at) - var(--reading-light-ramp)),
    rgb(0 0 0 / 1) calc(var(--reading-at) - var(--reading-light)),
    rgb(0 0 0 / 1) calc(var(--reading-at) + var(--reading-light)),
    rgb(0 0 0 / var(--reading-next)) calc(var(--reading-at) + var(--reading-light-ramp))
  );
}

.script-panel__text {
  position: relative; /* the lines' offsetTop is measured from here */
  padding: 0 var(--space-4);
  will-change: transform;
}

.script-panel__para {
  margin: 0 0 var(--reading-para-gap);
  font-size: var(--text-lg);
  line-height: var(--leading-current);
  color: var(--text-primary);
}

.script-panel__para:last-child {
  margin-bottom: 0;
}

/* A line of a scene that can play: a click plays the scene from it (the only hover effect is the cursor). */
.script-panel__para.is-playable {
  cursor: pointer;
}

.script-panel__footer {
  display: flex;
  flex-shrink: 0;
  align-items: center;
  padding: var(--script-panel-footer-pad);
}

.script-panel__status {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  font-size: var(--text-xs);
  /* as tall as the buttons, so the footer keeps its height with no button (the panel's box is one size) */
  line-height: var(--icon-button-size);
  color: var(--text-tertiary);
}

/* A narrow top bar keeps the step count, time and button; the step name goes (and the board name ends with an ellipsis). */
@container topbar (max-width: 760px) {
  .scene-pill .pill__label:has(+ .pill__count),
  .scene-pill .pill__sep {
    display: none;
  }

  .scene-pill .pill__count {
    margin-left: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .scene-pill,
  .script-panel,
  .script-panel.is-into-pill {
    transition: none;
  }

  .pill--flash {
    animation: none;
  }
}

/* ---------- Chat panel (web only, design A: components/ChatPanel.tsx) ---------- */

/* A third column right of the main column: the board gets narrower, nothing covers it. */
.shell[data-chat] {
  grid-template-columns: var(--sidebar-width) minmax(0, 1fr) var(--chat-panel-width);
}

.shell[data-chat][data-sidebar-hidden] {
  grid-template-columns: minmax(0, 1fr) var(--chat-panel-width);
}

.chat-panel {
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
  height: 100%;
  background: var(--bg-sidebar);
  border-left: 1px solid var(--border-subtle);
}

/* As the top bar: 44 px, its line drawn inside it. */
.chat-panel__header {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-shrink: 0;
  height: var(--topbar-height);
  padding: var(--chat-header-pad);
  box-shadow: inset 0 -1px 0 var(--border-subtle);
}

.chat-panel__title {
  font-size: var(--text-base);
  font-weight: 560;
  color: var(--text-primary);
}

.chat-panel__actions {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-left: auto;
}

.chat-panel__messages {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
  padding: var(--chat-messages-pad);
  --scroll-pad-end: var(--space-4); /* the .scroll-area's right padding: the same 16 px */
}

.chat-message {
  margin-bottom: var(--chat-line-gap);
  font-size: var(--text-base);
  line-height: var(--leading);
  color: var(--text-primary);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  user-select: text;
}

.chat-message--user {
  align-self: flex-end;
  max-width: var(--chat-bubble-max);
  margin-bottom: var(--chat-user-gap);
  padding: var(--chat-bubble-pad);
  background: var(--bg-elevated-2);
  border-radius: var(--radius-lg);
}

.chat-message--error {
  color: var(--status-bad);
}

.chat-activity {
  display: flex;
  align-items: center;
  gap: var(--chat-activity-gap);
  margin-bottom: var(--chat-line-gap);
  font-size: var(--text-sm);
  line-height: var(--leading);
  color: var(--text-tertiary);
}

.chat-activity__icon {
  display: grid;
  place-items: center;
  flex-shrink: 0;
  width: var(--chat-activity-icon);
  height: var(--chat-activity-icon);
}

/* An activity line with tool calls or thinking behind it: a click or Enter/Space shows them (.chat-detail). */
.chat-activity[data-expandable] {
  cursor: pointer;
  border-radius: var(--radius-sm);
}

.chat-activity[data-expandable]:hover {
  color: var(--text-secondary);
}

.chat-activity[data-expandable]:focus-visible {
  outline: 2px solid var(--accent-ring);
  outline-offset: 2px;
}

.chat-activity__text {
  min-width: 0;
  overflow-wrap: anywhere;
}

.chat-activity__chevron {
  display: grid;
  place-items: center;
  flex-shrink: 0;
  width: var(--chat-chevron-size);
  height: var(--chat-chevron-size);
  color: var(--text-tertiary);
  transition: transform 120ms ease;
}

.chat-activity__chevron[data-open] {
  transform: rotate(90deg);
}

/* The details: each tool call (name, failed, time; its input and result; images), or the thinking text. */
.chat-detail {
  display: flex;
  flex-direction: column;
  gap: var(--chat-detail-gap);
  min-width: 0;
  margin: calc(var(--space-1) - var(--chat-line-gap)) 0 var(--chat-line-gap) var(--chat-detail-indent);
}

.chat-call {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  min-width: 0;
}

.chat-call__head {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  font-size: var(--text-xs);
  line-height: var(--leading);
  color: var(--text-tertiary);
}

.chat-call__name {
  min-width: 0;
  font-family: var(--font-mono);
  color: var(--text-secondary);
  overflow-wrap: anywhere;
  user-select: text;
}

.chat-call__failed {
  color: var(--status-bad);
}

.chat-call__time {
  margin-left: auto;
  white-space: nowrap;
}

.chat-detail__text {
  margin: 0;
  padding: var(--chat-detail-pad);
  background: var(--bg-elevated);
  border-radius: var(--radius-sm);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  line-height: var(--leading);
  color: var(--text-secondary);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  user-select: text;
}

.chat-detail__text--plain {
  font-family: var(--font-ui);
  font-size: var(--text-sm);
}

.chat-detail__text[data-failed] {
  color: var(--status-bad);
}

.chat-detail__more {
  align-self: flex-start;
}

.chat-call__image {
  display: block;
  max-width: 100%;
  padding: 0;
  border: 0;
  background: none;
  cursor: zoom-in;
}

.chat-call__image img {
  display: block;
  max-width: 100%;
  border-radius: var(--radius-sm);
}

.chat-call__note {
  font-size: var(--text-xs);
  color: var(--text-tertiary);
}

/* A tool result's image, larger, on the window's backdrop: a click or Escape closes it. */
.chat-image-view {
  display: grid;
  place-items: center;
  padding: var(--space-8);
  cursor: zoom-out;
}

.chat-image-view img {
  max-width: 100%;
  max-height: 100%;
  border-radius: var(--radius-sm);
}

.chat-activity[data-working] .chat-activity__icon {
  color: var(--text-secondary);
}

.chat-activity__spinner {
  animation: chat-spin 1s linear infinite;
}

@keyframes chat-spin {
  to {
    transform: rotate(360deg);
  }
}

@media (prefers-reduced-motion: reduce) {
  .chat-activity__spinner {
    animation: none;
  }
}

.chat-composer {
  flex-shrink: 0;
  margin: var(--chat-composer-margin);
  background: var(--bg-elevated);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-lg);
}

.chat-composer__input {
  display: block;
  width: 100%;
  max-height: calc(var(--text-base) * var(--leading) * var(--chat-input-lines) + var(--chat-input-pad-top) + var(--chat-input-pad-bottom));
  padding: var(--chat-input-pad-top) var(--chat-input-pad-x) var(--chat-input-pad-bottom);
  overflow-y: auto;
  resize: none;
  border: 0;
  outline: none;
  background: transparent;
  font: inherit;
  font-size: var(--text-base);
  line-height: var(--leading);
  color: var(--text-primary);
}

.chat-composer__input::placeholder {
  color: var(--text-tertiary);
}

.chat-composer__row {
  display: flex;
  justify-content: flex-end;
  padding: var(--chat-row-pad);
}

/* Send: the one primary action. While the agent works it becomes Stop. */
.chat-composer__button {
  display: grid;
  place-items: center;
  width: var(--chat-button-size);
  height: var(--chat-button-size);
  border-radius: var(--control-radius);
  background: var(--accent);
  color: var(--text-on-accent);
  transition: background 120ms ease;
}

.chat-composer__button:hover:not(:disabled) {
  background: var(--accent-hover);
}

.chat-composer__button:disabled {
  opacity: var(--disabled-opacity);
  cursor: default;
}

.chat-composer__button--stop {
  background: var(--bg-field);
  color: var(--text-primary);
}

.chat-composer__button--stop:hover:not(:disabled) {
  background: var(--bg-field-hover);
}

/* ---------- Canvas ---------- */

.canvas {
  position: relative;
  flex: 1;
  min-width: 0;
  min-height: 0;
  overflow: hidden;
  background-color: var(--bg-canvas);
  background-image: radial-gradient(circle at 1px 1px, var(--canvas-dot) 1px, transparent 1.4px);
  background-size: var(--canvas-dot-pitch) var(--canvas-dot-pitch);
  background-position: calc(var(--canvas-dot-pitch) / 2) calc(var(--canvas-dot-pitch) / 2);
}

/* ---------- Board controls (decisions U10, U13) ---------- */

/*
 * The bottom row over the canvas: the tool pill in the middle column and the
 * corner (undo and zoom) at the end, as far from the bottom edge as from the
 * right edge. With 1fr auto 1fr
 * the tool pill is centred on the canvas while the last column has room; on
 * a narrow canvas the last column takes its own width and the tool pill
 * moves left, one gap before it. The style pill sits above the tool
 * pill; BoardControls shifts it (--style-shift) to stay a margin inside the
 * canvas. The corner is bare buttons, no pill; the style pill is quiet; the tool pill floats
 * (--shadow-float). The two pills share one height.
 */
.board-controls {
  position: absolute;
  z-index: 6;
  left: 0;
  right: 0;
  bottom: 0;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  column-gap: var(--space-3);
  align-items: end;
  padding: var(--space-3);
  pointer-events: none;
}

/*
 * The corner: bare buttons (no pill, no border, no shade) at the end of the
 * row, in the third column; a button shows its round hover fill when the
 * pointer reaches it.
 */
.board-controls__corner {
  --tool-size: var(--corner-button-size);
  --tool-icon-size: var(--corner-icon-size);
  grid-column: 3;
  grid-row: 1;
  display: flex;
  align-items: center;
  gap: var(--space-half);
  justify-self: end;
  /* At the bottom of the row: the same 12 px from the canvas's right and bottom edges. */
  align-self: end;
  pointer-events: auto;
}

/* Quieter than the tools, as every bare icon button (.icon-button): tertiary at rest, primary on hover. */
.board-controls__corner .tool,
.board-controls__corner .zoom-label {
  color: var(--text-tertiary);
}

.board-controls__corner .tool:hover,
.board-controls__corner .zoom-label:hover {
  color: var(--text-primary);
}

/* The space between undo and zoom. */
.board-controls__gap {
  width: var(--corner-group-gap);
  flex-shrink: 0;
}

.board-controls__center {
  position: relative;
  grid-column: 2;
  grid-row: 1;
}

/* Each pill sets its own height (.pill-bar has none). The tool pill floats. */
.board-controls__tools {
  height: var(--tools-pill-height);
  box-shadow: var(--shadow-float);
}

.board-controls__style {
  height: var(--style-pill-height);
  position: absolute;
  left: 50%;
  bottom: calc(100% + var(--space-2));
  transform: translateX(calc(-50% + var(--style-shift, 0px)));
  white-space: nowrap;
}

.pill-bar {
  display: flex;
  align-items: center;
  gap: var(--space-half);
  padding: 0 var(--pill-bar-pad);
  background: var(--bg-elevated);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-pill);
  pointer-events: auto;
}

.pill-bar__divider {
  flex-shrink: 0;
  width: 1px;
  height: var(--pill-divider-height);
  margin: 0 var(--pill-divider-gap);
  background: var(--border-subtle);
}

.tool {
  display: grid;
  place-items: center;
  flex-shrink: 0;
  width: var(--tool-size);
  height: var(--tool-size);
  border-radius: var(--radius-pill);
  color: var(--text-secondary);
  transition: background 120ms ease, color 120ms ease;
}

/* --icon-scale (tools.ts iconScale) evens the icons' optical size; the stroke keeps its weight. */
.tool > .lucide {
  width: calc(var(--tool-icon-size) * var(--icon-scale, 1));
  height: calc(var(--tool-icon-size) * var(--icon-scale, 1));
  stroke-width: calc(1.75 / var(--icon-scale, 1));
}

.tool:hover {
  background: var(--bg-hover);
  color: var(--text-primary);
}

.tool[aria-pressed='true'] {
  background: var(--accent-soft);
  color: var(--accent);
}

.tool--quiet {
  color: var(--text-tertiary);
}

.zoom-label {
  flex-shrink: 0;
  min-width: var(--zoom-label-min);
  height: var(--tool-size);
  padding: 0 var(--space-1);
  border-radius: var(--radius-pill);
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  color: var(--text-secondary);
  text-align: center;
  transition: background 120ms ease, color 120ms ease;
}

.zoom-label:hover {
  background: var(--bg-hover);
  color: var(--text-primary);
}

.swatch {
  display: grid;
  place-items: center;
  flex-shrink: 0;
  width: var(--swatch-size);
  height: var(--swatch-size);
  border-radius: 50%;
}

/* The colour as a small pen ring in the agents' ink (components/InkGlyph.tsx PenRing). */
.swatch__dot {
  display: block;
  width: var(--swatch-dot);
  height: var(--swatch-dot);
  color: var(--swatch);
  transition: transform 120ms ease;
}

.swatch:hover .swatch__dot {
  transform: scale(1.12);
}

.swatch:hover {
  background: var(--bg-hover);
}

/* The chosen colour: the grey circle every chosen option has (no ring). */
.swatch[aria-pressed='true'] {
  background: var(--bg-active);
}

.option {
  display: grid;
  place-items: center;
  flex-shrink: 0;
  min-width: var(--option-size);
  height: var(--option-size);
  border-radius: var(--radius-pill);
  color: var(--text-tertiary);
  transition: background 120ms ease, color 120ms ease;
}

.option > .lucide {
  width: var(--option-icon-size);
  height: var(--option-icon-size);
}

.option:hover {
  background: var(--bg-hover);
}

.option[aria-pressed='true'],
.option[aria-expanded='true'] {
  background: var(--bg-active);
  color: var(--text-primary);
}

.option--text {
  padding: 0 var(--option-text-pad);
  font-size: var(--text-sm);
}

.option__bar {
  width: var(--option-bar-width);
  border-radius: var(--radius-pill);
  background: currentColor;
}

/* A shape's fill: a small square in outline, at a light tint, or solid (tools.ts FILLS). */
.option__fill {
  width: var(--option-fill-size);
  height: var(--option-fill-size);
  border: 1.5px solid currentColor;
  border-radius: calc(var(--radius-sm) - 2px);
}

.option__fill[data-fill='light'] {
  background: color-mix(in srgb, currentColor 30%, transparent);
}

.option__fill[data-fill='solid'] {
  background: currentColor;
}

/* A shape's line: a bar in its pattern (tools.ts LINE_STYLES). */
.option__line {
  width: var(--option-bar-width);
  height: 4px;
  overflow: visible;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
}

/* ---------- Canvas notice (CanvasNotice.tsx) ---------- */

.overlay-center {
  position: absolute;
  inset: 0;
  z-index: 5;
  display: grid;
  place-items: center;
  padding: var(--space-8) var(--space-8) 120px;
  pointer-events: none;
}

/* ---------- Splash: the start screen with no folder (U20) ---------- */

/* Over the whole window on the window-wide backdrop (principle 5 exception); under a .backdrop panel (Settings). */
.splash {
  position: fixed;
  inset: 0;
  z-index: 150;
  display: grid;
  place-items: center;
  padding: var(--panel-margin-y) var(--panel-margin-x);
  background: var(--backdrop);
  animation: splash-fade var(--fade) both;
}

/* The title row stays a drag region over the backdrop; the window buttons are native, above it. */
.splash__drag {
  position: absolute;
  inset: 0 0 auto;
  height: var(--topbar-height);
  -webkit-app-region: drag;
}

.splash__card {
  /* The shared menu parts inside the card take the menu's type (.menu). */
  --menu-font: var(--text-base);
  --menu-meta-font: var(--text-sm);
  --menu-heading-font: var(--text-xs);
  --menu-separator-margin: var(--space-2) var(--space-1);
  display: flex;
  flex-direction: column;
  width: min(var(--splash-width), 100%);
  max-height: 100%;
  overflow: hidden;
  container-type: inline-size; /* the band's height follows the card's width (cqi) */
  background: var(--bg-elevated);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-card);
  color: var(--text-secondary);
  line-height: 1.4;
  -webkit-app-region: no-drag;
  animation: splash-rise var(--splash-rise) both;
}

/* The band keeps about 2:1 in a narrow window and shrinks first in a short one (its shrink weight is far above the
   panel's, so the panel gives only when the band is at its least); the drawing scales to fit it (art.ts). */
.splash__band {
  position: relative;
  flex: 0 1000 min(var(--splash-band-height), 100cqi / var(--splash-band-aspect));
  min-height: var(--splash-band-min-height);
  overflow: hidden;
  background: var(--bg-canvas);
  border-bottom: 1px solid var(--border-subtle);
}

.splash__art {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

.splash__name {
  position: absolute;
  left: var(--splash-name-left);
  bottom: var(--splash-name-bottom);
  color: var(--text-primary);
  font-size: var(--splash-name-font);
  font-weight: 600;
  letter-spacing: -0.01em;
}

.splash__version {
  position: absolute;
  right: var(--space-4);
  bottom: var(--space-4);
  color: var(--text-tertiary);
  font-size: var(--text-xs);
}

/* Start and Recent: the shared menu parts with the splash's row metrics. */
.splash__panel {
  --menu-item-pad: 0 var(--splash-row-pad-x);
  --menu-item-radius: var(--row-radius);
  display: grid;
  flex-shrink: 1;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.25fr);
  gap: var(--splash-panel-gap);
  min-height: 0;
  padding: var(--splash-panel-pad);
}

.splash__column {
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
}

.splash__panel .menu__heading {
  padding: var(--splash-heading-pad);
}

.splash__panel .menu__item {
  flex-shrink: 0;
  height: var(--splash-row-height);
}

.splash__panel .menu__icon {
  color: var(--text-secondary);
  opacity: 1;
}

.splash__panel .menu__item.splash__primary {
  background: var(--accent-soft);
}

.splash__panel .splash__primary .menu__icon {
  color: var(--accent);
}

.splash__recent {
  min-height: 0;
  overflow-y: auto;
}

/* A recent folder: its name whole, then where it is at the right. The path gives all its width before the name gives
   any: its shrink weight is far above the name's, and a flex item that reaches its least width stops there, so the
   name is cut only when it alone is wider than the row. The selectors outrank .menu__label:has(+ .menu__sub). */
.splash__recent .menu__item .splash__recent-name {
  flex: 0 1 auto;
  min-width: 0;
}

.splash__recent .menu__item .splash__recent-path {
  flex: 1 100000 auto;
  min-width: 0;
  margin-right: 0;
  padding-left: var(--space-2);
  text-align: right;
}

.splash__empty {
  padding: 0 var(--splash-row-pad-x);
  line-height: var(--splash-row-height);
  color: var(--text-tertiary);
  font-size: var(--text-sm);
}

/* Connect an agent: the agent popover's connect rows, in the card. */
.splash__panel--connect {
  --menu-item-pad: var(--space-1) var(--splash-row-pad-x);
  display: flex;
  flex-direction: column;
  overflow-y: auto;
}

.splash__panel--connect .menu__item {
  height: auto;
  min-height: var(--splash-row-height);
}

.splash__footer {
  display: flex;
  flex-shrink: 0;
  gap: var(--space-4);
  padding: var(--splash-footer-pad);
  border-top: 1px solid var(--border-subtle);
}

.splash__link {
  color: var(--text-tertiary);
  font-size: var(--text-sm);
}

.splash__link:hover {
  color: var(--text-secondary);
}

/* The entry: the title, the version, the rows and the footer come in one after the other. */
/* The connect view comes in at once (the learner chose it). */
.splash__name,
.splash__version,
.splash__column .menu__heading,
.splash__column .menu__item,
.splash__empty,
.splash__footer {
  animation: splash-item var(--splash-item) both;
  animation-delay: calc(var(--splash-item-delay) + var(--i, 0) * var(--splash-stagger));
}

@keyframes splash-fade {
  from {
    opacity: 0;
  }
}

@keyframes splash-rise {
  from {
    opacity: 0;
    transform: translateY(var(--splash-rise-offset)) scale(var(--splash-rise-scale));
  }
}

@keyframes splash-item {
  from {
    opacity: 0;
    transform: translateY(var(--splash-item-offset));
  }
}

@media (prefers-reduced-motion: reduce) {
  .splash,
  .splash__card,
  .splash__name,
  .splash__version,
  .splash__column .menu__heading,
  .splash__column .menu__item,
  .splash__empty,
  .splash__footer {
    animation: none;
  }
}

/* ---------- Board list ---------- */

.board-list {
  margin: 0;
  padding: 0;
  list-style: none;
}

.board-row {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  height: var(--sidebar-row-height);
  padding: 0 var(--space-2);
  border-radius: var(--row-radius);
  color: var(--text-secondary);
  cursor: default;
  outline: none;
}

.board-row:hover {
  background: var(--bg-hover);
  color: var(--text-primary);
}

.board-row:focus-visible {
  box-shadow: inset 0 0 0 1px var(--accent-ring);
}

.board-row--active,
.board-row--active:hover {
  background: var(--bg-active);
  color: var(--text-primary);
}

.board-row__icon {
  flex-shrink: 0;
  color: var(--text-tertiary);
}

.board-row--active .board-row__icon {
  color: var(--accent);
}

.board-row__name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.board-row__dir {
  flex-shrink: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: var(--text-xs);
  color: var(--text-tertiary);
}

/*
 * The right end of a board row: the time ("now", "5m", "3h"…), and in the same cell the ellipsis button,
 * which replaces the time on hover, on the open row and on keyboard focus. The cell is as wide as the wider
 * of the two, so nothing moves when they swap. Its right edge lines up with the hints of the rows above.
 */
.board-row__end {
  display: grid;
  flex-shrink: 0;
  margin-left: auto;
  place-items: center end;
}

.board-row__time,
.board-row__more {
  grid-area: 1 / 1;
}

.board-row__time {
  color: var(--text-tertiary);
  font-size: var(--text-xs);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.board-row__more {
  display: grid;
  place-items: center end;
  width: var(--icon-button-size);
  height: var(--icon-button-size);
  border-radius: var(--radius-md);
  color: var(--text-tertiary);
  visibility: hidden;
}

/* The dots' right edge on the text edge (the glyph has a small inset in its box). */
.board-row__more svg {
  margin-right: calc(var(--space-1) / -2);
}

.board-row__more:hover {
  color: var(--text-primary);
}

.board-row__more:focus-visible {
  box-shadow: inset 0 0 0 1px var(--accent-ring);
}

.board-row:hover .board-row__more,
.board-row--active .board-row__more,
.board-row:focus-visible .board-row__more,
.board-row:has(.board-row__more:focus-visible) .board-row__more {
  visibility: visible;
}

.board-row:hover .board-row__time,
.board-row--active .board-row__time,
.board-row:focus-visible .board-row__time,
.board-row:has(.board-row__more:focus-visible) .board-row__time {
  visibility: hidden;
}

/* "Show N more" / "Show less" at the end of the boards list. */
.board-row--quiet {
  color: var(--text-tertiary);
}

.board-row--quiet:hover {
  color: var(--text-secondary);
}

/* A sidebar row that runs an action (New board, Search boards): a button, icon in secondary, a shortcut hint at the right. */
.board-row--action {
  width: 100%;
  padding: 0 var(--space-2);
  text-align: left;
}

.board-row--action .board-row__icon {
  color: var(--text-secondary);
}

.board-row--action .board-row__name {
  flex: 1;
}

.board-row__hint {
  flex-shrink: 0;
  color: var(--text-tertiary);
  font-size: var(--text-xs);
}

.board-row--editing {
  padding: 0 var(--space-1);
  background: var(--bg-active);
}

/* In a sidebar row the name stays where the row shows it: row padding + border + field padding = the row's 8 px. */
.board-row--editing .board-row__input {
  padding: 0 calc(var(--space-1) - 1px);
}

.board-row__input {
  flex: 1;
  min-width: 0;
  height: 22px;
  padding: 0 6px;
  border: 1px solid var(--accent-ring);
  border-radius: var(--radius-sm);
  outline: none;
  background: var(--bg-app);
  color: var(--text-primary);
  font: inherit;
  user-select: text;
}

/* ---------- Menu ---------- */

/*
 * One menu system for every popup: Menu.tsx (sidebar folder and board menus),
 * the agent popover and the setup flyout. A menu sets only its position and
 * width; spacing and type come from the custom properties below. Menu.tsx opens
 * below its point, or above it with `above` (an anchor at the bottom, as the
 * sidebar footer); Escape gives the focus back to the element that had it.
 *
 *   .menu__heading         small uppercase section label
 *   .menu__title/__lede    a title and one muted line (or two: a second .menu__lede follows closely); long words wrap
 *   .menu__path            a quiet one-line path at the top of a menu (tertiary, meta size, ellipsis)
 *   .menu__item            clickable row: .menu__icon, .menu__label (one line, ellipsis), .menu__hint (right);
 *                          an empty .menu__icon keeps a row's label in the column of the other rows' labels
 *   .menu__item--current   the row of what shows now (a selected row: --bg-active, also on hover)
 *   .menu__sub             dim text right after a .menu__label (a board's folder); the .menu__hint goes to the right
 *   .menu__match           the part of a label that matches the typed text (--accent)
 *   .menu--panel           a modal panel over a .backdrop (ModalPanel.tsx: the search panel, the Settings dialog): opaque --bg-elevated (popups are glass),
 *                          --radius-xl, --border-strong, --shadow-card, rows of --panel-row-height; the selection is
 *                          the one fill (hover moves it); the instance sets the panel's height
 *   .menu__field/__input   the panel's search field at the top: a 17 px icon, 15 px text, a hairline under it
 *                          (a panel without a field starts with a .menu__title, padded as the field)
 *   .menu--split           a modal panel in two parts side by side: .menu__nav (the section list: .menu__item rows,
 *                          the current one --current, a hover fill; .menu__nav-end pins its last rows at the bottom) and
 *                          .menu__pane (a .menu__header, the section's title and a close .icon-button, over a .menu__scroll)
 *   .menu__setting         one setting: a .menu__setting-row (an optional .menu__radio, .menu__setting-text with a
 *                          .menu__name and a muted .menu__desc under it, then one .menu__control at the right), lines under
 *                          it; a hairline parts two settings. A row with role radio is one choice of a group (.menu__radio);
 *                          .menu__settings wraps such a group (role radiogroup) and keeps the hairlines
 *   .menu__sheet           a key sheet: headings and .menu__sheet-line keys (.menu__keys of .menu__key caps) in columns;
 *                          its parts are in "The key sheet" below
 *   .menu__scroll          the panel's rows under the field: it fills the panel and scrolls
 *   .menu__row             plain row: .menu__name left, .menu__meta or .menu__control right
 *   .menu__switch          a small on/off toggle in a .menu__control
 *   .menu__select          the app's own dropdown's trigger (Select.tsx, never a native select) in a .menu__control: a soft
 *                          --bg-field, the value, a chevron; in a .menu__select-root that also holds its list
 *   .menu--select          the dropdown's open list: --bg-glass-2, rows of .menu__option (hover and keys move the one
 *                          --bg-active fill, data-active; the chosen one has a .menu__option-check at the right)
 *   .menu__text            a small text field in a .menu__row (a key), before its .btn-sm
 *   .menu__progress        a 90 × 4 px accent progress bar (.menu__progress-bar sets its width), a % .menu__meta--mono after it
 *   .menu__meta--mono      a live number in a row: mono, tabular figures, secondary text
 *   .menu__line            one short line under a row (--warn, --error), with a .menu__fix text button
 *   .menu__status          inline status: green check + text, or .menu__spinner
 *   .menu__separator       hairline
 *   .menu__footer          quiet text action left, a .btn-sm right (in a .menu--panel: a title, a lede and a footer
 *                          make a small question, in the title's column: the trust question)
 *   .btn-sm, .btn-text     the one small button (the select trigger's look: one rule, "The small control"), and its
 *                          quiet text variant
 */
.menu {
  --menu-pad: 6px;
  --menu-radius: var(--popup-radius);
  --menu-item-pad: 4px 8px;
  --menu-row-pad: 4px 8px;
  /* Concentric with the menu's corner (U16): the corner's radius less the padding between them. */
  --menu-item-radius: calc(var(--menu-radius) - var(--menu-pad));
  --scroll-pad-end: var(--menu-pad); /* when the menu is a .scroll-area */
  --menu-font: 13px;
  --menu-meta-font: 12px;
  --menu-heading-font: 11px;
  --menu-separator-margin: 8px 4px;
  position: fixed;
  z-index: 100;
  padding: var(--menu-pad);
  /* A popup lets a little of the board through (U16); a modal panel stays opaque (.menu--panel). */
  background: var(--bg-glass);
  backdrop-filter: var(--glass-filter);
  border: 1px solid var(--border-subtle);
  border-radius: var(--menu-radius);
  box-shadow: var(--shadow-float);
  color: var(--text-secondary);
  font-size: var(--menu-font);
  line-height: 1.4;
}

.menu__heading {
  padding: 6px 8px 2px;
  color: var(--text-tertiary);
  font-size: var(--menu-heading-font);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.menu__title {
  padding: 6px 8px 2px;
  color: var(--text-primary);
  font-weight: 560;
  overflow-wrap: anywhere;
}

.menu__lede {
  padding: 0 8px 8px;
  color: var(--text-tertiary);
  font-size: var(--menu-meta-font);
  overflow-wrap: anywhere;
}

.menu__lede:has(+ .menu__lede) {
  padding-bottom: var(--space-half);
}

/* A quiet path line at the top of a menu (the folder menu): one line, an ellipsis at the end. */
.menu__path {
  padding: var(--menu-row-pad);
  overflow: hidden;
  color: var(--text-tertiary);
  font-size: var(--menu-meta-font);
  white-space: nowrap;
  text-overflow: ellipsis;
}

.menu__item {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  width: 100%;
  padding: var(--menu-item-pad);
  border-radius: var(--menu-item-radius);
  color: var(--text-primary);
  font-size: var(--menu-font);
  text-align: left;
}

.menu__item:hover:not(:disabled) {
  background: var(--bg-hover);
}

.menu__item:disabled {
  color: var(--text-tertiary);
}

.menu__item--current,
.menu__item--current:hover:not(:disabled) {
  background: var(--bg-active);
}

.menu__item--danger {
  color: var(--ink-pink);
}

.menu__item--quiet {
  color: var(--text-secondary);
}

.menu__item--quiet:hover:not(:disabled) {
  color: var(--text-primary);
}

.menu__icon {
  display: grid;
  flex-shrink: 0;
  place-items: center;
  width: 16px;
  opacity: 0.85;
}

.menu__label {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.menu__hint {
  flex-shrink: 0;
  color: var(--text-tertiary);
  font-size: var(--menu-meta-font);
}

/* A label with dim text after it: both shrink with an ellipsis, the text takes the free space, so a hint stays at the right. */
.menu__label:has(+ .menu__sub) {
  flex: 0 1 auto;
}

.menu__sub {
  flex: 0 1 auto;
  min-width: 0;
  margin-right: auto;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  color: var(--text-tertiary);
  font-size: var(--menu-meta-font);
}

.menu__match {
  background: none;
  color: var(--accent);
}

/* A modal panel (ModalPanel.tsx: the search panel, the Settings dialog): over a .backdrop, opaque (U14; popups are glass, U16); the instance sets its position, width and height. */
.menu--panel {
  --menu-radius: var(--radius-xl); /* its rows: 16 less the list's 6 px padding = 10 (.menu) */
  display: flex;
  flex-direction: column;
  padding: 0;
  overflow: hidden;
  background: var(--bg-elevated);
  backdrop-filter: none;
  border-color: var(--border-strong);
  box-shadow: var(--shadow-card);
}

.menu--panel .menu__scroll {
  flex: 1;
}

.menu--panel .menu__item {
  height: var(--panel-row-height);
  padding-block: 0;
}

/* A panel that holds the focus itself (the Settings dialog, for its keys) shows no ring: its controls show theirs. */
.menu--panel:focus-visible {
  outline: none;
}

/* A panel's plain rows have the height of its items. */
.menu--panel .menu__row {
  min-height: var(--panel-row-height);
  padding-block: 0;
}

/* The pointer moves the selection, so a hovered row has no fill of its own: the selected row is the one fill. */
.menu--panel .menu__item:not(.menu__item--current):hover:not(:disabled) {
  background: none;
}

/* A panel's title in place of a field: its text in the rows' column. */
.menu--panel > .menu__title {
  flex-shrink: 0;
  padding: var(--space-4) calc(var(--menu-pad) + var(--space-2)) var(--space-1);
}

/* A panel's lede and footer under its title (the trust question): in the title's column. */
.menu--panel > .menu__lede {
  padding: 0 calc(var(--menu-pad) + var(--space-2)) var(--space-3);
}

.menu--panel > .menu__footer {
  padding: var(--space-1) calc(var(--menu-pad) + var(--space-2)) var(--space-3);
}

/* A split panel (the Settings dialog): the section list on the left, the section on the right. */
.menu--split {
  flex-direction: row;
}

.menu__nav {
  display: flex;
  flex-direction: column;
  flex-shrink: 0;
  gap: var(--space-half);
  width: var(--panel-nav-width);
  /* The Settings spacing rules (U15): its first row level with the pane's title row. */
  --scroll-pad-end: var(--space-3); /* a .scroll-area */
  padding: var(--settings-pane-pad-y) var(--space-3);
  overflow-y: auto;
  border-right: 1px solid var(--border-subtle);
}

/* The list's rows choose a section: the pointer does not move a selection, so a hovered row has its fill. */
.menu--panel .menu__nav .menu__item:not(.menu__item--current):hover:not(:disabled) {
  background: var(--bg-hover);
}

.menu__nav-end {
  margin-top: auto;
}

.menu__pane {
  display: flex;
  flex: 1;
  flex-direction: column;
  min-width: 0;
}

/* The pane's title row (U15): the title in the rows' column, as high as a section-list row and level with the first
   one; a close button at the right. The section's rows follow --settings-title-gap under it. */
.menu__header {
  display: flex;
  flex-shrink: 0;
  align-items: center;
  gap: var(--space-2);
  box-sizing: content-box;
  height: var(--panel-row-height);
  padding: var(--settings-pane-pad-y) var(--settings-pane-pad-x) var(--settings-title-gap);
}

.menu__header .menu__title {
  flex: 1;
  min-width: 0;
  padding: 0;
  font-size: var(--settings-title-size);
}

/* The pane's rows: the pane's sides, its bottom (the header holds its top). */
.menu__pane > .menu__scroll {
  --scroll-pad-end: var(--settings-pane-pad-x); /* a .scroll-area */
  padding: 0 var(--settings-pane-pad-x) var(--settings-pane-pad-y);
}

/* A plain item in the pane (Agents: "Manual setup and other agents"): its fill reaches out as a setting row's does. */
.menu__pane > .menu__scroll > .menu__item {
  width: calc(100% + 2 * var(--space-2));
  margin-inline: calc(-1 * var(--space-2));
}

/* A group heading in the pane: --settings-group-gap above it, --settings-heading-gap under it. */
.menu__pane .menu__heading {
  padding: var(--settings-group-gap) 0 var(--settings-heading-gap);
}

.menu__setting + .menu__setting,
.menu__setting + .menu__settings,
.menu__settings + .menu__setting,
.menu__settings > .menu__setting + .menu__setting {
  border-top: 1px solid var(--border-subtle);
}

/* The text sits in the pane's column; the row reaches --space-2 out on both sides for its focus ring. */
.menu__setting-row {
  display: flex;
  align-items: center;
  gap: var(--setting-row-gap);
  margin-inline: calc(-1 * var(--space-2));
  padding: var(--setting-row-pad-y) var(--space-2);
  border-radius: var(--menu-item-radius);
}

.menu__setting-row[role='radio'] {
  cursor: pointer;
}

.menu__setting-row[role='radio'][aria-disabled='true'] {
  cursor: default;
}

.menu__setting-row[role='radio']:focus-visible {
  outline: 2px solid var(--accent-ring);
  outline-offset: -2px;
}

.menu__setting-text {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: var(--setting-desc-gap);
  min-width: 0;
}

.menu__desc {
  color: var(--text-tertiary);
  font-size: var(--menu-meta-font);
  line-height: var(--setting-desc-leading);
  overflow-wrap: anywhere;
}

.menu__radio {
  display: grid;
  flex-shrink: 0;
  place-items: center;
  width: var(--radio-size);
  height: var(--radio-size);
  border: 1px solid var(--border-strong);
  border-radius: 50%;
}

.menu__setting-row[aria-checked='true'] .menu__radio {
  border-color: var(--accent);
}

.menu__setting-row[aria-checked='true'] .menu__radio::after {
  width: var(--radio-dot);
  height: var(--radio-dot);
  border-radius: 50%;
  background: var(--accent);
  content: '';
}

.menu__setting-row[aria-disabled='true'] .menu__radio {
  opacity: var(--disabled-opacity);
}

/* A setting's text field has a fixed width before its button. */
.menu__control .menu__text {
  flex: none;
  width: var(--setting-field-width);
}

/* A setting's lines line up with its text, --space-2 under the row's text. */
.menu__setting .menu__line {
  margin-top: calc(var(--space-2) - var(--setting-row-pad-y));
  padding: 0 0 var(--setting-row-pad-y);
}

/* The field's icon lines up with the rows' icons (the list padding + the row padding). */
.menu__field {
  display: flex;
  flex-shrink: 0;
  align-items: center;
  gap: var(--space-2);
  height: var(--panel-field-height);
  padding: 0 calc(var(--menu-pad) + var(--space-2));
  border-bottom: 1px solid var(--border-subtle);
  color: var(--text-tertiary);
}

.menu__input {
  flex: 1;
  min-width: 0;
  height: 100%;
  padding: 0;
  border: 0;
  outline: none;
  background: none;
  color: var(--text-primary);
  font: inherit;
  font-size: var(--text-lg);
  user-select: text;
}

.menu__input::placeholder {
  color: var(--text-tertiary);
}

.menu__scroll {
  --scroll-pad-end: var(--menu-pad); /* a .scroll-area */
  min-height: 0;
  padding: var(--menu-pad);
  overflow-y: auto;
  overscroll-behavior: contain;
  /* Rows move when a newer list arrives (edit-time order): the scroll stays where the learner left it, not with a moved row. */
  overflow-anchor: none;
}

.menu__list {
  margin: 0;
  padding: 0;
  list-style: none;
}

.menu__row {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--menu-row-pad);
  line-height: 1.2;
}

.menu__name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  color: var(--text-primary);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.menu__name--mono {
  color: var(--text-secondary);
  font-family: var(--font-mono);
  font-size: var(--menu-meta-font);
}

.menu__meta {
  flex-shrink: 0;
  color: var(--text-tertiary);
  font-size: var(--menu-meta-font);
  font-variant-numeric: tabular-nums;
}

.menu__meta--mono {
  color: var(--text-secondary);
  font-family: var(--font-mono);
}

.menu__meta--accent {
  color: var(--accent);
}

.menu__control {
  display: inline-flex;
  flex-shrink: 0;
  align-items: center;
  gap: var(--space-1);
  min-height: 24px;
}

/* ---------- The key sheet (U15): Settings > Keyboard shortcuts ---------- */

/*
 * Shared parts for a list of keys:
 *   .menu__sheet       the groups in columns (two, or one when the pane has no room for two --keys-column-min);
 *                      a group's heading stays with its first line, a line never splits
 *   .menu__sheet-line  one key: its .menu__keys, then the name, close together, --keys-line-height high
 *   .menu__keys        the caps of a key in a --keys-caps-width column: .menu__key caps (a combo is one cap per key)
 *                      and .menu__key-word plain words between them ("or", "drag")
 */
.menu__sheet {
  columns: var(--keys-column-min) 2;
  column-gap: var(--keys-column-gap);
}

/* The space above a heading is a margin: a column break drops it, so every column starts at its top. */
.menu__sheet .menu__heading {
  margin-top: var(--settings-group-gap);
  padding-top: 0;
  break-after: avoid;
}

.menu__sheet > .menu__heading:first-child {
  margin-top: 0;
}

/* A name too long for its column wraps to a second line in the same height, never an ellipsis. */
.menu__sheet-line {
  display: flex;
  align-items: center;
  gap: var(--keys-name-gap);
  min-height: var(--keys-line-height);
  break-inside: avoid;
  color: var(--text-primary);
}

.menu__sheet-line .menu__name {
  flex: 1;
  line-height: 1.15;
  white-space: normal;
}

.menu__keys {
  display: inline-flex;
  flex-shrink: 0;
  align-items: center;
  gap: var(--keycap-gap);
  min-width: var(--keys-caps-width);
}

.menu__key {
  display: inline-grid;
  place-items: center;
  min-width: var(--keycap-size);
  height: var(--keycap-size);
  padding: var(--keycap-pad);
  border-radius: var(--keycap-radius);
  background: var(--bg-active);
  color: var(--text-primary);
  font-family: var(--font-ui);
  font-size: var(--keycap-font);
  line-height: 1;
  white-space: nowrap;
}

.menu__key--symbol {
  font-size: var(--keycap-symbol-font);
}

.menu__key-word {
  padding: 0 var(--space-half);
  color: var(--text-tertiary);
  font-size: var(--keycap-font);
}

/* ---------- The select (U14): the app's own dropdown (Select.tsx) ---------- */

.menu__select-root {
  display: inline-flex;
}

/* The trigger is the small control (U15, below with .btn-sm): its own parts are the chevron and its tighter side. */
.menu__select {
  gap: var(--space-2);
  padding-right: var(--select-chevron-pad);
}

.menu__select[aria-expanded='true'] {
  background: var(--bg-field-hover);
}

.menu__select-chevron {
  flex-shrink: 0;
  color: var(--text-secondary);
}

/* The open list: fixed at the trigger (Select.tsx places it), over the panel it is in. */
.menu--select {
  --menu-pad: var(--select-list-pad);
  --menu-radius: var(--select-list-radius);
  min-width: var(--select-list-min-width);
  overflow-y: auto;
  overscroll-behavior: contain;
  border-color: var(--border-strong);
  background: var(--bg-glass-2);
}

/* The list holds the focus for its keys; the --bg-active row shows where they are. */
.menu--select:focus-visible {
  outline: none;
}

.menu__option {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  height: var(--select-option-height);
  padding: var(--select-option-pad);
  border-radius: var(--menu-item-radius); /* concentric with the list (U16) */;
  color: var(--text-primary);
  font-size: var(--text-base);
  white-space: nowrap;
}

.menu__option[data-active] {
  background: var(--bg-active);
}

.menu__option-label {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}

.menu__option-check {
  flex-shrink: 0;
  color: var(--text-primary);
}

.menu__text {
  flex: 1;
  min-width: 0;
  height: var(--control-height);
  padding: 0 var(--space-2);
  border: 1px solid var(--border-strong);
  border-radius: var(--control-radius);
  outline: none;
  background: transparent;
  color: var(--text-primary);
  font: inherit;
  font-size: var(--menu-meta-font);
  user-select: text;
}

.menu__text:focus-visible {
  border-color: var(--accent);
}

.menu__text::placeholder {
  color: var(--text-tertiary);
}

.menu__progress {
  position: relative;
  width: 90px;
  height: 4px;
  overflow: hidden;
  border-radius: var(--radius-pill);
  background: var(--bg-active);
}

.menu__progress-bar {
  position: absolute;
  inset: 0 auto 0 0;
  background: var(--accent);
}

.menu__switch {
  position: relative;
  flex-shrink: 0;
  width: var(--switch-width);
  height: var(--switch-height);
  padding: 0;
  border: 0;
  border-radius: var(--radius-pill);
  background: var(--bg-active);
  cursor: pointer;
}

.menu__switch::after {
  position: absolute;
  top: var(--switch-inset);
  left: var(--switch-inset);
  width: var(--switch-knob);
  height: var(--switch-knob);
  border-radius: 50%;
  background: var(--text-secondary);
  content: '';
}

.menu__switch[aria-checked='true'] {
  background: var(--accent);
}

.menu__switch[aria-checked='true']::after {
  left: calc(var(--switch-width) - var(--switch-knob) - var(--switch-inset));
  background: var(--text-primary);
}

.menu__line {
  display: flex;
  align-items: baseline;
  gap: 6px;
  padding: 0 8px 4px;
  color: var(--text-tertiary);
  font-size: var(--menu-meta-font);
}

.menu__line-text {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.menu__line--warn {
  color: var(--ink-orange);
}

.menu__line--error {
  align-items: flex-start;
  color: var(--ink-pink);
}

.menu__line--error svg {
  flex-shrink: 0;
  margin-top: 2px;
}

.menu__fix {
  flex-shrink: 0;
  color: var(--text-primary);
  font-weight: 560;
}

.menu__fix:hover {
  text-decoration: underline;
}

.menu__status {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  color: var(--text-secondary);
  font-size: var(--menu-meta-font);
}

.menu__status svg {
  color: var(--status-live);
}

.menu__spinner {
  animation: menu-spin 800ms linear infinite;
  color: var(--text-secondary);
}

@keyframes menu-spin {
  to {
    transform: rotate(360deg);
  }
}

.menu__separator {
  height: 1px;
  margin: var(--menu-separator-margin);
  background: var(--border-subtle);
}

.menu__footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  padding: 2px 8px 4px;
}

/*
 * The small control (U15): the one small button and the select's trigger share this one rule, so they cannot drift:
 * --control-height, --control-pad-x, --control-radius, the soft --bg-field (a little brighter on hover), no border,
 * 13 px --text-primary; disabled at --disabled-opacity; the focus ring is the buttons' keyboard-only one. A popup
 * menu's compact rows take --control-height-menu (the setting below on .menu).
 */
.btn-sm,
.menu__select {
  display: inline-flex;
  align-items: center;
  height: var(--control-height);
  padding: 0 var(--control-pad-x);
  border: 0;
  border-radius: var(--control-radius);
  background: var(--bg-field);
  color: var(--text-primary);
  font-size: var(--text-base);
  line-height: 1;
  white-space: nowrap;
  transition: background 120ms ease;
}

.btn-sm:hover:not(:disabled),
.menu__select:hover:not(:disabled) {
  background: var(--bg-field-hover);
}

.btn-sm:disabled,
.menu__select:disabled {
  opacity: var(--disabled-opacity);
}

.menu:not(.menu--panel) {
  --control-height: var(--control-height-menu);
  --control-radius: var(--menu-item-radius); /* as the menu's rows */
  --switch-width: var(--switch-width-menu);
  --switch-height: var(--switch-height-menu);
  --switch-knob: var(--switch-knob-menu);
}

.btn-sm--quiet {
  color: var(--text-tertiary);
}

/* The quiet text button ("Don't ask for this folder"). */
.btn-text {
  color: var(--text-tertiary);
  font-size: 12px;
}

.btn-text:hover {
  color: var(--text-secondary);
}

/* ---------- Save status ---------- */

/* Only a failed save shows: "Not saved" with its alert icon. The live region stays, empty, otherwise. */
.save-status {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  margin-left: var(--space-3);
  font-size: var(--text-xs);
  color: var(--ink-pink);
}

.save-status:empty {
  margin-left: 0;
}

/* ---------- Canvas notices ---------- */

.notice {
  display: flex;
  flex-direction: column;
  align-items: center;
  max-width: 340px;
  pointer-events: auto;
  text-align: center;
}

.notice__icon {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  margin-bottom: var(--space-4);
  border-radius: var(--radius-lg);
  background: var(--bg-elevated);
  border: 1px solid var(--border-subtle);
  color: var(--text-secondary);
}

.notice__title {
  font-size: var(--text-lg);
  font-weight: 600;
}

.notice__body {
  margin: var(--space-1) 0 var(--space-5);
  color: var(--text-secondary);
}

.button-secondary {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  height: 32px;
  padding: 0 var(--space-4);
  border: 1px solid var(--border-strong);
  border-radius: var(--row-radius);
  background: var(--bg-elevated);
  color: var(--text-primary);
  font-weight: 560;
  transition: background 120ms ease;
}

.button-secondary:hover {
  background: var(--bg-elevated-2);
}

/* ---------- Preview panel ---------- */

.preview {
  display: flex;
  flex-direction: column;
  width: 420px;
  flex-shrink: 0;
  min-height: 0;
  background: var(--bg-app);
  border-left: 1px solid var(--border-subtle);
}

.preview__header {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  height: 40px;
  flex-shrink: 0;
  padding: 0 var(--space-2) 0 var(--space-4);
  border-bottom: 1px solid var(--border-subtle);
}

.preview__title {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  flex: 1;
  min-width: 0;
}

.preview__name {
  font-weight: 560;
  white-space: nowrap;
}

.preview__dir,
.preview__size {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: var(--text-xs);
  color: var(--text-tertiary);
}

.preview__body {
  flex: 1;
  overflow: auto;
  --scroll-pad-end: var(--space-6); /* a .scroll-area */
  padding: var(--space-5) var(--space-6) var(--space-8);
  user-select: text;
}

.preview__text {
  margin: 0;
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  line-height: 1.55;
  white-space: pre-wrap;
  word-break: break-word;
  color: var(--text-secondary);
}

.preview__message {
  margin-top: var(--space-4);
  font-size: var(--text-sm);
  color: var(--text-tertiary);
}

.preview__image {
  display: grid;
  place-items: center;
  padding: var(--space-4);
  border-radius: var(--radius-lg);
  background: repeating-conic-gradient(var(--bg-elevated) 0% 25%, var(--preview-checker) 0% 50%) 50% / 16px 16px;
}

.preview__image img {
  max-width: 100%;
  height: auto;
}

.markdown {
  color: var(--text-secondary);
  line-height: 1.6;
}

.markdown > :first-child {
  margin-top: 0;
}

.markdown h1,
.markdown h2,
.markdown h3,
.markdown h4 {
  margin: 1.4em 0 0.5em;
  color: var(--text-primary);
  font-weight: 620;
  line-height: 1.3;
}

.markdown h1 {
  font-size: 19px;
}

.markdown h2 {
  font-size: 16px;
}

.markdown h3,
.markdown h4 {
  font-size: 14px;
}

.markdown p,
.markdown ul,
.markdown ol,
.markdown blockquote,
.markdown pre {
  margin: 0 0 0.9em;
}

.markdown ul,
.markdown ol {
  padding-left: 1.3em;
}

.markdown li + li {
  margin-top: 0.25em;
}

.markdown strong {
  color: var(--text-primary);
  font-weight: 600;
}

.markdown code {
  padding: 1px 5px;
  border-radius: var(--radius-sm);
  background: var(--bg-elevated);
  font-family: var(--font-mono);
  font-size: 0.92em;
  color: var(--text-primary);
}

.markdown pre {
  padding: var(--space-3);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  background: var(--bg-elevated);
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  white-space: pre-wrap;
  color: var(--text-primary);
}

.markdown blockquote {
  padding-left: var(--space-3);
  border-left: 2px solid var(--border-strong);
  color: var(--text-tertiary);
}

.markdown hr {
  margin: 1.4em 0;
  border: 0;
  border-top: 1px solid var(--border-subtle);
}

/* ---------- Toast ---------- */

.toast {
  position: absolute;
  left: 50%;
  bottom: var(--toast-bottom);
  z-index: 20;
  display: flex;
  align-items: center;
  gap: var(--space-2);
  max-width: min(520px, calc(100% - 48px));
  padding: var(--space-2) var(--space-3);
  transform: translateX(-50%);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-lg);
  background: var(--bg-elevated-2);
  box-shadow: var(--shadow-float);
  color: var(--text-primary);
}

.toast svg {
  flex-shrink: 0;
  color: var(--ink-pink);
}


.toast--info svg {
  color: var(--status-live);
}

/* A notice that asks for a step (the voice's daily limit): a warn icon and one text action after the text. */
.toast--warn svg {
  color: var(--status-warn);
}

.toast__action {
  flex-shrink: 0;
  color: var(--text-primary);
  font-weight: 560;
}

.toast__action:hover {
  text-decoration: underline;
}

/* ---------- Folder guide overrides (.askaboard/guide.md, instructions.md) ---------- */

.folder-overrides {
  display: flex;
  flex-direction: column;
  margin-top: var(--space-1);
}

.agent-pop__overrides {
  display: flex;
  flex-direction: column;
  margin-top: var(--space-3);
  padding-top: var(--space-3);
  border-top: 1px solid var(--border-subtle);
}

.guide-override {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: 2px var(--space-2);
  border-radius: var(--radius-md);
  color: var(--text-tertiary);
  font-size: var(--text-xs);
  text-align: left;
  transition: background 120ms ease, color 120ms ease;
}

.guide-override span {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.guide-override svg {
  flex-shrink: 0;
}

.guide-override:hover {
  background: var(--bg-hover);
  color: var(--text-secondary);
}

.guide-override--warn {
  color: var(--ink-orange);
}

/* ---------- Set up for learning ---------- */

/* The quiet sidebar row under Search boards (a board row, --action). */

.setup-row__icon {
  flex-shrink: 0;
  color: var(--accent);
}

.setup-row .board-row__name {
  flex: 1;
}

.setup-row__dot {
  flex-shrink: 0;
  width: 6px;
  height: 6px;
  margin-right: var(--space-1);
  border-radius: 50%;
  background: var(--accent);
}

/* The sidebar footer's folder menu: layout only (width: the sidebar's, inside its padding); it opens above the footer. */
.menu.folder-menu {
  width: calc(var(--sidebar-width) - 2 * var(--space-2));
}

/* The "Set up this folder" flyout: layout only (width); the content is shared .menu parts. */
.menu.setup-menu {
  width: 270px;
}

/* ---------- Scrollbars (U14) ---------- */

/*
 * One style for every scroll area, as a macOS overlay scrollbar in our look: a 6 px rounded thumb, no track, no arrow
 * buttons. The thumb is invisible at rest; it shows while the area is hovered or scrolls (lib/scrollbars.ts sets
 * data-scrolling for a moment after each scroll), then hides again. The board canvas does not scroll natively.
 *
 * .scroll-area is the one shared part for a scroll area (U16). It reserves no gutter: while it does not overflow, its
 * right padding is the whole --scroll-pad-end, so a row's fill ends as far from the right edge as from the left. While
 * it overflows (data-overflow, set by lib/scrollbars.ts for every .scroll-area), the scrollbar takes its width out of
 * that padding, so the content's right edge stays put. --scroll-pad-end does not inherit: each area sets its own (a
 * menu sets its --menu-pad), so a dropdown list inside a Settings pane does not take the pane's padding. Every
 * --scroll-pad-end is at least --scrollbar-size, so the thumb sits inside the padding. It sets no other padding.
 * This rule sits at the end of the file so that it follows every area's own padding.
 */
@property --scroll-pad-end {
  syntax: '<length>';
  inherits: false;
  initial-value: 0px;
}

/* The thumb's colour now. It inherits, because a scrollbar part takes its values from its element by inheritance;
   every element sets its own, so a hovered ancestor does not show the thumbs of the areas inside it. */
@property --scrollbar-thumb-shown {
  syntax: '<color>';
  inherits: true;
  initial-value: transparent;
}

:where(*) {
  --scrollbar-thumb-shown: transparent;
}

::-webkit-scrollbar {
  width: var(--scrollbar-size);
  height: var(--scrollbar-size);
  background: transparent;
}

::-webkit-scrollbar-track,
::-webkit-scrollbar-corner {
  background: transparent;
}

::-webkit-scrollbar-button {
  display: none;
}

::-webkit-scrollbar-thumb {
  border-radius: var(--radius-pill);
  background: var(--scrollbar-thumb-shown);
}

::-webkit-scrollbar-thumb:hover {
  background: var(--scrollbar-thumb-hover);
}

:hover,
[data-scrolling] {
  --scrollbar-thumb-shown: var(--scrollbar-thumb);
}

.scroll-area {
  overflow-y: auto;
  /* The thumb keeps clear of a rounded edge (a menu's corners, U15): --scroll-track-inset at its top and bottom. */
  --scroll-track-inset: var(--menu-radius, 0px);
  padding-right: var(--scroll-pad-end);
  transition: --scrollbar-thumb-shown var(--fade);
}

.scroll-area[data-overflow] {
  padding-right: calc(var(--scroll-pad-end) - var(--scrollbar-size));
}

.scroll-area::-webkit-scrollbar-track {
  margin-block: var(--scroll-track-inset);
}

@media (prefers-reduced-motion: reduce) {
  .scroll-area {
    transition: none;
  }
}

/* ---------- The web app's chat panel footer (decision P30) ---------- */

/* Under the composer: the credit left at the left, the account and Sign out at the right. */
.chat-panel__footer {
  display: flex;
  flex-shrink: 0;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  padding: var(--chat-footer-pad);
  font-size: var(--chat-footer-font);
  color: var(--text-tertiary);
}

.chat-panel__account {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  min-width: 0;
}

.chat-panel__email {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.chat-panel__sign-out {
  flex-shrink: 0;
  color: inherit;
  font-size: inherit;
}

.chat-panel__sign-out:hover {
  color: var(--text-secondary);
}

/* The credit is used up: the composer fades and does not send. */
.chat-composer[data-disabled] {
  opacity: var(--disabled-opacity);
}

/* ---------- The web app's sign-in screen (decision P30) ---------- */

.sign-in {
  display: grid;
  place-items: center;
  min-height: 100vh;
  padding: var(--space-4);
  background: var(--bg-app);
  font-family: var(--font-ui);
  color: var(--text-primary);
}

.sign-in__card {
  display: flex;
  flex-direction: column;
  width: var(--sign-in-width);
  max-width: 100%;
  padding: var(--sign-in-pad);
  background: var(--bg-elevated);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-card);
}

.sign-in__tile {
  display: grid;
  place-items: center;
  align-self: center;
  width: var(--sign-in-tile);
  height: var(--sign-in-tile);
  margin-bottom: var(--sign-in-tile-gap);
  border: 1px solid var(--accent-tile-border);
  border-radius: var(--control-radius);
  background: linear-gradient(160deg, var(--accent-tile-from), var(--accent-tile-to));
}

.sign-in__mark {
  width: var(--sign-in-mark);
  height: auto;
}

.sign-in__title {
  margin: 0 0 var(--sign-in-title-gap);
  text-align: center;
  font-size: var(--sign-in-title-font);
  font-weight: var(--sign-in-title-weight);
}

.sign-in__lede {
  margin: 0 0 var(--sign-in-head-gap);
  font-size: var(--sign-in-lede-font);
  text-align: center;
  color: var(--text-tertiary);
  overflow-wrap: anywhere;
}

/* The one primary action of each step: Continue with Google, Sign in. */
.sign-in__primary {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  height: var(--control-height);
  border-radius: var(--control-radius);
  background: var(--accent);
  color: var(--text-on-accent);
  font-size: var(--text-base);
  transition: background 120ms ease;
}

.sign-in__primary:hover:not(:disabled) {
  background: var(--accent-hover);
}

.sign-in__primary:disabled {
  opacity: var(--disabled-opacity);
  cursor: default;
}

.sign-in__google {
  width: 14px;
  height: 14px;
}

.sign-in__divider {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin: var(--sign-in-divider-gap) 0;
  font-size: var(--sign-in-divider-font);
  color: var(--text-tertiary);
}

.sign-in__divider::before,
.sign-in__divider::after {
  content: '';
  flex: 1;
  border-top: 1px solid var(--border-subtle);
}

.sign-in__email {
  display: flex;
  flex-direction: column;
  gap: var(--sign-in-email-gap);
}

.sign-in__email .menu__text {
  flex: none;
  font-size: var(--text-sm);
}

.sign-in__email .btn-sm {
  justify-content: center;
}

/* Sign in and Use another email, below the code. */
.sign-in__code + .sign-in__primary,
.sign-in__back {
  margin-top: var(--sign-in-gap);
}

.sign-in__code {
  display: flex;
  justify-content: center;
  gap: var(--sign-in-digit-gap);
}

.sign-in__digit {
  flex: none;
  width: var(--sign-in-digit-width);
  height: var(--sign-in-digit-height);
  padding: 0;
  border: 1px solid var(--border-strong);
  border-radius: var(--control-radius);
  outline: none;
  background: transparent;
  color: var(--text-primary);
  font-family: var(--font-mono);
  font-size: var(--sign-in-digit-font);
  text-align: center;
  user-select: text;
}

.sign-in__digit[data-filled],
.sign-in__digit:focus-visible {
  border-color: var(--accent);
}

.sign-in__back {
  align-self: center;
}

.sign-in__error {
  margin: var(--sign-in-gap) 0 0;
  text-align: center;
  font-size: var(--text-sm);
  color: var(--status-bad);
}

/* The web server (renderer/web-link.ts): the one line a browser tab shows when its board link ends. */
.web-link-line {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 2147483647;
  padding: var(--space-2) var(--space-4);
  background: var(--bg-elevated);
  border-bottom: 1px solid var(--border-strong);
  color: var(--text-primary);
  font: var(--text-sm) var(--font-ui);
  text-align: center;
}
