/* ============================================================
   Tsinglan iGEM Wiki — Members showcase cabinet
   --------------------------------------------------------------
   Pairs with:
     - wiki/pages/members.html   (shelf, roster, per-member dialogs)
     - static/js/members.js      (highlight, prev/next, photo fallback)
     - wiki/layout.html          (the "modals" block, outside .bio-canvas)

   Every bottle is inline SVG tinted with two per-member variables:
     --polish-color  the liquid inside the bottle
     --cap-color     the cap
   Everything else follows the shared theme variables, so the cabinet
   re-skins itself with all four nail-polish themes.
   ============================================================ */

/* ============================================================
   The cabinet
   ------------------------------------------------------------
   The cabinet is its own surface, so the shared "bare .row" card
   is muted for this row only (the reveal animation stays).
   ============================================================ */

.site-main #main-content > .members-stage.row {
  background-color: transparent;
  border-radius: 0;
  box-shadow: none;
  padding: 0;
  margin-bottom: 2.1rem;
}

.site-main #main-content > .members-stage.row:hover {
  box-shadow: none;
  transform: none;
}

.members-cabinet {
  position: relative;
  padding: 1.15rem 1.2rem 0;
  border: 3px solid var(--navy);
  border-radius: 0.9rem;
  background-color: var(--cream-light);
  background-image: linear-gradient(180deg, rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0) 42%);
  box-shadow: 12px 12px 0 0 var(--navy);
}

.members-cabinet__head {
  position: relative;
  z-index: 2;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.35rem 1rem;
}

.members-cabinet__title {
  margin: 0;
  font-size: clamp(1.55rem, 3.4vw, 2.3rem);
}

.members-cabinet__meta {
  margin: 0;
  font-family: var(--font-nav);
  font-size: 0.76rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
}

.members-cabinet__hint {
  position: relative;
  z-index: 2;
  margin: 0.3rem 0 0.55rem;
  font-size: 0.92rem;
  color: var(--muted);
}

/* Glass front: a soft diagonal sheen behind the bottles. */
.members-cabinet__glass {
  position: absolute;
  inset: 0;
  z-index: 1;
  border-radius: inherit;
  pointer-events: none;
  background-image: linear-gradient(
    115deg,
    rgba(255, 255, 255, 0.42) 0%,
    rgba(255, 255, 255, 0) 26%,
    rgba(255, 255, 255, 0.16) 48%,
    rgba(255, 255, 255, 0) 64%
  );
}

.members-cabinet__shelves {
  position: relative;
  z-index: 2;
}

/* ============================================================
   Shelves (one board per row of bottles)
   ============================================================ */

.members-shelf {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 0.35rem 0.6rem;
  align-items: end;
  margin: 0;
  padding: 1.15rem 0.75rem 1.5rem;
  list-style: none;
  border-bottom: 10px solid var(--navy);
  box-shadow: inset 0 -16px 20px -16px rgba(31, 66, 107, 0.4);
}

.polish-shelf__item {
  display: flex;
  justify-content: center;
}

/* ============================================================
   One bottle = one member
   ============================================================ */

.polish {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.4rem;
  width: 100%;
  max-width: 6.5rem;
  padding: 0.3rem 0.25rem 0.15rem;
  border: 0;
  border-radius: 0.6rem;
  background-color: transparent;
  cursor: pointer;
}

.polish__stage {
  position: relative;
  display: block;
}

.polish__bottle {
  display: block;
  width: clamp(44px, 5.4vw, 64px);
  height: auto;
  filter: drop-shadow(0 5px 6px rgba(31, 66, 107, 0.26));
  transition: transform 0.25s ease, filter 0.25s ease;
}

/* Pool of light under the bottle; currentColor keeps it theme-aware. */
.polish__glow {
  position: absolute;
  left: 50%;
  bottom: -0.15rem;
  width: 108%;
  height: 0.85rem;
  transform: translateX(-50%);
  border-radius: 50%;
  color: var(--navy);
  background: radial-gradient(ellipse at center, currentColor, transparent 72%);
  opacity: 0.24;
  transition: opacity 0.25s ease;
}

.polish__cap { fill: var(--cap-color, #1f426b); }
.polish__cap-sheen { fill: #ffffff; opacity: 0.32; }
.polish__collar { fill: var(--cap-color, #1f426b); opacity: 0.72; }
.polish__glass { fill: #ffffff; opacity: 0.5; }
.polish__fill { fill: var(--polish-color, #1f426b); }
.polish__shine { fill: #ffffff; opacity: 0.55; }
.polish__shine--soft { opacity: 0.3; }
.polish__glass-sheen { fill: #ffffff; opacity: 0.42; }
.polish__outline {
  fill: none;
  stroke: var(--navy);
  stroke-width: 2.5;
  opacity: 0.9;
}

/* Name plate on the shelf edge: small, always readable, and it doubles as
   the accessible name of the button. */
.polish__plate {
  display: block;
  max-width: 100%;
  padding: 0.1rem 0.45rem;
  border: 1px solid var(--navy);
  border-radius: 0.35rem;
  background-color: var(--cream);
  font-family: var(--font-nav);
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.03em;
  line-height: 1.35;
  color: var(--navy);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  transition: background-color 0.22s ease, color 0.22s ease;
}

.polish:hover .polish__bottle,
.polish:focus-visible .polish__bottle {
  transform: translateY(-7px) rotate(-2.5deg);
  filter: drop-shadow(0 12px 14px rgba(31, 66, 107, 0.34));
}

.polish:hover .polish__glow,
.polish:focus-visible .polish__glow {
  opacity: 0.5;
}

.polish:hover .polish__plate,
.polish:focus-visible .polish__plate {
  background-color: var(--navy);
  color: var(--cream);
}

.polish:focus-visible {
  outline: 2px solid var(--navy);
  outline-offset: 2px;
}

/* Last opened bottle: a colour halo so you can find your place again. */
.polish.is-active .polish__bottle {
  filter: drop-shadow(0 8px 10px rgba(31, 66, 107, 0.34)) drop-shadow(0 0 0.5rem var(--polish-color, #1f426b));
}

.polish.is-active .polish__plate {
  background-color: var(--navy);
  border-color: var(--cap-color, var(--navy));
  color: var(--cream);
}

/* ============================================================
   Full roster — the same people as a plain, keyboard-friendly list
   ============================================================ */

.members-roster {
  display: grid;
  gap: 0.5rem;
  margin: 1.1rem 0 0;
  padding: 0;
  list-style: none;
}

.members-roster__btn {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  width: 100%;
  padding: 0.5rem 0.7rem;
  border: 2px solid var(--navy);
  border-radius: 0.55rem;
  background-color: var(--cream-light);
  text-align: left;
  cursor: pointer;
  box-shadow: 3px 3px 0 0 var(--navy);
  transition: transform 0.22s ease, box-shadow 0.22s ease;
}

.members-roster__btn:hover {
  transform: translate(-1px, -1px);
  box-shadow: 5px 5px 0 0 var(--navy);
}

.members-roster__btn:focus-visible {
  outline: 2px solid var(--navy);
  outline-offset: 2px;
}

.members-roster__index {
  flex: 0 0 auto;
  font-family: var(--font-nav);
  font-size: 0.82rem;
  font-weight: 700;
  color: var(--muted);
}

.members-roster__swatch {
  flex: 0 0 auto;
  width: 1.15rem;
  height: 1.15rem;
  border: 2px solid var(--navy);
  border-radius: 50%;
  background-color: var(--polish-color, var(--navy));
  box-shadow: inset 0 -3px 0 rgba(0, 0, 0, 0.12);
}

.members-roster__text {
  flex: 1 1 auto;
  min-width: 0;
}

.members-roster__name {
  display: block;
  font-weight: 700;
  color: var(--navy);
}

.members-roster__meta {
  display: block;
  font-size: 0.8rem;
  line-height: 1.4;
  color: var(--muted);
}

.members-roster__cue {
  flex: 0 0 auto;
  font-family: var(--font-nav);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--navy);
}

.members-note {
  font-size: 0.9rem;
  color: var(--muted);
}

.members-note code {
  padding: 0.05rem 0.3rem;
  border-radius: 0.25rem;
  background-color: rgba(31, 66, 107, 0.12);
  font-size: 0.85em;
}

/* ============================================================
   Profile card inside a dialog
   ============================================================ */

.member-card__top {
  display: flex;
  align-items: flex-start;
  gap: 1rem;
}

.member-avatar {
  position: relative;
  display: grid;
  place-items: center;
  flex: 0 0 auto;
  width: 5.4rem;
  height: 5.4rem;
  border: 3px solid var(--navy);
  border-radius: 50%;
  background-color: var(--polish-color, var(--navy));
  overflow: hidden;
}

.member-avatar__seal {
  font-family: var(--font-display);
  font-size: 1.9rem;
  font-weight: 700;
  line-height: 1;
  color: #ffffff;
  text-shadow: 0 2px 0 rgba(0, 0, 0, 0.22);
}

.member-avatar__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* members.js adds .is-broken when a portrait fails, revealing the seal. */
.member-avatar.is-broken .member-avatar__img {
  display: none;
}

/* ============================================================
   Picture at the top of a profile
   ------------------------------------------------------------
   Only rendered when that member has a `photo` URL. The frame
   reuses the shared offset-shadow look of the cabinet and the
   dialog; while it shows, the small circular seal avatar steps
   aside, and that seal comes straight back if the picture fails.
   ============================================================ */

.member-portrait {
  /* The frame is as wide as the profile text and as tall as its own picture,
     so a wide group collage and a tall portrait both show uncropped.
     `photo_w` / `photo_h` on each member reserve that space, which is what
     stops the dialog from jumping while the picture loads. */
  width: 100%;
  margin: 0 0 1.15rem;
  border: 3px solid var(--navy);
  border-radius: 0.75rem;
  background-color: rgba(31, 66, 107, 0.12);
  box-shadow: 6px 6px 0 0 var(--navy);
  overflow: hidden;
}

.member-portrait__img {
  display: block;
  width: 100%;
  height: auto;
  /* Safety valve for a very tall upload: it is cropped rather than allowed
     to push the role and the introduction out of the dialog. */
  max-height: 30rem;
  object-fit: cover;
}

/* members.js adds .is-broken when a portrait fails, hiding the whole frame. */
.member-portrait.is-broken {
  display: none;
}

/* The picture replaces the seal: while the hero frame is showing, the small
   circular avatar would only repeat it, so it steps aside. If the picture
   fails the frame is marked broken and the seal comes straight back. */
.member-modal__body:has(.member-portrait:not(.is-broken)) .member-avatar {
  display: none;
}

.member-card__id {
  min-width: 0;
}

.member-card__areas {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem;
  margin: 0.5rem 0 0;
  padding: 0;
  list-style: none;
}

.member-card__area {
  padding: 0.1rem 0.5rem;
  border: 1px solid var(--navy);
  border-radius: 999px;
  background-color: rgba(255, 255, 255, 0.42);
  font-family: var(--font-nav);
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--navy);
}

.member-card__polish {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin: 1.05rem 0 0;
  padding: 0.5rem 0.7rem;
  border: 1px solid var(--navy);
  border-radius: 0.5rem;
  background-color: rgba(255, 255, 255, 0.4);
  font-size: 0.92rem;
}

.member-card__swatch {
  flex: 0 0 auto;
  width: 1.3rem;
  height: 1.3rem;
  border: 2px solid var(--navy);
  border-radius: 50%;
  background-color: var(--polish-color, var(--navy));
  box-shadow: inset 0 -4px 0 rgba(0, 0, 0, 0.14);
}

.member-card__hex {
  font-family: var(--font-nav);
  font-size: 0.78rem;
  letter-spacing: 0.04em;
  color: var(--muted);
}

.member-card__bio {
  margin: 1rem 0 0;
}

.member-card__fact {
  margin: 0.9rem 0 0;
  padding: 0.55rem 0.8rem;
  border-left: 4px solid var(--polish-color, var(--navy));
  background-color: rgba(255, 255, 255, 0.4);
  font-style: italic;
}

.member-card__fact-label {
  display: block;
  font-family: var(--font-nav);
  font-size: 0.68rem;
  font-style: normal;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
}

/* ============================================================
   Person dialogs
   ------------------------------------------------------------
   z-index note: the fixed theme switcher (1080) and the mobile TOC
   drawer (1090) sit above Bootstrap's default modal (1055), so both
   the dialog and its backdrop are lifted past them.
   ============================================================ */

.member-modal {
  z-index: 1095;
  /* html { scroll-behavior: smooth } would animate the focus jump when
     Bootstrap moves focus into the dialog. */
  scroll-behavior: auto;
}

body.page-members .modal-backdrop {
  z-index: 1094;
}

.member-modal .modal-dialog {
  max-width: min(44rem, calc(100vw - 1.6rem));
}

.member-modal .modal-content {
  background-color: var(--cream);
  color: var(--ink);
  border: 3px solid var(--navy);
  border-radius: 0.9rem;
  box-shadow: 12px 12px 0 0 var(--navy);
  overflow: hidden;
}

.member-modal__header {
  position: relative;
  align-items: flex-start;
  gap: 0.75rem;
  padding: 1rem 1.1rem 0.9rem;
  border-bottom: 3px solid var(--navy);
  background-color: var(--navy);
  color: var(--cream);
}

/* The member's own shade tints the dialog bar. */
.member-modal__header::before {
  content: "";
  position: absolute;
  inset: 0;
  background-color: var(--polish-color, transparent);
  opacity: 0.36;
  pointer-events: none;
}

.member-modal__header > * {
  position: relative;
  z-index: 1;
}

.member-modal__name {
  margin: 0;
  font-size: clamp(1.3rem, 3.5vw, 1.7rem);
  font-weight: 700;
  color: var(--cream);
}

.member-modal__bottle {
  margin: 0.15rem 0 0;
  font-family: var(--font-nav);
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--cream);
  opacity: 0.85;
}

.member-modal__close {
  margin: 0.15rem 0 0 auto;
  opacity: 0.85;
}

.member-modal__close:hover,
.member-modal__close:focus-visible {
  opacity: 1;
}

.member-modal__body {
  padding: 1.15rem 1.1rem 1.3rem;
}

.member-modal__footer {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem;
  padding: 0.85rem 1.1rem 1rem;
  border-top: 3px solid var(--navy);
  background-color: rgba(255, 255, 255, 0.32);
}

.member-modal__counter {
  margin: 0;
  font-family: var(--font-nav);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
}

.member-modal__steps {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.member-modal__step {
  max-width: 12rem;
  padding: 0.32rem 0.7rem;
  border: 2px solid var(--navy);
  border-radius: 0.5rem;
  background-color: var(--cream);
  font-family: var(--font-nav);
  font-size: 0.76rem;
  font-weight: 700;
  color: var(--navy);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  cursor: pointer;
  box-shadow: 3px 3px 0 0 var(--navy);
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}

.member-modal__step:hover {
  transform: translate(-1px, -1px);
  box-shadow: 5px 5px 0 0 var(--navy);
}

.member-modal__step:focus-visible {
  outline: 2px solid var(--navy);
  outline-offset: 2px;
}

/* ============================================================
   Responsive
   ============================================================ */

@media (min-width: 768px) {
  .members-roster {
    grid-template-columns: 1fr 1fr;
  }
}

@media (max-width: 991.98px) {
  .members-cabinet {
    padding: 1rem 0.9rem 0;
  }

  .members-shelf {
    padding: 1rem 0.5rem 1.3rem;
  }
}

@media (max-width: 767.98px) {
  .members-stage.row {
    margin-bottom: 1.7rem;
  }

  .members-cabinet {
    padding: 0.85rem 0.7rem 0;
    box-shadow: 8px 8px 0 0 var(--navy);
  }

  .members-shelf {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 0.3rem 0.4rem;
    padding: 0.85rem 0.35rem 1.15rem;
    border-bottom-width: 8px;
  }

  .polish {
    max-width: 5.6rem;
  }

  .polish__bottle {
    width: 44px;
  }

  .polish__plate {
    padding: 0.08rem 0.35rem;
    font-size: 0.62rem;
  }

  .polish__glow {
    height: 0.6rem;
  }

  .member-modal .modal-dialog {
    max-width: none;
    margin: 0.75rem;
  }

  .member-avatar {
    width: 4.4rem;
    height: 4.4rem;
  }

  .member-avatar__seal {
    font-size: 1.55rem;
  }

  .member-modal__footer {
    padding: 0.7rem 0.9rem 0.85rem;
  }

  .members-roster__cue {
    display: none;
  }

  .member-portrait {
    box-shadow: 4px 4px 0 0 var(--navy);
  }
}

@media (max-width: 575.98px) {
  .members-cabinet__meta {
    letter-spacing: 0.05em;
  }

  .members-shelf {
    gap: 0.25rem 0.3rem;
  }

  .member-modal__steps {
    width: 100%;
  }

  .member-modal__step {
    flex: 1 1 auto;
    max-width: none;
    text-align: center;
  }
}

/* ============================================================
   Reduced motion
   ============================================================ */

@media (prefers-reduced-motion: reduce) {
  .polish__bottle,
  .polish__glow,
  .polish__plate,
  .members-roster__btn,
  .member-modal__step {
    transition: none !important;
  }

  .polish:hover .polish__bottle,
  .polish:focus-visible .polish__bottle {
    transform: none;
  }
}
