/* Shared control primitives for guest components: buttons, link-buttons
   and glass materials. Loaded once before the per-component stylesheets;
   consumes tokens only. */
/* These two base rules travel WITH the components so they stay correct
   in any standalone consumer (the design system previews): author
   display rules beat the UA's [hidden] otherwise, and the controls size
   themselves assuming border-box. app.css repeats both for the shell. */
[hidden] { display: none !important; }
*, *::before, *::after { box-sizing: border-box; }
.btn { font: 700 var(--type-cta)/1.2 var(--font-ui); padding: 15px 22px; border-radius: var(--radius-ctl);
  border: 0; cursor: pointer; -webkit-tap-highlight-color: transparent; min-height: var(--ctl-h); }
.btn.primary { background: linear-gradient(180deg, var(--accent-2), var(--accent));
  color: var(--accent-ink); box-shadow: inset 0 1px 0 var(--cta-edge), var(--shadow-cta); }
.btn.primary:active { background: var(--accent-2); }
.btn.primary[disabled] { opacity: .45; cursor: default; }
.btn.ghost { background: var(--glass-soft); color: var(--ink); border: 1px solid var(--border-ctl); font-weight: 600; }
.btn.ghost:active { background: var(--glass); }
.btn.full { width: 100%; display: block; }
/* Stacked-action rhythm: any full-width action following another gets the
   stack gap automatically, so no consumer can collapse the hierarchy. */
.btn.full + .btn.full, .btn.full + .linklike.center { margin-top: var(--space-xs); }
/* Two quiet actions may now sit under one primary (the camera-roll save, the
   zip beneath it, saving one at a time last). At the 2px below they stacked
   as one blob of underlined text and the second read as a wrapped line of
   the first. Each already carries a full tap target; this gives them a
   visible gap to match. */
.linklike.center + .linklike.center { margin-top: var(--space-xs); }

.linklike { background: none; border: 0; color: var(--ink-3); font: var(--type-note)/1.5 var(--font-ui);
  text-decoration: underline; cursor: pointer; padding: 10px; }
.linklike:hover { color: var(--accent); }
.linklike.center { display: block; margin: 2px auto 0; color: var(--ink); text-decoration: underline;
  text-underline-offset: 4px; text-decoration-color: var(--border-ctl); font-weight: 600; min-height: var(--tap-min); }
.linklike.center:hover { color: var(--accent); text-decoration-color: var(--accent); }

/* Floating glass controls (viewer chrome; iteration 07 rounds 3-4). */
.glass { background: var(--glass); border: 1px solid var(--accent-soft-border);
  color: var(--ink); backdrop-filter: blur(var(--blur-glass)) saturate(var(--glass-saturate));
  box-shadow: inset 0 1px 0 var(--glass-edge); cursor: pointer; font: 600 var(--type-ui)/1 var(--font-ui); }
.glass.pill { padding: 14px 18px; border-radius: var(--radius-pill); min-height: var(--tap-min); }
.glass.round { width: var(--ctl-h); height: var(--ctl-h); border-radius: 50%; font-size: 18px; flex: 0 0 auto; }

.serif { font-family: var(--font-display); font-weight: 500; }

/* Messaging voices (MESSAGING.md, 2026-07-15 handoff). Three speakers,
   told apart at a glance: gold = an offer, quiet gray = a fact, ink + a
   count = the guest's own ledger. Actions are the fourth language
   (glow/border/underline above) and never share a style with these. */
.msg-promo { font: 600 var(--type-note)/1.6 var(--font-ui); color: var(--accent-2); margin: var(--space-2xs) 0 0; }
.msg-status { font: 400 var(--type-note)/1.6 var(--font-ui); color: var(--ink-2); margin: var(--space-2xs) 0 0; }
.msg-ledger { display: flex; justify-content: space-between; font: var(--type-note)/1.6 var(--font-ui);
  color: var(--ink-2); margin: var(--space-2xs) 0 0;
  text-decoration: underline; text-underline-offset: 3px; text-decoration-color: var(--accent-soft-border); }
.msg-ledger .count { color: var(--ink); font-weight: 600; }
