/* Shared styling for every Tenant App page (index.html, stack.html, welcome.html, settings.html).
   Issue #582 pulled this out of index.html's own inline <style> block (issues #579/#580/#581) so a
   second and third page didn't have to duplicate ~180 lines of CSS. Loaded via `<link
   rel="stylesheet" href="/style.css">`; still just a plain static file, no bundler, same
   zero-build-step posture as the rest of this directory (see README.md). CSP
   (`static-files.ts::STATIC_SECURITY_HEADERS`) allows `style-src 'self'`, so this external file
   works the same as the inline block it replaced.

   The signed-in surfaces (the account home's All Stacks index and the per-Stack console) follow the
   "Stack console layouts" design in the Zozo design-system project: a full-bleed app topbar over a
   wide content column, with the Stack itself ranked above account chrome. The signed-out and
   onboarding surfaces keep the narrow centered card they have always had. */

/* --------------------------------------------------------------------------
   Tokens. A subset of design-system/tokens/*.css, inlined here because this
   directory ships verbatim with no build step to import them.
   -------------------------------------------------------------------------- */
:root {
  --zz-bg-base: #0b0d11;
  --zz-bg-surface: #12151d;
  --zz-bg-surface-2: #161b24;
  --zz-bg-elevated: #1c222d;
  --zz-bg-hover: #1a202b;
  --zz-border-subtle: #1c222d;
  --zz-border: #272e3a;
  --zz-border-strong: #39424f;
  --zz-text-primary: #e9ecf1;
  --zz-text-secondary: #a8afbd;
  --zz-text-tertiary: #6c7686;
  --zz-text-disabled: #4a515f;
  --zz-text-inverse: #0b0d11;
  --zz-accent: #3b82f6;
  --zz-accent-hover: #5c97ff;
  --zz-accent-text: #8fbaff;
  --zz-accent-soft: rgba(59, 130, 246, 0.14);
  --zz-accent-border: rgba(59, 130, 246, 0.38);
  --zz-success: #34d399;
  --zz-success-text: #7ee7c0;
  --zz-success-soft: rgba(126, 231, 192, 0.12);
  --zz-danger: #f2686a;
  --zz-danger-soft: rgba(242, 104, 106, 0.14);
  --zz-danger-text: #ff9d9e;
  --zz-warning-text: #f2c868;
  --zz-warning-soft: rgba(242, 200, 104, 0.12);
  --zz-focus-ring: rgba(59, 130, 246, 0.5);
  --zz-radius-xs: 3px;
  --zz-radius-sm: 5px;
  --zz-radius-md: 7px;
  --zz-radius-lg: 10px;
  --zz-font-sans: "Geist", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --zz-font-mono: "Geist Mono", ui-monospace, "SF Mono", "Cascadia Mono", Menlo, Consolas, monospace;
  --zz-topbar-h: 54px;
}

/* Geist (UI) and Geist Mono (data, IDs, hostnames), self-hosted: CSP is `font-src 'self'`, so an
   external font host would not load anyway. */
@font-face {
  font-family: "Geist";
  src: url("/fonts/Geist-Variable.woff2") format("woff2");
  font-weight: 100 900;
  font-display: swap;
}
@font-face {
  font-family: "Geist Mono";
  src: url("/fonts/GeistMono-Variable.woff2") format("woff2");
  font-weight: 100 900;
  font-display: swap;
}

* { box-sizing: border-box; }
html, body {
  margin: 0;
  height: 100%;
  background: var(--zz-bg-base);
  color: var(--zz-text-primary);
  font-family: var(--zz-font-sans);
  -webkit-font-smoothing: antialiased;
}
body {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}
main {
  width: 100%;
  max-width: 400px;
}

/* --------------------------------------------------------------------------
   The app shell. `body.app` opts a page into the full-bleed topbar plus a wide
   content column; without it a page keeps the original centered 400px card
   stack (the sign-in card and every onboarding step still use that column,
   nested inside the shell as `main.narrow`).
   -------------------------------------------------------------------------- */
body.app {
  display: block;
  padding: 0;
  height: auto;
  min-height: 100%;
}
main.page {
  max-width: 1040px;
  margin: 0 auto;
  padding: 34px 40px 56px;
}
main.narrow {
  max-width: 400px;
  margin: 0 auto;
  padding: 56px 24px 48px;
}
/* The signed-out root is a single centered authentication card. Its width and rhythm mirror the
   design reference, while the signed-in onboarding steps retain the narrow column above. */
body.app.auth-view {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
}
body.app.auth-view main.narrow {
  max-width: 389px;
  padding: 24px;
}

/* --------------------------------------------------------------------------
   Topbar. `<div class="topbar">` is the shared signed-in chrome on every page;
   pages.test.mjs reads it by that class to prove the Account & billing link is
   reachable from every step rather than from one card.
   -------------------------------------------------------------------------- */
.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 16px;
}
body.app .topbar {
  position: relative;
  gap: 20px;
  justify-content: flex-start;
  height: var(--zz-topbar-h);
  padding: 0 24px;
  margin: 0;
  background: rgba(18, 21, 29, 0.9);
  border-bottom: 1px solid var(--zz-border);
}
.topbar-spacer { flex: 1; }

/* The canonical Zozo wordmark (design kit `components/brand/Wordmark.jsx`, same as the Dashboard's
   top-left): lowercase mono "zozo" in Geist Mono at weight 600 / -0.04em tracking, with the accent
   live-dot trailing the word (never leading it). */
.brand {
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 28px;
  font-family: var(--zz-font-mono);
  font-weight: 600;
  font-size: 15px;
  letter-spacing: -0.04em;
  color: var(--zz-text-primary);
}
.brand .dot {
  width: 0.42em;
  height: 0.42em;
  border-radius: 50%;
  background: var(--zz-accent);
  margin-left: 0.12em;
  box-shadow: 0 0 10px var(--zz-accent-border);
}
/* The same wordmark sitting in the topbar: inline, larger, no bottom margin. */
.topbar .brand {
  margin: 0;
  font-size: 19px;
  flex: none;
  text-decoration: none;
}

.topbar-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}
body.app .topbar-actions { gap: 2px; }
/* An <a> that reads as topbar navigation. Deliberately not `.button-link`, whose full-width primary
   look belongs to a card's main call to action. */
.topbar-link {
  background: transparent;
  border: 1px solid var(--zz-border-strong);
  border-radius: 8px;
  color: var(--zz-text-secondary);
  font-size: 14px;
  font-weight: 500;
  padding: 8px 14px;
  text-decoration: none;
  white-space: nowrap;
}
.topbar-link:hover { border-color: var(--zz-text-tertiary); }
body.app .topbar-link,
body.app .topbar-btn {
  border: 0;
  background: transparent;
  color: var(--zz-text-tertiary);
  font-family: inherit;
  font-size: 13px;
  font-weight: 500;
  width: auto;
  display: inline-block;
  padding: 6px 11px;
  border-radius: var(--zz-radius-sm);
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
}
body.app .topbar-link:hover,
body.app .topbar-btn:hover {
  color: var(--zz-text-primary);
  background: var(--zz-bg-elevated);
}
/* The page you are already on stays lit, so the topbar says where you are. */
body.app .topbar-link[aria-current="page"] {
  color: var(--zz-text-primary);
  background: var(--zz-bg-elevated);
}

/* Stack switcher: the current Stack, and a menu of the account's other Stacks. */
.stack-switcher { position: relative; flex: none; }
.stack-switcher[hidden] { display: none; }
.stack-switcher-btn {
  display: flex;
  align-items: center;
  gap: 9px;
  width: auto;
  background: var(--zz-bg-elevated);
  border: 1px solid var(--zz-border);
  border-radius: var(--zz-radius-sm);
  padding: 5px 10px;
  cursor: pointer;
  color: var(--zz-text-secondary);
  font-family: var(--zz-font-mono);
  font-size: 12.5px;
  font-weight: 400;
  text-align: left;
}
.stack-switcher-btn:hover { background: var(--zz-bg-hover); border-color: var(--zz-border-strong); }
.stack-switcher-caret { color: var(--zz-text-disabled); font-size: 10px; margin-left: auto; }
.stack-menu {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  min-width: 260px;
  z-index: 30;
  background: var(--zz-bg-surface);
  border: 1px solid var(--zz-border-strong);
  border-radius: var(--zz-radius-md);
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.5);
  padding: 6px;
}
.stack-menu-item {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 8px 10px;
  border-radius: var(--zz-radius-sm);
  font-family: var(--zz-font-mono);
  font-size: 12.5px;
  color: var(--zz-text-secondary);
  text-decoration: none;
}
.stack-menu-item:hover { background: var(--zz-bg-elevated); color: var(--zz-text-primary); }
.stack-menu-item[aria-current="page"] { color: var(--zz-text-primary); background: var(--zz-bg-elevated); }
.stack-menu-sep { height: 1px; background: var(--zz-border-subtle); margin: 6px 4px; }
.stack-menu-all {
  display: block;
  padding: 8px 10px;
  border-radius: var(--zz-radius-sm);
  font-size: 12.5px;
  color: var(--zz-accent-text);
  text-decoration: none;
}
.stack-menu-all:hover { background: var(--zz-bg-elevated); }

/* Hamburger. Hidden on desktop; on narrow viewports it is the only way to the topbar actions. */
.topbar-menu-btn {
  display: none;
  width: auto;
  flex-direction: column;
  gap: 4px;
  background: transparent;
  border: 0;
  padding: 10px 4px;
  cursor: pointer;
}
.topbar-menu-btn span { width: 17px; height: 1.5px; background: var(--zz-text-secondary); }

/* --------------------------------------------------------------------------
   Page furniture: headings, eyebrows, buttons.
   -------------------------------------------------------------------------- */
.page-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 30px;
  margin-bottom: 18px;
}
.page-head h1 { font-size: 21px; letter-spacing: -0.01em; margin: 0 0 5px; }
.page-head .lede { margin: 0; font-size: 13.5px; color: var(--zz-text-tertiary); }
.page-head-count {
  font-family: var(--zz-font-mono);
  font-size: 12px;
  color: var(--zz-text-tertiary);
  flex: none;
  white-space: nowrap;
}
.page-title {
  display: flex;
  align-items: baseline;
  gap: 12px;
  margin-bottom: 18px;
}
.page-title h1 { margin: 0; font-size: 21px; letter-spacing: -0.01em; }
.eyebrow {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--zz-text-tertiary);
  margin-bottom: 12px;
}

h1 {
  font-size: 17px;
  font-weight: 600;
  margin: 0 0 6px;
}
p.lede {
  margin: 0 0 20px;
  font-size: 13px;
  color: var(--zz-text-secondary);
  line-height: 1.5;
}
p.hint {
  margin: -8px 0 16px;
  font-size: 12px;
  color: var(--zz-text-tertiary);
  line-height: 1.4;
}
/* Standalone docs-link row not preceded by an input or button: the same look as `.hint` minus the
   negative top margin that only makes sense snugged up under a form field. */
.link-row {
  margin: 0 0 8px;
  font-size: 12px;
  color: var(--zz-text-tertiary);
  line-height: 1.4;
}
.link-row:last-child { margin-bottom: 0; }

.card {
  background: var(--zz-bg-surface);
  border: 1px solid var(--zz-border);
  border-radius: 12px;
  padding: 28px;
  margin-bottom: 16px;
}
.card:last-child { margin-bottom: 0; }
body.app main.page .card { border-radius: var(--zz-radius-md); padding: 20px 22px; }

/* Root authentication card. */
#signin-card {
  padding: 26px 25px 20px;
  border-color: var(--zz-border-strong);
}
#signin-card .brand {
  justify-content: flex-start;
  margin-bottom: 18px;
}
.signin-tabs {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 2px;
  padding: 2px;
  margin-bottom: 20px;
  background: #080a0e;
  border: 1px solid var(--zz-border);
  border-radius: var(--zz-radius-md);
}
button.signin-tab {
  width: 100%;
  padding: 7px 10px;
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--zz-radius-sm);
  color: var(--zz-text-tertiary);
  font-size: 11.5px;
  font-weight: 500;
}
button.signin-tab:hover { background: var(--zz-bg-elevated); color: var(--zz-text-secondary); }
button.signin-tab.active {
  background: var(--zz-bg-elevated);
  border-color: var(--zz-border-strong);
  color: var(--zz-text-primary);
}
#signin-card .error-banner { margin-bottom: 16px; }
#signin-card .signin-panel > :last-child { margin-bottom: 0; }
#signin-card .signin-panel .lede {
  margin-bottom: 16px;
  color: var(--zz-text-tertiary);
  font-size: 11.5px;
  line-height: 1.55;
}
#signin-card .signin-panel label { margin-top: 0; font-size: 11px; }
#signin-card .signin-panel input[type="text"] {
  margin-bottom: 12px;
  padding: 8px 12px;
  font-size: 12px;
}
#signin-card .signin-panel button:not(.signin-tab) {
  padding: 10px 14px;
  font-size: 12px;
}
.request-access {
  margin: 11px 0 0;
  color: var(--zz-text-tertiary);
  font-size: 11px;
  line-height: 1.4;
}
.request-access a { color: var(--zz-accent-text); text-decoration: none; }
.request-access a:hover { text-decoration: underline; }
.signin-footer {
  margin-top: 18px;
  padding-top: 17px;
  border-top: 1px solid var(--zz-border);
}
.signin-footer .docs-link { color: var(--zz-text-tertiary); }
#signin-card .signin-footer .docs-link { font-size: 11px; }

.error-banner {
  display: none;
  background: var(--zz-danger-soft);
  border: 1px solid rgba(242, 104, 106, 0.3);
  color: var(--zz-danger-text);
  border-radius: 8px;
  padding: 10px 12px;
  font-size: 13px;
  line-height: 1.4;
  margin-bottom: 16px;
}
.warning-banner {
  background: var(--zz-warning-soft);
  border: 1px solid rgba(242, 200, 104, 0.3);
  color: var(--zz-warning-text);
  border-radius: 8px;
  padding: 10px 12px;
  font-size: 12px;
  line-height: 1.5;
  margin-bottom: 16px;
}
/* Issue #582's /welcome payment-confirmation banner: the success-toned sibling of .warning-banner,
   using the same --zz-success-text token the status block renders "Your Stack is ready" copy in. */
.success-banner {
  background: var(--zz-success-soft);
  border: 1px solid rgba(126, 231, 192, 0.3);
  color: var(--zz-success-text);
  border-radius: 8px;
  padding: 10px 12px;
  font-size: 12px;
  line-height: 1.5;
  margin-bottom: 16px;
}

label {
  display: block;
  font-size: 12px;
  color: var(--zz-text-tertiary);
  margin-bottom: 6px;
}
input[type="text"] {
  width: 100%;
  background: var(--zz-bg-elevated);
  border: 1px solid var(--zz-border-strong);
  border-radius: 8px;
  color: var(--zz-text-primary);
  font-family: inherit;
  font-size: 14px;
  padding: 10px 12px;
  margin-bottom: 16px;
}
input[type="text"]:focus {
  outline: none;
  border-color: var(--zz-accent);
  box-shadow: 0 0 0 3px var(--zz-focus-ring);
}
button, .button-link {
  display: block;
  width: 100%;
  background: var(--zz-accent);
  color: #fff;
  border: none;
  border-radius: 8px;
  font-family: inherit;
  font-size: 14px;
  font-weight: 600;
  padding: 11px 14px;
  cursor: pointer;
  text-align: center;
  text-decoration: none;
}
button:hover, .button-link:hover { background: var(--zz-accent-hover); }
button.secondary {
  width: auto;
  background: transparent;
  border: 1px solid var(--zz-border-strong);
  color: var(--zz-text-secondary);
  font-weight: 500;
  padding: 8px 14px;
}
button.secondary:hover { border-color: var(--zz-text-tertiary); background: transparent; }
/* Destructive action (Stack deletion, issue #1743). Reads clearly as danger and dims while the
   typed Stack Slug confirmation has not yet matched (the button stays `disabled` until it does). */
button.danger {
  background: var(--zz-danger-soft);
  border: 1px solid var(--zz-danger);
  color: var(--zz-danger-text);
}
button.danger:hover:not(:disabled) { background: rgba(242, 104, 106, 0.22); }
button.danger:disabled { opacity: 0.5; cursor: not-allowed; }

/* Inline controls used across the redesigned signed-in surfaces. `.btn` beats the bare `button`
   rule above on specificity, so these stay auto-width rather than full-bleed. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: auto;
  font-family: inherit;
  font-size: 12.5px;
  font-weight: 500;
  border-radius: var(--zz-radius-sm);
  padding: 7px 14px;
  border: 1px solid transparent;
  cursor: pointer;
  text-align: center;
  text-decoration: none;
  white-space: nowrap;
}
.btn-primary {
  background: var(--zz-accent);
  border-color: var(--zz-accent);
  color: var(--zz-text-inverse);
  font-weight: 600;
}
.btn-primary:hover { background: var(--zz-accent-hover); border-color: var(--zz-accent-hover); }
.btn-lg { font-size: 13.5px; padding: 10px 20px; }
.btn-ghost {
  background: transparent;
  border-color: var(--zz-border);
  color: var(--zz-text-secondary);
}
.btn-ghost:hover { border-color: var(--zz-border-strong); color: var(--zz-text-primary); background: transparent; }
.btn-quiet {
  background: var(--zz-bg-elevated);
  border-color: var(--zz-border-strong);
  color: var(--zz-text-primary);
}
.btn-quiet:hover { background: var(--zz-bg-hover); color: var(--zz-text-primary); }
.btn:disabled,
.btn[aria-disabled="true"] {
  background: transparent;
  border-color: var(--zz-border-subtle);
  color: var(--zz-text-disabled);
  cursor: not-allowed;
}

/* --------------------------------------------------------------------------
   The Stack hero (status-block.mjs). One big card carrying the only thing
   anyone opens this page for: the Stack, its state, and the way into its
   Dashboard. Wraps by flex-basis rather than a media query so the same block
   also reads correctly inside /welcome's narrow column.
   -------------------------------------------------------------------------- */
.stack-hero {
  background: var(--zz-bg-surface);
  border: 1px solid var(--zz-border);
  border-radius: var(--zz-radius-lg);
  overflow: hidden;
  margin-bottom: 22px;
  /* The hero is reused verbatim in two very different columns: the full-width per-Stack console and
     /welcome's 400px card stack, the second of which is narrow on a wide viewport. Sizing it against
     its own width rather than the viewport's is what lets one block serve both. */
  container-type: inline-size;
}
.stack-hero-main {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: 18px 40px;
  padding: 26px 28px;
}
.stack-hero-info { flex: 1 1 320px; min-width: 0; }
.stack-hero-actions {
  display: flex;
  flex-direction: column;
  gap: 8px;
  flex: 0 1 auto;
  min-width: 190px;
}
.stack-hero-actions .btn { width: 100%; }
.stack-hero-host {
  font-family: var(--zz-font-mono);
  font-size: 22px;
  font-weight: 500;
  color: var(--zz-text-primary);
  letter-spacing: -0.02em;
  margin-bottom: 8px;
  overflow-wrap: anywhere;
}
.stack-hero-lede {
  margin: 0;
  font-size: 13.5px;
  color: var(--zz-text-tertiary);
  line-height: 1.55;
}
.status-pill {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 10px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--zz-success-text);
}
.status-pill-pending { color: var(--zz-warning-text); }
.live-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--zz-success);
  box-shadow: 0 0 8px var(--zz-success);
  flex: none;
}
.status-pill-pending .live-dot { background: var(--zz-warning-text); box-shadow: 0 0 8px var(--zz-warning-text); }

/* The Plan / Region / Created strip along the foot of the hero and of a Stack card. */
.meta-strip {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  border-top: 1px solid var(--zz-border-subtle);
  background: var(--zz-bg-surface-2);
}
.meta-cell { padding: 12px 20px; border-right: 1px solid var(--zz-border-subtle); min-width: 0; }
.meta-cell:first-child { padding-left: 28px; }
.meta-cell:last-child { border-right: 0; }
.meta-cell-label {
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--zz-text-tertiary);
  margin-bottom: 4px;
}
.meta-cell-value {
  font-family: var(--zz-font-mono);
  font-size: 12.5px;
  color: var(--zz-text-secondary);
  overflow-wrap: anywhere;
}

@container (max-width: 470px) {
  .stack-hero-main { padding: 18px 16px; gap: 15px; }
  .stack-hero-host { font-size: 15px; }
  .stack-hero-actions { min-width: 0; flex: 1 1 100%; }
  .meta-cell { padding: 11px 14px; }
  .meta-cell:first-child { padding-left: 14px; }
  .meta-cell-label { font-size: 9.5px; }
  .meta-cell-value { font-size: 12px; }
}

/* --------------------------------------------------------------------------
   Stack management: the demoted two-up utility row under the hero.
   -------------------------------------------------------------------------- */
.card-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
}
.card-grid > .card { margin-bottom: 0; }
/* The delete card grows a typed-confirmation form when the Stack is actually deletable; that is
   far too tall for one half of a two-up row, so it takes the full width in that state. */
.card-grid > .span-2 { grid-column: 1 / -1; }

/* --------------------------------------------------------------------------
   The All Stacks index (index.html's account home). One full-width row per
   Stack, the hero's metadata strip re-read as list columns, and capacity plus
   trial state collapsed into a single quiet footer row.
   -------------------------------------------------------------------------- */
.stack-table {
  border: 1px solid var(--zz-border);
  border-radius: var(--zz-radius-lg);
  overflow: hidden;
  background: var(--zz-bg-surface);
}
.stack-table-head,
.stack-row {
  display: grid;
  grid-template-columns: 1fr 120px 100px 130px 160px;
  gap: 16px;
  align-items: center;
}
.stack-table-head {
  padding: 9px 22px;
  background: var(--zz-bg-surface-2);
  border-bottom: 1px solid var(--zz-border-subtle);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--zz-text-tertiary);
}
.stack-list { display: block; }
.stack-row { padding: 16px 22px; }
.stack-row + .stack-row { border-top: 1px solid var(--zz-border-subtle); }
.stack-row-name { min-width: 0; }
/* The wrapper dissolves on the desktop grid so Plan, Region, and Created are real columns; on a
   narrow viewport it becomes a block and regroups them into one dense line. */
.stack-row-cells { display: contents; }
.stack-row-host {
  display: flex;
  align-items: center;
  gap: 9px;
  margin-bottom: 4px;
}
.stack-slug {
  font-family: var(--zz-font-mono);
  font-size: 14.5px;
  color: var(--zz-text-primary);
  letter-spacing: -0.01em;
  overflow-wrap: anywhere;
}
.stack-detail {
  margin: 0;
  font-size: 12px;
  color: var(--zz-text-tertiary);
  padding-left: 16px;
}
.stack-cell {
  font-family: var(--zz-font-mono);
  font-size: 12.5px;
  color: var(--zz-text-secondary);
  min-width: 0;
  overflow-wrap: anywhere;
}
.stack-row-actions { display: flex; justify-content: flex-end; gap: 7px; }

/* The live-dot colors carry Stack health in the list, so a healthy row needs no badge at all. */
.stack-health-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  flex: none;
  background: var(--zz-text-disabled);
}
.stack-health-live { background: var(--zz-success); box-shadow: 0 0 8px var(--zz-success); }
.stack-health-provisioning { background: var(--zz-warning-text); box-shadow: 0 0 8px var(--zz-warning-text); }
.stack-health-suspended,
.stack-health-deprovisioning,
.stack-health-deprovisioned { background: var(--zz-danger); box-shadow: 0 0 8px var(--zz-danger); }

/* Capacity and trial state, demoted to one quiet footer row with the add action beside it. */
.stack-table-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding: 14px 22px;
  border-top: 1px solid var(--zz-border-subtle);
  background: var(--zz-bg-surface-2);
}
.stack-table-foot-copy {
  display: flex;
  align-items: center;
  gap: 14px;
  min-width: 0;
}
.cap-meter { display: flex; gap: 4px; flex: none; }
.cap-meter span {
  width: 26px;
  height: 5px;
  border-radius: 999px;
  background: var(--zz-border);
}
.cap-meter span.used { background: var(--zz-accent); }
.cap-note {
  margin: 0;
  font-size: 12.5px;
  color: var(--zz-text-tertiary);
  line-height: 1.5;
}
/* A genuine problem (unpaid invoice, suspended account, cap reached) still reads as a warning; only
   the trial notice is demoted to the quiet footer voice. */
.cap-note-warn { color: var(--zz-warning-text); }
.stack-table-foot .btn { flex: none; }

/* --------------------------------------------------------------------------
   Onboarding steps and per-Stack forms carried over unchanged.
   -------------------------------------------------------------------------- */
.plan-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 16px; }
.plan-option {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--zz-border);
  border-radius: var(--zz-radius-md);
  background: var(--zz-bg-surface-2);
  padding: 18px;
}
.plan-option h2 { margin-top: 0; font-size: 15px; }
.plan-option > button { margin-top: auto; }
.plan-option > button:disabled {
  background: var(--zz-bg-elevated);
  color: var(--zz-text-disabled);
  cursor: not-allowed;
}
.plan-change-panel { border-top: 1px solid var(--zz-border); margin-top: 20px; padding-top: 18px; }
.plan-change-panel h2 { margin-top: 0; font-size: 15px; }
.plan-change-warning {
  background: var(--zz-warning-soft);
  border-left: 3px solid var(--zz-warning-text);
  color: var(--zz-text-secondary);
  border-radius: var(--zz-radius-xs);
  padding: 12px;
  font-size: 12.5px;
  line-height: 1.5;
}
.plan-price { font-size: 1.35rem; font-weight: 650; }

.delete-effects { margin: 0 0 16px; padding-left: 20px; color: var(--zz-text-secondary); font-size: 13px; line-height: 1.55; }
.delete-effects li { margin-bottom: 6px; }
.delete-label { display: block; margin-bottom: 8px; font-size: 13px; color: var(--zz-text-secondary); }

.meta {
  font-family: var(--zz-font-mono);
  font-size: 12px;
  color: var(--zz-text-tertiary);
}
.docs-link {
  display: inline-block;
  font-size: 12px;
  color: var(--zz-accent-text);
  text-decoration: none;
}
.docs-link:hover { text-decoration: underline; }
.slug-preview {
  color: var(--zz-text-primary);
  font-weight: 600;
}
.spinner {
  width: 22px;
  height: 22px;
  margin: 4px auto 2px;
  border-radius: 50%;
  border: 2px solid var(--zz-border-strong);
  border-top-color: var(--zz-accent);
  animation: zz-spin 0.8s linear infinite;
}
@keyframes zz-spin { to { transform: rotate(360deg); } }

/* New-Stack flow (issue #1742, ADR-0133): a compact expansion below the All Stacks index. */
.new-stack { margin-top: 12px; }
.new-stack-form > .eyebrow { margin-bottom: 10px; }
.new-stack-panel {
  overflow: hidden;
  background: var(--zz-bg-surface);
  border: 1px solid var(--zz-border);
  border-radius: var(--zz-radius-md);
}
.new-stack-body { padding: 20px 21px 16px; }
.new-stack-body > .lede {
  max-width: 760px;
  margin-bottom: 18px;
  font-size: 12px;
  color: var(--zz-text-tertiary);
}
#new-stack-quote h3 {
  font-size: 15px;
  font-weight: 600;
  margin: 0 0 8px;
}
.new-stack-field {
  display: grid;
  grid-template-columns: 148px minmax(0, 394px);
  gap: 20px;
  align-items: start;
  margin-top: 14px;
}
.new-stack-field-copy label,
.new-stack-field-label {
  display: block;
  margin: 0 0 2px;
  color: var(--zz-text-primary);
  font-size: 12px;
  font-weight: 600;
}
.new-stack-field-copy .hint {
  margin: 0;
  font-size: 10.5px;
  line-height: 1.45;
}
.new-stack-slug-control { display: flex; }
.new-stack-slug-control input[type="text"] {
  min-width: 0;
  margin: 0;
  padding: 8px 12px;
  border-radius: var(--zz-radius-sm) 0 0 var(--zz-radius-sm);
  background: #0b0d11;
  font-family: var(--zz-font-mono);
  font-size: 12px;
}
.new-stack-slug-suffix {
  display: flex;
  align-items: center;
  flex: none;
  padding: 0 11px;
  border: 1px solid var(--zz-border);
  border-left: 0;
  border-radius: 0 var(--zz-radius-sm) var(--zz-radius-sm) 0;
  background: var(--zz-bg-elevated);
  color: var(--zz-text-disabled);
  font-family: var(--zz-font-mono);
  font-size: 10.5px;
}
.new-stack-field-control > .error-banner { margin: 8px 0 0; }
.new-stack-plans {
  min-width: 0;
  border: 1px solid var(--zz-border);
  border-radius: var(--zz-radius-sm);
  padding: 0;
  margin: 0;
  overflow: hidden;
}
.new-stack-plan {
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: 1px 11px;
  align-items: baseline;
  min-height: 48px;
  padding: 8px 12px;
  cursor: pointer;
  color: var(--zz-text-primary);
}
.new-stack-plan + .new-stack-plan { border-top: 1px solid var(--zz-border); }
.new-stack-plan input[type="radio"] { grid-row: span 2; margin: 0; align-self: center; }
.new-stack-plan-name { font-size: 11.5px; font-weight: 600; }
.new-stack-plan .hint {
  grid-column: 2;
  margin: 0;
  font-family: var(--zz-font-mono);
  font-size: 9.5px;
  white-space: nowrap;
}
.new-stack-plan-price {
  grid-column: 3;
  grid-row: 1 / span 2;
  align-self: center;
  color: var(--zz-text-secondary);
  font-family: var(--zz-font-mono);
  font-size: 10px;
}
.new-stack-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  min-height: 51px;
  padding: 10px 21px;
  border-top: 1px solid var(--zz-border-subtle);
  background: var(--zz-bg-surface-2);
}
.new-stack-action-buttons { display: flex; align-items: center; gap: 8px; }
.new-stack-actions .btn { font-size: 11px; padding: 7px 14px; }
.new-stack-actions .new-stack-cancel {
  background: transparent;
  border-color: transparent;
  color: var(--zz-text-tertiary);
}
.new-stack-actions .new-stack-cancel:hover { background: transparent; color: var(--zz-text-primary); }
.new-stack-renewal {
  margin: 0;
  color: var(--zz-text-disabled);
  font-size: 10px;
  text-align: right;
}
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.hidden { display: none; }

/* --------------------------------------------------------------------------
   Narrow viewports. The topbar collapses to the wordmark plus a menu button,
   the Stack switcher drops to its own full-width strip beneath it, and the
   Stack table's columns re-stack into one card per Stack.
   -------------------------------------------------------------------------- */
@media (max-width: 760px) {
  main.page { padding: 22px 16px 40px; }
  main.narrow { padding: 32px 16px 40px; }

  body.app .topbar {
    flex-wrap: wrap;
    height: auto;
    padding: 0 16px;
    gap: 12px;
  }
  body.app .topbar > .brand { height: 50px; }
  .topbar-menu-btn { display: flex; }
  /* The actions become a drop-down panel the menu button opens. */
  body.app .topbar-actions {
    display: none;
    order: 4;
    width: 100%;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding: 4px 0 10px;
    border-top: 1px solid var(--zz-border-subtle);
  }
  body.app .topbar.open .topbar-actions { display: flex; }
  body.app .topbar-actions .topbar-link,
  body.app .topbar-actions .topbar-btn {
    display: block;
    width: 100%;
    text-align: left;
    font-size: 14px;
    padding: 11px 8px;
  }
  /* The switcher becomes the full-width strip under the header. */
  .stack-switcher {
    order: 3;
    margin: 0 -16px;
    width: calc(100% + 32px);
  }
  .stack-switcher-btn {
    width: 100%;
    border: 0;
    border-top: 1px solid var(--zz-border-subtle);
    border-bottom: 1px solid var(--zz-border-subtle);
    border-radius: 0;
    background: var(--zz-bg-surface-2);
    padding: 10px 16px;
  }
  .stack-menu { left: 8px; right: 8px; min-width: 0; }

  .page-head { flex-direction: column; align-items: flex-start; gap: 8px; }
  .page-head h1,
  .page-title h1 { font-size: 19px; }
  /* The index's own X-of-Y count is dropped here rather than stacked above its heading: the footer
     meter below already carries capacity, and this narrow a column has no room to say it twice. */
  .page-head .page-head-count { display: none; }

  .card-grid { grid-template-columns: 1fr; gap: 12px; }
  body.app main.page .card { padding: 16px; }

  /* One card per Stack: the header row goes away and each row stacks. */
  .stack-table-head { display: none; }
  .stack-row {
    grid-template-columns: 1fr;
    gap: 10px;
    padding: 15px 16px;
  }
  .stack-slug { font-size: 13px; }
  .stack-detail { padding-left: 16px; }
  /* Plan, Region, and Created read as one dense mono line rather than three stacked rows. */
  .stack-row-cells { display: block; padding-left: 15px; }
  .stack-row .stack-cell {
    display: inline-block;
    margin-right: 18px;
    font-size: 12px;
    color: var(--zz-text-tertiary);
  }
  .stack-row-actions { justify-content: stretch; }
  .stack-row-actions .btn { padding: 11px 16px; font-size: 13.5px; }
  .stack-row-actions .btn-primary { flex: 1; }

  .stack-table-foot { flex-direction: column; align-items: stretch; gap: 11px; }
  .stack-table-foot-copy { flex-direction: column; align-items: stretch; gap: 8px; }
  .cap-meter span { width: auto; flex: 1; }
  .stack-table-foot .btn { width: 100%; padding: 10px 14px; font-size: 13px; }

  .new-stack-field { grid-template-columns: 1fr; gap: 8px; }
  .new-stack-body { padding: 18px 16px 14px; }
  .new-stack-actions { align-items: stretch; flex-direction: column; gap: 8px; padding: 12px 16px; }
  .new-stack-action-buttons { width: 100%; }
  .new-stack-action-buttons .btn-primary { flex: 1; }
  .new-stack-renewal { text-align: left; }
}
