/*
 * Purpose: Site header, primary navigation and the mobile off-canvas drawer.
 */

/* ------------------------------------------------------- ANNOUNCEMENT BAR */

.rh-announcement {
  background-color: var(--rh-dark);
  color: var(--rh-text-inverse);
  font-size: var(--fs-caption);
  text-align: center;
}

.rh-announcement__viewport {
  display: flex;
  align-items: center;
  justify-content: center;
  /* The height is the band; the text is centred in it rather than padded. */
  min-height: 34px;
  padding-block: var(--space-4);
}

.rh-announcement a {
  color: var(--rh-lime);
  font-weight: var(--fw-semibold);
  text-decoration: underline;
}

/*
 * One continuous marquee across every announcement, at all screen sizes.
 *
 * The track carries the set twice and travels exactly half its own width, so
 * the second copy lands where the first started and the loop never shows a
 * seam. Duration is set from the measured width by main.js, so a long set and
 * a short one move at the same speed rather than the same tempo.
 */
.rh-announcement--marquee .rh-announcement__viewport {
  overflow: hidden;
}

/*
 * The animation only runs once main.js has cloned enough copies to fill the
 * track. Before that - and with JavaScript off - the single group simply sits
 * centred and readable rather than sliding across a half-empty bar.
 */
.rh-announcement--marquee .rh-announcement__track {
  display: flex;
  width: max-content;
}

.rh-announcement--marquee.is-marquee .rh-announcement__track {
  animation: rh-marquee var(--rh-marquee-duration, 40s) linear infinite;
}

.rh-announcement__group {
  display: flex;
  align-items: center;
  margin: 0;
  padding: 0;
  list-style: none;
}

/*
 * No padding on the item itself. The separator dot carries equal margins
 * instead, which is what puts it exactly halfway between two messages - with
 * padding on the item the dot sat 8px from one and 48px from the next.
 */
.rh-announcement__item {
  display: flex;
  align-items: center;
  gap: 0;
  white-space: nowrap;
}

.rh-announcement__item::after {
  content: "";
  flex-shrink: 0;
  width: 4px;
  height: 4px;
  margin-inline: var(--space-24);
  border-radius: var(--r-pill);
  background-color: currentColor;
  opacity: 0.45;
}

@keyframes rh-marquee {
  from {
    transform: translateX(0);
  }

  to {
    transform: translateX(-50%);
  }
}

/* Hovering or tabbing to a link stops it, so it can be read and clicked. */
.rh-announcement--marquee.is-marquee:hover .rh-announcement__track,
.rh-announcement--marquee.is-marquee:focus-within .rh-announcement__track {
  animation-play-state: paused;
}

/*
 * No travelling text under reduced motion. The duplicate copy is dropped and
 * the set wraps normally, which is taller but entirely readable.
 */
@media (prefers-reduced-motion: reduce) {
  .rh-announcement--marquee .rh-announcement__track {
    animation: none;
    width: auto;
    justify-content: center;
  }

  .rh-announcement__group[aria-hidden="true"] {
    display: none;
  }

  .rh-announcement__group {
    flex-wrap: wrap;
    justify-content: center;
  }

  .rh-announcement__item {
    white-space: normal;
  }
}

/* ------------------------------------------------------------------ HEADER */

.rh-header {
  position: relative;
  z-index: var(--z-header);
  background-color: var(--rh-white);
  border-bottom: 1px solid var(--rh-border);
}

/*
 * Hides on the way down, returns on the way up. main.js toggles .is-hidden and
 * publishes --rh-header-offset, which is what any other sticky element on the
 * page (the search bar on Find a Room) sits below - so the two move together
 * instead of overlapping or leaving a gap.
 */
.rh-header--sticky {
  position: sticky;
  top: 0;
  transition: transform var(--dur-base) var(--ease-out);
}

/*
 * The admin bar is fixed at the top of the viewport, so a sticky header pinned
 * at 0 ends up underneath it. Only ever visible to a logged-in editor, but that
 * is exactly who is looking at the site while building it. main.js reads this
 * computed top, so the search bar below stays in step automatically.
 */
body.admin-bar .rh-header--sticky {
  top: 32px;
}

@media screen and (max-width: 782px) {
  body.admin-bar .rh-header--sticky {
    top: 46px;
  }
}

.rh-header--sticky.is-hidden {
  transform: translateY(-100%);
}

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

/*
 * The gap scales with the room available. 24px is right once the full nav is
 * showing, but the header already overflowed by 55px at exactly 1024px, so
 * spending the same gap on a narrow screen would take space from the one thing
 * that must not shrink - the logo lockup.
 */
.rh-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-8);
  min-height: var(--header-height);
}

/*
 * Below 360px the tagline lockup (189px) and the header actions (96px) leave
 * only 3px of slack inside the default 16px gutters, so the actions were being
 * clipped by a few pixels on the very smallest phones. The gutter gives way
 * rather than the logo: the lockup staying at 48px at every size is a
 * deliberate decision, and this is scoped to the header so the page's own
 * rhythm is untouched.
 */
@media (max-width: 359px) {
  .rh-header .rh-container {
    padding-inline: var(--space-12);
  }
}

@media (min-width: 480px) {
  .rh-header__inner {
    gap: var(--space-12);
  }
}

@media (min-width: 768px) {
  .rh-header__inner {
    gap: var(--space-16);
  }
}

@media (min-width: 1200px) {
  .rh-header__inner {
    gap: var(--space-24);
  }
}

.rh-header__brand {
  display: inline-flex;
  align-items: center;
  flex-shrink: 0;
}

/*
 * The header carries the tagline lockup, which is a taller, denser artwork than
 * the plain wordmark (1007x256 rather than 938x200). It therefore needs more
 * height to keep the tagline legible, and it is capped by width so it can never
 * crowd the navigation on a narrow viewport.
 */
.rh-header__brand img,
.rh-header__brand svg {
  height: 48px;
  width: auto;
  /* Wide enough for the lockup at 48px; it is a 3.93:1 image. */
  max-width: 200px;
  object-fit: contain;
  object-position: left center;
}

@media (min-width: 1024px) {
  .rh-header__brand img,
  .rh-header__brand svg {
    height: 48px;
    max-width: 232px;
  }
}

/*
 * The tagline lockup is the logo everywhere, including the smallest phones and
 * the drawer, at the brand owner's direction. The compact mark stays in the
 * markup for the narrow desktop band below, and is otherwise never shown.
 *
 * At 320px the lockup is about 118px wide at this height, so it still clears
 * the search and menu buttons beside it.
 */
.rh-header__brand-mark {
  display: none;
}

/*
 * Held at 48px down to the smallest phone. At 320px the lockup is about 189px
 * wide, which still clears the search and menu buttons beside it.
 */
@media (max-width: 399px) {
  .rh-header .rh-header__brand img,
  .rh-header .rh-header__brand svg {
    height: 48px;
    max-width: 190px;
  }
}

/*
 * The compact mark also comes back in the narrow band just above the desktop
 * breakpoint. At exactly 1024px the full nav appears while the tagline lockup
 * is still at full width, and the row overflowed the viewport by 55px - a real
 * horizontal scrollbar on a common laptop and tablet-landscape width.
 */
@media (min-width: 1024px) and (max-width: 1199px) {
  .rh-header__brand-full {
    display: none;
  }

  .rh-header__brand-mark {
    display: block;
    height: 40px;
    width: auto;
  }
}

/* Primary navigation - desktop only; mobile uses the drawer. */
.rh-header__nav {
  display: none;
}

@media (min-width: 1024px) {
  .rh-header__nav {
    display: block;
    flex: 1;
  }
}

.rh-nav__list {
  display: flex;
  align-items: center;
  gap: var(--space-4);
}

.rh-nav__link {
  display: inline-flex;
  align-items: center;
  /* Horizontal padding is hit area only; the item carries no background. */
  padding: var(--space-4) var(--space-12);
  font-size: var(--fs-small);
  font-weight: var(--fw-semibold);
  color: var(--rh-text-primary);
  white-space: nowrap;
}

/* Hover is a colour change only - no pill, no underline. */
.rh-nav__link:hover {
  color: var(--rh-teal);
  text-decoration: none;
}

.rh-nav__item--active .rh-nav__link {
  color: var(--rh-teal);
}

/* Header actions */
.rh-header__actions {
  display: flex;
  align-items: center;
  gap: var(--space-8);
  flex-shrink: 0;
}

/*
 * One height across the whole action row. The account pill stands at
 * --touch-target and the icon button matches it, but the CTA is a --sm button
 * at 36px, so it sat 8px short of the pill beside it. Levelling up rather than
 * down keeps every target at the full 44px.
 */
.rh-header__actions .rh-btn {
  min-height: var(--touch-target);
}

.rh-header__action-desktop {
  display: none;
}

@media (min-width: 1024px) {
  .rh-header__action-desktop {
    display: inline-flex;
  }
}

.rh-header__menu-toggle {
  display: inline-flex;
}

@media (min-width: 1024px) {
  .rh-header__menu-toggle {
    display: none;
  }
}

/* --------------------------------------------------------- ACCOUNT MENU */

.rh-account {
  position: relative;
  display: none;
}

@media (min-width: 1024px) {
  .rh-account {
    display: block;
  }
}

/*
 * Even padding on all four sides. The 12px sides were declared and the 4px top
 * and bottom were not what showed: min-height won, and flex centring spread the
 * difference, so the gap above and below the avatar was whatever happened to be
 * left over. Stated properly here - 12 + 18 + 12 plus the two borders is exactly
 * the 44px touch target, so the height is the same and nothing is accidental.
 */
.rh-account__trigger {
  display: inline-flex;
  align-items: center;
  gap: var(--space-8);
  min-height: var(--touch-target);
  padding: var(--space-8);
  border: 1px solid var(--rh-border);
  border-radius: var(--r-pill);
  font-size: var(--fs-small);
  font-weight: var(--fw-semibold);
}

.rh-account__trigger:hover {
  border-color: var(--rh-border-strong);
}

/*
 * Both classes are on the same element, and .rh-avatar in sections.css sets
 * 40px. That file loads after this one, so at equal specificity it won and this
 * rule did nothing at all - the avatar rendered at 40px in a 44px pill, all but
 * touching the border. Qualified with .rh-avatar so it is the more specific
 * selector rather than merely the later one.
 */
.rh-avatar.rh-account__avatar {
  width: 26px;
  height: 26px;
  font-size: 11px;
}

.rh-account__panel {
  position: absolute;
  top: calc(100% + var(--space-8));
  right: 0;
  z-index: var(--z-dropdown);
  width: 280px;
  /* Stay inside the viewport; scroll internally when taller. */
  max-height: calc(100vh - var(--header-height) - var(--space-32));
  overflow-y: auto;
  padding: var(--space-8);
  background-color: var(--rh-white);
  border: 1px solid var(--rh-border);
  border-radius: var(--r-card);
  box-shadow: var(--shadow-lg);
}


/*
 * The panel shows one side of the account at a time. Stacked, the two sides ran
 * to 15 links and fell past the fold, which put the owner half behind a scroll
 * inside a dropdown.
 */
.rh-account__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-8);
  padding: var(--space-8) var(--space-12) var(--space-12);
  border-bottom: 1px solid var(--rh-border);
}

.rh-account__name {
  font-size: var(--fs-12);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--rh-text-secondary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.rh-account__alert {
  display: inline-flex;
  align-items: center;
  gap: var(--space-4);
  flex-shrink: 0;
  font-size: var(--fs-12);
  font-weight: var(--fw-semibold);
  color: var(--rh-teal);
}

/* Two-way switch between the student and owner sides. */
.rh-account__tabs {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-4);
  margin: var(--space-8) 0;
  padding: var(--space-4);
  border-radius: var(--r-button);
  background-color: var(--rh-surface);
}

.rh-account__tab {
  min-height: 34px;
  padding: var(--space-4) var(--space-8);
  border-radius: var(--r-button);
  font-size: var(--fs-12);
  font-weight: var(--fw-semibold);
  color: var(--rh-text-secondary);
  cursor: pointer;
  /* Two words on a narrow tab should not clip. */
  line-height: var(--lh-snug);
}

.rh-account__tab[aria-selected="true"] {
  background-color: var(--rh-white);
  color: var(--rh-teal);
  box-shadow: var(--shadow-sm);
}


.rh-account__list--fixed {
  margin-top: var(--space-8);
  padding-top: var(--space-8);
  border-top: 1px solid var(--rh-border);
}

.rh-account__group-label {
  padding: var(--space-8) var(--space-12) var(--space-4);
  font-size: var(--fs-12);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--rh-text-secondary);
}

.rh-account__link {
  display: flex;
  align-items: center;
  gap: var(--space-12);
  padding: var(--space-8) var(--space-12);
  border-radius: var(--r-button);
  font-size: var(--fs-small);
  color: var(--rh-text-primary);
}

.rh-account__link:hover {
  background-color: var(--rh-surface);
  color: var(--rh-teal);
  text-decoration: none;
}

.rh-account__link .rh-icon {
  width: 18px;
  height: 18px;
  color: var(--rh-text-secondary);
}

/* --------------------------------------------------------- MOBILE DRAWER */

.rh-drawer {
  position: fixed;
  inset: 0;
  z-index: var(--z-drawer);
  visibility: hidden;
}

.rh-drawer[data-open="true"] {
  visibility: visible;
}

.rh-drawer__overlay {
  position: absolute;
  inset: 0;
  background-color: rgba(3, 38, 34, 0.5);
  opacity: 0;
  transition: opacity var(--dur-base) var(--ease-out);
}

.rh-drawer[data-open="true"] .rh-drawer__overlay {
  opacity: 1;
}

.rh-drawer__panel {
  position: absolute;
  inset-block: 0;
  right: 0;
  display: flex;
  flex-direction: column;
  width: min(92vw, 380px);
  /* Full viewport height, accounting for mobile browser chrome. */
  height: 100dvh;
  background-color: var(--rh-white);
  transform: translateX(100%);
  transition: transform var(--dur-base) var(--ease-out);
}

.rh-drawer[data-open="true"] .rh-drawer__panel {
  transform: translateX(0);
}

.rh-drawer__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-16);
  padding: var(--space-16);
  border-bottom: 1px solid var(--rh-border);
  flex-shrink: 0;
}

.rh-drawer__head img {
  height: 30px;
  width: auto;
}

/* The drawer body scrolls internally, never the page behind it. */
.rh-drawer__body {
  flex: 1;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: var(--space-16);
}

.rh-drawer__foot {
  flex-shrink: 0;
  display: grid;
  gap: var(--space-8);
  padding: var(--space-16);
  padding-bottom: calc(var(--space-16) + env(safe-area-inset-bottom, 0px));
  border-top: 1px solid var(--rh-border);
  background-color: var(--rh-white);
}

.rh-drawer__nav {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.rh-drawer__link {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-12);
  min-height: var(--touch-target);
  padding: var(--space-12);
  border-radius: var(--r-button);
  font-size: var(--fs-body);
  font-weight: var(--fw-semibold);
  color: var(--rh-text-primary);
}

.rh-drawer__link:hover {
  background-color: var(--rh-surface);
  text-decoration: none;
}

.rh-drawer__section-label {
  padding: var(--space-16) var(--space-12) var(--space-8);
  font-size: var(--fs-12);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--rh-text-secondary);
}

/* The drawer shows the same lockup as the header, sized for the panel. */
.rh-drawer__brand img,
.rh-drawer__brand svg {
  height: 40px;
  width: auto;
  max-width: 180px;
  object-fit: contain;
  object-position: left center;
}

/* The compact mark is a header-only affordance. */
.rh-drawer__brand .rh-header__brand-mark {
  display: none;
}

/* ------------------------------------------------------------ NAV STATES */

/*
 * The current section is marked so a visitor can see where they are. WordPress
 * sets the current-menu-* classes; roomhaina_mark_current_nav_item() extends
 * that to detail pages, where the menu item points at the archive rather than
 * at the post being viewed.
 */
/*
 * Matches .rh-nav__link above. These have to move together - this rule is what
 * the active-item underline is positioned against, so leaving it at 8px would
 * float the rule away from the text it belongs to.
 */
.rh-header__nav a {
  position: relative;
  padding-block: var(--space-4);
}

.rh-header__nav .rh-nav__item--active > a {
  color: var(--rh-teal);
  font-weight: var(--fw-semibold);
}

/*
 * An underline marks the active item without shifting anything around it. It
 * is inset by the link's own horizontal padding so the rule sits under the
 * word rather than under the whole hit area.
 */
.rh-header__nav .rh-nav__item--active > a::after {
  content: "";
  position: absolute;
  left: var(--space-12);
  right: var(--space-12);
  bottom: 0;
  height: 2px;
  border-radius: 2px;
  background-color: var(--rh-teal);
}

/* The drawer marks the current item too, without the underline. */
.rh-drawer .rh-nav__item--active > a {
  color: var(--rh-teal);
  font-weight: var(--fw-semibold);
}

