.comments-panel {
  width: min(560px, 96vw);
  max-height: min(82vh, 720px);
  display: flex;
  flex-direction: column;
  padding: 0;
  overflow: hidden;
}

.comments-head {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
  border-bottom: 1px solid var(--line);
  flex: 0 0 auto;
}

.comments-head-copy {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  min-width: 0;
  max-width: calc(100% - 80px);
}

.comments-head-copy strong {
  font-size: 15px;
  color: var(--text);
}

.comments-subtitle {
  font-size: 12px;
  color: var(--text-muted);
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Centrado con `inset` + `margin: auto`, NO con `transform`. El estilo comun de
   `.modal-close` cambia el transform al pasar el raton (un `scale` del 3%), y
   como transform es una sola propiedad, ese hover se cargaba el
   `translateY(-50%)` que centraba: la cruz se caia media altura de golpe. Asi el
   centrado no depende del transform y el hover vuelve a ser el detalle que
   pretendia ser. */
.comments-close {
  position: absolute;
  left: 10px;
  top: 0;
  bottom: 0;
  margin-block: auto;
}

.comments-list {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 14px 16px;
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.comments-item {
  display: flex;
  gap: 10px;
  align-items: flex-start;
}

.comments-item-avatar {
  flex: 0 0 auto;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  border-radius: 999px;
}

.comments-avatar {
  width: 34px;
  height: 34px;
  border-radius: 999px;
  object-fit: cover;
  display: grid;
  place-items: center;
}

.comments-item-body {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.comments-item-text {
  margin: 0;
  font-size: 14px;
  line-height: 1.45;
  color: var(--text);
  word-break: break-word;
}

.comments-item-name {
  padding: 0;
  border: 0;
  background: none;
  color: var(--text);
  font-weight: 700;
  font-size: 14px;
  cursor: pointer;
  margin-right: 4px;
}

/* --- Respuestas -------------------------------------------------------------
   Un solo nivel de anidado: la respuesta se mete hacia dentro y con avatar mas
   pequeno, para que se lea como parte del hilo y no como un comentario suelto. */
.comments-item.is-reply {
  margin-left: 32px;
}

.comments-item.is-reply .comments-avatar {
  width: 26px;
  height: 26px;
  font-size: 12px;
}

.comments-thread {
  display: flex;
  flex-direction: column;
  gap: 14px;
  margin-top: -6px;
}

.comments-thread-toggle {
  display: flex;
  align-items: center;
  gap: 10px;
  align-self: flex-start;
  margin-left: 32px;
  padding: 0;
  border: 0;
  background: none;
  color: var(--text-soft);
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
}

.comments-thread-toggle:hover {
  color: var(--text);
}

.comments-thread-line {
  display: block;
  width: 22px;
  height: 1px;
  background: var(--line);
}

.comments-item-meta {
  display: flex;
  align-items: center;
  gap: 12px;
}

.comments-item-reply {
  padding: 0;
  border: 0;
  background: none;
  color: var(--text-soft);
  font-size: 11px;
  font-weight: 700;
  cursor: pointer;
}

.comments-item-reply:hover {
  color: var(--text);
}

/* Barra "Respondiendo a ..." justo encima del compositor: sin ella no se ve a
   quien va lo que estas escribiendo. */
.comments-reply-bar {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 8px 16px;
  border-top: 1px solid var(--line);
  background: var(--bg-2);
  font-size: 12px;
  color: var(--text-soft);
}

.comments-reply-bar strong {
  color: var(--text);
}

.comments-reply-cancel {
  flex: 0 0 auto;
  width: 26px;
  height: 26px;
  padding: 0;
  display: grid;
  place-items: center;
  border-radius: 999px;
  font-size: 12px;
}

.comments-item-time {
  font-size: 11px;
  color: var(--text-soft);
}

/* --- Borrar un comentario ---------------------------------------------------
   Dos puertas al mismo menu: los tres puntos (raton, donde hay sitio y hover) y
   mantener pulsado el comentario (dedo, donde no lo hay). El boton solo se
   pinta si de verdad puedes borrar: quien escribio el comentario y el admin. */
.comments-item {
  position: relative;
}

.comments-item-tools {
  position: relative;
  flex: 0 0 auto;
  margin-left: auto;
}

.comments-item-menu-toggle {
  display: inline-grid;
  place-items: center;
  width: 28px;
  height: 28px;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: none;
  color: var(--text-muted);
  font-size: 14px;
  cursor: pointer;
  /* Discreto hasta que la mano se acerca: en una lista de comentarios, tres
     puntos a plena luz en cada linea pesan mas que los propios comentarios. */
  opacity: 0.45;
  transition: opacity 0.16s ease, color 0.16s ease, background 0.16s ease;
}

.comments-item:hover .comments-item-menu-toggle,
.comments-item-menu-toggle:hover,
.comments-item-menu-toggle:focus-visible {
  opacity: 1;
  color: var(--text);
  background: rgba(255, 255, 255, 0.07);
}

/* Con el dedo no hay hover y el menu se abre manteniendo pulsado, asi que los
   tres puntos sobran: se quitan de en medio y el texto gana el ancho. */
@media (hover: none) {
  .comments-item-tools {
    display: none;
  }
}

.comments-item-menu {
  position: absolute;
  top: calc(100% + 4px);
  right: 0;
  z-index: 5;
  min-width: 208px;
  padding: 6px;
  border: 1px solid var(--line-strong, rgba(255, 255, 255, 0.16));
  border-radius: 12px;
  background: var(--surface-2, #16161a);
  box-shadow: 0 14px 30px rgba(0, 0, 0, 0.45);
}

/* Con el dedo el menu nace del propio comentario (los tres puntos no existen),
   asi que se ancla al comentario y no a un boton que esta oculto. */
@media (hover: none) {
  .comments-item-menu {
    display: block;
    position: absolute;
    top: auto;
    bottom: -6px;
    right: 8px;
  }

  .comments-item-tools:has(.comments-item-menu:not(.hidden)) {
    display: block;
    position: static;
  }
}

.comments-item-menu-item {
  display: flex;
  align-items: center;
  gap: 9px;
  width: 100%;
  padding: 9px 11px;
  border: 0;
  border-radius: 9px;
  background: none;
  color: var(--text);
  font-size: 13.5px;
  font-weight: 600;
  text-align: left;
  cursor: pointer;
}

.comments-item-menu-item:hover,
.comments-item-menu-item:focus-visible {
  background: rgba(255, 255, 255, 0.07);
}

.comments-item-menu-item.is-danger {
  color: #ff8a8a;
}

.comments-item-menu-item.is-danger:hover,
.comments-item-menu-item.is-danger:focus-visible {
  background: rgba(255, 92, 92, 0.14);
}

.comments-empty {
  margin: auto;
  text-align: center;
  color: var(--text-muted);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 30px 12px;
}

.comments-empty i {
  font-size: 28px;
  opacity: 0.5;
}

.comments-empty p {
  margin: 0;
  font-weight: 700;
  color: var(--text);
}

.comments-compose {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 12px 16px calc(12px + env(safe-area-inset-bottom));
  border-top: 1px solid var(--line);
}

.comments-compose input {
  flex: 1;
  min-width: 0;
  height: 42px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--bg-2);
  color: var(--text);
  padding: 0 16px;
  font-size: 14px;
  outline: none;
}

.comments-compose input:focus {
  border-color: var(--primary);
}

.comments-send-btn {
  flex: 0 0 auto;
  width: 42px;
  height: 42px;
  border-radius: 999px;
  display: grid;
  place-items: center;
  font-size: 15px;
}

/* ============================================================
   Comentarios: hoja inferior (movil) / panel lateral (PC).
   Por defecto —movil y tablet— sale DESDE ABAJO ocupando el ancho, con las
   esquinas superiores redondeadas y un tirador, estilo Instagram. En PC con
   sitio (>=1025px) se acopla como panel LATERAL derecho a pantalla completa.
   Se engancha a las clases modal-enter/modal-leave que pone show()/hide(). */
/* El alto lo manda `visualViewport`, no la pantalla: con el teclado abierto, el
   "100%" del navegador sigue contando el trozo que tapan las teclas y el
   compositor se quedaba debajo. `--comments-vh` y `--comments-vt` los pone
   `syncCommentsViewport()` en cuanto el teclado entra o sale. */
#commentsModal {
  align-items: flex-end;
  justify-content: center;
  top: var(--comments-vt, 0px);
  height: var(--comments-vh, 100%);
}
#commentsModal .comments-panel {
  width: 100%;
  max-width: 100%;
  max-height: min(86vh, var(--comments-vh, 86vh));
  border-radius: 22px 22px 0 0;
  border-bottom: 0;
}

/* Con el teclado fuera, la hoja puede ocupar casi todo el hueco que queda: si se
   quedara en el 86% se veria una franja muerta encima del teclado. */
body.comments-keyboard-open #commentsModal .comments-panel {
  max-height: var(--comments-vh, 100%);
}

/* El area de la barra de inicio del movil solo hay que respetarla cuando NO hay
   teclado: con el teclado abierto, ese hueco no existe y deja un escalon. */
body.comments-keyboard-open .comments-compose {
  padding-bottom: 12px;
}

/* La lista no arrastra el scroll de la pagina al llegar al final. */
.comments-list {
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
}

/* La cabecera es el tirador: el navegador no debe interpretar el arrastre como
   scroll ni sacar el menu de seleccion. */
.comments-head {
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
}
/* Tirador de la hoja: pista visual de que arrastra/viene de abajo. */
#commentsModal .comments-head::before {
  content: "";
  position: absolute;
  top: 7px;
  left: 50%;
  transform: translateX(-50%);
  width: 40px;
  height: 4px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.28);
}
#commentsModal.modal-enter .comments-panel {
  animation: commentsSheetIn 0.32s cubic-bezier(0.2, 0.8, 0.2, 1) both;
}
#commentsModal.modal-leave .comments-panel {
  animation: commentsSheetOut 0.26s ease both;
}
@keyframes commentsSheetIn {
  from {
    transform: translateY(100%);
  }
  to {
    transform: translateY(0);
  }
}
@keyframes commentsSheetOut {
  from {
    transform: translateY(0);
  }
  to {
    transform: translateY(100%);
  }
}
@keyframes commentsSideIn {
  from {
    transform: translateX(100%);
  }
  to {
    transform: translateX(0);
  }
}
@keyframes commentsSideOut {
  from {
    transform: translateX(0);
  }
  to {
    transform: translateX(100%);
  }
}

@media (min-width: 1025px) {
  /* PC con espacio: panel lateral derecho, a pantalla completa. */
  #commentsModal {
    align-items: stretch;
    justify-content: flex-end;
  }
  #commentsModal .comments-panel {
    width: min(440px, 42vw);
    max-width: 440px;
    height: 100vh;
    max-height: 100vh;
    border-radius: 0;
    border-top: 0;
    border-right: 0;
    border-bottom: 0;
  }
  /* En lateral no hay tirador (no viene de abajo). */
  #commentsModal .comments-head::before {
    display: none;
  }
  #commentsModal.modal-enter .comments-panel {
    animation: commentsSideIn 0.34s cubic-bezier(0.2, 0.8, 0.2, 1) both;
  }
  #commentsModal.modal-leave .comments-panel {
    animation: commentsSideOut 0.26s ease both;
  }
}

@media (prefers-reduced-motion: reduce) {
  #commentsModal.modal-enter .comments-panel,
  #commentsModal.modal-leave .comments-panel {
    animation: none;
  }
}

/* --- Acciones sociales del reproductor de pista (solo panel abierto) --- */

.sets-player-social {
  display: none;
  width: min(100%, 560px);
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin: 0 auto;
}

#communityLiveRadioBar[data-mode="set"].is-expanded .sets-player-social {
  display: flex;
}

#communityLiveRadioBar .sets-player-social.hidden {
  display: none !important;
}

.sets-player-author {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px;
  border: 0;
  background: none;
  color: inherit;
  cursor: default;
  min-width: 0;
  text-align: left;
}

.sets-player-author.is-linkable {
  cursor: pointer;
}

.sets-player-author-avatar {
  width: 40px;
  height: 40px;
  border-radius: 999px;
  overflow: hidden;
  display: grid;
  place-items: center;
  background: rgba(255, 255, 255, 0.1);
  color: var(--text);
  flex: 0 0 auto;
}

.sets-player-author-avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.sets-player-author-copy {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.sets-player-author-kicker {
  font-size: 11px;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.sets-player-author-name {
  font-size: 14px;
  font-weight: 700;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sets-player-social-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 0 0 auto;
}

.sets-player-social-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 40px;
  padding: 0 14px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: rgba(255, 255, 255, 0.05);
  color: var(--text);
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: border-color 0.15s ease, color 0.15s ease;
}

.sets-player-social-btn:hover {
  border-color: var(--primary);
}

.sets-player-social-btn.is-active {
  color: #ff5d73;
  border-color: rgba(255, 93, 115, 0.5);
}

/* --- Minimapa de ubicacion de la fiesta --- */

.location-panel {
  width: min(560px, 96vw);
  max-height: min(84vh, 720px);
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.location-head {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding-right: 40px;
}

.location-head strong {
  font-size: 17px;
  color: var(--text);
}

.location-place {
  font-size: 13px;
  color: var(--text-muted);
}

.location-map {
  flex: 1;
  min-height: 300px;
  border-radius: 16px;
  overflow: hidden;
  border: 1px solid var(--line);
  background: var(--bg-2);
}

.location-map .leaflet-container {
  width: 100%;
  height: 100%;
  background: var(--bg-2);
}

/* --- Mapa de fiestas vistas (multiples puntos) ---
   Ya no es un modal que se abre desde la barra: es una diapositiva mas del feed
   (`.tt-slide-parties`) y va A SANGRE, sin titular ni marco: solo el mapa, igual
   que un cartel ocupa su pantalla entera. */
.tt-slide-parties {
  padding: 0;
  gap: 0;
}

.tt-slide-parties .tt-slide-content {
  gap: 0;
}

.tt-parties-map-wrap {
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
  border-radius: inherit;
  overflow: hidden;
  background: var(--bg-2);
  overscroll-behavior: contain;
  touch-action: pan-y;
}

.tt-parties-map {
  width: 100%;
  height: 100%;
  touch-action: pan-y;
}
.tt-parties-map .leaflet-container {
  width: 100%;
  height: 100%;
  background: var(--bg-2);
  touch-action: pan-y;
}

/* Bloqueado: dejamos que el feed siga desplazando. El mapa queda como decoracion
   hasta que el usuario toca el boton de desbloqueo, y el boton vive fuera de esa
   capa para no quedar bloqueado por el mismo gesto. */
.tt-parties-map-wrap.is-map-locked,
.tt-parties-map.is-map-locked,
.tt-parties-map .leaflet-container.is-map-locked,
.tt-parties-map.is-map-locked.leaflet-container {
  touch-action: pan-y !important;
  pointer-events: none !important;
}

.tt-parties-map-wrap.is-map-locked .tt-parties-map-toggle,
.tt-parties-map-wrap.is-map-unlocked .tt-parties-map-toggle {
  pointer-events: auto !important;
}

/* Suelto: el dedo es del mapa. */
.tt-parties-map-wrap.is-map-unlocked,
.tt-parties-map.is-map-unlocked,
.tt-parties-map .leaflet-container.is-map-unlocked,
.tt-parties-map.is-map-unlocked.leaflet-container {
  touch-action: none !important;
  pointer-events: auto !important;
}

/* El mapa nace bloqueado para que el dedo siga pasando de pantalla; este boton
   lo libera cuando quieres arrastrarlo o hacer zoom. */
.tt-parties-map-toggle {
  position: absolute;
  right: 10px;
  /* Por encima del reproductor de radio, que flota sobre el feed. */
  bottom: calc(10px + var(--tt-player-h, 0px) + var(--tt-player-gap, 0px));
  z-index: 1000;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 8px 12px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: rgba(6, 6, 7, 0.82);
  backdrop-filter: blur(6px);
  color: var(--text);
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
}
.tt-parties-map-toggle.is-active {
  border-color: var(--primary);
  color: var(--primary);
}

/* Marcador de fiesta: el CARTEL en miniatura clavado en el mapa (con su punta),
   que es lo que el usuario reconoce del feed. Si la fiesta se guardo sin imagen,
   dentro cae el icono de siempre. */
.parties-map-pin {
  display: flex;
  flex-direction: column;
  align-items: center;
  filter: drop-shadow(0 4px 8px rgba(0, 0, 0, 0.55));
}

.parties-map-pin-poster {
  position: relative;
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  overflow: hidden;
  border-radius: 12px;
  border: 2px solid var(--primary, #d2f365);
  background: #0c0c0e;
  color: #ff2d55;
  font-size: 20px;
}

/* La foto tapa al icono de reserva; si falla y se quita, el icono reaparece. */
.parties-map-pin-poster img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* La punta que apunta al sitio exacto (el ancla del icono cae justo aqui). */
.parties-map-pin-tip {
  width: 0;
  height: 0;
  margin-top: -1px;
  border-left: 6px solid transparent;
  border-right: 6px solid transparent;
  border-top: 9px solid var(--primary, #d2f365);
}

.location-empty {
  height: 100%;
  min-height: 300px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  text-align: center;
  color: var(--text-muted);
  padding: 20px;
}

.location-empty i {
  font-size: 34px;
  opacity: 0.5;
}

.location-empty p {
  margin: 0;
  font-weight: 700;
  color: var(--text);
}

.location-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
}

.location-distance {
  font-size: 13px;
  font-weight: 700;
  color: var(--primary);
}

.location-maps-link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px 16px;
  border-radius: 999px;
  border: 1px solid var(--line);
  color: var(--text);
  font-weight: 600;
  font-size: 14px;
  text-decoration: none;
}

.location-maps-link:hover {
  border-color: var(--primary);
}

.tt-thread-more {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}

.tt-thread-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-2);
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: 14px;
  background: var(--bg-2);
  color: var(--text);
  cursor: pointer;
  text-align: left;
  transition: border-color 0.15s ease;
}

.tt-thread-row:hover {
  border-color: var(--primary);
}

/* Cada atajo lleva ya la cara y el nombre de quien abrio el hilo: una lista de
   titulos pelados no dice si al otro lado hay alguien. */
.tt-thread-row-avatar {
  width: 30px;
  height: 30px;
  flex: 0 0 30px;
  border-radius: 999px;
  object-fit: cover;
}

.tt-thread-row-copy {
  min-width: 0;
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.tt-thread-row-author {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 12px;
  color: var(--text-muted);
}

.tt-thread-row-title {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: 600;
  font-size: 14px;
}

.tt-thread-row-meta {
  flex: 0 0 auto;
  font-size: 12px;
  color: var(--text-muted);
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.tt-deck {
  position: relative;
  flex: 1;
  min-height: 0;
}

.tt-deck .feed-deck-list {
  height: 100%;
}

/* Gente */

/* Musica */

.tt-music-list {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}

.tt-music-row {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-2);
  border: 1px solid var(--line);
  border-radius: 14px;
  background: var(--surface);
}

.tt-music-cover {
  position: relative;
  flex: 0 0 auto;
  width: 52px;
  height: 52px;
  border: 0;
  border-radius: 10px;
  overflow: hidden;
  background: var(--surface-2);
  cursor: pointer;
  padding: 0;
}

.tt-music-cover img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.tt-music-play {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  background: rgba(10, 13, 3, 0.42);
  color: #fff;
  font-size: 15px;
}

.tt-music-copy {
  min-width: 0;
}

.tt-music-copy h4 {
  margin: 0;
  font-size: 13px;
  font-weight: 700;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tt-music-copy p {
  margin: 0;
  font-size: 11px;
  color: var(--text-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Fotos de anoche */

.tt-recap-grid {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: var(--sp-3);
  align-content: start;
}

.tt-recap-card {
  height: auto;
  position: relative;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 16px;
  overflow: hidden;
  aspect-ratio: 3 / 4;
  background: var(--surface-2);
  cursor: pointer;
}

.tt-recap-card.is-mine {
  border-color: var(--primary);
}

.tt-recap-card img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.tt-recap-empty {
  display: grid;
  place-items: center;
  width: 100%;
  height: 100%;
  color: var(--text-soft);
  font-size: 24px;
}

.tt-recap-copy {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 22px 10px 10px;
  text-align: left;
  background: linear-gradient(to top, rgba(0, 0, 0, 0.82), transparent);
}

.tt-recap-title {
  font-size: 12px;
  font-weight: 700;
  color: #fff;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tt-recap-meta {
  font-size: 11px;
  color: var(--primary);
}

@media (max-width: 640px) {
  #feed.is-social {
    --tt-chrome-offset: 108px;
    border-radius: 0;
  }

  .tt-title {
    font-size: 21px;
  }

  .tt-actions {
    bottom: 108px;
  }
}

/* Pantalla de descarga de la app dentro del feed. */

.tt-slide-install {
  justify-content: center;
  align-items: center;
  text-align: center;
  background: transparent;
}

/* La diapositiva de descarga es un HERO que LLENA el slide: tarjeta con
   degradado + halo verde, logo grande, lista de ventajas y CTA. Antes era una
   columna estrecha centrada que dejaba medio panel vacio. */
.tt-slide-install .tt-slide-content {
  justify-content: stretch;
}





/* ===========================================================================
   SORTEO — la entrada troquelada
   ===========================================================================
   Esta pantalla no se lee: se fotografia. Subir la captura a stories es uno de
   los requisitos, asi que el objetivo no es "que se entienda", es "que apetezca
   enseñarla". Por eso es una ENTRADA -cartel arriba, perforacion, resguardo
   abajo- y no una tarjeta con una lista.

   La paleta sale del flyer de makina de finales de los 90: letras cromadas,
   laser, negro de imprenta barata. Se toma el verde acido de la casa y se le
   pone al lado un MAGENTA LASER que no esta en el resto de la app. Ese duotono
   es lo que evita que sea otro rectangulo negro con brillo verde.

   TODO se mide en `vh`. La captura tiene que salir entera de una pasada: si el
   contenido no cabe y hay que hacer scroll, la foto sale cortada y el requisito
   no se cumple. Por eso los tamaños se encogen con la pantalla en vez de tener
   un tamaño fijo con scroll detras.
   ======================================================================== */
.tt-slide-sorteo {
  --so-void: #07070a;
  --so-acid: #d2f365;
  --so-laser: #ff2f87;
  --so-line: rgba(255, 255, 255, 0.1);
  --so-dim: rgba(233, 255, 233, 0.58);
}

.sorteo-stage {
  flex: 1 1 auto;
  min-height: 0;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: clamp(6px, 1.4vh, 14px) 0;
}

/* La entrada. El fondo lleva los dos laseres en esquinas opuestas: verde arriba
   a la izquierda, magenta abajo a la derecha, muy abiertos y muy tenues. Es lo
   que hace que el negro no sea plano sin convertirlo en un degradado de
   plantilla. */
.sorteo-ticket {
  position: relative;
  width: 100%;
  max-width: 400px;
  max-height: 100%;
  display: flex;
  flex-direction: column;
  border-radius: 20px;
  border: 1px solid var(--so-line);
  background:
    radial-gradient(120% 90% at 0% 0%, rgba(210, 243, 101, 0.16), transparent 52%),
    radial-gradient(120% 90% at 100% 100%, rgba(255, 47, 135, 0.18), transparent 55%),
    var(--so-void);
  box-shadow: 0 30px 70px rgba(0, 0, 0, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.06);
  overflow: hidden;
}

/* --- Cartel --------------------------------------------------------------- */
.sorteo-flyer {
  flex: 0 0 auto;
  padding: clamp(11px, 2vh, 18px) 18px clamp(9px, 1.6vh, 15px);
  text-align: center;
}

.sorteo-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: clamp(9px, 1.3vh, 10.5px);
  font-weight: 800;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--so-acid);
}

/* El separador es un punto de luz, no un caracter: un "·" a este tamaño se lee
   como suciedad. */
.sorteo-logo {
  width: clamp(20px, 2.8vh, 26px);
  height: auto;
  margin-right: 2px;
  filter: drop-shadow(0 0 10px rgba(210, 243, 101, 0.45));
}

.sorteo-eyebrow i {
  width: 4px;
  height: 4px;
  border-radius: 999px;
  background: var(--so-laser);
  box-shadow: 0 0 8px var(--so-laser);
}

.sorteo-kicker {
  margin: clamp(6px, 1.1vh, 10px) 0 2px;
  font-size: clamp(11px, 1.5vh, 12.5px);
  font-weight: 600;
  color: var(--so-dim);
}

/* EL TITULO. Cromo: degradado claro-oscuro-claro sobre el texto, como las letras
   metalicas de los flyers de la epoca.

   Entra PALABRA A PALABRA, cada una con su turno (`--w`). Antes el cartel ya
   estaba puesto cuando llegabas a el y no habia nada que mirar: una pantalla
   quieta en un feed vertical se pasa de largo. El degradado va en cada palabra y
   no en el `h3` porque una palabra que se mueve tiene que llevarse su recorte de
   fondo con ella. */
.sorteo-prize {
  position: relative;
  margin: 0;
  font-size: clamp(30px, 7.4vh, 54px);
  line-height: 0.9;
  font-weight: 900;
  letter-spacing: -0.035em;
  text-transform: uppercase;
}

.sorteo-prize-word {
  display: inline-block;
  background: linear-gradient(178deg, #ffffff 8%, #cdd7e0 34%, #7d8b98 52%, #eef4f8 74%, #ffffff 96%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
  filter: drop-shadow(0 3px 0 rgba(0, 0, 0, 0.55)) drop-shadow(0 0 26px rgba(210, 243, 101, 0.22));
}

.tt-slide-sorteo.is-onscreen .sorteo-prize-word {
  animation:
    sorteoGolpe 0.62s cubic-bezier(0.18, 1.25, 0.32, 1) both calc(var(--w, 0) * 0.13s),
    sorteoPulso 3.2s ease-in-out calc(1.15s + var(--w, 0) * 0.13s) infinite;
}

/* El golpe: la palabra cae de arriba, grande y desenfocada, y se planta. */
@keyframes sorteoGolpe {
  0% {
    opacity: 0;
    transform: translate3d(0, 30px, 0) scale(1.3);
    filter: blur(11px) drop-shadow(0 3px 0 rgba(0, 0, 0, 0.55));
  }
  55% {
    opacity: 1;
  }
  100% {
    opacity: 1;
    transform: none;
    filter: drop-shadow(0 3px 0 rgba(0, 0, 0, 0.55)) drop-shadow(0 0 26px rgba(210, 243, 101, 0.22));
  }
}

/* Y luego respira. Sin esto el cartel se apaga en cuanto termina de entrar,
   justo mientras se lee la lista de abajo, que es cuando mas falta hace que siga
   estando vivo. */
@keyframes sorteoPulso {
  0%,
  100% {
    filter: drop-shadow(0 3px 0 rgba(0, 0, 0, 0.55)) drop-shadow(0 0 20px rgba(210, 243, 101, 0.2));
  }
  50% {
    filter: drop-shadow(0 3px 0 rgba(0, 0, 0, 0.55)) drop-shadow(0 0 42px rgba(210, 243, 101, 0.55));
  }
}

.sorteo-prize::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(100deg, transparent 38%, rgba(255, 255, 255, 0.85) 50%, transparent 62%);
  mix-blend-mode: overlay;
  opacity: 0;
  pointer-events: none;
}

/* La pasada de luz vuelve cada cinco segundos. Ocupa un quinto del ciclo: el
   resto del tiempo no hay nada, asi que se lee como un foco que barre el cartel
   y no como el brillo en bucle de un banner. */
.tt-slide-sorteo.is-onscreen .sorteo-prize::after {
  animation: sorteoBrillo 5s ease-out 0.75s infinite;
}

@keyframes sorteoBrillo {
  0% {
    opacity: 0;
    transform: translateX(-60%);
  }
  7% {
    opacity: 1;
  }
  22%,
  100% {
    opacity: 0;
    transform: translateX(60%);
  }
}

/* Sede y fecha: la voz de una entrada es monoespaciada y en mayusculas. */
.sorteo-data {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  margin: clamp(7px, 1.3vh, 12px) 0 0;
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  font-size: clamp(10.5px, 1.5vh, 12.5px);
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: #eafff0;
}

.sorteo-data b {
  width: 26px;
  height: 1px;
  background: linear-gradient(90deg, var(--so-acid), var(--so-laser));
}

/* --- La perforacion ------------------------------------------------------- */
/* Dos muescas recortadas en los laterales y una linea de puntos entre ellas. Es
   LA pieza que hace que esto se lea como una entrada y no como una tarjeta
   partida en dos. Las muescas van del color del FONDO DEL FEED, no del de la
   entrada: si fueran del suyo se verian como dos manchas. */
.sorteo-perf {
  position: relative;
  flex: 0 0 auto;
  height: 20px;
  background-image: repeating-linear-gradient(
    90deg,
    rgba(255, 255, 255, 0.28) 0 5px,
    transparent 5px 12px
  );
  background-size: calc(100% - 44px) 1px;
  background-position: center;
  background-repeat: no-repeat;
}

.sorteo-perf::before,
.sorteo-perf::after {
  content: "";
  position: absolute;
  top: 50%;
  width: 20px;
  height: 20px;
  border-radius: 999px;
  background: var(--bg, #0b0b0d);
  transform: translateY(-50%);
}

.sorteo-perf::before {
  left: -10px;
}

.sorteo-perf::after {
  right: -10px;
}

/* --- Resguardo ------------------------------------------------------------ */
.sorteo-stub {
  flex: 1 1 auto;
  min-height: 0;
  padding: 0 clamp(12px, 3vw, 16px) clamp(14px, 2.4vh, 20px);
  display: flex;
  flex-direction: column;
  gap: clamp(6px, 1vh, 9px);
}

.sorteo-block {
  border: 1px solid var(--so-line);
  border-radius: 13px;
  background: rgba(255, 255, 255, 0.03);
  padding: clamp(7px, 1.1vh, 10px) clamp(9px, 1.4vh, 12px);
}

.sorteo-block.is-bonus {
  border-color: rgba(255, 47, 135, 0.34);
  background: rgba(255, 47, 135, 0.07);
}

/* Bloque completo: el borde se enciende. Es la unica recompensa visual que hay
   por terminarlo, y es suficiente. */
.sorteo-block.is-full {
  border-color: rgba(210, 243, 101, 0.55);
  background: rgba(210, 243, 101, 0.08);
}

.sorteo-block-head {
  display: flex;
  align-items: center;
  gap: 9px;
  margin-bottom: clamp(4px, 0.7vh, 7px);
}

.sorteo-block-head h4 {
  margin: 0;
  font-size: clamp(9.5px, 1.3vh, 11px);
  font-weight: 800;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--so-dim);
}

/* El "+1" es el dato que manda en cada bloque: cuanto suma hacerlo. */
.sorteo-plus {
  flex: 0 0 auto;
  padding: 2px 9px;
  border-radius: 999px;
  background: var(--so-acid);
  color: #161c04;
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  font-size: clamp(10.5px, 1.4vh, 12px);
  font-weight: 800;
}

.sorteo-block.is-bonus .sorteo-plus {
  background: var(--so-laser);
  color: #1a0510;
}

.sorteo-reqs {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: clamp(3px, 0.55vh, 5px);
}

.sorteo-req {
  display: flex;
  align-items: center;
  gap: 8px;
}

/* La fila NO se pulsa: es solo el estado. Lo que marca un requisito es la
   accion de al lado (abrir Instagram, entrar al grupo, compartir la imagen) o el
   servidor. Una casilla que se marca a mano no dice nada de nadie. */
.sorteo-req-main {
  flex: 1;
  min-width: 0;
  min-height: 28px;
  display: flex;
  align-items: center;
  gap: 9px;
}

/* Anillo vacio o check: el ESTADO, no un numero de orden. Los requisitos no son
   una secuencia -da igual por cual empieces- asi que numerarlos seria mentir. */
.sorteo-req-mark {
  flex: 0 0 17px;
  width: 17px;
  height: 17px;
  display: grid;
  place-items: center;
  border-radius: 999px;
  border: 1.5px solid rgba(255, 255, 255, 0.24);
  color: #161c04;
  font-size: 8.5px;
  transition: background 0.14s ease, border-color 0.14s ease;
}

.sorteo-req.is-done .sorteo-req-mark {
  border-color: transparent;
  background: var(--so-acid);
}

.sorteo-req-text {
  flex: 1;
  min-width: 0;
  font-size: clamp(11.5px, 1.6vh, 13px);
  line-height: 1.3;
  color: var(--text);
}

.sorteo-req-text i {
  margin-right: 6px;
  color: var(--so-dim);
  font-size: 0.92em;
}

/* Un requisito HECHO no puede parecer DESHABILITADO. Antes se apagaba a gris y
   se leia como "esto no lo puedes tocar" en vez de "esto ya lo tienes". Se
   mantiene a plena luz y lo que cambia es la marca verde de la izquierda. */
.sorteo-req.is-done .sorteo-req-text {
  color: var(--text);
}

.sorteo-req.is-done .sorteo-req-text i {
  color: var(--so-acid);
}

.sorteo-go {
  flex: 0 0 auto;
  /* Hay una regla global `input, select, button { height: 44px }` para que los
     formularios se puedan pulsar con el dedo. Aqui hacia que "Editar" y "Otra
     vez" (botones) midieran 44 px y "Abrir" (enlaces) 26: la misma fila con dos
     alturas distintas, y 36 px de lista comidos en un movil. */
  height: auto;
  padding: 5px 11px;
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.06);
  color: var(--text);
  font-size: clamp(10.5px, 1.4vh, 12px);
  font-weight: 700;
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
}

.sorteo-go:hover,
.sorteo-go:focus-visible {
  border-color: var(--so-acid);
  color: var(--so-acid);
}

/* Cuando el paso ya esta hecho, su boton deja de reclamar atencion: sigue ahi
   para editar, pero en voz baja. */
/* "Editar" y "Otra vez" bajan el tono, pero tienen que LEERSE: al 42% de
   opacidad sobre el resguardo oscuro practicamente desaparecian. */
.sorteo-go.is-quiet {
  border-color: rgba(255, 255, 255, 0.14);
  background: rgba(255, 255, 255, 0.04);
  color: rgba(233, 255, 233, 0.82);
  text-decoration: none;
}

.sorteo-cta {
  width: 100%;
  min-height: clamp(40px, 5.2vh, 48px);
  display: inline-flex;
  /* Dos lineas: la accion y, debajo, cuando cierra. El cierre entraba antes por
     su cuenta en el cartel; aqui va pegado a lo que hay que pulsar. */
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1px;
  padding: 6px 12px;
  border: 0;
  border-radius: 13px;
  background: linear-gradient(96deg, var(--so-acid), #b9e94a);
  color: #161c04;
  font-size: clamp(13.5px, 1.9vh, 15.5px);
  font-weight: 900;
  cursor: pointer;
  box-shadow: 0 12px 26px rgba(210, 243, 101, 0.18);
}



/* Datos guardados pero sin bloque completo: ni boton ni celebracion. Solo dice
   que falta, porque lo que falta esta justo encima, en las filas. */
.sorteo-cta.is-pending {
  margin: 0;
  background: rgba(255, 255, 255, 0.04);
  border: 1px dashed rgba(255, 255, 255, 0.2);
  color: var(--so-dim);
  font-size: clamp(12px, 1.6vh, 13.5px);
  font-weight: 700;
  box-shadow: none;
  cursor: default;
}

/* Confirmado. Ocupa el sitio del boton para que la pantalla no se descoloque al
   pasar de "por hacer" a "hecho", pero deja de ser un boton: ya no hay nada que
   pulsar ahi. Editar los datos se hace desde su propia fila, arriba. */
.sorteo-cta.is-done {
  margin: 0;
  background: rgba(210, 243, 101, 0.12);
  border: 1px solid rgba(210, 243, 101, 0.45);
  color: var(--primary);
  font-size: clamp(12.5px, 1.7vh, 14px);
  font-weight: 800;
  box-shadow: none;
  cursor: default;
}

.sorteo-cta > span {
  display: inline-flex;
  align-items: center;
  gap: 10px;
}

/* La cuenta atras: presente, pero sin robarle el sitio a la frase principal. */
.sorteo-cta-cierra {
  font-size: clamp(9.5px, 1.25vh, 11px);
  font-weight: 700;
  letter-spacing: 0.2px;
  opacity: 0.74;
}

.sorteo-cta:hover,
.sorteo-cta:focus-visible {
  filter: brightness(1.06);
}

.sorteo-foot {
  margin: 0;
  text-align: center;
  font-size: clamp(10px, 1.3vh, 11.5px);
  line-height: 1.4;
  color: rgba(233, 255, 233, 0.42);
}

.sorteo-foot strong {
  color: var(--so-dim);
}

/* Con una participacion o mas, el marco se tiñe: la entrada ya es tuya. */
.sorteo-ticket.is-in {
  border-color: rgba(210, 243, 101, 0.4);
}

@media (prefers-reduced-motion: reduce) {
  .tt-slide-sorteo.is-onscreen .sorteo-prize::after,
  .tt-slide-sorteo.is-onscreen .sorteo-prize-word {
    animation: none;
  }

  /* Sin animacion de entrada las palabras se quedarian en el fotograma cero
     (invisibles): hay que devolverlas a su sitio a mano. */
  .sorteo-prize-word {
    opacity: 1;
    transform: none;
  }
}

/* --- Formulario de participacion ------------------------------------------ */
.raffle-panel {
  max-width: 440px;
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}

.raffle-intro {
  margin: 0;
  font-size: 13.5px;
  line-height: 1.5;
  color: var(--text-muted);
}

.raffle-field {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.raffle-field > span {
  font-size: 12.5px;
  font-weight: 700;
  color: var(--text-muted);
}

.raffle-field > span i {
  margin-right: 6px;
  color: var(--primary);
}

.raffle-field input {
  width: 100%;
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--bg-2);
  color: var(--text);
  font-size: 15px;
}

.raffle-field input:focus {
  outline: none;
  border-color: var(--primary);
}


/* Las condiciones. Van pegadas al boton a proposito: aceptar es confirmar, y
   leerlas tiene que costar menos que saltarselas. Tipografia pequeña pero con
   interlineado ancho -son cinco lineas, no un contrato-. */
.raffle-terms {
  border: 1px solid var(--line);
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.03);
  padding: 11px 13px;
}

.raffle-terms h4 {
  margin: 0 0 7px;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--primary);
}

.raffle-terms ul {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 5px;
}

.raffle-terms li {
  position: relative;
  padding-left: 15px;
  font-size: 12.5px;
  line-height: 1.45;
  color: var(--text-muted);
}

/* La viñeta es un guion corto y no un punto: a este tamaño un punto se pierde
   contra el fondo y las lineas dejan de leerse como una lista. */
.raffle-terms li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 9px;
  width: 7px;
  height: 1.5px;
  border-radius: 2px;
  background: var(--primary);
  opacity: 0.7;
}

.raffle-error {
  margin: 0;
  padding: 10px 12px;
  border-radius: 10px;
  border: 1px solid rgba(255, 120, 120, 0.4);
  background: rgba(255, 92, 92, 0.12);
  color: #ffdede;
  font-size: 13px;
}

.raffle-submit {
  width: 100%;
  min-height: 46px;
  justify-content: center;
}

.raffle-foot {
  margin: 0;
  font-size: 12px;
  line-height: 1.5;
  color: var(--text-soft);
}

.tt-install-inner {
  flex: 1 1 auto;
  min-height: 0;
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  /* `safe center` centra cuando cabe, pero si el alto se reduce (p.ej. con el
     reproductor abierto) NO recorta arriba: alinea al inicio y deja hacer scroll
     interno para llegar al boton, en vez de cortar el CTA. */
  justify-content: safe center;
  text-align: center;
  gap: var(--sp-2);
  padding: var(--sp-4);
  border-radius: var(--tt-card-radius, 22px);
  border: 1px solid rgba(210, 243, 101, 0.22);
  background:
    radial-gradient(120% 70% at 50% -8%, rgba(176, 209, 67, 0.24), transparent 60%),
    linear-gradient(180deg, rgba(14, 14, 15, 0.92), rgba(8, 8, 8, 0.96));
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.45);
  overflow-y: auto;
  scrollbar-width: none;
}
.tt-install-inner::-webkit-scrollbar {
  display: none;
}

/* Halo detras del logo para que el icono destaque como en una store. */
.tt-install-hero {
  position: relative;
  display: grid;
  place-items: center;
  margin-bottom: 0;
}

.tt-install-glow {
  position: absolute;
  width: 120px;
  height: 120px;
  border-radius: 999px;
  background: radial-gradient(circle, rgba(210, 243, 101, 0.4), transparent 66%);
  filter: blur(6px);
  pointer-events: none;
}

.tt-install-logo {
  position: relative;
  width: 58px;
  height: 58px;
  object-fit: contain;
  filter: drop-shadow(0 8px 16px rgba(0, 0, 0, 0.5));
}

.tt-slide-install h3 {
  margin: 0;
  font-size: 21px;
  font-weight: 800;
  color: var(--text);
  line-height: 1.15;
}

.tt-slide-install p {
  margin: 0;
  font-size: 13px;
  line-height: 1.4;
  color: var(--text-muted);
  max-width: 34ch;
}

/* Ventajas: rellenan el centro y dan sustancia. */
.tt-install-features {
  list-style: none;
  margin: var(--sp-1) 0 0;
  padding: 0;
  width: 100%;
  max-width: 360px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.tt-install-features li {
  display: flex;
  align-items: center;
  gap: 11px;
  text-align: left;
  padding: 8px 11px;
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.06);
}

.tt-install-feature-ic {
  flex: 0 0 auto;
  width: 32px;
  height: 32px;
  border-radius: 10px;
  display: grid;
  place-items: center;
  font-size: 14px;
  color: #d1ed73;
  background: rgba(210, 243, 101, 0.14);
  box-shadow: inset 0 0 0 1px rgba(210, 243, 101, 0.3);
}

.tt-install-features li div {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.tt-install-features li strong {
  font-size: 13px;
  color: var(--text);
}

.tt-install-features li div span {
  font-size: 11.5px;
  color: var(--text-muted);
  line-height: 1.3;
}

.tt-install-cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  margin-top: var(--sp-2);
  padding: 12px 30px;
  border-radius: 999px;
  background: linear-gradient(135deg, var(--primary), #afd339);
  color: #1b2302;
  font-size: 15px;
  font-weight: 800;
  text-decoration: none;
  box-shadow: 0 12px 26px rgba(175, 211, 57, 0.3);
  transition: filter 0.16s ease, transform 0.16s ease;
}

.tt-install-cta:hover,
.tt-install-cta:focus-visible {
  filter: brightness(1.08);
  transform: translateY(-1px);
}

.tt-install-note {
  font-size: 12px;
  color: var(--text-muted);
  letter-spacing: 0.02em;
}

.tt-install-note .fa-star {
  color: #ffcf5a;
  font-size: 11px;
}

/* ==========================================================================
   Inicio a pantalla completa
   El contenedor de la app ocupa todo el ancho y, en la pestana de inicio,
   exactamente el alto del viewport: barra arriba, feed en medio, nav abajo.
   Nada de scroll de pagina, para que el unico gesto sea el salto entre
   pantallas del feed.
   ========================================================================== */

.app {
  width: 100%;
  margin: 0;
}

/* --- Barra superior compacta: solo marca, lupa y campana --- */

.topbar-quick {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 6px;
}

/* Un boton colapsado sigue contando para el `gap` de la fila: con los otros dos
   a cero de ancho quedaban 12px de aire muerto a la derecha del campo. Mientras
   se busca solo queda un boton visible -la X-, asi que no hay nada que separar
   y el hueco sobra entero. */
.topbar.is-searching .topbar-quick {
  gap: 0;
}

.topbar-icon-btn {
  position: relative;
  display: inline-grid;
  place-items: center;
  width: 40px;
  height: 40px;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: rgba(12, 12, 13, 0.6);
  color: var(--text);
  font-size: 16px;
  cursor: pointer;
  transition: border-color 0.16s ease, background 0.16s ease, width 0.28s ease,
    opacity 0.22s ease;
}

.topbar-icon-btn:hover,
.topbar-icon-btn:focus-visible {
  border-color: var(--line-strong);
  background: rgba(17, 17, 19, 0.82);
}

.topbar-icon-btn .topbar-notif-badge {
  top: -2px;
  right: -2px;
}


/* --- Pestana de inicio: viewport bloqueado --- */

body.tt-feed-active[data-main-tab="posts"] {
  overflow: hidden;
}

body.tt-feed-active[data-main-tab="posts"] .app {
  height: 100dvh;
  min-height: 0;
  padding: 0;
  overflow: hidden;
}

body.tt-feed-active[data-main-tab="posts"] .topbar {
  flex: 0 0 auto;
  position: relative;
}

body.tt-feed-active[data-main-tab="posts"] .topbar-main {
  min-height: 44px;
}

body.tt-feed-active[data-main-tab="posts"] .main-panels-layout,
body.tt-feed-active[data-main-tab="posts"] .main-panels-content,
body.tt-feed-active[data-main-tab="posts"] [data-main-panel="posts"] {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

body.tt-feed-active[data-main-tab="posts"] [data-main-panel="posts"] > main {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  margin: 0;
  padding: 0;
}

/* La publicacion es lo primero que se ve: el feed ocupa todo el hueco que
   queda entre la barra y la navegacion inferior. */
body.tt-feed-active[data-main-tab="posts"] #feed.is-social {
  flex: 1;
  height: auto;
  min-height: 0;
  border-radius: 0;
}

/* --- Historias: capa flotante sobre la publicacion --- */

/* Las historias ocupan la columna central de la barra. Al avanzar se pliegan
   en vertical, asi que la barra encoge a solo marca e iconos en vez de dejar
   un hueco vacio. */
#feedGuidedRail {
  min-width: 0;
  margin: 0;
  overflow: hidden;
  transition: max-height 0.28s ease, opacity 0.22s ease;
  max-height: 132px;
}

#feedGuidedRail.is-tucked {
  max-height: 0;
  opacity: 0;
  pointer-events: none;
}

/* La navegacion inferior es fija en movil: el feed le reserva su alto para que
   la ultima pantalla no quede por debajo. */
@media (max-width: 760px) {
  body.tt-feed-active[data-main-tab="posts"] .app {
    padding: 0 0 calc(48px + env(safe-area-inset-bottom, 0px));
  }
}

/* El pie y la barra de cookies no pueden robar alto al feed: fuera del flujo
   mientras el inicio esta a pantalla completa. */
body.tt-feed-active[data-main-tab="posts"] .site-footer {
  display: none;
}

body.tt-feed-active[data-main-tab="posts"] #adsConsentBar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: calc(48px + env(safe-area-inset-bottom, 0px));
  z-index: 41;
  margin: 0;
  width: auto;
  max-width: none;
  /* La regla base lo centra con left:50% + translateX(-50%); aqui lo anclamos
     a todo el ancho, asi que hay que anular tambien el desplazamiento. */
  transform: none;
  border-radius: 0;
}

/* Marca compacta: en el inicio la barra es solo un carril de iconos. */
body.tt-feed-active[data-main-tab="posts"] .brand-logo {
  height: 34px;
  width: auto;
}

body.tt-feed-active[data-main-tab="posts"] .topbar {
  padding: var(--sp-1) var(--sp-2);
}

/* ==========================================================================
   Barra superior con las historias dentro
   Sin fondo propio: la barra flota sobre la publicacion y solo los avatares y
   los iconos tienen presencia. Igual que la lupa y la campana, que pierden su
   pastilla y se quedan en icono limpio.
   ========================================================================== */

body.tt-feed-active[data-main-tab="posts"] .topbar::before {
  display: none;
}

body.tt-feed-active[data-main-tab="posts"] .topbar {
  background: transparent;
}

/* Iconos sin pastilla: solo el glifo, con sombra para que se lea sobre
   cualquier cartel. */
body.tt-feed-active[data-main-tab="posts"] .topbar-icon-btn {
  border: 0;
  background: none;
  color: #fff;
  font-size: 19px;
  text-shadow: 0 2px 8px rgba(0, 0, 0, 0.55);
}

body.tt-feed-active[data-main-tab="posts"] .topbar-icon-btn:hover,
body.tt-feed-active[data-main-tab="posts"] .topbar-icon-btn:focus-visible {
  border: 0;
  background: none;
  color: var(--primary);
}

/* Marca | historias | iconos, en la misma fila. */
/* Flex, no grid: la barra tiene cuatro piezas (historias, buscador, iconos y
   el menu de cuenta) y con una plantilla de tres columnas las historias se
   quedaban con ancho cero. */
body.tt-feed-active[data-main-tab="posts"] .topbar-main {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 0;
}

body.tt-feed-active[data-main-tab="posts"] #feedGuidedRail,
body.tt-feed-active[data-main-tab="posts"] #searchCluster {
  flex: 1 1 auto;
  min-width: 0;
}

body.tt-feed-active[data-main-tab="posts"] .topbar.is-searching #feedGuidedRail {
  flex: 0 0 auto;
}

body.tt-feed-active[data-main-tab="posts"] .topbar-quick,
body.tt-feed-active[data-main-tab="posts"] .topbar-actions {
  flex: 0 0 auto;
}

body.tt-feed-active[data-main-tab="posts"] .topbar {
  padding: var(--sp-1) var(--sp-2) 0;
}

/* La barra se superpone a la publicacion en vez de empujarla: la primera
   pantalla se ve entera. */
body.tt-feed-active[data-main-tab="posts"] .topbar {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  z-index: 14;
  background: linear-gradient(to bottom, rgba(6, 6, 7, 0.78) 34%, rgba(6, 6, 7, 0) 100%);
}

body.tt-feed-active[data-main-tab="posts"] .app {
  position: relative;
}

/* --- Historias mas pequenas --- */

body.tt-feed-active[data-main-tab="posts"] .feed-live-strip-shell {
  padding: 0;
  border-radius: 0;
}

body.tt-feed-active[data-main-tab="posts"] .feed-live-strip {
  gap: 2px;
  /* Un poco mas abajo: pegadas al borde superior quedaban muy justas, sobre
     todo con la muesca o la barra de estado del movil. */
  padding: 18px 2px 8px;
}

body.tt-feed-active[data-main-tab="posts"] .feed-live-story {
  min-width: 0;
  padding: 0 3px;
  /* Gap uniforme entre aro y nombre en TODAS las historias: las sugerencias
     traian `gap:6px` propio y su texto quedaba mas abajo que el resto. Con esto
     todas las etiquetas quedan a la misma distancia. */
  gap: 0;
}

body.tt-feed-active[data-main-tab="posts"] .feed-live-story-ring {
  width: 54px;
  height: 54px;
  padding: 2px;
}



body.tt-feed-active[data-main-tab="posts"] .feed-live-story-name {
  font-size: 10px;
  max-width: 62px;
}

body.tt-feed-active[data-main-tab="posts"] .feed-live-story-follow-badge,
body.tt-feed-active[data-main-tab="posts"] .feed-live-story-badge {
  width: 18px;
  height: 18px;
  font-size: 9px;
}

/* --- Centro de notificaciones ---------------------------------------------- */

.topbar-notifications-count {
  display: inline-grid;
  place-items: center;
  min-width: 22px;
  height: 22px;
  padding: 0 6px;
  margin-left: 6px;
  border-radius: 999px;
  background: var(--primary);
  color: #1b2302;
  font-size: 12px;
  font-weight: 700;
  vertical-align: middle;
}

.topbar-notifications-filters {
  display: flex;
  gap: 6px;
  padding: 0 0 var(--sp-3);
}

.topbar-notifications-filter {
  padding: 6px 14px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: transparent;
  color: var(--text-muted);
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  transition: border-color 0.16s ease, color 0.16s ease, background 0.16s ease;
}

.topbar-notifications-filter:hover {
  border-color: var(--line-strong);
  color: var(--text);
}

.topbar-notifications-filter.is-active {
  background: var(--primary);
  border-color: var(--primary);
  color: #1b2302;
}

.topbar-notifications-group + .topbar-notifications-group {
  margin-top: var(--sp-4);
}

.topbar-notifications-group-label {
  margin: 0 0 6px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-soft);
}

/* El avatar lleva el tipo pegado en una esquina: se distingue un like de una
   invitacion sin leer el texto. */
.topbar-notification-media-wrap {
  position: relative;
  flex: 0 0 auto;
  display: inline-block;
  line-height: 0;
}

.topbar-notification-glyph {
  position: absolute;
  right: -3px;
  bottom: -3px;
  display: grid;
  place-items: center;
  width: 20px;
  height: 20px;
  border-radius: 999px;
  border: 2px solid var(--surface);
  background: var(--text-soft);
  color: #fff;
  font-size: 9px;
  line-height: 1;
}

.topbar-notification-glyph.is-like {
  background: #ff5f7a;
}

.topbar-notification-glyph.is-follow {
  background: var(--accent);
}

.topbar-notification-glyph.is-going,
.topbar-notification-glyph.is-recap {
  background: var(--primary);
  color: #1b2302;
}

.topbar-notification-glyph.is-comment {
  background: #5aa2ff;
}

.topbar-notification-glyph.is-invite {
  background: #ffb24d;
  color: #2a1602;
}

.topbar-notification-glyph.is-live {
  background: #e23a5a;
}

.topbar-notification-glyph.is-event {
  background: #a78bfa;
}

/* Lo no leido se marca con una barra lateral en vez de solo un fondo: se ve
   igual de bien en la lista larga. */
.topbar-notification-item.is-unread {
  position: relative;
}

.topbar-notification-item.is-unread::before {
  content: "";
  position: absolute;
  left: 0;
  top: 8px;
  bottom: 8px;
  width: 3px;
  border-radius: 999px;
  background: var(--primary);
}

/* ==========================================================================
   Pantallas de panel: gente, musica y swipe
   ========================================================================== */

/* --- Gente: lista de filas, no rejilla de cuadrados --- */

/* Dimensiones fijas y recorte: sin esto las fotos verticales deformaban la
   fila entera. */
/* --- Musica: reproductor --- */

.tt-slide-music {
  align-items: stretch;
}

.tt-player {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: var(--sp-4);
  border: 1px solid var(--line);
  border-radius: 22px;
  background: linear-gradient(165deg, rgba(130, 108, 246, 0.14), rgba(15, 15, 17, 0.9));
  text-align: center;
}

/* Plato de vinilo: el disco gira mientras suena y el brazo baja sobre el.
   La caratula del artista hace de etiqueta central. */
.tt-vinyl {
  position: relative;
  width: 190px;
  height: 190px;
  margin-bottom: var(--sp-3);
}

.tt-vinyl-disc {
  position: absolute;
  inset: 0;
  border-radius: 999px;
  display: grid;
  place-items: center;
  background:
    repeating-radial-gradient(circle at 50% 50%, #14161a 0 2px, #0b0d10 2px 4px);
  box-shadow: 0 14px 34px rgba(0, 0, 0, 0.5), inset 0 0 0 1px rgba(255, 255, 255, 0.06);
  animation: tt-vinyl-spin 4s linear infinite;
  animation-play-state: paused;
}

.tt-player.is-playing .tt-vinyl-disc {
  animation-play-state: running;
}

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

.tt-vinyl-label {
  width: 40%;
  height: 40%;
  border-radius: 999px;
  overflow: hidden;
  display: grid;
  place-items: center;
  background: var(--primary);
  color: #1b2302;
  font-size: 26px;
  box-shadow: 0 0 0 4px rgba(10, 13, 3, 0.85);
}

.tt-vinyl-label img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Punto central del disco. */
.tt-vinyl-label::after {
  content: "";
  position: absolute;
  width: 8px;
  height: 8px;
  border-radius: 999px;
  background: #1b2302;
}

.tt-vinyl-arm {
  position: absolute;
  top: 2px;
  right: 6px;
  width: 8px;
  height: 92px;
  border-radius: 999px;
  background: linear-gradient(180deg, #e1e5d6, #a4aa91);
  transform-origin: top center;
  transform: rotate(28deg);
  transition: transform 0.5s ease;
  box-shadow: 0 4px 10px rgba(0, 0, 0, 0.4);
}

.tt-player.is-playing .tt-vinyl-arm {
  transform: rotate(6deg);
}

.tt-vinyl-arm-head {
  position: absolute;
  left: -4px;
  bottom: -8px;
  width: 16px;
  height: 20px;
  border-radius: 4px;
  background: #edeeec;
}

.tt-player-title {
  margin: 0;
  font-size: 16px;
  font-weight: 700;
  color: var(--text);
  line-height: 1.25;
}

.tt-player-user {
  display: inline-flex;
  align-items: center;
  gap: 7px;
}

.tt-player-user-avatar {
  width: 22px;
  height: 22px;
  border-radius: 999px;
  object-fit: cover;
  display: block;
}

.tt-player-user-avatar-fallback {
  display: grid;
  place-items: center;
  background: var(--surface-2);
  color: var(--primary);
  font-size: 11px;
  font-weight: 700;
}

.tt-player-user-name {
  font-size: 12px;
  color: var(--primary);
  font-weight: 600;
}

.tt-player-chips {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  justify-content: center;
}

.tt-player-chip {
  padding: 3px 10px;
  border-radius: 999px;
  border: 1px solid var(--line);
  font-size: 10px;
  color: var(--text-muted);
}

.tt-player-progress {
  position: relative;
  width: 100%;
  height: 6px;
  margin-top: var(--sp-3);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.12);
  cursor: pointer;
  overflow: hidden;
}

.tt-player-progress-fill {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 0%;
  border-radius: 999px;
  background: linear-gradient(90deg, var(--primary), var(--accent));
  transition: width 0.25s linear;
}

.tt-player-times {
  display: flex;
  justify-content: space-between;
  width: 100%;
  font-size: 11px;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}

.tt-player-controls {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  margin-top: var(--sp-3);
}

.tt-player-skip {
  width: 40px;
  height: 40px;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--text-muted);
  font-size: 16px;
  cursor: pointer;
}

.tt-player-skip:hover {
  color: var(--text);
}

.tt-player-play {
  display: grid;
  place-items: center;
  width: 58px;
  height: 58px;
  border: 0;
  border-radius: 999px;
  background: var(--primary);
  color: #1b2302;
  font-size: 20px;
  cursor: pointer;
  box-shadow: 0 8px 20px rgba(210, 243, 101, 0.28);
  transition: transform 0.14s ease;
}

.tt-player-play:active {
  transform: scale(0.94);
}

.tt-queue-label {
  margin: 0 0 6px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-soft);
}

.tt-queue-row {
  /* Hereda `.music-row` (grid 52px/1fr/auto), pero solo tiene UN hijo (el boton),
     que quedaba aplastado en la 1a columna y ocultaba el titulo. La volvemos
     bloque para que el boton ocupe toda la fila con su propio layout. */
  display: block;
  border: 0;
  background: none;
  padding: 0;
}

.tt-queue-open {
  height: auto;
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  width: 100%;
  padding: 8px 10px;
  border: 1px solid var(--line);
  border-radius: 14px;
  background: var(--surface);
  cursor: pointer;
  text-align: left;
}

.tt-queue-art {
  flex: 0 0 auto;
  width: 40px;
  height: 40px;
  border-radius: 10px;
  overflow: hidden;
  display: grid;
  place-items: center;
  background: var(--surface-2);
  color: var(--text-soft);
}

.tt-queue-art img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.tt-queue-copy {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
}

.tt-queue-title {
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tt-queue-meta {
  font-size: 11px;
  color: var(--text-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tt-queue-time {
  flex: 0 0 auto;
  font-size: 11px;
  color: var(--text-soft);
  font-variant-numeric: tabular-nums;
}

/* --- Estetica de la lista de canciones: filas mas vivas, con play al pasar --- */
.tt-queue-label {
  margin: 0 2px 2px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--primary);
}

.tt-queue-open {
  transition: background 0.15s ease, border-color 0.15s ease, transform 0.12s ease;
}
.tt-queue-open:hover,
.tt-queue-open:focus-visible {
  background: rgba(130, 108, 246, 0.14);
  border-color: rgba(130, 108, 246, 0.4);
  transform: translateY(-1px);
}
.tt-queue-open:active {
  transform: scale(0.99);
}

/* Icono de play que aparece sobre la caratula al pasar el raton/tocar. */
.tt-queue-art {
  position: relative;
}
.tt-queue-art::after {
  content: "\f04b"; /* fa-play */
  font-family: "Font Awesome 6 Free";
  font-weight: 900;
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-size: 13px;
  color: #fff;
  background: rgba(5, 5, 6, 0.55);
  opacity: 0;
  transition: opacity 0.15s ease;
}
.tt-queue-open:hover .tt-queue-art::after,
.tt-queue-open:focus-visible .tt-queue-art::after {
  opacity: 1;
}

/* --- Swipe: botonera bajo el mazo --- */

.tt-deck {
  display: flex;
  flex-direction: column;
}

.tt-deck .feed-deck-list {
  flex: 1;
  min-height: 0;
}

.tt-deck-actions {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-4);
  padding-top: var(--sp-3);
}

.tt-deck-btn {
  display: grid;
  place-items: center;
  width: 54px;
  height: 54px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: rgba(12, 12, 13, 0.72);
  color: var(--text-muted);
  font-size: 20px;
  cursor: pointer;
  transition: transform 0.14s ease, border-color 0.14s ease, color 0.14s ease;
}

.tt-deck-btn:active {
  transform: scale(0.9);
}

.tt-deck-btn-open {
  width: 44px;
  height: 44px;
  font-size: 15px;
}

.tt-deck-btn-nope:hover {
  border-color: #ff5f7a;
  color: #ff5f7a;
}

.tt-deck-btn-like {
  border-color: var(--primary);
  color: var(--primary);
}

.tt-deck-btn-like:hover {
  background: var(--primary);
  color: #1b2302;
}



/* --- Sugerencias de perfiles: tarjeta con accion a todo el ancho ----------- */

/* Accion a todo el ancho, separada por una linea: el objetivo de la tarjeta es
   seguir, asi que el area de pulsado es toda la base. */

/* --- Sugerencias de perfiles: carrusel horizontal de tarjetas -------------- */

/* El carrusel se centra en el hueco de la pantalla: una sola fila arriba
   dejaria la mitad inferior vacia. */
/* Centrado solo si sobra sitio. Con `justify-content: center` a secas, en
   pantallas bajas la rejilla se desbordaba HACIA ARRIBA y se comia el titulo. */
.tt-slide-people-inner {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  justify-content: safe center;
  overflow-y: auto;
}

/* Rejilla 2x2: dos arriba, dos abajo, sin arrastre lateral. */
.tt-suggest-list {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--sp-3);
  padding: var(--sp-2) 0 var(--sp-3);
}

.tt-suggest-list::-webkit-scrollbar {
  display: none;
}

.tt-suggest-card {
  position: relative;
  width: auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: var(--sp-4) var(--sp-3) var(--sp-3);
  border: 1px solid var(--line);
  border-radius: 18px;
  background: var(--surface);
}

.tt-suggest-dismiss {
  height: 26px;
  position: absolute;
  top: 6px;
  right: 6px;
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--text-soft);
  font-size: 13px;
  cursor: pointer;
}

.tt-suggest-dismiss:hover {
  color: var(--text);
  background: rgba(255, 255, 255, 0.08);
}

.tt-suggest-top {
  height: auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  width: 100%;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  text-align: center;
}

.tt-suggest-avatar-wrap {
  overflow: hidden;
  width: 76px;
  height: 76px;
  margin-bottom: var(--sp-2);
  border-radius: 999px;
  padding: 2px;
  background: linear-gradient(135deg, var(--primary), var(--accent));
  display: grid;
  place-items: center;
}

.tt-suggest-avatar {
  width: 100%;
  height: 100%;
  border-radius: 999px;
  object-fit: cover;
  display: block;
  background: var(--surface-2);
}

.tt-suggest-avatar-fallback {
  display: grid;
  place-items: center;
  background: var(--surface-2);
  color: var(--primary);
  font-size: 26px;
  font-weight: 700;
}

.tt-suggest-name {
  max-width: 100%;
  font-size: 13px;
  font-weight: 700;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tt-suggest-handle {
  max-width: 100%;
  font-size: 11px;
  color: var(--text-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tt-suggest-proof {
  max-width: 100%;
  font-size: 10px;
  color: var(--text-soft);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tt-suggest-follow {
  height: auto;
  width: 100%;
  margin-top: var(--sp-3);
  padding: 9px 12px;
  border: 0;
  border-radius: 10px;
  background: var(--accent);
  color: #fff;
  font-size: 13px;
  font-weight: 700;
  cursor: pointer;
  transition: filter 0.16s ease;
}

.tt-suggest-follow:hover {
  filter: brightness(1.12);
}

.tt-suggest-follow.is-following {
  background: transparent;
  border: 1px solid var(--line);
  color: var(--text-soft);
  cursor: default;
}

/* Insignia de procedencia de cada pista del feed de musica. */
.tt-source-badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 10px;
  border-radius: 999px;
  border: 1px solid var(--line);
  font-size: 10px;
  font-weight: 600;
  color: var(--text-muted);
}

.tt-source-badge.is-soundcloud {
  border-color: rgba(255, 136, 0, 0.5);
  color: #ff8800;
}

.tt-source-badge.is-youtube {
  border-color: rgba(255, 60, 60, 0.5);
  color: #ff4d4d;
}

.tt-source-badge.is-spotify {
  border-color: rgba(179, 229, 16, 0.5);
  color: #b3e510;
}

.tt-source-badge.is-upload {
  border-color: var(--line-strong);
  color: var(--primary);
}

.tt-slide-music .tt-music-list {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  margin-top: var(--sp-3);
}

/* ==========================================================================
   Interacciones del inicio: buscador, pulsacion mantenida y mazo
   ========================================================================== */

/* --- Buscador que empuja las historias -------------------------------------
   Historias y buscador comparten la columna central. Al abrir, las historias
   se encogen a cero y el campo ocupa su sitio: una transicion, no un salto. */

body.tt-feed-active[data-main-tab="posts"] .topbar-main {
  overflow: hidden;
  justify-content: end;
}

body.tt-feed-active[data-main-tab="posts"] #feedGuidedRail,
body.tt-feed-active[data-main-tab="posts"] #searchCluster {
  transition: max-width 0.28s ease, opacity 0.22s ease, transform 0.28s ease;
}

body.tt-feed-active[data-main-tab="posts"] #searchCluster {
  max-width: 0;
  opacity: 0;
  transform: translateX(14px);
  pointer-events: none;
  overflow: hidden;
  padding: 0;
}

body.tt-feed-active[data-main-tab="posts"] .topbar.is-searching #searchCluster {
  max-width: 100%;
  opacity: 1;
  transform: none;
  pointer-events: auto;
}

body.tt-feed-active[data-main-tab="posts"] .topbar.is-searching #feedGuidedRail {
  max-width: 0;
  opacity: 0;
  transform: translateX(-14px);
  pointer-events: none;
}

/* Al abrir el buscador, la barra ENTERA se convierte en el buscador: el
   calendario y las notificaciones se apartan y el campo se queda con su sitio.
   Antes seguian ahi, y el resultado era un campo estrecho encajado entre tres
   iconos mientras debajo se abria un desplegable a todo lo ancho: la fila decia
   una cosa y el panel otra.

   Se colapsan (ancho y borde a cero), no se ocultan con `display:none`: asi
   entran y salen con la misma transicion que ya usan las historias y el campo,
   y la fila no pega un salto. La lupa se queda porque ES el boton de cerrar. */
body.tt-feed-active[data-main-tab="posts"] .topbar.is-searching #agendaBtn,
body.tt-feed-active[data-main-tab="posts"] .topbar.is-searching #filterBtn {
  width: 0;
  border-width: 0;
  margin: 0;
  opacity: 0;
  overflow: hidden;
  pointer-events: none;
}

body.tt-feed-active[data-main-tab="posts"] #searchCluster .search-group {
  width: 100%;
}

body.tt-feed-active[data-main-tab="posts"] #searchCluster input {
  width: 100%;
}

/* Los iconos necesitan leerse sobre cualquier cartel, ahora que la barra no
   tiene fondo propio. */
body.tt-feed-active[data-main-tab="posts"] .topbar-icon-btn {
  background: rgba(6, 6, 7, 0.42);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
}

body.tt-feed-active[data-main-tab="posts"] .topbar-icon-btn:hover,
body.tt-feed-active[data-main-tab="posts"] .topbar-icon-btn:focus-visible {
  background: rgba(6, 6, 7, 0.62);
}

/* --- Pulsacion mantenida: la publicacion, limpia --- */

/* Solo se atenuan: quitarles los eventos dejaba botones muertos si el modo
   mirar se activaba sin querer. Se oculta TODA la interfaz (barra superior con
   historias, botonera, textos, degradados, navegacion inferior y el reproductor)
   para dejar SOLO la foto/video, como en TikTok. */
body.tt-peeking .tt-actions,
body.tt-peeking .tt-overlay,
body.tt-peeking .topbar,
body.tt-peeking #feedGuidedRail,
body.tt-peeking .main-tabs-shell,
body.tt-peeking #communityLiveRadioBar,
body.tt-peeking #feedLoadMoreSentinel,
body.tt-peeking .tt-today-badge,
body.tt-peeking .tt-media-scrim {
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.18s ease;
}

body.tt-peeking .tt-actions,
body.tt-peeking .tt-overlay {
  transform: translateY(6px);
}

.tt-actions,
.tt-overlay,
.topbar,
.main-tabs-shell,
.tt-media-scrim {
  transition: opacity 0.2s ease, transform 0.2s ease;
}

/* --- Mazo de swipe: que ocupe el hueco ------------------------------------
   La regla base usa `clamp(225px, 60vw, 200px)`, cuyo maximo es menor que el
   minimo, asi que la carta nunca crecia. Aqui se dimensiona con el alto del
   panel, que es lo que sobra en una pantalla completa. */

/* La carta del mazo tiene FORMA DE CARTA VERTICAL (tipo tinder), no un
   rectangulo horizontal: se dimensiona por ALTO (llena el mazo) y el ancho sale
   de una proporcion de carta (retrato). Esquinas redondeadas, sombra y borde. */
/* El mazo es el contenedor de referencia: la carta se mide contra SU alto y SU
   ancho, no contra el viewport. */
.tt-deck .feed-deck-list {
  container-type: size;
  container-name: deck;
}

/* El alto sale del menor de dos limites -el que da el alto del mazo y el que
   deja su ancho- y ademas se acota entre un minimo y un maximo. Antes solo se
   miraba el alto (94%) con un `max-width: 100%` de parche: en pantallas altas
   la carta crecia hasta desbordar y el cartel salia cortado. */
.tt-deck .feed-deck-list .feed-simple-row.feed-deck-card,
.tt-deck .feed-deck-list .feed-simple-row.feed-deck-card.is-tall-poster,
.tt-deck .feed-deck-list .feed-simple-row.feed-deck-card.is-extra-tall-poster {
  /* El tamano sale de lo que ocupa el ABANICO, no solo la carta de delante: las
     de detras van giradas hasta 13 grados y desplazadas hasta 66px en x / 28px
     en y (ver updateStackPositions). Una carta girada ocupa mas que su propio
     rectangulo, asi que el alto util se reduce a ~0.9 y hay que descontar los
     desplazamientos; si no, las esquinas del abanico se salen del mazo y se ven
     cortadas en seco. Se coge el menor de los dos limites (alto y ancho). */
  height: clamp(240px, min(calc(88cqh - 56px), calc(110cqw - 110px)), 600px);
  width: auto;
  max-width: 84cqw;
  aspect-ratio: 0.7;
  border-radius: 22px;
  overflow: hidden;
  box-shadow: 0 16px 40px rgba(0, 0, 0, 0.55);
  border: 1px solid rgba(255, 255, 255, 0.08);
}

/* Sin soporte de container queries se vuelve al comportamiento de antes, pero
   con techo y suelo para que la carta no se desmadre en pantallas grandes. */
@supports not (height: 1cqh) {
  .tt-deck .feed-deck-list .feed-simple-row.feed-deck-card,
  .tt-deck .feed-deck-list .feed-simple-row.feed-deck-card.is-tall-poster,
  .tt-deck .feed-deck-list .feed-simple-row.feed-deck-card.is-extra-tall-poster {
    height: clamp(240px, 78%, 600px);
    max-width: 84%;
  }
}

/* La imagen de dentro respeta las esquinas de la carta. */
.tt-deck .feed-deck-list .feed-simple-row.feed-deck-card .feed-deck-card-media {
  border-radius: inherit;
  overflow: hidden;
}

/* El cartel llena la carta entera: nada de bandas vacias. Lo que no puede pasar
   es que la CARTA se salga del mazo, y de eso se encarga el tamano de arriba. */
.tt-deck .feed-deck-list .feed-simple-row.feed-deck-card .feed-deck-card-poster {
  object-fit: cover;
  object-position: center center;
}

/* El panel deja un margen a los lados: la carta no toca los bordes (forma de
   tarjeta). A la derecha reserva ademas el carril de acciones (gutter) para que
   la carta no se meta debajo de la botonera. */
.tt-slide-panel[data-tt-slide="swipe"] {
  padding-left: var(--sp-4);
  /* El padding derecho (carril de acciones) lo pone la regla unica de
     `.tt-slide-panel`; aqui solo el margen izquierdo de la carta. */
}

.tt-deck .feed-deck-list {
  overflow: clip;
  /* Sitio para la sombra y para las cartas de detras, que van giradas hasta 9
     grados y desplazadas: con 44px la esquina superior se cortaba en seco. */
  overflow-clip-margin: 80px;
}

.tt-deck-actions {
  padding-top: var(--sp-4);
}

/* El alto del feed no puede depender de una cadena de cinco contenedores flex:
   basta con que un ancestro no propague el limite para que todo se estire. La
   barra superior flota (position:absolute), asi que el feed puede ocupar el
   viewport menos la navegacion inferior, y punto. */

/* --- Sorteo: piezas nuevas -------------------------------------------------
   Que se sortea, cuando cierra, cuantas participaciones llevas y por donde se
   sigue. Cada una tapa un agujero concreto: sin la primera nadie sabe que hay
   en juego; sin la segunda no hay urgencia; sin la tercera no sabes si vas 1 o
   2; y sin la cuarta se capta un correo y se pierde un usuario. */
.sorteo-que {
  margin: 2px 0 0;
  font-size: clamp(11px, 1.5vh, 13px);
  font-weight: 700;
  color: var(--so-acid);
  letter-spacing: 0.2px;
}

/* El marcador contesta "¿voy 1 o 2?" sin que haya que contar casillas. */
.sorteo-marcador {
  display: flex;
  align-items: center;
  gap: 7px;
  margin: 0 0 8px;
  padding: 6px 11px;
  border-radius: 10px;
  border: 1px solid rgba(255, 255, 255, 0.12);
  background: rgba(255, 255, 255, 0.04);
  font-size: clamp(11px, 1.5vh, 13px);
  color: rgba(255, 255, 255, 0.72);
}

.sorteo-marcador i {
  color: rgba(255, 255, 255, 0.5);
}

.sorteo-marcador.is-in {
  border-color: rgba(180, 255, 120, 0.4);
  background: rgba(150, 255, 90, 0.09);
  color: var(--text);
}

.sorteo-marcador.is-in i,
.sorteo-marcador b {
  color: var(--so-acid);
}

/* La entrada obligatoria se separa de los extras: no valen lo mismo. */
.sorteo-req.is-entrada {
  border-left: 2px solid var(--so-acid);
  padding-left: 8px;
}

.sorteo-suma {
  margin: 10px 0 4px;
  font-size: clamp(10px, 1.3vh, 11.5px);
  letter-spacing: 0.6px;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.45);
}

.sorteo-suma b {
  color: var(--so-acid);
}

/* --- Invitar a un amigo ---------------------------------------------------
   La unica accion de la lista que trae gente NUEVA. Seguir una cuenta o entrar
   en un grupo mueve a quien ya esta dentro; esta hace crecer la web. Por eso no
   es una fila mas de la lista: tiene su propio bloque, su color y el boton mas
   fuerte de la pantalla. */
.sorteo-invita {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 8px;
  padding: 8px 10px;
  border-radius: 12px;
  border: 1px solid rgba(255, 47, 135, 0.38);
  background: linear-gradient(96deg, rgba(255, 47, 135, 0.14), rgba(255, 47, 135, 0.04));
}

.sorteo-invita-txt {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.sorteo-invita-txt b {
  font-size: clamp(11.5px, 1.6vh, 13px);
  font-weight: 800;
  color: var(--text);
}

.sorteo-invita-txt b i {
  margin-right: 6px;
  color: var(--so-laser);
}

.sorteo-invita-txt small {
  font-size: clamp(10px, 1.3vh, 11.5px);
  color: rgba(255, 255, 255, 0.62);
}

/* Con amigos dentro el recuento deja de ser una promesa y pasa a ser un
   marcador: se enciende. */
.sorteo-invita.is-in {
  border-color: rgba(210, 243, 101, 0.45);
  background: linear-gradient(96deg, rgba(210, 243, 101, 0.14), rgba(210, 243, 101, 0.04));
}

.sorteo-invita.is-in .sorteo-invita-txt b i {
  color: var(--so-acid);
}

.sorteo-invita.is-in .sorteo-invita-txt small {
  color: var(--so-acid);
  font-weight: 700;
}

/* El unico boton de la lista que se pinta lleno: es el que hay que pulsar. */
.sorteo-go.is-strong {
  border-color: transparent;
  background: var(--so-laser);
  color: #240010;
  font-weight: 800;
}

.sorteo-invita.is-in .sorteo-go.is-strong {
  background: var(--so-acid);
  color: #161c04;
}

.sorteo-go.is-strong:hover,
.sorteo-go.is-strong:focus-visible {
  color: #240010;
  filter: brightness(1.08);
}

.sorteo-invita.is-in .sorteo-go.is-strong:hover,
.sorteo-invita.is-in .sorteo-go.is-strong:focus-visible {
  color: #161c04;
}

/* La coletilla del marcador ("te faltan 2 faciles") es un empujon, no el dato:
   va en voz baja detras del numero. */
.sorteo-marcador span {
  color: rgba(255, 255, 255, 0.55);
  font-size: 0.92em;
}

.sorteo-salida {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 8px;
}

.sorteo-salida-btn {
  flex: 1 1 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 8px 10px;
  border-radius: 10px;
  border: 1px solid rgba(255, 255, 255, 0.16);
  background: rgba(255, 255, 255, 0.05);
  color: var(--text);
  font-size: clamp(10.5px, 1.4vh, 12px);
  font-weight: 700;
  cursor: pointer;
  white-space: nowrap;
}

.sorteo-salida-btn:hover,
.sorteo-salida-btn:focus-visible {
  border-color: var(--so-acid);
  color: var(--so-acid);
}

.sorteo-legal {
  margin: 6px 0 0;
  font-size: clamp(9px, 1.2vh, 10.5px);
  line-height: 1.4;
  color: rgba(255, 255, 255, 0.42);
  text-align: center;
}

.sorteo-legal a {
  color: rgba(255, 255, 255, 0.68);
  text-decoration: underline;
}

/* --- Que TODO se vea en un movil ------------------------------------------
   En un iPhone SE (667 px de alto) el resguardo pedia 451 px y tenia 258: la
   mitad de la lista, el boton, el pie y las bases se quedaban cortados por el
   `overflow: hidden` de la entrada. Y no era un detalle: lo que desaparecia era
   justo la confirmacion de que estas dentro.

   La solucion tiene dos partes. Esta es la primera: la lista de requisitos es lo
   unico que puede desplazarse, y el cierre (boton + bases) se queda SIEMPRE
   pegado abajo. No se le pone `overscroll-behavior: contain` a proposito: al
   llegar al final de la lista el gesto tiene que seguir moviendo el feed, que es
   lo que la gente espera al deslizar. */
.sorteo-lista {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  display: flex;
  flex-direction: column;
  gap: clamp(6px, 1vh, 9px);
}

.sorteo-lista::-webkit-scrollbar {
  display: none;
}

.sorteo-fin {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  gap: clamp(5px, 0.8vh, 8px);
  padding-top: clamp(6px, 1vh, 9px);
}

/* La segunda parte: apretar lo que no es dato. El objetivo es que la lista NO
   tenga que desplazarse; el desplazamiento es la red de seguridad, no el plan.

   El corte va por ALTURA y no por anchura, y a 900 px, no a 740: el problema no
   era "moviles pequeños". Todo el cartel esta medido en `vh`, asi que en un
   movil alto crece MAS de lo que crece el hueco disponible, y un iPhone 13 (844
   px) se quedaba con 64 px fuera mientras un SE (667 px) entraba. */
@media (max-height: 1000px) {
  .sorteo-stage {
    padding: 4px 0;
  }

  .sorteo-flyer {
    padding: 8px 16px 6px;
  }

  /* El titulo sigue siendo lo mas grande de la pantalla, con diferencia; solo
     deja de comerse la lista. */
  .sorteo-prize {
    font-size: min(6.4vh, 54px);
  }

  .sorteo-data {
    margin-top: 5px;
  }

  .sorteo-perf {
    height: 16px;
  }

  .sorteo-stub {
    padding-bottom: 10px;
    gap: 5px;
  }

  .sorteo-lista {
    gap: 5px;
  }

  .sorteo-fin {
    gap: 4px;
    padding-top: 5px;
  }

  .sorteo-marcador {
    margin-bottom: 0;
    padding: 4px 10px;
  }

  .sorteo-reqs {
    gap: 3px;
  }

  .sorteo-req-main {
    min-height: 24px;
  }

  .sorteo-suma {
    margin: 4px 0 1px;
  }

  .sorteo-invita {
    margin-top: 4px;
    padding: 6px 9px;
  }

  .sorteo-cta {
    min-height: 40px;
  }
}

/* Y en los de verdad bajos (SE, Androids de 640), donde apretar no basta, se
   quitan las dos cosas que se REPITEN. */
@media (max-height: 700px) {
  .sorteo-stage {
    padding: 2px 0;
  }

  .sorteo-prize {
    font-size: min(6vh, 54px);
  }

  .sorteo-reqs {
    gap: 2px;
  }

  .sorteo-flyer {
    padding: 6px 16px 5px;
  }

  .sorteo-logo {
    width: 17px;
  }

  /* "GAVÀ — 10/09" dice lo mismo que la linea del premio ("1 entrada · Brisa
     (Gavà) · 10 sept"). Con sitio de sobra es tipografia de entrada; sin sitio,
     son 34 px gastados en decir dos veces lo mismo. */
  .sorteo-data {
    display: none;
  }

  .sorteo-perf {
    height: 14px;
  }

  .sorteo-stub {
    padding-bottom: 9px;
    gap: 4px;
  }

  .sorteo-lista {
    gap: 4px;
  }

  .sorteo-marcador {
    padding: 2px 10px;
  }

  .sorteo-invita {
    padding: 5px 9px;
  }

  .sorteo-req-main {
    min-height: 20px;
  }

  .sorteo-req-mark {
    flex-basis: 15px;
    width: 15px;
    height: 15px;
  }

  .sorteo-invita-txt b {
    font-size: 12px;
  }

  .sorteo-invita-txt small {
    font-size: 10.5px;
  }

  .sorteo-cta {
    min-height: 36px;
  }

  /* El pie explicativo se va: "te creamos la imagen" ya lo dice el boton "Crear
     imagen", y la fecha del ganador esta en las bases, a un toque. Lo que NO se
     puede quitar es la linea legal. */
  .sorteo-foot {
    display: none;
  }
}

/* Androids de 640 px. Aqui ya no queda grasa que quitar sin empezar a borrar
   informacion, asi que se recorta el interlineado y poco mas; lo que sobre lo
   absorbe el desplazamiento de la lista, que para eso esta. */
@media (max-height: 660px) {
  .sorteo-lista {
    gap: 3px;
  }

  .sorteo-invita {
    padding: 4px 8px;
  }

  .sorteo-invita-txt small {
    line-height: 1.25;
  }

  .sorteo-req-text {
    font-size: 12px;
  }
}

.sorteo-cartel {
  width: clamp(48px, 9vh, 70px);
  height: clamp(48px, 9vh, 70px);
  object-fit: cover;
  border-radius: 10px;
  border: 1px solid rgba(255, 255, 255, 0.22);
  margin-bottom: 4px;
}

/* ============================================================
   "Sigue donde lo dejaste": la oferta de volver al punto del feed
   donde estabas en la visita anterior. Va FIJA sobre el feed (no
   dentro: el feed es un contenedor con snap y cualquier hijo
   viajaria con el scroll) y por debajo de los modales.
   ============================================================ */
.tt-sitio-chip {
  position: fixed;
  left: 50%;
  bottom: calc(var(--tt-nav-h, 0px) + 18px + env(safe-area-inset-bottom, 0px));
  z-index: 1500;
  display: flex;
  align-items: stretch;
  gap: 2px;
  max-width: min(92vw, 420px);
  padding: 4px;
  border-radius: 999px;
  border: 1px solid var(--line-strong, rgba(210, 243, 101, 0.45));
  background: rgba(13, 13, 14, 0.92);
  backdrop-filter: blur(14px);
  box-shadow: 0 18px 40px rgba(0, 0, 0, 0.44);
  /* Entra desde abajo: sin `is-in` no se ve, para que no parpadee al montarse. */
  opacity: 0;
  transform: translate(-50%, 14px);
  transition: opacity 0.22s ease, transform 0.22s cubic-bezier(0.22, 1, 0.36, 1);
}

.tt-sitio-chip.is-in {
  opacity: 1;
  transform: translate(-50%, 0);
}

/* Mientras se va no se puede pulsar: un clic a medio desvanecer no se sabe si
   era para el chip o para lo que hay debajo, y acababa haciendo lo que no era. */
.tt-sitio-chip:not(.is-in) {
  pointer-events: none;
}

.tt-sitio-ir {
  flex: 1 1 auto;
  min-width: 0;
  appearance: none;
  border: 0;
  border-radius: 999px;
  min-height: 44px;
  padding: 0 16px;
  display: inline-flex;
  align-items: center;
  gap: 11px;
  cursor: pointer;
  background: transparent;
  color: var(--text, #f4f4f3);
  text-align: left;
  transition: background 0.16s ease;
}

.tt-sitio-ir:hover {
  background: rgba(210, 243, 101, 0.1);
}

.tt-sitio-ir > i {
  flex: 0 0 auto;
  color: var(--primary, #d2f365);
  font-size: 15px;
  animation: ttSitioNudge 1.9s ease-in-out infinite;
}

.tt-sitio-copy {
  display: flex;
  flex-direction: column;
  min-width: 0;
  line-height: 1.2;
}

.tt-sitio-copy b {
  font-size: 13.5px;
  font-weight: 700;
}

/* El titulo del evento es la pista de QUE hay ahi abajo; si no cabe, se corta:
   una sola linea, porque el chip no puede crecer y tapar el cartel. */
.tt-sitio-copy small {
  font-size: 11.5px;
  color: var(--text-muted, #c7d2a5);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tt-sitio-no {
  flex: 0 0 auto;
  appearance: none;
  border: 0;
  border-radius: 999px;
  width: 40px;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  background: transparent;
  color: rgba(244, 244, 243, 0.55);
  font-size: 14px;
  transition: color 0.16s ease, background 0.16s ease;
}

.tt-sitio-no:hover {
  color: var(--text, #f4f4f3);
  background: rgba(255, 255, 255, 0.06);
}

@keyframes ttSitioNudge {
  0%,
  100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(3px);
  }
}

@media (max-width: 480px) {
  .tt-sitio-copy small {
    max-width: 46vw;
  }
}

@media (prefers-reduced-motion: reduce) {
  .tt-sitio-chip {
    transition: opacity 0.2s ease;
    transform: translate(-50%, 0);
  }

  .tt-sitio-ir > i {
    animation: none;
  }
}

/* La racha reutiliza el chip de abajo, pero NO es una oferta: no se pulsa, solo
   informa. Llama de color distinto (fuego) para que no se confunda con el boton
   de volver a tu sitio. */
.tt-racha-chip .tt-sitio-ir {
  cursor: default;
}

.tt-racha-chip .tt-sitio-ir:hover {
  background: transparent;
}

.tt-racha-chip .tt-sitio-ir > i {
  color: #ffab5e;
  animation: none;
}

/* ============================================================
   Cierre de la agenda. El feed ya no se rellena con eventos
   pasados, asi que termina: esta pantalla es ese final, y da la
   siguiente accion en vez de dejar al usuario en un callejon.
   ============================================================ */
.tt-final-inner {
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 14px;
  padding: 32px 24px;
  text-align: center;
}

.tt-final-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 62px;
  height: 62px;
  border-radius: 50%;
  font-size: 26px;
  color: var(--primary, #d2f365);
  border: 1px solid var(--line, rgba(210, 243, 101, 0.24));
  background: rgba(210, 243, 101, 0.07);
}

.tt-final-inner h3 {
  margin: 0;
  font-size: clamp(22px, 5vw, 30px);
  font-weight: 800;
  line-height: 1.1;
}

.tt-final-inner p {
  margin: 0;
  max-width: 34ch;
  color: var(--text-muted, #c7d2a5);
  font-size: 14px;
  line-height: 1.45;
}

.tt-final-actions {
  display: flex;
  flex-direction: column;
  gap: 10px;
  width: min(100%, 300px);
  margin-top: 6px;
}

.tt-final-btn {
  appearance: none;
  border: 1px solid var(--line, rgba(210, 243, 101, 0.24));
  border-radius: 14px;
  min-height: 48px;
  padding: 0 18px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  cursor: pointer;
  background: transparent;
  color: var(--text, #f4f4f3);
  font-family: inherit;
  font-size: 14px;
  font-weight: 600;
  transition: background 0.16s ease, border-color 0.16s ease, transform 0.16s ease;
}

.tt-final-btn:hover {
  background: rgba(210, 243, 101, 0.08);
  border-color: var(--line-strong, rgba(210, 243, 101, 0.45));
}

.tt-final-btn:active {
  transform: translateY(1px);
}

/* La accion principal va llena: en una pantalla con dos botones, uno tiene que
   ganar visualmente o los dos se ignoran. */
.tt-final-btn.is-primary {
  background: var(--primary, #d2f365);
  border-color: var(--primary, #d2f365);
  color: #14200a;
  font-weight: 700;
}

.tt-final-btn.is-primary:hover {
  background: #dcf87d;
  border-color: #dcf87d;
}
