/*
 * The canvas (canvases/_canvas): a board of the space's harness that pans and
 * zooms inside the main pane, with the selected node in the details pane.
 * The canvas controller sets --canvas-x, --canvas-y, and --canvas-scale.
 * Edges are drawn in physical board coordinates, so this file uses physical
 * offsets where it places things on the board.
 */
@layer components {
  /* Forms sit in the inspector, so it is wider than other details panes. */
  .shell:has(.canvas) {
    --details-width: 24rem;
  }

  .canvas {
    --canvas-x: 0px;
    --canvas-y: 0px;
    --canvas-scale: 1;
    --canvas-dot: light-dark(oklch(0.85 0 0), oklch(1 0 0 / 14%));
    --canvas-edge: light-dark(oklch(0.8 0 0), oklch(1 0 0 / 22%));
    --canvas-motion: 200ms cubic-bezier(0.23, 1, 0.32, 1);

    position: relative;
    flex: 1;
    min-block-size: 0;
    /* clip, not hidden: focus must not scroll the board out from under the transform. */
    overflow: clip;
    background-color: light-dark(oklch(0.985 0 0), oklch(0.165 0 0));
    background-image: radial-gradient(circle, var(--canvas-dot) 1px, transparent 1.5px);
    background-position: var(--canvas-x) var(--canvas-y);
    background-size: calc(1.25rem * var(--canvas-scale)) calc(1.25rem * var(--canvas-scale));
    cursor: grab;
    touch-action: none;
    user-select: none;
    -webkit-user-select: none;

    &[data-panning] {
      cursor: grabbing;
    }

    &[data-animating] {
      transition: background-position var(--canvas-motion), background-size var(--canvas-motion);
    }
  }

  .canvas__stage {
    position: absolute;
    top: 0;
    left: 0;
    transform: translate(var(--canvas-x), var(--canvas-y)) scale(var(--canvas-scale));
    transform-origin: 0 0;
  }

  .canvas[data-animating] .canvas__stage {
    transition: transform var(--canvas-motion);
  }

  .canvas-board {
    position: relative;
    display: grid;
    grid-auto-columns: 15rem;
    grid-auto-flow: column;
    align-items: center;
    column-gap: 5rem;
    inline-size: max-content;
    padding: 2.5rem;
  }

  .canvas-board__edges {
    position: absolute;
    top: 0;
    left: 0;
    overflow: visible;
    pointer-events: none;
  }

  .canvas-edge {
    fill: none;
    stroke: var(--canvas-edge);
    stroke-width: 1.5;
    stroke-linecap: round;
    transition: stroke 150ms ease-out;

    &[data-hovered] {
      stroke: var(--muted-foreground);
    }

    &[data-selected] {
      stroke: var(--foreground);
      stroke-width: 2;
    }
  }

  .canvas-board__column {
    display: grid;
    gap: 2rem;
  }

  .canvas-group {
    display: grid;
    gap: 0.625rem;
  }

  .canvas-group__title {
    display: flex;
    align-items: center;
    gap: 0.375rem;
    padding-inline: 0.25rem;
    color: var(--muted-foreground);
    font-size: var(--text-xs);
    font-weight: var(--font-weight-medium);
    letter-spacing: var(--tracking-normal);
    line-height: var(--text-xs--line-height);
  }

  .canvas-group__count {
    font-variant-numeric: tabular-nums;
  }

  .canvas-group__nodes {
    display: grid;
    gap: 0.625rem;
    margin: 0;
    padding: 0;
    list-style: none;
  }

  /* React Flow's default node, in the card's tokens. */
  .canvas-node {
    position: relative;
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    align-items: start;
    gap: 0.625rem 0.75rem;
    padding: 0.75rem;
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    background: var(--card);
    box-shadow: 0 1px 2px oklch(0 0 0 / 6%);
    color: var(--card-foreground);
    text-decoration: none;
    -webkit-user-drag: none;
    transition: border-color 150ms ease-out, box-shadow 150ms ease-out, transform 150ms ease-out;

    &:hover {
      border-color: color-mix(in oklch, var(--border), var(--foreground) 30%);
    }

    &:active {
      transform: scale(0.97);
    }

    &:focus-visible {
      outline: 2px solid var(--ring);
      outline-offset: 2px;
    }

    &[aria-current="page"] {
      border-color: var(--foreground);
      box-shadow: 0 0 0 1px var(--foreground), 0 6px 16px oklch(0 0 0 / 10%);
    }
  }

  .canvas[data-panning] .canvas-node:active {
    transform: none;
  }

  /* Nothing connects to it yet. */
  .canvas-node--idle:not([aria-current="page"]) {
    border-style: dashed;
    background: color-mix(in oklch, var(--card) 60%, transparent);
    box-shadow: none;

    .canvas-node__icon,
    .canvas-node__text,
    .canvas-node__chips {
      opacity: 0.7;
    }
  }

  .canvas-node__icon {
    display: grid;
    place-items: center;
    inline-size: 2rem;
    block-size: 2rem;
    border-radius: var(--radius-md);
    background: var(--muted);
    color: var(--foreground);

    svg {
      inline-size: 1rem;
      block-size: 1rem;
    }
  }

  /* Agents are what the rest of the board serves. */
  .canvas-node--agent .canvas-node__icon {
    background: var(--primary);
    color: var(--primary-foreground);
  }

  .canvas-node__text {
    display: grid;
    gap: 0.125rem;
    min-inline-size: 0;
  }

  .canvas-node__kind {
    color: var(--muted-foreground);
    font-size: var(--text-xs);
    line-height: var(--text-xs--line-height);
  }

  .canvas-node__title {
    overflow: hidden;
    font-size: var(--text-sm);
    font-weight: var(--font-weight-medium);
    line-height: var(--text-sm--line-height);
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .canvas-node__meta {
    display: -webkit-box;
    overflow: hidden;
    color: var(--muted-foreground);
    font-size: var(--text-xs);
    line-height: var(--text-xs--line-height);
    overflow-wrap: anywhere;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
  }

  .canvas-node--agent .canvas-node__meta,
  .canvas-node--hook .canvas-node__meta {
    font-family: var(--font-mono);
  }

  .canvas-node__chips {
    display: flex;
    flex-wrap: wrap;
    grid-column: 1 / -1;
    gap: 0.25rem;
  }

  /* Where edges meet a node. Prompts only lead out; tools and hooks only lead in. */
  .canvas-node__port {
    position: absolute;
    top: 50%;
    inline-size: 0.625rem;
    block-size: 0.625rem;
    border: 1.5px solid color-mix(in oklch, var(--border), var(--foreground) 35%);
    border-radius: 50%;
    background: var(--card);
    translate: -50% -50%;
  }

  .canvas-node__port--in {
    left: 0;
  }

  .canvas-node__port--out {
    left: 100%;
  }

  .canvas-node--prompt .canvas-node__port--in,
  .canvas-node--tool .canvas-node__port--out,
  .canvas-node--hook .canvas-node__port--out {
    display: none;
  }

  .canvas-node[aria-current="page"] .canvas-node__port {
    border-color: var(--foreground);
  }

  .canvas-add {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    min-block-size: 2.75rem;
    border: 1px dashed color-mix(in oklch, var(--border), var(--foreground) 15%);
    border-radius: var(--radius-lg);
    color: var(--muted-foreground);
    font-size: var(--text-sm);
    line-height: var(--text-sm--line-height);
    text-decoration: none;
    -webkit-user-drag: none;
    transition: background-color 150ms ease-out, border-color 150ms ease-out, color 150ms ease-out, transform 150ms ease-out;

    &:hover,
    &[aria-current="page"] {
      border-color: color-mix(in oklch, var(--border), var(--foreground) 45%);
      background: color-mix(in oklch, var(--card) 70%, transparent);
      color: var(--foreground);
    }

    &:active {
      transform: scale(0.97);
    }

    &:focus-visible {
      outline: 2px solid var(--ring);
      outline-offset: 2px;
    }
  }

  .canvas-add__icon {
    display: inline-flex;

    svg {
      inline-size: 1rem;
      block-size: 1rem;
    }
  }

  /* React Flow's controls panel. */
  .canvas__controls {
    position: absolute;
    inset-block-end: 0.75rem;
    inset-inline-start: 0.75rem;
    display: flex;
    align-items: center;
    gap: 0.125rem;
    padding: 0.25rem;
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    background: var(--card);
    box-shadow: 0 1px 3px oklch(0 0 0 / 8%);
    cursor: default;
  }

  .canvas__zoom {
    min-inline-size: 3.75rem;
    padding-inline: 0.5rem;
    font-size: var(--text-sm);
    font-variant-numeric: tabular-nums;
  }

  .canvas__controls-rule {
    inline-size: 1px;
    block-size: 1.25rem;
    margin-inline: 0.125rem;
    background: var(--border);
  }

  /* The inspector frame. Its content dims while the next node loads. */
  .canvas-inspector {
    display: block;

    form {
      display: grid;
      gap: 1rem;
      transition: opacity 150ms ease-out;
    }

    /* A form waits for its save and takes no input meanwhile. */
    form[inert] {
      opacity: 0.72;
      transition-delay: 100ms;
    }

    .details-pane {
      transition: opacity 150ms ease-out;
    }

    &[busy] .details-pane {
      opacity: 0.55;
      transition-delay: 100ms;
    }
  }

  .canvas-inspector__header {
    display: flex;
    align-items: center;
    gap: 0.75rem;
  }

  .canvas-inspector__heading {
    display: grid;
    flex: 1;
    min-inline-size: 0;
  }

  .canvas-inspector__kind {
    color: var(--muted-foreground);
    font-size: var(--text-xs);
    line-height: var(--text-xs--line-height);
  }

  .canvas-inspector__title {
    font-size: var(--text-base);
    font-weight: var(--font-weight-semibold);
    letter-spacing: var(--tracking-normal);
    line-height: var(--text-base--line-height);
    overflow-wrap: anywhere;
  }

  /* The save outcome sits under the form and takes no room while empty. */
  .canvas-inspector__status:not(:empty) {
    margin-block-start: 0.75rem;
  }

  .canvas-inspector__saved {
    color: var(--muted-foreground);
    font-size: var(--text-sm);
    line-height: var(--text-sm--line-height);
    transition: opacity 200ms ease-out, translate 200ms ease-out;

    @starting-style {
      opacity: 0;
      translate: 0 -0.25rem;
    }
  }

  .canvas-inspector__code {
    max-block-size: 20rem;
    margin: 0;
    padding: 0.75rem;
    overflow: auto;
    border: 1px solid var(--sidebar-border);
    border-radius: var(--radius-md);
    background: var(--background);
    font-family: var(--font-mono);
    font-size: var(--text-xs);
    line-height: var(--text-xs--line-height);
  }

  @media (width >= 48rem) {
    .canvas__controls .button {
      min-block-size: 2rem;
    }

    .canvas__controls .button--icon {
      min-inline-size: 2rem;
    }
  }

  @media (prefers-reduced-motion: reduce) {
    .canvas[data-animating],
    .canvas[data-animating] .canvas__stage,
    .canvas-edge,
    .canvas-node,
    .canvas-add,
    .canvas-inspector .details-pane,
    .canvas-inspector form,
    .canvas-inspector__saved {
      transition: none;
    }

    .canvas-node:active,
    .canvas-add:active {
      transform: none;
    }
  }
}
