/* Lunar Delight — minimal dark base shared by root and /4u/.
   Aesthetic to layer on top later (still TBD: editorial almanac /
   midnight observatory / art-deco lunar). Keeping this lean and
   distinctive: serif system stack, deep night background with a
   warm ember and cool dawn vignette, small-caps lang switch. */

:root {
  --ld-bg:        #0a0a0c;
  --ld-bg-2:      #111114;
  --ld-fg:        #e9e6df;
  --ld-fg-dim:    #807a72;
  --ld-accent:    #d6a64a;          /* warm amber — moonlight */
  --ld-rule:      rgba(255, 255, 255, 0.08);

  /* Segoe UI on Windows; native system sans elsewhere. License blocks
     self-hosting Segoe UI, so we keep this as a system stack. Noto
     fallbacks cover scripts that system fonts may not have. Each Noto
     family is loaded via @font-face with unicode-range, so browsers
     only download the subsets that actually render on a given page. */
  --ld-sans:      'Segoe UI',
                  -apple-system, BlinkMacSystemFont,
                  'Helvetica Neue', Arial,
                  'Noto Sans Devanagari',
                  'Noto Sans JP',
                  'Noto Sans Thai',
                  'Noto Serif SC',
                  sans-serif;

  --ld-pad-x:     clamp(1.25rem, 4vw, 2.5rem);
  --ld-header-h:  56px;
  --ld-container-max: 72rem;
}

* { box-sizing: border-box; }

html {
  scroll-behavior: smooth;
}

html, body {
  margin: 0;
  padding: 0;
  background: var(--ld-bg);
  color: var(--ld-fg);
  font-family: var(--ld-sans);
  font-size: 17px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}

/* ---------- modern grid container ---------- */
/* Centered max-width wrapper used inside header, footer, and sections.
   Keeps content readable on wide screens; flexes down via clamp padding
   on narrow ones. */
.container {
  width: 100%;
  max-width: var(--ld-container-max);
  margin-inline: auto;
  padding-inline: var(--ld-pad-x);
}

/* Animated bloom positions — registered so they're interpolatable.
   Four blobs drift independently on offset (prime-ish) periods so
   the composition never quite repeats. Vignette stays put. */
@property --b1x { syntax: '<percentage>'; inherits: false; initial-value: 78%; }
@property --b1y { syntax: '<percentage>'; inherits: false; initial-value: -5%; }
@property --b2x { syntax: '<percentage>'; inherits: false; initial-value: 12%; }
@property --b2y { syntax: '<percentage>'; inherits: false; initial-value: 28%; }
@property --b3x { syntax: '<percentage>'; inherits: false; initial-value: 55%; }
@property --b3y { syntax: '<percentage>'; inherits: false; initial-value: 112%; }
@property --b4x { syntax: '<percentage>'; inherits: false; initial-value: 95%; }
@property --b4y { syntax: '<percentage>'; inherits: false; initial-value: 75%; }

@keyframes ld-drift-1 { to { --b1x: 60%; --b1y: 18%; } }
@keyframes ld-drift-2 { to { --b2x: 32%; --b2y: 10%; } }
@keyframes ld-drift-3 { to { --b3x: 72%; --b3y: 92%; } }
@keyframes ld-drift-4 { to { --b4x: 70%; --b4y: 88%; } }

body {
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  background-color: #03050a;
}

/* ---------- .bg-night : reusable atmospheric background --------------------
   Apply to any section that should carry the deep-blue gradient blooms +
   calendar ring backplate. Self-contained: gradients are scoped to the
   element, the calendar lives on the element's ::before, and `overflow:
   hidden` keeps the oversized blooms from bleeding into neighbouring
   sections. Variant classes (.bg-night--cool, etc.) can override colours,
   bloom counts, animation, opacity later — keeping the structural rules
   here as the base. */

.bg-night {
  position: relative;
  isolation: isolate;          /* contains ::before z-index: -1 */
  overflow: hidden;
  background-color: #03050a;
  background-image:
    radial-gradient(130% 95% at 50% 50%, transparent 25%, rgba(0, 0, 0, 0.70) 100%),
    radial-gradient(60% 50% at var(--b1x) var(--b1y), rgba(85, 95, 180, 0.24), transparent 70%),
    radial-gradient(70% 60% at var(--b2x) var(--b2y), rgba(30, 60, 145, 0.38), transparent 75%),
    radial-gradient(90% 80% at var(--b3x) var(--b3y), rgba(18, 42, 115, 0.55), transparent 75%),
    radial-gradient(50% 40% at var(--b4x) var(--b4y), rgba(55, 50, 120, 0.30), transparent 75%);
  animation:
    ld-drift-1 67s ease-in-out infinite alternate,
    ld-drift-2 89s ease-in-out infinite alternate,
    ld-drift-3 73s ease-in-out infinite alternate,
    ld-drift-4 97s ease-in-out infinite alternate;
}

.bg-night::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  /* Per-language, per-date image. Source URL is set as a CSS custom
     property on the .bg-night element via PHP (see ld_hero_bg_url()). */
  background-image: var(--bg-image, url('/data/assets/cring/cring_20260506_en.png'));
  background-position: center center;
  background-repeat: no-repeat;
  background-size: 110vmax auto;
  opacity: 0.28;
  pointer-events: none;
  /* enters second in the orchestration: title settles, then the
     calendar wheel slowly rotates into alignment as it fades in,
     then the actions land on top. */
  animation: bg-night-in 1700ms cubic-bezier(0.2, 0.7, 0.2, 1) 700ms both;
}

@keyframes bg-night-in {
  from {
    opacity: 0;
    transform: rotate(-4deg);
  }
  to {
    opacity: 0.28;
    transform: rotate(0deg);
  }
}

@media (prefers-reduced-motion: reduce) {
  .bg-night,
  .bg-night::before { animation: none; }
}

/* ---------- header ---------- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 10;
  /* No vertical padding — site-header__inner's min-height: var(--ld-header-h)
     defines the entire bar height, so sticky offsets in other elements
     (top: var(--ld-header-h)) align exactly with the header's bottom edge.
     Also: position context for the lang-switch which is absolutely
     positioned at the viewport's right edge, outside the .container. */
  border-bottom: 1px solid var(--ld-rule);
  background: rgba(255, 255, 255, 0.04);
  -webkit-backdrop-filter: blur(10px) saturate(140%);
          backdrop-filter: blur(10px) saturate(140%);
  transition: background 260ms ease, border-color 260ms ease, color 260ms ease;
}


/* Inverted header state — toggled by JS when a bright section sits
   directly behind the sticky header. Light frosted-glass bg, dark text,
   logo flipped via filter so the white mark reads on the light bg. */
.site-header.is-on-light {
  background: rgba(255, 255, 255, 0.65);
  border-bottom-color: rgba(0, 0, 0, 0.12);
  color: #0a0a0e;
}

.site-header.is-on-light .brand img {
  filter: invert(1);
  transition: filter 260ms ease;
}

.site-header .brand img { transition: filter 260ms ease; }

.site-header.is-on-light .primary-nav a {
  color: rgba(10, 10, 14, 0.6);
}
.site-header.is-on-light .primary-nav a:hover {
  color: #0a0a0e;
  border-bottom-color: var(--ld-accent);
}

.site-header.is-on-light .lang-switch__btn {
  color: #0a0a0e;
  background: rgba(0, 0, 0, 0.04);
  border-color: rgba(0, 0, 0, 0.18);
}
.site-header.is-on-light .lang-switch__btn:hover {
  border-color: rgba(214, 166, 74, 0.55);
  background: rgba(0, 0, 0, 0.06);
}
.site-header.is-on-light .lang-switch[open] .lang-switch__btn {
  border-color: rgba(214, 166, 74, 0.65);
  background: rgba(0, 0, 0, 0.08);
}

.site-header__inner {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  min-height: var(--ld-header-h);
}

/* push brand to the left, leaving nav + lang switch on the right */
.site-header__inner > .brand { margin-right: auto; }

.brand {
  display: inline-flex;
  align-items: center;
  line-height: 0;
  text-decoration: none;
}

.brand img {
  display: block;
  height: 32px;
  width: auto;
}

/* ---------- primary nav (in-header) ---------- */

.primary-nav {
  display: inline-flex;
  align-items: center;
  gap: 1.6rem;
  letter-spacing: 0.08em;
  font-size: 0.78rem;
  text-transform: uppercase;
}

.primary-nav a {
  position: relative;
  color: var(--ld-fg-dim);
  text-decoration: none;
  padding: 0.3rem 0;
  border-bottom: 1px solid transparent;
  transition: color 160ms ease, border-color 160ms ease;
}

/* 1px vertical separator centered in the gap between adjacent items —
   extends above and below the link box so the dividers feel architectural
   rather than tucked-in. Uses :last-of-type so the separator only sits
   between text links, not before the trailing pill button. */
.primary-nav a:not(:last-of-type)::after {
  content: '';
  position: absolute;
  right: -0.8rem;       /* half of .primary-nav gap (1.6rem) */
  top: -0.3rem;
  bottom: -0.3rem;
  width: 1px;
  background: rgba(255, 255, 255, 0.22);
}

.site-header.is-on-light .primary-nav a:not(:last-of-type)::after {
  background: rgba(0, 0, 0, 0.28);
}

/* Amber pill button — last item in the primary nav. Triggers the
   gift modal via dialog.js (data-open-dialog). */
.primary-nav .nav-pill {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.4rem 0.95rem;
  background: var(--ld-accent);
  color: #1a1500;
  border: 1px solid var(--ld-accent);
  border-radius: 999px;
  font: inherit;
  font-size: 0.74rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  font-weight: 500;
  cursor: pointer;
  transition: background 200ms ease, box-shadow 200ms ease, transform 200ms ease;
}

.primary-nav .nav-pill:hover {
  background: #e6b85c;
  border-color: #e6b85c;
  box-shadow: 0 6px 22px -8px rgba(214, 166, 74, 0.55);
}

.primary-nav .nav-pill:active { transform: scale(0.97); }

.primary-nav .nav-pill:focus-visible {
  outline: 2px solid var(--ld-accent);
  outline-offset: 3px;
}

.primary-nav .nav-pill i { font-size: 0.85em; opacity: 0.8; }

.primary-nav a:hover {
  color: var(--ld-fg);
  border-bottom-color: var(--ld-accent);
}

/* Selected state: server-side for URL items (aria-current="page"),
   client-side via scroll-spy for in-page anchors. Amber underline +
   soft glow to feel like the link is lit from behind. */
.primary-nav a.is-active,
.primary-nav a[aria-current="page"] {
  color: var(--ld-fg);
  border-bottom-color: var(--ld-accent);
  text-shadow: 0 0 12px rgba(214, 166, 74, 0.45);
}

/* Same selected treatment, adapted for the inverted (light) header. */
.site-header.is-on-light .primary-nav a.is-active,
.site-header.is-on-light .primary-nav a[aria-current="page"] {
  color: #0a0a0e;
  border-bottom-color: var(--ld-accent);
  text-shadow: none;
}

@media (max-width: 44rem) {
  /* On small screens drop the in-header nav so brand + lang switch keep room.
     Sections are still reachable by scrolling; nav can become a drawer later. */
  .primary-nav { display: none; }
}

/* ---------- language switch (custom dropdown via <details>) ---------- */

.lang-switch {
  position: relative;
  letter-spacing: 0.08em;
  font-size: 0.78rem;
  text-transform: uppercase;
}

.lang-switch__btn {
  list-style: none;             /* hide default summary marker (FF) */
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.45rem 0.95rem;
  color: var(--ld-fg);
  background: rgba(255, 255, 255, 0.025);
  border: 1px solid var(--ld-rule);
  border-radius: 999px;
  user-select: none;
  transition: border-color 180ms ease, background 180ms ease;
}

.lang-switch__btn::-webkit-details-marker { display: none; }   /* Safari */
.lang-switch__btn::marker                  { content: ''; }     /* spec  */
.lang-switch__btn:focus-visible {
  outline: 2px solid var(--ld-accent);
  outline-offset: 2px;
}

.lang-switch__btn:hover {
  border-color: rgba(214, 166, 74, 0.45);
  background: rgba(255, 255, 255, 0.045);
}

.lang-switch[open] .lang-switch__btn {
  border-color: rgba(214, 166, 74, 0.55);
  background: rgba(255, 255, 255, 0.05);
}

.lang-switch__chev {
  font-size: 0.65rem;
  opacity: 0.7;
  transition: transform 240ms ease;
}

.lang-switch[open] .lang-switch__chev { transform: rotate(180deg); }

.lang-switch__menu {
  position: absolute;
  top: calc(100% + 0.55rem);
  right: 0;
  min-width: 11rem;
  margin: 0;
  padding: 0.35rem;
  list-style: none;
  background: rgba(10, 12, 22, 0.92);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  border: 1px solid var(--ld-rule);
  border-radius: 12px;
  box-shadow: 0 24px 60px -20px rgba(0, 0, 0, 0.7);
  z-index: 50;
  transform-origin: top right;
  animation: lang-menu-in 180ms ease-out;
}

@keyframes lang-menu-in {
  from { opacity: 0; transform: translateY(-4px) scale(0.98); }
  to   { opacity: 1; transform: none; }
}

/* --up modifier: open the menu UPWARDS from the trigger. Used in the
   footer where dropping below would either overflow the viewport or
   break out of the footer's bounds. Anchored to the trigger's LEFT
   edge (since the trigger is left-aligned in its footer column) and
   capped at min(20rem, viewport-minus-chrome) so it can never spill
   past the top of the viewport. */
.lang-switch--up .lang-switch__menu {
  top: auto;
  bottom: calc(100% + 0.55rem);
  left: 0;
  right: auto;
  transform-origin: bottom left;
  max-height: calc(100vh - 6rem);
  overflow-y: auto;
  animation-name: lang-menu-in-up;
}

.lang-switch--up .lang-switch__chev { transform: rotate(180deg); }
.lang-switch--up[open] .lang-switch__chev { transform: rotate(0deg); }

@keyframes lang-menu-in-up {
  from { opacity: 0; transform: translateY(4px) scale(0.98); }
  to   { opacity: 1; transform: none; }
}

.lang-switch__opt {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.55rem 0.8rem;
  border-radius: 8px;
  text-decoration: none;
  color: var(--ld-fg-dim);
  letter-spacing: 0.06em;
  transition: background 140ms ease, color 140ms ease;
}

.lang-switch__opt:hover,
.lang-switch__opt:focus-visible {
  background: rgba(255, 255, 255, 0.05);
  color: var(--ld-fg);
  outline: none;
}

.lang-switch__opt.is-active { color: var(--ld-fg); }

@media (prefers-reduced-motion: reduce) {
  .lang-switch__menu { animation: none; }
  .lang-switch__chev { transition: none; }
}

/* main fills the space between header and footer */
main { flex: 1 1 auto; }

/* ---------- hero (generic placeholder, e.g. for /4u/) ---------- */

.hero {
  min-height: 60vh;
}

/* ---------- home hero (root /) ---------- */

.hero--home {
  position: relative;
  display: grid;
  grid-template-rows: 1fr auto;
  justify-items: center;
  min-height: calc(100dvh - var(--ld-header-h));
  padding: 3.5rem var(--ld-pad-x) 2rem;
  row-gap: 2rem;
  overflow: hidden;
}

/* NASA moon disk, fetched client-side from /api/nasa_moon and
   rotated to the observer's view angle. Positioned absolutely so it
   doesn't disturb the hero grid — the inner + social rows sit on
   top via z-index. Fades in (blur → sharp) once the image loads. */
.hero--home__moon {
  position: absolute;
  top: 50%;
  left: 50%;
  width: clamp(441px, 99vmin, 1470px);
  aspect-ratio: 1 / 1;
  /* The rotation angle from the API lives in --moon-rot; the
     translate centres the disk on the hero. */
  transform: translate(-50%, -50%) rotate(var(--moon-rot, 0deg));
  z-index: 0;
  opacity: 0;
  filter: blur(14px);
  pointer-events: none;
  transition: opacity 900ms cubic-bezier(0.2, 0.7, 0.2, 1),
              filter  900ms cubic-bezier(0.2, 0.7, 0.2, 1);
}
.hero--home__moon.is-loaded {
  opacity: 0.7;
  filter: blur(0);
}
@media (prefers-reduced-motion: reduce) {
  .hero--home__moon {
    transition: opacity 200ms linear;
    filter: none;
  }
  .hero--home__moon.is-loaded { filter: none; }
}

.hero--home__inner {
  position: relative;
  z-index: 1;
  align-self: center;        /* vertically centred in the 1fr row */
  max-width: 38rem;
  text-align: center;
}

.hero--home__social {
  position: relative;
  z-index: 1;
  /* sits in the auto bottom row of the hero grid */
  align-self: end;
}

.hero--home__title {
  font-size: clamp(2rem, 4.6vw, 3rem);
  line-height: 1.1;
  font-weight: 400;
  letter-spacing: -0.012em;
  margin: 0 0 1rem;
  font-style: italic;
  /* a hint of glow on the title */
  text-shadow: 0 0 28px rgba(214, 166, 74, 0.08);
  /* orchestration: title first (focus-pull), then atmosphere (PNG),
     then the actions land last so the eye knows where to act. */
  animation: hero-rise 1000ms cubic-bezier(0.2, 0.7, 0.2, 1) 80ms both;
}

.hero--home .cta-group .cta {
  animation: hero-rise 700ms cubic-bezier(0.2, 0.7, 0.2, 1) both;
}
.hero--home .cta-group .cta:nth-child(1) { animation-delay: 1950ms; }
.hero--home .cta-group .cta:nth-child(2) { animation-delay: 2100ms; }

.hero--home__social li a {
  animation: hero-rise 700ms cubic-bezier(0.2, 0.7, 0.2, 1) both;
}
.hero--home__social li:nth-child(1) a { animation-delay: 2350ms; }
.hero--home__social li:nth-child(2) a { animation-delay: 2450ms; }
.hero--home__social li:nth-child(3) a { animation-delay: 2550ms; }
.hero--home__social li:nth-child(4) a { animation-delay: 2650ms; }

@keyframes hero-rise {
  from {
    opacity: 0;
    transform: translateY(14px);
    filter: blur(6px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
    filter: blur(0);
  }
}

@media (prefers-reduced-motion: reduce) {
  .hero--home__title,
  .hero--home .cta-group .cta,
  .hero--home__social li a { animation: none; }
}

.hero--home__subhead {
  color: var(--ld-fg);
  margin: 0 0 2.4rem;
  font-size: 1rem;
  line-height: 1.55;
  letter-spacing: 0.01em;
  font-style: italic;
  opacity: 0.82;
}

.hero--home__about {
  text-align: left;
  color: var(--ld-fg);
  margin: 0 0 2rem;
  font-size: 1.02rem;
  line-height: 1.72;
  opacity: 0.92;
}

.hero--home__status {
  margin: 0 0 0.35rem;
  color: var(--ld-fg);
  font-size: 1rem;
}

.hero--home__newsletter {
  margin: 0 0 2.6rem;
  color: var(--ld-fg-dim);
  font-size: 0.92rem;
  font-style: italic;
}

/* ---------- social links ---------- */

.social-links {
  display: flex;
  justify-content: center;
  gap: 1.1rem;
  list-style: none;
  margin: 0;
  padding: 0;
}

.social-links a {
  color: var(--ld-fg-dim);
  font-size: 1.15rem;
  display: inline-flex;
  width: 2.6rem;
  height: 2.6rem;
  align-items: center;
  justify-content: center;
  background: rgba(8, 13, 32, 0.55);
  -webkit-backdrop-filter: blur(6px);
          backdrop-filter: blur(6px);
  border: 1px solid var(--ld-rule);
  border-radius: 50%;
  text-decoration: none;
  transition: color 200ms ease, border-color 200ms ease, background 200ms ease, transform 200ms ease;
}

.social-links a:hover {
  color: var(--ld-accent);
  border-color: var(--ld-accent);
  background: rgba(8, 13, 32, 0.7);
  transform: translateY(-2px);
}

/* Compact variant — no border circle, no lift, just an inline icon row.
   Inherits colour from the surrounding text. Used in the footer. */
.social-links--mini {
  display: inline-flex;
  align-items: center;
  gap: 0.7rem;
}
.social-links--mini a {
  width: auto;
  height: auto;
  font-size: 0.72rem;
  color: inherit;
  border: 0;
  border-radius: 0;
  background: transparent;
  transition: color 160ms ease;
}
.social-links--mini a:hover {
  color: var(--ld-accent);
  background: transparent;
  border-color: transparent;
  transform: none;
}

/* ---------- sections (homepage anchored blocks) ---------- */

.section {
  padding-block: clamp(3rem, 6vw, 5rem);
  /* offset for sticky header so #anchor lands below it, not under */
  scroll-margin-top: calc(var(--ld-header-h) + 0.75rem);
}

.section--alt {
  background: rgba(255, 255, 255, 0.04);
  -webkit-backdrop-filter: blur(2px);
          backdrop-filter: blur(2px);
  border-top: 1px solid var(--ld-rule);
}

/* Muted stone-grey panel with a faint cool tint — bright enough for
   dark text, restrained enough to sit between the dark sections.
   Inverts the typography colour without touching the rest of the page. */
.section--light {
  background: #c8c2b6;
  color: #0a0a0e;
  border-top: 1px solid rgba(0, 0, 0, 0.18);
}

.section--light .section__title {
  color: #0a0a0e;
  text-shadow: none;
}

.section--light .prose {
  color: #11131c;
  opacity: 1;
}

.section--light a {
  color: #1a3380;
}

/* social-links sit on a light panel inside .section--light — override
   the dark-theme defaults so they remain visible */
.section--light .social-links {
  margin-top: 2.2rem;
}
.section--light .social-links a {
  color: rgba(10, 10, 14, 0.55);
  border-color: rgba(0, 0, 0, 0.18);
}
.section--light .social-links a:hover {
  color: #1a3380;
  border-color: #1a3380;
  background: rgba(0, 0, 0, 0.03);
}

/* ---------- call-to-action buttons ---------- */

.cta-group {
  display: flex;
  gap: 1rem;
  flex-wrap: wrap;
  justify-content: center;
  margin-top: 2.5rem;
}

.cta {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.8rem 1.5rem;
  font: inherit;
  font-size: 0.95rem;
  font-weight: 500;
  letter-spacing: 0.015em;
  text-decoration: none;
  border-radius: 999px;
  border: 1px solid transparent;
  cursor: pointer;
  transition: background 200ms ease, border-color 200ms ease, color 200ms ease, transform 200ms ease, box-shadow 200ms ease;
}

.cta:active { transform: scale(0.97); }
.cta:focus-visible {
  outline: 2px solid var(--ld-accent);
  outline-offset: 3px;
}

.cta i { font-size: 0.95em; }

/* Stacked label variant — main label on top, small italic subtitle
   below. Used for the "Geburtstagsgeschenk / ja, komplett kostenlos"
   primary CTA in the hero. */
.cta--stacked { padding: 0.65rem 1.4rem; align-items: center; }
.cta--stacked .cta__text {
  display: inline-flex;
  flex-direction: column;
  align-items: flex-start;
  line-height: 1.1;
  text-align: left;
}
.cta--stacked .cta__main { font-size: 0.98rem; font-weight: 500; }
.cta--stacked .cta__sub  {
  font-size: 0.7rem;
  font-weight: 400;
  font-style: italic;
  opacity: 0.78;
  margin-top: 0.18rem;
}

.cta--primary {
  background: var(--ld-accent);
  color: #1a1500;
  box-shadow: 0 10px 32px -12px rgba(214, 166, 74, 0.55);
}
.cta--primary:hover {
  background: #e6b85c;
  box-shadow: 0 14px 38px -12px rgba(214, 166, 74, 0.7);
}

.cta--ghost {
  background: rgba(255, 255, 255, 0.04);
  color: var(--ld-fg);
  border-color: rgba(255, 255, 255, 0.18);
}
.cta--ghost:hover {
  border-color: var(--ld-accent);
  color: var(--ld-accent);
  background: rgba(214, 166, 74, 0.08);
}

/* ---------- modal dialog (native <dialog>) ---------- */

.dialog {
  width: min(28rem, calc(100vw - 2rem));
  max-width: 100%;
  /* Viewport-fixed: native top-layer + explicit centering for safety. */
  position: fixed;
  inset: 0;
  margin: auto;
  padding: 2.2rem 1.8rem 1.6rem;
  background: rgba(10, 12, 22, 0.95);
  -webkit-backdrop-filter: blur(18px);
          backdrop-filter: blur(18px);
  color: var(--ld-fg);
  border: 1px solid var(--ld-rule);
  border-radius: 18px;
  box-shadow: 0 30px 80px -20px rgba(0, 0, 0, 0.7);
}

/* Body scroll-lock while any dialog is open. */
body.dialog-open { overflow: hidden; }

.dialog::backdrop {
  background: rgba(3, 5, 10, 0.6);
  -webkit-backdrop-filter: blur(4px);
          backdrop-filter: blur(4px);
}

.dialog[open] {
  animation: dialog-in 240ms cubic-bezier(0.2, 0.7, 0.2, 1);
}
.dialog[open]::backdrop {
  animation: dialog-backdrop-in 240ms ease-out;
}

@keyframes dialog-in {
  from { opacity: 0; transform: translateY(8px) scale(0.97); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}
@keyframes dialog-backdrop-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

.dialog__close {
  position: absolute;
  top: 0.55rem;
  right: 0.55rem;
  width: 2rem;
  height: 2rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: none;
  color: var(--ld-fg-dim);
  font-size: 0.95rem;
  border-radius: 50%;
  cursor: pointer;
  transition: color 160ms ease, background 160ms ease;
}
.dialog__close:hover {
  color: var(--ld-fg);
  background: rgba(255, 255, 255, 0.06);
}

.dialog__title {
  font-size: 1.35rem;
  font-weight: 500;
  letter-spacing: -0.005em;
  margin: 0 0 0.7rem;
}

.dialog__body {
  color: var(--ld-fg-dim);
  margin: 0 0 1.6rem;
  line-height: 1.62;
  font-size: 0.95rem;
}

@media (prefers-reduced-motion: reduce) {
  .dialog[open], .dialog[open]::backdrop { animation: none; }
}

/* ---------- gift modal — two-column builder ---------- */

.dialog--gift {
  width:      min(80rem, calc(100vw - 4rem));
  max-height: calc(100vh - 4rem);   /* safety cap on tiny screens */
  padding: 0;            /* image flush to top + left edge */
  overflow: hidden;      /* clip image to dialog's rounded corners */
  /* height is intentionally unset — dialog hugs its content
     (image at 1:1 aspect-ratio in the left column + the actions
     strip beneath it). The form column stretches to match. */
}

.gift {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0;
  align-items: stretch;
}

.gift__preview {
  display: flex;
  flex-direction: column;
}

.gift__frame {
  position: relative;
  aspect-ratio: 1 / 1;
  width: 100%;
  background: #03050a;
  overflow: hidden;
  /* No border, no border-radius — image sits flush against the
     dialog's top-left rounded corner (clipped by dialog overflow). */
}

.gift__image {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  /* Default (no .is-loaded) state: invisible + blurred + slightly
     zoomed. JS removes .is-loaded between renders to snap back to
     this state, then re-adds it to fire the keyframe animation. */
  opacity: 0;
  filter: blur(14px);
  transform: scale(1.04);
}

.gift__image.is-loaded {
  animation: gift-image-reveal 700ms cubic-bezier(0.2, 0.7, 0.2, 1) forwards;
}

@keyframes gift-image-reveal {
  from {
    opacity: 0;
    filter: blur(14px);
    transform: scale(1.04);
  }
  to {
    opacity: 1;
    filter: blur(0);
    transform: scale(1);
  }
}

@media (prefers-reduced-motion: reduce) {
  .gift__image.is-loaded {
    animation: none;
    opacity: 1;
    filter: none;
    transform: none;
  }
}

/* Spinner + error states overlay the image. */
.gift__spinner,
.gift__error {
  position: absolute;
  inset: 0;
  display: grid;
  place-content: center;
  place-items: center;
  gap: 0.6rem;
  color: var(--ld-fg);
  text-align: center;
  padding: 1rem;
  background: rgba(3, 5, 10, 0.55);
  -webkit-backdrop-filter: blur(2px);
          backdrop-filter: blur(2px);
}
/* The class above sets display: grid, which overrides the UA rule
   for the hidden attribute. Restore the hide-when-hidden behavior. */
.gift__spinner[hidden],
.gift__error[hidden] {
  display: none;
}
.gift__spinner p { margin: 0; font-size: 0.85rem; }
.gift__error i { font-size: 1.8rem; color: rgba(240, 120, 120, 0.95); }
.gift__error p { margin: 0; font-size: 0.9rem; }

.spinner {
  width: 255px;
  height: 255px;
  border: 2px solid rgba(255, 255, 255, 0.18);
  border-top-color: var(--ld-accent);
  border-radius: 50%;
  animation: spin 900ms linear infinite;
}

/* Render-time stopwatch — tiny yellow pill in the bottom-right of
   the image frame. JS toggles `.is-fading` to play the fade-out.
   Bottom-right corner is squared off (mirroring the Update Moon
   button) so the pill visually anchors into the frame corner. */
.gift__timer {
  position: absolute;
  bottom: 12px;
  right: 12px;
  background: var(--ld-accent);
  color: #000;
  font-size: 0.78rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.02em;
  padding: 4px 10px;
  border-radius: 999px;
  border-bottom-right-radius: 0;
  pointer-events: none;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.35);
  z-index: 3;
  opacity: 1;
  transition: opacity 600ms ease;
}
.gift__timer.is-fading { opacity: 0; }
@keyframes spin { to { transform: rotate(360deg); } }

/* Shared bottom-action-bar styling for both columns: Download row in
   the preview column (.gift__actions) and Submit row in the form
   column (.form-row--submit). Same padding, border, gap, and button
   size — so the two buttons sit identically along the bottom of the
   modal. The form-column selector is .gift__form .form-row--submit
   (specificity 0,2,0) so it beats the generic .form-row column rules. */
.gift__actions,
.gift__form .form-row--submit {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  gap: 0.6rem;
  align-items: center;
  padding: 0.9rem 1rem;
  border-top: 1px solid var(--ld-rule);
  margin: 0;
}
.gift__form .form-row--submit { margin-top: auto; }

.gift__actions .cta,
.gift__form .form-row--submit .cta {
  padding: 0.55rem 0.95rem;
  font-size: 0.84rem;
  letter-spacing: 0.02em;
}

/* Update Moon: keep the pill shape on three corners but square off
   the top-left so the button visually anchors into the form column's
   border-top rule. */
.gift__form .form-row--submit .cta[data-gift-submit] {
  border-top-left-radius: 0;
}

.gift__form {
  display: flex;
  flex-direction: column;
  border-left: 1px solid var(--ld-rule);
}
.gift__form-title {
  margin: 0;
  padding: 1.2rem 1.4rem 0 1.2rem;
  font-size: 1rem;
  font-weight: 500;
  letter-spacing: -0.005em;
  color: var(--ld-fg);
}
.gift__form > form {
  display: flex;
  flex-direction: column;
  flex: 1;
}

/* ---------- background picker ---------- */

.bg-picker {
  position: relative;
  margin-top: 0.1rem;
}

.bg-picker__cards {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0.4rem;
}

.bg-card {
  aspect-ratio: 1 / 1;
  background-size: cover;
  background-position: center;
  /* Subtle baseline border so unselected cards still show a frame.
     Hover/focus/selected swap the colour to amber. */
  border: 2px solid rgba(255, 255, 255, 0.18);
  border-radius: 6px;
  padding: 0;
  cursor: pointer;
  transition: border-color 160ms ease, transform 160ms ease, box-shadow 160ms ease;
  outline: none;
  /* Entry animation — fires once when the card is inserted into the
     DOM (every reload re-creates the cards). Staggered via nth-child
     so the three cards cascade in. */
  animation: bg-card-in 520ms cubic-bezier(0.2, 0.7, 0.2, 1) both;
}
.bg-card:nth-child(1) { animation-delay:   0ms; }
.bg-card:nth-child(2) { animation-delay:  60ms; }
.bg-card:nth-child(3) { animation-delay: 120ms; }
.bg-card:nth-child(4) { animation-delay: 180ms; }
.bg-card:nth-child(5) { animation-delay: 240ms; }
.bg-card:nth-child(6) { animation-delay: 300ms; }
.bg-card:nth-child(7) { animation-delay: 360ms; }
.bg-card:nth-child(8) { animation-delay: 420ms; }

@keyframes bg-card-in {
  from {
    opacity: 0;
    transform: scale(0.92);
    filter: blur(6px);
  }
  to {
    opacity: 1;
    transform: scale(1);
    filter: blur(0);
  }
}

@media (prefers-reduced-motion: reduce) {
  .bg-card { animation: none; }
}
.bg-card:hover  { border-color: rgba(214, 166, 74, 0.5); }
.bg-card:focus-visible { border-color: var(--ld-accent); }
.bg-card.is-selected {
  border-color: var(--ld-accent);
  box-shadow: 0 4px 14px -6px rgba(214, 166, 74, 0.55);
}

/* Reload button — sits as a circle in the top-right corner of the
   cards grid, partly behind the corner card. */
.bg-picker__reload {
  position: absolute;
  top: -0.5rem;
  right: -0.5rem;
  width: 1.85rem;
  height: 1.85rem;
  background: rgba(214, 166, 74, 0.92);
  color: #1a1500;
  border: 1px solid rgba(0, 0, 0, 0.2);
  border-radius: 50%;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 0.72rem;
  z-index: 1;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.45);
  transition: transform 220ms ease, background 160ms ease;
}
.bg-picker__reload:hover {
  background: var(--ld-accent);
  transform: rotate(90deg);
}
.bg-picker__reload:active { transform: rotate(180deg); }
.bg-picker__reload.is-spinning { animation: bg-reload-spin 600ms cubic-bezier(0.35, 0, 0.25, 1); }
@keyframes bg-reload-spin {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}
/* The non-submit form rows (date / time / location) keep the
   form-column padding and tighter gap. Submit row is excluded so the
   shared action-bar styling above takes effect. */
.gift__form .form-row:not(.form-row--submit) {
  gap: 0.4rem;
  padding: 0 1.4rem 0 1.2rem;
}
.gift__form .form-row:not(.form-row--submit):first-child { padding-top: 1.4rem; }
.gift__form .form-row:not(.form-row--submit) + .form-row:not(.form-row--submit) { padding-top: 1rem; }
.gift__form input { padding: 0.55rem 0.75rem; font-size: 0.92rem; }

/* Inline row inside the gift form: two fields side-by-side. The
   row gap (0.4rem above) would be too tight as a column gap, so
   bump it. Each .form-field stays a vertical stack. */
.gift__form .form-row--inline { gap: 0.9rem; }
.gift__form .form-field { gap: 0.4rem; }

/* ---------- date quick-pick chips + flatpickr override ---------- */

.date-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.32rem;
}
.date-chip {
  font: inherit;
  font-size: 0.74rem;
  letter-spacing: 0.02em;
  padding: 0.28rem 0.6rem;
  background: rgba(255, 255, 255, 0.04);
  color: var(--ld-fg-dim);
  border: 1px solid var(--ld-rule);
  border-radius: 999px;
  cursor: pointer;
  transition: color 140ms ease, border-color 140ms ease, background 140ms ease;
}
.date-chip:hover,
.date-chip:focus-visible {
  color: var(--ld-fg);
  border-color: rgba(214, 166, 74, 0.45);
  outline: none;
}
.date-chip:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

/* Flatpickr theme override — adopt the celestial palette so the
   popup feels native to the rest of the site. */
.flatpickr-input[data-flatpickr] { cursor: pointer; }

.flatpickr-calendar {
  background: rgba(10, 12, 22, 0.97);
  -webkit-backdrop-filter: blur(14px);
          backdrop-filter: blur(14px);
  border: 1px solid var(--ld-rule);
  border-radius: 12px;
  box-shadow: 0 24px 60px -20px rgba(0, 0, 0, 0.7);
  font-family: inherit;
  color: var(--ld-fg);
}
.flatpickr-months .flatpickr-month,
.flatpickr-current-month { color: var(--ld-fg); }
.flatpickr-current-month .flatpickr-monthDropdown-months,
.flatpickr-current-month input.cur-year { color: var(--ld-fg); background: transparent; }
.flatpickr-weekdays {
  height: auto;
  padding-block: 0.55rem 0.4rem;
}
span.flatpickr-weekday {
  color: var(--ld-fg-dim);
  font-weight: 500;
  font-size: 0.78rem;
  letter-spacing: 0.04em;
  padding-block: 0.25rem;
  line-height: 1.4;
}

.flatpickr-day {
  color: var(--ld-fg);
  border-radius: 8px;
}
.flatpickr-day.today {
  border-color: rgba(214, 166, 74, 0.55);
  color: var(--ld-fg);
}
.flatpickr-day.today:hover { color: #1a1500; background: var(--ld-accent); border-color: var(--ld-accent); }
.flatpickr-day:hover {
  background: rgba(214, 166, 74, 0.18);
  border-color: rgba(214, 166, 74, 0.4);
}
.flatpickr-day.selected,
.flatpickr-day.selected:hover {
  background: var(--ld-accent);
  border-color: var(--ld-accent);
  color: #1a1500;
  font-weight: 500;
}
.flatpickr-day.flatpickr-disabled {
  color: rgba(233, 230, 223, 0.25);
}
.flatpickr-months .flatpickr-prev-month,
.flatpickr-months .flatpickr-next-month { fill: var(--ld-fg); color: var(--ld-fg); }
.flatpickr-months .flatpickr-prev-month:hover svg,
.flatpickr-months .flatpickr-next-month:hover svg { fill: var(--ld-accent); }

/* Time slider: full-width range with amber accent + tabular readout
   in the label. */
.gift__form input[type="range"] {
  width: 100%;
  padding: 0;
  background: transparent;
  border: 0;
  accent-color: var(--ld-accent);
}

.time-readout {
  margin-left: 0.5rem;
  padding: 0.05rem 0.4rem;
  font-size: 0.78rem;
  color: var(--ld-fg);
  background: rgba(214, 166, 74, 0.18);
  border-radius: 4px;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.03em;
}

/* searchable location dropdown */
.gift__location-wrap { position: relative; }

.gift__suggestions {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  z-index: 5;
  margin: 0;
  padding: 0;
  list-style: none;
  background: rgba(8, 13, 32, 0.95);
  -webkit-backdrop-filter: blur(10px);
          backdrop-filter: blur(10px);
  border: 1px solid var(--ld-rule);
  border-radius: 10px;
  max-height: 14rem;
  overflow-y: auto;
  box-shadow: 0 18px 40px -12px rgba(0, 0, 0, 0.55);
}

.gift__suggestions__item {
  padding: 0.55rem 0.85rem;
  cursor: pointer;
  font-size: 0.86rem;
  line-height: 1.4;
  color: var(--ld-fg);
  border-bottom: 1px solid var(--ld-rule);
  border-left: 3px solid transparent;
  transition: background 120ms ease, color 120ms ease, border-color 120ms ease;
}
.gift__suggestions__item:last-child { border-bottom: 0; }

/* Active state — both keyboard-highlighted (aria-selected="true")
   and mouse-hover. Strong amber tint so it's unmistakable. */
.gift__suggestions__item:hover,
.gift__suggestions__item[aria-selected="true"] {
  background: rgba(214, 166, 74, 0.18);
  color: #fff;
  border-left-color: var(--ld-accent);
}

/* Make the close button visible against the dark image at top-left. */
.dialog--gift .dialog__close {
  background: rgba(0, 0, 0, 0.45);
  color: rgba(255, 255, 255, 0.85);
  z-index: 5;
  top: 0.55rem;
  right: 0.55rem;
}
.dialog--gift .dialog__close:hover {
  background: rgba(0, 0, 0, 0.65);
  color: white;
}

/* Mobile-only consolidated action bar (Download / Share / Update Moon).
   Hidden on desktop — the buttons live inside .gift__preview /
   .form-row--submit there. The mobile media query below shows it. */
.gift__mobile-bar { display: none; }

@media (max-width: 40rem) {
  /* Fullscreen modal — no margin, no rounded corners, fills the viewport.
     100dvh handles the iOS / Android URL-bar overlap correctly. */
  .dialog--gift {
    width: 100vw;
    height: 100dvh;
    max-width:  none;
    max-height: 100dvh;
    margin: 0;
    inset: 0;
    border-radius: 0;
  }

  /* .gift becomes the single scroll viewport. Sticky preview at top,
     form in the middle, sticky submit at bottom — all anchored here. */
  .gift {
    grid-template-columns: 1fr;
    height: 100dvh;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
  }

  /* Preview (frame + DL/Share strip) pins to the top. Frame keeps its
     desktop 1:1 aspect so the full moon disk is visible — `object-fit:
     cover` would crop top/bottom in a non-square frame.
     The 1px border-bottom stays glued to the sticky element, giving a
     fixed visual seam at the preview's edge while the form scrolls. */
  .gift__preview {
    position: sticky;
    top: 0;
    z-index: 3;
    background: var(--ld-bg);
    border-bottom: 1px solid var(--ld-rule);
  }

  .gift__form {
    border-left: none;
    /* Seam line lives on .gift__preview (border-bottom) so it stays
       glued to the sticky preview as the form scrolls. */
    padding: 0;
  }
  .gift__form .form-row:not(.form-row--submit) {
    padding: 0 0.6rem;
  }
  .gift__form .form-row:not(.form-row--submit):first-child {
    padding-top: 1rem;
  }

  /* Date + Location stay side-by-side. The chips below the date input
     are hidden on mobile to save vertical space — Flatpickr is plenty.
     The explicit grid-template-columns beats the global @28rem rule
     that would otherwise stack every .form-row--inline on tiny screens. */
  .gift__form .form-row--inline {
    grid-template-columns: 1fr 1fr;
    gap: 0.6rem;
  }
  .gift__form .date-chips {
    display: none;
  }

  /* Background picker: 3 thumb-friendly cards in a single row, with a
     small breathing space below so the cards don't sit flush against
     the mobile action bar. */
  .bg-picker__cards {
    grid-template-columns: repeat(3, 1fr);
  }
  .bg-picker {
    padding-bottom: 10px;
  }

  /* The desktop DL/Share strip and the desktop Update Moon row are
     replaced on mobile by the consolidated bottom bar below. */
  .gift__actions { display: none; }
  .gift__form .form-row--submit { display: none; }

  /* Mobile bottom bar: three buttons in a single row, sticky-bottom
     so they're always reachable while the form scrolls above. */
  .gift__mobile-bar {
    display: flex;
    flex-direction: row;
    gap: 0.4rem;
    /* Tight gap above the buttons; a touch more below to clear the
       device's bottom edge / home indicator. */
    padding: 0.3rem 0.5rem 0.5rem;
    border-top: 1px solid var(--ld-rule);
    position: sticky;
    bottom: 0;
    z-index: 3;
    background: var(--ld-bg);
  }
  .gift__mobile-bar .cta {
    flex: 1 1 0;
    min-width: 0;
    padding: 0.35rem 0.4rem;
    font-size: 0.78rem;
    letter-spacing: 0.02em;
    white-space: nowrap;
    justify-content: center;
  }
  .gift__mobile-bar .cta i {
    font-size: 0.85rem;
  }

  /* Cap the autocomplete list so it can't push the layout off-screen. */
  .gift__suggestions {
    max-height: 12rem;
  }

  /* Smaller spinner — 255px is too dominant relative to the mobile
     preview frame. */
  .spinner {
    width:  150px;
    height: 150px;
  }
}

/* The spinner rotation is intentionally exempt from reduced-motion:
   it's a small, slow (900ms) essential loading indicator and the
   iOS/iPadOS "Reduce Motion" setting would otherwise leave a static
   ring with no feedback. Per WCAG, essential animations are allowed. */

.section__title {
  font-size: clamp(1.6rem, 3.6vw, 2.2rem);
  font-weight: 400;
  font-style: italic;
  letter-spacing: -0.012em;
  margin: 0 0 1rem;
  text-shadow: 0 0 24px rgba(214, 166, 74, 0.08);
}

.section__lead {
  color: var(--ld-fg-dim);
  font-size: 1rem;
  line-height: 1.6;
  max-width: 38rem;
  margin: 0 0 2.5rem;
}

.prose {
  max-width: 38rem;
  color: var(--ld-fg);
  opacity: 0.92;
  line-height: 1.72;
}

.prose p { margin: 0 0 1rem; }
.prose p:last-child { margin-bottom: 0; }

/* ---------- card grid ---------- */

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: 1.25rem;
}

.card {
  padding: 1.5rem 1.4rem;
  background: rgba(255, 255, 255, 0.025);
  border: 1px solid var(--ld-rule);
  border-radius: 14px;
  -webkit-backdrop-filter: blur(6px);
          backdrop-filter: blur(6px);
  transition: border-color 220ms ease, transform 220ms ease, background 220ms ease;
}

.card:hover {
  border-color: rgba(214, 166, 74, 0.42);
  background: rgba(255, 255, 255, 0.045);
  transform: translateY(-2px);
}

.card__icon {
  display: inline-block;
  font-size: 1.35rem;
  color: var(--ld-accent);
  margin-bottom: 0.85rem;
  filter: drop-shadow(0 0 8px rgba(214, 166, 74, 0.32));
}

.card__title {
  font-size: 1.05rem;
  font-weight: 400;
  font-style: italic;
  margin: 0 0 0.5rem;
  letter-spacing: 0.005em;
}

.card p {
  color: var(--ld-fg-dim);
  font-size: 0.93rem;
  line-height: 1.6;
  margin: 0;
}

/* ---------- forms (newsletter) ---------- */

.newsletter-form {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1.6rem 3rem;
  margin-top: 1.75rem;
  color: var(--ld-fg);
}

.newsletter-form__col {
  display: grid;
  gap: 1.4rem;
  align-content: start;
  min-width: 0;
}

.newsletter-form__actions {
  grid-column: 1 / -1;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.9rem;
  margin-top: 0.4rem;
}

.newsletter-form__consent {
  max-width: 38rem;
}

@media (max-width: 44rem) {
  .newsletter-form {
    grid-template-columns: 1fr;
  }
}

.newsletter-form__help,
.newsletter-form__consent {
  margin: 0;
  color: var(--ld-fg-dim);
  line-height: 1.6;
}

.newsletter-form__help {
  font-size: 0.92rem;
  font-style: italic;
}

.newsletter-form__consent {
  font-size: 0.78rem;
  opacity: 0.75;
}

.form-row {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

.form-row--inline {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1rem;
}
.form-row--inline > .form-field {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  min-width: 0;
}

.form-row label,
.form-field label {
  font-size: 0.75rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ld-fg-dim);
}

.form-row input,
.form-field input {
  width: 100%;
  padding: 0.7rem 0.9rem;
  font: inherit;
  font-size: 0.95rem;
  color: var(--ld-fg);
  background: rgba(8, 13, 32, 0.55);
  border: 1px solid var(--ld-rule);
  border-radius: 10px;
  color-scheme: dark;
  transition: border-color 160ms ease, background 160ms ease, box-shadow 160ms ease;
}

.form-row input::placeholder,
.form-field input::placeholder {
  color: rgba(233, 230, 223, 0.35);
}

.form-row input:focus,
.form-field input:focus {
  outline: none;
  border-color: rgba(214, 166, 74, 0.6);
  background: rgba(8, 13, 32, 0.7);
  box-shadow: 0 0 0 4px rgba(214, 166, 74, 0.12);
}

.form-row input:user-invalid,
.form-field input:user-invalid {
  border-color: rgba(220, 80, 80, 0.5);
}


/* ---------- interests fieldset ---------- */

.interests {
  border: none;
  padding: 0;
  margin: 0;
  display: grid;
  gap: 0.7rem;
}

.interests__title {
  padding: 0;
  margin-bottom: 0.4rem;
  font-size: 0.75rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ld-fg-dim);
}

.checkbox {
  display: flex;
  align-items: flex-start;
  gap: 0.7rem;
  cursor: pointer;
  font-size: 0.95rem;
  line-height: 1.5;
  color: var(--ld-fg);
}

.checkbox input[type="checkbox"] {
  appearance: none;
  -webkit-appearance: none;
  flex: 0 0 auto;
  width: 1.05rem;
  height: 1.05rem;
  margin: 0.18rem 0 0;
  background: rgba(8, 13, 32, 0.55);
  border: 1px solid var(--ld-rule);
  border-radius: 4px;
  cursor: pointer;
  display: inline-grid;
  place-content: center;
  transition: border-color 160ms ease, background 160ms ease, box-shadow 160ms ease;
}

.checkbox input[type="checkbox"]:hover {
  border-color: rgba(214, 166, 74, 0.4);
}

.checkbox input[type="checkbox"]:checked {
  border-color: var(--ld-accent);
  background: rgba(214, 166, 74, 0.18);
}

.checkbox input[type="checkbox"]:checked::after {
  content: '✓';
  color: var(--ld-accent);
  font-weight: 700;
  font-size: 0.78rem;
  line-height: 1;
}

.checkbox input[type="checkbox"]:focus-visible {
  outline: none;
  box-shadow: 0 0 0 4px rgba(214, 166, 74, 0.18);
  border-color: rgba(214, 166, 74, 0.6);
}

.checkbox span { flex: 1; }

@media (max-width: 28rem) {
  .form-row--inline { grid-template-columns: 1fr; }
}

/* ---------- astro events page ---------- */

/* dark intro band — title, lead, filter chips. Plain dark panel:
   no animation, no calendar PNG, just a navy-tinted band that spans
   the full page width while content follows .container. */
.astro-hero {
  padding: 1.1rem 0 0.9rem;
  background: #070d20;
  color: var(--ld-fg);
  border-bottom: 1px solid var(--ld-rule);
}
.astro-hero .page__title  { margin: 0 0 0.4rem; font-size: clamp(1.4rem, 3vw, 1.9rem); }
.astro-hero .page__lead   { margin: 0 0 0.85rem; font-size: 0.92rem; }
.astro-hero .astro-toolbar { margin: 0; }

/* Sticky on desktop so filter + local-time toggle stay in reach
   while the table scrolls past underneath. */
@media (min-width: 48rem) {
  .astro-hero {
    position: sticky;
    top: var(--ld-header-h);
    z-index: 5;
  }
}

.astro-toolbar__tz-group {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.25rem;
  margin-left: auto;       /* keep flush right even when toolbar wraps */
  max-width: 22rem;
  flex: 0 0 auto;
}

.astro-toolbar__tz-note {
  margin: 0;
  font-size: 0.7rem;
  font-style: italic;
  color: var(--ld-fg-dim);
  text-align: right;
  line-height: 1.45;
}

.astro-events__list { padding-block: clamp(2.5rem, 5vw, 4rem); }

.astro-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin: 1.4rem 0;
}

.astro-toolbar__filters {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.chip {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font: inherit;
  font-size: 0.78rem;
  letter-spacing: 0.04em;
  color: var(--ld-fg-dim);
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid var(--ld-rule);
  border-radius: 999px;
  padding: 0.4rem 0.85rem;
  cursor: pointer;
  transition: color 160ms ease, background 160ms ease, border-color 160ms ease;
}

.chip:hover { color: var(--ld-fg); border-color: rgba(214, 166, 74, 0.4); }

.chip.is-active {
  color: #1a1500;
  background: var(--ld-accent);
  border-color: var(--ld-accent);
}

.chip__count {
  font-size: 0.7rem;
  opacity: 0.7;
  font-variant-numeric: tabular-nums;
}
.chip.is-active .chip__count { opacity: 0.85; }

.astro-toolbar__tz {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  cursor: pointer;
  font-size: 0.85rem;
  color: var(--ld-fg-dim);
}
.astro-toolbar__tz input { accent-color: var(--ld-accent); }

.astro-table-wrap {
  overflow-x: auto;
  margin-bottom: 2rem;
  border: 1px solid var(--ld-rule);
  border-radius: 12px;
  background: rgba(8, 13, 32, 0.35);
  -webkit-backdrop-filter: blur(6px);
          backdrop-filter: blur(6px);
}

.astro-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.92rem;
}

.astro-table th,
.astro-table td {
  padding: 1rem 1.1rem;
  vertical-align: top;
  text-align: left;
}

.astro-table thead th {
  background: rgba(255, 255, 255, 0.06);
  font-size: 0.72rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ld-fg-dim);
  font-weight: 500;
  border-bottom: 1px solid var(--ld-rule);
  user-select: none;
}

.astro-table th[data-sort-key]:hover { color: var(--ld-fg); }
.astro-table th[aria-sort="ascending"]::after  { content: ' ▲'; opacity: 0.6; }
.astro-table th[aria-sort="descending"]::after { content: ' ▼'; opacity: 0.6; }

.astro-table tbody tr {
  border-bottom: 1px solid var(--ld-rule);
  transition: background 160ms ease;
}
.astro-table tbody tr:last-child { border-bottom: 0; }
.astro-table tbody tr:hover { background: rgba(255, 255, 255, 0.025); }

.astro-cell--date {
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
  color: var(--ld-fg);
  font-size: 0.88rem;
  min-width: 9rem;
}

.astro-cell--event { min-width: 18rem; max-width: 36rem; }

.astro-event__name {
  font-size: 1rem;
  font-weight: 500;
  margin: 0 0 0.3rem;
  letter-spacing: -0.005em;
  color: var(--ld-fg);
}

.astro-event__desc {
  margin: 0;
  font-size: 0.88rem;
  line-height: 1.55;
  color: var(--ld-fg-dim);
}

.astro-cell--type {
  white-space: nowrap;
  min-width: 9rem;
}

.astro-type-pill {
  display: inline-block;
  font-size: 0.7rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  padding: 0.22rem 0.6rem;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid var(--ld-rule);
  color: var(--ld-fg);
}

/* type accent colours — subtle border tint per category */
.astro-type-pill.astro-type-full_moon            { border-color: rgba(220, 220, 240, 0.45); color: #e9e6df; }
.astro-type-pill.astro-type-solar_eclipse        { border-color: rgba(245, 175,  90, 0.55); color: #f5b47a; }
.astro-type-pill.astro-type-lunar_eclipse        { border-color: rgba(220, 100, 100, 0.55); color: #e08a8a; }
.astro-type-pill.astro-type-meteor_shower        { border-color: rgba(120, 200, 240, 0.55); color: #a8d8f0; }
.astro-type-pill.astro-type-planet_opposition    { border-color: rgba(180, 160, 230, 0.55); color: #c2b3e6; }
.astro-type-pill.astro-type-asteroid_opposition  { border-color: rgba(180, 160, 230, 0.45); color: #c2b3e6; }
.astro-type-pill.astro-type-planetary_alignment  { border-color: rgba(180, 160, 230, 0.45); color: #b8a8d4; }
.astro-type-pill.astro-type-planetary_elongation { border-color: rgba(180, 160, 230, 0.4);  color: #b8a8d4; }
.astro-type-pill.astro-type-planetary_event      { border-color: rgba(180, 160, 230, 0.4);  color: #b8a8d4; }
.astro-type-pill.astro-type-conjunction          { border-color: rgba(160, 220, 180, 0.5);  color: #b0d8c0; }
.astro-type-pill.astro-type-occultation          { border-color: rgba(160, 220, 180, 0.4);  color: #b0d8c0; }
.astro-type-pill.astro-type-equinox              { border-color: rgba(214, 166,  74, 0.55); color: #d6a64a; }
.astro-type-pill.astro-type-solstice             { border-color: rgba(214, 166,  74, 0.55); color: #d6a64a; }
.astro-type-pill.astro-type-orbital_marker       { border-color: rgba(150, 160, 180, 0.5);  color: #aab0c0; }
.astro-type-pill.astro-type-space_mission        { border-color: rgba(255, 120,  80, 0.55); color: #ff8c66; }

.astro-tag {
  display: inline-block;
  margin-left: 0.3rem;
  font-size: 0.7rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ld-fg-dim);
  opacity: 0.75;
}

.astro-cell--sources ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  min-width: 9rem;
}
.astro-cell--sources a {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  color: var(--ld-fg-dim);
  text-decoration: none;
  font-size: 0.82rem;
  border-bottom: 1px solid transparent;
  transition: color 160ms ease, border-color 160ms ease;
}
.astro-cell--sources a:hover {
  color: var(--ld-fg);
  border-bottom-color: var(--ld-accent);
}
.astro-cell--sources i { font-size: 0.72rem; opacity: 0.7; }

/* ---------- table on the light (.section--light) panel ---------- */

.section--light .astro-table-wrap {
  border: 1px solid rgba(0, 0, 0, 0.12);
  background: rgba(255, 255, 255, 0.55);
  -webkit-backdrop-filter: blur(4px);
          backdrop-filter: blur(4px);
}

.section--light .astro-table thead th {
  background: rgba(255, 255, 255, 0.85);
  color: rgba(10, 10, 14, 0.75);
  border-bottom-color: rgba(0, 0, 0, 0.15);
}
.section--light .astro-table th[data-sort-key]:hover { color: #0a0a0e; }

.section--light .astro-table tbody tr {
  border-bottom-color: rgba(0, 0, 0, 0.1);
}
.section--light .astro-table tbody tr:hover { background: rgba(0, 0, 0, 0.03); }

.section--light .astro-cell--date { color: #0a0a0e; }

.section--light .astro-event__name { color: #0a0a0e; }
.section--light .astro-event__desc { color: rgba(10, 10, 14, 0.62); }

.section--light .astro-type-pill {
  color: #0a0a0e;
  background: rgba(255, 255, 255, 0.55);
}

/* deepened type accents for the light backplate */
.section--light .astro-type-pill.astro-type-full_moon            { border-color: rgba(80,  80,  90, 0.45); color: #2a2d3a; }
.section--light .astro-type-pill.astro-type-solar_eclipse        { border-color: rgba(200, 120,  40, 0.65); color: #8a4a10; }
.section--light .astro-type-pill.astro-type-lunar_eclipse        { border-color: rgba(180,  70,  70, 0.65); color: #80281e; }
.section--light .astro-type-pill.astro-type-meteor_shower        { border-color: rgba( 60, 130, 180, 0.65); color: #1f4a78; }
.section--light .astro-type-pill.astro-type-planet_opposition    { border-color: rgba(110,  90, 170, 0.65); color: #3a2a72; }
.section--light .astro-type-pill.astro-type-asteroid_opposition  { border-color: rgba(110,  90, 170, 0.55); color: #3a2a72; }
.section--light .astro-type-pill.astro-type-planetary_alignment  { border-color: rgba(110,  90, 170, 0.5);  color: #3a2a72; }
.section--light .astro-type-pill.astro-type-planetary_elongation { border-color: rgba(110,  90, 170, 0.45); color: #3a2a72; }
.section--light .astro-type-pill.astro-type-planetary_event      { border-color: rgba(110,  90, 170, 0.45); color: #3a2a72; }
.section--light .astro-type-pill.astro-type-conjunction          { border-color: rgba( 60, 130,  80, 0.65); color: #1d4d2a; }
.section--light .astro-type-pill.astro-type-occultation          { border-color: rgba( 60, 130,  80, 0.55); color: #1d4d2a; }
.section--light .astro-type-pill.astro-type-equinox              { border-color: rgba(180, 130,  40, 0.7);  color: #6a4d10; }
.section--light .astro-type-pill.astro-type-solstice             { border-color: rgba(180, 130,  40, 0.7);  color: #6a4d10; }
.section--light .astro-type-pill.astro-type-orbital_marker       { border-color: rgba( 90, 100, 120, 0.55); color: #2c3142; }
.section--light .astro-type-pill.astro-type-space_mission        { border-color: rgba(200,  80,  40, 0.7);  color: #802a10; }

.section--light .astro-tag { color: rgba(10, 10, 14, 0.55); }

.section--light .astro-cell--sources a {
  color: rgba(10, 10, 14, 0.6);
}
.section--light .astro-cell--sources a:hover {
  color: #0a0a0e;
  border-bottom-color: var(--ld-accent);
}

/* mobile: stack as cards */
@media (max-width: 48rem) {
  .astro-table-wrap { border: none; background: transparent; }
  .section--light .astro-table-wrap { background: transparent; -webkit-backdrop-filter: none; backdrop-filter: none; }
  .astro-table, .astro-table tbody, .astro-table thead, .astro-table tr, .astro-table th, .astro-table td {
    display: block;
    width: 100%;
  }
  .astro-table thead { display: none; }
  .astro-table tbody tr {
    border: 1px solid rgba(0, 0, 0, 0.12);
    border-radius: 12px;
    background: rgba(255, 255, 255, 0.6);
    margin-bottom: 0.9rem;
    padding: 1rem;
  }
  .astro-table td { padding: 0.4rem 0; }
  .astro-cell--date { font-size: 0.85rem; }
  .section--light .astro-cell--date { color: rgba(10, 10, 14, 0.7); }
}

/* ---------- generic page layout (imprint, 404, …) ---------- */

.page {
  display: grid;
  place-items: center;
  padding: 4rem var(--ld-pad-x) 5rem;
}

.page__inner {
  width: 100%;
  max-width: 38rem;
}

.page__title {
  font-size: clamp(1.8rem, 4.4vw, 2.6rem);
  font-weight: 400;
  font-style: italic;
  letter-spacing: -0.012em;
  margin: 0 0 1.5rem;
  text-shadow: 0 0 24px rgba(214, 166, 74, 0.08);
}

.page__lead {
  color: var(--ld-fg);
  opacity: 0.92;
  line-height: 1.7;
  margin: 0 0 2.5rem;
}

.page__back a {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  color: var(--ld-fg-dim);
  text-decoration: none;
  letter-spacing: 0.08em;
  font-size: 0.82rem;
  border-bottom: 1px solid transparent;
  transition: color 160ms ease, border-color 160ms ease;
}

.page__back a:hover {
  color: var(--ld-fg);
  border-bottom-color: var(--ld-accent);
}

.page__back i { font-size: 0.72rem; opacity: 0.7; }

/* ---------- footer ---------- */

.site-footer {
  margin-top: auto;          /* pushes footer to the bottom of the flex body */
  border-top: 1px solid var(--ld-rule);
  background: rgba(8, 13, 32, 0.4);
  -webkit-backdrop-filter: blur(10px) saturate(140%);
          backdrop-filter: blur(10px) saturate(140%);
  color: var(--ld-fg-dim);
}

.site-footer a {
  color: var(--ld-fg-dim);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: color 160ms ease, border-color 160ms ease;
  padding-bottom: 1px;
}

.site-footer a:hover {
  color: var(--ld-fg);
  border-bottom-color: var(--ld-accent);
}

/* ---------- footer grid (brand · content · legal · language) ---------- */

.site-footer__top {
  display: grid;
  grid-template-columns: minmax(10rem, 1.4fr) 1fr 1fr 1fr;
  gap: 2.4rem 2rem;
  padding-block: 2.6rem 2rem;
}

.site-footer__brand {
  display: flex;
  flex-direction: column;
  gap: 0.8rem;
  align-items: flex-start;
}

.site-footer__logo {
  display: inline-flex;
  border-bottom: 0;
}
.site-footer__logo img {
  display: block;
  width: 44px;
  height: auto;
}

.site-footer__name {
  font-size: 1rem;
  letter-spacing: 0.02em;
  color: var(--ld-fg);
}

.site-footer__heading {
  margin: 0 0 0.85rem;
  font-size: 0.7rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--ld-fg);
  opacity: 0.55;
}

.site-footer__col ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
}
.site-footer__col li { line-height: 1.4; }
.site-footer__col a {
  font-size: 0.88rem;
  letter-spacing: 0.01em;
}

/* ---------- footer language list (replaces dropdown) ---------- */

.lang-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
}

.lang-list__opt {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  font-size: 0.88rem;
  color: var(--ld-fg-dim);
  border-bottom: 1px solid transparent;
  padding-bottom: 1px;
  transition: color 160ms ease, border-color 160ms ease;
}
.lang-list__opt:hover { color: var(--ld-fg); border-bottom-color: var(--ld-accent); }
.lang-list__opt.is-active {
  color: var(--ld-fg);
  border-bottom-color: var(--ld-accent);
}

/* ---------- footer social band ---------- */

.site-footer__connect {
  display: flex;
  justify-content: center;
  padding: 1.25rem var(--ld-pad-x);
  border-top: 1px solid var(--ld-rule);
}

/* ---------- footer bottom rail (copyright) ---------- */

.site-footer__bottom {
  border-top: 1px solid var(--ld-rule);
  padding-block: 1rem;
  font-size: 0.78rem;
  text-align: center;
}

.site-footer__copy { margin: 0; }

/* ---------- footer responsive ---------- */

@media (max-width: 56rem) {
  .site-footer__top {
    grid-template-columns: 1fr 1fr;
    gap: 2rem 2rem;
  }
  .site-footer__brand { grid-column: 1 / -1; }
}

@media (max-width: 32rem) {
  .site-footer__top { grid-template-columns: 1fr; }
}

/* ---------- cookie banner ---------- */

.cookie-banner {
  position: fixed;
  bottom: clamp(0.75rem, 2vw, 1.5rem);
  left: 50%;
  z-index: 100;

  display: flex;
  align-items: center;
  gap: 0.95rem;
  max-width: min(38rem, calc(100vw - 1.5rem));
  padding: 0.85rem 1rem 0.85rem 1.15rem;

  background: rgba(10, 12, 22, 0.82);
  -webkit-backdrop-filter: blur(18px) saturate(140%);
          backdrop-filter: blur(18px) saturate(140%);
  border: 1px solid var(--ld-rule);
  border-radius: 999px;
  box-shadow:
    0 22px 50px -18px rgba(0, 0, 0, 0.7),
    0 0 0 1px rgba(255, 255, 255, 0.02) inset;

  font-size: 0.86rem;
  line-height: 1.45;
  color: var(--ld-fg);

  /* slide up + fade in, after a small settle delay */
  animation: cookie-banner-in 420ms cubic-bezier(0.2, 0.7, 0.2, 1) 600ms both;
  transform: translate(-50%, 24px);
  opacity: 0;
  will-change: transform, opacity;
}

.cookie-banner--out {
  animation: cookie-banner-out 240ms cubic-bezier(0.4, 0, 0.6, 1) both;
}

.cookie-banner__icon {
  flex: none;
  font-size: 1.05rem;
  color: var(--ld-accent);
  filter: drop-shadow(0 0 6px rgba(214, 166, 74, 0.35));
}

.cookie-banner__text {
  margin: 0;
  flex: 1;
  min-width: 0;
  color: var(--ld-fg);
  opacity: 0.92;
}

.cookie-banner__btn {
  flex: none;
  cursor: pointer;
  padding: 0.5rem 1.05rem;
  font: inherit;
  font-size: 0.78rem;
  letter-spacing: 0.08em;
  color: var(--ld-fg);
  background: rgba(214, 166, 74, 0.12);
  border: 1px solid rgba(214, 166, 74, 0.45);
  border-radius: 999px;
  transition: background 180ms ease, border-color 180ms ease, transform 180ms ease;
}

.cookie-banner__btn:hover {
  background: rgba(214, 166, 74, 0.22);
  border-color: var(--ld-accent);
}

.cookie-banner__btn:active {
  transform: scale(0.97);
}

.cookie-banner__btn:focus-visible {
  outline: 2px solid var(--ld-accent);
  outline-offset: 2px;
}

@keyframes cookie-banner-in {
  from { opacity: 0; transform: translate(-50%, 24px); }
  to   { opacity: 1; transform: translate(-50%, 0); }
}

@keyframes cookie-banner-out {
  from { opacity: 1; transform: translate(-50%, 0); }
  to   { opacity: 0; transform: translate(-50%, 16px); }
}

/* On narrow screens, stack vertically and lose the pill shape. */
@media (max-width: 30rem) {
  .cookie-banner {
    flex-wrap: wrap;
    border-radius: 18px;
    padding: 1rem 1.1rem;
    text-align: left;
  }
  .cookie-banner__btn { margin-left: auto; }
}

@media (prefers-reduced-motion: reduce) {
  .cookie-banner {
    animation: none;
    transform: translateX(-50%);
    opacity: 1;
  }
  .cookie-banner--out {
    animation: none;
    opacity: 0;
  }
}
