@font-face {
  font-family: "NB International Pro";
  src: url("/fonts/nbinternationalproreg-webfont.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
}

@font-face {
  font-family: "NB International Pro";
  src: url("/fonts/nbinternationalprolig-webfont.woff2") format("woff2");
  font-weight: 300;
  font-style: normal;
}

@font-face {
  font-family: "NB International Pro";
  src: url("/fonts/nbinternationalpromed-webfont.woff2") format("woff2");
  font-weight: 500;
  font-style: normal;
}

@font-face {
  font-family: "NB International Pro";
  src: url("/fonts/nbinternationalprobol-webfont.woff2") format("woff2");
  font-weight: 700;
  font-style: normal;
}

* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
  font-size: inherit;
}

:root {
  --bg: #ffffff;
  --fg: rgba(0, 0, 0, 0.78);
  --muted: rgba(0, 0, 0, 0.52);
  --muted-strong: rgba(0, 0, 0, 0.65);
  --border: rgba(0, 0, 0, 0.12);
  --accent: #2d5a45;
  --accent-rgb: 45, 90, 69;
  --user-bg: rgba(0, 0, 0, 0.07);
  --user-fg: rgba(0, 0, 0, 0.78);
  --assistant-bg: transparent;
  --error-bg: #fdf2f2;
  --error-border: rgba(0, 0, 0, 0.08);
  --input-bg: #ffffff;
  --debug-bg: #1a1a1a;
  --debug-fg: rgba(255, 255, 255, 0.75);
  --debug-info: #9cdcfe;
  --debug-success: #89d185;
  --debug-warn: #dcdcaa;
  --debug-error: #f48771;
  --shimmer-dim: rgba(0, 0, 0, 0.28);
  /* Sandbox palette — warm amber/sand. Distinct from the main forest-
     green accent so users can tell at a glance that they're looking at
     a scratch preview, not live state. Used for the sandbox-dialog and
     sandbox-preview chrome (top stripe, status pulse, UNCOMMITTED
     pill, current-step marker). */
  --sandbox-accent: #b87a1f;
  --sandbox-accent-rgb: 184, 122, 31;
  --sandbox-tint: #fef4dc;
  --sandbox-border: rgba(184, 122, 31, 0.32);
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #1c1c1c;
    --fg: rgba(255, 255, 255, 0.85);
    --muted: rgba(255, 255, 255, 0.52);
    --muted-strong: rgba(255, 255, 255, 0.65);
    --border: rgba(255, 255, 255, 0.12);
    --accent: #53d55e;
    --accent-rgb: 83, 213, 94;
    --user-bg: rgba(255, 255, 255, 0.08);
    --user-fg: rgba(255, 255, 255, 0.85);
    --assistant-bg: transparent;
    --error-bg: rgba(255, 0, 0, 0.06);
    --error-border: rgba(255, 0, 0, 0.12);
    --input-bg: rgba(255, 255, 255, 0.06);
    --debug-bg: #141414;
    --debug-fg: rgba(255, 255, 255, 0.75);
    --shimmer-dim: rgba(255, 255, 255, 0.28);
    --sandbox-accent: #f0c674;
    --sandbox-accent-rgb: 240, 198, 116;
    --sandbox-tint: rgba(240, 198, 116, 0.08);
    --sandbox-border: rgba(240, 198, 116, 0.32);
  }
}

html,
body {
  height: 100%;
  overflow: hidden;
}

body {
  font-family: "NB International Pro", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  font-size: 14px;
  font-weight: 400;
  color: var(--fg);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

#app {
  display: flex;
  flex-direction: column;
  height: 100vh;
  position: relative;
}

/* Top overlay — floats over the message list with a gradient fade */

#top-overlay {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 80px;
  background: linear-gradient(to bottom, var(--bg) 40%, transparent);
  pointer-events: none;
  z-index: 10;
  display: flex;
  align-items: flex-start;
  justify-content: flex-end;
  padding: 6px 40px 0 12px;
}

body.blurred #new-chat-btn,
body.blurred #settings-btn,
body.blurred .auto-approve-chip {
  opacity: 0;
  pointer-events: none;
}

/* Persistent state indicator + toggle for the session-scoped
   auto-approve flag. Sits on the left of the top overlay so the
   user can always see whether edits will commit automatically or
   stop for approval, and flip it without diving into the dialog. */
.auto-approve-chip {
  pointer-events: all;
  display: inline-flex;
  align-items: center;
  height: 26px;
  padding: 0 10px;
  margin-right: auto;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: transparent;
  color: var(--muted);
  font: inherit;
  font-size: 11.5px;
  font-weight: 500;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease,
    opacity 0.2s;
}

.auto-approve-chip:hover {
  border-color: var(--muted);
  color: var(--fg);
  background: var(--user-bg);
}

/* "On" state stays a ghost chip — solid fill was too shouty next to
   the chat. We just tint the icon/text accent-green and pull the
   border to a faint green so the state reads as "active" without
   competing with the message list for attention. */
.auto-approve-chip.is-on {
  color: var(--accent);
  border-color: rgba(var(--accent-rgb), 0.4);
  background: transparent;
}

.auto-approve-chip.is-on:hover {
  border-color: rgba(var(--accent-rgb), 0.7);
  background: rgba(var(--accent-rgb), 0.06);
}

.auto-approve-chip-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-right: 6px;
}

/* Idle the chip shows just "Auto" / "Ask". On hover it grows to
   reveal the full sentence ("Approving changes automatically" /
   "Ask before making changes"). Both labels live stacked at the same
   left edge inside a wrapper whose width animates between the short
   width and the full width. Crossfading via opacity rather than
   sliding avoids the right-then-left jump you get with sibling-based
   max-width transitions. */
/* The prefix ("Auto" / "Ask") is always visible. The suffix
   ("-approving changes" / " before making changes") is collapsed
   to zero width at rest and reveals itself on hover. Because the
   prefix never disappears, there's no crossfade or content swap —
   the chip simply grows to make room for more text. */
.auto-approve-chip-label {
  display: inline-flex;
  align-items: baseline;
  white-space: nowrap;
}

.auto-approve-chip-suffix {
  display: inline-block;
  overflow: hidden;
  max-width: 0;
  /* Preserve the leading space in " before making changes" — without
     `pre`, the browser collapses whitespace at the start of an
     inline-block and you get "Askbefore". */
  white-space: pre;
  transition: max-width 0.28s ease;
}

.auto-approve-chip:hover .auto-approve-chip-suffix {
  max-width: 240px;
}

#new-chat-btn {
  display: none;
  pointer-events: all;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  padding: 0;
  border: none;
  border-radius: 6px;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
  transition: color 0.3s, opacity 0.2s;
  position: relative;
}

#new-chat-btn:hover {
  color: var(--fg);
  background: var(--user-bg);
}

#new-chat-btn::after {
  content: "New chat";
  position: absolute;
  top: 50%;
  right: calc(100% + 8px);
  transform: translateY(-50%);
  background: #1f1f1f;
  color: #fff;
  font-size: 11px;
  font-weight: 400;
  white-space: nowrap;
  padding: 8px 12px;
  border-radius: 6px;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.3s;
  display: flex;
  align-items: center;
  z-index: 20;
}

#new-chat-btn:hover::after {
  opacity: 1;
}

/* Welcome state */

.welcome {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  flex: 1;
  gap: 16px;
  padding: 24px 16px;
  text-align: center;
  min-height: 100%;
}

.welcome-logo {
  margin-bottom: -8px;
}

.welcome-logo {
  margin-bottom: 8px;
}

.welcome-subtitle {
  color: var(--muted);
  font-weight: 300;
  font-size: 17px;
  margin-bottom: 16px;
}

.welcome-prompts {
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: 100%;
  max-width: 280px;
  margin-top: -8px;
}

.prompt-chip {
  padding: 10px 16px;
  border: none;
  border-radius: 12px;
  background: var(--user-bg);
  color: var(--fg);
  font-family: inherit;
  font-weight: 500;
  text-align: left;
  cursor: pointer;
  transition: background 0.3s;
}

.prompt-chip:hover {
  background: rgba(0, 0, 0, 0.04);
}

@media (prefers-color-scheme: dark) {
  .prompt-chip:hover {
    background: rgba(255, 255, 255, 0.06);
  }
}

/* Messages area */

#messages {
  flex: 1;
  overflow-y: auto;
  padding: 80px 12px 24px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  position: relative;
}

.scroll-to-bottom {
  position: sticky;
  bottom: 0px;
  align-self: center;
  width: 40px;
  height: 40px;
  border: 1px solid var(--border);
  border-radius: 50%;
  background: var(--bg);
  color: var(--muted-strong);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  transition: color 0.2s, background 0.2s;
  animation: fadeIn 0.2s ease-out;
  flex-shrink: 0;
  opacity: 0.95;
}

.scroll-to-bottom:hover {
  color: var(--fg);
  opacity: 1;
}

@keyframes messageIn {
  from {
    opacity: 0;
    transform: translateY(8px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes fadeIn {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

.message {
  max-width: 90%;
  padding: 8px 12px;
  border-radius: 10px;
  line-height: 1.45;
  word-wrap: break-word;
  animation: fadeIn 0.3s ease-out;
}

.message-user {
  align-self: flex-end;
  background: var(--user-bg);
  color: var(--user-fg);
  border-bottom-right-radius: 3px;
  white-space: pre-wrap;
  animation: fadeIn 0.3s ease-out;
  margin-bottom: 12px;
}

.message-assistant {
  align-self: flex-start;
  line-height: 1.6;
  max-width: 100%;
  padding-left: 0;
  padding-right: 8px;
}

.message-assistant p {
  margin-bottom: 12px;
}

.message-assistant p:last-child {
  margin-bottom: 0;
}

.message-assistant h1,
.message-assistant h2,
.message-assistant h3 {
  font-weight: 500;
  margin-bottom: 4px;
  margin-top: 12px;
}

.message-assistant h1:first-child,
.message-assistant h2:first-child,
.message-assistant h3:first-child {
  margin-top: 0;
}

.message-assistant h1 {
  font-size: 17px;
}
.message-assistant h2 {
  font-size: 15px;
}
.message-assistant h3 {
  font-size: 14px;
}

.message-assistant ul,
.message-assistant ol {
  padding-left: 20px;
  margin-bottom: 8px;
}

.message-assistant li {
  margin-bottom: 6px;
}

.message-assistant ul li::marker {
  font-size: 1.4em;
}

.message-assistant ol li::marker {
  font-size: 1.1em;
}

.message-assistant li:last-child {
  margin-bottom: 0;
}

.message-assistant code {
  font-family: "SF Mono", "Menlo", "Consolas", monospace;
  font-size: 13px;
  background: rgba(0, 0, 0, 0.06);
  padding: 1px 4px;
  border-radius: 3px;
}

.message-assistant pre {
  background: rgba(0, 0, 0, 0.06);
  border-radius: 6px;
  padding: 10px 12px;
  overflow-x: auto;
  margin-bottom: 8px;
}

.message-assistant pre code {
  background: none;
  padding: 0;
  font-size: 13px;
}

.message-assistant a {
  color: var(--accent);
  text-decoration: underline;
}

/* Clickable reference link — `grid:` markdown link rendered as a pill.
 * Negative horizontal margin cancels the hover padding so the line doesn't
 * reflow when the background appears. */
a.grid-ref-pill {
  color: var(--accent);
  text-decoration: underline dotted;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  cursor: pointer;
  border-radius: 3px;
  padding: 0 2px;
  margin: 0 -2px;
  transition: background 0.15s ease, text-decoration-style 0.15s ease;
}

/* Address-label variant — when the label is itself a cell reference, it should
 * read as code rather than prose: monospace plus the same subtle box as inline
 * `code`, while keeping the dotted-underline affordance that signals clickability. */
a.grid-ref-pill-mono {
  font-family: "SF Mono", "Menlo", "Consolas", monospace;
  font-size: 0.92em;
  background: rgba(0, 0, 0, 0.06);
  padding: 1px 4px;
}

a.grid-ref-pill:hover {
  background: color-mix(in srgb, var(--accent) 14%, transparent);
  text-decoration-style: solid;
}

a.grid-ref-pill:active {
  background: color-mix(in srgb, var(--accent) 22%, transparent);
}

a.grid-ref-pill:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  text-decoration: none;
}

.message-assistant strong {
  font-weight: 700;
}

.message-assistant hr {
  border: none;
  border-top: 1px solid var(--border);
  margin: 12px 0;
}

.message-assistant table {
  /* display: block + width: max-content lets the table size to its content
     and scroll horizontally inside the message instead of pushing the chat
     layout wider than the addin pane. The +20px on max-width consumes the
     cumulative right paddings (8px on .message-assistant + 12px on #messages)
     so a wide table extends to the viewport edge instead of stopping short. */
  display: block;
  width: max-content;
  max-width: calc(100% + 20px);
  overflow-x: auto;
  border-collapse: collapse;
  margin-bottom: 12px;
  font-size: 13px;
}

.message-assistant th {
  text-align: left;
  font-weight: 500;
  padding: 6px 12px 6px 0;
  border-bottom: 1px solid var(--border);
  color: var(--muted);
  white-space: nowrap;
}

.message-assistant td {
  padding: 6px 12px 6px 0;
  border-bottom: 1px solid var(--border);
  vertical-align: top;
}

.message-assistant tr:last-child td {
  border-bottom: none;
}

.message-error {
  align-self: flex-start;
  background: var(--error-bg);
  border: 1px solid var(--error-border);
  color: rgba(180, 40, 40, 0.85);
  font-size: 12px;
}

.message-status {
  align-self: center;
  color: var(--muted);
  font-size: 11px;
  font-style: italic;
  padding: 4px;
}

/* Activity status (thinking + tool execution) */

.activity {
  align-self: flex-start;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 8px 6px 8px;
  color: var(--muted-strong);
}

.activity-logo {
  flex-shrink: 0;
  display: flex;
  margin-left: -8px;
}

.activity-text {
  font-size: 12px;
  font-weight: 500;
  background: linear-gradient(
    90deg,
    var(--muted-strong) 0%,
    var(--muted-strong) 25%,
    var(--shimmer-dim) 50%,
    var(--muted-strong) 75%,
    var(--muted-strong) 100%
  );
  background-size: 200% 100%;
  background-clip: text;
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  animation: shimmer 2s linear infinite;
}

@keyframes shimmer {
  0% {
    background-position: 100% 0;
  }
  100% {
    background-position: -100% 0;
  }
}

/* ── Step markers (section breaks) ────────────────────────────────────── */

.step-marker {
  align-self: stretch;
  padding: 0;
  margin: 16px 0 0 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

/* Don't add extra space above the very first message in the chat. */
#messages > .step-marker:first-child {
  margin-top: 4px;
}

.step-marker-index {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
  font-family: "SF Mono", "Menlo", "Consolas", monospace;
  font-weight: 500;
  margin-bottom: 2px;
}

.step-marker-title {
  font-weight: 600;
  color: var(--fg);
  font-size: 14px;
  line-height: 1.35;
}

.step-marker-detail {
  color: var(--muted-strong);
  font-size: 13px;
  line-height: 1.5;
  margin-top: 2px;
}

/* Rollup affordance — borderless link-like control so it doesn't visually
   compete with phase widgets or the monospace step header. */
.step-marker-rollup {
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  margin-top: 6px;
  padding: 0;
  background: transparent;
  border: none;
  color: var(--muted-strong);
  font-family: inherit;
  font-size: 12px;
  line-height: 1.4;
  cursor: pointer;
  transition: color 0.15s;
}

.step-marker-rollup:hover {
  color: var(--fg);
}

.step-marker-rollup:hover > span {
  text-decoration: underline;
  text-underline-offset: 3px;
}

.step-marker-rollup-chevron {
  transition: transform 0.2s ease;
  color: var(--muted);
}

.step-marker-rollup-expanded .step-marker-rollup-chevron {
  transform: rotate(90deg);
}

/* ── Phase blocks ─────────────────────────────────────────────────────── */

.message-phase {
  align-self: stretch;
  /* Override the .message base max-width: 90% so phases get the full width
     of the messages container, matching step-marker / assistant text. */
  max-width: 100%;
  background: transparent;
  border: none;
  border-radius: 0;
  margin-left: 0;
  padding: 0;
  font-size: 12px;
}

.message-phase > details > summary {
  cursor: pointer;
  user-select: none;
  display: flex;
  align-items: center;
  gap: 8px;
  list-style: none;
  padding: 6px 8px 6px 8px;
  color: var(--muted-strong);
  position: relative;
  isolation: isolate;
}

.message-phase > details > summary::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: -8px;
  right: -8px;
  border-radius: 8px;
  z-index: -1;
  transition: background 0.15s;
}

.phase-logo {
  display: flex;
  align-items: center;
  flex-shrink: 0;
  margin-left: -8px;
}

.message-phase.phase-sealed .phase-logo svg {
  transition: filter 0.3s ease, opacity 0.3s ease;
  filter: grayscale(1);
  opacity: 0.55;
}

.message-phase.phase-sealed details[open] .phase-logo svg {
  filter: grayscale(1) brightness(0.75);
  opacity: 0.85;
}

.message-phase.phase-sealed .phase-logo svg * {
  animation: none !important;
}

.message-phase > details > summary:hover::before {
  background: rgba(0, 0, 0, 0.04);
}

@media (prefers-color-scheme: dark) {
  .message-phase > details > summary:hover::before {
    background: rgba(255, 255, 255, 0.06);
  }
}

.message-phase > details > summary::-webkit-details-marker {
  display: none;
}

.phase-chevron-wrap {
  display: flex;
  align-items: center;
  flex-shrink: 0;
  margin-left: auto;
  color: var(--muted);
  transition: transform 0.2s ease;
}

.message-phase details[open] > summary .phase-chevron-wrap {
  transform: rotate(90deg);
}

.message-phase.phase-live .phase-header-label {
  background: linear-gradient(
    90deg,
    var(--muted-strong) 0%,
    var(--muted-strong) 25%,
    var(--shimmer-dim) 50%,
    var(--muted-strong) 75%,
    var(--muted-strong) 100%
  );
  background-size: 200% 100%;
  background-clip: text;
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  animation: shimmer 2s linear infinite;
}

.message-phase.phase-sealed .phase-header-label {
  color: var(--muted-strong);
}

.phase-header-label {
  font-weight: 500;
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.phase-tool-count {
  flex-shrink: 0;
  font-size: 11px;
  color: var(--muted);
  font-family: "SF Mono", "Menlo", "Consolas", monospace;
  display: inline-flex;
  align-items: baseline;
  gap: 4px;
}

.phase-tool-count-num {
  display: inline-block;
  /* Re-keyed on every increment so React unmounts/mounts the span and
     restarts the animation. */
  animation: phaseToolCountPop 0.32s ease-out;
}

@keyframes phaseToolCountPop {
  0% { transform: scale(1); }
  35% { transform: scale(1.45); color: var(--accent); }
  100% { transform: scale(1); }
}

.phase-cancelled {
  flex-shrink: 0;
  font-size: 11px;
  color: rgba(180, 40, 40, 0.85);
  font-style: italic;
}

.phase-body {
  margin-top: 6px;
  margin-left: 6px;
  padding: 2px 8px 10px 8px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  border-left: 2px solid var(--border);
}

.phase-entry-text {
  font-size: 12px;
  color: var(--muted-strong);
  line-height: 1.55;
  font-style: italic;
}

.phase-entry-text p {
  margin: 0 0 4px 0;
}

.phase-entry-text p:last-child {
  margin-bottom: 0;
}

/* The global `* { padding: 0 }` reset wipes the UA list padding, so bullets
   render outside the box and overlap the phase's left rule. Restore enough
   padding to keep markers inside the body. */
.phase-entry-text ul,
.phase-entry-text ol {
  padding-left: 18px;
  margin: 4px 0;
}

.phase-entry-text li {
  margin-bottom: 2px;
}

.phase-entry-text li:last-child {
  margin-bottom: 0;
}

.phase-entry-text table {
  display: block;
  width: max-content;
  /* +20px consumes the .phase-body padding-right (8) + #messages padding-right
     (12) so a wide table reaches the viewport edge. */
  max-width: calc(100% + 20px);
  overflow-x: auto;
  border-collapse: collapse;
  margin: 4px 0;
  font-size: 12px;
}

.phase-entry-thinking {
  font-size: 11px;
  color: var(--muted);
  line-height: 1.5;
  white-space: pre-wrap;
  font-style: italic;
  padding: 4px 8px;
  background: rgba(0, 0, 0, 0.025);
  border-radius: 4px;
}

@media (prefers-color-scheme: dark) {
  .phase-entry-thinking {
    background: rgba(255, 255, 255, 0.04);
  }
}

.phase-entry-tool details {
  display: block;
}

.phase-entry-tool summary {
  cursor: pointer;
  user-select: none;
  display: flex;
  align-items: center;
  gap: 8px;
  list-style: none;
  padding: 3px 6px;
  margin-left: 6px;
  font-size: 12px;
  color: var(--fg);
  border-radius: 4px;
  transition: background 0.15s;
}

.phase-entry-tool summary:hover {
  background: rgba(0, 0, 0, 0.04);
}

@media (prefers-color-scheme: dark) {
  .phase-entry-tool summary:hover {
    background: rgba(255, 255, 255, 0.06);
  }
}

.phase-entry-tool summary::-webkit-details-marker {
  display: none;
}

.phase-entry-status {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 14px;
  color: var(--muted);
}

.phase-entry-tool-error .phase-entry-status,
.phase-entry-tool-error .phase-entry-label {
  color: rgba(180, 40, 40, 0.85);
}

.phase-entry-pending {
  display: inline-block;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: transparent;
  border: 1.5px solid var(--accent);
  box-sizing: border-box;
  opacity: 0.7;
  animation: phaseEntryPulse 1.2s ease-in-out infinite;
}

.phase-entry-done {
  display: inline-block;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--muted);
}

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

.phase-entry-label {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: 500;
}

.phase-entry-detail,
.phase-entry-result {
  margin: 4px 0 0 22px;
  padding: 6px 8px;
  background: rgba(0, 0, 0, 0.03);
  border-radius: 4px;
  font-size: 11px;
  font-family: "SF Mono", "Menlo", "Consolas", monospace;
  white-space: pre-wrap;
  color: var(--muted-strong);
}

.phase-entry-result {
  max-height: 140px;
  overflow-y: auto;
}

@media (prefers-color-scheme: dark) {
  .phase-entry-detail,
  .phase-entry-result {
    background: rgba(255, 255, 255, 0.04);
  }
}

/* ── Approval card (human-in-the-loop tool confirmation) ─────────────── */

.approval-card {
  margin: 12px 0;
  padding: 12px 14px;
  border: 1px solid var(--sandbox-border);
  border-radius: 8px;
  background: var(--sandbox-tint);
  display: flex;
  flex-direction: column;
  gap: 10px;
  font-size: 13px;
}

.approval-card-pending {
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--sandbox-accent) 12%, transparent);
}

.approval-card-approved,
.approval-card-rejected {
  opacity: 0.7;
}

.approval-card-header {
  display: flex;
  align-items: center;
  gap: 8px;
}

.approval-card-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--sandbox-accent);
  color: #fff;
  font-weight: 700;
  font-size: 11px;
  flex-shrink: 0;
}

.approval-card-title {
  font-weight: 600;
  color: var(--fg);
}

.approval-card-body {
  color: var(--fg);
}

.approval-card-summary {
  margin: 0;
  line-height: 1.4;
}

.approval-card-sheet-list {
  list-style: none;
  margin: 8px 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.approval-card-sheet {
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12px;
  color: var(--muted-strong);
}

.approval-card-sheet-dot {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--sandbox-accent);
  flex-shrink: 0;
}

.approval-card-actions {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding-top: 2px;
  border-top: 1px solid var(--sandbox-border);
}

.approval-card-always {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--muted-strong);
  cursor: pointer;
}

.approval-card-always input[type="checkbox"] {
  accent-color: var(--sandbox-accent);
  cursor: pointer;
}

.approval-card-target-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 8px;
}

.approval-card-target-label {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
}

.approval-card-target-chip {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11px;
  padding: 2px 6px;
  border-radius: 4px;
  background: rgba(var(--sandbox-accent-rgb), 0.12);
  color: var(--sandbox-accent);
  border: 1px solid var(--sandbox-border);
}

.approval-card-buttons {
  display: flex;
  gap: 8px;
  justify-content: flex-end;
}

.approval-card-preview {
  background: transparent;
  border-color: var(--sandbox-border);
  color: var(--sandbox-accent);
  margin-right: auto;
}

.approval-card-preview:hover {
  background: rgba(var(--sandbox-accent-rgb), 0.1);
}

.approval-card-button {
  padding: 6px 14px;
  border-radius: 6px;
  border: 1px solid transparent;
  font-family: inherit;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
}

.approval-card-reject {
  background: transparent;
  border-color: var(--border);
  color: var(--muted-strong);
}

.approval-card-reject:hover {
  background: var(--user-bg);
  color: var(--fg);
}

.approval-card-approve {
  background: var(--sandbox-accent);
  color: #fff;
}

.approval-card-approve:hover {
  filter: brightness(1.05);
}

.approval-card-resolved {
  font-size: 12px;
  color: var(--muted-strong);
  font-style: italic;
}

/* ── Plan widget (sticky above input) ─────────────────────────────────── */

#bottom-dock {
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  background: var(--bg);
  border-top: 1px solid var(--border);
  box-shadow: 0 -8px 16px -8px rgba(0, 0, 0, 0.06);
}

@media (prefers-color-scheme: dark) {
  #bottom-dock {
    box-shadow: 0 -8px 16px -8px rgba(0, 0, 0, 0.4);
  }
}

/* Plan UI v3 Hybrid — recreated from the design bundle exported via
   claude.ai/design (Plan UI v3 Hybrid.html / v3-hybrid.jsx). Tokens scoped
   to the widget so the rest of the app keeps its own palette. */
.plan-widget {
  --plan-ink: #1a1a17;
  --plan-muted: #8a8a82;
  --plan-muted-2: #b8b8b0;
  --plan-line: #e7e6df;
  --plan-line-2: #efeee7;
  --plan-accent: #2f5d4f;
  --plan-accent-soft: #e6efe9;
  position: relative;
  background: #ffffff;
  color: var(--plan-ink);
}

/* On first appearance, the widget grows upward from the bottom dock to its
   measured natural height. The component renders with inline `height: 0`
   first, measures `scrollHeight` next frame, then sets `height` to that
   pixel value — this transition carries it the rest of the way. After
   transition end, the inline height is dropped so subsequent content
   changes (status updates, resubmits) flow naturally without retriggering
   the entrance. Scoping the transition to the .plan-widget-entering class
   keeps height changes after entrance from re-animating. */
.plan-widget-entering {
  overflow: hidden;
  transition:
    height 720ms cubic-bezier(0.16, 0.84, 0.2, 1),
    opacity 720ms ease;
}

@media (prefers-color-scheme: dark) {
  .plan-widget {
    --plan-ink: rgba(255, 255, 255, 0.88);
    --plan-muted: rgba(255, 255, 255, 0.5);
    --plan-muted-2: rgba(255, 255, 255, 0.32);
    --plan-line: rgba(255, 255, 255, 0.12);
    --plan-line-2: rgba(255, 255, 255, 0.06);
    --plan-accent: #53d55e;
    --plan-accent-soft: rgba(83, 213, 94, 0.10);
    background: var(--bg);
  }
}

/* Progress meter — 2px line at top, fills (completed + 0.45 of active)/total. */
.plan-progress {
  height: 4px;
  width: 100%;
  background: var(--plan-line-2);
  position: relative;
  overflow: hidden;
}

.plan-progress-fill {
  position: absolute;
  inset: 0 auto 0 0;
  background: var(--plan-accent);
  /* Match the JS tick rate (500 ms) with linear easing so the
     asymptotic curve computed in planProgress comes through cleanly
     instead of being doubly-eased. */
  transition: width 500ms linear;
}

/* ───── Animated open/close wrapper ─────────────────────────────────── */
/* Both the collapsed and expanded views are always rendered; toggling the
   `plan-anim-open` class drives a smooth height transition via the
   grid 0fr/1fr trick (modern browsers interpolate between fr units). */
.plan-anim-wrap {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 300ms ease;
}

.plan-anim-wrap.plan-anim-open {
  grid-template-rows: 1fr;
}

.plan-anim-inner {
  overflow: hidden;
  min-height: 0;
}

/* ───── Collapsed row ───────────────────────────────────────────────── */

.plan-collapsed-row {
  width: 100%;
  /* Horizontal padding matches the input form's outer padding (6px) plus
     the input box's own padding-right (~14px) so the chevron's right edge
     lines up roughly with the send-button's right edge. */
  padding: 12px 18px 12px 14px;
  display: flex;
  align-items: center;
  gap: 11px;
  cursor: pointer;
  user-select: none;
  background: transparent;
  border: none;
  font-family: inherit;
  text-align: left;
  color: inherit;
}

.plan-collapsed-row:disabled {
  cursor: default;
}

.plan-collapsed-bullet {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.plan-collapsed-title {
  flex: 1;
  min-width: 0;
  font-size: 13px;
  font-weight: 400;
  color: var(--plan-ink);
  line-height: 1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ───── Expanded body ───────────────────────────────────────────────── */

.plan-expanded {
  /* No horizontal padding — the row's own margin handles edge alignment so
     the active step's green box lines up with the input box's edges. */
  padding: 0 0 8px;
}

.plan-expanded-meta {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: 10px;
  /* Padding-right matches the collapsed row so the chevron sits in the
     same horizontal position whether the widget is collapsed or expanded.
     Bottom padding gives the steps room to breathe below this header. */
  padding: 8px 18px 6px 0;
  cursor: pointer;
  user-select: none;
  background: transparent;
  border: none;
  width: 100%;
  font-family: inherit;
  color: inherit;
}

.plan-rows {
  list-style: none;
  margin: 0;
  padding: 0;
  max-height: 260px;
  overflow-y: auto;
}

.plan-row-item {
  list-style: none;
}

.plan-row {
  display: grid;
  grid-template-columns: 20px 1fr;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  /* 6px matches the input-form's outer padding so the active row's green
     overlay aligns horizontally with the input box's edges. */
  margin: 0 6px;
  border-radius: 8px;
  background: transparent;
  /* Smooth the active-state fade for subsequent step transitions (the
     first appearance is handled by the widget's entrance animation). */
  transition: background 220ms ease;
}

.plan-row-active {
  background: var(--plan-accent-soft);
}

.plan-row-bullet {
  height: 19px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.plan-row-body {
  min-width: 0;
}

.plan-row-title {
  font-size: 13px;
  font-weight: 400;
  color: var(--plan-ink);
  line-height: 1.3;
}

.plan-row-title-done {
  color: var(--plan-muted);
}

/* ───── Chevron ─────────────────────────────────────────────────────── */

.plan-chevron {
  color: var(--plan-muted);
  flex-shrink: 0;
  margin-left: 2px;
  transition: transform 200ms;
}

.plan-chevron-flipped {
  transform: rotate(180deg);
}

/* ───── Spinner (collapsed bullet, active step) ─────────────────────── */

.plan-spinner {
  flex-shrink: 0;
  animation: planV3Spin 1.4s linear infinite;
}

/* ───── Active dot pulse (expanded bullet, active step) ─────────────── */

.plan-active-dot {
  position: relative;
  display: inline-block;
  width: 10px;
  height: 10px;
}

.plan-active-dot-core {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: var(--plan-accent);
}

.plan-active-dot-ring {
  position: absolute;
  inset: -4px;
  border-radius: 50%;
  background: var(--plan-accent);
  opacity: 0.25;
  animation: planV3Pulse 1.6s ease-out infinite;
}

/* ───── Pending ring (expanded bullet, pending step) ────────────────── */

.plan-pending-ring {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  border: 1.5px solid var(--plan-muted-2);
  display: block;
}

.plan-done-check {
  display: block;
}

/* ───── Activity sub-line ───────────────────────────────────────────── */

.plan-activity-line {
  margin-top: 4px;
  font-size: 12px;
  color: var(--plan-accent);
  display: flex;
  align-items: center;
  min-width: 0;
}

.plan-activity-text {
  animation: planV3Fade 400ms ease;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}

/* ───── Animations ──────────────────────────────────────────────────── */

@keyframes planV3Spin {
  to { transform: rotate(360deg); }
}

@keyframes planV3Pulse {
  0% { transform: scale(0.6); opacity: 0.5; }
  100% { transform: scale(1.7); opacity: 0; }
}

@keyframes planV3Fade {
  from { opacity: 0; transform: translateY(2px); }
  to { opacity: 1; transform: none; }
}

/* Input area */

#input-form {
  padding: 6px 6px;
  background: var(--bg);
  flex-shrink: 0;
}

/* When the plan widget sits directly above the input, the widget's bottom
   padding already provides the gap to the input box. Stack the form's own
   top padding on top of that and the gap below the plan row reads ~6px
   larger than the gap above it. Zero out the form's top padding here so
   the row's 12px above and below match. */
.plan-widget + #input-form {
  padding-top: 0;
}

#input-wrapper {
  position: relative;
}

#input {
  width: 100%;
  padding: 12px 52px 12px 14px;
  border: 1px solid var(--border);
  border-radius: 8px;
  font-family: inherit;
  color: var(--fg);
  background: var(--input-bg);
  resize: none;
  max-height: 200px;
  line-height: 1.4;
  outline: none;
  display: block;
}

#input::placeholder {
  color: var(--muted);
}

#input:focus {
  border-color: var(--border);
}

#send-btn {
  position: absolute;
  right: 8px;
  bottom: 8px;
  width: 30px;
  height: 30px;
  border: none;
  border-radius: 4px;
  background: var(--accent);
  color: #ffffff;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition:
    opacity 0.3s,
    transform 0.15s ease;
}

#send-btn:hover:not(:disabled) {
  opacity: 0.85;
}

#send-btn:active:not(:disabled) {
  transform: scale(0.88);
}

#send-btn:disabled {
  opacity: 0.25;
  cursor: default;
}

/* Debug panel (toggle with Ctrl+Shift+D) */

#debug-panel {
  flex-shrink: 0;
}

#debug-log {
  display: none;
  max-height: 180px;
  overflow-y: auto;
  padding: 6px 10px;
  border-top: 1px solid var(--border);
  background: var(--debug-bg);
  color: var(--debug-fg);
  font-family: "SF Mono", "Menlo", "Consolas", monospace;
  font-size: 10px;
  line-height: 1.6;
  white-space: pre-wrap;
  word-wrap: break-word;
}

#debug-log.visible {
  display: block;
}

.debug-line {
  user-select: text;
  -webkit-user-select: text;
}

.debug-info {
  color: var(--debug-info);
}

.debug-success {
  color: var(--debug-success);
}

.debug-warn {
  color: var(--debug-warn);
}

.debug-error {
  color: var(--debug-error);
}

/* ── API Key Setup ─────────────────────────────────────────────────────── */

#api-key-setup {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px 16px;
}

#api-key-setup form {
  display: flex;
  flex-direction: column;
  gap: 12px;
  width: 100%;
  max-width: 320px;
}

#api-key-setup label {
  font-size: 13px;
  font-weight: 500;
  color: var(--muted-strong);
}

#api-key-setup select,
#api-key-setup input {
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 8px;
  font-family: inherit;
  font-size: 14px;
  color: var(--fg);
  background: var(--input-bg);
  outline: none;
  width: 100%;
}

#api-key-setup select:focus,
#api-key-setup input:focus {
  border-color: var(--border);
}

#api-key-setup button {
  padding: 10px 16px;
  border: none;
  border-radius: 8px;
  background: var(--accent);
  color: #ffffff;
  font-family: inherit;
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  transition: opacity 0.2s;
  align-self: flex-end;
}

#api-key-setup button:hover:not(:disabled) {
  opacity: 0.85;
}

#api-key-setup button:disabled {
  opacity: 0.25;
  cursor: default;
}

/* ── Settings Modal ────────────────────────────────────────────────────── */

#settings-modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.4);
  display: flex;
  align-items: flex-end;
  justify-content: center;
  z-index: 100;
  animation: fadeIn 0.2s ease-out;
}

#settings-modal {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 12px 12px 0 0;
  padding: 0;
  width: 100%;
  box-shadow: 0 -4px 24px rgba(0, 0, 0, 0.15);
  animation: slideUp 0.25s cubic-bezier(0.16, 1, 0.3, 1);
}

@keyframes slideUp {
  from { transform: translateY(100%); }
  to { transform: translateY(0); }
}

.settings-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 20px 12px;
  border-bottom: 1px solid var(--border);
}

.settings-header h2 {
  font-size: 15px;
  font-weight: 600;
  color: var(--fg);
  margin: 0;
}

.settings-close {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border: none;
  border-radius: 6px;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
  transition: color 0.2s, background 0.2s;
}

.settings-close:hover {
  color: var(--fg);
  background: var(--user-bg);
}

#settings-modal form {
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding: 20px;
}

.settings-field {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.settings-field label {
  font-size: 12px;
  font-weight: 500;
  color: var(--muted-strong);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

#settings-modal select,
#settings-modal input {
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 6px;
  font-family: inherit;
  font-size: 13px;
  color: var(--fg);
  background: var(--input-bg);
  outline: none;
  width: 100%;
  appearance: none;
  -webkit-appearance: none;
}

#settings-modal select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%236b7280' stroke-width='2'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
  padding-right: 32px;
  cursor: pointer;
}

#settings-modal select:focus,
#settings-modal input:focus {
  border-color: var(--muted);
}

.settings-actions {
  display: flex;
  gap: 8px;
  justify-content: flex-end;
  padding-top: 4px;
}

.settings-actions button[type="button"] {
  padding: 8px 16px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: transparent;
  color: var(--fg);
  font-family: inherit;
  font-size: 13px;
  cursor: pointer;
  transition: background 0.2s;
}

.settings-actions button[type="button"]:hover {
  background: var(--user-bg);
}

.settings-actions button[type="submit"] {
  padding: 8px 20px;
  border: none;
  border-radius: 6px;
  background: var(--accent);
  color: #ffffff;
  font-family: inherit;
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  transition: opacity 0.2s;
}

.settings-actions button[type="submit"]:hover:not(:disabled) {
  opacity: 0.85;
}

.settings-actions button[type="submit"]:disabled {
  opacity: 0.25;
  cursor: default;
}

/* ── Settings button (cogwheel in top overlay) ─────────────────────────── */

#settings-btn {
  pointer-events: all;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  padding: 0;
  border: none;
  border-radius: 6px;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
  transition: color 0.3s, opacity 0.2s;
  position: relative;
  margin-left: 2px;
}

#settings-btn:hover {
  color: var(--fg);
  background: var(--user-bg);
}

#settings-btn::after {
  content: "Settings";
  position: absolute;
  top: 50%;
  right: calc(100% + 8px);
  transform: translateY(-50%);
  background: #1f1f1f;
  color: #fff;
  font-size: 11px;
  font-weight: 400;
  white-space: nowrap;
  padding: 8px 12px;
  border-radius: 6px;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.3s;
  z-index: 20;
}

#settings-btn:hover::after {
  opacity: 1;
}

/* ── Sandbox preview panel (between chat and plan widget) ──────────────── */

.sandbox-preview {
  display: flex;
  flex-direction: column;
  border-bottom: 1px solid var(--border);
  background: var(--bg);
  /* Mondrian renders to canvas at the workbook's native cell sizes — there
     is no zoom prop. The only way to show more rows/cols is more pixels.
     Default reserves ~420px; the drag handle on top lets users grow or
     shrink it, persisted in localStorage. */
  height: 420px;
  min-height: 200px;
  max-height: 75vh;
  overflow: hidden;
}

.sandbox-preview-drag-handle {
  flex-shrink: 0;
  height: 6px;
  background: transparent;
  cursor: ns-resize;
  position: relative;
  touch-action: none;
}

/* Inner pill for hit-target visibility — full bar would overpower the
   panel's chrome, so we render a centered grab indicator that grows on
   hover. */
.sandbox-preview-drag-handle::before {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 32px;
  height: 3px;
  background: var(--border);
  border-radius: 2px;
  transform: translate(-50%, -50%);
  transition: background 0.15s, width 0.15s;
}

.sandbox-preview-drag-handle:hover::before {
  background: var(--muted);
  width: 56px;
}

.sandbox-preview-drag-handle.is-dragging::before {
  background: var(--accent);
  width: 64px;
}

.sandbox-preview-header {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 12px;
  border-bottom: 1px solid var(--border);
  font-size: 12px;
  line-height: 1.3;
}

.sandbox-preview-title {
  color: var(--muted-strong);
  font-weight: 500;
  flex-shrink: 0;
}

.sandbox-preview-description {
  color: var(--fg);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
  flex: 1;
}

.sandbox-preview-popout {
  flex-shrink: 0;
  margin-left: auto;
  background: transparent;
  border: none;
  padding: 2px 6px;
  font-size: 14px;
  line-height: 1;
  color: var(--muted-strong);
  cursor: pointer;
  border-radius: 4px;
  transition: background 0.15s, color 0.15s;
}

.sandbox-preview-popout:hover {
  background: var(--user-bg);
  color: var(--fg);
}

/* "Writing code…" indicator visible while tool input is streaming. */
.sandbox-preview-writing {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--fg);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
  flex: 1;
}

.sandbox-preview-writing-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent);
  flex-shrink: 0;
  animation: sandbox-preview-writing-pulse 1s ease-in-out infinite;
}

@keyframes sandbox-preview-writing-pulse {
  0%, 100% { opacity: 0.4; transform: scale(0.85); }
  50%      { opacity: 1; transform: scale(1.1); }
}

.sandbox-preview-writing-count {
  flex-shrink: 0;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  font-size: 11px;
  margin-left: auto;
}

/* ── Approval preview dialog (sidebar + stacked viewers) ─────────────── */

.preview-dialog {
  display: flex;
  flex-direction: row;
  height: 100vh;
  background: var(--bg);
  color: var(--fg);
  font-family: inherit;
}

.preview-sidebar {
  flex-shrink: 0;
  width: 360px;
  display: flex;
  flex-direction: column;
  gap: 24px;
  padding: 28px 24px;
  border-left: 1px solid var(--border);
  background: var(--user-bg);
  overflow-y: auto;
}

/* Fullscreen toggle in the top-right of the sidebar. Subtle ghost
   button — visible enough to be discovered, quiet enough not to
   compete with the action stack at the bottom. */
.preview-sidebar {
  position: relative;
}

.preview-sidebar-fullscreen {
  position: absolute;
  top: 14px;
  right: 14px;
  width: 30px;
  height: 30px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 6px;
  color: var(--muted-strong);
  cursor: pointer;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
}

.preview-sidebar-fullscreen:hover {
  background: var(--bg);
  border-color: var(--border);
  color: var(--fg);
}

/* Chat-style message — author byline above (avatar + name + meta),
 * the suggestion as prominent body text, a quiet meta line below.
 * The viewers carry the "what changes" visually; this carries the
 * "what is this and why". */
.preview-sidebar-message {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.preview-sidebar-author {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
}

.preview-sidebar-avatar {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--accent);
  flex-shrink: 0;
  box-shadow: 0 1px 2px rgba(var(--accent-rgb), 0.25),
    inset 0 1px 0 rgba(255, 255, 255, 0.2);
}

.preview-sidebar-author-name {
  font-weight: 600;
  color: var(--fg);
}

.preview-sidebar-author-meta {
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}

.preview-sidebar-description {
  margin: 0;
  font-size: 17px;
  line-height: 1.45;
  color: var(--fg);
  font-weight: 500;
  letter-spacing: -0.005em;
}

.preview-sidebar-meta {
  margin: 0;
  font-size: 12.5px;
  color: var(--muted);
}

/* "Pulls from" chips. Surface the existing-workbook sheets the new
   sheet pulls from via cross-sheet references so the user can see at
   a glance what the inserted sheet depends on. */
.preview-sidebar-references {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.preview-sidebar-references-label {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted-strong);
}

.preview-sidebar-references-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.preview-sidebar-chip {
  padding: 3px 9px;
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.05);
  border: 1px solid var(--border);
  font-size: 12px;
  color: var(--fg);
}

.preview-sidebar-actions {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.preview-action {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 13px 18px;
  border-radius: 10px;
  border: 1px solid transparent;
  font-family: inherit;
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  text-align: left;
  transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease,
    box-shadow 0.15s ease, transform 0.05s ease, opacity 0.15s ease;
}

.preview-action:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.preview-action:not(:disabled):active {
  transform: translateY(1px);
}

.preview-action-icon {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  font-size: 12px;
  opacity: 0.9;
}

.preview-action-approve {
  background: var(--accent);
  color: #fff;
  font-weight: 600;
  border-color: var(--accent);
  box-shadow: 0 1px 2px rgba(var(--accent-rgb), 0.25),
    inset 0 1px 0 rgba(255, 255, 255, 0.12);
}

.preview-action-approve:hover:not(:disabled) {
  filter: brightness(1.06);
  box-shadow: 0 2px 6px rgba(var(--accent-rgb), 0.3),
    inset 0 1px 0 rgba(255, 255, 255, 0.12);
}

.preview-action-auto {
  background: var(--bg);
  color: var(--fg);
  border-color: var(--border);
}

.preview-action-auto:hover:not(:disabled) {
  background: var(--bg);
  border-color: var(--muted);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04);
}

.preview-action-suggest {
  background: transparent;
  color: var(--fg);
  border-color: var(--border);
  font-weight: 500;
}

.preview-action-suggest:hover:not(:disabled) {
  background: var(--bg);
  border-color: var(--muted);
}

/* Mirrors the task-pane chat input (#input + #send-btn) so the
   suggestion box doesn't look like its own thing. The Send button is
   positioned inside the wrapper, bottom-right. */
.preview-suggestion-wrapper {
  position: relative;
}

.preview-suggestion-input {
  width: 100%;
  padding: 12px 52px 12px 14px;
  border: 1px solid var(--border);
  border-radius: 8px;
  font-family: inherit;
  font-size: 14px;
  line-height: 1.4;
  color: var(--fg);
  background: var(--input-bg);
  resize: none;
  max-height: 200px;
  outline: none;
  display: block;
}

.preview-suggestion-input::placeholder {
  color: var(--muted);
}

.preview-suggestion-input:focus {
  border-color: var(--border);
}

.preview-suggestion-send {
  position: absolute;
  right: 8px;
  bottom: 8px;
  width: 30px;
  height: 30px;
  border: none;
  border-radius: 4px;
  background: var(--accent);
  color: #ffffff;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: opacity 0.3s, transform 0.15s ease;
}

.preview-suggestion-send:hover:not(:disabled) {
  opacity: 0.85;
}

.preview-suggestion-send:active:not(:disabled) {
  transform: scale(0.88);
}

.preview-suggestion-send:disabled {
  opacity: 0.25;
  cursor: default;
}

.preview-dialog-placeholder {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  color: var(--muted);
  font-size: 13px;
  font-style: italic;
  padding: 0 24px;
  text-align: center;
}

/* ── Right side: stacked viewers ─────────────────────────────────────── */

.preview-stack {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  padding: 24px 24px;
  gap: 16px;
  background: var(--bg);
}

.preview-pane {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
  background: var(--bg);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.03);
}

.preview-pane-header {
  flex-shrink: 0;
  display: flex;
  align-items: baseline;
  gap: 12px;
  padding: 12px 18px;
  background: var(--user-bg);
  border-bottom: 1px solid var(--border);
}

.preview-pane-before .preview-pane-header {
  background: rgba(0, 0, 0, 0.04);
  border-bottom-color: var(--border);
}

.preview-pane-after {
  border-color: rgba(var(--accent-rgb), 0.35);
}

.preview-pane-after .preview-pane-header {
  background: rgba(var(--accent-rgb), 0.08);
  border-bottom-color: rgba(var(--accent-rgb), 0.3);
}

.preview-pane-label {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted-strong);
}

.preview-pane-before .preview-pane-label {
  color: var(--muted-strong);
}

.preview-pane-after .preview-pane-label {
  color: var(--accent);
}

/* Single-pane variant for the "insert new sheet" mode. There is no
   meaningful "before" for an inserted sheet, so we drop the
   before/divider/after stack and let one pane fill the column. */
.preview-stack-single .preview-pane {
  flex: 1;
}

.preview-pane-new-sheet {
  border-color: rgba(var(--accent-rgb), 0.35);
}

.preview-pane-new-sheet .preview-pane-header {
  background: rgba(var(--accent-rgb), 0.08);
  border-bottom-color: rgba(var(--accent-rgb), 0.3);
}

.preview-pane-new-sheet .preview-pane-label {
  color: var(--accent);
}

.preview-pane-hint {
  font-size: 12px;
  color: var(--muted);
  font-style: italic;
}

.preview-pane-viewer {
  flex: 1;
  min-height: 0;
  position: relative;
  overflow: hidden;
}

/* Each pane's SpreadsheetViewer lives inside its own iframe so the
   mondrian-react global theme lookup is scoped per-pane. The iframe
   fills the pane viewer area; the inner page sets its own
   transparent body so the chrome around it stays visible. */
.preview-pane-frame {
  width: 100%;
  height: 100%;
  border: none;
  display: block;
  background: transparent;
}

/* Standalone styles for /preview-viewer.html (single SpreadsheetViewer). */
#preview-viewer-root {
  position: absolute;
  inset: 0;
}

.preview-viewer {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  background: var(--bg);
}

.preview-viewer-placeholder {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--muted);
  font-size: 13px;
  font-style: italic;
}

.preview-stack-divider {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 4px 0;
  background: transparent;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted-strong);
}

.preview-stack-arrow {
  color: var(--accent);
  font-size: 16px;
}

/* ── Sandbox preview dialog (pop-out window) ─────────────────────────── */

/* Diagonal hatched stripe at the top of the dialog — a
   construction-tape cue that this is a scratch / not-yet-committed
   space. Deliberately subtle (3px tall, low contrast) so it reads as
   chrome, not noise. Scoped to the popout dialog only; the in-pane
   preview keeps the plain task-pane chrome. The stripes drift sideways
   on a slow loop so the bar reads as live progress. */
.sandbox-dialog::before {
  content: '';
  flex-shrink: 0;
  height: 3px;
  background: repeating-linear-gradient(
    -45deg,
    var(--sandbox-accent) 0 8px,
    color-mix(in srgb, var(--sandbox-accent) 35%, transparent) 8px 14px
  );
  animation: sandbox-dialog-stripe-slide 1.4s linear infinite;
}

/* The stripes are at -45deg with a 14px period along the gradient
   direction. A horizontal-only shift of 14px / cos(45°) ≈ 19.8px is
   the visually seamless loop distance. */
@keyframes sandbox-dialog-stripe-slide {
  from { background-position-x: 0; }
  to   { background-position-x: 19.8px; }
}

/* "UNCOMMITTED" badge that sits next to the title in both the dialog
   and the in-pane preview headers. Calls out the sandbox state in
   plain text so the cue isn't carried by color alone. */
.sandbox-uncommitted-pill {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  padding: 2px 7px;
  border: 1px solid var(--sandbox-border);
  border-radius: 4px;
  background: var(--sandbox-tint);
  color: var(--sandbox-accent);
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.sandbox-dialog {
  display: flex;
  flex-direction: column;
  height: 100vh;
  background: var(--bg);
  color: var(--fg);
  font-family: inherit;
}

.sandbox-dialog-header {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 10px 16px;
  border-bottom: 1px solid var(--border);
  font-size: 13px;
}

.sandbox-dialog-title {
  color: var(--muted-strong);
  font-weight: 500;
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

/* Status pulse dot. Idle: dim and breathing slowly so the user sees the
   dialog is "live" but quiet. Fresh: bright accent green, pulsing
   energetically — visible cue that an update just landed. We rely on
   React swapping the className to crossfade between the two animations. */
.sandbox-dialog-status {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--muted);
  transition: background 0.4s, box-shadow 0.4s;
}

.sandbox-dialog-status.is-idle {
  background: var(--muted);
  animation: sandbox-dialog-status-idle 2.4s ease-in-out infinite;
}

.sandbox-dialog-status.is-fresh {
  background: var(--sandbox-accent);
  animation: sandbox-dialog-status-fresh 1.2s ease-in-out infinite;
}

@keyframes sandbox-dialog-status-idle {
  0%, 100% { opacity: 0.55; box-shadow: 0 0 0 0 transparent; }
  50%      { opacity: 0.85; box-shadow: 0 0 0 0 transparent; }
}

@keyframes sandbox-dialog-status-fresh {
  0%   { box-shadow: 0 0 0 0 rgba(var(--sandbox-accent-rgb), 0.45); transform: scale(1); }
  60%  { box-shadow: 0 0 0 8px rgba(var(--sandbox-accent-rgb), 0); transform: scale(1.15); }
  100% { box-shadow: 0 0 0 0 transparent; transform: scale(1); }
}

/* Current action — slides in fresh on each update via the keyed wrapper. */
/* Pushes timestamp + action count to the right edge of the header. */
.sandbox-dialog-header-spacer {
  flex: 1;
}

.sandbox-dialog-timestamp {
  flex-shrink: 0;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  font-size: 12px;
}

/* Counter pill that pings on every increment via key-based re-mount. */
.sandbox-dialog-action-count {
  flex-shrink: 0;
  display: inline-flex;
  align-items: baseline;
  gap: 2px;
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--user-bg);
  color: var(--muted-strong);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  animation: sandbox-dialog-count-pop 0.45s cubic-bezier(0.2, 1.4, 0.3, 1);
}

.sandbox-dialog-action-count-label {
  font-size: 11px;
  color: var(--muted);
}

@keyframes sandbox-dialog-count-pop {
  0%   { transform: scale(0.85); }
  60%  { transform: scale(1.12); }
  100% { transform: scale(1); }
}

/* Body splits into a left timeline sidebar and the main viewer. The
   sidebar only renders once history exists or a writing snapshot is in
   flight; before that the viewer fills the dialog. */
.sandbox-dialog-body {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: row;
}

.sandbox-dialog-timeline {
  flex-shrink: 0;
  width: 240px;
  border-right: 1px solid var(--border);
  background: var(--user-bg);
  overflow-y: auto;
  padding: 12px 0 16px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.sandbox-dialog-timeline-heading {
  margin: 0;
  padding: 0 16px;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
}

/* Timeline entries: vertical list with a left rail. Most recent at top,
   highlighted as "current"; older entries dim progressively. */
.sandbox-dialog-history {
  flex-shrink: 0;
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  font-size: 12px;
}

.sandbox-dialog-history-item {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 8px 16px;
  color: var(--muted-strong);
  animation: sandbox-dialog-history-in 0.4s ease-out;
}

.sandbox-dialog-history-item.is-current {
  color: var(--fg);
  font-weight: 500;
}

.sandbox-dialog-history-item:not(.is-current):nth-child(2) { opacity: 0.85; }
.sandbox-dialog-history-item:not(.is-current):nth-child(3) { opacity: 0.7; }
.sandbox-dialog-history-item:not(.is-current):nth-child(4) { opacity: 0.55; }
.sandbox-dialog-history-item:not(.is-current):nth-child(n+5) { opacity: 0.45; }

@keyframes sandbox-dialog-history-in {
  from { opacity: 0; transform: translateY(-2px); }
  to   { opacity: var(--end-opacity, 1); transform: translateY(0); }
}

.sandbox-dialog-history-marker {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--muted);
  flex-shrink: 0;
  margin-top: 6px;
}

.sandbox-dialog-history-item.is-current .sandbox-dialog-history-marker {
  background: var(--sandbox-accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--sandbox-accent) 18%, transparent);
}

.sandbox-dialog-history-body {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.sandbox-dialog-history-desc {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.sandbox-dialog-history-target {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 10.5px;
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.sandbox-dialog-history-time {
  flex-shrink: 0;
  font-variant-numeric: tabular-nums;
  color: var(--muted);
  font-size: 11px;
  margin-top: 1px;
}

.sandbox-dialog-viewer {
  flex: 1;
  min-width: 0;
  min-height: 0;
  position: relative;
  overflow: hidden;
}

.sandbox-dialog-placeholder {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  color: var(--muted);
  font-size: 14px;
  font-style: italic;
}

.sandbox-preview-viewer {
  flex: 1;
  min-height: 0;
  position: relative;
  overflow: hidden;
}

/* Wrapper for the iframe-scaled viewer. Clips the over-sized iframe so
   the user only sees the scaled-down result. */
.sandbox-preview-scaled-frame {
  position: relative;
  overflow: hidden;
  width: 100%;
  height: 100%;
}

/* The iframe itself is sized at 1/scale of the wrapper, then visually
   shrunk via transform. transform-origin must be top-left so the
   scaled-down iframe lands flush with the wrapper's top-left corner. */
.sandbox-preview-scaled-iframe {
  border: 0;
  background: transparent;
  display: block;
  transform-origin: top left;
}

.sandbox-preview-placeholder {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--muted);
  font-size: 13px;
  font-style: italic;
}
*{box-sizing:border-box}body{margin:0;font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}._tabsWrapper_nzg1j_24{flex:1;position:relative;min-width:0}._tabsContainer_nzg1j_30{display:flex;overflow-x:auto;overflow-y:hidden;white-space:nowrap;height:100%;padding-right:24px;scrollbar-width:none;-ms-overflow-style:none}._tabsContainer_nzg1j_30::-webkit-scrollbar{display:none}._tab_nzg1j_24{padding:6px 16px;font-size:12px;cursor:pointer;background-color:var(--mondrian-bg-gray-100);color:var(--mondrian-text-gray-500);border:1px solid var(--mondrian-border-primary);border-top:0;border-bottom-left-radius:var(--mondrian-border-radius-sm);border-bottom-right-radius:var(--mondrian-border-radius-sm);margin-right:4px;flex-shrink:0}._tab_nzg1j_24:hover{background-color:var(--mondrian-bg-gray-200);color:var(--mondrian-text-black)}._active_nzg1j_62{background-color:var(--mondrian-bg-white);color:var(--mondrian-text-black)}._active_nzg1j_62:hover{background-color:var(--mondrian-bg-white)}._scrollOverlay_nzg1j_70{position:absolute;top:0;right:0;bottom:0;width:40px;background:linear-gradient(to right,transparent 0%,var(--mondrian-bg-gray-100) 100%);pointer-events:none;z-index:1}._container_1nw0m_24{background:var(--mondrian-bg-white);border:1px solid var(--mondrian-border-primary);border-top:0;border-bottom-left-radius:var(--mondrian-border-radius-sm);border-bottom-right-radius:var(--mondrian-border-radius-sm);padding:6px 12px;font-size:12px;display:flex;gap:8px;white-space:nowrap;align-items:center;margin-right:6px;position:relative;flex-shrink:0;margin-left:32px}._stat_1nw0m_42{display:flex;gap:4px;align-items:center}._label_1nw0m_48{color:var(--mondrian-text-gray-500);font-weight:500}._value_1nw0m_53{color:var(--mondrian-text-gray-700);font-weight:600;font-variant-numeric:tabular-nums}._dropdownContainer_1nw0m_59{position:relative}._dropdownTrigger_1nw0m_63{display:flex;align-items:center;gap:6px;background:none;border:none;cursor:pointer;padding:0;font-size:12px;color:var(--mondrian-text-gray-700);font-weight:500}._dropdownTrigger_1nw0m_63:hover{color:var(--mondrian-text-black)}._dropdownArrow_1nw0m_79{transition:transform .2s ease;color:var(--mondrian-text-gray-500)}._dropdownArrow_1nw0m_79._open_1nw0m_83{transform:rotate(180deg)}._dropdown_1nw0m_59{position:absolute;bottom:100%;right:0;margin-bottom:4px;background:var(--mondrian-bg-white);border:1px solid var(--mondrian-border-primary);border-radius:var(--mondrian-border-radius-sm);box-shadow:0 4px 6px -1px #0000001a,0 2px 4px -1px #0000000f;z-index:1000;min-width:max-content;max-width:200px;padding:6px 0}._dropdownItem_1nw0m_102{display:flex;justify-content:space-between;align-items:center;padding:6px 12px;font-size:12px;cursor:pointer;white-space:nowrap;gap:12px}._dropdownItem_1nw0m_102:hover{background-color:var(--mondrian-bg-gray-100)}._dropdownItem_1nw0m_102._selected_1nw0m_115{background-color:var(--mondrian-bg-gray-200);font-weight:600}._dropdownItem_1nw0m_102 ._label_1nw0m_48{flex-shrink:0}._dropdownItem_1nw0m_102 ._value_1nw0m_53{text-align:right;flex-shrink:0}._tooltip_zir2t_24{position:relative;background:var(--mondrian-bg-white);border-radius:var(--mondrian-border-radius-sm);box-shadow:0 4px 12px #00000026;max-width:200px;z-index:10000;padding-left:8px}._tooltip_zir2t_24:after{content:"";position:absolute;top:0;left:0;width:4px;height:100%;background:var(--mondrian-error-red)}._errorHeader_zir2t_43{color:var(--mondrian-error-red);font-weight:600;font-size:13px;padding:8px}._errorMessage_zir2t_50{color:var(--mondrian-text-gray-700);font-size:13px;line-height:1.4;padding:0 8px 8px}._errorOrigin_zir2t_58{color:var(--mondrian-text-gray-600);font-size:12px;line-height:1.4;padding:0 8px 8px}._errorOriginRef_zir2t_66{font-family:monospace}._errorOriginClickable_zir2t_70{cursor:pointer;text-decoration:underline;color:var(--mondrian-syntax-range)}._errorOriginClickable_zir2t_70:hover{color:var(--mondrian-highlight-stroke)}._container_1577i_24{position:absolute;inset:0;cursor:cell;outline:none}._contextMenu_1577i_31{background:var(--mondrian-bg-white);border:1px solid var(--mondrian-border-separator);border-radius:var(--mondrian-border-radius-sm);box-shadow:0 2px 8px #00000026;min-width:80px}._contextMenuItem_1577i_39{display:block;width:100%;padding:8px 12px;border:none;background:none;text-align:left;cursor:pointer;font-size:14px;color:var(--mondrian-text-gray-700)}._contextMenuItem_1577i_39:hover{background:var(--mondrian-bg-gray-100)}._canvas_wynlw_1{position:absolute;top:0;left:0;display:block;z-index:2}._formulaBar_iqwvf_24{font-family:monospace;line-height:24px;font-size:12px;width:100%;padding:0;display:flex;align-items:center;border-radius:var(--mondrian-border-radius) var(--mondrian-border-radius) 0 0;background-color:var(--mondrian-bg-white);border-bottom:1px solid #d8d9e5;height:32px}._formulaBar_iqwvf_24>*{padding:0 8px}._prefix_iqwvf_41{color:var(--mondrian-text-gray-400);width:12px;font-family:serif;font-style:italic;position:relative}._cell_iqwvf_49{color:var(--mondrian-text-gray-400);min-width:60px;text-align:center;position:relative;white-space:nowrap;padding:0 12px}._cell_iqwvf_49:after{content:"";position:absolute;left:0;top:4px;bottom:4px;border-left:1px solid var(--mondrian-border-separator)}._formula_iqwvf_24{flex-basis:100%;height:24px;display:flex;align-items:center;overflow-x:auto;white-space:nowrap;flex-grow:1}._fxToken_iqwvf_76{font-family:inherit;white-space:pre}._fxPrefix_iqwvf_81{color:var(--mondrian-syntax-prefix)}._fxRange_iqwvf_85,._fxRangeBeam_iqwvf_86{color:var(--mondrian-syntax-range)}._fxNumber_iqwvf_90,._fxBool_iqwvf_91{color:var(--mondrian-syntax-number)}._fxString_iqwvf_95{color:var(--mondrian-syntax-string)}._container_1hxqd_24{border:1px solid var(--mondrian-border-primary);border-radius:var(--mondrian-border-radius);color:var(--mondrian-text-gray-700);width:100%;height:100%;overflow:hidden}._canvasWrapper_1hxqd_33{position:relative}._viewport_1hxqd_37{position:absolute;inset:0;overflow:auto;z-index:1}._sheetSizer_1hxqd_44{pointer-events:none;visibility:hidden}._interactionLayer_1hxqd_49{position:relative;inset:0;z-index:3}._bottomBar_1hxqd_55{display:flex;background-color:var(--mondrian-bg-gray-100);padding-left:6px;padding-bottom:6px;border-top:1px solid var(--mondrian-border-primary);gap:8px;z-index:1000;height:40px}:root{--mondrian-border-primary: #d1d5db;--mondrian-border-separator: #ccc;--mondrian-bg-white: #ffffff;--mondrian-bg-gray-100: #f3f4f6;--mondrian-bg-gray-200: #e5e7eb;--mondrian-text-black: #000000;--mondrian-text-gray-400: #888;--mondrian-text-gray-500: #6b7280;--mondrian-text-gray-700: #374151;--mondrian-syntax-prefix: #aaa;--mondrian-syntax-range: #f7981d;--mondrian-syntax-number: #1155cc;--mondrian-syntax-string: #1a7f37;--mondrian-highlight-stroke: #217346;--mondrian-highlight-fill: #c6efce;--mondrian-error-red: #dc2626;--mondrian-border-radius: 8px;--mondrian-border-radius-sm: 4px;--mondrian-hover-overlay: rgba(0, 0, 0, .1);--mondrian-resizer-hover: rgba(0, 0, 0, .1)}._resizer_1biod_24{position:absolute;top:0;left:0;pointer-events:none;z-index:4}._col_1biod_32,._row_1biod_33{position:absolute;pointer-events:auto;background:transparent;transition:background .1s ease}._col_1biod_32:hover,._row_1biod_33:hover{background:var(--mondrian-resizer-hover)}._col_1biod_32{width:8px;margin-left:-4px;cursor:ew-resize;top:0}._row_1biod_33{height:8px;margin-top:-4px;cursor:ns-resize;left:0}._dragging_1biod_58 ._col_1biod_32,._dragging_1biod_58 ._row_1biod_33{opacity:0;pointer-events:none}._dragIndicatorRow_1biod_64,._dragIndicatorColumn_1biod_64{position:absolute;background-color:var(--mondrian-resizer-hover);pointer-events:none;z-index:5}._dragIndicatorColumn_1biod_64{top:0;width:4px;margin-left:-2px}._dragIndicatorRow_1biod_64{left:0;height:4px;margin-top:-2px}
