/* =========================================================
   main.css -- the ONLY stylesheet for this site.

   Everything you're likely to want to change lives in the :root
   block right below this comment. Nothing else in the file needs
   editing for a basic restyle.

   QUICK REFERENCE
   ----------------
   Colors
     --color-bg            page background (warm off-white)
     --color-bg-raised      modal / card surfaces (a touch whiter than bg)
     --color-ink            main text color (near-black)
     --color-muted          secondary text (captions, dates, footer)
     --color-accent         links, buttons, hover states, focus rings
     --color-accent-hover   accent on :hover (a shade darker)
     --color-border         hairline borders, dividers, placeholders

   Type
     --font-display   headings / titles -- a serif (Fraunces)
     --font-body       body copy, nav, buttons -- a sans (Inter)
     --font-size-*     the type scale, smallest to largest
     --line-height     body copy line spacing

   Spacing
     --space-*   one spacing scale used everywhere (xs..xl), so
                 padding/margin/gap stay consistent site-wide

   Layout
     --content-max-width   how wide the page ever gets
     --gallery-min-tile    smallest a gallery thumbnail is allowed to get
                            before the grid drops to fewer columns
     --gallery-ratio       the aspect ratio every gallery thumbnail is
                            cropped to (object-fit: cover), so tiles
                            line up evenly regardless of source image size
     --modal-max-width     how wide the project modal gets on desktop

   See docs/guides/00-how-hugo-works-here.md, section "Changing colors
   & fonts", for a longer walkthrough (including how to swap the
   Google Fonts).
   ========================================================= */

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

html,
body,
h1,
h2,
h3,
h4,
p,
figure,
ul,
ol {
  margin: 0;
  padding: 0;
}

ul,
ol {
  list-style: none;
}

img,
video {
  display: block;
  max-width: 100%;
  height: auto;
}

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

::selection {
  background: var(--color-accent);
  color: var(--color-bg-raised);
}

/* ---- Design tokens ---- */
:root {
  /* This site is deliberately light-only rather than also shipping a
     dark palette -- the warm off-white/ink pairing is the point. Every
     color below is still set explicitly (never left to browser
     defaults), and this tells the browser chrome (scrollbars, form
     controls) to render light too. */
  color-scheme: light;

  /* Colors */
  --color-bg: #faf8f5;
  --color-bg-raised: #ffffff;
  --color-ink: #1b1a17;
  --color-text: var(--color-ink);
  --color-muted: #6b6558;
  --color-accent: #a8593f;
  --color-accent-hover: #8c4630;
  --color-border: #e6e1d8;
  --color-border-strong: #d8cfc0;
  --color-overlay: rgba(27, 22, 18, 0.55);

  /* Spacing scale */
  --space-3xs: 0.25rem;
  --space-2xs: 0.5rem;
  --space-xs: 0.75rem;
  --space-sm: 1.25rem;
  --space-md: 2rem;
  --space-lg: 3.5rem;
  --space-xl: 6rem;

  /* Type -- a serif for headings/display, a clean sans for body copy.
     Loaded via Google Fonts in layouts/partials/head.html. Real
     fallback stacks so the page still looks intentional if the web
     font is blocked or slow. */
  --font-display: "Fraunces", Georgia, "Times New Roman", serif;
  --font-body:
    "Inter", -apple-system, BlinkMacSystemFont, "Helvetica Neue", Arial,
    sans-serif;

  --font-size-xs: 0.8125rem;
  --font-size-sm: 0.9375rem;
  --font-size-base: 1.0625rem;
  --font-size-lg: 1.25rem;
  --font-size-h2: 1.5rem;
  --font-size-h1: clamp(2rem, 1.65rem + 1.5vw, 2.75rem);
  --font-size-display: clamp(1.6rem, 1.35rem + 1vw, 2.1rem);

  --line-height: 1.65;
  --line-height-tight: 1.2;
  --measure: 34rem;

  /* Layout */
  --content-max-width: 76rem;

  /* Gallery */
  --gallery-gap: var(--space-sm);
  --gallery-min-tile: 15rem;
  --gallery-ratio: 4 / 5;
  --gallery-overlay-bg: linear-gradient(
    to top,
    rgba(27, 22, 18, 0.82),
    rgba(27, 22, 18, 0) 68%
  );
  --gallery-caption-color: #faf8f5;

  /* Motion */
  --transition-fast: 0.18s ease;
  --transition: 0.4s cubic-bezier(0.22, 0.61, 0.36, 1);

  /* Modal */
  --modal-max-width: 50rem;

  /* Juliette's style */
  --animation-duration: 60s;
  --quick-animation-duration: 6s;
  --animation-count: infinite;
  --not-black: #333;
  --not-white: #fcfcfc;
  --outline: 2px solid var(--not-black);
  --light-blue: #f0f8ff;
  --dark-blue: #b6cecf;
  --text-blue: #1d5f63;
  --light-pink: #fff0ff;
  --dark-pink: #c3b6cf;
  --text-pink: #431e66;
  --light-orange: #fff7f0;
  --dark-orange: #cfb7b6;
  --text-orange: #66211e;
  --light-green: #f0fff0;
  --dark-green: #c2cfb6;
  --text-green: #335219;
}

/* Juliette's style */
@keyframes background-palette {
  0% {
    background: var(--light-blue);
  }
  25% {
    background: var(--light-pink);
  }
  50% {
    background: var(--light-orange);
  }
  75% {
    background: var(--light-green);
  }
  100% {
    background: var(--light-blue);
  }
}

@keyframes active-palette {
  0% {
    background: var(--dark-blue);
  }
  25% {
    background: var(--dark-pink);
  }
  50% {
    background: var(--dark-orange);
  }
  75% {
    background: var(--dark-green);
  }
  100% {
    background: var(--dark-blue);
  }
}

@keyframes highlight {
  0% {
    color: var(--text-blue);
  }
  25% {
    color: var(--text-pink);
  }
  50% {
    color: var(--text-orange);
  }
  75% {
    color: var(--text-green);
  }
  100% {
    color: var(--text-blue);
  }
}

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

body {
  background: var(--color-bg);
  color: var(--color-text);
  font-family: var(--font-body);
  font-size: var(--font-size-base);
  line-height: var(--line-height);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;

  /* Juliette's style */
  animation-name: background-palette;
  @media (prefers-color-scheme: dark) {
    animation-name: active-palette;
  }
  animation-duration: var(--animation-duration);
  animation-iteration-count: var(--animation-count);
}

.fake-3d {
  border: 0px solid var(--not-black);
  border-bottom-width: medium;
  border-right-width: medium;
}

h1,
h2,
h3,
h4 {
  font-family: var(--font-display);
  font-weight: 500;
  line-height: var(--line-height-tight);
  color: var(--color-ink);
}

h1 {
  font-size: var(--font-size-h1);
  letter-spacing: -0.01em;
}

h2 {
  font-size: var(--font-size-h2);
}

a {
  text-underline-offset: 0.2em;
}

:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

/* ---- Header ---- */
.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: rgba(250, 248, 245, 0.9);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--color-border);
}

.site-header-inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-sm);
  max-width: var(--content-max-width);
  margin: 0 auto;
  padding: var(--space-xs) var(--space-md);
}

.site-title {
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 500;
  font-size: 1.15rem;
  color: var(--color-ink);
}

/* Wraps the main nav + language switch so both can be hidden together
   behind the hamburger toggle below --nav-collapse (see media query
   near the bottom of the Header section). On desktop this is just a
   flex row that fills the space next to the site title. */
.nav-panel {
  display: flex;
  flex: 1 1 auto;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: var(--space-md);
}

/* Hamburger button -- hidden until the mobile breakpoint. */
.nav-toggle {
  display: none;
  align-items: center;
  gap: var(--space-2xs);
  padding: var(--space-3xs) var(--space-2xs);
  border: 1px solid var(--color-border-strong);
  border-radius: 3px;
  background: none;
  font: inherit;
  font-size: var(--font-size-xs);
  letter-spacing: 0.02em;
  color: var(--color-ink);
  cursor: pointer;
}

.nav-toggle:hover,
.nav-toggle:focus-visible {
  border-color: var(--color-accent);
  color: var(--color-accent);
}

.nav-toggle-bars,
.nav-toggle-bars::before,
.nav-toggle-bars::after {
  display: block;
  width: 1.1rem;
  height: 2px;
  background: currentColor;
  border-radius: 1px;
}

.nav-toggle-bars {
  position: relative;
}

.nav-toggle-bars::before,
.nav-toggle-bars::after {
  content: "";
  position: absolute;
  left: 0;
}

.nav-toggle-bars::before {
  top: -0.35rem;
}

.nav-toggle-bars::after {
  top: 0.35rem;
}

.site-nav ul {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-sm);
}

.site-nav a {
  position: relative;
  padding: var(--space-3xs) 0;
  font-size: var(--font-size-sm);
  text-transform: lowercase;
  letter-spacing: 0.02em;
  color: var(--color-ink);
  transition: color var(--transition-fast);
}

.site-nav a::after {
  content: "";
  position: absolute;
  left: 0;
  right: 100%;
  bottom: -2px;
  height: 1px;
  background: var(--color-accent);
  transition: right var(--transition-fast);
}

.site-nav a:hover,
.site-nav a:focus-visible {
  color: var(--color-accent);
}

.site-nav a:hover::after,
.site-nav a:focus-visible::after,
.site-nav a.is-active::after {
  right: 0;
}

.site-nav a.is-active {
  color: var(--color-accent);
}

.lang-switch {
  display: flex;
  gap: var(--space-2xs);
  font-size: var(--font-size-xs);
  letter-spacing: 0.04em;
}

.lang-switch a {
  color: var(--color-muted);
  transition: color var(--transition-fast);
}

.lang-switch a:hover,
.lang-switch a:focus-visible {
  color: var(--color-accent);
}

.lang-current {
  font-weight: 600;
  color: var(--color-ink);
}

/* Below this width the nav + language switch don't comfortably fit
   next to the site title on one line (5 nav items + 2 languages), so
   they collapse behind a hamburger button instead of wrapping/
   overflowing. Toggle behavior: assets/js/main.js, "Mobile nav
   toggle". To change where this kicks in, edit this one value. */
@media (max-width: 40rem) {
  .nav-toggle {
    display: inline-flex;
  }

  .nav-panel {
    display: none;
    flex-basis: 100%;
    flex-direction: column;
    align-items: stretch;
    gap: var(--space-sm);
    padding-top: var(--space-2xs);
  }

  .nav-panel.is-open {
    display: flex;
  }

  .site-nav ul {
    flex-direction: column;
    gap: var(--space-xs);
  }

  .lang-switch {
    gap: var(--space-xs);
  }
}

/* ---- Main content ---- */
main {
  max-width: var(--content-max-width);
  margin: 0 auto;
  padding: 0 var(--space-md) var(--space-xl);
}

.home-section {
  padding-top: var(--space-xl);
  scroll-margin-top: 5rem;
}

.home-section:first-of-type {
  padding-top: var(--space-lg);
}

.home-section-title {
  margin-bottom: var(--space-2xs);
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 400;
  font-size: var(--font-size-display);
  text-transform: lowercase;
  letter-spacing: 0.01em;
  color: var(--color-ink);
}

.home-section-intro {
  max-width: var(--measure);
  margin-bottom: var(--space-md);
  color: var(--color-muted);
}

.home-section-empty {
  color: var(--color-muted);
  font-size: var(--font-size-sm);
}

/* ---- Gallery grid (thumbnail tiles, title on hover) ---- */
.gallery-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--gallery-gap);
}

@media (min-width: 30rem) {
  .gallery-grid {
    grid-template-columns: repeat(
      auto-fill,
      minmax(var(--gallery-min-tile), 1fr)
    );
  }
}

.gallery-cell {
  min-width: 0;
}

.gallery-item {
  position: relative;
  display: block;
  width: 100%;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
}

.gallery-item:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 3px;
}

/* The frame is the positioning context for the caption overlay and clips
   the image's hover-zoom to a rounded rectangle. */
.gallery-thumb-frame {
  position: relative;
  display: block;
  width: 100%;
  overflow: hidden;
  border-radius: 3px;
  background: var(--color-border);
}

.gallery-thumb {
  display: block;
  width: 100%;
  aspect-ratio: var(--gallery-ratio);
  object-fit: cover;
  transition:
    transform var(--transition),
    filter var(--transition-fast);
}

.gallery-thumb--placeholder {
  aspect-ratio: var(--gallery-ratio);
}

.gallery-item:hover .gallery-thumb,
.gallery-item:focus-visible .gallery-thumb {
  transform: scale(1.04);
  filter: brightness(0.82);
}

/* Ailie-Fraser style: the title sits over the image on a translucent
   scrim so it stays legible over any thumbnail; on hover the image
   darkens behind it, deepening the scrim and signalling which tile
   you're pointing at. */
.gallery-caption {
  position: absolute;
  inset: auto 0 0 0;
  padding: var(--space-md) var(--space-xs) var(--space-xs);
  background: var(--gallery-overlay-bg);
  color: var(--gallery-caption-color);
  font-family: var(--font-display);
  font-style: italic;
  font-size: 1.05rem;
  line-height: 1.3;
}

.single-page,
.list-page {
  padding-top: var(--space-lg);
}

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

/* ---- About page ---- */
.about-page {
  max-width: var(--measure);
}

.about-header {
  margin-bottom: var(--space-md);
}

.about-photo {
  width: 12rem;
  height: 12rem;
  object-fit: cover;
  border-radius: 6px;
  margin-bottom: var(--space-sm);
}

.about-body p {
  margin-bottom: var(--space-sm);
  color: var(--color-text);
}

.about-photo-secondary {
  width: 9rem;
  border-radius: 6px;
  margin-top: var(--space-lg);
}

/* ---- CV page ---- */
.cv-download {
  display: inline-flex;
  align-items: center;
  padding: 0.7rem 1.4rem;
  margin: var(--space-xs) 0 var(--space-lg);
  border: 1px solid var(--color-accent);
  border-radius: 4px;
  color: var(--color-accent);
  font-weight: 600;
  font-size: 0.95rem;
  transition:
    background var(--transition-fast),
    color var(--transition-fast);
}

.cv-download:hover {
  background: var(--color-accent);
  color: var(--color-bg-raised);
}

.cv-note {
  margin-top: calc(-1 * var(--space-md));
  margin-bottom: var(--space-lg);
  color: var(--color-muted);
  font-size: 0.85rem;
}

.cv-content {
  max-width: none;
}

.cv-content h2 {
  margin: var(--space-lg) 0 var(--space-sm);
  font-size: 1.4rem;
  font-weight: 500;
}

.cv-content h2:first-child {
  margin-top: 0;
}

.cv-content h3 {
  margin: var(--space-sm) 0 var(--space-xs);
  font-family: var(--font-body);
  font-size: 1rem;
  font-weight: 600;
}

.cv-content hr {
  border: 0;
  border-top: 1px solid var(--color-border);
  margin: var(--space-md) 0;
}

.cv-content a {
  color: var(--color-accent);
  text-decoration: underline;
}

.cv-content table {
  display: block;
  overflow-x: auto;
  width: 100%;
  border-collapse: collapse;
  margin-bottom: var(--space-sm);
  font-size: 0.95rem;
}

.cv-content th,
.cv-content td {
  padding: 0.5rem 0.75rem 0.5rem 0;
  text-align: left;
  vertical-align: top;
  border-bottom: 1px solid var(--color-border);
}

.cv-content table table {
  display: table;
  overflow: visible;
  margin: 0.25rem 0 0;
}

.cv-content table table th,
.cv-content table table td {
  padding: 0.15rem 0.5rem 0.15rem 0;
  border: 0;
}

/* ---- Project modal ---- */
body.modal-open {
  overflow: hidden;
}

.modal-overlay {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-md);
  background: var(--color-overlay);
  opacity: 0;
  transition: opacity var(--transition);
}

.modal-overlay[hidden] {
  display: none;
}

.modal-overlay.is-open {
  opacity: 1;
}

.modal-panel {
  position: relative;
  display: flex;
  flex-direction: column;
  width: min(var(--modal-max-width), 100%);
  max-height: 88vh;
  /* The panel itself doesn't scroll -- .modal-body does. This keeps the
     close button (absolutely positioned to this panel) pinned to the
     corner and visible no matter how long the content is. */
  overflow: hidden;
  background: var(--color-bg-raised);
  border-radius: 10px;
  box-shadow: 0 1.5rem 4rem rgba(27, 22, 18, 0.28);
  transform: translateY(1rem) scale(0.97);
  transition: transform var(--transition);
}

.modal-body {
  overflow-y: auto;
  min-height: 0;
  padding: var(--space-lg);
}

.modal-overlay.is-open .modal-panel {
  transform: none;
}

.modal-panel:focus-visible {
  outline: none;
}

.modal-close {
  position: absolute;
  top: var(--space-sm);
  right: var(--space-sm);
  z-index: 101;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  height: 2.75rem;
  border: 1px solid var(--color-border-strong);
  border-radius: 50%;
  background: var(--color-bg-raised);
  color: var(--color-ink);
  font-family: var(--font-body);
  font-size: 1.4rem;
  line-height: 1;
  cursor: pointer;
  box-shadow: 0 2px 10px rgba(27, 22, 18, 0.15);
  transition:
    background var(--transition-fast),
    color var(--transition-fast),
    border-color var(--transition-fast);
}

.modal-close:hover {
  background: var(--color-ink);
  color: var(--color-bg-raised);
  border-color: var(--color-ink);
}

.modal-close:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

.modal-item-title {
  margin-bottom: var(--space-sm);
  padding-right: var(--space-lg); /* clear the absolutely-placed close button */
  font-size: var(--font-size-h1);
  font-style: italic;
  font-weight: 500;
}

/* Title card: the tile's cover image as a full-bleed banner at the top of the
   modal, with the title over a scrim -- echoing the tile so the click reads
   as one continuous move. The negative margins pull it out to the panel edges
   (past the modal body's padding). */
.modal-item-cover {
  position: relative;
  margin: calc(-1 * var(--space-lg)) calc(-1 * var(--space-lg)) var(--space-md);
  height: clamp(9rem, 26vw, 16rem);
  overflow: hidden;
  background: var(--color-border);
}

.modal-item-cover-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.modal-item-title--over {
  position: absolute;
  inset: auto 0 0 0;
  margin: 0;
  padding: var(--space-lg) var(--space-md) var(--space-sm);
  background: var(--gallery-overlay-bg);
  color: var(--gallery-caption-color);
}

@media (max-width: 40rem) {
  .modal-item-cover {
    margin: calc(-1 * var(--space-xl)) calc(-1 * var(--space-md)) var(--space-md);
  }
}

.modal-item-gallery {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr));
  gap: var(--space-xs);
  margin-bottom: var(--space-sm);
}

.modal-item-gallery img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 4px;
}

.modal-item-body {
  color: var(--color-text);
}

.modal-item-body h1,
.modal-item-body h2,
.modal-item-body h3,
.modal-item-body h4 {
  margin: var(--space-md) 0 var(--space-xs);
  font-weight: 500;
}

.modal-item-body p {
  margin: 0 0 var(--space-sm);
}

/* The global reset strips list markers and indent (ul, ol { list-style:
   none; padding: 0 }). Restore them inside item bodies so Markdown
   numbered/bulleted lists (e.g. the HAND project's goals) render as
   lists, matching the galleries that fill the modal's full width. */
.modal-item-body ol,
.modal-item-body ul {
  margin: 0 0 var(--space-sm);
  padding-left: 1.5rem;
}

.modal-item-body ol {
  list-style: decimal;
}

.modal-item-body ul {
  list-style: disc;
}

.modal-item-body li {
  margin: 0 0 var(--space-2xs);
}

.modal-item-body hr {
  border: 0;
  border-top: 1px solid var(--color-border);
  margin: var(--space-sm) 0;
}

.modal-item-body a {
  color: var(--color-accent);
  text-decoration: underline;
}

.modal-item-body img {
  border-radius: 4px;
  margin: var(--space-xs) 0;
}

.modal-item-links {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-xs);
  margin-top: var(--space-md);
}

.modal-link-button {
  display: inline-flex;
  align-items: center;
  padding: 0.6rem 1.2rem;
  border: 1px solid var(--color-accent);
  border-radius: 4px;
  color: var(--color-accent);
  font-weight: 600;
  font-size: 0.9rem;
  transition:
    background var(--transition-fast),
    color var(--transition-fast);
}

.modal-link-button:hover {
  background: var(--color-accent);
  color: var(--color-bg-raised);
}

/* Full-screen modal on phones. */
@media (max-width: 40rem) {
  .modal-overlay {
    padding: 0;
  }

  .modal-panel {
    width: 100%;
    height: 100%;
    max-height: 100%;
    border-radius: 0;
  }

  .modal-body {
    padding: var(--space-xl) var(--space-md) var(--space-md);
  }
}

/* ---- Lazy video facades (click-to-load YouTube / Vimeo) ---- */
.yt-facade,
.vimeo-facade {
  position: relative;
  aspect-ratio: 16 / 9;
  margin: var(--space-sm) 0;
  background: var(--color-ink);
  border-radius: 4px;
  overflow: hidden;
}

.yt-facade-poster {
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0.85;
}

.yt-facade-play {
  position: absolute;
  inset: 0;
  margin: auto;
  width: 4.25rem;
  height: 3rem;
  padding: 0;
  border: 0;
  background: none;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}

.yt-facade-play:hover svg path:first-child {
  fill-opacity: 1;
}

.yt-facade-play:focus-visible {
  outline: 2px solid #fff;
  outline-offset: 4px;
}

.yt-facade iframe,
.vimeo-facade iframe {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
}

/* Vimeo has no key-free poster image (unlike YouTube's hqdefault.jpg),
   so this is a neutral placeholder card -- icon + label -- rather than
   a thumbnail. */
.vimeo-facade-play {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  padding: 0;
  border: 0;
  background: linear-gradient(160deg, #2a2622, var(--color-ink));
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-2xs);
  color: #faf8f5;
  cursor: pointer;
}

.vimeo-facade-play svg {
  transition: transform var(--transition-fast);
}

.vimeo-facade-play:hover svg,
.vimeo-facade-play:focus-visible svg {
  transform: scale(1.08);
}

.vimeo-facade-play:focus-visible {
  outline: 2px solid #fff;
  outline-offset: -4px;
}

.vimeo-facade-label {
  font-family: var(--font-body);
  font-size: var(--font-size-xs);
  letter-spacing: 0.06em;
  text-transform: lowercase;
  color: rgba(250, 248, 245, 0.75);
}

/* ---- Footer ---- */
.site-footer {
  border-top: 1px solid var(--color-border);
}

.site-footer-inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-sm);
  max-width: var(--content-max-width);
  margin: 0 auto;
  padding: var(--space-md);
}

.footer-links {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-sm);
}

.footer-link {
  color: var(--color-muted);
  font-size: var(--font-size-sm);
  text-transform: lowercase;
  letter-spacing: 0.02em;
  transition: color var(--transition-fast);
}

.footer-link:hover,
.footer-link:focus-visible {
  color: var(--color-accent);
}

.footer-copyright {
  color: var(--color-muted);
  font-size: var(--font-size-xs);
}

/* ---- Shortcode media (existing content bodies) ---- */
.shortcode-carousel {
  display: flex;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  gap: var(--space-2xs);
  margin: var(--space-sm) 0;
  -webkit-overflow-scrolling: touch;
}

.shortcode-carousel-item {
  flex: 0 0 88%;
  scroll-snap-align: center;
  max-width: 50rem;
}

.shortcode-carousel-item img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 4px;
}

@media (min-width: 44rem) {
  .shortcode-carousel-item {
    flex: 0 0 70%;
  }
}

.shortcode-gallery {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr));
  gap: var(--space-2xs);
  margin: var(--space-sm) 0;
}

.shortcode-gallery img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 4px;
}

/* ---- Formal outbound links (github / publication / pdf) ----
   One shared bordered card so every formal link reads the same. Rendered by
   layouts/partials/link-card.html. */
.link-card {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  margin: var(--space-xs) var(--space-2xs) var(--space-xs) 0;
  padding: 0.5rem 1rem;
  border: 1px solid var(--color-border-strong);
  border-radius: 4px;
  color: var(--color-ink);
  transition:
    border-color var(--transition-fast),
    color var(--transition-fast);
}

.link-card:hover,
.link-card:focus-visible {
  border-color: var(--color-accent);
  color: var(--color-accent);
}

.link-card-icon {
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  padding: 0.1rem 0.3rem;
  border-radius: 3px;
  background: var(--color-border);
  color: var(--color-muted);
}

.link-card:hover .link-card-icon,
.link-card:focus-visible .link-card-icon {
  background: var(--color-accent);
  color: var(--color-bg-raised);
}

/* ---- PDF embed (click-to-load viewer, from the pdf partial) ---- */
.pdf-embed {
  margin: var(--space-sm) 0;
}

.pdf-facade {
  border: 1px solid var(--color-border-strong);
  border-radius: 6px;
  overflow: hidden;
  background: var(--color-bg);
}

.pdf-facade-open {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-3xs);
  width: 100%;
  aspect-ratio: 8.5 / 11;
  max-height: 60vh;
  padding: var(--space-md);
  border: 0;
  background: none;
  font: inherit;
  color: var(--color-ink);
  cursor: pointer;
  transition: background var(--transition-fast);
}

.pdf-facade-open:hover {
  background: var(--color-bg-raised);
}

.pdf-facade-icon {
  font-size: 0.85rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  padding: 0.2rem 0.5rem;
  border-radius: 3px;
  background: var(--color-accent);
  color: var(--color-bg-raised);
}

.pdf-facade-label {
  font-family: var(--font-display);
  font-style: italic;
  font-size: 1.05rem;
}

.pdf-facade-hint {
  font-size: var(--font-size-xs);
  letter-spacing: 0.04em;
  text-transform: lowercase;
  color: var(--color-muted);
}

.pdf-frame {
  display: block;
  width: 100%;
  height: min(80vh, 45rem);
  border: 0;
}

.pdf-embed-fallback {
  display: inline-block;
  margin-top: var(--space-2xs);
  color: var(--color-accent);
  font-size: var(--font-size-sm);
  text-decoration: underline;
}

/* ---- Collaborators (named links to people Linnéa worked with) ---- */
.collaborator {
  display: inline-flex;
  align-items: baseline;
  gap: 0.35em;
  margin: 0 0.35em 0.35em 0;
  padding: 0.2rem 0.6rem;
  border: 1px solid var(--color-border);
  border-radius: 999px;
  color: var(--color-ink);
  font-size: var(--font-size-sm);
  transition:
    border-color var(--transition-fast),
    color var(--transition-fast);
}

a.collaborator:hover,
a.collaborator:focus-visible {
  border-color: var(--color-accent);
  color: var(--color-accent);
}

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

.collaborator-role {
  font-size: var(--font-size-xs);
  color: var(--color-muted);
  text-transform: lowercase;
  letter-spacing: 0.03em;
}

.collaborator-arrow {
  font-size: 0.8em;
  color: var(--color-muted);
}

/* ---- Carousel (uniform-height filmstrip + prev/next arrows) ---- */
/* The TRACK sets one shared height; each slide's WIDTH follows its own
   image at that height. So a set of same-size images shows with no crop
   and no margins at all, while a mixed set still lines up on one height
   like a filmstrip. Arrows + the peek of the next slide signal scroll;
   clicking an image opens it full-size in the lightbox. */
.carousel {
  position: relative;
  margin: var(--space-sm) 0;
}

.carousel-track {
  display: flex;
  gap: var(--space-xs);
  height: min(58vh, 30rem);
  /* Center the selected image. `safe` keeps the first slide reachable when
     the strip overflows (a plain `center` would push its start off the
     left edge, out of scroll range); a lone image that fits just centers. */
  justify-content: safe center;
  align-items: center;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
  border-radius: 6px;
}

.carousel-slide {
  flex: 0 0 auto;
  height: 100%;
  scroll-snap-align: center;
  border-radius: 6px;
  overflow: hidden;
}

/* Default: each slide's width follows its image at the track height, so the
   whole image shows (no crop) and mixed aspect ratios still line up on one
   height like a filmstrip. */
.carousel-slide img {
  display: block;
  height: 100%;
  width: auto;
  max-width: none; /* width follows the image's aspect, not the reset's 100% */
  object-fit: contain;
  cursor: zoom-in;
}

/* Opt-in crop mode (crop="true"): uniform-width slides that fill by cropping,
   for sets that read better as even tiles than as a whole-image filmstrip. */
.carousel--crop .carousel-slide {
  flex-basis: min(68%, 34rem);
}

.carousel--crop .carousel-slide img {
  width: 100%;
  object-fit: cover;
}

.carousel-arrow {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 3;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.6rem;
  height: 2.6rem;
  padding: 0 0 0.18em 0;
  border: none;
  border-radius: 50%;
  background: rgba(27, 22, 18, 0.6);
  color: #fff;
  font-size: 1.7rem;
  line-height: 1;
  cursor: pointer;
  transition: background var(--transition-fast);
}

.carousel-arrow:hover {
  background: rgba(27, 22, 18, 0.85);
}

.carousel-arrow:focus-visible {
  outline: 2px solid #fff;
  outline-offset: 2px;
}

.carousel-prev {
  left: 0.5rem;
}

.carousel-next {
  right: 0.5rem;
}

/* ---- Book viewer (page-flip gallery, the `book` shortcode) ---- */
.book {
  position: relative;
  margin: var(--space-sm) 0;
}

.book-stage {
  position: relative;
  height: min(60vh, 32rem);
  perspective: 2000px;
  background: var(--color-ink);
  border-radius: 6px;
  overflow: hidden;
}

.book-page {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-sm);
  transform-origin: left center;
  backface-visibility: hidden;
  cursor: pointer;
}

/* The `display: flex` above would otherwise override the browser's default
   [hidden] { display: none }, leaving every page stacked and the last one
   always on top. Re-hide inactive pages explicitly so only the current page
   (and, mid-turn, the one being revealed) shows. */
.book-page[hidden] {
  display: none;
}

.book-page img {
  display: block;
  height: 100%;
  width: auto;
  max-width: 100%;
  object-fit: contain;
  box-shadow: 0 0 2.5rem rgba(0, 0, 0, 0.45);
}

.book-flip {
  animation: book-flip 0.55s ease-in forwards;
}

.book-flip-back {
  animation: book-flip-back 0.55s ease-out forwards;
}

@keyframes book-flip {
  from {
    transform: rotateY(0);
  }
  to {
    transform: rotateY(-172deg);
  }
}

@keyframes book-flip-back {
  from {
    transform: rotateY(-172deg);
  }
  to {
    transform: rotateY(0);
  }
}

/* Reuse the round arrow look from the carousel. */
.book-nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 3;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.6rem;
  height: 2.6rem;
  padding: 0 0 0.18em 0;
  border: none;
  border-radius: 50%;
  background: rgba(27, 22, 18, 0.6);
  color: #fff;
  font-size: 1.7rem;
  line-height: 1;
  cursor: pointer;
  transition: background var(--transition-fast);
}

.book-nav:hover {
  background: rgba(27, 22, 18, 0.85);
}

.book-nav:focus-visible {
  outline: 2px solid #fff;
  outline-offset: 2px;
}

.book-prev {
  left: 0.5rem;
}

.book-next {
  right: 0.5rem;
}

.book-counter {
  position: absolute;
  bottom: 0.6rem;
  left: 50%;
  transform: translateX(-50%);
  z-index: 3;
  padding: 0.15rem 0.6rem;
  border-radius: 999px;
  background: rgba(27, 22, 18, 0.6);
  color: #fff;
  font-size: var(--font-size-xs);
  letter-spacing: 0.04em;
}

@media (prefers-reduced-motion: reduce) {
  .book-flip,
  .book-flip-back {
    animation-duration: 0.01ms;
  }
}

/* ---- Enlargeable images in the modal ---- */
#modal-body img {
  cursor: zoom-in;
}

#modal-body .yt-facade img,
#modal-body .vimeo-facade img,
#modal-body .book-page img {
  cursor: pointer;
}

/* ---- Image lightbox (click a modal image to see it full / uncropped) ---- */
.lightbox-overlay {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-md);
  background: rgba(14, 11, 9, 0.93);
  cursor: zoom-out;
  opacity: 0;
  transition: opacity var(--transition);
}

.lightbox-overlay[hidden] {
  display: none;
}

.lightbox-overlay.is-open {
  opacity: 1;
}

.lightbox-overlay img {
  max-width: 96vw;
  max-height: 92vh;
  width: auto;
  height: auto;
  object-fit: contain;
  border-radius: 4px;
  box-shadow: 0 1.5rem 4rem rgba(0, 0, 0, 0.5);
}

/* Prev/next arrows: step through the images of the carousel/gallery the
   enlarged image came from. Hidden (via [hidden]) when the group has one image. */
.lightbox-arrow {
  position: fixed;
  top: 50%;
  transform: translateY(-50%);
  z-index: 201;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 3.25rem;
  height: 3.25rem;
  padding: 0 0 0.18em 0;
  border: 1px solid rgba(255, 255, 255, 0.45);
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.4);
  color: #fff;
  font-size: 2rem;
  line-height: 1;
  cursor: pointer;
  transition: background var(--transition-fast);
}

.lightbox-arrow:hover {
  background: rgba(0, 0, 0, 0.75);
}

.lightbox-arrow:focus-visible {
  outline: 2px solid #fff;
  outline-offset: 2px;
}

.lightbox-prev {
  left: var(--space-sm);
}

.lightbox-next {
  right: var(--space-sm);
}

.lightbox-close {
  position: fixed;
  top: var(--space-sm);
  right: var(--space-sm);
  z-index: 201;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  height: 2.75rem;
  border: 1px solid rgba(255, 255, 255, 0.45);
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.4);
  color: #fff;
  font-size: 1.4rem;
  line-height: 1;
  cursor: pointer;
  transition: background var(--transition-fast);
}

.lightbox-close:hover {
  background: rgba(0, 0, 0, 0.75);
}

.lightbox-close:focus-visible {
  outline: 2px solid #fff;
  outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
  .lightbox-overlay {
    transition: none;
  }
  .carousel-track {
    scroll-behavior: auto;
  }
}
