/**
* Boletim renderer (C186; sober redesign C209): one A4 `.sheet` in voter-facing
* language. Ports the approved hi-fi classes
* (`docs/plans/dossies-sobrios-analiticos-ui-design.html`, cena 12) — list-based,
* no cards, badges or image placeholders. No source list: the facts come from
* the dossiê ledger, and the page is labelled as an internal model.
*/
import { isSubjectUnit } from './dossieUnit.mjs'
import { htmlEscape, moreItemsLabel } from './reportText.mjs'
const PRINT_CSS = `
* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body { font-family: 'Fira Sans', 'DejaVu Sans', Arial, sans-serif; color: var(--ink); background: #fff; }
:root {
--ink: #18232d;
--ink-soft: #52616d;
--accent: #4d6d7c;
--line: #bdc8ce;
--line-light: #dce3e6;
}
@page { size: A4; margin: 0; }
.sheet {
position: relative;
display: flex;
width: 210mm;
height: 297mm;
min-height: 297mm;
padding: 15mm 17mm 13mm;
overflow: hidden;
flex-direction: column;
background: #fff;
font-size: 9.4pt;
line-height: 1.42;
}
.sheet p, .sheet ul, .sheet ol, .sheet h1, .sheet h2 { margin-top: 0; }
.running-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 10mm; padding-bottom: 3mm; border-bottom: .35mm solid var(--ink); }
.running-kicker { margin: 0; color: var(--accent); font-size: 7.5pt; font-weight: 700; letter-spacing: .11em; text-transform: uppercase; }
.running-subtitle { margin: 1mm 0 0; color: var(--ink-soft); font-size: 8.7pt; }
.running-meta { min-width: 41mm; margin: 0; color: var(--ink-soft); font-size: 7.3pt; line-height: 1.45; text-align: right; }
.running-meta p { margin: 0; }
.running-footer { display: flex; margin-top: auto; padding-top: 2.6mm; border-top: .25mm solid var(--line); align-items: flex-end; justify-content: space-between; gap: 8mm; color: var(--ink-soft); font-size: 7.2pt; line-height: 1.3; }
.running-footer strong { color: var(--ink); }
.folio { color: var(--ink); font-weight: 700; white-space: nowrap; }
.section { margin-top: 5mm; }
.section + .section { margin-top: 6mm; }
.eyebrow { margin: 0 0 1.3mm; color: var(--accent); font-size: 7.2pt; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; }
.bulletin-title { max-width: 162mm; margin: 12mm 0 0; font-size: 28pt; font-weight: 650; line-height: 1.02; letter-spacing: -.035em; }
.bulletin-title span { color: var(--accent); }
.bulletin-lede { max-width: 155mm; margin: 4mm 0 0; color: var(--ink-soft); font-size: 10.2pt; line-height: 1.45; }
.bulletin-list { margin: 3mm 0 0; padding: 0; border-top: .35mm solid var(--ink); list-style: none; }
.bulletin-list li { display: grid; padding: 2.6mm 0; border-bottom: .2mm solid var(--line-light); grid-template-columns: 38mm 1fr; gap: 4mm; }
.bulletin-list strong { font-size: 8.6pt; }
.bulletin-list span { color: var(--ink-soft); font-size: 8.6pt; }
.bulletin-defense-list { margin: 3mm 0 0; padding: 0; border-top: .35mm solid var(--ink); list-style: none; }
.bulletin-defense-list li { display: grid; padding: 2.4mm 0; border-bottom: .2mm solid var(--line-light); grid-template-columns: 52mm 1fr; gap: 4mm; }
.bulletin-defense-list strong { font-size: 8.7pt; }
.bulletin-defense-list span { color: var(--ink-soft); font-size: 8.5pt; line-height: 1.35; }
.period-list { display: grid; margin: 3mm 0 0; padding: 0; border-top: .35mm solid var(--ink); grid-template-columns: 1fr 1fr; list-style: none; }
.period-list li { min-height: 18mm; padding: 2.6mm 4mm 2.6mm 0; border-bottom: .2mm solid var(--line-light); }
.period-list li:nth-child(odd) { border-right: .2mm solid var(--line-light); }
.period-list li:nth-child(even) { padding-left: 4mm; }
.period-list strong { display: block; color: var(--accent); font-size: 7.6pt; }
.period-list span { display: block; margin-top: 1mm; font-size: 8.4pt; line-height: 1.33; }
.plain-list { margin: 3mm 0 0; padding: 0; list-style: none; }
.plain-list li { position: relative; padding: 2.2mm 0 2.2mm 6mm; border-top: .2mm solid var(--line-light); }
.plain-list li:last-child { border-bottom: .2mm solid var(--line-light); }
.plain-list li::before { position: absolute; top: 3.3mm; left: 0; width: 2.2mm; height: .45mm; background: var(--accent); content: ''; }
.table-note { margin: 1.7mm 0 0; color: var(--ink-soft); font-size: 7.6pt; }
.note-line { margin-top: 3mm; padding: 2mm 0; border-top: .25mm solid var(--line); border-bottom: .25mm solid var(--line); color: var(--ink-soft); font-size: 8.2pt; }
.note-line strong { color: var(--ink); }
`
const highlightText = (highlight) => {
const parts = []
if (highlight.note) parts.push(highlight.note)
if (highlight.number) {
parts.push(
highlight.phaseLabel ? `${highlight.number} · ${highlight.phaseLabel}` : highlight.number,
)
}
return parts.join(' — ')
}
/** One sober composition for both shapes; the copy deltas come from the unit. */
export const renderBulletinHtml = (bulletin) => {
const sparse = Boolean(bulletin.sparse)
const subject = isSubjectUnit(bulletin.unit)
const copy = bulletin.unit.copy?.bulletin ?? {}
const subjectName = bulletin.meta.subjectName
const title = subject
? (() => {
const escaped = htmlEscape(copy.openingTitle(subjectName))
const name = htmlEscape(subjectName)
return escaped.includes(name) ? escaped.replace(name, `${name}`) : escaped
})()
: `O que Jorge Solla fez por ${htmlEscape(subjectName)}`
const lede = subject
? sparse
? copy.leadSparse
: copy.lead
: 'Da gestão da saúde ao mandato federal: ações no município e iniciativas para a região, apresentadas com o alcance de cada uma.'
const remaining = subject
? copy.remaining
: 'no dossiê da cidade — o boletim de uma página não os exibe.'
const sparseRule = subject
? copy.sparseRule
: 'Não repetir item, não ampliar efeito e não preencher espaço com fato sem lastro.'
return `
${htmlEscape(bulletin.meta.title)} — ${htmlEscape(subjectName)}
${title}
${htmlEscape(lede)}
Destaques
${
bulletin.highlights.length
? `${bulletin.highlights
.map(
(highlight) => `-
${htmlEscape(highlight.title)}
${htmlEscape(highlightText(highlight))}
`,
)
.join('')}
`
: `Sem fato com fonte suficiente para destacar — ver lacunas no dossiê.
`
}
${
bulletin.defenses.length
? `
O que Solla defende
${bulletin.defenses
.map(
(defense) => `-
${htmlEscape(defense.label)}
${htmlEscape(defense.text)}
`,
)
.join('')}
`
: ''
}
Trajetória em quatro períodos
${bulletin.timeline
.map(
(step) =>
`- ${htmlEscape(step.period)}${htmlEscape(step.text)}
`,
)
.join('')}
E mais
${
bulletin.moreItems.length
? `${bulletin.moreItems
.map((item) => `- ${htmlEscape(item.label)}
`)
.join('')}
`
: bulletin.factsRemaining === 0
? `Nenhum item adicional além dos destaques nesta página.
`
: ''
}
${
bulletin.factsRemaining > 0
? `${htmlEscape(moreItemsLabel(bulletin.factsRemaining, 'fato com fonte', 'fatos com fonte'))} ${htmlEscape(remaining)}
`
: ''
}
${
sparse
? `A página termina com espaço — de propósito. ${htmlEscape(sparseRule)}
`
: ''
}
`
}