PageSourceSearch

https://pietrostefani.com/projects

html pietrostefani.com collected 2026-10-01 13:55:24 UTC 28,909 bytes, 686 lines download raw bytes

1<!DOCTYPE html>
2<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"><head>
3
4<meta charset="utf-8">
5<meta name="generator" content="quarto-1.6.39">
6
7<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
8
9
10<title>Projects – Elisabetta Pietrostefani</title>
11<style>
12code{white-space: pre-wrap;}
13span.smallcaps{font-variant: small-caps;}
14div.columns{display: flex; gap: min(4vw, 1.5em);}
15div.column{flex: auto; overflow-x: auto;}
16div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
17ul.task-list{list-style: none;}
18ul.task-list li input[type="checkbox"] {
19  width: 0.8em;
20  margin: 0 0.8em 0.2em -1em; /* quarto-specific, see https://github.com/quarto-dev/quarto-cli/issues/4556 */ 
21  vertical-align: middle;
22}
23</style>
24
25
26<script src="site_libs/quarto-nav/quarto-nav.js"></script>
vendor: 1 bytes, line 26
26
27<script src="site_libs/clipboard/clipboard.min.js"></script>
vendor: 1 bytes, line 27
27
28<script src="site_libs/quarto-search/autocomplete.umd.js"></script>
vendor: 1 bytes, line 28
28
29<script src="site_libs/quarto-search/fuse.min.js"></script>
vendor: 1 bytes, line 29
29
30<script src="site_libs/quarto-search/quarto-search.js"></script>
30
31<meta name="quarto:offset" content="./">
32<link href="./assets/favicon.svg" rel="icon" type="image/svg+xml">
33<script src="site_libs/quarto-html/quarto.js"></script>
vendor: 1 bytes, line 33
33
34<script src="site_libs/quarto-html/popper.min.js"></script>
vendor: 1 bytes, line 34
34
35<script src="site_libs/quarto-html/tippy.umd.min.js"></script>
35
36<link href="site_libs/quarto-html/tippy.css" rel="stylesheet">
37<link href="site_libs/quarto-html/quarto-syntax-highlighting-e26003cea8cd680ca0c55a263523d882.css" rel="stylesheet" id="quarto-text-highlighting-styles">
38<script src="site_libs/bootstrap/bootstrap.min.js"></script>
38
39<link href="site_libs/bootstrap/bootstrap-icons.css" rel="stylesheet">
40<link href="site_libs/bootstrap/bootstrap-518349efc12e5c6411259d03c752f14e.min.css" rel="stylesheet" append-hash="true" id="quarto-bootstrap" data-mode="light">
41<script id="quarto-search-options" type="application/json">{
42  "location": "navbar",
43  "copy-button": false,
44  "collapse-after": 3,
45  "panel-placement": "end",
46  "type": "overlay",
47  "limit": 50,
48  "keyboard-shortcut": [
49    "f",
50    "/",
51    "s"
52  ],
53  "show-item-context": false,
54  "language": {
55    "search-no-results-text": "No results",
56    "search-matching-documents-text": "matching documents",
57    "search-copy-link-title": "Copy link to search",
58    "search-hide-matches-text": "Hide additional matches",
59    "search-more-match-text": "more match in this document",
60    "search-more-matches-text": "more matches in this document",
61    "search-clear-button-title": "Clear",
62    "search-text-placeholder": "",
63    "search-detached-cancel-button-title": "Cancel",
64    "search-submit-button-title": "Submit",
65    "search-label": "Search"
66  }
67}</script>
67
68<style>html{ scroll-behavior: smooth; }</style>
69<link rel="icon" href="./favicon.ico?v=4" sizes="any">
70<link rel="shortcut icon" href="./favicon.ico?v=4" type="image/x-icon">
71<link rel="icon" href="./favicon-v3.ico" sizes="any">
72<link rel="icon" href="./assets/favicon.svg?v=4" type="image/svg+xml">
73<link rel="apple-touch-icon" href="./apple-touch-icon.png?v=4">
74
75
76</head>
77
78<body class="nav-fixed fullcontent">
79
80<div id="quarto-search-results"></div>
81  <header id="quarto-header" class="headroom fixed-top">
82    <nav class="navbar navbar-expand-lg " data-bs-theme="dark">
83      <div class="navbar-container container-fluid">
84      <div class="navbar-brand-container mx-auto">
85    <a class='navbar-brand' href='/'>
86    <span class="navbar-title">Elisabetta Pietrostefani</span>
87    </a>
88  </div>
89            <div id="quarto-search" class="" title="Search"></div>
90          <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarCollapse" aria-controls="navbarCollapse" role="menu" aria-expanded="false" aria-label="Toggle navigation" onclick="if (window.quartoToggleHeadroom) { window.quartoToggleHeadroom(); }">
91  <span class="navbar-toggler-icon"></span>
92</button>
93          <div class="collapse navbar-collapse" id="navbarCollapse">
94            <ul class="navbar-nav navbar-nav-scroll me-auto">
95  <li class="nav-item">
96    <a aria-current='page' class='nav-link active' href='/projects'> 
97<span class="menu-text">Projects</span></a>
98  </li>  
99  <li class="nav-item">
100    <a class='nav-link' href='/papers'> 
101<span class="menu-text">Publications</span></a>
102  </li>  
103  <li class="nav-item">
104    <a class='nav-link' href='/courses'> 
105<span class="menu-text">Teaching</span></a>
106  </li>  
107  <li class="nav-item">
108    <a class='nav-link' href='/log'> 
109<span class="menu-text">Log</span></a>
110  </li>  
111</ul>
112          </div> <!-- /navcollapse -->
113            <div class="quarto-navbar-tools">
114</div>
115      </div> <!-- /container-fluid -->
116    </nav>
117</header>
118<!-- content -->
119<div id="quarto-content" class="quarto-container page-columns page-rows-contents page-layout-article page-navbar">
120<!-- sidebar -->
121<!-- margin-sidebar -->
122    
123<!-- main -->
124<main class="content" id="quarto-document-content">
125
126<header id="title-block-header" class="quarto-title-block default">
127<div class="quarto-title">
128<h1 class="title">Projects</h1>
129</div>
130
131
132
133<div class="quarto-title-meta">
134
135    
136  
137    
138  </div>
139  
140
141
142</header>
143
144
145<!--
146  STANDARD CARD FORMAT:
147    - Description in <span class="meta">...</span>
148    - Ends with two sentences: "Funded by X." and "With Y."
149    - Link is either:
150      * [Project website](url) — external project site
151      * [Learn more](page.qmd) — internal deep-dive page
152
153  Papers, reports, and additional links live on the internal .qmd
154  deep-dive pages, NOT on these cards.
155
156  Screenshots: drop images at `content/projects/<slug>.<ext>` and
157  reference with ![](path){fig-alt="..."} as first line of card.
158
159  Internal pages required (create these as .qmd files at repo root):
160    - beirut-blast.qmd (exists)
161    - displacement.qmd
162    - economics-of-architecture.qmd
163    - density.qmd
164    - evaluating-urban-policy.qmd
165    - informal-labour.qmd
166    - quality-of-life-lebanon.qmd
167    - fipal.qmd
168-->
169<p>Elisabetta’s work spans several research threads on urban shocks, inequality, and displacement. A selection is below; a full list of grants and collaborations is on the <a href="assets/cv.pdf">CV</a>.</p>
170<div class="media-grid">
171<div class="media-card">
172<p><img src="content/projects/imago.png" class="img-fluid" alt="Satellite imagery over a city"></p>
173<section id="imago" class="level3">
174<h3 data-anchor-id="imago">IMAGO</h3>
175<p><span class="meta">The SDR-UK Imagery Data Service for Sustainability, Prosperity and Wellbeing. Making satellite imagery useful, usable and used across social research and policy — through data infrastructure, applied case studies, and researcher training. Funded by UKRI ESRC (2024–2029). </span></p>
176<p><a href="https://imago.ac.uk">Project website</a></p>
177</section>
178</div>
179<div class="media-card">
180<p><img src="content/projects/displacement_disaster.png" class="img-fluid" alt="Map of displacement flows"></p>
181<section id="displacement-in-disaster-regions" class="level3">
182<h3 data-anchor-id="displacement-in-disaster-regions">Displacement in disaster regions</h3>
183<p><span class="meta">Developing methods to estimate internal displacement in real time by triangulating satellite imagery, mobile phone GPS data, and traditional surveys. Applications include the Russo-Ukrainian War and other disaster-affected contexts. Funded by Research England and ESRC. With IOM-DTM, UK government partners, Francisco Rowe, Matt Mason, Rodgers Iradukunda &amp; Andrea Nasuto.</span></p>
184<p><a href="https://pietrostefani.github.io/pop-displacement-disaster/">Project Website</a></p>
185</section>
186</div>
187<div class="media-card">
188<p><img src="content/projects/floodtraces.png" class="img-fluid" alt="Satellite imagery of flooded terrain"></p>
189<section id="floodtraces" class="level3">
190<h3 data-anchor-id="floodtraces">FloodTraces</h3>
191<p><span class="meta">Integrating traditional and digital trace data — satellite imagery, mobile phone signals, and social media — for real-time humanitarian decision-making in flood-affected regi
191ons. Funded by Research England (2025–2026). With IOM-DTM and UK government partners.</span></p>
192<p><a href="https://pietrostefani.github.io/floodtraces-hack/">Project website</a></p>
193</section>
194</div>
195<div class="media-card">
196<p><img src="content/projects/beirut_blast.png" class="img-fluid" alt="Aerial view of Beirut showing blast damage"></p>
197<section id="post-blast-beirut" class="level3">
198<h3 data-anchor-id="post-blast-beirut">Post-Blast Beirut</h3>
199<p><span class="meta">Investigating how the 4 August 2020 Beirut Blast reshaped vulnerability and inequality across the city. Combines spatial survey data collected in 2018 and 2021 with satellite-derived building damage assessments to track fine-grained changes in urban well-being and household resilience. Funded by GCRF and UCL Small Grants. With <a href="https://www.ucl.ac.uk/bartlett/global-prosperity">UCL’s Institute for Global Prosperity</a>, <a href="https://catalyticaction.org/assessing-vulnerabilities-in-beirut-post-explosion/">CatalyticAction</a> and Yara Sleiman.</span></p>
200<p><a href='/beirut-blast'>Learn more</a></p>
201</section>
202</div>
203<div class="media-card">
204<p><img src="content/projects/archi.jpg" class="img-fluid" alt="Architectural detail of a European city"></p>
205<section id="economics-of-architecture" class="level3">
206<h3 data-anchor-id="economics-of-architecture">Economics of Architecture</h3>
207<p><span class="meta">Do buildings and architectural quality shape economic outcomes in cities? An emerging research thread on high-quality Baukultur, real estate values, and long-term urban outcomes. Funded by the Swiss Federal Office of Culture. With Gabriel Ahlfeldt and Ailin Zhang.</span></p>
208<p><a href='/economics-of-architecture'>Learn more</a></p>
209</section>
210</div>
211<div class="media-card">
212<p><img src="content/projects/density.jpg" class="img-fluid" alt="Dense urban skyline"></p>
213<section id="density" class="level3">
214<h3 data-anchor-id="density">Density</h3>
215<p><span class="meta">A research strand on the economic effects of urban density — from a meta-analytic synthesis of 300+ studies globally to policy work on compact urban growth. Some funded by the OECD. With Gabriel Ahlfeldt, OECD, and the World Resources Institute.</span></p>
216<p><a href='/density'>Learn more</a></p>
217</section>
218</div>
219<div class="media-card">
220<p><img src="content/projects/Fig_1_OMI+and+re-allocated+assets.jpeg" class="img-fluid" alt="Historic building in an Italian city"></p>
221<section id="evaluating-urban-policy" class="level3">
222<h3 data-anchor-id="evaluating-urban-policy">Evaluating Urban Policy</h3>
223<p><span class="meta">Assessing the causal effects of urban policies on economic and social outcomes — from confiscated mafia real estate assets reallocated to communities in Italy, to conservation planning regulations and the politics of urban heritage across the Global North and South. Funded by LSE and the RGS-IBG. With Filippo Boeri, Marco Di Cataldo, and Nancy Holman.</span></p>
224<p><a href='/evaluating-urban-policy'>Learn more</a></p>
225</section>
226</div>
227<div class="media-card">
228<p><img src="content/projects/DCE_picture.jpg" class="img-fluid" alt="Informal market scene"></p>
229<section id="informal-labour-livelihoods" class="level3">
230<h3 data-anchor-id="informal-labour-livelihoods">Informal Labour &amp; Livelihoods</h3>
231<p><span class="meta">How do urban residents navigate formal and informal labour markets in contexts of crisis and displacement? Mixed-methods fieldwork in Lebanon on livelihood strategies and job security in the wake of economic collapse. Funded by the Leverhulme Trust. With George Melios, Diala Makki, Yara Sleiman, and UCL’s Institute for Global Prosperity.</span></p>
232<p><a href='/informal-labour'>Learn more</a></p>
233</section>
234</div>
235<div class="media-card">
236<p><img src="content/projects/cs.jpeg" class="img-fluid" alt="Citizen social science workshop in Lebanon"></p>
237<section id="quality-of-life-in-lebanon" class="level3">
238<h3 data-anchor-id="quality-of-life-in-lebanon">Quality of Life in Lebanon</h3>
239<p><span class="meta">Applied participatory research on quality of life and prosperity in Lebanon, using citizen social science to co-design measurement approaches with communities in Beirut, Tripoli (El Mina), and beyond. Funded by UKRI GCRF and the Leverhulme Trust. With UCL’s Institute for Global Prosperity, the RELIEF Centre, CatalyticAction, and the American University of Beirut.</sp
239an></p>
240<p><a href="https://www.relief-centre.org/">Project Website</a></p>
241</section>
242</div>
243<div class="media-card">
244<p><img src="content/projects/palestina.jpeg" class="img-fluid" alt="Streetscape in Ramallah, Palestine"></p>
245<section id="fipal-financial-inclusion-in-palestine" class="level3">
246<h3 data-anchor-id="fipal-financial-inclusion-in-palestine">FiPal — Financial Inclusion in Palestine</h3>
247<p><span class="meta">Transforming financial inclusion to finance inclusive prosperity in Ramallah, Palestine. Combines participatory citizen social science with quantitative analysis of financial access, extending the Prosperity Index framework to a new setting. Funded by ESRC (2024–2026). With UCL’s Institute for Global Prosperity and Palestinian civil society partners.</span></p>
248<p><a href="https://www.ucl.ac.uk/bartlett/research-projects/2022/oct/transforming-financial-inclusion-finance-inclusive-prosperity-ramallah-palestine">Project website</a></p>
249</section>
250</div>
251</div>
252
253
254
255</main> <!-- /main -->
256<script src="assets/menu.js"></script>
vendor: 1 bytes, line 256
256
257<script id="quarto-html-after-body" type="application/javascript">
258window.document.addEventListener("DOMContentLoaded", function (event) {
259  const toggleBodyColorMode = (bsSheetEl) => {
260    const mode = bsSheetEl.getAttribute("data-mode");
261    const bodyEl = window.document.querySelector("body");
262    if (mode === "dark") {
263      bodyEl.classList.add("quarto-dark");
264      bodyEl.classList.remove("quarto-light");
265    } else {
266      bodyEl.classList.add("quarto-light");
267      bodyEl.classList.remove("quarto-dark");
268    }
269  }
270  const toggleBodyColorPrimary = () => {
271    const bsSheetEl = window.document.querySelector("link#quarto-bootstrap");
272    if (bsSheetEl) {
273      toggleBodyColorMode(bsSheetEl);
274    }
275  }
276  toggleBodyColorPrimary();  
277  const isCodeAnnotation = (el) => {
278    for (const clz of el.classList) {
279      if (clz.startsWith('code-annotation-')) {                     
280        return true;
281      }
282    }
283    return false;
284  }
285  const onCopySuccess = function(e) {
286    // button target
287    const button = e.trigger;
288    // don't keep focus
289    button.blur();
290    // flash "checked"
291    button.classList.add('code-copy-button-checked');
292    var currentTitle = button.getAttribute("title");
293    button.setAttribute("title", "Copied!");
294    let tooltip;
295    if (window.bootstrap) {
296      button.setAttribute("data-bs-toggle", "tooltip");
297      button.setAttribute("data-bs-placement", "left");
298      button.setAttribute("data-bs-title", "Copied!");
299      tooltip = new bootstrap.Tooltip(button, 
300        { trigger: "manual", 
301          customClass: "code-copy-button-tooltip",
302          offset: [0, -8]});
303      tooltip.show();    
304    }
305    setTimeout(function() {
306      if (tooltip) {
307        tooltip.hide();
308        button.removeAttribute("data-bs-title");
309        button.removeAttribute("data-bs-toggle");
310        button.removeAttribute("data-bs-placement");
311      }
312      button.setAttribute("title", currentTitle);
313      button.classList.remove('code-copy-button-checked');
314    }, 1000);
315    // clear code selection
316    e.clearSelection();
317  }
318  const getTextToCopy = function(trigger) {
319      const codeEl = trigger.previousElementSibling.cloneNode(true);
320      for (const childEl of codeEl.children) {
321        if (isCodeAnnotation(childEl)) {
322          childEl.remove();
323        }
324      }
325      return codeEl.innerText;
326  }
327  const clipboard = new window.ClipboardJS('.code-copy-button:not([data-in-quarto-modal])', {
328    text: getTextToCopy
329  });
330  clipboard.on('success', onCopySuccess);
331  if (window.document.getElementById('quarto-embedded-source-code-modal')) {
332    const clipboardModal = new window.ClipboardJS('.code-copy-button[data-in-quarto-modal]', {
333      text: getTextToCopy,
334      container: window.document.getElementById('quarto-embedded-source-code-modal')
335    });
336    clipboardModal.on('success', onCopySuccess);
337  }
338    var localhostRegex = new RegExp(/^(?:http|https):\/\/localhost\:?[0-9]*\//);
339    var mailtoRegex = new RegExp(/^mailto:/);
340      var filterRegex = new RegExp("https:\/\/pietrostefani\.com");
341    var isInternal = (href) => {
342        return filterRegex.test(href) || localhostRegex.test(href) || mailtoRegex.test(href);
343    }
344    // Inspect non-navigation links and adorn them if external
345 	var links = window.document.querySelectorAll('a[href]:not(.nav-link):not(.navbar-brand):not(.toc-action):not(.sidebar-link):not(.sidebar-item-toggle):not(.pagination-link):not(.no-external):not([aria-hidden]):not(.dropdown-item):not(.quarto-navigation-tool):not(.about-link)');
346    for (var i=0; i<links.length; i++) {
347      const link = links[i];
348      if (!isInternal(link.href)) {
349        // undo the damage that might have been done by quarto-nav.js in the case of
350        // links that we want to consider external
351        if (link.dataset.originalHref !== undefined) {
352          link.href = link.dataset.originalHref;
353        }
354      }
355    }
356  function tippyHover(el, contentFn, onTriggerFn, onUntriggerFn) {
357    const config = {
358      allowHTML: true,
359      maxWidth: 500,
360      delay: 100,
361      arrow: false,
362      appendTo: function(el) {
363          return el.parentElement;
364      },
365      interactive: true,
366      interactiveBorder: 10,
367      theme: 'quarto',
368      placement: 'bottom-start',
369    };
370    if (contentFn) {
371      config.content = contentFn;
372    }
373    if (onTriggerFn) {
374      config.onTrigger = onTriggerFn;
375    }
376    if (onUntriggerFn) {
377      config.onUntrigger = onUntriggerFn;
378    }
379    window.tippy(el, config); 
380  }
381  const noterefs = window.document.querySelectorAll('a[role="doc-noteref"]');
382  for (var i=0; i<noterefs.length; i++) {
383    const ref = noterefs[i];
384    tippyHover(ref, function() {
385      // use id or data attribute instead here
386      let href = ref.getAttribute('data-footnote-href') || ref.getAttribute('href');
387      try { href = new URL(href).hash; } catch {}
388      const id = href.replace(/^#\/?/, "");
389      const note = window.document.getElementById(id);
390      if (note) {
391        return note.innerHTML;
392      } else {
393        return "";
394      }
395    });
396  }
397  const xrefs = window.document.querySelectorAll('a.quarto-xref');
398  const processXRef = (id, note) => {
399    // Strip column container classes
400    const stripColumnClz = (el) => {
401      el.classList.remove("page-full", "page-columns");
402      if (el.children) {
403        for (const child of el.children) {
404          stripColumnClz(child);
405        }
406      }
407    }
408    stripColumnClz(note)
409    if (id === null || id.startsWith('sec-')) {
410      // Special case sections, only their first couple elements
411      const container = document.createElement("div");
412      if (note.children && note.children.length > 2) {
413        container.appendChild(note.children[0].cloneNode(true));
414        for (let i = 1; i < note.children.length; i++) {
415          const child = note.children[i];
416          if (child.tagName === "P" && child.innerText === "") {
417            continue;
418          } else {
419            container.appendChild(child.cloneNode(true));
420            break;
421          }
422        }
423        if (window.Quarto?.typesetMath) {
424          window.Quarto.typesetMath(container);
425        }
426        return container.innerHTML
427      } else {
428        if (window.Quarto?.typesetMath) {
429          window.Quarto.typesetMath(note);
430        }
431        return note.innerHTML;
432      }
433    } else {
434      // Remove any anchor links if they are present
435      const anchorLink = note.querySelector('a.anchorjs-link');
436      if (anchorLink) {
437        anchorLink.remove();
438      }
439      if (window.Quarto?.typesetMath) {
440        window.Quarto.typesetMath(note);
441      }
442      if (note.classList.contains("callout")) {
443        return note.outerHTML;
444      } else {
445        return note.innerHTML;
446      }
447    }
448  }
449  for (var i=0; i<xrefs.length; i++) {
450    const xref = xrefs[i];
451    tippyHover(xref, undefined, function(instance) {
452      instance.disable();
453      let url = xref.getAttribute('href');
454      let hash = undefined; 
455      if (url.startsWith('#')) {
456        hash = url;
457      } else {
458        try { hash = new URL(url).hash; } catch {}
459      }
460      if (hash) {
461        const id = hash.replace(/^#\/?/, "");
462        const note = window.document.getElementById(id);
463        if (note !== null) {
464          try {
465            const html = processXRef(id, note.cloneNode(true));
466            instance.setContent(html);
467          } finally {
468            instance.enable();
469            instance.show();
470          }
471        } else {
472          // See if we can fetch this
473          fetch(url.split('#')[0])
474          .then(res => res.text())
475          .then(html => {
476            const parser = new DOMParser();
477            const htmlDoc = parser.parseFromString(html, "text/html");
478            const note = htmlDoc.getElementById(id);
479            if (note !== null) {
480              const html = processXRef(id, note);
481              instance.setContent(html);
482            } 
483          }).finally(() => {
484            instance.enable();
485            instance.show();
486          });
487        }
488      } else {
489        // See if we can fetch a full url (with no hash to target)
490        // This is a special case and we should probably do some content thinning / targeting
491        fetch(url)
492        .then(res => res.text())
493        .then(html => {
494          const parser = new DOMParser();
495          const htmlDoc = parser.parseFromString(html, "text/html");
496          const note = htmlDoc.querySelector('main.content');
497          if (note !== null) {
498            // This should only happen for chapter cross references
499            // (since there is no id in the URL)
500            // remove the first header
501            if (note.children.length > 0 && note.children[0].tagName === "HEADER") {
502              note.children[0].remove();
503            }
504            const html = processXRef(null, note);
505            instance.setContent(html);
506          } 
507        }).finally(() => {
508          instance.enable();
509          instance.show();
510        });
511      }
512    }, function(instance) {
513    });
514  }
515      let selectedAnnoteEl;
516      const selectorForAnnotation = ( cell, annotation) => {
517        let cellAttr = 'data-code-cell="' + cell + '"';
518        let lineAttr = 'data-code-annotation="' +  annotation + '"';
519        const selector = 'span[' + cellAttr + '][' + lineAttr + ']';
520        return selector;
521      }
522      const selectCodeLines = (annoteEl) => {
523        const doc = window.document;
524        const targetCell = annoteEl.getAttribute("data-target-cell");
525        const targetAnnotation = annoteEl.getAttribute("data-target-annotation");
526        const annoteSpan = window.document.querySelector(selectorForAnnotation(targetCell, targetAnnotation));
527        const lines = annoteSpan.getAttribute("data-code-lines").split(",");
528        const lineIds = lines.map((line) => {
529          return targetCell + "-" + line;
530        })
531        let top = null;
532        let height = null;
533        let parent = null;
534        if (lineIds.length > 0) {
535            //compute the position of the single el (top and bottom and make a div)
536            const el = window.document.getElementById(lineIds[0]);
537            top = el.offsetTop;
538            height = el.offsetHeight;
539            parent = el.parentElement.parentElement;
540          if (lineIds.length > 1) {
541            const lastEl = window.document.getElementById(lineIds[lineIds.length - 1]);
542            const bottom = lastEl.offsetTop + lastEl.offsetHeight;
543            height = bottom - top;
544          }
545          if (top !== null && height !== null && parent !== null) {
546            // cook up a div (if necessary) and position it 
547            let div = window.document.getElementById("code-annotation-line-highlight");
548            if (div === null) {
549              div = window.document.createElement("div");
550              div.setAttribute("id", "code-annotation-line-highlight");
551              div.style.position = 'absolute';
552              parent.appendChild(div);
553            }
554            div.style.top = top - 2 + "px";
555            div.style.height = height + 4 + "px";
556            div.style.left = 0;
557            let gutterDiv = window.document.getElementById("code-annotation-line-highlight-gutter");
558            if (gutterDiv === null) {
559              gutterDiv = window.document.createElement("div");
560              gutterDiv.setAttribute("id", "code-annotation-line-highlight-gutter");
561              gutterDiv.style.position = 'absolute';
562              const codeCell = window.document.getElementById(targetCell);
563              const gutter = codeCell.querySelector('.code-annotation-gutter');
564              gutter.appendChild(gutterDiv);
565            }
566            gutterDiv.style.top = top - 2 + "px";
567            gutterDiv.style.height = height + 4 + "px";
568          }
569          selectedAnnoteEl = annoteEl;
570        }
571      };
572      const unselectCodeLines = () => {
573        const elementsIds = ["code-annotation-line-highlight", "code-annotation-line-highlight-gutter"];
574        elementsIds.forEach((elId) => {
575          const div = window.document.getElementById(elId);
576          if (div) {
577            div.remove();
578          }
579        });
580        selectedAnnoteEl = undefined;
581      };
582        // Handle positioning of the toggle
583    window.addEventListener(
584      "resize",
585      throttle(() => {
586        elRect = undefined;
587        if (selectedAnnoteEl) {
588          selectCodeLines(selectedAnnoteEl);
589        }
590      }, 10)
591    );
592    function throttle(fn, ms) {
593    let throttle = false;
594    let timer;
595      return (...args) => {
596        if(!throttle) { // first call gets through
597            fn.apply(this, args);
598            throttle = true;
599        } else { // all the others get throttled
600            if(timer) clearTimeout(timer); // cancel #2
601            timer = setTimeout(() => {
602              fn.apply(this, args);
603              timer = throttle = false;
604            }, ms);
605        }
606      };
607    }
608      // Attach click handler to the DT
609      const annoteDls = window.document.querySelectorAll('dt[data-target-cell]');
610      for (const annoteDlNode of annoteDls) {
611        annoteDlNode.addEventListener('click', (event) => {
612          const clickedEl = event.target;
613          if (clickedEl !== selectedAnnoteEl) {
614            unselectCodeLines();
615            const activeEl = window.document.querySelector('dt[data-target-cell].code-annotation-active');
616            if (activeEl) {
617              activeEl.classList.remove('code-annotation-active');
618            }
619            selectCodeLines(clickedEl);
620            clickedEl.classList.add('code-annotation-active');
621          } else {
622            // Unselect the line
623            unselectCodeLines();
624            clickedEl.classList.remove('code-annotation-active');
625          }
626        });
627      }
628  const findCites = (el) => {
629    const parentEl = el.parentElement;
630    if (parentEl) {
631      const cites = parentEl.dataset.cites;
632      if (cites) {
633        return {
634          el,
635          cites: cites.split(' ')
636        };
637      } else {
638        return findCites(el.parentElement)
639      }
640    } else {
641      return undefined;
642    }
643  };
644  var bibliorefs = window.document.querySelectorAll('a[role="doc-biblioref"]');
645  for (var i=0; i<bibliorefs.length; i++) {
646    const ref = bibliorefs[i];
647    const citeInfo = findCites(ref);
648    if (citeInfo) {
649      tippyHover(citeInfo.el, function() {
650        var popup = window.document.createElement('div');
651        citeInfo.cites.forEach(function(cite) {
652          var citeDiv = window.document.createElement('div');
653          citeDiv.classList.add('hanging-indent');
654          citeDiv.classList.add('csl-entry');
655          var biblioDiv = window.document.getElementById('ref-' + cite);
656          if (biblioDiv) {
657            citeDiv.innerHTML = biblioDiv.innerHTML;
658          }
659          popup.appendChild(citeDiv);
660        });
661        return popup.innerHTML;
662      });
663    }
664  }
665});
666</script>
666
667</div> <!-- /content -->
668<footer class="footer">
669  <div class="nav-footer">
670    <div class="nav-footer-left">
671<p>© 2026 Elisabetta Pietrostefani</p>
672</div>   
673    <div class="nav-footer-center">
674      &nbsp;
675    </div>
676    <div class="nav-footer-right">
677<p><i class="bi bi-code-slash" aria-hidden="true"></i> Built with Quarto</p>
678</div>
679  </div>
680</footer>
681
682
683
684
685<script src="site_libs/quarto-html/zenscroll-min.js"></script>
685
686</body></html>

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.