/* bloo.app — Product deep-dive: "What's inside the AI Code Review Skill Pack".
   Registers window.Pages['ai-code-review-inside']; routed via app.jsx.
   Buyer-facing framing (founders/CTOs) with rich, inspectable proof: every
   review pass explained, five slash commands, and a live file explorer.
   Verbatim file bodies live in js/product-ai-code-review-raw.js (lazy-loaded
   here on mount) and are surfaced via window.PackUI (…-explorer.jsx). */
(function () {
const { Button, Badge, Card, Tag, Tabs } = window.BlooAppDesignSystem_ab7292;
const { LINKS, Icons, S } = window.Site;
const { useT } = window.I18n;
const { IconCode, IconLayers, IconUsers, IconTarget, IconCheck, IconArrow, IconSpark, IconTrendUp } = Icons;

/* ---- lazy-load the verbatim file bodies (only for visitors of this page) ---- */
function usePackRaw() {
  const [raw, setRaw] = React.useState(window.PackRaw || null);
  React.useEffect(() => {
    if (window.PackRaw) { setRaw(window.PackRaw); return; }
    let s = document.getElementById('pack-raw-js');
    const onload = () => setRaw(window.PackRaw || {});
    if (!s) {
      s = document.createElement('script');
      s.id = 'pack-raw-js';
      s.src = 'js/product-ai-code-review-raw.js';
      document.body.appendChild(s);
    }
    s.addEventListener('load', onload);
    return () => s.removeEventListener('load', onload);
  }, []);
  return raw;
}

/* ================================ data ================================
   Copy fields that need i18n are [en, pt] pairs — render with t(...field). */
const PASSES = [
  { id: 'general', kind: 'core', name: ['General', 'Geral'], file: 'references/general-code-review.md', size: 1994,
    line: ['The everyday pass for any language. Correctness, error handling, security, data integrity, and maintainability — reviewed in that priority order.', 'O passe do dia a dia para qualquer linguagem. Corretude, tratamento de erros, segurança, integridade de dados e manutenibilidade — nessa ordem de prioridade.'],
    when: ['Any change, any language, when no more specific pass fits.', 'Qualquer mudança, qualquer linguagem, quando nenhum passe mais específico se aplica.'],
    catches: [
      ['Correctness & edge cases', 'Corretude e casos extremos'],
      ['Error handling', 'Tratamento de erros'],
      ['Injection & unsafe input', 'Injeção e entrada insegura'],
      ['Race conditions & data integrity', 'Condições de corrida e integridade de dados'],
      ['Misleading names, dead code', 'Nomes enganosos, código morto'],
    ] },
  { id: 'pr', kind: 'core', name: ['Pull request', 'Pull request'], file: 'references/pull-request-review.md', size: 1951,
    line: ['Reviews the whole PR as a unit — scope, size, test coverage, and whether the code matches its description — not just the lines.', 'Revisa o PR inteiro como unidade — escopo, tamanho, cobertura de testes e se o código bate com a descrição — não só as linhas.'],
    when: ['Reviewing a complete PR before merge.', 'Ao revisar um PR completo antes do merge.'],
    catches: [
      ['Scope & coherence', 'Escopo e coerência'],
      ['PR size (200–400 line band)', 'Tamanho do PR (faixa de 200–400 linhas)'],
      ['Description accuracy', 'Precisão da descrição'],
      ['Untested risky paths', 'Caminhos de risco sem teste'],
      ['Migration & compat breaks', 'Migrações e quebras de compatibilidade'],
    ] },
  { id: 'large', kind: 'core', name: ['Large PR', 'PR grande'], file: 'references/large-pr-review.md', size: 3851,
    line: ['A workflow for big diffs: triage, a logical chunk plan, per-chunk review, then a synthesis pass for the risks that only surface between chunks.', 'Um fluxo para diffs grandes: triagem, plano de blocos lógicos, revisão por bloco e um passe de síntese para riscos que só aparecem entre blocos.'],
    when: ['Coherent diffs beyond ~200–400 changed lines you still need reviewed in one pass.', 'Diffs coerentes além de ~200–400 linhas alteradas que ainda precisam de revisão em um passe.'],
    catches: [
      ['Split-or-review triage', 'Triagem: dividir ou revisar'],
      ['Logical chunk plan', 'Plano de blocos lógicos'],
      ['Per-chunk findings', 'Achados por bloco'],
      ['Cross-chunk integration risk', 'Risco de integração entre blocos'],
      ['Coverage note', 'Nota de cobertura'],
    ] },
  { id: 'security', kind: 'focused', name: ['Security', 'Segurança'], file: 'references/security-review.md', size: 2243,
    line: ['A dedicated pass for anything touching auth, secrets, user input, payments, or personal data. Every finding names an attacker and what they get.', 'Um passe dedicado a tudo que toca auth, segredos, input do usuário, pagamentos ou dados pessoais. Todo achado nomeia um atacante e o que ele obtém.'],
    when: ['Auth, secrets, input handling, payments, personal data.', 'Auth, segredos, tratamento de input, pagamentos, dados pessoais.'],
    catches: [
      ['Injection: SQL, command, path', 'Injeção: SQL, comando, path'],
      ['AuthN / AuthZ & IDOR', 'AuthN / AuthZ e IDOR'],
      ['Secrets & data exposure', 'Segredos e exposição de dados'],
      ['Crypto & sessions', 'Criptografia e sessões'],
      ['Unsafe deserialization, CORS', 'Desserialização insegura, CORS'],
    ] },
  { id: 'perf', kind: 'focused', name: ['Performance', 'Performance'], file: 'references/performance-review.md', size: 1870,
    line: ['Cost at realistic scale, not micro-optimizations. Every finding estimates what gets slow — and at what data size it starts to hurt.', 'Custo em escala realista, não micro-otimizações. Todo achado estima o que fica lento — e a partir de qual volume de dados começa a doer.'],
    when: ['Hot paths, endpoints under load, batch jobs, large data.', 'Hot paths, endpoints sob carga, jobs em lote, grandes volumes de dados.'],
    catches: [
      ['N+1 queries & indexes', 'Queries N+1 e índices'],
      ['O(n²) on unbounded input', 'O(n²) em input sem limite'],
      ['Sequential I/O that could batch', 'I/O sequencial que poderia ser em lote'],
      ['Memory & streaming', 'Memória e streaming'],
      ['Lock contention on hot paths', 'Contenção de lock em hot paths'],
    ] },
  { id: 'a11y', kind: 'focused', name: ['Accessibility', 'Acessibilidade'], file: 'references/accessibility-review.md', size: 2127,
    line: ['WCAG 2.1 AA concerns on UI changes, each tied to a specific group of users and the task it blocks for them.', 'Preocupações WCAG 2.1 AA em mudanças de UI, cada uma ligada a um grupo específico de usuários e à tarefa que bloqueia para eles.'],
    when: ['Any user-facing UI change — web, Flutter, or native.', 'Qualquer mudança de UI voltada ao usuário — web, Flutter ou nativo.'],
    catches: [
      ['Semantic controls', 'Controles semânticos'],
      ['Labels & alt text', 'Labels e texto alternativo'],
      ['Keyboard operability', 'Operação por teclado'],
      ['Screen-reader state', 'Estado para leitores de tela'],
      ['Contrast & touch targets', 'Contraste e alvos de toque'],
    ] },
  { id: 'arch', kind: 'focused', name: ['Architecture', 'Arquitetura'], file: 'references/architecture-review.md', size: 3824,
    line: ['Layering and boundaries — soft hints by default, enforced only against the pattern your team names. Architecture alone is never a blocker.', 'Camadas e limites — dicas leves por padrão, reforçadas só contra o padrão que o time nomeia. Arquitetura sozinha nunca é bloqueante.'],
    when: ['New modules, big refactors, or a named pattern in conventions.', 'Novos módulos, refatorações grandes ou um padrão nomeado nas convenções.'],
    catches: [
      ['UI vs data/domain boundary', 'Limite UI vs dados/domínio'],
      ['Dependency direction', 'Direção de dependências'],
      ['Unidirectional data flow', 'Fluxo de dados unidirecional'],
      ['Global mutable state', 'Estado global mutável'],
      ['Discoverable placement', 'Organização descobrável'],
    ] },
  { id: 'api', kind: 'focused', name: ['API', 'API'], file: 'references/api-review.md', size: 1833,
    line: ['Reviewed as an interface you will live with for years — contract clarity, breaking changes, error design, pagination, and versioning.', 'Revisada como uma interface com a qual você vai conviver por anos — clareza de contrato, breaking changes, design de erros, paginação e versionamento.'],
    when: ['New or changed REST, GraphQL, RPC, or public library surfaces.', 'Novas ou alteradas superfícies REST, GraphQL, RPC ou de biblioteca pública.'],
    catches: [
      ['Contract clarity', 'Clareza de contrato'],
      ['Breaking changes', 'Breaking changes'],
      ['Error & status design', 'Design de erros e status'],
      ['Pagination & scale', 'Paginação e escala'],
      ['Idempotency & authZ granularity', 'Idempotência e granularidade de authZ'],
    ] },
  { id: 'flutter', kind: 'stack', name: ['Flutter', 'Flutter'], file: 'references/flutter-review.md', size: 2670,
    line: ['Dart/Flutter failure modes on top of the general pass — expensive build() work, disposal leaks, context-across-async crashes, layout under large text.', 'Modos de falha Dart/Flutter além do passe geral — trabalho caro em build(), leaks de dispose, crashes de context entre async, layout com texto grande.'],
    when: ['Dart / Flutter code (auto-attaches on *.dart).', 'Código Dart / Flutter (anexa automaticamente em *.dart).'],
    catches: [
      ['Heavy work in build()', 'Trabalho pesado em build()'],
      ['Undisposed controllers / streams', 'Controllers / streams sem dispose'],
      ['context across async gaps', 'context entre gaps async'],
      ['ListView.builder for long lists', 'ListView.builder para listas longas'],
      ['const constructors & keys', 'construtores const e keys'],
    ] },
  { id: 'react', kind: 'stack', name: ['React', 'React'], file: 'references/react-review.md', size: 2429,
    line: ['React/TypeScript failure modes on top of the general pass — effect dependencies, derived-state bugs, re-fetch races, and unsafe DOM.', 'Modos de falha React/TypeScript além do passe geral — dependências de effect, bugs de estado derivado, condições de corrida no re-fetch e DOM inseguro.'],
    when: ['React / TypeScript code (auto-attaches on *.tsx / *.jsx).', 'Código React / TypeScript (anexa automaticamente em *.tsx / *.jsx).'],
    catches: [
      ['useEffect deps & cleanup', 'deps e cleanup de useEffect'],
      ['Derived state stored in state', 'Estado derivado guardado em state'],
      ['Re-fetch race conditions', 'Condições de corrida no re-fetch'],
      ['Unstable refs defeating memo', 'refs instáveis que anulam memo'],
      ['dangerouslySetInnerHTML & DOM', 'dangerouslySetInnerHTML e DOM'],
    ] },
];

const KIND_LABEL = {
  core: ['Everyday', 'Dia a dia'],
  focused: ['Focused', 'Focados'],
  stack: ['Stack-specific', 'Por stack'],
};

const SKILLS = [
  { slash: '/code-review', name: ['Run a review', 'Rodar uma revisão'], file: 'skills/code-review.md', size: 3476, auto: true,
    line: ['Reviews a diff, PR, file, or staged changes — picks the right specialized pass and returns severity-ranked findings with specific fixes.', 'Revisa um diff, PR, arquivo ou mudanças staged — escolhe o passe especializado certo e devolve achados ranqueados por severidade com correções específicas.'],
    when: ['Every review. Also auto-matches plain “review this” requests.', 'Em toda revisão. Também reconhece pedidos simples de “revise isto”.'] },
  { slash: '/update-bloo-pack', name: ['Upgrade the pack', 'Atualizar o pacote'], file: 'skills/update-bloo-pack.md', size: 3788, auto: false,
    line: ['Pulls the latest prompts, checklists, and skills into your repo — preserving your filled conventions and any customizations.', 'Traz os prompts, checklists e skills mais recentes para o seu repo — preservando as convenções preenchidas e quaisquer customizações.'],
    when: ['When a new pack version ships.', 'Quando uma nova versão do pacote é lançada.'] },
  { slash: '/refresh-conventions', name: ['Re-learn the repo', 'Reaprender o repositório'], file: 'skills/refresh-conventions.md', size: 2818, auto: false,
    line: ['Re-inspects your stack, hot paths, and high-risk areas as the codebase evolves, and shows a before → after diff before writing anything.', 'Reinspeciona sua stack, hot paths e áreas de alto risco conforme o código evolui, e mostra um diff antes → depois antes de escrever qualquer coisa.'],
    when: ['After meaningful changes to stack or structure.', 'Depois de mudanças relevantes de stack ou estrutura.'] },
  { slash: '/customize-review', name: ['Add team rules', 'Adicionar regras do time'], file: 'skills/customize-review.md', size: 2019, auto: false,
    line: ['Layers in team-specific checks and severity tuning, tracked in CUSTOMIZATIONS.md so an update never clobbers them.', 'Adiciona checagens específicas do time e ajuste de severidade, rastreadas em CUSTOMIZATIONS.md para que uma atualização nunca as sobrescreva.'],
    when: ['After an incident, or to encode a team standard.', 'Depois de um incidente, ou para registrar um padrão do time.'] },
  { slash: '/review-the-review', name: ['Score a review', 'Pontuar uma revisão'], file: 'skills/review-the-review.md', size: 3011, auto: false,
    line: ['Grades an AI review against an 8-dimension rubric (0–2 each; 12+/16 is healthy) so you can calibrate the setup or compare models.', 'Avalia uma revisão de IA contra uma rubrica de 8 dimensões (0–2 cada; 12+/16 é saudável) para calibrar a configuração ou comparar modelos.'],
    when: ['When calibrating, or before trusting a new setup.', 'Ao calibrar, ou antes de confiar em uma configuração nova.'] },
];

/* ================================ styles ================================ */
const inStyles = {
  backLink: { display: 'inline-flex', alignItems: 'center', gap: 6, fontSize: 13.5, fontWeight: 500, color: 'var(--text-muted)', textDecoration: 'none', marginBottom: 18 },
  hero: { background: 'linear-gradient(180deg, var(--blue-50) 0%, var(--surface-card) 100%)', paddingTop: 64, paddingBottom: 72 },
  heroInner: { display: 'flex', flexDirection: 'column', gap: 18, alignItems: 'flex-start', maxWidth: 760 },
  h1: { fontFamily: 'var(--font-display)', fontWeight: 500, fontSize: 54, lineHeight: 1.06, letterSpacing: '-.03em', color: 'var(--text-strong)', margin: 0, textWrap: 'balance' },
  lede: { fontSize: 18.5, lineHeight: 1.55, color: 'var(--text-body)', maxWidth: 640, margin: 0 },
  band: { background: 'var(--surface-sunken)', borderTop: '1px solid var(--border-subtle)', borderBottom: '1px solid var(--border-subtle)' },

  grid3: { display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 20 },

  sevCard: { display: 'flex', flexDirection: 'column', gap: 12, alignItems: 'flex-start' },
  sevDef: { fontSize: 14.5, lineHeight: 1.6, color: 'var(--text-body)', margin: 0 },
  sevRule: { maxWidth: 720, margin: 'var(--space-10) auto 0', textAlign: 'center', fontSize: 15.5, lineHeight: 1.6, color: 'var(--text-muted)' },

  /* passes master-detail */
  md: { display: 'grid', gridTemplateColumns: '312px minmax(0, 1fr)', gap: 24, alignItems: 'start' },
  rail: { display: 'flex', flexDirection: 'column', gap: 14, position: 'sticky', top: 80 },
  railList: { display: 'flex', flexDirection: 'column', gap: 4 },
  railItem: { display: 'flex', alignItems: 'center', gap: 10, width: '100%', textAlign: 'left', border: '1px solid transparent', background: 'none', font: 'inherit', cursor: 'pointer', padding: '10px 12px', borderRadius: 'var(--radius-md)', color: 'var(--text-body)' },
  railItemActive: { background: 'var(--surface-card)', border: '1px solid var(--border-subtle)', boxShadow: 'var(--shadow-xs)', color: 'var(--text-strong)' },
  railNum: { fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--text-subtle)', width: 18, flex: 'none' },
  railName: { fontFamily: 'var(--font-display)', fontWeight: 600, fontSize: 15.5, letterSpacing: '-.01em', flex: 1 },

  detail: { display: 'flex', flexDirection: 'column', gap: 18, minWidth: 0 },
  detailHead: { display: 'flex', alignItems: 'center', gap: 10, flexWrap: 'wrap' },
  detailName: { fontFamily: 'var(--font-display)', fontWeight: 500, fontSize: 30, letterSpacing: '-.02em', color: 'var(--text-strong)', margin: 0 },
  detailLine: { fontSize: 16.5, lineHeight: 1.55, color: 'var(--text-body)', margin: 0, maxWidth: 640 },
  catchList: { listStyle: 'none', padding: 0, margin: 0, display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: '10px 24px' },
  catchItem: { display: 'flex', gap: 10, alignItems: 'flex-start', fontSize: 14.5, color: 'var(--text-body)', lineHeight: 1.45 },
  whenRow: { display: 'flex', gap: 10, alignItems: 'baseline', flexWrap: 'wrap', padding: '12px 0 2px' },
  whenLabel: { fontFamily: 'var(--font-mono)', fontSize: 10.5, letterSpacing: '.1em', color: 'var(--text-subtle)', flex: 'none' },
  whenText: { fontSize: 14, color: 'var(--text-muted)' },

  /* skills */
  skillGrid: { display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: 20 },
  skillCard: { display: 'flex', flexDirection: 'column', gap: 12, alignItems: 'flex-start', height: '100%' },
  slash: { fontFamily: 'var(--font-mono)', fontSize: 15, fontWeight: 600, color: 'var(--brand)', letterSpacing: '-.01em' },
  skillName: { fontFamily: 'var(--font-display)', fontWeight: 600, fontSize: 17, letterSpacing: '-.01em', color: 'var(--text-strong)', margin: 0 },
  skillWhen: { display: 'flex', gap: 8, alignItems: 'baseline', flexWrap: 'wrap', marginTop: 'auto', paddingTop: 4 },

  readBtn: { font: 'inherit', fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--text-link)', background: 'none', border: 'none', padding: 0, cursor: 'pointer', display: 'inline-flex', alignItems: 'center', gap: 6, textDecoration: 'none' },

  finalCta: { background: 'var(--surface-inverse)', padding: 'var(--space-21) 0' },
  finalInner: { textAlign: 'center', display: 'flex', flexDirection: 'column', gap: 18, alignItems: 'center' },
};

/* ================================ Hero ================================ */
function Hero() {
  const { t } = useT();
  return (
    <section style={inStyles.hero}>
      <div style={{ ...S.container, ...inStyles.heroInner }} className="site-container">
        <a href="product-ai-code-review.html" style={inStyles.backLink}>
          <span style={{ display: 'inline-flex', transform: 'rotate(180deg)' }}><IconArrow size={14} /></span>
          {t('AI code review skill pack', 'Pacote de skills de revisão de código com IA')}
        </a>
        <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
          <Badge tone="brand" dot>{t("What's inside", 'O que tem dentro')}</Badge>
          <Badge dot>{t('Plain Markdown · no SaaS', 'Markdown puro · sem SaaS')}</Badge>
        </div>
        <h1 style={inStyles.h1} className="site-h1-hero">{t("See exactly what you're installing.", 'Veja exatamente o que você instala.')}</h1>
        <p style={inStyles.lede}>{t('No black box. The pack is plain Markdown — ten specialized review passes, five slash commands, and drop-in integrations for Claude, Cursor, and Copilot. Browse the whole system here: open any pass to see how it works, and view exactly what lands in your repo.', 'Sem caixa-preta. O pacote é Markdown puro — dez passes de revisão especializados, cinco comandos slash e integrações nativas para Claude, Cursor e Copilot. Explore o sistema inteiro aqui: abra qualquer pass para ver como funciona e veja exatamente o que entra no seu repositório.')}</p>
        <div style={{ display: 'flex', gap: 12, flexWrap: 'wrap', marginTop: 6 }}>
          <Button as="a" href="#passes" size="lg" trailingIcon={<IconArrow />}>{t('Browse the passes', 'Ver os passes')}</Button>
          <Button as="a" href="#explorer" size="lg" variant="secondary">{t('What installs in my repo', 'O que entra no meu repo')}</Button>
        </div>
      </div>
    </section>
  );
}

/* ================================ Stats ================================ */
function Stats() {
  const { t } = useT();
  const items = [
    ['10', t('specialized review passes', 'passes de revisão especializados')],
    ['5', t('slash commands', 'comandos slash')],
    ['3', t('severity levels, one vocabulary', 'níveis de severidade, um vocabulário')],
    ['40+', t('plain-Markdown files', 'arquivos em Markdown puro')],
  ];
  return (
    <section style={S.metricsBand}>
      <div style={{ ...S.container, ...S.metricsInner }} className="site-container">
        {items.map(([n, l]) => (
          <div key={l} style={{ textAlign: 'center' }}>
            <div style={S.metricNum}>{n}</div>
            <div style={{ ...S.metricLabel, margin: '4px auto 0' }}>{l}</div>
          </div>
        ))}
      </div>
    </section>
  );
}

/* ================================ Severity ================================ */
function Severity() {
  const { t } = useT();
  const SEV = [
    { tone: 'danger', tag: t('Blocker', 'Bloqueante'), def: t('Fix before merge — correctness bugs, security flaws, data-loss risks.', 'Corrigir antes do merge — bugs de corretude, falhas de segurança, risco de perda de dados.') },
    { tone: 'warning', tag: t('Should-fix', 'Deveria corrigir'), def: t('Fix unless there’s a stated reason — missing error handling, untested risky paths, edge cases.', 'Corrigir, a menos que haja um motivo explícito — tratamento de erro ausente, caminhos de risco sem teste, casos extremos.') },
    { tone: 'neutral', tag: t('Suggestion', 'Sugestão'), def: t('Author’s judgment — naming, structure, simplification.', 'Critério do autor — nomes, estrutura, simplificação.') },
  ];
  return (
    <section style={{ ...S.section, ...inStyles.band }}>
      <div style={S.container} className="site-container">
        <div style={S.sectionHead}>
          <span style={S.eyebrow}>{t('THE VERDICT', 'O VEREDITO')}</span>
          <h2 style={S.h2}>{t('One severity vocabulary. Every pass.', 'Um vocabulário de severidade. Em todos os passes.')}</h2>
          <p style={S.sectionSub}>{t('From a two-line diff to a 2,000-line PR, every pass ranks findings the same three ways — so “blocker” means the same thing to everyone on your team.', 'De um diff de duas linhas a um PR de 2.000 linhas, todo pass classifica os achados das mesmas três formas — então “bloqueio” significa a mesma coisa para todo o time.')}</p>
        </div>
        <div style={inStyles.grid3} className="site-grid-3">
          {SEV.map((s) => (
            <Card key={s.tag} padding="lg" style={inStyles.sevCard}>
              <Badge tone={s.tone}>{s.tag}</Badge>
              <p style={inStyles.sevDef}>{s.def}</p>
            </Card>
          ))}
        </div>
        <p style={inStyles.sevRule}>{t('The rule behind all three: every finding must name the concrete scenario where the code breaks. No scenario → suggestion at most.', 'A regra por trás das três: todo achado precisa nomear o cenário concreto em que o código quebra. Sem cenário → no máximo uma sugestão.')}</p>
      </div>
    </section>
  );
}

/* ================================ Passes (master-detail) ================================ */
function Passes({ raw }) {
  const { t } = useT();
  const FileBlock = window.PackUI.FileBlock;
  const [cat, setCat] = React.useState('all');
  const [selId, setSelId] = React.useState('general');

  const cats = [
    { value: 'all', label: t('All', 'Todos'), count: PASSES.length },
    { value: 'core', label: t('Everyday', 'Dia a dia'), count: PASSES.filter((p) => p.kind === 'core').length },
    { value: 'focused', label: t('Focused', 'Focados'), count: PASSES.filter((p) => p.kind === 'focused').length },
    { value: 'stack', label: t('Stack-specific', 'Por stack'), count: PASSES.filter((p) => p.kind === 'stack').length },
  ];
  const list = cat === 'all' ? PASSES : PASSES.filter((p) => p.kind === cat);
  const sel = PASSES.find((p) => p.id === selId) || list[0];

  function pickCat(v) {
    setCat(v);
    const next = v === 'all' ? PASSES : PASSES.filter((p) => p.kind === v);
    if (!next.some((p) => p.id === selId)) setSelId(next[0].id);
  }

  return (
    <section id="passes" style={{ ...S.section, scrollMarginTop: 80 }}>
      <div style={S.container} className="site-container">
        <div style={S.sectionHead}>
          <span style={S.eyebrow}>{t('THE REVIEW PASSES', 'OS PASSES DE REVISÃO')}</span>
          <h2 style={S.h2}>{t('Ten specialized passes, each explained.', 'Dez passes especializados, cada um explicado.')}</h2>
          <p style={S.sectionSub}>{t('A pass is a focused review lens with its own checklist and output format. One generic prompt misses what a security- or performance-specific pass is built to catch. Pick one to read what it looks for — and a real excerpt of the prompt behind it.', 'Um pass é uma lente de revisão focada, com checklist e formato de saída próprios. Um prompt genérico deixa passar o que um pass específico de segurança ou performance foi feito para pegar. Escolha um para ver o que ele procura — e um trecho real do prompt por trás.')}</p>
        </div>

        <div style={{ display: 'flex', justifyContent: 'center', marginBottom: 24 }}>
          <Tabs variant="pill" value={cat} onChange={pickCat} items={cats} />
        </div>

        <div style={inStyles.md} className="pack-md">
          <div style={inStyles.rail} className="pack-md-rail">
            <div style={inStyles.railList}>
              {list.map((p, i) => {
                const active = p.id === sel.id;
                return (
                  <button key={p.id} type="button" aria-pressed={active}
                    style={{ ...inStyles.railItem, ...(active ? inStyles.railItemActive : {}) }}
                    onClick={() => setSelId(p.id)}
                    onMouseEnter={(e) => { if (!active) e.currentTarget.style.background = 'var(--surface-sunken)'; }}
                    onMouseLeave={(e) => { if (!active) e.currentTarget.style.background = 'none'; }}>
                    <span style={inStyles.railNum}>{String(PASSES.indexOf(p) + 1).padStart(2, '0')}</span>
                    <span style={inStyles.railName}>{t(...p.name)}</span>
                    <span style={{ fontFamily: 'var(--font-mono)', fontSize: 10, color: 'var(--text-subtle)' }}>{t(...KIND_LABEL[p.kind])}</span>
                  </button>
                );
              })}
            </div>
          </div>

          <div style={inStyles.detail} className="pack-md-detail">
            <div style={inStyles.detailHead}>
              <h3 style={inStyles.detailName}>{t(...sel.name)}</h3>
              <Badge tone={sel.kind === 'stack' ? 'neutral' : sel.kind === 'focused' ? 'brand' : 'success'}>{t(...KIND_LABEL[sel.kind])}</Badge>
            </div>
            <p style={inStyles.detailLine}>{t(...sel.line)}</p>
            <div>
              <div style={{ ...inStyles.whenLabel, marginBottom: 12 }}>{t('WHAT IT CATCHES', 'O QUE ELE PEGA')}</div>
              <ul style={inStyles.catchList} className="pack-catch-list">
                {sel.catches.map((c) => (
                  <li key={c[0]} style={inStyles.catchItem}>
                    <span style={S.checkDot}><IconCheck size={13} /></span>{t(...c)}
                  </li>
                ))}
              </ul>
            </div>
            <div style={inStyles.whenRow}>
              <span style={inStyles.whenLabel}>{t('USED WHEN', 'USADO QUANDO')}</span>
              <span style={inStyles.whenText}>{t(...sel.when)}</span>
            </div>
            <FileBlock path={'references/' + sel.file.split('/').pop()} size={sel.size} content={raw ? raw[sel.file] : undefined} maxHeight={300} />
          </div>
        </div>
      </div>
    </section>
  );
}

/* ================================ Skills ================================ */
function Skills({ raw, onRead }) {
  const { t } = useT();
  const featured = SKILLS[0];
  const rest = SKILLS.slice(1);
  const skillCard = (s, featuredCard) => (
    <Card key={s.slash} variant={featuredCard ? 'raised' : 'outline'} padding="lg"
      style={{ ...inStyles.skillCard, ...(featuredCard ? { borderColor: 'var(--border-brand)' } : {}) }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 10, flexWrap: 'wrap' }}>
        <span style={inStyles.slash}>{s.slash}</span>
        {s.auto
          ? <Badge tone="success" dot>{t('Auto', 'Automático')}</Badge>
          : <Badge tone="neutral">{t('On demand', 'Sob demanda')}</Badge>}
      </div>
      <h3 style={inStyles.skillName}>{t(...s.name)}</h3>
      <p style={S.cardBody}>{t(...s.line)}</p>
      <div style={inStyles.skillWhen}>
        <span style={inStyles.whenLabel}>{t('RUN IT', 'QUANDO RODAR')}</span>
        <span style={inStyles.whenText}>{t(...s.when)}</span>
      </div>
      <button type="button" style={inStyles.readBtn} onClick={() => onRead(s)}>
        {t('Preview the skill', 'Ver a skill')} <IconArrow size={13} />
      </button>
    </Card>
  );
  return (
    <section style={S.section}>
      <div style={S.container} className="site-container">
        <div style={S.sectionHead}>
          <span style={S.eyebrow}>{t('SLASH COMMANDS', 'COMANDOS SLASH')}</span>
          <h2 style={S.h2}>{t('Five commands keep it a system.', 'Cinco comandos que mantêm o pacote como um sistema.')}</h2>
          <p style={S.sectionSub}>{t('After install, your team runs these in Claude, Cursor, or Copilot. One reviews; the others keep the standard current, tailored, and honest.', 'Depois de instalar, o time roda estes no Claude, Cursor ou Copilot. Um revisa; os outros mantêm o padrão atual, ajustado e honesto.')}</p>
        </div>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 20 }}>
          {skillCard(featured, true)}
          <div style={inStyles.skillGrid} className="site-grid-2">
            {rest.map((s) => skillCard(s, false))}
          </div>
        </div>
      </div>
    </section>
  );
}

/* ================================ Explorer section ================================ */
function ExplorerSection({ raw }) {
  const { t } = useT();
  const Explorer = window.PackUI.Explorer;
  return (
    <section id="explorer" style={{ ...S.section, ...inStyles.band, scrollMarginTop: 80 }}>
      <div style={S.container} className="site-container">
        <div style={S.sectionHead}>
          <span style={S.eyebrow}>{t('THE FILES', 'OS ARQUIVOS')}</span>
          <h2 style={S.h2}>{t('See exactly what lands in your repo.', 'Veja exatamente o que entra no seu repo.')}</h2>
          <p style={S.sectionSub}>{t('Toggle the tools your team uses — the tree shows the folders that get committed. Everything is plain Markdown; open any file marked “view” to see a real excerpt.', 'Ative as ferramentas do seu time — a árvore mostra as pastas que vão para o repositório. Tudo é Markdown puro; abra qualquer arquivo marcado “view” para ver um trecho real.')}</p>
        </div>
        <Explorer raw={raw} />
      </div>
    </section>
  );
}

/* ================================ CTA ================================ */
function FinalCta() {
  const { t } = useT();
  return (
    <section id="get" style={inStyles.finalCta}>
      <div style={{ ...S.container, ...inStyles.finalInner }} className="site-container">
        <h2 style={{ ...S.h2, color: 'var(--text-onbrand)', maxWidth: 560 }}>{t('Seen enough? Get the pack.', 'Já viu o bastante? Quero o pacote.')}</h2>
        <p style={{ fontSize: 17, color: 'rgba(255,255,255,.75)', maxWidth: 520, lineHeight: 1.5, margin: '0 auto' }}>
          {t('Everything here installs and configures itself in about two minutes.', 'Tudo isso se instala e se configura em cerca de dois minutos.')}
        </p>
        <div style={{ display: 'flex', gap: 12, flexWrap: 'wrap', justifyContent: 'center', marginTop: 10 }}>
          <Button as="a" href="product-ai-code-review.html#pricing" size="lg" trailingIcon={<IconArrow />}>{t('Get the pack', 'Quero o pacote')}</Button>
          <Button as="a" href="product-ai-code-review.html" size="lg" variant="secondary"
            style={{ background: 'transparent', borderColor: 'rgba(255,255,255,.3)', color: 'var(--text-onbrand)' }}>
            {t('Back to overview', 'Voltar à visão geral')}
          </Button>
        </div>
      </div>
    </section>
  );
}

/* ================================ Page ================================ */
function ProductAiCodeReviewInsideContent() {
  const { t } = useT();
  const raw = usePackRaw();
  const [readSkill, setReadSkill] = React.useState(null);
  const FileViewer = window.PackUI.FileViewer;
  return (
    <>
      <Hero />
      <Stats />
      <Severity />
      <Passes raw={raw} />
      <Skills raw={raw} onRead={setReadSkill} />
      <ExplorerSection raw={raw} />
      <FinalCta />
      {readSkill && (
        <FileViewer
          file={{ path: '.claude/skills/' + readSkill.slash.slice(1) + '/SKILL.md', size: readSkill.size, purpose: t(...readSkill.line), raw: readSkill.file }}
          content={raw ? raw[readSkill.file] : undefined}
          onClose={() => setReadSkill(null)}
        />
      )}
    </>
  );
}

window.Pages = window.Pages || {};
window.Pages['ai-code-review-inside'] = { Content: ProductAiCodeReviewInsideContent, label: "Product — AI Code Review · What's inside" };
})();
