/* ═══════════════════════════════════════════════
   CyberColt Photobooth — booth (kiosk) styles
   Portrait-first. Large touch targets.
   ═══════════════════════════════════════════════ */

:root {
  --cc-lime:      #ACCA32;
  --cc-lime-hot:  #C4E64A;
  --cc-graphite:  #1B1D22;
  --cc-graphite-2:#232631;
  --cc-graphite-3:#2C303B;
  --cc-cream:     #F2F4EE;
  --cc-cream-mid: rgba(242,244,238,0.7);
  --cc-cream-dim: rgba(242,244,238,0.45);
  --cc-gold:      #E5C353;
  --cyan:         #00d4ff;
  --danger:       #C73E3E;
  --good:         #00c853;

  --font-display: 'Bebas Neue', sans-serif;
  --font-body:    'Inter', system-ui, sans-serif;
  --font-mono:    'JetBrains Mono', ui-monospace, monospace;
  /* Elegant script for wedding-style accents (event names, taglines). */
  --font-script:  'Dancing Script', 'Brush Script MT', cursive;
}

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; -webkit-tap-highlight-color: transparent; }
html, body {
  height: 100%;
  overflow: hidden;
  background: var(--cc-graphite);
  color: var(--cc-cream);
  font-family: var(--font-body);
  user-select: none;
  -webkit-user-select: none;
  touch-action: manipulation;
}
input { user-select: text; -webkit-user-select: text; }

/* ════════════════════════════════════════════════
   Screen routing
   ════════════════════════════════════════════════ */
.screen {
  position: fixed; inset: 0;
  display: none;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: clamp(24px, 5vw, 56px);
  background:
    radial-gradient(circle at 50% 18%, rgba(172,202,50,0.07) 0%, transparent 55%),
    var(--cc-graphite);
  gap: clamp(18px, 3.5vh, 30px);
  text-align: center;
}
.screen.active { display: flex; }

/* ════════════════════════════════════════════════
   Brand row + wordmark
   ════════════════════════════════════════════════ */
.brand-row {
  position: absolute; top: clamp(20px, 4vh, 40px); left: 50%; transform: translateX(-50%);
  display: flex; align-items: center; gap: 12px;
  z-index: 5;
}
.brand-row .logo-img { width: clamp(40px, 8vw, 56px); height: auto; filter: drop-shadow(0 0 12px rgba(172,202,50,0.45)); }
.wordmark {
  font-family: var(--font-body);
  font-size: clamp(1.05rem, 2.6vw, 1.4rem);
  display: inline-flex; align-items: center; gap: 0.4em;
  letter-spacing: -0.01em;
  color: var(--cc-cream);
}
.wordmark .handle  { font-weight: 900; color: var(--cc-cream); }
.wordmark .product { font-weight: 400; color: var(--cc-cream-mid); }
.wordmark .dot {
  display: inline-block;
  width: 0.4em; height: 0.4em; border-radius: 50%;
  background: var(--cc-lime);
  box-shadow: 0 0 8px rgba(172,202,50,0.6);
  animation: dotPulse 2.4s ease-in-out infinite;
}
@keyframes dotPulse {
  0%,100% { box-shadow: 0 0 0 0 rgba(172,202,50,0.5); }
  50%     { box-shadow: 0 0 0 6px rgba(172,202,50,0); }
}

/* ════════════════════════════════════════════════
   Typography
   ════════════════════════════════════════════════ */
.screen-title {
  font-family: var(--font-display);
  font-size: clamp(2.8rem, 8vw, 5rem);
  letter-spacing: 0.04em;
  color: var(--cc-cream);
  line-height: 1.02;
}
.screen-title-sm {
  font-family: var(--font-display);
  font-size: clamp(2rem, 5vw, 3rem);
  letter-spacing: 0.05em;
  color: var(--cc-cream);
  line-height: 1.05;
}
.screen-sub {
  font-size: clamp(1.05rem, 2.4vw, 1.4rem);
  color: var(--cc-cream-mid);
  max-width: 90%;
}
.screen-sub-sm {
  font-size: clamp(0.9rem, 1.9vw, 1.1rem);
  color: var(--cc-cream-mid);
}

/* ════════════════════════════════════════════════
   Inputs + buttons
   ════════════════════════════════════════════════ */
/* Code-hint chip buttons on the pairing screen */
.code-hint-btn {
  background: rgba(172,202,50,0.08);
  border: 1px solid rgba(172,202,50,0.32);
  border-radius: 999px;
  color: var(--cc-lime);
  font-family: var(--font-mono);
  font-weight: 700;
  font-size: 0.78rem;
  letter-spacing: 0.12em;
  padding: 5px 12px;
  cursor: pointer;
  transition: background 0.15s;
}
.code-hint-btn:active { background: rgba(172,202,50,0.18); transform: scale(0.97); }

.form { display: flex; flex-direction: column; gap: 18px; align-items: stretch; width: 100%; max-width: 540px; }
.form label {
  font-family: var(--font-mono);
  font-size: 0.85rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--cc-cream-dim);
  text-align: left;
}
.big-input {
  width: 100%;
  padding: 24px 28px;
  font-family: inherit;
  font-size: clamp(1.4rem, 3.5vw, 1.8rem);
  color: var(--cc-cream);
  background: rgba(0,0,0,0.32);
  border: 2px solid rgba(255,255,255,0.12);
  border-radius: 16px;
  outline: none;
  text-align: center;
}
.big-input:focus { border-color: var(--cc-lime); }
.big-input::placeholder { color: rgba(242,244,238,0.22); }
.code-input {
  font-family: var(--font-mono);
  letter-spacing: 0.4em;
  font-size: clamp(2rem, 6vw, 2.8rem);
  text-transform: uppercase;
}

.btn {
  display: inline-flex; align-items: center; justify-content: center;
  font-family: inherit; font-weight: 700;
  letter-spacing: 0.06em;
  border: none; cursor: pointer;
  border-radius: 14px;
  transition: background 0.15s, transform 0.1s, color 0.15s;
}
.btn:active { transform: scale(0.98); }
.btn:disabled { opacity: 0.35; cursor: not-allowed; transform: none; }
.btn-primary {
  background: var(--cc-lime);
  color: var(--cc-graphite);
  box-shadow: 0 12px 32px rgba(172,202,50,0.32);
}
.btn-primary:hover:not(:disabled) { background: var(--cc-lime-hot); }
.btn-secondary {
  background: rgba(255,255,255,0.08);
  color: var(--cc-cream);
  border: 1.5px solid rgba(255,255,255,0.12);
}
.btn-ghost {
  background: transparent;
  color: var(--cc-cream-mid);
  border: 1.5px solid rgba(255,255,255,0.1);
}
.btn-danger {
  background: var(--danger);
  color: var(--cc-cream);
  box-shadow: 0 12px 32px rgba(199,62,62,0.32);
}
.btn-danger:hover:not(:disabled) { background: #d84747; }

/* End event confirmation modal */
.end-confirm-body {
  display: flex; flex-direction: column;
  align-items: center;
  gap: 14px;
  max-width: 620px;
  text-align: center;
}
.end-confirm-icon {
  width: clamp(96px, 18vw, 130px);
  aspect-ratio: 1;
  border-radius: 50%;
  background: rgba(229,195,83,0.15);
  border: 2px solid var(--cc-gold);
  color: var(--cc-gold);
  font-size: clamp(3.6rem, 9vw, 5rem);
  display: flex; align-items: center; justify-content: center;
  margin-bottom: 6px;
}
.end-confirm-eventname {
  color: var(--cc-lime);
  font-weight: 800;
}

/* Test brightness confirm — same modal shape, gold tint */
.end-confirm-icon.test-icon {
  background: rgba(229,195,83,0.22);
  color: var(--cc-gold);
  border-color: var(--cc-gold);
}
/* Delete confirm — red destructive tint */
.end-confirm-icon.delete-icon {
  background: rgba(199,62,62,0.22);
  color: var(--cc-danger);
  border-color: var(--cc-danger);
  font-size: clamp(2.8rem, 7vw, 4rem);
}

/* ✓ / ✗ confirmation buttons — stack icon over label, large touch target */
.btn.confirm-check,
.btn.confirm-x {
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  gap: 4px;
  padding: 22px 36px;
  min-width: 200px;
  font-weight: 800;
  letter-spacing: 0.08em;
}
.big-btn    { padding: 22px 36px; font-size: clamp(1.1rem, 2.6vw, 1.35rem); min-width: 200px; }
.big-btn-sm { padding: 14px 24px; font-size: 1rem; }
.mega-btn   { padding: clamp(28px, 6vw, 40px) clamp(50px, 10vw, 90px); font-size: clamp(1.6rem, 5vw, 2.2rem); border-radius: 24px; }

.ghost-corner {
  position: absolute; bottom: 18px; right: 18px;
  padding: 10px 18px; font-size: 0.74rem;
}

.error-block {
  margin-top: 12px;
  color: var(--danger);
  font-weight: 600;
  display: none;
  font-size: 1.05rem;
}
.error-block.show { display: block; }

/* ════════════════════════════════════════════════
   Idle
   ════════════════════════════════════════════════ */
/* Idle screen: full-area tap zone above a fixed bottom operator toolbar.
   .screen's default flex centering is replaced with absolute positioning
   so the zones don't fight each other for layout. */
.idle-screen {
  padding: 0 !important;
  gap: 0 !important;
}
.idle-bg-video {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  z-index: 0;
  opacity: 0.55;
}
/* Still-image attract loop — Ken-Burns slow pan + zoom + subtle
   brightness "breathing" so the SAME pixel never sits on the same
   position long enough to burn into an OLED/AMOLED panel. Pan swings
   across ~5% of the image over 30s so it's imperceptible in-the-moment
   but big enough to shuffle any given screen pixel through many
   different image pixels over an evening. */
.idle-bg-image {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  z-index: 0;
  opacity: 0.55;
  transform-origin: center center;
}
.idle-bg-image.kenburns {
  animation:
    kenburnsPan 40s ease-in-out infinite alternate,
    burnInGuard 90s ease-in-out infinite;
}
@keyframes kenburnsPan {
  /* Combined slow pan + gentle 1.05× zoom that inverts each cycle so
     no single pixel of the panel is asked to hold the same color for
     more than ~20s. */
  0%   { transform: scale(1.05) translate(-2%, -1.5%); }
  25%  { transform: scale(1.08) translate( 1.5%, -1%); }
  50%  { transform: scale(1.05) translate( 2%,   1.5%); }
  75%  { transform: scale(1.08) translate(-1.5%, 1%); }
  100% { transform: scale(1.05) translate(-2%, -1.5%); }
}
@keyframes burnInGuard {
  /* Full-screen brightness sweep once every ~90s. The ±8% swing is
     imperceptible to a guest walking by but is more than enough to
     stop static-pixel image retention. */
  0%,100% { filter: brightness(1.0); }
  50%     { filter: brightness(0.92); }
}

/* TEST MODE badge — global fixed-position pill that stays visible across
   capture + preview screens during a flash-brightness test. Bright gold
   + pulsing dot make it obvious. Photos taken during test mode are
   discarded after the operator views the strip. */
.test-mode-badge {
  position: fixed;
  bottom: 24px;
  left: 50%;
  transform: translateX(-50%);
  flex-direction: row !important;
  align-items: center !important;
  gap: 12px;
  padding-right: 28px;
  display: flex; flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  padding: 10px 18px 10px 16px;
  background: rgba(229,195,83,0.95);
  color: var(--cc-graphite);
  border-radius: 14px;
  box-shadow:
    0 8px 24px rgba(229,195,83,0.45),
    0 0 30px rgba(229,195,83,0.35);
  z-index: 50;
  animation: testBadgePulse 2.2s ease-in-out infinite;
}
.test-mode-text {
  font-family: var(--font-display);
  font-size: clamp(1.1rem, 2.4vw, 1.4rem);
  font-weight: 900;
  letter-spacing: 0.18em;
  line-height: 1;
}
.test-mode-sub {
  font-family: var(--font-mono);
  font-size: clamp(0.7rem, 1.5vw, 0.85rem);
  font-weight: 700;
  letter-spacing: 0.05em;
  opacity: 0.78;
  padding-left: 4px;
  border-left: 1.5px solid rgba(27,29,34,0.35);
}
.test-mode-dot {
  width: 11px; height: 11px;
  border-radius: 50%;
  background: var(--cc-graphite);
  animation: testBadgeDot 1.1s ease-in-out infinite;
}
@keyframes testBadgePulse {
  0%, 100% { box-shadow: 0 8px 24px rgba(229,195,83,0.45), 0 0 30px rgba(229,195,83,0.35); }
  50%      { box-shadow: 0 8px 24px rgba(229,195,83,0.55), 0 0 60px rgba(229,195,83,0.6); }
}
@keyframes testBadgeDot {
  0%, 100% { opacity: 1;   transform: scale(1);   }
  50%      { opacity: 0.3; transform: scale(0.85); }
}

/* Captured-photo overlay also gets a "test" tint when the session is a
   flash-brightness test — same gold border around the photo frame so it's
   visually clear the snap is throwaway. */
.cap-gotit.test-mode .cap-gotit-frame {
  box-shadow:
    0 30px 80px rgba(0,0,0,0.7),
    0 0 0 4px var(--cc-gold),
    0 0 80px rgba(229,195,83,0.45);
}
.cap-gotit.test-mode .cap-gotit-label::before {
  content: "TEST · ";
  color: var(--cc-gold);
  font-weight: 900;
  letter-spacing: 0.1em;
}

/* ── Booth Closed screen ─────────────────────────────────────────────
   Simple: event chip at top, massive bold BOOTH CLOSED in center,
   toolbar at bottom. No background effects. */
.closed-screen {
  padding: 0 !important;
  gap: 0 !important;
  overflow: hidden;
  background: var(--cc-graphite);
}

/* Event chip — small badge pinned near the top */
.closed-event-chip {
  position: absolute;
  top: clamp(28px, 5vh, 56px);
  left: 50%;
  transform: translateX(-50%);
  display: flex; flex-direction: column; align-items: center;
  gap: 2px;
  padding: 10px 26px;
  background: rgba(0,0,0,0.35);
  border: 1px solid rgba(229,195,83,0.35);
  border-radius: 999px;
  z-index: 5;
  max-width: 90%;
  text-align: center;
}
.closed-event-chip-label {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--cc-cream-dim);
}
.closed-event-chip-name {
  font-family: var(--font-script);
  font-size: clamp(1.2rem, 2.4vw, 1.6rem);
  font-weight: 600;
  color: var(--cc-cream);
  line-height: 1;
}
.closed-event-chip-meta {
  font-family: var(--font-mono);
  font-size: 0.65rem;
  letter-spacing: 0.18em;
  color: var(--cc-lime);
  text-transform: uppercase;
}
.closed-event-chip-meta:empty { display: none; }

/* HERO — fills the screen with massive headline + cursive tagline */
.closed-hero {
  position: absolute;
  inset: 0;
  bottom: var(--idle-toolbar-h);
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  gap: clamp(20px, 4vh, 48px);
  padding: clamp(180px, 22vh, 240px) clamp(32px, 6vw, 64px) clamp(32px, 5vh, 64px);
  z-index: 4;
  text-align: center;
}
/* Three floating emoji icons, each starting at a different phase so the
   trio bobs in a relaxed rhythm rather than in lockstep. */
.closed-icons {
  display: flex; align-items: center;
  gap: clamp(18px, 3vw, 36px);
}
.closed-icon {
  font-size: clamp(3.2rem, 7.5vw, 5rem);
  display: inline-block;
  filter: drop-shadow(0 0 25px rgba(229,195,83,0.4));
  animation: closedIconFloat 3.4s ease-in-out var(--d, 0s) infinite;
}
@keyframes closedIconFloat {
  0%, 100% { transform: translateY(0) rotate(-6deg); }
  50%      { transform: translateY(-18px) rotate(8deg); }
}

/* Per-letter bounce — JS wraps each character in a .closed-letter span
   on entering the screen, with --i set to the character index so the
   bounces cascade left-to-right like a marquee. */
/* HUGE bold headline — fills the canvas */
.closed-hero-text {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(6rem, 22vw, 18rem);
  letter-spacing: 0.04em;
  line-height: 0.9;
  color: var(--cc-cream);
  text-shadow:
    0 0 60px rgba(229,195,83,0.35),
    0 12px 40px rgba(0,0,0,0.6);
}
.closed-status-text { display: none; }
@keyframes closedTextShimmer {
  0%, 100% { background-position: 0% 50%;  }
  50%      { background-position: 100% 50%; }
}
.closed-letter {
  display: inline-block;
  animation: closedLetterBounce 1.8s ease-in-out calc(var(--i, 0) * 0.07s) infinite;
}
@keyframes closedLetterBounce {
  0%, 60%, 100% { transform: translateY(0);  }
  15%           { transform: translateY(-14px) rotate(-4deg); }
  30%           { transform: translateY(0)    rotate(0); }
}

/* Cursive tagline beneath the hero — rotates through playful phrases */
.closed-hero-tagline {
  font-family: var(--font-script);
  font-weight: 600;
  font-size: clamp(1.8rem, 4vw, 3rem);
  color: var(--cc-cream-mid);
  letter-spacing: 0;
  transition: opacity 0.5s ease;
  text-shadow: 0 4px 20px rgba(0,0,0,0.5);
}
.closed-status-sub { display: none; }
@keyframes closedBreathe {
  0%, 100% { box-shadow: 0 24px 80px rgba(0,0,0,0.4), 0 0 100px rgba(229,195,83,0.12), inset 0 1px 0 rgba(255,255,255,0.06); }
  50%      { box-shadow: 0 24px 80px rgba(0,0,0,0.4), 0 0 140px rgba(229,195,83,0.22), inset 0 1px 0 rgba(255,255,255,0.06); }
}

/* Closed-screen toolbar — same chrome as idle but only Reopen + End */
.closed-toolbar {
  background: linear-gradient(to top, rgba(13,15,20,0.88), rgba(13,15,20,0));
}

/* ── Composing / preparing-your-strip screen ───────────────────────── */
.compose-body {
  display: flex; flex-direction: column; align-items: center;
  gap: 18px; text-align: center;
  max-width: 560px;
}
.compose-spark {
  font-size: clamp(4rem, 11vw, 6rem);
  animation: composeSpin 3s linear infinite;
  filter: drop-shadow(0 0 24px rgba(172,202,50,0.6));
}
@keyframes composeSpin {
  0%, 100% { transform: rotate(-12deg) scale(1); }
  50%      { transform: rotate(20deg)  scale(1.12); }
}
.compose-progress {
  width: min(460px, 80vw);
  height: 14px;
  background: rgba(255,255,255,0.08);
  border: 1px solid rgba(172,202,50,0.25);
  border-radius: 999px;
  overflow: hidden;
  margin-top: 12px;
  box-shadow: inset 0 2px 6px rgba(0,0,0,0.4);
}
.compose-progress-fill {
  width: 0%;
  height: 100%;
  border-radius: 999px;
  background: linear-gradient(90deg, #ACCA32 0%, #C4E64A 50%, #E8FF7A 100%);
  background-size: 200% 100%;
  box-shadow: 0 0 24px rgba(172,202,50,0.6);
  /* Width is driven by JS from real work milestones now (per-photo brighten
     completion + composite done). The old CSS keyframe animation ran on a
     fixed 2.4s clock regardless of actual work, so the bar would fill and
     then sit at 100% for 10+ seconds when tablets were slow — reading as
     "hung." transition + JS width updates give honest progress. */
  transition: width 0.35s cubic-bezier(0.22, 0.8, 0.3, 1);
  animation: composeShimmer 1.4s ease-in-out infinite;
}
@keyframes composeShimmer {
  0%, 100% { background-position: 0% 50%;  }
  50%      { background-position: 100% 50%; }
}
.compose-tip {
  font-family: var(--font-display, 'Bebas Neue'), serif;
  font-size: clamp(0.88rem, 1.6vw, 1.05rem);
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: rgba(242,244,238,0.55);
  margin-top: 14px;
  font-weight: 300;
}
/* Elegant wedding-mode overrides for the compose title/subtitle */
.compose-title {
  font-family: var(--font-display, 'Bebas Neue'), serif;
  letter-spacing: 0.06em;
  color: var(--cc-cream);
  margin: 6px 0 4px;
}
.compose-subtitle {
  font-family: var(--font-body, 'Inter'), serif;
  font-style: italic;
  font-size: clamp(0.92rem, 1.7vw, 1.08rem);
  color: rgba(242,244,238,0.7);
  margin: 0 auto 8px;
  max-width: 420px;
}

/* ═══════════════════════════════════════════════════════════════════
   Art-deco compose emblem — two counter-rotating gold rings framing a
   centered "CC" monogram. Replaces the emoji spark on the compose
   screen so the vibe reads elegant/wedding-appropriate.
   ═══════════════════════════════════════════════════════════════════ */
.compose-emblem {
  position: relative;
  width:  clamp(140px, 22vw, 200px);
  height: clamp(140px, 22vw, 200px);
  display: flex; align-items: center; justify-content: center;
  margin-bottom: 8px;
}
.compose-emblem-ring {
  position: absolute; inset: 0;
  border-radius: 50%;
  pointer-events: none;
}
.compose-emblem-ring-outer {
  border: 1.5px solid rgba(229,195,83,0.55);
  border-top-color: rgba(229,195,83,0.95);
  border-right-color: rgba(229,195,83,0.9);
  box-shadow:
    0 0 30px rgba(229,195,83,0.22),
    inset 0 0 30px rgba(229,195,83,0.08);
  animation: composeRingSpin 6s linear infinite;
}
.compose-emblem-ring-inner {
  inset: 14px;
  border: 1px solid rgba(172,202,50,0.5);
  border-bottom-color: rgba(172,202,50,0.95);
  border-left-color: rgba(172,202,50,0.9);
  box-shadow: 0 0 22px rgba(172,202,50,0.22);
  animation: composeRingSpin 4.4s linear infinite reverse;
}
@keyframes composeRingSpin {
  from { transform: rotate(0deg);   }
  to   { transform: rotate(360deg); }
}
.compose-emblem-mono {
  font-family: var(--font-display, 'Bebas Neue'), serif;
  font-size: clamp(2rem, 5.5vw, 3rem);
  font-weight: 700;
  letter-spacing: 0.04em;
  color: var(--cc-cream);
  text-shadow: 0 0 24px rgba(229,195,83,0.5);
  animation: composeMonoBreathe 3.4s ease-in-out infinite;
}
@keyframes composeMonoBreathe {
  0%,100% { transform: scale(1);    opacity: 0.92; }
  50%     { transform: scale(1.05); opacity: 1;    }
}

/* ═══════════════════════════════════════════════════════════════════
   Champagne bubbles — six pinpoints drifting up behind the emblem.
   Different sizes + start positions + delays so it never looks like a
   grid or a loop.
   ═══════════════════════════════════════════════════════════════════ */
.compose-bubbles {
  position: absolute; inset: 0;
  overflow: hidden;
  pointer-events: none;
  z-index: 0;
}
.compose-bubbles span {
  position: absolute;
  bottom: -30px;
  width: 8px; height: 8px;
  border-radius: 50%;
  background: radial-gradient(circle at 30% 30%, rgba(255,255,255,0.9), rgba(229,195,83,0.35) 55%, rgba(229,195,83,0) 80%);
  filter: blur(0.4px);
  opacity: 0;
  animation: composeBubbleFloat 9s linear infinite;
}
.compose-bubbles span:nth-child(1) { left: 12%; width: 10px; height: 10px; animation-duration: 11s; animation-delay: 0s;   }
.compose-bubbles span:nth-child(2) { left: 24%; width: 6px;  height: 6px;  animation-duration: 8s;  animation-delay: 1.4s; }
.compose-bubbles span:nth-child(3) { left: 38%; width: 12px; height: 12px; animation-duration: 12s; animation-delay: 3.2s; }
.compose-bubbles span:nth-child(4) { left: 58%; width: 8px;  height: 8px;  animation-duration: 9s;  animation-delay: 0.6s; }
.compose-bubbles span:nth-child(5) { left: 76%; width: 5px;  height: 5px;  animation-duration: 10s; animation-delay: 2.1s; }
.compose-bubbles span:nth-child(6) { left: 88%; width: 9px;  height: 9px;  animation-duration: 11.5s; animation-delay: 4.4s; }
@keyframes composeBubbleFloat {
  0%   { transform: translateY(0)     translateX(0); opacity: 0;   }
  10%  { opacity: 0.85; }
  50%  { transform: translateY(-42vh) translateX(-6px); opacity: 0.7; }
  90%  { opacity: 0.35; }
  100% { transform: translateY(-88vh) translateX(6px);  opacity: 0;   }
}
/* Make sure the body stack sits above bubbles */
.compose-body { position: relative; z-index: 1; }
/* Hide the legacy ✨ + all older compose-screen visuals so the new
   photo-strip design is the only thing on screen. */
.compose-spark,
.compose-glass,
.compose-water,
.compose-corner,
.compose-bubbles,
.compose-emblem,
.compose-divider { display: none !important; }
.compose-title,
.compose-subtitle,
.compose-tip { display: none !important; }
.compose-progress { display: none !important; }
.compose-screen::after { display: none !important; }

/* ═══════════════════════════════════════════════════════════════════
   PREPARING YOUR STRIP — full-viewport photo-strip reveal.
   The hero (strip + ring) takes the middle third of the screen; title
   and status stretch full-width; hairline progress hugs the bottom
   edge. Nothing sits in a boxed max-width — the composition owns the
   whole viewport.
   ═══════════════════════════════════════════════════════════════════ */
.compose-screen {
  background: radial-gradient(ellipse at 50% 30%, #1E2229 0%, #12141A 55%, #0A0B0F 100%);
  --compose-fill: 0;
  overflow: hidden;
  /* Override the base .screen padding + justify-content so the layout
     owns the entire viewport instead of being flex-centered as a block. */
  padding: 0 !important;
  gap: 0 !important;
  justify-content: stretch !important;
  align-items: stretch !important;
}
/* The body is absolutely positioned to guarantee it fills the entire
   compose-screen (which is fixed inset:0). That kills the flex-centering
   inherited from .screen — the previous grid approach left the entire
   bottom half of the viewport as dead black space because .screen's
   `justify-content: center` was sizing the grid to content-height. */
.compose-screen .compose-body {
  position: absolute;
  inset: 0;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  gap: clamp(14px, 2.4vh, 32px);
  width: 100%;
  max-width: none;
  padding: clamp(28px, 5vh, 60px) clamp(28px, 5vw, 60px) clamp(28px, 5vh, 60px);
}

/* Hero — grows to fill ALL available space between the top padding and
   the title cluster below. flex: 1 + min-height:0 lets it own the
   whole vertical middle of the screen. Photo strip inside scales up
   with it (no more max-height cap). */
.compose-hero {
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
  width: 100%;
  display: flex; align-items: center; justify-content: center;
  padding: clamp(8px, 1.5vh, 20px) 0;
}
/* Slowly rotating gold ring — sized to a circle inscribed in the hero
   area (uses min of width/height so it stays circular on any aspect). */
.compose-hero-ring {
  position: absolute;
  width: min(88vw, 82vh);
  height: min(88vw, 82vh);
  border-radius: 50%;
  border: 1.5px solid transparent;
  background:
    conic-gradient(from 0deg,
      rgba(229,195,83,0)   0deg,
      rgba(229,195,83,0)   200deg,
      rgba(229,195,83,0.85) 300deg,
      rgba(255,240,190,1)  340deg,
      rgba(229,195,83,0.85) 360deg) border-box;
  -webkit-mask:
    linear-gradient(#000 0 0) padding-box,
    linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask-composite: exclude;
  animation: heroRingSpin 4.2s linear infinite;
  filter: drop-shadow(0 0 34px rgba(229,195,83,0.4));
}
@keyframes heroRingSpin {
  from { transform: rotate(0deg);   }
  to   { transform: rotate(360deg); }
}

/* The photo strip itself — narrow tall card, 3 cells stacked, elegant
   gold border, brand mark at the bottom. FILLS the hero: on portrait
   tablets it becomes a truly dominant element (~80% of viewport height).
   No max-height cap — scales with the container. */
.compose-strip {
  position: relative;
  height: 100%;
  aspect-ratio: 1 / 3;    /* 2×6 strip proportions */
  padding: clamp(12px, 1.6vh, 22px) clamp(12px, 1.6vh, 22px) clamp(8px, 1vh, 14px);
  display: flex; flex-direction: column;
  gap: clamp(10px, 1.2vh, 16px);
  background: linear-gradient(180deg, #F5F0E4, #E8DFC9);
  border-radius: 6px;
  box-shadow:
    0 28px 80px rgba(0,0,0,0.6),
    0 0 0 1px rgba(229,195,83,0.35),
    0 0 40px rgba(229,195,83,0.2);
  transform: rotate(-2.5deg);
}
.compose-strip-cell {
  position: relative;
  flex: 1 1 0;
  min-height: 0;
  background: linear-gradient(135deg, #2C303B, #1B1D22);
  border-radius: 2px;
  overflow: hidden;
  box-shadow: inset 0 0 0 1px rgba(0,0,0,0.35);
}
/* The "shine" — a diagonal gold sweep that fires per cell in sequence,
   suggesting each photo is being processed / developed. */
.compose-strip-cell .cell-shine {
  position: absolute; inset: 0;
  background: linear-gradient(115deg,
    transparent 0%,
    transparent 30%,
    rgba(255,240,190,0.55) 46%,
    rgba(255,255,255,0.9)  50%,
    rgba(255,240,190,0.55) 54%,
    transparent 70%,
    transparent 100%);
  background-size: 240% 100%;
  background-position: 100% 0;
  animation: cellShine 3s ease-in-out infinite;
  mix-blend-mode: screen;
}
.compose-strip-cell:nth-child(1) .cell-shine { animation-delay: 0.0s; }
.compose-strip-cell:nth-child(2) .cell-shine { animation-delay: 0.9s; }
.compose-strip-cell:nth-child(3) .cell-shine { animation-delay: 1.8s; }
@keyframes cellShine {
  0%   { background-position: 100% 0; }
  35%  { background-position: -100% 0; }
  100% { background-position: -100% 0; }
}
/* Each cell also breathes a soft internal light so the whole strip
   feels alive between shine sweeps. */
.compose-strip-cell::after {
  content: "";
  position: absolute; inset: 0;
  background: radial-gradient(ellipse at center, rgba(229,195,83,0.22), transparent 65%);
  opacity: 0;
  animation: cellBreathe 3s ease-in-out infinite;
}
.compose-strip-cell:nth-child(1)::after { animation-delay: 0.0s; }
.compose-strip-cell:nth-child(2)::after { animation-delay: 0.9s; }
.compose-strip-cell:nth-child(3)::after { animation-delay: 1.8s; }
@keyframes cellBreathe {
  0%, 60%, 100% { opacity: 0;    }
  25%, 35%      { opacity: 0.9;  }
}
/* Brand line at the bottom of the strip — mirrors the physical print */
.compose-strip-brand {
  display: flex; align-items: center; justify-content: center; gap: 5px;
  font-family: var(--font-mono, monospace);
  font-size: 8px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: #6b5f3a;
  padding-top: 3px;
}
.compose-strip-brand .dot {
  width: 3px; height: 3px; border-radius: 50%;
  background: #B89B3E;
}

/* Title + status — clean, centered, editorial. Scales bigger with the
   full-viewport layout so it commands presence, not tucked-away. */
.compose-title-new {
  font-family: var(--font-display, 'Bebas Neue'), sans-serif;
  font-size: clamp(3rem, 8vw, 6rem);
  letter-spacing: 0.05em;
  color: var(--cc-cream);
  margin: 0;
  line-height: 1;
  text-shadow: 0 4px 24px rgba(0,0,0,0.5), 0 0 60px rgba(229,195,83,0.18);
}
.compose-status {
  font-family: var(--font-body, 'Inter'), sans-serif;
  font-style: italic;
  font-size: clamp(1.15rem, 2.6vw, 1.7rem);
  color: rgba(242,244,238,0.8);
  margin: 0;
  min-height: 1.4em;
  transition: opacity 240ms ease;
  letter-spacing: 0.01em;
  text-align: center;
  max-width: 40ch;
}
.compose-status.swap { opacity: 0; }

/* Hairline horizontal progress — sits at the very bottom of the layout
   stack, stretched WIDE so it visually corresponds to the whole screen.
   Driven by --compose-fill custom property. */
.compose-line {
  width: min(720px, 82vw);
  height: 3px;
  background: rgba(229,195,83,0.15);
  border-radius: 3px;
  overflow: hidden;
}
.compose-line-fill {
  display: block;
  width: calc(var(--compose-fill, 0) * 100%);
  height: 100%;
  background: linear-gradient(90deg, var(--cc-lime, #ACCA32) 0%, var(--cc-gold, #E5C353) 60%, var(--cc-cream, #F2F4EE) 100%);
  box-shadow: 0 0 14px rgba(229,195,83,0.6);
  transition: width 0.42s cubic-bezier(0.4, 0, 0.2, 1);
}

/* AI backdrop status pill — bottom-right of compose screen, small so
   guests don't clock it but operators can glance and confirm. Color
   coded: yellow=loading, green=applied, red=failed. */
.bd-status-pill {
  position: absolute;
  right: 16px; bottom: 16px;
  z-index: 4;
  display: flex; align-items: center; gap: 8px;
  padding: 6px 12px;
  border-radius: 999px;
  background: rgba(0,0,0,0.55);
  border: 1px solid rgba(255,255,255,0.14);
  font-family: var(--font-mono, monospace);
  font-size: 0.7rem;
  letter-spacing: 0.08em;
  color: rgba(242,244,238,0.75);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
.bd-status-dot {
  width: 8px; height: 8px; border-radius: 50%;
  background: rgba(255,255,255,0.5);
  transition: background 220ms;
}
.bd-status-pill.loading .bd-status-dot { background: #F5D453; box-shadow: 0 0 10px rgba(245,212,83,0.7); animation: bdPillPulse 1.2s ease-in-out infinite; }
.bd-status-pill.ok .bd-status-dot     { background: #ACCA32; box-shadow: 0 0 10px rgba(172,202,50,0.7); }
.bd-status-pill.fail .bd-status-dot   { background: #FF6F5E; box-shadow: 0 0 10px rgba(255,111,94,0.8); animation: bdPillPulse 1.0s ease-in-out infinite; }
.bd-status-pill.ok    { border-color: rgba(172,202,50,0.4); }
.bd-status-pill.fail  { border-color: rgba(255,111,94,0.5); color: #FFAAA0; }
@keyframes bdPillPulse {
  0%,100% { opacity: 0.7; }
  50%     { opacity: 1;   }
}


/* [Removed — legacy water-fill overrides. Superseded by the
   redesigned .compose-screen block earlier in this file.] */

.compose-water {
  position: absolute;
  /* Anchor to the screen edges NOT the padding box, so the water reaches
     border-to-border even though .compose-screen has clamp() padding. */
  left: 0; right: 0; bottom: 0;
  width: 100%;
  /* Height is % of the padding-box height, which equals the viewport height
     since .screen is `position: fixed; inset: 0`. --compose-fill goes 0..1. */
  height: calc(var(--compose-fill, 0) * 100%);
  pointer-events: none;
  transition: height 0.45s cubic-bezier(0.4, 0, 0.2, 1);
  z-index: 1;
  /* Give the whole water column a soft inner glow */
  filter: drop-shadow(0 -10px 40px rgba(229,195,83,0.28));
  will-change: height;
}
/* Reset class applied briefly on compose-screen entry so the water snaps
   to 0% instantly (instead of animating DOWN from a previous session's
   fill). Removed after one frame so subsequent updates transition. */
.compose-screen.water-reset .compose-water {
  transition: none !important;
}

/* The body of water — soft gradient below the wave line, blurring the
   background just slightly through it. Text on top gets legibility from
   a strong text-shadow, not from opaque water. */
.compose-water-body {
  position: absolute; inset: 0;
  background:
    linear-gradient(180deg,
      rgba(172,202,50,0.35) 0%,
      rgba(229,195,83,0.42) 45%,
      rgba(143,108,28,0.55) 100%);
  backdrop-filter: blur(2px) saturate(1.15);
  -webkit-backdrop-filter: blur(2px) saturate(1.15);
}

/* The animated wave surface — two paths drifting opposite directions
   at different speeds so it looks like real water, not a metronome. */
.compose-water-wave {
  position: absolute; left: 0; right: 0; top: -60px;
  width: 100%; height: 90px;
  display: block;
  overflow: visible;
}
.compose-water-wave-back  {
  animation: waveDriftA 8s linear infinite;
  opacity: 0.75;
}
.compose-water-wave-front {
  animation: waveDriftB 5s linear infinite;
}
@keyframes waveDriftA {
  from { transform: translateX(0);      }
  to   { transform: translateX(-1200px); }
}
@keyframes waveDriftB {
  from { transform: translateX(-1200px); }
  to   { transform: translateX(0);       }
}

/* Bright light ribbon just under the wave surface — mimics the way real
   water reflects light along the meniscus. */
.compose-water-highlight {
  position: absolute; left: 0; right: 0; top: -2px;
  height: 4px;
  background: linear-gradient(90deg,
    transparent 0%,
    rgba(255,240,190,0.85) 15%,
    rgba(255,255,255,0.7) 50%,
    rgba(255,240,190,0.85) 85%,
    transparent 100%);
  filter: blur(1.2px);
  opacity: 0.85;
  animation: waveHighlight 3.4s ease-in-out infinite;
}
@keyframes waveHighlight {
  0%, 100% { transform: translateX(-20px); opacity: 0.85; }
  50%      { transform: translateX(20px);  opacity: 1;    }
}

/* Rising sparkles inside the water column — mix of gold flakes + white
   pinpoint bubbles. 15 spans staggered by nth-child so they never sync. */
.compose-water-sparkles {
  position: absolute; inset: 0;
  overflow: hidden;
}
.compose-water-sparkles span {
  position: absolute;
  bottom: -12px;
  width: 6px; height: 6px;
  border-radius: 50%;
  background: radial-gradient(circle at 30% 30%, rgba(255,255,255,0.95), rgba(229,195,83,0.45) 55%, rgba(229,195,83,0) 90%);
  filter: blur(0.5px);
  opacity: 0;
  animation: waterSparkRise 6s linear infinite;
}
.compose-water-sparkles span:nth-child(1)  { left: 6%;  width: 5px; height: 5px; animation-delay: 0.0s; animation-duration: 6.5s; }
.compose-water-sparkles span:nth-child(2)  { left: 14%; width: 4px; height: 4px; animation-delay: 1.1s; animation-duration: 5.4s; }
.compose-water-sparkles span:nth-child(3)  { left: 22%; width: 7px; height: 7px; animation-delay: 2.3s; animation-duration: 7.2s; }
.compose-water-sparkles span:nth-child(4)  { left: 30%; width: 3px; height: 3px; animation-delay: 0.4s; animation-duration: 4.8s; }
.compose-water-sparkles span:nth-child(5)  { left: 38%; width: 5px; height: 5px; animation-delay: 3.0s; animation-duration: 6.8s; }
.compose-water-sparkles span:nth-child(6)  { left: 46%; width: 8px; height: 8px; animation-delay: 1.6s; animation-duration: 7.6s; }
.compose-water-sparkles span:nth-child(7)  { left: 54%; width: 4px; height: 4px; animation-delay: 2.8s; animation-duration: 5.2s; }
.compose-water-sparkles span:nth-child(8)  { left: 62%; width: 6px; height: 6px; animation-delay: 0.7s; animation-duration: 6.6s; }
.compose-water-sparkles span:nth-child(9)  { left: 70%; width: 3px; height: 3px; animation-delay: 3.5s; animation-duration: 4.6s; }
.compose-water-sparkles span:nth-child(10) { left: 78%; width: 7px; height: 7px; animation-delay: 1.9s; animation-duration: 7.4s; }
.compose-water-sparkles span:nth-child(11) { left: 86%; width: 5px; height: 5px; animation-delay: 0.2s; animation-duration: 5.8s; }
.compose-water-sparkles span:nth-child(12) { left: 92%; width: 4px; height: 4px; animation-delay: 2.4s; animation-duration: 6.2s; }
.compose-water-sparkles span:nth-child(13) { left: 50%; width: 9px; height: 9px; animation-delay: 4.2s; animation-duration: 8.0s; }
.compose-water-sparkles span:nth-child(14) { left: 18%; width: 3px; height: 3px; animation-delay: 3.8s; animation-duration: 5.0s; }
.compose-water-sparkles span:nth-child(15) { left: 82%; width: 6px; height: 6px; animation-delay: 1.3s; animation-duration: 6.9s; }
@keyframes waterSparkRise {
  0%   { transform: translate(0, 0)     scale(1);   opacity: 0;   }
  8%   { opacity: 0.9; }
  50%  { transform: translate(6px, -50vh) scale(1.1); opacity: 0.85; }
  92%  { opacity: 0.4; }
  100% { transform: translate(-4px, -110vh) scale(0.7); opacity: 0; }
}

/* Art-deco corner ornaments — small chevrons in each corner of the
   viewport, floating slightly (breathing) so the framing feels alive. */
.compose-corner {
  position: absolute;
  width: clamp(56px, 7vw, 84px);
  height: clamp(56px, 7vw, 84px);
  z-index: 4;
  filter: drop-shadow(0 0 8px rgba(229,195,83,0.35));
  animation: cornerBreathe 4.2s ease-in-out infinite;
}
.compose-corner-tl { top: clamp(14px, 2.4vw, 26px); left:  clamp(14px, 2.4vw, 26px); }
.compose-corner-tr { top: clamp(14px, 2.4vw, 26px); right: clamp(14px, 2.4vw, 26px); }
.compose-corner-bl { bottom: clamp(14px, 2.4vw, 26px); left:  clamp(14px, 2.4vw, 26px); }
.compose-corner-br { bottom: clamp(14px, 2.4vw, 26px); right: clamp(14px, 2.4vw, 26px); }
.compose-corner-tr, .compose-corner-bl { animation-delay: 1.1s; }
.compose-corner-br { animation-delay: 2.1s; }
@keyframes cornerBreathe {
  0%,100% { opacity: 0.75; transform: scale(1);    }
  50%     { opacity: 1;    transform: scale(1.06); }
}

/* Body copy sits ABOVE the water, always centered. Strong text-shadow
   guarantees legibility whether the water level is at 0% or 100%. */
.compose-body {
  position: relative;
  z-index: 5;
}
.compose-body .compose-title,
.compose-body .compose-subtitle,
.compose-body .prep-status-line,
.compose-body .compose-tip {
  text-shadow:
    0 2px 24px rgba(0,0,0,0.75),
    0 0 40px rgba(13,15,20,0.5);
}

/* Elegant divider — thin gold line with a diamond mark in the center */
.compose-divider {
  display: flex; align-items: center; justify-content: center;
  gap: 12px;
  width: min(320px, 60vw);
  margin: 4px auto 2px;
}
.compose-divider-line {
  flex: 1;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(229,195,83,0.75), transparent);
}
.compose-divider-mark {
  width: 8px; height: 8px;
  background: var(--cc-gold, #E5C353);
  transform: rotate(45deg);
  box-shadow: 0 0 12px rgba(229,195,83,0.85);
  animation: dividerMarkPulse 2.4s ease-in-out infinite;
}
@keyframes dividerMarkPulse {
  0%,100% { transform: rotate(45deg) scale(1);    box-shadow: 0 0 12px rgba(229,195,83,0.85); }
  50%     { transform: rotate(45deg) scale(1.25); box-shadow: 0 0 20px rgba(229,195,83,1);    }
}

/* Splash bursts on progress milestones — short-lived droplets that
   fling up + out from the water surface with gravity. Uses CSS custom
   props from JS (--dx, --dy) for randomized flight paths. */
.compose-splash-drop {
  position: absolute;
  top: -4px;
  border-radius: 50%;
  background: radial-gradient(circle at 30% 30%, rgba(255,255,255,0.95), rgba(229,195,83,0.5));
  box-shadow: 0 0 8px rgba(229,195,83,0.6);
  pointer-events: none;
  opacity: 0;
  animation: composeSplashFly 0.85s cubic-bezier(0.22, 0.7, 0.3, 1) forwards;
}
@keyframes composeSplashFly {
  0%   { transform: translate(0, 0)         scale(0.6); opacity: 0;   }
  15%  { transform: translate(calc(var(--dx)*0.35), calc(var(--dy)*0.35)) scale(1); opacity: 1; }
  70%  { opacity: 0.85; }
  100% { transform: translate(var(--dx), calc(var(--dy)*-1 + 60px)) scale(0.4); opacity: 0; }
}

/* ═══════════════════════════════════════════════════════════════════
   Get Ready — more excited call-to-action.
   Bigger, more animated, brand-color sweep on the label, plus a
   pulsing "STRIKE A POSE" call-to-action underneath the countdown.
   ═══════════════════════════════════════════════════════════════════ */
.getready-cta {
  display: block;
  font-family: var(--font-display, 'Bebas Neue'), sans-serif;
  font-size: clamp(1.6rem, 4.5vw, 2.8rem);
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--cc-gold, #E5C353);
  margin-top: 14px;
  text-shadow:
    0 0 20px rgba(229,195,83,0.8),
    0 0 40px rgba(229,195,83,0.4);
  animation: grCtaPulse 1.1s ease-in-out infinite;
}
@keyframes grCtaPulse {
  0%,100% { transform: scale(1);    opacity: 0.9; letter-spacing: 0.28em; }
  50%     { transform: scale(1.06); opacity: 1;   letter-spacing: 0.34em; }
}
/* Bigger, more animated rings — replaces the pair I already have */
.gr-ring::before, .gr-ring::after {
  width: min(60vw, 460px); height: min(60vw, 460px);
  border-width: 4px;
}
/* Confetti-style radial spokes around the countdown number for extra pop */
.getready-title.excited::before {
  content: "";
  position: absolute;
  inset: -60px;
  border-radius: 50%;
  background:
    conic-gradient(from 0deg,
      transparent 0deg 8deg, rgba(229,195,83,0.55) 10deg 14deg,
      transparent 16deg 45deg, rgba(172,202,50,0.5) 47deg 51deg,
      transparent 53deg 90deg, rgba(229,195,83,0.55) 92deg 96deg,
      transparent 98deg 135deg, rgba(172,202,50,0.5) 137deg 141deg,
      transparent 143deg 180deg, rgba(229,195,83,0.55) 182deg 186deg,
      transparent 188deg 225deg, rgba(172,202,50,0.5) 227deg 231deg,
      transparent 233deg 270deg, rgba(229,195,83,0.55) 272deg 276deg,
      transparent 278deg 315deg, rgba(172,202,50,0.5) 317deg 321deg,
      transparent 323deg 360deg);
  filter: blur(2px);
  animation: grSpokes 3.2s linear infinite;
  z-index: -1;
  mix-blend-mode: screen;
}
@keyframes grSpokes {
  from { transform: rotate(0deg);   opacity: 0.5; }
  to   { transform: rotate(360deg); opacity: 0.5; }
}



/* ═══════════════════════════════════════════════════════════════════
   Guest backdrop picker — matches the template picker grid + card
   pattern for consistency. Each card is a 16:9 preview of the backdrop
   image. Selected state is a gold ring; tap = immediate advance.
   ═══════════════════════════════════════════════════════════════════ */
.bd-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 18px;
  width: 100%;
  max-width: 860px;
}
.bd-card {
  background: rgba(255,255,255,0.05);
  border: 2px solid rgba(255,255,255,0.1);
  border-radius: 20px;
  padding: 12px;
  cursor: pointer;
  transition: border-color 0.18s, transform 0.15s, box-shadow 0.18s;
  display: flex; flex-direction: column; gap: 10px;
}
.bd-card:hover { border-color: var(--cc-lime); transform: translateY(-3px); }
.bd-card.selected {
  border-color: var(--cc-gold, #E5C353);
  box-shadow: 0 0 0 3px rgba(229,195,83,0.25), 0 12px 30px rgba(229,195,83,0.2);
}
.bd-card .bd-preview {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 10;
  border-radius: 12px;
  overflow: hidden;
  background: linear-gradient(135deg, #2C303B, #1B1D22);
  box-shadow: 0 6px 18px rgba(0,0,0,0.4);
}
.bd-card .bd-preview img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
}
.bd-card .bd-name {
  font-family: var(--font-display, 'Bebas Neue'), sans-serif;
  font-size: 1.15rem;
  color: var(--cc-cream);
  text-align: center;
  letter-spacing: 0.02em;
  margin: 0;
}

/* ═══════════════════════════════════════════════════════════════════
   Preparing Strip — "glass of water" fill.
   The rings become a champagne coupe outline; a rising water line
   fills the interior as progress advances. A wave animation on top
   of the fill sells the liquid. Bubbles inside rise faster than the
   ambient bubbles behind everything.
   ═══════════════════════════════════════════════════════════════════ */
.compose-glass {
  position: relative;
  width: clamp(160px, 26vw, 240px);
  height: clamp(200px, 32vw, 300px);
  margin: 0 auto 10px;
  --glass-fill: 0%;
}
/* The coupe silhouette: elegant, footed, minimal — art-deco vibe. */
.compose-glass-svg {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  filter: drop-shadow(0 12px 26px rgba(0,0,0,0.45));
}
.compose-glass-body {
  fill: none;
  stroke: rgba(229,195,83,0.85);
  stroke-width: 2;
  stroke-linejoin: round;
  filter: drop-shadow(0 0 8px rgba(229,195,83,0.4));
}
.compose-glass-highlight {
  fill: none;
  stroke: rgba(255,255,255,0.35);
  stroke-width: 1;
}
/* The liquid — clipped to the bowl shape via SVG clipPath so the wave
   only shows inside the glass. Fill height is animated by JS through
   a CSS custom property (--glass-fill). */
.compose-glass-fill {
  fill: url(#glassGrad);
  transition: transform 0.5s cubic-bezier(0.22, 0.8, 0.3, 1);
}
.compose-glass-wave {
  fill: rgba(255,255,255,0.18);
  animation: glassWave 2.6s ease-in-out infinite;
}
@keyframes glassWave {
  0%,100% { transform: translateX(0); }
  50%     { transform: translateX(-6px); }
}
/* Tiny bubbles inside the glass — rise from the base and pop near
   the current fill line. Purely decorative. */
.compose-glass-bubbles {
  position: absolute;
  left: 24%; right: 24%;
  bottom: 8%;
  top: 22%;
  pointer-events: none;
  overflow: hidden;
  border-radius: 0 0 50% 50% / 0 0 30% 30%;
}
.compose-glass-bubbles span {
  position: absolute;
  bottom: -6px;
  width: 5px; height: 5px;
  border-radius: 50%;
  background: radial-gradient(circle at 30% 30%, rgba(255,255,255,0.95), rgba(255,255,255,0.35));
  animation: glassBubbleRise 3.4s linear infinite;
}
.compose-glass-bubbles span:nth-child(1) { left: 15%; animation-delay: 0s;   width: 6px; height: 6px; }
.compose-glass-bubbles span:nth-child(2) { left: 42%; animation-delay: 0.9s; width: 4px; height: 4px; }
.compose-glass-bubbles span:nth-child(3) { left: 62%; animation-delay: 1.7s; width: 7px; height: 7px; }
.compose-glass-bubbles span:nth-child(4) { left: 80%; animation-delay: 2.4s; width: 4px; height: 4px; }
@keyframes glassBubbleRise {
  0%   { transform: translateY(0);    opacity: 0;   }
  15%  { opacity: 0.9; }
  85%  { opacity: 0.6; }
  100% { transform: translateY(-140px); opacity: 0; }
}



/* Bottom operator toolbar — two stacked rows:
     Row 1  ▸  Flash brightness slider (full width)
     Row 2  ▸  View strips · Test printer · Close Booth · End event
   Stacking the slider above the actions stops it from competing with
   the button row for horizontal space on tablets and reads cleaner. */
:root { --idle-toolbar-h: clamp(168px, 22vh, 220px); }
.idle-toolbar {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: var(--idle-toolbar-h);
  display: flex;
  flex-direction: column;
  gap: clamp(8px, 1vh, 14px);
  padding: clamp(12px, 1.6vh, 20px) clamp(18px, 2.4vw, 32px) clamp(14px, 1.8vh, 22px);
  background: linear-gradient(to top,
                rgba(13,15,20,0.92) 0%,
                rgba(13,15,20,0.78) 60%,
                rgba(13,15,20,0.0)  100%);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  z-index: 5;
}
.idle-toolbar .flash-control {
  margin-top: 0;
  width: 100%;
  max-width: none;
  padding: 10px clamp(14px, 2vw, 22px);
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(172, 202, 50, 0.18);
  border-radius: 12px;
}
.toolbar-actions {
  display: flex;
  flex: 1;
  min-height: 0;
  gap: clamp(10px, 1.2vw, 16px);
  align-items: stretch;
}
.toolbar-actions .toolbar-btn {
  flex: 1;
  height: 100%;
  min-width: 0;
  padding: 0 clamp(10px, 2vw, 22px);
  font-size: clamp(0.95rem, 1.6vw, 1.1rem);
  font-weight: 700;
  white-space: nowrap;
  letter-spacing: 0.01em;
}

/* Closed screen reuses .idle-toolbar but only has buttons (no slider),
   so override back to a single-row layout — Reopen + End event split
   the full width. Slimmer height too since there's only one row. */
.closed-toolbar {
  flex-direction: row !important;
  height: clamp(96px, 12vh, 124px) !important;
  align-items: stretch;
}
.closed-toolbar .toolbar-btn {
  flex: 1;
  min-width: 0;
  padding: 0 clamp(14px, 2.5vw, 28px);
  font-size: clamp(1rem, 1.7vw, 1.2rem);
  font-weight: 700;
  white-space: nowrap;
}

/* When an attract-loop MP4 is attached to the event, hide all the default
   branded copy — logo, wordmark CTA, typewriter line, tagline — so the
   video is the entire show. The tap zone itself stays interactive so
   tapping anywhere still starts a session, and the bottom operator
   toolbar still works. */
.idle-screen.has-attract-video .idle-brand,
.idle-screen.has-attract-video .idle-cta {
  display: none !important;
}

/* The tap-anywhere zone — covers the screen ABOVE the toolbar. */
.idle-tap-zone {
  position: absolute;
  left: 0; right: 0; top: 0;
  bottom: var(--idle-toolbar-h);
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  gap: clamp(16px, 3vh, 44px);
  padding: clamp(16px, 3vh, 48px);
  cursor: pointer;
  z-index: 1;
  overflow: hidden;          /* never let the attract content clip past the edges */
  min-height: 0;
}
.idle-tap-zone:active .idle-cta { transform: scale(0.985); }

/* ── Elegant CTA — wedding-appropriate ────────────────────────────────
   No bubble pill. Stacked vertical block of:
     1. tiny widely-spaced eyebrow (the brand wordmark)
     2. typewriter-animated headline with blinking caret
     3. thin lime divider that draws across after typing finishes
     4. italic tagline that fades up at the end
   On enterIdle JS toggles .animate to replay the full sequence. */
.idle-cta {
  pointer-events: none;
  display: flex; flex-direction: column;
  align-items: center;
  gap: clamp(10px, 1.6vh, 18px);
  text-align: center;
  max-width: 90%;
}
/* CTA wordmark: same brand structure as the pairing screen + website,
   just sized larger so it reads as the headline of the idle moment. */
.idle-cta-wordmark {
  font-size: clamp(1.05rem, 2.2vw, 1.5rem);
  gap: 0.5em;
}
.idle-cta-wordmark .handle  { color: var(--cc-cream);     letter-spacing: -0.005em; }
.idle-cta-wordmark .product { color: var(--cc-cream-mid); letter-spacing: -0.005em; }

.idle-cta-line {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(2rem, min(6.8vw, 5vh), 4.8rem);
  letter-spacing: 0.08em;
  color: var(--cc-cream);
  text-shadow: 0 0 60px rgba(172,202,50,0.32);
  white-space: nowrap;
  line-height: 1.05;
}
/* Typewriter — final width is set in pixels via --type-final-w by JS so
   the full headline fits regardless of font / font-loading. Caret blinks
   while typing. */
.cta-typewrite {
  display: inline-block;
  overflow: hidden;
  white-space: nowrap;
  border-right: 3px solid var(--cc-lime);
  width: var(--type-final-w, max-content);
  vertical-align: bottom;
}
.idle-cta.animate .cta-typewrite {
  width: 0;
  animation: typewrite 2.4s steps(22, end) 0.5s forwards,
             caretBlink 0.7s step-end infinite;
}
@keyframes typewrite { to { width: var(--type-final-w, 100%); } }
@keyframes caretBlink { 50% { border-color: transparent; } }

.idle-cta-divider {
  width: 240px;
  height: 1px;
  background: linear-gradient(90deg, transparent 0%, var(--cc-lime) 50%, transparent 100%);
  opacity: 1;
}
.idle-cta.animate .idle-cta-divider {
  width: 0;
  opacity: 0;
  animation: dividerDraw 1.4s ease-out 3.1s forwards;
}
@keyframes dividerDraw { to { width: 240px; opacity: 1; } }

.idle-cta-tagline {
  font-family: 'Inter', -apple-system, sans-serif;
  font-style: italic;
  font-size: clamp(1rem, 1.8vw, 1.25rem);
  color: var(--cc-cream-mid);
  letter-spacing: 0.06em;
}
.idle-cta.animate .idle-cta-tagline {
  opacity: 0;
  transform: translateY(8px);
  animation: taglineFade 1.4s ease-out 4.2s forwards;
}
@keyframes taglineFade {
  to { opacity: 0.85; transform: translateY(0); }
}

.idle-brand { display: flex; flex-direction: column; align-items: center; gap: clamp(8px, 1.6vh, 18px); min-height: 0; }
.logo-big {
  width: clamp(220px, 44vw, 360px); height: auto;
  max-height: 26vh;                 /* shrink with vertical space so it never clips */
  object-fit: contain;
  filter: drop-shadow(0 0 70px rgba(172,202,50,0.5));
  animation: idleBreathe 5.6s ease-in-out infinite;
}
@keyframes idleBreathe {
  0%, 100% { filter: drop-shadow(0 0 40px rgba(172,202,50,0.35)); }
  50%      { filter: drop-shadow(0 0 75px rgba(172,202,50,0.6)); }
}
.event-title {
  font-family: var(--font-script);
  font-weight: 700;
  /* Bounded by BOTH width and height so a long event name (or a short
     screen) never blows the attract layout past the tap zone. */
  font-size: clamp(3rem, min(12vw, 9vh), 7rem);
  letter-spacing: 0;
  color: var(--cc-cream);
  text-shadow: 0 0 60px rgba(172,202,50,0.32), 0 6px 18px rgba(0,0,0,0.6);
  line-height: 1.04;
  max-width: 94%;
  overflow-wrap: break-word;
}
.event-meta {
  font-family: var(--font-mono);
  font-size: clamp(0.85rem, 2vw, 1rem);
  color: var(--cc-lime);
  letter-spacing: 0.22em;
  text-transform: uppercase;
}

/* ════════════════════════════════════════════════
   Template picker
   ════════════════════════════════════════════════ */
.tpl-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 18px;
  width: 100%;
  max-width: 760px;
}
.tpl-card {
  background: rgba(255,255,255,0.05);
  border: 2px solid rgba(255,255,255,0.1);
  border-radius: 20px;
  padding: 14px 14px 16px;
  cursor: pointer;
  transition: border-color 0.2s, transform 0.15s;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.tpl-card:hover { border-color: var(--cc-lime); transform: translateY(-3px); }
.tpl-card .tpl-preview {
  position: relative;
  width: 100%;
  aspect-ratio: var(--tpl-ratio, 1 / 3);
  max-height: 280px;
  margin: 0 auto;
  background: linear-gradient(135deg, var(--tpl-accent, #2C303B), #1B1D22);
  border-radius: 10px;
  overflow: hidden;
  box-shadow: 0 6px 18px rgba(0,0,0,0.4);
}
.tpl-card .tpl-preview img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: contain;
  z-index: 1;
}
.tpl-card .tpl-preview .tpl-slot {
  position: absolute;
  background: rgba(172,202,50,0.35);
  border: 1px dashed rgba(172,202,50,0.9);
  border-radius: 2px;
  box-sizing: border-box;
  z-index: 2;
}
.tpl-card .tpl-name {
  font-family: var(--font-display);
  font-size: 1.3rem;
  color: var(--cc-cream);
  text-align: center;
  margin: 0;
}
.tpl-card .tpl-meta {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--cc-cream-dim);
  text-align: center;
}

/* ════════════════════════════════════════════════
   CAPTURE SCREEN — portrait-first
   ════════════════════════════════════════════════ */
.capture-screen {
  padding: 0;
  gap: 0;
  justify-content: stretch;
}
/* Top slot collapsed — the counter moved to .cap-bottom so the camera
   preview gets the full top of the screen. Keeping the .cap-top element
   in the DOM (empty) avoids reflow issues in the flex column layout. */
.cap-top {
  width: 100%;
  height: 0;
  padding: 0;
  display: none;
  z-index: 2;
}
/* Bottom counter — smaller, subtle, out of the way of the guest's
   view of themselves. Sized about 40% smaller than the old top counter
   and sitting flush at the bottom edge with a tight pill. */
.cap-bottom {
  position: absolute;
  left: 50%; bottom: clamp(14px, 2.4vh, 26px);
  transform: translateX(-50%);
  z-index: 3;
  pointer-events: none;
}
.cap-photo-counter {
  font-family: var(--font-display, 'Bebas Neue'), sans-serif;
  font-size: clamp(1.4rem, 3.4vw, 2rem);
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--cc-cream);
  padding: 8px 22px;
  border-radius: 999px;
  background: rgba(0,0,0,0.6);
  border: 1.5px solid rgba(229,195,83,0.55);
  box-shadow:
    0 6px 20px rgba(0,0,0,0.5),
    0 0 22px rgba(229,195,83,0.14);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
.cap-photo-counter .of { color: var(--cc-cream-dim); margin: 0 0.3em; font-size: 0.72em; opacity: 0.75; }
.cap-photo-counter span#capN, .cap-photo-counter span#capTotal { color: var(--cc-gold, #E5C353); }

.cap-stage {
  position: relative;
  flex: 1;
  width: 100%;
  background: #000;
  overflow: hidden;
}
/* Both camera surfaces (<video> for built-in / <img> for UVC) are sized
   and positioned by JS (applySlotFrame) to match the crop guide pixel-for-
   pixel — so what guests see during countdown IS what gets printed. */
.cap-stage video,
.cap-stage #uvcPreviewImg {
  position: absolute;
  object-fit: cover;
  border-radius: 22px;
  transform: scaleX(-1); /* selfie mirror */
  z-index: 0;
}

/* USB camera preview: the native plugin streams base64 JPEG frames into
   #uvcPreviewImg via the Capacitor bridge. The img is hidden by default
   and shown only while a UVC camera is active (camera.js toggles display).
   No body/WebView transparency tricks needed — purely a layered <img>. */
/* Crop-area guide — only the inside of this rounded rectangle shows the
   camera; everything outside is masked nearly black via a heavy box-shadow.
   So guests focus on exactly what'll be in the strip, no distractions. */
/* Crop guide rectangle — sized and positioned in pixels by JS
   (applySlotFrame) to match the camera surfaces exactly. The heavy
   box-shadow masks everything outside so guests focus only on what's
   in-frame. NOTE: no top/left/transform centering here — JS owns
   the geometry and overlapping CSS positioning was double-offsetting
   the box, which is why it ended up off-screen up-left. */
.cap-crop-guide {
  position: absolute;
  border: 4px solid var(--cc-lime);
  border-radius: 22px;
  pointer-events: none;
  box-shadow:
    0 0 0 9999px var(--cc-graphite),
    0 0 0 6px rgba(172,202,50,0.18),
    0 14px 40px rgba(0,0,0,0.6),
    inset 0 0 28px rgba(0,0,0,0.25);
  z-index: 1;
}

/* Mini template strip in top-right showing current slot highlighted */
.cap-mini-strip {
  position: absolute;
  top: 18px; right: 18px;
  width: clamp(60px, 8vw, 90px);
  display: flex; flex-direction: column;
  background: linear-gradient(180deg, #2C303B, #1B1D22);
  border-radius: 8px;
  padding: 4px;
  gap: 3px;
  box-shadow: 0 4px 12px rgba(0,0,0,0.5);
  border: 1px solid rgba(255,255,255,0.12);
  z-index: 3;
}
.cap-mini-strip .mini-slot {
  flex: 1;
  border-radius: 3px;
  background: rgba(255,255,255,0.18);
  min-height: 14px;
}
.cap-mini-strip .mini-slot.active {
  background: var(--cc-lime);
  box-shadow: 0 0 0 1px rgba(172,202,50,0.5);
  animation: thumbPulse 1.2s ease-in-out infinite;
}
.cap-mini-strip .mini-slot.done { background: rgba(172,202,50,0.55); }
.cap-mini-strip.size-4x6 { aspect-ratio: 4 / 6; flex-direction: row; flex-wrap: wrap; }
.cap-mini-strip.size-4x6 .mini-slot { width: calc(50% - 3px); flex: none; aspect-ratio: 1; }
.cap-countdown {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  /* Bebas Neue for the countdown reads much more editorial / "wedding
     invitation" than boldest Inter — same size, more classy. */
  font-family: var(--font-display, 'Bebas Neue'), 'Inter', sans-serif;
  font-weight: 700;
  font-size: clamp(14rem, 52vw, 38rem);
  color: var(--cc-cream);
  letter-spacing: 0;
  line-height: 1;
  -webkit-text-stroke: 3px rgba(0,0,0,0.55);
  text-shadow:
    0 0 90px rgba(0,0,0,0.98),
    0 16px 44px rgba(0,0,0,0.75),
    0 0 40px rgba(229,195,83,0.4);
  pointer-events: none;
  opacity: 0;
  z-index: 2;
}
.cap-countdown.show { opacity: 1; transition: opacity 0.08s ease; }
.cap-countdown.tick {
  animation: tickPop 0.9s cubic-bezier(0.19, 1, 0.22, 1);
}
/* Professional countdown motion — gentle fade + subtle scale down from
   1.15 to 1 (was a jarring 1.8 → 1 slam). Reads editorial, not cartoony. */
@keyframes tickPop {
  0%   { transform: scale(1.18); opacity: 0.4; letter-spacing: -0.02em; }
  22%  { transform: scale(1.02); opacity: 1;   letter-spacing: 0; }
  100% { transform: scale(1);    opacity: 1;   letter-spacing: 0; }
}
/* Get Ready overlay — separate visual identity from per-photo countdowns.
   Tinted scrim, eyebrow + headline + smaller ticker + lime progress bar. */
.cap-getready-overlay {
  position: absolute; inset: 0;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  gap: 14px;
  padding: 24px;
  /* backdrop-filter removed intentionally: the overlay covers the live
     camera video during the Get Ready countdown, and re-blurring the
     underlying 1080p feed every frame was pinning the WebView compositor
     on low-end Android tablets (dropped the countdown to ~15fps between
     shots). The 88% opaque scrim already reads as "dimmed camera" without
     the blur — cheaper AND cleaner. */
  background:
    radial-gradient(circle at 50% 40%, rgba(172,202,50,0.18) 0%, transparent 60%),
    rgba(13,19,28,0.88);
  opacity: 0;
  pointer-events: none;
  z-index: 5;
  transition: opacity 0.12s ease;
}
.cap-getready-overlay.show { opacity: 1; }

/* ── PHOTO N OF M eyebrow — big + prominent (was tiny mono label) ── */
.cap-getready-overlay .getready-eyebrow {
  font-family: var(--font-display, 'Bebas Neue'), sans-serif;
  font-size: clamp(1.4rem, 3.6vw, 2.4rem);
  font-weight: 700;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--cc-gold, #E5C353);
  opacity: 1;
  padding: 6px 22px;
  border: 1.5px solid rgba(229,195,83,0.55);
  border-radius: 999px;
  background: rgba(0,0,0,0.35);
  box-shadow: 0 0 24px rgba(229,195,83,0.18);
}
/* ── GET READY headline ── */
.cap-getready-overlay .getready-title {
  font-family: var(--font-display, 'Bebas Neue'), sans-serif;
  font-size: clamp(4rem, 14vw, 9rem);
  font-weight: 900;
  letter-spacing: 0.04em;
  color: var(--cc-cream);
  line-height: 0.95;
  text-shadow: 0 8px 28px rgba(0,0,0,0.55), 0 0 60px rgba(172,202,50,0.35);
  animation: readyPulse 1.6s ease-in-out infinite;
}
@keyframes readyPulse {
  0%, 100% { transform: scale(1); text-shadow: 0 8px 28px rgba(0,0,0,0.55), 0 0 40px rgba(172,202,50,0.3); }
  50%      { transform: scale(1.04); text-shadow: 0 12px 36px rgba(0,0,0,0.55), 0 0 80px rgba(172,202,50,0.55); }
}
/* ── Standalone huge countdown numeral (was nested in sub, moved out) ── */
.cap-getready-overlay .getready-countdown {
  font-family: var(--font-display, 'Bebas Neue'), sans-serif;
  font-weight: 900;
  color: var(--cc-lime, #ACCA32);
  font-size: clamp(8rem, 26vw, 18rem);
  line-height: 0.9;
  text-shadow:
    0 0 40px rgba(172,202,50,0.85),
    0 12px 40px rgba(0,0,0,0.7);
  margin: -6px 0;
}
.cap-getready-overlay .getready-countdown.tick {
  animation: grCountdownTick 0.9s cubic-bezier(0.19, 1, 0.22, 1);
}
@keyframes grCountdownTick {
  0%   { transform: scale(1.28); opacity: 0.4;  filter: blur(2px); }
  22%  { transform: scale(1.03); opacity: 1;    filter: blur(0);   }
  100% { transform: scale(1);    opacity: 1;    filter: blur(0);   }
}
/* ── "Don't forget to look at the camera" instruction — LEGIBLE. Warm
   cream on a strong dark background from the overlay scrim; body font,
   comfortable reading size, subtle animation so it draws the eye. ── */
.cap-getready-overlay .getready-instruction,
.cap-getready-overlay .getready-sub {
  font-family: var(--font-body, 'Inter'), -apple-system, sans-serif;
  font-size: clamp(1.15rem, 2.6vw, 1.6rem);
  font-weight: 600;
  color: var(--cc-cream, #F2F4EE);
  letter-spacing: 0.01em;
  line-height: 1.35;
  max-width: 34ch;
  text-align: center;
  padding: 10px 20px;
  border-radius: 12px;
  background: rgba(0,0,0,0.42);
  text-shadow: 0 2px 12px rgba(0,0,0,0.65);
  animation: grInstructionBreathe 3.2s ease-in-out infinite;
}
@keyframes grInstructionBreathe {
  0%, 100% { opacity: 0.9; }
  50%      { opacity: 1;   }
}
/* Old rule for sub > span is now dead (countdown is its own element) */
.cap-getready-overlay .getready-sub span {
  all: unset;
  color: inherit;
  font: inherit;
}
/* Hide the old .getready-cta if any older HTML slips in */
.cap-getready-overlay .getready-cta { display: none !important; }
.cap-getready-overlay .getready-bar {
  width: clamp(180px, 30vw, 320px);
  height: 6px;
  border-radius: 999px;
  background: rgba(255,255,255,0.12);
  overflow: hidden;
  margin-top: 6px;
}
.cap-getready-overlay .getready-bar-fill {
  width: 0%;
  height: 100%;
  background: linear-gradient(90deg, var(--cc-lime), var(--cc-lime-hot));
  box-shadow: 0 0 12px rgba(172,202,50,0.6);
  transition: width 0.95s linear;
}

/* Captured-photo preview — between-shot beat. Larger, longer, with a slot
   caption so guests know which photo they just nailed. */
.cap-gotit {
  position: absolute; inset: 0;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  gap: 22px;
  /* backdrop-filter removed: same reason as .cap-getready-overlay — the
     overlay sits on top of the live camera feed, so re-blurring the 1080p
     video every frame pinned the WebView compositor and made the "Got it!"
     preview either not appear or fade in visibly late. Cranked the scrim
     to 96% opaque; reads as "camera dimmed" without the GPU cost. */
  background: rgba(13,19,28,0.96);
  z-index: 100;
  opacity: 0;
  pointer-events: none;
  /* Bumped from 0.08s → 0.14s: on slower tablets 80ms was too quick — the
     fade-in blitted mid-transition and looked like a hard cut. 140ms feels
     like a real "reveal" while still fitting well inside the 1s preview. */
  transition: opacity 0.14s ease;
}
.cap-gotit.show { opacity: 1; }
.cap-gotit-frame {
  position: relative;
  max-width: 75%;
  max-height: 65vh;
  border-radius: 18px;
  overflow: hidden;
  border: 5px solid var(--cc-lime);
  box-shadow:
    0 30px 80px rgba(0,0,0,0.7),
    0 0 80px rgba(172,202,50,0.45);
  transform: scale(0.96);
  transition: transform 0.16s cubic-bezier(0.16, 1, 0.3, 1);
}
.cap-gotit.show .cap-gotit-frame { transform: scale(1); }
/* The frame is given an explicit width + aspect-ratio by JS so it visually
   crops the raw camera frame to match what the strip will hold. The image
   uses object-fit:cover to center-crop into that aspect — same behavior as
   the canvas snap crop but with zero CPU work. */
.cap-gotit-frame {
  width: min(75vw, calc(65vh * var(--gotit-ratio, 1)));
  aspect-ratio: var(--gotit-ratio, 4 / 3);
  overflow: hidden;
}
.cap-gotit-frame img {
  width: 100%; height: 100%;
  display: block;
  object-fit: cover;
  /* CSS mirror is toggled inline by showCapturedPhoto based on whether
     the source data URL is already mirrored. */
}
.cap-gotit-label {
  font-family: 'Inter', -apple-system, sans-serif;
  font-weight: 900;
  /* Bigger so it's readable from across a venue — guests stand 6-10 ft
     away from the booth. */
  font-size: clamp(2.6rem, 6.5vw, 4rem);
  letter-spacing: -0.01em;
  color: var(--cc-lime);
  text-align: center;
  text-shadow: 0 4px 24px rgba(0,0,0,0.5);
}

/* Thumbnail strip across the bottom */
.cap-thumbs {
  width: 100%;
  padding: 16px 20px;
  display: flex; gap: 10px; justify-content: center;
  z-index: 2;
  background: rgba(0,0,0,0.5);
}
.cap-thumb {
  width: clamp(60px, 14vw, 90px);
  aspect-ratio: 1;
  border-radius: 12px;
  border: 2px solid rgba(255,255,255,0.12);
  overflow: hidden;
  background: rgba(255,255,255,0.04);
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-display);
  font-size: 1.6rem;
  color: var(--cc-cream-dim);
  position: relative;
}
.cap-thumb.taken { border-color: var(--cc-lime); background: transparent; }
.cap-thumb.taken img { width: 100%; height: 100%; object-fit: cover; transform: scaleX(-1); }
.cap-thumb.active {
  border-color: var(--cc-lime);
  color: var(--cc-lime);
  box-shadow: 0 0 0 4px rgba(172,202,50,0.2);
  animation: thumbPulse 1.2s ease-in-out infinite;
}
@keyframes thumbPulse {
  0%, 100% { box-shadow: 0 0 0 4px rgba(172,202,50,0.2); }
  50%      { box-shadow: 0 0 0 8px rgba(172,202,50,0.05); }
}
.cap-thumb.pending { border-style: dashed; }

/* Full-screen camera flash — booth fill-light effect for dark venues.
   Peak opacity is controlled by --flash-peak (0..1, default 1) which is
   set from the Flash brightness slider on the pairing screen. Native
   screen brightness is always at max during capture so the flash actually
   puts out light, not just changes the page color. */
.camera-flash {
  position: fixed; inset: 0;
  /* PURE WHITE = maximum panel luminance, and daylight-balanced like a real
     studio strobe (AlienBees ~5600K). The booth uses this overlay as its
     actual key light, so we want every nit the screen can put out. Color is
     a CSS var so it can be warmed back down per-tablet if a venue needs it. */
  background: var(--flash-color, #ffffff);
  opacity: 0;
  pointer-events: none;
  z-index: 9999;
  --flash-peak: 1;
}
.camera-flash.fire {
  animation: cameraFlash 950ms ease-out forwards;
}
@keyframes cameraFlash {
  0%   { opacity: 0; }
  4%   { opacity: var(--flash-peak); }                    /* snap to peak fast */
  60%  { opacity: var(--flash-peak); }                    /* HOLD bright through the whole exposure */
  80%  { opacity: calc(var(--flash-peak) * 0.55); }       /* gentle fade */
  100% { opacity: 0; }
}

/* Flash brightness control on the idle screen — sits below the Reprint
   button as a compact operator panel. Stays unobtrusive but in reach. */
.flash-control {
  margin-top: 18px;
  width: min(440px, 88%);
  padding: 14px 18px;
  background: rgba(0,0,0,0.32);
  border: 1px solid rgba(172,202,50,0.22);
  border-radius: 14px;
  display: flex; flex-direction: column; gap: 10px;
}
.flash-control-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px;
}
.flash-control-label {
  font-family: var(--font-mono);
  font-size: 0.74rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--cc-cream-dim);
}
.flash-control-val {
  font-family: var(--font-mono);
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--cc-lime);
}
.flash-control input[type="range"] { flex: 1; }
.flash-control #flashTestBtn {
  padding: 8px 16px;
  font-size: 0.78rem;
  min-width: 72px;
}

/* Lime-themed range slider for the flash brightness control */
input[type="range"] {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 6px;
  background: rgba(255,255,255,0.12);
  border-radius: 999px;
  outline: none;
  cursor: pointer;
}
input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 22px; height: 22px;
  background: var(--cc-lime);
  border-radius: 50%;
  cursor: pointer;
  box-shadow: 0 2px 8px rgba(172,202,50,0.5);
}
input[type="range"]::-moz-range-thumb {
  width: 22px; height: 22px;
  background: var(--cc-lime);
  border: none;
  border-radius: 50%;
  cursor: pointer;
}

/* ════════════════════════════════════════════════
   PREVIEW SCREEN — strip dominant + 4 big actions
   ════════════════════════════════════════════════ */
.preview-screen {
  padding: clamp(16px, 3vh, 28px);
  gap: clamp(14px, 2vh, 22px);
  justify-content: flex-start;
}
.preview-head {
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  padding-top: 8px;
}
.preview-stage {
  flex: 1;
  width: 100%;
  display: flex; align-items: center; justify-content: center;
  background:
    repeating-conic-gradient(rgba(255,255,255,0.025) 0 25%, transparent 0 50%) 50% / 22px 22px;
  border-radius: 18px;
  padding: 16px;
  min-height: 0;
  overflow: hidden;
}
#compositeCanvas {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  display: block;
  border-radius: 8px;
  box-shadow: 0 30px 80px rgba(0,0,0,0.55);
  background: #000;
}

.preview-actions {
  /* Flex auto-stretches visible buttons across the row when some are
     hidden (event.printEnabled/smsEnabled/retakeEnabled toggles in the
     admin dashboard). Each visible action-btn gets an equal share. */
  display: flex;
  flex-wrap: nowrap;
  gap: 12px;
  width: 100%;
  max-width: 720px;
}
.action-btn { flex: 1 1 0; min-width: 0; }
.action-btn {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 6px;
  padding: 18px 8px;
  border-radius: 18px;
  border: 2px solid;
  background: rgba(255,255,255,0.05);
  color: var(--cc-cream);
  font-family: var(--font-display);
  font-size: clamp(1rem, 2.4vw, 1.3rem);
  letter-spacing: 0.08em;
  cursor: pointer;
  transition: background 0.15s, transform 0.1s;
}
.action-btn:active { transform: scale(0.97); }
.action-btn .ico { font-size: clamp(1.8rem, 5vw, 2.6rem); line-height: 1; }
.action-btn .lbl { font-weight: 400; }
.action-btn.print  { border-color: var(--cc-lime); color: var(--cc-lime); }
.action-btn.text   { border-color: var(--cyan);    color: var(--cyan);    }
.action-btn.retake { border-color: rgba(255,255,255,0.18); color: var(--cc-cream-mid); }
.action-btn.done   { border-color: var(--cc-gold); color: var(--cc-gold); }
.action-btn.print:hover  { background: rgba(172,202,50,0.12); }
.action-btn.text:hover   { background: rgba(0,212,255,0.12); }
.action-btn.retake:hover { background: rgba(255,255,255,0.08); }
.action-btn.done:hover   { background: rgba(229,195,83,0.12); }

/* ════════════════════════════════════════════════
   COPIES PICKER
   ════════════════════════════════════════════════ */
.copies-grid {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: clamp(10px, 1.6vw, 16px);
  max-width: 720px;
  width: 100%;
}
@media (max-width: 520px) { .copies-grid { grid-template-columns: repeat(3, 1fr); } }
/* Premium tactile keycaps — match the dialpad / keyboard language. */
.copies-num {
  font-family: var(--font-display);
  font-size: clamp(2.2rem, 6vw, 3.4rem);
  aspect-ratio: 1 / 1;
  display: flex; align-items: center; justify-content: center;
  padding: 0;
  border-radius: 18px;
  color: var(--cc-cream);
  background: linear-gradient(180deg, var(--cc-graphite-3), var(--cc-graphite-2));
  border: 1px solid rgba(242,244,238,0.1);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.07), 0 4px 0 rgba(0,0,0,0.42), 0 8px 16px rgba(0,0,0,0.3);
  cursor: pointer;
  transition: transform 0.07s ease, box-shadow 0.12s, background 0.14s, border-color 0.14s, color 0.14s;
}
.copies-num:hover { background: linear-gradient(180deg, rgba(172,202,50,0.2), rgba(172,202,50,0.06)); border-color: rgba(172,202,50,0.5); color: var(--cc-lime-hot); }
.copies-num:active { transform: translateY(3px); box-shadow: inset 0 1px 0 rgba(255,255,255,0.04), 0 1px 4px rgba(0,0,0,0.4); }
.copies-qty {
  margin-top: clamp(8px, 1.6vh, 16px);
  padding: clamp(14px, 2vh, 18px) clamp(24px, 4vw, 34px);
  font-family: var(--font-body);
  font-weight: 800;
  font-size: clamp(1rem, 2.2vw, 1.18rem);
  letter-spacing: 0.06em;
  background: linear-gradient(180deg, rgba(229,195,83,0.16), rgba(229,195,83,0.06));
  border: 1.5px solid rgba(229,195,83,0.42);
  color: var(--cc-gold);
  border-radius: 14px;
  cursor: pointer;
  transition: background 0.15s, transform 0.1s, box-shadow 0.12s;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.06);
}
.copies-qty:hover { background: linear-gradient(180deg, rgba(229,195,83,0.24), rgba(229,195,83,0.1)); }
.copies-qty:active { transform: translateY(2px); }

/* Custom quantity screen */
/* ── Custom quantity: clean type-in numpad ── */
.qty-wrap {
  display: flex; flex-direction: column; align-items: center;
  gap: clamp(14px, 2.4vh, 26px);
  width: min(380px, 88vw);
}
.qty-headblock { text-align: center; display: flex; flex-direction: column; gap: 4px; }
.qty-h1 { font-family: var(--font-display); font-size: clamp(2rem, 6vw, 2.8rem); letter-spacing: 0.03em; color: var(--cc-cream); margin: 0; line-height: 1; }
.qty-hint { font-family: var(--font-body); font-size: clamp(0.85rem, 1.9vw, 1rem); color: var(--cc-cream-mid); margin: 0; }
.qty-readout {
  display: flex; align-items: center; justify-content: center;
  min-width: clamp(150px, 44vw, 220px);
  padding: clamp(8px, 1.4vh, 14px) 28px;
  background: rgba(0,0,0,0.30);
  border: 1.5px solid rgba(172,202,50,0.3);
  border-radius: 16px;
  box-shadow: inset 0 2px 10px rgba(0,0,0,0.45);
}
.qty-num { font-family: var(--font-display); font-size: clamp(2.6rem, 9vw, 3.8rem); line-height: 1; letter-spacing: 0.04em; color: var(--cc-lime); text-shadow: 0 0 26px rgba(172,202,50,0.4); }
.qty-num.qty-empty { color: rgba(242,244,238,0.28); text-shadow: none; }
.qty-pad {
  display: grid; grid-template-columns: repeat(3, 1fr);
  gap: clamp(9px, 1.6vw, 14px);
  width: 100%;
}
.qty-key {
  aspect-ratio: 1 / 1;
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-display); font-size: clamp(1.7rem, 6vw, 2.4rem);
  color: var(--cc-cream);
  background: linear-gradient(180deg, var(--cc-graphite-3), var(--cc-graphite-2));
  border: 1px solid rgba(242,244,238,0.1);
  border-radius: 16px;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.07), 0 4px 0 rgba(0,0,0,0.42), 0 7px 14px rgba(0,0,0,0.3);
  cursor: pointer;
  transition: transform 0.06s ease, box-shadow 0.12s, background 0.14s, color 0.14s, border-color 0.14s;
}
.qty-key:hover { background: linear-gradient(180deg, rgba(172,202,50,0.2), rgba(172,202,50,0.06)); color: var(--cc-lime-hot); border-color: rgba(172,202,50,0.5); }
.qty-key:active { transform: translateY(3px); box-shadow: inset 0 1px 0 rgba(255,255,255,0.04), 0 1px 4px rgba(0,0,0,0.4); }
.qty-key-fn { font-family: var(--font-body); font-weight: 800; font-size: clamp(0.8rem, 2.4vw, 1.05rem); letter-spacing: 0.05em; text-transform: uppercase; color: var(--cc-cream-mid); }
.qty-key-back { color: var(--danger); }
.qty-key-back:active { background: linear-gradient(180deg, rgba(199,62,62,0.26), rgba(199,62,62,0.08)); border-color: rgba(199,62,62,0.45); color: var(--cc-cream); }
.qty-foot { display: flex; gap: clamp(10px, 2vw, 14px); width: 100%; }
.qty-foot .qty-btn { flex: 1; min-height: 56px; font-size: clamp(1rem, 2.4vw, 1.18rem); }

/* Reprint gallery */
.reprint-grid {
  display: grid;
  /* Fixed 180px column width with auto-fit + centering. The mixed
     min/max + aspect-ratio combo we had before let the browser do
     whatever it wanted per row, which caused the visible overlap on
     tablets. Going hard-fixed here. */
  grid-template-columns: repeat(auto-fit, 180px);
  grid-auto-rows: 320px;
  justify-content: center;
  align-content: start;
  gap: 18px;
  width: 100%;
  max-width: 1100px;
  max-height: 62vh;
  overflow-y: auto;
  overflow-x: hidden;
  padding: 16px 10px 28px;
  box-sizing: border-box;
  scrollbar-width: thin;
  scrollbar-color: rgba(172,202,50,0.5) rgba(255,255,255,0.05);
}
.reprint-grid::-webkit-scrollbar { width: 8px; }
.reprint-grid::-webkit-scrollbar-track { background: rgba(255,255,255,0.04); border-radius: 999px; }
.reprint-grid::-webkit-scrollbar-thumb { background: rgba(172,202,50,0.45); border-radius: 999px; }
.reprint-tile {
  position: relative;
  /* Fixed 180×320 so every tile occupies exactly one grid cell — no
     more aspect-ratio vs max-height fighting. The strip image inside
     uses object-fit: contain so 2x6 / 4x6 / 5x7 all fit cleanly with
     gentle letterboxing instead of stretching/cropping. */
  width: 180px;
  height: 320px;
  border-radius: 14px;
  overflow: hidden;
  background: rgba(255,255,255,0.03);
  border: 2px solid rgba(255,255,255,0.1);
  cursor: pointer;
  box-shadow: 0 6px 18px rgba(0,0,0,0.35);
  transition: transform 0.15s, border-color 0.2s, box-shadow 0.2s;
}
.reprint-tile:hover, .reprint-tile:active {
  border-color: var(--cc-lime);
  transform: translateY(-3px);
  box-shadow: 0 12px 30px rgba(0,0,0,0.5);
}
.reprint-tile img {
  width: 100%; height: 100%;
  /* contain so the full strip is visible regardless of its native
     aspect (2x6 / 4x6 / 5x7) — letterboxes with the dark tile bg
     showing top/bottom or sides as needed. */
  object-fit: contain;
  display: block;
}
.reprint-del {
  position: absolute;
  top: 6px; right: 6px;
  width: 30px; height: 30px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%;
  background: rgba(199,62,62,0.92);
  border: 2px solid rgba(255,255,255,0.85);
  color: #fff;
  font-size: 1.1rem;
  font-weight: 900;
  line-height: 1;
  cursor: pointer;
  box-shadow: 0 4px 12px rgba(0,0,0,0.5);
  opacity: 0;
  transition: opacity 0.15s, transform 0.1s, background 0.15s;
  z-index: 3;
}
.reprint-tile:hover .reprint-del,
.reprint-tile:focus-within .reprint-del { opacity: 1; }
@media (pointer: coarse) { .reprint-del { opacity: 0.9; } }   /* always visible on touch */
.reprint-del:hover  { background: #d84747; transform: scale(1.1); }
.reprint-del:active { transform: scale(0.92); }
.reprint-del:disabled { opacity: 0.4; cursor: wait; }
/* Failed image — surfaces the broken URL visibly so we can debug rather
   than guessing. onerror attribute on the <img> adds .broken to the tile. */
.reprint-tile.broken {
  background:
    repeating-linear-gradient(45deg, rgba(199,62,62,0.15) 0 10px, transparent 10px 20px),
    rgba(199,62,62,0.18);
  border-color: var(--danger);
}
.reprint-tile.broken::after {
  content: "⚠ broken link\A tap to see URL";
  white-space: pre-line;
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  text-align: center;
  color: var(--cc-cream);
  font-family: var(--font-mono);
  font-size: 0.75rem;
  padding: 8px;
  background: rgba(199,62,62,0.55);
  z-index: 2;
  pointer-events: none;
}
.reprint-tile { position: relative; }
.reprint-empty {
  grid-column: 1 / -1;
  text-align: center;
  padding: 60px 20px;
  color: rgba(242,244,238,0.55);
  font-size: 1rem;
}

/* ════════════════════════════════════════════════
   GET YOUR DIGITAL COPY — QR + URL + optional text link
   ════════════════════════════════════════════════ */
.send-share-screen {
  /* Was justify-content:center — caused tall content (two QRs + header +
     tips + buttons) to overflow off the top + bottom on tablet heights.
     Top-aligned + scrollable means nothing ever falls off; the Done
     button is always reachable. */
  justify-content: flex-start;
  align-items: center;
  padding: clamp(20px, 3vh, 36px) clamp(16px, 3vw, 40px);
  overflow-y: auto;
  /* Soft lime ambient glow behind the whole screen so the page reads as
     a premium "moment" rather than just another modal. */
  background:
    radial-gradient(ellipse 80% 60% at 50% 40%, rgba(172,202,50,0.18) 0%, transparent 60%),
    radial-gradient(ellipse 70% 50% at 50% 80%, rgba(229,195,83,0.08) 0%, transparent 70%);
}
.qr-shell {
  display: flex; flex-direction: column;
  align-items: center; justify-content: flex-start;
  /* Tighter vertical gap — earlier 36px values plus a ~700px QR + headers
     + tips + actions overflowed an 800px tablet viewport. */
  gap: clamp(12px, 1.8vh, 20px);
  width: 100%;
  max-width: min(1180px, 96vw);
  text-align: center;
  padding-bottom: clamp(16px, 2vh, 28px);
}
/* Side-by-side layout when both strip + event-gallery codes are shown.
   The grid auto-shrinks the QR cards based on AVAILABLE width AND height,
   not just viewport width — that's why we use vmin (smaller of vw/vh)
   for canvas sizing below. */
.qr-grid {
  display: flex; flex-direction: row; flex-wrap: wrap;
  align-items: flex-start; justify-content: center;
  gap: clamp(14px, 2vw, 32px);
  width: 100%;
}
.qr-col {
  display: flex; flex-direction: column;
  align-items: center;
  gap: clamp(8px, 1vh, 14px);
  flex: 0 1 auto;
}
.qr-col-eyebrow {
  font-family: var(--font-mono);
  font-size: clamp(0.7rem, 1.1vw, 0.85rem);
  font-weight: 700;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: rgba(242,244,238,0.78);
}
.qr-col-secondary .qr-col-eyebrow { color: rgba(172,202,50,0.82); }
.qr-card-secondary {
  padding: clamp(16px, 2vh, 26px);
  box-shadow:
    0 24px 60px rgba(172,202,50,0.32),
    0 0 80px rgba(172,202,50,0.18),
    inset 0 0 0 1px rgba(0,0,0,0.04);
}
.qr-card-secondary #qrEventCanvas {
  display: block;
  /* vmin keeps the secondary code from blowing out the available HEIGHT
     on landscape tablets where vw is huge but vh is the real constraint. */
  width: clamp(180px, 24vmin, 280px);
  height: clamp(180px, 24vmin, 280px);
  image-rendering: pixelated;
}
/* On narrow screens (portrait phones / small kiosks) stack vertically. */
@media (max-width: 720px) {
  .qr-grid { flex-direction: column; align-items: center; }
}
.qr-header {
  display: flex; flex-direction: column;
  align-items: center;
  gap: 8px;
}
.qr-eyebrow {
  font-family: var(--font-mono);
  font-size: clamp(0.75rem, 1.4vw, 0.95rem);
  font-weight: 700;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--cc-lime);
  text-shadow: 0 0 18px rgba(172,202,50,0.4);
}
.qr-title {
  font-family: var(--font-display, 'Bebas Neue'), sans-serif;
  /* Pulled down from 5.2vw / 4rem cap — the header was eating 200+ vertical
     pixels before the QR cards even rendered, pushing the Done button off
     the bottom on landscape tablets. */
  font-size: clamp(1.8rem, 3.6vw, 2.8rem);
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--cc-cream);
  margin: 0;
  line-height: 1.05;
}
.qr-sub {
  font-family: var(--font-body, 'Inter'), sans-serif;
  font-size: clamp(0.85rem, 1.4vw, 1rem);
  color: rgba(242,244,238,0.78);
  margin: 0;
}

/* Pure-white card that floats the QR. Lime glow + subtle scale-in. */
.qr-card {
  position: relative;
  padding: clamp(18px, 2.6vh, 30px);
  background: #ffffff;
  border-radius: 28px;
  box-shadow:
    0 30px 90px rgba(172,202,50,0.40),
    0 0 80px rgba(172,202,50,0.18),
    inset 0 0 0 1px rgba(0,0,0,0.04);
  animation: qrCardIn 0.55s cubic-bezier(0.16,1,0.3,1) both;
}
@keyframes qrCardIn {
  from { transform: scale(0.82) translateY(12px); opacity: 0; }
  to   { transform: scale(1)    translateY(0);   opacity: 1; }
}
#qrCanvas {
  display: block;
  /* vmin so the QR doesn't get clipped on a landscape tablet (~800px tall).
     Cap at 460px — beyond that the QR is already easily phone-scannable
     across the room and we're just consuming screen real-estate. */
  width: clamp(260px, 42vmin, 460px);
  height: clamp(260px, 42vmin, 460px);
  image-rendering: pixelated;
}
/* Four lime corner brackets framing the QR card — subtle viewfinder vibe */
.qr-card-corners { position: absolute; inset: 0; pointer-events: none; }
.qr-card-corners span {
  position: absolute;
  width: 26px; height: 26px;
  border: 3px solid var(--cc-lime);
  border-radius: 4px;
}
.qr-card-corners span:nth-child(1) { top: -10px; left: -10px;  border-right: none; border-bottom: none; }
.qr-card-corners span:nth-child(2) { top: -10px; right: -10px; border-left: none;  border-bottom: none; }
.qr-card-corners span:nth-child(3) { bottom: -10px; left: -10px;  border-right: none; border-top: none; }
.qr-card-corners span:nth-child(4) { bottom: -10px; right: -10px; border-left: none;  border-top: none; }

.qr-meta {
  display: flex; flex-direction: column;
  align-items: center; gap: clamp(8px, 1.2vh, 14px);
  width: 100%;
}
.qr-url-row {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 8px 18px;
  background: rgba(0,0,0,0.45);
  border: 1.5px solid rgba(172,202,50,0.35);
  border-radius: 999px;
  max-width: 92%;
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}
.qr-url-label {
  font-family: var(--font-mono);
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: rgba(242,244,238,0.55);
}
.qr-url {
  font-family: var(--font-mono);
  font-size: clamp(0.75rem, 1.2vw, 0.95rem);
  font-weight: 600;
  color: var(--cc-lime);
  letter-spacing: 0.02em;
  word-break: break-all;
}
.qr-tips {
  display: inline-flex; flex-wrap: wrap;
  align-items: center; justify-content: center;
  gap: 10px;
  padding: 4px 4px;
  color: rgba(242,244,238,0.62);
  font-family: var(--font-body, 'Inter'), sans-serif;
  font-size: clamp(0.72rem, 1.1vw, 0.85rem);
}
.qr-tip {
  display: inline-flex; align-items: center; gap: 8px;
  font-weight: 600;
}
.qr-tip-num {
  display: inline-flex;
  align-items: center; justify-content: center;
  width: 24px; height: 24px;
  border-radius: 50%;
  background: rgba(172,202,50,0.18);
  border: 1.5px solid rgba(172,202,50,0.55);
  color: var(--cc-lime);
  font-family: var(--font-mono);
  font-weight: 800;
  font-size: 0.78rem;
}
.qr-tip-sep {
  color: rgba(172,202,50,0.5);
  font-weight: 800;
}
.qr-actions {
  display: flex; flex-direction: row; flex-wrap: wrap;
  gap: 12px;
  justify-content: center;
  width: 100%;
  max-width: 540px;
  margin-top: clamp(2px, 0.5vh, 8px);
  /* Reserve space at the bottom of the screen so the buttons never get
     clipped by a tablet's gesture/nav bar even when scroll is disabled. */
  padding-bottom: 4px;
}
.qr-actions .btn {
  flex: 1; min-width: 160px;
  font-size: clamp(0.85rem, 1.3vw, 0.98rem);
  /* Match the tighter screen — overrides the global .big-btn that was
     adding ~80px of vertical for the Done/Send buttons. */
  padding: 14px 22px;
  min-height: 56px;
}

/* ════════════════════════════════════════════════
   SEND SCREEN — custom phone keypad
   ════════════════════════════════════════════════ */
.send-screen {
  justify-content: flex-start;
  padding-top: clamp(32px, 5vh, 60px);
  padding-bottom: clamp(24px, 4vh, 40px);
  gap: clamp(14px, 2vh, 22px);
}
.phone-display {
  display: inline-flex;
  align-items: baseline; gap: 14px;
  padding: 22px 38px;
  background: rgba(0,0,0,0.4);
  border: 2px solid rgba(172,202,50,0.45);
  border-radius: 20px;
  font-family: var(--font-mono);
  box-shadow:
    0 0 30px rgba(172,202,50,0.15),
    inset 0 2px 8px rgba(0,0,0,0.3);
}
.phone-prefix {
  color: var(--cc-cream-dim);
  font-size: clamp(1rem, 2.4vw, 1.3rem);
  letter-spacing: 0.1em;
}
.phone-digits {
  font-size: clamp(1.6rem, 4.5vw, 2.4rem);
  font-weight: 600;
  color: var(--cc-cream);
  letter-spacing: 0.08em;
}

/* Queued recipient chips — appear above the keypad once "Add another"
   has been tapped. Tap a chip to remove that recipient. */
.phone-recipients {
  display: flex; flex-wrap: wrap; justify-content: center;
  gap: 8px;
  max-width: 92%;
  min-height: 0;
}
.phone-recipients:empty { display: none; }
.phone-chip {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 8px 14px;
  background: rgba(172,202,50,0.12);
  border: 1.5px solid rgba(172,202,50,0.55);
  border-radius: 999px;
  color: var(--cc-lime);
  font-family: var(--font-mono);
  font-size: 0.85rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  cursor: pointer;
  transition: background 0.15s, transform 0.1s;
}
.phone-chip:hover  { background: rgba(172,202,50,0.2); }
.phone-chip:active { transform: scale(0.97); }
.phone-chip .x {
  font-weight: 900;
  font-size: 1.1em;
  color: var(--cc-cream-mid);
  line-height: 1;
}

/* iPhone-style circular keypad. Each key is a perfect circle via
   aspect-ratio:1 + border-radius:50%. Grid items justify to center so the
   circles don't stretch with the column width. */
.keypad {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(14px, 2.4vw, 22px);
  width: 100%;
  max-width: 440px;
  justify-items: center;
}
.key {
  font-family: var(--font-display);
  font-size: clamp(2.4rem, 7vw, 3.4rem);
  width: clamp(82px, 22vw, 110px);
  aspect-ratio: 1;
  padding: 0;
  background: rgba(255,255,255,0.08);
  border: 1.5px solid rgba(255,255,255,0.15);
  color: var(--cc-cream);
  border-radius: 50%;
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  transition: background 0.12s, transform 0.08s, color 0.12s, border-color 0.12s,
              box-shadow 0.12s;
  box-shadow:
    inset 0 2px 6px rgba(255,255,255,0.08),
    0 4px 12px rgba(0,0,0,0.3);
}
.key:hover {
  background: rgba(172,202,50,0.15);
  color: var(--cc-lime);
  border-color: rgba(172,202,50,0.45);
  box-shadow: inset 0 2px 6px rgba(255,255,255,0.08), 0 0 16px rgba(172,202,50,0.25);
}
.key:active {
  transform: scale(0.92);
  background: rgba(172,202,50,0.28);
  box-shadow: inset 0 2px 6px rgba(0,0,0,0.25);
}
.key-fn {
  font-family: var(--font-body);
  font-size: clamp(0.9rem, 2.2vw, 1.1rem);
  font-weight: 800;
  letter-spacing: 0.08em;
  color: var(--cc-cream-mid);
  text-transform: uppercase;
}
.key-back {
  font-size: clamp(1.4rem, 3.5vw, 1.8rem);
  color: var(--danger);
  border-color: rgba(199,62,62,0.32);
}
.key-back:hover {
  background: rgba(199,62,62,0.15);
  color: var(--danger);
  border-color: var(--danger);
  box-shadow: inset 0 2px 6px rgba(255,255,255,0.05), 0 0 16px rgba(199,62,62,0.3);
}

/* Pairing on-screen keyboard */
.kbd { display: flex; flex-direction: column; gap: 8px; width: 100%; max-width: 580px; margin: 4px auto 2px; }
.kbd-row { display: flex; gap: 6px; justify-content: center; }
.kkey { flex: 1 1 0; min-width: 0; padding: 16px 0; font-family: var(--font-display); font-size: 1.35rem; line-height: 1; color: var(--cc-cream); background: rgba(255,255,255,0.08); border: 1.5px solid rgba(255,255,255,0.15); border-radius: 12px; cursor: pointer; transition: background 0.1s, transform 0.06s, border-color 0.1s, color 0.1s; }
.kkey:hover { background: rgba(172,202,50,0.15); color: var(--cc-lime); border-color: rgba(172,202,50,0.45); }
.kkey:active { transform: scale(0.93); background: rgba(172,202,50,0.28); }
.kkey.fn { font-family: var(--font-body); font-size: 0.92rem; font-weight: 800; letter-spacing: 0.04em; text-transform: uppercase; color: var(--cc-cream-mid); flex: 1.5 1 0; }
.kkey.on { background: rgba(172,202,50,0.28); color: var(--cc-lime); border-color: rgba(172,202,50,0.55); }
.kkey.back { color: var(--danger); border-color: rgba(199,62,62,0.32); }
.kkey.back:active { background: rgba(199,62,62,0.28); }
@media (max-width: 600px) { .kkey { font-size: 1.1rem; padding: 13px 0; } .kbd-row { gap: 5px; } .kkey.fn { font-size: 0.78rem; } }

/* POS-terminal keypad — readout + keypad grouped into one grounded panel */
.ip-pad {
  width: 100%;
  display: flex; flex-direction: column; gap: 16px;
  background: rgba(255,255,255,0.035);
  border: 1px solid rgba(255,255,255,0.1);
  border-radius: 20px;
  padding: 18px 18px 20px;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.05), 0 8px 24px rgba(0,0,0,0.22);
}
.ip-pad .ip-display {
  width: 100%; max-width: none; text-align: center;
  font-family: var(--font-mono); font-size: clamp(1.7rem, 6vw, 2.3rem); font-weight: 600;
  letter-spacing: 0.04em; color: var(--cc-cream);
  background: rgba(0,0,0,0.28);
  border: 1.5px solid rgba(255,255,255,0.12); border-radius: 14px;
  padding: 16px 18px; margin: 0;
}
.ip-pad .ip-display::placeholder { color: rgba(242,244,238,0.3); font-weight: 400; }
.ip-pad .kbd { margin: 0; max-width: 100%; align-items: center; gap: 6px; }

/* Phone-style dialpad for the IP keypad — reuses the round .key from the SMS
   keypad, stacks the digit over classic letter sub-labels (ABC/DEF…). */
.dialpad { margin: 0 auto; max-width: 340px; gap: clamp(12px, 2.6vw, 20px); }
.dialpad .key { flex-direction: column; gap: 1px; width: clamp(72px, 19vw, 92px); }
.dialpad .kdigit { font-family: var(--font-display); font-size: clamp(1.8rem, 6vw, 2.4rem); line-height: 1; }
.dialpad .ksub { font-family: var(--font-body); font-weight: 700; font-size: clamp(0.5rem, 1.5vw, 0.6rem); letter-spacing: 0.16em; color: var(--cc-cream-dim); }
.dialpad .key-back .kdigit { font-size: clamp(1.4rem, 4.4vw, 1.8rem); }
.dialpad-clear {
  display: block; margin: 4px auto 0; padding: 10px 18px;
  background: transparent; border: none; cursor: pointer;
  font-family: var(--font-body); font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.12em; font-size: 0.82rem; color: var(--cc-cream-dim);
}
.dialpad-clear:active { color: var(--cc-lime); }
/* Highlight whichever field the keypad is currently driving (Advanced login) */
.adv-input.field-active { border-color: rgba(172,202,50,0.55); box-shadow: 0 0 0 3px rgba(172,202,50,0.14); }

/* Pairing "Booth setup" expander */
.setup-panel { display: flex; flex-direction: column; gap: 12px; align-self: stretch; width: 100%; margin-top: 4px; padding-top: 14px; border-top: 1px solid rgba(242,244,238,0.1); }

/* Pairing screen — clean card + segmented code boxes */
.pairing-screen, .printer-screen { justify-content: center; gap: 0; }
.pair-card {
  width: min(680px, 92vw);
  display: flex; flex-direction: column; align-items: center;
  gap: clamp(16px, 2.6vh, 28px);
  background: rgba(255,255,255,0.045);
  border: 1px solid rgba(242,244,238,0.1);
  border-radius: 30px;
  padding: clamp(30px, 5vw, 52px) clamp(24px, 4vw, 44px);
  box-shadow: 0 30px 90px rgba(0,0,0,0.4);
  max-height: calc(100vh - 24px); overflow-y: auto;
}
.pair-card .screen-title { font-size: clamp(2.4rem, 7vw, 3.6rem); letter-spacing: 0.03em; line-height: 1.0; margin: 0; }
.pair-card .screen-sub { font-size: clamp(0.95rem, 2vw, 1.15rem); margin: -6px 0 2px; max-width: 100%; }
.code-hidden-input { position: absolute; opacity: 0; width: 1px; height: 1px; pointer-events: none; }
.code-boxes { display: flex; gap: clamp(10px, 1.8vw, 16px); justify-content: center; margin: 2px 0; }
.code-box {
  width: clamp(50px, 13vw, 68px); height: clamp(62px, 16vw, 84px);
  border-radius: 16px; background: rgba(255,255,255,0.06);
  border: 2px solid rgba(242,244,238,0.16);
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-display); font-size: clamp(2rem, 7vw, 2.8rem); color: var(--cc-cream);
  transition: border-color 0.12s, box-shadow 0.12s, background 0.12s;
}
.code-box.filled { border-color: rgba(172,202,50,0.6); background: rgba(172,202,50,0.1); }
.code-box.active { border-color: var(--cc-lime); box-shadow: 0 0 0 4px rgba(172,202,50,0.18); }
.pair-card .kbd { width: 100%; max-width: 620px; gap: 9px; margin: 2px auto; }
.pair-card .kbd-row { gap: 8px; }
.pair-card .kkey { padding: clamp(15px, 2vh, 20px) 0; font-size: clamp(1.2rem, 3.4vw, 1.55rem); border-radius: 14px; }
.pair-card .kkey.fn { font-size: clamp(0.8rem, 2vw, 1rem); }
.pair-card .big-btn { width: 100%; padding: clamp(18px, 2.4vh, 24px); font-size: clamp(1.15rem, 2.8vw, 1.4rem); margin-top: 4px; }
.pair-card .big-btn-sm { width: 100%; }
.pair-go:disabled { opacity: 0.45; cursor: not-allowed; }

/* ════════════════════════════════════════════════════════════════
   PAIRING SCREEN — "ATELIER GLASS" luxury elevation
   Unified frosted-glass instrument: sapphire readout on top, keyboard
   directly below; milled metallic + gold-hairline bezel; one GPU-cheap
   aurora drifts far behind; engineered lime CTA with a one-shot sweep.
   Lime = the single ACTION accent. Gold = hairline micro-accents only.
   ════════════════════════════════════════════════════════════════ */
.pairing-screen {
  /* NB: do NOT set position here — the base .screen is position:fixed;inset:0,
     which gives the full-viewport height the card centers against. */
  justify-content: center;     /* center the card vertically in the screen */
  gap: 0;
  padding: 0;
  overflow: hidden;
  isolation: isolate;
  background:
    radial-gradient(125% 80% at 50% -8%, rgba(44,48,59,0.9) 0%, transparent 55%),
    radial-gradient(120% 70% at 50% 118%, rgba(0,0,0,0.5) 0%, transparent 60%),
    var(--cc-graphite);
}

/* ── Ambient aurora: far-behind, transform-only drift, GPU-cheap ── */
.pair-aurora { position: absolute; inset: 0; z-index: 0; pointer-events: none; overflow: hidden; }
/* filter: blur(70px) on a 70vw element is extraordinarily expensive to
   rasterize on Android WebView — dropped to 40px, still reads as an
   ambient aurora glow, cuts rasterization cost roughly in half. */
.aurora-blob { position: absolute; border-radius: 50%; filter: blur(40px); opacity: 0.5; will-change: transform; mix-blend-mode: screen; }
.aurora-a {
  width: 70vw; height: 70vw; top: -22vw; left: -14vw;
  background: radial-gradient(circle, rgba(172,202,50,0.30) 0%, rgba(172,202,50,0) 68%);
  animation: auroraDriftA 36s ease-in-out infinite alternate;
}
.aurora-b {
  width: 64vw; height: 64vw; bottom: -26vw; right: -16vw;
  background: radial-gradient(circle, rgba(229,195,83,0.18) 0%, rgba(229,195,83,0) 68%);
  animation: auroraDriftB 44s ease-in-out infinite alternate;
}
.aurora-grain { position: absolute; inset: 0; background: radial-gradient(140% 100% at 50% 40%, transparent 55%, rgba(0,0,0,0.4) 100%); opacity: 0.9; }
@keyframes auroraDriftA { 0% { transform: translate3d(0,0,0) scale(1); } 100% { transform: translate3d(7vw, 5vh, 0) scale(1.12); } }
@keyframes auroraDriftB { 0% { transform: translate3d(0,0,0) scale(1.05); } 100% { transform: translate3d(-6vw, -4vh, 0) scale(1); } }

/* Card sits above the aurora. Do NOT make .brand-row relative — it must keep
   the base position:absolute + left:50%/translateX(-50%) so it stays centered. */
.pairing-screen .pair-card { position: relative; z-index: 1; }
.pairing-screen .brand-row { z-index: 5; }

/* Watermark — pairing screen only. Subtle, centered at the very bottom. */
.pair-watermark {
  position: absolute; left: 50%; bottom: clamp(14px, 2.4vh, 26px);
  transform: translateX(-50%); z-index: 2;
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  text-align: center; pointer-events: none;
}
.pair-watermark-product {
  font-family: var(--font-body); font-weight: 800;
  font-size: clamp(0.7rem, 1.5vw, 0.82rem); letter-spacing: 0.22em; text-transform: uppercase;
  color: rgba(242,244,238,0.42);
}
.pair-watermark-by {
  font-family: var(--font-mono);
  font-size: clamp(0.58rem, 1.2vw, 0.68rem); letter-spacing: 0.14em; text-transform: uppercase;
  color: rgba(242,244,238,0.3);
}
.pair-watermark-by strong { color: var(--cc-lime); opacity: 0.7; font-weight: 700; }

/* ── Brand lockup: gold hairline separator + soft lime logo glow ── */
.pairing-screen .pair-brand .logo-img { filter: drop-shadow(0 0 14px rgba(172,202,50,0.4)) drop-shadow(0 1px 1px rgba(0,0,0,0.5)); }
.pair-brand .brand-hair { width: 1px; height: clamp(20px, 4vw, 28px); background: linear-gradient(180deg, transparent, rgba(229,195,83,0.55), transparent); margin: 0 2px; }
.pairing-screen .wordmark .dot { box-shadow: 0 0 8px rgba(172,202,50,0.6), 0 0 0 2px rgba(229,195,83,0.35); }

.pairing-screen .pair-card {
  width: min(640px, 94vw);
  height: auto;                   /* size to content; centered via margin:auto */
  max-height: 100%;
  margin: auto;                   /* absorbs free space on all sides → true centering */
  display: flex;
  flex-direction: column;
  align-items: stretch;
  justify-content: center;
  gap: clamp(16px, 2.6vh, 30px);
  background: none;
  border: none;
  border-radius: 0;
  box-shadow: none;
  overflow: visible;
  padding: clamp(20px, 3.5vh, 40px) clamp(20px, 5vw, 36px);
}

/* ── Refined typographic lockup ── */
.pair-head { display: flex; flex-direction: column; align-items: center; text-align: center; gap: clamp(6px, 1.1vh, 11px); }
.pair-eyebrow {
  display: inline-flex; align-items: center; gap: 0.7em;
  font-family: var(--font-mono); font-size: clamp(0.66rem, 1.6vw, 0.78rem);
  letter-spacing: 0.36em; text-transform: uppercase; color: var(--cc-lime); opacity: 0.92; padding-left: 0.36em;
}
.eyebrow-tick { width: 6px; height: 6px; transform: rotate(45deg); background: var(--cc-gold); box-shadow: 0 0 8px rgba(229,195,83,0.55); }
.pairing-screen .pair-title {
  font-size: clamp(3.4rem, 13vw, 5rem); letter-spacing: 0.06em; line-height: 0.92; margin: 0;
  background: linear-gradient(180deg, #ffffff 0%, var(--cc-cream) 42%, rgba(242,244,238,0.78) 100%);
  -webkit-background-clip: text; background-clip: text; color: transparent; -webkit-text-fill-color: transparent;
  text-shadow: 0 1px 0 rgba(0,0,0,0.25);
}
.pair-rule { width: clamp(52px, 12vw, 84px); height: 1px; margin: clamp(2px, 0.6vh, 6px) 0 clamp(2px, 0.4vh, 4px); background: linear-gradient(90deg, transparent, rgba(229,195,83,0.7), transparent); }
.pairing-screen .pair-sub { font-size: clamp(1rem, 2.4vw, 1.18rem); color: var(--cc-cream-mid); max-width: 30ch; margin: 0 auto; line-height: 1.45; }
.code-hidden-input { position: absolute; opacity: 0; width: 1px; height: 1px; pointer-events: none; }

/* ── The unified instrument: frosted glass + milled metallic bezel ── */
.code-terminal {
  position: relative;
  display: flex; flex-direction: column; gap: clamp(12px, 1.9vh, 18px);
  border-radius: 26px;
  padding: clamp(15px, 2.3vh, 22px) clamp(13px, 2.1vw, 19px);
  background:
    linear-gradient(180deg, rgba(255,255,255,0.07) 0%, rgba(255,255,255,0.022) 38%, rgba(20,22,27,0.10) 100%),
    rgba(35,38,49,0.42);
  -webkit-backdrop-filter: blur(18px) saturate(135%);
  backdrop-filter: blur(18px) saturate(135%);
  border: 1px solid rgba(242,244,238,0.10);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.16),
    inset 0 0 0 1px rgba(229,195,83,0.10),
    inset 0 -14px 28px rgba(0,0,0,0.30),
    0 1px 0 rgba(255,255,255,0.04),
    0 30px 60px rgba(0,0,0,0.46),
    0 8px 20px rgba(0,0,0,0.30);
  overflow: hidden;
}
.code-terminal::before {
  content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  background:
    linear-gradient(135deg, rgba(255,255,255,0.14) 0%, rgba(255,255,255,0) 32%),
    radial-gradient(120% 60% at 50% -10%, rgba(255,255,255,0.10) 0%, transparent 60%);
  mix-blend-mode: screen;
}
.terminal-edgelight {
  position: absolute; left: 16%; right: 16%; top: -1px; height: 2px; border-radius: 2px;
  background: linear-gradient(90deg, transparent, rgba(172,202,50,0.5) 30%, rgba(196,230,74,0.65) 50%, rgba(172,202,50,0.5) 70%, transparent);
  opacity: 0.65; pointer-events: none; z-index: 1;
}

/* ── Sapphire readout well ── */
.code-readout {
  position: relative;
  display: flex; flex-direction: column; align-items: center; gap: clamp(9px, 1.5vh, 15px);
  background:
    linear-gradient(180deg, rgba(36,42,58,0.55) 0%, rgba(10,12,18,0.55) 100%),
    rgba(8,10,15,0.45);
  border: 1px solid rgba(0,0,0,0.45); border-radius: 18px;
  padding: clamp(12px, 1.8vh, 18px) clamp(12px, 2vw, 18px) clamp(14px, 2vh, 20px);
  box-shadow:
    inset 0 3px 12px rgba(0,0,0,0.55),
    inset 0 -1px 0 rgba(255,255,255,0.04),
    inset 0 0 0 1px rgba(120,150,210,0.05);
}
.readout-head { display: flex; align-items: center; justify-content: center; gap: 0.8em; }
.readout-monogram {
  font-family: var(--font-display); font-size: clamp(0.78rem, 1.9vw, 0.94rem); letter-spacing: 0.04em; line-height: 1;
  padding: 2px 6px; border-radius: 5px; color: var(--cc-gold);
  border: 1px solid rgba(229,195,83,0.32); background: linear-gradient(180deg, rgba(229,195,83,0.10), rgba(229,195,83,0.02));
  text-shadow: 0 1px 0 rgba(0,0,0,0.5); box-shadow: inset 0 1px 0 rgba(255,255,255,0.08);
}
.readout-label { font-family: var(--font-mono); font-size: clamp(0.62rem, 1.5vw, 0.72rem); letter-spacing: 0.3em; text-transform: uppercase; color: var(--cc-cream-dim); }
.pairing-screen .code-boxes { display: flex; gap: clamp(8px, 1.7vw, 14px); justify-content: center; margin: 0; }
.pairing-screen .code-box {
  position: relative; flex: 0 0 auto;
  width: clamp(44px, 12vw, 66px); height: clamp(60px, 15.5vw, 86px); border-radius: 14px;
  background:
    linear-gradient(180deg, rgba(120,150,210,0.10) 0%, rgba(255,255,255,0.015) 22%, rgba(10,13,20,0.6) 100%),
    rgba(12,15,22,0.6);
  border: 1.5px solid rgba(160,180,220,0.12);
  box-shadow: inset 0 3px 8px rgba(0,0,0,0.55), inset 0 -1px 0 rgba(255,255,255,0.04), 0 1px 0 rgba(255,255,255,0.03);
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-display); font-size: clamp(2rem, 7.5vw, 3rem); color: var(--cc-cream); text-shadow: 0 1px 0 rgba(0,0,0,0.5);
  transition: border-color 0.18s ease, box-shadow 0.22s ease, background 0.18s ease, transform 0.14s cubic-bezier(.2,.8,.2,1);
}
.pairing-screen .code-box::before {
  content: ""; position: absolute; left: 14%; right: 14%; top: 6px; height: 30%; border-radius: 10px;
  background: linear-gradient(180deg, rgba(255,255,255,0.16), rgba(255,255,255,0)); pointer-events: none;
}
.pairing-screen .code-box.filled {
  border-color: rgba(172,202,50,0.42);
  background:
    linear-gradient(180deg, rgba(172,202,50,0.16) 0%, rgba(172,202,50,0.02) 45%, rgba(10,13,20,0.6) 100%),
    rgba(12,15,22,0.6);
  box-shadow: inset 0 3px 8px rgba(0,0,0,0.5), inset 0 0 14px rgba(172,202,50,0.06), 0 1px 0 rgba(255,255,255,0.05);
}
.pairing-screen .code-box.active {
  border-color: var(--cc-lime);
  box-shadow:
    inset 0 3px 8px rgba(0,0,0,0.45),
    0 0 0 3px rgba(172,202,50,0.20),
    0 0 0 4.5px rgba(229,195,83,0.12),
    0 0 26px rgba(172,202,50,0.24);
  transform: translateY(-3px);
}
.pairing-screen .code-box.active:empty::after {
  content: ""; width: 2px; height: 44%;
  background: linear-gradient(180deg, var(--cc-lime), var(--cc-gold)); border-radius: 2px;
  box-shadow: 0 0 8px rgba(172,202,50,0.6); animation: pairCaret 1.1s steps(1, end) infinite;
}
@keyframes pairCaret { 0%,100% { opacity: 1; } 50% { opacity: 0; } }

.terminal-divider { position: relative; height: 1px; margin: clamp(0px, 0.4vh, 4px) clamp(6px, 2vw, 14px); background: linear-gradient(90deg, transparent, rgba(229,195,83,0.38) 20%, rgba(229,195,83,0.38) 80%, transparent); }
.terminal-divider-mark { position: absolute; top: 50%; left: 50%; width: 6px; height: 6px; transform: translate(-50%, -50%) rotate(45deg); background: var(--cc-gold); box-shadow: 0 0 8px rgba(229,195,83,0.5); }

/* ── Keyboard — tactile keys with crisp specular top edge ── */
.code-terminal .kbd { position: relative; width: 100%; max-width: 100%; margin: 0; gap: clamp(7px, 1.2vh, 11px); }
.code-terminal .kbd-row { gap: clamp(6px, 1.4vw, 10px); justify-content: center; }
.code-terminal .kkey {
  flex: 1 1 0; min-width: 0; padding: clamp(13px, 1.9vh, 19px) 0;
  font-family: var(--font-display); font-size: clamp(1.2rem, 3.8vw, 1.6rem); line-height: 1; color: var(--cc-cream);
  background: linear-gradient(180deg, var(--cc-graphite-3), var(--cc-graphite-2));
  border: 1px solid rgba(242,244,238,0.10); border-radius: 13px;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.10), inset 0 -1px 0 rgba(0,0,0,0.35), 0 3px 0 rgba(0,0,0,0.48), 0 6px 12px rgba(0,0,0,0.34);
  transition: transform 0.05s ease, box-shadow 0.05s ease, background 0.12s ease, color 0.12s ease, border-color 0.12s ease;
}
.code-terminal .kkey:hover { background: linear-gradient(180deg, rgba(172,202,50,0.16), rgba(172,202,50,0.05)); color: var(--cc-lime-hot); border-color: rgba(172,202,50,0.4); }
.code-terminal .kkey:active,
.code-terminal .kkey.on {
  transform: translateY(3px);
  background: linear-gradient(180deg, rgba(172,202,50,0.28), rgba(172,202,50,0.10)); color: var(--cc-lime-hot); border-color: rgba(172,202,50,0.5);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.04), inset 0 1px 5px rgba(0,0,0,0.4), 0 0 14px rgba(172,202,50,0.18);
}
.code-terminal .kkey.fn { font-family: var(--font-body); font-weight: 800; font-size: clamp(0.74rem, 1.9vw, 0.92rem); letter-spacing: 0.08em; text-transform: uppercase; color: var(--cc-cream-mid); flex: 1.5 1 0; }
.code-terminal .kkey.back { color: var(--cc-cream-mid); border-color: rgba(242,244,238,0.10); font-size: clamp(1.05rem, 2.6vw, 1.35rem); }
.code-terminal .kkey.back:active,
.code-terminal .kkey.back.on { background: linear-gradient(180deg, rgba(199,62,62,0.24), rgba(199,62,62,0.08)); color: var(--cc-cream); border-color: rgba(199,62,62,0.45); }

/* ── Action footer ── */
.pair-foot { display: flex; flex-direction: column; align-items: stretch; gap: clamp(8px, 1.4vh, 14px); }
.pair-foot .error-block { min-height: 0; }
.pairing-screen .pair-go {
  position: relative; overflow: hidden; width: 100%;
  padding: clamp(18px, 2.6vh, 24px); font-size: clamp(1.15rem, 3vw, 1.42rem); letter-spacing: 0.1em; border-radius: 16px; margin: 0; min-height: 60px;
  background: linear-gradient(180deg, var(--cc-lime-hot) 0%, var(--cc-lime) 100%);
  transition: background 0.16s ease, box-shadow 0.16s ease, transform 0.1s ease, opacity 0.16s ease;
}
.pair-go-label { position: relative; z-index: 2; }
.pair-go-sweep { position: absolute; inset: 0; z-index: 1; pointer-events: none; background: linear-gradient(110deg, transparent 30%, rgba(255,255,255,0.45) 50%, transparent 70%); transform: translateX(-120%); opacity: 0; }
.pairing-screen .pair-go:disabled { opacity: 0.4; cursor: not-allowed; background: linear-gradient(180deg, rgba(172,202,50,0.55), rgba(172,202,50,0.4)); box-shadow: none; }
.pairing-screen .pair-go:not(:disabled) {
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.35),
    inset 0 -2px 6px rgba(0,0,0,0.12),
    inset 0 0 0 1px rgba(229,195,83,0.18),
    0 16px 40px rgba(172,202,50,0.36);
  animation: pairCtaWake 0.42s cubic-bezier(.2,.8,.2,1);
}
.pairing-screen .pair-go:not(:disabled) .pair-go-sweep { animation: pairCtaSweep 0.9s cubic-bezier(0.3,0.7,0.3,1) 0.12s 1; }
.pairing-screen .pair-go:not(:disabled):hover { box-shadow: inset 0 1px 0 rgba(255,255,255,0.4), inset 0 0 0 1px rgba(229,195,83,0.22), 0 18px 46px rgba(172,202,50,0.44); }
.pairing-screen .pair-go:not(:disabled):active { transform: translateY(1px) scale(0.995); box-shadow: inset 0 2px 6px rgba(0,0,0,0.18), 0 8px 22px rgba(172,202,50,0.3); }
@keyframes pairCtaWake { 0% { transform: scale(0.985); } 60% { transform: scale(1.012); } 100% { transform: scale(1); } }
@keyframes pairCtaSweep { 0% { transform: translateX(-120%); opacity: 0; } 12% { opacity: 1; } 100% { transform: translateX(120%); opacity: 0; } }

.pairing-screen .pair-setup { width: 100%; padding: 13px 20px; font-size: 0.95rem; letter-spacing: 0.05em; border: none; background: transparent; color: var(--cc-cream-dim); border-radius: 12px; min-height: 48px; }
.pairing-screen .pair-setup:hover { color: var(--cc-cream-mid); }

/* ── Entrance: calm top→bottom cascade; the instrument settles with a subtle scale ── */
.pairing-screen.active .pair-head,
.pairing-screen.active .code-terminal,
.pairing-screen.active .pair-foot { animation: pairRise 0.6s cubic-bezier(0.16, 0.84, 0.34, 1) both; }
.pairing-screen.active .code-terminal { animation: pairInstrumentSettle 0.7s cubic-bezier(0.16, 0.84, 0.34, 1) both; animation-delay: 0.08s; }
.pairing-screen.active .pair-foot { animation-delay: 0.16s; }
@keyframes pairRise { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: translateY(0); } }
@keyframes pairInstrumentSettle { from { opacity: 0; transform: translateY(18px) scale(0.985); } to { opacity: 1; transform: translateY(0) scale(1); } }

/* Shorter portrait panels (~800x1280): tighten so nothing scrolls. */
@media (max-height: 1300px) {
  .pairing-screen .pair-sub  { display: none; }
  .pair-rule { margin-top: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .pairing-screen.active .pair-head,
  .pairing-screen.active .code-terminal,
  .pairing-screen.active .pair-foot { animation: none; }
  .pairing-screen .code-box.active:empty::after { animation: none; }
  .pairing-screen .pair-go:not(:disabled) { animation: none; }
  .pairing-screen .pair-go:not(:disabled) .pair-go-sweep { animation: none; }
  .pairing-screen .code-box,
  .code-terminal .kkey { transition: none; }
  .aurora-a, .aurora-b { animation: none; }
}

/* Printer-connect screen — IP display + advanced fields */
.ip-display { width: 100%; max-width: 460px; text-align: center; font-family: var(--font-mono); font-size: clamp(1.5rem, 5vw, 2.1rem); letter-spacing: 0.06em; padding: clamp(14px,2vh,20px); background: rgba(255,255,255,0.06); border: 2px solid rgba(242,244,238,0.16); border-radius: 14px; color: var(--cc-cream); }
.ip-display:focus { outline: none; border-color: var(--cc-lime); box-shadow: 0 0 0 4px rgba(172,202,50,0.16); }
.pair-card .seg-label { align-self: flex-start; font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.16em; text-transform: uppercase; color: var(--cc-cream-dim); margin-top: 2px; }
.pair-card .adv-input { width: 100%; text-align: center; font-size: 1.05rem; padding: 14px 18px; }
.pair-card .setup-panel { gap: 10px; }

/* Booth setup — fullscreen modal */
.setup-modal { position: fixed; inset: 0; z-index: 300; display: none; align-items: center; justify-content: center; padding: 20px; background: rgba(10,11,14,0.86); backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px); }
.setup-modal.show { display: flex; }
.setup-modal-card { width: min(560px, 96vw); max-height: 90vh; overflow-y: auto; background: #1b1d22; border: 1px solid rgba(242,244,238,0.12); border-radius: 22px; padding: 24px; box-shadow: 0 30px 90px rgba(0,0,0,0.5); }
.setup-modal-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 18px; }
.setup-modal-head h2 { margin: 0; font-family: var(--font-display); font-size: 1.6rem; color: var(--cc-cream); }
.setup-modal-x { width: 44px; height: 44px; border-radius: 50%; border: 1px solid rgba(242,244,238,0.2); background: rgba(255,255,255,0.06); color: var(--cc-cream); font-size: 1.1rem; cursor: pointer; display: grid; place-items: center; }
.setup-modal-x:hover { background: rgba(255,255,255,0.14); }
.setup-modal-body { display: flex; flex-direction: column; gap: 12px; }
.setup-modal-body .big-btn, .setup-modal-body .big-btn-sm { width: 100%; }

/* ═══════════════════════════════════════════════
   Printer setup — hub-and-spoke modals
   ═══════════════════════════════════════════════ */
/* The #wcmTestBtn handler sets color to var(--cc-danger), which was never
   defined (only --danger exists) — alias it so failures actually turn red. */
:root { --cc-danger: var(--danger); }

/* Back button in a modal head — mirrors .setup-modal-x */
.setup-modal-back {
  width: 44px; height: 44px; border-radius: 50%;
  border: 1px solid rgba(242,244,238,0.2);
  background: rgba(255,255,255,0.06); color: var(--cc-cream);
  font-size: 1.6rem; line-height: 1; cursor: pointer;
  display: grid; place-items: center; flex: 0 0 auto;
}
.setup-modal-back:hover { background: rgba(255,255,255,0.14); }
.setup-modal-head:has(.setup-modal-back) { gap: 12px; }
.setup-modal-head:has(.setup-modal-back) h2 { flex: 1 1 auto; text-align: center; }

/* HUB — large captioned nav rows */
.wcm-nav-row {
  display: flex; align-items: center; gap: 16px;
  width: 100%; min-height: 76px; padding: 16px 20px;
  text-align: left; cursor: pointer;
  background: var(--cc-graphite-3);
  border: 1px solid rgba(242,244,238,0.12); border-radius: 16px;
  color: var(--cc-cream);
  transition: background 0.12s, border-color 0.12s, transform 0.06s;
}
.wcm-nav-row:hover  { background: rgba(172,202,50,0.12); border-color: rgba(172,202,50,0.45); }
.wcm-nav-row:active { transform: scale(0.985); }
.wcm-nav-txt   { display: flex; flex-direction: column; gap: 5px; flex: 1 1 auto; min-width: 0; }
.wcm-nav-title { font-family: var(--font-display); font-size: 1.5rem; letter-spacing: 0.01em; line-height: 1; }
.wcm-nav-cap   { font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.04em; color: var(--cc-cream-dim); }
.wcm-nav-chev  { font-family: var(--font-display); font-size: 2.1rem; line-height: 1; color: var(--cc-lime); flex: 0 0 auto; }

/* LOGIN modal — transport toggle row */
.wcm-xport-row { display: flex; gap: 10px; width: 100%; }
.wcm-xport-row .wcm-xport-btn { flex: 1 1 0; min-width: 0; min-height: 52px; }

/* seg-labels + fields inside any modal body */
.setup-modal-body .seg-label {
  align-self: flex-start; font-family: var(--font-mono);
  font-size: 0.72rem; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--cc-cream-dim); margin-top: 4px;
}
.setup-modal-body .adv-input { width: 100%; text-align: center; font-size: 1.1rem; padding: 16px 18px; }

/* Login keyboard: full width inside the modal */
.wcm-login-kbd { margin: 6px auto 2px; max-width: 100%; }

/* TEST modal */
.wcm-test-help {
  font-family: var(--font-body); font-size: 0.9rem; line-height: 1.5;
  color: var(--cc-cream-mid); margin: 0 0 2px;
}
.wcm-test-status {
  width: 100%;
  min-height: 150px; max-height: 42vh;
  overflow-y: auto; -webkit-overflow-scrolling: touch;
  margin: 0; padding: 14px 16px;
  font-family: var(--font-mono); font-size: 0.82rem; line-height: 1.5;
  color: var(--cc-cream-mid);
  white-space: pre-wrap; word-break: break-word;
  background: rgba(0,0,0,0.32);
  border: 1px solid rgba(242,244,238,0.12); border-radius: 14px;
}
.wcm-test-status:focus { outline: none; border-color: rgba(172,202,50,0.45); }
.wcm-test-divider { width: 100%; height: 1px; background: rgba(242,244,238,0.1); margin: 4px 0; }
@media (max-height: 860px) {
  .wcm-test-status { min-height: 120px; max-height: 32vh; }
}

.send-actions {
  display: flex; flex-direction: column;
  gap: 14px;
  width: 100%;
  max-width: 560px;
  margin-top: 14px;
}
.send-actions-row {
  display: flex; gap: 14px;
  width: 100%;
}
/* Secondary buttons (Cancel / + Add another) get proper height + padding
   so they're not cramped against each other. Previously they fell back
   to the tiny .btn defaults. */
.send-actions-row .btn {
  flex: 1;
  padding: 18px 20px;
  font-size: clamp(1rem, 2.2vw, 1.2rem);
  font-weight: 700;
  letter-spacing: 0.06em;
  white-space: nowrap;
  min-height: 64px;
}
/* Primary "Send" button — full width, larger, sits BELOW the secondary
   actions so the eye lands on it. */
.send-go-btn {
  width: 100%;
  padding: 24px 32px;
  font-size: clamp(1.25rem, 3vw, 1.6rem);
  font-weight: 800;
  letter-spacing: 0.1em;
  min-height: 78px;
}

/* ════════════════════════════════════════════════
   A2P 10DLC OPT-IN DISCLOSURE
   Required for Twilio SMS campaign approval. Must be visible at the
   point where the phone number is collected. Kept small enough to
   not dominate the keypad UI but large enough to satisfy carrier
   readability requirements (guests can visibly read it before
   tapping Send). Links to Privacy + Terms open in the system
   browser (target=_blank) so guests can review before consenting.
   ════════════════════════════════════════════════ */
.sms-consent {
  width: 100%;
  max-width: 640px;
  margin: 14px auto 4px;
  padding: 14px 18px;
  border-radius: 12px;
  background: rgba(0,0,0,0.32);
  border: 1px solid rgba(229,195,83,0.22);
  text-align: left;
  color: rgba(242,244,238,0.85);
}
.sms-consent-lead {
  margin: 0 0 8px;
  font-family: var(--font-body, 'Inter'), sans-serif;
  font-size: clamp(0.82rem, 1.6vw, 0.95rem);
  line-height: 1.4;
  color: rgba(242,244,238,0.9);
}
.sms-consent-fine {
  margin: 0;
  font-family: var(--font-body, 'Inter'), sans-serif;
  font-size: clamp(0.72rem, 1.4vw, 0.82rem);
  line-height: 1.45;
  color: rgba(242,244,238,0.68);
  letter-spacing: 0.01em;
}
.sms-consent-lead strong { color: var(--cc-cream, #F2F4EE); font-weight: 700; }
.sms-consent-fine strong { color: rgba(242,244,238,0.85); font-weight: 700; }
/* Kiosk mode — the "cybercoltphotobooth.com/privacy" URL text is NOT a
   link. Guests can read it and type it into their own phone later; the
   booth WebView never navigates away. Styled to visually stand out
   without inviting a tap. */
.sms-consent strong { color: var(--cc-cream, #F2F4EE); }

/* ═══════════════════════════════════════════════════════════════════
   STICKER PICKER (fun props)
   ═══════════════════════════════════════════════════════════════════ */
.sticker-selected-row {
  display: flex; align-items: center; justify-content: center;
  gap: 16px; margin: 4px 0 8px;
}
.sticker-selected-label {
  font-family: var(--font-mono, monospace);
  font-size: 0.72rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: rgba(242,244,238,0.55);
}
.sticker-selected-slots { display: flex; gap: 10px; }
.sticker-selected-slot {
  width: 56px; height: 56px;
  border-radius: 12px;
  background: rgba(255,255,255,0.06);
  border: 2px dashed rgba(229,195,83,0.35);
  display: flex; align-items: center; justify-content: center;
  font-size: 2.2rem;
  transition: transform 200ms, border-color 200ms, background 200ms;
}
.sticker-selected-slot.filled {
  border-style: solid;
  border-color: rgba(229,195,83,0.85);
  background: rgba(229,195,83,0.12);
  animation: stickerPop 0.32s cubic-bezier(0.16,1,0.3,1);
}
@keyframes stickerPop {
  0%   { transform: scale(0.4); opacity: 0; }
  70%  { transform: scale(1.15); opacity: 1; }
  100% { transform: scale(1);    opacity: 1; }
}
.sticker-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(90px, 1fr));
  gap: 14px;
  width: 100%;
  max-width: 720px;
  margin: 6px 0;
}
.sticker-tile {
  aspect-ratio: 1;
  background: rgba(255,255,255,0.04);
  border: 2px solid rgba(255,255,255,0.10);
  border-radius: 18px;
  font-size: clamp(2.6rem, 6vw, 3.6rem);
  line-height: 1;
  cursor: pointer;
  transition: transform 140ms, border-color 140ms, background 140ms;
  display: flex; align-items: center; justify-content: center;
  padding: 0;
}
.sticker-tile:active { transform: scale(0.95); }
.sticker-tile.picked {
  border-color: var(--cc-gold, #E5C353);
  background: rgba(229,195,83,0.15);
  box-shadow: 0 0 0 2px rgba(229,195,83,0.35), 0 10px 24px rgba(229,195,83,0.2);
}
.sticker-actions {
  display: flex; gap: 14px; margin-top: 6px;
}

/* ═══════════════════════════════════════════════════════════════════
   DRAWING OVERLAY — finger-paint canvas over the composite preview
   ═══════════════════════════════════════════════════════════════════ */
.draw-overlay {
  position: fixed; inset: 0;
  background: rgba(13,15,20,0.94);
  z-index: 10600;
  display: none !important;
  flex-direction: column;
  align-items: center; justify-content: center;
  padding: 20px;
  gap: 16px;
}
.draw-overlay.show { display: flex !important; }
.draw-header {
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  text-align: center;
}
.draw-header-title {
  font-family: var(--font-display, 'Bebas Neue'), sans-serif;
  font-size: clamp(1.6rem, 4.5vw, 2.4rem);
  letter-spacing: 0.06em;
  color: var(--cc-cream);
}
.draw-header-sub {
  font-family: var(--font-body, 'Inter'), sans-serif;
  font-size: clamp(0.85rem, 1.6vw, 1rem);
  color: rgba(242,244,238,0.65);
  font-style: italic;
}
.draw-stage {
  position: relative;
  flex: 1;
  max-width: 100%;
  min-height: 0;
  display: flex; align-items: center; justify-content: center;
}
.draw-stage img,
.draw-stage canvas {
  position: relative;
  max-width: 100%;
  max-height: 100%;
  border-radius: 8px;
  box-shadow: 0 20px 60px rgba(0,0,0,0.55);
}
.draw-stage canvas {
  position: absolute; inset: 0;
  margin: auto;
  touch-action: none;
  cursor: crosshair;
}
.draw-toolbar {
  display: flex; flex-direction: column;
  gap: 12px; align-items: center;
  padding: 12px 20px;
  background: rgba(27,29,34,0.85);
  border: 1px solid rgba(229,195,83,0.28);
  border-radius: 18px;
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}
/* Controls row groups colors + thickness so they live on the same tier
   of the toolbar and stack cleanly on narrow screens. */
.draw-controls-row {
  display: flex;
  gap: 18px;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  padding: 4px 6px;
  border-bottom: 1px solid rgba(255,255,255,0.06);
}
.draw-colors { display: flex; gap: 10px; flex-wrap: wrap; justify-content: center; }
.draw-color {
  width: 44px; height: 44px;
  border-radius: 50%;
  border: 3px solid rgba(255,255,255,0.35);
  cursor: pointer;
  padding: 0;
  transition: transform 140ms, border-color 140ms;
}
.draw-color:active { transform: scale(0.94); }
.draw-color.selected {
  border-color: var(--cc-gold, #E5C353);
  box-shadow: 0 0 0 3px rgba(229,195,83,0.4);
  transform: scale(1.1);
}
/* Line thickness picker — three buttons showing filled dots at Fine /
   Medium / Thick scales. Selected state matches the color-swatch look
   so the toolbar reads as a single family. */
.draw-thickness {
  display: flex;
  gap: 6px;
  align-items: center;
  padding: 4px 8px;
  background: rgba(0,0,0,0.35);
  border-radius: 999px;
  border: 1px solid rgba(255,255,255,0.08);
}
.draw-thick-btn {
  width: 42px; height: 42px;
  border-radius: 50%;
  border: 2px solid rgba(255,255,255,0.15);
  background: rgba(255,255,255,0.04);
  cursor: pointer;
  padding: 0;
  display: flex; align-items: center; justify-content: center;
  transition: transform 140ms, border-color 140ms, background 140ms;
}
.draw-thick-btn:active { transform: scale(0.92); }
.draw-thick-btn.selected {
  border-color: var(--cc-gold, #E5C353);
  background: rgba(229,195,83,0.15);
  box-shadow: 0 0 0 2px rgba(229,195,83,0.35);
  transform: scale(1.06);
}
.draw-thick-dot {
  display: block;
  border-radius: 50%;
  background: var(--cc-cream, #F2F4EE);
}
.draw-tools { display: flex; gap: 10px; flex-wrap: wrap; justify-content: center; }
.draw-tool-btn { padding: 12px 20px; font-size: 0.95rem; min-width: 96px; }

/* ═══════════════════════════════════════════════════════════════════
   PRINTER SUPPLIES BANNER — fixed top header
   ═══════════════════════════════════════════════════════════════════ */
.paper-banner {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 11000;
  padding: 10px 20px;
  display: flex; align-items: center; justify-content: center; gap: 14px;
  font-family: var(--font-body, 'Inter'), sans-serif;
  font-size: clamp(0.9rem, 1.8vw, 1.05rem);
  font-weight: 700;
  color: #1B1D22;
  background: linear-gradient(90deg, #F5D453, #E5C353);
  box-shadow: 0 4px 18px rgba(229,195,83,0.4);
  cursor: pointer;
  border-bottom: 2px solid rgba(0,0,0,0.15);
  animation: paperBannerSlideDown 380ms cubic-bezier(0.16,1,0.3,1);
}
@keyframes paperBannerSlideDown {
  from { transform: translateY(-100%); }
  to   { transform: translateY(0);     }
}
.paper-banner.warn {
  background: linear-gradient(90deg, #F5D453, #E5C353);
  color: #1B1D22;
}
.paper-banner.critical {
  background: linear-gradient(90deg, #FF7D6E, #FF5A45);
  color: #FFFFFF;
  animation: paperBannerSlideDown 380ms cubic-bezier(0.16,1,0.3,1),
             paperCriticalPulse 1.8s ease-in-out 380ms infinite;
}
@keyframes paperCriticalPulse {
  0%,100% { box-shadow: 0 4px 18px rgba(255,90,69,0.5); }
  50%     { box-shadow: 0 4px 32px rgba(255,90,69,0.85); }
}
.paper-banner-icon { font-size: 1.3em; }
.paper-banner-text { flex: 0 1 auto; }
.paper-banner-action {
  font-family: var(--font-mono, monospace);
  font-size: 0.78em;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  opacity: 0.8;
}
/* Armed state — first tap primes a reset. Blue accent so it's obvious
   the state changed; second tap within 3s confirms and resets. */
.paper-banner.armed {
  background: linear-gradient(90deg, #4ac0ff, #2eb8ff) !important;
  color: #0A2440 !important;
  animation: paperArmedPulse 0.9s ease-in-out infinite !important;
}
@keyframes paperArmedPulse {
  0%,100% { box-shadow: 0 4px 18px rgba(46,184,255,0.4); }
  50%     { box-shadow: 0 4px 30px rgba(46,184,255,0.8); }
}

/* ════════════════════════════════════════════════
   TOAST — bottom-popup banner for transient status (print success /
   failure / errors). Lives outside the .screen routing so it can overlay
   any screen without forcing a route change.
   ════════════════════════════════════════════════ */
.toast {
  position: fixed;
  left: 50%;
  bottom: 32px;
  transform: translate(-50%, calc(100% + 80px));
  min-width: 280px;
  max-width: 88vw;
  padding: 16px 28px;
  background: rgba(27,29,34,0.96);
  border: 2px solid rgba(172,202,50,0.5);
  border-radius: 18px;
  color: var(--cc-cream);
  font-family: var(--font-body);
  font-size: clamp(0.95rem, 2vw, 1.15rem);
  font-weight: 600;
  text-align: center;
  box-shadow: 0 20px 60px rgba(0,0,0,0.6), 0 0 40px rgba(172,202,50,0.18);
  z-index: 10000;
  opacity: 0;
  transition: transform 0.32s cubic-bezier(0.16,1,0.3,1), opacity 0.32s ease;
  pointer-events: none;
  max-height: 35vh;
  overflow-y: auto;
}
.toast.show {
  transform: translate(-50%, 0);
  opacity: 1;
  pointer-events: auto;
}
.toast.ok    { border-color: var(--cc-lime);  box-shadow: 0 20px 60px rgba(0,0,0,0.6), 0 0 40px rgba(172,202,50,0.35); }
.toast.err   { border-color: var(--cc-danger); box-shadow: 0 20px 60px rgba(0,0,0,0.6), 0 0 40px rgba(199,62,62,0.4); color: #ffe6e6; }
.toast.warn  { border-color: var(--cc-gold);   box-shadow: 0 20px 60px rgba(0,0,0,0.6), 0 0 40px rgba(229,195,83,0.35); }
.toast .toast-icon {
  display: inline-block;
  margin-right: 8px;
  font-size: 1.25em;
  vertical-align: middle;
}
.toast .toast-title {
  display: block;
  font-weight: 800;
  letter-spacing: 0.04em;
  margin-bottom: 4px;
}

/* ── Test camera modal ────────────────────────────────────────────── */
.test-cam-modal {
  position: fixed; inset: 0;
  background: rgba(13, 15, 20, 0.96);
  z-index: 10000;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  gap: 18px;
  padding: 32px;
  cursor: pointer;
}
.test-cam-modal img,
.test-cam-modal video {
  max-width: 90vw;
  max-height: 78vh;
  width: auto; height: auto;
  border-radius: 18px;
  border: 2px solid rgba(172, 202, 50, 0.55);
  box-shadow: 0 30px 80px rgba(0,0,0,0.7), 0 0 60px rgba(172,202,50,0.25);
  background: #000;
  object-fit: contain;
}
/* Live web-camera preview — mirror it so the operator sees themselves the
   way they would in a mirror (matches the capture-screen selfie preview). */
#testCamVideo { transform: scaleX(-1); }
.test-cam-status {
  font-family: var(--font-mono, monospace);
  font-size: 0.95rem;
  color: var(--cc-cream, #F2F4EE);
  letter-spacing: 0.04em;
  text-align: center;
  min-height: 1.2em;
}
.test-cam-footer {
  font-family: var(--font-body, sans-serif);
  font-size: 0.8rem;
  color: rgba(242,244,238,0.55);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* ── Hardware test chooser ────────────────────────────────────────── */
.hw-test-modal {
  position: fixed; inset: 0;
  background: rgba(13, 15, 20, 0.78);
  z-index: 10000;
  display: flex; align-items: center; justify-content: center;
  padding: 24px;
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}
.hw-test-card {
  width: min(520px, 92vw);
  padding: clamp(28px, 4vh, 44px);
  background: linear-gradient(180deg, rgba(27,29,34,0.96), rgba(13,15,20,0.96));
  border: 1px solid rgba(172,202,50,0.28);
  border-radius: 22px;
  box-shadow:
    0 40px 100px rgba(0,0,0,0.6),
    0 0 80px rgba(172,202,50,0.18);
  display: flex; flex-direction: column;
  gap: 18px;
  text-align: center;
  animation: hwTestIn 0.32s cubic-bezier(0.16,1,0.3,1) both;
}
@keyframes hwTestIn {
  from { transform: scale(0.92) translateY(8px); opacity: 0; }
  to   { transform: scale(1) translateY(0);     opacity: 1; }
}
.hw-test-title {
  font-family: var(--font-display, 'Bebas Neue'), sans-serif;
  font-size: clamp(1.8rem, 4vw, 2.6rem);
  letter-spacing: 0.02em;
  color: var(--cc-cream);
  margin: 0;
}
.hw-test-sub {
  font-family: var(--font-body, 'Inter'), sans-serif;
  font-size: clamp(0.9rem, 1.5vw, 1rem);
  color: rgba(242,244,238,0.7);
  margin: 0;
}
.hw-test-actions {
  display: flex; flex-direction: column; gap: 12px;
  margin-top: 8px;
}
.hw-test-actions .btn { width: 100%; }
.hw-test-modal #hwTestCancelBtn { margin-top: 4px; }

/* Two equal-weight tiles, one big icon + label + sub-hint per tile.
   Hover/active states are crisp without being noisy. */
.hw-test-tiles {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
  margin-top: 10px;
}
.hw-test-tile {
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  gap: 8px;
  padding: 26px 18px;
  border-radius: 18px;
  background: linear-gradient(180deg, rgba(255,255,255,0.05), rgba(255,255,255,0.015));
  border: 1px solid rgba(172, 202, 50, 0.28);
  color: var(--cc-cream, #F2F4EE);
  font-family: var(--font-body, 'Inter'), sans-serif;
  cursor: pointer;
  transition: transform 0.18s ease, border-color 0.18s ease, box-shadow 0.18s ease, background 0.18s ease;
}
.hw-test-tile:hover {
  border-color: var(--cc-lime, #ACCA32);
  background: linear-gradient(180deg, rgba(172,202,50,0.10), rgba(172,202,50,0.03));
  transform: translateY(-2px);
  box-shadow: 0 16px 40px rgba(0,0,0,0.35), 0 0 60px rgba(172,202,50,0.18);
}
.hw-test-tile:active { transform: translateY(0); }
.hw-tile-icon {
  width: 36px;
  height: 36px;
  color: var(--cc-lime, #ACCA32);
  display: flex; align-items: center; justify-content: center;
}
.hw-tile-icon svg { width: 100%; height: 100%; stroke: currentColor; fill: none; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }

/* Inline SVG icon helper — sized to sit cleanly inside any button. */
.btn-icon {
  display: inline-flex;
  align-items: center; justify-content: center;
  width: 18px; height: 18px;
  margin-right: 8px;
  vertical-align: -3px;
  color: currentColor;
}
.btn-icon svg { width: 100%; height: 100%; stroke: currentColor; fill: none; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.toolbar-btn .btn-icon { width: 20px; height: 20px; margin-right: 10px; }
.hw-tile-label {
  font-weight: 700;
  font-size: 1.05rem;
  letter-spacing: 0.01em;
  color: var(--cc-cream, #F2F4EE);
}
.hw-tile-hint {
  font-family: var(--font-mono, monospace);
  font-size: 0.7rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(242,244,238,0.55);
  text-align: center;
}
.hw-test-cancel {
  margin-top: 14px;
  padding: 12px 18px;
  border-radius: 999px;
  background: transparent;
  border: 1px solid rgba(242,244,238,0.18);
  color: rgba(242,244,238,0.78);
  font-family: var(--font-body, 'Inter'), sans-serif;
  font-weight: 600;
  font-size: 0.88rem;
  letter-spacing: 0.06em;
  cursor: pointer;
  transition: all 0.15s ease;
}
.hw-test-cancel:hover {
  border-color: var(--cc-lime, #ACCA32);
  color: var(--cc-lime, #ACCA32);
}

/* ════════════════════════════════════════════════
   Camera source pills + advanced toggles (pairing screen)
   ════════════════════════════════════════════════ */
.cam-source-row {
  display: flex; gap: 6px;
  padding: 4px;
  background: rgba(0,0,0,0.3);
  border: 1px solid rgba(242,244,238,0.10);
  border-radius: 14px;
}
.cam-src-btn {
  flex: 1;
  padding: 12px 10px;
  border-radius: 10px;
  background: transparent;
  border: none;
  color: rgba(242,244,238,0.7);
  font-family: var(--font-mono);
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  cursor: pointer;
  transition: all 0.15s ease;
}
.cam-src-btn:hover { color: var(--cc-cream); }
.cam-src-btn.active {
  background: var(--cc-lime);
  color: var(--cc-graphite);
}

/* Advanced disclosure */
.cam-advanced {
  margin-top: 6px;
  border: 1px solid rgba(242,244,238,0.10);
  border-radius: 12px;
  background: rgba(0,0,0,0.2);
}
.cam-advanced summary {
  cursor: pointer;
  padding: 12px 16px;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(242,244,238,0.6);
  list-style: none;
  user-select: none;
}
.cam-advanced summary::-webkit-details-marker { display: none; }
.cam-advanced summary::after {
  content: '+';
  float: right;
  font-size: 1.2rem; line-height: 0.9;
  color: var(--cc-lime);
  transition: transform 0.2s ease;
}
.cam-advanced[open] summary::after { content: '−'; }
.cam-advanced summary:hover { color: var(--cc-cream); }
.cam-adv-body {
  padding: 4px 16px 16px;
  display: flex; flex-direction: column; gap: 14px;
  border-top: 1px solid rgba(242,244,238,0.06);
  margin-top: 4px;
  padding-top: 14px;
}
.cam-adv-row {
  display: flex; flex-direction: column; gap: 6px;
}
.cam-adv-label {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(242,244,238,0.55);
}
.cam-adv-pills {
  display: flex; gap: 4px; flex-wrap: wrap;
  padding: 3px;
  background: rgba(0,0,0,0.3);
  border: 1px solid rgba(242,244,238,0.08);
  border-radius: 10px;
}
.cam-adv-pills button {
  flex: 1; min-width: 56px;
  padding: 9px 12px;
  border: none;
  border-radius: 7px;
  background: transparent;
  color: rgba(242,244,238,0.7);
  font-family: var(--font-mono);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  cursor: pointer;
  transition: all 0.15s ease;
}
.cam-adv-pills button:hover { color: var(--cc-cream); }
.cam-adv-pills button.active {
  background: var(--cc-lime);
  color: var(--cc-graphite);
}
.cam-adv-check {
  display: flex; align-items: flex-start; gap: 10px;
  padding: 10px 12px;
  background: rgba(0,0,0,0.18);
  border: 1px solid rgba(242,244,238,0.06);
  border-radius: 10px;
  cursor: pointer;
  font-size: 0.84rem;
  color: rgba(242,244,238,0.75);
  line-height: 1.45;
}
.cam-adv-check input[type="checkbox"] {
  margin-top: 2px;
  flex-shrink: 0;
  width: 18px; height: 18px;
  accent-color: var(--cc-lime);
}
.cam-adv-check strong { color: var(--cc-cream); font-weight: 700; }

/* ════════════════════════════════════════════════
   Camera Settings sub-panel (Hardware Test modal)
   ════════════════════════════════════════════════ */
.cam-set {
  display: flex; flex-direction: column; gap: 6px;
  text-align: left;
}
.cam-set-label {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(242,244,238,0.55);
}
.cam-set-input {
  width: 100%;
  padding: 12px 14px;
  border-radius: 10px;
  background: rgba(0,0,0,0.3);
  border: 1px solid rgba(242,244,238,0.10);
  color: var(--cc-cream);
  font-family: var(--font-body), 'Inter', sans-serif;
  font-size: 0.92rem;
}
.cam-set-hint {
  font-size: 0.78rem;
  color: rgba(242,244,238,0.5);
  margin: 0;
  line-height: 1.5;
}
.cam-set-row {
  display: flex; align-items: flex-start; gap: 10px;
  cursor: pointer;
  font-size: 0.88rem;
  color: var(--cc-cream);
  line-height: 1.4;
}
.cam-set-row input[type="checkbox"] {
  margin-top: 3px;
  width: 18px; height: 18px;
  accent-color: var(--cc-lime);
}
.toast .toast-sub {
  display: block;
  font-size: 0.85em;
  opacity: 0.85;
  font-weight: 500;
}

/* ════════════════════════════════════════════════
   CONFIRMATION
   ════════════════════════════════════════════════ */
.confirm-body { display: flex; flex-direction: column; align-items: center; gap: 18px; }
.confirm-mark {
  width: clamp(120px, 24vw, 160px);
  aspect-ratio: 1;
  border-radius: 50%;
  background: var(--cc-lime);
  color: var(--cc-graphite);
  font-size: clamp(5rem, 14vw, 8rem);
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 0 0 0 rgba(172,202,50,0.5);
  animation: pulseRing 1.2s ease-out infinite;
}
@keyframes pulseRing {
  0%   { box-shadow: 0 0 0 0 rgba(172,202,50,0.5); }
  100% { box-shadow: 0 0 0 32px rgba(172,202,50,0); }
}

/* ════════════════════════════════════════════════
   Watermark
   ════════════════════════════════════════════════ */
.cc-watermark {
  position: fixed; bottom: 14px; left: 14px;
  width: clamp(40px, 7vw, 60px);
  opacity: 0.1;
  filter: invert(1) brightness(1.1) drop-shadow(0 0 6px rgba(172,202,50,0.35));
  pointer-events: none;
  z-index: 1;
}
/* Hide watermark on capture + preview where the strip dominates */
.capture-screen ~ .cc-watermark,
.preview-screen ~ .cc-watermark { display: none; }

/* ════════════════════════════════════════════════
   LANDSCAPE adjustments
   ════════════════════════════════════════════════ */
@media (orientation: landscape) {
  .preview-screen {
    flex-direction: row;
    align-items: stretch;
    justify-content: center;
    gap: 24px;
  }
  .preview-head {
    align-self: center;
    text-align: left;
    align-items: flex-start;
  }
  .preview-stage {
    flex: 1;
    max-width: 60%;
  }
  .preview-actions {
    flex-direction: column;
    flex-wrap: nowrap;
    align-self: center;
    max-width: 200px;
    height: 100%;
    max-height: 460px;
  }

  .send-screen { padding-top: 24px; }
  .keypad { max-width: 380px; }

  .cap-stage { /* still fills width — fine in landscape */ }

  .brand-row { top: 14px; }
}

/* ════════════════════════════════════════════════
   GET YOUR DIGITAL COPY — clean, elegant, no-scroll
   White QR card(s) on graphite, refined type, lime accent.
   QR sized by viewport height so it always fits without scrolling.
   ════════════════════════════════════════════════ */
.send-share-screen {
  justify-content: center; align-items: center;
  padding: clamp(14px, 3vh, 32px) clamp(16px, 4vw, 40px);
  overflow: hidden;
  background:
    radial-gradient(ellipse 70% 44% at 50% 4%, rgba(172,202,50,0.16) 0%, transparent 60%),
    var(--cc-graphite);
}
.share-wrap {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: clamp(14px, 2.8vh, 30px);
  width: 100%; max-width: min(520px, 94vw); height: 100%;
}
.share-head { display: flex; flex-direction: column; align-items: center; gap: clamp(5px, 1vh, 10px); text-align: center; }
.share-eyebrow {
  display: inline-flex; align-items: center; gap: 0.6em;
  font-family: var(--font-mono); font-size: clamp(0.66rem, 1.5vw, 0.8rem);
  letter-spacing: 0.26em; text-transform: uppercase; color: var(--cc-lime);
}
.share-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--cc-lime-hot); box-shadow: 0 0 0 0 rgba(196,230,74,0.6); animation: shareDot 2.2s ease-out infinite; }
@keyframes shareDot { 0% { box-shadow: 0 0 0 0 rgba(196,230,74,0.5); } 70% { box-shadow: 0 0 0 9px rgba(196,230,74,0); } 100% { box-shadow: 0 0 0 0 rgba(196,230,74,0); } }
.share-title { font-family: var(--font-display); font-size: clamp(2.2rem, 7vw, 3.4rem); letter-spacing: 0.03em; line-height: 1; margin: 0; color: var(--cc-cream); }
.share-sub { font-family: var(--font-body); font-size: clamp(0.88rem, 2vw, 1.05rem); color: var(--cc-cream-mid); margin: 0; }

.share-cards { display: flex; flex-direction: column; align-items: center; gap: clamp(10px, 1.8vh, 16px); width: 100%; }
.share-card {
  display: flex; flex-direction: column; align-items: center; gap: clamp(8px, 1.4vh, 14px);
  width: auto; flex: none;
  background: rgba(255,255,255,0.04); border: 1px solid rgba(242,244,238,0.1);
  border-radius: 22px; padding: clamp(12px, 2vh, 20px);
  box-shadow: 0 20px 50px rgba(0,0,0,0.4);
}
.qr-frame { background: #fff; border-radius: 16px; padding: clamp(10px, 1.6vh, 16px); line-height: 0; box-shadow: 0 6px 18px rgba(0,0,0,0.25); }
.share-card #qrCanvas { display: block; width: min(40vmin, 34vh, 320px); height: min(40vmin, 34vh, 320px); min-width: 200px; min-height: 200px; image-rendering: pixelated; }
.qr-frame-sm { padding: clamp(8px, 1.2vh, 12px); }
.share-card-gallery #qrEventCanvas { display: block; width: min(22vmin, 16vh, 170px); height: min(22vmin, 16vh, 170px); min-width: 120px; min-height: 120px; image-rendering: pixelated; }
.share-card-tag { font-family: var(--font-mono); font-size: clamp(0.6rem, 1.2vw, 0.7rem); letter-spacing: 0.18em; text-transform: uppercase; color: var(--cc-gold); }

.share-url { display: inline-flex; align-items: center; gap: 8px; max-width: 100%; }
.share-url-label { font-family: var(--font-mono); font-size: 0.58rem; letter-spacing: 0.16em; text-transform: uppercase; color: var(--cc-cream-dim); flex: none; }
.share-url-val { font-family: var(--font-mono); font-size: clamp(0.72rem, 1.4vw, 0.88rem); font-weight: 700; color: var(--cc-lime); letter-spacing: 0.01em; word-break: break-all; }

.share-actions { display: flex; gap: clamp(10px, 2vw, 14px); width: 100%; max-width: 440px; }
.share-actions .share-btn { flex: 1; min-height: 56px; font-size: clamp(0.95rem, 2.2vw, 1.12rem); }
.share-actions #qrTextItBtn[style*="none"] + #qrDoneBtn { flex: 0 1 320px; margin: 0 auto; }

@media (prefers-reduced-motion: reduce) { .share-dot { animation: none; } }

/* ═══════════════════════════════════════════════════════════════════
   Security-code modal (corporate close-booth / end-event gating)
   Same visual language as the pairing screen keypad so it feels
   consistent when it appears — not like a bolt-on.
   ═══════════════════════════════════════════════════════════════════ */
.sec-modal {
  position: fixed; inset: 0;
  background: rgba(13, 15, 20, 0.82);
  z-index: 10050;
  display: flex; align-items: center; justify-content: center;
  padding: 24px;
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}
.sec-modal-card {
  width: min(720px, 96vw);
  max-height: 96vh;
  overflow: hidden;
  padding: clamp(24px, 3.5vh, 36px) clamp(24px, 3vw, 40px);
  background: linear-gradient(180deg, rgba(27,29,34,0.98), rgba(13,15,20,0.98));
  border: 1px solid rgba(172,202,50,0.32);
  border-radius: 22px;
  box-shadow:
    0 40px 100px rgba(0,0,0,0.65),
    0 0 90px rgba(172,202,50,0.18);
  display: flex; flex-direction: column;
  gap: 14px;
  text-align: center;
  animation: hwTestIn 0.32s cubic-bezier(0.16,1,0.3,1) both;
}
.sec-modal-eyebrow {
  display: inline-flex; align-items: center; gap: 8px;
  align-self: center;
  font-family: var(--font-mono, monospace);
  font-size: 0.72rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: rgba(242,244,238,0.7);
}
.sec-modal-dot {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--cc-danger, #ff6f5e);
  box-shadow: 0 0 0 4px rgba(255,111,94,0.18);
  animation: secDotPulse 1.6s ease-in-out infinite;
}
@keyframes secDotPulse {
  0%,100% { box-shadow: 0 0 0 4px rgba(255,111,94,0.18); }
  50%     { box-shadow: 0 0 0 8px rgba(255,111,94,0.08); }
}
.sec-modal-title {
  font-family: var(--font-display, 'Bebas Neue'), sans-serif;
  font-size: clamp(1.7rem, 3.4vw, 2.4rem);
  letter-spacing: 0.02em;
  color: var(--cc-cream);
  margin: 0;
}
.sec-modal-sub {
  font-family: var(--font-body, 'Inter'), sans-serif;
  font-size: clamp(0.86rem, 1.4vw, 0.98rem);
  color: rgba(242,244,238,0.65);
  margin: 0 auto;
  max-width: 480px;
}
.sec-code-boxes {
  display: flex; gap: 10px; justify-content: center; margin: 6px 0 2px;
}
.sec-code-box {
  width: clamp(38px, 6.5vw, 54px);
  height: clamp(52px, 8.5vw, 68px);
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-mono, monospace);
  font-weight: 900;
  font-size: clamp(1.4rem, 3.2vw, 1.9rem);
  color: var(--cc-cream);
  background: rgba(255,255,255,0.03);
  border: 1.5px solid rgba(242,244,238,0.14);
  border-radius: 12px;
  transition: border-color 140ms, background 140ms, box-shadow 140ms;
}
.sec-code-box.filled {
  border-color: rgba(172,202,50,0.55);
  background: rgba(172,202,50,0.08);
  box-shadow: inset 0 0 0 1px rgba(172,202,50,0.16), 0 6px 18px rgba(172,202,50,0.14);
}
.sec-code-box.error { border-color: rgba(255,111,94,0.75); background: rgba(255,111,94,0.08); animation: secShake 0.36s cubic-bezier(.36,.07,.19,.97) both; }
@keyframes secShake {
  10%,90% { transform: translateX(-2px); }
  20%,80% { transform: translateX(3px);  }
  30%,50%,70% { transform: translateX(-5px); }
  40%,60%     { transform: translateX(5px);  }
}
.sec-err {
  min-height: 20px;
  font-family: var(--font-mono, monospace);
  font-size: 0.78rem;
  letter-spacing: 0.08em;
  color: var(--cc-danger, #ff6f5e);
}
.sec-kbd {
  display: flex; flex-direction: column; gap: 8px;
  padding: 12px 8px 6px;
}
.sec-kbd-row {
  display: flex; gap: 6px; justify-content: center;
}
.sec-kkey {
  flex: 1 1 0;
  min-height: clamp(44px, 6.5vh, 58px);
  min-width: 0;
  font-family: var(--font-mono, monospace);
  font-weight: 700;
  font-size: clamp(0.95rem, 2vw, 1.2rem);
  color: var(--cc-cream);
  background: linear-gradient(180deg, rgba(255,255,255,0.06), rgba(255,255,255,0.02));
  border: 1px solid rgba(242,244,238,0.12);
  border-radius: 10px;
  cursor: pointer;
  transition: transform 80ms, background 140ms, border-color 140ms;
}
.sec-kkey:active { transform: translateY(1px) scale(0.98); background: rgba(172,202,50,0.14); border-color: rgba(172,202,50,0.5); }
.sec-kkey.fn { flex: 1.4 1 0; font-size: 0.85rem; letter-spacing: 0.08em; text-transform: uppercase; color: rgba(242,244,238,0.75); }
.sec-actions {
  display: flex; gap: 12px; margin-top: 8px;
}
.sec-actions .sec-btn { flex: 1; min-height: 56px; font-size: 1rem; }

/* ═══════════════════════════════════════════════════════════════════
   Preview-screen idle-timer bar — a 3px gold hairline pinned to the
   very bottom edge that fills as the 60s idle window elapses. No
   label, no chrome — just a live cue that fades in only when a strip
   is on screen. Zero attention theft from the print/text/retake row.
   ═══════════════════════════════════════════════════════════════════ */
.preview-idle-bar {
  position: fixed; left: 0; right: 0; bottom: 0;
  height: 3px;
  display: none;
  pointer-events: none;
  z-index: 9000;
  background: rgba(242,244,238,0.10);
}
.preview-idle-bar.active { display: block; }
.preview-idle-bar-fill {
  width: 0%; height: 100%;
  background: linear-gradient(90deg, var(--cc-lime, #ACCA32) 0%, var(--cc-gold, #E5C353) 60%, var(--cc-cream, #F2F4EE) 100%);
  box-shadow: 0 0 12px rgba(229,195,83,0.55);
  transition: width 0.4s linear;
}

/* ═══════════════════════════════════════════════════════════════════
   Confetti overlay
   ═══════════════════════════════════════════════════════════════════ */
.confetti-canvas {
  position: fixed; inset: 0;
  width: 100%; height: 100%;
  pointer-events: none;
  z-index: 9500;
  display: none;
}
.confetti-canvas.firing { display: block; }

/* ═══════════════════════════════════════════════════════════════════
   Get Ready — more excited: pulse ring + shimmer sweep on the label
   ═══════════════════════════════════════════════════════════════════ */
.gr-ring {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  pointer-events: none;
}
.gr-ring::before, .gr-ring::after {
  content: ""; position: absolute;
  width: min(52vw, 380px); height: min(52vw, 380px);
  border-radius: 50%;
  border: 3px solid rgba(172,202,50,0.55);
  box-shadow: 0 0 60px rgba(172,202,50,0.35), inset 0 0 40px rgba(172,202,50,0.18);
  animation: grPulse 1.6s cubic-bezier(0.16,1,0.3,1) infinite;
}
.gr-ring::after { animation-delay: 0.8s; border-color: rgba(229,195,83,0.6); box-shadow: 0 0 70px rgba(229,195,83,0.35); }
@keyframes grPulse {
  0%   { transform: scale(0.6); opacity: 0.0; }
  35%  { opacity: 0.9; }
  100% { transform: scale(1.35); opacity: 0; }
}
.get-ready-label.excited {
  position: relative;
  background: linear-gradient(90deg, var(--cc-cream) 0%, var(--cc-lime, #ACCA32) 45%, var(--cc-gold, #E5C353) 55%, var(--cc-cream) 100%);
  background-size: 220% 100%;
  background-clip: text; -webkit-background-clip: text;
  color: transparent; -webkit-text-fill-color: transparent;
  animation: grSweep 1.8s linear infinite;
  filter: drop-shadow(0 8px 24px rgba(172,202,50,0.35));
}
@keyframes grSweep {
  0%   { background-position: 100% 0; }
  100% { background-position: -100% 0; }
}
.gr-countdown-tick {
  display: inline-block;
  animation: grTickPop 0.5s cubic-bezier(0.16,1,0.3,1);
}
@keyframes grTickPop {
  0%   { transform: scale(0.4); opacity: 0; }
  60%  { transform: scale(1.15); opacity: 1; }
  100% { transform: scale(1);    opacity: 1; }
}

/* ═══════════════════════════════════════════════════════════════════
   Preparing Strip — more eventful: shimmer bar + rotating status
   ═══════════════════════════════════════════════════════════════════ */
.prep-shimmer {
  width: min(420px, 78vw);
  height: 6px;
  margin: 22px auto 8px;
  background: rgba(242,244,238,0.10);
  border-radius: 4px;
  overflow: hidden;
  position: relative;
}
.prep-shimmer::after {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(90deg, transparent 0%, var(--cc-lime, #ACCA32) 40%, var(--cc-gold, #E5C353) 60%, transparent 100%);
  transform: translateX(-100%);
  animation: prepShimmerSlide 1.4s linear infinite;
}
@keyframes prepShimmerSlide {
  0%   { transform: translateX(-100%); }
  100% { transform: translateX(100%);  }
}
.prep-status-line {
  font-family: var(--font-mono, monospace);
  font-size: clamp(0.78rem, 1.4vw, 0.92rem);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(242,244,238,0.75);
  min-height: 18px;
  margin-top: 6px;
  transition: opacity 240ms ease;
}
.prep-status-line.swap { opacity: 0; }

/* ═══════════════════════════════════════════════════════════════════════
   RESPONSIVE LAYER  —  landscape + mobile, every screen size
   ───────────────────────────────────────────────────────────────────────
   Appended last so plain source-order lets it refine the portrait-first
   rules above without touching them. Four ideas, in order:
     1. Foundations — dynamic viewport height (mobile chrome) + a universal
        scroll safety-net so NO screen ever clips its content, at any size.
     2. Landscape — reflow the tall stacked screens so they use the width.
     3. Short viewport — compact vertical rhythm (phones held sideways).
     4. Mobile width — tighten padding / touch targets on small phones.
   ═══════════════════════════════════════════════════════════════════════ */

/* ── 1. FOUNDATIONS ─────────────────────────────────────────────────── */

/* Track the *visible* viewport (dvh) so mobile browser toolbars don't clip
   the bottom of a screen. 100vh first as the fallback for older engines. */
html, body { height: 100vh; height: 100dvh; }
.screen {
  bottom: auto;                 /* release inset bottom so height wins      */
  height: 100vh;                /* fallback                                 */
  height: 100dvh;               /* modern: visible-viewport height          */
  overflow-y: auto;             /* scroll instead of clip when content is   */
  overflow-x: hidden;           /*   taller than the viewport               */
  -webkit-overflow-scrolling: touch;
  justify-content: safe center; /* center when it fits; top-align (never
                                   clip the start) when it overflows        */
}
/* Full-bleed screens manage their own absolutely-positioned layout — keep
   them locked (no scroll, no safe-center reflow). */
.capture-screen { justify-content: stretch; overflow: hidden; }
.idle-screen,
.closed-screen  { justify-content: center;  overflow: hidden; }

/* dvh for the two panels that hard-coded 100vh internally. */
.pair-card         { max-height: calc(100dvh - 24px); }
.setup-modal-card  { max-height: 90dvh; }

/* ── 2. LANDSCAPE ───────────────────────────────────────────────────── */
@media (orientation: landscape) {
  /* Global: tighten the vertical gap/padding since height is the scarce axis. */
  .screen { gap: clamp(10px, 2vh, 22px); padding: clamp(14px, 3vh, 40px) clamp(20px, 4vw, 56px); }

  /* Pairing keypad: shave the tall key padding so the card fits without
     scrolling on landscape tablets. */
  .pair-card .kkey,
  .code-terminal .kkey { padding: clamp(9px, 1.6vh, 16px) 0; }
  .pairing-screen .pair-card { max-height: calc(100dvh - 16px); }
}

/* Wide landscape: put the pairing brand/copy beside the keypad instead of
   above it — no vertical scrolling on a landscape booth. The hidden code
   input is position:absolute, so it stays out of the grid. */
@media (orientation: landscape) and (min-width: 860px) {
  .pairing-screen .pair-card {
    width: min(1060px, 95vw);
    display: grid;
    grid-template-columns: 1.05fr 1fr;
    grid-template-areas: "head     terminal"
                         "foot     terminal";
    align-content: center; align-items: center;
    column-gap: clamp(28px, 4vw, 60px);
    row-gap: clamp(12px, 2.4vh, 22px);
    text-align: left;
  }
  .pairing-screen .pair-head { grid-area: head; align-items: flex-start; text-align: left; }
  .pairing-screen .pair-title { text-align: left; }
  .pairing-screen .pair-sub  { margin-left: 0; }
  .pairing-screen .code-terminal { grid-area: terminal; align-self: center; margin: 0; }
  .pairing-screen .pair-foot { grid-area: foot; align-items: stretch; width: 100%; }
}

/* "Get your digital copy": lay the QR card(s) side-by-side on wide landscape. */
@media (orientation: landscape) and (min-width: 760px) {
  .share-wrap  { max-width: min(940px, 95vw); }
  .share-cards { flex-direction: row; flex-wrap: wrap; align-items: stretch; justify-content: center; }
}

/* ── 3. SHORT VIEWPORT (phones held sideways, small landscape panels) ── */

/* Slim the idle operator toolbar so the attract content keeps the stage. */
@media (max-height: 720px) { :root { --idle-toolbar-h: clamp(120px, 20vh, 168px); } }
@media (max-height: 560px) {
  :root { --idle-toolbar-h: clamp(96px, 24vh, 134px); }
  .idle-toolbar { gap: 6px; padding: 8px clamp(12px, 2vw, 22px) 10px; }
  .idle-toolbar .flash-control { padding: 6px clamp(10px, 2vw, 16px); }
}

/* Hide decorative / optional copy that would otherwise force a scroll. */
@media (max-height: 820px) { .pair-watermark { display: none; } }
@media (max-height: 600px) {
  .screen-sub, .pair-sub, .share-sub { display: none; }
  .pairing-screen .pair-rule { display: none; }
}

/* Very short (small phones sideways): scale the display type down a notch. */
@media (max-height: 430px) {
  .screen-title    { font-size: clamp(2rem, 9vh, 3.2rem); }
  .screen-title-sm { font-size: clamp(1.6rem, 7vh, 2.4rem); }
  .share-title     { font-size: clamp(1.8rem, 10vh, 2.8rem); }
}

/* ── 4. MOBILE WIDTH (small phones, portrait or landscape) ──────────── */
@media (max-width: 560px) {
  .screen   { padding: clamp(16px, 5vw, 28px); gap: clamp(12px, 2.5vh, 20px); }
  .pair-card { padding: clamp(20px, 5vw, 34px) clamp(16px, 4vw, 26px); border-radius: 22px; width: min(680px, 94vw); }
  .brand-row { gap: 8px; }
  .send-actions-row .btn { min-height: 54px; padding: 14px 14px; }
  .send-go-btn { min-height: 66px; padding: 18px 24px; }
  /* Denser picker grids so tiles stay tappable without overflowing. */
  .tpl-grid     { grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 12px; }
  .bd-grid      { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px; }
  .sticker-grid { grid-template-columns: repeat(auto-fit, minmax(72px, 1fr)); gap: 10px; }
}

/* Tiny phones: shrink the code boxes + keys so a 6-slot row never overflows. */
@media (max-width: 380px) {
  .pairing-screen .code-box { width: clamp(36px, 12vw, 50px); height: clamp(46px, 15vw, 62px); font-size: clamp(1.5rem, 6vw, 2.2rem); }
  .pairing-screen .code-boxes { gap: clamp(5px, 1.4vw, 10px); }
  .pair-card .kkey, .code-terminal .kkey { font-size: 1.02rem; }
  .keypad .key { font-size: 1.3rem; }
}

/* ── 5. LANDSCAPE REFLOW for the few screens that stack too tall ─────── */

/* SEND (text-your-photo): keypad on the right, everything else on the
   left — fits a landscape booth without scrolling to reach "Send". The
   SMS consent stays full-width across the bottom (carrier readability). */
@media (orientation: landscape) and (min-width: 760px) {
  .send-screen.active {
    display: grid;
    align-content: center; align-items: center; justify-items: center;
    width: 100%; max-width: 1040px; margin: 0 auto;
    column-gap: clamp(24px, 4vw, 52px);
    row-gap: clamp(6px, 1.2vh, 12px);
    grid-template-columns: 1fr minmax(300px, 380px);
    grid-template-areas:
      "title   keypad"
      "phone   keypad"
      "recips  keypad"
      "actions keypad"
      "err     keypad"
      "consent consent";
  }
  .send-screen > .screen-title-sm  { grid-area: title;  align-self: end; }
  .send-screen > .screen-sub-sm    { display: none; }
  .send-screen > .phone-display    { grid-area: phone; }
  .send-screen > .phone-recipients { grid-area: recips; width: 100%; }
  .send-screen > #keypad           { grid-area: keypad; width: 100%; max-width: 360px; align-self: center; margin: 0; }
  .send-screen > .send-actions     { grid-area: actions; margin-top: 0; }
  .send-screen > #sendErr          { grid-area: err; }
  .send-screen > .sms-consent      { grid-area: consent; margin: 4px auto 0; }
}

/* COPIES-QTY (custom quantity dialpad): tighten the column so the 4-row
   pad + readout fit a short landscape panel. */
@media (orientation: landscape) and (max-height: 820px) {
  .qty-screen .qty-wrap { width: min(300px, 82vw); gap: clamp(8px, 1.6vh, 16px); }
  .qty-num { font-size: clamp(2.2rem, 7vh, 3rem); }
}

/* CONFIRM dialogs (end / test / delete): shrink the badge + gaps so the
   icon + copy + buttons fit without scrolling in short landscape. */
@media (orientation: landscape) and (max-height: 780px) {
  .end-confirm-icon { width: clamp(64px, 11vh, 96px); font-size: clamp(2.2rem, 6.2vh, 3.2rem); margin-bottom: 0; }
  .end-confirm-body { gap: 10px; }
  .end-confirm-body .action-row { margin-top: 14px !important; }
}

