/* ==========================================================================
   ProjectManagementPro.ClientWASM — layout
   The frames the application renders a screen inside: the pre-render screen, the empty
   shell of the access routes, the shell of the signed-in workspace, the access panel
   both auth routes draw, and — since PROJECTS-001 — the shell of a project with the
   three page frames of the portfolio (the listing, the entry and the project context),
   the head every one of them opens with, the phase strip and the pager. Rules that
   belong to a single component stay in that component's own sheet; the sheets here are
   global because more than one route uses them.
   ========================================================================== */

/* ---- Bootstrap screen, replaced by the first render ------------------- */
/* The markup lives in wwwroot/index.html, so this block is what a visitor sees while
   the WebAssembly bundle loads, before any component exists. The spinner is declared
   here as well as in feedback.css on purpose: index.html is not part of this delivery
   and it names `.boot__spinner`, so that class has to keep working on its own. */
.boot {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-sm);
  min-height: 100vh;
  padding: var(--space-lg);
  color: var(--color-text-muted);
}

.boot__spinner {
  width: 32px;
  height: 32px;
  border: 3px solid var(--color-primary-border);
  border-top-color: var(--color-primary);
  border-radius: 50%;
  animation: boot-spin var(--duration-loop) linear infinite;
}

.boot__text {
  margin: 0;
  font-size: var(--font-size-sm);
}

@keyframes boot-spin {
  to { transform: rotate(360deg); }
}

/* ---- Shell for the screens that need no session (EmptyLayout) --------- */
/* `Layout/EmptyLayout.razor` draws exactly `.layout-empty` and `.layout-empty__main`.
   The soft gradient is the one the active client paints behind its access card. */
.layout-empty {
  display: grid;
  place-items: center;
  min-height: 100vh;
  padding: var(--space-xl) var(--space-md);
  background: linear-gradient(160deg, var(--color-primary-soft) 0%, var(--color-bg) 55%);
}

.layout-empty__main {
  width: 100%;
  max-width: var(--layout-form-max);
}

/* ---- Shell for the signed-in workspace (MainLayout) ------------------- */
/* `Layout/MainLayout.razor` draws the header — the brand, the destinations, the way into
   the global search, the identity with its sign-out and the state of the live connection —
   the main region, and the notification host of the shell. The chrome is drawn only for a
   session, so a visitor sees the brand alone. */
.layout-header {
  position: sticky;
  top: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  gap: var(--space-md);
  min-height: var(--layout-header-height);
  padding: var(--space-3xs) var(--layout-content-padding);
  background: var(--color-surface-muted);
  border-bottom: var(--border-default);
  box-shadow: 0 1px 3px rgba(24, 31, 42, 0.06);
  color: var(--color-text);
}

.layout-header__brand {
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
  flex: 0 0 auto;
  font-size: var(--font-size-base);
  font-weight: var(--font-weight-semibold);
  color: var(--color-primary-strong);
  text-decoration: none;
}

.layout-header__brand-name {
  white-space: nowrap;
}

.product-mark {
  display: block;
  flex: 0 0 auto;
  overflow: visible;
}

.product-mark__path {
  fill: none;
  stroke: var(--color-primary);
  stroke-width: 3;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.product-mark__stage {
  fill: var(--color-surface);
  stroke: var(--color-primary);
  stroke-width: 2.5;
}

.product-mark__stage--final {
  fill: var(--color-accent);
  stroke: var(--color-surface);
}

/* The destinations of the header, and the current one: `aria-current` carries the state and
   this rule is what a sighted reader sees of it, so the two never disagree. */
.layout-header__nav,
.layout-header__item {
  display: flex;
  align-items: center;
}

.layout-header__links {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  margin: 0;
  padding: 0;
  list-style: none;
}

.layout-header__link {
  display: inline-flex;
  align-items: center;
  min-height: var(--layout-header-control-height);
  padding: var(--space-2xs) var(--space-sm);
  border-radius: var(--radius-sm);
  color: var(--color-text-muted);
  text-decoration: none;
  font-size: var(--font-size-sm);
  transition: background var(--duration-fast) var(--easing-standard);
}

.layout-header__link:hover {
  background: var(--color-surface);
  color: var(--color-text);
}

.layout-header__link[aria-current="page"] {
  background: var(--color-primary-soft);
  color: var(--color-primary-strong);
  font-weight: var(--font-weight-semibold);
}

/* The search entry. It sits after the destinations and takes the space left over, so the
   identity and the connection state stay at the end of the header whatever is drawn. */
.layout-header__search {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  margin-left: auto;
}

.layout-header__search-input {
  min-width: 180px;
  max-width: 280px;
  padding: var(--space-2xs) var(--space-xs);
  border: var(--border-width) solid var(--color-primary-border);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  color: var(--color-text);
  font-family: inherit;
  font-size: var(--font-size-sm);
}

/* Why the search did not navigate: the client's own sentence, next to the field it is about. */
.layout-header__note {
  max-width: 22ch;
  margin: 0;
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
}

/* The identity and its panel. The panel is positioned against this box, which is the only
   reason the box exists. */
.layout-header__user {
  position: relative;
}

.layout-header__user-button {
  min-height: var(--layout-header-control-height);
  padding: var(--space-2xs) var(--space-sm);
  border: var(--border-default);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  color: var(--color-text);
  font-family: inherit;
  font-size: var(--font-size-sm);
  cursor: pointer;
}

.layout-header__menu {
  position: absolute;
  top: calc(100% + var(--space-2xs));
  right: 0;
  z-index: 50;
  min-width: 220px;
  padding: var(--space-md);
  background: var(--color-surface);
  color: var(--color-text);
  border: var(--border-default);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
}

.layout-header__menu-name {
  margin: 0;
  font-weight: var(--font-weight-semibold);
}

.layout-header__menu-email {
  margin: 0 0 var(--space-sm);
  color: var(--color-text-muted);
  font-size: var(--font-size-sm);
  overflow-wrap: anywhere;
}

/* The state of the live connection. It is text and not a dot: a colour alone would say
   nothing to a reader who cannot see it, and this state is worth saying. */
.layout-header__status {
  margin: 0;
  font-size: var(--font-size-sm);
  color: var(--color-secondary-strong);
}

.layout-main {
  max-width: var(--layout-content-max);
  margin: 0 auto;
  padding: var(--layout-content-padding);
}

/* ---- Access panel: sign in and registration --------------------------- */
/* The card the two access routes render inside `.layout-empty__main`. The class names
   and the widths are the shared part of those two screens, which is why they are here
   and not in a scoped sheet: sign in and registration are two real consumers of the
   same panel. The forms themselves are composed from Components/Forms. */
.auth-panel {
  padding: var(--space-xl);
  background: var(--color-surface);
  border: var(--border-default);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
}

.auth-panel__title {
  margin: 0 0 var(--space-2xs);
}

/* `__note` is the name the placeholder routes of this delivery use for the line under
   the heading; `__subtitle` is the same element on the real screens. One rule, so the
   placeholder keeps its styling until AUTH-001 rewrites it. */
.auth-panel__note,
.auth-panel__subtitle {
  margin: 0 0 var(--space-lg);
  color: var(--color-text-muted);
  font-size: var(--font-size-sm);
}

/* The alert a screen draws above its form — the server's message, or the notice the other access
   screen left behind — is separated from the form it precedes. The spacing belongs to the panel
   because it is the panel that stacks its own children, and the rule is scoped to `.auth-panel` so
   it cannot space an alert anywhere else. It replaces the empty spacer the active client inserted
   for exactly this gap (`<div style="height:var(--space-md)"></div>`, read from its `/login` page): a
   static inline style is what gate 7 forbids, so the distance lives here, as a token. */
.auth-panel > .alert {
  margin-bottom: var(--space-md);
}

/* The form the two access routes draw inside the panel: one more element of the panel family that
   `__title`, `__subtitle` and `__footer` already belong to — which is why the rule is here and not
   in forms.css, whose own header scopes it to the classes `Components/Forms` render, while this one
   is named by the two access forms. It is a single column: the fields and the action that submits
   them are stacked and separated by the shared rhythm, the 16px the active client's `.stack` put
   between the same children of the same two forms. Without this rule the four fields of the
   registration form and its submit action sit flush against one another. */
.auth-panel__form {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}

.auth-panel__footer {
  margin-top: var(--space-lg);
  padding-top: var(--space-md);
  border-top: var(--border-default);
  font-size: var(--font-size-sm);
}

/* ==========================================================================
   Portfolio — shell of a project, page frames, head, phase strip and pager
   The screens PROJECTS-001 landed: `/` (HomePage), `/projects` (ProjectsPage) and
   `/projects/{id}` (ProjectWorkspacePage, drawn inside ProjectLayout). What is here is
   the frame and the page furniture — the repeated record and the dialog have their own
   sheets (collections.css, dialogs.css). Every value is a token of tokens.css.
   ========================================================================== */

/* ---- Shell of a project (Layout/ProjectLayout.razor) ------------------ */
/* `ProjectLayout` is nested in `MainLayout`, so the product header and the page padding
   are already drawn by the time this renders: what it adds is the way back to the
   portfolio and the body the context page fills. */
.project-shell {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
  /* **La banda del proyecto queda pegada debajo de la cabecera de la aplicación**, que es la instrucción del dueño
     del 2026-09-30: «esa primera barra la vamos a subir lo suficiente de tal forma que esté exactamente debajo de la
     barra donde está el dashboard, los proyectos, cost centers etc». Lo que había en medio es el relleno de arriba de
     `.layout-main`, y sólo el de arriba se cancela: los lados y el pie siguen como estaban y las pantallas de dentro
     conservan su ritmo. */
  margin-top: calc(-1 * var(--layout-content-padding));
}

.project-chrome {
  position: sticky;
  top: var(--layout-header-height);
  z-index: 90;
  display: flex;
  flex-direction: column;
  min-width: 0;
  background: transparent;
  border: 0;
  border-radius: 0;
  box-shadow: none;
}

/* The band of the project: its practical summary, in two rows — the name, and the status with the facts spread across
   the whole width (`ProjectHeader`). It is a column now and no longer a two-column grid of name and status chip,
   because what it holds is the whole summary and the summary decides its own two lines.
   **Y se separa un poco de la tira de fases**, que es la otra mitad de la instrucción del dueño del 2026-09-30: «vamos
   a separar un poco la primer barra de la segunda barra de las fases del proyecto». El hueco es el fondo del marco, que
   es lo que hace que se lean como dos barras y no como una sola partida en dos. */
.project-chrome__identity {
  display: flex;
  flex-direction: column;
  gap: var(--space-3xs);
  min-width: 0;
  margin-bottom: var(--space-3xs);
  padding: var(--space-xs) var(--space-md);
  background: var(--color-surface);
  border-radius: var(--radius-lg);
}

.project-chrome__heading {
  min-width: 0;
}

.project-chrome__name {
  margin: 0;
  overflow: hidden;
  color: var(--color-text);
  font-size: var(--font-size-xl);
  font-weight: var(--font-weight-semibold);
  line-height: 1.2;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.project-chrome__status {
  padding: var(--space-3xs) var(--space-xs);
  background: var(--color-primary-soft);
  border: var(--border-width) solid var(--color-primary-border);
  border-radius: var(--radius-sm);
  color: var(--color-primary-strong);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  white-space: nowrap;
}

/* `min-width: 0` so a wide child — the artefact table, a long project name — shrinks with
   its column instead of widening the shell. */
.project-shell__body {
  min-width: 0;
}

/* ---- The page frames -------------------------------------------------- */
/* `/projects`, `/` and the project context are the same frame: a column of regions
   separated by the shared rhythm, so a screen that adds a note, a filter bar, a list or a
   pager does not space it itself. The active client spaced its own regions with margins
   (`.section`); a flex gap keeps the distances equal whatever a state hides. The artefact
   screens of a project are drawn in this same frame — the background of a project is the
   first of them — so an artefact adds its own regions to the same rhythm instead of
   introducing a second one. */
.projects,
.home,
.project-workspace {
  display: flex;
  flex-direction: column;
  gap: var(--space-lg);
}

/* **El marco de una pantalla de artefacto: la leyenda y lo suyo, a 2 px.** Los catorce artefactos del Iniciando
   comparten una sola forma, y el dueno la fijo mirando la pantalla de los interesados el 2026-09-30 y la extendio a
   todas el 2026-10-01: «cuando abro cualquier artefacto hay una leyenda explicativa de lo que significa ese artefacto
   que abri y debajo de esa leyenda esta el contenido propio del artefacto tablas/cards lo que sea que defina cada
   artefacto.. la organizacion y visualizacion de esa leyenda en cada artefacto debe ser igual a como se organizo en
   stakeholders en terminos de alto de la card tamano de letra y separacion con el contenido del artefacto propio».
   Las tres cosas viven aqui y en ningun otro sitio: **la card**, **la letra** y **la distancia**.
     · la card y su letra las dibuja `.page-header__subtitle--card` —una superficie blanca, con borde y esquinas, a
       `var(--font-size-base)` (12 px) y con su relleno, igual para las catorce—;
     · la distancia la pone este marco: **2 px** entre la leyenda y lo que va debajo, que es el contenido del artefacto.
   **Antes cada familia decia lo suyo**: nueve hojas declaraban la pagina como `display: block` o con 12 px de hueco y
   cinco venian del marco comun con 24, asi que la leyenda quedaba a una distancia distinta en cada artefacto —y en
   cuatro de ellos pegada al contenido—. Ahora el marco es **uno solo** y las hojas de familia no lo repiten.
   El marco de `/projects`, `/` y el contexto de proyecto sigue separando sus regiones con 24 px: aquello no es un
   artefacto, no tiene leyenda y no se toca. */
.background-page,
.constraint-page,
.criterion-page,
.deliverable-page,
.exclusion-page,
.expectation-page,
.expert-judgement-page,
.hazop-page,
.investment-page,
.known-risk-page,
.quality-page,
.risk-page,
.scope-page,
.stakeholder-page {
  display: flex;
  flex-direction: column;
  gap: var(--space-3xs);
}

/* The head of a screen: its title, the sentence that says what it shows, and the actions
   of the page. It is the block the active client called `.page-header`; here the actions
   are a third child of the same header rather than a sibling column, so the head is a
   column and the action row starts below the subtitle.

   One component draws it — `Components/Chrome/PageHeader` — and every screen of this
   client composes that component, so these are the only rules a page title has: no screen
   declares a head of its own any more (UI-004 finished the migration UI-003 opened, which
   left `/projects`, `/` and the project context drawing their own). */
.page-header {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-2xs);
}

/* The page title carries `tabindex="-1"` and takes the caret on arrival and when a dialog
   closes; base.css draws the one focus ring for it and nothing here removes it. The icon
   sits inside the heading and these three values are the only thing the head does with it:
   it is aligned with the text and it never squeezes a long title. */
.page-header__title {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  margin: 0;
}

/* The heading anchors the screens' own automation addresses, which they pass to the shared
   head as its `HeadingClass`: a shared piece renders them, so their rule belongs to this
   sheet, beside the one that draws the head, and it adds nothing but the margin the head
   already takes care of. They are anchors and never a second style. */
.background-page__title,
.constraint-page__title,
.stakeholder-page__title,
.quality-page__title,
.projects__title {
  margin: 0;
}

/* The same kind of anchor, for the two screens whose own automation addresses the action row
   by name (`/projects` and `/`). It draws no box of its own on purpose — `display: contents`
   leaves the controls as the row's own items — so the row a person sees is still the head's
   and never the screen's. */
.projects__actions,
.home__actions {
  display: contents;
}

/* One icon of `Components/Icons/Icon`. The drawing, the size and the colour are the
   component's and the caller's; what belongs to the sheet is that an icon is never
   squeezed by the label beside it, which matters in the two places it is a flex item. */
.icon {
  flex: 0 0 auto;
  vertical-align: middle;
}

/* The sentence that says what the screen shows. It takes the whole width the page has — the cap it used to carry
   (72ch) wrapped a long explanation into three or four lines, which is height taken from the collection — and one
   step down in size, because it is guidance about the screen and not content of it. */
.page-header__subtitle {
  margin: 0;
  color: var(--color-text-muted);
  font-size: var(--font-size-xs);
}

/* The same sentence as the card that opens an artefact screen. Inside a project the chrome above has already named
   the artefact and the tab is marked, so what is left above the control is what the artefact is; drawn as the surface
   it reads as the screen's own opening rather than as another line of chrome, and it spans the whole width the page
   gives it.
   **La letra es de 12 px y la tarjeta se pega a la barra de arriba**, y las dos cosas son del 2026-09-30: el dueno
   pidio sobre la pantalla de los interesados que a esta leyenda «le aumentaremos el tamano de letra a 12 px y la
   pondremos 2 px mas abajo de la barra ficticia». La barra ficticia es el hueco de la barra 5 —la de los artefactos de
   una etapa, que esta etapa no tiene y cuyo alto se respeta igual—, y el `margin-top` negativo es lo que la sube contra
   el marco: el armazon separa el chrome del cuerpo con 16 px (`project-shell`) y aqui se dejan **2**, que es el numero
   que el dueno pidio. */
.page-header__subtitle--card {
  align-self: stretch;
  padding: var(--space-sm) var(--space-md);
  margin-top: calc(var(--space-3xs) - var(--space-md));
  background: var(--color-surface);
  border: var(--border-default);
  border-radius: var(--radius-lg);
  font-size: var(--font-size-base);
}

.page-header__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-xs);
  margin-top: var(--space-sm);
}

/* The way back a screen can offer for itself, for the case it is not framed by a chrome
   that already draws one. The two artefact screens of this delivery are framed by the
   project shell, which has its breadcrumb, so they pass none; the head keeps the slot for
   the screen that needs it. */
.page-header__back {
  margin: 0;
  color: var(--color-text-muted);
  font-size: var(--font-size-sm);
}

.page-header__back-link {
  white-space: nowrap;
}

/* The lines that explain what a screen is showing, or what the server does with a
   parameter it accepts (`scope=tenant`). They are page text and not a message of the
   feedback family: nothing here is a reaction to a failure. */
.projects__note,
.home__note,
.background-page__note,
.constraint-page__note {
  max-width: 80ch;
  margin: 0;
  color: var(--color-text-muted);
  font-size: var(--font-size-sm);
}

/* The count the server answered, announced through `role="status"`, so it is read as a
   status and drawn as the secondary line the note above is. An artefact screen does not
   draw its own: the count of the entries it holds is the one the workspace prints beside
   the tab of its content (`ArtifactWorkspace`), which is why `background-page__count` —
   the class this rule shared with the two screens below — was deleted with the last line
   that used it. */
.projects__summary,
.home__count,
.constraint-page__summary {
  margin: 0;
  color: var(--color-text-muted);
  font-size: var(--font-size-sm);
}

/* The way out a failed or empty state offers — retry, clear the filters, go to the first
   page. It follows the alert or the empty state of its own region, so it only has to hold
   its controls in a row. */
.projects__recovery,
.home__recovery,
.project-workspace__recovery,
.background-page__recovery,
.constraint-page__recovery {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-xs);
}

/* The section heading of the entry screen. It is a heading of a frame that already
   separates its regions with a gap, so it carries no margin of its own. */
.home__section {
  margin: 0;
}

/* ---- Pager of the listing (ProjectsPage.razor) ----------------------- */
/* Paging is the server's, so the pager closes the listing under a hairline and says which
   page of how many the server actually applied. */
.projects__pager {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--space-md);
  padding-top: var(--space-md);
  border-top: var(--border-default);
}

.projects__page {
  margin: 0;
  color: var(--color-text-muted);
  font-size: var(--font-size-sm);
}

/* ---- Header of the open project (ProjectHeader.razor) ---------------- */
/* **Dos filas y nada más**, que es la instrucción del dueño del 2026-09-30: la primera con el nombre y su leyenda
   `Status : …`, la segunda con los datos. Vive dentro de la banda del proyecto (`.project-chrome__identity`), que es
   quien pone la superficie, así que aquí no hay tarjeta, relleno ni borde propios.
   Los valores que el servidor no publicó no se dibujan (`PROJECTS-001.md` §4), así que nada deja hueco para una fila
   vacía. */
.project-header {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  column-gap: var(--space-md);
  /* **Las dos filas comparten las mismas dos columnas**: el nombre y los datos a la izquierda, las acciones del
     proyecto a la derecha. Es la corrección del dueño del 2026-09-30 — «hay que mejorar que salga un poquito más bajo
     como 2 px y el último dato no salga abajo de los botones de la primera fila»—: el hueco entre las dos filas es el
     doble del que había (4 px en vez de 2) y la fila de los datos ocupa **la primera columna**, así que se reparte a lo
     ancho hasta donde empiezan los botones y su última pieza no cae debajo de ellos. */
  row-gap: var(--space-2xs);
  align-items: center;
  min-width: 0;
}

/* La etiqueta de la fase se retiró de la vista con la instrucción de las dos filas —la tira de fases que va justo
   debajo ya dice dónde está el proyecto— y su regla se queda aquí porque su marcado se quedó comentado en
   `ProjectHeader.razor`: volver a ponerla es descomentar las dos cosas. */
.project-header__phase {
  margin: 0;
  color: var(--color-secondary);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
}

/* **La primera fila: el nombre a la izquierda y las dos acciones del proyecto a la derecha**, que es donde el dueño
   las pidió el 2026-09-30. El par de botones es el compartido `RowActions` —icono solo, con su leyenda al pasar el
   puntero— y esta caja no dibuja nada: sus dos piezas son las dos columnas de la rejilla de arriba, que es lo que hace
   que la fila de los datos venga después **a la izquierda** y termine antes de los botones. */
.project-header__head {
  display: contents;
}

/* Las dos acciones no se encogen ni se parten: son dos botones de icono y caben siempre. */
.project-header__actions {
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  gap: var(--space-2xs);
}

/* **La segunda fila, repartida a todo lo ancho**: el estado y los siete datos, de extremo a extremo. Es la corrección
   del dueño del 2026-09-30 — «el contenido de la segunda fila lo vas distribuir de forma que ocupe todo el ancho de la
   barra»—, y se envuelve sólo cuando la ventana no los sostiene, momento en el que el reparto se rehace entre las dos
   líneas. */
.project-header__row {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-2xs) var(--space-lg);
  width: 100%;
  min-width: 0;
}

/* Un nombre de proyecto es texto libre que escribió una persona: en una banda de una sola línea se recorta antes que
   ensanchar el marco, que es lo que hacía el nombre cuando esta banda lo dibujaba sola. */
.project-header__name {
  margin: 0;
  min-width: 0;
  overflow: hidden;
  color: var(--color-text);
  font-size: calc(var(--font-size-xl) + 2px);
  font-weight: var(--font-weight-semibold);
  line-height: 1.2;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.project-header__status {
  margin: 0;
  color: var(--color-text-muted);
  font-size: var(--font-size-base);
  white-space: nowrap;
}

/* El valor del estado, destacado sobre su leyenda: la leyenda dice qué es y el valor qué dice. */
.project-header__status-value {
  color: var(--color-text);
  font-weight: var(--font-weight-semibold);
}

/* La lista de datos **no dibuja caja**: sus siete piezas son piezas de la fila de arriba y se reparten con ella, que es
   lo que hace que el estado y los datos sean una sola línea repartida y no dos bloques pegados. */
.project-header__facts {
  display: contents;
}

.project-header__fact {
  display: flex;
  align-items: baseline;
  gap: var(--space-2xs);
  min-width: 0;
}

.project-header__fact dt {
  color: var(--color-text-muted);
  font-size: var(--font-size-base);
}

.project-header__fact dd {
  margin: 0;
  font-size: var(--font-size-base);
  overflow-wrap: anywhere;
}

/* ---- Phase strip (PhaseNavigation.razor) ----------------------------- */
/* The strip of the five phases of the walk: one small surface per step, with its label as the whole tab
   (`DEC-048`). The step being read is the one the markup marks `aria-current="page"` — the same attribute assistive
   technology reads, so the drawing cannot disagree with the announcement — and a step drawn as a link leads to **the
   dashboard of that phase**, which is the project's own screen with the phase selected, and not to an artefact of the
   phase (`DEC-053`). A step the caller cannot open is a `span` and not a fake link. */
.phase-navigation {
  overflow-x: auto;
  overscroll-behavior-x: contain;
  background: transparent;
  border-top: 0;
  border-bottom: 0;
  scrollbar-width: thin;
}

.phase-navigation__list {
  display: flex;
  flex-wrap: nowrap;
  gap: var(--space-2xs);
  margin: 0;
  /* **Todas las barras empiezan y acaban donde empieza y acaba la tarjeta del proyecto.** Es la correccion del dueno
     del 2026-09-30: «la barra 2 (del nombre del proyecto) tiene una card ahi deben iniciar y finalizar todas las demas
     barras porque si no se ve una barra mas ancha que otra como un escalon». La tarjeta rellena 16 px por dentro para
     su texto, pero lo que manda es **su borde**: las barras van a ras de el, sin sangria propia. */
  padding: var(--space-2xs) 0;
  list-style: none;
}

.phase-navigation__step {
  display: block;
  flex: 1 0 132px;
  min-width: 132px;
}

.phase-navigation__tab {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  /* The height of a control on a pointer layout, which is what this strip is: one row of five steps that are read
     across. It used to be 44 px here too, which made the strip 4 px taller than the bar of artefacts below it for
     no reason — the touch minimum is served by the media query at the end of this sheet, where the step is 44 px
     again (`DEC-049`). */
  min-height: var(--control-height);
  padding: var(--space-2xs) var(--space-sm);
  border: var(--border-width) solid transparent;
  border-radius: var(--radius-sm); background: var(--color-surface);
  color: var(--color-text);
  text-align: center;
  text-decoration: none;
  transition: background var(--duration-fast) var(--easing-standard), border-color var(--duration-fast) var(--easing-standard);
}

a.phase-navigation__tab:hover {
  background: var(--color-surface-muted);
  border-color: var(--color-border);
}

/* The faint outline of a step that is **neither the one being read nor one already approved**: it is what tells a
   reader that the step is a place they can still go to, and it is the same outline the artefact tabs of the strip
   below wear. The step being read keeps the filled treatment, and a phase already approved wears nothing at all:
   it is behind the walk and it invites no click (`DEC-049`). The two `:not()`s are what exclude those two, so the
   rule cannot take the selected treatment away from the step being read. */
.phase-navigation__tab:not(.phase-navigation__tab--selected):not(.phase-navigation__tab--completed) {
  border-color: var(--color-border);
}

.phase-navigation__tab--selected {
  background: var(--color-primary-soft);
  border-color: var(--color-primary-border);
  color: var(--color-primary-strong);
}

.phase-navigation__tab--locked {
  border-color: var(--color-border-strong); border-style: dashed; background: var(--color-border); color: var(--color-text-muted);
  cursor: not-allowed;
}

/* The state the server published and, for a locked step, the sentence that says why it cannot be opened:
   **both are in the markup and neither is drawn.** The owner removed the two captions from the strip on
   2026-09-25 (`DEC-048`) — a locked step was three lines of explanation tall — and the strip is now the
   names, with the state and the reason left to the screen reader, to the `title` and to the styling of the
   step. The classes stay in the markup because the chrome tests read the published values through them, so a
   rule that paints either of them again would undo that decision instead of completing it. */

/* La fila del nombre de una fase: su icono y su palabra, centrados. El icono no se encoge nunca y la palabra es la que
   manda — así una fase con un nombre largo no empuja el icono fuera. */
.phase-navigation__head {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-3xs);
  min-width: 0;
}

.phase-navigation__label {
  font-size: var(--font-size-base);
  font-weight: var(--font-weight-semibold);
  overflow-wrap: anywhere;
}

/* ---- Bar of artefacts (Components/Chrome/ArtifactNavigation) ---------- */
/* The second level of the project chrome, drawn by the layout so it travels with every screen of the project: the
   server's own table of artefacts, with the one being read marked. It is the access the owner lost — «la app
   anterior en la phase initiating tenia una barra horizontal y uno accedia al artefacto de forma facil y no perdia
   de vista uno ese acceso hoy ya no esta» — and it lives in the chrome rather than in a screen precisely because a
   screen is left behind when the artefact is opened.

   One row of the bar is the same three facts in both of its shapes: the icon of the family, the label the server
   published and the figures of the row. A row whose screen does not exist is a `span` and not an anchor, and that
   is `DEC-W28` drawn: it is a row of the table and nothing a pointer or a keyboard can act on. */
.artifact-navigation {
  /* The strip never wraps into several lines of rows: it is one row of two-line tabs the person reads across, and
     the higher floor is what those two lines need. On a narrow window it scrolls inside itself instead of pushing
     the screen down, but the two-line row is what keeps that scroll from arriving in the first place.
     `overscroll-behavior` keeps a scroll that reaches the end of the strip from moving the page behind it. */
  overflow-x: auto;
  overscroll-behavior-x: contain;
  min-height: 60px;
  padding: var(--space-2xs) var(--space-sm);
  background: var(--color-surface);
  border-radius: 0 0 var(--radius-lg) var(--radius-lg);
  scrollbar-width: thin;
}

.artifact-navigation__list {
  display: flex;
  flex-wrap: nowrap;
  gap: var(--space-2xs);
  margin: 0;
  /* **A ras del borde de la tarjeta del proyecto**, como las otras tres barras: esta no se dibuja en Inicio —alli la
     navegacion es el recorrido—, pero en las fases siguientes aparece pegada a las mismas barras y era la unica sin
     arreglar (2026-09-30). */
  padding: 0;
  list-style: none;
}

.artifact-navigation__item {
  /* The tab keeps the width it asks for and the strip scrolls when the phase publishes more rows than fit: a row of
     fourteen artefacts that were allowed to shrink is what used to squeeze the shortest names. */
  display: flex;
  flex: none;
}

/* **In `Initiating` the tabs share the width the phase strip above already occupies.** The phase publishes fourteen
   rows and the sum of their tabs was narrower than the sum of the five steps, so the two strips ended in different
   places and the row of artefacts read as if it were cut short; here the free room is spread equally between the tabs,
   which leaves the two strips the same width and the tabs still close to each other in size (`DEC-052`, the owner:
   «aprovechemos esa información… de tal forma que la suma de los anchos de los nombres de las fases sea igual a la
   suma de los anchos de los nombres de los artefactos»). It is **not** applied to the other phases: four artefacts
   sharing that width would be four very wide tabs, which is exactly what he asked to avoid. */
.artifact-navigation__list--justified .artifact-navigation__item {
  flex: 1 1 auto;
}

/* One row, in two lines: the icon above and the name below, both centred on the row. The shape is what keeps the
   strip narrow: a phase publishes fourteen artefacts and, laid out in one line, every row was as wide as its icon plus
   its whole label. The name is never shortened to buy that width (the owner asked for it complete); it is the layout
   that gives the room.

   **Every tab is at least as wide as the longest single word of the artefact names** — the floor is declared once, in
   `tokens.css`, as `--layout-artifact-tab-min-width`, and it is twelve characters plus the tab's own padding, which is
   `Stakeholders`, `Expectations` and `Deliverables` (`DEC-051`). It is what stops `Scope` from being a third of the
   width of the row beside it. A name of two words — `Acceptance criteria`, `Investment items` — is wider than the
   floor and keeps its own width, which is what the owner asked for: the two-word names adjust, and every other tab is
   the same width. */
.artifact-navigation__link,
.artifact-navigation__row {
  display: grid;
  justify-items: center;
  gap: var(--space-3xs);
  min-width: var(--layout-artifact-tab-min-width);
  min-height: 52px;
  padding: var(--space-2xs) var(--space-xs);
  border: var(--border-width) solid transparent;
  border-radius: var(--radius-sm);
  color: inherit;
  font-size: var(--font-size-sm);
  text-decoration: none;
  white-space: nowrap;
}

/* A row of the table whose screen is not built yet: it is drawn as the record it is and it does not pretend to be
   a control — no pointer, no hover, no caret. */
.artifact-navigation__row {
  color: var(--color-text-muted);
  cursor: default;
}

.artifact-navigation__link:hover {
  background: var(--color-surface-muted);
  border-color: var(--color-border);
}

/* The same faint outline as the phases above, and for the same reason: a tab that is not the artefact being read
   is a place the reader can still go to, and the outline is what says so without filling the strip with fourteen
   coloured buttons (`DEC-049`). The rows whose screen does not exist are **not** outlined: they are records of
   the table and not controls, they carry no pointer and no hover (`DEC-W28`), and an outline would offer a click
   that nothing answers. */
.artifact-navigation__link:not([aria-current="page"]) {
  border-color: var(--color-border);
}

/* The artefact being read, marked with the attribute assistive technology reads: the drawing cannot disagree with
   the announcement because both are this one attribute. */
.artifact-navigation__link[aria-current="page"] {
  background: var(--color-primary-soft);
  border-color: var(--color-primary-border);
  color: var(--color-primary-strong);
  font-weight: var(--font-weight-semibold);
}

.artifact-navigation__icon {
  display: flex;
  align-items: center;
}

.artifact-navigation__label {
  overflow-wrap: anywhere;
}

.artifact-navigation__empty {
  margin: 0;
  padding: var(--space-xs);
  color: var(--color-text-muted);
  font-size: var(--font-size-sm);
}

@media (max-width: 767px) {
  :root {
    --layout-header-height: 56px;
  }

  .layout-header {
    gap: var(--space-sm);
    min-height: var(--layout-header-height);
    padding-inline: var(--space-sm);
    overflow-x: auto;
    overscroll-behavior-x: contain;
  }

  .layout-header__search,
  .layout-header__note,
  .layout-header__status {
    display: none;
  }

  .layout-header__brand-name {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
  }

  .layout-header__user {
    margin-left: auto;
  }

  .project-chrome {
    top: var(--layout-header-height);
    margin-inline: calc(-1 * var(--layout-content-padding));
    border-right: 0;
    border-left: 0;
    border-radius: 0;
  }

  .project-chrome__identity {
    grid-template-columns: minmax(0, 1fr);
    border-radius: 0;
  }

  .project-chrome__status {
    display: none;
  }

  .project-chrome__name {
    display: -webkit-box;
    overflow: hidden;
    font-size: var(--font-size-lg);
    white-space: normal;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
  }

  .phase-navigation__step {
    flex-basis: 124px;
    min-width: 124px;
  }

  /* The phase tabs are the ones that have to grow to the touch minimum here: the artefact tabs are already 52px,
     because their two lines are taller than that. */
  .phase-navigation__tab {
    min-height: 44px;
  }

  .artifact-navigation {
    border-radius: 0;
  }
}

/* The three figures of a row — its items, the ones needing investigation and the ones in scope — are **not drawn**
   any more: they sat on the name's own line and took the width the names need, which is what the owner asked to stop
   (`DEC-051`). They are still read, because they are the row's `title`, and the screen behind the row is where a
   count is a measurement. The classes are gone from the markup with the rules: a `.artifact-navigation__count` that
   is painted again would be a fourth value competing with the name. */

/* ==========================================================================
   The page of the quality artefact — Features/Quality/QualityPage.razor
   ========================================================================== */
/* The frame itself is the shared one above — `.quality-page` is one more screen of a project
   and joins the same selector list — so what is declared here is only the furniture this page
   adds: the figures of the artefact, the notice of what is incomplete, and the two columns.

   **Why it is here and not in a sheet of its own.** The page frame of an artefact is this
   sheet's (`deliverables.css` is a sheet of its own because its list is a tree, a shape no
   other family draws); the rule of the artefact template §0.9 is that a missing style goes to
   the sheet that already owns the pattern. */

/* The three figures the active screen draws in its own row of badges
   (`NewProjectQuality.razor:73-81`): how many items the project has, how many the server
   publishes as defined, and how many still hold the phase open. They are figures of the
   screen and not a status, so they are drawn as a list of readings. */
.quality-page__figures {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2xs);
  margin: 0 0 var(--space-sm);
  padding: 0;
  list-style: none;
}

.quality-figure {
  padding: var(--space-3xs) var(--space-xs);
  background: var(--color-surface-muted);
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius-sm);
  color: var(--color-text-muted);
  font-size: var(--font-size-sm);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* The one that keeps the phase gate closed carries the palette's warning role, which is what
   the active screen's own badge does with it. */
.quality-figure--warning {
  background: var(--color-accent-soft);
  border-color: var(--color-accent-border);
  color: var(--color-text);
}

/* And the artefact with nothing outstanding is drawn plainly. It is a modifier of its own and
   not the absence of the other one: the class the screen draws is stated once, in the
   code-behind that owns the reading. */
.quality-figure--settled {
  background: var(--color-success-soft);
  border-color: var(--color-success-border);
  color: var(--color-secondary-strong);
}

/* The same truth the phase gate refuses the approval with, said where the person can act on
   it: the shared alert draws an outcome and has no warning variant, so this line is the
   screen's own — the same reason the constraints and the exclusions screens draw theirs. */
.quality-page__incomplete {
  margin: 0 0 var(--space-md);
  padding: var(--space-xs) var(--space-sm);
  background: var(--color-accent-soft);
  border: var(--border-width) solid var(--color-accent-border);
  border-radius: var(--radius-sm);
}

/* Why the write controls are absent when the reason is the phase: the sentence names the
   phase and the way out of it. */
.quality-page__note {
  margin: 0 0 var(--space-md);
  color: var(--color-text-muted);
}

.quality-page__recovery {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-xs);
  margin-top: var(--space-sm);
}

/* The count of the list when it is empty, in one line of secondary text: the empty state
   below it says what to do. */
.quality-page__summary {
  margin: 0 0 var(--space-sm);
  color: var(--color-text-muted);
}

/* The action that adds an item: `DEC-090` point 3 puts it above the list and below the
   suggestions, which is the hole the artefact template fixes for every screen. */
.quality-page__list-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-xs);
  margin-bottom: var(--space-md);
}

.quality-page__main,
.quality-page__scope {
  min-width: 0;
}

/* ==========================================================================
   The row of chips that filters a listing — Components/Filters/FilterChips.razor
   ========================================================================== */
/* A control of a page and not of a family: three artefacts filter a listing by a value the server publishes, so the
   row is declared once here, beside the other shared furniture of a screen (the head, the phase strip, the artefact
   bar). It looks like the segmented control of the view switch because it is the same kind of thing — a small set of
   words, one of them in force — with one difference that comes from what it holds: each chip carries its count, and
   the count is what says whether choosing it can match anything (`DEC-067`). */
.filter-chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2xs);
  min-width: 0;
}

.filter-chips__chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  min-height: var(--button-height);
  padding: 0 var(--space-sm);
  border: var(--border-default);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  color: var(--color-text-muted);
  font-family: inherit;
  font-size: var(--font-size-sm);
  cursor: pointer;
  white-space: nowrap;
}

.filter-chips__chip:hover {
  background: var(--color-surface-muted);
  color: var(--color-text);
}

/* The chip in force. The state is the attribute assistive technology reads, so the drawing cannot disagree with the
   announcement. */
.filter-chips__chip[aria-pressed="true"] {
  background: var(--color-primary-soft);
  border-color: var(--color-primary-border);
  color: var(--color-primary-strong);
  font-weight: var(--font-weight-semibold);
}

.filter-chips__chip:focus-visible {
  outline: var(--focus-ring-width) solid var(--focus-ring-color);
  outline-offset: var(--focus-ring-offset);
}

.filter-chips__count {
  color: var(--color-text-subtle);
  font-variant-numeric: tabular-nums;
}

.filter-chips__chip[aria-pressed="true"] .filter-chips__count {
  color: var(--color-primary-strong);
}

/* On a touch layout the chip is a target of a finger, which is the same rule the button family follows. */
@media (max-width: 767px) {
  .filter-chips__chip {
    min-height: 44px;
  }
}