/* pebi.me/p/{token} — "The Travel Desk" profile-stack page.
   A PUBLIC user's postcards scattered on a dark walnut writing desk; pick one up to inspect it.
   Served as a static asset (the root [token].js catch-all passes dotted paths through). Paired
   with /p-stack.js. Dark, vintage-postal — same brand palette/fonts as the single-card page. */

:root{
  --parchment:#F0E8DA; --parchment-deep:#E8DCC8;
  --maroon:#8D2D2D;    --maroon-light:#9E3838;
  --brown-title:#633323; --brown-caption:#734444;
  --stamp-frame:#BFA68B; --ink:#29385C; --text-body:#5C3A2A;
  --wood-a:#3a2417; --wood-b:#33200f; --wood-c:#452c1a; --wood-edge:#1f120a;
  --leather:#3c211d; --leather-2:#4a2925; --leather-edge:#26120f;
  --brass:#c8a25a; --gold:#d8b878;
}
*,*::before,*::after{margin:0;padding:0;box-sizing:border-box}
html,body{height:100%}
body{
  font-family:'Inter',-apple-system,BlinkMacSystemFont,sans-serif;
  color:var(--parchment);
  min-height:100svh; overflow:hidden;
  display:flex; flex-direction:column; -webkit-font-smoothing:antialiased;
  background:
    radial-gradient(120% 90% at 50% 12%, rgba(255,222,170,.20), rgba(255,222,170,0) 46%),
    repeating-linear-gradient(91deg,
      var(--wood-a) 0 86px, var(--wood-b) 86px 88px, var(--wood-c) 88px 174px, var(--wood-edge) 174px 176px),
    linear-gradient(180deg,#2a1a10,#160d07);
  background-blend-mode:screen,normal,normal;
}
.grain{position:fixed; inset:0; z-index:0; pointer-events:none; opacity:.5; mix-blend-mode:multiply;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)' opacity='0.05'/%3E%3C/svg%3E");}
.vignette{position:fixed; inset:0; z-index:0; pointer-events:none;
  background:radial-gradient(130% 100% at 50% 38%, transparent 40%, rgba(0,0,0,.5) 100%);}
/* the vintage world map, ghosted onto the dark desk (screen-blended so it etches light) */
.map-bg{position:fixed; inset:0; z-index:0; pointer-events:none; opacity:.1; mix-blend-mode:screen;
  background:image-set(url("/assets/vintage_map.webp") type("image/webp"), url("/assets/vintage_map.jpg") type("image/jpeg")) center/cover no-repeat;
  filter:sepia(.6) saturate(.7) brightness(1.2);
  -webkit-mask-image:radial-gradient(ellipse 86% 80% at 50% 46%, rgba(0,0,0,.25) 6%, #000 86%);
  mask-image:radial-gradient(ellipse 86% 80% at 50% 46%, rgba(0,0,0,.25) 6%, #000 86%);}

/* header */
.top{position:relative; z-index:35; display:flex; align-items:center; justify-content:space-between;
  width:100%; max-width:1100px; margin:0 auto; padding:.95rem 1.4rem .25rem;}
.brand{display:flex; align-items:center; gap:11px}
.brand-mark{width:40px; height:40px; border-radius:50%; object-fit:cover; background:var(--parchment-deep);
  border:1.5px solid var(--stamp-frame); box-shadow:0 3px 10px rgba(0,0,0,.4);}
.brand-name{font-family:'Playfair Display',serif; font-weight:700; font-size:1.4rem;
  color:var(--parchment); letter-spacing:-.02em; text-shadow:0 1px 3px rgba(0,0,0,.5)}
.who{display:flex; align-items:center; gap:12px}
.who-text{text-align:right; line-height:1.25}
/* the owner's penguin — header chip */
.who-avatar{width:52px; height:52px; border-radius:50%; object-fit:contain; padding:4px;
  background:var(--parchment-deep); border:1.5px solid var(--stamp-frame);
  box-shadow:0 3px 10px rgba(0,0,0,.4);}
.who-name{font-family:'Playfair Display',serif; font-style:italic; font-weight:600; font-size:1.05rem;
  color:#f3e7d2; text-shadow:0 1px 3px rgba(0,0,0,.5)}
.who-stat{font-family:'Special Elite',monospace; font-size:.72rem; letter-spacing:.06em; color:#cdb48f}

/* desk stage — NOTE: no z-index here on purpose (a stacking context would trap the picked-up card under the scrim) */
/* min-height:0 lets the stage shrink so the bottom CTAs always fit; the blotter then fills the leftover
   space (min(100%,…)) instead of a fixed vh — which on mobile (vh includes the browser chrome) pushed
   the "What is Pebi?" button off-screen. */
.stage{position:relative; flex:1; min-height:0; display:grid; place-items:center; padding:.4rem .8rem;}
.blotter{position:relative; width:min(94vw,2400px); height:min(100%,1180px); border-radius:12px;
  background:
    radial-gradient(120% 120% at 50% 30%, rgba(255,210,150,.10), transparent 60%),
    radial-gradient(140% 120% at 50% 50%, var(--leather-2), var(--leather) 70%);
  box-shadow:0 2px 0 rgba(255,220,180,.06) inset, 0 0 0 2px var(--leather-edge),
    0 0 0 9px rgba(0,0,0,.20), 0 34px 70px rgba(0,0,0,.55), 0 6px 18px rgba(0,0,0,.5);}
.blotter::before{content:''; position:absolute; inset:8px; border-radius:8px;
  border:1.5px dashed rgba(216,184,120,.28); pointer-events:none;}
.corner{position:absolute; width:30px; height:30px; z-index:2; pointer-events:none;
  background:linear-gradient(135deg,var(--gold),var(--brass)); opacity:.85; box-shadow:0 2px 5px rgba(0,0,0,.4);}
.corner.tl{top:6px; left:6px; clip-path:polygon(0 0,100% 0,0 100%); border-top-left-radius:8px}
.corner.tr{top:6px; right:6px; clip-path:polygon(0 0,100% 0,100% 100%); border-top-right-radius:8px}
.corner.bl{bottom:6px; left:6px; clip-path:polygon(0 0,0 100%,100% 100%); border-bottom-left-radius:8px}
.corner.br{bottom:6px; right:6px; clip-path:polygon(100% 0,100% 100%,0 100%); border-bottom-right-radius:8px}
.seal{position:absolute; left:3%; bottom:6%; width:50px; height:50px; border-radius:50%; z-index:1;
  display:grid; place-items:center; transform:rotate(-12deg); pointer-events:none;
  background:radial-gradient(circle at 38% 32%, var(--maroon-light), #6f2020 72%);
  color:#f0d9d0; font-family:'Playfair Display',serif; font-weight:700; font-size:1.4rem;
  box-shadow:0 4px 10px rgba(0,0,0,.5), 0 0 0 2px rgba(0,0,0,.15) inset;}
/* the Pebi penguin "postman" — peeks up at the desk corner */
.postman{position:absolute; right:-14px; bottom:-30px; z-index:30; width:78px; height:auto; pointer-events:none;
  filter:drop-shadow(0 8px 12px rgba(0,0,0,.55)); transform-origin:50% 100%;
  animation:postmanBob 3.6s ease-in-out infinite;}
@keyframes postmanBob{0%,100%{transform:translateY(0) rotate(0)} 50%{transform:translateY(-5px) rotate(-3deg)}}
/* owner's avatar as postman — 2x the default mascot */
.postman.owner{width:156px; right:-24px; bottom:-46px}
@media (max-width:560px){ .postman{width:62px; right:-8px; bottom:-22px}
  .postman.owner{width:118px; right:-12px; bottom:-32px} }

/* the pile — cards spill a little past the blotter onto the bare desk, like a real stack */
.pile{position:absolute; inset:0; overflow:visible; --w:130}
.pc{position:absolute; top:50%; left:50%; width:calc(var(--w)*1px); aspect-ratio:2/3; z-index:var(--z,1);
  transform:translate(calc(-50% + var(--x,0)*1px), calc(-50% + var(--y,0)*1px)) rotate(calc(var(--rot,0)*1deg));
  /* opacity IS transitioned: with transform-only, all 36 cards' opacity snapped
     0->1 in a single frame at deal time — one giant raster burst (the load lag
     spike). With it, the per-card transitionDelay staggers paint too. */
  transition:transform .62s cubic-bezier(.2,.85,.25,1), opacity .35s ease;
  cursor:grab; border:none; padding:0; background:none; -webkit-tap-highlight-color:transparent;}
.pc.predeal{transform:translate(125%,-160%) rotate(34deg) scale(.92); opacity:0; transition:none}
.pc-img{width:100%; height:100%; object-fit:contain; display:block; pointer-events:none;
  /* ONE drop-shadow, NEVER transitioned (perf, 2026-08-25): drop-shadow is a filter,
     so tweening it re-rasterizes the card's alpha-blurred bitmap EVERY FRAME — with 33
     cards under two full-viewport blend layers, mousing across the desk was a re-raster
     storm ("feels laggy", Frank). The shadow now snaps between states; the .62s
     transform lift still animates, and under that motion the snap is imperceptible. */
  filter:drop-shadow(0 8px 12px rgba(0,0,0,.52));}
.pile:not(.inspecting) .pc:not(.pc--pending):hover{z-index:900;
  transform:translate(calc(-50% + var(--x)*1px), calc(-50% + var(--y)*1px - 22px)) rotate(calc(var(--rot)*.3deg)) scale(1.08);}
/* Hover blur capped at 16px (was 24/32px double): blur cost grows ~radius², and the
   scale(1.08) lift already sells the elevation. */
.pile:not(.inspecting) .pc:not(.pc--pending):hover .pc-img{filter:drop-shadow(0 14px 16px rgba(0,0,0,.58));}
.pc:active{cursor:grabbing}
.pc:focus:not(:focus-visible){outline:none}   /* no lingering ring after a click-dismissed card... */
.pc:focus-visible{outline:2px solid rgba(240,232,218,.85); outline-offset:3px}   /* ...but REAL keyboard focus stays visible on the dark felt */
.pc.lifted{z-index:50; cursor:zoom-out}  /* above the scrim(40), below the close/nav controls(62) */
.pc.lifted .pc-img{filter:drop-shadow(0 40px 66px rgba(0,0,0,.7))}
/* jpg masters (V15_60): no alpha margin, so the element box must hug the image
   (flex-centered natural height) and the corners/shadow are drawn here. box-shadow
   follows border-radius, and like the drop-shadows above it SNAPS between states —
   never transitioned (same re-raster rule). */
.pc--flat{display:flex; align-items:center; justify-content:center}
.pc-img--flat{height:auto; border-radius:6.6%/4.3%; filter:none; box-shadow:0 8px 12px rgba(0,0,0,.52)}
.pile:not(.inspecting) .pc:not(.pc--pending):hover .pc-img--flat{filter:none; box-shadow:0 14px 16px rgba(0,0,0,.58)}
.pc.lifted .pc-img--flat{filter:none; box-shadow:0 40px 66px rgba(0,0,0,.7)}
/* a card whose composed PNG isn't rendered yet: a non-inspectable placeholder, NEVER the raw photo */
.pc--pending{cursor:default; display:flex; align-items:center; justify-content:center;
  background:rgba(240,232,218,.05); border:1px dashed var(--stamp-frame); border-radius:7px;}
.pc-pending{font-family:'Special Elite',monospace; text-align:center; color:#cdb48f; font-size:.78rem; line-height:1.4; padding:.5rem;}
/* desk flourishes on a couple of cards */
.pc-tape{position:absolute; z-index:5; width:44%; height:12%; top:-5%; left:28%;
  background:rgba(214,196,160,.45); border-left:1px dashed rgba(255,255,255,.4); border-right:1px dashed rgba(255,255,255,.4);
  box-shadow:0 1px 3px rgba(0,0,0,.25); transform:rotate(-3deg);}

/* empty / owner_private state, centred on the desk */
.desk-empty{position:absolute; inset:0; display:flex; flex-direction:column; align-items:center; justify-content:center; gap:.5rem; text-align:center; padding:2rem;}
.desk-empty-penguin{width:92px; height:auto; opacity:.92; filter:drop-shadow(0 6px 12px rgba(0,0,0,.5))}
.desk-empty-title{font-family:'Playfair Display',serif; font-style:italic; font-size:1.5rem; color:#f3e7d2; margin-top:.3rem}
.desk-empty-sub{font-family:'Inter',sans-serif; font-size:.92rem; color:#cdb48f}

/* inspect overlay */
.scrim{position:fixed; inset:0; z-index:40; background:rgba(18,10,6,.62);
  -webkit-backdrop-filter:blur(2.5px); backdrop-filter:blur(2.5px);
  opacity:0; pointer-events:none; transition:opacity .4s ease;}
.scrim.on{opacity:1; pointer-events:auto}
.reader{position:fixed; left:0; right:0; bottom:0; z-index:60; padding:.7rem 1.2rem 1.2rem; text-align:center;
  transform:translateY(120%); transition:transform .45s cubic-bezier(.2,.85,.25,1); pointer-events:none;}
.reader.on{transform:translateY(0)}
.reader-place{font-family:'Playfair Display',serif; font-style:italic; font-weight:600;
  font-size:clamp(1.3rem,4.6vw,2.05rem); color:#f5e9d4; text-shadow:0 2px 8px rgba(0,0,0,.6);}
/* Scales with the viewport like .reader-place above it (Frank: fixed .8rem read too
   small) — 13.6px floor on phones up to ~17px on desktop. */
.reader-meta{font-family:'Special Elite',monospace; font-size:clamp(.85rem,1.9vw,1.05rem); letter-spacing:.05em; color:#e3cfa6; margin-top:.25rem}
.reader-meta b{color:#f0b8a8; font-weight:400}
.nav{position:fixed; top:50%; z-index:62; width:52px; height:52px; transform:translateY(-50%);
  border-radius:50%; border:1px solid rgba(255,255,255,.25); background:rgba(255,255,255,.1); color:#fff;
  font-size:1.5rem; cursor:pointer; opacity:0; pointer-events:none; transition:opacity .35s, background .2s;
  -webkit-backdrop-filter:blur(6px); backdrop-filter:blur(6px);}
.nav.on{opacity:1; pointer-events:auto}
.nav:hover{background:rgba(255,255,255,.22)}
.nav.prev{left:max(14px,3vw)} .nav.next{right:max(14px,3vw)}
.close{position:fixed; top:16px; right:18px; z-index:62; width:44px; height:44px; border-radius:50%;
  border:1px solid rgba(255,255,255,.25); background:rgba(255,255,255,.12); color:#fff; font-size:1.6rem; line-height:1;
  cursor:pointer; opacity:0; pointer-events:none; transition:opacity .35s;}
.close.on{opacity:1; pointer-events:auto}

/* controls */
.deck-bar{position:relative; z-index:6; display:flex; gap:.7rem; justify-content:center; align-items:center;
  padding:.15rem 1rem .9rem; flex-wrap:wrap;}
.btn{font-family:'Playfair Display',serif; font-style:italic; font-weight:500; font-size:.9rem; color:var(--parchment);
  background:rgba(141,45,45,.92); border:1px solid rgba(0,0,0,.2); padding:.5rem 1.15rem; border-radius:999px;
  cursor:pointer; box-shadow:0 4px 12px rgba(0,0,0,.4); transition:transform .15s, background .2s, box-shadow .2s;}
.btn:hover{transform:translateY(-2px); background:var(--maroon-light); box-shadow:0 7px 16px rgba(0,0,0,.5)}
.btn:active{transform:translateY(0)}
/* CTA block: parchment "What is Pebi?" + maroon "Get Pebi" + Free·iOS */
.install-row{position:relative; z-index:6; display:flex; gap:.6rem; justify-content:center; align-items:center; flex-wrap:wrap; padding:.1rem 1rem .15rem;}
.install-cta{display:inline-block; font-family:'Playfair Display',serif; font-style:italic; font-weight:500; font-size:.9rem;
  color:var(--parchment); background:var(--maroon); text-decoration:none; padding:.46rem 1.15rem; border-radius:999px;
  border:1px solid var(--maroon); box-shadow:0 3px 12px rgba(0,0,0,.4); transition:background .2s, transform .15s, box-shadow .2s; white-space:nowrap;}
.install-cta:hover{background:var(--maroon-light); transform:translateY(-2px); box-shadow:0 6px 16px rgba(0,0,0,.5)}
.install-cta.secondary{color:#f0e3cf; background:rgba(240,232,218,.1); border-color:rgba(216,184,120,.4)}
.install-cta.secondary:hover{background:rgba(240,232,218,.2)}
.install-note{font-family:'Inter',sans-serif; font-size:.74rem; color:#cdb48f; opacity:.7; text-align:center}
.foot{position:relative; z-index:6; text-align:center; padding:.25rem 0 .55rem;
  font-family:'Special Elite',monospace; font-size:.64rem; letter-spacing:.08em; color:#a78a64; opacity:.7;}

.toast{position:fixed; left:50%; top:16%; z-index:30; transform:translateX(-50%);
  font-family:'Special Elite',monospace; font-size:.82rem; letter-spacing:.05em; color:#3a2418;
  background:linear-gradient(180deg,#f6efe0,var(--parchment-deep)); padding:.5rem 1rem; border-radius:6px;
  box-shadow:0 6px 18px rgba(0,0,0,.4); border:1px solid var(--stamp-frame);
  opacity:0; transition:opacity .5s; pointer-events:none; rotate:-1.5deg;}
.toast.on{opacity:1}

@media (prefers-reduced-motion:reduce){ .pc,.reader,.scrim,.nav,.close,.toast{transition-duration:.001s !important} }

/* invite page (/i/{token}): one invitation card on the desk — who is inviting, never postcards */
.invite{position:absolute; inset:0; z-index:2; display:flex; align-items:center; justify-content:center; padding:1.25rem}
.invite-card{position:relative; width:100%; max-width:520px; padding:2.2rem 2rem 1.5rem; border-radius:6px; color:var(--text-body);
  background:linear-gradient(180deg,var(--parchment),var(--parchment-deep)); transform:rotate(-1.2deg);
  box-shadow:0 22px 44px rgba(0,0,0,.55), 0 3px 8px rgba(0,0,0,.35)}
.invite-card::before{content:''; position:absolute; inset:10px; border:1.5px solid rgba(141,45,45,.32); border-radius:3px; pointer-events:none}
.invite-stamp{position:absolute; top:20px; right:20px; width:86px; height:102px; padding:7px; background:#fbf6ec; transform:rotate(3deg);
  border:2px dashed var(--stamp-frame); display:flex; align-items:center; justify-content:center; box-shadow:0 2px 6px rgba(0,0,0,.18)}
.invite-stamp img{max-width:100%; max-height:100%; object-fit:contain}
.invite-postmark{position:absolute; top:58px; right:84px; width:96px; opacity:.5; transform:rotate(-14deg); pointer-events:none}
.invite-kicker{font-family:'Special Elite',monospace; font-size:.8rem; letter-spacing:.14em; text-transform:uppercase; color:var(--maroon)}
.invite-title{font-family:'Playfair Display',serif; font-style:italic; font-weight:600; font-size:clamp(1.55rem,5.4vw,2.05rem);
  line-height:1.15; color:var(--brown-title); margin:.55rem 6.8rem 0 0}
.invite-sub{font-size:.95rem; line-height:1.5; margin-top:.9rem}
.invite-address{display:flex; justify-content:space-between; gap:1rem; margin-top:1.4rem; padding-top:.8rem;
  border-top:1px dashed rgba(92,58,42,.35); font-family:'Special Elite',monospace; font-size:.95rem; color:var(--ink)}
@media (max-width:420px){
  .invite-card{padding:1.8rem 1.25rem 1.25rem}
  .invite-stamp{width:66px; height:80px; top:16px; right:16px}
  .invite-postmark{width:72px; top:46px; right:62px}
  .invite-title{margin-right:4.6rem}
}
