/* ============================================================================
 * Drawer — edge-anchored overlay panel (Sheet / Slide-over): a panel that
 * slides in from any screen edge over a scrim. Fully token-driven so it
 * re-themes across accents + light/dark. Shares its scrim + focus trap with
 * confirm() (see overlay.js). Under `prefers-reduced-motion` the kit's net
 * (reduced-motion.css) makes the slide and the fade instant.
 *
 * Local tokens (surface/shadow/scrim) so the panel + scrim re-theme cleanly:
 *   --drawer-surface  panel background
 *   --drawer-scrim    backdrop colour (--scrim already re-themes per theme)
 * ========================================================================== */

.ui-drawer {
  /* The floating step; the edge is the hairline each --drawer--<edge> rule below draws.
     why: docs/foundations.md#elevation */
  --drawer-surface: var(--bg-elevated);
  --drawer-scrim: var(--scrim);
  --drawer-w: var(--panel-md);   /* left|right panels: width  */
  --drawer-h: 45vh;    /* top|bottom panels: height */

  position: fixed;
  inset: 0;
  z-index: var(--z-overlay);
  pointer-events: none; /* container never blocks; scrim/panel opt back in */

  /* One place owns "is this drawer on screen at all", and the scrim and panel
     inherit it. Only the HIDE is transitioned, so the panel is still on screen
     while it slides out; the show is instant (`.is-open` cancels the
     transition) because openDrawer() focuses a control in the same frame it
     opens, and focus() on a hidden element does nothing. `linear` and not
     var(--ease): visibility is discrete, easing a step buys nothing, and a curve
     that leaves [0, 1] would flip it in the middle of the fade. */
  visibility: hidden;
  transition: visibility var(--dur-med) linear;
}
.ui-drawer.is-open { visibility: visible; transition: none; }

/* Hit-testable only while open. The root stays visible for --dur-med after
   closeDrawer() has stopped trapping, and any control still clickable in that
   window — the footer's actions, the close button — runs the caller's handler
   again on the way out. */
.ui-drawer.is-open .ui-drawer__scrim,
.ui-drawer.is-open .ui-drawer__panel { pointer-events: auto; }

/* Scrim — fades in and out; the drawer root decides when it stops existing. */
.ui-drawer__scrim {
  position: absolute;
  inset: 0;
  background: var(--drawer-scrim);
  opacity: 0;
  transition: opacity var(--dur-med) var(--ease);
}
.ui-drawer.is-open .ui-drawer__scrim { opacity: 1; }

/* Panel — the sliding surface. Flex column: header / scrollable body / footer. */
.ui-drawer__panel {
  position: absolute;
  display: flex;
  flex-direction: column;
  background: var(--drawer-surface);
  /* A drawer is flush to a screen edge, so it has one edge rather than four and the
     two-step edge runs along that one: --border-strong on the edge rule below, the
     inner line one pixel inside it. This is the one floating surface that writes no
     inset RING — a full ring would draw 1px lines across the top and bottom of a
     full-height panel, where there is no edge — so it composes its own directional
     line with the drops instead. The line is a variable so the focus rule can
     compose all three layers without knowing which edge it is on; its default is a
     no-op layer rather than `none`, which is valid only alone and would invalidate
     the list. why: docs/foundations.md#elevation */
  --drawer-line: 0 0 0 0 transparent;
  box-shadow: var(--drawer-line), var(--elev-drop);
  transition: transform var(--dur-med) var(--ease);
}
.ui-drawer.is-open .ui-drawer__panel { transform: none; }

/* -- Edge anchoring + slide-in direction ---------------------------------- */
.ui-drawer--right .ui-drawer__panel,
.ui-drawer--left  .ui-drawer__panel {
  top: 0; bottom: 0;
  width: min(var(--drawer-w), 100vw);
  max-width: 100vw;
}
.ui-drawer--right .ui-drawer__panel {
  right: 0;
  border-left: 1px solid var(--float-edge);
  --drawer-line: inset 1px 0 0 var(--float-edge-inner);
  transform: translateX(100%);
}
.ui-drawer--left .ui-drawer__panel {
  left: 0;
  border-right: 1px solid var(--float-edge);
  --drawer-line: inset -1px 0 0 var(--float-edge-inner);
  transform: translateX(-100%);
}
.ui-drawer--top .ui-drawer__panel,
.ui-drawer--bottom .ui-drawer__panel {
  left: 0; right: 0;
  height: min(var(--drawer-h), 100vh);
  max-height: 100vh;
}
.ui-drawer--top .ui-drawer__panel {
  top: 0;
  border-bottom: 1px solid var(--float-edge);
  --drawer-line: inset 0 -1px 0 var(--float-edge-inner);
  transform: translateY(-100%);
}
.ui-drawer--bottom .ui-drawer__panel {
  bottom: 0;
  border-top: 1px solid var(--float-edge);
  --drawer-line: inset 0 1px 0 var(--float-edge-inner);
  transform: translateY(100%);
}

/* The ring leaves the drawer's own elevation alone: it is an outline since #578, so
   the edge and the drop no longer have to be restated here to survive focus.
   why: docs/foundations.md#elevation */
.ui-drawer__panel:focus-visible { outline: var(--ring); outline-offset: var(--ring-offset); }

/* -- Sizes ----------------------------------------------------------------- */
/* left|right → width; top|bottom → height. Same names, axis chosen by side. */
.ui-drawer--right.ui-drawer--sm, .ui-drawer--left.ui-drawer--sm { --drawer-w: var(--panel-sm); }
.ui-drawer--right.ui-drawer--md, .ui-drawer--left.ui-drawer--md { --drawer-w: var(--panel-md); }
.ui-drawer--right.ui-drawer--lg, .ui-drawer--left.ui-drawer--lg { --drawer-w: var(--panel-lg); }
.ui-drawer--top.ui-drawer--sm, .ui-drawer--bottom.ui-drawer--sm { --drawer-h: 30vh; }
.ui-drawer--top.ui-drawer--md, .ui-drawer--bottom.ui-drawer--md { --drawer-h: 45vh; }
.ui-drawer--top.ui-drawer--lg, .ui-drawer--bottom.ui-drawer--lg { --drawer-h: 72vh; }

/* -- Slots ----------------------------------------------------------------- */
/* The header marks the scroll boundary; actions share the panel surface. */
.ui-drawer__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-5);
  border-bottom: 1px solid var(--border);
  flex: none;
}
/* An h2, and base.css would give it the display face. It opts out: at 15px in a
   panel header it is a label on a piece of UI rather than a heading anybody
   reads, and the display face at that size is exactly what #253 was about.
   why: docs/foundations.md#typefaces */
.ui-drawer__title {
  margin: 0;
  font-family: var(--font-sans);
  font-size: calc(var(--text-base) + 0.5px);
  font-weight: 600;
  letter-spacing: 0.01em;
  color: var(--strong);
}
/* Header actions stand at the far end, beside the close button. */
.ui-drawer__actions { display: flex; align-items: center; gap: var(--space-1); margin-inline-start: auto; }
.ui-drawer__close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px; height: 30px;
  flex: none;
  cursor: pointer;
  /* muted-ink: glyph — dismiss icon */ color: var(--muted);
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  font: inherit;
  transition:
    color var(--dur-fast) var(--ease),
    background var(--dur-fast) var(--ease),
    border-color var(--dur-fast) var(--ease);
}
.ui-drawer__close:hover { color: var(--strong); background: var(--surface-3); /* code-bg: inherit — control paint; the containing surface is the ground, for a chip and for a band alike. */ }
.ui-drawer__close:focus-visible { outline: var(--ring); outline-offset: var(--ring-offset); }
.ui-drawer__close svg { width: 18px; height: 18px; stroke: currentColor; fill: none; stroke-width: 2.1; }

.ui-drawer__body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  padding: 20px;
  color: var(--text);
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  line-height: 1.55;
}
/* A body of prose scrolls, so the browser makes it a keyboard stop and it answered
   with the native outline. The band is drawn INWARD, inside the 20px padding: the body
   is flush with a panel that is itself flush with a screen edge, so an outset ring — on
   either box — is painted off-screen. Measured at 390, where an outset one left no
   indicator at all. why: docs/foundations.md#the-focus-ring */
.ui-drawer__body:focus-visible { outline: var(--ring-scroll); outline-offset: var(--ring-scroll-offset); }

.ui-drawer__footer {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-5);
  flex: none;
}

/* -- Groups and rows ------------------------------------------------------- */
/* drawerSection(): a heading over label/value rows. The value sits beside its
   label rather than at the far edge, so nothing has to lead the eye across the
   panel, and rows are held apart by space alone. Group from group is the one
   division inside the body worth a line; the body's padding insets it, so it
   parts the groups without cutting the panel in two.
   why: docs/components.md#the-drawer */
.ui-drawer__section + .ui-drawer__section {
  margin-top: var(--space-6);
  padding-top: var(--space-6);
  border-top: 1px solid var(--border);
}
/* An h3, and it opts out of the display face for the reason .ui-drawer__title does.
   why: docs/foundations.md#typefaces */
.ui-drawer__section-title {
  margin: 0 0 var(--space-2);
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  /* Semibold, and so outside the rank table, which has nothing at this size and
     weight. A group heading set in the label rank would match the row labels
     under it in size and weight both, and differ from them by colour alone. */
  font-weight: var(--weight-semibold);
  color: var(--strong);
}
.ui-drawer__rows {
  display: grid;
  grid-template-columns: minmax(0, 2fr) minmax(0, 3fr);
  column-gap: var(--space-4);
  margin: 0;
}
.ui-drawer__row { display: contents; }
.ui-drawer__row dt,
.ui-drawer__row dd {
  margin: 0;
  padding-block: var(--space-1);
  overflow-wrap: anywhere;
}
/* A control in the value column has its own border and padding, so its first line sits lower
   than a label's. A row whose value holds a field or a dropdown lines both first lines up on
   their baseline, whatever the control is, and a row of text keeps its place. At 560px and
   below the label stacks over the value and there is nothing to align. A field's own label
   stays for a screen reader only when one field fills the value cell. With two
   fields, each label remains visible to name its control. */
.ui-drawer__row:has(> dd :is(.ui-input, .ui-textarea, .ui-select, .ui-dropdown)) > :is(dt, dd) { align-self: baseline; }
.ui-drawer__row > dd:has(> .ui-field:only-child) > .ui-field > .ui-field__label { position: absolute; width: 1px; height: 1px; padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.ui-drawer__row dt { color: var(--text); }
.ui-drawer__row dd { color: var(--text); font-variant-numeric: tabular-nums; }
.ui-drawer .ui-drawer__rows + *,
.ui-drawer .ui-kv + * { margin-top: var(--space-3); }

/* Under reduced motion the net gives every element a 0.01ms transition, so a
   child inherits `visible` one tick after the root: the control openDrawer()
   focuses is still hidden in that frame, and focus lands on the panel. So an
   open drawer carries no transition inside it at all — for as long as it is
   open, not only in the frame it opens — which is what reduced motion asked
   for anyway: under the net nothing inside had longer than 0.01ms to run.
   why: docs/foundations.md#reduced-motion-travels-with-the-stylesheet */
@media (prefers-reduced-motion: reduce) {
  .ui-drawer.is-open * { transition: none !important; }
}

