/* Shared styles — loaded on every page, before the page's own stylesheet.
   Anything here is either a true site-wide base rule or a component used
   identically by two or more pages. Page-specific variants and one-off
   rules belong in that page's own css/<page>.css instead. */

/* ---------------------------------------------------------------------
   Font tokens — the ONE place to change when swapping the site's typeface.
   Every font-family rule on the site (here and in the page-specific
   stylesheets) reads one of these variables instead of a literal font name,
   and js/tailwind-config.js points its fontFamily config at the same
   variables, so Tailwind utilities (font-sans, font-headline, font-body,
   font-label, font-serif) pick up the change too without editing that file.
   The one thing a variable can't reach: the Google Fonts <link> repeated in
   every page's <head> still has to be updated by hand (see the comment
   next to it, and "Changing the site font" in CLAUDE.md) since there's no
   shared include to hold it.
   --------------------------------------------------------------------- */
:root {
    --font-sans: "Heebo", sans-serif;
    --font-handwritten: "Playpen Sans", "Heebo", cursive;
    /* Not the brand font — just a decorative quotation-mark glyph on the
       letter/story cards, kept independent of --font-sans on purpose. */
    --font-decorative-quote: Georgia, "Times New Roman", serif;
}

/* ---------------------------------------------------------------------
   Base
   --------------------------------------------------------------------- */
.material-symbols-outlined {
    font-variation-settings: 'FILL' 0, 'wght' 400, 'GRAD' 0, 'opsz' 24;
}
body {
    font-family: var(--font-sans);
    background-color: #eef0f2;
}
html {
    scroll-behavior: smooth;
}
/* The fixed top nav is usually one line (~4rem) but wraps to two lines on
   narrow screens once the title no longer fits. --nav-h is the real,
   measured nav height (set by site.js); the 4rem fallback only applies
   before that JS runs. Anything that assumes a fixed nav height reads from
   this variable instead of a hardcoded value, so it stays correct either way. */
main {
    padding-top: var(--nav-h, 4rem);
}
/* Offsets anchor-jump targets so content doesn't land underneath the fixed nav.
   Exactly --nav-h and not a pixel more: a nav-link jump should park the
   section's top edge flush against the nav, with no sliver of the previous
   section still showing above it. The section's own top padding supplies the
   breathing room. */
section[id] {
    scroll-margin-top: var(--nav-h, 4rem);
}
.gold-border { border-color: #7C8CA0; }
.gold-text { color: #7C8CA0; }

/* A faint paper grain over the whole page, so surfaces read as parchment
   rather than flat digital color. Fixed + negative z-index keeps it behind
   all in-flow content without needing to touch every section's stacking. */
body::before {
    content: "";
    position: fixed;
    inset: 0;
    z-index: -1;
    pointer-events: none;
    opacity: 0.05;
    mix-blend-mode: multiply;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* ---------------------------------------------------------------------
   Top nav / mobile menu
   --------------------------------------------------------------------- */
#mobile-nav-panel {
    max-height: 0;
    overflow: hidden;
    transition: max-height 400ms ease-out;
}
#mobile-nav-panel.open {
    max-height: 20rem;
}

/* ---------------------------------------------------------------------
   Scroll-reveal animation
   Driven by site.js: every ".reveal" target gets "reveal-pending" added on
   load, then swapped for "in-view" the first time it crosses the viewport.
   --------------------------------------------------------------------- */
@keyframes reveal-up {
    from { opacity: 0; transform: translateY(24px); }
    to { opacity: 1; transform: translateY(0); }
}
.reveal.reveal-pending {
    opacity: 0;
}
.reveal.in-view {
    animation: reveal-up 700ms ease-out forwards;
}

/* ---------------------------------------------------------------------
   Photo frame — the mounted-photograph treatment used across the site:
   a clean white mat, like a page from a physical photo album, instead of
   a hard dark frame. This is the shared "shape"; each page adds its own
   box-shadow depth and hover behavior in css/<page>.css.
   --------------------------------------------------------------------- */
.photo-frame {
    position: relative;
    background: #ffffff;
    border-radius: 0;
    padding: 0.4rem;
}
.photo-frame-inner {
    display: block;
    border-radius: 0;
    overflow: hidden;
}

/* Light variant for photos sitting on the dark navy section, where a
   navy-on-navy frame would lose all definition. */
.photo-frame-light {
    background: #ffffff;
    border-radius: 0.5rem;
    padding: 0.625rem;
    box-shadow: 0 4px 10px rgba(27, 28, 25, 0.10);
}
.photo-frame-light .photo-frame-inner {
    border-radius: 0.25rem;
    overflow: hidden;
}

/* ---------------------------------------------------------------------
   Category filter pills (gallery + letters pages)
   --------------------------------------------------------------------- */
/* Sticks right below the nav — top offset uses the same real, measured
   --nav-h variable so the bar's own top edge never sits under the nav. */
.filters-sticky {
    position: sticky;
    top: var(--nav-h, 4rem);
}
.filter-scroll {
    scrollbar-width: none;
    -ms-overflow-style: none;
    /* Setting overflow-x (for the horizontal scroll) makes the browser treat
       overflow-y as "auto" too, turning this into a clipping box on both
       axes. Without vertical padding, the active/hover pill's -1px lift and
       box-shadow get clipped clean off — the active pill's top border
       vanishes. Padding gives that lift room inside the scroll box. */
    padding: 6px 2px 10px;
}
.filter-scroll::-webkit-scrollbar {
    display: none;
}
.category-pill {
    background-color: #e9edf1 !important;
    border-color: rgba(124, 140, 160, 0.25) !important;
    transition: background-color 300ms ease-out, color 300ms ease-out, box-shadow 300ms ease-out, border-color 300ms ease-out, transform 200ms ease-out;
}
.category-pill:hover {
    border-color: rgba(124, 140, 160, 0.5) !important;
    box-shadow: 0 8px 18px rgba(27, 28, 25, 0.12);
    transform: translateY(-1px);
}
.category-pill .pill-count {
    color: inherit;
    opacity: 0.5;
    font-variant-numeric: tabular-nums;
    margin-inline-start: 0.15em;
}
.category-pill.active {
    background-color: rgba(124, 140, 160, 0.16) !important;
    border-color: rgba(124, 140, 160, 0.55) !important;
    color: #1A2E44;
    box-shadow: 0 4px 10px rgba(124, 140, 160, 0.18);
    transform: translateY(-1px);
}
.category-pill.active .pill-count {
    opacity: 0.65;
}

/* ---------------------------------------------------------------------
   Memorial bouquet icon ("דם המכבים") — replaces the candle-flame glyph.
   A slow, quiet pulse on each cluster of buds, a gentle sway on each
   branch, and faint embers drifting up from the buds — alive, not bouncy.
   --------------------------------------------------------------------- */
.memorial-bouquet {
    display: inline-block;
    animation: mb-glow 2400ms ease-in-out infinite;
}
.memorial-bouquet .mb-bud,
.memorial-bouquet .mb-branch,
.memorial-bouquet .mb-ember {
    transform-box: fill-box;
    transform-origin: center;
}
@keyframes mb-glow {
    0%, 100% { filter: drop-shadow(0 0 2px rgba(231, 162, 60, 0.3)); }
    50% { filter: drop-shadow(0 0 7px rgba(231, 162, 60, 0.75)); }
}
@keyframes mb-pulse {
    0%, 100% { transform: scale(1); opacity: 1; }
    50% { transform: scale(1.18); opacity: 0.82; }
}
@keyframes mb-sway-a {
    0%, 100% { transform: rotate(-4deg); }
    50% { transform: rotate(4deg); }
}
@keyframes mb-sway-b {
    0%, 100% { transform: rotate(4deg); }
    50% { transform: rotate(-4deg); }
}
@keyframes mb-ember {
    0% { transform: translateY(0) scale(1); opacity: 1; }
    100% { transform: translateY(-18px) scale(0.3); opacity: 0; }
}
.memorial-bouquet .mb-bud {
    animation: mb-pulse 1600ms ease-in-out infinite;
}
.memorial-bouquet .mb-bud.mb-d2 { animation-duration: 1900ms; animation-delay: 400ms; }
.memorial-bouquet .mb-bud.mb-d3 { animation-duration: 1400ms; animation-delay: 800ms; }
.memorial-bouquet .mb-bud.mb-d4 { animation-duration: 1750ms; animation-delay: 1100ms; }
.memorial-bouquet .mb-branch-a { animation: mb-sway-a 3400ms ease-in-out infinite; }
.memorial-bouquet .mb-branch-b { animation: mb-sway-b 3100ms ease-in-out infinite; }
.memorial-bouquet .mb-branch-c { animation: mb-sway-b 3800ms ease-in-out infinite; }
.memorial-bouquet .mb-ember {
    animation: mb-ember 1600ms ease-in infinite;
}
.memorial-bouquet .mb-e2 { animation-delay: 550ms; }
.memorial-bouquet .mb-e3 { animation-delay: 1050ms; }
@media (prefers-reduced-motion: reduce) {
    .memorial-bouquet,
    .memorial-bouquet .mb-bud,
    .memorial-bouquet .mb-branch,
    .memorial-bouquet .mb-ember {
        animation: none;
    }
}

/* Same idea, but for the real דם המכבים photo asset: held still (no
   scale/sway) and just the same warm glow breathing as the SVG version. */
.memorial-photo {
    display: inline-block;
    height: 1em;
    width: auto;
    vertical-align: middle;
    animation: mb-glow 2400ms ease-in-out infinite;
}
@media (prefers-reduced-motion: reduce) {
    .memorial-photo { animation: none; }
}

/* Soft ambient light behind the candle-section flower, standing in for a
   boxed icon badge: a radial gradient has no edge to read as a shape, so it
   avoids the concentric-square look a bordered/rounded container gave here. */
.candle-halo {
    background: radial-gradient(circle, rgba(124, 140, 160, 0.32), rgba(124, 140, 160, 0.12) 45%, rgba(124, 140, 160, 0) 72%);
    animation: candle-halo-pulse 2400ms ease-in-out infinite;
}
@keyframes candle-halo-pulse {
    0%, 100% { opacity: 0.75; transform: scale(1); }
    50% { opacity: 1; transform: scale(1.08); }
}
@media (prefers-reduced-motion: reduce) {
    .candle-halo { animation: none; }
}

/* ---------------------------------------------------------------------
   Top nav links
   --------------------------------------------------------------------- */
/* Same center-out rule the section jump-links on sections.html use: hovering
   a nav item draws the exact underline the current page already wears, so
   the hover previews "this is where you'd land". Drawn as a pseudo-element
   rather than a border-bottom so it can animate without nudging the text. */
.nav-link {
    position: relative;
    padding-bottom: 0.25rem;
    transition: color 300ms ease-out;
}
.nav-link::after {
    content: "";
    position: absolute;
    inset-inline: 0;
    bottom: 0;
    height: 2px;
    background-color: #1A2E44;
    transform: scaleX(0);
    transform-origin: center;
    transition: transform 300ms ease-out;
}
.nav-link:hover::after,
.nav-link:focus-visible::after,
.nav-link.is-active::after {
    transform: scaleX(1);
}
@media (prefers-reduced-motion: reduce) {
    .nav-link::after { transition: none; }
}

/* ---------------------------------------------------------------------
   Prominent nav — once the page's opening navy header has scrolled out of
   view, the translucent nav flips to a solid navy band instead of blending
   into the surface, so it stays impossible to miss and signals there's a
   full nav worth of other pages above, not just this one page's scroll.
   Toggled site-wide by setupNavProminentOnScroll() in site.js.
   --------------------------------------------------------------------- */
nav.nav-prominent {
    background-color: rgba(26, 46, 68, 0.94);
}

nav.nav-prominent a.font-serif {
    color: #ffffff !important;
}

nav.nav-prominent .nav-link {
    color: rgba(255, 255, 255, 0.72) !important;
}

nav.nav-prominent .nav-link:hover,
nav.nav-prominent .nav-link:focus-visible,
nav.nav-prominent .nav-link.is-active {
    color: #ffffff !important;
}

nav.nav-prominent .nav-link::after {
    background-color: #ffffff;
}

nav.nav-prominent #mobile-nav-toggle {
    color: #ffffff !important;
}

/* ---------------------------------------------------------------------
   Typographic polish
   --------------------------------------------------------------------- */
body {
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}
/* Headings that wrap get their lines evened out instead of leaving one or
   two words stranded on the last line — the single most visible difference
   between a hand-set headline and a browser-default one. Body copy gets the
   lighter "pretty" treatment, which only prevents orphans. */
h1, h2, h3, .hero-title {
    text-wrap: balance;
}
p, blockquote, figcaption {
    text-wrap: pretty;
}
/* Underlines sit off the baseline rather than hugging it. */
a {
    text-underline-offset: 0.22em;
    text-decoration-thickness: 1px;
}
/* html { scroll-behavior: smooth } above is a motion effect like any other. */
@media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto; }
}

/* ---------------------------------------------------------------------
   Keyboard focus
   One ring, in the site's own navy, instead of whatever blue each browser
   draws by default. :focus-visible only, so a mouse click never shows it.
   Element-level selectors so this outranks Tailwind's .outline-none without
   touching the form fields, which have their own underline focus state.
   --------------------------------------------------------------------- */
a:focus-visible,
button:focus-visible,
summary:focus-visible,
[tabindex]:focus-visible {
    outline: 2px solid #1A2E44;
    outline-offset: 3px;
}
/* Navy-on-navy is invisible: on the dark sections and the media overlays the
   same ring switches to the light accent. */
.bg-primary :is(a, button):focus-visible,
#lightbox :is(a, button):focus-visible,
#legacy-modal :is(a, button):focus-visible,
#candle-modal :is(a, button):focus-visible {
    outline-color: #b4c8e4;
}

/* ---------------------------------------------------------------------
   Floating elements (the two corner buttons)
   DESIGN.md: shadows on floating elements are extra-diffused and tinted
   from on-surface, never pure black. Tailwind's shadow-2xl is a black
   shadow, which reads as a hard drop shadow against the pale surfaces.
   --------------------------------------------------------------------- */
#scroll-top-btn,
.candle-fab {
    box-shadow: 0 12px 28px rgba(27, 28, 25, 0.14), 0 2px 6px rgba(27, 28, 25, 0.07);
}
#scroll-top-btn:hover,
.candle-fab:hover {
    box-shadow: 0 18px 38px rgba(27, 28, 25, 0.20), 0 3px 8px rgba(27, 28, 25, 0.09);
}
