/* ============================================================================
   DREAMWEB — Design System components
   Source of truth: Figma "DM Web -  Design System" → 02 - Components
   Every value below resolves to a Foundations token. Do not introduce new
   colours, type styles, spacing, radii or states in this file.
   ========================================================================== */

*, *::before, *::after { box-sizing: border-box; }

html, body { height: 100%; }

body {
  margin: 0;
  font-family: var(--font-family);
  font-size: var(--body-medium-size);
  line-height: var(--body-medium-line);
  color: var(--text-primary);
  background: var(--background-primary);
  -webkit-font-smoothing: antialiased;
}

button, input, select, textarea { font: inherit; color: inherit; }

.dw-icon { width: 24px; height: 24px; display: block; flex: none; }
.dw-icon--16 { width: 16px; height: 16px; }
.dw-icon--20 { width: 20px; height: 20px; }
/* Glyphs whose exported artboard is not square — sized to their real
   dimensions so the exported vector is never stretched. */
.dw-icon--16x15  { width: 16px; height: 15px; }
.dw-icon--camera { width: 16px; height: 12px; }
.dw-icon--trash  { width: 14px; height: 16px; }

/* Icon/UI/x frames in Figma are 24x24 boxes holding a 16 or 20 px glyph. */
.dw-icon-box {
  width: 24px; height: 24px; flex: none;
  display: flex; align-items: center; justify-content: center;
}
.dw-icon-box--20 { width: 20px; height: 20px; }

.dw-sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ---------------------------------------------------------------------------
   Header (mobile) — Header, Type=Default
   ------------------------------------------------------------------------- */
.dw-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 64px;
  padding: var(--spacing-16) var(--spacing-20);
  background: var(--background-primary);
  border-bottom: 1px solid var(--border-subtle);
  flex: none;
}

/* ---------------------------------------------------------------------------
   LogoDREAMWeb — official brand asset, composed exactly as in Figma.
   Never reconstruct the logo with text or CSS.
   ------------------------------------------------------------------------- */
.dw-logo {
  position: relative;
  display: block;
  width: 120px;
  aspect-ratio: 120 / 22.403;
  flex: none;
}
/* Both marks are placed with the exact percentages the component uses in
   Figma. Replaced elements ignore right/bottom once a width is set, so the
   rectangles are expressed as top/left plus width/height. */
.dw-logo img { position: absolute; display: block; }
.dw-logo .dw-logo__wordmark {
  top: 0; left: 0;
  width: 100%;      /* inset right 0    */
  height: 60.18%;   /* inset bottom 39.82% */
}
.dw-logo .dw-logo__dreammedia {
  top: 81.58%; left: 64.97%;
  width: 35.03%;    /* inset right 0  */
  height: 18.42%;   /* inset bottom 0 */
}
.dw-logo--sidebar { width: 144px; }

/* ---------------------------------------------------------------------------
   Button — State: Default | Hover | Pressed | Focus | Disabled
            Type:  Primary | Secondary
   ------------------------------------------------------------------------- */
.dw-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--spacing-08);
  height: var(--field-height);
  padding: var(--spacing-12) var(--spacing-20);
  border: 0;
  border-radius: var(--radius-small);
  font-size: var(--label-large-size);
  line-height: var(--label-large-line);
  font-weight: var(--label-large-weight);
  cursor: pointer;
  transition: background-color 120ms linear, border-color 120ms linear;
}

.dw-button--primary { background: var(--action-primary); color: var(--text-onbrand); }
.dw-button--primary:hover:not(:disabled)  { background: var(--action-primary-hover); }
.dw-button--primary:active:not(:disabled) { background: var(--action-primary-pressed); }
.dw-button--primary:focus-visible {
  outline: none;
  box-shadow: inset 0 0 0 2px var(--neutral-950);
}

/* Compacto — para linhas de lista, onde um botão de 48px de altura come a
   linha inteira e faz três acções parecerem três formulários.

   Mede 36px e é o mesmo botão em tudo o resto: mesmas cores, mesma borda,
   mesmos estados. Não é um botão novo, é o mesmo mais apertado — por isso é
   modificador e não classe própria. Só se usa onde a acção é secundária e
   vive dentro de uma linha; um botão de submissão continua a ter 48px, que é
   o alvo de toque que o Design System fixa. */
.dw-button--compacto {
  height: 36px;
  padding: var(--spacing-04) var(--spacing-12);
  font-size: var(--body-small-size);
  line-height: var(--body-small-line);
}

.dw-button--secondary {
  background: transparent;
  color: var(--text-primary);
  border: 1px solid var(--border-default);
}
.dw-button--secondary:hover:not(:disabled),
.dw-button--secondary:active:not(:disabled) { background: var(--surface-secondary); }
.dw-button--secondary:focus-visible {
  outline: none;
  border-width: 2px;
  border-color: var(--border-default);
}

.dw-button--primary:disabled {
  background: var(--surface-secondary);
  border: 1px solid var(--border-subtle);
  color: var(--text-disabled);
  cursor: not-allowed;
}
.dw-button--secondary:disabled {
  background: var(--action-disabled);
  border-color: transparent;
  color: var(--text-disabled);
  cursor: not-allowed;
}

.dw-button--block { width: 100%; }

/* ---------------------------------------------------------------------------
   Shared field scaffolding.
   Field / Select Field / Location Field / Photo Upload all compose as
   label -> control -> (helper).
   ------------------------------------------------------------------------- */
.dw-field {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-08);
  width: 100%;
}

.dw-field__helper {
  font-size: var(--caption-size);
  line-height: var(--caption-line);
  font-weight: var(--caption-weight);
  color: var(--text-secondary);
  margin: 0;
}

.dw-field__control {
  display: flex;
  align-items: center;
  width: 100%;
  height: var(--field-height);
  padding: var(--spacing-12) var(--spacing-16);
  background: var(--field-surface);
  border: 1px solid var(--field-border);
  backdrop-filter: blur(var(--field-blur));
  -webkit-backdrop-filter: blur(var(--field-blur));
  color: var(--text-primary);
  transition: border-color 120ms linear;
}

/* ---------------------------------------------------------------------------
   A ETIQUETA DE UM CAMPO — uma só, para todos os tipos de campo.

   Cada componente do Figma traz a sua: o Text Field diz Body/Medium, o Select
   Field diz Label/Medium, o Location Field e o Photo Upload dizem Label/Large.
   Seguidas à letra, dão três tamanhos diferentes no mesmo formulário — porque
   no Figma estes componentes aparecem cada um no seu frame, e nunca empilhados
   num ecrã real.

   Medido na Verificação de faces a 25/09/2026, que tem os três:

       Estado da face    12px / 600     (Select)
       Fotografias       14px / 600     (Photo)
       Observações       14px / 400     (Text)

   Três tamanhos para a mesma coisa — o nome do campo que está por baixo. Quem
   preenche lê isso como um erro de composição, e é.

   Fica Body/Medium, que é a do Text Field. A DIVERGÊNCIA DOS COMPONENTES DO
   FIGMA É DELIBERADA e está registada em DECISOES.md (25/09/2026): uma
   sincronização com o design não a deve desfazer sem tratar da causa, que é os
   componentes não concordarem entre si.

   O tipo de campo muda o CONTROLO — a altura, o raio, o que se carrega. Não
   muda o que a etiqueta é.
   ------------------------------------------------------------------------- */
.dw-field__label {
  font-size: var(--body-medium-size);
  line-height: var(--body-medium-line);
  font-weight: var(--body-medium-weight);
  color: var(--text-primary);
  margin: 0;
}

/* ---------------------------------------------------------------------------
   Field — Type=Text, State: Default | Focus | Filled | Error | Disabled
   Control radius = Radius/Medium. A etiqueta é a de cima.
   ------------------------------------------------------------------------- */

.dw-input__control {
  gap: var(--spacing-08);
  border-radius: var(--radius-medium);
}

.dw-input__control input {
  flex: 1 0 0;
  min-width: 0;
  border: 0;
  background: transparent;
  outline: none;
  font-size: var(--body-medium-size);
  line-height: var(--body-medium-line);
  font-weight: var(--body-medium-weight);
  color: var(--text-primary);
}
.dw-input__control input::placeholder { color: var(--text-secondary); }

.dw-input__control:focus-within { border-color: var(--action-primary); }

.dw-input.is-error .dw-input__control { border-color: var(--feedback-error); }

.dw-input.is-disabled .dw-field__label { color: var(--text-disabled); }
.dw-input.is-disabled .dw-input__control {
  background: var(--surface-secondary);
  border-color: var(--border-subtle);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
.dw-input.is-disabled .dw-input__control input,
.dw-input.is-disabled .dw-input__control input::placeholder { color: var(--text-disabled); }

/* ---------------------------------------------------------------------------
   Field — multi-line. The Field component with a taller control, used by the
   free-text fields (Observações). Same surface, border, radius and states.
   ------------------------------------------------------------------------- */
.dw-textarea__control {
  height: auto;
  align-items: stretch;
}

.dw-textarea__control textarea {
  flex: 1 0 0;
  min-width: 0;
  min-height: calc(var(--body-medium-line) * 4);
  resize: vertical;
  border: 0;
  background: transparent;
  outline: none;
  font-family: inherit;
  font-size: var(--body-medium-size);
  line-height: var(--body-medium-line);
  font-weight: var(--body-medium-weight);
  color: var(--text-primary);
}
.dw-textarea__control textarea::placeholder { color: var(--text-secondary); }

/* Unit suffix — Body/Medium, secondary. Used by the dimension fields. */
.dw-input__suffix {
  flex: none;
  font-size: var(--body-medium-size);
  line-height: var(--body-medium-line);
  color: var(--text-secondary);
}

/* ---------------------------------------------------------------------------
   Select Field — State: Default | Focus | Selected | Error | Disabled
   Control radius = Radius/Small. A etiqueta é a partilhada, acima.
   ------------------------------------------------------------------------- */
.dw-select__control {
  position: relative;
  justify-content: space-between;
  border-radius: var(--radius-small);
}

.dw-select__control select {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  border: 0;
  cursor: pointer;
}

.dw-select__value {
  font-size: var(--body-medium-size);
  line-height: var(--body-medium-line);
  color: var(--text-secondary);
  margin: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Icon/UI/Chevron is rotated 90deg to point down, exactly as in Figma. */
.dw-select__chevron { transform: rotate(90deg); color: var(--icon-secondary); }

.dw-select.is-selected .dw-select__value { color: var(--text-primary); }

.dw-select__control:focus-within { border-color: var(--action-primary); }

.dw-select.is-error .dw-select__control { border-color: var(--feedback-error); }

.dw-select.is-disabled .dw-field__label { color: var(--text-secondary); }
.dw-select.is-disabled .dw-select__control {
  background: var(--surface-secondary);
  border-color: var(--border-subtle);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
.dw-select.is-disabled .dw-select__value { color: var(--text-disabled); }
.dw-select.is-disabled .dw-select__chevron { color: var(--text-disabled); }
.dw-select.is-disabled .dw-select__control select { cursor: not-allowed; }

/* ---------------------------------------------------------------------------
   Location Field — State: Default | Detected
   Control height 56, gap 12, no vertical padding. A etiqueta é a partilhada.
   ------------------------------------------------------------------------- */
.dw-location__control {
  gap: var(--spacing-12);
  height: 56px;
  padding: 0 var(--spacing-16);
  border-radius: var(--radius-small);
  text-align: left;
  cursor: pointer;
}
.dw-location__control:hover { border-color: var(--border-default); }
.dw-location__control:focus-visible { outline: none; border-color: var(--action-primary); }

.dw-location__pin { color: var(--icon-secondary); }

.dw-location__content {
  display: flex;
  flex-direction: column;
  gap: 2px;
  flex: 1 0 0;
  min-width: 0;
}
.dw-location__primary {
  font-size: var(--body-medium-size);
  line-height: var(--body-medium-line);
  color: var(--text-primary);
  margin: 0;
}
.dw-location__secondary {
  font-size: var(--caption-size);
  line-height: var(--caption-line);
  font-weight: var(--caption-weight);
  color: var(--text-secondary);
  margin: 0;
}
.dw-location__chevron { color: var(--icon-secondary); }

.dw-location.is-error .dw-location__control { border-color: var(--feedback-error); }

/* ---------------------------------------------------------------------------
   Photo Upload — State: Default | Added
   O helper usa Caption. A etiqueta é a partilhada, acima.
   ------------------------------------------------------------------------- */
.dw-photo__control {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--spacing-12);
  width: 100%;
  background: var(--field-surface);
  border: 1px solid var(--field-border);
  backdrop-filter: blur(var(--field-blur));
  -webkit-backdrop-filter: blur(var(--field-blur));
  border-radius: var(--radius-small);
  transition: border-color 120ms linear;
}
.dw-photo__control:focus-within { border-color: var(--action-primary); }

/* State=Default */
.dw-photo__dropzone {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--spacing-12);
  width: 100%;
  height: 96px;
  padding: 0 var(--spacing-16);
  background: transparent;
  border: 0;
  cursor: pointer;
  color: var(--text-primary);
}
.dw-photo__dropzone:focus-visible { outline: none; }
.dw-photo__camera { color: var(--action-primary); }
.dw-photo__cta {
  font-size: var(--body-medium-size);
  line-height: var(--body-medium-line);
  color: var(--text-primary);
  text-align: center;
  margin: 0;
}

/* State=Added */
.dw-photo__preview {
  position: relative;
  width: 100%;
  height: 160px;
  border-radius: var(--radius-small);
  overflow: hidden;
}
.dw-photo__preview img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.dw-photo__divider {
  width: 100%;
  height: 1px;
  background: var(--field-divider);
  flex: none;
}
.dw-photo__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--spacing-12);
  width: 100%;
  height: 44px;
  padding: 0 var(--spacing-16);
}
.dw-photo__row-label {
  font-size: var(--body-medium-size);
  line-height: var(--body-medium-line);
  color: var(--text-primary);
  margin: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.dw-photo__action {
  display: flex;
  align-items: center;
  gap: var(--spacing-08);
  background: transparent;
  border: 0;
  padding: 0;
  cursor: pointer;
  font-size: var(--body-medium-size);
  line-height: var(--body-medium-line);
  color: var(--text-primary);
}
.dw-photo__trash { color: var(--icon-secondary); }
.dw-photo__action:hover .dw-photo__trash { color: var(--text-primary); }

.dw-photo.is-error .dw-photo__control { border-color: var(--feedback-error); }

/* ---------------------------------------------------------------------------
   Search Bar — State: Default | Focus | Filled | Disabled
   Radius/Large. Desktop only on this page, per Desktop Guidelines.
   ------------------------------------------------------------------------- */
.dw-searchbar {
  display: flex;
  align-items: center;
  gap: var(--spacing-12);
  width: 100%;
  padding: var(--spacing-12) var(--spacing-16);
  background: var(--field-surface);
  border: 1px solid var(--field-border);
  backdrop-filter: blur(var(--field-blur));
  -webkit-backdrop-filter: blur(var(--field-blur));
  border-radius: var(--radius-large);
}
.dw-searchbar:focus-within { border-color: var(--action-primary); }

/* A barra passou a levar a páginas, e os resultados caem por baixo dela.

   `position: relative` na barra e `absolute` na lista: a lista tem de sair do
   fluxo, senão empurrava os cartões da Home para baixo a cada tecla — o
   conteúdo a saltar enquanto se escreve é pior do que não haver pesquisa.

   O `z-index` fica acima da barra de navegação inferior (5), que é o único
   elemento com quem a lista se pode cruzar num ecrã baixo. */
/* `z-index` AQUI, e nao so no painel. A barra tem `backdrop-filter`, e um
   elemento com backdrop-filter cria um contexto de empilhamento: o z-index do
   painel era resolvido dentro da barra e nunca chegava a competir com o resto
   da pagina. O `.dw-metadata` (SEMANA / AMBITO), que tambem tem
   backdrop-filter e vem depois no DOM, era pintado por cima e tapava o titulo
   do primeiro resultado. Subindo a barra inteira, o painel sobe com ela. */
.dw-searchbar { position: relative; z-index: 20; }
.dw-searchbar__resultados {
  position: absolute;
  top: calc(100% + var(--spacing-08));
  left: 0;
  right: 0;
  /* Dentro do contexto da barra, portanto 1 chega. */
  z-index: 1;
  max-height: 320px;
  overflow-y: auto;
  padding: var(--spacing-08);
  /* Opaco, e nao `--card-surface`. Esse e rgba(17,17,17,0.45): serve um cartao
     assente no fundo, mas aqui a lista tapa conteudo, e a 45% a linha
     SEMANA/AMBITO atravessava as linhas de resultado ate ficarem ilegiveis.
     Uma camada que cobre outra coisa nao pode ser translucida. */
  background: var(--surface-primary);
  border: 1px solid var(--card-border);
  border-radius: var(--radius-medium);
  box-shadow: var(--card-shadow);
}

/* A linha sob as setas do teclado marca-se como a que o rato aponta: quem
   navega sem rato tem de ver onde está antes de carregar em Enter. */
.dw-searchbar__resultados .dw-record.is-activo {
  background: var(--neutral-900);
  border-color: var(--action-primary);
}
.dw-searchbar__icon { color: var(--icon-secondary); }

/* A contagem da barra de filtro: "3 de 12". Encostada a direita, dentro da
   propria barra -- e sobre o que ali esta, e nao um aviso da pagina.
   `flex: none` e `nowrap` para a contagem nunca ser o que encolhe: quem
   encolhe e o campo de texto, que tem de sobra. */
.dw-searchbar__estado {
  flex: none;
  margin: 0;
  white-space: nowrap;
  font-size: var(--caption-size);
  line-height: var(--caption-line);
  color: var(--text-secondary);
}
/* Zero resultados nao e um erro -- e uma resposta -- mas tem de se notar,
   senao quem filtrou fica a olhar para uma lista vazia sem perceber porque. */
.dw-searchbar__estado.is-vazio { color: var(--action-primary); }
.dw-searchbar input {
  flex: 1 0 0;
  min-width: 0;
  border: 0;
  background: transparent;
  outline: none;
  font-size: var(--body-medium-size);
  line-height: var(--body-medium-line);
  color: var(--text-primary);
}
.dw-searchbar input::placeholder { color: var(--text-secondary); }

/* ---------------------------------------------------------------------------
   Page Header — title matches the active primary module.
   ------------------------------------------------------------------------- */
.dw-page-header { display: flex; flex-direction: column; width: 100%; }
/* O caminho de volta, por cima do título. Mesma métrica e mesma cor do
   `dw-hero__back` do telemóvel: é a mesma coisa, no sítio que cada ecrã tem
   para ela. `align-self: flex-start` para a área de clique acabar no fim do
   texto — a largura toda faria uma faixa clicável ao longo da página. */
.dw-page-header__back {
  display: flex;
  align-items: center;
  align-self: flex-start;
  gap: var(--spacing-04);
  padding: 0;
  margin-bottom: var(--spacing-08);
  background: transparent;
  border: 0;
  cursor: pointer;
  text-decoration: none;
  font-size: var(--label-medium-size);
  line-height: var(--label-medium-line);
  font-weight: var(--label-medium-weight);
  color: var(--text-secondary);
}
.dw-page-header__back:hover { color: var(--neutral-white); }
/* Chevron rodado 180°, como no cabeçalho do telemóvel. */
.dw-page-header__back-icon { transform: rotate(180deg); color: var(--icon-secondary); }
/* O título e o que o ecrã está a mostrar, na mesma linha. Quebra em duas
   quando não couber, para um código longo não empurrar nada para fora. */
.dw-page-header__linha {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--spacing-12);
}
.dw-page-header__title {
  font-size: var(--heading-h2-size);
  line-height: var(--heading-h2-line);
  font-weight: var(--heading-h2-weight);
  color: var(--neutral-white);
  margin: 0;
}
/* Pela linha de base do título e não pelo topo: são dois tamanhos diferentes
   e alinhados pelo topo o menor ficaria a flutuar. A cor de marca separa-o do
   nome do módulo sem precisar de um traço entre os dois. */
.dw-page-header__extra {
  font-size: var(--heading-h3-size, var(--body-large-size));
  line-height: var(--heading-h3-line, var(--body-large-line));
  font-weight: var(--label-large-weight);
  color: var(--action-primary);
}

/* ---------------------------------------------------------------------------
   Sidebar + Sidebar Item — desktop primary navigation
   ------------------------------------------------------------------------- */
.dw-sidebar {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-08);
  width: var(--layout-desktop-sidebar-width);
  height: 100%;
  padding: var(--spacing-24);
  background: var(--neutral-950);
  flex: none;
}
.dw-sidebar__brand {
  display: flex;
  align-items: center;
  padding-bottom: var(--spacing-32);
  width: 100%;
}
.dw-sidebar__nav,
.dw-sidebar__account {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-08);
  width: 100%;
}
.dw-sidebar__spacer { flex: 1 0 0; min-height: 0; }

.dw-sidebar-item {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--spacing-12);
  width: 192px;
  padding: 10px var(--spacing-12);
  background: transparent;
  border: 0;
  text-align: left;
  text-decoration: none;
  cursor: pointer;
  font-size: var(--label-large-size);
  line-height: var(--label-large-line);
  font-weight: var(--label-large-weight);
  color: var(--neutral-400);
}
.dw-sidebar-item__icon { color: currentColor; }
.dw-sidebar-item:hover,
.dw-sidebar-item:focus-visible {
  background: var(--neutral-900);
  color: var(--neutral-white);
  outline: none;
}
.dw-sidebar-item.is-active { color: var(--neutral-white); }
.dw-sidebar-item.is-active::before {
  content: "";
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 3px;
  height: 40px;
  background: var(--brand-orange-500);
}

/* ---------------------------------------------------------------------------
   Submodule Navigation + Submodule Tab — desktop secondary navigation
   State: Default | Hover | Active
   ------------------------------------------------------------------------- */
.dw-submodule-nav {
  display: flex;
  align-items: flex-end;
  width: 100%;
  height: 48px;
  border-bottom: 1px solid var(--neutral-700);
  overflow-x: auto;
  scrollbar-width: none;
}
.dw-submodule-nav::-webkit-scrollbar { display: none; }

.dw-submodule-tab {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  height: 48px;
  padding: 0 var(--spacing-20);
  background: transparent;
  border: 0;
  cursor: pointer;
  white-space: nowrap;
  text-decoration: none;
  font-size: var(--label-large-size);
  line-height: var(--label-large-line);
  font-weight: var(--label-large-weight);
  color: var(--neutral-500);
}
.dw-submodule-tab > span { margin: auto 0; }
.dw-submodule-tab:hover,
.dw-submodule-tab:focus-visible { background: var(--neutral-900); outline: none; }
.dw-submodule-tab.is-active { color: var(--neutral-white); }
.dw-submodule-tab.is-active > span { margin-bottom: 10px; }
.dw-submodule-tab.is-active::after {
  content: "";
  width: 100%;
  height: 3px;
  background: var(--brand-orange-500);
}

/* ---------------------------------------------------------------------------
   Bottom Navigation + Nav item — mobile primary navigation
   Component: height 72, padding 8 vertical, items 55 tall.
   ------------------------------------------------------------------------- */
.dw-bottom-nav {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  /* Colada ao fundo do que se vê, e não ao fundo do documento. Era `static`, e
     numa janela baixa — um dobrável aberto, um telemóvel deitado — ficava
     centenas de pixels abaixo da dobra: a 740x312 o documento tem 794px de
     altura e a barra começava aos 722, fora de alcance sem rolar tudo.

     `sticky` e não `fixed`: o elemento continua a ocupar o seu lugar no fim do
     fluxo, portanto o último cartão não fica preso por baixo dela quando se
     chega ao fim. Com `fixed` era preciso compensar com padding no conteúdo, e
     esse padding é sempre errado em algum ecrã.

     O `backdrop-filter` abaixo já pressupunha isto: um desfoque do que está
     por trás só faz sentido se houver conteúdo a passar por baixo. */
  position: sticky;
  bottom: 0;
  z-index: 5;
  height: 72px;
  padding: var(--spacing-08) 0;
  padding-bottom: calc(var(--spacing-08) + env(safe-area-inset-bottom, 0px));
  background: var(--bottomnav-surface);
  border-top: 1px solid var(--bottomnav-border);
  backdrop-filter: blur(var(--bottomnav-blur));
  -webkit-backdrop-filter: blur(var(--bottomnav-blur));
  flex: none;
}
.dw-nav-item {
  display: flex;
  flex: 1 0 0;
  min-width: 0;
  flex-direction: column;
  align-items: center;
  gap: var(--spacing-04);
  height: 55px;
  background: transparent;
  border: 0;
  cursor: pointer;
  text-decoration: none;
  font-size: var(--caption-size);
  line-height: var(--caption-line);
  font-weight: var(--caption-weight);
  color: var(--text-secondary);
}
.dw-nav-item.is-active { color: var(--action-primary); }
.dw-nav-item__icon { color: currentColor; }

/* ---------------------------------------------------------------------------
   Module Card — mobile Home module grid. State: Default | Selected
   Selected marks the primary module whose submodules are expanded inline.
   ------------------------------------------------------------------------- */
.dw-module-card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  /* Figma sizes the card 169x128 on a 390px frame, where two cards plus the
     12 gap and the 20 page padding come to exactly 390.

     A largura deixou de estar aqui. Quem a decide é a faixa da grelha em
     `.dw-module-rows`, que a 390px dá exatamente os 169 do Figma e acima
     disso acrescenta colunas. O `max-width: 169px` que aqui esteve era um
     teto absoluto: mantinha o cartão nos 169 por muito espaço que houvesse, e
     a 1023px os seis amontoavam-se em 350px com 633 de vazio ao lado.

     `min-width: 0` fica: sem ele uma descrição longa impede a faixa de
     encolher e a grelha transborda em ecrãs estreitos.

     A altura continua a ser um piso e não um valor fixo, porque o cartão
     cresce com o que o título e a descrição ocupam. Desde 30/09/2026 os seis
     desenham-se para a MESMA mancha — títulos de uma linha (o quadrado do
     módulo 2 lê "Parque", ver `tituloDoCartao` nos MODULOS) e descrições de
     duas (os textos andam a par, ver a nota nos MODULOS; o `__desc` reserva
     as duas linhas em baixo) — mas o piso fica: um texto que cresça num ecrã
     mais estreito continua a caber em vez de ser cortado.
     Cards in a row stretch to match, so a row still reads as one band. */
  min-width: 0;
  min-height: 128px;
  padding: var(--spacing-16);
  background: var(--card-surface);
  border: 1px solid var(--card-border);
  backdrop-filter: blur(var(--card-blur));
  -webkit-backdrop-filter: blur(var(--card-blur));
  border-radius: var(--radius-medium);
  box-shadow: var(--card-shadow);
  text-align: left;
  text-decoration: none;
  transition: background-color 120ms linear, border-color 120ms linear;
}
.dw-module-card--interactive { cursor: pointer; }
.dw-module-card--interactive:hover,
.dw-module-card--interactive:focus-visible {
  border-color: var(--action-primary);
  outline: none;
}
.dw-module-card.is-selected {
  background: var(--card-surface-selected);
  border-color: var(--action-primary);
}
.dw-module-card__body {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--spacing-12);
  min-height: 96px;
  flex: 1 0 auto;
  width: 100%;
}
.dw-module-card__icon { color: var(--action-primary); }
.dw-module-card__text {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--spacing-08);
}
.dw-module-card__title {
  font-size: var(--label-large-size);
  line-height: var(--label-large-line);
  font-weight: var(--label-large-weight);
  color: var(--text-primary);
  margin: 0;
}
.dw-module-card__desc {
  font-size: var(--body-small-size);
  line-height: var(--body-small-line);
  font-weight: var(--body-small-weight);
  color: var(--text-secondary);
  margin: 0;
  /* As duas linhas da descrição ficam reservadas mesmo onde o texto couber
     numa (colunas largas do desktop): é o que mantém a mancha dos seis
     cartões igual em qualquer largura, e não só na do telemóvel. */
  min-height: calc(var(--body-small-line) * 2);
}

/* --- um cartão com acção própria (28/09/2026) ------------------------------ *

   O cartão da Verificação de parque leva um "Exportar" no canto. Como um
   <button> dentro de outro <button> é HTML inválido, o cartão passa a ser um
   contentor e o botão grande vai lá para dentro -- ver `moduleCard`. Estas
   regras devolvem-lhe o aspecto que tinha: o botão interior não traz moldura
   nem fundo nenhum, e ocupa o cartão inteiro.

   Só se aplicam ao cartão que tem acção; os outros continuam a ser o
   <button> que sempre foram.                                              */
.dw-module-card--com-acao { position: relative; }
.dw-module-card__principal {
  display: flex;
  flex: 1 0 auto;
  width: 100%;
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.dw-module-card__principal:focus-visible { outline: none; }
/* A descrição passa por baixo do botão do canto; sem esta folga a linha mais
   comprida ia parar debaixo dele. */
.dw-module-card--com-acao .dw-module-card__text { padding-right: var(--spacing-04); }
.dw-module-card__acao {
  position: absolute;
  top: var(--spacing-08);
  right: var(--spacing-08);
  padding: var(--spacing-04) var(--spacing-08);
  border: 1px solid var(--card-border);
  border-radius: var(--radius-small);
  background: var(--card-surface);
  color: var(--text-secondary);
  font-size: var(--body-small-size);
  line-height: var(--body-small-line);
  font-weight: var(--label-large-weight);
  cursor: pointer;
  transition: color 120ms linear, border-color 120ms linear;
}
.dw-module-card__acao:hover,
.dw-module-card__acao:focus-visible {
  color: var(--text-primary);
  border-color: var(--action-primary);
  outline: none;
}
.dw-module-card__acao[aria-expanded="true"] {
  color: var(--text-primary);
  border-color: var(--action-primary);
}

/* O painel do export, por baixo do cartão que o abriu e a ocupar a linha
   toda -- como a lista de submódulos. */
.dw-export {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-12);
  width: 100%;
  padding: var(--spacing-16);
  background: var(--list-surface);
  border: 1px solid var(--list-border);
  border-radius: var(--radius-small);
  backdrop-filter: blur(var(--field-blur));
  -webkit-backdrop-filter: blur(var(--field-blur));
}
/* O botão que abre o painel, quando vive num ecrã de lista e não num cartão
   (29/09/2026): a zona de filtros é uma coluna esticada, e um botão
   secundário de ponta a ponta lia-se como submissão do que está por cima.
   Encosta-se à esquerda e fica do tamanho do seu texto. */
.dw-export-abrir { align-self: flex-start; }

/* Duas datas lado a lado enquanto couberem: são campos curtos, e uma por
   linha dava um painel alto de mais num telemóvel. */
.dw-export__datas {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: var(--spacing-12);
}

/* ---------------------------------------------------------------------------
   Modules / Metadata — operation week and status strip.
   ------------------------------------------------------------------------- */
.dw-metadata {
  display: flex;
  align-items: stretch;
  gap: var(--spacing-24);
  padding: var(--spacing-08) 0;
  border-radius: var(--radius-small);
  backdrop-filter: blur(var(--field-blur));
  -webkit-backdrop-filter: blur(var(--field-blur));
}
.dw-metadata__group {
  display: flex;
  align-items: center;
  gap: 6px;
  white-space: nowrap;
}
.dw-metadata__key {
  font-size: var(--overline-size);
  line-height: var(--overline-line);
  font-weight: var(--overline-weight);
  letter-spacing: var(--overline-tracking);
  text-transform: uppercase;
  color: var(--text-secondary);
  margin: 0;
}
.dw-metadata__value {
  font-size: var(--label-medium-size);
  line-height: var(--label-medium-line);
  font-weight: var(--label-medium-weight);
  color: var(--text-primary);
  margin: 0;
}
.dw-metadata__divider {
  width: 1px;
  align-self: stretch;
  background: var(--metadata-divider);
  flex: none;
}
.dw-metadata__dot {
  width: 8px;
  height: 8px;
  flex: none;
  border-radius: var(--radius-full);
  background: var(--action-primary);
}

/* ---------------------------------------------------------------------------
   Submodule List + Submodule List Item — mobile secondary navigation.
   Never used on desktop.
   ------------------------------------------------------------------------- */
.dw-submodule-list {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  width: 100%;
  background: var(--list-surface);
  border: 1px solid var(--list-border);
  border-radius: var(--radius-small);
  backdrop-filter: blur(var(--field-blur));
  -webkit-backdrop-filter: blur(var(--field-blur));
  overflow: hidden;
}
.dw-submodule-list-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  height: 52px;
  padding: 14px var(--spacing-16);
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--list-border);
  cursor: pointer;
  text-align: left;
  text-decoration: none;
  font-size: var(--body-medium-size);
  line-height: var(--body-medium-line);
  color: var(--text-primary);
}
.dw-submodule-list-item:last-child { border-bottom: 0; }
.dw-submodule-list-item:hover,
.dw-submodule-list-item:focus-visible { background: var(--neutral-900); outline: none; }
.dw-submodule-list-item__chevron { color: var(--icon-secondary); }

/* ---------------------------------------------------------------------------
   Face Selector — State: Empty | Selected
   ------------------------------------------------------------------------- */
.dw-face-selector {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--spacing-16);
  width: 100%;
  max-width: 350px;
  padding: 0 var(--spacing-16);
}
/* Dentro do formulário, sem o recuo próprio.

   Os 16px acima são o que o componente precisa quando está sozinho no topo do
   ecrã, fora do `.dw-form`. Ancorado entre campos (Ilegalidades, 15/09/2026)
   somam-se aos 16px que o `.dw-form` já dá a todos os campos, e o seletor
   ficava 16px mais à direita do que tudo o resto. Modificador e não alteração
   da regra base: no topo continua a precisar deles. */
.dw-face-selector--em-formulario { padding-left: 0; padding-right: 0; }

/* O bloco da face: o seletor e o que o ecrã mostre SOBRE a face escolhida.

   Nasceu a 29/09/2026, quando a Verificação de Faces passou a mostrar o
   retrato da face debaixo do seletor. É um nó só de propósito: a face muda
   por substituição do nó inteiro, e separados o retrato da face anterior
   ficava no ecrã por baixo do seletor da nova.

   `:not(:empty)` porque duas em cada três faces não têm retrato no arquivo do
   ERP. Sem ele a zona fica vazia, e uma zona vazia não pode deixar um buraco
   de 24px entre o seletor e o primeiro campo do formulário. */
.dw-face-bloco {
  display: flex;
  flex-direction: column;
  width: 100%;
}
.dw-face-extra:not(:empty) {
  padding: 0 var(--spacing-16);
  margin-top: var(--spacing-24);
}
/* O retrato da face — o mesmo bloco na Verificação de Faces e na de
   Campanhas, e por isso a medida vive NELE e não no sítio onde calha estar.

   Presa a `.dw-face-extra`, a regra não alcançava o ecrã das Campanhas — ali
   o bloco vive noutro contentor —, e a mesma fotografia saía a 318px num
   ecrã e a 220px no outro, com um vazio à direita.

   Uma fotografia só não precisa da grelha de uma galeria: esticada à largura
   de um ecrã grande ficava com 4/3 dessa largura de altura e empurrava o
   formulário inteiro para fora da vista. */
.dw-retrato-da-face .dw-gallery { grid-template-columns: minmax(0, 320px); }

/* As tipologias do filtro de reports (30/09/2026): CHIPS, desde o mesmo dia
   à noite — "coloca algo mais bonito e intuitivo". Eram treze caixas de
   visto em grelha, e treze quadradinhos leem-se como um formulário de
   recenseamento. Um chip é um alvo do tamanho de um dedo, o estado vê-se à
   cor sem procurar o visto, e o "Todas" à cabeça diz o estado por omissão em
   vez de o deixar subentendido no texto.

   Por dentro cada chip continua a ser um <label> com um checkbox invisível:
   o teclado, o leitor de ecrã e as suites veem o controlo de sempre — só a
   pele mudou. */
.dw-tipologias-bloco { margin-top: 8px; }
.dw-tipologias {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 8px;
}
.dw-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 14px;
  border: 1px solid var(--card-border);
  border-radius: 999px;
  background: transparent;
  color: var(--text-secondary);
  font-size: var(--body-small-size);
  line-height: var(--body-small-line);
  font-weight: var(--body-small-weight);
  cursor: pointer;
  user-select: none;
  transition: border-color 120ms linear, background-color 120ms linear,
    color 120ms linear;
}
.dw-chip:hover,
.dw-chip:focus-visible,
.dw-chip:has(input:focus-visible) {
  border-color: var(--action-primary);
  outline: none;
}
/* O visto só ocupa lugar quando está lá: um chip desligado com um buraco à
   esquerda parecia partido. */
.dw-chip__visto { display: none; }
.dw-chip.is-on {
  border-color: var(--action-primary);
  background: var(--card-surface-selected);
  color: var(--text-primary);
}
.dw-chip.is-on .dw-chip__visto {
  display: inline;
  color: var(--action-primary);
  font-weight: 600;
}
/* A linha que diz o que a escolha significa, por baixo dos chips. */
.dw-tipologias-estado { margin-top: 8px; }
.dw-face-selector__info {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--spacing-08);
}
.dw-face-selector__label {
  font-size: var(--caption-size);
  line-height: var(--caption-line);
  font-weight: var(--caption-weight);
  color: var(--text-secondary);
  margin: 0;
}
.dw-face-selector__empty {
  font-size: var(--body-medium-size);
  line-height: var(--body-medium-line);
  color: var(--text-primary);
  margin: 0;
}
.dw-face-selector__selected {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--spacing-04);
}
.dw-face-selector__code {
  font-size: var(--label-large-size);
  line-height: var(--label-large-line);
  font-weight: var(--label-large-weight);
  color: var(--text-primary);
  margin: 0;
}
.dw-face-selector__meta {
  font-size: var(--body-small-size);
  line-height: var(--body-small-line);
  font-weight: var(--body-small-weight);
  color: var(--text-secondary);
  margin: 0;
}

/* ---------------------------------------------------------------------------
   Notice — a standing statement about the screen: an undefined catalogue, a
   source that is not integrated, a rule that applies to the whole record.
   ------------------------------------------------------------------------- */
.dw-notice {
  margin: 0;
  padding: var(--spacing-12);
  width: 100%;
  border-radius: var(--radius-medium);
  border: 1px solid var(--field-border);
  background: var(--field-surface);
  backdrop-filter: blur(var(--field-blur));
  font-size: var(--body-small-size);
  line-height: var(--body-small-line);
  font-weight: var(--body-small-weight);
  color: var(--text-secondary);
}
.dw-notice--warning {
  border-left: 2px solid var(--action-primary);
  color: var(--text-primary);
}

/* ---------------------------------------------------------------------------
   Summary — read-only key/value rows for a record resolved by the system.
   ------------------------------------------------------------------------- */
.dw-summary {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-08);
  width: 100%;
}
.dw-summary__label {
  font-size: var(--caption-size);
  line-height: var(--caption-line);
  font-weight: var(--caption-weight);
  color: var(--text-secondary);
  margin: 0;
}
.dw-summary__rows {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-04);
  margin: 0;
  padding: var(--spacing-12);
  width: 100%;
  border-radius: var(--radius-medium);
  border: 1px solid var(--field-border);
  background: var(--field-surface);
  backdrop-filter: blur(var(--field-blur));
}
.dw-summary__row {
  display: flex;
  align-items: baseline;
  gap: var(--spacing-12);
  justify-content: space-between;
}
.dw-summary__key {
  font-size: var(--body-small-size);
  line-height: var(--body-small-line);
  color: var(--text-secondary);
  margin: 0;
  flex: none;
}
.dw-summary__value {
  font-size: var(--body-medium-size);
  line-height: var(--body-medium-line);
  font-weight: var(--label-large-weight);
  color: var(--text-primary);
  margin: 0;
  text-align: right;
  min-width: 0;
  overflow-wrap: anywhere;
}

/* ---------------------------------------------------------------------------
   Choice — a small set of mutually exclusive values, one row of buttons.
   ------------------------------------------------------------------------- */
/* Os botões dimensionam-se ao texto e mudam de linha quando não couberem.

   Antes eram `flex: 1 0 0`, e o `0` do meio é `flex-basis: 0`: todos ficavam
   com a MESMA largura, calculada a dividir a linha pelo número de opções e
   sem olhar ao que lá tinham dentro. Num telemóvel de 390px isso dava 57px
   por botão para caber "Registados", "Em avaliação", "Aprovados" e
   "Rejeitados" — o texto não cabia e, como não há `overflow: hidden`, não
   era cortado: era derramado para fora do botão, por cima do botão ao lado.
   Os rótulos liam-se uns por cima dos outros.

   `flex-wrap: wrap` com `flex: 0 1 auto` resolve: a base passa a ser a largura
   do conteúdo — ninguém fica mais pequeno do que o seu texto — e o que não
   couber desce para a linha seguinte em vez de transbordar.

   Sem `grow`, de propósito. Com `flex-grow: 1` os botões repartiam a sobra e
   a linha lia-se como uma banda cheia, mas o último a mudar de linha ficava
   sozinho e esticava-se à largura toda: em Verificações, um "Fechadas" de
   318px por baixo de três botões normais. Cada botão do tamanho do seu
   rótulo é o que se lê melhor e o que nunca se parte.

   `min-height` em vez de `height`: com altura fixa, um rótulo que precise de
   duas linhas fica com metade de fora. */
.dw-choice {
  display: flex;
  flex-wrap: wrap;
  align-items: stretch;
  gap: var(--spacing-08);
  width: 100%;
}
.dw-choice__option {
  flex: 0 1 auto;
  min-width: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  min-height: 40px;
  padding: var(--spacing-08) var(--spacing-12);
  border-radius: var(--radius-medium);
  border: 1px solid var(--field-border);
  background: var(--field-surface);
  backdrop-filter: blur(var(--field-blur));
  font-family: var(--font-family);
  font-size: var(--label-large-size);
  line-height: var(--label-large-line);
  font-weight: var(--label-large-weight);
  color: var(--text-secondary);
  cursor: pointer;
}
.dw-choice__option:hover { border-color: var(--border-default); color: var(--text-primary); }
.dw-choice__option:focus-visible { outline: none; border-color: var(--action-primary); }
.dw-choice__option.is-active {
  background: var(--action-primary);
  border-color: var(--action-primary);
  color: var(--text-onbrand);
}

/* --- Choice segmentado -------------------------------------------------- *
   O mesmo componente, com a mesma semântica de radiogroup, noutra pele.

   Três botões soltos, cada um com a sua moldura e 8px entre eles, lêem-se
   como três acções possíveis — e com o escolhido em laranja cheio a 40px de
   altura, lêem-se como três acções URGENTES. Nas Notificações do Perfil são
   quatro destes empilhados, e o bloco inteiro gritava.

   Encostados e dentro de uma moldura só, lêem-se como o que são: uma escolha
   com três posições, uma delas acesa. Trinta e quatro pixels em vez de
   quarenta, porque aqui a escolha acompanha uma linha de lista e não é o
   assunto principal dela.

   O anel de foco passa a `outline`: os segmentos não têm moldura própria para
   mudar de cor, e sem isto quem navega por teclado deixava de ver onde está.
   ------------------------------------------------------------------------- */
.dw-choice--segmentado {
  width: auto;
  flex-wrap: nowrap;
  gap: 0;
  border: 1px solid var(--field-border);
  border-radius: var(--radius-medium);
  background: var(--field-surface);
  backdrop-filter: blur(var(--field-blur));
  -webkit-backdrop-filter: blur(var(--field-blur));
  overflow: hidden;
}
.dw-choice--segmentado .dw-choice__option {
  min-height: 34px;
  padding: var(--spacing-04) var(--spacing-12);
  border: 0;
  border-left: 1px solid var(--field-border);
  border-radius: 0;
  background: transparent;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  font-size: var(--body-small-size);
  line-height: var(--body-small-line);
  white-space: nowrap;
}
.dw-choice--segmentado .dw-choice__option:first-child { border-left: 0; }
.dw-choice--segmentado .dw-choice__option:hover {
  background: var(--surface-secondary);
  color: var(--text-primary);
}
.dw-choice--segmentado .dw-choice__option:focus-visible {
  outline: 2px solid var(--action-primary);
  outline-offset: -2px;
}
.dw-choice--segmentado .dw-choice__option.is-active {
  background: var(--action-primary);
  color: var(--text-onbrand);
}

/* ---------------------------------------------------------------------------
   Campaign row — one active campaign plus its classification (Módulo 2.2).
   ------------------------------------------------------------------------- */
.dw-campaign-list {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-12);
  width: 100%;
}
.dw-campaign {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-12);
  width: 100%;
  padding: var(--spacing-16);
  border-radius: var(--radius-medium);
  border: 1px solid var(--field-border);
  background: var(--field-surface);
  backdrop-filter: blur(var(--field-blur));
}
.dw-campaign__titles {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-04);
}
.dw-campaign__name {
  font-size: var(--label-large-size);
  line-height: var(--label-large-line);
  font-weight: var(--label-large-weight);
  color: var(--text-primary);
  margin: 0;
}
.dw-campaign__client {
  font-size: var(--body-small-size);
  line-height: var(--body-small-line);
  color: var(--text-secondary);
  margin: 0;
}
/* The whole title block is the disclosure control: clicking a campaign opens
   its detail (Módulo 2.2, step 6). */
.dw-campaign__disclosure {
  display: flex;
  align-items: center;
  gap: var(--spacing-12);
  width: 100%;
  padding: 0;
  border: 0;
  background: transparent;
  font-family: var(--font-family);
  text-align: left;
  cursor: pointer;
  color: inherit;
}
.dw-campaign__disclosure:focus-visible { outline: 1px solid var(--action-primary); outline-offset: 2px; }
.dw-campaign__disclosure .dw-campaign__titles { flex: 1 0 0; min-width: 0; }
.dw-campaign__chevron {
  color: var(--icon-secondary);
  transform: rotate(90deg);
  flex: none;
}
.dw-campaign__disclosure[aria-expanded="true"] .dw-campaign__chevron {
  transform: rotate(270deg);
}
.dw-campaign__detail { width: 100%; }
.dw-campaign__nonconformity {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-12);
  width: 100%;
  padding-top: var(--spacing-12);
  border-top: 1px solid var(--field-divider);
}

/* ---------------------------------------------------------------------------
   Flag — a short state marker the system puts on a record.
   ------------------------------------------------------------------------- */
.dw-flag {
  display: inline-flex;
  align-items: center;
  align-self: flex-start;
  padding: 2px var(--spacing-08);
  border-radius: var(--radius-full);
  font-size: var(--caption-size);
  line-height: var(--caption-line);
  font-weight: var(--overline-weight);
  letter-spacing: var(--overline-tracking);
  text-transform: uppercase;
}
.dw-flag--alert {
  background: var(--feedback-error);
  color: var(--neutral-white);
}
.dw-flag--neutral {
  background: var(--surface-secondary);
  color: var(--text-secondary);
}
/* Um papel que o utilizador tem, e nao um estado do sistema: leva a cor da
   marca, a mesma que o resto do produto usa para "isto esta ligado". Nao ha
   verde nas Foundations, e inventar um so para aqui punha uma cor fora do
   sistema no sitio mais visivel do ecra de contas. */
.dw-flag--marca {
  background: var(--action-primary);
  color: var(--text-onbrand);
}

/* ---------------------------------------------------------------------------
   Record list — read-only rows of an existing record (Face ID ficha).
   ------------------------------------------------------------------------- */
.dw-record-list {
  display: flex;
  flex-direction: column;
  width: 100%;
  border-radius: var(--radius-medium);
  border: 1px solid var(--list-border);
  background: var(--list-surface);
  backdrop-filter: blur(var(--field-blur));
  -webkit-backdrop-filter: blur(var(--field-blur));
  overflow: hidden;
}
.dw-record {
  display: flex;
  align-items: center;
  gap: var(--spacing-12);
  width: 100%;
  padding: var(--spacing-12) var(--spacing-16);
  border-bottom: 1px solid var(--list-border);
  color: var(--text-primary);
  text-decoration: none;
}
.dw-record:last-child { border-bottom: 0; }
.dw-record--link:hover,
.dw-record--link:focus-visible { background: var(--neutral-900); outline: none; }
.dw-record__body {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-04);
  flex: 1 0 0;
  min-width: 0;
}
.dw-record__title {
  font-size: var(--body-medium-size);
  line-height: var(--body-medium-line);
  font-weight: var(--label-large-weight);
  color: var(--text-primary);
  overflow-wrap: anywhere;
}
/* O identificador no sistema de origem, ao lado do nome: o numero do
   cliente no PHC. Laranja da marca porque e uma referencia a OUTRO sistema --
   quem o le esta a preparar-se para o escrever noutro lado --, e nao mais um
   atributo deste. Peso normal para nao competir com o nome. */
.dw-record__tag {
  /* `--spacing-03` nao existe neste sistema -- os tokens sao 04 e 08 --, e
     um `var()` sem valor nem omissao cai para nada: o numero ficava colado ao
     nome, "LDA21988". */
  margin-left: var(--spacing-08);
  color: var(--action-primary);
  font-weight: var(--body-medium-weight, 400);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.dw-record__meta {
  font-size: var(--body-small-size);
  line-height: var(--body-small-line);
  color: var(--text-secondary);
  overflow-wrap: anywhere;
}
.dw-record__chevron { color: var(--icon-secondary); flex: none; }

/* ---------------------------------------------------------------------------
   Method list — the equivalent ways into a module (Face ID).
   ------------------------------------------------------------------------- */
.dw-method-list {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-12);
  width: 100%;
}
.dw-method {
  display: flex;
  /* `center` e não `flex-start` desde 28/09/2026. Com a descrição por baixo do
     nome, o bloco de texto tinha duas linhas e enchia o cartão; sem ela ficou
     uma linha de 20px ao lado de um ícone de 24px, e encostada ao cimo dava
     17px de folga acima contra 21px abaixo. Quatro pixeis, mas lêem-se: o
     texto parecia pendurado.

     Se algum dia um método voltar a trazer descrição, vale a pena olhar —
     com duas linhas, o ícone alinhado à primeira costuma ler-se melhor do que
     o ícone ao centro do bloco. */
  align-items: center;
  gap: var(--spacing-12);
  width: 100%;
  padding: var(--spacing-16);
  border-radius: var(--radius-medium);
  border: 1px solid var(--field-border);
  background: var(--field-surface);
  backdrop-filter: blur(var(--field-blur));
  -webkit-backdrop-filter: blur(var(--field-blur));
  font-family: var(--font-family);
  text-align: left;
  color: var(--text-primary);
}
button.dw-method { cursor: pointer; }
button.dw-method:hover,
button.dw-method:focus-visible { border-color: var(--action-primary); outline: none; }
.dw-method__icon { color: var(--action-primary); }
.dw-method__text {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-04);
  flex: 1 0 0;
  min-width: 0;
}
.dw-method__label {
  font-size: var(--label-large-size);
  line-height: var(--label-large-line);
  font-weight: var(--label-large-weight);
}
.dw-method__desc {
  font-size: var(--body-small-size);
  line-height: var(--body-small-line);
  color: var(--text-secondary);
}
/* O método escolhido, com a mesma cor que o hover já usa — não é um visual
   novo, é o mesmo estado a ficar. Sem isto, escolher "Código manual" fazia
   aparecer um campo mais abaixo e nada acontecia no sítio onde a pessoa
   acabou de carregar. */
button.dw-method.is-active { border-color: var(--action-primary); }
.dw-method.is-disabled { border-style: dashed; }
.dw-method.is-disabled .dw-method__icon { color: var(--text-disabled); }
.dw-method.is-disabled .dw-method__label { color: var(--text-disabled); }

/* ---------------------------------------------------------------------------
   Checkbox — used by the conditional report option (Módulo 2.2).
   ------------------------------------------------------------------------- */
.dw-checkbox {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-04);
  width: 100%;
}
.dw-checkbox__row {
  display: flex;
  align-items: center;
  gap: var(--spacing-12);
}
.dw-checkbox__input {
  appearance: none;
  -webkit-appearance: none;
  width: 20px;
  height: 20px;
  flex: none;
  margin: 0;
  border-radius: var(--radius-small);
  border: 1px solid var(--field-border);
  background: var(--field-surface);
  cursor: pointer;
  position: relative;
}
.dw-checkbox__input:checked {
  background: var(--action-primary);
  border-color: var(--action-primary);
}
.dw-checkbox__input:checked::after {
  content: "";
  position: absolute;
  left: 6px;
  top: 2px;
  width: 5px;
  height: 10px;
  border: solid var(--text-onbrand);
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}
.dw-checkbox__input:focus-visible { outline: none; border-color: var(--action-primary); }
.dw-checkbox__label {
  font-size: var(--body-medium-size);
  line-height: var(--body-medium-line);
  color: var(--text-primary);
  cursor: pointer;
}
.dw-checkbox__helper {
  margin: 0;
  padding-left: 32px;
  font-size: var(--body-small-size);
  line-height: var(--body-small-line);
  color: var(--text-secondary);
}

/* ---------------------------------------------------------------------------
   Stat grid — um número grande com o que ele conta (KPI do CRM, cap. 8.6).
   Grelha que se adapta: duas colunas no telemóvel, quantas couberem no
   desktop. Mesma superfície e borda dos campos, para pertencer ao resto.
   ------------------------------------------------------------------------- */
.dw-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: var(--spacing-12);
  width: 100%;
}
.dw-stat {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-04);
  padding: var(--spacing-12);
  border-radius: var(--radius-medium);
  border: 1px solid var(--field-border);
  background: var(--field-surface);
  backdrop-filter: blur(var(--field-blur));
  -webkit-backdrop-filter: blur(var(--field-blur));
}
.dw-stat__value {
  margin: 0;
  font-size: var(--heading-h2-size);
  line-height: var(--heading-h2-line);
  font-weight: var(--heading-h2-weight);
  color: var(--text-primary);
  overflow-wrap: anywhere;
}
.dw-stat__label {
  margin: 0;
  font-size: var(--body-small-size);
  line-height: var(--body-small-line);
  color: var(--text-secondary);
}

/* ---------------------------------------------------------------------------
   Barra de progresso — faturado sobre objetivo (KPI do CRM). A cor de
   preenchimento é a da marca, a mesma que o produto usa para "isto está
   ligado"; não há verde nas Foundations e não se inventa um.
   ------------------------------------------------------------------------- */
.dw-bar {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-04);
  width: 100%;
}
.dw-bar__head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--spacing-12);
}
.dw-bar__label {
  font-size: var(--label-large-size);
  line-height: var(--label-large-line);
  font-weight: var(--label-large-weight);
  color: var(--text-primary);
}
.dw-bar__meta {
  font-size: var(--body-small-size);
  line-height: var(--body-small-line);
  color: var(--text-secondary);
  text-align: right;
}
.dw-bar__track {
  display: block;
  width: 100%;
  height: 8px;
  border-radius: var(--radius-full);
  background: var(--surface-secondary);
  overflow: hidden;
}
.dw-bar__fill {
  display: block;
  height: 100%;
  border-radius: var(--radius-full);
  background: var(--action-primary);
  transition: width 240ms ease;
}
.dw-bar.is-complete .dw-bar__fill { background: var(--action-primary-hover); }

/* ---------------------------------------------------------------------------
   Footer — DREAMMEDIA mark. Used on the mobile Login screen.
   ------------------------------------------------------------------------- */
.dw-footer {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: 100%;
  padding-top: var(--spacing-24);
  padding-bottom: var(--spacing-48);
  flex: none;
}
.dw-footer img { display: block; width: 120px; height: auto; }

/* --- Photo Gallery ------------------------------------------------------ *
 * As fotografias de um registo, nos ecrãs de consulta. Grelha que se adapta:
 * uma coluna no telemóvel estreito, quantas couberem no desktop. A moldura
 * tem proporção fixa para a grelha não saltar enquanto os ficheiros chegam.
 * -------------------------------------------------------------------------- */
.dw-gallery {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
  gap: var(--spacing-12);
  width: 100%;
}
.dw-gallery__item {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-04);
  margin: 0;
  min-width: 0;
}
.dw-gallery__frame {
  position: relative;
  width: 100%;
  aspect-ratio: 4 / 3;
  max-width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-small);
  overflow: hidden;
  background: var(--field-surface);
  border: 1px solid var(--border-subtle);
}
/* Só depois de a imagem chegar (`is-ampliavel`, posta pelo JS). Uma moldura
   que ainda diz "a carregar" não tem o que ampliar, e o cursor de ponteiro
   prometeria uma ação que não acontecia. */
.dw-gallery__frame.is-ampliavel { cursor: zoom-in; }
.dw-gallery__frame.is-ampliavel:focus-visible {
  outline: 2px solid var(--action-primary);
  outline-offset: 2px;
}

/* --- A lupa: uma fotografia em grande ----------------------------------- *
 * `<dialog>` nativo — traz o Escape, o foco preso lá dentro e o fundo inerte
 * sem JS para isso. O `:modal` é o que permite dimensionar sem lutar com os
 * `max-width` que o navegador põe por omissão num dialog.                   */
.dw-lupa {
  max-width: 100vw;
  max-height: 100vh;
  padding: 0;
  border: 0;
  background: transparent;
  overflow: visible;
}
.dw-lupa::backdrop { background: rgba(0, 0, 0, 0.82); }
.dw-lupa__caixa { position: relative; }
.dw-lupa__imagem {
  display: block;
  /* Cabe sempre, seja a fotografia alta ou larga, e nunca cresce acima do
     tamanho real — esticar uma imagem pequena não a torna mais legível. */
  max-width: min(92vw, 1400px);
  max-height: 90vh;
  width: auto;
  height: auto;
  border-radius: var(--radius-medium);
}
.dw-lupa__fechar {
  position: absolute;
  top: calc(var(--spacing-08) * -1);
  right: calc(var(--spacing-08) * -1);
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  padding: 0;
  font-size: 24px;
  line-height: 1;
  color: var(--text-primary);
  background: var(--surface-primary);
  border: 1px solid var(--border-default);
  border-radius: 50%;
  cursor: pointer;
}
.dw-lupa__fechar:hover { border-color: var(--action-primary); }
.dw-gallery__frame img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.dw-gallery__estado,
.dw-gallery__meta {
  font-size: var(--caption-size);
  line-height: var(--caption-line);
  font-weight: var(--caption-weight);
  color: var(--text-secondary);
}
.dw-gallery__meta {
  margin: 0;
  overflow-wrap: anywhere;
}

/* --- Código QR do MFA ---------------------------------------------------- *
 * Mostrado uma única vez, na ativação de uma conta. Fundo branco e sempre
 * branco: um QR sobre o castanho da aplicação não é lido por câmara nenhuma,
 * e este ecrã só vale se for lido à primeira.
 * -------------------------------------------------------------------------- */
.dw-qr-codigo {
  display: flex;
  justify-content: center;
  align-items: center;
  padding: var(--spacing-16);
  background: var(--neutral-white);
  border-radius: var(--radius-medium);
  width: fit-content;
  max-width: 100%;
  margin: 0 auto;
}
.dw-qr-codigo svg {
  display: block;
  width: 100%;
  height: auto;
  max-width: 260px;
}
.dw-qr-codigo__ajuda {
  margin: 0;
  font-size: var(--caption-size);
  line-height: var(--caption-line);
  color: var(--text-secondary);
  text-align: center;
}

/* ---------------------------------------------------------------------------
   Paginacao — "26 a 50 de 312", com anterior e seguinte.
   Aparece so quando ha mais do que uma pagina (ver ui.js).
   ------------------------------------------------------------------------- */
.dw-paginacao {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--spacing-12);
  width: 100%;
  padding-top: var(--spacing-16);
  border-top: 1px solid var(--border-subtle);
}
/* A contagem e o seletor andam juntos, a esquerda: sao as duas a mesma
   pergunta -- "onde estou e quanto vejo de cada vez?" --, e soltos num
   `space-between` de tres o seletor ficava a boiar no meio da barra. */
.dw-paginacao__esquerda {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--spacing-12);
}
.dw-paginacao__tamanho {
  display: flex;
  align-items: center;
  gap: var(--spacing-08);
  font-size: var(--caption-size);
  line-height: var(--caption-line);
  color: var(--text-secondary);
}
.dw-paginacao__tamanho select {
  padding: var(--spacing-04) var(--spacing-08);
  background: var(--field-surface);
  border: 1px solid var(--field-border);
  border-radius: var(--radius-medium);
  color: var(--text-primary);
  font-size: var(--caption-size);
  line-height: var(--caption-line);
}
.dw-paginacao__tamanho select:focus-visible {
  outline: 2px solid var(--action-primary);
  outline-offset: 1px;
}
.dw-paginacao__conta {
  font-size: var(--caption-size);
  line-height: var(--caption-line);
  color: var(--text-secondary);
}
.dw-paginacao__botoes {
  display: flex;
  align-items: center;
  gap: var(--spacing-08);
}
.dw-paginacao__pagina {
  font-size: var(--caption-size);
  line-height: var(--caption-line);
  color: var(--text-secondary);
  white-space: nowrap;
  /* Nao encolhe: quem encolhe sao os botoes, que teem texto de sobra. */
  flex: none;
}

/* Um botao desactivado nao pode chamar mais a atencao do que o activo.

   `--action-disabled` e claro, e num fundo escuro o "Anterior" desligado da
   pagina 1 lia-se como o botao principal, com o "Seguinte" -- o unico que
   funciona ali -- a parecer secundario. Aqui recolhe, que e o que desactivado
   quer dizer. Ambito so na paginacao: o token serve outros sitios e nao e meu
   para mudar por causa deste. */
.dw-paginacao .dw-button--secondary:disabled {
  background: transparent;
  border: 1px solid var(--border-subtle);
  color: var(--text-disabled);
}
