:root {
  /* El color de todo lo que hace la IA: el rosa del logo, con la misma
     transparencia con la que se ve ahí. El rosa puro es #FF7475, y al 45% sobre
     blanco da el #FFC0C1 de los círculos del logo cuando se superponen.

     Va como botón **claro con texto oscuro** y no al revés: el rosa del logo con
     texto blanco encima da 2.6:1, muy por debajo del 4.5:1 de WCAG AA, y
     oscurecerlo hasta que el blanco se lea lo convierte en un vino tinto que no
     tiene nada que ver con la marca. Así se lee a 5.9:1 y sigue siendo el rosa
     del logo.

     Por qué no el violeta que usa todo el mundo: es el default de nadie. Salió
     de que Tailwind puso `indigo-500` en 2019, lo copiaron los tutoriales, y hoy
     es lo que cualquier modelo genera solo — al punto de que se lo reconoce como
     la huella del diseño hecho por IA. Las chispas sí son convención de verdad y
     se quedan; el color es el de la marca. */
  --psico-ai-bg: #ffc0c1;
  --psico-ai-bg-hover: #ffb3b3;
  --psico-ai-ink: #8a1c2b;
  --psico-ai-soft: #ffe0e1;
  --psico-ai-rgb: 255, 116, 117;
}

/* El botón de IA. Uno solo en toda la app: si alguna pantalla lo dibuja de otro
   color, deja de servir para lo único que sirve, que es reconocer de un vistazo
   que del otro lado hay un modelo. Va siempre con `ui/_icon_ai.html` adelante. */
.btn-ai {
  --tblr-btn-color: var(--psico-ai-ink);
  --tblr-btn-bg: var(--psico-ai-bg);
  --tblr-btn-border-color: var(--psico-ai-bg);
  --tblr-btn-hover-color: var(--psico-ai-ink);
  --tblr-btn-hover-bg: var(--psico-ai-bg-hover);
  --tblr-btn-hover-border-color: var(--psico-ai-bg-hover);
  --tblr-btn-active-color: var(--psico-ai-ink);
  --tblr-btn-active-bg: var(--psico-ai-bg-hover);
  --tblr-btn-active-border-color: var(--psico-ai-bg-hover);
  --tblr-btn-disabled-color: var(--psico-ai-ink);
  --tblr-btn-disabled-bg: var(--psico-ai-bg);
  --tblr-btn-disabled-border-color: var(--psico-ai-bg);
  --tblr-btn-focus-shadow-rgb: var(--psico-ai-rgb);
  color: var(--psico-ai-ink);
  background-color: var(--psico-ai-bg);
  border-color: var(--psico-ai-bg);
}

.btn-ai:hover,
.btn-ai:focus,
.btn-ai:active {
  color: var(--psico-ai-ink);
  background-color: var(--psico-ai-bg-hover);
  border-color: var(--psico-ai-bg-hover);
}

/* El encabezado de un grupo tiene que verse como una región, no como un
   renglón más.

   El `.card-header` de Tabler es blanco y sus filas también, así que el título
   del grupo quedaba a un borde de distancia de la primera fila: la división
   existía en las palabras y no en la pantalla. Lo que separa dos grupos no es
   más texto ni un ícono por fila —dentro de un grupo todas las filas comparten
   la misma respuesta, así que repetirlo no informa— sino fondo: un plano
   distinto es lo que hace que el ojo cierre la región sin leer nada.
   -------------------------------------------------------------------------- */
.psico-group-header {
  /* No sirve `--tblr-bg-surface-tertiary`: es #f9fafb, un 2% de blanco. Es el
     mismo gris con el que Tabler pinta la tira de pestañas y que ya se había
     descartado por invisible. Un plano que no se ve no separa nada. */
  background: #eef1f6;
}

/* El engranaje de la barra, cuando uno está en Configuración.

   Tabler pinta `.btn-ghost-*.active` con el fondo del color al 100%: un
   cuadrado gris oscuro, que es una **tercera** manera de decir «estás aquí»
   —el menú lateral lo dice con el azul de marca y una barra, las pestañas con
   el azul y un subrayado—. La regla del proyecto es que eso se diga una sola
   vez y de la misma forma, así que acá también es el azul.
   -------------------------------------------------------------------------- */
.navbar .btn-ghost-secondary.active {
  color: var(--tblr-primary);
  background: rgba(var(--tblr-primary-rgb), .08);
}

/* --------------------------------------------------------------------------
   Jerarquía: por qué la ficha «parecía encimada».

   No era falta de espacio —la separación entre bloques ya era 8/24— sino falta
   de **contraste**. En todo el panel Resumen había exactamente **dos tamaños de
   letra**, 12 y 14 px, y los encabezados de sección eran `<h3 class="h4">`, que
   en Tabler mide 14 px en negrita: lo mismo que la etiqueta de cada fila que el
   encabezado agrupa. Sin diferencia de tamaño no hay jerarquía posible y todo
   pesa igual, que es exactamente lo que se ve.

   Se resuelve con tres niveles y no más: el encabezado de sección a 16/600, la
   etiqueta de fila a 14/500 en gris, y el valor a 14/400 en tinta. El de arriba
   respira el doble de lo que separa lo que agrupa (1.5rem contra .25rem), que es
   lo que hace que la sección se lea como una sola cosa.
   -------------------------------------------------------------------------- */
.psico-section-title {
  margin: 1.5rem 0 .25rem;
  font-size: 1rem;
  font-weight: 600;
  line-height: 1.4;
}

/* Cuando abre la tarjeta no hace falta el aire de arriba: ya lo pone la tarjeta. */
.card-body > .psico-section-title:first-child,
.psico-section-title.mt-0 {
  margin-top: 0;
}

/* La etiqueta de una fila «etiqueta: valor». Estaba en `<strong>`, que la dejaba
   con el mismo peso que el encabezado de su propia sección. */
.psico-row-label {
  font-weight: 500;
  color: var(--tblr-secondary, #667382);
}

/* El `datagrid` de Tabler reparte por `--tblr-datagrid-item-width`, que por
   defecto es 15rem: en la columna de la ficha —que mide unos 400 px— eso no
   entra dos veces nunca, así que siete datos de una palabra («52 años»,
   «Masculino») se apilaban en más de 400 px de alto. Con 8.5rem forman dos
   columnas y ocupan menos de la mitad. */
.psico-datagrid-compact {
  --tblr-datagrid-item-width: 8.5rem;
  --tblr-datagrid-padding: .75rem;
}

/* El lápiz y el disquete: la misma corrección que ya se le hizo al botón de IA,
   que acá no se había aplicado. `btn-warning` dibuja un ícono blanco sobre
   ámbar —2,04:1— y `btn-success` blanco sobre verde —2,63:1—, cuando el mínimo
   de WCAG AA para un control gráfico es 3:1. Y en estos dos el ícono **es** la
   etiqueta: no hay palabra al lado que lo salve.

   Se corrige con tinta oscura, igual que en `.btn-ai`, en vez de oscurecer el
   fondo: el ámbar oscurecido hasta que el blanco se lea deja de ser ámbar. */
.btn-warning {
  --tblr-btn-color: #1a2229;
  --tblr-btn-hover-color: #1a2229;
  --tblr-btn-active-color: #1a2229;
  --tblr-btn-disabled-color: #1a2229;
  color: #1a2229;
}

.btn-success {
  --tblr-btn-color: #0b3d17;
  --tblr-btn-hover-color: #0b3d17;
  --tblr-btn-active-color: #0b3d17;
  --tblr-btn-disabled-color: #0b3d17;
  color: #0b3d17;
}

/* ------------------------------------------------------------------------
   El foco del teclado: uno solo, y en un solo lugar
   ------------------------------------------------------------------------

   Esto decía ser «uno solo» y era una lista de tres: `.btn`, el `summary` de un
   bloque y la fila de un listado. Todo lo demás quedaba con lo que el navegador
   ponga o —peor— con lo mismo que el hover del mouse, que es lo que le pasaba
   al menú lateral: enfocar un ítem con Tab pintaba el mismo blanco al 68 % que
   pasarle el mouse por encima. Diez ítems, y tabular por el menú es lo primero
   que hace quien no usa mouse.

   Va sobre `:focus-visible` a secas, sin lista de componentes, y esa es la
   parte que importa: el próximo control que alguien agregue lo hereda sin
   acordarse de nada. La lista era justamente la forma de olvidarse.

   `:focus-visible` y no `:focus`: el navegador ya distingue el foco que llega
   por teclado del que llega por clic, y dibujar el anillo al hacer clic en un
   botón es ruido. En un campo de texto sí lo dibuja con el mouse, y también
   corresponde.

   **El anillo va por fuera** (`outline-offset: 2px`) y antes iba por dentro.
   Adentro de un `.btn-primary` es un contorno azul sobre fondo azul: no se ve
   nada, y es el botón principal de cada pantalla. Por fuera se recorta contra
   el fondo de la página cualquiera sea el color del control.

   Y lleva `!important`, que en este archivo se usa en dos lugares y los dos por
   la misma razón: Tabler apaga el `outline` en unas cuantas reglas suyas
   —`.nav-link:focus-visible { outline: 0 }` entre ellas— y las escribe con una
   clase, así que le ganan a un `:focus-visible` a secas. La alternativa era
   volver a una lista de componentes, que es justo lo que este cambio saca: una
   lista no cubre lo que todavía no existe. Las dos excepciones de abajo lo
   llevan también, y dicen por qué. */
:focus-visible {
  outline: 2px solid var(--tblr-primary, #206bc4) !important;
  outline-offset: 2px;
}

/* Adentro, y sólo aquí: lo que llena su caja hasta el borde. En una fila de
   listado o en la pestaña de una tarjeta, el anillo de afuera queda cortado por
   el borde de la tarjeta y se lee como media línea suelta. */
.list-group-item-action:focus-visible,
.psico-block > summary:focus-visible,
.nav-tabs .nav-link:focus-visible,
.dropdown-item:focus-visible,
.psico-sidebar .nav-link:focus-visible {
  outline-offset: -2px;
}

/* --------------------------------------------------------------------------
   El gesto: qué pasa cuando se aprieta algo.

   Son dos cosas distintas y las dos faltaban. **La presión** —que el control se
   hunda al tocarlo— es la confirmación de que el clic llegó, y se paga en
   milisegundos. **La espera** es lo que se muestra mientras el servidor
   contesta, y es lo que pidió Orlando: hasta hoy sólo lo tenía el botón de IA,
   así que 65 de los 76 botones que envían un formulario dejaban la pantalla
   idéntica. Por el `paint holding` del navegador no se mueve ni un píxel, y lo
   que hace cualquiera pasados cinco segundos es volver a apretar: una nota
   clínica duplicada, una factura enviada dos veces.

   Vive acá y no en cada pantalla por la misma razón que `.btn-ai`: un solo
   dibujo en toda la app. Antes de esto había **siete** maneras de decir «estoy
   trabajando», ninguna compartida, así que la octava pantalla inventaba la
   octava.
   -------------------------------------------------------------------------- */

/* Tabler declara `.btn:active` con color y sombra pero **no incluye `transform`
   en su `transition`**, así que hay que repetir la lista entera: si sólo se
   agrega la propiedad, el hundido ocurre pero no se anima de vuelta. */
.btn,
.psico-block > summary,
.nav-link,
.dropdown-item {
  transition: color .15s ease-in-out, background-color .15s ease-in-out,
              border-color .15s ease-in-out, box-shadow .15s ease-in-out,
              transform .08s ease-in-out;
}

.btn:active,
.psico-block > summary:active,
.nav-link:active,
.dropdown-item:active {
  transform: translateY(1px);
}

/* El estado de espera.

   **La caja no cambia ni un píxel**, y ésa es la regla que hace que sirva: la
   versión anterior reemplazaba el contenido del botón, así que «Descartar mis
   cambios y volver a generarlo» se convertía en «Escribiendo…» y la fila entera
   se corría de lugar. Acá el texto se vuelve transparente —sigue midiendo lo
   mismo— y el spinner se dibuja encima, centrado. */
.is-pending {
  position: relative;
  color: transparent !important;
  cursor: progress;
  pointer-events: none;
}

.is-pending > * {
  visibility: hidden;
}

.is-pending::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 1rem;
  height: 1rem;
  margin: -0.5rem 0 0 -0.5rem;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  /* `currentColor` es transparente por la regla de arriba, así que el color se
     repone acá: el spinner hereda el del botón sin que haya que declararlo por
     variante. */
  color: var(--tblr-btn-color, var(--tblr-body-color));
  animation: psico-spin .6s linear infinite;
}

/* El botón de IA es el único que dice además el verbo, porque su espera es de
   entre seis y veinte segundos y el spinner solo no alcanza para explicarla.

   Con verbo el spinner deja de ir centrado y se ancla a la izquierda, en el
   lugar que ocupaban las chispas: centrar los dos obligaría a medir el texto,
   y `attr()` no se puede usar en un cálculo. */
.is-pending[data-busy]::before {
  content: attr(data-busy);
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding-left: 1.25rem;
  color: var(--tblr-btn-color, var(--tblr-body-color));
  font-size: inherit;
  white-space: nowrap;
}

.is-pending[data-busy]::after {
  left: .75rem;
  margin-left: 0;
}

@keyframes psico-spin {
  to { transform: rotate(360deg); }
}

/* La barra indeterminada, para lo que pasa de diez segundos: transcribir un
   audio (hasta dos minutos) y subir un adjunto de 25 MB. Un spinner que gira
   dos minutos deja de leerse como progreso y empieza a leerse como colgado. */
.psico-progress-indeterminate {
  position: relative;
  height: 3px;
  margin-top: .5rem;
  overflow: hidden;
  background-color: var(--tblr-border-color);
  border-radius: 3px;
}

.psico-progress-indeterminate::after {
  content: "";
  position: absolute;
  inset: 0;
  width: 40%;
  background-color: var(--tblr-primary);
  border-radius: inherit;
  animation: psico-slide 1.1s ease-in-out infinite;
}

@keyframes psico-slide {
  from { transform: translateX(-100%); }
  to { transform: translateX(250%); }
}

/* Quien pidió menos movimiento no pierde el feedback: pierde la animación. El
   spinner se queda quieto y la barra se dibuja llena y fija, que sigue diciendo
   «esto está en curso». */
@media (prefers-reduced-motion: reduce) {
  .btn,
  .psico-block > summary,
  .nav-link,
  .dropdown-item {
    transition: color .15s ease-in-out, background-color .15s ease-in-out,
                border-color .15s ease-in-out, box-shadow .15s ease-in-out;
  }
  .btn:active,
  .psico-block > summary:active,
  .nav-link:active,
  .dropdown-item:active {
    transform: none;
  }
  .is-pending::after,
  .psico-progress-indeterminate::after {
    animation: none;
  }
  .psico-progress-indeterminate::after {
    width: 100%;
  }
}

/* La etiqueta que dice que un texto lo escribió la IA. Más suave que el botón:
   no es una acción, es un dato. */
.badge-ai {
  color: var(--psico-ai-ink);
  background-color: var(--psico-ai-soft);
}

/* El espacio del scrollbar queda siempre reservado: sin esto, al pasar de una
   página alta a una corta desaparece la barra y todo el contenido se ensancha
   unos píxeles (se nota entre secciones de Configuración, por ejemplo al pasar
   de "Preferencias de trabajo" a "Recordatorios").

   `scrollbar-gutter: stable` es la forma moderna de pedir eso y es lo que había
   acá, pero **no funciona**: medido en Edge/Chromium 151 sobre Windows, en una
   página mínima sin nada más, `documentElement.clientWidth` sigue saltando 15px
   al desaparecer el contenido. El navegador dice soportar la propiedad
   (`CSS.supports` da true, `getComputedStyle` devuelve "stable") y la ignora en
   el elemento raíz. Se queda declarada por si algún día la respeta, y el que
   realmente reserva el espacio es `overflow-y: scroll`, el truco de siempre. */
html {
  overflow-y: scroll;
  scrollbar-gutter: stable;
}

/* Y la otra mitad del mismo problema, que no es el ancho sino la posición.
   Tabler declara en `tabler.min.css`, de 992px para arriba,
   `:host, :root { margin-left: calc(100vw - 100%) }`. `100vw` mide **con** la
   barra de scroll y `100%` **sin** ella, así que ese margen vale 15px cuando la
   página scrollea y 0 cuando entra entera: la página completa se corre 15px a
   la derecha y se angosta otros 15. Es el truco para que un contenido centrado
   no salte al aparecer la barra; con la barra lateral anclada a la izquierda
   hace justo lo contrario, y es lo que se veía al pasar de una sección de
   Configuración a otra —el menú interno y todo lo de su derecha cambiaban de
   lugar—. Medido: el hueco entre la barra lateral y la tarjeta pasa de 31.2px a
   16px, y la tarjeta de 1188 a 1203.

   Hacen falta las dos reglas: `overflow-y: scroll` mantiene el ancho y ésta
   mantiene el lugar. Con una sola queda la mitad del salto. */
@media (min-width: 992px) {
  :root {
    margin-left: 0;
    margin-right: 0;
  }
}

body {
  letter-spacing: 0;
}

.navbar-brand img,
.brand-logo {
  border-radius: 10px;
}

.auth-cover {
  min-height: 100vh;
}

.auth-onboarding-page {
  align-items: stretch;
  justify-content: flex-start;
  min-height: 100vh;
  overflow-y: auto;
  padding-top: max(1rem, env(safe-area-inset-top));
}

.auth-onboarding-page > .container {
  margin-top: 0;
}

.auth-panel {
  width: min(100%, 420px);
}


.metric-card .subheader {
  min-height: 18px;
}

.patient-status {
  width: 0.65rem;
  height: 0.65rem;
  border-radius: 999px;
  display: inline-block;
}

.clinical-timeline {
  position: relative;
  padding-left: 1.25rem;
}

.clinical-timeline::before {
  content: "";
  position: absolute;
  left: 0.35rem;
  top: 0.25rem;
  bottom: 0.25rem;
  width: 1px;
  background: var(--tblr-border-color);
}

.clinical-timeline-item {
  position: relative;
  padding-bottom: 1rem;
}

.clinical-timeline-item::before {
  content: "";
  position: absolute;
  left: -1.08rem;
  top: 0.35rem;
  width: 0.55rem;
  height: 0.55rem;
  border-radius: 999px;
  background: var(--tblr-primary);
  box-shadow: 0 0 0 4px #fff;
}

.calendar-slot {
  border-left: 3px solid var(--tblr-primary);
}

.notes-box {
  min-height: 116px;
}

.voice-dictation {
  border: 1px solid var(--tblr-border-color);
  border-radius: var(--tblr-border-radius);
  padding: 1rem;
  background: var(--tblr-bg-surface);
}

/* El alto fijo es para los campos con dictado de la ficha
   (`_dictation_field.html`), que son campos normales de un formulario. La caja
   de redacción libre (`.psico-composer`) crece con el texto y queda excluida a
   propósito: esta regla le ganaba por especificidad y la dejaba arrancando de
   180px con la mitad vacía. */
.voice-dictation:not(.psico-composer) textarea {
  min-height: 180px;
}

.navbar-search {
  max-width: 520px;
}

.mobile-search-bar {
  background: var(--tblr-bg-surface);
  border-bottom: 1px solid var(--tblr-border-color);
}

.psico-sidebar .offcanvas-header {
  min-height: 64px;
  border-bottom: 1px solid var(--tblr-border-color);
}

.psico-sidebar .navbar-nav {
  align-items: stretch;
  width: 100%;
  min-width: 0;
  overflow-x: hidden;
}

.psico-sidebar .nav-item {
  width: 100%;
  min-width: 0;
}

.psico-sidebar .nav-link {
  justify-content: flex-start;
  gap: .75rem;
  text-align: left;
  min-width: 0;
  max-width: 100%;
  overflow-x: hidden;
}

.psico-sidebar .nav-link-icon {
  flex: 0 0 1.5rem;
  margin-right: 0;
}

.psico-sidebar .nav-link-title {
  display: inline-flex;
  align-items: center;
  flex: 0 1 auto;
  gap: .375rem;
  min-width: 0;
  width: auto;
  max-width: calc(100% - 2.25rem);
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Dónde estoy. El menú no lo decía nunca: diez ítems iguales en las diez
   pantallas. Se marca con el celeste de la marca, no con el gris de hover, para
   que el estado se distinga de "el mouse está encima". */
.psico-sidebar .nav-link.active {
  color: var(--tblr-primary);
  background: rgba(var(--tblr-primary-rgb), .08);
  font-weight: 600;
  border-radius: var(--tblr-border-radius, 4px);
  box-shadow: inset 3px 0 0 var(--tblr-primary);
}

.psico-sidebar .nav-link.active .nav-link-icon {
  color: var(--tblr-primary);
}

.psico-nav-disabled {
  color: var(--tblr-secondary);
  cursor: not-allowed;
  opacity: .78;
}

.psico-nav-disabled:hover,
.psico-nav-disabled:focus-visible {
  color: var(--tblr-secondary);
  text-decoration: none;
}

.psico-nav-soon {
  flex: 0 0 auto;
  position: static !important;
  inset: auto !important;
  transform: none !important;
  margin-left: 0;
  vertical-align: middle;
  font-size: .625rem;
  font-weight: 500;
  white-space: nowrap;
}

.psico-breadcrumb {
  margin-bottom: .25rem;
}

.psico-breadcrumb .breadcrumb {
  --tblr-breadcrumb-divider-color: var(--tblr-secondary);
  margin-bottom: 0;
  font-size: .8125rem;
}

.psico-breadcrumb .breadcrumb-item {
  color: var(--tblr-secondary);
}

/* Los eslabones son la vuelta atrás de toda la plataforma, así que tienen que
   parecer enlaces: en gris de texto y sin subrayado se leían como el rastro
   impreso de dónde estás, no como algo que se toca. */
.psico-breadcrumb .breadcrumb-item a {
  color: var(--tblr-body-color);
  text-decoration: none;
}

.psico-breadcrumb .breadcrumb-item a:hover,
.psico-breadcrumb .breadcrumb-item a:focus-visible {
  color: var(--tblr-primary);
  text-decoration: underline;
}

.psico-breadcrumb .breadcrumb-item.active {
  color: var(--tblr-muted);
}

.psico-user-avatar,
.psico-profile-avatar-preview {
  overflow: hidden;
  background: var(--tblr-bg-surface);
  border-radius: 999px;
}

.psico-user-avatar img,
.psico-profile-avatar-preview img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  border-radius: 999px;
}

.psico-avatar-carousel {
  --psico-avatar-visible: 5;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: .5rem;
  max-width: 30rem;
  margin-inline: auto;
}

.psico-avatar-carousel-viewport {
  overflow: hidden;
  flex: 1 1 auto;
  min-width: 0;
}

.psico-avatar-carousel-track {
  display: flex;
  align-items: center;
  transition: transform .18s ease;
  will-change: transform;
}

.psico-avatar-carousel-btn {
  flex: 0 0 auto;
  width: 2rem;
  height: 2rem;
  min-height: 2rem;
  color: var(--tblr-secondary);
  border-color: transparent;
  box-shadow: none;
}

.psico-avatar-carousel-btn:hover:not(:disabled),
.psico-avatar-carousel-btn:focus-visible {
  color: var(--tblr-primary);
  background: rgba(var(--tblr-primary-rgb), .06);
  border-color: rgba(var(--tblr-primary-rgb), .16);
}

.psico-avatar-carousel-btn:disabled {
  opacity: .32;
  cursor: not-allowed;
}

.psico-avatar-option {
  position: relative;
  display: grid;
  place-items: center;
  flex: 0 0 calc(100% / var(--psico-avatar-visible));
  cursor: pointer;
  padding: .25rem;
}

.psico-avatar-option input {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

.psico-avatar-option-card {
  display: grid;
  place-items: center;
  width: 3.75rem;
  height: 3.75rem;
  border: 1px solid transparent;
  border-radius: 999px;
  background: transparent;
  transition: border-color .16s ease, box-shadow .16s ease;
}

.psico-avatar-option-card img {
  width: 3.25rem;
  height: 3.25rem;
  border-radius: 999px;
  object-fit: cover;
  display: block;
}

.psico-avatar-option:hover .psico-avatar-option-card,
.psico-avatar-option input:focus-visible + .psico-avatar-option-card {
  border-color: rgba(var(--tblr-primary-rgb), .48);
  box-shadow: 0 0 0 .125rem rgba(var(--tblr-primary-rgb), .12);
}

.psico-avatar-option input:checked + .psico-avatar-option-card {
  border-color: var(--tblr-primary);
  box-shadow: 0 0 0 .1875rem rgba(var(--tblr-primary-rgb), .18);
}

.btn-list {
  align-items: center;
}

.psico-sidebar-close {
  display: none;
}

@media (min-width: 992px) {
  body {
    --psico-sidebar-expanded-width: 15rem;
    --psico-sidebar-collapsed-width: 4.75rem;
    --psico-sidebar-current-width: var(--psico-sidebar-expanded-width);
  }

  body.sidebar-collapsed {
    --psico-sidebar-current-width: var(--psico-sidebar-collapsed-width);
  }

  .psico-sidebar,
  .page-wrapper,
  .page > .navbar:not(.navbar-vertical) {
    transition: width .18s ease, max-width .18s ease, flex-basis .18s ease, margin-left .18s ease, padding-left .18s ease;
  }

  .navbar-vertical.navbar-expand-lg.psico-sidebar {
    flex: 0 0 var(--psico-sidebar-current-width);
    width: var(--psico-sidebar-current-width);
    max-width: var(--psico-sidebar-current-width);
    background-color: #f3f7fb !important;
    border-right: 1px solid rgba(31, 41, 55, .08);
    box-shadow: 1px 0 0 rgba(255, 255, 255, .82) inset, 4px 0 14px rgba(31, 41, 55, .025);
    overflow-x: hidden;
    /* Tabler pone `overflow-y: scroll` en `.navbar-vertical`, así que el menú
       dibujaba una barra con sus flechas apagadas aunque las nueve opciones
       entraran de sobra. Con `auto` la barra aparece sólo si de verdad no
       entran (pantalla baja, zoom grande), que es cuando hace falta. */
    overflow-y: auto;
  }

  .page-wrapper,
  .page > .navbar:not(.navbar-vertical) {
    width: calc(100% - var(--psico-sidebar-current-width)) !important;
    margin-left: var(--psico-sidebar-current-width) !important;
    padding-left: 0 !important;
  }

  .navbar-vertical.navbar-expand-lg.psico-sidebar > .container-fluid {
    align-items: stretch;
    width: 100%;
    max-width: none;
    padding-right: .75rem;
    padding-left: .75rem;
    background-color: #f3f7fb;
    overflow-x: hidden;
  }

  .psico-sidebar-header {
    align-items: center;
    justify-content: space-between;
    gap: .75rem;
    min-height: 64px;
    width: 100%;
    padding: .75rem 0;
  }

  .psico-sidebar-brand {
    display: inline-flex;
    align-items: center;
    gap: .625rem;
    min-width: 0;
    color: inherit;
    max-width: 100%;
  }

  .psico-sidebar-brand:hover {
    color: inherit;
  }

  .psico-sidebar .nav-link {
    border-radius: var(--tblr-border-radius);
  }

  .psico-sidebar .nav-link:hover,
  .psico-sidebar .nav-link:focus-visible {
    background: rgba(255, 255, 255, .68);
  }

  .psico-sidebar .psico-nav-disabled:hover,
  .psico-sidebar .psico-nav-disabled:focus-visible {
    background: rgba(255, 255, 255, .48);
  }

  .psico-sidebar-logo-wrap {
    position: relative;
    display: inline-grid;
    place-items: center;
    flex: 0 0 2.25rem;
    width: 2.25rem;
    height: 2.25rem;
    border-radius: var(--tblr-border-radius);
  }

  .psico-sidebar-logo,
  .psico-sidebar-open-icon {
    grid-area: 1 / 1;
    pointer-events: none;
    transition: opacity .14s ease, transform .14s ease;
  }

  .psico-sidebar-open-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.25rem;
    height: 2.25rem;
    color: var(--tblr-secondary);
    opacity: 0;
    transform: scale(.92);
  }

  .psico-sidebar-brand-text {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .psico-sidebar-close {
    display: inline-flex;
    flex: 0 0 auto;
  }

  .psico-sidebar .navbar-brand {
    width: 100%;
    margin-right: 0;
    min-width: 0;
  }

  .psico-sidebar .navbar-brand > a {
    min-width: 0;
  }

  .navbar-vertical.navbar-expand-lg.psico-sidebar .nav-link {
    justify-content: flex-start !important;
  }

  body.sidebar-collapsed .psico-sidebar {
    width: var(--psico-sidebar-collapsed-width);
  }

  body.sidebar-collapsed .navbar-vertical.navbar-expand-lg.psico-sidebar > .container-fluid,
  body.sidebar-collapsed .psico-sidebar .offcanvas-body,
  body.sidebar-collapsed .psico-sidebar .navbar-nav {
    width: var(--psico-sidebar-collapsed-width);
    max-width: none;
    overflow-x: hidden;
  }

  body.sidebar-collapsed .navbar-vertical.navbar-expand-lg.psico-sidebar > .container-fluid {
    padding-right: 0;
    padding-left: 0;
  }

  body.sidebar-collapsed .psico-sidebar-header {
    justify-content: center;
    padding-right: 0;
    padding-left: 0;
  }

  body.sidebar-collapsed .psico-sidebar-brand {
    justify-content: center;
    width: 2.75rem;
    height: 2.75rem;
    border-radius: var(--tblr-border-radius);
    cursor: pointer;
  }

  body.sidebar-collapsed .psico-sidebar-brand:hover,
  body.sidebar-collapsed .psico-sidebar-brand:focus-visible {
    background: rgba(255, 255, 255, .72);
  }

  body.sidebar-collapsed .psico-sidebar-brand:hover .psico-sidebar-logo,
  body.sidebar-collapsed .psico-sidebar-brand:focus-visible .psico-sidebar-logo {
    opacity: 0;
    transform: scale(.92);
  }

  body.sidebar-collapsed .psico-sidebar-brand:hover .psico-sidebar-open-icon,
  body.sidebar-collapsed .psico-sidebar-brand:focus-visible .psico-sidebar-open-icon {
    opacity: 1;
    transform: scale(1);
  }

  body.sidebar-collapsed .psico-sidebar-brand-text,
  body.sidebar-collapsed .psico-sidebar-close {
    display: none;
  }

  /* El texto del enlace no se oculta con `display:none`: eso lo saca del árbol
     de accesibilidad y deja ocho enlaces sin nombre —un lector de pantalla
     anuncia "enlace" ocho veces—. Se saca de la vista sin sacarlo del árbol; el
     tooltip para quien ve lo pone `syncSidebar()` al plegar. */
  body.sidebar-collapsed .psico-sidebar .nav-link-title {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
  }

  body.sidebar-collapsed .psico-nav-disabled {
    opacity: .66;
  }

  body.sidebar-collapsed .psico-nav-soon {
    display: none;
  }

  body.sidebar-collapsed .navbar-vertical.navbar-expand-lg.psico-sidebar .nav-link {
    justify-content: center !important;
    width: 100%;
    padding-right: 0;
    padding-left: 0;
  }

  body.sidebar-collapsed .psico-sidebar .nav-link-icon {
    display: inline-flex !important;
    align-items: center;
    justify-content: center;
    flex: 0 0 1.5rem;
    width: 1.5rem;
    margin: 0;
  }

  body.sidebar-collapsed .page-wrapper,
  body.sidebar-collapsed .page > .navbar:not(.navbar-vertical) {
    width: calc(100% - var(--psico-sidebar-collapsed-width)) !important;
    margin-left: var(--psico-sidebar-collapsed-width) !important;
    padding-left: 0 !important;
  }
}

.modal-dialog {
  max-width: min(var(--tblr-modal-width), calc(100vw - 1rem));
}

.table-responsive {
  overflow-x: auto;
}

@media (max-width: 991.98px) {
  .psico-sidebar.offcanvas-lg {
    width: min(78vw, 300px);
    max-width: calc(100vw - 64px);
    overflow-x: hidden;
  }

  .psico-sidebar > .container-fluid {
    display: block;
    min-height: 100%;
    padding-right: 0;
    padding-left: 0;
  }

  .psico-sidebar .offcanvas-header {
    align-items: center;
    justify-content: space-between;
    padding: .875rem 1rem;
  }

  .psico-sidebar .navbar-brand {
    margin-right: .75rem;
    min-width: 0;
  }

  .psico-sidebar .navbar-brand span {
    max-width: 170px;
  }

  .psico-sidebar .offcanvas-body {
    padding: .75rem;
    overflow-x: hidden;
    overflow-y: auto;
  }

  .psico-sidebar .navbar-nav {
    width: 100%;
    padding-top: 0 !important;
  }

  .psico-sidebar .nav-item {
    width: 100%;
  }

  .psico-sidebar .nav-link {
    justify-content: flex-start !important;
    gap: .75rem;
    min-height: 44px;
    padding: .625rem .75rem;
    border-radius: var(--tblr-border-radius);
  }

  .psico-breadcrumb .breadcrumb {
    font-size: .75rem;
    flex-wrap: wrap;
  }

  .psico-sidebar .nav-link-icon {
    flex: 0 0 1.5rem;
    margin-right: 0;
  }

  .page .navbar:not(.navbar-vertical) .container-xl {
    min-height: 56px;
    gap: .5rem;
  }

  .page .navbar-brand {
    min-width: 0;
  }

  .page .navbar-brand span {
    max-width: 44vw;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  /* --- La cabecera de la pantalla, en el teléfono -------------------------
     La regla es una sola: **se estira la acción principal y nada más**. Es el
     objetivo del pulgar y es lo que se viene a hacer acá. Lo secundario conserva
     su tamaño y se alinea a la derecha, que es donde la cabecera ya lo pone en
     pantalla ancha, así que no hay dos comportamientos que aprender.

     Antes se estiraba todo, y eso convertía cualquier enlace en el botón más
     grande de la pantalla. En la Biblioteca, «Mi Biblioteca» —que es un enlace a
     otra pantalla y **a propósito** no es primario, según lo que dice el
     comentario de su plantilla— se dibujaba como una barra de borde a borde
     encima del catálogo entero: decía exactamente lo contrario de lo que se
     había decidido. Y en la ficha del paciente eran cuatro barras apiladas antes
     de la primera línea de la historia clínica.

     `:has()` es lo que permite preguntar «¿esta cabecera tiene acción
     principal?» sin agregarle una clase a cada plantilla. Ya se usa para abrir
     el panel del genograma sin JavaScript. */
  .page-header .row {
    row-gap: .75rem;
  }

  .page-header .col-auto {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: .5rem;
  }

  /* Con más de una acción, el bloque se lleva el renglón entero para que no
     queden apretadas contra el título. */
  .page-header .col-auto:has(.btn-primary),
  .page-header .col-auto:has(.btn + .btn),
  .page-header .col-auto:has(.btn-list) {
    width: 100%;
    margin-left: 0 !important;
  }

  .page-header .btn-list {
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: .5rem;
    width: 100%;
  }

  /* El botón suelto y solo, sin grupo alrededor: el mismo criterio. */
  .page-header .col-auto > .btn:only-child,
  .page-header .col-auto > form:only-child,
  .page-header .col-auto > form:only-child > .btn {
    width: 100%;
  }

  /* El menú de avisos se salía **por la izquierda de la pantalla**: mide 21rem,
     se alinea con el borde derecho de la campanita, y la campanita está a unos
     260 px del borde en un teléfono, así que empezaba en negativo y las tres
     primeras letras de cada renglón quedaban fuera del vidrio.

     En vez de pelearle al posicionamiento que calcula Popper —que es lo que hace
     que cualquier arreglo parcial vuelva a romperse—, acá se lo reemplaza
     entero: la caja se ancla a los dos bordes de la pantalla, debajo de la
     barra. En un teléfono un desplegable de este tamaño es una hoja, no un
     globo colgado de un botón. */
  .psico-notifications-menu.dropdown-menu {
    position: fixed !important;
    inset: 3.5rem .5rem auto .5rem !important;
    width: auto;
    max-width: none;
    transform: none !important;
  }

  .card-header {
    align-items: stretch;
    gap: .75rem;
  }

  .card-header > .card-title {
    width: 100%;
  }

  .psico-avatar-carousel {
    --psico-avatar-visible: 3;
    gap: .25rem;
    max-width: 21rem;
  }

  .psico-avatar-option-card {
    width: 3.5rem;
    height: 3.5rem;
  }

  .psico-avatar-option-card img {
    width: 3rem;
    height: 3rem;
  }

  .modal-dialog {
    margin: .5rem;
  }
}

@media (max-width: 575.98px) {
  .container-xl {
    padding-right: .875rem;
    padding-left: .875rem;
  }

  .page-title {
    font-size: 1.25rem;
    line-height: 1.25;
  }

  .btn-list {
    gap: .5rem;
  }

  /* --- Qué se estira en el teléfono, y qué no ------------------------------
     Esta era **la** regla que hacía ver mal la app en pantalla angosta: decía
     que *todo* botón dentro de un grupo ocupa el ancho, así que la ficha del
     paciente eran cuatro barras apiladas antes de la primera línea de la
     historia clínica, y cualquier enlace secundario se dibujaba tan importante
     como la acción principal. Estirar todo es lo mismo que no jerarquizar nada.

     Se estira **la acción cuando es la única**, y nada más. Ahí no hay nada de
     qué distinguirla y el ancho entero la hace fácil de acertar con el pulgar.

     Con dos o más, ninguna se estira: se acomodan lado a lado. Estirar la
     principal las partía en renglones distintos, y en Cobros eso separaba
     «Registrar una seña» de «Registrar un cobro», que son dos formas de lo
     mismo y se leen juntas o no se leen. La jerarquía entre ellas ya la dice el
     color; no hace falta decirla otra vez con el tamaño.

     Es una regla más chica que la anterior en todos los casos: una pantalla que
     tenía un solo botón se ve igual que antes. */
  .btn-list > .btn:only-child,
  .btn-list > form:only-child,
  .btn-list > form:only-child > .btn {
    width: 100%;
  }

  .card-body,
  .card-header {
    padding: .875rem;
  }
}

/* Tabs desplazables sin barras de scroll visibles (evita las flechitas del scrollbar de Windows) */
.psico-tabs-scroll {
  display: flex;
  flex-wrap: nowrap;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
  -ms-overflow-style: none;
}

.psico-tabs-scroll::-webkit-scrollbar {
  display: none;
}

/* Centrado seguro en paginas de acceso: con contenido mas alto que el viewport,
   justify-content:center recorta la parte superior; los margenes auto no. */
.page-center {
  justify-content: flex-start;
}

.page-center > .container-tight {
  margin-top: auto;
  margin-bottom: auto;
}

/* reCAPTCHA centrado dentro de la card de acceso */
.psico-recaptcha {
  display: flex;
  justify-content: center;
}

/* Menu de avisos de la campanita */
.psico-notifications-menu {
  width: 21rem;
  max-width: 92vw;
  padding: 0;
}

.psico-notifications-list {
  max-height: 21rem;
  overflow-y: auto;
}

.psico-notification-dot {
  flex-shrink: 0;
}

/* Texto del consentimiento informado en el formulario de admisión:
   alto acotado y con scroll propio, para que el formulario no se vuelva
   infinito y el botón de aceptar siga a la vista. */
.psico-consent-text {
  max-height: 16rem;
  overflow-y: auto;
  font-size: 0.875rem;
  line-height: 1.5;
}
.psico-consent-text p:last-child {
  margin-bottom: 0;
}

/* Configuración por secciones: navegación lateral en escritorio y una fila de
   pestañas desplazable en móvil, para no comer media pantalla con una columna. */
.psico-settings-nav-list {
  gap: 0.25rem;
  padding: 0.75rem;
}
@media (max-width: 767.98px) {
  .psico-settings-nav {
    border-right: 0 !important;
    border-bottom: 1px solid var(--tblr-border-color);
  }
  .psico-settings-nav-list {
    flex-wrap: nowrap;
    overflow-x: auto;
  }
}

/* Genograma: se dibuja a tamaño natural y se achica si no entra; si es muy ancho
   scrollea dentro de su marco en vez de romper el layout de la página. */
.psico-genogram-frame {
  overflow-x: auto;
  padding: 0.5rem 0;
  /* Un genograma más angosto que el marco se ve centrado, no pegado a la izquierda. */
  text-align: center;
}
.psico-genogram {
  max-width: 100%;
  height: auto;
  color: var(--tblr-body-color);
}
.psico-genogram .geno-name {
  font-size: 13px;
  font-weight: 600;
  fill: currentColor;
}
.psico-genogram .geno-date,
.psico-genogram .geno-union-label {
  font-size: 11px;
  fill: var(--tblr-secondary);
}
.psico-genogram .geno-age {
  font-size: 13px;
  fill: currentColor;
}
.psico-genogram .geno-note {
  font-size: 10px;
  fill: var(--tblr-secondary);
}

/* intl-tel-input envuelve el input en un .iti que por defecto no ocupa el ancho
   de la columna: el campo de teléfono quedaba más angosto que los de al lado. */
.iti {
  width: 100%;
}
.iti__tel-input {
  width: 100%;
}
/* La bandera y el selector heredan el alto y el borde de Tabler. */
.iti--separate-dial-code .iti__selected-country {
  background-color: transparent;
  border-radius: var(--tblr-border-radius) 0 0 var(--tblr-border-radius);
}

/* ---------------------------------------------------------------------------
   Avisos flotantes (django.contrib.messages)

   Estaban al tope del contenido y se perdían de vista cuando la página venía
   scrolleada: la persona guardaba algo, el aviso aparecía arriba y parecía que
   no había pasado nada. Fijos sobre la pantalla se ven siempre.
   --------------------------------------------------------------------------- */
.psico-toast-stack {
  position: fixed;
  z-index: 1090; /* por encima del modal de Bootstrap (1055) */
  /* Arriba a la derecha, cerca de donde está la vista al navegar: abajo se
     pasaban por alto ("Elemento eliminado" quedaba muy abajo, QA de Karina). */
  top: 4rem;
  left: 1rem;
  right: 1rem;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  pointer-events: none; /* el fondo sigue siendo clickeable entre avisos */
}

@media (min-width: 576px) {
  .psico-toast-stack {
    left: auto;
    max-width: 26rem;
  }
}

.psico-toast {
  pointer-events: auto;
  margin: 0;
  box-shadow: 0 0.5rem 1.5rem rgba(24, 36, 51, 0.18);
  animation: psico-toast-in 0.18s ease-out;
}

/* Sobre el fondo de color pleno, la cruz de cerrar tiene que ser blanca. */
.psico-toast.alert-important .btn-close {
  filter: invert(1) grayscale(1) brightness(2);
}

/* Lo que sale bien no grita. El fondo verde pleno venía de un hallazgo correcto
   —el alert de Tabler pasaba desapercibido como aviso flotante— pero la salida
   no era pintar la barra entera: una franja saturada arriba de la pantalla se
   lee como una alarma, y guardar el perfil no es una alarma.

   Lo que lo hace visible acá es **la sombra y el ícono**, no el relleno, que es
   lo que hacen hoy las apps de este tipo. El error y la advertencia conservan el
   fondo pleno: son la excepción y tienen que frenar a quien va rápido. */
.psico-toast--ok,
.psico-toast--info {
  display: flex;
  align-items: center;
  gap: .625rem;
  background: var(--tblr-bg-surface);
  border: var(--tblr-border-width) solid var(--tblr-border-color);
  color: var(--tblr-body-color);
  font-weight: 500;
}

.psico-toast--ok .icon,
.psico-toast--info .icon {
  flex-shrink: 0;
}

/* --- La huella se toca, no se lee ------------------------------------------
   Un botón ancho que dice «Entrar con mi huella» explica con palabras algo que
   el dibujo ya dice: cualquiera que haya desbloqueado un teléfono reconoce una
   huella y sabe que se toca. Es además el idioma que usan los bancos de acá, que
   es donde la profesional ya aprendió el gesto.

   El rótulo se queda **debajo y chico**: la primera vez todavía hace falta, y no
   compite con el dibujo. */
.psico-fingerprint {
  display: flex;
  align-items: center;
  justify-content: center;
  /* 5,5 rem = 88 px, que es la medida del círculo en la referencia. Antes eran
     8 rem: un 47 % más grande, y con un dibujo que igual no lo llenaba. */
  width: 5.5rem;
  height: 5.5rem;
  margin: 0 auto;
  padding: 0;
  border-radius: 50%;
  /* Gris y sin borde, que es al revés de como estaba. Con el círculo blanco, el
     dibujo quedaba sobre el mismo plano que la tarjeta de arriba y no tenía
     dónde apoyarse; sobre un gris apenas más oscuro que el fondo, las crestas
     se separan y el círculo se lee como una superficie donde poner el dedo —que
     es lo que hacen las apps de banco de las que salió este gesto.

     El borde se va: con el relleno gris ya hay una forma, y el borde encima la
     duplicaba con una línea más fina que el propio dibujo.

     **El tono sale de la paleta y no de un hex escrito a mano.** El fondo de esa
     pantalla es `gray-100` (#f3f4f6); el círculo es `gray-200`, el escalón
     siguiente de la misma rampa. Un hex inventado —#e9edf2, que era lo que
     había— cae en otra familia: más azulado, y al lado del fondo se nota que son
     dos grises distintos y no dos niveles del mismo. Además, tomarlo de la
     paleta lo hace seguir al tema oscuro sin escribir nada más. */
  border: var(--tblr-border-width) solid transparent;
  background: var(--tblr-gray-200);
  color: var(--tblr-primary);
  transition: background-color .15s ease, transform .1s ease;
}

/* El dibujo ocupa **casi todo** el círculo, y para eso hay que contar dos veces:
   el trazo de la huella llena sólo un 70 % de su propio `viewBox` —tiene aire
   arriba y a los costados—, así que un ícono al 56 % del círculo dibujaba una
   huella al 37 % y el resto era espacio vacío. A 6,5 rem dentro de 8, el trazo
   visible queda en torno al 68 % del diámetro, que es la proporción que tiene en las
   apps donde este gesto ya se aprendió. */
/* 4,5 rem, y el número sale de una medición y no del ojo: el trazado llena el
   74,2 % de su lienzo, así que 4,5 rem dibujan una huella de 53 px dentro de un
   círculo de 88 — el 61 %, que es la proporción de la referencia. */
.psico-fingerprint .icon {
  width: 4.5rem;
  height: 4.5rem;
}

/* Mientras espera. El spinner de `pending.js` mide 1rem y va centrado, que es lo
   correcto en un botón de una línea y se pierde adentro de un círculo de 8rem:
   acá se agranda a la medida del dibujo que reemplaza. */
.psico-fingerprint.is-pending::after {
  width: 2rem;
  height: 2rem;
  margin: -1rem 0 0 -1rem;
  border-width: 3px;
  color: var(--tblr-primary);
}

.psico-fingerprint:hover {
  background: var(--tblr-gray-300);
}

.psico-fingerprint:active {
  transform: scale(.96);
}

.psico-toast.is-leaving {
  opacity: 0;
  transform: translateY(-0.5rem);
  transition: opacity 0.2s ease, transform 0.2s ease;
}

@keyframes psico-toast-in {
  from { opacity: 0; transform: translateY(-0.5rem); }
  to { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .psico-toast,
  .psico-toast.is-leaving { animation: none; transition: none; }
}

/* Panel "Agregar al genograma": se elige qué agregar y aparece ese formulario.

   Lo hacía JavaScript poniendo y sacando el atributo `hidden`, así que sin él
   se veían los cuatro botones y ningún formulario: el genograma no se podía
   cargar. Ahora lo dice el CSS a partir del radio marcado, que es un estado del
   documento y no de un script, y cuál viene marcado lo decide el servidor
   —`active_section`— cuando un formulario vuelve con errores o se está
   editando. El JavaScript no participa.

   Los cuatro selectores nombran los ids porque CSS no puede comparar el valor
   de un radio con el de un atributo. Es el precio de que la pantalla funcione
   sin JavaScript, y son cuatro líneas. */
#geno-add [data-geno-section] {
  display: none;
}

#geno-add:has(#geno-choice-person:checked) [data-geno-section="person"],
#geno-add:has(#geno-choice-union:checked) [data-geno-section="union"],
#geno-add:has(#geno-choice-child:checked) [data-geno-section="child"],
#geno-add:has(#geno-choice-relation:checked) [data-geno-section="relation"] {
  display: block;
}

/* La explicación del orden («cada integrante entra como Persona…») se va en
   cuanto se eligió algo: ya cumplió, y abajo hay un formulario que leer. */
#geno-add:has(.btn-check:checked) [data-geno-hint] {
  display: none;
}

/* Panel "Lo que ya está cargado" del genograma: cada grupo colapsado con su
   cuenta. Antes eran cuatro cards de listas y formularios todas juntas. */
.psico-geno-group {
  border-bottom: 1px solid var(--tblr-border-color);
}
.psico-geno-group:last-child {
  border-bottom: 0;
}
.psico-geno-group > summary {
  cursor: pointer;
  padding: 0.625rem 0;
  font-weight: 600;
}
.psico-geno-group > summary:hover {
  color: var(--tblr-primary);
}

/* Leyenda de símbolos del genograma. */
.psico-genogram-legend {
  list-style: none;
  margin: 0.75rem 0 0.5rem;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 1.25rem;
  font-size: 0.8125rem;
  color: var(--tblr-secondary, #667382);
}

.psico-genogram-legend li {
  display: flex;
  align-items: center;
  gap: 0.375rem;
}

.psico-genogram-legend svg {
  width: 18px;
  height: 18px;
  flex: none;
  stroke: currentColor;
  stroke-width: 2;
  fill: none;
}

/* --- Avisos con título --------------------------------------------------- */
/* Tabler deja `.alert` en `display:flex; flex-wrap:nowrap`, así que un
   `.alert-title` se convierte en una columna angosta al costado del texto y el
   título termina partido palabra por palabra («Antes / de / usarlo»). Se corrige
   dejando que el aviso envuelva y que el título ocupe el renglón entero; un
   aviso sin título tiene un solo hijo y no cambia en nada. */

.alert {
  flex-wrap: wrap;
}

.alert .alert-title {
  flex: 1 0 100%;
  margin-bottom: 0.25rem;
}

/* --- Instrumento de la Biblioteca ---------------------------------------- */
/* Se lee como un artículo, no como un tablero: una sola columna de texto con
   medida de lectura acotada, y los datos duros en un recuadro al costado. Con
   tarjetas, un texto corrido se parte en bloques sueltos y se vuelve ilegible.

   La grilla es propia y no row/col de Bootstrap: la medida de lectura hace que
   el texto termine bastante antes que su columna, así que con col-8/col-4 queda
   un hueco vacío entre el texto y el recuadro. Acá la columna de texto mide
   exactamente la medida de lectura y el recuadro arranca pegado a ella; lo que
   sobra queda como margen al borde de la página, que es donde no molesta. */

.psico-article {
  display: grid;
  grid-template-columns: minmax(0, 72ch) minmax(15rem, 22rem);
  gap: 2.5rem;
  /* Las dos celdas van estiradas a la misma altura a propósito: `sticky` solo
     se despega mientras su contenedor pasa por la pantalla, así que con la
     celda a la altura del recuadro no tiene por dónde viajar y el recuadro
     deja de acompañar al scroll. El recuadro igual no se estira: lo sostiene
     arriba el propio `sticky`. */
  align-items: stretch;
}

.psico-wiki {
  font-size: 0.9375rem;
  line-height: 1.7;
  color: var(--tblr-body-color, #1a2229);
}

.psico-wiki > .psico-wiki-lead {
  font-size: 1.125rem;
  line-height: 1.6;
  color: var(--tblr-secondary, #667382);
  margin-bottom: 1.75rem;
}

.psico-wiki h2 {
  font-size: 1.0625rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  margin: 2.25rem 0 0.75rem;
  padding-bottom: 0.375rem;
  border-bottom: 1px solid var(--tblr-border-color, #e6e7e9);
}

.psico-wiki h2:first-of-type {
  margin-top: 0;
}

.psico-wiki h3 {
  font-size: 0.9375rem;
  font-weight: 600;
  margin: 1.5rem 0 0.5rem;
}

.psico-wiki p,
.psico-wiki ul,
.psico-wiki ol {
  margin-bottom: 1rem;
}

/* Texto corrido justificado, con partido de palabra: sin `hyphens` el
   justificado en castellano abre huecos enormes entre palabras. Las viñetas
   quedan en bandera a propósito: son líneas cortas y justificarlas exagera
   esos huecos en vez de disimularlos. */
.psico-wiki p,
.psico-wiki dd {
  text-align: justify;
  text-wrap: pretty;
  hyphens: auto;
}

.psico-wiki ul {
  padding-left: 1.125rem;
}

.psico-wiki li + li {
  margin-top: 0.375rem;
}

.psico-wiki dl {
  margin: 0;
}

.psico-wiki dt {
  font-weight: 600;
  margin-top: 0.875rem;
}

.psico-wiki dt:first-child {
  margin-top: 0;
}

.psico-wiki dd {
  margin: 0.125rem 0 0;
  color: var(--tblr-secondary, #667382);
}

/* Los nombres de las escalas cuando no hay nada que contar de cada una: en
   fila y como etiquetas, no una lista vertical de quince renglones vacíos. */
.psico-wiki .psico-taglist {
  display: flex;
  flex-wrap: wrap;
  gap: 0.375rem;
  list-style: none;
  padding: 0;
  margin: 0 0 1rem;
}

.psico-wiki .psico-taglist li {
  margin: 0;
  padding: 0.125rem 0.5rem;
  border: 1px solid var(--tblr-border-color, #e6e7e9);
  border-radius: 999px;
  background: var(--tblr-bg-surface, #fff);
  font-size: 0.8125rem;
  line-height: 1.5;
}

/* El recuadro de datos duros, al costado y sin competir con el texto. */
.psico-factbox {
  position: sticky;
  top: 1rem;
  border: 1px solid var(--tblr-border-color, #e6e7e9);
  border-radius: var(--tblr-border-radius, 4px);
  background: var(--tblr-bg-surface, #fff);
  padding: 1rem 1.125rem;
  font-size: 0.8125rem;
}

.psico-factbox h2 {
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--tblr-secondary, #667382);
  margin: 0 0 0.75rem;
}

.psico-factbox dl {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.5rem 0.875rem;
  margin: 0;
}

.psico-factbox dt {
  color: var(--tblr-secondary, #667382);
  font-weight: 400;
}

.psico-factbox dd {
  margin: 0;
  text-align: right;
  font-weight: 500;
}

/* El crédito y la licencia: texto corrido, no un dato de la grilla. */
.psico-factbox__note {
  margin: 0.875rem 0 0;
  padding-top: 0.875rem;
  border-top: 1px solid var(--tblr-border-color, #e6e7e9);
  color: var(--tblr-secondary, #667382);
  font-size: 0.75rem;
  line-height: 1.5;
}

/* Cuando hay más de un crédito —la procedencia, la autoría y los derechos de
   un recurso son tres cosas distintas— cada uno dice cuál es. Sin el rótulo son
   tres párrafos grises seguidos y no hay forma de saber cuál es cuál; con el
   rótulo adentro de la grilla, en cambio, el valor queda en una columna angosta
   alineada a la derecha, que es lo que no se puede leer. Va arriba y a lo
   ancho. */
.psico-factbox__note > b {
  display: block;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-size: 0.6875rem;
  margin-bottom: 0.25rem;
}

@media (max-width: 991.98px) {
  .psico-article {
    grid-template-columns: minmax(0, 1fr);
    gap: 1.5rem;
  }

  .psico-factbox {
    position: static;
  }
}

/* --- Asistente público del genograma ------------------------------------- */
/* La tarjeta ya completada se pliega a una línea: con cinco personas cargadas,
   un formulario todo abierto deja de poder leerse. El resumen es un <button>
   para que se llegue con el teclado, así que hay que sacarle el aspecto de
   botón y dejarle el de fila de tarjeta. */
.geno-card-summary {
  width: 100%;
  border: 0;
  background: none;
  color: inherit;
  text-align: left;
  cursor: pointer;
}

.geno-card-summary:hover {
  background: var(--tblr-bg-surface-tertiary, rgba(0, 0, 0, .03));
}

.geno-card-summary .min-w-0 {
  min-width: 0;
}

/* Las cuatro opciones de "¿quién es?" entran en una fila en pantalla ancha y
   se apilan de a dos en un teléfono, que es donde el paciente lo completa.
   El estado normal de Tabler las dibuja con borde fino y fondo blanco, o sea
   iguales a los campos de texto de abajo: la opción elegida se rellena para
   que se vea de un vistazo cuál es, y las otras quedan grises de botón. */
.geno-card .form-selectgroup-item {
  min-width: 8.5rem;
}

.geno-card .form-selectgroup-label {
  background: var(--tblr-bg-surface-secondary, #f6f8fb);
  border-color: transparent;
  font-weight: 500;
}

.geno-card .form-selectgroup-input:checked + .form-selectgroup-label {
  background: var(--tblr-primary);
  border-color: var(--tblr-primary);
  color: #fff;
}

/* Igual que arriba: el radio no se ve, así que el anillo se dibuja sobre su
   etiqueta, que es lo que sí está en pantalla. */
.geno-card .form-selectgroup-input:focus-visible + .form-selectgroup-label {
  outline: 2px solid var(--tblr-primary);
  outline-offset: 2px;
}

/* --- Escala numérica de un cuestionario ----------------------------------- */
/* El CAIM se responde puntuando cada actividad de 0 a 10: once opciones que
   tienen que entrar en una sola fila del teléfono, porque una escala partida en
   dos renglones deja de leerse como una escala. `btn-group` no sirve acá: sus
   botones se dimensionan según el texto y el "10" quedaría más ancho que el "0",
   dando una regla despareja. Por eso se reparte el ancho en once partes iguales
   y se dejan los números centrados. */
.psico-scale {
  display: flex;
  gap: 0.25rem;
}

.psico-scale .btn {
  flex: 1 1 0;
  min-width: 0;
  padding-inline: 0;
  font-variant-numeric: tabular-nums;
}

.psico-scale-anchors {
  display: flex;
  justify-content: space-between;
  margin-top: 0.35rem;
}

@media (max-width: 480px) {
  .psico-scale {
    gap: 0.15rem;
  }

  .psico-scale .btn {
    font-size: 0.8125rem;
  }
}

/* --- Opciones de un cuestionario ------------------------------------------ */
/* Las opciones de un test son frases, no etiquetas de botón: «Toma muy a pecho
   cosas de poca importancia; sufre una profunda conmoción...» no entra en un
   renglón. Bootstrap le pone `white-space: nowrap` a todo `.btn`, así que el
   texto no se cortaba: se salía del recuadro y de la tarjeta, y en las opciones
   en fila una se encimaba con la siguiente. */
.psico-options .btn {
  white-space: normal;
}

/* En fila, que se repartan el ancho en partes iguales. Con el `flex-basis: auto`
   de Bootstrap la opción más larga se lleva más lugar y las tres quedan
   desparejas, que es lo último que se quiere en una escala. */
.psico-options.btn-group > .btn {
  flex: 1 1 0;
}

/* --- Alta del espacio profesional ----------------------------------------- */
/* Los avatares del alta reusan `.psico-avatar-option` pero sin las flechas del
   carrusel de Configuración: acá la lista entra en una fila que se desplaza
   sola, que en un teléfono es un gesto más natural que dos botones chicos. */
.psico-setup-avatars {
  --psico-avatar-visible: 5;
  display: flex;
  gap: .25rem;
  overflow-x: auto;
  padding-bottom: .25rem;
  scroll-snap-type: x proximity;
  -webkit-overflow-scrolling: touch;
}

.psico-setup-avatars .psico-avatar-option {
  flex: 0 0 4.5rem;
  scroll-snap-align: start;
}

/* Los puntos del progreso no deben saltar de ancho al cambiar de paso. */
[data-setup-dot] .badge {
  min-width: 1.5rem;
}

/* --- Páginas legales ------------------------------------------------------ */
/* Texto largo para leer, no para escanear: medida cómoda y aire entre bloques. */
.psico-legal {
  line-height: 1.65;
}

.psico-legal h2 {
  margin-top: 2rem;
}

.psico-legal ul {
  padding-left: 1.25rem;
}

.psico-legal li {
  margin-bottom: .35rem;
}

/* ---------------------------------------------------------------------------
   Asistente de la plataforma.

   Panel a la derecha y no modal: la profesional tiene que poder leer el paso 2
   mientras hace el paso 1. Un modal obliga a memorizar y cerrar, que es
   exactamente lo que hace que la gente no use la ayuda.
   --------------------------------------------------------------------------- */
.psico-help {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  width: 380px;
  max-width: 100vw;
  z-index: 1045;
  display: flex;
  flex-direction: column;
  background: var(--tblr-bg-surface, #fff);
  border-left: 1px solid var(--tblr-border-color, #dadfe5);
  box-shadow: -8px 0 24px rgba(24, 36, 51, 0.08);
}

.psico-help[hidden] {
  display: none;
}

.psico-help__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  padding: 16px 20px;
  border-bottom: 1px solid var(--tblr-border-color, #dadfe5);
}

.psico-help__title {
  font-weight: 700;
}

.psico-help__sub,
.psico-help__note,
.psico-help__state {
  color: var(--tblr-secondary, #667382);
  font-size: 0.875rem;
}

.psico-help__form {
  padding: 16px 20px;
  border-bottom: 1px solid var(--tblr-border-color, #dadfe5);
}

.psico-help__body {
  flex: 1;
  overflow-y: auto;
  padding: 16px 20px 24px;
}

.psico-help__lead {
  font-weight: 600;
  margin-bottom: 12px;
}

.psico-help__answer-title {
  color: var(--tblr-secondary, #667382);
  font-size: 0.8125rem;
  margin-bottom: 6px;
}

/* Los pasos numerados son la respuesta: se leen de un vistazo y se siguen de a
   uno. Ese es todo el formato que hace falta. */
.psico-help__steps {
  margin: 0 0 12px;
  padding-left: 20px;
}

.psico-help__steps li {
  margin-bottom: 8px;
}

.psico-help__note {
  border-left: 2px solid var(--tblr-border-color, #dadfe5);
  padding-left: 10px;
  margin-bottom: 0;
}

/* Ejemplos y alternativas: se tocan, no se escriben. Quien no sabe qué
   preguntar necesita ver una pregunta posible, no un campo vacío. */
.psico-help__chip {
  display: block;
  width: 100%;
  text-align: left;
  border: 1px solid var(--tblr-border-color, #dadfe5);
  border-radius: 8px;
  background: transparent;
  padding: 8px 12px;
  margin-bottom: 8px;
  font-size: 0.875rem;
  color: inherit;
}

.psico-help__chip:hover {
  border-color: var(--tblr-primary, #206bc4);
}

/* El anillo lo pone la regla general; aquí sólo el borde, que es lo propio del
   chip. Estaban juntos con el hover y con `outline: none`, así que quien tabula
   por el panel —que está en las 59 pantallas— no sabía dónde estaba parado. */
.psico-help__chip:focus-visible {
  border-color: var(--tblr-primary, #206bc4);
}

/* En celular ocupa la pantalla: al ancho de un teléfono, un panel de 380px al
   costado no deja ver ni el panel ni la app. */
@media (max-width: 575px) {
  .psico-help {
    width: 100vw;
    border-left: 0;
  }
}

/* Cuál pestaña estoy viendo. Tabler lo resuelve con la metáfora de carpeta: la
   activa toma el blanco de la tarjeta y las inactivas van sobre una tira gris.
   El gris es `gray-50` y el contraste contra el blanco es de un 2%: en pantalla
   no se ve nada, y como el texto activo queda en `inherit`, las siete pestañas
   de la ficha se leen iguales. Se marca con el celeste de la marca y una barra
   inferior, la misma señal que ya usa el menú lateral, para que "dónde estoy"
   se diga una sola vez en toda la app. */
.card-header-tabs .nav-link.active,
.nav-tabs .nav-link.active {
  color: var(--tblr-primary);
  font-weight: 600;
  box-shadow: inset 0 -2px 0 var(--tblr-primary);
}

/* ------------------------------------------------------------------------
   Las pestañas, sin JavaScript
   ------------------------------------------------------------------------

   Bootstrap esconde los paneles con `.tab-content > .tab-pane { display: none }`
   y el único que los vuelve a mostrar es su propio JavaScript, enganchado en
   `data-bs-toggle="tab"`. El contenido viaja en el HTML —está ahí, se descargó—
   pero no hay forma de llegar: el enlace `href="#tab-sesiones"` salta a un
   elemento con `display: none` y la página no se mueve. En la ficha del
   paciente eso son cinco de seis paneles, el 83 % de la historia clínica.

   Se arregla sin JavaScript y sin tocar el servidor: el navegador ya sabe qué
   `#` se pidió, y eso es `:target`.

   Va bajo `html:not(.js)` porque las dos vías no pueden convivir. Con
   JavaScript, Bootstrap cancela el clic y mueve `.active` sin tocar la URL;
   pero el `#tab-recursos` de una redirección sí queda puesto, así que al
   cambiar de pestaña el `:target` seguiría abriendo la vieja y se verían dos
   paneles a la vez. */
html:not(.js) .tab-content > .tab-pane:target {
  display: block;
  opacity: 1;
}

html:not(.js) .tab-content:has(> .tab-pane:target) > .tab-pane:not(:target) {
  display: none;
}

/* Y si hay una pestaña pedida por `#`, la marca de "estoy aquí" se apaga en
   vez de mentir. Sin JavaScript no hay forma genérica de pintar el enlace que
   corresponde —CSS no puede comparar el `href` de uno con el `id` de otro— y
   entre no decirlo y decirlo mal, no decirlo. El panel abierto ya se ve. */
html:not(.js) .card:has(.tab-pane:target) .nav-tabs .nav-link.active {
  color: inherit;
  font-weight: inherit;
  box-shadow: none;
}

/* La tira de las inactivas se separa un poco más del blanco: sin esto la
   pestaña activa se distingue por el color de su texto, pero el borde de la
   carpeta sigue sin verse. */
.card-header-tabs {
  background: var(--tblr-bg-surface-secondary, #f6f8fb);
}

/* El QR de vinculación de Telegram. El SVG sale con medidas en milímetros —así
   lo dibuja la librería— y en pantalla eso no significa nada: se le fija el
   ancho acá y el alto sale del viewBox. */
.psico-qr {
  width: 168px;
  max-width: 100%;
}

.psico-qr svg {
  width: 100%;
  height: auto;
  display: block;
}

/* Un canal de avisos: email y Telegram, uno por tarjeta.

   Iban corridos, uno atrás del otro dentro del mismo cuerpo, y se leían como
   una sola cosa —con el agravante de que el segundo tiene estado (vinculado o
   no) y el primero no—. Son tarjetas livianas y no `.card`: la sección entera
   ya vive adentro de una, y anidar tarjetas con sombra encima de una tarjeta
   con sombra ensucia la jerarquía en vez de aclararla. Alcanza con el borde. */
.psico-channel {
  border: 1px solid var(--tblr-border-color, #e6e7e9);
  border-radius: var(--tblr-border-radius, .25rem);
  overflow: hidden;
}

.psico-channel-head {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: .75rem;
  padding: .75rem 1rem;
  border-bottom: 1px solid var(--tblr-border-color, #e6e7e9);
  background: var(--tblr-bg-surface-secondary, #f6f8fb);
}

.psico-channel-body {
  padding: 1rem;
}

.psico-channel-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: 50%;
  flex: none;
  color: var(--tblr-secondary, #6c7a91);
  background: var(--tblr-bg-surface, #fff);
  border: 1px solid var(--tblr-border-color, #e6e7e9);
}

/* Telegram tiene color propio y la gente lo reconoce antes de leer el título. */
.psico-channel-icon-telegram {
  color: #229ed9;
}

/* Un importe no es un texto largo: el campo tiene el ancho de lo que se escribe
   en él. Ocupando toda la tarjeta prometía un dato que no existe. */
.psico-money {
  max-width: 15rem;
}

/* Buscador sobre un `<select>` largo. Ver `static/js/searchable-select.js`. */
.psico-picker {
  position: relative;
}

.psico-picker-list {
  position: absolute;
  z-index: 1050;
  top: calc(100% + .25rem);
  left: 0;
  right: 0;
  max-height: 17rem;
  overflow-y: auto;
  padding: .25rem;
  background: var(--tblr-bg-surface, #fff);
  border: 1px solid var(--tblr-border-color, #e6e7e9);
  border-radius: var(--tblr-border-radius, .25rem);
  box-shadow: 0 .5rem 1rem rgba(0, 0, 0, .1);
}

.psico-picker-option {
  display: block;
  width: 100%;
  padding: .375rem .5rem;
  text-align: left;
  border: 0;
  border-radius: var(--tblr-border-radius, .25rem);
  background: transparent;
  color: inherit;
}

.psico-picker-option:hover,
.psico-picker-option.is-active {
  background: var(--tblr-bg-surface-secondary, #f6f8fb);
}

.psico-picker-group {
  padding: .375rem .5rem .125rem;
  font-size: .75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .02em;
  color: var(--tblr-secondary, #6c7a91);
}

.psico-picker-empty {
  padding: .5rem;
  color: var(--tblr-secondary, #6c7a91);
}

/* Un bloque de formulario que agrupa una pregunta y lo que depende de ella
   —«¿ya me pagó?» y, si sí, cómo y con qué comprobante—. Suelto, el checkbox
   quedaba flotando sin contexto y su select de al lado parecía otra cosa. */
.psico-fieldset {
  border: 1px solid var(--tblr-border-color, #e6e7e9);
  border-radius: var(--tblr-border-radius, .25rem);
  padding: .875rem 1rem;
  background: var(--tblr-bg-surface-secondary, #f6f8fb);
}

.psico-fieldset > legend {
  float: none;
  width: auto;
  margin-bottom: .5rem;
  padding: 0;
  font-size: .875rem;
  font-weight: 600;
}

/* Selects de opciones cortas (cómo pagó, cuánto antes): del ancho de su
   contenido y no del de la tarjeta. */
.psico-input-sm {
  max-width: 15rem;
}

/* Un número de arriba que además lleva a su lista. Es una tarjeta que es un
   enlace: sin esto el subrayado y el azul de enlace le comen el número. */
.psico-metric-link {
  color: inherit;
  text-decoration: none;
  transition: box-shadow .12s ease;
}

.psico-metric-link:hover,
.psico-metric-link:focus-visible {
  color: inherit;
  text-decoration: none;
  box-shadow: 0 0 0 2px rgba(var(--tblr-primary-rgb), .35);
}

/* --- La caja de redacción libre ------------------------------------------
   Un solo recuadro que crece con lo que se escribe y tiene sus acciones
   adentro, abajo a la derecha: la forma del prompt de un chat, que es la que
   todo el mundo ya usa todos los días en WhatsApp. Antes eran dos botones en
   esquinas opuestas de la caja —dictar arriba a la derecha, ordenar abajo a la
   izquierda— y la mirada tenía que cruzarla en diagonal para hacer dos pasos
   del mismo trabajo.

   El foco se dibuja sobre el recuadro entero y no sobre el textarea, que no
   tiene borde propio: lo que la profesional ve como un control es la caja. */
/* Gana sobre `.voice-dictation`, que trae su propio borde y fondo: la caja es
   las dos cosas a la vez y sin esto se dibujaban dos recuadros. */
.voice-dictation.psico-composer,
.psico-composer {
  border: 1px solid var(--tblr-border-color);
  border-radius: var(--tblr-border-radius);
  background: #fff;
  padding: .75rem;
  transition: border-color .15s ease, box-shadow .15s ease;
}

.psico-composer:focus-within {
  border-color: rgba(var(--tblr-primary-rgb), .48);
  box-shadow: 0 0 0 .125rem rgba(var(--tblr-primary-rgb), .12);
}

/* El campo de adentro no tiene borde propio —lo dibuja la caja— así que apaga
   su anillo (dos líneas abajo) y el foco se dibuja sobre la caja. Con el mismo
   anillo que todo lo demás y no con el resplandor suave de arriba: ése dice
   «hay algo enfocado acá dentro», que es correcto cuando el foco está en el
   micrófono o en el botón de IA, y no alcanza cuando el cursor está en el
   texto. `:has()` distingue las dos cosas; `:focus-within` no puede. */
.psico-composer:has(.psico-composer__input:focus-visible),
.psico-composer:has(.form-control:focus-visible) {
  outline: 2px solid var(--tblr-primary, #206bc4);
  outline-offset: 2px;
}

.psico-composer__input {
  display: block;
  width: 100%;
  border: 0;
  padding: 0;
  resize: none;
  overflow-y: auto;
  background: transparent;
  color: inherit;
  font: inherit;
  line-height: 1.5;
  /* Crece con el texto hasta acá y recién entonces scrollea, para que una nota
     larga no empuje el formulario de la ficha fuera de la pantalla. */
  min-height: 4.5rem;
  max-height: 22rem;
}

/* Excepción declarada al «nunca `outline: none`»: el anillo de este campo lo
   dibuja la caja que lo contiene, dos reglas más arriba. Sin esto habría dos
   anillos, uno adentro del otro. */
.psico-composer__input:focus {
  outline: 0 !important;
  box-shadow: none;
}

/* Un campo del formulario metido en la caja: Django le pone `form-control` y su
   borde propio, que adentro del recuadro dibujaría un segundo marco. Se
   normaliza acá y no en el widget para que el partial de dictado no tenga que
   saber nada del formulario que lo usa. */
.psico-composer .form-control {
  border: 0;
  padding: 0;
  background: transparent;
  box-shadow: none;
  resize: none;
  min-height: 4.5rem;
  max-height: 22rem;
  overflow-y: auto;
}

/* Ídem para el campo que viene del formulario de Django. */
.psico-composer .form-control:focus {
  outline: 0 !important;
  box-shadow: none;
}

.psico-composer__bar {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  flex-wrap: wrap;
  gap: .5rem;
  margin-top: .5rem;
}

/* Lo que la caja está haciendo (grabando, transcribiendo, ordenando) va a la
   izquierda de los botones y empuja: es lo que se lee mientras se espera. */
.psico-composer__bar .voice-dictation__status,
.psico-composer__bar .ai-assist__status {
  margin-right: auto;
}

/* La caja apagada: se sigue viendo, con lo que dice, pero no invita a escribir.
   La forma manual queda entera abajo — nunca se pierde el acceso a la ficha. */
.psico-composer--off {
  background: var(--tblr-bg-surface-secondary, #f6f8fb);
  border-style: dashed;
}

/* --- Botones de ícono chicos ---------------------------------------------
   `.btn-icon` de Tabler compensa el padding del botón con un margen negativo en
   el ícono: `margin: calc(-1 * var(--tblr-btn-padding-x))`. En un botón normal
   eso funciona, pero en `.btn-sm` el padding es .5rem y el ícono 1rem, así que
   el margen se lo come **entero** y el botón queda de 1.6px de ancho — los dos
   bordes y nada más. Se veía como tres puntitos naranjas al lado del nombre del
   paciente.

   Los botones de ícono son chicos por convención en esta app (editar, guardar,
   descartar): acompañan a un contenido y no deben pesar más que él. Así que la
   combinación tiene que funcionar, y acá se le devuelve el tamaño. */
.btn-icon.btn-sm {
  width: 1.75rem;
  height: 1.75rem;
  padding: 0;
}

.btn-icon.btn-sm .icon {
  margin: 0;
}


/* --- Bloques plegables de la entrevista -----------------------------------
   Siete bloques abiertos son cuatro pantallas antes de la primera pregunta, y
   esta pantalla se usa **en sesión**: lo que no se está hablando tiene que
   ocupar una línea. Son `<details>` nativos y no un acordeón de JavaScript
   porque así se pliegan con el JS apagado, y porque lo que queda cerrado se
   envía igual al guardar — un acordeón que desmonta el contenido no.

   **Al `summary` no se le declara el `display`, porque ya lo tiene.** Lleva
   `.card-header`, que es `display: flex`, y un estilo de autor le gana al
   `display: list-item` que el navegador le pone por defecto. Repetirlo acá no
   agrega nada y esconde de dónde viene el layout.

   Lo que sí hay que sacarle es el triangulito del navegador —`list-style` sigue
   haciendo falta— para que quede el chevrón propio, que es el que ya usan las
   filas de Recursos: dos formas distintas de decir "esto se abre" en la misma
   app se leen como dos cosas distintas. */
.psico-block > summary {
  cursor: pointer;
  list-style: none;
}

.psico-block > summary::-webkit-details-marker {
  display: none;
}

.psico-block > summary:hover {
  background: var(--tblr-bg-surface-secondary, #f6f8fb);
}

/* La flecha del bloque. La decide el bloque y no el ícono: el mismo chevron,
   en otro lado, no gira ni es gris. */
.psico-block > summary .icon {
  flex-shrink: 0;
  color: var(--tblr-secondary, #667382);
  transition: transform 0.15s ease-in-out;
}

.psico-block[open] > summary .icon {
  transform: rotate(180deg);
}

/* --- Elegir una opción en un formulario ----------------------------------
   Una lista de opciones donde se elige una. Es **otra cosa** que las opciones
   de un test (`.psico-options`), y conviene tener clara la diferencia porque el
   primer intento las confundió y se veía mal:

   - `.psico-options` es un control segmentado: una barra de botones pegados.
     Está bien ahí porque las opciones de un test son una **escala** —«Nunca …
     Siempre»— y pegarlas dice que son puntos de una misma línea. Además el
     paciente responde ochenta ítems seguidos y la barra le ahorra recorrido.
   - Esto es una **pregunta de formulario con opciones categóricas**: «Antes de
     estudiar», «La noche anterior». No hay línea que las una, así que pegarlas
     afirma algo falso; y el formulario se manda con un botón, no se aplica al
     instante, que es el otro rasgo que distingue a un segmentado de un radio.

   La forma es la que usan los sistemas de diseño de gobierno para formularios
   en el celular (GOV.UK y sus derivados, «radio card»): una fila entera por
   opción, con el círculo del radio a la vista, el texto alineado a la
   izquierda, y toda la fila como área de toque. El círculo se ve **antes** de
   elegir, que es lo que dice «acá tenés que elegir una» — con `btn-check` no se
   ve nada hasta el primer clic. */
.psico-choice {
  display: grid;
  gap: .5rem;
  border: 0;
  padding: 0;
  margin: 0;
}

.psico-choice__option {
  display: flex;
  align-items: center;
  gap: .75rem;
  /* 3rem de alto mínimo: el mínimo recomendado de área táctil es 44-48px, y
     esto se completa con el pulgar y con nervios. */
  min-height: 3rem;
  padding: .625rem .875rem;
  margin: 0;
  border: 1px solid var(--tblr-border-color, #e6e7e9);
  border-radius: var(--tblr-border-radius, .25rem);
  background: var(--tblr-bg-surface, #fff);
  cursor: pointer;
  transition: border-color .12s ease, background-color .12s ease;
}

.psico-choice__option:hover {
  border-color: var(--tblr-primary, #206bc4);
}

/* El input real se esconde pero sigue existiendo: lo lee el lector de pantalla,
   lo recorre el teclado y lo manda el formulario. `opacity: 0` y no
   `display: none`, que lo sacaría del orden de foco. */
.psico-choice__input {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  margin: 0;
}

/* El foco se dibuja sobre la fila, porque el input está escondido y el anillo
   general no tendría dónde aparecer. Es `:focus-within` y no `:focus-visible`
   por lo mismo: quien recibe el foco es el input, no la fila. */
.psico-choice__option:focus-within {
  outline: 2px solid var(--tblr-primary, #206bc4);
  outline-offset: 2px;
}

.psico-choice__mark {
  flex-shrink: 0;
  width: 1.25rem;
  height: 1.25rem;
  border: 2px solid var(--tblr-border-color-active, #a6b0c2);
  border-radius: 50%;
  background: #fff;
  transition: border-color .12s ease, box-shadow .12s ease;
}

.psico-choice__input:checked + .psico-choice__mark {
  border-color: var(--tblr-primary, #206bc4);
  /* El punto de adentro es una sombra y no un pseudo-elemento: así el círculo
     no cambia de tamaño al elegirlo y la fila no se mueve. */
  box-shadow: inset 0 0 0 .25rem var(--tblr-primary, #206bc4);
}

.psico-choice__input:checked ~ .psico-choice__label {
  font-weight: 600;
}

/* La fila elegida se tiñe entera. Es progresivo: donde `:has()` no exista
   —navegadores viejos de teléfono— el punto del círculo ya dice cuál está
   elegida, que es lo que no puede faltar. */
.psico-choice__option:has(.psico-choice__input:checked) {
  border-color: var(--tblr-primary, #206bc4);
  background: var(--tblr-primary-lt, #ecf3fb);
}

/* --- La lista de viñetas con ícono ----------------------------------------
   El ícono hace de viñeta: verde, alineado con la primera línea del texto y
   sin encogerse cuando la oración es larga. Estaba escrito en cada `<svg>`
   —cuatro veces la misma terna de clases— y no es una propiedad del ícono
   sino del lugar: el mismo sobre, en un botón, no es verde. */
.psico-hints .icon {
  color: var(--tblr-green);
  flex-shrink: 0;
  margin-top: .125rem;
}
