/* Slide-in panel. DESIGN.md section 4 (Drawer, popover, dialog, reference
   stack), section 6 (z-drawer budget) and section 8, which is explicit about
   the shape at each width: "Mobile: full width sheet from the bottom.
   Desktop: 380px from the right, capped at 92vw."

   Written mobile first, so the bottom sheet is the base and the side panel is
   the override. It was the side panel at every width, and on a phone it was
   not even full width: `<dialog>`'s UA stylesheet caps a dialog at
   `calc(100% - 6px - 2em)`, so `width: 100vw` rendered as 352px of 390 with a
   38px sliver of the page showing down one side. That reads as a misplaced
   panel rather than as a sheet, and `max-width: none` is what stops it.

   Same shape as dialog.css: a `<dialog>` in the top layer, so no manual
   z-index is needed for stacking above the app. `--z-drawer` is set anyway,
   per the budget rule that nothing may rely on implicit top-layer ordering. */

@layer components {
  .drawer {
    padding: 0;
    margin: 0;
    border: none;
    border-block-start: 1px solid var(--border);
    border-radius: 0;
    background: var(--surface-1);
    /* The bar's blur, for the bar's reason. `--surface-1` became translucent
       on 2026-09-11, and the drawer is the largest single panel in the product:
       its 55% scrim alone leaves roughly a tenth of the page's own text
       showing through the panel, which reads as a printing fault rather than
       as glass. Blurring the backdrop flattens whatever is behind it into a
       wash. One element, so this costs one compositor layer - unlike cards,
       which is why they carry no filter. */
    backdrop-filter: var(--glass-filter-strong);
    color: var(--text);
    box-shadow: var(--shadow-2);
    position: fixed;
    inset: auto 0 0 0;
    width: 100%;
    max-width: none;
    height: auto;
    max-height: 88dvh;
    z-index: var(--z-drawer);
    /* A grid container with ONE BOUNDED ROW, and the `minmax(0, 1fr)` is the
       whole point of it rather than a flourish.

       `display: grid` alone is not enough and shipped broken for an hour: an
       auto-sized row takes its height from the panel's content, the sheet's
       `max-height` clamps only the sheet, and the panel keeps its full height
       and overflows it. Measured on the shipped rule with twenty rows in a
       300px sheet: the body was 820px tall, `scrollHeight === clientHeight`,
       and every row past the fifth was clipped and unreachable. With
       `minmax(0, 1fr)` the row is bounded by the sheet's content box, the
       panel fills it, and the body scrolls: body 282px, scrollable.

       It still sizes to its content when there is little of it, which is what
       a bottom sheet should do: two rows gives a 102px sheet, not a 300px one.

       The e2e suite cannot catch this. No drawer in the app has enough content
       to overflow 88dvh yet, so the failure is invisible until a writer has
       twelve chapters. */
    display: grid;
    grid-template-rows: minmax(0, 1fr);
    transform: translateY(100%);
    transition: transform var(--dur-4) var(--ease-out);
  }

  .drawer[open] { transform: translateY(0); }

  @starting-style {
    .drawer[open] { transform: translateY(100%); }
  }

  /* Closing. The dialog stays [open] for the length of the slide-out, because
     a <dialog> without [open] is display:none - closing it first removed the
     panel in the same frame and the exit never played. drawer.js sets this,
     waits for the transition, and only then closes and removes. */
  .drawer[open][data-closing] { transform: translateY(100%); }

  /* Once there is room, the panel comes in from the side it was asked for.
     Comfortable fixed width, capped at 92vw so a narrow tablet viewport never
     forces a horizontal scrollbar underneath. */
  @media (min-width: 640px) {
    .drawer {
      inset: 0 0 0 auto;
      width: min(380px, 92vw);
      height: 100dvh;
      max-height: 100dvh;
      border-block-start: none;
      border-inline-start: 1px solid var(--border);
      border-radius: 0;
      transform: translateX(100%);
    }
    .drawer[open] { transform: translateX(0); }
    @starting-style {
      .drawer[open] { transform: translateX(100%); }
    }
    .drawer[open][data-closing] { transform: translateX(100%); }

    .drawer[data-side="left"] {
      inset: 0 auto 0 0;
      border-inline-start: none;
      border-inline-end: 1px solid var(--border);
      transform: translateX(-100%);
    }
    .drawer[data-side="left"][open] { transform: translateX(0); }
    @starting-style {
      .drawer[data-side="left"][open] { transform: translateX(-100%); }
    }
    .drawer[data-side="left"][open][data-closing] { transform: translateX(-100%); }
  }

  .drawer::backdrop {
    background: color-mix(in oklab, black 55%, transparent);
    opacity: 0;
    transition: opacity var(--dur-3) var(--ease-out);
  }
  .drawer[open]::backdrop { opacity: 1; }
  .drawer[open][data-closing]::backdrop { opacity: 0; }

  .drawer__panel {
    display: grid;
    /* `minmax(0, 1fr)`, not `1fr`: a `1fr` row has an automatic minimum of its
       content, which stops the body ever scrolling and pushes the sheet past
       its own max-height. */
    grid-template-rows: auto minmax(0, 1fr);
    min-height: 0;
    height: 100%;
    overscroll-behavior: contain;
  }

  .drawer__head {
    display: flex;
    align-items: start;
    justify-content: space-between;
    gap: var(--space-4);
    padding: var(--space-5) var(--space-5) 0;
  }

  .drawer__title {
    font-size: var(--text-xl);
    line-height: var(--text-xl-lh);
    margin: 0;
    text-wrap: balance;
  }

  .drawer__close {
    flex: 0 0 auto;
    width: calc(44px * var(--ui-scale));
    height: calc(44px * var(--ui-scale));
    margin: -6px -6px 0 0;
    display: grid;
    place-items: center;
    border-radius: var(--radius-pill);
    color: var(--text-muted);
    font-size: var(--text-lg);
    line-height: 1;
    cursor: pointer;
    transition: background-color var(--dur-2) var(--ease-out), color var(--dur-2) var(--ease-out);
  }
  .drawer__close:hover { background: var(--surface-2); color: var(--text); }

  /* The labelled variant. Black rather than the outlined `btn--secondary`
     default (owner, 2026-09-10): the drawer's own panel is a raised surface,
     so a transparent button on it reads as part of the header rather than as
     the way out. Overrides the icon variant's fixed 44px box, which would
     crop a word. */
  .drawer__close--labelled {
    inline-size: auto;
    block-size: auto;
    min-height: calc(32px * var(--ui-scale));
    margin: 0;
    border-radius: 0;
    color: var(--text);
    font-size: var(--text-sm);
    /* `var(--bg)`, not `#000`. DESIGN.md 12.2: "No raw colour, ever, including
       #000 and #fff inside a color-mix(). Black is {--bg} composited, or a
       token of its own." Filed as an open violation in 12.5 and fixed here -
       a raw hex in a kit component is also CLAUDE.md rule 7. It darkens toward
       the page's own ground now, so a skin whose ground is not near-black gets
       a hover that belongs to it rather than to Noval. */
    --btn-bg: color-mix(in oklab, var(--bg) 62%, var(--surface-1));
  }

  .drawer__close--labelled:hover { background: var(--btn-bg); color: var(--text); }
  .drawer__close:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 2px; }

  .drawer__body {
    /* The sheet ends at the bottom of the screen on a phone, so the last row
       has to clear the home indicator. */
    padding: var(--space-5) var(--space-5) max(var(--space-5), env(safe-area-inset-bottom, 0));
    overflow-y: auto;
    overscroll-behavior: contain;
    display: grid;
    gap: var(--space-4);
    align-content: start;
  }

  @media (prefers-reduced-motion: reduce) {
    .drawer,
    .drawer[data-side="left"] {
      transform: none;
      opacity: 0;
      transition: opacity var(--dur-2) linear;
    }
    .drawer[open],
    .drawer[data-side="left"][open] { transform: none; opacity: 1; }
    @starting-style {
      .drawer[open] { opacity: 0; }
    }
    .drawer::backdrop { transition: opacity var(--dur-2) linear; }
  }
}
