/* ==========================================================================
   Programs, cover mode
   Markup comes from [uaeedc_programs] in inc/shortcode-programs.php and the
   swap between grid and cover is driven by assets/js/programs.js. Every
   rule is scoped under .u-programs. Tokens only, no raw hex.

   Two deliberate departures from the design prototype: the cover uses a
   flat --u-green-900 background with the campus photo at opacity .35
   beneath the content (no gradient, no wash overlay), and the tile
   placeholder is flat --u-bg-alt with the code mark in --u-green-700.

   Layout: tile grid is 2 columns below 640px, 4 columns from 640px up. The
   cover replaces the grid entirely rather than overlaying it, so it never
   needs its own z-index above the page.
   ========================================================================== */

.u-programs {
  --u-programs-tile-ratio: 4 / 3;
}

/* --- Heading ---------------------------------------------------------------- */

.u-programs__heading {
  margin: 0 0 var(--u-space-8);
}

/* --- Toolbar ------------------------------------------------------------- */

.u-programs__toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--u-space-4);
  margin: 0 0 var(--u-space-8);
}

.u-programs__chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--u-space-2);
}

.u-programs__chip {
  height: 40px;
  padding: 0 var(--u-space-4);
  border: 1px solid var(--u-border);
  border-radius: var(--u-radius-pill);
  background: var(--u-bg);
  color: var(--u-text-muted);
  font-size: var(--u-text-sm);
  font-weight: var(--u-weight-medium);
  cursor: pointer;
  transition:
    background-color var(--u-dur-fast) var(--u-ease),
    border-color var(--u-dur-fast) var(--u-ease),
    color var(--u-dur-fast) var(--u-ease);
}

.u-programs__chip:hover {
  border-color: var(--u-ink-40);
  color: var(--u-text);
}

/* Ink pill, not the brand green: this is a filter control, not a call to
   action, and the green is saved for things the visitor is meant to do. */
.u-programs__chip.is-on {
  background: var(--u-ink);
  border-color: var(--u-ink);
  color: var(--u-white);
}

.u-programs__search {
  display: flex;
  align-items: center;
  gap: var(--u-space-2);
  flex: 1 1 auto;
  min-width: 12rem;
  height: 48px;
  padding: 0 var(--u-space-4);
  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-programs__search: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-programs .u-programs__search input,
.u-programs .u-programs__search input:focus,
.u-programs .u-programs__search input:focus-visible {
  height: auto;
  padding: 0;
  border: 0;
  outline: 0;
  box-shadow: none;
}

.u-programs__search input {
  width: 100%;
  min-width: 0;
  border: 0;
  outline: 0;
  background: transparent;
  font-size: var(--u-text-sm);
  color: var(--u-text);
}

.u-programs__search input::placeholder {
  color: var(--u-ink-40);
}

/* Count and, under it, the date the university 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-programs__status {
  display: flex;
  flex: none;
  flex-direction: column;
  align-items: flex-end;
  gap: 2px;
  margin-left: auto;
  line-height: var(--u-leading-snug);
}

.u-programs__count {
  font-size: var(--u-text-sm);
  color: var(--u-ink-40);
  white-space: nowrap;
}

.u-programs__updated {
  font-size: var(--u-text-xs);
  color: var(--u-ink-40);
  white-space: nowrap;
}

@media (max-width: 40em) {
  .u-programs__status {
    align-items: flex-start;
    margin-left: 0;
  }
}

/* --- Visibility -------------------------------------------------------------
   programs.js toggles the grid, the cover, individual levels and individual
   list items with the hidden attribute. The browser default [hidden] rule
   is display:none, but .u-programs__grid and .u-programs__level each carry
   their own display value (grid, flex) that wins on specificity and would
   otherwise silently override [hidden], leaving the "hidden" element still
   visible. Guarded here as a set so the same mistake cannot recur on a
   sibling element later.
   ------------------------------------------------------------------------- */

.u-programs__grid[hidden],
.u-programs__cover[hidden],
.u-programs__level[hidden],
.u-programs__list li[hidden] {
  display: none;
}

/* --- Grid and tile --------------------------------------------------------- */

.u-programs__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-programs__grid {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: var(--u-space-12) var(--u-space-8);
  }
}

.u-programs__item {
  margin: 0;
  padding: 0;
  min-width: 0;
}

.u-programs__tile {
  display: flex;
  flex-direction: column;
  gap: var(--u-space-3);
  width: 100%;
  padding: 0;
  border: 0;
  background: transparent;
  color: inherit;
  text-align: left;
  cursor: pointer;
  transition: opacity var(--u-dur) var(--u-ease);
}

.u-programs__art {
  position: relative;
  overflow: hidden;
  aspect-ratio: var(--u-programs-tile-ratio);
  border-radius: var(--u-radius);
  background: var(--u-bg-alt);
  transition:
    transform var(--u-dur) var(--u-ease),
    box-shadow var(--u-dur) var(--u-ease);
}

/* Astra paints every button green on hover and focus (button:hover, 0,1,1).
   The tile is a button for keyboard and click semantics only, so its own
   surface stays transparent and the caption keeps its ink colour; the lift
   on the artwork below is the whole hover. */
.u-programs__tile:hover,
.u-programs__tile:focus,
.u-programs__tile:active {
  background: transparent;
  color: inherit;
}

.u-programs__tile:hover .u-programs__art,
.u-programs__tile:focus-visible .u-programs__art {
  transform: translateY(-6px);
  box-shadow: var(--u-shadow-lg);
}

.u-programs .u-programs__art img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Flat mist placeholder, code mark in the pressed green. No gradient. */
.u-programs__code {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-family: var(--u-font-display);
  font-size: var(--u-text-initials);
  font-weight: var(--u-weight-semi);
  letter-spacing: var(--u-tracking-tight);
  color: var(--u-green-700);
}

.u-programs__tile.is-dim {
  opacity: .35;
}

.u-programs__meta {
  display: flex;
  flex-direction: column;
  gap: var(--u-space-1);
}

.u-programs .u-programs__name {
  margin: 0;
  font-family: var(--u-font-body);
  font-size: var(--u-text-base);
  font-weight: var(--u-weight-semi);
  line-height: var(--u-leading-snug);
  color: var(--u-text);
}

.u-programs__label {
  font-size: var(--u-text-2xs);
  color: var(--u-text-muted);
}

/* --- Cover ------------------------------------------------------------------
   The wrapper toggles the hidden attribute; the article inside it is what
   carries the dark surface, so a template with no photo still renders
   correctly with no empty positioned element left behind.
   ------------------------------------------------------------------------- */

.u-programs__cover-inner {
  position: relative;
  /* clip, not hidden: hidden still lets scrollIntoView or focus scroll the
     card's contents out of view; clip only cuts the photo at the corners. */
  overflow: clip;
  display: flex;
  flex-direction: column;
  gap: var(--u-space-12);
  min-height: 640px;
  padding: var(--u-space-12);
  border-radius: var(--u-radius);
  background: var(--u-green-900);
  color: var(--u-text-invert);
  /* Keyboard focus inside the cover: the pale ring, green-900 behind it. */
  --u-focus: var(--u-focus-on-dark);
}

/* The campus photo fills the cover, toned into the green. The title reads
   on it because it is large and bold; the program columns read on it
   because each one carries its own translucent panel (below). Two-class
   selector: Elementor's ".elementor img { height: auto }" would otherwise
   win and stop the photo partway down the card. */
.u-programs .u-programs__cover-photo {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: .4;
  z-index: 0;
}

.u-programs__cover-mark {
  position: absolute;
  right: -16px;
  bottom: -60px;
  z-index: 0;
  font-family: var(--u-font-display);
  font-size: var(--u-text-mark);
  font-weight: var(--u-weight-semi);
  line-height: 1;
  letter-spacing: -0.05em;
  color: var(--u-white-06);
  pointer-events: none;
  user-select: none;
}

.u-programs__cover-head,
.u-programs__cover-title,
.u-programs__levels {
  position: relative;
  z-index: 1;
}

.u-programs__cover-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--u-space-4);
}

.u-programs__cover-steps {
  display: flex;
  gap: var(--u-space-2);
}

.u-programs__nav {
  display: inline-flex;
  align-items: center;
  gap: var(--u-space-2);
  height: 40px;
  padding: 0 var(--u-space-4);
  border: 1px solid var(--u-white-30);
  border-radius: var(--u-radius-pill);
  background: transparent;
  color: var(--u-text-invert);
  font-size: var(--u-text-sm);
  font-weight: var(--u-weight-medium);
  cursor: pointer;
  transition:
    background-color var(--u-dur-fast) var(--u-ease),
    color var(--u-dur-fast) var(--u-ease),
    border-color var(--u-dur-fast) var(--u-ease);
}

.u-programs__nav:hover {
  background: var(--u-text-invert);
  border-color: var(--u-text-invert);
  color: var(--u-green-900);
}

.u-programs__cover-title {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--u-space-3);
}

/* Only the heading keeps a short measure; the links row below it takes the
   whole cover, so pills sit side by side whenever they fit. */
.u-programs__cover-title h3 {
  margin: 0;
  max-width: 60%;
  font-family: var(--u-font-body);
  font-size: var(--u-text-h2);
  color: var(--u-text-invert);
}

.u-programs__cover-count {
  font-size: var(--u-text-sm);
  color: var(--u-white-72);
}

/* Links out of the site: the university, then the college or school whose
   dean sits on the council (two where two deans do). Pills in the cover's
   own nav language, lightly filled so they read as links rather than the
   panel's controls, with an arrow because they leave the site. Client, 28
   August 2026. */
.u-programs__links {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--u-space-2);
  width: 100%;
}

.u-programs__links-label {
  margin-right: var(--u-space-1);
  font-size: var(--u-text-xs);
  font-weight: var(--u-weight-medium);
  letter-spacing: var(--u-tracking-wide);
  text-transform: uppercase;
  color: var(--u-white-72);
}

.u-programs__link {
  display: inline-flex;
  align-items: center;
  gap: var(--u-space-2);
  min-height: 36px;
  padding: var(--u-space-1) var(--u-space-4);
  border: 1px solid var(--u-white-30);
  border-radius: var(--u-radius-pill);
  background: var(--u-white-10);
  color: var(--u-text-invert);
  font-size: var(--u-text-sm);
  font-weight: var(--u-weight-medium);
  line-height: var(--u-leading-snug);
  text-decoration: none;
  transition:
    background-color var(--u-dur-fast) var(--u-ease),
    color var(--u-dur-fast) var(--u-ease),
    border-color var(--u-dur-fast) var(--u-ease);
}

.u-programs__link:hover {
  background: var(--u-text-invert);
  border-color: var(--u-text-invert);
  color: var(--u-green-900);
}

.u-programs__link-arrow {
  flex: none;
  opacity: .8;
}

/* A pill never breaks its own text: when the row is full the whole pill
   moves to the next line. Phones are the exception, where a long college
   name would otherwise overflow the cover. Client, 28 August 2026. */
@media (min-width: 40em) {
  .u-programs__link {
    white-space: nowrap;
  }
}

.u-programs__levels {
  display: grid;
  /* min() lets a column shrink below 240px when the panel itself is
     narrower, as it is at 360px inside the page gutters; without it the
     grid overflows and the panel's overflow: hidden clips the list. */
  grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr));
  gap: var(--u-space-8);
  /* Panels hug their lists; a two-line doctoral column should not become
     a slab as tall as a fifteen-line bachelor one. */
  align-items: start;
}

/* Each column sits on a faint green panel so its text has one consistent
   surface whatever part of the photo is behind it. The blur keeps the
   photo readable as a photo through the panel rather than as noise. */
.u-programs__level {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--u-space-3);
  padding: var(--u-space-6);
  border-radius: var(--u-radius);
  background: var(--u-scrim);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
}

.u-programs__level-name {
  margin: 0;
  padding-bottom: var(--u-space-2);
  border-bottom: 1px solid var(--u-white-20);
  font-family: var(--u-font-body);
  font-size: var(--u-text-xs);
  font-weight: var(--u-weight-semi);
  letter-spacing: var(--u-tracking-wide);
  text-transform: uppercase;
  color: var(--u-white-80);
}

/* Sits above the name's bottom border as a small count badge, since the
   markup keeps the name and the count as separate elements. */
.u-programs__level-count {
  position: absolute;
  top: var(--u-space-6);
  right: var(--u-space-6);
  font-size: var(--u-text-xs);
  font-weight: var(--u-weight-semi);
  color: var(--u-white-80);
}

.u-programs__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--u-space-2);
}

.u-programs__list li {
  font-size: var(--u-text-2xs);
  line-height: var(--u-leading-snug);
  color: var(--u-white-92);
}

/* Narrow screens: tighter padding on the cover and the column panels, and
   the title takes the full width. */
@media (max-width: 40em) {
  .u-programs__cover-inner {
    gap: var(--u-space-8);
    min-height: 0;
    padding: var(--u-space-6);
  }

  .u-programs__level {
    padding: var(--u-space-4);
  }

  .u-programs__level-count {
    top: var(--u-space-4);
    right: var(--u-space-4);
  }
}

/* --- Motion ------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  .u-programs__chip,
  .u-programs__search,
  .u-programs__tile,
  .u-programs__art,
  .u-programs__nav,
  .u-programs__link {
    transition: none;
  }
}

/* --- Touch ---------------------------------------------------------------
   Hover-capable pointers keep the compact 40px chips and nav buttons from
   the design; a touch pointer cannot hover, so it gets the full 44px
   target instead.
   ------------------------------------------------------------------------- */

@media (hover: none) {
  .u-programs__tile {
    min-height: 44px;
  }

  .u-programs__chip,
  .u-programs__nav {
    height: 44px;
  }

  .u-programs__link {
    min-height: 44px;
  }
}
