/*
 * paste-to-reveal.css — homepage paste-to-reveal experience.
 *
 * Spec: MASSER_PASTE_TO_REVEAL_LANDING_DESIGN_v1.md (sec 3, 4, 5, 6, 7, 8).
 *
 * Visual system (sec 8):
 *  - Obsidian background family, brand v5
 *  - Arc Blue (#5B8BFF) primary, Phase (#A07EFF) accent
 *  - Stellar gradient (Arc → Phase) reserved for the primary CTA only
 *  - Plus Jakarta Sans 800 display, DM Sans body, Orbitron wordmark only
 *  - 4px radius on all buttons (standing rule)
 *  - Zero radius on containers / cards
 *  - No em-dashes anywhere
 *  - No glow/halo around letters (standing rule)
 *
 * CSS variables namespaced --ptr-* to avoid collision with the
 * existing global tokens (--arc, --phase, etc.) so the homepage's
 * cascade is independent and the inline-mounted reveal masters can
 * carry their own --color-* / --font-* without interference.
 */

:root {
  /* Mirror the homepage's brand variables — single source of truth. */
  --ptr-obsidian: #09090C;
  --ptr-void: #0F0F14;
  --ptr-crater: #181820;
  --ptr-surface: #1F1F2A;
  --ptr-rim: #2A2A38;
  --ptr-border: rgba(255, 255, 255, 0.08);
  --ptr-mist: #7E7E98;
  --ptr-dust: #9494A8;
  --ptr-lunar: #E2E2ED;
  --ptr-white: #F4F4FA;
  --ptr-arc: #5B8BFF;
  --ptr-arc-light: #7BA5FF;
  --ptr-phase: #A07EFF;
  --ptr-corona: #F5C842;
  --ptr-red: #FF5C5C;
  --ptr-stellar: linear-gradient(135deg, #5B8BFF 0%, #A07EFF 100%);
  --ptr-font-logo: 'Orbitron', sans-serif;
  --ptr-font-display: 'Plus Jakarta Sans', sans-serif;
  --ptr-font-body: 'DM Sans', sans-serif;
  --ptr-font-mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, monospace;
  --ptr-ease: cubic-bezier(0.16, 1, 0.3, 1);
  --ptr-nav-h: 66px;
}

* { box-sizing: border-box; margin: 0; padding: 0; }
html { scroll-behavior: smooth; }
body {
  background: var(--ptr-obsidian);
  color: var(--ptr-lunar);
  font-family: var(--ptr-font-body);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
  position: relative;
  min-height: 100svh;
}

/* Background atmosphere — faint grid + grain. Mirrors index.html so on
   flag-flip the background field is identical. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image:
    linear-gradient(rgba(255, 255, 255, 0.028) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.028) 1px, transparent 1px);
  background-size: 74px 74px;
  opacity: 0.5;
}
body::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: 0.04;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='2'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* SR-only utility */
.ptr-sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
.ptr-sr-focusable:focus {
  position: fixed;
  top: 14px;
  left: 14px;
  width: auto;
  height: auto;
  clip: auto;
  background: var(--ptr-white);
  color: var(--ptr-obsidian);
  padding: 10px 16px;
  z-index: 9999;
  border-radius: 4px;
}

/* ============================================================ */
/* NAV — quiet, wordmark top-left, brand v5. sec 3.              */
/* ============================================================ */

.ptr-nav {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: var(--ptr-nav-h);
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 clamp(20px, 4vw, 46px);
  background: rgba(9, 9, 12, 0.55);
  backdrop-filter: blur(16px);
  border-bottom: 1px solid transparent;
  transition: background .4s, border-color .4s;
}
.ptr-nav.scrolled {
  background: rgba(9, 9, 12, 0.85);
  border-bottom: 1px solid var(--ptr-border);
}
.ptr-nav__wordmark {
  font-family: var(--ptr-font-logo);
  font-weight: 800;
  font-size: 19px;
  letter-spacing: 0.14em;
  color: var(--ptr-white);
  text-decoration: none;
}
.ptr-nav__signin {
  font-size: 14px;
  color: var(--ptr-dust);
  text-decoration: none;
  padding: 8px 12px;
  border-radius: 4px;
  transition: color .25s, background .25s;
}
.ptr-nav__signin:hover {
  color: var(--ptr-white);
  background: rgba(255, 255, 255, 0.04);
}

/* ============================================================ */
/* HERO — paste-first. sec 3.                                    */
/* ============================================================ */

.ptr-hero {
  position: relative;
  min-height: 100svh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: calc(var(--ptr-nav-h) + 40px) 24px 60px;
  overflow: hidden;
  z-index: 1;
}
.ptr-hero__bg {
  position: absolute;
  inset: 0;
  z-index: 0;
  background:
    radial-gradient(60% 80% at 30% 30%, rgba(91, 139, 255, 0.10), transparent 60%),
    radial-gradient(50% 60% at 75% 70%, rgba(160, 126, 255, 0.08), transparent 60%);
  pointer-events: none;
}
.ptr-hero__inner {
  position: relative;
  z-index: 2;
  width: 100%;
  max-width: 820px;
  text-align: center;
  margin-inline: auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 28px;
  padding: 0 4px;
}
/* Headline container. No size of its own — children own the type scale
   so the lead/main/soft hierarchy isn't flattened by inheritance. */
.ptr-hero__h1 {
  font-family: var(--ptr-font-display);
  font-weight: 700;
  color: var(--ptr-white);
  width: 100%;
  margin: 0;
  /* Stack the three phrases with a controlled rhythm: small gap setup→payoff,
     larger gap payoff→subline. Implemented via per-child margins below. */
  word-wrap: break-word;
  overflow-wrap: break-word;
}
/* Lead phrase — quieter, lighter, sets the premise.
   Sized at ~55% of the payoff so the eye reads it as setup, not headline.
   text-wrap:balance kills orphan single-word lines. */
.ptr-hero__h1-lead {
  display: block;
  width: 100%;
  font-family: var(--ptr-font-display);
  font-weight: 500;
  font-style: normal;
  color: var(--ptr-mist);
  font-size: clamp(20px, 4vw, 38px);
  line-height: 1.25;
  letter-spacing: -0.01em;
  text-wrap: balance;
  margin: 0 0 14px;
}
/* Main phrase — the largest, boldest element on the page. The eye must land
   here. Display line-height + slight negative tracking. Balanced wrap so the
   br between "that" and the accent is the only forced break. */
.ptr-hero__h1-main {
  display: block;
  width: 100%;
  font-family: var(--ptr-font-display);
  font-weight: 800;
  font-style: normal;
  color: var(--ptr-white);
  font-size: clamp(36px, 7vw, 72px);
  line-height: 1.15;
  padding-bottom: 0.06em;
  letter-spacing: -0.02em;
  text-wrap: balance;
  margin: 0;
}
/* Accent — "wins customers" — colour lift only, no italic.
   Same family + weight as the main phrase; arc-blue carries the emphasis. */
.ptr-hero__h1-accent {
  font-family: var(--ptr-font-display);
  font-style: normal;
  font-weight: 800;
  color: var(--ptr-arc);
  letter-spacing: -0.02em;
}
/* Subline — smaller than the payoff, muted, balanced.
   Sits on the same centred axis with a clear gap above. */
.ptr-hero__h1-soft {
  display: block;
  font-family: var(--ptr-font-display);
  font-style: normal;
  font-weight: 500;
  color: var(--ptr-mist);
  font-size: clamp(15px, 2.5vw, 22px);
  line-height: 1.4;
  letter-spacing: -0.005em;
  text-wrap: balance;
  max-width: 48ch;
  margin: 18px auto 0;
}
/* Mobile / small viewport recompose (375px target).
   Suppress the forced <br> on the payoff so the line wraps naturally with
   balance instead of producing two stranded lines. Tighten the scale. */
/* -- Picker v2: row actions (rename / add-inside / remove / drag) -- */
.wz7__row-actions {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  margin-left: auto;
  opacity: 0;
  transition: opacity 0.15s ease;
}
.wz7__tree-row:hover .wz7__row-actions,
.wz7__tree-row:focus-within .wz7__row-actions {
  opacity: 1;
}
/* Touch: no hover — actions stay visible at reduced prominence. */
@media (pointer: coarse) {
  .wz7__row-actions { opacity: 0.6; }
  .wz7__tree-row:focus-within .wz7__row-actions { opacity: 1; }
}
.wz7__row-action {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  padding: 7px;
  background: transparent;
  border: none;
  color: rgba(255, 255, 255, 0.45);
  cursor: pointer;
  transition: color 0.15s ease, background 0.15s ease;
}
.wz7__row-action svg { width: 100%; height: 100%; display: block; }
.wz7__row-action:hover,
.wz7__row-action:focus-visible {
  color: var(--ptr-white);
  background: rgba(255, 255, 255, 0.06);
  outline: none;
}
.wz7__row-action--remove:hover { color: #e2584d; }
.wz7__row-action--grip { cursor: grab; }
.wz7__tree-row--dragging { opacity: 0.35; }
/* Drag is a fine-pointer affordance; order stays editable in the portal.
   (Ship-or-hide: no half-working touch drag.) Keyboard arrows on the
   handle still work everywhere. */
@media (pointer: coarse) {
  .wz7__row-action--grip { display: none; }
  /* >=36px tap targets on touch (spec 4.5) — placed after the base
     .wz7__row-action rule so it wins the cascade at equal specificity */
  .wz7__row-action { width: 36px; height: 36px; padding: 8px; }
}

/* -- Picker v2: inline rename wrapper + validation error -- */
.wz7__tree-edit-wrap {
  display: flex;
  flex: 1;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
.wz7__tree-err {
  flex-basis: 100%;
  margin: 4px 0 0;
  font-family: var(--wz-font-body);
  font-size: var(--wz-type-caption);
  color: #e2938c;
}

/* -- Picker v2: in-place remove confirm -- */
.wz7__tree-row--confirm { border-color: rgba(226, 88, 77, 0.35); }
.wz7__tree-confirm-remove {
  background: rgba(226, 88, 77, 0.16);
  border-color: rgba(226, 88, 77, 0.5);
  color: #ffb4ad;
}
.wz7__tree-confirm-remove:hover { background: rgba(226, 88, 77, 0.3); }
.wz7__tree-confirm-keep { opacity: 0.8; }

@media (max-width: 520px) {
  .ptr-hero__h1-lead { font-size: clamp(15px, 4vw, 19px); margin-bottom: 8px; }
  .ptr-hero__h1-main { font-size: clamp(28px, 8.5vw, 38px); line-height: 1.2; padding-bottom: 0.06em; }
  .ptr-hero__h1-soft { font-size: clamp(14.5px, 3.8vw, 17px); margin-top: 12px; max-width: 28ch; }
  .ptr-hero__h1-break { display: none; }
}

/* Paste form: large single input + direction button. */
.ptr-hero__form {
  width: 100%;
  max-width: 600px;
  margin-top: 6px;
}
.ptr-hero__row {
  display: flex;
  gap: 10px;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid var(--ptr-border);
  border-radius: 4px;
  padding: 6px;
  cursor: text; /* whole field reads as a typable text box */
  transition: border-color .25s, box-shadow .25s;
}
.ptr-hero__row:focus-within {
  border-color: var(--ptr-arc);
  box-shadow: 0 0 0 2px rgba(91, 139, 255, 0.35);
}
.ptr-hero__input {
  flex: 1;
  background: transparent;
  border: none;
  outline: none;
  padding: 14px 18px;
  font-family: var(--ptr-font-body);
  font-size: 17px;
  color: var(--ptr-white);
  caret-color: var(--ptr-arc); /* visible blinking caret on dark surface */
  cursor: text;
  min-width: 0;
}
.ptr-hero__input::placeholder { color: var(--ptr-mist); }
.ptr-hero__cta {
  font-family: var(--ptr-font-display);
  font-weight: 600;
  font-size: 15px;
  color: var(--ptr-white);
  background: var(--ptr-stellar);
  border: none;
  border-radius: 4px;
  padding: 12px 22px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  white-space: nowrap;
  box-shadow: 0 12px 36px -14px rgba(123, 165, 255, 0.55);
  transition: transform .18s var(--ptr-ease), box-shadow .18s var(--ptr-ease);
}
.ptr-hero__cta:hover {
  transform: translateY(-2px) scale(1.02);
  box-shadow: 0 12px 36px -10px rgba(245, 200, 66, 0.30), 0 4px 18px -6px rgba(91, 139, 255, 0.40);
}
.ptr-hero__cta:active { transform: translateY(0) scale(1); }
.ptr-hero__cta[disabled] { opacity: 0.6; cursor: progress; }
.ptr-hero__cta svg { width: 16px; height: 16px; stroke: var(--ptr-white); fill: none; stroke-width: 2.2; }

.ptr-hero__error {
  margin-top: 10px;
  color: var(--ptr-red);
  font-size: 14px;
  font-weight: 500;
  text-align: center;
}

/* Managed Turnstile, interaction-only: renders no visible UI on the
   clean path, so it takes no space. If Cloudflare requires interaction
   the challenge surfaces here, centred and visible, rather than being
   parked off-screen where the user could not complete it. */
.ptr-hero__turnstile { display: flex; justify-content: center; }
.ptr-hero__turnstile:empty { display: none; }

.ptr-hero__reassure {
  font-size: 13.5px;
  color: var(--ptr-mist);
  letter-spacing: 0.04em;
}
/* Permanent bluey-purple shimmer band over a mist base.
   Base colour is var(--ptr-mist) (not transparent), so every character is
   visible at every animation frame. The highlight band is arc-blue lifting
   into phase-violet — a continuous glimmer that drifts L→R every 4.5s. */
.ptr-hero__reassure-shimmer {
  display: inline-block;
  background-image: linear-gradient(
    90deg,
    var(--ptr-mist) 0%,
    var(--ptr-mist) 38%,
    var(--ptr-arc) 47%,
    var(--ptr-phase) 50%,
    var(--ptr-arc) 53%,
    var(--ptr-mist) 62%,
    var(--ptr-mist) 100%
  );
  background-size: 220% 100%;
  background-position: 100% 0;
  background-repeat: repeat-x;
  -webkit-background-clip: text;
          background-clip: text;
  -webkit-text-fill-color: transparent;
          color: transparent;
  animation: ptr-reassure-shimmer 4.5s linear infinite;
}
@keyframes ptr-reassure-shimmer {
  from { background-position: 100% 0; }
  to   { background-position: -100% 0; }
}

/* Bold letterform shimmer — "reading your pages" loading states (2026-07-13).
   The letters themselves sweep into the accent colour; no glow or halo
   (standing rule above) — background-clip:text only, never text-shadow or
   filter. Bolder weight + a fuller accent band than .ptr-hero__reassure-
   shimmer's quiet permanent glimmer above: this one is meant to be noticed,
   not just felt. Shared by every render of this exact loading moment:
    - the signup gate's "Reading your current pages…" status line
      (lib/paste-to-reveal/gate.js, class applied there)
    - the theatre's phase-2 "Reading your website." title, scoped below so
      theatre.js/buildCinemaScaffold needs no change — only phase 2 shimmers,
      phases 3/4/5/7/9/8 stay plain white. */
.ptr-shimmer-reading,
.ptr-cinema__phase[data-phase="2"] .ptr-cinema__title {
  background-image: linear-gradient(
    100deg,
    var(--ptr-white) 0%,
    var(--ptr-white) 32%,
    var(--ptr-arc) 46%,
    var(--ptr-phase) 50%,
    var(--ptr-arc) 54%,
    var(--ptr-white) 68%,
    var(--ptr-white) 100%
  );
  background-size: 260% 100%;
  background-position: 100% 0;
  background-repeat: repeat-x;
  -webkit-background-clip: text;
          background-clip: text;
  -webkit-text-fill-color: transparent;
          color: transparent;
  animation: ptr-shimmer-reading-sweep 2.4s linear infinite;
}
@keyframes ptr-shimmer-reading-sweep {
  from { background-position: 100% 0; }
  to   { background-position: -160% 0; }
}
@media (prefers-reduced-motion: reduce) {
  .ptr-shimmer-reading,
  .ptr-cinema__phase[data-phase="2"] .ptr-cinema__title {
    animation: none;
    background-position: 0% 0;
  }
}
/* Gate modal's status line was a quiet 14px inline-styled grey paragraph
   (color:#9aa0a6) — now bold + shimmering via the shared class above. */
.ptr-gate__loading-line {
  font-family: var(--ptr-font-display);
  font-weight: 700;
  font-size: 15px;
  padding: 14px 2px;
  margin: 0;
  display: inline-block;
}

/* The other door — a true secondary CTA paired with the primary.
   Ghost treatment on the dark hero: transparent fill, muted arc-blue
   1px border, white label, 4px radius per brand law. Hover brightens
   the border to arc-blue with a faint arc glow; the Stellar gradient
   stays reserved for the primary so the eye ranks them correctly. */
.ptr-hero__nosite {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 264px;
  padding: 13px 26px;
  background: transparent;
  border: 1px solid rgba(123, 165, 255, 0.32);
  border-radius: 4px;
  font-family: var(--ptr-font-body);
  font-size: 15px;
  font-weight: 600;
  color: var(--ptr-white);
  cursor: pointer;
  transition: border-color .2s, background-color .2s, box-shadow .2s;
}
.ptr-hero__nosite:hover {
  border-color: var(--ptr-arc);
  background: rgba(91, 139, 255, 0.08);
  box-shadow: 0 0 0 3px rgba(91, 139, 255, 0.10);
}
.ptr-hero__nosite:focus-visible { outline: 2px solid var(--ptr-arc); outline-offset: 2px; }

/* Google reviews strip - approved mock 2026-07-17, quiet under hero.
   Hidden ([hidden] + data-available) until google-reviews.js mounts it. */
.ptr-gstrip {
  margin-top: 26px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  font-size: 13px;
  color: var(--ptr-dust);
  letter-spacing: 0.01em;
  text-decoration: none;
}
.ptr-gstrip[hidden] { display: none; }
.ptr-gstrip__badge { display: flex; align-items: center; gap: 8px; flex: none; }
.ptr-gstrip__g { width: 18px; height: 18px; flex: none; }
.ptr-gstrip__score { font-weight: 700; color: var(--ptr-white); font-size: 13.5px; }
.ptr-gstrip__stars {
  color: var(--ptr-corona);
  letter-spacing: 0.14em;
  font-size: 12px;
  text-shadow: 0 0 10px rgba(245, 200, 66, 0.4);
}
.ptr-gstrip__div { width: 1px; height: 16px; background: rgba(255, 255, 255, 0.16); flex: none; }
.ptr-gstrip__quote {
  max-width: 430px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  color: var(--ptr-lunar);
  font-style: italic;
}
.ptr-gstrip__quote b { font-style: normal; font-weight: 600; color: var(--ptr-mist); flex: none; }
.ptr-gstrip__link { color: var(--ptr-arc); white-space: nowrap; flex: none; }
.ptr-gstrip:hover .ptr-gstrip__link { text-decoration: underline; }
.ptr-gstrip:focus-visible { outline: 2px solid var(--ptr-arc); outline-offset: 3px; }

@media (max-width: 520px) {
  .ptr-hero { padding: calc(var(--ptr-nav-h) + 24px) 18px 40px; }
  .ptr-hero__inner { gap: 22px; }
  .ptr-hero__row { flex-direction: column; padding: 6px; gap: 6px; }
  .ptr-hero__cta { width: 100%; justify-content: center; padding: 14px 22px; }
  .ptr-hero__nosite { width: 100%; min-width: 0; box-sizing: border-box; padding: 14px 22px; }
  .ptr-gstrip { flex-direction: column; gap: 7px; margin-top: 20px; }
  .ptr-gstrip__div { display: none; }
  .ptr-gstrip__quote { max-width: 88vw; font-size: 12.5px; }
  .ptr-gstrip__link { font-size: 12px; }
}

/* ============================================================ */
/* THEATRE — sec 4. Filled when paste submits.                   */
/* ============================================================ */

.ptr-theatre {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  background: var(--ptr-obsidian);
  overflow: hidden;
  opacity: 0;
  transition: opacity .55s var(--ptr-ease);
}
/* Inline `hidden` attribute must actually hide — the explicit `display: flex`
   above otherwise overrides the UA `[hidden] { display: none }` and the panel
   stays on the page intercepting clicks over the hero. */
.ptr-theatre[hidden] { display: none; }
.ptr-theatre[data-active] { opacity: 1; }

.ptr-theatre__canvas {
  flex: 1;
  position: relative;
  overflow: hidden;
  /* Beats 1-4 render layers into this canvas. The "develop" stage uses
     the prospect's confirmed colour via CSS custom properties applied
     to the canvas root (set by theatre.js). */
}

/* Persistent MASSER wordmark — top centre, calm. Subtle enough that
   the phase title at centre-screen is always the focal point. Matches
   .welcome__wordmark (Orbitron 800, all-caps, wide tracking) so the
   theatre's brand identity is consistent with the welcome modal.
   Lives inside .ptr-theatre so it inherits the theatre's opacity
   fade-in/out — no separate JS lifecycle, disappears with the theatre
   when reveal mounts. */
.ptr-theatre__logo {
  position: absolute;
  top: 22px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 5; /* above the constellation canvas + phases, below the confirm card slide-in */
  font-family: var(--ptr-font-logo);
  font-weight: 800;
  font-size: clamp(13px, 1.2vw, 16px);
  letter-spacing: 0.28em;
  color: var(--ptr-white);
  opacity: 0.72; /* quieter than the centred phase text */
  text-transform: uppercase;
  white-space: nowrap;
  line-height: 1;
  pointer-events: none;
  user-select: none;
}
@media (max-width: 520px) {
  .ptr-theatre__logo { top: 18px; letter-spacing: 0.24em; }
}

/* Stage label — bottom centre, honest, no percentage. sec 4 rule 3. */
.ptr-theatre__stage {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 32px;
  display: flex;
  justify-content: center;
  pointer-events: none;
  z-index: 5;
}
.ptr-theatre__stage-label {
  font-family: var(--ptr-font-body);
  font-size: 13px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ptr-dust);
  font-weight: 500;
  padding: 10px 18px;
  background: rgba(9, 9, 12, 0.6);
  border: 1px solid var(--ptr-border);
  border-radius: 4px;
  backdrop-filter: blur(8px);
  opacity: 0;
  transform: translateY(8px);
  transition: opacity .4s var(--ptr-ease), transform .4s var(--ptr-ease);
}
.ptr-theatre__stage-label[data-visible] { opacity: 1; transform: translateY(0); }

/* Source-material framing — Beat 1 raw layer, desaturated image-on-workbench. */
.ptr-theatre__raw {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  gap: 32px;
  padding: 80px 24px;
  opacity: 0;
  transition: opacity .8s var(--ptr-ease);
}
.ptr-theatre__raw[data-visible] { opacity: 1; }
.ptr-theatre__raw-meta {
  font-family: var(--ptr-font-body);
  font-size: 13px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ptr-mist);
}
.ptr-theatre__raw-name {
  font-family: var(--ptr-font-display);
  font-weight: 700;
  font-size: clamp(36px, 6vw, 64px);
  color: var(--ptr-white);
  letter-spacing: -0.02em;
  text-align: center;
  line-height: 1.2;
  padding-bottom: 0.06em;
}
.ptr-theatre__raw-line {
  font-family: var(--ptr-font-body);
  font-size: clamp(16px, 2vw, 19px);
  font-weight: 500;
  color: var(--ptr-dust);
  max-width: 50ch;
  text-align: center;
  line-height: 1.5;
}
.ptr-theatre__raw-image {
  width: clamp(220px, 30vw, 360px);
  aspect-ratio: 4 / 3;
  background: var(--ptr-void);
  border: 1px solid var(--ptr-border);
  background-size: cover;
  background-position: center;
  filter: saturate(0.15) brightness(0.65) contrast(1.05);
  position: relative;
}
.ptr-theatre__raw-image::after {
  content: "BEFORE";
  position: absolute;
  bottom: 10px;
  left: 12px;
  font-family: var(--ptr-font-body);
  font-size: 10px;
  letter-spacing: 0.3em;
  color: rgba(255, 255, 255, 0.5);
  background: rgba(0, 0, 0, 0.6);
  padding: 4px 8px;
}

/* Develop layer — Beat 2. Blocks compose, colour floods in. */
.ptr-theatre__develop {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  padding: 64px clamp(24px, 5vw, 80px);
  opacity: 0;
  transition: opacity 1s var(--ptr-ease);
  --ptr-develop-accent: var(--ptr-arc);
  --ptr-develop-surface: var(--ptr-obsidian);
}
.ptr-theatre__develop[data-visible] { opacity: 1; }
.ptr-theatre__develop-block {
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid var(--ptr-border);
  margin-bottom: 18px;
  height: 14vh;
  position: relative;
  overflow: hidden;
  opacity: 0;
  transform: translateY(20px);
  animation: ptr-block-in .9s var(--ptr-ease) forwards;
}
@keyframes ptr-block-in {
  to { opacity: 1; transform: translateY(0); }
}
.ptr-theatre__develop-block::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(135deg, var(--ptr-develop-accent), transparent 60%);
  opacity: 0.18;
}
.ptr-theatre__develop-block--hero { height: 32vh; }
.ptr-theatre__develop-block--hero::after {
  content: "";
  position: absolute;
  left: 5%;
  bottom: 12%;
  width: 50%;
  height: 4px;
  background: var(--ptr-develop-accent);
}
.ptr-theatre__develop-block:nth-child(2) { animation-delay: .2s; }
.ptr-theatre__develop-block:nth-child(3) { animation-delay: .4s; }
.ptr-theatre__develop-block:nth-child(4) { animation-delay: .6s; }
.ptr-theatre__develop-block:nth-child(5) { animation-delay: .8s; }

/* ============================================================ */
/* CINEMA — eight-phase cinematic arc inside #ptr-theatre-canvas */
/* (replaces the Beat 1 raw + Beat 2 develop layers).            */
/* See docs/RECON_CINEMATIC_THEATRE.md §3, §5.                    */
/*                                                              */
/* Structure: one container with eight stacked phase layers. Only */
/* one phase has data-active at a time. Phase swap = cross fade  */
/* on opacity. Internal element animations land in C3.           */
/*                                                              */
/* This commit (C2) ships SCAFFOLD ONLY — base layout, type      */
/* tokens, no animations. Cinema is invisible until theatre.js   */
/* hydrates it in C3+.                                            */
/* ============================================================ */

.ptr-cinema {
  position: absolute;
  inset: 0;
  display: block;
  pointer-events: none; /* cinema is decorative; confirm card owns interaction */
}

/* Each phase is a stacked absolute layer. Only the active one is */
/* visible. opacity is the sole property animated for phase swap. */
.ptr-cinema__phase {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  /* Generous breathing room. 60-80px desktop, 32-48px mobile (override below). */
  padding: 72px clamp(24px, 5vw, 56px);
  text-align: center;
  opacity: 0;
  transition: opacity .55s var(--ptr-ease);
}
.ptr-cinema__phase[data-active] { opacity: 1; }

/* Inner composition column — centred, breathing, capped width.
 *
 * 40px desktop gap is above the brief's 40px flag threshold. Mobile
 * recompose (max-width: 520px below) collapses to 28px which is
 * still above the brief's 24px mobile flag threshold. Type weights
 * carry the visual hierarchy; the gap stays uniform so every phase
 * reads as the same beat structure. */
.ptr-cinema__column {
  width: 100%;
  max-width: 720px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 40px;
}

/* Top-of-composition label tray. Small caps in the display family per
   George's call (was JetBrains Mono, swapped to Plus Jakarta for brand
   consistency with the rest of the cinematic). */
.ptr-cinema__mono {
  font-family: var(--ptr-font-display);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ptr-mist);
  line-height: 1.4;
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
/* Pre-title pip — small square that picks up the active accent. */
.ptr-cinema__mono::before {
  content: "";
  display: inline-block;
  width: 6px;
  height: 6px;
  background: var(--ptr-arc);
  border-radius: 1px;
}

/* Phase title — the headline of each beat. Plus Jakarta, oversized. */
.ptr-cinema__title {
  font-family: var(--ptr-font-display);
  font-weight: 700;
  font-size: clamp(36px, 5vw, 56px);
  line-height: 1.2;
  padding-bottom: 0.08em;
  letter-spacing: -0.02em;
  color: var(--ptr-white);
  margin: 0;
  text-wrap: balance;
}

/* Phase body — supporting line below the title. DM Sans, lunar. */
.ptr-cinema__body {
  font-family: var(--ptr-font-body);
  font-size: 17px;
  font-weight: 500;
  line-height: 1.55;
  color: var(--ptr-lunar);
  max-width: 56ch;
  margin: 0;
  text-wrap: balance;
}

/* Phase 1 business name — oversized hero word. */
.ptr-cinema__name {
  font-family: var(--ptr-font-display);
  font-weight: 800;
  font-size: clamp(48px, 7vw, 80px);
  line-height: 1.15;
  padding-bottom: 0.08em;
  letter-spacing: -0.025em;
  color: var(--ptr-white);
  margin: 0;
  text-wrap: balance;
}

/* Phase 1 town subtitle. */
.ptr-cinema__town {
  font-family: var(--ptr-font-body);
  font-size: 18px;
  font-weight: 500;
  color: var(--ptr-dust);
  letter-spacing: 0.02em;
  margin: 0;
}

/* Workbench thumbnail — phase 1 only, atmospheric, not centrepiece. */
.ptr-cinema__thumb {
  width: 240px;
  aspect-ratio: 4 / 3;
  background: var(--ptr-void);
  border: 1px solid var(--ptr-border);
  border-radius: 12px;
  background-size: cover;
  background-position: center;
  filter: saturate(0.85) brightness(0.85) contrast(1.02);
  position: relative;
  overflow: hidden;
}
/* Vignette gradient over the thumbnail for premium feel — no glow. */
/* radius inherits so the gradient doesn't bleed the rounded corners.*/
.ptr-cinema__thumb::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background:
    linear-gradient(180deg, transparent 60%, rgba(9, 9, 12, 0.45) 100%),
    linear-gradient(90deg, rgba(9, 9, 12, 0.2) 0%, transparent 30%, transparent 70%, rgba(9, 9, 12, 0.2) 100%);
  pointer-events: none;
}

/* Mono ticker — bottom of composition (phases 2-5, 7). Three rows  */
/* of small-caps mono lines that look like live signal markers.      */
/* INDICATIVE only — no measured score, no /100, no ms, no seconds.  */
.ptr-cinema__ticker {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 8px;
}
.ptr-cinema__ticker-row {
  font-family: var(--ptr-font-logo); /* Orbitron — short all-caps data-feel labels. */
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ptr-dust);
  display: inline-flex;
  align-items: center;
  gap: 8px;
  opacity: 0.85;
}
/* Ticker row prefix — a tiny rule that reads as a signal channel. */
.ptr-cinema__ticker-row::before {
  content: "";
  display: inline-block;
  width: 14px;
  height: 1px;
  background: var(--ptr-rim);
}
/* When marked complete, the row prefix turns arc-blue — quiet tick. */
.ptr-cinema__ticker-row[data-state="ok"] {
  color: var(--ptr-lunar);
  opacity: 1;
}
.ptr-cinema__ticker-row[data-state="ok"]::before { background: var(--ptr-arc); }

/* ── Phase 8 quiet pulse — runs during the final "Bringing it to life"
 * beat while we wait on the reveal data + welcome handoff. Three
 * arc-blue dots breathing in soft sequence. Transform + opacity only,
 * GPU-friendly. Bigger gap above so it sits separate from the ticker.
 * Reduced motion (handled at the bottom of the file) collapses the
 * animation to a still arc-blue trio. */
.ptr-cinema__pulse {
  display: inline-flex;
  gap: 9px;
  margin-top: 36px;
  opacity: 0;
  transition: opacity .6s var(--ptr-ease) .8s;
}
.ptr-cinema__phase[data-active] .ptr-cinema__pulse { opacity: 1; }
.ptr-cinema__pulse-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--ptr-arc);
  animation: ptr-cinema-pulse 1.4s var(--ptr-ease) infinite;
  will-change: transform, opacity;
}
.ptr-cinema__pulse-dot:nth-child(2) { animation-delay: .2s; }
.ptr-cinema__pulse-dot:nth-child(3) { animation-delay: .4s; }
@keyframes ptr-cinema-pulse {
  0%, 100% { transform: scale(0.7); opacity: 0.35; }
  50%      { transform: scale(1.15); opacity: 1; }
}
/* Honest reassurance line directly under the pulse. Fades in slightly
 * after the pulse so the eye lands on the dots first. Muted DM Sans
 * body so it reads as supporting copy, not a second headline. */
.ptr-cinema__pulse-line {
  font-family: var(--ptr-font-body);
  font-size: 14px;
  font-weight: 500;
  color: var(--ptr-dust);
  line-height: 1.5;
  margin-top: 22px;
  opacity: 0;
  transition: opacity .6s var(--ptr-ease) 1.1s;
  text-align: center;
  max-width: 38ch;
}
.ptr-cinema__phase[data-active] .ptr-cinema__pulse-line { opacity: 1; }
@media (prefers-reduced-motion: reduce) {
  .ptr-cinema__pulse-dot { animation: none !important; transform: scale(1); opacity: 0.85; }
}

/* ── Internal choreography (per-element enter staggers).
 * Each child of a phase column starts in a held "before" state and
 * eases to its "after" state when the parent phase carries
 * data-active. All animation is on transform + opacity + clip-path
 * only (GPU-friendly, no layout thrash, no shadow/filter jank).
 * Single curve (--ptr-ease). Staggers from the audit doc §5.
 *
 * Reduced motion (handled at the very bottom of this file) collapses
 * the staggers to instant — type is still revealed in order but no
 * motion is performed.
 */

/* Mono label — fades in plain, 200ms after phase activates. */
.ptr-cinema__phase .ptr-cinema__mono {
  opacity: 0;
  transform: translateY(8px);
  transition: opacity .5s var(--ptr-ease) .2s, transform .5s var(--ptr-ease) .2s;
}
.ptr-cinema__phase[data-active] .ptr-cinema__mono {
  opacity: 1;
  transform: translateY(0);
}

/* Title — mask wipe left-to-right via clip-path. The title "writes
 * in" rather than fading. 900ms duration, 350ms delay so the mono
 * label is visible first.
 *
 * Why two layers (clip-path + opacity): clip-path alone leaves a hard
 * leading edge that can feel mechanical. Adding a tiny opacity fade
 * on top softens the leading edge to read as ink resolving rather
 * than text being painted.
 */
.ptr-cinema__phase .ptr-cinema__title,
.ptr-cinema__phase .ptr-cinema__name {
  opacity: 0;
  clip-path: inset(0 100% 0 0);
  transition:
    clip-path .9s var(--ptr-ease) .35s,
    opacity .55s var(--ptr-ease) .35s;
}
.ptr-cinema__phase[data-active] .ptr-cinema__title,
.ptr-cinema__phase[data-active] .ptr-cinema__name {
  opacity: 1;
  clip-path: inset(0 0 0 0);
}

/* Phase 1 town subtitle — quiet fade in after the name. */
.ptr-cinema__phase .ptr-cinema__town {
  opacity: 0;
  transform: translateY(8px);
  transition: opacity .55s var(--ptr-ease) .85s, transform .55s var(--ptr-ease) .85s;
}
.ptr-cinema__phase[data-active] .ptr-cinema__town {
  opacity: 1;
  transform: translateY(0);
}

/* Body line — vertical lift fade, 650ms after activate. */
.ptr-cinema__phase .ptr-cinema__body {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity .7s var(--ptr-ease) .65s, transform .7s var(--ptr-ease) .65s;
}
.ptr-cinema__phase[data-active] .ptr-cinema__body {
  opacity: 1;
  transform: translateY(0);
}

/* Phase 1 thumbnail — gentle opacity fade with a small scale lift
 * (1.04 → 1) so the thumbnail "settles" into frame. */
.ptr-cinema__phase .ptr-cinema__thumb {
  opacity: 0;
  transform: scale(1.04);
  transition: opacity 1.1s var(--ptr-ease) .8s, transform 1.4s var(--ptr-ease) .8s;
}
.ptr-cinema__phase[data-active] .ptr-cinema__thumb {
  opacity: 1;
  transform: scale(1);
}

/* Ticker — container fades in then rows light one by one. Each row
 * carries a per-row delay via :nth-child(n). The first row state-flips
 * to ok at ~1.4s, second at ~2.0s, third at ~2.6s. Engine writes the
 * data-state attribute via setTimeout in C5 — until then the CSS-only
 * fade gives the row a quiet presence on enter.
 */
.ptr-cinema__phase .ptr-cinema__ticker {
  opacity: 0;
  transform: translateY(8px);
  transition: opacity .55s var(--ptr-ease) .9s, transform .55s var(--ptr-ease) .9s;
}
.ptr-cinema__phase[data-active] .ptr-cinema__ticker {
  opacity: 1;
  transform: translateY(0);
}
.ptr-cinema__phase .ptr-cinema__ticker-row {
  opacity: 0;
  transition: opacity .45s var(--ptr-ease), color .35s var(--ptr-ease);
}
.ptr-cinema__phase .ptr-cinema__ticker-row::before {
  transition: background .35s var(--ptr-ease);
}
.ptr-cinema__phase[data-active] .ptr-cinema__ticker-row { opacity: 0.85; }
.ptr-cinema__phase[data-active] .ptr-cinema__ticker-row:nth-child(1) {
  transition-delay: 1.0s;
}
.ptr-cinema__phase[data-active] .ptr-cinema__ticker-row:nth-child(2) {
  transition-delay: 1.35s;
}
.ptr-cinema__phase[data-active] .ptr-cinema__ticker-row:nth-child(3) {
  transition-delay: 1.7s;
}

/* Mobile 375 recomposition — composition not squished, type scaled. */
@media (max-width: 520px) {
  .ptr-cinema__phase { padding: 48px 24px; }
  .ptr-cinema__column { gap: 28px; max-width: none; }
  .ptr-cinema__mono { font-size: 11px; letter-spacing: 0.18em; }
  .ptr-cinema__title { font-size: clamp(28px, 7vw, 34px); line-height: 1.2; padding-bottom: 0.08em; }
  .ptr-cinema__body { font-size: 15px; max-width: none; }
  .ptr-cinema__name { font-size: clamp(36px, 9vw, 46px); line-height: 1.15; padding-bottom: 0.08em; }
  .ptr-cinema__town { font-size: 16px; }
  .ptr-cinema__thumb { width: 100%; max-width: 320px; }
  .ptr-cinema__ticker-row { font-size: 11px; letter-spacing: 0.1em; }
}

/* ============================================================ */
/* CONFIRM (Beat 3) — sec 5.                                     */
/* ============================================================ */

.ptr-confirm {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(9, 9, 12, 0.78);
  backdrop-filter: blur(12px);
  padding: 24px;
  opacity: 0;
  transition: opacity .4s var(--ptr-ease);
}
.ptr-confirm[data-visible] { opacity: 1; }
.ptr-confirm__card {
  width: 100%;
  max-width: 480px;
  background: var(--ptr-void);
  border: 1px solid var(--ptr-border);
  border-radius: 0;
  padding: 36px 32px;
  display: flex;
  flex-direction: column;
  gap: 22px;
}
.ptr-confirm__eyebrow {
  font-family: var(--ptr-font-body);
  font-size: 11.5px;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--ptr-corona);
  font-weight: 600;
}
.ptr-confirm__heading {
  font-family: var(--ptr-font-display);
  font-weight: 800;
  font-size: clamp(26px, 3.6vw, 34px);
  color: var(--ptr-white);
  letter-spacing: -0.025em;
  line-height: 1.2;
  padding-bottom: 0.05em;
}
.ptr-confirm__field { display: flex; flex-direction: column; gap: 6px; }
.ptr-confirm__label {
  font-family: var(--ptr-font-body);
  font-size: 12px;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--ptr-mist);
  font-weight: 600;
}
.ptr-confirm input[type="text"] {
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid var(--ptr-border);
  outline: none;
  padding: 12px 14px;
  font-family: var(--ptr-font-body);
  font-size: 15.5px;
  color: var(--ptr-white);
  border-radius: 0;
  transition: border-color .2s;
}
.ptr-confirm input[type="text"]:focus { border-color: var(--ptr-arc); }
.ptr-confirm__colour { display: flex; flex-direction: column; gap: 10px; }
.ptr-confirm__swatches {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 8px;
}
.ptr-confirm__swatch {
  aspect-ratio: 1;
  border: 2px solid transparent;
  cursor: pointer;
  background-color: var(--swatch-colour, #5B8BFF);
  border-radius: 4px;
  transition: border-color .2s, transform .2s;
}
.ptr-confirm__swatch:hover { transform: translateY(-2px); }
.ptr-confirm__swatch[data-selected] { border-color: var(--ptr-white); }
.ptr-confirm__custom-row {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  cursor: pointer;
  padding: 8px 12px;
  border: 1px solid var(--ptr-border);
  border-radius: 4px;
  width: fit-content;
}
.ptr-confirm__custom-row input[type="color"] {
  -webkit-appearance: none;
  appearance: none;
  width: 28px;
  height: 28px;
  border: none;
  background: none;
  padding: 0;
  cursor: pointer;
}
.ptr-confirm__custom-row input[type="color"]::-webkit-color-swatch-wrapper { padding: 0; }
.ptr-confirm__custom-row input[type="color"]::-webkit-color-swatch { border: 1px solid var(--ptr-border); border-radius: 3px; }
.ptr-confirm__custom-hex {
  font-family: ui-monospace, SFMono-Regular, monospace;
  font-size: 13px;
  color: var(--ptr-lunar);
  letter-spacing: 0.04em;
}
.ptr-confirm__submit {
  font-family: var(--ptr-font-display);
  font-weight: 700;
  font-size: 15px;
  color: var(--ptr-white);
  background: var(--ptr-stellar);
  border: none;
  border-radius: 4px;
  padding: 14px 22px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  margin-top: 4px;
  box-shadow: 0 12px 36px -14px rgba(123, 165, 255, 0.55);
  transition: transform .25s var(--ptr-ease);
}
.ptr-confirm__submit:hover { transform: translateY(-2px); }
.ptr-confirm__submit svg { width: 16px; height: 16px; stroke: var(--ptr-white); fill: none; stroke-width: 2.2; }

/* Sector picker — confirm-card retheme. Inherits base styles from
   /lib/components/sector-picker.css and overrides tokens to match
   the surrounding confirm card. */
.ptr-confirm__sector { display: flex; flex-direction: column; gap: 6px; }
.ptr-confirm .sector-picker__input,
.ptr-confirm .sector-picker__free-input {
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid var(--ptr-border);
  font-family: var(--ptr-font-body);
  color: var(--ptr-white);
  border-radius: 0;
}
.ptr-confirm .sector-picker__input:focus,
.ptr-confirm .sector-picker__free-input:focus { border-color: var(--ptr-arc); }
.ptr-confirm .sector-picker__dropdown {
  background: #14141c;
  border-color: var(--ptr-border);
}
.ptr-confirm .sector-picker__option { color: var(--ptr-lunar); }
.ptr-confirm .sector-picker__option:hover,
.ptr-confirm .sector-picker__option[aria-selected="true"] {
  background: rgba(91, 139, 255, 0.16);
  color: var(--ptr-white);
}
.ptr-confirm .sector-picker__option-group { color: var(--ptr-mist); }
.ptr-confirm .sector-picker__escape-btn { color: var(--ptr-dust); }
.ptr-confirm .sector-picker__escape-btn:hover { color: var(--ptr-white); }
.ptr-confirm .sector-picker__free-hint { color: var(--ptr-mist); }

/* ============================================================ */
/* REVEAL — sec 6.                                               */
/* ============================================================ */

.ptr-reveal {
  position: fixed;
  inset: 0;
  z-index: 300;
  display: flex;
  flex-direction: column;
  background: var(--ptr-obsidian);
  opacity: 0;
  transition: opacity .6s var(--ptr-ease);
}
.ptr-reveal[hidden] { display: none; }
.ptr-reveal[data-active] { opacity: 1; }

.ptr-reveal__stage {
  flex: 1;
  position: relative;
  overflow: auto;
  -webkit-overflow-scrolling: touch;
}
.ptr-reveal__layer {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity .55s var(--ptr-ease);
  overflow: auto;
  -webkit-overflow-scrolling: touch;
  /* Inactive layers must not intercept wheel/pointer events. Both
     layers stack at position:absolute;inset:0 with overflow:auto, so
     the inactive layer (later DOM sibling, painted on top) was eating
     wheel events that should have reached the active iframe. Result:
     whichever pair of registers ended up on the underlying layer (A)
     could not scroll past the hero. pointer-events:none on inactive
     + auto on active routes events cleanly to the active iframe. */
  pointer-events: none;
  /* Base stacking level. The active layer bumps to z-index:2 (see
     `.ptr-reveal__layer--active` below) so it always paints on top
     regardless of DOM order. Without this the LATER DOM sibling
     naturally wins hit-testing during the 550ms crossfade —
     combined with commit 5569ad8's deferred pointer-events flip
     (both layers left pointer-events:auto for 550-750ms after a
     switch to protect an in-flight iOS Safari touch capture), a
     switch to the EARLIER DOM sibling meant fresh touchstarts
     landed on the now-empty-iframe of the LATER sibling and iOS's
     -webkit-overflow-scrolling capture stalled the scroll. z-index:2
     on --active makes fresh touches always hit the new layer,
     while an already-captured in-flight gesture keeps its target
     regardless of z-index change (iOS retains capture across paint
     re-orderings until touchend). */
  z-index: 1;
}
.ptr-reveal__layer--active { opacity: 1; pointer-events: auto; z-index: 2; }
.ptr-reveal__iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
  background: transparent;
  display: block;
}
.ptr-reveal__layer-error {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 40px;
  text-align: center;
  color: var(--ptr-lunar);
}
.ptr-reveal__layer-error-h {
  font-family: var(--ptr-display);
  font-weight: 700;
  font-size: 20px;
  color: var(--ptr-white);
  letter-spacing: -0.01em;
}
.ptr-reveal__layer-error-l {
  font-size: 14px;
  color: var(--ptr-lunar);
  max-width: 32ch;
}
.ptr-reveal__layer-skeleton {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding: 60px clamp(24px, 6vw, 80px);
  pointer-events: none;
  opacity: 1;
  transition: opacity .4s var(--ptr-ease);
}
.ptr-reveal__layer-skeleton[data-hidden] { opacity: 0; }

/* ── P3 "crafting your preview" hold panel ──────────────────────────
   Shown over the reveal stage BEFORE any iframe mounts when the
   backend signals X-Library-Generating or X-Library-Cap-Hit. The
   built-sector path never reaches this — it mounts the iframe
   directly, no panel, no regression. Same panel surface for both
   generating + cap-hit cases; only the copy changes. */
.ptr-reveal__crafting-hold {
  position: absolute;
  inset: 0;
  z-index: 5;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 32px;
  background: radial-gradient(
    ellipse at center,
    rgba(20, 20, 28, 0.92) 0%,
    rgba(9, 9, 12, 0.98) 80%
  );
  backdrop-filter: blur(8px);
}
.ptr-reveal__crafting-hold__inner {
  max-width: 480px;
  width: 100%;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 18px;
}
.ptr-reveal__crafting-hold__mark {
  width: 56px;
  height: 56px;
  border-radius: 50%;
  border: 1.5px solid var(--ptr-arc);
  border-top-color: transparent;
  animation: ptr-crafting-spin 1.4s linear infinite;
}
@keyframes ptr-crafting-spin {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}
@media (prefers-reduced-motion: reduce) {
  .ptr-reveal__crafting-hold__mark { animation: none; }
}
.ptr-reveal__crafting-hold__title {
  font-family: var(--ptr-display);
  font-weight: 700;
  font-size: clamp(22px, 3vw, 28px);
  color: var(--ptr-white);
  letter-spacing: -0.015em;
  line-height: 1.2;
  margin: 0;
}
.ptr-reveal__crafting-hold__sub {
  font-size: 15px;
  color: var(--ptr-lunar);
  line-height: 1.5;
  max-width: 42ch;
  margin: 0;
}
.ptr-reveal__crafting-hold__cta {
  margin-top: 8px;
  padding: 12px 22px;
  font-family: var(--ptr-body);
  font-weight: 500;
  font-size: 14.5px;
  color: var(--ptr-white);
  background: transparent;
  border: 1px solid rgba(255, 255, 255, 0.30);
  border-radius: 4px;
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s;
}
.ptr-reveal__crafting-hold__cta:hover,
.ptr-reveal__crafting-hold__cta:focus {
  border-color: var(--ptr-arc);
  background: rgba(91, 139, 255, 0.08);
}
/* In-hold email capture (part 4 degrade ladder) — appears on cap-hit /
   unresolved immediately and at the 120s phase of a live mint. Same
   J1 pipeline as the Layer B capture field. Buttons 4px, inputs sharp
   (house corner rules). */
.ptr-reveal__crafting-hold__capture {
  display: flex;
  gap: 8px;
  width: 100%;
  max-width: 380px;
  margin-top: 4px;
}
.ptr-reveal__crafting-hold__capture input {
  flex: 1 1 auto;
  min-width: 0;
  padding: 12px 14px;
  font-family: var(--ptr-body);
  font-size: 14.5px;
  color: var(--ptr-white);
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.22);
  border-radius: 0;
}
.ptr-reveal__crafting-hold__capture input:focus {
  outline: none;
  border-color: var(--ptr-arc);
}
.ptr-reveal__crafting-hold__capture input[aria-invalid="true"] {
  border-color: #e5484d;
}
.ptr-reveal__crafting-hold__capture button {
  flex: 0 0 auto;
  padding: 12px 18px;
  font-family: var(--ptr-body);
  font-weight: 600;
  font-size: 14px;
  color: #0b0b10;
  background: var(--ptr-white);
  border: 1px solid var(--ptr-white);
  border-radius: 4px;
  cursor: pointer;
  transition: opacity 0.15s;
}
.ptr-reveal__crafting-hold__capture button:hover,
.ptr-reveal__crafting-hold__capture button:focus {
  opacity: 0.88;
}
.ptr-reveal__crafting-hold__capture button:disabled {
  opacity: 0.6;
  cursor: default;
}
.ptr-reveal__crafting-hold__sent {
  font-size: 15px;
  color: var(--ptr-white);
  line-height: 1.5;
  margin: 0;
}
@media (max-width: 480px) {
  .ptr-reveal__crafting-hold__capture { flex-direction: column; }
}

/* Phase-driven mark tone — at cap-hit / timeout the spinner is
   inappropriate (nothing's still happening). Hide it via the
   data-msr-phase attribute on the panel's children. */
.ptr-reveal__crafting-hold__title[data-msr-phase="timeout"] ~ * ~ .ptr-reveal__crafting-hold__mark,
.ptr-reveal__crafting-hold__inner:has([data-msr-phase="timeout"]) .ptr-reveal__crafting-hold__mark {
  animation: none;
  border-top-color: var(--ptr-arc);
  opacity: 0.3;
}

/* Per-layer loading skeleton shown while a lazy /api/reveal/:register
   fetch is in flight (chromed-reveal pivot — commit 3). Distinct from
   the initial #ptr-reveal-skeleton which lives outside the layers. */
.ptr-reveal__layer-loading {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 14px;
  padding: 40px;
  background: var(--ptr-obsidian);
}
.ptr-reveal__layer-loading-bar {
  width: 140px;
  height: 2px;
  background: rgba(255, 255, 255, 0.06);
  position: relative;
  overflow: hidden;
  border-radius: 2px;
}
.ptr-reveal__layer-loading-bar::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, transparent 0%, var(--ptr-arc) 50%, transparent 100%);
  animation: ptr-loading-shimmer 1.4s linear infinite;
}
.ptr-reveal__layer-loading-label {
  font-family: var(--ptr-font-body);
  font-size: 12px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ptr-dust);
}
@keyframes ptr-loading-shimmer {
  0% { transform: translateX(-100%); }
  100% { transform: translateX(100%); }
}
.ptr-reveal__skel-row {
  background: rgba(255, 255, 255, 0.04);
  border-radius: 4px;
  animation: ptr-skel 1.6s ease-in-out infinite;
}
.ptr-reveal__skel-row.r1 { height: 12vh; }
.ptr-reveal__skel-row.r2 { height: 30vh; }
.ptr-reveal__skel-row.r3 { height: 18vh; }
@keyframes ptr-skel { 0%, 100% { opacity: 0.5; } 50% { opacity: 0.8; } }

/* ============================================================ */
/* LAYER B — parent-page bottom bar (chromed-reveal pivot).      */
/*                                                              */
/* Floating capsule centred at the bottom of the viewport.       */
/* Lives outside the iframe so it never overlaps Layer A's       */
/* in-iframe nav. Sits above the iframe stage (z-index: 10),     */
/* below the close-takeover button.                              */
/* ============================================================ */

.ptr-layerb {
  position: fixed;
  left: 50%;
  bottom: clamp(12px, 2vw, 22px);
  transform: translateX(-50%) translateY(10px);
  z-index: 350;
  opacity: 0;
  pointer-events: none;
  transition: opacity .35s var(--ptr-ease), transform .45s var(--ptr-ease);
  max-width: calc(100vw - 24px);
}

.ptr-layerb[hidden] { display: none; }
.ptr-layerb[data-active] {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
  pointer-events: auto;
}

.ptr-layerb__inner {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 10px 14px 10px 18px;
  background: rgba(9, 9, 12, 0.92);
  backdrop-filter: blur(18px) saturate(140%);
  -webkit-backdrop-filter: blur(18px) saturate(140%);
  border: 1px solid var(--ptr-border);
  border-radius: 999px;
  box-shadow: 0 16px 50px -20px rgba(0, 0, 0, 0.7), 0 4px 14px -4px rgba(0, 0, 0, 0.4);
}

/* Groups inside the capsule */
.ptr-layerb__group {
  display: flex;
  align-items: center;
  gap: 6px;
}
.ptr-layerb__group--chips { gap: 4px; }
.ptr-layerb__group--colour { gap: 6px; }
.ptr-layerb__group-label {
  font-family: var(--ptr-font-body);
  font-size: 10.5px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ptr-mist);
  font-weight: 600;
  margin-right: 4px;
}

.ptr-layerb__divider {
  width: 1px;
  height: 22px;
  background: rgba(255, 255, 255, 0.10);
}

/* First-visit auto-refresh status pill ("Tailoring fresh imagery to
   your trade."). Quiet, premium, framed as bespoke craft. Hidden by
   default; reveal.js flips data-active to fade in/out so the pill
   never blocks interaction with the chips, colour picker or Build CTA.
   The divider variant collapses with the pill so the toolbar geometry
   stays clean when the signal isn't shown. */
.ptr-layerb__group--status {
  gap: 7px;
  padding: 0 4px;
  opacity: 0;
  transform: translateY(2px);
  transition: opacity .35s var(--ptr-ease), transform .35s var(--ptr-ease);
  pointer-events: none; /* never intercept clicks on neighbours */
}
.ptr-layerb__group--status[data-active] {
  opacity: 1;
  transform: translateY(0);
}
.ptr-layerb__divider--status { display: none; }
.ptr-layerb__group--status[data-active] ~ .ptr-layerb__divider--status { display: block; }
.ptr-layerb__group--status[hidden] { display: none; }

.ptr-layerb__status-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  color: var(--ptr-arc);
  animation: ptr-layerb-status-spin 3.6s linear infinite;
}
@keyframes ptr-layerb-status-spin {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}
@media (prefers-reduced-motion: reduce) {
  .ptr-layerb__status-icon { animation: none; }
}
.ptr-layerb__status-text {
  font-family: var(--ptr-font-body);
  font-size: 11.5px;
  letter-spacing: 0.02em;
  color: var(--ptr-dust);
  white-space: nowrap;
}

/* Register chips */
.ptr-layerb__chip {
  font-family: var(--ptr-font-body);
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--ptr-dust);
  background: transparent;
  border: 1px solid transparent;
  padding: 7px 13px;
  border-radius: 999px;
  cursor: pointer;
  transition: color .2s, background .2s, border-color .2s;
  white-space: nowrap;
}
.ptr-layerb__chip:hover { color: var(--ptr-white); background: rgba(255, 255, 255, 0.06); }
.ptr-layerb__chip:focus-visible { outline: 2px solid var(--ptr-arc); outline-offset: 2px; }
.ptr-layerb__chip[data-active] {
  color: var(--ptr-obsidian);
  background: var(--ptr-white);
  border-color: var(--ptr-white);
}

/* Font pairing chips — same pill language as the register chips, plus a
   display-font "Ag" sample so each chip previews its pairing. The group
   is hidden until reveal.js loads the typography registry. */
.ptr-layerb__fontchips {
  display: flex;
  align-items: center;
  gap: 4px;
}
.ptr-layerb__fontchip {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-family: var(--ptr-font-body);
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--ptr-dust);
  background: transparent;
  border: 1px solid transparent;
  padding: 5px 12px;
  border-radius: 999px;
  cursor: pointer;
  transition: color .2s, background .2s, border-color .2s;
  white-space: nowrap;
}
.ptr-layerb__fontchip:hover { color: var(--ptr-white); background: rgba(255, 255, 255, 0.06); }
.ptr-layerb__fontchip:focus-visible { outline: 2px solid var(--ptr-arc); outline-offset: 2px; }
.ptr-layerb__fontchip[data-active] {
  color: var(--ptr-obsidian);
  background: var(--ptr-white);
  border-color: var(--ptr-white);
}
.ptr-layerb__fontchip-sample {
  font-size: 15px;
  font-weight: 700;
  line-height: 1;
}
.ptr-layerb__fontchip-label { line-height: 1; }
@media (max-width: 720px) {
  /* Inside the collapsible the bar stacks; let the chips wrap rather
     than overflow, matching the register-chip row's mobile behaviour. */
  .ptr-layerb__fontchips { flex-wrap: wrap; }
}
/* Width budget (2 Jul live report): the full-label chips widen the bar
   past its pre-fonts envelope and clip the Build CTA on non-fullscreen
   laptop windows. Compact tier keeps the Ag samples (with a title
   tooltip) and drops the text labels; below the old bar's own fit
   point the group hides entirely so the fonts feature can never cost
   the conversion button. */
@media (min-width: 721px) and (max-width: 1320px) {
  .ptr-layerb__fontchip-label { display: none; }
  .ptr-layerb__fontchip { padding: 5px 10px; }
  .ptr-layerb__fontchip-sample { font-size: 17px; }
}
@media (min-width: 721px) and (max-width: 1120px) {
  .ptr-layerb__group--fonts,
  #ptr-layerb-fonts-divider { display: none !important; }
}

/* Colour swatches */
.ptr-layerb__swatch {
  width: 22px;
  height: 22px;
  padding: 0;
  border: 1.5px solid rgba(255, 255, 255, 0.18);
  background: var(--ptr-swatch, var(--ptr-arc));
  border-radius: 999px;
  cursor: pointer;
  position: relative;
  transition: transform .15s var(--ptr-ease), border-color .15s;
}
.ptr-layerb__swatch:hover {
  transform: scale(1.12);
  border-color: rgba(255, 255, 255, 0.42);
}
.ptr-layerb__swatch:focus-visible { outline: 2px solid var(--ptr-arc); outline-offset: 2px; }
.ptr-layerb__swatch[data-active] {
  border-color: var(--ptr-white);
  box-shadow: 0 0 0 2px var(--ptr-obsidian), 0 0 0 3.5px var(--ptr-white);
}
.ptr-layerb__swatch--custom {
  background: conic-gradient(from 0deg, #ff0080, #ff8000, #ffff00, #00ff80, #0080ff, #8000ff, #ff0080);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 13px;
  font-weight: 700;
  color: rgba(255, 255, 255, 0.9);
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.4);
}
.ptr-layerb__swatch--custom input[type="color"] {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  cursor: pointer;
  border: 0;
  padding: 0;
}

/* Mobile-only relocated chrome. Desktop hides both — the iframe nav
   keeps the original "add your logo" + edit pencil cluster via
   lib/reveal-chrome.ts injection. At @media (max-width: 720px) the
   iframe copy is hidden by the same injection's media query and this
   Layer B copy takes over (rules in the mobile block below). */
.ptr-layerb__group--reassure,
.ptr-layerb__divider--reassure { display: none; }

/* Mobile-only collapsed colour control trigger. Hidden on desktop —
   the existing inline swatch row stays as-is at desktop widths. The
   mobile rule at @media (max-width: 720px) flips this visibility and
   collapses the swatch grid to a small drop-up panel. */
.ptr-layerb__colour-toggle { display: none; }
.ptr-layerb__swatches {
  display: flex;
  align-items: center;
  gap: 6px;
}

/* Build CTA */

.ptr-layerb__build {
  font-family: var(--ptr-font-display);
  font-weight: 700;
  font-size: 13.5px;
  letter-spacing: 0.01em;
  color: var(--ptr-white);
  background: var(--ptr-stellar);
  border: none;
  border-radius: 999px;
  padding: 10px 18px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  box-shadow: 0 8px 24px -10px rgba(123, 165, 255, 0.55);
  transition: transform .2s var(--ptr-ease), box-shadow .2s;
  white-space: nowrap;
}
.ptr-layerb__build:hover {
  transform: translateY(-1.5px);
  box-shadow: 0 12px 30px -10px rgba(123, 165, 255, 0.7);
}
.ptr-layerb__build:focus-visible { outline: 2px solid var(--ptr-white); outline-offset: 2px; }
.ptr-layerb__build svg {
  width: 14px;
  height: 14px;
  stroke: var(--ptr-white);
  fill: none;
  stroke-width: 2.2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Mobile — redesigned as a three-row vertical stack inside a rounded
   card. The horizontal capsule is cramped at narrow widths; on mobile
   we stack:
     1. Register chips — 4-column equal grid (tappable, 42px tall)
     2. Colour swatches — single centred row, 7 swatches at 30px each
     3. Build CTA — full-width, prominent
   Every tap target is ≥40px in its smallest dimension for Wix-grade
   touch ergonomics. The capsule's pill shape becomes a 18px-radius
   card so the rows breathe properly. */
@media (max-width: 720px) {
  .ptr-layerb {
    left: 8px;
    right: 8px;
    bottom: 10px;
    transform: translateY(10px);
    max-width: none;
    width: auto;
  }
  .ptr-layerb[data-active] {
    transform: translateY(0);
  }
  .ptr-layerb__inner {
    display: grid;
    grid-template-columns: 1fr;
    align-items: stretch;
    justify-content: stretch;
    gap: 10px;
    padding: 12px;
    border-radius: 18px;
    max-width: 460px;
    margin: 0 auto;
  }
  .ptr-layerb__divider { display: none; }

  /* Relocated reassurance chrome — shown on mobile, hidden on desktop
     by the default rule above. Centred row with the shimmer "add your
     logo" prompt + the pulsing pencil sitting alongside it. Popovers
     drop UP above the bar so they don't clip below the viewport. */
  .ptr-layerb__group--reassure {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 4px;
    width: 100%;
    position: relative;
    padding: 2px 0;
  }
  .ptr-layerb__addlogo,
  .ptr-layerb__pencil {
    appearance: none;
    -webkit-appearance: none;
    background: transparent;
    border: 0;
    border-radius: 4px;
    cursor: pointer;
    transition: background-color 0.2s ease, color 0.2s ease;
  }
  .ptr-layerb__addlogo {
    padding: 8px 12px;
    font-family: var(--ptr-font-display);
    font-weight: 600;
    font-size: 11px;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.55);
    background-image: linear-gradient(
      100deg,
      rgba(255, 255, 255, 0.45) 0%,
      rgba(255, 255, 255, 0.45) 40%,
      var(--ptr-arc) 50%,
      rgba(255, 255, 255, 0.45) 60%,
      rgba(255, 255, 255, 0.45) 100%
    );
    background-size: 280% 100%;
    background-position: 100% 0%;
    background-clip: text;
    -webkit-background-clip: text;
    color: transparent;
    -webkit-text-fill-color: transparent;
    animation: ptr-layerb-addlogo-shimmer 3.4s ease-in-out infinite;
  }
  .ptr-layerb__pencil {
    padding: 6px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: rgba(255, 255, 255, 0.55);
    animation: ptr-layerb-pencil-pulse 3.4s ease-in-out infinite;
    animation-delay: 0.6s;
  }
  .ptr-layerb__pencil svg {
    width: 16px;
    height: 16px;
    display: block;
    transition: transform 0.2s ease;
  }
  .ptr-layerb__pencil:hover svg,
  .ptr-layerb__pencil:focus-visible svg {
    transform: rotate(-8deg) scale(1.05);
  }
  .ptr-layerb__addlogo:hover,
  .ptr-layerb__addlogo:focus-visible,
  .ptr-layerb__pencil:hover,
  .ptr-layerb__pencil:focus-visible {
    background-color: rgba(255, 255, 255, 0.08);
  }
  .ptr-layerb__pencil:hover,
  .ptr-layerb__pencil:focus-visible {
    color: var(--ptr-white);
  }
  .ptr-layerb__addlogo:focus-visible,
  .ptr-layerb__pencil:focus-visible {
    outline: 2px solid var(--ptr-arc);
    outline-offset: 2px;
  }
  @keyframes ptr-layerb-addlogo-shimmer {
    0%   { background-position: 100% 0%; }
    100% { background-position: -180% 0%; }
  }
  @keyframes ptr-layerb-pencil-pulse {
    0%, 100% { color: rgba(255, 255, 255, 0.55); }
    50%      { color: var(--ptr-arc); }
  }
  @media (prefers-reduced-motion: reduce) {
    .ptr-layerb__addlogo,
    .ptr-layerb__pencil {
      animation: none;
      background-position: 50% 0%;
    }
  }
  /* Popover — drop up above the bar. */
  .ptr-layerb__popover {
    position: absolute;
    bottom: calc(100% + 10px);
    left: 50%;
    transform: translateX(-50%);
    z-index: 12;
    width: max-content;
    max-width: min(280px, calc(100vw - 32px));
    padding: 14px 16px;
    border-radius: 10px;
    background: rgba(15, 15, 20, 0.95);
    color: var(--ptr-white);
    border: 1px solid var(--ptr-border);
    box-shadow: 0 12px 32px -8px rgba(0, 0, 0, 0.5);
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
    font: 400 13px/1.5 var(--ptr-font-display);
    letter-spacing: 0;
    text-transform: none;
  }

  /* First-visit status pill — full-width row, compact copy, centred. */
  .ptr-layerb__group--status {
    width: 100%;
    justify-content: center;
    padding: 4px 0 0;
  }
  .ptr-layerb__status-text {
    font-size: 11px;
  }

  /* Register chips — equal-width grid, 4 across, generous touch targets. */
  .ptr-layerb__group--chips {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 6px;
    width: 100%;
  }
  .ptr-layerb__chip {
    min-height: 42px;
    padding: 10px 6px;
    font-size: 12.5px;
    text-align: center;
    justify-content: center;
    line-height: 1.1;
    width: 100%;
  }

  /* Colour control on mobile collapses to a single pill trigger that
     mirrors the active colour. Tapping it drops a small panel above
     the bar with the same swatch grid. Frees the row of horizontal
     real estate the inline row used to consume. */
  .ptr-layerb__group--colour {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0;
    width: 100%;
    padding: 0;
    position: relative;
  }
  .ptr-layerb__group-label { display: none; }
  /* Trigger pill — shows the active colour + a chevron. */
  .ptr-layerb__colour-toggle {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 9px 14px;
    min-height: 42px;
    border: 1px solid rgba(255, 255, 255, 0.18);
    border-radius: 999px;
    background: transparent;
    color: var(--ptr-white);
    font-family: var(--ptr-font-display);
    font-size: 13px;
    font-weight: 500;
    letter-spacing: 0.04em;
    cursor: pointer;
    transition: border-color .15s, background .15s;
  }
  .ptr-layerb__colour-toggle:hover {
    border-color: rgba(255, 255, 255, 0.36);
    background: rgba(255, 255, 255, 0.04);
  }
  .ptr-layerb__colour-toggle:focus-visible {
    outline: 2px solid var(--ptr-arc);
    outline-offset: 2px;
  }
  .ptr-layerb__colour-toggle-dot {
    width: 18px;
    height: 18px;
    border-radius: 999px;
    background: var(--ptr-swatch, var(--ptr-arc));
    border: 1.5px solid rgba(255, 255, 255, 0.36);
    display: inline-block;
  }
  .ptr-layerb__colour-toggle-chev {
    width: 14px;
    height: 14px;
    transition: transform .2s var(--ptr-ease);
  }
  .ptr-layerb__colour-toggle[aria-expanded="true"] .ptr-layerb__colour-toggle-chev {
    transform: rotate(180deg);
  }
  /* Swatch panel — collapsed by default; drops up over the bar when
     the trigger is expanded. Positioned absolutely so it doesn't
     reflow the Build CTA below. */
  .ptr-layerb__swatches {
    display: none;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 12px;
    position: absolute;
    bottom: calc(100% + 10px);
    left: 50%;
    transform: translateX(-50%);
    padding: 14px 16px;
    background: rgba(15, 15, 20, 0.95);
    border: 1px solid var(--ptr-border);
    border-radius: 14px;
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
    box-shadow: 0 12px 32px -8px rgba(0, 0, 0, 0.5);
    min-width: 220px;
    z-index: 10;
  }
  .ptr-layerb__colour-toggle[aria-expanded="true"] + .ptr-layerb__swatches {
    display: flex;
  }
  .ptr-layerb__swatch {
    width: 30px;
    height: 30px;
    border-width: 1.5px;
  }
  .ptr-layerb__swatch--custom {
    font-size: 16px;
  }
  .ptr-layerb__swatch[data-active] {
    box-shadow: 0 0 0 2px rgba(15, 15, 20, 0.95), 0 0 0 4px var(--ptr-white);
  }

  /* Build CTA — full width, prominent, ≥46px tall. */
  .ptr-layerb__build {
    width: 100%;
    min-height: 46px;
    justify-content: center;
    padding: 13px 18px;
    font-size: 14.5px;
    margin: 0;
  }

  /* ── Mobile-only Layer B collapse ────────────────────────────────
     By default only two controls show: the "See it in a different
     style" toggle and the Build CTA below it. Everything else — the
     register chips, the add-logo + edit-pencil reassure row, the
     status pill, the colour picker — collapses behind the toggle.
     Tapping the toggle expands the group upward (the panel is
     bottom-anchored, so growing height pushes the top up).

     Smooth max-height + opacity transition. The exact max-height on
     open is generous (60vh) so the whole group fits without clipping
     on tall phones; the inner content naturally caps at its own
     size, so the number is just a ceiling for the animation.

     Desktop (@media min-width:721px) treats .ptr-layerb__collapsible
     as a transparent wrapper (children flow as-is) and hides
     .ptr-layerb__mobile-toggle entirely — desktop Layer B is
     unchanged. */

  .ptr-layerb__collapsible {
    display: grid;
    grid-template-columns: 1fr;
    gap: 10px;
    max-height: 0;
    opacity: 0;
    overflow: hidden;
    pointer-events: none;
    transition:
      max-height 320ms cubic-bezier(0.4, 0, 0.2, 1),
      opacity   200ms cubic-bezier(0.4, 0, 0.2, 1),
      margin-bottom 320ms cubic-bezier(0.4, 0, 0.2, 1);
    margin-bottom: 0;
  }
  .ptr-layerb__collapsible.is-open {
    max-height: 60vh;
    opacity: 1;
    pointer-events: auto;
    margin-bottom: 2px;
  }

  .ptr-layerb__mobile-toggle {
    appearance: none;
    -webkit-appearance: none;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    width: 100%;
    min-height: 40px;
    padding: 10px 16px;
    border: 1px solid rgba(255, 255, 255, 0.14);
    border-radius: 999px;
    background: transparent;
    color: rgba(255, 255, 255, 0.9);
    font-family: var(--ptr-font-display);
    font-size: 13px;
    font-weight: 500;
    letter-spacing: 0.02em;
    cursor: pointer;
    position: relative;
    overflow: hidden;
    transition: border-color 0.18s ease, background 0.18s ease;
  }
  .ptr-layerb__mobile-toggle:hover {
    border-color: rgba(255, 255, 255, 0.28);
    background: rgba(255, 255, 255, 0.04);
  }
  .ptr-layerb__mobile-toggle:focus-visible {
    outline: 2px solid var(--ptr-arc);
    outline-offset: 2px;
  }

  /* Sheen: a soft diagonal highlight that slowly sweeps across the
     label. Uses background-clip: text on a linear-gradient the same
     way the "add your logo" prompt does, but slower (~5s) and lower-
     contrast so it reads as an ambient hint rather than a pulse. */
  .ptr-layerb__mobile-toggle-label {
    background-image: linear-gradient(
      100deg,
      rgba(255, 255, 255, 0.85) 0%,
      rgba(255, 255, 255, 0.85) 40%,
      #ffffff 50%,
      rgba(255, 255, 255, 0.85) 60%,
      rgba(255, 255, 255, 0.85) 100%
    );
    background-size: 260% 100%;
    background-position: 100% 0%;
    background-clip: text;
    -webkit-background-clip: text;
    color: transparent;
    -webkit-text-fill-color: transparent;
    animation: ptr-layerb-mobile-toggle-sheen 5s ease-in-out infinite;
  }
  @keyframes ptr-layerb-mobile-toggle-sheen {
    0%   { background-position: 100% 0%; }
    100% { background-position: -160% 0%; }
  }

  .ptr-layerb__mobile-toggle-chev {
    width: 14px;
    height: 14px;
    color: rgba(255, 255, 255, 0.55);
    transition: transform 0.22s cubic-bezier(0.4, 0, 0.2, 1);
  }
  .ptr-layerb__mobile-toggle[aria-expanded="true"] .ptr-layerb__mobile-toggle-chev {
    transform: rotate(180deg);
  }

  @media (prefers-reduced-motion: reduce) {
    .ptr-layerb__collapsible {
      transition: none;
    }
    .ptr-layerb__mobile-toggle-label {
      animation: none;
      background-position: 50% 0%;
    }
    .ptr-layerb__mobile-toggle-chev {
      transition: none;
    }
  }
}

/* Desktop: the collapsible wrapper is transparent (children flow as
   if it weren't there) and the mobile toggle button is hidden. Layer
   B on desktop stays byte-for-byte the layout it was pre-change. */
@media (min-width: 721px) {
  .ptr-layerb__collapsible {
    display: contents;
  }
  .ptr-layerb__mobile-toggle {
    display: none;
  }
}

/* Very narrow phones (≤360px): keep everything tappable, dial down
   visual padding only — never shrink touch targets below WCAG minima. */
@media (max-width: 360px) {
  .ptr-layerb__inner { padding: 10px; gap: 9px; }
  .ptr-layerb__chip { font-size: 12px; padding: 9px 4px; min-height: 40px; }
  .ptr-layerb__group--colour { gap: 8px; }
  .ptr-layerb__swatch { width: 28px; height: 28px; }
  .ptr-layerb__build { font-size: 14px; min-height: 44px; }
}

/* When Layer B is active, pad the iframe stage's bottom so the iframe
   content can scroll past the capsule. We can't pad the iframe's
   internal body, but giving the stage container a bottom padding
   means the iframe (position:absolute;inset:0) shrinks accordingly. */
.ptr-reveal[data-active] .ptr-reveal__stage {
  padding-bottom: 78px;
}
@media (max-width: 720px) {
  .ptr-reveal[data-active] .ptr-reveal__stage {
    padding-bottom: 140px;
  }
}

/* ============================================================ */
/* GATE — sec 7.                                                 */
/* ============================================================ */

.ptr-gate {
  position: fixed;
  inset: 0;
  z-index: 500;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  opacity: 0;
  transition: opacity .35s var(--ptr-ease);
}
/* Without this, the explicit `display: flex` above defeats the UA
   `[hidden] { display: none }` and the gate stays full-screen at z-index 500
   capturing every click in the hero — the paste input then appears unclickable. */
.ptr-gate[hidden] { display: none; }
.ptr-gate[data-active] { opacity: 1; }
.ptr-gate__backdrop {
  position: absolute;
  inset: 0;
  background: rgba(9, 9, 12, 0.78);
  backdrop-filter: blur(12px);
}
.ptr-gate__card {
  position: relative;
  width: 100%;
  max-width: 520px;
  max-height: calc(100svh - 48px);
  overflow-y: auto;
  background: var(--ptr-void);
  border: 1px solid var(--ptr-border);
  padding: 32px 28px 24px;
  display: flex;
  flex-direction: column;
  gap: 14px;
  border-radius: 6px;
}
.ptr-gate__close {
  position: absolute;
  top: 12px;
  right: 12px;
  background: none;
  border: none;
  font-size: 24px;
  color: var(--ptr-mist);
  cursor: pointer;
  line-height: 1;
  padding: 6px 10px;
  border-radius: 4px;
}
.ptr-gate__close:hover { color: var(--ptr-white); background: rgba(255, 255, 255, 0.04); }
.ptr-gate__title {
  font-family: var(--ptr-font-display);
  font-weight: 800;
  font-size: 26px;
  color: var(--ptr-white);
  letter-spacing: -0.022em;
}
.ptr-gate__body {
  font-size: 15px;
  color: var(--ptr-dust);
  line-height: 1.5;
}
.ptr-gate input {
  display: block;
  width: 100%;
  box-sizing: border-box;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid var(--ptr-border);
  outline: none;
  padding: 13px 14px;
  font-family: var(--ptr-font-body);
  font-size: 15px;
  color: var(--ptr-white);
  border-radius: 4px;
  margin-top: 8px;
  transition: border-color .2s;
}
.ptr-gate input:focus { border-color: var(--ptr-arc); }
.ptr-gate__error { color: var(--ptr-red); font-size: 13.5px; margin-top: 4px; }
.ptr-gate__submit {
  display: block;
  width: 100%;
  font-family: var(--ptr-font-display);
  font-weight: 700;
  font-size: 15px;
  color: var(--ptr-white);
  background: var(--ptr-stellar);
  border: none;
  border-radius: 4px;
  padding: 13px 20px;
  cursor: pointer;
  margin-top: 8px;
  box-shadow: 0 12px 36px -14px rgba(123, 165, 255, 0.55);
  transition: transform .2s var(--ptr-ease);
}
.ptr-gate__submit:hover { transform: translateY(-1.5px); }
.ptr-gate__submit[disabled] { opacity: 0.6; cursor: progress; }
.ptr-gate__price {
  font-size: 12px;
  color: var(--ptr-mist);
  text-align: center;
  letter-spacing: 0.02em;
  margin-top: 4px;
}

/* ── Reassurance moment — leads the gate. Calm, scannable, tight
     rhythm. This is what a cold prospect reads on their phone at the
     moment of deciding to switch website providers, so both the copy
     AND the visual pace are load-bearing: no dense paragraph, no
     shouting, no marketing chrome. Bullets get equal weight, each
     one lifts one specific fear. The final line is the single price
     reassurance, framed by a soft accent rule, replacing the old
     £45/£480 fine-print. */
.ptr-gate__reassure {
  margin-bottom: 22px;
}
.ptr-gate__reassure-heading {
  font-family: var(--ptr-font-display);
  font-weight: 700;
  font-size: clamp(22px, 2.8vw, 30px);
  line-height: 1.2;
  padding-bottom: 0.05em;
  letter-spacing: -0.015em;
  color: var(--ptr-white);
  margin: 0 0 16px;
}
.ptr-gate__reassure-list {
  list-style: none;
  padding: 0;
  margin: 0 0 18px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.ptr-gate__reassure-list li {
  font-family: var(--ptr-font-body);
  font-size: 14.5px;
  line-height: 1.5;
  color: var(--ptr-lunar);
  position: relative;
  padding-left: 20px;
}
/* Restrained accent tick, sized to sit on the first line's baseline. */
.ptr-gate__reassure-list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.62em;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--ptr-arc);
  opacity: 0.85;
}
/* Bold price headline. Sits directly above the framed reassurance
   line, gives the panel a clear single price statement without
   reviving the old £45/£480 fine-print. Sized between the reassure
   heading and the bullets so it reads as a definitive line, not
   another list item. */
.ptr-gate__reassure-headline {
  font-family: var(--ptr-font-display);
  font-weight: 700;
  font-size: 18px;
  line-height: 1.25;
  letter-spacing: -0.005em;
  color: var(--ptr-white);
  margin: 0 0 8px;
}
.ptr-gate__reassure-price {
  font-family: var(--ptr-font-display);
  font-weight: 600;
  font-size: 14px;
  letter-spacing: 0.01em;
  color: var(--ptr-arc-light);
  margin: 0;
  padding: 11px 14px;
  background: rgba(123, 165, 255, 0.06);
  border-left: 2px solid var(--ptr-arc);
  border-radius: 0 4px 4px 0;
}

/* ── Sitemap picker v2 — the structure builder (docs/PAGE_PICKER_SPEC.md).
 * Grown from the wizard's Sitemap Moment tree; the old sync-verbatim
 * contract with step-7.css is superseded (step-7 no longer exists on
 * main). Base row/toggle/input rules retain the wizard values; the
 * v2 affordances (row actions, confirm, drag, errors) extend them. */
.ptr-gate__sitemap {
  /* Wizard CSS variable bridge — keeps the rules below identical to
     lib/wizard-v2/styles/step-7.css so they lift without edits. */
  --wz-font-display: var(--ptr-font-display);
  --wz-font-body: var(--ptr-font-body);
  --wz-white: var(--ptr-white);
  --wz-type-body: 16px;
  --wz-type-caption: 13px;
  --wz-accent: var(--ptr-arc);
  margin-bottom: 22px;
  padding-top: 4px;
}

/* ============ SITEMAP MOMENT (verbatim from wizard step-7.css) ============ */

.wz7__sitemap {
  margin-top: 8px;
}

.wz7__sitemap-heading {
  font-family: var(--wz-font-display);
  font-size: clamp(1.25rem, 3vw, 1.5rem);
  font-weight: 700;
  color: var(--wz-white);
  margin: 0 0 6px;
  letter-spacing: -0.01em;
}

.wz7__sitemap-subhead {
  font-size: var(--wz-type-caption);
  color: rgba(255, 255, 255, 0.4);
  margin: 0 0 20px;
  line-height: 1.5;
}

.wz7__sitemap-banner {
  font-size: var(--wz-type-caption);
  color: rgba(255, 255, 255, 0.5);
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(255, 255, 255, 0.06);
  padding: 10px 14px;
  margin: 0 0 16px;
  font-style: italic;
}

/* -- Tree -- */
.wz7__tree {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.wz7__tree-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 14px;
  background: rgba(255, 255, 255, 0.02);
  border: 1px solid rgba(255, 255, 255, 0.05);
  transition: opacity 200ms, background 200ms;
}

.wz7__tree-row--depth-1 {
  padding-left: 40px;
  background: rgba(255, 255, 255, 0.01);
  border-color: rgba(255, 255, 255, 0.03);
}

.wz7__tree-row--disabled {
  opacity: 0.4;
}

.wz7__tree-row--locked {
  opacity: 0.7;
}

.wz7__tree-row--add {
  border-style: dashed;
  border-color: rgba(255, 255, 255, 0.08);
  background: transparent;
}

/* -- Toggle button -- */
.wz7__tree-toggle {
  width: 28px;
  height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  border: 1.5px solid rgba(255, 255, 255, 0.2);
  background: rgba(255, 255, 255, 0.04);
  color: rgba(255, 255, 255, 0.7);
  font-size: 14px;
  cursor: pointer;
  transition: border-color 200ms, background 200ms;
  padding: 0;
}

.wz7__tree-toggle:hover {
  border-color: rgba(255, 255, 255, 0.4);
  background: rgba(255, 255, 255, 0.08);
}

.wz7__tree-toggle--locked {
  cursor: default;
  border-color: rgba(255, 255, 255, 0.15);
}

.wz7__tree-toggle--locked:hover {
  border-color: rgba(255, 255, 255, 0.15);
  background: rgba(255, 255, 255, 0.04);
}

.wz7__tree-check {
  font-size: 12px;
  color: var(--wz-white);
}

.wz7__tree-plus {
  font-size: 16px;
  color: rgba(255, 255, 255, 0.4);
}

/* -- Title -- */
.wz7__tree-title {
  font-size: 15px;
  font-weight: 500;
  color: rgba(255, 255, 255, 0.85);
}

.wz7__tree-row--disabled .wz7__tree-title {
  color: rgba(255, 255, 255, 0.4);
}

/* -- Add button -- */
.wz7__tree-add-btn {
  font-size: var(--wz-type-caption);
  font-weight: 500;
  font-family: var(--wz-font-body);
  color: rgba(255, 255, 255, 0.4);
  background: none;
  border: none;
  cursor: pointer;
  padding: 0;
  transition: color 200ms;
}

.wz7__tree-add-btn:hover {
  color: rgba(255, 255, 255, 0.7);
}

.wz7__tree-add-btn:disabled {
  cursor: default;
  opacity: 0.5;
}

/* -- Inline input for adding service child -- */
.wz7__tree-inline-input {
  flex: 1;
  height: 36px;
  padding: 0 10px;
  font-size: 16px; /* >=16px prevents iOS Safari auto-zoom on focus */
  font-family: var(--wz-font-body);
  color: var(--ptr-white);
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.12);
  outline: none;
  box-sizing: border-box;
}

.wz7__tree-inline-input::placeholder {
  color: rgba(255, 255, 255, 0.35);
}

.wz7__tree-inline-add {
  height: 36px;
  padding: 0 14px;
  font-size: var(--wz-type-caption);
  font-weight: 500;
  font-family: var(--wz-font-body);
  color: var(--wz-white);
  background: rgba(255, 255, 255, 0.1);
  border: 1px solid rgba(255, 255, 255, 0.15);
  cursor: pointer;
  transition: background 200ms;
}

.wz7__tree-inline-add:hover {
  background: rgba(255, 255, 255, 0.15);
}

/* -- Cap note -- */
.wz7__sitemap-cap {
  font-size: var(--wz-type-caption);
  color: rgba(255, 255, 255, 0.4);
  margin: 12px 0 0;
}

/* -- Cap toast (animated inline message) -- */
.wz7__cap-toast {
  font-size: var(--wz-type-caption);
  color: rgba(255, 255, 255, 0.65);
  margin: 12px 0 0;
  padding: 10px 14px;
  background: rgba(255, 255, 255, 0.03);
  border-left: 3px solid var(--wz-accent, rgba(255, 255, 255, 0.25));
  line-height: 1.5;
}

/* -- Custom suggestions -- */
.wz7__sitemap-suggestions {
  margin-top: 16px;
}

.wz7__sitemap-suggest-label {
  font-size: var(--wz-type-caption);
  color: rgba(255, 255, 255, 0.35);
  margin: 0 0 8px;
}

.wz7__sitemap-suggest-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.wz7__sitemap-suggest-chip {
  height: 34px;
  padding: 0 14px;
  font-size: var(--wz-type-caption);
  font-weight: 500;
  font-family: var(--wz-font-body);
  color: rgba(255, 255, 255, 0.45);
  background: transparent;
  border: 1px dashed rgba(255, 255, 255, 0.12);
  cursor: pointer;
  transition: border-color 200ms, color 200ms, background 200ms;
}

.wz7__sitemap-suggest-chip:hover {
  border-color: rgba(255, 255, 255, 0.3);
  color: rgba(255, 255, 255, 0.7);
  background: rgba(255, 255, 255, 0.03);
}

@media (max-width: 520px) {
  /* Tighten the card padding on phones so the reassurance heading
     sits high in the viewport and the list is visible without
     scrolling. */
  .ptr-gate__card { padding: 26px 20px 20px; gap: 12px; }
  .ptr-gate__reassure-heading { font-size: 21px; }
  .ptr-gate__reassure-list li { font-size: 14px; }
  .ptr-gate__reassure-headline { font-size: 16.5px; }
  .ptr-gate__reassure-price { font-size: 13.5px; padding: 10px 12px; }
}

/* ============================================================ */
/* TOAST + SAFETY NET — sec 10                                    */
/* ============================================================ */

.ptr-toast {
  position: fixed;
  bottom: 24px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 600;
  background: var(--ptr-void);
  border: 1px solid var(--ptr-border);
  border-left: 3px solid var(--ptr-arc);
  padding: 14px 18px;
  font-size: 14px;
  color: var(--ptr-lunar);
  border-radius: 4px;
  max-width: 90vw;
  box-shadow: 0 18px 50px -12px rgba(0, 0, 0, 0.6);
  opacity: 0;
  transform: translate(-50%, 10px);
  transition: opacity .3s var(--ptr-ease), transform .3s var(--ptr-ease);
}
.ptr-toast[data-visible] { opacity: 1; transform: translate(-50%, 0); }
.ptr-toast[data-tone="error"] { border-left-color: var(--ptr-red); }

.ptr-safetynet {
  position: fixed;
  bottom: 16px;
  right: 16px;
  z-index: 600;
  max-width: 320px;
  opacity: 0;
  transition: opacity .4s var(--ptr-ease), transform .4s var(--ptr-ease);
  transform: translateY(10px);
}
.ptr-safetynet[data-visible] { opacity: 1; transform: translateY(0); }
.ptr-safetynet__card {
  background: var(--ptr-void);
  border: 1px solid var(--ptr-border);
  padding: 16px 18px;
  border-radius: 4px;
  box-shadow: 0 18px 50px -12px rgba(0, 0, 0, 0.6);
}
.ptr-safetynet__title {
  font-family: var(--ptr-font-display);
  font-weight: 700;
  font-size: 14px;
  color: var(--ptr-white);
  margin-bottom: 4px;
}
.ptr-safetynet__body {
  font-size: 13px;
  color: var(--ptr-dust);
  line-height: 1.5;
}

/* ============================================================ */
/* REDUCED MOTION — sec 4 rule 1.                                */
/* ============================================================ */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
  .ptr-theatre__develop-block { opacity: 1; transform: none; animation: none; }
  /* Reassure shimmer: drop the gradient entirely so text reads as solid mist. */
  .ptr-hero__reassure-shimmer {
    animation: none !important;
    background-image: none !important;
    -webkit-text-fill-color: var(--ptr-mist) !important;
            color: var(--ptr-mist) !important;
  }
}


/* ────────────────────────────────────────────────────────────────────
 * WELCOME MODAL — cinematic on-arrival infographic
 * ────────────────────────────────────────────────────────────────────
 * Ported from origin/landing-public-page landing.html (L885-1550) on
 * 2026-06-28 with tokens renamed --masser-* -> --ptr-*. Welcome is
 * Masser's voice, not the prospect's register accent — accent stays
 * pinned to violet (Phase) regardless of the active register, by
 * locally rebinding the accent var inside the welcome subtree.
 *
 * Sits ABOVE Layer B (z 350) so the iframe + chrome bar are visually
 * dimmed beneath while the four scenes auto-advance over ~5.6s, then
 * the "Let's take a look" CTA holds until dismissed.
 *
 * Audit confirmed easing cubic-bezier(0.16, 1, 0.3, 1) matches PTR's
 * --ptr-ease exactly; intent-ease cubic-bezier(0.22, 1, 0.36, 1) is
 * the source's secondary curve and is preserved verbatim for fidelity.
 * ──────────────────────────────────────────────────────────────────── */

/* Welcome-scoped re-bindings so all internal accent references resolve
   to a fixed Masser accent (Phase violet from the stellar gradient),
   not the prospect's register accent. Welcome runs over the up-front
   register iframe but speaks AS Masser. */
.welcome {
  --ptr-register-accent: var(--ptr-phase);
  --ptr-bar-height: 0px;
}

/* Shimmer-char base — extracted from landing.html L286-298. Scoped to
   the welcome subtree to avoid leaking the letter-shimmer animation
   into other PTR contexts. */
.welcome .shimmer-char {
  display: inline-block;
  color: var(--ptr-lunar);
  animation: ptr-welcome-letter-shimmer 4.8s ease-in-out infinite;
  animation-delay: calc(var(--i, 0) * 0.05s);
  will-change: color;
}
@keyframes ptr-welcome-letter-shimmer {
  0%, 62%, 100% { color: var(--ptr-lunar); }
  31%           { color: var(--ptr-register-accent); }
}

.welcome {
  position: fixed;
  inset: 0;
  z-index: 400;
  display: none; /* hard hide when closed — backdrop-filter still hit-tests in some Chrome paint paths even at opacity:0 */
  align-items: stretch;
  justify-content: stretch;
  background: rgba(9, 9, 12, 0.74);
  backdrop-filter: blur(22px) saturate(108%);
  -webkit-backdrop-filter: blur(22px) saturate(108%);
  opacity: 0;
  pointer-events: none;
  transition: opacity 360ms cubic-bezier(0.22, 1, 0.36, 1);
  isolation: isolate;
}
.welcome.is-open { display: flex; opacity: 1; pointer-events: auto; }

/* While the welcome is up, hide the reveal stage + Layer B + close X so
 * the chromed site can never peek through the welcome's backdrop-filter
 * blur (which is 74% black, not fully opaque). The welcome's own bokeh
 * surface owns the entire screen during scenes 1-4. When the user
 * dismisses the welcome (Let's take a look / X / Esc), the attribute is
 * removed and the reveal fades in over 450ms with --ptr-ease. */
body[data-ptr-welcome-up] #ptr-reveal,
body[data-ptr-welcome-up] #ptr-layerb,
body[data-ptr-welcome-up] .ptr-close-takeover {
  opacity: 0 !important;
  pointer-events: none !important;
  transition: opacity .25s var(--ptr-ease) !important;
}
#ptr-reveal,
#ptr-layerb,
.ptr-close-takeover {
  transition: opacity .45s var(--ptr-ease);
}
.welcome::before {
  content: '';
  position: absolute;
  inset: 0;
  background:
    radial-gradient(120% 90% at 50% 35%, rgba(255,255,255,0.04) 0%, transparent 55%),
    radial-gradient(140% 100% at 50% 110%, rgba(0,0,0,0.55) 0%, transparent 65%);
  pointer-events: none;
  z-index: 0;
}
.welcome::after {
  content: '';
  position: absolute;
  inset: 0;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='240' height='240'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 1   0 0 0 0 1   0 0 0 0 1   0 0 0 0.04 0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
  mix-blend-mode: overlay;
  opacity: 0.28;
  pointer-events: none;
  z-index: 0;
}

.welcome__bokeh {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
}
.welcome__orb {
  position: absolute;
  left: var(--x);
  top: var(--y);
  width: var(--sz);
  height: var(--sz);
  border-radius: 50%;
  background: radial-gradient(circle, rgba(160, 126, 255, 0.08) 0%, transparent 60%);
  filter: blur(48px);
  transform: translate(-50%, -50%);
  opacity: 0;
  transition: opacity 1200ms ease-out;
}
.welcome.is-open .welcome__orb {
  opacity: 0.55;
  animation: welcome-orb-drift var(--dur, 22s) ease-in-out infinite;
  animation-delay: var(--delay, 0s);
}
@keyframes welcome-orb-drift {
  0%   { transform: translate(-50%, -50%) translate(0, 0) scale(1); }
  33%  { transform: translate(-50%, -50%) translate(40px, -30px) scale(1.08); }
  66%  { transform: translate(-50%, -50%) translate(-30px, 40px) scale(0.94); }
  100% { transform: translate(-50%, -50%) translate(0, 0) scale(1); }
}

.welcome__sweep { display: none; }

.welcome__stage {
  position: relative;
  z-index: 1;
  flex: 1 1 auto;
  display: grid;
  grid-template-rows: auto 1fr auto;
  padding: clamp(20px, 4vw, 56px);
  padding-bottom: calc(clamp(20px, 4vw, 56px) + var(--ptr-bar-height));
  min-width: 0;
  min-height: 0;
}

.welcome__top {
  grid-row: 1;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 14px;
  transform: translateY(-6px);
  opacity: 0;
  transition: opacity 480ms cubic-bezier(0.22, 1, 0.36, 1) 200ms,
              transform 480ms cubic-bezier(0.22, 1, 0.36, 1) 200ms;
}
.welcome.is-open .welcome__top {
  opacity: 1;
  transform: translateY(0);
}
.welcome__wordmark {
  font-family: var(--ptr-font-logo);
  font-weight: 800;
  font-size: clamp(15px, 1.4vw, 18px);
  letter-spacing: 0.26em;
  color: var(--ptr-white);
  text-transform: uppercase;
  white-space: nowrap;
  line-height: 1;
  justify-self: center;
  text-shadow: 0 0 24px rgba(255, 255, 255, 0.18);
}
.welcome__spacer { width: 44px; height: 44px; justify-self: start; }
.welcome__close { justify-self: end; }
.welcome__progress {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
.welcome__dot {
  width: 22px;
  height: 2px;
  background: rgba(255, 255, 255, 0.18);
  border-radius: 1px;
  position: relative;
  overflow: hidden;
}
.welcome__dot::after {
  content: '';
  position: absolute;
  inset: 0 100% 0 0;
  background: rgba(255, 255, 255, 0.85);
  transition: inset 360ms cubic-bezier(0.22, 1, 0.36, 1);
}
.welcome__dot.is-done::after { inset: 0; }
.welcome__dot.is-active::after { inset: 0 0 0 0; transition: inset linear var(--scene-ms, 1400ms); }
.welcome__close {
  width: 44px;
  height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.08);
  color: var(--ptr-lunar);
  font-size: 18px;
  line-height: 1;
  padding: 0;
  border-radius: 50%;
  cursor: pointer;
  transition: background 200ms ease, border-color 200ms ease, color 200ms ease;
}
.welcome__close:hover {
  background: rgba(255, 255, 255, 0.08);
  border-color: rgba(255, 255, 255, 0.18);
  color: var(--ptr-white);
}
.welcome__close svg { width: 14px; height: 14px; display: block; }

.welcome__scenes {
  grid-row: 2;
  position: relative;
  min-height: clamp(240px, 50vh, 460px);
  width: 100%;
  max-width: 940px;
  margin: 0 auto;
  align-self: center;
}
.welcome__scene {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: clamp(24px, 3.2vw, 44px);
  text-align: center;
  opacity: 0;
  transform: scale(0.992);
  transition: opacity 600ms cubic-bezier(0.16, 1, 0.3, 1),
              transform 720ms cubic-bezier(0.16, 1, 0.3, 1);
  pointer-events: none;
  will-change: opacity, transform;
}
.welcome__scene.is-active {
  opacity: 1;
  transform: scale(1);
  pointer-events: auto;
}
.welcome__scene.is-leaving {
  opacity: 0;
  transform: scale(1.008);
  transition-duration: 380ms;
}

.welcome__eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-family: var(--ptr-font-body);
  font-weight: 600;
  font-size: clamp(11px, 0.9vw, 12.5px);
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--ptr-register-accent);
  margin: 0;
}
.welcome__eyebrow::before,
.welcome__eyebrow::after {
  content: '';
  width: clamp(14px, 2.4vw, 28px);
  height: 1px;
  background: var(--ptr-register-accent);
  opacity: 0.45;
}

.welcome__title {
  font-family: var(--ptr-font-display);
  font-weight: 800;
  font-size: clamp(36px, 6.6vw, 88px);
  line-height: 1.02;
  letter-spacing: -0.032em;
  color: var(--ptr-white);
  margin: 0;
  max-width: 18ch;
  text-shadow: 0 0 90px color-mix(in oklab, var(--ptr-register-accent) 14%, transparent);
}
.welcome__title--md {
  font-size: clamp(30px, 4.8vw, 64px);
  max-width: 22ch;
}
.welcome__title .placeholder-note--inline {
  font-size: 10px;
  vertical-align: middle;
  margin-left: 4px;
  text-shadow: none;
}

.welcome__word {
  display: inline-block;
  vertical-align: baseline;
}
.welcome__word-in {
  display: inline-block;
  opacity: 0;
  transform: translateY(18px) scale(0.965);
  filter: blur(6px);
  transform-origin: center bottom;
  will-change: opacity, transform, filter;
}
.welcome__scene.is-active .welcome__word-in {
  animation: welcome-word-glide 900ms cubic-bezier(0.16, 1, 0.3, 1) forwards;
  animation-delay: calc(120ms + var(--w, 0) * 75ms);
}
@keyframes welcome-word-glide {
  0%   { opacity: 0; transform: translateY(18px) scale(0.965); filter: blur(6px); }
  55%  { opacity: 1; filter: blur(0); }
  100% { opacity: 1; transform: translateY(0) scale(1); filter: blur(0); }
}

.welcome__marks {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: clamp(14px, 1.8vw, 28px);
  width: min(940px, 100%);
  margin-top: clamp(36px, 4.2vw, 64px);
  position: relative;
  padding-top: 28px;
}
.welcome__marks::before {
  content: '';
  position: absolute;
  left: 8%;
  right: 8%;
  top: 28px;
  height: 1px;
  background: linear-gradient(90deg,
    transparent,
    color-mix(in oklab, var(--ptr-register-accent) 38%, transparent) 18%,
    color-mix(in oklab, var(--ptr-register-accent) 38%, transparent) 82%,
    transparent);
  transform-origin: left center;
  transform: scaleX(0);
  opacity: 0;
}
.welcome__scene--2.is-active .welcome__marks::before {
  animation: welcome-marks-line 880ms cubic-bezier(0.22, 1, 0.36, 1) forwards;
  animation-delay: 140ms;
}
@keyframes welcome-marks-line {
  0%   { transform: scaleX(0); opacity: 0; }
  30%  { opacity: 1; }
  100% { transform: scaleX(1); opacity: 1; }
}

.welcome__mark {
  display: grid;
  grid-template-rows: auto 16px auto;
  justify-items: center;
  align-items: start;
  gap: 8px;
  padding: 0 8px;
  position: relative;
  will-change: transform;
}
.welcome__mark-num {
  font-family: var(--ptr-font-body);
  font-weight: 700;
  font-size: clamp(13px, 1.05vw, 17px);
  letter-spacing: 0.24em;
  color: var(--ptr-register-accent);
  font-feature-settings: "tnum" 1, "lnum" 1;
  opacity: 0;
  transform: translateY(-6px);
  filter: blur(2px);
  will-change: opacity, transform, filter;
}
.welcome__scene--2.is-active .welcome__mark-num {
  animation: welcome-mark-num-glide 680ms cubic-bezier(0.16, 1, 0.3, 1) forwards;
  animation-delay: calc(260ms + var(--i, 0) * 130ms);
}
@keyframes welcome-mark-num-glide {
  0%   { opacity: 0; transform: translateY(-6px); filter: blur(2px); }
  60%  { opacity: 1; filter: blur(0); }
  100% { opacity: 1; transform: translateY(0); filter: blur(0); }
}
.welcome__mark::before {
  content: '';
  position: absolute;
  top: 28px;
  left: 50%;
  width: 11px;
  height: 11px;
  border-radius: 50%;
  background: var(--ptr-register-accent);
  transform: translate(-50%, -50%) scale(0);
  box-shadow: 0 0 14px color-mix(in oklab, var(--ptr-register-accent) 40%, transparent);
  will-change: transform;
}
.welcome__scene--2.is-active .welcome__mark::before {
  animation: welcome-mark-dot-glide 720ms cubic-bezier(0.16, 1, 0.3, 1) forwards;
  animation-delay: calc(320ms + var(--i, 0) * 160ms);
}
@keyframes welcome-mark-dot-glide {
  0%   { transform: translate(-50%, -50%) scale(0.2); opacity: 0; filter: blur(4px); }
  60%  { opacity: 1; filter: blur(0); }
  100% { transform: translate(-50%, -50%) scale(1); opacity: 1; filter: blur(0); }
}
.welcome__mark-name {
  font-family: var(--ptr-font-display);
  font-weight: 800;
  font-size: clamp(14px, 1.45vw, 20px);
  letter-spacing: -0.008em;
  color: var(--ptr-white);
  text-transform: none;
  opacity: 0;
  transform: translateY(14px) scale(0.97);
  filter: blur(4px);
  will-change: opacity, transform, filter;
}
.welcome__scene--2.is-active .welcome__mark-name {
  animation: welcome-mark-name-glide 820ms cubic-bezier(0.16, 1, 0.3, 1) forwards;
  animation-delay: calc(460ms + var(--i, 0) * 160ms);
}
@keyframes welcome-mark-name-glide {
  0%   { opacity: 0; transform: translateY(14px) scale(0.97); filter: blur(4px); }
  55%  { opacity: 1; filter: blur(0); }
  100% { opacity: 1; transform: translateY(0) scale(1); filter: blur(0); }
}
@media (max-width: 720px) {
  .welcome__marks {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    max-width: 320px;
    margin-top: clamp(28px, 6vw, 40px);
    padding-top: 0;
    gap: 28px 24px;
  }
  .welcome__marks::before { display: none; }
  .welcome__mark { grid-template-rows: auto auto; }
  .welcome__mark::before { display: none; }
  .welcome__mark-num {
    font-size: 12px;
    letter-spacing: 0.28em;
    margin-bottom: 6px;
  }
  .welcome__mark-name {
    font-size: 17px;
    letter-spacing: -0.005em;
  }
  .welcome__mark:nth-child(5) {
    grid-column: 1 / -1;
    margin-top: 4px;
  }
}

.welcome__shimmer {
  position: relative;
  display: inline-block;
  white-space: nowrap;
  color: var(--ptr-white);
  padding-bottom: 0.08em;
}
.welcome__shimmer::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: -0.04em;
  height: 2px;
  border-radius: 2px;
  background: linear-gradient(90deg,
    transparent,
    color-mix(in oklab, var(--ptr-register-accent) 70%, transparent) 16%,
    color-mix(in oklab, var(--ptr-register-accent) 70%, transparent) 84%,
    transparent);
  box-shadow: 0 0 16px color-mix(in oklab, var(--ptr-register-accent) 35%, transparent);
  transform-origin: left center;
  transform: scaleX(0);
  opacity: 0;
}
.welcome__scene--3.is-active .welcome__shimmer::after {
  animation: welcome-shimmer-beam 1080ms cubic-bezier(0.22, 1, 0.36, 1) forwards;
  animation-delay: 280ms;
}
@keyframes welcome-shimmer-beam {
  0%   { transform: scaleX(0); opacity: 0; }
  30%  { opacity: 1; }
  100% { transform: scaleX(1); opacity: 1; }
}
.welcome__scene--3.is-active .welcome__shimmer .shimmer-char {
  animation: welcome-shimmer-ignite 720ms cubic-bezier(0.22, 1, 0.36, 1) forwards,
             ptr-welcome-letter-shimmer 4.8s ease-in-out infinite 1500ms;
  animation-delay: calc(750ms + var(--i, 0) * 55ms), calc(1500ms + var(--i, 0) * 55ms);
}
@keyframes welcome-shimmer-ignite {
  0%   { color: var(--ptr-white); text-shadow: none; }
  50%  { color: var(--ptr-register-accent); text-shadow: 0 0 18px color-mix(in oklab, var(--ptr-register-accent) 65%, transparent); }
  100% { color: var(--ptr-white); text-shadow: 0 0 0 transparent; }
}

.welcome__bottom {
  grid-row: 3;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  gap: 14px;
  padding-top: clamp(16px, 2vw, 24px);
  min-height: 84px;
}
.welcome__primary {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding: 18px 32px;
  background: var(--ptr-white);
  color: var(--ptr-obsidian);
  font-family: var(--ptr-font-body);
  font-weight: 700;
  font-size: 15px;
  letter-spacing: 0.005em;
  border: 0;
  border-radius: 999px;
  cursor: pointer;
  opacity: 0;
  transform: translateY(14px) scale(0.95);
  transition: opacity 620ms cubic-bezier(0.22, 1, 0.36, 1),
              transform 620ms cubic-bezier(0.22, 1, 0.36, 1),
              background 200ms ease;
  box-shadow: 0 16px 48px rgba(0, 0, 0, 0.42),
              0 0 0 1px rgba(255, 255, 255, 0.06);
}
.welcome__primary::after {
  content: '';
  position: absolute;
  inset: -20px;
  border-radius: 999px;
  background: radial-gradient(circle, color-mix(in oklab, var(--ptr-register-accent) 45%, transparent) 0%, transparent 60%);
  z-index: -1;
  opacity: 0;
  filter: blur(18px);
}
.welcome.is-cta-ready .welcome__primary {
  opacity: 1;
  transform: translateY(0) scale(1);
}
.welcome.is-cta-ready .welcome__primary::after {
  animation: welcome-cta-aura 3.6s ease-in-out infinite;
}
@keyframes welcome-cta-aura {
  0%, 100% { opacity: 0.45; transform: scale(1); }
  50%      { opacity: 0.75; transform: scale(1.05); }
}
.welcome__primary:hover { background: #ffffff; }
.welcome__primary .arrow {
  display: inline-block;
  transition: transform 220ms cubic-bezier(0.22, 1, 0.36, 1);
}
.welcome__primary:hover .arrow { transform: translateX(4px); }
.welcome__skip {
  background: transparent;
  border: 0;
  color: var(--ptr-dust);
  font-family: var(--ptr-font-body);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.06em;
  padding: 6px 10px;
  cursor: pointer;
  opacity: 0;
  transition: opacity 380ms ease, color 200ms ease;
}
.welcome.is-open:not(.is-cta-ready) .welcome__skip { opacity: 0.7; }
.welcome.is-cta-ready .welcome__skip { opacity: 0; pointer-events: none; }
.welcome__skip:hover { color: var(--ptr-lunar); }

@media (max-width: 720px) {
  .welcome__stage { padding: 20px 18px; padding-bottom: calc(20px + var(--ptr-bar-height)); }
  .welcome__scenes { min-height: clamp(220px, 46svh, 360px); }
  .welcome__title { max-width: 14ch; }
  .welcome__title--md { max-width: 18ch; }
}

@media (prefers-reduced-motion: reduce) {
  .welcome,
  .welcome__top,
  .welcome__scene,
  .welcome__mark,
  .welcome__mark::before,
  .welcome__mark-num,
  .welcome__mark-name,
  .welcome__word-in,
  .welcome__marks::before,
  .welcome__shimmer::after,
  .welcome__primary {
    transition: none !important;
    animation: none !important;
  }
  .welcome__scene.is-active {
    opacity: 1; transform: none; filter: none;
  }
  .welcome__mark-num,
  .welcome__mark-name,
  .welcome__word-in {
    opacity: 1 !important; transform: none !important; filter: none !important;
  }
  .welcome__mark::before { transform: translate(-50%, -50%) scale(1) !important; opacity: 1 !important; filter: none !important; }
  .welcome__marks::before { transform: scaleX(1) !important; opacity: 1 !important; }
  .welcome__shimmer::after { transform: scaleX(1) !important; opacity: 1 !important; }
  .welcome .shimmer-char {
    animation: none !important;
    color: var(--ptr-register-accent);
  }
}

.welcome .placeholder-note--inline {
  display: inline-block;
  padding: 0 4px;
  border: 0;
  background: transparent;
  font-size: 10px;
  color: var(--ptr-corona);
  opacity: 0.7;
  vertical-align: baseline;
  letter-spacing: 0.06em;
  white-space: nowrap;
  font-weight: 700;
  text-transform: uppercase;
}
