(** Shapes a civil year of resolved days into the value a template renders against (spec section 4). This layer exists because a month grid needs leading blank cells, week bucketing and an "is this cell in the current month" test, and a logic-less template can compute none of it. Shaping the data here keeps the engine logic-less AND makes the grid template trivial. The view model IS the design. Both [weeks] and [days] are offered at every level: the booklet walks [days], the grid walks [weeks]. One model, two artefacts, no second code path that could drift. Colours are exposed as six booleans rather than a hex string: hex would bake a presentation policy into the engine, and LaTeX, groff and HTML each want a different colour expression. Exactly one of the six is true on every day. *) val of_days : lang:Colitur_naming.Lang.t -> vocab:('s, 'r) Colitur_kernel.Vocab.t -> rite:string -> year:int -> ('s, 'r) Colitur_kernel.Liturgical_day.t list -> Template.value (** [of_days ~lang ~vocab ~rite ~year days] where [days] is one civil year, 1 January to 31 December, in order. Pure and total. [lang] resolves every display string -- a day's [name], its localised [weekday]/[rank_name]/[colour_name]/[season_name], each month's [name], and the top-level [term] vocabulary and [weekday_headings]. [name] is a PLAIN STRING, not the old lang-keyed object: a dotted [{{name.la}}] reference that misses falls back WHOLESALE to the enclosing scope (a month's own [name.la]), which is how a printed booklet came to show "Ianuarius" in place of a feast with no Latin name. A plain string has no dotted path to fall back through, so that hazard is unrepresentable. [slug] is untouched by [lang] -- it stays the stable machine key, identical between any two calls that differ only in [lang]. Pass {!Colitur_naming.Lang.raw} for the pre-naming behaviour, under which [name] equals [slug] exactly (this is what CLI [--raw] uses). *)