:host {
  --_dropzone-min-height: var(--file-input-dropzone-min-height-md);
  --_dropzone-padding-block: var(--file-input-dropzone-padding-block-md);
  --_dropzone-padding-inline: var(--file-input-dropzone-padding-inline-md);
  --_dropzone-gap: var(--file-input-dropzone-gap-md);
  --_dropzone-radius: var(--file-input-dropzone-border-radius);
  --_dropzone-border-width: var(--file-input-dropzone-border-width-default);
  --_dropzone-transition-duration: var(--file-input-dropzone-transition-duration);
  --_dropzone-transition-easing: var(--file-input-dropzone-transition-timing-function);

  /* Icon-circle (background pill behind the cloud-upload glyph). */
  --_icon-circle-size: var(--file-input-dropzone-icon-circle-size-md);
  --_icon-circle-padding: var(--file-input-dropzone-icon-circle-padding-md);
  --_icon-circle-bg: var(--file-input-dropzone-icon-circle-background);
  --_icon-circle-bg-disabled: var(--file-input-dropzone-icon-circle-background-disabled);
  --_icon-glyph-size: var(--file-input-dropzone-icon-glyph-size-md);
  --_icon-glyph-color: var(--file-input-dropzone-icon-glyph-color);
  --_icon-glyph-color-disabled: var(--file-input-dropzone-icon-glyph-color-disabled);

  /* CTA row: lead-in body + inline brand-blue link. */
  --_cta-gap: var(--file-input-dropzone-cta-gap);
  --_cta-body-color: var(--file-input-dropzone-cta-body-color);
  --_cta-body-color-disabled: var(--file-input-dropzone-cta-body-color-disabled);
  --_cta-link-color: var(--file-input-dropzone-cta-link-color);
  --_cta-link-color-hover: var(--file-input-dropzone-cta-link-color-hover);
  --_cta-link-color-disabled: var(--file-input-dropzone-cta-link-color-disabled);

  --_primary-font-size: var(--file-input-primary-text-font-size-md);
  --_primary-line-height: var(--file-input-primary-text-line-height-md);

  --_bg: var(--file-input-background-default);
  --_bg-active: var(--file-input-background-active);
  --_text-primary: var(--file-input-text-primary);
  --_text-secondary: var(--file-input-text-secondary);
  --_border-color: var(--file-input-border-default);
  --_border-color-hover: var(--file-input-border-hover);
  --_border-color-focus: var(--file-input-border-focus);
  --_border-color-active: var(--file-input-border-active);

  display: flex;
  flex-direction: column;
  gap: var(--file-input-field-gap);
  inline-size: 100%;
  font-family: var(--file-input-primary-text-font-family);
  color: var(--_text-primary);
}

:host([size='lg']) {
  --_dropzone-min-height: var(--file-input-dropzone-min-height-lg);
  --_dropzone-padding-block: var(--file-input-dropzone-padding-block-lg);
  --_dropzone-padding-inline: var(--file-input-dropzone-padding-inline-lg);
  --_dropzone-gap: var(--file-input-dropzone-gap-lg);
  --_icon-circle-size: var(--file-input-dropzone-icon-circle-size-lg);
  --_icon-circle-padding: var(--file-input-dropzone-icon-circle-padding-lg);
  --_icon-glyph-size: var(--file-input-dropzone-icon-glyph-size-lg);
  --_primary-font-size: var(--file-input-primary-text-font-size-lg);
  --_primary-line-height: var(--file-input-primary-text-line-height-lg);
}

/* Invalid validation flag — recolors the dashed border to danger, swaps focus ring.
 * Not a style variant per Figma; a state-level recolor. */
:host([invalid]) {
  --_border-color: var(--file-input-border-invalid);
  --_border-color-hover: var(--file-input-border-invalid);
  --_border-color-focus: var(--file-input-border-invalid);
}

/* ---------- Label ---------- */

.label {
  display: flex;
  align-items: center;
  gap: var(--file-input-label-gap);
  font-family: var(--file-input-label-font-family);
  font-size: var(--file-input-label-font-size);
  line-height: var(--file-input-label-line-height);
  font-weight: var(--file-input-label-font-weight);
  color: var(--file-input-label-color-default);
  inline-size: 100%;
  min-inline-size: 0;
}

.label-text {
  display: block;
  min-inline-size: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.required-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: var(--file-input-label-required-mark-size);
  block-size: var(--file-input-label-required-mark-size);
  color: var(--file-input-label-required-mark-color);
  line-height: 1;
}

:host(.is-disabled) .label,
:host(.is-disabled) .required-mark {
  color: var(--file-input-label-color-disabled);
}

:host(:not(.has-label)) .label {
  display: none;
}

/* ---------- Drop zone ---------- */

.dropzone {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  gap: var(--_dropzone-gap);
  min-block-size: var(--_dropzone-min-height);
  padding-block: var(--_dropzone-padding-block);
  padding-inline: var(--_dropzone-padding-inline);
  background-color: var(--_bg);
  /* The dashed affordance is an outline pulled inside the box rather than a
     border. A Figma stroke sits inside the frame and moves nothing, while a CSS
     border would add its width to the height — 2px taller than 262:6717 — and
     a 1.5px border is floored to 1px by Chromium anyway. `outline` takes the
     dash, honours the radius, and stays out of the layout. */
  outline: var(--_dropzone-border-width) dashed var(--_border-color);
  outline-offset: calc(-1 * var(--_dropzone-border-width));
  border-radius: var(--_dropzone-radius);
  text-align: center;
  cursor: pointer;
  user-select: none;
  transition:
    outline-color var(--_dropzone-transition-duration) var(--_dropzone-transition-easing),
    background-color var(--_dropzone-transition-duration) var(--_dropzone-transition-easing),
    box-shadow var(--_dropzone-transition-duration) var(--_dropzone-transition-easing);
}

/* `.is-hover-demo` is a Storybook-only helper that statically paints the hover
   border (real hover still works via `:hover`). */
:host(:not(.is-disabled):not(.is-focused):not(.is-active):hover) .dropzone,
:host(.is-hover-demo:not(.is-disabled)) .dropzone {
  outline-color: var(--_border-color-hover);
}

/* Figma 616:7146 leaves the resting dashed stroke alone and rings the drop zone
   with the shared two-band focus ring. `.is-focus-demo` mirrors it for static
   story capture. */
:host(.is-focused:not(.is-disabled)) .dropzone,
:host(.is-focus-demo:not(.is-disabled)) .dropzone {
  box-shadow:
    0 0 0 var(--file-input-focus-ring-width-inner) var(--focus-ring-color-inner),
    0 0 0 calc(var(--file-input-focus-ring-width-inner) + var(--file-input-focus-ring-width-outer))
      var(--focus-ring-color-outer);
}

/* Figma "Active" state — drag-over (262:6720). The one variant whose stroke is
   solid, over the brand-tinted fill. */
:host(.is-active:not(.is-disabled)) .dropzone {
  outline-style: solid;
  outline-color: var(--_border-color-active);
  background-color: var(--_bg-active);
}

:host(.is-disabled) .dropzone {
  background-color: var(--file-input-background-disabled);
  outline-color: var(--file-input-border-disabled);
  cursor: not-allowed;
}

/* ---------- Centre icon circle (Figma: 48×48 pill at lg, 40×40 at md) ---------- */

.dropzone-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  inline-size: var(--_icon-circle-size);
  block-size: var(--_icon-circle-size);
  padding: var(--_icon-circle-padding);
  background-color: var(--_icon-circle-bg);
  border-radius: var(--border-radius-full);
  color: var(--_icon-glyph-color);
  box-sizing: border-box;
}

.dropzone-icon mud-icon {
  inline-size: var(--_icon-glyph-size);
  block-size: var(--_icon-glyph-size);
}

:host(.is-disabled) .dropzone-icon {
  background-color: var(--_icon-circle-bg-disabled);
  color: var(--_icon-glyph-color-disabled);
}

/* Slotted custom icon inherits the themed color. */
::slotted([slot='icon']) {
  color: inherit;
}

.dropzone-body {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--spacing-4);
  min-inline-size: 0;
}

.dropzone-text {
  display: block;
  font-size: var(--_primary-font-size);
  line-height: var(--_primary-line-height);
  font-weight: var(--file-input-primary-text-font-weight);
  color: var(--_text-primary);
}

/* Figma Active: body text stays at ink primary (no accent recolor). */
:host(.is-active:not(.is-disabled)) .dropzone-text {
  color: var(--_text-primary);
}

:host(.is-disabled) .dropzone-text {
  color: var(--file-input-text-disabled);
}

/* ---------- CTA row: "Drag and drop or [choose files]" ---------- */

.dropzone-cta {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: var(--_cta-gap);
  font-size: var(--_primary-font-size);
  line-height: var(--_primary-line-height);
  font-weight: var(--file-input-primary-text-font-weight);
}

.dropzone-cta__body {
  color: var(--_cta-body-color);
}

:host(.is-disabled) .dropzone-cta__body {
  color: var(--_cta-body-color-disabled);
}

/* Inline link affordance — a real <button> for keyboard + a11y, styled as a
 * brand-blue underlined link. Padding-free so it inlines with the body text. */
.dropzone-cta__link {
  appearance: none;
  background: none;
  border: 0;
  padding: 0;
  margin: 0;
  font: inherit;
  color: var(--_cta-link-color);
  text-decoration: underline;
  text-underline-offset: var(--file-input-dropzone-cta-link-underline-offset);
  cursor: pointer;
}

.dropzone-cta__link:hover {
  color: var(--_cta-link-color-hover);
}

/* Figma 616:7146 rings the drop zone and nothing else. The link is what the
   keyboard reaches, and its focus is what raises `.is-focused` on the host, so
   an outline here would draw a second indicator inside the first. */
.dropzone-cta__link:focus-visible {
  outline: none;
}

:host(.is-disabled) .dropzone-cta__link,
.dropzone-cta__link:disabled {
  color: var(--_cta-link-color-disabled);
  cursor: not-allowed;
  text-decoration-color: var(--_cta-link-color-disabled);
}

/* ---------- Captions row (outside the dashed border, below the dropzone) ---------- */

.captions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--file-input-caption-gap);
  /* Figma 262:6717 puts 12px between the drop zone and the captions. The host is
     a flex column whose own gap already contributes `field-gap`, so the margin
     carries only the remainder and the token stays the Figma number. */
  margin-block-start: calc(var(--file-input-caption-margin-block-start) - var(--file-input-field-gap));
  font-family: var(--file-input-caption-font-family);
  font-size: var(--file-input-caption-font-size);
  line-height: var(--file-input-caption-line-height);
  font-weight: var(--file-input-caption-font-weight);
  color: var(--file-input-caption-color-default);
  inline-size: 100%;
  min-inline-size: 0;
}

/* At the 588px Figma draws (262:6711) both captions sit on one row, the first
   filling it. Narrower than that, the second drops to its own line instead of
   squeezing the first to an ellipsis — the max-size fact is short and the
   formats list is the one worth reading. */
.captions__formats {
  flex: 1 1 auto;
  min-inline-size: 0;
  text-align: start;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.captions__max-size {
  flex-shrink: 0;
  margin-inline-start: auto;
  text-align: end;
  white-space: nowrap;
}

:host(.is-disabled) .captions {
  color: var(--file-input-caption-color-disabled);
}

/* ---------- Upload-button variant ---------- */

/* Button hugs its content instead of stretching the full field width. */
.upload-button {
  align-self: flex-start;
}

/* In button mode the captions sit above the button as one left-aligned line
   (wrapping rather than truncating, since there's no fixed dropzone width). */
.captions--inline {
  justify-content: flex-start;
  flex-wrap: wrap;
  gap: var(--spacing-4) var(--spacing-8);
  margin-block-start: 0;
}

.captions--inline .captions__formats {
  flex: 0 1 auto;
  overflow: visible;
  text-overflow: clip;
  white-space: normal;
}

/* ---------- Native hidden input ---------- */

.native {
  position: absolute;
  inline-size: 1px;
  block-size: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
  pointer-events: none;
}

/* ---------- File list ---------- */

.file-list {
  display: flex;
  flex-direction: column;
  gap: var(--file-input-list-gap);
  margin: 0;
  margin-block-start: var(--file-input-list-margin-block-start);
  padding: 0;
  list-style: none;
  inline-size: 100%;
}

.file-list-item {
  display: block;
}

/* ---------- Assistive (helper / error) ---------- */

.assistive {
  display: flex;
  align-items: flex-start;
  gap: var(--file-input-assistive-gap-default);
  font-family: var(--file-input-assistive-font-family);
  font-size: var(--file-input-assistive-font-size);
  line-height: var(--file-input-assistive-line-height);
  font-weight: var(--file-input-assistive-font-weight);
  color: var(--file-input-assistive-color-default);
  inline-size: 100%;
  min-inline-size: 0;
}

.assistive-error {
  gap: var(--file-input-assistive-gap-error);
  color: var(--file-input-assistive-color-error);
}

.assistive-icon {
  flex-shrink: 0;
  inline-size: var(--file-input-assistive-icon-size);
  block-size: var(--file-input-assistive-icon-size);
  margin-block-start: 0;
}

.assistive-text {
  flex: 1 1 auto;
  min-inline-size: 0;
  overflow: hidden;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  text-overflow: ellipsis;
}

/* ---------- Live region ---------- */

.visually-hidden {
  position: absolute;
  inline-size: 1px;
  block-size: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ---------- prefers-reduced-motion ---------- */

@media (prefers-reduced-motion: reduce) {
  .dropzone {
    transition: none;
  }
}
