/**
 * Card — compositional primitive.
 *
 * Surface for grouped content. Composes with badge, button, link, divider,
 * and icon-block. The bench shows the canonical compositions; this CSS
 * defines the container and hand-off slots only.
 *
 * Three variants by layout, two emphasis levels, optional click affordance.
 *
 * Markup pattern (standard):
 *   <article class="ds-card">
 *     <div class="ds-card__media">...</div>
 *     <div class="ds-card__body">
 *       <div class="ds-card__badges">...</div>
 *       <h3 class="ds-card__title">...</h3>
 *       <p class="ds-card__desc">...</p>
 *       <div class="ds-card__footer">...</div>
 *     </div>
 *   </article>
 */

.ds-card {
  display: flex;
  flex-direction: column;
  background: var(--ds-color-surface-raised);
  border: 1px solid var(--ds-color-border-subtle);
  border-radius: var(--ds-radius-card);
  overflow: hidden;
  position: relative;
  transition: transform var(--ds-duration-default) var(--ds-ease-default),
              border-color var(--ds-duration-default) var(--ds-ease-default),
              box-shadow var(--ds-duration-default) var(--ds-ease-default);
}

/* ─── Slots ──────────────────────────────────────────────────── */
/* Media slot. Aspect ratio is consumer-overridable via --ds-card-media-ratio
   (per design-language.md §7). Defaults to 2:3 — catalogue posters are the
   90% case. Promo / key-art rows opt into 16/9 explicitly:
     <article class="ds-card" style="--ds-card-media-ratio: 16/9">
   Fallback colour appears when no <img> loads (or while async loading);
   override per-card via --ds-card-media-fallback for content-derived tints. */
.ds-card__media {
  position: relative;
  aspect-ratio: var(--ds-card-media-ratio, 2 / 3);
  background: var(--ds-card-media-fallback, var(--ds-color-surface-sunken));
  overflow: hidden;
}
.ds-card__media img,
.ds-card__media video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Modifier: contain-fit for packshots, logos, product photography
   where full visibility matters (design-language.md §7). */
.ds-card--media-contain .ds-card__media img,
.ds-card--media-contain .ds-card__media video {
  object-fit: contain;
  padding: var(--ds-space-2xs);
}

.ds-card__body {
  display: flex;
  flex-direction: column;
  gap: var(--ds-space-2xs);
  padding: var(--ds-space-md);
  flex-grow: 1;
}

.ds-card__badges {
  display: flex;
  flex-wrap: wrap;
  gap: var(--ds-space-2xs);
  margin-bottom: var(--ds-space-2xs);
}

.ds-card__eyebrow {
  font-size: var(--ds-text-caption);
  font-weight: var(--ds-weight-strong);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ds-color-text-action);
  margin: 0;
}

.ds-card__title {
  font-family: var(--ds-font-body);
  font-size: var(--ds-text-heading-md);
  font-weight: var(--ds-weight-heading);
  line-height: var(--ds-leading-heading);
  color: var(--ds-color-text-heading);
  margin: 0;
}

.ds-card__desc {
  font-size: var(--ds-text-body-sm);
  line-height: var(--ds-leading-body);
  color: var(--ds-color-text-secondary);
  margin: 0;
}

.ds-card__meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--ds-space-2xs) var(--ds-space-sm);
  font-size: var(--ds-text-caption);
  color: var(--ds-color-text-muted);
  margin-top: var(--ds-space-2xs);
}

.ds-card__footer {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--ds-space-sm);
  margin-top: var(--ds-space-md);
  padding-top: var(--ds-space-sm);
  border-top: 1px solid var(--ds-color-border-subtle);
}

/* ─── Variants ───────────────────────────────────────────────── */

/* Compact: horizontal split, image left, content right.
   Two media shapes per design-language.md §7 — pick via modifier:
     ds-card--compact + ds-card--compact-square (default)
       → 1:1 thumbnail at row height (tidy cadence, content-led)
     ds-card--compact + ds-card--compact-poster
       → 2:3 thumbnail at ~64x96 (poster-led, recognisable at a glance)
   Avoids the previous 96px-wide-with-auto-aspect squashing. */
.ds-card--compact {
  flex-direction: row;
  align-items: stretch;
}
.ds-card--compact .ds-card__media {
  /* Default: square (1:1) tied to card body height — uses the body's
     intrinsic content height so the thumbnail aligns with the row.
     Modifier classes below override the aspect/width as needed. */
  aspect-ratio: 1 / 1;
  width: auto;
  height: auto;
  flex-shrink: 0;
  align-self: stretch;
}
.ds-card--compact .ds-card__media img {
  height: 100%;
  width: auto;
  aspect-ratio: 1 / 1;
}
.ds-card--compact-square .ds-card__media {
  aspect-ratio: 1 / 1;
}
.ds-card--compact-poster .ds-card__media {
  aspect-ratio: 2 / 3;
  width: var(--ds-space-2xl);  /* 64px wide → ~96px tall poster */
}
.ds-card--compact-poster .ds-card__media img {
  width: 100%;
  height: 100%;
  aspect-ratio: 2 / 3;
}
.ds-card--compact .ds-card__body { padding: var(--ds-space-md); }

/* Hero: large, no border, used as section opener */
.ds-card--hero {
  border: none;
  border-radius: var(--ds-radius-modal);
  background: var(--ds-gradient-hero);
  color: var(--ds-color-text-inverse);
}
.ds-card--hero .ds-card__title {
  font-family: var(--ds-font-display);
  font-size: var(--ds-text-display-md);
  font-weight: var(--ds-weight-display);
  line-height: var(--ds-leading-display);
  color: var(--ds-color-text-inverse);
}
.ds-card--hero .ds-card__desc { color: var(--ds-color-text-inverse-secondary); }
.ds-card--hero .ds-card__eyebrow { color: var(--ds-color-brand-highlight); }
.ds-card--hero .ds-card__body { padding: var(--ds-space-xl); }
.ds-card--hero .ds-card__footer { border-top-color: var(--ds-color-border-inverse-subtle); }

/* Stat: number-led, no media, dense */
.ds-card--stat .ds-card__body { gap: var(--ds-space-3xs); }
.ds-card--stat .ds-card__title {
  font-family: var(--ds-font-display);
  font-size: var(--ds-text-display-md);
  font-weight: var(--ds-weight-display);
  line-height: var(--ds-leading-display);
}

/* ─── Emphasis levels ────────────────────────────────────────── */
.ds-card--raised { box-shadow: var(--ds-shadow-card); border-color: transparent; }
.ds-card--inverse {
  background: var(--ds-color-surface-inverse);
  color: var(--ds-color-text-inverse);
  border-color: transparent;
}
.ds-card--inverse .ds-card__title { color: var(--ds-color-text-inverse); }
.ds-card--inverse .ds-card__desc { color: var(--ds-color-text-inverse-secondary); }
.ds-card--inverse .ds-card__eyebrow { color: var(--ds-color-brand-highlight); }
.ds-card--inverse .ds-card__footer { border-top-color: var(--ds-color-border-inverse-subtle); }

/* ─── Click affordance ───────────────────────────────────────── */
.ds-card--clickable { cursor: pointer; }
.ds-card--clickable:hover {
  transform: translateY(-2px);
  border-color: var(--ds-color-border-brand);
  box-shadow: var(--ds-shadow-card);
}
.ds-card--clickable.ds-card--raised:hover { box-shadow: var(--ds-shadow-overlay); }
.ds-card--clickable:focus-visible {
  outline: var(--ds-focus-ring);
  outline-offset: var(--ds-focus-ring-offset);
}

/* ─── Disabled / coming-soon ───────────────────────────────────
   Per design-language.md §2: no element-level opacity. Body text
   shifts to the disabled foreground token; the existing media
   overlay (a semi-transparent darkening on the image, not a global
   opacity) provides the visual "muted" cue without breaking focus
   ring contrast. */
.ds-card--disabled {
  cursor: not-allowed;
}
.ds-card--disabled .ds-card__title,
.ds-card--disabled .ds-card__desc,
.ds-card--disabled .ds-card__eyebrow,
.ds-card--disabled .ds-card__meta {
  color: var(--ds-color-fg-disabled);
}
.ds-card--disabled .ds-card__media::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--ds-color-surface-inverse);
  opacity: 0.3;  /* Media-overlay treatment, not element-opacity — safe. */
}

/* Reduced-motion: keep colour shifts (border, shadow), drop the lift
   (Apple HIG: meaningful motion gets a fade fallback, not a hard cut). */
@media (prefers-reduced-motion: reduce) {
  .ds-card--clickable:hover { transform: none; }
}
