/* The Opengeni app's design system on Tailwind: the token bridge, base styles,
   variants and motion shared by every surface that renders the session UI
   (the web app, the desktop app, first-party panes). The importing stylesheet
   brings Tailwind and `@opengeni/react/styles.css`, and adds an `@source` for
   `@opengeni/react`'s `src`. */
@custom-variant dark (&:where(.dark, .dark *));
/* A desktop app window at least 640px wide. Desktop windows are never phones,
   so layouts that fold into a header below 1024px on the web keep their side
   column in the app down to its own minimum. */
@custom-variant desktop-wide {
  @media (min-width: 640px) {
    &:where(html[data-desktop] *) {
      @slot;
    }
  }
}

/* ---------------------------------------------------------------------------
   Design tokens
   Tailwind bridge for the canonical @opengeni/react token palette.
   --------------------------------------------------------------------------- */
@theme {
  --font-sans: "Inter Variable", "Noto Sans JP Variable", "Noto Sans Arabic Variable",
    ui-sans-serif, system-ui, sans-serif;
  --font-mono: "JetBrains Mono Variable", ui-monospace, SFMono-Regular,
    "Noto Sans JP Variable", "Noto Sans Arabic Variable", Menlo, monospace;
  --font-display: "DM Sans Variable", "Inter Variable", ui-sans-serif, system-ui, sans-serif;
  --font-serif: "Instrument Serif", ui-serif, Georgia, serif;

  --text-2xs: 0.6875rem;
  --text-2xs--line-height: 1rem;

  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 14px;
  --radius-xl: 20px;

  --color-bg: var(--og-color-bg);
  --color-canvas: var(--og-color-canvas);
  --color-selection: var(--og-color-selection);
  --color-hover: var(--og-color-hover);
  --color-surface: var(--og-color-surface-1);
  --color-surface-2: var(--og-color-surface-2);
  --color-surface-3: var(--og-color-surface-3);
  --color-border: var(--og-color-border);
  --color-border-strong: var(--og-color-border-strong);
  --color-fg: var(--og-color-fg);
  --color-fg-label: var(--og-color-fg-label);
  --color-fg-muted: var(--og-color-fg-muted);
  --color-fg-subtle: var(--og-color-fg-subtle);

  --color-brand: var(--og-color-accent);
  --color-brand-strong: var(--og-color-accent-deep);
  --color-brand-fg: var(--og-color-accent-fg);

  /* The filled primary action ("teal wash"). `primary` is the button only;
     brand stays the neutral mark for icons, links, focus and selection. */
  --color-primary: var(--og-color-primary);
  --color-primary-foreground: var(--og-color-primary-fg);
  --color-primary-border: var(--og-color-primary-border);
  --color-primary-hover: var(--og-color-primary-hover);
  --color-switch-track: var(--og-color-switch-track);
  --color-switch-thumb: var(--og-color-switch-thumb);

  --color-glow-teal: var(--og-glow-teal);
  --color-glow-peach: var(--og-glow-peach);

  --color-status-queued: var(--og-color-status-queued);
  --color-status-running: var(--og-color-status-running);
  --color-status-idle: var(--og-color-status-idle);
  --color-status-waiting: var(--og-color-status-waiting);
  --color-status-success: var(--og-color-status-idle);
  --color-status-failed: var(--og-color-status-failed);
  --color-status-cancelled: var(--og-color-status-cancelled);
  --color-danger: var(--og-color-danger);

  /* Chat updates are not lifecycle states. Keep unread and following-up
     markers teal without recoloring neutral navigation or other statuses. */
  --color-session-update: light-dark(#0f766e, #5ad4c5);

  /* Data visualization (Insights). Token classes, then series in fixed order.
     Validated with the dataviz palette checks against both canvases. */
  --color-chart-input: var(--og-chart-input);
  --color-chart-cache-read: var(--og-chart-cache-read);
  --color-chart-cache-write: var(--og-chart-cache-write);
  --color-chart-output: var(--og-chart-output);
  --color-chart-1: var(--og-chart-1);
  --color-chart-2: var(--og-chart-2);
  --color-chart-3: var(--og-chart-3);
  --color-chart-4: var(--og-chart-4);
  --color-chart-5: var(--og-chart-5);
  --color-chart-6: var(--og-chart-6);

  /* shadcn compatibility — map canonical token names to ours */
  --color-background: var(--color-bg);
  --color-foreground: var(--color-fg);

  --color-card: var(--color-surface);
  --color-card-foreground: var(--color-fg);

  /* Menus and popovers are the surface (DESIGN.md "Menus and popovers"). */
  --color-popover: var(--color-surface);
  --color-popover-foreground: var(--color-fg);

  --color-secondary: var(--color-selection);
  --color-secondary-foreground: var(--color-fg-muted);

  --color-muted: var(--color-surface-2);
  --color-muted-foreground: var(--color-fg-muted);

  --color-accent: var(--color-surface-2);
  --color-accent-foreground: var(--color-fg);

  --color-destructive: var(--og-color-danger);
  /* Danger is tuned as a readable foreground token. Filled destructive
     controls use the darker danger fill to preserve AA white-text contrast
     in both themes. */
  --color-destructive-filled: var(--og-color-danger-fill);
  --color-destructive-foreground: var(--og-color-danger-fg);

  --color-input: var(--color-surface-2);
  --color-ring: var(--color-brand);

  --color-sidebar: var(--color-surface);
  --color-sidebar-foreground: var(--color-fg);
  --color-sidebar-primary: var(--color-primary);
  --color-sidebar-primary-foreground: var(--color-primary-foreground);
  --color-sidebar-accent: var(--color-surface-2);
  --color-sidebar-accent-foreground: var(--color-fg);
  --color-sidebar-border: var(--color-border);
  --color-sidebar-ring: var(--color-brand);

  --background: var(--color-bg);
  --foreground: var(--color-fg);
  --card: var(--color-surface);
  --card-foreground: var(--color-fg);
  --muted: var(--color-surface-2);
  --muted-foreground: var(--color-fg-muted);
  --border: var(--color-border);
  --input: var(--color-surface-2);
  --primary: var(--color-primary);
  --primary-foreground: var(--color-primary-foreground);
  --radius: var(--radius-md);
}

/* ---------------------------------------------------------------------------
   Base
   --------------------------------------------------------------------------- */
/* Chart palette: dark is the default canvas; light re-steps the same hues. */
:root,
[data-og-theme="dark"] {
  --og-chart-input: #3987e5;
  --og-chart-cache-read: #199e70;
  --og-chart-cache-write: #9085e9;
  --og-chart-output: #d95926;
  --og-chart-1: #3987e5;
  --og-chart-2: #d95926;
  --og-chart-3: #199e70;
  --og-chart-4: #c98500;
  --og-chart-5: #d55181;
  --og-chart-6: #9085e9;
}

[data-og-theme="light"],
.og-light {
  --og-chart-input: #2a78d6;
  --og-chart-cache-read: #1baf7a;
  --og-chart-cache-write: #4a3aa7;
  --og-chart-output: #eb6834;
  --og-chart-1: #2a78d6;
  --og-chart-2: #eb6834;
  --og-chart-3: #1baf7a;
  --og-chart-4: #eda100;
  --og-chart-5: #e87ba4;
  --og-chart-6: #4a3aa7;
}

/* The main content pane (next to the rail or the settings rail). It paints
   the canvas, and inside it the page background *is* the canvas: sticky
   footers, page-variant forms and inset wells that use `bg-bg` keep matching
   the pane they sit on, while the rail and page chrome outside keep `bg`.
   Portalled menus and dialogs copy the effective tokens from their trigger. */
[data-canvas] {
  --og-color-bg: var(--og-color-canvas);
  --color-bg: var(--og-color-canvas);
  background-color: var(--og-color-canvas);
}

/* The hover wash on something that has its own fill (a suggestion card, an
   outline card): the same --color-hover, layered over the fill instead of
   replacing it. Transparent rows and menu items use `hover:bg-hover`. */
@utility hover-layer {
  background-image: linear-gradient(var(--color-hover), var(--color-hover));
}

/* Rail glow: a soft teal wash from the top-left and a peach wash from the
   bottom-right over the rail color. Used by the main rail and the settings
   rail; layered so a rail's own background utilities can still override it. */
@layer components {
  .og-rail-glow {
    background:
      radial-gradient(ellipse 130% 45% at 0 0, var(--og-glow-teal), transparent 85%),
      radial-gradient(ellipse 140% 45% at 100% 100%, var(--og-glow-peach), transparent 85%),
      var(--og-color-bg);
  }

  /* The signed-out pages: the same two washes along the left edge of the
     canvas. */
  .og-page-glow {
    background:
      radial-gradient(ellipse 42% 70% at 0 20%, var(--og-glow-teal), transparent 95%),
      radial-gradient(ellipse 42% 65% at 0 100%, var(--og-glow-peach), transparent 95%),
      var(--og-color-canvas);
  }
}

@media (forced-colors: active) {
  .og-rail-glow,
  .og-page-glow {
    background: Canvas;
  }
}

/* Layered so Tailwind border-color utilities (border-brand, border-danger...)
   can override the default. Unlayered, this rule beat every utility. */
@layer base {
  * {
    border-color: var(--color-border);
  }
}

::selection {
  background: color-mix(in oklch, var(--color-brand) 45%, transparent);
  color: var(--color-fg);
}

/* Subtle scrollbars. On classic-scrollbar platforms (see markClassicScrollbars
   in @opengeni/react) Chromium would draw arrow buttons on these, so engines
   with ::-webkit-scrollbar get a slim rounded thumb that widens on hover. */
* {
  scrollbar-width: thin;
  scrollbar-color: var(--color-border-strong) transparent;
}

@supports selector(::-webkit-scrollbar) {
  :where(:root[data-og-scrollbars="classic"]) * {
    scrollbar-width: auto;
    scrollbar-color: auto;
  }

  :where(:root[data-og-scrollbars="classic"]) *::-webkit-scrollbar {
    width: 10px;
    height: 10px;
    background: transparent;
  }

  :where(:root[data-og-scrollbars="classic"]) *::-webkit-scrollbar-thumb {
    border: 3px solid transparent;
    border-radius: 999px;
    background: var(--color-border-strong) padding-box;
  }

  :where(:root[data-og-scrollbars="classic"]) *::-webkit-scrollbar-thumb:hover {
    border-width: 2px;
    background-color: var(--color-fg-subtle);
  }

  :where(:root[data-og-scrollbars="classic"]) *::-webkit-scrollbar-corner {
    background: transparent;
  }
}

/* Focus ring. One calm, intentional treatment: a soft brand-tinted ring set off
   from the control by a 2px gap (never a harsh full-chroma hairline hugging the
   edge). Kept clearly visible for keyboard users while reading as designed, not
   as a default browser outline.

   Exclusions:
   - the composer textarea (`.og-root textarea`) already shows a whole-composer
     focus affordance (focus-within border + soft glow), so a second outline
     bounded to the textarea box would double it;
   - the model search input sits in its menu's search header, like the
     combobox search, where the caret shows focus;
   - shadcn buttons (`[data-slot="button"]`) carry their own offset ring in
     button.tsx — excluding them here avoids stacking two rings on one control;
   - `[tabindex="-1"]` is for programmatic focus only (timeline scroller, etc.).
     Mouse-click + any key (e.g. Shift) flips keyboard modality and would paint
     a huge ring around the whole pane — skip those; real tab stops use 0+.
   - menu items take roving, programmatic focus even under the mouse; their
     focus is the menu highlight (the `hover` wash), the same for pointer
     and keyboard (DESIGN.md "Menus and popovers"). */
:where(
  button,
  a,
  input,
  textarea,
  [role="button"],
  [tabindex]:not([tabindex="-1"])
):focus-visible:not(.og-root textarea):not(.og-model-policy-search-input):not([data-slot="button"]):not(.connector-control):not([role^="menuitem"]) {
  outline: 2px solid color-mix(in oklch, var(--color-ring) 55%, transparent);
  outline-offset: 2px;
}

/* Round the ring on unstyled targets (bare links, text buttons) without
   overriding a control's own rounded-* utility, which would snap it to 6px. */
@layer base {
  :where(
    button,
    a,
    input,
    textarea,
    [role="button"],
    [tabindex]:not([tabindex="-1"])
  ):focus-visible:not(.og-root textarea):not(.og-model-policy-search-input):not([data-slot="button"]):not(.connector-control):not([role^="menuitem"]) {
    border-radius: var(--radius-sm);
  }
}

/* Connector controls own a bounded inset ring, so adjacent actions never overlap. */
.connector-control:focus-visible {
  outline: 2px solid color-mix(in oklch, var(--color-ring) 55%, transparent);
  outline-offset: -3px;
}

:where(button, a[href], [role="button"], [role="menuitem"], [role="option"], summary):not(:disabled, [aria-disabled="true"]) {
  cursor: pointer;
}

:where(button, [role="button"], [role="menuitem"], [role="option"]):disabled,
:where([aria-disabled="true"]) {
  cursor: not-allowed;
}

:where(input, textarea) {
  cursor: text;
}

/* Sonner keeps the toast container's slide/fade, but its default child-opacity
   tween passes through low-contrast text while a notification joins or leaves
   the collapsed stack. Switch the content atomically so every rendered frame
   remains readable. */
.toaster [data-sonner-toast] > * {
  transition: none;
}

/* A theme flip swaps every token at once; no control animates through the
   mix of the two palettes (see lib/appearance.tsx). */
:root[data-og-theme-switching] *,
:root[data-og-theme-switching] *::before,
:root[data-og-theme-switching] *::after {
  transition: none !important;
}

/* Respect reduced motion */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}

/* Message entry animation */
@keyframes og-message-in {
  from {
    opacity: 0;
    transform: translateY(4px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.message-in {
  animation: og-message-in 180ms ease-out both;
}

.chat-scroll-mask {
  scrollbar-gutter: stable;
  scroll-padding-block: 2.5rem 14rem;
}

.markdown-stream {
  max-width: 100%;
  overflow-wrap: anywhere;
}

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

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

.markdown-stream-compact {
  font-size: 0.875rem;
  line-height: 1.5rem;
}

.markdown-stream [data-streamdown-table-wrapper],
.markdown-stream [data-sd-table-wrapper] {
  max-width: 100%;
  overflow-x: auto;
}

/* Shrink to fit, then wrap cells within the (possibly widened) table wrapper
   instead of forcing one-line rows and horizontal scrolling. */
.markdown-stream table {
  width: auto;
  min-width: min(100%, 32rem);
}

/* Pending dots */
@keyframes og-pending-dot {
  0%,
  80%,
  100% {
    opacity: 0.25;
    transform: translateY(0);
  }
  40% {
    opacity: 1;
    transform: translateY(-2px);
  }
}

.pending-dot {
  animation: og-pending-dot 1.2s infinite ease-in-out both;
}

/* Spend the title's last pixels on letters, not an ellipsis. Keep the fade
   within the title column, before the gap to trailing icons. The mask affects
   only text, so the rail glow and selected/hover backgrounds stay untouched. */
[data-session-row-title] {
  mask-image: linear-gradient(to right, #000 calc(100% - 1rem), transparent);
}

/* Workspace Insights — tabular figures for meter columns */
[data-insights] {
  font-feature-settings: "cv11", "ss01", "ss03", "tnum";
}

/* Keep the tools entry point compact in narrow composers. */
@media (max-width: 639px) {
  .session-tools-trigger { width: 2rem; padding-inline: 0; gap: 0; }
  .session-tools-label, .session-tools-chevron { display: none; }
}
@container og-composer (max-width: 39.999rem) {
  /* A split desktop pane needs the same overflow menu as a phone. These
     hooks keep the compact controls without duplicating them or changing
     their keyboard/menu behavior. */
  .console-composer-wide-control { display: none; }
  .console-composer-compact-control { display: inline-flex; }
  .session-tools-trigger { width: 2rem; padding-inline: 0; gap: 0; }
  .session-tools-label, .session-tools-chevron { display: none; }
}
.capabilities-tab-bar { display:flex; flex-wrap:wrap; align-items:center; justify-content:space-between; gap:8px 16px; border-bottom:1px solid var(--color-border); }
.capabilities-tab-action { display:flex; align-items:center; margin-left:auto; padding-block:4px; }
.capabilities-tab-action:empty { display:none; }
.capabilities-tabs { margin-top: 16px; gap: 20px; }
.capabilities-tab-bar > [data-slot="tabs-list"] {
  width: auto; height: auto; min-height: 44px; justify-content: flex-start;
  gap: 24px; padding: 0; border-bottom: 0;
  border-radius: 0; background: transparent;
}
.capabilities-tab-bar > [data-slot="tabs-list"] > [data-slot="tabs-trigger"] {
  flex: none; height: 44px; padding: 0 2px; border: 0; border-radius: 0;
  background: transparent; box-shadow: none;
}
.capabilities-tab-bar > [data-slot="tabs-list"] > [data-slot="tabs-trigger"]::after {
  bottom: -1px; height: 2px; border-radius: 2px;
}

/* Skill editing controls keep a visible surface in either theme. */
.skills-panel .skill-editor { background:var(--color-surface); }
.skills-panel [data-variant="outline"], .skills-panel select { background:var(--color-surface); border:1px solid var(--color-border-strong); color:var(--color-fg); box-shadow:none; }
.skills-panel [data-variant="outline"]:hover:not(:disabled), .skills-panel select:hover:not(:disabled) { background:var(--color-surface-2, var(--color-bg)); }
.skills-panel [aria-expanded="true"] { background:var(--color-surface); color:var(--color-fg); box-shadow:inset 0 -2px var(--color-brand); border:1px solid var(--color-border-strong); }
.skills-panel textarea, .skills-panel input { background:var(--color-bg); border-color:var(--color-border-strong); color:var(--color-fg); }
.skills-panel button:disabled { opacity:.55; }

.skills-panel [hidden] { display:none !important; }
.skills-panel .skill-list { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:4px 24px; }
.skills-panel .skill-list-row { display:flex; align-items:center; justify-content:space-between; gap:16px; min-width:0; min-height:52px; padding:12px; border:0; border-radius:8px; background:transparent; color:var(--color-fg); text-align:left; cursor:pointer; box-shadow:none; }
.skills-panel .skill-list-row:hover, .skills-panel .skill-list-row[aria-expanded="true"] { background:var(--color-surface-2,var(--color-surface)); border:0; box-shadow:none; }
.skills-panel .skill-list-row:focus-visible { outline:2px solid var(--color-brand); outline-offset:2px; }
@media (max-width:640px) { .skills-panel .skill-list { grid-template-columns:minmax(0,1fr); } }

/* All-results boundaries; tab-specific layouts keep their own spacing. */
.capability-search-section {
  margin-top: 28px;
  padding-top: 24px;
  border-top: 1px solid var(--color-border);
}
.capability-search-section > .og-plugin-discovery,
.capability-search-section > section {
  margin-top: 0;
}
