:root {
  --bg-deep: #080704;
  --bg-mid: #151105;
  --parchment-edge: #6f5418;
  --gold: #d7b64a;
  --gold-soft: #a8832e;
  --gold-deep: #8b6914;
  --ink: #2a1f0a;
  --ink-soft: #4a3a18;
  --seal: #8b0000;
  --seal-deep: #5c0808;
  --serif: Georgia, "Times New Roman", "Songti SC", serif;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: radial-gradient(ellipse at 50% 30%, #1f1808 0%, var(--bg-mid) 50%, var(--bg-deep) 100%);
  color: var(--gold);
  font-family: var(--serif);
  min-height: 100%;
  overflow-x: hidden;
}

body {
  min-height: 100vh;
  min-height: 100dvh;
  -webkit-font-smoothing: antialiased;
  -webkit-tap-highlight-color: transparent;
}

#app {
  max-width: 1080px;
  margin: 0 auto;
  padding: clamp(16px, 3vw, 36px) clamp(12px, 3vw, 32px) 48px;
}

button {
  font-family: var(--serif);
  cursor: pointer;
  background: none;
  border: none;
  color: inherit;
}

a { color: var(--gold); text-decoration: none; }
a:hover, a:focus { color: #f1d970; }

/* ─── Promo banner (sampler notice) ──────────────────────────────────── */
.promo-banner {
  background: linear-gradient(180deg, rgba(20, 13, 2, 0.92), rgba(8, 6, 2, 0.92));
  border-bottom: 1px solid rgba(139, 96, 20, 0.45);
  box-shadow: 0 2px 16px rgba(0, 0, 0, 0.5);
  font-family: var(--serif);
}
.promo-inner {
  max-width: 1080px;
  margin: 0 auto;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 10px clamp(12px, 3vw, 24px);
}
.promo-icon img {
  width: 36px;
  height: 36px;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.45);
  display: block;
}
.promo-text {
  flex: 1;
  margin: 0;
  font-size: 13px;
  line-height: 1.4;
  color: #efd789;
}
.promo-text strong { color: var(--gold); font-weight: 700; }
.promo-text-soft { display: block; color: var(--gold-soft); font-size: 12px; margin-top: 2px; }
.promo-ctas { display: flex; gap: 8px; flex-shrink: 0; }
.promo-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 12px;
  font-family: var(--serif);
  font-size: 12px;
  letter-spacing: 0.1em;
  font-weight: 600;
  border-radius: 6px;
  white-space: nowrap;
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.promo-btn:hover { transform: translateY(-1px); }
.promo-btn-ios {
  background: #000;
  border: 1px solid #333;
  color: #fff;
}
.promo-btn-ios:hover { box-shadow: 0 4px 14px rgba(255, 215, 0, 0.18); color: #fff; }
.promo-btn-vanguard {
  background: linear-gradient(180deg, #f1e2b4 0%, #e6cf92 100%);
  border: 1px solid var(--gold-deep);
  color: #2d1a00;
}
.promo-btn-vanguard:hover { color: #2d1a00; }
.promo-seal {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: radial-gradient(circle at 40% 40%, #cc2200, #8B0000);
  color: var(--gold);
  font-size: 11px;
  transform: rotate(-6deg);
}

@media (max-width: 720px) {
  .promo-inner { flex-wrap: wrap; gap: 10px; padding: 9px 12px; }
  .promo-text { flex-basis: 100%; order: 2; }
  .promo-icon { order: 1; }
  .promo-ctas { order: 3; flex-basis: 100%; justify-content: center; }
}
@media (max-width: 380px) {
  .promo-text-soft { display: none; }
}

/* ─── Topbar ─────────────────────────────────────────────────────────── */
.topbar {
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 8px 4px 16px;
  position: relative;
}
.topbar-title {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 2px;
}
.topbar-title:hover, .topbar-title:focus { color: var(--gold); }
.topbar-title .eyebrow {
  font-size: 11px;
  letter-spacing: 0.32em;
  color: var(--gold-soft);
}
.topbar-title .title {
  font-size: clamp(28px, 6vw, 38px);
  letter-spacing: 0.08em;
  color: var(--gold);
}
.topbar-title .chinese-subtitle {
  font-size: 12px;
  letter-spacing: 0.18em;
  color: var(--gold-soft);
  margin-top: 2px;
}

/* ─── Swipe hint ─────────────────────────────────────────────────────── */
.swipe-hint {
  text-align: center;
  font-size: 11px;
  letter-spacing: 0.32em;
  color: var(--gold-soft);
  margin: 4px 0 12px;
  opacity: 0.7;
}

/* ─── Scroll card ────────────────────────────────────────────────────── */
.scroll-card {
  display: block;
  position: relative;
  margin: 0 auto;
  max-width: 820px;
  user-select: none;
  touch-action: pan-y;
  outline: none;
}
.scroll-card .parchment {
  position: relative;
  padding: clamp(28px, 5vw, 56px) clamp(22px, 5vw, 60px) clamp(28px, 5vw, 56px);
  background-image: url("./assets/parchment.png");
  background-size: 100% 100%;
  background-repeat: no-repeat;
  border-radius: 8px;
  box-shadow:
    0 28px 60px rgba(0, 0, 0, 0.6),
    0 0 0 1px rgba(0, 0, 0, 0.25),
    inset 0 0 80px rgba(120, 80, 20, 0.2);
  min-height: clamp(520px, 70vh, 760px);
  overflow: hidden;
}
.chinese-decor {
  position: absolute;
  top: clamp(16px, 2.5vw, 28px);
  right: clamp(14px, 2.5vw, 28px);
  font-size: clamp(14px, 1.6vw, 20px);
  line-height: 1.6;
  color: rgba(139, 0, 0, 0.35);
  letter-spacing: 0;
  font-family: var(--serif);
  text-align: center;
  pointer-events: none;
}

.content-area {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(16px, 2.4vw, 28px);
}

/* image frame */
.image-frame {
  position: relative;
  margin: 8px 0 4px;
  width: 100%;
  display: flex;
  justify-content: center;
}
.image-container {
  position: relative;
  width: clamp(220px, 48vw, 460px);
  aspect-ratio: 1 / 1;
  border-radius: 8px;
  overflow: hidden;
  background: #2a1f0a;
  box-shadow:
    inset 0 0 0 2px rgba(139, 105, 20, 0.5),
    0 12px 32px rgba(0, 0, 0, 0.55);
}
.scroll-image {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  background: #1a1408;
  opacity: 0;
  transition: opacity 240ms ease;
}
.scroll-image.loaded { opacity: 1; }
.image-wash {
  position: absolute; inset: 0;
  background: radial-gradient(ellipse at center, rgba(0,0,0,0) 0%, rgba(20, 16, 6, 0.18) 100%);
  pointer-events: none;
}
.image-shade {
  position: absolute; inset: 0;
  box-shadow: inset 0 0 60px rgba(20, 12, 0, 0.5);
  pointer-events: none;
}

.dragon-divider {
  width: 100%;
  height: 18px;
  background: linear-gradient(90deg, transparent 0%, rgba(139, 0, 0, 0.5) 30%, var(--gold-deep) 50%, rgba(139, 0, 0, 0.5) 70%, transparent 100%);
  mask-image: radial-gradient(ellipse at center, #000 30%, transparent 70%);
  -webkit-mask-image: radial-gradient(ellipse at center, #000 30%, transparent 70%);
  position: relative;
}
.dragon-divider::after {
  content: "❋";
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  font-size: 16px;
  color: var(--seal);
  background: #f0d99b;
  padding: 0 8px;
  border-radius: 50%;
}

.quote-text {
  font-size: clamp(19px, 2.4vw, 28px);
  line-height: 1.55;
  color: var(--ink);
  text-align: center;
  margin: 6px 6px;
  font-style: italic;
  max-width: 28ch;
}
.attribution {
  font-size: clamp(12px, 1.1vw, 14px);
  letter-spacing: 0.2em;
  color: var(--ink-soft);
  text-align: center;
  margin: 0 6px;
}

/* ─── Controls ───────────────────────────────────────────────────────── */
.controls {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  margin-top: 22px;
}
.arrow-btn {
  width: 52px;
  height: 52px;
  border-radius: 50%;
  border: 1px solid var(--gold-deep);
  font-size: 28px;
  color: var(--gold);
  background: rgba(215, 182, 74, 0.05);
  display: flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
}
.arrow-btn:hover, .arrow-btn:focus { background: rgba(215, 182, 74, 0.15); }
.arrow-btn:active { transform: scale(0.96); }
.random-btn {
  padding: 13px 22px;
  font-size: 14px;
  letter-spacing: 0.16em;
  border: 1px solid var(--seal);
  background: linear-gradient(180deg, #a01010 0%, #6b0808 100%);
  color: #f7e6b4;
  border-radius: 4px;
  font-weight: 600;
}
.random-btn:hover, .random-btn:focus { transform: translateY(-1px); }

.action-row {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px;
  margin-top: 14px;
}
.share-btn {
  padding: 10px 18px;
  font-size: 13px;
  letter-spacing: 0.12em;
  border: 1px solid var(--gold-deep);
  border-radius: 4px;
  background: rgba(215, 182, 74, 0.08);
  color: var(--gold);
}
.share-btn:hover { background: rgba(215, 182, 74, 0.18); }

.counter {
  text-align: center;
  font-size: 11px;
  letter-spacing: 0.32em;
  color: var(--gold-soft);
  margin: 24px 0 6px;
}

/* ─── App promo section (replaces stand-alone landing) ───────────────── */
.app-promo {
  background:
    linear-gradient(180deg, rgba(20, 13, 2, 0.85), rgba(8, 6, 2, 0.95)),
    radial-gradient(ellipse at center, rgba(139, 0, 0, 0.18), transparent 70%);
  border-top: 1px solid rgba(139, 96, 20, 0.35);
  border-bottom: 1px solid rgba(139, 96, 20, 0.35);
  padding: 56px 0 64px;
  margin-top: 40px;
}
.app-promo-inner {
  max-width: 920px;
  margin: 0 auto;
  padding: 0 clamp(16px, 4vw, 28px);
  text-align: center;
}
.section-eyebrow {
  font-size: 11px;
  letter-spacing: 0.32em;
  color: var(--gold-soft);
  margin: 0 0 6px;
}
.section-title {
  font-size: clamp(20px, 4.6vw, 26px);
  color: var(--gold);
  margin: 0 0 8px;
  font-weight: 600;
  letter-spacing: 0.02em;
}
.app-promo .section-title {
  font-size: clamp(28px, 5vw, 40px);
  color: var(--gold);
  margin: 0 0 8px;
  font-weight: 900;
  letter-spacing: -0.5px;
  text-shadow: 2px 2px 0 var(--gold-deep);
}
.app-promo-divider {
  display: flex;
  align-items: center;
  gap: 16px;
  margin: 8px auto 26px;
  max-width: 360px;
  color: var(--gold-deep);
}
.app-promo-divider::before, .app-promo-divider::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--gold-deep);
  opacity: 0.55;
}
.app-promo-divider span { color: var(--seal); font-size: 22px; }

.app-promo-banner {
  margin: 0 auto 32px;
  border-radius: 12px;
  overflow: hidden;
  max-width: 720px;
  box-shadow: 0 18px 44px rgba(0, 0, 0, 0.6), 0 0 0 1px rgba(139, 96, 20, 0.4);
}
.app-promo-banner img { width: 100%; display: block; height: auto; }

.app-promo-features {
  list-style: none;
  margin: 0 auto 32px;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 12px;
  text-align: left;
  max-width: 760px;
}
.app-promo-features li {
  padding: 12px 14px;
  border: 1px solid rgba(139, 96, 20, 0.4);
  background: rgba(20, 13, 2, 0.7);
  border-radius: 8px;
  font-size: 13.5px;
  color: #efd789;
  line-height: 1.5;
}
.app-promo-features strong { color: var(--gold); margin-right: 4px; }
.app-promo-features .ap-glyph {
  display: inline-block;
  margin-right: 8px;
  color: #cc2200;
  font-size: 16px;
  width: 18px;
  text-align: center;
}

.app-promo-ctas {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  gap: 14px;
  margin: 12px 0 18px;
}
.store-btn {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  padding: 12px 22px;
  border-radius: 10px;
  background: #000;
  border: 1px solid #333;
  color: #fff;
  font-family: var(--serif);
  transition: transform 0.15s ease, box-shadow 0.15s ease;
  min-width: 180px;
  text-decoration: none;
}
.store-btn:hover {
  transform: translateY(-2px);
  box-shadow: 0 10px 24px rgba(255, 215, 0, 0.18), 0 0 0 1px rgba(255, 215, 0, 0.3);
  color: #fff;
}
.store-btn .stack { display: flex; flex-direction: column; line-height: 1.1; text-align: left; }
.store-btn .sub { font-size: 10px; letter-spacing: 1.5px; text-transform: uppercase; opacity: 0.8; }
.store-btn .label { font-size: 20px; font-weight: 600; letter-spacing: 0.3px; margin-top: 2px; }

.scroll-btn {
  display: inline-flex;
  align-items: center;
  gap: 14px;
  padding: 12px 22px 12px 18px;
  border-radius: 10px;
  background: linear-gradient(180deg, #f1e2b4 0%, #e6cf92 100%);
  border: 1px solid var(--gold-deep);
  color: #2d1a00;
  font-family: var(--serif);
  transition: transform 0.15s ease, box-shadow 0.15s ease;
  min-width: 180px;
  box-shadow: 0 6px 14px rgba(0, 0, 0, 0.45), inset 0 1px 0 rgba(255, 255, 255, 0.4);
  text-decoration: none;
}
.scroll-btn:hover {
  transform: translateY(-2px);
  box-shadow: 0 12px 28px rgba(255, 215, 0, 0.25), 0 0 0 1px var(--gold), inset 0 1px 0 rgba(255, 255, 255, 0.4);
  color: #2d1a00;
}
.scroll-btn-seal {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: radial-gradient(circle at 40% 40%, #cc2200, #8B0000);
  border: 2px solid #6b0000;
  color: var(--gold);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 18px;
  flex-shrink: 0;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.4);
  transform: rotate(-6deg);
}
.scroll-btn .stack { display: flex; flex-direction: column; line-height: 1.1; text-align: left; }
.scroll-btn .sub {
  font-size: 10px;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: #6b4a10;
  opacity: 0.9;
}
.scroll-btn .label {
  font-size: 18px;
  font-weight: 700;
  letter-spacing: 0.3px;
  margin-top: 3px;
  color: #2d1a00;
}

.app-promo-note {
  font-style: italic;
  font-size: 15px;
  color: #efd789;
  margin: 18px auto 0;
  max-width: 480px;
  line-height: 1.55;
}
.app-promo-note .attr {
  display: block;
  font-style: normal;
  font-size: 11px;
  letter-spacing: 4px;
  color: var(--gold-soft);
  text-transform: uppercase;
  margin-top: 10px;
}

/* ─── Site footer ────────────────────────────────────────────────────── */
.site-footer {
  padding: 40px 24px 48px;
  border-top: 1px solid rgba(139, 96, 20, 0.2);
  text-align: center;
  color: #6b5020;
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  font-family: var(--serif);
}
.site-footer .parody-disclaimer {
  font-style: italic;
  text-transform: none;
  letter-spacing: 0;
  font-size: 12px;
  color: var(--gold-soft);
  opacity: 0.7;
  margin: 0 auto 14px;
  max-width: 540px;
  line-height: 1.55;
}
.site-footer .footer-line {
  margin: 8px 0 12px;
  color: var(--gold-soft);
  letter-spacing: 0.18em;
}
.site-footer .footer-links a {
  color: var(--gold-deep);
  margin: 0 10px;
  font-size: 11px;
  letter-spacing: 0.18em;
}
.site-footer .footer-links a:hover { color: var(--gold); }

/* ─── Toast ──────────────────────────────────────────────────────────── */
.toast {
  position: fixed;
  bottom: 24px;
  left: 50%;
  transform: translateX(-50%);
  background: rgba(15, 11, 4, 0.96);
  color: var(--gold);
  border: 1px solid var(--gold-deep);
  padding: 10px 18px;
  border-radius: 4px;
  font-size: 13px;
  letter-spacing: 0.12em;
  z-index: 80;
  animation: toastUp 200ms ease;
  pointer-events: none;
}
@keyframes toastUp { from { transform: translate(-50%, 8px); opacity: 0; } to { transform: translate(-50%, 0); opacity: 1; } }

@media (max-width: 540px) {
  #app { padding: 10px 10px 56px; }
  .scroll-card .parchment { padding: 22px 16px 18px; min-height: 480px; }
  .topbar-title .title { font-size: 30px; }
  .quote-text { max-width: none; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

/* ─── Ask Don Tzu — live-page pop-out overlay ────────────────────────── */
/*
   Closed: a compact FAB at bottom-left (Don avatar + "ASK DON TZU" label).
   Open:   Don and a parchment speech bubble float above the current page.
           The bubble sits above/right of Don with the embedded prompt inside
           the safe area of the bubble art.

   The FAB is the entry point and remains in `.ask-widget` (a fixed-position
   layer that stays out of the document flow). When the widget enters the
   "open" state, the overlay underneath spans the full viewport.
*/
.ask-widget {
  position: fixed;
  left: clamp(12px, 2vw, 24px);
  bottom: clamp(12px, 2vw, 24px);
  z-index: 9999;
  font-family: var(--serif);
}

/* ── FAB ── */
.ask-fab {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 6px 16px 6px 6px;
  background: linear-gradient(180deg, rgba(43, 30, 6, 0.95) 0%, rgba(20, 14, 3, 0.98) 100%);
  border: 1px solid rgba(168, 131, 46, 0.7);
  border-radius: 999px;
  box-shadow:
    0 8px 24px rgba(0, 0, 0, 0.55),
    inset 0 1px 0 rgba(247, 215, 137, 0.18);
  cursor: pointer;
  appearance: none;
  font-family: inherit;
  color: #f1d970;
  transition: transform 0.12s ease, filter 0.15s ease, box-shadow 0.15s ease;
}
.ask-fab:hover { filter: brightness(1.08); }
.ask-fab:active { transform: translateY(1px); }
.ask-fab:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 3px;
}

.ask-fab-pose-wrap {
  width: 44px; height: 44px;
  border-radius: 50%;
  overflow: hidden;
  border: 2px solid rgba(168, 131, 46, 0.85);
  background: rgba(8, 6, 2, 0.6);
  flex: 0 0 auto;
  display: block;
}
.ask-fab-pose {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
}

.ask-fab-label {
  font-size: 14px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-weight: 700;
  color: #f1d970;
  white-space: nowrap;
}

/* Subtle pulse to draw the eye on first paint. Hidden once opened. */
.ask-fab-pulse {
  position: absolute;
  inset: -2px;
  border-radius: 999px;
  border: 2px solid rgba(215, 182, 74, 0.65);
  pointer-events: none;
  animation: ask-fab-pulse 2.4s ease-out infinite;
  opacity: 0;
}
@keyframes ask-fab-pulse {
  0%   { transform: scale(1);    opacity: 0.65; }
  70%  { transform: scale(1.18); opacity: 0; }
  100% { transform: scale(1.18); opacity: 0; }
}
.ask-widget[data-state="open"] .ask-fab-pulse { display: none; }
.ask-widget[data-state="open"] .ask-fab { filter: brightness(0.92); }

/* On phones, drop the label so the FAB is just an avatar circle. */
@media (max-width: 480px) {
  .ask-fab { padding: 4px; gap: 0; }
  .ask-fab-label { display: none; }
  .ask-fab-pose-wrap { width: 52px; height: 52px; }
}

/* ── Pop-out overlay ──
   The redesign: Don's character + a speech bubble grow out of the FAB and
   sit on top of the live page. There is NO full-screen "stage", parchment
   background, gold corners, or page header. The page stays visible through
   a very light scrim so the popup feels integrated, not modal. */
.ask-overlay {
  position: fixed;
  inset: 0;
  z-index: 9998;             /* one below .ask-widget so the FAB stays clickable */
  pointer-events: none;      /* let clicks fall through everywhere except the
                                explicit interactive children below */
  animation: ask-overlay-in 0.22s ease;
}
.ask-overlay[hidden] { display: none; }
@keyframes ask-overlay-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* Light scrim — feathered radial gradient so the popup feels grown out of
   the page (warm glow under bottom-left where the FAB lives) rather than
   sitting on top of an opaque dark sheet. The corners stay near-clear so
   the parchment page is visible and the popup "connects to the back".
   Click-to-close is handled by JS on this layer. */
.ask-backdrop {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(ellipse 70% 60% at 18% 88%,
      rgba(255, 213, 130, 0.13) 0%,
      rgba(60, 30, 5, 0.20) 42%,
      rgba(8, 5, 1, 0.08) 74%,
      rgba(8, 5, 1, 0.02) 100%);
  backdrop-filter: blur(0.6px);
  pointer-events: auto;      /* but the backdrop itself is clickable to close */
  cursor: pointer;
}

/* The pop-out is composed like a comic panel: Don anchors the lower-left,
   while the speech bubble starts near his mouth and expands upward/right. */
.ask-popup {
  position: absolute;
  left: clamp(16px, 2vw, 32px);
  bottom: clamp(16px, 2vw, 32px);
  width: min(92vw, 660px);
  height: min(76vh, 520px);
  min-height: 360px;
  pointer-events: auto;
  /* Grow from the bottom-left corner so the animation feels like it
     emerges from the FAB rather than dropping in from above. */
  transform-origin: bottom left;
  animation: ask-popup-in 0.32s cubic-bezier(0.16, 1, 0.3, 1);
}
@keyframes ask-popup-in {
  from { opacity: 0; transform: translateY(20px) scale(0.7); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}

/* Don's figure — tall transparent PNG floating free, no card / parchment
   behind it. Just the character on the page with a soft drop shadow.

   IMPORTANT (anti-distortion): the bounding box lives on the FIGURE; the
   <img> fills it via `object-fit: contain`. If we put the size constraints
   on the <img> directly (height + max-width), narrowing the viewport
   clamps the rendered width while height stays fixed, which squishes Don.
   Putting both constraints on the figure and letting the img scale inside
   keeps aspect ratio correct at every viewport size. */
.ask-don-figure {
  position: absolute;
  left: 0;
  bottom: 0;
  margin: 0;
  display: flex;
  align-items: flex-end;
  width: clamp(170px, 20vw, 260px);
  height: clamp(260px, 43vh, 400px);
  position: relative;
  z-index: 1;
}
.ask-don-pose {
  width: 100%;
  height: 100%;
  object-fit: contain;
  object-position: bottom center;
  display: block;
  filter: drop-shadow(0 14px 30px rgba(0, 0, 0, 0.55));
}
@media (max-width: 720px) {
  .ask-popup {
    left: clamp(8px, 2vw, 16px);
    right: clamp(8px, 2vw, 16px);
    bottom: clamp(8px, 2vw, 16px);
    width: auto;
    height: min(72vh, 560px);
    min-height: 430px;
  }
  .ask-don-figure {
    width: clamp(150px, 40vw, 210px);
    height: clamp(240px, 38vh, 320px);
  }
}

/* Close button — wax-seal disc sitting just outside the speech bubble. */
.ask-close {
  position: absolute;
  top: -14px;
  right: -12px;
  appearance: none;
  background: linear-gradient(180deg, #a8181a 0%, #6e0d0e 100%);
  border: 2px solid #c79a3d;
  color: #f5e29a;
  font-size: 18px;
  font-weight: 700;
  line-height: 1;
  width: 30px; height: 30px;
  border-radius: 50%;
  cursor: pointer;
  z-index: 5;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow:
    0 2px 6px rgba(0, 0, 0, 0.45),
    inset 0 1px 0 rgba(255, 255, 255, 0.25);
  transition: background 0.15s ease, color 0.15s ease, transform 0.1s ease, filter 0.15s ease;
}
.ask-close:hover  { filter: brightness(1.15); color: #fff5cf; }
.ask-close:active { transform: scale(0.92); }

/* Speech bubble — a wider comic-style parchment panel. The welcome prompt is
   deliberately more rectangular than the old portrait art so the copy, input,
   and submit button sit inside a predictable safe area. */
.ask-bubble {
  position: absolute;
  left: clamp(130px, 18vw, 214px);
  bottom: clamp(178px, 26vh, 258px);
  width: clamp(310px, 35vw, 430px);
  /* min-height (not height) so the parchment frame grows to contain its
     content. Earlier this was a fixed `height: clamp(...)` which clipped
     the DECREE button when the textarea placeholder wrapped to 2 lines
     on mobile after we bumped its font-size to 16px (iOS auto-zoom fix). */
  min-height: clamp(290px, 42vh, 340px);
  max-width: calc(100vw - 168px);
  margin: 0;
  padding:
    clamp(26px, 3vw, 36px)
    clamp(24px, 3.2vw, 38px)
    clamp(24px, 3vw, 34px);
  z-index: 2;
  isolation: isolate;
  color: #2a1f0a;
  font-family: var(--serif);
  background: transparent;
  border: 0;
  outline: none;
  border-radius: 30px 34px 28px 32px;
  overflow: visible;
  -webkit-overflow-scrolling: touch;
}
.ask-bubble::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  border-radius: inherit;
  background:
    linear-gradient(180deg, rgba(255, 239, 191, 0.90), rgba(244, 211, 137, 0.80)),
    url("./assets/parchment.png");
  background-size: 100% 100%, 120% 120%;
  background-position: center;
  border: 2px solid rgba(197, 151, 45, 0.86);
  box-shadow:
    0 18px 34px rgba(0, 0, 0, 0.50),
    0 0 24px rgba(199, 154, 61, 0.22),
    inset 0 0 0 2px rgba(92, 55, 12, 0.45),
    inset 0 0 38px rgba(120, 72, 12, 0.18);
}
.ask-bubble::after {
  content: "";
  position: absolute;
  left: -30px;
  bottom: clamp(92px, 37%, 132px);
  width: 42px;
  height: 34px;
  z-index: 0;
  pointer-events: none;
  background:
    linear-gradient(135deg, rgba(255, 239, 191, 0.91), rgba(244, 211, 137, 0.80)),
    url("./assets/parchment.png");
  background-size: 100% 100%, 170% 170%;
  border-left: 2px solid rgba(197, 151, 45, 0.86);
  border-bottom: 2px solid rgba(197, 151, 45, 0.86);
  clip-path: polygon(0 48%, 100% 0, 100% 100%);
  filter: drop-shadow(-6px 7px 9px rgba(0, 0, 0, 0.28));
}

/* Result mode keeps the SAME comic-bubble silhouette as the welcome view —
   user requested visual uniformity ("everything needs to be inside the
   bubble, beautifully like in the question bubble"). The bubble grows
   taller to host the question + decree + scroll-ref, and shifts down a
   touch to accommodate the extra height while still pointing at Don's
   mouth. The action buttons (Ask another / Get the App) live OUTSIDE this
   bubble in `.ask-floating-actions` — so this parchment shows ONLY the
   speech, like a clean comic panel. */
.ask-bubble:has(.ask-result:not([hidden])) {
  left: clamp(130px, 18vw, 214px);
  /* Sits a touch higher than welcome to leave a clear gap for the floating
     action row below it (which is anchored to bottom: 28-56px). */
  bottom: clamp(190px, 26vh, 264px);
  width: clamp(320px, 36vw, 440px);
  /* min-height not height — same reasoning as welcome bubble. Long answers
     should grow the parchment instead of overflowing it. */
  min-height: clamp(310px, 44vh, 380px);
  padding:
    clamp(28px, 3.4vw, 40px)
    clamp(26px, 3.4vw, 40px)
    clamp(24px, 3vw, 32px);
}

@media (max-width: 720px) {
  .ask-bubble {
    left: clamp(98px, 27vw, 124px);
    bottom: clamp(205px, 27vh, 236px);
    width: min(260px, calc(100vw - 112px));
    /* min-height with a slight bump (+22px on the lower bound) — accommodates
       the placeholder wrapping to 2 lines under the 16px touch font-size. */
    min-height: clamp(292px, 38vh, 332px);
    max-width: none;
    padding:
      clamp(20px, 5.5vw, 26px)
      clamp(18px, 5vw, 24px)
      clamp(18px, 5vw, 24px);
    border-radius: 24px 28px 24px 28px;
  }
  .ask-bubble::after {
    left: -24px;
    bottom: 116px;
    width: 34px;
    height: 28px;
  }
  .ask-bubble:has(.ask-result:not([hidden])) {
    left: clamp(98px, 27vw, 124px);
    bottom: clamp(220px, 30vh, 260px);
    width: min(280px, calc(100vw - 112px));
    /* min-height not height — long answers should grow the parchment. */
    min-height: clamp(280px, 36vh, 320px);
    padding:
      clamp(20px, 5.5vw, 26px)
      clamp(18px, 5vw, 24px)
      clamp(18px, 5vw, 24px);
  }
  .ask-don-figure {
    width: clamp(145px, 39vw, 190px);
    height: clamp(235px, 37vh, 310px);
  }
  .ask-result { gap: 10px; }
  .ask-divider { height: 14px; margin: 2px 0; }
}

.ask-bubble-content {
  position: relative;
  z-index: 1;
  display: block;
  padding-right: 0;
  width: 100%;
  height: 100%;
  max-height: 100%;
  overflow: hidden;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  scrollbar-color: rgba(111, 84, 24, 0.45) transparent;
}
.ask-bubble-content[data-mode="result"] { overflow-y: auto; }

/* The HTML `hidden` attribute must beat the explicit display rules below.
   Without this, .ask-result { display: flex } overrides [hidden] and the
   result section leaks into the welcome view (and vice versa). */
.ask-welcome[hidden],
.ask-result[hidden] { display: none !important; }

/* ── Welcome mode (default) ── */
.ask-welcome {
  min-height: 100%;
  display: flex;
  flex-direction: column;
}
.ask-welcome-text {
  margin: 0 auto 18px;
  max-width: 27ch;
  font-size: clamp(15px, 1.45vw, 19px);
  line-height: 1.32;
  color: #2a1f0a;
  text-align: center;
  text-wrap: balance;
}
.ask-welcome-text em {
  display: block;
  margin-top: 8px;
  color: var(--seal-deep);
  font-size: 1.08em;
  font-style: italic;
}

/* Stacked form: textarea pill on top, full-width DECREE submit below.
   Mirrors the mobile FAB layout — the primary action is a labelled pill
   ("✦ DECREE ›") rather than a tiny circular icon, so first-time users
   don't have to hunt for the submit affordance. */
.ask-form {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: auto;
}

.ask-input-row {
  /* Now contains only the textarea — the submit button moved outside.
     Kept as a wrapper to preserve the bordered "input pill" look and
     the focus-within ring that surrounds the typing area. */
  display: flex;
  align-items: stretch;
  width: 100%;
  background: rgba(255, 252, 235, 0.76);
  border: 1px solid rgba(111, 84, 24, 0.52);
  border-radius: 12px;
  padding: 5px;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.36);
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.ask-input-row:focus-within {
  border-color: var(--seal-deep);
  box-shadow: 0 0 0 3px rgba(139, 0, 0, 0.15);
}

.ask-input {
  flex: 1;
  min-width: 0;
  resize: none;
  min-height: 42px;
  max-height: 96px;
  padding: 8px 9px;
  font-family: var(--serif);
  font-size: clamp(12.5px, 1vw, 14px);
  line-height: 1.35;
  color: #2a1f0a;
  background: transparent;
  border: 0;
  outline: none;
  box-sizing: border-box;
}
.ask-input::placeholder { color: rgba(80, 50, 12, 0.55); font-style: italic; }

/* iOS Safari (and any touch browser) auto-zooms an input on focus when its
   computed font-size is < 16px. The clamp above caps at 14px for desktop
   typography, which triggers the zoom on iPhone/iPad. Force 16px only on
   coarse-pointer devices so desktop layout stays unchanged but the keyboard
   never causes the parchment to zoom in.
   We deliberately do NOT use `maximum-scale=1` / `user-scalable=no` on the
   viewport meta — that would also block pinch-zoom and fails WCAG 2.1 SC 1.4.4. */
@media (pointer: coarse) {
  .ask-input {
    font-size: 16px;
  }
}

.ask-submit {
  appearance: none;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  width: 100%;
  padding: 12px 18px;
  font-family: var(--serif);
  font-size: clamp(13px, 1.05vw, 15px);
  font-weight: 700;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: #fff5cf;
  background: linear-gradient(180deg, #a8181a 0%, #6e0d0e 100%);
  border: 1px solid #4a0708;
  border-radius: 999px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.18);
  cursor: pointer;
  transition: transform 0.08s ease, filter 0.15s ease;
}
.ask-submit:hover  { filter: brightness(1.08); }
.ask-submit:active { transform: scale(0.985); }
.ask-submit:disabled { opacity: 0.55; cursor: not-allowed; filter: grayscale(0.5); }
.ask-submit-icon {
  font-size: 14px;
  line-height: 1;
  color: #fff;
  text-shadow: 0 0 6px rgba(255, 230, 150, 0.55);
}
.ask-submit-label {
  /* letter-spacing + uppercase inherited from .ask-submit */
  line-height: 1;
}
.ask-submit-arrow {
  font-size: 18px;
  font-weight: 700;
  line-height: 1;
  margin-top: -1px; /* optical centering with the cap-height of DECREE */
}

.ask-status {
  display: block;
  text-align: center;
  font-size: 12px;
  color: var(--seal-deep);
  font-style: italic;
  min-height: 18px;
}

/* Free-feature / AI / no-PII disclaimer below the DECREE pill. Subdued so
   it never competes with the input or the avatar's voice — but always
   present so we have a consistent in-context disclosure to point at. */
.ask-disclaimer {
  margin: 8px 2px 0;
  text-align: center;
  font-size: 10.5px;
  line-height: 1.35;
  color: rgba(80, 50, 12, 0.62);
  font-style: italic;
  letter-spacing: 0.1px;
}
@media (max-width: 720px) {
  .ask-disclaimer {
    font-size: 10px;
    margin-top: 6px;
  }
}

@media (max-width: 720px) {
  .ask-welcome-text {
    font-size: clamp(14px, 4.2vw, 17px);
    line-height: 1.28;
    margin-bottom: 14px;
  }
}

/* Discreet floating chip anchored to the popup. Visible only when localStorage
   carries a bypass token, so production users never see it. */
.ask-dev-badge {
  position: absolute;
  top: -10px;
  left: -8px;
  padding: 2px 7px;
  font-size: 9px;
  letter-spacing: 0.22em;
  color: rgba(241, 217, 112, 0.78);
  background: rgba(8, 6, 2, 0.7);
  border: 1px solid rgba(168, 131, 46, 0.5);
  border-radius: 3px;
  text-transform: uppercase;
  font-weight: 700;
  z-index: 3;
  pointer-events: none;
  font-family: var(--serif);
}
.ask-dev-badge[hidden] { display: none; }

/* ── Result mode ──
   Designed to read as SPEECH, not a document. The bubble silhouette already
   declares Don as the speaker, so we drop "DON TZU'S DECREE" labels and
   "— DON TZU" attributions — they'd be redundant inside a speech bubble.
   The user's question appears as a tiny dim italic at the top (like a
   remembered prompt). The decree is the HERO — big centered italic, mirroring
   the welcome line's typographic hierarchy so the eye lands the same way
   on welcome→result handover. Quote length is capped server-side
   (system_prompt.ts softTruncateQuote) so the answer always fits. */
.ask-result {
  min-height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: clamp(10px, 1.6vh, 14px);
  text-align: center;
}
.ask-question-echo {
  margin: 0;
  max-width: 32ch;
  font-size: clamp(11px, 1.15vw, 12.5px);
  line-height: 1.30;
  font-style: italic;
  color: rgba(74, 56, 18, 0.78);
  text-align: center;
  /* Quote-marked so the eye reads it as "what you asked", not as more decree. */
  text-wrap: balance;
}
.ask-question-echo::before { content: "“"; opacity: 0.55; }
.ask-question-echo::after  { content: "”"; opacity: 0.55; }
/* The HERO line — Don's decree. Sized and weighted to match the welcome
   text's visual gravity so welcome → result feels like the same voice
   continuing, not a switch from speech to document. */
.ask-quote {
  margin: 0;
  max-width: 28ch;
  font-size: clamp(15px, 1.55vw, 19px);
  line-height: 1.34;
  font-style: italic;
  color: #2a1f0a;
  text-align: center;
  text-wrap: balance;
}

/* In-voice scroll-ref footer: reads as a sentence Don is muttering, not as a
   stamped button. The link itself is just an underlined number sitting inside
   the prose, like a footnote rendered as part of the speech. JS rotates the
   prose phrasing per-render so it doesn't feel boilerplate. */
.ask-scroll-ref-line {
  margin: 4px 0 0;
  padding: 0;
  max-width: 32ch;
  font-size: clamp(11px, 1.1vw, 12.5px);
  line-height: 1.35;
  color: rgba(74, 56, 18, 0.85);
  font-style: italic;
  text-align: center;
  text-wrap: balance;
}
.ask-scroll-ref-line[hidden] { display: none; }
.ask-scroll-ref-prose { white-space: normal; }

/* Scroll-coin badge — the affordance for the inline scroll reference.
   Reads as a parchment-and-gold catalog chip, distinct from primary CTAs
   (red wax-seal pills) so it doesn't compete for the eye. The chip makes
   it unambiguous that the number is tappable, while preserving the
   "footnote in a sentence" register of the surrounding italic prose. */
.ask-scroll-ref {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  margin: 0 4px;
  padding: 2px 8px;
  min-height: 22px;
  border: 1px solid var(--gold-deep);
  border-radius: 999px;
  background: #fff8e0;
  color: var(--ink);
  font-style: normal;
  text-decoration: none;
  font-weight: 700;
  letter-spacing: 0.02em;
  white-space: nowrap;
  cursor: pointer;
  vertical-align: baseline;
  transition: border-color 120ms ease, transform 80ms ease, color 120ms ease;
}
.ask-scroll-ref:hover {
  border-color: var(--gold);
  color: var(--seal-deep);
}
.ask-scroll-ref:active {
  transform: scale(0.96);
  border-color: var(--seal-deep);
}
.ask-scroll-ref:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
}
.ask-scroll-coin-glyph {
  font-size: 11px;
  line-height: 1;
  color: var(--ink-soft);
}
.ask-scroll-ref-number {
  font-style: normal;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.04em;
}

.ask-result-meta {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 14px;
}
.ask-cached-badge {
  font-size: 10px;
  letter-spacing: 0.14em;
  color: var(--seal-deep);
  text-transform: uppercase;
  padding: 3px 7px;
  border: 1px dashed rgba(111, 84, 24, 0.5);
  border-radius: 4px;
}

/* ── Floating action row (OUTSIDE the bubble, horizontal under it) ──
   Anchored just below the bubble's bottom edge, side-by-side, so the eye
   reads bubble → actions in a single vertical sweep. NOT stacked vertically
   (user feedback: "horizontally next to each other rather than stacked").
   Hidden in welcome mode; revealed when the bubble flips to result. Buttons
   use temple-aesthetic styling but read as actions, not as part of speech.
   The horizontal anchor is right-aligned so the row sits under the bubble's
   right side (where the bubble lives in the popup), not under Don. */
.ask-floating-actions {
  position: absolute;
  /* Lines up under the bubble — same `left` floor as `.ask-bubble:has(...)`
     so the actions sit directly beneath the speech, not centered under the
     whole popup (which would put them under Don). The row sits BELOW the
     bubble with a small ~17px breathing gap — close enough to feel
     connected to the parchment, NOT attached. Bubble bottom edge is at
     clamp(190px, 26vh, 264px); buttons (~46px tall) anchored at
     clamp(130px, 20vh, 200px) leaves ~14–18px of clean gap. */
  left: clamp(130px, 18vw, 214px);
  right: clamp(8px, 2vw, 24px);
  bottom: clamp(130px, 20vh, 200px);
  display: flex;
  flex-direction: row;
  align-items: stretch;
  justify-content: center;
  gap: 12px;
  z-index: 3;
  pointer-events: auto;
  opacity: 0;
  transform: translateY(6px);
  visibility: hidden;
  transition:
    opacity 0.22s ease,
    transform 0.22s ease,
    visibility 0s linear 0.22s;
}
.ask-floating-actions[data-mode="result"] {
  opacity: 1;
  transform: translateY(0);
  visibility: visible;
  transition:
    opacity 0.28s ease 0.05s,
    transform 0.28s cubic-bezier(0.16, 1, 0.3, 1) 0.05s,
    visibility 0s;
}

/* Shared button geometry: rounded parchment tablets with a gold rim and a
   subtle inset highlight so they feel like solid carved pieces rather than
   flat web buttons. Equal flex so both halves of the row weigh the same. */
.ask-again-btn,
.ask-cta-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  flex: 1 1 0;
  min-width: 0;
  padding: 9px 14px;
  font-family: var(--serif);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.04em;
  border-radius: 10px;
  cursor: pointer;
  text-decoration: none;
  text-align: center;
  line-height: 1.15;
  border: 1px solid var(--gold-deep);
  box-shadow:
    0 6px 14px rgba(0, 0, 0, 0.40),
    inset 0 1px 0 rgba(255, 255, 255, 0.30);
  transition: transform 0.12s ease, filter 0.15s ease, box-shadow 0.15s ease;
}
.ask-again-btn:hover,
.ask-cta-btn:hover {
  transform: translateY(-1px);
  filter: brightness(1.06);
  box-shadow:
    0 10px 22px rgba(0, 0, 0, 0.45),
    inset 0 1px 0 rgba(255, 255, 255, 0.35);
}
.ask-again-btn:active,
.ask-cta-btn:active { transform: translateY(0); }

/* "Ask another" — wax-seal red, the active/default action. */
.ask-again-btn {
  color: #fff5cf;
  background: linear-gradient(180deg, #b21d1f 0%, #6e0d0e 100%);
  border-color: #4a0708;
}
.ask-again-btn:hover { color: #fff5cf; }

/* "Get the App" — parchment-and-gold, the secondary pitch. */
.ask-cta-btn {
  color: #1a0f00 !important;
  background:
    linear-gradient(180deg, #f1e2b4 0%, #e0c178 60%, #b58a26 100%),
    url("./assets/parchment.png");
  background-size: 100% 100%, 200% 200%;
  background-blend-mode: multiply;
  border-color: #6f5418;
}
.ask-cta-btn:hover { color: #1a0f00 !important; }

/* Emblem: gold-rimmed circular medallion at the start of each tablet —
   matches the temple/heraldic look from the reference image (cream disc,
   gold border, single bold glyph). The two button variants flip the
   colorway so the emblem reads as a contrasting seal against its tablet
   (cream-on-red for "ask another", red-on-cream for "download"). */
.ask-btn-emblem {
  flex: 0 0 auto;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
  /* Default (overridden per-button below) — neutral gold disc. */
  background: linear-gradient(180deg, #f6e6b8 0%, #d8b96a 100%);
  border: 1.5px solid var(--gold-deep);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.45),
    0 1px 3px rgba(0, 0, 0, 0.40);
}
.ask-btn-emblem-glyph {
  font-size: 15px;
  font-weight: 700;
  line-height: 1;
  color: #2d1a00;
  font-family: var(--serif);
  /* Pull the glyph up by a hair — the serif "?" sits low otherwise. */
  margin-top: -1px;
}

/* "Ask another" (red tablet) → cream emblem with deep-red glyph. */
.ask-again-btn .ask-btn-emblem {
  background: linear-gradient(180deg, #f6e6b8 0%, #d8b96a 100%);
  border-color: #6f5418;
}
.ask-again-btn .ask-btn-emblem-glyph { color: #6e0d0e; }

/* "Download the app" (parchment tablet) → deep-red emblem with cream glyph. */
.ask-cta-btn .ask-btn-emblem {
  background: radial-gradient(circle at 38% 35%, #c41618 0%, #8b0000 60%, #5c0808 100%);
  border-color: #4a0708;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.18),
    0 1px 3px rgba(0, 0, 0, 0.45);
}
.ask-cta-btn .ask-btn-emblem-glyph { color: #f5e29a; }

.ask-btn-label {
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.04em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

@media (max-width: 720px) {
  /* On mobile the popup is more compact — actions sit BELOW the bubble
     with a small ~15px gap (mobile bubble is at bottom: 220-260px;
     anchoring the row at 165-210px leaves a snug breathing gap). */
  .ask-floating-actions {
    left: clamp(98px, 27vw, 124px);
    right: clamp(8px, 2vw, 16px);
    bottom: clamp(165px, 22vh, 210px);
    flex-direction: row;
    gap: 8px;
  }
  .ask-again-btn,
  .ask-cta-btn {
    padding: 8px 10px;
    font-size: 12px;
    gap: 7px;
  }
  .ask-btn-emblem { width: 24px; height: 24px; }
  .ask-btn-emblem-glyph { font-size: 12px; }
  .ask-btn-label { font-size: 12px; }
}

/* ── Turnstile container — only shows if Cloudflare needs an interaction. ──
   Anchored above the bubble so a real challenge appears next to the popup,
   not in some far corner of the page. */
.ask-turnstile {
  position: absolute;
  top: -78px;
  right: 0;
  min-height: 0;
  z-index: 2;
}
.ask-turnstile:not(:empty) { min-height: 65px; }

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0,0,0,0);
  white-space: nowrap; border: 0;
}

/* The popup is non-modal — we deliberately do NOT lock body scroll. The page
   stays interactable behind the light scrim; clicking the scrim closes. */

/* Toast for share/copy feedback (lifted above the FAB so it's not occluded). */
.toast {
  position: fixed;
  left: 50%;
  bottom: 96px;
  transform: translateX(-50%);
  z-index: 10000;
  padding: 10px 16px;
  background: rgba(20, 14, 3, 0.95);
  color: #f1d970;
  border: 1px solid rgba(168, 131, 46, 0.55);
  border-radius: 6px;
  font-family: var(--serif);
  font-size: 13px;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.55);
}
.toast[hidden] { display: none; }
