/* In-field dictation (dictate_controller.js). The controller puts one
   "Dictate" button inside the focused field's box, at its bottom-right
   corner. On a multi-line field with text it is the microphone only
   (owner, 2026-11-11). The button is position:absolute and placed by
   measurement; top/left come from the controller. Every colour is a token,
   so dark mode follows. */

/* The band the button sits in. While dictation is available (the layout's
   head script sets data-dictation="on" before first paint) every multi-line
   field keeps this room at its bottom, focused or not. A field therefore has
   one size: nothing below it moves when focus comes or goes, and typed text
   never runs under the button. The selector list matches
   dictate_controller#isDictatable: no read-only or disabled fields, nothing
   opted out with data-dictate="off", and not Trix's own caption textarea.
   !important because component rules (.chat-input and others) set the
   padding shorthand. */
:root {
  --dictate-band: 42px; /* 36px button + 4px inset below + 2px clear above */
}

[data-dictation="on"] textarea:not([readonly], [disabled], [data-dictate="off"], [data-dictate="off"] *, trix-editor *),
[data-dictation="on"] trix-editor:not([data-dictate="off"], [data-dictate="off"] *) {
  padding-bottom: var(--dictate-band) !important;
}

.dictate-inline {
  position: absolute;
  top: 0;
  right: 0;
  left: auto;
  z-index: 3;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.45rem;
  height: 44px;
  margin: 0;
  padding: 0 0.85rem;
  border: 1px solid var(--teal-accent);
  border-radius: var(--radius-sm);
  background: var(--teal-light);
  color: var(--teal-ink);
  font-family: var(--font-body);
  font-size: var(--size-ui);
  font-weight: var(--weight-semibold);
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
  box-shadow: var(--shadow-sm);
  -webkit-tap-highlight-color: transparent;
  transition: background var(--motion-quick) var(--ease-out), color var(--motion-quick) var(--ease-out), border-color var(--motion-quick) var(--ease-out);
}

.dictate-inline i {
  font-size: 1.05em;
  line-height: 1;
}

/* Hover-capable pointers only: a tap must not stick this. */
@media (hover: hover) {
  .dictate-inline:hover {
    background: var(--teal-fill);
    border-color: var(--teal-fill);
    color: var(--text-on-accent);
  }
}

.dictate-inline:focus-visible {
  outline: var(--focus-ring-width) solid var(--focus-ring-color);
  outline-offset: var(--focus-ring-offset);
}

/* Multi-line fields: a 36px button. The invisible ::before keeps the touch
   target 44px tall. */
.dictate-inline:not(.dictate-inline--input) {
  height: 36px;
  padding: 0 0.7rem;
  font-size: var(--size-ui-sm);
}

.dictate-inline:not(.dictate-inline--input)::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  height: 44px;
  transform: translateY(-50%);
}

/* One-line inputs: the controller sizes the button to the input's height.
   The invisible ::before keeps the touch target 44px tall. */
.dictate-inline--input {
  padding: 0 0.6rem;
  font-size: var(--size-ui-sm);
}

.dictate-inline--input::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  height: 44px;
  transform: translateY(-50%);
}

/* Compact: a multi-line field that has text (owner, 2026-11-11). The
   microphone only, and the word slides out to the left while the pointer
   is on the button or the keyboard focus is on it. The controller pins the
   button by its right edge, so it grows into the field. The aria-label
   names the action at all times. */
.dictate-inline--compact {
  gap: 0;
  padding: 0 0.72rem;
  transition: gap var(--motion-quick) var(--ease-out), opacity var(--motion-quick) var(--ease-out),
              background var(--motion-quick) var(--ease-out), color var(--motion-quick) var(--ease-out),
              border-color var(--motion-quick) var(--ease-out);
}

.dictate-inline--compact .dictate-inline-label {
  display: inline-block;
  max-width: 0;
  overflow: hidden;
  opacity: 0;
  transition: max-width 220ms var(--ease-out), opacity 160ms var(--ease-out);
}

.dictate-inline--compact:focus-visible {
  gap: 0.35rem;
}

.dictate-inline--compact:focus-visible .dictate-inline-label {
  max-width: 12rem;
  opacity: 1;
}

@media (hover: hover) {
  .dictate-inline--compact:hover {
    gap: 0.35rem;
  }

  .dictate-inline--compact:hover .dictate-inline-label {
    max-width: 12rem;
    opacity: 1;
  }

  /* Dictating into a field with text: see-through until the pointer is on
     the button, so the words coming in are easy to read. The field's red
     ring still shows that dictation is on. */
  .dictate-inline--compact.recording:not(:hover, :focus-visible) {
    opacity: 0.4;
  }
}

/* Icon only: one-line inputs too narrow for the word. The aria-label
   still names the action and the field. */
.dictate-inline--icon-only {
  aspect-ratio: 1;
  padding: 0;
}

.dictate-inline--icon-only .dictate-inline-label {
  display: none;
}

/* Listening: a filled red button with a pulsing ring. --bg-primary is
   white in the light theme and near-black in the dark theme, which is the
   readable ink on --status-danger in each. */
.dictate-inline.recording {
  background: var(--status-danger);
  border-color: var(--status-danger);
  color: var(--bg-primary);
  animation: dictate-button-pulse 1.4s ease-in-out infinite;
}

.dictate-inline.recording i {
  animation: dictate-mic-beat 1.4s ease-in-out infinite;
}

@keyframes dictate-button-pulse {
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--status-danger) 55%, transparent); }
  50%      { box-shadow: 0 0 0 7px color-mix(in srgb, var(--status-danger) 0%, transparent); }
}

@keyframes dictate-mic-beat {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(1.18); }
}

/* The ring on the field being dictated into, matching the button. */
.dictate-active-target {
  outline: 2px solid var(--status-danger) !important;
  outline-offset: 2px;
  animation: dictate-field-pulse 1.4s ease-in-out infinite;
}

@keyframes dictate-field-pulse {
  0%, 100% { box-shadow: 0 0 0 2px color-mix(in srgb, var(--status-danger) 10%, transparent); }
  50%      { box-shadow: 0 0 0 7px color-mix(in srgb, var(--status-danger) 25%, transparent); }
}

@media (prefers-reduced-motion: reduce) {
  .dictate-inline--compact,
  .dictate-inline--compact .dictate-inline-label {
    transition: none;
  }

  .dictate-inline.recording,
  .dictate-inline.recording i,
  .dictate-active-target {
    animation: none;
  }

  .dictate-inline.recording {
    box-shadow: 0 0 0 4px color-mix(in srgb, var(--status-danger) 35%, transparent);
  }
}

/* Short messages and the microphone troubleshooting panel. position:fixed
   just above the button; the controller sets bottom/right. */
.dictate-status {
  position: fixed;
  z-index: 1060;
  max-width: min(18rem, calc(100vw - 16px));
  padding: 0.5rem 0.75rem;
  border: 1px solid var(--border-light);
  border-radius: var(--radius-sm);
  background: var(--bg-primary);
  color: var(--text-dark);
  box-shadow: var(--shadow-md);
  font-size: var(--size-ui-sm);
  line-height: 1.35;
  opacity: 0;
  pointer-events: none;
  transform: translateY(4px);
  transition: opacity var(--motion-quick) var(--ease-out), transform var(--motion-quick) var(--ease-out);
}

.dictate-status.visible {
  opacity: 1;
  transform: translateY(0);
}

.dictate-status.troubleshooting {
  max-width: min(24rem, calc(100vw - 16px));
  padding: 0.75rem 0.9rem;
  pointer-events: auto;
  text-align: left;
}

.dictate-status .dictate-troubleshooting-headline {
  margin-bottom: 0.2rem;
  color: var(--text-heading);
  font-weight: var(--weight-semibold);
}

.dictate-status .dictate-troubleshooting-mic {
  margin-bottom: 0.4rem;
  padding: 0.3rem 0.5rem;
  border-left: 2px solid var(--teal-accent);
  background: var(--bg-secondary);
  font-size: var(--size-xs);
}

.dictate-status .dictate-mic-key {
  margin-right: 0.25rem;
  color: var(--text-muted);
}

.dictate-status .dictate-troubleshooting-sub {
  margin-bottom: 0.35rem;
  color: var(--text-muted);
  font-size: var(--size-xs);
}

.dictate-status .dictate-troubleshooting-list {
  margin: 0 0 0.5rem;
  padding-left: 1.1rem;
}

.dictate-status .dictate-troubleshooting-list li {
  margin-bottom: 0.25rem;
}

.dictate-status .dictate-troubleshooting-list li:last-child {
  margin-bottom: 0;
}

.dictate-status .dictate-troubleshooting-os {
  padding-top: 0.4rem;
  border-top: 1px solid var(--border-light);
  color: var(--text-muted);
  font-size: var(--size-xs);
}

.dictate-status .dictate-troubleshooting-os strong {
  color: var(--text-dark);
  font-weight: var(--weight-semibold);
}
