/* Text inputs */
.input {
  accent-color: var(--input-accent-color, var(--color-text));
  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-border-darker));
  color: var(--input-color, var(--color-text));
  font-size: max(16px, 1em);
  inline-size: 100%;
  padding: var(--input-padding, 0.5em 0.8em);
  resize: none;

  &:disabled {
    cursor: not-allowed;
    color: var(--color-border-darker);
    background-color: var(--color-bg-sunk);
    filter: brightness(1);
  }

  &[type="search"] {
    &::-webkit-search-decoration,
    &::-webkit-search-results-button,
    &::-webkit-search-results-decoration {
      display: none;
    }
  }

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

}

/* The v2.1 field primitive: hover darkens the border, focus paints the accent
   border plus a 3px accent-bd ring. The composer and search "actor" inputs draw
   their own border and glow, and the message editor (.lexxy-content) rides
   inside one, so all three opt out. Fields sit at 14px, bumping to 16px under
   the mobile drawer so iOS Safari never zooms in on focus. */
.input:not(.input--actor):not(.lexxy-content) {
  font-size: 14px;
  padding: 9px 11px;

  &:hover:not(:disabled) {
    border-color: var(--color-text-subtle);
  }

  &:focus-visible {
    border-color: var(--color-accent-brand);
    box-shadow: 0 0 0 3px var(--color-selected-dark);
    outline: none;
  }
}

@media (max-width: 833px) {
  .input:not(.input--actor):not(.lexxy-content) {
    font-size: 16px;
  }
}

/* Placeholders are hints, not values: a step lighter than muted text so a
   suggested name never reads as one that was typed. */
input::placeholder,
textarea::placeholder {
  color: var(--color-text-subtle);
  opacity: 1;
}

input[type="checkbox"]:not(.switch__input),
input[type="radio"] {
  --outline-size: min(0.2em, 2px);

  background-color: var(--color-bg);
  block-size: var(--control-size, 1.075em);
  border: 1.5px solid var(--color-border-darker);
  border-radius: 0.35em;
  cursor: pointer;
  display: grid;
  flex-shrink: 0;
  inline-size: var(--control-size, 1.075em);
  margin: 0;
  place-items: center;
  position: relative;
  print-color-adjust: exact;
  transition: border-color 150ms ease, background-color 150ms ease, box-shadow 150ms ease;
  user-select: none;
}

input[type="checkbox"]:not(.switch__input)::after,
input[type="radio"]::after {
  content: "";
  display: block;
  transition: transform 150ms cubic-bezier(0.25, 1, 0.5, 1);

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

input[type="checkbox"]:not(.switch__input) {
  border-radius: 0.35em;
}

input[type="checkbox"]:not(.switch__input)::after {
  block-size: 0.55em;
  border-inline-end: 0.18em solid var(--color-bg);
  border-block-end: 0.18em solid var(--color-bg);
  inline-size: 0.3em;
  transform: rotate(45deg) scale(0);
  transform-origin: center;
}

input[type="checkbox"]:not(.switch__input):checked {
  background-color: var(--color-text);
  border-color: var(--color-text);
  color: var(--color-bg);
}

input[type="checkbox"]:not(.switch__input):checked::after {
  transform: rotate(45deg) scale(1);
}

input[type="checkbox"]:not(.switch__input):focus-visible,
input[type="radio"]:focus-visible {
  outline-offset: 0.15em;
}

input[type="radio"] {
  border-radius: 50%;
}

input[type="radio"]::after {
  background-color: currentColor;
  block-size: 45%;
  border-radius: 50%;
  inline-size: 45%;
  transform: scale(0);
}

input[type="radio"]:checked {
  background-color: var(--color-text);
  border-color: var(--color-text);
  color: var(--color-bg);
}

input[type="radio"]:checked::after {
  transform: scale(1);
}

input[type="checkbox"]:not(.switch__input):disabled,
input[type="radio"]:disabled {
  background-color: var(--color-border);
  border-color: var(--color-border-dark);
  color: var(--color-border-darker);
  cursor: not-allowed;
  filter: none;
}

input[type="checkbox"]:not(.switch__input):disabled::after,
input[type="radio"]:disabled::after {
  border-color: var(--color-border-darker);
  background-color: var(--color-border-darker);
}

/* Room-type picker: three selectable cards; the radio itself is visually
   hidden and the checked state paints the card accent. */
.room-type-grid {
  display: grid;
  gap: 8px;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  margin-block-end: 18px;

  @media (max-width: 480px) {
    grid-template-columns: 1fr;
  }
}

.room-type-card {
  border: 1px solid var(--color-border);
  border-radius: 11px;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  gap: 5px;
  padding: 12px 11px;

  &:has(input:checked) {
    background-color: var(--color-selected);
    border-color: var(--color-accent-brand);

    .room-type-card__head {
      color: var(--color-accent-brand);
    }
  }

  &:has(input:focus-visible) {
    outline: 2px solid var(--color-link);
    outline-offset: 2px;
  }
}

.room-type-card__head {
  align-items: center;
  display: inline-flex;
  font-size: 0.84375rem;
  font-weight: 700;
  gap: 7px;
}

.room-type-card__blurb {
  color: var(--color-text-muted);
  font-size: 0.75rem;
  line-height: 1.45;
}

.input--transparent {
  --input-border-color: currentColor;
  --input-color: currentColor;
  --input-background: transparent;
}

.input--actor {
  transition:
    box-shadow 150ms ease,
    outline-offset 150ms ease;

  &:focus-within {
    --input-border-color: var(--color-selected-dark);
    --hover-color: var(--color-selected-dark);
    --outline-size: 0;

    filter: var(--hover-filter);
    box-shadow: 0 0 0 var(--hover-size) var(--hover-color);
  }

  .input {
    --input-padding: 0;
    --input-border-radius: 0;
    --input-background: transparent;
    --input-border-size: 0;
    --hover-size: 0;
    --outline-size: 0;
    --outline-color: transparent;

    outline: 0;
  }

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

  .btn:not(.avatar) {
    margin-block: -0.4em;

    &:last-child {
      margin-inline-end: -0.7em;
    }
  }

  .btn--reversed img {
    inline-size: 1em;
  }
}

/* An actor input draws no focus ring of its own: the wrapper's :focus-within
   glow is the field's focus indicator, and the inner input riding inside it is
   transparent. The base .input:focus-visible rule above paints a border and a
   ring, and on keyboard focus it out-specifies the actor's own inner reset — so
   without this an actor field shows two rings at once, the inner input's inside
   the wrapper's, in two different accent tints. Matched at the base rule's
   specificity and placed after it, so it wins by source order. */
.input--actor .input:not(.lexxy-content):focus-visible {
  border-color: transparent;
  box-shadow: none;
}

.input--file {
  input[type="file"] {
    --hover-size: 0;

    block-size: 100%;
    border: 0;
    border-radius: 50%;
    inline-size: 100%;
    overflow: clip;
    padding: 0;

    &::file-selector-button {
      appearance: none;
      cursor: pointer;
      opacity: 0;
    }
  }

  &:not(.avatar) {
    img {
      inline-size: 1.6em;
    }
  }
}

/* Switches — v2: 38×22 pill, accent track when on */
.switch {
  block-size: 22px;
  display: inline-flex;
  inline-size: 38px;
  position: relative;
  border-radius: 2em;

  @media (hover: hover) and (pointer: fine) {
    &:where(:not(:active):hover) .switch__btn {
      filter: brightness(0.7);
      box-shadow: none;
    }
  }

  &:focus-within .switch__btn {
    --shadow-size: min(0.2em, 2px);

    box-shadow:
      0 0 0 var(--shadow-size) var(--color-bg),
      0 0 0 calc(var(--shadow-size) * 2) var(--color-link);
  }
}

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

/* Settings toggle row: label + hint stack on the left, switch flush-right.
   Whole row is the click target. */
.setting-row {
  align-items: center;
  cursor: default;
  display: flex;
  gap: var(--inline-space);
  justify-content: space-between;
  padding-block: var(--block-space-half);
  text-align: start;
}

/* Link/button rows navigate as a whole, so the pointer covers the text too. A
   toggle row is a <label>, but its descriptive text is content, not a control —
   the pointer belongs on the switch (.switch__btn carries its own), so the row
   itself keeps the default arrow. A plain <div> row (the accent picker) does the
   same. */
a.setting-row,
button.setting-row {
  cursor: pointer;
}

.setting-row__text {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
}

.setting-row__title {
  font-size: 0.90625rem;
  font-weight: 600;
}

/* Every other .setting-row ends in a switch, button, or link that carries its
   own colour. A row that states a fact ends in text, so it takes the same
   secondary treatment the hint text uses elsewhere in settings rather than
   inventing a third one. */
.setting-row__value {
  color: var(--color-text-muted);
  flex-shrink: 0;
  font-size: var(--font-size-small);
  text-align: end;
}

/* A second line under the title — the row's current value or a one-line
   explanation — in the hint colour the rest of settings uses. */
.setting-row__hint {
  color: var(--color-text-subtle);
  font-size: 0.78125rem;
  line-height: 1.45;
}

.setting-row__link {
  color: var(--color-accent-brand);
}

.setting-row__sep {
  color: var(--color-text-subtle);
  padding-inline: 0.25em;
}

.setting-row .switch {
  flex-shrink: 0;
  margin-inline-start: var(--block-space);
}

/* On the narrowest phones a trailing control plus its label can exceed the row
   width. Let the row wrap so the control drops to its own line instead of
   overflowing — still flush right, where it sits on a row wide enough not to
   wrap, so a column of rows keeps one edge to read down. */
@media (max-width: 480px) {
  .setting-row {
    flex-wrap: wrap;
  }

  .setting-row__text ~ :last-child {
    margin-inline-start: auto;
  }
}

.switch__btn {
  background-color: var(--color-border-darker);
  border-radius: 2em;
  cursor: pointer;
  inset: 0;
  position: absolute;
  transition: background-color 200ms cubic-bezier(0.25, 1, 0.5, 1);

  &::before {
    /* knob stays white on the accent track in both themes */
    background-color: oklch(100% 0 0);
    block-size: 18px;
    border-radius: 50%;
    box-shadow: 0 1px 2px oklch(var(--lch-always-black) / 0.25);
    content: "";
    inline-size: 18px;
    inset-block-end: 2px;
    inset-inline-start: 2px;
    position: absolute;
    transition: transform 200ms cubic-bezier(0.25, 1, 0.5, 1);

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

  .switch__input:disabled + & {
    background-color: var(--color-border-darker) !important;
    cursor: not-allowed;
    opacity: 0.4;
  }

  .switch__input:checked + & {
    background-color: var(--color-accent-brand);

    &::before {
      transform: translateX(16px);
    }
  }
}

/* Selects drop the native widget and draw their own chevron; the stroke is a
   mid grey that reads on both themes because a data-URI image cannot take a
   token. Multi-selects keep the plain list box. */
select {
  accent-color: var(--input-accent-color, var(--color-text));
  appearance: none;
  background-color: var(--input-background, transparent);
  background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='oklch(55.1%25 0.027 264.364)' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e");
  background-position: right 0.5rem center;
  background-repeat: no-repeat;
  background-size: 1.5em 1.5em;
  border-radius: var(--input-border-radius, 0.5em);
  border: var(--input-border-size, 1px) solid
    var(--input-border-color, var(--color-border-darker));
  color: var(--input-color, var(--color-text));
  font-size: max(16px, 1em);
  inline-size: 100%;
  padding: var(--input-padding, 0.5em 0.8em);
  print-color-adjust: exact;

  /* Keep the value clear of the chevron, which sits 1.5em wide inset 0.5rem
     from the end edge — without this a long option runs underneath it. */
  &:not(:where([multiple], [size]:not([size="1"]))) {
    padding-inline-end: 2.5rem;
  }

  &:where([multiple], [size]:not([size="1"])) {
    background-image: none;
  }
}
