/* === FRIDA WED/index.html — extracted inline <style> block ===
   Originally lines 18-1693 of WED/index.html. The page also
   loads /css/wed-bday.css; this file holds the page-specific
   overrides + the inline animations the wedding page uses. */

  /* ------------------------------------------------------------------
     Hero greeting + formal invitation copy.
     Replaces the old "Welcome, X" pill, "Together with their families"
     eyebrow, and "are getting married" sub-line with a personalised
     "Dear <guest>, / With love, joy, and a promise of forever, / we invite
     you to celebrate / the wedding of / Eddy & Antonella" composition.
     Layered with strong text-shadows so it stays legible over any hero
     background image without an extra dark scrim.
     ------------------------------------------------------------------ */
  .hero-greeting{
    font-family:var(--display, 'Playfair Display'), Georgia, serif;
    font-style:italic;
    font-size:clamp(20px, 2.4vw, 28px);
    font-weight:400;
    color:#fff;
    letter-spacing:.005em;
    margin:0 0 22px;
    line-height:1.3;
    text-shadow:
      0 1px 3px rgba(0,0,0,.55),
      0 2px 14px rgba(0,0,0,.35);
  }
  .hero-greeting #heroGuestName{
    font-style:normal;
    font-weight:600;
    color:var(--gold-2, #fcc440);
    letter-spacing:.01em;
  }
  .hero-invite-text{
    font-family:var(--display, 'Playfair Display'), Georgia, serif;
    font-style:italic;
    font-size:clamp(17px, 2vw, 22px);
    font-weight:400;
    color:#fff;
    letter-spacing:.005em;
    line-height:1.55;
    max-width:640px;
    margin:0 auto 26px;
    text-shadow:
      0 1px 3px rgba(0,0,0,.55),
      0 2px 14px rgba(0,0,0,.35);
  }
  /* Tighten the gap between "the wedding of" and the script names. */
  .hero-invite-text + .hero-script,
  .hero-text-box + .hero-script{ margin-top:14px }

  /* Allow line breaks in hero invite text (saved value uses \n in
     state.hero.inviteText so the host can break lines naturally). */
  .hero-invite-text{ white-space:pre-line }

  /* ------------------------------------------------------------------
     Edit-mode placeholders: when an editable field is empty, show its
     data-placeholder attribute as faint italic guidance text so the
     host knows where to click. The .is-empty class is added by render()
     whenever the bound state value is empty/null/undefined.
     ------------------------------------------------------------------ */
  body.edit [data-edit][contenteditable="true"]{
    outline:1px dashed transparent;
    outline-offset:6px;
    transition:outline-color .2s, background-color .2s;
    border-radius:4px;
  }
  body.edit [data-edit][contenteditable="true"]:hover,
  body.edit [data-edit][contenteditable="true"]:focus{
    outline-color:rgba(252,196,64,.55);
    background-color:rgba(252,196,64,.05);
  }
  body.edit [data-edit].is-empty[data-placeholder]::before{
    content:attr(data-placeholder);
    display:inline-block;
    color:rgba(252,196,64,.55);
    font-style:italic;
    font-weight:400;
    letter-spacing:.01em;
    pointer-events:none;
  }
  body.theme-light.edit [data-edit].is-empty[data-placeholder]::before{
    color:rgba(140,108,68,.65);
  }

  /* ------------------------------------------------------------------
     Translucent backing for the greeting + body invitation text only.
     Sized to its content (display:inline-block + max-width), no border,
     subtle backdrop-blur so the text reads cleanly even over bright
     sunset / floral hero photos. The names below stay OUTSIDE this
     box and keep their unboxed look (their text-shadows are enough).
     ------------------------------------------------------------------ */
  .hero-text-box{
    display:inline-block;
    /* Wine/burgundy tint instead of plain black so the box reads warm
       against the floral hero photo, not as a heavy dark slab. Lower
       alpha (.30 → .25 on light hero, .35 default) keeps it lighter. */
    background:rgba(120, 24, 18, .35);
    -webkit-backdrop-filter:blur(2px);
            backdrop-filter:blur(2px);
    padding:18px 30px 22px;
    border-radius:6px;
    margin:0 auto;
    max-width:min(680px, 92vw);
  }
  /* Tighten internal margins now that the box provides external spacing */
  .hero-text-box .hero-greeting{ margin:0 0 16px }
  .hero-text-box .hero-invite-text{ margin:0; max-width:none }
  @media (max-width:600px){
    .hero-text-box{ padding:14px 18px 16px; max-width:94vw }
    .hero-text-box .hero-greeting{ margin-bottom:12px }
  }

  /* ------------------------------------------------------------------
     Unify all hero text to a single white color (overrides the gold
     accents on the guest name and the ampersand from wed-bday.css).
     ------------------------------------------------------------------ */
  .hero .hero-greeting,
  .hero .hero-greeting *,
  .hero .hero-greeting #heroGuestName,
  .hero .hero-invite-text,
  .hero .hero-invite-text *,
  .hero .hero-script,
  .hero .hero-script > span,
  .hero .hero-script .hero-and,
  .hero .hero-and{
    color:#fff !important;
    background:none !important;
    -webkit-background-clip:initial !important;
            background-clip:initial !important;
    -webkit-text-fill-color:#fff !important;
  }

  /* ------------------------------------------------------------------
     Both RSVP buttons share the same transparent / gold-outline look.
     Overrides the filled gold-gradient styling from wed-bday.css that
     made the "yes" button visually heavier than "no".
     ------------------------------------------------------------------ */
  .hero .hero-rsvp-btn.yes,
  .hero .hero-rsvp-btn.no{
    background:transparent !important;
    background-image:none !important;
    color:#fff !important;
    border:1px solid rgba(252,196,64,.65) !important;
    box-shadow:0 6px 18px rgba(0,0,0,.30) !important;
    text-shadow:0 1px 2px rgba(0,0,0,.6) !important;
    backdrop-filter:blur(4px);
  }
  .hero .hero-rsvp-btn.yes:hover,
  .hero .hero-rsvp-btn.no:hover{
    background:rgba(252,196,64,.08) !important;
    border-color:#fcc440 !important;
    color:#fcc440 !important;
  }

  /* ------------------------------------------------------------------
     Remove the decorative ornament/box that used to sit between the
     script names and the RSVP buttons (hero-rule), the "Scroll"
     status indicator at the hero bottom, and the classic-day-block
     callout (only visible in classic layout — also a "box" that
     could appear under the names).
     ------------------------------------------------------------------ */
  .hero .hero-rule,
  .hero .hero-scroll,
  .hero-scroll,
  .classic-day-block{ display:none !important }

  /* ------------------------------------------------------------------
     Wedding Gifts — sealed envelope card. Closed by default with a wax
     seal and "Tap to open" hint; the account number is hidden until
     the guest taps. Once open, three actions: copy, WhatsApp, and
     download a designed gift card image (PNG generated client-side
     via canvas — no external libs).
     ------------------------------------------------------------------ */
  .gifts-section{ padding:90px 24px; text-align:center }
  .gifts-section .section-head{ margin-bottom:0 }
  .gifts-section .lead{ max-width:560px; margin:14px auto 0 }

  /* The closed envelope. 3D perspective so the flap can fold open. */
  .gift-envelope{
    position:relative;
    width:min(420px, 92vw);
    aspect-ratio: 7 / 5;
    margin:36px auto 0;
    border-radius:10px;
    cursor:pointer;
    perspective:1200px;
    transform-style:preserve-3d;
    transition:transform .35s ease, box-shadow .35s ease;
    background:
      radial-gradient(ellipse at 30% 25%, rgba(255,255,255,.10) 0%, transparent 55%),
      radial-gradient(ellipse at 75% 80%, rgba(0,0,0,.18) 0%, transparent 60%),
      linear-gradient(155deg, #f8eed4 0%, #ebd6a4 50%, #c9a55e 100%);
    box-shadow:
      0 1px 0 rgba(255,255,255,.40) inset,
      0 26px 50px -10px rgba(60,40,10,.45),
      0 12px 24px -8px rgba(60,40,10,.30);
  }
  .gift-envelope:hover{
    transform:translateY(-3px);
    box-shadow:
      0 1px 0 rgba(255,255,255,.40) inset,
      0 30px 60px -10px rgba(60,40,10,.55),
      0 14px 28px -8px rgba(60,40,10,.36);
  }
  /* The triangular V-flap that folds open on click */
  .gift-flap{
    position:absolute; inset:0;
    border-radius:10px 10px 0 0;
    background:
      linear-gradient(180deg, rgba(255,255,255,.20) 0%, rgba(0,0,0,.08) 100%),
      linear-gradient(155deg, #f0e0b4 0%, #d8b878 100%);
    clip-path:polygon(0 0, 100% 0, 50% 65%);
    transform-origin: top center;
    transition:transform .8s cubic-bezier(.4,.05,.2,.95);
    box-shadow:0 1px 0 rgba(255,255,255,.30) inset, 0 4px 8px rgba(60,40,10,.18);
    z-index:3;
  }
  .gift-envelope.open .gift-flap{ transform:rotateX(-180deg); }
  /* Wax seal at the V's tip */
  .gift-seal{
    position:absolute;
    top:55%; left:50%;
    width:74px; height:74px;
    transform:translate(-50%, -50%) rotate(-6deg);
    border-radius:50%;
    display:flex; align-items:center; justify-content:center;
    background:
      radial-gradient(circle at 32% 28%, rgba(255,235,200,.55), transparent 42%),
      radial-gradient(circle at 70% 75%, rgba(60,10,5,.40), transparent 55%),
      radial-gradient(circle at center, #b22222 0%, #841515 65%, #4f0707 100%);
    box-shadow:
      0 6px 14px rgba(60,5,5,.40),
      inset 0 2px 4px rgba(255,255,255,.30),
      inset 0 -3px 6px rgba(40,5,5,.35);
    color:#f5e3c2;
    font-family:'Pinyon Script', cursive;
    font-size:30px;
    letter-spacing:.02em;
    text-shadow:0 1px 1px rgba(0,0,0,.35);
    z-index:4;
    transition:transform .3s, opacity .35s;
  }
  .gift-envelope.open .gift-seal{ opacity:0; transform:translate(-50%, -50%) rotate(-6deg) scale(.7) }
  /* "Tap to open" prompt that pulses gently below the seal */
  .gift-tap{
    position:absolute;
    bottom:22px; left:50%;
    transform:translateX(-50%);
    font-family:var(--mono, 'Unbounded'), monospace;
    font-size:10px; font-weight:500;
    letter-spacing:.4em; text-transform:uppercase;
    color:#5a3a14;
    opacity:.85;
    z-index:4;
    animation:gift-tap-pulse 2.4s ease-in-out infinite;
  }
  /* Pseudo-content so the same node reads "Tap to open" when sealed and
     "Tap to close" when the flap is folded back. Pointer-events stay on
     so it acts as a hint, but the click is on the whole envelope. */
  .gift-tap::before{ content:"Tap to open"; pointer-events:none }
  .gift-envelope.open .gift-tap{ color:#a05818; bottom:18px }
  .gift-envelope.open .gift-tap::before{ content:"Tap to close" }
  @keyframes gift-tap-pulse{
    0%,100%{ opacity:.55; transform:translate(-50%, 0) }
    50%   { opacity:1;   transform:translate(-50%, -3px) }
  }
  /* Inner contents — revealed when the envelope opens */
  .gift-inside{
    position:absolute; inset:14px;
    border-radius:6px;
    background:#fffaf0;
    padding:22px 18px 18px;
    display:flex; flex-direction:column; align-items:center; justify-content:center;
    text-align:center;
    opacity:0;
    transform:scale(.95);
    transition:opacity .4s ease .4s, transform .4s ease .4s;
    z-index:2;
    overflow:hidden;
  }
  .gift-envelope.open .gift-inside{ opacity:1; transform:scale(1) }
  .gift-inside-eyebrow{
    font-family:var(--mono, 'Unbounded'), monospace;
    font-size:9px; font-weight:500;
    letter-spacing:.4em; text-transform:uppercase;
    color:#a05818;
    margin-bottom:10px;
  }
  .gift-inside-num{
    font-family:'SF Mono', Menlo, monospace;
    font-size:clamp(20px, 4vw, 26px);
    font-weight:600;
    letter-spacing:.08em;
    color:#3a1818;
    user-select:all;
    margin-bottom:6px;
  }
  .gift-inside-meta{
    font-family:var(--serif, 'Crimson Pro'), Georgia, serif;
    font-style:italic;
    font-size:14px;
    color:#5a3a18;
    margin-bottom:14px;
  }
  .gift-inside-actions{
    display:flex; gap:8px; justify-content:center; flex-wrap:wrap;
  }
  /* Optional Whish logo — when set it replaces the "Whish" label */
  .gift-whish-logo{
    width:90px; height:36px;
    margin:0 auto 8px;
    background:transparent center/contain no-repeat;
    display:none;
  }
  .gift-whish-logo.has-logo{ display:block }
  body.edit .gift-whish-logo{
    cursor:pointer;
    outline:1px dashed transparent; outline-offset:4px;
    transition:outline-color .2s;
  }
  body.edit .gift-whish-logo:hover{ outline-color:#c4a050 }
  body.edit .gift-whish-logo:not(.has-logo){
    display:flex; align-items:center; justify-content:center;
    border:1px dashed rgba(196,160,80,.55);
    color:#a05818;
    font-family:var(--mono, 'Unbounded'), monospace;
    font-size:9px; letter-spacing:.32em; text-transform:uppercase;
    border-radius:4px;
  }
  body.edit .gift-whish-logo:not(.has-logo)::before{
    content:"+ Logo";
  }
  /* Remove the cream "strip" feel from the invitee banner stat — the
     wide-letterspaced uppercase line was reading like a horizontal band.
     Just italic text now, sitting quietly under the name. */
  .invitee-banner .stat{
    margin-top:6px !important;
    font-family:var(--display, 'Playfair Display'), Georgia, serif !important;
    font-style:italic !important;
    font-size:clamp(13px, 1.4vw, 16px) !important;
    font-weight:400 !important;
    letter-spacing:.005em !important;
    text-transform:none !important;
    color:rgba(245,234,212,.78) !important;
    background:transparent !important;
    padding:0 !important;
  }
  body.theme-light .invitee-banner .stat{ color:var(--ink-soft, #5a4836) !important }
  .gift-inside-btn{
    padding:8px 14px;
    background:transparent;
    border:1px solid #c4a050;
    color:#5a3a14;
    border-radius:999px;
    font-family:var(--mono, 'Unbounded'), monospace;
    font-size:9px; font-weight:500;
    letter-spacing:.32em; text-transform:uppercase;
    cursor:pointer;
    transition:background .2s, color .2s;
    text-decoration:none;
    display:inline-block;
  }
  .gift-inside-btn:hover{ background:#c4a050; color:#fff5e0 }
  .gift-inside-btn.primary{ background:#5a2a14; color:#fff5e0; border-color:#5a2a14 }
  .gift-inside-btn.primary:hover{ background:#3a1808 }
  /* Tiny "× close" so a guest can re-seal the envelope after copying */
  .gift-close{
    position:absolute; top:8px; right:10px;
    width:22px; height:22px;
    background:transparent; border:none;
    color:#a05818; font-size:18px; line-height:1;
    cursor:pointer;
    display:none;
  }
  .gift-envelope.open .gift-close{ display:block }
  @media (max-width:600px){
    .gifts-section{ padding:60px 18px }
    .gift-envelope{ aspect-ratio: 4 / 3 }
    .gift-seal{ width:62px; height:62px; font-size:24px }
  }

  /* Hide the legacy open-display card (kept in DOM for backwards
     compatibility but visually replaced by the envelope). */
  .gifts-section .gifts-card{ display:none }

  /* ------------------------------------------------------------------
     Show the FULL page to every invitee, regardless of their RSVP
     status. The shared wed-bday.css restricts pending guests to just
     the hero/countdown and shows declined guests only the thank-you
     screen — these overrides revert that so every section, the footer,
     and the floating chat/share buttons are always reachable.

     IMPORTANT: `.edit-only` elements (the entire `<section
     class="invitees-section edit-only">` guest-list dashboard, the
     "+ Add Photos" buttons, the schedule edit row, etc.) MUST stay
     hidden for non-host guests. The :not(.edit-only) filter and the
     explicit override at the bottom guarantee they never leak — even
     if the guest's RSVP status changes.
     ------------------------------------------------------------------ */
  body.invitee-pending  #app > section:not(.edit-only),
  body.invitee-pending  #app > footer,
  body.invitee-declined #app > *:not(.edit-only){ display:revert !important }
  body.invitee-declined .thank-you-screen{ display:none !important }
  body.invitee-pending  .chat-fab,
  body.invitee-declined .chat-fab,
  body.invitee-pending  .share-fab,
  body.invitee-attending .share-fab,
  body.invitee-declined .share-fab{ display:flex !important }
  /* Hard fence — the host's tools NEVER show to a public guest, no
     matter what other rules say. Only body.edit (host in edit mode)
     can reveal them. */
  body:not(.edit) .edit-only,
  body:not(.edit) .invitees-section,
  body:not(.edit) #editbar,
  body:not(.edit) #editToggleBtn,
  body:not(.edit) #editPanel{ display:none !important }
  /* Dress-code section — two cards, one for women, one for men, sharing
     the same translucent card style as the Wedding Gifts section. */
  .dress-grid{
    display:grid;
    grid-template-columns:repeat(2, 1fr);
    gap:18px;
    max-width:780px;
    margin:36px auto 0;
  }
  @media(max-width:600px){
    .dress-grid{ grid-template-columns:1fr; gap:14px }
  }
  .dress-card{
    background:rgba(245,234,212,.06);
    border:1px solid rgba(212,172,108,.45);
    border-radius:6px;
    padding:32px 22px;
    text-align:center;
  }
  .dress-card h4{
    font-family:var(--mono, 'Unbounded'), monospace;
    font-size:11px; font-weight:500;
    letter-spacing:.45em; text-transform:uppercase;
    color:var(--gold-2, #fcc440);
    margin-bottom:14px;
  }
  .dress-card p{
    font-family:var(--display, 'Playfair Display'), Georgia, serif;
    font-style:italic;
    font-size:clamp(15px, 1.4vw, 18px);
    color:var(--paper, #f5ead4);
    line-height:1.5;
    margin:0;
  }
  body.theme-light .dress-card{
    background:rgba(255,255,255,.55);
    border-color:rgba(140,108,68,.30);
  }
  body.theme-light .dress-card p{ color:var(--ink, #1a1410) }
  body.theme-light .dress-card h4{ color:var(--gold-3, #b8780a) }

  /* ------------------------------------------------------------------
     Per-card dress photo gallery. Each card holds an array of photos
     rendered as a small grid above the title. In edit mode an extra
     "+" tile appears for adding more, and each thumbnail gets a remove
     (×) button on hover.
     ------------------------------------------------------------------ */
  .dress-gallery{
    display:grid;
    grid-template-columns:repeat(3, 1fr);
    gap:8px;
    margin-bottom:18px;
  }
  .dress-gallery.empty{ display:none }
  body.edit .dress-gallery.empty{
    display:grid;            /* still show the "+" tile in edit mode */
    grid-template-columns:1fr;
  }
  .dress-thumb{
    position:relative;
    aspect-ratio: 1 / 1;
    border-radius:5px;
    background:#1a1410 no-repeat center / cover;
    overflow:hidden;
    cursor:pointer;
    transition:transform .2s;
  }
  .dress-thumb:hover{ transform:scale(1.03) }
  .dress-thumb-remove{
    position:absolute; top:4px; right:4px;
    width:22px; height:22px;
    border:none; border-radius:50%;
    background:rgba(20,10,8,.75);
    color:#fff; font-size:14px; line-height:1;
    cursor:pointer;
    display:none;
    align-items:center; justify-content:center;
    transition:background .15s;
  }
  body.edit .dress-thumb-remove{ display:flex }
  .dress-thumb-remove:hover{ background:rgba(180,40,30,.95) }
  /* "+" add tile, only shown in edit mode */
  .dress-add-tile{
    aspect-ratio: 1 / 1;
    display:none;
    align-items:center; justify-content:center;
    background:rgba(245,234,212,.04);
    border:1px dashed rgba(212,172,108,.55);
    border-radius:5px;
    cursor:pointer;
    color:var(--gold-2, #fcc440);
    font-family:var(--mono, 'Unbounded'), monospace;
    font-size:10px; font-weight:500;
    letter-spacing:.28em; text-transform:uppercase;
    transition:background .15s, border-color .15s;
  }
  body.edit .dress-add-tile{ display:flex }
  /* When the gallery is empty, the lone "+ Add" tile takes the full
     card width with a friendlier prompt — a small square is easy to
     miss next to a card with no other photos. */
  .dress-gallery.empty .dress-add-tile{
    aspect-ratio: 16 / 9;
    font-size:11px;
    letter-spacing:.32em;
  }
  .dress-gallery.empty .dress-add-tile::before{
    content:"📷  ";
    margin-right:6px;
    font-size:18px;
    letter-spacing:0;
  }
  .dress-add-tile:hover{
    background:rgba(252,196,64,.08);
    border-color:var(--gold-2, #fcc440);
  }
  body.theme-light .dress-add-tile{
    background:rgba(255,255,255,.45);
    border-color:rgba(140,108,68,.40);
    color:var(--gold-3, #b8780a);
  }
  body.theme-light .dress-add-tile:hover{
    background:rgba(184,120,10,.08);
    border-color:var(--gold-3, #b8780a);
  }
  /* Lightbox click target — full-size view of a thumbnail */
  body:not(.edit) .dress-thumb{ cursor:zoom-in }
  .dress-upload-cta{
    margin-top:14px;
    padding:9px 18px;
    background:transparent;
    color:var(--gold-2, #fcc440);
    border:1px solid rgba(212,172,108,.55);
    border-radius:999px;
    font-family:var(--mono, 'Unbounded'), monospace;
    font-size:10px; font-weight:500;
    letter-spacing:.32em; text-transform:uppercase;
    cursor:pointer;
    transition:background .2s, color .2s, border-color .2s;
  }
  .dress-upload-cta:hover{
    background:rgba(252,196,64,.10);
    border-color:var(--gold-2, #fcc440);
  }
  body.theme-light .dress-upload-cta{
    color:var(--gold-3, #b8780a);
    border-color:rgba(140,108,68,.45);
  }
  body.theme-light .dress-upload-cta:hover{
    background:rgba(184,120,10,.08);
    border-color:var(--gold-3, #b8780a);
  }

  /* ------------------------------------------------------------------
     Moments — gentle guest upload right inside the page. Reuses the
     /api/wed.php?a=guest-photo backend so submissions land in the
     same album the host manages.
     ------------------------------------------------------------------ */
  .moments-ask{
    margin-top:14px;
    font-family:var(--display, 'Playfair Display'), Georgia, serif;
    font-style:italic;
    font-size:clamp(15px, 1.6vw, 18px);
    color:var(--gold-2, #fcc440);
    max-width:560px;
    margin-left:auto; margin-right:auto;
    line-height:1.55;
  }
  body.theme-light .moments-ask{ color:var(--gold-3, #b8780a) }
  .moments-cta-wrap{
    display:flex; flex-direction:column; align-items:center;
    gap:8px;
    margin:24px auto 28px;
  }
  .moments-cta{
    padding:14px 28px;
    background:linear-gradient(135deg, #fcc440 0%, #e8890a 100%);
    color:#1a0e08;
    border:none; border-radius:999px;
    font-family:var(--mono, 'Unbounded'), monospace;
    font-size:11px; font-weight:600;
    letter-spacing:.42em; text-transform:uppercase;
    cursor:pointer;
    box-shadow:0 10px 30px -8px rgba(232,137,10,.45);
    transition:transform .15s, box-shadow .2s;
  }
  .moments-cta:hover{ transform:translateY(-1px) }
  .moments-cta:disabled{ opacity:.6; cursor:wait }
  .moments-progress{
    min-height:16px;
    font-family:var(--mono, 'Unbounded'), monospace;
    font-size:10px; letter-spacing:.32em; text-transform:uppercase;
    color:var(--gold-2, #fcc440);
    opacity:.85;
  }
  .moments-wall{
    display:grid;
    grid-template-columns:repeat(auto-fill, minmax(140px, 1fr));
    gap:10px;
    margin-top:18px;
  }
  .moments-photo{
    position:relative;
    aspect-ratio: 1 / 1;
    border-radius:6px;
    overflow:hidden;
    background:#1a1410 center/cover no-repeat;
    box-shadow:0 4px 10px rgba(0,0,0,.30);
    cursor:zoom-in;
    transition:transform .25s;
  }
  .moments-photo:hover{ transform:translateY(-2px) }
  .moments-photo .mp-credit{
    position:absolute; bottom:0; left:0; right:0;
    padding:18px 8px 6px;
    background:linear-gradient(180deg, transparent 0%, rgba(0,0,0,.65) 100%);
    color:#fff;
    font-family:var(--serif, 'Crimson Pro'), Georgia, serif;
    font-style:italic;
    font-size:11px;
  }
  body.theme-light .moments-photo{ background:#f0e6d2 center/cover no-repeat }
  @media (max-width:600px){
    .moments-wall{ grid-template-columns:repeat(auto-fill, minmax(110px, 1fr)) }
  }

  /* ------------------------------------------------------------------
     Host-side guest photos grid — admin view of guest submissions.
     ------------------------------------------------------------------ */
  .host-photo-grid{
    display:grid;
    grid-template-columns:repeat(auto-fill, minmax(140px, 1fr));
    gap:10px;
  }
  .host-photo{
    position:relative;
    aspect-ratio: 1 / 1;
    border-radius:6px;
    overflow:hidden;
    background:#1a1410 center/cover no-repeat;
    box-shadow:0 4px 10px rgba(0,0,0,.30);
    cursor:zoom-in;
  }
  .host-photo .hp-credit{
    position:absolute; bottom:0; left:0; right:0;
    padding:14px 8px 6px;
    background:linear-gradient(180deg, transparent 0%, rgba(0,0,0,.65) 100%);
    color:#fff;
    font-family:var(--serif, 'Crimson Pro'), Georgia, serif;
    font-style:italic;
    font-size:11px;
  }
  .host-photo .hp-del{
    position:absolute; top:6px; right:6px;
    width:24px; height:24px;
    border:none; border-radius:50%;
    background:rgba(180,40,30,.88);
    color:#fff; font-size:14px; line-height:1;
    cursor:pointer;
    display:flex; align-items:center; justify-content:center;
    opacity:0;
    transition:opacity .15s;
  }
  .host-photo:hover .hp-del{ opacity:1 }
  .host-photo-empty{
    grid-column:1/-1;
    text-align:center;
    padding:40px 12px;
    color:var(--ink-soft);
    font-style:italic;
  }

  /* ------------------------------------------------------------------
     Guest photo upload takeover — "/?upload=1" landing.
     Designed to feel light, fast, fun. Mobile-first, no fancy libs.
     ------------------------------------------------------------------ */
  .guest-upload{
    position:fixed; inset:0;
    z-index:120;
    overflow-y:auto;
    background:
      radial-gradient(ellipse 60% 40% at 30% 20%, rgba(252,196,64,.18), transparent 60%),
      radial-gradient(ellipse 50% 35% at 80% 70%, rgba(212,80,40,.18), transparent 60%),
      linear-gradient(170deg, #1a0e08 0%, #0c0604 100%);
    color:var(--paper, #f5ead4);
    padding:48px 22px 80px;
  }
  .gu-inner{ max-width:680px; margin:0 auto }
  .gu-hero{ text-align:center; margin-bottom:32px }
  .gu-eyebrow{
    font-family:var(--mono, 'Unbounded'), monospace;
    font-size:11px; font-weight:500;
    letter-spacing:.45em; text-transform:uppercase;
    color:var(--gold-2, #fcc440);
    margin-bottom:14px;
  }
  .gu-title{
    font-family:var(--display, 'Playfair Display'), Georgia, serif;
    font-style:italic; font-weight:600;
    font-size:clamp(34px, 7vw, 54px);
    line-height:1.05; margin-bottom:14px;
    color:#fff;
  }
  .gu-lead{
    font-family:var(--serif, 'Crimson Pro'), Georgia, serif;
    font-style:italic;
    font-size:clamp(15px, 1.6vw, 18px);
    color:rgba(245,234,212,.78);
    max-width:520px; margin:0 auto;
    line-height:1.55;
  }
  .gu-form{
    background:rgba(245,234,212,.04);
    border:1px solid rgba(212,172,108,.30);
    border-radius:10px;
    padding:20px;
    margin-bottom:28px;
  }
  .gu-input{
    width:100%;
    padding:12px 14px;
    background:rgba(255,255,255,.05);
    border:1px solid rgba(212,172,108,.30);
    border-radius:6px;
    font-family:var(--serif, 'Crimson Pro'), Georgia, serif;
    font-size:16px;
    color:var(--paper, #f5ead4);
    outline:none;
    margin-bottom:14px;
    transition:border-color .2s;
  }
  .gu-input::placeholder{ color:rgba(212,172,108,.45); font-style:italic }
  .gu-input:focus{ border-color:var(--gold-2, #fcc440) }

  .gu-drop{
    display:flex; flex-direction:column;
    align-items:center; justify-content:center;
    padding:38px 22px;
    border:2px dashed rgba(212,172,108,.5);
    border-radius:10px;
    background:rgba(252,196,64,.04);
    cursor:pointer;
    transition:background .2s, border-color .2s, transform .15s;
    text-align:center;
  }
  .gu-drop:hover, .gu-drop.drag{
    background:rgba(252,196,64,.10);
    border-color:var(--gold-2, #fcc440);
    transform:translateY(-1px);
  }
  .gu-drop-icon{ font-size:36px; margin-bottom:10px }
  .gu-drop-title{
    font-family:var(--mono, 'Unbounded'), monospace;
    font-size:12px; font-weight:500;
    letter-spacing:.32em; text-transform:uppercase;
    color:var(--gold-2, #fcc440);
    margin-bottom:6px;
  }
  .gu-drop-hint{
    font-family:var(--serif, 'Crimson Pro'), Georgia, serif;
    font-style:italic;
    font-size:13px;
    color:rgba(245,234,212,.55);
  }
  /* Thumbnail row of selected photos before sending */
  .gu-preview{
    display:grid;
    grid-template-columns:repeat(auto-fill, minmax(80px, 1fr));
    gap:8px;
    margin-top:14px;
  }
  .gu-preview:empty{ margin-top:0 }
  .gu-thumb{
    position:relative;
    aspect-ratio: 1 / 1;
    border-radius:6px;
    overflow:hidden;
    background:#1a1410 center/cover no-repeat;
    box-shadow:0 4px 10px rgba(0,0,0,.30);
  }
  .gu-thumb-x{
    position:absolute; top:4px; right:4px;
    width:22px; height:22px;
    border:none; border-radius:50%;
    background:rgba(20,10,8,.78);
    color:#fff; font-size:14px; line-height:1;
    cursor:pointer;
    display:flex; align-items:center; justify-content:center;
  }
  .gu-thumb.uploading::after{
    content:""; position:absolute; inset:0;
    background:rgba(20,10,8,.55) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='28' height='28' viewBox='0 0 28 28'%3E%3Ccircle cx='14' cy='14' r='10' stroke='%23fcc440' stroke-width='2.5' fill='none' stroke-linecap='round' stroke-dasharray='40 22'%3E%3CanimateTransform attributeName='transform' type='rotate' from='0 14 14' to='360 14 14' dur='1s' repeatCount='indefinite'/%3E%3C/circle%3E%3C/svg%3E") center / 28px no-repeat;
  }
  .gu-thumb.done::after{
    content:"✓"; position:absolute; inset:0;
    background:rgba(110,160,90,.40);
    color:#fff; font-size:24px;
    display:flex; align-items:center; justify-content:center;
  }

  .gu-send{
    width:100%;
    margin-top:18px;
    padding:16px 22px;
    background:linear-gradient(135deg, #fcc440 0%, #e8890a 100%);
    color:#1a0e08;
    border:none; border-radius:999px;
    font-family:var(--mono, 'Unbounded'), monospace;
    font-size:12px; font-weight:600;
    letter-spacing:.42em; text-transform:uppercase;
    cursor:pointer;
    transition:transform .15s, box-shadow .2s, opacity .2s;
    box-shadow:0 10px 30px -8px rgba(232,137,10,.45);
  }
  .gu-send:not(:disabled):hover{ transform:translateY(-1px) }
  .gu-send:disabled{ opacity:.45; cursor:not-allowed; box-shadow:none }
  .gu-progress{
    margin-top:10px; min-height:18px;
    text-align:center;
    font-family:var(--mono, 'Unbounded'), monospace;
    font-size:10px; letter-spacing:.32em; text-transform:uppercase;
    color:var(--gold-2, #fcc440);
    opacity:.85;
  }

  .gu-wall-head{ text-align:center; margin:36px 0 14px }
  .gu-wall-eyebrow{
    font-family:var(--mono, 'Unbounded'), monospace;
    font-size:9px; font-weight:500;
    letter-spacing:.45em; text-transform:uppercase;
    color:var(--gold-2, #fcc440);
    display:block; margin-bottom:6px;
  }
  .gu-wall-title{
    font-family:var(--display, 'Playfair Display'), Georgia, serif;
    font-style:italic; font-weight:500;
    font-size:clamp(22px, 3vw, 28px);
    color:#fff;
  }
  .gu-wall{
    display:grid;
    grid-template-columns:repeat(auto-fill, minmax(110px, 1fr));
    gap:8px;
  }
  .gu-wall-photo{
    position:relative;
    aspect-ratio: 1 / 1;
    border-radius:6px;
    overflow:hidden;
    background:#1a1410 center/cover no-repeat;
    cursor:zoom-in;
    box-shadow:0 4px 10px rgba(0,0,0,.30);
    transition:transform .25s;
  }
  .gu-wall-photo:hover{ transform:translateY(-2px) }
  .gu-wall-photo .gu-credit{
    position:absolute; bottom:0; left:0; right:0;
    padding:18px 8px 6px;
    background:linear-gradient(180deg, transparent 0%, rgba(0,0,0,.65) 100%);
    color:#fff;
    font-family:var(--serif, 'Crimson Pro'), Georgia, serif;
    font-style:italic;
    font-size:11px;
    letter-spacing:.02em;
  }
  .gu-wall-empty{
    grid-column:1/-1;
    text-align:center;
    padding:32px 12px;
    color:rgba(245,234,212,.55);
    font-style:italic;
    font-family:var(--serif, 'Crimson Pro'), Georgia, serif;
  }

  .gu-back{
    display:block;
    text-align:center;
    margin-top:36px;
    color:rgba(212,172,108,.75);
    text-decoration:none;
    font-family:var(--mono, 'Unbounded'), monospace;
    font-size:10px; letter-spacing:.4em; text-transform:uppercase;
    transition:color .2s;
  }
  .gu-back:hover{ color:var(--gold-2, #fcc440) }

  @media (max-width:600px){
    .guest-upload{ padding:36px 16px 60px }
    .gu-form{ padding:16px }
    .gu-drop{ padding:30px 18px }
    .gu-preview{ grid-template-columns:repeat(auto-fill, minmax(70px, 1fr)) }
    .gu-wall{ grid-template-columns:repeat(auto-fill, minmax(96px, 1fr)) }
  }

  /* ------------------------------------------------------------------
     Role chip in the edit bar — tells the host which account they're
     signed in as (Bride / Groom / Planner / Host).
     ------------------------------------------------------------------ */
  .eb-role{
    display:inline-flex; align-items:center;
    margin-left:10px;
    padding:4px 10px;
    border:1px solid rgba(212,172,108,.45);
    border-radius:999px;
    font-family:var(--mono, 'Unbounded'), monospace;
    font-size:9px; font-weight:500;
    letter-spacing:.32em; text-transform:uppercase;
    color:var(--gold-2, #fcc440);
    background:rgba(252,196,64,.08);
  }
  .eb-role.role-bride  { color:#e8a8c4; border-color:rgba(232,168,196,.5); background:rgba(232,168,196,.10) }
  .eb-role.role-groom  { color:#9ec3e8; border-color:rgba(158,195,232,.5); background:rgba(158,195,232,.10) }
  .eb-role.role-planner{ color:#fcc440; border-color:rgba(252,196,64,.5);  background:rgba(252,196,64,.10) }

  /* Settings — role passwords panel */
  .role-pass-grid{ display:grid; grid-template-columns:1fr 1fr 1fr; gap:10px; margin-top:10px }
  @media(max-width:600px){ .role-pass-grid{ grid-template-columns:1fr } }
  .role-pass-grid .field{ margin:0 }
  .role-pass-grid label{
    font-family:var(--mono, 'Unbounded'), monospace;
    font-size:10px; font-weight:500;
    letter-spacing:.32em; text-transform:uppercase;
    color:var(--ink-soft, #5a4836);
    display:block; margin-bottom:4px;
  }
  .role-pass-grid input{
    width:100%; padding:10px 12px;
    border:1px solid var(--line-2, rgba(140,108,68,.30));
    border-radius:4px;
    font-family:'SF Mono', Menlo, monospace;
    font-size:14px;
  }

  /* ------------------------------------------------------------------
     Pending-save indicator — small pulsing dot on the edit bar so the
     host can see when a delta save is still in flight. The
     beforeunload guard also blocks navigation while this is active.
     ------------------------------------------------------------------ */
  #editbar.syncing::before{
    content:"";
    display:inline-block;
    width:8px; height:8px;
    margin-right:8px;
    border-radius:50%;
    background:var(--gold-2, #fcc440);
    box-shadow:0 0 0 0 rgba(252,196,64,.6);
    animation:syncing-pulse 1.4s ease-in-out infinite;
    vertical-align:middle;
  }
  @keyframes syncing-pulse{
    0%,100%{ box-shadow:0 0 0 0 rgba(252,196,64,.6); transform:scale(1); }
    50%   { box-shadow:0 0 0 8px rgba(252,196,64,0); transform:scale(1.1); }
  }

  /* ------------------------------------------------------------------
     Sent-invitation tracking — pill filter + green check on each row.
     ------------------------------------------------------------------ */
  .invitee-filters{
    display:inline-flex; gap:4px;
    padding:3px;
    background:rgba(212,172,108,.10);
    border-radius:999px;
    margin-left:8px;
  }
  .invitee-filter-btn{
    padding:6px 14px;
    background:transparent;
    border:none;
    border-radius:999px;
    font-family:var(--mono, 'Unbounded'), monospace;
    font-size:10px; font-weight:500;
    letter-spacing:.32em; text-transform:uppercase;
    color:var(--ink-soft, #998878);
    cursor:pointer;
    transition:background .15s, color .15s;
  }
  .invitee-filter-btn:hover{ color:var(--gold-2, #fcc440) }
  .invitee-filter-btn.active{
    background:var(--ink, #1a1410);
    color:var(--gold-2, #fcc440);
  }
  body.theme-light .invitee-filter-btn.active{
    background:var(--ink, #1a1410);
    color:#fff;
  }
  .inv-icon-btn.sent{
    color:#7fb37a;
    border-color:rgba(127,179,122,.6);
    background:rgba(127,179,122,.10);
  }
  .inv-icon-btn.sent:hover{
    color:#a3d098;
    border-color:#a3d098;
  }
  /* Confirmation/last-call icon — color reflects guest status. */
  .inv-icon-btn.confirm-attending{
    color:#a3d098; border-color:rgba(127,179,122,.5); background:rgba(127,179,122,.10);
  }
  .inv-icon-btn.confirm-declined{
    color:#d8826b; border-color:rgba(177,77,60,.45); background:rgba(177,77,60,.10);
  }
  .inv-icon-btn.confirm-pending{
    color:var(--gold-2, #fcc440); border-color:rgba(252,196,64,.45); background:rgba(252,196,64,.06);
  }
  .inv-icon-btn.confirm-pending-sent{
    color:var(--gold-2, #fcc440); border-color:rgba(252,196,64,.65); background:rgba(252,196,64,.18);
  }
  .inv-icon-btn.confirm-overdue{
    color:#fff; border-color:#d8826b; background:#b14d3c;
    animation:overdue-pulse 2s ease-in-out infinite;
  }
  @keyframes overdue-pulse{
    0%,100%{ box-shadow:0 0 0 0 rgba(216,130,107,.55) }
    50%   { box-shadow:0 0 0 6px rgba(216,130,107,0) }
  }
  /* Overdue pill next to the guest's name. */
  .inv-overdue-badge{
    display:inline-block;
    margin-left:6px;
    padding:2px 8px;
    border-radius:999px;
    background:rgba(216,130,107,.18);
    color:#e89a82;
    font-family:var(--mono, 'Unbounded'), monospace;
    font-size:9px; font-weight:500;
    letter-spacing:.18em; text-transform:uppercase;
    vertical-align:middle;
  }
  body.theme-light .inv-overdue-badge{
    background:rgba(177,77,60,.12);
    color:#a8442e;
  }
  .inv-icon-btn.has-table{
    color:var(--gold-2, #fcc440);
    border-color:rgba(252,196,64,.5);
    background:rgba(252,196,64,.10);
  }
  .inv-icon-btn.has-table:hover{
    color:#fff;
    background:var(--gold-2, #fcc440);
  }
  .inv-table-badge{
    display:inline-block;
    margin-left:8px;
    padding:2px 8px;
    border-radius:999px;
    background:rgba(252,196,64,.15);
    color:var(--gold-2, #fcc440);
    font-family:var(--mono, 'Unbounded'), monospace;
    font-size:9px; font-weight:500;
    letter-spacing:.18em; text-transform:uppercase;
    vertical-align:middle;
  }
  body.theme-light .inv-table-badge{
    background:rgba(184,120,10,.12);
    color:var(--gold-3, #b8780a);
  }
  /* Dedicated Gift column — shows the cash amount or note plus the
     thank-you status. Pink while pending; green once thanked. */
  .inv-gift-cell{
    display:flex; flex-direction:column; gap:2px;
    overflow:hidden;
  }
  .inv-gift-cell .inv-gift-amount{
    font-family:var(--serif, 'Crimson Pro'), Georgia, serif;
    font-size:14px; font-weight:500;
    color:#f3a5b8;
    line-height:1.2;
    white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
  }
  .inv-gift-cell.thanked .inv-gift-amount{ color:#a3d098 }
  .inv-gift-cell .inv-gift-status{
    font-family:var(--mono, 'Unbounded'), monospace;
    font-size:9px; font-weight:500;
    letter-spacing:.28em; text-transform:uppercase;
    color:#a3d098;
  }
  .inv-gift-cell .inv-gift-status.pending{
    color:rgba(243,165,184,.75);
  }
  .inv-gift-cell .inv-gift-empty{
    font-family:var(--serif), Georgia, serif;
    font-style:italic;
    color:var(--muted, #998878);
    text-align:left;
  }
  body.theme-light .inv-gift-cell .inv-gift-amount{ color:#9c2e58 }
  body.theme-light .inv-gift-cell.thanked .inv-gift-amount{ color:#3d7a3a }
  body.theme-light .inv-gift-cell .inv-gift-status{ color:#3d7a3a }
  body.theme-light .inv-gift-cell .inv-gift-status.pending{ color:#9c2e58; opacity:.7 }
  body.theme-light .inv-gift-cell .inv-gift-empty{ color:var(--ink-soft, #5a4836) }

  /* Gift chip on each row — pink/magenta when gift received but not
     yet thanked, soft green when a thank-you has been sent. */
  .inv-gift-badge{
    display:inline-block;
    margin-left:6px;
    padding:2px 8px;
    border-radius:999px;
    background:rgba(232,90,140,.18);
    color:#f3a5b8;
    font-family:var(--mono, 'Unbounded'), monospace;
    font-size:9px; font-weight:500;
    letter-spacing:.16em; text-transform:none;
    vertical-align:middle;
    max-width:140px;
    overflow:hidden;
    text-overflow:ellipsis;
    white-space:nowrap;
  }
  .inv-gift-badge.thanked{
    background:rgba(127,179,122,.18);
    color:#a3d098;
  }
  body.theme-light .inv-gift-badge{
    background:rgba(196,40,90,.10);
    color:#9c2e58;
  }
  body.theme-light .inv-gift-badge.thanked{
    background:rgba(80,140,80,.12);
    color:#3d7a3a;
  }
  /* Thank-you action button — coral when gift recorded but unthanked,
     green when already sent, dim when no gift to thank. */
  .inv-icon-btn.has-gift{
    color:#f3a5b8;
    border-color:rgba(232,90,140,.45);
    background:rgba(232,90,140,.10);
  }
  .inv-icon-btn.has-gift:hover{ color:#fff; background:#e85a8c; border-color:#e85a8c }
  .inv-icon-btn.thanked{
    color:#a3d098;
    border-color:rgba(127,179,122,.6);
    background:rgba(127,179,122,.10);
  }
  .inv-icon-btn.thanked:hover{ color:#cce8c4; border-color:#a3d098 }

  /* ------------------------------------------------------------------
     Admin metrics dashboard — extra "Total seats" / "Comments" cards
     and the stacked attending/declined/pending ratio bar.
     ------------------------------------------------------------------ */
  .invitee-stats{ flex-wrap:wrap }
  .invitee-stats .istat{ position:relative }
  .istat-sub{
    margin-top:6px;
    font-family:var(--mono, 'Unbounded'), monospace;
    font-size:9px; font-weight:500;
    letter-spacing:.32em; text-transform:uppercase;
    color:var(--gold-2, #fcc440);
    opacity:.8;
  }
  body.theme-light .istat-sub{ color:var(--gold-3, #b8780a) }
  .invitee-bar{
    display:flex;
    height:10px;
    width:100%;
    margin:14px 0 4px;
    background:rgba(212,172,108,.12);
    border-radius:999px;
    overflow:hidden;
  }
  .invitee-bar > div{ height:100%; transition:width .4s ease }
  .invitee-bar-yes    { background:linear-gradient(90deg, #6f9d6e, #b9d49e); }
  .invitee-bar-no     { background:linear-gradient(90deg, #b14d3c, #d8826b); }
  .invitee-bar-pending{ background:linear-gradient(90deg, #c4a050, #e3c98c); }

  /* ------------------------------------------------------------------
     Admin invitee table — Comments column + mobile fallback block.
     Override the 6-column grid from wed-bday.css to add the new cell.
     On mobile, .hide-m hides the dedicated cell and the wrapped
     .inv-note-mobile block under the row takes over.
     ------------------------------------------------------------------ */
  .invitee-table .inv-row,
  .invitee-table .inv-row.head{
    /* checkbox · avatar · guest · phone · side · status · gift · comments · actions */
    /* Bumped GIFT column 0.7fr → 1.05fr so the amount input is visible
       and editable (was so narrow it looked like just a "—" dash). */
    grid-template-columns: 22px 28px 1.5fr 1fr 0.75fr 0.95fr 1.05fr 1.2fr auto;
    gap:8px;
    padding:8px 12px;
    align-items:center;
  }
  /* Compact type so all 9 columns fit on a laptop without scroll. */
  .invitee-table .inv-row.head{
    font-size:8.5px;
    letter-spacing:.22em;
    padding:10px 12px;
  }
  .invitee-table .inv-name{ font-size:13.5px; line-height:1.2 }
  .invitee-table .inv-meta{ font-size:10.5px; margin-top:1px }
  .invitee-table .inv-status{ font-size:8px; padding:3px 7px; letter-spacing:.18em }
  .invitee-table .inv-avatar{ width:28px; height:28px; font-size:11px }
  .invitee-table .inv-icon-btn{ width:28px; height:28px; font-size:12px }
  .invitee-table .inv-actions{ gap:3px }
  /* (Inline selects styling unified into the single block below to
     avoid two competing rules — see "Inline selects — single look"
     further down.) */
  /* Inline gift input — single-line cell. Just the amount; thank-you
     state is conveyed by the green ✓ tick (when sent) and by the
     coral 💌 action button on the same row. No more "pending" text
     mixed in with the amount. */
  .inv-gift-cell{
    display:flex; align-items:center; gap:4px;
    overflow:hidden;
  }
  .inv-gift-input{
    flex:1; min-width:0; width:100%;
    padding:6px 9px;
    /* Subtle field background + dashed border so the host can SEE it's
       an input, not just a placeholder dash. Filled state turns gold. */
    background:rgba(252,196,64,.06);
    border:1px dashed rgba(160,118,61,.35);
    border-radius:5px;
    font-family:var(--mono, 'Unbounded'), monospace;
    font-size:13px; font-weight:700;
    color:#a0763d;
    text-align:center;
    outline:none;
    transition:border-color .15s, background .15s, color .15s;
  }
  /* Empty cell — softer "Add $" hint. */
  .inv-gift-cell:not(.has-gift) .inv-gift-input{
    color:var(--muted, #998878); font-weight:500;
    background:transparent; border-style:dashed; border-color:rgba(160,118,61,.25);
  }
  /* Filled — solid gold pill so the amount POPS in the table. */
  .inv-gift-cell.has-gift .inv-gift-input{
    background:rgba(252,196,64,.18);
    border:1px solid rgba(160,118,61,.35);
    color:#7a5a2c;
  }
  .inv-gift-cell.thanked .inv-gift-input{
    background:rgba(122,168,114,.16);
    border-color:rgba(63,107,58,.35);
    color:#3f6b3a;
  }
  .inv-gift-input::placeholder{ color:var(--muted, #998878); font-style:italic; font-weight:400; opacity:.7 }
  .inv-gift-input:hover{ border-color:rgba(160,118,61,.6); background:rgba(252,196,64,.14) }
  .inv-gift-input:focus{ border-style:solid; border-color:#fcc440; background:rgba(252,196,64,.22); color:#a0763d }
  .inv-gift-thanked-tick{
    font-size:11px; font-weight:600;
    color:#a3d098;
    flex-shrink:0;
  }
  body.theme-light .inv-gift-input{ color:#9c2e58 }
  body.theme-light .inv-gift-cell.thanked .inv-gift-input{ color:#3d7a3a }
  body.theme-light .inv-gift-thanked-tick{ color:#3d7a3a }
  /* Smooth image fade-in for the progressive-load Phase 2. Every
     element that gets its backgroundImage set in render() inherits
     this transition, so photos appear with a gentle 600 ms fade
     instead of popping in. */
  .hero-bg, .hero-corner,
  .venue-img, #venueImg, #venueImg2,
  .dress-thumb, .moments-photo, .gu-wall-photo,
  .gallery-grid > *, .gift-whish-logo{
    transition: background-image .6s ease, opacity .6s ease;
  }

  /* Sortable column headers — click to toggle. Active column shows
     ▲ / ▼ and tints gold so it's easy to see what's being sorted. */
  .inv-row.head .inv-sortable{
    cursor:pointer;
    user-select:none;
    transition:color .15s;
  }
  .inv-row.head .inv-sortable:hover{
    color:var(--gold-2, #fcc440);
  }
  .inv-row.head .inv-sortable.active{
    color:var(--gold-2, #fcc440);
  }
  body.theme-light .inv-row.head .inv-sortable:hover,
  body.theme-light .inv-row.head .inv-sortable.active{
    color:var(--gold-3, #b8780a);
  }

  /* Filter pills — compact too, so they don't dwarf the table. */
  .invitee-filter-btn{
    font-size:9px;
    padding:5px 10px;
    letter-spacing:.22em;
  }
  /* Stat cards — slightly smaller numbers so the row of 10 cards fits. */
  .istat .istat-val{ font-size:24px }
  .istat .istat-label{ font-size:9px; letter-spacing:.28em }
  .istat-sub{ font-size:8.5px; letter-spacing:.22em }
  /* Inline selects — single look. Same font + size as the Guest
     name so every cell in the row reads on one visual line. The
     pill chrome stays so they're recognisable as actionable
     dropdowns; just no more shouty uppercase mono text. */
  .inv-inline-status,
  .inv-inline-side{
    width:100%;
    height:32px;                         /* fixed row height for alignment */
    padding:0 22px 0 12px;
    background:transparent;
    border:1px solid var(--seam, rgba(212,172,108,.30));
    border-radius:999px;
    font-family:var(--serif, 'Crimson Pro'), Georgia, serif;
    font-size:13.5px;
    font-weight:500;
    letter-spacing:.005em;
    text-transform:none;
    color:var(--paper, #f5ead4);
    cursor:pointer;
    appearance:none; -webkit-appearance:none;
    background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'><path fill='none' stroke='%23fcc440' stroke-width='1.4' d='M1 1l4 4 4-4'/></svg>");
    background-repeat:no-repeat;
    background-position:right 8px center;
    transition:border-color .15s, background-color .15s, color .15s;
    line-height:30px;                    /* matches height-2px so text centers */
    text-align:left;
    text-overflow:ellipsis;
    overflow:hidden;
    white-space:nowrap;
  }
  .inv-inline-status:hover, .inv-inline-side:hover{ border-color:var(--gold-2, #fcc440) }
  .inv-inline-status.status-pending  { color:var(--muted, #998878) }
  .inv-inline-status.status-attending{ color:#a3d098; border-color:rgba(127,179,122,.45) }
  .inv-inline-status.status-declined { color:#d8826b; border-color:rgba(177,77,60,.45) }
  .inv-inline-side.side-bride{ color:#e8a8c4; border-color:rgba(232,168,196,.45) }
  .inv-inline-side.side-groom{ color:#9ec3e8; border-color:rgba(158,195,232,.45) }
  .inv-inline-side.side-both { color:#fcc440; border-color:rgba(252,196,64,.45) }
  body.theme-light .inv-inline-status,
  body.theme-light .inv-inline-side{ color:var(--ink, #1a1410); border-color:rgba(140,108,68,.30) }

  /* ─── Row-wide visual alignment ─────────────────────────────────
     Center every cell vertically against the same baseline. Force
     the gift input to the same height as the pills so the row reads
     as a single horizontal line. The Comments cell shrinks to a
     single line with ellipsis so it never grows the row. */
  .invitee-table .inv-row{ align-items:center; }
  .invitee-table .inv-row > div{ min-width:0 }
  .inv-gift-input{
    height:32px;
    line-height:32px;
    padding:0 10px;
    font-size:13.5px;
    font-weight:500;
  }
  .inv-gift-cell{ height:32px; align-items:center }
  .inv-gift-thanked-tick{ font-size:14px; line-height:32px }
  .inv-note-cell{
    display:flex; flex-direction:column; justify-content:center;
    height:auto;
    font-size:13.5px;
    line-height:1.3;
  }
  .inv-note-cell .inv-note-text{
    -webkit-line-clamp:1;                /* one line in the row */
    line-clamp:1;
    font-size:13.5px;
  }
  .inv-note-cell .inv-note-when{
    font-size:9.5px;
    margin-top:2px;
  }
  /* Avatar + action buttons share the same height so no column
     overhangs the row. */
  .invitee-table .inv-avatar{ width:32px; height:32px; line-height:32px; font-size:12px }
  .invitee-table .inv-icon-btn{ width:32px; height:32px; line-height:30px; font-size:13px }
  .invitee-table .inv-name{ font-size:13.5px; line-height:1.25 }
  .invitee-table .inv-meta{ font-size:11px; line-height:1.3 }
  .invitee-table .inv-row{
    grid-template-columns: 24px 32px 1.5fr 1fr 0.85fr 1.05fr 0.8fr 1.4fr auto;
    gap:10px;
    padding:9px 14px;
  }
  .invitee-table .inv-row.head{ font-size:9.5px; letter-spacing:.22em; padding:11px 14px }
  @media(max-width:760px){
    .invitee-table .inv-row,
    .invitee-table .inv-row.head{
      grid-template-columns: 24px 38px 1fr auto;
    }
  }
  .inv-note-cell{
    font-family:var(--serif, 'Crimson Pro'), Georgia, serif;
    font-size:14px;
    color:var(--paper, #f5ead4);
    line-height:1.4;
    overflow:hidden;
  }
  .inv-note-cell .inv-note-text{
    font-style:italic;
    display:-webkit-box;
    -webkit-line-clamp:2;
    -webkit-box-orient:vertical;
    overflow:hidden;
    white-space:pre-wrap;
    word-break:break-word;
  }
  .inv-note-cell .inv-note-when{
    font-family:var(--mono, 'Unbounded'), monospace;
    font-size:9px; letter-spacing:.3em; text-transform:uppercase;
    color:var(--gold-2, #fcc440);
    margin-top:4px; opacity:.85;
  }
  .inv-note-cell.inv-note-empty{
    color:var(--muted, #998878);
    font-style:italic;
    text-align:center;
  }
  body.theme-light .inv-note-cell{ color:var(--ink, #1a1410) }
  body.theme-light .inv-note-cell .inv-note-when{ color:var(--gold-3, #b8780a) }
  body.theme-light .inv-note-cell.inv-note-empty{ color:var(--ink-soft, #5a4836) }

  /* Mobile fallback — quoted block under the row when the column is hidden. */
  .inv-note-mobile{ display:none }
  @media(max-width:760px){
    .inv-row.has-note{ padding-bottom:18px }
    .inv-note-mobile{
      display:block;
      grid-column: 1 / -1;
      margin-top:10px;
      padding:12px 14px;
      background:rgba(212,172,108,.06);
      border-left:3px solid var(--gold-2, #fcc440);
      border-radius:3px;
    }
    .inv-note-mobile .inv-note-label{
      display:block;
      font-family:var(--mono, 'Unbounded'), monospace;
      font-size:9px; font-weight:500;
      letter-spacing:.35em; text-transform:uppercase;
      color:var(--gold-2, #fcc440);
      margin-bottom:6px;
    }
    .inv-note-mobile .inv-note-text{
      font-family:var(--serif, 'Crimson Pro'), Georgia, serif;
      font-style:italic;
      font-size:14px;
      color:var(--paper, #f5ead4);
      line-height:1.5;
      white-space:pre-wrap;
      word-break:break-word;
    }
    body.theme-light .inv-note-mobile{
      background:rgba(184,120,10,.06);
      border-left-color:var(--gold-3, #b8780a);
    }
    body.theme-light .inv-note-mobile .inv-note-label{ color:var(--gold-3, #b8780a) }
    body.theme-light .inv-note-mobile .inv-note-text{ color:var(--ink, #1a1410) }
  }

  /* ------------------------------------------------------------------
     Guest-page "Leave a Note" — always available to invitees, separate
     from the manage-reservation flow so a pending or declined guest
     can still send the couple a message.
     ------------------------------------------------------------------ */
  .guest-note-section{ padding:80px 24px; text-align:center }
  .guest-note-card{
    max-width:560px;
    margin:24px auto 0;
    padding:28px 26px;
    background:rgba(245,234,212,.06);
    border:1px solid rgba(212,172,108,.45);
    border-radius:6px;
    backdrop-filter:blur(2px);
  }
  .guest-note-card textarea{
    width:100%;
    min-height:110px;
    padding:14px 16px;
    background:rgba(255,255,255,.04);
    border:1px solid rgba(212,172,108,.35);
    border-radius:4px;
    font-family:var(--serif, 'Crimson Pro'), Georgia, serif;
    font-size:16px;
    color:var(--paper, #f5ead4);
    resize:vertical;
    outline:none;
    transition:border-color .2s;
  }
  .guest-note-card textarea:focus{
    border-color:var(--gold-2, #fcc440);
  }
  .guest-note-card textarea::placeholder{
    color:rgba(212,172,108,.55);
    font-style:italic;
  }
  .guest-note-card .gn-actions{
    margin-top:14px;
    display:flex; gap:10px; justify-content:center; flex-wrap:wrap;
  }
  body.theme-light .guest-note-card{
    background:rgba(255,255,255,.55);
    border-color:rgba(140,108,68,.30);
  }
  body.theme-light .guest-note-card textarea{
    background:#fff;
    border-color:rgba(140,108,68,.35);
    color:var(--ink, #1a1410);
  }
  body.theme-light .guest-note-card textarea::placeholder{
    color:rgba(140,108,68,.55);
  }

  /* The gifts line — phone number, "at Whish", and the account name all
     read at the same size as body text, separated by thin gold dots.
     Number stays in a slightly mono-spaced face for clarity but sized
     to match the surrounding line so nothing shouts. */
  .gifts-line{
    font-family:var(--serif, 'Crimson Pro'), Georgia, serif;
    font-size:clamp(15px, 1.4vw, 18px);
    font-weight:400;
    letter-spacing:.025em;
    line-height:1.55;
    color:var(--paper, #f5ead4);
    margin:0 0 24px;
    text-align:center;
  }
  .gifts-num{
    font-family:'SF Mono', Menlo, 'Courier New', monospace;
    font-size:1em;            /* same size as the line, just monospace */
    font-weight:500;
    letter-spacing:.06em;
    color:var(--gold-2, #fcc440);
    user-select:all;
    white-space:nowrap;
  }
  .gifts-sep{
    color:var(--gold-2, #fcc440);
    opacity:.7;
    margin:0 4px;
  }
  .gifts-actions{
    display:flex; gap:10px;
    justify-content:center;
    flex-wrap:wrap;
  }
  /* Light-theme adjustments — match the rest of the page */
  body.theme-light .gifts-card{
    background:rgba(255,255,255,.55);
    border-color:rgba(140,108,68,.30);
  }
  body.theme-light .gifts-line{ color:var(--ink, #1a1410) }
  body.theme-light .gifts-num{ color:var(--gold-3, #b8780a) }
  body.theme-light .gifts-sep{ color:var(--gold-3, #b8780a) }
  @media (max-width:600px){
    .gifts-section{ padding:60px 18px }
    .gifts-line{ font-size:15px }
  }

  /* ------------------------------------------------------------------
     Traced hearts — sparingly random gold heart outlines that fade in,
     drift up gently, and fade out. Pure CSS animation; spawn cadence
     controlled by JS (every 3–10 seconds at random viewport positions).
     Skipped on prefers-reduced-motion and in edit mode.
     ------------------------------------------------------------------ */
  .float-heart{
    position:fixed;
    pointer-events:none;
    z-index:6;
    /* color is set per-heart via inline style — defaults to gold if missing */
    color:var(--gold-2, #fcc440);
    opacity:0;
    will-change:transform, opacity;
    animation:heart-float 6s ease-out forwards;
  }
  .float-heart svg{
    width:100%; height:100%; display:block;
    /* glow color matches heart color, set per-heart via --heart-glow */
    filter:drop-shadow(0 2px 10px var(--heart-glow, rgba(232,137,10,.40)));
  }
  @keyframes heart-float{
    0%   { opacity:0;   transform:translateY(0)    scale(.85) rotate(-4deg); }
    18%  { opacity:.80; transform:translateY(-10px) scale(1)   rotate(0deg); }
    78%  { opacity:.80; transform:translateY(-72px) scale(1.05) rotate(3deg); }
    100% { opacity:0;   transform:translateY(-110px) scale(.95) rotate(-1deg); }
  }
  @media (prefers-reduced-motion: reduce){
    .float-heart{ display:none !important }
  }

  /* ------------------------------------------------------------------
     Suppress iOS Safari's native long-press chrome on the hero.
     The dark pill with a "+" icon that the user reported was the
     iOS text-selection toolbar (Copy / Look Up / Share / More). The
     blue dot handles around it were iOS's selection markers. They
     trigger when a finger presses-and-holds on text. Disabling
     user-select + touch-callout on the hero stops them from ever
     appearing. Inputs, the gifts number, and contenteditable text
     stay selectable so people can still copy the Whish number, type
     in the RSVP form, and the host can edit fields.
     ------------------------------------------------------------------ */
  .hero, .hero *,
  .gifts-section, .gifts-section *{
    -webkit-user-select:none;
       -moz-user-select:none;
            user-select:none;
    -webkit-touch-callout:none;
  }
  .hero input, .hero textarea,
  .hero [contenteditable="true"],
  .gifts-num,
  body.edit [data-edit]{
    -webkit-user-select:text;
       -moz-user-select:text;
            user-select:text;
    -webkit-touch-callout:default;
  }

  /* ------------------------------------------------------------------
     Toast: never render an empty toast box. The DOM eval showed the
     .toast element painting its dark `var(--ink)` background as a tiny
     36×20 rectangle at the bottom of the viewport even when its text
     was empty (a theme override was bypassing the default opacity:0).
     `:empty` makes it impossible — without text inside, the box
     collapses to display:none.
     ------------------------------------------------------------------ */
  .toast:empty{ display:none !important }
  .toast:not(.show){
    opacity:0 !important;
    pointer-events:none !important;
    visibility:hidden !important;
  }

  /* ------------------------------------------------------------------
     Save-the-date callout under the eyebrow — uses the dynamic
     state.details.dateLabel so it stays in sync with everything else.
     ------------------------------------------------------------------ */
  .count-date{
    font-family:var(--display, 'Playfair Display'), Georgia, serif;
    font-style:italic;
    font-size:clamp(28px, 4vw, 44px);
    color:var(--gold-2, #fcc440);
    margin:14px 0 36px;
    letter-spacing:.015em;
    text-align:center;
    line-height:1.1;
  }
  /* Tighten the eyebrow → date spacing */
  .count .eyebrow + .count-date{ margin-top:10px }

  /* ------------------------------------------------------------------
     Romantic loader — hearts + energy field overlay.
     The loader stays visible at least 2500ms so guests feel a beat of
     anticipation. While it's up, traced gold hearts rise in a steady
     "field" from the bottom, against a slow-pulsing radial glow.
     ------------------------------------------------------------------ */
  .loader-energy{
    position:absolute; inset:0; pointer-events:none; z-index:0;
    background:
      radial-gradient(ellipse 60% 40% at 30% 35%, rgba(232,137,10,.18), transparent 70%),
      radial-gradient(ellipse 55% 45% at 70% 60%, rgba(212,50,30,.22), transparent 70%),
      radial-gradient(ellipse 80% 50% at 50% 100%, rgba(252,196,64,.25), transparent 70%);
    animation:loader-energy-pulse 3.4s ease-in-out infinite alternate;
  }
  @keyframes loader-energy-pulse{
    0%   { opacity:.55; transform:scale(1); }
    100% { opacity:1;   transform:scale(1.06); }
  }
  .loader-hearts{
    position:absolute; inset:0; pointer-events:none; z-index:1; overflow:hidden;
  }
  .loader-trace-heart{
    position:absolute; bottom:-40px;
    color:var(--gold-2, #fcc440);
    opacity:0;
    animation:loader-heart-rise var(--dur,4s) ease-out forwards;
  }
  .loader-trace-heart svg{
    width:100%; height:100%; display:block;
    filter:drop-shadow(0 2px 14px rgba(232,137,10,.45));
  }
  @keyframes loader-heart-rise{
    0%   { opacity:0;   transform:translateY(40px)   scale(.7) rotate(var(--rot,0deg)); }
    18%  { opacity:.95; transform:translateY(0)      scale(1)  rotate(var(--rot,0deg)); }
    78%  { opacity:.85; transform:translateY(-260px) scale(1.05) rotate(calc(var(--rot,0deg) + 8deg)); }
    100% { opacity:0;   transform:translateY(-360px) scale(.9) rotate(calc(var(--rot,0deg) - 4deg)); }
  }
  /* Lift the existing loader content above the energy + hearts layers. */
  .loader-inner{ position:relative; z-index:2 }
  @media (prefers-reduced-motion: reduce){
    .loader-energy{ animation:none }
    .loader-trace-heart{ display:none }
  }

  @media (max-width:600px){
    .hero-greeting{ font-size:19px; margin-bottom:18px }
    .hero-invite-text{ font-size:15.5px; margin-bottom:20px; padding:0 8px }
  }
