html {
  overscroll-behavior: none;
}

:root {
  /* Las areas seguras, una vez y con nombre.
     La app se declara instalable (`apple-mobile-web-app-capable`) y el
     `viewport-fit=cover` del layout es lo que hace que estos valores dejen de
     ser 0 en un movil con notch. Con el fallback a 0px, en un navegador sin
     recortes no suman nada.

     En `:root` y no en `body`: las custom properties solo heredan hacia abajo,
     asi que otro token declarado en `:root` que las use no las veria. */
  --safe-top: env(safe-area-inset-top, 0px);
  --safe-bottom: env(safe-area-inset-bottom, 0px);
  --safe-left: env(safe-area-inset-left, 0px);
  --safe-right: env(safe-area-inset-right, 0px);
}

body {
  /* Lo que ocupa el composer, para colocar encima el boton de volver al ultimo
     mensaje (messages.css). Esto es solo el arranque: composer_controller lo
     sobreescribe con la altura medida, porque el composer crece con la barra
     de formato, los adjuntos pendientes y la densidad. */
  --footer-height: calc(5.5rem + var(--safe-bottom));

  /* La cabecera de la sala. Ya no es fija: es la primera fila del grid, asi
     que nada tiene que reservarle hueco. El token queda para quien quiera
     alinear algo con ella. */
  --navbar-height: calc(3.25rem + var(--safe-top));

  /* Las tres columnas: rail, barra y conversacion. Fuera de una sala y en
     movil las dos primeras miden cero y el grid es una sola columna. */
  --rail-width: 0px;
  --sidebar-width: 0px;

  /* El ancho de la columna de conversacion. Lo comparten la lista de mensajes
     y el composer: ver el bloque del final de este fichero. 100ch son ~863px,
     el ancho de linea que usan Slack y Zulip por la misma razon. */
  --conversation-width: 100ch;

  display: grid;
  grid-template-areas:
    "rail sidebar nav"
    "rail sidebar main";
  grid-template-columns: var(--rail-width) var(--sidebar-width) minmax(0, 1fr);
  grid-template-rows: min-content minmax(0, 1fr);
  /* `--vvh` solo existe con el teclado abierto en iOS: es la altura que deja
     visible (visual_viewport_controller). El resto del tiempo, 100dvh. El
     minimo va tambien: el `min-height: 100dvh` de _reset.css le ganaria. */
  block-size: var(--vvh, 100dvh);
  max-block-size: var(--vvh, 100dvh);
  min-block-size: var(--vvh, 100dvh);

  &.sidebar {
    @media (min-width: 100ch) {
      --sidebar-width: min(26vw, 17rem);
    }
  }

  &.rail {
    @media (min-width: 100ch) {
      --rail-width: 4.25rem;
    }
  }

  /* La barra y el rail al otro lado.
     Es una preferencia de pantalla y no de cuenta, asi que la recuerda el
     navegador: ver preferences_controller. Solo cambia el reparto del grid;
     ni la barra ni la conversacion saben en que columna han caido. */
  &.sidebar-end {
    grid-template-areas:
      "nav sidebar rail"
      "main sidebar rail";
    grid-template-columns: minmax(0, 1fr) var(--sidebar-width) var(--rail-width);
  }
}

#main-content {
  align-content: start;
  background-color: var(--color-bg);
  display: flex;
  flex-direction: column;
  grid-area: main;
  min-block-size: 0;
  overflow: auto;
  /* El recorte lateral se aparta aqui y no en cada hijo: dentro viven la lista
     y el composer, y apartandolos juntos siguen alineados el uno con el otro. */
  padding-inline: var(--safe-left) var(--safe-right);
  position: relative;

  .sidebar & {
    justify-content: end;
  }
}

#sidebar {
  grid-area: sidebar;
  position: relative;
  transition: transform 300ms ease;

  .sidebar & {
    background-color: var(--sb-bg);
    block-size: 100dvh;
    color: var(--sb-text);
    max-block-size: 100dvh;
    z-index: 3;

    @media (max-width: 100ch) {
      inline-size: min(100vw, 22rem);
      inset: 0 auto 0 0;
      position: fixed;
      transform: translate(-100%);
    }
  }

  &.open {
    @media (max-width: 100ch) {
      transform: translate(0);
    }
  }
}

/* En movil la barra no ocupa columna: entra deslizandose sobre la
   conversacion, y si vive a la derecha entra desde la derecha.
   Va aqui fuera y con selectores explicitos a proposito: anidado dentro de
   `.sidebar &` se aplanaba a un selector que pedia dos ancestros distintos, y
   `sidebar` y `sidebar-end` son dos clases del mismo <body>. */
@media (max-width: 100ch) {
  body.sidebar-end #sidebar {
    inset: 0 0 0 auto;
    transform: translate(100%);
  }

  body.sidebar-end #sidebar.open {
    transform: translate(0);
  }
}

/* El fondo del cajon. Sin el, la franja de conversacion que queda a la vista
   con la barra abierta seguia viva: se tocaba un mensaje en vez de cerrar.
   Tapa todo menos la barra (z-index 3, detras en el DOM) y el rail (4), y
   solo existe en estrecho: en ancho la barra es una columna y no hay cajon. */
.sidebar__scrim {
  display: none;
}

@media (max-width: 100ch) {
  .sidebar__scrim {
    background-color: oklch(0% 0 0 / 0.4);
    display: block;
    inset: 0;
    opacity: 0;
    pointer-events: none;
    position: fixed;
    transition: opacity 300ms ease;
    z-index: 3;
  }

  body.sidebar:has(#sidebar.open) .sidebar__scrim {
    opacity: 1;
    pointer-events: auto;
  }
}

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

/* La columna de conversacion.
 *
 * El tope va al contenido, no al contenedor: `.messages` es la superficie de
 * scroll y la unica caja real del drop-target de ficheros, asi que tiene que
 * llegar a sangre. Lo que se acota son las filas, centradas. Es lo que hacen
 * Slack y Zulip: el scroller ocupa todo y solo la lista se centra. */
.messages > * {
  inline-size: 100%;
  margin-inline: auto;
  max-inline-size: var(--conversation-width);
}

/* El composer, por padding y no por ancho, y por lo mismo: la caja tiene que
   llegar a sangre para que sus laterales acepten ficheros. El padding centra
   el contenido sin encogerla. El termino de centrado suma el padding que
   lleva la propia fila de mensaje, para que la caja de escribir empiece donde
   empieza el texto y no donde empieza la fila. */
#footer > .composer {
  padding-inline: max(
    calc(var(--inline-space) + 1vw),
    calc((100% - var(--conversation-width)) / 2 + var(--inline-space) + 1vw)
  );
}
