/* ============================================================
   Wedding reply card — bespoke, self-contained page styles.
   Identity: graphite pencil portrait on its own cream paper,
   a single deep-laurel accent, system serif + sans (no webfonts).
   Namespaced under .inv so it never leans on Bootstrap.
   ============================================================ */

/* ============================================================
   TOKENS
   ============================================================ */
:root {
    /* the palette is three colours; everything else is derived from them, so the
       triplets are kept alongside for the rgba() lines, washes and shadows */
    --paper-rgb:   255, 250, 238;  /* cream, sampled from the drawing's own paper */
    --ink-rgb:      44,  42,  38;  /* warm graphite-black */
    --laurel-rgb:   69,  96,  79;  /* deep laurel green */

    --paper:       rgb(var(--paper-rgb));
    --ink:         rgb(var(--ink-rgb));    /* body text */
    --pencil:      #6E6A62;                /* muted graphite — secondary text, matches the drawing */
    --laurel:      rgb(var(--laurel-rgb)); /* the green as a *field* — never inverted */
    --accent:      var(--laurel);          /* the green as a *mark* — re-pointed inside .topband */
    --accent-ink:  #354B3E;                /* darker green for text-on-paper contrast */
    --line:        rgba(var(--ink-rgb), 0.16);  /* hairline rules */
    --line-strong: rgba(var(--ink-rgb), 0.30);
    --flag:        #9B3B2E;                /* the one red — form errors only */

    --display: Georgia, "Times New Roman", Times, serif;
    --body:    -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;

    --measure: 1120px;
    --ease: cubic-bezier(0.22, 1, 0.36, 1);
    --transition: 0.3s var(--ease);  /* the default hover/focus timing */
}

/* ============================================================
   PAGE SHELL
   ============================================================ */
*, *::before, *::after { box-sizing: border-box; }

/* this page opts out of the Bootstrap entrypoint, so it carries its own reset —
   without it the UA's 8px body margin leaves a gutter around the paper */
html { background: var(--paper); }  /* also colours the overscroll area */
body { margin: 0; }

.inv {
    margin: 0;
    min-height: 100svh;
    background: var(--paper);
    color: var(--ink);
    font-family: var(--body);
    font-weight: 400;
    line-height: 1.6;
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
    overflow-x: hidden;
}

/* faint paper grain — sits above the background, below content */
.inv::before {
    content: "";
    position: fixed;
    inset: 0;
    z-index: 0;
    pointer-events: none;
    opacity: 0.05;
    mix-blend-mode: multiply;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

.inv__wrap {
    position: relative;
    z-index: 1;
    max-width: var(--measure);
    margin: 0 auto;
    padding: 0 clamp(1.25rem, 4vw, 2.5rem);
}

/* ============================================================
   SHARED PRIMITIVES
   ============================================================ */

/* the small letterspaced cap — eyebrows, form labels, the copy confirmation */
.eyebrow,
.form-label,
.col-form-label,
.gifts__accounts-label,
.gifts__copy-status {
    font-family: var(--body);
    font-weight: 600;
    font-size: 0.72rem;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--accent-ink);
    margin: 0;
}

/* the standfirst under a section title */
.reply__lede,
.gifts__lede {
    max-width: 30rem;
    margin: 1rem auto 0;
    font-size: 1.02rem;
    color: var(--pencil);
}

/* one focus treatment for everything interactive; the components below shift
   the offset where a ring at arm's length would collide with a neighbour */
.langbar__link:focus-visible,
.form-check-input:focus-visible + .form-check-label,
.submit:focus-visible,
.gifts__iban:focus-visible,
.gallery__track:focus-visible,
.gallery__btn:focus-visible,
.foot__contact:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 3px;
}

/* ============================================================
   TOP BAND — the first screen, full-bleed laurel
   The paper-context tokens are re-pointed here, so every rule
   inside inverts without being rewritten. Islands that stay on
   paper (the portrait's mat) reset them back.
   ============================================================ */
.topband {
    position: relative;
    background: var(--laurel);
    --ink:         var(--paper);
    --pencil:      rgba(var(--paper-rgb), 0.68);
    --accent-ink:  rgba(var(--paper-rgb), 0.84);
    --accent:      #B7CCBA;  /* light sage — the amp, focus rings */
    --line:        rgba(var(--paper-rgb), 0.20);
    --line-strong: rgba(var(--paper-rgb), 0.34);
}

/* the band holds exactly one screen: langbar on top, hero taking the rest */
.topband > .inv__wrap {
    display: flex;
    flex-direction: column;
    min-height: 100svh;
}

/* the active pill inverts too — paper chip, laurel type */
.topband .langbar__link.is-active {
    background: var(--paper);
    color: var(--laurel);
}

/* ============================================================
   LANGUAGE SWITCH — pinned to the top of the page
   ============================================================ */
.langbar {
    position: relative;
    z-index: 2;
    padding-top: clamp(1.1rem, 2.5vw, 1.6rem);
}

.langbar__list {
    /* wide enough that the active pill's fill clears the separator on both sides */
    --langbar-gap: 0.9rem;
    display: flex;
    justify-content: flex-end;
    align-items: center;
    gap: var(--langbar-gap);
    list-style: none;
    margin: 0;
    padding: 0;
}

.langbar__link {
    display: inline-block;
    padding: 0.4rem 0.7rem;
    font-family: var(--body);
    font-weight: 600;
    font-size: 0.7rem;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--pencil);
    text-decoration: none;
    border-radius: 2px;
    transition: color var(--transition), background-color var(--transition);
}
.langbar__link:hover { color: var(--accent-ink); }
.langbar__link:focus-visible { outline-offset: 2px; }
.langbar__link.is-active {
    color: var(--paper);
    background: var(--accent);
}

/* hairline separators between the language options */
.langbar__list li + li { position: relative; }
.langbar__list li + li::before {
    content: "";
    position: absolute;
    left: calc(var(--langbar-gap) / -2);  /* centred in the gap, so both neighbours clear it equally */
    top: 50%;
    transform: translateY(-50%);
    width: 1px;
    height: 0.9rem;
    background: var(--line);
}

@media (max-width: 800px) {
    .langbar__list { justify-content: center; }
}

/* ============================================================
   HERO — the opened invitation
   ============================================================ */
.hero {
    display: grid;
    /* the drawing carries the page — give its leaf the wider share */
    grid-template-columns: 1.15fr 1fr;
    align-items: stretch;
    gap: clamp(1.5rem, 4vw, 3.5rem);
    /* less air up top so the hero sits closer to the language switch */
    padding: clamp(0.25rem, 1vw, 0.75rem) 0 clamp(1.5rem, 3vw, 2.5rem);
}
/* inside the band the langbar already claims its slice, so the hero just
   fills what's left of the screen; min-height:0 lets it shrink to do so */
.topband .hero { flex: 1; min-height: 0; }

/* left leaf — the portrait, matted like a framed drawing */
.hero__plate {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* the fold — hairline between the two leaves */
.hero__plate::after {
    content: "";
    position: absolute;
    top: 8%;
    bottom: 8%;
    right: calc(clamp(1.5rem, 4vw, 3.5rem) / -2);
    width: 1px;
    background: linear-gradient(to bottom, transparent, var(--line-strong) 18%, var(--line-strong) 82%, transparent);
}

/* the mat: a passe-partout in the page's own paper, so the frame and the page
   below the band are the same ground — only the hairline border separates them */
.portrait {
    --mat: clamp(0.85rem, 2.2vw, 1.6rem);
    /* against the dark field the sheet reads as hung, not printed:
       a tight contact shadow under a wide, deep ambient one */
    --lift:     14px 30px -16px;
    --lift-far: 46px 80px -44px;
    /* a paper island on the laurel field — put the paper-context hairlines back
       so the mat keeps its graphite rules instead of the band's light ones */
    --line:        rgba(var(--ink-rgb), 0.16);
    --line-strong: rgba(var(--ink-rgb), 0.30);
    position: relative;
    /* the drawing is a tall 5:7 sheet — track the viewport height so it never
       outgrows the fold on short screens */
    width: min(100%, 34rem, 58svh);
    margin: 0;
    padding: var(--mat);
    background: var(--paper);
    border: 1px solid var(--line-strong);
    box-shadow:
        0 1px 2px rgba(20, 30, 24, 0.20),
        0 var(--lift) rgba(20, 30, 24, 0.45),
        0 var(--lift-far) rgba(15, 24, 19, 0.75);
}
/* second hairline, hugging the sheet itself */
.portrait::after {
    content: "";
    position: absolute;
    inset: calc(var(--mat) - 1px);
    border: 1px solid var(--line);
    pointer-events: none;
}
.portrait__img {
    display: block;
    width: 100%;
    height: auto;
    /* the signature move: multiply melts the scan's white into the paper */
    mix-blend-mode: multiply;
}

/* right leaf — the words */
.hero__card {
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding: clamp(1rem, 3vw, 2rem) 0;
}
.hero__intro { margin: 0 0 1.6rem; }

.names {
    font-family: var(--display);
    font-weight: 400;
    font-optical-sizing: auto;
    line-height: 0.92;
    letter-spacing: -0.01em;
    margin: 0;
    color: var(--ink);
}
.names__line { display: block; font-size: clamp(3rem, 8.5vw, 5.75rem); }
.names__amp {
    display: block;
    font-style: italic;
    font-weight: 300;
    font-size: clamp(2.4rem, 6vw, 4rem);
    color: var(--accent);
    margin: 0.1em 0 0.05em;
    padding-left: 0.15em;
}

.meta {
    margin: 2rem 0 0;
    font-size: 1.02rem;
    color: var(--pencil);
    line-height: 1.7;
}
/* the date is marked in the drawing's own paper tone — a highlighter swipe.
   The negative margin cancels the padding so the text still lines up with the
   schedule below; the band is what overhangs, the way a marker would. */
.meta strong {
    display: inline-block;
    font-family: var(--display);
    font-weight: 500;
    font-size: 1.35rem;
    color: var(--laurel);
    background: var(--paper);
    padding: 0.08em 0.45em 0.14em;
    margin-left: -0.45em;
    letter-spacing: 0.005em;
}
.meta__schedule { display: grid; gap: 0.7rem; margin-top: 0.7rem; }
.meta__event { display: grid; gap: 0.1rem; }
.meta__event-when { color: var(--ink); font-weight: 500; }
.meta__event-where { font-size: 0.94rem; color: var(--pencil); }

.scroll-cue {
    display: inline-flex;
    align-items: center;
    gap: 0.6rem;
    margin-top: 2.5rem;
    font-size: 0.85rem;
    font-weight: 600;
    letter-spacing: 0.01em;
    color: var(--accent-ink);
    text-decoration: none;
}
.scroll-cue__arrow {
    position: relative;
    display: inline-block;
    width: 2.25rem;
    height: 1px;
    background: currentColor;
}
/* the head: top + right borders spun about the box centre, so the vertex points
   along the rule and only its tip meets the end — the arms stay clear of it */
.scroll-cue__arrow::after {
    content: "";
    position: absolute;
    right: 0;
    top: 50%;
    width: 6px;
    height: 6px;
    border-top: 1px solid currentColor;
    border-right: 1px solid currentColor;
    transform: translate(-1px, -50%) rotate(45deg);
    transition: transform 0.4s var(--ease);
}
.scroll-cue:hover .scroll-cue__arrow::after { transform: translate(2px, -50%) rotate(45deg); }

/* ---- confirmation: the same right leaf, with the receipt instead of the date ---- */

/* the eyebrow carries the tick, so it sets its own line */
.confirm__eyebrow {
    display: flex;
    align-items: center;
    gap: 0.6rem;
}

/* the seal — a small ring around the tick, the one "done" mark on the page.
   Fixed width, so the eyebrow's line-height doesn't pull the ring into an oval */
.confirm__seal {
    display: grid;
    place-items: center;
    flex: none;
    width: 1.5rem;
    height: 1.5rem;
    border: 1px solid var(--line-strong);
    border-radius: 50%;
    color: var(--accent);
}
.confirm__seal svg { width: 0.8rem; height: 0.8rem; }

.confirm__title {
    font-family: var(--display);
    font-weight: 400;
    font-size: clamp(2.2rem, 5vw, 3.4rem);
    line-height: 1.06;
    letter-spacing: -0.01em;
    margin: 0;
    color: var(--ink);
}
.confirm__lede {
    max-width: 34ch;
    margin: 1.6rem 0 0;
    font-size: 1.02rem;
    color: var(--pencil);
    line-height: 1.7;
}

/* the sign-off — the salutation in the body hand, the names in the display one,
   so the two lines read as a hand-written close rather than one more paragraph */
.confirm__signoff {
    margin: 1.7rem 0 0;
    font-size: 1.02rem;
    color: var(--pencil);
    line-height: 1.5;
}
.confirm__names {
    font-family: var(--display);
    font-size: 1.35rem;
    letter-spacing: 0.005em;
    color: var(--ink);
}

/* stack the leaves on narrow screens */
@media (max-width: 800px) {
    .hero {
        grid-template-columns: 1fr;
        gap: 1.5rem;
        padding-top: 3rem;
        text-align: center;
    }
    .hero__plate::after { display: none; }
    .portrait {
        --mat: 0.8rem;
        --lift:     10px 22px -14px;
        --lift-far: 32px 56px -36px;
        width: min(100%, 24rem);
    }
    .hero__card { padding-top: 0.5rem; align-items: center; }
    .hero__intro, .meta, .confirm__lede, .confirm__signoff { text-align: center; }
    .confirm__eyebrow { justify-content: center; }
    /* centred here, so the swipe shouldn't be pulled left */
    .meta strong { margin-left: 0; }
    .scroll-cue { align-self: center; }
}

/* ============================================================
   REPLY CARD
   ============================================================ */
.reply {
    position: relative;
    padding: clamp(3.5rem, 8vw, 7rem) 0 clamp(2rem, 5vw, 3.5rem);
}
/* the form sits on its own white card, lifted off the cream page —
   the only white surface on the page, so the one thing to *do* stands out */
.reply__inner {
    position: relative;
    z-index: 1;
    /* the measure is the content's; the padding is added on top so the form
       keeps the same line length it had on the bare page */
    --reply-pad: clamp(1.5rem, 5vw, 3.25rem);
    max-width: calc(40rem + 2 * var(--reply-pad));
    margin: 0 auto;
    padding: var(--reply-pad);
    background: #FFFFFF;
    border: 1px solid var(--line);
    border-radius: 3px;
    box-shadow:
        0 1px 2px rgba(var(--ink-rgb), 0.05),
        0 18px 40px -24px rgba(var(--ink-rgb), 0.35);
}
.reply__head { text-align: center; margin-bottom: clamp(2rem, 5vw, 3rem); }
.reply__title {
    font-family: var(--display);
    font-weight: 400;
    font-size: clamp(2rem, 5vw, 3rem);
    line-height: 1.05;
    margin: 0.9rem 0 0;
    color: var(--ink);
}

/* ---- form scaffolding ----
   The reply card is rendered by the Symfony form component through the Bootstrap 5
   theme. Bootstrap's stylesheet is never loaded — only its class names are, and
   they're dressed here as this page's own primitives:
     .mb-3 …………… one field row      .form-control ……… text input / textarea
     .form-label ……… its label        .form-text ……………… the "optional" hint
     .form-check …… one radio        .invalid-feedback … a field's error
*/
.form { display: grid; gap: 1.75rem; }

/* one field row. The theme prints label → control → hint → errors, but the hint
   belongs beside its label, so the first line is shared and everything else
   claims a full line of its own. */
.mb-3 {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.4rem;
}
.mb-3 > * { flex: 0 0 100%; }
.mb-3 > .form-label { flex: 0 1 auto; order: -2; }
.mb-3 > .form-text  { flex: 0 1 auto; order: -1; }

/* fieldsets reset to plain boxes — the legend does the labelling */
fieldset.mb-3,
.events {
    border: 0;
    padding: 0;
    margin: 0;
    min-width: 0;
}
/* a <legend> can't take part in the fieldset's grid gap, so it needs an explicit
   bottom margin to match the label→input rhythm; padding drops the UA's inline nudge */
legend.col-form-label {
    padding: 0;
    margin-bottom: 0.4rem;
}
.form-text {
    font-size: 0.86rem;
    color: var(--pencil);
}

/* the real radio, kept operable but out of sight — the label beside it is the UI */
.form-check-input {
    position: absolute;
    opacity: 0;
    width: 1px;
    height: 1px;
    pointer-events: none;
}

/* the pressable face shared by both radio groups */
.form-check-label {
    font-family: var(--body);
    font-size: 0.76rem;
    font-weight: 600;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--pencil);
    cursor: pointer;
}

/* ---- text inputs ---- */
.form-control {
    width: 100%;
    font-family: var(--body);
    font-size: 1.02rem;
    color: var(--ink);
    background: transparent;
    border: 0;
    border-bottom: 1px solid var(--line-strong);
    padding: 0.6rem 0.1rem;
    transition: border-color var(--transition);
}
.form-control::placeholder { color: var(--pencil); opacity: 0.7; }
/* the underline is the focus signal here, so no ring */
.form-control:focus {
    outline: none;
    border-bottom-color: var(--accent);
}
textarea.form-control { resize: vertical; min-height: 3.2rem; line-height: 1.6; }

/* the theme flags a rejected value on the control itself */
.form-control.is-invalid { border-bottom-color: var(--flag); }
.invalid-feedback,
.alert-danger {
    font-size: 0.86rem;
    color: var(--flag);
}

/* ---- party size — one connected bar of choices, the whole answer visible at a
   glance. Two options of equal weight, so two equal halves. ----
   The theme wraps expanded choices in an unclassed <div>; inside a field row
   that div is the group, and party is the page's only such row. */
fieldset.mb-3 > div {
    display: grid;
    grid-template-columns: 1fr 1fr;
    border: 1px solid var(--line-strong);
    border-radius: 2px;
    overflow: hidden;
}
fieldset.mb-3 .form-check { position: relative; display: flex; }
fieldset.mb-3 .form-check-label {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    padding: 0.7rem 0.6rem;
    transition: background-color var(--transition), color var(--transition);
}
/* hairlines between segments, never on the outer edge */
fieldset.mb-3 .form-check + .form-check .form-check-label { border-left: 1px solid var(--line-strong); }
fieldset.mb-3 .form-check-label:hover { color: var(--accent-ink); background: rgba(var(--laurel-rgb), 0.07); }
fieldset.mb-3 .form-check-input:checked + .form-check-label {
    background: var(--accent);
    color: var(--paper);
}
/* inset, so the ring stays inside the bar's own frame */
fieldset.mb-3 .form-check-input:focus-visible + .form-check-label { outline-offset: -3px; }

/* ---- attendance — mark yes / no for each event on its own ---- */
.events { display: grid; gap: 0.9rem; }
.event {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: 1rem 1.15rem;
    border: 1px solid var(--line-strong);
    border-radius: 2px;
}
.event__info { display: grid; gap: 0.2rem; }
.event__name {
    font-family: var(--display);
    font-size: 1.3rem;
    line-height: 1.1;
    color: var(--ink);
}
.event__time,
.event__where { font-size: 0.82rem; color: var(--pencil); }

.event > [role="radiogroup"] { display: inline-flex; gap: 0.4rem; flex-shrink: 0; }
.event .form-check { position: relative; }
.event .form-check-label {
    display: block;
    min-width: 3.5rem;
    text-align: center;
    padding: 0.5rem 0.9rem;
    border: 1px solid var(--line-strong);
    border-radius: 2px;
    transition: border-color var(--transition), background-color var(--transition), color var(--transition);
}
.event .form-check-label:hover { border-color: var(--accent); color: var(--accent-ink); }
.event .form-check-input:checked + .form-check-label {
    border-color: var(--accent);
    background: var(--accent);
    color: var(--paper);
}

/* ---- submit ---- */
.submit {
    justify-self: center;
    display: inline-flex;
    align-items: center;
    gap: 0.6rem;
    margin-top: 0.75rem;
    font-family: var(--body);
    font-weight: 600;
    font-size: 0.8rem;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--paper);
    background: var(--accent);
    border: 1px solid var(--accent);
    border-radius: 2px;
    padding: 1rem 2.75rem;
    cursor: pointer;
    transition: background-color var(--transition), transform 0.25s var(--ease);
}
.submit:hover { background: var(--accent-ink); }
.submit:active { transform: translateY(1px); }

@media (max-width: 460px) {
    .event { flex-direction: column; align-items: stretch; gap: 0.85rem; text-align: left; }
    .event > [role="radiogroup"] { align-self: stretch; }
    .event .form-check { flex: 1; }
    .event .form-check-label { width: 100%; }
    /* too narrow for two written-out options side by side — stack them */
    fieldset.mb-3 > div { grid-template-columns: 1fr; }
    fieldset.mb-3 .form-check + .form-check .form-check-label {
        border-left: 0;
        border-top: 1px solid var(--line-strong);
    }
}

/* ============================================================
   GIFTS — a quiet note on presents, set off as an aside
   ============================================================ */
.gifts {
    position: relative;
    padding: clamp(2.5rem, 6vw, 4rem) 0;
}
.gifts__inner {
    max-width: 34rem;
    margin: 0 auto;
    text-align: center;
    /* hairline rules top and bottom frame it as an aside between the two cards */
    border-top: 1px solid var(--line);
    border-bottom: 1px solid var(--line);
    padding: clamp(2.5rem, 6vw, 3.5rem) clamp(1.25rem, 4vw, 2rem);
}
.gifts__title {
    font-family: var(--display);
    font-weight: 400;
    font-size: clamp(1.6rem, 4vw, 2.4rem);
    line-height: 1.12;
    margin: 0.9rem auto 0;
    max-width: 22ch;
    color: var(--ink);
}
.gifts__accounts-label { margin: 1.9rem 0 0; }

/* two accounts side by side, stacking on narrow screens */
.gifts__accounts {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 0.9rem clamp(1rem, 4vw, 2rem);
    list-style: none;
    margin: 1rem 0 0;
    padding: 0;
}
.gifts__account {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.4rem;
}
.gifts__account-name {
    font-family: var(--display);
    font-size: 0.95rem;
    letter-spacing: 0.06em;
    color: var(--pencil);
}
/* the plate doubles as a copy button — same frame, now tappable */
.gifts__iban {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    font-family: var(--display);
    font-size: clamp(1.05rem, 3.4vw, 1.3rem);
    letter-spacing: 0.08em;
    white-space: nowrap;
    color: var(--laurel);
    background: none;
    padding: 0.55rem 1.1rem;
    border: 1px solid var(--line-strong);
    border-radius: 2px;
    cursor: pointer;
    transition: color var(--transition), border-color var(--transition);
}
.gifts__iban:hover { color: var(--accent-ink); border-color: var(--accent); }
.gifts__iban:active { transform: translateY(1px); }
.gifts__iban.is-copied { color: var(--accent-ink); border-color: var(--accent); }

.gifts__copy-icon {
    width: 0.85em;
    height: 0.85em;
    flex-shrink: 0;
    opacity: 0.45;
    transition: opacity var(--transition);
}
.gifts__iban:hover .gifts__copy-icon { opacity: 0.75; }
.gifts__copy-icon--done,
.gifts__iban.is-copied .gifts__copy-icon--copy { display: none; }
.gifts__iban.is-copied .gifts__copy-icon--done { display: block; opacity: 1; }

/* live region: reserves its own line so the row doesn't jump when it fills */
.gifts__copy-status {
    min-height: 1.2em;
    margin: 0.7rem 0 0;
}

/* ============================================================
   CLOSING — footer and gallery share one padded block, so the
   names, note and filmstrip read as a single sign-off
   ============================================================ */
.closing {
    padding: clamp(2.5rem, 6vw, 4rem) 0 clamp(2rem, 5vw, 3rem);
}

/* ---- footer ---- */
.foot { text-align: center; }
.foot__amp {
    font-family: var(--display);
    font-style: italic;
    font-weight: 300;
    font-size: 2rem;
    color: var(--accent);
    line-height: 1;
}
.foot__names {
    font-family: var(--display);
    font-size: 1.15rem;
    letter-spacing: 0.02em;
    color: var(--ink);
    margin: 0.5rem 0 0.75rem;
}
.foot__amp-sep { margin: 0 0.5rem; color: var(--accent); font-style: italic; }
/* each host's name is a tap-to-call link; the handset icon hints it */
.foot__contact {
    display: inline-flex;
    align-items: baseline;
    gap: 0.3rem;
    color: inherit;
    text-decoration: none;
    transition: color var(--transition);
}
.foot__contact:hover { color: var(--accent-ink); }
.foot__contact:hover .foot__phone { opacity: 0.7; }
.foot__contact:focus-visible { border-radius: 2px; }
/* a discreet hint — small, dim, and lifted to sit like a superscript beside the name */
.foot__phone {
    width: 0.56em;
    height: 0.56em;
    flex-shrink: 0;
    opacity: 0.4;
    transform: translateY(-0.15em);
    transition: opacity var(--transition);
}
.foot__note { font-size: 0.82rem; letter-spacing: 0.06em; color: var(--pencil); margin: 0; }

/* ============================================================
   GALLERY — a swipeable filmstrip carousel below the footer.
   Fixed height + auto width, so portrait and landscape frames
   sit side by side without cropping.
   ============================================================ */
.gallery {
    position: relative;
    /* sits tight under the footer — the two form the closing block */
    padding: clamp(1.25rem, 3vw, 1.75rem) 0 0;
}
.gallery__viewport { position: relative; }
.gallery__track {
    display: flex;
    gap: clamp(0.75rem, 2vw, 1.25rem);
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scroll-behavior: smooth;
    -webkit-overflow-scrolling: touch;
    list-style: none;
    margin: 0;
    padding: 0;
    scrollbar-width: none;  /* nav is by swipe + buttons */
}
.gallery__track::-webkit-scrollbar { display: none; }
.gallery__track:focus-visible { outline-offset: 4px; border-radius: 2px; }
.gallery__item { flex: 0 0 auto; scroll-snap-align: center; margin: 0; }
.gallery__img {
    display: block;
    height: clamp(8.5rem, 26vw, 13rem);
    width: auto;
    max-width: none;
    border: 1px solid var(--line-strong);
    border-radius: 2px;
    box-shadow: 0 14px 30px -20px rgba(var(--ink-rgb), 0.55);
}

.gallery__btn {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.25rem;
    height: 2.25rem;
    border-radius: 50%;
    /* translucent paper so the button reads over any photo without a hard plate */
    background: rgba(var(--paper-rgb), 0.6);
    -webkit-backdrop-filter: blur(4px);
    backdrop-filter: blur(4px);
    color: var(--accent-ink);
    border: 1px solid var(--line);
    cursor: pointer;
    /* kept out of the way until the viewer hovers or tabs to it */
    opacity: 0;
    transition: opacity 0.25s var(--ease), color var(--transition), border-color var(--transition);
    z-index: 2;
}
.gallery__btn--prev { left: clamp(0.25rem, 1.5vw, 1rem); }
.gallery__btn--next { right: clamp(0.25rem, 1.5vw, 1rem); }
.gallery__viewport:hover .gallery__btn,
.gallery__btn:focus-visible { opacity: 1; }
.gallery__btn:hover { color: var(--accent); border-color: var(--accent); }
.gallery__btn:active { transform: translateY(-50%) scale(0.96); }
.gallery__btn:focus-visible { outline-offset: 2px; }

/* ============================================================
   ENTRANCE MOTION
   ============================================================ */
.reveal { opacity: 0; transform: translateY(14px); }
.inv.is-ready .reveal {
    opacity: 1;
    transform: none;
    transition: opacity 0.9s var(--ease), transform 0.9s var(--ease);
}
.inv.is-ready .reveal[data-delay="1"] { transition-delay: 0.08s; }
.inv.is-ready .reveal[data-delay="2"] { transition-delay: 0.18s; }
.inv.is-ready .reveal[data-delay="3"] { transition-delay: 0.30s; }
.inv.is-ready .reveal[data-delay="4"] { transition-delay: 0.44s; }
.inv.is-ready .reveal[data-delay="5"] { transition-delay: 0.60s; }

/* the drawing settles rather than slides — slower, with a touch of scale */
.portrait.reveal { transform: translateY(14px) scale(0.985); }
.inv.is-ready .portrait.reveal { transform: none; transition: opacity 1.4s var(--ease), transform 1.4s var(--ease); }

@media (prefers-reduced-motion: reduce) {
    .reveal, .inv.is-ready .reveal { opacity: 1; transform: none; transition: none; }
    .scroll-cue__arrow::after { transition: none; }
    .gallery__track { scroll-behavior: auto; }
}