+ {{ 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 }} +
+ +
+
+
+ {{/* EMBEDDED SLIDES SECTION - Replaces featured image for events with slides */}}
+ {{ if .Params.slides }}
+ {{/* Enable Alpine.js for fullscreen functionality */}}
+ {{ .Store.Set "has_alpine" true }}
+
+ {{/* Construct slides URL */}}
+ {{ $slides_page := site.GetPage (printf "/slides/%s" .Params.slides) }}
+
+ {{ if $slides_page }}
+
+ {{- 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" . }}
+ {{ if and $featured (not .Params.image.preview_only) }}
+ {{/* Fit image within max size. */}}
+ {{ $image := $featured }}
+
+ {{/* Determine image placement. */}}
+ {{ $placement := .Params.image.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
+
+
+
+
+ {{ else }}
+ {{/* Handle GIF - apply same placement constraints without responsive processing */}}
+ {{ $image := $featured }}
+ {{ if eq $placement 2}}
+ {{ $image = $featured.Fit "1200x2500" }}
+ {{else if eq $placement 3}}
+ {{ $image = $featured.Fit "2560x2560" }}
+ {{else}}
+ {{ $image = $featured.Fit "720x2500" }}
+ {{end}}
+
+
+ {{ with $.Params.image.caption }}{{ . | markdownify | emojify }}{{ end }}
+
+
+
+ {{ end }}
+ {{end}}
+ {{ end }}
+
+ {{/* EVENT METADATA */}}
+ {{ if .Params.abstract | or (eq .Type "events") }}
+
+
+ {{ with $.Params.image.caption }}{{ . | markdownify | emojify }}{{ end }}
+
+
+
+ {{ if .Params.abstract }}
+
+ {{ 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" }}
+
+
+ {{ end }}
+
+ {{ .Params.location | markdownify }}
+ {{ if .Params.address }} +{{partial "functions/get_address" (dict "root" . "address" .Params.address) }}
+ {{end}} +
+ {{ .Content }}
+
+
+ {{ partial "components/last-edited.html" . }}
+
+
+ {{ .Scratch.Set "invert_pager" true }}
+ {{ partial "page_footer" . }}
+
+
+