{
  "$schema": "https://uipkge.dev/schema/registry-item.json",
  "name": "case-study",
  "title": "Case Study",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-angular/blocks/case-study/case-study.component.ts",
      "content": "// Customer-proof set pairing a featured split story with a sticky results panel, a\n// filterable story index, three-up metric cards, a before-and-after metric comparison\n// table, and a compact results strip. Port of the React block 1:1.\n//\n// The five sections ship as five standalone components (one per install file in the\n// Vue/React blocks) plus a `UiCaseStudyComponent` wrapper that stacks the full set.\nimport { ChangeDetectionStrategy, Component, Input, computed, signal } from '@angular/core'\nimport { ArrowRight, ArrowUpRight, LucideAngularModule, Quote, TrendingDown, TrendingUp } from 'lucide-angular'\nimport { cn } from '@/lib/utils'\nimport { UiAvatarComponent, UiAvatarFallbackComponent } from '@/ui/avatar/avatar.component'\nimport { UiBadgeComponent } from '@/ui/badge/badge.component'\nimport { UiButtonComponent } from '@/ui/button/button.component'\nimport { UiCardComponent, UiCardContentComponent } from '@/ui/card/card.component'\nimport { UiSeparatorComponent } from '@/ui/separator/separator.component'\nimport {\n  UiTableBodyComponent,\n  UiTableCellComponent,\n  UiTableComponent,\n  UiTableHeadComponent,\n  UiTableHeaderComponent,\n  UiTableRowComponent,\n} from '@/ui/table/table.component'\nimport { UiToggleGroupComponent, UiToggleGroupItemComponent } from '@/ui/toggle-group/toggle-group.component'\n\n// ---------------------------------------------------------------- Featured story\n\ninterface FeaturedResult {\n  value: string\n  label: string\n}\n\ninterface CompanyFact {\n  term: string\n  detail: string\n}\n\nconst featuredResults: FeaturedResult[] = [\n  { value: '5 days', label: 'off the monthly close' },\n  { value: '11 → 1', label: 'reconciliation spreadsheets' },\n  { value: '340', label: 'certified metrics published' },\n  { value: '6 weeks', label: 'kickoff to full hand-over' },\n]\n\nconst companyFacts: CompanyFact[] = [\n  { term: 'Industry', detail: 'Freight forwarding' },\n  { term: 'Size', detail: '1,200 staff · 18 countries' },\n  { term: 'Stack', detail: 'Snowflake · dbt · Okta' },\n  { term: 'Live since', detail: 'Q1 2026' },\n]\n\n@Component({\n  changeDetection: ChangeDetectionStrategy.Eager,\n  selector: 'ui-case-study-featured-story, [ui-case-study-featured-story]',\n  standalone: true,\n  host: { '[attr.class]': '\"contents\"' },\n  imports: [\n    LucideAngularModule,\n    UiAvatarComponent,\n    UiAvatarFallbackComponent,\n    UiBadgeComponent,\n    UiButtonComponent,\n    UiCardComponent,\n    UiCardContentComponent,\n    UiSeparatorComponent,\n  ],\n  template: `\n    <section data-slot=\"case-study-featured-story\" [class]=\"rootClass\">\n      <div class=\"mx-auto max-w-6xl px-6 py-20 lg:py-28\">\n        <div class=\"grid gap-12 lg:grid-cols-[1.4fr_1fr] lg:gap-16\">\n          <article>\n            <span ui-badge variant=\"secondary\">Case study</span>\n            <h2 class=\"mt-4 text-3xl font-semibold tracking-tight text-balance sm:text-4xl\">\n              How Northwind Logistics closed the books five days early\n            </h2>\n\n            <div class=\"mt-8 space-y-8\">\n              <div>\n                <h3 class=\"text-muted-foreground font-mono text-xs tracking-[0.14em] uppercase\">The challenge</h3>\n                <p class=\"mt-2.5 leading-relaxed\">\n                  Month-end ran on eleven spreadsheets maintained by four people across three time zones. Every close\n                  opened with a reconciliation pass nobody had budgeted for, and restatements were tracked in email.\n                </p>\n              </div>\n\n              <div>\n                <h3 class=\"text-muted-foreground font-mono text-xs tracking-[0.14em] uppercase\">The approach</h3>\n                <p class=\"mt-2.5 leading-relaxed\">\n                  We mirrored the warehouse schema, rebuilt revenue and margin as versioned definitions, and reconciled\n                  them against the prior four quarters before anything was published. A single regional team piloted the\n                  first close; the rest of finance moved over two weeks later.\n                </p>\n              </div>\n\n              <div>\n                <h3 class=\"text-muted-foreground font-mono text-xs tracking-[0.14em] uppercase\">The result</h3>\n                <p class=\"mt-2.5 leading-relaxed\">\n                  Close now starts from a reconciled position. Restatements open a reviewable change instead of a\n                  thread, and the audit pack is generated from the same history.\n                </p>\n              </div>\n            </div>\n\n            <figure class=\"border-border mt-10 border-l-2 pl-6\">\n              <lucide-icon [img]=\"Quote\" class=\"text-muted-foreground/60 size-5\" />\n              <blockquote class=\"mt-3 text-lg leading-snug font-medium text-balance\">\n                We stopped arguing about whose number was right and started arguing about what to do next. That is the\n                whole change, and it was worth the six weeks.\n              </blockquote>\n              <figcaption class=\"mt-5 flex items-center gap-3\">\n                <ui-avatar class=\"size-9\">\n                  <ui-avatar-fallback class=\"text-xs\">EW</ui-avatar-fallback>\n                </ui-avatar>\n                <div>\n                  <p class=\"text-sm font-medium\">Erin Walsh</p>\n                  <p class=\"text-muted-foreground text-xs\">VP Finance, Northwind Logistics</p>\n                </div>\n              </figcaption>\n            </figure>\n\n            <button ui-button class=\"mt-10\">\n              Read the full story\n              <lucide-icon [img]=\"ArrowRight\" class=\"ml-2 size-4\" />\n            </button>\n          </article>\n\n          <!-- Sticky results panel: keeps the numbers in view while the narrative scrolls. -->\n          <aside class=\"lg:sticky lg:top-24 lg:self-start\">\n            <div ui-card>\n              <div ui-card-content class=\"p-6\">\n                <h3 class=\"text-muted-foreground font-mono text-xs tracking-[0.14em] uppercase\">Results</h3>\n                <dl class=\"mt-5 grid grid-cols-2 gap-x-4 gap-y-6\">\n                  @for (result of results; track result.label) {\n                    <div>\n                      <dt class=\"sr-only\">{{ result.label }}</dt>\n                      <dd>\n                        <span class=\"font-display block text-2xl font-bold tracking-tight\">{{ result.value }}</span>\n                        <span class=\"text-muted-foreground mt-1 block text-xs leading-snug\">{{ result.label }}</span>\n                      </dd>\n                    </div>\n                  }\n                </dl>\n\n                <ui-separator class=\"my-6\" />\n\n                <dl class=\"space-y-3\">\n                  @for (fact of facts; track fact.term) {\n                    <div class=\"flex items-baseline justify-between gap-4 text-sm\">\n                      <dt class=\"text-muted-foreground\">{{ fact.term }}</dt>\n                      <dd class=\"text-right font-medium\">{{ fact.detail }}</dd>\n                    </div>\n                  }\n                </dl>\n              </div>\n            </div>\n          </aside>\n        </div>\n      </div>\n    </section>\n  `,\n})\nexport class UiCaseStudyFeaturedStorySectionComponent {\n  protected readonly ArrowRight = ArrowRight\n  protected readonly Quote = Quote\n\n  protected readonly results = featuredResults\n  protected readonly facts = companyFacts\n\n  @Input('class') className?: string\n\n  get rootClass(): string {\n    return cn('bg-background', this.className)\n  }\n}\n\n// ------------------------------------------------------------ Filterable list\n\ninterface StoryIndexItem {\n  company: string\n  industry: string\n  result: string\n  stack: string\n  readTime: string\n}\n\nconst storyIndex: StoryIndexItem[] = [\n  {\n    company: 'Northwind Logistics',\n    industry: 'Logistics',\n    result: '5 days off the monthly close',\n    stack: 'Snowflake · dbt · Okta',\n    readTime: '8 min',\n  },\n  {\n    company: 'Halden Health',\n    industry: 'Healthcare',\n    result: '71% fewer ad-hoc data requests',\n    stack: 'BigQuery · Airflow',\n    readTime: '6 min',\n  },\n  {\n    company: 'Verity Retail Group',\n    industry: 'Retail',\n    result: '2.4pp tighter forecast band',\n    stack: 'Redshift · dbt',\n    readTime: '7 min',\n  },\n  {\n    company: 'Calder Manufacturing',\n    industry: 'Manufacturing',\n    result: '11 spreadsheets retired',\n    stack: 'Postgres · Dagster',\n    readTime: '5 min',\n  },\n  {\n    company: 'Ridgeway Freight',\n    industry: 'Logistics',\n    result: 'Per-shipment landed cost',\n    stack: 'Snowflake · Fivetran',\n    readTime: '9 min',\n  },\n  {\n    company: 'Ashford Clinics',\n    industry: 'Healthcare',\n    result: 'PHI-scoped self-serve reporting',\n    stack: 'BigQuery · Entra ID',\n    readTime: '6 min',\n  },\n]\n\nconst ALL_INDUSTRIES = 'All'\n\n@Component({\n  changeDetection: ChangeDetectionStrategy.Eager,\n  selector: 'ui-case-study-filterable-list, [ui-case-study-filterable-list]',\n  standalone: true,\n  host: { '[attr.class]': '\"contents\"' },\n  imports: [\n    LucideAngularModule,\n    UiBadgeComponent,\n    UiButtonComponent,\n    UiCardComponent,\n    UiCardContentComponent,\n    UiSeparatorComponent,\n    UiToggleGroupComponent,\n    UiToggleGroupItemComponent,\n  ],\n  template: `\n    <section data-slot=\"case-study-filterable-list\" [class]=\"rootClass\">\n      <div class=\"mx-auto max-w-4xl px-6 py-20 lg:py-28\">\n        <div class=\"flex flex-wrap items-end justify-between gap-6\">\n          <div>\n            <span ui-badge variant=\"secondary\">Customer stories</span>\n            <h2 class=\"mt-4 text-3xl font-semibold tracking-tight sm:text-4xl\">Read one close to your own</h2>\n          </div>\n\n          <div\n            ui-toggle-group\n            type=\"single\"\n            variant=\"outline\"\n            size=\"sm\"\n            class=\"flex-nowrap overflow-x-auto\"\n            aria-label=\"Filter case studies by industry\"\n            [value]=\"active()\"\n            (valueChange)=\"onChange($event)\"\n          >\n            @for (industry of industries(); track industry) {\n              <button ui-toggle-group-item [value]=\"industry\">{{ industry }}</button>\n            }\n          </div>\n        </div>\n\n        <div ui-card class=\"mt-8\">\n          <div ui-card-content class=\"p-2\">\n            @if (visible().length === 0) {\n              <div class=\"px-4 py-16 text-center\">\n                <p class=\"text-sm font-medium\">No stories in that industry yet.</p>\n                <button ui-button variant=\"outline\" size=\"sm\" class=\"mt-4\" (click)=\"active.set(allLabel)\">\n                  Show all\n                </button>\n              </div>\n            } @else {\n              <ul>\n                @for (study of visible(); track study.company; let last = $last) {\n                  <li>\n                    <a\n                      href=\"#\"\n                      class=\"hover:bg-muted focus-visible:ring-ring group flex items-center gap-4 rounded-lg p-4 transition-colors focus-visible:ring-2 focus-visible:outline-none\"\n                    >\n                      <div class=\"min-w-0 flex-1\">\n                        <div class=\"flex flex-wrap items-center gap-2\">\n                          <p class=\"text-sm font-semibold\">{{ study.company }}</p>\n                          <span ui-badge variant=\"outline\">{{ study.industry }}</span>\n                        </div>\n                        <p class=\"mt-1 text-sm\">{{ study.result }}</p>\n                        <p class=\"text-muted-foreground mt-1 font-mono text-xs\">{{ study.stack }}</p>\n                      </div>\n                      <span class=\"text-muted-foreground shrink-0 text-xs\">{{ study.readTime }}</span>\n                      <lucide-icon\n                        [img]=\"ArrowUpRight\"\n                        class=\"text-muted-foreground size-4 shrink-0 transition-transform group-hover:translate-x-0.5 group-hover:-translate-y-0.5\"\n                      />\n                    </a>\n                    @if (!last) {\n                      <ui-separator />\n                    }\n                  </li>\n                }\n              </ul>\n            }\n          </div>\n        </div>\n      </div>\n    </section>\n  `,\n})\nexport class UiCaseStudyFilterableListComponent {\n  protected readonly ArrowUpRight = ArrowUpRight\n  protected readonly allLabel = ALL_INDUSTRIES\n\n  @Input('class') className?: string\n\n  readonly active = signal<string>(ALL_INDUSTRIES)\n\n  readonly industries = computed(() => [ALL_INDUSTRIES, ...new Set(storyIndex.map((study) => study.industry))])\n  readonly visible = computed(() =>\n    this.active() === ALL_INDUSTRIES ? storyIndex : storyIndex.filter((study) => study.industry === this.active()),\n  )\n\n  get rootClass(): string {\n    return cn('bg-background', this.className)\n  }\n\n  // Single-select emits '' when the pressed chip is pressed again; fall back to\n  // ALL so the list is never empty by accident.\n  onChange(value: unknown): void {\n    this.active.set(typeof value === 'string' && value ? value : ALL_INDUSTRIES)\n  }\n}\n\n// --------------------------------------------------------------- Metric cards\n\ninterface MetricCardStudy {\n  metric: string\n  metricLabel: string\n  company: string\n  industry: string\n  outcome: string\n  quote: string\n  author: { name: string; role: string; initials: string }\n}\n\nconst metricCardStudies: MetricCardStudy[] = [\n  {\n    metric: '5 days',\n    metricLabel: 'off the monthly close',\n    company: 'Northwind Logistics',\n    industry: 'Freight forwarding · 1,200 staff',\n    outcome: 'Replaced eleven reconciliation spreadsheets with one certified revenue model.',\n    quote: 'We stopped arguing about whose number was right and started arguing about what to do next.',\n    author: { name: 'Erin Walsh', role: 'VP Finance', initials: 'EW' },\n  },\n  {\n    metric: '71%',\n    metricLabel: 'fewer ad-hoc data requests',\n    company: 'Halden Health',\n    industry: 'Provider network · 40 clinics',\n    outcome: 'Clinic leads self-serve their own quality metrics without filing a ticket.',\n    quote: 'The analytics team went from a request queue to actually building things again.',\n    author: { name: 'Daniel Brooks', role: 'Head of Analytics', initials: 'DB' },\n  },\n  {\n    metric: '2.4pp',\n    metricLabel: 'tighter forecast accuracy',\n    company: 'Verity Retail Group',\n    industry: 'Omnichannel retail · 310 stores',\n    outcome: 'Sales and finance now forecast off the same pipeline definition, snapshotted weekly.',\n    quote: 'Forecast review stopped opening with twenty minutes of reconciling two decks.',\n    author: { name: 'Priya Raman', role: 'RevOps Director', initials: 'PR' },\n  },\n]\n\n@Component({\n  changeDetection: ChangeDetectionStrategy.Eager,\n  selector: 'ui-case-study-metric-cards, [ui-case-study-metric-cards]',\n  standalone: true,\n  host: { '[attr.class]': '\"contents\"' },\n  imports: [\n    LucideAngularModule,\n    UiAvatarComponent,\n    UiAvatarFallbackComponent,\n    UiBadgeComponent,\n    UiButtonComponent,\n    UiCardComponent,\n    UiCardContentComponent,\n    UiSeparatorComponent,\n  ],\n  template: `\n    <section data-slot=\"case-study-metric-cards\" [class]=\"rootClass\">\n      <div class=\"mx-auto max-w-6xl px-6 py-20 lg:py-28\">\n        <div class=\"flex flex-wrap items-end justify-between gap-6\">\n          <div class=\"max-w-2xl\">\n            <span ui-badge variant=\"secondary\">Customer results</span>\n            <h2 class=\"mt-4 text-3xl font-semibold tracking-tight sm:text-4xl\">What changed after the rollout</h2>\n            <p class=\"text-muted-foreground mt-3 text-lg\">\n              Three teams, measured against their own numbers from the quarter before.\n            </p>\n          </div>\n          <button ui-button variant=\"outline\">All case studies</button>\n        </div>\n\n        <div class=\"mt-10 grid gap-4 md:grid-cols-3\">\n          @for (study of studies; track study.company) {\n            <div ui-card class=\"group\">\n              <div ui-card-content class=\"flex h-full flex-col p-6\">\n                <!-- Metric leads: it is the only part that survives a skim. -->\n                <p class=\"font-display text-4xl font-bold tracking-tight\">{{ study.metric }}</p>\n                <p class=\"text-muted-foreground mt-1 text-sm\">{{ study.metricLabel }}</p>\n\n                <ui-separator class=\"my-5\" />\n\n                <p class=\"text-sm font-semibold\">{{ study.company }}</p>\n                <p class=\"text-muted-foreground mt-0.5 text-xs\">{{ study.industry }}</p>\n                <p class=\"mt-4 text-sm leading-relaxed\">{{ study.outcome }}</p>\n\n                <blockquote class=\"border-border text-muted-foreground mt-5 border-l-2 pl-4 text-sm italic\">\n                  &ldquo;{{ study.quote }}&rdquo;\n                </blockquote>\n\n                <div class=\"mt-auto flex items-center gap-3 pt-6\">\n                  <ui-avatar class=\"size-8\">\n                    <ui-avatar-fallback class=\"text-xs\">{{ study.author.initials }}</ui-avatar-fallback>\n                  </ui-avatar>\n                  <div class=\"min-w-0\">\n                    <p class=\"truncate text-sm font-medium\">{{ study.author.name }}</p>\n                    <p class=\"text-muted-foreground truncate text-xs\">{{ study.author.role }}</p>\n                  </div>\n                  <button\n                    ui-button\n                    variant=\"ghost\"\n                    size=\"icon\"\n                    class=\"ml-auto\"\n                    [attr.aria-label]=\"'Read the ' + study.company + ' case study'\"\n                  >\n                    <lucide-icon\n                      [img]=\"ArrowUpRight\"\n                      class=\"size-4 transition-transform group-hover:translate-x-0.5 group-hover:-translate-y-0.5\"\n                    />\n                  </button>\n                </div>\n              </div>\n            </div>\n          }\n        </div>\n      </div>\n    </section>\n  `,\n})\nexport class UiCaseStudyMetricCardsComponent {\n  protected readonly ArrowUpRight = ArrowUpRight\n  protected readonly studies = metricCardStudies\n\n  @Input('class') className?: string\n\n  get rootClass(): string {\n    return cn('bg-background', this.className)\n  }\n}\n\n// ---------------------------------------------------------- Metric comparison\n\ninterface ComparisonMetric {\n  name: string\n  before: string\n  after: string\n  delta: string\n  better: 'up' | 'down'\n}\n\n// `better` records which direction is good, so the delta colour never has to be\n// hard-coded per row — a falling close time is good, falling accuracy is not.\nconst comparisonMetrics: ComparisonMetric[] = [\n  { name: 'Days to close', before: '9.4', after: '4.2', delta: '−55%', better: 'down' },\n  { name: 'Ad-hoc data requests / month', before: '212', after: '61', delta: '−71%', better: 'down' },\n  { name: 'Certified metrics published', before: '0', after: '340', delta: '+340', better: 'up' },\n  { name: 'Forecast accuracy band', before: '±6.1pp', after: '±3.7pp', delta: '−2.4pp', better: 'down' },\n]\n\n@Component({\n  changeDetection: ChangeDetectionStrategy.Eager,\n  selector: 'ui-case-study-metric-comparison, [ui-case-study-metric-comparison]',\n  standalone: true,\n  host: { '[attr.class]': '\"contents\"' },\n  imports: [\n    LucideAngularModule,\n    UiBadgeComponent,\n    UiButtonComponent,\n    UiCardComponent,\n    UiCardContentComponent,\n    UiSeparatorComponent,\n    UiTableBodyComponent,\n    UiTableCellComponent,\n    UiTableComponent,\n    UiTableHeadComponent,\n    UiTableHeaderComponent,\n    UiTableRowComponent,\n  ],\n  template: `\n    <section data-slot=\"case-study-metric-comparison\" [class]=\"rootClass\">\n      <div class=\"mx-auto max-w-4xl px-6 py-20 lg:py-28\">\n        <span ui-badge variant=\"secondary\">Northwind Logistics</span>\n        <h2 class=\"mt-4 text-3xl font-semibold tracking-tight text-balance sm:text-4xl\">\n          Two quarters either side of the rollout\n        </h2>\n        <p class=\"text-muted-foreground mt-3 text-lg\">\n          Their numbers, their definitions, measured the same way before and after. Nothing normalised.\n        </p>\n\n        <div ui-card class=\"mt-8\">\n          <div ui-card-content class=\"p-0\">\n            <table ui-table>\n              <thead ui-table-header>\n                <tr ui-table-row>\n                  <th ui-table-head>Metric</th>\n                  <th ui-table-head class=\"text-right\">Q4 2025</th>\n                  <th ui-table-head class=\"text-right\">Q2 2026</th>\n                  <th ui-table-head class=\"text-right\">Change</th>\n                </tr>\n              </thead>\n              <tbody ui-table-body>\n                @for (metric of metrics; track metric.name) {\n                  <tr ui-table-row>\n                    <td ui-table-cell class=\"font-medium\">{{ metric.name }}</td>\n                    <td ui-table-cell class=\"text-muted-foreground text-right font-mono text-sm\">\n                      {{ metric.before }}\n                    </td>\n                    <td ui-table-cell class=\"text-right font-mono text-sm font-semibold\">{{ metric.after }}</td>\n                    <td ui-table-cell class=\"text-right\">\n                      <span class=\"text-success inline-flex items-center gap-1.5 font-mono text-sm\">\n                        @if (metric.better === 'down') {\n                          <lucide-icon [img]=\"TrendingDown\" class=\"size-3.5\" />\n                        } @else {\n                          <lucide-icon [img]=\"TrendingUp\" class=\"size-3.5\" />\n                        }\n                        {{ metric.delta }}\n                      </span>\n                    </td>\n                  </tr>\n                }\n              </tbody>\n            </table>\n\n            <ui-separator />\n\n            <p class=\"text-muted-foreground px-6 py-4 text-xs leading-relaxed\">\n              Measured from their own close calendar and ticket queue. The rollout completed between the two quarters;\n              no headcount was added or removed in finance during the period.\n            </p>\n          </div>\n        </div>\n\n        <button ui-button class=\"mt-8\">\n          Read how they did it\n          <lucide-icon [img]=\"ArrowRight\" class=\"ml-2 size-4\" />\n        </button>\n      </div>\n    </section>\n  `,\n})\nexport class UiCaseStudyMetricComparisonComponent {\n  protected readonly ArrowRight = ArrowRight\n  protected readonly TrendingDown = TrendingDown\n  protected readonly TrendingUp = TrendingUp\n  protected readonly metrics = comparisonMetrics\n\n  @Input('class') className?: string\n\n  get rootClass(): string {\n    return cn('bg-background', this.className)\n  }\n}\n\n// --------------------------------------------------------------- Results strip\n\ninterface StripResult {\n  wordmark: string\n  metric: string\n  label: string\n}\n\n// One result per customer. A second number halves the weight of the first.\nconst stripResults: StripResult[] = [\n  { wordmark: 'Northwind', metric: '5 days', label: 'off the monthly close' },\n  { wordmark: 'Halden', metric: '71%', label: 'fewer ad-hoc requests' },\n  { wordmark: 'Verity', metric: '2.4pp', label: 'tighter forecast band' },\n  { wordmark: 'Calder', metric: '11 → 1', label: 'reporting spreadsheets' },\n]\n\n@Component({\n  changeDetection: ChangeDetectionStrategy.Eager,\n  selector: 'ui-case-study-results-strip, [ui-case-study-results-strip]',\n  standalone: true,\n  host: { '[attr.class]': '\"contents\"' },\n  imports: [LucideAngularModule, UiBadgeComponent, UiButtonComponent, UiSeparatorComponent],\n  template: `\n    <section data-slot=\"case-study-results-strip\" [class]=\"rootClass\">\n      <div class=\"mx-auto max-w-6xl px-6 py-10\">\n        <div class=\"flex flex-wrap items-center justify-between gap-4\">\n          <span ui-badge variant=\"secondary\">Proven</span>\n          <button ui-button variant=\"link\" class=\"h-auto p-0 text-sm\">\n            All case studies\n            <lucide-icon [img]=\"ArrowRight\" class=\"ml-1.5 size-3.5\" />\n          </button>\n        </div>\n\n        <div class=\"mt-6 grid gap-6 sm:grid-cols-2 lg:grid-cols-4 lg:gap-0\">\n          @for (result of results; track result.wordmark; let last = $last) {\n            <div class=\"relative lg:px-6 lg:first:pl-0\">\n              <p class=\"text-sm font-semibold tracking-[0.18em] uppercase\">{{ result.wordmark }}</p>\n              <p class=\"font-display mt-3 text-3xl font-bold tracking-tight\">{{ result.metric }}</p>\n              <p class=\"text-muted-foreground mt-1 text-sm\">{{ result.label }}</p>\n\n              @if (!last) {\n                <ui-separator orientation=\"vertical\" class=\"absolute top-0 right-0 hidden h-full lg:block\" />\n              }\n            </div>\n          }\n        </div>\n      </div>\n    </section>\n  `,\n})\nexport class UiCaseStudyResultsStripComponent {\n  protected readonly ArrowRight = ArrowRight\n  protected readonly results = stripResults\n\n  @Input('class') className?: string\n\n  get rootClass(): string {\n    return cn('border-border bg-card border-y', this.className)\n  }\n}\n\n// ------------------------------------------------------------------ Full stack\n\n@Component({\n  changeDetection: ChangeDetectionStrategy.Eager,\n  selector: 'ui-case-study, [ui-case-study]',\n  standalone: true,\n  host: { '[attr.class]': '\"contents\"' },\n  imports: [\n    UiCaseStudyFeaturedStorySectionComponent,\n    UiCaseStudyFilterableListComponent,\n    UiCaseStudyMetricCardsComponent,\n    UiCaseStudyMetricComparisonComponent,\n    UiCaseStudyResultsStripComponent,\n  ],\n  template: `\n    <div data-slot=\"case-study\" [class]=\"rootClass\">\n      <ui-case-study-featured-story />\n      <ui-case-study-filterable-list />\n      <ui-case-study-metric-cards />\n      <ui-case-study-metric-comparison />\n      <ui-case-study-results-strip />\n    </div>\n  `,\n})\nexport class UiCaseStudyComponent {\n  @Input('class') className?: string\n\n  get rootClass(): string {\n    return cn('w-full', this.className)\n  }\n}\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/case-study/case-study.component.ts"
    },
    {
      "path": "packages/registry-angular/blocks/case-study/index.ts",
      "content": "export {\n  UiCaseStudyComponent,\n  UiCaseStudyFeaturedStorySectionComponent,\n  UiCaseStudyFilterableListComponent,\n  UiCaseStudyMetricCardsComponent,\n  UiCaseStudyMetricComparisonComponent,\n  UiCaseStudyResultsStripComponent,\n} from './case-study.component'\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/case-study/index.ts"
    }
  ],
  "dependencies": [
    "lucide-angular"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/angular/avatar.json",
    "https://uipkge.dev/r/angular/badge.json",
    "https://uipkge.dev/r/angular/button.json",
    "https://uipkge.dev/r/angular/card.json",
    "https://uipkge.dev/r/angular/separator.json",
    "https://uipkge.dev/r/angular/table.json",
    "https://uipkge.dev/r/angular/toggle-group.json"
  ],
  "description": "Customer-proof set pairing a featured split story with a sticky results panel, a filterable story index, three-up metric cards, a before-and-after metric comparison table, and a compact results strip.",
  "categories": [
    "marketing"
  ]
}