/* mobius.you — signed-in surfaces.
   Design system first (tokens, primitives, components), then the three page
   blocks (composer, dashboard, connect), then the rules the routes that were
   not redesigned still depend on. The public landing page styles itself in
   home.css; everything here is either shared chrome or signed-in surface. */

:root {
  color-scheme: dark;

  /* Surfaces — layered instead of flat. Each step is a real, visible tier. */
  --bg:         #08080a;
  --surface-1:  #0e0e11;
  --surface-2:  #141419;
  --surface-3:  #1b1b21;
  --hairline:   rgba(255, 255, 255, 0.07);
  --hairline-2: rgba(255, 255, 255, 0.11);

  /* Ink */
  --ink:        #f4f2f7;
  --ink-2:      #a8a4b0;
  /* 5.11:1 on the darkest surface it is used against. The previous
     #6f6b78 measured 3.31-3.86:1 across the four tiers — under AA for
     normal text, and this token carries every hint, unit and caption. */
  --ink-3:      #8f8a99;

  /* Accent — violet stays, copper comes from the brand mark */
  --violet:     #9b82ff;
  --violet-hi:  #b3a0ff;
  --violet-lo:  #7c5df0;
  --violet-dim: rgba(155, 130, 255, 0.14);
  --copper:     #e8a87c;

  /* Status */
  --ok:         #34d399;
  --ok-dim:     rgba(52, 211, 153, 0.13);
  --warn:       #f2c879;
  --warn-dim:   rgba(242, 200, 121, 0.13);
  --danger:     #fb7185;
  --danger-dim: rgba(251, 113, 133, 0.13);

  /* Geometry — 4px base. Radii step up so cards read as objects, not boxes. */
  --r-sm: 8px;
  --r-md: 12px;
  --r-lg: 18px;
  --r-xl: 24px;

  --ease: cubic-bezier(0.16, 1, 0.3, 1);

  /* The one shadow recipe: a hairline top highlight + soft ambient occlusion.
     Reads as glass under a light source instead of a drop shadow. */
  --lift: inset 0 1px 0 rgba(255, 255, 255, 0.06), 0 1px 2px rgba(0, 0, 0, 0.4);
  --lift-lg: inset 0 1px 0 rgba(255, 255, 255, 0.07), 0 24px 60px -20px rgba(0, 0, 0, 0.8);

  /* Aliases kept so the pages that were not redesigned (transparency, the
     OAuth error page, the sign-in fallbacks) resolve against the same palette
     instead of carrying a second one. */
  --surface: var(--surface-1);
  --surface2: var(--surface-2);
  --surface3: var(--surface-3);
  --border: var(--hairline-2);
  --border-light: var(--hairline);
  --text: var(--ink);
  --muted: var(--ink-2);
  --accent: var(--violet);
  --accent-hover: var(--violet-lo);
  --accent-active: #6d4fd8;
  --accent-dim: var(--violet-dim);
  --ok-soft: var(--ok-dim);
  --warn-soft: var(--warn-dim);
  --danger-soft: var(--danger-dim);
  --radius: var(--r-md);
  --ease-out-expo: var(--ease);
}

* { box-sizing: border-box; }
/* Components below set display on their own class, which outranks the UA
   [hidden] rule. Without this, `hidden` popovers render open. */
[hidden] { display: none !important; }
html { color-scheme: dark; -webkit-text-size-adjust: 100%; }
html, body { margin: 0; min-height: 100%; }

body {
  background: var(--bg);
  color: var(--ink);
  font-family: Inter, ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  font-feature-settings: "cv01", "ss01";
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -webkit-tap-highlight-color: transparent;
  overflow-x: hidden;
}

/* Ambient light from the top-right, and a 2% film grain over everything.
   The grain is what stops large dark fields from banding and reading as flat. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background:
    radial-gradient(90rem 50rem at 82% -18%, rgba(155, 130, 255, 0.10), transparent 62%),
    radial-gradient(60rem 40rem at 8% 0%, rgba(232, 168, 124, 0.045), transparent 60%);
}
body::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: 0.025;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
}
body > * { position: relative; z-index: 1; }

a { color: inherit; text-decoration: none; }

:where(a, button, input, select, summary):focus-visible {
  outline: 2px solid var(--violet);
  outline-offset: 3px;
  border-radius: 6px;
}

/* ---------------------------------------------------------------- type --- */

h1, h2, h3 { margin: 0; line-height: 1.2; letter-spacing: -0.01em; }
h1 { font-size: 20px; font-weight: 700; }
h2 { font-size: 19px; font-weight: 680; }
h3 { font-size: 15px; font-weight: 650; }

.display {
  margin: 0;
  font-size: clamp(30px, 4.4vw, 46px);
  font-weight: 700;
  line-height: 1.03;
  letter-spacing: -0.035em;
  text-wrap: balance;
}
.title    { margin: 0; font-size: 20px; font-weight: 650; letter-spacing: -0.02em; }
.subtitle { margin: 0; color: var(--ink-2); font-size: 15px; line-height: 1.55; text-wrap: pretty; }
.eyebrow {
  margin: 0;
  color: var(--ink-3);
  font-size: 11px;
  font-weight: 620;
  letter-spacing: 0.09em;
  text-transform: uppercase;
}
.num { font-variant-numeric: tabular-nums; font-feature-settings: "tnum"; }
.hint { margin: 6px 0 0; color: var(--ink-2); font-size: 13px; }
.fine { margin: 8px 0 0; color: var(--ink-3); font-size: 12.5px; line-height: 1.5; }
.muted { color: var(--ink-2); }

/* --------------------------------------------------------------- shell --- */

.shell {
  width: min(100%, 1160px);
  margin-inline: auto;
  padding: 0 clamp(16px, 3vw, 28px) 64px;
}

/* One header for every signed-in page. On mobile it collapses to a single
   56px-tall bar — the old version spent ~180px here before any content. */
.topbar {
  position: sticky;
  top: 0;
  z-index: 40;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  min-height: 64px;
  margin-bottom: 22px;
}

.topbar::before {
  content: "";
  position: absolute;
  z-index: -1;
  top: 0;
  bottom: 0;
  left: 50%;
  width: 100vw;
  transform: translateX(-50%);
  background: color-mix(in srgb, var(--bg) 86%, transparent);
  backdrop-filter: blur(14px) saturate(1.3);
  border-bottom: 1px solid transparent;
  transition: border-color 180ms ease;
}
.topbar.pinned::before { border-bottom-color: var(--hairline); }

.brand { display: inline-flex; align-items: center; gap: 10px; min-width: 0; min-height: 44px; }
.brand b { font-size: 16px; font-weight: 680; letter-spacing: -0.02em; }
.brand > span { color: var(--ink-3); font-size: 12px; }
.topbar .brand img { width: 30px; height: 30px; border-radius: 8px; filter: none; }

.topbar-actions { display: flex; align-items: center; gap: 8px; }
.topbar-actions form { display: contents; }

/* The account control: full identity on desktop, one 40px avatar on mobile. */
.account {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  min-height: 40px;
  height: 40px;
  padding: 0 6px 0 12px;
  border: 1px solid var(--hairline);
  border-radius: 999px;
  background: var(--surface-1);
  color: var(--ink-2);
  font: inherit;
  font-size: 13px;
  cursor: pointer;
  transition: border-color 160ms var(--ease), background 160ms var(--ease);
}
.account:hover { border-color: var(--hairline-2); background: var(--surface-2); }
.account .who { display: flex; flex-direction: column; min-width: 0; line-height: 1.15; text-align: right; }
.account .who small { color: var(--ink-3); font-size: 10px; letter-spacing: 0.05em; text-transform: uppercase; }
.account .who strong {
  overflow: hidden;
  max-width: min(34vw, 220px);
  color: var(--ink);
  font-size: 12.5px;
  font-weight: 560;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.account .pfp {
  display: grid;
  place-items: center;
  flex: none;
  width: 28px;
  height: 28px;
  border-radius: 999px;
  background: linear-gradient(150deg, var(--violet), var(--copper));
  color: #0b0b0d;
  font-size: 12px;
  font-weight: 720;
  text-transform: uppercase;
}

/* -------------------------------------------------------------- buttons --- */

/* Base for the surfaces that were not redesigned: they use `.button` and bare
   `<button>`. The `.btn` block below is the design-system button and comes
   after on purpose so it wins where an element carries both. */
.button, button {
  appearance: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 40px;
  padding: 9px 13px;
  border: 1px solid var(--hairline-2);
  border-radius: var(--r-sm);
  background: var(--surface-2);
  color: var(--ink);
  font: inherit;
  font-size: 13px;
  font-weight: 620;
  white-space: nowrap;
  text-decoration: none;
  cursor: pointer;
  touch-action: manipulation;
  transition: background 160ms var(--ease), border-color 160ms var(--ease), color 160ms var(--ease);
}
.button.subtle, button.subtle { background: transparent; color: var(--ink-2); }
.button.primary, button.primary {
  border-color: #7052dc;
  background: #7052dc;
  box-shadow: 0 4px 8px rgba(139, 108, 247, 0.22);
  color: #fff;
}
.button:hover, button:hover { border-color: var(--hairline-2); text-decoration: none; }
.button.primary:hover, button.primary:hover { border-color: var(--accent-active); background: var(--accent-active); }
button:disabled { cursor: not-allowed; opacity: 0.55; }

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 44px;
  padding: 0 18px;
  border: 1px solid var(--hairline);
  border-radius: var(--r-md);
  background: var(--surface-2);
  box-shadow: var(--lift);
  color: var(--ink);
  font: inherit;
  font-size: 14px;
  font-weight: 560;
  white-space: nowrap;
  text-decoration: none;
  cursor: pointer;
  touch-action: manipulation;
  transition: transform 140ms var(--ease), background 140ms var(--ease), border-color 140ms var(--ease);
}
.btn:hover { background: var(--surface-3); border-color: var(--hairline-2); }
.btn:active { transform: translateY(1px); }
.btn svg { width: 16px; height: 16px; flex: none; }

.btn.primary {
  border-color: #7052dc;
  background: #7052dc;
  box-shadow: 0 4px 8px rgba(139, 108, 247, 0.22);
  color: #fff;
  font-weight: 650;
}
.btn.primary:hover { border-color: var(--accent-active); background: var(--accent-active); }
.btn.ghost { background: transparent; box-shadow: none; color: var(--ink-2); }
.btn.ghost:hover { background: var(--surface-1); color: var(--ink); }
.btn.danger { color: var(--danger); border-color: rgba(251, 113, 133, 0.28); background: var(--danger-dim); box-shadow: none; }
.btn.lg { min-height: 52px; padding: 0 24px; font-size: 15px; border-radius: var(--r-md); }
.btn.block { width: 100%; }
.btn:disabled { cursor: not-allowed; opacity: 0.55; }

.icon-svg {
  width: 16px;
  height: 16px;
  display: block;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* ---------------------------------------------------------------- cards --- */

.card {
  border: 1px solid var(--hairline);
  border-radius: var(--r-lg);
  background: var(--surface-1);
  box-shadow: var(--lift-lg);
}

.pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 26px;
  padding: 0 11px;
  border: 1px solid var(--hairline);
  border-radius: 999px;
  background: var(--surface-2);
  color: var(--ink-2);
  font-size: 12px;
  font-weight: 580;
  letter-spacing: -0.005em;
  white-space: nowrap;
}
.pill.ok, .pill.warn, .pill.danger, .pill.err { border-color: transparent; }
.pill.ok::before, .pill.warn::before, .pill.danger::before, .pill.err::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 999px;
  background: currentColor;
}
.pill.ok     { background: var(--ok-dim);     color: var(--ok); }
.pill.warn   { background: var(--warn-dim);   color: var(--warn); }
.pill.danger,
.pill.err    { background: var(--danger-dim); color: var(--danger); }
.pill.ok::before { animation: pulse 2.4s var(--ease) infinite; }

@keyframes pulse {
  0%, 100% { box-shadow: 0 0 0 0 var(--ok-dim); }
  50%      { box-shadow: 0 0 0 5px transparent; }
}

/* ---------------------------------------------------------------- forms --- */

form { display: grid; gap: 12px; margin: 0; }
label { display: grid; gap: 6px; color: var(--ink-2); font-size: 12px; font-weight: 620; }
input, select, textarea {
  width: 100%;
  min-height: 44px;
  padding: 9px 12px;
  border: 1px solid var(--hairline-2);
  border-radius: var(--r-sm);
  background: var(--surface-2);
  color: var(--ink);
  font: inherit;
  font-size: 16px;
}
select {
  appearance: none;
  padding-right: 34px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%236f6b78' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 10px center;
  background-size: 16px 16px;
}

/* The old name field had no border and shared a pill with the submit button,
   so it did not read as editable. This is an ordinary, obvious text field. */
.field { display: block; }
.field > .lbl {
  display: block;
  margin-bottom: 8px;
  color: var(--ink-2);
  font-size: 13px;
  font-weight: 560;
}
.field .wrap { position: relative; display: flex; align-items: center; }
.field input {
  width: 100%;
  min-height: 56px;
  padding: 0 46px 0 16px;
  border: 1px solid var(--hairline-2);
  border-radius: var(--r-md);
  background: var(--surface-2);
  color: var(--ink);
  font: inherit;
  font-size: 17px;
  font-weight: 560;
  letter-spacing: -0.01em;
  transition: border-color 160ms var(--ease), box-shadow 160ms var(--ease);
}
.field input::placeholder { color: var(--ink-3); font-weight: 450; }
.field input:focus {
  outline: none;
  border-color: var(--violet);
  box-shadow: 0 0 0 4px var(--violet-dim);
}
.field .tick {
  position: absolute;
  right: 15px;
  display: grid;
  place-items: center;
  width: 20px;
  height: 20px;
  border-radius: 999px;
  background: var(--ok-dim);
  color: var(--ok);
}
.field .hint { display: block; margin: 8px 0 0; color: var(--ink-3); font-size: 12.5px; font-weight: 400; }

/* Secondary inputs inside advanced settings. */
.subfield { display: grid; gap: 6px; }
.subfield > span { color: var(--ink-3); font-size: 12px; font-weight: 560; }
.subfield input, .subfield select { min-height: 44px; font-size: 15px; }
.subgrid { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 10px; }

/* Disclosure that looks like it opens, because it does. */
.disclosure { border: 1px solid var(--hairline); border-radius: var(--r-md); background: var(--surface-1); }
.disclosure > summary {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 52px;
  padding: 0 16px;
  cursor: pointer;
  list-style: none;
  font-size: 14px;
  font-weight: 560;
}
.disclosure > summary::-webkit-details-marker { display: none; }
.disclosure > summary .caret {
  display: grid;
  place-items: center;
  flex: none;
  color: var(--ink-3);
  transition: transform 200ms var(--ease);
}
.disclosure[open] > summary .caret { transform: rotate(90deg); }
/* The summary state ("Sign-in on · 5 GB") must sit outside .caret, or the
   open-state rotation spins the text with the chevron. */
.disclosure > summary .state {
  margin-left: auto;
  color: var(--ink-3);
  font-size: 13px;
  font-weight: 450;
  white-space: nowrap;
}
.disclosure .body { padding: 4px 16px 16px; border-top: 1px solid var(--hairline); }
.disclosure .body > * + * { margin-top: 14px; }

.switch { display: flex; align-items: flex-start; gap: 14px; padding: 14px 0; margin: 0; cursor: pointer; }
.switch + .switch, .disclosure .body .switch + * { border-top: 1px solid var(--hairline); }
.switch-input { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; border: 0; clip-path: inset(50%); overflow: hidden; }
.switch .track {
  flex: none;
  position: relative;
  width: 42px;
  height: 25px;
  margin-top: 2px;
  border-radius: 999px;
  background: var(--surface-3);
  border: 1px solid var(--hairline-2);
  transition: background 180ms var(--ease);
}
.switch .track::after {
  content: "";
  position: absolute;
  top: 2px; left: 2px;
  width: 19px; height: 19px;
  border-radius: 999px;
  background: var(--ink-2);
  transition: transform 180ms var(--ease), background 180ms var(--ease);
}
.switch.on .track,
.switch-input:checked ~ .track { background: var(--violet); border-color: transparent; }
.switch.on .track::after,
.switch-input:checked ~ .track::after { transform: translateX(17px); background: #fff; }
.switch-input:focus-visible ~ .track { outline: 2px solid var(--violet); outline-offset: 3px; }
.switch strong { display: block; color: var(--ink); font-size: 14px; font-weight: 560; }
.switch .switch-copy > span { display: block; margin-top: 3px; color: var(--ink-3); font-size: 13px; font-weight: 400; line-height: 1.45; }

/* ----------------------------------------------------------------- spec --- */

/* Replaces the "- -" placeholder tiles. A spec row states what you get; a
   metric row states what is happening. Neither ever renders an empty bar.
   The 1px gap over a hairline background draws the dividers, so a row that
   wraps to two lines still separates cleanly. */
.spec {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(0, 1fr));
  border: 1px solid var(--hairline);
  border-radius: var(--r-md);
  background: var(--surface-1);
  overflow: hidden;
}
.spec > div { padding: 14px 16px; }
.spec > div + div { border-left: 1px solid var(--hairline); }

/* A spec that has to wrap runs on a six-column bed and spans its cells so
   every row ends flush — a ragged half-empty row reads as a rendering bug.
   The 1px gaps over a hairline background draw the dividers, which only works
   because the spans leave no empty cell behind. */
.spec.wide {
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: 1px;
  background: var(--hairline);
}
.spec.wide > div { background: var(--surface-1); border-left: 0; grid-column: span 3; }
.spec.wide[data-cells="5"] > div:nth-child(-n+3) { grid-column: span 2; }
.spec.wide[data-cells="5"] > div:nth-child(n+4) { grid-column: span 3; }
.spec dt { margin: 0 0 3px; color: var(--ink-3); font-size: 11px; font-weight: 600; letter-spacing: 0.07em; text-transform: uppercase; }
.spec dd { margin: 0; font-size: 14px; font-weight: 560; }
.spec dd small { display: block; margin-top: 2px; color: var(--ink-3); font-size: 12px; font-weight: 450; }

.metrics { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 10px; }
.metric {
  padding: 13px 14px;
  border: 1px solid var(--hairline);
  border-radius: var(--r-md);
  background: var(--surface-1);
}
.metric .k { color: var(--ink-3); font-size: 11px; font-weight: 600; letter-spacing: 0.07em; text-transform: uppercase; }
.metric .v { margin-top: 5px; font-size: 19px; font-weight: 620; letter-spacing: -0.02em; }
.metric .v small { color: var(--ink-3); font-size: 12px; font-weight: 500; }
.metric .bar { margin-top: 9px; height: 4px; border-radius: 999px; background: var(--surface-3); overflow: hidden; }
.metric .bar i { display: block; width: 0; height: 100%; border-radius: 999px; background: linear-gradient(90deg, var(--violet-lo), var(--violet-hi)); }
.metric.idle .bar i { background: var(--hairline-2); }

/* A measurement that has not arrived shows a shimmer, never a "- -". */
.skeleton {
  display: inline-block;
  min-width: 48px;
  height: 1em;
  border-radius: 5px;
  background: linear-gradient(90deg, var(--surface-2) 25%, var(--surface-3) 37%, var(--surface-2) 63%);
  background-size: 300% 100%;
  animation: shimmer 1.5s linear infinite;
  vertical-align: -0.12em;
}
@keyframes shimmer { from { background-position: 100% 0; } to { background-position: -100% 0; } }

/* -------------------------------------------------------------- utility --- */

.row { display: flex; align-items: center; gap: 10px; }
.row.wrap { flex-wrap: wrap; }
.spread { display: flex; align-items: center; justify-content: space-between; gap: 16px; }
.grow { flex: 1 1 auto; min-width: 0; }
.mono { font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 13px; }
.only-mobile { display: none; }

/* ------------------------------------------------------------- composer --- */

/* The first decision gets a composed stage without turning a short form into a
   full-screen wall. */
.composer {
  display: grid;
  grid-template-columns: minmax(0, 0.74fr) minmax(0, 1fr);
  min-height: 0;
  overflow: hidden;
}

.composer-aside {
  display: flex;
  flex-direction: column;
  gap: 0;
  position: relative;
  overflow: hidden;
  padding: clamp(28px, 2.8vw, 38px);
  border-right: 1px solid var(--hairline);
  background:
    radial-gradient(34rem 26rem at 12% 108%, rgba(155, 130, 255, 0.16), transparent 70%),
    radial-gradient(24rem 20rem at 96% -8%, rgba(232, 168, 124, 0.08), transparent 66%),
    var(--surface-2);
  isolation: isolate;
}

/* Möbius band, drawn rather than imported, sitting behind the copy. */
.composer-aside .orbit {
  position: absolute;
  z-index: -1;
  right: -34%;
  bottom: -30%;
  width: 150%;
  opacity: 0.55;
  pointer-events: none;
}
.composer-aside .orbit ellipse { fill: none; stroke: rgba(155, 130, 255, 0.16); }

.mark-lockup { display: flex; align-items: center; gap: 13px; }
.mark-lockup img { width: 42px; height: 42px; border-radius: 11px; }
.mark-lockup strong { display: block; color: var(--violet-hi); font-size: 14px; font-weight: 620; }
.mark-lockup span span { display: block; margin-top: 1px; color: var(--ink-3); font-size: 12.5px; }

.aside-body { margin-block: 28px 0; }
/* The line break is set by measure, not a <br> — a <br> hidden at mobile
   deletes the word space along with the break. */
.aside-body .display { max-width: 13ch; font-size: clamp(30px, 3.2vw, 38px); }
.aside-body .subtitle { margin-top: 12px; max-width: 34ch; }
.aside-rest { margin-top: 22px; }

.inventory {
  display: grid;
  gap: 1px;
  margin: 0;
  padding: 0;
  overflow: hidden;
  border: 1px solid var(--hairline);
  border-radius: var(--r-md);
  background: var(--hairline);
  list-style: none;
}
.inventory li { display: flex; align-items: center; gap: 10px; padding: 9px 12px; background: rgba(10, 10, 13, 0.55); font-size: 13px; }
.inventory svg { width: 16px; height: 16px; flex: none; color: var(--violet); }
.inventory span { color: var(--ink-2); }
.inventory b { color: var(--ink); font-weight: 560; }
.host-note { display: flex; align-items: center; gap: 9px; margin: 0; color: var(--ink-3); font-size: 12.5px; }
.host-note b { color: var(--ink-2); font-weight: 560; }
.host-note .dot { flex: none; width: 6px; height: 6px; border-radius: 999px; background: var(--ok); box-shadow: 0 0 0 4px var(--ok-dim); }

.composer-main {
  display: flex;
  flex-direction: column;
  gap: 18px;
  padding: clamp(28px, 2.8vw, 38px);
}
.composer-main .head { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; }
.composer-main .head > div { display: grid; gap: 7px; }
.composer-form { display: flex; flex-direction: column; gap: 18px; }

.launch-summary {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 0;
  margin: 0;
  padding-block: 14px;
  border-block: 1px solid var(--hairline);
  color: var(--ink-3);
  font-size: 12.5px;
  line-height: 1.4;
}
.launch-summary span { white-space: nowrap; }
.launch-summary b { color: var(--ink); font-weight: 600; }
.launch-summary i { width: 1px; height: 16px; margin-inline: 16px; background: var(--hairline-2); }

.composer-foot { display: flex; align-items: center; justify-content: flex-end; gap: 12px; margin-top: auto; padding-top: 10px; }
.composer-note { max-width: 36ch; margin: 0 auto 0 0; color: var(--ink-3); font-size: 12.5px; line-height: 1.5; }
.composer-foot .btn.primary { min-width: 190px; }

/* The second and later deployments compose inline under the list rather than
   replacing the page, so the deployments you already have stay in view. */
.new-panel { display: grid; gap: 14px; }
.new-panel > .composer { min-height: 0; }
/* Inline, the aside is only as tall as the form beside it, so the headline
   starts at the top and the reassurance sinks to the bottom instead of
   leaving a void above the words. */
.new-panel .aside-body { margin-block: 18px 0; }
.composer-close { flex: none; width: 44px; min-width: 44px; padding: 0; }

/* ------------------------------------------------------------ dashboard --- */

.page-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 20px; margin-bottom: 20px; }
.page-head .display { max-width: 18ch; }
.page-head .subtitle { margin-top: 8px; max-width: 52ch; }

.deployments { display: grid; gap: 14px; }

.dep { padding: 18px; }
.dep-head { display: flex; align-items: flex-start; gap: 14px; }
.dep-head .grow { display: grid; gap: 5px; }
.dep-title { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.dep-title h2 { margin: 0; font-size: 20px; font-weight: 650; letter-spacing: -0.022em; }
.dep-url {
  display: inline-flex; align-items: center; gap: 6px;
  width: max-content; max-width: 100%;
  min-height: 44px; margin-block: -12px;
  color: var(--ink-3); font-size: 13px;
}
a.dep-url:hover { color: var(--violet-hi); }
.dep-meta,
.railway-project-meta,
.railway-account-meta { margin: 0; color: var(--ink-3); font-size: 12.5px; }
.dep-meta strong,
.railway-project-meta strong,
.railway-account-meta strong { color: var(--ink-2); font-weight: 560; }
.dep-meta a,
.railway-account-meta a {
  margin-left: 6px;
  color: var(--violet-hi);
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* Actions keep their words at every width. The old layout collapsed them to
   bare icons on mobile — including an unlabelled destructive delete. */
.dep-actions { display: flex; align-items: center; gap: 8px; flex: none; }
.dep-actions .btn { padding: 0 14px; }
.dep-actions form { display: contents; }

.menu { position: relative; }
.menu > .btn { width: 44px; padding: 0; }
.menu-pop {
  position: absolute; top: calc(100% + 6px); right: 0; z-index: 20;
  display: grid; gap: 2px; min-width: 232px; padding: 6px;
  /* The popup anchors to its toggle. Clamp it to the viewport so it can never
     open off-screen when that toggle is not near the right edge. */
  max-width: min(280px, calc(100vw - 24px));
  border: 1px solid var(--hairline-2); border-radius: var(--r-md);
  background: var(--surface-2); box-shadow: 0 20px 44px -14px rgba(0,0,0,0.85);
}
.menu-pop form { display: block; gap: 0; }
.menu-pop a,
.menu-pop button {
  display: flex; align-items: center; gap: 10px; width: 100%;
  min-height: 44px; padding: 0 10px;
  border: 0; border-radius: var(--r-sm); background: none; box-shadow: none;
  color: var(--ink-2); font: inherit; font-size: 13.5px; font-weight: 500;
  text-align: left; justify-content: flex-start; cursor: pointer;
}
.menu-pop a:hover,
.menu-pop button:hover { background: var(--surface-3); color: var(--ink); border-color: transparent; }
.menu-pop .danger { color: var(--danger); }
.menu-pop .danger:hover { background: var(--danger-dim); color: var(--danger); }
.menu-pop hr { margin: 4px 0; border: 0; border-top: 1px solid var(--hairline); }
.menu-pop .who {
  display: grid; gap: 1px; padding: 6px 10px 8px;
  border-bottom: 1px solid var(--hairline); margin-bottom: 4px;
}
.menu-pop .who small { color: var(--ink-3); font-size: 10px; letter-spacing: 0.05em; text-transform: uppercase; }
.menu-pop .who strong { overflow: hidden; color: var(--ink); font-size: 13px; font-weight: 560; text-overflow: ellipsis; }

.dep-body { margin-top: 16px; padding-top: 16px; border-top: 1px solid var(--hairline); }
.dep-body > * + * { margin-top: 14px; }

.usage-line { display: flex; align-items: baseline; justify-content: space-between; gap: 14px; margin-bottom: 9px; }
.usage-line b { font-size: 14px; font-weight: 600; }
.usage-line span { color: var(--ink-3); font-size: 12.5px; text-align: right; }
.usage-bar { height: 6px; border-radius: 999px; background: var(--surface-3); overflow: hidden; }
.usage-bar i { display: block; width: 0; height: 100%; border-radius: 999px; background: linear-gradient(90deg, var(--violet-lo), var(--violet-hi)); }
.dep-note {
  display: flex;
  gap: 8px;
  margin: 0;
  padding: 10px 12px;
  border: 1px solid rgba(242, 200, 121, 0.24);
  border-radius: var(--r-sm);
  background: var(--warn-dim);
  color: var(--warn);
  font-size: 12.5px;
}
.usage-bar.pending {
  background: linear-gradient(90deg, var(--surface-2) 25%, var(--surface-3) 37%, var(--surface-2) 63%);
  background-size: 300% 100%;
  animation: shimmer 1.5s linear infinite;
}

/* ---- building state ---- */
.build { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr); gap: 0; overflow: hidden; }
.build-left { padding: 22px; display: flex; flex-direction: column; gap: 18px; }
.build-art {
  position: relative; min-height: 300px;
  border-left: 1px solid var(--hairline);
  background: radial-gradient(28rem 22rem at 60% 40%, rgba(155,130,255,0.16), transparent 70%), var(--surface-2);
  display: grid; padding: 22px;
}
.build-art .cap { margin-top: 16px; }
.build-art .cap b { display: block; font-size: 15px; font-weight: 600; }
.build-art .cap span { display: block; margin-top: 3px; color: var(--ink-2); font-size: 13px; }

/* Three brand illustrations rotate behind the caption; each one carries its
   own words, so the caption changes with the picture. */
.build-slide {
  grid-area: 1 / 1;
  display: flex; flex-direction: column; justify-content: space-between;
  opacity: 0; visibility: hidden;
  transition: opacity 600ms var(--ease);
}
.build-slide.active { opacity: 1; visibility: visible; }
.build-slide img {
  display: block; width: 100%; max-width: 320px; margin: 0 auto;
  aspect-ratio: 3 / 2; object-fit: cover;
  border-radius: var(--r-md);
  -webkit-mask-image: radial-gradient(120% 110% at 50% 40%, #000 55%, transparent 100%);
          mask-image: radial-gradient(120% 110% at 50% 40%, #000 55%, transparent 100%);
}
.build-dots { position: absolute; right: 18px; top: 18px; display: flex; gap: 2px; z-index: 2; }
.build-dot {
  width: 26px; height: 26px; min-height: 26px; padding: 0;
  border: 0; background: none; box-shadow: none;
  display: grid; place-items: center; cursor: pointer;
}
.build-dot::before { content: ""; width: 6px; height: 6px; border-radius: 999px; background: var(--hairline-2); transition: background 200ms var(--ease); }
.build-dot.active::before { background: var(--violet-hi); }
.build-dot:hover { background: none; border-color: transparent; }

.steps { display: grid; gap: 0; list-style: none; margin: 0; padding: 0; }
.steps li { display: flex; align-items: center; gap: 12px; padding: 11px 0; font-size: 14px; color: var(--ink-3); }
.steps li + li { border-top: 1px solid var(--hairline); }
.steps .dot {
  flex: none; display: grid; place-items: center;
  width: 22px; height: 22px; border-radius: 999px;
  border: 1px solid var(--hairline-2); background: var(--surface-2);
  font-size: 11px; font-weight: 620;
}
.steps li.done { color: var(--ink-2); }
.steps li.done .dot { border-color: transparent; background: var(--ok-dim); color: var(--ok); }
.steps li.done .dot .n { display: none; }
.steps li:not(.done) .dot .tickmark { display: none; }
.steps li.now { color: var(--ink); font-weight: 560; }
.steps li.now .dot { border-color: var(--violet); color: var(--violet); box-shadow: 0 0 0 4px var(--violet-dim); }
.steps li.now .dot .n { display: none; }
/* Relaxed from 1.4s on main ("relax build motion"): builds can outlast the
   usual minute, and a fast throb reads as anxious. */
.steps li.now .dot::after { content: ""; width: 7px; height: 7px; border-radius: 999px; background: var(--violet); animation: pulse2 2.8s var(--ease) infinite; }
@keyframes pulse2 { 0%,100% { opacity: 1; transform: scale(1); } 50% { opacity: .45; transform: scale(.75); } }

.eta { display: flex; align-items: center; gap: 9px; margin-top: auto; color: var(--ink-2); font-size: 13px; }
.eta .track { flex: 1 1 auto; height: 4px; border-radius: 999px; background: var(--surface-3); overflow: hidden; }
.eta .track i { display: block; width: 100%; height: 100%; border-radius: 999px; background: linear-gradient(90deg, var(--violet-lo), var(--violet-hi)); transform: scaleX(var(--build-progress, 0)); transform-origin: left; transition: transform 600ms var(--ease); }

/* ---- error state ---- */
.alert {
  display: flex; align-items: flex-start; gap: 12px;
  padding: 14px 16px; border: 1px solid rgba(251,113,133,0.25);
  border-radius: var(--r-md); background: var(--danger-dim);
}
.alert > svg { flex: none; width: 18px; height: 18px; color: var(--danger); margin-top: 1px; }
.alert b { display: block; font-size: 14px; font-weight: 600; }
.alert p { margin: 3px 0 0; color: var(--ink-2); font-size: 13.5px; line-height: 1.5; }
.alert .row { margin-top: 12px; }
.alert form { display: contents; }
.alert .btn { min-height: 44px; }

/* ---- new deployment ---- */
.new-dep {
  display: flex; align-items: center; gap: 16px;
  padding: 16px 18px;
  border: 1px dashed var(--hairline-2); border-radius: var(--r-lg);
  background: transparent; width: 100%; text-align: left; cursor: pointer;
  color: inherit; font: inherit; list-style: none;
  transition: border-color 160ms var(--ease), background 160ms var(--ease);
}
.new-dep::-webkit-details-marker { display: none; }
.new-dep:hover { border-color: var(--violet); background: var(--surface-1); }
.new-dep .plus {
  flex: none; display: grid; place-items: center; width: 40px; height: 40px;
  border-radius: var(--r-md); border: 1px solid var(--hairline);
  background: var(--surface-2); color: var(--violet);
  transition: transform 220ms var(--ease);
}
.new-dep b { display: block; font-size: 15px; font-weight: 600; }
.new-dep .grow > span { display: block; margin-top: 2px; color: var(--ink-3); font-size: 13px; }
.new-panel[open] > .new-dep { border-style: solid; background: var(--surface-1); }
.new-panel[open] > .new-dep .plus { transform: rotate(45deg); }

/* -------------------------------------------------------------- connect --- */

.setup { display: grid; grid-template-columns: minmax(0, 0.86fr) minmax(0, 1fr);
         min-height: calc(100svh - 64px - 44px); overflow: hidden; }

.setup-aside {
  position: relative;
  display: flex; flex-direction: column; gap: 26px;
  padding: clamp(28px, 3.4vw, 46px);
  border-right: 1px solid var(--hairline);
  background:
    radial-gradient(32rem 24rem at 10% 106%, rgba(155,130,255,0.15), transparent 70%),
    radial-gradient(22rem 18rem at 98% -6%, rgba(232,168,124,0.07), transparent 66%),
    var(--surface-2);
}
.setup-aside .display { max-width: 12ch; }
.setup-aside .subtitle { max-width: 34ch; margin-top: 16px; }
.setup-aside .rail { margin-top: auto; }

/* Progress is a real two-step rail, not a numbered orphan sitting under a card. */
.rail { display: grid; gap: 0; margin: 0; padding: 0; list-style: none; }
.rail li { display: grid; grid-template-columns: 26px minmax(0, 1fr); gap: 14px; padding: 0 0 22px; position: relative; }
.rail li:last-child { padding-bottom: 0; }
.rail li::before {
  content: ""; position: absolute; left: 12.5px; top: 28px; bottom: 6px;
  width: 1px; background: var(--hairline-2);
}
.rail li:last-child::before { display: none; }
.rail .badge {
  display: grid; place-items: center; width: 26px; height: 26px; border-radius: 999px;
  border: 1px solid var(--hairline-2); background: var(--surface-1);
  color: var(--ink-3); font-size: 12px; font-weight: 620;
}
.rail li.now .badge { border-color: transparent; background: var(--violet); color: #14101f; }
.rail h3, .rail b { display: block; margin: 0; font-size: 15px; font-weight: 600; }
.rail li:not(.now) h3, .rail li:not(.now) b { color: var(--ink-3); }
.rail span span, .rail p { display: block; margin: 3px 0 0; color: var(--ink-3); font-size: 13.5px; line-height: 1.5; }

.setup-main { display: flex; flex-direction: column; gap: 22px; padding: clamp(28px, 3.4vw, 46px); }

.provider {
  display: flex; align-items: center; gap: 14px;
  padding: 16px; border: 1px solid var(--hairline); border-radius: var(--r-md);
  background: var(--surface-1);
}
.provider .logo {
  flex: none; display: grid; place-items: center; width: 44px; height: 44px;
  border-radius: var(--r-md); background: #0b0b0d; border: 1px solid var(--hairline-2);
}
.provider .logo img { width: 22px; height: 22px; display: block; }
.provider b { display: block; font-size: 15px; font-weight: 600; }
.provider .grow > span { display: block; margin-top: 2px; color: var(--ink-3); font-size: 13px; }

.grants { display: grid; gap: 1px; border: 1px solid var(--hairline); border-radius: var(--r-md);
          background: var(--hairline); overflow: hidden; margin: 0; padding: 0; list-style: none; }
.grants li { display: flex; align-items: flex-start; gap: 11px; padding: 13px 15px; background: var(--surface-1); font-size: 13.5px; }
.grants svg { flex: none; width: 15px; height: 15px; margin-top: 2px; }
.grants .yes { color: var(--ok); }
.grants .no  { color: var(--ink-3); }
.grants b { font-weight: 560; }
.grants span { color: var(--ink-2); }

.setup-foot { margin-top: auto; display: grid; gap: 12px; }
.setup-foot .fine { margin: 0; text-align: center; }
.connect-status { margin: 0; min-height: 18px; color: var(--ink-3); font-size: 13px; text-align: center; }
.connect-status[data-tone="error"] { color: var(--danger); }
.connect-status[data-tone="success"] { color: var(--ok); }
.connect-fallback { display: flex; flex-wrap: wrap; justify-content: center; gap: 10px; color: var(--ink-3); font-size: 12.5px; }
.connect-fallback a { color: var(--violet-hi); text-decoration: underline; text-underline-offset: 2px; }

/* ---------------------------------------------------- carried-over rules --- */

/* Still rendered by /transparency, the OAuth error page, the sign-in
   fallbacks and the notices inside the signed-in surfaces. */

.shell.narrow { width: min(100%, 480px); padding-top: 72px; }
.stack { display: grid; gap: 14px; }
.panel {
  border: 1px solid var(--hairline);
  border-radius: var(--r-lg);
  background: var(--surface-1);
  box-shadow: var(--lift-lg);
  overflow: hidden;
}
.section { padding: 20px; }
.section + .section { border-top: 1px solid var(--hairline); }
.section-title { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 14px; }
.actions { display: flex; align-items: center; justify-content: flex-end; gap: 8px; flex-wrap: wrap; }
.actions.left { justify-content: flex-start; }

.brand.block { align-items: flex-start; margin-bottom: 18px; }
.brand .mark { width: 44px; height: 44px; flex: none; display: block; object-fit: contain; }
.brand .subtitle { margin: 3px 0 0; font-size: 13px; overflow-wrap: anywhere; }
.brand-name { display: block; font-size: 20px; font-weight: 700; line-height: 1.2; }

.meta { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 11px; }
.trust-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; }
.trust-card { border: 1px solid var(--hairline); border-radius: var(--r-md); padding: 14px; background: var(--surface-2); }
.trust-card ul { margin: 10px 0 0; padding-left: 18px; color: var(--ink-2); font-size: 13px; }
.trust-card li + li { margin-top: 6px; }

.provider-list { display: grid; gap: 10px; margin-bottom: 16px; }
.provider-mark { width: 20px; height: 20px; display: inline-grid; place-items: center; flex: none; }
.provider-mark svg { width: 20px; height: 20px; display: block; }

.notice {
  border: 1px solid rgba(242, 200, 121, 0.28);
  border-radius: var(--r-md);
  background: var(--warn-dim);
  color: #f5d79a;
  padding: 12px 14px;
  font-size: 13px;
}
.notice.danger { border-color: rgba(251, 113, 133, 0.28); background: var(--danger-dim); color: #fecaca; }
.notice p { margin: 0; }
.command {
  margin-top: 10px;
  border: 1px solid var(--hairline-2);
  border-radius: var(--r-sm);
  background: #0a0a0a;
  color: #e8e3ff;
  min-height: 38px;
  padding: 9px 10px;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 12px;
  overflow-x: auto;
  white-space: nowrap;
}
.account-required { display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
.account-required strong { display: block; }
.account-required p { margin: 4px 0 0; }

/* ------------------------------------------------------------ responsive --- */

@media (max-width: 860px) {
  /* Mobile gets a short hero for context, then the form, then reassurance.
     `display: contents` dissolves the aside so its two halves can be ordered
     independently around the form — the old page stacked a 300px decorative
     panel above the task. */
  .composer { grid-template-columns: minmax(0, 1fr); min-height: 0; }
  .composer-aside { display: contents; }
  .composer-aside .orbit, .mark-lockup { display: none; }
  .aside-rest { display: none; }

  .aside-body {
    order: 1;
    margin: 0;
    padding: 26px 20px 24px;
    background:
      radial-gradient(20rem 14rem at 100% -20%, rgba(155, 130, 255, 0.16), transparent 70%),
      var(--surface-2);
    border-bottom: 1px solid var(--hairline);
  }
  .aside-body .display { font-size: 27px; max-width: none; }
  .aside-body .subtitle { max-width: none; margin-top: 10px; font-size: 14px; }

  .composer-main { order: 2; padding: 22px 20px 24px; }

  .composer-foot { flex-direction: column-reverse; align-items: stretch; gap: 8px; }
  .composer-foot .btn { width: 100%; }
  .composer-note { max-width: none; margin: 0; text-align: center; }

  /* Status first, reassurance art second. Leading with the art on a narrow
     screen buries the one thing the user opened the page to check. */
  .build { grid-template-columns: minmax(0, 1fr); }
  .build-art { min-height: 170px; border-left: none; border-top: 1px solid var(--hairline); }
  .build-art .cap { margin-top: 14px; }
  .build-slide img { max-width: 260px; }

  .setup { grid-template-columns: minmax(0, 1fr); min-height: 0; }
  .setup-aside { order: 1; border-right: none; border-bottom: 1px solid var(--hairline); padding: 26px 20px; }
  .setup-aside .display { font-size: 27px; max-width: none; }
  .setup-aside .subtitle { max-width: none; font-size: 14px; }
  .setup-aside .rail { display: none; }
  .setup-main { order: 2; padding: 22px 20px 26px; }
  .setup-foot .btn { width: 100%; }

  .trust-grid { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 760px) {
  .hide-mobile { display: none !important; }
  .only-mobile { display: initial; }
  .topbar { min-height: 56px; margin-bottom: 16px; }
  .brand > span { display: none; }
  .account { height: 44px; width: 44px; padding: 0; justify-content: center; }
  .metrics { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .spec { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .spec > div + div { border-left: none; }
  .spec > div:nth-child(even) { border-left: 1px solid var(--hairline); }
  .spec > div:nth-child(n + 3) { border-top: 1px solid var(--hairline); }
  .spec.wide > div,
  .spec.wide[data-cells="5"] > div:nth-child(-n+3),
  .spec.wide[data-cells="5"] > div:nth-child(n+4) { grid-column: span 3; border-top: 0; }
  .spec.wide[data-cells="5"] > div:nth-child(5) { grid-column: span 6; }

  .page-head { display: block; }
  .page-head .display { max-width: none; font-size: 27px; }
  .dep { padding: 16px; }
  .dep-head { flex-wrap: wrap; }
  /* A lone overflow button stays beside the title; a pair takes its own row so
     the primary action can run the full width. */
  .dep-actions { width: 100%; }
  .dep-actions.compact { width: auto; margin-left: auto; }
  .dep-actions .btn:first-child { flex: 1 1 auto; }
  .menu-pop { min-width: min(280px, calc(100vw - 48px)); }

  .usage-line { display: grid; gap: 2px; }
  .usage-line span { text-align: left; }
}

@media (max-width: 420px) {
  .disclosure > summary { flex-wrap: wrap; padding: 12px 14px; position: relative; }
  .disclosure > summary .state { flex-basis: 100%; margin: 2px 0 0 28px; }
  .disclosure > summary .caret { position: absolute; right: 14px; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
}

/* An action that exists but is not yet usable during a build. Carried over
   from the container-actions work on main: it must read as deliberately
   unavailable, not as a broken control. */
.container-action--unavailable:disabled,
.container-action--unavailable:disabled:hover {
  border-color: var(--hairline);
  background: var(--surface-2);
  color: var(--ink-3);
  box-shadow: none;
  opacity: 0.48;
  transform: none;
  cursor: default;
}
