/* Exclivia · components.css — piezas reutilizables.
 * Prefijo exc- en todo para no chocar con Bootstrap (ni con Tailwind el día que
 * el admin cambie de framework: los componentes viven de las variables, no del
 * framework).
 */

/* ── Tarjetas ───────────────────────────────────────────────────────────── */

.exc-card {
  background: var(--exc-surface);
  border: var(--exc-border-width) solid var(--exc-border);
  border-radius: var(--exc-radius-card);
  padding: 1.25rem;
  box-shadow: var(--exc-shadow);
}

.exc-card + .exc-card { margin-top: 1rem; }

.exc-card-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: .75rem; flex-wrap: wrap;
  margin-bottom: 1rem;
}
.exc-card-title { margin: 0; font-size: 1.05rem; font-weight: 600; }
.exc-card-sub   { margin: .15rem 0 0; font-size: .85rem; color: var(--exc-muted); }

.exc-card-accent { border-left: 3px solid var(--exc-accent); }

.exc-card-link {
  display: block; color: inherit;
  transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease;
}
.exc-card-link:hover {
  transform: translateY(-2px);
  border-color: var(--exc-accent);
  box-shadow: var(--exc-shadow-lg);
  opacity: 1;
}

/* ── Botones ────────────────────────────────────────────────────────────── */

.exc-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
  padding: .62rem 1.15rem;
  min-height: 44px;               /* objetivo táctil cómodo en celular */
  border: var(--exc-border-width) solid transparent;
  border-radius: var(--exc-radius);
  font: inherit; font-size: .94rem; font-weight: 600;
  line-height: 1;
  cursor: pointer;
  text-decoration: none;
  transition: background .15s ease, border-color .15s ease, transform .1s ease, opacity .15s ease;
  -webkit-tap-highlight-color: transparent;
}
.exc-btn:active { transform: translateY(1px); }
.exc-btn:disabled, .exc-btn.is-busy { opacity: .6; cursor: not-allowed; }

.exc-btn-primary {
  background: var(--exc-accent);
  color: var(--exc-accent-contrast);
  border-color: var(--exc-accent);
}
.exc-btn-primary:hover { filter: brightness(1.06); opacity: 1; }

.exc-btn-outline {
  background: transparent;
  color: var(--exc-text);
  border-color: var(--exc-border);
}
.exc-btn-outline:hover { border-color: var(--exc-accent); color: var(--exc-accent); opacity: 1; }

.exc-btn-ghost {
  background: transparent; color: var(--exc-text); border-color: transparent;
}
.exc-btn-ghost:hover { background: var(--exc-surface-2); opacity: 1; }

.exc-btn-danger {
  background: var(--exc-danger); color: #fff; border-color: var(--exc-danger);
}

/* De qué color va el icono de cada variante — el mismo que su texto.
   El mecanismo está en «Iconos», en base.css. */
.exc-btn-primary { --exc-ico: var(--exc-accent-contrast); }
.exc-btn-outline,
.exc-btn-ghost   { --exc-ico: var(--exc-text); }
.exc-btn-danger  { --exc-ico: #fff; }
.exc-btn-outline:hover { --exc-ico: var(--exc-accent); }

/* `display: inline-flex` le gana al `hidden` del navegador: sin esta regla,
   esconder un botón desde el JS no lo escondía —seguía ahí, ofreciendo algo que
   el servidor iba a rechazar—. Pasó con el botón de «agregar motivo» al llegar
   al tope y con el enlace de «ver mi cita» cuando no había enlace. */
.exc-btn[hidden] { display: none; }

.exc-btn-sm    { padding: .4rem .8rem; min-height: 36px; font-size: .85rem; }
.exc-btn-lg    { padding: .85rem 1.6rem; min-height: 52px; font-size: 1rem; }
.exc-btn-block { display: flex; width: 100%; }
.exc-btn-icon  { padding: .5rem; min-width: 44px; }

/* Estado cargando: el texto se atenúa y aparece el giro. */
.exc-btn .exc-spinner { display: none; }
.exc-btn.is-busy .exc-spinner { display: inline-block; }

.exc-spinner {
  width: 1em; height: 1em;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  animation: exc-spin .7s linear infinite;
}
@keyframes exc-spin { to { transform: rotate(360deg); } }

/* ── Formularios ────────────────────────────────────────────────────────── */

/* `display: block` NO es decorativo.
 *
 * `.exc-field` se pone casi siempre en un `<label>`, y un label es `inline`.
 * Dentro de un grid no se nota —el grid convierte a sus hijos en bloque— pero
 * SUELTO, el campo se queda inline y el `width: 100%` de su input o su textarea
 * no tiene contra qué medirse: se encoge al ancho del contenido. Ese era el
 * caso de la descripción de un auto, que salía en una columna estrecha en medio
 * de una fila vacía sin que nada estuviera mal escrito en su vista. */
.exc-field { display: block; margin-bottom: 1rem; }

.exc-label {
  display: block;
  margin-bottom: .35rem;
  font-size: .88rem;
  font-weight: 600;
}

.exc-input, .exc-select, .exc-textarea {
  display: block; width: 100%;
  padding: .68rem .85rem;
  min-height: 46px;
  font: inherit;
  font-size: 16px;               /* menos de 16px hace que iOS acerque el zoom */
  color: var(--exc-text);
  background: var(--exc-bg);
  border: var(--exc-border-width) solid var(--exc-border);
  border-radius: var(--exc-radius);
  transition: border-color .15s ease, box-shadow .15s ease;
}
.exc-input:focus, .exc-select:focus, .exc-textarea:focus {
  outline: none;
  border-color: var(--exc-accent);
  box-shadow: 0 0 0 3px rgba(var(--exc-accent-rgb), .18);
}
.exc-input::placeholder, .exc-textarea::placeholder { color: var(--exc-muted); }
.exc-input:disabled, .exc-select:disabled, .exc-textarea:disabled {
  opacity: .6; cursor: not-allowed;
}
.exc-textarea { min-height: 110px; resize: vertical; }

.exc-select {
  appearance: none;
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
                    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: calc(100% - 18px) 50%, calc(100% - 13px) 50%;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
  padding-right: 2.4rem;
}

/* Los renglones del desplegable, pintados a mano.
 *
 * `color-scheme` en la raíz debería bastar —y está puesto—, pero no todos los
 * navegadores lo aplican a la lista que abre un `<select>`: sale con el blanco
 * y el azul del sistema encima de una pantalla oscura. Esto sí lo respetan
 * Chromium y Firefox en Windows y Linux.
 *
 * En macOS ese menú lo dibuja el sistema y estas reglas no le llegan; ahí lo
 * único que funciona es `color-scheme`, que por eso se queda. Las dos juntas
 * cubren los dos casos.
 *
 * Se pintan TODOS los `option`, no solo los de `.exc-select`: en el sitio hay
 * desplegables con `.exc-input` y con clases de módulo, y una lista blanca en
 * uno solo se ve igual de rota. */
select option,
select optgroup {
  background-color: var(--exc-surface);
  color: var(--exc-text);
}

.exc-hint  { margin: .3rem 0 0; font-size: .8rem; color: var(--exc-muted); }
.exc-error { margin: .3rem 0 0; font-size: .8rem; color: var(--exc-danger); }
.exc-input.is-invalid, .exc-select.is-invalid { border-color: var(--exc-danger); }
.exc-input.is-valid { border-color: var(--exc-success); }

/* Casilla y switch */
.exc-check {
  display: flex; align-items: flex-start; gap: .6rem;
  padding: .5rem 0; cursor: pointer;
}
.exc-check input { width: 20px; height: 20px; accent-color: var(--exc-accent); flex: none; margin-top: .1rem; }

.exc-switch { display: inline-flex; align-items: center; gap: .6rem; cursor: pointer; }
.exc-switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.exc-switch-track {
  width: 46px; height: 26px; flex: none;
  background: var(--exc-border);
  border-radius: 999px;
  position: relative;
  transition: background .18s ease;
}
.exc-switch-track::after {
  content: ""; position: absolute; top: 3px; left: 3px;
  width: 20px; height: 20px; border-radius: 50%;
  background: var(--exc-surface);
  transition: transform .18s ease;
}
.exc-switch input:checked + .exc-switch-track { background: var(--exc-accent); }
.exc-switch input:checked + .exc-switch-track::after { transform: translateX(20px); }
.exc-switch input:focus-visible + .exc-switch-track { outline: 2px solid var(--exc-accent); outline-offset: 2px; }

/* Opciones tocables — en celular se usan mejor que un <select>. */
.exc-choices { display: grid; gap: .6rem; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); }
.exc-choice {
  position: relative;
  display: flex; align-items: center; gap: .6rem;
  padding: .8rem .9rem;
  border: var(--exc-border-width) solid var(--exc-border);
  border-radius: var(--exc-radius);
  cursor: pointer;
  transition: border-color .15s ease, background .15s ease;
}
.exc-choice input { position: absolute; opacity: 0; }
.exc-choice.is-selected { border-color: var(--exc-accent); background: rgba(var(--exc-accent-rgb), .08); }

/* Una opción por renglón, para cuando cada una necesita explicarse.
 *
 * La rejilla de arriba reparte el ancho entre las opciones y va bien con
 * etiquetas de una palabra —«Perro», «Gato»—; con un título y una línea debajo,
 * dos columnas dejan cuatro palabras por renglón. Aquí la decisión no es de un
 * vistazo: se lee. */
.exc-choices-block { grid-template-columns: 1fr; }
.exc-choices-block .exc-choice { align-items: flex-start; }

/* `min-width: 0` para que el texto largo se corte dentro del renglón en vez de
   ensanchar la caja. */
.exc-choices-block .exc-choice > span {
  display: flex; flex-direction: column; gap: .15rem; min-width: 0;
}
.exc-choices-block .exc-choice strong {
  display: inline-flex; align-items: center; gap: .4rem;
}
.exc-choices-block .exc-choice small { color: var(--exc-muted); line-height: 1.4; }

/* Color: el navegador pinta un cuadrito feo; se le da forma. */
.exc-color {
  width: 46px; height: 46px; padding: 3px;
  border: var(--exc-border-width) solid var(--exc-border);
  border-radius: var(--exc-radius-sm);
  background: var(--exc-bg);
  cursor: pointer;
}
.exc-color-row { display: flex; align-items: center; gap: .7rem; }
.exc-color-row .exc-input { max-width: 130px; font-family: ui-monospace, monospace; }

/* ── Avisos ─────────────────────────────────────────────────────────────── */

.exc-alert {
  padding: .85rem 1rem;
  border-radius: var(--exc-radius);
  border: 1px solid transparent;
  font-size: .92rem;
  margin-bottom: 1rem;
}
.exc-alert-success { background: rgba(30,158,106,.12); border-color: rgba(30,158,106,.35); color: var(--exc-success); }
.exc-alert-danger  { background: rgba(214,72,63,.12);  border-color: rgba(214,72,63,.35);  color: var(--exc-danger); }
.exc-alert-warning { background: rgba(217,133,24,.12); border-color: rgba(217,133,24,.35); color: var(--exc-warning); }
.exc-alert-info    { background: rgba(47,125,209,.12); border-color: rgba(47,125,209,.35); color: var(--exc-info); }

/* ── Badges ─────────────────────────────────────────────────────────────── */

.exc-badge {
  display: inline-flex; align-items: center; gap: .3rem;
  padding: .22rem .6rem;
  border-radius: 999px;
  font-size: .72rem;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  border: 1px solid transparent;
  white-space: nowrap;
}
.exc-badge-accent  { background: rgba(var(--exc-accent-rgb), .16); color: var(--exc-accent); }
.exc-badge-success { background: rgba(30,158,106,.16); color: var(--exc-success); }
.exc-badge-warning { background: rgba(217,133,24,.16); color: var(--exc-warning); }
.exc-badge-danger  { background: rgba(214,72,63,.16);  color: var(--exc-danger); }
.exc-badge-muted   { background: var(--exc-surface-2); color: var(--exc-muted); }

.exc-badge.is-solid   { color: var(--exc-accent-contrast); background: var(--exc-accent); }
.exc-badge.is-outline { background: transparent; border-color: currentColor; }

/* ── La etiqueta de los personajes generados ──────────────────────────────
 *
 * Va pegada al nombre, en todas partes donde sale un nombre. La pinta
 * `Ia::badge()`; aquí solo se le da forma.
 *
 * ── Por qué NO es un `.exc-badge` más ────────────────────────────────────
 *
 * Los badges del sitio son etiquetas de estado —«activo», «pendiente»,
 * «pagado»— y comparten familia porque dicen lo mismo: en qué punto está algo.
 * Esto dice otra cosa: con QUIÉN estás hablando. Si compartiera clase, un día
 * alguien le pondría `is-solid` para que resaltara en una pantalla y la
 * etiqueta cambiaría de aspecto según dónde caiga — y una advertencia que no
 * se ve igual en todos lados deja de leerse como una advertencia.
 *
 * ── Y por qué es GRIS y no del color de acento ───────────────────────────
 *
 * Porque no es un premio. En dorado, al lado del sello de verificación, se
 * leería como un tercer nivel de cuenta —«azul, oro, IA»— que es exactamente
 * lo contrario de lo que dice. Neutra, discreta y siempre igual: informa sin
 * felicitar y sin acusar.
 */
.exc-ia {
  display: inline-flex;
  align-items: center;
  gap: .22rem;
  padding: .12rem .42rem .12rem .3rem;
  border: 1px solid var(--exc-border);
  border-radius: 999px;
  background: var(--exc-surface-2);
  color: var(--exc-muted);
  --exc-ico: currentColor;
  /* `em` y no `rem`: la etiqueta acompaña a un nombre que mide distinto en el
     `h1` del perfil y en el renglón de una tarjeta del muro. Con `rem` había
     que escribir un tamaño por sitio; con `em` se ajusta sola y siempre queda
     en proporción con lo que está etiquetando. */
  font-size: .72em;
  font-weight: 700;
  letter-spacing: .04em;
  line-height: 1.5;
  white-space: nowrap;
  /* Se queda quieta en la línea base del nombre en vez de flotar a media
     altura, que es donde acaba si hereda el `vertical-align` del texto. */
  vertical-align: middle;
  /* El nombre de al lado puede ir en cursiva o con otra caja tipográfica —la
     bio, un título—; la etiqueta no hereda nada de eso: siempre igual. */
  font-style: normal;
  text-transform: none;
}

/* El icono, un pelo más chico que las letras: es el acento, no el mensaje. */
.exc-ia svg { width: 1em; height: 1em; }

/* En una tarjeta del muro, junto a un @usuario ya pequeño, se queda solo la
   chispa: las letras a ese tamaño son tres píxeles borrosos que no se leen, y
   una etiqueta ilegible es peor que ninguna porque ocupa sitio y no avisa. El
   `title` sigue ahí, y quien toque el nombre llega al perfil, donde la etiqueta
   está entera. */
.exc-ia-sm span { display: none; }
.exc-ia-sm      { padding: .12rem .26rem; }

/* ── Avatares ───────────────────────────────────────────────────────────── */

.exc-avatar {
  width: 40px; height: 40px;
  border-radius: 50%;
  object-fit: cover;
  flex: none;
  background: var(--exc-surface-2);
}
.exc-avatar-initials {
  display: inline-flex; align-items: center; justify-content: center;
  font-size: .8rem; font-weight: 700;
  color: var(--exc-accent-contrast);
  background: var(--exc-accent);
}
.exc-avatar-sm { width: 30px; height: 30px; font-size: .7rem; }
.exc-avatar-lg { width: 64px; height: 64px; font-size: 1.1rem; }
.exc-avatar-xl { width: 112px; height: 112px; font-size: 1.9rem; }

/* ── Tablas ─────────────────────────────────────────────────────────────── */

/* La tabla se desplaza DENTRO de su caja: la página nunca se mueve de lado. */
.exc-table-wrap {
  overflow-x: auto;
  border: var(--exc-border-width) solid var(--exc-border);
  border-radius: var(--exc-radius-card);
  background: var(--exc-surface);
  -webkit-overflow-scrolling: touch;
}
.exc-table { width: 100%; border-collapse: collapse; font-size: .92rem; }
.exc-table th, .exc-table td {
  padding: .75rem .9rem;
  text-align: left;
  border-bottom: 1px solid var(--exc-border);
  vertical-align: middle;
}
.exc-table th {
  font-size: .76rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: .05em;
  color: var(--exc-muted);
  background: var(--exc-surface-2);
  white-space: nowrap;
}
.exc-table tbody tr:last-child td { border-bottom: 0; }
.exc-table tbody tr:hover { background: var(--exc-surface-2); }
.exc-table-actions { display: flex; gap: .4rem; justify-content: flex-end; }

/* ── Estado vacío ───────────────────────────────────────────────────────── */

.exc-empty { padding: 2.5rem 1rem; text-align: center; color: var(--exc-muted); }
/* A este tamaño un trazo de 1.6 pesa demasiado: se adelgaza. */
.exc-empty-icon  { font-size: 2.4rem; opacity: .55; margin-bottom: .5rem; --exc-ico-w: 1.25; }
.exc-empty-title { margin: 0 0 .25rem; font-weight: 600; color: var(--exc-text); }
.exc-empty-hint  { margin: 0; font-size: .88rem; }

/* ── Pestañas ───────────────────────────────────────────────────────────── */

.exc-tabs {
  display: flex; gap: .25rem;
  overflow-x: auto;
  border-bottom: 1px solid var(--exc-border);
  margin-bottom: 1.25rem;
  scrollbar-width: none;
}
.exc-tabs::-webkit-scrollbar { display: none; }
.exc-tab {
  padding: .7rem 1rem;
  border: 0; background: transparent;
  color: var(--exc-muted);
  font: inherit; font-size: .9rem; font-weight: 600;
  white-space: nowrap; cursor: pointer;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
}
.exc-tab:hover { color: var(--exc-text); }
.exc-tab.is-active { color: var(--exc-accent); border-bottom-color: var(--exc-accent); }
.exc-tabpanel[hidden] { display: none; }

/* ── Avisos flotantes ───────────────────────────────────────────────────── */

.exc-toasts {
  position: fixed;
  /* Por encima de cualquier capa que pueda dispararlos.
   *
   * Estaba en 1080, debajo de las ventanas del sitio (1200) y de las capas a
   * pantalla completa de los módulos: un «Copiado» o un «Historia borrada»
   * lanzado desde dentro de una de ellas se pintaba DETRÁS y no lo veía nadie
   * — la acción parecía no haber hecho nada.
   *
   * Debajo del «¿seguro?» (2000) a propósito: ése interrumpe y tiene que
   * quedarse solo en pantalla. */
  z-index: 1900;
  left: 50%; transform: translateX(-50%);
  bottom: calc(env(safe-area-inset-bottom, 0px) + 5rem);
  display: flex; flex-direction: column; gap: .5rem;
  width: min(420px, calc(100vw - 2rem));
  pointer-events: none;
}
@media (min-width: 992px) {
  .exc-toasts { left: auto; right: 1.5rem; transform: none; bottom: 1.5rem; }
}
.exc-toast {
  pointer-events: auto;
  padding: .8rem 1rem;
  border-radius: var(--exc-radius);
  background: var(--exc-surface);
  border: 1px solid var(--exc-border);
  box-shadow: var(--exc-shadow-lg);
  font-size: .9rem;
  animation: exc-toast-in .22s ease;
}
.exc-toast-success { border-left: 3px solid var(--exc-success); }
.exc-toast-danger  { border-left: 3px solid var(--exc-danger); }
.exc-toast-warning { border-left: 3px solid var(--exc-warning); }
.exc-toast-info    { border-left: 3px solid var(--exc-info); }
@keyframes exc-toast-in { from { opacity: 0; transform: translateY(8px); } }

/* ── Barra de progreso ──────────────────────────────────────────────────── */

.exc-progress {
  height: 8px; border-radius: 999px;
  background: var(--exc-surface-2);
  overflow: hidden;
}
.exc-progress-bar {
  height: 100%;
  background: var(--exc-accent);
  transition: width .3s ease;
}

/* ── Esqueleto de carga ─────────────────────────────────────────────────── */

.exc-skeleton {
  background: linear-gradient(90deg, var(--exc-surface-2) 25%, var(--exc-border) 50%, var(--exc-surface-2) 75%);
  background-size: 200% 100%;
  animation: exc-shimmer 1.3s infinite;
  border-radius: var(--exc-radius-sm);
}
@keyframes exc-shimmer { to { background-position: -200% 0; } }

/* ── Encabezado de página ───────────────────────────────────────────────── */

.exc-page-head {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 1rem; flex-wrap: wrap;
  margin-bottom: 1.5rem;
}
.exc-page-title { margin: 0; }
.exc-page-sub   { margin: .25rem 0 0; color: var(--exc-muted); font-size: .92rem; }

/* Varios botones a la derecha del título. En un teléfono el encabezado ya
   envuelve, así que aquí lo que importa es que los botones envuelvan ENTRE
   ELLOS en vez de encogerse hasta cortar su texto. */
.exc-page-acciones {
  display: flex; align-items: center; gap: .5rem; flex-wrap: wrap;
}

/* Anchos fijos para demos y barras estáticas — evitan un style="" suelto en
   las vistas. Los porcentajes calculados en tiempo real sí van como atributo,
   porque son un DATO, no una decisión de diseño. */
.exc-w-25 { width: 25%; }
.exc-w-50 { width: 50%; }
.exc-w-70 { width: 70%; }
.exc-w-100 { width: 100%; }

/* ── Pares clave / valor ────────────────────────────────────────────────────
   Vivían sólo en el CSS del admin, pero `.exc-kv` también se usa en el panel
   del usuario («Tu cuenta»), que no carga ese archivo: ahí la etiqueta y el
   valor salían pegados —«Usuario@iigoons»— porque la clase no tenía estilo.
   Al ser un componente compartido, su sitio es este. */
.exc-kv {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 1rem; padding: .3rem 0;
  font-size: .88rem;
}
.exc-kv span { color: var(--exc-muted); }

/* ── Selector de iconos ─────────────────────────────────────────────────── */
/* Un solo cajón por pantalla, compartido por todos los campos que lo abren. */

.exc-noscroll { overflow: hidden; }

.exc-icofield { display: inline-flex; }
.exc-icofield-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 46px; height: 46px; flex: none;
  padding: 0;
  background: var(--exc-bg);
  border: var(--exc-border-width) solid var(--exc-border);
  border-radius: var(--exc-radius);
  color: var(--exc-text);
  cursor: pointer;
  transition: border-color .15s ease;
}
.exc-icofield-btn:hover { border-color: var(--exc-accent); }
.exc-icofield-preview { display: inline-flex; font-size: 1.35rem; }

.exc-icopicker {
  position: fixed; inset: 0; z-index: 1200;
  display: flex; align-items: flex-end; justify-content: center;
  padding: 0;
}
@media (min-width: 640px) {
  .exc-icopicker { align-items: center; padding: 1.5rem; }
}
.exc-icopicker[hidden] { display: none; }

.exc-icopicker-backdrop {
  position: absolute; inset: 0;
  background: rgba(0, 0, 0, .55);
}

.exc-icopicker-panel {
  position: relative;
  display: flex; flex-direction: column; gap: .9rem;
  width: 100%; max-width: 560px;
  max-height: 88vh;
  padding: 1.1rem;
  background: var(--exc-surface);
  border: var(--exc-border-width) solid var(--exc-border);
  /* En celular sube desde abajo y se pega al borde: el pulgar llega mejor. */
  border-radius: var(--exc-radius-card) var(--exc-radius-card) 0 0;
  box-shadow: var(--exc-shadow-lg);
  animation: exc-ico-in .18s ease;
}
@media (min-width: 640px) {
  .exc-icopicker-panel { border-radius: var(--exc-radius-card); }
}

@keyframes exc-ico-in { from { transform: translateY(14px); opacity: 0; } }
@media (prefers-reduced-motion: reduce) {
  .exc-icopicker-panel { animation: none; }
}

.exc-icopicker-head {
  display: flex; align-items: flex-start; justify-content: space-between; gap: .75rem;
}
.exc-icopicker-head span { display: block; }

.exc-icopicker-grid {
  display: grid; gap: .4rem;
  grid-template-columns: repeat(auto-fill, minmax(74px, 1fr));
  overflow-y: auto;
  min-height: 0;                 /* sin esto el grid no cede y no hay scroll */
  padding: .15rem;
}

.exc-icopicker-item {
  display: flex; flex-direction: column; align-items: center; gap: .3rem;
  padding: .6rem .3rem;
  background: transparent;
  border: var(--exc-border-width) solid transparent;
  border-radius: var(--exc-radius);
  color: var(--exc-text);
  font: inherit; font-size: 1.4rem;
  cursor: pointer;
  transition: background .12s ease, border-color .12s ease;
}
.exc-icopicker-item:hover {
  background: var(--exc-surface-2);
  border-color: var(--exc-accent);
}
.exc-icopicker-item[hidden] { display: none; }

.exc-icopicker-name {
  font-size: .62rem; line-height: 1.1;
  color: var(--exc-muted);
  max-width: 100%;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.exc-icopicker-none { margin: 0; text-align: center; color: var(--exc-muted); font-size: .88rem; }

.exc-icopicker-foot {
  display: flex; justify-content: flex-end;
  border-top: var(--exc-border-width) solid var(--exc-border);
  padding-top: .8rem;
}

/* ── El recortador de imágenes y su campo ───────────────────────────────────
 *
 * Vivían en el CSS del admin, que solo se carga en el panel. Desde que el
 * diálogo es un componente compartido —lo usan el admin, el perfil y los
 * logotipos de los negocios— sus estilos tienen que estar donde estén los
 * demás componentes: con el marcado en un sitio y las reglas en otro, el
 * recortador se abre sin estilo y parece roto. */

/* ── Campo de imagen ────────────────────────────────────────────────────── */

.exc-imgfield {
  display: flex; align-items: center; gap: 1rem;
  padding: .8rem;
  border: 1px dashed var(--exc-border);
  border-radius: var(--exc-radius);
}

.exc-imgfield-preview {
  width: 72px; height: 72px; flex: none;
  object-fit: contain;
  background: var(--exc-surface-2);
  border-radius: var(--exc-radius-sm);
  padding: .3rem;
}

.exc-imgfield-empty {
  width: 72px; height: 72px; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 1.6rem; opacity: .5;
  background: var(--exc-surface-2);
  border-radius: var(--exc-radius-sm);
}

.exc-imgfield-actions { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: .35rem; }

.exc-imgfield-actions .exc-input { padding: .45rem; min-height: auto; font-size: .85rem; }

/* ── Recortador de imágenes ────────────────────────────────────────────────
   Compartido por cualquier campo que declare `crop`. El lienzo manda: el
   panel se estira a lo que la pantalla dé, porque encuadrar una foto en una
   ventanita de 300 px es adivinar, no recortar. */

.exc-crop {
  position: fixed; inset: 0; z-index: 1200;
  display: flex; align-items: center; justify-content: center;
  padding: 1rem;
}

.exc-crop[hidden] { display: none; }

.exc-crop-back {
  position: absolute; inset: 0;
  background: rgba(0, 0, 0, .72);
}

.exc-crop-panel {
  position: relative;
  width: min(920px, 100%);
  max-height: calc(100dvh - 2rem);
  display: flex; flex-direction: column;
  background: var(--exc-surface);
  border: 1px solid var(--exc-border);
  border-radius: var(--exc-radius);
  box-shadow: 0 24px 60px rgba(0, 0, 0, .45);
  overflow: hidden;
}

.exc-crop-head {
  display: flex; align-items: baseline; gap: .6rem; flex-wrap: wrap;
  padding: .9rem 1rem;
  border-bottom: 1px solid var(--exc-border);
}

/* El lienzo va sobre fondo neutro oscuro: sobre el color del tema, una foto
   clara y el panel se funden y no se ve dónde termina el recorte. */
.exc-crop-stage {
  flex: 1; min-height: 0;
  background: #14161a;
  padding: .5rem;
}

/* Cropper mide la IMAGEN al arrancar y arma su lienzo de ese tamaño, así que
   el límite va aquí y no en `.cropper-container`: puesto en el contenedor solo
   recortaría un lienzo que ya nació demasiado alto. */
.exc-crop-stage img {
  display: block;
  max-width: 100%;
  max-height: 62dvh;
  margin: 0 auto;
}

.exc-crop-foot {
  display: flex; align-items: center; gap: .5rem;
  padding: .8rem 1rem;
  border-top: 1px solid var(--exc-border);
}

/* Recorte REDONDO: para los avatares. El archivo que sale sigue siendo
   cuadrado; lo único que cambia es que se encuadra viendo la forma en la que
   la foto se va a ver. `cropper-face` es la superficie que se arrastra y
   `cropper-view-box` el marco: las dos tienen que redondearse o queda un
   círculo dentro de un cuadrado. */
.exc-crop.is-redondo .cropper-view-box,
.exc-crop.is-redondo .cropper-face { border-radius: 50%; }

/* Las guías de Cropper vienen en azul de fábrica: se llevan al acento para
   que el recortador no parezca pegado de otro sitio. */
.exc-crop .cropper-view-box { outline-color: var(--exc-accent); }

.exc-crop .cropper-point,
.exc-crop .cropper-line   { background-color: var(--exc-accent); }

.exc-crop-panel { width: 100%; max-height: 100dvh; height: 100dvh; border-radius: 0; border: 0; }

.exc-crop-stage img { max-height: 58dvh; }

.exc-crop-foot .exc-btn { flex: 1; }

.exc-crop-head strong { flex: none; }

.exc-crop-size {
  margin-left: auto;
  font-size: .75rem; font-variant-numeric: tabular-nums;
  padding: .15rem .5rem;
  color: var(--exc-muted);
  background: var(--exc-surface-2);
  border-radius: 999px;
}

/* Sin tamaño fijo declarado el JS lo deja vacío, y una píldora vacía se lee
   como que algo no cargó. */
.exc-crop-size:empty { display: none; }

/* «Foto 2 de 4»: quién viene detrás. Se pinta en el acento y no en gris
   porque no es un dato de referencia como el tamaño — es lo que explica por
   qué el diálogo vuelve a abrirse al terminar. */
.exc-crop-paso {
  font-size: .75rem; font-weight: 600; font-variant-numeric: tabular-nums;
  padding: .15rem .5rem;
  color: var(--exc-accent);
  background: var(--exc-accent-soft);
  border-radius: 999px;
}
.exc-crop-paso[hidden] { display: none; }

/* Las proporciones. Van DEBAJO del lienzo y encima de los botones: es una
   decisión sobre lo que se está viendo, no una acción de cerrar. */
.exc-crop-ratios {
  display: flex; gap: .4rem; flex-wrap: wrap;
  padding: .6rem 1rem 0;
}
/* Sin esto el `hidden` no vale nada: un `display` de autor le gana siempre al
   atributo, y la fila saldría vacía en todos los campos del admin. */
.exc-crop-ratios[hidden] { display: none; }

.exc-crop-chip {
  font: inherit; font-size: .78rem; font-weight: 600;
  padding: .3rem .7rem;
  color: var(--exc-muted);
  background: var(--exc-surface-2);
  border: 1px solid var(--exc-border);
  border-radius: 999px;
  cursor: pointer;
  transition: color .15s, border-color .15s;
}
.exc-crop-chip:hover { color: var(--exc-text); }

.exc-crop-chip.is-on {
  color: var(--exc-accent);
  border-color: var(--exc-accent);
  background: var(--exc-accent-soft);
}

/* En un teléfono el recortador ocupa la pantalla entera: los márgenes le
   quitan sitio justo a lo único que importa, que es ver el encuadre. */
@media (max-width: 640px) {
  .exc-crop { padding: 0; }
}

/* ── Los diez colores ───────────────────────────────────────────────────────
 *
 * Paleta CERRADA. Nada de hex libre: un color elegido en modo claro se vuelve
 * ilegible en el oscuro y quien lo eligió no tiene cómo saberlo.
 *
 * Hacen falta las DOS familias de selector porque el color se usa en dos
 * planos distintos:
 *
 *   .exc-cal-<color>       el acento de una RAÍZ (el calendario de esta persona).
 *   .exc-cal-c.is-<color>  el color de UNA cosa: este evento, esta muestra.
 *
 * Están aquí y no en el CSS de un módulo porque los usan varios —el calendario
 * y Signature— y una copia por módulo es exactamente la que un día dirá otro
 * tono. Signature no carga el CSS del calendario: mientras vivieron allá, sus
 * diez muestras salían todas del acento. */

/* El valor de partida. Lo que no diga otra cosa sale del acento del sitio. */
.exc-cal-c { --cal-c: var(--exc-accent); --cal-c-rgb: var(--exc-accent-rgb, 214,162,61); }

.exc-cal-accent, .exc-cal-c.is-accent { --cal-c: var(--exc-accent); --cal-c-rgb: var(--exc-accent-rgb, 214,162,61); }
.exc-cal-rose,   .exc-cal-c.is-rose   { --cal-c: #d1607f; --cal-c-rgb: 209,96,127; }
.exc-cal-coral,  .exc-cal-c.is-coral  { --cal-c: #dd6b4d; --cal-c-rgb: 221,107,77; }
.exc-cal-amber,  .exc-cal-c.is-amber  { --cal-c: #d9922b; --cal-c-rgb: 217,146,43; }
.exc-cal-lime,   .exc-cal-c.is-lime   { --cal-c: #7ba428; --cal-c-rgb: 123,164,40; }
.exc-cal-teal,   .exc-cal-c.is-teal   { --cal-c: #2a9d8f; --cal-c-rgb: 42,157,143; }
.exc-cal-sky,    .exc-cal-c.is-sky    { --cal-c: #2f8fd1; --cal-c-rgb: 47,143,209; }
.exc-cal-indigo, .exc-cal-c.is-indigo { --cal-c: #5b6bd4; --cal-c-rgb: 91,107,212; }
.exc-cal-violet, .exc-cal-c.is-violet { --cal-c: #9061cf; --cal-c-rgb: 144,97,207; }
.exc-cal-slate,  .exc-cal-c.is-slate  { --cal-c: #6b7280; --cal-c-rgb: 107,114,128; }

/* ── Campo con icono dentro, y el ojo de las contraseñas ─────────────────── */

/* Global y no del registro: el acceso y el perfil lo van a querer igual, y dos
   copias del mismo campo acaban separándose. */
.exc-icf { position: relative; display: flex; align-items: center; }

.exc-icf > svg {
  position: absolute;
  left: .8rem;
  /* Sin anclaje vertical, un `absolute` dentro de un contenedor FLEX se coloca
     en su posición estática, que es el borde de ARRIBA: el icono saldría
     pegado al techo del campo en vez de centrado. */
  top: 50%;
  transform: translateY(-50%);
  pointer-events: none;   /* el icono no puede robarle el clic al campo */
  color: var(--exc-muted);
}

.exc-icf .exc-input { width: 100%; min-width: 0; padding-left: 2.5rem; }
.exc-icf-pass .exc-input { padding-right: 2.8rem; }

.exc-ojo {
  position: absolute;
  right: .4rem;
  top: 50%;
  transform: translateY(-50%);
  display: grid;
  place-items: center;
  width: 32px; height: 32px;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--exc-muted);
  cursor: pointer;
}

.exc-ojo:hover { background-color: rgba(127, 127, 127, .16); color: var(--exc-text); }
/* Enseñando la contraseña, el ojo se marca: es un estado que conviene ver de
   reojo antes de que alguien se asome. */
.exc-ojo.is-on { color: var(--exc-accent); }

/* ── El «¿seguro?» del sitio ─────────────────────────────────────────────── */

.exc-conf-velo {
  position: fixed;
  inset: 0;
  z-index: 2000;              /* sobre cualquier hoja: interrumpe a todo */
  background-color: rgba(0, 0, 0, .55);
}

.exc-conf {
  position: fixed;
  z-index: 2001;
  left: 50%;
  /* Anclado por ARRIBA y centrado con `translate`: con `top: 50%` un texto
     largo lo hace crecer hacia los dos lados y en un móvil se sale por el
     borde de abajo, donde están los botones. */
  top: 50%;
  transform: translate(-50%, -50%);
  width: min(26rem, calc(100vw - 2rem));
  max-height: 85dvh;
  overflow-y: auto;
  padding: 1.25rem;
  border: 1px solid var(--exc-border);
  border-radius: 16px;
  background-color: var(--exc-surface);
  box-shadow: 0 20px 60px rgba(0, 0, 0, .5);
}

.exc-conf-t { margin: 0 0 .4rem; font-size: 1.05rem; font-weight: 600; }
.exc-conf-p { margin: 0; font-size: .95rem; line-height: 1.5; }

/* Los datos que hay que REVISAR antes de aceptar.
   Cada uno en su renglón y el valor con letra de máquina: un celular en tipo
   proporcional se lee de corrido y los dígitos repetidos se pierden. Con
   `tabular-nums` cada cifra ocupa lo mismo y el ojo puede contarlas. */
.exc-conf-datos {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: .35rem .75rem;
  margin: .85rem 0 0;
  padding: .75rem .85rem;
  border-radius: 12px;
  background-color: var(--exc-surface-2);
}
.exc-conf-datos dt {
  font-size: .78rem;
  color: var(--exc-muted);
  white-space: nowrap;
}
.exc-conf-datos dd {
  margin: 0;
  font-size: .92rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  word-break: break-word;
}

/* La casilla del «¿seguro?»: la SEGUNDA decisión, cuando la hay.
   Toda la fila es el objetivo del toque —etiqueta incluida— porque un cuadrito
   de 16 px con el pulgar se falla, y fallarlo aquí significa borrar unas fotos
   que se querían conservar (o al revés). */
.exc-conf-chk {
  display: flex; align-items: flex-start; gap: .6rem;
  margin: .9rem 0 0;
  padding: .7rem .85rem;
  font-size: .88rem; line-height: 1.45;
  border-radius: 12px;
  background-color: var(--exc-surface-2);
  cursor: pointer;
}

.exc-conf-chk input {
  flex: none;
  width: 1.05rem; height: 1.05rem;
  margin: .15rem 0 0;
  accent-color: var(--exc-accent);
  cursor: pointer;
}

.exc-conf-pie {
  display: flex;
  justify-content: flex-end;
  gap: .6rem;
  margin-top: 1.25rem;
}

/* En un teléfono los botones van a lo ancho y el de confirmar ABAJO: es donde
   llega el pulgar, y el de cancelar queda donde no se pulsa sin querer. */
@media (max-width: 400px) {
  .exc-conf-pie { flex-direction: column-reverse; }
  .exc-conf-pie .exc-btn { width: 100%; justify-content: center; }
}

/* Lo destructivo se marca con el borde, no solo con el color del botón: un
   diálogo idéntico para «guardar» y para «borrar» se contesta igual sin leer. */
.exc-conf.is-peligro { border-color: var(--exc-danger); }

/* ═══════════════════════════════════════════════════════════════════════════
   El bloque de alta del formulario de acceso
   (`resources/views/components/acceso.php`)
   ═══════════════════════════════════════════════════════════════════════════

   Va aquí y no en un módulo porque el componente es global: lo pintan la
   pantalla de acceso y la landing del área de negocios.

   Existe para separar DOS trabajos que antes tenían el mismo peso. Debajo del
   botón de entrar había dos enlaces seguidos —«¿olvidaste tu contraseña?» y
   «créala aquí»— y quien llega sin cuenta no viene a recuperar nada: viene a
   crearla. Ahora eso es la segunda acción de la pantalla, con su línea y su
   botón, y recuperar la contraseña se queda donde le toca: pequeño, junto al
   campo que falló. */

.exc-acceso-alta {
  margin-top: 1.5rem;
  padding-top: 1.4rem;
  /* La línea NO llega a los bordes: se desvanece por los dos lados. Una regla
     de punta a punta parte la tarjeta en dos mitades que se leen como dos
     tarjetas pegadas; ésta separa sin cortar. */
  border-top: 1px solid transparent;
  border-image: linear-gradient(90deg, transparent, var(--exc-border) 22%,
                                var(--exc-border) 78%, transparent) 1;
}

.exc-acceso-alta-t {
  margin: 0 0 .8rem;
  text-align: center;
  font-size: .9rem;
  color: var(--exc-muted);
}

.exc-acceso-alta .exc-btn { justify-content: center; gap: .5rem; }

/* ══ El selector de emojis ════════════════════════════════════════════════
 *
 * Lo pide `View::component('emoji')` y lo mueve `assets/js/emoji.js`. Vive
 * aquí, con los demás componentes compartidos, y no dentro de un módulo:
 * borrar ese módulo se lo llevaría de las otras pantallas que lo usen.
 *
 * Ojo: el panel es `absolute` sobre el documento —lo coloca el JS con la
 * posición del botón, ya sumado el desplazamiento de la página—. Una regla de
 * grupo que le ponga `position: relative` a un ancestro lo movería de sitio,
 * y ganaría por ESPECIFICIDAD, no por orden.
 */

.exc-emoji-campo { position: relative; display: block; }

/* El botón se mete DENTRO del campo, arriba a la derecha. En un textarea el
   texto empieza arriba a la izquierda, así que ahí no tapa nada de lo escrito
   hasta que hay muchas líneas — y entonces ya se está mirando el final. */
.exc-emoji-abrir {
    position: absolute;
    top: .35rem;
    right: .35rem;
    /* 44×44 de área tocable, que es lo que pide un dedo. */
    width: 44px;
    height: 44px;
    display: grid;
    place-items: center;
    font-size: 1.15rem;
    line-height: 1;
    border: 0;
    border-radius: .5rem;
    background: none;
    cursor: pointer;
    opacity: .55;
    transition: opacity .15s ease, background-color .15s ease;
}
.exc-emoji-abrir:hover,
.exc-emoji-abrir[aria-expanded="true"] {
    opacity: 1;
    background: var(--exc-bg-soft, var(--exc-bg));
}

/* El campo deja sitio para el botón. Sin esto, la primera línea se escribe
   por debajo y el texto queda partido de una forma que parece un error. */
.exc-emoji-campo > .exc-textarea,
.exc-emoji-campo > .exc-input { padding-right: 3rem; }

.exc-emoji {
    position: absolute;
    /* Por encima de TODO lo que pueda contener un campo de texto.
     *
     * Estaba en 60, que basta cuando el campo vive en una página normal —así
     * nació, en el editor de Comercio— pero no cuando quien lo abre es una capa
     * a pantalla completa: el compositor de Momentos está en 1110 y el panel
     * quedaba enterrado detrás. Un selector que se abre y no se ve se lee como
     * un botón roto.
     *
     * 1210 lo deja también sobre las ventanas del sitio (1200), que es lo
     * correcto para un desplegable: se abre DESDE ellas. Y por debajo de los
     * avisos flotantes (2000), que interrumpen a todo. */
    z-index: 1210;
    width: min(20rem, calc(100vw - 1rem));
    background: var(--exc-surface);
    border: 1px solid var(--exc-border);
    border-radius: var(--exc-radius, .75rem);
    box-shadow: 0 8px 28px rgb(0 0 0 / .18);
    overflow: hidden;
}
.exc-emoji[hidden] { display: none; }

.exc-emoji-tabs {
    display: flex;
    gap: .15rem;
    padding: .35rem;
    overflow-x: auto;
    scrollbar-width: none;
    border-bottom: 1px solid var(--exc-border);
}
.exc-emoji-tabs::-webkit-scrollbar { display: none; }

.exc-emoji-tab {
    flex: none;
    font: inherit;
    font-size: .72rem;
    padding: .25rem .5rem;
    border: 0;
    border-radius: 999px;
    background: none;
    color: var(--exc-muted);
    white-space: nowrap;
    cursor: pointer;
}
.exc-emoji-tab.is-on {
    color: var(--exc-accent);
    background: color-mix(in srgb, var(--exc-accent) 12%, transparent);
}

/* Alto fijo: sin él, el grupo de 102 símbolos estiraba el panel hasta salirse
   de la pantalla y el de 49 lo dejaba diminuto — el panel cambiaba de tamaño
   al cambiar de pestaña. */
.exc-emoji-cuerpo {
    max-height: 14rem;
    overflow-y: auto;
    padding: .35rem;
    overscroll-behavior: contain;
}

.exc-emoji-grupo {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(2.1rem, 1fr));
    gap: .1rem;
}
.exc-emoji-grupo[hidden] { display: none; }

.exc-emoji-b {
    aspect-ratio: 1;
    display: grid;
    place-items: center;
    /* El emoji lo dibuja el sistema con SUS colores: aquí `font-size` es lo
       único que se toca. Teñirlo no se puede y no hace falta — que traiga sus
       colores es justo lo que se busca en el contenido. */
    font-size: 1.35rem;
    line-height: 1;
    border: 0;
    border-radius: .35rem;
    background: none;
    cursor: pointer;
    padding: 0;
}
.exc-emoji-b:hover,
.exc-emoji-b:focus-visible { background: var(--exc-bg-soft, var(--exc-bg)); }

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

/* ══ El sello de verificación ══════════════════════════════════════════════
 *
 * Dos niveles con la MISMA silueta: una roseta de seis lóbulos gordos —un
 * sello de lacre, no la ráfaga de ocho puntas que usan todas las demás—. Lo
 * que cambia entre azul y oro es el acabado, no la figura: dos figuras
 * distintas dirían «dos cosas distintas», y son lo mismo un nivel más arriba.
 *
 * Los trazos van en `Verificado::svg()`. Aquí solo vive el TAMAÑO, y va en
 * `em` a propósito: el sello crece con la letra de su contexto —grande junto
 * al nombre de un perfil, pequeño en una fila de la tabla del admin— sin una
 * regla por sitio.
 */
.exc-sello {
  width: 1.05em; height: 1.05em;
  flex: none;
  vertical-align: -.16em;
  /* Nunca se encoge en un flex apretado: medio sello es un sello roto. */
  min-width: 1.05em;
}

/* Un pelín de sombra para que despegue del fondo. Sin ella, el azul sobre una
   superficie oscura y el oro sobre una clara se funden con lo de detrás. */
.exc-sello-azul { filter: drop-shadow(0 1px 2px rgba(47, 125, 209, .35)); }
.exc-sello-oro  { filter: drop-shadow(0 1px 3px rgba(169, 118, 26, .45)); }

/* Junto a un nombre va pegado a él, no al elemento siguiente: separado por
   igual de los dos parecía un icono suelto entre dos cosas. */
.exc-sello + * { margin-left: .1rem; }

/* ── Soltar un archivo ─────────────────────────────────────────────────────
   Sustituye al control del navegador, que es el único del sitio que no obedece
   al tema, al idioma ni al tamaño de letra —y que en inglés dice «No file
   chosen» aunque la persona tenga Exclivia en español—.

   Es un `<label>`: tocarlo abre el selector sin una línea de JS, así que sin
   guion sigue siendo un campo de archivo que funciona. */
.exc-soltar {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: .3rem;
  min-height: 118px;
  padding: 1rem;
  border: 2px dashed var(--exc-border);
  border-radius: 14px;
  background: var(--exc-surface-2);
  color: var(--exc-muted);
  text-align: center;
  cursor: pointer;
  transition: border-color .15s, background-color .15s;
}

.exc-soltar:hover,
.exc-soltar:focus-within { border-color: var(--exc-accent); }

/* Mientras el archivo va encima. El cambio es EVIDENTE a propósito: soltar es
   un gesto a ciegas y hay que ver dónde se va a caer antes de abrir la mano. */
.exc-soltar.is-sobre {
  border-color: var(--exc-accent);
  border-style: solid;
  background-color: rgba(var(--exc-accent-rgb), .1);
}

.exc-soltar-vacio { display: grid; place-items: center; gap: .15rem; }
.exc-soltar-vacio svg { width: 1.7em; height: 1.7em; opacity: .7; }
.exc-soltar-vacio strong { font-size: .92rem; color: var(--exc-text); font-weight: 600; }
.exc-soltar-vacio small  { font-size: .78rem; }

/* Con algo dentro se enseña la foto y se retira la invitación: repetir
   «arrastra aquí» encima de la imagen que ya está puesta confunde sobre si se
   guardó o no. */
.exc-soltar.tiene { padding: .55rem; border-style: solid; }
.exc-soltar.tiene .exc-soltar-vacio { display: none; }

.exc-soltar-prev { margin: 0; width: 100%; }
.exc-soltar-prev img {
  display: block;
  width: 100%;
  max-height: 220px;
  object-fit: contain;
  border-radius: 10px;
}

/* El pie solo aparece con archivo: vacío deja un hueco que descuadra la caja. */
.exc-soltar-pie { display: none; align-items: center; gap: .6rem; width: 100%; }
.exc-soltar.tiene .exc-soltar-pie { display: flex; }

.exc-soltar-pie [data-ex-soltar-nom] {
  flex: 1 1 auto;
  min-width: 0;
  font-size: .78rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
