html {
  overscroll-behavior: none;
}

body {
  --footer-height: calc((var(--block-space)) + 3.6em + var(--block-space));
  --navbar-height: 54px;
  --sidebar-width: 0vw;
  --thread-panel-width: clamp(420px, 28vw, 520px);

  display: grid;
  grid-template-areas:
    "sidebar notice"
    "sidebar connection"
    "sidebar nav"
    "sidebar main";
  grid-template-columns: var(--sidebar-width) 1fr;
  grid-template-rows: min-content min-content min-content 1fr;
  max-block-size: 100dvh;

  /* The header trims 2px below tablet-portrait so it stays proportional
     as the shell narrows. */
  @media (max-width: 833.9px) {
    --navbar-height: 52px;
  }

  /* The Pencil room header is deliberately taller than the shared shell.
     Keep that geometry local to standard web rooms and forums. */
  &.room-header--pencil {
    --navbar-height: 62px;
  }

  /* Sidebar states: docked >=1280 (272px wide desktop, 240px narrow),
     a 60px icon rail 834-1279 that expands over the content on demand,
     and an off-canvas drawer below 834. */
  &.sidebar {
    @media (min-width: 834px) {
      --sidebar-width: 60px;
    }

    @media (min-width: 1280px) {
      --sidebar-width: 272px;
    }
  }
}

#nav {
  grid-area: nav;

  .sidebar & {
    @media (min-width: 1024px) {
      border-inline-start: 1px solid var(--color-border-darker);
    }
  }
}

.connection-banner {
  grid-area: connection;
}

.top-banner {
  grid-area: notice;
}

#main-content {
  align-content: start;
  background-color: var(--color-bg);
  display: flex;
  flex-direction: column;
  grid-area: main;
  overflow: auto;
  position: relative;

  .sidebar & {
    justify-content: end;

    @media (min-width: 1024px) {
      border-inline-start: 1px solid var(--color-border-darker);
    }
  }
}

/* The skip-link target: focusing the main region must not ring the whole
   content column. */
#main-content:focus {
  outline: none;
}

#main-content > #app {
  overflow: auto;
}

#sidebar {
  grid-area: sidebar;
  position: relative;
  transition: transform 300ms cubic-bezier(0.25, 1, 0.5, 1);

  .sidebar & {
    background-color: var(--color-bg-side);
    block-size: 100dvh;
    contain: layout style;
    max-block-size: 100dvh;
    z-index: 3;

    /* Drawer: off-canvas over a scrim */
    @media (max-width: 833.9px) {
      inline-size: min(300px, 85vw);
      inset: 0 auto 0 0;
      position: fixed;
      padding-block: env(safe-area-inset-top) env(safe-area-inset-bottom);
      transform: translate(-100%);
    }

    /* Rail: keep the closed element genuinely 60px wide so its size-container
       query renders the compact, keyboard-safe rail. Opening swaps once to the
       expanded layout, then lets the inner surface settle on the compositor;
       the 60px grid track stays put so the panel overlays the conversation. */
    @media (min-width: 834px) and (max-width: 1279.9px) {
      inline-size: 60px;
      inset: 0 auto 0 0;
      position: fixed;

      &.open {
        box-shadow: var(--shadow-overlay);
        inline-size: 264px;

        .sidebar__container {
          animation: sidebar-rail-open 240ms cubic-bezier(0.32, 0.72, 0, 1);
        }
      }

      @media (prefers-reduced-motion: reduce) {
        &,
        &.open .sidebar__container {
          animation: none;
          transition: none;
        }
      }
    }
  }

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

@keyframes sidebar-rail-open {
  from {
    opacity: 0.88;
    transform: translateX(-8px);
  }
}

@media (prefers-reduced-motion: reduce) {
  #sidebar {
    transition: none;
  }
}

/* The drawer covers the conversation, so dim it with a scrim (clicks land on
   body and close via the controller) and lock the page scroll. Drawer widths
   only: the rail above 834px is docked, and expanding it overlays a 264px
   column that separates itself with a shadow — scrimming there would dim the
   room header and lock a transcript the reader can still see beside it. */
@media (max-width: 833.9px) {
  body.sidebar:has(#sidebar.open) {
    overflow: hidden;

    &::after {
      background-color: var(--color-scrim);
      content: "";
      inset: 0;
      position: fixed;
      z-index: 2;
    }
  }
}

/* Contextual panels dock only after their own width fits beside the sidebar and
   a readable transcript. Room info earns a 288px column at 1160px; threads
   scale from 420px to 520px and dock at 1360px. Until then, thread_panel.css
   keeps them as overlays so the transcript retains its full measure. */
@media (min-width: 1160px) {
  body:has(#thread-panel:not([hidden]) [data-panel-kind="roster"]) {
    --thread-width: 288px;

    grid-template-areas:
      "sidebar notice notice"
      "sidebar connection connection"
      "sidebar nav thread"
      "sidebar main thread";
    grid-template-columns: var(--sidebar-width) 1fr var(--thread-width);
  }
}

@media (min-width: 1360px) {
  body:not(:has(#list-rail)):has(#thread-panel:not([hidden]) [data-panel-kind="thread"]) {
    --thread-width: var(--thread-panel-width);

    grid-template-areas:
      "sidebar notice notice"
      "sidebar connection connection"
      "sidebar nav thread"
      "sidebar main thread";
    grid-template-columns: var(--sidebar-width) 1fr var(--thread-width);
  }
}

/* A forum post is a reading column, not a thread. Keep its existing wider
   clamp and inline treatment. */
@media (min-width: 1024px) {
  body:has(#thread-panel:not([hidden]) [data-panel-kind="forum"]) {
    --thread-width: clamp(360px, 42vw, 680px);

    grid-template-areas:
      "sidebar notice notice"
      "sidebar connection connection"
      "sidebar nav thread"
      "sidebar main thread";
    grid-template-columns: var(--sidebar-width) 1fr var(--thread-width);
  }
}

#thread-panel {
  grid-area: thread;
}

/* DM split view: the conversation rail docks between the sidebar and the
   open conversation. Below the split width, direct rooms hide the rail
   (conversation full-width, back link in the header) while the DM inbox
   promotes it to the whole content area — the list is the screen. */
#list-rail {
  display: none;
  grid-area: rail;
}

@media (min-width: 1024px) {
  body:has(#list-rail) {
    grid-template-areas:
      "sidebar notice notice"
      "sidebar connection connection"
      "sidebar rail nav"
      "sidebar rail main";
    grid-template-columns: var(--sidebar-width) 272px minmax(0, 1fr);
  }

  #list-rail {
    background-color: var(--color-bg);
    border-inline-end: 1px solid var(--color-border);
    display: flex;
    flex-direction: column;
    min-block-size: 0;
    overflow: hidden;

    .sidebar & {
      border-inline-start: 1px solid var(--color-border-darker);
    }
  }

  body:has(#list-rail) .dm-back {
    display: none;
  }
}

@media (min-width: 1160px) {
  body:has(#list-rail):has(#thread-panel:not([hidden]) [data-panel-kind="roster"]) {
    grid-template-areas:
      "sidebar notice notice notice"
      "sidebar connection connection connection"
      "sidebar rail nav thread"
      "sidebar rail main thread";
    grid-template-columns: var(--sidebar-width) 272px minmax(0, 1fr) var(--thread-width);
  }
}

/* Direct rooms also carry the 272px conversation rail, so their thread needs
   a wider viewport before all four columns can remain readable. */
@media (min-width: 1536px) {
  body:has(#list-rail):has(#thread-panel:not([hidden]) [data-panel-kind="thread"]) {
    --thread-width: var(--thread-panel-width);

    grid-template-areas:
      "sidebar notice notice notice"
      "sidebar connection connection connection"
      "sidebar rail nav thread"
      "sidebar rail main thread";
    grid-template-columns: var(--sidebar-width) 272px minmax(0, 1fr) var(--thread-width);
  }
}

@media (max-width: 1023.9px) {
  body.inbox:has(#list-rail) {
    #list-rail {
      display: flex;
      flex-direction: column;
      grid-area: main;
      min-block-size: 0;
    }

    #main-content {
      display: none;
    }
  }
}

#footer {
  grid-area: footer;
}
