/* Connections, and Connect your compute (the same page under the first-run title, pages/connect.css): the providers
   Portal may run on, what to ask Claude Code, the secrets and the import, laid out as Supabase lays out integrations:
   a list, never a card wall. Each group is a panel as on every page (a rule of ink, its title on the rule's line,
   its one action at the head's end) and its rows sit on hairlines. Each provider wears its line, the colour it has
   on every run's path: solid once connected, dotted while it is only available. A cap is a plain meter beside its
   figures, never a path. The page's rules are under .conn-page (both pages' content); the connection sheet is a
   dialog outside the page, so its rules are under .conn-sheet. Tokens from styles.css only. */

.conn-page { gap: 40px; }
.conn-page .conn-section { display: grid; grid-template-columns: minmax(0, 1fr); }
.conn-page .conn-section > .panel-head { align-items: center; }

/* the lists: one row per provider, one per secret, on hairlines. A provider's facts read across: its name, its
   state, what it has spent of its cap, its one action. */
.conn-page .conn-list { display: grid; grid-template-columns: minmax(0, 1fr); }
.conn-page .conn-row {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 16rem) minmax(0, 16rem) 6.5rem;
  align-items: center; column-gap: 24px; padding: 13px 0; min-height: 64px; border-bottom: 1px solid var(--rule);
}
.conn-page .conn-row:last-child { border-bottom: 0; }
/* the line hangs before the name, on the name's line; the sentence under the name starts where the name does */
.conn-page .conn-main {
  display: grid; grid-template-columns: 18px minmax(0, 1fr); align-items: center; column-gap: 12px; min-width: 0;
}
.conn-page .conn-main > .pline { grid-row: 1; }
.conn-page .conn-name {
  grid-column: 2; font-size: 14.5px; font-weight: 550; line-height: 1.4;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.conn-page .conn-product { grid-column: 2; font-size: 13px; line-height: 1.45; color: var(--ink-2); }
.conn-page .conn-state,
.conn-page .conn-spend { display: grid; gap: 4px; justify-items: start; min-width: 0; }
.conn-page .conn-detail { font-size: 12.5px; line-height: 1.45; color: var(--ink-2); text-wrap: pretty; }
.conn-page .conn-sub { font-size: 12.5px; line-height: 1.45; color: var(--ink-3); font-variant-numeric: tabular-nums; }
.conn-page .conn-spend { font-size: 13.5px; }
.conn-page .conn-cap { display: inline-flex; align-items: center; gap: 10px; white-space: nowrap; }
.conn-page .conn-reached { color: var(--warn); font-weight: 550; padding-left: 66px; }
.conn-page .conn-action { display: flex; justify-content: flex-end; }
.conn-page .conn-none { padding: 16px 0; color: var(--ink-2); }

/* a secret: its name as a run asks for it, its one action quiet at the row's end */
.conn-page .conn-secret { grid-template-columns: minmax(0, 1fr) auto; min-height: 48px; padding: 8px 0; }
.conn-page .conn-secret-name { font-size: 13px; overflow-wrap: anywhere; }
/* the quiet action's word ends on the list's edge, where the buttons above end */
.conn-page .conn-secret .btn-ghost { margin-right: -10px; }

/* a group whose head is a disclosure (what to ask Claude Code, the import): its words, then the caret a select wears
   right after them */
.conn-page :is(.conn-agent, .conn-import) > summary { align-items: center; justify-content: flex-start; gap: 10px; cursor: pointer; list-style: none; }
.conn-page :is(.conn-agent, .conn-import) > summary::-webkit-details-marker { display: none; }
.conn-page :is(.conn-agent, .conn-import) > summary:focus-visible { outline-offset: 2px; }
@media (hover: hover) { .conn-page :is(.conn-agent, .conn-import) > summary:hover .panel-title { text-decoration: underline; text-decoration-color: var(--ink-4); text-underline-offset: 4px; } }
.conn-page .conn-caret {
  flex: none; width: 10px; height: 5px; margin-right: 6px;
  background-image: linear-gradient(45deg, transparent 50%, var(--ink-2) 50%), linear-gradient(135deg, var(--ink-2) 50%, transparent 50%);
  background-position: 0 0, 5px 0; background-size: 5px 5px; background-repeat: no-repeat;
  transition: transform var(--speed) ease-out;
}
.conn-page details[open]:not([data-motion="closing"]) > summary .conn-caret { transform: rotate(180deg); }

/* what to ask Claude Code: one sentence, then the console's steps (styles.css .steps), then the command that does the
   same from a terminal; the prompt reads as words to say (a quotation in the text face) with its own Copy after it */
.conn-page .conn-agent-body { display: grid; grid-template-columns: minmax(0, 1fr); gap: 14px; padding: 2px 0 4px; }
.conn-page .conn-agent-about { color: var(--ink-2); max-width: 72ch; }
.conn-page .conn-agent .steps { margin-top: 4px; }
.conn-page .conn-detect { display: grid; gap: 6px; padding-top: 14px; border-top: 1px solid var(--rule); }
.conn-page .conn-detect > p { color: var(--ink-2); }
/* the prompt is words to say, not a command: no "$" and no line under it, its Copy on the commands' right edge */
.conn-page .conn-prompt { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; width: 100%; max-width: none; }
.conn-page .conn-prompt q { font-size: 14px; color: var(--ink); padding: 3px 0; }
.conn-page .conn-prompt .copy-btn { margin-right: -4px; padding: 0 4px; }  /* its word on the commands' edge */

/* import: its form is the sheet's: a label, the field and a note in the margin; the button and the outcome on the
   fields' edge */
.conn-page .conn-import-body { display: grid; grid-template-columns: minmax(0, 1fr); gap: 18px; padding: 10px 0 4px; max-width: 800px; }
.conn-page .conn-import-body .unit-input input { width: 120px; }
.conn-page .conn-import-actions { display: flex; gap: 8px; padding-left: 154px; }
.conn-page .conn-import-out { padding-top: 14px; border-top: 1px solid var(--rule); }
.conn-page .conn-import-out:empty { display: none; }
.conn-page .conn-import-out .kv { grid-template-columns: 136px minmax(0, 1fr); column-gap: 18px; }

@media (max-width: 899px) {
  /* the name and the action on the first line; the state and the spend under the name */
  .conn-page .conn-row {
    grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "main action" "state state" "spend spend";
    align-items: start; row-gap: 10px; column-gap: 12px; padding: 14px 0;
  }
  .conn-page .conn-main { grid-area: main; padding-top: 2px; }
  .conn-page .conn-state { grid-area: state; padding-left: 30px; }
  .conn-page .conn-spend { grid-area: spend; padding-left: 30px; }
  .conn-page .conn-action { grid-area: action; }
  .conn-page .conn-state:empty, .conn-page .conn-spend:empty { display: none; }
  .conn-page .conn-secret { grid-template-areas: none; grid-template-rows: auto; align-items: center; padding: 6px 0; }
}
@media (max-width: 699px) {
  .conn-page .conn-import-actions { padding-left: 0; }
  .conn-page .conn-import-out .kv { grid-template-columns: max-content minmax(0, 1fr); }
}

/* ---------------------------------------------------------------- the connection sheet (a dialog, outside the page) */

/* What is not a field (where the values come from, a line about the fields) starts on the fields' edge: the label
   column and its gap. Below 700px the labels sit over their fields and everything starts at the left. */
.conn-sheet .conn-aside { margin-left: 154px; }
.conn-sheet .how { gap: 8px; }
.conn-sheet .conn-route-sep { color: var(--ink-3); }
.conn-sheet .unit-input input { width: 120px; }
/* a cap typed under what the connection's running machines need: its note says what follows, in the warning's ink */
.conn-sheet .help.text-warn { color: var(--warn); }

/* the steps after Verify and save: stations on one line, each wearing its state's glyph (a ring while it runs or
   waits, a cross where it failed; a step done is its word in ink), the line in ink as far as they got */
.conn-sheet .conn-steps { display: flex; flex-wrap: wrap; align-items: center; row-gap: 8px; color: var(--ink-3); font-size: 13.5px; }
.conn-sheet .conn-step { display: inline-flex; align-items: center; gap: 7px; white-space: nowrap; }
.conn-sheet .conn-step + .conn-step::before { content: ""; flex: none; width: 22px; height: 1.5px; margin: 0 3px 0 10px; background: var(--rule-2); }
.conn-sheet .conn-step[data-state="done"] + .conn-step::before { background: var(--ink); }
.conn-sheet .conn-step[data-state="done"], .conn-sheet .conn-step[data-state="running"] { color: var(--ink); }
.conn-sheet .conn-step[data-state="failed"] { color: var(--bad); }
.conn-sheet .conn-step[data-state="todo"] .glyph { color: var(--ink-4); }
.conn-sheet .conn-step[data-state="running"] .glyph { animation: conn-pulse 1.1s ease-in-out infinite; }
@keyframes conn-pulse { 0%, 100% { opacity: .3; } 50% { opacity: 1; } }
.conn-sheet .conn-done { gap: 14px; }
/* why the connection is not well, under its facts: a sentence between hairlines, as everywhere */
.conn-sheet .sheet-section > .kv + .notice { margin-top: 4px; }

@media (max-width: 699px) {
  .conn-sheet .conn-aside { margin-left: 0; }
}

/* ---------------------------------------------------------------- your machines, and a further connection */

/* Add connection's picker opens under its button, at the page's edge: each cloud's line (dotted, not connected yet),
   its name, then what it runs in its rows' words, in columns; on a phone what it runs wraps under its own column */
.conn-page .page-actions .conn-add .menu-list { min-width: 300px; max-width: min(460px, calc(100vw - 32px)); }
@media (max-width: 599px) {
  .conn-add .menu-item[data-sub] { height: auto; min-height: 44px; padding-top: 6px; padding-bottom: 6px; white-space: normal; }
  .conn-add .menu-item-sub { min-width: 0; line-height: 1.35; }
  .conn-add .menu-item[data-sub] > .menu-item-label { min-width: 88px; }
}

/* a further connection's name: the cloud's part fixed before what is typed, as a cap's "$" */
.conn-sheet .conn-label-input { display: flex; align-items: baseline; gap: 0; }
.conn-sheet .conn-label-input .unit { font-size: 13px; color: var(--ink-2); }
.conn-sheet .conn-label-input input { flex: 1; width: auto; min-width: 0; max-width: 200px; padding-left: 1px; }

/* after a save: the command that runs on the new connection, then the once-per-machine steps folded under a quiet
   line that opens them */
.conn-sheet .conn-next { display: grid; gap: 10px; padding-top: 6px; }
.conn-sheet .conn-quota-prompt { display: flex; align-items: flex-start; gap: 12px; }
.conn-sheet .conn-quota-prompt q { flex: 1; min-width: 0; overflow-wrap: anywhere; }
.conn-sheet .conn-quota-prompt .copy-btn { flex-shrink: 0; }
.conn-sheet .conn-once > summary {
  display: inline-flex; align-items: center; gap: 10px; cursor: pointer; list-style: none; color: var(--ink-2);
  font-size: 13px; padding: 4px 0;
}
.conn-sheet .conn-once > summary::-webkit-details-marker { display: none; }
@media (hover: hover) { .conn-sheet .conn-once > summary:hover { color: var(--ink); } }
.conn-sheet .conn-caret {
  flex: none; width: 10px; height: 5px;
  background-image: linear-gradient(45deg, transparent 50%, var(--ink-2) 50%), linear-gradient(135deg, var(--ink-2) 50%, transparent 50%);
  background-position: 0 0, 5px 0; background-size: 5px 5px; background-repeat: no-repeat;
  transition: transform var(--speed) ease-out;
}
.conn-sheet .conn-once[open]:not([data-motion="closing"]) > summary .conn-caret { transform: rotate(180deg); }
.conn-sheet .conn-once .steps { margin-top: 8px; }

/* a machine's row is a connection's: under its name two fixed lines, what it reported of its hardware and the user its
   runs run as (ui.js facts); its state, with how long it has been away, when a waiting one is removed or the run on
   it now; its price, the owner's estimate, said as such */
:is(.conn-page, .conn-sheet) .mach-state { display: inline-flex; align-items: baseline; gap: 6px; flex-wrap: wrap; }
:is(.conn-page, .conn-sheet) .mach-since { font-size: 13.5px; color: var(--ink-3); font-variant-numeric: tabular-nums; }
.conn-page .mach-row .conn-product { padding-top: 1px; }
.conn-page .mach-row .conn-product + .conn-product { padding-top: 0; }
.conn-page .mach-running a { color: var(--ink-2); }
/* the first-run page's offer of a machine has no state or spend: its sentence runs across their columns */
@media (min-width: 900px) {
  .conn-page .conn-offer .conn-main { grid-column: 1 / span 3; }
  .conn-page .conn-offer .conn-action { grid-column: 4; }
}
.conn-page .mach-row .facts { column-gap: 12px; }
.conn-page .mach-price { white-space: nowrap; }
.conn-page .mach-estimate, .conn-page .mach-noprice { color: var(--ink-3); }
/* on a phone a machine with no price set says nothing of it: a row's lines are its own */
@media (max-width: 599px) { .conn-page .mach-row .conn-spend:has(> .mach-noprice:only-child) { display: none; } }

/* a machine's sheet: each part's title with "Reported by the machine" at its end where the facts are the machine's */
.conn-sheet .mach-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.conn-sheet .mach-reported {
  font-size: 12.5px; color: var(--ink-3); font-stretch: var(--label-stretch); font-weight: 500; white-space: nowrap;
}
/* a line of facts in a sheet (ui.js facts): hardware, the user's privilege; where it is reads quieter */
.conn-sheet .mach-line { font-size: 13.5px; line-height: 1.6; }
.conn-sheet .mach-line .facts { row-gap: 2px; }
.conn-sheet .mach-quiet { color: var(--ink-2); font-size: 13px; }
/* who runs there: the sentence (in the warning's ring only when a run could do anything there), then who may send runs */
.conn-sheet .mach-trust { display: grid; gap: 6px; }
.conn-sheet .mach-trust > p:first-child { color: var(--ink); }
/* what a run there could do beyond its user (sudo without a password, the docker group): the warning's ink */
.conn-sheet .mach-risk { color: var(--warn); font-weight: 600; }
/* steps that open a sheet's body need no rule of their own under the sheet's head */
.conn-sheet .sheet-body > .steps:first-child { border-top: 0; }
.conn-sheet .sheet-body > .steps:first-child > .step:first-child { padding-top: 0; }
/* a step done folds to one line: its words quiet, its number in ink */
.conn-sheet .step[data-done] .step-body > p { color: var(--ink-2); }
/* the code the machine printed, typed in the figures a terminal's code is shown in */
.conn-sheet .mach-code {
  height: 44px; max-width: 240px; padding: 0 2px; font-size: 22px; font-weight: 600; letter-spacing: .06em;
  text-transform: uppercase; font-variant-numeric: tabular-nums;
}
.conn-sheet .mach-code::placeholder { font-weight: 500; letter-spacing: .04em; }
/* who the command installs for: its label in the label cut, the choice as words */
.conn-sheet .mach-for { display: flex; align-items: center; flex-wrap: wrap; gap: 4px 14px; margin-top: -6px; }
.conn-sheet .mach-for-label { font-size: 13px; color: var(--ink-3); font-stretch: var(--label-stretch); font-weight: 500; }
/* the command waiting for its machine: a ring that breathes, as a setup under way */
.conn-sheet .mach-wait { display: inline-flex; align-items: center; gap: 9px; color: var(--ink-2); }
.conn-sheet .mach-wait .glyph { color: var(--ink-3); animation: conn-pulse 1.1s ease-in-out infinite; }
.conn-sheet .mach-wait + .help { margin-top: -6px; }
.conn-sheet .mach-expires { margin-top: -4px; }
/* the footer's start: a quiet action (Cancel the command), or a refusal beside the button it answers. The buttons
   keep their row: the refusal wraps beside them, and on a phone takes the line above them. */
.conn-sheet .mach-foot { flex: 1 1 0; min-width: 0; }
.conn-sheet .sheet-foot:has(> .mach-foot) > .sheet-actions { flex: none; }
.conn-sheet .mach-foot .field-error { line-height: 1.4; }
.conn-sheet .mach-cancel { font-size: 13px; color: var(--ink-2); font-weight: 500; }
/* one Remove, its reason beside it; Revoke now a quiet line under it */
.conn-sheet .mach-danger { gap: 10px; }
.conn-sheet .mach-danger .btn { min-width: 96px; }
.conn-sheet .mach-remove { flex-wrap: nowrap; align-items: baseline; column-gap: 12px; }
.conn-sheet .mach-remove .help a { color: var(--ink-2); }
.conn-sheet .mach-revoke .btn-link { font-size: inherit; color: var(--ink-2); }
@media (prefers-reduced-motion: reduce) { .conn-sheet .mach-wait .glyph { animation: none; } }
@media (max-width: 699px) {
  /* a machine's facts come in several lists: one label column for all of them, a long label wrapping in it */
  .conn-sheet.mach-sheet .kv { grid-template-columns: 112px minmax(0, 1fr); column-gap: 14px; }
}
@media (max-width: 599px) {
  /* each reason under its button */
  .conn-sheet .mach-remove { flex-direction: column; align-items: flex-start; row-gap: 6px; }
  .conn-sheet .sheet-foot:has(> .mach-foot .field-error) { flex-wrap: wrap; row-gap: 10px; }
  .conn-sheet .sheet-foot:has(> .mach-foot .field-error) > .mach-foot { flex-basis: 100%; }
}
