/* Sentinel UI. Warm neutral surfaces, one muted blue accent, Poppins for the
   interface, Lora for reading text. Tokens first, then the shell, then every
   component and its states. The theme scope sits on the document root, so
   overlays and portaled content inherit the same tokens and scrollbars.

   Nothing here hardcodes a color outside the token block. */

/* Sentinel UI fonts, self hosted. Poppins for interface text, Lora for reading
   text. Both are SIL Open Font License, downloaded once into static/fonts so
   the app never calls a font CDN at runtime. */

@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/static/fonts/poppins-400-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/static/fonts/poppins-400-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/static/fonts/poppins-500-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/static/fonts/poppins-500-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/static/fonts/poppins-600-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/static/fonts/poppins-600-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Lora';
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url('/static/fonts/lora-400-italic-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Lora';
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url('/static/fonts/lora-400-italic-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Lora';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/static/fonts/lora-400-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Lora';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/static/fonts/lora-400-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* Tokens. Light is the default; dark follows the OS unless the operator has
   chosen a theme explicitly, which is what data-theme="light|dark" pins. */
.sentinel-ui {
  color-scheme: light;
  --sn-bg: #FAF9F5;
  --sn-sidebar: #F3F2EC;
  --sn-surface: #FFFFFF;
  --sn-raised: #FFFFFF;
  --sn-input: #F6F5F0;
  --sn-hover: #EDECE5;
  --sn-text: #20201D;
  --sn-secondary: #67665E;
  --sn-muted: #716F66;
  --sn-border: #25251F16;
  --sn-border-strong: #25251F26;
  --sn-control-border: #8F8C82;
  --sn-control-border-hover: #68665D;
  --sn-accent: #6A9BCC;
  --sn-accent-hover: #7CAAD6;
  --sn-accent-active: #5A8BBB;
  --sn-on-accent: #102334;
  --sn-accent-soft: #6A9BCC17;
  --sn-link: #356B9E;
  --sn-focus: #5488BD;
  --sn-success: #3F6C4C;
  --sn-warning: #855E20;
  --sn-danger: #A53D37;
  --sn-selection-bg: #CEE0F0;
  --sn-selection-text: #102334;
  --sn-scroll-thumb: #96938A;
  --sn-scroll-thumb-hover: #747168;
  --sn-scroll-track: transparent;
  --sn-chevron: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23716F66' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  --sn-backdrop: #14141366;
  --sn-shadow-panel: 0 8px 28px #23231D12, 0 2px 6px #23231D08;
  --sn-shadow-dialog: 0 24px 64px #23231D26, 0 2px 8px #23231D14;
  --sn-font-ui: 'Poppins', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --sn-font-reading: 'Lora', Georgia, serif;
  --sn-font-mono: ui-monospace, 'SFMono-Regular', 'SF Mono', Menlo, Consolas, monospace;
  --sn-radius-sm: 6px;
  --sn-radius-control: 8px;
  --sn-radius-menu: 10px;
  --sn-radius-panel: 12px;
  --sn-radius-composer: 14px;
  --sn-radius-dialog: 16px;
  --sn-control-height: 36px;
  --sn-sidebar-width: 240px;
  --sn-duration-fast: 140ms;
  --sn-duration-overlay: 180ms;
  --sn-ease: cubic-bezier(.2,.8,.2,1);
  --sn-z-sticky: 10;
  --sn-z-drawer: 45;
  --sn-z-menu: 60;
  --sn-z-dialog: 80;
  --sn-z-toast: 100;

  background: var(--sn-bg);
  color: var(--sn-text);
  font: 400 13px/1.5 var(--sn-font-ui);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

@media (prefers-color-scheme: dark) {
  .sentinel-ui:not([data-theme="light"]) {
    color-scheme: dark;
    --sn-bg: #141413;
    --sn-sidebar: #1B1B19;
    --sn-surface: #232320;
    --sn-raised: #2B2B26;
    --sn-input: #1C1C19;
    --sn-hover: #2B2B26;
    --sn-text: #FAF9F5;
    --sn-secondary: #B5B3A9;
    --sn-muted: #96948A;
    --sn-border: #FFFFFF12;
    --sn-border-strong: #FFFFFF1F;
    --sn-control-border: #79776D;
    --sn-control-border-hover: #AAA79A;
    --sn-accent-soft: #6A9BCC19;
    --sn-link: #91BAE2;
    --sn-focus: #83AFDA;
    --sn-success: #9BC2A6;
    --sn-warning: #DDB67A;
    --sn-danger: #EBA49F;
    --sn-selection-bg: #35546D;
    --sn-selection-text: #FAF9F5;
    --sn-scroll-thumb: #79776D;
    --sn-scroll-thumb-hover: #96948A;
  --sn-chevron: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2396948A' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
    --sn-backdrop: #08080799;
    --sn-shadow-panel: 0 8px 28px #00000040, 0 1px 3px #00000026;
    --sn-shadow-dialog: 0 24px 64px #00000066, 0 2px 8px #00000033;
  }
}

.sentinel-ui[data-theme="dark"] {
  color-scheme: dark;
  --sn-bg: #141413;
  --sn-sidebar: #1B1B19;
  --sn-surface: #232320;
  --sn-raised: #2B2B26;
  --sn-input: #1C1C19;
  --sn-hover: #2B2B26;
  --sn-text: #FAF9F5;
  --sn-secondary: #B5B3A9;
  --sn-muted: #96948A;
  --sn-border: #FFFFFF12;
  --sn-border-strong: #FFFFFF1F;
  --sn-control-border: #79776D;
  --sn-control-border-hover: #AAA79A;
  --sn-accent-soft: #6A9BCC19;
  --sn-link: #91BAE2;
  --sn-focus: #83AFDA;
  --sn-success: #9BC2A6;
  --sn-warning: #DDB67A;
  --sn-danger: #EBA49F;
  --sn-selection-bg: #35546D;
  --sn-selection-text: #FAF9F5;
  --sn-scroll-thumb: #79776D;
  --sn-scroll-thumb-hover: #96948A;
  --sn-chevron: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2396948A' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  --sn-backdrop: #08080799;
  --sn-shadow-panel: 0 8px 28px #00000040, 0 1px 3px #00000026;
  --sn-shadow-dialog: 0 24px 64px #00000066, 0 2px 8px #00000033;
}

/* Base. Scrollbars are themed on the document and on every nested scroll
   region: sidebar, transcript, menus, dialogs, tables, code and textareas. */
*, *::before, *::after { box-sizing: border-box; }
html, body { height: 100%; margin: 0; }
.sentinel-ui, .sentinel-ui * {
  scrollbar-width: thin;
  scrollbar-color: var(--sn-scroll-thumb) var(--sn-scroll-track);
}
.sentinel-ui::-webkit-scrollbar, .sentinel-ui *::-webkit-scrollbar { width: 10px; height: 10px; }
.sentinel-ui::-webkit-scrollbar-track, .sentinel-ui *::-webkit-scrollbar-track { background: var(--sn-scroll-track); }
.sentinel-ui::-webkit-scrollbar-thumb, .sentinel-ui *::-webkit-scrollbar-thumb {
  background: var(--sn-scroll-thumb);
  border: 2px solid transparent;
  background-clip: padding-box;
  border-radius: 999px;
}
.sentinel-ui::-webkit-scrollbar-thumb:hover, .sentinel-ui *::-webkit-scrollbar-thumb:hover { background-color: var(--sn-scroll-thumb-hover); }
.sentinel-ui::-webkit-scrollbar-corner, .sentinel-ui *::-webkit-scrollbar-corner { background: var(--sn-bg); }
.sentinel-ui ::selection { background: var(--sn-selection-bg); color: var(--sn-selection-text); }
.sentinel-ui :where(input, textarea, [contenteditable="true"]) { caret-color: var(--sn-accent); }
.sentinel-ui :where(input, textarea)::placeholder { color: var(--sn-muted); opacity: 1; }
.sentinel-ui :where(button, a, input, textarea, select, summary, [contenteditable], [role="button"], [tabindex]):focus-visible {
  outline: 2px solid var(--sn-focus);
  outline-offset: 2px;
  border-radius: var(--sn-radius-sm);
}
.sentinel-ui :where(button, input, select, textarea):disabled,
.sentinel-ui [aria-disabled="true"] { opacity: .5; cursor: not-allowed; }

.hidden { display: none !important; }
/* the browser's hidden attribute loses to any display rule of ours, so say
   it outright: an element with hidden is not on the page, whatever it is */
[hidden] { display: none !important; }
.muted { color: var(--sn-muted); }
.dim { color: var(--sn-secondary); }
.spacer { flex: 1; }
.icon { display: block; flex: none; }
button, input, textarea, select { font: inherit; }
b, strong { font-weight: 600; }
h1, h2, h3, h4 { font-family: var(--sn-font-ui); }

/* Small shared pieces used by more than one surface. */
.pop-item .tick { display: inline-flex; align-items: center; width: 16px; min-width: 16px; color: var(--sn-link); }
.pop-field > label { display: block; margin-bottom: 5px; font-size: 12px; color: var(--sn-secondary); }
.chip.label { color: var(--sn-on-accent); font-weight: 500; border-color: transparent; }
.skel { height: 12px; border-radius: 6px; background: var(--sn-hover); }
.skel + .skel { margin-top: 10px; }
.skel.w40 { width: 40%; }
.skel.w55 { width: 55%; }
.skel.w70 { width: 70%; }
.send-btn[aria-busy="true"] .icon { animation: spin 1s linear infinite; }
#auth-form .btn.block { margin-top: 20px; }

/* Fields. Label above, help or error below, control border for a boundary that
   survives both themes. The composer uses its own integrated surface instead. */
input, textarea, select {
  width: 100%; min-width: 0; min-height: 38px; padding: 9px 11px; color: var(--sn-text);
  background: var(--sn-input); border: 1px solid var(--sn-control-border);
  border-radius: var(--sn-radius-control); font-size: 13px;
  transition: border-color var(--sn-duration-fast), background-color var(--sn-duration-fast);
}
input:hover, textarea:hover, select:hover { border-color: var(--sn-control-border-hover); }
input:focus, textarea:focus, select:focus { outline: none; border-color: var(--sn-focus); box-shadow: 0 0 0 3px var(--sn-accent-soft); }
input[aria-invalid="true"], textarea[aria-invalid="true"] { border-color: var(--sn-danger); }
input:user-invalid, textarea:user-invalid { border-color: var(--sn-danger); }
input[readonly], textarea[readonly] { background: var(--sn-surface); color: var(--sn-secondary); }
input:autofill, input:-webkit-autofill {
  -webkit-text-fill-color: var(--sn-text);
  -webkit-box-shadow: 0 0 0 1000px var(--sn-input) inset;
  caret-color: var(--sn-accent);
}
input[type="color"] {
  padding: 3px; width: 44px; min-height: 36px; cursor: pointer; background: var(--sn-input);
}
input[type="color"]::-webkit-color-swatch-wrapper { padding: 0; }
input[type="color"]::-webkit-color-swatch, input[type="color"]::-moz-color-swatch { border: 0; border-radius: 4px; }
input[type="file"] { padding: 7px 9px; font-size: 12px; color: var(--sn-secondary); }
input[type="file"]::file-selector-button {
  margin-inline-end: 12px; padding: 7px 12px; border: 1px solid var(--sn-control-border);
  border-radius: 8px; background: var(--sn-surface); color: var(--sn-text); font: inherit; cursor: pointer;
}
input[type="file"]::file-selector-button:hover { background: var(--sn-hover); }
select {
  appearance: none; padding-right: 30px; cursor: pointer;
  background-image: var(--sn-chevron);
  background-repeat: no-repeat; background-position: right 9px center; background-size: 14px;
}
select option { background: var(--sn-raised); color: var(--sn-text); }

/* Checkboxes, radios and switches keep their native semantics. The visible box
   is drawn here, the mark is drawn on the input itself. */
input[type="checkbox"], input[type="radio"] {
  appearance: none; -webkit-appearance: none; display: inline-grid; place-content: center;
  width: 17px; height: 17px; min-width: 17px; min-height: 0; padding: 0; margin: 0; flex: none;
  border: 1px solid var(--sn-control-border); background: var(--sn-input);
  color: var(--sn-on-accent); cursor: pointer;
  transition: background-color var(--sn-duration-fast), border-color var(--sn-duration-fast);
}
input[type="checkbox"] { border-radius: 4px; }
input[type="radio"] { border-radius: 50%; }
input[type="checkbox"]:hover, input[type="radio"]:hover { border-color: var(--sn-control-border-hover); }
input[type="checkbox"]:checked, input[type="checkbox"]:indeterminate, input[type="radio"]:checked {
  background: var(--sn-accent); border-color: var(--sn-link);
}
input[type="checkbox"]::before {
  content: ''; width: 10px; height: 10px; background: currentColor;
  clip-path: polygon(14% 44%, 0 59%, 39% 96%, 100% 20%, 84% 7%, 37% 67%); transform: scale(0);
}
input[type="checkbox"]:checked::before { transform: scale(1); }
input[type="checkbox"]:indeterminate::before {
  width: 9px; height: 2px; clip-path: none; transform: none; border-radius: 1px;
}
input[type="radio"]::before { content: ''; width: 7px; height: 7px; border-radius: 50%; background: currentColor; transform: scale(0); }
input[type="radio"]:checked::before { transform: scale(1); }

/* A switch for a setting that applies straight away. Native checkbox semantics,
   role="switch" for the announcement, and the same track in both themes. */
input[role="switch"] {
  position: relative; width: 34px; height: 20px; min-width: 34px; border-radius: 999px;
  background: var(--sn-input); border: 1px solid var(--sn-control-border);
}
input[role="switch"]::before {
  content: ''; position: absolute; top: 2px; left: 2px; width: 14px; height: 14px;
  border-radius: 50%; background: var(--sn-secondary); clip-path: none; transform: none;
  transition: transform var(--sn-duration-fast) var(--sn-ease);
}
input[role="switch"]:checked { background: var(--sn-accent); border-color: var(--sn-link); }
input[role="switch"]:checked::before { transform: translateX(14px); background: var(--sn-on-accent); }
input[role="switch"]:disabled { opacity: .5; }
input[type="checkbox"][aria-invalid="true"], input[type="radio"][aria-invalid="true"] { border-color: var(--sn-danger); }

label.field { display: block; font-size: 12px; font-weight: 500; color: var(--sn-text); margin: 14px 0 6px; }
.field-row { display: flex; gap: 10px; align-items: flex-start; }
.field-row > * { flex: 1; min-width: 0; }
.grid2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
.hint { color: var(--sn-secondary); font-size: 12px; margin: 0 0 12px; line-height: 1.6; }

/* A labeled checkbox or radio row is the click target, not just the box. */
label.check, label.pop-item {
  display: flex; align-items: center; gap: 8px; min-height: 32px; margin: 0;
  color: var(--sn-text); font-size: 13px; cursor: pointer;
}

/* Buttons. Secondary stays quiet so the blue action is the only loud thing. */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px; min-height: var(--sn-control-height);
  padding: 8px 12px; color: var(--sn-text); background: var(--sn-surface);
  border: 1px solid var(--sn-border-strong); border-radius: var(--sn-radius-control);
  font-size: 12px; font-weight: 400; cursor: pointer; text-decoration: none;
  transition: background-color var(--sn-duration-fast), border-color var(--sn-duration-fast), color var(--sn-duration-fast);
}
.btn:hover:not(:disabled) { background: var(--sn-hover); border-color: var(--sn-control-border); }
.btn:active:not(:disabled) { border-color: var(--sn-control-border-hover); }
.btn.primary { background: var(--sn-accent); border-color: transparent; color: var(--sn-on-accent); font-weight: 500; }
.btn.primary:hover:not(:disabled) { background: var(--sn-accent-hover); }
.btn.primary:active:not(:disabled) { background: var(--sn-accent-active); }
.btn.ghost { background: transparent; border-color: transparent; color: var(--sn-secondary); }
.btn.ghost:hover:not(:disabled) { background: var(--sn-hover); color: var(--sn-text); }
.btn.danger { color: var(--sn-danger); }
.btn.danger:hover:not(:disabled) { background: var(--sn-hover); border-color: var(--sn-danger); }
.btn.sm { min-height: 32px; padding: 6px 10px; }
.btn.block { width: 100%; }
.btn:disabled { cursor: default; }
.icon-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px; min-height: 32px; min-width: 32px;
  padding: 6px; background: transparent; border: 1px solid transparent; border-radius: var(--sn-radius-control);
  color: var(--sn-secondary); font-size: 12px; cursor: pointer;
  transition: background-color var(--sn-duration-fast), color var(--sn-duration-fast), border-color var(--sn-duration-fast);
}
.icon-btn:hover { background: var(--sn-hover); color: var(--sn-text); }
.icon-btn.on, .icon-btn[aria-pressed="true"] {
  color: var(--sn-link); border-color: var(--sn-accent); background: var(--sn-accent-soft);
}
a.icon-btn { text-decoration: none; }

/* Sign in and first run. The two screens are one shell, and signing in or out
   slides between them rather than cutting. */
#auth-screen, #app {
  transition: opacity 170ms var(--sn-ease), transform 170ms var(--sn-ease);
}
/* Both directions move up. A screen that slides down past the bottom of the
   viewport makes the document scroll for the length of the animation, which shows
   up as a scrollbar that flashes and vanishes. */
#auth-screen.leaving, #app.leaving { opacity: 0; transform: translateY(-6px); pointer-events: none; }
#auth-screen.entering, #app.entering { opacity: 0; transform: translateY(-6px); }
@media (prefers-reduced-motion: reduce) {
  #auth-screen, #app { transition: none; }
  #auth-screen.leaving, #app.leaving,
  #auth-screen.entering, #app.entering { transform: none; opacity: 1; }
}

/* Sign in and first run. */
#auth-screen { display: grid; place-items: center; min-height: 100%; padding: 24px; background: var(--sn-bg); }
#auth-form { width: 100%; max-width: 360px; }
/* The login form carries no brand: a heading, a line of prose, two fields, one
   action. The heading uses the same measure as the page heading inside the app. */
#auth-form .auth-title {
  margin: 0 0 10px; color: var(--sn-text); text-align: center;
  font: 400 30px/1.25 var(--sn-font-ui); letter-spacing: -.035em;
}
#auth-form .auth-sub {
  margin: 0 0 28px; color: var(--sn-secondary); text-align: center;
  font: 400 15px/1.7 var(--sn-font-reading);
}
#auth-form .field:first-of-type { margin-top: 0; }
#auth-submit[aria-busy="true"] .icon { animation: spin 1s linear infinite; }
/* the second step of a sign in: the code, one box per digit, the way an
   authenticator app presents it */
#auth-form .auth-who {
  margin: 0 0 18px; color: var(--sn-secondary); text-align: center;
  font: 400 13px/1.6 var(--sn-font-reading);
}
.otp-row { display: flex; gap: 10px; justify-content: center; margin: 4px 0 0; }
.otp-digit {
  width: 46px; height: 54px; padding: 0; text-align: center;
  font: 500 22px/1 var(--sn-font-ui); color: var(--sn-text);
  background: var(--sn-input); border: 1px solid var(--sn-border-strong);
  border-radius: var(--sn-radius-control); caret-color: var(--sn-accent);
}
.otp-digit:focus { outline: none; border-color: var(--sn-accent); }
.otp-digit[aria-invalid="true"] { border-color: var(--sn-danger); }
#auth-form .btn.block { margin-top: 20px; }

/* Shell. A compact sidebar, a quiet 60px header, then the working region. */
#app { display: grid; grid-template-columns: var(--sn-sidebar-width) minmax(0, 1fr) auto; height: 100%; }

#sidebar {
  display: flex; flex-direction: column; min-height: 0; min-width: 0;
  background: var(--sn-sidebar); border-right: 1px solid var(--sn-border);
}
.side-top { padding: 26px 20px 0; }
.brandmark { display: block; width: 141px; color: var(--sn-text); }
.brandmark svg { width: 100%; height: auto; display: block; }
.side-top .brandmark { margin-bottom: 28px; }
.new-btn {
  display: flex; align-items: center; gap: 8px; width: calc(100% - 32px); margin: 0 16px;
  min-height: var(--sn-control-height); padding: 8px 12px; background: var(--sn-surface);
  border: 1px solid var(--sn-border-strong); border-radius: var(--sn-radius-control);
  color: var(--sn-text); font-size: 13px; font-weight: 500; cursor: pointer;
  transition: background-color var(--sn-duration-fast), border-color var(--sn-duration-fast);
}
.new-btn:hover { background: var(--sn-hover); border-color: var(--sn-control-border); }
.new-btn .icon { color: var(--sn-accent); }
.list-head { display: flex; align-items: center; gap: 8px; padding: 25px 10px 8px 18px; }
.list-head .lh-label, .list-head span { font-size: 12px; color: var(--sn-secondary); }
.list-head .lh-count { color: var(--sn-muted); }
.list-head .spacer { flex: 1; }
.session-items { flex: 1; min-height: 0; overflow-y: auto; padding: 0 8px 12px; }
.session-item {
  position: relative; padding: 7px 32px 7px 10px; border-radius: var(--sn-radius-control);
}
.session-item + .session-item { margin-top: 2px; }
.session-item:hover { background: var(--sn-hover); }
.session-item.active { background: var(--sn-hover); }
.si-open {
  display: flex; align-items: center; gap: 9px; width: 100%; padding: 0; text-align: left;
  background: none; border: 0; color: inherit; cursor: pointer; min-width: 0;
}
.si-title {
  display: block; min-width: 0; font-size: 13px; color: var(--sn-secondary);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.session-item:hover .si-title { color: var(--sn-text); }
.session-item.active .si-title { color: var(--sn-text); font-weight: 500; }
/* One dot for what a session is doing, and nothing else on the row. */
.si-state { width: 8px; height: 8px; flex: none; border-radius: 50%; background: var(--sn-border-strong); }
.si-state.running { background: var(--sn-success); }
.si-state.waiting { background: var(--sn-warning); }
.si-state.error { background: var(--sn-danger); }
.si-state.done, .si-state.stopped { background: var(--sn-muted); }
.si-state.paused { background: var(--sn-border-strong); }
.si-more {
  position: absolute; right: 4px; top: 50%; transform: translateY(-50%);
  display: inline-flex; padding: 4px; line-height: 0;
  background: none; border: 0; border-radius: var(--sn-radius-sm); color: var(--sn-secondary);
  cursor: pointer; opacity: 0;
}
.session-item:hover .si-more, .session-item:focus-within .si-more, .session-item.active .si-more { opacity: 1; }
.si-more:hover { background: var(--sn-hover); color: var(--sn-text); }
.pin-mark { color: var(--sn-link); }
.unread { width: 7px; height: 7px; border-radius: 50%; background: var(--sn-accent); flex: none; }
.dots { display: inline-flex; gap: 4px; align-items: center; }
.dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; flex: none; }
.rail-group { font-size: 12px; color: var(--sn-muted); padding: 12px 10px 4px; }
.rail-empty { display: flex; flex-direction: column; align-items: center; text-align: center; padding: 28px 16px; }
.rail-empty .icon { color: var(--sn-muted); margin-bottom: 10px; }
.rail-empty .re-title { font-size: 13px; color: var(--sn-text); }
.rail-empty .re-body { font-size: 12px; color: var(--sn-secondary); line-height: 1.6; margin-top: 4px; }
.side-foot {
  display: flex; align-items: center; gap: 8px; padding: 8px 12px;
  border-top: 1px solid var(--sn-border);
}
.avatar {
  display: grid; place-items: center; width: 28px; height: 28px; flex: none; border-radius: 50%;
  background: var(--sn-surface); border: 1px solid var(--sn-border-strong); color: var(--sn-text);
  font-size: 12px; font-weight: 500; cursor: pointer;
}
.avatar:hover { background: var(--sn-hover); }
.side-id { min-width: 0; min-height: 0; font-size: 12px; color: var(--sn-secondary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* the same identity row, reused on the profile screen: the letter mark and
   the name, with the role said once beside it */
.profile-id { padding: 0 0 14px; border: 0; }
.profile-id .side-id { font-size: 14px; color: var(--sn-text); font-weight: 500; }
.profile-id .you { margin-left: 6px; font-size: 11px; color: var(--sn-muted); }

#main { display: flex; flex-direction: column; min-width: 0; min-height: 0; }
.head-bar {
  display: flex; align-items: center; gap: 12px; flex: none; min-height: 60px;
  padding: 0 28px; border-bottom: 1px solid var(--sn-border); background: var(--sn-bg);
}
#nav-toggle { display: none; }
#chat-head { display: flex; align-items: center; gap: 14px; min-width: 0; flex: 1; }
.head-main { min-width: 0; flex: 1; }
.ch-line { display: flex; align-items: baseline; gap: 8px; min-width: 0; }
.crumb-root, .crumb-sep { flex: none; font-size: 13px; }
.crumb-root { color: var(--sn-secondary); }
.crumb-sep { color: var(--sn-muted); }
.ch-title {
  min-width: 0; font-size: 13px; font-weight: 500; color: var(--sn-text); white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; cursor: text; border-radius: var(--sn-radius-sm);
}
.ch-title[contenteditable="true"] {
  padding: 3px 8px; margin-left: -9px; background: var(--sn-input);
  border: 1px solid var(--sn-focus); outline: none; white-space: normal;
}
.ch-sub { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; min-width: 0;
  font-size: 12px; color: var(--sn-muted); margin-top: 3px; }
/* A session note can be a whole sentence. It keeps one line and is cut off: the header
   is a place to see the state, and the tooltip under it has the whole sentence. */
.ch-sub [data-note] { min-width: 0; max-width: 100%; flex: 0 1 auto;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ch-sub .dim { color: var(--sn-muted); }
.head-actions { display: flex; align-items: center; gap: 6px; flex: none; }

/* A stretch of tool activity: one line while collapsed, so the chat reads as the work
   rather than as a log of it. The caller can open it to see exactly what was run. The
   model's narration inside the stretch is never folded away: it reads as ordinary text
   whether the trace is open or not. */
div.trace { width: 100%; max-width: 820px; margin: 2px auto; }
.trace-head {
  display: flex; align-items: center; gap: 6px; cursor: pointer; width: 100%;
  min-height: 24px; padding: 2px 2px; border-radius: var(--sn-radius-sm);
  font-size: 12px; color: var(--sn-muted); background: none; border: 0; text-align: left;
}
.trace-head:hover { color: var(--sn-secondary); background: var(--sn-hover); }
.trace-head .icon { flex: none; transition: transform var(--sn-duration-fast); }
.trace[data-open="0"] .trace-head .icon { transform: rotate(0deg); }
.trace:not([data-open="0"]) .trace-head .icon { transform: rotate(90deg); }
.trace-items { padding-left: 14px; border-left: 1px solid var(--sn-border); margin: 2px 0 4px 6px; }
.trace-items .msg { animation: none; }
.trace-items .msg-call { margin-top: 2px; }
.trace-items .msg.tool { margin-top: 2px; }
.trace[data-open="0"] .ti-step { display: none; }
.ti-prose { color: var(--sn-text); }

/* A message arriving is part of the reading: it fades up rather than appearing, and an
   answer wipes in from the top the way it is read. Reduced motion turns both off. */
@keyframes msg-in {
  from { opacity: 0; transform: translateY(5px); }
  to { opacity: 1; transform: none; }
}
@keyframes write-in {
  from { clip-path: inset(0 0 100% 0); opacity: 0.4; }
  to { clip-path: inset(0 0 0 0); opacity: 1; }
}
.transcript > .msg { animation: msg-in 170ms var(--sn-ease) both; }
/* An answer is revealed letter by letter in the page, not wiped: nothing here, so a
   repaint or a hidden tab cannot leave it half written. */
.transcript > .msg#streaming, .transcript > .msg#streaming > .md { animation: none; }

/* Transcript. The reading column, then the card shapes used inside it. */
.transcript {
  flex: 1; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; gap: 16px;
  padding: 24px 24px 8px; overscroll-behavior: contain; min-width: 0;
}
.transcript .msg { min-width: 0; overflow-wrap: anywhere; }
.transcript.empty { justify-content: center; padding-bottom: 48px; }
.msg { width: 100%; max-width: 820px; margin: 0 auto; min-width: 0; }
/* What the operator said is a bubble that takes the width of what they wrote, on their
   side of the page, with its actions under it rather than in it. */
.msg.user { display: flex; flex-direction: column; align-items: flex-end; }
.msg.user .bubble {
  max-width: 78%; padding: 11px 14px; background: var(--sn-surface);
  border: 1px solid var(--sn-border-strong); border-radius: var(--sn-radius-panel)
  var(--sn-radius-panel) 4px var(--sn-radius-panel);
}
.msg.user pre {
  margin: 0; font-family: var(--sn-font-reading); font-size: 15px; line-height: 1.65;
  white-space: pre-wrap; overflow-wrap: anywhere;
}
.msg.user .msg-actions { justify-content: flex-end; }
.msg.assistant { padding: 0 2px; }
.msg.tool { padding-left: 14px; border-left: 2px solid var(--sn-border-strong); }
.msg.tool summary {
  display: flex; align-items: center; gap: 7px; cursor: pointer; color: var(--sn-secondary);
  font-size: 12px; font-family: var(--sn-font-mono); list-style: none;
}
.msg.tool summary::-webkit-details-marker { display: none; }
.msg.tool summary .icon { color: var(--sn-muted); transition: transform var(--sn-duration-fast); }
.msg.tool[open] summary .icon { transform: rotate(90deg); }
.msg.tool pre {
  margin-top: 8px; padding: 12px; max-height: 340px; overflow: auto; font-family: var(--sn-font-mono);
  font-size: 12px; line-height: 1.6; color: var(--sn-text); background: var(--sn-input);
  border: 1px solid var(--sn-border-strong); border-radius: var(--sn-radius-control);
  white-space: pre-wrap; overflow-wrap: anywhere;
}
.msg-call {
  display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap; min-width: 0;
  margin-top: 6px; font-family: var(--sn-font-mono); font-size: 12px;
  color: var(--sn-secondary); overflow-wrap: anywhere;
}
.msg-call .icon { color: var(--sn-muted); flex: none; }
.msg-call .mc-name { flex: none; }
/* the arguments are what is long: they take the rest of the line and wrap under the
   name rather than widening the transcript */
.msg-call .mc-args { min-width: 0; flex: 1 1 12ch; overflow-wrap: anywhere; }
/* What the model thought before it answered, folded away behind the reasoning toggle.
   It is the same voice as the answer, one step quieter. */
/* Thinking is text in the same column as the answer, not a card beside it: dimmed, in
   the answer's own type, with one quiet word saying what it is. */
.transcript .reasoning {
  margin: 0 0 8px; padding: 0; max-width: 100%;
  background: none; border: 0; border-radius: 0;
  font-size: 13px; color: var(--sn-secondary); opacity: 0.6;
}
.transcript .reasoning[open]:hover, .transcript .reasoning:focus-within { opacity: 0.85; }
.transcript .reasoning summary {
  display: inline-flex; align-items: center; gap: 5px; cursor: pointer; font-size: 11.5px;
  font-style: italic; color: var(--sn-muted); list-style: none; margin-bottom: 2px;
}
.transcript .reasoning summary::-webkit-details-marker { display: none; }
.transcript .reasoning summary .icon { flex: none; }
.transcript .reasoning[open] summary { margin-bottom: 6px; }
.transcript .reasoning .md { min-width: 0; overflow-wrap: anywhere; font-style: italic; }
#composer-reasoning.on { color: var(--sn-link); background: var(--sn-accent-soft); }

/* Notes and errors are the session talking to itself: output, so left aligned, with a
   mark that says which kind it is. */
.msg.note, .msg.error {
  display: flex; align-items: flex-start; gap: 8px; padding-left: 2px;
  color: var(--sn-muted); font-size: 12px; line-height: 1.6;
}
.msg.note .icon, .msg.error .icon { flex: none; margin-top: 2px; color: var(--sn-muted); }
.msg.error { color: var(--sn-danger); }
.msg.error .icon { color: var(--sn-danger); }
.msg.note span, .msg.error span { min-width: 0; overflow-wrap: anywhere; }
/* What the agent said keeps its row of actions on show: that is where the time, the
   retry and the copy live, and hunting for them by hovering is a chore. What the
   operator said keeps its own row for the hover, so the bubble stays clean. */
.msg-actions {
  display: flex; align-items: center; gap: 4px; margin-top: 8px;
  transition: opacity var(--sn-duration-fast);
}
.msg.user .msg-actions { opacity: 0; }
.msg.user:hover .msg-actions, .msg.user:focus-within .msg-actions { opacity: 1; }
.msg-when {
  margin-right: 2px; font-size: 11px; color: var(--sn-muted);
  font-variant-numeric: tabular-nums;
}
.msg-actions .icon-btn { padding: 4px; min-height: 0; min-width: 0; color: var(--sn-muted); }
/* Output arrives, it is not printed: a short fade and rise, and nothing at all when the
   operator has asked for less motion. */
.msg.arrive { animation: msg-arrive 240ms var(--sn-ease) both; }
@keyframes msg-arrive {
  from { opacity: 0; transform: translateY(4px); }
  to { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .msg.arrive { animation: none; }
}
.msg-actions .icon-btn:hover { color: var(--sn-text); background: var(--sn-hover); }
.msg.user .msg-actions { justify-content: flex-end; }

.card-msg { background: var(--sn-surface); border: 1px solid var(--sn-border-strong); border-radius: var(--sn-radius-panel); padding: 16px; }
.card-msg.attention { border-color: var(--sn-accent); background: var(--sn-raised); }
.card-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 10px; }
.card-title { font-size: 14px; font-weight: 500; }
.msg.finding { border-left: 3px solid var(--sn-status, var(--sn-border-strong)); }
/* The summary is the headline of a finished session and nothing else: no card, no
   border, no background. A small label, one line saying what it is, then the prose. */
.msg.summary { padding: 2px 2px 0; background: none; border: 0; }
.msg.summary .sum-head {
  display: flex; align-items: center; gap: 8px; margin-bottom: 10px;
}
.msg.summary .sum-head .badge { font-size: 11px; }
.msg.summary .sum-head .sub { font-size: 12px; color: var(--sn-muted); }
.msg.summary .md { margin-top: 0; }

/* A compaction is a note like any other: it belongs in the log, in the same voice as
   "stopped by operator", not in a shape of its own. */
.msg.attachment { border-left: 3px solid var(--sn-accent); }
.card-msg.sev-critical, .card-msg.sev-high, .card-msg.sev-error { --sn-status: var(--sn-danger); }
.card-msg.sev-medium, .card-msg.sev-warning { --sn-status: var(--sn-warning); }
.card-msg.sev-low, .card-msg.sev-info { --sn-status: var(--sn-muted); }
.card-msg.sev-done, .card-msg.sev-success { --sn-status: var(--sn-success); }
[data-status="success"] { --sn-status: var(--sn-success); }
[data-status="warning"] { --sn-status: var(--sn-warning); }
[data-status="error"] { --sn-status: var(--sn-danger); }
[data-status="info"] { --sn-status: var(--sn-link); }

.badge {
  display: inline-flex; align-items: center; gap: 5px; padding: 2px 7px; border-radius: 5px;
  border: 1px solid var(--sn-border-strong); background: color-mix(in srgb, var(--sn-status, transparent) 10%, transparent);
  color: var(--sn-status, var(--sn-secondary)); font-size: 12px; white-space: nowrap;
}
.badge.critical, .badge.high, .badge.error, .badge.stopped, .badge.blocked { --sn-status: var(--sn-danger); }
.badge.medium, .badge.paused, .badge.queued, .badge.draft { --sn-status: var(--sn-warning); }
.badge.done, .badge.accepted { --sn-status: var(--sn-success); }
.badge.running, .badge.waiting { --sn-status: var(--sn-link); }
.badge.low, .badge.info { --sn-status: var(--sn-muted); }
.ev { display: flex; align-items: flex-start; gap: 5px; font-family: var(--sn-font-mono); font-size: 12px; }
.ev.ok { color: var(--sn-success); }
.ev.bad { color: var(--sn-danger); }
.ev .t { color: var(--sn-muted); }
.request-actions { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 14px; }
.request-cmd {
  padding: 10px 12px; font-family: var(--sn-font-mono); font-size: 12px; line-height: 1.6;
  background: var(--sn-input); border: 1px solid var(--sn-border-strong);
  border-radius: var(--sn-radius-control); overflow-x: auto; white-space: pre-wrap; overflow-wrap: anywhere;
}
.answer-line { font-size: 12px; color: var(--sn-secondary); }
.attach-path { font-family: var(--sn-font-mono); font-size: 12px; color: var(--sn-muted); overflow-wrap: anywhere; }
#typing { display: flex; align-items: center; gap: 12px; min-width: 0; }
.typing-text { min-width: 0; font-size: 12.5px; color: var(--sn-muted); overflow-wrap: anywhere; }
.typing-meta { flex: none; font-size: 11.5px; color: var(--sn-muted); opacity: 0.75; }
.typing { display: inline-flex; align-items: center; gap: 6px; color: var(--sn-link);
  font-size: 12px; flex: none; }
.typing i { width: 5px; height: 5px; border-radius: 50%; background: var(--sn-link); animation: pulse 1.1s infinite; }
.typing i:nth-child(2) { animation-delay: .15s; }
.typing i:nth-child(3) { animation-delay: .3s; }
.caret { display: inline-block; width: 7px; height: 15px; margin-left: 3px; background: var(--sn-accent); animation: pulse 1.1s infinite; vertical-align: text-bottom; }
@keyframes pulse { 0%, 60%, 100% { opacity: .25; } 30% { opacity: 1; } }
@keyframes spin { to { transform: rotate(360deg); } }

/* The plan, both as a header disclosure and as a panel above the composer. */
.plan li.in_progress .icon { color: var(--sn-accent); animation: spin 2.4s linear infinite; }
.plan li.pending .icon { color: var(--sn-muted); }
/* The live plan, while there is work in it, sits at the end of the chat. Once every
   item is done it is written into the transcript as a message and this goes away. */
.plan-holder { width: 100%; max-width: 820px; margin: 0 auto; min-width: 0; }
/* The finished plan is the same thing in the same place: it does not animate in, it
   does not gain a box, and it scrolls with the chat rather than sitting above it. */
.msg.plan-msg, .transcript > .msg.plan-msg { animation: none; padding: 0; }
.plan-holder:empty { display: none; }
/* The plan is part of the chat: it sits in the reading column with the same spacing as
   everything else, and carries no card of its own. */
.plan-panel { max-width: 100%; margin: 0; padding: 0; background: none; border: 0; }
.plan-head { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--sn-muted); }
.plan-head .icon { color: var(--sn-muted); }
.plan-meter { flex: 1; height: 4px; margin-left: 8px; background: var(--sn-hover); border-radius: 2px; overflow: hidden; }
.plan-meter > div { height: 100%; background: var(--sn-accent); }
/* every step checked: the meter says so in green, not in the working color */
.plan-panel.complete .plan-meter > div { background: var(--sn-success); }
.plan-panel li.plan-more { color: var(--sn-muted); }
.plan-panel li.plan-more .btn { padding: 2px 10px; font-size: 12px; }
.plan-panel ul { list-style: none; margin: 8px 0 0; padding: 0; }
.plan-panel li { display: flex; align-items: flex-start; gap: 8px; padding: 3px 0; font-size: 13px; color: var(--sn-text); }
.plan-panel li.done { color: var(--sn-muted); text-decoration: line-through; }
.plan-panel li.done .icon { color: var(--sn-success); }
.plan-panel li.in_progress .icon { color: var(--sn-accent); }
/* Only while the session is running. Stopped or paused, the current step is where it got
   to, and a spinner there says work is happening when none is. */
.plan-panel.live li.in_progress .icon { animation: spin 2.4s linear infinite; }
.plan-panel li.pending .icon { color: var(--sn-muted); }
.plan-panel .icon { margin-top: 3px; }

/* Composer for a session that already exists. The starter composer below
   shares the surface, the radius and the single focus ring. */
#composer { flex: none; padding: 12px 24px 20px; }
#composer:empty { display: none; }
.composer-inner {
  position: relative;
  max-width: 820px; margin: 0 auto; background: var(--sn-surface);
  border: 1px solid var(--sn-border-strong); border-radius: var(--sn-radius-composer);
  transition: border-color var(--sn-duration-fast);
}
.composer-inner:focus-within { outline: 2px solid var(--sn-focus); outline-offset: 2px; }
.composer-inner textarea {
  display: block; width: 100%; min-height: 54px; max-height: 240px; padding: 16px 18px 6px;
  resize: none; border: 0; border-radius: 14px 14px 0 0; background: transparent;
  color: var(--sn-text); font: 400 15px/1.65 var(--sn-font-reading); overflow-y: auto;
}
.composer-inner textarea:hover, .composer-inner textarea:focus { border: 0; box-shadow: none; }
.composer-inner textarea:focus-visible { outline: none; }
.composer-bar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; padding: 4px 12px 12px; }
.composer-bar select {
  width: auto; max-width: 200px; min-height: 32px; padding: 6px 28px 6px 10px; font-size: 12px;
  background-color: var(--sn-surface); border-color: var(--sn-border-strong);
  border-radius: var(--sn-radius-control); text-overflow: ellipsis;
}
.composer-bar select.mode { max-width: 124px; }
.composer-bar select:hover { border-color: var(--sn-control-border); }
.composer-bar .select-trigger {
  width: auto; max-width: 200px; min-height: 32px; padding: 6px 6px 6px 10px;
  font-size: 12px; background: var(--sn-surface); border-color: var(--sn-border-strong);
}
.composer-bar .select-trigger.mode { max-width: 124px; }
.send-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: var(--sn-control-height); padding: 8px 14px; border: 1px solid transparent;
  border-radius: var(--sn-radius-control); background: var(--sn-accent); color: var(--sn-on-accent);
  font-size: 12px; font-weight: 500; cursor: pointer;
  transition: background-color var(--sn-duration-fast), color var(--sn-duration-fast);
}
.send-btn:hover:not(:disabled) { background: var(--sn-accent-hover); }
.send-btn:active:not(:disabled) { background: var(--sn-accent-active); }
.send-btn:disabled { cursor: default; }
.send-btn[aria-busy="true"] { cursor: progress; }
.send-btn.stop { background: var(--sn-surface); border-color: var(--sn-border-strong); color: var(--sn-danger); }
.send-btn.stop:hover:not(:disabled) { background: var(--sn-hover); }
.attach-chip {
  display: inline-flex; align-items: center; gap: 6px; padding: 3px 9px; font-size: 12px;
  color: var(--sn-text); background: var(--sn-hover); border: 1px solid var(--sn-border-strong);
  border-radius: 6px;
}
.composer-hint { max-width: 820px; margin: 10px auto 0; font-size: 12px; color: var(--sn-muted); }

/* Session commands: a slash opens the list above the composer, where the operator is
   already looking, instead of a dialog that takes the keyboard away. */
.slash-menu {
  position: absolute; left: 8px; right: 8px; bottom: calc(100% + 8px);
  padding: 4px; background: var(--sn-raised); border: 1px solid var(--sn-border-strong);
  border-radius: var(--sn-radius-menu); box-shadow: var(--sn-shadow-panel);
  z-index: var(--sn-z-menu);
}
.slash-menu.hidden { display: none; }
.slash-item {
  display: flex; align-items: baseline; gap: 10px; width: 100%; padding: 8px 10px;
  background: none; border: 0; border-radius: 8px; cursor: pointer;
  color: var(--sn-text); text-align: left; font: inherit;
}
.slash-item[aria-selected="true"], .slash-item:hover { background: var(--sn-accent-soft); }
.slash-item .sc-name { flex: none; font: 500 12.5px var(--sn-font-mono); color: var(--sn-link); }
.slash-item .sc-hint { font-size: 12px; color: var(--sn-muted); }
.slash-empty { padding: 8px 10px; font-size: 12px; color: var(--sn-muted); }

/* The first message of the session, shown only when the operator scrolls up to it. */
.msg.start-mark { justify-content: center; padding: 2px 0 8px; color: var(--sn-muted); }
.msg.start-mark .icon { color: var(--sn-muted); }

/* Starting a session. 640px column, one clear task, generous space around it. */
.new-hero { width: 100%; max-width: 640px; margin: 0 auto; }
.new-mark { width: 37px; margin-bottom: 22px; color: var(--sn-accent); }
.new-mark svg { width: 100%; height: auto; display: block; }
.new-hero h1 { margin: 0 0 12px; font: 400 30px/1.25 var(--sn-font-ui); letter-spacing: -.035em; }
.new-sub { margin: 0 0 28px; font: 400 15px/1.7 var(--sn-font-reading); color: var(--sn-secondary); }
.new-box { background: var(--sn-surface); border: 1px solid var(--sn-border-strong); border-radius: var(--sn-radius-composer); }
.new-box:focus-within { outline: 2px solid var(--sn-focus); outline-offset: 2px; }
.new-box textarea {
  display: block; width: 100%; min-height: 128px; padding: 20px; resize: vertical;
  border: 0; border-radius: 14px 14px 0 0; background: transparent; color: var(--sn-text);
  font: 400 16px/1.7 var(--sn-font-reading);
}
.new-box textarea:hover, .new-box textarea:focus { border: 0; box-shadow: none; }
.new-box textarea:focus-visible { outline: none; }
.new-bar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; padding: 4px 12px 12px; }
.new-bar select {
  width: auto; max-width: 200px; min-height: 32px; padding: 6px 28px 6px 10px; font-size: 12px;
  background-color: var(--sn-surface); border-color: var(--sn-border-strong);
  border-radius: var(--sn-radius-control); text-overflow: ellipsis;
}
.new-bar select.mode { max-width: 124px; }
.new-bar select:hover { border-color: var(--sn-control-border); }
.new-bar .select-trigger {
  width: auto; max-width: 200px; min-height: 32px; padding: 6px 6px 6px 10px;
  font-size: 12px; background: var(--sn-surface); border-color: var(--sn-border-strong);
}
.new-bar .select-trigger.mode { max-width: 124px; }
.new-bar .spacer { flex: 1; }
.new-foot {
  display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap;
  padding: 10px 20px; border-top: 1px solid var(--sn-border); font-size: 12px; color: var(--sn-muted);
}
.new-foot .foot-left { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; min-width: 0; }
.new-foot .chip { color: var(--sn-secondary); background: var(--sn-hover); border-color: transparent; }
.new-foot .chip.label { color: var(--sn-on-accent); font-weight: 500; }
.chip {
  display: inline-flex; align-items: center; gap: 6px; padding: 3px 9px; font-size: 12px;
  color: var(--sn-text); background: var(--sn-hover); border: 1px solid var(--sn-border-strong);
  border-radius: 6px;
}
.chip .icon { color: var(--sn-secondary); }
.chip-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.btn.example { padding: 6px 12px; min-height: 32px; font-size: 12px; text-align: left; max-width: 100%; }
.new-examples { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 20px; }
.new-note { display: flex; align-items: center; gap: 7px; margin-top: 20px; font-size: 12px; color: var(--sn-muted); }
.new-note .icon { color: var(--sn-muted); }

/* Reading content, tables and code. Serif for prose, sans for data, mono for
   anything that is literally code or a log line. */
.md { font: 400 15px/1.7 var(--sn-font-reading); overflow-wrap: anywhere; }
.md > *:first-child { margin-top: 0; }
.md > *:last-child { margin-bottom: 0; }
.md p { margin: 0 0 10px; }
.md h1, .md h2, .md h3, .md h4 {
  margin: 20px 0 8px; font-family: var(--sn-font-ui); font-weight: 500; line-height: 1.35; letter-spacing: -.01em;
}
.md h1 { font-size: 20px; }
.md h2 { font-size: 18px; }
.md h3 { font-size: 16px; }
.md h4 { font-size: 14px; }
.md ul, .md ol { margin: 0 0 10px; padding-left: 24px; }
.md li { margin: 4px 0; }
.md blockquote {
  margin: 0 0 10px; padding: 2px 0 2px 14px; border-left: 2px solid var(--sn-control-border);
  color: var(--sn-secondary);
}
.md hr { border: 0; border-top: 1px solid var(--sn-border); margin: 18px 0; }
.md a { color: var(--sn-link); text-decoration: underline; text-underline-offset: 3px; }
.md a:hover { text-decoration-thickness: 2px; }
.md code.inline { padding: 2px 5px; border-radius: 4px; background: var(--sn-hover); font: 400 .85em/1.5 var(--sn-font-mono); }
.md .table-wrap { overflow-x: auto; margin: 0 0 12px; overscroll-behavior: contain; }
.md table.md { width: 100%; border-collapse: collapse; font-family: var(--sn-font-ui); font-size: 13px; }
.md table.md th {
  padding: 10px 12px; text-align: left; font-weight: 500; font-size: 12px; color: var(--sn-secondary);
  background: var(--sn-hover); border-bottom: 1px solid var(--sn-border-strong); white-space: nowrap;
}
.md table.md td { padding: 10px 12px; border-bottom: 1px solid var(--sn-border); vertical-align: top; }
.md table.md tr:last-child td { border-bottom: 0; }
.code { margin: 0 0 12px; border: 1px solid var(--sn-border-strong); border-radius: var(--sn-radius-menu); overflow: hidden; background: var(--sn-input); }
.code-head {
  display: flex; align-items: center; gap: 8px; padding: 6px 10px; font-family: var(--sn-font-mono);
  font-size: 12px; color: var(--sn-secondary); background: var(--sn-hover); border-bottom: 1px solid var(--sn-border);
}
.code-head .copy {
  display: inline-flex; align-items: center; gap: 5px; margin-left: auto; padding: 3px 8px;
  background: transparent; border: 1px solid transparent; border-radius: 6px; color: var(--sn-secondary);
  font: inherit; cursor: pointer;
}
.code-head .copy:hover { color: var(--sn-text); background: var(--sn-raised); }
.code pre { margin: 0; padding: 12px 14px; overflow: auto; max-height: 480px; overscroll-behavior: contain; }
.code code { font-family: var(--sn-font-mono); font-size: 12px; line-height: 1.65; color: var(--sn-text); background: none; padding: 0; }
.dl { display: block; }
.dl.add { color: var(--sn-success); }
.dl.del { color: var(--sn-danger); }
pre.diffstat, pre.diff {
  margin: 0; padding: 10px 12px; font-family: var(--sn-font-mono); font-size: 12px; line-height: 1.6;
  background: var(--sn-input); border: 1px solid var(--sn-border-strong); border-radius: var(--sn-radius-control);
  overflow-x: auto; white-space: pre-wrap; overflow-wrap: anywhere;
}
pre.diff { max-height: 340px; overflow-y: auto; }
pre.live-out {
  margin: 0; padding: 10px 12px; max-height: 260px; overflow: auto; font-family: var(--sn-font-mono);
  font-size: 12px; line-height: 1.6; background: var(--sn-input);
  border: 1px solid var(--sn-border-strong); border-radius: var(--sn-radius-control);
}
.hljs-comment, .hljs-quote { color: var(--sn-muted); font-style: italic; }
.hljs-keyword, .hljs-selector-tag, .hljs-literal, .hljs-type,
.hljs-title, .hljs-name, .hljs-section, .hljs-function, .hljs-built_in { color: var(--sn-link); }
.hljs-string, .hljs-attr, .hljs-addition, .hljs-regexp { color: var(--sn-success); }
.hljs-number, .hljs-symbol, .hljs-bullet { color: var(--sn-warning); }
.hljs-variable, .hljs-template-variable, .hljs-params, .hljs-property { color: var(--sn-text); }
.hljs-meta, .hljs-doctag, .hljs-tag { color: var(--sn-secondary); }
.hljs-deletion { color: var(--sn-danger); }
.hljs-emphasis { font-style: italic; }
.hljs-strong { font-weight: 600; }

/* Workspace drawer. A column on a wide window, a dismissible overlay below. */
#files-panel {
  width: 380px; flex: none; min-height: 0; display: flex; flex-direction: column;
  background: var(--sn-sidebar); border-left: 1px solid var(--sn-border);
}
.files-head {
  display: flex; align-items: center; gap: 6px; flex: none; padding: 14px 12px;
  border-bottom: 1px solid var(--sn-border); font-size: 12px; color: var(--sn-secondary);
}
.files-body { flex: 1; min-height: 0; overflow-y: auto; padding: 16px; overscroll-behavior: contain; }
.files-sect { margin-bottom: 22px; }
.files-sect h4 { margin: 0 0 8px; font-size: 12px; font-weight: 500; color: var(--sn-secondary); }
#files-body .fname {
  flex: 1; min-width: 0; padding: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  background: none; border: 0; text-align: left; color: var(--sn-text); cursor: pointer;
  font-family: var(--sn-font-mono); font-size: 12px;
}
#files-body .fname:hover { color: var(--sn-link); text-decoration: underline; }
/* The workspace tree: a file manager's rows, not a list of paths. Folders first, one
   level of indentation per depth, and the size where a file's own row ends. */
.tree { margin: 0 -6px; }
.tree-row {
  display: flex; align-items: center; gap: 7px; min-height: 26px; padding: 3px 6px;
  border-radius: var(--sn-radius-sm); cursor: pointer; color: var(--sn-text);
}
.tree-row:hover { background: var(--sn-hover); }
.tree-row:focus-visible { outline: 2px solid var(--sn-focus); outline-offset: -2px; }
.tree-row .icon { flex: none; color: var(--sn-muted); }
.tree-row.dir .icon { color: var(--sn-secondary); }
.tree-row.dir.open > .icon { color: var(--sn-link); }
.tree-row .tname {
  flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-family: var(--sn-font-mono); font-size: 12px;
}
.tree-row.file .tname { color: var(--sn-secondary); }
.tree-row.file:hover .tname { color: var(--sn-text); }
.tree-row .tcount, .tree-row .fsize {
  flex: none; font-size: 11px; color: var(--sn-muted); font-variant-numeric: tabular-nums;
}
#files-panel .preview { margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--sn-border); }
#files-panel .preview h4 { margin: 0 0 8px; font-size: 12px; font-weight: 500; color: var(--sn-secondary); overflow-wrap: anywhere; }
#files-panel .preview pre { max-height: 360px; overflow: auto; margin: 0; }
/* The preview says what it is showing and gets out of the way when asked. */
.preview-head { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.preview-head h4 { flex: 1; min-width: 0; margin: 0; font-size: 13px; font-weight: 500;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#files-panel .preview img.art { max-width: 100%; border: 1px solid var(--sn-border-strong); border-radius: var(--sn-radius-control); }

/* Settings dialog. Rows, meters and the activity log. */
.sect { margin-bottom: 26px; }
.sect:last-child { margin-bottom: 0; }
.sect h3 { margin: 0 0 8px; font-size: 16px; font-weight: 500; }
.row-item {
  display: flex; align-items: center; gap: 10px; padding: 10px 12px; margin-bottom: 6px;
  background: var(--sn-surface); border: 1px solid var(--sn-border-strong); border-radius: var(--sn-radius-control);
}
.row-item .grow { flex: 1; min-width: 0; }
.row-item .name { font-size: 13px; overflow-wrap: anywhere; }
.row-item .sub { font-size: 12px; color: var(--sn-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Buttons that belong together, with a fact about them on the right. */
.row-actions { display: flex; align-items: center; gap: 8px; margin-top: 14px; }
.row-actions.tight { margin-top: 0; }
.row-actions .models-count { margin-left: auto; font-size: 12px; }
.sect .row-actions input[type=file] { flex: 1; min-width: 0; }

/* Two lines in a row that has no icon: name over detail, with a gap between them. */
.row-item .grow { display: flex; flex-direction: column; gap: 2px; }
.sect h3.sub-head { margin-top: 24px; }

/* A section with a title and a description on one side, its action on the other. */
.sect-head { display: flex; align-items: flex-start; gap: 16px; margin-bottom: 14px; }
.sect-head > div { flex: 1; min-width: 0; }
.sect-head h3 { margin: 0 0 4px; }
.sect-head > .btn { margin-left: auto; }
.sect-head .hint { margin: 0; }
.nav-title {
  padding: 4px 10px 10px; font-size: 12px; font-weight: 500; letter-spacing: .04em;
  text-transform: uppercase; color: var(--sn-muted);
}
/* the "Admin" heading over the administrator's tabs: the same voice as the
   "Settings" one above it, with a little air before it */
.nav-title.admin-sep { padding-top: 14px; }

/* Skills: drop a file here, or pick one. Rounded, subtle, light blue when hovered. */
.drop {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px;
  padding: 18px; margin-bottom: 22px; cursor: default;
  background: var(--sn-surface); border: 1px dashed var(--sn-border-strong);
  border-radius: var(--sn-radius-control); color: var(--sn-muted); font-size: 13px;
  transition: border-color var(--sn-duration-fast), background-color var(--sn-duration-fast);
}
.drop .icon { color: var(--sn-muted); }
.drop.over, .drop:hover { border-color: var(--sn-accent); background: var(--sn-accent-soft); }
.drop.over { color: var(--sn-text); }

/* Tables that scroll inside themselves, header and all. */
.tbl-scroll { max-height: 320px; overflow-y: auto; overscroll-behavior: contain;
  scrollbar-gutter: stable; }
.tbl-scroll thead th { position: sticky; top: 0; z-index: 1; background: var(--sn-bg); }
/* the users list: a fixed window on the accounts, grown in chunks as the
   scroller reaches its end, so a long name always renders in full */
.users-scroll { max-height: 360px; }
.tbl .name { font-size: 13px; }
/* the largest sessions: the title is cut off when it is long, and the full
   one is on the row as a tooltip. The title column takes what is left, the
   size gets a narrow fixed slice, and the eye sits at the right edge. */
.tbl .top-title { overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; font-size: 13px; }
.tbl .top-title + .when, .tbl .u-acts { white-space: nowrap; }
.tbl.top-tbl td:nth-child(2) { width: 70px; }
.tbl.top-tbl td:nth-child(3) { width: 48px; text-align: right; }
.tbl.top-tbl .u-acts .icon-btn { margin-left: auto; }
.skills-tbl td:last-child, .skills-tbl th:last-child {
  text-align: right; white-space: nowrap; overflow: visible;
}
.skills-tbl td .btn + .btn { margin-left: 6px; }
.rename-row { display: flex; align-items: center; gap: 8px; }
.rename-row input { flex: 1; min-width: 0; }
.models-scroll { margin-top: 0; height: 100%; }
/* Folders sit beside the table: a model belongs to one of them, and dragging it there
   is the whole interaction. */
.models-panes { display: grid; grid-template-columns: 200px minmax(0, 1fr); gap: 16px; margin-top: 14px; }
/* The provider tab is a pane of its own: the fields and the buttons stay put, the table
   and the folders take the space that is left and scroll inside themselves. Nothing
   moves the tab while you are dragging a model into a folder. */
.sect.fill { display: flex; flex-direction: column; height: 100%; min-height: 0; }
.sect.fill > h3, .sect.fill > .field, .sect.fill > input { flex: none; }
.sect.fill > .models-panes { flex: 1; min-height: 0; align-items: stretch; }
.sect.fill .folders { min-height: 0; overflow-y: auto; overscroll-behavior: contain;
  scrollbar-gutter: stable; }
.sect.fill .models-scroll { max-height: none; min-height: 0; }
.sect.fill .row-add.slim,
.sect.fill > .row-actions { flex: none; }
.folders { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.folders-head { font-size: 12px; color: var(--sn-muted); padding: 0 2px 2px; }
.folder {
  display: flex; align-items: center; gap: 6px; min-height: 34px; padding: 6px 4px 6px 9px;
  background: var(--sn-surface); border: 1px dashed var(--sn-border-strong);
  border-radius: var(--sn-radius-control); font-size: 13px; color: var(--sn-text);
  transition: border-color var(--sn-duration-fast), background-color var(--sn-duration-fast);
}
.folder .icon { flex: none; color: var(--sn-muted); }
.folder-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* every location node is exactly the same height, folders included: one has an icon,
   one has buttons, and an inline svg on a text baseline is what made them differ */
.folder { height: 36px; min-height: 36px; box-sizing: border-box; align-items: center; }
.folder .icon, .folder svg { display: block; }
.folder .icon-btn { flex: none; }
.folder-sep { height: 1px; margin: 6px 2px; background: var(--sn-border); }
/* a row reads its model and its settings; the editor is where they are changed */
.mrow-label { display: block; font-size: 13px; overflow: hidden; text-overflow: ellipsis; }
.mrow-model {
  display: flex; align-items: center; gap: 6px; font-size: 11px; color: var(--sn-muted);
  font-family: var(--sn-font-mono); overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap;
}
.mrow-model .mrow-prov { color: var(--sn-secondary); }
.mrow-tag {
  display: inline-flex; align-items: center; gap: 4px; margin-top: 3px; font-size: 11px;
  color: var(--sn-secondary); font-family: var(--sn-font-mono);
}
.tbl.models td.num { font-variant-numeric: tabular-nums; color: var(--sn-secondary); }
.folder-count { margin-left: auto; font-size: 12px; color: var(--sn-muted); }
.folder.over { border-color: var(--sn-accent); background: var(--sn-accent-soft); }
.folder.dim { color: var(--sn-muted); cursor: default; }
/* The location you are looking at, the way a file explorer shows one. */
.folder { cursor: pointer; }
.folder.on { border-style: solid; border-color: var(--sn-accent); background: var(--sn-accent-soft); }
.folder.editing { cursor: default; }
.folder.editing { border-style: solid; padding-left: 6px; }
.folder.editing input { flex: 1; min-width: 0; min-height: 26px; padding: 3px 7px; font-size: 13px; }
.folder-tag {
  display: inline-flex; align-items: center; gap: 4px; margin-right: 8px;
  font-size: 11px; color: var(--sn-muted);
}
tr.dragging { opacity: .45; }
tr.drop-target { outline: 2px solid var(--sn-accent); outline-offset: -2px; }
.tbl.models tr[draggable] { cursor: grab; }

/* Accounts: four quiet columns and one row to add somebody. The table is a roster,
   not a form: a role is a select, a password reset opens only for the row asked for. */
.user-new { display: flex; align-items: center; gap: 8px; margin: 0 0 12px; flex-wrap: wrap; }
.user-new input { flex: 1 1 160px; min-width: 0; }
.user-new select { width: auto; min-width: 96px; }
.tbl.users col.c-role { width: 108px; }
.tbl.users col.c-when { width: 112px; }
.tbl.users col.c-acts { width: 84px; }
.tbl.users .uname { font-size: 13px; color: var(--sn-text); }
.tbl.users .you { margin-left: 6px; font-size: 11px; color: var(--sn-muted); }
/* presence: a dot that says online now, and how many sessions the account has live */
.presence { display: inline-block; width: 8px; height: 8px; margin-right: 7px;
  border-radius: 50%; background: var(--sn-border-strong); vertical-align: 1px; }
.presence.on { background: var(--sn-success); }
.run-badge { display: inline-flex; align-items: center; gap: 3px; margin-right: 6px;
  padding: 1px 7px; border-radius: 9px; font-size: 11px; color: var(--sn-accent);
  background: var(--sn-hover); }
.tbl.users .u-acts { text-align: right; white-space: nowrap; }
.tbl.users .u-acts .icon-btn { width: 28px; height: 28px; }
/* the name reads as text and only grows chrome under the pointer, the way the
   skill renames do: it is a control, not a button */
.tbl.users .name {
  padding: 2px 6px; margin-left: -6px; background: none; border: 1px solid transparent;
  border-radius: var(--sn-radius-sm); color: var(--sn-text); font: inherit;
  font-size: 13px; text-align: left; cursor: text; max-width: 100%;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.tbl.users .name:hover { border-color: var(--sn-border-strong); background: var(--sn-hover); }
.tbl.users .name:focus-visible { border-color: var(--sn-focus); }
/* the users tab fills the modal: the list takes the height that is left and
   scrolls inside itself, so nothing spills sideways */
.users-sect { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.users-sect .user-new { flex: none; }
.users-scroll { flex: 1; min-height: 0; max-height: none; overflow-x: hidden; }
.sect-note { margin: 12px 0 0; font-size: 12px; line-height: 1.6; color: var(--sn-muted); }

/* The activity log's own bar: search for everyone, whose log and which level for an
   administrator. */
.activity-bar { display: flex; align-items: center; gap: 8px; margin: 0 0 12px; flex-wrap: nowrap; }
.activity-bar select { width: auto; flex: none; min-width: 104px; }
.activity-bar input { flex: 1 1 auto; min-width: 0; }
.tbl.activity col.c-user { width: 110px; }
.tbl.activity td.who { color: var(--sn-muted); font-size: 12px; }
@media (max-width: 760px) {
  .models-panes { grid-template-columns: minmax(0, 1fr); }
  .folders { flex-direction: row; flex-wrap: wrap; }
  .folder { min-width: 140px; }
  .folders-head { width: 100%; }
}
.models-scroll thead th { background: var(--sn-bg); }
.row-add.slim { margin-top: 10px; padding: 8px 11px; }
.empty-cell { padding: 0 !important; }
.tbl-empty .btn { width: auto; }

/* Tables. Skills, the activity log, anything that is genuinely rows and columns. */
.tbl { width: 100%; border-collapse: collapse; table-layout: fixed; }
.tbl th {
  padding: 0 10px 8px; text-align: left; font-size: 12px; font-weight: 500;
  color: var(--sn-muted); border-bottom: 1px solid var(--sn-border-strong);
}
.tbl td { padding: 10px; color: var(--sn-text); font-size: 13px; border-bottom: 1px solid var(--sn-border); vertical-align: middle; }
.tbl tbody tr:last-child td { border-bottom: 0; }
.tbl td.right, .tbl th.right { text-align: right; }
/* Long names are clipped in a cell; a cell holding buttons must never be, or the
   button reads as an ellipsis. */
.tbl th, .tbl td { overflow: hidden; text-overflow: ellipsis; }
.tbl td.right, .tbl td:last-child { overflow: visible; text-overflow: clip; }
.tbl th { white-space: nowrap; }
.tbl th.right .icon-btn { width: 26px; height: 26px; vertical-align: middle; }
.tbl td.num, .tbl th.num { text-align: right; }
.tbl input { min-height: 32px; padding: 6px 8px; font-size: 13px; }
.tbl td.num input { width: 100%; text-align: right; }
/* The activity log: fixed columns, and room for the time to be read at a glance. */
.tbl.activity col.c-when { width: 132px; }
.tbl.activity col.c-level { width: 84px; }
/* The table lists models; what each one is set to lives in its editor. */
.tbl.models col.c-label { width: 80%; }
.tbl.models col.c-act { width: 20%; }
.mrow-label { display: inline; vertical-align: middle; }
/* A pill before the name says which folder a model is in, in the full list. */
.pill {
  display: inline-flex; align-items: center; gap: 4px; margin-right: 8px;
  padding: 2px 8px; border-radius: 999px; vertical-align: middle;
  background: var(--sn-accent-soft); color: var(--sn-link); font-size: 11px;
}
.pill .icon { color: currentColor; }
.with-suffix { position: relative; display: block; }
.with-suffix input { padding-right: 26px; }
.with-suffix .suffix {
  position: absolute; right: 11px; top: 50%; transform: translateY(-50%);
  font-size: 12px; color: var(--sn-muted); pointer-events: none;
}
.tbl.skills-tbl col.c-name { width: 30%; }
.tbl.skills-tbl col.c-details { width: 28%; }
.tbl.skills-tbl col.c-when { width: 14%; }
.tbl.skills-tbl col.c-act { width: 28%; }
.tbl.skills-tbl td.when { color: var(--sn-muted); white-space: nowrap; }
/* The name is the thing you click to rename it, so it reads as text and behaves as a
   control: no button chrome until the pointer is on it. */
.sk-name {
  padding: 2px 6px; margin-left: -6px; background: none; border: 1px solid transparent;
  border-radius: var(--sn-radius-sm); color: var(--sn-text); font: inherit;
  font-size: 13px; text-align: left; cursor: text; max-width: 100%;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.sk-name:hover { border-color: var(--sn-border-strong); background: var(--sn-hover); }
.sk-name:focus-visible { border-color: var(--sn-focus); }
.tbl.activity td.when { white-space: nowrap; color: var(--sn-secondary); font-variant-numeric: tabular-nums; }
/* One line per entry: the rest is behind the ellipsis and in the tooltip, and the copy
   button hands over the whole thing. The td stays a table cell so a row that grows
   (a wrapped username in the user column) keeps every column on the same baseline;
   the flex layout lives on the inner wrapper, not on the cell. */
.tbl.activity td { vertical-align: middle; }
.tbl.activity td.msg { padding-right: 4px; }
.tbl.activity td.msg .msg-line { display: flex; align-items: center; gap: 8px; min-width: 0; }
.tbl.activity td.msg .msg-text { min-width: 0; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; }
.tbl.activity td.msg .copy { flex: none; opacity: 0; transition: opacity var(--sn-duration-fast); }
.tbl.activity tr:hover td.msg .copy,
.tbl.activity td.msg:focus-within .copy { opacity: 1; }
.tbl td:last-child { white-space: nowrap; }
.tbl .lvl { font-family: var(--sn-font-mono); font-size: 12px; color: var(--sn-secondary); }
.tbl .lvl.warn { color: var(--sn-warning); }
.tbl .lvl.error { color: var(--sn-danger); }

/* The state of having nothing yet, centered in the table that will hold it. */
.tbl-empty { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px; padding: 30px 12px; color: var(--sn-muted); font-size: 13px; text-align: center; }
.tbl td > .tbl-empty { width: 100%; }
.tbl-empty .icon { color: var(--sn-muted); }

/* A row that adds one, shaped like the rows it sits under. */
.row-add {
  width: 100%; border-style: dashed; background: transparent; color: var(--sn-secondary);
  font: inherit; text-align: left; cursor: pointer;
}
.row-add:hover { border-color: var(--sn-control-border-hover); color: var(--sn-text); background: var(--sn-hover); }
.row-add .icon { flex: none; color: var(--sn-muted); }

/* The JSON editor: a highlighted pre under a transparent textarea, so the caret and
   the selection behave natively while the syntax is coloured. */
#providers-backdrop {
  width: min(680px, calc(100vw - 32px)); height: min(560px, calc(100dvh - 32px));
  margin: auto; padding: 0;
  background: var(--sn-raised); color: var(--sn-text);
  border: 1px solid var(--sn-border-strong); border-radius: var(--sn-radius-dialog);
  box-shadow: var(--sn-shadow-dialog);
}
#providers-backdrop::backdrop { background: var(--sn-backdrop); }
#providers-modal {
  padding: 20px 20px 24px; display: flex; flex-direction: column; height: 100%;
  box-sizing: border-box;
}
#providers-modal .confirm-actions { margin-top: auto; }
#providers-modal h3 { margin: 0 0 4px; font-size: 15px; font-weight: 500; }
.prov-list { display: flex; flex-direction: column; gap: 10px; flex: 1; min-height: 0;
  overflow-y: auto; margin: 8px 0 14px; }
.prov-row {
  display: grid; grid-template-columns: minmax(0, 1fr) auto auto auto auto;
  gap: 8px; align-items: center; padding: 10px; background: var(--sn-surface);
  border: 1px solid var(--sn-border-strong); border-radius: var(--sn-radius-control);
}
.prov-row .prov-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#prov-edit-backdrop {
  width: min(460px, calc(100vw - 32px));
  margin: auto; padding: 0;
  background: var(--sn-raised); color: var(--sn-text);
  border: 1px solid var(--sn-border-strong); border-radius: var(--sn-radius-dialog);
  box-shadow: var(--sn-shadow-dialog);
}
#prov-edit-modal { padding: 20px 20px 24px; }
#prov-edit-modal h3 { margin: 0 0 4px; font-size: 15px; font-weight: 500; }
#prov-edit-modal .field-col { max-width: none; }
.prov-row input { min-height: 32px; padding: 5px 8px; font-size: 13px; }
.prov-row .key-set { font-size: 11px; color: var(--sn-muted); white-space: nowrap; }
#providers-modal .grow { flex: 1; }
#providers-modal .confirm-actions { align-items: center; }
@media (max-width: 620px) {
  .prov-row { grid-template-columns: minmax(0, 1fr); }
}

#json-backdrop {
  width: min(560px, calc(100vw - 32px));
  height: min(560px, calc(100dvh - 32px));
  margin: auto; padding: 0;
  background: var(--sn-raised); color: var(--sn-text);
  border: 1px solid var(--sn-border-strong); border-radius: var(--sn-radius-dialog);
  box-shadow: var(--sn-shadow-dialog);
}
#json-backdrop::backdrop { background: var(--sn-backdrop); }
/* Cancel and Save have to be inside the dialog with room under them, so the editor
   takes the space that is left and gives it back when the fields above it are tall. */
#json-modal { padding: 20px 20px 24px; display: flex; flex-direction: column;
  max-height: 100%; box-sizing: border-box; overflow-y: auto; }
#json-modal .json-edit { flex: 1 1 120px; min-height: 96px; }
#json-backdrop[open] { display: block; }
#json-modal h3 { margin: 0 0 4px; font-size: 15px; font-weight: 500; }
.json-sub { margin: 0 0 12px; font-size: 12px; color: var(--sn-muted); overflow-wrap: anywhere; }
.json-edit { position: relative; }
#json-view, #json-input {
  position: absolute; inset: 0; margin: 0; padding: 10px 12px; overflow: auto;
  font: 400 12.5px/1.6 var(--sn-font-mono); white-space: pre-wrap; overflow-wrap: anywhere;
  border: 1px solid var(--sn-control-border); border-radius: var(--sn-radius-control);
  background: var(--sn-input); color: var(--sn-text); tab-size: 2;
}
#json-view { pointer-events: none; }
#json-input {
  background: transparent; color: transparent; caret-color: var(--sn-text);
  resize: none; border-color: transparent;
}
#json-input:focus { outline: 2px solid var(--sn-focus); outline-offset: 1px; }
#json-input[aria-invalid="true"] { outline: 2px solid var(--sn-danger); outline-offset: 1px; }
.json-note { margin: 8px 0 0; font-size: 12px; color: var(--sn-danger); }
.json-note.hidden { display: none; }

#confirm-backdrop {
  width: min(420px, calc(100vw - 32px)); margin: auto; padding: 0;
  background: var(--sn-raised); color: var(--sn-text);
  border: 1px solid var(--sn-border-strong); border-radius: var(--sn-radius-dialog);
  box-shadow: var(--sn-shadow-dialog);
}
#confirm-backdrop::backdrop { background: var(--sn-backdrop); }
#confirm { padding: 20px 20px 16px; }
#import-box { padding: 20px 20px 16px; }
#import-box h3 { margin: 0 0 6px; font-size: 15px; font-weight: 500; }
#import-box p { margin: 0; font-size: 13px; color: var(--sn-secondary); }
#confirm h3 { margin: 0 0 6px; font-size: 15px; font-weight: 500; }
#confirm p { margin: 0; font-size: 13px; color: var(--sn-secondary); }
.confirm-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 18px; }
details.adv { margin-top: 10px; border: 1px solid var(--sn-border-strong); border-radius: var(--sn-radius-control); padding: 10px 12px; }
details.adv summary { cursor: pointer; font-size: 12px; color: var(--sn-secondary); }
details.adv summary:hover { color: var(--sn-text); }

/* Selects. The native element stays in the DOM as the value holder and the source
   of the change event, but it is never shown: the trigger and the list are ours,
   so the option list is themed on every platform. */
.sentinel-ui select.select-native {
  position: absolute; width: 1px; min-width: 0; height: 1px; min-height: 0; padding: 0;
  margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}
.select-trigger {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  width: 100%; min-width: 0; min-height: 38px; padding: 8px 9px 8px 11px; cursor: pointer;
  background: var(--sn-input); border: 1px solid var(--sn-control-border);
  border-radius: var(--sn-radius-control); color: var(--sn-text);
  font: 400 13px/1.5 var(--sn-font-ui); text-align: left;
  transition: border-color var(--sn-duration-fast), background-color var(--sn-duration-fast);
}
.select-trigger:hover { border-color: var(--sn-control-border-hover); }
.select-trigger[aria-expanded="true"] { border-color: var(--sn-control-border-hover); }
.select-trigger:focus-visible { outline: 2px solid var(--sn-focus); outline-offset: 1px; }
.select-trigger:disabled { cursor: not-allowed; }
.select-value { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  display: flex; align-items: center; }
/* The folder pill, at the size a picker row needs rather than the size the table uses. */
.select-value .pill, .select-option .pill {
  margin-right: 7px; padding: 0 7px; font-size: 10px; line-height: 17px; flex: none;
}
/* A name that does not fit wraps onto a second line by whole words, and one that still
   does not fit is cut off with an ellipsis. text-wrap: pretty is what keeps a single
   word or character from being left alone on the last line. */
.select-option .select-label {
  margin-right: 8px; min-width: 0; line-height: 1.35;
  white-space: normal; overflow-wrap: break-word; text-wrap: pretty;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden;
}
.select-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.select-chevron { display: inline-flex; flex: none; color: var(--sn-muted); }
.select-trigger[aria-expanded="true"] .select-chevron { color: var(--sn-link); }
#select-panel {
  position: fixed; z-index: calc(var(--sn-z-menu) + 3); min-width: 220px;
  display: flex; flex-direction: column;
  max-width: min(420px, calc(100vw - 24px)); padding: 6px;
  background: var(--sn-raised); color: var(--sn-text); border: 1px solid var(--sn-border-strong);
  border-radius: var(--sn-radius-menu); box-shadow: var(--sn-shadow-panel);
}
.select-search { padding: 2px 2px 6px; }
.select-search input { min-height: 34px; padding: 7px 10px; font-size: 13px; }
.select-scroll { flex: 1 1 auto; min-height: 0; max-height: min(320px, 48dvh);
  overflow-y: auto; overscroll-behavior: contain; scrollbar-gutter: stable; }
.select-option {
  display: flex; align-items: center; gap: 0; min-height: 34px; padding: 7px 9px;
  border-radius: var(--sn-radius-sm); color: var(--sn-text); font-size: 13px; cursor: pointer;
}
.select-option[hidden] { display: none; }
.select-label { min-width: 0; overflow-wrap: anywhere; }
.select-check { display: inline-flex; flex: none; width: 16px; min-width: 16px;
  margin-left: auto; color: var(--sn-link); }
.select-option[data-active="true"] { background: var(--sn-hover); }
.select-option[aria-selected="true"] { background: var(--sn-accent-soft); }
.select-option[aria-selected="true"][data-active="true"] { background: var(--sn-hover); }
.select-option[aria-disabled="true"] { color: var(--sn-muted); cursor: not-allowed; background: transparent; }
/* A folder in the model picker: a header you can open, with its models inside. */
.select-group {
  display: flex; align-items: center; gap: 7px; padding: 7px 9px; cursor: pointer;
  font-size: 12px; color: var(--sn-secondary); font-weight: 500;
}
.select-group .icon { flex: none; color: var(--sn-muted); transition: transform var(--sn-duration-fast); }
.select-group-block.open > .select-group .icon { transform: rotate(90deg); }
.select-group .count { margin-left: auto; color: var(--sn-muted); font-weight: 400; }
.select-group:hover { color: var(--sn-text); }
.select-group-block > .select-option { display: none; }
.select-group-block.open > .select-option { display: flex; }
.select-empty { padding: 14px 10px; font-size: 12px; color: var(--sn-secondary); }

/* Overlays. Menus, the tooltip, the dialog and the toasts all sit on the raised
   surface with the same border, shadow, font and scrollbar as the page. */
#popover, #popover2 {
  position: fixed; z-index: var(--sn-z-menu); min-width: 200px; max-width: min(360px, calc(100vw - 24px));
  max-height: min(70vh, 520px); overflow-y: auto; overscroll-behavior: contain; padding: 6px;
  background: var(--sn-raised); color: var(--sn-text); border: 1px solid var(--sn-border-strong);
  border-radius: var(--sn-radius-menu); box-shadow: var(--sn-shadow-panel);
}
#popover2 { z-index: calc(var(--sn-z-menu) + 2); }
.pop-title { padding: 7px 9px 4px; font-size: 12px; color: var(--sn-muted); }
.pop-item {
  display: flex; align-items: center; gap: 8px; width: 100%; padding: 7px 9px;
  border: 0; border-radius: var(--sn-radius-sm); background: transparent; color: var(--sn-text);
  font: inherit; font-size: 13px; text-align: left; text-decoration: none; cursor: pointer;
  transition: background-color var(--sn-duration-fast), color var(--sn-duration-fast);
}
.pop-item > .icon { flex: none; }
.pop-item:hover { background: var(--sn-hover); }
.pop-item.danger { color: var(--sn-danger); }
.pop-item.danger .icon { color: var(--sn-danger); }
.pop-item .icon { color: var(--sn-secondary); }
.pop-item.dim { color: var(--sn-muted); cursor: default; }
.pop-item[aria-disabled="true"], .pop-item:disabled { cursor: not-allowed; }
.pop-item.dim:hover { background: transparent; }
.pop-sep { height: 1px; margin: 5px 3px; background: var(--sn-border); }
.pop-field { padding: 4px 9px 8px; }
.pop-field > span { display: block; margin-bottom: 5px; font-size: 12px; color: var(--sn-secondary); }
.pop-field input, .pop-field select { min-height: 34px; padding: 7px 10px; font-size: 13px; }
/* The label color picker. Ours end to end: presets, a live swatch, a hex field
   and three sliders, so no OS color dialog is involved. */
.picker { display: grid; gap: 5px; margin-top: 9px; }
.picker-head { display: flex; align-items: center; gap: 8px; }
.picker-preview { width: 26px; height: 26px; flex: none; border-radius: 50%; border: 1px solid var(--sn-border-strong); }
.picker-hex {
  flex: 1; min-width: 0; min-height: 30px; padding: 5px 9px; font-family: var(--sn-font-mono);
  font-size: 12px; text-transform: uppercase;
}
.picker-row {
  display: grid; grid-template-columns: 64px minmax(0, 1fr); align-items: center; gap: 8px;
  font-size: 12px; color: var(--sn-secondary);
}
.picker-label { display: inline-flex; align-items: center; gap: 4px; }
.picker-warn { display: inline-flex; color: var(--sn-warning); }
.picker-warn .icon { width: 13px; height: 13px; }
.picker-note { margin: 2px 0 0; font-size: 12px; color: var(--sn-status, var(--sn-secondary)); }
.picker-note[data-status="warning"] { --sn-status: var(--sn-warning); }
.picker-note[data-status="error"] { --sn-status: var(--sn-danger); }
.sentinel-ui input[type="range"].sn-range {
  appearance: none; -webkit-appearance: none; width: 100%; height: 22px;
  padding: 0; margin: 0; border: 0; background: transparent;
}
.sentinel-ui input[type="range"].sn-range:focus { box-shadow: none; }
.sentinel-ui input[type="range"].sn-range::-webkit-slider-runnable-track {
  height: 4px; border-radius: 2px;
  background: linear-gradient(to right, var(--sn-accent) 0 var(--sn-range-fill, 0%),
              var(--sn-control-border) var(--sn-range-fill, 0%) 100%);
}
.sentinel-ui input[type="range"].sn-range::-webkit-slider-thumb {
  -webkit-appearance: none; width: 15px; height: 15px; margin-top: -6px;
  border: 1px solid var(--sn-link); border-radius: 50%; background: var(--sn-accent);
}
.sentinel-ui input[type="range"].sn-range::-moz-range-track {
  height: 4px; border-radius: 2px; background: var(--sn-control-border);
}
.sentinel-ui input[type="range"].sn-range::-moz-range-progress {
  height: 4px; border-radius: 2px; background: var(--sn-accent);
}
.sentinel-ui input[type="range"].sn-range::-moz-range-thumb {
  width: 15px; height: 15px; border: 1px solid var(--sn-link); border-radius: 50%;
  background: var(--sn-accent);
}
.sentinel-ui input[type="range"].hue::-webkit-slider-runnable-track {
  background: linear-gradient(to right, #ff0000 0%, #ffff00 17%, #00ff00 33%,
              #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);
}
.sentinel-ui input[type="range"].hue::-moz-range-track {
  background: linear-gradient(to right, #ff0000 0%, #ffff00 17%, #00ff00 33%,
              #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);
}
.sentinel-ui input[type="range"].hue::-moz-range-progress { background: transparent; }
.swatches { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; padding: 4px 9px 8px; }
.swatch { width: 20px; height: 20px; padding: 0; border-radius: 50%; border: 2px solid transparent; cursor: pointer; }
.swatch.on { border-color: var(--sn-text); }

#tooltip {
  position: fixed; z-index: 110; display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 9px; border-radius: 6px; white-space: nowrap;
  max-width: calc(100vw - 24px);
  background: var(--sn-raised); color: var(--sn-text); border: 1px solid var(--sn-border-strong);
  box-shadow: var(--sn-shadow-panel); font: 400 12px/1.5 var(--sn-font-ui); pointer-events: none;
}
#tooltip .icon { flex: none; color: var(--sn-secondary); }
#tooltip.wrap { display: block; white-space: normal; max-width: min(320px, calc(100vw - 24px)); }

/* Settings is a fixed size window and a small page of its own: the canvas tone for
   the window, the sidebar tone for its navigation, the surface tone for the cards.
   Menus, tooltips and toasts still use the raised tone, so they read as floating
   above the window rather than being part of it. */
#modal-backdrop {
  width: min(920px, calc(100vw - 32px)); max-width: none;
  height: min(620px, calc(100dvh - 32px)); max-height: none;
  margin: auto; padding: 0; background: var(--sn-bg); color: var(--sn-text);
  border: 1px solid var(--sn-border-strong); border-radius: var(--sn-radius-dialog);
  box-shadow: var(--sn-shadow-dialog);
}
#modal-backdrop[open] { display: flex; flex-direction: column; }
#modal-backdrop::backdrop { background: var(--sn-backdrop); }
#modal { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
.modal-main {
  flex: 1; min-height: 0; display: grid;
  grid-template-columns: 208px minmax(0, 1fr);
}
#modal-tabs {
  display: flex; flex-direction: column; gap: 2px; min-width: 0; min-height: 0;
  padding: 12px 10px; overflow-y: auto; overscroll-behavior: contain;
  background: var(--sn-sidebar); border-right: 1px solid var(--sn-border);
}
#modal-tabs button {
  display: flex; align-items: center; gap: 10px; width: 100%; min-height: 36px; padding: 8px 10px;
  background: transparent; border: 1px solid transparent; border-radius: var(--sn-radius-control);
  color: var(--sn-secondary); font-size: 13px; text-align: left; cursor: pointer;
}
#modal-tabs button .icon { flex: none; color: var(--sn-muted); }
#modal-tabs button:hover { background: var(--sn-hover); color: var(--sn-text); }
#modal-tabs button:hover .icon { color: var(--sn-secondary); }
#modal-tabs button[aria-selected="true"] {
  background: var(--sn-accent-soft); color: var(--sn-text); font-weight: 500;
}
#modal-tabs button[aria-selected="true"] .icon { color: var(--sn-link); }
#modal-body { min-height: 0; overflow-y: auto; padding: 22px 24px 26px; overscroll-behavior: contain; }
/* Back, pinned to the bottom of the sidebar: the dialog has no header bar, so leaving it
   needs somewhere obvious to press. */
#modal-tabs .nav-back {
  display: flex; align-items: center; gap: 10px; width: 100%; min-height: 36px;
  margin-top: auto; padding: 8px 10px; background: transparent; border: 1px solid transparent;
  border-radius: var(--sn-radius-control); color: var(--sn-secondary); font: inherit;
  font-size: 13px; text-align: left; cursor: pointer;
}
#modal-tabs .nav-back:hover { background: var(--sn-hover); color: var(--sn-text); }
#modal-tabs .nav-back .icon { flex: none; color: var(--sn-muted); }

#nav-backdrop, #files-backdrop {
  position: fixed; inset: 0; z-index: var(--sn-z-drawer); background: var(--sn-backdrop);
}
#nav-backdrop { display: none; }
#search-bar {
  position: fixed; z-index: var(--sn-z-toast); top: calc(16px + env(safe-area-inset-top));
  right: calc(16px + env(safe-area-inset-right));
  display: flex; align-items: center; gap: 4px; width: min(340px, calc(100vw - 32px));
  padding: 6px 8px; background: var(--sn-raised); color: var(--sn-text);
  border: 1px solid var(--sn-border-strong); border-radius: var(--sn-radius-panel);
  box-shadow: var(--sn-shadow-dialog);
}
#search-bar.hidden { display: none; }
#search-bar input {
  flex: 1; min-width: 0; background: transparent; border: 0; color: var(--sn-text);
  font: 400 13px/1.5 var(--sn-font-ui); padding: 4px 2px; outline: none;
}
#search-bar input::placeholder { color: var(--sn-muted); }
#search-bar input::-webkit-search-cancel-button { display: none; }
#search-bar .icon-btn { width: 26px; height: 26px; }
/* A toast and the search bar share the top right corner: the toast drops below the bar
   while the bar is open, so both stay readable. */
body:has(#search-bar:not(.hidden)) #toast { top: calc(72px + env(safe-area-inset-top)); }

#toast {
  position: fixed; z-index: var(--sn-z-toast); top: calc(16px + env(safe-area-inset-top));
  right: calc(16px + env(safe-area-inset-right));
  display: flex; align-items: flex-start; gap: 10px;
  max-width: min(400px, calc(100vw - 32px)); padding: 12px;
  background: var(--sn-raised); color: var(--sn-text);
  border: 1px solid var(--sn-border-strong); border-radius: var(--sn-radius-panel);
  box-shadow: var(--sn-shadow-dialog); font: 400 13px/1.5 var(--sn-font-ui);
  opacity: 0; transform: translateX(12px);
  transition: opacity var(--sn-duration-overlay) var(--sn-ease),
              transform var(--sn-duration-overlay) var(--sn-ease);
}
#toast.show { opacity: 1; transform: none; }
#toast #toast-icon {
  display: inline-flex; align-items: center; justify-content: center; flex: none;
  width: 24px; height: 24px; border-radius: 999px;
  background: var(--sn-accent-soft); color: var(--sn-link);
}
#toast.bad #toast-icon {
  background: color-mix(in srgb, var(--sn-danger) 16%, transparent); color: var(--sn-danger);
}
#toast #toast-msg { flex: 1; min-width: 0; padding-top: 2px; overflow-wrap: anywhere; }
#toast #toast-close {
  display: inline-flex; align-items: center; justify-content: center; flex: none;
  width: 28px; height: 28px; min-width: 28px; min-height: 28px; margin: -2px -4px 0 0;
  padding: 0; color: var(--sn-secondary);
}
#toast #toast-close:hover { background: var(--sn-hover); color: var(--sn-text); }

/* Responsive. Tighten first, then move the sidebar behind a labeled control. */
@media (max-width: 1100px) {
  #files-panel {
    position: fixed; top: 0; right: 0; height: 100%; width: min(420px, calc(100vw - 32px));
    z-index: var(--sn-z-drawer); box-shadow: var(--sn-shadow-dialog);
  }
  #files-backdrop { z-index: calc(var(--sn-z-drawer) - 1); }
}
@media (min-width: 1101px) {
  #files-backdrop { display: none !important; }
}
@media (max-width: 900px) {
  .sentinel-ui { --sn-sidebar-width: 190px; }
}
@media (max-width: 760px) {
  .modal-main { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto minmax(0, 1fr); }
  #modal-tabs {
    flex-direction: row; gap: 6px; padding: 10px 12px; overflow-x: auto; overflow-y: hidden;
    border-right: 0; border-bottom: 1px solid var(--sn-border);
  }
  #modal-tabs button { width: auto; flex: none; min-height: 34px; padding: 7px 11px; }
  #modal-tabs button .icon { display: none; }
  /* the navigation is a strip here, so Back sits at its end and the title has served
     its purpose */
  #modal-tabs .nav-title { display: none; }
  #modal-tabs .nav-back {
    width: 34px; min-height: 34px; flex: none; margin: 0 0 0 auto; padding: 0;
    justify-content: center;
  }
  #modal-tabs .nav-back span { display: none; }

  /* Fixed columns are right for a window and wrong for a phone: below this width each
     row stacks, so nothing is clipped and no input is 60px wide. */
  .tbl, .tbl.models, .tbl.activity, .tbl.skills-tbl { table-layout: auto; }
  .tbl colgroup, .tbl thead { display: none; }
  .tbl.models thead { display: block; }
  .tbl.models thead tr { display: flex; justify-content: flex-end; padding: 0 0 6px; }
  .tbl.models thead th { display: none; }
  .tbl.models thead th.right { display: block; padding: 0; border: 0; }
  .tbl tbody, .tbl tr, .tbl td { display: block; width: auto; }
  .tbl tr {
    padding: 10px 0; border-bottom: 1px solid var(--sn-border);
  }
  .tbl tbody tr:last-child { border-bottom: 0; }
  .tbl td {
    padding: 2px 0; border: 0; text-align: left !important;
    overflow: visible; text-overflow: clip; white-space: normal;
  }
  .tbl td:last-child { white-space: normal; }
  .tbl td > input { width: 100%; }
  .tbl td.num > input { text-align: left; }
  .tbl td .tbl-empty { padding: 20px 8px; }
  .tbl.activity td.when { white-space: nowrap; }
  /* a log line is a sentence: stacked on a phone it wraps rather than widening the
     table past the screen */
  .tbl.activity td, .tbl.activity .msg-line, .tbl.activity .msg-text {
    white-space: normal; overflow-wrap: anywhere; max-width: 100%; }
  .skills-tbl td:last-child { text-align: left; }
  .models-scroll, .tbl-scroll { max-height: none; }
}
@media (max-width: 850px) {
  .head-bar { padding: 0 16px; }
  .transcript { padding: 20px 16px 8px; }
  #composer { padding: 10px 16px 16px; }
  .grid2 { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 620px) {
  #app { grid-template-columns: minmax(0, 1fr); }
  #sidebar {
    position: fixed; top: 0; left: 0; bottom: 0; z-index: calc(var(--sn-z-drawer) + 1);
    width: min(84vw, 288px); transform: translateX(-100%);
    transition: transform var(--sn-duration-overlay) var(--sn-ease);
  }
  #app.nav-open #sidebar { transform: none; box-shadow: var(--sn-shadow-dialog); }
  #app.nav-open #nav-backdrop { display: block; }
  #nav-toggle { display: inline-flex; }
  .head-bar { min-height: 56px; padding: 0 12px; gap: 8px; }
  .transcript { padding: 16px 20px 8px; }
  #composer { padding: 10px 20px 16px; }
  .new-hero h1 { font-size: 27px; }
  .new-sub { font-size: 14px; }
  #auth-form .auth-title { font-size: 27px; }
  #auth-form .auth-sub { font-size: 14px; }
  #toast {
    left: calc(12px + env(safe-area-inset-left));
    right: calc(12px + env(safe-area-inset-right));
    max-width: none; top: calc(12px + env(safe-area-inset-top));
  }
  .new-bar .send-btn, .composer-bar .send-btn { width: 100%; }
  .new-bar select, .composer-bar select { max-width: none; flex: 1 1 132px; }
  .new-box textarea { padding: 16px; }
  #modal-backdrop { width: calc(100vw - 16px); height: calc(100dvh - 16px); }
  #modal-body { padding: 14px 14px 18px; }
  .card-msg { padding: 14px; }
}
@media (pointer: coarse) {
  .sentinel-ui :where(.btn, .icon-btn, .send-btn, .new-btn, .pop-item, .si-open, input, select,
    .select-trigger, .select-option, #modal-tabs button) { min-height: 44px; }
  .sentinel-ui .icon-btn { min-width: 44px; }
  .sentinel-ui :where(input, textarea, select) { font-size: 16px; }
  .sentinel-ui .new-box textarea, .sentinel-ui .composer-inner textarea { font-size: 16px; min-height: 96px; }
  .sentinel-ui .session-item { min-height: 44px; padding-right: 48px; }
  .sentinel-ui .si-more { right: 2px; top: 50%; transform: translateY(-50%);
    width: 44px; height: 44px; align-items: center; justify-content: center; opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .sentinel-ui *, .sentinel-ui *::before, .sentinel-ui *::after {
    animation-duration: .01ms !important; animation-iteration-count: 1 !important;
    transition-duration: .01ms !important; scroll-behavior: auto !important;
  }
}
@media (forced-colors: active) {
  .sentinel-ui {
    --sn-focus: Highlight; --sn-border: CanvasText; --sn-border-strong: CanvasText;
    --sn-control-border: ButtonText; --sn-text: CanvasText; --sn-secondary: CanvasText;
    --sn-muted: CanvasText; --sn-surface: Canvas; --sn-input: Canvas; --sn-bg: Canvas;
    --sn-raised: Canvas; --sn-sidebar: Canvas; --sn-hover: Canvas; --sn-accent: Highlight;
    --sn-on-accent: Canvas; --sn-link: LinkText; --sn-success: CanvasText; --sn-warning: CanvasText;
    --sn-danger: CanvasText; --sn-scroll-thumb: CanvasText;
  }
  .sentinel-ui input[type="checkbox"], .sentinel-ui input[type="radio"],
  .sentinel-ui input[role="switch"] { appearance: auto; -webkit-appearance: auto; forced-color-adjust: auto; }
  .sentinel-ui input[type="checkbox"]::before, .sentinel-ui input[type="radio"]::before,
  .sentinel-ui input[role="switch"]::before { content: none; }
  .sentinel-ui :where(.btn, .new-btn, .send-btn, input, select, textarea, .select-trigger) { border: 1px solid ButtonText; }
  .sentinel-ui .select-option[aria-selected="true"] { outline: 1px solid Highlight; }
  .sentinel-ui .session-item.active { outline: 1px solid Highlight; }
}

/* The user session viewer: an administrator reading a regular user's sessions
   without touching them. Two panes, like the settings dialog, but read-only. */
#user-view {
  width: min(1080px, calc(100vw - 32px)); max-width: none;
  height: min(720px, calc(100dvh - 32px)); max-height: none;
  margin: auto; padding: 0; background: var(--sn-bg); color: var(--sn-text);
  border: 1px solid var(--sn-border-strong); border-radius: var(--sn-radius-dialog);
  box-shadow: var(--sn-shadow-dialog);
}
#user-view[open] { display: flex; flex-direction: column; }
#user-view::backdrop { background: var(--sn-backdrop); }
#uv-head {
  display: flex; align-items: center; gap: 10px; flex: none;
  padding: 12px 16px; border-bottom: 1px solid var(--sn-border);
  font-weight: 500;
}
#uv-head .grow { flex: 1; min-width: 0; }
#uv-title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#uv-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; }
.uv-list { display: flex; flex-direction: column; gap: 8px; padding: 16px; }
.uv-row {
  display: flex; align-items: center; gap: 10px; padding: 10px 12px;
  border: 1px solid var(--sn-border); border-radius: var(--sn-radius-control);
  background: var(--sn-raised); cursor: pointer; text-align: left; font: inherit;
  color: inherit; width: 100%;
}
.uv-row:hover { background: var(--sn-hover); }
.uv-row .uv-title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.uv-row .dim { color: var(--sn-muted); font-size: 12px; flex: none; }
.uv-transcript { padding: 16px; display: flex; flex-direction: column; gap: 10px; }
.uv-empty { padding: 32px 16px; text-align: center; color: var(--sn-muted); }
.uv-note {
  margin: 0 16px; padding: 8px 12px; font-size: 12px; color: var(--sn-muted);
  border: 1px solid var(--sn-border); border-radius: var(--sn-radius-control);
  background: var(--sn-raised);
}

/* The generated password dialog. The value starts blurred so a shoulder read
   sees nothing; the eye unblurs it, the copy button takes it away. */
#pw-backdrop {
  width: min(460px, calc(100vw - 32px));
  margin: auto; padding: 0; background: var(--sn-bg); color: var(--sn-text);
  border: 1px solid var(--sn-border-strong); border-radius: var(--sn-radius-dialog);
  box-shadow: var(--sn-shadow-dialog);
}
#pw-backdrop::backdrop { background: var(--sn-backdrop); }
#pw-modal { padding: 22px 24px 20px; }
#pw-row { display: flex; align-items: center; gap: 8px; margin: 14px 0 4px; }
#pw-value {
  flex: 1; min-width: 0; font-family: var(--sn-font-mono, monospace); font-size: 14px;
  padding: 9px 12px; border: 1px solid var(--sn-border); border-radius: var(--sn-radius-control);
  background: var(--sn-input); overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
#pw-value.blurred { filter: blur(5px); user-select: none; }

/* Profile and statistics tabs. */
.field-col { display: flex; flex-direction: column; gap: 6px; max-width: 380px; }
.field-col .field { margin: 6px 0 0; }
.field-col .btn { align-self: flex-start; margin-top: 8px; }
.totp-secret code {
  display: block; padding: 9px 12px; font-family: var(--sn-font-mono, monospace);
  font-size: 14px; letter-spacing: 1px; background: var(--sn-input);
  border: 1px solid var(--sn-border); border-radius: var(--sn-radius-control);
  overflow-wrap: break-word; user-select: all;
}
.quota-line { display: flex; justify-content: space-between; font-size: 13px; margin-bottom: 5px; }
.quota-bar {
  height: 9px; border-radius: 5px; background: var(--sn-hover);
  border: 1px solid var(--sn-border); overflow: hidden; width: 100%;
}
.quota-fill { height: 100%; background: var(--sn-accent); transition: width .3s var(--sn-ease); }
.quota-fill.full { background: var(--sn-danger); }
.stat-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(130px, 1fr)); gap: 10px; }
/* My Stats: a plain bar chart for the tokens per day, and a share bar per
   model. No library, just divs with a height and a width. */
.mychart { display: flex; align-items: flex-end; gap: 4px; height: 120px;
  padding: 8px 4px 0; border-bottom: 1px solid var(--sn-border); }
.mybar { flex: 1; height: 100%; display: flex; align-items: flex-end; min-width: 0; }
.mybar-fill { width: 100%; background: var(--sn-accent); border-radius: 3px 3px 0 0;
  min-height: 2px; transition: height .3s var(--sn-ease); }
.mybar:hover .mybar-fill { background: var(--sn-accent-soft); }
.mymodel { max-width: 420px; margin-bottom: 10px; }
.mymodel-head { display: flex; justify-content: space-between; font-size: 13px;
  margin-bottom: 4px; }
.mymodel-head span:last-child { color: var(--sn-secondary); }
.mymodel-bar { height: 6px; border-radius: 3px; background: var(--sn-hover); overflow: hidden; }
.mymodel-fill { height: 100%; background: var(--sn-accent); border-radius: 3px; }
.stat-card {
  display: flex; flex-direction: column; gap: 3px; padding: 12px;
  background: var(--sn-raised); border: 1px solid var(--sn-border);
  border-radius: var(--sn-radius-control);
}
.stat-value { font-size: 19px; font-weight: 500; }
.stat-label { font-size: 12px; color: var(--sn-muted); }

/* Subtle per-item download buttons in the workspace explorer: they appear with
   the row hover, so the tree stays quiet until the mouse is on it. */
.tree-row .tdl {
  min-height: 22px; min-width: 22px; padding: 2px; flex: none;
  opacity: 0; color: var(--sn-muted);
}
.tree-row:hover .tdl, .tree-row .tdl:focus-visible { opacity: 1; }
.tree-row .tdl:hover { color: var(--sn-text); }
.tree-row .fsize { flex: none; }
