/* The attendee portal's brand bar. Figma 516:5528. */

.portal-header {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  padding: 0 1.5rem;
  min-height: 3.25rem;
  background: var(--wa-color-brand-fill-loud);
  color: var(--wa-color-brand-on-loud);
}

.portal-header__brand {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  color: inherit;
  text-decoration: none;
  font-family: var(--wa-font-family-heading);
  font-weight: var(--wa-font-weight-heading);
  font-size: 1.125rem;
}

.portal-header__nav {
  display: flex;
  align-items: center;
  gap: 0.25rem;
}

.portal-header__nav-link {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.4rem 0.75rem;
  border-radius: 0.375rem;
  color: inherit;
  text-decoration: none;
  font-size: 0.9375rem;
  font-weight: 500;
  /* A two-line "My Bookings" reads as broken on the wrapped phone nav row. */
  white-space: nowrap;
}

/* brand-40, matching the admin topbar. NOT --wa-color-brand-fill-normal, which
   resolves to brand-90 (var(--wa-color-brand-90)) and put white text on a near-white pill at
   1.29:1 against a 4.5:1 requirement. The design-token test passes either way —
   it checks that a token RESOLVES, never that the result can be read. */
.portal-header__nav-link:hover,
.portal-header__nav-link:focus-visible {
  background: var(--wa-color-brand-40);
}

.portal-header__nav-link--current {
  background: var(--wa-color-brand-40);
}

/* The unread-count pill inside the brand-coloured header bar. It inverts the
   loud brand fill because the link's hover/current state is already brand-40 —
   matching that would hide the pill exactly when the Notifications tab is lit. */
.portal-header__nav-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-inline-size: 1.125rem;
  block-size: 1.125rem;
  padding-inline: 0.25rem;
  border-radius: 999px;
  /* Inverted pill: the link's own hover/current state is already brand-40, so
     the badge needs the loud fill's on-colour to stay visible there. */
  background: var(--wa-color-brand-on-loud);
  color: var(--wa-color-brand-fill-loud);
  font-size: 0.75rem;
  font-weight: 600;
  line-height: 1;
}

/* The boxed back arrow and the hamburger are mobile chrome — the desktop bar
   keeps its labelled nav row and the in-page back pill (Figma 516:5528). */
.portal-header__back,
.portal-header__menu {
  display: none;
}

/* Menu panel links are dark-on-white (the dropdown panel is a raised surface,
   not the navy bar). Current page gets the same visual weight as the desktop
   current pill so the menu answers "where am I". */
.portal-header__menu-panel {
  min-width: 12rem;
  padding: 0.25rem;
}

.portal-header__menu-link {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  padding: 0.625rem 0.75rem;
  border-radius: 0.375rem;
  color: var(--wa-color-text-normal);
  text-decoration: none;
  font-size: 0.9375rem;
  white-space: nowrap;
}

.portal-header__menu-link i {
  width: 1rem;
  color: var(--wa-color-text-quiet);
}

.portal-header__menu-link:hover {
  background: var(--wa-color-neutral-fill-quiet);
}

.portal-header__menu-link--current {
  font-weight: 600;
}

.portal-header__actions {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-inline-start: auto;
  /* HMS-468 (QA) — the actions group is one unit. Letting it flex-shrink
     squeezed the nowrap "Se connecter" past its own right edge (a ~4-32px
     page overflow under ~360px) once the locale form held its width. The
     group holds; the brand wordmark is the bar's squeeze valve. */
  flex-shrink: 0;
}

.portal-header__avatar-button {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 2.25rem;
  min-height: 2.25rem;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: inherit;
  cursor: pointer;
}

.portal-header__profile-menu {
  padding: 0.75rem;
  min-width: 14rem;
}

.portal-header__profile-name {
  margin: 0;
  font-weight: 600;
}

.portal-header__profile-email {
  margin: 0 0 0.5rem;
  font-size: 0.875rem;
  color: var(--wa-color-text-quiet);
  overflow-wrap: anywhere;
}

.portal-header__locale {
  margin: 0;
  /* HMS-468 (QA) — the FORM is the flex item the bar squeezes, not the
     select inside it. Letting it shrink compressed the select to ~43-85px
     and clipped the longest autonym to "Franç…" whenever "Se connecter"
     widened the signed-out bar. Holding the form's width keeps the label
     readable; the brand wordmark is the element that gives instead. */
  flex-shrink: 0;
}

.portal-header__locale-select {
  max-inline-size: 7.5rem;
  font-size: 0.875rem;
  color: inherit;
  /* HMS-468 — `background: transparent` is a shorthand that also wipes
     background-image, which is where Web Awesome's native.css puts the
     select caret. The control kept native.css's ~38px end padding (the
     caret's room) but painted no caret, so the value read as clipped bare
     text. background-color keeps the transparent fill AND the caret. */
  background-color: transparent;
  border: 0;
  /* HMS-468 (QA) — a flex item's default shrink let the tight signed-out
     phone bar squeeze the select below its 5.75rem cap, clipping the
     longest autonym to "Franç…" whenever "Se connecter" widened the bar.
     The control holds its width; the brand wordmark is the element that
     gives (see the ≤640px block). */
  flex-shrink: 0;
}

.portal-header__locale-select option {
  color: var(--wa-color-text-normal);
}

/* The six signed-in nav links plus brand, locale select and avatar measure
   ~1039px — under ~1040px the avatar clips off the right edge of the bar, so
   the nav collapses into the hamburger at tablet width too, not just phones. */
@media (max-width: 66rem) {
  .portal-header__nav {
    display: none;
  }

  .portal-header__back {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    border: 1px solid var(--wa-color-brand-40);
    border-radius: 0.375rem;
    color: inherit;
    text-decoration: none;
    flex-shrink: 0;
  }

  .portal-header__back:hover {
    background: var(--wa-color-brand-40);
  }

  .portal-header__menu {
    display: block;
  }

  .portal-header__menu-button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 2.25rem;
    min-height: 2.25rem;
    padding: 0;
    border: 0;
    border-radius: 0.375rem;
    background: transparent;
    color: inherit;
    cursor: pointer;
  }

  .portal-header__menu-button:hover,
  .portal-header__menu-button:focus-visible {
    background: var(--wa-color-brand-40);
  }
}

@media (max-width: 639.98px) {
  .portal-header {
    gap: 0.5rem;
    padding: 0 0.75rem;
  }

  /* The nav row collapses into the hamburger — the nav/menu swap lives in the
     66rem block above, so this phone block only shrinks the bar itself. */
  .portal-header__brand-name {
    display: none;
  }

  /* The avatar + selector must fit inside the bar. The old 3.5rem cap +
     zeroed padding clipped even "English"; ~5.75rem fits the longest
     autonym ("Français") plus the caret. The room comes from shrinking the
     brand logo a step (below, after its base rule) and a tighter bar gap —
     not from cropping the label. */
  .portal-header__locale-select {
    max-inline-size: 5.75rem;
    padding-inline: 0.375rem 1.625rem;
    background-position: center right 0.375rem;
  }

  /* The brand link is the bar's squeeze valve: with the locale select now
     unshrinkable, the wordmark absorbs narrow widths instead. min-width:0
     lets the link shrink below its content; max-inline-size on the logo
     lets the image follow (object-fit: contain keeps it undistorted). */
  .portal-header__brand {
    min-width: 0;
  }

  .portal-header__nav-link {
    /* ~8px back for the long signed-out label ("Se connecter" ≈117px). */
    padding-inline: 0.5rem;
  }

  .portal-header__actions {
    gap: 0.25rem;
  }
}

/* Off-screen until focused. The project's .visually-hidden helper has no focus
   escape, so a skip link built on it can never be reached — which is why this
   is spelled out rather than reusing it. */
.portal__skip-link {
  position: absolute;
  inset-inline-start: -9999px;
  z-index: 100;
  padding: 0.5rem 1rem;
  background: var(--wa-color-surface-default);
  color: var(--wa-color-text-link);
}

.portal__skip-link:focus {
  inset-inline-start: 0.5rem;
  top: 0.5rem;
}

/* HMS-400 — the event wordmark replaces the product mark when brand_logo_url
   is configured. Sized like the text mark it replaces; contain keeps wide
   wordmarks from stretching the 3.25rem bar. */
.portal-header__brand-logo {
  display: block;
  height: 1.75rem;
  width: auto;
  max-width: 12rem;
  object-fit: contain;
}

@media (max-width: 639.98px) {
  /* HMS-468 — a step smaller on phones buys back the ~30px the wider
     locale select needed; height drives the width, so the wordmark keeps
     its aspect ratio. Must live AFTER the base rule above: an equal-order
     media block earlier in the file loses the cascade. */
  .portal-header__brand-logo {
    height: 1.4rem;
    /* HMS-468 (QA) — the wordmark is the squeeze valve once the locale
       select holds its width. Both properties are needed: max-inline-size
       lets the img follow a shrinking link box, and min-inline-size:0
       overrides the flex item's min-width:auto floor that would otherwise
       freeze it at intrinsic width and overflow the bar. */
    max-inline-size: 100%;
    min-inline-size: 0;
  }
}

/* HMS-1409 — the tabbar's total content height, shared with the hotel detail
   sticky booking bar which stacks directly on top of it. Keep the two quoting
   this one number or the bars drift apart again. */
:root {
  --portal-tabbar-h: 3.5rem;
}

/* Figma 576:3733 — the mobile bottom tab bar replaces the collapsed header
   nav for the four primary destinations. Desktop never renders it. */
.portal-tabbar {
  display: none;
}

@media (max-width: 639.98px) {
  .portal-tabbar {
    position: fixed;
    inset-inline: 0;
    bottom: 0;
    z-index: 950;
    display: flex;
    /* HMS-1409 — definite height: content sizing (~3.41rem) drifted under the
       booking bar's 3.5rem offset and left a dead gap between the bars. The
       safe-area padding lives inside the border-box height. */
    height: calc(var(--portal-tabbar-h) + env(safe-area-inset-bottom, 0px));
    background: var(--wa-color-surface-raised);
    border-top: 1px solid var(--wa-color-neutral-border-quiet);
    padding-bottom: env(safe-area-inset-bottom, 0px);
  }

  .portal-tabbar__tab {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.125rem;
    padding: 0.625rem 0.25rem 0.375rem;
    font-size: 0.6875rem;
    color: var(--wa-color-text-quiet);
    text-decoration: none;
  }

  .portal-tabbar__tab i {
    font-size: 1.125rem;
  }

  .portal-tabbar__tab--current {
    color: var(--wa-color-brand);
    font-weight: 600;
  }

  /* The tab bar occupies the bottom-right corner the chatbot FAB normally
     sits in — the FAB rises above the ~3.5rem bar. */
  .chatbot-widget {
    bottom: calc(4.5rem + env(safe-area-inset-bottom, 0px));
  }

  /* HMS-383 — when the hotel detail sticky Book bar is rendered it reserves a
     5.5rem right lane (see .hotel-detail__stickybar padding-inline-end) sized
     for this FAB. Dock the FAB into that lane — its bottom edge 0.5rem above
     the bar's own — instead of floating over the bar's copy or the waitlist
     text. Pages without the bar keep the 4.5rem tabbar clearance above. */
  body:has(.hotel-detail__stickybar) .chatbot-widget {
    bottom: calc(4rem + env(safe-area-inset-bottom, 0px));
  }
}

/* Figma attendee footer — brand left, greeting + copyright centre, legal
   labels right. */
.portal-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 1rem;
  padding: 1rem 1.5rem;
  border-top: 1px solid var(--wa-color-neutral-border-quiet);
  color: var(--wa-color-text-quiet);
  font-size: 0.875rem;
}

.portal-footer__brand {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  color: var(--wa-color-text-normal);
  text-decoration: none;
  font-weight: 600;
}

.portal-footer__meta {
  margin: 0;
}

.portal-footer__legal {
  display: flex;
  gap: 1rem;
  margin: 0;
  color: var(--wa-color-text-link);
  font-weight: 600;
}

/* The fixed chat bubble owns the bottom-right 5rem of the viewport and would
   sit on the legal labels whenever the footer is the page's last element.
   Phones are exempt — the bubble rides above the tab bar there and the
   wrapped footer keeps the legal row left-aligned. */
@media (min-width: 40rem) {
  .portal-footer {
    padding-inline-end: 6rem;
  }
}

/* But the phone tab bar is the fixed element that actually covers the footer:
   it is ~3.5rem + safe-area tall, and the footer sits below #main-content's
   9.5rem chatbot clearance, so the last ~5rem of every page hides under it. */
@media (max-width: 639.98px) {
  .portal-footer {
    padding-bottom: calc(4.5rem + env(safe-area-inset-bottom, 0px));
  }

  /* HMS-367 — on hotel detail the sticky Book bar stacks ABOVE the tabbar
     (bottom: 3.5rem + safe, up to ~7.5rem tall when the stay line wraps), so
     the footer's legal row needs the whole stack's height, not the tabbar's
     alone. Matches the 12rem budget .hotel-detail--sticky gives the page. */
  body:has(.hotel-detail__stickybar) .portal-footer {
    padding-bottom: calc(11.5rem + env(safe-area-inset-bottom, 0px));
  }
}

/* HMS-539 — pin the footer to the bottom on short pages. */
body:has(> .portal-footer) { display: flex; flex-direction: column; min-height: 100vh; min-height: 100dvh; }
body:has(> .portal-footer) > main#main-content { flex: 1; }

/* HMS-558 — the avatar upload row in the profile dropdown. The label is the
   visible control; the file input is visually hidden but keyboard-reachable. */
.portal-header__avatar-form {
  margin: 0;
  margin-bottom: var(--spacing-2, 0.5rem);
}

.portal-header__avatar-label {
  display: flex;
  align-items: center;
  gap: var(--spacing-2, 0.5rem);
  padding: var(--spacing-2, 0.5rem) var(--spacing-3, 0.75rem);
  font-size: var(--font-size-sm, 0.875rem);
  color: var(--color-text, inherit);
  cursor: pointer;
}

.portal-header__avatar-label:hover,
.portal-header__avatar-label:focus-within {
  background: var(--color-surface-hover, rgba(0, 0, 0, 0.04));
}

/* HMS-814 — profile-menu actions: the button_to form wrapper carries no
   spacing of its own, so the gap lives on the avatar form; the signout button
   itself is styled like the label rows so the menu reads as one control list. */
.portal-header__profile-menu .button_to {
  margin: 0;
}

.portal-header__signout {
  display: block;
  width: 100%;
  padding: var(--spacing-2, 0.5rem) var(--spacing-3, 0.75rem);
  background: none;
  border: 0;
  font-size: var(--font-size-sm, 0.875rem);
  color: var(--color-text, inherit);
  text-align: left;
  cursor: pointer;
}

.portal-header__signout:hover,
.portal-header__signout:focus-visible {
  background: var(--color-surface-hover, rgba(0, 0, 0, 0.04));
}

/* HMS-638 — Figma puts the attendee portal on the lowered gray surface so
   white cards read as raised. The portal layout marks <body class="portal">. */
body.portal {
  background: var(--wa-color-surface-lowered);
}

/* HMS-1392 — Figma 576:3733: on phones the brand bar pins to the top so the
   logo and profile photo stay in view while results scroll. The hotel-search
   quickbar stacks directly beneath it at top: 3.25rem — this bar's
   min-height. z 940 sits under the tab bar (950) and the chat bubble (1000),
   and over the pinned toolbar (930) so this bar's own dropdowns keep
   rendering above it. */
@media (max-width: 639.98px) {
  .portal-header {
    position: sticky;
    top: 0;
    z-index: 940;
  }
}
