/* ==========================================================================
   ProjectManagementPro.ClientWASM — dialogs
   The dialog family: the layer that covers the page while a dialog is open, the backdrop a
   click closes it on, and the surface itself with its title, its note, the form it holds and
   the row of actions that ends it. Two screens of this delivery draw one — the creation of a
   project and the confirmation before deleting one:

     * Features/Projects/Components/CreateProjectDialog.razor
     * Features/Projects/Components/DeleteProjectDialog.razor

   It is a family of its own rather than a rule in layout.css or forms.css: a dialog is a
   surface that floats over the page and blocks it, which is neither a frame of the page nor a
   control of a form. The fields and the buttons inside it are the ones of forms.css and are
   used unchanged — nothing here re-draws an input.

   The geometry is the one the active client measured for its own modal and wrote down in its
   `components.css`: a layer that scrolls on its own, and a dialog centred by `margin: auto`
   so that a viewport too short for it reads the dialog from its title instead of starting in
   the middle of the form. The values are the tokens of tokens.css; the reasoning is reused and
   the file is not.
   ========================================================================== */

/* The layer covers the viewport and is the dialog's positioning context. It sits below the
   unhandled-error bar, the only other fixed layer of the client (base.css gives that one
   1000), so a failure is never hidden behind a dialog. */
.dialog-layer {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: var(--space-xl) var(--space-md);
  overflow-y: auto;
  overscroll-behavior: contain;
}

/* The backdrop is a sibling of the dialog and not its parent (see the markup), so a click
   inside the dialog cannot reach it. It is painted between the page and the surface; it
   carries no colour of its own beyond the scrim role `--color-overlay` declares. */
.dialog-backdrop {
  position: fixed;
  inset: 0;
  background: var(--color-overlay);
}

/* One column wide at most, so the form's fields stay readable and the dialog is never wider
   than the screen it is opened on. `position: relative` is what puts it above the fixed
   backdrop without a second stacking layer. */
.dialog {
  position: relative;
  width: 100%;
  max-width: 560px;
  /* Centred while it fits, pushed to the top of the layer's scroll when it does not. */
  margin: auto;
  padding: var(--space-lg);
  background: var(--color-surface);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
}

/* The dialog takes the caret when it opens (`tabindex="-1"`, focused by its own code) and it
   is the element that answers Escape. base.css draws the one focus ring for it and nothing
   here removes it. */
.dialog__title {
  margin: 0 0 var(--space-2xs);
}

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

/* The item a confirmation names, quoted above its own explanation. The constraints artefact has no
   name field, so the confirmation names the row by its definition text — free text that can be long —
   and this is what tells it apart from the sentence of the dialog: it is the value, not the wording. */
.dialog__quote {
  margin: 0 0 var(--space-sm);
  padding: var(--space-xs) var(--space-sm);
  background: var(--color-surface-muted);
  border-left: var(--border-width) solid var(--color-border-strong);
  border-radius: var(--radius-sm);
  font-size: var(--font-size-base);
  white-space: pre-line;
  overflow-wrap: anywhere;
}

/* The alert a failed submission draws — the server's own sentence — is separated from the form
   it precedes, the way the access panel separates its own. The distance belongs to the dialog
   because it is the dialog that stacks its children. */
.dialog__surface > .alert {
  margin-bottom: var(--space-md);
}

/* The title row: the name of the dialog and, when the artefact has one, the act that opens its help. It is a row of
   its own so the button sits at the far end and the name keeps the whole of the room it had. */
.dialog__heading {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-sm);
}

.dialog__help-toggle {
  flex: 0 0 auto;
  margin-left: auto;
}

/* **The dialog with its help beside it.** The surface stops being capped and becomes two columns: the form keeps
   exactly the width the caller named (`MaxWidth`, written in the same style attribute this class is read against) and
   the panel takes the rest, so the pair reaches further right and the form reads as moved to the left — the geometry
   the owner asked for on 2026-09-27. The two columns are separated by the hairline the product uses between panels. */
.dialog--with-help {
  display: grid;
  align-items: start;
  padding: 0;
}

.dialog--with-help .dialog__surface {
  min-width: 0;
  padding: var(--space-lg);
}

.dialog__help {
  min-width: 0;
  padding: var(--space-lg);
  border-left: var(--border-default);
}

/* What the panel holds is the caller's own writing: a stack of titled blocks that mirrors the fields of the form, so
   the reader goes down the panel in the same order they go down the dialog. */
.dialog__help-section + .dialog__help-section {
  margin-top: var(--space-md);
}

.dialog__help-term {
  margin: 0 0 var(--space-2xs);
  font-weight: var(--font-weight-semibold);
}

.dialog__help-text {
  margin: 0 0 var(--space-2xs);
  color: var(--color-text-muted);
  font-size: var(--font-size-sm);
}

.dialog__help-example {
  margin: 0;
  padding: var(--space-xs) var(--space-sm);
  background: var(--color-surface-muted);
  border-left: var(--border-width) solid var(--color-border-strong);
  border-radius: var(--radius-sm);
  font-size: var(--font-size-sm);
  overflow-wrap: anywhere;
}

/* The form of the dialog: one column, the shared rhythm between the fields and the action row
   under them — the same stack the access forms of layout.css declare for their own fields. */
.dialog__form {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}

.dialog__form--two-column {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  align-items: start;
}

.dialog__field--wide {
  grid-column: 1 / -1;
  min-width: 0;
}

/* **A row of three fields inside the two-column form**, declared once and used by every dialog that needs it.
   The owner asked for these rows on 2026-09-27 — the risk editor puts «Cause · Effect · Trigger» and
   «Probability · Impact · Strategy» in one line each, the HAZOP deviation puts «Causes · Consequences · Safeguards»
   in one, and the known risk puts its three lists in one — and the row is the same piece in all of them because a
   second copy of the same grid is what the product's own rule forbids.
   It spans both columns of the form and is itself a three-column grid, so the three fields are equal, they keep the
   `align-items: start` of their own row and the form's gap is the one between them. */
.dialog__form__row--three {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  align-items: start;
  gap: var(--space-md);
}

/* The same row with two fields: a dialog whose first line is one field alone — the node of a HAZOP deviation — puts the
   pair that follows in a row of its own, so the two are the two columns of the form and not one column and a half. */
.dialog__form__row--two {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  align-items: start;
  gap: var(--space-md);
}

/* The classes that drew a group of choices inside a dialog — `dialog__group`, `dialog__legend`, `dialog__choices`,
   `dialog__hint` and the four `dialog__new-choice*` ones — were deleted on 2026-09-25 with their last consumer: the
   background editor filed an entry under a **set** of categories with checkboxes and a field that created a new
   name, and `DEC-068` made the category one single-select field (`BackgroundCategoryField`, which carries its own
   styles in forms.css). A rule with no consumer is a rule the next person maintains for nothing. */

/* The end of the dialog: under the same hairline the other action rows of the client use, at
   the end of the row it closes. */
.dialog__actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: var(--space-sm);
  padding-top: var(--space-md);
  border-top: var(--border-default);
}

/* **The row that ends a dialog stays in view while the dialog is scrolled** (`DEC-063`). What scrolls when a dialog is
   taller than the window is the layer — the HAZOP deviation editor, the risk editor and a confirmation with a long
   cascade all overflow a laptop — so a save button that scrolled away asked the person to go looking for it. This is
   the same thing the rules for a narrow window already did, now said for every width; the surface behind the row is
   what keeps the content from passing under it. The row is still bounded by the dialog, so when the end of the dialog
   is on screen the row sits where it always sat. */
.dialog__actions,
.dialog-frame__actions {
  position: sticky;
  bottom: 0;
  z-index: 1;
  background: var(--color-surface);
}

/* While a dialog is open the page behind it does not scroll: the dialog owns the wheel, and a
   page that kept scrolling under a modal would move the screen the user returns to. The markup
   has no class to say "a dialog is open" — the layer itself is the only signal — so the rule
   asks for it with `:has`. It is a progressive enhancement on purpose: a browser without
   `:has` drops this one rule and the dialog still opens and closes. */
body:has(.dialog-layer) {
  overflow: hidden;
}

/* ==========================================================================
   The frame of an artefact dialog — Components/Dialogs/ArtifactDialogFrame.razor
   ========================================================================== */
/* The shape `DEC-040` fixes for the contents of an artefact dialog: its sections as tabs, the first
   one carrying the summary of the others, and the action row under all of them. These rules live in
   this sheet and not in a screen's, because the piece that draws the classes is shared: a screen
   composes the frame and declares nothing (ARTEFACT-SCREEN-TEMPLATE.md §0.8). */
.dialog-frame {
  display: flex;
  flex-direction: column;
}

/* The strip of tabs. It is one line the person reads across and it scrolls inside itself on a narrow
   window instead of pushing the dialog wider. */
.dialog-frame__tabs {
  display: flex;
  gap: var(--space-2xs);
  overflow-x: auto;
  overscroll-behavior-x: contain;
  border-bottom: var(--border-default);
}

.dialog-frame__tab {
  padding: var(--space-xs) var(--space-sm);
  border: 0;
  /* The transparent border keeps the tab's box the same height whether it is the one on show or
     not, so switching a tab never moves the line under it. */
  border-bottom: 2px solid transparent;
  background: transparent;
  color: var(--color-text-muted);
  font-family: inherit;
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  white-space: nowrap;
  cursor: pointer;
}

.dialog-frame__tab:hover {
  color: var(--color-text);
}

/* The tab on show, marked with the attribute assistive technology reads: `aria-selected="true"` is
   both the announcement and the underline, so the two cannot disagree. */
.dialog-frame__tab[aria-selected="true"] {
  border-bottom-color: var(--color-primary);
  color: var(--color-primary-strong);
}

/* One section. The panels are all mounted and the inactive ones carry the boolean `hidden`
   attribute, which the browser's own stylesheet turns into `display: none` — so this rule says
   nothing about visibility and cannot fight that decision. */
.dialog-frame__panel {
  padding-top: var(--space-md);
}

/* The rules of the «In this dialog» summary stood here — the block, its title, one line per section with the
   name, the sentence and the button that opened it — and they are gone with it: the owner asked for that block
   to be taken out of every creation and edition dialog of any artefact because it is not needed, so nothing
   draws `.dialog-frame__summary`, `__summary-title`, `__summary-line`, `__summary-name`, `__summary-text` or
   `__summary-open` any more. */

/* The row that ends the dialog, drawn outside the panels so it is reachable from every section. A
   dialog whose save button lived inside its first panel would ask the person to go back to it before
   they could keep what they wrote. */
.dialog-frame__actions {
  margin-top: var(--space-md);
}

/* The action row of a dialog carries the form class as well as its own, and it is not a leftover: the two values
   below are what makes it a row and not the column a form is, and the class is how the row that ends a dialog has
   been read since the first editor — the cases find the save as `.dialog__form button[type=submit]`, and the row is
   the element the save lives in whenever the fields have a form of their own. Every row of the client is
   `DialogActions`, so this is one spelling and not two. */
.dialog__form.dialog__actions {
  flex-direction: row;
  justify-content: flex-end;
  gap: var(--space-sm);
}

@media (max-width: 767px) {
  .dialog__form--two-column {
    grid-template-columns: minmax(0, 1fr);
  }

  /* A row of three fields stacks like every other row of the form: on a phone there is no room for three columns and
     the order of the fields is what has to be read, not their line. */
  .dialog__form__row--three,
  .dialog__form__row--two {
    grid-template-columns: minmax(0, 1fr);
  }

  /* The help of a dialog is read under it, never beside it: the two columns of the help layout are one, and the
     declaration is `!important` because the columns of that layout travel in the style attribute of the dialog —
     the caller's own measurement — and a sheet cannot outrank an inline style without saying so. */
  .dialog--with-help {
    grid-template-columns: minmax(0, 1fr) !important;
    padding: 0;
  }

  .dialog__help {
    border-top: var(--border-default);
    border-left: 0;
  }

  .dialog__field--wide {
    grid-column: auto;
  }
  .dialog-layer {
    padding: 0;
  }

  .dialog {
    min-height: 100dvh;
    max-height: none;
    padding: var(--space-md);
    border-radius: 0;
  }

  /* The row is already sticky at every width (see `DEC-063`); on a phone it also keeps the gesture bar of the
     device away from the buttons. */
  .dialog__actions,
  .dialog-frame__actions {
    padding-bottom: max(var(--space-sm), env(safe-area-inset-bottom));
  }
}
