/* Invitera — native-app feel, safe areas, motion. Tailwind CDN handles utilities;
   this file owns things Tailwind can't: safe-area insets, keyframes, view
   transitions, reveal states, and reduced-motion. */

:root {
  --safe-top: env(safe-area-inset-top, 0px);
  --safe-bottom: env(safe-area-inset-bottom, 0px);
  --bottom-nav-h: 4.25rem;
  --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
}

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

body {
  font-family: 'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  color: #2A2440;
  background: #FFF8F0;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  /* Prevent overscroll bounce revealing white; feel native. */
  overscroll-behavior-y: none;
  min-height: 100dvh;
}

h1, h2, h3, .font-display { font-family: 'Fredoka', ui-rounded, system-ui, sans-serif; }

/* Never let the page scroll horizontally. */
html, body { max-width: 100%; overflow-x: clip; }

/* Safe-area helpers */
.pt-safe { padding-top: calc(0.75rem + var(--safe-top)); }
.pb-safe { padding-bottom: calc(0.75rem + var(--safe-bottom)); }
.has-bottom-nav { padding-bottom: calc(var(--bottom-nav-h) + var(--safe-bottom)); }

/* ---- Inside the native app shell (body.is-native-app — see middleware/nativeApp.js) ----
   The app draws its own top bar and tab bar, so we omit ours. But its WebView is EDGE-TO-EDGE:
   without this, the first line of every page sits under the clock and battery, and the last
   sits under the floating tab bar.

   ⚠️ `--app-inset-bottom` is written by the shell (`pushLayoutMetrics` in
   InviteraViewController.swift) because CSS cannot know how tall the native tab bar is — on
   iOS 26 it's a floating pill whose *occluded region* is taller than the bar itself. The
   literal below is only the pre-measurement fallback, so a page never renders obviously wrong
   in the instant before the shell reports in.

   ⚠️ We re-point `--bottom-nav-h` rather than hard-coding new offsets, so every rule that
   already reserved room for the web bottom nav — `.has-bottom-nav`, `.save-bar`, anything
   added later — clears the NATIVE bar instead, with no further changes. Subtracting
   `--safe-bottom` keeps those existing `calc(var(--bottom-nav-h) + var(--safe-bottom))`
   expressions landing on exactly `--app-inset-bottom`. */
body.is-native-app {
  --bottom-nav-h: calc(var(--app-inset-bottom, 88px) - var(--safe-bottom));
  padding-top: var(--safe-top);
}

/* ---- Tap feedback: subtle scale on active for a native button feel ---- */
.tap { transition: transform 0.12s var(--ease-spring), box-shadow 0.2s ease; }
.tap:active { transform: scale(0.96); }

/* ---- Playful animated background blobs ---- */
.blob {
  position: absolute;
  border-radius: 42% 58% 63% 37% / 41% 44% 56% 59%;
  filter: blur(8px);
  opacity: 0.5;
  animation: blob-float 14s ease-in-out infinite;
  will-change: transform;
  pointer-events: none;
}
@keyframes blob-float {
  0%, 100% { transform: translate3d(0, 0, 0) rotate(0deg) scale(1); }
  33% { transform: translate3d(20px, -24px, 0) rotate(12deg) scale(1.06); }
  66% { transform: translate3d(-16px, 14px, 0) rotate(-8deg) scale(0.97); }
}

/* ---- Scroll-reveal ---- */
[data-reveal] {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity 0.7s ease, transform 0.7s var(--ease-spring);
  transition-delay: var(--reveal-delay, 0ms);
}
[data-reveal].is-visible { opacity: 1; transform: none; }

/* ---- Entrance keyframes ---- */
@keyframes fade-up { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: none; } }
@keyframes pop-in { 0% { opacity: 0; transform: scale(0.9); } 60% { transform: scale(1.03); } 100% { opacity: 1; transform: scale(1); } }
@keyframes float-y { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-8px); } }
.animate-fade-up { animation: fade-up 0.6s var(--ease-spring) both; }
.animate-pop-in { animation: pop-in 0.45s var(--ease-spring) both; }
.animate-float { animation: float-y 4s ease-in-out infinite; }

/* ---- Toasts ---- */
.toast-stack {
  position: fixed; left: 50%; transform: translateX(-50%);
  top: calc(0.75rem + var(--safe-top)); z-index: 80;
  display: flex; flex-direction: column; gap: 0.5rem; width: min(92vw, 26rem);
}
.toast {
  padding: 0.8rem 1rem; border-radius: 1rem; color: #2A2440;
  background: #fff; box-shadow: 0 12px 30px -12px rgba(42,36,64,0.4);
  border: 1px solid rgba(42,36,64,0.06);
  animation: pop-in 0.4s var(--ease-spring) both;
  display: flex; gap: 0.6rem; align-items: flex-start;
}
.toast--success { border-left: 4px solid #2DD4BF; }
.toast--error { border-left: 4px solid #F14D4D; }
.toast--info { border-left: 4px solid #7C5CFC; }
.toast.hide { opacity: 0; transform: translateY(-8px); transition: all 0.35s ease; }

/* ---- Bottom nav (mobile app feel) ---- */
.bottom-nav {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 60;
  padding-bottom: var(--safe-bottom);
  background: rgba(255,255,255,0.86);
  backdrop-filter: saturate(180%) blur(14px);
  -webkit-backdrop-filter: saturate(180%) blur(14px);
  border-top: 1px solid rgba(42,36,64,0.07);
}

/* ---- Sticky "save" bar (profile editor) — slides up when the form is dirty ---- */
.save-bar {
  position: fixed; left: 0; right: 0; z-index: 50;
  bottom: calc(var(--bottom-nav-h) + var(--safe-bottom));
  padding: 0 1rem 0.75rem;
  transform: translateY(170%); opacity: 0;
  transition: transform 0.3s ease, opacity 0.3s ease;
  pointer-events: none;
}
@media (min-width: 640px) { .save-bar { bottom: 0; padding-bottom: 1rem; } }
.save-bar.is-visible { transform: translateY(0); opacity: 1; }
.save-bar .save-bar-inner { pointer-events: auto; }

/* ---- Background presets (event/group hero gradients) ---- */
.bg-preset-default { background: linear-gradient(135deg, #FF8585 0%, #7C5CFC 55%, #2DD4BF 100%); }
.bg-preset-sunset  { background: linear-gradient(135deg, #FF6B6B 0%, #FFC53D 100%); }
.bg-preset-grape   { background: linear-gradient(135deg, #7C5CFC 0%, #B9A3FF 100%); }
.bg-preset-mint    { background: linear-gradient(135deg, #17A99A 0%, #7FE1D2 100%); }
.bg-preset-peach   { background: linear-gradient(135deg, #FF9E9E 0%, #FFD166 100%); }
.bg-preset-night   { background: linear-gradient(135deg, #2A2440 0%, #5433BE 100%); }
.bg-preset-confetti{ background: linear-gradient(135deg, #FF6B6B 0%, #FFD166 38%, #2DD4BF 68%, #7C5CFC 100%); }
/* Extra "looks" for public profiles (§18a) */
.bg-preset-ocean   { background: linear-gradient(160deg, #0EA5E9 0%, #2DD4BF 100%); }
.bg-preset-fire    { background: linear-gradient(160deg, #F14D4D 0%, #FF8A3D 55%, #FFC53D 100%); }
.bg-preset-candy   { background: linear-gradient(160deg, #EC4899 0%, #8B5CF6 100%); }
.bg-preset-berry   { background: linear-gradient(160deg, #7C2D6B 0%, #C93B7B 55%, #FF8585 100%); }
.bg-preset-forest  { background: linear-gradient(160deg, #14532D 0%, #17A99A 100%); }
.bg-preset-midnight{ background: linear-gradient(160deg, #0F172A 0%, #1E293B 60%, #334155 100%); }
.bg-preset-noir    { background: linear-gradient(160deg, #0B0B0F 0%, #232334 100%); }
.bg-preset-slate   { background: linear-gradient(160deg, #334155 0%, #64748B 100%); }
.bg-preset-mono    { background: radial-gradient(120% 120% at 50% 0%, #3a3a3a 0%, #0b0b0b 100%); }
.bg-preset-snow    { background: linear-gradient(160deg, #ffffff 0%, #eceaf6 100%); }
.bg-preset-paper   { background: linear-gradient(160deg, #FFF8F0 0%, #F3EDE2 100%); }

/* ---- Minimal prose (rich_text block) — Tailwind CDN has no typography plugin ---- */
.prose-invitera p { margin: 0 0 0.75rem; }
.prose-invitera p:last-child { margin-bottom: 0; }
.prose-invitera h3 { font-family: 'Fredoka', ui-rounded, sans-serif; font-weight: 600; font-size: 1.15rem; color: #2A2440; margin: 1rem 0 0.5rem; }
.prose-invitera h4 { font-weight: 600; color: #2A2440; margin: 0.75rem 0 0.4rem; }
.prose-invitera a { color: #6742E6; text-decoration: underline; }
.prose-invitera ul { list-style: disc; padding-left: 1.25rem; margin: 0 0 0.75rem; }
.prose-invitera ol { list-style: decimal; padding-left: 1.25rem; margin: 0 0 0.75rem; }
.prose-invitera li { margin: 0.15rem 0; }
.prose-invitera blockquote { border-left: 3px solid #D6C9FF; padding-left: 0.85rem; color: #5B5470; margin: 0 0 0.75rem; }
.prose-invitera code { background: #F3F0FF; padding: 0.1rem 0.35rem; border-radius: 0.4rem; font-size: 0.9em; }
.prose-invitera hr { border: 0; border-top: 1px solid rgba(42,36,64,0.1); margin: 1rem 0; }
.tabular-nums { font-variant-numeric: tabular-nums; }

/* ---- Share dialog ---- */
dialog.share-dialog { border: none; margin: auto; padding: 0; color: inherit; }
dialog.share-dialog::backdrop { background: rgba(20, 15, 40, 0.45); }
dialog.share-dialog[open] { animation: pop-in 0.28s var(--ease-spring) both; }

/* ---- Collapsible guest list (native <details>, CSP-safe) ---- */
details[data-guestlist] > summary { list-style: none; }
details[data-guestlist] > summary::-webkit-details-marker { display: none; }
details[data-guestlist] .gl-open-label { display: none; }
details[data-guestlist][open] .gl-open-label { display: inline; }
details[data-guestlist][open] .gl-closed-label { display: none; }
details[data-guestlist][open] .gl-preview { display: none; }

/* ---- Collapsible content-block editor (native <details>, CSP-safe) ---- */
.block-summary { list-style: none; }
.block-summary::-webkit-details-marker { display: none; }
.block-chevron { transition: transform 0.18s ease; }
.block-item[open] .block-chevron { transform: rotate(180deg); }

/* ---- Schedule / timeline block (state set live by blocks.js) ---- */
.sched-dot { transition: background-color 0.2s ease; }
[data-sched-item][data-state="past"] { opacity: 0.5; }
[data-sched-item][data-state="now"] .sched-dot {
  background-color: #FF6B6B;
  box-shadow: 0 0 0 4px rgba(255, 107, 107, 0.28);
  animation: schedPulse 1.8s ease-in-out infinite;
}
@keyframes schedPulse {
  0%, 100% { box-shadow: 0 0 0 4px rgba(255, 107, 107, 0.28); }
  50% { box-shadow: 0 0 0 8px rgba(255, 107, 107, 0.10); }
}
@media (prefers-reduced-motion: reduce) {
  [data-sched-item][data-state="now"] .sched-dot { animation: none; }
}

/* ---- View Transitions ---- */
@view-transition { navigation: auto; }
::view-transition-old(root),
::view-transition-new(root) { animation-duration: 0.35s; }

/* ---- Reduced motion: honor the user ---- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
  [data-reveal] { opacity: 1 !important; transform: none !important; }
  .blob { animation: none !important; }
}

/* ---- Paste: rendered Markdown (Tailwind Play CDN has no typography plugin) ---- */
.paste-md { line-height: 1.65; word-wrap: break-word; }
.paste-md > :first-child { margin-top: 0; }
.paste-md > :last-child { margin-bottom: 0; }
.paste-md h1, .paste-md h2, .paste-md h3, .paste-md h4, .paste-md h5, .paste-md h6 {
  font-family: 'Fredoka', ui-rounded, system-ui, sans-serif;
  font-weight: 700; line-height: 1.25; margin: 1.4em 0 0.5em;
}
.paste-md h1 { font-size: 1.6rem; }
.paste-md h2 { font-size: 1.35rem; }
.paste-md h3 { font-size: 1.15rem; }
.paste-md h4, .paste-md h5, .paste-md h6 { font-size: 1rem; }
.paste-md p { margin: 0.75em 0; }
.paste-md a { color: #ff6b6b; text-decoration: underline; text-underline-offset: 2px; }
.paste-md a:hover { color: #e8492c; }
.paste-md ul, .paste-md ol { margin: 0.75em 0; padding-left: 1.5em; }
.paste-md ul { list-style: disc; }
.paste-md ol { list-style: decimal; }
.paste-md li { margin: 0.25em 0; }
.paste-md blockquote {
  margin: 1em 0; padding: 0.4em 1em; border-left: 3px solid rgba(124, 92, 252, 0.4);
  background: rgba(124, 92, 252, 0.06); border-radius: 0 0.5rem 0.5rem 0; color: #4b4666;
}
.paste-md code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.9em;
  background: rgba(42, 36, 64, 0.06); padding: 0.15em 0.4em; border-radius: 0.375rem;
}
.paste-md pre {
  margin: 1em 0; padding: 0.9em 1em; overflow-x: auto; border-radius: 0.75rem;
  background: #2a2440; color: #f3f1ff; font-size: 0.85rem; line-height: 1.5;
}
.paste-md pre code { background: none; padding: 0; font-size: inherit; color: inherit; }
.paste-md hr { margin: 1.5em 0; border: 0; border-top: 1px solid rgba(42, 36, 64, 0.12); }
.paste-md img { max-width: 100%; height: auto; border-radius: 0.5rem; }
.paste-md table { width: 100%; border-collapse: collapse; margin: 1em 0; font-size: 0.92em; }
.paste-md th, .paste-md td { border: 1px solid rgba(42, 36, 64, 0.12); padding: 0.45em 0.7em; text-align: left; }
.paste-md th { background: rgba(42, 36, 64, 0.04); font-weight: 600; }

/* ---- Landing v2 ---- */
/* Dot pattern lives on a ::before so its fade MASK only touches the decorative dots — a mask on
   the section itself would clip the hero's own content (the CTA buttons + card were being cut). */
.hero-dots { position: relative; isolation: isolate; }
.hero-dots::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image: radial-gradient(rgba(124, 92, 252, 0.10) 1px, transparent 1px);
  background-size: 22px 22px;
  -webkit-mask-image: radial-gradient(ellipse 90% 70% at 50% 30%, #000 45%, transparent 82%);
  mask-image: radial-gradient(ellipse 90% 70% at 50% 30%, #000 45%, transparent 82%);
}
.hero-dots > * { position: relative; z-index: 1; }
.marquee { overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
}
.marquee__track { display: inline-flex; align-items: center; gap: 1rem; white-space: nowrap;
  padding-left: 1rem; animation: marquee 42s linear infinite; will-change: transform; }
.marquee:hover .marquee__track { animation-play-state: paused; }
@keyframes marquee { from { transform: translateX(0); } to { transform: translateX(-50%); } }
.lift { transition: transform 0.25s var(--ease-spring), box-shadow 0.25s ease; }
.lift:hover { transform: translateY(-4px); }
.live-dot { display: inline-block; position: relative; }
.live-dot::before { content: ''; position: absolute; inset: 0; border-radius: 9999px;
  background: currentColor; opacity: 0.55; animation: live-ping 1.7s ease-out infinite; }
@keyframes live-ping { 0% { transform: scale(1); opacity: 0.55; } 100% { transform: scale(2.6); opacity: 0; } }
@media (prefers-reduced-motion: reduce) {
  .marquee__track { animation: none; }
  .live-dot::before { animation: none; }
}

/* ---- Keyboard focus: one consistent, on-brand ring everywhere (nothing removed the UA default before) ---- */
:focus-visible { outline: 2px solid #7C5CFC; outline-offset: 2px; }
