/*
  Otto for Office — task pane styles.

  Skinned against the LIVE EmployeeWorks CONVERSATION view, sampled off the
  shipped product: docs/EW_CONVERSATION_UI.md (+ ew-convo-02-top.png,
  ew-convo-06-thinking.png, ew-convo-07-reasoning-expanded.png,
  ew-convo-raw-styles.txt). EMPLOYEEWORKS_UI.md still governs the home/empty
  state. Where anything disagrees, the conversation capture wins.

  THE STRUCTURAL FACT: there are NO CHAT BUBBLES. Both speakers render the same
  left-aligned transparent row — mark in a left gutter, name + timestamp as
  peers on one line, prose on the bare canvas. EW is a transcript, not a
  messenger; a pale slab on a pale canvas is what read as ugly.

  TWO FONTS, deliberately: chrome (name labels, status row, buttons, table
  `th`) is "ServiceNow Sans"; message content and reasoning text are Inter.

  ADAPTED FOR A 350px PANE (verified at 320px). What changed from the web spec
  and why — the pane is 1/2.3 the width of EW's 800px column:
    · avatar gutter 22px + 8px gap, not 32px + 16px (saves 26px of column)
    · body prose Inter 14px/21px, not 16px/24px (16px leaves ~34 characters
      per line at 320px, which reads as shouting)
    · name 14px/20px not 16px/24px; timestamp 11.5px/16px not 14px/20px, and
      today's messages show the clock only (see formatTimestamp)
    · reasoning label 13.5px/19px not 14px/20px; steps 11.5px/16px not 12/16;
      expanded block indented 24px not 28px
    · block spacing 14px not 16px; table cells 6px 10px not 8px 16px
    · composer frame radius 30/24px not 41/32px (at 96px tall, a 41px radius
      turns the frame into a lozenge), send button 34px not 40px
  Everything else — structure, colour, weight, hairline width, the two-font
  split, zebra striping, radii of cards — is as captured.
*/

:root {
  /* surface ladder, live values */
  --bg-canvas: #edece9;      /* body / transcript canvas */
  --bg-primary: #ffffff;     /* cards, composer inner, tables */
  --bg-secondary: #f4f3f0;   /* composer frame, zebra rows, chips */
  --bg-hover: #e3e2df;
  --bg-active: #c2c1be;

  --text-primary: #000000;
  --text-secondary: #4d4c4a;
  --text-tertiary: #656462;
  --text-inverted: #ffffff;

  /* All hairlines are 0.5556px (a 1/1.8 device-ratio hairline). Never 1px. */
  --hairline: 0.5556px solid #e3e2df;
  --hairline-frame: 0.5556px solid #edece9;
  --hairline-strong: 0.5556px solid #c2c1be;
  --connector: #c2c1be;
  --neutral-400: #c2c1be;

  --primary-main: #0e4e69;   /* ICONS: reasoning checks, table options */
  --primary-hover: #0b3e54;
  --link: #1b59bb;           /* the real link blue — not #0e4e69 */
  --green-500: #009b60;
  --send-green: #68e353;     /* send button + the assistant spark mark */
  --user-disc: rgba(104, 227, 83, 0.24);
  --red-600: #e2161c;

  --font-chrome: "ServiceNow Sans", Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --font-body: Inter, "ServiceNow Sans", -apple-system, BlinkMacSystemFont, sans-serif;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;

  /* radii — EW tokens resolved at a 16px root */
  --r-sm: 8px;
  --r-md: 16px;
  --r-lg: 20.8px;   /* 2xl — cards and tables */
  --r-full: 999px;

  --shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.1);
  --shadow-inner-glow: 0 0 8px 0 rgba(0, 0, 0, 0.05);
  --shadow-pop: 0 12px 34px rgba(23, 22, 20, 0.18);

  /* the 22px mark + 8px gap gutter, referenced by the message grid */
  --gutter: 22px;
  --gutter-gap: 8px;
}

* { box-sizing: border-box; }

/* Several rules below set display:flex/grid, which would otherwise defeat the
   UA's [hidden] rule. This has to win. */
[hidden] { display: none !important; }

html, body {
  margin: 0;
  height: 100%;
  font-family: var(--font-chrome);
  font-size: 14px;
  line-height: 20px;
  color: var(--text-primary);
  background: var(--bg-canvas);
  -webkit-font-smoothing: antialiased;
}

.app {
  display: flex;
  flex-direction: column;
  height: 100%;
  min-width: 300px;
  position: relative;
  background: var(--bg-canvas);
}

/* ------------------------------------------- assistant / status line
   Office draws its own pane title above this, so this row names the
   ASSISTANT only (EW's own chat header is the assistant name too). */

.status-line {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 10px 8px 8px 12px;
  flex: 0 0 auto;
  background: var(--bg-canvas);
}

.status-id { display: flex; align-items: center; gap: 8px; min-width: 0; }

.status-name {
  font-size: 14px;
  font-weight: 500;
  color: var(--text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.status-name:empty { display: none; }

.assistant-btn {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  min-width: 0;
  font: inherit;
  padding: 3px 8px 3px 4px;
  margin-left: -4px;
  border: 0;
  border-radius: var(--r-full);
  background: transparent;
  color: inherit;
  cursor: pointer;
  transition: background 120ms ease;
}
.assistant-btn:hover { background: var(--bg-hover); }
.assistant-btn:disabled { background: transparent; cursor: default; padding-right: 4px; }
.assistant-caret { display: inline-flex; color: var(--text-tertiary); flex: 0 0 auto; }

.beta-chip {
  font-size: 9px;
  font-weight: 600;
  letter-spacing: 0.07em;
  color: var(--text-tertiary);
  background: var(--bg-secondary);
  border-radius: var(--r-full);
  padding: 2px 7px;
  line-height: 13px;
  flex: 0 0 auto;
}

.status-tools { display: flex; align-items: center; gap: 1px; flex: 0 0 auto; }

.otto-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--bg-primary);
  box-shadow: 0 1px 3px rgba(23, 22, 20, 0.08);
  flex: 0 0 auto;
}

.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--text-tertiary);
  cursor: pointer;
  transition: background 120ms ease, color 120ms ease;
}
.icon-btn:hover { background: var(--bg-hover); color: var(--text-primary); }
.icon-btn:active { background: var(--bg-active); }

.btn-link {
  font: inherit;
  font-size: 12px;
  font-weight: 500;
  color: var(--link);
  background: none;
  border: 0;
  padding: 0 2px;
  cursor: pointer;
  text-decoration: underline;
  text-decoration-color: rgba(27, 89, 187, 0.35);
}

/* ---------------------------------------------------------- popovers */

.popover {
  position: absolute;
  z-index: 20;
  min-width: 190px;
  max-width: calc(100% - 20px);
  padding: 8px;
  background: var(--bg-primary);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-pop);
}
.popover-settings { top: 46px; right: 10px; width: 232px; padding: 12px 14px; }
.popover-plus { bottom: 76px; left: 14px; }
.popover-assistant { top: 42px; left: 10px; width: 216px; }

.menu-item {
  display: block;
  width: 100%;
  text-align: left;
  font: inherit;
  font-size: 13px;
  color: var(--text-primary);
  background: none;
  border: 0;
  border-radius: var(--r-sm);
  padding: 8px 10px;
  cursor: pointer;
}
.menu-item:hover { background: var(--bg-secondary); }

/* picker rows: check gutter, label, optional quiet flag. An unknown bot name
   is shown raw and can be long, so rows wrap rather than overrun. */
.menu-item-check {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  max-width: 100%;
  overflow: hidden;
}
.menu-check {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 14px;
  height: 18px;
  flex: 0 0 auto;
  color: var(--green-500);
}
.menu-text {
  flex: 1 1 auto;
  min-width: 0;
  line-height: 18px;
  overflow-wrap: anywhere;
}
.menu-hint {
  flex: 0 0 auto;
  align-self: center;
  font-size: 10px;
  line-height: 14px;
  color: var(--text-tertiary);
}
.menu-note {
  margin: 6px 10px 2px;
  font-size: 10.5px;
  line-height: 15px;
  color: var(--text-tertiary);
}

.kv { margin: 0 0 10px; font-size: 12px; }
.kv dt {
  color: var(--text-tertiary);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.kv dd {
  margin: 0 0 8px;
  color: var(--text-primary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.popover-note { margin: 0 0 10px; font-size: 11px; line-height: 16px; color: var(--text-tertiary); }

/* ------------------------------------------------------ okta account
   Lives in the settings popover, under the identity rows. The whole block is
   `hidden` by taskpane.js unless /auth/session reports `enabled`, so on a
   server without Okta configured none of this occupies any space. */

.auth-block {
  margin: 0 0 10px;
  padding-top: 8px;
  border-top: var(--hairline);
}
/* The last dd in the block carries the dl's own bottom margin; drop it so the
   Sign in / Sign out row sits tight under the address. */
.kv-auth { margin: 0; }
.kv-auth dd { margin-bottom: 0; }
/* An email is the one value in this popover that is legitimately longer than
   232px, and truncating it hides the diagnostic half. Let it wrap. */
.kv-auth dd { white-space: normal; overflow-wrap: anywhere; }

.auth-actions { display: flex; align-items: baseline; gap: 10px; margin-top: 6px; }
.auth-busy { font-size: 11px; color: var(--text-tertiary); }
.auth-note {
  margin: 6px 0 0;
  font-size: 10.5px;
  line-height: 15px;
  color: var(--text-tertiary);
  overflow-wrap: anywhere;
}

/* ------------------------------------------------------------ banner */

.banner {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin: 0 12px 6px;
  padding: 10px 14px;
  font-size: 12px;
  line-height: 17px;
  color: var(--text-secondary);
  background: var(--bg-secondary);
  border-radius: var(--r-md);
  flex: 0 0 auto;
  overflow-wrap: anywhere;
}
.banner[data-tone="error"] {
  background: var(--bg-primary);
  border: var(--hairline);
  box-shadow: inset 3px 0 0 var(--red-600);
}

/* -------------------------------------------------------- transcript */

.transcript {
  flex: 1 1 auto;
  overflow-y: auto;
  padding: 4px 14px 14px;
  display: flex;
  flex-direction: column;
  gap: 2px;                    /* rows carry their own padding, as in EW */
}

/* ---------------------------------------------------- empty / home state */

.empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: 14px 4px 8px;
}
/* Centred when it fits; `safe` keeps an overflowing greeting + starter list
   scrollable from the top instead of clipping its head. */
.transcript:has(> .empty) { justify-content: safe center; }

.empty-greeting {
  margin: 0 0 12px;
  font-size: 29px;
  line-height: 36px;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--text-primary);
  overflow-wrap: anywhere;
}
.empty-body {
  margin: 0;
  max-width: 280px;
  font-family: var(--font-body);
  font-size: 13px;
  line-height: 19px;
  color: var(--text-secondary);
}

/* Conversation starters: a vertical stack of quiet full-width rows. A chip
   cloud would ragged-wrap into nonsense at 320px. */
.starters {
  display: flex;
  flex-direction: column;
  gap: 8px;
  align-self: stretch;
  width: 100%;
  margin-top: 20px;
}
.starter {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  text-align: left;
  font-family: var(--font-body);
  font-size: 13px;
  line-height: 18px;
  color: var(--text-secondary);
  background: var(--bg-secondary);
  border: 0;
  border-radius: var(--r-md);
  padding: 11px 12px 11px 13px;
  cursor: pointer;
  transition: background 120ms ease, color 120ms ease;
}
.starter:hover { background: var(--bg-hover); color: var(--text-primary); }
.starter:active { background: var(--bg-active); }
.starter-icon { display: inline-flex; color: var(--primary-main); flex: 0 0 auto; }
.starter-text { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }
.starter-arrow { display: inline-flex; color: var(--neutral-400); flex: 0 0 auto; }

/* ===================================================== transcript rows
   ONE component for both speakers: `mark | column`. Transparent, no bubble,
   no right-alignment, no surface. */

.msg {
  display: grid;
  grid-template-columns: var(--gutter) minmax(0, 1fr);
  column-gap: var(--gutter-gap);
  align-items: start;
  padding: 8px 0;
  background: transparent;
  border: 0;
}

.msg-mark {
  grid-column: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--gutter);
  height: var(--gutter);
  margin-top: 1px;            /* optically centres against the 20px name row */
  border-radius: 50%;
  flex: 0 0 auto;
}
/* user: a pale-green disc carrying the initial */
.msg[data-who="user"] .msg-mark { background: var(--user-disc); }
.msg-initial {
  font-family: var(--font-chrome);
  font-size: 11.5px;
  font-weight: 500;
  line-height: 1;
  color: var(--text-primary);
}
/* assistant: the bright-green spark glyph, NO disc behind it */
.msg[data-who="assistant"] .msg-mark { background: transparent; }
.msg-spark { display: inline-flex; color: var(--send-green); }

.msg-col { grid-column: 2; min-width: 0; }

/* name and timestamp are PEERS on one row, gap 8px */
.msg-head {
  display: flex;
  align-items: baseline;
  gap: 8px;
  min-width: 0;
  margin: 0 0 2px;
  min-height: 20px;
}
.msg-name {
  font-family: var(--font-chrome);
  font-size: 14px;
  line-height: 20px;
  font-weight: 500;
  color: var(--text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  flex: 0 1 auto;
}
.msg-time {
  font-family: var(--font-chrome);
  font-size: 11.5px;
  line-height: 16px;
  font-weight: 400;
  color: var(--text-tertiary);
  white-space: nowrap;
  flex: 0 0 auto;
}

.msg-body {
  font-family: var(--font-body);
  font-size: 14px;
  line-height: 21px;
  color: var(--text-primary);
  min-width: 0;
}

/* the user's own words: plain prose, preserving their line breaks */
.msg-text {
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

/* assistant body: narration blocks and edit cards, stacked */
.stream { display: flex; flex-direction: column; gap: 12px; }

/* ------------------------------------------------- prose / markdown body */

.narration {
  font-family: var(--font-body);
  font-size: 14px;
  line-height: 21px;
  color: var(--text-primary);
}
.narration > *:first-child { margin-top: 0; }
.narration > *:last-child { margin-bottom: 0; }
/* EW spaces blocks by a flat margin-bottom; there are no <h*> tags in a reply,
   "headings" are just bold text on their own line. */
.narration p { margin: 0 0 14px; overflow-wrap: anywhere; }
.narration ul, .narration ol { margin: 0 0 14px; padding-left: 16px; }
.narration ul { list-style-type: disc; }
.narration li { margin: 0; }          /* no gap between items, per the capture */
.narration strong { font-weight: 600; color: var(--text-primary); }
.narration a {
  color: var(--link);
  font-weight: 500;
  text-decoration: none;
}
.narration a:hover { text-decoration: underline; }
.narration code {
  font-family: var(--mono);
  font-size: 12px;
  background: var(--bg-secondary);
  border-radius: 5px;
  padding: 1px 5px;
  word-break: break-all;
}
.narration pre {
  margin: 0 0 14px;
  padding: 10px 12px;
  background: var(--bg-primary);
  border: var(--hairline);
  border-radius: var(--r-lg);
  overflow-x: auto;
}
.narration pre code { background: none; padding: 0; word-break: normal; }

/* Tables: a white card at 2xl radius with a hairline and NO shadow. Product
   Pulse returns these constantly, so this is load-bearing. */
.narration table {
  border-collapse: separate;
  border-spacing: 0;
  width: 100%;
  margin: 0 0 14px;
  background: var(--bg-primary);
  border: var(--hairline);
  border-radius: var(--r-lg);
  overflow: hidden;
  table-layout: fixed;
}
.narration th {
  font-family: var(--font-chrome);   /* chrome font, weight 700 */
  font-size: 12px;
  line-height: 18px;
  font-weight: 700;
  color: var(--text-tertiary);
  text-align: left;
  background: var(--bg-primary);
  padding: 7px 10px;
  border-bottom: var(--hairline);
  overflow-wrap: anywhere;
}
.narration td {
  font-family: var(--font-body);
  font-size: 12.5px;
  line-height: 18px;
  font-weight: 300;                  /* LIGHT — yes, 300 */
  color: var(--text-primary);
  padding: 6px 10px;
  border-bottom: var(--hairline);
  vertical-align: top;
  overflow-wrap: anywhere;
}
.narration tbody tr:nth-child(odd) td { background: var(--bg-secondary); }
.narration tbody tr:last-child td { border-bottom: 0; }

/* =============================================== reasoning / thinking
   ONE quiet inline line between the name header and the body. No card, no
   surface, no dot, no live timer. */

.reasoning {
  display: inline-flex;
  flex-direction: column;
  align-items: stretch;
  padding-left: 6px;
  margin: 0 0 10px;
  background: transparent;
  border: 0;
  max-width: 100%;
}

.reasoning-head {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 20px;
  padding: 0;
  font: inherit;
  background: transparent;
  border: 0;
  color: var(--text-primary);
  cursor: pointer;
  text-align: left;
}
/* Expandable at any time, in flight or done. */
.reasoning-head:hover .reasoning-label { text-decoration: underline; text-decoration-color: var(--neutral-400); }

.reasoning-spark {
  display: inline-flex;
  flex: 0 0 auto;
  width: 16px;
  height: 16px;
  color: var(--text-primary);
}
/* The EW loader animates inside this slot while the turn is in flight and is
   replaced by the static spark on completion. */
.reasoning-spark svg { width: 16px; height: 16px; display: block; }

.reasoning-label {
  flex: 1 1 auto;
  min-width: 0;
  font-family: var(--font-body);
  font-size: 13.5px;
  line-height: 19px;
  font-weight: 400;
  color: var(--text-primary);       /* primary, NOT muted */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Live elapsed time, never truncated: the label ellipsises before this does. */
.reasoning-elapsed {
  flex: 0 0 auto;
  font-family: var(--font-body);
  font-size: 12px;
  line-height: 19px;
  font-weight: 400;
  color: var(--text-tertiary);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.reasoning-elapsed:empty { display: none; }

.reasoning-chev {
  display: inline-flex;
  flex: 0 0 auto;
  color: var(--text-primary);
  transition: transform 140ms ease;
}
.reasoning[data-expanded="1"] .reasoning-chev { transform: rotate(180deg); }

.reasoning-steps {
  display: flex;
  flex-direction: column;
  padding: 8px 0 0 24px;           /* aligns under the label */
}

/* Each step: a 14px icon column and a text column, with a hairline connector
   running between consecutive icons. */
.rstep { display: flex; align-items: stretch; gap: 8px; }

.rstep-icon {
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 14px;
  flex: 0 0 auto;
  color: var(--primary-main);      /* #0E4E69 teal-navy, not green */
  padding-top: 1px;
}
.rstep-icon svg { width: 14px; height: 14px; display: block; }
/* the in-flight step carries the loader and reads a shade stronger */
.rstep[data-state="active"] .rstep-label { color: var(--text-secondary); }
.rstep-icon::after {
  content: "";
  width: 1px;
  flex: 1 1 auto;
  min-height: 7px;
  margin: 2px 0;
  background: var(--connector);
}
.rstep:last-child .rstep-icon svg { width: 14px; height: 14px; display: block; }
/* the in-flight step carries the loader and reads a shade stronger */
.rstep[data-state="active"] .rstep-label { color: var(--text-secondary); }
.rstep-icon::after { display: none; }

.rstep-col {
  flex: 1 1 auto;
  min-width: 0;
  /* 8px of tail below each row keeps the #C2C1BE connector hairline visible;
     at 5px the icons nearly touch and the connector disappears. */
  padding: 0 0 8px;
}
.rstep-label {
  font-family: var(--font-body);
  font-size: 11.5px;
  line-height: 16px;
  font-weight: 600;
  color: var(--text-tertiary);
  overflow-wrap: anywhere;
}
.rstep-detail {
  font-family: var(--font-body);
  font-size: 11.5px;
  line-height: 16px;
  font-weight: 400;
  color: var(--text-tertiary);
  padding-left: 12px;
  position: relative;
  overflow-wrap: anywhere;
}
.rstep-detail::before {
  content: "•";
  position: absolute;
  left: 2px;
}
.rstep-label code, .rstep-detail code {
  font-family: var(--mono);
  font-size: 10.5px;
  background: var(--bg-secondary);
  border-radius: 4px;
  padding: 0 4px;
  word-break: break-all;
}
.rstep-label strong, .rstep-detail strong { font-weight: 700; }

/* ---------------------------------------------------------- edit cards
   Our own affordance, styled like EW's content cards: white, 2xl radius,
   hairline, no shadow. */

.card {
  border-radius: var(--r-lg);
  background: var(--bg-primary);
  border: var(--hairline);
  overflow: hidden;
}

.card-head {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  width: 100%;
  padding: 11px 10px 10px 12px;
  font: inherit;
  font-family: var(--font-chrome);
  text-align: left;
  background: none;
  border: 0;
  cursor: pointer;
  color: var(--text-primary);
}
.card-head:hover { background: var(--bg-secondary); }

.card-icon {
  display: inline-flex;
  color: var(--primary-main);
  flex: 0 0 auto;
  margin-top: 1px;
}
.card-main { flex: 1 1 auto; min-width: 0; }
.card-label {
  display: block;
  font-size: 13px;
  font-weight: 500;
  line-height: 18px;
  overflow-wrap: anywhere;
}
.card-target {
  display: inline-block;
  margin-top: 6px;
  font-family: var(--mono);
  font-size: 10px;
  line-height: 15px;
  color: var(--text-secondary);
  background: var(--bg-secondary);
  border-radius: var(--r-full);
  padding: 2px 9px;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  vertical-align: middle;
}
.card-chev {
  display: inline-flex;
  color: var(--neutral-400);
  flex: 0 0 auto;
  margin-top: 1px;
  transition: transform 140ms ease;
}
.card[data-expanded="1"] .card-chev { transform: rotate(180deg); }

.card-detail { padding: 2px 12px 4px; }
.card-type {
  font-family: var(--mono);
  font-size: 10px;
  color: var(--text-tertiary);
  margin-bottom: 7px;
  overflow-wrap: anywhere;
}
.card-payload {
  margin: 0;
  padding: 10px 12px;
  font-family: var(--mono);
  font-size: 11px;
  line-height: 16px;
  color: var(--text-secondary);
  background: var(--bg-secondary);
  border-radius: var(--r-md);
  max-height: 220px;
  overflow: auto;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

.card-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  padding: 2px 12px 12px;
}
.card-foot:empty { display: none; }

.card-btn {
  font-family: var(--font-chrome);
  font-size: 12px;
  font-weight: 500;
  line-height: 17px;
  padding: 5px 14px;
  border-radius: var(--r-full);
  border: 0;
  background: var(--bg-secondary);
  color: var(--text-secondary);
  cursor: pointer;
  transition: background 120ms ease, color 120ms ease;
}
.card-btn:hover { background: var(--bg-hover); color: var(--text-primary); }
.card-btn-primary { background: var(--primary-main); color: var(--text-inverted); }
.card-btn-primary:hover { background: var(--primary-hover); color: var(--text-inverted); }
.card-btn:disabled { opacity: 0.45; cursor: default; }

.card-status {
  display: flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-chrome);
  font-size: 11.5px;
  line-height: 16px;
  color: var(--text-tertiary);
  min-width: 0;
  overflow-wrap: anywhere;
}
.card-status:empty { display: none; }
.card-status svg { flex: 0 0 auto; }
.card-status-icon { display: inline-flex; }
.card-status-icon:empty { display: none; }

.card[data-state="applied"] .card-status { color: var(--green-500); }
.card[data-state="failed"] .card-status { color: var(--red-600); }
.card[data-state="running"] .card-status { color: var(--text-secondary); }
.card[data-state="running"] .card-status-icon { animation: spin 900ms linear infinite; }
.card[data-state="dismissed"] { background: var(--bg-secondary); }
.card[data-state="dismissed"] .card-label { color: var(--text-tertiary); }
.card[data-state="unsupported"] { background: var(--bg-secondary); }
.card[data-state="unsupported"] .card-icon,
.card[data-state="unsupported"] .card-label { color: var(--text-secondary); }
.card[data-state="unsupported"] .card-target { background: var(--bg-hover); }
.card[data-state="unsupported"] .card-head:hover { background: var(--bg-hover); }

@keyframes spin { to { transform: rotate(360deg); } }
@keyframes pulse { 0%, 100% { opacity: 0.3; } 50% { opacity: 1; } }

/* ------------------------------------------------------------- errors */

.turn-error {
  font-family: var(--font-body);
  color: var(--red-600);
  font-size: 13px;
  line-height: 19px;
  overflow-wrap: anywhere;
}
.turn-retry {
  align-self: flex-start;
  margin-top: 8px;
  font-family: var(--font-chrome);
  font-size: 12.5px;
  font-weight: 500;
  color: var(--text-inverted);
  background: var(--primary-main);
  border: 0;
  border-radius: var(--r-full);
  padding: 7px 14px;
  cursor: pointer;
}
.turn-retry:hover { background: var(--primary-hover); }
.turn-retry:disabled { background: var(--bg-hover); color: var(--text-tertiary); cursor: default; }

/* A refused-for-auth turn offers TWO things in sequence — sign in, then re-ask
   the question that was refused — so they share a row and wrap at 320px rather
   than stacking two full-width pills. */
.turn-auth { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.turn-auth .turn-retry { margin-top: 8px; }
/* The second action is secondary until sign-in has actually happened; once it
   is the only action left it is the one that matters, so it keeps the filled
   treatment and only the outline variant is used while both are on screen. */
.turn-retry-secondary {
  color: var(--primary-main);
  background: var(--bg-primary);
  box-shadow: inset 0 0 0 1px var(--neutral-400);
}
.turn-retry-secondary:hover { color: var(--text-inverted); background: var(--primary-main); }

/* Said in the transcript, not in the red error line: the sign-in succeeded and
   the question survived it. */
.turn-auth-ok {
  font-family: var(--font-body);
  font-size: 13px;
  line-height: 19px;
  color: var(--text-secondary);
  overflow-wrap: anywhere;
}

.uuid {
  font-family: var(--mono);
  font-size: 10px;
  color: var(--text-tertiary);
  overflow-wrap: anywhere;
}

/* ---------------------------------------------------------- composer
   EW's composer is a NESTED PAIR: a tinted #F4F3F0 frame with shadow-xl
   wrapping a white card with its own soft inner glow. */

.composer-wrap {
  flex: 0 0 auto;
  position: relative;
  padding: 4px 14px 12px;
  background: var(--bg-canvas);
}

.ctx-chip {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  max-width: 100%;
  margin-bottom: 9px;
  padding: 4px 5px 4px 11px;
  font-size: 12px;
  color: var(--text-secondary);
  background: var(--bg-primary);
  border: var(--hairline);
  border-radius: var(--r-full);
}
.ctx-icon { display: inline-flex; color: var(--text-tertiary); flex: 0 0 auto; }
.ctx-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ctx-x {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--text-tertiary);
  cursor: pointer;
  flex: 0 0 auto;
}
.ctx-x:hover { background: var(--bg-secondary); color: var(--text-primary); }
/* The selection's size, after the label: "Slides 44-64 selected · 21 slides". */
.ctx-count { color: var(--text-tertiary); flex: 0 0 auto; white-space: nowrap; }

/* Pre-flight read warning. Quiet — it is information, not an error, and
   nothing about it may read as "you can't send this". */
.ctx-warn {
  margin: -4px 0 9px;
  padding: 0 4px;
  font-size: 11.5px;
  line-height: 1.45;
  color: var(--text-tertiary);
}

/* ------------------------------------------------------------ read notes
   A read is auto-executed with no approval, so it gets a QUIET ONE-LINE NOTE
   rather than a card: no border, no surface, no Accept button. It exists so he
   can always see what Otto looked at — the trail, not an interaction.
   Deliberately much lighter than .card: at 350px, cards and notes sitting in
   the same column must be distinguishable at a glance.

   It IS expandable, though. A read is a tool call against his document, so the
   note discloses the verb, the payload and the result Otto actually received —
   collapsed by default so the quiet default is preserved. The expansion
   borrows .card-type/.card-payload from the edit card rather than restyling
   them, so reads and edits stay ONE convention instead of drifting into two. */
.read-note { margin: 5px 0; }

.read-head {
  display: flex;
  align-items: baseline;
  /* WRAP. A rejected read carries the server's whole reason ("speaker notes are
     not readable through the PowerPoint API"), which does not fit beside a
     label in 350px. Without wrapping it overflowed the column and painted over
     the label — verified in the harness screenshot. */
  flex-wrap: wrap;
  gap: 2px 6px;
  width: 100%;
  padding: 2px 4px;
  font: inherit;
  font-family: var(--font-chrome);
  font-size: 12px;
  line-height: 1.5;
  text-align: left;
  background: none;
  border: 0;
  border-radius: var(--r-sm);
  cursor: pointer;
  color: var(--text-tertiary);
}
.read-head:hover { background: var(--bg-secondary); }

.read-icon { display: inline-flex; align-items: center; flex: 0 0 auto; transform: translateY(2px); }
.read-label { flex: 0 1 auto; min-width: 0; }
/* Inline when it fits, its own (indented) line when it doesn't. */
.read-detail { color: var(--neutral-400); flex: 0 1 auto; min-width: 0; }
.read-detail:empty { display: none; }
/* Same glyph, same rotation, same easing as .card-chev — one convention. */
.read-chev {
  display: inline-flex;
  align-items: center;
  color: var(--neutral-400);
  flex: 0 0 auto;
  margin-left: auto;
  transform: translateY(2px);
  transition: transform 140ms ease;
}
.read-note[data-expanded="1"] .read-chev { transform: translateY(2px) rotate(180deg); }

.read-note[data-state="reading"] .read-icon { animation: spin 900ms linear infinite; }
.read-note[data-state="failed"] .read-head { color: var(--text-secondary); }
.read-note[data-state="failed"] .read-icon { color: var(--red-600); }
/* A client-side note ("Stopped.") is not a tool call, so it does not disclose. */
.read-note[data-state="info"] .read-head { color: var(--text-secondary); cursor: default; }
.read-note[data-state="info"] .read-chev { display: none; }

/* The expanded tool call. Indented under the eye glyph so it reads as
   belonging to the note it came from. */
.read-body { padding: 2px 0 8px 19px; }
.read-section {
  margin: 9px 0 5px;
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-tertiary);
}
/* A read result is document content and runs to thousands of characters; give
   it more room than a payload but KEEP the internal scroll, so expanding a
   read never pushes the composer off a 350px pane. */
.read-result { max-height: 260px; }
.read-warn {
  margin: 9px 0 0;
  padding: 7px 10px;
  font-size: 11.5px;
  line-height: 1.45;
  color: var(--text-primary);
  background: var(--bg-secondary);
  border-left: 2px solid var(--red-600);
  border-radius: var(--r-sm);
}

.composer-frame {
  background: var(--bg-secondary);
  border: var(--hairline-frame);
  border-radius: 30px;
  padding: 6px;
  box-shadow: var(--shadow-xl);
}

.composer {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 11px 10px 8px 14px;
  background: var(--bg-primary);
  border: var(--hairline-frame);
  border-radius: 24px;
  box-shadow: var(--shadow-inner-glow);
}

.prompt {
  flex: 1 1 auto;
  border: 0;
  outline: none;
  resize: none;
  font-family: var(--font-body);
  font-size: 14px;
  line-height: 21px;
  color: var(--text-primary);
  background: transparent;
  max-height: 110px;
  min-height: 21px;
  padding: 0;
  overflow-y: auto;
}
.prompt::placeholder { color: var(--text-tertiary); }

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

.plus-btn {
  flex: 0 0 auto;
  width: 30px;
  height: 30px;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--text-tertiary);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  margin-left: -6px;
}
.plus-btn:hover { background: var(--bg-secondary); color: var(--text-primary); }

.send {
  flex: 0 0 auto;
  width: 34px;
  height: 34px;
  border: 0;
  border-radius: 50%;
  background: var(--send-green);
  color: #0d2b12;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: filter 120ms ease;
}
.send:hover { filter: brightness(0.95); }
.send:disabled { opacity: 0.45; cursor: default; filter: none; }
/* Stop. Same disc, neutral fill: halting a turn is not a primary action, but it
   has to be unmistakably the same button he just pressed to send. */
.send[data-mode="stop"] { background: var(--bg-active); color: var(--text-primary); }

/* ------------------------------------------------- pending-edit tray */

.accept-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-bottom: 8px;
}
.accept-row:empty { display: none; }

.accept-all {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-family: var(--font-chrome);
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text-inverted);
  background: var(--primary-main);
  border: 0;
  border-radius: var(--r-full);
  padding: 8px 16px 8px 13px;
  cursor: pointer;
  transition: background 120ms ease;
}
.accept-all:hover { background: var(--primary-hover); }
.accept-all:disabled {
  background: var(--bg-hover);
  color: var(--text-tertiary);
  cursor: default;
}
.accept-all-icon { display: inline-flex; }

.dismiss-all {
  font-family: var(--font-chrome);
  font-size: 12.5px;
  font-weight: 500;
  color: var(--text-secondary);
  background: none;
  border: 0;
  border-radius: var(--r-full);
  padding: 8px 12px;
  cursor: pointer;
}
.dismiss-all:hover { background: var(--bg-hover); color: var(--text-primary); }
.dismiss-all:disabled { color: var(--neutral-400); cursor: default; }

.accept-result {
  font-size: 11.5px;
  color: var(--text-tertiary);
  overflow-wrap: anywhere;
}

.no-undo {
  margin: 8px 4px 0;
  font-size: 10px;
  line-height: 14px;
  color: #8a8986;
  text-align: center;
}

/* --------------------------------------------------- narrow-pane guard
   Office can drag the pane to ~320px. Nothing may overflow there. */
@media (max-width: 340px) {
  :root { --gutter: 20px; --gutter-gap: 7px; }
  .transcript { padding: 4px 10px 12px; }
  .composer-wrap { padding: 4px 10px 10px; }
  .status-line { padding: 10px 6px 8px 10px; }
  .empty-greeting { font-size: 25px; line-height: 32px; }
  .msg-body, .narration, .prompt { font-size: 13.5px; line-height: 20px; }
  .msg-name { font-size: 13.5px; }
  .reasoning-steps { padding-left: 20px; }
  .card-head { padding: 10px 8px 9px 10px; }
  .card-foot, .card-detail { padding-left: 10px; padding-right: 10px; }
  .accept-all { padding: 7px 13px 7px 11px; }
  .narration th, .narration td { padding-left: 8px; padding-right: 8px; }
}

/* ==========================================================================
   STREAM-IN
   ==========================================================================

   The Conversations API has no streaming transport: a turn is POSTed and then
   polled, and each message arrives complete. Narration and reasoning DO appear
   progressively, because the server emits them as separate messages while the
   turn runs — that part is real. The final answer and the proposed-edit cards
   parsed out of it all land in a single poll, so without this they appear as
   one abrupt block.

   This staggers their entrance. It is a cosmetic reveal of data already in
   hand, not simulated progress: the delay is capped low enough that it never
   holds anything back meaningfully, and the cards are live from the moment
   they exist. The animation only moves opacity and transform, so it never
   affects layout or hit-testing.
   ========================================================================== */

@keyframes stream-in {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}

.stream-in {
  /* `both` so the item is not painted before its delay elapses. */
  animation: stream-in 240ms cubic-bezier(0.2, 0.7, 0.3, 1) both;
}

/* Someone who has asked the OS to reduce motion has asked for exactly this to
   stop. Show everything immediately rather than a shorter animation. */
@media (prefers-reduced-motion: reduce) {
  .stream-in { animation: none; }
}
