{{ partial "components/breadcrumb.html" . }}
{{ end }}
{{/* Add spacing if cover has overlapping icon */}}
{{ $cover := partial "functions/get_cover_image.html" . }}
{{ $has_overlap_icon := false }}
{{ if $cover }}
{{ $icon_config := .Params.cover.icon | default (dict) }}
{{ if or $icon_config.name $icon_config.emoji }}
{{ $icon_position := $icon_config.position | default "overlap" }}
{{ if eq $icon_position "overlap" }}
{{ $has_overlap_icon = true }}
{{ end }}
{{ end }}
{{ end }}
{{/* Inline icon before title if specified */}} {{ if $cover }} {{ $icon_config := .Params.cover.icon | default (dict) }} {{ if or $icon_config.name $icon_config.emoji }} {{ $icon_position := $icon_config.position | default "overlap" }} {{ if eq $icon_position "inline" }} {{ if $icon_config.emoji }} {{ $icon_config.emoji }} {{ else if $icon_config.name }} {{ partial "components/icon.html" (dict "name" $icon_config.name "attributes" "class=\"w-full h-full\"") }} {{ end }} {{- .Title -}} {{ else }} {{- .Title -}} {{ end }} {{ else }} {{- .Title -}} {{ end }} {{ else }} {{- .Title -}} {{ end }}
{{- if .Date | and (not .Params.hide_date) -}}
{{- .Date | time.Format (site.Params.hugoblox.locale.date_format | default ":date_long") -}}
{{- if .Params.authors }}·{{ end -}}
{{- end -}}
{{/* Set Alpine.js flag if author notes exist */}}
{{ if isset .Params "author_notes" }}
{{ .Store.Set "has_alpine" true }}
{{ end }}
{{ range $i, $slug := .Params.authors }}
{{ $profile := partial "functions/get_author_profile" $slug }}
{{ $avatar := $profile.avatar }}
{{ if and $i (not $avatar) }},{{ end }}
{{ with $avatar }}
{{ $avatar_32 := .Process "Fill 32x32 Center webp" }}
{{ end }}
{{/* Add author note tooltip if available */}}
{{- if isset $.Params "author_notes" -}}
{{- with (index $.Params.author_notes $i) -}}
{{ $profile.title }}
{{.}}
{{- end -}}
{{- end -}}
{{ end }}
{{ if ne .Params.reading_time false }}
·
{{ .ReadingTime }} {{ i18n "minute_read" }}
{{ end }}
{{ partial "page_links_div.html" . }}
{{/* Slides iframe container - must contain button for fullscreen visibility */}}
{{ end }}
{{ else }}
{{/* Fallback to featured image if no slides */}}
{{ $featured := partial "functions/get_featured_image.html" . }}
{{/* Safely extract image parameters - handle case where image is not a map */}}
{{ $image_params := dict }}
{{ if and .Params.image (reflect.IsMap .Params.image) }}
{{ $image_params = .Params.image }}
{{ end }}
{{ if and $featured (not $image_params.preview_only) }}
{{/* Fit image within max size. */}}
{{ $image := $featured }}
{{/* Determine image placement. */}}
{{ $placement := $image_params.placement | default 1 }}{{/* Default to full column width. */}}
{{/* Configure responsive processing based on placement */}}
{{ $image_container := "" }}
{{ $responsive_sizes := slice }}
{{ $sizes_attr := "" }}
{{ if eq $placement 2}}
{{ $image_container = "container" }}
{{ $responsive_sizes = slice 480 768 1024 1200 1600 }}
{{ $sizes_attr = "(max-width: 480px) 100vw, (max-width: 768px) 90vw, (max-width: 1200px) 80vw, 1200px" }}
{{else if eq $placement 3}}
{{ $image_container = "container-fluid" }}
{{ $responsive_sizes = slice 768 1024 1366 1920 2560 }}
{{ $sizes_attr = "(max-width: 768px) 100vw, (max-width: 1366px) 90vw, (max-width: 1920px) 80vw, 2560px" }}
{{else}}
{{ $image_container = "article-container" }}
{{ $responsive_sizes = slice 320 480 640 720 960 }}
{{ $sizes_attr = "(max-width: 480px) 100vw, (max-width: 640px) 90vw, (max-width: 720px) 80vw, 720px" }}
{{end}}
{{/* Process featured image using utility with placement-specific constraints */}}
{{ if ne $featured.MediaType.SubType "gif" }}
{{/* Pre-fit image to placement constraints, then apply responsive processing */}}
{{ $fitted_image := $featured }}
{{ if eq $placement 2}}
{{ $fitted_image = $featured.Fit "1200x2500" }}
{{else if eq $placement 3}}
{{ $fitted_image = $featured.Fit "2560x2560" }}
{{else}}
{{ $fitted_image = $featured.Fit "720x2500" }}
{{end}}
{{ $responsive := partial "functions/process_responsive_image.html" (dict
"image" $fitted_image
"mode" "responsive"
"sizes" $responsive_sizes
) }}
{{/* Featured image - use fitted image dimensions for container, responsive for srcset */}}
{{/* Fullscreen toggle button - must be inside fullscreen container */}}
{{/* Slides metadata */}}
{{/* Direct link to slides */}}
View slides in new tab
{{/* Presentation mode hint */}}
S
for speaker notes
{{ if .Params.abstract }}
{{ end }}
{{ end }}
{{ i18n "abstract" }}
{{ .Params.abstract | markdownify }}
{{ end }}
{{ if eq .Type "events" }}
{{ i18n "date" }}
{{ partial "functions/get_event_dates" . }}
{{ end }}
{{ if .Params.event }}
{{ i18n "event" }}
{{ with .Params.event_url }}{{ end }}
{{ .Params.event | markdownify }}
{{ if .Params.event_url }}{{ end }}
{{ end }}
{{ if .Params.location }}
{{ i18n "location" }}
{{ .Params.location | markdownify }}
{{ if .Params.address }}{{partial "functions/get_address" (dict "root" . "address" .Params.address) }}
{{end}}
{{ with .Section }}
{{ end }}
{{ with .Params.categories }}
{{ end }}
{{ .Content }}
{{ partial "components/last-edited.html" . }}
{{ .Scratch.Set "invert_pager" true }}
{{ partial "page_footer" . }}