-
Notifications
You must be signed in to change notification settings - Fork 27
Expand file tree
/
Copy pathindex.html
More file actions
1114 lines (1069 loc) · 64.8 KB
/
Copy pathindex.html
File metadata and controls
1114 lines (1069 loc) · 64.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!doctype html>
<html lang="en-GB">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- ── Every relative URL on this page resolves against the site root ──
Not decoration, and not only for the generated pages: routes are
carried by the *path* now (shared/routes.js), so `writeRoute` moves
this document's URL from `/` to `/people/memories/` to
`/publications/gallery/` as the reader goes. A site-relative
`research/img/logo-neurokit.png` in a card built *after* that move
resolves to `/publications/gallery/research/img/…` and 404s.
That is exactly the bug this fixed: the Creations logos, the
publication figures and the Information backdrops all vanished,
because those are the panels built on demand rather than at
startup — and `fetch(post.file)` was about to fail the same way.
It shows as empty space, not as an error.
The cost is that a bare `href="#sec-…"` now resolves against the
base, so it stops being a same-document fragment once the path has
moved and the browser would reload rather than scroll. The nine
section anchors are scrolled by hand instead — see the delegated
click handler at the foot of script.js.
`./` and NOT `/`, and the difference matters twice over. A
relative base is resolved **once, at parse time**, against the
document's own URL, and is then frozen — measured: after
`replaceState("/people/memories/")` the baseURI is still the site
root. So it fixes the moving-path bug exactly as `/` does, while
making no assumption about where the site is mounted. `/` broke
every setup that is not the deployed root: the site served under a
sub-path, or the folder opened over file://. Every stylesheet and
every module resolved to the wrong place and the page came up
bare. -->
<base href="./" />
<!-- ── How this page describes itself ──────────────────────────────
The site is one document, so this block is the *whole* of what a
crawler or a social card gets before any JavaScript runs. Two
consequences worth knowing:
- shared/page-meta.js rewrites the title and the og:* tags as the
reader moves between hash routes, which is for the browser tab,
the history menu and bookmarks. It is NOT read by search or
social crawlers: those fetch the raw HTML and never run the
modules, so what is written here is what they index and what
every shared link renders as, whichever route it points at.
- the canonical is absolute and is the deployed root, not this
folder, so it stays correct when the site is served from a
sub-path or opened locally. It is
https://realitybendinglab.com/, which is the CNAME in the repo
root — a domain bought from Namecheap and set as the custom
domain in the repository's Pages settings, which is what wrote
that file. It is NOT realitybending.github.io, which was this
site's original address (a GitHub Pages user site, hence the
repository's name) and which Pages still answers on and 301s
away from. Moving it again means changing
**this tag is the single source of the site's URL.**
`generate_pages.py` reads the origin from it (and so do
sitemap.xml, llms.txt and robots.txt), `shared/page-meta.js`
reads it off the live DOM, and CNAME is checked against it.
There are no other copies — do not reintroduce one. -->
<title>Reality Bending Lab — Neuropsychology of Reality | University of Sussex</title>
<meta
name="description"
content="The Reality Bending Lab, led by Dominique Makowski at the University of Sussex, studies how people construct and distort reality — perception, illusions, deception, fake news and AI beliefs."
/>
<link rel="canonical" href="https://realitybendinglab.com/" />
<!-- Open Graph: what X, LinkedIn, Bluesky, Slack, Mastodon and iMessage
show when a link is shared. Without these a shared link is a bare
grey rectangle. og:image must be an absolute URL — relative paths
are not resolved by any of these crawlers. -->
<meta property="og:type" content="website" />
<meta property="og:site_name" content="Reality Bending Lab" />
<meta property="og:title" content="Reality Bending Lab — Neuropsychology of Reality" />
<meta
property="og:description"
content="Led by Dominique Makowski at the University of Sussex: research on reality perception, illusions, deception, fake news and AI beliefs."
/>
<meta property="og:url" content="https://realitybendinglab.com/" />
<meta property="og:image" content="https://realitybendinglab.com/img/og-card.jpg" />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta property="og:image:alt" content="Reality Bending Lab" />
<meta property="og:locale" content="en_GB" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:site" content="@Dom_Makowski" />
<meta name="twitter:creator" content="@Dom_Makowski" />
<!-- Cream behind the black mark in both icons: a transparent logo is
black-on-black in a dark tab bar. The Sussex wordmark in the corner
of lab_logo_black.png is cropped away for these — at 48px it is
noise rather than a second brand. -->
<link rel="icon" type="image/png" href="img/favicon.png" />
<link rel="apple-touch-icon" href="img/apple-touch-icon.png" />
<meta name="theme-color" content="#f5f4ef" />
<!-- One stylesheet cut into numbered pieces. THE ORDER IS THE CASCADE:
these are loaded and applied exactly as listed, so a rule in a
later file beats the same-specificity rule in an earlier one.
Several overrides here depend on that (the narrow/wide blocks beat
the section files; the zoom's own 1800px rule beats 20-wide.css).
Add a file where it belongs in the order, never at the end for
convenience. -->
<link rel="stylesheet" href="css/01-base.css" />
<link rel="stylesheet" href="css/02-door.css" />
<link rel="stylesheet" href="css/03-shell.css" />
<link rel="stylesheet" href="css/04-hero.css" />
<link rel="stylesheet" href="css/05-research.css" />
<link rel="stylesheet" href="css/06-people.css" />
<link rel="stylesheet" href="css/07-shared.css" />
<link rel="stylesheet" href="css/08-memories.css" />
<link rel="stylesheet" href="css/09-collaborations.css" />
<link rel="stylesheet" href="css/10-people-mlp.css" />
<link rel="stylesheet" href="css/11-alumni.css" />
<link rel="stylesheet" href="css/12-profile-panel.css" />
<link rel="stylesheet" href="css/13-news.css" />
<link rel="stylesheet" href="css/14-publications.css" />
<link rel="stylesheet" href="css/15-contact.css" />
<link rel="stylesheet" href="css/16-join.css" />
<link rel="stylesheet" href="css/17-services.css" />
<link rel="stylesheet" href="css/18-fabs-footer.css" />
<link rel="stylesheet" href="css/19-narrow.css" />
<link rel="stylesheet" href="css/20-wide.css" />
<link rel="stylesheet" href="css/21-reality-zoom.css" />
<link rel="stylesheet" href="css/22-debug.css" />
<!-- ── The no-JS stylesheet ──
In <head> because it has to apply before the first paint, and
inside <noscript> because it must never apply to anyone else.
Deliberately not in the numbered set: those sheets are written for
the working site, and a `#door-screen { display: none }` sitting in
one of them is a rule waiting to be applied by accident.
`display: none` on the door and `pointer-events: auto` on
#main-page are together what opens the landing screen — the door
merely hidden still leaves the page unclickable, which is the same
pair the inline bootstrap sets for a deep link. The four hidden
sections and the note that replaces them are explained at the
<noscript> block in the body. -->
<noscript>
<style>
#door-screen {
display: none;
}
#main-page {
pointer-events: auto;
}
#main-page::before {
display: none;
}
#sec-people-full,
#sec-research-full,
#sec-news-full,
#sec-publications-full,
.fab-group {
display: none;
}
.noscript-note {
max-width: 44rem;
margin: 3rem auto;
padding: 1.6rem 1.8rem;
border: 1px solid rgba(17, 17, 17, 0.14);
border-radius: 18px;
background: rgba(255, 255, 255, 0.72);
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}
.noscript-note__lead {
margin: 0;
font-size: 1rem;
line-height: 1.75;
color: #3c3936;
}
.noscript-note__links {
display: flex;
flex-wrap: wrap;
gap: 0.5rem 1.4rem;
margin: 1.1rem 0 0;
padding: 0;
list-style: none;
}
.noscript-note__links a {
font-weight: 600;
color: #7e2f2f;
}
</style>
</noscript>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Raleway:wght@400;700&display=swap" rel="stylesheet" />
<!-- Preload heavy assets during the landing screen -->
<!-- ── `media` here is not optional ──
This is a 5.7 MB fetch, and a preload hint is honoured whether or
not anything ever asks for the file — so gating the *module* below
on `.hero__brain` being displayed saved nothing at all while this
line went on pulling the model down on every phone.
A preload cannot ask the stylesheet the way the module can, so this
is the one place the 900px breakpoint is written twice. It has to
stay in step with `.hero__brain { display: none }` in
css/19-narrow.css: 901px here is that sheet's `max-width: 900px`
inverted. Change one and change the other. -->
<link rel="preload" href="img/brain.glb" as="fetch" crossorigin media="(min-width: 901px)" />
<link rel="preload" href="img/lab_logo_black.png" as="image" />
<!-- model-viewer web component -->
<script type="importmap">
{
"imports": {
"three": "https://cdn.jsdelivr.net/npm/three@0.167.1/build/three.module.js",
"three/addons/": "https://cdn.jsdelivr.net/npm/three@0.167.1/examples/jsm/"
}
}
</script>
<!-- ── Structured data ─────────────────────────────────────────────
What the lab *is*, in the vocabulary Google, Bing and the LLM
crawlers parse directly rather than infer from prose. This is the
one part of the page that does not depend on JavaScript having run
and does not depend on anything being fetched, so it is what a
crawler that renders nothing still comes away with.
It is hand-kept, and it duplicates three things that live in a
manifest: the lab's name, the PI's name and the PI's social links
(people/people_manifest.json, member `dominique-makowski`). Kept by
hand because there is exactly one PI and one organisation and a
script to derive two objects would be more machinery than the
thing it generates. If a fourth of these appears, generate it.
@id lets the three refer to each other rather than repeat: the
WebSite is published by the Organization, the Person works for it.
Publications are deliberately NOT here. They would be 67
ScholarlyArticle nodes on a page that is not about any of them,
and Google matches structured data against what the page visibly
shows. Each one carries its own node on its own page instead —
`build_publications` in generate_pages.py, and docs/routing.md. -->
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@graph": [
{
"@type": "ResearchOrganization",
"@id": "https://realitybendinglab.com/#organization",
"name": "Reality Bending Lab",
"alternateName": "ReBeL",
"url": "https://realitybendinglab.com/",
"logo": "https://realitybendinglab.com/img/lab_logo_black.png",
"image": "https://realitybendinglab.com/img/og-card.jpg",
"email": "D.Makowski@sussex.ac.uk",
"description": "A psychology and neuroscience world-leading research group at the University of Sussex (Brighton, UK), led by Dr Dominique Makowski. The lab studies the neuropsychology of reality and its distortions — how people construct, perceive and misjudge what is real — spanning visual illusions, deception and lie detection, misinformation and fake news, beliefs about AI-generated content, interoception and the body's role in emotion, and the cognitive control of reality monitoring. It also develops open-source scientific software (NeuroKit2, Pyllusion, easystats and others), psychometric scales (the LIE Scale, the Illusion Game) and Bayesian statistical methods.",
"parentOrganization": {
"@type": "CollegeOrUniversity",
"name": "University of Sussex",
"url": "https://www.sussex.ac.uk/"
},
"address": {
"@type": "PostalAddress",
"streetAddress": "Pevensey 1, room 2B7, School of Psychology, University of Sussex",
"addressLocality": "Brighton",
"postalCode": "BN1 9QH",
"addressCountry": "GB"
},
"founder": { "@id": "https://realitybendinglab.com/#dominique-makowski" },
"sameAs": ["https://github.com/RealityBending", "https://x.com/Dom_Makowski"],
"knowsAbout": [
"Neuropsychology",
"Reality perception",
"Visual illusions",
"Deception",
"Misinformation",
"Interoception",
"Psychophysiology",
"Bayesian statistics"
]
},
{
"@type": "Person",
"@id": "https://realitybendinglab.com/#dominique-makowski",
"name": "Dominique Makowski",
"jobTitle": "Lecturer in Psychology",
"image": "https://realitybendinglab.com/people/dominique-makowski/avatar.jpg",
"email": "D.Makowski@sussex.ac.uk",
"affiliation": { "@id": "https://realitybendinglab.com/#organization" },
"worksFor": { "@id": "https://realitybendinglab.com/#organization" },
"url": "https://realitybendinglab.com/#dominique-makowski",
"sameAs": [
"https://scholar.google.com/citations?user=bg0BZ-QAAAAJ&hl",
"https://github.com/DominiqueMakowski",
"https://x.com/Dom_Makowski",
"https://www.researchgate.net/profile/Dominique_Makowski",
"https://www.linkedin.com/in/dominiquemakowski/",
"https://dominiquemakowski.github.io/CV/"
]
},
{
"@type": "WebSite",
"@id": "https://realitybendinglab.com/#website",
"url": "https://realitybendinglab.com/",
"name": "Reality Bending Lab",
"inLanguage": "en-GB",
"publisher": { "@id": "https://realitybendinglab.com/#organization" }
}
]
}
</script>
<!-- ── GoatCounter, with its own pageview counting switched off ──
`no_onload` is the whole point of this block, and it is not a
preference. count.js counts a pageview when it loads and then
again on History API changes — and this site is one document that
writes every URL with `replaceState` (CLAUDE.md: "Every URL write
is a replaceState"). Whether a given version of count.js hooks
`replaceState` as well as `pushState` is not a thing to depend on:
leaving it on means either one pageview for an entire visit, or
two for every route once shared/analytics.js also reports. So it
counts nothing by itself, and shared/analytics.js calls
`goatcounter.count()` once per route the reader actually reaches,
off `onRouteSettled` — the same channel page-meta.js reads.
The settings object must be assigned before count.js runs, which
is why it is a separate blocking line above an async script rather
than an attribute on it. The id is how analytics.js knows when the
async script has arrived; a hit made before then is queued. -->
<script>
window.goatcounter = { no_onload: true }
</script>
<script
id="goatcounter"
data-goatcounter="https://dommak.goatcounter.com/count"
async
src="//gc.zgo.at/count.js"
></script>
</head>
<body>
<!-- ════════════════════════════════════
DOOR SCREEN (landing)
════════════════════════════════════ -->
<div id="door-screen" role="button" tabindex="0" aria-label="Open main page">
<div id="door-bg"></div>
<div id="door-container">
<div class="door door-left"></div>
<div class="door door-right"></div>
</div>
<canvas id="rain-left" class="rain-canvas rain-canvas--left"></canvas>
<canvas id="rain-right" class="rain-canvas rain-canvas--right"></canvas>
<span class="click-hint">Click to Open</span>
</div>
<!-- ════════════════════════════════════
MAIN PAGE
════════════════════════════════════ -->
<div id="main-page">
<nav class="nav--hidden">
<!-- The mark is the way home. A real anchor rather than a
button, so middle-click and "copy link address" behave —
and `href="."` rather than "/" for the same reason
`<base href="./">` is relative: it resolves against the
base, which is the site root from a generated page three
segments down and from a sub-path-mounted copy alike.
The plain left click is handled in script.js instead, or
the browser would reload the whole site to reach a place
that is already on screen. -->
<a class="nav-left nav-home" href="." aria-label="Reality Bending Lab — back to top">
<img src="img/sussex_logo.svg" alt="University of Sussex logo" class="nav-logo nav-logo--sussex" />
<img src="img/lab_logo_black.png" alt="Reality Bending Lab logo" class="nav-logo" />
<span class="nav-brand">Reality Bending Lab</span>
</a>
<ul>
<li><a href="#sec-people-full">People</a></li>
<li><a href="#sec-research-full">Research</a></li>
<li><a href="#sec-news-full">News</a></li>
<li><a href="#sec-publications-full">Publications</a></li>
<!-- Join is a tab of Information, not a section: the href
scrolls there and data-contact-tab-target opens the tab.
data-section keeps applySectionTheme from confusing the
two links that share this href. -->
<li><a href="#sec-contact-full" data-section="sec-join" data-contact-tab-target="join">Join</a></li>
<li><a href="#sec-contact-full" data-section="sec-contact">Information</a></li>
<!-- One list item holding all three, not three items: the
bar is a row here and a 14rem column past 1800px, and
as separate items the icons would become three more
rows of that column. Inside one item they stay a
cluster in both. The marks are inline SVG in
currentColor, so the dark dress the Research zoom puts
on the nav (main-page--dark-zoom) carries them with
the section links and nothing has to know about them.
Inline rather than the People panel's icon CDN: this
bar is on screen for the whole visit. -->
<li class="nav-social">
<a
href="https://x.com/Dom_Makowski"
target="_blank"
rel="noopener noreferrer"
aria-label="Dominique Makowski on X"
title="X"
>
<svg viewBox="0 0 24 24" aria-hidden="true">
<path
d="M18.24 2.25h3.31l-7.23 8.26 8.5 11.24h-6.66l-5.22-6.82-5.96 6.82H1.66l7.73-8.84L1.25 2.25h6.83l4.71 6.23 5.45-6.23Zm-1.16 17.52h1.83L7.08 4.13H5.11l11.97 15.64Z"
/>
</svg>
</a>
<a
href="https://www.linkedin.com/in/dominiquemakowski/"
target="_blank"
rel="noopener noreferrer"
aria-label="Dominique Makowski on LinkedIn"
title="LinkedIn"
>
<svg viewBox="0 0 24 24" aria-hidden="true">
<path
d="M20.45 20.45h-3.56v-5.57c0-1.33-.02-3.04-1.85-3.04-1.85 0-2.14 1.45-2.14 2.94v5.67H9.35V9h3.41v1.56h.05a3.74 3.74 0 0 1 3.37-1.85c3.6 0 4.27 2.37 4.27 5.46v6.28ZM5.34 7.43a2.07 2.07 0 1 1 0-4.13 2.07 2.07 0 0 1 0 4.13Zm1.78 13.02H3.55V9h3.57v11.45ZM22.22 0H1.77C.79 0 0 .77 0 1.72v20.56C0 23.23.79 24 1.77 24h20.45c.98 0 1.78-.77 1.78-1.72V1.72C24 .77 23.2 0 22.22 0Z"
/>
</svg>
</a>
<a
href="https://github.com/DominiqueMakowski"
target="_blank"
rel="noopener noreferrer"
aria-label="Dominique Makowski on GitHub"
title="GitHub"
>
<svg viewBox="0 0 16 16" aria-hidden="true">
<path
d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82a7.65 7.65 0 0 1 2-.27c.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.01 8.01 0 0 0 16 8c0-4.42-3.58-8-8-8z"
/>
</svg>
</a>
</li>
</ul>
</nav>
<div class="hero">
<div class="hero__intro">
<img class="hero__banner" src="img/lab_banner_white.png" alt="Reality Bending Lab" />
<h1 class="hero__title">Exploring the neuropsychology of reality and its distortions.</h1>
<p class="hero__summary">
The Reality Bending Lab, led by Dominique Makowski at the University of Sussex in Brighton, UK, conducts
world-leading research on reality perception, illusions, fake news, AI-beliefs, deception and its links with
emotions, cognitive control and the Self. Using recording signals from the body (ECG, EDA…) and the brain
(EEG), we analyse data using advanced modelling (Bayesian statistics, chaos theory, computational models) and
develop
<a href="https://github.com/RealityBending" target="_blank" rel="noopener">open-source tools</a> to improve
neuropsychological science.
</p>
<p class="hero__quote">
<a href="https://www.youtube.com/watch?v=uAXtO5dMqEI" target="_blank" rel="noopener">
“Do not try to bend the spoon — that’s impossible. Instead, only try to realise the truth:
there is no spoon. Then you'll see that it is not the spoon that bends, <b>it is only yourself</b>.”
</a>
</p>
</div>
<div class="hero__brain">
<div class="brain-atlas">
<div class="brain-atlas__center">
<div id="brain-viewer">
<div id="brain-tooltip"></div>
</div>
</div>
<!-- Source order is the order down the arc: the
positions come from :nth-child in css/04-hero.css,
and so
do the colours, which stay with the position rather
than with the section. Same order as the nav. -->
<div class="menu-buttons">
<button type="button" class="menu-button section--people" id="sec-people">
<span class="menu-button__label">People</span>
</button>
<button type="button" class="menu-button section--research" id="sec-research">
<span class="menu-button__label">Research</span>
</button>
<button type="button" class="menu-button section--news" id="sec-news">
<span class="menu-button__label">News</span>
</button>
<button type="button" class="menu-button section--publications" id="sec-publications">
<span class="menu-button__label">Publications</span>
</button>
<button type="button" class="menu-button section--join" id="sec-join" data-contact-tab-target="join">
<span class="menu-button__label">Join</span>
</button>
<button type="button" class="menu-button section--contact" id="sec-contact">
<span class="menu-button__label">Information</span>
</button>
</div>
</div>
</div>
</div>
<!-- ── With JavaScript off ──
The homepage is the one page here with no `#prerender` block —
a generated page carries its content statically and a reader
with no JS keeps it, but this one is the shell the modules fill.
Two things follow, and the second is the one that matters:
- Four sections would render as a heading, a tab bar and
nothing, which reads as broken rather than as degraded. The
<style> in <head> takes them away, and this block replaces
them with links to the same six sections at their real paths
— which *are* statically rendered, so those links work.
- **The door would otherwise be a wall.** #door-screen is fixed
over everything and #main-page is `pointer-events: none`
until script adds `.visible`; without that stylesheet a
reader with no JS cannot get past the landing screen at all,
and nothing on the page tells them why.
The hero and the whole Information section are static markup
and survive untouched, so what is left is a real page: who the
lab is, where it is, and the way in to everything else. -->
<noscript>
<div class="noscript-note">
<p class="noscript-note__lead">
This site uses JavaScript for its interactive parts — the 3D brain, the research dive, and the panels that
open over People, News and Publications. Every one of those has a plain page of its own:
</p>
<ul class="noscript-note__links">
<li><a href="people/">People</a></li>
<li><a href="research/">Research</a></li>
<li><a href="news/">News</a></li>
<li><a href="publications/">Publications</a></li>
<li><a href="join/">Join the Lab</a></li>
<li><a href="information/">Information</a></li>
</ul>
</div>
</noscript>
<!-- ════════════════════════════════════
PEOPLE SECTION
════════════════════════════════════ -->
<section class="people-full" id="sec-people-full">
<!-- Dimmed backdrop loop. preload="none" holds the download
until the section scrolls into view; initPeopleVideo in
script.js starts it from there. No autoplay attribute —
it would defeat preload="none" and fetch immediately.
muted + playsinline are what make script-driven play
permitted. Sources are built by encode_intro_bg.sh. -->
<div class="people-full__video" aria-hidden="true">
<video
class="people-full__video-el"
poster="img/intro-bg.jpg"
preload="none"
muted
loop
playsinline
disablepictureinpicture
>
<source src="img/intro-bg.webm" type="video/webm; codecs=vp9" />
<source src="img/intro-bg.mp4" type="video/mp4" />
</video>
</div>
<h2>People</h2>
<div class="people-tabs-nav" role="tablist" aria-label="People views">
<button
type="button"
class="people-tab-btn people-tab-btn--active"
data-tab="lab"
role="tab"
aria-selected="true"
aria-controls="people-tab-lab"
>
The Lab
</button>
<button
type="button"
class="people-tab-btn"
data-tab="collaborations"
role="tab"
aria-selected="false"
aria-controls="people-tab-collaborations"
>
Collaborations
</button>
<button
type="button"
class="people-tab-btn"
data-tab="memories"
role="tab"
aria-selected="false"
aria-controls="people-tab-memories"
>
Memories
</button>
</div>
<div class="people-tab-panel" id="people-tab-lab" role="tabpanel">
<div id="people-grid">
<!-- populated by people/people.js from people/people_manifest.json -->
</div>
</div>
<div class="people-tab-panel" id="people-tab-collaborations" role="tabpanel" hidden>
<div class="people-collaborations">
<div class="people-collaborations__section people-collaborations__section--network">
<div class="people-collaborations__section-header">
<h3>Collaboration Network</h3>
<p>
The Reality Bending Lab is a highly collaborative environment, with many friends and colleagues from all
over the world involved in various projects.
</p>
</div>
<div class="people-collaborations__layout">
<div class="people-collaborations__canvas">
<div
id="collaboration-network"
class="collaboration-network"
aria-label="Full collaboration network graph"
></div>
</div>
</div>
</div>
<div class="people-collaborations__section" id="close-collaborators-section" hidden>
<div class="people-collaborations__section-header">
<h3>Close Collaborators</h3>
<p>Our academic family. Friends and colleagues with shared passions and interests.</p>
</div>
<div id="close-collaborators" class="collaboration-people-list" aria-label="Close Collaborators"></div>
</div>
<div class="people-collaborations__section" id="consultants-section" hidden>
<div class="people-collaborations__section-header">
<h3>Consultants</h3>
<p>We get help from the very best.</p>
</div>
<div id="consultants" class="collaboration-people-list" aria-label="Consultants"></div>
</div>
</div>
</div>
<div class="people-tab-panel" id="people-tab-memories" role="tabpanel" hidden>
<div class="memories-gallery" id="memories-gallery">
<!-- populated by memories/memories.js from memories/memories_manifest.json -->
</div>
</div>
</section>
<!-- ════════════════════════════════════
RESEARCH SECTION
════════════════════════════════════ -->
<section class="research-full" id="sec-research-full">
<div id="research-root"></div>
</section>
<!-- ════════════════════════════════════
NEWS SECTION
════════════════════════════════════ -->
<section class="news-full" id="sec-news-full">
<!-- populated by news/news.js from news/news_manifest.json,
which update_news.py builds from the folders in news/ -->
<div id="news-root"></div>
</section>
<!-- ════════════════════════════════════
PUBLICATIONS SECTION
════════════════════════════════════ -->
<section class="publications-full" id="sec-publications-full">
<div class="pub-header">
<h2>Publications</h2>
<!-- The link is the fallback and the anchor stays whatever
happens; publications.js replaces the label with the
rotating metrics once the manifest has landed, because
one of the three numbers is the manifest's own length.
With no JS this is still a working Scholar link. -->
<a
href="https://scholar.google.com/citations?user=bg0BZ-QAAAAJ"
target="_blank"
rel="noopener noreferrer"
class="pub-scholar"
aria-label="View our Google Scholar profile"
>
<svg class="pub-scholar__cap" viewBox="0 0 24 24" aria-hidden="true">
<path d="M12 24a7 7 0 1 1 0-14 7 7 0 0 1 0 14zm0-24L0 9.5h3.18v6.82h17.64V9.5H24L12 0z" />
</svg>
<span class="pub-scholar__label">View on Google Scholar</span>
</a>
</div>
<div class="pub-tabs-nav" role="tablist">
<button
type="button"
class="pub-tab-btn pub-tab-btn--active"
data-tab="list"
role="tab"
aria-selected="true"
aria-controls="pub-tab-list"
>
List
</button>
<button
type="button"
class="pub-tab-btn"
data-tab="gallery"
role="tab"
aria-selected="false"
aria-controls="pub-tab-gallery"
>
Gallery
</button>
</div>
<div class="pub-tab-panel" id="pub-tab-list" role="tabpanel">
<div class="pub-search-bar">
<input
type="search"
id="pub-search"
placeholder="Filter by title, keyword, author…"
aria-label="Filter publications"
/>
</div>
<div id="publications-list">
<!-- populated by publications/publications.js from publications/publications_manifest.json -->
</div>
</div>
<div class="pub-tab-panel" id="pub-tab-gallery" role="tabpanel" hidden>
<div id="publications-gallery">
<!-- populated by publications/publications.js -->
</div>
</div>
</section>
<!-- ════════════════════════════════════
CONTACT SECTION
════════════════════════════════════ -->
<section class="contact-full" id="sec-contact-full">
<!-- Parallaxed backdrop for the whole section, all three tabs.
Replaces the per-panel .contact-banner this used to be. -->
<div
class="contact-full__backdrop"
role="img"
aria-label="University of Sussex collage showing Brighton, campus, and Brighton Pier"
>
<span class="contact-full__backdrop-img"></span>
<!-- Crossfade partner. Holds the outgoing photograph while the
Join tab swaps levels, then fades out over it. Both layers
read --contact-parallax off the parent, so they move
together and the fade never shears. -->
<span class="contact-full__backdrop-img contact-full__backdrop-img--out" aria-hidden="true"></span>
</div>
<h2 class="contact-full__title">Information</h2>
<div class="contact-tabs-nav" role="tablist" aria-label="Information views">
<button
type="button"
class="contact-tab-btn contact-tab-btn--active"
id="contact-tab-btn-contact"
data-tab="contact"
role="tab"
aria-selected="true"
aria-controls="contact-contact"
>
Contact
</button>
<button
type="button"
class="contact-tab-btn"
id="contact-tab-btn-join"
data-tab="join"
role="tab"
aria-selected="false"
aria-controls="contact-join"
>
Join
</button>
<button
type="button"
class="contact-tab-btn"
id="contact-tab-btn-services"
data-tab="services"
role="tab"
aria-selected="false"
aria-controls="contact-services"
>
Services
</button>
</div>
<div
class="contact-tab-panel"
id="contact-contact"
role="tabpanel"
aria-labelledby="contact-tab-btn-contact"
>
<div class="contact-full__inner">
<div class="contact-panel__content">
<p class="contact-full__eyebrow">Where to find us</p>
<p class="contact-full__lede">
The Reality Bending Lab is based in the School of Psychology, at the
<a class="contact-inline-link" href="https://www.sussex.ac.uk/" target="_blank" rel="noreferrer noopener"
>University of Sussex</a
>
in Brighton, UK.
</p>
<div class="contact-address-card">
<div class="contact-detail">
<span class="contact-detail__icon" aria-hidden="true">
<svg
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="1.8"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M3.75 6.75h16.5v10.5H3.75z"></path>
<path d="M4.5 7.5 12 13.5l7.5-6"></path>
</svg>
</span>
<a class="contact-inline-link" href="mailto:D.Makowski@sussex.ac.uk">D.Makowski@sussex.ac.uk</a>
</div>
<div class="contact-detail">
<span class="contact-detail__icon" aria-hidden="true">
<svg
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="1.8"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M12 21s6-5.33 6-11a6 6 0 1 0-12 0c0 5.67 6 11 6 11Z"></path>
<circle cx="12" cy="10" r="2.35"></circle>
</svg>
</span>
<p>Pevensey 1 - room 2B7, School of Psychology, University of Sussex, BN1 9QH</p>
</div>
</div>
</div>
<div class="contact-full__map">
<iframe
title="University of Sussex location on Google Maps"
src="https://maps.google.com/maps?width=100%25&height=600&hl=en&q=University%20of%20Sussex%2C%20Falmer%2C%20Brighton%20BN1%209QH%2C%20UK&t=&z=6&ie=UTF8&iwloc=B&output=embed"
width="100%"
height="100%"
loading="lazy"
referrerpolicy="no-referrer-when-downgrade"
></iframe>
</div>
</div>
<!-- ── Why here ──
Carried over from the old site, where it sat under the
Sussex photograph on the homepage, and kept for the
reason it was written: most of the people this lab
wants to hear from are not in the UK, and "University
of Sussex, Brighton" means nothing to them. An address
says where the lab is; this says what it is like to be
there, which is the part a prospective PhD student in
Lisbon or Singapore is actually weighing.
Below the address panel rather than inside it: the
glass card answers "where", and its left column is
already a lede plus an address against a map. This is a
different question and gets its own block, at reading
width rather than in a half-column.
It is also the only substantial block of static prose
on the page outside the hero, which is worth knowing
before anyone trims it — the raw HTML a crawler that
runs nothing comes away with is ~270 words, and this is
a third of them. See SEO-PLAN.md §4. -->
<div class="contact-why">
<!-- ── The picture and the mark, together ──
The section's own backdrop is a collage, parallaxed
and largely behind the panels; this is the one place
a reader gets to actually look at the place. The
crest rides on it rather than sitting beside it,
because a crest next to a photograph of the same
campus is two ways of saying "Sussex" competing for
the same corner — on it, the photograph is the
subject and the mark is the label.
A column rather than a banner across the top: the
block is only ~380px tall, and a 1200px-wide band
cut to that leaves a 5:1 letterbox of a landscape.
As a column it fills whatever height the prose turns
out to be, the same arrangement the publication
cards use for their figures. It becomes a banner
below 900px, at the photograph's own 16:9. -->
<figure class="contact-why__figure">
<img
class="contact-why__photo"
src="information/img/sussex_landscape.jpg"
alt="The University of Sussex campus in the South Downs"
width="1200"
height="675"
loading="lazy"
/>
<img
class="contact-why__crest"
src="information/img/logo_sussex.svg"
alt="University of Sussex crest"
width="577"
height="624"
loading="lazy"
/>
</figure>
<div class="contact-why__copy">
<p class="contact-full__eyebrow">University of Sussex</p>
<p class="contact-why__lede">
<a
class="contact-inline-link"
href="https://en.wikipedia.org/wiki/Brighton"
target="_blank"
rel="noreferrer noopener"
>Brighton</a
>
is the sunniest city in the UK and, by some margin, its most cheerfully strange — on the sea, an
hour from London. The University of Sussex sits just above it in the South Downs, and its School of
Psychology is one of the largest and strongest in the country.
</p>
<p class="contact-why__lede">
It is famous for its research on consciousness and interoception, with scientists like
<a
class="contact-inline-link"
href="https://www.anilseth.com/"
target="_blank"
rel="noreferrer noopener"
>Anil Seth</a
>,
<a
class="contact-inline-link"
href="https://en.wikipedia.org/wiki/Andy_Clark"
target="_blank"
rel="noreferrer noopener"
>Andy Clark</a
>,
<a
class="contact-inline-link"
href="https://scholar.google.fr/citations?user=1n48dTUAAAAJ&hl=en"
target="_blank"
rel="noreferrer noopener"
>Zoltan Dienes</a
>
and
<a
class="contact-inline-link"
href="https://scholar.google.co.uk/citations?user=5jA5GcAAAAAJ&hl=en"
target="_blank"
rel="noreferrer noopener"
>Hugo Critchley</a
>, its teaching of cutting-edge psychological methods (with stats rockstar
<a
class="contact-inline-link"
href="https://en.wikipedia.org/wiki/Andy_Field_(academic)"
target="_blank"
rel="noreferrer noopener"
>Andy Field</a
>), its history of multidisciplinary research (arts and science), and its radical engagement in
open and disruptive science.
</p>
<p class="contact-why__tail">
<a class="contact-cta" href="#sec-contact-full" data-contact-tab-target="join"
>Join this community</a
>
</p>
</div>
</div>
</div>
<div class="contact-tab-panel" id="contact-join" role="tabpanel" aria-labelledby="contact-tab-btn-join" hidden>
<!-- Rendered by information/join.js from information/join-content.js.
Copy and links live in the content module, not here. -->
<div id="join-root"></div>
</div>
<div class="contact-tab-panel" id="contact-services" role="tabpanel" aria-labelledby="contact-tab-btn-services" hidden>
<!-- Rendered by information/services.js from information/services-content.js.
Copy, imagery and the past-work list live in the content module, not here. -->
<div id="services-root"></div>
</div>
</section>
<footer>© 2026 Reality Bending Lab · University of Sussex</footer>
<!-- Floating action buttons -->
<div class="fab-group">
<!-- Sits above the two standing offers, and is placed against
the group rather than laid out in its column so it cannot
widen them (see .fab--research). It is up only while the
Research section's Overview is the tab on screen, and it
makes the same jump the zoom's own rail exit does;
research.js owns both. A button rather than an anchor:
there is no fragment for "the other tab". -->
<button type="button" class="fab fab--research" id="fab-research-creations">What we created</button>
<a href="#sec-contact-full" class="fab" data-contact-tab-target="services">Hire us</a>
<a href="#sec-contact-full" class="fab fab--primary" data-contact-tab-target="join">Join the Lab</a>
<!-- Slides up under the other two half way down the page, and
withdraws again on the Information section. initSitePromoFab
in script.js owns the timing; the tab it opens is handled by
the same data-contact-tab-target as the buttons above. -->
<a href="#sec-contact-full" class="fab fab--promo" id="fab-site-promo" data-contact-tab-target="services">
<span class="fab__lead">Like this website?</span>
<span class="fab__sub">See how to get yours</span>
</a>
</div>
</div>
<!-- Bulletproof landing fallback: opens the door even if the ES modules
below fail to load. script.js re-attaches richer handlers on top. -->
<script>
;(function () {
var doorScreen = document.getElementById("door-screen")
var mainPage = document.getElementById("main-page")
if (!doorScreen || !mainPage) return
function openDoors() {
if (doorScreen.classList.contains("opening")) return