@layer components {
  .fieldset {
    display: flex;
    flex-direction: column;
    gap: var(--block-space-half);
  }

  /* Hint text under an input ("Comma-separated…"). Pulls itself back against
     the input by countering the fieldset's flex gap, so notes hug their field
     with no extra vertical space. */
  .fieldset__note {
    color: var(--color-ink-dark);
    font-size: var(--text-small);
    margin-block-start: calc(var(--block-space-half) * -0.75);
  }

  /* Direct-upload gallery: existing + staged thumbnails + an "add" tile */
  .upload {
    border: 2px dashed var(--color-ink-light);
    border-radius: 0.75em;
    padding: var(--block-space);
    transition: border-color 150ms ease, background-color 150ms ease;
  }

  .upload--dragover {
    background-color: var(--color-selected);
    border-color: var(--color-link);
  }

  .upload--error {
    border-color: var(--color-negative);
  }

  .upload__input {
    display: none;
  }

  .upload__grid {
    display: flex;
    flex-wrap: wrap;
    gap: var(--block-space-half);
  }

  .upload__add {
    align-items: center;
    background: none;
    block-size: 5rem;
    border: 2px dashed var(--color-ink-light);
    border-radius: 0.5em;
    color: var(--color-ink-medium);
    cursor: pointer;
    display: flex;
    flex-direction: column;
    gap: 0.1em;
    inline-size: 5rem;
    justify-content: center;

    @media (any-hover: hover) {
      &:hover {
        border-color: var(--color-link);
        color: var(--color-link);
      }
    }
  }

  .upload__add-icon {
    font-size: 1.5rem;
    line-height: 1;
  }

  /* Staged selections become direct children of the grid, uniform with existing */
  .upload__preview {
    display: contents;
  }

  /* Staged (selected, not-yet-uploaded) files, each removable before submit */
  .upload__staged {
    block-size: 5rem;
    border-radius: 0.5em;
    inline-size: 5rem;
    overflow: hidden;
    position: relative;

    img {
      block-size: 100%;
      inline-size: 100%;
      object-fit: cover;
    }
  }

  .upload__staged-remove {
    align-items: center;
    background-color: oklch(var(--lch-black) / 55%);
    border: 0;
    border-radius: 50%;
    block-size: 1.4em;
    color: white;
    cursor: pointer;
    display: flex;
    font-size: 1rem;
    inline-size: 1.4em;
    inset-block-start: 0.25rem;
    inset-inline-end: 0.25rem;
    justify-content: center;
    line-height: 1;
    padding: 0;
    position: absolute;
  }

  .upload__progress {
    background-color: var(--color-ink-lightest);
    block-size: 0.4rem;
    border-radius: 99rem;
    margin-block-start: var(--block-space-half);
    overflow: hidden;
  }

  .upload__bar {
    background-color: var(--color-link);
    block-size: 100%;
    inline-size: 0;
    transition: inline-size 150ms ease;
  }

  /* Existing attachment tiles, with a mark-to-remove toggle (applied on save) */
  .upload__file {
    align-items: center;
    block-size: 5rem;
    border-radius: 0.5em;
    cursor: pointer;
    display: flex;
    inline-size: 5rem;
    justify-content: center;
    overflow: hidden;
    position: relative;

    img {
      block-size: 100%;
      inline-size: 100%;
      object-fit: cover;
    }
  }

  .upload__filename {
    padding: var(--block-space-half);
    text-align: center;
    word-break: break-word;
  }

  .upload__remove-check {
    position: absolute;
    opacity: 0;
    pointer-events: none;
  }

  .upload__remove {
    align-items: center;
    background-color: oklch(var(--lch-black) / 55%);
    block-size: 1.4em;
    border-radius: 50%;
    color: white;
    display: flex;
    font-size: 1rem;
    inline-size: 1.4em;
    inset-block-start: 0.25rem;
    inset-inline-end: 0.25rem;
    justify-content: center;
    line-height: 1;
    position: absolute;
  }

  /* Marked for removal → dim + strike so it's clear it'll go on save */
  .upload__file:has(.upload__remove-check:checked) {
    outline: 2px solid var(--color-negative);

    img,
    .upload__filename {
      filter: grayscale(1);
      opacity: 0.45;
    }

    .upload__remove {
      background-color: var(--color-negative);
    }
  }

  .input {
    accent-color: var(--input-accent-color, var(--color-ink));
    background-color: var(--input-background, transparent);
    border-radius: var(--input-border-radius, 0.5em);
    border: var(--input-border-size, 1px) solid var(--input-border-color, var(--color-ink-medium));
    color: var(--input-color, var(--color-ink));
    font-size: max(16px, 1em);
    inline-size: 100%;
    line-height: inherit;
    max-inline-size: var(--input-max-width, 30em);
    padding: var(--input-padding, 0.5em 0.8em);
    resize: none;

    &:autofill,
    &:-webkit-autofill,
    &:-webkit-autofill:hover,
    &:-webkit-autofill:focus {
      -webkit-text-fill-color: var(--color-ink);
      -webkit-box-shadow: 0 0 0px 1000px var(--color-selected) inset;
    }

    &:where(:focus) {
      --focus-ring-offset: -1px;
    }

    &[readonly] {
      --focus-ring-size: 0;
    }

    &[type='number'] {
      &::-webkit-outer-spin-button,
      &::-webkit-inner-spin-button {
        -webkit-appearance: none;
        margin: 0;
      }
    }

    @supports (hanging-punctuation: first) and (font: -apple-system-body) and (-webkit-appearance: none) {
      @media (hover: none) {
        font-size: max(16px, 1em) !important;
      }
    }

    &.input--invalid {
      --input-border-color: var(--color-negative);
    }
  }

  .field-error {
    color: var(--color-negative);
    font-size: var(--text-small);
    margin: 0;
  }

  .input--select {
    --input-border-radius: 2em;
    --input-padding: 0.5em 1.8em 0.5em 1.2em;
    --caret-icon: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='m12 19.5c-.7 0-1.3-.3-1.7-.8l-9.8-11.1c-.7-.8-.6-1.9.2-2.6.8-.6 1.9-.6 2.5.2l8.6 9.8c0 .1.2.1.4 0l8.6-9.8c.7-.8 1.8-.9 2.6-.2s.9 1.8.2 2.6l-9.8 11.1c-.4.5-1.1.8-1.7.8z' fill='%23000'/%3E%3C/svg%3E");
    --caret-icon-dark: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='m12 19.5c-.7 0-1.3-.3-1.7-.8l-9.8-11.1c-.7-.8-.6-1.9.2-2.6.8-.6 1.9-.6 2.5.2l8.6 9.8c0 .1.2.1.4 0l8.6-9.8c.7-.8 1.8-.9 2.6-.2s.9 1.8.2 2.6l-9.8 11.1c-.4.5-1.1.8-1.7.8z' fill='%23fff'/%3E%3C/svg%3E");

    -webkit-appearance: none;
    appearance: none;
    background-image: var(--caret-icon);
    background-size: 0.5em;
    background-position: center right 0.9em;
    background-repeat: no-repeat;
    text-align: start;

    html[data-theme="dark"] & {
      --caret-icon: var(--caret-icon-dark);
    }

    @media (prefers-color-scheme: dark) {
      html:not([data-theme]) & {
        --caret-icon: var(--caret-icon-dark);
      }
    }

    option {
      background-color: var(--color-canvas);
      color: var(--color-ink);
    }
  }

  .input--textarea {
    --input-padding: 0.5em 0.8em;
    /* Free text gets more room than single-line inputs, but still caps out
       near a comfortable prose measure. */
    --input-max-width: 45em;

    line-height: inherit;
    min-block-size: 6em;
    min-inline-size: 100%;

    @supports (field-sizing: content) {
      field-sizing: content;
      max-block-size: 20em;
      min-block-size: 3em;
    }
  }

  /* Toggle switch */
  .switch {
    --switch-color: var(--color-ink-medium);

    block-size: 1.75em;
    border-radius: 2em;
    display: inline-flex;
    inline-size: 3em;
    position: relative;

    &:has(:focus-visible) {
      .switch__btn {
        outline: var(--focus-ring-size) solid var(--focus-ring-color);
      }
    }
  }

  .switch__input {
    block-size: 0;
    inline-size: 0;
    opacity: 0.1;
  }

  .switch__btn {
    background-color: var(--switch-color);
    border-radius: 2em;
    cursor: pointer;
    inset: 0;
    outline-offset: var(--focus-ring-offset);
    position: absolute;
    transition: 150ms ease;

    &::before {
      background-color: var(--color-ink-inverted);
      block-size: 1.35em;
      border-radius: 50%;
      content: "";
      inline-size: 1.35em;
      inset-block-end: 0.2em;
      inset-inline-start: 0.2em;
      position: absolute;
      transition: 150ms ease;
    }

    @media (any-hover: hover) {
      &:hover {
        background-color: color-mix(in srgb, var(--switch-color) 80%, var(--color-ink));
      }
    }

    .switch__input:checked + & {
      --switch-color: var(--color-link);

      &::before {
        transform: translateX(1.2em);
      }
    }

    .switch__input:disabled + & {
      cursor: not-allowed;
      opacity: 0.5;
    }
  }

  /* Checkbox */
  .checkbox {
    appearance: none;
    background-color: var(--color-canvas);
    block-size: 1.1em;
    border: 1px solid currentColor;
    border-radius: 0.15em;
    color: currentColor;
    display: grid;
    font: inherit;
    inline-size: 1.1em;
    margin: 0;
    place-content: center;
    transform: translateY(0.1em);

    &::before {
      background-color: CanvasText;
      block-size: 0.65em;
      box-shadow: inset 1em 1em currentColor;
      clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%);
      content: "";
      inline-size: 0.65em;
      transform: scale(0);
      transform-origin: center;
      transition: 150ms transform ease-in-out;
    }

    &:checked::before {
      transform: scale(1) rotate(10deg);
    }

    &:where([disabled]):not(:hover):not(:active) {
      filter: none;
      opacity: 0.5;
    }
  }
}
