:host {
  --width: 31rem;
  --border-radius: 6px;
  --padding: 1.5rem;
  --header-padding: var(--padding);
  --footer-padding: var(--padding);
  --show-duration: 200ms;
  --hide-duration: 200ms;
  --backdrop: var(--l-backdrop);
  --backdrop-blur: 0;

  display: contents;
}

dialog {
  position: fixed;
  inset: 0;
  box-sizing: border-box;
  width: var(--width);
  max-inline-size: min(90vw, var(--width));
  max-block-size: min(80dvb, 100%);
  margin: auto;
  padding: 0;
  border: 0;
  border-radius: var(--border-radius);
  background-color: var(--l-color-surface-overlay);
  color: var(--l-color-text-primary);

  /* EXIT STATE */
  opacity: 0;

  transition-property: opacity, display, overlay;
  transition-duration: var(--hide-duration);
  transition-behavior: allow-discrete;

  &::backdrop {
    background: var(--backdrop);
    backdrop-filter: blur(var(--backdrop-blur));
  }

  /* OPEN STATE */
  /* grid layout pins header/footer; the middle row (body) scrolls via
     overflow on [part='body'] and minmax(0, 1fr) allowing it to shrink. */
  &[open] {
    display: grid;
    grid-template-rows: auto minmax(0, 1fr) auto;
    opacity: 1;
    transition-duration: var(--show-duration);
  }

  /* BEFORE-OPEN STATE */
  @starting-style {
    &[open] {
      opacity: 0;
    }
  }
}

[part='header'] {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
  padding: var(--header-padding);
}

[part='title'] {
  margin: 0;
  font-size: 1.125rem;
  font-weight: 600;
  line-height: 1.4;
}

/* Pin body and footer so the layout stays correct when [without-header]
   removes the header and only two children auto-place into the grid. */
[part='body'] {
  grid-row: 2;
  padding-inline: var(--padding);
  overflow-y: auto;
}

[part='footer'] {
  grid-row: 3;
  display: flex;
  place-content: end;
  gap: 0.5rem;
  padding: var(--footer-padding);
}

/* Collapse the footer row when nothing is slotted into it, so an empty
   dialog/drawer reserves no space at the bottom. `data-empty` is toggled by the
   HasSlotController in dialog.ts: `:host(:has(...))` can't be used because
   `:has()` is invalid inside `:host()` and the whole rule is dropped by the
   browser. */
[part='footer'][data-empty] {
  display: none;
}

/* With the footer collapsed, the body has to provide its own block-end padding
   (normally inherited visually from the footer padding below it). */
[part='body']:has(~ [part='footer'][data-empty]) {
  padding-block-end: var(--padding);
}

/* Without a header, the body has to provide its own block-start padding
   (normally inherited visually from the header padding above it). */
:host([without-header]) [part='body'] {
  padding-block-start: var(--padding);
}

::slotted(menu[slot='footer']) {
  display: contents;
}

@media (prefers-reduced-motion: reduce) {
  :host {
    --show-duration: 0ms;
    --hide-duration: 0ms;
  }
}
