/* * Setup wizard (src/ui/index.html) page styles. * Components come from relmio-ui.css. This file only lays out this page and * uses kit tokens; see DESIGN.md for the one-screen rule. */ /* Shell ------------------------------------------------------------------ */ .setup-layout { width: 100%; max-width: calc(var(--rm-content-width) + 2 * var(--rm-gutter)); margin-inline: auto; } /* The safety card and the Ready badges follow the panel in the DOM, so narrow screens show the step first. From 1024px they sit in the rail column under the stepper. The safety card closes on Ready, where the badges appear. */ @media (min-width: 64rem) { .setup-layout { grid-template-rows: auto minmax(0, 1fr); } .setup-rail { grid-area: 1 / 1; } .setup-content { grid-area: 1 / 2 / 3 / 3; } .setup-safety, .setup-layout > .rm-guide-finish { grid-area: 2 / 1; align-self: start; } } @media (min-width: 64rem) and (min-height: 37.5rem) { .setup-layout { padding-block: var(--rm-space-3); } /* The panel fills the column so the action bar keeps one position. */ .rm-app--fit .setup-panel { flex: 1 1 auto; } } /* Rail ------------------------------------------------------------------- */ .setup-safety { display: grid; gap: var(--rm-space-2); } .setup-safety .rm-status { align-items: flex-start; line-height: 1.45; } .setup-safety .rm-status__dot { margin-top: 0.375rem; } .operation-progress { display: grid; gap: var(--rm-space-2); padding: var(--rm-space-3) var(--rm-space-4); border: 1px solid var(--rm-accent-line); border-radius: var(--rm-radius-lg); background: var(--rm-surface); } .setup-progress__head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--rm-space-3); } .setup-progress__label { min-width: 0; color: var(--rm-ink); font-size: var(--rm-text-md); font-weight: 600; line-height: 1.4; } .setup-progress__elapsed { flex: none; color: var(--rm-ink-muted); font-family: var(--rm-font-mono); font-size: var(--rm-text-sm); font-variant-numeric: tabular-nums; } .setup-progress__note { color: var(--rm-ink-muted); font-size: var(--rm-text-sm); line-height: 1.45; } /* Panel, steps and views ------------------------------------------------- */ .setup-step, .setup-view { display: flex; flex: 1 1 auto; flex-direction: column; min-height: 0; } /* Shared action bar. Each step's actions sit in a group that shows only for the current step; the status line sits between secondary and primary. */ .setup-footer { flex: none; order: 2; } .setup-actions { display: none; } body[data-current-step="1"] [data-step-actions="1"], body[data-current-step="2"] [data-step-actions="2"], body[data-current-step="3"] [data-step-actions="3"], body[data-current-step="4"] [data-step-actions="4"], body[data-current-step="5"] [data-step-actions="5"] { display: contents; } @supports selector(:has(*)) { .setup-panel:has(#chatgpt-setup[hidden]) [data-subview="chatgpt"] { display: none; } /* Once ChatGPT is chosen the title names sign-in; the route prompt goes. */ .setup-step:has(#chatgpt-setup:not([hidden])) .rm-panel__heading > .rm-muted { display: none; } } .setup-message { order: 1; flex: 1 1 10rem; align-items: flex-start; line-height: 1.45; } .setup-message .rm-status__dot { margin-top: 0.375rem; } .setup-footer .rm-push, .setup-footer #stop-login-button { order: 2; } /* Review: the approval sits on its own row right above Back and Install. */ .setup-approval { flex: 1 1 100%; font-size: var(--rm-text-md); font-weight: 560; } /* The footer sticks to the bottom on narrow screens, so the status line takes its own row above the actions instead of splitting them. While an install runs the approval is locked; the plan and the progress card carry the state, so the footer shrinks to its actions and the step title stays in view. */ @media (max-width: 63.99rem) { .setup-message { order: -1; flex-basis: 100%; } body[data-operation-busy="true"] .setup-approval { display: none; } } /* Small phones: a tighter ghost Back fits beside the primary action. */ @media (max-width: 22.5rem) { .setup-footer .rm-button--ghost { padding-inline: var(--rm-space-2); } } /* Blocking errors. The callout comes first in the panel DOM. Below 1024px it shows just above the action bar and clears on the next action, so it has no close button that would sit out of tab order. From 1024px the panel is a grid and the callout sits in the header row beside the step title, which keeps the body height unchanged. */ .setup-error { order: 1; margin: 0 var(--rm-space-6) var(--rm-space-3); } .setup-error .rm-callout__content { color: var(--rm-ink); } @media (max-width: 63.99rem) { .setup-error .rm-callout__close { display: none; } } @media (min-width: 64rem) { .setup-panel { display: grid; grid-template-columns: minmax(0, 1fr) auto; grid-template-rows: auto minmax(0, 1fr) auto; } .setup-step { display: contents; } .setup-step > .rm-panel__header { grid-area: 1 / 1; } .setup-step > :not(.rm-panel__header) { grid-area: 2 / 1 / 3 / 3; } .setup-error { grid-area: 1 / 2; align-self: start; width: 18rem; margin: var(--rm-space-5) var(--rm-space-6) var(--rm-space-4) 0; } .setup-footer { grid-area: 3 / 1 / 4 / 3; } } /* From 1024 to 1279px the header is narrow, so the error takes its own full-width row under the step title, and the step label and hint step aside while it shows. */ @media (min-width: 64rem) and (max-width: 79.99rem) { .setup-panel { grid-template-rows: auto auto minmax(0, 1fr) auto; } .setup-step > .rm-panel__header { grid-area: 1 / 1 / 2 / 3; } .setup-step > :not(.rm-panel__header) { grid-area: 3 / 1 / 4 / 3; } .setup-error { grid-area: 2 / 1 / 3 / 3; width: auto; margin: 0 var(--rm-space-6) var(--rm-space-1); } .setup-footer { grid-area: 4 / 1 / 5 / 3; } .setup-panel:has(> .setup-error:not([hidden])) .rm-panel__heading > :not(.rm-h1) { display: none; } .setup-panel:has(> .setup-error:not([hidden])) .setup-step > .rm-panel__header { padding-bottom: 0; } /* The status line takes its own row above the actions while an error shows, instead of wrapping into a tall column between the buttons. */ .setup-panel:has(> .setup-error:not([hidden])) .setup-message { order: -1; flex-basis: 100%; } } @media (min-width: 80rem) { .setup-error { width: 26rem; } } /* Shared pieces ---------------------------------------------------------- */ .setup-warning { display: flex; align-items: flex-start; gap: var(--rm-space-2); color: var(--rm-warning); font-size: var(--rm-text-md); font-weight: 560; line-height: 1.45; } .setup-warning .rm-icon { margin-top: 0.125rem; } .setup-values { align-items: center; row-gap: var(--rm-space-1); } .setup-value { display: flex; align-items: center; gap: var(--rm-space-2); min-width: 0; } .setup-value > code { min-width: 0; } .setup-value--block { align-items: flex-start; } .setup-code { flex: 1 1 auto; min-width: 0; margin: 0; padding: var(--rm-space-3); border: 1px solid var(--rm-terminal-line); border-radius: var(--rm-radius-md); background: var(--rm-terminal-bg); color: var(--rm-terminal-fg); font-size: var(--rm-text-sm); line-height: 1.5; white-space: pre-wrap; overflow-wrap: anywhere; } /* Step 1: choose a route ------------------------------------------------- */ .setup-routes { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr)); gap: var(--rm-space-3) var(--rm-space-4); } .setup-route { display: grid; grid-row: span 2; grid-template-rows: subgrid; row-gap: var(--rm-space-1); min-width: 0; } /* Cards in a row share its height; their text stays together at the top. */ .setup-route > .rm-choice { align-content: start; } /* Five routes fit two rows on laptops; descriptions use the card's full width. */ @media (min-width: 64rem) { #setup-choices > .rm-panel__body { gap: var(--rm-space-2); padding-bottom: var(--rm-space-2); } .setup-routes { grid-template-columns: repeat(6, minmax(0, 1fr)); row-gap: var(--rm-space-2); } .setup-route { grid-column: span 2; } .setup-route:nth-last-child(-n + 2) { grid-column: span 3; grid-row: span 1; } .setup-route > .rm-choice { padding-block: var(--rm-space-3); } .setup-route .rm-choice__icon { grid-row: 1; } .setup-route .rm-choice__text, .setup-route .rm-choice__meta { grid-column: 1 / -1; } } .setup-route .rm-choice__title .rm-badge { margin-inline-start: var(--rm-space-1); vertical-align: 0.0625rem; } .setup-route .rm-disclosure--plain > summary { min-height: 2rem; font-size: var(--rm-text-md); } .setup-hosting { display: flex; flex-wrap: wrap; gap: var(--rm-space-1) var(--rm-space-2); } .setup-subhead { display: grid; gap: var(--rm-space-2); } .setup-subhead > p { max-width: var(--rm-reading-width); } .setup-auth__dot { margin-top: 0.4375rem; } .setup-auth__dot.ready { background: var(--rm-success); } .setup-auth:has(.setup-auth__dot.ready) { --rm-tone: var(--rm-success); --rm-tone-soft: var(--rm-success-soft); --rm-tone-line: var(--rm-success-line); } .setup-signin__column { display: grid; align-content: start; gap: var(--rm-space-4); min-width: 0; } /* From 1024px the explanation and status sit beside the account card, so the view fits one screen. Each column keeps its own DOM order. */ @media (min-width: 64rem) { .setup-signin { display: grid; grid-template-columns: minmax(0, 4fr) minmax(0, 5fr); align-items: start; column-gap: var(--rm-space-6); } } /* Step 2: check the server ----------------------------------------------- */ .setup-server-row, .setup-signin-row { display: grid; align-items: start; gap: var(--rm-space-3) var(--rm-space-4); } .setup-server-row { grid-template-columns: minmax(0, 1fr) 10rem auto; } /* Lines the button up with the inputs: label line plus field gap. */ .setup-server-row__check { min-height: 2.75rem; margin-top: calc(var(--rm-text-md) * 1.55 + 0.375rem); } .setup-signin-row { grid-template-columns: minmax(0, 13rem) minmax(0, 12rem) minmax(0, 1fr); } .setup-signin-row__agent { grid-column: 1 / -1; } @supports selector(:has(*)) { .setup-signin-row__agent { display: none; } .setup-signin-row:has(option[value="agent"]:checked) .setup-signin-row__password { display: none; } .setup-signin-row:has(option[value="agent"]:checked) .setup-signin-row__agent { display: block; grid-column: auto; padding-top: calc(var(--rm-text-md) * 1.55 + 0.375rem); } } .setup-fingerprint__label { display: block; font-weight: 600; } .setup-fingerprint__value { display: block; margin-top: var(--rm-space-1); } .setup-fingerprint__name { color: var(--rm-ink-muted); font-size: var(--rm-text-sm); } .setup-signin-notes { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0 var(--rm-space-4); } .setup-signin-notes > details[open] { flex-basis: 100%; } .setup-session { flex: 1 1 20rem; min-width: 0; color: var(--rm-ink-muted); font-size: var(--rm-text-sm); overflow-wrap: anywhere; } .setup-session:empty { display: none; } /* Step 3: choose n8n ----------------------------------------------------- */ .setup-n8n-fields { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr)); align-items: start; gap: var(--rm-space-4); } .setup-n8n-details > summary { min-height: 1.75rem; font-size: var(--rm-text-sm); } .setup-manage { display: grid; gap: var(--rm-space-2); padding-top: var(--rm-space-3); border-top: 1px solid var(--rm-line); } .setup-manage__head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: var(--rm-space-1) var(--rm-space-4); } .setup-manage__intro { flex-basis: 100%; } .setup-manage__options { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 12rem), 1fr)); gap: var(--rm-space-3); } .setup-manage__actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--rm-space-2) var(--rm-space-3); } /* The installed-session and recovery disclosures share a row from 1024px, so step 3 fits one screen while both are closed. */ @media (min-width: 64rem) { .setup-manage { grid-template-columns: repeat(2, minmax(0, 1fr)); align-items: start; } .setup-manage > :not(#vps-siwc-owner, #vps-siwc-recovery) { grid-column: 1 / -1; } } /* Step 4: review --------------------------------------------------------- */ .setup-review-facts { grid-template-columns: max-content minmax(0, 1fr) max-content minmax(0, 1fr); } .setup-review-facts__server > dd { grid-column: 2 / -1; } .setup-review-lists { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 4fr); gap: var(--rm-space-4) var(--rm-space-6); } .setup-review-lists section { display: grid; align-content: start; gap: var(--rm-space-2); } .setup-list { display: grid; gap: var(--rm-space-1); margin: 0; padding: 0; font-size: var(--rm-text-sm); line-height: 1.45; list-style: none; } .setup-list:empty { display: none; } /* Plan warnings from the server, one sentence per line. */ .setup-warnings { margin: 0; padding: 0; list-style: none; } .setup-host-key { overflow-wrap: anywhere; } .setup-list > li { position: relative; padding-inline-start: 1.5rem; overflow-wrap: anywhere; } .setup-list > li::before { position: absolute; top: 0.125rem; left: 0; width: 1rem; height: 1rem; background-color: currentColor; content: ""; } .setup-list--will > li::before { color: var(--rm-success); -webkit-mask: var(--rm-icon-check) center / contain no-repeat; mask: var(--rm-icon-check) center / contain no-repeat; } .setup-list--wont > li::before { color: var(--rm-danger); -webkit-mask: var(--rm-icon-x) center / contain no-repeat; mask: var(--rm-icon-x) center / contain no-repeat; } /* Step 5: ready ---------------------------------------------------------- */ .setup-done-eyebrow .rm-icon { color: var(--rm-success); } .setup-results { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); align-items: start; gap: var(--rm-space-4) var(--rm-space-6); } .setup-results__main, .setup-results__side, .setup-settings { display: grid; align-content: start; gap: var(--rm-space-2); min-width: 0; } .setup-results__head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--rm-space-2) var(--rm-space-3); margin-bottom: var(--rm-space-2); } .setup-assistant-result { display: grid; gap: var(--rm-space-3); } /* The values stack label over value, so long URLs and keys get the full column width instead of the space left beside a long label. */ .setup-assistant-result .setup-values { grid-template-columns: minmax(0, 1fr); row-gap: 0.125rem; } .setup-assistant-result .setup-values dd { margin-bottom: var(--rm-space-2); } /* From 1024 to 1279px each result column is narrow. The base URL and key take the full column under their labels, so they wrap less; the short rows keep label and value side by side. The heading wraps beside Copy all instead of pushing it to its own row. Together this keeps step 5 on one screen when a held key adds its warning. */ @media (min-width: 64rem) and (max-width: 79.99rem) { .setup-results__main .setup-values :is(dt:has(+ dd.setup-value), dd.setup-value) { grid-column: 1 / -1; } .setup-results__main .setup-values dd.setup-value { margin-bottom: var(--rm-space-1); } .setup-results__head > .rm-h3 { flex: 1 1 10rem; min-width: 0; } } /* The stacked values need less width than the settings block. */ @media (min-width: 64rem) { .setup-assistant-result .setup-results { grid-template-columns: minmax(0, 2fr) minmax(0, 3fr); } } /* Narrow screens --------------------------------------------------------- */ @media (max-width: 63.99rem) { .setup-results { grid-template-columns: minmax(0, 1fr); } } @media (max-width: 47.99rem) { .setup-server-row { grid-template-columns: minmax(0, 1fr) auto; } .setup-server-row__host { grid-column: 1 / -1; } .setup-signin-row { grid-template-columns: minmax(0, 1fr); } .setup-review-lists { grid-template-columns: minmax(0, 1fr); } .setup-review-facts { grid-template-columns: max-content minmax(0, 1fr); } .setup-review-facts__server > dd { grid-column: auto; } } @media (max-width: 30rem) { .setup-review-facts { grid-template-columns: minmax(0, 1fr); } } @media (forced-colors: active) { .setup-list > li::before { background-color: CanvasText; forced-color-adjust: none; } }