/* ════════════════════════════════════════════════════════════════
 * Eventcard — shared base
 * ────────────────────────────────────────────────────────────────
 * Common foundation for all three card sizes (small / medium / large).
 * The three size files only add shell + layout; everything visual and
 * shared — typography, meta, social, pill controls, dropdown, badge,
 * hover and dark mode — lives here so it is defined exactly once.
 *
 * DOM prefixes rendered by components.js:
 *   small  → .ecs / .ecs-*
 *   medium → .ecm / .ecm-*
 *   large  → .po.ncard-lg / .nc-lg-left .nc-* / .nc-lg-right
 *   shared → .ec-ticket, .ec-btn--attend, .ec-btn--bookmark, .att-dropdown*
 *
 * Reference design: frontend/eventcards/eventcard-{small,medium,large}.html
 * Depends on: vars.css (--t, --cat-*, --a, --font-*, --space-*, --text-sm …)
 * ════════════════════════════════════════════════════════════════ */

:root {
  --ec-radius: 8px;          /* card + image corner radius */
  --ec-pad: 16px;            /* content padding */
  --ec-pill-radius: 999px;   /* full pill for buttons / badges / venue */
  --ec-pill-pad: 8px 12px;   /* buttons + ticket */
  --ec-stroke: 1px;          /* control border */
}

/* ════════════════════════════════════════════════════════════════
 * Card shell — shared behaviour (background + radius stay per size)
 * ════════════════════════════════════════════════════════════════ */
/* @penpot cmp.eventcard-base */
.ecs,
.ecm,
.po.ncard-lg {
  font-family: var(--font-heading);
  color: var(--t);
  cursor: pointer;
  border-radius: var(--ec-radius);
  margin-bottom: 16px;
  box-shadow: none;
}

/* No hover decoration on the card shell. box-shadow:none + transform:none also
 * neutralise the legacy .po:hover shadow + lift the large card would otherwise
 * inherit (it carries the shared .po class). */
.ecs:hover,
.ecm:hover,
.po.ncard-lg:hover {
  box-shadow: none;
  transform: none;
}

/* Cards are role="button" + tabindex="0" (see cardA11yAttrs in components.js).
 * Without a visible ring, keyboard users have no idea where they are. */
.ecs:focus-visible,
.ecm:focus-visible,
.po:focus-visible {
  outline: 2px solid var(--a);
  outline-offset: 2px;
}

/* Suppress the ring for pointer users, who already get the hover cue. */
.ecs:focus:not(:focus-visible),
.ecm:focus:not(:focus-visible),
.po:focus:not(:focus-visible) {
  outline: none;
}

@media (prefers-reduced-motion: reduce) {
  .ecs, .ecm, .po {
    transition: none;
    animation: none;
  }
}

/* ─────────────────────────────────────────────────────────
 * Live badge — "gerade", shown while an event is running.
 * Reads as a broadcast indicator: red dot with a pulsing halo.
 * Shared by cards and the event modal.
 * ───────────────────────────────────────────────────────── */
/* @penpot cmp.eventcard-live-badge */
.live-badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px 4px 8px;
  border-radius: var(--ec-pill-radius);
  background: #fef2f2;
  border: 1px solid #fecaca;
  color: #dc2626;
  font-family: var(--font-heading);
  font-size: 12px;
  font-weight: 700;
  line-height: 1;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  white-space: nowrap;
}

/* @penpot cmp.eventcard-live-dot */
.live-dot {
  position: relative;
  flex-shrink: 0;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #dc2626;
}

/* Expanding halo — the "on air" pulse. */
.live-dot::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: #dc2626;
  animation: livePulse 1.8s ease-out infinite;
}

@keyframes livePulse {
  0% { transform: scale(1); opacity: 0.7; }
  70% { transform: scale(2.6); opacity: 0; }
  100% { transform: scale(2.6); opacity: 0; }
}

/* Card placement: top-right of the media. The category tag owns the top-left
 * corner on every card variant, and the image copyright the bottom-right. */
.live-badge.ec-live {
  position: absolute;
  top: 12px;
  right: 12px;
  z-index: 3;
  background: rgba(220, 38, 38, 0.95);
  border-color: rgba(255, 255, 255, 0.35);
  color: #fff;
  backdrop-filter: blur(4px);
}

.live-badge.ec-live .live-dot,
.live-badge.ec-live .live-dot::after {
  background: #fff;
}

body.dark .live-badge {
  background: rgba(220, 38, 38, 0.16);
  border-color: rgba(248, 113, 113, 0.45);
  color: #f87171;
}

body.dark .live-badge .live-dot,
body.dark .live-badge .live-dot::after {
  background: #f87171;
}

body.dark .live-badge.ec-live {
  background: rgba(220, 38, 38, 0.95);
  color: #fff;
}

body.dark .live-badge.ec-live .live-dot,
body.dark .live-badge.ec-live .live-dot::after {
  background: #fff;
}

/* A blinking element is a vestibular trigger — hold the dot steady instead. */
@media (prefers-reduced-motion: reduce) {
  .live-dot::after {
    animation: none;
    opacity: 0;
  }
}

/* ════════════════════════════════════════════════════════════════
 * Typography — title / description
 * ════════════════════════════════════════════════════════════════ */
/* @penpot cmp.eventcard-title */
.ecs-title,
.ecm-title,
.nc-lg-left .nc-title {
  margin: 0;
  font-family: var(--font-heading);
  font-size: 24px;
  line-height: 24px;
  font-weight: 900;
  color: var(--t);
}

/* @penpot cmp.eventcard-desc */
.ecs-desc,
.ecm-desc,
.nc-lg-left .nc-desc {
  margin: 0;
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 19.2px;
  font-weight: 600;
  color: var(--t);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* ════════════════════════════════════════════════════════════════
 * Meta row — date ● time · pin · venue pill
 * ════════════════════════════════════════════════════════════════ */
.ecs-meta,
.ecm-meta,
.nc-lg-left .nc-meta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 4px;
  font-size: 14px;
  line-height: 12px;
  font-weight: 600;
  color: var(--t);
}

.ecs-date,
.ecm-date,
.nc-lg-left .nc-date {
  font-size: 14px;
  line-height: 14px;
  font-weight: 600;
  color: var(--t);
  white-space: nowrap;
}

.ecs-dot,
.ecm-dot,
.nc-lg-left .nc-dot {
  font-size: 7px;
  line-height: 1;
  color: var(--t);
}

.ecs-pin,
.ecm-pin,
.nc-lg-left .nc-pin {
  display: inline-flex;
  align-items: center;
  font-size: 14px;
  line-height: 1;
}

.nc-lg-left .nc-pin svg,
.ecs-pin svg,
.ecm-pin svg {
  width: 14px;
  height: 14px;
}

.nc-multiday {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 14px;
  line-height: 1;
}

.nc-multiday svg {
  width: 14px;
  height: 14px;
  flex-shrink: 0;
}

.ecs-venue,
.ecm-venue,
.nc-lg-left .nc-venue {
  display: inline-block;
  padding: 6px 12px;
  border: var(--ec-stroke) solid var(--t);
  border-radius: var(--ec-pill-radius);
  font-size: 14px;
  line-height: 14px;
  font-weight: 600;
  color: var(--t);
  /* nowrap keeps the pill on one line, but without a cap a long venue name
   * ("Jugendverkehrsschule Aschaffenburg, Kleine Schönbuschallee 17") grew the
   * chip past the card and pushed the whole page into horizontal scroll. */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
  min-width: 0;
  vertical-align: bottom;
}

/* Hide dangling separators when time is unknown */
.ecs-time:empty,
.ecm-time:empty {
  display: none;
}

/* ════════════════════════════════════════════════════════════════
 * Category badge — pill on the image (medium + large; small has none)
 * ════════════════════════════════════════════════════════════════ */
.ecm-cat,
.ncard-lg .nc-cat {
  position: absolute;
  top: 12px;
  left: 12px;
  z-index: 2;
  padding: 4px 10px;
  border-radius: var(--ec-pill-radius);
  /* Pill takes the card's own category colour (inherited via --ec-card-bg),
   * sitting on top of the photo — not a dark overlay. */
  background: var(--ec-card-bg, var(--cat-default));
  color: var(--t);
  font-family: var(--font-heading);
  font-size: 11px;
  font-weight: 700;
  line-height: 1;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}

/* ════════════════════════════════════════════════════════════════
 * Social proof — avatar stack + text
 * ════════════════════════════════════════════════════════════════ */
.ecs-social-txt,
.ecm-social-txt,
.nc-lg-att-txt {
  font-family: var(--font-heading);
  font-size: 12px;
  line-height: 12px;
  font-weight: 600;
  color: var(--t);
}

/* Avatar base — medium & small (large avatars use the shared app .mav).
 * Flex-centres the fallback initial; overflow-clips the image to the circle. */
.ecs-av,
.ecm-av {
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  overflow: hidden;
  flex-shrink: 0;
  background: var(--c2);
  font-family: var(--font-heading);
  font-weight: 700;
  line-height: 1;
  color: var(--t);
}

/* Text-avatar colour variants (shared across all sizes) */
.ecs-av.c1, .ecm-av.c1, .mav-lg.c1 { background: linear-gradient(135deg, #6366f1, #818cf8); color: #fff; }
.ecs-av.c2, .ecm-av.c2, .mav-lg.c2 { background: linear-gradient(135deg, #10b981, #34d399); color: #fff; }
.ecs-av.c3, .ecm-av.c3, .mav-lg.c3 { background: linear-gradient(135deg, #ec4899, #f472b6); color: #fff; }
.ecs-av.c4, .ecm-av.c4, .mav-lg.c4 { background: linear-gradient(135deg, #06b6d4, #22d3ee); color: #fff; }
.ecs-av.c5, .ecm-av.c5, .mav-lg.c5 { background: linear-gradient(135deg, #f59e0b, #fbbf24); color: #fff; }

/* Avatar image fill (shared) — covers the whole circle */
.ecs-av img,
.ecm-av img,
.mav-lg .avatar-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Image variant has no gradient/tint behind the photo */
.ecs-av--img,
.ecm-av--img {
  background: none;
}

/* ════════════════════════════════════════════════════════════════
 * Pill controls — ticket / attend / bookmark
 * One system: 1px stroke, transparent fill, accent-fill on hover.
 * ════════════════════════════════════════════════════════════════ */
.ec-ticket,
.ec-btn--attend,
.ec-btn--bookmark,
.att-dropdown-btn,
.cact,
.cact-bookmark {
  display: inline-flex;
  align-items: center;
  gap: var(--space-4);
  padding: var(--ec-pill-pad);
  border: var(--ec-stroke) solid var(--t);
  border-radius: var(--ec-pill-radius);
  background: transparent;
  color: var(--t);
  font-family: var(--font-heading);
  font-size: var(--text-sm);
  line-height: var(--text-sm);
  font-weight: 600;
  white-space: nowrap;
  text-decoration: none;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}

.ec-ticket svg,
.ec-btn--attend svg,
.ec-btn--bookmark svg,
.cact svg,
.ec-btn__icon,
.ec-ticket__icon {
  flex-shrink: 0;
  width: 16px;
  height: 16px;
}

.ec-ticket:hover,
.ec-btn--attend:hover,
.ec-btn--bookmark:hover,
.att-dropdown-btn:hover,
.cact:hover,
.cact-bookmark:hover {
  background: var(--a);
  color: var(--bg);
  border-color: var(--a);
}

/* Invert stroke icons on filled hover */
.ec-ticket:hover svg,
.ec-btn--attend:hover svg,
.ec-btn--bookmark:hover svg,
.cact:hover svg {
  filter: brightness(0) invert(1);
}

.ec-ticket:focus-visible,
.ec-btn--attend:focus-visible,
.ec-btn--bookmark:focus-visible,
.cact:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* A committed signal fills the trigger — same treatment the saved bookmark
 * gets, so "I'm in" reads identically across both controls. `declined` stays
 * outlined: it is the absence of a commitment, not one. */
.ec-btn--attend.is-attendance,
.ec-btn--attend.is-attendance:hover,
.ec-btn--attend.is-interest,
.ec-btn--attend.is-interest:hover {
  background: var(--a);
  border-color: var(--a);
  color: var(--bg);
}

/* Icons here are stroke-drawn, so they follow currentColor rather than the
 * brightness/invert filter used for the hover state on outlined buttons. */
.ec-btn--attend.is-attendance svg,
.ec-btn--attend.is-interest svg {
  filter: none;
  color: var(--bg);
}

.ec-btn--attend.is-attendance .chevron,
.ec-btn--attend.is-interest .chevron {
  opacity: 0.75;
}

/* Attendance dropdown chevron */
.ec-btn--attend .chevron,
.att-dropdown-btn .chevron {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  font-size: 10px;
  opacity: 0.6;
  transition: transform 0.15s ease;
}

.ec-btn--attend .chevron svg,
.att-dropdown-btn .chevron svg {
  width: 16px;
  height: 16px;
}

.ec-btn--attend.open .chevron,
.att-dropdown-btn.open .chevron {
  transform: rotate(180deg);
}

/* index.html re-styles `.cact-bookmark` (padding 6px, amber hover) and loads
 * after this file. Re-assert the shared pill look at higher specificity
 * (`.ec-btn--bookmark.cact-bookmark`, both classes always present) so the
 * bookmark stays identical to the attend/ticket buttons. */
.ec-btn--bookmark.cact-bookmark {
  padding: var(--ec-pill-pad);
}

.ec-btn--bookmark.cact-bookmark:hover {
  background: var(--a);
  color: var(--bg);
  border-color: var(--a);
}

.ec-btn--bookmark.cact-bookmark:hover svg {
  filter: brightness(0) invert(1);
}

/* Bookmark saved state — filled accent (black bg / white text + icon in light).
 * Specificity is raised to `.ec-btn--bookmark.cact-bookmark.on` (the rendered
 * button always carries both classes) so it beats index.html's amber
 * `.cact-bookmark.on` / `.cact-bookmark:hover`, which would otherwise win. */
.ec-btn--bookmark.cact-bookmark.on,
.ec-btn--bookmark.cact-bookmark.on:hover {
  background: var(--a);
  color: var(--bg);
  border-color: var(--a);
}

/* Icon follows the text colour (white in light) — filled bookmark = saved */
.ec-btn--bookmark.cact-bookmark.on svg {
  filter: none;
}

.ec-btn--bookmark.cact-bookmark.on svg path {
  fill: currentColor;
  stroke: currentColor;
}

/* ════════════════════════════════════════════════════════════════
 * Attendance dropdown menu (shared, all sizes)
 * ════════════════════════════════════════════════════════════════ */
.att-dropdown {
  position: relative;
  display: inline-block;
}

.att-dropdown-menu {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  z-index: 100;
  min-width: 180px;
  padding: 4px 0;
  background: var(--surface-solid);
  border: 1px solid var(--b);
  border-radius: var(--r);
  box-shadow: var(--shadow-lg);
  display: none;
}

.att-dropdown-menu.open,
.att-dropdown-menu.show {
  display: block;
}

/* Portaled variant: while open, utils.js appends the menu to <body> and
 * positions it fixed against the trigger's rect. Event cards create their
 * own stacking context (hover transform / entry animation) and clip with
 * overflow:hidden, so an in-card z-index can NEVER rise above the next
 * card — the portal puts the menu on the top layer, above the modal
 * overlay (z-index 1000). top/left are set inline by JS. */
.att-dropdown-menu.att-portal {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 2000;
}

.att-dropdown-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 14px;
  border-left: 3px solid transparent;
  font-family: var(--font-heading);
  font-size: 13px;
  font-weight: 500;
  color: var(--t);
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
}

.att-dropdown-item:hover {
  background: var(--c2);
}

.att-dropdown-item .att-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  flex-shrink: 0;
}

.att-dropdown-item .att-icon svg {
  width: 16px;
  height: 16px;
}

.att-dropdown-item.active {
  font-weight: 700;
}

/* Monochrome menu. The options used to be green / amber / red per signal,
 * which read as status colour rather than as a choice and clashed with the
 * otherwise black-and-white control set. Selection is carried by weight and
 * the left rule instead. */
.att-dropdown-item[data-signal]:hover,
.att-dropdown-item[data-signal].active {
  background: var(--c2);
  border-left-color: var(--t);
  color: var(--t);
  font-weight: 700;
}

.att-dropdown-divider {
  margin-top: 4px;
  padding: 8px 14px 6px;
  border-top: 1px solid var(--b);
  font-family: var(--font-heading);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--t4);
}

/* ════════════════════════════════════════════════════════════════
 * Priority badges (editorial / trending / past) — large card
 * ════════════════════════════════════════════════════════════════ */
.nc-badge-wrap {
  display: inline-flex;
  gap: 4px;
}

.cbadge {
  padding: 2px 8px;
  border-radius: var(--ec-pill-radius);
  font-size: 10px;
  font-weight: 700;
  white-space: nowrap;
}

.cbadge.cb-ed    { background: var(--color-score-recommended); color: #fff; }
.cbadge.cb-taste { background: var(--color-score-popular); color: #fff; }
.cbadge.cb-trend { background: var(--today-soft); color: var(--today); }
.cbadge.cb-past  { background: var(--c2); color: var(--t4); }
.cbadge.cb-kinder { background: var(--color-score-popular); color: #fff; }
/* Exhibition badge (features/15.md A4): solid black pill with white text +
   Lucide-Icon (2026-08-29, User-Wunsch) — gleiche solid-Badge-Sprache wie
   .ec-live (LIVE: rot/weiß). Content-fit in allen Card-Varianten. */
.cbadge.cb-exhibition {
  background: #111114;
  color: #fff;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  width: fit-content;
}
.cbadge.cb-exhibition .cb-ico,
.cbadge.cb-exhibition svg {
  width: 12px;
  height: 12px;
  flex-shrink: 0;
}

/* ════════════════════════════════════════════════════════════════
 * Dark mode — shared overrides
 * ════════════════════════════════════════════════════════════════ */
body.dark .ecs-desc,
body.dark .ecm-desc,
body.dark .nc-lg-left .nc-desc,
body.dark .ecs-meta,
body.dark .ecm-meta,
body.dark .nc-lg-left .nc-meta,
body.dark .ecs-social-txt,
body.dark .ecm-social-txt,
body.dark .nc-lg-att-txt {
  color: var(--t2);
}

body.dark .ecs-venue,
body.dark .ecm-venue,
body.dark .nc-lg-left .nc-venue {
  border-color: var(--t2);
  color: var(--t);
}
