/* LobsterMane admin — v7.
   viktor.com's design system, measured off viktor.com's live CSS rather than
   eyeballed: the #faf5f1 parchment canvas, white cards on a 5% hairline, ink
   #1a182b for text and primary buttons, pill controls, a display face with
   -0.035em tracking, lavender-style eyebrow chips, glass rings around previews,
   and Viktor's indigo -> accent -> peach gradient surfaces for hero moments.
   The deliberate divergence is still hue: LobsterMane orange takes the role of
   Viktor's violet, while Viktor's deep indigo (#150079) stays as the dark
   anchor of every gradient. Status colour is reserved for status. */

:root {
  /* Viktor sets UI text in Gellix and display type in UlmGrotesk; both are
     commercially licensed, so we ship the closest freely licensed matches —
     Figtree for Gellix, Outfit (weight 500, which matches UlmGrotesk's cut) for
     UlmGrotesk. If the real families are ever licensed, these two vars are the
     only edit needed. */
  --font: Figtree, -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif;
  --font-display: Outfit, Figtree, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --mono: 'SF Mono', 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
  color-scheme: light;

  /* Viktor primitives (viktor.com --primitive-*). */
  --lm-beige: #faf5f1;
  --lm-beige-light: #fcfaf9;
  --lm-ink: #1a182b;
  --lm-indigo: #150079;
  --lm-plum: #7a1d6e;
  --lm-peach: #ffbb98;
  --lm-grey-dark: #716f7e;
  --lm-grey: #9693a3;
  --lm-grey-lighter: #d3cfe5;

  /* LobsterMane orange, stepped the way Viktor steps its violet. */
  --lm-orange-50: #fff4ee;
  --lm-orange-200: #ffcbb0;
  --lm-orange-300: #ffa477;
  --lm-orange-400: #ff8450;
  --lm-orange-500: #ff6523;
  --lm-orange-600: #eb5413;
  --lm-orange-700: #c2410c;

  /* Parchment canvas, white cards floating on it. */
  --bg: var(--lm-beige);
  --surface: #ffffff;
  --surface-2: #f5f0eb;
  --surface-3: #ece6e0;
  --surface-muted: var(--lm-beige-light);
  --input-bg: #ffffff;

  /* Hairlines are the ink at low alpha — never a neutral gray. Viktor's own
     values: 8% for dividers, 10% for control outlines, 5% black for cards. */
  --border: rgba(26, 24, 43, 0.08);
  --border-strong: rgba(26, 24, 43, 0.14);
  --border-control: rgba(26, 24, 43, 0.1);
  --border-card: rgba(0, 0, 0, 0.05);

  --text: var(--lm-ink);
  --text-secondary: #42424a;
  --text-muted: var(--lm-grey-dark);
  --text-faint: var(--lm-grey);
  /* Small text on the sidebar's sand (--surface-2): --text-faint is only
     2.65:1 there, --text-muted 4.34:1; this reads at 4.73:1. */
  --text-faint-on-sand: #6b6978;

  --accent: var(--lm-orange-500);
  --accent-hover: var(--lm-orange-600);
  --accent-text: var(--lm-orange-700);
  --accent-soft: rgba(255, 101, 35, 0.1);
  --accent-tint: var(--lm-orange-50);
  /* Eyebrows sit on the parchment, so they need a step more tint than the
     white-surface wash to read as a chip (Viktor's lavender on beige). */
  --eyebrow-bg: #ffe5d7;
  --eyebrow-text: #b0390a;
  --accent-line: rgba(255, 101, 35, 0.28);
  --accent-ring: rgba(255, 101, 35, 0.22);
  /* The one focus ring: a solid darker-orange edge (--accent-hover is 3.2:1
     on the sand, 3.3 on the canvas, 3.6 on white; the halo alone was 1.3:1)
     with the soft --accent-ring halo around it. Fields draw it as this
     shadow (plus an accent border); everything else as --focus-outline,
     offset from the edge, with the halo as a shadow. */
  --focus-ring: 0 0 0 1px var(--accent-hover), 0 0 0 4px var(--accent-ring);
  --focus-outline: 2px solid var(--accent-hover);

  /* Viktor's primary button is ink, not the accent. */
  --ink-btn: var(--lm-ink);
  --ink-btn-hover: #2d2a45;
  /* Text and icons on ink, accent and danger fills. */
  --text-inverse: #ffffff;

  --ok: #54c423;
  --ok-text: #146f2e;
  --ok-soft: #f2fbee;
  --ok-line: #dcefd9;
  --warn: #d97706;
  --warn-text: #b45309;
  --warn-soft: #fdf6e9;
  --warn-line: rgba(217, 119, 6, 0.24);
  --danger: #c42323;
  --danger-text: #c42323;
  --danger-soft: #fef1f0;
  --danger-line: rgba(196, 35, 35, 0.24);

  --hover: rgba(26, 24, 43, 0.04);
  --active: rgba(26, 24, 43, 0.07);
  /* Every disabled control (button, segment, switch, icon button) fades the same. */
  --disabled-opacity: 0.45;

  /* Viktor's geometry (base radius .875rem): anything you click is a pill,
     cards are 26px, hero surfaces 36px, and only chips/code stay squared off. */
  --radius-pill: 999px;
  --radius-2xl: 26px;
  --radius-lg: 22px;
  --radius-xl: 20px;
  --radius: 14px;
  --radius-md: 12px;
  --radius-sm: 10px;
  --radius-xs: 8px;

  /* One control height: buttons, fields, selects and the segmented track
     share a row at 36px; compact controls are 30px, hero CTAs 48px. */
  --control-h: 36px;
  --control-h-sm: 30px;
  --control-h-lg: 48px;

  /* Elevation is a whisper — Viktor's cards sit on a hairline with no blur;
     only overlays and floating tiles get a real shadow. */
  --shadow-card: 0 1px 2px rgba(26, 24, 43, 0.04);
  --shadow-tile: 0 8px 16px rgba(26, 24, 41, 0.06), inset 1.8px 1.8px 3.6px #f5f1ed;
  --shadow-float: 0 12px 32px -8px rgba(26, 24, 43, 0.16), 0 2px 6px rgba(26, 24, 43, 0.05);
  --shadow-raised: 0 20px 48px rgba(26, 24, 43, 0.14);
  --shadow-modal: 0 40px 80px -24px rgba(26, 24, 41, 0.35), 0 20px 48px rgba(26, 24, 43, 0.1);

  /* Viktor's gradient system, re-hued: indigo anchor -> plum -> orange -> peach. */
  --grad-cta: radial-gradient(46.77% 100% at 50% 0%, var(--lm-orange-500) 0%, var(--lm-ink) 100%);
  --grad-cta-inset: inset 0 4px 4px 0 rgba(255, 255, 255, 0.25);
  --grad-text: linear-gradient(180deg, #ff8450 0%, var(--lm-orange-500) 55%, #e2480f 100%);
  --grad-mark: linear-gradient(
    160deg,
    #ffa477 0%,
    var(--lm-orange-500) 45%,
    #d23c10 78%,
    var(--lm-plum) 100%
  );
  --grad-glow: radial-gradient(
    60% 55% at 50% 100%,
    rgba(255, 132, 80, 0.2) 0%,
    rgba(122, 29, 110, 0.08) 45%,
    rgba(250, 245, 241, 0) 75%
  );
  --tile-bg: linear-gradient(135deg, #f9f5f1 19.75%, #fffefc 100.45%);
  /* A person without a photo: the same letter avatar everywhere. */
  --grad-avatar: linear-gradient(135deg, var(--lm-peach), var(--lm-plum));

  /* Motion: Viktor enters content 8-16px up over ~0.6s on an ease-out curve. */
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --enter-y: 10px;

  /* The persona mark's eyes are cut-outs: they take the colour of whatever
     the mark sits on, so each surface retints this. */
  --persona-eye: var(--surface);
}

* {
  box-sizing: border-box;
}

[hidden] {
  display: none !important;
}

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

/* Viktor's ramp: 14px/1.4 for UI text, 16px/1.5 for prose, 400 for body and
   500 for anything that carries emphasis. 600 does not exist in their system. */
body {
  color: var(--text);
  font-family: var(--font);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  background: var(--bg);
  font-size: 14px;
}

#root {
  height: 100%;
}

a {
  color: var(--text-secondary);
  text-decoration: none;
}
a:hover {
  color: var(--text);
  text-decoration: underline;
  text-underline-offset: 2px;
}

code {
  font-family: var(--mono);
  font-size: 11.5px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 1px 5px;
}

.mono {
  font-family: var(--mono);
  font-size: 11.5px;
}
/* Keys, URLs and commands typed into a form: mono at a readable size. */
:is(.manual-integration, .secret-modal) :is(input, textarea).mono {
  font-size: 13px;
}

::selection {
  background: var(--accent-ring);
}

*::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}
*::-webkit-scrollbar-thumb {
  border-radius: 4px;
  border: 2px solid transparent;
  background-clip: content-box;
  background-color: rgba(26, 24, 43, 0.16);
}
*::-webkit-scrollbar-thumb:hover {
  background-color: rgba(26, 24, 43, 0.26);
  background-clip: content-box;
}
*::-webkit-scrollbar-track {
  background: transparent;
}

button,
input,
textarea,
select {
  font: inherit;
}

/* Keyboard focus is the one ring (--focus-ring) everywhere. :where() keeps
   the catch-all for focusable rows and tiles below any component's own rule. */
button:focus-visible,
a:focus-visible,
input:focus-visible,
textarea:focus-visible,
select:focus-visible,
summary:focus-visible,
:where([tabindex]:not([tabindex='-1']), [role='button']):focus-visible {
  outline: var(--focus-outline);
  outline-offset: 2px;
  box-shadow: 0 0 0 5px var(--accent-ring);
}

/* One line, cut with an ellipsis. */
.org-switch-name,
.org-switch-product,
.account-row-name,
.side-menu-clip,
.side-menu-title,
.side-menu-sub,
.conv-item-title,
.composer-approval-head strong,
.conv-item-meta,
.chat-code-panel-title,
.chat-code-panel-path,
.chat-code-panel-reason,
.chat-head-title,
.chat-head-sub,
.vm-stat-label,
.vm-locked-name,
.vm-locked-why,
.vm-state-text,
.shot-name,
.vm-task-title,
.shot-detail,
.art-foot .shot-meta,
.md-code-label,
.chat-working-text,
.chat-queue-text,
.chat-composer-hint,
.chat-stash-entry-copy,
.chat-context-detail-head span,
.cc-head-word,
.cc-head-meta,
.cc-changed-file > span:nth-child(2),
.cc-ctx-item-name,
.cc-ctx-item-detail,
.cc-task-fleet-meta,
.cc-tool-arg,
.cc-result-text,
.ig-name,
.ig-label,
:is(.integration-row, .vault-row) .ig-name-line > :is(.ig-key, .ig-label, .role-lock, .ig-flag),
.ig-desc,
.ig-settings-how code,
.tk-title h3,
.attach-name,
.attach-note,
.screen-title,
.bot-integration-name,
.bot-roster-name,
.bot-roster-preview,
.phone-call-row-goal,
.team-member-name-text,
.team-member-email,
.link-popover-head,
.link-option-detail,
.role-option-name,
.role-option-detail,
.pool-id,
.save-bar-text,
.agent-request-outcome,
.cron-row-title,
.cron-run-summary,
.rt-row-link,
.rt-meta,
.rt-row-error,
.rt-crumb-trail a,
.rt-run-time,
.rt-run-num,
.rt-run-outcome,
.role-chip-name,
.repo-picker-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ============ App shell ============ */

.app-shell {
  position: relative;
  display: flex;
  height: 100vh;
  overflow: hidden;
  background: var(--bg);
}

/* The sidebar is one column attached to the window's edge (the user didn't
   want a floating island): a sand tone a step darker than the canvas, a
   hairline edge, full height. The org switcher sits on top, the nav in the
   middle, the account row pinned to the bottom. */
.sidebar {
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  width: 248px;
  padding: 10px 10px 10px;
  border-right: 1px solid var(--border);
  background: var(--surface-2);
  transition: width 0.18s var(--ease-out);
}

.sidebar-top {
  display: flex;
  align-items: center;
  gap: 4px;
  padding-bottom: 10px;
}

/* The org switcher: LM mark, the org, "LobsterMane" (and Staging) under it. */
.org-switch {
  display: flex;
  flex: 1;
  align-items: center;
  gap: 10px;
  min-width: 0;
  padding: 7px 8px;
  border: 0;
  border-radius: var(--radius-md);
  background: transparent;
  color: var(--text);
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: background 0.14s ease;
}
.org-switch:hover,
.account-row:hover {
  background: var(--hover);
}
/* The control whose menu is open keeps its wash, so the menu has an owner. */
.org-switch[aria-expanded='true'],
.account-row[aria-expanded='true'] {
  background: var(--hover);
}
.org-switch .brand-mark {
  width: 30px;
  height: 30px;
  border-radius: 9px;
}
.org-switch-text,
.account-row-text {
  display: flex;
  flex: 1;
  flex-direction: column;
  min-width: 0;
}
.org-switch-name {
  font-family: var(--font-display);
  font-size: 15px;
  font-weight: 500;
  letter-spacing: -0.02em;
  line-height: 1.25;
}
.org-switch-sub {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
  margin-top: 1px;
  overflow: hidden;
  color: var(--text-faint-on-sand);
  font-size: 11.5px;
  line-height: 1.3;
}
.org-switch-product {
  min-width: 0;
}
.org-switch-sub .env-chip {
  height: 17px;
  padding: 0 7px 0 6px;
  font-size: 10.5px;
}
.org-switch-chevrons {
  display: inline-flex;
  flex: none;
  color: var(--text-muted);
}
.org-switch-chevrons .icon {
  width: 14px;
  height: 14px;
}
.sidebar-collapse {
  display: inline-flex;
  flex: none;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border: 0;
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--text-muted);
  cursor: pointer;
}
.sidebar-collapse:hover {
  background: var(--hover);
  color: var(--text);
}

/* The account row: avatar, name, access; opens the account menu. */
.account-row {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 8px;
  border: 0;
  border-radius: var(--radius-md);
  background: transparent;
  color: var(--text);
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: background 0.14s ease;
}
.account-row-name {
  font-size: 13.5px;
  font-weight: 500;
}
.account-row-sub {
  color: var(--text-faint-on-sand);
  font-size: 11.5px;
}

/* The org and account menus (showSideMenu), narrower than a plain .popover. */
.popover.side-popover {
  width: min(264px, calc(100vw - 16px));
  padding: 6px;
}
.side-menu-clip {
  min-width: 0;
}
.side-menu-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 8px 10px;
}
.side-menu-head .brand-mark {
  width: 34px;
  height: 34px;
  border-radius: 10px;
}
.side-menu-head-text {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
}
.side-menu-title {
  color: var(--text);
  font-size: 13.5px;
  font-weight: 500;
}
/* The org menu's header: the one place the whole org name reads. */
.side-menu-title-wrap {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-height: 1.3;
  white-space: normal;
  overflow-wrap: anywhere;
}
.side-menu-sub {
  display: flex;
  align-items: center;
  gap: 6px;
  color: var(--text-faint);
  font-size: 12px;
}
.side-menu-sub.is-wrap {
  display: block;
  line-height: 1.35;
  white-space: normal;
}
.side-menu-access {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  margin: 0 2px 4px;
  padding: 8px 10px;
  border-radius: var(--radius-md);
  background: var(--surface-2);
  color: var(--text-secondary);
  font-size: 12px;
  line-height: 1.4;
  text-decoration: none;
}
.side-menu-access:hover,
.side-menu-access:focus-visible {
  background: var(--surface-3);
  color: var(--text);
}
/* Highlight-only keyboard focus, like the rows under it. */
.side-menu-access:focus-visible {
  outline: none;
  box-shadow: none;
}
/* Link rows (the access line, Switch organization…) wash like the button
   rows; they never pick up the global link underline. */
.side-menu-item:hover,
.side-menu-item:focus-visible,
.side-menu-access:hover,
.side-menu-access:focus-visible {
  text-decoration: none;
}
.side-menu-access .icon {
  width: 13px;
  height: 13px;
  margin-top: 1px;
  color: var(--accent-text);
}
.side-menu-sep {
  height: 1px;
  margin: 6px 4px;
  background: var(--border);
}
/* Rows read like the context menu's (.ctx-item): same radius, wash and
   highlight-only keyboard focus. */
.side-menu-item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  height: 34px;
  padding: 0 10px;
  border: 0;
  border-radius: var(--radius-md);
  background: transparent;
  color: var(--text);
  font: inherit;
  font-size: 13.5px;
  text-align: left;
  text-decoration: none;
  cursor: pointer;
}
.side-menu-item:hover {
  background: var(--hover);
}
/* Keyboard focus is a firmer wash than hover, so it reads on white. */
.side-menu-item:focus-visible {
  background: var(--active);
  outline: none;
  box-shadow: none;
}
.side-menu-item .icon {
  width: 15px;
  height: 15px;
  color: var(--text-muted);
}
.side-menu-note {
  padding: 8px 10px;
  color: var(--text-faint);
  font-size: 12.5px;
}

/* Viktor's app mark: a glossy gradient tile with a lit top edge and a soft
   drop, like a physical key. */
.brand-mark {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 32px;
  height: 32px;
  border-radius: 10px;
  background: var(--grad-mark);
  color: #fff;
  box-shadow:
    inset 0 1.5px 1px rgba(255, 255, 255, 0.45),
    inset 0 -2px 3px rgba(21, 0, 121, 0.25),
    0 4px 10px -2px rgba(194, 65, 12, 0.35);
}

.brand-mark span {
  font-family: var(--font-display);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: -0.04em;
  text-shadow: 0 1px 1px rgba(21, 0, 121, 0.25);
}

/* Environment chip: calm amber, its own row position, never touching the name. */
.env-chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  flex: none;
  height: 19px;
  padding: 0 8px 0 7px;
  border-radius: var(--radius-pill);
  background: #fff1d6;
  color: #8a5300;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.01em;
}

.env-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: #f59e0b;
  box-shadow: 0 0 0 2px rgba(245, 158, 11, 0.22);
}

/* Collapsed sidebar: the brand text is hidden, so a small text label says it. */
.env-mini {
  display: none;
  align-items: center;
  height: 15px;
  padding: 0 5px;
  border-radius: var(--radius-pill);
  background: #fff1d6;
  color: #8a5300;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.06em;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* The mark carries the environment too. */
.org-switch.is-staging .brand-mark::after {
  content: '';
  position: absolute;
  top: -3px;
  right: -3px;
  width: 11px;
  height: 11px;
  border-radius: 50%;
  background: #f59e0b;
  box-shadow: 0 0 0 2.5px var(--surface);
}

.sidebar-nav {
  flex: 1;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  gap: 2px;
  /* Room for a row's focus ring, which the scroller would otherwise clip;
     the rows stay where they were. */
  margin: -5px;
  padding: 5px;
}
/* More past an edge: the rows there fade out instead of being cut at the
   header or the footer's hairline (paintNavOverflow). */
.sidebar-nav.is-overflowing {
  -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 28px), transparent);
  mask-image: linear-gradient(to bottom, #000 calc(100% - 28px), transparent);
}
.sidebar-nav.is-scrolled {
  -webkit-mask-image: linear-gradient(to bottom, transparent, #000 20px);
  mask-image: linear-gradient(to bottom, transparent, #000 20px);
}
.sidebar-nav.is-scrolled.is-overflowing {
  -webkit-mask-image: linear-gradient(
    to bottom,
    transparent,
    #000 20px,
    #000 calc(100% - 28px),
    transparent
  );
  mask-image: linear-gradient(
    to bottom,
    transparent,
    #000 20px,
    #000 calc(100% - 28px),
    transparent
  );
}

.nav-group-label {
  user-select: none;
  padding: 16px 12px 6px;
  color: var(--text-faint-on-sand);
  font-size: 12px;
  font-weight: 500;
}
.sidebar-nav > .nav-group-label:first-child {
  padding-top: 4px;
}

/* Nav rows are pills, matching the pill tabs in viktor.com's own header. */
.nav-item {
  display: flex;
  align-items: center;
  width: 100%;
  height: 34px;
  flex: none;
  gap: 11px;
  padding: 0 12px;
  border: 0;
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--text-muted);
  font-family: inherit;
  font-size: 13.5px;
  font-weight: 500;
  letter-spacing: -0.005em;
  cursor: pointer;
  text-align: left;
  transition:
    background 0.14s ease,
    color 0.14s ease;
}

.nav-item:hover {
  background: var(--hover);
  color: var(--text);
}

/* The page you're on: a white tile on the sand column, ink text, orange icon. */
.nav-item.active {
  background: var(--surface);
  color: var(--text);
  box-shadow:
    0 1px 2px rgba(26, 24, 43, 0.06),
    inset 0 0 0 1px rgba(26, 24, 43, 0.05);
}

.nav-item .icon {
  color: inherit;
  opacity: 0.85;
}

.nav-item.active .icon {
  color: var(--accent);
  opacity: 1;
}

.icon {
  width: 16px;
  height: 16px;
  display: inline-flex;
  flex-shrink: 0;
}
.icon svg {
  width: 100%;
  height: 100%;
}

.sidebar-footer {
  padding-top: 8px;
  border-top: 1px solid var(--border);
}

.sidebar-avatar {
  flex: none;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  object-fit: cover;
}
.sidebar-avatar.is-lg {
  width: 36px;
  height: 36px;
}
.sidebar-avatar-letter {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--grad-avatar);
  color: #fff;
  font-size: 12.5px;
  font-weight: 500;
}

.content-wrap {
  position: relative;
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
  background: transparent;
  isolation: isolate;
}

/* Viktor warms the bottom of its canvas with a peach-to-plum glow; the app
   keeps a faint version of it behind the content column. */
.content-wrap::before {
  content: '';
  position: absolute;
  inset: auto 0 0 0;
  height: 46vh;
  background: var(--grad-glow);
  pointer-events: none;
  z-index: -1;
}

/* Viktor's page header: display face, heavy negative tracking, muted sub. */
.topbar {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  flex-shrink: 0;
  padding: 34px 40px 10px;
}

.topbar-copy {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
  min-width: 0;
}

/* Viktor's section eyebrow: a 12px/500 pill on the accent's lightest step. */
.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 22px;
  padding: 0 10px;
  border-radius: var(--radius-pill);
  background: var(--eyebrow-bg);
  color: var(--eyebrow-text);
  font-size: 12px;
  font-weight: 500;
  line-height: 1;
  white-space: nowrap;
}

.topbar-eyebrow {
  margin-bottom: 4px;
}

/* Display type is Viktor's: weight 500, -0.035em, 1.1 leading. */
.topbar-title {
  margin: 0;
  font-family: var(--font-display);
  font-size: 38px;
  font-weight: 500;
  letter-spacing: -0.035em;
  line-height: 1.1;
  white-space: nowrap;
}

/* Wraps rather than truncating: on a phone the whole sentence still reads. */
.topbar-sub {
  margin: 0;
  max-width: 1080px;
  color: var(--text-muted);
  font-size: 15px;
  text-wrap: pretty;
}

/* Chat page: compact header so the conversation keeps the vertical space,
   its title in line with the chat card's edge (the pane's 14px inset). */
.content-wrap:has(.content-chat) .topbar {
  padding: 16px 14px 12px;
  align-items: center;
}
.content-wrap:has(.content-chat) .topbar-eyebrow {
  display: none;
}
.content-wrap:has(.content-chat) .topbar-title {
  font-size: 24px;
  letter-spacing: -0.03em;
}
.content-wrap:has(.content-chat) .topbar-sub {
  font-size: 13px;
}

/* A subpage (a bot's settings, one of its routines): its card has the title
   and the way back, so the list's header only stays for screen readers. */
.content-wrap.is-subpage .topbar {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
.content-wrap.is-subpage .content {
  padding-top: 34px;
}

/* Once the pane scrolls, a hairline under the page header, so content passes
   under an edge instead of being sliced off (as in a scrolled modal body). */
.content-wrap > .topbar {
  transition: box-shadow 0.14s ease;
}
/* (Not on a subpage, whose header is only there for screen readers.) */
.content-wrap:not(.is-subpage):has(> .content.is-scrolled) > .topbar {
  position: relative;
  z-index: 1;
  box-shadow: 0 1px 0 var(--border);
}

.content {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 20px;
  min-height: 0;
  padding: 22px 40px 80px;
  overflow-y: auto;
  overflow-x: hidden;
}

/* Left-aligned column under the big page title, like the reference app. */
.content > * {
  flex: 0 0 auto;
  width: 100%;
  max-width: 1080px;
  margin-inline: 0;
  min-width: 0;
}

.content.content-chat {
  /* The chat card keeps its distance from the sidebar and the window edges. */
  padding: 0 14px 14px;
  gap: 0;
  overflow: hidden;
}

.content.content-chat > * {
  flex: 1 1 auto;
  max-width: none;
  min-height: 0;
}

/* A chat pane that didn't load (a chat, Bots or a bot's settings) shows the
   page-state card at its own height, like every other page, not stretched
   over the whole pane. */
.content.content-chat > .page-state {
  flex: 0 0 auto;
  margin-top: 14px;
}
@media (max-width: 900px) {
  /* The chat card goes edge to edge here; the page-state card keeps the
     title's inset. */
  .content.content-chat > .page-state {
    width: auto;
    margin: 4px 20px 0;
  }
}
@media (max-width: 600px) {
  .content.content-chat > .page-state {
    margin: 4px 10px 0;
  }
}

/* The pane takes focus from the skip link; it needs no ring of its own. */
.content:focus {
  outline: none;
}

/* Generic loading state: a page's pane stays empty while it fetches, so
   after a beat it says so, shimmering like other in-flight labels. */
.content:empty::before {
  content: 'Loading…';
  align-self: flex-start;
  margin: 4px 2px;
  background-image: linear-gradient(
    90deg,
    var(--text-faint) 35%,
    var(--text-secondary) 50%,
    var(--text-faint) 65%
  );
  background-size: 200% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  font-size: 13px;
  animation:
    fade-up 0.4s var(--ease-out) 0.3s both,
    shimmer-text 1.4s linear infinite;
}

/* In a chat pane, in line with the compact title. */
.content.content-chat:empty::before {
  margin: 4px 0;
}

/* Other pages: in a card's frame where the page's first card will be, like
   its empty and error states; the word pulses (a clipped-text shimmer can't
   share the card's background). */
.content:not(.content-chat):empty::before {
  display: flex;
  align-items: center;
  justify-content: center;
  align-self: stretch;
  box-sizing: border-box;
  width: 100%;
  max-width: 1080px;
  min-height: 160px;
  margin: 0;
  border: 1px solid var(--border-card);
  border-radius: var(--radius-2xl);
  background: var(--surface);
  -webkit-background-clip: border-box;
  background-clip: border-box;
  box-shadow: var(--shadow-card);
  color: var(--text-muted);
  font-size: 13.5px;
  animation:
    fade-up 0.4s var(--ease-out) 0.3s both,
    loading-pulse 1.4s ease-in-out 0.7s infinite;
}
@keyframes loading-pulse {
  50% {
    color: var(--text-faint);
  }
}

@media (prefers-reduced-motion: reduce) {
  .content:empty::before,
  .content:not(.content-chat):empty::before {
    background-image: none;
    color: var(--text-muted);
    animation: none;
  }
}

/* ============ Buttons / badges / forms ============ */

/* Viktor's buttons (measured): full pills, 14px/500 at -0.01em. Secondary
   is white on a 10% ink hairline; primary is solid ink. The accent only
   appears on the CTA variant's gradient. Heights follow --control-h.
   Hover rules skip disabled buttons through :where(), which adds no
   specificity, so page rules still win exactly as before. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  height: var(--control-h);
  padding: 0 18px;
  border: 1px solid var(--border-control);
  border-radius: var(--radius-pill);
  background: var(--surface);
  color: var(--text);
  font-family: inherit;
  font-size: 14px;
  font-weight: 500;
  letter-spacing: -0.01em;
  cursor: pointer;
  white-space: nowrap;
  transition:
    background 0.14s ease,
    border-color 0.14s ease,
    color 0.14s ease,
    box-shadow 0.14s ease,
    transform 0.14s ease;
}

.btn:hover:where(:not(:disabled)) {
  background: var(--surface-muted);
  border-color: var(--border-strong);
  color: var(--text);
}

.btn:active:not(:disabled) {
  transform: translateY(0.5px);
}

.btn:disabled {
  cursor: not-allowed;
  opacity: var(--disabled-opacity);
}
/* Disabled only while its request runs ("Signing in…"): it keeps its colour
   and says so, rather than greying out like a dead control. */
.btn[aria-busy='true']:disabled {
  opacity: 1;
  cursor: progress;
}

/* Busy while its request runs: it keeps focus (unlike :disabled) but looks
   and acts off. */
.btn[aria-disabled='true'] {
  opacity: var(--disabled-opacity);
  pointer-events: none;
}

.btn-primary {
  border-color: var(--ink-btn);
  background: var(--ink-btn);
  color: var(--text-inverse);
}
.btn-primary:hover:where(:not(:disabled)) {
  background: var(--ink-btn-hover);
  border-color: var(--ink-btn-hover);
  color: var(--text-inverse);
}

/* Viktor's hero CTA: accent glowing down into ink, lit from the top edge. */
.btn-cta {
  border: 0;
  background: var(--grad-cta);
  box-shadow: var(--grad-cta-inset);
  color: var(--text-inverse);
}
.btn-cta:hover:where(:not(:disabled)) {
  border: 0;
  background: var(--grad-cta);
  box-shadow:
    var(--grad-cta-inset),
    0 6px 18px -6px color-mix(in srgb, var(--accent) 55%, transparent);
  color: var(--text-inverse);
}
/* Off reads as off: a plain faded ink pill, like .btn-primary:disabled, not
   a half-lit gradient. */
.btn-cta:disabled {
  background: var(--ink-btn);
  box-shadow: none;
}

.btn-danger {
  border-color: transparent;
  background: transparent;
  color: var(--danger-text);
}
.btn-primary.btn-danger {
  border-color: var(--danger);
  background: var(--danger);
  color: var(--text-inverse);
}
.btn-danger:hover:where(:not(:disabled)) {
  border-color: var(--danger-line);
  background: var(--danger-soft);
  color: var(--danger-text);
}
/* A solid danger button darkens on hover, like primary; it never fades to
   the quiet variant's tint. */
.btn-primary.btn-danger:hover:where(:not(:disabled)) {
  border-color: color-mix(in srgb, var(--danger) 86%, var(--lm-ink));
  background: color-mix(in srgb, var(--danger) 86%, var(--lm-ink));
  color: var(--text-inverse);
}

.btn-ghost,
.btn-quiet {
  color: var(--text-muted);
  border-color: transparent;
  background: transparent;
}
.btn-ghost:hover:where(:not(:disabled)),
.btn-quiet:hover:where(:not(:disabled)) {
  background: var(--hover);
  border-color: transparent;
  color: var(--text);
}

.btn-sm {
  height: var(--control-h-sm);
  padding: 0 14px;
  font-size: 13px;
}

/* Focused like a field: accent edge inside the ring. */
.btn:focus-visible {
  border-color: var(--accent);
}

/* Viktor's chips: pill, 12px/500, 2px 8px, on a flat warm tint with no border. */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  height: 22px;
  padding: 0 9px;
  border: 1px solid transparent;
  border-radius: var(--radius-pill);
  background: var(--surface-2);
  color: var(--text-secondary);
  font-size: 12px;
  font-weight: 500;
  white-space: nowrap;
}

.badge-accent {
  background: var(--accent-tint);
  color: var(--accent-text);
}

.badge-success {
  border-color: var(--ok-line);
  background: var(--ok-soft);
  color: var(--ok-text);
}

.badge-warning {
  border-color: var(--warn-line);
  background: var(--warn-soft);
  color: var(--warn-text);
}

.badge-danger {
  border-color: var(--danger-line);
  background: var(--danger-soft);
  color: var(--danger-text);
}

.badge-neutral {
  color: var(--text-muted);
}

/* Fields share the buttons' height (--control-h) so a field, a select and a
   button line up in one row. */
input,
textarea,
select {
  width: 100%;
  min-height: var(--control-h);
  padding: 6px 14px;
  border: 1px solid var(--border-control);
  border-radius: var(--radius-md);
  background: var(--input-bg);
  color: var(--text);
  font-family: inherit;
  font-size: 14px;
  outline: none;
  transition:
    border-color 0.12s ease,
    box-shadow 0.12s ease;
}

input:hover:not(:focus):not(:disabled),
textarea:hover:not(:focus):not(:disabled),
select:hover:not(:focus):not(:disabled) {
  border-color: var(--border-strong);
}

/* Compact control inside running text (e.g. a card subtitle). The right
   padding keeps the text clear of the arrow. */
select.input-inline {
  display: inline-block;
  width: auto;
  max-width: 280px;
  min-height: 0;
  padding: 2px 28px 2px 10px;
  margin: 0 2px;
  background-position: right 10px center;
  font-size: 13px;
}

input::placeholder,
textarea::placeholder {
  color: var(--text-faint);
}

/* A search field's clear button: the app's own muted ×, not the browser's blue one. */
input[type='search']::-webkit-search-cancel-button {
  -webkit-appearance: none;
  appearance: none;
  width: 14px;
  height: 14px;
  margin-left: 6px;
  background: var(--text-muted);
  cursor: pointer;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M4 4l8 8M12 4l-8 8' stroke='black' stroke-width='1.6' stroke-linecap='round'/%3E%3C/svg%3E")
    center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M4 4l8 8M12 4l-8 8' stroke='black' stroke-width='1.6' stroke-linecap='round'/%3E%3C/svg%3E")
    center / contain no-repeat;
}
input[type='search']::-webkit-search-cancel-button:hover {
  background: var(--text);
}

input:focus,
textarea:focus,
select:focus {
  border-color: var(--accent);
  box-shadow: var(--focus-ring);
  outline: none;
}

/* :where() keeps these states below page rules (a composer, a filter). */
:where(input, textarea, select):disabled {
  background-color: var(--surface-muted);
  color: var(--text-muted);
  cursor: not-allowed;
}

/* Search fields are toolbar controls, so they are pills like the buttons and
   segmented controls beside them. :where() leaves page rules in charge. */
input:where([type='search']) {
  border-radius: var(--radius-pill);
  padding-inline: 16px;
}

/* Checkboxes and radios are 16px native controls in ink (like a switch that
   is on), never stretched to a field's width. Their ring is keyboard-only. */
input:where([type='checkbox'], [type='radio']) {
  flex: none;
  width: 16px;
  height: 16px;
  min-height: 0;
  margin: 0;
  padding: 0;
  border-radius: calc(var(--radius-xs) / 2);
  accent-color: var(--ink-btn);
  cursor: pointer;
}
/* Radios are drawn (appearance: none) so the keyboard ring follows the
   circle: a native radio paints any shadow or outline as a square. */
input:where([type='radio']) {
  -webkit-appearance: none;
  appearance: none;
  display: inline-grid;
  place-content: center;
  border: 1.5px solid var(--border-strong);
  border-radius: 50%;
  background: var(--surface);
}
input:where([type='radio'])::before {
  content: '';
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--ink-btn);
  transform: scale(0);
  transition: transform 0.12s ease;
}
input:where([type='radio']):focus {
  border-color: var(--border-strong);
}
input:where([type='radio']):checked,
input:where([type='radio']):checked:focus,
input:where([type='radio']):checked:hover:not(:focus):not(:disabled) {
  border-color: var(--ink-btn);
}
input:where([type='radio']):checked::before {
  transform: scale(1);
}
input:where([type='radio']):disabled {
  opacity: 0.55;
}
input:where([type='checkbox'], [type='radio']):focus {
  box-shadow: none;
}
input:where([type='checkbox'], [type='radio']):focus-visible {
  box-shadow: var(--focus-ring);
  outline: none;
}
input:where([type='checkbox'], [type='radio']):disabled {
  cursor: not-allowed;
}

textarea {
  line-height: 1.5;
  resize: vertical;
  padding: 10px 14px;
  border-radius: var(--radius);
}

select {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%23716f7e' fill='none' stroke-width='1.5' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 13px center;
  padding: 0 32px 0 14px;
}

.field {
  margin-bottom: 14px;
}

.field-label {
  display: block;
  margin-bottom: 6px;
  color: var(--text-secondary);
  font-size: 13px;
  font-weight: 500;
}
.field-optional {
  color: var(--text-faint);
  font-weight: 400;
}

/* Muted, like every other line of helper copy (card and modal subtitles,
   row subs): faint grey is too light to read at 12px. */
.field-hint {
  margin-top: 6px;
  color: var(--text-muted);
  font-size: 12px;
}

/* ============ Cards / rows ============ */

/* Viktor's cards: white, 26px radius, a 5% hairline and no blur. */
.card {
  border: 1px solid var(--border-card);
  border-radius: var(--radius-2xl);
  background: var(--surface);
  box-shadow: var(--shadow-card);
  overflow: hidden;
}

.card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  padding: 24px 28px 22px;
}

.card-header-text {
  min-width: 0;
}

.card-header-text h2 {
  margin: 0;
  font-family: var(--font-display);
  font-size: 21px;
  font-weight: 500;
  letter-spacing: -0.03em;
  line-height: 1.2;
}

.card-header-text p {
  margin: 5px 0 0;
  max-width: 660px;
  color: var(--text-muted);
  font-size: 14px;
  line-height: 1.45;
}

.card-body {
  border-top: 1px solid var(--border);
  min-width: 0;
}

.card-empty {
  text-align: center;
  font-size: 14px;
  border-top: 1px solid var(--border);
  padding: 44px 28px;
  color: var(--text-muted);
  background:
    radial-gradient(
      50% 90% at 50% 100%,
      color-mix(in srgb, var(--lm-peach) 14%, transparent) 0%,
      transparent 70%
    ),
    var(--surface);
}

.card-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  padding: 16px 28px;
  border-top: 1px solid var(--border);
}

.row {
  display: grid;
  align-items: center;
  gap: 12px;
  min-height: 60px;
  padding: 12px 28px;
  border-bottom: 1px solid var(--border);
  transition: background 0.1s ease;
}
.row:hover {
  background: var(--surface-muted);
}
.row:last-child {
  border-bottom: none;
}

/* Badges are labels, not fields — never stretch them to the grid track. */
.row > .badge {
  justify-self: start;
}

.row-name {
  font-size: 14px;
  color: var(--text);
  font-weight: 500;
  letter-spacing: -0.005em;
}

.row-sub {
  margin-top: 2px;
  color: var(--text-muted);
  font-size: 12.5px;
}

.section-toolbar {
  display: flex;
  align-items: center;
  gap: 6px;
  justify-content: flex-end;
}

.table-head {
  display: grid;
  align-items: center;
  gap: 12px;
  min-height: 38px;
  padding: 0 28px;
  border-bottom: 1px solid var(--border);
  background: var(--surface-muted);
  color: var(--text-faint);
  font-size: 11px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

/* Model pool and Secrets rows end in a switch and icon actions (house style);
   their head cells over those stay empty, as on Cron jobs and Team. */
.table-head-pool,
.row-pool {
  grid-template-columns: minmax(200px, 1fr) 110px 100px 38px 52px;
  column-gap: 20px;
}
.pool-actions {
  display: flex;
  gap: 4px;
}

/* Toggle: label.toggle > input[type=checkbox] + span.toggle-slider. The
   input stays focusable but draws nothing; the slider shows its state, its
   hover and the focus ring. */

.toggle {
  position: relative;
  display: inline-block;
  flex-shrink: 0;
  width: 38px;
  height: 22px;
}
.toggle input {
  position: absolute;
  opacity: 0;
  width: 0;
  height: 0;
}
.toggle-slider {
  position: absolute;
  inset: 0;
  border-radius: var(--radius-pill);
  border: 1px solid var(--border-strong);
  background: var(--surface-3);
  transition:
    background 0.15s ease,
    border-color 0.15s ease;
  cursor: pointer;
}
.toggle-slider::before {
  content: '';
  position: absolute;
  left: 2px;
  top: 2px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--surface);
  box-shadow: 0 1px 3px color-mix(in srgb, var(--lm-ink) 20%, transparent);
  transition: transform 0.2s var(--ease-out);
}
.toggle:hover input:not(:checked):not(:disabled) + .toggle-slider {
  border-color: var(--text-faint);
}
/* On is ink, like Viktor's primary controls; orange stays an accent. */
.toggle input:checked + .toggle-slider {
  border-color: transparent;
  background: var(--ink-btn);
}
.toggle:hover input:checked:not(:disabled) + .toggle-slider {
  background: var(--ink-btn-hover);
}
.toggle input:checked + .toggle-slider::before {
  transform: translateX(16px);
}
.toggle input:focus-visible + .toggle-slider {
  outline: var(--focus-outline);
  outline-offset: 2px;
  box-shadow: 0 0 0 5px var(--accent-ring);
}
.toggle input:disabled + .toggle-slider {
  opacity: var(--disabled-opacity);
  cursor: not-allowed;
}
/* Saving: focus stays on the switch, which takes no input until it's done. */
.toggle input[aria-disabled='true'] + .toggle-slider {
  opacity: var(--disabled-opacity);
  cursor: progress;
}

/* Alerts */

.alert {
  border: 1px solid var(--border-card);
  border-radius: var(--radius-lg);
  padding: 13px 18px;
  background: var(--surface);
  color: var(--text-secondary);
  font-size: 13.5px;
}
.alert-error {
  border-color: var(--danger-line);
  background: var(--danger-soft);
  color: var(--danger-text);
}
.alert-success {
  border-color: var(--ok-line);
  background: var(--ok-soft);
  color: var(--ok-text);
}
.alert-warning {
  border-color: var(--warn-line);
  background: var(--warn-soft);
  color: var(--warn-text);
}
/* A note, not a field: a quiet tint with no outline, so it never reads as an
   empty input on a white card or the canvas. */
.alert-info {
  border-color: transparent;
  background: var(--surface-2);
  color: var(--text-secondary);
}
/* On the canvas, a note keeps to a reading width. */
.content > .alert-info {
  max-width: 80ch;
}

/* A page whose data changed while someone was working on it (see
   showPageChangedBar): an ink pill floating over the top of the page, so
   nothing under it moves, with Refresh. */
.page-changed {
  position: absolute;
  top: 12px;
  left: 50%;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: 10px;
  width: max-content;
  max-width: calc(100% - 24px);
  padding: 5px 5px 5px 14px;
  border-radius: var(--radius-pill);
  background: var(--ink-btn);
  box-shadow: var(--shadow-float);
  color: var(--text-inverse);
  font-size: 13px;
  font-weight: 500;
  line-height: 1.35;
  transform: translateX(-50%);
  animation: page-changed-in 0.28s var(--ease-out) both;
}
.page-changed > .icon {
  width: 14px;
  height: 14px;
  opacity: 0.8;
}
.page-changed .btn {
  flex: none;
}
.page-changed-short {
  display: none;
}
/* Phones: the short copy on one line, docked at the bottom like a toast
   (above an open chat's composer: --changed-bottom), clear of the page's
   title and a chat's header. */
@media (max-width: 600px) {
  .page-changed {
    top: auto;
    bottom: var(--changed-bottom, 16px);
    white-space: nowrap;
    animation-name: page-changed-up;
  }
  .page-changed-long {
    display: none;
  }
  .page-changed-short {
    display: inline;
  }
}
@keyframes page-changed-in {
  from {
    opacity: 0;
    transform: translate(-50%, -6px);
  }
}
@keyframes page-changed-up {
  from {
    opacity: 0;
    transform: translate(-50%, 6px);
  }
}

/* Modal */

.modal {
  position: fixed;
  inset: 0;
  display: flex;
  justify-content: center;
  align-items: flex-start;
  z-index: 50;
  overflow-y: auto;
  padding: 8vh 18px;
  background: rgba(26, 24, 43, 0.3);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}

/* Viktor frames anything floating in a translucent white ring (the glass
   border around its product shots). */
.modal-content {
  width: min(480px, 100%);
  padding: 28px;
  border: 0;
  border-radius: var(--radius-2xl);
  background: var(--surface);
  box-shadow:
    0 0 0 8px rgba(255, 255, 255, 0.5),
    var(--shadow-modal);
  animation: lm-modal-in 0.32s var(--ease-out) both;
}

@keyframes lm-modal-in {
  from {
    opacity: 0;
    transform: translateY(var(--enter-y)) scale(0.985);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

.modal-content h2 {
  margin: 0;
  font-size: 23px;
  font-family: var(--font-display);
  font-weight: 500;
  letter-spacing: -0.03em;
  line-height: 1.2;
}

.modal-sub {
  font-size: 14px;
  color: var(--text-muted);
  margin: 6px 0 20px;
}

.modal-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 20px;
  padding-top: 18px;
  border-top: 1px solid var(--border);
}

/* Dialogs (openModal, confirmDialog, promptDialog in app.js): the modal card
   above, split into a head (title, subtitle, close button), a body that
   scrolls when tall, an inline error, and actions that stay in view. Three
   widths: small for questions, default for forms, wide for two-column forms. */
.modal-dialog {
  display: flex;
  flex-direction: column;
  max-height: 84vh;
  max-height: calc(100dvh - 16vh);
  padding: 0;
  overflow: hidden;
}
.modal-dialog.modal-sm {
  width: min(400px, 100%);
}
.modal-dialog.modal-wide {
  width: min(640px, 100%);
  max-width: none;
}
.modal-dialog:focus {
  outline: none;
}
.modal-head {
  display: flex;
  flex: none;
  align-items: flex-start;
  gap: 12px;
  padding: 28px 28px 0;
}
.modal-head-text {
  flex: 1;
  min-width: 0;
  overflow-wrap: anywhere;
}
.modal-head .modal-sub {
  margin: 6px 0 0;
  line-height: 1.45;
}
.modal-sub code {
  font-size: 12.5px;
}
.modal-close {
  display: inline-flex;
  flex: none;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  margin: -3px -10px 0 0;
  padding: 0;
  border: 0;
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--text-muted);
  cursor: pointer;
  transition:
    background 0.14s ease,
    color 0.14s ease;
}
.modal-close:hover {
  background: var(--hover);
  color: var(--text);
}
.modal-body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 20px 28px;
  transition: box-shadow 0.14s ease;
}
/* A hairline under the head once the body scrolls under it. */
.modal-body.is-scrolled {
  box-shadow: inset 0 1px 0 var(--border);
}
.modal-body:empty {
  flex: none;
  padding: 20px 0 0;
}
.modal-body > :last-child {
  margin-bottom: 0;
}
.modal-dialog > .modal-error {
  flex: none;
  max-height: 30vh;
  margin: 0 28px 16px;
  overflow-y: auto;
  white-space: pre-line;
}
.modal-dialog > .modal-actions {
  flex: none;
  flex-wrap: wrap;
  margin: 0 28px;
  padding-bottom: 28px;
}
.modal-message {
  margin: 0;
  color: var(--text-secondary);
  font-size: 14px;
  line-height: 1.5;
}
/* Inline validation: the field is outlined and the reason sits under it. */
input[aria-invalid='true'],
textarea[aria-invalid='true'],
select[aria-invalid='true'] {
  border-color: var(--danger);
}
input[aria-invalid='true']:focus,
textarea[aria-invalid='true']:focus,
select[aria-invalid='true']:focus {
  border-color: var(--danger);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--danger) 16%, transparent);
}
.field-error {
  margin-top: 6px;
  color: var(--danger-text);
  font-size: 12px;
}
/* An error that offers its own fix ("Use MY_API_KEY?", "Edit it instead"). */
.field-error-action {
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
}
.field-error-action:hover {
  color: var(--text);
}
.form-error {
  margin-top: 12px;
}
/* Link buttons (Open sign-in page, Open original, New tab) stay buttons on hover. */
a.btn:hover {
  text-decoration: none;
}
.secret-reveal-value {
  font-size: 13px;
  word-break: break-all;
  resize: none;
}
/* Error toasts (showToast(text, { tone: 'error' })) read like .alert-error
   and stay up long enough to read. */
.mini-toast.is-error {
  border: 1px solid var(--danger-line);
  background: var(--danger-soft);
  color: var(--danger-text);
}
@media (max-width: 600px) {
  .modal-head {
    padding: 22px 22px 0;
  }
  .modal-body {
    padding: 18px 22px;
  }
  .modal-body:empty {
    padding: 18px 0 0;
  }
  .modal-dialog > .modal-error {
    margin: 0 22px 14px;
  }
  .modal-dialog > .modal-actions {
    margin: 0 22px;
    padding-bottom: 22px;
  }
}

/* Codex sign-in: while it waits, a spinner and a line (not an alert, which
   reads as an empty field); the outcome swaps in as an alert. */
.oauth-status {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  border-radius: var(--radius);
  background: var(--surface-2);
  color: var(--text-secondary);
  font-size: 13.5px;
}
/* The command in the Claude token dialog's subtitle (claude setup-token)
   stays on one line; other subtitles (a long secret name) still wrap. */
.pool-token-modal .modal-sub code {
  white-space: nowrap;
}

/* A pasted token or sign-in address: monospace, broken anywhere, so it
   wraps evenly instead of at its first hyphen. */
textarea.token-input {
  font-family: var(--mono);
  font-size: 12px;
  line-height: 1.5;
  word-break: break-all;
}
/* The Codex dialog's notes and field sit one gap apart. */
.codex-login .modal-body {
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.codex-login .modal-body > .field {
  margin-bottom: 0;
}

/* Boot: index.html's placeholder until the app draws. The mark fades in
   only when startup takes a moment, so a fast start doesn't flash it. */
.boot {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  animation: fade-in-plain 0.4s ease-out 0.3s both;
}
.boot .brand-mark {
  width: 46px;
  height: 46px;
  border-radius: 14px;
  animation: boot-breathe 1.6s ease-in-out 0.7s infinite;
}
.boot .brand-mark span {
  font-size: 15px;
}
@keyframes boot-breathe {
  50% {
    opacity: 0.6;
  }
}
@media (prefers-reduced-motion: reduce) {
  .boot .brand-mark {
    animation: none;
  }
}

/* Login */

/* A focused portal, not a landing page: one glass-ringed card on the
   parchment, with Viktor's peach-to-indigo glow rising from the bottom edge. */
.login-wrap {
  position: relative;
  min-height: 100vh;
  display: flex;
  /* From a fixed top: a card grows downward (an error, a loaded list)
     instead of shifting up and down. */
  align-items: flex-start;
  justify-content: center;
  padding: clamp(40px, 12vh, 140px) 16px 96px;
  background: var(--bg);
  overflow: hidden;
  isolation: isolate;
}

.login-wrap::before {
  content: '';
  position: absolute;
  left: 50%;
  bottom: -38vh;
  width: max(1400px, 130vw);
  height: 70vh;
  transform: translateX(-50%);
  border-radius: 50%;
  background: radial-gradient(
    50% 50% at 50% 50%,
    rgba(21, 0, 121, 0.85) 0%,
    rgba(122, 29, 110, 0.7) 28%,
    rgba(255, 101, 35, 0.5) 50%,
    rgba(255, 187, 152, 0.35) 68%,
    rgba(250, 245, 241, 0) 100%
  );
  filter: blur(24px);
  pointer-events: none;
  z-index: -1;
}

.login {
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: min(400px, calc(100vw - 32px));
  padding: 36px 36px 30px;
  border: 0;
  border-radius: var(--radius-2xl);
  background: var(--surface);
  box-shadow:
    0 0 0 8px rgba(255, 255, 255, 0.55),
    var(--shadow-float);
  animation: lm-modal-in 0.5s var(--ease-out) both;
}

.login .brand-mark,
.identity-card > .brand-mark {
  width: 46px;
  height: 46px;
  border-radius: 14px;
  margin-bottom: 22px;
}
.login .brand-mark span,
.identity-card > .brand-mark span {
  font-size: 15px;
}

.login h1 {
  margin: 0;
  font-family: var(--font-display);
  font-size: 32px;
  font-weight: 500;
  letter-spacing: -0.035em;
  line-height: 1.1;
}

.login p {
  margin: 0 0 18px;
  color: var(--text-muted);
  font-size: 14px;
  text-wrap: pretty;
}
/* The address they typed, whole: a long one breaks anywhere rather than at
   its hyphen. */
.login-email {
  color: var(--text);
  font-weight: 500;
  overflow-wrap: anywhere;
}
/* Check your inbox: send the link again, or go back to change the address.
   Stacked, so "Sent. Try again in 30s" never reflows the pair. */
.login-inbox-actions {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
}

.login input {
  min-height: var(--control-h-lg);
}

.login .btn-primary {
  height: var(--control-h-lg);
  font-size: 15px;
}

/* The same card holds every sign-in step outside the app too — the front
   door (sign in, create an organization, check your inbox) and private links
   (vault, secrets): its steps stack like the card itself. */
.login-view,
.login-form {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.login-view[hidden] {
  display: none;
}
.login .login-note {
  margin: 10px 0 0;
  text-align: center;
  color: var(--text-muted);
  font-size: 13px;
}
.login-stack {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 18px;
}
.login-legal {
  color: var(--text-faint);
  font-size: 12px;
}
.login-legal a {
  color: var(--text-muted);
}
.login .login-continue {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 0 0 12px;
}

.login .alert {
  margin-top: 10px;
}

/* ============ Chat ============ */

/* The whole chat surface is one floating white panel, like the sidebar. */
.chat-shell {
  position: relative;
  display: flex;
  height: 100%;
  min-height: 0;
  margin: 0 0 0 0;
  overflow: hidden;
  border: 1px solid var(--border-card);
  border-radius: var(--radius-2xl);
  background: var(--surface);
  box-shadow: var(--shadow-card);
}

.chat-list {
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  /* Wide enough for the 34px avatar column plus its 9px gap without the
     titles losing more room than they had before the persona mark. */
  width: 300px;
  border-right: 1px solid var(--border);
  background: var(--surface-muted);
  /* Eyes and the corner-dot ring are cut-outs of whatever the row sits on. */
  --persona-eye: var(--surface-muted);
}

.chat-list-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: 50px;
  padding: 12px 12px 6px 16px;
}

.chat-list-title {
  font-size: 11px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-faint);
}

.chat-list-actions {
  display: flex;
  align-items: center;
  gap: 6px;
}

.chat-list-actions .chat-list-close {
  display: none;
}

.chat-list-actions .btn-ghost {
  padding-inline: 7px;
  color: var(--text-faint);
  font-size: 11px;
}

.chat-list-search {
  padding: 0 12px 12px;
  border-bottom: 1px solid var(--border);
}

/* All / Pinned / Archived segmented control above the search box. */
/* Viktor's segmented control: a beige pill track, the selected tab a solid
   ink pill. */
.chat-view-tabs {
  display: flex;
  gap: 2px;
  margin-bottom: 10px;
  padding: 3px;
  border-radius: var(--radius-pill);
  background: var(--surface-2);
}

.chat-view-tab {
  flex: 1;
  display: inline-flex;
  /* The count is the label's size less a step, so centring keeps one baseline. */
  align-items: center;
  justify-content: center;
  gap: 5px;
  white-space: nowrap;
  min-height: 28px;
  padding: 0 6px;
  border: 0;
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--text-muted);
  font-family: inherit;
  font-size: 12px;
  font-weight: 500;
  cursor: pointer;
  transition:
    background 0.12s ease,
    color 0.12s ease;
}

.chat-view-tab:hover {
  background: var(--hover);
  color: var(--text);
}

/* Same selected pill as the shared segmented control (.seg-btn.active). */
.chat-view-tab.active {
  background: var(--ink-btn);
  color: var(--text-inverse);
  box-shadow: 0 1px 2px color-mix(in srgb, var(--lm-ink) 16%, transparent);
}

.chat-view-count {
  font-variant-numeric: tabular-nums;
  font-size: 11.5px;
  font-weight: 500;
  color: var(--text-faint);
}

.chat-view-count:empty {
  display: none;
}

.chat-view-tab.active .chat-view-count {
  color: color-mix(in srgb, var(--text-inverse) 70%, transparent);
}

.chat-filter {
  min-height: var(--control-h);
  height: var(--control-h);
  padding-inline: 16px;
  font-size: 13.5px;
  background: var(--surface);
  border-color: var(--border-control);
  border-radius: var(--radius-pill);
}
.chat-filter:focus {
  background: var(--surface);
}

.chat-list-body {
  flex: 1;
  overflow-y: auto;
  padding: 8px 10px 16px;
}

.conv-item {
  position: relative;
  display: grid;
  grid-template-columns: 34px minmax(0, 1fr) auto;
  align-items: center;
  gap: 9px;
  width: 100%;
  min-height: 58px;
  margin-bottom: 2px;
  padding: 8px 10px;
  border: 0;
  border-radius: var(--radius);
  background: transparent;
  color: var(--text-muted);
  font-family: inherit;
  cursor: pointer;
  text-align: left;
  transition: background 0.1s ease;
}

.conv-item:hover {
  background: var(--hover);
}

.conv-item.active {
  background: var(--surface);
  box-shadow:
    0 0 0 1px var(--border-card),
    var(--shadow-card);
}

/* Every row leads with the same 34px slot: the origin mark at rest, the
   face while LobsterMane is active on the chat, so titles never move. */
.conv-item-avatar {
  position: relative;
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
}

.conv-item-origin {
  border-radius: var(--radius-pill);
  background: var(--surface-2);
  color: var(--text-muted);
}

.conv-item.active .conv-item-origin {
  background: var(--surface-muted);
}

.conv-item-origin > .icon,
.conv-item-origin > .brand-icon,
.conv-item-origin > .conv-item-bot {
  width: 16px;
  height: 16px;
}

.conv-item.archived .conv-item-origin {
  opacity: 0.6;
}

.conv-item-body {
  display: grid;
  gap: 4px;
  min-width: 0;
}

.conv-item-trailing {
  display: grid;
  justify-items: end;
  align-items: center;
  gap: 8px;
}

.conv-item-marker {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 16px;
}

.conv-item-top {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}

.conv-item-title {
  flex: 1;
  font-weight: 500;
  color: var(--text-secondary);
  font-size: 13px;
}

.conv-item.active .conv-item-title {
  color: var(--text);
}

.conv-item-time {
  flex-shrink: 0;
  font-variant-numeric: tabular-nums;
  color: var(--text-faint);
  font-size: 10.5px;
}

/* Row actions float over the meta line as a small pill toolbar instead of
   reserving a column, so titles keep their width and nothing invisible can
   be tapped. */
.conv-item-actions {
  display: none;
  align-items: center;
  gap: 2px;
}

/* On hover or keyboard focus. The open chat's row waits too: its header,
   right beside it, already shows the same buttons at rest. */
.conv-item:hover .conv-item-actions,
.conv-item:focus-within .conv-item-actions {
  position: absolute;
  right: 8px;
  bottom: 5px;
  display: flex;
  padding: 1px;
  border-radius: var(--radius-pill);
  background: var(--surface);
  box-shadow:
    0 0 0 1px var(--border-card),
    var(--shadow-card);
}

.conv-item-actions > .conv-action {
  width: 22px;
  height: 22px;
}

/* A pinned row keeps its pin badge under the time at rest; the rest wait for hover. */
.conv-item.pinned:not(:hover):not(:focus-within) .conv-item-actions {
  display: flex;
}

.conv-item.pinned:not(:hover):not(:focus-within) .conv-item-actions > .conv-action:not(.active) {
  display: none;
}

/* Touch has no hover: there the open chat's row keeps its pill at rest. */
@media (hover: none) {
  .conv-item.active .conv-item-actions {
    position: absolute;
    right: 8px;
    bottom: 5px;
    display: flex;
    padding: 1px;
    border-radius: var(--radius-pill);
    background: var(--surface);
    box-shadow:
      0 0 0 1px var(--border-card),
      var(--shadow-card);
  }

  .conv-item.active.pinned .conv-item-actions > .conv-action {
    display: inline-flex;
  }
}

.conv-item.archived .conv-item-title {
  color: var(--text-muted);
  font-weight: 500;
}

/* The icon-only action button (iconActionButton): a round ghost button. Its
   hover tint is the ink wash, so it shows on white cards and sand alike. */
.conv-action {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  padding: 0;
  border: 0;
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--text-faint);
  cursor: pointer;
  transition:
    background 0.12s ease,
    color 0.12s ease;
}

.conv-action:hover {
  background: var(--hover);
  color: var(--text);
}

.conv-action:disabled {
  opacity: var(--disabled-opacity);
  cursor: default;
  pointer-events: none;
}

/* Off but still focusable (aria-disabled): the keyboard focus stays on it. */
.conv-action[aria-disabled='true'] {
  opacity: var(--disabled-opacity);
  cursor: default;
}
.conv-action[aria-disabled='true']:hover {
  background: transparent;
  color: inherit;
}

.conv-action-danger:hover {
  background: var(--danger-soft);
  color: var(--danger-text);
}

/* Text button with a small leading icon (e.g. "+ Claude Code"). */
.btn-icon-text {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.btn-icon-text .icon {
  width: 13px;
  height: 13px;
  flex: none;
}

/* Cron run transcripts reuse the chat flow styles inside a muted panel. */
.cron-run-detail .chat-messages {
  width: 100%;
  padding: 16px 18px;
}

/* ---- Composer-owned approval requests ---- */
.chat-composer-interactions {
  /* Several asks (or a live takeover screen) can stack up: they scroll
     inside the composer instead of pushing the message box off-screen, with
     a soft shadow at whichever edge has more to see. */
  --asks-bg: color-mix(in srgb, var(--surface-muted) 72%, var(--surface));
  --asks-shade: color-mix(in srgb, var(--lm-ink) 16%, transparent);
  max-height: min(56vh, 560px);
  margin: -12px -14px 8px;
  overflow-x: hidden;
  overflow-y: auto;
  overscroll-behavior: contain;
  border-bottom: 1px solid var(--border);
  border-radius: calc(var(--radius-xl) - 1px) calc(var(--radius-xl) - 1px) 0 0;
  background:
    linear-gradient(var(--asks-bg) 40%, transparent) top / 100% 24px no-repeat local,
    linear-gradient(transparent, var(--asks-bg) 60%) bottom / 100% 24px no-repeat local,
    radial-gradient(farthest-side at 50% 0, var(--asks-shade), transparent) top / 100% 9px no-repeat
      scroll,
    radial-gradient(farthest-side at 50% 100%, var(--asks-shade), transparent) bottom / 100% 9px
      no-repeat scroll,
    var(--asks-bg);
}

@media (max-width: 1024px) {
  .chat-composer-interactions {
    max-height: min(45vh, 460px);
  }
}

/* One ask is open at a time; the rest fold to their head row. */
.composer-approval-panel.is-collapsed {
  padding-block: 9px;
}

.composer-approval-panel.is-collapsed > :not(.composer-approval-head) {
  display: none !important;
}

.composer-approval-panel.is-collapsed > .composer-approval-head {
  cursor: pointer;
  border-radius: var(--radius-xs);
}

.composer-approval-panel.is-collapsed > .composer-approval-head:hover strong {
  text-decoration: underline;
  text-underline-offset: 2px;
}

.composer-approval-panel.is-collapsed > .composer-approval-head:focus-visible {
  outline: 3px solid var(--accent-ring);
  outline-offset: 3px;
}

.composer-approval-head > .icon.composer-ask-chevron {
  margin-left: auto;
  color: var(--text-faint);
}

.composer-approval-panel + .composer-approval-panel {
  border-top: 1px solid var(--border);
}

.chat-composer-interactions[hidden] {
  display: none;
}

.chat-composer-notice {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 34px;
  padding: 7px 10px 7px 13px;
  border-bottom: 1px solid color-mix(in srgb, var(--border) 72%, transparent);
  color: var(--text-muted);
  font-size: 12px;
}

.chat-composer-notice .icon {
  width: 13px;
  height: 13px;
  flex: none;
}

.chat-composer-notice-warning > .icon {
  color: var(--warn);
}

.chat-composer-notice-error > .icon {
  color: var(--danger);
}

.chat-composer-notice-error {
  color: var(--danger-text);
}

.chat-composer-notice-copy {
  flex: 1;
  min-width: 0;
}

.chat-composer-notice-action.btn {
  flex: none;
  height: 26px;
  padding: 0 10px;
  color: var(--text-secondary);
  font-size: 12px;
}

.chat-composer-notice-dismiss.conv-action {
  flex: none;
  width: 22px;
  height: 22px;
}

.chat-composer-notice-dismiss .icon {
  width: 12px;
  height: 12px;
}

.composer-approval-panel {
  padding: 12px 14px 11px;
}

.composer-approval-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  min-width: 0;
  gap: 4px 7px;
  color: var(--text-secondary);
}

.composer-approval-head .icon {
  width: 14px;
  height: 14px;
  flex: none;
  color: var(--accent-text);
}

.composer-approval-head strong {
  flex: 1 1 0;
  min-width: 6ch;
  color: var(--text);
  font-size: 13px;
  font-weight: 500;
}

.composer-approval-kicker {
  flex: none;
  color: var(--text-muted);
  font-size: 10.5px;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.composer-approval-count {
  flex: none;
  margin-left: auto;
  color: var(--text-faint);
  font-size: 10.5px;
  font-variant-numeric: tabular-nums;
}

.composer-approval-summary {
  position: relative;
  margin-top: 9px;
  padding: 9px 12px;
  overflow: auto;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text-secondary);
  font-size: 13px;
  line-height: 1.5;
  overflow-wrap: anywhere;
}

/* Only a summary that really overflows stays clamped. The fade sits inside
   the box so its border and corners stay whole. */
.composer-approval-summary.is-clamped {
  max-height: 124px;
  overflow: hidden;
}

.composer-approval-summary.is-clamped::after {
  content: '';
  position: absolute;
  inset: auto 0 0;
  height: 40px;
  background: linear-gradient(transparent, var(--surface));
  pointer-events: none;
}

.composer-approval-more.btn {
  height: 26px;
  margin-top: 4px;
  padding: 0 10px;
  font-size: 12px;
}

.composer-approval-more[hidden] {
  display: none;
}

.composer-approval-summary > :first-child {
  margin-top: 0;
}

.composer-approval-summary > :last-child {
  margin-bottom: 0;
}

.composer-approval-error {
  margin-top: 8px;
  color: var(--danger);
  font-size: 11.5px;
}

.composer-approval-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 10px;
}

/* The open ask's buttons stay in reach while its body scrolls under them;
   the hairline shows only once something is actually behind them. */
.chat-composer-interactions
  > .composer-approval-panel:not(.is-collapsed)
  > .composer-approval-actions {
  position: sticky;
  bottom: 0;
  z-index: 1;
  margin: 2px -14px -8px;
  padding: 8px 14px;
  background: var(--asks-bg);
  transition: box-shadow 0.12s ease;
}

.chat-composer-interactions
  > .composer-approval-panel:not(.is-collapsed)
  > .composer-approval-actions.is-stuck {
  box-shadow:
    0 -1px 0 var(--border),
    0 -8px 12px -10px var(--asks-shade);
}

.chat-composer-box.has-pending-interaction .chat-input:disabled {
  color: var(--text-faint);
  cursor: default;
  opacity: 0.72;
}

.chat-composer-box.has-pending-interaction .chat-input:disabled::placeholder {
  color: var(--text-faint);
  opacity: 1;
}

.chat-composer-box.has-pending-interaction .chat-composer-row > .attach-btn,
.chat-composer-box.has-pending-interaction .chat-composer-row > .chat-stash-control,
.chat-composer-box.has-pending-interaction .chat-composer-row > .chat-model-slot,
.chat-composer-box.has-pending-interaction .chat-composer-row > .chat-composer-hint,
.chat-composer-box.has-pending-interaction .chat-composer-row > .btn-primary {
  display: none;
}

.composer-input-progress {
  margin-top: 8px;
  color: var(--text-faint);
  font-size: 11.5px;
  font-variant-numeric: tabular-nums;
}

.composer-input-fieldset {
  min-width: 0;
  margin: 9px 0 0;
  padding: 0;
  border: 0;
}

.composer-input-question {
  width: 100%;
  padding: 0;
  color: var(--text);
  font-size: 13.5px;
  font-weight: 500;
  line-height: 1.45;
}

.composer-input-help {
  margin-top: 3px;
  color: var(--text-faint);
  font-size: 11.5px;
}

.composer-input-options {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 6px;
  margin-top: 9px;
}

.composer-input-option {
  display: flex;
  min-width: 0;
  align-items: flex-start;
  gap: 8px;
  padding: 8px 9px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: color-mix(in srgb, var(--surface) 72%, transparent);
  color: var(--text-secondary);
  cursor: pointer;
  transition:
    border-color 0.12s ease,
    background 0.12s ease;
}

.composer-input-option:hover {
  border-color: var(--border-strong);
  background: var(--surface);
}

.composer-input-option:has(input[type='radio']:checked),
.composer-input-option:has(input[type='checkbox']:checked) {
  border-color: color-mix(in srgb, var(--accent-text) 46%, var(--border));
  background: color-mix(in srgb, var(--accent-text) 7%, var(--surface));
}

/* Radios and checkboxes only: the Other row's text field must still grow. */
.composer-input-option > input:is([type='radio'], [type='checkbox']),
.composer-input-other-label > input {
  margin: 1px 0 0;
}

.composer-input-option-copy {
  display: flex;
  min-width: 0;
  flex-direction: column;
  gap: 2px;
}

.composer-input-option-copy strong {
  color: var(--text);
  font-size: 13px;
  font-weight: 500;
  line-height: 1.3;
}

.composer-input-option-copy > span {
  color: var(--text-muted);
  font-size: 12px;
  line-height: 1.4;
}

.composer-input-option.is-wide {
  grid-column: 1 / -1;
}

/* Radio, "Other" and its field share one centre line. */
.composer-input-other {
  grid-column: 1 / -1;
  align-items: center;
  cursor: default;
}

.composer-input-other-label {
  display: flex;
  flex: none;
  align-items: center;
  gap: 8px;
  cursor: pointer;
}

.composer-input-other-label > input {
  margin: 0;
}

.composer-input-other-text {
  min-width: 100px;
  min-height: 0;
  height: 30px;
  flex: 1;
  padding: 4px 10px;
  border-color: var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  font-size: 12.5px;
}

.composer-input-actions {
  justify-content: space-between;
}

.composer-input-actions .btn-primary:last-child {
  margin-left: auto;
}

@media (max-width: 620px) {
  .composer-input-options {
    grid-template-columns: minmax(0, 1fr);
  }

  .composer-input-other {
    grid-column: auto;
    flex-wrap: wrap;
  }

  .composer-input-other-text {
    flex-basis: 100%;
  }
}

/* ---- Resolved gated-integration decisions in the chat history ---- */
.approval-card {
  margin: 14px 0;
  padding: 12px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface);
}

/* History is quieter than a live ask: muted surface and ink, never faded
   with opacity (which also fades the status colour). */
.approval-card.approval-resolved {
  margin-block: 10px;
  padding: 10px 14px;
  background: var(--surface-muted);
}

.approval-card.approval-resolved .approval-head {
  margin-bottom: 4px;
}

.approval-card.approval-resolved .approval-head .icon {
  color: var(--text-faint);
}

.approval-card.approval-resolved .approval-head strong {
  color: var(--text-secondary);
}

.approval-card.approval-resolved .approval-summary {
  color: var(--text-muted);
}

.approval-card.approval-resolved .approval-status {
  margin-top: 6px;
}

.approval-head {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 6px;
}

.approval-head .icon {
  width: 15px;
  height: 15px;
  flex: none;
  color: var(--accent-text);
}

.approval-head strong {
  min-width: 0;
  color: var(--text);
  font-size: 13px;
  font-weight: 500;
}

.approval-summary {
  font-size: 13px;
  overflow-wrap: anywhere;
}

.approval-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-top: 10px;
}

.approval-status {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 8px;
  font-size: 12px;
  color: var(--text-muted);
}

.approval-status .icon {
  width: 13px;
  height: 13px;
  flex: none;
}

.approval-status-approved {
  color: var(--ok-text);
}

.approval-status-denied {
  color: var(--danger-text);
}

.chat-input-history {
  display: grid;
  gap: 6px;
}

.chat-input-history .approval-head {
  margin-bottom: 2px;
}

.chat-input-history-row {
  display: grid;
  grid-template-columns: minmax(100px, 0.42fr) minmax(0, 1fr);
  gap: 12px;
  font-size: 13px;
}

.chat-input-history-question {
  color: var(--text-muted);
  overflow-wrap: anywhere;
}

.chat-input-history-answer {
  color: var(--text-secondary);
  overflow-wrap: anywhere;
}

.chat-interrupted-card {
  border-color: var(--warn-line);
  background: var(--warn-soft);
}

.chat-interrupted-card .approval-head .icon {
  color: var(--warn-text);
}

.chat-interrupted-note {
  align-self: center;
  color: var(--text-muted);
  font-size: 12px;
}

.conv-action.active {
  color: var(--accent-text);
  opacity: 1;
}

.conv-action .icon {
  width: 14px;
  height: 14px;
  opacity: 1;
}

.chat-head-actions {
  display: flex;
  align-items: center;
  gap: 6px;
}

/* Header actions are labeled pills: easy to see, easy to hit. */
.chat-head-btn {
  height: 34px;
  gap: 7px;
  padding: 0 14px 0 12px;
  font-size: 13px;
  color: var(--text-secondary);
}

.chat-head-btn .icon {
  width: 15px;
  height: 15px;
  color: var(--text-muted);
}

.chat-head-btn:hover .icon {
  color: var(--text);
}

.chat-head-btn.active {
  border-color: var(--accent-line);
  background: var(--accent-tint);
  color: var(--accent-text);
}

.chat-head-btn.active .icon {
  color: var(--accent);
}

/* Screen while its VM starts: a spinner where the icon was, not faded out. */
.conv-screen-action.is-busy:disabled {
  opacity: 1;
  cursor: progress;
}

.conv-screen-action.is-busy .spinner-dot {
  width: 13px;
  height: 13px;
  border-width: 1.75px;
}

.conv-action.conv-screen-action.is-busy .spinner-dot {
  width: 11px;
  height: 11px;
}

@media (max-width: 1100px) {
  .chat-head-btn {
    width: 34px;
    padding: 0;
  }
  .chat-head-btn-label {
    display: none;
  }
}

/* A bot's chat keeps "Routines" in words after Screen has become an icon. */
@media (max-width: 1100px) {
  .chat-head-routines {
    width: auto;
    padding: 0 12px;
  }
  .chat-head-routines .chat-head-btn-label {
    display: inline;
  }
}

/* The code panel halves the pane without changing the window: follow the pane.
   A bot's "Routines" is the last to give up its word. */
@container chat-head (max-width: 720px) {
  .chat-head-btn {
    width: 34px;
    padding: 0;
  }
  .chat-head-btn-label {
    display: none;
  }
  .chat-head-routines {
    width: auto;
    padding: 0 12px;
  }
  .chat-head-routines .chat-head-btn-label {
    display: inline;
  }
}

@container chat-head (max-width: 380px) {
  .chat-head-routines {
    width: 34px;
    padding: 0;
  }
  .chat-head-routines .chat-head-btn-label {
    display: none;
  }
}

/* "⋯" after the pills: the copy commands (every action on a phone). */
.chat-head-btn.chat-head-more {
  width: 34px;
  padding: 0;
}

.chat-head-right .conv-action {
  opacity: 1;
  border: 1px solid var(--border);
  background: var(--surface);
}

.chat-head-right .conv-action.active {
  border-color: var(--accent-ring);
  background: var(--accent-soft);
}

.conv-item-meta {
  min-height: 14px;
  color: var(--text-faint);
  font-size: 11.5px;
}

@media (min-width: 601px) {
  .chat-list-empty.chat-list-empty-mirrored {
    display: none;
  }
}

.chat-list-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: 20px 10px;
  text-align: center;
  color: var(--text-faint);
  font-size: 12.5px;
  overflow-wrap: anywhere;
}

.chat-main {
  flex: 1;
  display: flex;
  flex-direction: column;
  position: relative;
  min-width: 0;
  background: var(--surface);
}

.chat-work-area {
  position: relative;
  display: flex;
  flex: 1 1 auto;
  min-width: 0;
  min-height: 0;
  overflow: hidden;
  background: var(--surface);
}

.chat-code-panel {
  position: relative;
  z-index: 8;
  display: flex;
  flex: 0 0 auto;
  flex-direction: column;
  min-width: 420px;
  max-width: min(900px, calc(100% - 420px));
  min-height: 0;
  overflow: hidden;
  border-left: 1px solid var(--border-strong);
  background: var(--surface);
  box-shadow: -10px 0 30px color-mix(in srgb, var(--lm-ink) 6%, transparent);
}

.chat-code-panel.closing {
  pointer-events: none;
  opacity: 0.72;
}

.chat-code-panel-resizer {
  position: absolute;
  z-index: 12;
  inset: 0 auto 0 -4px;
  width: 8px;
  cursor: col-resize;
}

.chat-code-panel-resizer:hover {
  background: color-mix(in srgb, var(--accent-text) 18%, transparent);
}

.chat-code-panel-head {
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  min-height: 54px;
  padding: 8px 10px 8px 14px;
  border-bottom: 1px solid var(--border);
  background: var(--surface-muted);
}

.chat-code-panel-copy {
  min-width: 0;
}

.chat-code-panel-heading {
  display: flex;
  align-items: center;
  gap: 7px;
  min-width: 0;
}

.chat-code-panel-heading > .icon {
  flex: 0 0 auto;
  width: 14px;
  height: 14px;
  color: var(--accent-text);
}

.chat-code-panel-title {
  flex: 0 0 auto;
  max-width: 180px;
  color: var(--text);
  font-size: 12.5px;
}

.chat-code-panel-path {
  color: var(--text-faint);
  font-family: var(--mono);
  font-size: 10.5px;
}

.chat-code-panel-reason {
  margin-top: 2px;
  color: var(--text-muted);
  font-size: 10.5px;
}

.chat-code-panel-actions {
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  gap: 4px;
}

.chat-code-panel-actions .conv-action {
  opacity: 1;
  border: 1px solid var(--border);
  background: var(--surface);
}

.chat-code-editor {
  display: flex;
  flex: 1 1 auto;
  min-width: 0;
  min-height: 0;
  overflow: hidden;
}

.chat-work-area.code-maximized .chat-main {
  display: none;
}

.chat-work-area.code-maximized .chat-code-panel {
  width: 100% !important;
  max-width: none;
  border-left: 0;
}

.chat-head {
  container: chat-head / inline-size;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  min-height: 60px;
  padding: 12px 24px;
  border-bottom: 1px solid var(--border);
  background: var(--surface);
}

.chat-head-leading {
  display: flex;
  flex: 1 1 auto;
  align-items: center;
  gap: 9px;
  min-width: 0;
}

.chat-mobile-list-toggle,
.chat-mobile-list-backdrop {
  display: none;
}

/* The title always keeps about a dozen characters beside the actions. */
.chat-head-text {
  flex: 1;
  min-width: min(12ch, 100%);
  font-size: 18px;
}

.chat-head-title {
  font-family: var(--font-display);
  font-size: 18px;
  font-weight: 500;
  letter-spacing: -0.025em;
  line-height: 1.2;
}

.chat-head-sub {
  margin-top: 2px;
  color: var(--text-faint);
  font-size: 12px;
}

.chat-head-right {
  display: flex;
  align-items: center;
  flex-shrink: 0;
  gap: 10px;
}

/* As wide as the chosen model, not the longest one in the list. */
.chat-model-select {
  field-sizing: content;
  width: auto;
  min-height: 30px;
  height: 30px;
  max-width: 230px;
  padding: 0 28px 0 12px;
  border-radius: var(--radius-pill);
  background-color: var(--surface);
  color: var(--text-secondary);
  font-size: 12.5px;
}

.chat-live-dot {
  width: 10px;
  height: 10px;
  margin: 0 4px;
  border-radius: var(--radius-pill);
  background: var(--text-faint);
  box-shadow: 0 0 0 3px var(--active);
  flex-shrink: 0;
}
.chat-live-dot.live {
  background: var(--ok);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--ok) 20%, transparent);
}
.chat-live-dot.connecting,
.chat-live-dot.synchronizing,
.chat-live-dot.backoff {
  animation: pulse 1.2s ease-in-out infinite;
  background: var(--warn);
}

.chat-live-dot.cached,
.chat-live-dot.offline {
  background: var(--text-faint);
}

.chat-live-dot.blocked {
  background: var(--danger);
}

.chat-scroll {
  flex: 1;
  overflow-y: auto;
  position: relative;
  padding: 0 22px;
  scroll-padding-bottom: 24px;
}

.chat-messages {
  display: flex;
  flex-direction: column;
  width: min(720px, 100%);
  margin: 0 auto;
  padding: 28px 0 14px;
}

/* Settled rows off screen skip style, layout and paint until they near the
   viewport, so an update to a 300-message chat lays out the rows on screen
   instead of all of them. Off screen a row stands in at the size it last
   rendered at (paintMessages carries that over when it rebuilds rows), so
   scroll anchoring keeps what a reader is looking at in place. Text stays
   in the page for find and selection. A row holding focus renders fully, so
   paint containment never clips its focus ring. */
.chat-messages
  > :is(.msg:not([data-chat-anchor^='pending:']), .approval-card, .cc-run-finished):not(
    :focus-within
  ) {
  content-visibility: auto;
  contain-intrinsic-size: auto 96px;
}

.chat-history-window {
  display: flex;
  min-height: 32px;
  margin: -8px 0 18px;
  align-items: center;
  justify-content: center;
  gap: 10px;
  color: var(--text-faint);
  font-size: 11.5px;
}

.chat-history-button.btn:disabled {
  cursor: default;
  opacity: 0.65;
}

.chat-history-error {
  color: var(--danger);
}

.chat-empty {
  margin: 20vh auto 0;
  text-align: center;
  animation: lm-enter 0.6s var(--ease-out) both;
}
.chat-empty-eyebrow {
  margin-bottom: 16px;
}
.chat-empty-title {
  font-family: var(--font-display);
  font-size: 38px;
  font-weight: 500;
  letter-spacing: -0.035em;
  line-height: 1.1;
}
.chat-empty-sub {
  font-size: 15px;
  margin: 10px auto 0;
  max-width: 520px;
  color: var(--text-muted);
}

.starter-chips {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
  max-width: 660px;
  margin: 28px auto 0;
}

.starter-chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 38px;
  padding: 0 16px 0 14px;
  border: 1px solid var(--border-control);
  border-radius: var(--radius-pill);
  background: var(--surface);
  color: var(--text-secondary);
  font-family: inherit;
  font-size: 13.5px;
  font-weight: 500;
  letter-spacing: -0.005em;
  cursor: pointer;
  animation: lm-enter 0.5s var(--ease-out) both;
  transition:
    background 0.14s ease,
    border-color 0.14s ease,
    color 0.14s ease,
    transform 0.14s ease;
}

.starter-chip:nth-child(2) {
  animation-delay: 40ms;
}
.starter-chip:nth-child(3) {
  animation-delay: 80ms;
}
.starter-chip:nth-child(4) {
  animation-delay: 120ms;
}
.starter-chip:nth-child(5) {
  animation-delay: 160ms;
}

.starter-chip .icon {
  width: 15px;
  height: 15px;
  color: var(--accent);
}

.starter-chip:hover {
  border-color: var(--accent-line);
  background: var(--accent-tint);
  color: var(--text);
  transform: translateY(-1px);
}

/* The agent's asks (vault login, takeover) in the Viktor language: the
   takeover screen in a product frame. Scoped a step higher than their base
   rules so both can evolve. */
div.agent-takeover-screen {
  border: 0;
  border-radius: var(--radius-xl);
  box-shadow:
    0 0 0 1px var(--border-card),
    0 0 0 6px color-mix(in srgb, var(--surface) 70%, transparent),
    var(--shadow-float);
}
form.vault-add-form,
div.vault-add-form {
  padding: 20px 28px;
}

/* Reduced motion: the v7 entrances (sign-in card, modals, the live screen,
   the new-chat state and its starter chips) appear in place. */
@media (prefers-reduced-motion: reduce) {
  /* "html" lifts these above rules that appear later in the file. */
  html .login,
  html .modal-content,
  html .screen-panel,
  html .chat-empty,
  html .starter-chip {
    animation: none;
  }
  html .btn,
  html .starter-chip,
  html .toggle-slider::before,
  html .meter-fill {
    transition: none;
  }
  html .starter-chip:hover,
  html .btn:active:not(:disabled) {
    transform: none;
  }
}

/* Viktor's segmented pills, reusable: a beige track with the chosen option
   in ink. The 3px track around --control-h-sm buttons makes --control-h.
   --radius-xl still reads as a pill on one row, and keeps a track that
   wraps on a phone a rounded card instead of a lozenge. */
.seg {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 2px;
  padding: 3px;
  border-radius: var(--radius-xl);
  background: var(--surface-2);
}

.seg-btn {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  height: var(--control-h-sm);
  padding: 0 14px;
  border: 0;
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--text-muted);
  font-family: inherit;
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  transition:
    background 0.14s ease,
    color 0.14s ease;
}

.seg-btn:hover:where(:not(:disabled)) {
  background: var(--hover);
  color: var(--text);
}

.seg-btn.active {
  background: var(--ink-btn);
  color: var(--text-inverse);
  box-shadow: 0 1px 2px color-mix(in srgb, var(--lm-ink) 16%, transparent);
}

.seg-btn:disabled {
  cursor: not-allowed;
  opacity: var(--disabled-opacity);
}

.seg-count {
  font-size: 11.5px;
  color: var(--text-faint);
  font-variant-numeric: tabular-nums;
}

.seg-btn.active .seg-count {
  color: color-mix(in srgb, var(--text-inverse) 65%, transparent);
}

.ig-state-bar {
  margin-top: -6px;
  padding: 0 28px 18px;
}

/* ============ VMs (Royal TS-style overview) ============ */

.vm-summary {
  display: flex;
  border: 1px solid var(--border-card);
  border-radius: var(--radius-2xl);
  background: var(--surface);
  overflow: hidden;
}

/* Four counts share one row (no wrapped odd one out). Each is a button that
   filters the grid; the picked one sits on the sand. */
.vm-stat {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  padding: 18px 24px;
  border: 0;
  border-right: 1px solid var(--border);
  background: transparent;
  color: var(--text);
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: background 0.14s ease;
}

.vm-stat:hover:not(:disabled) {
  background: var(--hover);
}

.vm-stat.active,
.vm-stat.active:hover {
  background: var(--surface-2);
}

.vm-stat.active:not(.vm-stat-bad) .vm-stat-value {
  color: var(--accent-text);
}

.vm-stat:disabled {
  cursor: default;
}

/* Inside the strip's clip: the ring sits within the cell, rounded to fit. */
.vm-stat:focus-visible {
  outline-offset: -5px;
  border-radius: 22px;
  box-shadow: none;
}

.vm-stat:last-child {
  border-right: 0;
}

.vm-stat-value {
  font-family: var(--font-display);
  font-size: 28px;
  font-weight: 500;
  letter-spacing: -0.035em;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
}

.vm-stat-label {
  max-width: 100%;
  color: var(--text-muted);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.vm-stat-bad .vm-stat-value {
  color: var(--danger-text);
}

.vm-stat-zero .vm-stat-value {
  color: var(--text-muted);
}

/* Admins only: when the VM image was built and the projects last synced. */
.vm-summary-note {
  margin: 8px 0 0;
  color: var(--text-muted);
  font-size: 12.5px;
}

.vm-summary[hidden] + .vm-summary-note {
  margin-top: 0;
}

.grid-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.grid-size-control {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  color: var(--text-muted);
  font-size: 12.5px;
  font-weight: 500;
}

/* Icon-only segments (the tile-size toggle): square pills on the same track. */
.seg-icon {
  width: 34px;
  padding: 0;
  justify-content: center;
}

.seg-icon .icon {
  width: 15px;
  height: 15px;
}

/* VMs an admin can see but not open: a titled list of compact rows under the
   grid, so the screens you can open lead the page. */
.vm-locked {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-top: 10px;
}

.vm-locked-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 14px;
}

.vm-locked-title {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  font-family: var(--font-display);
  font-size: 19px;
  font-weight: 500;
  letter-spacing: -0.02em;
}

.vm-locked-title .icon {
  width: 15px;
  height: 15px;
  color: var(--text-muted);
}

.vm-locked-note {
  margin: 0;
  color: var(--text-muted);
  font-size: 13px;
  line-height: 1.5;
  text-wrap: pretty;
}

.vm-locked-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 300px), 1fr));
  gap: 10px;
}

.vm-locked-row {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
  padding: 12px 14px;
  border: 1px solid var(--border-card);
  border-radius: var(--radius-xl);
  background: var(--surface);
  box-shadow: var(--shadow-card);
}

.vm-locked-line {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}

.vm-locked-dot {
  flex: none;
  display: inline-flex;
}

.vm-locked-name {
  min-width: 0;
  font-family: var(--font-display);
  font-size: 15px;
  font-weight: 500;
  letter-spacing: -0.015em;
}

.vm-locked-state {
  flex: none;
  margin-left: auto;
  color: var(--text-muted);
  font-size: 12px;
}

.vm-locked-sub {
  display: flex;
  align-items: center;
  gap: 5px;
  min-width: 0;
  color: var(--text-muted);
  font-size: 12.5px;
}

.vm-locked-sub .icon {
  width: 13px;
  height: 13px;
  color: var(--text-faint);
}

.vm-locked-why {
  min-width: 0;
}

.vm-locked-meta {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  margin-top: 3px;
}

/* One line in a row: the phrases that don't fit are left off whole. */
.vm-locked-meta .shot-meta {
  flex: 1 1 auto;
  min-width: 0;
  max-height: 1.45em;
}

.vm-locked-meta .vm-chip-btn {
  flex: none;
}

.content > .shot-grid {
  max-width: none;
}

/* A page whose grid runs full width (VMs, Artifacts) is that wide in every
   state (loading, error, empty), so nothing jumps when the grid arrives. */
.content.content-wide > * {
  max-width: none;
}

.shot-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, var(--tile-min, 320px)), 1fr));
  gap: 18px;
}

/* Each tile is a Viktor product frame: the screen inset in a white card. */
.shot-tile {
  display: flex;
  flex-direction: column;
  min-width: 0;
  padding: 8px;
  border: 1px solid var(--border-card);
  border-radius: var(--radius-2xl);
  background: var(--surface);
  box-shadow: var(--shadow-card);
  transition:
    transform 0.18s var(--ease-out),
    box-shadow 0.18s ease,
    border-color 0.18s ease;
}

.shot-tile-open {
  cursor: pointer;
}

.shot-tile-open:hover,
.shot-tile-open:has(.shot-frame:focus-visible) {
  transform: translateY(-2px);
  border-color: var(--border-strong);
  box-shadow: var(--shadow-float);
}

/* The screen is the tile's button; the app's one ring goes round the whole
   tile. */
.shot-tile-open:has(.shot-frame:focus-visible) {
  outline: var(--focus-outline);
  outline-offset: 2px;
  box-shadow:
    0 0 0 5px var(--accent-ring),
    var(--shadow-float);
}

.shot-frame {
  position: relative;
}

button.shot-frame {
  display: block;
  width: 100%;
  padding: 0;
  border: 0;
  border-radius: 18px;
  background: none;
  color: inherit;
  text-align: inherit;
  cursor: pointer;
}

button.shot-frame:focus-visible {
  outline: none;
}

.shot {
  position: relative;
  display: grid;
  place-items: center;
  aspect-ratio: 16 / 10;
  overflow: hidden;
  border-radius: 18px;
  background: #0f0e1a;
}

.shot-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* A paused or failed VM's last screenshot is a memory, not a live screen:
   dimmed like an archived artifact (the chips stay crisp). Hover shows it
   as it was. */
.vm-tile:is([data-state='paused'], [data-state='error']) .shot-img {
  filter: grayscale(0.6);
  opacity: 0.75;
  transition:
    filter 0.18s ease,
    opacity 0.18s ease;
}

.vm-tile[data-state='error'] .shot {
  outline: 1px solid color-mix(in srgb, var(--danger) 45%, transparent);
  outline-offset: -1px;
}

/* A short frame (Small tiles) drops the icon, so its line never rides up
   into the chips. */
.vm-tile .shot {
  container-type: inline-size;
}

@container (max-width: 260px) {
  .shot-empty > .icon {
    display: none;
  }
}

/* What a click does ("Open screen", "Resume and open"), over a scrim, on
   hover and keyboard focus. While the screen is on its way, the same spot
   holds the spinner (.vm-opening). */
.vm-tile .shot::after {
  content: '';
  position: absolute;
  inset: 0;
  background: rgba(20, 18, 32, 0.28);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.16s ease;
}

.shot-cta {
  position: absolute;
  inset: 50% auto auto 50%;
  z-index: 1;
  transform: translate(-50%, -50%);
}

.shot-cta,
.vm-opening {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 7px 14px;
  border-radius: var(--radius-pill);
  background: rgba(255, 255, 255, 0.94);
  color: var(--text);
  font-size: 12.5px;
  font-weight: 500;
  white-space: nowrap;
  box-shadow: var(--shadow-float);
  pointer-events: none;
}

.shot-cta {
  opacity: 0;
  transition: opacity 0.16s ease;
}

.shot-cta .icon {
  width: 14px;
  height: 14px;
  color: var(--text-muted);
}

/* The spinner pill and its Cancel, over the screen (the tile's padding box
   starts where the screen does) but outside its button. */
.vm-tile {
  position: relative;
}

.vm-opening-layer {
  position: absolute;
  top: 8px;
  left: 8px;
  right: 8px;
  z-index: 2;
  aspect-ratio: 16 / 10;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  pointer-events: none;
}

.vm-opening-cancel {
  display: inline-flex;
  align-items: center;
  height: 26px;
  padding: 0 12px;
  border: 0;
  border-radius: var(--radius-pill);
  background: rgba(20, 18, 32, 0.6);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  color: #ffffff;
  font: inherit;
  font-size: 12px;
  font-weight: 500;
  cursor: pointer;
  pointer-events: auto;
  transition: background 0.14s ease;
}

.vm-opening-cancel:hover {
  background: rgba(20, 18, 32, 0.82);
}

.vm-tile .shot-empty > * {
  transition: opacity 0.16s ease;
}

.vm-tile .shot-frame:focus-visible .shot::after,
.vm-tile .shot-frame:focus-visible .shot-cta {
  opacity: 1;
}

/* The CTA takes the placeholder's spot ("No screenshot yet" under it). */
.vm-tile .shot-frame:focus-visible .shot-empty > * {
  opacity: 0;
}

@media (hover: hover) {
  .vm-tile:hover .shot::after,
  .vm-tile:hover .shot-cta {
    opacity: 1;
  }
  .vm-tile:hover .shot-empty > * {
    opacity: 0;
  }
  .vm-tile:hover .shot-img {
    filter: none;
    opacity: 1;
  }
}

/* A live VM whose screenshot stopped updating says how old it is. */
.shot-age {
  position: absolute;
  right: 10px;
  bottom: 10px;
  display: inline-flex;
  align-items: center;
  height: 22px;
  padding: 0 9px;
  border-radius: var(--radius-pill);
  background: rgba(20, 18, 32, 0.72);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  color: #ffffff;
  font-size: 11px;
  font-weight: 500;
}

.shot-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  width: 100%;
  height: 100%;
  /* Clear of the state chip (10px + 26px), however short the frame. */
  padding: 44px 16px 16px;
  background:
    radial-gradient(90% 80% at 50% 110%, rgba(255, 132, 80, 0.28) 0%, rgba(255, 132, 80, 0) 60%),
    linear-gradient(160deg, var(--ink-btn-hover) 0%, var(--lm-ink) 100%);
  color: rgba(255, 255, 255, 0.72);
  text-align: center;
}

.shot-empty .icon {
  width: 28px;
  height: 28px;
  opacity: 0.7;
}

.shot-note {
  display: -webkit-box;
  overflow: hidden;
  max-width: 240px;
  font-size: 12.5px;
  line-height: 1.4;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
}

.shot-top {
  position: absolute;
  top: 10px;
  left: 10px;
  right: 10px;
  display: flex;
  justify-content: space-between;
  gap: 6px;
  pointer-events: none;
}

/* The state gives way (ellipsis) before "Yours" does. */
.vm-state {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-width: 0;
  height: 26px;
  padding: 0 11px;
  border-radius: var(--radius-pill);
  background: rgba(20, 18, 32, 0.72);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  color: #ffffff;
  font-size: 12px;
  font-weight: 500;
}

.vm-state-dot {
  flex: none;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--lm-grey);
}

.vm-state-task .vm-state-dot,
.vm-state-finishing .vm-state-dot {
  background: var(--accent);
  box-shadow: 0 0 0 0 rgba(255, 101, 35, 0.6);
  animation: vm-pulse 1.8s ease-out infinite;
}

.vm-state-grace .vm-state-dot,
.vm-state-running .vm-state-dot {
  background: var(--ok);
}

.vm-state-viewing .vm-state-dot {
  background: var(--lm-peach);
}

.vm-state-error .vm-state-dot {
  background: var(--danger);
}

@keyframes vm-pulse {
  0% {
    box-shadow: 0 0 0 0 rgba(255, 101, 35, 0.6);
  }
  70% {
    box-shadow: 0 0 0 7px rgba(255, 101, 35, 0);
  }
  100% {
    box-shadow: 0 0 0 0 rgba(255, 101, 35, 0);
  }
}

.vm-mine {
  flex: none;
  display: inline-flex;
  align-items: center;
  height: 26px;
  padding: 0 10px;
  border-radius: var(--radius-pill);
  background: var(--eyebrow-bg);
  color: var(--eyebrow-text);
  font-size: 12px;
  font-weight: 500;
}

.spinner-dot {
  flex-shrink: 0;
  width: 12px;
  height: 12px;
  border: 2px solid var(--border-strong);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: vm-spin 0.8s linear infinite;
}

.shot-empty .spinner-dot {
  width: 22px;
  height: 22px;
  border-color: rgba(255, 255, 255, 0.22);
  border-top-color: var(--accent);
}

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

.shot-tile-opening {
  pointer-events: none;
}

/* A VM tile that is opening keeps its hover and shows it is busy (a second
   click does nothing): the frame's own content steps back behind a darker
   scrim and the spinner. */
.vm-tile.shot-tile-opening {
  pointer-events: auto;
  cursor: progress;
}

.vm-tile.shot-tile-opening .shot-frame {
  cursor: progress;
}

.vm-tile.shot-tile-opening .shot-empty > *,
.vm-tile.shot-tile-opening .shot-cta,
.vm-tile.shot-tile-opening .shot-age {
  visibility: hidden;
}

.vm-tile.shot-tile-opening .shot::after {
  background: rgba(20, 18, 32, 0.35);
  opacity: 1;
}

.shot-body {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 12px 8px 6px;
  min-width: 0;
}

.shot-name {
  font-family: var(--font-display);
  font-size: 17px;
  font-weight: 500;
  letter-spacing: -0.02em;
  line-height: 1.2;
}

.shot-detail {
  margin-top: 1px;
  color: var(--text-muted);
  font-size: 12.5px;
}

.vm-task {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  font-size: 13px;
}

/* "Now" / "Last": the shared pill chip, a size down. */
.vm-task-label {
  flex: none;
  height: 20px;
  padding: 0 8px;
  font-size: 11px;
}

.vm-task-title {
  min-width: 0;
  color: var(--text);
  font-weight: 500;
}

a.vm-task-title:hover {
  color: var(--accent-text);
}

.vm-task-when {
  flex: none;
  margin-left: auto;
  color: var(--text-muted);
  font-size: 12px;
}

.vm-task-none {
  color: var(--text-faint);
}

.shot-meta {
  color: var(--text-muted);
  font-size: 12px;
  line-height: 1.45;
}

/* Each phrase wraps whole. The dot before it sits in its left padding, and
   the row starts 13px left of the edge (clipped), so the dot before a line's
   first phrase is never seen: no line starts or ends on a dot. */
.vm-tile .shot-meta,
.vm-locked-meta .shot-meta {
  overflow: hidden;
}

.shot-meta-bits {
  display: flex;
  flex-wrap: wrap;
  margin-left: -13px;
}

.shot-meta-bit {
  position: relative;
  padding-left: 13px;
  white-space: nowrap;
}

.shot-meta-bit::before {
  content: '·';
  position: absolute;
  left: 4px;
}

.shot-meta-bad {
  color: var(--danger-text);
}

/* What went wrong, in words: up to two lines (the full text on hover). */
.shot-error {
  display: -webkit-box;
  overflow: hidden;
  color: var(--danger-text);
  font-size: 12px;
  line-height: 1.45;
  overflow-wrap: anywhere;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
}

.shot-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

/* A chip that explains itself on click (Older image). */
.vm-chip-btn {
  cursor: pointer;
}

/* On touch, the chip and the task link take a tap that just misses them
   (at least 32px tall), not the tile's "open the screen". The link clips
   its text for the ellipsis, so it grows by padding instead. */
@media (pointer: coarse) {
  .vm-chip-btn {
    position: relative;
  }
  .vm-chip-btn::after {
    content: '';
    position: absolute;
    inset: -6px -4px;
  }
  a.vm-task-title {
    margin: -7px -4px;
    padding: 7px 4px;
  }
}

.vm-chip-btn:hover {
  border-color: var(--warn-text);
}

/* Small tiles and phones: the text tightens with the screen. One meta line
   (the phrases that don't fit are left off whole), one error line (the full
   text on hover), and no "when" beside the task (the meta line has it). */
.shot-grid-sm .shot-body {
  gap: 6px;
  padding: 10px 6px 4px;
}

.shot-grid-sm .shot-name {
  font-size: 15px;
}

.shot-grid-sm .vm-task-when {
  display: none;
}

.shot-grid-sm .shot-meta {
  max-height: 1.45em;
}

.shot-grid-sm .shot-error {
  -webkit-line-clamp: 1;
  line-clamp: 1;
}

@media (max-width: 600px) {
  .vm-tile .shot-body {
    gap: 6px;
    padding: 10px 6px 4px;
  }
  .vm-tile .shot-name {
    font-size: 15px;
  }
  .vm-tile .vm-task-when {
    display: none;
  }
  .vm-tile .shot-meta {
    max-height: 1.45em;
  }
  .vm-tile .shot-error {
    -webkit-line-clamp: 1;
    line-clamp: 1;
  }
}

.vm-popover {
  width: min(300px, calc(100vw - 16px));
  padding: 12px 14px;
}

.vm-popover-text {
  margin: 0;
  color: var(--text-secondary);
  font-size: 13px;
  line-height: 1.5;
}

.grid-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 56px 24px;
  text-align: center;
}

.grid-empty-art {
  display: grid;
  place-items: center;
  width: 56px;
  height: 56px;
  margin-bottom: 16px;
  border-radius: 16px;
  background: var(--tile-bg);
  box-shadow: var(--shadow-tile);
  color: var(--accent);
}

.grid-empty-art .icon {
  width: 24px;
  height: 24px;
}

.grid-empty-title {
  margin: 0;
  font-family: var(--font-display);
  font-size: 24px;
  font-weight: 500;
  letter-spacing: -0.03em;
}

.grid-empty-sub {
  max-width: 460px;
  margin: 8px 0 0;
  color: var(--text-muted);
  text-wrap: balance;
}
/* A failed page's server message, under what to do about it. */
.grid-empty-sub.page-state-detail {
  margin-top: 4px;
  color: var(--text-faint);
  font-size: 12.5px;
  overflow-wrap: anywhere;
}

@media (max-width: 600px) {
  /* Sized by their words first, so no label is cut on a narrow phone. */
  .vm-stat {
    flex: 1 1 auto;
    padding: 12px 10px 12px 12px;
  }
  .vm-stat-label {
    font-size: 10px;
    letter-spacing: 0.04em;
  }
  .vm-stat-value {
    font-size: 22px;
  }
  .grid-size-control {
    display: none;
  }
  /* No size on a phone: with no pills either, no toolbar. */
  .grid-toolbar:has(> .seg[hidden]) {
    display: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  html .shot-tile {
    transition: none;
  }
  html .shot-tile-open:hover {
    transform: none;
  }
  html .vm-tile .shot::after,
  html .shot-cta,
  html .shot-img {
    transition: none;
  }
  html .vm-state-task .vm-state-dot,
  html .vm-state-finishing .vm-state-dot,
  html .spinner-dot {
    animation: none;
  }
}

/* ============ Artifacts grid ============ */

.grid-filters {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
}

select.grid-select {
  width: auto;
  min-height: 36px;
  height: 36px;
  border-radius: var(--radius-pill);
  font-size: 13px;
  font-weight: 500;
}

/* The chips sit low so they never cover the top of a screenshot, where a page keeps its
   heading and navigation. At the smallest tile a chip that does not fit wraps onto its own
   line rather than being cut. */
.art-tile .shot-top {
  top: auto;
  bottom: 10px;
  flex-wrap: wrap;
  justify-content: flex-start;
  gap: 6px;
}

.art-tile-archived .shot {
  filter: grayscale(0.6);
  opacity: 0.75;
}

.art-scope {
  display: inline-flex;
  align-items: center;
  height: 24px;
  padding: 0 10px;
  border-radius: var(--radius-pill);
  background: rgba(20, 18, 32, 0.72);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  color: #ffffff;
  font-size: 12px;
  font-weight: 500;
}

.art-desc {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
  color: var(--text-secondary);
  font-size: 13px;
  line-height: 1.45;
}

.art-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

/* "Published … · yours" stays one line beside the buttons at every tile size. */
.art-foot .shot-meta {
  min-width: 0;
}

.art-actions {
  display: flex;
  flex: none;
  gap: 2px;
}

/* An artifact without a screenshot: the VM grid's empty card with one plain
   line, never a made-up page. min-width: 0 keeps it the frame's width (.shot
   is a grid), so a long file name ends in an ellipsis instead of widening it. */
.art-state {
  min-width: 0;
  padding: 16px 20px 44px;
}

.art-state .shot-note {
  max-width: min(240px, 100%);
  overflow-wrap: anywhere;
}

/* A download: its type in large letters, then its real name and size. */
.art-state-file {
  gap: 6px;
}

.art-file-ext {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: #ffffff;
  font-family: var(--font-display);
  font-size: 26px;
  font-weight: 500;
  letter-spacing: -0.02em;
  line-height: 1;
}

.art-state-file .art-file-ext .icon {
  width: 22px;
  height: 22px;
  opacity: 0.75;
}

.art-file-name {
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: rgba(255, 255, 255, 0.86);
  font-size: 12.5px;
  font-weight: 500;
}

/* Viktor's accent words ("A hire."): the accent, lit a step lighter at the top. */
.grad-text {
  background: var(--grad-text);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

@keyframes lm-enter {
  from {
    opacity: 0;
    transform: translateY(var(--enter-y));
  }
  to {
    opacity: 1;
    transform: none;
  }
}

.msg {
  position: relative;
  margin-bottom: 26px;
  padding-left: 42px;
}

.msg-copy {
  position: absolute;
  top: 1px;
  right: 0;
  display: inline-flex;
  width: 26px;
  height: 26px;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 0;
  border-radius: var(--radius-pill);
  background: color-mix(in srgb, var(--surface) 88%, transparent);
  color: var(--text-faint);
  opacity: 0;
  cursor: pointer;
  transition:
    opacity 0.12s ease,
    color 0.12s ease,
    background 0.12s ease;
}

.msg-copy .icon {
  width: 13px;
  height: 13px;
}

.msg:hover .msg-copy,
.msg-copy:focus-visible {
  opacity: 1;
}

.msg-copy:hover {
  background: var(--hover);
  color: var(--text-secondary);
}

/* The copy button takes the head's right end; the time sits just before it. */
.msg:has(> .msg-copy) > .msg-head {
  padding-right: 32px;
}

.msg-grouped {
  margin-top: -16px;
}

.msg-head {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 4px;
  min-height: 30px;
  margin-left: -42px;
}

.author-dot {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 30px;
  height: 30px;
  border-radius: var(--radius-pill);
  border: 1px solid var(--border);
  background: var(--accent-tint);
  color: var(--accent-text);
  font-size: 11.5px;
  font-weight: 500;
}

/* A person with no photo: the same gradient letter as the sidebar and Team. */
.author-dot:not(.author-dot-bot):not(.author-avatar) {
  border: 0;
  background: linear-gradient(135deg, var(--lm-peach), var(--lm-plum));
  color: #fff;
}

/* LobsterMane's reply avatar is its Moodie face: no circle, no monogram — the
 * diamond fills the 26px slot and its expression performances may overshoot. */
.author-dot-bot {
  border: 0;
  background: none;
  color: inherit;
  overflow: visible;
}
.author-dot-bot .persona-face {
  width: 30px;
  height: 30px;
}

img.author-avatar {
  object-fit: cover;
  background: var(--surface-2);
}

.msg-author {
  color: var(--text);
  font-size: 14px;
  font-weight: 700;
  letter-spacing: -0.005em;
}

.msg-author-bot {
  color: var(--text);
}

.msg-time {
  margin-left: auto;
  font-variant-numeric: tabular-nums;
  color: var(--text-faint);
  font-size: 11px;
}

.msg-content {
  word-wrap: break-word;
  overflow-wrap: break-word;
  color: var(--text);
  font-size: 14.5px;
  line-height: 1.62;
}

.msg-content-collapsed {
  position: relative;
  max-height: 11rem;
  overflow: hidden;
  -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 1.75rem), transparent);
  mask-image: linear-gradient(to bottom, #000 calc(100% - 1.75rem), transparent);
}

.msg-expand {
  align-self: flex-start;
  margin: 2px 0 0;
  padding: 3px 5px;
  border: 0;
  border-radius: var(--radius-xs);
  background: transparent;
  color: var(--text-muted);
  font: inherit;
  font-size: 11.5px;
  cursor: pointer;
}

.msg-expand:hover {
  background: var(--hover);
  color: var(--text);
}

.msg-content a {
  color: var(--accent-text);
}

/* The person's own turn: a warm bubble on the right, tucked at the corner
   nearest its author. */
.msg-prompt {
  width: fit-content;
  max-width: min(600px, 90%);
  margin: 4px 0 24px auto;
  padding: 11px 16px 12px;
  border: 1px solid transparent;
  border-radius: 22px 22px 8px 22px;
  background: var(--surface-2);
}
.msg-prompt .msg-head {
  margin-left: 0;
}
.msg-prompt.msg {
  padding-left: 14px;
}
.msg-prompt > .msg-copy {
  top: 8px;
  right: 8px;
}
.msg-prompt:has(> .msg-copy) > .msg-head {
  padding-right: 22px;
}
.msg-prompt .author-dot {
  width: 20px;
  height: 20px;
  border-radius: var(--radius-pill);
  font-size: 10px;
}
.msg-prompt .msg-content {
  color: var(--text);
}

.msg-retry {
  background: none;
  border: none;
  color: var(--danger-text);
  font-family: inherit;
  font-size: inherit;
  font-weight: 500;
  cursor: pointer;
  padding: 0;
  text-decoration: none;
}

.msg-retry:hover {
  text-decoration: underline;
  text-underline-offset: 2px;
}

.msg-retry.msg-retry-neutral {
  color: var(--text-secondary);
}

.msg-content .chip {
  background: var(--accent-soft);
  color: var(--accent-text);
  border-radius: var(--radius-pill);
  padding: 0 7px;
  font-weight: 500;
  overflow-wrap: anywhere;
}

.md-attachment-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}

.md-attachment-chip .icon {
  flex: none;
  width: 12px;
  height: 12px;
}

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

.chat-markdown > :last-child {
  margin-bottom: 0;
}

.chat-markdown p {
  margin: 0 0 8px;
}

.chat-markdown h1,
.chat-markdown h2,
.chat-markdown h3,
.chat-markdown h4,
.chat-markdown h5,
.chat-markdown h6 {
  margin: 16px 0 7px;
  color: var(--text);
  font-weight: 500;
  line-height: 1.3;
  letter-spacing: -0.01em;
}

/* Headings are titles, so they take the display face at weight 500. */
.chat-markdown h1,
.chat-markdown h2,
.chat-markdown h3 {
  font-family: var(--font-display);
  letter-spacing: -0.02em;
}

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

.chat-markdown h2 {
  font-size: 17px;
}

.chat-markdown h3 {
  font-size: 15.5px;
}

.chat-markdown h4,
.chat-markdown h5,
.chat-markdown h6 {
  font-size: 14px;
}

.chat-markdown code {
  padding: 1px 4px;
  border: 1px solid color-mix(in srgb, var(--border) 78%, transparent);
  border-radius: 4px;
  background: color-mix(in srgb, var(--text) 5%, transparent);
  color: var(--text);
  font-family: var(--mono);
  font-size: 0.88em;
}

.chat-markdown blockquote {
  margin: 8px 0;
  padding: 1px 0 1px 12px;
  border-left: 2px solid var(--border-strong);
  color: var(--text-muted);
}

.chat-markdown ul,
.chat-markdown ol {
  margin: 7px 0 9px;
  padding-left: 24px;
}

.chat-markdown li {
  margin: 2px 0;
  padding-left: 2px;
}

.chat-markdown li > p {
  margin: 0;
}

.chat-markdown li > ul,
.chat-markdown li > ol {
  margin: 2px 0;
}

.chat-markdown .md-task-item {
  display: flex;
  gap: 7px;
  align-items: flex-start;
  margin-left: -20px;
  padding-left: 0;
  list-style: none;
}

.md-task-check {
  position: relative;
  flex: none;
  width: 14px;
  height: 14px;
  margin: 0.3em 0 0;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-xs);
  background: var(--surface);
}

.md-task-check.is-done {
  border-color: var(--ink-btn);
  background: var(--ink-btn);
}

.md-task-check.is-done::after {
  content: '';
  position: absolute;
  left: 4px;
  top: 1px;
  width: 4px;
  height: 8px;
  border: solid var(--text-inverse);
  border-width: 0 1.6px 1.6px 0;
  transform: rotate(45deg);
}

.md-task-copy {
  min-width: 0;
}

.chat-markdown hr {
  height: 1px;
  margin: 14px 0;
  border: 0;
  background: var(--border);
}

.md-table-wrap {
  max-width: 100%;
  margin: 9px 0;
  overflow-x: auto;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}

.chat-markdown table {
  width: 100%;
  min-width: 320px;
  border-collapse: collapse;
  font-size: 13px;
  line-height: 1.45;
}

/* Short cells (numbers, dates, labels) never break mid-value: the long
   cells wrap instead, at a readable width, and a table that still cannot
   fit scrolls. */
.chat-markdown .md-nowrap {
  white-space: nowrap;
}

.chat-markdown td:not(.md-nowrap),
.chat-markdown th:not(.md-nowrap) {
  min-width: 160px;
}

.chat-markdown th,
.chat-markdown td {
  padding: 7px 9px;
  border-right: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  text-align: left;
  vertical-align: top;
}

.chat-markdown th:last-child,
.chat-markdown td:last-child {
  border-right: 0;
}

.chat-markdown tbody tr:last-child td {
  border-bottom: 0;
}

.chat-markdown th {
  background: var(--surface-2);
  color: var(--text);
  font-weight: 500;
}

.chat-markdown .md-align-center {
  text-align: center;
}

.chat-markdown .md-align-right {
  text-align: right;
}

.md-code-block {
  position: relative;
  margin: 9px 0;
  overflow: hidden;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
}

.md-code-head {
  display: flex;
  min-height: 28px;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 4px 6px 4px 12px;
  border-bottom: 1px solid var(--border);
  color: var(--text-faint);
  font-family: var(--mono);
  font-size: 11px;
}

.md-code-streaming .md-code-label::after {
  content: ' · streaming';
  color: var(--text-faint);
}

.md-code-copy {
  flex: none;
  padding: 2px 9px;
  border: 0;
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--text-muted);
  font-family: var(--font);
  font-size: 11.5px;
  font-weight: 500;
  cursor: pointer;
  opacity: 0;
  transition:
    opacity 0.12s ease,
    color 0.12s ease,
    background 0.12s ease;
}

.md-code-block:hover .md-code-copy,
.md-code-copy:focus-visible {
  opacity: 1;
}

.md-code-copy:hover {
  background: var(--hover);
  color: var(--text-secondary);
}

.chat-markdown .md-code {
  margin: 0;
  padding: 10px 12px;
  overflow-x: auto;
  border: 0;
  border-radius: 0;
  background: transparent;
  font-family: var(--mono);
  font-size: 12px;
  line-height: 1.55;
  white-space: pre;
}

.chat-markdown .md-code code {
  padding: 0;
  border: 0;
  background: transparent;
  color: inherit;
  font-size: inherit;
}

.md-file-link {
  text-decoration: none;
  text-underline-offset: 2px;
}

.md-file-link:hover {
  text-decoration: underline;
}

.md-file-link code {
  color: var(--accent-text);
}

.md-subtext {
  color: var(--text-faint);
  font-size: 11.5px;
}

@media (hover: none) {
  .md-code-copy {
    opacity: 0.8;
  }
}

@keyframes pulse {
  0%,
  100% {
    opacity: 1;
    transform: scale(1);
  }
  50% {
    opacity: 0.3;
    transform: scale(0.8);
  }
}

/* The face sits in the avatar column and the text starts on the reply column. */
.chat-working {
  display: flex;
  align-items: center;
  gap: 8px;
  width: min(720px, 100%);
  margin: 0 auto;
  padding: 0 0 18px 6px;
  color: var(--text-muted);
}

.chat-working-text {
  color: var(--text-muted);
  font-family: var(--mono);
  font-size: 11px;
}

.chat-working-elapsed {
  flex: none;
  color: var(--text-faint);
  font-family: var(--mono);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
}

.chat-working-elapsed:not(:empty)::before {
  content: '· ';
}

/* Sticks to the bottom of the transcript viewport, so it never covers the
   composer or an ask above it, whatever their height. */
.chat-jump {
  position: sticky;
  bottom: 14px;
  z-index: 5;
  display: block;
  width: fit-content;
  height: 30px;
  margin: -30px auto 0;
  padding: 0 14px;
  border: 1px solid var(--border-control);
  border-radius: var(--radius-pill);
  background: var(--surface);
  color: var(--text-secondary);
  font-family: inherit;
  font-size: 12.5px;
  font-weight: 500;
  cursor: pointer;
  box-shadow: var(--shadow-float);
}
.chat-jump:hover {
  border-color: var(--border-strong);
  color: var(--text);
}

.chat-composer {
  flex-shrink: 0;
  padding: 10px 24px 20px;
}

.chat-queue-dock {
  width: min(720px, 100%);
  margin: 0 auto -1px;
  padding: 0 0 4px;
  border: 1px solid var(--border-strong);
  border-bottom: 0;
  border-radius: var(--radius) var(--radius) 0 0;
  background: var(--surface-muted);
  max-height: 168px;
  overflow-y: auto;
}
.chat-queue-dock[hidden] {
  display: none;
}
.chat-queue-dock:not([hidden]) + .chat-composer-box {
  border-top-left-radius: var(--radius-sm);
  border-top-right-radius: var(--radius-sm);
}
.chat-queue-head {
  display: flex;
  gap: 6px;
  padding: 8px 14px 6px;
  font-size: 12px;
  font-weight: 500;
  color: var(--text-muted);
  border-bottom: 1px solid var(--border);
}

.chat-queue-head-failed {
  color: var(--danger-text);
}

.chat-queue-attachments,
.msg-pending-attachments > span {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}

.chat-queue-attachments .icon,
.msg-pending-attachments .icon {
  width: 12px;
  height: 12px;
}
.chat-queue-item {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 2px 10px;
  padding: 8px 14px 4px;
  font-size: 13.5px;
  color: var(--text);
  min-width: 0;
}
/* On a narrow screen the status drops under the text instead of crushing it. */
.chat-queue-text {
  flex: 1 1 160px;
  min-width: 0;
}
.chat-queue-attachments,
.chat-queue-status {
  flex-shrink: 0;
  font-size: 12px;
  color: var(--text-faint);
}
.chat-queue-status-error {
  color: var(--danger-text);
  white-space: nowrap;
}
.chat-queue-item-failed .chat-queue-text {
  color: var(--text-secondary);
}

/* Viktor's message box: a white slab on a hairline with a soft float; focus
   warms the edge instead of drawing a hard ring. */
.chat-composer-box {
  display: flex;
  flex-direction: column;
  width: min(720px, 100%);
  margin: 0 auto;
  padding: 12px 14px 10px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-xl);
  background: var(--surface);
  box-shadow: var(--shadow-float);
  transition:
    border-color 0.15s ease,
    box-shadow 0.15s ease;
}

.chat-composer-box:focus-within {
  border-color: var(--accent-line);
  box-shadow:
    0 0 0 4px var(--accent-soft),
    0 12px 32px -14px color-mix(in srgb, var(--accent) 35%, transparent);
}

.chat-input {
  max-height: 180px;
  resize: none;
  line-height: 1.55;
  min-height: 34px;
  padding: 5px 4px;
  border: 0;
  background: transparent;
  box-shadow: none;
  font-size: 14.5px;
}
.chat-input:focus {
  border: none;
  box-shadow: none;
}

.chat-composer-row {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 6px;
}

/* Every control on the composer row is one compact height (--control-h-sm),
   level with Send. */
.chat-composer-row > .attach-btn {
  width: var(--control-h-sm);
  height: var(--control-h-sm);
}

/* The hint is the first thing to give way when the row gets tight: under
   640px of composer it goes rather than ending in an ellipsis. */
.chat-composer-box {
  container: composer / inline-size;
}
@container composer (max-width: 640px) {
  .chat-composer-hint {
    display: none;
  }
}
.chat-composer-hint {
  flex: 0 1000 auto;
  min-width: 0;
  color: var(--text-faint);
  font-size: 11.5px;
}

.chat-stop-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--text-secondary);
  border-color: var(--border-strong);
}

.chat-stop-btn:hover:where(:not(:disabled)) {
  color: var(--danger-text);
  border-color: var(--danger-line);
  background: var(--danger-soft);
}

/* "Stopping…" reads as in progress, not faded out. */
.chat-stop-btn[aria-busy='true']:disabled {
  opacity: 1;
  color: var(--text-muted);
  cursor: progress;
}

.chat-stop-icon {
  width: 8px;
  height: 8px;
  border-radius: 2px;
  background: currentColor;
}

.chat-composer-spacer {
  flex: 1;
}

.chat-stash-control {
  position: relative;
  display: inline-flex;
  flex: none;
}

.chat-stash-button {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  height: var(--control-h-sm);
  padding: 0 10px;
  border: 1px solid transparent;
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--text-muted);
  font-family: inherit;
  font-size: 12px;
  cursor: pointer;
}

.chat-stash-button:hover,
.chat-stash-button[aria-expanded='true'],
.chat-stash-button.has-stash {
  border-color: var(--border);
  color: var(--text-secondary);
}

.chat-stash-button:disabled {
  cursor: not-allowed;
  opacity: var(--disabled-opacity);
}

.chat-stash-button .icon,
.chat-stash-save .icon,
.chat-stash-entry-main .icon {
  width: 12px;
  height: 12px;
  flex: none;
}

.chat-stash-count {
  min-width: 16px;
  padding: 1px 4px;
  border-radius: var(--radius-pill);
  background: var(--surface-2);
  color: var(--text-muted);
  font-size: 10.5px;
  font-variant-numeric: tabular-nums;
  line-height: 1.4;
  text-align: center;
}

.chat-stash-count[hidden] {
  display: none;
}

/* Same frame as the context menu: a card-hairline float with pill-ish rows. */
.chat-stash-menu {
  position: absolute;
  bottom: calc(100% + 9px);
  left: 0;
  z-index: 40;
  width: min(370px, calc(100vw - 54px));
  overflow: hidden;
  border: 1px solid var(--border-card);
  border-radius: var(--radius-xl);
  background: var(--surface);
  box-shadow: var(--shadow-float);
}

.chat-stash-menu[hidden] {
  display: none;
}

.chat-stash-menu-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 16px 6px;
  color: var(--text-faint);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.chat-stash-save {
  display: flex;
  width: calc(100% - 12px);
  min-height: 34px;
  align-items: center;
  gap: 8px;
  margin: 0 6px 6px;
  padding: 6px 10px;
  border: 0;
  border-radius: var(--radius-md);
  background: transparent;
  color: var(--text-secondary);
  font-family: inherit;
  font-size: 13px;
  font-weight: 500;
  text-align: left;
  cursor: pointer;
}

.chat-stash-save:hover:not(:disabled) {
  background: var(--hover);
  color: var(--text);
}

.chat-stash-save:disabled {
  cursor: not-allowed;
  opacity: var(--disabled-opacity);
}

.chat-stash-save kbd {
  margin-left: auto;
  color: var(--text-faint);
  font-family: inherit;
  font-size: 11px;
}

.chat-stash-list {
  max-height: 250px;
  padding: 6px;
  overflow-y: auto;
  border-top: 1px solid var(--border);
}

.chat-stash-empty {
  padding: 10px;
  color: var(--text-faint);
  font-size: 12.5px;
}

.chat-stash-entry {
  display: flex;
  align-items: center;
  gap: 2px;
  border-radius: var(--radius-md);
}

.chat-stash-entry:hover,
.chat-stash-entry:focus-within {
  background: var(--hover);
}

.chat-stash-entry-main {
  display: flex;
  min-width: 0;
  min-height: 34px;
  flex: 1;
  align-items: center;
  gap: 7px;
  padding: 6px 5px 6px 10px;
  border: 0;
  background: transparent;
  color: var(--text-secondary);
  font-family: inherit;
  text-align: left;
  cursor: pointer;
}

.chat-stash-entry-copy {
  min-width: 0;
  flex: 1;
  font-size: 12.5px;
}

.chat-stash-entry-files {
  flex: none;
  color: var(--text-faint);
  font-size: 11px;
}

.chat-stash-delete {
  width: 25px;
  height: 25px;
  flex: none;
  margin-right: 4px;
  padding: 0;
  border: 0;
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--text-faint);
  font-family: inherit;
  font-size: 16px;
  line-height: 1;
  cursor: pointer;
  opacity: 0;
}

.chat-stash-entry:hover .chat-stash-delete,
.chat-stash-entry:focus-within .chat-stash-delete {
  opacity: 1;
}

.chat-stash-delete:hover {
  background: var(--danger-soft);
  color: var(--danger-text);
}

@media (max-width: 620px) {
  .chat-stash-label {
    display: none;
  }

  /* Anchored to the composer box, not their tiny triggers, so neither
     popover can run past the screen edge. */
  .chat-composer-box {
    position: relative;
  }

  .chat-composer-box .chat-stash-control,
  .chat-composer-box .chat-model-slot,
  .chat-composer-box .chat-context-meter {
    position: static;
  }

  .chat-composer-box .chat-stash-menu,
  .chat-composer-box .chat-context-detail {
    left: 8px;
    right: 8px;
    bottom: calc(100% + 8px);
    width: auto;
    max-width: none;
  }
}

.chat-model-slot {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  position: relative;
}

.chat-model-slot .chat-model-select {
  width: auto;
  max-width: 240px;
  min-height: var(--control-h-sm);
  height: var(--control-h-sm);
  padding: 0 28px 0 12px;
  font-size: 12px;
  font-weight: 500;
  color: var(--text-secondary);
  background-color: var(--surface-2);
  border-color: transparent;
  border-radius: var(--radius-pill);
}

.chat-model-slot .chat-model-select:hover {
  color: var(--text);
  border-color: var(--border-control);
}

/* Until the chat's own model is known, rather than flash the default. */
.chat-model-select.is-pending {
  visibility: hidden;
}

.chat-context-meter {
  --context-used: 0%;
  position: relative;
  align-items: center;
  justify-content: center;
  height: var(--control-h-sm);
  border: 0;
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--text-faint);
  cursor: default;
}

.chat-context-meter:hover,
.chat-context-meter:focus-visible {
  background: var(--hover);
  color: var(--text-muted);
}

.chat-context-meter {
  gap: 4px;
  width: auto;
  padding: 0 6px;
}

.chat-context-pct {
  color: var(--text-faint);
  font-size: 11.5px;
  font-variant-numeric: tabular-nums;
}

.chat-context-meter.near-limit .chat-context-pct {
  color: var(--danger-text);
}

.chat-context-ring {
  flex: none;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: conic-gradient(var(--text-muted) var(--context-used), var(--border) 0);
  -webkit-mask: radial-gradient(circle, transparent 46%, #000 48%);
  mask: radial-gradient(circle, transparent 46%, #000 48%);
}

.chat-context-meter.near-limit .chat-context-ring {
  background: conic-gradient(var(--danger) var(--context-used), var(--border) 0);
}

.chat-context-detail {
  position: absolute;
  z-index: 40;
  right: 0;
  bottom: calc(100% + 8px);
  display: none;
  width: 270px;
  padding: 12px 14px;
  border: 1px solid var(--border-card);
  border-radius: var(--radius-md);
  background: var(--surface);
  box-shadow: var(--shadow-float);
  color: var(--text-muted);
  font-size: 12px;
  line-height: 1.5;
  text-align: left;
}

.chat-context-detail strong,
.chat-context-detail span {
  display: block;
}

.chat-context-detail strong {
  margin-bottom: 3px;
  color: var(--text-secondary);
  font-weight: 500;
}

.chat-context-detail-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}

.chat-context-detail-head strong,
.chat-context-detail-head span {
  display: inline;
}

.chat-context-detail-head span {
  max-width: 150px;
  color: var(--text-faint);
}

.chat-context-meter:hover .chat-context-detail,
.chat-context-meter:focus-visible .chat-context-detail {
  display: block;
}

/* ---- Claude Code-style live transcript (.cc-*), inline in the chat flow ---- */

.cc-run {
  /* The run lines up with the messages: its glyphs sit in the 30px avatar
     column and its text starts on the message text column. */
  --cc-glyph: 30px;
  --cc-glyph-gap: 12px;
  --cc-gutter: calc(var(--cc-glyph) + var(--cc-glyph-gap));
  font-family: var(--mono);
  font-size: 12.5px;
  line-height: 1.6;
  margin: 8px 0;
  padding: 5px 0;
  border-radius: var(--radius-xs);
  background: transparent;
  border: 0;
}

.cc-run-finished {
  opacity: 0.88;
}

.cc-head {
  display: flex;
  align-items: baseline;
  gap: 7px;
  min-height: 20px;
  user-select: none;
}

.cc-head[role='button'] {
  cursor: pointer;
}

.cc-head-done:hover .cc-head-word {
  color: var(--text);
}

.cc-head[role='button']:hover .cc-chevron {
  border-color: var(--text-muted);
}

.cc-head[role='button']:focus-visible,
.cc-clickable:focus-visible {
  outline: var(--focus-outline);
  outline-offset: 2px;
  border-radius: var(--radius-xs);
}

.cc-head-failed .cc-done-dot,
.cc-head-error .cc-done-dot {
  color: var(--danger);
}

.cc-head-interrupted .cc-done-dot,
.cc-head-cancelled .cc-done-dot,
.cc-head-stopped .cc-done-dot {
  color: var(--warn);
}

.cc-spin {
  color: var(--accent);
  width: 1.1em;
  display: inline-block;
  text-align: center;
}

/* The head's gap already spaces the word: the glyph box makes up the rest. */
.cc-head > .cc-bullet,
.cc-head > .cc-spin {
  flex: none;
  width: var(--cc-glyph);
  margin-right: calc(var(--cc-glyph-gap) - 7px);
}

/* One line at any width: the meta line gives way first, then the label
   (capped so the bullet and chevron always keep their room). */
.cc-head-word {
  flex-shrink: 0;
  max-width: calc(100% - 40px);
  color: var(--text-secondary);
  font-weight: 500;
}

.cc-glow {
  background-image: linear-gradient(
    90deg,
    color-mix(in srgb, var(--accent-text) 45%, var(--bg)) 35%,
    var(--accent-text) 50%,
    color-mix(in srgb, var(--accent-text) 45%, var(--bg)) 65%
  );
  background-size: 200% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  animation: shimmer-text 1.4s linear infinite;
}

@keyframes cc-pulse {
  0%,
  100% {
    opacity: 1;
  }
  50% {
    opacity: 0.55;
  }
}

.cc-head-meta {
  flex-shrink: 1000;
  min-width: 0;
  color: var(--text-faint);
  font-size: 11.5px;
}

.cc-chevron {
  flex: none;
  margin-left: 4px;
  width: 8px;
  height: 8px;
  border-right: 1.5px solid var(--text-faint);
  border-bottom: 1.5px solid var(--text-faint);
  transform: rotate(-45deg);
  transition: transform 0.15s ease;
  align-self: center;
}

.cc-chevron.open {
  transform: rotate(45deg);
}

.cc-body {
  margin-top: 8px;
  display: flex;
  flex-direction: column;
  gap: 7px;
}

.cc-entries {
  display: flex;
  flex-direction: column;
  gap: 7px;
}

.cc-plan-card {
  display: grid;
  gap: 5px;
  margin: 0 0 2px var(--cc-gutter);
  padding: 8px 10px;
  max-width: min(620px, calc(100% - var(--cc-gutter)));
  border: 1px solid color-mix(in srgb, var(--border) 72%, transparent);
  border-radius: var(--radius-sm);
  background: color-mix(in srgb, var(--surface-muted) 42%, transparent);
  color: var(--text-muted);
  font-family: var(--font);
  font-size: 12px;
}

.cc-plan-head {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  color: var(--text-faint);
}

.cc-plan-head strong {
  color: var(--text-secondary);
  font-weight: 500;
}

.cc-plan-explanation {
  color: var(--text-faint);
}

.cc-plan-markdown {
  max-height: 360px;
  overflow: auto;
  color: var(--text-muted);
  font-size: 12px;
  line-height: 1.5;
}

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

.cc-plan-markdown > :last-child {
  margin-bottom: 0;
}

.cc-plan-steps {
  display: grid;
  gap: 3px;
}

.cc-plan-step {
  display: grid;
  grid-template-columns: 12px minmax(0, 1fr);
  gap: 6px;
}

.cc-plan-step-completed {
  color: var(--text-faint);
}

.cc-plan-step-in_progress .cc-plan-mark {
  color: var(--accent-text);
}

.cc-plan-step-completed .cc-plan-mark {
  color: var(--ok);
}

.cc-tail-toggle {
  align-self: flex-start;
  min-height: 26px;
  margin: 0 0 1px calc(var(--cc-gutter) - 9px);
  padding: 2px 9px;
  border: 0;
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--text-faint);
  font: inherit;
  font-size: 11.5px;
  text-align: left;
  cursor: pointer;
}

.cc-tail-toggle:hover {
  background: var(--hover);
  color: var(--text-muted);
}

.cc-changes {
  margin: 5px 0 0 calc(var(--cc-gutter) - 9px);
  max-width: min(620px, calc(100% - var(--cc-gutter) + 9px));
}

.cc-changes-toggle {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 26px;
  padding: 2px 9px;
  border: 0;
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--text-faint);
  font: inherit;
  font-size: 11.5px;
  cursor: pointer;
}

.cc-changes-toggle:hover,
.cc-changed-file:hover {
  background: var(--hover);
  color: var(--text-secondary);
}

.cc-changes-mark {
  color: var(--ok);
  font-weight: 500;
}

.cc-changes-chevron {
  width: 6px;
  height: 6px;
  margin: 0 2px 2px 3px;
  border-right: 1px solid currentColor;
  border-bottom: 1px solid currentColor;
  transform: rotate(45deg);
  transition: transform 0.15s ease;
}

.cc-changes-chevron.open {
  margin-bottom: -2px;
  transform: rotate(225deg);
}

/* Inside a run every disclosure turns like the run's own: › shut, ⌄ open. */
.cc-run .cc-changes-chevron {
  margin: 0 2px 0 3px;
  transform: rotate(-45deg);
}

.cc-run .cc-changes-chevron.open {
  margin: 0 2px 2px 3px;
  transform: rotate(45deg);
}

.cc-diff-add {
  color: var(--ok-text);
}

.cc-diff-del {
  color: var(--danger-text);
}

.cc-changes-list {
  display: flex;
  flex-direction: column;
  gap: 1px;
  margin-top: 2px;
  padding-left: 2px;
}

.cc-changes-list[hidden] {
  display: none;
}

.cc-changed-file {
  display: grid;
  grid-template-columns: 16px minmax(0, 1fr) auto;
  align-items: center;
  gap: 7px;
  width: 100%;
  min-height: 28px;
  padding: 3px 7px;
  border: 0;
  border-radius: var(--radius-xs);
  background: transparent;
  color: var(--text-muted);
  font: inherit;
  font-size: 11.5px;
  text-align: left;
  cursor: pointer;
}

.cc-changed-file:disabled {
  opacity: 0.62;
  cursor: default;
}

.cc-changed-file:disabled:hover {
  background: transparent;
  color: var(--text-muted);
}

.cc-changed-file .icon {
  color: var(--text-faint);
}

.cc-changed-file-action,
.cc-changes-note {
  color: var(--text-faint);
  font-size: 10.5px;
}

.cc-changes-note {
  padding: 3px 7px 1px 30px;
}

/* ---- Loaded context (stacked context-window bar + section breakdown) ---- */

.cc-context {
  margin: 5px 0 0 calc(var(--cc-gutter) - 9px);
  max-width: min(620px, calc(100% - var(--cc-gutter) + 9px));
}

.cc-ctx-mark {
  color: var(--text-muted);
  font-size: 12px;
  line-height: 1;
}

.cc-ctx-body {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 4px 0 2px 7px;
  padding: 10px 12px 9px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  font-size: 11.5px;
}

.cc-ctx-body[hidden] {
  display: none;
}

.cc-ctx-bar {
  display: flex;
  height: 22px;
  overflow: hidden;
  border: 1px solid var(--border-strong);
  border-radius: 3px;
  background: var(--surface-2);
}

.cc-ctx-seg {
  flex: 0 0 0%;
  min-width: 0;
  transition: flex-basis 0.25s ease;
}

.cc-ctx-seg + .cc-ctx-seg {
  box-shadow: inset 1px 0 0 color-mix(in srgb, var(--surface) 70%, transparent);
}

.cc-ctx-kind-system {
  background: #5b5970;
}

.cc-ctx-kind-tools {
  background: #a29fb5;
}

.cc-ctx-kind-agents,
.cc-ctx-kind-memory {
  background: #c9a45c;
}

.cc-ctx-kind-other {
  background: #8a8799;
}

.cc-ctx-kind-mcp {
  background: #6f86d6;
}

.cc-ctx-kind-skills {
  background: #4fae86;
}

.cc-ctx-kind-messages {
  background: var(--accent);
}

.cc-ctx-window {
  height: 4px;
  margin-top: -2px;
  overflow: hidden;
  border-radius: 2px;
  background: var(--surface-2);
}

.cc-ctx-window-fill {
  display: block;
  height: 100%;
  min-width: 2px;
  border-radius: 2px;
  background: var(--text-faint);
}

.cc-ctx-bar-caption {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  color: var(--text-muted);
  font-size: 11px;
}

.cc-ctx-bar-caption > span:last-child {
  color: var(--text-faint);
  font-family: var(--mono);
  font-size: 10.5px;
}

.cc-ctx-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 14px;
  color: var(--text-secondary);
  font-size: 11px;
}

.cc-ctx-legend-item {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.cc-ctx-legend-size {
  color: var(--text-faint);
  font-variant-numeric: tabular-nums;
}

.cc-ctx-swatch {
  display: inline-block;
  width: 9px;
  height: 9px;
  flex: none;
  border-radius: 50%;
}

.cc-ctx-sections {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin-top: 2px;
  border-top: 1px solid var(--border);
  padding-top: 6px;
}

.cc-ctx-section-head {
  display: grid;
  grid-template-columns: 9px minmax(0, 1fr) auto 12px;
  align-items: center;
  gap: 8px;
  width: 100%;
  min-height: 26px;
  padding: 3px 5px;
  border: 0;
  border-radius: var(--radius-xs);
  background: transparent;
  color: var(--text-secondary);
  font: inherit;
  font-size: 11.5px;
  text-align: left;
  cursor: pointer;
}

.cc-ctx-section-head:not(:disabled):hover {
  background: var(--hover);
}

.cc-ctx-section-head:disabled {
  cursor: default;
}

.cc-ctx-section-label {
  display: inline-flex;
  align-items: baseline;
  gap: 7px;
  min-width: 0;
}

.cc-ctx-section-label strong {
  font-weight: 500;
  color: var(--text);
}

.cc-ctx-section-count,
.cc-ctx-section-size {
  color: var(--text-faint);
  font-size: 10.5px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.cc-ctx-chevron-spacer {
  width: 12px;
}

.cc-ctx-items {
  display: flex;
  flex-direction: column;
  gap: 1px;
  margin: 0 0 6px 22px;
  padding: 4px 0 4px 8px;
  border-left: 1px solid var(--border);
}

.cc-ctx-items[hidden] {
  display: none;
}

.cc-ctx-item {
  display: grid;
  grid-template-columns: minmax(0, auto) minmax(0, 1fr) auto;
  align-items: baseline;
  gap: 8px;
  padding: 2px 4px;
  font-size: 11px;
}

.cc-ctx-item-name {
  color: var(--text-secondary);
  font-family: var(--mono);
  font-size: 10.5px;
}

.cc-ctx-item-detail {
  color: var(--text-faint);
}

.cc-ctx-item-size {
  color: var(--text-faint);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.cc-ctx-note {
  color: var(--text-faint);
  font-size: 10.5px;
  line-height: 1.4;
}

.cc-entry {
  display: block;
  overflow-wrap: anywhere;
}

.cc-bullet {
  display: inline-block;
  flex: none;
  width: var(--cc-glyph);
  margin-right: var(--cc-glyph-gap);
  color: var(--text-secondary);
  text-align: center;
}

/* Status lines keep their dot in the glyph column too. */
.cc-status,
.cc-task {
  display: flex;
  align-items: baseline;
}

.cc-dim {
  color: var(--text-faint);
}

/* Streamed assistant text keeps its bullet on the first line. */
.cc-assistant {
  display: flex;
  align-items: baseline;
}

.cc-assistant .cc-md {
  flex: 1;
  min-width: 0;
}

.cc-md p {
  margin: 0 0 6px;
}

.cc-md p:last-child {
  margin-bottom: 0;
}

.cc-md pre {
  background: color-mix(in srgb, var(--text) 6%, transparent);
  padding: 8px 10px;
  border-radius: var(--radius-xs);
  overflow-x: auto;
  margin: 6px 0;
}

.cc-think-head {
  color: var(--text-faint);
}

.cc-think-body {
  font-family: var(--font);
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--text-secondary);
  margin: 3px 0 4px calc(var(--cc-glyph) / 2 - 1px);
  padding: 1px 0 1px calc(var(--cc-gutter) - var(--cc-glyph) / 2 - 1px);
  border-left: 2px solid var(--border-strong);
}

.cc-status {
  color: var(--text-faint);
}

.cc-task-fleet-line {
  display: flex;
  align-items: baseline;
  min-width: 0;
  color: var(--text-faint);
  font-size: 11.5px;
}

.cc-task-fleet-mark {
  flex: none;
  width: var(--cc-glyph);
  margin-right: var(--cc-glyph-gap);
  color: var(--text-faint);
  text-align: center;
}

.cc-task-fleet-name {
  flex: none;
  color: var(--text-muted);
  font-weight: 500;
}

.cc-task-fleet-meta {
  min-width: 0;
}

.cc-task-fleet-running .cc-task-fleet-mark {
  color: var(--accent);
  animation: cc-pulse 1.2s ease-in-out infinite;
}

.cc-task-fleet-failed .cc-task-fleet-mark,
.cc-task-fleet-failed .cc-task-fleet-meta {
  color: var(--danger);
}

.cc-task-fleet-completed .cc-task-fleet-mark {
  color: var(--ok);
}

.cc-tool-line {
  display: flex;
  align-items: baseline;
  gap: 0;
  min-width: 0;
}

.cc-clickable {
  cursor: pointer;
}

.cc-clickable:hover .cc-tool-name {
  text-decoration: underline;
}

.cc-tool-dot {
  color: var(--ok);
}

.cc-tool-running .cc-tool-dot {
  color: var(--accent);
  animation: cc-pulse 1.2s ease-in-out infinite;
}

.cc-tool-error .cc-tool-dot {
  color: var(--danger);
}

.cc-tool-stopped .cc-tool-dot,
.cc-tool-cancelled .cc-tool-dot,
.cc-tool-unknown .cc-tool-dot,
.cc-tool-incomplete .cc-tool-dot {
  color: var(--text-faint);
  animation: none;
}

.cc-tool-name {
  color: var(--text);
  font-weight: 500;
  white-space: nowrap;
}

.cc-tool-arg {
  color: var(--text-muted);
  margin-left: 0.6ch;
}

.cc-tool-outcome {
  flex: none;
  color: var(--text-faint);
  /* Keep the leading space of " · failed" at the start of the flex item. */
  white-space: pre;
}

.cc-tool-error .cc-tool-outcome {
  color: var(--danger);
}

.cc-result-line {
  color: var(--text-faint);
  margin-left: calc(var(--cc-gutter) - 9px);
  display: flex;
  align-items: baseline;
  gap: 7px;
  min-width: 0;
}

.cc-result-more {
  flex: none;
  color: var(--text-faint);
}

.cc-elbow {
  flex: none;
}

.cc-payload {
  margin: 6px 0 2px var(--cc-gutter);
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  max-height: 260px;
  overflow: auto;
  font-size: 11.5px;
  white-space: pre-wrap;
}

.chat-empty-pane h2 {
  margin: 0;
  color: var(--text);
  font-family: var(--font-display);
  font-size: 20px;
  font-weight: 500;
  letter-spacing: -0.02em;
  line-height: 1.2;
}
/* Reading pane placeholder for an empty Pinned/Archived view. */
.chat-empty-pane {
  margin: auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  max-width: 340px;
  padding: 36px;
  text-align: center;
  color: var(--text-muted);
}

.chat-empty-pane .icon {
  width: 26px;
  height: 26px;
  margin-bottom: 4px;
  color: var(--text-faint);
}

.chat-empty-pane p {
  margin: 0;
  font-size: 13.5px;
}

/* Bots with no chat to show: the head is there for a phone's roster button. */
@media (min-width: 601px) {
  .bots-pane-head {
    display: none;
  }
}

.chat-empty-pane .btn {
  margin-top: 12px;
}

.chat-empty-pane .btn .icon {
  width: 14px;
  height: 14px;
  margin: 0;
  color: currentColor;
}

.chat-list-actions .btn[aria-busy='true'],
.chat-empty-pane .btn[aria-busy='true'] {
  cursor: progress;
}

/* The first load failed: the page-state look, where the loader was, without
   a card of its own inside the chat card. */
.grid-empty.chat-load-error {
  max-width: 460px;
  margin: 12vh auto 0;
  padding: 24px 20px;
  border: 0;
  background: transparent;
  box-shadow: none;
}

@media (max-width: 600px) {
  .grid-empty.chat-load-error {
    margin-top: 8vh;
  }
  .chat-load-error .grid-empty-title {
    font-size: 21px;
  }
}

/* First open of a conversation, before its history arrives. */
.chat-loading {
  display: flex;
  justify-content: center;
  margin: 18vh auto 0;
  color: var(--text-muted);
  font-size: 13px;
}

/* ============ Context menu ============ */

.ctx-menu {
  position: fixed;
  z-index: 220;
  min-width: 200px;
  padding: 6px;
  border: 1px solid var(--border-card);
  border-radius: var(--radius-xl);
  background: var(--surface);
  box-shadow: var(--shadow-float);
  animation: ctx-menu-in 0.14s var(--ease-out);
}

@keyframes ctx-menu-in {
  from {
    opacity: 0;
    transform: translateY(-3px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

/* Opened above its button: it rises toward it instead. */
.ctx-menu.is-above {
  animation-name: ctx-menu-in-above;
}

@keyframes ctx-menu-in-above {
  from {
    opacity: 0;
    transform: translateY(3px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

.ctx-item {
  display: flex;
  align-items: center;
  gap: 9px;
  width: 100%;
  padding: 8px 12px;
  border: 0;
  border-radius: var(--radius-md);
  background: transparent;
  color: var(--text);
  font-family: inherit;
  font-size: 13.5px;
  font-weight: 500;
  text-align: left;
  cursor: pointer;
}

.ctx-item:hover,
.ctx-item:focus-visible {
  background: var(--hover);
  color: var(--text);
  outline: none;
  box-shadow: none;
}

.ctx-item .icon {
  width: 14px;
  height: 14px;
  flex-shrink: 0;
  color: var(--text-faint);
}

.ctx-item:hover .icon,
.ctx-item:focus-visible .icon {
  color: var(--text-muted);
}

/* An item with a hint: the label, and what it does on a quiet second line;
   the icon keeps to the label's line. */
.ctx-item:has(.ctx-item-sub) {
  align-items: flex-start;
  padding-top: 9px;
  padding-bottom: 9px;
}
.ctx-item:has(.ctx-item-sub) .icon {
  margin-top: 3px;
}
.ctx-item-text {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
}
.ctx-item-sub {
  color: var(--text-muted);
  font-size: 12px;
  font-weight: 400;
}

.ctx-item.danger {
  color: var(--danger-text);
}

.ctx-item[aria-disabled='true'],
.ctx-item[aria-disabled='true']:hover {
  background: transparent;
  color: var(--text-faint);
  cursor: default;
}

.ctx-item[aria-disabled='true']:focus-visible {
  background: var(--hover);
  color: var(--text-faint);
}

.ctx-item.danger .icon {
  color: var(--danger-text);
}

.ctx-item.danger:hover,
.ctx-item.danger:focus-visible {
  background: var(--danger-soft);
  color: var(--danger-text);
}

.ctx-sep {
  height: 1px;
  margin: 4px 6px;
  background: var(--border);
}

/* ============ Usage ============ */

.usage-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  border-top: 1px solid var(--border);
}

.usage-account {
  padding: 20px 28px;
  border-right: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  margin-right: -1px;
  margin-bottom: -1px;
}

.usage-account-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 16px;
}

/* One person's usage: Models used takes the whole row. */
.usage-account-wide {
  grid-column: 1 / -1;
}

/* A state that stands in for the grid's columns spans all of them, under
   the grid's own divider. */
.usage-grid > .card-empty,
.usage-grid > .card-load-error,
.usage-grid > .usage-loading {
  grid-column: 1 / -1;
  border-top: 0;
}

/* A filter change keeps the rows, dimmed, until the new ones land. */
.usage-grid.is-loading {
  opacity: 0.5;
  pointer-events: none;
  transition: opacity 0.15s ease;
}

.usage-loading {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 22px 28px;
  color: var(--text-muted);
  font-size: 13.5px;
}

/* An account whose limit check failed: the reason, and where to fix it. */
.usage-account-error {
  color: var(--danger-text);
}
.usage-account-fix {
  margin-top: 12px;
}

/* A Cursor billing bucket: name, spend, bar and detail, each on its own line
   so the bars line up across the row. */
.usage-bucket .meter-label {
  display: block;
  margin-bottom: 4px;
}
.usage-bucket .usage-spend {
  display: block;
  margin-bottom: 10px;
  font-family: var(--font-display);
  font-size: 20px;
  letter-spacing: -0.03em;
}
.usage-spend-limit {
  color: var(--text-muted);
  font-family: var(--font);
  font-size: 13px;
  font-weight: 400;
  letter-spacing: 0;
}

/* Model capacity: each provider's active accounts as one pool (renderUsage). */
.usage-pools {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr));
  border-top: 1px solid var(--border);
}

.usage-pool {
  min-width: 0;
  padding: 20px 28px 22px;
  border-right: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  margin-right: -1px;
  margin-bottom: -1px;
}

.usage-pool-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.usage-pool-title {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 2px 10px;
  min-width: 0;
}

.usage-pool-title h3 {
  margin: 0;
  font-family: var(--font-display);
  font-size: 20px;
  font-weight: 500;
  letter-spacing: -0.035em;
}

.usage-pool-count {
  color: var(--text-faint);
  font-size: 12px;
  white-space: nowrap;
}

.badge.usage-pool-pill {
  height: 24px;
  padding: 0 10px;
  font-size: 12px;
}

.usage-pool-headline {
  max-width: 62ch;
  margin: 8px 0 18px;
  color: var(--text-secondary);
  font-size: 13.5px;
  line-height: 1.5;
}

/* A provider with no pool keeps its column, quietly. */
.usage-pool-none .usage-pool-title h3 {
  color: var(--text-faint);
}
.usage-pool-none .usage-pool-headline {
  margin-bottom: 0;
  color: var(--text-muted);
}

/* First loads hold about their loaded height (capacity; five team rows;
   four cron rows), the spinner line at the top, so nothing under them jumps
   when the numbers land. */
.usage-capacity-loading {
  min-height: 300px;
}
.usage-grid.usage-team-first-load {
  min-height: 400px;
  align-content: start;
}
.usage-cron-first-load {
  min-height: 320px;
}

/* A filter change in flight: the summary dims with the rows. */
.usage-summary {
  transition: opacity 0.15s ease;
}
.usage-summary.is-loading {
  opacity: 0.5;
}
.usage-controls-spinner {
  align-self: center;
  margin-right: 2px;
}

/* A long Top spenders list: the first rows, and the rest on request. */
.usage-show-all {
  margin: 10px 0 0 -14px;
}

.usage-reset-credits {
  border-top: 1px solid var(--border);
  margin-top: 14px;
  padding-top: 12px;
}

.usage-reset-head {
  align-items: center;
  display: flex;
  justify-content: space-between;
  margin-bottom: 6px;
}

.usage-spend {
  font-variant-numeric: tabular-nums;
  color: var(--text);
  font-size: 13.5px;
  font-weight: 500;
  white-space: nowrap;
}

.usage-checked {
  margin-top: 8px;
}

.meter {
  margin-bottom: 17px;
}
.meter:last-child {
  margin-bottom: 0;
}

.meter-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 6px;
}

.meter-label {
  flex: 1 1 auto;
  min-width: 0;
  overflow-wrap: anywhere;
  color: var(--text-muted);
  font-weight: 500;
  font-size: 12.5px;
}

.meter-value {
  flex-shrink: 0;
  white-space: nowrap;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  font-size: 12.5px;
  color: var(--text);
}

.meter-bar {
  position: relative;
  overflow: hidden;
  border-radius: var(--radius-pill);
  height: 8px;
  background: var(--surface-2);
  box-shadow: inset 0 1px 1px rgba(26, 24, 43, 0.04);
}

.meter-status {
  display: inline-flex;
  align-items: center;
  gap: 7px;
}

.badge.meter-pill {
  height: 19px;
  padding: 0 7px;
  font-size: 11px;
}

/* Where usage lands at the reset at the current rate: the fill carried on in
   peach hatching (red when it runs past the limit), after Copilot Money's
   pace line and Sentry's projected spend. */
.meter-projection {
  position: absolute;
  top: 0;
  bottom: 0;
  background: repeating-linear-gradient(
    -45deg,
    color-mix(in srgb, var(--lm-peach) 62%, transparent) 0 3px,
    color-mix(in srgb, var(--lm-peach) 28%, transparent) 3px 6px
  );
}

.meter-projection.is-hot {
  background: repeating-linear-gradient(
    -45deg,
    color-mix(in srgb, var(--danger) 32%, transparent) 0 3px,
    color-mix(in srgb, var(--danger) 12%, transparent) 3px 6px
  );
}

.meter-note {
  margin-top: 6px;
  color: var(--text-muted);
  font-size: 12px;
  line-height: 1.4;
  font-variant-numeric: tabular-nums;
  text-wrap: pretty;
}

.meter-note-action {
  padding: 0;
  border: 0;
  border-radius: 4px;
  background: none;
  color: var(--accent-text);
  font: inherit;
  font-weight: 500;
  cursor: pointer;
}

.meter-note-action:hover {
  text-decoration: underline;
}

/* The window reset after the last reading: the bar shows the old window. */
.meter.is-stale .meter-bar {
  opacity: 0.45;
}

/* Fills glow from the accent's light step into the accent, like Viktor's
   chart strokes. */
.meter-fill {
  position: relative;
  height: 100%;
  transition: width 0.6s var(--ease-out);
  border-radius: var(--radius-pill);
}
.meter-ok {
  background: linear-gradient(90deg, var(--lm-orange-300), var(--lm-orange-500));
}
.meter-warning {
  background: linear-gradient(
    90deg,
    color-mix(in srgb, var(--warn) 62%, var(--surface)),
    var(--warn)
  );
}
.meter-danger {
  background: linear-gradient(
    90deg,
    color-mix(in srgb, var(--danger) 62%, var(--surface)),
    var(--danger)
  );
}

/* "Updated 5:19 PM · Check now", in the capacity card's header. */
.usage-toolbar {
  display: flex;
  flex-shrink: 0;
  align-items: center;
  justify-content: flex-end;
  gap: 12px;
}

/* ============ Identity onboarding ============ */

/* The Discord and Linear link screens sit on the sign-in canvas (.login-wrap),
   in a wider cut of its card: same mark, eyebrow pill and display title. */
.identity-card {
  width: min(560px, calc(100vw - 32px));
  padding: 36px;
  border: 0;
  border-radius: var(--radius-2xl);
  background: var(--surface);
  box-shadow:
    0 0 0 8px rgba(255, 255, 255, 0.55),
    var(--shadow-float);
  animation: lm-modal-in 0.5s var(--ease-out) both;
}

.identity-card h1 {
  margin: 12px 0 8px;
  font-family: var(--font-display);
  font-size: 32px;
  font-weight: 500;
  letter-spacing: -0.035em;
  line-height: 1.1;
}

.identity-card > p {
  margin: 0 0 18px;
  color: var(--text-muted);
  font-size: 14px;
  text-wrap: pretty;
}

.identity-card > input {
  margin-bottom: 10px;
}

.identity-results {
  max-height: 380px;
  overflow-y: auto;
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
}

/* An error fills the list's frame instead of nesting a second one in it. */
.identity-results > .alert {
  border: 0;
  border-radius: 0;
}

.identity-user {
  width: 100%;
  display: grid;
  /* minmax: a long name or handle wraps, so the chip at the end never
     leaves the list. */
  grid-template-columns: 34px minmax(0, 1fr) auto;
  align-items: center;
  gap: 10px;
  min-height: 56px;
  padding: 9px 12px;
  border: 0;
  border-bottom: 1px solid var(--border);
  background: transparent;
  color: var(--text);
  font-family: inherit;
  cursor: pointer;
  text-align: left;
}

.identity-user img,
.identity-avatar {
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: var(--grad-avatar);
  object-fit: cover;
  display: grid;
  place-items: center;
  color: #fff;
  font-size: 13px;
  font-weight: 500;
}

/* Wrapped, not cut short: people pick out their own handle. */
.identity-user .row-name,
.identity-user .row-sub {
  overflow-wrap: anywhere;
}
.identity-user:last-child {
  border-bottom: 0;
}
.identity-user:hover:not(:disabled) {
  background: var(--hover);
}
.identity-user:disabled {
  cursor: default;
  opacity: 0.5;
}

.identity-status:not(:empty) {
  margin: 10px 0;
}
.identity-note,
.identity-card > .identity-note {
  margin: 14px 0 0;
  color: var(--text-muted);
  font-size: 12px;
}
.identity-switch-account {
  margin-top: 18px;
  padding-top: 16px;
  border-top: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 10px;
}
.identity-switch-account .identity-note {
  margin: 0;
}
/* The ghost button's text lines up with the note above it. */
.identity-switch-account .btn-ghost {
  margin-inline-start: -14px;
}
/* Waiting on the Discord DM: the empty-state tile, a line, and a live loader. */
.identity-waiting {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 32px 24px 28px;
  text-align: center;
}
.identity-waiting h2 {
  margin: 0 0 4px;
  font-family: var(--font-display);
  font-size: 19px;
  font-weight: 500;
  letter-spacing: -0.02em;
}
.identity-waiting p {
  max-width: 380px;
  margin: 0 0 16px;
  color: var(--text-muted);
  font-size: 13.5px;
}
.identity-waiting > .btn {
  margin-top: 14px;
}
/* Under a Linear link's last word: its text lines up with the alert's edge. */
.identity-open-app {
  display: flex;
  margin: 12px 0 0 -14px;
}
@media (prefers-reduced-motion: reduce) {
  html .identity-card {
    animation: none;
  }
}

/* ============ Integrations ============ */

.ig-filter-wrap {
  flex-shrink: 0;
  width: 230px;
}

.ig-filter {
  height: 36px;
  min-height: 36px;
  padding-inline: 16px;
  font-size: 13.5px;
  border-radius: var(--radius-pill);
  background: var(--surface);
  border-color: var(--border-control);
}
.ig-filter:focus {
  background: var(--surface);
}

/* Apps once connected through Composio, to add back as MCP servers. */
.ig-phone-actions {
  flex-shrink: 0;
}

.card-header-text p.ig-phone-status {
  font-size: 13px;
}

.ig-phone-secret.is-set {
  color: var(--text);
}

.ig-phone-secret.is-missing {
  color: var(--text-muted);
}

.ig-previous-list {
  display: flex;
  flex-direction: column;
  border-top: 1px solid var(--border);
}

.ig-previous-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 28px;
}
.ig-previous-item + .ig-previous-item {
  border-top: 1px solid var(--border);
}
.ig-previous-item .ig-name {
  flex: 1;
  min-width: 0;
}

.ig-previous-scope {
  color: var(--text-muted);
  font-size: 11.5px;
  white-space: nowrap;
}
.ig-previous-actions {
  display: flex;
  flex-shrink: 0;
  align-items: center;
  gap: 4px;
}

.ig-sections {
  border-top: 1px solid var(--border);
}

/* Small-caps section labels, like Viktor's CONNECTED / POPULAR / ALL. */
.ig-subhead {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 18px 28px 8px;
  font-size: 11px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-muted);
}
.ig-subhead span {
  font-weight: 500;
  font-size: 11.5px;
  color: var(--text-muted);
  text-transform: none;
  letter-spacing: 0;
}
.ig-subhead ~ .ig-subhead {
  border-top: 1px solid var(--border);
  margin-top: 6px;
  padding-top: 18px;
}

.ig-list {
  padding-bottom: 4px;
}

.ig-item {
  border-bottom: 1px solid var(--border);
}
/* The last row shown ends the list: no divider, even when filtered. */
.ig-list > .ig-item:not(:has(~ .ig-item:not([hidden]))) {
  border-bottom: 0;
}

.ig-row {
  display: grid;
  grid-template-columns: 38px minmax(0, 1fr) 84px 120px minmax(112px, auto);
  align-items: center;
  gap: 14px;
  min-height: 62px;
  padding: 10px 28px;
  transition: background 0.1s ease;
}
.ig-row:hover {
  background: var(--surface-muted);
}

/* Integrations: no type column; an open row is tinted around its settings. */
.ig-row.integration-row {
  grid-template-columns: 38px minmax(0, 1fr) 132px auto;
}
.ig-item.is-open {
  background: var(--surface-muted);
}
.ig-item.is-open > .ig-row:hover {
  background: transparent;
}

/* Viktor's integration tiles: a parchment-to-white gradient square with an
   inner highlight and a soft drop, the logo floating in the middle. */
.ig-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 38px;
  height: 38px;
  border-radius: var(--radius-md);
  object-fit: contain;
}
img.ig-mark {
  background: var(--tile-bg);
  border: 1px solid var(--surface);
  box-shadow: var(--shadow-tile);
  padding: 7px;
}
.ig-mark-letter {
  border: 1px solid var(--surface);
  background: var(--tile-bg);
  box-shadow: var(--shadow-tile);
  color: var(--text-secondary);
  font-family: var(--font-display);
  font-size: 15px;
  font-weight: 500;
}

/* Team usage filters: two pills side by side at a fixed width, so a long
   name neither widens nor wraps them; on narrow screens they share the row. */
.usage-controls {
  display: flex;
  flex-wrap: nowrap;
  flex-shrink: 0;
  gap: 8px;
}
.usage-controls select.grid-select {
  width: 164px;
  text-overflow: ellipsis;
}
.usage-since {
  white-space: nowrap;
}
/* Phones: each filter gets a full-width line, so a name isn't cut short.
   (Specific enough to win over the 900px rules further down.) */
@media (max-width: 600px) {
  .card-header .usage-controls {
    flex-wrap: wrap;
  }
  .card-header .usage-controls select.grid-select {
    flex: 1 1 100%;
    width: 100%;
  }
  /* The dimmed summary and rows say it's loading; no line of its own. */
  .usage-controls-spinner {
    display: none;
  }
}

.usage-breakdown {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.ig-mark-wrap {
  display: inline-flex;
  flex-shrink: 0;
}

.ig-title {
  min-width: 0;
}

.ig-name-line {
  display: flex;
  align-items: baseline;
  gap: 8px;
  min-width: 0;
}

.ig-name {
  font-size: 13.5px;
  font-weight: 500;
  color: var(--text);
}

.ig-key {
  font-family: var(--mono);
  font-size: 10.5px;
  color: var(--text-faint);
  flex-shrink: 0;
}

/* Account label distinguishing multiple connections of the same app: plain
   secondary text, so the orange pill only ever means "limited to roles". */
.ig-label {
  font-size: 12px;
  color: var(--text-muted);
  flex-shrink: 0;
  max-width: 220px;
}

/* In a row's name line the readable name wins: the slug, label and tags
   shrink (and ellipsize) before it does. */
:is(.integration-row, .vault-row) .ig-name-line > .ig-name {
  flex-shrink: 0;
  max-width: 70%;
}
:is(.integration-row, .vault-row) .ig-name-line > :is(.ig-key, .ig-label, .role-lock, .ig-flag) {
  flex-shrink: 1;
  min-width: 0;
}
/* A short tag ("Asks first") stays whole: the role list ellipsizes first. */
:is(.integration-row, .vault-row) .ig-name-line > .ig-flag {
  flex-shrink: 0;
}
.role-lock-text {
  align-self: baseline;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}

.ig-desc {
  margin-top: 1px;
  color: var(--text-muted);
  font-size: 12px;
}

.ig-status {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 12.5px;
  font-weight: 500;
  color: var(--text-secondary);
  white-space: nowrap;
}

/* Linked-platform brand icons (Team page and friends). */
.team-links {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  color: var(--text-muted);
}

.brand-icon {
  display: inline-flex;
  width: 15px;
  height: 15px;
}

.brand-icon svg {
  width: 100%;
  height: 100%;
}

.brand-icon:hover {
  color: var(--text);
}

.ig-status-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  flex-shrink: 0;
  background: var(--text-faint);
}
.ig-status.ok .ig-status-dot {
  background: var(--ok);
}
.ig-status.ok {
  color: var(--ok-text);
}
.ig-status.warn .ig-status-dot {
  background: var(--warn);
}
.ig-status.warn {
  color: var(--warn-text);
}
.ig-status.muted {
  color: var(--text-muted);
}
.ig-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
}

.ig-expand {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  padding: 0;
  border: 0;
  border-radius: var(--radius-xs);
  background: transparent;
  color: var(--text-faint);
  cursor: pointer;
  transition:
    color 0.1s ease,
    background 0.1s ease;
}
.ig-expand svg {
  width: 14px;
  height: 14px;
  transition: transform 0.15s ease;
}
.ig-expand:hover {
  background: var(--hover);
  color: var(--text-secondary);
}
.ig-expand.open svg {
  transform: rotate(90deg);
}

/* An integration's settings, under its row: one setting per line (what it
   is and why on the left, its control on the right), then how it connects. */
.ig-settings {
  margin: 0 28px 16px 80px;
  overflow: hidden;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: var(--shadow-card);
}
.ig-settings > * + * {
  border-top: 1px solid var(--border);
}
.ig-setting {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px 24px;
  padding: 14px 18px;
}
.ig-setting-text {
  min-width: 0;
}
/* The label column never collapses beside a long role list. */
@media (min-width: 601px) {
  .ig-setting:not(.ig-setting-stacked) > .ig-setting-text {
    flex: 1 1 240px;
    min-width: 240px;
  }
}
.role-chip.role-chip-more {
  flex-shrink: 0;
  cursor: default;
}
/* An open row's guidance box shows its description: not twice. */
.ig-item.is-open:has(.ig-guidance) > .ig-row .ig-desc {
  display: none;
}
.ig-setting-label {
  color: var(--text);
  font-size: 13.5px;
  font-weight: 500;
}
.ig-setting-hint {
  margin-top: 2px;
  color: var(--text-muted);
  font-size: 12.5px;
  line-height: 1.45;
}
.ig-setting-control,
.ig-setting-inline {
  display: flex;
  flex-shrink: 0;
  align-items: center;
  gap: 10px;
}
.ig-setting-value {
  color: var(--text-secondary);
  font-size: 13px;
  white-space: nowrap;
}
.ig-role-list {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 4px;
}

/* Guidance spans the panel; Save and Cancel show once the text changes. */
.ig-setting-stacked {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 10px;
}
.ig-guidance {
  width: 100%;
  min-height: 76px;
  resize: vertical;
}
.ig-guidance-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
}
.ig-setting-stacked > .field-error {
  margin-top: -4px;
}

/* What to fix first: a missing secret, an unfinished sign-in. */
.ig-attention {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 14px 12px 18px;
  background: var(--warn-soft);
  color: var(--warn-text);
  font-size: 13px;
  line-height: 1.45;
}
.ig-attention > svg {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
}
.ig-attention-text {
  flex: 1;
  min-width: 0;
}
.ig-attention-actions {
  display: flex;
  flex-shrink: 0;
  flex-wrap: wrap;
  gap: 6px;
}
.ig-attention code {
  font-family: var(--mono);
  font-size: 12px;
}

.ig-settings-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 8px 10px 8px 18px;
  background: var(--surface-muted);
}
.ig-settings-how {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  color: var(--text-muted);
  font-size: 12.5px;
}
.ig-settings-how code {
  color: var(--text-faint);
  font-family: var(--mono);
  font-size: 11.5px;
}
.ig-settings-actions {
  display: flex;
  flex-shrink: 0;
  gap: 4px;
}
.btn.ig-remove {
  color: var(--danger-text);
}
.btn.ig-remove:hover {
  background: var(--danger-soft);
  color: var(--danger-text);
}

/* "Asks first": each call waits for a person to approve it. */
.ig-flag {
  flex-shrink: 0;
  padding: 0 8px;
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  background: var(--surface-2);
  color: var(--text-muted);
  font-size: 10.5px;
  font-weight: 500;
  line-height: 17px;
  white-space: nowrap;
}
/* Keeps the chevrons in line on rows you can't switch. */
.ig-switch-space {
  width: 38px;
  flex-shrink: 0;
}
:is(.integrations-card, .vault-card, .secrets-card) .ig-filter-wrap {
  display: flex;
  align-items: center;
  gap: 8px;
  width: auto;
}
:is(.integrations-card, .vault-card, .secrets-card) .ig-filter {
  width: 220px;
  height: var(--control-h-sm);
  min-height: var(--control-h-sm);
}
/* "Nothing matches" and other empty states with a way out. */
.card-empty > .btn {
  margin-top: 14px;
}

/* Add a service: a search/name box and a directory of services. */

/* The catalog scrolls with the page (no scroller inside it); its toolbar
   sticks to the top of the page's scroll pane. overflow: clip keeps the
   card's rounded corners without making the card the sticky's scroller. */
.browse-card {
  overflow: clip;
}
.browse-body {
  border-top: 1px solid var(--border);
}

.browse-toolbar {
  display: grid;
  grid-template-columns: minmax(220px, 1fr) 180px auto auto;
  align-items: center;
  gap: 12px;
  /* Sticks to the very top of the page's scroll pane: less its top padding,
     which sticky offsets count from. */
  position: sticky;
  top: -22px;
  z-index: 4;
  padding: 14px 28px;
  border-bottom: 1px solid var(--border);
  background: var(--surface);
}

/* Without the directory: just the box and Add, under the card header, and a
   few services to start from. */
.browse-toolbar.is-plain {
  grid-template-columns: minmax(220px, 1fr) auto;
  position: static;
  border-top: 1px solid var(--border);
  border-bottom: 0;
}
.browse-toolbar .field-error {
  grid-column: 1 / -1;
  margin-top: -6px;
}
.browse-suggestions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  padding: 0 28px 18px;
}
.browse-suggestions-label {
  margin-right: 4px;
  color: var(--text-muted);
  font-size: 12px;
}

.browse-search {
  height: 36px;
  min-height: 36px;
  padding-inline: 16px;
  border-color: var(--border-control);
  border-radius: var(--radius-pill);
  background: var(--surface);
  font-size: 13.5px;
}

.browse-category {
  height: 36px;
  min-height: 36px;
  padding-inline: 14px;
  border-radius: var(--radius-pill);
  font-size: 13px;
}

.browse-count {
  min-width: 10ch;
  color: var(--text-muted);
  font-size: 11.5px;
  font-variant-numeric: tabular-nums;
  text-align: right;
  white-space: nowrap;
}
.browse-grid > .browse-error {
  grid-column: 1 / -1;
}
.browse-error {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.browse-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: 12px;
  padding: 16px 28px 20px;
}

.browse-grid .card-empty {
  grid-column: 1 / -1;
  border-top: 0;
}

.tk-card {
  display: flex;
  flex-direction: column;
  min-height: 148px;
  padding: 15px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  cursor: pointer;
  transition:
    border-color 0.12s ease,
    box-shadow 0.12s ease;
}
/* The whole tile adds (or opens) the service. */
.tk-card:hover {
  border-color: var(--border-strong);
  box-shadow: var(--shadow-tile);
}

.tk-head {
  display: flex;
  align-items: center;
  gap: 11px;
  min-width: 0;
}

.tk-title {
  min-width: 0;
}

.tk-title h3 {
  margin: 0;
  font-size: 13.5px;
  font-weight: 500;
  letter-spacing: -0.01em;
}

.tk-desc {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  margin: 11px 0 13px;
  color: var(--text-muted);
  font-size: 12px;
  line-height: 1.5;
}

.tk-foot {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px 8px;
  margin-top: auto;
  min-height: 26px;
}
/* Already an integration: "Added", and Open instead of Add. */
.tk-card.is-added .tk-foot {
  justify-content: space-between;
}

/* A row just added: lit up for a moment, then back to plain. */
.ig-item.row-flash,
.rt-row.row-flash {
  animation: row-flash 1.2s var(--ease-out) both;
}
@keyframes row-flash {
  0%,
  35% {
    background: var(--accent-soft);
  }
  100% {
    background: transparent;
  }
}
@media (prefers-reduced-motion: reduce) {
  .ig-item.row-flash,
  .rt-row.row-flash {
    animation: none;
  }
}

/* No integrations yet: the empty-state art inside the card, and both ways
   to add one. */
.ig-empty {
  padding: 40px 24px 44px;
  border-top: 1px solid var(--border);
}
.ig-empty .grid-empty-title {
  font-size: 20px;
}
.ig-empty-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
  margin-top: 18px;
}

/* Adding an integration by hand: short fields in pairs, so the address
   starts in view. */
.manual-pair {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 0 14px;
}
.manual-integration .seg:is(.manual-scope, .manual-type) {
  display: flex;
  flex-wrap: nowrap;
}
.manual-integration :is(.manual-scope, .manual-type) .seg-btn {
  flex: 1 1 0;
  justify-content: center;
  padding-inline: 8px;
  white-space: nowrap;
}
.manual-blocked {
  margin-bottom: 16px;
}
.role-audience .seg {
  display: flex;
  flex-wrap: nowrap;
}
.role-audience .seg-btn {
  flex: 1 1 0;
  justify-content: center;
}
/* No role checked: the choice has no effect, so it rests, muted. */
.role-audience.is-disabled .field-label {
  color: var(--text-muted);
}
.role-audience.is-disabled .seg {
  opacity: 0.55;
}
@media (max-width: 600px) {
  .manual-pair {
    grid-template-columns: minmax(0, 1fr);
  }
}
/* The vault's edit dialog carries the same how-to-write-it note as the page. */
.vault-edit-modal .vault-secret-hint {
  margin: -4px 0 0;
}

/* Misc */

.model-select {
  font-size: 13px;
}

/* ============ Responsive ============ */

@media (max-width: 1180px) {
  .chat-list {
    width: 260px;
  }
}

@media (max-width: 900px) {
  .topbar {
    padding: 22px 20px 8px;
  }
  .topbar-title {
    font-size: 24px;
  }
  .topbar-sub {
    font-size: 13px;
  }
  .content {
    padding: 12px 20px 44px;
  }
  .content-wrap.is-subpage .content {
    padding-top: 22px;
  }
  .content.content-chat {
    padding: 0;
  }
  .content-wrap:has(.content-chat) .topbar {
    padding: 14px 20px 10px;
  }
  .content.content-chat:empty::before {
    margin: 4px 20px;
  }
  .chat-list {
    width: 252px;
  }
  .chat-list-title {
    display: none;
  }
  .chat-list-head {
    justify-content: flex-end;
    min-height: 44px;
  }
  .chat-view-tab {
    gap: 4px;
    padding: 0 5px;
    font-size: 11px;
  }
  .chat-model-select {
    max-width: 160px;
  }
  .card-header {
    align-items: flex-start;
    flex-direction: column;
    gap: 10px;
  }
  .ig-filter-wrap {
    width: 100%;
  }
  .usage-controls {
    width: 100%;
  }
  /* The period keeps its words; the person takes the rest of the row. */
  .usage-controls select.grid-select {
    width: auto;
  }
  .usage-controls select.usage-person {
    flex: 1 1 0;
    min-width: 0;
  }
  .usage-controls select.usage-period {
    flex: none;
  }
  .table-head {
    display: none;
  }
  /* Model pool: the switch and actions beside the name, the badges under it. */
  .row-pool {
    grid-template-columns: auto minmax(0, 1fr) auto auto;
    grid-template-areas:
      'account account switch actions'
      'provider status status status';
    gap: 8px 12px;
  }
  .row-pool > .pool-account {
    grid-area: account;
  }
  .row-pool .pool-provider {
    grid-area: provider;
  }
  .row-pool .pool-status {
    grid-area: status;
  }
  .row-pool > .toggle {
    grid-area: switch;
  }
  .row-pool > .pool-actions {
    grid-area: actions;
  }
  .ig-row {
    grid-template-columns: 38px minmax(0, 1fr) minmax(90px, auto) auto;
  }
  .ig-settings {
    margin-left: 28px;
  }
  .browse-toolbar {
    top: -12px;
    grid-template-columns: 1fr 150px auto;
  }
  .browse-toolbar.is-plain {
    grid-template-columns: 1fr auto;
  }
  .browse-toolbar .browse-count {
    display: none;
  }
}
/* Phones and short (landscape) screens: the header drops its eyebrow, which
   only repeats the sidebar's group, and starts with the page's name. After
   the rules above, so its padding wins. */
@media (max-width: 600px), (max-height: 500px) {
  .topbar-eyebrow {
    display: none;
  }
  .topbar {
    padding-top: 16px;
  }
}

@media (max-width: 1300px) {
  .chat-code-panel {
    position: absolute;
    inset: 0;
    width: 100% !important;
    max-width: none;
    min-width: 0;
    border-left: 0;
    box-shadow: -16px 0 40px color-mix(in srgb, var(--lm-ink) 14%, transparent);
  }

  .chat-code-panel-resizer,
  .chat-code-maximize {
    display: none;
  }
}

/* The composer's controls shrink before Send can leave the screen. */
.chat-model-slot {
  min-width: 0;
  flex-shrink: 1;
}
.chat-model-slot .chat-model-select {
  min-width: 0;
  max-width: min(240px, 100%);
  text-overflow: ellipsis;
}
.chat-composer-row > .btn-primary {
  flex-shrink: 0;
}

/* Phones: an integration row stacks its status under the name instead of
   squeezing the name column to nothing. */
@media (max-width: 600px) {
  .chat-composer-hint {
    display: none;
  }
  /* The model pill keeps room for its name: tighter gaps, and the context
     meter is its ring alone (the number is in its detail). */
  .chat-composer-row {
    gap: 6px;
  }
  .chat-composer-row .chat-context-pct {
    display: none;
  }
  .ig-row:has(> .ig-status) {
    grid-template-columns: 38px minmax(0, 1fr) auto;
    grid-template-areas:
      'mark title actions'
      'mark status actions';
    row-gap: 4px;
    padding: 12px 16px;
  }
  .ig-row:has(> .ig-status) > :first-child {
    grid-area: mark;
  }
  .ig-row:has(> .ig-status) > .ig-title {
    grid-area: title;
  }
  .ig-row:has(> .ig-status) > .ig-status {
    grid-area: status;
  }
  .ig-row:has(> .ig-status) > :last-child {
    grid-area: actions;
  }
  .ig-row:has(> .ig-status) .ig-desc,
  .ig-row:has(> .ig-status) .ig-key {
    display: none;
  }
  /* Tags (account label, roles, "Asks first") wrap under the name
     instead of squeezing it out. */
  .integration-row .ig-name-line {
    flex-wrap: wrap;
    row-gap: 2px;
  }
  .integration-row .ig-name,
  .integration-row .ig-name-line > .ig-name {
    max-width: 100%;
  }
  /* ...and shrink to the column rather than run under the switch. */
  .integration-row .ig-name-line > :is(.ig-label, .role-lock, .ig-flag) {
    max-width: 100%;
  }
  .ig-settings {
    margin: 0 12px 12px;
  }
  .ig-setting {
    flex-wrap: wrap;
    padding: 12px 14px;
  }
  /* A setting's control (roles and Change) takes its own line and wraps... */
  .ig-setting-control {
    flex: 1 1 100%;
    min-width: 0;
  }
  /* ...but a switch or a plain value stays top-right, beside its label. */
  .ig-setting-text {
    flex: 1 1 0;
    min-width: 0;
  }
  .ig-setting-control:has(> .toggle),
  .ig-setting-control:has(> .ig-setting-value) {
    flex: 0 0 auto;
    align-self: flex-start;
    margin-left: auto;
  }
  .ig-setting-inline {
    flex-wrap: wrap;
    flex-shrink: 1;
    min-width: 0;
  }
  .ig-role-list {
    justify-content: flex-start;
  }
  /* The fix-it note: text full width, its button under it. */
  .ig-attention {
    flex-wrap: wrap;
    align-items: flex-start;
  }
  .ig-attention-text {
    flex: 1 1 calc(100% - 26px);
  }
  .ig-attention > .ig-attention-actions {
    margin-left: 26px;
  }
  .ig-attention code {
    overflow-wrap: anywhere;
  }
  /* State tabs stay one row (scrolling sideways if they must, fading at
     the edge that has more). */
  .ig-state-tabs {
    flex-wrap: nowrap;
    max-width: 100%;
    overflow-x: auto;
    scrollbar-width: none;
  }
  .ig-state-tabs.is-overflowing {
    mask-image: linear-gradient(90deg, #000 calc(100% - 28px), transparent);
  }
  .ig-state-tabs .seg-btn {
    flex-shrink: 0;
    white-space: nowrap;
  }
  /* Catalog: one row, the search and a narrower category. Typed names add
     with Enter (or the "Add …" a miss offers), so the Add button goes. It
     scrolls with the page: fixed, it took a third of a phone's screen.
     Without the directory, Add stays beside the box. */
  .browse-toolbar {
    position: static;
    grid-template-columns: minmax(0, 1fr) 36px;
    gap: 8px;
    padding: 12px 16px;
  }
  .browse-toolbar.is-plain {
    grid-template-columns: minmax(0, 1fr) auto;
  }
  .browse-toolbar:not(.is-plain) > .browse-add {
    display: none;
  }
  /* The category is a round filter icon (the picker opens as usual); it
     turns orange while a category is picked. */
  .browse-category {
    width: 36px;
    min-width: 36px;
    padding: 0;
    color: transparent;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='none' stroke='%23716f7e' stroke-width='1.5' stroke-linecap='round'%3E%3Cpath d='M2.5 4.5h11M4.5 8h7M6.5 11.5h3'/%3E%3C/svg%3E");
    background-position: center;
    background-size: 16px;
  }
  .browse-category.is-set {
    border-color: var(--accent-line);
    background-color: var(--accent-tint);
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='none' stroke='%23eb5413' stroke-width='1.5' stroke-linecap='round'%3E%3Cpath d='M2.5 4.5h11M4.5 8h7M6.5 11.5h3'/%3E%3C/svg%3E");
  }
  .browse-category option {
    color: var(--text);
  }
  .browse-suggestions {
    padding: 0 16px 14px;
  }
  .browse-error {
    flex-wrap: wrap;
  }
  /* Services read as a list on a phone: logo, name and a line, Add. */
  .browse-grid {
    grid-template-columns: minmax(0, 1fr);
    gap: 0;
    padding: 0 16px 6px;
  }
  .tk-card {
    display: grid;
    grid-template-columns: 38px minmax(0, 1fr) auto;
    grid-template-areas:
      'mark title foot'
      'mark desc foot';
    align-items: center;
    column-gap: 12px;
    min-height: 0;
    padding: 10px 0;
    border: 0;
    border-bottom: 1px solid var(--border);
    border-radius: 0;
  }
  .tk-card:last-of-type {
    border-bottom: 0;
  }
  .tk-card > .tk-head {
    display: contents;
  }
  .tk-card > .tk-head > :first-child {
    grid-area: mark;
  }
  .tk-card .tk-title {
    grid-area: title;
  }
  .tk-card > .tk-desc {
    grid-area: desc;
    margin: 0;
    -webkit-line-clamp: 1;
  }
  .tk-card > .tk-desc:empty {
    display: none;
  }
  .tk-card:has(> .tk-desc:empty) {
    grid-template-areas: 'mark title foot';
  }
  .tk-card > .tk-foot {
    grid-area: foot;
    flex-wrap: nowrap;
    margin: 0;
  }
  /* Previously connected: the name, and who had it under it. */
  .ig-previous-item {
    display: grid;
    grid-template-columns: 38px minmax(0, 1fr) auto;
    grid-template-areas:
      'mark name actions'
      'mark scope actions';
    column-gap: 12px;
    row-gap: 1px;
    padding: 10px 16px;
  }
  .ig-previous-item > :first-child {
    grid-area: mark;
  }
  .ig-previous-item > .ig-name {
    grid-area: name;
  }
  .ig-previous-item > .ig-previous-scope {
    grid-area: scope;
    white-space: normal;
  }
  .ig-previous-item > .ig-previous-actions {
    grid-area: actions;
  }
  .ig-settings-foot {
    flex-wrap: wrap;
    padding-left: 14px;
  }
  /* The agent's name for it shows whole. */
  .ig-settings-how {
    flex-wrap: wrap;
  }
  .ig-settings-how code {
    overflow: visible;
    text-overflow: clip;
  }
  :is(.integrations-card, .vault-card, .secrets-card) .card-header {
    flex-wrap: wrap;
  }
  :is(.integrations-card, .vault-card, .secrets-card) .ig-filter-wrap {
    width: 100%;
  }
  :is(.integrations-card, .vault-card, .secrets-card) .ig-filter {
    flex: 1;
    width: auto;
    min-width: 0;
  }
  :is(.integrations-card, .vault-card, .secrets-card) .ig-filter-wrap > .btn {
    flex-shrink: 0;
  }
  .ig-row:not(:has(> .ig-status)) .ig-name-line {
    flex-wrap: wrap;
    row-gap: 0;
  }
  .ig-row:not(:has(> .ig-status)) .ig-key {
    flex-shrink: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
}

@media (max-width: 600px) {
  .content-wrap:has(.content-chat) .topbar {
    padding: 10px 10px 8px;
  }
  .content.content-chat:empty::before {
    margin: 4px 10px;
  }

  .content-wrap:has(.content-chat) .topbar-title {
    font-size: 20px;
  }

  .content-wrap:has(.content-chat) .topbar-sub {
    display: none;
  }

  .chat-shell {
    margin: 0;
  }

  .chat-list {
    position: absolute;
    z-index: 42;
    inset: 0 auto 0 0;
    width: min(286px, calc(100% - 12px)) !important;
    height: 100%;
    border-radius: 0 var(--radius-lg) var(--radius-lg) 0;
    box-shadow: 12px 0 36px color-mix(in srgb, var(--lm-ink) 16%, transparent);
    transform: translateX(-105%);
    visibility: hidden;
    transition:
      transform 0.18s ease,
      visibility 0.18s ease;
  }

  /* Visible from the first frame of opening, so focus can land inside. */
  .chat-shell.mobile-list-open .chat-list {
    transform: translateX(0);
    visibility: visible;
    transition:
      transform 0.18s ease,
      visibility 0s;
  }

  .chat-resizer {
    display: none;
  }

  .chat-mobile-list-backdrop {
    position: absolute;
    z-index: 41;
    inset: 0;
    display: block;
    padding: 0;
    border: 0;
    background: color-mix(in srgb, var(--lm-ink) 14%, transparent);
    opacity: 0;
    pointer-events: none;
    visibility: hidden;
    transition:
      opacity 0.18s ease,
      visibility 0.18s ease;
  }

  .chat-shell.mobile-list-open .chat-mobile-list-backdrop {
    opacity: 1;
    pointer-events: auto;
    visibility: visible;
  }

  .chat-mobile-list-toggle {
    display: inline-flex;
    flex: 0 0 auto;
    width: 34px;
    height: 34px;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: 1px solid var(--border-control);
    border-radius: var(--radius-pill);
    background: var(--surface);
    color: var(--text-muted);
  }

  .chat-mobile-list-toggle:hover {
    border-color: var(--border-strong);
    background: var(--surface-muted);
    color: var(--text);
  }

  .chat-head {
    min-height: 48px;
    padding: 8px 10px;
  }

  .chat-head-right {
    gap: 5px;
  }

  .chat-head-actions {
    display: none;
  }

  .chat-head-more .icon {
    width: 16px;
    height: 16px;
  }

  /* A long title gets two lines here; the subtitle then makes way for it. */
  .chat-head-title {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    white-space: normal;
    overflow-wrap: anywhere;
  }

  .chat-head-text.is-wrapped .chat-head-sub {
    display: none;
  }

  /* The drawer names itself and closes from its own head. */
  .chat-list-head {
    justify-content: space-between;
    padding-left: 16px;
  }

  .chat-list-title {
    display: block;
  }

  .chat-list-actions .chat-list-close {
    display: inline-flex;
    width: 32px;
    height: 32px;
  }

  .chat-scroll {
    padding-inline: 10px;
  }

  /* Replies use the full width: the avatar stays on the name line above. */
  .msg {
    padding-left: 0;
  }

  /* With no avatar column, a run keeps a narrow glyph column of its own. */
  .cc-run {
    --cc-glyph: 14px;
    --cc-glyph-gap: 6px;
  }

  .msg-head {
    margin-left: 0;
  }

  .chat-working {
    padding-left: 2px;
  }

  .chat-composer {
    padding: 8px 8px 12px;
  }

  .chat-code-panel {
    position: fixed;
    z-index: 80;
    inset: 10px;
    width: auto !important;
    height: auto;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-modal);
  }
}

/* === Skill editor / viewer screens === */
.content.content-editor {
  padding-bottom: 22px;
}
.content.content-editor > * {
  max-width: none;
  flex: 1 1 auto;
  min-height: 0;
}

.skill-screen {
  display: flex;
  flex-direction: column;
  gap: 14px;
  min-height: 0;
}

/* Back and the actions on top, then the title: a cron job's page layout. */
.skill-screen-head {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas:
    'back actions'
    'title title';
  align-items: center;
  gap: 10px 16px;
  flex: 0 0 auto;
}
.skill-screen-head > .btn {
  grid-area: back;
  justify-self: start;
  margin-left: -10px;
}
.skill-screen-title {
  grid-area: title;
  min-width: 0;
}
.skill-screen-title h2 {
  margin: 0;
  font-family: var(--font-display);
  font-size: 28px;
  font-weight: 500;
  letter-spacing: -0.035em;
  line-height: 1.15;
  overflow-wrap: anywhere;
}
.skill-screen-title p {
  max-width: 760px;
  margin: 6px 0 0;
  font-size: 14px;
  color: var(--text-muted);
}
.skill-screen-actions {
  grid-area: actions;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
}
@media (max-width: 600px) {
  .skill-screen-head {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas:
      'back'
      'title'
      'actions';
  }
  .skill-screen-actions {
    justify-content: flex-start;
  }
  .skill-screen-title h2 {
    font-size: 24px;
  }
}

.skill-meta {
  display: flex;
  gap: 14px;
  flex-wrap: wrap;
  flex: 0 0 auto;
}
.skill-meta .field {
  flex: 0 1 240px;
  margin: 0;
}
.skill-meta .field.skill-meta-desc {
  flex: 1 1 320px;
}

.skill-editor-host {
  flex: 1 1 auto;
  min-height: 420px;
}
.skill-editor-host .toastui-editor-defaultUI {
  font-family: var(--font);
  border: 1px solid var(--border-card);
  border-radius: var(--radius-xl);
  overflow: hidden;
  background: var(--surface);
  box-shadow: var(--shadow-card);
}
.skill-editor-host .toastui-editor-defaultUI-toolbar {
  background: var(--surface-2);
  border-bottom: 1px solid var(--border);
  border-radius: 0;
}
.skill-editor-host .toastui-editor-toolbar-icons {
  border-color: transparent;
}
.skill-editor-host .toastui-editor-md-tab-container {
  background: var(--surface-2);
  border-color: var(--border);
}
.skill-editor-host .toastui-editor-defaultUI .ProseMirror,
.skill-editor-host .toastui-editor-contents {
  font-size: 13.5px;
}
.skill-editor-host .toastui-editor-mode-switch {
  height: 34px;
  padding: 4px 8px;
  background: var(--surface-2);
  border-top: 1px solid var(--border);
}

/* Toast UI in the app's colours and type: ink for "on", the accent's tint for
   the preview's current block and its markers, never the stock blue/yellow. */
.skill-editor-host .toastui-editor-md-tab-container .tab-item {
  width: auto;
  height: 28px;
  margin: 8px 2px 0 0;
  padding: 0 12px;
  border: 0;
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--text-muted);
  font-family: var(--font);
  line-height: 28px;
}
.skill-editor-host .toastui-editor-md-tab-container .tab-item.active {
  border: 0;
  background: var(--surface);
  color: var(--text);
  box-shadow: var(--shadow-card);
}
.skill-editor-host .toastui-editor-mode-switch .tab-item {
  width: auto;
  height: 26px;
  margin: 0 0 0 2px;
  padding: 0 12px;
  border: 0;
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--text-muted);
  font-family: var(--font);
  font-size: 12px;
  line-height: 26px;
}
.skill-editor-host .toastui-editor-mode-switch .tab-item.active {
  border: 0;
  background: var(--surface);
  color: var(--text);
  box-shadow: var(--shadow-card);
}
.skill-editor-host .toastui-editor-defaultUI-toolbar button:not(:disabled):hover {
  background-color: var(--surface);
  border-color: var(--border);
}
.skill-editor-host .toastui-editor-toolbar-divider {
  background-color: var(--border-strong);
}
.skill-editor-host .toastui-editor-defaultUI-toolbar .scroll-sync::before {
  color: var(--text-muted);
  font-family: var(--font);
  font-size: 13px;
}
.skill-editor-host .toastui-editor-defaultUI-toolbar .scroll-sync.active::before {
  color: var(--text);
}
.skill-editor-host .toastui-editor-defaultUI-toolbar .switch {
  background-color: var(--surface-3);
}
.skill-editor-host .toastui-editor-defaultUI-toolbar .switch::before {
  background-color: var(--lm-grey);
}
.skill-editor-host .toastui-editor-defaultUI-toolbar input:checked + .switch {
  background-color: var(--lm-grey-lighter);
}
.skill-editor-host .toastui-editor-defaultUI-toolbar input:checked + .switch::before {
  background-color: var(--ink-btn);
}
.skill-editor-host .ProseMirror .placeholder {
  color: var(--text-faint);
}
.skill-editor-host .toastui-editor-md-list-item-style.toastui-editor-md-list-item-odd,
.skill-editor-host
  .toastui-editor-md-link.toastui-editor-md-link-desc.toastui-editor-md-marked-text {
  color: var(--accent-text);
}
.skill-editor-host .toastui-editor-md-list-item-style.toastui-editor-md-list-item-even,
.skill-editor-host .toastui-editor-md-code.toastui-editor-md-marked-text {
  color: var(--lm-plum);
}
.skill-editor-host .toastui-editor-contents .toastui-editor-md-preview-highlight::after {
  background-color: var(--accent-tint);
}
.skill-editor-host .toastui-editor-contents td.toastui-editor-md-preview-highlight,
.skill-editor-host .toastui-editor-contents th.toastui-editor-md-preview-highlight {
  background-color: var(--accent-tint);
}
.skill-editor-host .toastui-editor-contents :is(h1, h2, h3, h4, h5, h6),
.skill-viewer-host .toastui-editor-contents :is(h1, h2, h3, h4, h5, h6) {
  color: var(--text);
  font-family: var(--font-display);
  font-weight: 500;
  letter-spacing: -0.02em;
}
.skill-editor-host .toastui-editor-contents :is(h1, h2),
.skill-viewer-host .toastui-editor-contents :is(h1, h2) {
  border-bottom: 1px solid var(--border);
}
.skill-editor-host .toastui-editor-contents a,
.skill-viewer-host .toastui-editor-contents a {
  color: var(--accent-text);
}
.skill-editor-host .toastui-editor-contents ul > li::before,
.skill-viewer-host .toastui-editor-contents ul > li::before {
  background-color: var(--text-faint);
}
.skill-editor-host .toastui-editor-contents blockquote,
.skill-viewer-host .toastui-editor-contents blockquote {
  border-left-color: var(--border-strong);
}
.skill-editor-host .toastui-editor-contents code,
.skill-viewer-host .toastui-editor-contents code {
  background-color: var(--surface-2);
  border-radius: var(--radius-xs);
  color: var(--lm-plum);
  font-family: var(--mono);
}
.skill-editor-host .toastui-editor-contents pre,
.skill-viewer-host .toastui-editor-contents pre {
  background-color: var(--surface-muted);
  border-radius: var(--radius-sm);
}
.skill-editor-host .toastui-editor-contents pre code,
.skill-viewer-host .toastui-editor-contents pre code {
  background-color: transparent;
  color: inherit;
}

.skill-viewer-host {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--border-card);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-card);
  padding: 26px 30px;
}
.skill-viewer-host .toastui-editor-contents {
  font-family: var(--font);
  font-size: 14px;
}
.skill-viewer-host .toastui-editor-contents pre,
.skill-viewer-host .toastui-editor-contents code {
  font-family: var(--mono);
}

.ig-row-clickable {
  cursor: pointer;
}

/* A long file path wraps instead of pushing the page sideways. */
.skill-files code {
  overflow-wrap: anywhere;
}

/* Skill "When to use" — multi-line, grows with content. */
.skill-desc-input {
  field-sizing: content;
  min-height: 42px;
  max-height: 220px;
  resize: vertical;
  line-height: 1.45;
}

/* ---- Composer attachments ---- */
.attach-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  width: min(720px, calc(100% - 48px));
  margin: 0 auto;
  padding: 6px 0 0;
}

.attach-chip > .icon {
  flex: none;
  width: 14px;
  height: 14px;
  color: var(--text-muted);
}

.attach-chip.attach-failed > .icon {
  color: var(--danger-text);
}

.attach-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 30px;
  padding: 0 4px 0 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  background: var(--surface-muted);
  color: var(--text-secondary);
  font-size: 12.5px;
  max-width: 260px;
}

.attach-chip:has(.attach-thumb) {
  padding-left: 4px;
}

.attach-chip.attach-failed {
  max-width: 100%;
  height: auto;
  min-height: 30px;
  padding-block: 4px;
  border-color: var(--danger-line);
  background: var(--danger-soft);
  color: var(--danger-text);
}

/* The reason a file failed is the point of the chip: the name gives way
   first, and the reason wraps rather than cuts. */
.attach-chip.attach-failed .attach-name {
  flex-shrink: 1000;
}

.attach-chip.attach-failed .attach-note {
  flex: 0 1 auto;
  min-width: 12ch;
  color: var(--danger-text);
  white-space: normal;
}

/* Enter while a file is still uploading (or failed): point at the chip. */
.attach-chip.is-nudged {
  animation: attach-nudge 0.42s ease;
}

@keyframes attach-nudge {
  0%,
  100% {
    transform: none;
  }
  25% {
    transform: translateX(-3px);
  }
  50% {
    transform: translateX(3px);
  }
  75% {
    transform: translateX(-2px);
  }
}

@media (prefers-reduced-motion: reduce) {
  .attach-chip.is-nudged {
    animation: none;
    outline: 2px solid var(--accent-ring);
  }
}

.attach-thumb {
  width: 22px;
  height: 22px;
  flex: none;
  border-radius: var(--radius-pill);
  object-fit: cover;
}

.attach-name {
  flex: 0 1 auto;
  min-width: 3ch;
}

/* The status always shows in full; only the file name ellipsizes. */
.attach-note {
  flex: none;
  min-width: 0;
  color: var(--text-faint);
  font-size: 11.5px;
}

.attach-remove {
  display: inline-flex;
  flex: none;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  padding: 0;
  border: 0;
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--text-faint);
  cursor: pointer;
  font-size: 15px;
  line-height: 1;
}

.attach-remove:hover {
  background: var(--danger-soft);
  color: var(--danger-text);
}

.chat-main.drop-active {
  outline: 2px dashed var(--accent-text);
  outline-offset: -6px;
}

/* CH-34: say what a drop does. */
.chat-main.drop-active::after {
  content: 'Drop files to attach';
  position: absolute;
  inset: 8px;
  z-index: 30;
  display: grid;
  place-items: center;
  border-radius: var(--radius-lg);
  background: color-mix(in srgb, var(--accent-tint) 82%, transparent);
  color: var(--accent-text);
  font-family: var(--font-display);
  font-size: 18px;
  font-weight: 500;
  pointer-events: none;
}

@media (max-width: 600px) {
  .attach-chips {
    width: calc(100% - 16px);
  }

  /* A chip takes its own row only when its name needs it, never a stub. */
  .attach-chip {
    max-width: 100%;
  }
}

/* ---- Resizable conversations sidebar ---- */
.chat-resizer {
  flex: none;
  width: 5px;
  margin-left: -3px;
  cursor: col-resize;
  z-index: 5;
}

.chat-resizer:hover {
  background: color-mix(in srgb, var(--accent-text) 25%, transparent);
}

body.resizing-x {
  cursor: col-resize;
  user-select: none;
}

/* ---- The rail: the sidebar collapsed to icons (by choice, or on a window
 * ≤900px). The org switcher keeps only the mark, the collapse button sits
 * under it above a hairline (chrome, not a page), the Configuration header
 * becomes a hairline, the account row an avatar; names show in the rail
 * tooltip (.rail-tip). ---- */
.sidebar.is-rail {
  width: 64px;
  padding: 10px 8px;
}
.sidebar.is-rail .sidebar-top {
  flex-direction: column;
  gap: 6px;
  margin-bottom: 6px;
  border-bottom: 1px solid var(--border);
}
.sidebar.is-rail .nav-group-label:first-child {
  display: none;
}
.sidebar.is-rail .org-switch,
.sidebar.is-rail .account-row {
  justify-content: center;
  padding: 7px 0;
}
.sidebar.is-rail .org-switch-text,
.sidebar.is-rail .account-row-text,
.sidebar.is-rail .org-switch-chevrons,
.sidebar.is-rail .nav-label {
  display: none;
}
.sidebar.is-rail .env-mini {
  display: inline-flex;
}
.sidebar.is-rail .org-switch.is-staging .brand-mark::after {
  display: none;
}
.sidebar.is-rail .nav-item {
  justify-content: center;
  height: 36px;
  padding: 0;
}
.sidebar.is-rail .nav-group-label {
  height: 1px;
  margin: 10px 8px;
  padding: 0;
  overflow: hidden;
  background: var(--border);
  color: transparent;
}

/* Phones: a slimmer rail. Kept after the rules above so it wins. */
@media (max-width: 600px) {
  .sidebar.is-rail {
    width: 56px;
    padding: 10px 6px;
  }
}

/* Touch screens (not narrow windows: a trackpad keeps the dense layout):
   the shell's controls reach touch size. The phone rail is 56px wide, so
   the 44px menu button fits. */
@media (pointer: coarse) {
  .sidebar-collapse {
    width: 44px;
    height: 44px;
  }
  .nav-item,
  .side-menu-item {
    height: 42px;
  }
  /* Bigger, around the same centre. */
  .modal-close {
    width: 44px;
    height: 44px;
    margin: -9px -16px 0 0;
  }
  /* The error toast's × keeps its size; its hit area grows. */
  .mini-toast-close {
    position: relative;
  }
  .mini-toast-close::before {
    content: '';
    position: absolute;
    inset: -9px;
  }
}

/* A rail control's name, beside it (showRailTip): an ink pill, with the
   shortcut as a keycap where there is one. */
.rail-tip {
  position: fixed;
  z-index: 1001;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 4px 10px;
  border-radius: var(--radius-pill);
  background: var(--ink-btn);
  box-shadow: var(--shadow-float);
  color: var(--text-inverse);
  font-size: 12px;
  font-weight: 500;
  line-height: 1.4;
  white-space: nowrap;
  pointer-events: none;
  animation: rail-tip-in 0.12s ease-out both;
}
.rail-tip kbd {
  padding: 0 5px;
  border-radius: 5px;
  background: rgba(255, 255, 255, 0.16);
  font-family: var(--mono);
  font-size: 11px;
  line-height: 16px;
}
@keyframes rail-tip-in {
  from {
    opacity: 0;
    transform: translateX(-4px);
  }
}

/* ≤900px the sidebar is the rail, and its button opens the full sidebar as
   a drawer over the page, on a scrim. The rail's width stays reserved, so
   the page doesn't move. */
.sidebar-scrim {
  position: absolute;
  inset: 0;
  z-index: 39;
  background: rgba(26, 24, 43, 0.3);
  animation: fade-in-plain 0.18s ease-out both;
}
.sidebar.is-drawer {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  z-index: 40;
  width: 248px;
  box-shadow: var(--shadow-raised);
}
.app-shell:has(> .sidebar.is-drawer) {
  padding-left: 64px;
}
@media (max-width: 600px) {
  .app-shell:has(> .sidebar.is-drawer) {
    padding-left: 56px;
  }
}
@keyframes fade-in-plain {
  from {
    opacity: 0;
  }
}

/* Keyboard users skip the sidebar: hidden until focused, then an ink pill
   over the top-left corner. */
.skip-link {
  position: absolute;
  top: 10px;
  left: 10px;
  z-index: 60;
  padding: 8px 16px;
  border-radius: var(--radius-pill);
  background: var(--ink-btn);
  box-shadow: var(--shadow-float);
  color: var(--text-inverse);
  font-size: 13px;
  font-weight: 500;
  transform: translateY(-160%);
}
.skip-link:focus,
.skip-link:hover {
  color: var(--text-inverse);
  text-decoration: none;
  transform: none;
}

/* ---- Drag to reorder chats ---- */
.conv-item.drag-over {
  box-shadow: inset 0 2px 0 var(--accent-text);
}

/* ---- Status face (Moodie) + row layout ----
 * A conversation row is a body / trailing grid at 9px gaps and a 58px minimum
 * height, gaining a 34px avatar column only while LobsterMane is active on it;
 * the chat header carries a 28px face at the same 9px gap. The face's
 * expression performances overshoot its box, so nothing clips it. */
.persona-face {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: var(--persona-size, 28px);
  height: var(--persona-size, 28px);
  overflow: visible;
  vertical-align: middle;
}
.persona-face > svg {
  display: block;
  width: 100%;
  height: 100%;
  overflow: visible;
}

/* Corner status dot on the row avatar: 8px, inset 2px from the bottom-right. */
.conv-corner-dot {
  position: absolute;
  right: 2px;
  bottom: 2px;
  width: 8px;
  height: 8px;
  border-radius: var(--radius-pill);
  box-shadow: 0 0 0 2px var(--persona-eye, var(--surface));
  pointer-events: none;
}
.conv-corner-dot.working {
  background: var(--ok);
}
.conv-corner-dot.waiting {
  background: var(--warn);
}
.conv-corner-dot.blocked {
  background: var(--danger);
}
.conv-item.active {
  --persona-eye: var(--surface);
}

.chat-head-face {
  display: inline-flex;
  flex-shrink: 0;
}
.chat-working .persona-face {
  margin-left: -2px;
  margin-right: 8px;
}

@media (prefers-reduced-motion: reduce) {
  .cc-glow,
  .cc-tool-running .cc-tool-dot {
    animation: none;
  }
}

.draft-label {
  margin-left: 6px;
  font-size: 10.5px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-faint);
}

/* ---- Mini toast (copy feedback) ---- */
/* max-content + max-width: a long message wraps at the viewport's width,
   not at the 50% a left-anchored fixed box would otherwise get. One line is
   still a pill; a wrapped one becomes a rounded card. Centred on the page
   column, beside the sidebar (--sidebar-w), not on the window. */
body:has(.sidebar) {
  --sidebar-w: 248px;
}
body:has(.sidebar.is-rail),
body:has(.sidebar.is-drawer) {
  --sidebar-w: 64px;
}
.mini-toast {
  position: fixed;
  bottom: var(--toast-bottom, 24px);
  left: calc(50% + var(--sidebar-w, 0px) / 2);
  transform: translateX(-50%) translateY(8px);
  display: flex;
  align-items: flex-start;
  gap: 8px;
  width: max-content;
  max-width: min(560px, calc(100vw - var(--sidebar-w, 0px) - 32px));
  padding: 9px 18px;
  border-radius: var(--radius-lg);
  background: var(--ink-btn);
  box-shadow: var(--shadow-float);
  color: var(--text-inverse);
  font-size: 13px;
  font-weight: 500;
  line-height: 1.4;
  text-align: start;
  opacity: 0;
  pointer-events: none;
  transition:
    opacity 0.15s ease,
    transform 0.15s ease;
  z-index: 200;
}

.mini-toast.show {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}

/* An error toast can be dismissed: a close button at its end. */
.mini-toast.is-error {
  padding-right: 8px;
}
.mini-toast.is-error.show {
  pointer-events: auto;
}
.mini-toast-text {
  min-width: 0;
}
.mini-toast-close {
  display: inline-flex;
  flex: none;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  margin: -1px 0 -1px 2px;
  padding: 0;
  border: 0;
  border-radius: var(--radius-pill);
  background: transparent;
  color: inherit;
  cursor: pointer;
}
.mini-toast-close:hover {
  background: color-mix(in srgb, currentColor 12%, transparent);
}
.mini-toast-close .icon {
  width: 12px;
  height: 12px;
}

/* Phones: the toast spans the page column, clear of the rail. */
@media (max-width: 600px) {
  body:has(.sidebar.is-rail),
  body:has(.sidebar.is-drawer) {
    --sidebar-w: 56px;
  }
  .mini-toast {
    left: calc(var(--sidebar-w, 0px) + 12px);
    right: 12px;
    width: auto;
    max-width: none;
    transform: translateY(8px);
  }
  .mini-toast.show {
    transform: none;
  }
}

/* A dialog is centred on the window: so is a toast over it. Kept after the
   rules above (and as specific as them) so it wins. */
body:has(.sidebar):has(.modal),
body:has(.sidebar.is-rail):has(.modal),
body:has(.sidebar.is-drawer):has(.modal) {
  --sidebar-w: 0px;
}
/* Phones: the toast spans the column, so its text takes the room and the
   error's × sits at the right edge. */
@media (max-width: 600px) {
  .mini-toast-text {
    flex: 1;
  }
}

/* An Undo-style action sits at the end of the note. */
.mini-toast.has-action {
  display: flex;
  align-items: center;
  gap: 14px;
  padding-right: 8px;
}

.mini-toast.show.has-action {
  pointer-events: auto;
}

.mini-toast-action {
  height: 26px;
  padding: 0 10px;
  border: 0;
  border-radius: var(--radius-pill);
  background: color-mix(in srgb, var(--text-inverse) 16%, transparent);
  color: var(--text-inverse);
  font: inherit;
  font-weight: 500;
  white-space: nowrap;
  cursor: pointer;
}

.mini-toast-action:hover {
  background: color-mix(in srgb, var(--text-inverse) 26%, transparent);
}

/* On an error toast (Retry), the action takes the error's ink. */
.mini-toast.is-error .mini-toast-action {
  background: color-mix(in srgb, var(--danger-text) 10%, transparent);
  color: var(--danger-text);
}

.mini-toast.is-error .mini-toast-action:hover {
  background: color-mix(in srgb, var(--danger-text) 17%, transparent);
}

/* ---- Chat multi-select ---- */
.select-bar {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 4px 0 6px;
  padding: 5px 8px 5px 10px;
  border: 1px solid color-mix(in srgb, var(--accent-text) 30%, transparent);
  border-radius: var(--radius-sm);
  background: color-mix(in srgb, var(--accent-text) 7%, transparent);
}

.select-bar-count {
  font-size: 12px;
  font-weight: 500;
  color: var(--accent-text);
}

/* A tint and a full hairline ring (a side stripe bends round the corners). */
.conv-item.selected {
  background: color-mix(in srgb, var(--accent-text) 10%, transparent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent-text) 35%, transparent);
}

/* ---- Linear-origin chats ---- */
.conv-item-origin .brand-icon {
  flex: none;
  color: var(--text-muted);
}

.chat-composer-note {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 14px;
  color: var(--text-muted);
  font-size: 13px;
}

.chat-composer-note .brand-icon {
  width: 15px;
  height: 15px;
}

/* ---- Motion primitives (adapted from Beautiful UI — beautiful-ui-five.vercel.app) ---- */

@keyframes shimmer-text {
  0% {
    background-position: 150% 0;
  }
  100% {
    background-position: -50% 0;
  }
}

@keyframes cc-stream-in {
  0% {
    opacity: 0;
    filter: blur(4px);
  }
  100% {
    opacity: 1;
    filter: blur(0);
  }
}

@keyframes pop-in {
  0% {
    opacity: 0;
    transform: scale(0.9);
  }
  100% {
    opacity: 1;
    transform: scale(1);
  }
}

@keyframes fade-up {
  0% {
    opacity: 0;
    transform: translateY(var(--enter-y));
  }
  100% {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes px-on {
  0%,
  100% {
    opacity: 0.15;
  }
  50% {
    opacity: 0.9;
  }
}

@keyframes caret-blink {
  0%,
  100% {
    opacity: 1;
  }
  50% {
    opacity: 0;
  }
}

/* Shimmer gradient text for in-flight labels */
.shimmer-text {
  background-image: linear-gradient(
    90deg,
    var(--text-muted) 35%,
    var(--text) 50%,
    var(--text-muted) 65%
  );
  background-size: 200% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  animation: shimmer-text 1.4s linear infinite;
}

/* New live-transcript lines blur-fade in as they stream */
.cc-entry-in {
  /* `backwards` (not `both`) so the blur filter fully clears after the
     entrance and never lingers as a stacking/containing block. */
  animation: cc-stream-in 300ms cubic-bezier(0.23, 1, 0.32, 1) backwards;
}

/* Live "Thinking…" label shimmers while it is the active entry */
.cc-run:not(.cc-run-finished) .cc-entry:last-child .cc-think-head {
  background-image: linear-gradient(
    90deg,
    var(--text-muted) 35%,
    var(--text) 50%,
    var(--text-muted) 65%
  );
  background-size: 200% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  animation: shimmer-text 1.4s linear infinite;
}

/* Streaming caret on the live assistant paragraph */
.cc-run:not(.cc-run-finished) .cc-entry:last-child .cc-md > p:last-child::after {
  content: '';
  display: inline-block;
  width: 2px;
  height: 12px;
  margin-left: 3px;
  vertical-align: -1px;
  border-radius: 1px;
  background: var(--accent);
  animation: caret-blink 1s step-end infinite;
}

/* Subagent fleet marks pop in as they resolve (live runs only) */
.cc-run:not(.cc-run-finished) .cc-task-fleet-completed .cc-task-fleet-mark,
.cc-run:not(.cc-run-finished) .cc-task-fleet-failed .cc-task-fleet-mark {
  animation: pop-in 300ms cubic-bezier(0.23, 1, 0.32, 1) both;
}

/* Pixel-grid loader */
.px-loading {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

.px-loader {
  display: grid;
  grid-template-columns: repeat(3, 4px);
  gap: 1.5px;
}

.px-cell {
  width: 4px;
  height: 4px;
  border-radius: 1px;
  background: var(--text);
  opacity: 0.15;
  animation: px-on 650ms ease-in-out infinite;
}

/* Pages fade-up once on navigation */
.content.page-enter > * {
  animation: fade-up 560ms var(--ease-out) both;
}
.content.page-enter > :nth-child(2) {
  animation-delay: 40ms;
}
.content.page-enter > :nth-child(3) {
  animation-delay: 80ms;
}
.content.page-enter > :nth-child(4) {
  animation-delay: 120ms;
}
.content.page-enter > :nth-child(n + 5) {
  animation-delay: 160ms;
}

@media (prefers-reduced-motion: reduce) {
  .shimmer-text,
  .cc-glow,
  .cc-run:not(.cc-run-finished) .cc-entry:last-child .cc-think-head,
  .cc-run:not(.cc-run-finished) .cc-entry:last-child .cc-md > p:last-child::after,
  .cc-entry-in,
  .cc-run:not(.cc-run-finished) .cc-task-fleet-completed .cc-task-fleet-mark,
  .cc-run:not(.cc-run-finished) .cc-task-fleet-failed .cc-task-fleet-mark,
  .px-cell,
  .content.page-enter > * {
    animation: none;
  }

  .shimmer-text {
    background-image: none;
    color: var(--text-secondary);
  }

  .cc-run:not(.cc-run-finished) .cc-entry:last-child .cc-think-head {
    background-image: none;
    color: inherit;
  }

  .cc-glow {
    background-image: none;
    color: var(--accent-text);
  }
}

/* Live sandbox screen (noVNC) overlay: Viktor's product frame — a white
   window inside a glass ring, a traffic-light bar, and the screen inset. */
.screen-overlay {
  position: fixed;
  inset: 0;
  background: rgba(26, 24, 43, 0.45);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
}
.screen-panel {
  width: min(1240px, 95vw);
  height: min(840px, 92vh);
  background: var(--surface);
  border: 0;
  border-radius: var(--radius-2xl);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  box-shadow:
    0 0 0 10px rgba(255, 255, 255, 0.35),
    0 40px 90px -20px rgba(21, 0, 121, 0.45);
  animation: lm-modal-in 0.36s var(--ease-out) both;
}
.screen-bar {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 14px 10px 72px;
  border-bottom: 1px solid var(--border);
  background: var(--surface-muted);
}
.screen-bar::before {
  content: '';
  position: absolute;
  left: 16px;
  top: 50%;
  width: 10px;
  height: 10px;
  margin-top: -5px;
  border-radius: 50%;
  background: #ff5f57;
  box-shadow:
    16px 0 0 #febc2e,
    32px 0 0 #28c840;
}
.screen-title {
  flex: 1;
  min-width: 0;
  font-size: 13px;
  font-weight: 500;
  color: var(--text-secondary);
}
.screen-bar-actions {
  flex: none;
  display: flex;
  align-items: center;
  gap: 8px;
}
/* The dialogs' ×, at the bar's end. */
.screen-close {
  margin: 0 -6px 0 0;
}
/* On touch the × is 44px (as in every dialog): it reaches into the bar's
   padding around the same centre, so the bar keeps its height. */
@media (pointer: coarse) {
  .screen-close {
    margin: -6px -12px -6px 0;
  }
}
.screen-frame {
  flex: 1;
  width: 100%;
  border: 0;
  background: #000;
}
/* A phone is portrait and the desktop is 16:10 (noVNC scales it): the panel
   fits the screen instead of framing a tall black box. */
@media (max-width: 600px) {
  /* Edge to edge from the top, so the screen gets the phone's whole width. */
  .screen-panel {
    align-self: flex-start;
    width: 100vw;
    height: auto;
    border-radius: 0;
    box-shadow: none;
  }
  .screen-frame {
    flex: none;
    aspect-ratio: 16 / 10;
  }
  /* New tab and Full screen as icons (they keep their names), so the title
     keeps its width. */
  .screen-bar-btn {
    width: var(--control-h-sm);
    padding: 0;
    justify-content: center;
  }
  .screen-bar-label {
    display: none;
  }
}

/* ---- Unread completed-session indicator (per-viewer accent dot) ---- */

.conv-unread-dot {
  flex-shrink: 0;
  width: 8px;
  height: 8px;
  border-radius: var(--radius-pill);
  background: var(--accent);
  box-shadow: 0 0 0 2px var(--accent-ring);
}

/* Waiting on a person (approval, question, request): yellow, not blue. */
.conv-unread-dot.is-attention {
  background: #f5b700;
  box-shadow: 0 0 0 2px rgba(245, 183, 0, 0.28);
}

.conv-item.needs-attention .conv-item-title,
.conv-item.unread .conv-item-title {
  font-weight: 700;
  color: var(--text);
}

/* ---- Inline chat media (Discord-style embeds) ---- */

.md-media-block {
  margin: 6px 0;
}

.chat-markdown .md-media-image {
  display: inline-block;
  line-height: 0;
}

.chat-markdown .md-media-image img {
  display: block;
  max-width: min(420px, 100%);
  max-height: 350px;
  border-radius: var(--radius-xs);
  border: 1px solid var(--border);
  background: var(--surface-2);
  cursor: zoom-in;
}

.chat-markdown video.md-media-video {
  display: block;
  max-width: min(520px, 100%);
  max-height: 400px;
  border-radius: var(--radius-xs);
  border: 1px solid var(--border);
  background: var(--lm-ink);
}

.chat-markdown audio.md-media-audio {
  display: block;
  width: min(420px, 100%);
}

.media-lightbox {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 14px;
  padding: 32px 16px;
  background: color-mix(in srgb, var(--lm-ink) 84%, transparent);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  cursor: zoom-out;
}

.media-lightbox-image {
  max-width: min(1240px, 92vw);
  max-height: 84vh;
  object-fit: contain;
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-modal);
  cursor: default;
}

.media-lightbox-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  cursor: default;
}

/* === Bots — roster, avatars, detail === */

/* Bots are "hires", so they wear Viktor's app-icon shape: a glossy rounded
   square in the bot's colour, lit from the top edge. */
.bot-avatar {
  --bot-color: #6366f1;
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  border-radius: 32%;
  background: linear-gradient(
    160deg,
    color-mix(in srgb, var(--bot-color) 14%, #ffffff) 0%,
    color-mix(in srgb, var(--bot-color) 30%, #ffffff) 100%
  );
  border: 1px solid color-mix(in srgb, var(--bot-color) 30%, transparent);
  box-shadow:
    inset 0 1.5px 1px rgba(255, 255, 255, 0.8),
    inset 0 -6px 12px color-mix(in srgb, var(--bot-color) 16%, transparent),
    0 4px 10px -4px color-mix(in srgb, var(--bot-color) 45%, transparent);
  line-height: 1;
  user-select: none;
}
.bot-avatar-xs {
  width: 26px;
  height: 26px;
  font-size: 14px;
}
.bot-avatar-sm {
  width: 28px;
  height: 28px;
  font-size: 15px;
}
.bot-avatar-md {
  width: 40px;
  height: 40px;
  font-size: 21px;
}
.bot-avatar-xl {
  width: 72px;
  height: 72px;
  font-size: 38px;
}
.bot-avatar-face {
  display: inline-block;
  transform-origin: 50% 80%;
}
.bot-avatar-working .bot-avatar-face {
  animation: bot-bob 1.6s ease-in-out infinite;
}
.bot-avatar-ring {
  position: absolute;
  inset: -4px;
  border-radius: 34%;
  border: 2px solid var(--bot-color);
  opacity: 0.7;
  animation: bot-ring 1.6s ease-out infinite;
  pointer-events: none;
}
.bot-avatar-paused {
  filter: grayscale(1);
  opacity: 0.6;
}
@keyframes bot-bob {
  0%,
  100% {
    transform: translateY(0) rotate(0deg);
  }
  30% {
    transform: translateY(-2px) rotate(-6deg);
  }
  60% {
    transform: translateY(0) rotate(5deg);
  }
}
@keyframes bot-ring {
  0% {
    transform: scale(0.85);
    opacity: 0.8;
  }
  100% {
    transform: scale(1.25);
    opacity: 0;
  }
}
@media (prefers-reduced-motion: reduce) {
  .bot-avatar-working .bot-avatar-face,
  .bot-avatar-ring,
  .bot-roster-state.working {
    animation: none;
  }
}

.bot-state-badge {
  text-transform: none;
}
/* Beside a paused bot's name in its chat head: the name gives way, the badge
   stays, and the line is no taller. */
.chat-head-title:has(> .bot-state-badge) {
  display: flex;
  align-items: center;
  gap: 8px;
}
.chat-head-title-text {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}
.chat-head-title .bot-state-badge {
  flex: none;
  height: 20px;
  margin-right: 4px;
  font-family: var(--font);
  letter-spacing: 0;
}
@media (max-width: 600px) {
  .chat-head-title .bot-state-badge {
    height: 18px;
    padding: 0 7px;
    font-size: 11px;
  }
}

/* Detail header: back and the actions on top, then who the bot is (the
   layout of a cron job's page). */
.bot-head {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas:
    'back actions'
    'main main';
  align-items: center;
  gap: 14px 16px;
  padding: 18px 28px 24px;
}
.bot-head-back {
  grid-area: back;
  justify-self: start;
  margin-left: -10px;
}
.bot-head-main {
  grid-area: main;
  display: flex;
  align-items: center;
  gap: 18px;
  min-width: 0;
}
.bot-head-text {
  min-width: 0;
}
.bot-head-name {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
}
.bot-head-text h2 {
  margin: 0;
  font-family: var(--font-display);
  font-size: 28px;
  font-weight: 500;
  letter-spacing: -0.035em;
  line-height: 1.15;
  overflow-wrap: anywhere;
}
.bot-head-title {
  margin: 4px 0 0;
  font-size: 14px;
  color: var(--text-secondary);
}
.bot-head-meta {
  margin: 4px 0 0;
  font-size: 12.5px;
  color: var(--text-muted);
}
.bot-head-actions {
  grid-area: actions;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
  flex-wrap: wrap;
}

/* Routines */
.bot-routine {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 16px;
  padding: 18px 28px;
  border-bottom: 1px solid var(--border);
}
.bot-routine:last-child {
  border-bottom: none;
}
.bot-routine-main {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.bot-routine-name-line {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
/* Two lines at most; the whole prompt is in the tooltip and the editor. */
.bot-routine-prompt {
  display: -webkit-box;
  max-width: 720px;
  overflow: hidden;
  font-size: 13px;
  color: var(--text-secondary);
  white-space: pre-wrap;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
}
.bot-routine-actions {
  display: flex;
  align-items: center;
  align-self: start;
  gap: 6px;
}
/* A paused routine dims, like a paused cron job. */
.bot-routine.is-paused .bot-routine-main {
  opacity: 0.55;
}

/* Create / edit forms */
.bot-form-grid {
  display: grid;
  grid-template-columns: 180px 1fr;
  gap: 20px;
  align-items: start;
}
.bot-form-grid-settings {
  grid-template-columns: 1fr 1fr;
  margin-top: 8px;
}
.bot-form-identity {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.bot-swatches {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
/* Even rows: twelve emoji as 6 × 2, ten colors in one row (5 × 2 where the
   column is narrow). */
.bot-emoji-swatches {
  display: grid;
  grid-template-columns: repeat(6, 30px);
}
.bot-color-swatches {
  display: grid;
  grid-template-columns: repeat(10, 22px);
}
.bot-form-identity .bot-emoji-swatches {
  grid-template-columns: repeat(4, 30px);
}
.bot-form-identity .bot-color-swatches {
  grid-template-columns: repeat(5, 22px);
}
.bot-swatch {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  border: 2px solid transparent;
  cursor: pointer;
  padding: 0;
  box-shadow: 0 0 0 1px var(--border-strong);
}
.bot-swatch-active {
  border-color: var(--surface);
  box-shadow: 0 0 0 2px var(--text);
}
.bot-check {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  font-size: 13px;
  margin: 8px 0;
  cursor: pointer;
}
.bot-check input,
.bot-integration-mode input,
.bot-integration-item input {
  flex: none;
  width: 15px;
  height: 15px;
  min-height: 0;
  margin: 0;
  padding: 0;
}
.bot-check input {
  margin-top: 2px;
}
.bot-integration-picker {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.bot-integration-mode {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  cursor: pointer;
}
.bot-integration-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
  gap: 4px 12px;
  max-height: 220px;
  overflow: auto;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface-muted);
}
.bot-integration-list-disabled {
  opacity: 0.5;
}
.bot-integration-item {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 12.5px;
  cursor: pointer;
  min-width: 0;
}
.bot-integration-inactive .bot-integration-name {
  color: var(--text-muted);
}
.bot-edit {
  padding: 22px 28px 8px;
}
/* Someone who can't change a bot reads its identity instead of a dead form. */
.bot-readonly {
  display: grid;
  gap: 16px;
  padding: 22px 28px 20px;
}
.bot-readonly-row {
  display: grid;
  grid-template-columns: 160px minmax(0, 1fr);
  gap: 4px 20px;
  align-items: baseline;
}
.bot-readonly-row > .field-label {
  margin: 0;
}
.bot-readonly-value {
  min-width: 0;
  color: var(--text);
  font-size: 14px;
  overflow-wrap: anywhere;
}
.bot-readonly-text {
  max-height: 320px;
  overflow: auto;
  padding: 12px 14px;
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  color: var(--text-secondary);
  font-size: 13.5px;
  line-height: 1.55;
  white-space: pre-wrap;
}
.bot-readonly-empty {
  color: var(--text-muted);
}
@media (max-width: 600px) {
  .bot-readonly {
    padding: 18px 20px;
  }
  .bot-readonly-row {
    grid-template-columns: minmax(0, 1fr);
  }
}
/* Unsaved identity edits float Save in reach on a phone; wider windows have
   the card's own button in view of the fields. */
@media (min-width: 601px) {
  .save-bar.bot-save-bar {
    display: none;
  }
}
/* Long-term memory: an on/off setting, so a switch like every other one. */
.bot-memory {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  margin: 4px 0 8px;
  cursor: pointer;
}
.bot-memory .toggle {
  margin-top: 1px;
}
.bot-memory-text {
  display: flex;
  flex-direction: column;
  min-width: 0;
}
.bot-memory-name {
  color: var(--text-secondary);
  font-size: 13px;
  font-weight: 500;
}
.bot-memory .field-hint {
  margin-top: 2px;
}

/* Chats list: bot-bound conversations */
.conv-item-bot {
  --bot-color: #6366f1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  font-size: 10px;
  line-height: 1;
  background: color-mix(in srgb, var(--bot-color) 20%, #ffffff);
  flex-shrink: 0;
}

@media (max-width: 720px) {
  .bot-form-grid,
  .bot-form-grid-settings {
    grid-template-columns: 1fr;
  }
  .bot-routine {
    grid-template-columns: 1fr;
  }
  .bot-head {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas:
      'back'
      'main'
      'actions';
  }
  .bot-head-main {
    align-items: flex-start;
  }
  /* Message, Pause and Retire keep one line beside a phone's edges. */
  .bot-head {
    padding: 16px 20px 20px;
  }
  .bot-head-main {
    gap: 14px;
  }
  .bot-head-actions {
    justify-content: flex-start;
    gap: 6px;
  }
  .bot-head .bot-avatar-xl {
    width: 44px;
    height: 44px;
    font-size: 24px;
  }
  .bot-head-text h2 {
    font-size: 24px;
  }
}

/* === Bots — chat-first roster (Grok Bot layout) === */

.bot-roster-item {
  position: relative;
  display: grid;
  grid-template-columns: 40px minmax(0, 1fr);
  align-items: center;
  gap: 10px;
  width: 100%;
  min-height: 60px;
  margin-bottom: 2px;
  padding: 8px;
  border: 0;
  border-radius: var(--radius);
  background: transparent;
  color: var(--text-muted);
  font-family: inherit;
  cursor: pointer;
  text-align: left;
  transition: background 0.1s ease;
}
.bot-roster-item:hover {
  background: var(--hover);
}
/* The same selected row as the Chats list. */
.bot-roster-item.active {
  --persona-eye: var(--surface);
  background: var(--surface);
  box-shadow:
    0 0 0 1px var(--border-card),
    0 4px 12px -6px rgba(26, 24, 43, 0.12);
}
.bot-roster-item.paused {
  opacity: 0.7;
}
/* Drag to reorder: a line where the bot will land. */
.bot-roster-item.dragging {
  opacity: 0.4;
}
.bot-roster-item.drop-before {
  box-shadow: inset 0 2px 0 var(--accent-text);
}
.bot-roster-item.drop-after {
  box-shadow: inset 0 -2px 0 var(--accent-text);
}
.bot-roster-item:focus-visible {
  outline: 2px solid var(--accent-text);
  outline-offset: -2px;
}
.bot-roster-body {
  display: grid;
  gap: 3px;
  min-width: 0;
}
.bot-roster-top {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}
.bot-roster-name {
  flex: 1;
  font-weight: 500;
  font-size: 13px;
  color: var(--text-secondary);
}
.bot-roster-item.active .bot-roster-name {
  color: var(--text);
}
.bot-roster-time {
  flex-shrink: 0;
  font-variant-numeric: tabular-nums;
  color: var(--text-faint);
  font-size: 10.5px;
}
.bot-roster-preview {
  font-size: 12px;
  color: var(--text-muted);
}
.bot-roster-preview-you {
  color: var(--text-faint);
}
.bot-roster-avatar {
  position: relative;
  display: grid;
  place-items: center;
}
/* A cut-out ring in the row's own colour, like the Chats list's corner dot. */
.bot-roster-state {
  position: absolute;
  right: 0;
  bottom: 0;
  width: 8px;
  height: 8px;
  border-radius: var(--radius-pill);
  box-shadow: 0 0 0 2px var(--persona-eye, var(--surface));
  background: var(--text-faint);
}
.bot-roster-state.working {
  background: var(--warn);
  animation: bot-pulse 1.2s ease-in-out infinite;
}
.bot-roster-state.idle {
  background: var(--ok);
}
.bot-roster-empty {
  padding: 28px 14px;
  text-align: center;
  color: var(--text-muted);
  font-size: 13px;
  line-height: 1.5;
}
.bot-roster-empty strong {
  display: block;
  color: var(--text);
  font-size: 14px;
  margin-bottom: 4px;
}
@keyframes bot-pulse {
  0%,
  100% {
    transform: scale(1);
    opacity: 1;
  }
  50% {
    transform: scale(1.35);
    opacity: 0.7;
  }
}

/* Quick create: name + avatar, then talk to it. */
.bot-quick-form {
  display: grid;
  gap: 14px;
}
.bot-quick-identity {
  display: grid;
  grid-template-columns: 72px minmax(0, 1fr);
  gap: 14px;
  align-items: center;
}
.bot-quick-identity .bot-avatar {
  justify-self: center;
}
.bot-quick-name {
  height: var(--control-h);
  font-size: 15px;
}
.bot-quick-hint {
  margin-top: 10px;
  margin-bottom: 6px;
  font-size: 12.5px;
  color: var(--text-muted);
  line-height: 1.5;
}
.bot-quick-avatar {
  display: grid;
  place-items: center;
}
.bot-emoji-swatch {
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  font-size: 16px;
  line-height: 1;
  background: var(--surface) !important;
  border: 1px solid var(--border);
}
.bot-quick-identity .bot-swatches {
  margin-top: 6px;
}
.bot-quick-templates {
  display: grid;
  gap: 6px;
}
.bot-quick-templates-title {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-faint);
}
.bot-quick-template {
  display: grid;
  grid-template-columns: 28px minmax(0, 1fr) auto;
  gap: 10px;
  align-items: center;
  padding: 7px 9px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--text-secondary);
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.bot-quick-template:hover {
  background: var(--hover);
}
/* Chosen: the accent edge and ring the scope options use, and a check. */
.bot-quick-template.active {
  border-color: color-mix(in srgb, var(--accent, #6366f1) 55%, var(--border));
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent, #6366f1) 18%, transparent);
  color: var(--text);
}
.bot-quick-template-check {
  display: inline-flex;
  color: var(--accent);
}
.bot-quick-template-check .icon {
  width: 15px;
  height: 15px;
}
.bot-quick-template-routines {
  display: flex;
  align-items: center;
  gap: 4px;
  margin-top: 4px;
  font-size: 11.5px;
  color: var(--text-muted);
}
.bot-quick-template-routines .icon {
  flex: none;
  width: 12px;
  height: 12px;
}
.bot-quick-template-name {
  font-weight: 500;
  font-size: 13px;
}
.bot-quick-template-desc {
  font-size: 11.5px;
  color: var(--text-muted);
}

/* Transcript events: something the bot did, not said. */
.msg-event {
  display: block;
  margin: 14px auto 10px;
  padding: 0 12px;
  font-size: 12px;
  line-height: 1.6;
  color: var(--text-muted);
  text-align: center;
}
.msg-event-icon {
  display: inline-flex;
  vertical-align: -2px;
}
.msg-event-verb {
  color: var(--text-faint);
}
.msg-event-icon .icon {
  width: 13px;
  height: 13px;
  opacity: 0.7;
}
.msg-event-label {
  font-weight: 500;
  color: var(--text-secondary);
  text-decoration: none;
}
a.msg-event-label:hover {
  color: var(--text);
  text-decoration: underline;
}
.msg-event-detail {
  color: var(--text-faint);
}
.msg-event-routine_ran .msg-event-label {
  font-weight: 400;
}

/* Roster groups: your personal bots, then the team's. */
.bot-roster-group {
  margin: 12px 8px 4px;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-faint);
}
.bot-roster-group:first-child {
  margin-top: 4px;
}
.bot-roster-lock {
  display: inline-flex;
  flex-shrink: 0;
  color: var(--text-faint);
}
.bot-roster-lock .icon {
  width: 12px;
  height: 12px;
}

/* Who a new bot is for. */
.bot-scope-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
}
.bot-scope-option {
  display: grid;
  gap: 2px;
  padding: 9px 11px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--text-secondary);
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.bot-scope-option span {
  font-size: 11.5px;
  color: var(--text-muted);
  line-height: 1.4;
}
.bot-scope-option:hover {
  background: var(--hover);
}
.bot-scope-option.active {
  border-color: color-mix(in srgb, var(--accent, #6366f1) 55%, var(--border));
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent, #6366f1) 18%, transparent);
  color: var(--text);
}
.bot-quick-roles .bot-quick-hint {
  margin-top: 0;
}
.bot-role-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.bot-role-chip {
  padding: 4px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--text-secondary);
  font: inherit;
  font-size: 12px;
  cursor: pointer;
}
.bot-role-chip:not(:disabled):hover {
  background: var(--hover);
}
.bot-role-chip.active {
  border-color: var(--role-color, var(--accent, #6366f1));
  background: color-mix(in srgb, var(--role-color, var(--accent, #6366f1)) 16%, transparent);
  color: var(--text);
}
.bot-role-chip:disabled {
  cursor: default;
  opacity: 0.8;
}
.bot-role-chip.active:not(:disabled):hover {
  background: color-mix(in srgb, var(--role-color, var(--accent, #6366f1)) 22%, transparent);
}
@media (max-width: 600px) {
  .bot-scope-row {
    grid-template-columns: 1fr;
  }
  /* Real touch targets, like Model pool's and Development's row actions. */
  .bot-routine-actions .conv-action {
    width: 40px;
    height: 40px;
  }
  .bot-routine-actions {
    gap: 8px;
  }
  .bot-integration-item {
    min-height: 36px;
  }
  .bot-role-chip {
    min-height: 36px;
    padding-inline: 14px;
  }
  /* One scroll on a long page: the integrations list isn't a box of its own. */
  .bot-integration-list {
    max-height: none;
    overflow: visible;
  }
  .bot-color-swatches,
  .bot-form-identity .bot-color-swatches {
    grid-template-columns: repeat(5, 28px);
    gap: 8px;
  }
  .bot-color-swatches .bot-swatch {
    width: 28px;
    height: 28px;
  }
}

/* What woke a bot: a routine, webhook, or another bot's message. */
.bot-task-turn {
  margin: 12px 0;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface-2, var(--hover));
}
.bot-task-head {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 12.5px;
  color: var(--text-muted);
  flex-wrap: wrap;
}
.bot-task-head .msg-time {
  margin-left: auto;
}
.bot-task-icon {
  display: inline-flex;
  color: var(--text-faint);
}
.bot-task-icon .icon {
  width: 13px;
  height: 13px;
}
.bot-task-label {
  color: var(--text-secondary);
  font-weight: 500;
}
a.bot-task-label {
  text-decoration: none;
}
a.bot-task-label:hover {
  text-decoration: underline;
  text-underline-offset: 2px;
}
.bot-task-by {
  color: var(--text-faint);
}
.bot-task-open-run {
  color: var(--text-muted);
  text-decoration: none;
  white-space: nowrap;
}
.bot-task-open-run:hover {
  color: var(--text-secondary);
  text-decoration: underline;
  text-underline-offset: 2px;
}
.bot-task-body {
  margin-top: 6px;
}
.bot-task-details {
  margin-top: 6px;
  font-size: 12.5px;
}
.bot-task-details summary {
  cursor: pointer;
  color: var(--text-muted);
}
.bot-task-payload {
  max-height: 260px;
  overflow: auto;
  margin-top: 6px;
  padding: 8px;
  border-radius: var(--radius-sm);
  background: var(--surface);
  font-size: 11.5px;
  white-space: pre-wrap;
  word-break: break-word;
}

/* A call report's recording, under its summary in chat. */
.phone-call-card-recording {
  display: grid;
  gap: 4px;
  margin-top: 8px;
}
.phone-call-audio {
  display: block;
  width: 100%;
  max-width: 480px;
  height: 36px;
}
.phone-call-recording-note {
  margin: 0;
  font-size: 12.5px;
  color: var(--text-muted);
}
.phone-call-open {
  justify-self: start;
  font-size: 12.5px;
  color: var(--text-muted);
}
.phone-call-open:hover {
  color: var(--text-secondary);
}

/* Calls page: the list, then one call with its player and transcript. */
.phone-calls-list {
  padding: 4px 0;
}
.phone-call-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 16px;
  color: var(--text);
  text-decoration: none;
  border-top: 1px solid var(--border);
}
.phone-call-row:first-child {
  border-top: 0;
}
.phone-call-row:hover {
  background: var(--hover);
}
.phone-call-row-icon {
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  flex: none;
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  color: var(--text-secondary);
}
.phone-call-row-main {
  display: grid;
  min-width: 0;
  flex: 1;
  gap: 2px;
}
.phone-call-row-title {
  font-weight: 560;
  font-variant-numeric: tabular-nums;
}
.phone-call-row-for {
  font-weight: 400;
  color: var(--text-muted);
}
.phone-call-row-goal {
  font-size: 12.5px;
  color: var(--text-muted);
}
.phone-call-row-meta {
  display: flex;
  align-items: center;
  gap: 10px;
  flex: none;
}
.phone-call-row-rec {
  display: inline-flex;
  color: var(--text-faint);
}
.phone-call-row-when {
  min-width: 72px;
  font-size: 12.5px;
  color: var(--text-muted);
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.phone-call-detail {
  display: grid;
  gap: 14px;
}
.phone-call-back {
  justify-self: start;
  font-size: 13px;
  color: var(--text-muted);
  text-decoration: none;
}
.phone-call-back:hover {
  color: var(--text);
}
.phone-call-head,
.phone-call-transcript {
  display: grid;
  gap: 10px;
  padding: 16px 18px;
}
.phone-call-head-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.phone-call-head-title {
  margin: 0;
  font-size: 18px;
  font-variant-numeric: tabular-nums;
}
.phone-call-head-meta {
  font-size: 12.5px;
  color: var(--text-muted);
}
.phone-call-field strong {
  font-size: 12px;
  color: var(--text-muted);
  font-weight: 560;
}
.phone-call-field p {
  margin: 2px 0 0;
  white-space: pre-wrap;
}
.phone-call-player .phone-call-audio {
  max-width: none;
  height: 40px;
}
.phone-call-transcript-title {
  margin: 0;
  font-size: 14px;
}
.phone-call-lines {
  display: grid;
  gap: 2px;
}
.phone-call-line {
  display: grid;
  grid-template-columns: 48px 92px 1fr;
  gap: 8px;
  align-items: baseline;
  padding: 6px 8px;
  border-radius: var(--radius-sm);
}
.phone-call-line.is-playing {
  background: var(--surface-2);
}
.phone-call-line-time {
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  font-size: 12px;
  color: var(--text-faint);
  text-align: left;
  font-variant-numeric: tabular-nums;
  cursor: pointer;
}
.phone-call-line-time:hover:not(:disabled) {
  color: var(--accent-text);
  text-decoration: underline;
}
.phone-call-line-time:disabled {
  cursor: default;
}
.phone-call-line-who {
  font-size: 12.5px;
  font-weight: 560;
  color: var(--text-secondary);
}
.phone-call-line-assistant .phone-call-line-who {
  color: var(--accent-text);
}
.phone-call-line-text {
  white-space: pre-wrap;
  word-break: break-word;
}
@media (max-width: 640px) {
  .phone-call-row-goal {
    white-space: normal;
  }
  .phone-call-row-when {
    display: none;
  }
  .phone-call-line {
    grid-template-columns: 40px 1fr;
  }
  .phone-call-line-text {
    grid-column: 2;
  }
}

/* A team bot's access card: in line with its header and actions. */
.bot-access-body {
  display: grid;
  gap: 10px;
  padding: 18px 28px 20px;
}
.bot-access-body .field-hint a {
  color: var(--accent-text);
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* A bot's Activity: a personal routine run, webhook call or message is a run row that
   opens the chat (a link, so no chevron), led by what woke it. */
a.cron-run-row {
  color: inherit;
  text-decoration: none;
}
.cron-run-source {
  display: inline-block;
  margin-right: 8px;
  padding: 1px 8px;
  border-radius: var(--radius-pill);
  background: var(--surface-2);
  color: var(--text-muted);
  font-size: 11.5px;
  font-weight: 500;
  vertical-align: 1px;
}

/* The webhook's curl example: a code block of its own, not bare text. */
.bot-webhook-curl-label {
  margin: 14px 0 6px;
}
.bot-webhook-curl {
  margin: 0;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  font-family: var(--mono);
  font-size: 12px;
  line-height: 1.5;
  white-space: pre-wrap;
  word-break: break-all;
}

/* Over a paused bot's composer: a slim notice, Resume at its end. */
.bot-paused-note {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  width: min(720px, calc(100% - 48px));
  margin: 8px auto 0;
  padding: 7px 8px 7px 16px;
  font-size: 13px;
}
.bot-paused-note .btn {
  flex: none;
}
@media (max-width: 600px) {
  .bot-paused-note {
    width: calc(100% - 16px);
    padding-left: 14px;
    font-size: 12.5px;
    line-height: 1.45;
  }
}

/* Progress bubbles posted mid-run: same voice, lighter weight. */
.msg-interim .msg-content {
  color: var(--text-secondary);
}

/* Suggestion lists (timezones) open as you type: no native arrow. Chrome's
   own rule for it is !important, so this one has to be too. */
input[list]::-webkit-calendar-picker-indicator {
  display: none !important;
}

/* A bot's name keeps room beside the header pills. */
.bots-shell .chat-head-leading {
  min-width: 160px;
}

.msg-pending-attachments {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  margin-top: 7px;
  color: var(--text-faint);
  font-size: 11px;
}

.msg-pending-attachments > span {
  padding: 2px 6px;
  border-radius: var(--radius-xs);
  background: var(--surface-2);
}

/* Company page: monospace JSON editor. */
textarea.code-textarea {
  font-family: var(--mono);
  font-size: 12px;
  line-height: 1.5;
  /* Code keeps its lines: long ones scroll sideways instead of wrapping. */
  white-space: pre;
  overflow-x: auto;
  overflow-wrap: normal;
}

/* Each editor sits inside its card with the card's own inset. */
.card-body.company-editor {
  padding: 20px 28px 24px;
}
.company-editor textarea {
  display: block;
}
/* Nothing can be saved without a volume: the editors say so by look too. */
.company-editor textarea[readonly] {
  background: var(--surface-muted);
  color: var(--text-secondary);
}
/* An error under an editor scrolls in above the floating save bar. */
.company-editor .field-error {
  scroll-margin-bottom: 140px;
}
/* Settings still on the shipped defaults: a badge by the title, and what
   the first save does under the description. */
.card-title-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 10px;
}
.card-header-text p.company-defaults-note {
  margin-top: 2px;
}

/* "Continue with Google" on a hosted organization's sign-in page: Google's
   neutral pill, as on the front door and dealseek.com. */
.btn-google {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  width: 100%;
  min-height: 48px;
  padding: 12px 20px;
  border: 0;
  border-radius: var(--radius-pill);
  background: #f2f2f2;
  color: #1f1f1f;
  font-weight: 500;
  text-decoration: none;
  transition: filter 0.15s ease;
}
.btn-google:hover {
  background: #f2f2f2;
  color: #1f1f1f;
  filter: brightness(0.95);
}
.btn-google-mark {
  display: inline-flex;
}
.btn-google-mark svg {
  width: 20px;
  height: 20px;
}
.login-divider {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 14px 0 2px;
  color: var(--text-faint);
  font-size: 12px;
}
.login-divider::before,
.login-divider::after {
  content: '';
  flex: 1;
  border-top: 1px solid var(--border);
}

/* Team: one card holding the members table (renderTeam). */
.team-search {
  flex: 0 1 230px;
  width: auto;
  min-width: 180px;
}
.team-filters {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  margin-top: -6px;
}
/* The table stacks by the card's own width, not the window's: beside the
   full sidebar, a 1024px window leaves too little room for its columns. */
.team-card {
  overflow: hidden;
  container: team-card / inline-size;
}
.team-row {
  display: grid;
  grid-template-columns:
    minmax(200px, 1.25fr) minmax(210px, 1.35fr) minmax(190px, 1.1fr)
    minmax(140px, 0.8fr) 36px;
  align-items: center;
  gap: 16px;
  padding: 12px 28px;
  border-bottom: 1px solid var(--border);
}
.team-row:last-child {
  border-bottom: 0;
}
.team-row:not(.team-head):hover {
  background: var(--surface-muted);
}
.team-head {
  padding-top: 14px;
  padding-bottom: 10px;
  color: var(--text-faint);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.team-cell {
  min-width: 0;
}
.team-member {
  display: flex;
  align-items: center;
  gap: 12px;
}
.team-avatar {
  flex: none;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  object-fit: cover;
}
.team-avatar-letter {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--grad-avatar);
  color: #fff;
  font-size: 13px;
  font-weight: 500;
}
/* Six tones, one per member (teamAvatar picks it from the email), so a
   column of initials tells people apart. */
.team-avatar-letter.tone-1 {
  background: linear-gradient(135deg, var(--lm-orange-300), var(--lm-orange-700));
}
.team-avatar-letter.tone-2 {
  background: linear-gradient(135deg, #b8b2e0, var(--lm-indigo));
}
.team-avatar-letter.tone-3 {
  background: linear-gradient(135deg, #f9a8d4, #be185d);
}
.team-avatar-letter.tone-4 {
  background: linear-gradient(135deg, #7fcfa6, #2f9e6b);
}
.team-avatar-letter.tone-5 {
  background: linear-gradient(135deg, #9cc2f7, #3b5bdb);
}
.team-member-text {
  min-width: 0;
}
.team-member-name {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  color: var(--text);
  font-size: 13.5px;
  font-weight: 500;
}
.team-member-name-text {
  min-width: 0;
}
/* An empty cell (no roles, no linked accounts): one quiet dash. */
.team-muted {
  color: var(--text-faint);
  font-size: 12.5px;
}
.team-member-email {
  color: var(--text-faint);
  font-size: 12px;
}
.team-you {
  padding: 0 7px;
  border-radius: var(--radius-pill);
  background: var(--accent-soft);
  color: var(--accent-text);
  font-size: 10.5px;
  font-weight: 500;
  line-height: 17px;
}
.access-chip,
.link-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  max-width: 100%;
  height: 26px;
  padding: 0 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  background: var(--surface);
  color: var(--text-secondary);
  font: inherit;
  font-size: 12.5px;
  font-weight: 500;
  white-space: nowrap;
}
button.access-chip,
button.link-chip {
  cursor: pointer;
  transition:
    border-color 0.12s ease,
    color 0.12s ease;
}
button.access-chip:hover,
button.link-chip:hover {
  border-color: var(--border-strong);
  color: var(--text);
}
.access-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--text-faint);
}
.access-chip.is-admin .access-dot {
  background: var(--lm-orange-500);
}
.access-chip-caret {
  width: 5px;
  height: 5px;
  margin: -3px 1px 0 2px;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  opacity: 0.55;
  transform: rotate(45deg);
}
.team-links,
.team-role {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
/* Role chips in the table sit at the table's chip size. */
.team-role .role-chip {
  height: 26px;
  padding: 0 10px;
  background: var(--surface);
  color: var(--text-secondary);
  font-size: 12.5px;
  line-height: normal;
}
.team-role .role-chip .brand-icon {
  width: 13px;
  height: 13px;
}
/* Synced from Discord: the same chip, ending in a quiet Discord mark. */
.role-chip .brand-icon.role-chip-source {
  width: 12px;
  height: 12px;
  color: var(--text-faint);
}
/* More roles than fit: "+2", named in its tooltip. */
.team-role .role-chip.role-more {
  padding: 0 9px;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}
/* For whoever assigns roles, the chips and the + are one button: any of them
   opens the member's roles, and hovering lifts them together. */
.team-role-edit {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  min-width: 0;
  max-width: 100%;
  padding: 0;
  border: 0;
  border-radius: 14px;
  background: none;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.team-role-edit .role-chip,
.team-role-edit .role-add {
  transition:
    border-color 0.12s ease,
    color 0.12s ease;
}
.team-role-edit:hover .role-chip,
.team-role-edit:hover .role-add {
  border-color: var(--border-strong);
}
.team-role-edit:hover .role-add {
  color: var(--text);
}
/* The last chip and the + wrap as one, so the + never sits alone. */
.role-tail {
  display: inline-flex;
  gap: 6px;
  min-width: 0;
  max-width: 100%;
}
.role-add {
  justify-content: center;
  width: 26px;
  padding: 0;
}
.link-chip.is-empty.role-add {
  border-color: var(--border-strong);
  color: var(--text-muted);
}
.role-add .icon {
  width: 13px;
  height: 13px;
}
.role-add.has-label {
  width: auto;
  padding: 0 11px 0 9px;
  gap: 5px;
}
/* Tabs that are links (Team's Members | Roles, Vault's Logins & keys | Secrets). */
:is(.team-tabs, .vault-tabs) .seg-btn {
  text-decoration: none;
}
.team-note {
  max-width: 72ch;
  margin: -4px 0 0;
  color: var(--text-muted);
  font-size: 13px;
  line-height: 1.5;
}
.link-chip {
  padding-left: 8px;
}
.link-chip .brand-icon {
  width: 14px;
  height: 14px;
}
.link-chip-discord .brand-icon {
  color: #5865f2;
}
.link-chip-text {
  overflow: hidden;
  text-overflow: ellipsis;
}
.link-chip.is-empty {
  border-style: dashed;
  color: var(--text-faint);
}
.link-chip.is-empty .brand-icon {
  color: var(--text-faint);
  opacity: 0.7;
}
.team-status {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 7px;
  color: var(--text-muted);
  font-size: 12.5px;
}
.team-status-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--ok);
}
.team-status.is-invited .team-status-dot {
  background: var(--warn);
}
.team-status.is-expired {
  color: var(--danger-text);
}
.team-status.is-expired .team-status-dot {
  background: var(--danger);
}
/* An action inside the status line (Resend): ink and underlined, so it reads
   as a link apart from a red "Invite expired". */
.team-status-action {
  padding: 0;
  border: 0;
  background: none;
  color: var(--text);
  font: inherit;
  font-weight: 500;
  text-decoration: underline;
  text-decoration-color: var(--border-strong);
  text-underline-offset: 2px;
  cursor: pointer;
}
.team-status-action:hover {
  text-decoration-color: currentColor;
}
.team-actions {
  display: flex;
  justify-content: flex-end;
}
.team-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 28px;
  border-top: 1px solid var(--border);
  background: var(--surface-muted);
}
.team-join {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 10px;
  color: var(--text-muted);
  font-size: 12.5px;
}
.team-join-hint {
  color: var(--text-faint);
  font-size: 12px;
  overflow-wrap: anywhere;
}
/* Roles that didn't load: said once above the table, with Try again. */
.alert.team-alert {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 10px 16px;
  padding-block: 9px;
}
/* A role's name opens its editor (admins). */
.roles-name-btn {
  padding: 0;
  border: 0;
  border-radius: 6px;
  background: none;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.roles-name-btn:hover {
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* A role's member count opens the Members tab searched for it. */
.roles-people-link {
  text-decoration: none;
}
.roles-people-link:hover {
  color: var(--text);
  text-decoration: underline;
  text-underline-offset: 2px;
}
/* The phone Invite / New role: the + alone (the label stays for screen
   readers), so the tabs and the button share one row on both tabs. */
@media (max-width: 600px) {
  .team-search {
    flex: 1 1 100%;
  }
  .team-toolbar .btn-cta {
    width: var(--control-h);
    padding: 0;
    justify-content: center;
  }
  .team-toolbar .btn-cta .team-cta-label {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
  }
}

/* A panel anchored to a control (showPopover): the account-link search.
   Same surface as the context menu: card hairline, --radius-xl, float. */
.popover {
  position: fixed;
  z-index: 1000;
  width: min(340px, calc(100vw - 16px));
  padding: 10px;
  border: 1px solid var(--border-card);
  border-radius: var(--radius-xl);
  background: var(--surface);
  box-shadow: var(--shadow-float);
}
.link-popover-head {
  padding: 2px 4px 8px;
  color: var(--text-faint);
  font-size: 12px;
}
.link-search {
  width: 100%;
}
.link-error {
  margin-top: 8px;
  padding: 7px 10px;
  border-radius: 10px;
  background: var(--danger-soft);
  color: var(--danger-text);
  font-size: 12.5px;
}
.link-results {
  display: flex;
  flex-direction: column;
  gap: 2px;
  max-height: 280px;
  margin-top: 8px;
  overflow-y: auto;
}
.link-option {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 7px 8px;
  border: 0;
  border-radius: 10px;
  background: none;
  color: var(--text);
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.link-option:hover,
.link-option.is-active {
  background: var(--surface-muted);
}
/* The list scrolls, which would clip an outside ring: it's drawn inside. */
.link-option:focus-visible {
  outline: none;
  background: var(--surface-muted);
  box-shadow: inset 0 0 0 2px var(--accent-hover);
}
.link-option.is-current {
  background: var(--accent-soft);
}
/* Accounts linked to someone else can't be picked (the server refuses them). */
.link-option.is-taken {
  opacity: var(--disabled-opacity);
  cursor: default;
}
.link-option.is-taken:hover {
  background: none;
}
.link-group-label {
  padding: 10px 8px 4px;
  color: var(--text-faint);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.link-option-avatar {
  flex: none;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  object-fit: cover;
}
.link-option-letter {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--surface-2);
  color: var(--text-secondary);
  font-size: 11px;
  font-weight: 500;
}
.link-option-text {
  display: flex;
  flex: 1;
  flex-direction: column;
  min-width: 0;
}
.link-option-name {
  font-size: 13px;
  font-weight: 500;
}
.link-option-detail {
  color: var(--text-faint);
  font-size: 11.5px;
}
.link-option .icon {
  color: var(--accent-text);
}
.link-empty {
  padding: 14px 8px;
  color: var(--text-faint);
  font-size: 12.5px;
  text-align: center;
}
.link-popover-foot {
  display: flex;
  justify-content: flex-end;
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px solid var(--border);
}

/* A member's roles (openMemberRolesPopover) */
.role-options {
  display: flex;
  flex-direction: column;
  gap: 2px;
  max-height: 300px;
  overflow-y: auto;
}
.role-option {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px;
  border-radius: 10px;
  cursor: pointer;
}
.role-option:hover {
  background: var(--surface-muted);
}
.role-option.is-synced {
  cursor: default;
}
.role-option input {
  flex: none;
  width: 16px;
  height: 16px;
}
.role-option .role-dot {
  margin: 0 -2px 0 -2px;
}
/* A role you can't give fades (box, dot, name, mark) and says why in a line
   that stays readable. Rows locked by Discord say "From Discord" instead. */
.role-option.is-disabled {
  cursor: default;
}
.role-option.is-disabled:hover {
  background: none;
}
.role-option.is-disabled > input,
.role-option.is-disabled > .role-dot,
.role-option.is-disabled > .brand-icon,
.role-option.is-disabled .role-option-name {
  opacity: var(--disabled-opacity);
}
.role-option-detail.is-reason {
  color: var(--text-muted);
}
.role-option-text {
  display: flex;
  flex: 1;
  flex-direction: column;
  min-width: 0;
}
.role-option-name {
  color: var(--text);
  font-size: 13px;
  font-weight: 500;
}
.role-option-detail {
  color: var(--text-faint);
  font-size: 11.5px;
}
.role-option .brand-icon {
  flex: none;
  width: 13px;
  height: 13px;
  color: #5865f2;
}
/* A member's roles popover: a taller list that fades at the bottom while
   more roles are below the fold. In a popover cut short by the window, the
   list is what shrinks, so the heading and Manage roles stay. */
.popover:has(> .role-popover) {
  display: flex;
  flex-direction: column;
}
.role-popover {
  display: flex;
  flex-direction: column;
  min-height: 0;
}
.role-popover .role-options {
  min-height: 0;
  max-height: min(60vh, 420px);
}
.role-popover .role-options.has-more {
  -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 28px), transparent);
  mask-image: linear-gradient(to bottom, #000 calc(100% - 28px), transparent);
}

/* Roles tab */
.roles-row {
  display: grid;
  grid-template-columns:
    minmax(220px, 1.5fr) minmax(130px, 0.9fr) minmax(150px, 0.9fr)
    minmax(170px, 1fr) 36px;
  align-items: center;
  gap: 16px;
  padding: 12px 28px;
  border-bottom: 1px solid var(--border);
}
.roles-row:last-child {
  border-bottom: 0;
}
.roles-row:not(.team-head):hover {
  background: var(--surface-muted);
}
.roles-cell {
  min-width: 0;
}
.roles-name {
  display: flex;
  align-items: center;
  gap: 12px;
}
.roles-mark {
  display: inline-flex;
  flex: none;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border-radius: var(--radius-md);
  background: linear-gradient(135deg, rgba(122, 29, 110, 0.12), rgba(21, 0, 121, 0.1));
  color: var(--lm-plum);
}
.roles-mark .icon {
  width: 15px;
  height: 15px;
}
.roles-muted {
  color: var(--text-muted);
  font-size: 12.5px;
}
.roles-access {
  color: var(--text-secondary);
  font-size: 12.5px;
  font-weight: 500;
}
.roles-access.is-admin {
  color: var(--accent-text);
}
.roles-people {
  display: flex;
  align-items: center;
  gap: 10px;
}
.avatar-stack {
  display: inline-flex;
}
.avatar-stack .team-avatar {
  width: 24px;
  height: 24px;
  margin-left: -6px;
  border: 2px solid var(--surface);
  font-size: 10px;
}
.avatar-stack .team-avatar:first-child {
  margin-left: 0;
}

/* Role chips and options carry the role's color as a dot; Admin leans orange. */
.role-dot {
  flex: none;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--text-faint);
}
.role-dot.is-admin:not([style]) {
  background: var(--lm-orange-500);
}

/* Role editor (openRoleEditor) */
.role-editor-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 14px 16px;
}
.role-editor-grid .field {
  margin: 0;
}
.role-field-wide {
  grid-column: 1 / -1;
}
.role-swatches {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  min-height: var(--control-h);
}
.role-swatch {
  width: 22px;
  height: 22px;
  padding: 0;
  border: 2px solid var(--surface);
  border-radius: 50%;
  box-shadow: 0 0 0 1px var(--border);
  cursor: pointer;
}
.role-swatch.active {
  box-shadow: 0 0 0 2px var(--text);
}
.role-editor-section {
  margin: 20px 0 10px;
  color: var(--text-faint);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.perm-note {
  margin: -4px 0 10px;
  color: var(--text-muted);
  font-size: 12.5px;
  line-height: 1.45;
}
.perm-admin {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px 16px;
  border-radius: 16px;
  background: linear-gradient(135deg, rgba(122, 29, 110, 0.08), rgba(21, 0, 121, 0.07));
  cursor: pointer;
}
/* Something you can't grant: the same fade as a role you can't give; why is
   said once, under the heading (.perm-note). */
.perm-admin.is-disabled {
  cursor: default;
}
.perm-admin.is-disabled .perm-name,
.perm-admin.is-disabled .perm-desc,
.perm-option.is-disabled > input,
.perm-option.is-disabled .perm-name,
.perm-option.is-disabled .perm-desc {
  opacity: var(--disabled-opacity);
}
.perm-admin .perm-text {
  flex: 1;
}
.perm-list {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 2px 12px;
  margin-top: 10px;
}
.perm-option {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 8px;
  border-radius: 10px;
  cursor: pointer;
}
.perm-option:hover {
  background: var(--surface-muted);
}
.perm-option input {
  flex: none;
  width: 16px;
  height: 16px;
  margin-top: 1px;
  accent-color: var(--ink, #1a182b);
}
.perm-option:has(input:disabled) {
  cursor: default;
}
.perm-option.is-disabled:hover {
  background: none;
}
.perm-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.perm-name {
  color: var(--text);
  font-size: 13px;
  font-weight: 500;
}
.perm-desc {
  color: var(--text-faint);
  font-size: 11.5px;
  line-height: 1.4;
}
@media (max-width: 600px) {
  .perm-list,
  .role-editor-grid {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* Invite dialog */
.invite-emails {
  width: 100%;
  min-height: 84px;
  resize: vertical;
}
/* Invites that didn't go: one address and its reason per line. */
.invite-dialog .field-error {
  white-space: pre-line;
}
/* In a dialog the body scrolls, so role lists don't need their own scroll;
   the rows' hover wash runs into the gutter so the boxes line up with labels. */
.modal-dialog .role-options {
  max-height: none;
  margin-inline: -8px;
  overflow: visible;
}

/* A narrower card (a 1024px window beside the sidebar): three columns, with
   the linked accounts under the member and a role's source under its access. */
@container team-card (min-width: 601px) and (max-width: 900px) {
  .team-row {
    /* A fixed status track, so every row's columns line up with the head
       whatever its status says ("Invited · expires in 5d" fits). */
    grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr) 150px 36px;
    grid-template-areas:
      'member role status actions'
      'links role status actions';
    gap: 6px 14px;
    padding: 12px 20px;
  }
  .team-row.team-head {
    grid-template-areas: 'member role status actions';
    padding-top: 14px;
    padding-bottom: 10px;
  }
  .team-head > :nth-child(1) {
    grid-area: member;
  }
  .team-head > :nth-child(2) {
    grid-area: role;
  }
  .team-head > :nth-child(3) {
    display: none;
  }
  .team-head > :nth-child(4) {
    grid-area: status;
  }
  .team-head > :nth-child(5) {
    grid-area: actions;
  }
  .team-member {
    grid-area: member;
  }
  .team-role {
    grid-area: role;
  }
  /* Under the name: past the 34px avatar and its 12px gap. */
  .team-links {
    grid-area: links;
    padding-left: 46px;
  }
  .team-status {
    grid-area: status;
  }
  .team-actions {
    grid-area: actions;
  }
  .roles-row {
    grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr) minmax(0, 1fr) 36px;
    grid-template-areas:
      'name access people actions'
      'name source people actions';
    gap: 6px 14px;
    padding: 12px 20px;
  }
  .roles-row.team-head {
    grid-template-areas: 'name access people actions';
  }
  .roles-row.team-head > :nth-child(1) {
    grid-area: name;
  }
  .roles-row.team-head > :nth-child(2) {
    grid-area: access;
  }
  .roles-row.team-head > :nth-child(3) {
    display: none;
  }
  .roles-row.team-head > :nth-child(4) {
    grid-area: people;
  }
  .roles-row.team-head > :nth-child(5) {
    grid-area: actions;
  }
  .roles-name {
    grid-area: name;
  }
  .roles-access-cell {
    grid-area: access;
  }
  .roles-source {
    grid-area: source;
  }
  .roles-people {
    grid-area: people;
  }
  .roles-row > .team-actions {
    grid-area: actions;
  }
}

/* A phone-width card: each member and role stacks into a small card. */
@container team-card (max-width: 600px) {
  /* A role: its name and ⋯, then one line of what it allows and who has it,
     split by a dot; a Discord role's source chip goes under it ("Assigned
     here", the default, is left out). */
  .roles-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px 8px;
    padding: 14px 16px;
  }
  .team-head,
  .roles-row.team-head {
    display: none;
  }
  .roles-name {
    flex: 1 1 calc(100% - 48px);
    min-width: 0;
  }
  .roles-row > .team-actions {
    flex: none;
    order: 1;
  }
  .roles-access-cell,
  .roles-source,
  .roles-people {
    display: inline-flex;
    flex: none;
    order: 2;
    align-items: center;
    max-width: 100%;
  }
  .roles-source {
    flex-basis: 100%;
    order: 3;
  }
  .roles-source:not(:has(.link-chip)) {
    display: none;
  }
  .roles-people::before {
    content: '·';
    margin-right: 8px;
    color: var(--text-faint);
  }
  .roles-people-discord {
    display: none;
  }
  .roles-people {
    gap: 8px;
  }
  .roles-people .avatar-stack {
    display: none;
  }
  .team-row {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas:
      'member actions'
      'role role'
      'links links'
      'status status';
    gap: 8px 12px;
    padding: 14px 16px;
  }
  .team-member {
    grid-area: member;
  }
  .team-role {
    grid-area: role;
  }
  .team-links {
    grid-area: links;
  }
  .team-status {
    grid-area: status;
  }
  .team-actions {
    grid-area: actions;
  }
  /* A thumb-sized ⋯ (the only way to Remove or Resend here); the negative
     margin keeps the glyph and the card's height where they were. */
  .team-more {
    width: 40px;
    height: 40px;
    margin: -8px -8px -8px 0;
  }
}

@container team-card (max-width: 900px) {
  .team-foot {
    padding: 12px 16px;
  }
  .team-join {
    flex: 1 1 100%;
  }
  .team-join select.input-inline {
    width: auto;
    min-width: 0;
    max-width: 100%;
    margin: 0;
  }
}

/* Audit log page: filters, then the search and its count, then entries
   grouped by day. Two fixed rows, so typing or filtering never moves the
   list below. */
.audit-toolbar {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.audit-toolbar-filters,
.audit-toolbar-search {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  min-width: 0;
}
.audit-toolbar-search {
  flex-wrap: nowrap;
}
.audit-filter,
.audit-actor-filter {
  width: auto;
  min-width: 170px;
  max-width: 260px;
}
.audit-search {
  flex: 1 1 320px;
  width: auto;
  min-width: 0;
  max-width: 420px;
}
.audit-count {
  flex: none;
  margin-left: auto;
  min-width: 18ch;
  color: var(--text-faint);
  font-size: 12.5px;
  font-variant-numeric: tabular-nums;
  text-align: right;
  white-space: nowrap;
}
/* clip, not hidden: rounds the corners without becoming a scroll container,
   so the day labels stick to the top of the pane. */
.audit-card {
  overflow: clip;
}
.audit-day + .audit-day {
  border-top: 1px solid var(--border);
}
/* Sticks at the pane's very top edge: -22px undoes the pane's top padding
   (12px on narrow windows), so no row shows above the label. */
.audit-day-label {
  position: sticky;
  top: -22px;
  z-index: 1;
  margin: 0;
  padding: 14px 24px 8px;
  background: var(--surface);
  color: var(--text-faint);
  font-family: var(--font);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.audit-row > summary,
div.audit-row {
  display: grid;
  grid-template-columns: 28px minmax(0, 1fr) auto 64px 16px;
  align-items: center;
  gap: 12px;
  padding: 9px 24px;
  font-size: 13px;
  line-height: 1.45;
}
.audit-row > summary {
  list-style: none;
  cursor: pointer;
}
.audit-row > summary::-webkit-details-marker {
  display: none;
}
.audit-row > summary:hover,
div.audit-row:hover {
  background: var(--surface-muted);
}
.audit-row[open] > summary {
  background: var(--surface-muted);
}
/* Two open rows in a row stay two. */
.audit-row[open] + .audit-row[open] {
  border-top: 1px solid var(--border);
}
/* A row that opens ends in a chevron (right when closed, down when open), in
   a column of its own so they line up. */
.audit-chevron {
  display: inline-flex;
  justify-content: center;
  color: var(--text-faint);
}
.audit-chevron .icon {
  width: 14px;
  height: 14px;
  transform: rotate(-90deg);
  transition: transform 0.15s ease;
}
.audit-row[open] > summary .audit-chevron .icon {
  transform: none;
}
/* Filtered to one area, every badge would say it: they go, and so does
   their column. */
.audit-card.is-area-filtered .audit-area {
  display: none;
}
.audit-card.is-area-filtered .audit-row > summary,
.audit-card.is-area-filtered div.audit-row {
  grid-template-columns: 28px minmax(0, 1fr) 64px 16px;
}
/* Another filter's rows on their way: the ones there stay, dimmed, so the
   card keeps its height and the page its place. */
.audit-days,
.audit-state {
  transition: opacity 0.15s ease;
}
.audit-card.is-reloading .audit-days,
.audit-card.is-reloading .audit-state {
  opacity: 0.5;
  pointer-events: none;
}
/* The focus ring drawn inside the row, so the card's edge can't clip it. */
.audit-row > summary:focus-visible {
  outline: none;
  border-radius: var(--radius-sm);
  background: var(--surface-muted);
  box-shadow: inset 0 0 0 2px var(--accent);
}
.audit-avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--surface-2);
  color: var(--text-secondary);
  font-size: 11px;
  font-weight: 500;
}
.audit-avatar.is-discord {
  background: rgba(88, 101, 242, 0.1);
  color: #5865f2;
}
.audit-avatar .brand-icon {
  display: inline-flex;
  width: 14px;
  height: 14px;
}
.team-avatar.is-audit {
  width: 28px;
  height: 28px;
  font-size: 11px;
}
.audit-sentence {
  min-width: 0;
  color: var(--text-secondary);
  overflow-wrap: anywhere;
}
.audit-actor {
  font-weight: 500;
  color: var(--text);
}
/* An identifier (secret, tool, account): code, kept whole on the next line
   when it fits one; a longer one breaks after a _ - . / or : (auditCode). */
.audit-target {
  display: inline-block;
  max-width: 100%;
  vertical-align: baseline;
  font-family: var(--mono);
  font-size: 12px;
  line-height: 1.5;
  padding: 0 6px;
  border-radius: var(--radius-xs);
  background: var(--surface-2);
  color: var(--text);
  overflow-wrap: anywhere;
}
/* A name (a person, role, app, job): plain text a step stronger. */
.audit-target-name {
  color: var(--text);
  font-weight: 500;
}
.audit-when {
  color: var(--text-faint);
  font-size: 12px;
  text-align: right;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.audit-detail {
  display: grid;
  grid-template-columns: 120px minmax(0, 1fr);
  gap: 5px 14px;
  margin: 0;
  padding: 4px 24px 14px 64px;
  background: var(--surface-muted);
  font-size: 12.5px;
}
.audit-detail dt {
  color: var(--text-faint);
}
.audit-detail dd {
  margin: 0;
  color: var(--text-secondary);
  overflow-wrap: anywhere;
}
.audit-detail dd.is-code {
  font-family: var(--mono);
  font-size: 12px;
}
/* A role color beside its name. */
.audit-swatch {
  display: inline-block;
  width: 9px;
  height: 9px;
  margin-right: 6px;
  border-radius: 50%;
  vertical-align: 0;
}
.audit-detail .audit-detail-event {
  color: var(--text-faint);
  font-size: 11px;
}
.audit-loading {
  padding: 18px 24px;
  font-size: 13px;
}
.audit-footer {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  padding: 12px;
  border-top: 1px solid var(--border);
}
.audit-older-error {
  align-self: stretch;
  padding-block: 9px;
}
.audit-card .audit-state {
  padding: 48px 24px;
}
.audit-state .grid-empty-title {
  font-size: 20px;
}
@media (max-width: 900px) {
  .audit-day-label {
    top: -12px;
  }
}
@media (max-width: 600px) {
  /* The two filters share a row, then the range; the search and count below. */
  .audit-filter,
  .audit-actor-filter {
    flex: 1 1 140px;
    min-width: 0;
    max-width: none;
  }
  /* The search takes the width; its count gets a line of its own. */
  .audit-toolbar-search {
    flex-wrap: wrap;
    row-gap: 6px;
  }
  .audit-search {
    flex: 1 1 100%;
    max-width: none;
  }
  .audit-count {
    min-width: 0;
    min-height: 1lh;
    margin-left: 0;
    text-align: left;
  }
  /* The chevron's column is narrower here, so the sentence keeps its width. */
  .audit-row > summary,
  div.audit-row {
    grid-template-columns: 28px minmax(0, 1fr) auto 12px;
    column-gap: 10px;
    padding: 9px 16px;
  }
  .audit-card.is-area-filtered .audit-row > summary,
  .audit-card.is-area-filtered div.audit-row {
    grid-template-columns: 28px minmax(0, 1fr) auto 12px;
  }
  .audit-chevron .icon {
    width: 12px;
    height: 12px;
  }
  .audit-area {
    display: none;
  }
  .audit-day-label {
    padding: 14px 16px 8px;
  }
  /* Each label over its value, so values get the width. */
  .audit-detail {
    grid-template-columns: minmax(0, 1fr);
    row-gap: 2px;
    padding: 4px 16px 14px 56px;
  }
  .audit-detail dt:not(:first-child) {
    margin-top: 8px;
  }
}

/* ============ Configuration pages ============ */

/* A page with nothing to show (failed to load, no access): the empty-state
   card, with room above its one action. */
.page-state-action {
  margin-top: 16px;
}

/* Model pool: an account that's off dims, like a paused cron job. */
.row-pool.is-off .pool-account,
.row-pool.is-off .pool-provider {
  opacity: 0.55;
}
/* The provider and status badges are grid cells of their own, except on
   phones (below). */
.pool-badges {
  display: contents;
}
.pool-badges > .badge {
  justify-self: start;
}
.pool-account {
  min-width: 0;
}
.pool-status-error {
  color: var(--danger-text);
}
/* The provider as the sub-line's first words: phones only (below), where
   it stands in for the provider badge. */
.pool-provider-sub,
.pool-provider-sep,
.pool-provider-line {
  display: none;
}
.pool-provider-sub {
  color: var(--text-muted);
}
.pool-signin {
  margin-top: 8px;
}
/* A rename or removal saving: the row says so beside its name. */
.row-pool[aria-busy='true'] .pool-account > .row-name::after {
  content: '';
  display: inline-block;
  width: 8px;
  height: 8px;
  margin-left: 8px;
  border: 2px solid var(--border-strong);
  border-top-color: var(--accent);
  border-radius: 50%;
  vertical-align: -1px;
  animation: vm-spin 0.8s linear infinite;
}
/* No accounts yet: the empty state carries both ways to add one. */
.pool-empty-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
}
@media (max-width: 600px) {
  /* Phones keep the label and drop the account's id. The name gets the
     whole first line; the status badge, switch and actions share the
     second. The provider moves into the sub-line, so the badge cell holds
     one badge and the row stays two lines. */
  .row-pool .ig-key,
  .row-pool .pool-provider {
    display: none;
  }
  .row-pool .pool-provider-sub,
  .row-pool .pool-provider-sep {
    display: inline;
  }
  .row-pool .pool-provider-line {
    display: block;
  }
  .row-pool {
    grid-template-columns: minmax(0, 1fr) auto auto;
    grid-template-areas:
      'account account account'
      'badges switch actions';
  }
  .row-pool > .pool-badges {
    grid-area: badges;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    min-width: 0;
  }
  /* Touch-size row actions. */
  .row-pool .pool-actions .conv-action {
    width: 40px;
    height: 40px;
  }
}

/* A card whose own data didn't load, while the rest of the page did. */
.card-load-error {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 12px;
  padding: 20px 28px 24px;
}
.card-load-error > .alert {
  align-self: stretch;
}

/* Company: Save and Discard float at the bottom of the pane while there are
   unsaved edits. A sticky bar keeps clear of the pane's content box, so the
   pane's bottom padding shrinks to the gap the bar floats on while it shows. */
.save-bar {
  position: sticky;
  bottom: 0;
  z-index: 5;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 8px 8px 8px 20px;
  border: 1px solid var(--border-card);
  border-radius: var(--radius-pill);
  background: var(--surface);
  box-shadow: var(--shadow-float);
}
.save-bar-text {
  min-width: 0;
  color: var(--text-secondary);
  font-size: 13.5px;
  font-weight: 500;
}
/* A failed save says why in the bar, over as many lines as it takes. */
.save-bar:has(.is-error) {
  border-radius: var(--radius-lg);
}
.save-bar-text.is-error {
  color: var(--danger-text);
  font-weight: 400;
  white-space: normal;
}
.save-bar-short {
  display: none;
}
@media (max-width: 600px) {
  .save-bar-long {
    display: none;
  }
  .save-bar-short {
    display: inline;
  }
}
.save-bar-actions {
  display: flex;
  flex-shrink: 0;
  gap: 8px;
}
.content:has(> .save-bar:not([hidden])) {
  padding-bottom: 16px;
}
@media (max-width: 900px) {
  .content:has(> .save-bar:not([hidden])) {
    padding-bottom: 12px;
  }
}

/* Phones: Secrets and Vault row actions are real touch targets. */
@media (max-width: 600px) {
  .vault-row .conv-action {
    width: 36px;
    height: 36px;
  }
}

/* Development: rows lead with a name and its status badge and end with their
   actions; a repository's notices run the full width under both. */
.dev-name {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
}
.row.dev-row {
  grid-template-columns: minmax(0, 1fr) auto;
  row-gap: 10px;
}
.dev-row > .alert {
  grid-column: 1 / -1;
  overflow-wrap: anywhere;
}
.dev-row-actions {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  justify-content: flex-end;
  gap: 12px;
}
.dev-row.is-off .dev-row-main {
  opacity: 0.55;
}
/* The template notice carries its one action at the end of the line. */
.alert.dev-notice {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 10px 16px;
}
.dev-notice > span {
  flex: 1 1 320px;
}
.dev-row .nowrap {
  white-space: nowrap;
}
/* A refresh in flight: its button spins (and waits), the row's pill says
   Refreshing with a spinner of its own. */
.dev-row-actions .conv-action[aria-disabled='true'] {
  pointer-events: none;
}
.conv-action-refresh[aria-busy='true'] .icon {
  animation: vm-spin 0.9s linear infinite;
}
.badge-busy .spinner-dot {
  width: 10px;
  height: 10px;
}
.dev-row.is-removing {
  opacity: 0.55;
  transition: opacity 0.15s ease;
}
/* A refresh's log: its own lines, the first three, and the rest on request. */
.dev-error-text {
  display: -webkit-box;
  overflow: hidden;
  white-space: pre-line;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
}
.dev-error.is-open .dev-error-text {
  display: block;
  -webkit-line-clamp: unset;
}
.dev-error a {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 2px;
}
.dev-error-more {
  margin-top: 10px;
}
@media (max-width: 900px) {
  .row.dev-row {
    grid-template-columns: minmax(0, 1fr);
  }
  .dev-row-actions {
    justify-content: flex-start;
  }
  /* A repository's switch and icons are small: they stay beside its name,
     until a phone needs the whole width for the name. */
  .row.dev-row-repo {
    grid-template-columns: minmax(0, 1fr) auto;
  }
  .dev-row-repo > .dev-row-actions {
    justify-content: flex-end;
  }
}
@media (max-width: 600px) {
  .row.dev-row-repo {
    grid-template-columns: minmax(0, 1fr);
  }
  .dev-row-repo > .dev-row-actions {
    justify-content: flex-start;
  }
  /* Touch-size row actions, as on Model pool. */
  .dev-row-actions .conv-action {
    width: 40px;
    height: 40px;
  }
}

/* The agent's asks in web chat: vault login, takeover, tool review */
.agent-request + .agent-request,
.agent-request + .composer-approval-panel {
  border-top: 1px solid var(--border);
}
.agent-request-detail {
  margin-top: 8px;
  color: var(--text);
  font-size: 13px;
  line-height: 1.45;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.agent-request-note {
  margin-top: 6px;
  color: var(--text-muted);
  font-size: 12px;
  line-height: 1.45;
}
/* An ask card still working on your answer, or why it failed. */
.agent-request-status {
  margin-top: 8px;
  color: var(--text-secondary);
  font-size: 12px;
  line-height: 1.45;
  overflow-wrap: anywhere;
}
.agent-request-status[hidden] {
  display: none;
}
.agent-request-status.is-error {
  color: var(--danger);
}
.agent-request-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 8px;
}
.agent-request-chip {
  max-width: 100%;
  padding: 1px 8px;
  border-radius: var(--radius-pill);
  background: var(--surface-2);
  color: var(--text-secondary);
  font-family: var(--mono);
  font-size: 11.5px;
  overflow-wrap: anywhere;
}
.agent-request-outcome {
  flex: 0 1 auto;
  min-width: 0;
  margin-left: auto;
  font-size: 12px;
  font-weight: 500;
}

@media (max-width: 480px) {
  .composer-approval-kicker {
    display: none;
  }

  .agent-request-outcome {
    flex-basis: 100%;
    margin-left: 0;
    padding-left: 21px;
  }
}

.agent-request-fields {
  align-self: center;
  color: var(--text-secondary);
  font-size: 12px;
}
.agent-request-ok {
  color: var(--ok-text);
}
.agent-request-off {
  color: var(--text-faint);
}
.agent-request-done {
  padding-bottom: 12px;
}
/* Sized so the note and the hand-back button stay in view with the screen
   (the composer caps its asks at 56vh); Full screen is one click away. */
.agent-takeover-screen {
  position: relative;
  width: min(100%, 58vh);
  margin: 10px auto 0;
  aspect-ratio: 16 / 10;
  max-height: 36vh;
  overflow: hidden;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--lm-ink);
}
.agent-takeover-frame {
  width: 100%;
  height: 100%;
  border: 0;
}
/* Other asks folded under the screen: shrink it so their rows stay in view. */
.chat-composer-interactions:has(.is-collapsed) .agent-takeover-screen {
  width: min(100%, 44vh);
  max-height: 27vh;
}

div.agent-takeover-screen.is-error {
  width: 100%;
  box-shadow: none;
  aspect-ratio: auto;
  max-height: none;
  overflow: visible;
  border: 0;
  background: transparent;
}

.agent-takeover-error {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 10px 10px 14px;
  font-size: 12.5px;
}

.agent-takeover-error > .icon {
  flex: none;
  width: 14px;
  height: 14px;
}

.agent-takeover-error-copy {
  flex: 1;
  min-width: 0;
}

.agent-takeover-loading {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  padding: 16px;
  color: var(--lm-grey-lighter);
  font-size: 12.5px;
  text-align: center;
}
.agent-takeover-note {
  width: 100%;
  margin-top: 8px;
}
/* One box: plain read-only values in a definition list, like the setting
   preview's single mono block (no field-like boxes inside it). */
.agent-tool-summary {
  display: grid;
  gap: 3px;
  margin: 8px 0 0;
  padding: 8px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
}
.agent-tool-row {
  display: grid;
  grid-template-columns: 90px minmax(0, 1fr);
  align-items: baseline;
  gap: 10px;
  font-size: 12px;
}
.agent-tool-key {
  margin: 0;
  color: var(--text-faint);
}
.agent-tool-value {
  margin: 0;
  color: var(--text-secondary);
  overflow-wrap: anywhere;
  font-family: var(--mono);
  font-size: 11.5px;
  line-height: 1.5;
}
.vault-add-form {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 14px 12px;
  padding: 16px 20px;
}
.vault-field {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
}
.vault-field-label {
  color: var(--text-secondary);
  font-size: 13px;
  font-weight: 500;
}
.vault-field-optional {
  color: var(--text-faint);
  font-weight: 400;
}
.vault-field > .field-error {
  margin-top: 0;
}
/* One plain-text box for the whole secret: monospace, like a note. */
.vault-add-form .vault-field-wide,
.vault-add-form .vault-secret-hint,
.vault-add-form .vault-add-actions,
.vault-add-form > .form-error {
  grid-column: 1 / -1;
}
.vault-add-form > .form-error {
  margin: 0;
}
@media (max-width: 640px) {
  .vault-add-form {
    grid-template-columns: minmax(0, 1fr);
  }
  /* Who it's for stacks like the other fields; Save goes under it. */
  .vault-add-form .vault-add-actions {
    flex-wrap: wrap;
    justify-content: flex-end;
  }
  .vault-add-form .vault-scope {
    flex: 1 1 100%;
    flex-direction: column;
    align-items: stretch;
    gap: 6px;
  }
  .vault-add-form .vault-scope-note {
    flex: 1;
  }
  .vault-add-form .vault-add-actions select {
    width: 100%;
    min-width: 0;
  }
}
/* Vault and Secrets rows: key, name (and a line under it), actions. Team and
   personal items sit under their own subheads, so rows carry no scope chip. */
.ig-row.vault-row {
  grid-template-columns: 38px minmax(0, 1fr) auto;
}
.vault-row > .ig-actions {
  gap: 4px;
}
.secret-row .ig-name {
  font-family: var(--mono);
  font-size: 12.5px;
}
.secret-preview {
  font-family: var(--mono);
  font-size: 11.5px;
}
.secrets-list {
  padding-bottom: 0;
}
@media (max-width: 600px) {
  .ig-row.vault-row {
    gap: 6px 12px;
    padding: 12px 16px;
  }
  .vault-row .ig-name-line > .ig-name {
    max-width: 100%;
  }
  .vault-row > .ig-mark {
    align-self: start;
  }
  /* The line under the name wraps, up to two lines. */
  .vault-row .ig-desc {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    white-space: normal;
  }
  /* Secrets: the whole name on top (wrapping after an underscore), when it
     changed and the icons on the line under it. */
  .ig-row.secret-row {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas:
      'name name'
      'desc actions';
    row-gap: 2px;
  }
  .secret-row > .ig-mark {
    display: none;
  }
  .secret-row > .ig-title {
    display: contents;
  }
  .secret-row .ig-name-line {
    grid-area: name;
  }
  .secret-row .ig-name {
    white-space: normal;
  }
  .secret-row .ig-desc {
    grid-area: desc;
    display: block;
    white-space: nowrap;
    text-overflow: ellipsis;
  }
  .secret-row > .ig-actions {
    grid-area: actions;
    gap: 4px;
  }
}
.vault-secret-input {
  min-height: 132px;
  padding: 12px 14px;
  font-family: var(--mono);
  font-size: 13px;
  line-height: 1.55;
  resize: vertical;
}
.vault-secret-hint {
  margin: -4px 0 0;
  color: var(--text-muted);
  font-size: 12.5px;
  line-height: 1.5;
}
.vault-secret-hint code {
  font-family: var(--mono);
  font-size: 12px;
}
.vault-add-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}
.vault-scope {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
}
.vault-scope-note {
  color: var(--text-muted);
  font-size: 13px;
}
.vault-add-actions select {
  width: auto;
  min-width: 190px;
}
.agent-change-target {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-top: 8px;
  font-size: 12px;
}
.agent-change-area {
  padding: 1px 8px;
  border-radius: var(--radius-pill);
  background: var(--surface-2);
  color: var(--text-secondary);
}
.agent-change-tech {
  margin-top: 6px;
  color: var(--text-faint);
  font-size: 11.5px;
}

.agent-change-tech summary {
  display: flex;
  align-items: center;
  gap: 7px;
  width: max-content;
  cursor: pointer;
  list-style: none;
}

.agent-change-tech summary::-webkit-details-marker {
  display: none;
}

/* The run's disclosure chevron: › shut, ⌄ open. */
.agent-change-tech summary::before {
  content: '';
  width: 6px;
  height: 6px;
  margin: 0 1px 0 2px;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: rotate(-45deg);
  transition: transform 0.15s ease;
}

.agent-change-tech[open] summary::before {
  margin-bottom: 3px;
  transform: rotate(45deg);
}

.agent-change-tech summary:hover {
  color: var(--text-muted);
}

.agent-change-tech code {
  display: block;
  margin-top: 4px;
  font-family: var(--mono);
  font-size: 11px;
  overflow-wrap: anywhere;
}
.agent-change-preview {
  max-height: 180px;
  margin: 8px 0 0;
  padding: 8px 12px;
  overflow: auto;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  font-family: var(--mono);
  font-size: 11.5px;
  line-height: 1.45;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

/* ============ Skills: yours first, then the team's, as a grid of cards ============ */

.skills-toolbar-left {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
  min-width: 0;
}

.skills-body {
  display: flex;
  flex-direction: column;
  gap: 36px;
}

.skills-section {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.skills-section-head {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.skills-section-title {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin: 0;
  font-family: var(--font-display);
  font-size: 22px;
  font-weight: 500;
  letter-spacing: -0.03em;
}

.skills-section-count {
  color: var(--text-faint);
  font-size: 15px;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0;
}

.skills-section-sub {
  max-width: 760px;
  margin: 0;
  color: var(--text-muted);
  font-size: 13.5px;
}

.skill-grid {
  --tile-min: 280px;
  gap: 14px;
}

.skill-tile {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
  padding: 18px 18px 16px;
  border: 1px solid var(--border-card);
  border-radius: var(--radius-2xl);
  background: var(--surface);
  box-shadow: var(--shadow-card);
  color: var(--text);
  text-align: left;
  cursor: pointer;
  transition:
    transform 0.18s var(--ease-out),
    box-shadow 0.18s ease,
    border-color 0.18s ease,
    background 0.18s ease;
}

.skill-tile:hover,
.skill-tile:focus-visible {
  transform: translateY(-2px);
  border-color: var(--border-strong);
  box-shadow: var(--shadow-float);
  outline: none;
}

.skill-tile:focus-visible {
  box-shadow:
    0 0 0 3px var(--accent-ring),
    var(--shadow-float);
}

.skill-tile-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 8px;
}

.skill-tile-controls {
  display: flex;
  align-items: center;
  gap: 4px;
  cursor: default;
}

.skill-more {
  width: 28px;
  height: 28px;
  border-radius: var(--radius-pill);
  opacity: 0;
  transition: opacity 0.14s ease;
}

.skill-tile:hover .skill-more,
.skill-tile:focus-within .skill-more {
  opacity: 1;
}

.skill-more:hover {
  background: var(--surface-2);
  color: var(--text);
}

@media (hover: none) {
  .skill-more {
    opacity: 1;
  }
}

.skill-mono {
  display: grid;
  place-items: center;
  flex: none;
  width: 40px;
  height: 40px;
  border-radius: 12px;
  color: #ffffff;
  font-family: var(--font-display);
  font-size: 14px;
  font-weight: 600;
  letter-spacing: -0.02em;
  text-shadow: 0 1px 1px rgba(21, 0, 121, 0.2);
  box-shadow:
    inset 0 1.5px 1px rgba(255, 255, 255, 0.35),
    inset 0 -2px 3px rgba(21, 0, 121, 0.18),
    0 4px 10px -3px rgba(26, 24, 43, 0.25);
  transition:
    filter 0.18s ease,
    opacity 0.18s ease;
}

.skill-mono-0 {
  background: linear-gradient(140deg, var(--lm-peach) 0%, var(--lm-orange-500) 100%);
}
.skill-mono-1 {
  background: linear-gradient(140deg, var(--lm-orange-400) 0%, var(--lm-plum) 100%);
}
.skill-mono-2 {
  background: linear-gradient(140deg, var(--lm-plum) 0%, var(--lm-indigo) 100%);
}
.skill-mono-3 {
  background: linear-gradient(140deg, var(--lm-orange-300) 0%, var(--lm-orange-700) 100%);
}
.skill-mono-4 {
  background: linear-gradient(140deg, var(--lm-indigo) 0%, var(--lm-ink) 100%);
}
.skill-mono-5 {
  background: linear-gradient(140deg, var(--lm-orange-200) 0%, var(--lm-plum) 100%);
}

.skill-tile-name {
  font-family: var(--font-display);
  font-size: 16px;
  font-weight: 500;
  letter-spacing: -0.02em;
  overflow-wrap: anywhere;
}

.skill-tile-desc {
  display: -webkit-box;
  margin: 0;
  overflow: hidden;
  color: var(--text-muted);
  font-size: 13.5px;
  line-height: 1.45;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  line-clamp: 3;
}

.skill-tile-desc.is-empty {
  color: var(--text-faint);
}

.skill-tile-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 4px;
}

.skill-chip {
  display: inline-flex;
  align-items: center;
  height: 22px;
  padding: 0 9px;
  border-radius: var(--radius-pill);
  background: var(--eyebrow-bg);
  color: var(--eyebrow-text);
  font-size: 11.5px;
  font-weight: 500;
}

.skill-chip-muted {
  background: var(--surface-2);
  color: var(--text-muted);
}

.skill-tile-foot {
  margin-top: auto;
  padding-top: 10px;
  color: var(--text-faint);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
}

.skill-tile.is-off .skill-mono {
  filter: grayscale(1);
  opacity: 0.4;
}

.skill-tile.is-off .skill-tile-name,
.skill-tile.is-off .skill-tile-desc,
.skill-tile.is-off .skill-tile-chips {
  opacity: 0.55;
}

.skill-teach {
  display: flex;
  align-items: flex-start;
  gap: 20px;
  padding: 28px;
  border: 1.5px dashed var(--border-strong);
  border-radius: var(--radius-2xl);
  background:
    radial-gradient(60% 120% at 0% 0%, rgba(255, 187, 152, 0.2) 0%, rgba(255, 187, 152, 0) 70%),
    var(--surface);
}

.skill-teach-art {
  flex: none;
  margin-bottom: 0;
}

.skill-teach-title {
  margin: 0;
  font-family: var(--font-display);
  font-size: 20px;
  font-weight: 500;
  letter-spacing: -0.03em;
}

.skill-teach-sub {
  max-width: 540px;
  margin: 6px 0 0;
  color: var(--text-muted);
  font-size: 14px;
}

.skill-starters {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 16px;
}

.skill-starter {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 32px;
  padding: 0 14px;
  border: 1px solid var(--border-control);
  border-radius: var(--radius-pill);
  background: var(--surface);
  color: var(--text);
  font-family: inherit;
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  transition:
    border-color 0.14s ease,
    background 0.14s ease;
}

.skill-starter:hover {
  border-color: var(--accent-line);
  background: var(--accent-tint);
}

.skill-starter-blank {
  border-style: dashed;
  color: var(--text-muted);
}

.skill-group {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-top: 14px;
}

.skill-group-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.skill-group-title {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  min-width: 0;
}

.skill-group-title .eyebrow .icon {
  width: 13px;
  height: 13px;
}

.skill-group-count {
  color: var(--text-secondary);
  font-size: 13px;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
}

.skill-group-desc {
  color: var(--text-faint);
  font-size: 13px;
}

.skill-group-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-left: auto;
}

.skill-group-empty {
  margin: 0;
  padding: 18px;
  border: 1.5px dashed var(--border);
  border-radius: var(--radius-xl);
  color: var(--text-faint);
  font-size: 13px;
  text-align: center;
}

.skill-group-more {
  align-self: flex-start;
}

@media (max-width: 600px) {
  .skills-toolbar-left,
  .skills-toolbar-left .ig-filter-wrap {
    width: 100%;
  }
  .skills-toolbar-left .seg {
    flex-wrap: nowrap;
    max-width: 100%;
    overflow-x: auto;
    scrollbar-width: none;
  }
  .skills-toolbar-left .seg-btn {
    flex: none;
    padding: 0 11px;
  }
  .skill-teach {
    flex-direction: column;
    padding: 22px;
  }
}

/* ============ Cron runs (a bot's Activity) and the routine editor's shared parts ============ */

.cron-row-title {
  min-width: 0;
  font-family: var(--font-display);
  font-size: 15.5px;
  font-weight: 500;
  letter-spacing: -0.02em;
}

.cron-when-text {
  display: flex;
  align-items: flex-start;
  gap: 6px;
  font-size: 13.5px;
  font-weight: 500;
}

/* Beside the first line when the words wrap. */
.cron-when-text .icon {
  flex: none;
  width: 14px;
  height: 14px;
  margin-top: 2px;
  color: var(--accent);
}

.cron-run-day,
.cron-form-title {
  color: var(--text-faint);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.cron-run-groups {
  padding-bottom: 10px;
}

.cron-run-day {
  padding: 14px 28px 6px;
}

/* A bot's Activity card: a divider under its header, like its other cards. */
.bot-activity > .cron-run-groups {
  border-top: 1px solid var(--border);
}

/* The routine page's run language: glyph, time, what came of it, how long,
   the chevron. */
.cron-run-row {
  display: grid;
  grid-template-columns: 18px 112px minmax(0, 1fr) 56px 16px;
  align-items: center;
  gap: 12px;
  min-height: 44px;
  padding: 0 28px;
  cursor: pointer;
  transition: background 0.14s ease;
}

.cron-run-row:hover,
.cron-run-row:focus-visible {
  background: var(--surface-muted);
  outline: none;
}

.cron-run-row:focus-visible {
  box-shadow: inset 0 0 0 2px var(--accent-ring);
}

.cron-run-time {
  color: var(--text);
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.cron-run-duration {
  color: var(--text-muted);
  font-size: 12.5px;
  font-variant-numeric: tabular-nums;
  text-align: right;
  white-space: nowrap;
}

.cron-run-summary {
  color: var(--text-muted);
  font-size: 13px;
}

.cron-run-summary.is-bad {
  color: var(--danger-text);
}

/* A bot's runs lead with the routine's name. */
.cron-run-name {
  margin-right: 8px;
  color: var(--text);
  font-weight: 500;
}

.cron-run-detail {
  padding: 12px 28px 20px;
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  background: var(--surface-muted);
}

/* The run row's disclosure chevron: down when closed, up when open. */
.cron-run-chevron {
  justify-self: center;
  color: var(--text-muted);
}

/* Loading, empty and failed transcripts: a quiet line in the panel. */
.cron-run-note {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  margin: 8px 0 0;
  color: var(--text-muted);
  font-size: 13px;
}

.cron-run-note.is-bad {
  color: var(--danger-text);
}

.cron-modal {
  width: min(640px, 100%);
}

.cron-form-section {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 18px 0 20px;
  border-top: 1px solid var(--border);
}

.cron-form-section:last-child {
  padding-bottom: 0;
}

.cron-form-section .field {
  margin: 0;
}

.cron-day {
  height: 30px;
  min-width: 42px;
  padding: 0 10px;
  border: 1px solid var(--border-control);
  border-radius: var(--radius-pill);
  background: var(--surface);
  color: var(--text);
  font-family: inherit;
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  transition:
    border-color 0.14s ease,
    background 0.14s ease,
    color 0.14s ease;
}

.cron-day:hover {
  border-color: var(--border-strong);
}

.cron-day.active {
  border-color: var(--ink-btn);
  background: var(--ink-btn);
  color: #ffffff;
}

.cron-days {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  width: 100%;
}

/* The editor's next runs: a quiet line under the schedule, not a banner. */
.cron-preview {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  color: var(--text-secondary);
  font-size: 13px;
  line-height: 1.45;
}

.cron-preview .icon {
  flex: none;
  width: 14px;
  height: 14px;
  margin-top: 2px;
  color: var(--text-faint);
}

.cron-preview-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.cron-preview-yours {
  color: var(--text-muted);
}

/* A bad schedule pointed out under its field: the line would repeat it. */
.cron-form-section:has(.field-error) .cron-preview.is-bad {
  display: none;
}

.cron-preview.is-bad,
.cron-preview.is-bad .icon {
  color: var(--danger-text);
}

/* The preview couldn't be asked (offline): nothing is known to be wrong. */
.cron-preview.is-unknown {
  color: var(--text-muted);
}

.cron-preview:empty {
  display: none;
}

.cron-where-fixed {
  margin: 0;
  color: var(--text-muted);
  font-size: 13.5px;
}

@media (max-width: 600px) {
  .cron-run-row {
    grid-template-columns: 18px minmax(0, 1fr) 16px;
    row-gap: 4px;
    padding: 10px 16px;
  }
  .cron-run-row > .rt-state,
  .cron-run-time,
  .cron-run-chevron {
    grid-row: 1;
  }
  .cron-run-chevron {
    grid-column: 3;
  }
  /* A transcript gets the width: no stacked gutters on a phone. */
  .cron-run-detail {
    padding: 8px 12px 14px;
  }
  .cron-run-detail .chat-messages {
    padding: 12px 0;
  }
  .cron-transcript .msg-prompt {
    max-width: 100%;
  }
  .cron-run-duration {
    display: none;
  }
  .cron-run-summary {
    grid-column: 2 / -1;
    white-space: normal;
  }
  .cron-run-summary:empty {
    display: none;
  }
}

/* ============ Routines: a bot's list, a routine's page, the editor ============ */

/* A state as an 18px glyph: a shape inside a circle, never colour alone. */
.rt-state {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  box-sizing: border-box;
  width: 18px;
  height: 18px;
  border: 1px solid transparent;
  border-radius: 50%;
}

.rt-state .icon {
  width: 11px;
  height: 11px;
}

.rt-state svg,
.rt-badge .icon svg {
  stroke-width: 2;
}

.rt-state-healthy {
  border-color: var(--ok-line);
  background: var(--ok-soft);
  color: var(--ok-text);
}

.rt-state-flaky {
  border-color: var(--warn-line);
  background: var(--warn-soft);
  color: var(--warn-text);
}

.rt-state-failing {
  border-color: var(--danger-line);
  background: var(--danger-soft);
  color: var(--danger-text);
}

.rt-state-paused,
.rt-state-bot-paused,
.rt-state-done {
  background: var(--surface-2);
  color: var(--text-muted);
}

.rt-state-new {
  border: 1.5px dashed var(--border-strong);
}

/* Running: an ink ring turning (orange would read as a warning). */
.rt-spin {
  position: relative;
  box-sizing: border-box;
  width: 14px;
  height: 14px;
  border: 2px solid var(--border-strong);
  border-top-color: var(--text);
  border-radius: 50%;
  animation: vm-spin 0.9s linear infinite;
}

.badge.rt-badge {
  height: 24px;
  gap: 6px;
  padding: 0 10px 0 8px;
}

.rt-badge .icon {
  width: 12px;
  height: 12px;
}

.rt-badge .rt-spin {
  width: 10px;
  height: 10px;
  border-width: 1.5px;
}

.rt-badge-running {
  color: var(--text);
}

.rt-badge-ring {
  box-sizing: border-box;
  width: 10px;
  height: 10px;
  border: 1.5px dashed var(--border-strong);
  border-radius: 50%;
}

/* The last ten runs, oldest on the left: failures stand taller. */
.rt-ticks {
  display: inline-flex;
  flex: none;
  align-items: flex-end;
  gap: 2px;
  width: 58px;
  height: 16px;
}

.rt-tick {
  width: 4px;
  height: 10px;
  border-radius: 2px;
  background: var(--surface-3);
}

/* Successes stay quiet: a softened green, the failures at full red. */
.rt-tick-success {
  background: color-mix(in srgb, var(--ok) 50%, var(--surface-3));
}

.rt-tick-error {
  height: 16px;
  background: var(--danger);
}

.rt-tick-running {
  height: 16px;
  background: var(--text);
  animation: rt-pulse 1.2s ease-in-out infinite;
}

@keyframes rt-pulse {
  50% {
    opacity: 0.35;
  }
}

.rt-sep {
  color: var(--text-faint);
}

/* One piece on a narrow line: a channel ("#ops-alerts" never splits at its
   hyphen), or a next run and its "(in 2d)". */
.rt-keep,
.rt-channel {
  white-space: nowrap;
}

.rt-bad {
  color: var(--danger-text);
  font-weight: 500;
}

.rt-warn {
  color: var(--warn-text);
}

code.rt-cron {
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font-family: var(--mono);
  font-size: 12px;
}

.rt-channel-unknown {
  color: var(--warn-text);
}

.rt-eyebrow {
  color: var(--text-faint);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.08em;
  line-height: 1;
  text-transform: uppercase;
}

/* --- A bot's Routines card --- */

.card-header-text p.rt-health {
  font-variant-numeric: tabular-nums;
}

.rt-new-short {
  display: none;
}

.rt-filters {
  padding: 12px 28px;
  border-top: 1px solid var(--border);
}

.rt-seg-bad .seg-count {
  color: var(--danger-text);
}

.rt-list {
  container: rt-list / inline-size;
}

.rt-head-row,
.rt-row {
  display: grid;
  grid-template-columns: 18px minmax(0, 1fr) 132px 120px 112px;
  column-gap: 16px;
  padding: 0 28px;
  border-top: 1px solid var(--border);
}

.rt-head-row.is-readonly,
.rt-row.is-readonly {
  grid-template-columns: 18px minmax(0, 1fr) 132px 120px;
}

.rt-head-row {
  align-items: center;
  height: 32px;
  color: var(--text-faint);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.08em;
  line-height: 1;
  text-transform: uppercase;
}

/* A row is a link to its routine (the title's ::after covers it), with its
   Run / Resume / ⋯ buttons above that. */
.rt-row {
  position: relative;
  align-items: start;
  min-height: 60px;
  padding-top: 12px;
  padding-bottom: 12px;
  transition: background 0.14s ease;
}

.rt-row:hover {
  background: var(--hover);
}

.rt-row:has(.rt-row-link:focus-visible) {
  outline: var(--focus-outline);
  outline-offset: -2px;
}

.rt-row > .rt-state {
  margin-top: 1px;
}

.rt-main {
  min-width: 0;
}

.rt-row-link {
  display: block;
  min-width: 0;
  color: var(--text);
  font-size: 14px;
  font-weight: 500;
  letter-spacing: -0.005em;
  line-height: 1.35;
  text-decoration: none;
}

.rt-row-link:hover,
.rt-row-link:focus-visible {
  outline: none;
  box-shadow: none;
  text-decoration: none;
}

.rt-row-link::after {
  content: '';
  position: absolute;
  inset: 0;
}

.rt-meta,
.rt-row-error {
  min-width: 0;
  margin-top: 3px;
  font-size: 12.5px;
  line-height: 1.4;
}

.rt-meta {
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}

.rt-row-error {
  color: var(--danger-text);
}

.rt-row-foot {
  display: contents;
}

.rt-last {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
  padding-top: 1px;
}

.rt-last-text {
  color: var(--text-muted);
  font-size: 12.5px;
  font-variant-numeric: tabular-nums;
  line-height: 1.3;
  white-space: nowrap;
}

.rt-last-text.is-bad {
  color: var(--danger-text);
}

.rt-last-text.is-running {
  color: var(--text);
}

.rt-last-text.is-none {
  color: var(--text-faint);
}

.rt-next {
  display: flex;
  flex-direction: column;
  gap: 2px;
  color: var(--text);
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  line-height: 1.35;
  white-space: nowrap;
}

.rt-next.is-muted {
  color: var(--text-muted);
}

.rt-next-word {
  display: none;
}

.rt-next-rel {
  color: var(--text-faint);
  font-size: 12.5px;
}

/* The buttons centre on the title's line without making it taller, so every
   row's title sits the same distance above its meta. */
.rt-actions {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 6px;
  margin-block: -6px;
}

.rt-row .rt-run-btn[aria-disabled='true'] {
  cursor: default;
}

/* Shown only on a phone's paused row (below), a small pill in place of
   "Paused". Above the row's link. */
.btn.rt-resume-foot {
  position: relative;
  z-index: 1;
  display: none;
  gap: 4px;
  height: 28px;
  margin-block: -6px;
  padding: 0 11px 0 9px;
  color: var(--text);
  font-size: 12.5px;
}

.rt-resume-foot .icon {
  width: 12px;
  height: 12px;
}

.rt-row .conv-action,
.rt-head .rt-more {
  width: var(--control-h-sm);
  height: var(--control-h-sm);
  color: var(--text-secondary);
}

.rt-row .conv-action .icon,
.rt-head .rt-more .icon {
  width: 14px;
  height: 14px;
}

.rt-row .rt-more,
.rt-head .rt-more {
  color: var(--text-muted);
}

.rt-row .conv-action .spinner-dot {
  border-top-color: var(--text);
}

.rt-list-empty {
  padding: 20px 28px;
  border-top: 1px solid var(--border);
  color: var(--text-muted);
  font-size: 14px;
}

.rt-list-empty p {
  margin: 0;
}

/* Below 760px of card (a window beside the full sidebar, a tablet, a
   phone): the title and its buttons on one line, the meta under it, then the
   ticks and the next run. */
@container rt-list (max-width: 759px) {
  .rt-head-row {
    display: none;
  }
  .rt-row,
  .rt-row.is-readonly {
    grid-template-columns: 18px minmax(0, 1fr) auto;
  }
  .rt-main {
    display: contents;
  }
  .rt-row-link {
    grid-column: 2;
    grid-row: 1;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    white-space: normal;
    overflow-wrap: anywhere;
  }
  .rt-meta {
    grid-column: 2 / -1;
    white-space: normal;
  }
  .rt-row-error {
    grid-column: 2 / -1;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    white-space: normal;
    overflow-wrap: anywhere;
  }
  /* Ticks and the last run on the left, the next run on the right: one
     line that never wraps. */
  .rt-row-foot {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    gap: 8px;
    grid-column: 2 / -1;
    margin-top: 8px;
  }
  .rt-last {
    flex-direction: row;
    align-items: center;
    gap: 8px;
    padding-top: 0;
  }
  .rt-last-text {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .rt-next {
    display: block;
    font-size: 12.5px;
    text-align: right;
  }
  .rt-next-word {
    display: inline;
  }
  .rt-next-rel {
    display: none;
  }
  .rt-actions {
    grid-column: 3;
    grid-row: 1;
  }
}

@container rt-list (max-width: 759px) {
  .rt-last-word {
    display: none;
  }
}

/* A phone: only ⋯ on the title's line, so the name keeps its room. Run now
   leads the menu; a paused row's Resume takes the place of "Paused" in its
   foot, still one tap. */
@container rt-list (max-width: 419px) {
  .rt-last-dur {
    display: none;
  }
  .rt-actions .rt-run-btn,
  .rt-actions .rt-run-wrap,
  .rt-actions .rt-resume {
    display: none;
  }
  .rt-next.has-resume .rt-next-paused {
    display: none;
  }
  .rt-next .btn.rt-resume-foot {
    display: inline-flex;
  }
}

/* A phone beside the rail: the next run as "in 23m" (its moment in the
   tooltip), so the last run keeps its words. */
@container rt-list (max-width: 339px) {
  .rt-next-word,
  .rt-next-abs {
    display: none;
  }
  .rt-next .rt-next-rel {
    display: inline;
    color: var(--text);
  }
}

/* No routines yet: what one is, how to start, and four templates. */
.rt-empty {
  container: rt-empty / inline-size;
  padding: 24px 28px 26px;
  border-top: 1px solid var(--border);
}

.rt-empty-line {
  max-width: 640px;
  margin: 0;
  color: var(--text-secondary);
  font-size: 14px;
  line-height: 1.5;
}

.rt-empty-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 14px;
}

.rt-templates-label {
  margin-top: 22px;
}

.rt-templates {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 10px;
  margin-top: 12px;
}

@container rt-empty (min-width: 520px) {
  .rt-templates {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@container rt-empty (min-width: 900px) {
  .rt-templates {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

.rt-template {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 8px;
  min-width: 0;
  padding: 14px 16px;
  border: 1px solid var(--border-control);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--text);
  font-family: inherit;
  text-align: left;
  cursor: pointer;
  transition:
    background 0.14s ease,
    border-color 0.14s ease;
}

.rt-template:hover {
  border-color: var(--border-strong);
  background: var(--hover);
}

.rt-template:focus-visible {
  border-color: var(--border-strong);
  outline: var(--focus-outline);
  outline-offset: 2px;
}

.rt-template .eyebrow .icon {
  width: 12px;
  height: 12px;
}

.rt-template-title {
  max-width: 100%;
  padding-right: 14px;
  font-size: 14px;
  font-weight: 500;
  line-height: 1.3;
}

.rt-template-sub {
  display: -webkit-box;
  overflow: hidden;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  color: var(--text-muted);
  font-size: 12.5px;
  line-height: 1.45;
}

.rt-template-arrow {
  position: absolute;
  top: 14px;
  right: 16px;
  color: var(--text-faint);
  opacity: 0;
  transition: opacity 0.14s ease;
}

.rt-template:hover .rt-template-arrow,
.rt-template:focus-visible .rt-template-arrow {
  opacity: 1;
}

/* --- A routine's page --- */

.rt-head {
  padding: 24px 28px;
}

.rt-crumbs {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  min-height: 30px;
}

.rt-crumb-trail {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  font-size: 13px;
}

.rt-crumb-trail a {
  color: var(--text-secondary);
  text-decoration: none;
}

.rt-crumb-trail a:hover {
  color: var(--text);
  text-decoration: underline;
}

.rt-crumb-sep {
  color: var(--text-faint);
}

/* The bot's name gives way first; "Routines" keeps its word. */
.rt-crumb-trail > * {
  flex: none;
}

.rt-crumb-trail > .rt-crumb-bot {
  flex: 0 1 auto;
  min-width: 0;
}

/* A phone's "View only" (the crumb row's badge, elsewhere). */
.rt-meta-item.rt-meta-view-only {
  display: none;
}

.rt-head-actions {
  display: flex;
  flex: none;
  align-items: center;
  gap: 8px;
}

.rt-title {
  margin: 12px 0 0;
  font-family: var(--font-display);
  font-size: 28px;
  font-weight: 500;
  letter-spacing: -0.035em;
  line-height: 1.15;
  overflow-wrap: anywhere;
}

.rt-status {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 10px;
  margin-top: 10px;
}

.rt-status-text {
  color: var(--text-secondary);
  font-size: 14px;
  font-variant-numeric: tabular-nums;
  line-height: 1.45;
}

.rt-meta-row {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 18px;
  margin-top: 12px;
}

.rt-meta-item {
  display: inline-flex;
  align-items: flex-start;
  gap: 6px;
  min-width: 0;
  color: var(--text-muted);
  font-size: 13px;
  line-height: 1.4;
}

.rt-meta-item > .icon {
  width: 14px;
  height: 14px;
  margin-top: 2px;
  color: var(--text-faint);
}

.rt-head-actions-phone {
  display: none;
}

/* The last failure: what it said, what might fix it, and a way to ask. */
.alert.rt-callout {
  display: grid;
  gap: 10px;
  margin-top: 16px;
  padding: 14px 16px;
  border-radius: var(--radius-lg);
}

.rt-callout-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 8px 12px;
}

/* On a phone the title takes the line and Open run drops under it. */
.rt-callout-title {
  flex: 1 1 220px;
  min-width: 0;
  color: var(--danger-text);
  font-size: 14px;
  font-weight: 500;
}

.rt-callout-head .btn {
  flex: none;
}

/* Open run: top right on a wide card, with the other actions on a phone. */
.rt-open-run-narrow {
  display: none;
}

/* Inside the callout the error needs no second red line: the card's fill
   and edge already say it failed. */
.rt-callout .rt-error-box {
  border: 0;
}

/* A quiet button that starts a line sits on the text's edge, not its
   padding's. */
.rt-callout-actions > .btn-quiet:first-child,
.rt-callout-actions > .rt-open-run-narrow:first-child + .btn-quiet,
.rt-prompt-more {
  margin-left: -15px;
}

.rt-callout-hint {
  margin: 0;
  color: var(--text-secondary);
  font-size: 14px;
  line-height: 1.45;
}

.rt-error-box {
  max-height: 160px;
  margin: 0;
  padding: 10px 12px;
  overflow: auto;
  border: 1px solid var(--danger-line);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--danger-text);
  font-family: var(--mono);
  font-size: 12px;
  line-height: 1.5;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

.rt-callout-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.rt-prompt {
  margin-top: 16px;
  padding: 14px 16px;
  border-radius: var(--radius);
  background: var(--surface-2);
}

.rt-prompt-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  min-height: 22px;
  margin: -4px -8px 6px 0;
}

.rt-prompt-text {
  display: -webkit-box;
  overflow: hidden;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  color: var(--text-secondary);
  font-size: 14px;
  line-height: 1.55;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

.rt-prompt-text.is-open {
  display: block;
  overflow: visible;
}

.rt-prompt-more {
  margin-top: 6px;
  margin-bottom: -6px;
}

.rt-prompt-by {
  margin-left: auto;
  color: var(--text-faint);
  font-size: 12.5px;
  white-space: nowrap;
}

.rt-prompt-by + .btn {
  margin-left: -4px;
}

.rt-runs-summary {
  font-variant-numeric: tabular-nums;
}

.rt-runs-body {
  container: rt-runs / inline-size;
}

.rt-day-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  height: 36px;
  padding: 0 28px;
  border-top: 1px solid var(--border);
}

.rt-day-label {
  color: var(--text-secondary);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.08em;
  line-height: 1;
  white-space: nowrap;
}

.rt-day-counts {
  color: var(--text-muted);
  font-size: 12.5px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* A run: glyph, time, number, what came of it, how long, the chevron. */
.rt-run {
  display: grid;
  grid-template-columns: 18px 72px 108px minmax(0, 1fr) 56px 16px;
  align-items: center;
  column-gap: 12px;
  width: 100%;
  height: 40px;
  padding: 0 28px;
  border: 0;
  background: transparent;
  color: var(--text);
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: background 0.14s ease;
}

/* Runs sparser than two a day: one list, each time with its day
   ("Fri, Sep 25 · 9:00 AM"), in a wider time column. */
.rt-runs-dated .rt-run {
  grid-template-columns: 18px 150px 108px minmax(0, 1fr) 56px 16px;
}

.rt-day-flat {
  border-top: 1px solid var(--border);
}

.rt-run:hover {
  background: var(--hover);
}

.rt-run:focus-visible {
  outline: var(--focus-outline);
  outline-offset: -2px;
}

.rt-run > .rt-state {
  grid-column: 1;
  grid-row: 1;
}

.rt-run-time {
  grid-column: 2;
  grid-row: 1;
  min-width: 0;
  color: var(--text);
  font-size: 13px;
  font-variant-numeric: tabular-nums;
}

.rt-run-at-sep {
  color: var(--text-faint);
}

.rt-run-sub {
  display: contents;
}

.rt-run-num {
  grid-column: 3;
  grid-row: 1;
  color: var(--text-faint);
  font-size: 12.5px;
  font-variant-numeric: tabular-nums;
}

.rt-run-outcome {
  grid-column: 4;
  grid-row: 1;
  min-width: 0;
  color: var(--text-secondary);
  font-size: 13px;
}

.rt-run-outcome.is-bad {
  color: var(--danger-text);
}

.rt-run-outcome.is-faint {
  color: var(--text-faint);
}

.rt-run-outcome.is-running {
  color: var(--text);
}

.rt-run-sub-sep {
  display: none;
}

.rt-run-dur {
  grid-column: 5;
  grid-row: 1;
  color: var(--text-muted);
  font-size: 12.5px;
  font-variant-numeric: tabular-nums;
  text-align: right;
  white-space: nowrap;
}

.rt-run-chevron {
  grid-column: 6;
  grid-row: 1;
  justify-self: center;
  color: var(--text-muted);
}

.rt-streak-runs {
  background: var(--surface-muted);
}

.rt-run-detail {
  padding: 14px 28px 20px 58px;
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  background: var(--surface-muted);
}

.rt-run-facts {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  color: var(--text-muted);
  font-size: 12.5px;
  font-variant-numeric: tabular-nums;
}

.rt-run-facts .conv-action {
  width: var(--control-h-sm);
  height: var(--control-h-sm);
  margin: -6px -8px -6px 0;
  color: var(--text-muted);
}

.rt-run-detail > .rt-error-box {
  margin-top: 10px;
}

.rt-run-detail .chat-messages {
  width: 100%;
  padding: 12px 0 0;
}

.rt-run-prompt {
  margin: 0 0 10px;
}

/* The app's own chevron (› shut, ⌄ open), not the browser's triangle. */
.rt-run-prompt summary {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  width: fit-content;
  color: var(--text-secondary);
  font-size: 13px;
  list-style: none;
  cursor: pointer;
}

.rt-run-prompt summary::-webkit-details-marker {
  display: none;
}

.rt-run-prompt summary:hover {
  color: var(--text);
}

.rt-run-prompt summary .cc-changes-chevron {
  margin: 0 2px;
  transform: rotate(-45deg);
}

.rt-run-prompt[open] summary .cc-changes-chevron {
  margin-bottom: 3px;
  transform: rotate(45deg);
}

.rt-run-prompt-text {
  margin-top: 8px;
  padding: 12px 14px;
  border-radius: var(--radius);
  background: var(--surface-2);
  color: var(--text-secondary);
  font-size: 14px;
  line-height: 1.55;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

.btn.rt-more-btn {
  justify-content: center;
  width: 100%;
  height: 44px;
  border-top: 1px solid var(--border);
  border-radius: 0;
}

.rt-history-end {
  margin: 0;
  padding: 14px;
  border-top: 1px solid var(--border);
  color: var(--text-faint);
  font-size: 12.5px;
  text-align: center;
}

.rt-runs-empty {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 14px;
}

/* A narrow runs card (a phone): the number and duration under the outcome,
   so every time sits at the same x. */
@container rt-runs (max-width: 559px) {
  .rt-run,
  .rt-runs-dated .rt-run {
    grid-template-columns: 18px 60px minmax(0, 1fr) 16px;
    align-items: start;
    row-gap: 2px;
    height: auto;
    min-height: 48px;
    padding: 8px 18px;
  }
  .rt-run-time,
  .rt-run-outcome {
    line-height: 18px;
  }
  .rt-run-outcome {
    grid-column: 3;
  }
  .rt-run-chevron {
    grid-column: 4;
    margin-top: 5px;
  }
  /* "Runs 1–10 · since 4:53 AM · ~44s": the numbers always show; the tail
     is what gives way on a very narrow card. */
  .rt-run-sub {
    display: flex;
    grid-column: 3;
    grid-row: 2;
    min-width: 0;
    overflow: hidden;
    color: var(--text-muted);
    font-size: 12.5px;
    white-space: nowrap;
  }
  .rt-run-sub > span {
    flex: none;
  }
  .rt-run-num {
    color: var(--text-muted);
  }
  .rt-run-sub-sep {
    display: inline;
    white-space: pre;
  }
  /* A folded row says what it came to, and a failed run its error, on up
     to two lines; a fold's since when gives way to it. */
  .rt-run-since {
    display: none;
  }
  .rt-run-fold .rt-run-outcome,
  .rt-run-outcome.is-bad {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    white-space: normal;
    overflow-wrap: anywhere;
  }
  .rt-run-dur {
    text-align: left;
  }
  .rt-day-head {
    padding: 0 18px;
  }
  .rt-run-detail {
    padding: 12px 18px;
  }
  /* A dated list: the day over its time ("Sep 25" / "9:00 AM"). */
  .rt-runs-dated .rt-run {
    grid-template-columns: 18px 66px minmax(0, 1fr) 16px;
  }
  .rt-runs-dated .rt-run-time {
    display: flex;
    flex-direction: column;
    grid-row: 1 / span 2;
    line-height: 18px;
  }
  .rt-runs-dated .rt-run-wd,
  .rt-runs-dated .rt-run-at-sep {
    display: none;
  }
  .rt-runs-dated .rt-run-at {
    color: var(--text-muted);
    font-size: 12.5px;
  }
}

@container rt-runs (max-width: 399px) {
  .rt-day-avg {
    display: none;
  }
}

/* --- The routine editor: What across the top, When beside Where --- */

.rt-editor-row {
  display: flex;
  gap: 12px;
}

.rt-editor-name {
  flex: 1;
  min-width: 0;
}

.rt-editor-model {
  flex: 0 0 220px;
  min-width: 0;
}

.rt-editor-model select {
  width: 100%;
}

.rt-editor .rt-prompt-input {
  resize: vertical;
}

.rt-editor-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 0 24px;
  padding-top: 16px;
  border-top: 1px solid var(--border);
}

.rt-editor-grid > .cron-form-section {
  align-content: start;
  padding: 0;
  border-top: 0;
}

.rt-when-controls {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.rt-when-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
}

.rt-when-row select,
.rt-when-row input {
  width: auto;
}

/* Wide enough for "09:00 AM" beside the clock button. */
.rt-when-row input[type='time'] {
  flex: none;
  width: 136px;
}

.rt-when-word {
  flex: none;
  color: var(--text-muted);
  font-size: 13px;
}

/* The zone takes the rest of its line ("PDT (you)"). */
.rt-when-row select.rt-zone {
  flex: 1 1 96px;
  min-width: 96px;
  max-width: 180px;
}

.rt-when-options {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.rt-when-range {
  margin-top: -2px;
  padding-left: 24px;
}

.rt-editor .modal-body > .cron-form-section {
  padding: 14px 0 16px;
}

/* When and Where: the same space under each title, so their first fields
   line up. */
.rt-editor .rt-editor-grid > .cron-form-section {
  gap: 10px;
}

.rt-check {
  display: inline-flex;
  width: fit-content;
  align-items: center;
  gap: 8px;
  color: var(--text-secondary);
  font-size: 13px;
  cursor: pointer;
}

.rt-check input {
  width: auto;
  height: auto;
  margin: 0;
}

.rt-cron-row {
  display: flex;
  align-items: center;
  gap: 8px;
}

.rt-cron-row input {
  flex: 1;
  min-width: 0;
}

.rt-cron-row select.rt-zone {
  flex: none;
  width: 118px;
}

.rt-when-controls .rt-cron-hint {
  margin-top: -4px;
}

.rt-editor .cron-days {
  flex-wrap: nowrap;
}

.rt-editor .cron-day {
  flex: 1;
  min-width: 0;
  padding: 0;
}

/* How many runs a short interval makes, beside it, in warning ink. */
.rt-freq-note {
  color: var(--warn-text);
  font-size: 12.5px;
  white-space: nowrap;
  cursor: help;
}

.rt-freq-note[hidden] {
  display: none;
}

/* A preview breaks between runs, never inside one. */
.cron-preview-item {
  white-space: nowrap;
}

.rt-month-hint {
  margin-top: -4px;
}

.rt-run-after {
  display: inline-flex;
  order: -1;
  align-items: center;
  gap: 8px;
  margin-right: auto;
  color: var(--text-secondary);
  font-size: 13.5px;
  cursor: pointer;
}

.rt-run-after input {
  width: auto;
  height: auto;
  margin: 0;
}

.rt-run-after.is-disabled {
  cursor: default;
  opacity: var(--disabled-opacity);
}

@media (max-width: 700px) {
  .rt-editor-grid {
    grid-template-columns: minmax(0, 1fr);
  }
  .rt-editor-grid > .cron-form-section + .cron-form-section {
    margin-top: 18px;
    padding-top: 16px;
    border-top: 1px solid var(--border);
  }
}

/* --- Elsewhere: a failing dot on the roster, the Company page's Alerts --- */

.bot-roster-alert {
  flex: none;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--danger);
}

.page-state-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
  margin-top: 16px;
}

.page-state-actions .page-state-action {
  margin-top: 0;
}

.company-alerts-body {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
  padding: 18px 28px;
}

.company-alerts-body .field-label {
  margin: 0;
}

.company-alerts-body select {
  width: 280px;
  max-width: 100%;
}

.usage-routine-link {
  color: inherit;
  text-decoration: none;
}

.usage-routine-link:hover {
  text-decoration: underline;
}

@media (pointer: coarse) {
  .rt-row .conv-action,
  .rt-head .rt-more {
    width: 40px;
    height: 40px;
  }
  .btn.rt-resume-foot::after {
    content: '';
    position: absolute;
    inset: -6px -4px;
  }
  .rt-actions {
    margin-block: -11px;
  }
}

@media (max-width: 600px) {
  .bot-routines > .card-header,
  .rt-runs > .card-header,
  .rt-filters,
  .rt-head-row,
  .rt-row,
  .rt-list-empty,
  .rt-empty {
    padding-right: 18px;
    padding-left: 18px;
  }
  .rt-filters .seg {
    flex-wrap: nowrap;
    max-width: 100%;
    overflow-x: auto;
    scrollbar-width: none;
  }
  .rt-filters .seg-btn {
    flex: none;
  }
  .rt-new-long {
    display: none;
  }
  .rt-new-short {
    display: inline;
  }
  .rt-head {
    padding: 20px 18px;
  }
  .rt-title {
    font-size: 22px;
  }
  .rt-head-actions .rt-edit,
  .rt-head-actions .rt-run-btn,
  .rt-head-actions .rt-run-wrap,
  .rt-head-actions .rt-view-only {
    display: none;
  }
  /* Only ⋯ beside the crumbs: its glyph lines up with the card's edge, and
     the bot's name gets the room. */
  .rt-crumbs {
    gap: 8px;
  }
  .rt-crumb-trail {
    gap: 6px;
  }
  .rt-crumbs .rt-head-actions {
    margin-right: -8px;
  }
  .rt-meta-item.rt-meta-view-only {
    display: inline-flex;
  }
  /* Equal halves, whatever each button's padding (a disabled Run now sits
     in a wrapper that has none). */
  .rt-head-actions-phone:not([hidden]) {
    display: grid;
    grid-auto-columns: minmax(0, 1fr);
    grid-auto-flow: column;
    gap: 8px;
    margin-top: 14px;
  }
  .rt-head-actions-phone > * {
    display: flex;
    min-width: 0;
  }
  .rt-head-actions-phone .btn {
    flex: 1;
    justify-content: center;
    height: var(--control-h);
  }
  .rt-meta-row {
    gap: 4px 14px;
  }
  .rt-open-run-wide {
    display: none;
  }
  .rt-open-run-narrow {
    display: inline-flex;
  }
  /* The ask first, on its own line; Open run and Copy error under it. */
  .rt-callout-actions > .rt-callout-ask {
    order: -1;
    flex: 1 0 100%;
    justify-content: center;
  }
  .rt-callout-actions > .rt-open-run-narrow:first-child + .btn-quiet {
    margin-left: 0;
  }
  .rt-editor-row {
    flex-direction: column;
    gap: 0;
  }
  .rt-editor-row .field + .field {
    margin-top: 12px;
  }
  .rt-editor-model {
    flex-basis: auto;
  }
  .rt-editor .modal-actions {
    flex-wrap: wrap;
  }
  .rt-run-after {
    flex: 1 0 100%;
  }
  .rt-editor .modal-actions > .btn {
    flex: 1;
  }
}

@media (prefers-reduced-motion: reduce) {
  .rt-spin {
    animation: none;
  }
  .rt-spin::after {
    content: '';
    position: absolute;
    inset: 0;
    width: 4px;
    height: 4px;
    margin: auto;
    border-radius: 50%;
    background: var(--text);
  }
  .rt-tick-running {
    animation: none;
  }
}

/* Roles: chips on members, the lock on restricted integrations, the picker. */
.role-chip,
.role-lock {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 10.5px;
  font-weight: 500;
  line-height: 17px;
  padding: 0 8px;
  border-radius: var(--radius-pill);
  border: 1px solid var(--border);
  background: var(--surface-2);
  color: var(--text-muted);
  white-space: nowrap;
  flex-shrink: 0;
}

/* A role chip never runs past its cell: its name truncates (the tooltip has
   all of it). */
.role-chip {
  flex-shrink: 1;
  min-width: 0;
  max-width: 100%;
}
.role-chip-name {
  min-width: 0;
}

.role-lock {
  color: var(--accent-text);
  border-color: var(--accent-line);
  background: var(--accent-soft);
  max-width: 200px;
  overflow: hidden;
  text-overflow: ellipsis;
}

.role-chip .brand-icon,
.role-lock svg {
  flex: none;
  width: 11px;
  height: 11px;
}

/* Role picker (openRolePicker): a list of role options, then who must hold one. */
.role-picker-hint {
  margin-top: 6px;
}

/* Development → Add a repository: a compact, scrolling repository picker. */
.repo-picker {
  width: min(560px, 100%);
}

.repo-picker .input {
  width: 100%;
  margin-bottom: 8px;
}

.repo-picker-list {
  max-height: min(420px, 50vh);
  overflow-y: auto;
  margin: 8px -8px 0;
}
/* While GitHub answers: as tall as a full list, so the dialog doesn't jump
   when the repositories land. */
.repo-picker-list.is-loading {
  min-height: min(420px, 50vh);
}
.repo-picker-list > .usage-loading {
  padding: 14px 8px;
}

.repo-picker-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 8px;
  border-radius: var(--radius-md);
}

.repo-picker-row:hover {
  background: var(--hover);
}

.repo-picker-text {
  min-width: 0;
}

.repo-picker-text .row-name {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
}

.repo-picker-name {
  min-width: 0;
}

/* Browser notifications dialog: the switch beside its label, the status
   as a hint under them. */
.notif-toggle {
  margin-bottom: 14px;
}
.notif-toggle:last-child {
  margin-bottom: 0;
}
/* In a Safari tab the Home Screen note comes first. */
.alert + .notif-toggle {
  margin-top: 14px;
}
.repo-picker-text .badge {
  flex-shrink: 0;
}

/* Already connected: a quiet note where Add would be. */
.repo-added {
  display: inline-flex;
  flex-shrink: 0;
  align-items: center;
  gap: 4px;
  padding-right: 6px;
  color: var(--text-muted);
  font-size: 12.5px;
  font-weight: 500;
}

.repo-added .icon {
  width: 14px;
  height: 14px;
  color: var(--ok-text);
}

.repo-picker-error {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.repo-picker-hint {
  margin: 12px 0 0;
}

.notif-toggle-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.notif-toggle-label {
  color: var(--text);
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
}
/* What went wrong turning it on or checking it, in place of the status. */
.notif-toggle .field-hint.is-error {
  color: var(--danger-text);
}

/* Company: deployment JSON stays behind a keyboard-accessible disclosure. */
.company-advanced > summary {
  cursor: pointer;
  font-weight: 500;
  list-style: none;
}
.company-advanced > summary::-webkit-details-marker {
  display: none;
}
.company-advanced > summary::after {
  content: '+';
  margin-left: auto;
}
.company-advanced[open] > summary::after {
  content: '−';
}
.company-advanced > summary:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}
