
/* /src/shared/design-system/tokens.css */
/* Cozero design system — canonical tokens + utility classes for the Control app.
   Ported from control-module/apps/web/src/styles/tokens.css (OKLCH navy
   #272C5F primary, finance indigo accent, AI green, Inter-first font stack). This file is the
   single source of styling; it is imported directly in __root.tsx. */

:root {
  /* Core */
  --background: 96.5% 0.004 286; /* #F4F4F6 */
  --white: 100% 0 0;
  --white-foreground: 27% 0.085 269; /* #272C5F */

  --primary: 27% 0.085 269; /* navy #272C5F */
  --primary-foreground: 100% 0 0;
  --primary-active: 27% 0.085 269;

  --secondary: 64% 0.04 276; /* #888BAA */
  --secondary-foreground: 100% 0 0;

  --accent: 44% 0.05 269; /* #4F5484 */
  --accent-foreground: 100% 0 0;

  --muted-bg: 91% 0.01 276; /* #E0E2EB */
  --muted: 37% 0.025 275; /* #46475C */
  --muted-2: 55% 0.025 275; /* lighter muted text */

  --input: 91% 0.01 276;
  --ring: 44% 0.05 269;
  --radius: 0.625rem;

  /* Sidebar (uses primary navy in this build) */
  --sidebar-background: 27% 0.085 269;
  --sidebar-foreground: 100% 0 0;
  --sidebar-accent: 44% 0.05 269;

  /* AI green #5CC63C */
  --ai: 70% 0.19 138;
  --ai-foreground: 100% 0 0;

  /* Action blue #2871FF */
  --action: 55% 0.22 258;
  --action-foreground: 100% 0 0;

  /* Brand green #28A003 */
  --brand: 56% 0.17 142;
  --brand-foreground: 100% 0 0;

  /* Scope colors */
  --scope-1: 62% 0.13 285; /* purple */
  --scope-2: 55% 0.09 148; /* sage */
  --scope-3: 61% 0.12 66; /* amber */

  /* Semantic */
  --green-bg: 91% 0.03 140;
  --green: 53% 0.17 141;
  --orange-bg: 94% 0.04 70;
  --orange: 71% 0.16 60;
  --error-bg: 90% 0.03 20;
  --error: 59% 0.2 26;

  /* CONTROL-specific finance accent (deep indigo with warmth) */
  --finance: 38% 0.1 270;
  --finance-soft: 95% 0.015 270;

  /* Tables */
  --table-header: 64% 0.04 276;
  --table-row-hover: 96.77% 0.0027 286.35;
  --table-row-selected: 91% 0.01 276;

  /* Surface radii */
  --radius-sm: 8px;
  --radius-surface: 16px;
}

* {
  box-sizing: border-box;
  border-color: oklch(var(--muted-bg));
}
html,
body,
#root {
  height: 100%;
}
body {
  margin: 0;
  font-family:
    'Inter',
    ui-sans-serif,
    system-ui,
    -apple-system,
    sans-serif;
  background: oklch(var(--background));
  color: oklch(var(--primary));
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
button {
  font-family: inherit;
}

/* Reset all <button>s to behave like an unstyled action surface.
   Each custom button restyles itself. */
button {
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  color: inherit;
}

a {
  color: inherit;
  text-decoration: none;
}

/* Typography */
.h0 {
  font-size: 2rem;
  line-height: 2.5rem;
  font-weight: 700;
  letter-spacing: -0.01em;
}
.h1 {
  font-size: 1.5rem;
  line-height: 2rem;
  font-weight: 600;
  letter-spacing: -0.005em;
}
.h2 {
  font-size: 1rem;
  line-height: 1.5rem;
  font-weight: 600;
}
.h3 {
  font-size: 0.75rem;
  line-height: 1rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.body-bold {
  font-size: 0.875rem;
  line-height: 1.25rem;
  font-weight: 600;
}
.body {
  font-size: 0.875rem;
  line-height: 1.25rem;
  font-weight: 400;
}
.caption {
  font-size: 0.75rem;
  line-height: 1rem;
  font-weight: 400;
}
.caption-bold {
  font-size: 0.75rem;
  line-height: 1rem;
  font-weight: 600;
}
.eyebrow {
  font-size: 0.6875rem;
  line-height: 0.875rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: oklch(var(--muted) / 0.7);
}
.tabular {
  font-variant-numeric: tabular-nums;
}

/* Color utility classes */
.text-primary {
  color: oklch(var(--primary));
}
.text-accent {
  color: oklch(var(--accent));
}
.text-secondary {
  color: oklch(var(--secondary));
}
.text-muted {
  color: oklch(var(--muted));
}
.text-muted-2 {
  color: oklch(var(--muted-2));
}
.text-white {
  color: white;
}
.text-action {
  color: oklch(var(--action));
}
.text-ai {
  color: oklch(var(--ai));
}
.text-brand {
  color: oklch(var(--brand));
}
.text-green {
  color: oklch(var(--green));
}
.text-error {
  color: oklch(var(--error));
}
.text-orange {
  color: oklch(var(--orange));
}
.text-finance {
  color: oklch(var(--finance));
}

.bg-background {
  background: oklch(var(--background));
}
.bg-white {
  background: white;
}
.bg-primary {
  background: oklch(var(--primary));
}
.bg-accent {
  background: oklch(var(--accent));
}
.bg-action {
  background: oklch(var(--action));
}
.bg-ai {
  background: oklch(var(--ai));
}
.bg-brand {
  background: oklch(var(--brand));
}
.bg-muted-bg {
  background: oklch(var(--muted-bg));
}
.bg-finance-soft {
  background: oklch(var(--finance-soft));
}
.bg-green-bg {
  background: oklch(var(--green-bg));
}
.bg-orange-bg {
  background: oklch(var(--orange-bg));
}
.bg-error-bg {
  background: oklch(var(--error-bg));
}

.border {
  border: 1px solid oklch(var(--muted-bg));
}
.border-b {
  border-bottom: 1px solid oklch(var(--muted-bg));
}
.border-t {
  border-top: 1px solid oklch(var(--muted-bg));
}
.border-r {
  border-right: 1px solid oklch(var(--muted-bg));
}
.border-l {
  border-left: 1px solid oklch(var(--muted-bg));
}
.divide-y > * + * {
  border-top: 1px solid oklch(var(--muted-bg));
}

.rounded-md {
  border-radius: 8px;
}
.rounded-lg {
  border-radius: 10px;
}
.rounded-xl {
  border-radius: 16px;
}
.rounded-2xl {
  border-radius: 20px;
}
.rounded-full {
  border-radius: 9999px;
}

/* Buttons */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 8px 14px;
  border-radius: 8px;
  font-size: 14px;
  font-weight: 500;
  transition:
    background-color 150ms,
    border-color 150ms,
    opacity 150ms;
  white-space: nowrap;
}
button:focus-visible,
[role='button']:focus-visible,
[role='radio']:focus-visible,
a:focus-visible {
  outline: 2px solid oklch(var(--action));
  outline-offset: 2px;
}
.btn-primary {
  background: oklch(var(--primary));
  color: white;
}
.btn-primary:hover {
  background: oklch(var(--primary) / 0.92);
}
.btn-action {
  background: oklch(var(--action));
  color: white;
}
.btn-action:hover {
  background: oklch(var(--action) / 0.92);
}
.btn-outline {
  background: white;
  color: oklch(var(--primary));
  border: 1px solid oklch(var(--muted-bg));
}
.btn-outline:hover {
  border-color: oklch(var(--muted));
}
.btn-ghost {
  background: transparent;
  color: oklch(var(--primary));
}
.btn-ghost:hover {
  background: oklch(var(--muted-bg) / 0.6);
}
.btn-sm {
  padding: 6px 10px;
  font-size: 13px;
}
.btn-pill {
  border-radius: 9999px;
  padding: 6px 12px;
  font-size: 13px;
}

/* Card */
.card {
  background: white;
  border: 1px solid oklch(var(--muted-bg));
  border-radius: 16px;
}
.card-stat {
  background: white;
  border: 1px solid oklch(var(--muted-bg));
  border-radius: 16px;
  padding: 16px 18px;
}
.card-stat-accent {
  border-left: 4px solid oklch(var(--primary));
  padding-left: 14px;
}

/* Status badges */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 10px;
  border-radius: 9999px;
  font-size: 12px;
  font-weight: 600;
  line-height: 16px;
  white-space: nowrap;
}
.badge-success {
  background: oklch(var(--green-bg));
  color: oklch(var(--green));
}
.badge-warning {
  background: oklch(var(--orange-bg));
  color: oklch(var(--orange));
}
.badge-error {
  background: oklch(var(--error-bg));
  color: oklch(var(--error));
}
.badge-info {
  background: oklch(0.93 0.04 258);
  color: oklch(var(--action));
}
.badge-neutral {
  background: oklch(var(--muted-bg));
  color: oklch(var(--muted));
}
.badge-finance {
  background: oklch(var(--finance-soft));
  color: oklch(var(--finance));
}

/* Status dots */
.dot {
  width: 8px;
  height: 8px;
  border-radius: 9999px;
  display: inline-block;
}
.dot-success {
  background: oklch(var(--green));
}
.dot-warning {
  background: oklch(var(--orange));
}
.dot-error {
  background: oklch(var(--error));
}
.dot-info {
  background: oklch(var(--action));
}
.dot-ai {
  background: oklch(var(--ai));
}

.shadow-sm {
  box-shadow:
    0 1px 2px rgba(20, 20, 40, 0.04),
    0 1px 1px rgba(20, 20, 40, 0.04);
}
.shadow-panel {
  box-shadow:
    0 30px 60px -10px rgba(20, 20, 40, 0.18),
    0 8px 20px -8px rgba(20, 20, 40, 0.08);
}
.shadow-pill {
  box-shadow: 8px 8px 12px 0px oklch(var(--muted-bg));
}

/* Flex / grid utils */
.flex {
  display: flex;
}
.flex-col {
  flex-direction: column;
}
.items-center {
  align-items: center;
}
.items-start {
  align-items: flex-start;
}
.items-stretch {
  align-items: stretch;
}
.items-end {
  align-items: flex-end;
}
.items-baseline {
  align-items: baseline;
}
.justify-center {
  justify-content: center;
}
.justify-between {
  justify-content: space-between;
}
.justify-end {
  justify-content: flex-end;
}
.flex-1 {
  flex: 1 1 0;
  min-width: 0;
  min-height: 0;
}
.flex-wrap {
  flex-wrap: wrap;
}
.flex-shrink-0 {
  flex-shrink: 0;
}
.grid {
  display: grid;
}
.gap-1 {
  gap: 4px;
}
.gap-2 {
  gap: 8px;
}
.gap-3 {
  gap: 12px;
}
.gap-4 {
  gap: 16px;
}
.gap-5 {
  gap: 20px;
}
.gap-6 {
  gap: 24px;
}
.gap-8 {
  gap: 32px;
}

/* Sidebar floating pill enter */
@keyframes slideInLeft {
  from {
    opacity: 0;
    transform: translateX(-6px);
  }
  to {
    opacity: 1;
    transform: translateX(0);
  }
}
.anim-slide-in-left {
  animation: slideInLeft 150ms ease-out;
}

@keyframes pulse {
  0%,
  100% {
    opacity: 1;
  }
  50% {
    opacity: 0.5;
  }
}
.anim-pulse {
  animation: pulse 2s ease-in-out infinite;
}

@keyframes popIn {
  from {
    opacity: 0;
    transform: translateY(4px) scale(0.98);
  }
  to {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}

/* Overlay (Modal/Drawer) enter — see src/shared/ui/overlay.tsx */
@keyframes overlayFade {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}
@keyframes slideInRight {
  from {
    opacity: 0;
    transform: translateX(12px);
  }
  to {
    opacity: 1;
    transform: translateX(0);
  }
}
.anim-slide-in-right {
  animation: slideInRight 200ms ease-out;
}
/* Inline row editor expand — see ledger-catalogs RowEditor */
@keyframes expandDown {
  from {
    opacity: 0;
    transform: translateY(-4px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* Scrollbar (subtle) */
::-webkit-scrollbar {
  width: 10px;
  height: 10px;
}
::-webkit-scrollbar-track {
  background: transparent;
}
::-webkit-scrollbar-thumb {
  background: oklch(var(--muted-bg));
  border-radius: 9999px;
  border: 2px solid oklch(var(--background));
}
::-webkit-scrollbar-thumb:hover {
  background: oklch(var(--secondary) / 0.5);
}

/* The Strategy-Builder view navigation scrolls sideways rather than wrapping,
   and a visible track would cost as much height as the row it protects. */
.sb-viewnav::-webkit-scrollbar {
  display: none;
}

/* A pill rail or chip strip that scrolls sideways inside a control of its own.
   The global scrollbar above is 10px of permanent track — a third of such a
   row's height. The partially-cut item at the edge is the affordance. */
.scroll-rail {
  scrollbar-width: none;
}
.scroll-rail::-webkit-scrollbar {
  display: none;
}

/* Page transition (opacity-only on purpose) */
@keyframes pageFade {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}
.page-fade {
  animation: pageFade 200ms ease-out;
}
/* A navigation the browser is already crossfading does not fade the page a second time. */
html:active-view-transition .page-fade {
  animation: none;
}

/* Subtle hover lift for clickable cards */
.hover-lift {
  transition:
    border-color 150ms,
    transform 150ms,
    box-shadow 150ms;
}
.hover-lift:hover {
  border-color: oklch(var(--muted) / 0.5);
}

/* Glow for finance-related highlight */
.finance-glow {
  box-shadow:
    0 0 0 1px oklch(var(--finance) / 0.2),
    0 8px 24px -8px oklch(var(--finance) / 0.25);
}

/* Planning exposure-slider thumb / track */
.planning-range::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 18px;
  height: 18px;
  border-radius: 9999px;
  background: white;
  border: 2px solid oklch(var(--finance));
  box-shadow: 0 1px 3px rgba(20, 20, 40, 0.18);
  cursor: pointer;
  margin-top: 0;
}
.planning-range::-moz-range-thumb {
  width: 18px;
  height: 18px;
  border-radius: 9999px;
  background: white;
  border: 2px solid oklch(var(--finance));
  box-shadow: 0 1px 3px rgba(20, 20, 40, 0.18);
  cursor: pointer;
}
.planning-range::-webkit-slider-runnable-track {
  background: transparent;
  height: 4px;
}
.planning-range::-moz-range-track {
  background: transparent;
  height: 4px;
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}


/* /src/shared/design-system/components.css */
/* Cozero design system — form and band components, as classes.
   Companion to tokens.css; imported next to it in __root.tsx.

   These are the recipes that were previously written inline at every call site
   — an input's border and radius, a segmented toggle, the four coloured
   explanation bands — expressed once. A rule here may reference only tokens
   from tokens.css, never a literal colour, so a token change moves every
   component with it.

   Font family is deliberately absent: tokens.css sets the stack on `body` and
   `button`, and `input`/`select`/`textarea` do NOT inherit it by default, so
   `font: inherit` below is load-bearing rather than redundant. */

/* ---- inputs ---- */
.input,
.select,
.textarea {
  width: 100%;
  padding: 8px 10px;
  border: 1px solid oklch(var(--muted-bg));
  border-radius: 8px;
  background: white;
  font: inherit;
  font-size: 13px;
  color: oklch(var(--primary));
  outline: none;
}
.input:focus,
.select:focus,
.textarea:focus {
  border-color: oklch(var(--ring));
}
.textarea {
  min-height: 70px;
  resize: vertical;
  line-height: 1.45;
}
/* The chevron is a data: URI rather than an overlaid element so a <select> stays
   one focusable node. Its stroke is #6D7181 — the one literal colour in this
   file, because a url() cannot read a CSS variable. It matches --muted-2. */
.select {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%236D7181' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 9px center;
  padding-right: 28px;
}

.field {
  display: flex;
  flex-direction: column;
  gap: 5px;
  min-width: 0;
}
.field > .caption-bold {
  color: oklch(var(--muted));
}
/* A unit or currency inside the input's right edge. The suffix is
   pointer-events:none so clicking it still focuses the field. */
.input-suffix {
  position: relative;
}
/* The room reserved for the suffix FOLLOWS THE SUFFIX. It was a flat 64px,
   which a long unit overruns — "kgCO₂e/t·km" printed straight over the
   placeholder. `SuffixedInput` sets `--suffix-pad` from the suffix's own
   length; the fallback keeps hand-written markup working. */
.input-suffix .input {
  padding-right: var(--suffix-pad, 64px);
}
.input-suffix > span {
  position: absolute;
  right: 10px;
  top: 50%;
  transform: translateY(-50%);
  font-size: 12px;
  color: oklch(var(--muted-2));
  pointer-events: none;
}
.money {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

/* ---- segmented toggle ---- */
.seg {
  display: inline-flex;
  gap: 2px;
  background: oklch(var(--muted-bg) / 0.5);
  padding: 3px;
  border-radius: 10px;
}
.seg > button {
  padding: 6px 12px;
  border-radius: 8px;
  font-size: 12.5px;
  font-weight: 600;
  color: oklch(var(--muted));
  transition: background-color 120ms;
}
.seg > button.on {
  background: white;
  color: oklch(var(--primary));
  box-shadow:
    0 1px 2px rgba(20, 20, 40, 0.06),
    0 0 0 1px oklch(var(--muted-bg));
}

/* ---- inline add action ---- */
.add-link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12.5px;
  font-weight: 600;
  color: oklch(var(--action));
  padding: 6px 4px;
  border-radius: 7px;
}
.add-link:hover {
  background: oklch(var(--muted-bg) / 0.4);
}

/* ---- separator ---- */
.hr {
  height: 1px;
  background: oklch(var(--muted-bg));
  border: 0;
  margin: 18px 0;
}

/* ---- explanation bands ----
   Four tones for one shape. The tone carries the meaning, so the copy never
   has to say "warning:" — success states a resolved fact, warn states an
   incomplete answer, error states a refusal, info states how something
   composes. */
.success-line,
.warn-line,
.error-line,
.info-line {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  border-radius: 10px;
  padding: 10px 12px;
  font-size: 13px;
  color: oklch(var(--muted));
  margin-top: 14px;
}
.success-line {
  background: oklch(var(--green-bg) / 0.55);
  border: 1px solid oklch(var(--green) / 0.25);
}
.warn-line {
  background: oklch(var(--orange-bg) / 0.7);
  border: 1px solid oklch(var(--orange) / 0.3);
}
.error-line {
  background: oklch(var(--error-bg) / 0.7);
  border: 1px solid oklch(var(--error) / 0.3);
}
.info-line {
  background: oklch(var(--finance-soft));
  border: 1px solid oklch(var(--finance) / 0.18);
  font-size: 12.5px;
}

/* A read-only strip of figures the author is working against — the starting
   emissions above an editor, the operating position below one. */
.baseline-strip {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  background: oklch(var(--muted-bg) / 0.35);
  border: 1px solid oklch(var(--muted-bg));
  border-radius: 12px;
  padding: 11px 14px;
  margin-bottom: 16px;
  font-size: 13px;
  color: oklch(var(--muted));
}

/* ---- small chips ---- */
/* Names the per-year shape a section's values carry — "Discrete payments",
   "Step and hold". The three shapes must never be confused, so each section
   says which one it is. */
.sem-chip {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  border-radius: 5px;
  padding: 2px 7px;
  background: oklch(var(--muted-bg) / 0.8);
  color: oklch(var(--muted));
}
/* Where a picked thing came from. The author never needs to care, but seeing
   it makes "we already measure this" legible at a glance. */
.src-chip {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  border-radius: 5px;
  padding: 2px 6px;
}
.src-ccf {
  background: oklch(var(--green-bg));
  color: oklch(var(--green));
}
.src-core {
  background: oklch(0.93 0.04 258);
  color: oklch(var(--action));
}
.src-new {
  background: oklch(var(--orange-bg));
  color: oklch(var(--orange));
}
.scope-pill {
  width: 22px;
  height: 22px;
  border-radius: 6px;
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  color: white;
  font-size: 10px;
  font-weight: 700;
}
.new-chip {
  font-size: 8.5px;
  font-weight: 700;
  letter-spacing: 0.07em;
  background: oklch(0.93 0.04 258);
  color: oklch(var(--action));
  border-radius: 4px;
  padding: 1px 5px;
}

/* ---- card padding ---- */
.pane {
  padding: 22px 24px;
}


/* /src/features/carbon-intelligence/chat/components/artifacts.css */
/* Artifacts: the panel beside the conversation, the list inside it, the modal it expands into,
   and the page that lists everything across conversations. All three share the row and the
   viewer, so their styles live together rather than in chat.css, which is about the thread. */

.ci-artifact-panel {
  position: relative;
  display: flex;
  flex-shrink: 0;
  flex-direction: column;
  min-height: 0;
  border-left: 1px solid oklch(var(--muted-bg));
  background: oklch(var(--white));
}

/* Sits over the border, wide enough to grab without hunting for it. */
.ci-artifact-resize {
  position: absolute;
  top: 0;
  bottom: 0;
  left: -3px;
  z-index: 5;
  width: 6px;
  cursor: col-resize;
}
.ci-artifact-resize:hover,
.ci-artifact-resize:focus-visible {
  background: oklch(var(--ai) / 0.25);
}

.ci-artifact-header {
  display: flex;
  flex-shrink: 0;
  align-items: center;
  gap: 8px;
  padding: 12px 14px 11px 16px;
  border-bottom: 1px solid oklch(var(--muted-bg));
}

.ci-artifact-title {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  line-height: 1.35;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ci-artifact-header-btn {
  display: inline-flex;
  flex-shrink: 0;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border-radius: 7px;
  color: oklch(var(--muted-2));
}
.ci-artifact-header-btn:hover {
  background: oklch(var(--muted-bg) / 0.7);
  color: oklch(var(--primary));
}

.ci-artifact-body {
  display: flex;
  flex: 1;
  flex-direction: column;
  min-height: 0;
}
.ci-artifact-body-scroll {
  overflow-y: auto;
}

/* ---- the list ---- */

.ci-artifact-list {
  padding: 12px 14px 18px;
}

.ci-artifact-filters {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 14px;
}
.ci-artifact-filters .btn-pill {
  height: 26px;
  padding: 0 11px;
  font-size: 12px;
}

.ci-artifact-empty {
  margin: 0;
  padding: 6px 2px;
  line-height: 1.5;
}

.ci-artifact-family + .ci-artifact-family {
  margin-top: 16px;
}

.ci-artifact-family-label {
  margin: 0 0 6px 2px;
}

.ci-artifact-rows {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.ci-artifact-row {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 9px 10px;
  border: 1px solid transparent;
  border-radius: 10px;
  text-align: left;
  transition:
    background-color 140ms,
    border-color 140ms;
}
.ci-artifact-row:hover {
  background: oklch(var(--muted-bg) / 0.45);
}
.ci-artifact-row[data-open='true'] {
  border-color: oklch(var(--ai) / 0.35);
  background: oklch(var(--ai) / 0.08);
}

/* Uploaded and generated are told apart by the glyph's tint, not by a word on every row. */
.ci-artifact-glyph {
  display: inline-flex;
  flex-shrink: 0;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border-radius: 9px;
  background: oklch(var(--muted-bg) / 0.8);
  color: oklch(var(--muted));
}
.ci-artifact-glyph[data-origin='generated'] {
  background: oklch(var(--ai) / 0.12);
  color: oklch(var(--ai));
}

.ci-artifact-text {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
}

.ci-artifact-name {
  overflow: hidden;
  line-height: 1.35;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ci-artifact-kind,
.ci-artifact-thread {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ci-artifact-time {
  flex-shrink: 0;
  align-self: flex-start;
  margin-top: 2px;
  font-variant-numeric: tabular-nums;
}

/* ---- the modal ---- */

.ci-artifact-modal {
  display: flex;
  flex-direction: column;
  width: min(1200px, 100vw - 48px);
  height: calc(100vh - 48px);
  overflow: hidden;
  border-radius: var(--radius-surface);
  background: oklch(var(--white));
}

.ci-artifact-modal-title {
  gap: 0;
}

/* ---- the page ---- */

.ci-artifacts-page {
  max-width: 900px;
  margin: 0 auto;
}

.ci-artifacts-search {
  margin-bottom: 14px;
}
.ci-artifacts-search .input {
  padding-left: 32px;
}
.ci-artifacts-search-icon {
  position: absolute;
  top: 50%;
  left: 10px;
  color: oklch(var(--muted-2));
  pointer-events: none;
  transform: translateY(-50%);
}
.ci-artifacts-page .ci-artifact-list {
  padding: 0;
}
.ci-artifacts-page .ci-artifact-row {
  border-color: oklch(var(--muted-bg));
  background: oklch(var(--white));
}
.ci-artifacts-page .ci-artifact-row:hover {
  border-color: oklch(var(--muted));
}

/* ---- the actions row, shared by panel and modal ---- */

.ci-artifact-actions {
  flex-shrink: 0;
  padding: 10px 14px;
  border-top: 1px solid oklch(var(--muted-bg));
  background: oklch(var(--white));
}

/* The card an artifact came from, lit for a moment after "Show in conversation" found it. */
[data-ci-found='true'] {
  border-radius: var(--radius-surface);
  outline: 2px solid oklch(var(--ai) / 0.55);
  outline-offset: 3px;
  transition: outline-color 300ms ease;
}


/* /src/features/carbon-intelligence/chat/sections/message-actions.css */
/* The action row under an answer, the overflow menu it opens, and the affordance that carries
   one figure out of a view into the next question — the controls a person acts on an answer
   with, wherever on the answer they sit.

   The row's reveal-on-hover is chat.css's (`.ci-turn:hover .ci-actions`). What is here are the
   two cases where hovering is not how it gets found: a touch screen, which has no hover at all,
   and the last answer, which is the one being acted on. */

/* Both selectors are written against `.ci-turn` so they outweigh the single-class rule in
   chat.css that hides the row. Bundlers are free to order two stylesheets either way, and at
   equal specificity the later one wins — which would leave the row hidden on a touch screen
   half the time. */
@media (hover: none) {
  .ci-turn .ci-actions {
    opacity: 1;
  }
}

/* The newest answer keeps its row on screen: it is where a rating, a retry or a follow-up is
   most likely, and nothing above it is competing for the same attention. */
.ci-turn .ci-actions-last {
  opacity: 1;
}

/* Small, quiet, and only lit under the pointer — the row states what is possible without
   drawing the eye away from the answer it belongs to. */
.ci-actions button {
  transition:
    background 120ms,
    color 120ms;
}
.ci-actions > button:hover:not(:disabled),
.ci-actions-menu-wrap > button:hover:not(:disabled) {
  background: oklch(var(--muted-bg) / 0.6);
}

.ci-actions-menu-wrap {
  position: relative;
  display: inline-flex;
}

.ci-actions-menu {
  position: absolute;
  bottom: calc(100% + 6px);
  left: 0;
  z-index: 20;
  min-width: 216px;
  padding: 5px;
  border: 1px solid oklch(var(--muted-bg));
  border-radius: 10px;
  background: oklch(var(--white));
  box-shadow: 0 10px 30px oklch(var(--primary) / 0.12);
}

.ci-actions-menu-item {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 7px 9px;
  border-radius: 7px;
  font-size: 12.5px;
  text-align: left;
  color: oklch(var(--primary));
  background: transparent;
}
.ci-actions-menu-item:hover:not([aria-disabled='true']),
.ci-actions-menu-item:focus-visible:not([aria-disabled='true']) {
  background: oklch(var(--muted-bg) / 0.6);
}
.ci-actions-menu-item[aria-disabled='true'] {
  color: oklch(var(--muted-2) / 0.7);
  cursor: default;
}

/* Flipped below the trigger when there is not room above it — near the top of the stream the
   scroll container clips anything that reaches past it. */
.ci-actions-menu-down {
  top: calc(100% + 6px);
  bottom: auto;
}

/* Why a disabled item cannot be used, on the line under its name — the same sentence its
   tooltip carries, said where it does not need hovering to be read. */
.ci-actions-menu-why {
  display: block;
  margin-top: 1px;
  font-size: 11px;
  color: oklch(var(--muted-2) / 0.7);
}

/* Quoting one figure out of a view. The control belongs to the row or tile it sits in and
   surfaces when that is hovered or holds focus — a table of thirty rows showing thirty of these
   at once would be louder than the figures. Opacity only: it stays in the tab order unhovered,
   so a keyboard finds it, and it lights up as soon as it takes focus. */
.ci-quote {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border-radius: 6px;
  color: oklch(var(--muted-2));
  opacity: 0;
  transition:
    opacity 120ms,
    background 120ms;
}
.ci-quote-host:hover .ci-quote,
.ci-quote-host:focus-within .ci-quote,
.ci-quote:focus-visible {
  opacity: 1;
}
.ci-quote:hover {
  background: oklch(var(--muted-bg) / 0.7);
  color: oklch(var(--primary));
}

/* Under a chart, where the figure being pointed at has to be named for the control to mean
   anything — the bar itself cannot hold a button the pointer could reach. */
.ci-quote-inline {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  height: 24px;
  padding: 0 8px;
  border-radius: 7px;
  font-size: 12px;
  color: oklch(var(--muted));
  transition: background 120ms;
}
.ci-quote-inline:hover {
  background: oklch(var(--muted-bg) / 0.7);
  color: oklch(var(--primary));
}

/* On a tile the control has no column of its own, so it sits in the corner over the figure. */
.ci-quote-corner {
  position: absolute;
  top: 6px;
  right: 6px;
}

/* A tile is the positioning context for the corner control above. */
.ci-quote-host-tile {
  position: relative;
}

@media (hover: none) {
  .ci-quote {
    opacity: 1;
  }
}

/* The one field a rating opens. Optional — Send with it empty and the rating still lands. */
.ci-feedback {
  margin-top: 8px;
  max-width: 460px;
  padding: 12px 14px;
  border: 1px solid oklch(var(--muted-bg));
  border-radius: 12px;
  background: oklch(var(--white));
}
.ci-feedback-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 10px;
}


/* /src/features/carbon-intelligence/chat/sections/chat.css */
/* Carbon Intelligence — the few animations and scroll behaviours the chat needs.
   Everything else comes from the design system's tokens and component classes. */

/* A page change that carries the conversation with it: the rest of the page crossfades while
   the conversation itself glides from where it was to where it is now. */
::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: 240ms;
}

::view-transition-group(ci-conversation) {
  animation-duration: 480ms;
  animation-timing-function: cubic-bezier(0.22, 1, 0.36, 1);
}

::view-transition-old(ci-conversation) {
  animation: ci-vt-leave 200ms ease-out both;
}

::view-transition-new(ci-conversation) {
  animation: ci-vt-arrive 280ms ease-out 140ms both;
}

@keyframes ci-vt-leave {
  to {
    opacity: 0;
  }
}

@keyframes ci-vt-arrive {
  from {
    opacity: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*) {
    animation-duration: 0.01ms !important;
  }
}

@keyframes ci-caret {
  0%,
  100% {
    opacity: 1;
  }
  50% {
    opacity: 0;
  }
}

/* A card that grows above the reading position must not push what is being read.
   `overflow-anchor` keeps the browser's scroll anchor pinned to the content below. */
.ci-stream {
  overflow-anchor: auto;
}
.ci-stream > * {
  overflow-anchor: none;
}
.ci-anchor {
  overflow-anchor: auto;
  height: 1px;
}

.ci-fade-in {
  animation: ci-fade-in 260ms ease both;
}
@keyframes ci-fade-in {
  from {
    opacity: 0;
    transform: translateY(4px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

/* The message action row appears on hover or when anything inside it has focus. It keeps its
   height either way — a row that collapses when unhovered makes the whole thread jump under
   the pointer — but its height is the only space it takes. */
.ci-actions {
  opacity: 0;
  transition: opacity 140ms;
}
.ci-turn:hover .ci-actions,
.ci-turn:focus-within .ci-actions {
  opacity: 1;
}

/* Streaming prose ends with a caret AFTER the last word. Markdown's final block is a `<p>` (or
   an `<li>`), so a caret rendered as its sibling would drop onto a line of its own underneath.
   It is drawn instead as an `::after` on that final block, which puts it in the same inline
   flow as the text it is trailing — no measurement, no negative margins, correct on a wrapped
   line and on a list. */
.ci-streaming > div > :last-child::after,
.ci-streaming > div > :last-child > li:last-child::after {
  content: '';
  display: inline-block;
  width: 7px;
  height: 0.92em;
  margin-left: 3px;
  vertical-align: text-bottom;
  border-radius: 1px;
  background: oklch(var(--ai));
  animation: ci-caret 1s steps(2, start) infinite;
}

/* A list's own `::after` would double up with its last item's. */
.ci-streaming > div > ul:last-child::after,
.ci-streaming > div > ol:last-child::after {
  content: none;
}

@media (prefers-reduced-motion: reduce) {
  .ci-streaming > div > :last-child::after,
  .ci-streaming > div > :last-child > li:last-child::after {
    animation: none;
  }
}

/* A placeholder for something the server is still writing — the follow-up questions after an
   answer, the sources under it. It carries the shape of the real thing (a pill of about the
   right width) so nothing jumps when the content replaces it, and a slow sheen crossing it says
   the wait is expected rather than broken. */
.ci-skeleton {
  position: relative;
  overflow: hidden;
  border-radius: 7px;
  background: oklch(var(--muted-bg) / 0.55);
}

.ci-skeleton::after {
  content: '';
  position: absolute;
  inset: 0;
  transform: translateX(-100%);
  background: linear-gradient(90deg, transparent, oklch(var(--surface) / 0.75), transparent);
  animation: ci-sheen 1.5s ease-in-out infinite;
}

@keyframes ci-sheen {
  100% {
    transform: translateX(100%);
  }
}

/* Motion is decoration here: the placeholder still reserves the space without it. */
@media (prefers-reduced-motion: reduce) {
  .ci-skeleton::after {
    animation: none;
  }
}

/* The files travelling with the next turn, inside the composer frame above the box. Two abreast
   so a card can carry a real name and a state sentence; the rest collapse into one tile rather
   than wrapping the frame into a second panel. */
/* Two cards abreast, wrapping to the next line rather than narrowing further. A grid of
   `auto-fill` columns takes as many as the composer is wide and squeezes every name into an
   ellipsis; a card has to be wide enough to show a name and a size at once. */
.ci-file-cards {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  padding: 10px 10px 0 12px;
}

.ci-file-cards > .ci-file-card {
  flex: 1 1 240px;
  min-width: 0;
  max-width: 100%;
}

/* The overflow tile is a marker, not a card: it takes only the width of its own label. */
.ci-file-cards > .ci-file-more {
  flex: 0 0 auto;
  min-width: 56px;
}

.ci-file-card {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  padding: 7px 8px 7px 9px;
  border: 1px solid oklch(var(--muted-bg));
  border-radius: var(--radius-sm);
  background: oklch(var(--background) / 0.6);
  text-align: left;
  transition:
    border-color 140ms,
    background 140ms;
}

.ci-file-card[role='button'] {
  cursor: pointer;
}
.ci-file-card[role='button']:hover {
  border-color: oklch(var(--ai) / 0.5);
  background: oklch(var(--white));
}

.ci-file-card[data-status='failed'] {
  border-color: oklch(var(--error) / 0.45);
  background: oklch(var(--error-bg) / 0.35);
}

/* One tile standing in for the cards past the second. */
.ci-file-more {
  justify-content: center;
  min-height: 44px;
  color: oklch(var(--muted));
  cursor: pointer;
}
.ci-file-more:hover {
  border-color: oklch(var(--muted) / 0.5);
}

.ci-file-glyph {
  display: inline-flex;
  flex-shrink: 0;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border-radius: 7px;
  background: oklch(var(--muted-bg) / 0.7);
  color: oklch(var(--muted));
}
.ci-file-card[data-status='failed'] .ci-file-glyph {
  background: oklch(var(--error-bg));
  color: oklch(var(--error));
}
.ci-file-card[data-status='ready'] .ci-file-glyph {
  color: oklch(var(--ai));
}

.ci-file-body {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
}

/* The name is shortened in the middle before it reaches the DOM, so this only guards a name
   that is one unbroken word wider than the card. */
.ci-file-name {
  overflow: hidden;
  color: oklch(var(--primary));
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ci-file-state {
  overflow: hidden;
  color: oklch(var(--muted-2));
  text-overflow: ellipsis;
  white-space: nowrap;
}
.ci-file-state-failed {
  color: oklch(var(--error));
}

.ci-file-controls {
  display: inline-flex;
  flex-shrink: 0;
  align-items: center;
  gap: 2px;
}

.ci-file-action {
  padding: 3px 7px;
  border-radius: 6px;
  color: oklch(var(--action));
  white-space: nowrap;
}
.ci-file-action:hover {
  background: oklch(var(--muted-bg) / 0.7);
}

.ci-file-remove {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border-radius: 6px;
  color: oklch(var(--muted-2));
}
.ci-file-remove:hover {
  background: oklch(var(--muted-bg));
  color: oklch(var(--primary));
}

/* ---- Quotes: the floating control, the chip row, and the marks they light ---- */

/* A quoted span, painted back inside the answer it came from. The browser's own highlight
   registry does this without a wrapper element, so the rendered markdown is never touched. */
::highlight(ci-quote) {
  background: oklch(var(--ai) / 0.18);
  color: oklch(var(--primary));
}

/* The card a reference chip points at, lit while the chip is hovered. Matches the focused
   surface a card takes in the transcript. */
[data-ci-quote-focus='true'] > * {
  border-color: oklch(var(--ai) / 0.45);
  box-shadow: 0 6px 24px oklch(var(--primary) / 0.08);
}

.ci-quote-float {
  z-index: 45;
  width: max-content;
}

/* Styled in full here rather than on top of `.btn`: the shared button's own hover paints the
   background and leaves the colour to the variant, so a float button carrying `.btn` with no
   variant went invisible under the pointer. It owns every property it needs instead. */
.ci-quote-float-btn {
  display: inline-flex;
  gap: 5px;
  align-items: center;
  padding: 6px 12px;
  border: 1px solid oklch(var(--muted-bg));
  border-radius: 9999px;
  background: oklch(var(--white));
  box-shadow: 0 6px 20px oklch(var(--primary) / 0.14);
  color: oklch(var(--primary));
  font-size: 12.5px;
  font-weight: 500;
  white-space: nowrap;
  transition:
    background 140ms,
    border-color 140ms;
}
.ci-quote-float-btn:hover,
.ci-quote-float-btn:focus-visible {
  border-color: oklch(var(--ai) / 0.45);
  background: oklch(var(--muted-bg) / 0.6);
  color: oklch(var(--primary));
}

.ci-ask-choices {
  display: flex;
  flex-direction: column;
  gap: 2px;
  width: max-content;
  min-width: 200px;
  margin-top: 6px;
  padding: 5px;
  border: 1px solid oklch(var(--muted-bg));
  border-radius: 10px;
  background: oklch(var(--white));
  box-shadow: 0 8px 24px oklch(var(--primary) / 0.12);
}

.ci-ask-choice {
  display: flex;
  gap: 8px;
  align-items: center;
  padding: 7px 9px;
  border-radius: 7px;
  color: oklch(var(--primary));
  font-size: 12.5px;
  text-align: left;
  white-space: nowrap;
}
.ci-ask-choice:hover,
.ci-ask-choice:focus-visible {
  background: oklch(var(--muted-bg) / 0.7);
  outline: none;
}

.ci-quote-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  margin: 0;
  padding: 8px 12px 0;
  list-style: none;
}

.ci-quote-chip {
  display: inline-flex;
  gap: 6px;
  align-items: center;
  height: 26px;
  padding: 0 4px 0 8px;
  border: 1px solid oklch(var(--muted-bg));
  border-radius: 7px;
  background: oklch(var(--white));
  color: oklch(var(--primary));
  font-size: 12px;
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
  transition:
    border-color 140ms,
    background 140ms;
}
.ci-quote-chip:hover,
.ci-quote-chip:focus-within {
  border-color: oklch(var(--ai) / 0.45);
  outline: none;
}

/* A chip carrying a note says so without spending a word on it. */
.ci-quote-chip[data-ci-noted='true'] {
  border-color: oklch(var(--ai) / 0.45);
  background: oklch(var(--ai) / 0.06);
}

/* The chip's body is the button that opens its note; the remove control sits beside it. */
.ci-quote-chip-open {
  display: inline-flex;
  gap: 6px;
  align-items: center;
  min-width: 0;
  color: inherit;
  font: inherit;
}

.ci-quote-chip-numeral {
  color: oklch(var(--ai));
  font-size: 13px;
}

.ci-quote-chip-label {
  overflow: hidden;
  max-width: 220px;
  color: oklch(var(--muted));
  text-overflow: ellipsis;
}

.ci-quote-chip-remove {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  border-radius: 5px;
  color: oklch(var(--muted-2));
}
.ci-quote-chip-remove:hover {
  background: oklch(var(--muted-bg));
  color: oklch(var(--primary));
}

/* What a chip opens: the words in full, and a field for what to say about them. Anchored over
   the chip, above it, because the row sits at the bottom of the screen. */
.ci-quote-note {
  position: absolute;
  bottom: calc(100% + 8px);
  left: 0;
  z-index: 45;
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: 300px;
  padding: 11px 12px;
  border: 1px solid oklch(var(--muted-bg));
  border-radius: 12px;
  background: oklch(var(--white));
  box-shadow: 0 14px 40px oklch(var(--primary) / 0.14);
}

/* The quoted words, readable in full and wrapping — the chip is the truncated form, not this. */
.ci-quote-note-text {
  max-height: 108px;
  overflow-y: auto;
  padding-left: 9px;
  border-left: 2px solid oklch(var(--ai) / 0.4);
  color: oklch(var(--primary));
  font-size: 12.5px;
  line-height: 1.5;
  white-space: pre-wrap;
}

.ci-quote-note-field {
  min-height: 54px;
  resize: vertical;
  font-family: inherit;
}

/* How much of the note is left, shown only near the cap. */
.ci-quote-note-count {
  margin: 4px 0 0;
  color: oklch(var(--muted-2));
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  text-align: right;
}

/* The chip numbers, painted beside the words each one was taken from. The layer never takes the
   pointer: the answer underneath stays selectable straight through it. */
.ci-quote-marks {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 30;
  pointer-events: none;
}

.ci-quote-mark {
  position: absolute;
  transform: translate(-100%, -2px);
  padding-right: 3px;
  color: oklch(var(--ai));
  font-size: 12px;
  line-height: 1;
}

/* The icon-only controls at the right end of the chip row — attach, and the allowance ring. The
   same square as a chip is tall, quiet at rest, lifted on hover like the chips beside them. */
.ci-row-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: 7px;
  color: oklch(var(--muted-2));
  transition:
    background 140ms,
    color 140ms;
}
.ci-row-button:hover,
.ci-row-button[aria-expanded='true'] {
  background: oklch(var(--muted-bg));
  color: oklch(var(--primary));
}

/* Send, at the very end of the row: filled once there is something to send, red while an answer
   is being written and the same control stops it. */
.ci-send {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  margin-left: 4px;
  border-radius: 9999px;
  background: oklch(var(--muted-bg));
  color: oklch(var(--muted-2));
  transition:
    background 140ms,
    color 140ms;
}
.ci-send[data-ci-ready='true'] {
  background: oklch(var(--primary));
  color: oklch(var(--white));
}
.ci-send[data-ci-busy='true'] {
  background: oklch(var(--error));
  color: oklch(var(--white));
}

/* ---- The header row ---- */

/* A control in the header. Quiet at rest, on a surface of its own when hovered or when it is the
   one that is on, so the state reads from the lift rather than from a second colour. */
.ci-header-action {
  display: inline-flex;
  flex-shrink: 0;
  gap: 6px;
  align-items: center;
  height: 28px;
  padding: 0 10px;
  border: 1px solid transparent;
  border-radius: 9999px;
  color: oklch(var(--muted));
  font-size: 12.5px;
  white-space: nowrap;
  transition:
    background 140ms,
    border-color 140ms,
    color 140ms;
}
.ci-header-action:hover {
  border-color: oklch(var(--muted-bg));
  background: oklch(var(--white));
  color: oklch(var(--primary));
}
.ci-header-action[data-ci-active='true'] {
  border-color: oklch(var(--muted-bg));
  background: oklch(var(--muted-bg) / 0.7);
  color: oklch(var(--primary));
}

/* How many artifacts the conversation has. A numeral riding the control, not a badge stuck to
   it: the count is part of what the control says. */
.ci-header-count {
  min-width: 16px;
  padding: 0 4px;
  border-radius: 9999px;
  background: oklch(var(--ai) / 0.14);
  color: oklch(var(--ai));
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  line-height: 16px;
  text-align: center;
}

/* The line in the transcript while a proposed edit waits in the document beside the panel. The
   line already carries the assistant's colour, so the only motion is the arrow leaning toward the
   document the decision is waiting in — direction, not a pulse. */
.ci-pending-edit svg:last-of-type {
  animation: ci-pending-lean 2.6s ease-in-out infinite;
}

@keyframes ci-pending-lean {
  0%,
  100% {
    transform: none;
  }
  50% {
    transform: translateX(-3px);
  }
}

@media (prefers-reduced-motion: reduce) {
  .ci-pending-edit svg:last-of-type {
    animation: none;
  }
}

/* The one action under an answer that starts something rather than acting on the answer itself.
   It is the same quiet shape as its neighbours until it is approached, and then it takes the
   assistant's colour — clear about what it leads to without shouting across the transcript. */
.ci-convert-action button:hover:not(:disabled) {
  background: oklch(var(--ai) / 0.12);
  color: oklch(var(--ai));
}

/* "Convert into insight": the same menu shell as the ask choices, opening from the action that
   raised it and wide enough for a real insight name. */
.ci-convert-menu {
  min-width: 232px;
  max-width: 320px;
  /* Placed against the action's box by the component, so it carries no offset of its own. */
  margin-top: 0;
  overflow-y: auto;
  scrollbar-width: thin;
  transform-origin: top left;
  animation: ci-menu-in 140ms cubic-bezier(0.22, 1, 0.36, 1) both;
}

.ci-convert-menu[data-side='above'] {
  transform-origin: bottom left;
  animation-name: ci-menu-in-up;
}

@keyframes ci-menu-in {
  from {
    opacity: 0;
    transform: translateY(-4px) scale(0.97);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@keyframes ci-menu-in-up {
  from {
    opacity: 0;
    transform: translateY(4px) scale(0.97);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

.ci-convert-menu .ci-ask-choice {
  gap: 9px;
  width: 100%;
  min-width: 0;
  color: oklch(var(--primary));
  transition:
    background 120ms ease,
    color 120ms ease;
}

.ci-convert-menu .ci-ask-choice svg {
  flex-shrink: 0;
  color: oklch(var(--muted-2));
  transition: color 120ms ease;
}

.ci-convert-menu .ci-ask-choice:hover svg,
.ci-convert-menu .ci-ask-choice:focus-visible svg {
  color: oklch(var(--ai));
}

.ci-convert-menu .ci-ask-choice:disabled {
  color: oklch(var(--muted-2) / 0.6);
  cursor: default;
}

.ci-convert-menu .ci-ask-choice:disabled:hover {
  background: transparent;
}

/* The one that starts something new sits above the list, with a hairline between. */
.ci-convert-menu-section {
  margin-top: 4px;
  padding: 7px 9px 4px;
  border-top: 1px solid oklch(var(--muted-bg) / 0.8);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  font-size: 10px;
}

@media (prefers-reduced-motion: reduce) {
  .ci-convert-menu {
    animation: none;
  }
}

/* ---- The panel beside an insight, before the first question ---- */

/* The assistant introducing itself as a co-author: a mark, an invitation in the app's own voice,
   and three ways in. It sits at the top of the room rather than floating in the middle, so the
   panel reads as ready rather than as empty. */
.ci-insight-welcome {
  padding: 4px 0 8px;
}

.ci-insight-welcome-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: 13px;
  background: oklch(var(--ai) / 0.12);
  color: oklch(var(--ai));
}

.ci-insight-welcome-starters {
  display: flex;
  flex-direction: column;
  gap: 7px;
}

/* One way in. A card rather than a line in a list, so the three read as offers and the pointer
   has something to land on. */
.ci-insight-starter {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 10px 11px;
  border-radius: 11px;
  border: 1px solid oklch(var(--muted-bg));
  background: oklch(var(--white));
  text-align: left;
  font-size: 13px;
  line-height: 1.45;
  color: oklch(var(--primary));
  transition:
    border-color 160ms ease,
    box-shadow 200ms ease,
    transform 200ms cubic-bezier(0.22, 1, 0.36, 1);
  animation: ci-fade-in 340ms cubic-bezier(0.22, 1, 0.36, 1) both;
}

.ci-insight-starter:hover,
.ci-insight-starter:focus-visible {
  transform: translateY(-1px);
  border-color: oklch(var(--ai) / 0.45);
  box-shadow: 0 8px 20px -10px oklch(var(--primary) / 0.35);
}

.ci-insight-starter-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  flex-shrink: 0;
  border-radius: 8px;
  background: oklch(var(--muted-bg) / 0.6);
  color: oklch(var(--muted));
  transition:
    background 180ms ease,
    color 180ms ease;
}

.ci-insight-starter:hover .ci-insight-starter-mark,
.ci-insight-starter:focus-visible .ci-insight-starter-mark {
  background: oklch(var(--ai) / 0.14);
  color: oklch(var(--ai));
}

.ci-insight-starter-go {
  flex-shrink: 0;
  color: oklch(var(--ai));
  opacity: 0;
  transform: translateX(-4px);
  transition:
    opacity 180ms ease,
    transform 220ms cubic-bezier(0.22, 1, 0.36, 1);
}

.ci-insight-starter:hover .ci-insight-starter-go,
.ci-insight-starter:focus-visible .ci-insight-starter-go {
  opacity: 1;
  transform: none;
}

@media (prefers-reduced-motion: reduce) {
  .ci-insight-starter {
    animation: none;
  }
  .ci-insight-starter:hover,
  .ci-insight-starter:focus-visible {
    transform: none;
  }
  .ci-insight-starter-go {
    transform: none;
  }
}


/* /src/shared/ui/ai-elements/ai-elements.css */
/* The ported AI Elements. Tokens only — every colour is an oklch(var(--token)) from
   design-system/tokens.css, and every animation degrades to a static, legible resting state
   under prefers-reduced-motion. */

/* Text that is still being worked on: a bright band crossing the glyphs, clipped to the text,
   so a running line reads as live without a spinner anywhere on screen.

   Two stacked layers. Underneath, a flat muted fill is the text's resting colour. Above it, a
   250%-wide band travelling right to left whose centre is the full-contrast ink — on a light
   surface the sweep therefore reads as the sentence brightening rather than as a pale wash,
   which is what a page-background highlight would give here. The band's half-width comes from
   `--ci-shimmer-spread`, which the component sets from the length of the sentence, so a short
   step and a long one sweep at the same apparent speed. */
@keyframes ci-shimmer-sweep {
  0% {
    background-position:
      100% center,
      0 0;
  }
  100% {
    background-position:
      0% center,
      0 0;
  }
}

.ci-shimmer {
  --ci-shimmer-spread: 24px;
  --ci-shimmer-duration: 2s;
  position: relative;
  display: inline-block;
  background-image:
    linear-gradient(
      90deg,
      transparent calc(50% - var(--ci-shimmer-spread)),
      oklch(var(--primary)),
      transparent calc(50% + var(--ci-shimmer-spread))
    ),
    linear-gradient(oklch(var(--muted-2)), oklch(var(--muted-2)));
  background-size:
    250% 100%,
    auto;
  background-repeat: no-repeat, padding-box;
  background-clip: text;
  -webkit-background-clip: text;
  color: transparent;
  animation: ci-shimmer-sweep var(--ci-shimmer-duration) linear infinite;
}

@media (prefers-reduced-motion: reduce) {
  .ci-shimmer {
    animation: none;
    color: oklch(var(--muted));
    background-image: none;
    -webkit-text-fill-color: currentColor;
  }
}

/* A disclosure whose body slides rather than snapping. The height is animated by the component;
   this only carries the easing and the reduced-motion opt-out. */
.ci-disclosure-body {
  overflow: hidden;
}

/* One step of a chain of thought. The pending steps sit back so the running one is the only
   line at full contrast — status drives opacity, never colour. */
.ci-step {
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 3px 0;
  font-size: 13px;
  transition: opacity 180ms ease;
}

.ci-step-pending {
  opacity: 0.55;
}

.ci-step-active {
  opacity: 1;
}

.ci-step-complete {
  opacity: 0.72;
}

.ci-step-dot {
  flex-shrink: 0;
  width: 5px;
  height: 5px;
  border-radius: 9999px;
  align-self: center;
  background: oklch(var(--muted-2));
}

.ci-step-active .ci-step-dot {
  background: oklch(var(--ai));
  box-shadow: 0 0 0 3px oklch(var(--ai) / 0.18);
}

.ci-step-complete .ci-step-dot {
  background: oklch(var(--ai));
}

.ci-step-error .ci-step-dot {
  background: oklch(var(--error));
}

.ci-step-label {
  flex: 1;
  min-width: 0;
  color: oklch(var(--muted));
}

.ci-step-error .ci-step-label,
.ci-step-error .ci-step-result {
  color: oklch(var(--error));
}

.ci-step-result {
  flex-shrink: 0;
  color: oklch(var(--muted-2));
  font-variant-numeric: tabular-nums;
}


/* /src/features/carbon-intelligence/chat/sections/sent-quotes.css */
/* What a question was asked about, above the person's own words. Right-aligned with the bubble
   it belongs to, quiet enough that the question is still what the eye lands on. */
.ci-sent-quotes {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  justify-content: flex-end;
  margin: 0 0 5px;
  padding: 0;
  max-width: 76%;
  list-style: none;
}

.ci-sent-quote {
  display: inline-flex;
  gap: 5px;
  align-items: center;
  max-width: 320px;
  height: 22px;
  padding: 0 8px;
  border: 1px solid oklch(var(--muted-bg));
  border-radius: 7px;
  color: oklch(var(--muted-2));
  font-size: 11.5px;
  line-height: 1;
  white-space: nowrap;
  transition:
    color 140ms,
    border-color 140ms;
}
.ci-sent-quote:hover,
.ci-sent-quote:focus-visible {
  border-color: oklch(var(--ai) / 0.45);
  color: oklch(var(--primary));
  outline: none;
}

.ci-sent-quote-text {
  overflow: hidden;
  text-overflow: ellipsis;
}

.ci-quote-numeral {
  flex-shrink: 0;
  color: oklch(var(--ai));
  font-size: 12px;
}


/* /src/features/act/simulate/sections/wizard-components.css */
/* Simulate Action wizard — the components only this flow has.
   Imported once, from wizard-shell.tsx.

   The generic half (inputs, .seg, .field, the four explanation bands, the
   chips) lives in shared/design-system/components.css, because those recipes
   are not specific to authoring a reduction measure. What is here is: the
   pickers on steps 2-4, the two adjustment shapes on step 5, the phase-in row
   on step 6, the line-item editor on steps 7-8, and the result tiles and
   cash-flow table on step 9.

   Same rule as the shared file: tokens only, no literal colours. */

/* ---- Assistant bubble and step heading ---- */
.bubble {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  margin-bottom: 18px;
}
.bubble .avatar {
  width: 32px;
  height: 32px;
  border-radius: 9999px;
  background: oklch(var(--ai));
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  color: white;
  margin-top: 2px;
}
/* The square corner points at the avatar, which is what makes it read as
   speech rather than as a card. */
.bubble .say {
  background: white;
  border: 1px solid oklch(var(--muted-bg));
  border-radius: 4px 14px 14px 14px;
  padding: 10px 14px;
  font-size: 14px;
  line-height: 1.5;
  color: oklch(var(--muted));
  max-width: 620px;
}
.step-title {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 14px;
}
.step-title .ico {
  width: 30px;
  height: 30px;
  border-radius: 9px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: white;
  flex: none;
}

/* ---- steps 2-4: pickable rows ---- */
.pick-row {
  display: flex;
  align-items: center;
  gap: 9px;
  width: 100%;
  text-align: left;
  padding: 9px 12px;
  border-radius: 9px;
  border: 1px solid oklch(var(--muted-bg));
  background: white;
  margin-bottom: 6px;
  transition:
    border-color 120ms,
    background-color 120ms;
  font-size: 13px;
}
.pick-row:hover {
  border-color: oklch(var(--secondary));
}
.pick-row.sel {
  border-color: oklch(var(--finance));
  background: oklch(var(--finance-soft));
  box-shadow: 0 0 0 1px oklch(var(--finance) / 0.35);
}
.pick-row .amt {
  margin-left: auto;
  font-size: 11.5px;
  color: oklch(var(--muted-2));
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* ---- step 4: narrowing ---- */
.narrow-head {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  text-align: left;
  padding: 11px 0 4px;
  color: oklch(var(--muted));
  font-size: 13px;
  font-weight: 600;
}
.narrow-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 12px;
  margin-top: 10px;
}
.narrow-card {
  border: 1px solid oklch(var(--muted-bg));
  border-radius: 12px;
  padding: 11px 12px;
  background: white;
}
.narrow-card .hint {
  font-size: 11px;
  color: oklch(var(--muted-2));
  margin: 2px 0 8px;
}
.narrow-opt {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 5px 6px;
  border-radius: 7px;
  width: 100%;
  text-align: left;
  font-size: 12.5px;
  color: oklch(var(--muted));
}
.narrow-opt:hover {
  background: oklch(var(--muted-bg) / 0.4);
}
.narrow-opt .cb {
  width: 15px;
  height: 15px;
  border-radius: 5px;
  border: 1.5px solid oklch(var(--secondary));
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  color: white;
}
.narrow-opt.on .cb {
  background: oklch(var(--finance));
  border-color: oklch(var(--finance));
}
.narrow-opt .sub {
  margin-left: auto;
  font-size: 10.5px;
  color: oklch(var(--muted-2));
  font-variant-numeric: tabular-nums;
}

/* ---- step 4: the switch's receiving activities ---- */
.recv-row {
  display: flex;
  align-items: center;
  gap: 10px;
  border: 1px solid oklch(var(--muted-bg));
  border-radius: 10px;
  padding: 10px 12px;
  margin-bottom: 8px;
  background: white;
}
/* One wide panel: search, a grouped list, and create-new in its footer. Three
   sources of a receiving activity are presented as one picker on purpose —
   the author never needs to know which of the three they used. */
.picker-pop {
  border: 1px solid oklch(var(--muted-bg));
  border-radius: 12px;
  background: white;
  box-shadow:
    0 30px 60px -10px rgba(20, 20, 40, 0.18),
    0 8px 20px -8px rgba(20, 20, 40, 0.08);
  padding: 10px;
  margin-top: 8px;
}
.picker-pop .grp {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: oklch(var(--muted-2));
  padding: 8px 8px 4px;
}
.picker-opt {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  text-align: left;
  padding: 7px 8px;
  border-radius: 8px;
  font-size: 13px;
}
.picker-opt:hover {
  background: oklch(var(--muted-bg) / 0.45);
}
.picker-opt .sub {
  margin-left: auto;
  font-size: 11px;
  color: oklch(var(--muted-2));
  font-variant-numeric: tabular-nums;
}

/* ---- step 5: the two adjustment shapes ---- */
.adj-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
}
.adj-card {
  border: 1px solid oklch(var(--muted-bg));
  border-radius: 12px;
  padding: 14px 15px;
  background: white;
  position: relative;
}
/* `.live` marks the adjustments the author has actually authored. Either alone
   is a complete measure, so neither card can be styled as the primary one. */
.adj-card.live {
  border-color: oklch(var(--finance) / 0.45);
  box-shadow: 0 0 0 1px oklch(var(--finance) / 0.2);
}
.delta-badge {
  position: absolute;
  top: 12px;
  right: 12px;
}
/* Claims against the donor activity, which are validated together against
   100% — an initiative cannot switch away more than it has. */
.total-bar {
  height: 8px;
  border-radius: 9999px;
  background: oklch(var(--muted-bg));
  overflow: hidden;
  margin-top: 6px;
}
.total-bar > div {
  height: 100%;
  border-radius: 9999px;
  background: oklch(var(--finance));
  transition: width 200ms;
}
.total-bar.over > div {
  background: oklch(var(--error));
}

/* ---- step 6: the phase-in ----
   One cell per year of the lifetime, all on one row, so each year lines up
   with its bar in the preview below. Long lifetimes scroll horizontally
   rather than wrapping, which would break that alignment.

   ONE SCROLLER AROUND BOTH the cells and the preview, which is what keeps
   that alignment true past ~13 years: with a scrollbar on the cells alone, a
   15-year lifetime scrolled the cells while the bars stayed put, so the year
   under a bar was not the year in the cell above it. Both tracks share
   `flex: 1 1 0` and the same min-width, so a column is one year wide in both. */
.phase-scroll {
  overflow-x: auto;
  padding-bottom: 4px;
}
.phase-grid {
  display: flex;
  gap: 6px;
  margin-top: 12px;
}
.phase-cell {
  flex: 1 1 0;
  min-width: 58px;
  border: 1px solid oklch(var(--muted-bg));
  border-radius: 9px;
  padding: 6px 7px;
  background: white;
}
.phase-cell .yr {
  font-size: 10.5px;
  font-weight: 600;
  color: oklch(var(--muted-2));
  display: flex;
  justify-content: space-between;
}
.phase-cell input {
  width: 100%;
  border: 0;
  outline: none;
  font: inherit;
  font-size: 14px;
  font-weight: 600;
  color: oklch(var(--primary));
  padding: 2px 0 0;
  background: transparent;
  font-variant-numeric: tabular-nums;
}
.phase-preview {
  display: flex;
  align-items: flex-end;
  gap: 6px;
  height: 54px;
  margin-top: 14px;
}
.phase-preview .pb {
  flex: 1 1 0;
  min-width: 58px;
  background: oklch(var(--finance) / 0.75);
  border-radius: 3px 3px 0 0;
  min-height: 2px;
  position: relative;
}
.phase-preview .pb span {
  position: absolute;
  bottom: 100%;
  left: 50%;
  transform: translateX(-50%);
  font-size: 8.5px;
  color: oklch(var(--muted-2));
  padding-bottom: 2px;
  white-space: nowrap;
}

/* ---- steps 7-8: the line-item editor ----
   One shape for capex, opex and revenue. A name, a value, and the period it
   applies to — the per-year semantics differ, and the section's .sem-chip
   says which, but the editor does not. */
.line-item {
  border: 1px solid oklch(var(--muted-bg));
  border-radius: 12px;
  padding: 13px 14px;
  margin-bottom: 10px;
  background: white;
}
.li-head {
  display: flex;
  align-items: center;
  gap: 10px;
}
.li-head .input {
  flex: 1;
}
.li-del {
  color: oklch(var(--muted-2));
  padding: 6px;
  border-radius: 7px;
  flex: none;
}
.li-del:hover {
  color: oklch(var(--error));
  background: oklch(var(--error-bg) / 0.5);
}
.li-body {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: flex-end;
  margin-top: 10px;
}
.sched-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 7px;
}

/* ---- step 9: the metric tiles ---- */
.kpi-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 12px;
}
.kpi {
  background: white;
  border: 1px solid oklch(var(--muted-bg));
  border-radius: 16px;
  padding: 14px 16px;
  position: relative;
}
.kpi .lbl {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: oklch(var(--muted-2));
  display: flex;
  align-items: center;
  gap: 6px;
}
.kpi .val {
  font-size: 21px;
  font-weight: 700;
  letter-spacing: -0.01em;
  margin-top: 5px;
  font-variant-numeric: tabular-nums;
}
.kpi .hint {
  font-size: 10.5px;
  color: oklch(var(--muted-2));
  margin-top: 3px;
}
/* The two tiles the cash-flow table's cumulative columns reconcile to. The
   lift is the visual claim that nothing is unaccounted for between them. */
.kpi.reconciled {
  box-shadow:
    0 0 0 1px oklch(var(--finance) / 0.2),
    0 8px 24px -8px oklch(var(--finance) / 0.25);
}

/* ---- step 9: the working ---- */
.cf-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 12px;
}
.cf-table th {
  text-align: right;
  padding: 9px 10px;
  background: oklch(var(--muted-bg) / 0.25);
  border-bottom: 1px solid oklch(var(--muted-bg));
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: oklch(var(--table-header));
  white-space: nowrap;
}
.cf-table th:first-child,
.cf-table td:first-child {
  text-align: left;
}
.cf-table td {
  text-align: right;
  padding: 8px 10px;
  border-bottom: 1px solid oklch(var(--muted-bg) / 0.6);
  font-variant-numeric: tabular-nums;
  color: oklch(var(--muted));
  white-space: nowrap;
}
.cf-table tr:last-child td {
  border-bottom: 0;
  font-weight: 600;
  color: oklch(var(--primary));
  background: oklch(var(--finance-soft) / 0.6);
}
.legend {
  display: flex;
  gap: 14px;
  flex-wrap: wrap;
  align-items: center;
  margin-top: 8px;
}
.legend .li {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: oklch(var(--muted));
}
.legend .box {
  width: 11px;
  height: 11px;
  border-radius: 2px;
}
.chart-tip {
  position: fixed;
  z-index: 90;
  background: white;
  border: 1px solid oklch(var(--muted-bg));
  border-radius: 10px;
  box-shadow: 0 8px 24px rgba(20, 20, 40, 0.12);
  padding: 9px 12px;
  min-width: 170px;
  max-width: 280px;
  pointer-events: none;
  display: none;
}
.jump-links {
  display: flex;
  gap: 18px;
  flex-wrap: wrap;
  margin-top: 16px;
}
.jump-links button {
  font-size: 12.5px;
  font-weight: 600;
  color: oklch(var(--action));
  display: inline-flex;
  gap: 5px;
  align-items: center;
}

/* Two columns rather than four once four will not fit, then one. The
   adjustment pair collapses on the same breakpoints. */
@media (max-width: 900px) {
  .adj-grid,
  .kpi-grid {
    grid-template-columns: 1fr 1fr;
  }
}
@media (max-width: 560px) {
  .adj-grid,
  .kpi-grid {
    grid-template-columns: 1fr;
  }
}
