/* index.html — home page only. Loaded after css/shared.css. */

/* ---------------------------------------------------------------------
   Hero: an editorial diptych. The photograph holds one side, the text the
   other, each on its own surface — nothing is set over the image, so the
   type carries no shadows and the photograph is never cut by words.

   shared.css gives every page's <main> a padding-top of the measured nav
   height. The hero pulls that back off so the photograph bleeds up behind
   the frosted bar (DESIGN.md: the photography should show through the UI),
   and the text column re-adds it as padding so the words stay clear of it.
   --------------------------------------------------------------------- */
#hero {
    margin-top: calc(-1 * var(--nav-h, 4rem));
    /* At least one viewport, never a cage: the text column used to be a
       scroll container with its scrollbar suppressed, so on short screens
       the memorial text scrolled *inside* the hero with nothing on screen
       to say so. The hero now grows past the fold when the words need the
       room, and the ordinary page scroll carries the reader down. */
    min-height: 100svh;
    display: flex;
    flex-direction: column;
    background: #eef0f2;
}

@media (min-width: 900px) {
    #hero {
        /* The figure comes first in the DOM so it stacks on top on phones.
           Reversing the row hands the RTL reading start — the right — to
           the text column, and sends the photograph to the left. */
        flex-direction: row-reverse;
    }
}

/* --- the photograph --- */
#hero .hero-figure {
    position: relative;
    flex: 0 0 46svh;
    overflow: hidden;
    background: #1A2E44;
}

@media (min-width: 900px) {
    #hero .hero-figure {
        flex: 1 1 auto;
    }
}

#hero .hero-bg-img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    opacity: 0;
    transition: opacity 1.2s ease-out;
    filter: saturate(0.88) contrast(1.02) brightness(0.96);
}

#hero .hero-bg-img-active {
    opacity: 1;
}

/* Grounds the caption without a line: the image simply darkens into it. */
#hero .hero-figure-scrim {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 11rem;
    background: linear-gradient(to top, rgba(3, 25, 46, 0.72) 0%, rgba(3, 25, 46, 0) 100%);
    pointer-events: none;
}

#hero .hero-figure-caption {
    position: absolute;
    right: 1.5rem;
    bottom: 1.35rem;
    margin: 0;
    font-family: var(--font-sans);
    font-size: 0.72rem;
    letter-spacing: 0.13em;
    color: rgba(255, 255, 255, 0.76);
}

@media (min-width: 900px) {
    #hero .hero-figure-caption {
        right: 2.25rem;
        bottom: 2rem;
    }
}

/* --- the text column --- */
#hero .hero-panel {
    /* 1 1 auto, not 1 1 0: the column may grow, but it must never be
       squeezed below the height of the text it holds. */
    flex: 1 1 auto;
    display: flex;
    align-items: center;
    background: #eef0f2;
    padding: 2.25rem 1.5rem 3rem;
}

@media (min-width: 900px) {
    #hero .hero-panel {
        flex: 0 0 clamp(31rem, 42%, 37.5rem);
        padding: calc(var(--nav-h, 4rem) + 2.25rem) clamp(2.5rem, 3.4vw, 3.75rem) 2.75rem;
    }
}

#hero .hero-panel-inner {
    width: 100%;
    max-width: 34rem;
    margin: 0 auto;
    font-family: var(--font-sans);
    text-align: center;
}

/* The column is centred, so weight hung under the text lifts it: the block
   sits higher against the photograph without ever being pinned to the nav,
   and the lift scales with the viewport instead of stranding the text at
   the top of a tall screen. */
@media (min-width: 900px) {
    #hero .hero-panel-inner {
        margin-bottom: clamp(1.5rem, 7vh, 4.5rem);
    }
}

#hero .hero-kicker {
    margin: 0 0 1.2rem;
    font-size: 0.94rem;
    font-weight: 700;
    letter-spacing: 0.34em;
    color: #C9A34E;
}

#hero .hero-title {
    margin: 0 0 1.1rem;
    font-size: clamp(1.7rem, 2.5vw + 0.55rem, 2.45rem);
    line-height: 1.2;
    font-weight: 700;
    letter-spacing: -0.015em;
    color: #1A2E44;
}

#hero .hero-lead {
    margin: 0 0 1rem;
    font-size: clamp(1.08rem, 0.5vw + 0.93rem, 1.2rem);
    line-height: 1.7;
    color: #1A2E44;
}

#hero .hero-dates {
    margin: 0 0 1.55rem;
    font-size: 0.95rem;
    line-height: 1.6;
    color: #43474d;
}

#hero .hero-years {
    margin: 1.35rem 0 0;
    font-size: 0.88rem;
    font-weight: 700;
    letter-spacing: 0.16em;
    color: #43474d;
}

/* The vow reads as an inscription rather than a heading: a touch larger
   than it was, a lighter weight, and the letters opened up so the line
   carries by spacing instead of by boldness. The name and the acrostic
   initials (א־ל־ו־נ) carry the weight — navy on the gold inscription. */
#hero .hero-remembrance {
    margin: 0 0 1.7rem;
    font-size: clamp(1.18rem, 0.75vw + 0.92rem, 1.45rem);
    font-weight: 500;
    line-height: 1.55;
    letter-spacing: 0.07em;
    color: #C9A34E;
}

#hero .hero-remembrance-name {
    font-weight: 700;
    font-size: 1.22em;
    letter-spacing: 0.04em;
    color: #C9A34E;
}

#hero .acrostic-letter {
    font-weight: 700;
    font-size: 1.14em;
    color: #C9A34E;
}

#hero .hero-quote-block {
    /* Sits well below the memorial lines — the gap is what separates his
       words from ours, so it grows with the room the panel has. */
    margin: clamp(1.5rem, 8vh, 4.5rem) 0 0;
    padding: 0;
}

#hero .hero-quote-text {
    padding: 1.3rem 1.4rem;
    background: #e1e4e8;
}

#hero .hero-quote {
    margin: 0 0 0.7rem;
    font-size: 0.96rem;
    line-height: 1.85;
    color: #43474d;
}

#hero .hero-quote-source {
    margin: 0;
    font-size: 0.72rem;
    letter-spacing: 0.07em;
    color: #585f65;
}

/* Short laptop screens: tighten the rhythm so the whole memorial text still
   lands in one view without the hero having to run past the fold. */
@media (min-width: 900px) and (max-height: 800px) {
    #hero .hero-panel {
        padding-top: calc(var(--nav-h, 4rem) + 1.5rem);
        padding-bottom: 1.75rem;
    }
    #hero .hero-kicker { margin-bottom: 0.9rem; }
    #hero .hero-title { margin-bottom: 0.8rem; }
    #hero .hero-lead { margin-bottom: 0.75rem; }
    #hero .hero-dates { margin-bottom: 1.1rem; }
    #hero .hero-remembrance { margin-bottom: 1.15rem; }
    #hero .hero-years { margin-top: 1rem; }
    #hero .hero-quote-text { padding: 1.05rem 1.2rem; }
    #hero .hero-quote { line-height: 1.72; }
}

/* Short enough that the lift and the quote's gap no longer fit: the whole
   memorial text still has to land in one view, so they are what give. */
@media (min-width: 900px) and (max-height: 660px) {
    #hero .hero-panel-inner { margin-bottom: 0; }
    #hero .hero-quote-block { margin-top: 1rem; }
}

img { filter: saturate(0.82) contrast(0.97) brightness(0.99); }

/* Photo frame: this page's specific shadow depth + hover lift. */
.photo-frame {
    box-shadow: 0 4px 10px rgba(27, 28, 25, 0.10);
    transition: box-shadow 400ms ease-out;
}
.photo-frame:hover {
    box-shadow: 0 8px 18px rgba(27, 28, 25, 0.15);
}
/* Reads as quiet archival grayscale until a visitor's cursor finds it,
   then color returns. Pointer-only: touch visitors see full color. */
@media (hover: hover) {
    .photo-frame .photo-frame-inner img {
        filter: grayscale(85%) contrast(1.02);
        transition: filter 600ms ease-out, transform 700ms ease-out;
    }
    .photo-frame:hover .photo-frame-inner img {
        filter: grayscale(0%);
        transform: scale(1.05);
    }
}

/* Home gallery preview strip: the thumbnails are reshuffled at random on every
   load, so no per-photo focal point can be authored. Square-cropping a portrait
   from the center cuts heads off, so anchor every one of the ten to the top of
   the frame — a bit of feet lost beats a face lost. */
#home-gallery-grid .photo-frame-inner img {
    object-position: center top;
    transform-origin: center top;
}

/* Life-chapters photos: deeper resting shadow than the shared default. */
.photo-frame-stacked {
    box-shadow: 0 14px 28px rgba(27, 28, 25, 0.16);
}

/* New candle-lighting entry sliding into the memorial list. */
@keyframes candle-in {
    from { opacity: 0; transform: translateY(12px); box-shadow: 0 0 0 rgba(124, 140, 160, 0); }
    30% { box-shadow: 0 0 24px rgba(124, 140, 160, 0.25); }
    to { opacity: 1; transform: translateY(0); box-shadow: 0 0 0 rgba(124, 140, 160, 0); }
}
.candle-entry-new {
    animation: candle-in 1400ms ease-out;
}

/* Life-spine photo crossfade — JS-driven, synced with the quote rotator below.
   6s hold per slide, 1.5s dissolve (LIFE_SPINE_HOLD_MS / _FADE_MS in site.js).

   Selectors are .photo-frame-qualified on purpose: the grayscale hover rule
   above declares its own `transition` at that same specificity, and a bare
   `.crossfade-frame img` loses to it on pointer devices — which dropped the
   opacity transition entirely and made the slides hard-cut. */
.crossfade-frame {
    background: #eceae5;
}

.photo-frame .crossfade-frame img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    /* Default focal point: upper-body center, not forehead crop. */
    object-position: center 42%;
    transform-origin: center 42%;
    opacity: 0;
    z-index: 0;
    transition:
        opacity 1500ms cubic-bezier(0.4, 0, 0.2, 1),
        filter 600ms ease-out,
        transform 700ms ease-out;
}

/* The outgoing frame is held fully opaque *underneath* the incoming one for the
   length of the dissolve. Fading both at once leaves them each near 50% mid-way,
   which lets the mat show through and reads as a flash. */
.photo-frame .crossfade-frame img.is-leaving {
    opacity: 1;
    z-index: 1;
}

.photo-frame .crossfade-frame img.is-active {
    opacity: 1;
    z-index: 2;
}

.crossfade-frame img.is-portrait {
    object-position: center 42%;
    transform-origin: center 42%;
}

.crossfade-frame img.is-landscape {
    object-position: center center;
    transform-origin: center center;
}

@media (prefers-reduced-motion: reduce) {
    .crossfade-frame img {
        transition: none;
    }
    .crossfade-frame img.is-active,
    .crossfade-frame img:first-child {
        opacity: 1;
    }
    .crossfade-frame img:not(.is-active):not(:first-child) {
        opacity: 0;
    }
}

/* Year-spine life chapters */
.life-spine {
  padding: 5rem 1.5rem 6rem;
}

.life-spine-inner {
  max-width: 72rem;
  margin: 0 auto;
}

.life-spine-intro {
  max-width: 48rem;
  margin: 0 auto 3.5rem;
  text-align: center;
}

.life-spine-prologue {
  margin: 1.75rem auto 0;
  max-width: 46rem;
  text-align: start;
}

.life-spine-prologue p {
  margin: 0 0 1rem;
  font-size: 1.12rem;
  line-height: 1.8;
  color: #585f65;
  text-align: justify;
  text-justify: inter-word;
  hyphens: none;
  text-wrap: pretty;
}

.life-spine-prologue p:last-child {
  margin-bottom: 0;
}

/* Mid-chapter rotating photo stations — parallel to prose in the chapter grid. */
.life-spine-rotate {
  margin: 0;
  max-width: 23.4rem;
  width: 100%;
}

.life-spine-rotate .photo-frame {
  margin: 0;
  max-width: none;
  width: 100%;
}

/* Rotating pull-quotes: relocated into the body copy (a sibling of the
   paragraphs, not nested under a photo) so a quote never reads as if it
   were describing whatever image happens to be on screen. Grid stack keeps
   height at the tallest quote so the paragraph below never reflows on
   rotation. */
.life-spine-quote-rotate {
  display: grid;
  grid-template-areas: "stack";
  margin: 1.6rem 0;
}

.life-spine-quote-rotate > .life-spine-quote {
  grid-area: stack;
  margin: 0;
  align-self: start;
  /* visibility flips only once the fade has finished, so the outgoing quote
     dissolves with its photo instead of blinking out on the first frame. */
  transition: opacity 1500ms cubic-bezier(0.4, 0, 0.2, 1), visibility 0s linear 1500ms;
}

.life-spine-quote-rotate > .life-spine-quote:not(.is-active) {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  z-index: 0;
}

.life-spine-quote-rotate > .life-spine-quote.is-active {
  opacity: 1;
  visibility: visible;
  z-index: 1;
  transition: opacity 1500ms cubic-bezier(0.4, 0, 0.2, 1), visibility 0s;
}

@media (prefers-reduced-motion: reduce) {
  .life-spine-quote-rotate > .life-spine-quote {
    transition: none;
  }
}

.life-spine-heading {
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: center;
  gap: 0.85rem;
  width: max-content;
  max-width: 100%;
  margin: 0 auto;
}

.life-spine-heading-text {
  text-align: center;
}

.life-spine-emblem {
  display: block;
  height: 4.5rem;
  width: auto;
  flex-shrink: 0;
  filter: none;
}

.life-spine-range {
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: baseline;
  direction: ltr;
  unicode-bidi: isolate;
  margin: 0.7rem 0 0;
}

.life-spine-stop {
  display: grid;
  grid-template-columns: 8.25rem 1.25rem minmax(0, 1fr);
  column-gap: 1.15rem;
  align-items: start;
  margin-bottom: 3.25rem;
}

.life-spine-year {
  padding-top: 0.15rem;
  text-align: left;
}

.life-spine-date {
  font-family: var(--font-sans);
  font-size: 1.15rem;
  font-weight: 800;
  letter-spacing: 0.02em;
  color: #7C8CA0;
  margin: 0;
}

.life-spine-hebrew {
  margin: 0.3rem 0 0;
  font-size: 0.92rem;
  font-weight: 600;
  line-height: 1.45;
  color: #585f65;
}

.life-spine-rail {
  position: relative;
  justify-self: center;
  width: 0.7rem;
  min-height: 100%;
  align-self: stretch;
}

.life-spine-rail::before {
  content: "";
  position: absolute;
  top: 0.45rem;
  right: 50%;
  transform: translateX(50%);
  width: 0.7rem;
  height: 0.7rem;
  border-radius: 999px;
  background: #1A2E44;
  z-index: 1;
}

/* One unbroken line: it runs the full height of the chapter and reaches
   exactly into the next one (bottom == .life-spine-stop's margin-bottom), so
   the spine never breaks between chapters. The dot sits on top of it. */
.life-spine-rail::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: -3.25rem;
  right: 50%;
  width: 2px;
  transform: translateX(50%);
  background: #d5d8dc;
}

.life-spine-stop:first-of-type .life-spine-rail::after {
  top: 0.45rem;
}

.life-spine-stop-last .life-spine-rail::after {
  bottom: 0;
}

.life-spine-title {
  font-family: var(--font-sans);
  font-size: clamp(1.45rem, 2.4vw, 1.9rem);
  font-weight: 800;
  color: #1A2E44;
  margin: 0 0 0.55rem;
}

.life-spine-stop > .life-spine-body {
  grid-column: 3;
  min-width: 0;
}

.life-spine-body {
  display: block;
}

/* The chapter's lead photo floats beside the lead + the start of body copy,
   same as the small aside photos above: text hugs it tightly, then — once
   there's enough of it to clear the photo's height — widens back out to the
   full timeline measure, the way a real newspaper column runs past an inset
   photo. This only stays gap-free because every chapter's lead+copy already
   runs taller than its lead photo (checked across all seven); a chapter
   that was ever shorter than its own photo would need the fixed two-column
   treatment instead (see life-spine-aside-media, which stays that way on
   purpose since a one-paragraph caption can't be relied on to outrun it). */
.life-spine-row {
  display: flow-root;
}

.life-spine-media {
  float: inline-start;
  width: min(39.6%, 21.6rem);
  min-width: 12rem;
  margin-inline-end: 1.6rem;
  margin-bottom: 0.85rem;
}

.life-spine-body .photo-frame {
  margin: 0;
  max-width: none;
  width: 100%;
}

.life-spine-lead {
  display: flow-root;
  max-width: none;
  font-size: 1.25rem;
  font-style: italic;
  line-height: 1.7;
  color: #1A2E44;
  margin: 0 0 0.95rem;
  text-align: justify;
  text-justify: inter-word;
  text-align-last: start;
  hyphens: none;
  text-wrap: pretty;
}

.life-spine-copy {
  min-width: 0;
}

/* Mid-chapter stations: a small inset photo with its paragraph hugging it
   tightly on the near side — Word's "Tight" wrap, not "Square" — so the
   text reads as one column flowing around a photo rather than two boxed-off
   halves. That means a float, not a flex row: floats are what let text
   fill in close beside the photo and then run the full column width again
   once it clears. Kept small (28%) specifically so a one-paragraph caption
   almost always out-runs the photo's height — the float's one real failure
   mode is the reverse case (a full-height float with no dedicated text to
   fill it), which is why the photo is sized down rather than up. */
.life-spine-aside {
  clear: both;
  margin: 2.5rem 0 1.25rem;
  width: 100%;
}

.life-spine-aside::after {
  content: "";
  display: table;
  clear: both;
}

.life-spine-aside:first-of-type {
  margin-top: 2.75rem;
}

.life-spine-aside + .life-spine-aside {
  margin-top: 2.75rem;
}

.life-spine-aside-media {
  float: inline-start;
  width: min(28%, 14rem);
  min-width: 10rem;
  margin-inline-end: 1.2rem;
  margin-bottom: 0.5rem;
}

.life-spine-aside:nth-of-type(even) .life-spine-aside-media {
  float: inline-end;
  margin-inline-end: 0;
  margin-inline-start: 1.2rem;
}

.life-spine-aside .life-spine-rotate {
  width: 100%;
  max-width: none;
  margin: 0;
}

.life-spine-aside-copy {
  min-width: 0;
}

/* Chapter prose. `display: flow-root` + auto width (no width:100%) is what lets
   a paragraph sit *beside* a floated photo at the remaining measure — a definite
   100% width won't fit next to the float and drops below it. `max-width: none`
   removes the old 42rem cap so once the float clears, continuation lines reclaim
   the full spine column instead of a narrow RTL strip with empty left margin. */
.life-spine-text > p,
.life-spine-copy > p,
.life-spine-aside-copy p {
  display: flow-root;
  max-width: none;
  margin: 0 0 1rem;
  font-size: 1.12rem;
  line-height: 1.8;
  color: #585f65;
  text-align: justify;
  text-justify: inter-word;
  text-align-last: start;
  hyphens: none;
  text-wrap: pretty;
}

/* Continuation after an image cluster: clear the float and span the full column. */
.life-spine-aside + p,
.life-spine-text > .life-spine-aside ~ p {
  clear: both;
  max-width: none;
}

.life-spine-text > p:last-child,
.life-spine-copy > p:last-child,
.life-spine-aside-copy p:last-child {
  margin-bottom: 0;
}

.life-spine-quote {
  margin: 0;
  padding: 0;
  background: none;
  border: none;
  outline: none;
}

.life-spine-quote p {
  margin: 0;
  padding: 0;
  max-width: 34rem;
  font-size: 1.2rem;
  font-weight: 700;
  font-style: italic;
  line-height: 1.55;
  color: #1A2E44;
  background: none;
  outline: none;
  hyphens: none;
  text-wrap: pretty;
}

.life-spine-quote footer {
  display: block;
  margin-top: 0.35rem;
  font-size: 0.78rem;
  font-weight: 400;
  letter-spacing: 0;
  color: #7C8CA0;
}

@media (max-width: 839px) {
  .life-spine-stop {
    grid-template-columns: 1fr;
    row-gap: 0.55rem;
    margin-bottom: 2rem;
  }

  .life-spine-year {
    text-align: right;
  }

  .life-spine-rail {
    display: none;
  }

  .life-spine-stop > .life-spine-body {
    grid-column: 1;
  }

  .life-spine-media {
    float: none;
    width: 100%;
    max-width: 23.4rem;
    margin-inline: 0;
    margin-bottom: 0.9rem;
  }

  .life-spine-aside,
  .life-spine-aside:nth-of-type(even) {
    margin: 1.5rem 0 0;
  }

  .life-spine-aside:first-of-type {
    margin-top: 1.75rem;
  }

  .life-spine-aside-media,
  .life-spine-aside:nth-of-type(even) .life-spine-aside-media {
    float: none;
    width: 100%;
    max-width: 23.4rem;
    margin-inline: 0;
    margin-bottom: 0.55rem;
  }

  .life-spine-aside .life-spine-rotate {
    max-width: 23.4rem;
  }
}
