def render_header(style: StyleConfig, template_path: Path, title: str) -> str:
"""Read header.tex template and substitute config values.
Returns the fully rendered LaTeX preamble string.
Magic placeholders in header/footer strings:
{doc_title} → the document title
{logo_path} → absolute path to logo file (from style.logo) or empty
"""
template = template_path.read_text(encoding="utf-8")
# Logo path is now resolved to absolute during config loading
logo_path = style.logo if style.logo else ""
header_left = _substitute_placeholders(style.header_left, title, logo_path)
header_right = _substitute_placeholders(style.header_right, title, logo_path)
footer_left = _substitute_placeholders(style.footer_left, title, logo_path)
footer_center = _substitute_placeholders(style.footer_center, title, logo_path)
footer_right = _substitute_placeholders(style.footer_right, title, logo_path)
unicode_char_block = _build_unicode_char_block(style.unicode_chars)
font_block = _build_font_block(style.mainfont, style.sansfont, style.monofont)
line_spacing_block = _build_line_spacing_block(style.line_spacing)
header_footer_block = _build_header_footer_block(
header_left, header_right, footer_left, footer_center, footer_right
)
brand_colors_block = _build_brand_colors_block(style.brand_colors)
heading_styles_block = _build_heading_styles_block(style.heading_styles)
title_style_block = _build_title_style_block(style.title_style)
code_block = _build_code_block(style.code_fontsize)
cc = style.callout_colors
return template.format(
image_max_height_ratio=style.image_max_height_ratio,
note_r=cc.note[0],
note_g=cc.note[1],
note_b=cc.note[2],
tip_r=cc.tip[0],
tip_g=cc.tip[1],
tip_b=cc.tip[2],
warn_r=cc.warning[0],
warn_g=cc.warning[1],
warn_b=cc.warning[2],
danger_r=cc.danger[0],
danger_g=cc.danger[1],
danger_b=cc.danger[2],
unicode_char_block=unicode_char_block,
font_block=font_block,
line_spacing_block=line_spacing_block,
header_footer_block=header_footer_block,
brand_colors_block=brand_colors_block,
heading_styles_block=heading_styles_block,
title_style_block=title_style_block,
code_block=code_block,
)