/*
 *
 * Basics
 *
 */

:root {
  --textColor: #363636;
  --textColor2: #363636;
  --bodyBgColor: #fff;
  --linkColor: rgb(27, 94, 32);
  --borderColor: #eee;
  --surfaceColor: #fafafa;
  --shadowColor: rgba(0, 0, 0, 0.05);
  --imageShadowColor: #bbb;
}

:root[data-theme="dark"] {
  --textColor: #e6e6e6;
  --textColor2: #b8b8b8;
  --bodyBgColor: #181818;
  --linkColor: #66bb6a;
  --borderColor: #707070;
  --surfaceColor: #232323;
  --shadowColor: rgba(0, 0, 0, 0.4);
  /* dark rather than light gray: a light shadow would glow against the dark
     background instead of reading as a shadow */
  --imageShadowColor: rgba(0, 0, 0, 0.6);
}

a,
a:visited {
  color: var(--linkColor);
  text-decoration: none;
}

h1 {
  margin-top: 0;
  margin-bottom: 18px;
  text-align: center;
  font-size: 32px;
  color: var(--textColor2)
}

h1.title {
  font-size: 40px;
}

.nameHeading {
  color: var(--linkColor);
}

p.subtitle {
  margin-top: 0;
  margin-bottom: 1rem;
}

h2,
h3 {
  margin-top: 25px;
  font-size: 20px;
  color: var(--textColor2);
}

a:hover {
  text-decoration: underline;
}

h3 a,
h3 a:visited {
  color: var(--textColor2);
}

body,
main {
  min-width: 0px;
  margin: 0;
  background-color: var(--bodyBgColor);
  color: var(--textColor);
  font-size: 14.5px;
  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}

body {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

main {
  /* auto margins center a flex item but don't stretch it, so without an
     explicit width main would shrink to content width instead of 960px
     (breaks on the gallery page, whose photos are absolutely positioned
     and contribute no width) */
  width: min(960px, 100%);
  box-sizing: border-box;
  margin: 90px auto 0;
  display: flex;
  flex-direction: column;
  flex: 1;
  padding: 10px 20px;
}

/* wraps each page's article(s); grows to fill main so the footer sticks to
   the bottom of the viewport instead of floating right after short content */
.pageContent {
  display: flex;
  flex-direction: column;
  flex: 1;
}

.siteFooter {
  margin-top: auto;
  padding-top: 20px;
}

header {
  padding: 10px 0;
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  z-index: 100;
  background-color: var(--bodyBgColor);
  border-bottom: 1px solid var(--borderColor);
  box-shadow: 0 2px 8px var(--shadowColor);
}

/* max-width/padding match main, so content lines up with the page content's
   left edge instead of the viewport edge. Below the tablet breakpoint:
   hamburger - name - theme toggle in a 3-column grid; the name is centered
   because the two icon buttons flanking it are the same size */
.headerInner {
  max-width: 960px;
  margin: 0 auto;
  padding: 0 20px;
  align-items: center;
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: 10px;
}

header h1 {
  margin: 0 10px;
  text-align: left;
}

.siteName {
  font-weight: bold;
  font-size: 1.1em;
  color: var(--linkColor);
  text-align: center;
}

article {
  margin: 0 5px 5px 5px;
  padding-bottom: 40px;
}

/*
 *
 * Nav
 *
 */

/* below the tablet breakpoint, the nav collapses into a hamburger-triggered
   menu (nav ul, positioned fixed) instead of a horizontal link list */
.navToggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  margin-left: auto;
  padding: 0;
  border: 1px solid var(--borderColor);
  border-radius: 50%;
  background: none;
  color: var(--textColor);
  font-size: 1em;
  cursor: pointer;
  transition: color 0.2s ease, border-color 0.2s ease;
}

.navToggle:hover,
.navToggle:focus-visible {
  color: var(--linkColor);
  border-color: var(--linkColor);
}

/* display: contents removes <nav> as a grid item of .headerInner, so its
   3 columns are exactly the hamburger, the name, and the theme toggle */
nav {
  display: contents;
}

/* covers the viewport below the header (still on top via its higher
   z-index), keeping the hamburger (now an X) and theme toggle reachable */
nav ul {
  display: none;
  position: fixed;
  inset: 0;
  margin: 0;
  padding: 90px 20px 20px;
  list-style: none;
  flex-direction: column;
  justify-content: center;
  background-color: var(--bodyBgColor);
  overflow-y: auto;
  z-index: 99;
}

nav.navOpen ul {
  display: flex;
}

nav ul li {
  display: block;
  list-style: none;
  font-size: 1.3em;
  padding: 0;
  line-height: 2.6em;
  text-align: center;
}

nav ul ul li {
  margin-left: 15px;
  font-size: 1em;
  line-height: 2.2em;
}

nav a,
nav a:visited {
  display: block;
  position: relative;
  text-decoration: none;
  color: var(--textColor);
  font-weight: 500;
  letter-spacing: 0.02em;
  transition: color 0.2s ease;
}

nav a::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0.35em;
  height: 2px;
  background-color: var(--linkColor);
  transform: scaleX(0);
  transition: transform 0.2s ease;
}

nav a:hover,
nav a:focus-visible {
  color: var(--linkColor);
  text-decoration: none;
}

nav a:hover::after,
nav a:focus-visible::after {
  transform: scaleX(1);
}

nav a[aria-current="page"] {
  color: var(--linkColor);
}

nav a[aria-current="page"]::after {
  transform: scaleX(1);
}

.themeToggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  padding: 0;
  border: 1px solid var(--borderColor);
  border-radius: 50%;
  background: none;
  color: var(--textColor);
  font-size: 1em;
  cursor: pointer;
  transition: color 0.2s ease, border-color 0.2s ease;
}

.themeToggle:hover,
.themeToggle:focus-visible {
  color: var(--linkColor);
  border-color: var(--linkColor);
}

/*
 *
 * QR codes
 *
 */

.qrcontainer {
  text-align: center;
}

.qrcontainer .qrimage {
  width: 140px;
  margin-top: 30px;
  padding: 8px;
  background: #fff;
  border-radius: 4px;
}


/*
 *
 * Social links
 *
 */
.social-links {
  gap: 20px 28px;
  align-items: center;
  max-width: 620px;
  margin: 30px auto 0;
  display: flex;
  flex-wrap: wrap;
  text-align: center;
  justify-content: center;
}

.icon-link,
.icon-link:link,
.icon-link:visited {
  font-size: 36px;
  color: var(--textColor2);
  text-decoration: none;
  transition: color 0.3s ease, transform 0.2s ease;
}

.icon-link:hover,
.icon-link:focus-visible {
  transform: translateY(-3px);
}

.icon-link[title="Email"]:hover,
.icon-link[title="Email"]:focus-visible {
  color: #ea4335;
}

/* Gmail Red */
.icon-link[title="ORCID"]:hover,
.icon-link[title="ORCID"]:focus-visible {
  color: #a6ce39;
}

/* ORCID Green */
.icon-link[title="Google Scholar"]:hover,
.icon-link[title="Google Scholar"]:focus-visible {
  color: #4285f4;
}

/* Scholar Blue */
.icon-link[title="ResearchGate"]:hover,
.icon-link[title="ResearchGate"]:focus-visible {
  color: #00ccbb;
}

/* ResearchGate Teal */
.icon-link[title="GitHub"]:hover,
.icon-link[title="GitHub"]:focus-visible {
  color: #24292e;
}

/* GitHub Black */
.icon-link[title="LinkedIn"]:hover,
.icon-link[title="LinkedIn"]:focus-visible {
  color: #0a66c2;
}

/* LinkedIn Blue */
.icon-link[title="DBLP"]:hover,
.icon-link[title="DBLP"]:focus-visible {
  color: #1889c4;
}

/* DBLP Blue (dblp.org's own site accent color; dblp has no official brand color) */

/*
 *
 * About pages
 *
 */
.avatarAndBio {
  display: grid;
  grid-template-columns: 1fr;
  gap: 15px;
  justify-items: center;
  align-items: center;
}

.avatarAndBio .bio {
  /* .avatarAndBio's justify-items: center shrink-wraps grid items by
     default; override back to full column width for the text side */
  justify-self: stretch;
  padding: 10px;
  text-align: justify;
}

/* on the CV, unlike the About page, .bio's own padding still made
   Languages/Interests narrower than the rest of the (unpadded) CV content */
.cvAvatarBio .bio {
  padding: 0;
}

.avatarAndBio img.avatar {
  border-radius: 50%;
  box-shadow: var(--imageShadowColor) 1px 1px 15px;
}

.furtherInfo {
  padding: 10px 10px 10px 30px;
  display: grid;
  grid-template-columns: 1fr;
  gap: 15px;
}

.furtherInfo h2 {
  font-size: 1em;
  margin-top: 0;
  margin-bottom: 6px;
}

.furtherInfo p {
  margin: 0;
}

/*
 *
 * Year headings
 *
 */
.yearHeading {
  text-align: center;
  color: var(--linkColor);
  border-bottom: 2px solid #eee;
}

/*
 *
 * CV page
 *
 */
.cvSections {
  grid-template-columns: 1fr;
}

/* subheadings (entry titles, supervision categories, etc.) stay visually
   subordinate to the yearHeading section titles above them */
.cvSections h3 {
  font-size: 1em;
  margin-top: 15px;
  margin-bottom: 6px;
}

.cvTimeline {
  display: grid;
  gap: 20px;
  margin: 15px 0 25px;
}

.cvEntry {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2px;
}

.cvEntry .cvDate {
  font-size: 0.9em;
  font-weight: 600;
  color: var(--textColor2);
}

.cvTimelinePlainDate .cvDate {
  font-weight: normal;
}

.cvGloss {
  font-weight: normal;
}

.cvEntry .cvContent h3 {
  margin: 0;
}

.cvEntry .cvContent .cvSubtitle {
  font-style: italic;
  color: var(--textColor2);
  margin-bottom: 4px;
}

.cvEntry .cvContent ul {
  margin: 6px 0 0;
  padding-left: 20px;
}

/*
 *
 * Publications on other pages
 *
 */
/* on narrow screens, title/image/metadata stack instead of sitting
   side-by-side. grid-template-areas places .paper's three direct children
   (h3, the image, .metaData) independent of source order, without needing
   flexbox/grid "order" (which reorders visually only, not for tab order) */
.paper {
  margin-bottom: 0;
  display: grid;
  border-radius: 10px;
  padding: 15px;
  grid-template-columns: 1fr;
  grid-template-areas:
    "title"
    "image"
    "rest";
}

.paper.noImage {
  grid-template-areas:
    "title"
    "rest";
}

.paper h3 {
  grid-area: title;
  margin-top: 0;
  margin-bottom: 8px;
  font-size: 15px;
  font-weight: 600;
}

/* the image is wrapped in a link, and that link (not the img itself) is
   .paper's actual direct grid item, so the placement goes on it */
.paper > a:has(img.publicationImage) {
  grid-area: image;
}

.paper img.publicationImage {
  width: 100%;
  margin: 4px 0 15px 0;
  border-radius: 6px;
  box-shadow: var(--imageShadowColor) 1px 1px 15px;
}

.paper .metaData {
  grid-area: rest;
  font-size: 0.95em;
  color: var(--textColor2);
}

.paper .metaData div {
  margin-bottom: 8px;
}

.paper .metaData .links a {
  padding-right: 8px;
}

.paper .metaData div.authors a {
  color: inherit;
}

.paper .metaData div.authors b {
  font-weight: 600;
}

/*
 *
 * Gallery page
 *
 */
/* Justified-row layout (assets/js/gallery-layout.js): each photo's
   position/size is set in JS from its real aspect ratio, so .gallery's own
   height is set by JS too - absolutely positioned children don't
   contribute to their parent's size on their own. */
.gallery {
  position: relative;
}

.galleryItem {
  position: absolute;
  padding: 0;
  border: none;
  background: none;
  cursor: pointer;
}

.galleryItem img {
  display: block;
  width: 100%;
  height: 100%;
  box-shadow: var(--imageShadowColor) 1px 1px 15px;
  transition: transform 0.2s ease;
}

.galleryItem:hover img,
.galleryItem:focus-visible img {
  transform: scale(1.02);
}

.lightbox {
  border: none;
  padding: 0;
  background: none;
  max-width: 92vw;
  max-height: 92vh;
  transition: opacity 0.18s ease, transform 0.18s ease, overlay 0.18s ease allow-discrete, display 0.18s ease allow-discrete;
  opacity: 0;
  transform: scale(0.96);
}

.lightbox[open] {
  opacity: 1;
  transform: scale(1);
}

@starting-style {
  .lightbox[open] {
    opacity: 0;
    transform: scale(0.96);
  }
}

.lightbox::backdrop {
  background: rgba(0, 0, 0, 0.75);
}

.lightbox img {
  display: block;
  max-width: 92vw;
  max-height: 92vh;
  border-radius: 4px;
}

.lightbox .lightboxClose {
  position: fixed;
  top: 16px;
  right: 24px;
  width: 40px;
  height: 40px;
  border: none;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.5);
  color: #fff;
  font-size: 1.5em;
  line-height: 1;
  cursor: pointer;
  transition: background-color 0.2s ease;
}

.lightbox .lightboxClose:hover,
.lightbox .lightboxClose:focus-visible {
  background: rgba(0, 0, 0, 0.75);
}

/*
 *
 * Publication pages
 *
 */
.pubPageContent {
  text-align: center;
}

.pubPageContent div {
  margin-top: 10px;
}

.pubPageContent img.teaser {
  max-width: 100%;
  max-height: 400px;
  border-radius: 3px;
}

.pubPageContent .video {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  border: none;
  border-radius: 3px;
}

.pubPageContent .abstract {
  text-align: justify;
  width: 100%;
  margin-top: 10px;
}

.pubPageContent .bibtex {
  position: relative;
  width: 75%;
  margin: 10px auto 0;
  text-align: left;
}

.pubPageContent textarea {
  width: 100%;
  min-height: 120px;
  padding: 12px;
  border: 1px solid var(--borderColor);
  border-radius: 8px;
  background: var(--surfaceColor);
  color: var(--textColor);
  font-family: 'Consolas', 'Courier New', monospace;
  font-size: 0.85em;
  line-height: 1.5;
  white-space: pre;
  overflow-x: auto;
  resize: vertical;
  box-sizing: border-box;
}

.pubPageContent .copyButton {
  position: absolute;
  top: 8px;
  right: 8px;
  padding: 2px 4px;
  font-size: 0.85em;
  border: 1px solid #aaa;
  border-radius: 6px;
  background: var(--bodyBgColor);
  color: var(--textColor);
  cursor: pointer;
  transition: color 0.2s ease, border-color 0.2s ease;
}

.pubPageContent .copyButton:hover,
.pubPageContent .copyButton:focus-visible {
  color: var(--linkColor);
  border-color: var(--linkColor);
}

.pubPageContent div.materials a {
  padding: 0 3px;
}

.pubPageContent div.authors a {
  color: inherit;
}

.pubPageContent b {
  font-weight: 700;
}

/*
 *
 * Link icons
 *
 */

/* base formatting and icon for links that open in a new tab, excluding images.
   Uses mask-image (shape only) with background-color for the visible color,
   rather than background-image with a color baked into the SVG, so the icon
   follows the theme instead of always being black (unreadable in dark mode) */
a[target="_blank"]:not(:has(img), .icon-link)::after {
  content: "";
  display: inline-block;
  width: 0.85em;
  height: 0.85em;
  margin-left: 6px;
  margin-top: .2em;
  background-color: var(--textColor2);
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-size: contain;
  mask-size: contain;
  /* new-tab icon*/
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6'%3E%3C/path%3E%3Cpolyline points='15 3 21 3 21 9'%3E%3C/polyline%3E%3Cline x1='10' y1='14' x2='21' y2='3'%3E%3C/line%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6'%3E%3C/path%3E%3Cpolyline points='15 3 21 3 21 9'%3E%3C/polyline%3E%3Cline x1='10' y1='14' x2='21' y2='3'%3E%3C/line%3E%3C/svg%3E");
}

/* internal PDFs get PDF icon */
a[href*=".pdf" i]:not([href^="http"])::after,
a[href*=".pdf" i][href*="visvar.github.io"]::after {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z'%3E%3C/path%3E%3Cpolyline points='14 2 14 8 20 8'%3E%3C/polyline%3E%3Cline x1='16' y1='13' x2='8' y2='13'%3E%3C/line%3E%3Cline x1='16' y1='17' x2='8' y2='17'%3E%3C/line%3E%3Cline x1='10' y1='9' x2='8' y2='9'%3E%3C/line%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z'%3E%3C/path%3E%3Cpolyline points='14 2 14 8 20 8'%3E%3C/polyline%3E%3Cline x1='16' y1='13' x2='8' y2='13'%3E%3C/line%3E%3Cline x1='16' y1='17' x2='8' y2='17'%3E%3C/line%3E%3Cline x1='10' y1='9' x2='8' y2='9'%3E%3C/line%3E%3C/svg%3E");
}

/* internal ZIPs get ZIP icon */
a[href*=".zip" i]:not([href^="http"])::after,
a[href*=".zip" i][href*="visvar.github.io"]::after {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4'%3E%3C/path%3E%3Cpolyline points='7 10 12 15 17 10'%3E%3C/polyline%3E%3Cline x1='12' y1='15' x2='12' y2='3'%3E%3C/line%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4'%3E%3C/path%3E%3Cpolyline points='7 10 12 15 17 10'%3E%3C/polyline%3E%3Cline x1='12' y1='15' x2='12' y2='3'%3E%3C/line%3E%3C/svg%3E");
}

/* internal MP4s get MP4 icon */
a[href*=".mp4" i]:not([href^="http"])::after,
a[href*=".mp4" i][href*="visvar.github.io"]::after {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='2' y='2' width='20' height='20' rx='2.18' ry='2.18'%3E%3C/rect%3E%3Cline x1='7' y1='2' x2='7' y2='22'%3E%3C/line%3E%3Cline x1='17' y1='2' x2='17' y2='22'%3E%3C/line%3E%3Cline x1='2' y1='12' x2='22' y2='12'%3E%3C/line%3E%3Cline x1='2' y1='7' x2='7' y2='7'%3E%3C/line%3E%3Cline x1='2' y1='17' x2='7' y2='17'%3E%3C/line%3E%3Cline x1='17' y1='17' x2='22' y2='17'%3E%3C/line%3E%3Cline x1='17' y1='7' x2='22' y2='7'%3E%3C/line%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='2' y='2' width='20' height='20' rx='2.18' ry='2.18'%3E%3C/rect%3E%3Cline x1='7' y1='2' x2='7' y2='22'%3E%3C/line%3E%3Cline x1='17' y1='2' x2='17' y2='22'%3E%3C/line%3E%3Cline x1='2' y1='12' x2='22' y2='12'%3E%3C/line%3E%3Cline x1='2' y1='7' x2='7' y2='7'%3E%3C/line%3E%3Cline x1='2' y1='17' x2='7' y2='17'%3E%3C/line%3E%3Cline x1='17' y1='17' x2='22' y2='17'%3E%3C/line%3E%3Cline x1='17' y1='7' x2='22' y2='7'%3E%3C/line%3E%3C/svg%3E");
}

/*
 *
 * Accessibility
 *
 */

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/*
 *
 * Responsiveness
 *
 */

/* phone layout */
@media (min-width: 0px) {

  html {
    scroll-padding-top: 90px;
  }

  article {
    grid-template-columns: auto;
  }

  img.avatar {
    width: 128px;
    height: 128px;
  }
}

/* tablet layout */
@media (min-width: 720px) {

  html {
    scroll-padding-top: 90px;
  }

  /* enough width for a horizontal nav: hide the hamburger, reset the
     full-screen menu and centered-name grid back to a plain inline layout */
  .headerInner {
    display: flex;
    gap: 30px;
  }

  .siteName {
    text-align: left;
  }

  .navToggle {
    display: none;
  }

  nav {
    display: block;
    margin-left: auto;
    padding-left: 10px;
  }

  nav ul {
    display: block;
    position: static;
    padding: 0;
    background: none;
    border-bottom: none;
    box-shadow: none;
  }

  nav ul li {
    display: inline-block;
    font-size: 1.1em;
    padding: 0 16px;
    text-align: left;
  }

  article {
    grid-template-columns: 1fr 1fr;
  }

  .avatarAndBio {
    grid-template-columns: auto 1fr;
    justify-items: initial;
    gap: 0;
  }

  .avatarAndBio .bio {
    padding: 10px 10px 10px 30px;
  }

  .cvEntry {
    grid-template-columns: 160px 1fr;
    gap: 15px;
  }

  img.avatar {
    width: 192px;
    height: 192px;
  }

  /* side-by-side from here up: image on the left spanning both rows, title
     and metadata stacked in the right column. The second column is 1fr, not
     auto: auto sizes a track to fit its content, leaving the card narrower
     than the container on entries with short text. grid-template-rows is
     explicit so the image (spanning both rows) can't inflate the title
     row's height beyond its own content */
  .paper {
    grid-template-columns: 192px 1fr;
    grid-template-rows: auto 1fr;
    grid-template-areas:
      "image title"
      "image rest";
  }

  .paper.noImage {
    grid-template-columns: 1fr;
    grid-template-rows: auto 1fr;
    grid-template-areas:
      "title"
      "rest";
  }

  .paper.noImage h3,
  .paper.noImage .metaData {
    margin-left: 192px;
  }

  .paper img.publicationImage {
    width: 192px;
  }

  .paper h3,
  .paper .metaData {
    padding-left: 25px;
  }
}

/* desktop layout */
@media (min-width: 1020px) {

  html {
    scroll-padding-top: 90px;
  }

  article {
    grid-template-columns: 1fr 1fr;
  }

  img.avatar {
    width: 256px;
    height: 256px;
  }

  .paper {
    grid-template-columns: 256px 1fr;
  }

  .paper.noImage h3,
  .paper.noImage .metaData {
    margin-left: 256px;
  }

  .paper img.publicationImage {
    width: 256px;
  }

  .paper h3,
  .paper .metaData {
    padding-left: 30px;
  }
}
