/*
Drawer

A Dialog panel on an edge that the user can drag away:

<dialog class="dialog-overlay drawer-overlay">    top layer, transparent
  <div class="drawer-backdrop">                     fades; follows the drag
  <div class="dialog drawer" data-direction="bottom">
    .drawer-handle > .drawer-handle-bar             the grab bar
    .drawer-header > .drawer-title + .drawer-description
    .drawer-body                                    scrolls when tall
    .drawer-footer

The panel's position is --drawer-x / --drawer-y (set by drawer.ts while
dragging and for snap points), read by transform, so a drag never
changes layout. [data-swiping] turns transitions off while the pointer
leads. A drawer opened from inside another sets data-nested-drawer-open
on the outer panel, which steps back with scale and translate.
DrawerWrapper (.drawer-wrapper) scales the page back while a
scaleBackground drawer is open.
*/

@layer components {

.dialog-overlay.drawer-overlay {
  padding:         0;
  background:      none;
  backdrop-filter: none;
  overflow:        hidden;
}

.dialog-overlay.drawer-overlay[open] {
  display: block;
}

.dialog-overlay.drawer-overlay[data-state] {
  animation: none;
}

.drawer-backdrop {
  position:        fixed;
  inset:           0;
  background:      var(--backdrop);
  backdrop-filter: blur(var(--backdrop-blur));
  transition:      opacity var(--duration-enter) var(--ease-enter);
}

.drawer-backdrop[data-swiping] {
  transition: none;
}

.dialog-overlay.drawer-overlay:not([data-modal="true"]) > .drawer-backdrop {
  display: none;
}

.drawer-backdrop[data-state="open"] {
  animation: drawer-fade-in var(--duration-enter) var(--ease-enter);
}

.drawer-backdrop[data-state="closed"] {
  animation: drawer-fade-out var(--duration-exit) var(--ease-exit) forwards;
}

.dialog.drawer {
  --drawer-x: 0px;
  --drawer-y: 0px;

  position:       fixed;
  gap:            var(--dialog-gap);
  max-width:      none;
  overflow:       visible;
  border:         0 solid var(--dialog-border);
  border-radius:  0;
  transform:      translate3d(var(--drawer-x), var(--drawer-y), 0);
  transition:     transform var(--duration-enter) var(--ease-enter),
                  translate var(--duration-enter) var(--ease-enter),
                  scale var(--duration-enter) var(--ease-enter);
  touch-action:   none;
  will-change:    transform;
}

.dialog.drawer[data-swiping] {
  transition: none;
}

/* The bleed (vaul's ::after, shadcn's --drawer-bleed-background): the panel
   continues past its edge, so a drag past fully open lifts the panel
   without showing the backdrop between it and the screen edge. */
.dialog.drawer::after {
  content:    "";
  position:   absolute;
  background: var(--drawer-bleed-background, inherit);
}

.dialog.drawer[data-direction="bottom"]::after { top: calc(100% + var(--drawer-inset, 0px));    left: 0; right: 0;  height: 200%; }
.dialog.drawer[data-direction="top"]::after    { bottom: calc(100% + var(--drawer-inset, 0px)); left: 0; right: 0;  height: 200%; }
.dialog.drawer[data-direction="right"]::after  { left: calc(100% + var(--drawer-inset, 0px));   top: 0;  bottom: 0; width: 200%; }
.dialog.drawer[data-direction="left"]::after   { right: calc(100% + var(--drawer-inset, 0px));  top: 0;  bottom: 0; width: 200%; }

/* bottom and top: full width, as tall as the content, never past the viewport. */
/* --drawer-inset (shadcn), set by the caller on the panel through class:
   the panel floats that far off the viewport edges, with every corner
   rounded and every side bordered. 0 by default: flush to its edge. The
   min() terms are 0 with no inset and the full value with any inset. */
.dialog.drawer {
  --drawer-float-radius: min(var(--radius-dialog), calc(var(--drawer-inset, 0px) * 1000));
  --drawer-float-border: min(var(--dialog-border-width), calc(var(--drawer-inset, 0px) * 1000));

  border-width:  var(--drawer-float-border);
  border-radius: var(--drawer-float-radius);
}

.dialog.drawer[data-direction="bottom"],
.dialog.drawer[data-direction="top"] {
  left:       var(--drawer-inset, 0px);
  right:      var(--drawer-inset, 0px);
  width:      auto;
  max-height: calc(100% - var(--space-24));
}

.dialog.drawer[data-direction="bottom"] {
  bottom:                  var(--drawer-inset, 0px);
  border-top-width:        var(--dialog-border-width);
  border-top-left-radius:  var(--radius-dialog);
  border-top-right-radius: var(--radius-dialog);
  transform-origin:        top center;
}

.dialog.drawer[data-direction="top"] {
  top:                        var(--drawer-inset, 0px);
  border-bottom-width:        var(--dialog-border-width);
  border-bottom-left-radius:  var(--radius-dialog);
  border-bottom-right-radius: var(--radius-dialog);
  transform-origin:           bottom center;
}

/* With snap points the panel is nearly the viewport tall and rests translated. */
.dialog.drawer[data-snap-points][data-direction="bottom"],
.dialog.drawer[data-snap-points][data-direction="top"] {
  height:     calc(100% - var(--space-6));
  max-height: none;
}

/* left and right: full height, 75% wide up to --container-sm. */
.dialog.drawer[data-direction="left"],
.dialog.drawer[data-direction="right"] {
  top:       var(--drawer-inset, 0px);
  bottom:    var(--drawer-inset, 0px);
  width:     75%;
  max-width: var(--container-sm);
  height:    auto;
}

.dialog.drawer[data-direction="right"] {
  right:                     var(--drawer-inset, 0px);
  border-left-width:         var(--dialog-border-width);
  border-top-left-radius:    var(--radius-dialog);
  border-bottom-left-radius: var(--radius-dialog);
}

.dialog.drawer[data-direction="left"] {
  left:                       var(--drawer-inset, 0px);
  border-right-width:         var(--dialog-border-width);
  border-top-right-radius:    var(--radius-dialog);
  border-bottom-right-radius: var(--radius-dialog);
}

/* The handle: a pill with a larger hit area. At the top of a bottom
   drawer, the bottom of a top drawer. */
.drawer-handle {
  display:         flex;
  justify-content: center;
  flex:            none;
  margin-block:    calc((var(--dialog-padding) - var(--space-2)) * -1) calc(var(--space-2) * -1);
  padding-block:   var(--space-2);
  cursor:          grab;
  touch-action:    none;
}

.dialog.drawer[data-direction="top"] > .drawer-handle {
  order:        99;
  margin-block: calc(var(--space-2) * -1) calc((var(--dialog-padding) - var(--space-2)) * -1);
}

.drawer-handle-bar {
  width:         var(--drawer-handle-width);
  height:        var(--drawer-handle-height);
  border-radius: var(--radius-pill);
  background:    var(--rule-strong);
}

.drawer-handle:focus-visible {
  outline:       none;
  border-radius: var(--radius-control);
  box-shadow:    var(--focus-ring);
}

.dialog.drawer[data-swiping] .drawer-handle {
  cursor: grabbing;
}

.dialog.drawer .dialog-close {
  top:              calc(var(--dialog-padding) - var(--space-2));
  right:            auto;
  left:             auto;
  inset-inline-end: calc(var(--dialog-padding) - var(--space-2));
}

.drawer-header {
  display:        flex;
  flex-direction: column;
  gap:            var(--space-1-5);
}

.dialog.drawer .dialog-header {
  padding-right: 0;
}

.dialog.drawer[data-direction="bottom"] .drawer-header,
.dialog.drawer[data-direction="top"] .drawer-header {
  text-align: center;
}

@media (min-width: 48rem) {
  .dialog.drawer[data-direction="bottom"] .drawer-header,
  .dialog.drawer[data-direction="top"] .drawer-header {
    text-align: start;
  }
}

.drawer-body {
  display:             flex;
  flex-direction:      column;
  gap:                 var(--space-3);
  flex:                1 1 auto;
  min-height:          0;
  overflow-y:          auto;
  overscroll-behavior: contain;
  touch-action:        pan-y;
  /* Room on all four sides for the focus ring of a field at a scroll
     edge; the negative margin keeps the layout where it was. */
  margin:              calc(var(--space-1) * -1);
  padding:             var(--space-1);
}

/* A body that scrolls is a Tab stop (sheet.ts keepScrollStops). */
.drawer-body:focus-visible {
  outline:    none;
  box-shadow: var(--focus-ring);
}

.drawer-footer {
  display:        flex;
  flex-direction: column;
  gap:            var(--space-2);
  margin-top:     auto;
}

.drawer-footer > .button,
.drawer-footer > .dialog-close-part > .button {
  width: 100%;
}

/* NESTED: the outer drawer steps back. While the inner one is dragged,
   --drawer-nested-progress (1 open, 0 closed) follows it, so the outer one
   comes forward continuously (vaul). */
.dialog.drawer[data-nested-drawer-open] {
  scale: calc(1 - (1 - var(--enter-scale)) * var(--drawer-nested-progress, 1));
}

.dialog.drawer[data-nested-drawer-open][data-direction="bottom"] {
  translate: 0 calc(var(--space-4) * -1 * var(--drawer-nested-progress, 1));
}

.dialog.drawer[data-nested-drawer-open][data-direction="top"] {
  translate: 0 calc(var(--space-4) * var(--drawer-nested-progress, 1));
}

.dialog.drawer[data-nested-drawer-swiping] {
  transition: none;
}

/* SWIPE AREA: an invisible strip on the edge its swipe starts from (the
   drawer's own edge by default); a swipe from it opens the drawer, which
   follows the finger (Base UI SwipeArea). */
.drawer-swipe-area {
  position:     fixed;
  z-index:      var(--z-fixed);   /* an edge gesture: above sticky page chrome */
  touch-action: none;
}

.drawer-swipe-area[data-direction="bottom"] { left: 0; right: 0; bottom: 0; height: var(--space-6); }
.drawer-swipe-area[data-direction="top"]    { left: 0; right: 0; top: 0;    height: var(--space-6); }
.drawer-swipe-area[data-direction="right"]  { top: 0; bottom: 0; right: 0;  width: var(--space-6); }
.drawer-swipe-area[data-direction="left"]   { top: 0; bottom: 0; left: 0;   width: var(--space-6); }

/* Disabled (Base UI SwipeArea disabled): the page under it takes touches. */
.drawer-swipe-area[data-disabled] {
  pointer-events: none;
}

/* Motion */

.dialog.drawer[data-direction="bottom"] { --drawer-from: translate3d(0, calc(100% + var(--drawer-inset, 0px)), 0); }
.dialog.drawer[data-direction="top"]    { --drawer-from: translate3d(0, calc(-100% - var(--drawer-inset, 0px)), 0); }
.dialog.drawer[data-direction="right"]  { --drawer-from: translate3d(calc(100% + var(--drawer-inset, 0px)), 0, 0); }
.dialog.drawer[data-direction="left"]   { --drawer-from: translate3d(calc(-100% - var(--drawer-inset, 0px)), 0, 0); }

.dialog.drawer[data-state="open"] {
  animation: drawer-in var(--duration-enter) var(--ease-enter);
}

.dialog.drawer[data-state="closed"] {
  animation: drawer-out calc(var(--duration-exit) * var(--drawer-swipe-strength, 1)) var(--ease-exit) forwards;
}

/* Opened by a swipe from the swipe area: the panel and backdrop follow the
   finger, so neither plays its enter animation. */
.dialog.drawer[data-state="open"][data-swipe-opened],
.drawer-backdrop[data-state="open"][data-swipe-opened] {
  animation: none;
}

@keyframes drawer-in       { from { transform: var(--drawer-from); } }
@keyframes drawer-out      { to   { transform: var(--drawer-from); } }
@keyframes drawer-fade-in  { from { opacity: 0; } }
@keyframes drawer-fade-out { to   { opacity: 0; } }

/* Background Scale */

.drawer-wrapper {
  background:       var(--bg);
  transform-origin: top center;
  transition:       transform var(--duration-enter) var(--ease-enter),
                    border-radius var(--duration-enter) var(--ease-enter);
}

.drawer-wrapper[data-active] {
  --drawer-progress: 1;

  overflow:      hidden;
  border-radius: calc(var(--radius-dialog) * var(--drawer-progress));
  transform:     translateY(calc(var(--space-3-5) * var(--drawer-progress)))
                 scale(calc(1 - (1 - var(--drawer-wrapper-scale, 1)) * var(--drawer-progress)));
}

.drawer-wrapper[data-swiping] {
  transition: none;
}

html[data-drawer-scaled],
html[data-drawer-scaled] body {
  background: var(--drawer-canvas);
}

/* repositionInputs: above the on-screen keyboard, never taller than what shows. */
.dialog.drawer[data-direction="bottom"][data-keyboard] {
  bottom:     var(--drawer-keyboard);
  max-height: calc(100% - var(--drawer-keyboard) - var(--space-6));
}

.dialog.drawer[data-snap-points][data-direction="bottom"][data-keyboard] {
  height: calc(100% - var(--drawer-keyboard) - var(--space-6));
}

/* fixed (vaul): the top stays put and the panel ends at the keyboard; its
   content scrolls in the shorter box. */
.dialog.drawer[data-direction="bottom"][data-keyboard][data-fixed] {
  top:        var(--drawer-fixed-top);
  max-height: none;
}

/* A long unbroken title (a filename, a URL) wraps inside the panel. */
.drawer-title,
.drawer-description {
  min-width:     0;
  overflow-wrap: anywhere;
}

}
