/**
 * ucbExplain — the reusable hover/focus "?" explainer.
 * =========================================================================
 *
 * A drop-in tooltip for any label, legend or header. Show/hide is pure CSS,
 * so it survives a JS re-render with no wiring, and the trigger is a real
 * <button> so keyboard and touch both reach it.
 *
 * IN-CONTEXT HELP IS THIS, NEVER A `title` ATTRIBUTE (CLAUDE.md convention
 * 14): `title` is unreachable by keyboard and touch, and renders blank on a
 * disabled control.
 *
 * Markup — built by `ucbExplain()` / `ucbExplainNode()` in ucb-explain.js, or
 * written inline by PHP with a unique pop id:
 *
 *   <span class="ucb-explain">
 *     <button type="button" class="ucb-explain__trigger"
 *             aria-label="More info" aria-describedby="POP_ID">?</button>
 *     <span class="ucb-explain__pop" role="tooltip" id="POP_ID">…</span>
 *   </span>
 *
 * PLACEMENT: must sit OUTSIDE any <label> — a <button> inside a label toggles
 * the control it labels. Inside a <legend> is fine (a legend labels nothing
 * clickable). Put ONE on a header or label, never one per row.
 *
 * PORTABILITY: extracted from shows-dashboard.css (2026-08-28) so consumers
 * outside the Shows Dashboard can enqueue the `ucb-explain` handle instead of
 * copying the rules. Every custom property carries a literal fallback, so the
 * component renders correctly on a page that declares none of the dashboard's
 * tokens — that is what makes it portable, so keep the fallbacks.
 *
 * KNOWN INTENTIONAL DIVERGENCE: sales-pulse.css keeps its own scoped copy
 * under `.ucb-sales-pulse` with a larger, accent-coloured trigger (owner
 * request 2026-07-24). That is a deliberate variant, not drift — leave it be.
 */

.ucb-explain {
  position: relative;
  display: inline-flex;
  vertical-align: middle;
}

.ucb-explain__trigger {
  width: 15px;
  height: 15px;
  padding: 0;
  border: 1px solid var(--ucb-border-strong, #767676);
  border-radius: 50%;
  background: #fff;
  color: var(--ucb-gray-500, #71717a);
  font-size: 10px;
  font-weight: 700;
  line-height: 1;
  /* Same inheritance guard as the popup below, for a different reason: a button
     inherits letter-spacing, and letter-spacing puts its gap AFTER the glyph — so
     inside a tracked chip (the scheduled-publish pill runs .4px) the lone "?" is
     pushed off-centre in its 15px circle. */
  letter-spacing: normal;
  text-transform: none;
  cursor: help;
}

.ucb-explain__trigger:focus-visible {
  outline: 2px solid var(--ucb-brand, #8B2025);
  outline-offset: 1px;
}

.ucb-explain__pop {
  /* Typography RESET, not just styling. The explainer is routinely nested inside a
     chip/pill (scheduled-publish pill, student-ID flag), and everything the host sets
     — uppercase, letter-spacing, and worst of all `nowrap`, which blows the note out
     of its 230px box as one long line — otherwise inherits straight into this popup.
     Declared here so each new consumer doesn't have to rediscover it. */
  white-space: normal;
  letter-spacing: normal;
  text-transform: none;
  font-style: normal;
  position: absolute;
  /* Drop below the trigger: the explainer's first use sits on the top row of
     the list, and an upward popup would be clipped by the opaque sticky
     header above. Downward, it harmlessly overlays the rows beneath. */
  top: calc(100% + 8px);
  left: 50%;
  transform: translateX(-50%);
  width: 230px;
  padding: 9px 11px;
  /* 15.9:1 white-on-slate — comfortably past the 4.5:1 body-text threshold. */
  background: #1f2937;
  color: #fff;
  font-size: 12px;
  font-weight: 400;
  line-height: 1.45;
  text-align: left;
  border-radius: 6px;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.22);
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.12s ease;
  /* ⚠ NOT pointer-events:none. WCAG 2.1 SC 1.4.13 requires hover content to be
     HOVERABLE — the pointer must be able to travel onto it (to read a long
     explainer, or select text). With pointer-events:none the popup could not be
     hit-tested at all, so the cursor fell through to whatever sat underneath,
     :hover went false, and the panel vanished as you reached for it. */
  z-index: 200;
}

/* Bridges the 8px gap between the trigger and the panel. Without it the pointer
   crosses dead space on the way down, un-hovering the component mid-journey —
   the same failure as pointer-events:none, just harder to see. */
.ucb-explain__pop::before {
  content: "";
  position: absolute;
  bottom: 100%;
  left: 0;
  right: 0;
  height: 10px;
}

.ucb-explain__pop::after {
  content: "";
  position: absolute;
  bottom: 100%;
  left: 50%;
  margin-left: -5px;
  border: 5px solid transparent;
  border-bottom-color: #1f2937;
}

.ucb-explain:hover .ucb-explain__pop,
.ucb-explain:focus-within .ucb-explain__pop {
  opacity: 1;
  visibility: visible;
}

/* SC 1.4.13 also requires the content be DISMISSIBLE without moving the pointer
   or losing focus — Escape. Set by ucb-explain.js; cleared once the pointer or
   focus leaves, so the explainer works again next time. Declared AFTER the
   :hover/:focus-within rule: identical specificity (0,2,1), so source order is
   what makes it win. */
.ucb-explain.is-dismissed .ucb-explain__pop {
  opacity: 0;
  visibility: hidden;
}

/* The only animation here is the fade-in; honour a reduced-motion request
   without hiding the popup (matching sales-pulse.css's copy). */
@media (prefers-reduced-motion: reduce) {
  .ucb-explain__pop {
    transition: none;
  }
}
