/* The one modal behind shared/_dialog, and the ⋯ action dialog. Both float,
   so both take the float radius and the single warm shadow. */
@layer components {
  /* The one modal, behind shared/_dialog for every form in the app. Sized by
     its content, never taller than the viewport. It floats, so it takes the
     float radius and the single warm shadow instead of the flat-surface
     radius that cards and inputs use. */
  .modal {
    /* The two a variant retunes. Everything else about a modal — the float
       radius, the warm shadow, the scrim, the 85dvh ceiling — is the same
       whatever is inside it, so a wider one sets these and nothing else.
       Height is `fit-content` for every modal but one: a form is as tall as
       it is. NOT `auto` — a modal dialog sits in the top layer with the UA's
       `inset: 0`, where auto means STRETCH, and every form dialog quietly
       filled to the 85dvh ceiling with a void under its buttons. fit-content
       is the UA's own dialog sizing, restated because this declaration
       exists to be retuned. */
    --modal-inline-size: 34rem;
    --modal-block-size: fit-content;

    inline-size: min(var(--modal-inline-size), 92vw);
    block-size: var(--modal-block-size);
    /* A fresh surface, like the action dialog: a modal renders wherever its
       trigger lives, and the intake's add-card dialog inherited the tool
       card's centering — every label and input drifted to the middle. */
    text-align: start;
    max-block-size: 85dvh;
    margin: auto;
    padding: var(--block-space-double) var(--inline-space-double);
    overflow-y: auto;
    color: var(--color-ink);
    background-color: var(--color-canvas);
    border: var(--border);
    border-radius: var(--border-radius-float);
    box-shadow: var(--shadow);

    /* The fade the starting style always meant: without a transition the
       rule was inert and every modal popped (found porting the lightbox,
       2026-08-24). Both ways — the scrim breathes with the card — on the
       quick clock (HANSHI). */
    opacity: 1;
    transition:
      display var(--speed-quick) allow-discrete,
      overlay var(--speed-quick) allow-discrete,
      opacity var(--speed-quick) var(--ease-out);

    @starting-style {
      opacity: 0;
    }

    &:not([open]) {
      opacity: 0;
    }

    &::backdrop {
      background-color: var(--color-scrim);
      transition:
        display var(--speed-quick) allow-discrete,
        overlay var(--speed-quick) allow-discrete,
        background-color var(--speed-quick) var(--ease-out);

      @starting-style {
        background-color: transparent;
      }
    }
  }

  /* Settings is the one modal whose content is a whole layout rather than a
     form, so it is the one that says all four of these.

     ONE HEIGHT, whatever pane you pick. Panes differ by a lot — four rail rows
     against a session per browser — and a dialog that resizes under the cursor
     between two clicks is the thing you notice (user, 2026-08-13). Fixed here,
     still capped at 85dvh above, and the pane scrolls inside it: which is why
     the modal's own overflow is shut off. The padding goes with it — the rail
     is tinted to the dialog's own edges, and the shell puts the room back
     inside each column (settings.css). */
  .modal--settings {
    --modal-inline-size: 52rem;
    --modal-block-size: 32rem;

    padding: 0;
    overflow: hidden;
  }

  /* The card dialog: a description editor wants more line than the default
     form column gives it (user, 2026-08-14 — "a tad cramped"). */
  .modal--wide {
    --modal-inline-size: 42rem;
  }

  /* On a phone a modal-hosted editor gives most of its floor back: lexxy's
     own 8-line minimum (layer base, so this outranks it) put an empty
     description at 188px and the add-card dialog at 85% of the screen
     (user, 2026-08-30 — "too big on mobile"). Four lines still read as a
     place to write, and the editor grows with the words. A viewport query
     like the modal's own sizing (92vw, 85dvh) — the question is the
     screen's room, not #main's. */
  @media (width < 35rem) {
    .modal .lexxy-editor__content {
      min-block-size: 4lh;
    }
  }

  /* Hierarchy by weight and the space under it, not by size — the title sits
     one step above body text and lets the whitespace do the separating. */
  .modal__title {
    font-size: var(--text-medium);
    font-weight: 600;
    margin-block-end: var(--block-space);
  }

  /* A form's buttons already say how to leave; only a modal that holds a
     chooser needs telling. Same words, same whisper as the action dialog. */
  .modal__dismiss {
    margin-block-start: var(--block-space);
    font-size: var(--text-x-small);
    color: var(--color-ink-faint);
  }

  .modal:has(.actions) .modal__dismiss {
    display: none;
  }

  /* And on a keyboardless screen there is no esc to speak of (user,
     2026-08-24) — the popups' footers stand down the same way (popups.css). */
  @media (hover: none) {
    .modal__dismiss {
      display: none;
    }
  }

  /* Everything else a card or record can do lives behind ⋯ in this one spare
     dialog: context line on top, plain rows, destructive last after a
     hairline, "esc to close" underneath. It floats — float radius and the warm
     shadow.

     It is a .popup — see popups.css for why a menu is a popover and never a
     <dialog>, and for everything it inherits from being one. All this adds is
     where it hangs: off the ⋯'s own end corner rather than centred under it,
     which is the difference between a menu and a palette. */
  .action-dialog {
    --popup-area: block-end span-inline-start;

    min-inline-size: 16rem;

    /* A menu is a fresh surface, not a continuation of whatever it hangs off.
       The day divider whispers in tracked uppercase, and the person card
       opening from its faces inherited the shouting — a name is a name. */
    text-transform: none;
    letter-spacing: normal;

    /* The one menu that lives at the bottom of the screen: up off the
       avatar, start edges aligned — the ⋯ area mirrored. Here and not in
       layout.css because this assignment must sit in the same layer to win. */
    #footer & {
      --popup-area: block-start span-inline-end;

      margin-block-end: var(--block-space-half);
    }

    /* And the one that hangs in a left gutter — the to-do row's ⋯ — opens
       toward the text: centring over the margin would run it off the sheet. */
    .todo__menu & {
      --popup-area: block-end span-inline-end;
    }

    /* On a narrow shell that same ⋯ stands at the row's END (todos.css), so
       the menu mirrors with it — toward the text again, now leftward. Without
       this it kept opening rightward, straight off a phone's edge
       (user, 2026-08-11). */
    @media (width < 35rem) {
      .todo__menu & {
        --popup-area: block-end span-inline-start;
      }
    }

    header {
      padding: var(--block-space-half) var(--inline-space);
      font-size: var(--text-x-small);
      color: var(--color-ink-subtle);
    }

    menu {
      list-style: none;
      margin: 0;
      padding: 0;
    }

    /* A row is a link or a button_to depending on the verb; both read the
       same. Scoped to the dialog, so no control rule escapes into the page. */
    menu :where(a, button) {
      /* A flex row rather than a block, so a row that leads with a glyph
         (the chat line's menu) lines it up with the word. */
      display: flex;
      align-items: center;
      gap: var(--inline-space);
      inline-size: 100%;
      padding: var(--block-space-half) var(--inline-space);
      font-weight: 400;
      text-align: start;
      color: var(--color-ink);
      background-color: transparent;
      border: none;
      border-radius: var(--border-radius);
      text-decoration: none;
      cursor: pointer;

      &:hover {
        background-color: var(--color-surface);
      }
    }

    /* A row that is a fact rather than a verb — "1 person was notified" —
       wears the row's shape in the subtle ink and answers no pointer. */
    menu .action-dialog__note {
      display: block;
      padding: var(--block-space-half) var(--inline-space);
      color: var(--color-ink-subtle);
    }

    /* The destructive row is one of the four places shu is spent; on its own
       tint it takes the paired ink, as every tint does. */
    menu .action-dialog__row--destructive {
      color: var(--color-accent);

      &:hover {
        color: var(--color-accent-ink);
        background-color: var(--color-accent-tint);
      }
    }

    /* Destructive last, after a hairline. */
    menu li.action-dialog__row--separated {
      border-block-start: var(--border);
      margin-block-start: var(--block-space-half);
      padding-block-start: var(--block-space-half);
    }

    footer {
      margin-block-start: var(--block-space-half);
      padding: var(--block-space-half) var(--inline-space) 0;
      border-block-start: var(--border);
      font-size: var(--text-x-small);
      color: var(--color-ink-faint);
    }
  }

}
