/*
FileUpload

A dropzone surface with a trigger, then the accepted files and the rejected
ones as rows. Dragging over the dropzone changes its border and fill only;
reading shows a spinner over the trigger's hidden label (the width holds);
upload progress is a bar overlaid on a row's bottom edge. A row is a fixed
height from the item tier, its error line included, so nothing moves when
a row gains a progress bar or an error.

  .file-upload                  root (data-dragging, data-disabled, data-readonly, data-invalid, data-reading)
  .file-upload-dropzone         the drop target (data-dragging)
  .file-upload-trigger          "Browse files"
  .file-upload-input            the real <input type=file>, visually hidden
  .file-upload-list             accepted (data-type="accepted") or rejected rows
  .file-upload-item             a row (data-type, data-kind)
  .file-upload-item-preview     image thumbnail or a kind icon
  .file-upload-item-progress    the progress overlay (--progress)
  .file-upload-clear            clears every file
*/

@layer components {

.file-upload {
  --file-upload-thumb: calc(var(--item-height) * 1.25);

  display:        flex;
  flex-direction: column;
  gap:            var(--space-3);
  width:          100%;
  min-width:      0;
}

.file-upload-input {
  position:   absolute;
  width:      1px;
  height:     1px;
  margin:     -1px;
  padding:    0;
  overflow:   hidden;
  clip:       rect(0 0 0 0);
  white-space: nowrap;
  border:     0;
}

/* Dropzone */

.file-upload-dropzone {
  display:         flex;
  flex-direction:  column;
  align-items:     center;
  justify-content: center;
  gap:             var(--space-2);
  box-sizing:      border-box;
  min-height:      calc(var(--control-height) * 4);
  padding:         var(--surface-padding-sm);
  border:          calc(var(--control-border-width) * 2) dashed var(--control-border);
  border-radius:   var(--radius-surface);
  background:      var(--control-bg);
  color:           var(--ink-soft);
  text-align:      center;
  cursor:          pointer;
  transition:      border-color var(--duration-fast) var(--ease-out),
                   background-color var(--duration-fast) var(--ease-out);
}

.file-upload-dropzone:hover {
  border-color: var(--rule-strong);
}

.file-upload-dropzone:focus-visible {
  outline:      none;
  border-color: var(--focus);
  box-shadow:   var(--focus-ring);
}

.file-upload-dropzone[data-dragging] {
  border-color: var(--accent);
  background:   var(--accent-soft);
}

.file-upload[data-invalid] .file-upload-dropzone {
  border-color: var(--danger);
}

.file-upload[data-disabled] .file-upload-dropzone {
  opacity: var(--opacity-disabled);
  cursor:  not-allowed;
}

.file-upload[data-readonly] .file-upload-dropzone,
.file-upload-dropzone[data-disable-click] {
  cursor: default;
}

.file-upload-dropzone-icon {
  display:       inline-grid;
  place-items:   center;
  width:         var(--control-height);
  height:        var(--control-height);
  border-radius: var(--radius-pill);
  background:    var(--bg-muted);
  color:         var(--ink-soft);
}

.file-upload-dropzone-icon .icon {
  width:  var(--icon-size-lg);
  height: var(--icon-size-lg);
}

.file-upload-dropzone-title {
  margin:      0;
  color:       var(--ink);
  font-family: var(--font-ui);
  font-size:   var(--text-ui);
  font-weight: var(--weight-ui);
}

.file-upload-dropzone-hint {
  margin:    0;
  color:     var(--ink-dim);
  font-size: var(--text-caption);
}

/* The trigger is a Button-shaped element; the spinner overlays its kept label. */
.file-upload-trigger {
  position: relative;
}

.file-upload-trigger-label {
  display:     inline-flex;
  align-items: center;
  gap:         var(--control-gap);
}

.file-upload[data-reading] .file-upload-trigger-label {
  visibility: hidden;
}

.file-upload-spinner {
  position:      absolute;
  inset:         0;
  margin:        auto;
  width:         var(--icon-size);
  height:        var(--icon-size);
  border:        calc(var(--icon-stroke) * 1px) solid currentColor;
  border-top-color: transparent;
  border-radius: var(--radius-pill);
  animation:     file-upload-spin calc(var(--duration-loop) * 1.4) linear infinite;
}

@keyframes file-upload-spin {
  to { transform: rotate(1turn); }
}

/* List */

.file-upload-header {
  display:         flex;
  align-items:     center;
  justify-content: space-between;
  gap:             var(--space-2);
  color:           var(--ink-soft);
  font-size:       var(--text-caption);
}

.file-upload-list {
  display:        flex;
  flex-direction: column;
  gap:            var(--space-2);
  margin:         0;
  padding:        0;
  list-style:     none;
}

.file-upload-item {
  position:      relative;
  display:       grid;
  grid-template-columns: var(--file-upload-thumb) minmax(0, 1fr) auto;
  align-items:   center;
  gap:           var(--item-gap) var(--space-3);
  box-sizing:    border-box;
  min-height:    calc(var(--file-upload-thumb) + 2 * var(--space-2));
  padding:       var(--space-2);
  padding-inline-end: var(--space-1);
  overflow:      hidden;
  border:        var(--surface-border-width) solid var(--surface-border);
  border-radius: var(--radius-control);
  background:    var(--surface-bg);
}

.file-upload-item[data-type="rejected"] {
  border-color: color-mix(in srgb, var(--danger) 50%, var(--surface-border));
}

.file-upload-item-preview {
  display:       inline-grid;
  place-items:   center;
  width:         var(--file-upload-thumb);
  height:        var(--file-upload-thumb);
  overflow:      hidden;
  border-radius: var(--radius-item);
  background:    var(--bg-muted);
  color:         var(--ink-soft);
}

.file-upload-item-preview img {
  width:      100%;
  height:     100%;
  object-fit: cover;
}

.file-upload-item-preview .icon {
  width:  var(--icon-size);
  height: var(--icon-size);
}

.file-upload-item-body {
  display:        flex;
  flex-direction: column;
  gap:            0;
  min-width:      0;
}

.file-upload-item-name {
  overflow:      hidden;
  color:         var(--ink);
  font-family:   var(--font-ui);
  font-size:     var(--text-ui);
  font-weight:   var(--weight-ui);
  text-overflow: ellipsis;
  white-space:   nowrap;
}

.file-upload-item-size,
.file-upload-item-error {
  overflow:      hidden;
  font-size:     var(--text-caption);
  text-overflow: ellipsis;
  white-space:   nowrap;
}

.file-upload-item-size {
  color:                var(--ink-dim);
  font-variant-numeric: tabular-nums;
}

.file-upload-item-error {
  color: var(--danger);
}

.file-upload-item-delete,
.file-upload-clear {
  display:         inline-grid;
  place-items:     center;
  margin:          0;
  padding:         0;
  border:          0;
  border-radius:   var(--radius-control);
  background:      transparent;
  color:           var(--ink-dim);
  cursor:          pointer;
}

.file-upload-item-delete {
  width:  var(--control-height-sm);
  height: var(--control-height-sm);
}

.file-upload-clear {
  padding:        0 var(--space-2);
  height:         var(--control-height-sm);
  font-family:    var(--font-ui);
  font-size:      var(--text-ui-sm);
  font-weight:    var(--weight-ui);
  letter-spacing: var(--tracking-ui);
  text-transform: var(--case-ui);
}

/* Disabled or read-only: the buttons stay in layout, disabled, so a row
   and the header keep their size when the state changes. */
.file-upload-item-delete:disabled,
.file-upload-clear:disabled {
  opacity: var(--opacity-disabled);
  cursor:  not-allowed;
}

.file-upload-item-delete:not(:disabled):hover,
.file-upload-clear:not(:disabled):hover {
  background: var(--item-highlight);
  color:      var(--item-highlight-ink);
}

.file-upload-item-delete:focus-visible,
.file-upload-clear:focus-visible {
  outline:    none;
  box-shadow: var(--focus-ring);
}

.file-upload-item-delete .icon {
  width:  var(--icon-size);
  height: var(--icon-size);
}

.file-upload-item-progress {
  position:   absolute;
  inset-inline: 0;
  bottom:     0;
  height:     calc(var(--control-border-width) * 3);
  background: var(--bg-muted);
}

.file-upload-item-progress::after {
  content:          "";
  position:         absolute;
  inset-block:      0;
  inset-inline-start: 0;
  width:            100%;
  background:       var(--accent);
  transform:        scaleX(calc(var(--progress) / 100));
  transform-origin: left;
  transition:       transform var(--duration-normal) var(--ease-out);
}

.file-upload-item-progress:dir(rtl)::after {
  transform-origin: right;
}

}
