/* ==========================================================================
   Ally Rahmani — memorial site
   Tokens
   ========================================================================== */

:root {
  --paper: #F3ECDD;
  --paper-soft: #EAE0C9;
  --ink: #241F17;
  --ink-soft: #4B4536;
  --black: #0E0D0A;
  --white-on-black: #F6F1E4;
  --white-on-black-soft: #B9B2A0;
  --rust: #B5562E;
  --rust-deep: #94431F;
  --sage: #6E7A5C;
  --line-on-paper: rgba(36, 31, 23, 0.16);
  --line-on-black: rgba(246, 241, 228, 0.18);

  --font-display: "Newsreader", Georgia, "Times New Roman", serif;
  --font-body: "Newsreader", Georgia, "Times New Roman", serif;
  --font-hand: "Caveat", cursive;

  --measure: 62ch;
}

/* ==========================================================================
   Reset & base
   ========================================================================== */

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

html {
  scroll-behavior: smooth;
  /* jumping to a section lands it exactly under the pinned top bar (same height as the bar) */
  scroll-padding-top: 4.1rem;
}

/* anything hidden with the hidden attribute stays hidden, even if a class gives it a display value */
[hidden] {
  display: none !important;
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  font-optical-sizing: auto;
  font-size: 1.125rem;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

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

a {
  color: inherit;
}

h1, h2, p, ul {
  margin: 0;
}

:focus-visible {
  outline: 2px solid var(--rust);
  outline-offset: 4px;
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  * {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* ==========================================================================
   Top bar — clear over the landing videos, then solid cream and pinned to
   the top once you start scrolling
   ========================================================================== */

.site-bar {
  /* the bar stays in the same place the whole time; scrolling only changes its color */
  --bar-side: clamp(1.25rem, 4vw, 3rem);
  position: fixed;
  z-index: 40;
  top: 0;
  left: 0;
  right: 0;
  display: flex;
  align-items: center;
  gap: clamp(2rem, 4vw, 3.5rem);
  height: 4.1rem;
  padding: 0 var(--bar-side);
  color: #fff;
  background: transparent;
  transition: background 0.35s ease, color 0.35s ease, box-shadow 0.35s ease;
}

/* over the videos: a deep shade behind the links that fades softly down into the picture, with a light
   blur so busy video behind the words doesn't compete with them */
.site-bar::before {
  content: "";
  position: absolute;
  z-index: -1;
  top: 0;
  left: 0;
  right: 0;
  height: 170%;
  background: linear-gradient(
    to bottom,
    rgba(6, 6, 5, 0.78) 0%,
    rgba(6, 6, 5, 0.6) 45%,
    rgba(6, 6, 5, 0.25) 75%,
    rgba(6, 6, 5, 0) 100%
  );
  -webkit-backdrop-filter: blur(3px);
  backdrop-filter: blur(3px);
  -webkit-mask-image: linear-gradient(to bottom, #000 55%, transparent 100%);
  mask-image: linear-gradient(to bottom, #000 55%, transparent 100%);
  pointer-events: none;
  transition: opacity 0.35s ease;
}

.site-bar.is-solid::before {
  opacity: 0;
}

.site-bar.is-solid {
  color: var(--ink);
  background: var(--paper);
  box-shadow: 0 1px 0 var(--line-on-paper), 0 0.5rem 1.5rem rgba(36, 31, 23, 0.06);
}

.site-bar a {
  color: inherit;
  text-decoration: none;
}

/* nudged up a touch so the circle lines up with the middle of the links' capital letters,
   which sit a little above the middle of their text box */
.site-bar-logo {
  flex-shrink: 0;
  display: block;
  width: 2.6rem;
  height: 2.6rem;
  transform: translateY(-2px);
  transition: opacity 0.2s ease, transform 0.2s ease;
}

.site-bar-logo svg {
  display: block;
  width: 100%;
  height: 100%;
  overflow: visible;
}

.site-bar-logo text {
  font-family: var(--font-display);
  font-weight: 400;
}

.site-bar:not(.is-solid) .site-bar-logo svg {
  filter: drop-shadow(0 1px 6px rgba(0, 0, 0, 0.5));
}

.site-bar-logo:hover,
.site-bar-logo:focus-visible {
  opacity: 0.8;
  transform: translateY(-2px) scale(1.05);
}

.site-bar-links {
  display: flex;
  align-items: center;
  gap: clamp(1.75rem, 3vw, 2.75rem);
}

.site-bar-links a {
  position: relative;
  white-space: nowrap;
  font-family: var(--font-display);
  font-size: 1.2rem;
  font-weight: 500;
  letter-spacing: 0.005em;
  padding: 0.35rem 0;
}

/* a thin underline slides in on hover */
.site-bar-links a::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.25s ease;
}

.site-bar-links a:hover::after,
.site-bar-links a:focus-visible::after {
  transform: scaleX(1);
}

.site-bar:not(.is-solid) .site-bar-links a {
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.45), 0 2px 14px rgba(0, 0, 0, 0.55);
}

/* Donate sits flush in the top-right corner, a solid block like a tab */
.site-bar-donate {
  margin-left: auto;
  flex-shrink: 0;
  white-space: nowrap;
  display: flex;
  align-items: center;
  height: 3.3rem;
  padding: 0 clamp(1.5rem, 2.5vw, 2.25rem);
  font-family: var(--font-display);
  font-size: 1.25rem;
  font-weight: 500;
  color: var(--ink) !important;
  background: var(--paper);
  transition: background 0.35s ease, color 0.35s ease;
}

.site-bar.is-solid .site-bar-donate {
  color: var(--paper) !important;
  background: #56623f;
}

.site-bar-donate:hover,
.site-bar-donate:focus-visible {
  background: #fffdf8;
}

.site-bar.is-solid .site-bar-donate:hover,
.site-bar.is-solid .site-bar-donate:focus-visible {
  background: var(--ink);
}

/* the phone menu button (three lines), hidden on wider screens */
.site-bar-menu {
  display: none;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  width: 3.25rem;
  align-self: stretch;
  padding: 0 0.9rem;
  border: none;
  background: none;
  color: inherit;
  cursor: pointer;
}

.site-bar-menu span {
  display: block;
  height: 1.5px;
  background: currentColor;
  transition: transform 0.25s ease, opacity 0.25s ease;
}

.site-bar-menu[aria-expanded="true"] span:nth-child(1) {
  transform: translateY(6.5px) rotate(45deg);
}

.site-bar-menu[aria-expanded="true"] span:nth-child(2) {
  opacity: 0;
}

.site-bar-menu[aria-expanded="true"] span:nth-child(3) {
  transform: translateY(-6.5px) rotate(-45deg);
}

/* below this width the four links no longer fit comfortably, so they move into the menu */
@media (max-width: 74rem) {
  .site-bar {
    --bar-side: 1rem;
    gap: 0;
    height: 3.6rem;
  }

  /* phone and tablet layout: the menu button at the top left (it has its own padding, so the bar's
     left edge is tighter), then the circle mark, and the Support button at the top right */
  .site-bar {
    padding-left: 0.25rem;
  }

  .site-bar-menu {
    display: flex;
    order: -1;
  }

  .site-bar-logo {
    margin-left: 0.15rem;
  }

  .site-bar-donate {
    height: 2.7rem;
    padding: 0 1.1rem;
    font-size: 1.05rem;
  }

  /* the section links drop down in a cream panel under the bar */
  .site-bar-links {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding: 0.5rem 0 1rem;
    background: var(--paper);
    box-shadow: 0 1rem 2rem rgba(36, 31, 23, 0.15);
    visibility: hidden;
    opacity: 0;
    transform: translateY(-0.5rem);
    transition: opacity 0.2s ease, transform 0.2s ease, visibility 0.2s;
  }

  .site-bar-links.is-open {
    visibility: visible;
    opacity: 1;
    transform: none;
  }

  .site-bar-links a {
    padding: 0.9rem 1.5rem;
    color: var(--ink);
    text-shadow: none !important;
    font-size: 1.1rem;
  }

  .site-bar-links a::after {
    display: none;
  }
}

/* ==========================================================================
   Hero
   ========================================================================== */

.hero {
  position: relative;
  height: 100svh;
  min-height: 32rem;
  overflow: hidden;
  background: var(--black);
}

/* the videos start a little below the top of the screen, under the top bar, so the bar never sits over
   Ally's face; the strip above them stays dark and blends into the bar's shading */
.hero-video-pair {
  position: absolute;
  inset: 0;
  top: 4.5rem;
  display: flex;
}

@media (max-width: 74rem) {
  .hero-video-pair {
    top: 3.5rem;
  }
}

.hero-video-panel {
  position: relative;
  flex: 1 1 50%;
  overflow: hidden;
  background: var(--black);
}

.hero-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0.82;
}

/* never show Safari's own play button over the landing videos */
.hero-video::-webkit-media-controls,
.hero-video::-webkit-media-controls-start-playback-button,
.hero-video::-webkit-media-controls-overlay-play-button {
  display: none !important;
  -webkit-appearance: none;
}

/* phone held upright: just the one full-screen panel */
@media (max-width: 48rem) and (orientation: portrait) {
  .hero-video-panel--side {
    display: none;
  }
}

/* the cycling panel's two stacked players: the one on screen shows, the other waits invisibly with the
   next clip loaded, then fades in over it */
.hero-video-layer {
  opacity: 0;
  transition: opacity 0.7s ease;
}

.hero-video-layer.is-showing {
  opacity: 0.82;
}

/* graceful fallback when a video file hasn't been added yet */
.hero-video-panel.media-missing {
  background:
    linear-gradient(160deg, rgba(181, 86, 46, 0.35), rgba(14, 13, 10, 0.1)),
    var(--black);
}

.hero-video-panel.media-missing .hero-video {
  display: none;
}

.hero-video-panel.media-missing::after {
  content: "Drop ally-running-1.mp4 or ally-running-2.mp4 into /videos";
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2rem;
  text-align: center;
  color: var(--white-on-black-soft);
  font-size: 0.85rem;
  font-family: var(--font-body);
}

.hero-scrim {
  position: absolute;
  inset: 0;
  z-index: 3;
  background:
    linear-gradient(to top, var(--black) 0%, rgba(14, 13, 10, 0.15) 42%, rgba(14, 13, 10, 0.35) 100%);
}

.hero-content {
  position: relative;
  z-index: 4;
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  text-align: center;
  padding: 0 1.5rem 7rem;
  color: var(--white-on-black);
  pointer-events: none;
}

.hero-name {
  font-family: var(--font-display);
  font-weight: 300;
  font-size: clamp(2.1rem, 6.4vw, 5.75rem);
  line-height: 0.95;
  letter-spacing: -0.025em;
}

/* ---- zoom through her name: the hero pins in place while you scroll; "Remembering" fades away
   while "Ally Rahmani" moves to the middle of the screen and grows toward the camera until you pass through it ---- */

/* dark behind the whole landing page, so no beige ever shows around the videos on iPhone (behind
   Safari's shrinking toolbar, or when the page bounces at the top) */
html.home {
  background: var(--black);
}

.hero-scroll {
  background: var(--black);
}

.hero-scroll.is-zooming {
  height: 210svh;
}

.hero-scroll.is-zooming .hero {
  position: sticky;
  top: 0;
  z-index: 1;
}

/* the letters section tucks up underneath the pinned hero, so the moment the zoom ends in black the
   letters section is already in place behind it, instead of a further screen of black scrolling past */
.hero-scroll.is-zooming + .letters-flow {
  position: relative;
  z-index: 0;
  margin-top: -100svh;
}

/* sized to its own text, so scaling from its center grows evenly in every direction */
.hero-name-line {
  display: block;
  width: fit-content;
  margin-inline: auto;
}

/* "Remembering" is a softer gray-cream so "Ally Rahmani" is what stands out */
#hero-name-lead {
  color: #b3ad9f;
}

.hero-tagline {
  margin-top: 1rem;
  font-size: clamp(1.05rem, 1.6vw, 1.3rem);
  font-style: italic;
  color: var(--white-on-black-soft);
}

/* fixed to the bottom of the screen from the landing page through the notes, then fades away
   once Ally's letter comes into view */
.scroll-cue {
  position: fixed;
  z-index: 30;
  left: 50%;
  bottom: 2rem;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.6rem;
  text-decoration: none;
  color: var(--white-on-black-soft);
  font-size: 0.85rem;
  transition: opacity 0.4s ease, visibility 0.4s;
}

.scroll-cue.is-hidden {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}

/* the words only show on the landing page; after that the moving dot alone keeps nudging */
.scroll-cue-text {
  transition: opacity 0.3s ease;
}

.scroll-cue.is-quiet .scroll-cue-text {
  opacity: 0;
}

.scroll-cue-icon {
  display: block;
  color: var(--white-on-black-soft);
  transition: color 0.25s ease;
}

.scroll-cue:hover .scroll-cue-icon,
.scroll-cue:focus-visible .scroll-cue-icon {
  color: var(--white-on-black);
}

.scroll-cue-dot {
  animation: scroll-dot-travel 1.8s ease-in-out infinite;
  transform-box: fill-box;
  transform-origin: center;
}

@keyframes scroll-dot-travel {
  0% { transform: translateY(0); opacity: 1; }
  65% { opacity: 1; }
  100% { transform: translateY(17px); opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .scroll-cue-dot {
    animation: none;
  }
}

/* ==========================================================================
   Letters flow — after the zoom through her name, the notes she saved
   (and short excerpts from them) drift in out of the dark as you scroll
   ========================================================================== */

.letters-flow {
  background: var(--black);
  color: var(--white-on-black);
}

.flow-wrapper {
  position: relative;
}

.flow-stage {
  position: sticky;
  top: 0;
  height: 100svh;
  overflow: hidden;
  background: var(--black);
}

.flow-field {
  position: relative;
  width: 100%;
  height: 100%;
  margin: 0;
}

.flow-tile,
.flow-quote {
  position: absolute;
  top: 50%;
  left: 50%;
  margin: 0;
  opacity: 0;
  visibility: hidden;
}

.flow-tile {
  width: min(300px, 30vw);
  background: var(--paper-soft);
  box-shadow: 0 2rem 5rem rgba(0, 0, 0, 0.65);
  will-change: transform, opacity;
  pointer-events: none;
}

.flow-tile img {
  display: block;
  width: 100%;
  height: auto;
  cursor: pointer;
  pointer-events: auto;
}

.flow-tile.media-missing {
  display: none;
}

/* excerpts are text, so they are not layer-promoted: that keeps them crisp while they scale up */
.flow-quote {
  width: min(26rem, 36vw);
  text-align: center;
  font-family: var(--font-display);
  font-weight: 300;
  font-style: italic;
  font-size: clamp(1.35rem, 2.6vw, 2.15rem);
  line-height: 1.3;
  color: var(--white-on-black);
  text-shadow: 0 0.25rem 2rem rgba(0, 0, 0, 0.85);
  pointer-events: none;
}

/* the opening line of the section: upright rather than italic, so it reads as narration, not a quote */
.flow-intro {
  width: min(40rem, 82vw);
  font-style: normal;
  font-size: clamp(1.6rem, 3.2vw, 2.6rem);
}

@media (max-width: 42rem) {
  .flow-tile {
    width: min(240px, 56vw);
  }

  .flow-quote {
    width: 82vw;
  }
}

/* ---- static fallback: used when JS is unavailable or the visitor prefers reduced motion ---- */

.flow-wrapper.is-static .flow-stage {
  position: static;
  height: auto;
  padding: 6rem 1.75rem 7rem;
}

.flow-wrapper.is-static .flow-field {
  max-width: 40rem;
  height: auto;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2.5rem;
}

.flow-wrapper.is-static .flow-tile,
.flow-wrapper.is-static .flow-quote {
  position: static;
  opacity: 1;
  visibility: visible;
  transform: none;
}

.flow-wrapper.is-static .flow-tile {
  width: min(360px, 80vw);
}

.flow-wrapper.is-static .flow-quote {
  width: min(40rem, 90vw);
}

/* ==========================================================================
   Letter
   ========================================================================== */

.letter {
  background: var(--paper);
  padding: 3.5rem 1.75rem 5rem;
}

.letter-grid {
  max-width: 68rem;
  margin: 0 auto;
  display: grid;
  grid-template-columns: minmax(12rem, 0.8fr) minmax(0, 1.4fr);
  gap: clamp(2rem, 6vw, 5rem);
  align-items: start;
}

.letter-portraits {
  display: flex;
  flex-direction: column;
}

.letter-portrait-wrap {
  margin: 0;
  background: var(--paper-soft);
  border: 1px solid var(--line-on-paper);
  box-shadow: 0 1rem 2.5rem rgba(36, 31, 23, 0.14);
  padding: 0.5rem;
}

.letter-portrait-wrap--family {
  width: 84%;
  margin-left: auto;
  margin-top: -2.5rem;
  position: relative;
  z-index: 1;
}

.letter-portrait {
  display: block;
  width: 100%;
  height: auto;
}

.letter-portrait-wrap.media-missing {
  aspect-ratio: 4 / 5;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.25rem;
  background: var(--paper);
}

.letter-portrait-wrap.media-missing .letter-portrait {
  display: none;
}

.letter-portrait-wrap.media-missing::after {
  content: "Drop a photo into /letter";
  text-align: center;
  font-size: 0.78rem;
  font-family: var(--font-body);
  color: var(--ink-soft);
}

.letter-inner {
  max-width: var(--measure);
}

@media (max-width: 48rem) {
  .letter-grid {
    grid-template-columns: 1fr;
  }

  .letter-portraits {
    max-width: 20rem;
    margin: 0 auto 3rem;
  }

  .letter-portrait-wrap--family {
    width: 84%;
    margin-top: -2.5rem;
  }
}

.letter-salutation {
  font-family: var(--font-display);
  font-size: 1.6rem;
  font-weight: 400;
}

.letter-body {
  margin-top: 1.75rem;
  font-family: var(--font-display);
  font-size: 1.15rem;
  line-height: 1.85;
  color: var(--ink);
}

.letter-body p {
  margin-bottom: 1.25rem;
}

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

.letter-sign-off {
  margin-top: 2.5rem;
  font-family: var(--font-display);
  font-size: 1.1rem;
}

.letter-signature {
  display: inline-block;
  margin-top: 0.4rem;
  font-family: var(--font-hand);
  font-size: 2rem;
  font-weight: 600;
}

/* ==========================================================================
   Photos — "Ally around school" carousel: five photos in view, growing
   from small at the edges to full size in the middle
   ========================================================================== */

.photos {
  background: var(--black);
  color: var(--white-on-black);
  padding: 3rem 0 4.5rem;
}

.photos .section-heading {
  text-align: center;
  padding: 0 1.75rem;
}

.section-heading {
  max-width: 72rem;
  margin: 0 auto 2.5rem;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(1.6rem, 3vw, 2.2rem);
}

/* five photos are always in view: a large one in the middle, a medium one either side of it and a
   small one at each edge. JS sets --photo-width (the middle photo's width) to fit the screen and
   places every photo; the track only provides the stage. */
/* the starting size matches the size the script settles on (at most 440px; five photos across, or about
   half the screen on a phone), so the section doesn't change height once the photos arrive, which on an
   iPhone would make the page you're reading jump */
.photo-carousel {
  --photo-width: min(440px, max((96vw - 72px) / 3.16, 52vw));
  position: relative;
}

/* its own stacking context, so the photos' per-frame z-index never climbs over the arrows */
.photo-carousel-track {
  position: relative;
  z-index: 0;
  height: calc(var(--photo-width) * 1.25 + 3rem);
  overflow: hidden;
  touch-action: pan-y;
  user-select: none;
  -webkit-user-select: none;
  cursor: grab;
  outline: none;
}

.photo-carousel-track.is-dragging {
  cursor: grabbing;
}

.photo-carousel-track.is-empty {
  height: auto;
  text-align: center;
  padding: 2rem 1rem;
  color: var(--white-on-black-soft);
  font-size: 0.95rem;
  cursor: default;
}

.photo-carousel-tile {
  position: absolute;
  top: 50%;
  left: 50%;
  width: var(--photo-width);
  margin: 0;
  aspect-ratio: 4 / 5;
  overflow: hidden;
  transform-origin: center;
  box-shadow: 0 1.5rem 4rem rgba(0, 0, 0, 0.55);
  will-change: transform, opacity;
}

.photo-carousel-tile img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 20%;
  cursor: pointer;
  -webkit-user-drag: none;
}

.photo-carousel-tile.media-missing {
  display: none;
}

.photo-carousel-track:focus-visible .photo-carousel-tile.is-center {
  outline: 2px solid var(--white-on-black);
  outline-offset: 4px;
}

/* the shared carousel arrows are dark-on-paper; flip them for the black photo section */
.photos .carousel-arrow {
  background: var(--white-on-black);
  color: var(--ink);
  box-shadow: 0 0.5rem 1.5rem rgba(0, 0, 0, 0.45);
}

.photos .carousel-arrow:hover,
.photos .carousel-arrow:focus-visible {
  background: var(--rust);
  color: var(--white-on-black);
}

/* ==========================================================================
   Section intro + "see more" link (shared by Old Letters and Messages)
   ========================================================================== */

.section-intro {
  max-width: 42rem;
  margin: -1.5rem auto 2.5rem;
  font-size: 1.05rem;
  color: var(--ink-soft);
}

.old-letters .section-heading,
.old-letters .section-intro,
.messages .section-heading,
.messages .section-intro {
  text-align: center;
}

.section-more-link {
  display: block;
  width: fit-content;
  margin: 2.5rem auto 0;
  font-family: var(--font-display);
  font-size: 1.05rem;
  text-decoration: none;
  color: var(--ink);
  border-bottom: 1px solid var(--line-on-paper);
  padding-bottom: 0.2rem;
  transition: color 0.25s ease, border-color 0.25s ease;
}

.section-more-link:hover,
.section-more-link:focus-visible {
  color: var(--rust-deep);
  border-color: var(--rust-deep);
}

/* ==========================================================================
   Old letters
   ========================================================================== */

.old-letters {
  background: var(--paper);
  padding: 3rem 0 4.5rem;
}

.old-letters .section-heading,
.old-letters .section-intro {
  padding: 0 1.75rem;
}

.carousel-arrow {
  position: absolute;
  z-index: 3;
  top: 50%;
  transform: translateY(-50%);
  width: 3rem;
  height: 3rem;
  border: none;
  border-radius: 50%;
  background: var(--ink);
  color: var(--paper);
  font-size: 1.6rem;
  line-height: 1;
  cursor: pointer;
  box-shadow: 0 0.5rem 1.5rem rgba(36, 31, 23, 0.25);
  transition: transform 0.2s ease, background 0.2s ease, opacity 0.2s ease;
}

.carousel-arrow:hover,
.carousel-arrow:focus-visible {
  background: var(--rust-deep);
  transform: translateY(-50%) scale(1.08);
}

.carousel-arrow:disabled {
  opacity: 0.3;
  cursor: default;
  pointer-events: none;
}

.carousel-arrow--prev {
  left: 1.25rem;
}

.carousel-arrow--next {
  right: 1.25rem;
}

/* scanned notes come in every shape, so they sit whole on a paper card instead of being cropped */
.photo-carousel-tile--letter {
  background: var(--paper-soft);
  border: 1px solid var(--line-on-paper);
  box-shadow: 0 1rem 2.5rem rgba(36, 31, 23, 0.18);
}

.photo-carousel-tile--letter img {
  object-fit: contain;
  object-position: center;
}

.photo-carousel--letters .photo-carousel-track:focus-visible .photo-carousel-tile.is-center {
  outline-color: var(--ink);
}

@media (max-width: 42rem) {
  .carousel-arrow {
    width: 2.5rem;
    height: 2.5rem;
    font-size: 1.35rem;
  }
}

/* ==========================================================================
   Articles — pieces written about Ally, as cards that open the article
   ========================================================================== */

/* dark, like the notes, photos and support sections */
.articles {
  background: var(--black);
  color: var(--white-on-black);
  padding: 3rem 1.75rem 4.5rem;
}

.articles .section-heading {
  text-align: center;
  color: var(--white-on-black);
}

.article-list {
  max-width: 72rem;
  margin: 0 auto;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 1.5rem;
}

.article-card {
  flex: 0 1 22rem;
  display: flex;
  flex-direction: column;
  padding: 1.75rem 1.75rem 1.6rem;
  background: #fffdf8;
  border: 1px solid transparent;
  color: var(--ink);
  text-decoration: none;
  transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease;
}

.article-card:hover,
.article-card:focus-visible {
  transform: translateY(-3px);
  box-shadow: 0 1rem 2.25rem rgba(0, 0, 0, 0.45);
}

.article-source {
  font-size: 0.8rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #56623f;
}

.article-title {
  margin-top: 0.6rem;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 1.35rem;
  line-height: 1.3;
  color: #56623f;
}

.article-excerpt {
  margin-top: 0.9rem;
  font-family: var(--font-display);
  font-style: italic;
  font-size: 1.02rem;
  line-height: 1.5;
  color: var(--ink-soft);
}

.article-meta {
  margin-top: 1rem;
  font-size: 0.88rem;
  color: var(--ink-soft);
}

/* sits at the bottom of the card, so links line up when there are several cards in a row */
.article-link {
  margin-top: auto;
  padding-top: 1.1rem;
  font-family: var(--font-display);
  font-size: 1rem;
  color: #56623f;
}

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

/* ==========================================================================
   Leave a story / messages — the section on the main page, the full
   messages page, and the share form. Cards and buttons are shared.
   ========================================================================== */

.messages {
  background: var(--paper-soft);
  padding: 3rem 1.75rem 4.5rem;
}

.messages .section-heading {
  max-width: 42rem;
}

.messages .section-intro {
  max-width: 42rem;
}

.messages-actions {
  display: flex;
  justify-content: center;
  margin: 0 auto 3rem;
}

.button-primary {
  display: inline-block;
  padding: 0.95rem 2rem;
  border: none;
  border-radius: 999px;
  background: var(--ink);
  color: var(--paper);
  font-family: var(--font-display);
  font-size: 1.1rem;
  font-weight: 500;
  text-decoration: none;
  cursor: pointer;
  transition: background 0.2s ease, transform 0.2s ease;
}

.button-primary:hover,
.button-primary:focus-visible {
  background: var(--rust-deep);
  transform: translateY(-1px);
}

.button-primary:disabled {
  opacity: 0.6;
  cursor: default;
  transform: none;
}

/* cards sit side by side, three across on a wide screen, and any row that isn't full is centered */
/* cards in the same row stretch to the same height */
.message-list {
  max-width: 72rem;
  margin: 0 auto;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: stretch;
  gap: 1.5rem;
}

/* white cards read clearly against the cream page, like notes laid on a table */
.message-card {
  scroll-margin-top: 6rem;
  flex: 0 0 100%;
  max-width: 32rem;
  background: #fffdf8;
  border: 1px solid var(--line-on-paper);
  overflow: hidden;
  scroll-margin-top: 5rem;
}

.message-list .message-card {
  display: flex;
  flex-direction: column;
}

.message-body {
  padding: 1.5rem 1.6rem 1.75rem;
}

/* "Read more" sits at the bottom of the card, lined up across a row */
.message-list .message-body {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}

.message-list .message-body .message-header {
  align-self: stretch;
}

/* cards in a row line up: the row is as tall as its longest message needs, and no taller. Each message
   shows at most 8 lines under a photo (more on a card without one), ending in "…" when there's more;
   the rest continues on the message's own page. So a row of short messages stays short, and a row
   with a long one is as tall as a full card. On a phone each card simply fits its own message. */
.message-list .message-text {
  margin-bottom: 1rem;
  line-height: 1.45;
  max-height: calc(1.45em * 8);
  overflow: hidden;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 8;
}

/* a long name stays on one line so it can't make one card taller than the rest */
.message-list .message-header {
  flex-wrap: nowrap;
}

.message-list .message-name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.message-list .message-date {
  flex-shrink: 0;
}

/* "Read more" sits at the bottom of its card, so the buttons line up across a row */
.message-list .message-read-more {
  margin-top: auto;
}

.message-header {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.25rem 1rem;
  margin-bottom: 1rem;
}

.message-name {
  font-family: var(--font-display);
  font-size: 1.15rem;
  font-weight: 500;
  color: var(--ink);
}

.message-date {
  font-size: 0.9rem;
  color: var(--ink-soft);
}

/* keeps the line breaks people typed */
.message-text {
  font-family: var(--font-display);
  font-size: 1.05rem;
  line-height: 1.65;
  color: var(--ink);
  white-space: pre-line;
  overflow-wrap: anywhere;
}

.message-read-more {
  display: inline-flex;
  align-items: center;
  height: 2.5rem;
  margin-top: 1rem;
  padding: 0 1.1rem;
  border: 1px solid var(--ink);
  border-radius: 999px;
  font-family: var(--font-display);
  font-size: 0.95rem;
  color: var(--ink);
  text-decoration: none;
  transition: background 0.2s ease, color 0.2s ease;
}

.message-read-more:hover,
.message-read-more:focus-visible {
  background: var(--ink);
  color: var(--paper);
}

/* ---- a single message on its own page ---- */

.single-message .message-card {
  max-width: none;
}

.single-message .message-text {
  font-size: 1.15rem;
  line-height: 1.75;
}

.single-message-links {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-top: 2.5rem;
}

.single-message-links .section-more-link {
  margin: 0;
}

/* every photo sits in the same wide (4:3) frame at the top of its card; a tall or square photo is
   shown whole, with black filling the rest of the frame */
.message-photo {
  position: relative;
  flex-shrink: 0;
  margin: 0;
  aspect-ratio: 4 / 3;
  background: #000;
}

.message-photo img {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  cursor: zoom-in;
}

.message-empty {
  flex-basis: 100%;
  text-align: center;
  color: var(--ink-soft);
  font-size: 1rem;
  padding: 2rem 0;
}

.photo-viewer {
  max-width: none;
  max-height: none;
  width: 100vw;
  height: 100vh;
  margin: 0;
  padding: 0;
  border: none;
  background: rgba(14, 13, 10, 0.94);
}

.photo-viewer img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  padding: 3rem 1rem;
}

.photo-viewer-close {
  position: absolute;
  top: 1rem;
  right: 1.25rem;
  border: none;
  background: none;
  color: var(--white-on-black);
  font-size: 2.4rem;
  line-height: 1;
  cursor: pointer;
}

/* ---- the messages page and the share page ---- */

.subpage {
  background: var(--paper);
}

/* the fixed top bar sits over the top of the other pages, so their content starts below it */
.subpage {
  padding-top: 4.1rem;
}

@media (max-width: 74rem) {
  html {
    scroll-padding-top: 3.6rem;
  }

  .subpage {
    padding-top: 3.6rem;
  }

  .subpage .timeline-rail {
    top: 4.4rem;
  }
}

.subpage-main {
  max-width: 36rem;
  margin: 0 auto;
  padding: 4.5rem 1.75rem 6rem;
}

.subpage-main--wide {
  max-width: 72rem;
  text-align: center;
}

.subpage-main--wide .message-card {
  text-align: left;
}

/* ---- messages page month label: pinned to the top of the screen while scrolling through the
   messages, showing the month and year of the messages at the top ---- */

.timeline-layout {
  margin-top: 3rem;
}

.timeline-layout .message-list {
  margin: 0 auto;
}

.timeline-rail {
  position: sticky;
  top: 5rem;
  z-index: 5;
  display: flex;
  justify-content: center;
  margin-bottom: 1.25rem;
  pointer-events: none;
}

/* slightly see-through, with the page behind it softly blurred so the label stays easy to read */
.timeline-marker {
  padding: 0.4rem 1.1rem;
  border-radius: 999px;
  background: rgba(36, 31, 23, 0.72);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  box-shadow: 0 0.35rem 1rem rgba(36, 31, 23, 0.15);
}

.timeline-label {
  font-family: var(--font-display);
  font-size: 0.95rem;
  color: var(--paper);
}

.subpage-title {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(2rem, 5vw, 2.75rem);
  line-height: 1.15;
  letter-spacing: -0.01em;
}

.subpage-intro {
  margin: 1rem 0 2.5rem;
  font-size: 1.1rem;
  color: var(--ink-soft);
}

/* ---- share form ---- */

.share-form {
  display: flex;
  flex-direction: column;
  gap: 1.75rem;
}

.share-field {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.share-label {
  font-family: var(--font-display);
  font-size: 1.05rem;
  font-weight: 500;
  color: var(--ink);
}

.share-optional {
  font-weight: 400;
  color: var(--ink-soft);
}

.share-input {
  width: 100%;
  padding: 0.85rem 1rem;
  border: 1px solid var(--line-on-paper);
  border-radius: 6px;
  background: #fffdf8;
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 1.1rem;
  line-height: 1.6;
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
}

.share-input:focus {
  outline: none;
  border-color: var(--ink-soft);
  box-shadow: 0 0 0 3px rgba(36, 31, 23, 0.08);
}

.share-textarea {
  min-height: 14rem;
  resize: vertical;
}

.share-count {
  align-self: flex-end;
  font-size: 0.85rem;
  color: var(--ink-soft);
}

.share-count.is-near-limit {
  color: var(--rust-deep);
}

/* the real file input is hidden; the dashed box is its label */
.share-photo-input {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
}

.share-photo-pick {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  padding: 1.75rem 1rem;
  border: 1.5px dashed var(--line-on-paper);
  border-radius: 6px;
  color: var(--ink-soft);
  font-size: 1.05rem;
  cursor: pointer;
  transition: border-color 0.2s ease, color 0.2s ease;
}

.share-photo-pick:hover,
.share-photo-pick:has(+ .share-photo-input:focus-visible) {
  border-color: var(--ink-soft);
  color: var(--ink);
}

.share-photo-pick-icon {
  font-size: 1.5rem;
  line-height: 1;
}

/* shown whole, exactly as it will be posted */
.share-photo-preview img {
  display: block;
  max-width: 100%;
  max-height: 26rem;
  border-radius: 6px;
}

.share-photo-actions {
  display: flex;
  gap: 1.25rem;
  margin-top: 0.75rem;
}

.share-link-button {
  padding: 0;
  border: none;
  background: none;
  font-family: var(--font-body);
  font-size: 1rem;
  color: var(--rust-deep);
  text-decoration: underline;
  text-underline-offset: 0.2em;
  cursor: pointer;
}

.share-link-button:hover,
.share-link-button:focus-visible {
  color: var(--ink);
}

/* ---- photo editor ---- */

.share-editor {
  padding: 1rem;
  border: 1px solid var(--line-on-paper);
  border-radius: 8px;
  background: #fffdf8;
}

.share-editor-hint {
  margin-bottom: 0.75rem;
  font-size: 0.92rem;
  color: var(--ink-soft);
}

.share-editor-stage {
  position: relative;
  height: clamp(16rem, 55vh, 28rem);
  border-radius: 6px;
  overflow: hidden;
  background: #1c1a15;
  cursor: grab;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
}

.share-editor-stage.is-dragging {
  cursor: grabbing;
}

.share-editor-stage:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}

.photo-editor-image {
  position: absolute;
  top: 50%;
  left: 50%;
  max-width: none;
  pointer-events: none;
}

/* the frame: everything outside it is dimmed, so it's clear what will be kept */
.photo-editor-frame {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  border: 2px solid rgba(255, 255, 255, 0.9);
  box-shadow: 0 0 0 100vmax rgba(14, 13, 10, 0.6);
  pointer-events: none;
}

.share-editor-zoom {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  margin-top: 0.9rem;
}

.share-editor-zoom-label {
  font-size: 0.95rem;
  color: var(--ink-soft);
}

.share-editor-zoom input {
  flex: 1;
  accent-color: var(--ink);
}

.share-editor-tools {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 0.75rem;
  margin-top: 0.85rem;
}

.share-editor-group {
  display: flex;
  gap: 0.35rem;
}

.share-editor-tool {
  min-width: 2.5rem;
  padding: 0.5rem 0.85rem;
  border: 1px solid var(--line-on-paper);
  border-radius: 999px;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 0.95rem;
  line-height: 1.2;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}

.share-editor-tool:hover,
.share-editor-tool:focus-visible {
  border-color: var(--ink-soft);
}

.share-editor-tool[aria-pressed="true"] {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--paper);
}

.share-editor-footer {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: 1.5rem;
  margin-top: 1.1rem;
  padding-top: 1rem;
  border-top: 1px solid var(--line-on-paper);
}

.share-editor-done {
  font-size: 1rem;
  padding: 0.75rem 1.5rem;
}

.share-error {
  padding: 0.85rem 1rem;
  border-radius: 6px;
  background: rgba(181, 86, 46, 0.1);
  color: var(--rust-deep);
  font-size: 0.98rem;
}

.share-submit {
  align-self: flex-start;
}

.share-help {
  font-size: 0.95rem;
  color: var(--ink-soft);
}

.share-help a {
  color: var(--ink);
}

/* ---- contact page ---- */

.contact-card {
  padding: 1.5rem 1.75rem;
  background: #fffdf8;
  border: 1px solid var(--line-on-paper);
}

.contact-label {
  font-size: 0.8rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #56623f;
}

.contact-email {
  display: inline-block;
  margin-top: 0.35rem;
  font-family: var(--font-display);
  font-size: 1.35rem;
  color: var(--ink);
  text-decoration: none;
}

.contact-email:hover,
.contact-email:focus-visible {
  color: #56623f;
}

.contact-note {
  margin-top: 1.75rem;
  font-size: 1.02rem;
  line-height: 1.6;
  color: var(--ink-soft);
}

.share-done {
  outline: none;
}

.share-done-title {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(1.8rem, 4vw, 2.4rem);
}

.share-done-links {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1.5rem;
}

.share-done-links .section-more-link {
  margin: 0;
}

/* every card in a row is the same width, including a last row that isn't full */
@media (min-width: 40rem) {
  .message-card {
    flex-basis: calc((100% - 1.5rem) / 2);
  }
}

@media (min-width: 60rem) {
  .message-card {
    flex-basis: calc((100% - 3rem) / 3);
  }
}

@media (max-width: 42rem) {
  .message-body {
    padding: 1.25rem 1.25rem 1.5rem;
  }
}

/* ==========================================================================
   Donate
   ========================================================================== */

/* black, like the notes and photos sections, so the page closes the way it opened; the cream button
   is the one bright thing in it */
.donate {
  background: var(--black);
  padding: 2.75rem 1.75rem 5rem;
  text-align: center;
}

/* wide enough that the whole section fits on one laptop screen */
.donate-inner {
  max-width: 58rem;
  margin: 0 auto;
}

.donate-heading {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(1.9rem, 4vw, 2.6rem);
  color: var(--white-on-black);
}

.donate-text {
  margin-top: 1rem;
  font-size: 1.15rem;
  line-height: 1.6;
  color: var(--white-on-black-soft);
}

/* the second paragraph (the foundation's status and the donation site) matches the first */
.donate-note {
  margin-top: 1rem;
  font-size: 1.15rem;
  line-height: 1.6;
  color: var(--white-on-black-soft);
}

.donate-button {
  display: inline-block;
  margin-top: 1.75rem;
  padding: 1.35rem 3.5rem;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.3rem;
  letter-spacing: 0.01em;
  text-decoration: none;
  color: var(--ink);
  background: var(--paper);
  animation: donate-pulse 2.6s ease-in-out infinite;
  transition: transform 0.2s ease, background 0.2s ease, box-shadow 0.2s ease;
}

.donate-button:hover,
.donate-button:focus-visible {
  background: #fffdf8;
  transform: translateY(-3px) scale(1.03);
  box-shadow: 0 1.25rem 2.5rem rgba(0, 0, 0, 0.5);
  animation-play-state: paused;
}

/* a steady soft glow around the button, plus a ring that swells outward and fades */
@keyframes donate-pulse {
  0% {
    box-shadow: 0 0 22px 2px rgba(243, 236, 221, 0.35), 0 0 0 0 rgba(243, 236, 221, 0.6);
  }
  70% {
    box-shadow: 0 0 34px 6px rgba(243, 236, 221, 0.5), 0 0 0 28px rgba(243, 236, 221, 0);
  }
  100% {
    box-shadow: 0 0 22px 2px rgba(243, 236, 221, 0.35), 0 0 0 0 rgba(243, 236, 221, 0);
  }
}

/* ==========================================================================
   Footer
   ========================================================================== */

.site-footer {
  padding: 3rem 1.75rem;
  text-align: center;
  background: var(--paper);
  border-top: 1px solid var(--line-on-paper);
}

.site-footer p {
  margin-top: 0.75rem;
  font-family: var(--font-display);
  font-size: 0.95rem;
  color: var(--ink-soft);
}

.footer-contact {
  display: inline-block;
  margin-top: 0.6rem;
  font-family: var(--font-display);
  font-size: 0.95rem;
  color: var(--ink);
  text-decoration: underline;
  text-underline-offset: 0.2em;
  text-decoration-color: var(--line-on-paper);
}

.footer-contact:hover,
.footer-contact:focus-visible {
  color: #56623f;
  text-decoration-color: currentColor;
}

.site-footer .footer-copyright {
  margin-top: 1rem;
  font-size: 0.82rem;
  color: var(--ink-soft);
  opacity: 0.8;
}

.footer-logo {
  display: inline-block;
  width: 3rem;
  height: 3rem;
  color: var(--ink);
  transition: opacity 0.2s ease, transform 0.2s ease;
}

.footer-logo svg {
  display: block;
  width: 100%;
  height: 100%;
  overflow: visible;
}

.footer-logo text {
  font-family: var(--font-display);
  font-weight: 400;
}

.footer-logo:hover,
.footer-logo:focus-visible {
  opacity: 0.75;
  transform: scale(1.05);
}

/* ==========================================================================
   Lightbox
   ========================================================================== */

.lightbox {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(14, 13, 10, 0.96);
  opacity: 1;
  transition: opacity 0.25s ease;
}

.lightbox[hidden] {
  display: none;
}

.lightbox-image {
  max-width: min(88vw, 68rem);
  max-height: 86vh;
  width: auto;
  height: auto;
  box-shadow: 0 2rem 4rem rgba(0, 0, 0, 0.5);
}

.lightbox-close,
.lightbox-prev,
.lightbox-next {
  position: absolute;
  background: none;
  border: none;
  color: var(--white-on-black-soft);
  font-family: var(--font-body);
  cursor: pointer;
  line-height: 1;
  transition: color 0.2s ease;
}

.lightbox-close:hover,
.lightbox-close:focus-visible,
.lightbox-prev:hover,
.lightbox-prev:focus-visible,
.lightbox-next:hover,
.lightbox-next:focus-visible {
  color: var(--white-on-black);
}

.lightbox-close {
  top: 1.5rem;
  right: 1.75rem;
  font-size: 2.25rem;
  padding: 0.25rem 0.5rem;
}

.lightbox-prev,
.lightbox-next {
  top: 50%;
  transform: translateY(-50%);
  font-size: 3rem;
  padding: 0.5rem 1rem;
}

.lightbox-prev {
  left: 0.5rem;
}

.lightbox-next {
  right: 0.5rem;
}

@media (max-width: 42rem) {
  .lightbox-image {
    max-width: 92vw;
    max-height: 78vh;
  }

  .lightbox-close {
    top: 1rem;
    right: 1rem;
  }

  .lightbox-prev,
  .lightbox-next {
    font-size: 2.25rem;
  }
}

/* spam trap on the share form: kept off-screen (not display:none, which some spam tools skip) */
.share-trap {
  position: absolute;
  left: -10000px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}
