/* Styles for the function parameter form. The Composer's own module
   keeps the rules that toggle the *wrapper* into fn-form mode (padding,
   bottom-row separator, send-button position); everything that lives
   inside the form itself is here. */

/* Panel is anchored to the top edge of the input-bottom-row (54px
   tall) so its bottom edge always sits flush against the divider.
   The wrapper has `overflow: hidden` and an inline `height` driven by
   React. As the wrapper's height grows from chat-mode to fn-form-mode,
   the panel's top edge slides UP into view from behind the bottom row,
   matching the "growing out from behind the divider" feel the user
   asked for. */
/* Header, body, and inputBottomRow are three flat siblings of the
   wrapper. No `.panel` div wraps the body — body is the middle row.
*/

/* Header / body fade in with the staggered timings shared by the
   composer (header first, body slightly later) so the form reads as
   one continuous reveal. Close fades both out together over 0.12s
   before the wrapper begins its height transition.

   Header height mirrors `--composer-bottom-row-h` so the form's top
   strip and the input options strip read as a matched pair (same
   thickness, same vertical breathing room). */
/* Header — mirror of `.inputBottomRow` in fn-form-mode, flipped top↔
   bottom. The bottom row has a 1px `border-top` divider and shaves
   1px off its top padding to keep the plus-button equidistant from
   the divider above and the wrapper edge below. The header does the
   same flipped: 1px `border-bottom` divider, 1px shaved off its
   bottom padding.
       1 (border-bottom)
       + 15 (padding-bottom = pad − 1)
       + 32 (button-size)
       + 16 (padding-top = pad)
       = 64 = --composer-bottom-row-h
*/
.header {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  /* Right padding reserves space for the wrapper-level close button
     (16 offset + 32 size + 8 breathing room = 56), mirroring how
     `.inputTopRow` reserves space for the action button. */
  padding: var(--composer-bottom-row-pad)
    calc(var(--composer-bottom-row-pad) + var(--composer-button-size) + 8px)
    calc(var(--composer-bottom-row-pad) - 1px)
    24px;
  /* Lock the header height to `--composer-bottom-row-h` (= 64), so it
     matches the bottom row and centres the absolute-positioned close
     button (top: 16, size: 32 → centre 32 = header centre when h=64).
     Otherwise, with the close button hoisted out, the header would
     shrink to whatever the title text needs. */
  min-height: var(--composer-bottom-row-h);
  border-bottom: 1px solid var(--border);
  box-sizing: border-box;
  flex-shrink: 0;
  /* Default opacity 1 (don't rely on the fade-in animation to reach
     the visible state). Background-tab Chrome pauses the animation
     timeline at currentTime=0, so the previous opacity:0 + animation
     keyframe combo left the fn-form blank whenever the tab wasn't
     focused at mount. Closing transition (.header.closing below)
     still drives a 1 → 0 fade. */
  opacity: 1;
}

.header.closing,
.body.closing {
  animation: none;
  opacity: 0;
  /* Matches the open fade-in duration so the close is a true mirror
     image: wrapper shrinks (0.3s) while header/body fade 1→0 (0.25s)
     in parallel, instead of fading out first and then animating the
     height. */
  transition: opacity var(--composer-fade-duration) ease;
}
/* Header title — same single-line + fade-on-overflow + hover-to-expand
   treatment as the field labels below, so long function descriptions
   don't get cut with an ellipsis but instead trail off with a mask
   gradient and reveal fully when the user hovers the row. */
.title {
  display: block;
  flex: 1 1 auto;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  -webkit-mask-image: linear-gradient(
    to right,
    #000 calc(100% - 48px),
    transparent 100%
  );
  mask-image: linear-gradient(
    to right,
    #000 calc(100% - 48px),
    transparent 100%
  );
  cursor: default;
}
/* No hover-expand on the header title either — same reason as .label.
   The full text is reachable via the `title` attribute set in the
   FunctionForm header. */
.name {
  font-family: var(--font-mono);
  font-size: var(--fs-base);
  font-weight: 600;
  color: var(--accent-orange);
  flex-shrink: 0;
}
.keyword {
  color: var(--text-secondary);
  font-weight: 400;
}
.dash {
  font-family: var(--font-sans);
  font-size: var(--fs-base);
  color: var(--text-muted);
  flex-shrink: 0;
}
.desc {
  font-family: var(--font-sans);
  font-size: var(--fs-base);
  color: var(--text-muted);
}
/* Close button moved out to composer.module.css (.closeBtn) — it
   lives at the wrapper level so it stays mounted across fn-form
   switches. */

.body {
  padding: 14px 24px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  /* Divider between the form fields and the bottom row. Living here
     (rather than on the bottom row as a `border-top`) keeps the
     bottom row's geometry identical between chat mode and fn-form
     mode — only the body adds the line. */
  border-bottom: 1px solid var(--border);
  /* See .header above — opacity defaults to 1 to survive
     background-tab animation-timeline pauses. */
  opacity: 1;
  /* 自然高度（不 `flex: 1` 撑满）：flex 填充会把 wrapper 多出来的高度
     堆到 body 底部，造成「底 padding 比顶多几 px」的不可控余量。改成
     内容高度后顶底 padding 严格对称、所见即所得。内容超长仍可内部滚动。 */
  flex: 0 0 auto;
  overflow-y: auto;
  /* Keep the body scrollable but hide the scrollbar chrome — same
     treatment as `.slashMenu` / `.scroll-overlay` elsewhere in the app. */
  scrollbar-width: none; /* Firefox */
}
.body::-webkit-scrollbar {
  display: none; /* WebKit / Chromium */
}
.field {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
/* Field label — PyTorch-docs style, all on one line at the same size.
   The only typographic distinction is `--font-mono` on the param name
   (to mark it as a code identifier). Everything else is plain
   sans-serif prose so the row reads as a single sentence:
     param_name (type, optional) – description.

   Long descriptions are clipped to a single line by default; the
   trailing edge fades out via a mask gradient (no ellipsis dots) so
   the truncation reads as "more content here" rather than a hard cut.
   Hovering the row drops the clip + mask so the full description
   wraps and reveals. */
.label {
  display: block;
  font-family: var(--font-sans);
  font-size: var(--fs-base);
  line-height: 1.5;
  color: var(--text-secondary);
  white-space: nowrap;
  overflow: hidden;
  -webkit-mask-image: linear-gradient(
    to right,
    #000 calc(100% - 48px),
    transparent 100%
  );
  mask-image: linear-gradient(
    to right,
    #000 calc(100% - 48px),
    transparent 100%
  );
  cursor: default;
}
/* No hover-expand on the label any more — the inline-grow caused
   the wrapper to resize on every hover, which read as jarring.
   Full text is now shown via a native `title` tooltip set in
   FieldRow (fn-form-fields.tsx) so the layout doesn't move at all. */
.labelName {
  font-family: var(--font-mono);
  font-weight: 600;
  /* Cream / off-white — dimmer than `--text-bright` so it doesn't
     glare next to the muted prose around it. */
  color: var(--text-primary);
}
.labelMeta {
  font-style: italic;
  color: var(--text-secondary);
}
.labelDash {
  color: var(--text-muted);
}
.labelDesc {
  color: var(--text-secondary);
}

/* Single-line inputs (.input, .select, .workdirInput) all share the
   same 32px height / 8px radius / 0 12 padding so they line up as a
   matched set. The multi-line textarea variant breaks out of these
   constraints below. */
.input {
  background: var(--bg-primary);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 0 12px;
  height: 32px;
  line-height: 30px;
  color: var(--text-bright);
  font-size: var(--fs-base);
  font-family: var(--font-mono);
  outline: none;
  transition: border-color 180ms ease;
  width: 100%;
  box-sizing: border-box;
}
.input:focus {
  border-color: var(--accent-blue);
}
.input::placeholder {
  color: var(--text-muted);
  font-family: var(--font-sans);
  font-size: var(--fs-base);
}
.input.textarea {
  /* Multi-line textareas grow with content (auto-resized by
     fn-form-fields.tsx) so the height + line-height that the single-
     line variants share don't apply. Reset to natural so the
     min-height 48 / max-height 160 govern. */
  height: auto;
  line-height: 1.5;
  padding: 8px 12px;
  min-height: 48px;
  max-height: 160px;
  resize: none;
  overflow-y: auto;
}
.inputError {
  border-color: var(--accent-red) !important;
}

.select {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23636d83'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
  padding-right: 30px;
  cursor: pointer;
}

/* Bool toggle */
.toggle {
  display: flex;
  align-items: center;
  gap: 8px;
}
/* Solid pill — no border. Idle state uses a low-opacity tint, hover
   bumps it a notch, active flips to the accent-blue tint that the
   send button uses. Same visual family as `.toolChip`. */
.toggleBtn {
  padding: 0 14px;
  height: 30px;
  line-height: 30px;
  border-radius: 999px;
  border: none;
  background: color-mix(in srgb, var(--text-secondary) 10%, transparent);
  color: var(--text-secondary);
  font-family: var(--font-sans);
  font-size: var(--fs-base);
  cursor: pointer;
  transition: background 180ms ease, color 180ms ease;
  user-select: none;
  box-sizing: border-box;
}
.toggleBtn:hover {
  background: color-mix(in srgb, var(--text-secondary) 18%, transparent);
  color: var(--text-primary);
}
.toggleBtn.toggleActive {
  background: color-mix(in srgb, var(--accent-blue) 18%, transparent);
  color: var(--accent-blue);
}
.toggleBtn.toggleActive:hover {
  background: color-mix(in srgb, var(--accent-blue) 26%, transparent);
}

/* Option chips */
.options {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.chip {
  padding: 0 14px;
  height: 30px;
  line-height: 30px;
  border-radius: 999px;
  border: none;
  background: color-mix(in srgb, var(--text-secondary) 10%, transparent);
  color: var(--text-secondary);
  font-family: var(--font-mono);
  font-size: var(--fs-base);
  cursor: pointer;
  transition: background 180ms ease, color 180ms ease;
  user-select: none;
  box-sizing: border-box;
}
.chip:hover {
  background: color-mix(in srgb, var(--text-secondary) 18%, transparent);
  color: var(--text-primary);
}
.chip.chipActive {
  background: color-mix(in srgb, var(--accent-blue) 18%, transparent);
  color: var(--accent-blue);
}
.chip.chipActive:hover {
  background: color-mix(in srgb, var(--accent-blue) 26%, transparent);
}
/* chipCustom is a text input alongside the option chips — same
   pill geometry. Idle state matches `.chip`'s tinted-fill so it
   visually reads as another chip in the row. When the user actually
   focuses it (about to type), it flips to a solid input look — solid
   `bg-primary` background + a 1px `text-secondary` border. */
.chipCustom {
  padding: 0 12px;
  height: 30px;
  line-height: 30px;
  border-radius: 999px;
  border: 1px solid transparent;
  background: color-mix(in srgb, var(--text-secondary) 10%, transparent);
  color: var(--text-primary);
  font-family: var(--font-mono);
  font-size: var(--fs-base);
  width: 60px;
  outline: none;
  transition: background 180ms ease, border-color 180ms ease;
  box-sizing: border-box;
}
.chipCustom:hover {
  background: color-mix(in srgb, var(--text-secondary) 18%, transparent);
}
.chipCustom:focus {
  background: var(--bg-primary);
  border-color: var(--accent-blue);
}

.noParams {
  color: var(--text-muted);
  font-family: var(--font-sans);
  font-size: var(--fs-base);
  padding: 4px 0;
}

/* workdir row — folder picker + path input. */
.workdirRow {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
}
.workdirBtn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 32px;
  padding: 0 12px;
  background: var(--bg-primary);
  border: 1px solid var(--border);
  border-radius: 8px;
  font-family: var(--font-sans);
  font-size: var(--fs-base);
  color: var(--text-primary);
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s, color 0.15s;
  white-space: nowrap;
  flex: 0 0 auto;
}
.workdirBtn svg {
  flex-shrink: 0;
  color: var(--text-secondary);
}
.workdirBtn:hover {
  border-color: var(--border-light);
  background: var(--bg-secondary);
  color: var(--text-bright);
}
.workdirInput {
  flex: 1 1 auto;
  height: 32px;
  padding: 0 12px;
  background: var(--bg-primary);
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text-bright);
  font-family: var(--font-mono);
  font-size: var(--fs-base);
  outline: none;
  transition: border-color 0.15s;
  min-width: 0;
}
.workdirInput:focus {
  border-color: var(--accent-blue);
}
.workdirInput::placeholder {
  color: var(--text-muted);
  font-family: var(--font-sans);
  font-size: var(--fs-base);
}
.workdirError {
  border-color: var(--accent-red) !important;
}
