/* ── Reset ─────────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
button { cursor: pointer; border: none; background: none; font: inherit; }
input, textarea { font: inherit; outline: none; }
a { text-decoration: none; color: inherit; }

/* ── Design tokens ──────────────────────────────────────────────── */
:root {
  --cream:  #F4EFE4;
  --paper:  #FBF7EE;
  --ink:    #2A1F18;
  --mono:   #6B5A4A;
  --ink-soft: #8B7355;
  --rule:   rgba(42,31,24,.13);
  --accent: #E04B2E;   /* UI accent — buttons, links, selection, hero word */
  --logo:   #3E5641;   /* sprig brand mark only (green). On dark surfaces it falls back to cream. */
  --font-d: 'Cormorant Garamond', Georgia, serif;
  --font-s: 'DM Sans', -apple-system, sans-serif;
  --font-e: 'EB Garamond', Georgia, serif;
  --font-m: 'JetBrains Mono', monospace;
}

/* ── Base ───────────────────────────────────────────────────────── */
html { scroll-behavior: smooth; }
body {
  font-family: var(--font-d);
  background: var(--cream);
  color: var(--ink);
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}
.page-wrap { flex: 1 0 auto; }

/* ── Nav ────────────────────────────────────────────────────────── */
.nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 60px;
  border-bottom: 1px solid var(--rule);
  background: var(--cream);
  position: sticky;
  top: 0;
  z-index: 100;
}
/* iOS: as the URL bar collapses/expands, the sticky nav can briefly reveal a sliver
   of scrolled content above its top edge. Extend the nav's background upward to mask
   that peek. Off-screen at rest; only matters during the toolbar transition. */
.nav::before {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: 100%;
  height: 70px;
  background: var(--cream);
}
.nav-left {
  display: flex;
  align-items: center;
  min-width: 0;
  flex: 1;
}
.nav-logo {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
}
.nav-logo-mark { color: var(--logo); line-height: 0; }
.nav-logo-word {
  font-family: var(--font-d);
  font-style: italic;
  font-weight: 500;
  font-size: 30px;
  letter-spacing: -1px;
  line-height: 1;
  color: var(--ink);
}
.nav-hamburger {
  display: none;
  align-items: center;
  justify-content: center;
  color: var(--ink);
  padding: 5px;
  margin-left: 16px;
  border-radius: 5px;
  flex-shrink: 0;
  transition: opacity .15s;
}
.nav-hamburger:hover { opacity: .55; }
.nav-hamburger.signed-out { display: none !important; }

/* Header sign-out (account page) — matches the .nav-link text treatment */
.nav-signout {
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
}
.nav-signout:disabled { opacity: .55; cursor: default; }

/* Hamburger → X morphing animation */
.nav-hamburger svg rect {
  transition: transform .25s ease, opacity .2s ease;
  transform-box: fill-box;
}
/* Each bar rotates around the SVG's vertical centre (y=7 in a 14-tall viewBox) */
.nav-hamburger svg rect:nth-child(1) { transform-origin: 50% 350%;  }
.nav-hamburger svg rect:nth-child(2) { transform-origin: center;    }
.nav-hamburger svg rect:nth-child(3) { transform-origin: 50% -250%; }
.nav-hamburger[aria-expanded="true"] svg rect:nth-child(1) { transform: rotate(45deg);  }
.nav-hamburger[aria-expanded="true"] svg rect:nth-child(2) { opacity: 0; transform: scaleX(0); }
.nav-hamburger[aria-expanded="true"] svg rect:nth-child(3) { transform: rotate(-45deg); }
.nav-sep {
  width: 1px;
  height: 18px;
  background: rgba(42,31,24,.22);
  flex-shrink: 0;
  margin: 0 13px;
  align-self: center;
  position: relative;
  top: 2px;
}
/* h1 semantics, nav styling — reset browser heading defaults */
.nav-occasion-title {
  font-family: var(--font-d);
  font-style: italic;
  font-weight: 400;
  font-size: 21px;
  letter-spacing: -.35px;
  color: var(--ink);
  opacity: .6;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
  margin: 0;
  position: relative;
  top: 2px;
}
.nav-links { display: flex; gap: 32px; align-items: center; flex-shrink: 0; }
.nav-link {
  font-family: var(--font-d);
  font-style: italic;
  font-size: 17px;
  color: var(--ink);
  opacity: .75;
  transition: opacity .15s;
}
.nav-link:hover { opacity: 1; }
.nav-divider { width: 1px; height: 22px; background: var(--rule); }

/* Hamburger drawer (mobile) */
/* Always display:flex (position:absolute so no layout impact);
   visibility/opacity/transform handle show/hide with a smooth transition */
.nav-drawer {
  display: flex;
  flex-direction: column;
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  background: var(--paper);
  border-bottom: 1px solid var(--rule);
  z-index: 99;
  padding: 4px 20px 10px;
  box-shadow: 0 8px 24px rgba(42,31,24,.08);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transform: translateY(-6px);
  transition: opacity .2s ease, transform .2s ease, visibility .2s;
}
.nav-drawer.open {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transform: translateY(0);
}
.nav-drawer-link {
  font-family: var(--font-d);
  font-style: italic;
  font-size: 18px;
  color: var(--ink);
  opacity: .78;
  padding: 11px 0;
  border-bottom: 1px solid var(--rule);
  transition: opacity .15s;
}
.nav-drawer-link:last-child { border-bottom: none; padding-bottom: 4px; }
.nav-drawer-link:hover { opacity: 1; }
button.nav-drawer-link {
  background: none;
  border: none;
  border-bottom: 1px solid var(--rule);
  text-align: left;
  width: 100%;
  cursor: pointer;
}
button.nav-drawer-link:last-child { border-bottom: none; }

@media (max-width: 768px) {
  .nav { padding: 13px 20px; }
  .nav-hamburger { display: flex; }
  .nav-links { display: none; }           /* hide all nav links on mobile */
  .nav-links-acct { display: flex; }      /* …except the account sign-out */
  .nav-logo-word { font-size: 25px; letter-spacing: -.8px; }
  .nav-sep { margin: 0 9px; height: 15px; }
  .nav-occasion-title { font-size: 17px; letter-spacing: -.2px; }
}

/* ── Visually hidden (screen-reader / SEO only) ─────────────────── */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0,0,0,0);
  white-space: nowrap;
  border: 0;
}

/* ── Step indicator ─────────────────────────────────────────────── */
.step-indicator {
  padding: 16px 60px 0;
  background: var(--cream);
  display: none;
}
.step-indicator.visible { display: block !important; }
.step-indicator-inner {
  background: var(--paper);
  border-radius: 14px;
  padding: 14px 18px;
  border: 1px solid var(--rule);
  display: flex;
  align-items: center;
  gap: 14px;
}
.step-node {
  display: flex;
  align-items: center;
  gap: 10px;
  flex: 0 0 auto;
}
.step-bubble {
  width: 24px;
  height: 24px;
  border-radius: 12px;
  background: transparent;
  border: 1.5px solid rgba(107,90,74,.35);
  color: var(--mono);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-m);
  font-size: 11px;
  font-weight: 600;
  flex-shrink: 0;
  transition: all .2s;
}
.step-bubble.active { background: var(--accent); border-color: var(--accent); color: var(--paper); }
.step-bubble.done   { background: var(--ink);   border-color: var(--ink);   color: var(--paper); }
.step-meta { opacity: .45; transition: opacity .2s; text-align: left; }
.step-meta.active, .step-meta.done { opacity: 1; }
.step-label {
  font-family: var(--font-m);
  font-size: 9px;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--mono);
  line-height: 1;
}
.step-value {
  font-style: italic;
  font-size: 16px;
  line-height: 1.2;
  margin-top: 2px;
  max-width: 160px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.step-connector { flex: 1; height: 1px; background: var(--rule); min-width: 8px; }
.step-node-back { transition: opacity .15s; }
.step-node-back:hover { opacity: .65; }
/* Locked completed steps (after the first card's link is generated): visible but
   not interactive — no back-navigation into the dead-end edit steps. */
.step-node-back.is-locked { cursor: default; }
.step-node-back.is-locked:hover { opacity: 1; }

/* Responsive step labels */
.sl-short { display: none; }
@media (max-width: 768px) {
  .step-indicator { padding: 10px 20px 0; }
  .step-node:not(.active-node) .step-meta { display: none; }
  .step-connector { min-width: 4px; }
  .sl-full  { display: none; }
  .sl-short { display: inline; }
}

/* ── Steps ──────────────────────────────────────────────────────── */
.step { display: none; }
.step.active { display: block; }

/* ── Step 1 ─────────────────────────────────────────────────────── */
.hero {
  padding: 24px 60px 8px;
  text-align: center;
}
.hero-eyebrow {
  display: block;
  margin-bottom: 28px;
}
.hero-eyebrow-text {
  font-family: var(--font-m);
  font-size: 13px;
  letter-spacing: 2.4px;
  text-transform: uppercase;
  color: var(--ink);
  opacity: .88;
}
/* On small phones, scale the eyebrow down so it never breaks to a second line */
@media (max-width: 480px) {
  .hero-eyebrow-text {
    font-size: clamp(8.5px, 3vw, 12px);
    letter-spacing: 1.4px;
    white-space: nowrap;
  }
}
.hero-headline {
  font-size: clamp(46px, 7vw, 102px);
  line-height: .92;
  letter-spacing: clamp(-2px, -.35vw, -3.8px);
  font-weight: 500;
  font-style: italic;
}
.hero-headline .accent { color: var(--accent); }
.hero-tagline {
  font-family: var(--font-m);
  font-size: 11px;
  letter-spacing: 2.2px;
  text-transform: uppercase;
  color: var(--mono);
  opacity: .6;
  margin-top: 14px;
}
.hero-sub {
  font-style: italic;
  font-size: 20px;
  color: var(--ink);
  opacity: .78;
  margin-top: 12px;
  line-height: 1.4;
  max-width: 600px;
  margin-left: auto;
  margin-right: auto;
}
.mono-tag {
  font-family: var(--font-m);
  font-size: 9px;
  letter-spacing: 1.6px;
  text-transform: uppercase;
  color: var(--mono);
}

/* ── Home preview cards ─────────────────────────────────────────── */
@keyframes previewFadeIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}
/* ── Occasion grid (Step 1) ─────────────────────────────────────── */
.occasions-label {
  font-style: italic;
  font-size: clamp(20px, 2.8vw, 32px);
  letter-spacing: -.5px;
  text-align: center;
  margin-bottom: 18px;
}
.occasions-label .accent { color: var(--accent); }

/* ── Sitegeist stamp (home hero) ────────────────────────────────── */
/* A slowly spinning seal with the all-time opens count, linking to
   /sitegeist. Absolutely placed beside the headline on desktop; on phones
   there's no room, so it drops into the flow below the headline. */
.hero--home { position: relative; }
.sg-stamp {
  position: absolute; right: max(4vw, 24px); top: 36px;
  width: 132px; height: 132px;
  color: var(--accent); text-decoration: none;
  transform: rotate(-10deg);
}
.sg-stamp-ring { position: absolute; inset: 0; animation: sgStampSpin 28s linear infinite; }
@keyframes sgStampSpin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .sg-stamp-ring { animation: none; } }
/* No inner circle: the number floats inside the ring text, matching the
   phone nav stamp. */
.sg-stamp-core {
  position: absolute; inset: 20px; border-radius: 50%;
  display: grid; place-items: center; text-align: center;
}
/* "10.4K+" in DM Sans, all one size (the serif with a smaller K+ read as
   three different sizes). */
.sg-stamp-num {
  display: flex; align-items: baseline; justify-content: center;
  font: 600 24px/1 var(--font-s); letter-spacing: -.6px; color: var(--accent);
  font-variant-numeric: lining-nums tabular-nums; font-feature-settings: "lnum" 1, "tnum" 1;
}
/* Wide screens: hug the headline instead of drifting to the window edge. */
@media (min-width: 1100px) { .sg-stamp { right: calc(50% - 500px); top: 48px; } }
@media (max-width: 900px) {
  .sg-stamp { width: 112px; height: 112px; right: 16px; }
  .sg-stamp-core { inset: 18px; }
  .sg-stamp-num { font-size: 20px; }
}
/* Phones: a 40px stamp beside the headline's first line, in the same spot
   as on desktop (the full-size one was too much on a small screen). It uses
   shorter ring text so the letters stay legible at this size. */
.sg-stamp-mini { display: none; }
@media (max-width: 600px) {
  .sg-stamp { display: none; }
  .sg-stamp-mini {
    display: block; position: absolute; top: 54px; right: 14px;
    width: 40px; height: 40px;
    color: var(--accent); text-decoration: none; transform: rotate(-10deg);
  }
  .sg-stamp-mini .sg-stamp-ring { position: absolute; inset: 0; }
  .sg-stamp-mini .sg-stamp-num {
    /* wrap + align-content centres the line vertically while the number and
       the smaller "K+" stay baseline-aligned. */
    position: absolute; inset: 0; flex-wrap: wrap; align-content: center;
    font-size: 8.4px; letter-spacing: -.3px;
  }
}
/* Narrow phones: the headline runs closer to the edge, so tuck it in. */
@media (max-width: 360px) {
  .sg-stamp-mini { width: 34px; height: 34px; right: 4px; top: 52px; }
  .sg-stamp-mini .sg-stamp-num { font-size: 7.2px; }
}
.occasions-wrap { padding: 20px 60px 32px; }
.occasions-grid {
  display: flex;
  flex-direction: column;
  gap: 26px;                 /* clear break between the two occasion groups */
  max-width: 740px;
  margin: 0 auto;
}
/* Each group is its own centered four-up row on desktop. */
.occasion-group {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 12px;
}
.occasions-grid .occasion-group .occasion-tile { flex: 0 1 calc(25% - 10px); }
/* Mobile: one continuous 2-up grid in document order, so each row pairs
   consecutive occasions (not the Nth item of each group side by side). */
@media (max-width: 600px) {
  .occasions-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 12px;
  }
  .occasions-grid .occasion-group {
    display: contents;
  }
  .occasions-grid .occasion-group .occasion-tile { width: 100%; }
}
a.occasion-tile { text-decoration: none; color: inherit; }
.occasion-tile {
  background: var(--paper);
  border-radius: 16px;
  padding: 16px 12px;
  border: 1px solid var(--rule);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  cursor: pointer;
  position: relative;
  min-height: 108px;
  min-width: 0;
  justify-content: center;
  transition: all .18s ease;
  -webkit-tap-highlight-color: transparent;
}
.occasion-tile:hover { transform: translateY(-3px); box-shadow: 0 8px 22px rgba(0,0,0,.09); }
.occasion-tile.selected { border-color: transparent; }
.occasion-tile-label {
  font-style: italic;
  font-size: 18px;
  letter-spacing: -.3px;
  line-height: 1.1;
  text-align: center;
  overflow-wrap: break-word;
}
/* Fixed icon row so a taller illustration (Coupon is drawn at 48px vs 42px for the
   rest) can't make its tile taller than the others — bigger icons just overflow the
   row visually. Keeps every occasion tile the same height, side by side on mobile. */
.occ-tile-icon {
  height: 42px;
  display: flex;
  align-items: center;
  justify-content: center;
}
/* Passed Note: 20% larger and nudged down a touch. Other icons sit as drawn. */
.occasion-tile .occ-tile-icon--pn { transform: translateY(6px) scale(1.2); }
/* Featured seasonal occasion (e.g. Halloween in October): a big tile that, on
   desktop, sits to the left of BOTH occasion rows (spanning them), so the two
   rows stretch wider instead of wrapping into a third. Styled like any tile. */
.occasions-grid:has(> .occasion-tile--feature) {
  display: grid;
  grid-template-columns: 2fr 4fr;
  gap: 12px;               /* rows sit as close as tiles do (not the usual 26px) */
  max-width: 1120px;
}
.occasions-grid > .occasion-tile--feature { grid-row: 1 / span 2; }
.occasion-tile--feature { gap: 8px; min-height: 228px; }
.occasion-tile--feature .occasion-tile-label { font-size: 32px; letter-spacing: -.6px; }
.occ-feature-art { line-height: 0; }
.occ-feature-kicker {
  font-family: var(--font-m);
  font-size: 9px;
  letter-spacing: 2.4px;
  text-transform: uppercase;
  color: var(--mono);
  margin-top: 6px;
}
/* Home grid tiles keep their original height (min-height 108px) but are only
   as wide as the longest label needs (~98px + padding), so they sit close to
   square. Groups stay centred; the featured tile is exactly two tiles wide. */
.occasions-grid { --occ-tile-w: 132px; }
.occasions-grid .occasion-group .occasion-tile { flex: 0 0 var(--occ-tile-w); }
.occasions-grid:has(> .occasion-tile--feature) { grid-template-columns: auto auto; justify-content: center; }
.occasions-grid > .occasion-tile--feature { width: calc(var(--occ-tile-w) * 2 + 12px); }
@media (max-width: 900px) {
  /* Stacked: the featured tile matches the width of a row of four below it. */
  .occasions-grid > .occasion-tile--feature { width: calc(var(--occ-tile-w) * 4 + 36px); align-self: center; }
}
@media (max-width: 600px) {
  /* Phones keep the original two-up grid. */
  .occasions-grid .occasion-group .occasion-tile { flex: none; }
  .occasions-grid > .occasion-tile--feature { width: auto; align-self: auto; }
}
/* Narrower screens: the featured tile goes full width above the rows. */
@media (max-width: 900px) {
  .occasions-grid:has(> .occasion-tile--feature) { display: flex; max-width: 740px; gap: 12px; }
  .occasion-tile--feature { min-height: 200px; }
}
/* In the New-card picker it's just a wider tile at the top. */
.occ-modal-grid > .occasion-tile--feature { min-height: 168px; }
@media (max-width: 600px) {
  .occasions-grid:has(> .occasion-tile--feature) { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
  .occasion-tile--feature { grid-column: 1 / -1; }
}
@media (max-width: 900px) {
  .occasions-wrap { padding: 20px 20px 56px; }
}
@media (max-width: 768px) {
  .hero { padding: 28px 20px 16px; }
  .occasions-wrap { padding: 16px 20px 48px; }
  .hero-eyebrow { margin-bottom: 32px; }
}

/* ── New-card occasion modal ─────────────────────────────────────── */
.occ-modal {
  position: fixed;
  inset: 0;
  z-index: 320;
  display: none;          /* JS toggles to flex */
  align-items: center;
  justify-content: center;
  padding: 24px;
}
.occ-modal-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(26,20,16,.55);
  -webkit-backdrop-filter: blur(2px);
  backdrop-filter: blur(2px);
}
.occ-modal-card {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 700px;
  max-height: 86vh;
  max-height: 86dvh;
  overflow-y: auto;
  background: var(--cream);
  border-radius: 20px;
  padding: 32px 28px 34px;
  box-shadow: 0 24px 70px rgba(26,20,16,.32);
  animation: occModalIn .26s cubic-bezier(.2,.7,.3,1);
}
@keyframes occModalIn {
  from { opacity: 0; transform: translateY(12px) scale(.98); }
  to   { opacity: 1; transform: none; }
}
.occ-modal-close {
  position: absolute;
  top: 12px;
  right: 16px;
  background: none;
  border: none;
  font-size: 26px;
  line-height: 1;
  color: var(--mono);
  cursor: pointer;
  padding: 4px 8px;
  transition: color .15s;
}
.occ-modal-close:hover { color: var(--ink); }
.occ-modal-title {
  font-family: 'Cormorant Garamond', Georgia, serif;
  font-style: italic;
  font-size: clamp(22px, 4vw, 30px);
  letter-spacing: -.5px;
  text-align: center;
  margin: 0 0 22px;
  color: var(--ink);
}
/* Four-up per row on desktop, matching the home grid. Flex-wrap (not grid)
   so a partial last row stays centered if a group's count isn't a multiple
   of 4. */
.occ-modal-grid {
  display: flex;
  flex-direction: column;
  gap: 12px;                 /* same as the gap between tiles in a row */
}
.occ-modal-grid .occasion-group .occasion-tile { flex: 0 1 calc(25% - 10px); }
/* Mobile: same continuous 2-up grid as the home grid — see note there. */
@media (max-width: 600px) {
  .occ-modal-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 12px;
  }
  .occ-modal-grid .occasion-group {
    display: contents;
  }
  .occ-modal-grid .occasion-group .occasion-tile { width: 100%; }
}


/* ── Gallery controls ───────────────────────────────────────────────── */

/* Outer sticky wrapper */
.gallery-controls {
  padding: 16px 60px;
  background: var(--cream);
  border-bottom: 1px solid var(--rule);
  position: sticky;
  top: 63px;
  /* Above the gallery sections (whose scaled card previews get promoted to their
     own compositing layers on iOS and would otherwise paint over a low z-index),
     but below the nav (100) and the mobile drawer (99). */
  z-index: 90;
}

/* Rounded box — two sections: names | colors */
.gallery-controls-inner {
  background: var(--paper);
  border-radius: 14px;
  border: 1px solid var(--rule);
  display: flex;
  align-items: center;
  overflow: hidden;
  max-width: 740px;
}

/* Left section: For / From inputs — takes whatever the swatches leave */
.gc-fields {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 1 1 auto;
  padding: 10px 16px;
  min-width: 0;
}

/* Short centred hairline between fields and swatches */
.gc-sep {
  width: 1px;
  height: 20px;
  background: var(--rule);
  flex-shrink: 0;
}

.gc-label {
  font-family: var(--font-m);
  font-size: 9px;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--mono);
  flex-shrink: 0;
}

.gc-input {
  flex: 1;
  min-width: 50px;
  background: var(--cream);
  border: 1px solid rgba(107,90,74,.3);
  border-radius: 8px;
  padding: 7px 10px;
  font-family: var(--font-d);
  font-style: italic;
  font-size: 16px;
  color: var(--ink);
  transition: border-color .15s;
}
.gc-input::placeholder { opacity: .6; }
.gc-input:focus { border-color: var(--accent); outline: none; }

/* Right section: color swatches — sized to fit every swatch (Passed Notes
   adds a notebook swatch to the palette, so the count varies by page). */
.gc-swatches {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  padding: 10px 12px;
  min-width: 0;
}

.gallery-swatches {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  /* The selected ring reaches 3px past the circle (1.5px outline + 1.5px
     offset); a 7px minimum gap keeps it clear of the neighbours. */
  gap: 7px;
  padding: 0;
}
.gallery-swatch {
  width: 17px; height: 17px; border-radius: 50%;
  cursor: pointer;
  border: 2px solid transparent;
  outline: 1.5px solid transparent;
  outline-offset: 1.5px;
  transition: all .15s;
  flex-shrink: 0;
}
.gallery-swatch.sel { border-color: white; outline-color: var(--ink); }
.gallery-swatch:hover { transform: scale(1.12); }

.gallery-toggle {
  padding: 7px 14px;
  border-radius: 100px;
  border: 1.5px solid var(--rule);
  font-family: var(--font-m);
  font-size: 9px;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  cursor: pointer;
  transition: all .15s;
  color: var(--mono);
  background: transparent;
  margin-top: auto;
}
.gallery-toggle.on { background: var(--ink); border-color: var(--ink); color: var(--paper); }

.gallery-section { padding: 24px 60px 0; }
.gallery-section-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  margin-bottom: 20px;
  padding-bottom: 16px;
  border-bottom: 1px solid var(--rule);
}
.gallery-theme-title { font-style: italic; font-size: 26px; letter-spacing: -.5px; line-height: 1; }
.gallery-theme-desc { font-family: var(--font-s); font-size: 12px; color: var(--mono); margin-top: 5px; }
.gallery-count { font-family: var(--font-m); font-size: 9px; letter-spacing: 1.4px; text-transform: uppercase; color: var(--mono); opacity: .5; }

.gallery-grid {
  display: flex;
  overflow-x: auto;
  gap: 16px;
  /* Extra left padding so the first card's hover shadow sits INSIDE the
     scroll container's padding box (otherwise overflow clipping slices it
     off abruptly). The negative margin pulls the grid back so cards keep
     their original visual position. */
  padding: 16px 8px 28px 40px;
  margin-left: -28px;
  scroll-snap-type: x proximity;
  scroll-padding-left: 40px;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
  scrollbar-color: rgba(42,31,24,.15) transparent;
}
.gallery-grid::-webkit-scrollbar { height: 3px; }
.gallery-grid::-webkit-scrollbar-track { background: transparent; }
.gallery-grid::-webkit-scrollbar-thumb { background: rgba(42,31,24,.15); border-radius: 2px; }
.gallery-card-item {
  /*
   * Use 100vw (reliable) instead of 100% (broken inside overflow:auto flex).
   * Desktop: section=60px×2, grid-pad=8px×2, gaps=4×16px → (100vw−200px)/4.25
   * Shows 4 full cards + 25% peek of the 5th.
   */
  flex: 0 0 auto;
  width: calc((100vw - 200px) / 4.25);
  scroll-snap-align: start;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  gap: 10px;
  -webkit-tap-highlight-color: transparent;
}
.gallery-card-inner {
  position: relative;
  aspect-ratio: 5 / 7;
  border-radius: 6px;
  overflow: hidden;
  box-shadow: 0 2px 8px rgba(0,0,0,.07), 0 6px 20px rgba(0,0,0,.09);
  transition: box-shadow .2s ease;
}
.gallery-card-scaler,
.preview-card-scaler,
.edit-preview-scaler {
  display: block;
  width: 320px;
  height: 448px;
}
.gallery-card-frame {
  border-radius: 6px;
  transition: transform .2s ease;
  /* No overflow:hidden — keeps this element out of GPU compositing so
     the selection outline is never clipped at the element boundary */
}
.gallery-card-item:hover .gallery-card-frame {
  transform: translateY(-4px);
}
.gallery-card-item:hover .gallery-card-inner {
  box-shadow: 0 6px 16px rgba(0,0,0,.1), 0 18px 40px rgba(0,0,0,.14);
}
.gallery-card-item.sel .gallery-card-frame {
  outline: 2.5px solid var(--ink);
  outline-offset: 3px;
}
.gallery-card-item.sel .gallery-card-inner {
  box-shadow: 0 8px 28px rgba(0,0,0,.22);
}
.gallery-card-meta { display: flex; justify-content: space-between; align-items: baseline; }
.gallery-card-name { font-style: italic; font-size: 14px; color: var(--ink); }
.gallery-card-id {
  font-family: var(--font-m);
  font-size: 9px;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--mono);
  opacity: .5;
}
.gallery-footer { display: flex; align-items: center; gap: 16px; padding: 36px 60px 64px; }

@media (max-width: 900px) {
  /* top must equal the mobile nav height (26px mark + 13px×2 padding + 1px border
     = 53px) so the bar pins flush to the nav — otherwise a gap lets gallery
     content peek through while scrolling. */
  .gallery-controls { padding: 10px 20px; top: 53px; }
  .gc-fields { padding: 9px 12px; gap: 7px; }
  .gc-swatches { padding: 9px 10px; }
  .gc-input { font-size: 15px; padding: 5px 8px; }
  .gallery-section { padding: 20px 20px 0; }
  .gallery-footer { padding: 28px 20px 48px; }
  /* Mobile: section=20px×2, grid-pad=8px×2, gaps=2×16px → (100vw−88px)/2.25 */
  /* Shows 2 full cards + 25% peek of the 3rd. */
  .gallery-card-item { width: calc((100vw - 88px) / 2.25); }
  /* Less room here (section padding is only 20px), so use a gentler offset. */
  .gallery-grid { padding-left: 28px; margin-left: -16px; scroll-padding-left: 28px; }
}

/* Pinned Next FAB */
.gallery-next-fab {
  position: fixed;
  bottom: 28px;
  right: 28px;
  z-index: 200;
  display: none;
  align-items: center;
  gap: 10px;
  padding: 14px 22px;
  border-radius: 100px;
  border: none;
  background: var(--ink);
  color: var(--paper);
  font-family: var(--font-d);
  font-style: italic;
  font-size: 19px;
  font-weight: 500;
  cursor: default;
  pointer-events: none;
  opacity: 0;
  box-shadow: 0 4px 20px rgba(0,0,0,.3);
  transition: background .25s ease, box-shadow .25s ease, opacity .25s ease;
}
.gallery-next-fab.ready {
  background: var(--accent);
  opacity: 1;
  pointer-events: auto;
  cursor: pointer;
  box-shadow: 0 6px 28px color-mix(in srgb, var(--accent) 45%, transparent);
}
.gallery-next-fab.ready:hover {
  transform: translateY(-2px);
  box-shadow: 0 10px 32px color-mix(in srgb, var(--accent) 55%, transparent);
}
@media (max-width: 640px) {
  .gallery-text-input { font-size: 16px; }
  /* Stack fields over swatches on narrow viewports */
  .gallery-controls-inner { flex-direction: column; align-items: stretch; }
  .gc-sep { display: none; }
  .gc-fields { flex: none; border-bottom: 1px solid var(--rule); }
  .gc-swatches { flex: none; }
  .gallery-swatch { width: 16px; height: 16px; }
}
/* Reduce swatch size at intermediate widths — prevents squeezing in side-by-side layout */
@media (max-width: 900px) and (min-width: 641px) {
  .gallery-swatch { width: 15px; height: 15px; }
}
/* Narrow phones: 13 swatches (Passed Notes) need a size step to fit one row. */
@media (max-width: 380px) {
  .gallery-swatch { width: 14px; height: 14px; }
  .gallery-swatches { gap: 6px; }
}

.btn-primary {
  padding: 14px 26px;
  border-radius: 100px;
  background: var(--accent);
  color: var(--paper);
  font-family: var(--font-d);
  font-style: italic;
  font-size: 19px;
  font-weight: 500;
  line-height: 1;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  box-shadow: 0 8px 22px color-mix(in srgb, var(--accent) 25%, transparent);
  transition: all .15s ease;
  flex-shrink: 0;
}
.btn-primary:hover { transform: translateY(-1px); box-shadow: 0 12px 28px color-mix(in srgb, var(--accent) 30%, transparent); }
.btn-primary:active { transform: scale(.97); }
.btn-arrow { flex-shrink: 0; }
@media (max-width: 768px) {
  .name-section { padding: 16px 20px 40px; }
  .name-card { gap: 16px; }
}

/* ── Step 3: Edit ───────────────────────────────────────────────── */
.step-section { padding: 20px 60px 60px; }
.step-headline {
  font-size: clamp(32px, 4vw, 56px);
  font-style: italic;
  letter-spacing: -1.8px;
  line-height: .95;
  margin-top: 10px;
  margin-bottom: 12px;
}
.step-sub { font-style: italic; font-size: 16px; color: var(--mono); line-height: 1.4; max-width: 600px; }
.step-footer {
  margin-top: 32px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
}
.step-footer-right {
  display: flex;
  align-items: center;
  gap: 12px;
}
.btn-ghost {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  /* top-heavy padding nudges the italic label to its optical centre (it otherwise
     rides high because the font reserves descender space the word doesn't use) */
  padding: 13px 20px 9px;
  border-radius: 100px;
  border: 1.5px solid rgba(107,90,74,.28);
  font-family: var(--font-d);
  font-style: italic;
  font-size: 16px;
  line-height: 1;
  color: var(--mono);
  background: var(--paper);
  cursor: pointer;
  transition: border-color .15s, color .15s;
  flex-shrink: 0;
}
.btn-ghost:hover { border-color: var(--ink); color: var(--ink); }
/* Thin left chevron (lighter counterpart to the bold forward arrow); the
   small counter-translate keeps it centred against the label's optical nudge. */
.btn-ghost-arrow { transform: translateY(-1px); }
.step-footer .btn-ghost,
.gallery-footer .btn-ghost { padding: 16px 20px 12px; font-size: 18px; }
@media (max-width: 768px) {
  .step-section { padding: 16px 20px 40px; }
  .step-headline { font-size: 32px; letter-spacing: -1.2px; }
}

/* ── Step 3: Edit (layout) ──────────────────────────────────────── */
.edit-layout {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 60px;
  align-items: flex-start;
  margin-top: 32px;
}
.edit-preview-wrap {
  display: flex;
  justify-content: center;
  padding-top: 12px;
}
.edit-preview-card {
  width: min(78%, calc(52vh * 5/7));
  aspect-ratio: 5 / 7;
  border-radius: 4px;
  overflow: hidden;
  box-shadow: 0 4px 12px rgba(0,0,0,.08), 0 30px 60px rgba(0,0,0,.18);
}
.edit-panel {}
.edit-fields-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
}
.edit-field { display: flex; flex-direction: column; gap: 6px; }
.edit-field-label {
  font-family: var(--font-m);
  font-size: 9px;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--mono);
}
.edit-field-input {
  width: 100%;
  background: var(--paper);
  border: 1.5px solid var(--rule);
  border-radius: 10px;
  padding: 10px 14px;
  font-family: var(--font-d);
  font-style: italic;
  font-size: 17px;
  color: var(--ink);
  transition: border-color .15s;
}
.edit-field-input:focus { border-color: var(--ink); outline: none; }
.edit-field-input.error { border-color: var(--accent); }
.edit-msg-header {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-bottom: 10px;
}
.char-count { font-family: var(--font-m); font-size: 10px; letter-spacing: 1.4px; text-transform: uppercase; color: var(--mono); }
.edit-textarea {
  width: 100%;
  background: var(--paper);
  border: 1.5px solid var(--rule);
  border-radius: 14px;
  padding: 18px 22px;
  font-size: 18px;
  font-style: italic;
  color: var(--ink);
  line-height: 1.45;
  resize: none;
  min-height: 120px;
  display: block;
  caret-color: var(--accent);
  transition: border-color .15s;
}
.edit-textarea:focus { border-color: var(--ink); }
.edit-textarea.error { border-color: var(--accent); }
.chips {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  margin-top: 16px;
}
.chip {
  padding: 8px 14px;
  border-radius: 100px;
  background: var(--paper);
  border: 1px solid var(--rule);
  font-style: italic;
  font-size: 14px;
  color: var(--ink);
  cursor: pointer;
  transition: all .15s;
}
.chip:hover { background: var(--ink); color: var(--paper); border-color: var(--ink); }
.chip.active { background: var(--ink); color: var(--paper); border-color: var(--ink); }
.sign-row {
  margin-top: 24px;
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: 14px;
  padding: 16px 20px;
  display: flex;
  align-items: center;
  gap: 14px;
}
.sign-label { font-family: var(--font-m); font-size: 9px; letter-spacing: 1.6px; text-transform: uppercase; color: var(--mono); flex-shrink: 0; }
.sign-input {
  font-size: 22px;
  font-style: italic;
  letter-spacing: -.5px;
  color: var(--ink);
  background: none;
  border: none;
  flex: 1;
}
@media (max-width: 900px) {
  .edit-layout { grid-template-columns: 1fr; gap: 16px; margin-top: 20px; }
  .edit-preview-wrap { padding-top: 0; min-width: 0; }
  .edit-panel { min-width: 0; }
  .edit-preview-card { width: min(42%, 180px); }
  .edit-textarea {
    height: clamp(120px, calc(100dvh - 570px), 200px);
    min-height: unset;
    overflow-y: auto;
  }
}

/* ── Step 5: Send ───────────────────────────────────────────────── */
.send-layout {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  gap: 0;
  align-items: stretch;
}
.send-option {
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: 18px;
  padding: 28px;
  display: flex;
  flex-direction: column;
  gap: 18px;
}
.send-or {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 28px;
  font-style: italic;
  font-size: 20px;
  color: var(--mono);
}
.send-option-num { font-family: var(--font-m); font-size: 9px; letter-spacing: 1.6px; text-transform: uppercase; color: var(--mono); }
.send-option-title { font-style: italic; font-size: 28px; letter-spacing: -.8px; line-height: 1.05; }
.send-option-desc { font-style: italic; font-size: 15px; color: var(--mono); line-height: 1.4; }
.phone-input-wrap {
  background: var(--cream);
  border: 1.5px solid var(--rule);
  border-radius: 12px;
  padding: 14px 18px;
  display: flex;
  align-items: center;
  gap: 10px;
}
.phone-flag { font-size: 18px; }
.phone-input {
  font-size: 18px;
  font-style: italic;
  color: var(--ink);
  background: none;
  border: none;
  flex: 1;
  caret-color: var(--accent);
}
.phone-input::placeholder { opacity: .4; }
.btn-send {
  padding: 15px 28px;
  border-radius: 100px;
  background: var(--accent);
  color: var(--paper);
  font-style: italic;
  font-size: 19px;
  font-weight: 500;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  box-shadow: 0 8px 22px color-mix(in srgb, var(--accent) 25%, transparent);
  transition: all .15s;
  width: 100%;
  margin-top: 4px;
}
.btn-send:hover { transform: translateY(-1px); }
.btn-send:active { transform: scale(.97); }
.btn-send:disabled { opacity: .55; cursor: not-allowed; transform: none; }
.link-box {
  background: var(--cream);
  border: 1.5px solid var(--rule);
  border-radius: 12px;
  padding: 14px 18px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.link-text { font-family: var(--font-m); font-size: 12px; letter-spacing: .5px; color: var(--mono); flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.btn-copy {
  padding: 8px 16px;
  border-radius: 8px;
  background: var(--accent);
  color: var(--paper);
  font-style: italic;
  font-size: 14px;
  flex-shrink: 0;
  transition: all .15s;
}
.btn-copy:hover { opacity: .85; }
/* Share options are plain icon+text links (not buttons) so they sit quietly
   under the link box instead of competing with the primary actions. */
.share-btns { display: flex; justify-content: flex-start; gap: 26px; flex-wrap: wrap; }
.share-btn {
  /* Emoji fonts first so the ✉ / 💬 icons render in their color form; latin
     labels aren't in the emoji fonts, so they fall through to the serif. */
  font-family: 'Apple Color Emoji', 'Segoe UI Emoji', 'Noto Color Emoji', var(--font-d, 'Cormorant Garamond'), Georgia, serif;
  font-style: normal;
  font-size: 18px;
  color: var(--ink);
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  transition: color .15s;
}
.share-ic { font-style: normal; display: inline-flex; align-items: center; }
.share-btn:hover { color: var(--accent); }
@media (max-width: 480px) {
  .share-btns { gap: 22px; }
  .share-btn { font-size: 17px; gap: 7px; }
}
@media (max-width: 900px) {
  .send-layout { grid-template-columns: 1fr; }
  .send-or { padding: 16px 0; font-size: 16px; border-top: 1px solid var(--rule); border-bottom: 1px solid var(--rule); margin: 4px 0; }
}

/* ── Auth / Get-link step ───────────────────────────────────────── */
.auth-preamble {
  font-size: 18px;
  color: var(--mono);
  margin: 10px 0 0;
  line-height: 1.45;
}
.auth-perks {
  list-style: none;
  padding: 0;
  margin: 18px 0 0;
  display: flex;
  flex-direction: column;
  gap: 9px;
}
.auth-perks li {
  font-size: 18px;
  color: var(--ink);
  display: flex;
  align-items: baseline;
  gap: 10px;
}
.auth-perks li::before {
  content: '•';
  font-size: 18px;
  line-height: 1;
  color: var(--accent);
  flex-shrink: 0;
}
.auth-legal {
  font-size: 12px;
  color: var(--mono);
  line-height: 1.4;
  margin: 12px 0 0;
  text-align: center;
}
.auth-legal a {
  color: var(--mono);
  text-decoration: underline;
}
.auth-sub {
  font-style: italic;
  font-size: 15px;
  color: var(--mono);
  line-height: 1.4;
  margin-top: 16px;
}
.auth-lead {
  font-size: 18px;
  color: var(--ink);
  line-height: 1.5;
  margin: 22px 0 0;
}
.auth-form {
  display: flex;
  flex-direction: column;
  gap: 14px;
  margin-top: 28px;
  max-width: 480px;
}
.auth-field {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.auth-label {
  font-family: var(--font-m);
  font-size: 10px;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--mono);
}
.auth-input {
  background: var(--paper);   /* distinct from the cream page bg (matches .edit-textarea) */
  border: 1.5px solid var(--rule);
  border-radius: 12px;
  padding: 15px 18px;
  font-size: 19px;
  font-style: italic;
  color: var(--ink);
  width: 100%;
  box-sizing: border-box;
  transition: border-color .15s;
  caret-color: var(--accent);
  font-variant-numeric: tabular-nums;
}
.auth-input:focus { outline: none; border-color: var(--accent); }
.auth-input::placeholder { color: var(--ink); opacity: .35; }
/* If a browser still auto-links a phone/email in a confirmation line, keep it
   looking like plain text (no blue underline). */
.auth-dest a { color: inherit; text-decoration: none; }
/* Responsive label utilities — e.g. "Save changes" on desktop, "Save" on mobile. */
.mobile-only { display: none; }
@media (max-width: 480px) {
  .mobile-hide { display: none; }
  .mobile-only { display: inline; }
}
.auth-code-input {
  font-family: var(--font-s);
  font-style: normal;
  font-weight: 600;
  font-size: 30px;
  letter-spacing: 10px;
  text-indent: 10px; /* balance trailing letter-spacing so digits sit centered */
  text-align: center;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}
.auth-code-input::placeholder {
  font-weight: 500;
  opacity: .28;
}
.auth-error {
  font-style: italic;
  font-size: 14px;
  color: var(--accent);
  margin: -4px 0 0;
}
.auth-returning-banner {
  background: color-mix(in srgb, var(--accent) 8%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 20%, transparent);
  border-radius: 10px;
  padding: 12px 16px;
  font-style: italic;
  font-size: 15px;
  color: var(--ink);
}
.auth-switch {
  font-size: 18px;
  color: var(--mono);
  margin: 10px 0 0;
}
.auth-switch-btn {
  background: none;
  border: none;
  padding: 0 0 0 4px;
  font-family: var(--font-d);
  font-style: italic;
  font-size: 18px;
  color: var(--accent);
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 3px;
}
.auth-switch-btn:hover { opacity: .8; }

.auth-resend-btn {
  background: none;
  border: none;
  padding: 4px 0;
  font-family: var(--font-d);
  font-style: italic;
  font-size: 14px;
  color: var(--mono);
  cursor: pointer;
  text-decoration: underline;
  text-decoration-color: transparent;
  text-underline-offset: 3px;
  transition: color .15s, text-decoration-color .15s;
  align-self: center;
  margin-top: 2px;
}
.auth-resend-btn:hover {
  color: var(--ink);
  text-decoration-color: currentColor;
}
.auth-resend-btn:disabled {
  opacity: .45;
  cursor: default;
  text-decoration-color: transparent;
}
/* Reframed "didn't get it?" helper — check the destination, then resend / edit */
.auth-resend-help {
  font-family: var(--font-d);
  font-style: italic;
  font-size: 14.5px;
  line-height: 1.5;
  color: var(--mono);
  text-align: center;
  margin: 4px 0 0;
}
.auth-link-btn {
  background: none;
  border: none;
  padding: 0;
  font-family: var(--font-d);
  font-style: italic;
  font-size: 14.5px;
  color: var(--accent);
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-color: color-mix(in srgb, var(--accent) 45%, transparent);
  transition: text-decoration-color .15s, opacity .15s;
}
.auth-link-btn:hover { text-decoration-color: currentColor; }
.auth-link-btn:disabled { opacity: .45; cursor: default; text-decoration-color: transparent; }
.auth-dest {
  font-style: normal;
  font-weight: 600;
  color: var(--ink);
  white-space: nowrap;
}
.auth-link-wrap {
  margin-top: 28px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  max-width: 480px;
}
.auth-tracking-note {
  font-style: italic;
  font-size: 17px;
  color: var(--mono);
  margin-top: 16px;
  margin-bottom: 34px;
  line-height: 1.45;
}
.auth-tracking-link {
  color: var(--ink);
  font-weight: 500;
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-color: color-mix(in srgb, var(--ink) 38%, transparent);
  transition: text-decoration-color .15s;
}
/* ── Tip jar (get-link screens) ──────────────────────────────────────── */
.tip-module { margin-top: 34px; padding-top: 26px; border-top: 1px solid var(--rule); max-width: 480px; }
.tip-line { font-size: 17px; line-height: 1.5; color: var(--ink); margin: 0 0 16px; }
.tip-line strong, .acct-tip-sub strong { font-weight: 700; }
.tip-amts { display: flex; gap: 9px; flex-wrap: wrap; }
.tip-amt {
  font-family: var(--font-s);
  font-weight: 600;
  font-size: 15px;
  padding: 8px 18px;
  border-radius: 100px;
  border: 1.5px solid var(--ink);
  background: transparent;
  color: var(--ink);
  cursor: pointer;
  transition: background .12s;
}
.tip-amt:hover { background: rgba(42, 31, 24, .06); }
.tip-amt.sel { background: var(--ink); color: var(--paper); }
.tip-otherwrap { display: none; margin-top: 12px; align-items: center; gap: 8px; }
.tip-otherwrap.show { display: flex; }
.tip-cur { font-family: var(--font-s); font-weight: 600; font-size: 16px; color: var(--mono); }
.tip-otherwrap input {
  font-family: var(--font-s);
  font-weight: 600;
  font-size: 15px;
  padding: 8px 12px;
  width: 110px;
  border: 1.5px solid var(--rule);
  border-radius: 10px;
  background: var(--paper);
  color: var(--ink);
}
.tip-cta {
  margin-top: 18px;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 12px 24px;
  border-radius: 100px;
  background: var(--accent);
  color: var(--paper);
  font-family: var(--font-d);
  font-style: italic;
  font-weight: 500;
  font-size: 17px;
  border: 0;
  cursor: pointer;
  transition: opacity .15s;
}
.tip-cta:hover { opacity: .9; }
.tip-cta:disabled, .tip-cta.loading { opacity: .6; cursor: default; }
.tip-fine {
  font-family: var(--font-m);
  font-size: 9px;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin: 12px 0 0;
}
.tip-thankyou {
  margin-top: 34px;
  padding-top: 26px;
  border-top: 1px solid var(--rule);
  max-width: 480px;
  font-style: italic;
  font-size: 17px;
  color: var(--ink);
}

/* Boxed variant — a separate, harder-to-miss section (get-link screens) */
.tip-boxed {
  margin-top: 24px;
  padding: 20px 22px;
  border: 1.5px solid var(--accent);
  border-radius: 12px;
  background: var(--paper);
}
.tip-boxed.tip-module { border-top: 1.5px solid var(--accent); padding-top: 20px; }
.tip-boxed.tip-thankyou { border-top: 1.5px solid var(--accent); padding-top: 20px; text-align: center; }

/* Shared eyebrow + small headline for boxed tip callouts (get-link screens,
   account page) — matches tip-jar.php's own eyebrow/headline treatment,
   scaled down to fit a compact box. */
.tip-box-eyebrow {
  font-family: var(--font-m);
  font-size: 10px;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--accent);
  margin: 0 0 6px;
}
.tip-box-headline { font-family: var(--font-d); font-style: italic; font-size: 23px; font-weight: 500; color: var(--ink); margin: 0 0 8px; }

.auth-success-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 46px;
}
.auth-success-actions .btn-new { margin-top: 0; }
/* Keep both buttons on one line on phones */
@media (max-width: 480px) {
  .auth-success-actions { gap: 10px; flex-wrap: nowrap; }
  .auth-success-actions .btn-new { padding: 11px 16px; font-size: 15px; }
}

/* QR code: desktop-only button in the link box + the scan modal */
.btn-qr {
  display: none;            /* shown on desktop only (see media query) */
  align-items: center;
  justify-content: center;
  padding: 7px 9px;
  border-radius: 8px;
  background: var(--paper);
  border: 1.5px solid var(--rule);
  color: var(--ink);
  flex-shrink: 0;
  cursor: pointer;
  transition: all .15s;
}
.btn-qr:hover { background: var(--ink); color: var(--paper); border-color: var(--ink); }
@media (min-width: 768px) { .btn-qr { display: inline-flex; } }

.qr-modal {
  position: fixed;
  inset: 0;
  z-index: 1000;   /* above the account card-preview overlay (z-index 900) */
  align-items: center;
  justify-content: center;
  /* Near-opaque so it fully obscures the card preview underneath (rather than
     a light scrim that competes with the card's edges showing through). */
  background: rgba(42,31,24,.97);
  padding: 24px;
}
.qr-modal-card {
  position: relative;
  background: var(--paper);
  border-radius: 16px;
  padding: 30px 28px 22px;
  width: 100%;
  max-width: 320px;
  text-align: center;
  box-shadow: 0 18px 50px rgba(42,31,24,.35);
}
.qr-modal-close {
  position: absolute;
  top: 10px;
  right: 14px;
  font-size: 26px;
  line-height: 1;
  color: var(--mono);
  background: none;
  border: 0;
  cursor: pointer;
}
.qr-modal-close:hover { color: var(--ink); }
.qr-modal-title {
  font-family: var(--font-d);
  font-style: italic;
  font-size: 21px;
  color: var(--ink);
  margin: 0 0 16px;
}
.qr-modal-code { width: 220px; height: 220px; margin: 0 auto 14px; }
.qr-modal-code svg { width: 100%; height: 100%; display: block; }
/* Recolor the QR's white background rect to the modal cream so it blends in
   (modules stay dark — plenty of contrast against the light background). */
.qr-modal-code svg rect { fill: var(--paper); }
.qr-modal-url {
  font-family: var(--font-m);
  font-size: 11px;
  letter-spacing: .3px;
  color: var(--mono);
  word-break: break-all;
  margin: 0;
}
.auth-tracking-link:hover { text-decoration-color: currentColor; }
/* Preview your card link */
.preview-link {
  display: inline-block;
  margin-top: 10px;
  font-style: italic;
  font-size: 13px;
  color: var(--mono);
  opacity: .6;
  transition: opacity .15s;
}
.preview-link:hover { opacity: 1; }

/* First-time upsell */
.ft-link-loading .link-text { opacity: .5; font-style: italic; }
.ft-link-loading .btn-copy  { opacity: .35; }
.ft-upsell {
  margin-top: 36px;
}
.upsell-card {
  position: relative;
  overflow: hidden;
  max-width: 480px;
  padding: 28px 28px 30px;
  border-radius: 18px;
  border: 1px solid var(--rule);
  background: var(--paper);
  box-shadow: 0 1px 2px rgba(42,31,24,.04), 0 18px 40px -22px rgba(42,31,24,.35);
}
.upsell-eyebrow {
  font-family: var(--font-m);
  font-size: 11px;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--accent);
  margin: 0 0 8px;
}
.upsell-head {
  font-family: var(--font-d);
  font-style: italic;
  font-weight: 500;
  font-size: clamp(26px, 4.5vw, 32px);
  letter-spacing: -.5px;
  line-height: 1.04;
  color: var(--ink);
  margin: 0 0 20px;
}
.upsell-head em { font-style: italic; color: var(--accent); }
.upsell-perks {
  list-style: none;
  margin: 0 0 24px;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.upsell-perks li {
  display: flex;
  align-items: flex-start;
  gap: 11px;
  font-size: 15.5px;
  line-height: 1.4;
  color: var(--mono);
}
.upsell-perks li strong { color: var(--ink); font-weight: 600; }
.upsell-perks svg {
  flex-shrink: 0;
  width: 21px;
  height: 21px;
  margin-top: 1px;
  color: var(--accent);
}
.upsell-cta {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 15px 30px;
  border-radius: 100px;
  border: none;
  background: var(--accent);
  color: var(--paper);
  font-family: var(--font-d);
  font-style: italic;
  font-weight: 500;
  font-size: 19px;
  line-height: 1;
  cursor: pointer;
  box-shadow: 0 8px 22px color-mix(in srgb, var(--accent) 28%, transparent);
  transition: transform .15s ease, box-shadow .15s ease;
}
.upsell-cta:hover { transform: translateY(-1px); box-shadow: 0 12px 30px color-mix(in srgb, var(--accent) 36%, transparent); }
.upsell-cta:active { transform: scale(.98); }

.btn-new {
  margin-top: 12px;
  padding: 12px 24px;
  border-radius: 100px;
  background: var(--ink);
  color: var(--paper);
  font-style: italic;
  font-size: 17px;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  white-space: nowrap;
  transition: all .15s;
}
.btn-new:hover { opacity: .85; }
.btn-new-secondary {
  background: var(--accent);
  color: var(--paper);
}
/* Lower-emphasis accent: outlined, not filled — for the "New card" action on
   the account page where a solid orange pill was too loud. */
.btn-new-outline {
  background: transparent;
  color: var(--accent);
  border: 1.5px solid var(--accent);
}
.btn-new-outline:hover { background: var(--accent); color: var(--paper); opacity: 1; }
/* On the share / get-link screen the Copy button now carries the accent, so the
   two secondary actions (Track opens + New card) read as ink outlines instead of
   orange. Scoped to .auth-success-actions so the account page keeps its orange
   outline buttons. */
.auth-success-actions .btn-new-outline { color: var(--ink); border-color: var(--ink); }
.auth-success-actions .btn-new-outline:hover { background: var(--ink); color: var(--paper); }

/* ── Footer ─────────────────────────────────────────────────────── */
.footer {
  border-top: 1px solid var(--rule);
  padding: 32px 60px 36px;
  background: var(--cream);
  flex-shrink: 0;
}
/* Option C: a centered row — logo · divider · menu — over a centered copyright. */
.footer-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
}
.footer-row {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 20px;
}
.footer-divider {
  width: 1px;
  height: 16px;
  background: rgba(42, 31, 24, .2);
}
.footer-copy { display: block; text-align: center; }
.footer-logo {
  display: flex;
  align-items: center;
  gap: 6px;
}
a.footer-logo, a.footer-logo:visited { color: inherit; }
.footer-logo-mark { line-height: 0; }
.footer-logo-word {
  font-family: var(--font-d);
  font-style: italic;
  font-weight: 500;
  font-size: 16px;
  letter-spacing: -.3px;
  line-height: 1;
}
.footer-copy {
  font-family: var(--font-m);
  font-size: 9px;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--mono);
  opacity: .55;
}
/* Keep each phrase whole, and allow a line break ONLY after a separator (the
   zero-width space), so the copyright wraps cleanly at a "·" instead of
   orphaning a single word like "RESERVED". */
.footer-copy > span:not(.footer-dot) { white-space: nowrap; }
.footer-dot::after { content: "\200B"; }
.footer-nav {
  display: flex;
  gap: 20px;
  align-items: center;
  flex-wrap: wrap;
  justify-content: center;
}
.footer-link {
  font-family: var(--font-d);
  font-style: italic;
  font-size: 16px;
  color: var(--mono);
  opacity: .75;
  transition: opacity .15s;
}
.footer-link:hover { opacity: 1; color: var(--ink); }
@media (max-width: 768px) {
  /* Less side padding and tighter row/nav gaps on small screens. Stack the
     logo above the nav instead of letting them wrap mid-row — otherwise the
     divider can end up dangling alone next to the logo on its own line. */
  .footer { padding: 28px 20px 32px; }
  .footer-row { gap: 14px; flex-direction: column; }
  .footer-divider { display: none; }
  .footer-nav { gap: 16px; }
}
@media (max-width: 480px) {
  /* On phones, shrink + tighten tracking so the copyright still fits one line. */
  .footer-copy { font-size: 8px; letter-spacing: .2px; }
}

/* ── Spinner ─────────────────────────────────────────────────────── */
.spinner {
  width: 18px; height: 18px;
  border: 2px solid rgba(255,255,255,.4);
  border-top-color: #fff;
  border-radius: 50%;
  animation: spin .7s linear infinite;
  display: none;
}
@keyframes spin { to { transform: rotate(360deg); } }
.loading .spinner { display: block; }
.loading .btn-label { display: none; }

/* ── Neutral resolving loader (step 3) ───────────────────────────── */
.auth-loading-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 18px;
  padding: 72px 0;
  text-align: center;
}
.auth-loading-text {
  margin: 0;
  font-size: 15px;
  color: var(--ink-soft);
}

/* ── Card viewer (h.php) ────────────────────────────────────────── */
.card-viewer body {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  min-height: 100vh;
  min-height: 100dvh;
  padding: 28px 20px 28px;
  gap: 16px;
  background: var(--cream);
  color: var(--ink);
}
/* Card fills the space between the brand line and the pinned bottom group,
   centered vertically within it. */
.card-center {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: 0;
}
/* Note reveal (owner view): a quiet "replied" line under the card — small
   all-caps sans, well clear of the card. */
.note-reply-when {
  margin-top: 44px;
  font-family: var(--font-s);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 1.6px;
  text-transform: uppercase;
  color: var(--mono);
  text-align: center;
}
.brand-top {
  font-family: var(--font-m);
  font-size: 10px;
  letter-spacing: 1.6px;
  text-transform: uppercase;
  color: var(--mono);
  text-decoration: none;
  transition: color .2s ease;
}
.brand-top:hover { color: var(--ink); }
.card-wrap {
  width: min(calc(100vw - 40px), calc((100dvh - 270px) * 5 / 7), 400px);
  aspect-ratio: 5 / 7;
  border-radius: 6px;
  overflow: hidden;
  box-shadow:
    0 8px 24px rgba(42,31,24,.12),
    0 28px 56px rgba(42,31,24,.18),
    0 0 60px color-mix(in srgb, var(--card-color) 12%, transparent);
  opacity: 0;
  transform: scale(.96) rotate(-3deg);
  animation: cardOpen 600ms cubic-bezier(.2,.7,.3,1) 120ms forwards;
}
@keyframes cardOpen {
  to { opacity: 1; transform: scale(1) rotate(-1.5deg); }
}
.reactions-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  opacity: 0;
  transform: translateY(16px);
  animation: reactIn 400ms ease 1700ms forwards;
}
@keyframes reactIn {
  to { opacity: 1; transform: translateY(0); }
}
.tap-label {
  font-family: var(--font-m);
  font-size: 9px;
  letter-spacing: 1.6px;
  text-transform: uppercase;
  color: var(--mono);
}
.reactions {
  display: flex;
  gap: 10px;
  position: relative;
}
/* Float-up reaction particles (positioned/animated from JS in h.php) */
.react-float {
  position: absolute;
  pointer-events: none;
  z-index: 20;
  line-height: 1;
  transform: translate(-50%, -50%);
  will-change: transform, opacity;
}
.reaction-btn {
  position: relative;             /* anchors the lock-in ring overlay */
  width: 52px;
  height: 52px;
  border-radius: 50%;
  border: 1px solid rgba(42,31,24,.18);
  background: var(--paper);
  color: var(--ink);
  font-size: 24px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: transform .2s ease, box-shadow .2s ease, border-color .2s ease, opacity .3s ease;
  -webkit-tap-highlight-color: transparent;
}
.reaction-btn:hover { transform: scale(1.1); }
.reaction-btn.selected {
  transform: scale(1.14);
  border-color: transparent;
  box-shadow: 0 3px 10px rgba(42,31,24,.12);   /* ring is drawn by .react-ring now */
}
/* Lock-in ring: a grey circle around the chosen emoji whose dark arc sweeps
   clockwise over the lock window, then holds — the choice is locked (see h.php). */
.react-ring {
  position: absolute;
  /* Constrain the SVG to the button box so it's always centered. An unsized SVG
     renders at its intrinsic viewBox size and can sit off-centre (notably on iOS);
     the ring still surrounds the emoji via the circle radius + overflow. */
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  transform: rotate(-90deg);      /* start the sweep at 12 o'clock */
  pointer-events: none;
  overflow: visible;
  z-index: 5;
}
.react-ring circle { fill: none; stroke-width: 2.4; }
.react-ring-track { stroke: rgba(42,31,24,.09); }
.react-ring-fill {
  stroke: rgba(42,31,24,.4);
  stroke-linecap: butt;            /* match the track exactly — no thicker rounded tip */
  stroke-dasharray: 101;           /* one unit past the circumference so the ends overlap */
  stroke-dashoffset: 101;          /* (closes the 12 o'clock seam) — see h.php sweep */
}
/* Once the choice is locked: it's not interactive (no pointer / hover), and the
   other emojis fade back so the chosen one stands out. The winner holds still —
   a scale bounce read as a distracting jitter, so the fade is the only feedback. */
.reactions.react-locked .reaction-btn { cursor: default; }
.reactions.react-locked .reaction-btn:not(.selected) { opacity: .38; }
.reactions.react-locked .reaction-btn:not(.selected):hover { transform: none; }
/* Pinned bottom caption: "Tap to react · Send Your Own" in one mono line */
.tap-foot {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  font-family: var(--font-m);
  font-size: 9px;
  letter-spacing: 1.6px;
  text-transform: uppercase;
  color: var(--mono);
}
.tap-foot .footer-cta {
  font-style: normal;
  font-size: inherit;
  letter-spacing: inherit;
  color: var(--mono);
  text-decoration: none;
  transition: color .2s ease;
}
.tap-foot .footer-cta:hover { color: var(--ink); }
/* Sender preview — reactions disabled */
.sender-view .reaction-btn {
  pointer-events: none;
  opacity: .3;
  transform: none !important;
}
.sender-view .tap-label {
  font-style: italic;
  opacity: .5;
  font-size: 13px;
}
.footer-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  opacity: 0;
  animation: reactIn 400ms ease 2200ms forwards;
}
.footer-cta {
  font-style: italic;
  font-size: 17px;
  color: var(--accent);
  text-decoration: none;
  letter-spacing: -.3px;
}
.footer-cta:hover { opacity: .8; }

/* Tap-to-enlarge fullscreen viewer (#4) */
.card-wrap { cursor: zoom-in; }
/* Notes have no fullscreen enlarge (they're interactive / a reveal), so the
   zoom-in magnifying-glass cursor is misleading — the note's own tappable parts
   set their own pointer cursor. */
.card-wrap.pn-note-host { cursor: default; }
/* Cut-paper postcards flip on tap (cards.js) rather than enlarge. Whatever
   frame holds one (recipient card, editor preview, full preview) hands its
   shadow and rounding to the two faces, so they turn with the card instead
   of leaving an empty frame behind mid-flip. */
.card-wrap.is-postcard { cursor: pointer; }
.card-wrap:has([data-sprig-flip]),
.edit-preview-card:has([data-sprig-flip]),
.cfp-card-wrap:has([data-sprig-flip]) { overflow: visible; box-shadow: none; min-height: 0; }
[data-sprig-flip] > div > div {
  border-radius: 6px;
  overflow: hidden;
  box-shadow: 0 8px 24px rgba(42,31,24,.12), 0 28px 56px rgba(42,31,24,.18);
}
/* Gallery postcards: selecting one (click or tap — c.php syncPostcardFlip)
   turns it to its back and lifts it 6px with a deeper shadow, on the same 0.9s
   ease-in-out as the turn (cards.js renderPostcard). No hover flip. The frame
   hand-off below keeps the shadow turning with the card. (min-height: 0 matters:
   with overflow visible, an aspect-ratio box otherwise grows to its unscaled
   448px content on phones.) */
.gallery-card-item.pc-flipped .sprig-hover-inner { transform: rotateY(180deg); }
.gallery-card-item.pc-flipped .sprig-hover-inner > div { box-shadow: 0 10px 28px rgba(0,0,0,.16); }
/* The ink selection outline waits for the turn to finish. The delay sits on the
   selected state only, so a deselected card loses it (and settles) promptly. */
.gallery-card-item:has([data-sprig-hover]) .gallery-card-frame {
  outline: 2.5px solid transparent; outline-offset: 3px;
  transition: transform .2s ease, outline-color 0s;
}
.gallery-card-item.sel:is(.pc-flipped, .pc-front) .gallery-card-frame {
  transform: translateY(-6px);
  outline-color: var(--ink);
  transition: transform .9s cubic-bezier(.45,0,.55,1), outline-color 0s linear .9s;
}
/* Passed Notes: the gallery notes load folded and unfold ~3s later; a selected
   note's ink outline waits until they're open (passednotes-create.js adds .pn-ready). */
#gallery-grid-mw:not(.pn-ready) .gallery-card-item.pn-note.sel .gallery-card-frame { outline-color: transparent; }
/* The turned-away face is hidden outright (see renderPostcard in cards.js). */
.sprig-face-back { visibility: hidden; }
.gallery-card-item.pc-flipped .sprig-face-front { visibility: hidden; }
.gallery-card-item.pc-flipped .sprig-face-back { visibility: visible; }
.gallery-card-inner:has([data-sprig-hover]),
.gallery-card-item:hover .gallery-card-inner:has([data-sprig-hover]),
.gallery-card-item.sel .gallery-card-inner:has([data-sprig-hover]) { overflow: visible; box-shadow: none; min-height: 0; }
.gallery-card-inner [data-sprig-hover] .sprig-hover-inner > div {
  border-radius: 6px;
  overflow: hidden;
  box-shadow: 0 2px 8px rgba(0,0,0,.07), 0 6px 20px rgba(0,0,0,.09);
}
.flip-hint {
  margin-top: 18px;
  font-family: var(--font-m);
  font-size: 10px;
  letter-spacing: 1.6px;
  text-transform: uppercase;
  color: var(--mono);
  text-align: center;
}
.card-fs {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 12px;
  box-sizing: border-box;
  background: rgba(26,19,13,.93);
}
.card-fs[hidden] { display: none; }
.card-fs-stage {
  width: min(calc(100vw - 24px), calc((100dvh - 24px) * 5 / 7));
  aspect-ratio: 5 / 7;
  border-radius: 8px;
  overflow: hidden;
  box-shadow: 0 20px 70px rgba(0,0,0,.5);
}
.card-fs-close {
  position: absolute;
  top: 12px;
  right: 16px;
  background: none;
  border: none;
  color: #FBF7EE;
  font-size: 30px;
  line-height: 1;
  opacity: .8;
  cursor: pointer;
  padding: 4px 10px;
}

/* Maximize the card on phones: trim surrounding chrome and widen it (#2, #3, #5) */
@media (max-width: 480px) {
  .card-viewer body {
    padding: max(16px, env(safe-area-inset-top, 0px)) 18px 16px;
    gap: 12px;
  }
  .card-wrap {
    width: min(calc(100vw - 36px), calc((100dvh - 170px) * 5 / 7), 420px);
  }
  .reactions-wrap { gap: 12px; }
  .reaction-btn { width: 44px; height: 44px; font-size: 21px; }
}
.footer-tag {
  font-family: var(--font-m);
  font-size: 8px;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--mono);
  opacity: .6;
}

/* ── Card preview overlay ───────────────────────────────────────── */
.preview-overlay {
  position: fixed;
  inset: 0;
  z-index: 900;
  display: flex;
  flex-direction: column;
  background: var(--paper);
}
.preview-banner {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 16px;
  background: var(--ink);
  color: var(--paper);
  flex-shrink: 0;
  min-height: 52px;
}
.preview-back {
  background: none;
  border: none;
  color: var(--paper);
  cursor: pointer;
  font-family: var(--font-s, 'DM Sans', sans-serif);
  font-size: 14px;
  font-weight: 500;
  padding: 6px 10px;
  border-radius: 6px;
  white-space: nowrap;
  flex-shrink: 0;
  opacity: .85;
}
.preview-back:hover { opacity: 1; background: rgba(251,247,238,.1); }
/* Brand lockup shown (instead of Back + share) when the owner views their own
   card via the normal link. margin-right:auto pushes Edit/Delete to the right. */
.preview-brand { display: inline-flex; align-items: center; gap: 7px; text-decoration: none; flex-shrink: 0; margin-right: auto; }
/* In the QR/share bar the brand sits left of the link+Copy (which is flex:1), so
   it must not consume the free space the way the normal owner-banner brand does. */
.preview-brand-qr { margin-right: 0; }
.preview-brand-mark { display: block; }
.preview-brand-word {
  font-family: var(--font-d); font-style: italic; font-weight: 500;
  font-size: 20px; line-height: 1; letter-spacing: -.5px; color: var(--paper);
}
/* While confirming a delete, hide the share (Copy link) + Edit controls so the
   "Are you sure?" group has breathing room — especially on mobile. They return
   when the confirmation is cancelled.
   Keyed off the Delete button being hidden (which the confirm flow always does),
   so this works without depending on any extra JS/markup. */
.preview-banner:has(#preview-delete[style*="none"]) .preview-share,
.preview-banner:has(#preview-delete[style*="none"]) .preview-edit-btn { display: none; }
.preview-banner:has(#preview-delete[style*="none"]) .preview-delete-wrap { margin-left: auto; }
.preview-share {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-width: 0;
}
.preview-link-text {
  font-family: 'JetBrains Mono', monospace;
  font-size: 12px;
  color: rgba(251,247,238,.6);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.preview-copy-btn {
  background: rgba(251,247,238,.1);
  border: 1px solid rgba(251,247,238,.18);
  color: var(--paper);
  font-size: 12px;
  font-weight: 500;
  padding: 4px 12px;
  border-radius: 20px;
  cursor: pointer;
  flex-shrink: 0;
  transition: background 150ms;
}
.preview-copy-btn:hover { background: rgba(251,247,238,.2); }
/* QR button in the preview banner — matches the Copy pill, icon-only. Desktop
   only: a QR is for pulling the link onto a phone, pointless on the phone itself. */
.preview-qr-btn {
  display: none;
  align-items: center;
  justify-content: center;
  background: rgba(251,247,238,.1);
  border: 1px solid rgba(251,247,238,.18);
  color: var(--paper);
  padding: 5px 9px;
  border-radius: 20px;
  cursor: pointer;
  flex-shrink: 0;
  transition: background 150ms;
}
.preview-qr-btn:hover { background: rgba(251,247,238,.2); }
.preview-qr-btn svg { display: block; }
@media (min-width: 768px) { .preview-qr-btn { display: inline-flex; } }
.preview-edit-btn {
  background: rgba(251,247,238,.1);
  border: 1px solid rgba(251,247,238,.22);
  color: var(--paper);
  font-size: 13px;
  font-weight: 500;
  text-decoration: none;
  white-space: nowrap;
  flex-shrink: 0;
  padding: 5px 14px;
  border-radius: 20px;
  transition: background 150ms, border-color 150ms;
}
.preview-edit-btn:hover { background: rgba(251,247,238,.2); border-color: rgba(251,247,238,.35); }
.preview-delete-wrap {
  display: flex;
  align-items: center;
  flex-shrink: 0;
}
.preview-delete-btn {
  background: none;
  border: 1px solid rgba(255,107,107,.4);
  color: #ff8a8a;
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  padding: 5px 14px;
  border-radius: 20px;
  transition: color 150ms, background 150ms, border-color 150ms;
}
.preview-delete-btn:hover { color: #fff; background: rgba(255,107,107,.18); border-color: rgba(255,107,107,.6); }
.preview-delete-confirm {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  color: rgba(251,247,238,.7);
  white-space: nowrap;
}
.preview-delete-q .confirm-short { display: none; }
.preview-delete-yes {
  position: relative;
  background: #c0392b;
  border: none;
  color: #fff;
  font-size: 12px;
  font-weight: 600;
  padding: 4px 10px;
  min-width: 62px;
  text-align: center;
  border-radius: 20px;
  cursor: pointer;
}
.preview-delete-yes:hover { background: #a93226; }
.preview-delete-yes.is-loading { color: transparent; cursor: default; }
.preview-delete-yes.is-loading::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 12px;
  height: 12px;
  margin: -6px 0 0 -6px;
  border: 2px solid rgba(255,255,255,.4);
  border-top-color: #fff;
  border-radius: 50%;
  animation: btnspin .6s linear infinite;
}
@keyframes btnspin { to { transform: rotate(360deg); } }
.preview-delete-no {
  background: rgba(251,247,238,.1);
  border: 1px solid rgba(251,247,238,.15);
  color: var(--paper);
  font-size: 12px;
  padding: 4px 10px;
  border-radius: 20px;
  cursor: pointer;
}
.preview-delete-no:hover { background: rgba(251,247,238,.2); }
.preview-frame-wrap {
  flex: 1;
  overflow: hidden;
}
.preview-frame-wrap iframe {
  width: 100%;
  height: 100%;
  border: none;
  display: block;
}
@media (max-width: 480px) {
  .preview-link-text { display: none; }
  .preview-share { justify-content: flex-end; }
  .preview-delete-q .confirm-full { display: none; }
  .preview-delete-q .confirm-short { display: inline; }
}

/* ── Account / profile page ─────────────────────────────────────── */
.acct-wrap {
  max-width: 680px;
  margin: 0 auto;
  padding: 48px 20px 80px;
  min-height: 60vh;
}
.acct-loading {
  display: flex;
  justify-content: center;
  padding: 80px 0;
}
.acct-spinner {
  width: 28px;
  height: 28px;
  border: 2.5px solid rgba(42,31,24,.12);
  border-top-color: var(--logo);
  border-radius: 50%;
  animation: spin 700ms linear infinite;
}
.acct-header {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 16px;
  /* Pinned so "New card" stays reachable while scrolling the list. `top` is set
     from JS to the sticky nav's height; the bg + gutter bleed keep scrolling cards
     fully hidden behind it. */
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--cream);
  margin: 0 -20px 22px;
  padding: 10px 20px;
}
.acct-header.is-stuck {
  box-shadow: 0 6px 16px -12px rgba(42,31,24,.4);
  border-bottom: 1px solid var(--rule);
}
.acct-headline {
  font-family: 'Cormorant Garamond', serif;
  font-size: clamp(28px, 6vw, 40px);
  font-weight: 500;
  color: var(--ink);
  margin: 0 0 4px;
  line-height: 1.1;
}
.acct-count {
  font-family: 'Cormorant Garamond', Georgia, serif;
  font-style: italic;
  font-size: 17px;
  color: var(--mono);
  margin: 0;
  line-height: 1.2;
}
.acct-count strong {
  font-style: normal;
  font-weight: 600;
  color: var(--ink);
}
.acct-count-dot { margin: 0 9px; opacity: .55; }
.acct-header-actions {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-shrink: 0;
}
.acct-signout { white-space: nowrap; }

/* Sign-in form (account page, not signed in) */
.acct-signin-form {
  max-width: 340px;
  margin: 24px auto 0;
  text-align: left;
}
.acct-signin-form .btn-send { width: 100%; }
.acct-signin-mark {
  line-height: 0;
  margin: 0 0 16px;
  display: flex;
  justify-content: center;
}
.acct-signin-create {
  font-size: 15px;
  color: var(--mono);
  margin: 20px 0 0;
}
.acct-signin-create a {
  color: var(--ink);
  text-decoration: underline;
  text-underline-offset: 2px;
}
.acct-signin-create a:hover { opacity: .7; }
.signin-br { display: none; }

/* Profile: default sender name */
.acct-profile {
  margin-bottom: 28px;
  padding-bottom: 24px;
  border-bottom: 1px solid var(--rule);
}
/* Account-information block: no divider line, just open space before the cards */
#acct-contacts {
  border-bottom: none;
  padding-bottom: 0;
  margin-bottom: 48px;
}
.acct-profile-label {
  display: block;
  font-family: var(--font-m);
  font-size: 10px;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--mono);
  margin-bottom: 8px;
}
.acct-profile-row {
  display: flex;
  gap: 10px;
  align-items: stretch;
}
.acct-name-input {
  background: var(--cream);
  border: 1.5px solid var(--rule);
  border-radius: 12px;
  padding: 12px 16px;
  font-size: 16px;
  font-style: italic;
  color: var(--ink);
  flex: 1;
  min-width: 0;
  box-sizing: border-box;
  transition: border-color .15s;
  caret-color: var(--accent);
}
.acct-name-input:focus { outline: none; border-color: var(--accent); }
.acct-name-input::placeholder { color: var(--ink); opacity: .35; }
.acct-name-save { white-space: nowrap; }
.acct-name-input.error { border-color: var(--accent); }
.acct-profile-error {
  font-style: italic;
  font-size: 13px;
  color: var(--accent);
  margin: 8px 0 0;
}
.acct-profile-hint {
  font-size: 13px;
  color: var(--ink-soft);
  margin: 8px 0 0;
}
.acct-contacts-hint { font-size: 15px; line-height: 1.45; margin: 1px 0 14px; }

/* Sign-in contacts (email / phone) */
.acct-contact-rows {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.acct-contact-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 11px 0;
}
.acct-contact-row + .acct-contact-row {
  border-top: 1px solid var(--rule);
}
.acct-contact-label {
  flex: 0 0 76px;   /* matches .acct-pref-label so both tables' columns line up */
  font-family: var(--font-m);
  font-size: 10px;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--mono);
}
.acct-contact-value {
  flex: 1;
  min-width: 0;
  font-size: 16px;
  color: var(--ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.acct-contact-value.acct-contact-empty {
  font-style: italic;
  color: var(--ink);
  opacity: .4;
}
/* Belt-and-suspenders with the format-detection meta: if iOS still auto-links a
   detected email/phone, keep it looking like plain text (no blue underline). */
.acct-contact-value a { color: inherit; text-decoration: none; }
.acct-contact-row-actions {
  display: flex;
  gap: 14px;
  flex-shrink: 0;
}
.acct-contact-link {
  background: none;
  border: none;
  padding: 0;
  font-family: var(--font-d);
  font-size: 14px;
  color: var(--accent);
  cursor: pointer;
  transition: opacity .15s;
}
.acct-contact-link:hover { opacity: .7; }
.acct-contact-link-danger { color: var(--mono); }

/* Inline add/change editor */
.acct-contact-editor {
  margin-top: 14px;
  padding: 16px;
  background: var(--cream);
  border: 1px solid var(--rule);
  border-radius: 12px;
}
.acct-contact-editor-title {
  font-family: var(--font-m);
  font-size: 10px;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--mono);
  margin: 0 0 10px;
}
.acct-contact-editor .auth-input {
  width: 100%;
  box-sizing: border-box;
  margin-bottom: 4px;
}
.acct-contact-actions {
  display: flex;
  gap: 10px;
  align-items: stretch;   /* equal height */
  margin-top: 12px;
}
/* Save/Send/Verify dominates (≈3×) with Cancel a comfortable secondary; both
   match height. */
.acct-contact-actions .btn-send,
.acct-contact-actions .btn-ghost {
  width: auto;            /* override .btn-send width:100% */
  margin-top: 0;          /* override .btn-send margin-top (was nudging it down) */
}
.acct-contact-actions .btn-send { flex: 3; }
.acct-contact-actions .btn-ghost { flex: 1; justify-content: center; }
.acct-contact-btn { white-space: nowrap; }
.acct-contact-sent {
  font-size: 14px;
  color: var(--ink-soft);
  margin: 0 0 12px;
}
.acct-contact-error {
  margin: 2px 0 0;
}

/* Card list */
.acct-card-list-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 16px 10px;
  margin-bottom: 4px;
  border-bottom: 1px solid var(--rule);
}
.acct-card-list-head .acct-count,
.acct-col-status {
  font-family: var(--font-m);
  font-size: 10px;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--mono);
}
.acct-col-status { padding-right: 4px; }
.acct-card-list {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.acct-card-item {
  display: flex;
  align-items: center;
  gap: 16px;
  /* Negative side margins = the hover highlight bleeds into the page gutters
     while the card art + status stay flush with the content edges. */
  padding: 14px 16px;
  margin-left: -16px;
  margin-right: -16px;
  border-radius: 10px;
  text-decoration: none;
  background: transparent;
  transition: background 150ms;
  cursor: pointer;
}
.acct-card-item:hover { background: rgba(42,31,24,.05); }
.acct-card-swatch {
  position: relative;           /* anchors the scaled-down live card render */
  flex-shrink: 0;
  width: 46px;
  aspect-ratio: 5 / 7;          /* same proportions as the cards we send */
  border-radius: 3px;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(42,31,24,.06);  /* neutral placeholder until the thumbnail paints */
  box-shadow: inset 0 0 0 1px rgba(42,31,24,.12),
              0 1px 3px rgba(42,31,24,.14);
  /* Same easing as the card-viewer's cardOpen, so the hover tilt feels like
     the card settling on the preview page. */
  transition: transform 350ms cubic-bezier(.2,.7,.3,1),
              box-shadow 350ms cubic-bezier(.2,.7,.3,1);
}
/* Hovering the row tilts the little card the way it rests on the preview page
   (a soft counter-clockwise lean), with a slight lift. */
.acct-card-item:hover .acct-card-swatch {
  transform: rotate(-5deg) scale(1.06);
  box-shadow: inset 0 0 0 1px rgba(42,31,24,.12),
              0 6px 16px rgba(42,31,24,.20);
}
@media (prefers-reduced-motion: reduce) {
  .acct-card-swatch { transition: none; }
  .acct-card-item:hover .acct-card-swatch { transform: none; }
}
/* A real, scaled-down card render fills the swatch (scaleThumbs() sets the
   transform). It's a fixed 320x448 box pinned to the top-left corner and
   shrunk to the swatch width — no stored PNG involved. */
.acct-card-render {
  position: absolute;
  top: 0;
  left: 0;
  transform-origin: top left;
  pointer-events: none;
}
/* Live open-note thumbnail, pinned top-left and scaled to the swatch (see
   scaleThumbs / mountNoteThumbs) — the note equivalent of .acct-card-render. */
.acct-note-render {
  position: absolute;
  top: 0;
  left: 0;
  transform-origin: top left;
  pointer-events: none;
}
.acct-card-info {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
}
.acct-card-to {
  font-size: 16px;
  font-weight: 600;
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.acct-card-occasion {
  font-family: 'Cormorant Garamond', serif;
  font-style: italic;
  font-size: 16px;
  line-height: 1.1;
  color: var(--ink);
}
.acct-card-meta {
  font-size: 12.5px;
  color: var(--mono);
}
.acct-card-right {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-shrink: 0;
}
.acct-reaction {
  font-size: 18px;
  line-height: 1;
  width: 24px;
  text-align: center;
}
.acct-chip {
  display: inline-flex;
  align-items: center;
  font-size: 12px;
  font-weight: 500;
  padding: 3px 9px;
  border-radius: 20px;
  white-space: nowrap;
}
.acct-chip-opened {
  background: rgba(34,139,34,.1);
  color: #226622;
}
.acct-chip-pending {
  background: rgba(42,31,24,.07);
  color: var(--mono);
}
/* Passed Notes: a folded-note glyph on ruled paper fills the swatch (the
   interactive note can't render statically), plus reply feedback on the right. */
.acct-note-thumb {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #FBF9F1;
  background-image: repeating-linear-gradient(transparent, transparent 5px, #DBDFE4 6px);
  color: #2C4A73;
}
.acct-note-thumb svg { width: 62%; height: 62%; }
/* the recipient's answer, shown where a reaction emoji would be */
.acct-reply-val {
  max-width: 120px;
  font-size: 13px;
  font-weight: 600;
  color: var(--ink);
  text-align: right;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.acct-reply-val.unread { color: var(--accent); }
/* an unread reply gets an accent chip so it stands out in the list */
.acct-chip-new {
  background: rgba(224,75,46,.12);
  color: var(--accent);
  font-weight: 600;
}
/* "See reply" affordance — a quiet ghost pill (same family as the chips) that
   opens the note to reveal the recipient's reply. Fills green on row hover to
   echo the Opened chip; an unread reply reads in accent to draw the eye. */
.acct-reply-link {
  font-family: var(--font-d);   /* same serif as the Opened / Unopened chips */
  font-size: 12px;
  font-weight: 500;
  line-height: 1;
  padding: 4px 11px;
  border-radius: 20px;
  border: 1px solid rgba(42,31,24,.2);
  color: var(--mono);
  white-space: nowrap;
  transition: color .15s, border-color .15s, background .15s;
}
.acct-card-item:hover .acct-reply-link { color: #226622; border-color: #226622; background: rgba(34,102,34,.09); }
/* Unread reply: a bolder green outline draws the eye without going back to red. */
.acct-reply-link.is-new { color: #226622; border-color: rgba(34,102,34,.55); font-weight: 600; }
.acct-card-item:hover .acct-reply-link.is-new { color: #226622; border-color: #226622; background: rgba(34,102,34,.13); }

/* Email notification prefs — two toggles tucked under the email address in the
   Account Information rows. Checkbox on the left; grey by default, ink on check. */
.acct-contact-row-tall { align-items: flex-start; }
.acct-contact-row-tall .acct-contact-label { margin-top: 2px; }   /* line up with the address */
.acct-contact-row-tall .acct-contact-value {
  display: flex;
  flex-direction: column;
  gap: 9px;
  white-space: normal;
  overflow: visible;
}
/* Address line: email left, "Change/Remove" right — spans the full value column
   so the toggles' "Saved" below can right-align flush with "Change". */
.acct-email-top { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.acct-email-top .acct-contact-row-actions { flex: 0 0 auto; }
.acct-email-addr { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.acct-email-prefs { display: flex; flex-direction: column; gap: 8px; margin-top: 3px; }
.acct-pref-line {
  display: flex;
  align-items: center;
  min-height: 22px; /* reserve the pill's height so the "Saved" pill never grows the row */
  gap: 9px;
  cursor: pointer;
  font-size: 14px;
  line-height: 1.3;
  color: var(--mono);
  transition: color .15s;
}
/* Custom checkbox: a soft, page-blended box (not stark white) that fills ink with
   a cream check when on. */
.acct-pref-line input[type="checkbox"] {
  appearance: none;
  -webkit-appearance: none;
  flex: 0 0 auto;
  width: 16px;
  height: 16px;
  margin: 0;
  border: 1.5px solid rgba(42,31,24,.26);
  border-radius: 4px;
  background: rgba(42,31,24,.04);
  cursor: pointer;
  transition: background .12s ease, border-color .12s ease;
}
.acct-pref-line input[type="checkbox"]:checked {
  background-color: var(--ink);
  border-color: var(--ink);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12' fill='none' stroke='%23FBF7EE' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2.5 6.3l2.3 2.4 4.7-5.1'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: center;
}
.acct-pref-line input:checked ~ span:not(.acct-pref-line-saved) { color: var(--ink); }
/* "Saved" pill at the far right of the toggled line — same treatment as the
   "Opened" chip on the cards list (green tint, rounded), right-justified. */
.acct-pref-line-saved {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  padding: 3px 9px;
  border-radius: 20px;
  background: rgba(34,139,34,.1);
  color: #226622;
  font-size: 12px;
  font-weight: 500;
  white-space: nowrap;
  opacity: 0;
  transform: scale(.9);
  transition: opacity .3s ease, transform .3s ease; /* smooth fade-out after the pop */
}
.acct-pref-line-saved.show { opacity: 1; transform: scale(1); animation: acct-saved-pop .32s ease; }
@keyframes acct-saved-pop {
  0%   { opacity: 0; transform: scale(.9); }
  55%  { opacity: 1; transform: scale(1.06); }
  100% { opacity: 1; transform: scale(1); }
}
.acct-pref-line-saved.is-error { background: rgba(224,75,46,.12); color: var(--accent); }

/* Sign-up opt-in checkboxes (create-account step in c.php) */
.auth-optins { display: flex; flex-direction: column; gap: 10px; margin: 4px 0 16px; text-align: left; }
.auth-optin { display: flex; align-items: flex-start; gap: 10px; cursor: pointer; font-size: 14px; color: var(--mono); line-height: 1.4; }
.auth-optin input[type="checkbox"] {
  appearance: none; -webkit-appearance: none;
  margin: 1px 0 0; width: 17px; height: 17px; flex: 0 0 auto;
  border: 1.5px solid rgba(42,31,24,.26); border-radius: 4px;
  background: rgba(42,31,24,.04); cursor: pointer;
  transition: background .12s ease, border-color .12s ease;
}
.auth-optin input[type="checkbox"]:checked {
  background-color: var(--ink); border-color: var(--ink);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12' fill='none' stroke='%23FBF7EE' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2.5 6.3l2.3 2.4 4.7-5.1'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: center;
}
/* Email-only: dim + lock the opt-ins when the contact looks like a phone number. */
.auth-optins.is-muted .auth-optin { opacity: .45; cursor: default; }
.auth-optins.is-muted .auth-optin input[type="checkbox"] { cursor: default; }
.auth-optins-hint { margin: -2px 0 0; font-size: 13px; line-height: 1.4; color: var(--mono); opacity: .7; }

/* ── Tip jar (account page) ──────────────────────────────────────────── */
.acct-tip {
  margin: 0 0 24px;
  padding: 18px 20px;
  border: 1.5px solid var(--accent);
  border-radius: 12px;
  background: var(--paper);
}
.acct-tip-sub { font-size: 16px; color: var(--ink); line-height: 1.5; margin: 0 0 14px; }
.acct-tip .tip-cta { margin-top: 14px; }
.acct-tip-thanks {
  font-style: italic;
  font-size: 15px;
  color: var(--ink);
  text-align: center;
}

/* Empty / sign-in states */
.acct-empty-state {
  text-align: center;
  padding: 36px 20px 72px;
}
.acct-empty-icon {
  font-size: 40px;
  margin: 0 0 16px;
  line-height: 1;
}
.acct-empty-headline {
  font-family: 'Cormorant Garamond', serif;
  font-size: 28px;
  font-weight: 500;
  line-height: 1.05;
  color: var(--ink);
  margin: 0 0 10px;
}
.acct-empty-sub {
  font-size: 15px;
  color: var(--mono);
  margin: 0 0 24px;
  line-height: 1.4;
  text-wrap: balance;
}

@media (max-width: 480px) {
  .acct-header { align-items: center; flex-wrap: wrap; }
  .signin-br { display: inline; }
  .acct-card-right { gap: 7px; }
  .acct-card-item { margin: 0; padding: 12px 0; border-radius: 0; gap: 12px;
    border-bottom: 1px solid rgba(42,31,24,.08); }
  /* No trailing hairline under the last card — it just adds empty space. */
  .acct-card-item:last-child { border-bottom: none; }
  .acct-card-item:hover { background: transparent; }
}


/* ── Desktop: card preview is clickable ────────────────────────── */
@media (min-width: 901px) {
  .edit-preview-wrap {
    position: relative;
  }
  .edit-preview-wrap.preview-ready {
    cursor: pointer;
  }
  /* Hover hint: a small grey, all-caps label centred under the card so it's
     clear the preview is clickable ("Click to preview" opens the full view). */
  .edit-preview-wrap::after {
    content: 'Click to preview';
    position: absolute;
    bottom: -40px;
    left: 50%;
    transform: translateX(-50%);
    font-family: var(--font-m);
    font-size: 10px;
    letter-spacing: 1.5px;
    text-transform: uppercase;
    color: var(--mono);
    opacity: 0;
    transition: opacity .18s ease;
    white-space: nowrap;
    pointer-events: none;
  }
  .edit-preview-wrap.preview-ready:hover::after { opacity: .7; }
  /* Cut-paper postcards: a click turns the card over (cards.js), so say that —
     and show it on hover even before For/From are filled in. */
  .edit-preview-wrap:has([data-sprig-flip]) { cursor: pointer; }
  .edit-preview-wrap:has([data-sprig-flip])::after { content: 'Click to flip'; }
  .edit-preview-wrap:has([data-sprig-flip]):hover::after { opacity: .7; }
}

/* ── Full-size card preview overlay (step 3) ────────────────────── */
.card-full-preview {
  position: fixed;
  inset: 0;
  z-index: 500;
  background: var(--cream);
  display: flex;
  flex-direction: column;
}
.cfp-banner {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 16px;
  background: var(--cream);
  border-bottom: 1px solid var(--rule);
  flex-shrink: 0;
  gap: 12px;
}
/* Centered "Preview" label so it's clear this modal is a preview, not the live
   card. Absolutely centred in the bar so the flanking buttons don't shift it. */
.cfp-title {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  font-family: var(--font-m);
  font-size: 11px;
  letter-spacing: 2.5px;
  text-transform: uppercase;
  color: var(--mono);
  pointer-events: none;
  white-space: nowrap;
}
/* On narrow screens the buttons can crowd the centre — hide the label there. */
@media (max-width: 560px) { .cfp-title { display: none; } }
.cfp-back {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: var(--paper);
  border: 1.5px solid rgba(107,90,74,.28);
  border-radius: 100px;
  cursor: pointer;
  font-family: var(--font-d);
  font-style: italic;
  font-weight: 500;
  font-size: 18px;
  line-height: 1;
  color: var(--mono);
  padding: 16px 20px 12px;          /* optical-centre nudge (see .btn-ghost) */
  box-shadow: 0 1px 3px rgba(42,31,24,.08);
  transition: background .15s, border-color .15s, box-shadow .15s, color .15s;
}
.cfp-back:hover {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--cream);
  box-shadow: 0 2px 8px rgba(42,31,24,.18);
}
.cfp-proceed {
  flex-shrink: 0;
}
.cfp-body {
  flex: 1;
  overflow-y: auto;
  display: flex;
  flex-direction: column;   /* card, then the postcard flip hint under it */
  align-items: center;
  justify-content: center;
  padding: 32px 20px 48px;
}
.cfp-card-wrap {
  width: min(calc(100vw - 40px), calc((100vh - 140px) * 5 / 7), 420px);
  aspect-ratio: 5 / 7;
  flex-shrink: 0;
  border-radius: 6px;
  overflow: hidden;
  box-shadow:
    0 8px 24px rgba(42,31,24,.18),
    0 28px 56px rgba(42,31,24,.32),
    0 0 60px color-mix(in srgb, var(--card-color, #2A1F18) 14%, transparent);
  animation: cardOpen 500ms cubic-bezier(.2,.7,.3,1) forwards;
}
@media (min-width: 901px) {
  .cfp-card-wrap {
    width: min(calc((100vh - 160px) * 5 / 7), 520px);
  }
  .cfp-body { padding: 40px 60px 56px; }
}

/* ── Examples carousel ─────────────────────────────────────────────── */
.examples-wrap {
  padding: 40px 24px 0;
  max-width: 760px;
  margin: 0 auto;
}
.examples-stage {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 46px;
  margin-top: 8px;
}
.ex-arrow {
  flex-shrink: 0;
  width: 54px;
  height: 54px;
  border-radius: 50%;
  border: 1px solid var(--rule);
  background: var(--paper);
  color: var(--ink);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  box-shadow: 0 2px 10px rgba(42,31,24,.08);
  transition: transform .15s ease, background .15s ease, color .15s ease;
}
/* Hover only on devices that truly hover — avoids sticky black on touch taps */
@media (hover: hover) {
  .ex-arrow:hover { background: var(--ink); color: var(--paper); transform: scale(1.07); }
}
.ex-arrow:active { transform: scale(.96); }
.ex-arrow-hidden { visibility: hidden; pointer-events: none; }
.ex-card-col {
  display: flex;
  flex-direction: column;
  align-items: center;
}
.ex-card-frame {
  width: min(62vw, 408px);
  aspect-ratio: 5 / 7;
  border-radius: 10px;
  overflow: hidden;
  background: var(--paper);
  box-shadow:
    0 8px 24px rgba(42,31,24,.12),
    0 28px 56px rgba(42,31,24,.18),
    0 0 60px color-mix(in srgb, var(--card-color, var(--accent)) 12%, transparent);
  transform: rotate(-1.5deg);
}
@keyframes exSlideL { from { opacity: 0; transform: translateX(-22px) rotate(-1.5deg); } to { opacity: 1; transform: rotate(-1.5deg); } }
@keyframes exSlideR { from { opacity: 0; transform: translateX( 22px) rotate(-1.5deg); } to { opacity: 1; transform: rotate(-1.5deg); } }
.ex-card-frame.slide-l { animation: exSlideL .28s cubic-bezier(.2,.7,.3,1); }
.ex-card-frame.slide-r { animation: exSlideR .28s cubic-bezier(.2,.7,.3,1); }
.ex-dots {
  display: flex;
  justify-content: center;
  gap: 9px;
  margin-top: 22px;
}
.ex-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  border: 0;
  padding: 0;
  background: color-mix(in srgb, var(--ink) 22%, transparent);
  cursor: pointer;
  transition: background .15s ease, transform .15s ease;
}
@media (hover: hover) {
  .ex-dot:hover { background: color-mix(in srgb, var(--ink) 40%, transparent); }
}
.ex-dot.on { background: var(--ink); transform: scale(1.25); }
.examples-cta {
  text-align: center;
  margin-top: 40px;
  padding: 0 24px 64px;
}
.examples-make {
  font-family: var(--font-d);
  font-style: italic;
  font-weight: 500;
  font-size: 18px;
  line-height: 1;
  color: var(--mono);
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 13px 24px;
  border-radius: 100px;
  border: 1.5px solid rgba(107,90,74,.28);
  background: var(--paper);
  transition: border-color .15s ease, color .15s ease, transform .15s ease;
}
.examples-make-arrow {
  font-style: normal;
  display: inline-flex;
  align-items: center;
  flex-shrink: 0;
}
.examples-make:hover { border-color: var(--ink); color: var(--ink); transform: translateY(-1px); }
.examples-make:active { transform: scale(.97); }
/* A magnifying-glass cursor invites the click-to-enlarge; the overlay shows a shrink
   cursor since a click anywhere closes it. (Hover-only — touch has no cursor.) */
@media (hover: hover) {
  .ex-card-frame { cursor: zoom-in; }
}
#ex-fs { cursor: zoom-out; }
@media (max-width: 560px) {
  /* Fill the *visible* viewport (dvh accounts for the mobile URL bar; 100vh would
     push the CTA below the fold) and vertically center the card between nav and CTA. */
  .page-wrap.examples-page { display: flex; flex-direction: column; min-height: 100vh; min-height: 100dvh; }
  .examples-wrap { padding: 8px 8px 0; flex: 1 1 auto; display: flex; flex-direction: column; justify-content: center; }
  .examples-stage { gap: 12px; justify-content: space-between; }
  .ex-arrow { width: 36px; height: 36px; }
  .ex-card-frame { width: min(62vw, 300px); }
  .examples-cta { margin-top: 20px; padding: 0 24px 28px; }
}
