/* ---------------------------------------------------------------
   Bruno Weber Lab — Prototype
   Design source: Figma "Bruno Weber Lab – Screendesign"
   Design width: 1500px. Above that, the page scales uniformly.
   --------------------------------------------------------------- */

/* Original type is GT Planar Trial (Grilli Type).
   Drop the trial webfonts into assets/fonts/ and they take over
   automatically; until then Onest renders as the stand-in. */
@font-face {
  font-family: 'GT Planar Trial';
  src: url('assets/fonts/GT-Planar-Trial-Light.woff2') format('woff2');
  font-weight: 300;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'GT Planar Trial';
  src: url('assets/fonts/GT-Planar-Trial-Regular.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'GT Planar Trial';
  src: url('assets/fonts/GT-Planar-Trial-Medium.woff2') format('woff2');
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}

html {
  font-size: max(16px, calc(100vw / 93.75));
}

:root {
  --u: 0.0625rem;            /* 1 design px */
  --bg: #f5f5f5;
  --yellow: #fce68a;
  --font: 'GT Planar Trial', system-ui, -apple-system, sans-serif;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: #000;
  font-family: var(--font);
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
}

.page {
  position: relative;
  width: 100%;
  overflow: hidden;
}

/* Everything below the hero keeps its original design coordinates; the
   negative margin re-anchors the origin to the hero image's bottom edge,
   so the 124px gap from the design is preserved at any viewport height. */
.rest {
  position: relative;
  height: calc(6928 * var(--u));
  margin-top: calc(-906 * var(--u));
  /* That negative margin pulls this container up over the whole hero,
     including the header. Its own box must therefore not catch clicks —
     only its (absolutely positioned) contents may. */
  pointer-events: none;
}
.rest * { pointer-events: auto; }

a { color: inherit; text-decoration: none; }

/* --- absolute placement helpers ------------------------------- */

.abs {
  position: absolute;
  left: calc(var(--x) * var(--u));
  top: calc(var(--y) * var(--u));
}
.abs[style*="--w"] { width: calc(var(--w) * var(--u)); }
.abs[style*="--h"] { height: calc(var(--h) * var(--u)); }

.clip { overflow: hidden; }
.clip > img {
  position: absolute;
  max-width: none;
  object-fit: cover;
  transform: translate3d(0, var(--shift, 0px), 0) scaleX(var(--sx, 1));
  left: calc(var(--ix, 0) * var(--u));
  top: calc(var(--iy, 0) * var(--u));
  width: calc(var(--iw) * var(--u));
  height: calc(var(--ih) * var(--u));
}
.clip.flip > img { --sx: -1; }

/* Avatars are a circular window onto a much larger portrait; the crop is
   expressed in percent so it stays correct at any rendered size. */
.av {
  position: relative;
  overflow: hidden;
  border-radius: 50%;
  flex: none;
}
.av > img {
  position: absolute;
  max-width: none;
  object-fit: cover;
  left: calc(var(--px) * 1%);
  top: calc(var(--py) * 1%);
  width: calc(var(--pw) * 1%);
  height: calc(var(--ph) * 1%);
}
.av.ring { box-shadow: inset 0 0 0 calc(1.2 * var(--u)) #fff; }

.img-fill {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

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

.wordmark,
.nav-item {
  font-size: calc(18 * var(--u));
  line-height: calc(25 / 18);
  font-weight: 400;
}

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

.hero-section {
  position: relative;
  height: 100vh;
  min-height: calc(620 * var(--u));
}

.hero {
  position: absolute;
  left: calc(40 * var(--u));
  right: calc(40 * var(--u));
  top: calc(72 * var(--u));
  bottom: calc(40 * var(--u));
  overflow: hidden;
}
.hero::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(to bottom, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.8));
}

.hero-title {
  position: absolute;
  left: calc(80 * var(--u));
  bottom: calc(72 * var(--u));
  width: calc(825 * var(--u));
  color: #fff;
  font-size: calc(80 * var(--u));
  line-height: calc(92 / 80);
  font-weight: 300;
  letter-spacing: calc(-2.4 * var(--u));
  margin: 0;
}

.hero-title .hl { display: block; }

.hero-card {
  position: absolute;
  right: calc(136 * var(--u));
  bottom: calc(110 * var(--u));
  display: flex;
  align-items: center;
  gap: calc(24 * var(--u));
  padding: 0 calc(24 * var(--u));
  background: rgba(255, 255, 255, 0.15);
  border: 0.5px solid rgba(255, 255, 255, 0.15);
  -webkit-backdrop-filter: blur(calc(20.5 * var(--u)));
  backdrop-filter: blur(calc(20.5 * var(--u)));
}
.hero-card-text {
  width: calc(328 * var(--u));
  padding: calc(16 * var(--u)) 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: calc(10 * var(--u));
}
.hero-tag {
  background: rgba(255, 255, 255, 0.07);
  border-radius: calc(4 * var(--u));
  padding: calc(1 * var(--u)) calc(6 * var(--u)) calc(3 * var(--u));
  color: #fff;
  font-size: calc(12 * var(--u));
  line-height: 1.3;
}
.hero-card-title {
  color: #fff;
  font-size: calc(16 * var(--u));
  line-height: 1.3;
  margin: 0;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.hero-card-btn {
  flex: none;
  width: calc(32 * var(--u));
  height: calc(32 * var(--u));
  background: rgba(255, 255, 255, 0.07);
  display: flex;
  align-items: center;
  justify-content: center;
}
.hero-card-btn svg {
  width: calc(14 * var(--u));
  height: calc(14 * var(--u));
}

/* --- section furniture ---------------------------------------- */

.eyebrow {
  font-size: calc(16 * var(--u));
  line-height: 1.4;
  color: rgba(0, 0, 0, 0.6);
}

.lead {
  font-size: calc(40 * var(--u));
  line-height: 1.3;
  font-weight: 400;
  letter-spacing: calc(-1.2 * var(--u));
  margin: 0;
}

.section-title {
  font-size: calc(32 * var(--u));
  line-height: calc(40 / 32);
  font-weight: 400;
  margin: 0;
}

.link {
  font-size: calc(16 * var(--u));
  line-height: 1.5;
  text-decoration: underline;
  text-underline-offset: calc(4 * var(--u));
}

.badge {
  width: calc(20 * var(--u));
  height: calc(20 * var(--u));
  border-radius: 50%;
  background: #fde68a;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: calc(9 * var(--u));
  line-height: 1.4;
  font-weight: 500;
}

/* --- publication card ----------------------------------------- */

/* The card scales as a unit through --c. It defaults to the design size;
   a page can shrink the whole card, type included, by redefining --c. */
.pcard {
  --c: var(--u);
  background: #fff;
  overflow: hidden;
  height: calc(501 * var(--c));
  padding: calc(32 * var(--c)) calc(24 * var(--c));
}
.abs.pcard[style*="--w"] { width: calc(var(--w) * var(--c)); }
.pcard-body {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: calc(24 * var(--c));
  width: calc(322 * var(--c));
}
.pcard-author {
  display: flex;
  align-items: center;
  height: calc(48 * var(--c));
  gap: calc(16 * var(--c));
}
.pcard-author .av {
  width: calc(48 * var(--c));
  height: calc(48 * var(--c));
}
.meta {
  font-size: calc(16 * var(--u));
  line-height: 1.4;
  color: rgba(0, 0, 0, 0.5);
  font-weight: 500;
}
.pcard .meta { font-size: calc(16 * var(--c)); }
.pcard-title {
  font-size: calc(24 * var(--c));
  line-height: 1.3;
  letter-spacing: calc(-0.2 * var(--c));
  font-weight: 400;
  margin: 0;
  width: 100%;
}
.pcard-foot {
  position: absolute;
  left: calc(24 * var(--c));
  top: calc(453 * var(--c));
  width: calc(322 * var(--c));
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.pcard-foot .meta { color: rgba(0, 0, 0, 0.6); }
.arrow {
  width: calc(24 * var(--u));
  height: calc(24 * var(--u));
}
.pcard .arrow {
  width: calc(24 * var(--c));
  height: calc(24 * var(--c));
}

/* cards that sit slightly wider in the design */
.pcard.wide { padding-left: calc(23.4 * var(--c)); }
.pcard.wide .pcard-foot { left: calc(23.4 * var(--c)); }

/* Publications page: cards render smaller than the Figma frame so the
   images stop dominating the scatter. */
.page[data-compact-cards] .pcard { --c: calc(var(--u) * 0.84); }

/* --- feature image blocks (What we're working on) ------------- */

.feature { overflow: hidden; }
.feature .feature-img { position: absolute; left: 0; width: 100%; max-width: none; }
.feature::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(to top, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.8));
}
.feature-text {
  position: absolute;
  left: calc(48 * var(--u));
  top: calc(64 * var(--u));
  z-index: 2;
}
.feature-title {
  font-size: calc(30 * var(--u));
  font-weight: 300;
  letter-spacing: calc(-0.9 * var(--u));
  color: #fff;
  margin: 0;
  white-space: nowrap;
}
.feature-copy {
  position: absolute;
  left: 0;
  top: calc(59 * var(--u));
  width: calc(634 * var(--u));
  margin: 0;
  font-size: calc(20 * var(--u));
  line-height: 1.4;
  letter-spacing: calc(-0.15 * var(--u));
  color: #fff;
}

/* --- news card ------------------------------------------------ */

.ncard {
  background: #fff;
  padding: calc(24 * var(--u)) calc(16 * var(--u));
  height: calc(214 * var(--u));
}
.ncard-author {
  display: flex;
  align-items: center;
  gap: calc(16 * var(--u));
  height: calc(32 * var(--u));
}
.ncard-author.tight { gap: calc(8 * var(--u)); }
.ncard-author .av {
  width: calc(32 * var(--u));
  height: calc(32 * var(--u));
}
.ncard-name {
  font-size: calc(14 * var(--u));
  line-height: 1.3;
  color: rgba(0, 0, 0, 0.6);
}
.ncard-title {
  margin: calc(16 * var(--u)) 0 0;
  font-size: calc(20 * var(--u));
  line-height: 1.3;
  font-weight: 400;
}
.ncard-foot {
  position: absolute;
  left: calc(16 * var(--u));
  top: calc(174 * var(--u));
  width: calc(421.33 * var(--u));
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.ncard-date {
  font-size: calc(14 * var(--u));
  line-height: 1.2;
  color: rgba(0, 0, 0, 0.6);
}

/* --- yellow institute block ----------------------------------- */

.institute { background: var(--yellow); }
.institute-title {
  font-size: calc(32 * var(--u));
  line-height: 1.3;
  font-weight: 400;
  margin: 0;
}
.body-copy {
  font-size: calc(20 * var(--u));
  line-height: 1.4;
  margin: 0;
}
.experts-card { background: #fff; }

/* --- publications page ---------------------------------------- */

.page-title {
  font-size: calc(48 * var(--u));
  line-height: calc(55 / 48);
  font-weight: 300;
  letter-spacing: calc(-1.44 * var(--u));
  margin: 0;
}

.filter {
  background: #fff;
  height: calc(40 * var(--u));
  display: flex;
  align-items: center;
  padding: 0 calc(16 * var(--u)) 0 calc(24 * var(--u));
  gap: calc(4 * var(--u));
  font-size: calc(16 * var(--u));
  line-height: calc(18 / 16);
}
.filter svg {
  width: calc(24 * var(--u));
  height: calc(24 * var(--u));
}


/* ---------------------------------------------------------------
   Motion — subtle, and fully disabled under prefers-reduced-motion
   (the `anim` class is only set by script.js when motion is allowed)
   --------------------------------------------------------------- */

.anim [data-reveal] {
  opacity: 0;
  transform: translateY(calc(20 * var(--u)));
  transition:
    opacity 0.7s cubic-bezier(0.22, 0.61, 0.36, 1),
    transform 0.7s cubic-bezier(0.22, 0.61, 0.36, 1);
  transition-delay: var(--d, 0ms);
  will-change: opacity, transform;
}
.anim [data-reveal].in {
  opacity: 1;
  transform: none;
}
.anim [data-reveal].in { will-change: auto; }

/* Image and card belong to one unit: they share a delay, and the image
   additionally travels a little to the right as it comes in. */
.anim .media[data-reveal] {
  transform: translateX(calc(-32 * var(--u)));
  transition-duration: 0.9s;
}
.anim .media[data-reveal].in { transform: none; }

/* hero intro — keyframes rather than a class swap, so the first frame
   always plays regardless of when the `anim` class lands */
@keyframes heroZoom {
  from { transform: scale(1.05); }
  to   { transform: none; }
}
@keyframes riseIn {
  from { opacity: 0; transform: translateY(calc(28 * var(--u))); }
  to   { opacity: 1; transform: none; }
}

.anim .hero img {
  animation: heroZoom 1.8s cubic-bezier(0.22, 0.61, 0.36, 1) both;
}
.anim .hero-title .hl,
.anim .hero-card {
  animation: riseIn 0.9s cubic-bezier(0.22, 0.61, 0.36, 1) both;
}
.anim .hero-title .hl:nth-child(1) { animation-delay: 0.25s; }
.anim .hero-title .hl:nth-child(2) { animation-delay: 0.36s; }
.anim .hero-card { animation-delay: 0.6s; }

/* hover */
.pub-item { display: contents; }

.pcard,
.ncard {
  transition: transform 0.4s cubic-bezier(0.22, 0.61, 0.36, 1),
              box-shadow 0.4s cubic-bezier(0.22, 0.61, 0.36, 1);
}
.pub-item:hover .pcard,
.ncard:hover {
  transform: translateY(calc(-4 * var(--u)));
  box-shadow: 0 calc(12 * var(--u)) calc(32 * var(--u)) rgba(0, 0, 0, 0.09);
}
.arrow path,
.hero-card-btn path { transition: transform 0.35s cubic-bezier(0.22, 0.61, 0.36, 1); }
.pub-item:hover .arrow path,
.ncard:hover .arrow path,
.hero-card:hover .hero-card-btn path { transform: translateX(2px); }

/* the reveal transform must survive the hover rule while it is still playing */
.anim .pcard[data-reveal]:not(.in) { transform: translateY(calc(20 * var(--u))); }

.hero-card { transition: background 0.4s ease; }
.hero-card:hover { background: rgba(255, 255, 255, 0.22); }

.link { transition: text-underline-offset 0.3s ease, opacity 0.3s ease; }
.link:hover { text-underline-offset: calc(6 * var(--u)); }

.nav-item { transition: opacity 0.3s ease; }
.nav-item:hover { opacity: 0.55; }

.filter { transition: background 0.3s ease, transform 0.3s ease; }
.filter:hover { background: #fff; transform: translateY(calc(-2 * var(--u))); }

@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
}
