PageSourceSearch

https://lifestories.org/public/theme/chunks/interview-CWgKRnHz.js

js lifestories.org collected 2026-10-02 17:19:18 UTC 49,618 bytes, 820 lines download raw bytes

1import{T as t}from"../scripts-CvZq4oMA.min.js";import"./player-B0WZnxGH.js";/*! lifestories v1.0.23 |  | (c) 2026 Huncwot.com | All Rights Reserved */const e=`{#
2  Template: t_interview-back-btn
3  Exit button displayed in the top-left corner of the interview lightbox.
4  @param {string} url_back - URL for the back/exit navigation
5#}
6<a href="{{ url_back }}" class="interview__back js-interview-close" data-history="false" data-gtm='{"event":"interview_exit_btn_click"}'>
7    <i class="icon-close"></i>
8    <span class="sr-only">Exit</span>
9</a>
10`,n=`{#
11  Template: t_interview-sidebar--details
12  Details panel with rich-text interview description.
13  @param {string} [info] - HTML string with interview description
14#}
15{%- if info -%}
16	<div class="interview-panel interview-details interview-text js-interview-details" id="details" role="tabpanel" aria-labelledby="tab-details">
17		<div class="interview-panel__content interview-panel__content--details">
18			<div class="interview-panel__head">
19				<h2 class="interview-panel__title">Details</h2>
20				<button class="interview-panel__close button button--ghost button--dark button--small button--helvetica js-nav-close" data-gtm='{"event":"interview_details_close_btn_click"}'>Close</button>
21			</div>
22			<div class="interview-details__text">
23				{% if info %}
24					{{info|raw}}
25				{% endif %}
26			</div>
27		</div>
28	</div>
29{%- endif %}
30`,i=`{% if lessons -%}
31<div class="interview-bottombar interview-bottombar--education" id="bottom-education" role="tabpanel" aria-labelledby="bottom-tab-education" data-hidden="true">
32    <div class="interview-bottombar__head">
33        <span class="interview-bottombar__title">Education</span>
34        <button class="button button--ghost button--dark js-nav-close" type="button" data-gtm='{"event":"interview_education_close_btn_click"}'>Close</button>
35    </div>
36    <div class="interview-bottombar__content">
37        <ul class="interview-tiles">
38            {% for item in lessons %}
39            {% set item_image = (item.image.desktop is defined or item.image.src is defined) ? item.image : (item.image ? {src: item.image} : null) %}
40            <li class="interview-tile interview-tile--horizontal js-item">
41                <a href="{{item.url}}" class="interview-tile__link" data-gtm='{"event":"interview_education_tile_click"}'>
42                    <figure class="interview-tile__image">
43                        {{- picture({ image: item_image, alt: '', lazy: true }) -}}
44                    </figure>
45                    <div class="interview-tile__main">
46                        <div class="interview-tile__title">{{item.type}}</div>
47                        <div class="interview-tile__descr">{{item.title}}</div>
48                    </div>
49                </a>
50            </li>
51            {% endfor %}
52        </ul>
53    </div>
54</div>
55{%- endif %}
56`,a=`{#
57  Template: t_interview-emotions
58
59  @param {string} api.emotions - Emotions endpoint; query string carries object_type/object_id for GET, POST goes to the bare path
60  @param {string} id           - Interview ID sent as a POST param
61  @param {object} [emotions]   - Emotion counts keyed by emotion name (e.g. emotions['like'])
62#}
63{% if api.emotions %}
64    {% set emotions_url = api.emotions|split('?')|first %}
65    <div class="interview-emotions">
66
67        <button type="button" class="interview-emotions__item js-emotions-item" aria-label="Like"
68            data-api='{ "url": "{{ emotions_url }}", "action": "POST", "turnstile": true, "callback": "onEmotion", "params": {"object_id": "{{ id }}", "object_type": "{{ type }}", "emotion": "like"}}'
69            data-gtm='{"event":"interview_emotions_btn_click", "id": "{{ id }}", "emotion": "like"}'>
70            <span class="interview-emotions__icon"><svg class="svg-30-emotions-like"  viewBox="0 0 30 30"><path d="M9.75 12.81H6.93a.47.47 0 0 0-.47.47v7.51c0 .26.21.47.47.47h2.82c.26 0 .47-.21.47-.47v-7.51a.47.47 0 0 0-.47-.47M23.32 13.7c0-.76-.52-1.54-1.53-1.54h-4.55c.65-1.16.84-2.8.39-3.99-.33-.88-.97-1.39-1.79-1.44h-.01c-.53-.03-1 .37-1.04.9-.12 1.19-.64 3.28-1.38 4.03-.63.63-1.16.89-2.05 1.32q-.195.09-.42.21v7.529999999999999c.11.04.21.07.32.11 1.47.51 2.74.94 4.68.94h3.67c1 0 1.53-.77 1.53-1.54 0-.23-.05-.45-.14-.66.33-.06.63-.22.84-.47.25-.28.38-.65.38-1.05 0-.23-.05-.45-.14-.66.81-.14 1.22-.83 1.22-1.51 0-.4-.14-.8-.42-1.09.27-.29.42-.69.42-1.
7009Z"/></svg></span>
71            <span class="interview-emotions__count js-count">{{ emotions['like'] ?? 0 }}</span>
72            <span class="interview-emotions__tooltip">Like</span>
73        </button>
74
75        <button type="button" class="interview-emotions__item js-emotions-item" aria-label="This Moved Me"
76            data-api='{ "url": "{{ emotions_url }}", "action": "POST", "turnstile": true, "callback": "onEmotion", "params": {"object_id": "{{ id }}", "object_type": "{{ type }}", "emotion": "moved-me"}}'
77            data-gtm='{"event":"interview_emotions_btn_click", "id": "{{ id }}", "emotion": "moved-me"}'>
78            <span class="interview-emotions__icon"><svg class="svg-30-emotions-moved-me"  xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 30 30"><path d="M14.924 10.205a4.38 4.38 0 0 0-3.847-2.262c-2.404 0-4.36 1.917-4.36 4.271 0 5.214 8.207 9.798 8.207 9.798s8.207-4.584 8.207-9.798c0-2.354-1.956-4.27-4.36-4.27a4.38 4.38 0 0 0-3.847 2.261" clip-rule="evenodd"/></svg></span>
79            <span class="interview-emotions__count js-count">{{ emotions['moved-me'] ?? 0 }}</span>
80            <span class="interview-emotions__tooltip">This Moved Me</span>
81        </button>
82
83        <button type="button" class="interview-emotions__item js-emotions-item" aria-label="I Needed This Today"
84            data-api='{ "url": "{{ emotions_url }}", "action": "POST", "turnstile": true, "callback": "onEmotion", "params": {"object_id": "{{ id }}", "object_type": "{{ type }}", "emotion": "hope"}}'
85            data-gtm='{"event":"interview_emotions_btn_click", "id": "{{ id }}", "emotion": "hope"}'>
86            <span class="interview-emotions__icon"><svg class="svg-30-emotions-hope"  xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 30 30"><path d="M20.027 6.686a3.23 3.23 0 0 0-2.259-.936c-.814 0-1.628.306-2.259.936l-.509.53-.529-.53a3.23 3.23 0 0 0-2.259-.936c-.834 0-1.689.326-2.3.977-1.2 1.262-1.119 3.277.102 4.498l4.6 4.6a.54.54 0 0 0 .753 0l4.66-4.661c1.241-1.201 1.241-3.236 0-4.478M12.843 18.104c-.326-.55-.896-1.221-1.466-1.873-.488-.57-1.017-1.14-1.384-1.689-.264-.387-.732-.387-1.058-.183-.407.244-.712.794-.264 1.648.223.448.773 1.038 1.343 1.67.04.04.06.08.102.121.142.143.101.387-.061.489-.143.081-.306.04-.428-.061l-.102-.102c-.427-.489-.834-.936-1.14-1.343a3 3 0 0 1-.305-.489c-.346-.651-.346-1.241-.162-1.689-.306-.651-.57-1.282-.692-1.689-.367-1.16-1.954-.875-1.893.366.061 1.282.509 5.454 1.73 6.879.55.651 1.547 1.526 2.605 2.259a.64.64 0 0 1 .264.509v.855a.46.46 0 0 0 .468.468h2.972a.46.46 0 0 0 .468-.468c-.02-.51-.04-1.364-.082-2.097-.101-1.546-.57-2.97-.915-3.581M22.774 12.934c-.122.407-.386 1.018-.692 1.69.183.447.163 1.037-.162 1.688-.082.163-.184.306-.306.489a18 18 0 0 1-1.14 1.343c-.02.04-.06.061-.101.102a.316.316 0 0 1-.428.06c-.162-.1-.203-.345-.06-.488.04-.04.06-.08.101-.122.57-.63 1.12-1.22 1.343-1.668.428-.835.143-1.405-.264-1.649-.346-.203-.814-.203-1.059.183-.366.55-.875 1.14-1.383 1.69-.57.65-1.14 1.322-1.466 1.872-.366.61-.814 2.035-.915 3.54-.041.733-.062 1.588-.082 2.097a.46.46 0 0 0 .468.468H19.6a.46.46 0 0 0 .469-.468v-.855c0-.203.101-.386.264-.508 1.058-.733 2.056-1.608 2.605-2.26 1.221-1.424 1.649-5.596 1.73-6.838.061-1.24-1.526-1.526-1.893-.366"/></svg></span>
87            <span class="interview-emotions__count js-count">{{ emotions['hope'] ?? 0 }}</span>
88            <span class="interview-emotions__tooltip">I Needed This Today</span>
89        </button>
90
91        <button type="button" class="interview-emotions__item js-emotions-item" aria-label="I Learned Something"
92            data-api='{ "url": "{{ emotions_url }}", "action": "POST", "turnstile": true, "callback": "onEmotion", "params": {"object_id": "{{ id }}", "object_type": "{{ type }}", "emotion": "learned"}}'
93            data-gtm='{"event":"interview_emotions_btn_click", "id": "{{ id }}", "emotion": "learned"}'>
94            <span class="interview-emotions__icon"><svg class="svg-30-emotions-learned"  xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 30 30"><path d="M16.51 22.96c-.12.898-1.034 1.596-2.144 1.597s-2.023-.699-2.143-1.596zm.528-1.843a.519.519 0 0 1 0 1.037h-5.49a.519.519 0 0 1 0-1.037zm-2.71-17.194q.506 0 1.019.074c1.944.28 3.676 1.419 4.752 3.123a6.76 6.76 0 0 1 .744 5.701c-.236.76-.649 1.523-1.228 2.267-.382.491-.79 1.051-1.211 1.666-.604.881-.923 1.115-.923 2.188v.602a.64.64 0 0 1-.637.638h-5.063a.64.64 0 0 1-.636-.638v-.615c0-1.08-.32-1.315-.924-2.19a35 35 0 0 0-1.29-1.752c-1.209-1.541-1.693-3.47-1.362-5.43a6.56 6.56 0 0 1 1.277-2.92c1.349-1.74 3.346-2.714 5.482-2.714m-2.154 8.132a.5.5 0 1 0 0 1h1.49v5.468a.5.5 0 0 0 1 0v-5.468h1.5a.5.5 0 0 0 0-1z" clip-rule="evenodd"/></svg></span>
95            <span class="interview-emotions__count js-count">{{ emotions['learned'] ?? 0 }}</span>
96            <span class="interview-emotions__tooltip">I Learned Something</span>
97        </button>
98
99        {# <button type="button" class="interview-emotions__item js-emotions-item" aria-label="Rare Find"
100            data-api='{"beforeCall": "login", "theme": "dark", "url": "{{ emotions_url }}", "action": "POST", "turnstile": true, "callback": "onEmotion", "params": {"object_id": "{{ id }}", "object_type": "{{ type }}", "emotion": "rare"}}'>
101            <span class="interview-emotions__icon"><svg class="svg-30-emotions-rare"  xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30"><path d="m19.13 13.21-3.97 10.38h-.34l-3.97-10.38h8.27Zm-15.44 0 9.48 10.38h.46L9.66 13.21zm15.24-1.12L15 7.01l-3.93 5.08h7.85Zm7.49 0L22.71 7l-1.95 5.09h5.65ZM16.37 23.6h.46l9.48-10.38h-5.97zm5.35-17.15h-5.73l3.83 4.96zm-7.71 0H8.28l1.9 4.96zm-6.73.54-3.7 5.1h5.65z"/></svg></span>
102            <span class="interview-emotions__count js-count">{{ emotions['rare'] ?? 0 }}</span>
103            <span class="interview-emotions__tooltip">Rare</span>
104        </button>#}
105
106        <button type="button" class="interview-emotions__item js-emotions-item" aria-label="Speaks to Me"
107            data-api='{ "url": "{{ emotions_url }}", "action": "POST", "turnstile": true, "callback": "onEmotion", "params": {"object_id": "{{ id }}", "object_type": "{{ type }}", "emotion": "speaks-to-me"}}'
108            data-gtm='{"event":"interview_emotions_btn_click", "id": "{{ id }}", "emotion": "speaks-to-me"}'>
109            <span class="interview-emotions__icon"><svg class="svg-30-emotions-speaks-to-me"  xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 30 30"><path d="M21.115 6.34c-.301.023-.651.22-.95.699-1.094 1.504-5.568 3.417-9.295 3.417H7.453a2.734 2.734 0 0 0-2.734 2.734v.683a2.734 2.734 0 0 0 2.734 2.734L6.7 21.621l-.099.62c-.127.424.48.924.851.85h2.337c.17 0 .314-.137.403-.284.088-.148.166-.347.166-.49l.856-5.71c2.624-.164 7.174 1.367 9.224 4.101.547.683 1.367.43 1.367 0V6.902c0-.327-.303-.59-.69-.561m1.759 4.283v5.812h.001a2.97 2.97 0 0 0 2.377-2.901 2.97 2.97 0 0 0-2.377-2.91z"/></svg></span>
110            <span class="interview-emotions__count js-count">{{ emotions['speaks-to-me'] ?? 0 }}</span>
111            <span class="interview-emotions__tooltip">Speaks to Me</span>
112        </button>
113
114    </div>
115{% endif %}
116`,s=`<div class="interview-foot js-footnotes">
117    {% if footnotes %}
118        <div class="interview-foot__footnotes">
119            <button class="interview-foot__close js-footnotes-close" aria-label="Close footnotes" data-gtm='{"event":"interview_footnotes_close_btn_click"}'><i class="icon-x"></i></button>
120            <ol>
121                {% for footnote in footnotes %}
122                    <li class="js-footnote" data-id="{{loop.index}}">{{footnote}}</li>
123                {% endfor %}
124            </ol>
125        </div>
126    {% endif %}
127</div>
128`,o=`{#
129  Template: t_interview-head
130  @param {string} id              - Interview ID
131  @param {object} head            - Head info: title (string|array), description, source: { label, url }
132  @param {string} [description]   - Interview description (shown in playlist mode)
133  @param {object} [playlist]      - Playlist data; presence triggers playlist modifier
134  @param {string} [url_full]      - Full interview URL (shown in playlist mode, desktop)
135  @param {string} [api.favorite]  - Favorites toggle API URL
136  @param {array}   [tags]    - Array of tag objects: name, url
137#}
138{% if head or tags %}
139	<div class="interview-panel interview-head js-interview-head">
140
141		<div class="interview-panel__content interview-panel__content--head">
142
143			{% set headTitle = head.title is iterable ? head.title : [head.title] %}
144			{% if head.url -%}
145				<a href="{{head.url}}" class="interview-head__title" data-close-search data-gtm='{"event":"interview_head_title_click"}'>
146					<span>{{headTitle|join('</span>
147        <span>')}}</span>
148				</a>
149			{%- else -%}
150				<div class="interview-head__title">
151					<span>{{headTitle|join('</span> <span>')}}</span>
152				</div>
153			{%- endif %}
154
155			{% if head.description -%}
156				<div class="interview-head__description">
157					<span>{{head.description}}</span>
158				</div>
159			{%- endif %}
160
161			{% if tags %}
162				<div class="interview-head__tags interview-tags js-interview-tags">
163					{% for tag in tags %}
164						{% if tag.name and tag.url %}
165							<a href="{{tag.url}}" class="interview-tag{% if loop.index > 5 %} interview-tag--hidden{% endif %}" data-close-search data-gtm='{"event":"interview_tag_click", "tag":"{{tag.name}}"}'>{{tag.name}}</a>
166						{% endif %}
167					{% endfor %}
168					{% if tags|length > 5 %}
169						<button type="button" class="interview-tag interview-tag--more js-interview-tags-more" data-gtm='{"event":"interview_head_tags_more_click"}'>...</button>
170					{% endif %}
171				</div>
172			{% endif %}
173
174			{% if head.source.label or head.dates or head.interviewers -%}
175				<div class="interview-head__details">
176					{% if head.interviewers %}
177						<div>Interviewer
178							{%- if head.interviewers|length > 1 -%}s
179							{%- endif -%}:
180							{% for i in head.interviewers %}
181							<a style="text-decoration:none" href="{{i.url}}" data-close-search data-gtm='{"event":"interview_head_interviewer_link_click"}'>{{i.label}}</a>{% if not loop.last %}, {% endif %}
182							{% endfor %}
183						</div>
184					{% endif %}
185					{% if head.dates %}
186						<div>Date
187							{%- if head.dates|length > 1 -%}s
188							{%- endif -%}:
189							{{head.dates|join(', ')}}</div>
190					{% endif %}
191					{% if head.source.label or head.source.copyright %}
192						<div>Source:
193							{% if head.source.url %}<a style="text-decoration:none" href="{{head.source.url}}" data-close-search data-gtm='{"event":"interview_head_source_link_click"}'>{{head.source.label}}</a>{% else %}{{head.source.label}}{% endif %}
194							{% if head.source.copyright %}
195							©&nbsp;{{head.source.copyright}}
196							{% endif %}
197						</div>
198					{% endif %}					
199				</div>
200			{%- endif %}
201
202			<div class="interview-head__time player__time desktop-only"><span class="js-interview-time"></span> / <span class="js-interview-duration"></span></div>
203
204		</div>
205
206	</div>
207{% endif %}
208`,r=`{#
209  Template: t_interview-index
210  Content list (chapter index) for the interview.
211  @param {array}  sessions    - Array of sessions; each has index[] entries
212  @param {object} [media]     - Media metadata: duration (seconds), used for session time offsets
213#}
214{% import 'interview-macros' as macros %}
215
216{% if not playlist and (sessions|first).index is defined %}
217<div class="interview-panel interview-index{% if sessions|length <= 1 %} interview-index--single{% endif %} js-interview-index" id="index" role="tabpanel" aria-labelledby="tab-index">
218
219    <div class="interview-panel__content interview-panel__content--index">
220
221        <div class="interview-panel__head">
222            <h2 class="interview-panel__title">Content List</h2>
223            <button class="interview-panel__close button button--ghost button--dark button--small button--helvetica js-nav-close" data-gtm='{"event":"interview_index_close_btn_click"}'>Close</button>
224        </div>
225
226
227        <div class="interview-index__main">
228        {% set sessionOffset = 0 %}
229        {% for session in sessions %}
230
231            {% if sessions|length > 1 %}
232            <div class="interview-index__session">
233                <div class="interview-index__session-label interview-index__session-label--top">
234                    Session <span>{{loop.index}}</span>
235                </div>
236                {% endif %}{# end if more sessions #}
237
238                {% for paragraph in session.index %}
239                {% set time = paragraph[0] + sessionOffset %}
240                <div class="interview-index__item{% if paragraph[2] %} interview-index__item--{{paragraph[2]}}{% endif %} js-index-part">
241
242                    <button  data-time="{{time}}" data-gtm='{"event":"transcript_time_btn_click"}'>
243                        <span class="interview-index__time">{{ macros.secondsToMinutes(time) }}</span>
244                        <span class="interview-index__title">{{paragraph[1]}}</span>
245                    </button>
246
247                </div>
248                {% endfor %}
249
250                {% set sessionOffset = sessionOffset + (session.video.duration ?? session.audio.duration ?? 0) %}
251
252                {% if sessions|length > 1 %}{# end if more sessions #}
253            </div>{# close div if more sessions #}
254            {% endif %}
255
256            {% endfor %}{# end for sessions #}
257        </div>{# close main #}
258    </div>{# close content #}
259</div>{# close panel #}
260{% endif %}
261`,l=`{#
262  Template: t_interview-sidebar--macros
263  Shared Twig macros for sidebar sub-templates.
264#}
265{% macro secondsToMinutes(seconds) %}
266
267{% set hours = seconds / 3600 %}
268{% set hours = hours|round(0, 'floor') %}
269{% set hours = hours|number_format %}
270
271{% set minutes = (seconds / 60)|round(0, 'floor') % 60 %}
272{% set minutes = minutes|number_format %}
273{% set minutes = ('00' ~ minutes)|slice(-2) %}
274
275{% set seconds = seconds|round(0, 'floor') % 60 %}
276{% set seconds = seconds|number_format %}
277{% set seconds = ('00' ~ seconds)|slice(-2) %}
278
279{{ hours }}:{{ minutes}}:{{ seconds }}
280
281{% endmacro %}
282
283
284{% macro duration(seconds) %}
285
286{% set mins = (seconds / 60)|round(0, 'floor') %}
287{% set secs = seconds|round(0, 'floor') % 60 %}
288{% set secs = ('00' ~ secs)|slice(-2) %}
289
290{% if seconds >= 3600 %}
291    {% set hrs = (seconds / 3600)|round(0, 'floor') %}
292    {% set mins = ('00' ~ mins % 60)|slice(-2) %}
293    {{- hrs }}:{{ mins }}:{{ secs -}}
294{% else %}
295    {{- mins }}:{{ secs -}}
296{% endif %}
297
298{% endmacro %}
299`,d=`{#
300  Template: t_interview-modal-comment
301  @param {string} id            - Interview ID (used in API params)
302  @param {object} [api]         - API URL overrides (inherited from t_interview)
303  @param {string}
303 [api.comments] - POST: submit comment (default: /api/comments)
304#}
305{% set url_comment = api.comments ?: '/api/comments' %}
306<dialog class="interview-modal" id="comment-imodal" data-component="InterviewModal">
307    <div class="interview-modal__panel">
308        <div class="interview-modal__header">
309            <span class="interview-modal__title">Add a comment</span>
310        </div>
311        <button class="interview-modal__close js-imodal-close" type="button" data-gtm='{"event":"modal_close_btn_click", "id": "{{ id }}"}'>
312            <i class="icon-close"></i>
313            <span class="sr-only">Close</span>
314        </button>
315        <form class="interview-modal__body" action="{{ url_comment }}" method="post" data-api='{"beforeCall": "login", "theme": "dark", "callback": "onComment", "params": {"object_type": "{{type}}", "object_id": "{{id}}"}}' novalidate>
316            <div class="interview-modal__field">
317                <textarea class="interview-modal__textarea" name="comment" placeholder="Share your thoughts…" required></textarea>
318            </div>
319            <label class="interview-modal__checkbox checkbox checkbox--dark">
320                <input type="checkbox" name="anonymous" value="1">
321                <span></span>
322                Share this comment anonymously
323            </label>
324            <div class="interview-modal__footer">
325                <button class="interview-modal__submit button button--secondary button--dark" type="submit" data-gtm='{"event":"interview_comment_submit_click", "id": "{{ id }}"}'>Send <svg class="sprite-30-arrow-right"><use xlink:href="#sprite-30-arrow-right"/></svg></button>
326            </div>
327        </form>
328    </div>
329</dialog>
330`,c=`{#
331  Template: t_interview-modal-highlight
332  @param {string} id               - Interview ID (used in API params)
333  @param {string} type             - Object type (used in API params)
334  @param {object} [api]            - API URL overrides (inherited from t_interview)
335  @param {string} [api.highlights] - POST: save highlight (default: /api/highlights)
336#}
337{% set url_highlights = api.highlights ?: '/api/highlights' %}
338<dialog class="interview-modal interview-modal--highlight" id="highlight-imodal" data-component="InterviewModal">
339    <div class="interview-modal__panel">
340        <div class="interview-modal__header">
341            <span class="interview-modal__title">Select what to add to Highlights</span>
342        </div>
343        <button class="interview-modal__close js-imodal-close" type="button" data-gtm='{"event":"modal_close_btn_click", "id": "{{ id }}"}'>
344            <i class="icon-close"></i>
345            <span class="sr-only">Close</span>
346        </button>
347        <form class="interview-modal__body" action="{{ url_highlights }}" method="post" data-api='{"beforeCall": "login", "theme": "dark", "callback": "onHighlight", "params": {"object_type": "{{type}}", "object_id": "{{id}}"}}' novalidate>
348            <div class="interview-modal__field">
349                <div class="interview-modal__quote js-highlight-quote"></div>
350            </div>
351            <input type="hidden" name="text" value="">
352            <input type="hidden" name="seconds" value="">
353            <div class="interview-modal__footer">
354                <button class="interview-modal__submit button button--secondary" type="submit" data-gtm='{"event":"interview_highlight_submit_click", "id": "{{ id }}"}'>Save <svg class="sprite-30-arrow-right"><use xlink:href="#sprite-30-arrow-right"/></svg></button>
355            </div>
356        </form>
357    </div>
358</dialog>
359`,v=`{#
360  Template: t_interview-modal-playlist
361  @param {string} id                    - Interview ID (used in API params)
362  @param {string} type                  - Object type (used in API params)
363  @param {object} [api]                 - API URL overrides (inherited from t_interview)
364  @param {string} [api.playlists]       - GET: load playlists list
365  @param {string} [api.playlist_create] - POST: create new playlist
366  @param {string} [api.playlist_add]    - POST: add interview to playlist; playlist_id appended as URL path segment
367#}
368{%- if api.playlists -%}
369<dialog class="interview-modal" id="playlist-imodal" data-component="InterviewModal" data-playlist-url="{{ api.playlist_add ?: api.playlists }}" data-object-id="{{ id }}" data-object-type="{{ type }}">
370    <div class="interview-modal__panel">
371        <div class="interview-modal__header">
372            <span class="interview-modal__title">Add to playlist</span>
373        </div>
374        <button class="interview-modal__close js-imodal-close" type="button" data-gtm='{"event":"modal_close_btn_click", "id": "{{ id }}"}'>
375            <i class="icon-close"></i>
376            <span class="sr-only">Close</span>
377        </button>
378        <div class="interview-modal__body">
379            <form action="{{ api.playlists }}" method="post" data-api='{"beforeCall": "login", "theme": "dark", "callback": "onPlaylistAdded"}' class="interview-modal__new-playlist">
380                <input class="interview-modal__input" type="text" name="label" placeholder="New playlist title">
381                <button class="interview-modal__add-btn" type="submit" data-gtm='{"event":"playlist_create_submit_click"}'>
382                    <i class="icon-plus"></i>
383                </button>
384            </form>
385            <form class="interview-modal__playlist-list js-imodal-playlist-list" data-api-load='{"auth": true, "action": "GET", "url": "{{ api.playlists }}", "template": "playlists", "callback": "onInterviewPlaylistsLoaded"}' id="playlists-list">
386            </form>
387            <div class="interview-modal__footer">
388                <button class="interview-modal__submit button button--secondary button--dark js-imodal-close" type="button" data-gtm='{"event":"playlist_modal_done_click", "id": "{{ id }}"}'>
389                    Done <svg class="sprite-30-arrow-right"><use xlink:href="#sprite-30-arrow-right"/></svg>
390                </button>
391            </div>
392        </div>
393    </div>
394</dialog>
395{%- endif -%}
396`,p=`{#
397  Template: t_interview-nav
398  Sidebar navigation tabs. Active state managed entirely by JS via is-active / aria-selected.
399  @param {object}  [info]     - Details panel data; button shown only when info.text is present
400  @param {array}   [sessions] - Sessions array; index/transcript buttons shown only when transcript exists
401  @param {object}  [playlist] - Playlist data; when present, index/transcript buttons are hidden
402  @param {array}   [related]  - Related items; button shown only when present
403  @param {array}   [lessons]  - Education items; button shown only when present
404  @param {string}  [url_full] - Full interview URL; renders the "Go to full interview" button
405#}
406{%- if info or (sessions|first).index is defined or (sessions|first).transcript is defined or related or lessons or url_full -%}
407	<div class="interview-nav js-interview-nav" role="tablist">
408
409		{%- if info is defined -%}
410			<a class="button button--ghost button--dark" id="tab-details" role="tab" href="#details" aria-controls="details" aria-selected="false" data-gtm='{"event":"transcript_tab_click", "tab":"details"}'>Details</a>
411		{%- endif -%}
412
413		{%- if not playlist and (sessions|first).index is defined -%}
414			<a class="button button--ghost button--dark" id="tab-index" role="tab" href="#index" aria-controls="index" aria-selected="false" data-gtm='{"event":"transcript_tab_click", "tab":"index"}'>Content List</a>
415		{%- endif -%}
416
417		{%- if (sessions|first).transcript is defined -%}
418			<a class="button button--ghost button--dark" id="tab-transcript" role="tab" href="#transcript" aria-controls="transcript" aria-selected="false" data-gtm='{"event":"transcript_tab_click", "tab":"transcript"}'>Transcript</a>
419		{%- endif -%}
420
421		{%- if related -%}
422			<a class="button button--ghost button--dark" id="bottom-tab-related" role="tab" href="#bottom-related" aria-controls="bottom-related" aria-selected="false" data-gtm='{"event":"transcript_tab_click", "tab":"related"}'>Related</a>
423		{%- endif -%}
424
425		{%- if lessons -%}
426			<a class="button button--ghost button--dark" id="bottom-tab-education" role="tab" href="#bottom-education" aria-controls="bottom-education" aria-selected="false" data-gtm='{"event":"transcript_tab_click", "tab":"education"}'>Education</a>
427		{%- endif -%}
428
429		{%- if url_full %}
430			<a class="button button--ghost button--dark" data-interview='{"id":{{id}}}' href="{{url_full}}" data-gtm='{"event":"interview_full_link_click"}'>Go to full interview <svg class="sprite-30-arrow-right"><use xlink:href="#sprite-30-arrow-right"/></svg></a>
431		{%- endif %}
432	</div>
433{%- endif %}
434`,m=`{% if playlist and playlist.items|length > 1 %}
435<div class="interview-playlist__head desktop-only">
436    {% if playlist.title %}
437    <div class="interview-playlist__title">{{ playlist.title }}</div>
438    <div class="interview-playlist__amount amount amount--dark amount--extra-small">{{ playlist.items|length }}</div>
439    {% endif %}
440    {% if playlist.description %}
441    <div class="interview-playlist__description">{{ playlist.description }}</div>
442    {% endif %}
443    {% if playlist.date %}
444    <div class="interview-playlist__date"><time>{{ playlist.date }}</time></div>
445    {% endif %}
446</div>
447<ul class="interview-playlist__list">
448    {% for item in playlist.items %}
449    <li class="interview-playlist__tile interview-tile  interview-tile--vert
449ical js-item">
450        {% include 'tile' with {mode: 'playlist', url: item.url, id: item.id, image: item.image, name: item.name, description: item.description, duration: item.duration, gtm_event: 'playlist_item_click'} %}
451    </li>
452    {% endfor %}
453</ul>
454{% endif %}
455`,_=`{% if related -%}
456<div class="interview-bottombar interview-bottombar--related" id="bottom-related" role="tabpanel" aria-labelledby="bottom-tab-related" data-hidden="true">
457    <div class="interview-bottombar__head">
458        <span class="interview-bottombar__title">Related</span>
459        <button class="interview-bottombar__close button button--ghost button--dark button--small js-nav-close" type="button" data-gtm='{"event":"interview_related_close_btn_click"}'>Close</button>
460    </div>
461    <div class="interview-bottombar__content">
462        <ul class="interview-tiles">
463            {% for item in related %}
464            {# backend ships some related entries without a slug (url = bare "/interviews") — fall back to the id route, which the api resolves too #}
465            {% set item_url = null %}
466            {% if (item.url|split('/')|length) > 2 %}
467                {% set item_url = item.url %}
468            {% elseif item.id and item.type == 'clip' %}
469                {% set item_url = '/stories/' ~ item.id %}
470            {% elseif item.id and item.type == 'interview' %}
471                {% set item_url = '/interviews/' ~ item.id %}
472            {% endif %}
473            {% if item_url %}
474            <li class="interview-tile interview-tile--horizontal interview-tile--{{item.type}} js-item">
475                {% include 'tile' with {
476                    url: item_url,
477                    image: item.image,
478                    name: item.narrator ?: item.title,
479                    description: item.profession ?: item.description,
480                    duration: item.duration,
481                    author: item.narrator,
482                    gtm_event: 'interview_related_tile_click'
483                } %}
484            </li>
485            {% endif %}
486            {% endfor %}
487        </ul>
488    </div>
489</div>
490{%- endif %}
491`,u=`{#
492  Template: t_interview-survey
493  End-of-video overlay: emotions survey, comment prompt and community quote steps + "Next to watch" strip.
494  @param {string} id                - Interview ID (used in API params)
495  @param {object} [api]             - API URLs (emotions, comments — steps render only when set)
496  @param {object} [emotions]        - Emotion counts keyed by emotion name (step 1 gate, as in t_interview-emotions)
497  @param {string} [community_quote] - Community quote text (step 3, skipped when empty)
498  @param {array}  [related]         - Related items; first 3 render as "Next to watch"
499#}
500{% if api.emotions or api.comments or community_quote %}
501<div class="interview-survey js-interview-survey">
502
503    {% if api.emotions %}
504    <div class="interview-survey__step js-survey-step">
505        <h2 class="interview-survey__title">How did this story resonate with you?</h2>
506        {% include 'interview-emotions' %}
507    </div>
508    {% endif %}
509
510    {% if api.comments %}
511    <div class="interview-survey__step js-survey-step">
512        <h2 class="interview-survey__title">Leave a comment</h2>
513        <button class="interview-survey__comment" type="button" data-imodal="comment-imodal" data-gtm='{"event":"interview_survey_comment_click", "id": "{{id}}"}' aria-label="Leave a comment"><svg class="svg-30-comment"  xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 30 30"><path d="M10.42 24.096v-4.58h1.386a6.806 6.806 0 1 1 0-13.611h6.39a6.805 6.805 0 0 1 0 13.61H15zm.868-9.694a1.242 1.242 0 1 0 0 2.485 1.242 1.242 0 0 0 0-2.485m3.712 0a1.243 1.243 0 1 0 .001 2.486A1.243 1.243 0 0 0 15 14.402m3.712 0a1.243 1.243 0 1 0 0 2.485 1.243 1.243 0 0 0 0-2.485"/></svg></button>
514    </div>
515    {% endif %}
516
517    {% if community_quote %}
518    <div class="interview-survey__step interview-survey__step--quote js-survey-step">
519        <span class="interview-survey__label">Community quote</span>
520        <blockquote class="interview-survey__quote">&ldquo;{{ community_quote }}&rdquo;</blockquote>
521    </div>
522    {% endif %}
523
524    {% if related %}
525    <div class="interview-survey__related js-survey-related">
526        <span class="interview-survey__related-title">Watch Next</span>
527        <ul class="interview-survey__tiles js-survey-tiles">
528            {% for item in related %}
529            {# backend ships some related entries without a slug (url = bare "/interviews") — fall back to the id route, which the api resolves too #}
530            {% set item_url = null %}
531            {% if (item.url|split('/')|length) > 2 %}
532                {% set item_url = item.url %}
533            {% elseif item.id and item.type == 'clip' %}
534                {% set item_url = '/stories/' ~ item.id %}
535            {% elseif item.id and item.type == 'interview' %}
536                {% set item_url = '/interviews/' ~ item.id %}
537            {% endif %}
538            {% if item_url %}
539            <li class="interview-tile interview-tile--horizontal interview-survey__tile js-item" style="--i: {{ loop.index0 }}">
540                {% include 'tile' with {
541                    url: item_url,
542                    image: item.image,
543                    name: item.narrator ?: item.title,
544                    description: item.profession ?: item.description,
545                    duration: item.duration,
546                    author: item.narrator,
547                    gtm_event: 'interview_survey_tile_click'
548                } %}
549            </li>
550            {% endif %}
551            {% endfor %}
552        </ul>
553    </div>
554    {% endif %}
555
556</div>
557{% endif %}
558`,w=`{#
559  Template: t_interview-tools
560  @param {object} api          - API URLs; each key renders its tool button
561  @param {string} [api.favorite]  - Favorites toggle URL
562  @param {string} [api.playlists] - Playlists list URL
563  @param {string} [api.comments]  - Comments URL
564  @param {string} [type]       - Object type (GTM)
565  @param {string} [id]         - Object id (GTM)
566
567  On mobile only the plus toggle is shown; it expands the list below (see \`.js-tools-toggle\`,
568  handled in Interview.ts). \`data-no-expand\` keeps the generic Expand widget off the button —
569  it binds every [aria-controls] element and would fight the class-based toggle.
570#}
571{% if api.favorite or api.playlists or api.comments %}
572	<div class="interview-tools js-interview-tools">
573		<button type="button" data-no-expand aria-expanded="false" aria-controls="interview-tools-list" aria-label="Show tools" class="interview-tool interview-tool--toggle button button--ghost button--dark js-tools-toggle" data-gtm='{"event":"interview_head_tools_toggle_click"}'>
574			<i class="icon-plus-small"></i>
575		</button>
576
577		<div class="interview-tools__list" id="interview-tools-list">
578			{% if api.favorite %}
579				<a href="{{api.favorite}}" data-api='{"beforeCall": "login", "theme": "dark", "callback": "onFavoriteToggle"}' data-gtm='{"event":"interview_head_favorite_click", "object_type": "{{type}}", "object_id": "{{id}}"}' class="interview-tool interview-tool--fav button button--ghost button--dark button--icon-left js-favorite-btn">
580					<span>Remove from favorites</span>
581					<span>Add to favorites</span>
582					<i class="icon-plus-small"></i>
583				</a>
584			{% endif %}
585
586			{% if api.playlists %}
587				<a href="#" data-imodal="playlist-imodal" data-gtm='{"event":"interview_head_playlist_btn_click", "id": "{{id}}"}' class="interview-tool interview-tool--playlist button button--ghost button--dark button--icon-left js-playlist-btn">
588					Add to playlist<i class="icon-plus-small"></i>
589				</a>
590			{% endif %}
591
592			{% if api.comments %}
593				<a href="#" data-imodal="comment-imodal" data-gtm='{"event":"interview_head_comment_btn_click", "id": "{{id}}"}' class="interview-tool interview-tool--comment button button--ghost button--dark button--icon-left">
594					Add a comment<i class="icon-plus-small"></i>
595				</a>
596			{% endif %}
597		</div>
598	</div>
599{% endif %}
600`,g=`{#
601  Template: t_interview-transcript
602  Transcript panel with per-session paragraphs and time-jump buttons.
603  @param {array}  sessions    - Array of sessions; each has transcript[] entries
604  @param {object} [media]     - Media metadata: duration (seconds), used for session time offsets
605#}
606{% import 'interview-macros' as macros %}
607
608{% if (sessions|first.transcript ?? null) %}
609<div class="interview-panel interview-transcript{% if sessions|length <= 1 %} interview-transcript--single{% endif %} js-interview-transcript" id="transcript" role="tabpanel" aria-labelledby="tab-transcript">
610
611    <div class="interview-panel__content interview-panel__content--transcript">
612
613        <div class="interview-panel__head">
614            <h2 class="interview-panel__title">Transcript</h2>
615            <button class="interview-panel__close button button--ghost button--dark button--small button--helvetica js-nav-close" data-gtm='{"event":"interview_transcript_close_btn_click"}'>Close</button>
616        </div>
617
618        <div class="interview-transcript__main js-transcript-content">
619
620            {% set sessionOffset = 0 %}
621            {% for session in sessions %}
622
623            {% set sessionId = loop.index %}
624
625            {% if sessions|length > 1 %}
626            <div class="interview-transcript__session">
627                <div class="interview-transcript__session-label">
628                    Session <span>{{loop.index}}</span>
629                </div>
630                {% endif %}{# end if more sessions #}
631
632
633                {# paragraphs #}
634                {% for paragraph in session.transcript %}
635
636                {% set time = paragraph[0] + sessionOffset %}
637
638                <div
639                    class="interview-transcript__part{% if paragraph[2] %} interview-transcript__part--{{paragraph[2]}}{% endif %} js-transcript-part">
640                    <button class="interview-transcript__time" data-time="{{time}}" data-gtm='{"event":"transcript_time_btn_click"}'>{{ macros.secondsToMinutes(time) }}</button>
641                    <button class="interview-transcript__highlight js-highlight-open" type="button" data-imodal="highlight-imodal" data-gtm='{"event":"transcript_highlight_btn_click"}'>+ Add to Highlights</button>
642                    <div class="interview-transcript__paragraph js-transcript-paragraph">
643                        {#{% if paragraph[2] and paragraph[2]!='question' and paragraph[2]!='answer' %}<span class="interview-transcript__speaker">{{paragraph[2]}}:</span> {% endif %}#}
644                        {{paragraph[1]}}</div>
645                </div>
646
647                {% endfor %}{# end for transcript paragraphs #}
648
649                {# increase session time offset #}
650                {% set sessionOffset = sessionOffset + (session.video.duration ?? session.audio.duration ?? 0) %}
651                {% if sessions|length > 1 %}
652            </div>{# close div if more sessions #}
653            {% endif %}
654
655            {% endfor %}{# end for sessions #}
656        </div>{# close main #}
657
658
659        {# SEARCH #}
660        <div class="interview-search">
661            <form class="interview-search__form js-transcript-search" novalidate autocomplete="off">
662                <div class="interview-search__input">
663                    <span class="interview-search__icon"><svg class="svg-30-search"  xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30"><circle cx="13.8" cy="13.73" r="4.5" fill="none" stroke="#000"/><path fill="none" stroke="#000" d="m17.16 17.38 3.54 3.53"/></svg></span>
664                    <input type="search" name="transcript" id="transcript-search" maxlength="52" placeholder=" ">
665                    <label for="transcript-search">Search</label>
666                </div>
667                <div class="interview-search__nav js-transcript-navigation">
668                    <span class="interview-search__numbers js-transcript-numbers"><strong>0</strong> / 0</span>
669                    <button class="interview-search__btn js-transcript-prev" type="button" aria-label="Previous result" data-gtm='{"event":"transcript_search_prev_click"}'><svg class="svg-nexus-chevron"  viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
670    <path d="M6 3 L11 8 L6 13" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
671</svg>
672</button>
673                    <button class="interview-search__btn js-transcript-next" type="button" aria-label="Next result" data-gtm='{"event":"transcript_search_next_click"}'><svg class="svg-nexus-chevron"  viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
674    <path d="M6 3 L11 8 L6 13" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
675</svg>
676</button>
677                    <button class="interview-search__close js-transcript-close" type="button" aria-label="Clear search" data-gtm='{"event":"transcript_search_clear_click"}'><i class="icon-close"></i></button>
678                </div>
679            </form>
680        </div>
681    </div>{# close content #}
682</div>{# close panel #}
683{% endif %}
684`,b=`{#
685  Template: t_interview-video
686  @param {array}   sessions  - Array of sessions; if all are 'text' type, video is hidden.
687                                Each session may define \`chapterCaptions\`: [time, text, duration?][]
688                                — chapter-title cards shown over the video at \`time\` for \`duration\` seconds (default 4).
689  @param {boolean} [result]  - API result flag; when false, message is shown instead of player
690  @param {string}  [message] - Error message from API (e.g. HTTP 451 region block)
691  @param {string}  [action]   - 'login' when the video needs a signed-in user (HTTP 401) — renders the login prompt instead of message
692  @param {string}  [shareUrl] - Current page URL; the login link's href, so sign-in returns to this video
693#}
694{% if message %}
695<div class="interview-video js-interview-video" id="interview-video">
696    <div class="interview-video__wrap">
697        {% if action == 'login' %}
698        <div class="interview-video__error interview-video__error--login">
699            <p class="interview-video__error-heading">This video is free to watch but you need to be logged in.</p>
700            <svg class="interview-video__error-arrow" viewBox="0 0 9 24" aria-hidden="true"><path d="M4.5 0v18" stroke="currentColor"/><path d="M1 17h7l-3.5 7z" fill="currentColor"/></svg>
701            <p class="interview-video__error-text">Please <a href="{{ shareUrl }}" data-login="dark" data-gtm='{"event":"stream_login_link_click"}'>login</a> or <a href="/register" data-gtm='{"event":"stream_register_link_click"}'>create</a> free account if you don't have one.</p>
702        </div>
703        {% else %}
704        <div class="interview-video__error">{{ message }}</div>
705        {% endif %}
706    </div>
707</div>
708{% else %}
709{% set noMedia = true %}
710{% for session in sessions %}
711    {% if session.media != 'text' %}{% set noMedia = false %}{% endif %}
712{% endfor %}
713{% if not noMedia %}
714<div class="interview-video js-interview-video" id="interview-video">
715    <div class="interview-video__wrap">
716        {% include 'player' %}
717        {% include 'interview-survey' %}
718
719        <div class="interview-video__chapter-captions js-video-chapter-captions">
720            {% set sessionOffset = 0 %}
721            {% for session in sessions %}
722                {% for caption in session.chapterCaptions %}
723                <div class="interview-video__chapter-caption js-video-chapter-caption" data-time="{{ caption[0] + sessionOffset }}" data-duration="{{ caption[2] ?? 4 }}">
724                    {{ caption[1] }}
725                </div>
726                {% endfor %}
727                {% set sessionOffset = sessionOffset + (session.video.duration ?? session.audio.duration ?? 0) %}
728            {% endfor %}
729        </div>
730    </div>
731</div>
732{% endif %}
733{% endif %}
734`,h=`{#
735  Template: t_interview-warning
736  @param {string}
736 [warning]  - Content warning label (e.g. "Sexual Content"); omit to skip rendering
737  @param {string} [url_back] - URL to navigate to when the user closes without consenting
738#}
739{% if warning %}
740<dialog class="interview-warning" data-component="InterviewWarning" data-options="{{ { warning: warning.id, urlBack: url_back|default('')|url_encode }|json_encode|e('html_attr') }}">
741    <div class="interview-warning__panel">
742        <button class="interview-warning__close js-iwarning-close" type="button" data-gtm='{"event":"interview_warning_dismiss_btn_click"}'>
743            <i class="icon-close"></i>
744            <span class="sr-only">Close</span>
745        </button>
746        <p class="interview-warning__label">Content Warning</p>
747        <h2 class="interview-warning__title">{{ warning.text }}</h2>
748        <label class="interview-warning__remember checkbox checkbox--dark">
749            <input class="js-iwarning-remember" type="checkbox" value="1">
750            <span></span>
751            Remember my consent
752        </label>
753    </div>
754    <div class="interview-warning__panel">
755        <div class="interview-warning__actions">
756            <button class="js-iwarning-close button button--dark button--ghost button--large" type="button" data-gtm='{"event":"interview_warning_close_btn_click"}'>Close</button>
757            <button class="js-iwarning-continue button button--secondary button--large button--dark" type="button" data-gtm='{"event":"interview_warning_continue_btn_click"}'>Continue viewing <svg class="sprite-30-arrow-right"><use xlink:href="#sprite-30-arrow-right"/></svg></button>
758        </div>
759    </div>
760</dialog>
761{% endif %}
762`,f=`{#
763  Template: t_interview
764  @param {string}  url_back              - URL for the exit/back button
765  @param {string}  id                    - Interview ID
766  @param {object}  head                  - Head: title (string|array), description, source: { label, url }
767  @param {string}  [description]         - Description (shown in playlist mode)
768  @param {object}  [playlist]            - Playlist data; triggers playlist layout
769  @param {string}  [url_full]            - Full interview URL (playlist mode only)
770  @param {string}  [shareUrl]            - Absolute URL for the share widget (set client-side from window.location.href)
771  @param {array}   sessions              - Sessions with transcript[], index[], media.duration
772  @param {object}  [media]               - Media metadata (duration etc.)
773  @param {array}   [tags]                - Tag objects: name, url
774  @param {object}  [info]                - Details: text (HTML string)
775  @param {array}
775   [related]             - Related tiles
776  @param {array}   [lessons]             - Education tiles
777  @param {boolean} [result]               - API result flag; when false, message is shown instead of video
778  @param {string}  [message]             - Error message from API (e.g. HTTP 451)
779  @param {object}  [api]                 - API URL overrides
780  @param {string}  [api.favorite]        - Favorites toggle URL
781  @param {string}  [api.comment]         - POST: submit comment (default: /api/comment)
782  @param {string}  [api.playlists]       - GET: load playlists list (default: /api/playlists)
783  @param {string}  [api.playlist_create] - POST: create new playlist (default: /api/playlist/create)
784  @param {string}  [api.playlist_add]    - POST: add interview to playlist (default: /api/playlist)
785#}
786
787{% include 'interview-back-btn' %}
788{% include 'interview-head' %}
789
790{% if related or lessons or api.emotions %}
791{% include 'share' with {
792    classes: ['interview__share', 'js-interview-share'],
793    modifiers: ['left'],
794    buttonDark: true,
795    shareUrl: shareUrl
796} %}
797{% endif %}
798
799{% include 'interview-tools' %}
800{% include 'interview-video' %}
801{% include 'interview-nav' %}
802
803<div class="interview__bottom js-bottombar">
804    {% include 'interview-emotions' %}
805    {% include 'interview-related' %}
806    {% include 'interview-education' %}
807</div>
808
809{% include 'interview-details' with { info: info } %}
810{% include 'interview-index' with { sessions: sessions, media: media } %}
811{% include 'interview-transcript' with { sessions: sessions, media: media } %}
812
813<div class="interview-modals">
814    {% include 'interview-modal-comment' %}
815    {% include 'interview-modal-playlist' %}
816    {% include 'interview-modal-highlight' %}
817</div>
818
819{% include 'interview-warning' %}
820`;t.register(Object.assign({"/application/views/templates/t_interview-back-btn.twig":e,"/application/views/templates/t_interview-details.twig":n,"/application/views/templates/t_interview-education.twig":i,"/application/views/templates/t_interview-emotions.twig":a,"/application/views/templates/t_interview-foot.twig":s,"/application/views/templates/t_interview-head.twig":o,"/application/views/templates/t_interview-index.twig":r,"/application/views/templates/t_interview-macros.twig":l,"/application/views/templates/t_interview-modal-comment.twig":d,"/application/views/templates/t_interview-modal-highlight.twig":c,"/application/views/templates/t_interview-modal-playlist.twig":v,"/application/views/templates/t_interview-nav.twig":p,"/application/views/templates/t_interview-playlist.twig":m,"/application/views/templates/t_interview-related.twig":_,"/application/views/templates/t_interview-survey.twig":u,"/application/views/templates/t_interview-tools.twig":w,"/application/views/templates/t_interview-transcript.twig":g,"/application/views/templates/t_interview-video.twig":b,"/application/views/templates/t_interview-warning.twig":h,"/application/views/templates/t_interview.twig":f}));

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.