/* Screen rules for projects, apps, deployments and their tabs.
   ===================================================================

   app.css owns the Console design system: tokens, the shell, and every shared
   component (sections, cards, tables, the rail, controls, status, steppers,
   banners, overlays, the log). This file is for rules that belong to one
   screen and nowhere else — a grid only the app Overview uses, a column width
   only the deployments table needs.

   Owned by the screens implementer for:
     projects.js  projectdetail.js  apps.js  appdetail.js  appsettings.js
     deployment.js

   (settings.js — Activity and the platform forms — is screens-data.css.)

   Rules:
     - Every colour comes from a token in app.css. A literal hex here is a bug
       in one of the two themes.
     - Prefix a class with the screen it belongs to (.app-overview-grid,
       .deploy-row-tag) so nothing here collides with the kit.
     - If two screens need the same shape, it is not a screen rule: add it to
       view.js and app.css instead.
     - Wide content scrolls in its own container. The body never scrolls
       sideways at 390px.
*/

/* ---- the Projects list ---------------------------------------------------
   The home screen has one job: say what is running and what needs attention
   before anything is read. The chip in the Health column says it in words and
   the kit's tone stripe (tr.tone-warn / tr.tone-bad) says it in shape; this is
   the one thing left that is only this screen's. */

/* A project's description is a sentence somebody wrote, so it is set in the
   sans and allowed to wrap — .cell-sub is the machine line, and it would put
   this in the mono of a repository path and refuse to break it. */
.projects-about {
  margin-top: 3px;
  max-width: 52ch;
  font-size: 12.5px;
  line-height: 1.45;
  color: var(--ink-2);
}

/* ---- the project page ----------------------------------------------------
   Apps and Databases are two sections of one wall, each with a search box in
   its head. Side by side, half the page each, a 320px box is wider than its
   own column: the label, the box, the count and the button come to more than
   the half holds and the strip wraps onto a second line. So while the halves
   are side by side the box gives way — and only then, because once they stack
   a growing search box would run the width of the page. */

@media (min-width: 1360px) {
  .split .search { flex: 1 1 150px; width: auto; }
}

/* ---- the app's Settings tab ----------------------------------------------
   A section has no box around it, so a lone control in one runs the width of
   the page unless it is told not to. A replica count is three characters and
   a domain is forty; neither is 1180px of anything. */

.app-narrow-field { max-width: 320px; }
.app-narrow-row { max-width: 560px; }

@media (max-width: 639px) {
  /* On a phone the description would be squeezed into a 40px column and turn
     every row into a paragraph. It keeps a readable measure and the table
     scrolls inside its own box instead, which is the rule everywhere else. */
  .projects-about { max-width: none; min-width: 26ch; }
}

/* ---- projects / project map / add app (worker A) ------------------------- */

/* The Projects list is a two-column screen: the table selects, the rail on the
   right says what the selected project holds. Everything here is either the
   rail's own furniture or the map's, and nothing else uses it. */

.projects-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  flex: none;
  border-radius: var(--radius);
  background: var(--accent-soft);
  color: var(--accent);
  font-size: 15px;
  font-weight: 650;
}

.projects-deploy { display: inline-flex; align-items: center; gap: var(--sp-2); }

/* The first-project hero centres its one control under the form. */
.projects-hero-actions { justify-content: center; margin-top: var(--sp-2); }

.projects-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.projects-chip {
  display: inline-flex;
  align-items: center;
  padding: 3px 9px;
  border-radius: var(--radius-tag);
  background: var(--surface-2);
  border: 1px solid var(--line);
  color: var(--ink-2);
  font-size: 12.5px;
}

.projects-rail-block { display: flex; flex-direction: column; gap: var(--sp-2); }
.projects-rail-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-3);
  padding-bottom: 6px;
  border-bottom: 1px solid var(--line);
}
.projects-rail-list { display: flex; flex-direction: column; }
.projects-rail-row {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding: 7px 0;
  min-width: 0;
  font-size: 13.5px;
}
.projects-rail-row + .projects-rail-row { border-top: 1px solid var(--line); }
.projects-rail-mark { display: inline-flex; color: var(--ink-3); flex: none; }
.projects-rail-name { font-weight: 500; }
.projects-rail-sub {
  margin-left: auto;
  font: 400 12px/1.5 var(--mono);
  color: var(--ink-2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 55%;
}

/* ---- the project map -----------------------------------------------------
   Apps in a row over the databases they are attached to, joined by elbowed
   edges. The edges are drawn from the boxes' measured positions after layout,
   so the canvas is the positioning context for all of them. */

.map-canvas {
  position: relative;
  padding: var(--sp-5) var(--sp-4) var(--sp-6);
  display: flex;
  flex-direction: column;
  gap: 52px;
  overflow-x: auto;
  min-height: 320px;
}
.map-row {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  gap: var(--sp-5);
  position: relative;
  z-index: 1;
}
.map-entry {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 10px;
  border: 1px solid var(--line-2);
  border-radius: var(--radius-tag);
  background: var(--surface);
  color: var(--ink-2);
  font-size: 12.5px;
}

.map-node {
  position: relative;
  width: 232px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 13px var(--sp-4) 14px;
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  background: var(--surface);
  box-shadow: var(--shadow-card);
  cursor: pointer;
  text-align: left;
}
.map-node:hover { border-color: var(--line-2); }
.map-node.on {
  border-color: var(--accent);
  box-shadow: 0 0 0 1px var(--accent);
}
.map-node-head { display: flex; align-items: center; gap: 10px; min-width: 0; }
.map-node-head .icon { width: 22px; height: 22px; color: var(--ink-3); flex: none; }
.map-node-name {
  border: none;
  background: none;
  padding: 0;
  font: 650 15px/1.3 var(--sans);
  color: var(--ink);
  cursor: pointer;
  text-align: left;
}
.map-node-name:hover { color: var(--accent); }
.map-node-sub {
  font: 400 12px/1.4 var(--mono);
  color: var(--ink-2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.map-node-foot {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  font-size: 12.5px;
  color: var(--ink-2);
  min-width: 0;
}
.map-node-foot a { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.map-bar {
  flex: 1 1 auto;
  height: 6px;
  min-width: 40px;
  border-radius: 3px;
  background: var(--surface-3);
  overflow: hidden;
}
.map-bar-fill { display: block; height: 100%; background: var(--accent); }
.map-bar-fill.warn { background: var(--warn); }
.map-bar-fill.bad { background: var(--bad); }

/* One edge is three straight segments and an arrowhead, positioned in pixels
   from the measured boxes. They sit under the cards. */
.map-edges { position: absolute; inset: 0; z-index: 0; pointer-events: none; }
.map-seg { position: absolute; background: var(--line-2); }
.map-arrow {
  position: absolute;
  width: 0;
  height: 0;
  border-left: 4px solid transparent;
  border-right: 4px solid transparent;
  border-top: 6px solid var(--line-2);
}
.map-edge-label {
  position: absolute;
  transform: translate(-50%, -50%);
  padding: 2px 7px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  color: var(--ink-2);
  font-size: 11.5px;
  white-space: nowrap;
}
.map-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  padding: 10px var(--sp-4);
  border-top: 1px solid var(--line);
  font-size: 12.5px;
  color: var(--ink-2);
}
.map-zoom { display: inline-flex; align-items: center; gap: var(--sp-2); }

/* ---- the add-app wizard --------------------------------------------------
   One page, four blocks down the left and the summary rail on the right. The
   blocks are the kit's numbered step sections with a rule between them. */

.appnew-block + .appnew-block {
  margin-top: var(--sp-5);
  padding-top: var(--sp-5);
  border-top: 1px solid var(--line);
}
.appnew-foot {
  display: flex;
  justify-content: flex-end;
  gap: var(--sp-2);
  flex-wrap: wrap;
}
.appnew-sub { font-size: 13px; color: var(--ink-2); margin-top: -6px; }
/* A segmented control in a form grid is one cell wide, so its buttons share
   that width rather than sizing to their labels: "2" is not a third of the
   control just because it is one character. */
.appnew-block .seg { width: 100%; }
.appnew-block .seg-btn { flex: 1 1 0; }
.appnew-summary-head { display: flex; align-items: center; gap: 10px; }
.appnew-summary-head .icon { width: 20px; height: 20px; color: var(--ink-3); }

@media (max-width: 639px) {
  .map-node { width: 100%; }
  .projects-rail-sub { display: none; }
}

/* ---- app / deployment / app settings / deployments list (worker B) --------
   Rules that belong to one of these screens and nowhere else. Everything with
   a colour in it takes a token from app.css. */

/* -- the Environment tab --------------------------------------------------
   The table is the document and the rail is the diff of what you have typed
   on top of it, so a pending row has to read as pending from across the
   page: a tinted left edge on the row, the old value struck through when it
   is on its way out. */

.env-filter { width: 260px; }
.env-num {
  width: 44px;
  color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}
.env-key { font-weight: 500; }
.env-value { display: inline-flex; align-items: center; gap: var(--sp-3); max-width: 100%; }
.env-text, .env-masked { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.env-lock { display: inline-flex; color: var(--ink-3); flex: none; }
.env-lock .icon { width: 13px; height: 13px; }
.env-masked { letter-spacing: 0.06em; color: var(--ink-2); }

tbody tr.env-pending > td:first-child { box-shadow: inset 2px 0 0 var(--accent); }
tbody tr.env-pending > td { background: var(--accent-soft); }
tbody tr.env-deleted > td:first-child { box-shadow: inset 2px 0 0 var(--bad); }
tbody tr.env-deleted > td { background: var(--bad-soft); }
tbody tr.env-deleted .env-key,
tbody tr.env-deleted .env-value { text-decoration: line-through; opacity: 0.75; }

/* The rail's diff: the two values side by side with an arrow between them,
   the pending one carrying the accent edge. */
.env-changes { display: flex; flex-direction: column; gap: var(--sp-3); }
.env-change {
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  padding: var(--sp-3);
  background: var(--surface);
}
.env-change-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-2);
  margin-bottom: var(--sp-3);
}
.env-change-key { font-size: 13.5px; font-weight: 600; }
.env-change-diff {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  align-items: end;
  gap: var(--sp-2);
}
.env-side { min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.env-side-label {
  font-size: 11.5px;
  color: var(--ink-2);
  background: var(--surface-2);
  border-radius: var(--radius-tag);
  padding: 1px 8px;
  align-self: flex-start;
}
.env-side.pending .env-side-label { background: var(--accent-soft); color: var(--accent); }
.env-side-value {
  border: 1px solid var(--line-2);
  border-radius: var(--radius);
  padding: 7px 10px;
  font-size: 12.5px;
  background: var(--surface-2);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.env-side.pending .env-side-value {
  background: var(--surface);
  border-left: 2px solid var(--accent);
}
.env-arrow { color: var(--ink-3); padding-bottom: 9px; }
.env-affected { margin-top: var(--sp-4); }
.env-affected-row {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin-top: var(--sp-2);
  font-size: 13px;
  color: var(--ink-2);
}
.env-affected-row .icon { color: var(--ink-3); }
.env-import { width: 100%; min-height: 220px; line-height: 1.6; }

/* The apply bar sits at the foot of the viewport while a draft exists: the
   count of what is pending and the three things you can do with it. */
.env-bar {
  position: sticky;
  bottom: 0;
  z-index: 5;
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  margin-top: var(--sp-5);
  padding: var(--sp-3) var(--sp-4);
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  background: var(--surface);
  box-shadow: var(--shadow-pop);
}
.env-bar > .icon { color: var(--accent); flex: none; }
.env-bar-text { font-size: 13.5px; }

/* -- the deployment page --------------------------------------------------
   A failed run says so in the title, in red, with the mark beside it. */

.deploy-title-failed {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-3);
  color: var(--bad);
}
.deploy-title-failed .icon { width: 24px; height: 24px; }

/* The rail carries more than one block on these two screens — Error, Release
   and Previous release; the selected domain's DNS record — so each after the
   first is set off by a rule rather than by space alone. */
.deploy-rail, .set-rail {
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
  min-width: 0;
}
.deploy-rail > .rail-head:not(:first-child),
.set-rail > .rail-head:not(:first-child) {
  padding-top: var(--sp-4);
  border-top: 1px solid var(--line);
}

/* The log card carries its tabs in its head instead of a title, so the tab
   row loses the page-level rule under it. */
.deploy-logs .tabs { border-bottom: 0; margin: 0; gap: var(--sp-4); }
.deploy-logs .tabs a, .deploy-logs .tabs button { padding: 6px 0; font-size: 13.5px; }
.deploy-logs .search { width: 200px; }
.deploy-logs .card-head { flex-wrap: wrap; }

/* -- app settings ---------------------------------------------------------
   The sub-tabs are a second, quieter row under the app's own tabs: same
   shape, one step down in weight, so the hierarchy reads at a glance. */

.set-subtabs { margin-bottom: var(--sp-5); }
.set-subtabs a, .set-subtabs button { font-size: 13.5px; padding-bottom: 8px; }

/* The five steps of a rollout, in the rail of Build & deploy. */
.set-behavior { list-style: none; margin: 0; padding: 0; }
.set-behavior li {
  display: grid;
  grid-template-columns: 24px minmax(0, 1fr);
  gap: var(--sp-3);
  padding-bottom: var(--sp-4);
  position: relative;
}
.set-behavior li:last-child { padding-bottom: 0; }
.set-behavior li:not(:last-child)::before {
  content: "";
  position: absolute;
  left: 11px;
  top: 26px;
  bottom: 6px;
  width: 1px;
  background: var(--line);
}
.set-behavior-text { display: flex; flex-direction: column; gap: 2px; }
.set-behavior-title { font-size: 13.5px; font-weight: 600; }
.set-behavior-sub { font-size: 12.5px; color: var(--ink-2); line-height: 1.5; }

/* -- the deployments list -------------------------------------------------
   Eight columns is a wide table. It scrolls inside .table-wrap like every
   other, but the two states that are read first must not wrap mid-word. */

.deploy-list th, .deploy-list td:first-child { white-space: nowrap; }

@media (max-width: 999px) {
  .env-filter { width: 160px; }
  .env-change-diff { grid-template-columns: minmax(0, 1fr); }
  .env-arrow { display: none; }
}

@media (max-width: 639px) {
  .env-bar { flex-wrap: wrap; }
  .deploy-logs .search { width: 100%; }
}
