{#
ProjectDetail content block - paragraphs (repeatable) + image. ProjectDetail-only block
type, no Actualité equivalent - see "Repeatable Block Templates (Exception)" in
spec-driven-development/rules/section-component-architecture.md.
Parameters:
- block (object): block data with `id`, `type`, `fields.{paragraphs[], image, imagePath}`
(`paragraphs[]` = `{title, subtitle, text}[]`; `image` = media UUID for the editor's
data-media-id, `imagePath` = resolved file path for , set by
ProjectDetailPageEnricher's generic `fields.image` -> `fields.imagePath` resolution)
Two-column layout (repeatable list left, sticky image right) reuses the Expertise page's
`components/_expertise-list.html.twig` shell via {% embed %}, overriding its `items` and
`image` blocks - same grid/sticky/aspect-ratio visual as Expertise's list (see
assets/styles/components/_expertise-list.scss, imported by both assets/expertise.ts and
assets/project-detail.ts). Only the paragraph-specific typography/remove-button/add-button
styling stays block-local (`.project-detail-block-paragraphs-image__paragraph*` /
`__add`, in assets/styles/pages/_project-detail.scss).
Left column's paragraph list is RepeatableObjectListEditor-managed in edit mode
(assets/admin/editor/RepeatableObjectListEditor.ts), instantiated per-block-instance by
BlockListEditor.bindBlockControls() (mirrors bindGalleryControls()'s block-scoping).
`data-field="paragraphs[N][title|subtitle|text]"`, index-contiguous.
The paragraph item's hidden lives NESTED inside this block's own hidden
block-level (templates/projects/detail.html.twig's
`project-detail-block-template-paragraphs-image` fragment) - verified that
BlockListEditor.addBlock()'s `cloneNode(true)` on the outer template's `.content`
correctly preserves this inner 's `.content` (jsdom/browsers clone template
contents recursively per the HTML spec's template cloning steps), see
tests/frontend/admin/editor/BlockListEditor.test.ts.
#}
{% for paragraph in block.fields.paragraphs|default([]) %}
{{ paragraph.title|default('') }}
{% if (paragraph.subtitle is defined and paragraph.subtitle) or editMode|default(false) %}
{{ paragraph.subtitle|default('') }}
{% endif %}
{{ paragraph.text|default('')|raw }}
{% if editMode|default(false) %}
{% endif %}
{% endfor %}
{% if editMode|default(false) %}
{% endif %}
{% endblock %}
{% block image %}
{% if editMode|default(false) and not (block.fields.image|default(false) or block.fields.imageDark|default(false)) %}
+Ajouter une image
{% endif %}
{% include 'components/_themed_img.html.twig' with {light: block.fields.imagePath|default(''), dark: block.fields.imageDarkPath|default(''), alt: '', class: 'expertise-list__img'} only %}