/* ============================================================
   Curiosity Current — Speaker Panel (shared)
   ------------------------------------------------------------
   Single source of truth for the slideover that renders a
   guest's identity, sector, optional topic-framing + top
   claim, episode card, axis-positions (Constellation only),
   "also-in" episode grid (Constellation only), and the
   Resonance Map CTA.

   Used by:
     - curiosity-current/Topic-Timeline/topic-template.html (What portal)
     - curiosity-current/prototypes/constellation.html       (Who portal)

   Visual donor: topic-template.html. Constellation-specific
   sections (axis-positions, also-in) are rendered in the same
   visual language (frosted glass, rounded chips, family-color
   accents).

   Per spec 12_portal_architecture.md v0.1.1, "Shared UI primitives".
   ============================================================ */

/* The panel inherits --family-color from the calling page's :root.
   Constellation has no per-context family color, so it falls back to
   the donor's default violet. Calling pages can override per-open via
   panel.style.setProperty('--family-color', hex). */

/* Overlay is fully transparent and never captures pointer events — main page
   content stays interactive while the panel is open. Click-outside-to-close
   is handled by a document-level listener in speaker-panel.js. */
.sp-overlay {
  position: fixed;
  inset: 0;
  z-index: 100;
  background: transparent;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s ease-in;
}
.sp-overlay.visible {
  opacity: 1;
  pointer-events: none;
  transition: opacity 0.25s ease-out;
}

.sp-panel {
  position: fixed;
  top: 0;
  right: 0;
  height: 100vh;
  width: 380px;
  max-width: 90vw;
  background: rgba(37, 37, 45, 1.0);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  border-left: 4px solid var(--sp-family-color, var(--family-color, #8b5cf6));
  box-shadow: -8px 0 40px rgba(0, 0, 0, 0.5);
  transform: translateX(100%);
  transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  overflow-y: auto;
  z-index: 101;
  padding: 28px 28px 60px;
  color: #e6e8ee;
  font-family: 'Merriweather Sans', -apple-system, BlinkMacSystemFont, "Segoe UI", "Inter", Roboto, sans-serif;
  font-weight: 500;
  font-size: 14px;
  line-height: 1.5;
}
.sp-panel.visible { transform: translateX(0); }
/* The panel is programmatically focused on open (a11y) — suppress the browser's
   default focus ring on the container, which otherwise paints a stray blue line
   along its top/left edges. Interactive controls inside keep their focus rings. */
.sp-panel:focus { outline: none; }

.sp-panel[hidden],
.sp-overlay[hidden],
.sp-section[hidden],
.sp-thumb[hidden],
.sp-secondary[hidden],
.sp-sector[hidden],
.sp-linkedin[hidden] { display: none !important; }

.sp-close {
  position: absolute;
  top: 18px;
  right: 18px;
  width: 32px;
  height: 32px;
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.05);
  color: #9aa0ad;
  border-radius: 0.5rem;
  cursor: pointer;
  font-size: 16px;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: color 0.15s ease, background 0.15s ease, border-color 0.15s ease;
  z-index: 2;
  padding: 0;
}
.sp-close:hover {
  background: rgba(255, 255, 255, 0.1);
  color: #fff;
  border-color: rgba(255, 255, 255, 0.18);
}
.sp-close svg {
  width: 14px;
  height: 14px;
  stroke: currentColor;
  stroke-width: 2;
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* ----- Identity (avatar + name + role/org + linkedin) -----
   Header content (avatar + name + role/org) is rendered by the shared
   guest-card module — see /curiosity-current/shared/guest-card.{js,css} and
   spec 12_portal_architecture.md "Guest card → Per-page usage → Speaker
   panel header". The `.sp-identity-card` selector below applies panel-only
   spacing tweaks; the visual treatment (avatar size, type scale) lives in
   the shared module. */
.sp-identity-card {
  margin: 0 0 14px;
}

/* LinkedIn affordance — the entire role/org line is a single <a> link to
   the speaker's LinkedIn profile (per the speaker panel spec — see
   12_portal_architecture.md "identity" section). Layout:

     <div class="gc-role sp-role-with-linkedin">
       <a class="sp-role-link" href="...linkedin...">
         <span class="sp-linkedin">[icon]</span>
         <span class="sp-role-text">role/org text</span>
       </a>
     </div>

   The anchor is an inline-flex container so the parent .gc-role keeps its
   text-align: center (inherited from gc-vertical), centering the link
   horizontally. align-items: center vertically aligns the icon and the
   role text on a single horizontal axis. When the role/org wraps to
   multiple lines, the icon stays vertically centered against the wrapped
   text block (acceptable trade-off vs. the previous top-pinned behavior;
   single-line roles are the common case and now read cleanly). */
.sp-identity-card .gc-role.sp-role-with-linkedin {
  /* Parent stays centered via .gc-vertical's text-align: center; the
     anchor child (inline-flex) handles icon + text composition. */
  overflow: visible;
}
.sp-identity-card .sp-role-link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  text-decoration: none;
  color: inherit;
  cursor: pointer;
  transition: color 0.15s;
}
.sp-identity-card .sp-role-link .sp-role-text {
  /* Left-align text within its own span so multi-line wraps don't go
     ragged-center; the parent flex container handles outer centering. */
  text-align: left;
  min-width: 0;
}
/* Hover affordance — text brightens, icon inverts to LinkedIn-blue.
   Hovering anywhere on the row triggers both. */
.sp-identity-card .sp-role-link:hover .sp-role-text {
  color: #c8c8cc;
}
.sp-identity-card .sp-role-link:hover .sp-linkedin {
  color: #ffffff;
  background: #0A66C2;
  transform: scale(1.06);
}

.sp-linkedin {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  color: #0A66C2;
  background: rgba(10, 102, 194, 0.10);
  border-radius: 4px;
  text-decoration: none;
  transition: color 0.15s, background 0.15s, transform 0.15s;
}
.sp-linkedin svg { width: 16px; height: 16px; display: block; }
.sp-linkedin:hover {
  color: #ffffff;
  background: #0A66C2;
  transform: scale(1.06);
}

/* ----- Sector pill ----- */
.sp-sector {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  margin: 0 0 16px;
  border: 1px solid currentColor;
  background: rgba(255, 255, 255, 0.04);
}
.sp-sector-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
  box-shadow: 0 0 4px currentColor;
}

/* ----- Topic-framing line ("N claims about <topic>") ----- */
.sp-topic-framing {
  font-size: 12px;
  color: #9aa0ad;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  margin: 0 0 14px;
}

/* ----- Section labels ----- */
.sp-section { margin-bottom: 4px; }
.sp-section-label {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: #6b7280;
  font-weight: 600;
  margin: 18px 0 8px;
}

/* ----- Top claim card ----- */
.sp-claim {
  background: rgba(255, 255, 255, 0.04);
  border-left: 2px solid var(--sp-family-color, var(--family-color, #8b5cf6));
  border-radius: 0 0.5rem 0.5rem 0;
  padding: 12px 14px;
  margin: 0 0 4px;
  font-size: 13.5px;
  line-height: 1.5;
  color: #e6e8ee;
}
.sp-claim-attr {
  font-size: 11.5px;
  color: #9aa0ad;
  font-style: italic;
  margin-top: 6px;
  padding-top: 6px;
  border-top: 1px solid rgba(255, 255, 255, 0.05);
}

/* ----- Episode thumbnail card ----- */
.sp-thumb {
  display: block;
  margin-top: 8px;
  aspect-ratio: 16 / 9;
  border-radius: 0.5rem;
  overflow: hidden;
  position: relative;
  text-decoration: none;
  background: rgba(0, 0, 0, 0.3);
  border: 1px solid rgba(255, 255, 255, 0.05);
  transition: border-color 0.15s, transform 0.15s;
}
.sp-thumb:hover {
  border-color: rgba(255, 255, 255, 0.18);
  transform: translateY(-1px);
}
.sp-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform 0.3s ease;
}
.sp-thumb:hover img { transform: scale(1.03); }
.sp-thumb::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 48px;
  height: 48px;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.55) url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='white'><path d='M8 5v14l11-7z'/></svg>") center/22px no-repeat;
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
  transition: background-color 0.15s;
}
.sp-thumb:hover::after { background-color: rgba(229, 9, 20, 0.85); }
.sp-thumb[data-platform="apple"]:hover::after { background-color: rgba(252, 60, 68, 0.85); }
.sp-thumb[data-platform="spotify"]:hover::after { background-color: rgba(30, 215, 96, 0.85); }

.sp-episode-meta { margin: 8px 0 4px; }
.sp-episode-title {
  font-size: 12.5px;
  color: #e6e8ee;
  line-height: 1.4;
  margin: 0;
}
.sp-episode-date {
  font-size: 11px;
  color: #6b7280;
  letter-spacing: 0.04em;
  margin-top: 2px;
}

/* ----- Axis positions (Constellation only) -----
   A small viz showing where this guest sits on each active axis
   in the constellation. Each row is: axis label (caption) above
   a thin track; the position dot sits on the track at the
   guest's coordinate in [-1, +1]. */
.sp-axis-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 4px;
}
.sp-axis-row {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.sp-axis-label {
  font-size: 10.5px;
  color: #9aa0ad;
  letter-spacing: 0.04em;
  display: flex;
  gap: 8px;
}
.sp-axis-label .sp-axis-name {
  color: #e6e8ee;
  font-weight: 500;
}
/* Track row places the negative-pole anchor on the far left, the position
   track in the middle (flex-grow: 1), and the positive-pole anchor on the
   far right. Anchor spans render with empty text when a pole label is
   null in source data; the layout stays aligned. */
.sp-axis-track-row {
  display: flex;
  align-items: center;
  gap: 8px;
}
.sp-axis-pole {
  font-size: 10.5px;
  color: #9aa0ad;
  letter-spacing: 0.04em;
  flex-shrink: 0;
  white-space: nowrap;
  line-height: 1;
}
.sp-axis-pole-neg { text-align: right; }
.sp-axis-pole-pos { text-align: left; }
.sp-axis-track {
  position: relative;
  flex: 1 1 auto;
  height: 6px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.04);
}
.sp-axis-track::before {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 1px;
  height: 10px;
  background: rgba(255, 255, 255, 0.12);
  transform: translate(-50%, -50%);
}
.sp-axis-dot {
  position: absolute;
  top: 50%;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--sp-family-color, var(--family-color, #8b5cf6));
  box-shadow: 0 0 8px var(--sp-family-color, var(--family-color, #8b5cf6));
  transform: translate(-50%, -50%);
}

/* ----- "Also in" episode grid (Constellation only) ----- */
.sp-also { margin-top: 4px; }
.sp-also-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(80px, 1fr));
  gap: 6px;
}
.sp-also-thumb {
  display: block;
  aspect-ratio: 16 / 9;
  border-radius: 4px;
  overflow: hidden;
  background: rgba(0, 0, 0, 0.35);
  border: 1px solid rgba(255, 255, 255, 0.05);
  transition: border-color 0.15s, transform 0.15s;
  position: relative;
  text-decoration: none;
}
.sp-also-thumb:hover {
  border-color: rgba(165, 180, 252, 0.4);
  transform: translateY(-1px);
}
.sp-also-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* ----- "Clips" vertical-shorts facade grid -----
   Each clip is a facade: a 9:16 poster + play glyph + title that, on user
   activation (click / Enter / Space), swaps the poster IN PLACE for an inline
   youtube-nocookie player filling the same 9:16 box — the reader never leaves
   the panel, autoplay fires only post-activation. Mirrors the "also-in" grid's
   visual language (rounded glass tile, hairline border, hover lift). Spec:
   12_portal_architecture.md v0.5.0 "speaker panel → clips". */
.sp-clips { margin-top: 4px; }
.sp-clips-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(80px, 1fr));
  gap: 8px;
}
.sp-clip {
  display: block;
  text-decoration: none;
  color: inherit;
  cursor: pointer;
}
.sp-clip[role="button"]:focus-visible {
  outline: 2px solid var(--sp-family-color, var(--family-color, #8b5cf6));
  outline-offset: 2px;
  border-radius: 0.5rem;
}
/* The 9:16 box — shared by the poster and (after activation) the iframe so the
   player fills exactly the same footprint. Capped so a tall 9:16 player can't
   overrun a narrow desktop panel; full width / taller on the mobile panel. */
.sp-clip-frame {
  position: relative;
  aspect-ratio: 9 / 16;
  max-height: 60vh;
  border-radius: 0.5rem;
  overflow: hidden;
  background: rgba(0, 0, 0, 0.35);
  border: 1px solid rgba(255, 255, 255, 0.05);
  transition: border-color 0.15s, transform 0.15s;
}
.sp-clip:hover .sp-clip-frame {
  border-color: rgba(165, 180, 252, 0.4);
  transform: translateY(-1px);
}
/* Activated clip breaks out of the small poster grid to the full panel width
   so the inline player is actually watchable (a ~100px grid cell would render
   a broken / off-screen-looking YouTube embed). Height is capped to the
   viewport so a 9:16 player can't run past the fold of the scrollable panel. */
.sp-clip.sp-clip-playing {
  cursor: default;
  grid-column: 1 / -1;
}
.sp-clip.sp-clip-playing .sp-clip-frame {
  transform: none;
  border-color: rgba(255, 255, 255, 0.10);
  max-height: 70vh;
}
.sp-clip-thumb {
  position: absolute;
  inset: 0;
  display: block;
}
.sp-clip-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform 0.3s ease;
}
.sp-clip:hover .sp-clip-thumb img { transform: scale(1.03); }
.sp-clip-thumb::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.55) url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='white'><path d='M8 5v14l11-7z'/></svg>") center/18px no-repeat;
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
  transition: background-color 0.15s;
}
.sp-clip:hover .sp-clip-thumb::after { background-color: rgba(229, 9, 20, 0.85); }
/* Inline player — fills the same 9:16 box the poster occupied. */
.sp-clip-player {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
  display: block;
}
.sp-clip-title {
  font-size: 11.5px;
  color: #c8c8cc;
  line-height: 1.35;
  margin-top: 6px;
  transition: color 0.15s ease;
}
.sp-clip:hover .sp-clip-title { color: #e6e8ee; }

/* ----- Secondary CTA: Resonance Map -----
   Subtle "go deeper" affordance — sized to its content, family-color
   border + tinted text on a barely-there background. Hover bumps the
   tint and brightens the border without ever competing with the
   top-claim block above it. */
.sp-cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 8px 18px;
  background: rgba(255, 255, 255, 0.02);
  color: var(--sp-family-color, var(--family-color, #8b5cf6));
  text-decoration: none;
  font-size: 16px;
  font-weight: 500;
  letter-spacing: 0.01em;
  line-height: 1.15;
  white-space: nowrap;
  border-radius: 0.5rem;
  border: 1px solid var(--sp-family-color, var(--family-color, #8b5cf6));
  cursor: pointer;
  margin-top: 16px;
  transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease, transform 0.15s ease;
  font-family: inherit;
}
.sp-cta:hover {
  background: color-mix(in srgb, var(--sp-family-color, var(--family-color, #8b5cf6)) 18%, transparent);
  border-color: color-mix(in srgb, var(--sp-family-color, var(--family-color, #8b5cf6)) 100%, white 25%);
  color: #fff;
  transform: translateY(-1px);
}
.sp-cta svg { display: block; flex-shrink: 0; }
.sp-cta-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.sp-cta-icon svg { width: 18px; height: 18px; }
.sp-cta-label { display: inline-block; }
.sp-cta.disabled {
  background: rgba(255, 255, 255, 0.03);
  color: #6b7280;
  border-color: rgba(255, 255, 255, 0.10);
  cursor: not-allowed;
  pointer-events: none;
}

/* ----- Secondary CTA: text fallback ("Watch the episode") ----- */
.sp-secondary {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 0;
  margin-top: 10px;
  font-size: 12.5px;
  color: #9aa0ad;
  text-decoration: none;
  border-bottom: 1px dotted rgba(255, 255, 255, 0.18);
  align-self: flex-start;
  transition: color 0.15s ease, border-color 0.15s ease;
}
.sp-secondary:hover {
  color: var(--sp-family-color, var(--family-color, #8b5cf6));
  border-color: var(--sp-family-color, var(--family-color, #8b5cf6));
}

@media (prefers-reduced-motion: reduce) {
  .sp-panel,
  .sp-overlay,
  .sp-thumb,
  .sp-thumb img,
  .sp-also-thumb,
  .sp-clip-frame,
  .sp-clip-thumb img,
  .sp-clip-title,
  .sp-cta {
    transition: none !important;
  }
}

/* ---- Mobile: full-screen bottom-up panel ---- */
@media (max-width: 640px) {
  .sp-panel {
    top: auto;
    bottom: 0;
    left: 0;
    right: 0;
    width: 100%;
    max-width: 100%;
    height: 92vh;
    max-height: 92vh;
    border-radius: 20px 20px 0 0;
    border-left: none;
    border-top: 1px solid rgba(255,255,255,0.10);
    transform: translateY(100%);
    /* drag handle */
    padding-top: 28px;
  }
  .sp-panel.visible {
    transform: translateY(0);
  }
  /* Drag handle pill above content */
  .sp-panel::before {
    content: '';
    position: absolute;
    top: 10px;
    left: 50%;
    transform: translateX(-50%);
    width: 40px;
    height: 4px;
    border-radius: 2px;
    background: rgba(255,255,255,0.20);
  }
  /* Ensure overlay stays full-screen */
  .sp-overlay {
    position: fixed;
    inset: 0;
  }
  /* Close button repositioned for bottom panel */
  .sp-close {
    top: 36px;
    right: 16px;
  }
}
