// The variables and the desktop mixin. Neither outputs anything on its own.
@import 'top-nav-vars';
@import 'top-nav-desktop';

.ds2-top-nav {
  position: relative;
  font-family: uolInter, Arial, Helvetica, sans-serif;
  background: $topNavBgColour;
  color: $topNavFgColour;

  // Keeps sizing consistent, as the site doesn't set border-box globally.
  &,
  *,
  *::before,
  *::after {
    box-sizing: border-box;
  }

  // One keyboard focus ring for the whole header. :where() keeps it easy to override.
  :where(a, button):focus-visible {
    outline: $topNavFocusOutlineWidth solid $topNavHighlightColour;
    outline-offset: $topNavFocusOutlineOffset;
  }

  // Top row.

  &__bar {
    display: flex;
    align-items: center;
    position: relative;
    // Keeps the bar's height when the search box hides the logo.
    min-height: $topNavBarHeight;
    padding: $spacing-5;
  }

  &__logo {
    display: inline-flex;
    align-items: center;
    margin-right: auto;
    padding-block: $topNavLogoPaddingBlock;
    // Tops up the bar's padding to $topNavLogoInset. Shrinks on very narrow screens with large
    // text, so the bar still fits.
    padding-inline: unquote("min(#{$topNavLogoInset} - #{$spacing-5}, 8.6vw) min(#{$spacing-5}, 8.6vw)");
    color: inherit;
    fill: currentColor;
  }

  // Mobile and tablet show the crest alone; desktop swaps it for the full logo.
  &__logo-crest {
    width: $topNavCrestWidth;
    height: $topNavCrestHeight;

    @media (min-width: $topNavDesktopBreakpoint) {
      display: none;
    }
  }

  &__logo-full {
    display: none;
    height: $topNavCrestHeight;

    @media (min-width: $topNavDesktopBreakpoint) {
      display: block;
    }
  }

  // Shared reset for the icon buttons.
  &__search-toggle,
  &__search-close,
  &__menu-toggle,
  &__search-submit {
    align-items: center;
    justify-content: center;
    flex: none;
    width: $topNavIconButtonSize;
    height: $topNavIconButtonSize;
    padding: 0;
    border: 0;
    background: none;
    color: inherit;
    cursor: pointer;

    // Hover colour for mouse users only, so it doesn't stick after a tap.
    @media (hover: hover) {
      &:hover {
        color: $topNavHighlightColour;
      }
    }
  }

  &__menu-toggle {
    width: $topNavMenuButtonSize;
    height: $topNavMenuButtonSize;
  }

  // Only shown once the JS is running.
  &__search-toggle,
  &__menu-toggle {
    display: none;
  }

  // Only shown while the search box is open, so touch users can close it.
  &__search-close {
    display: none;

    .ds2-top-nav__back-arrow {
      margin: 0;
    }
  }

  &__search-icon {
    width: $topNavSearchIconSize;
    height: $topNavSearchIconSize;
    fill: currentColor;
  }

  &__menu-icon {
    fill: currentColor;

    &--burger {
      // In px, like the other icon sizes.
      width: 24px;
      height: 12px;
    }

    &--close {
      display: none;
      width: $topNavCloseIconSize;
      height: $topNavCloseIconSize;
    }
  }

  // The burger turns into a cross when aria-expanded is true, so the icon matches what's announced.
  &__menu-toggle[aria-expanded="true"] {
    .ds2-top-nav__menu-icon--burger {
      display: none;
    }

    .ds2-top-nav__menu-icon--close {
      display: block;
    }
  }

  // Only used on desktop, where the close arrow and box move together.
  &__search-group {
    display: contents;
  }

  // Search box.

  &__search {
    display: flex;
    align-items: center;
    flex: 1;
    min-width: 0;
    max-width: $topNavSearchMaxWidth;
    height: 3.75rem;
    margin-inline: $spacing-3;
    // The border stays px so it remains a hairline.
    border: 1px solid $topNavSearchBorderColour;
    border-radius: 0.25rem;

    // The focus ring goes round the whole box, not just the input.
    &:has(.ds2-top-nav__search-input:focus-visible) {
      outline: $topNavFocusOutlineWidth solid $topNavHighlightColour;
      outline-offset: $topNavFocusOutlineOffset;
    }
  }

  &__search-input {
    flex: 1;
    min-width: 0;
    height: 100%;
    padding: 0 $spacing-3 0 $spacing-1;
    border: 0;
    background: transparent;
    color: inherit;
    font: inherit;
    // Keeps iOS from zooming in on focus; 1rem is 16px unless the user has chosen a larger size.
    font-size: $topNavLinkFontSize;

    &::placeholder {
      color: inherit;
      opacity: 1;
    }

    &:focus {
      outline: none;
    }
  }

  // Comes after the input in the markup but sits on the left, to match the design.
  &__search-submit {
    display: inline-flex;
    order: -1;
    margin-left: $spacing-2;
  }

  // Menu.

  &__list {
    display: flex;
    flex-direction: column;
    gap: $spacing-1;
    max-width: $topNavListMaxWidth;
    margin: 0;
    padding: 0;
    list-style: none;
  }

  &__list--level-1 {
    padding-block: $spacing-7 $spacing-6;
  }

  &__link {
    display: flex;
    align-items: center;
    width: 100%;
    // Uses min-height so rows can grow without clipping the text or tap target.
    min-height: $topNavRowHeight;
    padding: 0 $topNavLinkPaddingInline;
    border: 0;
    background: none;
    color: inherit;
    font: inherit;
    font-size: $topNavLinkFontSize;
    line-height: 1.5;
    text-align: left;
    text-decoration: none;
    cursor: pointer;

    // The focus ring sits inside the row, so the screen edge doesn't cut it off.
    &:focus-visible {
      outline-offset: -$topNavFocusOutlineWidth * 2;
    }

    @media (hover: hover) {
      &:hover {
        color: $topNavHighlightColour;
        text-decoration: underline;
        // Px so the line stays a hairline.
        text-decoration-thickness: 1px;
        text-underline-offset: 4px;
      }
    }
  }

  &__panel &__link {
    min-height: $topNavChildRowHeight;
  }

  &__list--level-2,
  &__list--level-3 {
    padding-bottom: $spacing-6;
  }

  // Back buttons need the JS, so they're hidden until it runs.
  &__back {
    display: none;
    align-items: center;
    height: $topNavBackHeight;
    padding: 0 $spacing-5;
    border: 0;
    background: none;
    color: $topNavHighlightColour;
    cursor: pointer;

    // Keeps the focus ring inside the button, away from the screen edge.
    &:focus-visible {
      outline-offset: -$topNavFocusOutlineWidth * 2;
    }
  }

  // Arrows are drawn with borders so they stay visible in high contrast mode.
  &__arrow,
  &__back-arrow {
    position: relative;
    flex: none;
    // In px, like the rest of the arrow.
    width: 13px;
    border-top: $topNavArrowStroke solid currentColor;

    // The arrowhead is a rotated square with two borders.
    &::after {
      content: '';
      position: absolute;
      top: -($topNavArrowStroke / 2) - ($topNavArrowHeadSize / 2);
      right: $topNavArrowStroke / 2;
      width: $topNavArrowHeadSize;
      height: $topNavArrowHeadSize;
      border-top: $topNavArrowStroke solid currentColor;
      border-right: $topNavArrowStroke solid currentColor;
      transform: rotate(45deg);
    }
  }

  &__arrow {
    margin-left: $spacing-4;
  }

  // The same arrow, pointing left.
  &__back-arrow {
    transform: scaleX(-1);
  }

  // Without JS every level shows as one indented list, with no arrows suggesting a drill-down.
  &:not(.ds2-top-nav--js) {
    .ds2-top-nav__arrow {
      display: none;
    }

    .ds2-top-nav__list--level-2,
    .ds2-top-nav__list--level-3 {
      padding-left: $spacing-5;
    }
  }

  // With JS, the search box and menu stay hidden behind the icon buttons until opened.
  &--js {
    .ds2-top-nav__search-toggle,
    .ds2-top-nav__menu-toggle {
      display: inline-flex;
    }

    .ds2-top-nav__search,
    .ds2-top-nav__nav {
      display: none;
    }

    // The open menu fills the screen below the bar.
    // It overlaps the bar by 1px so no gap shows on scaled displays.
    .ds2-top-nav__nav {
      position: absolute;
      top: calc(100% - #{$topNavSeamOverlap});
      left: 0;
      right: 0;
      z-index: $topNavMenuZIndex;
      min-height: unquote("calc(100vh - #{$topNavBarHeight} + #{$topNavSeamOverlap})");
      min-height: unquote("calc(100dvh - #{$topNavBarHeight} + #{$topNavSeamOverlap})");
      padding-top: $topNavSeamOverlap;
      background: $topNavBgColour;
      // Closed panels sit off to the right; this stops them causing sideways scrolling.
      overflow-x: clip;
    }

    .ds2-top-nav__back {
      display: inline-flex;
    }

    // Drill-down: each panel slides in from the right over its parent list.
    .ds2-top-nav__panel {
      position: absolute;
      // Sits above the arrows in the list below.
      z-index: 1;
      top: 0;
      left: 0;
      width: 100%;
      // Closed panels don't add to the page height.
      height: 100%;
      overflow: hidden;
      padding-top: $spacing-5;
      background: $topNavBgColour;
      transform: translateX(100%);
      // Hidden once closed, so nothing in it can be focused or read out.
      visibility: hidden;
      transition: transform $topNavSlideDuration ease, visibility 0s linear $topNavSlideDuration;
    }

    .ds2-top-nav__panel--open {
      height: auto;
      min-height: 100%;
      overflow: visible;
      transform: none;
      visibility: visible;
      transition: transform $topNavSlideDuration ease;
    }

    @media (prefers-reduced-motion: reduce) {
      .ds2-top-nav__panel,
      .ds2-top-nav__panel--open {
        transition: none;
      }
    }
  }

  // Open menu, mobile and tablet.
  &--menu-open {
    .ds2-top-nav__nav {
      display: block;
    }
  }

  // Search open. --search-closing keeps the open layout while it animates closed.
  &--search-open,
  &--search-closing {
    // The arrow sits against the box, and the pair is centred between the edge and the burger.
    .ds2-top-nav__search-close {
      display: inline-flex;
      margin-left: auto;
    }

    .ds2-top-nav__search {
      display: flex;
      max-width: $topNavSearchSlideEndWidth;
      margin-inline: $spacing-3 auto;
      overflow: hidden;
    }
  }

  // Once search is open, the logo and search icon are hidden and leave the tab order.
  &--search-open {
    .ds2-top-nav__logo,
    .ds2-top-nav__search-toggle {
      display: none;
    }

    .ds2-top-nav__search {
      animation: ds2-top-nav-search-grow $topNavSearchSlideDuration ease;

      @media (prefers-reduced-motion: reduce) {
        animation: none;
      }
    }
  }

  // While the box opens or closes, the logo and search icon fade where they stand.
  // Must come after &--search-open.
  &--search-opening,
  &--search-closing {
    .ds2-top-nav__logo,
    .ds2-top-nav__search-toggle {
      display: inline-flex;
      // Taken out of the flow so the box has room straight away.
      position: absolute;
      top: $spacing-5;
      bottom: $spacing-5;
      margin-block: auto;
      pointer-events: none;
    }

    .ds2-top-nav__logo {
      left: $spacing-5;
    }

    // Just left of the burger.
    .ds2-top-nav__search-toggle {
      right: unquote("calc(#{$spacing-5} + #{$topNavMenuButtonSize})");
    }
  }

  &--search-opening {
    .ds2-top-nav__logo,
    .ds2-top-nav__search-toggle {
      animation: ds2-top-nav-fade-out $topNavSearchSlideDuration ease forwards;
    }

    .ds2-top-nav__search-close {
      animation: ds2-top-nav-fade-in $topNavSearchSlideDuration ease;
    }
  }

  // The same in reverse. Nothing in the closing box takes clicks.
  &--search-closing {
    .ds2-top-nav__logo,
    .ds2-top-nav__search-toggle {
      animation: ds2-top-nav-fade-in $topNavSearchSlideDuration ease;
    }

    .ds2-top-nav__search-close {
      pointer-events: none;
      animation: ds2-top-nav-fade-out $topNavSearchSlideDuration ease forwards;
    }

    .ds2-top-nav__search {
      pointer-events: none;
      animation: ds2-top-nav-search-shrink $topNavSearchSlideDuration ease forwards;
    }
  }

  // From tablet up the logo stays while search is open, and the box is centred between it and the
  // burger. Must come after the rules above. Desktop overrides it.
  @media (min-width: $topNavTabletBreakpoint) {
    &--search-open,
    &--search-closing {
      // Gives up its auto margin so the arrow and box are centred in the space that's left.
      .ds2-top-nav__logo {
        margin-right: 0;
      }

      .ds2-top-nav__search {
        max-width: $topNavTabletSearchSlideEndWidth;
      }
    }

    &--search-open {
      .ds2-top-nav__logo {
        display: inline-flex;
      }

      .ds2-top-nav__search {
        animation: ds2-top-nav-tablet-search-grow $topNavSearchSlideDuration ease;

        @media (prefers-reduced-motion: reduce) {
          animation: none;
        }
      }
    }

    // The logo stays where it is rather than fading.
    &--search-opening,
    &--search-closing {
      .ds2-top-nav__logo {
        position: static;
        pointer-events: auto;
        animation: none;
      }
    }

    &--search-closing .ds2-top-nav__search {
      animation: ds2-top-nav-tablet-search-shrink $topNavSearchSlideDuration ease forwards;
    }
  }

  // Desktop layout, from _ds2-top-nav-desktop.scss.
  @include ds2-top-nav-desktop;

  // Search animations. Opening and closing need different names, or the browser won't replay them.
  @keyframes ds2-top-nav-fade-out {
    from {
      opacity: 1;
    }

    to {
      opacity: 0;
    }
  }

  @keyframes ds2-top-nav-fade-in {
    from {
      opacity: 0;
    }

    to {
      opacity: 1;
    }
  }

  // Fades in over the last 15%.
  @keyframes ds2-top-nav-icon-fade-in-late {
    from {
      opacity: 0;
    }

    85% {
      opacity: 0;
    }

    to {
      opacity: 1;
    }
  }

  @keyframes ds2-top-nav-search-shrink {
    from {
      max-width: $topNavSearchSlideEndWidth;
      opacity: 1;
    }

    67% {
      opacity: 1;
    }

    to {
      max-width: $topNavIconButtonSize;
      opacity: 0;
    }
  }

  @keyframes ds2-top-nav-search-grow {
    from {
      max-width: $topNavIconButtonSize;
      opacity: 0;
    }

    33% {
      opacity: 1;
    }

    to {
      max-width: $topNavSearchSlideEndWidth;
      opacity: 1;
    }
  }

  // The same as the mobile ones, with room left for the logo.
  @keyframes ds2-top-nav-tablet-search-grow {
    from {
      max-width: $topNavIconButtonSize;
      opacity: 0;
    }

    33% {
      opacity: 1;
    }

    to {
      max-width: $topNavTabletSearchSlideEndWidth;
      opacity: 1;
    }
  }

  @keyframes ds2-top-nav-tablet-search-shrink {
    from {
      max-width: $topNavTabletSearchSlideEndWidth;
      opacity: 1;
    }

    67% {
      opacity: 1;
    }

    to {
      max-width: $topNavIconButtonSize;
      opacity: 0;
    }
  }

  @keyframes ds2-top-nav-desktop-search-grow {
    from {
      max-width: $topNavIconButtonSize;
    }

    to {
      max-width: $topNavDesktopSearchMaxWidth;
    }
  }

  // Fades out over the same 15% the icon fades in.
  @keyframes ds2-top-nav-desktop-search-shrink {
    from {
      max-width: $topNavDesktopSearchMaxWidth;
      opacity: 1;
    }

    85% {
      opacity: 1;
    }

    to {
      max-width: $topNavIconButtonSize;
      opacity: 0;
    }
  }

  // Text for screen readers only. In px, as it's a fixed 1px box.
  &__visually-hidden {
    position: absolute !important;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
  }
}