component Card {
  outputs {
    click(payload: { sourceEvent?: Event; [key: string]: string | number | boolean | null | object })
    action(payload: { sourceEvent?: Event; [key: string]: string | number | boolean | null | object })
    navigate(payload: { sourceEvent?: Event; [key: string]: string | number | boolean | null | object })
    dismiss(payload: { sourceEvent?: Event; [key: string]: string | number | boolean | null | object })
    load(payload: { sourceEvent?: Event; [key: string]: string | number | boolean | null | object })
    error(payload: { error: Error | string; sourceEvent?: Event; [key: string]: string | number | boolean | null | object } | Error | string)
  }

  props {
    title: string = "Card title"
    subtitle: string = ""
    description: string = ""
    header: string = ""
    footer: string = ""
    imageSrc: string = ""
    imageAlt: string = ""
    imagePosition: string = "top"
    actionLabel: string = ""
    actionHref: string = ""
    headerActions: unknown[] = []
    navigation: unknown[] = []
    activeNav: string = ""
    mobileNavigation: boolean = false
    alertTitle: string = ""
    alertDescription: string = ""
    empty: boolean = false
    emptyTitle: string = "No data to show"
    emptyIcon: string = "icon-[lucide--inbox]"
    items: unknown[] = []
    size: string = "md"
    color: string = "primary"
    variant: string = "default"
    layout: string = "vertical"
    align: string = "left"
    hover: string = "none"
    scrollable: boolean = false
    maxHeight: string = "18rem"
    dismissible: boolean = false
    ariaLabel: string = ""
    class: string = ""
  }

  state dismissed: boolean = false

  functions {
    // Outputs must go through output.*; a CustomEvent dispatched on the root
    // bubbles past every parent @binding without being seen, because the
    // runtime keeps parent handlers in a registry only the output proxy reads.
    client function dispatchCardNavigation(sourceEvent, item, index) {
      output.navigate({ component: "Card", item: item, index: index })
    }

    client function dispatchCardNavigationValue(sourceEvent) {
      output.navigate({
        component: "Card",
        value: sourceEvent.currentTarget.value
      })
    }

    client function dispatchCardHeaderAction(sourceEvent, action, index) {
      output.action({ component: "Card", action: action, index: index })
    }

    client function dismissCard() {
      dismissed = true
      output.dismiss({ component: "Card", title: title })
    }
  }

  view {
    <div
      {...attrs}
      data-ui-component="Card"
      data-wrn-card
      data-size='{size}'
      data-color='{color}'
      data-variant='{variant}'
      data-layout='{layout}'
      data-hover='{hover}'
      data-align='{align}'
      class='wrn-component wrn-next--card wrn-component--color-{color} wrn-component--size-{size} wrn-next--variant-{variant} {class}'
    >
      {#if items.length > 0}
        <div class="wrn-next__card-group">
          {#each items as item, itemIndex}
            <article
              class="wrn-next__card-panel"
              aria-label='{item.ariaLabel || item.title || item.label || "Card item"}'
              data-index='{itemIndex}'
            >
              {#if item.imageSrc || item.image}
                <div class="wrn-next__card-media">
                  <img
                    src='{item.imageSrc || item.image}'
                    alt='{item.imageAlt || item.alt || ""}'
                    loading='{item.loading || "lazy"}'
                    decoding="async"
                    @load='output.load({ item: item, index: itemIndex })'
                    @error='output.error({ item: item, index: itemIndex })'
                  />
                </div>
              {/if}

              <div class="wrn-next__card-content">
                {#if item.title || item.label}
                  <h3>{item.title || item.label}</h3>
                {/if}
                {#if item.subtitle}
                  <p class="wrn-next__card-subtitle">{item.subtitle}</p>
                {/if}
                {#if item.description}
                  <p class="wrn-next__card-description">{item.description}</p>
                {/if}
                {#if item.actionLabel || item.href}
                  <a
                    href='{item.actionHref || item.href || "#"}'
                    class="wrn-next__card-action"
                    @click='output.action({ item: item, index: itemIndex })'
                  >
                    <span>{item.actionLabel || "Learn more"}</span>
                    <span class="icon-[lucide--arrow-right]" aria-hidden="true"></span>
                  </a>
                {/if}
              </div>
            </article>
          {/each}
        </div>
      {:else}
        <article
          class="wrn-next__card-panel"
          aria-label='{ariaLabel || title || "Card"}'
          hidden='{dismissed}'
        >
          {#if imageSrc && imagePosition === "overlay"}
            <div class="wrn-next__card-overlay">
              <img
                src='{imageSrc}'
                alt='{imageAlt}'
                loading="lazy"
                decoding="async"
                @load='output.load({ src: imageSrc })'
                @error='output.error({ src: imageSrc })'
              />
              <div class="wrn-next__card-overlay-shade" aria-hidden="true"></div>
            </div>
          {/if}

          {#if imageSrc && (imagePosition === "top" || imagePosition === "left")}
            <div class="wrn-next__card-media wrn-next__card-media--{imagePosition}">
              <img
                src='{imageSrc}'
                alt='{imageAlt}'
                loading="lazy"
                decoding="async"
                @load='output.load({ src: imageSrc })'
                @error='output.error({ src: imageSrc })'
              />
            </div>
          {/if}

          <div class="wrn-next__card-content">
            {#if header || title || subtitle || headerActions.length > 0 || dismissible}
              <header class="wrn-next__card-header">
                <div class="wrn-next__card-heading">
                  {#if header}
                    <p class="wrn-next__card-eyebrow">{header}</p>
                  {/if}
                  {#if title}
                    <h3>{title}</h3>
                  {/if}
                  {#if subtitle}
                    <p class="wrn-next__card-subtitle">{subtitle}</p>
                  {/if}
                </div>

                {#if headerActions.length > 0 || dismissible}
                  <div class="wrn-next__card-header-actions">
                    {#each headerActions as headerAction, actionIndex}
                      <button
                        type="button"
                        aria-label='{headerAction.ariaLabel || headerAction.label || "Card action"}'
                        @click='dispatchCardHeaderAction(event, headerAction, actionIndex)'
                      >
                        {#if headerAction.icon}
                          <span class='{headerAction.icon}' aria-hidden="true"></span>
                        {/if}
                        {#if headerAction.label && !headerAction.icon}
                          <span>{headerAction.label}</span>
                        {/if}
                      </button>
                    {/each}

                    {#if dismissible}
                      <button
                        type="button"
                        aria-label="Dismiss card"
                        @click='dismissCard(event)'
                      >
                        <span class="icon-[lucide--x]" aria-hidden="true"></span>
                      </button>
                    {/if}
                  </div>
                {/if}
              </header>
            {/if}

            {#if navigation.length > 0}
              <nav aria-label='{ariaLabel || title || "Card navigation"}' class="wrn-next__card-navigation">
                {#if mobileNavigation}
                  <select
                    class="wrn-next__card-navigation-select"
                    aria-label='{ariaLabel || title || "Card navigation"}'
                    @change='dispatchCardNavigationValue(event)'
                  >
                    {#each navigation as navItem}
                      <option
                        value='{navItem.value || navItem.href || navItem.label}'
                        selected='{activeNav === navItem.value || activeNav === navItem.href}'
                      >
                        {navItem.label}
                      </option>
                    {/each}
                  </select>
                {/if}

                <div class="wrn-next__card-tabs" data-mobile-navigation='{mobileNavigation}'>
                  {#each navigation as navItem, navIndex}
                    <button
                      type="button"
                      aria-pressed='{activeNav === navItem.value || activeNav === navItem.href}'
                      @click='dispatchCardNavigation(event, navItem, navIndex)'
                    >
                      {#if navItem.icon}
                        <span class='{navItem.icon}' aria-hidden="true"></span>
                      {/if}
                      <span>{navItem.label}</span>
                      {#if navItem.badge}
                        <span class="wrn-next__card-tab-badge">{navItem.badge}</span>
                      {/if}
                    </button>
                  {/each}
                </div>
              </nav>
            {/if}

            {#if alertTitle || alertDescription}
              <div class="wrn-next__card-alert" role="status">
                {#if alertTitle}
                  <strong>{alertTitle}</strong>
                {/if}
                {#if alertDescription}
                  <p>{alertDescription}</p>
                {/if}
              </div>
            {/if}

            <div
              class="wrn-next__card-body"
              data-scrollable='{scrollable}'
              style='max-height: {scrollable ? maxHeight : "none"};'
            >
              {#if empty}
                <div class="wrn-next__card-empty">
                  <span class='{emptyIcon}' aria-hidden="true"></span>
                  <p>{emptyTitle}</p>
                </div>
              {:else}
                {#if description}
                  <p class="wrn-next__card-description">{description}</p>
                {/if}
                <slot></slot>
              {/if}
            </div>

            {#if footer || actionLabel}
              <footer class="wrn-next__card-footer">
                {#if footer}
                  <span>{footer}</span>
                {/if}
                {#if actionLabel}
                  <a
                    href='{actionHref || "#"}'
                    class="wrn-next__card-action"
                    @click='output.action({ href: actionHref, label: actionLabel })'
                  >
                    <span>{actionLabel}</span>
                    <span class="icon-[lucide--arrow-right]" aria-hidden="true"></span>
                  </a>
                {/if}
              </footer>
            {/if}
          </div>

          {#if imageSrc && (imagePosition === "bottom" || imagePosition === "right")}
            <div class="wrn-next__card-media wrn-next__card-media--{imagePosition}">
              <img
                src='{imageSrc}'
                alt='{imageAlt}'
                loading="lazy"
                decoding="async"
                @load='output.load({ src: imageSrc })'
                @error='output.error({ src: imageSrc })'
              />
            </div>
          {/if}
        </article>
      {/if}
    </div>
  }

  style {
    .wrn-next__card-media--overlay {
      aspect-ratio: 16 / 9;
      min-height: 18rem;
    }
    .wrn-next__card-media--overlay > img {
      position: absolute;
      inset: 0;
      width: 100%;
      height: 100%;
    }
    @media (max-width: 480px) {
      .wrn-next__card-media--overlay {
        aspect-ratio: 4 / 3;
        min-height: 16rem;
      }
    }

    .wrn-next--card {
      --wrn-card-color: var(--wrn-component-color, var(--wrn-color-primary));
      --wrn-card-padding: 1.25rem;
      display: block;
      width: 100%;
      color: var(--wrn-color-text);
    }

    .wrn-next--card[data-size="sm"] {
      --wrn-card-padding: 0.85rem;
    }

    .wrn-next--card[data-size="lg"] {
      --wrn-card-padding: 1.75rem;
    }

    .wrn-next__card-panel {
      position: relative;
      display: flex;
      overflow: hidden;
      flex-direction: column;
      width: 100%;
      min-width: 0;
      border: 1px solid var(--wrn-color-border);
      border-radius: var(--wrn-radius-md);
      background: var(--wrn-color-surface);
      box-shadow: var(--wrn-shadow-1);
      transition:
        transform var(--wrn-motion-base) var(--wrn-ease-emphasized),
        border-color var(--wrn-motion-base) ease,
        box-shadow var(--wrn-motion-base) var(--wrn-ease-emphasized);
    }

    .wrn-next--card[data-variant="top-border"] > .wrn-next__card-panel,
    .wrn-next--card[data-variant="accent"] > .wrn-next__card-panel {
      border-top: 4px solid var(--wrn-card-color);
    }

    .wrn-next--card[data-hover="raise"] > .wrn-next__card-panel:hover {
      border-color: color-mix(in srgb, var(--wrn-card-color) 38%, var(--wrn-color-border));
      box-shadow: var(--wrn-shadow-3);
      transform: translateY(-4px);
    }

    .wrn-next__card-header,
    .wrn-next__card-footer {
      display: flex;
      gap: 1rem;
      align-items: center;
      justify-content: space-between;
      padding: 0.85rem var(--wrn-card-padding);
      background: var(--wrn-color-surface-2);
      color: var(--wrn-color-muted);
      font-size: 0.875rem;
    }

    .wrn-next__card-header {
      border-bottom: 1px solid var(--wrn-color-border);
    }

    .wrn-next__card-footer {
      margin-top: auto;
      border-top: 1px solid var(--wrn-color-border);
    }

    .wrn-next__card-header-actions {
      display: inline-flex;
      gap: 0.2rem;
      align-items: center;
    }

    .wrn-next__card-header-actions button {
      display: inline-grid;
      width: 2rem;
      height: 2rem;
      border: 0;
      border-radius: var(--wrn-radius-sm);
      background: transparent;
      color: var(--wrn-color-muted);
      cursor: pointer;
      place-items: center;
    }

    .wrn-next__card-header-actions button:hover {
      background: color-mix(in srgb, var(--wrn-card-color) 12%, transparent);
      color: var(--wrn-card-color);
    }

    .wrn-next__card-header-actions button:focus-visible {
      outline: 2px solid var(--wrn-card-color);
      outline-offset: 1px;
    }

    .wrn-next__card-media {
      position: relative;
      overflow: hidden;
      min-height: 10rem;
      background: var(--wrn-color-surface-2);
    }

    .wrn-next__card-media > img {
      display: block;
      width: 100%;
      height: 100%;
      min-height: inherit;
      object-fit: cover;
      transition: transform 420ms var(--wrn-ease-emphasized);
    }

    .wrn-next--card[data-hover="image"] .wrn-next__card-panel:hover .wrn-next__card-media > img {
      transform: scale(1.06);
    }

    .wrn-next__card-overlay {
      position: absolute;
      inset: 0;
      display: flex;
      flex-direction: column;
      gap: 0.55rem;
      padding: clamp(1.25rem, 4vw, 2rem);
      background: linear-gradient(
        180deg,
        rgb(2 6 23 / 0.9) 0%,
        rgb(2 6 23 / 0.68) 38%,
        rgb(2 6 23 / 0.34) 58%,
        rgb(2 6 23 / 0.86) 100%
      );
      color: white;
      text-shadow: 0 1px 2px rgb(0 0 0 / 0.42);
    }

    .wrn-next__card-overlay h3 {
      color: white;
      font-size: clamp(1.1rem, 2.2vw, 1.35rem);
    }

    .wrn-next__card-overlay p {
      max-width: 48rem;
      color: #fff;
      font-weight: 500;
      line-height: 1.6;
      text-shadow:
        0 1px 2px rgb(0 0 0 / 0.9),
        0 2px 8px rgb(0 0 0 / 0.62);
    }

    .wrn-next__card-overlay .wrn-next__card-subtitle {
      color: rgb(255 255 255 / 0.78);
    }

    .wrn-next__card-overlay small {
      margin-top: auto;
      color: rgb(255 255 255 / 0.88);
      font-weight: 600;
      text-shadow: 0 1px 2px rgb(0 0 0 / 0.55);
    }

    .wrn-next__card-body {
      display: grid;
      gap: 0.65rem;
      min-width: 0;
      padding: var(--wrn-card-padding);
    }

    .wrn-next__card-body[data-scrollable="true"] {
      max-height: var(--wrn-card-max-height);
      overflow: auto;
      overscroll-behavior: contain;
      scrollbar-color: var(--wrn-card-color) transparent;
      scrollbar-width: thin;
    }

    .wrn-next__card-body h3,
    .wrn-next__card-body p,
    .wrn-next__card-overlay h3,
    .wrn-next__card-overlay p {
      margin: 0;
    }

    .wrn-next__card-body p {
      color: var(--wrn-color-muted);
      line-height: 1.65;
    }

    .wrn-next__card-subtitle {
      color: var(--wrn-color-muted);
      font-size: 0.72rem;
      font-weight: 700;
      letter-spacing: 0.06em;
      text-transform: uppercase;
    }

    .wrn-next__card-action {
      display: inline-flex;
      gap: 0.25rem;
      align-items: center;
      width: fit-content;
      margin-top: 0.2rem;
      color: var(--wrn-card-color);
      font-weight: 700;
      text-decoration: none;
    }

    .wrn-next__card-action:hover {
      text-decoration: underline;
      text-underline-offset: 0.2em;
    }

    .wrn-next__card-navigation {
      background: var(--wrn-color-surface-2);
    }

    .wrn-next__card-tabs {
      display: flex;
      overflow-x: auto;
    }

    .wrn-next__card-tabs button {
      min-height: 3rem;
      flex: 1 0 auto;
      padding-inline: 1rem;
      border: 0;
      border-bottom: 2px solid transparent;
      background: transparent;
      color: var(--wrn-color-muted);
      cursor: pointer;
      font-weight: 700;
    }

    .wrn-next__card-tabs button[data-active="true"] {
      border-color: var(--wrn-card-color);
      color: var(--wrn-color-text);
    }

    .wrn-next__card-navigation-select {
      display: none;
      width: calc(100% - 2rem);
      min-height: 2.75rem;
      margin: 1rem;
      border: 1px solid var(--wrn-color-border);
      border-radius: var(--wrn-radius-sm);
      background: var(--wrn-color-surface);
      color: var(--wrn-color-text);
    }

    .wrn-next__card-alert {
      display: flex;
      gap: 0.35rem;
      padding: 0.8rem var(--wrn-card-padding);
      background: color-mix(in srgb, var(--wrn-card-color) 14%, var(--wrn-color-surface-2));
      color: var(--wrn-color-text);
      font-size: 0.875rem;
    }

    .wrn-next__card-empty {
      display: grid;
      min-height: 12rem;
      color: var(--wrn-color-muted);
      place-content: center;
      place-items: center;
    }

    .wrn-next__card-empty > span {
      margin-bottom: 0.75rem;
      font-size: 2.25rem;
    }

    .wrn-next--card[data-align="center"] .wrn-next__card-body {
      text-align: center;
      place-items: center;
    }

    .wrn-next--card[data-layout="horizontal"] > .wrn-next__card-panel {
      display: grid;
      grid-template-columns: minmax(12rem, 42%) minmax(0, 1fr);
    }

    .wrn-next--card[data-layout="horizontal"] .wrn-next__card-media {
      grid-row: 1 / span 4;
      min-height: 100%;
    }

    .wrn-next__card-group {
      display: grid;
      grid-template-columns: repeat(var(--wrn-card-columns, 3), minmax(0, 1fr));
    }

    .wrn-next__card-group > .wrn-next__card-panel {
      border-radius: 0;
      box-shadow: none;
    }

    .wrn-next__card-group > .wrn-next__card-panel:not(:first-child) {
      margin-inline-start: -1px;
    }

    .wrn-next__card-group > .wrn-next__card-panel:first-child {
      border-start-start-radius: var(--wrn-radius-md);
      border-end-start-radius: var(--wrn-radius-md);
    }

    .wrn-next__card-group > .wrn-next__card-panel:last-child {
      border-start-end-radius: var(--wrn-radius-md);
      border-end-end-radius: var(--wrn-radius-md);
    }

    @media (max-width: 768px) {
    .wrn-next--card[data-layout="horizontal"] > .wrn-next__card-panel {
        display: flex;
      }
    .wrn-next--card[data-layout="horizontal"] .wrn-next__card-media {
        min-height: 12rem;
      }
    .wrn-next__card-group {
        grid-template-columns: 1fr;
      }
    .wrn-next__card-group > .wrn-next__card-panel:not(:first-child) {
        margin-top: -1px;
        margin-inline-start: 0;
      }
    .wrn-next__card-group > .wrn-next__card-panel {
        border-radius: 0;
      }
    .wrn-next__card-group > .wrn-next__card-panel:first-child {
        border-start-start-radius: var(--wrn-radius-md);
        border-start-end-radius: var(--wrn-radius-md);
      }
    .wrn-next__card-group > .wrn-next__card-panel:last-child {
        border-end-start-radius: var(--wrn-radius-md);
        border-end-end-radius: var(--wrn-radius-md);
      }
    }

    @media (max-width: 480px) {
    .wrn-next__card-tabs:has(+ .wrn-next__card-navigation-select) {
        display: none;
      }
    .wrn-next__card-navigation-select {
        display: block;
      }
    }

    /* Shared component foundation. */

        .wrn-component {
          --wrn-component-color: var(--wrn-color-primary);
          --wrn-component-scale: 1;
          margin: 0;
          color: var(--wrn-color-text);
          font-family: var(--wrn-font-sans, inherit);
        }

        .wrn-component--color-primary {
          --wrn-component-color: var(--wrn-color-primary);
        }

        .wrn-component--color-secondary {
          --wrn-component-color: var(--wrn-color-secondary);
        }

        .wrn-component--color-success {
          --wrn-component-color: var(--wrn-color-success);
        }

        .wrn-component--color-warning {
          --wrn-component-color: var(--wrn-color-warning);
        }

        .wrn-component--color-danger {
          --wrn-component-color: var(--wrn-color-danger);
        }

        .wrn-component--color-info {
          --wrn-component-color: var(--wrn-color-info);
        }

        .wrn-component--size-xs {
          --wrn-component-scale: 0.78;
        }

        .wrn-component--size-sm {
          --wrn-component-scale: 0.88;
        }

        .wrn-component--size-default,
        .wrn-component--size-md {
          --wrn-component-scale: 1;
        }

        .wrn-component--size-lg {
          --wrn-component-scale: 1.14;
        }

        .wrn-component--size-xl {
          --wrn-component-scale: 1.28;
        }

        .wrn-component:not(.wrn-btn) {
          font-size: calc(1em * var(--wrn-component-scale));
        }

        .wrn-component :is(a, button, input, select, textarea):focus-visible {
          outline-color: var(--wrn-component-color);
        }

        .wrn-component p {
          margin: 0;
          color: var(--wrn-color-muted);
          line-height: 1.6;
        }
  }
}
