/* eslint-disable @typescript-eslint/no-explicit-any */
import type { Config } from "@puckeditor/core";
import { MediaUploadField } from "@/components/editor/MediaUploadField";
import { IconPickerField } from "@/components/editor/IconPickerField";

// ─── Site-specific components (existing homepage sections) ──────────────────
import { NewsletterSection as SiteNewsletterSectionComponent } from "@/components/home/NewsletterSection";

// Editor previews for dynamic site components
import { SiteHeroSectionEditor } from "@/components/sections/SiteHeroSectionEditor";
import { SiteLatestArticlesEditor } from "@/components/sections/SiteLatestArticlesEditor";
import { SiteCategorySectionEditor as SiteAllCategorySectionsEditor } from "@/components/sections/SiteCategorySectionEditor";

// ─── Library components (copied from template) ──────────────────────────────
import { LibHeroSection } from "@/components/sections/LibHeroSection";
import { IconNavGrid } from "@/components/sections/IconNavGrid";
import { IntroSection } from "@/components/sections/IntroSection";
import { CategoryGrid } from "@/components/sections/CategoryGrid";
import { HighlightCards } from "@/components/sections/HighlightCards";
import { AppPromoSection } from "@/components/sections/AppPromoSection";
import { StepsTimeline } from "@/components/sections/StepsTimeline";
import { SectionHeading } from "@/components/sections/SectionHeading";
import { TextParagraph } from "@/components/sections/TextParagraph";
import { BannerCTA } from "@/components/sections/BannerCTA";
import { RankedTopList } from "@/components/sections/RankedTopList";
import { DataTable } from "@/components/sections/DataTable";
import { ComparisonTable } from "@/components/sections/ComparisonTable";
import { ProcessSteps } from "@/components/sections/ProcessSteps";
import { ReviewSection } from "@/components/sections/ReviewSection";
import { DetailedServiceCard } from "@/components/sections/DetailedServiceCard";
import { ServiceDetailBlock } from "@/components/sections/ServiceDetailBlock";

// Dynamic content editors (library)
import { BlogGridEditor } from "@/components/sections/BlogGridEditor";
import { AuthorBoxEditor } from "@/components/sections/AuthorBoxEditor";
import { ArticleGridTrendingRankingEditor } from "@/components/sections/ArticleGridTrendingRankingEditor";
import { ArticleGridCategorySectionsEditor } from "@/components/sections/ArticleGridCategorySectionsEditor";
import { FeaturedArticleHeroEditor } from "@/components/sections/FeaturedArticleHeroEditor";
import { HeroBlogCarouselEditor } from "@/components/sections/HeroBlogCarouselEditor";
import { HeroSlideCarouselEditor } from "@/components/sections/HeroSlideCarouselEditor";
import { TwoColumnLayoutEditor } from "@/components/sections/TwoColumnLayoutEditor";
import { FeaturedArticleSpotlightEditor } from "@/components/sections/FeaturedArticleSpotlightEditor";
import { BlogShowcaseGridEditor } from "@/components/sections/BlogShowcaseGridEditor";

// Client-side library components
import { Newsletter } from "@/components/sections/Newsletter";
import { NewsletterInline } from "@/components/sections/NewsletterInline";
import { AuthorProfileEditor } from "@/components/sections/AuthorProfileEditor";
import { HeroVideoCinematic } from "@/components/sections/HeroVideoCinematic";
import { FeaturesGrid } from "@/components/sections/FeaturesGrid";
import { LibTargetAudience } from "@/components/sections/LibTargetAudience";
import { CommonProblems } from "@/components/sections/CommonProblems";
import { Glossary } from "@/components/sections/Glossary";
import { ProcessFlow } from "@/components/sections/ProcessFlow";
import { SplitContentHero } from "@/components/sections/SplitContentHero";
import { HeroFullWidthSlider } from "@/components/sections/HeroFullWidthSlider";
import { ArticleCardCarousel } from "@/components/sections/ArticleCardCarousel";

// Generic building blocks
import { Spacer } from "@/components/sections/Spacer";
import { RichText } from "@/components/sections/RichText";
import { ImageBlock } from "@/components/sections/ImageBlock";
import { VideoEmbed } from "@/components/sections/VideoEmbed";
import { FAQ } from "@/components/sections/FAQ";
import { CTAButton } from "@/components/sections/CTAButton";
import { Divider } from "@/components/sections/Divider";
import { StickyNav } from "@/components/sections/StickyNav";
import { TableOfContents } from "@/components/sections/TableOfContents";

import { LINK_FIELDS } from "@/lib/puck/linkHelpers";

// Strip Puck internal props before passing to components
const PUCK_KEYS = new Set(['puck', 'editMode', 'id', 'renderDropZone', 'metadata', 'dragRef', 'isEditing']);
function stripPuck(props: any): any {
  const clean: any = {};
  for (const key of Object.keys(props)) {
    if (!PUCK_KEYS.has(key)) clean[key] = props[key];
  }
  return clean;
}

export const puckConfig: Config<any, any> = {
  categories: {
    // ─── SITE COMPONENTS (first in the list) ─────────────────────────
    "site-components": {
      title: "⭐ Site Components (Current Sections)",
      components: [
        "SiteHeroSection",
        "SiteLatestArticles",
        "SiteAllCategorySections",
        "SiteNewsletterSection",
      ],
    },
    // ─── LIBRARY CATEGORIES ───────────────────────────────────────────
    hero: {
      title: "Hero Sections",
      components: [
        "LibHeroSection", "HeroVideoCinematic", "HeroBlogCarousel",
        "HeroSlideCarousel", "HeroFullWidthSlider", "SplitContentHero",
        "FeaturedArticleHero", "FeaturedArticleSpotlight",
        "BlogShowcaseGrid", "ArticleCategorySections",
      ],
    },
    content: {
      title: "Content",
      components: [
        "SectionHeading", "IntroSection", "TextParagraph",
        "RichText", "ImageBlock", "VideoEmbed", "Glossary",
      ],
    },
    promotions: {
      title: "Promotions & CTA",
      components: ["BannerCTA", "CTAButton", "AppPromoSection"],
    },
    "cards-showcase": {
      title: "Cards & Showcase",
      components: [
        "HighlightCards", "FeaturesGrid", "LibTargetAudience",
        "CommonProblems", "CategoryGrid", "ArticleCardCarousel",
      ],
    },
    "lists-rankings": {
      title: "Lists & Rankings",
      components: ["RankedTopList", "ReviewSection", "DetailedServiceCard", "ServiceDetailBlock"],
    },
    tables: {
      title: "Tables",
      components: ["DataTable", "ComparisonTable"],
    },
    interactive: {
      title: "Interactive",
      components: ["ProcessSteps", "StepsTimeline", "ProcessFlow", "FAQ"],
    },
    navigation: {
      title: "Navigation",
      components: ["StickyNav", "TableOfContents", "IconNavGrid"],
    },
    "dynamic-content": {
      title: "Dynamic Content (Blog)",
      components: [
        "BlogGrid", "ArticleTrendingRanking",
        "AuthorBox", "AuthorProfile",
        "NewsletterFull", "NewsletterInline", "TwoColumnLayout",
      ],
    },
    layout: {
      title: "Layout Utilities",
      components: ["Spacer", "Divider"],
    },
  },

  components: {
    // ═══════════════════════════════════════════════════════════════════
    // SITE COMPONENTS — Wrappers for existing homepage sections
    // ═══════════════════════════════════════════════════════════════════

    SiteHeroSection: {
      label: "【Site】Hero Carousel",
      fields: {
        dataMode: {
          type: "radio",
          label: "Data Source",
          options: [
            { label: "Auto (latest from DB)", value: "auto" },
            { label: "Manual (enter items below)", value: "manual" },
          ],
        },
        count: {
          type: "number",
          label: "Number of Articles (Auto mode)",
          min: 1,
          max: 10,
        },
        autoRotateInterval: {
          type: "number",
          label: "Auto-rotate speed (ms)",
          min: 2000,
          max: 15000,
        },
        showExcerpt: {
          type: "radio",
          label: "Show Excerpt",
          options: [
            { label: "Yes", value: true },
            { label: "No", value: false },
          ],
        },
        manualItems: {
          type: "array",
          label: "Manual Carousel Items",
          arrayFields: {
            title: { type: "text", label: "Title" },
            excerpt: { type: "textarea", label: "Excerpt" },
            category: { type: "text", label: "Category" },
            image: {
              type: "custom",
              label: "Image",
              render: ({ value, onChange }: any) => (
                <MediaUploadField value={value || ''} onChange={onChange} accept="image" />
              ),
            },
            linkUrl: { type: "text", label: "Link URL" },
          },
          defaultItemProps: {
            title: "記事タイトル",
            excerpt: "",
            category: "",
            image: "",
            linkUrl: "/",
          },
        },
      },
      defaultProps: {
        dataMode: "auto",
        count: 5,
        autoRotateInterval: 5000,
        showExcerpt: true,
        manualItems: [],
      },
      render: (props: any) => <SiteHeroSectionEditor {...stripPuck(props)} />,
    },

    SiteLatestArticles: {
      label: "【Site】Latest Articles Carousel",
      fields: {
        count: {
          type: "number",
          label: "Article Count",
          min: 1,
          max: 20,
        },
      },
      defaultProps: { count: 12 },
      render: (props: any) => <SiteLatestArticlesEditor {...stripPuck(props)} />,
    },

    SiteAllCategorySections: {
      label: "【Site】All Category Sections",
      fields: {
        articlesPerCategory: {
          type: "number",
          label: "Articles Per Category",
          min: 1,
          max: 10,
        },
      },
      defaultProps: { articlesPerCategory: 4 },
      render: (props: any) => <SiteAllCategorySectionsEditor {...stripPuck(props)} />,
    },

    SiteNewsletterSection: {
      label: "【Site】Newsletter Section",
      fields: {
        title: { type: "text", label: "Heading" },
        description: { type: "textarea", label: "Description" },
        buttonText: { type: "text", label: "Button Text" },
        placeholder: { type: "text", label: "Input Placeholder" },
      },
      defaultProps: {
        title: "最新攻略情報をメールで受け取る",
        description: "新しい攻略記事やイベント情報を週1回お届けします。最新のゲーム情報をいち早くキャッチしましょう！",
        buttonText: "登録する",
        placeholder: "メールアドレスを入力",
      },
      render: (props: any) => <SiteNewsletterSectionComponent {...stripPuck(props)} />,
    },

    // ═══════════════════════════════════════════════════════════════════
    // LIBRARY COMPONENTS — Full 38-component library
    // ═══════════════════════════════════════════════════════════════════

    // ─── Hero & Banner ───────────────────────────────────────────────
    LibHeroSection: {
      label: "Hero Section (Full-screen)",
      fields: {
        tagline: { type: "text", label: "Tagline" },
        title: { type: "text", label: "Title" },
        subtitle: { type: "textarea", label: "Subtitle" },
        theme: {
          type: "select",
          label: "Design Theme",
          options: [
            { label: "Default (Brand)", value: "default" },
            { label: "Warm (Coral / Orange)", value: "warm" },
            { label: "Professional (Dark)", value: "professional" },
            { label: "Ocean (Blue / Indigo)", value: "ocean" },
            { label: "Forest (Green / Teal)", value: "forest" },
          ],
        },
        bgVideo: {
          type: "custom",
          label: "Background Video",
          render: ({ value, onChange }) => (
            <MediaUploadField value={value || ''} onChange={onChange} accept="video" />
          ),
        },
        bgImage: {
          type: "custom",
          label: "Background Image",
          render: ({ value, onChange }) => (
            <MediaUploadField value={value || ''} onChange={onChange} accept="image" />
          ),
        },
        mediaType: {
          type: "select",
          label: "Media Type",
          options: [
            { label: "Video", value: "video" },
            { label: "Image", value: "image" },
          ],
        },
        overlayOpacity: { type: "number", label: "Overlay Opacity (%)", min: 0, max: 100 },
        showScrollIndicator: {
          type: "radio",
          label: "Show Scroll Indicator",
          options: [{ label: "Yes", value: true }, { label: "No", value: false }],
        },
        bgColor: { type: "text", label: "Background Color (hex, e.g. #1e293b)" },
        bgGradientFrom: { type: "text", label: "Gradient Start Color (hex)" },
        bgGradientTo: { type: "text", label: "Gradient End Color (hex)" },
        bgGradientDirection: {
          type: "select",
          label: "Gradient Direction",
          options: [
            { label: "↘ Diagonal (to-br)", value: "to-br" },
            { label: "→ Right (to-r)", value: "to-r" },
            { label: "↓ Down (to-b)", value: "to-b" },
          ],
        },
        buttonText: { type: "text", label: "CTA Button Text" },
        buttonUrl: { type: "text", label: "CTA Button URL" },
        buttonStyle: {
          type: "select",
          label: "CTA Button Style",
          options: [
            { label: "Filled (white)", value: "filled" },
            { label: "Outlined", value: "outlined" },
            { label: "Ghost (underline)", value: "ghost" },
          ],
        },
      },
      defaultProps: {
        tagline: "最新の情報をお届け",
        title: "メディアタイトル",
        subtitle: "様々な情報や役立つコンテンツ、最新ニュースを定期的にお届けします。",
        bgVideo: "",
        bgImage: "",
        mediaType: "image",
        overlayOpacity: 40,
        bgColor: "",
        bgGradientFrom: "",
        bgGradientTo: "",
        bgGradientDirection: "to-br",
        buttonText: "",
        buttonUrl: "",
        buttonStyle: "filled",
        showScrollIndicator: true,
        theme: "default",
      },
      render: (props: any) => <LibHeroSection {...stripPuck(props)} />,
    },

    BannerCTA: {
      label: "Banner CTA",
      fields: {
        headline: { type: "text", label: "Headline" },
        description: { type: "textarea", label: "Description" },
        theme: {
          type: "select",
          label: "Design Theme",
          options: [
            { label: "Gradient (Brand Colors)", value: "gradient" },
            { label: "Solid (Dark / Gold)", value: "solid" },
            { label: "Outlined (Warm)", value: "outlined" },
            { label: "Ocean (Blue / Indigo)", value: "ocean" },
            { label: "Forest (Green / Teal)", value: "forest" },
          ],
        },
        ctaText: { type: "text", label: "Button Text" },
        ctaUrl: { type: "text", label: "Button URL" },
        bgImage: {
          type: "custom",
          label: "Background Image",
          render: ({ value, onChange }) => (
            <MediaUploadField value={value || ''} onChange={onChange} accept="image" />
          ),
        },
        openInNewTab: LINK_FIELDS.openInNewTab,
        relAttribute: LINK_FIELDS.relAttribute,
      },
      defaultProps: {
        headline: "今すぐ無料で始めましょう",
        description: "登録だけで入金不要ボーナスがもらえます。リスクゼロで実際のプレイを体験してみませんか？",
        ctaText: "無料登録する",
        ctaUrl: "#",
        bgImage: "",
        theme: "gradient",
        openInNewTab: "same",
        relAttribute: "follow",
      },
      render: (props: any) => <BannerCTA {...stripPuck(props)} />,
    },

    // ─── Content ─────────────────────────────────────────────────────
    IntroSection: {
      label: "Intro Section",
      fields: {
        title: { type: "text", label: "Title" },
        subtitle: { type: "textarea", label: "Subtitle" },
        body: { type: "textarea", label: "Body Text" },
        theme: {
          type: "select",
          label: "Design Theme",
          options: [
            { label: "Default (Brand)", value: "default" },
            { label: "Warm (Orange)", value: "warm" },
            { label: "Professional (Dark)", value: "professional" },
            { label: "Ocean (Blue / Indigo)", value: "ocean" },
            { label: "Forest (Green / Teal)", value: "forest" },
          ],
        },
        ctaText: { type: "text", label: "CTA Text" },
        ctaHref: { type: "text", label: "CTA Link" },
        showDivider: {
          type: "radio",
          label: "Show Divider",
          options: [{ label: "Yes", value: true }, { label: "No", value: false }],
        },
        openInNewTab: LINK_FIELDS.openInNewTab,
        relAttribute: LINK_FIELDS.relAttribute,
      },
      defaultProps: {
        title: "このサイトについて",
        subtitle: "情報メディアとして、初心者から経験者まで幅広いユーザーに向けて情報を提供します。",
        body: "様々なテーマに関する役立つ情報やガイド、レビューなどをわかりやすく解説。信頼できる情報をもとに、より安心して楽しむための知識を提供します。",
        ctaText: "最新情報を見る",
        ctaHref: "/blogs",
        showDivider: true,
        theme: "default",
        openInNewTab: "same",
        relAttribute: "follow",
      },
      render: (props: any) => <IntroSection {...stripPuck(props)} />,
    },

    TextParagraph: {
      label: "Text Block",
      fields: {
        heading: { type: "text", label: "Heading" },
        body: { type: "textarea", label: "Body Text" },
        style: {
          type: "select",
          label: "Style",
          options: [
            { label: "Default", value: "default" },
            { label: "Highlight", value: "highlight" },
            { label: "Card", value: "card" },
          ],
        },
        theme: {
          type: "select",
          label: "Design Theme",
          options: [
            { label: "Default (Brand)", value: "default" },
            { label: "Warm (Orange)", value: "warm" },
            { label: "Professional (Dark)", value: "professional" },
            { label: "Ocean (Blue / Indigo)", value: "ocean" },
            { label: "Forest (Green / Teal)", value: "forest" },
          ],
        },
      },
      defaultProps: {
        heading: "",
        body: "テキストを入力してください。",
        style: "default",
        theme: "default",
      },
      render: (props: any) => <TextParagraph {...stripPuck(props)} />,
    },

    SectionHeading: {
      label: "Section Heading",
      fields: {
        categoryLabel: { type: "text", label: "Category Label" },
        title: { type: "text", label: "Title" },
        subtitle: { type: "textarea", label: "Subtitle" },
        align: {
          type: "select",
          label: "Alignment",
          options: [
            { label: "Left", value: "left" },
            { label: "Center", value: "center" },
          ],
        },
        theme: {
          type: "select",
          label: "Design Theme",
          options: [
            { label: "Default (Brand)", value: "default" },
            { label: "Warm (Orange)", value: "warm" },
            { label: "Professional (Dark)", value: "professional" },
            { label: "Ocean (Blue / Indigo)", value: "ocean" },
            { label: "Forest (Green / Teal)", value: "forest" },
          ],
        },
        anchorId: { type: "text", label: "Section ID (for TOC/Nav anchor)" },
        buttonText: { type: "text", label: "CTA Button Text" },
        buttonUrl: { type: "text", label: "CTA Button URL" },
        buttonStyle: {
          type: "select",
          label: "CTA Button Style",
          options: [
            { label: "Filled", value: "filled" },
            { label: "Outlined", value: "outlined" },
            { label: "Ghost", value: "ghost" },
          ],
        },
      },
      defaultProps: {
        categoryLabel: "",
        title: "セクションタイトル",
        subtitle: "",
        align: "left",
        anchorId: "",
        buttonText: "",
        buttonUrl: "",
        buttonStyle: "filled",
        theme: "default",
      },
      render: (props: any) => <SectionHeading {...stripPuck(props)} />,
    },

    RichText: {
      label: "Rich Text",
      fields: {
        content: { type: "textarea", label: "Content (HTML supported)" },
        theme: {
          type: "select",
          label: "Design Theme",
          options: [
            { label: "Default", value: "default" },
            { label: "Warm (Orange)", value: "warm" },
            { label: "Professional (Dark)", value: "professional" },
            { label: "Ocean (Blue / Indigo)", value: "ocean" },
            { label: "Forest (Green / Teal)", value: "forest" },
          ],
        },
      },
      defaultProps: {
        content: "<p>リッチテキストコンテンツをここに入力してください。</p>",
        theme: "default",
      },
      render: (props: any) => <RichText {...stripPuck(props)} />,
    },

    ImageBlock: {
      label: "Image Block",
      fields: {
        src: {
          type: "custom",
          label: "Image",
          render: ({ value, onChange }) => (
            <MediaUploadField value={value || ''} onChange={onChange} accept="image" />
          ),
        },
        alt: { type: "text", label: "Alt Text" },
        caption: { type: "text", label: "Caption" },
        fullWidth: {
          type: "radio",
          label: "Width",
          options: [
            { label: "Container", value: false },
            { label: "Full Width", value: true },
          ],
        },
      },
      defaultProps: { src: "", alt: "", caption: "", fullWidth: false },
      render: (props: any) => <ImageBlock {...stripPuck(props)} />,
    },

    VideoEmbed: {
      label: "Video Embed",
      fields: {
        url: {
          type: "custom",
          label: "Video",
          render: ({ value, onChange }) => (
            <MediaUploadField value={value || ''} onChange={onChange} accept="video" />
          ),
        },
        title: { type: "text", label: "Title" },
        aspectRatio: {
          type: "select",
          label: "Aspect Ratio",
          options: [
            { label: "16:9", value: "16/9" },
            { label: "4:3", value: "4/3" },
            { label: "1:1", value: "1/1" },
          ],
        },
      },
      defaultProps: { url: "", title: "Video", aspectRatio: "16/9" },
      render: (props: any) => <VideoEmbed {...stripPuck(props)} />,
    },

    // ─── Lists & Rankings ────────────────────────────────────────────
    RankedTopList: {
      label: "Ranked List",
      fields: {
        sectionTitle: { type: "text", label: "Section Title" },
        sectionSubtitle: { type: "textarea", label: "Subtitle" },
        theme: {
          type: "select",
          label: "Design Theme",
          options: [
            { label: "Default (Brand Colors)", value: "default" },
            { label: "Warm (Coral / Orange)", value: "warm" },
            { label: "Professional (Dark / Gold)", value: "professional" },
            { label: "Ocean (Blue / Indigo)", value: "ocean" },
            { label: "Forest (Green / Teal)", value: "forest" },
          ],
        },
        items: {
          type: "array",
          label: "Ranked Items",
          arrayFields: {
            rank: { type: "number", label: "Rank (#)" },
            name: { type: "text", label: "Name" },
            logo: {
              type: "custom",
              label: "Logo",
              render: ({ value, onChange }: { value: string; onChange: (v: string) => void }) => (
                <MediaUploadField value={value || ''} onChange={onChange} accept="image" />
              ),
            },
            badge: { type: "text", label: "Badge Text" },
            rating: { type: "number", label: "Rating (1-5)", min: 1, max: 5 },
            bonusLabel: { type: "text", label: "Bonus Label" },
            bonusValue: { type: "text", label: "Bonus Value" },
            wageringLabel: { type: "text", label: "Spec 1 Label" },
            wageringValue: { type: "text", label: "Spec 1 Value" },
            maxWithdrawalLabel: { type: "text", label: "Spec 2 Label" },
            maxWithdrawalValue: { type: "text", label: "Spec 2 Value" },
            validityLabel: { type: "text", label: "Spec 3 Label" },
            validityValue: { type: "text", label: "Spec 3 Value" },
            licenseLabel: { type: "text", label: "Spec 4 Label" },
            licenseValue: { type: "text", label: "Spec 4 Value" },
            ctaText: { type: "text", label: "CTA Button Text" },
            ctaUrl: { type: "text", label: "CTA URL" },
            ctaMicroCopy: { type: "text", label: "CTA Micro Copy" },
            reviewLinkText: { type: "text", label: "Review Link Text" },
            pros: { type: "textarea", label: "Pros (one per line)" },
            cons: { type: "textarea", label: "Cons (one per line)" },
            detailSpecs: { type: "textarea", label: "Detail Specs (label: value per line)" },
            editorialReview: { type: "textarea", label: "Editorial Review" },
            reviewerName: { type: "text", label: "Reviewer Name" },
            reviewerAvatar: {
              type: "custom",
              label: "Reviewer Avatar",
              render: ({ value, onChange }: { value: string; onChange: (v: string) => void }) => (
                <MediaUploadField value={value || ''} onChange={onChange} accept="image" />
              ),
            },
          },
        },
        openInNewTab: LINK_FIELDS.openInNewTab,
        relAttribute: LINK_FIELDS.relAttribute,
      },
      defaultProps: {
        sectionTitle: "おすすめランキング",
        sectionSubtitle: "",
        theme: "default",
        items: [],
        openInNewTab: "new",
        relAttribute: "sponsored",
      },
      render: (props: any) => <RankedTopList {...stripPuck(props)} forceExpanded={!!props.puck} />,
    },

    ReviewSection: {
      label: "Review Section",
      fields: {
        sectionTitle: { type: "text", label: "Section Title" },
        sectionSubtitle: { type: "textarea", label: "Subtitle" },
        theme: {
          type: "select",
          label: "Design Theme",
          options: [
            { label: "Default (Brand Colors)", value: "default" },
            { label: "Magazine (Warm Colors)", value: "magazine" },
            { label: "Compact (Slate/Dark)", value: "compact" },
            { label: "Ocean (Blue / Indigo)", value: "ocean" },
            { label: "Forest (Green / Teal)", value: "forest" },
          ],
        },
        items: {
          type: "array",
          label: "Review Items",
          arrayFields: {
            rank: { type: "number", label: "Rank (#)" },
            name: { type: "text", label: "Name" },
            logo: {
              type: "custom",
              label: "Logo",
              render: ({ value, onChange }: { value: string; onChange: (v: string) => void }) => (
                <MediaUploadField value={value || ''} onChange={onChange} accept="image" />
              ),
            },
            tagline: { type: "text", label: "Tagline" },
            description: { type: "textarea", label: "Description" },
            specs: { type: "textarea", label: "Specs (label: value per line)" },
            pros: { type: "textarea", label: "Pros (one per line)" },
            cons: { type: "textarea", label: "Cons (one per line)" },
            editorialSummary: { type: "textarea", label: "Editorial Summary" },
            primaryCtaText: { type: "text", label: "Primary CTA Text" },
            primaryCtaUrl: { type: "text", label: "Primary CTA URL" },
            secondaryCtaText: { type: "text", label: "Secondary CTA Text" },
            secondaryCtaUrl: { type: "text", label: "Secondary CTA URL" },
          },
        },
        openInNewTab: LINK_FIELDS.openInNewTab,
        relAttribute: LINK_FIELDS.relAttribute,
      },
      defaultProps: {
        sectionTitle: "詳細レビュー",
        sectionSubtitle: "",
        theme: "default",
        items: [],
        openInNewTab: "new",
        relAttribute: "sponsored",
      },
      render: (props: any) => <ReviewSection {...stripPuck(props)} />,
    },

    DetailedServiceCard: {
      label: "Detailed Service Card",
      fields: {
        theme: {
          type: "select",
          label: "Design Theme",
          options: [
            { label: "Default (Green)", value: "default" },
            { label: "Warm (Orange)", value: "warm" },
            { label: "Professional (Dark)", value: "professional" },
            { label: "Ocean (Blue / Indigo)", value: "ocean" },
            { label: "Forest (Green / Teal)", value: "forest" },
          ],
        },
        rank: { type: "number", label: "Rank Position", min: 1 },
        name: { type: "text", label: "Service Name" },
        tagline: { type: "text", label: "Tagline (header bar)" },
        logo: {
          type: "custom",
          label: "Logo / Banner Image",
          render: ({ value, onChange }: any) => (
            <MediaUploadField value={value || ''} onChange={onChange} accept="image" />
          ),
        },
        overallRating: { type: "number", label: "Overall Rating (0-5)", min: 0, max: 5 },
        bonusTitle: { type: "text", label: "Bonus Section Title" },
        bonusAmount: { type: "text", label: "Bonus Amount" },
        bonusCondition: { type: "text", label: "Withdrawal Condition" },
        bonusSpeed: { type: "text", label: "Processing Speed" },
        bonusCode: { type: "text", label: "Bonus Code" },
        features: { type: "textarea", label: "Features (one per line)" },
        primaryCtaText: { type: "text", label: "Primary CTA Text" },
        primaryCtaUrl: { type: "text", label: "Primary CTA URL" },
        secondaryCtaText: { type: "text", label: "Secondary Link Text" },
        secondaryCtaUrl: { type: "text", label: "Secondary Link URL" },
        expertTitle: { type: "text", label: "Expert Review Title" },
        expertDescription: { type: "textarea", label: "Expert Review Text" },
        expertAuthor: { type: "text", label: "Expert Author Name" },
        radarLabels: { type: "textarea", label: "Radar Chart Labels (one per line)" },
        radarValues: { type: "textarea", label: "Radar Chart Values (one per line, 0-5)" },
        trustStatus: { type: "text", label: "Trust Status Text" },
        licenseRating: { type: "number", label: "License Rating (0-5)", min: 0, max: 5 },
        licenseName: { type: "text", label: "License Name" },
        gameTypes: { type: "textarea", label: "Game Types (comma-separated)" },
        paymentMethods: { type: "textarea", label: "Payment Methods (comma-separated)" },
        supportInfo: { type: "textarea", label: "Support Info (one per line)" },
        serviceBadges: { type: "textarea", label: "Service Badges (comma-separated)" },
        openInNewTab: LINK_FIELDS.openInNewTab,
        relAttribute: LINK_FIELDS.relAttribute,
      },
      defaultProps: {
        theme: "default", rank: 1, name: "サービス名", tagline: "限定ボーナス情報", logo: "",
        overallRating: 4.6, bonusTitle: "当サイト限定ボーナス", bonusAmount: "入金不要ボーナス",
        bonusCondition: "1倍", bonusSpeed: "即時", bonusCode: "",
        features: "業界最高水準のキャッシュバック\n豊富なゲームラインナップ",
        primaryCtaText: "公式サイトを見る", primaryCtaUrl: "#",
        secondaryCtaText: "", secondaryCtaUrl: "#",
        expertTitle: "専門家のレビュー", expertDescription: "", expertAuthor: "",
        radarLabels: "信頼度\nウェルカムボーナス\n決済サービス\nプレイヤー還元\nゲームの種類\nカスタマーサポート",
        radarValues: "5\n4.4\n5\n3.8\n4.2\n5",
        trustStatus: "信頼できる運営会社", licenseRating: 4, licenseName: "",
        gameTypes: "", paymentMethods: "", supportInfo: "", serviceBadges: "",
        openInNewTab: "new", relAttribute: "sponsored",
      },
      render: (props: any) => <DetailedServiceCard {...stripPuck(props)} forceExpanded={!!props.puck} />,
    },

    ServiceDetailBlock: {
      label: "Service Detail Block",
      fields: {
        theme: {
          type: "select",
          label: "Design Theme",
          options: [
            { label: "Default (Green)", value: "default" },
            { label: "Warm (Orange)", value: "warm" },
            { label: "Professional (Dark)", value: "professional" },
            { label: "Ocean (Blue / Indigo)", value: "ocean" },
            { label: "Forest (Green / Teal)", value: "forest" },
          ],
        },
        name: { type: "text", label: "Service Name" },
        screenshot: {
          type: "custom",
          label: "Screenshot Image",
          render: ({ value, onChange }: any) => (
            <MediaUploadField value={value || ''} onChange={onChange} accept="image" />
          ),
        },
        overallRating: { type: "number", label: "Overall Rating (0-5)", min: 0, max: 5 },
        overallLabel: { type: "text", label: "Overall Label" },
        ratingCategories: { type: "textarea", label: "Ratings (format: Label: N, one per line)" },
        radarLabels: { type: "textarea", label: "Radar Labels (one per line)" },
        radarValues: { type: "textarea", label: "Radar Values (one per line, 0-5)" },
        description: { type: "textarea", label: "Description" },
        authorName: { type: "text", label: "Author Name" },
        authorImpression: { type: "textarea", label: "Author Impression" },
        pros: { type: "textarea", label: "Pros (one per line)" },
        cons: { type: "textarea", label: "Cons (one per line)" },
        ctaText: { type: "text", label: "CTA Button Text" },
        ctaUrl: { type: "text", label: "CTA Button URL" },
        openInNewTab: LINK_FIELDS.openInNewTab,
        relAttribute: LINK_FIELDS.relAttribute,
      },
      defaultProps: {
        theme: "default", name: "サービス名", screenshot: "",
        overallRating: 4, overallLabel: "総合評価：★4 おすすめ",
        ratingCategories: "初期ボーナス: 3\n決済サービス: 5\nプレイヤー還元: 5\nゲームの種類: 5\nサポート: 4\n信頼度: 4",
        radarLabels: "ボーナスの充実\n決済方法の豊富さ\nプレイヤー還元\nゲームセレクション\nカスタマーサポート",
        radarValues: "4\n5\n5\n4.5\n4",
        description: "", authorName: "編集部", authorImpression: "",
        pros: "", cons: "", ctaText: "", ctaUrl: "#",
        openInNewTab: "new", relAttribute: "sponsored",
      },
      render: (props: any) => <ServiceDetailBlock {...stripPuck(props)} />,
    },

    // ─── Tables ──────────────────────────────────────────────────────
    DataTable: {
      label: "Data Table",
      fields: {
        sectionTitle: { type: "text", label: "Title" },
        theme: {
          type: "select",
          label: "Design Theme",
          options: [
            { label: "Default (Brand Colors)", value: "default" },
            { label: "Striped (Indigo)", value: "striped" },
            { label: "Minimal (Clean)", value: "minimal" },
            { label: "Ocean (Blue / Indigo)", value: "ocean" },
            { label: "Forest (Green / Teal)", value: "forest" },
          ],
        },
        scrollable: {
          type: "radio",
          label: "Scrollable",
          options: [{ label: "Enabled", value: true }, { label: "Disabled", value: false }],
        },
        columns: {
          type: "array",
          label: "Columns",
          arrayFields: {
            label: { type: "text", label: "Header Label" },
            align: {
              type: "select",
              label: "Alignment",
              options: [{ label: "Left", value: "left" }, { label: "Center", value: "center" }, { label: "Right", value: "right" }],
            },
            highlight: {
              type: "radio",
              label: "Highlight",
              options: [{ label: "Yes", value: true }, { label: "No", value: false }],
            },
          },
        },
        rows: {
          type: "array",
          label: "Rows",
          arrayFields: {
            col1: { type: "text", label: "Column 1 Value" },
            col2: { type: "text", label: "Column 2 Value" },
            col3: { type: "text", label: "Column 3 Value" },
            col4: { type: "text", label: "Column 4 Value" },
            col5: { type: "text", label: "Column 5 Value" },
            col6: { type: "text", label: "Column 6 Value" },
          },
        },
      },
      defaultProps: {
        sectionTitle: "比較データ",
        scrollable: true,
        theme: "default",
        columns: [],
        rows: [],
      },
      render: (props: any) => <DataTable {...stripPuck(props)} />,
    },

    ComparisonTable: {
      label: "Comparison Table",
      fields: {
        sectionTitle: { type: "text", label: "Title" },
        sectionSubtitle: { type: "textarea", label: "Subtitle" },
        theme: {
          type: "select",
          label: "Design Theme",
          options: [
            { label: "Default (Brand Colors)", value: "default" },
            { label: "Cards (Warm/Orange)", value: "cards" },
            { label: "Compact (Dark Slate)", value: "compact" },
            { label: "Ocean (Blue / Indigo)", value: "ocean" },
            { label: "Forest (Green / Teal)", value: "forest" },
          ],
        },
        itemsPerPage: { type: "number", label: "Items Per Page", min: 1, max: 10 },
        attributes: {
          type: "array",
          label: "Comparison Attributes (rows)",
          arrayFields: { label: { type: "text", label: "Attribute Label" } },
        },
        items: {
          type: "array",
          label: "Compared Items (columns)",
          arrayFields: {
            name: { type: "text", label: "Name" },
            logo: {
              type: "custom",
              label: "Logo",
              render: ({ value, onChange }: { value: string; onChange: (v: string) => void }) => (
                <MediaUploadField value={value || ''} onChange={onChange} accept="image" />
              ),
            },
            rank: { type: "number", label: "Rank" },
            rating: { type: "number", label: "Rating (1-5)", min: 1, max: 5 },
            ctaText: { type: "text", label: "CTA Text" },
            ctaUrl: { type: "text", label: "CTA URL" },
            attr1: { type: "text", label: "Attribute 1 Value" },
            attr2: { type: "text", label: "Attribute 2 Value" },
            attr3: { type: "text", label: "Attribute 3 Value" },
            attr4: { type: "text", label: "Attribute 4 Value" },
            attr5: { type: "text", label: "Attribute 5 Value" },
            attr6: { type: "text", label: "Attribute 6 Value" },
            attr7: { type: "text", label: "Attribute 7 Value" },
            attr8: { type: "text", label: "Attribute 8 Value" },
          },
        },
        openInNewTab: LINK_FIELDS.openInNewTab,
        relAttribute: LINK_FIELDS.relAttribute,
      },
      defaultProps: {
        sectionTitle: "比較表",
        sectionSubtitle: "",
        itemsPerPage: 5,
        theme: "default",
        attributes: [],
        items: [],
        openInNewTab: "new",
        relAttribute: "sponsored",
      },
      render: (props: any) => <ComparisonTable {...stripPuck(props)} />,
    },

    // ─── Interactive ─────────────────────────────────────────────────
    ProcessSteps: {
      label: "Process Steps",
      fields: {
        sectionTitle: { type: "text", label: "Title" },
        sectionSubtitle: { type: "textarea", label: "Subtitle" },
        theme: {
          type: "select",
          label: "Design Theme",
          options: [
            { label: "Default (Brand Colors)", value: "default" },
            { label: "Timeline (Indigo)", value: "timeline" },
            { label: "Gradient (Warm)", value: "gradient" },
            { label: "Ocean (Blue / Indigo)", value: "ocean" },
            { label: "Forest (Green / Teal)", value: "forest" },
          ],
        },
        columns: {
          type: "select",
          label: "Columns",
          options: [
            { label: "2 Columns", value: 2 },
            { label: "3 Columns", value: 3 },
            { label: "4 Columns", value: 4 },
          ],
        },
        steps: {
          type: "array",
          label: "Steps",
          arrayFields: {
            number: { type: "text", label: "Step Number" },
            icon: {
              type: "custom",
              label: "Icon",
              render: ({ value, onChange }: { value: string; onChange: (v: string) => void }) => (
                <IconPickerField value={value || ''} onChange={onChange} />
              ),
            },
            title: { type: "text", label: "Title" },
            description: { type: "textarea", label: "Description" },
          },
        },
      },
      defaultProps: {
        sectionTitle: "ステップガイド",
        sectionSubtitle: "",
        columns: 3,
        theme: "default",
        steps: [
          { number: "01", icon: "shield", title: "安全性を確認", description: "まずはライセンスと信頼性を確認しましょう。" },
          { number: "02", icon: "star", title: "サービスを比較", description: "特典や条件を比較して最適なサービスを選びます。" },
          { number: "03", icon: "zap", title: "実践開始", description: "知識を活かして実際にスタートしましょう。" },
        ],
      },
      render: (props: any) => <ProcessSteps {...stripPuck(props)} />,
    },

    StepsTimeline: {
      label: "Steps Timeline",
      fields: {
        title: { type: "text", label: "Title" },
        subtitle: { type: "textarea", label: "Subtitle" },
        theme: {
          type: "select",
          label: "Design Theme",
          options: [
            { label: "Default (Brand)", value: "default" },
            { label: "Warm (Orange)", value: "warm" },
            { label: "Professional (Dark)", value: "professional" },
            { label: "Ocean (Blue / Indigo)", value: "ocean" },
            { label: "Forest (Green / Teal)", value: "forest" },
          ],
        },
        steps: {
          type: "array",
          label: "Steps",
          arrayFields: {
            title: { type: "text", label: "Step Title" },
            description: { type: "textarea", label: "Description" },
          },
        },
      },
      defaultProps: {
        title: "オンラインカジノを始める3ステップ",
        subtitle: "初めての方でも安心して始められます。",
        theme: "default",
        steps: [
          { title: "情報収集", description: "まずは本サイトで安全なカジノの選び方を学びましょう。" },
          { title: "登録・ボーナス獲得", description: "信頼性の高いカジノに登録してウェルカムボーナスを受け取りましょう。" },
          { title: "ゲームスタート", description: "少額から始めて楽しみながらゲームを覚えていきましょう。" },
        ],
      },
      render: (props: any) => <StepsTimeline {...stripPuck(props)} />,
    },

    FAQ: {
      label: "FAQ",
      fields: {
        title: { type: "text", label: "Title" },
        theme: {
          type: "select",
          label: "Design Theme",
          options: [
            { label: "Default (Cards)", value: "default" },
            { label: "Minimal (Dividers)", value: "minimal" },
            { label: "Boxed (Warm Colors)", value: "boxed" },
            { label: "Ocean (Blue / Indigo)", value: "ocean" },
            { label: "Forest (Green / Teal)", value: "forest" },
          ],
        },
        items: {
          type: "array",
          label: "Questions",
          arrayFields: {
            question: { type: "text", label: "Question" },
            answer: { type: "textarea", label: "Answer" },
          },
        },
      },
      defaultProps: {
        title: "よくある質問",
        theme: "default",
        items: [
          { question: "オンラインカジノは日本で合法ですか？", answer: "日本にはオンラインカジノを直接規制する法律はありません。海外にサーバーを置くカジノは法的グレーゾーンにあります。" },
        ],
      },
      render: (props: any) => <FAQ {...stripPuck(props)} />,
    },

    CTAButton: {
      label: "CTA Button",
      fields: {
        text: { type: "text", label: "Button Text" },
        href: { type: "text", label: "Link URL" },
        variant: {
          type: "select",
          label: "Style",
          options: [
            { label: "Primary", value: "primary" },
            { label: "Secondary", value: "secondary" },
            { label: "Outline", value: "outline" },
          ],
        },
        align: {
          type: "select",
          label: "Alignment",
          options: [
            { label: "Left", value: "left" },
            { label: "Center", value: "center" },
            { label: "Right", value: "right" },
          ],
        },
        showArrow: {
          type: "radio",
          label: "Show Arrow",
          options: [{ label: "Yes", value: true }, { label: "No", value: false }],
        },
        theme: {
          type: "select",
          label: "Design Theme",
          options: [
            { label: "Default (Brand)", value: "default" },
            { label: "Warm (Orange)", value: "warm" },
            { label: "Professional (Dark)", value: "professional" },
            { label: "Ocean (Blue / Indigo)", value: "ocean" },
            { label: "Forest (Green / Teal)", value: "forest" },
          ],
        },
        openInNewTab: LINK_FIELDS.openInNewTab,
        relAttribute: LINK_FIELDS.relAttribute,
      },
      defaultProps: {
        text: "もっと詳しく",
        href: "#",
        variant: "primary",
        align: "center",
        showArrow: true,
        theme: "default",
        openInNewTab: "same",
        relAttribute: "follow",
      },
      render: (props: any) => <CTAButton {...stripPuck(props)} />,
    },

    IconNavGrid: {
      label: "Icon Nav Grid",
      fields: {
        theme: {
          type: "select",
          label: "Design Theme",
          options: [
            { label: "Default (Brand)", value: "default" },
            { label: "Warm (Orange)", value: "warm" },
            { label: "Professional (Dark)", value: "professional" },
            { label: "Ocean (Blue / Indigo)", value: "ocean" },
            { label: "Forest (Green / Teal)", value: "forest" },
          ],
        },
        items: {
          type: "array",
          label: "Nav Items",
          arrayFields: {
            label: { type: "text", label: "Label" },
            href: { type: "text", label: "Link URL" },
            iconName: {
              type: "custom",
              label: "Icon",
              render: ({ value, onChange }: { value: string; onChange: (v: string) => void }) => (
                <IconPickerField value={value || ''} onChange={onChange} />
              ),
            },
          },
        },
        openInNewTab: LINK_FIELDS.openInNewTab,
        relAttribute: LINK_FIELDS.relAttribute,
      },
      defaultProps: {
        items: [
          { label: "最新記事", href: "/blogs", iconName: "newspaper" },
          { label: "ボーナス情報", href: "/category/ボーナス", iconName: "gift" },
          { label: "ガイド", href: "/category/ガイド", iconName: "book-open" },
          { label: "お問い合わせ", href: "/contact", iconName: "mail" },
        ],
        theme: "default",
        openInNewTab: "same",
        relAttribute: "follow",
      },
      render: (props: any) => <IconNavGrid {...stripPuck(props)} />,
    },

    // ─── Dynamic Content ─────────────────────────────────────────────
    BlogGrid: {
      label: "Blog Post Grid",
      fields: {
        title: { type: "text", label: "Title" },
        count: { type: "number", label: "Post Count (Auto Mode)", min: 1, max: 12 },
        columns: {
          type: "select",
          label: "Columns",
          options: [
            { label: "2 Columns", value: 2 },
            { label: "3 Columns", value: 3 },
            { label: "4 Columns", value: 4 },
          ],
        },
        dataMode: {
          type: "select", label: "Data Source",
          options: [
            { label: "Auto (from Database)", value: "auto" },
            { label: "Manual (enter items below)", value: "manual" },
          ],
        },
        manualItems: {
          type: "array",
          label: "Manual Items",
          arrayFields: {
            title: { type: "text", label: "Title" },
            image: {
              type: "custom", label: "Image",
              render: ({ value, onChange }: any) => (
                <MediaUploadField value={value || ''} onChange={onChange} accept="image" />
              ),
            },
            linkUrl: { type: "text", label: "Link URL" },
            category: { type: "text", label: "Category" },
            author: { type: "text", label: "Author" },
          },
        },
      },
      defaultProps: {
        title: "最新記事",
        count: 4,
        columns: 2,
        dataMode: "auto",
        manualItems: [],
      },
      render: (props: any) => <BlogGridEditor {...stripPuck(props)} />,
    },

    AuthorBox: {
      label: "Author Profile (DB)",
      fields: {
        authorSlug: { type: "text", label: "Author Name (leave empty for default)" },
        showBio: {
          type: "radio",
          label: "Show Bio",
          options: [{ label: "Show", value: true }, { label: "Hide", value: false }],
        },
      },
      defaultProps: { authorSlug: "", showBio: true },
      render: (props: any) => <AuthorBoxEditor {...stripPuck(props)} />,
    },

    // ─── Cards & Showcase ─────────────────────────────────────────────
    CategoryGrid: {
      label: "Category Grid",
      fields: {
        title: { type: "text", label: "Title" },
        subtitle: { type: "textarea", label: "Subtitle" },
        theme: {
          type: "select",
          label: "Design Theme",
          options: [
            { label: "Default (Brand)", value: "default" },
            { label: "Warm (Orange)", value: "warm" },
            { label: "Professional (Dark)", value: "professional" },
            { label: "Ocean (Blue / Indigo)", value: "ocean" },
            { label: "Forest (Green / Teal)", value: "forest" },
          ],
        },
        items: {
          type: "array",
          label: "Categories",
          arrayFields: {
            label: { type: "text", label: "Label" },
            href: { type: "text", label: "Link URL" },
            iconName: {
              type: "custom",
              label: "Icon",
              render: ({ value, onChange }: { value: string; onChange: (v: string) => void }) => (
                <IconPickerField value={value || ''} onChange={onChange} />
              ),
            },
          },
        },
        openInNewTab: LINK_FIELDS.openInNewTab,
        relAttribute: LINK_FIELDS.relAttribute,
        buttonText: { type: "text", label: "CTA Button Text" },
        buttonUrl: { type: "text", label: "CTA Button URL" },
        buttonStyle: {
          type: "select",
          label: "CTA Button Style",
          options: [
            { label: "Filled", value: "filled" },
            { label: "Outlined", value: "outlined" },
            { label: "Ghost", value: "ghost" },
          ],
        },
      },
      defaultProps: {
        title: "カジノ情報カテゴリー",
        subtitle: "あなたの目的に合った情報を見つけてください。",
        theme: "default",
        items: [
          { label: "ボーナス", href: "/category/ボーナス", iconName: "gift" },
          { label: "ガイド", href: "/category/ガイド", iconName: "book-open" },
          { label: "最新記事", href: "/blogs", iconName: "newspaper" },
          { label: "レビュー", href: "/category/レビュー", iconName: "star" },
        ],
        openInNewTab: "same",
        relAttribute: "follow",
        buttonText: "",
        buttonUrl: "",
        buttonStyle: "filled",
      },
      render: (props: any) => <CategoryGrid {...stripPuck(props)} />,
    },

    HighlightCards: {
      label: "Highlight Cards",
      fields: {
        title: { type: "text", label: "Title" },
        subtitle: { type: "textarea", label: "Subtitle" },
        theme: {
          type: "select",
          label: "Design Theme",
          options: [
            { label: "Glass (Frosted)", value: "glass" },
            { label: "Solid (Dark)", value: "solid" },
            { label: "Outlined (Warm)", value: "outlined" },
            { label: "Ocean (Blue / Indigo)", value: "ocean" },
            { label: "Forest (Green / Teal)", value: "forest" },
          ],
        },
        card1Title: { type: "text", label: "Card 1 Title" },
        card1Desc: { type: "textarea", label: "Card 1 Description" },
        card1Href: { type: "text", label: "Card 1 Link" },
        card1Icon: {
          type: "custom",
          label: "Card 1 Icon",
          render: ({ value, onChange }: { value: string; onChange: (v: string) => void }) => (
            <IconPickerField value={value || 'shield'} onChange={onChange} />
          ),
        },
        card2Title: { type: "text", label: "Card 2 Title" },
        card2Desc: { type: "textarea", label: "Card 2 Description" },
        card2Href: { type: "text", label: "Card 2 Link" },
        card2Icon: {
          type: "custom",
          label: "Card 2 Icon",
          render: ({ value, onChange }: { value: string; onChange: (v: string) => void }) => (
            <IconPickerField value={value || 'star'} onChange={onChange} />
          ),
        },
        openInNewTab: LINK_FIELDS.openInNewTab,
        relAttribute: LINK_FIELDS.relAttribute,
      },
      defaultProps: {
        title: "カジノ選びの2つの視点",
        subtitle: "安全性と楽しさを両立するための情報を提供します。",
        card1Title: "初心者向けガイド",
        card1Desc: "オンラインカジノの始め方、安全な選び方、基本ルールなど、初めての方に必要な情報を丁寧に解説します。",
        card1Href: "/category/ガイド",
        card1Icon: "shield",
        card2Title: "ボーナス最新情報",
        card2Desc: "ウェルカムボーナス、フリースピン、入金不要ボーナスなど、最もお得なキャンペーン情報をリアルタイムで更新。",
        card2Href: "/category/ボーナス",
        card2Icon: "gift",
        theme: "glass",
        openInNewTab: "same",
        relAttribute: "follow",
      },
      render: (props: any) => <HighlightCards {...stripPuck(props)} />,
    },

    AppPromoSection: {
      label: "App / Feature Promotion",
      fields: {
        title: { type: "text", label: "Title" },
        subtitle: { type: "textarea", label: "Subtitle" },
        theme: {
          type: "select",
          label: "Design Theme",
          options: [
            { label: "Default (Brand)", value: "default" },
            { label: "Dark Mode", value: "dark" },
            { label: "Vibrant (Orange)", value: "vibrant" },
            { label: "Ocean (Blue / Indigo)", value: "ocean" },
            { label: "Forest (Green / Teal)", value: "forest" },
          ],
        },
        features: {
          type: "array",
          label: "Feature Cards",
          arrayFields: {
            title: { type: "text", label: "Feature Title" },
            description: { type: "textarea", label: "Feature Description" },
            icon: {
              type: "custom",
              label: "Icon",
              render: ({ value, onChange }: { value: string; onChange: (v: string) => void }) => (
                <IconPickerField value={value || ''} onChange={onChange} />
              ),
            },
          },
        },
      },
      defaultProps: {
        title: "このサイトの特長",
        subtitle: "信頼できる情報をもとに、役立つ知識を身につけましょう。",
        theme: "default",
        features: [
          { title: "最新情報", description: "リアルタイムで更新される役立つ情報をチェック。", icon: "gift" },
          { title: "専門家レビュー", description: "業界の専門家が徹底検証した信頼できるレビューを提供。", icon: "star" },
          { title: "初心者サポート", description: "基礎知識から応用まで、わかりやすく解説します。", icon: "help-circle" },
        ],
      },
      render: (props: any) => <AppPromoSection {...stripPuck(props)} />,
    },

    // ─── Layout Utilities ─────────────────────────────────────────────
    Spacer: {
      label: "Spacer",
      fields: {
        height: { type: "number", label: "Height (px)", min: 8, max: 256 },
      },
      defaultProps: { height: 64 },
      render: (props: any) => <Spacer {...stripPuck(props)} />,
    },

    Divider: {
      label: "Divider",
      fields: {
        label: { type: "text", label: "Label (optional)" },
        style: {
          type: "select",
          label: "Style",
          options: [
            { label: "Solid", value: "line" },
            { label: "Dashed", value: "dashed" },
            { label: "Dotted", value: "dotted" },
          ],
        },
      },
      defaultProps: { label: "", style: "line" },
      render: (props: any) => <Divider {...stripPuck(props)} />,
    },

    // ─── Navigation ───────────────────────────────────────────────────
    StickyNav: {
      label: "Sticky Navigation",
      fields: {
        theme: {
          type: "select",
          label: "Design Theme",
          options: [
            { label: "Default (Brand)", value: "default" },
            { label: "Warm (Orange)", value: "warm" },
            { label: "Professional (Dark)", value: "professional" },
            { label: "Ocean (Blue / Indigo)", value: "ocean" },
            { label: "Forest (Green / Teal)", value: "forest" },
          ],
        },
        position: {
          type: "select",
          label: "Position Behavior",
          options: [
            { label: "Sticky Top (stays at top on scroll)", value: "top" },
            { label: "Sticky Bottom (stays at bottom on scroll)", value: "bottom" },
            { label: "Inline (normal flow)", value: "inline" },
          ],
        },
        items: {
          type: "array",
          label: "Nav Items",
          arrayFields: {
            label: { type: "text", label: "Label" },
            anchorId: { type: "text", label: "Section ID (anchor)" },
          },
        },
      },
      defaultProps: {
        theme: "default",
        position: "top",
        items: [
          { label: "おすすめランキング", anchorId: "ranking" },
          { label: "比較表", anchorId: "comparison" },
          { label: "詳細レビュー", anchorId: "reviews" },
        ],
      },
      render: (props: any) => <StickyNav {...stripPuck(props)} />,
    },

    TableOfContents: {
      label: "Table of Contents",
      fields: {
        theme: {
          type: "select",
          label: "Design Theme",
          options: [
            { label: "Default (Brand)", value: "default" },
            { label: "Warm (Orange)", value: "warm" },
            { label: "Professional (Dark)", value: "professional" },
            { label: "Ocean (Blue / Indigo)", value: "ocean" },
            { label: "Forest (Green / Teal)", value: "forest" },
          ],
        },
        title: { type: "text", label: "Title" },
        showNumbers: {
          type: "select",
          label: "Show Numbers",
          options: [{ label: "Yes", value: "yes" }, { label: "No", value: "no" }],
        },
        dataMode: {
          type: "radio",
          label: "Data Source",
          options: [
            { label: "Auto (from Headings)", value: "auto" },
            { label: "Manual", value: "manual" },
          ],
        },
        manualItems: {
          type: "array",
          label: "Manual Items",
          arrayFields: {
            text: { type: "text", label: "Label" },
            targetId: { type: "text", label: "Target Section ID" },
            level: { 
              type: "radio", 
              label: "Heading Level", 
              options: [
                { label: "H2 (Main)", value: "h2" },
                { label: "H3 (Sub)", value: "h3" }
              ]
            }
          },
          defaultItemProps: { text: "セクション名", targetId: "section-1", level: "h2" }
        }
      },
      defaultProps: {
        theme: "default",
        title: "目次",
        showNumbers: "yes",
        dataMode: "auto",
        manualItems: [],
      },
      render: (props: any) => {
        const clean = stripPuck(props);
        return <TableOfContents {...clean} showNumbers={clean.showNumbers !== 'no'} />;
      },
    },

    // ─── Dynamic Content (Blog) ───────────────────────────────────────
    ArticleTrendingRanking: {
      label: "Trending + Ranking Grid",
      fields: {
        trendingTitle: { type: "text", label: "Trending Title" },
        rankingTitle: { type: "text", label: "Ranking Title" },
        trendingCount: { type: "number", label: "Trending Count (Auto Mode)", min: 1, max: 10 },
        rankingCount: { type: "number", label: "Ranking Count (Auto Mode)", min: 1, max: 10 },
        trendingMode: {
          type: "select", label: "Trending Data Source",
          options: [
            { label: "Auto (from Database)", value: "auto" },
            { label: "Manual (enter items below)", value: "manual" },
          ],
        },
        manualTrendingItems: {
          type: "array",
          label: "Manual Trending Items",
          arrayFields: {
            title: { type: "text", label: "Title" },
            linkUrl: { type: "text", label: "Link URL" },
          },
        },
        rankingMode: {
          type: "select", label: "Ranking Data Source",
          options: [
            { label: "Auto (from Database)", value: "auto" },
            { label: "Manual (enter items below)", value: "manual" },
          ],
        },
        manualRankingItems: {
          type: "array",
          label: "Manual Ranking Items",
          arrayFields: {
            title: { type: "text", label: "Title" },
            image: {
              type: "custom",
              label: "Image",
              render: ({ value, onChange }: any) => (
                <MediaUploadField value={value || ''} onChange={onChange} accept="image" />
              ),
            },
            linkUrl: { type: "text", label: "Link URL" },
          },
        },
        theme: {
          type: "select", label: "Design Theme",
          options: [
            { label: "Default (Brand)", value: "default" },
            { label: "Warm (Orange)", value: "warm" },
            { label: "Professional (Dark)", value: "professional" },
            { label: "Ocean (Blue)", value: "ocean" },
            { label: "Forest (Green)", value: "forest" },
          ],
        },
      },
      defaultProps: {
        trendingTitle: "いま話題",
        rankingTitle: "人気記事ランキング",
        trendingCount: 5,
        rankingCount: 5,
        trendingMode: "auto",
        rankingMode: "auto",
        manualTrendingItems: [],
        manualRankingItems: [],
        theme: "default",
      },
      render: (props: any) => <ArticleGridTrendingRankingEditor {...stripPuck(props)} />,
    },

    ArticleCategorySections: {
      label: "Category Sections Grid",
      fields: {
        articlesPerCategory: { type: "number", label: "Articles Per Category (Auto Mode)", min: 1, max: 10 },
        showViewMore: {
          type: "select", label: "Show View More",
          options: [{ label: "Yes", value: "yes" }, { label: "No", value: "no" }],
        },
        theme: {
          type: "select", label: "Design Theme",
          options: [
            { label: "Default (Brand)", value: "default" },
            { label: "Warm (Orange)", value: "warm" },
            { label: "Professional (Dark)", value: "professional" },
            { label: "Ocean (Blue)", value: "ocean" },
            { label: "Forest (Green)", value: "forest" },
          ],
        },
        dataMode: {
          type: "select", label: "Data Source",
          options: [
            { label: "Auto (from Database)", value: "auto" },
            { label: "Manual (enter items below)", value: "manual" },
          ],
        },
        manualCategories: {
          type: "array",
          label: "Manual Categories",
          arrayFields: {
            categoryName: { type: "text", label: "Category Name" },
          },
        },
      },
      defaultProps: {
        articlesPerCategory: 4,
        showViewMore: "yes",
        theme: "default",
        dataMode: "auto",
        manualCategories: [],
      },
      render: (props: any) => <ArticleGridCategorySectionsEditor {...stripPuck(props)} />,
    },

    FeaturedArticleHero: {
      label: "Featured Article Hero",
      fields: {
        theme: {
          type: "select", label: "Design Theme",
          options: [
            { label: "Default (Brand)", value: "default" },
            { label: "Warm (Orange)", value: "warm" },
            { label: "Professional (Dark)", value: "professional" },
            { label: "Ocean (Blue)", value: "ocean" },
            { label: "Forest (Green)", value: "forest" },
          ],
        },
        dataMode: {
          type: "select", label: "Data Source",
          options: [
            { label: "Auto (from Database)", value: "auto" },
            { label: "Manual (enter item below)", value: "manual" },
          ],
        },
        manualItems: {
          type: "array",
          label: "Manual Item (use 1 entry)",
          arrayFields: {
            title: { type: "text", label: "Title" },
            image: {
              type: "custom", label: "Image",
              render: ({ value, onChange }: any) => (
                <MediaUploadField value={value || ''} onChange={onChange} accept="image" />
              ),
            },
            excerpt: { type: "textarea", label: "Excerpt" },
            category: { type: "text", label: "Category" },
            linkUrl: { type: "text", label: "Link URL" },
            readingTime: { type: "number", label: "Reading Time (min)", min: 1, max: 60 },
          },
        },
      },
      defaultProps: { theme: "default", dataMode: "auto", manualItems: [] },
      render: (props: any) => <FeaturedArticleHeroEditor {...stripPuck(props)} />,
    },

    FeaturedArticleSpotlight: {
      label: "Featured Article Spotlight",
      fields: {
        sectionTitle: { type: "text", label: "Section Title" },
        articleCount: { type: "number", label: "Article Count (Auto Mode)", min: 1, max: 6 },
        theme: {
          type: "select", label: "Design Theme",
          options: [
            { label: "Default (Brand)", value: "default" },
            { label: "Warm (Orange)", value: "warm" },
            { label: "Professional (Dark)", value: "professional" },
            { label: "Ocean (Blue)", value: "ocean" },
            { label: "Forest (Green)", value: "forest" },
          ],
        },
        dataMode: {
          type: "select", label: "Data Source",
          options: [
            { label: "Auto (from Database)", value: "auto" },
            { label: "Manual (enter items below)", value: "manual" },
          ],
        },
        manualItems: {
          type: "array",
          label: "Manual Items",
          arrayFields: {
            title: { type: "text", label: "Title" },
            image: {
              type: "custom", label: "Image",
              render: ({ value, onChange }: any) => (
                <MediaUploadField value={value || ''} onChange={onChange} accept="image" />
              ),
            },
            excerpt: { type: "textarea", label: "Excerpt" },
            category: { type: "text", label: "Category" },
            linkUrl: { type: "text", label: "Link URL" },
          },
        },
      },
      defaultProps: { sectionTitle: "注目記事", articleCount: 3, theme: "default", dataMode: "auto", manualItems: [] },
      render: (props: any) => <FeaturedArticleSpotlightEditor {...stripPuck(props)} />,
    },

    HeroBlogCarousel: {
      label: "Hero (Blog Carousel)",
      fields: {
        sectionTitle: { type: "text", label: "Section Title" },
        articleCount: { type: "number", label: "Article Count (Auto Mode)", min: 2, max: 8 },
        bgImage: {
          type: "custom",
          label: "Fallback Background Image",
          render: ({ value, onChange }: any) => (
            <MediaUploadField value={value || ''} onChange={onChange} accept="image" />
          ),
        },
        showCategoryBadge: {
          type: "select", label: "Show Category Badge",
          options: [{ label: "Yes", value: "yes" }, { label: "No", value: "no" }],
        },
        showExcerpt: {
          type: "select", label: "Show Excerpt",
          options: [{ label: "Yes", value: "yes" }, { label: "No", value: "no" }],
        },
        theme: {
          type: "select", label: "Design Theme",
          options: [
            { label: "Default (Brand)", value: "default" },
            { label: "Warm (Orange)", value: "warm" },
            { label: "Professional (Dark)", value: "professional" },
            { label: "Ocean (Blue)", value: "ocean" },
            { label: "Forest (Green)", value: "forest" },
          ],
        },
        dataMode: {
          type: "select", label: "Data Source",
          options: [
            { label: "Auto (from Database)", value: "auto" },
            { label: "Manual (enter items below)", value: "manual" },
          ],
        },
        manualItems: {
          type: "array",
          label: "Manual Items",
          arrayFields: {
            title: { type: "text", label: "Title" },
            image: {
              type: "custom", label: "Image",
              render: ({ value, onChange }: any) => (
                <MediaUploadField value={value || ''} onChange={onChange} accept="image" />
              ),
            },
            category: { type: "text", label: "Category" },
            excerpt: { type: "textarea", label: "Excerpt" },
            linkUrl: { type: "text", label: "Link URL" },
          },
        },
      },
      defaultProps: {
        sectionTitle: "最新記事",
        articleCount: 5,
        bgImage: "",
        showCategoryBadge: "yes",
        showExcerpt: "yes",
        theme: "default",
        dataMode: "auto",
        manualItems: [],
      },
      render: (props: any) => <HeroBlogCarouselEditor {...stripPuck(props)} />,
    },

    HeroSlideCarousel: {
      label: "Hero (Slide Carousel)",
      fields: {
        slides: {
          type: "array",
          label: "Slides",
          arrayFields: {
            image: {
              type: "custom", label: "Image",
              render: ({ value, onChange }: any) => (
                <MediaUploadField value={value || ''} onChange={onChange} accept="image" />
              ),
            },
            title: { type: "text", label: "Title" },
            description: { type: "textarea", label: "Description" },
            tag: { type: "text", label: "Tag/Badge" },
            linkUrl: { type: "text", label: "Link URL" },
          },
        },
        theme: {
          type: "select", label: "Design Theme",
          options: [
            { label: "Default (Brand)", value: "default" },
            { label: "Warm (Orange)", value: "warm" },
            { label: "Professional (Dark)", value: "professional" },
            { label: "Ocean (Blue)", value: "ocean" },
            { label: "Forest (Green)", value: "forest" },
          ],
        },
      },
      defaultProps: {
        slides: [
          { image: "", title: "スライド 1", description: "説明文をここに入力", tag: "NEW", linkUrl: "#" },
        ],
        theme: "default",
      },
      render: (props: any) => <HeroSlideCarouselEditor {...stripPuck(props)} />,
    },

    HeroFullWidthSlider: {
      label: "Hero (Full-Width Slider)",
      fields: {
        slides: {
          type: "array",
          label: "Slides",
          arrayFields: {
            image: {
              type: "custom", label: "Image",
              render: ({ value, onChange }: any) => (
                <MediaUploadField value={value || ''} onChange={onChange} accept="image" />
              ),
            },
            title: { type: "text", label: "Title" },
            description: { type: "textarea", label: "Description" },
            tag: { type: "text", label: "Tag/Badge" },
            linkUrl: { type: "text", label: "Link URL" },
          },
        },
        autoplaySpeed: { type: "number", label: "Autoplay Speed (ms)", min: 1000, max: 10000 },
        theme: {
          type: "select", label: "Design Theme",
          options: [
            { label: "Default (Brand Colors)", value: "default" },
            { label: "Warm (Coral / Orange)", value: "warm" },
            { label: "Professional (Dark / Gold)", value: "professional" },
            { label: "Ocean (Blue / Indigo)", value: "ocean" },
            { label: "Forest (Green / Teal)", value: "forest" },
          ],
        },
      },
      defaultProps: {
        slides: [
          { image: "", title: "スライド 1", description: "説明文をここに入力", tag: "", linkUrl: "#" },
        ],
        autoplaySpeed: 5000,
      },
      render: (props: any) => <HeroFullWidthSlider {...stripPuck(props)} />,
    },

    SplitContentHero: {
      label: "Split Content Hero",
      fields: {
        title: { type: "text", label: "Title" },
        subtitle: { type: "textarea", label: "Subtitle" },
        image: {
          type: "custom", label: "Image",
          render: ({ value, onChange }: any) => (
            <MediaUploadField value={value || ''} onChange={onChange} accept="image" />
          ),
        },
        imagePosition: {
          type: "select", label: "Image Position",
          options: [{ label: "Right", value: "right" }, { label: "Left", value: "left" }],
        },
        theme: {
          type: "select", label: "Design Theme",
          options: [
            { label: "Default", value: "default" },
            { label: "Warm", value: "warm" },
            { label: "Professional", value: "professional" },
            { label: "Ocean", value: "ocean" },
            { label: "Forest", value: "forest" },
          ],
        },
        buttonText: { type: "text", label: "Button Text" },
        buttonUrl: { type: "text", label: "Button URL" },
      },
      defaultProps: {
        title: "タイトルをここに入力",
        subtitle: "サブタイトルをここに入力",
        image: "",
        imagePosition: "right",
        buttonText: "詳しく見る",
        buttonUrl: "#",
      },
      render: (props: any) => <SplitContentHero {...stripPuck(props)} />,
    },

    HeroVideoCinematic: {
      label: "Hero (Video Cinematic)",
      fields: {
        title: { type: "text", label: "Title" },
        subtitle: { type: "text", label: "Subtitle" },
        description: { type: "textarea", label: "Description" },
        bgVideo: {
          type: "custom", label: "Background Video",
          render: ({ value, onChange }: any) => (
            <MediaUploadField value={value || ''} onChange={onChange} accept="video" />
          ),
        },
        bgImage: {
          type: "custom", label: "Fallback Background Image",
          render: ({ value, onChange }: any) => (
            <MediaUploadField value={value || ''} onChange={onChange} accept="image" />
          ),
        },
        mediaType: {
          type: "select", label: "Media Type",
          options: [
            { label: "Video", value: "video" }, 
            { label: "Image", value: "image" },
            { label: "Color/Gradient", value: "color" }
          ],
        },
        bgColor: { type: "text", label: "Fallback Bg Color (e.g. #0F0F12)" },
        bgGradientFrom: { type: "text", label: "Gradient From Color (e.g. from-slate-900)" },
        bgGradientTo: { type: "text", label: "Gradient To Color (e.g. to-black)" },
        bgGradientDirection: {
          type: "select", label: "Gradient Direction",
          options: [
            { label: "Right", value: "bg-gradient-to-r" },
            { label: "Bottom", value: "bg-gradient-to-b" },
            { label: "Bottom Right", value: "bg-gradient-to-br" },
          ],
        },
        overlayOpacity: { type: "number", label: "Overlay Opacity (%)", min: 0, max: 100 },
        buttonText: { type: "text", label: "CTA Button Text" },
        buttonUrl: { type: "text", label: "CTA Button URL" },
        buttonStyle: {
          type: "select", label: "CTA Button Style",
          options: [
            { label: "Filled", value: "filled" },
            { label: "Outlined", value: "outlined" },
            { label: "Ghost", value: "ghost" },
          ],
        },
        theme: {
          type: "select", label: "Design Theme",
          options: [
            { label: "Default (Dark)", value: "default" },
            { label: "Warm (Orange)", value: "warm" },
            { label: "Professional (Slate)", value: "professional" },
            { label: "Ocean (Blue)", value: "ocean" },
            { label: "Forest (Green)", value: "forest" },
          ],
        },
      },
      defaultProps: {
        title: "ようこそ",
        subtitle: "Welcome",
        description: "最高の体験をお届けします。",
        bgVideo: "",
        bgImage: "",
        mediaType: "video",
        overlayOpacity: 40,
        buttonText: "",
        buttonUrl: "",
        theme: "default",
      },
      render: (props: any) => <HeroVideoCinematic {...stripPuck(props)} />,
    },

    // ─── Cards ────────────────────────────────────────────────────────
    FeaturesGrid: {
      label: "Features Grid",
      fields: {
        title: { type: "text", label: "Title" },
        subtitle: { type: "textarea", label: "Subtitle" },
        features: {
          type: "array",
          label: "Features",
          arrayFields: {
            title: { type: "text", label: "Title" },
            description: { type: "textarea", label: "Description" },
            icon: {
              type: "custom",
              label: "Icon",
              render: ({ value, onChange }: { value: string; onChange: (v: string) => void }) => (
                <IconPickerField value={value || ''} onChange={onChange} />
              ),
            },
          },
        },
        theme: {
          type: "select", label: "Design Theme",
          options: [
            { label: "Default (Brand)", value: "default" },
            { label: "Warm (Orange)", value: "warm" },
            { label: "Professional (Dark)", value: "professional" },
            { label: "Ocean (Blue)", value: "ocean" },
            { label: "Forest (Green)", value: "forest" },
          ],
        },
        buttonText: { type: "text", label: "CTA Button Text" },
        buttonUrl: { type: "text", label: "CTA Button URL" },
        buttonStyle: {
          type: "select", label: "CTA Button Style",
          options: [
            { label: "Filled", value: "filled" },
            { label: "Outlined", value: "outlined" },
            { label: "Ghost", value: "ghost" },
          ],
        },
      },
      defaultProps: {
        title: "特長",
        subtitle: "私たちの強みをご紹介します。",
        features: [
          { title: "信頼性の高い情報", description: "ライセンス済みカジノのみを厳選レビュー。", icon: "shield" },
          { title: "初心者でもわかりやすい", description: "基本から攻略法まで丁寧に解説。", icon: "book-open" },
          { title: "最新ボーナス情報", description: "キャンペーン情報をリアルタイムで更新。", icon: "gift" },
        ],
        buttonText: "",
        buttonUrl: "",
        theme: "default",
      },
      render: (props: any) => <FeaturesGrid {...stripPuck(props)} />,
    },

    LibTargetAudience: {
      label: "Target Audience (2 Cards)",
      fields: {
        performanceTitle: { type: "text", label: "Card 1 Title" },
        performanceDescription: { type: "textarea", label: "Card 1 Description" },
        performanceLinkUrl: { type: "text", label: "Card 1 Link URL" },
        performanceLinkText: { type: "text", label: "Card 1 Link Text" },
        healthTitle: { type: "text", label: "Card 2 Title" },
        healthDescription: { type: "textarea", label: "Card 2 Description" },
        healthLinkUrl: { type: "text", label: "Card 2 Link URL" },
        healthLinkText: { type: "text", label: "Card 2 Link Text" },
        theme: {
          type: "select", label: "Design Theme",
          options: [
            { label: "Default (Brand)", value: "default" },
            { label: "Warm (Orange)", value: "warm" },
            { label: "Professional (Dark)", value: "professional" },
            { label: "Ocean (Blue)", value: "ocean" },
            { label: "Forest (Green)", value: "forest" },
          ],
        },
      },
      defaultProps: {
        performanceTitle: "初心者プレイヤー向け",
        performanceDescription: "オンラインカジノの始め方、安全なサイトの選び方、基本的なゲームルールなど、初めての方でも安心して始められる情報を提供します。",
        performanceLinkUrl: "/category/ガイド",
        performanceLinkText: "初心者ガイドを見る",
        healthTitle: "経験者プレイヤー向け",
        healthDescription: "最新ボーナス情報、高RTPスロット比較、VIPプログラム分析など、経験者がさらにお得に楽しむための上級者向け情報を提供します。",
        healthLinkUrl: "/category/ボーナス",
        healthLinkText: "ボーナス情報を見る",
        theme: "default",
      },
      render: (props: any) => <LibTargetAudience {...stripPuck(props)} />,
    },

    CommonProblems: {
      label: "Common Problems",
      fields: {
        title: { type: "text", label: "Title" },
        subtitle: { type: "textarea", label: "Subtitle" },
        troubles: {
          type: "array",
          label: "Problems",
          arrayFields: {
            question: { type: "text", label: "Question" },
            category: { type: "text", label: "Category" },
            icon: {
              type: "custom",
              label: "Icon",
              render: ({ value, onChange }: { value: string; onChange: (v: string) => void }) => (
                <IconPickerField value={value || ''} onChange={onChange} />
              ),
            },
          },
        },
        theme: {
          type: "select", label: "Design Theme",
          options: [
            { label: "Default (Brand)", value: "default" },
            { label: "Warm (Orange)", value: "warm" },
            { label: "Professional (Dark)", value: "professional" },
            { label: "Ocean (Blue)", value: "ocean" },
            { label: "Forest (Green)", value: "forest" },
          ],
        },
      },
      defaultProps: {
        title: "よくある疑問から記事を探す",
        subtitle: "あなたの知りたいテーマから関連する記事を探せます。",
        troubles: [
          { question: "安全なオンラインカジノの選び方は？", category: "オンラインカジノ", icon: "help-circle" },
          { question: "ウェルカムボーナスの使い方は？", category: "ボーナス", icon: "gift" },
          { question: "入出金方法の比較ガイド", category: "ガイド", icon: "credit-card" },
          { question: "初心者におすすめのゲームは？", category: "ガイド", icon: "gamepad-2" },
          { question: "フリースピンの獲得方法", category: "ボーナス", icon: "sparkles" },
          { question: "モバイルカジノの遊び方", category: "ガイド", icon: "smartphone" },
        ],
        theme: "default",
      },
      render: (props: any) => <CommonProblems {...stripPuck(props)} />,
    },

    ArticleCardCarousel: {
      label: "Article Card Carousel",
      fields: {
        cards: {
          type: "array",
          label: "Cards",
          arrayFields: {
            image: {
              type: "custom", label: "Image",
              render: ({ value, onChange }: any) => (
                <MediaUploadField value={value || ''} onChange={onChange} accept="image" />
              ),
            },
            title: { type: "text", label: "Title" },
            excerpt: { type: "textarea", label: "Excerpt" },
            category: { type: "text", label: "Category" },
            linkUrl: { type: "text", label: "Link URL" },
          },
        },
        autoplaySpeed: { type: "number", label: "Autoplay Speed (ms)", min: 0, max: 10000 },
      },
      defaultProps: {
        cards: [],
        autoplaySpeed: 0,
      },
      render: (props: any) => <ArticleCardCarousel {...stripPuck(props)} />,
    },

    // ─── Newsletter ───────────────────────────────────────────────────
    NewsletterFull: {
      label: "Newsletter (Full Section)",
      fields: {
        title: { type: "text", label: "Title" },
        subtitle: { type: "textarea", label: "Subtitle" },
        placeholderText: { type: "text", label: "Input Placeholder" },
        buttonText: { type: "text", label: "Button Text" },
        theme: {
          type: "select", label: "Design Theme",
          options: [
            { label: "Default (Brand)", value: "default" },
            { label: "Warm (Orange)", value: "warm" },
            { label: "Professional (Dark)", value: "professional" },
            { label: "Ocean (Blue)", value: "ocean" },
            { label: "Forest (Green)", value: "forest" },
          ],
        },
      },
      defaultProps: {
        title: "ニュースレター購読",
        subtitle: "最新情報や特別コンテンツ、お役立ちガイドを定期的にお届けします。",
        placeholderText: "メールアドレスを入力",
        buttonText: "今すぐ登録",
        theme: "default",
      },
      render: (props: any) => <Newsletter {...stripPuck(props)} />,
    },

    NewsletterInline: {
      label: "Newsletter (Inline CTA)",
      fields: {
        title: { type: "text", label: "Title" },
        description: { type: "textarea", label: "Description" },
        buttonText: { type: "text", label: "Button Text" },
        theme: {
          type: "select", label: "Design Theme",
          options: [
            { label: "Default (Brand)", value: "default" },
            { label: "Warm (Orange)", value: "warm" },
            { label: "Professional (Dark)", value: "professional" },
            { label: "Ocean (Blue)", value: "ocean" },
            { label: "Forest (Green)", value: "forest" },
          ],
        },
      },
      defaultProps: {
        title: "メールで最新情報をお届け",
        description: "新着記事やお役立ち情報を配信中。",
        buttonText: "登録",
        theme: "default",
      },
      render: (props: any) => <NewsletterInline {...stripPuck(props)} />,
    },

    // ─── Author ───────────────────────────────────────────────────────
    AuthorProfile: {
      label: "Author (Full Profile)",
      fields: {
        authorName: { type: "text", label: "Author Name" },
        authorRole: { type: "text", label: "Author Role / Title" },
        authorBio: { type: "textarea", label: "Author Bio" },
        authorAvatar: {
          type: "custom",
          label: "Author Avatar Image",
          render: ({ value, onChange }: { value: string; onChange: (v: string) => void }) => (
            <MediaUploadField value={value || ''} onChange={onChange} accept="image" />
          ),
        },
        authorProfileUrl: { type: "text", label: "Author Profile URL" },
        socialTwitter: { type: "text", label: "Twitter / X URL" },
        socialInstagram: { type: "text", label: "Instagram URL" },
        socialYoutube: { type: "text", label: "YouTube URL" },
        socialLinkedin: { type: "text", label: "LinkedIn URL" },
        socialWebsite: { type: "text", label: "Personal Website URL" },
        theme: {
          type: "select", label: "Design Theme",
          options: [
            { label: "Default (Brand)", value: "default" },
            { label: "Warm (Orange)", value: "warm" },
            { label: "Professional (Dark)", value: "professional" },
            { label: "Ocean (Blue)", value: "ocean" },
            { label: "Forest (Green)", value: "forest" },
          ],
        },
      },
      defaultProps: {
        authorName: "",
        authorRole: "",
        authorBio: "",
        authorAvatar: "",
        authorProfileUrl: "",
        socialTwitter: "",
        socialInstagram: "",
        socialYoutube: "",
        socialLinkedin: "",
        socialWebsite: "",
        theme: "default",
      },
      render: (props: any) => <AuthorProfileEditor {...stripPuck(props)} />,
    },

    // ─── Layout Variants ──────────────────────────────────────────────
    TwoColumnLayout: {
      label: "Two-Column (Trending + Most Read)",
      fields: {
        trendTitle: { type: "text", label: "Trending Widget Title" },
        mostReadTitle: { type: "text", label: "Most Read Widget Title" },
        theme: {
          type: "select", label: "Design Theme",
          options: [
            { label: "Default (Brand)", value: "default" },
            { label: "Warm (Orange)", value: "warm" },
            { label: "Professional (Dark)", value: "professional" },
            { label: "Ocean (Blue)", value: "ocean" },
            { label: "Forest (Green)", value: "forest" },
          ],
        },
        trendDataMode: {
          type: "select", label: "Trending Data Source",
          options: [
            { label: "Auto (from Database)", value: "auto" },
            { label: "Manual (enter items below)", value: "manual" },
          ],
        },
        manualTrendItems: {
          type: "array",
          label: "Manual Trend Items",
          arrayFields: {
            title: { type: "text", label: "Title" },
            linkUrl: { type: "text", label: "Link URL" },
          },
        },
        mostReadDataMode: {
          type: "select", label: "Most Read Data Source",
          options: [
            { label: "Auto (from Database)", value: "auto" },
            { label: "Manual (enter items below)", value: "manual" },
          ],
        },
        manualMostReadItems: {
          type: "array",
          label: "Manual Most Read Items",
          arrayFields: {
            title: { type: "text", label: "Title" },
            image: {
              type: "custom", label: "Thumbnail Image",
              render: ({ value, onChange }: any) => (
                <MediaUploadField value={value || ''} onChange={onChange} accept="image" />
              ),
            },
            linkUrl: { type: "text", label: "Link URL" },
          },
        },
      },
      defaultProps: {
        trendTitle: "トレンド記事",
        mostReadTitle: "よく読まれている記事",
        theme: "default",
        trendDataMode: "auto",
        mostReadDataMode: "auto",
        manualTrendItems: [],
        manualMostReadItems: [],
      },
      render: (props: any) => <TwoColumnLayoutEditor {...stripPuck(props)} />,
    },

    Glossary: {
      label: "Glossary / Key Terms",
      fields: {
        title: { type: "text", label: "Title" },
        subtitle: { type: "textarea", label: "Subtitle" },
        terms: {
          type: "array",
          label: "Terms",
          arrayFields: {
            term: { type: "text", label: "Term" },
            reading: { type: "text", label: "Reading (English/Furigana)" },
            desc: { type: "textarea", label: "Description" },
          },
        },
        theme: {
          type: "select", label: "Design Theme",
          options: [
            { label: "Default (Brand)", value: "default" },
            { label: "Warm (Orange)", value: "warm" },
            { label: "Professional (Dark)", value: "professional" },
            { label: "Ocean (Blue)", value: "ocean" },
            { label: "Forest (Green)", value: "forest" },
          ],
        },
      },
      defaultProps: {
        title: "知っておきたいカジノ用語",
        subtitle: "オンラインカジノを始める前に押さえておきたい基本用語をわかりやすく解説します。",
        terms: [
          { term: "ウェルカムボーナス", reading: "Welcome Bonus", desc: "新規プレイヤーが初めて登録・入金した際に受け取れる特典。入金額に対する一定割合のボーナスマネーやフリースピンが付与されることが一般的です。" },
          { term: "フリースピン", reading: "Free Spins", desc: "スロットゲームを無料で回せる特典。ウェルカムボーナスやプロモーションの一部として提供されることが多く、獲得した賞金には賭け条件が適用されます。" },
          { term: "賭け条件（ウェイジャリング）", reading: "Wagering Requirements", desc: "ボーナスで得た賞金を出金するために必要な賭け金額の条件。例えば「30倍」の場合、ボーナス額の30倍を賭ける必要があります。" },
          { term: "RTP（還元率）", reading: "Return to Player", desc: "ゲームがプレイヤーに返す金額の理論上の割合。例えば RTP 96% のスロットは、長期的に賭けた金額の96%が戻ることを意味します。数値が高いほど有利です。" },
        ],
        theme: "default",
      },
      render: (props: any) => <Glossary {...stripPuck(props)} />,
    },

    ProcessFlow: {
      label: "Process Flow",
      fields: {
        heading: { type: "text", label: "Heading" },
        theme: {
          type: "select", label: "Design Theme",
          options: [
            { label: "Default (Brand)", value: "default" },
            { label: "Warm (Orange)", value: "warm" },
            { label: "Professional (Dark)", value: "professional" },
            { label: "Ocean (Blue)", value: "ocean" },
            { label: "Forest (Green)", value: "forest" },
          ],
        },
        steps: {
          type: "array",
          label: "Steps",
          arrayFields: {
            number: { type: "text", label: "Number (e.g. 01)" },
            title: { type: "text", label: "Title" },
            description: { type: "textarea", label: "Description" },
          },
        },
      },
      defaultProps: {
        heading: "始め方の流れ",
        theme: "default",
        steps: [
          { number: "01", title: "情報収集", description: "本サイトで信頼できるカジノを探しましょう。" },
          { number: "02", title: "登録", description: "選んだカジノに無料で登録します。" },
          { number: "03", title: "ボーナス獲得", description: "ウェルカムボーナスを受け取ってプレイ開始。" },
        ],
      },
      render: (props: any) => <ProcessFlow {...stripPuck(props)} />,
    },

    BlogShowcaseGrid: {
      label: "Blog Showcase Grid",
      fields: {
        bgColor: { type: "text", label: "Background Color (hex, e.g. #f9f9f9 or #0F0F12)" },
        viewAllText: { type: "text", label: "View All Button Text" },
        mostReadCount: { type: "number", label: "Most Read Count (Auto Mode)", min: 1, max: 10 },
        theme: {
          type: "select", label: "Design Theme",
          options: [
            { label: "Default (Brand)", value: "default" },
            { label: "Warm (Orange)", value: "warm" },
            { label: "Professional (Dark)", value: "professional" },
            { label: "Ocean (Blue)", value: "ocean" },
            { label: "Forest (Green)", value: "forest" },
          ],
        },
        dataMode: {
          type: "select", label: "Data Source",
          options: [
            { label: "Auto (from Database)", value: "auto" },
            { label: "Manual (enter items below)", value: "manual" },
          ],
        },
        manualItems: {
          type: "array",
          label: "Manual Items",
          arrayFields: {
            title: { type: "text", label: "Title" },
            image: {
              type: "custom", label: "Image",
              render: ({ value, onChange }: any) => (
                <MediaUploadField value={value || ''} onChange={onChange} accept="image" />
              ),
            },
            excerpt: { type: "textarea", label: "Excerpt" },
            category: { type: "text", label: "Category" },
            linkUrl: { type: "text", label: "Link URL" },
          },
        },
      },
      defaultProps: {
        bgColor: "",
        viewAllText: "記事一覧を見る",
        mostReadCount: 5,
        theme: "default",
        dataMode: "auto",
        manualItems: [],
      },
      render: (props: any) => <BlogShowcaseGridEditor {...stripPuck(props)} />,
    },
  },
};

// Automatically inject an anchorId field into all components
// so they can be targeted by Sticky Navigation or Table of Contents.
for (const key of Object.keys(puckConfig.components)) {
  const comp = puckConfig.components[key];
  if (!comp.fields) comp.fields = {};
  
  // Skip if it somehow already has an anchorId to avoid overriding custom logic,
  // but most won't have it.
  if (!comp.fields.anchorId) {
    comp.fields.anchorId = { type: "text", label: "Section ID (for anchor link)" };
  }

  const originalRender = comp.render;
  comp.render = (props: any) => {
    // Strip # if the user accidentally included it
    const anchorId = props.anchorId ? props.anchorId.replace(/^#/, '') : null;
    
    // We pass the original props in case the component itself wants to use anchorId (like SectionHeading),
    // but we also wrap it in a div with the anchorId if provided.
    // To prevent duplicate IDs if the inner component also renders it, we only wrap if the component doesn't inherently support it well,
    // or we just wrap it and let the inner component also have it (which is technically invalid HTML but browsers handle it fine by jumping to the first one).
    // Actually, to be perfectly safe, let's just render the wrapper and remove it from the props we pass down to avoid duplicates.
    const propsForChild = { ...props };
    delete propsForChild.anchorId;
    
    const content = originalRender(propsForChild);
    
    if (anchorId) {
      return (
        <div id={anchorId} className="scroll-mt-24 group/anchor relative">
          {content}
        </div>
      );
    }
    return content;
  };
}
