@stacksjs/ts-cloud 0.7.68 → 0.7.69

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/dist/bin/cli.js +1125 -1125
  2. package/dist/{chunk-349k40rw.js → chunk-j6zaxywt.js} +30 -10
  3. package/dist/deploy/index.js +1 -1
  4. package/dist/index.js +1 -1
  5. package/dist/queue/queue.d.ts +8 -0
  6. package/dist/queue/worker.d.ts +2 -0
  7. package/dist/ui/account/automation.html +3 -3
  8. package/dist/ui/account/security.html +2 -2
  9. package/dist/ui/applications/compose.html +3 -3
  10. package/dist/ui/applications/new.html +2 -2
  11. package/dist/ui/data/backups.html +4 -4
  12. package/dist/ui/data/services.html +4 -4
  13. package/dist/ui/data/volumes.html +4 -4
  14. package/dist/ui/index.html +4 -4
  15. package/dist/ui/integrations.html +2 -2
  16. package/dist/ui/operations/alerts.html +4 -4
  17. package/dist/ui/operations/configuration.html +4 -4
  18. package/dist/ui/operations/jobs.html +4 -4
  19. package/dist/ui/operations/maintenance.html +4 -4
  20. package/dist/ui/operations/observability.html +4 -4
  21. package/dist/ui/operations/previews.html +4 -4
  22. package/dist/ui/operations/queue.html +3 -3
  23. package/dist/ui/operations/regions.html +4 -4
  24. package/dist/ui/operations/releases.html +3 -3
  25. package/dist/ui/operations/workloads.html +3 -3
  26. package/dist/ui/security.html +2 -2
  27. package/dist/ui/server/actions.html +4 -4
  28. package/dist/ui/server/activity.html +2 -2
  29. package/dist/ui/server/capacity.html +4 -4
  30. package/dist/ui/server/database.html +3 -3
  31. package/dist/ui/server/deployments.html +3 -3
  32. package/dist/ui/server/diagnostics.html +2 -2
  33. package/dist/ui/server/firewall.html +4 -4
  34. package/dist/ui/server/fleet.html +4 -4
  35. package/dist/ui/server/logs.html +4 -4
  36. package/dist/ui/server/metrics.html +4 -4
  37. package/dist/ui/server/security.html +2 -2
  38. package/dist/ui/server/services.html +2 -2
  39. package/dist/ui/server/sites.html +4 -4
  40. package/dist/ui/server/ssh-keys.html +4 -4
  41. package/dist/ui/server/team.html +4 -4
  42. package/dist/ui/server/terminal.html +2 -2
  43. package/dist/ui/serverless/alarms.html +4 -4
  44. package/dist/ui/serverless/assets.html +2 -2
  45. package/dist/ui/serverless/cost.html +2 -2
  46. package/dist/ui/serverless/data.html +4 -4
  47. package/dist/ui/serverless/firewall.html +2 -2
  48. package/dist/ui/serverless/functions.html +4 -4
  49. package/dist/ui/serverless/logs.html +4 -4
  50. package/dist/ui/serverless/metrics.html +2 -2
  51. package/dist/ui/serverless/queues.html +4 -4
  52. package/dist/ui/serverless/secrets.html +4 -4
  53. package/dist/ui/serverless/traces.html +4 -4
  54. package/dist/ui/serverless.html +4 -4
  55. package/package.json +3 -3
@@ -84,7 +84,7 @@ var { opOutput, opShown, pending, typed, busy, confirmTok, confirmVerb, confirmD
84
84
  });
85
85
 
86
86
  return { opOutput, opShown, pending, typed, busy, confirmTok, confirmVerb, confirmDanger, confirmLabel, canRun, askOp, cancelOp, runOp };
87
- })</script> <!DOCTYPE html><html lang="en" data-theme="dark"><head><meta name="title" content="stx Project"><meta name="description" content="A website built with stx templating engine"><meta property="og:title" content="stx Project"><meta property="og:description" content="A website built with stx templating engine"><meta property="og:type" content="website"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:title" content="stx Project"><meta name="twitter:description" content="A website built with stx templating engine"><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>ts-cloud - Services</title><link rel="icon" type="image/svg+xml" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect x='3' y='3' width='26' height='26' rx='8' fill='%235a8be0'/%3E%3C/svg%3E"><link rel="preconnect" href="https://fonts.googleapis.com"><link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet"><style> :root { --bg: #0a0e15; --bg2: #0b0f18; --panel: rgba(255,255,255,0.03); --panel-br: rgba(255,255,255,0.072); --txt: #e9edf5; --txt2: #94a1b8; --txt3: #5a6577; --accent: #5a8be0; --accent-dim: rgba(90,139,224,0.14); --accent-ink: #061019; --ok: #35d19b; --okbg: rgba(53,209,155,0.11); --bad: #f0736e; --badbg: rgba(240,115,110,0.11); --warn: #edb949; --warnbg: rgba(237,185,73,0.11); --mono: ui-monospace, 'SF Mono', SFMono-Regular, Menlo, Consolas, monospace; } * { box-sizing: border-box; margin: 0; padding: 0; } html { background: var(--bg); min-height: 100%; } body { font-family: 'Inter', system-ui, sans-serif; color: var(--txt); min-height: 100vh; /* One calm accent wash, no AI blue-purple mesh. */ background: radial-gradient(900px 460px at 88% -8%, rgba(90,139,224,0.06), transparent 62%), linear-gradient(175deg, var(--bg), var(--bg2)); -webkit-font-smoothing: antialiased; font-feature-settings: 'tnum' 1, 'ss01' 1; padding-left: 248px; overflow-x: hidden; } /* Tabular monospaced numerals wherever a value is read at a glance (density 7). */ .stat, .gauge .pct, .vital .vval, .health-hero .hmeta .item b, .kv > b, td.mono { font-variant-numeric: tabular-nums; } .stat, .gauge .pct { font-family: var(--mono); letter-spacing: -0.03em; } a { color: inherit; text-decoration: none; } .wrap { max-width: 1240px; margin: 0 auto; padding: 0 28px 64px; min-width: 0; } .skip-link { position: fixed; z-index: 100; top: 8px; left: 264px; transform: translateY(-150%); background: var(--accent); color: var(--accent-ink); border-radius: 8px; padding: 8px 12px; font-size: 13px; font-weight: 800; } .skip-link:focus { transform: translateY(0); } .app-sidebar { position: fixed; inset: 0 auto 0 0; z-index: 30; width: 248px; display: flex; flex-direction: column; background: rgba(9,13,20,0.96); border-right: 1px solid var(--panel-br); backdrop-filter: blur(18px); padding: 18px 14px 14px; overflow-y: auto; overscroll-behavior: contain; } .brand { display: flex; align-items: center; gap: 10px; min-height: 38px; padding: 0 8px; font-weight: 800; font-size: 17px; letter-spacing: -0.02em; } .brand .dot { width: 20px; height: 20px; border-radius: 6px; background: var(--accent); box-shadow: inset 0 1px 0 rgba(255,255,255,0.35); } .sidebar-context { display: grid; gap: 3px; margin-top: 16px; padding: 12px; border: 1px solid var(--panel-br); border-radius: 12px; background: rgba(255,255,255,0.025); } .sidebar-context strong { font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .context-label { color: var(--txt3); font-size: 10px; font-weight: 800; letter-spacing: .09em; text-transform: uppercase; } .context-detail { color: var(--txt3); font-size: 11px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .environment-picker { display: grid; gap: 6px; margin: 14px 4px 4px; } .environment-picker details { position: relative; } .environment-current { display: flex; align-items: center; gap: 8px; min-height: 38px; padding: 7px 9px; cursor: pointer; list-style: none; border: 1px solid var(--panel-br); border-radius: 10px; background: rgba(255,255,255,0.03); } .environment-current::-webkit-details-marker { display: none; } .environment-current::after { content: '⌄'; margin-left: auto; color: var(--txt3); } .environment-current > span { min-width: 36px; padding: 3px 5px; border-radius: 5px; background: var(--accent-dim); color: var(--accent); font: 800 9px var(--mono); text-align: center; letter-spacing: .06em; } .environment-current.production > span { background: var(--warnbg); color: var(--warn); } .environment-current strong { font-size: 12px; text-transform: capitalize; } .environment-menu { position: absolute; z-index: 40; top: calc(100% + 6px); left: 0; right: 0; padding: 5px; border: 1px solid var(--panel-br); border-radius: 11px; background: #111722; box-shadow: 0 14px 36px rgba(0,0,0,.4); } .environment-menu a { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 8px; border-radius: 7px; font-size: 12px; text-transform: capitalize; } .environment-menu a:hover, .environment-menu a.active { background: var(--accent-dim); color: var(--accent); } .environment-menu small { color: var(--txt3); font-size: 9px; text-transform: uppercase; letter-spacing: .05em; } .command-trigger { display: flex; align-items: center; justify-content: space-between; gap: 8px; width: calc(100% - 8px); margin: 12px 4px 0; padding: 8px 9px; border: 1px solid var(--panel-br); border-radius: 9px; background: rgba(255,255,255,.025); color: var(--txt2); font: 600 12px inherit; text-align: left; } .command-trigger:hover { border-color: rgba(90,139,224,.35); color: var(--txt); } .command-trigger kbd { padding: 2px 5px; border: 1px solid var(--panel-br); border-radius: 5px; background: rgba(255,255,255,.04); color: var(--txt3); font: 600 10px var(--mono); } .nav-groups { display: grid; gap: 18px; margin-top: 20px; } .nav-group { display: grid; gap: 2px; } .nav-group h2 { padding: 0 10px 5px; color: var(--txt3); font-size: 10px; font-weight: 800; text-transform: uppercase; letter-spacing: .1em; } .nav-group a { position: relative; display: flex; align-items: center; min-height: 34px; padding: 7px 10px; border-radius: 8px; color: var(--txt2); font-size: 12.5px; font-weight: 600; } .nav-group a:hover { color: var(--txt); background: rgba(255,255,255,.035); } .nav-group a.active { color: var(--accent); background: var(--accent-dim); } .nav-group a.active::before { content: ''; position: absolute; left: -4px; width: 3px; height: 16px; border-radius: 4px; background: var(--accent); } .context-bar { position: sticky; top: 0; z-index: 20; min-height: 48px; display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 8px 28px; border-bottom: 1px solid var(--panel-br); background: rgba(10,14,21,.78); backdrop-filter: blur(14px); } .context-path { display: flex; align-items: center; gap: 12px; min-width: 0; overflow: hidden; } .context-breadcrumb { display: flex; align-items: center; gap: 8px; min-width: 0; color: var(--txt2); font-size: 12px; } .context-breadcrumb i { color: var(--txt3); font-style: normal; } .context-breadcrumb strong { color: var(--txt); text-transform: capitalize; } .context-breadcrumb small { margin-left: 7px; padding-left: 14px; border-left: 1px solid var(--panel-br); color: var(--txt3); white-space: nowrap; } .context-filters { display: flex; align-items: center; gap: 5px; min-width: 0; overflow-x: auto; } .filter-chip { flex: 0 0 auto; padding: 4px 8px; border: 1px solid rgba(90,139,224,.25); border-radius: 999px; background: var(--accent-dim); color: var(--accent); font: 700 10px var(--mono); } .filter-chip:hover { border-color: var(--accent); } .scope-safety { flex: 0 0 auto; padding: 4px 9px; border: 1px solid rgba(90,139,224,.25); border-radius: 999px; background: var(--accent-dim); color: var(--accent); font-size: 10px; font-weight: 800; text-transform: uppercase; letter-spacing: .06em; } .scope-safety.production { border-color: rgba(237,185,73,.3); background: var(--warnbg); color: var(--warn); } .env { padding: 4px 10px; border-radius: 999px; background: var(--okbg); color: var(--ok); font-weight: 600; font-size: 12px; } .signout { display: flex; margin-top: auto; padding: 18px 4px 0; } .signout button { width: 100%; appearance: none; border: 1px solid var(--panel-br); background: rgba(255,255,255,0.035); color: var(--txt2); border-radius: 8px; padding: 5px 11px; font: inherit; font-size: 12px; font-weight: 600; cursor: pointer; transition: color .12s, border-color .12s; } .signout button:hover { color: var(--txt); border-color: rgba(255,255,255,0.16); } .nav-toggle-button, .nav-scrim { display: none; } .nav-toggle-button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; } .state-page { min-height: calc(100vh - 48px); display: grid; align-content: center; justify-items: start; gap: 12px; max-width: 620px; padding: 48px 0; } .state-page .state-code { color: var(--accent); font: 800 12px var(--mono); text-transform: uppercase; letter-spacing: .12em; } .state-page h1 { font-size: clamp(28px, 5vw, 48px); letter-spacing: -.035em; } .state-page p { color: var(--txt2); max-width: 560px; font-size: 15px; line-height: 1.65; } .state-actions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 8px; } .auth-page { min-height: 100vh; display: grid; place-items: center; padding: 24px; } .auth-card { width: min(460px, 100%); display: grid; gap: 24px; padding: 28px; border: 1px solid var(--panel-br); border-radius: 18px; background: var(--panel); box-shadow: 0 24px 70px rgba(0,0,0,.35); } .auth-card .brand { padding: 0; } .auth-card h1 { margin-top: 7px; font-size: 28px; } .auth-card p { margin-top: 6px; color: var(--txt2); line-height: 1.55; } .auth-form { display: grid; gap: 14px; } .auth-form .field-block { display: grid; gap: 6px; } .auth-form .field-block input { width: 100%; } .auth-form small { color: var(--txt3); font-size: 11px; } .auth-form .btn { justify-self: stretch; } .auth-status { min-height: 20px; color: var(--txt2); font-size: 12px; } .sr-only { position: absolute !important; width: 1px !important; height: 1px !important; padding: 0 !important; margin: -1px !important; overflow: hidden !important; clip: rect(0,0,0,0) !important; white-space: nowrap !important; border: 0 !important; } .command-palette { width: min(660px, calc(100vw - 24px)); max-height: min(620px, calc(100vh - 40px)); margin: 9vh auto 0; padding: 0; overflow: hidden; border: 1px solid rgba(255,255,255,.13); border-radius: 16px; background: #0f151f; color: var(--txt); box-shadow: 0 28px 90px rgba(0,0,0,.58); } .command-palette::backdrop { background: rgba(2,5,9,.72); backdrop-filter: blur(5px); } .command-search { display: flex; align-items: center; gap: 10px; padding: 12px 14px; border-bottom: 1px solid var(--panel-br); } .command-search > span { color: var(--txt3); font-size: 22px; } .command-search input { flex: 1; min-width: 0; border: 0; outline: 0; background: transparent; color: var(--txt); font: 500 15px inherit; } .command-search input::placeholder { color: var(--txt3); } .command-close { padding: 4px 7px; border: 1px solid var(--panel-br); border-radius: 6px; color: var(--txt3); font: 700 10px var(--mono); } .command-status { padding: 12px 16px; color: var(--txt3); font-size: 12px; } .saved-views { display: grid; gap: 8px; padding: 0 14px 12px; border-bottom: 1px solid var(--panel-br); } .saved-views-heading { display: flex; align-items: center; justify-content: space-between; gap: 10px; } .saved-views h3, .command-group > h3 { color: var(--txt3); font: 800 9px var(--mono); text-transform: uppercase; letter-spacing: .08em; } .save-view-form { display: flex; align-items: center; gap: 6px; } .save-view-form input { width: 150px; min-width: 0; padding: 5px 7px; border: 1px solid var(--panel-br); border-radius: 7px; background: rgba(255,255,255,.035); color: var(--txt); font-size: 11px; } .save-view-form button, .saved-view-row button { padding: 5px 7px; border: 1px solid var(--panel-br); border-radius: 7px; color: var(--txt2); font-size: 10px; } .saved-view-list { display: flex; flex-wrap: wrap; gap: 6px; } .saved-view-row { display: inline-flex; align-items: center; overflow: hidden; border: 1px solid var(--panel-br); border-radius: 8px; } .saved-view-row a { padding: 5px 8px; color: var(--txt2); font-size: 11px; } .saved-view-row button { border: 0; border-left: 1px solid var(--panel-br); border-radius: 0; color: var(--txt3); } .saved-views.empty .saved-view-list::after { content: 'No saved views yet'; color: var(--txt3); font-size: 11px; } .tag-result-form { display: grid; grid-template-columns: 1fr 150px 32px auto; align-items: center; gap: 7px; padding: 9px 14px; border-bottom: 1px solid var(--panel-br); } .tag-result-form label { color: var(--txt3); font: 800 9px var(--mono); text-transform: uppercase; letter-spacing: .08em; } .tag-result-form input:not(.tag-color) { min-width: 0; padding: 5px 7px; border: 1px solid var(--panel-br); border-radius: 7px; background: rgba(255,255,255,.035); color: var(--txt); font-size: 11px; } .tag-result-form .tag-color { width: 32px; height: 27px; padding: 2px; border: 1px solid var(--panel-br); border-radius: 7px; background: transparent; } .tag-result-form button { padding: 5px 8px; border: 1px solid var(--panel-br); border-radius: 7px; color: var(--txt2); font-size: 10px; } .tag-result-form button:disabled { opacity: .45; cursor: not-allowed; } .command-results { display: grid; gap: 3px; max-height: 430px; overflow-y: auto; padding: 0 7px 10px; } .command-group { display: grid; gap: 3px; } .command-group > h3 { padding: 8px 10px 2px; } .command-result-row { display: grid; grid-template-columns: minmax(0, 1fr) 36px; align-items: center; } .command-results a { display: grid; grid-template-columns: 78px 1fr; gap: 10px; align-items: center; min-width: 0; padding: 10px; border-radius: 9px; } .command-results a:hover, .command-results a.selected { background: var(--accent-dim); } .favorite-result { display: grid; place-content: center; width: 30px; height: 30px; border-radius: 8px; color: var(--txt3); font-size: 17px; } .favorite-result:hover, .favorite-result.active { color: var(--warn); background: var(--warnbg); } .command-type { color: var(--txt3); font: 800 9px var(--mono); text-transform: uppercase; letter-spacing: .07em; } .command-copy { display: grid; gap: 3px; min-width: 0; } .command-copy strong, .command-copy small { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .command-copy strong { font-size: 13px; } .command-copy small { color: var(--txt3); font-size: 11px; } .command-copy mark { border-radius: 2px; background: var(--warnbg); color: var(--warn); } .command-palette footer { display: flex; flex-wrap: wrap; gap: 14px; padding: 9px 14px; border-top: 1px solid var(--panel-br); color: var(--txt3); font-size: 10px; } @media (max-width: 820px) { body { padding-left: 0; } .wrap { padding-left: 16px; padding-right: 16px; } .context-bar { padding: 8px 14px 8px 58px; } .context-breadcrumb small { display: none; } .nav-toggle-button { position: fixed; top: 9px; left: 12px; z-index: 50; width: 36px; height: 30px; display: grid; place-content: center; gap: 4px; border: 1px solid var(--panel-br); border-radius: 8px; background: #111722; cursor: pointer; } .nav-toggle-button span { display: block; width: 15px; height: 1px; background: var(--txt2); } .app-sidebar { transform: translateX(-102%); transition: transform .18s ease; box-shadow: 18px 0 48px rgba(0,0,0,.45); } .nav-scrim { position: fixed; inset: 0; z-index: 25; background: rgba(0,0,0,.58); } body.nav-open .nav-scrim { display: block; } body.nav-open .app-sidebar { transform: translateX(0); } .skip-link { left: 56px; } } @media (max-width: 420px) { .context-filters { display: none; } .saved-views-heading { align-items: stretch; flex-direction: column; } .save-view-form input { width: auto; flex: 1; } .tag-result-form { grid-template-columns: 1fr 32px auto; } .tag-result-form label { grid-column: 1 / -1; } .scope-safety { max-width: 92px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } header.page { padding-top: 22px; } header.page h1 { font-size: 23px; } .cards, .cards-3, .cards-2, .vitals { grid-template-columns: 1fr; } .panel { padding: 15px; } table { display: block; overflow-x: auto; } } header.page { padding: 30px 0 22px; display: flex; align-items: flex-start; gap: 20px; flex-wrap: wrap; } header.page h1 { font-size: 26px; font-weight: 800; letter-spacing: -0.02em; } header.page p { color: var(--txt2); margin-top: 4px; font-size: 14px; } .server-line { display: flex; flex-wrap: wrap; gap: 16px; margin-top: 14px; color: var(--txt2); font-size: 13px; } .server-line b { color: var(--txt); font-weight: 600; } .header-actions { margin-left: auto; display: flex; align-items: center; gap: 10px; } /* Breadcrumb / back link for drill-down pages */ .crumbs { display: flex; align-items: center; gap: 8px; padding-top: 26px; font-size: 13px; color: var(--txt3); } .crumbs a { color: var(--txt2); } .crumbs a:hover { color: var(--accent); } .crumbs .sep { color: var(--txt3); } .grid { display: grid; gap: 16px; } .cards { grid-template-columns: repeat(4, 1fr); } .cards-3 { grid-template-columns: repeat(3, 1fr); } .cards-2 { grid-template-columns: repeat(2, 1fr); } @media (max-width: 880px) { .cards, .cards-3, .cards-2 { grid-template-columns: repeat(2, 1fr); } } .panel { background: var(--panel); border: 1px solid var(--panel-br); border-radius: 16px; padding: 18px; backdrop-filter: blur(6px); } a.panel { display: block; transition: border-color .15s, transform .15s; } a.panel:hover { border-color: rgba(90,139,224,0.5); transform: translateY(-1px); } .panel h3 { font-size: 12px; text-transform: uppercase; letter-spacing: 0.08em; color: var(--txt3); font-weight: 700; } .stat { font-size: 28px; font-weight: 800; margin-top: 8px; letter-spacing: -0.02em; } .stat small { font-size: 14px; color: var(--txt2); font-weight: 500; } .bar { height: 7px; border-radius: 999px; background: rgba(255,255,255,0.07); margin-top: 12px; overflow: hidden; } .bar > i { display: block; height: 100%; border-radius: 999px; background: var(--accent); } .section { margin-top: 30px; } .section > h2 { font-size: 15px; font-weight: 700; margin-bottom: 12px; display: flex; align-items: center; gap: 8px; } .section > h2 .more { margin-left: auto; display: inline-flex; align-items: center; gap: 12px; font-size: 12px; font-weight: 600; color: var(--accent); } .section > h2 .more a { color: var(--accent); } .cols { display: grid; grid-template-columns: 1.6fr 1fr; gap: 16px; } @media (max-width: 880px) { .cols { grid-template-columns: 1fr; } } table { width: 100%; border-collapse: collapse; font-size: 14px; } th { text-align: left; color: var(--txt3); font-weight: 600; font-size: 12px; text-transform: uppercase; letter-spacing: 0.05em; padding: 0 12px 10px; } td { padding: 12px; border-top: 1px solid rgba(255,255,255,0.05); } tr:hover td { background: rgba(255,255,255,0.02); } .mono { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 13px; color: var(--txt2); } .pill { display: inline-flex; align-items: center; gap: 6px; padding: 3px 9px; border-radius: 999px; font-size: 12px; font-weight: 600; } .pill::before { content: ''; width: 7px; height: 7px; border-radius: 50%; background: currentColor; } .pill.ok { background: var(--okbg); color: var(--ok); } .pill.bad { background: var(--badbg); color: var(--bad); } .pill.warn { background: var(--warnbg); color: var(--warn); } .tag { padding: 2px 8px; border-radius: 6px; background: rgba(90,139,224,0.12); color: var(--accent); font-size: 12px; font-weight: 600; } .kv { display: flex; justify-content: space-between; padding: 9px 0; border-top: 1px solid rgba(255,255,255,0.05); font-size: 14px; gap: 16px; } .kv:first-of-type { border-top: 0; } .kv > span { color: var(--txt2); white-space: nowrap; } .kv > b { text-align: right; word-break: break-all; } .deploy { display: flex; align-items: center; gap: 12px; padding: 11px 0; border-top: 1px solid rgba(255,255,255,0.05); font-size: 14px; } .deploy:first-of-type { border-top: 0; } .deploy .when { margin-left: auto; color: var(--txt3); font-size: 12px; } .btn { background: var(--accent); color: var(--accent-ink); border: 0; border-radius: 10px; padding: 9px 16px; font-weight: 700; font-size: 13.5px; cursor: pointer; font-family: inherit; white-space: nowrap; transition: filter .12s, transform .12s; } .btn:hover { filter: brightness(1.06); } .btn:active { transform: translateY(1px); } .btn.ghost { background: rgba(255,255,255,0.045); border: 1px solid var(--panel-br); color: var(--txt); } .btn.ghost:hover { background: rgba(255,255,255,0.075); filter: none; } .btn.danger { background: transparent; border: 1px solid var(--badbg); color: var(--bad); } .btn.danger:hover { background: var(--badbg); filter: none; } .btn.sm { padding: 6px 12px; font-size: 12px; } .data-item { display: flex; align-items: center; gap: 12px; padding: 11px 0; border-top: 1px solid rgba(255,255,255,0.05); font-size: 14px; } .data-item:first-of-type { border-top: 0; } .data-item .detail { color: var(--txt3); font-size: 12px; } .data-item .st { margin-left: auto; } .secret { display: flex; align-items: center; gap: 12px; padding: 10px 0; border-top: 1px solid rgba(255,255,255,0.05); font-size: 14px; } .secret:first-of-type { border-top: 0; } .secret .val { margin-left: auto; color: var(--txt3); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; letter-spacing: 2px; } /* Drill-down extras */ .spark { display: flex; align-items: flex-end; gap: 3px; height: 48px; margin-top: 12px; } .spark > i { flex: 1; background: linear-gradient(180deg, var(--accent), rgba(90,139,224,0.25)); border-radius: 3px 3px 0 0; min-height: 2px; } .logs { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12.5px; line-height: 1.7; color: var(--txt2); max-height: 360px; overflow: auto; } .logs .ts { color: var(--txt3); } .logs .err { color: var(--bad); } .log-list { display: grid; gap: 10px; max-height: 680px; overflow: auto; padding-right: 4px; } .log-row { border: 1px solid rgba(255,255,255,0.07); border-radius: 12px; background: rgba(255,255,255,0.025); padding: 12px 14px; } .log-row.warn { border-color: rgba(251,191,36,0.18); background: rgba(251,191,36,0.04); } .log-row.error { border-color: rgba(248,113,113,0.2); background: rgba(248,113,113,0.045); } .log-meta { display: flex; align-items: center; flex-wrap: wrap; gap: 9px; color: var(--txt3); font-size: 12px; margin-bottom: 9px; } .log-row pre { white-space: pre-wrap; overflow-wrap: anywhere; color: var(--txt2); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12.5px; line-height: 1.55; } .timeline { display: grid; gap: 11px; } .timeline-row { display: grid; grid-template-columns: 92px 1fr auto; gap: 13px; align-items: start; border: 1px solid rgba(255,255,255,0.07); border-radius: 12px; background: rgba(255,255,255,0.025); padding: 12px 14px; } .timeline-row .type { color: var(--txt3); font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: 0.07em; } .timeline-row .title { font-weight: 800; } .timeline-row .detail { color: var(--txt2); font-size: 13px; margin-top: 3px; overflow-wrap: anywhere; } .timeline-row .when { color: var(--txt3); font-size: 12px; white-space: nowrap; } .check-list { display: grid; gap: 10px; } .check { display: grid; grid-template-columns: auto 1fr; gap: 12px; align-items: start; padding: 13px 0; border-top: 1px solid rgba(255,255,255,0.05); } .check:first-child { border-top: 0; padding-top: 0; } .check .mark { width: 12px; height: 12px; border-radius: 50%; margin-top: 4px; background: var(--ok); box-shadow: 0 0 0 4px var(--okbg); } .check.warn .mark { background: var(--warn); box-shadow: 0 0 0 4px var(--warnbg); } .check.fail .mark { background: var(--bad); box-shadow: 0 0 0 4px var(--badbg); } .check .name { font-weight: 800; } .check .detail { color: var(--txt2); font-size: 13px; margin-top: 3px; line-height: 1.45; } .port-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; } @media (max-width: 880px) { .port-grid { grid-template-columns: 1fr; } } .port-card { border: 1px solid rgba(255,255,255,0.07); border-radius: 12px; background: rgba(255,255,255,0.025); padding: 13px 14px; min-width: 0; } .port-card .top { display: flex; align-items: center; gap: 8px; justify-content: space-between; } .port-card .listen { margin-top: 8px; font-weight: 800; overflow-wrap: anywhere; } .port-card .proc { color: var(--txt3); font-size: 12px; margin-top: 5px; overflow-wrap: anywhere; } .action-runner { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; } .action-runner select { background: rgba(255,255,255,0.05); border: 1px solid var(--panel-br); border-radius: 10px; padding: 8px 10px; color: var(--txt); font-family: inherit; font-size: 13px; min-width: 150px; } .action-output { margin-top: 12px; white-space: pre-wrap; overflow: auto; max-height: 260px; border-radius: 12px; border: 1px solid rgba(255,255,255,0.07); background: rgba(0,0,0,0.22); padding: 12px; color: var(--txt2); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; line-height: 1.5; } .op-confirm { margin-top: 14px; display: flex; align-items: center; gap: 10px; flex-wrap: wrap; } .op-confirm-input { flex: 0 0 200px; background: rgba(255,255,255,0.05); border: 1px solid var(--panel-br); border-radius: 10px; padding: 8px 12px; color: var(--txt); font-family: inherit; font-size: 14px; } .op-confirm-input:focus { outline: none; border-color: var(--accent); } .note { color: var(--txt3); font-size: 12px; margin-top: 10px; } .row-actions { display: flex; gap: 8px; } .field { display: flex; gap: 8px; margin-top: 12px; } .field input { flex: 1; background: rgba(255,255,255,0.05); border: 1px solid var(--panel-br); border-radius: 10px; padding: 9px 12px; color: var(--txt); font-family: inherit; font-size: 14px; } .field input:focus { outline: none; border-color: var(--accent); } .empty { display: grid; place-items: center; gap: 6px; min-height: 132px; text-align: center; color: var(--txt3); border: 1px dashed rgba(255,255,255,0.12); border-radius: 14px; background: rgba(255,255,255,0.025); padding: 22px; } .empty strong { color: var(--txt); font-size: 14px; } .empty span { max-width: 540px; font-size: 13px; line-height: 1.5; } .empty.compact { min-height: 74px; margin-top: 10px; padding: 14px; } .form-grid { display: grid; grid-template-columns: minmax(180px, 0.7fr) minmax(280px, 1.4fr); gap: 14px; align-items: end; } .field-block { display: flex; flex-direction: column; gap: 7px; } .field-block.wide { grid-column: 1 / -1; } .field-block label, .select-filter span { color: var(--txt3); font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: 0.07em; } .field-block input, .field-block textarea, .select-filter select { width: 100%; background: rgba(255,255,255,0.05); border: 1px solid var(--panel-br); border-radius: 10px; padding: 10px 12px; color: var(--txt); font-family: inherit; font-size: 14px; } .field-block textarea { resize: vertical; min-height: 92px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; line-height: 1.5; } .field-block input:focus, .field-block textarea:focus, .select-filter select:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px rgba(90,139,224,0.12); } .form-actions { grid-column: 1 / -1; display: flex; align-items: center; gap: 12px; flex-wrap: wrap; } .msg { color: var(--txt3); font-size: 13px; } .msg.ok { color: var(--ok); } .msg.bad { color: var(--bad); } .table-actions { text-align: right; white-space: nowrap; } .filters { display: flex; align-items: center; justify-content: space-between; gap: 14px; flex-wrap: wrap; margin: 16px 0; } .segmented { display: inline-flex; padding: 4px; border: 1px solid var(--panel-br); background: rgba(255,255,255,0.035); border-radius: 12px; gap: 2px; } .segmented button { appearance: none; border: 0; background: transparent; color: var(--txt2); border-radius: 9px; padding: 7px 12px; font: inherit; font-size: 13px; font-weight: 700; cursor: pointer; } .segmented button.active { background: rgba(90,139,224,0.18); color: var(--accent); box-shadow: inset 0 0 0 1px rgba(90,139,224,0.18); } .select-filter { display: inline-flex; align-items: center; gap: 8px; } .select-filter select { min-width: 150px; padding: 8px 10px; } @media (max-width: 760px) { .form-grid { grid-template-columns: 1fr; } .filters { align-items: stretch; } .segmented, .select-filter, .select-filter select { width: 100%; } .segmented button { flex: 1; } } /* Honest action affordance: a copyable CLI command (static dashboard has no backend - the buttons would POST nowhere, so we show the exact command). */ .cmd { display: inline-flex; align-items: center; gap: 8px; padding: 6px 12px; border-radius: 10px; background: rgba(255,255,255,0.05); border: 1px solid var(--panel-br); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12.5px; color: var(--txt); white-space: nowrap; } .cmd::before { content: '$'; color: var(--txt3); } .cmd.accent { border-color: rgba(90,139,224,0.4); color: var(--accent); } .cmds { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; } /* Server dashboard components */ .svc { display: flex; flex-wrap: wrap; gap: 10px; } .svc .item { display: flex; align-items: center; gap: 8px; padding: 8px 12px; border-radius: 10px; background: rgba(255,255,255,0.03); border: 1px solid var(--panel-br); font-size: 13px; font-weight: 500; } .key { display: flex; align-items: center; gap: 12px; padding: 11px 0; border-top: 1px solid rgba(255,255,255,0.05); font-size: 14px; } .key:first-of-type { border-top: 0; } .key .fp { margin-left: auto; color: var(--txt3); font-size: 12px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; } .chart-panel { overflow: hidden; } .chart-panel.subtle { padding: 0; margin-bottom: 14px; background: transparent; border: 0; } svg.chart { display: block; width: 100%; height: auto; min-height: 150px; } svg.chart .chart-shell { fill: rgba(255,255,255,0.025); stroke: rgba(255,255,255,0.07); } svg.chart .chart-grid { stroke: rgba(255,255,255,0.08); stroke-width: 1; } svg.chart .chart-axis, svg.chart .chart-label { fill: var(--txt3); font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; } svg.chart .chart-value { fill: var(--txt); font-size: 12px; font-weight: 800; } svg.chart .chart-empty-title { fill: var(--txt); font-size: 15px; font-weight: 800; } svg.chart .chart-empty-sub { fill: var(--txt3); font-size: 12px; } svg.chart .bar-mark.ok rect { fill: var(--ok); opacity: 0.85; } svg.chart .bar-mark.warn rect { fill: var(--warn); opacity: 0.88; } svg.chart .bar-mark.bad rect { fill: var(--bad); opacity: 0.9; } svg.chart .spark-path { fill: none; stroke: var(--accent); stroke-width: 2.25; stroke-linecap: round; stroke-linejoin: round; } svg.chart circle.ok { fill: var(--ok); } svg.chart circle.bad { fill: var(--bad); } svg.chart.disabled { opacity: 0.86; } /* ───────────── Health / vital signs (server metrics) ───────────── */ /* Overall status banner - at-a-glance "is the box OK?" verdict. */ .health-hero { --hue: var(--ok); --huebg: var(--okbg); display: flex; align-items: center; gap: 18px 28px; flex-wrap: wrap; margin-top: 8px; background: radial-gradient(700px 200px at 0% 0%, var(--huebg), transparent 70%), var(--panel); border: 1px solid var(--panel-br); border-radius: 18px; padding: 18px 22px; backdrop-filter: blur(6px); } .health-hero.warn { --hue: var(--warn); --huebg: var(--warnbg); } .health-hero.bad { --hue: var(--bad); --huebg: var(--badbg); } .health-hero .status { display: inline-flex; align-items: center; gap: 12px; font-weight: 800; font-size: 17px; letter-spacing: -0.01em; color: var(--hue); } .health-hero .status .led { width: 13px; height: 13px; border-radius: 50%; background: var(--hue); box-shadow: 0 0 0 4px var(--huebg); animation: hb-pulse 2.4s ease-in-out infinite; } .health-hero .status small { display: block; color: var(--txt3); font-size: 12px; font-weight: 500; margin-top: 2px; letter-spacing: 0; } @keyframes hb-pulse { 0%, 100% { opacity: 1 } 50% { opacity: 0.5 } } .health-hero .hmeta { margin-left: auto; display: flex; flex-wrap: wrap; gap: 22px 26px; color: var(--txt2); font-size: 13px; } .health-hero .hmeta .item { display: flex; flex-direction: column; gap: 2px; } .health-hero .hmeta .item span { color: var(--txt3); font-size: 11px; text-transform: uppercase; letter-spacing: 0.07em; font-weight: 700; } .health-hero .hmeta .item b { color: var(--txt); font-weight: 600; font-size: 14px; } /* Radial gauges - the centerpiece read for CPU / memory / disk. */ .gauges { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; margin-top: 16px; } @media (max-width: 760px) { .gauges { grid-template-columns: 1fr; } } .gauge { --g: var(--ok); --gbg: var(--okbg); background: var(--panel); border: 1px solid var(--panel-br); border-radius: 18px; padding: 20px 20px 18px; backdrop-filter: blur(6px); display: flex; flex-direction: column; align-items: center; gap: 6px; text-align: center; transition: border-color .15s, transform .15s; } .gauge:hover { border-color: color-mix(in srgb, var(--g) 45%, transparent); transform: translateY(-1px); } .gauge.warn { --g: var(--warn); --gbg: var(--warnbg); } .gauge.bad { --g: var(--bad); --gbg: var(--badbg); } .gauge .ghead { display: flex; align-items: center; gap: 8px; font-size: 12px; text-transform: uppercase; letter-spacing: 0.08em; color: var(--txt3); font-weight: 700; } .gauge .ghead svg { width: 15px; height: 15px; color: var(--g); } .gauge .ring { position: relative; width: 172px; height: 172px; margin: 6px 0 2px; border-radius: 50%; background: conic-gradient(var(--g) calc(var(--pct) * 1%), rgba(255,255,255,0.07) 0); } .gauge .ring::after { content: ''; position: absolute; inset: 15px; border-radius: 50%; background: linear-gradient(160deg, #10151f, #0c1017); box-shadow: inset 0 0 0 1px rgba(255,255,255,0.035); } .gauge .center { position: absolute; inset: 0; z-index: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; } .gauge .pct { font-size: 40px; font-weight: 800; letter-spacing: -0.03em; line-height: 1; } .gauge .pct sup { font-size: 17px; font-weight: 700; color: var(--txt2); margin-left: 1px; top: -0.7em; } .gauge .punit { font-size: 11px; color: var(--txt3); font-weight: 600; margin-top: 7px; text-transform: uppercase; letter-spacing: 0.07em; } .gauge .gsub { color: var(--txt2); font-size: 14px; font-weight: 500; } .gauge .gsub b { color: var(--txt); font-weight: 700; } .gauge .gtag { display: inline-flex; align-items: center; gap: 6px; padding: 3px 11px; border-radius: 999px; background: var(--gbg); color: var(--g); font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: 0.05em; } /* Vital-sign tiles - the secondary numbers (free RAM, uptime, etc.). */ .vitals { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; } @media (max-width: 880px) { .vitals { grid-template-columns: repeat(2, 1fr); } } .vital { background: var(--panel); border: 1px solid var(--panel-br); border-radius: 14px; padding: 14px 16px; } .vital .vlabel { display: flex; align-items: center; gap: 7px; font-size: 11px; text-transform: uppercase; letter-spacing: 0.07em; color: var(--txt3); font-weight: 700; } .vital .vlabel svg { width: 13px; height: 13px; } .vital .vval { font-size: 21px; font-weight: 700; margin-top: 7px; letter-spacing: -0.01em; } .vital .vval small { font-size: 12.5px; color: var(--txt2); font-weight: 500; } .vital .vnote { font-size: 12px; color: var(--txt3); margin-top: 3px; } /* Tone-colored progress bars (shared with index health cards). */ .bar.ok > i { background: var(--ok); } .bar.warn > i { background: var(--warn); } .bar.bad > i { background: var(--bad); } /* Load trend chart - sparkline with capacity guide + axis labels. */ .chart { position: relative; } .chart .spark { height: 124px; align-items: flex-end; } .chart .spark > i { background: linear-gradient(180deg, var(--accent), rgba(90,139,224,0.22)); transition: height .6s ease; } .chart .spark > i.hot { background: linear-gradient(180deg, var(--warn), rgba(251,191,36,0.22)); } .chart .spark > i.peak { background: linear-gradient(180deg, var(--bad), rgba(248,113,113,0.25)); } .chart .xaxis { display: flex; justify-content: space-between; margin-top: 9px; color: var(--txt3); font-size: 11px; } .grid > *, .panel, header.page > *, .cols > * { min-width: 0; } @media (max-width: 420px) { .cards, .cards-3, .cards-2, .vitals, .gauges, .cols { grid-template-columns: minmax(0, 1fr); } .stat { max-width: 100%; font-size: 25px; overflow-wrap: anywhere; } .stat small { display: block; margin-top: 5px; letter-spacing: 0; } .header-actions { width: 100%; margin-left: 0; justify-content: flex-end; } .context-breadcrumb { overflow: hidden; } .context-breadcrumb span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .timeline-row { grid-template-columns: 1fr; } .timeline-row .when { white-space: normal; } .field, .action-runner, .op-confirm { align-items: stretch; flex-direction: column; } .field input, .op-confirm-input, .action-runner select { flex: 1 1 auto; width: 100%; min-width: 0; } } </style><style data-stx-cloak>[x-cloak]{display:none !important}</style><style data-crosswind="generated"> /* ! Tailwind CSS Preflight | MIT License | https://tailwindcss.com */ *, ::before, ::after { box-sizing: border-box; border-width: 0; border-style: solid; border-color: var(--border-color, currentColor); } ::before, ::after { --hw-content: ''; } html, :host { line-height: 1.5; -webkit-text-size-adjust: 100%; -moz-tab-size: 4; tab-size: 4; font-family: ui-sans-serif, system-ui, sans-serif; font-feature-settings: normal; font-variation-settings: normal; -webkit-tap-highlight-color: transparent; } body { margin: 0; line-height: inherit; } hr { height: 0; color: inherit; border-top-width: 1px; } abbr:where([title]) { text-decoration: underline dotted; } h1, h2, h3, h4, h5, h6 { font-size: inherit; font-weight: inherit; } a { color: inherit; text-decoration: inherit; } b, strong { font-weight: bolder; } code, kbd, samp, pre { font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; font-feature-settings: normal; font-variation-settings: normal; font-size: 1em; } small { font-size: 80%; } sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; } sub { bottom: -0.25em; } sup { top: -0.5em; } table { text-indent: 0; border-color: var(--border-color, inherit); border-collapse: collapse; } button, input, optgroup, select, textarea { font-family: inherit; font-feature-settings: inherit; font-variation-settings: inherit; font-size: 100%; font-weight: inherit; line-height: inherit; letter-spacing: inherit; color: inherit; margin: 0; padding: 0; } button, select { text-transform: none; } button, input:where([type='button']), input:where([type='reset']), input:where([type='submit']) { -webkit-appearance: button; background-color: transparent; background-image: none; } :-moz-focusring { outline: auto; } :-moz-ui-invalid { box-shadow: none; } progress { vertical-align: baseline; } ::-webkit-inner-spin-button, ::-webkit-outer-spin-button { height: auto; } [type='search'] { -webkit-appearance: textfield; outline-offset: -2px; } ::-webkit-search-decoration { -webkit-appearance: none; } ::-webkit-file-upload-button { -webkit-appearance: button; font: inherit; } summary { display: list-item; } blockquote, dl, dd, h1, h2, h3, h4, h5, h6, hr, figure, p, pre { margin: 0; } fieldset { margin: 0; padding: 0; } legend { padding: 0; } ol, ul, menu { list-style: none; margin: 0; padding: 0; } dialog { padding: 0; } textarea { resize: vertical; } input::placeholder, textarea::placeholder { opacity: 1; color: #9ca3af; } button, [role="button"] { cursor: pointer; } :disabled { cursor: default; } img, svg, video, canvas, audio, iframe, embed, object { display: block; vertical-align: middle; } img, video { max-width: 100%; height: auto; } [hidden] { display: none; } .sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border-width: 0; } </style></head><body data-stx-auto><a data-stx-scope="stx_scope_nav_35" class="skip-link" href="#main-content">Skip to content</a><button class="nav-toggle-button" type="button" aria-label="Open navigation" aria-controls="primary-navigation" aria-expanded="false"><span></span><span></span><span></span></button><button class="nav-scrim" type="button" aria-label="Close navigation"></button><aside class="app-sidebar" id="primary-navigation" aria-label="Primary navigation"><a class="brand" href="/?env=production"><span class="dot"></span><span>ts-cloud</span></a><div class="sidebar-context"><span class="context-label">Project</span><strong>acme-production-app</strong></div><div class="environment-picker" aria-label="Environment"><span class="context-label">Environment</span><details><summary class="environment-current production"><span>PROD</span><strong>production</strong></summary></details></div><button class="command-trigger" type="button" aria-keyshortcuts="Meta+K Control+K"><span>Search resources</span><kbd>⌘ K</kbd></button><div class="nav-groups"><section class="nav-group"><h2>Overview</h2><a class="active" href="/?env=production">Dashboard</a><a href="/server/activity?env=production">Activity</a></section><section class="nav-group"><h2>Applications</h2><a class="" href="/server/sites?env=production">Services</a><a class="" href="/server/deployments?env=production">Deployments</a><a class="" href="/server/logs?env=production">Logs</a><a class="" href="/integrations?env=production">Git integrations</a><a class="" href="/applications/new?env=production">Create application</a><a class="" href="/applications/compose?env=production">Compose applications</a></section><section class="nav-group"><h2>Operations</h2><a class="" href="/operations/queue?env=production">Deployment queue</a><a class="" href="/operations/previews?env=production">Preview environments</a><a class="" href="/operations/releases?env=production">Releases & promotion</a><a class="" href="/operations/regions?env=production">Regions & failover</a><a class="" href="/operations/maintenance?env=production">Maintenance & DR</a><a class="" href="/operations/workloads?env=production">Workloads</a><a class="" href="/operations/observability?env=production">Observability</a><a class="" href="/operations/alerts?env=production">Alerts & health</a><a href="/server/metrics?env=production">Metrics</a><a href="/server/services?env=production">Runtime services</a><a class="" href="/operations/jobs?env=production">Workers & schedules</a><a class="" href="/operations/configuration?env=production">Environment &amp; secrets</a><a class="" href="/data/backups?env=production">Backups &amp; recovery</a><a class="" href="/data/volumes?env=production">Persistent volumes</a><a href="/server/actions?env=production">Run operations</a></section><section class="nav-group"><h2>Infrastructure</h2><a class="" href="/data/services?env=production">Data services</a><a class="" href="/data/volumes?env=production">Persistent volumes</a><a href="/server/firewall?env=production">Network & firewall</a><a href="/server/ssh-keys?env=production">SSH keys</a><a class="" href="/server/fleet?env=production">Fleet inventory</a><a class="" href="/server/capacity?env=production">Capacity & placement</a><a href="/security?env=production">Security posture</a><a href="/server/terminal?env=production">Terminal</a></section><section class="nav-group"><h2>Organization</h2><a class="" href="/server/team?env=production">People & access</a><a class="" href="/account/automation?env=production">API & automation</a></section><section class="nav-group"><h2>Account</h2><a class="" href="/account/security?env=production">Sign-in & security</a></section></div><form method="post" action="/api/logout" class="signout"><button type="submit">Sign out</button></form></aside><dialog class="command-palette" aria-labelledby="command-title"><div class="command-search"><span aria-hidden="true">⌕</span><input type="search" placeholder="Search services, domains, deployments…" aria-label="Search resources" autocomplete="off"><button type="button" class="command-close" aria-label="Close search">Esc</button></div><h2 id="command-title" class="sr-only">Search resources and navigation</h2><div class="command-status" role="status">Start typing to search this project.</div><section class="saved-views" aria-labelledby="saved-views-title"><div class="saved-views-heading"><h3 id="saved-views-title">Saved views</h3><form class="save-view-form"><label class="sr-only" for="save-view-name">Saved view name</label><input id="save-view-name" maxlength="64" placeholder="Name this view" autocomplete="off"><button type="submit">Save current filters</button></form></div><div class="saved-view-list"></div></section><form class="tag-result-form"><label for="tag-result-name">Tag selected resource</label><input id="tag-result-name" maxlength="32" placeholder="customer-facing" pattern="[A-Za-z0-9][A-Za-z0-9 -]{0,31}" autocomplete="off"><input class="tag-color" type="color" value="#5a8be0" aria-label="Tag color"><button type="submit">Add tag</button></form><div class="command-results" role="listbox" aria-label="Search results"></div><footer><span>↑ ↓ navigate</span><span>Enter open</span><span>Esc close</span></footer></dialog><div class="context-bar" aria-label="Current scope"><div class="context-path"><div class="context-breadcrumb"><span>acme-production-app</span><i>/</i><strong>production</strong></div><div class="context-filters" aria-label="Active filters"></div></div><span class="scope-safety production">Production scope</span></div> <script data-stx-scoped>
87
+ })</script> <!DOCTYPE html><html lang="en" data-theme="dark"><head><meta name="title" content="stx Project"><meta name="description" content="A website built with stx templating engine"><meta property="og:title" content="stx Project"><meta property="og:description" content="A website built with stx templating engine"><meta property="og:type" content="website"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:title" content="stx Project"><meta name="twitter:description" content="A website built with stx templating engine"><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>ts-cloud - Services</title><link rel="icon" type="image/svg+xml" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect x='3' y='3' width='26' height='26' rx='8' fill='%235a8be0'/%3E%3C/svg%3E"><link rel="preconnect" href="https://fonts.googleapis.com"><link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet"><style> :root { --bg: #0a0e15; --bg2: #0b0f18; --panel: rgba(255,255,255,0.03); --panel-br: rgba(255,255,255,0.072); --txt: #e9edf5; --txt2: #94a1b8; --txt3: #5a6577; --accent: #5a8be0; --accent-dim: rgba(90,139,224,0.14); --accent-ink: #061019; --ok: #35d19b; --okbg: rgba(53,209,155,0.11); --bad: #f0736e; --badbg: rgba(240,115,110,0.11); --warn: #edb949; --warnbg: rgba(237,185,73,0.11); --mono: ui-monospace, 'SF Mono', SFMono-Regular, Menlo, Consolas, monospace; } * { box-sizing: border-box; margin: 0; padding: 0; } html { background: var(--bg); min-height: 100%; } body { font-family: 'Inter', system-ui, sans-serif; color: var(--txt); min-height: 100vh; /* One calm accent wash, no AI blue-purple mesh. */ background: radial-gradient(900px 460px at 88% -8%, rgba(90,139,224,0.06), transparent 62%), linear-gradient(175deg, var(--bg), var(--bg2)); -webkit-font-smoothing: antialiased; font-feature-settings: 'tnum' 1, 'ss01' 1; padding-left: 248px; overflow-x: hidden; } /* Tabular monospaced numerals wherever a value is read at a glance (density 7). */ .stat, .gauge .pct, .vital .vval, .health-hero .hmeta .item b, .kv > b, td.mono { font-variant-numeric: tabular-nums; } .stat, .gauge .pct { font-family: var(--mono); letter-spacing: -0.03em; } a { color: inherit; text-decoration: none; } .wrap { max-width: 1240px; margin: 0 auto; padding: 0 28px 64px; min-width: 0; } .skip-link { position: fixed; z-index: 100; top: 8px; left: 264px; transform: translateY(-150%); background: var(--accent); color: var(--accent-ink); border-radius: 8px; padding: 8px 12px; font-size: 13px; font-weight: 800; } .skip-link:focus { transform: translateY(0); } .app-sidebar { position: fixed; inset: 0 auto 0 0; z-index: 30; width: 248px; display: flex; flex-direction: column; background: rgba(9,13,20,0.96); border-right: 1px solid var(--panel-br); backdrop-filter: blur(18px); padding: 18px 14px 14px; overflow-y: auto; overscroll-behavior: contain; } .brand { display: flex; align-items: center; gap: 10px; min-height: 38px; padding: 0 8px; font-weight: 800; font-size: 17px; letter-spacing: -0.02em; } .brand .dot { width: 20px; height: 20px; border-radius: 6px; background: var(--accent); box-shadow: inset 0 1px 0 rgba(255,255,255,0.35); } .sidebar-context { display: grid; gap: 3px; margin-top: 16px; padding: 12px; border: 1px solid var(--panel-br); border-radius: 12px; background: rgba(255,255,255,0.025); } .sidebar-context strong { font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .context-label { color: var(--txt3); font-size: 10px; font-weight: 800; letter-spacing: .09em; text-transform: uppercase; } .context-detail { color: var(--txt3); font-size: 11px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .environment-picker { display: grid; gap: 6px; margin: 14px 4px 4px; } .environment-picker details { position: relative; } .environment-current { display: flex; align-items: center; gap: 8px; min-height: 38px; padding: 7px 9px; cursor: pointer; list-style: none; border: 1px solid var(--panel-br); border-radius: 10px; background: rgba(255,255,255,0.03); } .environment-current::-webkit-details-marker { display: none; } .environment-current::after { content: '⌄'; margin-left: auto; color: var(--txt3); } .environment-current > span { min-width: 36px; padding: 3px 5px; border-radius: 5px; background: var(--accent-dim); color: var(--accent); font: 800 9px var(--mono); text-align: center; letter-spacing: .06em; } .environment-current.production > span { background: var(--warnbg); color: var(--warn); } .environment-current strong { font-size: 12px; text-transform: capitalize; } .environment-menu { position: absolute; z-index: 40; top: calc(100% + 6px); left: 0; right: 0; padding: 5px; border: 1px solid var(--panel-br); border-radius: 11px; background: #111722; box-shadow: 0 14px 36px rgba(0,0,0,.4); } .environment-menu a { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 8px; border-radius: 7px; font-size: 12px; text-transform: capitalize; } .environment-menu a:hover, .environment-menu a.active { background: var(--accent-dim); color: var(--accent); } .environment-menu small { color: var(--txt3); font-size: 9px; text-transform: uppercase; letter-spacing: .05em; } .command-trigger { display: flex; align-items: center; justify-content: space-between; gap: 8px; width: calc(100% - 8px); margin: 12px 4px 0; padding: 8px 9px; border: 1px solid var(--panel-br); border-radius: 9px; background: rgba(255,255,255,.025); color: var(--txt2); font: 600 12px inherit; text-align: left; } .command-trigger:hover { border-color: rgba(90,139,224,.35); color: var(--txt); } .command-trigger kbd { padding: 2px 5px; border: 1px solid var(--panel-br); border-radius: 5px; background: rgba(255,255,255,.04); color: var(--txt3); font: 600 10px var(--mono); } .nav-groups { display: grid; gap: 18px; margin-top: 20px; } .nav-group { display: grid; gap: 2px; } .nav-group h2 { padding: 0 10px 5px; color: var(--txt3); font-size: 10px; font-weight: 800; text-transform: uppercase; letter-spacing: .1em; } .nav-group a { position: relative; display: flex; align-items: center; min-height: 34px; padding: 7px 10px; border-radius: 8px; color: var(--txt2); font-size: 12.5px; font-weight: 600; } .nav-group a:hover { color: var(--txt); background: rgba(255,255,255,.035); } .nav-group a.active { color: var(--accent); background: var(--accent-dim); } .nav-group a.active::before { content: ''; position: absolute; left: -4px; width: 3px; height: 16px; border-radius: 4px; background: var(--accent); } .context-bar { position: sticky; top: 0; z-index: 20; min-height: 48px; display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 8px 28px; border-bottom: 1px solid var(--panel-br); background: rgba(10,14,21,.78); backdrop-filter: blur(14px); } .context-path { display: flex; align-items: center; gap: 12px; min-width: 0; overflow: hidden; } .context-breadcrumb { display: flex; align-items: center; gap: 8px; min-width: 0; color: var(--txt2); font-size: 12px; } .context-breadcrumb i { color: var(--txt3); font-style: normal; } .context-breadcrumb strong { color: var(--txt); text-transform: capitalize; } .context-breadcrumb small { margin-left: 7px; padding-left: 14px; border-left: 1px solid var(--panel-br); color: var(--txt3); white-space: nowrap; } .context-filters { display: flex; align-items: center; gap: 5px; min-width: 0; overflow-x: auto; } .filter-chip { flex: 0 0 auto; padding: 4px 8px; border: 1px solid rgba(90,139,224,.25); border-radius: 999px; background: var(--accent-dim); color: var(--accent); font: 700 10px var(--mono); } .filter-chip:hover { border-color: var(--accent); } .scope-safety { flex: 0 0 auto; padding: 4px 9px; border: 1px solid rgba(90,139,224,.25); border-radius: 999px; background: var(--accent-dim); color: var(--accent); font-size: 10px; font-weight: 800; text-transform: uppercase; letter-spacing: .06em; } .scope-safety.production { border-color: rgba(237,185,73,.3); background: var(--warnbg); color: var(--warn); } .env { padding: 4px 10px; border-radius: 999px; background: var(--okbg); color: var(--ok); font-weight: 600; font-size: 12px; } .signout { display: flex; margin-top: auto; padding: 18px 4px 0; } .signout button { width: 100%; appearance: none; border: 1px solid var(--panel-br); background: rgba(255,255,255,0.035); color: var(--txt2); border-radius: 8px; padding: 5px 11px; font: inherit; font-size: 12px; font-weight: 600; cursor: pointer; transition: color .12s, border-color .12s; } .signout button:hover { color: var(--txt); border-color: rgba(255,255,255,0.16); } .nav-toggle-button, .nav-scrim { display: none; } .nav-toggle-button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; } .state-page { min-height: calc(100vh - 48px); display: grid; align-content: center; justify-items: start; gap: 12px; max-width: 620px; padding: 48px 0; } .state-page .state-code { color: var(--accent); font: 800 12px var(--mono); text-transform: uppercase; letter-spacing: .12em; } .state-page h1 { font-size: clamp(28px, 5vw, 48px); letter-spacing: -.035em; } .state-page p { color: var(--txt2); max-width: 560px; font-size: 15px; line-height: 1.65; } .state-actions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 8px; } .auth-page { min-height: 100vh; display: grid; place-items: center; padding: 24px; } .auth-card { width: min(460px, 100%); display: grid; gap: 24px; padding: 28px; border: 1px solid var(--panel-br); border-radius: 18px; background: var(--panel); box-shadow: 0 24px 70px rgba(0,0,0,.35); } .auth-card .brand { padding: 0; } .auth-card h1 { margin-top: 7px; font-size: 28px; } .auth-card p { margin-top: 6px; color: var(--txt2); line-height: 1.55; } .auth-form { display: grid; gap: 14px; } .auth-form .field-block { display: grid; gap: 6px; } .auth-form .field-block input { width: 100%; } .auth-form small { color: var(--txt3); font-size: 11px; } .auth-form .btn { justify-self: stretch; } .auth-status { min-height: 20px; color: var(--txt2); font-size: 12px; } .sr-only { position: absolute !important; width: 1px !important; height: 1px !important; padding: 0 !important; margin: -1px !important; overflow: hidden !important; clip: rect(0,0,0,0) !important; white-space: nowrap !important; border: 0 !important; } .command-palette { width: min(660px, calc(100vw - 24px)); max-height: min(620px, calc(100vh - 40px)); margin: 9vh auto 0; padding: 0; overflow: hidden; border: 1px solid rgba(255,255,255,.13); border-radius: 16px; background: #0f151f; color: var(--txt); box-shadow: 0 28px 90px rgba(0,0,0,.58); } .command-palette::backdrop { background: rgba(2,5,9,.72); backdrop-filter: blur(5px); } .command-search { display: flex; align-items: center; gap: 10px; padding: 12px 14px; border-bottom: 1px solid var(--panel-br); } .command-search > span { color: var(--txt3); font-size: 22px; } .command-search input { flex: 1; min-width: 0; border: 0; outline: 0; background: transparent; color: var(--txt); font: 500 15px inherit; } .command-search input::placeholder { color: var(--txt3); } .command-close { padding: 4px 7px; border: 1px solid var(--panel-br); border-radius: 6px; color: var(--txt3); font: 700 10px var(--mono); } .command-status { padding: 12px 16px; color: var(--txt3); font-size: 12px; } .saved-views { display: grid; gap: 8px; padding: 0 14px 12px; border-bottom: 1px solid var(--panel-br); } .saved-views-heading { display: flex; align-items: center; justify-content: space-between; gap: 10px; } .saved-views h3, .command-group > h3 { color: var(--txt3); font: 800 9px var(--mono); text-transform: uppercase; letter-spacing: .08em; } .save-view-form { display: flex; align-items: center; gap: 6px; } .save-view-form input { width: 150px; min-width: 0; padding: 5px 7px; border: 1px solid var(--panel-br); border-radius: 7px; background: rgba(255,255,255,.035); color: var(--txt); font-size: 11px; } .save-view-form button, .saved-view-row button { padding: 5px 7px; border: 1px solid var(--panel-br); border-radius: 7px; color: var(--txt2); font-size: 10px; } .saved-view-list { display: flex; flex-wrap: wrap; gap: 6px; } .saved-view-row { display: inline-flex; align-items: center; overflow: hidden; border: 1px solid var(--panel-br); border-radius: 8px; } .saved-view-row a { padding: 5px 8px; color: var(--txt2); font-size: 11px; } .saved-view-row button { border: 0; border-left: 1px solid var(--panel-br); border-radius: 0; color: var(--txt3); } .saved-views.empty .saved-view-list::after { content: 'No saved views yet'; color: var(--txt3); font-size: 11px; } .tag-result-form { display: grid; grid-template-columns: 1fr 150px 32px auto; align-items: center; gap: 7px; padding: 9px 14px; border-bottom: 1px solid var(--panel-br); } .tag-result-form label { color: var(--txt3); font: 800 9px var(--mono); text-transform: uppercase; letter-spacing: .08em; } .tag-result-form input:not(.tag-color) { min-width: 0; padding: 5px 7px; border: 1px solid var(--panel-br); border-radius: 7px; background: rgba(255,255,255,.035); color: var(--txt); font-size: 11px; } .tag-result-form .tag-color { width: 32px; height: 27px; padding: 2px; border: 1px solid var(--panel-br); border-radius: 7px; background: transparent; } .tag-result-form button { padding: 5px 8px; border: 1px solid var(--panel-br); border-radius: 7px; color: var(--txt2); font-size: 10px; } .tag-result-form button:disabled { opacity: .45; cursor: not-allowed; } .command-results { display: grid; gap: 3px; max-height: 430px; overflow-y: auto; padding: 0 7px 10px; } .command-group { display: grid; gap: 3px; } .command-group > h3 { padding: 8px 10px 2px; } .command-result-row { display: grid; grid-template-columns: minmax(0, 1fr) 36px; align-items: center; } .command-results a { display: grid; grid-template-columns: 78px 1fr; gap: 10px; align-items: center; min-width: 0; padding: 10px; border-radius: 9px; } .command-results a:hover, .command-results a.selected { background: var(--accent-dim); } .favorite-result { display: grid; place-content: center; width: 30px; height: 30px; border-radius: 8px; color: var(--txt3); font-size: 17px; } .favorite-result:hover, .favorite-result.active { color: var(--warn); background: var(--warnbg); } .command-type { color: var(--txt3); font: 800 9px var(--mono); text-transform: uppercase; letter-spacing: .07em; } .command-copy { display: grid; gap: 3px; min-width: 0; } .command-copy strong, .command-copy small { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .command-copy strong { font-size: 13px; } .command-copy small { color: var(--txt3); font-size: 11px; } .command-copy mark { border-radius: 2px; background: var(--warnbg); color: var(--warn); } .command-palette footer { display: flex; flex-wrap: wrap; gap: 14px; padding: 9px 14px; border-top: 1px solid var(--panel-br); color: var(--txt3); font-size: 10px; } @media (max-width: 820px) { body { padding-left: 0; } .wrap { padding-left: 16px; padding-right: 16px; } .context-bar { padding: 8px 14px 8px 58px; } .context-breadcrumb small { display: none; } .nav-toggle-button { position: fixed; top: 9px; left: 12px; z-index: 50; width: 36px; height: 30px; display: grid; place-content: center; gap: 4px; border: 1px solid var(--panel-br); border-radius: 8px; background: #111722; cursor: pointer; } .nav-toggle-button span { display: block; width: 15px; height: 1px; background: var(--txt2); } .app-sidebar { transform: translateX(-102%); transition: transform .18s ease; box-shadow: 18px 0 48px rgba(0,0,0,.45); } .nav-scrim { position: fixed; inset: 0; z-index: 25; background: rgba(0,0,0,.58); } body.nav-open .nav-scrim { display: block; } body.nav-open .app-sidebar { transform: translateX(0); } .skip-link { left: 56px; } } @media (max-width: 420px) { .context-filters { display: none; } .saved-views-heading { align-items: stretch; flex-direction: column; } .save-view-form input { width: auto; flex: 1; } .tag-result-form { grid-template-columns: 1fr 32px auto; } .tag-result-form label { grid-column: 1 / -1; } .scope-safety { max-width: 92px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } header.page { padding-top: 22px; } header.page h1 { font-size: 23px; } .cards, .cards-3, .cards-2, .vitals { grid-template-columns: 1fr; } .panel { padding: 15px; } table { display: block; overflow-x: auto; } } header.page { padding: 30px 0 22px; display: flex; align-items: flex-start; gap: 20px; flex-wrap: wrap; } header.page h1 { font-size: 26px; font-weight: 800; letter-spacing: -0.02em; } header.page p { color: var(--txt2); margin-top: 4px; font-size: 14px; } .server-line { display: flex; flex-wrap: wrap; gap: 16px; margin-top: 14px; color: var(--txt2); font-size: 13px; } .server-line b { color: var(--txt); font-weight: 600; } .header-actions { margin-left: auto; display: flex; align-items: center; gap: 10px; } /* Breadcrumb / back link for drill-down pages */ .crumbs { display: flex; align-items: center; gap: 8px; padding-top: 26px; font-size: 13px; color: var(--txt3); } .crumbs a { color: var(--txt2); } .crumbs a:hover { color: var(--accent); } .crumbs .sep { color: var(--txt3); } .grid { display: grid; gap: 16px; } .cards { grid-template-columns: repeat(4, 1fr); } .cards-3 { grid-template-columns: repeat(3, 1fr); } .cards-2 { grid-template-columns: repeat(2, 1fr); } @media (max-width: 880px) { .cards, .cards-3, .cards-2 { grid-template-columns: repeat(2, 1fr); } } .panel { background: var(--panel); border: 1px solid var(--panel-br); border-radius: 16px; padding: 18px; backdrop-filter: blur(6px); } a.panel { display: block; transition: border-color .15s, transform .15s; } a.panel:hover { border-color: rgba(90,139,224,0.5); transform: translateY(-1px); } .panel h3 { font-size: 12px; text-transform: uppercase; letter-spacing: 0.08em; color: var(--txt3); font-weight: 700; } .stat { font-size: 28px; font-weight: 800; margin-top: 8px; letter-spacing: -0.02em; } .stat small { font-size: 14px; color: var(--txt2); font-weight: 500; } .bar { height: 7px; border-radius: 999px; background: rgba(255,255,255,0.07); margin-top: 12px; overflow: hidden; } .bar > i { display: block; height: 100%; border-radius: 999px; background: var(--accent); } .section { margin-top: 30px; } .section > h2 { font-size: 15px; font-weight: 700; margin-bottom: 12px; display: flex; align-items: center; gap: 8px; } .section > h2 .more { margin-left: auto; display: inline-flex; align-items: center; gap: 12px; font-size: 12px; font-weight: 600; color: var(--accent); } .section > h2 .more a { color: var(--accent); } .cols { display: grid; grid-template-columns: 1.6fr 1fr; gap: 16px; } @media (max-width: 880px) { .cols { grid-template-columns: 1fr; } } table { width: 100%; border-collapse: collapse; font-size: 14px; } th { text-align: left; color: var(--txt3); font-weight: 600; font-size: 12px; text-transform: uppercase; letter-spacing: 0.05em; padding: 0 12px 10px; } td { padding: 12px; border-top: 1px solid rgba(255,255,255,0.05); } tr:hover td { background: rgba(255,255,255,0.02); } .mono { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 13px; color: var(--txt2); } .pill { display: inline-flex; align-items: center; gap: 6px; padding: 3px 9px; border-radius: 999px; font-size: 12px; font-weight: 600; } .pill::before { content: ''; width: 7px; height: 7px; border-radius: 50%; background: currentColor; } .pill.ok { background: var(--okbg); color: var(--ok); } .pill.bad { background: var(--badbg); color: var(--bad); } .pill.warn { background: var(--warnbg); color: var(--warn); } .tag { padding: 2px 8px; border-radius: 6px; background: rgba(90,139,224,0.12); color: var(--accent); font-size: 12px; font-weight: 600; } .kv { display: flex; justify-content: space-between; padding: 9px 0; border-top: 1px solid rgba(255,255,255,0.05); font-size: 14px; gap: 16px; } .kv:first-of-type { border-top: 0; } .kv > span { color: var(--txt2); white-space: nowrap; } .kv > b { text-align: right; word-break: break-all; } .deploy { display: flex; align-items: center; gap: 12px; padding: 11px 0; border-top: 1px solid rgba(255,255,255,0.05); font-size: 14px; } .deploy:first-of-type { border-top: 0; } .deploy .when { margin-left: auto; color: var(--txt3); font-size: 12px; } .btn { background: var(--accent); color: var(--accent-ink); border: 0; border-radius: 10px; padding: 9px 16px; font-weight: 700; font-size: 13.5px; cursor: pointer; font-family: inherit; white-space: nowrap; transition: filter .12s, transform .12s; } .btn:hover { filter: brightness(1.06); } .btn:active { transform: translateY(1px); } .btn.ghost { background: rgba(255,255,255,0.045); border: 1px solid var(--panel-br); color: var(--txt); } .btn.ghost:hover { background: rgba(255,255,255,0.075); filter: none; } .btn.danger { background: transparent; border: 1px solid var(--badbg); color: var(--bad); } .btn.danger:hover { background: var(--badbg); filter: none; } .btn.sm { padding: 6px 12px; font-size: 12px; } .data-item { display: flex; align-items: center; gap: 12px; padding: 11px 0; border-top: 1px solid rgba(255,255,255,0.05); font-size: 14px; } .data-item:first-of-type { border-top: 0; } .data-item .detail { color: var(--txt3); font-size: 12px; } .data-item .st { margin-left: auto; } .secret { display: flex; align-items: center; gap: 12px; padding: 10px 0; border-top: 1px solid rgba(255,255,255,0.05); font-size: 14px; } .secret:first-of-type { border-top: 0; } .secret .val { margin-left: auto; color: var(--txt3); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; letter-spacing: 2px; } /* Drill-down extras */ .spark { display: flex; align-items: flex-end; gap: 3px; height: 48px; margin-top: 12px; } .spark > i { flex: 1; background: linear-gradient(180deg, var(--accent), rgba(90,139,224,0.25)); border-radius: 3px 3px 0 0; min-height: 2px; } .logs { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12.5px; line-height: 1.7; color: var(--txt2); max-height: 360px; overflow: auto; } .logs .ts { color: var(--txt3); } .logs .err { color: var(--bad); } .log-list { display: grid; gap: 10px; max-height: 680px; overflow: auto; padding-right: 4px; } .log-row { border: 1px solid rgba(255,255,255,0.07); border-radius: 12px; background: rgba(255,255,255,0.025); padding: 12px 14px; } .log-row.warn { border-color: rgba(251,191,36,0.18); background: rgba(251,191,36,0.04); } .log-row.error { border-color: rgba(248,113,113,0.2); background: rgba(248,113,113,0.045); } .log-meta { display: flex; align-items: center; flex-wrap: wrap; gap: 9px; color: var(--txt3); font-size: 12px; margin-bottom: 9px; } .log-row pre { white-space: pre-wrap; overflow-wrap: anywhere; color: var(--txt2); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12.5px; line-height: 1.55; } .timeline { display: grid; gap: 11px; } .timeline-row { display: grid; grid-template-columns: 92px 1fr auto; gap: 13px; align-items: start; border: 1px solid rgba(255,255,255,0.07); border-radius: 12px; background: rgba(255,255,255,0.025); padding: 12px 14px; } .timeline-row .type { color: var(--txt3); font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: 0.07em; } .timeline-row .title { font-weight: 800; } .timeline-row .detail { color: var(--txt2); font-size: 13px; margin-top: 3px; overflow-wrap: anywhere; } .timeline-row .when { color: var(--txt3); font-size: 12px; white-space: nowrap; } .check-list { display: grid; gap: 10px; } .check { display: grid; grid-template-columns: auto 1fr; gap: 12px; align-items: start; padding: 13px 0; border-top: 1px solid rgba(255,255,255,0.05); } .check:first-child { border-top: 0; padding-top: 0; } .check .mark { width: 12px; height: 12px; border-radius: 50%; margin-top: 4px; background: var(--ok); box-shadow: 0 0 0 4px var(--okbg); } .check.warn .mark { background: var(--warn); box-shadow: 0 0 0 4px var(--warnbg); } .check.fail .mark { background: var(--bad); box-shadow: 0 0 0 4px var(--badbg); } .check .name { font-weight: 800; } .check .detail { color: var(--txt2); font-size: 13px; margin-top: 3px; line-height: 1.45; } .port-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; } @media (max-width: 880px) { .port-grid { grid-template-columns: 1fr; } } .port-card { border: 1px solid rgba(255,255,255,0.07); border-radius: 12px; background: rgba(255,255,255,0.025); padding: 13px 14px; min-width: 0; } .port-card .top { display: flex; align-items: center; gap: 8px; justify-content: space-between; } .port-card .listen { margin-top: 8px; font-weight: 800; overflow-wrap: anywhere; } .port-card .proc { color: var(--txt3); font-size: 12px; margin-top: 5px; overflow-wrap: anywhere; } .action-runner { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; } .action-runner select { background: rgba(255,255,255,0.05); border: 1px solid var(--panel-br); border-radius: 10px; padding: 8px 10px; color: var(--txt); font-family: inherit; font-size: 13px; min-width: 150px; } .action-output { margin-top: 12px; white-space: pre-wrap; overflow: auto; max-height: 260px; border-radius: 12px; border: 1px solid rgba(255,255,255,0.07); background: rgba(0,0,0,0.22); padding: 12px; color: var(--txt2); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; line-height: 1.5; } .op-confirm { margin-top: 14px; display: flex; align-items: center; gap: 10px; flex-wrap: wrap; } .op-confirm-input { flex: 0 0 200px; background: rgba(255,255,255,0.05); border: 1px solid var(--panel-br); border-radius: 10px; padding: 8px 12px; color: var(--txt); font-family: inherit; font-size: 14px; } .op-confirm-input:focus { outline: none; border-color: var(--accent); } .note { color: var(--txt3); font-size: 12px; margin-top: 10px; } .row-actions { display: flex; gap: 8px; } .field { display: flex; gap: 8px; margin-top: 12px; } .field input { flex: 1; background: rgba(255,255,255,0.05); border: 1px solid var(--panel-br); border-radius: 10px; padding: 9px 12px; color: var(--txt); font-family: inherit; font-size: 14px; } .field input:focus { outline: none; border-color: var(--accent); } .empty { display: grid; place-items: center; gap: 6px; min-height: 132px; text-align: center; color: var(--txt3); border: 1px dashed rgba(255,255,255,0.12); border-radius: 14px; background: rgba(255,255,255,0.025); padding: 22px; } .empty strong { color: var(--txt); font-size: 14px; } .empty span { max-width: 540px; font-size: 13px; line-height: 1.5; } .empty.compact { min-height: 74px; margin-top: 10px; padding: 14px; } .form-grid { display: grid; grid-template-columns: minmax(180px, 0.7fr) minmax(280px, 1.4fr); gap: 14px; align-items: end; } .field-block { display: flex; flex-direction: column; gap: 7px; } .field-block.wide { grid-column: 1 / -1; } .field-block label, .select-filter span { color: var(--txt3); font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: 0.07em; } .field-block input, .field-block textarea, .select-filter select { width: 100%; background: rgba(255,255,255,0.05); border: 1px solid var(--panel-br); border-radius: 10px; padding: 10px 12px; color: var(--txt); font-family: inherit; font-size: 14px; } .field-block textarea { resize: vertical; min-height: 92px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; line-height: 1.5; } .field-block input:focus, .field-block textarea:focus, .select-filter select:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px rgba(90,139,224,0.12); } .form-actions { grid-column: 1 / -1; display: flex; align-items: center; gap: 12px; flex-wrap: wrap; } .msg { color: var(--txt3); font-size: 13px; } .msg.ok { color: var(--ok); } .msg.bad { color: var(--bad); } .table-actions { text-align: right; white-space: nowrap; } .filters { display: flex; align-items: center; justify-content: space-between; gap: 14px; flex-wrap: wrap; margin: 16px 0; } .segmented { display: inline-flex; padding: 4px; border: 1px solid var(--panel-br); background: rgba(255,255,255,0.035); border-radius: 12px; gap: 2px; } .segmented button { appearance: none; border: 0; background: transparent; color: var(--txt2); border-radius: 9px; padding: 7px 12px; font: inherit; font-size: 13px; font-weight: 700; cursor: pointer; } .segmented button.active { background: rgba(90,139,224,0.18); color: var(--accent); box-shadow: inset 0 0 0 1px rgba(90,139,224,0.18); } .select-filter { display: inline-flex; align-items: center; gap: 8px; } .select-filter select { min-width: 150px; padding: 8px 10px; } @media (max-width: 760px) { .form-grid { grid-template-columns: 1fr; } .filters { align-items: stretch; } .segmented, .select-filter, .select-filter select { width: 100%; } .segmented button { flex: 1; } } /* Honest action affordance: a copyable CLI command (static dashboard has no backend - the buttons would POST nowhere, so we show the exact command). */ .cmd { display: inline-flex; align-items: center; gap: 8px; padding: 6px 12px; border-radius: 10px; background: rgba(255,255,255,0.05); border: 1px solid var(--panel-br); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12.5px; color: var(--txt); white-space: nowrap; } .cmd::before { content: '$'; color: var(--txt3); } .cmd.accent { border-color: rgba(90,139,224,0.4); color: var(--accent); } .cmds { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; } /* Server dashboard components */ .svc { display: flex; flex-wrap: wrap; gap: 10px; } .svc .item { display: flex; align-items: center; gap: 8px; padding: 8px 12px; border-radius: 10px; background: rgba(255,255,255,0.03); border: 1px solid var(--panel-br); font-size: 13px; font-weight: 500; } .key { display: flex; align-items: center; gap: 12px; padding: 11px 0; border-top: 1px solid rgba(255,255,255,0.05); font-size: 14px; } .key:first-of-type { border-top: 0; } .key .fp { margin-left: auto; color: var(--txt3); font-size: 12px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; } .chart-panel { overflow: hidden; } .chart-panel.subtle { padding: 0; margin-bottom: 14px; background: transparent; border: 0; } svg.chart { display: block; width: 100%; height: auto; min-height: 150px; } svg.chart .chart-shell { fill: rgba(255,255,255,0.025); stroke: rgba(255,255,255,0.07); } svg.chart .chart-grid { stroke: rgba(255,255,255,0.08); stroke-width: 1; } svg.chart .chart-axis, svg.chart .chart-label { fill: var(--txt3); font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; } svg.chart .chart-value { fill: var(--txt); font-size: 12px; font-weight: 800; } svg.chart .chart-empty-title { fill: var(--txt); font-size: 15px; font-weight: 800; } svg.chart .chart-empty-sub { fill: var(--txt3); font-size: 12px; } svg.chart .bar-mark.ok rect { fill: var(--ok); opacity: 0.85; } svg.chart .bar-mark.warn rect { fill: var(--warn); opacity: 0.88; } svg.chart .bar-mark.bad rect { fill: var(--bad); opacity: 0.9; } svg.chart .spark-path { fill: none; stroke: var(--accent); stroke-width: 2.25; stroke-linecap: round; stroke-linejoin: round; } svg.chart circle.ok { fill: var(--ok); } svg.chart circle.bad { fill: var(--bad); } svg.chart.disabled { opacity: 0.86; } /* ───────────── Health / vital signs (server metrics) ───────────── */ /* Overall status banner - at-a-glance "is the box OK?" verdict. */ .health-hero { --hue: var(--ok); --huebg: var(--okbg); display: flex; align-items: center; gap: 18px 28px; flex-wrap: wrap; margin-top: 8px; background: radial-gradient(700px 200px at 0% 0%, var(--huebg), transparent 70%), var(--panel); border: 1px solid var(--panel-br); border-radius: 18px; padding: 18px 22px; backdrop-filter: blur(6px); } .health-hero.warn { --hue: var(--warn); --huebg: var(--warnbg); } .health-hero.bad { --hue: var(--bad); --huebg: var(--badbg); } .health-hero .status { display: inline-flex; align-items: center; gap: 12px; font-weight: 800; font-size: 17px; letter-spacing: -0.01em; color: var(--hue); } .health-hero .status .led { width: 13px; height: 13px; border-radius: 50%; background: var(--hue); box-shadow: 0 0 0 4px var(--huebg); animation: hb-pulse 2.4s ease-in-out infinite; } .health-hero .status small { display: block; color: var(--txt3); font-size: 12px; font-weight: 500; margin-top: 2px; letter-spacing: 0; } @keyframes hb-pulse { 0%, 100% { opacity: 1 } 50% { opacity: 0.5 } } .health-hero .hmeta { margin-left: auto; display: flex; flex-wrap: wrap; gap: 22px 26px; color: var(--txt2); font-size: 13px; } .health-hero .hmeta .item { display: flex; flex-direction: column; gap: 2px; } .health-hero .hmeta .item span { color: var(--txt3); font-size: 11px; text-transform: uppercase; letter-spacing: 0.07em; font-weight: 700; } .health-hero .hmeta .item b { color: var(--txt); font-weight: 600; font-size: 14px; } /* Radial gauges - the centerpiece read for CPU / memory / disk. */ .gauges { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; margin-top: 16px; } @media (max-width: 760px) { .gauges { grid-template-columns: 1fr; } } .gauge { --g: var(--ok); --gbg: var(--okbg); background: var(--panel); border: 1px solid var(--panel-br); border-radius: 18px; padding: 20px 20px 18px; backdrop-filter: blur(6px); display: flex; flex-direction: column; align-items: center; gap: 6px; text-align: center; transition: border-color .15s, transform .15s; } .gauge:hover { border-color: color-mix(in srgb, var(--g) 45%, transparent); transform: translateY(-1px); } .gauge.warn { --g: var(--warn); --gbg: var(--warnbg); } .gauge.bad { --g: var(--bad); --gbg: var(--badbg); } .gauge .ghead { display: flex; align-items: center; gap: 8px; font-size: 12px; text-transform: uppercase; letter-spacing: 0.08em; color: var(--txt3); font-weight: 700; } .gauge .ghead svg { width: 15px; height: 15px; color: var(--g); } .gauge .ring { position: relative; width: 172px; height: 172px; margin: 6px 0 2px; border-radius: 50%; background: conic-gradient(var(--g) calc(var(--pct) * 1%), rgba(255,255,255,0.07) 0); } .gauge .ring::after { content: ''; position: absolute; inset: 15px; border-radius: 50%; background: linear-gradient(160deg, #10151f, #0c1017); box-shadow: inset 0 0 0 1px rgba(255,255,255,0.035); } .gauge .center { position: absolute; inset: 0; z-index: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; } .gauge .pct { font-size: 40px; font-weight: 800; letter-spacing: -0.03em; line-height: 1; } .gauge .pct sup { font-size: 17px; font-weight: 700; color: var(--txt2); margin-left: 1px; top: -0.7em; } .gauge .punit { font-size: 11px; color: var(--txt3); font-weight: 600; margin-top: 7px; text-transform: uppercase; letter-spacing: 0.07em; } .gauge .gsub { color: var(--txt2); font-size: 14px; font-weight: 500; } .gauge .gsub b { color: var(--txt); font-weight: 700; } .gauge .gtag { display: inline-flex; align-items: center; gap: 6px; padding: 3px 11px; border-radius: 999px; background: var(--gbg); color: var(--g); font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: 0.05em; } /* Vital-sign tiles - the secondary numbers (free RAM, uptime, etc.). */ .vitals { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; } @media (max-width: 880px) { .vitals { grid-template-columns: repeat(2, 1fr); } } .vital { background: var(--panel); border: 1px solid var(--panel-br); border-radius: 14px; padding: 14px 16px; } .vital .vlabel { display: flex; align-items: center; gap: 7px; font-size: 11px; text-transform: uppercase; letter-spacing: 0.07em; color: var(--txt3); font-weight: 700; } .vital .vlabel svg { width: 13px; height: 13px; } .vital .vval { font-size: 21px; font-weight: 700; margin-top: 7px; letter-spacing: -0.01em; } .vital .vval small { font-size: 12.5px; color: var(--txt2); font-weight: 500; } .vital .vnote { font-size: 12px; color: var(--txt3); margin-top: 3px; } /* Tone-colored progress bars (shared with index health cards). */ .bar.ok > i { background: var(--ok); } .bar.warn > i { background: var(--warn); } .bar.bad > i { background: var(--bad); } /* Load trend chart - sparkline with capacity guide + axis labels. */ .chart { position: relative; } .chart .spark { height: 124px; align-items: flex-end; } .chart .spark > i { background: linear-gradient(180deg, var(--accent), rgba(90,139,224,0.22)); transition: height .6s ease; } .chart .spark > i.hot { background: linear-gradient(180deg, var(--warn), rgba(251,191,36,0.22)); } .chart .spark > i.peak { background: linear-gradient(180deg, var(--bad), rgba(248,113,113,0.25)); } .chart .xaxis { display: flex; justify-content: space-between; margin-top: 9px; color: var(--txt3); font-size: 11px; } .grid > *, .panel, header.page > *, .cols > * { min-width: 0; } @media (max-width: 420px) { .cards, .cards-3, .cards-2, .vitals, .gauges, .cols { grid-template-columns: minmax(0, 1fr); } .stat { max-width: 100%; font-size: 25px; overflow-wrap: anywhere; } .stat small { display: block; margin-top: 5px; letter-spacing: 0; } .header-actions { width: 100%; margin-left: 0; justify-content: flex-end; } .context-breadcrumb { overflow: hidden; } .context-breadcrumb span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .timeline-row { grid-template-columns: 1fr; } .timeline-row .when { white-space: normal; } .field, .action-runner, .op-confirm { align-items: stretch; flex-direction: column; } .field input, .op-confirm-input, .action-runner select { flex: 1 1 auto; width: 100%; min-width: 0; } } </style><style data-stx-cloak>[x-cloak]{display:none !important}</style><style data-crosswind="generated"> /* ! Tailwind CSS Preflight | MIT License | https://tailwindcss.com */ *, ::before, ::after { box-sizing: border-box; border-width: 0; border-style: solid; border-color: var(--border-color, currentColor); } ::before, ::after { --hw-content: ''; } html, :host { line-height: 1.5; -webkit-text-size-adjust: 100%; -moz-tab-size: 4; tab-size: 4; font-family: ui-sans-serif, system-ui, sans-serif; font-feature-settings: normal; font-variation-settings: normal; -webkit-tap-highlight-color: transparent; } body { margin: 0; line-height: inherit; } hr { height: 0; color: inherit; border-top-width: 1px; } abbr:where([title]) { text-decoration: underline dotted; } h1, h2, h3, h4, h5, h6 { font-size: inherit; font-weight: inherit; } a { color: inherit; text-decoration: inherit; } b, strong { font-weight: bolder; } code, kbd, samp, pre { font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; font-feature-settings: normal; font-variation-settings: normal; font-size: 1em; } small { font-size: 80%; } sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; } sub { bottom: -0.25em; } sup { top: -0.5em; } table { text-indent: 0; border-color: var(--border-color, inherit); border-collapse: collapse; } button, input, optgroup, select, textarea { font-family: inherit; font-feature-settings: inherit; font-variation-settings: inherit; font-size: 100%; font-weight: inherit; line-height: inherit; letter-spacing: inherit; color: inherit; margin: 0; padding: 0; } button, select { text-transform: none; } button, input:where([type='button']), input:where([type='reset']), input:where([type='submit']) { -webkit-appearance: button; background-color: transparent; background-image: none; } :-moz-focusring { outline: auto; } :-moz-ui-invalid { box-shadow: none; } progress { vertical-align: baseline; } ::-webkit-inner-spin-button, ::-webkit-outer-spin-button { height: auto; } [type='search'] { -webkit-appearance: textfield; outline-offset: -2px; } ::-webkit-search-decoration { -webkit-appearance: none; } ::-webkit-file-upload-button { -webkit-appearance: button; font: inherit; } summary { display: list-item; } blockquote, dl, dd, h1, h2, h3, h4, h5, h6, hr, figure, p, pre { margin: 0; } fieldset { margin: 0; padding: 0; } legend { padding: 0; } ol, ul, menu { list-style: none; margin: 0; padding: 0; } dialog { padding: 0; } textarea { resize: vertical; } input::placeholder, textarea::placeholder { opacity: 1; color: #9ca3af; } button, [role="button"] { cursor: pointer; } :disabled { cursor: default; } img, svg, video, canvas, audio, iframe, embed, object { display: block; vertical-align: middle; } img, video { max-width: 100%; height: auto; } [hidden] { display: none; } .sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border-width: 0; } </style></head><body data-stx-auto><a data-stx-scope="stx_scope_nav_31" class="skip-link" href="#main-content">Skip to content</a><button class="nav-toggle-button" type="button" aria-label="Open navigation" aria-controls="primary-navigation" aria-expanded="false"><span></span><span></span><span></span></button><button class="nav-scrim" type="button" aria-label="Close navigation"></button><aside class="app-sidebar" id="primary-navigation" aria-label="Primary navigation"><a class="brand" href="/?env=production"><span class="dot"></span><span>ts-cloud</span></a><div class="sidebar-context"><span class="context-label">Project</span><strong>acme-production-app</strong></div><div class="environment-picker" aria-label="Environment"><span class="context-label">Environment</span><details><summary class="environment-current production"><span>PROD</span><strong>production</strong></summary></details></div><button class="command-trigger" type="button" aria-keyshortcuts="Meta+K Control+K"><span>Search resources</span><kbd>⌘ K</kbd></button><div class="nav-groups"><section class="nav-group"><h2>Overview</h2><a class="active" href="/?env=production">Dashboard</a><a href="/server/activity?env=production">Activity</a></section><section class="nav-group"><h2>Applications</h2><a class="" href="/server/sites?env=production">Services</a><a class="" href="/server/deployments?env=production">Deployments</a><a class="" href="/server/logs?env=production">Logs</a><a class="" href="/integrations?env=production">Git integrations</a><a class="" href="/applications/new?env=production">Create application</a><a class="" href="/applications/compose?env=production">Compose applications</a></section><section class="nav-group"><h2>Operations</h2><a class="" href="/operations/queue?env=production">Deployment queue</a><a class="" href="/operations/previews?env=production">Preview environments</a><a class="" href="/operations/releases?env=production">Releases & promotion</a><a class="" href="/operations/regions?env=production">Regions & failover</a><a class="" href="/operations/maintenance?env=production">Maintenance & DR</a><a class="" href="/operations/workloads?env=production">Workloads</a><a class="" href="/operations/observability?env=production">Observability</a><a class="" href="/operations/alerts?env=production">Alerts & health</a><a href="/server/metrics?env=production">Metrics</a><a href="/server/services?env=production">Runtime services</a><a class="" href="/operations/jobs?env=production">Workers & schedules</a><a class="" href="/operations/configuration?env=production">Environment &amp; secrets</a><a class="" href="/data/backups?env=production">Backups &amp; recovery</a><a class="" href="/data/volumes?env=production">Persistent volumes</a><a href="/server/actions?env=production">Run operations</a></section><section class="nav-group"><h2>Infrastructure</h2><a class="" href="/data/services?env=production">Data services</a><a class="" href="/data/volumes?env=production">Persistent volumes</a><a href="/server/firewall?env=production">Network & firewall</a><a href="/server/ssh-keys?env=production">SSH keys</a><a class="" href="/server/fleet?env=production">Fleet inventory</a><a class="" href="/server/capacity?env=production">Capacity & placement</a><a href="/security?env=production">Security posture</a><a href="/server/terminal?env=production">Terminal</a></section><section class="nav-group"><h2>Organization</h2><a class="" href="/server/team?env=production">People & access</a><a class="" href="/account/automation?env=production">API & automation</a></section><section class="nav-group"><h2>Account</h2><a class="" href="/account/security?env=production">Sign-in & security</a></section></div><form method="post" action="/api/logout" class="signout"><button type="submit">Sign out</button></form></aside><dialog class="command-palette" aria-labelledby="command-title"><div class="command-search"><span aria-hidden="true">⌕</span><input type="search" placeholder="Search services, domains, deployments…" aria-label="Search resources" autocomplete="off"><button type="button" class="command-close" aria-label="Close search">Esc</button></div><h2 id="command-title" class="sr-only">Search resources and navigation</h2><div class="command-status" role="status">Start typing to search this project.</div><section class="saved-views" aria-labelledby="saved-views-title"><div class="saved-views-heading"><h3 id="saved-views-title">Saved views</h3><form class="save-view-form"><label class="sr-only" for="save-view-name">Saved view name</label><input id="save-view-name" maxlength="64" placeholder="Name this view" autocomplete="off"><button type="submit">Save current filters</button></form></div><div class="saved-view-list"></div></section><form class="tag-result-form"><label for="tag-result-name">Tag selected resource</label><input id="tag-result-name" maxlength="32" placeholder="customer-facing" pattern="[A-Za-z0-9][A-Za-z0-9 -]{0,31}" autocomplete="off"><input class="tag-color" type="color" value="#5a8be0" aria-label="Tag color"><button type="submit">Add tag</button></form><div class="command-results" role="listbox" aria-label="Search results"></div><footer><span>↑ ↓ navigate</span><span>Enter open</span><span>Esc close</span></footer></dialog><div class="context-bar" aria-label="Current scope"><div class="context-path"><div class="context-breadcrumb"><span>acme-production-app</span><i>/</i><strong>production</strong></div><div class="context-filters" aria-label="Active filters"></div></div><span class="scope-safety production">Production scope</span></div> <script data-stx-scoped>
88
88
  (function() {
89
89
  var { state, derived, effect, batch, onMount, onDestroy, defineStore, useStore, useFetch, useRef, useQuery, useMutation, useOptimistic, useDebounce, useDebouncedValue, useThrottle, useInterval, useTimeout, useToggle, useCounter, useClickOutside, useFocus, useAsync, useLocalStorage, useSessionStorage, useCookie, useReactiveProp, useEventListener, useWebSocket, useColorMode, useDark, useHead, useSeoMeta, definePageMeta, useRoute, useSearchParams, navigate, goBack, goForward, provide, ref, reactive, computed, watch, watchEffect, defineProps, withDefaults, defineEmits, defineExpose, defineSlots } = window.stx;
90
90
  var __destroyHooks = [];
@@ -427,7 +427,7 @@ var { opOutput, opShown, pending, typed, busy, confirmTok, confirmVerb, confirmD
427
427
 
428
428
 
429
429
  if (!window.stx._scopes) window.stx._scopes = {};
430
- window.stx._scopes['stx_scope_nav_35'] = { __destroyCallbacks: __destroyHooks };
430
+ window.stx._scopes['stx_scope_nav_31'] = { __destroyCallbacks: __destroyHooks };
431
431
  })();
432
432
  </script> <div class="wrap"><div class="crumbs"><a href="/">Server</a><span class="sep">/</span> Services</div><header class="page"><div><h1>Services</h1><p>systemd / pantry services managed on the box.</p></div><div class="header-actions"><a class="btn ghost" href="/server/logs">View logs</a></div></header><div class="section"><div class="panel"><table><thead><tr><th scope="col">Service</th><th scope="col">Status</th><th scope="col">Uptime</th><th scope="col">Memory</th><th scope="col">Autostart</th><th scope="col">Manage</th></tr></thead><tbody><tr><td class="mono"><b>nginx</b></td><td><span class="pill ok">running</span></td><td style="color:var(--txt2)">14d</td><td>42 MB</td><td><span class="ok pill">enabled</span></td><td><div class="action-runner"><button class="btn ghost sm" type="button" aria-label="Restart nginx" @click="askOp('restart:nginx', 'restart nginx', 'restart nginx', null, 'nginx')">Restart</button><button class="btn ghost sm" type="button" aria-label="Reload nginx" @click="askOp('reload:nginx', 'reload nginx', 'reload nginx', null, 'nginx')">Reload</button><button class="btn ghost sm" type="button" aria-label="Start nginx" @click="askOp('start:nginx', 'start nginx', 'start nginx', null, 'nginx')">Start</button><button class="btn danger sm" type="button" aria-label="Stop nginx" @click="askOp('stop:nginx', 'stop nginx', 'stop nginx', null, 'nginx')">Stop</button><button class="btn ghost sm" type="button" aria-label="Enable nginx" @click="askOp('enable:nginx', 'enable nginx', 'enable nginx', null, 'nginx')">Enable</button><button class="btn ghost sm" type="button" aria-label="Disable nginx" @click="askOp('disable:nginx', 'disable nginx', 'disable nginx', null, 'nginx')">Disable</button></div></td></tr><tr><td class="mono"><b>php8.3-fpm</b></td><td><span class="pill ok">running</span></td><td style="color:var(--txt2)">14d</td><td>318 MB</td><td><span class="ok pill">enabled</span></td><td><div class="action-runner"><button class="btn ghost sm" type="button" aria-label="Restart php8.3-fpm" @click="askOp('restart:php8.3-fpm', 'restart php8.3-fpm', 'restart php8.3-fpm', null, 'php8.3-fpm')">Restart</button><button class="btn ghost sm" type="button" aria-label="Reload php8.3-fpm" @click="askOp('reload:php8.3-fpm', 'reload php8.3-fpm', 'reload php8.3-fpm', null, 'php8.3-fpm')">Reload</button><button class="btn ghost sm" type="button" aria-label="Start php8.3-fpm" @click="askOp('start:php8.3-fpm', 'start php8.3-fpm', 'start php8.3-fpm', null, 'php8.3-fpm')">Start</button><button class="btn danger sm" type="button" aria-label="Stop php8.3-fpm" @click="askOp('stop:php8.3-fpm', 'stop php8.3-fpm', 'stop php8.3-fpm', null, 'php8.3-fpm')">Stop</button><button class="btn ghost sm" type="button" aria-label="Enable php8.3-fpm" @click="askOp('enable:php8.3-fpm', 'enable php8.3-fpm', 'enable php8.3-fpm', null, 'php8.3-fpm')">Enable</button><button class="btn ghost sm" type="button" aria-label="Disable php8.3-fpm" @click="askOp('disable:php8.3-fpm', 'disable php8.3-fpm', 'disable php8.3-fpm', null, 'php8.3-fpm')">Disable</button></div></td></tr><tr><td class="mono"><b>mysql</b></td><td><span class="pill ok">running</span></td><td style="color:var(--txt2)">14d</td><td>612 MB</td><td><span class="ok pill">enabled</span></td><td><div class="action-runner"><button class="btn ghost sm" type="button" aria-label="Restart mysql" @click="askOp('restart:mysql', 'restart mysql', 'restart mysql', null, 'mysql')">Restart</button><button class="btn ghost sm" type="button" aria-label="Reload mysql" @click="askOp('reload:mysql', 'reload mysql', 'reload mysql', null, 'mysql')">Reload</button><button class="btn ghost sm" type="button" aria-label="Start mysql" @click="askOp('start:mysql', 'start mysql', 'start mysql', null, 'mysql')">Start</button><button class="btn danger sm" type="button" aria-label="Stop mysql" @click="askOp('stop:mysql', 'stop mysql', 'stop mysql', null, 'mysql')">Stop</button><button class="btn ghost sm" type="button" aria-label="Enable mysql" @click="askOp('enable:mysql', 'enable mysql', 'enable mysql', null, 'mysql')">Enable</button><button class="btn ghost sm" type="button" aria-label="Disable mysql" @click="askOp('disable:mysql', 'disable mysql', 'disable mysql', null, 'mysql')">Disable</button></div></td></tr><tr><td class="mono"><b>redis</b></td><td><span class="pill ok">running</span></td><td style="color:var(--txt2)">14d</td><td>28 MB</td><td><span class="ok pill">enabled</span></td><td><div class="action-runner"><button class="btn ghost sm" type="button" aria-label="Restart redis" @click="askOp('restart:redis', 'restart redis', 'restart redis', null, 'redis')">Restart</button><button class="btn ghost sm" type="button" aria-label="Reload redis" @click="askOp('reload:redis', 'reload redis', 'reload redis', null, 'redis')">Reload</button><button class="btn ghost sm" type="button" aria-label="Start redis" @click="askOp('start:redis', 'start redis', 'start redis', null, 'redis')">Start</button><button class="btn danger sm" type="button" aria-label="Stop redis" @click="askOp('stop:redis', 'stop redis', 'stop redis', null, 'redis')">Stop</button><button class="btn ghost sm" type="button" aria-label="Enable redis" @click="askOp('enable:redis', 'enable redis', 'enable redis', null, 'redis')">Enable</button><button class="btn ghost sm" type="button" aria-label="Disable redis" @click="askOp('disable:redis', 'disable redis', 'disable redis', null, 'redis')">Disable</button></div></td></tr><tr><td class="mono"><b>meilisearch</b></td><td><span class="pill ok">running</span></td><td style="color:var(--txt2)">6d</td><td>96 MB</td><td><span class="ok pill">enabled</span></td><td><div class="action-runner"><button class="btn ghost sm" type="button" aria-label="Restart meilisearch" @click="askOp('restart:meilisearch', 'restart meilisearch', 'restart meilisearch', null, 'meilisearch')">Restart</button><button class="btn ghost sm" type="button" aria-label="Reload meilisearch" @click="askOp('reload:meilisearch', 'reload meilisearch', 'reload meilisearch', null, 'meilisearch')">Reload</button><button class="btn ghost sm" type="button" aria-label="Start meilisearch" @click="askOp('start:meilisearch', 'start meilisearch', 'start meilisearch', null, 'meilisearch')">Start</button><button class="btn danger sm" type="button" aria-label="Stop meilisearch" @click="askOp('stop:meilisearch', 'stop meilisearch', 'stop meilisearch', null, 'meilisearch')">Stop</button><button class="btn ghost sm" type="button" aria-label="Enable meilisearch" @click="askOp('enable:meilisearch', 'enable meilisearch', 'enable meilisearch', null, 'meilisearch')">Enable</button><button class="btn ghost sm" type="button" aria-label="Disable meilisearch" @click="askOp('disable:meilisearch', 'disable meilisearch', 'disable meilisearch', null, 'meilisearch')">Disable</button></div></td></tr></tbody></table><div class="op-confirm panel" @show="pending() !== null" role="group" aria-labelledby="op-confirm-prompt" x-cloak><span id="op-confirm-prompt" x-cloak>Type <b class="mono" x-cloak>{{ confirmTok() }}</b> to {{ confirmVerb() }}:</span><input data-stx-ref="opConfirmInput" class="op-confirm-input" :value="typed()" @input="typed.set($event.target.value)" @keydown.enter="runOp()" placeholder="confirm" autocomplete="off" aria-labelledby="op-confirm-prompt"><button type="button" class="btn sm" :class="{ danger: confirmDanger() }" :disabled="!canRun()" @click="runOp()" x-cloak>{{ confirmLabel() }}</button><button type="button" class="btn ghost sm" :disabled="busy()" @click="cancelOp()">Cancel</button></div><pre class="action-output op-output" @show="opShown()" aria-live="polite" x-cloak>{{ opOutput() }}</pre><p class="note">Install software with <span class="mono">cloud server:recipe acme-production-app &lt;recipe&gt;</span>.</p></div></div></div> <script data-stx-scoped>
433
433
  (function() {