@layer components {
  /* INVITE — one paper letter that contains hero + body, with the
     RSVP as a separate action card below. Page scrolls naturally;
     signed-in returners are anchored to #rsvp on load. */
  .invite-page {
    position: relative;
    width: 100%;
    min-height: 100vh;
    color: var(--ink);
    padding: 88px 40px 80px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 24px;
  }

  /* Preview banner — sits inside the letter card as an inset band at the
     top, breaking the paper edge-to-edge so a host/steward previewing
     someone else's invite sees the "this is a preview" marker without
     a separate full-bleed bar covering the chrome. */
  .invite-preview-banner {
    margin: -72px -64px 28px;
    padding: 12px 24px;
    background: #f4c14d;
    color: #2a1f00;
    font-family: var(--sans);
    font-size: 13px;
    letter-spacing: var(--tracking-cap-wide);
    text-transform: uppercase;
    text-align: center;
    font-weight: var(--weight-semibold);
    border-bottom: 1px solid rgba(0, 0, 0, 0.10);
  }
  .invite-preview-banner strong {
    text-transform: none;
    letter-spacing: 0;
    font-weight: var(--weight-semibold);
  }
  /* RSVP buttons in preview mode (host/steward viewing someone else's
     invite). Visually disabled — clicks are blocked at pointer-events,
     submits are blocked server-side too. */
  .invite-rsvp-actions--preview {
    opacity: 0.55;
    pointer-events: none;
  }
  .invite-rsvp-preview-note {
    margin: 0 0 16px;
    font-family: var(--sans);
    font-size: 12px;
    letter-spacing: var(--tracking-cap-wide);
    text-transform: uppercase;
    color: var(--ink-faint);
    text-align: center;
  }
  /* Disabled submit buttons inside an RSVP card — match the visual
     treatment of pointer-events:none links so the row reads consistent. */
  .invite-rsvp-card .btn[disabled],
  .invite-rsvp-card .btn-paper[disabled] {
    opacity: 0.55;
    cursor: not-allowed;
  }
  .invite-page .stay-landscape {
    position: fixed;
    inset: 0;
    width: 100%;
    height: 100%;
    z-index: 0;
  }

  /* Hero content lives at the top of the letter, on paper. Ink-on-cream. */
  .invite-letter .invite-salutation {
    font-family: var(--hand);
    font-size: 56px;
    line-height: 1.05;
    color: var(--ink);
    margin: 0 0 28px;
    letter-spacing: 0.01em;
    text-align: center;
  }
  .invite-headline {
    font-family: var(--display);
    font-size: 44px;
    line-height: 1.1;
    letter-spacing: -0.005em;
    font-weight: var(--weight-medium);
    margin: 0 auto;
    max-width: 16ch;
    color: var(--ink);
    text-align: center;
  }
  .invite-headline-em {
    font-family: var(--display);
    font-style: italic;
    font-weight: var(--weight-semibold);
    text-decoration: underline;
    text-decoration-thickness: 2px;
    text-underline-offset: 6px;
  }

  /* Wooden trail sign — arrow plank pointing right, lightly tilted as
     if nailed to a tree at the trailhead. Three concentric clip-path
     layers reproduce the routed-edge bevel from the home-page wood
     drawer: dark outer rim → warm highlight → wood face.

     Sizing is content-driven (inline-flex). The arrow tip is a fixed
     22px wedge regardless of how wide the content is — calc() inside
     the polygon keeps the triangle visually flat instead of scaling
     with the box. A nailhead anchors the left end. */
  .invite-shingle {
    --tip: 22px;
    position: relative;
    margin: 56px auto 24px;
    display: inline-flex;
    align-items: center;
    padding: 18px calc(var(--tip) + 28px) 18px 38px;
    background: #1a0d04;
    clip-path: polygon(
      0 0,
      calc(100% - var(--tip)) 0,
      100% 50%,
      calc(100% - var(--tip)) 100%,
      0 100%
    );
    transform: rotate(-1.5deg);
    transform-origin: 0% 50%;
    filter: drop-shadow(0 4px 6px rgba(0, 0, 0, 0.45))
            drop-shadow(0 14px 22px rgba(0, 0, 0, 0.35));
  }
  /* Warm highlight ring. */
  .invite-shingle::before {
    content: '';
    position: absolute;
    inset: 2px;
    clip-path: polygon(
      0 0,
      calc(100% - var(--tip) + 1px) 0,
      100% 50%,
      calc(100% - var(--tip) + 1px) 100%,
      0 100%
    );
    background: rgba(255, 215, 170, 0.32);
    pointer-events: none;
  }
  /* Wood face. */
  .invite-shingle::after {
    content: '';
    position: absolute;
    inset: 4px;
    clip-path: polygon(
      0 0,
      calc(100% - var(--tip) + 2px) 0,
      100% 50%,
      calc(100% - var(--tip) + 2px) 100%,
      0 100%
    );
    background-color: #3a2414;
    background-image:
      radial-gradient(ellipse at 50% 50%, transparent 55%, rgba(0,0,0,0.4) 100%),
      linear-gradient(180deg, rgba(255, 235, 200, 0.10) 0%, rgba(0, 0, 0, 0.20) 100%),
      url("/assets/wood-drawer-6e423f3d.png");
    background-size: auto, auto, 260px auto;
    background-repeat: no-repeat, no-repeat, repeat;
    background-position: center, center, top center;
    pointer-events: none;
  }
  /* Nailhead — sits on top of the wood face on the left end. */
  .invite-shingle-nail {
    position: absolute;
    top: 50%;
    left: 16px;
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: radial-gradient(circle at 35% 30%, #6c6c6c 0%, #2c2c2c 60%, #0a0a0a 100%);
    box-shadow:
      inset 0 -1px 0 rgba(0, 0, 0, 0.6),
      0 1px 1px rgba(0, 0, 0, 0.6);
    transform: translateY(-50%);
    z-index: 2;
  }
  .invite-shingle-block {
    text-align: center;
    padding: 0 18px;
    position: relative;
    z-index: 2;
  }
  .invite-shingle-lbl {
    font-family: var(--sans);
    font-size: var(--cap-sm);
    letter-spacing: var(--tracking-cap-wide);
    text-transform: uppercase;
    font-weight: var(--weight-bold);
    color: rgba(255, 235, 200, 0.7);
    text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.5);
    margin-bottom: 4px;
  }
  .invite-shingle-val {
    font-family: var(--display);
    font-size: 22px;
    font-weight: var(--weight-semibold);
    letter-spacing: 0.02em;
    color: #fff5e0;
    text-shadow:
      0 -1px 0 rgba(0, 0, 0, 0.55),
      0 1px 0 rgba(0, 0, 0, 0.30);
  }
  .invite-shingle-sep {
    width: 1px;
    align-self: stretch;
    background: linear-gradient(180deg,
      rgba(0, 0, 0, 0) 0%,
      rgba(0, 0, 0, 0.45) 50%,
      rgba(0, 0, 0, 0) 100%);
    box-shadow: 1px 0 0 rgba(255, 255, 255, 0.10);
    position: relative;
    z-index: 1;
  }

  /* Letter — one paper card containing hero + body + signature. */
  .invite-letter {
    position: relative;
    z-index: 1;
    width: 100%;
    max-width: 620px;
    background-color: var(--paper);
    background-image: var(--paper-texture);
    background-repeat: repeat;
    background-size: 480px auto;
    color: var(--ink);
    padding: 72px 64px 56px;
    box-shadow: var(--shadow-paper-deep);
    border: 1px solid var(--paper-edge);
    font-family: var(--sans);
    font-size: 16px;
    line-height: 1.75;
  }
  .invite-letter-hero {
    text-align: center;
    margin-bottom: 8px;
  }
  .invite-letter-body {
    margin-top: 24px;
    padding-top: 24px;
    border-top: 1px solid var(--paper-edge);
  }
  .invite-letter p,
  .invite-letter li { font-size: 16px; line-height: 1.75; color: var(--ink); }
  .invite-letter p { margin: 0 0 18px; }
  /* Trix stores blocks as <div>, not <p>. Spacing rule must cover both. */
  .invite-letter-body > p,
  .invite-letter-body > div { margin: 0 0 18px; font-size: 16px; line-height: 1.75; color: var(--ink); }
  .invite-letter-body > p:last-child,
  .invite-letter-body > div:last-child { margin-bottom: 0; }
  .invite-letter ul { margin: 0 0 18px; padding-left: 20px; }
  .invite-letter ul li { margin-bottom: 6px; }

  /* Pull — same display-italic emphasis pattern used elsewhere in the
     letterhead voice. No card, no rules, no glyph. */
  .invite-pull {
    font-family: var(--display);
    font-style: italic;
    font-weight: var(--weight-medium);
    font-size: 18px;
    line-height: 1.55;
    color: var(--ink);
    margin: 8px 0 22px !important;
  }

  .invite-signature {
    margin: 36px 0 0 !important;
    color: var(--ink);
  }

  /* RSVP card — separate sibling paper card under the letter, with
     the same paper aesthetic. Anchor target for #rsvp scroll. */
  .invite-rsvp-card {
    position: relative;
    z-index: 1;
    width: 100%;
    max-width: 620px;
    background-color: var(--paper);
    background-image: var(--paper-texture);
    background-repeat: repeat;
    background-size: 480px auto;
    color: var(--ink);
    padding: 36px 64px 32px;
    box-shadow: var(--shadow-paper-deep);
    border: 1px solid var(--paper-edge);
    text-align: center;
    scroll-margin-top: 24px;
  }
  .invite-rsvp-eyebrow {
    margin: 0 0 18px !important;
    font-family: var(--sans);
    font-size: var(--cap-sm);
    letter-spacing: var(--tracking-cap-wide);
    text-transform: uppercase;
    color: var(--ink-soft);
    font-weight: var(--weight-semibold);
  }
  .invite-rsvp-actions {
    display: flex;
    gap: 12px;
    justify-content: center;
  }
  .invite-rsvp-actions > * { flex: 1 1 0; min-width: 0; }
  .invite-rsvp-actions .btn { flex: 1 1 0; min-width: 0; width: 100%; }
  .invite-rsvp-actions form { display: flex; }
  .invite-rsvp-actions--single > *,
  .invite-rsvp-actions--single .btn { flex: 0 1 auto; width: auto; }
  /* Reply-by stamp — borrows the .todo-due-stamp treatment so the RSVP
     deadline reads as a sibling of the checklist stamps elsewhere.
     Pinned to the top-right of the RSVP block, independent of the
     centered eyebrow / button group. Forest green ink. */
  .invite-deadline-stamp.invite-deadline-stamp {
    position: absolute;
    top: 18px;
    right: 0;
    color: var(--arrive);
    background: transparent;
    margin: 0;
  }
  .invite-deadline-stamp .caption,
  .invite-deadline-stamp .todo-due-stamp-date { color: var(--arrive); }
  /* Declined = soft gray variant of the deadline-stamp position. */
  .invite-deadline-stamp.invite-deadline-stamp--declined,
  .invite-deadline-stamp--declined .caption,
  .invite-deadline-stamp--declined .todo-due-stamp-date { color: var(--ink-faint); }

  .invite-decline-reason {
    margin: 0 0 18px !important;
    font-style: italic;
    color: var(--ink-soft);
    font-size: 14px;
    text-align: center;
  }
  .invite-rsvp-undo {
    margin: 16px 0 0 !important;
    font-size: 13px;
  }

  @media (max-width: 640px) {
    /* Top padding clears the 64px absolutely-positioned .stay-nav (brand
       on the left, avatar pinned top-right) with a comfortable margin so
       the letter card doesn't start under them. */
    .invite-page { padding: 96px 16px 64px; gap: 18px; }
    .invite-letter { padding: 48px 28px 36px; }
    .invite-preview-banner { margin: -48px -28px 22px; padding: 10px 16px; }
    .invite-rsvp-card { padding: 28px 28px 24px; }
    .invite-salutation { font-size: 42px; }
    .invite-headline { font-size: 32px; }
    .invite-shingle { padding: 14px 16px; margin-top: 36px; }
    .invite-shingle-block { padding: 0 16px; }
    .invite-shingle-val { font-size: 18px; }
    .invite-rsvp-actions { flex-direction: column; }
  }

  /* Welcome notice — friendly one-time banner at the top of the
     post-accept welcome page. Reads as a quiet aside, not an alert. */
  .welcome-notice {
    margin: 0 0 4px;
    padding: 14px 18px;
    background: var(--arrive-paper);
    border-left: 3px solid var(--arrive);
    color: var(--ink);
    font-size: 14px;
    line-height: 1.6;
    border-radius: 0 4px 4px 0;
  }
  .welcome-notice strong { font-weight: var(--weight-semibold); }
  .welcome-sent {
    margin: 0 !important;
    padding: 10px 14px;
    background: var(--arrive-paper);
    border: 1px solid var(--arrive-line);
    border-radius: 4px;
    color: var(--arrive);
    font-size: 14px;
  }

  /* Decline screen — small paper card on a desk surface. */
  .decline-page {
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--space-8) var(--space-5);
    background: var(--desk-2);
  }
  .decline-card {
    width: 480px;
    max-width: 100%;
    padding: 64px 60px 52px;
    box-shadow: var(--shadow-paper-deep);
  }

  /* First-timer gate — paper card on desk, single-column profile gate. */
  .gate-page {
    min-height: 100vh;
    background: var(--paper);
    background-image:
      radial-gradient(circle at 20% 30%, rgba(180, 160, 120, 0.06) 0%, transparent 45%),
      radial-gradient(circle at 80% 70%, rgba(180, 160, 120, 0.07) 0%, transparent 50%);
    padding: var(--space-8) var(--space-5);
    display: flex;
    align-items: flex-start;
    justify-content: center;
  }
  .gate-card {
    max-width: 540px;
    width: 100%;
    background: var(--paper);
    padding: 56px 60px 52px;
    box-shadow: var(--shadow-paper);
  }
}
