  :root{
    --cream:#faf5ef; --card:#fffdfb; --line:#ece2d7; --line-soft:#f2e9df;
    --ink:#4a413b; --ink-strong:#3f3630; --ink-soft:#5c524b; --muted:#8a7f76;
    --rose:#c68a86; --rose-deep:#a9645f; --rose-tint:#fbf1ee; --gold:#c9a961;
    --serif:'Cormorant Garamond',Georgia,serif;
    --sans:'Inter',system-ui,-apple-system,sans-serif;
  }
  *{box-sizing:border-box;margin:0;padding:0}
  html{-webkit-text-size-adjust:100%}
  body{
    font-family:var(--sans);line-height:1.6;color:var(--ink);
    background:radial-gradient(1100px 560px at 50% -180px,#f7e9e4 0%,rgba(247,233,228,0) 62%),var(--cream);
    min-height:100vh;padding:22px 16px 56px;display:flex;justify-content:center;
  }
  a{color:var(--rose-deep)}
  a:hover{color:#8d4b47}
  .wrap{width:100%;max-width:540px}

  .card{background:var(--card);border:1px solid var(--line);border-radius:20px;
    box-shadow:0 22px 60px -34px rgba(74,65,59,.45);overflow:hidden}
  .card + .card{margin-top:18px}

  /* ---- Hero ---- */
  .hero{position:relative;width:100%;aspect-ratio:4/3;background:#f3ebe2}
  .hero img{display:block;width:100%;height:100%;object-fit:cover;object-position:center 26%}
  .hero::after{content:'';position:absolute;left:0;right:0;bottom:0;height:80px;
    background:linear-gradient(to bottom,rgba(255,253,251,0),rgba(255,253,251,.82) 62%,var(--card))}

  .intro{padding:4px 26px 30px;text-align:center}
  .eyebrow{font-size:11px;letter-spacing:.32em;text-transform:uppercase;font-weight:600;
    color:var(--rose-deep);margin-bottom:14px}
  h1{font-family:var(--serif);font-weight:600;font-size:clamp(2.9rem,13vw,4rem);
    line-height:.98;letter-spacing:.005em;color:var(--ink-strong)}
  h1 .amp{font-style:italic;font-weight:400;color:var(--rose-deep)}
  .rule{display:flex;align-items:center;justify-content:center;gap:14px;margin-top:18px}
  .rule i{display:block;width:38px;height:1px;background:var(--gold)}
  .rule b{display:block;width:5px;height:5px;background:var(--gold);transform:rotate(45deg)}
  .date{font-family:var(--serif);font-size:1.35rem;margin-top:14px}
  .place{font-size:11px;letter-spacing:.24em;text-transform:uppercase;color:var(--muted);margin-top:6px}
  .invite-line{font-size:1rem;color:var(--ink-soft);margin-top:20px;text-align:left;text-wrap:pretty}

  .divider{height:1px;background:var(--line)}

  /* ---- Itinerary ---- */
  .section{padding:24px 26px 6px}
  .section-label{font-size:11px;letter-spacing:.24em;text-transform:uppercase;
    color:var(--muted);font-weight:600;margin-bottom:16px}
  .item{display:flex;gap:14px;padding:14px 0;border-top:1px solid var(--line-soft)}
  .item img{flex:none;width:68px;height:68px;border-radius:10px;object-fit:cover}
  .item-kind{font-size:10px;letter-spacing:.2em;text-transform:uppercase;
    color:var(--rose-deep);font-weight:600}
  .item-name{font-family:var(--serif);font-size:1.3rem;line-height:1.25;margin-top:2px}
  .item-time{font-size:.85rem;color:var(--muted);font-style:italic}
  .maplink{display:inline-block;font-size:.8rem;font-weight:500;margin-top:4px;
    text-decoration:none;border-bottom:1px solid #e2cfc8}
  .cal{display:block;text-align:center;margin:14px 0 4px;padding:12px;border:1px solid var(--line);
    border-radius:12px;font-size:.85rem;font-weight:600;text-decoration:none;background:var(--cream);color:var(--ink)}

  /* ---- Evening feature (the afters invitation leads on this) ---- */
  .feature{border-top:1px solid var(--line-soft);padding-top:16px}
  /* height:auto is load-bearing — without it the height="675" attribute wins
     and aspect-ratio never applies, rendering the feature image as a tall
     portrait block on a phone. */
  .feature img{display:block;width:100%;height:auto;aspect-ratio:16/9;object-fit:cover;border-radius:12px}
  .feature .item-kind{margin-top:14px}
  .feature .item-name{font-size:1.55rem}

  /* ---- Landscape band ---- */
  .band{position:relative;margin-top:20px}
  .band img{display:block;width:100%;height:190px;object-fit:cover;object-position:46% 76%}
  .band::after{content:'';position:absolute;inset:0;
    background:linear-gradient(to top,rgba(63,54,48,.55),rgba(63,54,48,.05))}
  .band span{position:absolute;left:0;right:0;bottom:12px;z-index:1;text-align:center;color:#fff;
    font-size:10px;letter-spacing:.28em;text-transform:uppercase}

  /* ---- Good to know ---- */
  .know{padding:22px 26px 26px}
  .know-grid{display:grid;gap:12px}
  .know-row{display:flex;gap:12px}
  .know-row dt{flex:none;width:88px;font-size:10px;letter-spacing:.14em;text-transform:uppercase;
    color:var(--rose-deep);font-weight:600;padding-top:4px}
  .know-row dd{font-size:.92rem;color:var(--ink-soft)}

  /* ---- RSVP ---- */
  .rsvp{padding:26px}
  .rsvp h2{font-family:var(--serif);font-size:1.85rem;font-weight:600;line-height:1.15}
  .rsvp .sub{font-size:.9rem;color:var(--muted);margin-top:4px}
  .field-label{display:block;font-size:10px;letter-spacing:.14em;text-transform:uppercase;
    color:var(--muted);font-weight:600;margin:18px 0 6px}
  .choices{display:grid;gap:10px;margin-top:18px}
  .choices.inline{display:flex;gap:10px;margin-top:0}
  .choice{display:flex;align-items:center;gap:12px;width:100%;text-align:left;
    border:1.5px solid var(--line);background:#fff;border-radius:14px;padding:14px 16px;
    cursor:pointer;font-family:inherit;font-size:1rem;font-weight:500;color:var(--ink);
    transition:border-color .15s,background .15s}
  .choice:hover{border-color:var(--rose)}
  .choice .dot{flex:none;width:22px;height:22px;border-radius:50%;border:2px solid var(--line);
    display:grid;place-items:center;font-size:.75rem;color:#fff;transition:inherit}
  .choice[aria-checked="true"]{border-color:var(--rose-deep);background:var(--rose-tint)}
  .choice[aria-checked="true"] .dot{border-color:var(--rose-deep);background:var(--rose-deep)}
  .choice.sm{font-size:.98rem;padding:13px 16px}
  .choice.xs{width:auto;font-size:.95rem;padding:11px 15px}
  .choice.xs .dot{width:18px;height:18px;font-size:.65rem}
  input[type=text],textarea{width:100%;font-family:var(--sans);font-size:1rem;padding:12px 14px;
    border:1px solid var(--line);border-radius:12px;background:#fff;color:var(--ink)}
  input[type=text]:focus,textarea:focus{outline:2px solid var(--rose);outline-offset:1px;border-color:transparent}
  textarea{resize:vertical;min-height:64px}
  .send{margin-top:20px;width:100%;font-family:var(--sans);font-size:1rem;font-weight:600;
    border:none;border-radius:99px;padding:15px 16px;cursor:pointer;color:#fff;
    background:var(--rose-deep);transition:background .15s,opacity .15s}
  .send:hover{background:var(--ink-strong)}
  .send:focus-visible{outline:2px solid var(--ink-strong);outline-offset:3px}
  .send[disabled]{opacity:.6;cursor:default}
  /* The incomplete state no longer dims the button. It is a live control: tapping
     it before you have answered gives you the hint that tells you what is missing,
     so dimming it to .75 read as "disabled, don't bother" and hid the one thing
     that explains what to do. The button now matches the RSVP button above it and
     the hint carries the state instead. Only a real send disables it. */
  .hint{min-height:1.2em;margin-top:10px;text-align:center;font-size:.85rem;color:var(--rose-deep)}

  .thanks{text-align:center;padding:6px 26px 26px}
  .thanks h2{font-family:var(--serif);font-size:2.2rem;font-weight:600;line-height:1.1;margin:14px 0 8px}
  .thanks p{font-size:1rem;color:var(--ink-soft);text-wrap:pretty}
  .echo{margin-top:18px;padding:14px 16px;border:1px solid var(--line);border-radius:14px;
    background:var(--cream);font-size:.9rem;color:var(--ink-soft);text-align:left}
  .amend{margin-top:14px;background:none;border:none;font-family:inherit;font-size:.85rem;
    font-weight:600;color:var(--rose-deep);cursor:pointer;text-decoration:underline;text-underline-offset:3px}

  /* ---- FAQ (content comes from the private dashboard, via Blobs) ---- */
  .faq{padding:24px 26px 20px}
  .faq h2{font-family:var(--serif);font-size:1.5rem;font-weight:600;line-height:1.2}
  .faq .sub{font-size:.9rem;color:var(--muted);margin-top:4px}
  .faq details{border-top:1px solid var(--line-soft);padding:2px 0}
  .faq details:first-of-type{margin-top:14px}
  .faq summary{list-style:none;cursor:pointer;padding:13px 28px 13px 0;position:relative;
    font-size:.96rem;font-weight:500;color:var(--ink)}
  .faq summary::-webkit-details-marker{display:none}
  .faq summary::after{content:'+';position:absolute;right:4px;top:50%;transform:translateY(-50%);
    font-size:1.2rem;font-weight:400;color:var(--rose-deep);line-height:1}
  .faq details[open] summary::after{content:'\2013'}
  .faq details[open] summary{color:var(--rose-deep)}
  .faq .ans{padding:0 4px 15px 0;font-size:.92rem;color:var(--ink-soft);text-wrap:pretty;
    white-space:pre-wrap}

  .signoff{text-align:center;margin-top:22px;font-family:var(--serif);
    font-size:1.05rem;font-style:italic;color:var(--muted)}

  .reveal{animation:fadeUp .25s ease}
  @keyframes fadeUp{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
  [hidden]{display:none !important}
  @media (prefers-reduced-motion:reduce){.reveal{animation:none}}

/* ---- Public page ----
   Reuses the invitation's cards, sections, feature block and FAQ; these are
   the few things it needs on top. */
.prose{font-size:.95rem;color:var(--ink-soft);text-wrap:pretty;line-height:1.65}
.prose + .prose{margin-top:12px}
.feature .prose{margin-top:8px}
.item .prose{margin-top:6px}
.know .prose:first-of-type{margin-top:2px}
.know-row dd .maplink{margin-top:2px}

/* On a narrow phone the 88px label column leaves too little room for the
   longer public-page entries (the address, the minibus, the taxi numbers),
   so stack the label above its content instead of beside it. */
@media (max-width:430px){
  .know-row{display:block}
  .know-row dt{width:auto;padding-top:0;margin-bottom:3px}
}


/* ---- Photo collage (public page) ----
   height:auto is load-bearing here for the same reason as the feature image:
   without it the width/height attributes win and aspect-ratio never applies. */
.collage{display:grid;grid-template-columns:repeat(3,1fr);gap:6px;margin-top:20px}
.collage img{width:100%;height:auto;aspect-ratio:1;object-fit:cover;display:block;
  border-radius:8px;background:#f3ebe2}
@media (min-width:500px){.collage{grid-template-columns:repeat(4,1fr);gap:8px}}
/* One tile carries the grid so it reads as a collage rather than a contact
   sheet. Dense flow lets the smaller tiles backfill around it. */
.collage{grid-auto-flow:dense}
.collage .lead{grid-column:span 2;grid-row:span 2}

/* ============================================================
   DESKTOP LAYOUT, public page only (.wrap.home)
   Everything above is the mobile design and is left alone: this is added on
   top, so the phone version cannot regress. The two invitations share this
   stylesheet and deliberately do not get any of it, because a personal
   invitation reads better as a single column than stretched across a monitor.
   ============================================================ */
@media (min-width:900px){
  body{padding:34px 28px 70px}

  .wrap.home{
    max-width:1120px;
    display:grid;
    grid-template-columns:1fr 1fr;
    gap:22px;
    align-items:start;
  }
  /* .card + .card margin is a mobile rule; the grid gap owns spacing here */
  .wrap.home .card + .card{margin-top:0}

  .wrap.home .card--intro,
  .wrap.home .card--day,
  .wrap.home .card--faq,
  .wrap.home .card--note,
  .wrap.home .signoff{grid-column:1 / -1}
  .wrap.home .card--travel{grid-column:1}
  .wrap.home .card--stay{grid-column:2}

  /* ---- hero runs the full width, so it wants a wider crop ---- */
  .wrap.home .hero{aspect-ratio:21/9}
  .wrap.home .hero img{object-position:center 30%}
  .wrap.home .intro{padding:8px 40px 26px}
  .wrap.home h1{font-size:4.6rem}
  .wrap.home .date{font-size:1.5rem}

  /* ---- story: collage on the left, the words on the right ---- */
  .wrap.home .card--intro .know{
    display:grid;
    grid-template-columns:2fr 1fr;
    gap:34px;
    /* start, not center: the staggered columns below are much taller than the
       prose, and centring left the words floating in the middle of nowhere. */
    align-items:start;
    padding:30px 40px 40px;
  }
  .wrap.home .card--intro .collage{margin-top:0}
  .wrap.home .card--intro .story-text{order:2}
  .wrap.home .card--intro .prose{font-size:1rem}

  /* ---- the photographs: three staggered columns ----
     Replaces the four-column mosaic. The mosaic's tiles were small enough that
     the section read as a texture rather than as photographs of people; these
     are roughly twice the size and you can see faces.

     Done entirely in CSS, deliberately: the markup stays one flat .collage of
     twelve <img>, so the phone layout above is untouched and the two invitations
     that share this stylesheet are unaffected.

     In a three-column grid, child n lands in column ((n-1) mod 3)+1, so
     :nth-child(3n+2) is the middle column and 3n+3 the right one. The offsets
     are a transform rather than a margin so they shift the picture without
     moving the grid row, which is what keeps the columns interlocking instead
     of just pushing everything down. */
  .wrap.home .collage{
    grid-template-columns:repeat(3,1fr);
    gap:12px;
    grid-auto-flow:row;          /* the mosaic's dense packing would refill the gaps */
    align-items:start;
    padding-bottom:44px;         /* the offset columns hang below the last row */
  }
  /* the mosaic's two special tiles become ordinary ones again */
  .wrap.home .collage .lead,
  .wrap.home .collage .wide{grid-column:auto;grid-row:auto;aspect-ratio:4/5}

  .wrap.home .collage img{aspect-ratio:4/5}
  .wrap.home .collage img:nth-child(3n+2){aspect-ratio:3/4;transform:translateY(44px)}
  .wrap.home .collage img:nth-child(3n+3){aspect-ratio:1;transform:translateY(16px)}

  /* ---- the day: feature image beside its words ---- */
  .wrap.home .card--day .section{padding:30px 40px 34px}
  .wrap.home .card--day .feature{
    display:grid;grid-template-columns:1.1fr 1fr;gap:28px;align-items:center;
    border-top:none;padding-top:0;margin-top:22px;
  }
  .wrap.home .card--day .feature img{grid-row:span 5}
  .wrap.home .card--day .feature .item-kind{margin-top:0}
  .wrap.home .card--day .item{max-width:none}
  .wrap.home .card--day .item img{width:150px;height:150px}

  .wrap.home .know{padding:28px 34px 32px}
  .wrap.home .faq{padding:28px 40px 26px}
  .wrap.home .card--faq .ans{max-width:70ch}
}

/* Between phone and desktop, keep the single column but let it breathe. */
@media (min-width:640px) and (max-width:899px){
  .wrap.home{max-width:620px}
  .wrap.home .collage{grid-template-columns:repeat(4,1fr)}
  .wrap.home .collage .lead{grid-column:span 2;grid-row:span 2}
  /* lead alone is 15 cells in a 4-column grid, which is three and three
     quarter rows and leaves a hole; the wide tile makes it 16. */
  .wrap.home .collage .wide{grid-column:span 2;aspect-ratio:2/1}
}

/* ---- Envelope line: who the invitation is addressed to ----
   Ported from the design template. The name lands here first, then again as
   the salutation, in the RSVP question and at the sign-off. */
.envelope{display:flex;align-items:center;justify-content:center;gap:14px;
  padding:15px 24px 14px;background:var(--cream);border-bottom:1px solid var(--line)}
.env-rule{flex:1;max-width:64px;height:1px;background:var(--line)}
.env-line{font-family:var(--serif);font-size:1.2rem;line-height:1;white-space:nowrap;color:var(--ink-soft)}
.env-line b{font-family:var(--sans);font-size:9px;font-weight:600;letter-spacing:.24em;
  text-transform:uppercase;color:var(--muted);margin-right:9px;vertical-align:middle}
.env-line span{font-style:italic;color:var(--ink-strong);vertical-align:middle}

/* ---- A hand-written line to the guest, from ?m= on the link ---- */
.note-from-us{margin-top:22px;padding-top:20px;border-top:1px solid var(--line-soft);text-align:left}
.note-from-us b{display:block;font-family:var(--sans);font-size:10px;font-weight:600;
  letter-spacing:.2em;text-transform:uppercase;color:var(--rose-deep);margin-bottom:8px}
.note-from-us span{font-family:var(--serif);font-size:1.15rem;font-style:italic;
  line-height:1.5;color:var(--ink-soft);text-wrap:pretty}

/* ---- Where to stay, shown once they have said yes ---- */
.stay{margin-top:20px;padding:16px 18px;border:1px solid var(--line);border-radius:14px;
  background:var(--cream);text-align:left}
.stay-head{display:block;font-size:10px;font-weight:600;letter-spacing:.2em;
  text-transform:uppercase;color:var(--rose-deep);margin-bottom:8px}
.stay-lede{font-size:.9rem;color:var(--ink-soft);text-wrap:pretty}
.stay-when{font-size:.8rem;color:var(--muted);margin-top:14px}
.stay-rates{display:grid;gap:6px;margin:6px 0 14px}
.stay-rates > div{display:flex;justify-content:space-between;gap:12px;font-size:.88rem;
  border-bottom:1px dotted var(--line);padding-bottom:5px}
.stay-rates dt{color:var(--ink)}
.stay-rates dd{color:var(--ink-soft);text-align:right;white-space:nowrap}
.stay-contact{display:grid;gap:3px;font-size:.85rem}
.stay-contact span{color:var(--muted)}
.signoff em{font-style:italic;color:var(--rose-deep)}


/* Download-as-PDF block. Some guests need a document to show an immigration
   officer, so this is given its own card rather than hidden in the small print. */
.pdf-card{text-align:center;padding:24px 26px 26px}
.pdf-h{font-family:var(--serif);font-weight:600;font-size:1.5rem;color:var(--ink-strong);margin:0 0 .4rem}
.pdf-p{font-size:.92rem;color:var(--muted);line-height:1.55;margin:0 auto 1.1rem;max-width:34rem}
.pdf-btn{display:inline-flex;align-items:center;gap:.5rem;font-family:var(--sans);font-size:.86rem;
  font-weight:600;text-decoration:none;color:#fff;background:var(--rose-deep);border:1px solid var(--rose-deep);
  padding:.62rem 1.25rem;border-radius:99px;transition:.15s}
.pdf-btn:hover{background:var(--ink-strong);border-color:var(--ink-strong)}
.pdf-btn:focus-visible{outline:2px solid var(--ink-strong);outline-offset:3px}
.pdf-btn::before{content:"";width:15px;height:15px;flex:none;
  background:currentColor;-webkit-mask:var(--dl) center/contain no-repeat;mask:var(--dl) center/contain no-repeat}
:root{--dl:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 4.6v10.2M8.2 11.2 12 14.9l3.8-3.7'/%3E%3Cpath d='M4.8 19.4h14.4'/%3E%3C/svg%3E")}


/* Language switch. Nihal's side of the list is largely Turkish-speaking, so the
   choice sits at the very top rather than buried at the foot of the page. */
/* The switch sits on the photo, top right, rather than in a bar of its own above
   the card: a strip at the very top pushed the whole invitation down and read as
   browser chrome rather than part of the page. The hero is already
   position:relative, and its gradient is at the bottom, so this corner is free.
   The pill carries its own scrim because it sits over a photograph and cannot
   rely on whatever happens to be behind it. */
.langbar{position:absolute;top:.6rem;right:.6rem;z-index:2;display:flex;gap:.3rem}
.langbtn{font-family:var(--sans);font-size:.7rem;font-weight:600;letter-spacing:.03em;
  border:1px solid rgba(255,255,255,.34);background:rgba(31,26,23,.42);color:#fff;
  -webkit-backdrop-filter:blur(7px);backdrop-filter:blur(7px);
  padding:.42rem .78rem;border-radius:99px;cursor:pointer;transition:.15s;
  text-shadow:0 1px 3px rgba(0,0,0,.4)}
.langbtn:hover{background:rgba(31,26,23,.62);border-color:rgba(255,255,255,.6)}
.langbtn[aria-pressed="true"]{background:var(--rose);border-color:var(--rose);color:#fff;text-shadow:none}
.langbtn:focus-visible{outline:2px solid #fff;outline-offset:2px}

/* Two links side by side in the same block were separated only by the whitespace
   between inline-blocks, four pixels, so "The Carrigart Hotel" and "Call +353..."
   read as one sentence rather than two things you can tap. Anywhere they sit
   together they need a real gap. */
/* The reply is the one thing the invitation is asking for, so it gets a real
   button by the opening paragraph rather than only existing at the foot of a long
   page. It is an anchor, not a button element: with no JS it still jumps. */
.rsvp-jump{display:inline-block;margin:22px 0 4px;padding:.62rem 1.4rem;border-radius:999px;
  background:var(--rose-deep);color:#fff;text-decoration:none;font-family:var(--sans);
  font-size:.82rem;font-weight:600;letter-spacing:.02em;transition:.15s}
.rsvp-jump:hover{background:var(--ink-strong)}
.rsvp-jump:focus-visible{outline:2px solid var(--ink-strong);outline-offset:3px}
@media (prefers-reduced-motion:no-preference){html{scroll-behavior:smooth}}

.maplink + .maplink{margin-left:.9rem}
/* The rates are the thing people scan this row for, so they get their own line
   rather than being buried at the end of the paragraph above. */
.rates{margin:.45rem 0 .5rem;font-variant-numeric:tabular-nums}

/* The two links belong with the paragraph they relate to, not stranded at the
   foot of the party detail where they read as belonging to the last row of it. */
.feature-links{display:flex;flex-wrap:wrap;gap:.4rem 1rem;margin:-2px 0 4px}

/* The party detail on the home page: same rows as Good to know, tucked under
   the feature so it reads as part of the party block rather than a new section. */
.party-detail{margin-top:16px;padding-top:14px;border-top:1px solid var(--line-soft)}
