> ## Documentation Index
> Fetch the complete documentation index at: https://docs.morada.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Teste a ideia de um app com um protótipo navegável

> Clique entre telas e teste uma ideia de fluxo antes de investir no desenvolvimento do aplicativo.

export const mockupArtifact = {
  filename: "prototipo-obra-aurora.html",
  sha256: "44cf73565af3b498852693c4169cb84b7c74cda53c2f667d4ecb0baaaef4d466",
  html: ["<!doctype html>\n<html lang=\"pt-BR\">\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, viewport-fit=cover\">\n  <meta name=\"theme-color\" content=\"#173B35\">\n  <title>Obra Aurora — Protótipo de acompanhamento</title>\n  <style>\n    :root {\n      --bg: #F2F4F0;\n      --surface: #FFFFFF;\n      --surface-soft: #F7F8F5;\n      --ink: #16231F;\n      --muted: #66736E;\n      --line: #DDE3DF;\n      --brand: #173B35;\n      --brand-2: #245C50;\n      --accent: #F3B94E;\n      --accent-soft: #FFF3D6;\n      --success: #237A57;\n      --success-soft: #E3F4EC;\n      --danger: #A84C3D;\n      --danger-soft: #FBEAE6;\n      --info-soft: #E7F0EE;\n      --radius: 20px;\n      --shadow: 0 16px 42px rgba(23, 59, 53, .11);\n      --tap: 48px;\n    }\n\n    * { box-sizing: border-box; }\n    html { background: #DDE4DF; }\n    body {\n      margin: 0;\n      min-width: 320px;\n      min-height: 100vh;\n      color: var(--ink);\n      background: var(--bg);\n      font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif;\n      -webkit-font-smoothing: antialiased;\n    }\n    button, summary { font: inherit; }\n    button { -webkit-tap-highlight-color: transparent; }\n\n    .app-shell {\n      width: min(100%, 480px);\n      min-height: 100vh;\n      margin: 0 auto;\n      background: var(--bg);\n      position: relative;\n      box-shadow: var(--shadow);\n      overflow-x: hidden;\n    }\n\n    .app-header {\n      position: sticky;\n      top: 0;\n      z-index: 20;\n      padding: calc(14px + env(safe-area-inset-top)) 20px 14px;\n      color: #fff;\n      background: var(--brand);\n    }\n    .header-row {\n      display: flex;\n      align-items: center;\n      justify-content: space-between;\n      gap: 12px;\n    }\n    .brand-lockup { min-width: 0; }\n    .eyebrow {\n      margin: 0 0 4px;\n      color: rgba(255,255,255,.72);\n      font-size: 11px;\n      font-weight: 800;\n      letter-spacing: .1em;\n      text-transform: uppercase;\n    }\n    .project-name {\n      margin: 0;\n      font-size: 23px;\n      line-height: 1.1;\n      letter-spacing: -.02em;\n    }\n    .prototype-badge {\n      flex: 0 0 auto;\n      padding: 7px 10px;\n      border: 1px solid rgba(255,255,255,.28);\n      border-radius: 999px;\n      background: rgba(255,255,255,.10);\n      font-size: 11px;\n      font-weight: 800;\n    }\n    .fiction-note {\n      display: flex;\n      align-items: center;\n      gap: 7px;\n      margin: 13px 0 0;\n      padding-top: 11px;\n      border-top: 1px solid rgba(255,255,255,.14);\n      color: rgba(255,255,255,.8);\n      font-size: 12px;\n      line-height: 1.35;\n    }\n    .fiction-dot {\n      width: 7px;\n      height: 7px;\n      flex: 0 0 auto;\n      border-radius: 50%;\n      background: var(--accent);\n    }\n\n    main {\n      padding: 22px 18px calc(110px + env(safe-area-inset-bottom));\n    }\n    .screen { display: none; }\n    .screen.is-active { display: block; animation: screenIn .2s ease-out; }\n    @keyframes screenIn {\n      from { opacity: 0; transform: translateY(5px); }\n      to { opacity: 1; transform: none; }\n    }\n    @media (prefers-reduced-motion: reduce) {\n      *, *::before, *::after { scroll-behavior: auto !important; animation: none !important; transition: none !important; }\n    }\n\n    .screen-heading {\n      display: flex;\n      justify-content: space-between;\n      align-items: flex-start;\n      gap: 14px;\n      margin-bottom: 18px;\n    }\n    .screen-title {\n      margin: 0;\n      font-size: 27px;\n      line-height: 1.12;\n      letter-spacing: -.035em;\n      outline: none;\n    }\n    .screen-subtitle {\n      margin: 7px 0 0;\n      color: var(--muted);\n      font-size: 14px;\n      line-height: 1.45;\n    }\n    .data-tag {\n      display: inline-flex;\n      align-items: center;\n      flex: 0 0 auto;\n      min-height: 26px;\n      padding: 5px 8px;\n      border: 1px solid #E8D39B;\n      border-radius: 999px;\n      color: #6A4D14;\n      background: var(--accent-soft);\n      font-size: 10px;\n      font-we", "ight: 850;\n      letter-spacing: .04em;\n      text-transform: uppercase;\n    }\n\n    .card {\n      margin-bottom: 14px;\n      padding: 18px;\n      border: 1px solid var(--line);\n      border-radius: var(--radius);\n      background: var(--surface);\n      box-shadow: 0 6px 22px rgba(23, 59, 53, .055);\n    }\n    .card-label {\n      margin: 0;\n      color: var(--muted);\n      font-size: 12px;\n      font-weight: 800;\n      letter-spacing: .045em;\n      text-transform: uppercase;\n    }\n    .card h2, .card h3 { margin: 0; }\n    .muted { color: var(--muted); }\n    .example-inline {\n      color: var(--muted);\n      font-size: 11px;\n      font-weight: 750;\n    }\n\n    .hero-card {\n      overflow: hidden;\n      color: white;\n      border: 0;\n      background: linear-gradient(145deg, var(--brand-2), var(--brand));\n    }\n    .hero-top {\n      display: flex;\n      align-items: flex-end;\n      justify-content: space-between;\n      gap: 14px;\n      margin-top: 14px;\n    }\n    .hero-number {\n      font-size: 47px;\n      font-weight: 850;\n      line-height: .95;\n      letter-spacing: -.06em;\n    }\n    .hero-copy {\n      max-width: 150px;\n      color: rgba(255,255,255,.76);\n      font-size: 12px;\n      line-height: 1.35;\n      text-align: right;\n    }\n    .progress-track {\n      width: 100%;\n      height: 10px;\n      margin-top: 18px;\n      overflow: hidden;\n      border-radius: 999px;\n      background: rgba(255,255,255,.17);\n    }\n    .progress-bar {\n      width: var(--progress);\n      height: 100%;\n      border-radius: inherit;\n      background: var(--accent);\n    }\n    .hero-foot {\n      display: flex;\n      justify-content: space-between;\n      gap: 10px;\n      margin-top: 11px;\n      color: rgba(255,255,255,.8);\n      font-size: 12px;\n    }\n\n    .metric-grid {\n      display: grid;\n      grid-template-columns: 1fr 1fr;\n      gap: 12px;\n      margin-bottom: 14px;\n    }\n    .metric-card {\n      min-width: 0;\n      padding: 16px;\n      border: 1px solid var(--line);\n      border-radius: 18px;\n      background: var(--surface);\n    }\n    .metric-icon {\n      display: grid;\n      width: 34px;\n      height: 34px;\n      margin-bottom: 14px;\n      place-items: center;\n      border-radius: 11px;\n      color: var(--brand);\n      background: var(--info-soft);\n    }\n    .metric-icon svg { width: 18px; height: 18px; }\n    .metric-value {\n      margin: 4px 0 0;\n      font-size: 16px;\n      font-weight: 820;\n      line-height: 1.22;\n    }\n    .metric-caption {\n      margin: 5px 0 0;\n      color: var(--muted);\n      font-size: 11px;\n      line-height: 1.35;\n    }\n\n    .section-row {\n      display: flex;\n      align-items: center;\n      justify-content: space-between;\n      gap: 12px;\n      margin-bottom: 15px;\n    }\n    .section-row h2 { font-size: 18px; letter-spacing: -.02em; }\n\n    .timeline { position: relative; }\n    .timeline::before {\n      content: \"\";\n      position: absolute;\n      top: 9px;\n      bottom: 12px;\n      left: 7px;\n      width: 2px;\n      background: var(--line);\n    }\n    .timeline-item {\n      position: relative;\n      display: grid;\n      grid-template-columns: 26px 1fr auto;\n      gap: 10px;\n      align-items: start;\n      padding-bottom: 17px;\n    }\n    .timeline-item:last-child { padding-bottom: 0; }\n    .timeline-dot {\n      z-index: 1;\n      width: 16px;\n      height: 16px;\n      margin-top: 2px;\n      border: 4px solid var(--surface);\n      border-radius: 50%;\n      background: #B9C4BF;\n      box-shadow: 0 0 0 1px var(--line);\n    }\n    .timeline-item.done .timeline-dot { background: var(--success); }\n    .timeline-item.current .timeline-dot { background: var(--accent); box-shadow: 0 0 0 2px #EFC66C; }\n    .timeline-name { font-size: 14px; font-weight: 780; }\n    .timeline-date { margin-top: 3px; color: var(--muted); font-size: 11px; }\n    .timeline-state { color: var(--muted); font-size: 11px; font-weight: 750; }\n    .timeline-item.current .timeline-state { color: #7A5715; }\n\n    .notice {\n      display: flex;\n      gap: 11px;\n", "      align-items: flex-start;\n      margin-bottom: 14px;\n      padding: 14px 15px;\n      border: 1px solid #CFE0DB;\n      border-radius: 16px;\n      background: var(--info-soft);\n      color: #294A43;\n      font-size: 12px;\n      line-height: 1.45;\n    }\n    .notice svg { width: 18px; height: 18px; flex: 0 0 auto; margin-top: 1px; }\n\n    .stage-name {\n      margin-top: 7px !important;\n      font-size: 27px;\n      letter-spacing: -.04em;\n    }\n    .stage-meta {\n      display: flex;\n      flex-wrap: wrap;\n      gap: 8px;\n      margin: 12px 0 0;\n    }\n    .chip {\n      display: inline-flex;\n      align-items: center;\n      min-height: 30px;\n      padding: 6px 10px;\n      border-radius: 999px;\n      color: var(--brand);\n      background: var(--info-soft);\n      font-size: 11px;\n      font-weight: 750;\n    }\n    .task-list {\n      display: grid;\n      gap: 0;\n      margin-top: 10px;\n    }\n    .task-row {\n      display: grid;\n      grid-template-columns: 22px 1fr auto;\n      gap: 10px;\n      align-items: center;\n      min-height: 50px;\n      border-bottom: 1px solid var(--line);\n    }\n    .task-row:last-child { border-bottom: 0; }\n    .task-mark {\n      display: grid;\n      width: 20px;\n      height: 20px;\n      place-items: center;\n      border: 2px solid #B9C4BF;\n      border-radius: 50%;\n      color: white;\n    }\n    .task-row.done .task-mark { border-color: var(--success); background: var(--success); }\n    .task-row.done .task-mark::after { content: \"✓\"; font-size: 12px; font-weight: 900; }\n    .task-name { font-size: 13px; font-weight: 720; }\n    .task-status { color: var(--muted); font-size: 10px; font-weight: 750; }\n\n    details.stage-details {\n      margin-bottom: 14px;\n      border: 1px solid var(--line);\n      border-radius: var(--radius);\n      background: var(--surface);\n      box-shadow: 0 6px 22px rgba(23, 59, 53, .055);\n      overflow: hidden;\n    }\n    details.stage-details summary {\n      display: flex;\n      align-items: center;\n      justify-content: space-between;\n      min-height: 58px;\n      padding: 0 18px;\n      cursor: pointer;\n      font-weight: 820;\n      list-style: none;\n    }\n    details.stage-details summary::-webkit-details-marker { display: none; }\n    .chevron { width: 20px; height: 20px; transition: transform .18s ease; }\n    details[open] .chevron { transform: rotate(180deg); }\n    .details-body { padding: 0 18px 18px; }\n    .detail-line {\n      display: grid;\n      grid-template-columns: 1fr;\n      gap: 4px;\n      padding: 12px 0;\n      border-top: 1px solid var(--line);\n    }\n    .detail-line dt { color: var(--muted); font-size: 11px; font-weight: 750; }\n    .detail-line dd { margin: 0; font-size: 13px; font-weight: 730; line-height: 1.4; }\n\n    .pending-summary {\n      display: flex;\n      align-items: center;\n      gap: 12px;\n      margin-bottom: 14px;\n      padding: 16px 18px;\n      border: 1px solid #ECD1CB;\n      border-radius: 18px;\n      background: var(--danger-soft);\n    }\n    .pending-number {\n      display: grid;\n      width: 44px;\n      height: 44px;\n      flex: 0 0 auto;\n      place-items: center;\n      border-radius: 14px;\n      color: white;\n      background: var(--danger);\n      font-size: 20px;\n      font-weight: 850;\n    }\n    .pending-summary strong { display: block; font-size: 14px; }\n    .pending-summary span { display: block; margin-top: 3px; color: #805047; font-size: 11px; }\n\n    .pending-list { display: grid; gap: 12px; }\n    .pending-card {\n      padding: 17px;\n      border: 1px solid var(--line);\n      border-radius: var(--radius);\n      background: var(--surface);\n      box-shadow: 0 6px 22px rgba(23, 59, 53, .055);\n    }\n    .pending-card.is-resolved {\n      border-color: #C4E0D3;\n      background: #F7FCF9;\n    }\n    .pending-top {\n      display: flex;\n      justify-content: space-between;\n      gap: 10px;\n      align-items: center;\n    }\n    .priority {\n      display: inline-flex;\n      align-items: center;\n      min-height: 25px;\n      padding: 5px 8px;\n      bord", "er-radius: 999px;\n      color: #85392D;\n      background: var(--danger-soft);\n      font-size: 10px;\n      font-weight: 850;\n      letter-spacing: .035em;\n      text-transform: uppercase;\n    }\n    .priority.medium { color: #6F5116; background: var(--accent-soft); }\n    .resolved-label {\n      display: none;\n      color: var(--success);\n      font-size: 10px;\n      font-weight: 850;\n      text-transform: uppercase;\n    }\n    .pending-card.is-resolved .resolved-label { display: inline; }\n    .pending-card.is-resolved .priority { display: none; }\n    .pending-title {\n      margin: 13px 0 0;\n      font-size: 16px;\n      line-height: 1.32;\n      letter-spacing: -.015em;\n    }\n    .pending-card.is-resolved .pending-title { color: #5E7069; text-decoration: line-through; }\n    .pending-description {\n      margin: 8px 0 0;\n      color: var(--muted);\n      font-size: 12px;\n      line-height: 1.45;\n    }\n    .pending-meta {\n      display: grid;\n      grid-template-columns: 1fr 1fr;\n      gap: 9px;\n      margin-top: 14px;\n    }\n    .meta-box {\n      padding: 9px 10px;\n      border-radius: 12px;\n      background: var(--surface-soft);\n    }\n    .meta-box span { display: block; color: var(--muted); font-size: 9px; font-weight: 800; text-transform: uppercase; }\n    .meta-box strong { display: block; margin-top: 3px; font-size: 11px; line-height: 1.3; }\n\n    .action-button, .secondary-button {\n      width: 100%;\n      min-height: var(--tap);\n      margin-top: 14px;\n      padding: 12px 16px;\n      border-radius: 14px;\n      cursor: pointer;\n      font-weight: 820;\n    }\n    .action-button {\n      color: white;\n      border: 1px solid var(--brand);\n      background: var(--brand);\n    }\n    .secondary-button {\n      color: var(--brand);\n      border: 1px solid #B8CAC4;\n      background: transparent;\n    }\n    .action-button:hover { background: var(--brand-2); }\n    .pending-card.is-resolved .action-button {\n      color: var(--success);\n      border-color: #B7D9CA;\n      background: var(--success-soft);\n    }\n    button:focus-visible, summary:focus-visible {\n      outline: 3px solid #F3B94E;\n      outline-offset: 3px;\n    }\n\n    .empty-state {\n      display: none;\n      padding: 28px 20px;\n      text-align: center;\n      border: 1px dashed #BFD4CC;\n      border-radius: var(--radius);\n      background: var(--surface);\n    }\n    .empty-state.is-visible { display: block; }\n    .empty-state-icon {\n      display: grid;\n      width: 48px;\n      height: 48px;\n      margin: 0 auto 12px;\n      place-items: center;\n      border-radius: 50%;\n      color: var(--success);\n      background: var(--success-soft);\n      font-size: 22px;\n      font-weight: 900;\n    }\n    .empty-state h2 { margin: 0; font-size: 17px; }\n    .empty-state p { margin: 7px 0 0; color: var(--muted); font-size: 12px; line-height: 1.45; }\n\n    .bottom-nav {\n      position: fixed;\n      z-index: 30;\n      bottom: 0;\n      left: 50%;\n      width: min(100%, 480px);\n      min-height: 76px;\n      padding: 9px 12px calc(9px + env(safe-area-inset-bottom));\n      transform: translateX(-50%);\n      display: grid;\n      grid-template-columns: repeat(3, 1fr);\n      gap: 7px;\n      border-top: 1px solid var(--line);\n      background: rgba(255,255,255,.96);\n      box-shadow: 0 -10px 30px rgba(23, 59, 53, .08);\n      backdrop-filter: blur(14px);\n    }\n    .nav-button {\n      min-height: 56px;\n      padding: 6px 4px;\n      display: flex;\n      flex-direction: column;\n      align-items: center;\n      justify-content: center;\n      gap: 4px;\n      color: var(--muted);\n      border: 0;\n      border-radius: 13px;\n      background: transparent;\n      cursor: pointer;\n      font-size: 10px;\n      font-weight: 760;\n    }\n    .nav-button svg { width: 21px; height: 21px; }\n    .nav-button.is-active { color: var(--brand); background: var(--info-soft); }\n    .nav-count {\n      position: absolute;\n      margin: -24px 0 0 22px;\n      min-width: 18px;\n      height: 18px;\n      padding: 0 5px;\n      display: grid;\n    ", "  place-items: center;\n      border: 2px solid white;\n      border-radius: 999px;\n      color: white;\n      background: var(--danger);\n      font-size: 9px;\n      font-weight: 850;\n    }\n    .nav-count[hidden] { display: none; }\n\n    .toast {\n      position: fixed;\n      z-index: 50;\n      left: 50%;\n      bottom: calc(92px + env(safe-area-inset-bottom));\n      width: min(calc(100% - 36px), 420px);\n      padding: 13px 15px;\n      transform: translate(-50%, 20px);\n      border-radius: 14px;\n      color: white;\n      background: #102E29;\n      box-shadow: var(--shadow);\n      opacity: 0;\n      pointer-events: none;\n      font-size: 12px;\n      line-height: 1.4;\n      transition: opacity .18s ease, transform .18s ease;\n    }\n    .toast.is-visible { opacity: 1; transform: translate(-50%, 0); }\n\n    @media (min-width: 481px) {\n      body { padding: 24px 0; }\n      .app-shell { min-height: calc(100vh - 48px); border-radius: 28px; overflow: hidden; }\n      .app-header { border-radius: 28px 28px 0 0; }\n      .bottom-nav { bottom: 24px; border-radius: 0 0 28px 28px; }\n    }\n  </style>\n</head>\n<body>\n  <div class=\"app-shell\">\n    <header class=\"app-header\">\n      <div class=\"header-row\">\n        <div class=\"brand-lockup\">\n          <p class=\"eyebrow\">Acompanhamento de obra</p>\n          <p class=\"project-name\"><strong>Obra Aurora</strong></p>\n        </div>\n        <span class=\"prototype-badge\">Protótipo</span>\n      </div>\n      <p class=\"fiction-note\"><span class=\"fiction-dot\" aria-hidden=\"true\"></span>Todos os nomes, datas, percentuais e responsáveis são exemplos fictícios.</p>\n    </header>\n\n    <main>\n      <section class=\"screen is-active\" id=\"screen-overview\" data-screen=\"overview\" aria-labelledby=\"title-overview\">\n        <div class=\"screen-heading\">\n          <div>\n            <h1 class=\"screen-title\" id=\"title-overview\" tabindex=\"-1\">Visão geral</h1>\n            <p class=\"screen-subtitle\">Resumo rápido para acompanhar o andamento.</p>\n          </div>\n          <span class=\"data-tag\">Dados de exemplo</span>\n        </div>\n\n        <article class=\"card hero-card\">\n          <p class=\"card-label\" style=\"color:rgba(255,255,255,.68)\">Avanço físico · exemplo</p>\n          <div class=\"hero-top\">\n            <strong class=\"hero-number\">42%</strong>\n            <span class=\"hero-copy\">Percentual ilustrativo do projeto completo</span>\n          </div>\n          <div class=\"progress-track\" role=\"progressbar\" aria-label=\"Avanço físico de exemplo\" aria-valuemin=\"0\" aria-valuemax=\"100\" aria-valuenow=\"42\">\n            <div class=\"progress-bar\" style=\"--progress:42%\"></div>\n          </div>\n          <div class=\"hero-foot\"><span>Início: 10/02/2026</span><span>Entrega: 15/11/2027</span></div>\n        </article>\n\n        <div class=\"metric-grid\" aria-label=\"Indicadores de exemplo\">\n          <article class=\"metric-card\">\n            <span class=\"metric-icon\" aria-hidden=\"true\">\n              <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M8 2v4M16 2v4M3 10h18M5 5h14a2 2 0 0 1 2 2v12H3V7a2 2 0 0 1 2-2Z\"/></svg>\n            </span>\n            <p class=\"card-label\">Prazo · exemplo</p>\n            <p class=\"metric-value\">No planejado</p>\n            <p class=\"metric-caption\">Referência fictícia</p>\n          </article>\n          <article class=\"metric-card\">\n            <span class=\"metric-icon\" aria-hidden=\"true\">\n              <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M4 20V10l8-6 8 6v10H4Z\"/><path d=\"M9 20v-6h6v6\"/></svg>\n            </span>\n            <p class=\"card-label\">Etapa · exemplo</p>\n            <p class=\"metric-value\">Estrutura</p>\n            <p class=\"metric-caption\">63% concluída</p>\n          </article>\n        </div>\n\n        <article class=\"card\">\n          <div class=\"section-row\">\n            <h2>Marcos da obra</h2>\n            <span class=\"example-inline\">Exemplos</span>\n          </div>\n          <div class=\"timeline\">\n            <div class=", "\"timeline-item done\">\n              <span class=\"timeline-dot\" aria-hidden=\"true\"></span>\n              <div><div class=\"timeline-name\">Fundação</div><div class=\"timeline-date\">Concluída em 18/08/2026 · exemplo</div></div>\n              <span class=\"timeline-state\">Concluída</span>\n            </div>\n            <div class=\"timeline-item current\">\n              <span class=\"timeline-dot\" aria-hidden=\"true\"></span>\n              <div><div class=\"timeline-name\">Estrutura</div><div class=\"timeline-date\">20/08 a 28/09/2026 · exemplo</div></div>\n              <span class=\"timeline-state\">Atual</span>\n            </div>\n            <div class=\"timeline-item\">\n              <span class=\"timeline-dot\" aria-hidden=\"true\"></span>\n              <div><div class=\"timeline-name\">Alvenaria</div><div class=\"timeline-date\">Início previsto: 01/10/2026 · exemplo</div></div>\n              <span class=\"timeline-state\">Próxima</span>\n            </div>\n            <div class=\"timeline-item\">\n              <span class=\"timeline-dot\" aria-hidden=\"true\"></span>\n              <div><div class=\"timeline-name\">Instalações</div><div class=\"timeline-date\">Início previsto: 16/11/2026 · exemplo</div></div>\n              <span class=\"timeline-state\">Planejada</span>\n            </div>\n          </div>\n        </article>\n      </section>\n\n      <section class=\"screen\" id=\"screen-stage\" data-screen=\"stage\" aria-labelledby=\"title-stage\" hidden>\n        <div class=\"screen-heading\">\n          <div>\n            <h1 class=\"screen-title\" id=\"title-stage\" tabindex=\"-1\">Etapa atual</h1>\n            <p class=\"screen-subtitle\">Detalhes do trabalho em andamento.</p>\n          </div>\n          <span class=\"data-tag\">Dados de exemplo</span>\n        </div>\n\n        <article class=\"card\">\n          <p class=\"card-label\">Etapa ilustrativa</p>\n          <h2 class=\"stage-name\">Estrutura</h2>\n          <div class=\"stage-meta\">\n            <span class=\"chip\">20/08 a 28/09/2026 · exemplo</span>\n            <span class=\"chip\">Status: em andamento · exemplo</span>\n          </div>\n          <div class=\"hero-top\" style=\"margin-top:22px;color:var(--ink)\">\n            <strong class=\"hero-number\" style=\"font-size:39px\">63%</strong>\n            <span class=\"hero-copy\" style=\"color:var(--muted)\">Avanço ilustrativo desta etapa</span>\n          </div>\n          <div class=\"progress-track\" role=\"progressbar\" aria-label=\"Avanço da etapa de exemplo\" aria-valuemin=\"0\" aria-valuemax=\"100\" aria-valuenow=\"63\" style=\"background:#E6EBE8\">\n            <div class=\"progress-bar\" style=\"--progress:63%;background:var(--brand-2)\"></div>\n          </div>\n        </article>\n\n        <article class=\"card\">\n          <div class=\"section-row\">\n            <h2>Atividades</h2>\n            <span class=\"example-inline\">Exemplos</span>\n          </div>\n          <div class=\"task-list\">\n            <div class=\"task-row done\"><span class=\"task-mark\" aria-hidden=\"true\"></span><span class=\"task-name\">Pilares do térreo</span><span class=\"task-status\">Concluída</span></div>\n            <div class=\"task-row done\"><span class=\"task-mark\" aria-hidden=\"true\"></span><span class=\"task-name\">Vigas do 1º pavimento</span><span class=\"task-status\">Concluída</span></div>\n            <div class=\"task-row\"><span class=\"task-mark\" aria-hidden=\"true\"></span><span class=\"task-name\">Laje do 2º pavimento</span><span class=\"task-status\">Em execução</span></div>\n            <div class=\"task-row\"><span class=\"task-mark\" aria-hidden=\"true\"></span><span class=\"task-name\">Escada estrutural</span><span class=\"task-status\">A iniciar</span></div>\n          </div>\n        </article>\n\n        <details class=\"stage-details\">\n          <summary>\n            <span>Ver detalhes da etapa</span>\n            <svg class=\"chevron\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\"><path d=\"m6 9 6 6 6-6\"/></svg>\n          </summary>\n          <div class=\"details-body\">\n            <dl style=\"margin:0\">\n              <div c", "lass=\"detail-line\"><dt>Responsável · exemplo</dt><dd>Eng. Marina Costa — equipe fictícia</dd></div>\n              <div class=\"detail-line\"><dt>Próxima verificação · exemplo</dt><dd>Conferência de armação em 24/09/2026</dd></div>\n              <div class=\"detail-line\"><dt>Frente de trabalho · exemplo</dt><dd>Bloco A, 2º pavimento</dd></div>\n              <div class=\"detail-line\"><dt>Observação · exemplo</dt><dd>Concretagem prevista após a liberação ilustrativa da armação.</dd></div>\n            </dl>\n          </div>\n        </details>\n\n        <div class=\"notice\">\n          <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\"><circle cx=\"12\" cy=\"12\" r=\"9\"/><path d=\"M12 11v5M12 8h.01\"/></svg>\n          <span>Este protótipo não possui login, integração, envio de dados nem armazenamento permanente.</span>\n        </div>\n      </section>\n\n      <section class=\"screen\" id=\"screen-pending\" data-screen=\"pending\" aria-labelledby=\"title-pending\" hidden>\n        <div class=\"screen-heading\">\n          <div>\n            <h1 class=\"screen-title\" id=\"title-pending\" tabindex=\"-1\">Pendências</h1>\n            <p class=\"screen-subtitle\">Itens ilustrativos que pedem atenção.</p>\n          </div>\n          <span class=\"data-tag\">Dados de exemplo</span>\n        </div>\n\n        <div class=\"pending-summary\" id=\"pending-summary\" aria-live=\"polite\">\n          <span class=\"pending-number\" id=\"pending-number\">3</span>\n          <div><strong id=\"pending-summary-text\">3 pendências abertas</strong><span>Contagem apenas deste protótipo</span></div>\n        </div>\n\n        <div class=\"notice\">\n          <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\"><circle cx=\"12\" cy=\"12\" r=\"9\"/><path d=\"M12 11v5M12 8h.01\"/></svg>\n          <span>Ao marcar um item, a mudança vale somente enquanto este arquivo estiver aberto. Nada será enviado ou salvo.</span>\n        </div>\n\n        <div class=\"pending-list\" id=\"pending-list\">\n          <article class=\"pending-card\" data-pending-id=\"p1\">\n            <div class=\"pending-top\"><span class=\"priority\">Prioridade alta · exemplo</span><span class=\"resolved-label\">Resolvida no protótipo</span><span class=\"example-inline\">Exemplo 01</span></div>\n            <h2 class=\"pending-title\">Validar armação da laje</h2>\n            <p class=\"pending-description\">Conferir a armação antes da concretagem ilustrativa do 2º pavimento.</p>\n            <div class=\"pending-meta\">\n              <div class=\"meta-box\"><span>Prazo · exemplo</span><strong>24/09/2026</strong></div>\n              <div class=\"meta-box\"><span>Responsável · exemplo</span><strong>Eng. Marina</strong></div>\n            </div>\n            <button class=\"action-button resolve-button\" type=\"button\" aria-pressed=\"false\">Marcar como resolvida</button>\n          </article>\n\n          <article class=\"pending-card\" data-pending-id=\"p2\">\n            <div class=\"pending-top\"><span class=\"priority medium\">Prioridade média · exemplo</span><span class=\"resolved-label\">Resolvida no protótipo</span><span class=\"example-inline\">Exemplo 02</span></div>\n            <h2 class=\"pending-title\">Confirmar entrega do concreto</h2>\n            <p class=\"pending-description\">Confirmar o horário fictício de chegada com o fornecedor de exemplo.</p>\n            <div class=\"pending-meta\">\n              <div class=\"meta-box\"><span>Prazo · exemplo</span><strong>25/09/2026</strong></div>\n              <div class=\"meta-box\"><span>Responsável · exemplo</span><strong>Paulo Nunes</strong></div>\n            </div>\n            <button class=\"action-button resolve-button\" type=\"button\" aria-pressed=\"false\">Marcar como resolvida</button>\n          </article>\n\n          <article class=\"pending-card\" data-pending-id=\"p3\">\n            <div class=\"pending-top\"><span class=\"priority medium\">Prioridade média · exemplo</span><span class=\"resolved-label\">Resolvida no protótipo</span><span class=\"example-inline\">Exemplo 03</span></div>\n  ", "          <h2 class=\"pending-title\">Registrar inspeção de segurança</h2>\n            <p class=\"pending-description\">Revisar o checklist ilustrativo da frente de trabalho do Bloco A.</p>\n            <div class=\"pending-meta\">\n              <div class=\"meta-box\"><span>Prazo · exemplo</span><strong>26/09/2026</strong></div>\n              <div class=\"meta-box\"><span>Responsável · exemplo</span><strong>Carla Lima</strong></div>\n            </div>\n            <button class=\"action-button resolve-button\" type=\"button\" aria-pressed=\"false\">Marcar como resolvida</button>\n          </article>\n        </div>\n\n        <div class=\"empty-state\" id=\"empty-state\">\n          <div class=\"empty-state-icon\" aria-hidden=\"true\">✓</div>\n          <h2>Todas resolvidas neste teste</h2>\n          <p>Reabra um item acima para continuar experimentando. Nada foi salvo fora deste protótipo.</p>\n        </div>\n      </section>\n    </main>\n\n    <nav class=\"bottom-nav\" aria-label=\"Navegação principal do protótipo\">\n      <button class=\"nav-button is-active\" type=\"button\" data-target=\"overview\" aria-current=\"page\">\n        <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\"><path d=\"M4 13h6V4H4v9ZM14 20h6v-9h-6v9ZM4 20h6v-3H4v3ZM14 7h6V4h-6v3Z\"/></svg>\n        <span>Visão geral</span>\n      </button>\n      <button class=\"nav-button\" type=\"button\" data-target=\"stage\">\n        <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\"><path d=\"M4 20V10l8-6 8 6v10H4Z\"/><path d=\"M8 20v-7h8v7\"/></svg>\n        <span>Etapa atual</span>\n      </button>\n      <button class=\"nav-button\" type=\"button\" data-target=\"pending\">\n        <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\"><path d=\"M12 8v5M12 17h.01\"/><path d=\"M10.3 3.6 2.8 17a2 2 0 0 0 1.7 3h15a2 2 0 0 0 1.7-3L13.7 3.6a2 2 0 0 0-3.4 0Z\"/></svg>\n        <span class=\"nav-count\" id=\"nav-count\">3</span>\n        <span>Pendências</span>\n      </button>\n    </nav>\n\n    <div class=\"toast\" id=\"toast\" role=\"status\" aria-live=\"polite\"></div>\n  </div>\n\n  <script>\n    (() => {\n      const screens = [...document.querySelectorAll('.screen')];\n      const navButtons = [...document.querySelectorAll('.nav-button')];\n      const pendingCards = [...document.querySelectorAll('.pending-card')];\n      const pendingNumber = document.getElementById('pending-number');\n      const pendingSummaryText = document.getElementById('pending-summary-text');\n      const navCount = document.getElementById('nav-count');\n      const emptyState = document.getElementById('empty-state');\n      const toast = document.getElementById('toast');\n      let toastTimer;\n\n      function showToast(message) {\n        toast.textContent = message;\n        toast.classList.add('is-visible');\n        clearTimeout(toastTimer);\n        toastTimer = setTimeout(() => toast.classList.remove('is-visible'), 2200);\n      }\n\n      function navigate(target, moveFocus = true) {\n        screens.forEach((screen) => {\n          const active = screen.dataset.screen === target;\n          screen.classList.toggle('is-active', active);\n          screen.hidden = !active;\n        });\n        navButtons.forEach((button) => {\n          const active = button.dataset.target === target;\n          button.classList.toggle('is-active', active);\n          if (active) button.setAttribute('aria-current', 'page');\n          else button.removeAttribute('aria-current');\n        });\n        window.scrollTo({ top: 0, behavior: 'smooth' });\n        if (moveFocus) {\n          const heading = document.querySelector(`[data-screen=\"${target}\"] .screen-title`);\n          if (heading) setTimeout(() => heading.focus({ preventScroll: true }), 120);\n        }\n      }\n\n      function updatePendingSummary() {\n        const openCount = pendingCards.filter(card => !card.classList.contains('is-resolved')).length;\n        pendingNumber.textContent = String(openCount);\n        pendingSummaryText.text", "Content = openCount === 1 ? '1 pendência aberta' : `${openCount} pendências abertas`;\n        navCount.textContent = String(openCount);\n        navCount.hidden = openCount === 0;\n        emptyState.classList.toggle('is-visible', openCount === 0);\n      }\n\n      navButtons.forEach((button) => {\n        button.addEventListener('click', () => navigate(button.dataset.target));\n      });\n\n      pendingCards.forEach((card) => {\n        const button = card.querySelector('.resolve-button');\n        button.addEventListener('click', () => {\n          const nowResolved = !card.classList.contains('is-resolved');\n          card.classList.toggle('is-resolved', nowResolved);\n          button.setAttribute('aria-pressed', String(nowResolved));\n          button.textContent = nowResolved ? 'Reabrir no protótipo' : 'Marcar como resolvida';\n          updatePendingSummary();\n          showToast(nowResolved\n            ? 'Pendência resolvida somente neste protótipo.'\n            : 'Pendência reaberta somente neste protótipo.');\n        });\n      });\n\n      updatePendingSummary();\n    })();\n  </script>\n</body>\n</html>\n"].join("")
};

export const GeneratedArtifact = ({example, source, language = "pt"}) => {
  const [artifact, setArtifact] = useState(null);
  const [expanded, setExpanded] = useState(false);
  const [canExpand, setCanExpand] = useState(false);
  const [expandFailed, setExpandFailed] = useState(false);
  const id = `generated-artifact-${example}`;
  const labels = language === "en" ? {
    loading: "Opening the generated example…",
    expand: "Enlarge example",
    restore: "Exit full screen",
    download: "Download original file",
    title: "Complete generated example",
    expandError: "Full screen is unavailable in this browser. You can still explore the example below or download it.",
    note: "Complete file generated in a Morada OS test conversation with fictional data. Scroll inside the example to explore the whole page."
  } : {
    loading: "Abrindo o exemplo gerado…",
    expand: "Ampliar exemplo",
    restore: "Sair da tela cheia",
    download: "Baixar arquivo original",
    title: "Exemplo completo gerado",
    expandError: "Não foi possível ampliar neste navegador. Você pode explorar o exemplo abaixo ou baixar o arquivo.",
    note: "Arquivo completo gerado em uma conversa de teste do Morada OS, com dados fictícios. Role dentro do exemplo para explorar a página inteira."
  };
  useEffect(() => {
    setExpandFailed(false);
    const escapes = {
      "&": "&amp;",
      '"': "&quot;",
      "<": "&lt;",
      ">": "&gt;"
    };
    const html = source.html.replace(/[&"<>]/g, character => escapes[character]);
    const policy = "default-src 'none'; script-src 'unsafe-inline'; style-src 'unsafe-inline'; img-src data: blob:; font-src data:; connect-src 'none'; base-uri 'none'; form-action 'none'; frame-src 'none'; worker-src 'none'; webrtc 'block'";
    const srcDoc = `<!doctype html><html><head><meta charset="utf-8"><base href="about:srcdoc"><meta http-equiv="Content-Security-Policy" content="${policy}"><meta name="referrer" content="no-referrer"><style>html,body{height:100%;margin:0}iframe{display:block;width:100%;height:100%;border:0}</style></head><body><iframe title="${language === "en" ? "Generated content" : "Conteúdo gerado"}" sandbox="allow-scripts allow-forms" referrerpolicy="no-referrer" srcdoc="${html}"></iframe></body></html>`;
    setArtifact({
      filename: source.filename,
      html: source.html,
      srcDoc
    });
  }, [source.html, source.filename, language]);
  useEffect(() => {
    setCanExpand(Boolean(document.fullscreenEnabled));
    const changed = () => setExpanded(document.fullscreenElement?.id === id);
    document.addEventListener("fullscreenchange", changed);
    return () => document.removeEventListener("fullscreenchange", changed);
  }, [id]);
  const download = () => {
    if (!artifact) return;
    const url = URL.createObjectURL(new Blob([artifact.html], {
      type: "text/html;charset=utf-8"
    }));
    const anchor = document.createElement("a");
    anchor.href = url;
    anchor.download = artifact.filename;
    document.body.appendChild(anchor);
    anchor.click();
    anchor.remove();
    setTimeout(() => URL.revokeObjectURL(url), 1000);
  };
  const enlarge = () => {
    setExpandFailed(false);
    const action = expanded ? document.exitFullscreen() : document.getElementById(id)?.requestFullscreen();
    action?.catch(() => setExpandFailed(true));
  };
  const css = `
.mo-artifact { --artifact-bg:#f8fafc; --artifact-ink:#1e293b; --artifact-line:#cbd5e1; --artifact-hover:#e2e8f0; margin:24px 0; border:1px solid var(--artifact-line); border-radius:16px; overflow:hidden; background:var(--artifact-bg); color:var(--artifact-ink); }
.dark .mo-artifact { --artifact-bg:#18212e; --artifact-ink:#f1f5f9; --artifact-line:#475569; --artifact-hover:#334155; }
.mo-artifact:fullscreen { width:100vw; height:100dvh; border:0; border-radius:0; margin:0; display:flex; flex-direction:column; }
.mo-artifact .artifact-toolbar { display:flex; align-items:center; flex-wrap:wrap; gap:8px; padding:12px; border-bottom:1px solid var(--artifact-line); flex-shrink:0; }
.mo-artifact .artifact-name { flex:1 1 180px; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-size:12px; }
.mo-artifact button { min-height:44px; padding:8px 12px; border:1px solid var(--artifact-line); border-radius:8px; color:var(--artifact-ink); background:transparent; cursor:pointer; font:inherit; font-size:12px; }
.mo-artifact button:hover { background:var(--artifact-hover); }
.mo-artifact button:active { box-shadow:inset 0 0 0 2px var(--artifact-ink); }
.mo-artifact button:focus-visible { outline:3px solid #2683eb; outline-offset:2px; }
.mo-artifact button:disabled { cursor:default; opacity:.5; }
.mo-artifact > iframe { display:block; width:100%; height:720px; border:0; background:white; }
.mo-artifact:fullscreen > iframe { flex:1; min-height:0; height:100%; }
.mo-artifact .artifact-status { padding:24px; font-size:14px; }
.mo-artifact .artifact-note { margin:0; padding:12px; font-size:12px; line-height:1.6; color:var(--artifact-ink); border-top:1px solid var(--artifact-line); }
.mo-artifact:fullscreen .artifact-note { display:none; }
@media(max-width:600px) { .mo-artifact > iframe { height:640px; } .mo-artifact .artifact-name { flex-basis:100%; } }
`;
  return <section id={id} className="mo-artifact" aria-label={labels.title}>
      <style>{css}</style>
      <div className="artifact-toolbar">
        <span className="artifact-name" title={artifact?.filename}>
          {artifact?.filename || labels.title}
        </span>
        {canExpand && <button type="button" onClick={enlarge} disabled={!artifact}>
            {expanded ? labels.restore : labels.expand}
          </button>}
        <button type="button" onClick={download} disabled={!artifact}>
          {labels.download}
        </button>
      </div>
      {artifact ? <iframe title={labels.title} srcDoc={artifact.srcDoc} sandbox="allow-scripts allow-forms" referrerPolicy="no-referrer" /> : <div className="artifact-status" role="status">
          {labels.loading}
        </div>}
      {expandFailed && <p className="artifact-note" role="status">
          {labels.expandError}
        </p>}
      <p className="artifact-note">{labels.note}</p>
    </section>;
};

**Precisa de:** quem vai usar o app e qual tarefa essa pessoa precisa realizar · **Exemplo:** acompanhar uma obra

Uma lista de requisitos nem sempre mostra onde um fluxo ficou complicado. Um **protótipo navegável** é um rascunho de telas com botões que permitem experimentar a ideia. Também chamado de mockup, ele ajuda o time a discutir o caminho do usuário antes de construir o aplicativo de verdade.

## Experimente o caminho do usuário

Troque de tela e marque a pendência do exemplo. São informações fictícias: nada altera uma obra ou um sistema real.

<GeneratedArtifact example="mockup" source={mockupArtifact} language="pt" />

<Note>Protótipo completo gerado pela assistente. Não é uma tela existente do Morada OS nem um aplicativo conectado.</Note>

## Copie este pedido

```text wrap theme={null}
Quero testar uma ideia de app para um gestor acompanhar uma obra. Crie um protótipo em que eu possa navegar por três telas: visão geral, etapa atual e pendências. Use uma obra fictícia chamada Aurora e identifique todos os dados como exemplos. Quero clicar para mudar de tela, ver detalhes da etapa e marcar uma pendência como resolvida apenas no protótipo. Use rótulos claros, poucos controles por tela e layout confortável no celular. Não simule login nem conexão com sistemas reais. Entregue como um arquivo que eu possa abrir e testar no chat.
```

**O mais importante é a tarefa**, não a lista de telas. Se o objetivo for outro — comparar unidades, preparar uma visita ou acompanhar solicitações — conte o que a pessoa precisa conseguir fazer e peça um fluxo para isso.

## Teste antes de pedir mais telas

1. **Clique no card do arquivo** e abra **Visualização**.
2. Tente realizar a tarefa sem precisar de uma explicação adicional. Use **Expandir visualização** para avaliar o fluxo com mais espaço.
3. Anote onde ficou em dúvida e peça um ajuste na mesma conversa. **Baixar arquivo** salva o protótipo original.

## Exemplos de feedback que ajudam

> "Não ficou claro qual etapa merece atenção. Dê destaque à pendência mais importante na primeira tela."

> "Junte etapa atual e pendências para reduzir um clique."

> "Inclua um estado sem pendências e um caminho para voltar à visão geral."

Você está validando **navegação, clareza e organização**. O protótipo não comprova que uma integração funciona e não substitui o desenvolvimento do app. Alterações feitas durante a exploração podem reiniciar ao reabrir; para guardar uma mudança, peça uma nova versão do arquivo.

[Conheça os controles e limites da visualização](/morada-os/casos-de-uso/crie-experiencias-visuais).
