/* One stylesheet for every page. No build step: edit and reload. */

:root {
  color-scheme: light;

  --bg: #fdfdfb;
  --text: #1c1c1a;
  --muted: #6b6b66;
  --rule: #e4e4de;
  --link: #1a4f8b;

  --sans: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --serif: "Iowan Old Style", "Palatino Linotype", Palatino, "Book Antiqua", Georgia, serif;
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

body {
  margin: 0;
  padding: 4rem 1.25rem 3rem;
  background: var(--bg);
  color: var(--text);
  font-family: var(--serif);
  font-size: 1.125rem;
  line-height: 1.65;
  text-rendering: optimizeLegibility;
}

/* The narrow text column. Header, main and footer all share it. */
.page {
  max-width: 720px;
  margin: 0 auto;
}

/* ---------- Text ---------- */

h1,
h2 {
  font-weight: 600;
  line-height: 1.25;
  text-wrap: balance;
}

h1 {
  font-size: 1.9rem;
  margin: 0 0 1.25rem;
  letter-spacing: -0.01em;
}

h2 {
  font-size: 1.25rem;
  margin: 0 0 0.75rem;
}

p {
  margin: 0 0 1rem;
}

a {
  color: var(--link);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
}

a:hover {
  text-decoration-thickness: 2px;
}

a:focus-visible {
  outline: 2px solid var(--link);
  outline-offset: 3px;
  border-radius: 2px;
}

section {
  margin-top: 3.5rem;
}

/* ---------- Homepage ---------- */

/* Intro: text on the left, photo on the right. */
.intro {
  display: grid;
  grid-template-columns: 1fr 280px;
  gap: 2.25rem;
  align-items: start;
}

.intro-text > :last-child {
  margin-bottom: 0;
}

/* Shown whole, at its own aspect ratio: never cropped. It comes first in
   the HTML so it leads on small screens. */
.photo {
  order: 2;
  display: block;
  width: 100%;
  height: auto;
}

.links {
  list-style: none;
  margin: 3rem 0 0;
  padding: 1.5rem 0;
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 0.4rem 1.5rem;
}

/* ---------- Inner pages ---------- */

.home-link {
  display: inline-block;
  margin-bottom: 2.5rem;
  color: var(--muted);
  font-size: 1rem;
}

.muted {
  color: var(--muted);
}

/* ---------- Best Reads page ---------- */

.books {
  margin: 2rem 0 0;
  padding-left: 1.25rem;
}

.books li {
  padding: 0.3rem 0;
}


/* Pages that should have no dividing lines at all. */
.no-rules footer {
  border-top: 0;
}

/* ---------- Footer ---------- */

footer {
  margin-top: 4.5rem;
  padding-top: 1.25rem;
  border-top: 1px solid var(--rule);
  font-size: 0.95rem;
}

footer a {
  color: var(--muted);
  margin-right: 1.25rem;
}

/* ---------- Events page ---------- */

/* The events pages use the same column width as every other page. */
.page.wide {
  max-width: 720px;
}

/* Same heading size as the other pages. */
.ev-head h1 {
  margin-bottom: 1.5rem;
}

/* The page's opening line: a little larger, and set apart from what follows. */
.ev-lead {
  max-width: 34em;
  margin: 0 0 3.5rem;
  font-size: 1.35rem;
  line-height: 1.5;
}

/* One plain sentence under the heading. */
.ev-line {
  margin: 0 0 2rem;
  font-size: 1.2rem;
}

/* A wall of photos in two columns. Every photo is shown whole, at its own
   shape, so tiles have different heights. The grid uses very thin rows and
   each tile spans as many as its photo needs: --d on wide screens, --m on
   narrow ones. Row height follows the page width, so the whole wall scales
   together and photos are never squeezed. */
.mosaic-wrap {
  container-type: inline-size;
}

.mosaic {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-auto-rows: 5.6px;
  grid-auto-rows: 0.5cqw;
  grid-auto-flow: row dense;
  column-gap: 10px;
}

.t-malaysia { --d: 86; --m: 88; }
.t-singapore { --d: 119; --m: 121; }
.t-vietnam { --d: 55; --m: 56; }
.t-bangalore { --d: 54; --m: 55; }
.t-toronto { --d: 55; --m: 56; }
.t-mumbai { --d: 61; --m: 63; }
.t-shanghai { --d: 81; --m: 83; }
.t-beijing { --d: 60; --m: 61; }
.t-beijing-2 { --d: 52; --m: 66; }
.t-shenzhen { --d: 70; --m: 72; }
.t-researcher-meetup { --d: 47; --m: 55; }
.t-researcher-dinner { --d: 67; --m: 69; }

/* Each tile is a card that flips: photo on the front, details on the back.
   A hidden checkbox holds the state on touch screens, so no script. */
.tile {
  position: relative;
  display: block;
  grid-row: span var(--d);
  perspective: 1400px;
}

.tile.left  { grid-column: 1 / span 2; }
.tile.right { grid-column: 3 / span 2; }
.t-vietnam { grid-column: 3; }
.t-toronto  { grid-column: 4; }

@container (max-width: 660px) {
  .mosaic {
    grid-template-columns: 1fr 1fr;
    grid-auto-rows: 1cqw;
  }

  .tile,
  .tile.left,
  .tile.right {
    grid-column: 1 / span 2;
    grid-row: span var(--m);
  }

  .t-vietnam { grid-column: 1; }
  .t-toronto  { grid-column: 2; }
}

.tile input {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
}

/* The 10px at the bottom is the gap between tiles in a column. */
.tile .inner {
  position: absolute;
  inset: 0 0 10px 0;
  transform-style: preserve-3d;
  transition: transform 0.55s cubic-bezier(0.2, 0.7, 0.2, 1);
}

/* With a mouse the card flips while the pointer is over it. */
@media (hover: hover) {
  .tile:hover .inner,
  .tile:focus-within .inner {
    transform: rotateY(180deg);
  }
}

/* On touch screens there is no hover, so a "Details" tag shows and a tap
   flips the card. */
@media (hover: none) {
  .tile {
    cursor: pointer;
  }

  .tile input:checked + .inner {
    transform: rotateY(180deg);
  }

  .mosaic .tile .tag {
    display: block;
  }
}

.tile input:focus-visible + .inner {
  outline: 2px solid var(--link);
  outline-offset: 3px;
}

.tile .front,
.tile .back {
  position: absolute;
  inset: 0;
  overflow: hidden;
  border-radius: 8px;
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
}

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

.tile .front::after {
  content: "";
  position: absolute;
  inset: 55% 0 0 0;
  background: linear-gradient(to top, rgba(0, 0, 0, 0.72), rgba(0, 0, 0, 0));
}

/* The name and date sit above the card and do not turn with it. */
.tile .cap {
  position: absolute;
  left: 1rem;
  right: 1rem;
  bottom: calc(0.8rem + 10px);
  z-index: 2;
  pointer-events: none;
  color: #fff;
  font-family: var(--sans);
  font-size: 0.8rem;
  line-height: 1.3;
}

.tile .cap strong {
  display: block;
  font-family: var(--serif);
  font-size: 1.45rem;
  font-weight: 600;
}

.tile.small .cap strong {
  font-size: 1.15rem;
}

/* A "Luma" button in Luma's own gradient, on the bottom-right corner of the
   card's back. It sits outside the flipping face (so it can be clicked) and
   is shown only while the card is flipped. */
.tile .luma {
  position: absolute;
  right: 0.9rem;
  bottom: calc(0.85rem + 10px);
  z-index: 3;
  padding: 0.32rem 0.75rem;
  border-radius: 7px;
  background: linear-gradient(120deg, #5b6cff 0%, #c44dff 45%, #ff5a8a 75%, #ff9a4d 100%);
  color: #fff;
  font-family: var(--sans);
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-decoration: none;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.25s, filter 0.2s;
}

.tile .luma:hover,
.tile .luma:focus-visible {
  filter: brightness(1.12);
  color: #fff;
}

@media (hover: hover) {
  .tile:hover .luma,
  .tile:focus-within .luma {
    opacity: 1;
    pointer-events: auto;
    transition-delay: 0.2s;
  }
}

@media (hover: none) {
  .tile input:checked ~ .luma {
    opacity: 1;
    pointer-events: auto;
    transition-delay: 0.2s;
  }
}

.tile.small .luma {
  right: 0.6rem;
  padding: 0.2rem 0.5rem;
  font-size: 0.7rem;
}

.tile .tag {
  display: none;
  position: absolute;
  top: 0.6rem;
  right: 0.6rem;
  z-index: 1;
  padding: 0.2rem 0.5rem;
  border-radius: 3px;
  background: rgba(255, 255, 255, 0.9);
  color: var(--text);
  font-family: var(--sans);
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.02em;
}

.tile .back {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  padding: 1.4rem 1.5rem 4.4rem;
  overflow-y: auto;
  background: var(--text);
  color: var(--bg);
  transform: rotateY(180deg);
}

.tile .back .meta {
  margin: 0 0 0.6rem;
  font-family: var(--sans);
  font-size: 0.78rem;
  opacity: 0.7;
}

.tile .back .desc {
  font-size: 1.05rem;
  line-height: 1.5;
}

.tile .back a {
  margin-top: 0.7rem;
  color: inherit;
  font-family: var(--sans);
  font-size: 0.8rem;
}

/* The two small tiles get tighter text. */
.tile.small .back {
  padding: 0.85rem 0.95rem 3.5rem;
}

.tile.small .back .meta {
  margin-bottom: 0.4rem;
  font-size: 0.72rem;
}

.tile.small .back .desc {
  font-size: 0.8rem;
  line-height: 1.42;
}

.tile.small .back a {
  margin-top: 0.4rem;
  font-size: 0.72rem;
}

/* ---------- Small screens ---------- */

/* Below the full column width there is no room for text beside the photo:
   stack them, photo first. */
@media (max-width: 760px) {
  .intro {
    grid-template-columns: 1fr;
    gap: 1.75rem;
  }

  .photo {
    order: 0;
    width: 220px;
    max-width: 60%;
  }
}

@media (max-width: 480px) {
  body {
    padding-top: 2.5rem;
    font-size: 1.0625rem;
  }

  h1 {
    font-size: 1.65rem;
  }
}

@media (max-width: 700px) {
  .tile .cap strong {
    font-size: 1.2rem;
  }

  .tile.small .cap strong {
    font-size: 0.95rem;
  }

  .mosaic .tile .back {
    padding: 0.9rem 1rem 3.6rem;
  }

  .mosaic .tile .back .desc {
    font-size: 0.9rem;
  }

  /* The two small tiles are tiny on phones. */
  .mosaic .tile.small .back {
    padding: 0.55rem 0.6rem 2.9rem;
  }

  .mosaic .tile.small .back .meta {
    font-size: 0.6rem;
  }

  .mosaic .tile.small .back .desc {
    font-size: 0.68rem;
    line-height: 1.32;
  }

  .mosaic .tile.small .back a {
    font-size: 0.6rem;
  }
}

@media (prefers-reduced-motion: reduce) {
  .tile .inner {
    transition: none;
  }
}

/* ---------- Hacker houses ---------- */

/* Shown as printed snapshots, not flip cards, so they read as something
   more personal than the events above. Widths follow each photo's shape,
   so prints in a row come out the same height. */
.houses {
  margin-top: 0;
}

.ev-wall {
  margin-top: 4rem;
}

.prints {
  display: flex;
  gap: 1.75rem;
  align-items: flex-start;
  margin-top: 2rem;
}

.print {
  flex: 1.333 1 0;
  margin: 0;
  padding: 10px 10px 0;
  background: #fff;
  border: 1px solid var(--rule);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06), 0 10px 24px rgba(0, 0, 0, 0.08);
  transform: rotate(0.9deg);
}

.print:first-child { transform: rotate(-1.4deg); }
.print:last-child  { transform: rotate(0.9deg); }

/* A see-through "Watch" button on the photo's top-right corner. */
.print {
  position: relative;
}

.print .watch {
  position: absolute;
  top: 22px;
  right: 22px;
  display: inline-flex;
  align-items: center;
  gap: 0.45em;
  padding: 0.4rem 0.85rem 0.4rem 0.75rem;
  border: 1px solid rgba(255, 255, 255, 0.55);
  border-radius: 999px;
  background: rgba(20, 20, 20, 0.32);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  color: #fff;
  font-family: var(--sans);
  font-size: 0.82rem;
  font-weight: 600;
  letter-spacing: 0.03em;
  text-decoration: none;
  transition: background 0.2s;
}

.print .watch span {
  font-size: 0.7em;
}

.print .watch:hover,
.print .watch:focus-visible {
  background: rgba(20, 20, 20, 0.6);
  color: #fff;
}

.print img {
  display: block;
  width: 100%;
  height: auto;
}

.print figcaption {
  padding: 0.7rem 0 0.85rem;
  font-style: italic;
  font-size: 0.95rem;
  text-align: center;
  color: var(--muted);
  font-weight: 600;
}

@media (max-width: 700px) {
  .prints {
    flex-direction: column;
    align-items: center;
    gap: 1.5rem;
  }

  .print {
    flex: none;
    width: 100%;
  }
}

/* The photo that closes the homepage. It is as wide as the text column and
   has no frame or caption; its top fades into the page so it sits behind the
   end of the page instead of looking like part of the story above it. */
.closing {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  object-position: 50% 25%;
  margin: 3rem 0 0;
  border-radius: 0 0 10px 10px;
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 24%);
  mask-image: linear-gradient(to bottom, transparent 0, #000 24%);
}

/* On phones the homepage links wrap to two rows; keep them left-aligned. */
@media (max-width: 640px) {
  .links {
    justify-content: flex-start;
    gap: 0.4rem 1.4rem;
  }
}

/* Homepage: small contact links in the top-right corner. */
.top-links {
  display: flex;
  justify-content: flex-end;
  gap: 1.25rem;
  margin: -2rem 0 2rem;
  font-size: 0.95rem;
}

.top-links a {
  color: var(--muted);
}

.top-links.icons {
  gap: 1.1rem;
  align-items: center;
}

.top-links.icons a {
  display: inline-flex;
  border: 0;
  text-decoration: none;
}

.top-links.icons svg {
  width: 19px;
  height: 19px;
  fill: currentColor;
}

.top-links.icons svg.line {
  width: 21px;
  height: 21px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Each icon in its own brand colour. */
.top-links.icons .i-li   { color: #0a66c2; }
.top-links.icons .i-x    { color: #000; }
.top-links.icons .i-gh   { color: #181717; }
.top-links.icons .i-mail { color: #ea4335; }

.top-links.icons a:hover {
  opacity: 0.7;
}

/* ---------- Greeting before "I'm Om" ---------- */

/* "Hello" in ten languages, one at a time, on the same line
   as the name. English returns after every three other languages, so the
   loop has 12 steps of 3s (36s). The words are stacked in one grid cell;
   each fades up into place, holds, and fades out as the next arrives. The
   cell's width glides to fit each word so "I'm Om" slides instead of
   jumping. Pure CSS. Widths are each word's measured width in em. Each
   language has its own colour. */
.hello {
  display: inline-grid;
  align-items: baseline;
  margin-right: 0.3em;
  color: var(--muted);
  white-space: nowrap;
  animation: hello-width 36s infinite ease-in-out;
}

.hello span {
  grid-area: 1 / 1;
  justify-self: start;
  opacity: 0;
  animation: hello 36s infinite both;
}

.hello span:nth-child(1) { animation-delay: 0s; color: #2b59c3; }
.hello span:nth-child(2) { animation-delay: 3s; color: #d62828; }
.hello span:nth-child(3) { animation-delay: 6s; color: #f77f00; }
.hello span:nth-child(4) { animation-delay: 9s; color: #b23a48; }
.hello span:nth-child(5) { animation-delay: 12s; color: #2b59c3; }
.hello span:nth-child(6) { animation-delay: 15s; color: #3a0ca3; }
.hello span:nth-child(7) { animation-delay: 18s; color: #2a9d5c; }
.hello span:nth-child(8) { animation-delay: 21s; color: #c2185b; }
.hello span:nth-child(9) { animation-delay: 24s; color: #2b59c3; }
.hello span:nth-child(10) { animation-delay: 27s; color: #0a9396; }
.hello span:nth-child(11) { animation-delay: 30s; color: #e0a800; }
.hello span:nth-child(12) { animation-delay: 33s; color: #1d6fa5; }

@keyframes hello {
  0%     { opacity: 0; transform: translateY(0.35em); filter: blur(6px); }
  2%     { opacity: 1; transform: translateY(0);      filter: blur(0); }
  6.67%  { opacity: 1; transform: translateY(0);      filter: blur(0); }
  8.33%  { opacity: 0; transform: translateY(-0.3em); filter: blur(6px); }
  100%   { opacity: 0; transform: translateY(-0.3em); filter: blur(6px); }
}

@keyframes hello-width {
  1.00%, 7.33% { width: 2.57em; }
  9.33%, 15.67% { width: 2.13em; }
  17.67%, 24.00% { width: 2.1em; }
  26.00%, 32.33% { width: 3.64em; }
  34.33%, 40.67% { width: 2.57em; }
  42.67%, 49.00% { width: 3.78em; }
  51.00%, 57.33% { width: 2.5em; }
  59.33%, 65.67% { width: 4.98em; }
  67.67%, 74.00% { width: 2.57em; }
  76.00%, 82.33% { width: 1.67em; }
  84.33%, 90.67% { width: 2.26em; }
  92.67%, 99.00% { width: 4.98em; }
  0%, 100% { width: 3.78em; }
}

@media (prefers-reduced-motion: reduce) {
  .hello {
    animation: none;
    width: 2.57em;
  }

  .hello span {
    animation: none;
  }

  .hello span:first-child {
    opacity: 1;
  }
}

/* Two photos side by side at the same height. Each one's share of the row
   follows its shape (16:9 and 9:16), so neither is cropped. */
.pair {
  display: flex;
  gap: 12px;
  margin: 0 0 1.5rem;
}

.pair img {
  display: block;
  min-width: 0;
  height: auto;
  border-radius: 8px;
}

.pair .wide { flex: 1.7778 1 0; }
.pair .tall { flex: 0.5625 1 0; }

/* Strava link: the Strava mark in its orange, with the name beside it. */
.strava {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.4rem 0.8rem 0.4rem 0.65rem;
  border: 1px solid #fc4c02;
  border-radius: 999px;
  color: #fc4c02;
  font-family: var(--sans);
  font-size: 0.85rem;
  font-weight: 600;
  text-decoration: none;
}

.strava svg {
  width: 18px;
  height: 18px;
  fill: currentColor;
}

.strava:hover,
.strava:focus-visible {
  background: #fc4c02;
  color: #fff;
}

/* A section heading that matches the page title in size and spacing. */
h2.big {
  font-size: 1.9rem;
  margin: 0 0 1.25rem;
  letter-spacing: -0.01em;
}

@media (max-width: 480px) {
  h2.big {
    font-size: 1.65rem;
  }
}

/* The opening note on the Events page: italic, with a rule down its left. */
.ev-lead.note {
  padding-left: 1.25rem;
  border-left: 2px solid var(--text);
  font-style: italic;
}

/* "I run." with the Strava button beside it. */
.strava-line {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  margin: 0;
}

/* A small label above a group of photos on the Adventures page. */
h2.kind {
  margin: 0 0 0.85rem;
  font-size: 1.15rem;
}

h2.kind span {
  margin-left: 0.2em;
  font-size: 0.95em;
}

/* The OpenClaw-only page shows nine of the tiles; a slightly taller
   Bangalore tile makes its two columns end level. */
.nights-only .t-bangalore { --d: 58; }

/* ---------- My Story timeline ---------- */

/* A line runs down the left with a circle at each chapter, like a path
   walked backwards from today. The line and circles are drawn dark; a pale
   veil fixed over the lower part of the screen lightens whatever is still
   below the reading point. So as you scroll, the line darkens downwards and
   each circle fills in turn. */
.rail {
  position: relative;
  margin-top: 0.5rem;
  padding-left: 1.75rem;
  border-left: 1px solid var(--text);
}

.stop {
  position: relative;
  margin-top: 2.4rem;
}

.stop:first-of-type {
  margin-top: 0;
}

.stop::before {
  content: "";
  position: absolute;
  left: calc(-1.75rem - 5px);
  top: 0.62em;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--text);
}

/* The ring is a separate layer above the veil, so unread circles keep a
   crisp outline while their centre goes pale. */
.stop::after {
  content: "";
  position: absolute;
  z-index: 2;
  left: calc(-1.75rem - 5px);
  top: 0.62em;
  width: 9px;
  height: 9px;
  border: 1.5px solid var(--text);
  border-radius: 50%;
  box-sizing: border-box;
}

/* The veil. Where the browser can tie an animation to scrolling, the veil
   covers the whole line at the top of the page and shrinks away downwards as
   the page is scrolled: the dark line grows from the very first circle and
   reaches the very bottom at the end of the page. */
.unread {
  position: absolute;
  z-index: 1;
  top: 0;
  bottom: 0;
  left: -12px;
  width: 22px;
  background: #dcdcd6;
  mix-blend-mode: lighten;
  pointer-events: none;
  transform-origin: 50% 100%;
}

/* The first circle is "now": always filled. */
.stop:first-of-type::before {
  z-index: 3;
}

@supports (animation-timeline: scroll()) {
  .unread {
    animation: read-on linear both;
    animation-timeline: scroll(root block);
  }
}

@keyframes read-on {
  from { transform: scaleY(1); }
  to   { transform: scaleY(0); }
}

/* Older browsers: a veil fixed over the lower part of the screen instead,
   so the line still darkens as the text scrolls up past the middle. */
@supports not (animation-timeline: scroll()) {
  .unread {
    position: fixed;
    top: 55vh;
    left: auto;
    margin-left: calc(-1.75rem - 12px);
  }
}

.stop p:last-child {
  margin-bottom: 0;
}

/* Two lines in a row under a heading sit closer together. */
.ev-line:has(+ .ev-line) {
  margin-bottom: 0.6rem;
}

/* The whole hacker house photo opens its video, not just the Watch button. */
.print-photo {
  display: block;
}

/* ---------- Homepage on phones ---------- */

/* A round photo and the name sit on the centre line; the paragraphs stay
   left-aligned for easy reading. The contact icons move to the very bottom
   of the page. */
@media (max-width: 760px) {
  .home .page {
    display: flex;
    flex-direction: column;
  }

  .home .top-links {
    order: 2;
    justify-content: center;
    margin: 2.5rem 0 0;
    padding-top: 1.5rem;
    border-top: 1px solid var(--rule);
  }

  .home .intro {
    justify-items: center;
  }

  .home .photo {
    width: 150px;
    max-width: none;
    aspect-ratio: 1 / 1;
    object-fit: cover;
    object-position: 50% 30%;
    border-radius: 50%;
  }

  .home .intro h1 {
    text-align: center;
  }

  .home .links {
    justify-content: center;
  }
}

/* ---------- Events: highlighted section headings ---------- */

/* A soft highlighter stroke behind the lower half of the words: yellow for
   Hacker Houses, blue for Demo Nights and Sessions. */
.houses h2,
.ev-wall h2 {
  font-size: 1.6rem;
  margin-bottom: 1rem;
}

.houses h2 span,
.ev-wall h2 span {
  padding: 0 0.25em;
  margin-left: -0.25em;
  background: linear-gradient(to top, #ffe58a 0, #ffe58a 42%, transparent 42%);
}

.ev-wall h2 span {
  background: linear-gradient(to top, #c9dcff 0, #c9dcff 42%, transparent 42%);
}

/* Library page: three equal sections (Notes, Books, Resources). */
.shelf {
  margin-top: 3rem;
}

.shelf:first-of-type {
  margin-top: 0.5rem;
}

.shelf h2 {
  font-size: 1.35rem;
  margin-bottom: 0.6rem;
}

/* ---------- Hacker house prints: a little life ---------- */

/* With a mouse: the print lifts, swings the other way and grows slightly. */
.print {
  transition: transform 0.45s cubic-bezier(0.2, 0.8, 0.2, 1), box-shadow 0.45s;
}

@media (hover: hover) {
  /* The two prints swing in opposite directions and drift apart. */
  .prints .print:hover {
    transform: rotate(2.6deg) translate(-8px, -10px) scale(1.03);
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.08), 0 22px 40px rgba(0, 0, 0, 0.16);
  }

  .prints .print:last-child:hover {
    transform: rotate(-3deg) translate(8px, -10px) scale(1.03);
  }
}

/* On touch screens: as a print scrolls into view it swings from a stronger
   tilt into its resting angle, like a photo being set down. */
@media (hover: none) {
  @supports (animation-timeline: view()) {
    .prints .print {
      animation: set-down linear both;
      animation-timeline: view();
      animation-range: entry 0% cover 40%;
    }

    .prints .print:first-child { --from: 8deg;  --to: -2deg; }
    .prints .print:last-child  { --from: -8deg; --to: 2deg; }
  }
}

@keyframes set-down {
  from { transform: rotate(var(--from, 6deg)) translateY(28px) scale(0.96); }
  to   { transform: rotate(var(--to, 0.9deg)) translateY(0) scale(1); }
}

@media (prefers-reduced-motion: reduce) {
  .print {
    transition: none;
  }

  .prints .print {
    animation: none;
  }
}

/* ---------- Library: highlighted section headings ---------- */

/* The same marker strokes as the Events headings, one colour
   per section, with a hairline between sections. */
.shelf {
  margin-top: 2.25rem;
  padding-top: 2.25rem;
  border-top: 1px solid var(--rule);
}

.shelf:first-of-type {
  margin-top: 0.5rem;
  padding-top: 0;
  border-top: 0;
}

.shelf h2 span {
  padding: 0 0.25em;
  margin-left: -0.25em;
  background: linear-gradient(to top, #ffe58a 0, #ffe58a 42%, transparent 42%);
}

.shelf:nth-of-type(2) h2 span {
  background: linear-gradient(to top, #c9dcff 0, #c9dcff 42%, transparent 42%);
}

.shelf:nth-of-type(3) h2 span {
  background: linear-gradient(to top, #c8ecd2 0, #c8ecd2 42%, transparent 42%);
}

.shelf:nth-of-type(4) h2 span {
  background: linear-gradient(to top, #ffd3c8 0, #ffd3c8 42%, transparent 42%);
}

/* Adventures: every activity gets the same small heading, with space above
   each one after the first. */
h2.kind:not(:first-of-type) {
  margin-top: 2.75rem;
}

/* Adventures: one or two plain lines under each heading. */
.kind-line {
  margin: 0 0 1.1rem;
}

/* Adventures, laid out like a magazine spread: each section has its
   heading and line in a narrow left column and its photos and silent
   clips on the right, with place names set on the pictures. On narrow
   screens the heading sits above the pictures. */
.page.mag{max-width:1000px}
.sec>*{min-width:0}
.sec{display:grid;grid-template-columns:230px minmax(0,1fr);gap:44px;padding:2.4rem 0;border-top:1px solid var(--rule)}
.sec:first-of-type{border-top:0;padding-top:.6rem}
.sec .side{position:sticky;top:2rem;align-self:start}
.sec h2.kind{margin-top:0!important}
.sec .kind-line{margin-bottom:1rem}
.mos{display:grid;grid-template-columns:repeat(3,1fr);gap:10px}
.mt{position:relative;margin:0;border-radius:8px;overflow:hidden;background:var(--rule)}
.mt img,.mt video{display:block;width:100%;height:auto;aspect-ratio:4/5;object-fit:cover}
.mt.fill img,.mt.fill video{position:absolute;inset:0;height:100%;aspect-ratio:auto}
.mt.big{grid-column:span 2;grid-row:span 2}
.mt.wide{grid-column:span 2}
.mt figcaption{position:absolute;left:0;right:0;bottom:0;padding:1.6rem .7rem .55rem;color:#fff;font-family:var(--sans);font-size:.74rem;background:linear-gradient(to top,rgba(0,0,0,.5),transparent)}
.mos.four{grid-template-columns:repeat(2,1fr)}
.mos.two{grid-template-columns:repeat(2,1fr);max-width:480px}
.fb{display:flex;gap:10px}.fb img{display:block;min-width:0;height:auto;border-radius:8px}
.fb .w{flex:1.7778 1 0}.fb .t{flex:.5625 1 0}
@media (max-width:760px){.sec{grid-template-columns:minmax(0,1fr);gap:0;padding:1.8rem 0}.sec .side{position:static}.sec .side .strava{margin-bottom:1rem}.mos{grid-template-columns:repeat(2,1fr)}.mt.big{grid-column:span 2;grid-row:auto}.mt.big.fill img{position:static;aspect-ratio:4/5}.mt.wide{grid-column:span 1}.mt.wide.fill img{position:static;aspect-ratio:4/5}}

/* Placeholder under a heading whose photos are not added yet. */
.soon {
  margin: 0;
  color: var(--muted);
  font-style: italic;
  font-size: 1rem;
}

/* ---------- Event cards on touch screens ---------- */

/* When a card is flipped by a tap, its caption steps aside so the text on
   the back has the whole card; only the Luma button stays in the corner. */
@media (hover: none) {
  .tile .cap {
    transition: opacity 0.25s;
  }

  .tile input:checked ~ .cap {
    opacity: 0;
  }

  .mosaic .tile .back {
    padding-bottom: 2.9rem;
  }

  .mosaic .tile .back .desc {
    font-size: 0.86rem;
    line-height: 1.42;
  }

  .mosaic .tile.small .back {
    padding-bottom: 2.2rem;
  }
}

/* Bigger tap areas for the homepage links and contact icons on phones. */
@media (max-width: 760px) {
  .home .links a {
    display: inline-block;
    padding: 0.3rem 0;
  }

  .home .top-links.icons a {
    padding: 0.6rem;
    margin: -0.6rem 0;
  }

  .home .top-links.icons {
    gap: 0.2rem;
  }
}

/* ---------- Back link ---------- */

/* The link back at the top of every inner page: a soft pill whose arrow
   slides left on hover. */
.home-pill {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  margin-bottom: 2.5rem;
  padding: 0.35rem 0.9rem 0.35rem 0.75rem;
  border: 1px solid var(--rule);
  border-radius: 999px;
  color: var(--text);
  font-family: var(--sans);
  font-size: 0.85rem;
  font-weight: 600;
  text-decoration: none;
  transition: border-color 0.2s, background 0.2s;
}

.home-pill span {
  transition: transform 0.2s;
}

.home-pill:hover {
  border-color: var(--text);
  background: #fff;
}

.home-pill:hover span {
  transform: translateX(-3px);
}

/* On a flipped card the "Details" tag must not show through on the back
   (some phone browsers let it). Hide it, and the whole front face, while
   the card is flipped. */
.tile input:checked + .inner .tag {
  visibility: hidden;
}

@media (hover: none) {
  .tile input:checked + .inner .front {
    visibility: hidden;
    transition: visibility 0s 0.28s;
  }
}

/* ---------- Event cards at the reading-column width ---------- */

/* The wall now sits in the same 720px column as the rest of the site, so on
   a laptop the cards are smaller. Captions and the text on the backs scale
   down to fit. */
@media (min-width: 701px) {
  .tile .cap {
    left: 0.8rem;
    right: 0.8rem;
    font-size: 0.72rem;
  }

  .tile .cap strong {
    font-size: 1.15rem;
  }

  .tile.small .cap strong {
    font-size: 0.92rem;
  }

  .tile .back {
    padding: 0.85rem 0.95rem 3.1rem;
  }

  .tile .back .meta {
    margin-bottom: 0.4rem;
    font-size: 0.68rem;
  }

  .tile .back .desc {
    font-size: 0.82rem;
    line-height: 1.42;
  }

  .tile.small .back {
    padding: 0.6rem 0.65rem 2.6rem;
  }

  .tile.small .back .meta {
    font-size: 0.6rem;
  }

  .tile.small .back .desc {
    font-size: 0.66rem;
    line-height: 1.32;
  }

  /* Two cards carry longer text than their height allows at this size. */
  .t-beijing-2 .back .desc,
  .t-researcher-meetup .back .desc {
    font-size: 0.76rem;
    line-height: 1.36;
  }

  .tile .luma {
    right: 0.7rem;
    padding: 0.24rem 0.6rem;
    font-size: 0.7rem;
  }

  .tile.small .luma {
    right: 0.45rem;
    padding: 0.16rem 0.42rem;
    font-size: 0.62rem;
  }
}

/* A long caption never runs under the Luma button: it wraps instead. */
.tile:has(.luma) .cap {
  right: 4.6rem;
}

/* Narrow windows on a computer behave like phones: while a card is flipped
   its caption steps aside so the text on the back has room. */
@media (hover: hover) and (max-width: 700px) {
  .tile .cap {
    transition: opacity 0.25s;
  }

  .tile:hover .cap,
  .tile:focus-within .cap {
    opacity: 0;
  }

  .mosaic .tile .back {
    padding-bottom: 2.9rem;
  }

  .mosaic .tile .back .desc {
    font-size: 0.86rem;
    line-height: 1.42;
  }

  .mosaic .tile.small .back {
    padding-bottom: 2.2rem;
  }
}

/* ---------- Site background ---------- */

/* Three soft glows in the highlighter colours used on the Events and
   Library headings. They are painted on the page itself, at the top, so
   they scroll away with it and do not follow the reader down. */
html {
  background-color: var(--bg);
  background-image:
    radial-gradient(44rem 32rem at 84% -4vh, rgba(255, 224, 120, 0.55), transparent 64%),
    radial-gradient(40rem 32rem at -6% 40vh, rgba(186, 211, 255, 0.55), transparent 64%),
    radial-gradient(38rem 30rem at 100% 96vh, rgba(186, 232, 202, 0.5), transparent 64%);
  background-repeat: no-repeat;
}

body {
  background: transparent;
}

/* On phones the glows keep the same proportions as on a laptop: sized to
   the screen, tucked into the corners and fading out smoothly, so the
   reading area stays plain. */
@media (max-width: 760px) {
  html {
    background-image:
      radial-gradient(62vw 34vh at 104% -3vh, rgba(255, 224, 120, 0.36), transparent 72%),
      radial-gradient(72vw 40vh at -8% 40vh, rgba(172, 200, 255, 0.52), transparent 72%),
      radial-gradient(56vw 32vh at 122% 97vh, rgba(186, 232, 202, 0.3), transparent 72%);
  }
}

/* Homepage links on phones: three on the first row, two on the second. */
@media (max-width: 760px) {
  .home .links::after {
    content: "";
    flex-basis: 100%;
    order: 1;
  }

  .home .links li:nth-child(n + 4) {
    order: 2;
  }
}
