/* ==========================================================================
   Council member directory
   Markup comes from [uaeedc_members] in inc/shortcode-members.php. The
   Chair is named in words on their grid card; the separate Chair cover
   card was removed on 27 August 2026 at the client's request. Filtering
   behaviour (search, university select) is driven by assets/js/filter.js,
   generic and shared with other blocks; this file only supplies the
   [hidden] guard and the toolbar look. Every rule is scoped under
   .u-members. Tokens only, no raw hex.

   Layout: 2 columns from 360px, then auto-fill columns of at least 260px,
   which gives 4 across inside the 1200px container. Photos are forced to a
   4:5 portrait box with object-fit so the mismatched source images on the
   current site all land at the same size.
   ========================================================================== */

.u-members {
  --u-members-photo-ratio: 4 / 5;
  --u-members-min-col: 260px;
}

/* --- Heading --------------------------------------------------------------- */

.u-members__heading {
  margin: 0 0 var(--u-space-8);
}

/* --- Toolbar -----------------------------------------------------------
   Plain row, wraps under 640px. A sticky toolbar under Astra's header is
   not attempted, since the header's own height is not ours to depend on.
   ------------------------------------------------------------------------- */

.u-members__toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--u-space-4);
  margin: 0 0 var(--u-space-8);
}

.u-members__search,
.u-members__select {
  display: flex;
  align-items: center;
  height: 48px;
  border: 1px solid var(--u-border);
  border-radius: var(--u-radius-sm);
  background: var(--u-bg);
  transition: border-color var(--u-dur-fast) var(--u-ease);
}

.u-members__search {
  flex: 1 1 auto;
  min-width: 12rem;
  padding: 0 var(--u-space-4);
}

.u-members__search input {
  width: 100%;
  min-width: 0;
  border: 0;
  outline: 0;
  background: transparent;
  font-size: var(--u-text-sm);
  color: var(--u-text);
}

.u-members__search input::placeholder {
  color: var(--u-ink-40);
}

/* Its own full-width row below 640px. The longest option, "Manipal Academy
   of Higher Education Dubai", gives the select an intrinsic width near
   347px, and at flex: none the label was sized to it, so the toolbar
   overflowed a 360px viewport. A 100% flex-basis drops the label onto its
   own line and min-width: 0 lets it shrink under that intrinsic width
   instead of pushing the row wider. */
.u-members__select {
  flex: 1 1 100%;
  max-width: 100%;
  min-width: 0;
}

.u-members__select select {
  width: 100%;
  min-width: 0;
  height: 100%;
  padding: 0 var(--u-space-4);
  border: 0;
  outline: 0;
  background: transparent;
  font-size: var(--u-text-sm);
  color: var(--u-text);
  cursor: pointer;
}

/* From 640px the row is wide enough for a shrink-to-fit control again, so
   the select sits beside the search field at its natural width. */
@media (min-width: 40em) {
  .u-members__select {
    flex: none;
    max-width: none;
  }

  .u-members__select select {
    width: auto;
  }
}

.u-members__search:focus-within,
.u-members__select:focus-within {
  /* The same green ring as keyboard focus, on the field's wrapper so the
     select and the search read as one control while being used. */
  outline: 3px solid var(--u-focus);
  outline-offset: 3px;
}

/* Astra styles input[type="search"]:focus and select:focus at (0,2,1) with
   its own padding, shadow and a dotted border, which drew a second box
   inside ours on click. Three-class specificity keeps the inner control
   bare in every state; the wrapper is the one visible box and carries the
   site's focus ring on :focus-within. */
.u-members .u-members__search input,
.u-members .u-members__search input:focus,
.u-members .u-members__search input:focus-visible {
  height: auto;
  padding: 0;
  border: 0;
  outline: 0;
  box-shadow: none;
}

.u-members .u-members__select select,
.u-members .u-members__select select:focus,
.u-members .u-members__select select:focus-visible {
  border: 0;
  outline: 0;
  box-shadow: none;
}

/* Count and, under it, the date the directory's records last changed
   (inc/helpers.php uaeedc_last_updated). Stacked and right-aligned on
   desktop; on phones the toolbar wraps and they sit at the left. */
.u-members__status {
  display: flex;
  flex: none;
  flex-direction: column;
  align-items: flex-end;
  gap: 2px;
  margin-left: auto;
  line-height: var(--u-leading-snug);
}

.u-members__count {
  font-size: var(--u-text-sm);
  color: var(--u-ink-40);
  white-space: nowrap;
}

.u-members__updated {
  font-size: var(--u-text-xs);
  color: var(--u-ink-40);
  white-space: nowrap;
}

@media (max-width: 40em) {
  .u-members__status {
    align-items: flex-start;
    margin-left: 0;
  }
}

/* --- Visibility ----------------------------------------------------------
   filter.js toggles matched items and the empty-state message with the
   hidden attribute. .u-members__item is a grid child, so its own display
   value (implicit "list-item" cleared to nothing by the grid) would not
   reliably win over [hidden] without this rule; programs.css hit exactly
   this bug first, so it is guarded here from the start.
   ------------------------------------------------------------------------- */

.u-members__item[hidden],
.u-members__empty[hidden] {
  display: none;
}

.u-members__empty {
  margin: var(--u-space-8) 0 0;
  color: var(--u-text-muted);
}

/* --- Grid ------------------------------------------------------------------ */

.u-members__grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--u-space-8) var(--u-space-4);
}

@media (min-width: 40em) {
  .u-members__grid {
    grid-template-columns: repeat(auto-fill, minmax(min(100%, var(--u-members-min-col)), 1fr));
    gap: var(--u-space-12) var(--u-space-6);
  }
}

.u-members__item {
  min-width: 0;   /* let long emails wrap instead of stretching the column */
  margin: 0;
  padding: 0;
}

/* --- Photo ----------------------------------------------------------------- */

.u-members__photo {
  position: relative;
  aspect-ratio: var(--u-members-photo-ratio);
  width: 100%;
  margin: 0 0 var(--u-space-4);
  overflow: hidden;
  border-radius: var(--u-radius);
  background-color: var(--u-bg-alt);
  transition:
    transform var(--u-dur) var(--u-ease),
    box-shadow var(--u-dur) var(--u-ease);
}

/* Descendant selector on purpose: Astra and Elementor both set img height
   to auto at the same specificity as a single class, and the cover crop
   depends on the image filling the box. */
.u-members .u-members__photo img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center top;   /* keep faces, crop shoulders */
}

/* No photo yet: initials on the mist surface, same box so the grid holds. */
.u-members__photo--empty {
  display: grid;
  place-items: center;
}

.u-members__initials {
  font-family: var(--u-font-display);
  font-size: var(--u-text-h2);
  line-height: 1;
  color: var(--u-ink-40);
  user-select: none;
}

/* Chair pill, solid green, never a tint: this is a status mark, not a
   decorative surface. */

/* Hover and keyboard focus (an icon link inside the card) both lift the
   photo and colour the name, since the card itself carries no link. */
.u-members__item:hover .u-members__photo,
.u-members__item:focus-within .u-members__photo {
  transform: translateY(-6px);
  box-shadow: var(--u-shadow-lg);
}

.u-members__item:hover .u-members__name,
.u-members__item:focus-within .u-members__name {
  color: var(--u-accent);
}

/* --- Body and text ----------------------------------------------------------
   A stacked column: the name/university/position text runs the full card
   width, matching the photo, and the icon buttons (email, profile,
   LinkedIn) sit in a row beneath it. Changed from a side-by-side row on
   31 August 2026 at the client's request: the text was being squeezed
   against the icons instead of filling the photo's width.
   ------------------------------------------------------------------------- */

.u-members__body {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: var(--u-space-3);
}

.u-members__text {
  min-width: 0;   /* let long text wrap inside the column */
}

/* Name stays in the body face. Twenty serif display headings in one grid is
   too much weight; the section h2 carries the display role. */
.u-members .u-members__name {
  font-family: var(--u-font-body);
  font-size: var(--u-text-base);
  font-weight: var(--u-weight-semi);
  line-height: var(--u-leading-snug);
  letter-spacing: 0;
  color: var(--u-text);
  margin: 0 0 var(--u-space-1);
  transition: color var(--u-dur-fast) var(--u-ease);
}

.u-members__position,
.u-members__university {
  font-size: var(--u-text-2xs);
  line-height: var(--u-leading-snug);
  margin: 0;
  max-width: none;   /* base.css caps p width for prose, not for cards */
}

.u-members__university {
  color: var(--u-text);
}

.u-members__position {
  color: var(--u-text-muted);
  margin-top: var(--u-space-1);
}

/* The Chair is named in words under the name, not badged on the photo. */
.u-members__chair {
  margin: var(--u-space-1) 0 0;
  max-width: none;
  font-size: var(--u-text-2xs);
  font-weight: var(--u-weight-medium);
  line-height: var(--u-leading-snug);
  color: var(--u-green-700);
}

/* --- Icons -------------------------------------------------------------
   Email, profile and LinkedIn links, icon only, in a row under the text.
   aria-label names each one with the member ("Email Dr. ..."); title keeps
   the short pointer tooltip. A member without a LinkedIn address simply
   has no LinkedIn button.
   ------------------------------------------------------------------------- */

.u-members__icons {
  display: flex;
  flex: none;
  gap: var(--u-space-2);
}

.u-members .u-members__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border: 1px solid var(--u-border);
  border-radius: var(--u-radius-sm);
  color: var(--u-text-muted);
  transition:
    border-color var(--u-dur-fast) var(--u-ease),
    color var(--u-dur-fast) var(--u-ease);
}

.u-members .u-members__icon:hover {
  border-color: var(--u-accent);
  color: var(--u-accent);
}

.u-members .u-members__icon:focus-visible {
  outline: 3px solid var(--u-focus);
  outline-offset: 3px;
  border-radius: var(--u-radius-sm);
}

/* --- Touch ---------------------------------------------------------------
   A touch pointer cannot hover, so the compact 36px icon button grows to
   the full 44px target instead of relying on visual size alone.
   ------------------------------------------------------------------------- */

@media (hover: none) {
  .u-members .u-members__icon {
    width: 44px;
    height: 44px;
  }
}

/* --- Motion ---------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  .u-members__search,
  .u-members__select,
  .u-members__photo,
  .u-members .u-members__name,
  .u-members .u-members__icon {
    transition: none;
  }
}
