/* NEB Network — one-page website.
   Flat and calm: paper + ink, Space Grotesk Light headlines, Inter body, mono labels.
   The three phase colours are markers only (rings, lines, badges). */

:root {
  --paper: #f7f7f5;
  --white: #ffffff;
  --ink: #111111;
  --grey: #5a5a5a;
  --muted: #808080;
  --hair: rgba(17, 17, 17, 0.12);
  --pressed: #ebebe8;

  --dreaming: #30a4e3;
  --decision: #e9ce10;
  --dwelling: #46a872;
  --dreaming-deep: #007cd5;
  --decision-deep: #cba700;
  --dwelling-deep: #06813a;

  --display: 'Space Grotesk', 'Inter', system-ui, sans-serif;
  --body: 'Inter', system-ui, -apple-system, sans-serif;
  --mono: 'Space Mono', ui-monospace, Menlo, monospace;

  --gutter: clamp(16px, 5vw, 64px);
  --max: 1160px;
}
/* Ukrainian: Space Grotesk and Space Mono have no Cyrillic, so its headings use Manrope and its labels JetBrains Mono
   (fonts/fonts.css), the app's name too; the language button and the English/German legal text keep the house fonts */
:root:lang(uk) { --display: 'Manrope', 'Inter', system-ui, sans-serif; --mono: 'JetBrains Mono', ui-monospace, Menlo, monospace; }
:root:lang(uk) :is(.lang, [lang]:not(:lang(uk))) { --display: 'Space Grotesk', 'Inter', system-ui, sans-serif; --mono: 'Space Mono', ui-monospace, Menlo, monospace; }

*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { transition: none !important; animation: none !important; }
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font: 300 17px/1.6 var(--body);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}
img, video { max-width: 100%; display: block; }
a { color: inherit; }
p { margin: 0; }

.wrap { width: 100%; max-width: var(--max); margin: 0 auto; padding: 0 var(--gutter); }

/* ---------- type ---------- */

h1, h2, h3 { font-family: var(--display); font-weight: 300; letter-spacing: -0.01em; margin: 0; }
h1 { font-size: clamp(38px, 4.8vw, 66px); line-height: 1.04; } /* the hero headline; was up to 80px (2026-11-03: "a little smaller"); 66 lets "Urban Experience" fit one line */
h2 { font-size: clamp(32px, 4.2vw, 54px); line-height: 1.08; }
h3 { font-size: clamp(28px, 3vw, 40px); line-height: 1.12; }
.lead { font-size: clamp(18px, 1.6vw, 20px); color: var(--grey); max-width: 34em; }

/* the App Store's section rule: a mono label sitting on a line */
.rule {
  display: flex;
  align-items: center;
  gap: 12px;
  font: 400 11px/1 var(--mono);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink);
}
.rule::after { content: ''; flex: 1; height: 1px; background: var(--rule, var(--grey)); }
.rule .dot { width: 12px; height: 12px; border-radius: 50%; border: 2px solid var(--rule, var(--grey)); flex: none; }

/* ---------- buttons ---------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 52px;
  padding: 0 26px;
  border-radius: 999px;
  border: 1px solid var(--grey);
  background: transparent;
  color: var(--grey);
  font: 400 16px/1 var(--body);
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color 0.15s;
}
.btn:hover { background: var(--pressed); }
.btn--ink { background: var(--ink); border-color: var(--ink); color: var(--white); }
.btn--ink:hover { background: #2a2a2a; }
.btn--sm { height: 40px; padding: 0 18px; font-size: 14px; }
.ctas { display: flex; flex-wrap: wrap; gap: 12px; }

/* ---------- header ---------- */

.top {
  position: fixed;
  inset: 0 0 auto;
  z-index: 50;
  height: 72px;
  background: var(--paper);
  border-bottom: 1px solid transparent;
  transition: border-color 0.2s;
}
.top.is-scrolled { border-bottom-color: var(--hair); }
.top .wrap { height: 100%; display: flex; align-items: center; justify-content: space-between; gap: 16px; }
.brand { display: flex; align-items: center; gap: 10px; text-decoration: none; color: var(--ink); }
.brand .mark { width: 40px; height: 40px; margin: -4px; } /* neb-mark-clear.png: the white made transparent, so it needs no multiply (which a moving logo breaks) */
.brand .name { font: 400 20px/1 var(--display); letter-spacing: -0.01em; display: grid; gap: 5px; white-space: nowrap; }
.brand small { font: 400 8px/1 var(--mono); letter-spacing: 0.18em; text-transform: uppercase; color: var(--muted); }
.btn .short { display: none; }
.top nav { display: flex; align-items: center; gap: 6px; }
.top nav a.link { color: var(--grey); text-decoration: none; font-size: 15px; padding: 8px 12px; }
.top nav a.link:hover { color: var(--ink); }
/* the language menu: a globe with the current code; the list (built by i18n.js) drops below it */
.lang { position: relative; margin: 0 4px; }
.lang-btn { display: flex; align-items: center; gap: 7px; height: 40px; padding: 0 12px; border: 0; border-radius: 999px; background: none; color: var(--ink); font: 400 12px/1 var(--mono); letter-spacing: 0.12em; cursor: pointer; transition: background 0.15s; }
.lang-btn:hover, .lang.is-open .lang-btn { background: var(--pressed); }
.lang-btn svg { flex: none; fill: none; stroke: currentColor; }
.lang-btn .globe { width: 16px; height: 16px; stroke-width: 1.1; color: var(--grey); }
.lang-btn .chev { width: 8px; height: 5px; stroke-width: 1.3; color: var(--muted); transition: transform 0.2s; }
.lang.is-open .lang-btn .chev { transform: rotate(180deg); }
.lang-list {
  position: absolute; top: calc(100% + 8px); right: 0; z-index: 60;
  min-width: 188px; max-height: calc(100vh - 88px); overflow-y: auto; overscroll-behavior: contain;
  margin: 0; padding: 6px; list-style: none;
  background: var(--white); border: 1px solid var(--hair); border-radius: 14px;
  box-shadow: 0 16px 40px rgba(17, 17, 17, 0.1), 0 2px 6px rgba(17, 17, 17, 0.04);
  opacity: 0; visibility: hidden; transform: translateY(-4px);
  transition: opacity 0.16s ease, transform 0.16s ease, visibility 0s linear 0.16s;
}
.lang.is-open .lang-list { opacity: 1; visibility: visible; transform: none; transition: opacity 0.16s ease, transform 0.16s ease; }
.lang-list button {
  display: flex; align-items: center; justify-content: space-between; gap: 20px; width: 100%;
  padding: 10px 12px; border: 0; border-radius: 9px; background: none;
  color: var(--grey); font: 300 15px/1.2 var(--body); text-align: left; cursor: pointer;
}
.lang-list button:hover, .lang-list button:focus-visible { background: var(--paper); color: var(--ink); outline: none; }
.lang-list button[aria-current='true'] { color: var(--ink); font-weight: 400; }
.lang-list .lang-code { display: flex; align-items: center; gap: 8px; font: 400 11px/1 var(--mono); letter-spacing: 0.12em; color: var(--muted); }
.lang-list button[aria-current='true'] .lang-code::before { content: ''; width: 6px; height: 6px; border-radius: 50%; background: var(--ink); }
@media (max-width: 820px) { .top nav a.link { display: none; } }
@media (max-width: 520px) {
  .top .wrap { gap: 8px; }
  .top nav { gap: 6px; }
  .lang { margin: 0 0 0 auto; }
  .lang-btn { padding: 0 9px; gap: 6px; }
  /* the name changes with the language: if it still does not fit beside the buttons, it takes two even lines */
  .top .brand { min-width: 0; }
  .top .brand .name { white-space: normal; text-wrap: balance; line-height: 1.05; }
  .top nav { margin-left: auto; }
  .top .btn--sm { padding: 0 14px; }
  .brand { gap: 8px; }
  .brand .mark { width: 34px; height: 34px; }
  .top { height: 60px; }
  .brand .name { font-size: 18px; }
  .top .btn .long { display: none; }
  .top .btn .short { display: inline; }
}
/* the globe and the code say enough on a small phone */
@media (max-width: 400px) { .lang-btn .chev { display: none; } }

/* ---------- the clip (2026-11-02) ----------
   3:4 like the recordings (~/website-recorder, encode43.sh) and no device frame (was a grey phone, then a tablet):
   rounded, lit from behind by its own colours (see "the clip's backlight" at the end).
   As wide as 440px allows, but never so tall that it and its note leave the screen on a laptop. */

:root { --dev-w: min(440px, 84vw, calc((100vh - 260px) * 0.75)); }
.phone { position: relative; width: var(--dev-w); aspect-ratio: 3 / 4; isolation: isolate; }
.phone-screen { position: relative; width: 100%; height: 100%; border-radius: 20px; overflow: hidden; background: #f4f4f2; isolation: isolate; box-shadow: 0 0 0 1px rgba(17, 17, 17, 0.06); } /* light, so a sub-pixel gap under the video never shows as a dark line */
.phone-screen > img, .phone-screen > video { position: absolute; inset: -1px; width: calc(100% + 2px); max-width: none; height: calc(100% + 2px); object-fit: cover; } /* max-width: none, or the reset caps the overscan and a 1px light line shows on the right */

/* ---------- hero ---------- */

.hero { min-height: 100svh; display: flex; align-items: center; padding: 120px 0 96px; }
.hero .wrap { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: clamp(32px, 5vw, 64px); align-items: center; }
.hero-copy { display: grid; gap: 26px; }
.hero h1 .soft { color: var(--grey); }
/* French, Spanish and Italian need longer words for the headline: a touch smaller on wide screens keeps it at
   three lines like the English */
@media (min-width: 861px) { .hero h1:is(:lang(fr), :lang(es), :lang(it)) { font-size: clamp(38px, 4.4vw, 63px); } }
.hero-phone { justify-self: center; display: flex; flex-direction: column; align-items: center; }
.hero-phone .phone { width: min(400px, var(--dev-w)); } /* 400: the headline's first line still fits beside it */
/* the small line under every phone with a recording: the content is made up */
.phone-note { margin: 12px 0 0; max-width: 260px; text-align: center; font-size: 11px; line-height: 1.4; color: var(--muted); }
.journey-phone .phone-note { margin: 0; }
@media (max-width: 860px) {
  .hero { min-height: 0; padding: 104px 0 96px; }
  .hero .wrap { grid-template-columns: 1fr; gap: 36px; }
  .hero-copy { gap: 20px; }
  .hero .ctas { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
  .hero .ctas .btn { padding: 0 12px; font-size: 15px; }
  .hero-phone .phone { width: min(260px, 66vw); }
}

/* ---------- sections ---------- */

.sec { padding: clamp(120px, 14vw, 190px) 0; }
.sec--white { background: var(--white); border-top: 1px solid var(--hair); border-bottom: 1px solid var(--hair); }
.sec-head { display: grid; gap: 24px; max-width: 760px; margin-bottom: clamp(56px, 7vw, 96px); }

/* what is a portal */
.portal-what { display: grid; grid-template-columns: 0.9fr 1.1fr; gap: clamp(32px, 6vw, 96px); align-items: center; }
.portal-what .copy { display: grid; gap: 22px; }
.voice-note {
  display: flex; gap: 16px; align-items: center;
  border-top: 1px solid var(--hair); padding-top: 22px; margin-top: 6px;
  color: var(--ink);
}
.mic {
  width: 52px; height: 52px; border-radius: 50%;
  border: 1.5px solid var(--grey); display: grid; place-items: center; flex: none;
}
.mic svg { width: 22px; height: 22px; stroke: var(--grey); fill: none; stroke-width: 1.4; stroke-linecap: round; }
@media (max-width: 860px) {
  .portal-what { grid-template-columns: 1fr; gap: 48px; }
}

/* ---------- the journey: the phone stays, the text moves ---------- */

.journey { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(32px, 6vw, 96px); }
.journey-phone { position: sticky; top: calc(50vh - var(--dev-w) * 4 / 3 / 2 + 36px); align-self: start; display: flex; justify-content: center; }
.journey-phone .phone-screen > * { opacity: 0; transition: opacity 0.5s ease; }
.journey-phone .phone-screen > .is-on { opacity: 1; }

.step { min-height: 88vh; display: flex; flex-direction: column; justify-content: center; gap: 20px; padding: 40px 0; }
.step p { color: var(--grey); max-width: 30em; }
.step .rule { --rule: var(--grey); }
.step[data-phase='dreaming'] .rule { --rule: var(--dreaming); }
.step[data-phase='decision'] .rule { --rule: var(--decision); }
.step[data-phase='dwelling'] .rule { --rule: var(--dwelling); }

/* the phase badges (the app's exports: disc / star / hexagon with the phase glyph) */
.badge { position: relative; width: 34px; height: 34px; flex: none; display: grid; place-items: center; order: 2; }
.badge img { position: absolute; inset: 0; width: 100%; height: 100%; }
.badge .glyph { position: static; width: 16px; height: auto; filter: brightness(0) invert(1); }
.step .rule::after { order: 3; }

/* a spoken line, as it would be said into the microphone */
.said {
  align-self: flex-start;
  display: inline-flex; align-items: center; gap: 12px;
  border: 1px solid var(--hair);
  background: var(--paper);
  border-radius: 999px;
  padding: 8px 20px 8px 8px;
  font-size: 16px;
  color: var(--ink);
}
.said .mic { width: 36px; height: 36px; border-width: 1px; }
.said .mic svg { width: 16px; height: 16px; }
@media (max-width: 520px) { .said { border-radius: 22px; font-size: 15px; align-items: flex-start; } .said .mic { margin-top: 1px; } }

.journey-phone { flex-direction: column; align-items: center; gap: 18px; }
.dots { display: flex; gap: 8px; }
.dots i { width: 8px; height: 8px; border-radius: 50%; background: var(--hair); transition: background-color 0.3s, transform 0.3s; }
.dots i.is-on { background: var(--grey); transform: scale(1.25); }
.dots i.d-dreaming.is-on { background: var(--dreaming); }
.dots i.d-decision.is-on { background: var(--decision); }
.dots i.d-dwelling.is-on { background: var(--dwelling); }
.journey .steps { order: 1; }
.journey-phone { order: 2; }



/* ---------- the team (2026-11-03): a wide photo (2:1 crop), the names below in an order main.js shuffles ---------- */
.team-photo { margin: 0; aspect-ratio: 2 / 1; border-radius: 22px; overflow: hidden; background: var(--pressed); }
.team-photo img { width: 100%; height: 100%; object-fit: cover; }
.team-names { list-style: none; margin: clamp(36px, 4.5vw, 56px) 0 0; padding: 0; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 32px clamp(20px, 3vw, 40px); }
.team-names li { display: grid; gap: 8px; align-content: start; padding-top: 18px; border-top: 1px solid var(--hair); }
.team-name { font: 400 19px/1.3 var(--body); color: var(--ink); }
.team-role { font: 400 11px/1.5 var(--mono); letter-spacing: 0.14em; text-transform: uppercase; color: var(--muted); }
@media (max-width: 860px) {
  .team-names { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 28px 20px; }
  .team-photo { border-radius: 16px; }
  .team-name { font-size: 17px; }
}
@media (max-width: 360px) { .team-names { grid-template-columns: 1fr; } }

/* ---------- NEB ---------- */

/* ---------- out in the field: the test gallery (2026-10-29) ----------
   A bento grid. On a mouse, every photo drifts against the cursor by its own depth (main.js sets --mx/--my on the
   gallery, -1..1), so the wall reads as layers; the one under the cursor lifts, tilts toward it and zooms in. */
.gallery { --mx: 0; --my: 0; display: grid; grid-template-columns: repeat(12, 1fr); grid-auto-rows: clamp(34px, 3.7vw, 52px); gap: clamp(10px, 1.4vw, 18px); perspective: 1200px; }
.g { --d: 1; --tx: 0; --ty: 0; margin: 0; position: relative; overflow: hidden; border-radius: 22px; background: var(--pressed);
  transform: rotateX(calc(var(--ty) * -4deg)) rotateY(calc(var(--tx) * 4deg)) scale(1); transition: transform 0.6s cubic-bezier(.2,.7,.2,1), box-shadow 0.6s ease; will-change: transform; }
.g img { position: absolute; top: -7%; left: -7%; width: 114%; height: 114%; max-width: none; object-fit: cover; display: block;
  transform: translate3d(calc(var(--mx) * var(--d) * -14px), calc(var(--my) * var(--d) * -14px), 0) scale(1);
  transition: transform 0.9s cubic-bezier(.2,.7,.2,1), filter 0.6s ease; }
.g::after { content: ''; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  background: radial-gradient(circle at calc(50% + var(--tx) * 50%) calc(50% + var(--ty) * 50%), rgba(255,255,255,0.22), transparent 55%); opacity: 0; transition: opacity 0.5s ease; }
.g--a { grid-column: 1 / 8; grid-row: span 6; } /* half-height rows: the two beside it get 3 each, not squeezed into 2 */
.g--b { grid-column: 8 / 13; grid-row: span 3; }
.g--c { grid-column: 8 / 13; grid-row: span 3; }
.g--d { grid-column: 1 / 5; grid-row: span 4; }
.g--e { grid-column: 5 / 9; grid-row: span 4; }
.g--f { grid-column: 9 / 13; grid-row: span 4; }
.g-quote { grid-column: 1 / 6; grid-row: span 4; margin: 0; align-self: center; padding: clamp(8px, 2vw, 28px) clamp(4px, 1.5vw, 24px) clamp(8px, 2vw, 28px) 0; }
.g-quote p { margin: 0; font: 300 clamp(20px, 2vw, 26px)/1.3 var(--display); color: var(--ink); }
.g-quote cite { display: block; margin-top: 18px; font: 400 11px/1 var(--mono); letter-spacing: 0.16em; text-transform: uppercase; font-style: normal; color: var(--muted); }
.g--g { grid-column: 6 / 13; grid-row: span 4; }
@media (hover: hover) and (pointer: fine) {
  .gallery:hover .g:not(:hover) img { filter: saturate(0.75) brightness(0.97); }
  .g:hover { transform: rotateX(calc(var(--ty) * -4deg)) rotateY(calc(var(--tx) * 4deg)) scale(1.025); box-shadow: 0 24px 50px -28px rgba(17,17,17,0.45); z-index: 1; }
  .g:hover img { transform: translate3d(calc(var(--tx) * -22px), calc(var(--ty) * -22px), 0) scale(1.06); transition-duration: 0.5s; }
  .g:hover::after { opacity: 1; }
}
@media (prefers-reduced-motion: reduce) { .g, .g img { transform: none !important; } .phone-screen { cursor: pointer; } }
@media (max-width: 860px) {
  .gallery { grid-template-columns: repeat(2, 1fr); grid-auto-rows: 38vw; }
  .g--a, .g--g { grid-column: 1 / -1; grid-row: span 1; }
  .g--b, .g--c, .g--d, .g--e, .g--f { grid-column: auto; grid-row: span 1; }
  .g--f { grid-column: 1 / -1; }
  .g-quote { grid-column: 1 / -1; grid-row: auto; padding: 20px 0; }
  .g { border-radius: 16px; }
}

/* the test gallery's photos open full screen (main.js, "lightbox") */
.g { cursor: zoom-in; }
.g:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }
.lightbox { position: fixed; inset: 0; z-index: 100; display: grid; place-items: center; background: rgba(12, 12, 12, 0.92);
  opacity: 0; transition: opacity 0.35s ease; cursor: zoom-out; touch-action: pan-y; }
.lightbox[hidden] { display: none; }
.lightbox.is-open { opacity: 1; }
.lightbox img { max-width: min(calc(100vw - 200px), 1600px); max-height: 86vh; width: auto; height: auto; border-radius: 14px; box-shadow: 0 30px 80px -30px rgba(0,0,0,0.6);
  transform: scale(0.94); transition: transform 0.45s cubic-bezier(.2,.7,.2,1), opacity 0.25s ease; cursor: default; }
.lightbox.is-open img { transform: scale(1); }
.lightbox img.is-swapping { opacity: 0; }
.lb-btn { position: absolute; width: 52px; height: 52px; border-radius: 50%; border: 1px solid rgba(255,255,255,0.35); background: rgba(255,255,255,0.06);
  display: grid; place-items: center; cursor: pointer; transition: background 0.2s ease, border-color 0.2s ease; }
.lb-btn:hover { background: rgba(255,255,255,0.16); border-color: rgba(255,255,255,0.6); }
.lb-btn svg { width: 22px; height: 22px; fill: none; stroke: #fff; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.lb-close { top: 20px; right: 20px; }
.lb-prev { left: 20px; top: 50%; translate: 0 -50%; }
.lb-next { right: 20px; top: 50%; translate: 0 -50%; }
.lb-count { position: absolute; bottom: 22px; left: 50%; translate: -50% 0; font: 400 11px/1 var(--mono); letter-spacing: 0.16em; color: rgba(255,255,255,0.7); }
@media (max-width: 860px) {
  .lb-prev, .lb-next { top: auto; bottom: 14px; translate: none; width: 46px; height: 46px; }
  .lb-close { top: 14px; right: 14px; width: 46px; height: 46px; }
  .lb-count { bottom: 30px; }
  .lightbox img { border-radius: 10px; max-width: 94vw; max-height: 76vh; }
}

/* ---------- where it began: Zeitz (2026-10-29) ---------- */
.zeitz { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(32px, 6vw, 96px); align-items: center; }
.zeitz-copy { display: grid; gap: 28px; }
.rzz-link { display: inline-flex; align-items: center; gap: 22px; justify-self: start; color: var(--ink); font: 400 15px/1 var(--body); text-decoration: underline; text-underline-offset: 4px; }
.rzz-logo { display: block; height: 40px; width: auto; }
.zeitz-map { margin: 0; position: relative; }
.zeitz-map img { display: block; width: 100%; height: auto; aspect-ratio: 1; -webkit-mask-image: radial-gradient(closest-side, #000 62%, transparent 100%); mask-image: radial-gradient(closest-side, #000 62%, transparent 100%); }
/* the Europe locator (img/europe-locator.svg): drawn in the map's own 1000x1000 frame, laid over it unmasked */
.zeitz-map img.zeitz-europe { position: absolute; inset: 0; -webkit-mask-image: none; mask-image: none; pointer-events: none; }
.zeitz-map figcaption { position: absolute; left: 0; bottom: 4%; font: 400 11px/1 var(--mono); letter-spacing: 0.16em; text-transform: uppercase; color: var(--muted); }
@media (max-width: 860px) {
  .zeitz { grid-template-columns: 1fr; gap: 28px; }
  .zeitz-map { max-width: 460px; }
}

.neb { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(32px, 6vw, 96px); align-items: start; }
.neb h2 { font-size: clamp(40px, 5.4vw, 72px); line-height: 1.04; }
.neb blockquote { margin: 0; display: grid; gap: 18px; color: var(--grey); font-size: 18px; }
.neb blockquote p:first-child { color: var(--ink); }
/* one statement since the text was cut (2026-10-29): larger, and level with the headline beside it */
@media (min-width: 861px) { .neb { align-items: center; } .neb blockquote { font-size: clamp(20px, 1.7vw, 24px); line-height: 1.45; max-width: 24em; } }
.neb-logo { display: block; height: 38px; width: auto; }
.neb-link { margin-top: 44px; }
/* the NEB link sits under the statement on the right since 2026-11-02 (it was under the headline) */
.neb-side { display: grid; justify-items: start; }
.more { display: none; justify-self: start; background: none; border: 0; padding: 0; font: 400 15px/1 var(--body); color: var(--ink); text-decoration: underline; text-underline-offset: 4px; cursor: pointer; }
@media (max-width: 860px) {
  .neb { grid-template-columns: 1fr; gap: 28px; }
  .neb blockquote { font-size: 16px; }
  .neb blockquote:not(.is-open) p:nth-child(n+2) { display: none; }
  .neb blockquote:not(.is-open) .more { display: block; }
  .neb-link { margin-top: 28px; }
}

/* ---------- take part ---------- */

.take { display: grid; grid-template-columns: 1.35fr 0.65fr; gap: clamp(48px, 8vw, 120px); align-items: center; }
.take-copy { display: grid; gap: 24px; justify-items: start; }
.take-copy .rule { width: 100%; }
.take small { color: var(--muted); font-size: 14px; }
.qr-card.qr-card--big {
  flex-direction: column;
  align-items: center !important;
  justify-self: end;
  gap: 14px;
  padding: 36px 40px 32px;
  border-radius: 32px;
  text-align: center;
}
.qr-card--big .qr.qr { width: 176px; height: 176px; margin-bottom: 10px; }
.qr-card--big strong { font: 300 24px/1.2 var(--display); }
.qr-card--big span { color: var(--grey); font-size: 14px; line-height: 1.4; }
.qr-card--big strong + span { margin-top: -4px; }
.qr-card--big span + span { margin-top: -12px; }
@media (max-width: 860px) {
  .take { grid-template-columns: 1fr; }
}

/* ---------- partners ---------- */

.partners { display: grid; gap: clamp(88px, 10vw, 136px); justify-items: center; }
.partners .rule { width: 100%; }
/* partner and funding logos share one 3-column grid, so their columns line up */
.logo-grid {
  --logo-h: clamp(28px, 4.9vw, 62px);
  width: 100%; max-width: 960px;
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(48px, 6vw, 88px) clamp(16px, 5vw, 72px);
  align-items: center; justify-items: center;
}
.logo-grid img { height: var(--logo-h); width: auto; max-width: 100%; object-fit: contain; }
.logo-grid img.logo--tall { height: calc(var(--logo-h) * 1.6); }
.paper {
  width: 100%;
  display: flex; flex-wrap: wrap; gap: 16px 32px; align-items: center; justify-content: space-between;
}
.paper p { color: var(--grey); font-size: 15px; max-width: 46em; }
.paper strong { font-weight: 400; color: var(--ink); }

/* ---------- footer ---------- */

.foot { padding: 40px 0 48px; }
.foot .wrap { display: flex; flex-wrap: wrap; gap: 20px 32px; align-items: center; justify-content: space-between; }
.foot .brand .name { font-size: 18px; }
.foot nav { display: flex; flex-wrap: wrap; gap: 8px 24px; }
.foot a { color: var(--grey); text-decoration: none; font-size: 14px; }
.foot a:hover { color: var(--ink); }
.foot .logos { display: flex; gap: 20px; align-items: center; }
.foot .logos img { height: 34px; width: auto; }
/* OpenStreetMap credit for the map in the hero and Find media (ODbL): required, kept tiny */
.foot a.credit { flex-basis: 100%; font-size: 10px; opacity: 0.6; }

@media (max-width: 520px) {
  .sec { padding: 112px 0; }
  .take .ctas { display: grid; grid-template-columns: 1fr; width: 100%; }
  .paper .btn { width: 100%; }
  .foot .wrap { flex-direction: column; align-items: flex-start; gap: 24px; }
}

/* contact in the header corner: words on wide screens, an envelope on phones */
.btn.contact { gap: 8px; }
.btn.contact .env { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.3; stroke-linejoin: round; display: none; }
@media (max-width: 520px) {
  .btn.contact { width: 40px; padding: 0; }
  .btn.contact .env { display: block; }
}

/* availability per platform */
.platforms { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.platforms li { display: flex; align-items: center; gap: 12px; font-size: 16px; }
.platforms strong { font-weight: 400; min-width: 76px; }
.platforms span:last-child { color: var(--grey); }
.pf-dot { width: 10px; height: 10px; border-radius: 50%; border: 1.5px solid var(--muted); flex: none; }
.pf-dot.is-live { background: var(--dwelling); border-color: var(--dwelling); }
.ios-note { color: var(--grey); font-size: 15px; }

/* ---------- desktop vs phone: no "open the app" on a computer, a QR code instead ---------- */
.desk-only { display: none !important; }
@media (hover: hover) and (pointer: fine) and (min-width: 861px) {
  .desk-only { display: flex !important; }
  .touch-only { display: none !important; }
}
.qr-card {
  align-items: center;
  gap: 22px;
  padding: 14px 26px 14px 14px;
  border: 1px solid var(--hair);
  border-radius: 24px;
  background: var(--white);
  justify-self: start;
  text-align: left;
}
.qr { width: 112px; height: 112px; flex: none; }
.qr svg { width: 100%; height: 100%; display: block; }
.qr-text { display: grid; gap: 6px; }
.qr-text strong { font: 300 22px/1.2 var(--display); }
.qr-text span { color: var(--grey); font-size: 14px; }
.textlink { color: var(--grey); font-size: 14px; text-underline-offset: 4px; }
.textlink:hover { color: var(--ink); }

/* ---------- reveal ---------- */

.rv { opacity: 0; transform: translateY(16px); transition: opacity 0.7s ease, transform 0.7s ease; }
.rv.is-in { opacity: 1; transform: none; }
.no-js .rv { opacity: 1; transform: none; }

/* phones: the header keeps the language switch and contact (as an envelope); no app button while the app is not public */

/* the header's app button steps aside while the try section's own button is on screen */
.top.at-try .head-app { display: none !important; }

/* ---------- mobile: one pattern everywhere ----------
   label, headline and short text first (left-aligned), then the picture below it,
   with generous space between blocks. */
.step-media { display: none; }
@media (max-width: 860px) {
  .sec { padding: 136px 0; }
  .hero { padding: 112px 0 120px; }

  .take-copy { justify-items: start; text-align: left; }
  .take-copy .rule, .partners .rule { width: 100%; }

  .hero .wrap { gap: 64px; }
  .portal-what { gap: 64px; }
  .sec-head { margin-bottom: 96px; }

  .journey { grid-template-columns: 1fr; gap: 0; }
  .journey-phone { display: none; }
  .steps { display: grid; gap: 136px; }
  .step { min-height: 0; padding: 0; gap: 18px; }
  .step h3 { font-size: 32px; }
  .step-media { display: flex; flex-direction: column; align-items: center; margin-top: 44px; }
  .step-media .phone { width: min(280px, 72vw); }

  .neb { gap: 72px; }
  .neb h2 { margin-top: 24px !important; }

  .take { gap: 0; }
  .platforms { margin-top: 8px; }
  .partners { gap: 104px; }
  .paper { flex-direction: column; align-items: flex-start; }
}

/* the journey opens straight on its first step (no section title): less room above it on desktop */
@media (min-width: 861px) { #journey { padding-top: clamp(24px, 3vw, 48px); } }


/* ---------- hero: what NEB Network is, and who makes it (2026-10-28, replaced the QR card) ---------- */
.hero-about { display: grid; gap: 14px; max-width: 36em; }
.hero-claim { font: 300 clamp(22px, 2.1vw, 28px)/1.3 var(--display); color: var(--ink); margin: 0; }
.hero-about .lead { margin: 0; }
.hero-by { display: grid; gap: 14px; padding-top: 22px; border-top: 1px solid var(--hair); max-width: 36em; }
.hero-by > span { color: var(--muted); font-size: 13px; letter-spacing: 0.02em; }
.hero-by .logos { display: flex; flex-wrap: wrap; gap: 18px 32px; align-items: center; }
.hero-by .logos img { height: 40px; width: auto; display: block; }
@media (max-width: 520px) { .hero-by .logos img { height: 32px; } }

/* ---------- get the app: store cards instead of the QR code ---------- */
.stores { display: grid; gap: 14px; justify-self: end; width: min(320px, 100%); }
.store { display: flex; align-items: center; gap: 16px; padding: 18px 22px; border: 1px solid var(--hair); border-radius: 22px; background: var(--white); }
.store svg { width: 30px; height: 30px; flex: none; fill: none; stroke: var(--ink); stroke-width: 1.4; stroke-linecap: round; }
.store span { display: grid; gap: 2px; }
.store small { color: var(--grey); font-size: 13px; }
.store strong { font: 300 22px/1.2 var(--display); }
@media (max-width: 860px) { .stores { justify-self: start; margin-top: 16px; } }

/* ---------- MOBILE, ONE SYSTEM (2026-10-29, "half baked … inconsistent … amateur") ----------
   Everything below 860px follows the same few numbers, and this block (last in the file) wins over the
   per-section mobile rules above:
     space   section 60 (was 88) · between blocks in a section 40 · label→headline 20 · headline→text 16
     type    h1 40 · every h2 / step h3 30 · lead 17 · quotes 21
     logos   one height for every inline logo (36), partner / funding logos in two readable columns
     phones  one size (the 3:4 tablet, as wide as the text, up to 400), every button full width */
@media (max-width: 860px) {
  :root { --m-sec: 60px; --m-block: 40px; --m-logo: 36px; --m-phone: min(400px, calc(100vw - 2 * var(--gutter))); }

  /* space */
  .sec, .sec.sec { padding: var(--m-sec) 0; }
  .hero { padding: 96px 0 var(--m-sec); }
  .hero .wrap, .portal-what, .zeitz, .neb { gap: var(--m-block); }
  .sec-head { margin-bottom: var(--m-block); gap: 16px; }
  .sec-head .rule, .zeitz-copy .rule, .take-copy .rule { margin-bottom: 4px; }
  .hero-copy, .portal-what .copy, .zeitz-copy, .take-copy { gap: 16px; }
  .steps { gap: 72px; }
  .step { gap: 16px; }
  .step-media { margin-top: 24px; }
  .neb h2 { margin-top: 20px !important; }
  .neb-link { margin-top: 24px; }
  .neb { gap: 32px; }
  .partners { gap: var(--m-block); }
  .take { gap: 0; }
  .stores { margin-top: 24px; }

  /* type */
  h1 { font-size: 36px; }
  h2, .neb h2, .step h3 { font-size: 30px; line-height: 1.1; }
  .lead { font-size: 17px; }
  .hero-claim { font-size: 21px; }
  .g-quote p { font-size: 21px; }
  .neb blockquote { font-size: 17px; }

  /* logos */
  .hero-by .logos img, .hero-by .logos img.logo, .rzz-logo, .neb-logo { height: var(--m-logo); }
  .hero-by .logos { gap: 16px 28px; }
  .rzz-link { gap: 18px; }
  .foot .logos img { height: 32px; }
  .logo-grid { --logo-h: 40px; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 40px 24px; }
  .logo-grid img { max-width: 150px; }
  .logo-grid img.logo--tall { height: 60px; }
  .logo-grid > :last-child:nth-child(odd) { grid-column: 1 / -1; }

  /* phones and buttons */
  .hero-phone .phone, .step-media .phone { width: var(--m-phone); }
  .stores { width: 100%; justify-self: stretch; }
  .paper .btn { width: 100%; }

  /* the gallery and the map */
  .g-quote { padding: 16px 0; }
  .zeitz-map { max-width: none; }
}

/* ---------- legal pages (impressum/, datenschutz/) ---------- */

.legal { padding: 140px 0 96px; }
.legal article { max-width: 680px; }
.legal h1 { font-size: clamp(36px, 4vw, 52px); margin-bottom: 32px; }
.legal h2 { font: 400 13px/1.3 var(--mono); letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted); margin: 40px 0 12px; }
.legal p, .legal li { font-size: 16px; line-height: 1.6; color: var(--ink); margin: 0 0 12px; }
.legal ul { padding-left: 20px; margin: 0; }
.legal a { color: inherit; text-decoration: underline; text-underline-offset: 3px; }
.legal .legal-note { color: var(--muted); font-size: 14px; }
.legal-lang-note { max-width: 680px; margin: 0 0 32px; padding: 12px 16px; border: 1px solid var(--hair); border-radius: 10px; font-size: 14px; line-height: 1.5; color: var(--grey); }
.foot nav a[aria-current="page"] { color: var(--ink); }
@media (max-width: 860px) { .legal { padding: 112px 0 72px; } }

/* get the app: only words while nothing is public yet (no store buttons) */
.take--solo { grid-template-columns: 1fr; }
.take--solo .take-copy { max-width: 760px; }

/* out in the field, smaller (2026-10-30): the wall was over a screen tall and outweighed the rest of the page;
   now photos + quote fit in about one screen */
.gallery { grid-auto-rows: clamp(22px, 2.3vw, 33px); gap: clamp(8px, 1vw, 12px); }
.g { border-radius: 16px; }
.g-quote p { font-size: clamp(18px, 1.6vw, 22px); }
@media (max-width: 860px) { .gallery { grid-auto-rows: 30vw; } .g { border-radius: 12px; } }

/* get the app (2026-10-30): a slim band with one real action */
#try.sec { padding: clamp(56px, 7vw, 96px) 0; }
.take-ask { display: flex; flex-wrap: wrap; align-items: center; gap: 12px 16px; margin: 4px 0 0; color: var(--ink); font-size: 16px; }
/* partner logos in one soft grey, their own colour on hover; the funding logos keep their colours */
.logo-grid--partners img { filter: grayscale(1); opacity: 0.6; transition: filter 0.3s ease, opacity 0.3s ease; }
.logo-grid--partners img:hover { filter: none; opacity: 1; }

/* ---------- the clip's backlight (2026-11-02) ----------
   Like a TV with ambient backlight: the clip's own colours bleed out round its edges onto the page. main.js puts a
   canvas behind every clip: a small copy (48 x 64 px) of the clip's middle (the app fades its own edges to white, so
   the middle carries the colour) in the centre of an empty 80 x 100 canvas, and blurs it there, so the light spreads
   into the empty margin and fades the way real light does. Placed so the copy sits exactly behind the clip.
   No CSS blur filter: Safari drew that with hard-edged boxes where the light overlaps the clip and its note. */
.phone > .bleed {
  position: absolute; z-index: -1; pointer-events: none;
  left: -33.333%; width: 166.667%;  /* 16 px margin either side of the 48 px copy */
  top: -28.125%; height: 156.25%;   /* 18 px above and below the 64 px copy */
}
.phone > .bleed--css { filter: blur(48px); } /* only when main.js cannot blur it (the page opened as a file) */
/* the light reaches past the screen's edge on phones: clip it there, or the page scrolls sideways
   (clip, not hidden: hidden would make main a scroll box and stop the journey's clip from sticking) */
main { overflow-x: clip; }

/* ---------- spacing, ONE SYSTEM on the computer too (2026-11-02, "small inconsistent spacing") ----------
   Every section's text column takes the same three steps, as the phone block above meant them to:
     label → headline 24 · headline → text 24 · text → a link, button or divided note 32
   (it was 20 to 28 depending on the section, and the NEB link 44). Phones: 20 · 16 · 24. */
@media (min-width: 861px) {
  .hero-copy, .portal-what .copy, .zeitz-copy, .take-copy, .sec-head, .step { gap: 24px; }
  .neb h2 { margin-top: 24px; }
  .hero-by, .voice-note, .zeitz-copy .rzz-link, .take-ask { margin-top: 8px; } /* 24 + 8 */
  .neb-link { margin-top: 32px; }
  /* the NEB statement starts level with the headline beside it (centred, the link under it lifted it) */
  .neb { align-items: start; }
  .neb-side { padding-top: 35px; } /* the label's 11 px line + 24 */
}
@media (max-width: 860px) {
  .hero-copy .rule, .portal-what .copy .rule, .step .rule { margin-bottom: 4px; } /* 16 + 4, like the others */
  .hero-by, .voice-note, .zeitz-copy .rzz-link, .take-ask { margin-top: 8px; } /* 16 + 8 */
}

/* ---------- what is a portal: the process slideshow instead of the drawing (2026-11-03, merged from website-slideshow 2) ----------
   One place over time, 9 pictures. The previews, the pause and the full-screen button sit inside the picture along
   its bottom edge, on a soft shade; under the picture the phase (left) and the note (right). Picture left, text right. */
@media (min-width: 861px) {
  .portal-what { grid-template-columns: minmax(0, 1.2fr) minmax(0, 0.8fr); gap: clamp(32px, 5vw, 72px); }
  .portal-what .slideshow { order: -1; }
}
.slideshow { display: grid; gap: 12px; min-width: 0; }
.frame-stage { position: relative; }
.slideshow .frame { position: relative; aspect-ratio: 4 / 3; border-radius: 22px; overflow: hidden; background: #f4f4f2; isolation: isolate; box-shadow: 0 24px 60px -28px rgba(0, 0, 0, 0.35); cursor: zoom-in; }
.slideshow .frame video { position: absolute; inset: -1px; width: calc(100% + 2px); max-width: none; height: calc(100% + 2px); object-fit: cover; }
.slideshow .frame .frame-wide { opacity: 0; transition: opacity 0.6s ease; pointer-events: none; } /* the 16:9 clip: only full screen (main.js) */
.slideshow .frame.is-wide .frame-wide { opacity: 1; }
/* the shade under the previews, so they read on any picture */
.slideshow .frame::after { content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 32%; background: linear-gradient(to top, rgba(0, 0, 0, 0.36), rgba(0, 0, 0, 0)); pointer-events: none; }
.frame-thumbs { position: absolute; left: 16px; right: 16px; bottom: 16px; z-index: 1; display: grid; grid-template-columns: auto repeat(9, minmax(0, 44px)) auto; justify-content: center; gap: 5px; align-items: stretch; }
.frame-thumbs button { padding: 0; border: 0; border-radius: 5px; overflow: hidden; background: none; cursor: pointer; opacity: 0.6; box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.4); transition: opacity 0.3s, box-shadow 0.3s; }
.frame-thumbs button:hover { opacity: 0.9; }
.frame-thumbs button.is-on { opacity: 1; box-shadow: 0 0 0 2px #fff; }
.frame-thumbs button:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
.frame-thumbs img { display: block; width: 100%; height: auto; aspect-ratio: 4 / 3; object-fit: cover; }
/* pause (left) and full screen (right): line icons as small as the previews, white on the picture */
.frame-thumbs .frame-btn { display: grid; place-items: center; width: 28px; opacity: 1; border: 1px solid rgba(255, 255, 255, 0.6); border-radius: 5px; color: #fff; background: rgba(0, 0, 0, 0.2); box-shadow: none; }
.frame-thumbs .frame-btn:hover { background: rgba(0, 0, 0, 0.4); opacity: 1; }
.frame-btn svg { width: 11px; height: 11px; fill: none; stroke: currentColor; stroke-width: 1.4; stroke-linecap: round; stroke-linejoin: round; }
.frame-btn .i-play, .frame-btn .i-shrink { display: none; }
.frame-pause.is-paused .i-pause, .frame-full.is-full .i-grow { display: none; }
.frame-pause.is-paused .i-play, .frame-full.is-full .i-shrink { display: inline; }
.frame-cap { display: flex; justify-content: space-between; align-items: baseline; gap: 16px; }
.frame-phase { display: inline-flex; align-items: center; gap: 7px; font-size: 13px; color: var(--ink); white-space: nowrap; }
.frame-phase i { width: 8px; height: 8px; border-radius: 50%; background: var(--c, var(--muted)); transition: background 0.3s; }
.frame-phase[data-phase='dreaming'] { --c: var(--dreaming); }
.frame-phase[data-phase='decision'] { --c: var(--decision); }
.frame-phase[data-phase='dwelling'] { --c: var(--dwelling); }
.slideshow .phone-note { margin: 0; max-width: none; text-align: right; }
@media (max-width: 860px) {
  .slideshow .frame { border-radius: 16px; }
  .frame-thumbs { left: 10px; right: 10px; bottom: 10px; gap: 3px; }
  .frame-thumbs button { border-radius: 3px; }
  .frame-thumbs .frame-btn { width: 22px; border-radius: 3px; }
}

/* ---------- full screen (2026-11-03): a click on any clip, or the slideshow's button, opens it full screen ----------
   The slideshow goes full screen with its previews and buttons, the picture as large as the screen allows on black.
   Any other clip goes on its own, whole (not cropped to the screen's shape). A second click or Esc closes it.
   (:is() skips the prefix a browser does not know, instead of dropping the rule.) */
.frame-stage:is(:fullscreen, :-webkit-full-screen) { display: flex; align-items: center; justify-content: center; background: #000; }
/* full screen the frame is 16:9: the 4:3 clip shows centred (contain) until the uncropped 16:9 clip fades in over it */
.frame-stage:is(:fullscreen, :-webkit-full-screen) .frame { aspect-ratio: 16 / 9; width: min(100vw, 177.778vh); background: #000; border-radius: 0; box-shadow: none; cursor: zoom-out; }
.frame-stage:is(:fullscreen, :-webkit-full-screen) .frame video { object-fit: contain; }
.frame-stage:is(:fullscreen, :-webkit-full-screen) .frame-thumbs { bottom: 24px; grid-template-columns: auto repeat(9, minmax(0, 72px)) auto; gap: 8px; }
.frame-stage:is(:fullscreen, :-webkit-full-screen) .frame-btn { width: 40px; }
.frame-stage:is(:fullscreen, :-webkit-full-screen) .frame-btn svg { width: 14px; height: 14px; }
video:is(:fullscreen, :-webkit-full-screen) { position: fixed !important; inset: 0 !important; width: 100% !important; height: 100% !important; max-width: none !important; object-fit: contain !important; background: #000; cursor: zoom-out; }
.phone-screen:has(> video) { cursor: zoom-in; }
.phone-screen:has(> img.is-on) { cursor: auto; } /* the journey's first shot is a still map, not a clip */
.portal-what .copy p { text-wrap: pretty; } /* no word alone on the last line ("take / shape.") */

/* ---------- phones, round 2 (2026-11-03: "how can we improve the mobile version?") ----------
   The page opens with its clip in view, every tap target is at least 44 px, small print is readable,
   and the slideshow is driven by a swipe and a control bar under the picture instead of nine tiny previews. */
@media (max-width: 860px) {
  /* the hero: the clip right under the words; the "developed in" line and the logos come after it */
  .hero .wrap { gap: 0; }
  .hero-copy { display: contents; }
  .hero-copy > .rule { order: 1; margin-bottom: 20px; }
  .hero-copy > h1 { order: 2; margin-bottom: 16px; }
  .hero-about { order: 3; }
  .hero-phone { order: 4; margin-top: var(--m-block); }
  .hero-by { order: 5; margin-top: var(--m-block); }

  /* small print a little larger, the slideshow's phase and note on their own lines */
  .phone-note { font-size: 12px; }
  .brand small { font-size: 10px; }
  .frame-cap { flex-direction: column; align-items: flex-start; gap: 4px; }
  .slideshow .phone-note { text-align: left; }

  /* 44 px to tap: the footer links, the logos, the "visit" links, the language list */
  .foot nav { gap: 0 24px; }
  .foot nav a, .foot a.credit { display: inline-flex; align-items: center; min-height: 44px; }
  .foot .logos a { display: block; padding: 6px 0; }
  .rzz-link { min-height: 44px; }
  .lang-list button { padding-top: 13px; padding-bottom: 13px; }
  .brand { min-height: 44px; }
  .hero-by .logos a { display: block; padding: 4px 0; }
  .btn--sm, .lang-btn { height: 44px; }
}
@media (max-width: 520px) { .btn.contact { width: 44px; } } /* the envelope alone, round */
@media (max-width: 600px) {
  /* the slideshow: a swipe on the picture, and under it pause · nine dots · full screen (the previews were 29 x 21 px) */
  .slideshow .frame { touch-action: pan-y pinch-zoom; }
  .slideshow .frame::after { display: none; }
  .frame-thumbs { position: static; margin-top: 6px; grid-template-columns: 44px repeat(9, minmax(0, 1fr)) 44px; gap: 0; align-items: center; justify-content: stretch; }
  .frame-thumbs button { height: 44px; display: grid; place-items: center; border-radius: 0; opacity: 1; box-shadow: none; overflow: visible; }
  .frame-thumbs button.is-on { box-shadow: none; }
  .frame-thumbs [data-slide] img { display: none; }
  .frame-thumbs [data-slide]::before { content: ''; width: 7px; height: 7px; border-radius: 4px; background: rgba(17, 17, 17, 0.22); transition: width 0.3s, background-color 0.3s; }
  .frame-thumbs [data-slide].is-on::before { width: 22px; background: var(--c, var(--ink)); }
  .frame-thumbs [data-phase='dreaming'] { --c: var(--dreaming); }
  .frame-thumbs [data-phase='decision'] { --c: var(--decision); }
  .frame-thumbs [data-phase='dwelling'] { --c: var(--dwelling); }
  .frame-thumbs .frame-btn, .frame-thumbs .frame-btn:hover { width: 44px; border: 0; border-radius: 50%; color: var(--ink); background: none; }
  .frame-thumbs .frame-btn:active { background: var(--pressed); }
  .frame-thumbs .frame-btn svg { width: 15px; height: 15px; }
  .frame-thumbs button:focus-visible { outline: 2px solid var(--ink); outline-offset: -4px; }
  /* full screen on a phone (Android; an iPhone uses its own player): the same bar, white, along the bottom of the screen */
  .frame-stage:is(:fullscreen, :-webkit-full-screen) .frame-thumbs { position: absolute; left: 8px; right: 8px; bottom: max(12px, env(safe-area-inset-bottom)); grid-template-columns: 44px repeat(9, minmax(0, 1fr)) 44px; gap: 0; }
  .frame-stage:is(:fullscreen, :-webkit-full-screen) .frame-btn { width: 44px; color: #fff; }
  .frame-stage:is(:fullscreen, :-webkit-full-screen) .frame-thumbs [data-slide]::before { background: rgba(255, 255, 255, 0.35); }
  .frame-stage:is(:fullscreen, :-webkit-full-screen) .frame-thumbs [data-slide].is-on::before { background: var(--c, #fff); }
  .frame-stage:is(:fullscreen, :-webkit-full-screen) .frame-thumbs button:focus-visible { outline-color: #fff; }
}

/* ---------- the Dream Tree in the dreaming step (2026-11-03): how dreams stack and branch ----------
   The app keeps dreams like git keeps code: each dream is a step on top of the one it started from (the place
   itself at the root), anyone can branch from any dream, nothing is overwritten. Drawn like the app's tree:
   the place at the bottom, the newest dreams at the top. One SVG for lanes and nodes, the words in an
   ordered list beside it on the same 28 px rows (condensed 2026-11-03: no box, no title, one sentence). */
.dream-tree { display: grid; gap: 8px; margin-top: 2px; }
.dt-text { font-size: 14px; line-height: 1.5; color: var(--grey); text-wrap: pretty; max-width: 34em; }
.dt-graph { margin: 0; display: grid; grid-template-columns: 36px minmax(0, 1fr); align-items: start; }
.dt-lines { display: block; overflow: visible; }
.dt-edge { fill: none; stroke: var(--dreaming); stroke-width: 1.5; stroke-linecap: round; opacity: 0.55; }
.dt-edge--branch { opacity: 0.35; }
.dt-node { fill: var(--dreaming); }
.dt-node--new { stroke: rgba(48, 164, 227, 0.25); stroke-width: 5; paint-order: stroke; }
.dt-root { fill: var(--white); stroke: var(--grey); stroke-width: 1.25; }
.dt-rows { list-style: none; margin: 0; padding: 0; display: grid; grid-auto-rows: 28px; }
.dt-rows li { display: flex; align-items: center; min-width: 0; font-size: 14px; line-height: 1.2; color: var(--ink); }
.dt-rows li span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.dt-rows .dt-branch { color: var(--grey); }
.dt-rows .dt-root-label { font: 400 10px/1.2 var(--mono); letter-spacing: 0.14em; text-transform: uppercase; color: var(--muted); }

/* the EU flag at the start of the team's line "We are a team from Europe…" (moved from the hero, 2026-11-03).
   The official construction (3:2, twelve stars on a circle, reflex blue and yellow), drawn small */
.eu-flag { display: inline-block; width: 21px; height: 14px; margin-right: 10px; vertical-align: -1px; border-radius: 1.5px; box-shadow: 0 0 0 0.5px rgba(0, 0, 0, 0.12); }

/* ---------- the app's name in the hero (2026-11-03: "we have the name twice"; "bigger in the intro, then into the header") ----------
   The hero's "NEB NETWORK APP" label is gone. Its place is an empty slot; main.js draws the header's own logo and
   name over it, scaled up (1.4x, 1.3x on phones; 2x was louder than the headline), in grey, and lets it ride up with the page into the header. The slot's height
   is set by main.js; these are only the sizes before the script runs. */
.top .brand { transform-origin: 0 0; }
.top .brand .name { color: color-mix(in srgb, var(--ink), var(--grey) calc(var(--big, 0) * 100%)); } /* quieter while large in the hero */
.hero-brand-slot { height: 45px; }
.no-js .hero-brand-slot { display: none; }
@media (prefers-reduced-motion: reduce) { .hero-brand-slot { display: none; } }
@media (max-width: 860px) {
  .hero-brand-slot { height: 57px; order: 1; margin-bottom: 20px; }
}
