/* ==========================================================================
   Opportunities board.

   A timeline, not a card grid: the page's job is to answer "what is new
   since I last looked", so the time-group headings do the heavy lifting and
   the cards stay quiet. Same tokens as the rest of the site.
   ========================================================================== */

/* --- live status chip ------------------------------------------------------ */
.opp__status {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  margin-top: var(--space-5);
  padding: 0.45rem 0.9rem 0.45rem 0.75rem;
  border: 1px solid var(--border);
  border-radius: var(--r-full);
  background: var(--bg-elevated);
  font-size: var(--step--2);
  font-weight: 500;
  color: var(--text-muted);
}
.opp__dot {
  width: 8px; height: 8px;
  border-radius: var(--r-full);
  background: var(--ink-400);
  flex-shrink: 0;
}
.opp__status[data-state="live"] .opp__dot { background: var(--brand-600); }
.opp__status[data-state="error"] .opp__dot { background: #B4231F; }
@media (prefers-reduced-motion: no-preference) {
  .opp__status[data-state="live"] .opp__dot { animation: opp-pulse 2.4s ease-in-out infinite; }
}
@keyframes opp-pulse {
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--brand-600) 55%, transparent); }
  60%      { box-shadow: 0 0 0 6px transparent; }
}

/* --- controls -------------------------------------------------------------- */
.opp__controls {
  display: grid;
  gap: var(--space-4);
  padding: var(--space-5);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--bg-sunken);
}
.opp__controls[hidden] { display: none; }
/* Grid items default to min-width:auto, so the no-wrap chip row below would
   stretch the whole panel past the viewport on a narrow screen instead of
   scrolling inside itself. */
.opp__controls > * { min-width: 0; }

.opp__search {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: 0 var(--space-4);
  min-height: 48px;
  border: 1.5px solid var(--border);
  border-radius: var(--r-sm);
  background: var(--bg-elevated);
  transition: border-color var(--dur-fast) var(--ease-out),
              box-shadow var(--dur-fast) var(--ease-out);
}
.opp__search:focus-within {
  border-color: var(--brand-600);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand-600) 20%, transparent);
}
.opp__search svg { width: 19px; height: 19px; color: var(--ink-400); flex-shrink: 0; }
.opp__search input {
  flex: 1;
  min-width: 0;
  border: 0;
  background: transparent;
  color: var(--text);
  font-size: var(--step--1);
  padding: 0.6rem 0;
}
.opp__search input:focus-visible { outline: none; }
.opp__search input::placeholder { color: var(--ink-400); opacity: 1; }
.opp__search input::-webkit-search-cancel-button { cursor: pointer; }

.opp__filters { display: flex; flex-wrap: wrap; gap: var(--space-4); }
.opp__group { display: flex; flex-wrap: wrap; gap: var(--space-2); }

.opp__chip {
  padding: 0.42rem 0.85rem;
  min-height: 34px;
  border: 1px solid var(--border);
  border-radius: var(--r-full);
  background: var(--bg-elevated);
  color: var(--text-muted);
  font-size: var(--step--2);
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
  transition: background var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out),
              transform var(--dur-fast) var(--ease-out);
}
.opp__chip:hover { color: var(--text); border-color: var(--ink-400); transform: translateY(-1px); }
.opp__chip[aria-pressed="true"] {
  background: var(--brand-solid);
  border-color: var(--brand-solid);
  color: #fff;
}

.opp__count {
  font-size: var(--step--2);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--accent-text);
}

/* --- time groups ----------------------------------------------------------- */
.opp__group-block + .opp__group-block { margin-top: var(--space-8); }

.opp__group-head {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  margin-bottom: var(--space-5);
  padding-bottom: var(--space-3);
  border-bottom: 2px solid var(--border);
  font-size: var(--step-1);
  font-weight: 700;
  letter-spacing: var(--tracking-flat);
  color: var(--text);
}
/* the newest band is the one people came for */
.opp__group-block:first-child .opp__group-head {
  border-bottom-color: var(--gold-500);
  color: var(--accent-text);
}
.opp__group-head > span:first-child { flex: 1; min-width: 0; }
.opp__group-n {
  flex-shrink: 0;
  min-width: 28px;
  padding: 0.1rem 0.5rem;
  border-radius: var(--r-full);
  background: var(--bg-sunken);
  border: 1px solid var(--border);
  font-size: var(--step--2);
  font-weight: 700;
  text-align: center;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}

.opp__cards { display: grid; gap: var(--space-4); }

/* --- card ------------------------------------------------------------------ */
.opp__card {
  position: relative;
  padding: var(--space-5) var(--space-5) var(--space-4);
  border: 1px solid var(--border);
  border-left: 3px solid var(--border);
  border-radius: var(--r-md);
  background: var(--bg-elevated);
  transition: border-left-color var(--dur) var(--ease-out),
              transform var(--dur) var(--ease-out),
              box-shadow var(--dur) var(--ease-out);
}
.opp__card:hover {
  border-left-color: var(--gold-500);
  transform: translateY(-2px);
  box-shadow: var(--shadow-md);
}

.opp__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-3);
  margin-bottom: var(--space-3);
  font-size: var(--step--2);
}
.opp__type {
  padding: 0.2rem 0.55rem;
  border-radius: var(--r-sm);
  font-weight: 700;
  letter-spacing: 0.02em;
  background: var(--brand-50);
  color: var(--brand-800);
}
.opp__type--tender     { background: var(--gold-100); color: var(--gold-700); }
.opp__type--fellowship { background: #E7EEF9; color: #1F3F7A; }
.opp__type--challenge  { background: #F7E9F1; color: #7A2050; }
@media (prefers-color-scheme: dark) {
  .opp__type            { background: var(--brand-100); color: var(--brand-500); }
  .opp__type--tender    { background: rgba(245,179,53,.16); color: var(--gold-400); }
  .opp__type--fellowship{ background: rgba(120,160,230,.16); color: #A9C4EE; }
  .opp__type--challenge { background: rgba(200,120,170,.16); color: #E4A8C8; }
}
.opp__region {
  font-weight: 600;
  color: var(--text-muted);
}
.opp__region::before { content: ""; }
.opp__source {
  color: var(--text-muted);
  font-weight: 500;
}
.opp__source::before { content: "\2022"; margin-right: var(--space-3); color: var(--border); }

.opp__title {
  font-size: var(--step-1);
  font-weight: 700;
  line-height: var(--lh-snug);
  letter-spacing: var(--tracking-flat);
  margin-bottom: var(--space-3);
}
.opp__title a {
  color: var(--text);
  text-decoration: none;
  background-image: linear-gradient(var(--gold-500), var(--gold-500));
  background-size: 0% 2px;
  background-repeat: no-repeat;
  background-position: 0 100%;
  transition: background-size var(--dur) var(--ease), color var(--dur-fast) var(--ease-out);
}
.opp__title a:hover { color: var(--brand-700); background-size: 100% 2px; }
/* the whole card is the hit area, the link is what is announced */
.opp__title a::after { content: ""; position: absolute; inset: 0; }

.opp__summary {
  font-size: var(--step--1);
  line-height: var(--lh-relaxed);
  color: var(--text-muted);
  max-width: 78ch;
  margin-bottom: var(--space-4);
}

.opp__foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-4);
  font-size: var(--step--2);
}
.opp__time { color: var(--text-muted); font-variant-numeric: tabular-nums; }
.opp__ago { color: var(--ink-400); }

.opp__deadline {
  padding: 0.18rem 0.55rem;
  border-radius: var(--r-sm);
  border: 1px solid var(--border);
  font-weight: 600;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}
.opp__deadline.is-urgent {
  background: #FDECEA;
  border-color: #F3B4AF;
  color: #8E1B17;
}
@media (prefers-color-scheme: dark) {
  .opp__deadline.is-urgent { background: #3A1614; border-color: #7A2A25; color: #FFB4AC; }
}

/* --- empty and loading ----------------------------------------------------- */
.opp__empty {
  padding: var(--space-9) var(--space-5);
  text-align: center;
  border: 1px dashed var(--border);
  border-radius: var(--r-md);
  background: var(--bg-sunken);
}
.opp__empty h2 { font-size: var(--step-2); margin-bottom: var(--space-3); }
.opp__empty p {
  color: var(--text-muted);
  max-width: 52ch;
  margin: 0 auto var(--space-5);
  line-height: var(--lh-relaxed);
}

.opp__skeleton { display: grid; gap: var(--space-4); }
.opp__sk-head { height: 28px; width: 200px; border-radius: var(--r-sm); }
.opp__sk-card { height: 132px; border-radius: var(--r-md); }
.opp__sk-head, .opp__sk-card {
  background: linear-gradient(90deg, var(--bg-sunken) 0%, var(--line-soft) 50%, var(--bg-sunken) 100%);
  background-size: 200% 100%;
}
@media (prefers-reduced-motion: no-preference) {
  .opp__sk-head, .opp__sk-card { animation: opp-shimmer 1.5s ease-in-out infinite; }
}
@keyframes opp-shimmer {
  from { background-position: 200% 0; }
  to   { background-position: -200% 0; }
}

/* --- small screens --------------------------------------------------------- */
@media (max-width: 620px) {
  .opp__controls { padding: var(--space-4); }
  .opp__filters { gap: var(--space-3); }
  .opp__filters { display: block; }
  .opp__filters > .opp__group + .opp__group { margin-top: var(--space-3); }
  .opp__group {
    flex-wrap: nowrap;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scrollbar-width: none;
    /* bleed to the panel edge so a half-visible chip signals "scroll me" */
    margin-inline: calc(var(--space-4) * -1);
    padding-inline: var(--space-4);
  }
  .opp__group::-webkit-scrollbar { display: none; }
  .opp__card { padding: var(--space-4); }
  .opp__title { font-size: var(--step-0); }
  .opp__group-head { font-size: var(--step-0); }
  .opp__foot { gap: var(--space-2); }
}

/* ==========================================================================
   Newsletter signup.

   Sits between the feed and the closing CTA: the reader has just finished
   the list, and the offer is to be told about the next one without coming
   back. Kept visually distinct from the cards above and the photo CTA below
   so it does not read as a third variation of the same block.
   ========================================================================== */

.news {
  display: grid;
  gap: var(--space-7);
  align-items: start;
  padding: var(--space-7);
  border: 1px solid var(--border);
  border-top: 3px solid var(--gold-500);
  border-radius: var(--r-md);
  background: var(--bg-sunken);
}
@media (min-width: 900px) {
  .news {
    grid-template-columns: 1.15fr 1fr;
    gap: var(--space-9);
    padding: var(--space-8);
    /* the copy column is the taller of the two; centring the panel against
       it reads better than leaving it stranded at the top */
    align-items: center;
  }
}

.news__eyebrow {
  font-size: var(--step--2);
  font-weight: 700;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--accent-text);
  margin-bottom: var(--space-3);
}
.news__title {
  font-size: var(--step-3);
  font-weight: 700;
  line-height: var(--lh-snug);
  letter-spacing: var(--tracking-tight);
  margin-bottom: var(--space-4);
}
.news__lede {
  font-size: var(--step--1);
  line-height: var(--lh-relaxed);
  color: var(--text-muted);
  max-width: 52ch;
  margin-bottom: var(--space-5);
}

.news__points {
  list-style: none;
  display: grid;
  gap: var(--space-3);
  font-size: var(--step--1);
  line-height: var(--lh-normal);
  color: var(--text-muted);
  max-width: 52ch;
}
.news__points li {
  position: relative;
  padding-left: var(--space-6);
}
/* a tick drawn in CSS rather than an icon file: two borders and a rotation */
.news__points li::before {
  content: "";
  position: absolute;
  left: 2px;
  top: 0.35em;
  width: 6px;
  height: 11px;
  border: solid var(--brand-600);
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}
.news__points strong { color: var(--text); font-weight: 600; }

/* --- the form ------------------------------------------------------------ */
.news__panel {
  padding: var(--space-6);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: var(--bg-elevated);
}

.news__label {
  display: block;
  font-size: var(--step--2);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-muted);
  margin-bottom: var(--space-2);
}

.news__input {
  width: 100%;
  min-height: 50px;
  padding: 0.75rem var(--space-4);
  border: 1.5px solid var(--border);
  border-radius: var(--r-sm);
  background: var(--bg);
  color: var(--text);
  font: inherit;
  font-size: var(--step--1);
  transition: border-color var(--dur-fast) var(--ease-out),
              box-shadow var(--dur-fast) var(--ease-out);
}
.news__input::placeholder { color: var(--ink-400); opacity: 1; }
.news__input:focus-visible {
  outline: none;
  border-color: var(--brand-600);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand-600) 20%, transparent);
}
.news__input[aria-invalid="true"] { border-color: #B4231F; }

.news__error {
  display: block;
  margin-top: var(--space-2);
  font-size: var(--step--2);
  font-weight: 600;
  color: #8E1B17;
}
.news__error[hidden] { display: none; }
@media (prefers-color-scheme: dark) {
  .news__error { color: #FFB4AC; }
}

.news__submit { width: 100%; margin-top: var(--space-4); }

.news__hint {
  margin-top: var(--space-4);
  font-size: var(--step--2);
  line-height: var(--lh-normal);
  color: var(--ink-400);
}

/* the shared .form-status block already carries the success and error
   treatments; this only places it in the panel */
.news__status { margin-top: var(--space-4); }

@media (max-width: 620px) {
  .news { padding: var(--space-5); gap: var(--space-6); }
  .news__panel { padding: var(--space-5); }
  .news__title { font-size: var(--step-2); }
}
