  :root {
    --paper:   #FCFCFD;
    --ink:     #171A21;
    --muted:   #616776;
    --line:    #E6E7ED;
    --accent:  #3A44A0;
    --ph-a:    #EEF0F7;
    --ph-b:    #E4E8F2;
    --ph-a2:   #F1EEF5;
    --ph-b2:   #E7ECF1;
    --ph-ink:  #9AA0B4;

    --serif: "Iowan Old Style", "Palatino Linotype", Palatino, "URW Palladio L", "Hoefler Text", Georgia, "Times New Roman", serif;
    --sans:  ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;

    --maxw-text: 40rem;
    --maxw-wide: 68rem;
    /* the gallery runs wider than the rest of the page: with a fixed two rows,
       width is the only thing left that makes the photos bigger */
    --maxw-gallery: 84rem;

    /* gallery elevation: resting / nudged out / lifted / hovered.
       On dark backgrounds a drop shadow is invisible, so the lifted states
       there carry a faint light ring instead - same depth cue, opposite tool. */
    --e0: 0 1px 2px rgba(20,24,40,0.05);
    --e1: 0 14px 30px -16px rgba(20,24,50,0.40);
    --e2: 0 26px 50px -22px rgba(20,24,50,0.50);
    --e3: 0 26px 46px -22px rgba(20,24,50,0.45);
  }

  @media (prefers-color-scheme: dark) {
    :root {
      --e0: 0 1px 3px rgba(0,0,0,0.55);
      --e1: 0 16px 32px -14px rgba(0,0,0,0.85), 0 0 0 1px rgba(255,255,255,0.06);
      --e2: 0 28px 54px -18px rgba(0,0,0,0.92), 0 0 0 1px rgba(255,255,255,0.10);
      --e3: 0 28px 50px -18px rgba(0,0,0,0.92), 0 0 0 1px rgba(255,255,255,0.13);
    }
  }
  :root[data-theme="light"] {
    --e0: 0 1px 2px rgba(20,24,40,0.05);
    --e1: 0 14px 30px -16px rgba(20,24,50,0.40);
    --e2: 0 26px 50px -22px rgba(20,24,50,0.50);
    --e3: 0 26px 46px -22px rgba(20,24,50,0.45);
  }
  :root[data-theme="dark"] {
    --e0: 0 1px 3px rgba(0,0,0,0.55);
    --e1: 0 16px 32px -14px rgba(0,0,0,0.85), 0 0 0 1px rgba(255,255,255,0.06);
    --e2: 0 28px 54px -18px rgba(0,0,0,0.92), 0 0 0 1px rgba(255,255,255,0.10);
    --e3: 0 28px 50px -18px rgba(0,0,0,0.92), 0 0 0 1px rgba(255,255,255,0.13);
  }

  @media (prefers-color-scheme: dark) {
    :root {
      --paper:  #0D0F13;
      --ink:    #ECEEF3;
      --muted:  #9096A6;
      --line:   #23272F;
      --accent: #9AA2EC;
      --ph-a:   #171A22;
      --ph-b:   #1E2230;
      --ph-a2:  #1C1A24;
      --ph-b2:  #191E27;
      --ph-ink: #565D70;
    }
  }
  :root[data-theme="light"] {
    --paper:#FCFCFD; --ink:#171A21; --muted:#616776; --line:#E6E7ED; --accent:#3A44A0;
    --ph-a:#EEF0F7; --ph-b:#E4E8F2; --ph-a2:#F1EEF5; --ph-b2:#E7ECF1; --ph-ink:#9AA0B4;
  }
  :root[data-theme="dark"] {
    --paper:#0D0F13; --ink:#ECEEF3; --muted:#9096A6; --line:#23272F; --accent:#9AA2EC;
    --ph-a:#171A22; --ph-b:#1E2230; --ph-a2:#1C1A24; --ph-b2:#191E27; --ph-ink:#565D70;
  }

  * { box-sizing: border-box; }
  html { -webkit-text-size-adjust: 100%; }
  body { margin: 0; }

  .page {
    background: var(--paper);
    color: var(--ink);
    font-family: var(--serif);
    min-height: 100vh;
    padding: clamp(2.5rem, 6vw, 5.5rem) clamp(1.25rem, 5vw, 3rem) 4rem;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: clamp(3.5rem, 8vw, 6.5rem);
    overflow-x: hidden;
  }

  /* ---------- Hero ---------- */
  .hero {
    text-align: center;
    max-width: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1.4rem;
  }
  .hero h1 {
    margin: 0;
    font-family: var(--sans);
    font-weight: 500;
    font-size: clamp(0.9rem, 2.1vw, 1.2rem);
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--muted);
    white-space: nowrap;
  }
  .lede {
    margin: 0;
    font-weight: 500;
    font-size: clamp(2.2rem, 8vw, 5.6rem);
    line-height: 1.02;
    letter-spacing: -0.02em;
    color: var(--ink);
    white-space: nowrap;
  }
  .rule {
    width: 3.25rem;
    height: 1px;
    background: var(--line);
    margin-top: 0.4rem;
  }

  /* ---------- Gallery ---------- */
  .gallery {
    width: 100%;
    max-width: var(--maxw-gallery);
    display: flex;
    flex-wrap: wrap;
    /* one value, so the vertical and horizontal gutters are always identical */
    gap: clamp(0.6rem, 1.2vw, 1.1rem);
    justify-content: flex-start;
    align-items: flex-start;
  }
  .photo:has(.ph) { width: clamp(150px, 22vw, 230px); height: 190px; flex: 0 0 auto; }
  .photo {
    /* Jigsaw offsets. These only ever MOVE a piece, never resize it - a scaled
       piece grows into its gutters and crowds its neighbours, which is exactly
       what went wrong before. Every gutter stays the gallery's one gap value. */
    --dx: 0px;      /* how far this piece is pulled sideways */
    --dy: 0px;      /* how far it is pulled up or down       */
    position: relative;
    margin: 0;
    border-radius: 12px;
    overflow: hidden;
    background: linear-gradient(135deg, var(--ph-a), var(--ph-b));
    box-shadow: var(--e0);
    transform: translate(var(--dx), var(--dy));
    transition: transform 0.55s cubic-bezier(.2,.7,.2,1), box-shadow 0.55s cubic-bezier(.2,.7,.2,1);
  }
  /* pieces nudged out of the block read as detached from it */
  .photo.out  { box-shadow: var(--e1); z-index: 2; }
  .photo:nth-child(even) { background: linear-gradient(135deg, var(--ph-a2), var(--ph-b2)); }
  .photo:nth-child(3n)   { background: linear-gradient(200deg, var(--ph-a), var(--ph-b2)); }
  .photo img { width: 100%; height: 100%; object-fit: cover; display: block; }

  .photo .ph {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    color: var(--ph-ink);
    font-family: var(--sans);
    letter-spacing: 0.12em;
    text-transform: uppercase;
    font-size: 0.62rem;
  }
  .photo .ph svg { width: 22px; height: 22px; opacity: 0.8; }

  .photo:hover {
    transform: translate(var(--dx), calc(var(--dy) - 7px));
    box-shadow: var(--e3);
    z-index: 6;
  }

  /* Photo layout is generated by build.py based on how many images are in photos/ */

  /* ---------- About ---------- */
  .about {
    max-width: 34rem;
    text-align: center;
  }
  .about p {
    margin: 0;
    font-size: clamp(1.12rem, 2.2vw, 1.4rem);
    line-height: 1.7;
    color: var(--ink);
  }
  .about .quiet { color: var(--muted); }

  /* ---------- Links ---------- */
  .links {
    width: 100%;
    max-width: var(--maxw-wide);
    border-top: 1px solid var(--line);
    padding-top: clamp(2rem, 4vw, 3rem);
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    align-items: center;
    gap: clamp(1.5rem, 5vw, 4rem);
  }

  /* ---------- Social icons ---------- */
  .social { display: inline-flex; align-items: center; gap: 0.4rem; }
  .icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.4rem;
    height: 2.4rem;
    border-radius: 999px;
    color: var(--muted);
    transition: color 0.35s ease, transform 0.35s cubic-bezier(.2,.7,.2,1);
  }
  .icon svg { width: 1.35rem; height: 1.35rem; display: block; }
  .icon:hover, .icon:focus-visible { color: var(--accent); transform: translateY(-2px); outline: none; }
  .icon:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

  .link {
    position: relative;
    text-decoration: none;
    color: var(--ink);
    font-family: var(--sans);
    font-size: 1rem;
    letter-spacing: 0.02em;
    display: inline-flex;
    align-items: baseline;
    gap: 0.4rem;
    padding-bottom: 0.3rem;
    transition: color 0.35s ease;
  }
  .link .arw {
    font-size: 0.85em;
    color: var(--muted);
    transition: transform 0.35s cubic-bezier(.2,.7,.2,1), color 0.35s ease;
  }
  .link::after {
    content: "";
    position: absolute;
    left: 0; bottom: 0;
    width: 100%; height: 1px;
    background: var(--accent);
    transform: scaleX(0);
    transform-origin: left;
    transition: transform 0.4s cubic-bezier(.2,.7,.2,1);
  }
  .link:hover, .link:focus-visible { color: var(--accent); outline: none; }
  .link:hover .arw, .link:focus-visible .arw { transform: translate(2px, -2px); color: var(--accent); }
  .link:hover::after, .link:focus-visible::after { transform: scaleX(1); }
  .link:focus-visible { outline: 2px solid var(--accent); outline-offset: 6px; border-radius: 2px; }

  /* ---------- Footer ---------- */
  .foot {
    font-family: var(--sans);
    font-size: 0.72rem;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--muted);
    opacity: 0.75;
  }

  /* ---------- Motion ---------- */
  .reveal { opacity: 1; }
  @media (prefers-reduced-motion: no-preference) {
    .reveal { animation: rise 0.9s cubic-bezier(.2,.7,.2,1) both; }
    /* `backwards`, not `both`: once the piece lands, its normal style takes
       over again so the jigsaw offsets and :hover still apply. */
    .gallery .photo { animation: pop 0.7s cubic-bezier(.2,.7,.2,1) backwards; }
    .gallery .photo:nth-child(1) { animation-delay: 0.30s; }
    .gallery .photo:nth-child(2) { animation-delay: 0.37s; }
    .gallery .photo:nth-child(3) { animation-delay: 0.44s; }
    .gallery .photo:nth-child(4) { animation-delay: 0.51s; }
    .gallery .photo:nth-child(5) { animation-delay: 0.58s; }
    .gallery .photo:nth-child(6) { animation-delay: 0.65s; }
    .gallery .photo:nth-child(7) { animation-delay: 0.72s; }
    .about  { animation-delay: 0.15s; }
    .links  { animation-delay: 0.25s; }
    .foot   { animation-delay: 0.35s; }
  }
  @keyframes rise { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: none; } }
  /* each piece drops into its slot, offsets and all */
  @keyframes pop {
    from { opacity: 0; transform: translate(var(--dx), calc(var(--dy) + 24px)); }
    to   { opacity: 1; transform: translate(var(--dx), var(--dy)); }
  }

  /* ---------- Quotes page ---------- */
  /* A smaller display line for interior pages - the home page lede is sized
     for two words and set nowrap, which a page title would overflow. */
  .lede.sm {
    font-size: clamp(1.9rem, 5vw, 3.4rem);
    white-space: normal;
  }
  .quotes {
    width: 100%;
    max-width: 44rem;
    display: flex;
    flex-direction: column;
    gap: clamp(2.4rem, 5vw, 3.6rem);
  }
  .quote {
    margin: 0;
    padding-left: clamp(0.9rem, 2vw, 1.4rem);
    border-left: 2px solid var(--line);
  }
  .quote p {
    margin: 0;
    font-size: clamp(1.2rem, 2.5vw, 1.6rem);
    line-height: 1.55;
    color: var(--ink);
  }
  .quote .who {
    display: block;
    margin-top: 0.75rem;
    font-family: var(--sans);
    font-size: 0.74rem;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--muted);
  }
  @media (prefers-reduced-motion: no-preference) {
    .quotes .quote { animation: rise 0.8s cubic-bezier(.2,.7,.2,1) backwards; }
    .quotes .quote:nth-child(1) { animation-delay: 0.20s; }
    .quotes .quote:nth-child(2) { animation-delay: 0.28s; }
    .quotes .quote:nth-child(3) { animation-delay: 0.36s; }
    .quotes .quote:nth-child(4) { animation-delay: 0.44s; }
    .quotes .quote:nth-child(5) { animation-delay: 0.52s; }
    .quotes .quote:nth-child(6) { animation-delay: 0.60s; }
    .quotes .quote:nth-child(n+7) { animation-delay: 0.68s; }
  }

  /* ---------- Books page ---------- */
  .shelf {
    width: 100%;
    max-width: 46rem;
    display: flex;
    flex-direction: column;
    gap: clamp(2.4rem, 5vw, 3.4rem);
  }
  .shelf-head {
    margin: 0 0 1.1rem;
    font-family: var(--sans);
    font-weight: 500;
    font-size: 0.74rem;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--muted);
    padding-bottom: 0.6rem;
    border-bottom: 1px solid var(--line);
  }
  .books { list-style: none; margin: 0; padding: 0; }
  .book {
    padding: 0.72rem 0;
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.15rem 0.7rem;
  }
  .book .title {
    font-size: clamp(1.2rem, 2.4vw, 1.55rem);
    line-height: 1.4;
    color: var(--ink);
  }
  .book .by {
    font-family: var(--sans);
    font-size: 0.88rem;
    color: var(--muted);
    white-space: nowrap;
  }
  /* keep the tilde the doc is written with, as the visible separator */
  .book .by::before {
    content: "~";
    margin-right: 0.45rem;
    opacity: 0.65;
  }
  @media (prefers-reduced-motion: no-preference) {
    .shelf .shelf-group { animation: rise 0.8s cubic-bezier(.2,.7,.2,1) backwards; }
    .shelf .shelf-group:nth-child(1) { animation-delay: 0.20s; }
    .shelf .shelf-group:nth-child(2) { animation-delay: 0.28s; }
    .shelf .shelf-group:nth-child(3) { animation-delay: 0.36s; }
    .shelf .shelf-group:nth-child(4) { animation-delay: 0.44s; }
    .shelf .shelf-group:nth-child(n+5) { animation-delay: 0.52s; }
  }

  /* ---------- Back to home (top + bottom of interior pages) ---------- */
  .topbar {
    width: 100%;
    max-width: var(--maxw-gallery);
    display: flex;
    justify-content: flex-start;
    /* .topbar carries .reveal, whose animation composites it into its own
       stacking context - so the menu's z-index is scoped INSIDE it and later
       siblings would paint over the dropdown. Lift the whole bar instead. */
    position: relative;
    z-index: 70;
    /* pull the hero back up: the page's section gap is far too large here */
    margin-bottom: calc(-1 * clamp(1.75rem, 4.5vw, 3.5rem));
  }
  .backbar {
    width: 100%;
    max-width: var(--maxw-wide);
    border-top: 1px solid var(--line);
    padding-top: clamp(2rem, 4vw, 3rem);
    display: flex;
    justify-content: center;
  }
  .back {
    display: inline-flex;
    align-items: center;
    gap: 0.55rem;
    font-family: var(--sans);
    font-size: 0.95rem;
    font-weight: 500;
    letter-spacing: 0.01em;
    color: var(--ink);
    text-decoration: none;
    padding: 0.62rem 1.25rem;
    border: 1px solid var(--line);
    border-radius: 999px;
    background: transparent;
    transition: color 0.3s ease, border-color 0.3s ease, background-color 0.3s ease;
  }
  .back .arw {
    font-size: 1.05em;
    line-height: 1;
    transition: transform 0.3s cubic-bezier(.2,.7,.2,1);
  }
  .back:hover, .back:focus-visible {
    color: var(--accent);
    border-color: var(--accent);
    outline: none;
  }
  .back:hover .arw, .back:focus-visible .arw { transform: translateX(-3px); }
  .back:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

  /* ==================================================================
     MOBILE (<=640px) - a different layout, not a squeezed desktop one.
     Same markup throughout: the page is a flex column, so the sections
     are simply reordered with `order` rather than duplicated.
     ================================================================== */
  @media (max-width: 640px) {
    .page {
      gap: 2.25rem;
      padding-top: 1.5rem;
    }

    /* links move to the very top, above the name */
    .links  { order: 1; }
    .hero   { order: 2; }
    .gallery{ order: 3; }
    .about  { order: 4; }
    .foot   { order: 5; }

    .links {
      border-top: 0;
      border-bottom: 1px solid var(--line);
      padding-top: 0;
      padding-bottom: 1.1rem;
      gap: 0.9rem 1.4rem;
      row-gap: 0.6rem;
    }
    .link { font-size: 0.9rem; padding-bottom: 0.15rem; }
    /* text links share the first line; the icons always get their own */
    .social { flex-basis: 100%; justify-content: center; gap: 0.1rem; }
    .icon { width: 2.1rem; height: 2.1rem; }
    .icon svg { width: 1.25rem; height: 1.25rem; }

    .hero { gap: 0.9rem; }
    .lede {
      white-space: normal;          /* let the title wrap instead of overflowing */
      font-size: clamp(2rem, 10.5vw, 3rem);
      line-height: 1.05;
    }
    .hero h1 { font-size: 0.82rem; letter-spacing: 0.18em; }

    /* --- the photos: ALL of them at once, in the same 4 + 3 block as the
       desktop. Small is fine - tapping one opens it full screen. --- */
    .gallery {
      width: 100vw;
      max-width: 100vw;
      margin-inline: calc(50% - 50vw);   /* break out of the page padding */
      padding-inline: 0.75rem;
      gap: 0.3rem;
    }
    .photo { border-radius: 8px; }
    /* the jigsaw offsets are far too large relative to a 90px photo */
    .photo.out { box-shadow: var(--e0); z-index: auto; }
    .photo:hover { transform: translate(var(--dx), var(--dy)); box-shadow: var(--e0); }

    .about { max-width: 100%; }
    .about p { font-size: 1.08rem; line-height: 1.65; }

    /* interior pages */
    .topbar { margin-bottom: -0.75rem; }
    .back { font-size: 0.9rem; padding: 0.55rem 1.05rem; }
    .quotes, .shelf { gap: 2rem; }
    .quote p { font-size: 1.12rem; }
    .book .title { font-size: 1.12rem; }
    .book .by { white-space: normal; }
  }

  /* ---------- Lightbox (tap a photo to see it big) ---------- */
  .photo { cursor: zoom-in; }
  .lightbox {
    position: fixed;
    inset: 0;
    z-index: 100;
    display: none;
    align-items: center;
    justify-content: center;
    padding: clamp(0.75rem, 3vw, 2.5rem);
    background: rgba(8, 10, 14, 0.98);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    -webkit-tap-highlight-color: transparent;
  }
  .lightbox.open { display: flex; }
  .lightbox img {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;          /* the whole photo, never cropped */
    border-radius: 6px;
    box-shadow: 0 30px 70px -30px rgba(0,0,0,0.9);
  }
  .lb-btn {
    position: absolute;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.9rem;
    height: 2.9rem;
    border: 1px solid rgba(255,255,255,0.22);
    border-radius: 999px;
    background: rgba(255,255,255,0.06);
    color: #fff;
    font-family: var(--sans);
    font-size: 1.15rem;
    line-height: 1;
    cursor: pointer;
    transition: background-color 0.25s ease, border-color 0.25s ease;
  }
  .lb-btn:hover, .lb-btn:focus-visible {
    background: rgba(255,255,255,0.16);
    border-color: rgba(255,255,255,0.5);
    outline: none;
  }
  .lb-close { top: clamp(0.75rem, 3vw, 1.5rem); right: clamp(0.75rem, 3vw, 1.5rem); }
  .lb-prev  { left:  clamp(0.5rem, 2vw, 1.5rem); top: 50%; transform: translateY(-50%); }
  .lb-next  { right: clamp(0.5rem, 2vw, 1.5rem); top: 50%; transform: translateY(-50%); }
  .lb-count {
    position: absolute;
    bottom: clamp(0.9rem, 3vw, 1.6rem);
    left: 50%;
    transform: translateX(-50%);
    font-family: var(--sans);
    font-size: 0.78rem;
    letter-spacing: 0.14em;
    color: rgba(255,255,255,0.65);
  }
  @media (max-width: 640px) {
    .lb-prev, .lb-next { display: none; }   /* swipe instead */
  }

  /* ---------- Page menu (hamburger + dropdown) ----------
     Phone only: the desktop keeps its inline row of links at the foot of the
     page, which is fine there and already familiar. */
  .topnav { display: none; }
  .menu-btn {
    width: 2.7rem;
    height: 2.7rem;
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 5px;
    padding: 0;
    border: 1px solid var(--line);
    border-radius: 12px;
    background: transparent;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
  }
  .menu-btn span {
    display: block;
    width: 18px;
    height: 1.6px;
    border-radius: 2px;
    background: var(--ink);
    transition: transform 0.3s cubic-bezier(.2,.7,.2,1), opacity 0.2s ease;
  }
  .menu-btn[aria-expanded="true"] span:nth-child(1) { transform: translateY(6.6px) rotate(45deg); }
  .menu-btn[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
  .menu-btn[aria-expanded="true"] span:nth-child(3) { transform: translateY(-6.6px) rotate(-45deg); }
  .menu-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

  .menu {
    position: absolute;
    top: calc(100% + 0.55rem);
    right: 0;
    z-index: 60;
    min-width: 15rem;
    display: flex;
    flex-direction: column;
    padding: 0.4rem;
    background: var(--paper);
    border: 1px solid var(--line);
    border-radius: 14px;
    box-shadow: var(--e2);
  }
  .menu[hidden] { display: none; }
  .menu a {
    font-family: var(--sans);
    font-size: 1rem;
    color: var(--ink);
    text-decoration: none;
    padding: 0.78rem 0.9rem;
    border-radius: 9px;
    transition: background-color 0.2s ease, color 0.2s ease;
  }
  .menu a:hover, .menu a:focus-visible {
    background: var(--ph-a);
    color: var(--accent);
    outline: none;
  }

  @media (max-width: 640px) {
    .topnav {
      display: flex;
      justify-content: flex-end;
      width: 100%;
      position: relative;
      /* the sibling sections animate opacity/transform, which composites them
         into their own stacking contexts - without a z-index here the dropdown
         renders UNDERNEATH the hero text */
      z-index: 70;
    }
    /* home page: the menu is the first thing on the page */
    .page > .topnav { order: 1; }

    /* the text links live in the hamburger now; only the icons stay below */
    .links .link { display: none; }
    .links {
      order: 5;
      border-top: 1px solid var(--line);
      border-bottom: 0;
      padding-top: 1.4rem;
      padding-bottom: 0;
    }
    .foot { order: 6; }

    /* interior pages: back button left, menu right, on one line */
    .topbar { justify-content: space-between; align-items: center; }
    .topbar .topnav { width: auto; }
  }
