/* Guest site shell, Marquee theme. Tokens live in tokens.css; component
   styles live beside their modules in components/. This file only styles
   the page shell: backdrop, header, display type, landing, search chrome.
   All assets self-hosted, no third-party requests on guest pages. */
* { box-sizing: border-box; }
/* Author display rules must never resurrect hidden elements (the UA's
   [hidden] { display: none } loses to any author display value). */
[hidden] { display: none !important; }
html, body { margin: 0; background: var(--surface); color: var(--ink); font-family: var(--font-ui); min-height: 100%; }

/* Venue ambiance backdrop (sub-identifiable washes). STATIC under the
   blur: the filtered layer rasterizes once; animating anything beneath a
   large blur re-rasterizes every frame and wedges weak GPUs. */
.ambient { position: fixed; inset: 0; opacity: 0; transition: opacity var(--dur-ambient) ease; pointer-events: none;
  filter: blur(34px) saturate(1.25) brightness(.45); transform: scale(1.3); display: flex; flex-wrap: wrap; z-index: 0; }
.ambient.on { opacity: 1; }
.ambient div { width: 50%; height: 33.4%; background-size: cover; background-position: center; }
@keyframes drift { to { transform: scale(1.12) translate(2%, 3%); } }
/* Landing glow when no ambiance is loaded: pre-soft radial gradients need
   no filter, so their transform-only drift stays on the compositor. */
body.glow .ambient { opacity: 1; filter: none; transform: none; }
body.glow .ambient::before { content: ''; position: absolute; width: 85%; height: 45%; left: -10%; top: -8%;
  border-radius: 50%; background: radial-gradient(circle at 40% 40%, rgba(217, 171, 84, .18), rgba(217, 171, 84, 0) 65%);
  animation: drift 14s ease-in-out infinite alternate; }
body.glow .ambient::after { content: ''; position: absolute; width: 90%; height: 50%; right: -18%; bottom: -12%;
  border-radius: 50%; background: radial-gradient(circle at 55% 55%, rgba(143, 0, 71, .24), rgba(143, 0, 71, 0) 62%);
  animation: drift 18s ease-in-out infinite alternate-reverse; }

.screen { position: relative; z-index: 1; max-width: 480px; margin: 0 auto; padding: var(--space-xl) var(--pad-side) var(--space-xl);
  min-height: 100dvh; display: flex; flex-direction: column; }
.top { flex: 0 0 auto; }
.headrow { display: flex; align-items: baseline; justify-content: space-between; min-height: 18px; gap: var(--space-sm); }
/* A site name long enough to wrap (and they do) needs leading, or the two
   uppercase lines close up on each other. min-width lets it take the wrap
   instead of shoving the count. */
.kicker { font: 600 var(--type-kicker)/1.3 var(--font-ui); letter-spacing: var(--kicker-tracking); color: var(--accent); text-transform: uppercase; min-width: 0; }
/* The count is two words that mean one thing: never let it break into "5"
   over "photos". It keeps its width and the name wraps around it. */
.headcount { font: var(--type-note)/1.3 var(--font-ui); color: var(--ink-3); flex: 0 0 auto; white-space: nowrap; }
.headrow:has(.headcount:empty) { justify-content: center; }
.rule { margin: 10px auto var(--space-md); width: 36px; border-bottom: 1px solid var(--accent-soft-border); }

.display { font: 500 var(--type-hero)/1.1 var(--font-display); text-align: center; margin: 26px 0 0; font-weight: 500; }
.display.md { font-size: var(--type-section); margin-top: 10px; }
/* The Delivered moment (iteration 07): the headline rises in, then the
   owned gallery below carries on. */
.display.delivered { animation: delivered-in .7s var(--ease-out) both; }
@keyframes delivered-in { from { opacity: 0; transform: translateY(14px); } }
.sub { font: var(--type-body)/1.55 var(--font-ui); color: var(--ink-2); text-align: center; margin: 14px 0 0; }
.hint { font: var(--type-note)/1.5 var(--font-ui); color: var(--ink-2); text-align: center; margin: var(--space-sm) 0 0; }
.foot { font: var(--type-fine)/1.6 var(--font-ui); color: var(--ink-3); text-align: center; margin-top: auto; padding-top: 28px; }

/* Code entry */
#code-form { margin-top: 30px; }

/* Journey search chrome */
.codechip { margin: var(--space-sm) auto 0; width: max-content; max-width: 100%; padding: 7px var(--space-md);
  border: 1px solid var(--accent-soft-border); border-radius: var(--radius-pill);
  font: var(--type-note)/1 var(--font-mono); color: var(--accent-2); background: var(--glass-soft); }
.narrate { min-height: 22px; text-align: center; font: var(--type-ui)/1.55 var(--font-ui); color: var(--ink-2); margin: 14px 0 0; }
.narrate .count { color: var(--accent-2); font-weight: 600; }
.hairline { height: 2px; border-radius: 1px; background: var(--hairline-wash); margin: var(--space-sm) 26px 0; overflow: hidden; }
.hairline i { display: block; height: 100%; background: var(--accent); border-radius: 1px; width: 30%;
  animation: indet 1.9s ease-in-out infinite; }
.hairline.det i { animation: none; transition: width .8s var(--ease-out); }
@keyframes indet { 0% { margin-left: -30%; } 100% { margin-left: 100%; } }

/* Clearance is MEASURED from the floating tenant (app.js sets
   --dock-clearance); 190px is only the pre-layout fallback. Two things were
   wrong before: one fixed value sized for the SHORTER tenant, and it sat on
   #view-journey while the legal footer lives OUTSIDE that section - so the
   footer had no clearance at all and slid under the dock (UAT 2026-07-22
   finding 3). On the body, every element above the fixed dock clears it. */
body.has-purchasebar { padding-bottom: var(--dock-clearance, 190px); }

.settle { text-align: center; margin-top: 18px; }
.done-note { font: var(--type-note)/1.6 var(--font-ui); color: var(--ink-3); }

/* Two-room bridge (journey pass): a prominent glass control that crosses to
   "your purchased photos" and back. Navigation, never an offer -- neutral ink
   on glass, not gold. */
.roombridge { display: block; width: 100%; margin: var(--space-md) 0 0; min-height: var(--ctl-h);
  padding: 12px 18px; border: 1px solid var(--border-ctl); border-radius: var(--radius-ctl);
  background: var(--glass-strong); color: var(--ink); font: 600 var(--type-cta)/1.2 var(--font-ui);
  letter-spacing: .01em; cursor: pointer; text-align: center;
  -webkit-backdrop-filter: blur(var(--blur-glass)) saturate(var(--glass-saturate));
  backdrop-filter: blur(var(--blur-glass)) saturate(var(--glass-saturate));
  box-shadow: inset 0 1px 0 var(--glass-edge); }
.roombridge[hidden] { display: none; }

/* The reveal moment (journey pass, stage 03): hero + strip, then the
   confirm. Watermarked previews where the photos are still locked. */
#reveal { margin-top: 18px; }
#reveal .rv-hero { width: 100%; aspect-ratio: 3/4; object-fit: cover; border-radius: var(--radius-photo); display: block; }
#reveal .rv-hero.wide { aspect-ratio: 4/3; }
#reveal .rv-grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--gap-grid); margin-top: var(--gap-grid); }
#reveal .rv-grid:empty { display: none; }
#reveal .rv-grid img { width: 100%; aspect-ratio: 4/3; object-fit: cover; border-radius: var(--radius-photo); display: block; }
#reveal .rv-tile { position: relative; display: block; }
/* "+N more" expands the rest in place: a frosted-glass button over the last
   teaser tile. Neutral ink on glass, never gold (gold outside a control = an
   offer). "Some of these aren't mine" only appears once nothing is withheld
   (see renderRevealGrid) -- you cannot judge a set you cannot see. */
#reveal .rv-more { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  border: 0; cursor: pointer; border-radius: var(--radius-photo); color: var(--ink);
  font: 600 var(--type-body)/1 var(--font-ui); letter-spacing: .01em; background: var(--glass-strong);
  -webkit-backdrop-filter: blur(var(--blur-glass)) saturate(var(--glass-saturate));
  backdrop-filter: blur(var(--blur-glass)) saturate(var(--glass-saturate));
  box-shadow: inset 0 1px 0 var(--glass-edge); }
#reveal .rv-actions { margin-top: 20px; display: flex; flex-direction: column; gap: 6px; }

/* Form fields (fresh link + support intake): shell primitives, tokens only. */
.field-label { display: block; font: 600 11px/1 var(--font-ui); letter-spacing: .12em; text-transform: uppercase;
  color: var(--ink-3); margin: 0 0 6px; text-align: left; }
.field-input { width: 100%; min-height: var(--ctl-h); background: var(--surface-2);
  border: 1px solid var(--accent-soft-border); border-radius: var(--radius-ctl); padding: 0 14px;
  font: var(--type-body)/1.3 var(--font-ui); color: var(--ink); }
.field-input:focus { outline: none; border-color: var(--border-ctl); }
.field-input::placeholder { color: var(--ink-3); }
.field-input.mono { font-family: var(--font-mono); letter-spacing: var(--code-tracking); }
.field-input.area { min-height: 76px; padding: 12px 14px; line-height: 1.5; resize: vertical; }
.field-note { margin: 6px 0 0; font: var(--type-fine)/1.5 var(--font-ui); color: var(--ink-3); text-align: left; }
.field-note.center { text-align: center; }
.field-pair { display: flex; gap: var(--space-sm); }
.field-pair > * { flex: 1; min-width: 0; }
.field-pair > .grow { flex: 1.2; }
#view-fresh #fresh-form { margin-top: 22px; display: flex; flex-direction: column; gap: 0; text-align: left; }
#view-fresh #fresh-form .btn { margin-top: 18px; }
#view-fresh .codechip { margin-top: 18px; }
#view-support .sp-fields { margin-top: 22px; display: flex; flex-direction: column; gap: var(--space-md); text-align: left; }

/* Purpose chips: single-select, quiet until chosen. */
.chip-row { display: flex; flex-wrap: wrap; gap: var(--space-xs); justify-content: center; margin-top: 18px; }
.chip { font: 600 var(--type-note)/1 var(--font-ui); color: var(--ink-2); border: 1px solid var(--accent-soft-border);
  border-radius: var(--radius-pill); padding: 12px 16px; background: var(--glass-soft); cursor: pointer;
  min-height: var(--tap-min); -webkit-tap-highlight-color: transparent; }
.chip.sel { color: var(--accent-2); border-color: var(--accent); background: var(--accent-wash); }

/* Kiosk chrome (site-config gated; kiosk look itself is token overrides).
   The scan veil and timeout sheet are isolated device-bound states. */
body.kiosk { --ctl-h: 64px; --type-cta: 20px; --inset-floating: 24px; --type-hero: 52px; --type-body: 17px; --pad-side: 40px; }
body.kiosk .screen { max-width: 640px; }
#scan-veil { position: fixed; inset: 0; z-index: 60; background: var(--surface-viewer); display: flex; flex-direction: column; }
#scan-veil video { flex: 1; width: 100%; object-fit: cover; min-height: 0; }
#scan-veil .scan-actions { padding: var(--space-lg) var(--pad-side) calc(var(--space-lg) + env(safe-area-inset-bottom)); }
#scan-veil .scan-hint { font: var(--type-body)/1.5 var(--font-ui); color: var(--ink-2); text-align: center; margin: 0 0 var(--space-sm); }
#kiosk-timeout { position: fixed; inset: 0; z-index: 70; background: var(--scrim); display: flex; align-items: center; justify-content: center; padding: 40px; }
#kiosk-timeout .kt-card { width: 100%; max-width: 420px; border-radius: var(--radius-card); background: var(--glass-strong);
  backdrop-filter: blur(var(--blur-glass-strong)) saturate(var(--glass-saturate)); border: 1px solid var(--accent-soft-border);
  box-shadow: inset 0 1px 0 var(--glass-edge); padding: 28px 24px; text-align: center; }
#kiosk-timeout .kt-title { font: 500 var(--type-title-lg)/1.2 var(--font-display); color: var(--ink); }
#kiosk-timeout .kt-body { margin: 10px 0 20px; font: var(--type-body)/1.55 var(--font-ui); color: var(--ink-2); }
#kiosk-timeout .kt-actions { display: flex; flex-direction: column; gap: 10px; }

/* Desktop (>= 900px): the journey widens; the dock stays a bottom-center
   card (never a sidebar). Grid columns widen in gallery-grid.css. */
@media (min-width: 900px) {
  .screen { max-width: 1140px; padding-left: 64px; padding-right: 64px; }
  #view-landing, #view-fresh, #view-support, gd-message-view { max-width: 520px; margin-left: auto; margin-right: auto; width: 100%; }
}

@media (prefers-reduced-motion: reduce) {
  .ambient div, body.glow .ambient::before, body.glow .ambient::after { animation: none; }
  .hairline i { animation: none; }
  .display.delivered { animation-duration: 1ms; }
}

/* Legal footer: quiet, never competing with the journey. */
.legal-links {
  text-align: center;
  padding: 20px 16px 28px;
  font-size: 12px;
  opacity: 0.6;
}
.legal-links a { color: inherit; }
