/* Launch console. See static/components/launch_console.js. */

.launch-console {
  background: var(--surface);
  border: 1px solid var(--border);
  position: relative;
}

/* ---- head ---------------------------------------------------------------- */
.console-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-4) var(--panel-padding);
  border-bottom: 1px solid var(--border);
  background: var(--surface-inset);
}

.console-title {
  font-size: var(--text-base);
  font-weight: 600;
  letter-spacing: var(--tracking-eyebrow);
  color: var(--text-muted);
}

/* ---- customize switch ----------------------------------------------------
   Replaces the old Quick/Advanced tab pair. Two tabs implied two separate forms
   and lost your place when you crossed between them; a switch says the same
   form has more of itself to show. */
.cust-switch {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  cursor: pointer;
  user-select: none;
}

.cust-track {
  position: relative;
  width: 38px;
  height: 18px;
  flex: 0 0 auto;
  background: var(--surface);
  border: 1px solid var(--border-control);
  transition: border-color var(--dur-fast) var(--ease-out),
              background var(--dur-fast) var(--ease-out);
}

.cust-knob {
  position: absolute;
  top: 2px;
  left: 2px;
  width: 12px;
  height: 12px;
  background: var(--text-muted);
  transition: transform var(--dur-base) var(--ease-out),
              background var(--dur-fast) var(--ease-out);
}

.cust-switch.is-on .cust-track { border-color: var(--graph); background: var(--graph-soft); }
.cust-switch.is-on .cust-knob { transform: translateX(20px); background: var(--graph); }

.cust-label {
  font-family: var(--font-display);
  font-size: var(--text-sm);
  font-weight: 600;
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--text-muted);
}
.cust-switch.is-on .cust-label { color: var(--text); }

/* The real input is visually hidden but focusable; the ring is drawn on the
   track so keyboard focus is unmistakable. */
.cust-switch:has(.spec-radio:focus-visible) .cust-track {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
}

.launch-body {
  padding: var(--panel-padding);
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
}

/* ---- GPU count cards ----------------------------------------------------- */
.spec-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 180px), 1fr));
  gap: var(--space-3);
}

.spec-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-4);
  border: 1px solid var(--border);
  background: var(--surface);
  cursor: pointer;
  transition: border-color var(--dur-fast) var(--ease-out),
              background var(--dur-fast) var(--ease-out);
}
.spec-card:hover { border-color: var(--border-emphasis); }

.spec-card.is-selected {
  border-color: var(--graph);
  background: var(--graph-soft);
}

.spec-card.is-disabled {
  cursor: not-allowed;
  color: var(--text-subtle);
  background: var(--surface-inset);
  opacity: 0.55;
}
.spec-card.is-disabled:hover { border-color: var(--border); }

/* Corner brackets mark the selected card. Drawn with pseudo-elements rather
   than clip-path BECAUSE clip-path clips the focus ring — verified in-browser.
   Two L-shaped corners read as a targeting reticle without touching the box. */
.spec-card.is-selected::before,
.spec-card.is-selected::after {
  content: "";
  position: absolute;
  width: 9px;
  height: 9px;
  border-color: var(--graph);
  border-style: solid;
  pointer-events: none;
}
.spec-card.is-selected::before {
  top: -1px; left: -1px;
  border-width: 2px 0 0 2px;
}
.spec-card.is-selected::after {
  bottom: -1px; right: -1px;
  border-width: 0 2px 2px 0;
}

/* ---- static (Customize off) ---------------------------------------------
   One card, no choice: it is a readout of what will launch, not a control. No
   pointer and no hover lift, because nothing happens when you click it. It
   keeps the selected border and brackets, since it IS the selection. */
.spec-card.is-static { cursor: default; }
.spec-card.is-static:hover { border-color: var(--graph); }

/* Full width when it stands alone — a lone card sized for a 4-up grid looks
   like the other three failed to load. */
.spec-grid:has(.spec-card.is-static) { grid-template-columns: 1fr; }
.spec-card.is-static {
  flex-direction: row;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
}
.spec-card.is-static .spec-head { flex: 0 1 auto; gap: var(--space-4); }

/* The radio is the real control — it carries keyboard and screen-reader
   behaviour. Visually hidden rather than display:none, which would remove it
   from the accessibility tree along with the tab order. */
.spec-radio {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
}
.spec-card:has(.spec-radio:focus-visible) {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
}

.spec-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
}
.spec-name {
  font-family: var(--font-display);
  font-size: var(--text-lg);
  font-weight: 700;
  letter-spacing: var(--tracking-display);
  text-transform: uppercase;
  /* "2 GPUs" is one label. Without this it breaks after the numeral on a narrow
     card, leaving a stranded digit above the word. */
  white-space: nowrap;
}

.spec-lines { display: flex; flex-direction: column; gap: 2px; }
.spec-line { font-size: var(--text-sm); color: var(--text-muted); }

/* ---- memory options ------------------------------------------------------
   Segmented rather than a dropdown: there are exactly two, and a dropdown would
   hide half the choice behind a click while occupying the same space. */
.mem-row { display: flex; gap: var(--space-3); flex-wrap: wrap; }

.mem-opt {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 132px;
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--border);
  background: var(--surface);
  cursor: pointer;
  transition: border-color var(--dur-fast) var(--ease-out),
              background var(--dur-fast) var(--ease-out);
}
.mem-opt:hover { border-color: var(--border-emphasis); }
.mem-opt.is-selected { border-color: var(--graph); background: var(--graph-soft); }
.mem-opt:has(.spec-radio:focus-visible) {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
}

.mem-value {
  font-family: var(--font-display);
  font-size: var(--text-lg);
  font-weight: 700;
  line-height: 1.1;
}
.mem-unit {
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--text-muted);
  margin-left: 2px;
}
.mem-credits { font-size: var(--text-xs); color: var(--text-muted); }

/* ---- fields --------------------------------------------------------------- */
.advanced-fields {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
  padding-top: var(--space-5);
  border-top: 1px dashed var(--border);
  /* Revealed by the Customize switch. Fill-mode none: the resting state is
     visible, so if the animation never runs the fields still appear. */
  animation: rc-fade-in var(--dur-base) var(--ease-out) none;
}

.field { display: flex; flex-direction: column; gap: var(--space-2); min-width: 0; }
.inference-model-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: var(--space-3);
  align-items: center;
}
.inference-model-row .btn {
  min-height: 40px;
  white-space: nowrap;
}
.field-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr));
  gap: var(--space-4);
}
.field-label {
  font-family: var(--font-display);
  font-size: var(--text-sm);
  font-weight: 600;
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--text-muted);
}
.field-help {
  margin: 0;
  font-size: var(--text-sm);
  color: var(--text-subtle);
  line-height: var(--leading-snug);
}
.field-empty {
  margin: 0;
  padding: var(--space-5);
  border: 1px dashed var(--border);
  color: var(--text-muted);
  font-size: var(--text-sm);
  text-align: center;
}

/* ---- footer ------------------------------------------------------------- */
.launch-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-4) var(--panel-padding);
  border-top: 1px solid var(--border);
  background: var(--surface-inset);
  flex-wrap: wrap;
}
.launch-summary {
  margin: 0;
  font-size: var(--text-sm);
  color: var(--text-muted);
  letter-spacing: 0.02em;
}
.launch-blocked {
  margin: 0;
  padding: 0 var(--panel-padding) var(--space-4);
  font-size: var(--text-sm);
  color: var(--attention);
  background: var(--surface-inset);
}

@media (max-width: 640px) {
  .launch-body { padding: var(--space-4); }
  .console-head { padding: var(--space-3) var(--space-4); }
  .launch-foot { flex-direction: column; align-items: stretch; }
  .launch-foot .btn { width: 100%; }
  /* One card per row on a phone. Two 150px columns left each card too narrow
     for its label plus lattice, so the lattice pushed the name into a wrap. */
  .spec-grid { grid-template-columns: 1fr; }
  .spec-card { flex-direction: row; align-items: center; justify-content: space-between; }
  .spec-head { flex: 1 1 auto; }
  .mem-opt { flex: 1 1 auto; min-width: 0; }
  .spec-card, .spec-card.is-static { flex-wrap: wrap; }
  .spec-lines { min-width: 0; overflow-wrap: anywhere; }
  .console-head { flex-wrap: wrap; }
  .inference-model-row { grid-template-columns: 1fr; }
  .inference-model-row .btn { width: 100%; }
}
