.App {
  position: relative !important;
  padding-top: var(--header-height);
  padding-bottom: var(--app-bottom-padding);
  min-height: 100vh;

  @media @phone {
    padding-top: var(--header-height-phone);
  }
}

// PHONES: Somewhere on the page there will be a .App-backControl, a
// .App-primaryControl, and a .App-titleControl. We will position these on the
// left, right, and center of the header respectively.
@media @phone {
  .App-navigation {
    .header-background();
    border-bottom: 0;
    position: absolute;

    .affix & {
      position: fixed;
    }

    .scrolled & {
      box-shadow: 0 2px 6px var(--shadow-color);
    }
  }
  .App-primaryControl, .App-titleControl, .App-backControl {
    position: absolute !important;
    z-index: calc(~"var(--zindex-header) + 1");
    top: 0 !important;
    margin: 0;

    .App.affix &, .Composer & {
      position: fixed !important;
    }

    > .Button {
      float: none;
      background: transparent !important;
      box-shadow: none !important;
      height: var(--header-height-phone);
      width: auto;
      padding: 13px !important;
      margin: 0 !important;

      &:active {
        opacity: 0.5;
      }
    }
    > .Button--icon {
      width: 40px;
    }
  }
  // `App-primaryControl` is an extension point, so a page can carry several
  // controls (core's "start discussion" plus, say, an extension's follow
  // button). Each is absolutely positioned against the right edge, which
  // stacks them on top of one another. Where they share a parent — they are
  // list items of the same nav — that parent becomes a right-anchored flex
  // row instead, so the browser lays them out side by side at whatever width
  // each one happens to be.
  :has(> .App-primaryControl ~ .App-primaryControl) {
    position: absolute;
    z-index: calc(~"var(--zindex-header) + 1");
    top: 0;
    right: 0;
    display: flex;

    .App.affix &, .Composer & {
      position: fixed;
    }

    > .App-primaryControl {
      position: relative !important;
      right: auto;
    }
  }
  .App-primaryControl {
    width: auto;
    right: 0;

    &.Dropdown {
      .Button, .Button-caret {
        display: none !important;
      }
      .Dropdown-toggle, .Button-icon {
        display: block !important;
      }
    }
  }
  .App-primaryControl, .App-backControl {
    margin: 0 !important;

    > .Button {
      color: var(--header-control-color) !important;

      .Button-icon {
        display: block;
        font-size: 20px;
        margin: 0;
      }
      .Button-label {
        display: none;
      }
    }
  }

  .App-titleControl {
    width: 200px;
    left: 50%;
    margin-left: -100px;
    text-align: center;
    color: var(--header-color) !important;

    &,
    > .Button {
      font-size: 16px;
    }
    > .Button {
      color: var(--header-color);
      width: 100%;
      overflow: hidden;
      text-overflow: ellipsis;
    }

    &--text {
      line-height: var(--header-height-phone);
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
      font-weight: normal;
    }
  }

  .App-backControl {
    left: 0;

    .Navigation-pin {
      display: none;
    }
  }
}

// ------------------------------------
// Drawer

// On phones, the drawer is displayed in its semantic sense: as a drawer on
// the left side of the screen. On other devices, the drawer has no specific
// appearance.
@media @phone {
  .App:not(.drawerOpen) .App-drawer {
    visibility: hidden;
  }
  .drawerOpen {
    overflow: hidden;
  }
  .App-drawer {
    background: var(--header-bg);
    width: var(--drawer-width);
    position: fixed;
    left: 0;
    top: 0;
    bottom: 0;
    box-shadow: 0 2px 6px var(--shadow-color);
    transform: translateX(calc(~"-6px - var(--drawer-width)"));
    transition: transform 0.2s;
    z-index: var(--zindex-modal);

    .drawerOpen & {
      -webkit-transform: none !important;
              transform: none !important;
    }
  }
  .drawer-backdrop {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    z-index: var(--zindex-modal-background);
    background-color: var(--overlay-bg);
    opacity: 0;
    transition: opacity 0.2s;

    &.in {
      opacity: 0.9;
    }
  }
}

// ------------------------------------
// Header

.App-header {
  display: flex;
}
.Header-navigation {
  position: absolute;
}
.Header-controls {
  margin: 0;
  padding: 0;
  list-style: none;
}
// Items collapsed out of the header row keep the markup they had on the row,
// including the flat header-button styling. Inside a menu that reads as a row
// of unpadded text, so give them the same shape as any other dropdown item.
.OverflowingList-dropdown > .Dropdown-menu {
  min-width: 180px;

  // Items arrive from the row as whatever component put them there — a plain
  // link, a button, the label of a dropdown — carrying whatever alignment and
  // padding that component uses. A `.Button` centres its contents and pads by
  // 13px, a menu link starts them and pads by 15px, so left alone the column
  // comes out ragged: icons at a different offset on every line, shifted by
  // however long each label happens to be.
  //
  // `justify-content` is the part that matters. These are flex containers, so
  // `text-align` alone does nothing about the centring.
  > li > .Button,
  > li > a,
  // A split dropdown renders its main action as a direct child of the group
  // rather than as the first entry of its menu, so it needs naming separately
  // to line up with the plain items above it.
  > li > .Dropdown > .Button,
  > li > .Dropdown > a {
    justify-content: flex-start;
    text-align: left;
    width: 100%;
    padding-left: 15px;
  }

  // An item that was itself a dropdown on the row would otherwise render its
  // own toggle and float a second panel alongside this one. Its contents are
  // laid out inline as a titled group instead: the toggle is redundant once
  // the group is always open, and a nested panel is unusable on the narrow
  // screens that trigger the collapse in the first place.
  .Dropdown {
    display: block;
    width: 100%;

    > .Dropdown-toggle,
    > .Dropdown-menu > li > .Dropdown-toggle {
      display: none;
    }

    > .Dropdown-menu {
      display: block;
      position: static;
      float: none;
      width: 100%;
      min-width: 0;
      margin: 0;
      padding: 0;
      border: 0;
      border-radius: 0;
      box-shadow: none;
      background: transparent;
    }

    // The group's own label stays as a heading, and its children are stepped in
    // from the common indent above so the nesting that was in the row is still
    // legible.
    > .Dropdown-menu > li:not(:first-child) > a,
    > .Dropdown-menu > li:not(:first-child) > .Button {
      padding-left: 30px;
    }
  }
}
.Header-logo {
  display: block;
  max-height: 30px;

  &--dark-mode {
    display: none;
  }

  // Replace with dark mode logo if it exists
  [data-theme^='dark']:has(&--dark-mode) & {
    display: none;

    &--dark-mode {
      display: block;
    }
  }
}

// On phones, the header is displayed inside of the drawer. We lay its
// contents out vertically.
@media @phone {
  .App-header {
    .container {
      padding: 0;
      width: 100%;
    }
  }
  .Header-navigation {
    display: none;
  }
  .Header-title {
    padding: 13px 10px;
    font-size: 16px;
    font-weight: normal;
    margin: 0;
    text-align: center;
  }
  .Header-controls {
    margin-top: 10px;

    > li {
      padding: 0 10px 0;
    }
    .FormControl, .ButtonGroup, .Button {
      width: 100%;
      justify-content: start;
    }
    .Dropdown-menu {
      .ButtonGroup, .Button {
        width: auto;
      }
    }
  }
}

// On other devices, we stick the header up the top of the page, overlaying
// the page toolbar that we styled earlier. We lay its contents out
// horizontally.
@media @phone {
  [data-colored-header=true] .App-drawer {
    .light-contents(@name: 'header-colored');
  }
}

@media @tablet-up {
  .App-navigation {
    display: none;
  }
  .App-header {
    .header-background();
    padding: 8px;
    position: absolute;
    border-bottom: 0;

    .container {
      display: flex;
      align-items: center;
      gap: 15px;
    }

    .affix & {
      position: fixed;
    }

    .scrolled & {
      box-shadow: 0 2px 6px var(--shadow-color);
    }

    [data-colored-header=true] & {
      .light-contents(@name: 'header-colored');
    }
  }

  .Header-controls {
    display: flex;
    align-items: center;
  }
  // Navigation is what yields when the header runs out of room; the controls
  // opposite it do not. `min-width: 0` is the part that does the work —
  // without it the flex default of `min-width: auto` pins this to its content
  // width, so a long set of links (from an extension, or just a lot of tags)
  // overflows the container and shoves the session controls off the edge
  // rather than compressing.
  //
  // Deliberately no `overflow` here. Header dropdown menus are absolutely
  // positioned but still descend from this element, so any non-visible
  // overflow value clips them shut, and `overflow-x` alone is no escape — the
  // other axis is then forced away from `visible` too. Items that do not fit
  // are moved into a menu by `OverflowingList` instead of being hidden.
  // Growing into the leftover room keeps the row reading as one group: with
  // the controls opposite held to the right edge by their auto margin, any
  // slack would otherwise collect as a single conspicuous hole between the
  // two. It costs nothing to lay out, since what actually fits is worked out
  // from the container's width rather than this element's.
  .Header-primary {
    min-width: 0;
    flex: 1 1 auto;

    .Header-controls {
      min-width: 0;
      flex-wrap: nowrap;
    }
  }
  // The logo is how you get back to the index once links start dropping off,
  // so it keeps its full width no matter how tight things get.
  .Header-title {
    font-size: 18px;
    font-weight: normal;
    line-height: 34px;
    flex-shrink: 0;
  }
  // No auto margin to push this to the right: an auto margin takes the free
  // space before flex distributes any of it, which would park the controls at
  // the edge and leave the slack in one gap mid-row. Nav grows into it
  // instead, which puts these in the same place whenever the row is full.
  .Header-secondary {
    flex-shrink: 0;

    // Spacing for the row lives here rather than on the individual controls.
    // Their own padding varies — an icon button has none horizontally, a
    // labelled one has 13px either side — so relying on it left the icons
    // touching each other while the labelled controls sat far apart.
    //
    // Kept small deliberately: this row can hold eight or more controls, and
    // every pixel between them is one the navigation opposite cannot use.
    .Header-controls {
      gap: 2px;
    }
  }
}

// Between tablet and the wide desktop layouts the header carries everything it
// will ever carry — logo, navigation, and the full set of controls — without
// the room the widest screens have for it. Labels that repeat what their icon
// already says are dropped through this range so the navigation keeps its
// space; they return at `desktop-hd`.
@media (min-width: @screen-tablet) and (max-width: (@screen-desktop-hd - 0.02)) {
  // The username goes and the avatar stays: it identifies the session just as
  // well, and a name truncated to a few characters tells you nothing the
  // avatar hasn't already. The negative margin that tucks the avatar against
  // the button's left padding is what would otherwise leave the circle sitting
  // off-centre.
  .Header-secondary .SessionDropdown .Dropdown-toggle {
    .Button-label {
      display: none;
    }

    .Avatar {
      margin-left: -2px;
      margin-right: -2px;
    }
  }

  // The locale name is by far the widest thing left in the row — several times
  // the width of the icon buttons beside it — and it is the label most easily
  // spared, since the globe stands in for it and the current language is shown
  // as the checked item once the menu is open.
  .Header-secondary .LocaleDropdown .Dropdown-toggle {
    .Button--icon();

    // Now that the name is gone, the globe is the only thing left to say what
    // this control selects.
    .Button-icon {
      display: inline-block;
    }
  }

}


@media @desktop-hd {
  .Header-navigation {
    .hasPane.panePinned & {
      position: relative;
      width: ~"min(20%, var(--pane-width))";
    }
  }
}

@media (max-width: calc(@screen-desktop-hd + 80px)) {
  .Header-navigation {
    position: relative;
    width: auto;
  }
}

// ------------------------------------
// Content Area

.App-content {
  border-top: 1px solid var(--control-bg);
}

// On phones, the content area overlays the drawer, so we must give it a
// background and min-height so it cannot be seen through. When the drawer is
// meant to be open, we slide the content to the right to reveal the drawer.
@media @phone {
  .App-content {
    background: var(--body-bg);
    width: 100%;
    min-height: calc(~"100vh - var(--header-height-phone)");
  }
}
