/* The composer: a bar at the bottom, or a floating field in the middle of the
   empty state. The same element does both, so it can hop between them. */
.composer {
  position: relative; z-index: 5;
  padding: 10px 16px calc(10px + env(safe-area-inset-bottom));
  background: var(--surface); border-top: 1px solid var(--line);
}
.composer-row, .held { display: flex; align-items: flex-end; gap: 8px; max-width: 820px; margin: 0 auto; }

.page[data-layout="centred"] .composer {
  grid-row: 1; grid-column: 1; align-self: start; justify-self: center;
  top: calc(45% + var(--empty-block) / 2 - 44px);
  width: min(640px, calc(100% - 2 * var(--gutter))); padding: 0;
  background: none; border: 0;
}

/* The box, not the field, wears the border and the focus ring, because it holds the tray of files as well as the + button and the field.
   One line is 44 px: the field's 42 px and the one-pixel border above and below. The field grows with its text up to 196 px, which holds eight lines, and then scrolls. */
.field-box {
  position: relative; flex: 1; min-width: 0; display: flex; flex-direction: column;
  background: var(--surface-2); border: 1px solid var(--line); border-radius: 22px;
}
.field-box.has-tray { border-radius: 20px; }
.field-box:has(#field:focus-visible) { outline: 2px solid var(--focus); }
.field-line { display: flex; align-items: flex-end; }

textarea#field {
  flex: 1; min-width: 0; min-height: 42px; max-height: 196px; padding: 10px 4px 10px 6px;
  background: none; border: 0; border-radius: 0 22px 22px 0; outline: 0;
  font-size: 16px; line-height: 22px; resize: none; display: block;
}
textarea#field::placeholder { color: var(--muted); }

/* The 3 px margins centre a 36 px button on a one-line field and keep it at the foot as the field grows.
   The ::after makes the press target 44 px across. The voice pill at the right end mirrors the + at the left. */
.attach, .voice, .hear {
  position: relative; display: grid; place-items: center; flex: none; width: 36px; height: 36px; margin: 3px 0 3px 4px; padding: 0;
  background: none; border: 0; border-radius: 50%; color: var(--muted);
  transition: background 120ms, color 120ms;
}
.voice, .hear { margin: 0; }
.attach::after, .voice::after, .hear::after { content: ""; position: absolute; inset: -4px; border-radius: 50%; }
.attach:hover, .attach:focus-visible, .voice:hover, .voice:focus-visible, .hear:hover, .hear:focus-visible { background: rgba(255, 255, 255, .06); color: var(--fg); }
.attach .icon, .voice .icon, .hear .icon { width: 20px; height: 20px; }

/* Speaker and mic share one 36 px pill. The speaker comes first, where people already reach for it,
   and the whole pill takes the accent tint when either half is on. */
.voice-pill {
  display: flex; flex: none; height: 36px; margin: 3px 4px 3px 0; border-radius: 18px;
  transition: background 120ms;
}
.voice-pill.has-on { background: rgba(61, 139, 255, .14); }
.voice-pill .voice { border-radius: 18px 0 0 18px; }
.voice-pill .hear { border-left: 1px solid var(--line); border-radius: 0 18px 18px 0; }

.voice[aria-pressed="true"] { color: var(--accent); }
.voice[aria-pressed="true"]:hover, .voice[aria-pressed="true"]:focus-visible { background: rgba(61, 139, 255, .22); color: var(--accent); }
.voice[aria-disabled="true"] { opacity: .45; }
.voice.is-speaking { background: rgba(61, 139, 255, .26); }
.voice.is-speaking .icon { animation: voice-pulse 1.2s ease-in-out infinite; }
.voice.has-problem::before, .hear.has-problem::before, .hear[data-state="asleep"]::before {
  content: ""; position: absolute; top: 4px; right: 4px; width: 8px; height: 8px;
  background: var(--warning); border: 2px solid var(--surface-2); border-radius: 50%;
}
@keyframes voice-pulse { 50% { opacity: .5; } }
.reduced .voice.is-speaking .icon { animation: none; }

/* The mic. data-state is the engine's state; the ring is ::before, driven by --level (0 to 1) while it listens. */
.hear[aria-disabled="true"] { opacity: .45; }
.hear[data-state="listening"], .hear[data-state="halfDuplexPause"] { color: var(--accent); }
.hear[data-state="listening"]:hover, .hear[data-state="listening"]:focus-visible, .hear[data-state="halfDuplexPause"]:hover, .hear[data-state="halfDuplexPause"]:focus-visible { background: rgba(61, 139, 255, .22); }
.hear[data-state="waitingForTouch"] { color: var(--accent); box-shadow: inset 0 0 0 1.5px var(--accent); }
.hear[data-state="starting"] .icon { opacity: .5; }
.hear[data-state="halfDuplexPause"] .icon { opacity: .6; }
.hear[data-state="asleep"]::before { background: var(--accent); }
.hear[data-state="listening"]::before, .hear[data-state="starting"]::before {
  content: ""; position: absolute; inset: -3px; border: 2px solid var(--accent); border-radius: 50%; pointer-events: none;
}
.hear[data-state="listening"]::before {
  opacity: calc(.25 + .65 * var(--level, 0)); transform: scale(calc(1 + .35 * var(--level, 0)));
}
.hear[data-state="starting"]::before { border-color: transparent; border-top-color: var(--accent); animation: hear-spin 1s linear 1; }
.hear.is-busy::before { transform: none; animation: voice-pulse 1.6s ease-in-out infinite; }
.hear.is-greeting .icon { animation: voice-pulse 1.2s ease-in-out 1; }
@keyframes hear-spin { to { transform: rotate(360deg); } }

/* The 12 px padding above leaves room for the × that overhangs each chip. */
.tray { display: flex; gap: 8px; margin: 0; padding: 12px 12px 4px; list-style: none; overflow-x: auto; scrollbar-width: thin; scrollbar-color: rgba(255, 255, 255, .18) transparent; }
.chip { position: relative; flex: none; animation: rise 160ms ease-out; }
.chip-body {
  position: relative; display: flex; align-items: center; gap: 10px; height: 52px; max-width: 240px; padding: 0 14px 0 10px; overflow: hidden;
  background: var(--surface); border: 1px solid var(--line); border-radius: 12px;
}
.chip.is-picture .chip-body { width: 52px; padding: 0; border-radius: 10px; }
.chip-thumb { display: block; width: 100%; height: 100%; object-fit: cover; }
.chip-text { display: flex; flex-direction: column; min-width: 0; max-width: 180px; }
.chip-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; font-weight: 600; line-height: 18px; }
.chip-meta { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--muted); font-size: 12px; line-height: 16px; }
.chip[data-state="uploading"] .chip-body > :not(.chip-bar) { opacity: .7; }
.chip[data-state="failed"] .chip-body { border-color: rgba(255, 123, 114, .5); }
.chip[data-state="failed"] .chip-meta { color: var(--danger); }

.chip-bar { position: absolute; left: 0; right: 0; bottom: 0; width: 100%; height: 2px; appearance: none; border: 0; background: none; accent-color: var(--accent); }
.chip-bar::-webkit-progress-bar { background: none; }
.chip-bar::-webkit-progress-value { background: var(--accent); }
.chip-bar::-moz-progress-bar { background: var(--accent); }
.chip:not([data-state="uploading"]) .chip-bar { display: none; }

/* The ::after makes the press target of the 22 px circle 44 px across. */
.chip-remove {
  position: absolute; top: -6px; right: -6px; display: grid; place-items: center; width: 22px; height: 22px; padding: 0;
  background: var(--surface); border: 1px solid var(--line); border-radius: 50%; color: var(--fg);
}
.chip-remove::after { content: ""; position: absolute; inset: -11px; border-radius: 50%; }
.chip-remove:hover { background: #1d2c38; }
.chip-remove .icon { width: 12px; height: 12px; }
.tray-note { margin: 0; padding: 4px 16px 0; color: var(--danger); font-size: 12px; line-height: 16px; }
.reduced .chip { animation: none; }
.reduced .hear.is-greeting .icon { animation: none; }
.reduced .hear::before, .reduced .send::before { animation: none; transition: none; transform: none; }
.reduced .hear[data-state="listening"]::before, .reduced .hear.is-busy::before { opacity: .25; }
.reduced .send.is-pending::before { opacity: 0; }

/* Files dragged over the page: the box turns into a place to drop them. */
.drop-label {
  position: absolute; inset: 0; display: none; place-items: center; margin: 0;
  background: rgba(23, 35, 45, .96); border-radius: inherit; color: var(--link-jet); font-size: 14px; font-weight: 600; pointer-events: none;
}
.composer.is-dropping .field-box { border-style: dashed; border-color: var(--accent); background: rgba(61, 139, 255, .08); }
.composer.is-dropping .drop-label { display: grid; }

/* The 3 px bottom margin centres the 38 px button on a one-line 44 px field and keeps it at the foot as the field grows.
   The ::after makes the press target 44 px across. */
.send {
  position: relative; display: grid; place-items: center; flex: none; width: 38px; height: 38px; margin-bottom: 3px; padding: 0;
  background: var(--accent); border: 0; border-radius: 50%; color: #fff;
  transition: background 120ms, color 120ms;
}
.send::after { content: ""; position: absolute; inset: -3px; border-radius: 50%; }
.send .icon { width: 20px; height: 20px; }
/* While the page waits out the end of a thought, a soft halo says the message is about to go. */
.send::before { content: ""; position: absolute; inset: -4px; border-radius: 50%; background: var(--accent); opacity: 0; z-index: -1; transition: opacity 200ms; }
.send.is-pending::before { opacity: .6; }
/* Solid rather than faded, so the tile does not show through the button in the empty state. */
.send:disabled { background: #23487b; color: rgba(255, 255, 255, .6); }

.held {
  justify-content: space-between; align-items: center; margin-bottom: 8px; padding: 0 4px 0 16px;
  background: var(--surface-2); border: 1px solid var(--line); border-radius: 22px;
  font-size: 13px; color: var(--muted);
}
.held-files { white-space: pre; }
.held .icon-button { position: relative; width: 36px; height: 36px; margin: 4px 0; color: var(--fg); }
.held .icon-button::after { content: ""; position: absolute; inset: -4px; }
@media (prefers-reduced-motion: reduce) {
  .chip, .voice.is-speaking .icon, .hear.is-greeting .icon { animation: none; }
  /* Rules inside a media query do not win by being there, so :root makes these as specific as the rule for each state. */
  :root .hear::before, :root .send::before { animation: none; transition: none; transform: none; }
  .hear[data-state="listening"]::before, .hear.is-busy::before { opacity: .25; }
  .send.is-pending::before { opacity: 0; }
}
