// frontend/src/pages/crm/customers/CustomerListCardView.jsx
// Card view for the Customer List — rendered when viewMode === 'card'

import { useState, useRef, useEffect } from 'react'
import { createPortal } from 'react-dom'
import Icon                from '@/components/ui/Icon'
import { fmtRelative }     from '@/lib/formatters'
import ComposeEmailModal   from '@/modals/crm/ComposeEmailModal'

// ─── Comm icon raw SVG imports ────────────────────────────────────────────────

import commEmailIcon    from '@/assets/comms/email.svg?raw'
import commWhatsappIcon from '@/assets/comms/whatsapp.svg?raw'
import commCallIcon     from '@/assets/comms/call.svg?raw'
import commSmsIcon      from '@/assets/comms/sms.svg?raw'
import commNoteIcon     from '@/assets/comms/note.svg?raw'
import commInPersonIcon from '@/assets/comms/inperson.svg?raw'

// ─── Status icon raw SVG imports ──────────────────────────────────────────────

import clientIcon            from '@/assets/customer-status/client.svg?raw'
import negotiatingIcon       from '@/assets/customer-status/negotiating.svg?raw'
import awaitingQuotationIcon from '@/assets/customer-status/awating-quotation.svg?raw'
import awaitingConfirmIcon   from '@/assets/customer-status/awaiting-confirmation.svg?raw'
import quotationAcceptedIcon from '@/assets/customer-status/quotation-accepted.svg?raw'
import startedMfgIcon        from '@/assets/customer-status/started-mfg.svg?raw'
import awaitingPaymentIcon   from '@/assets/customer-status/awaiting-payment.svg?raw'
import shippedIcon           from '@/assets/customer-status/shipped.svg?raw'
import inactiveIcon          from '@/assets/customer-status/inactive.svg?raw'
import declinedIcon          from '@/assets/customer-status/declined.svg?raw'
import churnedIcon           from '@/assets/customer-status/churned.svg?raw'
import exclamationIcon       from '@/assets/customer-status/exclamation.svg?raw'
import wrenchIcon            from '@/assets/customer-status/wrench.svg?raw'

// ─── Constants ────────────────────────────────────────────────────────────────

const COMM_TYPE_META = {
  email:     { label: 'Email',     color: 'var(--color-info)',        icon: commEmailIcon    },
  whatsapp:  { label: 'WhatsApp',  color: 'var(--color-success)',     icon: commWhatsappIcon },
  call:      { label: 'Call',      color: 'var(--color-warning)',     icon: commCallIcon     },
  sms:       { label: 'SMS',       color: 'var(--color-warning)',     icon: commSmsIcon      },
  note:      { label: 'Note',      color: 'var(--color-text-muted)',  icon: commNoteIcon     },
  in_person: { label: 'In Person', color: 'var(--color-primary)',     icon: commInPersonIcon },
}

// ─── Helpers ──────────────────────────────────────────────────────────────────

// Strips all hardcoded fill colours from SVG markup so fill:currentColor takes effect.
function sanitiseSvg(svgRaw) {
  return svgRaw
    // Remove XML/DOCTYPE/comment cruft
    .replace(/<\?xml[\s\S]*?\?>/gi, '')
    .replace(/<!DOCTYPE[\s\S]*?>/gi, '')
    .replace(/<!--[\s\S]*?-->/g, '')
    // Remove <style> blocks entirely (they contain hardcoded .st0{fill:#000} etc.)
    .replace(/<style[\s\S]*?<\/style>/gi, '')
    // Strip fill="..." attributes (but not fill="none")
    .replace(/\bfill\s*=\s*["'][^"']*["']/gi, (m) =>
      /fill\s*=\s*["']none["']/i.test(m) ? m : ''
    )
    // Strip inline style="...fill:..." declarations
    .replace(/style\s*=\s*["']([^"']*)["']/gi, (_, inner) => {
      const cleaned = inner
        .split(';')
        .filter((p) => !/^\s*(fill|color|stroke)\s*:/.test(p))
        .join(';')
        .replace(/^;+|;+$/g, '')
      return cleaned ? `style="${cleaned}"` : ''
    })
}

function renderMaskedIcon(svgRaw, color, title, size = 18) {
  const clean  = sanitiseSvg(svgRaw)
  const markup = clean.replace(
    /<svg\b([^>]*)>/i,
    `<svg$1 width="${size}" height="${size}" aria-label="${title}" role="img" focusable="false" ` +
    `style="display:block;width:${size}px;height:${size}px;color:${color};fill:currentColor;flex-shrink:0;">`,
  )
  return (
    <span
      title={title}
      aria-label={title}
      role="img"
      style={{ width: size, height: size, display: 'inline-flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0, lineHeight: 0 }}
      dangerouslySetInnerHTML={{ __html: markup }}
    />
  )
}

function resolveStatusIcon(customer) {
  const status    = customer.relationship_status || 'lead'
  const summary   = customer.crm_summary || {}
  const allOrders = summary.all_orders_statuses || []

  if (status === 'churned')  return { icon: churnedIcon,  color: 'var(--color-text-muted)', label: 'Went Cold' }
  if (status === 'lead')     return { icon: clientIcon,   color: 'var(--color-text-muted)', label: 'Lead' }
  if (status === 'prospect') return { icon: clientIcon,   color: 'var(--color-info)',        label: 'Prospect' }
  if (status === 'inactive') return { icon: inactiveIcon, color: 'var(--color-text-muted)', label: 'Archived' }

  if (status === 'active') {
    const s = summary.active_order_status
    const map = {
      negotiating:                    { icon: negotiatingIcon,       color: 'var(--color-text-secondary)', label: 'Negotiating' },
      awaiting_quotation:             { icon: awaitingQuotationIcon, color: 'var(--color-text-secondary)', label: 'Awaiting Quotation' },
      awaiting_customer_confirmation: { icon: awaitingConfirmIcon,   color: 'var(--color-text-secondary)', label: 'Awaiting Confirmation' },
      awaiting_fulfilment:            { icon: quotationAcceptedIcon, color: 'var(--color-info)',            label: 'Accepted - Waiting' },
      awaiting_payment:               { icon: awaitingPaymentIcon,   color: 'var(--color-warning)',         label: 'Awaiting Payment' },
      manufacturing:                  { icon: startedMfgIcon,        color: 'var(--color-success)',         label: 'Manufacturing' },
      shipped:                        { icon: shippedIcon,           color: 'var(--color-success)',         label: 'Shipped' },
      installed:                      { icon: inactiveIcon,          color: 'var(--color-success)',         label: 'Installed' },
    }
    if (s && map[s]) return map[s]
    if (allOrders.length > 0 && allOrders.every((x) => x === 'declined'))
      return { icon: declinedIcon, color: 'var(--color-danger)', label: 'All Declined' }
    if (allOrders.length > 0 && allOrders.every((x) => x === 'complete'))
      return { icon: inactiveIcon, color: 'var(--color-success)', label: 'All Complete' }
    return { icon: inactiveIcon, color: 'var(--color-info)', label: 'Active' }
  }

  return { icon: clientIcon, color: 'var(--color-text-muted)', label: status }
}

// Marks an element with data-overflow="true" when its inner text exceeds its width.
// Call the returned ref-setter on the wrapper element (the p/span with overflow:hidden).
function useOverflowMarquee() {
  const ref = useRef(null)
  useEffect(() => {
    const el = ref.current
    if (!el) return
    const inner = el.querySelector('.ccard__marquee-inner')
    if (!inner) return
    function check() {
      el.dataset.overflow = inner.scrollWidth > el.clientWidth ? 'true' : 'false'
    }
    check()
    const ro = new ResizeObserver(check)
    ro.observe(el)
    return () => ro.disconnect()
  }, [])
  return ref
}

function resolveLocation(customer) {
  const loc      = customer.location || {}
  const country  = (loc.country || '').trim()
  const city     = (loc.city    || '').trim()
  const isGreece = /^(greece|ελλάδα|ellada)$/i.test(country)
  return isGreece ? city : [city, country].filter(Boolean).join(', ')
}

// ─── 3-dot actions menu ───────────────────────────────────────────────────────

function CardActions({ onView, onEdit, onSendMail, canEdit }) {
  const [open, setOpen] = useState(false)
  const [pos, setPos]   = useState({ top: 0, right: 0 })
  const btnRef          = useRef(null)
  const menuRef         = useRef(null)

  useEffect(() => {
    if (!open) return
    function onDown(e) {
      if (btnRef.current?.contains(e.target))  return
      if (menuRef.current?.contains(e.target)) return
      setOpen(false)
    }
    function onScroll() { setOpen(false) }
    document.addEventListener('mousedown', onDown)
    document.addEventListener('scroll', onScroll, true)
    return () => {
      document.removeEventListener('mousedown', onDown)
      document.removeEventListener('scroll', onScroll, true)
    }
  }, [open])

  function handleToggle(e) {
    e.stopPropagation()
    if (!open && btnRef.current) {
      const r = btnRef.current.getBoundingClientRect()
      setPos({ top: r.bottom + 4, right: window.innerWidth - r.right })
    }
    setOpen((v) => !v)
  }

  const actions = [
    { label: 'View',      icon: <Icon name="eye"   size={14} />, onClick: onView },
    ...(canEdit ? [{ label: 'Edit', icon: <Icon name="edit" size={14} />, onClick: onEdit }] : []),
    { label: 'Send Mail', icon: <Icon name="mail"  size={14} />, onClick: onSendMail },
  ]

  return (
    <>
      <button
        ref={btnRef}
        className="ccard__dots"
        aria-label="Customer actions"
        aria-haspopup="true"
        aria-expanded={open}
        onClick={handleToggle}
        title="Actions"
      >
        <Icon name="more_vertical" size={20} />
      </button>

      {open && createPortal(
        <div
          ref={menuRef}
          role="menu"
          className="ccard-actions-menu"
          style={{ position: 'fixed', top: pos.top, right: pos.right, zIndex: 9999 }}
        >
          {actions.map((a) => (
            <button
              key={a.label}
              role="menuitem"
              className="ccard-actions-item"
              onClick={(e) => { e.stopPropagation(); setOpen(false); a.onClick?.() }}
            >
              <span className="ccard-actions-item__icon">{a.icon}</span>
              {a.label}
            </button>
          ))}
        </div>,
        document.body
      )}
    </>
  )
}

// ─── CustomerCard ─────────────────────────────────────────────────────────────

function CustomerCard({ customer, latestComm, canEdit, showTitles = true, onNavigate, onEdit }) {
  const [composeOpen, setComposeOpen] = useState(false)

  const summary    = customer.crm_summary || {}
  const statusInfo = resolveStatusIcon(customer)

  const nameParts   = showTitles ? [customer.title, customer.name, customer.surname] : [customer.name, customer.surname]
  const displayName = nameParts.filter(Boolean).join(' ') || 'Unnamed'
  const org         = customer.organization || ''
  const location    = resolveLocation(customer)
  const subLine     = [org, location].filter(Boolean).join(' · ')

  const issueCount   = summary.active_issues_count  || 0
  const supportCount = summary.active_support_count || 0

  const tags      = (customer.tags || []).slice(0, 5)
  const extraTags = (customer.tags || []).length - 5

  const commMeta = latestComm ? (COMM_TYPE_META[latestComm.type] || COMM_TYPE_META.note) : null

  const nameRef   = useOverflowMarquee()
  const subRef    = useOverflowMarquee()
  const statusRef = useOverflowMarquee()

  const watermarkSvg = sanitiseSvg(statusInfo.icon).replace(
    /<svg\b([^>]*)>/i,
    `<svg$1 width="100%" height="100%" aria-hidden="true" focusable="false" ` +
    `style="display:block;color:${statusInfo.color};fill:currentColor;">`,
  )

  // Resolve primary email — prefer contacts list, fall back to top-level email field
  const primaryEmail = (() => {
    const contacts = customer.contacts || []
    const emailContact = contacts.find((c) => c.type === 'email' && c.value)
    return emailContact?.value || customer.email || ''
  })()

  return (
    <>
      <a
        className="ccard"
        href={`/crm/customers/${customer.id}`}
        aria-label={`View ${displayName}`}
        onClick={(e) => { e.preventDefault(); onNavigate() }}
        style={{ backgroundImage: `linear-gradient(135deg, color-mix(in srgb, ${statusInfo.color} 20%, transparent) 0%, transparent 60%)` }}
      >
      {/* Background watermark — status icon at low opacity */}
      <span className="ccard__watermark" aria-hidden="true" dangerouslySetInnerHTML={{ __html: watermarkSvg }} />

      {/* Accent bar — vertical, left side */}
      <div className="ccard__accent-wrap">
        <div className="ccard__accent-bar" style={{ backgroundColor: statusInfo.color }} aria-hidden="true" />
      </div>

      {/* Body — justify-content: space-between so rows are evenly spaced */}
      <div className="ccard__body">

        {/* Row 1: Name + location + status — dark inset container */}
        <div className="ccard__name-container">
          <header className="ccard__header">
            <div className="ccard__name-block">
              <p className="ccard__name" ref={nameRef}>
                <span className="ccard__marquee-inner">{displayName}</span>
              </p>
              {/* Sub-line always reserves its height — empty string keeps the space */}
              <p className="ccard__sub" ref={subRef}>
                <span className="ccard__marquee-inner">{subLine || '\u00A0'}</span>
              </p>
            </div>
            <div onClick={(e) => e.stopPropagation()}>
              <CardActions
                onView={onNavigate}
                onEdit={onEdit}
                onSendMail={() => setComposeOpen(true)}
                canEdit={canEdit}
              />
            </div>
          </header>
          {/* Status — inside container, separated by a small top gap */}
          <div className="ccard__status-primary">
            {renderMaskedIcon(statusInfo.icon, statusInfo.color, statusInfo.label, 16)}
            <span className="ccard__status-label" ref={statusRef} style={{ color: statusInfo.color }}>
              <span className="ccard__marquee-inner">{statusInfo.label}</span>
            </span>
          </div>
        </div>

        {/* Row 3: Tags — always reserves height, even if no tags */}
        <div className="ccard__tags">
          {tags.map((tag) => (
            <span key={tag} className="ccard__tag">{tag}</span>
          ))}
          {extraTags > 0 && (
            <span className="ccard__tag ccard__tag--more">+{extraTags}</span>
          )}
          {/* Reserve height when empty */}
          {tags.length === 0 && <span className="ccard__tag-placeholder" aria-hidden="true" />}
        </div>

        {/* Row 4: Footer — comm · issues · support — always rendered */}
        <div className="ccard__footer-row">
          {commMeta ? (
            <span className="ccard__footer-group">
              {renderMaskedIcon(commMeta.icon, commMeta.color, commMeta.label, 13)}
              <span className="ccard__footer-label" style={{ color: commMeta.color }}>{commMeta.label}</span>
              <span className="ccard__footer-time">{fmtRelative(latestComm.occurred_at)}</span>
            </span>
          ) : (
            <span className="ccard__no-comm">No comms yet</span>
          )}

          {issueCount > 0 && (
            <span className="ccard__footer-group">
              {renderMaskedIcon(exclamationIcon, 'var(--color-danger)', 'Issues', 13)}
              <span className="ccard__footer-label" style={{ color: 'var(--color-danger)' }}>
                {issueCount} issue{issueCount > 1 ? 's' : ''}
              </span>
              <span className="ccard__footer-time">{fmtRelative(summary.latest_issue_at)}</span>
            </span>
          )}

          {supportCount > 0 && (
            <span className="ccard__footer-group">
              {renderMaskedIcon(wrenchIcon, 'var(--color-warning)', 'Support', 13)}
              <span className="ccard__footer-label" style={{ color: 'var(--color-warning)' }}>
                {supportCount} support
              </span>
              <span className="ccard__footer-time">{fmtRelative(summary.latest_support_at)}</span>
            </span>
          )}
        </div>

      </div>
      </a>

      <ComposeEmailModal
        open={composeOpen}
        onClose={() => setComposeOpen(false)}
        defaultTo={primaryEmail}
        customerId={customer.id}
      />
    </>
  )
}

// ─── Skeleton card ────────────────────────────────────────────────────────────

function SkeletonCard() {
  return (
    <div className="ccard ccard--skeleton" aria-hidden="true">
      <div className="ccard__accent-wrap">
        <div className="ccard__accent-bar" style={{ backgroundColor: 'var(--color-bg-island)' }} />
      </div>
      <div className="ccard__body">
        <header className="ccard__header">
          <div className="ccard__name-block">
            <div className="skel-line" style={{ width: '72%', height: 22 }} />
            <div className="skel-line" style={{ width: '50%', height: 14, marginTop: 6 }} />
          </div>
          <div className="skel-circle" style={{ width: 28, height: 28 }} />
        </header>
        <div style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-2)' }}>
          <div className="skel-circle" style={{ width: 22, height: 22 }} />
          <div className="skel-line" style={{ width: 140, height: 18 }} />
        </div>
        <div style={{ display: 'flex', gap: 'var(--space-2)' }}>
          <div className="skel-line" style={{ width: 52, height: 22, borderRadius: 'var(--radius-full)' }} />
          <div className="skel-line" style={{ width: 68, height: 22, borderRadius: 'var(--radius-full)' }} />
          <div className="skel-line" style={{ width: 56, height: 22, borderRadius: 'var(--radius-full)' }} />
        </div>
        <div className="skel-line" style={{ width: '60%', height: 14 }} />
      </div>
    </div>
  )
}

// ─── CustomerListCardView (exported) ─────────────────────────────────────────

export default function CustomerListCardView({ customers, latestComms = {}, loading, canEdit, showTitles = true, onNavigate, onEdit }) {

  if (loading) {
    return (
      <>
        <style>{CARD_STYLES}</style>
        <div className="ccard-grid">
          {Array.from({ length: 12 }).map((_, i) => <SkeletonCard key={i} />)}
        </div>
      </>
    )
  }

  if (!customers.length) {
    return (
      <>
        <style>{CARD_STYLES}</style>
        <div className="ccard-empty">
          <Icon name="customers" size={36} color="var(--color-text-muted)" />
          <p className="ccard-empty__title">No customers found</p>
          <p className="ccard-empty__sub">Try adjusting your search or filters.</p>
        </div>
      </>
    )
  }

  return (
    <>
      <style>{CARD_STYLES}</style>
      <div className="ccard-grid">
        {customers.map((c) => (
          <CustomerCard
            key={c.id}
            customer={c}
            latestComm={latestComms[c.id] || null}
            canEdit={canEdit}
            showTitles={showTitles}
            onNavigate={() => onNavigate(c)}
            onEdit={() => onEdit(c)}
          />
        ))}
      </div>
    </>
  )
}

// ─── Styles ───────────────────────────────────────────────────────────────────

const CARD_STYLES = `

/* ── Grid ───────────────────────────────────────────────────────────────────── */
.ccard-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(500px, 1fr));
  gap: var(--space-4);
  align-items: flex-start;
}

/* ── Card shell ─────────────────────────────────────────────────────────────── */
.ccard {
  height: 250px;
  display: flex;
  flex-direction: row;
  background-color: rgba(28, 32, 38, 0.30);
  backdrop-filter: var(--blur-modal);
  -webkit-backdrop-filter: var(--blur-modal);
  border: 0px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card), var(--shadow-sm);
  cursor: pointer;
  transition: background-color 200ms ease, border-color 200ms ease,
              box-shadow 200ms ease, transform 200ms;
  overflow: hidden;
  user-select: none;
  outline: none;
  box-sizing: border-box;
  position: relative;
}
.ccard:hover {
  background-color: rgba(49, 53, 60, 0.50);
  border-color: var(--color-border-strong);
  box-shadow: var(--shadow-card), var(--shadow-md);
  transform: scale(1.03);
}
.ccard:focus-visible {
  border-color: var(--color-border-focus);
  box-shadow: var(--shadow-focus);
}
.ccard:active {
  transform: translateY(0) scale(1);
}

/* ── Watermark icon ─────────────────────────────────────────────────────────── */
.ccard__watermark {
  position: absolute;
  bottom: -20%;
  right: -30%;
  width: 100%;
  height: 100%;
  opacity: 0.02;
  pointer-events: none;
  z-index: 0;
  display: flex;
  align-items: flex-end;
  justify-content: flex-end;
}
.ccard__watermark svg {
  width: 100%;
  height: 100%;
}
.ccard > *:not(.ccard__watermark) {
  position: relative;
  z-index: 1;
}

/* ── Accent bar — vertical, left side ──────────────────────────────────────── */
.ccard__accent-wrap {
  padding: var(--space-6) 0 var(--space-6) var(--space-6);
  flex-shrink: 0;
  display: flex;
}
.ccard__accent-bar {
  width: 10px;
  border-radius: var(--radius-sm);
  transition: opacity 100ms ease;
  align-self: stretch;
}

/* ── Body — space-between so 4 rows spread evenly ──────────────────────────── */
.ccard__body {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding: var(--space-6) var(--space-6) var(--space-6);
  min-height: 0;
  overflow: hidden;
}

/* ── Name container — dark inset pill behind name + sub ─────────────────────── */
.ccard__name-container {
  background-color: rgba(0, 0, 0, 0.28);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4);
  margin: 0 calc(-1 * var(--space-1));
}

/* ── Header: name block + dots ─────────────────────────────────────────────── */
.ccard__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  min-width: 0;
}
.ccard__name-block {
  flex: 1;
  min-width: 0;
  overflow: hidden;
}
.ccard .ccard__name {
  font-family: var(--font-family-display);
  font-size: var(--font-size-xl);
  font-weight: var(--font-weight-bold);
  color: #ffffff;
  letter-spacing: var(--tracking-tight);
  line-height: 1.2;
  margin: 0;
  overflow: hidden;
}
.ccard .ccard__sub {
  font-family: var(--font-family-base);
  font-size: var(--font-size-md);
  font-weight: var(--font-weight-medium);
  color: var(--color-text-more-muted);
  margin: 0;
  margin-top: 3px;
  overflow: hidden;
  line-height: 1.4;
  min-height: 1.4em;
}

/* ── Marquee — scrolls text only when it actually overflows ─────────────────── */
.ccard__name,
.ccard__sub,
.ccard__status-label {
  white-space: nowrap;
}
@keyframes ccard-marquee {
  0%   { transform: translateX(0); }
  20%  { transform: translateX(0); }
  80%  { transform: translateX(var(--marquee-shift, -30%)); }
  100% { transform: translateX(var(--marquee-shift, -30%)); }
}
.ccard__marquee-inner {
  display: inline-block;
}
/* Animation only fires when JS detects overflow and sets data-overflow="true" on the wrapper */
.ccard__name[data-overflow="true"]:hover .ccard__marquee-inner,
.ccard__sub[data-overflow="true"]:hover .ccard__marquee-inner,
.ccard__status-label[data-overflow="true"]:hover .ccard__marquee-inner {
  animation: ccard-marquee 4s ease-in-out infinite alternate;
}

/* ── 3-dot button ───────────────────────────────────────────────────────────── */
.ccard__dots {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: var(--radius-full);
  background: none;
  border: none;
  color: var(--color-text-secondary);
  cursor: pointer;
  transition: background-color 120ms ease, color 120ms ease;
  padding: 0;
}
.ccard__dots:hover {
  background-color: rgba(255, 255, 255, 0.20);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.15);
  color: var(--color-text-primary);
}
.ccard__dots:focus-visible {
  outline: 2px solid var(--color-border-focus);
  outline-offset: 1px;
}

/* ── Status primary row ─────────────────────────────────────────────────────── */
.ccard__status-primary {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-width: 0;
  overflow: hidden;
  margin-top: var(--space-3);
  padding-top: var(--space-2);
  border-top: 1px solid rgba(255, 255, 255, 0.07);
}
.ccard__status-label {
  font-family: var(--font-family-display);
  font-size: var(--font-size-md);
  font-weight: var(--font-weight-semibold);
  line-height: 1.2;
  overflow: hidden;
  min-width: 0;
  flex: 1;
}

/* ── Tags row — always reserves its height ──────────────────────────────────── */
.ccard__tags {
  display: flex;
  flex-wrap: nowrap;
  gap: var(--space-2);
  overflow: hidden;
  min-height: 24px;
  align-items: center;
}
.ccard__tag {
  display: inline-flex;
  align-items: center;
  padding: 2px var(--space-2);
  font-family: var(--font-family-base);
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-medium);
  color: var(--color-text-secondary);
  background-color: var(--color-bg-elevated);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-full);
  line-height: 1.5;
  white-space: nowrap;
  flex-shrink: 0;
}
.ccard__tag--more {
  color: var(--color-text-muted);
  background-color: transparent;
  border-color: transparent;
}
.ccard__tag-placeholder {
  display: inline-block;
  height: 22px;
}

/* ── Footer row: comm · issues · support ────────────────────────────────────── */
.ccard__footer-row {
  display: flex;
  align-items: center;
  gap: var(--space-5);
  flex-shrink: 0;
  flex-wrap: nowrap;
  overflow: hidden;
  min-height: 18px;
}
.ccard__footer-group {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  flex-shrink: 0;
}
.ccard__footer-label {
  font-family: var(--font-family-base);
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-semibold);
  line-height: 1.4;
  white-space: nowrap;
}
.ccard__footer-time {
  font-family: var(--font-family-base);
  font-size: var(--font-size-xs);
  color: var(--color-text-muted);
  white-space: nowrap;
  line-height: 1.4;
}
.ccard__no-comm {
  font-family: var(--font-family-base);
  font-size: var(--font-size-xs);
  color: var(--color-text-muted);
  font-style: italic;
}

/* ── Actions dropdown ───────────────────────────────────────────────────────── */
.ccard-actions-menu {
  min-width: 140px;
  background-color: var(--color-bg-elevated);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  padding: var(--space-1) 0;
  overflow: hidden;
}
.ccard-actions-item {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  width: 100%;
  padding: var(--space-2) var(--space-3);
  font-family: var(--font-family-base);
  font-size: var(--font-size-sm);
  color: var(--color-text-secondary);
  background: none;
  border: none;
  cursor: pointer;
  text-align: left;
  transition: background-color 80ms ease, color 80ms ease;
}
.ccard-actions-item:hover {
  background-color: var(--color-bg-island);
  color: var(--color-text-primary);
}
.ccard-actions-item__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  opacity: 0.75;
}
.ccard-actions-item:hover .ccard-actions-item__icon {
  opacity: 1;
}

/* ── Empty state ────────────────────────────────────────────────────────────── */
.ccard-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  padding: var(--space-16) var(--space-8);
  text-align: center;
  width: 100%;
}
.ccard-empty__title {
  font-family: var(--font-family-base);
  font-size: var(--font-size-md);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-secondary);
  margin: 0;
}
.ccard-empty__sub {
  font-family: var(--font-family-base);
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
  margin: 0;
}

/* ── Skeleton shimmer ───────────────────────────────────────────────────────── */
.ccard--skeleton {
  cursor: default;
  pointer-events: none;
}
.skel-line,
.skel-circle {
  background: linear-gradient(
    90deg,
    var(--color-bg-elevated) 0%,
    var(--color-bg-island)   50%,
    var(--color-bg-elevated) 100%
  );
  background-size: 200% 100%;
  animation: skel-shimmer 1.4s ease-in-out infinite;
  border-radius: var(--radius-sm);
}
.skel-circle { border-radius: var(--radius-full); }
@keyframes skel-shimmer {
  0%   { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

/* ── Responsive ─────────────────────────────────────────────────────────────── */
@media (max-width: 768px) {
  .ccard-grid {
    grid-template-columns: 1fr;
    gap: var(--space-3);
  }
  .ccard { height: auto; min-height: 240px; }
}
`
