/* ============================================================
   Homescreen — own surfaces (marketing site + builder + PWA host)
   Visual system: GLASS-FORWARD · SOFT LIGHT (DESIGN.md, locked 2026-06-23).
   Apple Liquid Glass on a calm near-white canvas; vibrancy lives in the
   content, never the wallpaper. Homescreen's OWN chrome stays CORAL #F4593A
   (generated apps theme away to a creator hue — that's app-runtime.js, not here).
   ============================================================ */

:root {
  /* ── Accent (coral — Homescreen brand; everything derives from it) ── */
  --accent:     #F4593A;   /* coral */
  --accent-2:   #C03623;   /* deep: text-on-light, hover, active nav, eyebrow */
  --accent-hi:  color-mix(in srgb, var(--accent), #fff 20%);   /* gradient highlight */
  --accent-tint:color-mix(in srgb, var(--accent) 18%, #fff);   /* thumbnails / soft fills */

  /* ── Calm near-white canvas: faint coral glow pinned top, ≤5% base tint ── */
  --app-bg:
    radial-gradient(120% 60% at 50% -15%, rgba(244,89,58,.11), transparent 60%),
    linear-gradient(180deg, #FCFAF8 0%, #F8F4F1 100%);
  --bg:        #FBF8F5;   /* near-white solid fallback */
  --peach:     #FBE9DF;   /* committed coral-tinted band (badges, glyphs, bands) */
  --card:      #FFFFFF;   /* opaque card fallback (glass surfaces override below) */

  /* ── Text — warm ink ramp (AA on glass + near-white) ── */
  --title:     #26190f;   /* titles */
  --ink:       #211a15;   /* body + headings */
  --muted:     #6a5d54;   /* secondary */
  --faint:     #756a5f;   /* tertiary / meta — darkened from #8a7d73 to clear WCAG-AA on every light surface (≈5.0 near-white, 4.7 peach); all --faint uses sit on a light bg (footer text uses a cream-mix) */

  --dark:      #1b1714;   /* CTA panel + footer (warm near-black) */
  --cream:     #F4F1ED;   /* text on dark */
  --line:      #ECE3DC;   /* hairline divider */
  --line-2:    #E0D5CC;

  /* ── Liquid Glass materials (chrome + content cards/rows). Every glass
        surface carries a 1px specular border + an inner top highlight. ── */
  --glass-row:    rgba(255,255,255,.74);   /* cards & list rows — high-opacity for AA */
  --glass-chrome: rgba(255,255,255,.55);   /* floating nav / bars (blur 26px) */
  --glass-line:   rgba(255,255,255,.85);   /* specular light edge (1px border) */
  --glass-inset:  inset 0 1px 0 rgba(255,255,255,.8);
  --blur:         saturate(180%) blur(22px);
  --blur-chrome:  saturate(180%) blur(26px);

  /* ── Elevation — layered (ambient + key), never a single flat shadow ── */
  --e1:        0 1px 2px rgba(40,30,25,.05),  0 6px 18px -10px rgba(40,30,25,.18);
  --e2:        0 2px 4px rgba(40,30,25,.05),  0 12px 28px -12px rgba(40,30,25,.22);
  --e-accent:  0 16px 40px -12px color-mix(in srgb, var(--accent) 55%, transparent),
               inset 0 1px 0 rgba(255,255,255,.55);

  /* Back-compat aliases (existing rules consume these) → now layered. */
  --shadow-sm:  var(--e1);
  --shadow-lg:  0 40px 80px -36px rgba(40,30,25,0.42);
  --shadow-acc: var(--e-accent);

  --maxw: 1180px;
  --pad-x: clamp(1.25rem, 5vw, 4rem);
  --section-y: clamp(3.25rem, 6.5vw, 5.75rem);

  /* ── Radii — concentric (child < parent) ── */
  --r-device: 44px; --r-card: 24px; --r-tab: 30px; --r-thumb: 16px; --r-btn: 16px;
  --radius: 24px;   /* back-compat: cards */

  --font: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;

  /* ── Motion — exponential ease-outs only (DESIGN.md §8: depth over flashiness).
        --ease-pop overshoots very slightly for icon/badge "settle" moments. ── */
  --ease-out:  cubic-bezier(0.16, 1, 0.3, 1);
  --ease-pop:  cubic-bezier(0.3, 1.28, 0.44, 1);

  /* Lets `height: auto` interpolate on <details> expand (progressive; FAQ). */
  interpolate-size: allow-keywords;
}

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; scroll-padding-top: 96px; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

/* `clip` (not `hidden`) — hidden turns the root into a scroll container, which
   silently kills position:sticky (the nav never stuck). clip just crops. */
html { overflow-x: hidden; overflow-x: clip; }
body {
  margin: 0;
  background: var(--app-bg);
  background-color: var(--bg);   /* solid fallback under the gradient */
  color: var(--ink);
  font-family: var(--font);
  font-size: 1.0625rem;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
  overflow-x: clip;
}

h1, h2, h3, h4 {
  margin: 0;
  color: var(--title);
  font-weight: 800;
  letter-spacing: -0.03em;
  line-height: 1.04;
  text-wrap: balance;   /* even heading line lengths (no lone trailing word) */
}
p { margin: 0; text-wrap: pretty; }   /* avoid single-word orphans on the last line */
a { color: inherit; text-decoration: none; }
.accent { color: var(--accent); }
.muted { color: var(--muted); }
::selection { background: var(--accent); color: #fff; }

.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;
}

/* ─────────────── Buttons ─────────────── */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.55rem;
  font-family: var(--font);
  font-weight: 700;
  font-size: 1rem;
  border: none;
  border-radius: 999px;
  cursor: pointer;
  line-height: 1;
  /* Sensible default so any unsized .btn (hero "Build my app", final CTA) has
     comfortable, vertically-centered breathing room. --sm/--lg override below. */
  padding: 0.85rem 1.55rem;
  transition: transform 0.16s ease, box-shadow 0.16s ease, background 0.16s ease;
}
.btn--accent { background: var(--accent); color: #fff; box-shadow: var(--shadow-acc); }
.btn--accent:hover {
  background: var(--accent-2);
  transform: translateY(-2px);
  box-shadow: 0 20px 44px -12px color-mix(in srgb, var(--accent) 62%, transparent),
              inset 0 1px 0 rgba(255,255,255,.55);
}
.btn--sm { padding: 0.62rem 1.1rem; font-size: 0.92rem; }
.btn--lg { padding: 1.05rem 1.9rem; font-size: 1.05rem; }
.btn__arrow { font-weight: 600; transition: transform 0.16s ease; }
.btn--accent:hover .btn__arrow { transform: translateX(3px); }
/* Specular sweep across the solid coral buttons on hover — glass-light, not gloss. */
.btn--accent { position: relative; overflow: hidden; }
.btn--accent::after {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(105deg, transparent 32%, rgba(255,255,255,0.32) 50%, transparent 68%);
  transform: translateX(-130%);
  pointer-events: none;
}
.btn--accent:hover::after { transition: transform 0.65s ease; transform: translateX(130%); }
@media (prefers-reduced-motion: reduce) {
  .btn--accent::after { display: none; }
  .btn, .btn--accent:hover, .btn--ghost:hover { transform: none; }
}

/* Keyboard focus — visible ring on the marketing-page interactive controls that
   only had the UA default (WCAG-AA; PRODUCT.md floor). Matches the dashboard/builder
   house ring (outline 2px accent + 2px offset). :focus-visible → mouse users see
   nothing; the outline follows each control's own border-radius. */
.btn:focus-visible,
.brand:focus-visible,
.nav__links a:focus-visible,
.nav__login:focus-visible,
.qa summary:focus-visible,
.foot__col a:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
/* The prompt textarea drops its own outline (the field shows :focus-within), but a
   keyboard user landing on it still needs an unmistakable ring — strengthen the
   field's focus state and give the textarea a fallback ring for AA. */
.prompt__field:focus-within { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ─────────────── Reveal ───────────────
   Two shapes: [data-reveal] animates the element itself; [data-reveal-group]
   staggers its direct children (70ms cadence via --d). Rise + de-blur.
   EVERY pre-state is gated on html.js (set inline in <head>) — a no-JS or
   headless render shows the finished page, never opacity-0 blanks. */
/* fix-landing-opacity-gate: NEVER opacity-gate content (the standing anti-AI-design rule). A fast flick can
   make the IntersectionObserver miss an element; the old `opacity: 0` pre-state then left whole sections
   (the FAQ) a blank peach band forever. The reveal is now a TRANSFORM/settle only — content is always fully
   opaque + sharp; a missed element simply sits a few px low, never invisible or blurred. */
html.js [data-reveal],
html.js [data-reveal-group] > * {
  transform: translateY(12px);
  transition: transform 0.7s var(--ease-out) var(--d, 0s);
}
html.js [data-reveal].is-in,
html.js [data-reveal-group].is-in > * {
  transform: none;
}
[data-reveal-group] > :nth-child(2) { --d: 70ms; }
[data-reveal-group] > :nth-child(3) { --d: 140ms; }
[data-reveal-group] > :nth-child(4) { --d: 210ms; }
[data-reveal-group] > :nth-child(5) { --d: 280ms; }
[data-reveal-group] > :nth-child(6) { --d: 350ms; }
[data-reveal-group] > :nth-child(7) { --d: 420ms; }
[data-reveal-group] > :nth-child(8) { --d: 490ms; }
[data-reveal-group] > :nth-child(n + 9) { --d: 560ms; }
@media (prefers-reduced-motion: reduce) {
  html.js [data-reveal],
  html.js [data-reveal-group] > * { opacity: 1; transform: none; filter: none; transition: none; }
}

/* ─────────────── Brand ─────────────── */
.brand { display: inline-flex; align-items: baseline; gap: 0.30em; font-size: 1.15rem; }
.brand__mark { display: inline-block; }
.brand__mark img { display: block; height: 1.08em; width: auto; }
.brand__name { font-family: 'Inter', system-ui, sans-serif; font-weight: 800; letter-spacing: -0.025em; }
.brand__home {
  background-image: linear-gradient(46deg, #F4593A 0%, #F15F46 38%, #F0726B 68%, #FB8A60 100%);
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.brand__screen { color: #2B211C; }
.brand--light .brand__screen { color: #F3EEEA; }

/* ─────────────── Nav ───────────────
   Sticky full-width shell; .nav__inner is the chrome. At rest it sits flush on
   the canvas; on scroll it detaches into a floating glass capsule (DESIGN.md
   floating-chrome material: frosted, specular edge, layered lift). */
.nav {
  position: sticky; top: 0; z-index: 60;
  padding: 0.55rem var(--pad-x);
  pointer-events: none;   /* the capsule below takes the events */
}
.nav__inner {
  pointer-events: auto;
  max-width: var(--maxw);
  margin: 0 auto;
  display: flex; align-items: center; justify-content: space-between;
  gap: 1.5rem;
  padding: 0.55rem 0.65rem 0.55rem 1.05rem;
  border-radius: 999px;
  border: 1px solid rgba(255,255,255,0.28);
  background: rgba(255,255,255,0.22);
  backdrop-filter: var(--blur-chrome);
  -webkit-backdrop-filter: var(--blur-chrome);
  transition: background 0.35s ease, border-color 0.35s ease, box-shadow 0.35s ease;
}
.nav.is-stuck .nav__inner {
  /* near-opaque: the capsule floats over arbitrary content including the
     dark CTA panel — anything translucent splits it into two tones there.
     0.92 keeps a whisper of frost on light sections, reads solid on dark. */
  background: rgba(255,255,255,0.92);
  border-color: var(--glass-line);
  box-shadow: 0 14px 34px -14px rgba(60,45,35,.3), inset 0 1px 0 rgba(255,255,255,.9);
}
html.js .nav { animation: hs-nav-in 0.8s var(--ease-out) both; }
@keyframes hs-nav-in {
  from { opacity: 0; transform: translateY(-14px); }
  to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) { html.js .nav { animation: none; } }
.nav__links { display: flex; gap: 1.9rem; font-size: 0.95rem; font-weight: 500; color: var(--muted); }
.nav__links a { position: relative; transition: color 0.15s ease; }
.nav__links a:hover { color: var(--ink); }
/* Hairline slide-in underline — quiet, coral, gone at rest. */
.nav__links a::after {
  content: "";
  position: absolute; left: 0; right: 0; bottom: -6px;
  height: 2px; border-radius: 2px;
  background: var(--accent);
  transform: scaleX(0); transform-origin: left;
  transition: transform 0.28s var(--ease-out);
}
.nav__links a:hover::after { transform: scaleX(1); }
.nav__links a.is-active { color: var(--ink); }
.nav__links a.is-active::after { transform: scaleX(1); }
@media (prefers-reduced-motion: reduce) { .nav__links a::after { transition: none; } }

/* Right-side action cluster (Log in / Start / Dashboard / account). main.js toggles
   which children show via the [hidden] attribute — this rule guarantees the attribute
   wins even on .btn (which sets display:inline-flex and would otherwise ignore hidden). */
.nav__cta { display: flex; align-items: center; gap: 0.9rem; }
.nav__cta [hidden] { display: none; }
/* Keep the header actions on one line each — at ~375px with both "Log in" + the
   accent CTA showing, "Start building free" and "Log in" otherwise wrap. */
.nav__cta .btn, .nav__login { white-space: nowrap; }
/* Low-emphasis "Log in" — reads as a nav text link, never competes with the accent CTA. */
.nav__login {
  background: none; border: none; cursor: pointer;
  font-family: var(--font); font-weight: 600; font-size: 0.95rem;
  color: var(--muted); padding: 0.4rem 0.2rem;
  transition: color 0.15s ease;
}
.nav__login:hover { color: var(--ink); }

/* ─────────────── Hero ─────────────── */
.hero {
  position: relative;
  max-width: var(--maxw);
  margin: 0 auto;
  padding: clamp(2.5rem, 6vw, 5rem) var(--pad-x) var(--section-y);
  display: grid;
  grid-template-columns: 1.05fr 0.95fr;
  gap: clamp(2rem, 5vw, 4.5rem);
  align-items: center;
}
.hero::before {
  content: "";
  position: absolute; inset: 0 -20vw auto auto; z-index: -1;
  height: 90%; width: 70vw;
  background: radial-gradient(60% 60% at 75% 30%, var(--accent-tint), transparent 70%);
  opacity: 0.5;
}
/* The ambient glow breathes — barely (stays inside the ≤5% bg-tint guardrail). */
html.js .hero::before { animation: hs-glow-drift 16s ease-in-out infinite alternate; }
@keyframes hs-glow-drift {
  from { transform: translate3d(0, 0, 0) scale(1); }
  to   { transform: translate3d(-3%, 3%, 0) scale(1.07); }
}
@media (prefers-reduced-motion: reduce) { html.js .hero::before { animation: none; } }
.hero__title {
  /* fix-site-mobile-audit-minors: the old 2.6rem clamp MIN forced ~41px on phones, so each locked line
     wrapped and the h1 read as 4 lines at 390. Lower the min + let it scale by vw so phones get a size
     where the two locked lines fit cleanly (copy is founder-locked, layout only). */
  font-size: clamp(1.7rem, 7.4vw, 3.85rem);
  letter-spacing: -0.035em;
  margin-bottom: 1.4rem;
}
/* Controlled lockup: "Describe your app." owns line one; the coral thought
   wraps on its own terms — no orphaned "app." mid-line. */
.hero__title-line { display: block; }
.hero__sub {
  font-size: clamp(1.05rem, 1.7vw, 1.2rem);
  color: var(--muted);
  max-width: 30rem;
  margin-bottom: 2rem;
}
/* site-value-prop-rewrite: the single locked-hero CTA (replaces the prompt box). */
.hero__cta { margin-top: 0.5rem; }
.hero__fineprint {
  display: flex; align-items: center; gap: 0.5rem;
  margin-top: 1rem; font-size: 0.9rem; color: var(--muted);
}
.hero__fineprint .dot { width: 0.55rem; height: 0.55rem; border-radius: 50%; background: var(--accent); flex: none; }
.hero__trust { margin-top: 1.6rem; font-size: 0.9rem; font-weight: 600; }
.hero__trust .sep { color: var(--line-2); margin: 0 0.5rem; }
.hero__trust .muted { font-weight: 500; }

/* ─────────────── Hero prompt (describe-your-app) ─────────────── */
.prompt { max-width: 32rem; margin-bottom: 0.25rem; }
.prompt__field {
  display: flex;
  align-items: flex-end;
  gap: 0.6rem;
  background: var(--glass-row);
  backdrop-filter: var(--blur);
  -webkit-backdrop-filter: var(--blur);
  border: 1px solid color-mix(in srgb, var(--accent) 14%, var(--glass-line));
  border-radius: 18px;
  padding: 0.7rem 0.7rem 0.7rem 0.95rem;
  box-shadow: var(--e2), 0 24px 60px -30px color-mix(in srgb, var(--accent) 30%, transparent), var(--glass-inset);
  transition: border-color 0.16s ease, box-shadow 0.16s ease;
}
.prompt__field:focus-within { border-color: var(--accent); box-shadow: var(--e-accent); }
.prompt__input {
  flex: 1 1 auto;
  min-width: 0;
  min-height: 5.5rem;
  resize: none;
  border: 0;
  background: transparent;
  font-family: var(--font);
  font-size: 1rem;
  line-height: 1.5;
  color: var(--ink);
  caret-color: var(--accent);
  padding: 0.35rem 0;
}
.prompt__input::placeholder { color: var(--faint); }
.prompt__input:focus { outline: none; }
.prompt__go { flex: none; white-space: nowrap; }
.prompt__chips {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: 0.45rem; margin-top: 0.85rem;
}
.prompt__try { font-size: 0.82rem; color: var(--faint); font-weight: 600; margin-right: 0.1rem; }
/* Frames what the primary action does — clicking opens a live, free build session
   (the unframed-state-jump fix), bound directly under the field. */
.prompt__note { margin: 0.7rem 0 0; max-width: 32rem; font-size: 0.9rem; line-height: 1.5; color: var(--muted); }
/* #32 — inline hint when "Build my app" is submitted empty. */
.prompt__hint { margin: 0.6rem 0 0; font-size: 0.85rem; font-weight: 600; color: var(--accent-2); }
.prompt__hint[hidden] { display: none; }
.prompt__hint--nudge { animation: hs-nudge 0.32s ease; }
.chip {
  font-family: var(--font);
  font-size: 0.82rem; font-weight: 600;
  color: var(--muted);
  background: var(--glass-row);
  backdrop-filter: var(--blur);
  -webkit-backdrop-filter: var(--blur);
  border: 1px solid var(--line-2);
  border-radius: 999px;
  padding: 0.4rem 0.85rem;
  cursor: pointer;
  transition: border-color 0.15s ease, color 0.15s ease, background 0.15s ease,
              transform 0.2s var(--ease-out), box-shadow 0.2s var(--ease-out);
}
.chip:hover {
  border-color: var(--accent); color: var(--accent-2); background: var(--peach);
  transform: translateY(-2px); box-shadow: var(--e1);
}
@media (prefers-reduced-motion: reduce) { .chip:hover { transform: none; } }

/* ─────────────── Phone ─────────────── */
.hero__device { position: relative; display: flex; justify-content: center; perspective: 1200px; padding-bottom: 34px; }
/* Contact shadow — the phone stands on a stage instead of floating in space. */
.hero__device::after {
  content: "";
  position: absolute; bottom: 6px; left: 50%;
  width: min(240px, 58vw); height: 30px;
  transform: translateX(-50%);
  background: radial-gradient(50% 50% at 50% 50%, rgba(40,18,8,0.28), transparent 70%);
  filter: blur(6px);
  pointer-events: none;
}
/* The hero device arrives with more travel + a settle (overrides the base reveal). */
html.js .hero__device[data-reveal] {
  transform: translateY(46px) scale(0.96) rotate(2deg);
  transition-duration: 1s;
  transition-delay: 0.25s;
}
html.js .hero__device[data-reveal].is-in { transform: none; }
@media (prefers-reduced-motion: reduce) {
  html.js .hero__device[data-reveal] { transform: none; transition: none; }
}
.phone {
  position: relative;
  width: min(300px, 76vw);
  aspect-ratio: 9 / 19.3;
  background: linear-gradient(180deg, #17171a 0%, #0d0d0f 55%, #101013 100%);
  border-radius: 46px;
  padding: 11px;
  box-shadow: var(--shadow-lg);
  transition: transform 0.25s var(--ease-out);   /* pointer tilt (landing-fx.js) */
}
/* Specular bezel edge — a 1px light catch around the frame, the glass signature. */
.phone::after {
  content: "";
  position: absolute; inset: 0;
  border-radius: 46px;
  box-shadow: inset 0 1px 1px rgba(255,255,255,0.28), inset 0 -1px 1px rgba(255,255,255,0.1),
              inset 1.5px 0 1px -1px rgba(255,255,255,0.14), inset -1.5px 0 1px -1px rgba(255,255,255,0.14);
  pointer-events: none;
}
.phone__notch {
  position: absolute; top: 19px; left: 50%; transform: translateX(-50%);
  width: 92px; height: 26px; background: #000; border-radius: 16px; z-index: 3;
}
.phone__notch--sm { width: 74px; height: 21px; top: 15px; }
.phone__screen { height: 100%; border-radius: 36px; overflow: hidden; }

/* ── Hero phone: the narrative loop — a real capture of three creator apps
      touring themselves. The bezel/notch stay DOM; the screen is the video. ── */
.phoneplay { position: relative; height: 100%; background: #1b1310; }
.phoneplay__video {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: top;
}
.phoneplay__open {
  position: absolute; inset: 0; z-index: 2;
  border: 0; padding: 0;
  background: transparent;
  cursor: zoom-in;
}
.phoneplay__open:focus-visible { outline: 2px solid var(--accent); outline-offset: -4px; border-radius: 32px; }

/* The chip whose idea is currently being "typed"/built glows quietly. */
.chip.is-live { border-color: var(--accent); color: var(--accent-2); background: var(--peach); box-shadow: var(--e1); }

/* The app-section phones show REAL captures of a generated recipe app
   (brand/app-shot-*.jpg, from the capture rig) — no more hand-drawn UI. */
.phone__shot { display: block; width: 100%; height: 100%; object-fit: cover; object-position: top; }

/* ─────────────── Section heads ─────────────── */
.section-head { max-width: 44rem; margin: 0 auto clamp(2.5rem, 5vw, 3.5rem); text-align: center; }
.section-head--left { margin-left: 0; margin-right: auto; text-align: left; }
.section-head h2 { font-size: clamp(1.9rem, 4vw, 3rem); }
.section-head p { margin-top: 1rem; color: var(--muted); font-size: 1.075rem; }

/* ─────────────── How it works ─────────────── */
.how { max-width: var(--maxw); margin: 0 auto; padding: var(--section-y) var(--pad-x); }
/* site-value-prop-rewrite (density cut): the reused .how shell now also carries the PROOF media and the
   "What you get" box list — both centered + constrained to the reading measure, no new visual elements. */
/* site-design-polish-batch item 12: the proof-of-magic build video read postage-stamp-small (42rem/672px
   = ~57% of the content column at 1440, narrower than the comparison table below it). Widen it so the one
   piece of live proof is prominent — comfortably past the founder's 2/3-width floor while staying centered
   and never oversized (it just fills the column on smaller screens). */
.proof-media { max-width: 52rem; margin: 0 auto; }
/* fix-landing-whatyouget-layout (layout only — copy is founder-locked):
   (1) center the "What you get" block under its centered heading. The base `.ticks { margin: 0 }` (:687,
       later in source) out-ordered an earlier `.box-list { margin: 0 auto }`, left-aligning the list with
       a dead right half — `.ticks.box-list` out-SPECIFIES it so the centering wins.
   (2) each row was a flex li, so `<strong>` + the bare description text became SEPARATE anonymous flex
       items: the strong shrank into a skinny 1-2 line column and each description started at a different x.
       A grid with a FIXED label column fixes both — every description shares one left edge; labels don't
       wrap into a skinny column. */
.ticks.box-list { max-width: 44rem; margin-left: auto; margin-right: auto; }
.ticks.box-list li {
  display: grid;
  grid-template-columns: 20px 9rem 1fr;
  column-gap: 0.85rem;
  align-items: baseline;
}
/* Asymmetric 3-step row — the middle "Shape it" step is wider + featured, so the
   sequence doesn't read as an identical 3-card grid. Collapses to 1 col ≤900px. */
.steps { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: 1fr 1.28fr 1fr; gap: 1.25rem; align-items: stretch; }
.step-card {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.6rem;
  box-shadow: var(--shadow-sm);
  transition: transform 0.3s var(--ease-out), box-shadow 0.3s var(--ease-out);
}
.step-card:hover { transform: translateY(-4px); box-shadow: var(--e2); }
@media (prefers-reduced-motion: reduce) { .step-card:hover { transform: none; } }
.step-card h3 { font-size: 1.3rem; margin-bottom: 0.55rem; }
.step-card p { color: var(--muted); font-size: 0.98rem; }

/* Featured middle step — the "watch it become real" moment. Glass + extra lift +
   a small in-browser preview set it apart from the flat side cards. */
.step-card--feature {
  background: var(--glass-row);
  backdrop-filter: var(--blur); -webkit-backdrop-filter: var(--blur);
  border-color: var(--glass-line);
  box-shadow: var(--e2);
}
/* Mini "app coming together in the browser" — a chrome bar + the accent app tile
   forming next to placeholder content. Decorative (aria-hidden), static. */
.step-preview {
  margin-top: 1.2rem;
  border-radius: 12px;
  border: 1px solid var(--line);
  background: #fff;
  box-shadow: var(--e1);
  overflow: hidden;
}
.step-preview__chrome {
  display: flex; gap: 5px; align-items: center;
  padding: 7px 10px;
  background: color-mix(in srgb, var(--accent) 6%, #fff);
  border-bottom: 1px solid var(--line);
}
.step-preview__chrome i { width: 7px; height: 7px; border-radius: 50%; background: var(--line-2); }

/* Mini product vignettes in steps 1 & 3 — our own UI at postcard size. */
.step-mini { margin-top: 1.2rem; }
.step-mini__field {
  display: flex; flex-direction: column; gap: 0.7rem;
  background: var(--glass-row);
  border: 1px solid color-mix(in srgb, var(--accent) 12%, var(--glass-line));
  border-radius: 14px;
  padding: 0.8rem 0.9rem;
  box-shadow: var(--e1), var(--glass-inset);
}
.step-mini__text { font-size: 0.85rem; line-height: 1.5; color: var(--ink); }
.step-mini__go {
  align-self: flex-end;
  background: var(--accent); color: #fff;
  font-size: 0.78rem; font-weight: 700;
  border-radius: 999px; padding: 0.4rem 0.85rem;
}
.step-mini__sheet {
  display: flex; align-items: center; gap: 0.65rem;
  background: var(--glass-row);
  border: 1px solid var(--glass-line);
  border-radius: 14px;
  padding: 0.7rem 0.85rem;
  box-shadow: var(--e1), var(--glass-inset);
}
.step-mini__appicon {
  width: 38px; height: 38px; flex: none; border-radius: 10px;
  background: url("/brand/appicon-final.png") center / cover no-repeat;
  box-shadow: 0 3px 8px -3px rgba(120,35,10,0.5);
}
.step-mini__meta { display: flex; flex-direction: column; min-width: 0; line-height: 1.3; }
.step-mini__meta strong { font-size: 0.85rem; letter-spacing: -0.01em; }
.step-mini__meta span { font-size: 0.72rem; color: var(--faint); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.step-mini__add { margin-left: auto; flex: none; color: var(--accent-2); font-weight: 700; font-size: 0.85rem; }
.step-mini__caption { margin: 0.5rem 0 0; font-size: 0.75rem; font-weight: 600; color: var(--faint); text-align: center; }

/* ── The real thing: the captured build loop inside the mini browser window ── */
.step-preview--video { overflow: hidden; }
.step-preview__watch {
  position: relative;
  display: block;
  width: 100%;
  padding: 0;
  border: 0;
  background: #FBF8F5;
  cursor: zoom-in;
}
.step-preview__watch:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.step-preview__video { display: block; width: 100%; aspect-ratio: 1440 / 900; object-fit: cover; }
.step-preview__expand {
  position: absolute; right: 8px; bottom: 8px;
  display: inline-flex; align-items: center;
  font-size: 0.72rem; font-weight: 700; color: var(--ink);
  background: rgba(255,255,255,0.85);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border: 1px solid var(--glass-line);
  border-radius: 999px;
  padding: 0.28rem 0.6rem;
  box-shadow: var(--e1);
  opacity: 0;
  transform: translateY(4px);
  transition: opacity 0.25s var(--ease-out), transform 0.25s var(--ease-out);
}
.step-preview__watch:hover .step-preview__expand,
.step-preview__watch:focus-visible .step-preview__expand { opacity: 1; transform: none; }
/* Reduced motion / no-autoplay: the badge stays visible as the affordance. */
@media (prefers-reduced-motion: reduce) {
  .step-preview__expand { opacity: 1; transform: none; transition: none; }
}
.step-preview__caption {
  padding: 0.55rem 0.9rem;
  border-top: 1px solid var(--line);
  font-size: 0.78rem; font-weight: 600; color: var(--faint);
  background: #fff;
}

/* ── Build-demo lightbox (native dialog, glass system) ── */
.demo-dialog {
  width: min(92vw, 1100px);
  border: 1px solid var(--glass-line);
  border-radius: var(--r-card);
  padding: 0.75rem 0.75rem 0.65rem;
  background: rgba(255,255,255,0.92);
  box-shadow: var(--shadow-lg);
}
.demo-dialog::backdrop {
  background: rgba(27,23,20,0.62);
  backdrop-filter: blur(10px) saturate(120%);
  -webkit-backdrop-filter: blur(10px) saturate(120%);
}
html.js .demo-dialog[open] { animation: hs-dialog-in 0.35s var(--ease-out); }
@keyframes hs-dialog-in {
  from { opacity: 0; transform: translateY(14px) scale(0.98); }
  to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) { html.js .demo-dialog[open] { animation: none; } }
.demo-dialog__video { display: block; width: 100%; border-radius: 14px; background: #FBF8F5; }
.demo-dialog--phone { width: min(92vw, 420px); }
.demo-dialog__video--phone { aspect-ratio: 640 / 1430; max-height: 78vh; object-fit: contain; background: #1b1310; }
.demo-dialog__caption { margin: 0.6rem 0.2rem 0; font-size: 0.88rem; color: var(--muted); text-align: center; }
.demo-dialog__close {
  position: absolute; top: -0.9rem; right: -0.9rem; z-index: 1;
  width: 2.3rem; height: 2.3rem;
  display: grid; place-items: center;
  border: 1px solid var(--glass-line);
  border-radius: 50%;
  background: #fff;
  color: var(--ink);
  font-size: 1.25rem; line-height: 1;
  cursor: pointer;
  box-shadow: var(--e2);
}
.demo-dialog__close:hover { color: var(--accent-2); }
.demo-dialog__close:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
@media (max-width: 640px) {
  .demo-dialog { width: 96vw; padding: 0.5rem 0.5rem 0.55rem; }
  .demo-dialog__close { top: 0.35rem; right: 0.35rem; }
}

/* ─────────────── The app ─────────────── */
.app {
  background: var(--peach);
  padding: var(--section-y) var(--pad-x);
}
.app {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(2rem, 5vw, 4rem);
  align-items: center;
  max-width: var(--maxw);
  margin: 0 auto;
  /* the band is an inset panel on the whiter canvas now — soften its corners
     to the same family as the CTA panel (32px), never a hard-edged slab */
  border-radius: 32px;
}
.app__devices { position: relative; min-height: 420px; display: flex; justify-content: center; align-items: center; overflow: clip; }
.app__devices .phone { width: min(240px, 60vw); }
.phone--back { position: absolute; transform: translateX(-32%) rotate(-8deg); filter: saturate(0.95); z-index: 1; }
.phone--front { position: relative; transform: translateX(18%) rotate(3deg); z-index: 2; }
/* The pair starts gathered + upright and fans out into its pose as the section
   scrolls in. Final transforms live in the rules above (and their ≤900px
   overrides) — the pre-state exists only before .is-in, under html.js, and
   only when motion is welcome (reduced-motion never sees it). */
@media (prefers-reduced-motion: no-preference) {
  html.js .app__devices .phone { transition: transform 1.1s var(--ease-out), opacity 0.6s ease; }
  html.js .app__devices:not(.is-in) .phone--back { transform: translateX(-8%) rotate(-1deg); opacity: 0; }
  html.js .app__devices:not(.is-in) .phone--front { transform: translateX(4%) rotate(0.5deg); opacity: 0; }
  html.js .app__devices.is-in .phone--front { transition-delay: 0.08s; }
}
.app__copy h2 { font-size: clamp(1.9rem, 4vw, 3rem); }
.app__lead { margin: 1rem 0 1.6rem; color: var(--muted); font-size: 1.075rem; }
/* Editorial rows, not checklist bubbles: a short coral dash + hairlines. */
.ticks { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.ticks li {
  display: flex; align-items: baseline; gap: 0.85rem;
  padding: 0.85rem 0;
  border-bottom: 1px solid var(--line);
  font-weight: 500;
}
.ticks li:last-child { border-bottom: 0; }
.ticks li::before {
  content: "";
  flex: none;
  width: 20px; height: 2px;
  border-radius: 2px;
  background: var(--accent);
  transform: translateY(-0.28em);
}

/* ─────────────── Why / comparison ─────────────── */
.why { max-width: var(--maxw); margin: 0 auto; padding: var(--section-y) var(--pad-x); }
/* Closing trust line under the comparison — a quiet guarantee, not a card. */
.why__assure {
  max-width: 44rem;
  margin: clamp(2rem, 4vw, 3rem) auto 0;
  text-align: center;
  text-wrap: balance;
  font-size: clamp(1.05rem, 1.6vw, 1.2rem);
  line-height: 1.55;
  color: var(--muted);
}
.why__assure strong { color: var(--accent-2); font-weight: 800; }
/* The table sits on a frosted glass sheet (content-card material, DESIGN.md §2). */
.compare {
  display: flex; flex-direction: column;
  background: var(--glass-row);
  backdrop-filter: var(--blur);
  -webkit-backdrop-filter: var(--blur);
  border: 1px solid var(--glass-line);
  border-radius: var(--r-card);
  padding: 0.4rem 1.5rem 0.9rem;
  box-shadow: var(--e2), var(--glass-inset);
}
/* Ticks pop down the sheet as the rows cascade in. */
@media (prefers-reduced-motion: no-preference) {
  html.js .compare.is-in .tick { animation: hs-tick-pop 0.4s var(--ease-pop) both; animation-delay: calc(var(--d, 0s) + 0.3s); }
}
@keyframes hs-tick-pop {
  from { opacity: 0; transform: scale(0.3); }
  to   { opacity: 1; transform: scale(1); }
}
.compare__row {
  display: grid;
  grid-template-columns: 1.6fr 1fr 1fr 1fr;
  align-items: center;
  border-bottom: 1px solid var(--line);
}
/* site-competitor-table: 4 competitor columns (feat + Homescreen · Patreon · Substack · beehiiv). The
   mobile stacked view (below) is column-count-agnostic (each cell shows its data-label), so only the
   desktop grid needs the extra track. */
.compare--4col .compare__row { grid-template-columns: 1.5fr repeat(4, 1fr); }
/* site-copy-approved-sweep: 5 competitor columns (feat + Homescreen · Linktree · Patreon · Substack ·
   Provecho). Same column-count-agnostic mobile stack; the desktop grid gets one more 1fr track. */
.compare--5col .compare__row { grid-template-columns: 1.3fr repeat(5, 1fr); }
.compare__row:last-child { border-bottom: 0; }
.compare__row::before {
  content: attr(data-feat);
  padding: 1.1rem 1rem 1.1rem 0;
  font-weight: 600;
}
.compare__row--head { border-bottom: 1px solid var(--line-2); }
.compare__row--head::before { content: ""; padding: 0; }
.compare__feat { display: none; }
.compare__col {
  text-align: center;
  padding: 1.1rem 0.5rem;
  color: var(--muted);
  font-weight: 600;
  font-size: 0.95rem;
}
.compare__col--us {
  display: flex; flex-direction: column; gap: 0.1rem;
  color: var(--accent-2);   /* text-on-light coral — "Homescreen" 16.8px bold needs AA (4.5:1) on the peach header band; --accent fails at 2.95:1 */
}
.compare__col--us strong { font-size: 1.05rem; }
.compare__col--us em { font-style: normal; font-size: 0.78rem; font-weight: 500; color: var(--faint); }
/* highlighted Homescreen column band */
.compare__row > .compare__col--us,
.compare__row::after { }
.compare__row {
  position: relative;
}
.compare__row .cell {
  text-align: center; padding: 1.1rem 0.5rem; font-weight: 600; color: var(--muted); font-size: 0.95rem;
}
.compare__row .cell--us { background: var(--peach); }
.compare__row--head .compare__col--us { background: var(--peach); border-radius: 14px 14px 0 0; }
.compare__row:last-child .cell--us { border-radius: 0 0 14px 14px; }
.tick {
  display: inline-grid; place-items: center;
  width: 1.6rem; height: 1.6rem; border-radius: 50%;
  background: var(--accent); color: #fff; font-size: 0.85rem; font-weight: 800;
}
.cell--us .tick { box-shadow: 0 4px 10px -4px rgba(244,89,58,0.6); }
.no { color: var(--line-2); font-size: 1.2rem; }

/* ─────────────── FAQ ─────────────── */
.faq { background: var(--peach); padding: var(--section-y) var(--pad-x); }
.faq .section-head, .faq__list { max-width: 46rem; margin-left: auto; margin-right: auto; }
.faq__list { display: flex; flex-direction: column; gap: 0.85rem; }
.qa {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 16px;
  padding: 0 1.25rem;
  box-shadow: var(--shadow-sm);
  transition: border-color 0.25s ease, box-shadow 0.25s ease;
}
.qa[open] { border-color: color-mix(in srgb, var(--accent) 35%, var(--line)); box-shadow: var(--e2); }
.qa summary {
  list-style: none; cursor: pointer;
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  padding: 1.15rem 0;
  font-weight: 700; font-size: 1.05rem;
}
.qa summary::-webkit-details-marker { display: none; }
.qa summary::after {
  content: "+";
  flex: none;
  width: 1.7rem; height: 1.7rem;
  display: grid; place-items: center;
  background: var(--peach); color: var(--accent);
  border-radius: 50%; font-size: 1.1rem; font-weight: 700;
  transition: transform 0.3s var(--ease-out), background 0.2s ease, color 0.2s ease;
}
/* The + rotates into a × — one glyph, no content swap. */
.qa[open] summary::after { transform: rotate(45deg); background: var(--accent); color: #fff; }
/* Answers glide open where `interpolate-size` is supported (Chromium);
   elsewhere they simply toggle — same content, no motion. */
.qa::details-content {
  height: 0;
  overflow: clip;
  transition: height 0.4s var(--ease-out), content-visibility 0.4s allow-discrete;
}
.qa[open]::details-content { height: auto; }
@media (prefers-reduced-motion: reduce) {
  .qa::details-content { transition: none; }
  .qa summary::after { transition: none; }
}
.qa p { padding: 0.05rem 0 1.2rem; color: var(--muted); font-size: 0.98rem; max-width: 40rem; }

/* ─────────────── Final CTA ─────────────── */
.cta { padding: var(--section-y) var(--pad-x); }
.cta__panel {
  position: relative;
  overflow: hidden;
  max-width: var(--maxw);
  margin: 0 auto;
  background: var(--dark);
  color: var(--cream);
  border: 1px solid rgba(255,255,255,0.08);
  border-radius: 28px;
  padding: clamp(2.75rem, 6vw, 5rem) clamp(1.5rem, 5vw, 4rem);
  text-align: center;
  box-shadow: 0 30px 70px -30px rgba(27,23,20,0.55), inset 0 1px 0 rgba(255,255,255,0.08);
}
/* Slow coral aurora inside the dark panel — vibrancy in the content, per the
   house rule. Static glow when motion is reduced. */
.cta__aurora {
  position: absolute; inset: -35%;
  background:
    radial-gradient(34% 42% at 32% 38%, rgba(244,89,58,0.34), transparent 62%),
    radial-gradient(30% 38% at 68% 62%, rgba(251,138,96,0.22), transparent 62%);
  filter: blur(44px);
  pointer-events: none;
}
html.js .cta__aurora { animation: hs-aurora 17s ease-in-out infinite alternate; }
@keyframes hs-aurora {
  from { transform: translate3d(-3%, -2%, 0) rotate(0deg) scale(1); }
  to   { transform: translate3d(3%, 2%, 0) rotate(7deg) scale(1.08); }
}
@media (prefers-reduced-motion: reduce) { html.js .cta__aurora { animation: none; } }
.cta__panel > :not(.cta__aurora) { position: relative; }
.cta__panel h2 { font-size: clamp(1.9rem, 4.4vw, 3.2rem); color: #fff; }
.cta__panel p { margin: 1.2rem auto 2rem; max-width: 34rem; color: color-mix(in srgb, var(--cream) 72%, transparent); }
.cta__fine { margin-top: 1.1rem; font-size: 0.88rem; color: color-mix(in srgb, var(--cream) 60%, transparent); }

/* Auth-first CTA action row — a single coral button, centered. */
.cta__actions { display: flex; justify-content: center; }

/* Ghost button: coral marks the action (per DESIGN.md) without competing with
   the solid coral button. Fills coral on hover. Used by the nav account chip. */
.btn--ghost {
  flex: none;
  background: transparent;
  color: var(--accent);
  border: 1px solid var(--accent);
}
.btn--ghost:hover { background: var(--accent); color: #fff; transform: translateY(-2px); }
.btn--ghost:disabled { opacity: 0.6; cursor: default; transform: none; }

/* ─────────────── /recipes niche landing ───────────────
   Deliberately a different gestalt from the home page: centered editorial
   hero with the phone as the stage (flanked by tilted photography),
   hairline feature ROWS instead of the card grid, and an import visual. */
.hero--stack {
  grid-template-columns: 1fr;
  text-align: center;
  gap: clamp(2rem, 4vw, 3rem);
  padding-bottom: clamp(3rem, 6vw, 5rem);
}
.hero--stack .hero__sub { margin-left: auto; margin-right: auto; max-width: 36rem; }
.hero--stack .prompt { margin-left: auto; margin-right: auto; }
.hero--stack .prompt__chips { justify-content: center; }
.hero--stack .prompt__optin { justify-content: center; }
.hero--stack .hero__device { margin-top: 0.5rem; }
.hero__flank {
  position: absolute; top: 14%; z-index: 0;
  width: min(190px, 16vw);
  height: auto;   /* the width/height attrs are CLS hints, not a fixed box */
  border-radius: 16px;
  border: 6px solid #fff;
  box-shadow: 0 24px 50px -22px rgba(70,35,12,0.45);
}
.hero__flank--l { left: max(2%, calc(50% - 430px)); transform: rotate(-7deg); }
.hero__flank--r { right: max(2%, calc(50% - 430px)); transform: rotate(6deg); top: 38%; }
@media (max-width: 900px) { .hero__flank { display: none; } }

/* editorial feature rows — hairlines, not cards */
.featrows { max-width: 56rem; margin: 0 auto; }
.featrow {
  display: grid; grid-template-columns: 0.9fr 1.4fr;
  gap: clamp(1.5rem, 4vw, 3rem);
  padding: clamp(1.6rem, 3.5vw, 2.4rem) 0;
  border-top: 1px solid var(--line-2);
}
.featrow h3 { font-size: 1.45rem; letter-spacing: -0.02em; }
.featrow p { color: var(--muted); font-size: 1rem; line-height: 1.7; }
@media (max-width: 720px) { .featrow { grid-template-columns: 1fr; gap: 0.6rem; } }

/* "paste a link" import visual */
.importviz {
  max-width: 34rem; margin: 0 auto clamp(2.5rem, 5vw, 3.5rem);
  display: flex; flex-direction: column; gap: 0.7rem;
  background: var(--glass-row);
  backdrop-filter: var(--blur);
  -webkit-backdrop-filter: var(--blur);
  border: 1px solid var(--glass-line);
  border-radius: var(--r-card);
  padding: 1.1rem 1.2rem;
  box-shadow: var(--e2), var(--glass-inset);
}
.importviz__url {
  display: flex; align-items: center; gap: 0.6rem;
  background: #fff; border: 1px solid var(--line-2); border-radius: 999px;
  padding: 0.55rem 1rem;
  font-size: 0.9rem; color: var(--muted);
}
.importviz__url strong { color: var(--ink); font-weight: 600; }
.importviz__go { margin-left: auto; color: var(--accent-2); font-weight: 700; font-size: 0.85rem; flex: none; }
.importviz__result {
  display: flex; align-items: center; gap: 0.75rem;
  background: #fff; border: 1px solid var(--line); border-radius: 14px;
  padding: 0.6rem 0.75rem;
}
.importviz__thumb {
  width: 52px; height: 52px; flex: none; border-radius: 10px;
  background: url("/brand/food-risotto.jpg") center / cover no-repeat;
}
.importviz__meta { display: flex; flex-direction: column; line-height: 1.35; min-width: 0; }
.importviz__meta strong { font-size: 0.95rem; letter-spacing: -0.01em; }
.importviz__meta span { font-size: 0.8rem; color: var(--faint); }
.importviz__check { margin-left: auto; flex: none; color: var(--accent-2); font-weight: 700; font-size: 0.82rem; }

/* home-page signpost ribbon → /recipes */
.niche-ribbon { max-width: var(--maxw); margin: 0 auto; padding: 0 var(--pad-x); }
.niche-ribbon a {
  display: flex; align-items: center; gap: 1rem; flex-wrap: wrap;
  margin-top: clamp(2rem, 4vw, 3rem);
  background: var(--glass-row);
  backdrop-filter: var(--blur);
  -webkit-backdrop-filter: var(--blur);
  border: 1px solid color-mix(in srgb, var(--accent) 14%, var(--glass-line));
  border-radius: 18px;
  padding: 1rem 1.3rem;
  box-shadow: var(--e1), var(--glass-inset);
  transition: transform 0.25s var(--ease-out), box-shadow 0.25s var(--ease-out);
}
.niche-ribbon a:hover { transform: translateY(-2px); box-shadow: var(--e2), var(--glass-inset); }
.niche-ribbon__thumb {
  width: 44px; height: 44px; flex: none; border-radius: 12px;
  background: url("/brand/food-bowl.jpg") center / cover no-repeat;
}
.niche-ribbon__text { display: flex; flex-direction: column; line-height: 1.35; }
.niche-ribbon__text strong { font-size: 1rem; letter-spacing: -0.01em; }
.niche-ribbon__text span { font-size: 0.88rem; color: var(--muted); }
.niche-ribbon__arrow { margin-left: auto; color: var(--accent-2); font-weight: 700; white-space: nowrap; }
@media (prefers-reduced-motion: reduce) { .niche-ribbon a:hover { transform: none; } }

/* ─────────────── Legal pages (privacy / terms) ─────────────── */
.legal { max-width: 46rem; margin: 0 auto; padding: clamp(2.5rem, 6vw, 4rem) var(--pad-x) var(--section-y); }
.legal h1 { font-size: clamp(2rem, 4.6vw, 2.9rem); margin-bottom: 0.5rem; }
.legal__updated { color: var(--faint); font-size: 0.9rem; margin-bottom: 2.2rem; }
.legal h2 { font-size: 1.25rem; margin: 2.2rem 0 0.7rem; }
.legal p, .legal li { color: var(--muted); font-size: 0.99rem; line-height: 1.7; }
.legal p + p { margin-top: 0.7rem; }
.legal ul { margin: 0.6rem 0 0; padding-left: 1.2rem; display: flex; flex-direction: column; gap: 0.45rem; }
.legal a { color: var(--accent-2); text-decoration: underline; text-underline-offset: 2px; }
.legal strong { color: var(--ink); }
.legal__nav { padding: 1.1rem var(--pad-x); max-width: 46rem; margin: 0 auto; }

/* ─────────────── Mobile sticky CTA ───────────────
   Slim frosted bar on phones once the hero scrolls away (landing-fx.js
   toggles .is-on). Hidden entirely at tablet+ and for signed-in creators. */
.mcta {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 70;
  display: none;
  padding: 0.6rem 1rem calc(0.6rem + env(safe-area-inset-bottom, 0px));
  background: rgba(255,255,255,0.82);
  backdrop-filter: var(--blur-chrome);
  -webkit-backdrop-filter: var(--blur-chrome);
  border-top: 1px solid var(--glass-line);
  box-shadow: 0 -10px 30px -18px rgba(60,45,35,0.35);
  transform: translateY(110%);
  transition: transform 0.35s var(--ease-out);
}
.mcta.is-on { transform: none; }
.mcta__btn { width: 100%; }
@media (max-width: 719px) {
  .mcta:not([hidden]) { display: block; }
}
@media (prefers-reduced-motion: reduce) { .mcta { transition: none; } }

/* ─────────────── Footer ─────────────── */
.foot { background: var(--dark); color: var(--cream); padding: clamp(3rem, 6vw, 4.5rem) var(--pad-x) 2rem; }
.foot__inner {
  max-width: var(--maxw); margin: 0 auto;
  display: grid; grid-template-columns: 2fr 1fr 1fr; gap: 2rem;
  padding-bottom: 2.5rem; border-bottom: 1px solid rgba(255,255,255,0.1);
}
.foot__brand p { margin-top: 0.9rem; color: color-mix(in srgb, var(--cream) 60%, transparent); max-width: 22rem; font-size: 0.95rem; }
.foot__col { display: flex; flex-direction: column; gap: 0.7rem; }
.foot__col h2, .foot__col h4 { font-size: 0.78rem; letter-spacing: 0.1em; text-transform: uppercase; color: color-mix(in srgb, var(--cream) 64%, transparent); font-weight: 700; margin-bottom: 0.2rem; line-height: 1.3; }
.foot__col a {
  position: relative; align-self: flex-start;
  color: color-mix(in srgb, var(--cream) 78%, transparent);
  font-size: 0.95rem; transition: color 0.15s ease;
}
.foot__col a::after {
  content: "";
  position: absolute; left: 0; right: 0; bottom: -3px;
  height: 1px; background: var(--accent);
  transform: scaleX(0); transform-origin: left;
  transition: transform 0.28s var(--ease-out);
}
.foot__col a:hover { color: #fff; }
.foot__col a:hover::after { transform: scaleX(1); }
.foot__base {
  max-width: var(--maxw); margin: 1.5rem auto 0;
  display: flex; justify-content: space-between; gap: 1rem; flex-wrap: wrap;
  font-size: 0.85rem; color: color-mix(in srgb, var(--cream) 58%, transparent);
}

/* ─────────────── Responsive ─────────────── */
@media (max-width: 900px) {
  .nav__links { display: none; }
  .hero { grid-template-columns: 1fr; text-align: center; padding-top: 1.5rem; }
  .hero::before { inset: -10% -30% auto auto; width: 120vw; height: 70%; }
  .hero__sub { margin-left: auto; margin-right: auto; }
  .prompt { margin-left: auto; margin-right: auto; }
  .prompt__chips { justify-content: center; }
  .hero__fineprint, .hero__trust { justify-content: center; }
  .hero__device { margin-top: 1.5rem; }
  .steps { grid-template-columns: 1fr; }
  .app { grid-template-columns: 1fr; text-align: center; }
  .app__devices { order: -1; min-height: 360px; }
  .app__devices .phone { width: min(210px, 52vw); }
  .phone--back { transform: translateX(-26%) rotate(-8deg); }
  .phone--front { transform: translateX(14%) rotate(3deg); }
  .ticks { max-width: 28rem; margin-left: auto; margin-right: auto; }
  .ticks li { text-align: left; }
  .app__lead { margin-left: auto; margin-right: auto; }
}

@media (max-width: 640px) {
  /* comparison → stacked cards; the glass sheet dissolves (each row IS a card) */
  .compare {
    gap: 1rem;
    background: transparent;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    border: 0;
    border-radius: 0;
    padding: 0;
    box-shadow: none;
  }
  .compare__row--head { display: none; }
  /* fix-site-mobile-audit-sweep CRITICAL #1: the base `.compare--5col .compare__row` (0,2,0) otherwise
     out-specifies a plain `.compare__row` (0,1,0) here, so phones kept the 6-column desktop grid
     (values collided + the Patreon/Substack/Provecho columns clipped unreachable under overflow-x:clip).
     Match specificity so the stacked-card layout actually applies. */
  .compare--4col .compare__row,
  .compare--5col .compare__row {
    grid-template-columns: 1fr;
    border: 1px solid var(--line);
    border-radius: 16px;
    padding: 1rem 1.1rem;
    background: var(--card);
    box-shadow: var(--shadow-sm);
  }
  .compare__row::before { padding: 0 0 0.75rem; font-size: 1.05rem; font-weight: 800; }
  .compare__row .cell {
    display: flex; align-items: center; justify-content: space-between;
    padding: 0.5rem 0; border-top: 1px solid var(--line);
    text-align: left;
  }
  .compare__row .cell::before { content: attr(data-label); color: var(--faint); font-weight: 500; }
  .compare__row .cell--us { background: transparent; }
  .compare__row .cell--us::before { content: "Homescreen"; color: var(--accent-2); font-weight: 700; }
}

@media (max-width: 520px) {
  .hero__device { transform: scale(0.92); }
  .foot__inner { grid-template-columns: 1fr; gap: 2rem; }
  .btn--lg { width: 100%; }
  .prompt__field { flex-direction: column; align-items: stretch; }
  .prompt__go { justify-content: center; }
}

/* Tighten the header so the brand + "Log in" + accent CTA fit on one line on
   phones (otherwise the CTA overflows under overflow-x:hidden and clips). */
@media (max-width: 480px) {
  .nav { padding-left: 0.6rem; padding-right: 0.6rem; }
  .nav__inner { gap: 0.6rem; padding: 0.45rem 0.5rem 0.45rem 0.85rem; }
  .nav__cta { gap: 0.5rem; }
  .nav__cta .btn--sm { padding: 0.55rem 0.72rem; font-size: 0.86rem; }
  /* fix-mobile-landing-login (audit-2): a RETURNING creator on a phone MUST have a sign-in path — the
     primary CTA is sign-UP, not sign-in, and "Log in" was display:none here (no login path at all). Keep it
     visible + compact so brand + Log in + the locked "Start building free" CTA hold one line down to ~360px
     (the header padding/gaps already tighten above; the CTA text is founder-locked so we don't shorten it). */
  .nav__login { display: inline-flex; align-items: center; min-height: 44px; padding: 0 0.15rem; font-size: 0.86rem; }
  /* fix-landing-opacity-gate (same surface): the signed-in email (max-width 14rem) overflowed the nav edge
     @390 alongside the Dashboard pill + Sign out. There's no landing avatar to fall back to, so drop the
     email text on phones — the Dashboard pill + Sign out keep the account reachable, no clip. */
  .account__email { display: none; }
}

/* fix-mobile-landing-login: on the SMALLEST phones (~360px) brand + Log in + the locked "Start building
   free" CTA are a tight fit — tighten the header gaps/padding + a hair of CTA size so all three hold one
   line without the CTA clipping mid-word. 390px (the persona iPhone) already fits at the ≤480px sizing. */
@media (max-width: 380px) {
  .nav { padding-left: 0.5rem; padding-right: 0.4rem; }
  .nav__inner { gap: 0.45rem; padding: 0.45rem 0.4rem 0.45rem 0.7rem; }
  .nav__cta { gap: 0.4rem; }
  .nav__cta .btn--sm { padding: 0.5rem 0.62rem; font-size: 0.82rem; }
  .nav__login { font-size: 0.82rem; padding: 0; }
}

/* ─────────────── Touch ergonomics ───────────────
   Raise interactive targets to the ≥44px house floor (DESIGN.md §4) on
   touch-primary devices, without bulking up the pointer-precise desktop UI.
   Gated on pointer:coarse = input method, not screen width — a touchscreen
   laptop gets the larger targets; a trackpad desktop keeps the tight ones. */
@media (pointer: coarse) {
  .btn { min-height: 44px; }                          /* prompt "Build my app", nav + pricing CTAs */
  .chip { min-height: 44px; display: inline-flex; align-items: center; }  /* example-idea accelerators */
  .qa summary { min-height: 44px; }
  /* Opt-in: make the whole row a 44px tap target (clicking the label toggles). */
  .prompt__optin { min-height: 44px; align-items: center; }
  .prompt__optin input { margin-top: 0; }
  /* fix-site-mobile-audit-sweep MEDIUM #5: footer nav links (were ~24px) + the Privacy/Terms legal
     links (~16px) get the 44px touch floor. */
  .foot__col a, .foot__base a { min-height: 44px; display: inline-flex; align-items: center; }
}
/* fix-mobile-landing-login: the nav "Log in" is now VISIBLE at every width (a phone creator needs a
   sign-in path); the ≤480px block above already gives it the 44px touch target + compact treatment, so the
   old touch-and->480px special-case is no longer needed. */
@media (pointer: coarse) {
  .nav__login { min-height: 44px; display: inline-flex; align-items: center; }
}

/* ============================================================
   Build overlay — trial-gate → streamed build session
   ============================================================ */
/* ============================================================
   Builder workspace primitives (shared by build.html / builder.js)
   The build flow now lives on its own route — these primitives (meter,
   stages, checks, codestream, paywall, AppPreview slot) are reused there.
   ============================================================ */

/* Credits meter — free build budget remaining. Coral fill, warm track. */
.meter { margin: -0.4rem 0 1.3rem; }
.meter[hidden] { display: none; }
.meter__head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 0.75rem; margin-bottom: 0.4rem;
}
.meter__label { font-size: 0.82rem; font-weight: 600; color: var(--muted); }
.meter__count { font-size: 0.82rem; font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums; }
.meter__track {
  height: 7px; border-radius: 999px; background: var(--line);
  overflow: hidden;
}
.meter__fill {
  height: 100%; border-radius: 999px; background: var(--accent);
  transition: width 0.5s cubic-bezier(0.4, 0, 0.2, 1);
}
/* Running low (<= 20%): warm the bar toward deep coral. */
.meter.is-low .meter__fill { background: var(--accent-2); }
.meter.is-low .meter__count { color: var(--accent-2); }
/* Subscribed: no cap to show — a quiet confirmation instead of a bar. */
.meter.is-subscribed .meter__track { display: none; }
.meter.is-subscribed .meter__count { color: var(--accent); }

/* Out-of-credits paywall — a CENTERED GLASS MODAL (its own `.creditwall*` namespace). Deliberately NOT the
   bare `.paywall` class: that belongs to the Phase-3 FAN paywall SHEET (a fixed bottom-overlay, §8 below).
   The two used to share the `.paywall` class, so this card inherited the fan sheet's full-screen overlay
   rules → the squished/overlapping glitch. Glass card per DESIGN.md (glass-row/line, shadow-lg, glass-inset). */
.creditwall {
  position: fixed; inset: 0; z-index: 1100; display: flex; align-items: center; justify-content: center;
  padding: 1.2rem;
  background: rgba(33,26,21,0.42); backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px);
  animation: creditwall-in 0.16s ease-out;
}
.creditwall__card {
  position: relative; width: min(26rem, 100%); text-align: left;
  background: var(--glass-row); border: 1px solid var(--glass-line);
  border-radius: var(--r-card); box-shadow: var(--shadow-lg), var(--glass-inset);
  backdrop-filter: var(--blur); -webkit-backdrop-filter: var(--blur);
  padding: 1.6rem 1.5rem 1.4rem;
  animation: creditwall-pop 0.18s cubic-bezier(.2,.8,.3,1);
}
.creditwall__eyebrow {
  display: inline-block; font-size: 0.72rem; font-weight: 800;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--accent-2); margin-bottom: 0.55rem;
}
.creditwall__title { font-size: 1.35rem; letter-spacing: -0.02em; color: var(--title); margin: 0 0 0.5rem; }
.creditwall__body { color: var(--muted); line-height: 1.55; margin: 0 0 1.3rem; }
.creditwall__actions { display: flex; flex-direction: column; gap: 0.6rem; }
.creditwall__actions .btn { width: 100%; justify-content: center; } /* coral primary */
/* Grey secondary — clearly subordinate ghost/text button. */
.creditwall__wait {
  width: 100%; padding: 0.7rem 1rem; border-radius: 12px;
  background: none; border: 1px solid transparent; cursor: pointer;
  font: inherit; font-weight: 600; font-size: 0.92rem; color: var(--muted);
  transition: background-color 0.15s ease, color 0.15s ease;
}
.creditwall__wait:hover { color: var(--ink); background: rgba(0,0,0,0.03); }
.creditwall__wait:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.creditwall__note { font-size: 0.8rem; color: var(--faint); margin: 0.9rem 0 0; text-align: center; }
@keyframes creditwall-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes creditwall-pop { from { opacity: 0; transform: translateY(8px) scale(0.98); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .creditwall, .creditwall__card { animation: none; } }

/* Auth gate eyebrow (builder auth gate reuses this) — kept intact after the credit paywall moved to
   its own `.creditwall*` namespace. */
.paywall__eyebrow {
  display: inline-block; font-size: 0.72rem; font-weight: 800;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--accent-2);
  margin-bottom: 0.55rem;
}

/* Marketing opt-in — used on the hero (landing) + the builder auth gate. */
.signup__optin {
  display: flex; align-items: flex-start; gap: 0.55rem;
  font-size: 0.9rem; color: var(--ink); margin-bottom: 1.1rem; cursor: pointer;
}
.signup__optin input { margin-top: 0.18rem; accent-color: var(--accent); width: 1rem; height: 1rem; flex: none; }

/* Account chip — signed-in email + sign-out (header / top bar). */
.account { display: flex; align-items: center; gap: 0.6rem; }
.account[hidden] { display: none; }
.account__email {
  font-size: 0.86rem; font-weight: 600; color: var(--muted);
  max-width: 14rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* fix-builder-import-button-overflow part 3 — the BUILDER account chip: a monogram+email button that opens
   a small menu holding Sign out, instead of a bare "Sign out" button sitting in the top bar (founder-
   confirmed regression). Only the builder emits .account__chip/__menu (main.js keeps its inline chip
   elsewhere); scoped to .wb-top for safety. At ≤1760 the email text hides but the monogram remains as the
   chip identity, so there's still no standalone Sign out. */
.wb-top .account { position: relative; }
.wb-top .account__chip {
  display: inline-flex; align-items: center; gap: 0.5rem; cursor: pointer; font: inherit; color: var(--muted);
  border: 1px solid var(--line, #ECE3DC); border-radius: 999px; background: var(--glass-row, rgba(255,255,255,.7));
  padding: 0.28rem 0.7rem 0.28rem 0.3rem;
}
.wb-top .account__chip:hover { border-color: var(--accent, #d5643c); }
.wb-top .account__mono {
  flex: none; width: 1.7rem; height: 1.7rem; border-radius: 50%; display: grid; place-items: center;
  background: linear-gradient(150deg, var(--accent-hi, #ef7f4f), var(--accent-2, #c9552f));
  color: #fff; font-size: 0.8rem; font-weight: 800;
}
.wb-top .account__menu {
  position: absolute; top: calc(100% + 0.4rem); right: 0; z-index: 40; min-width: 12rem;
  display: flex; flex-direction: column; gap: 0.55rem; padding: 0.7rem;
  border: 1px solid var(--glass-line, rgba(255,255,255,.85)); border-radius: 14px;
  background: var(--glass, rgba(255,255,255,.94)); box-shadow: var(--e2); backdrop-filter: var(--blur);
}
.wb-top .account__menu[hidden] { display: none; }
.wb-top .account__menu-email { font-size: 0.8rem; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wb-top .account__menu .account__signout { width: 100%; }

/* Staged progress */
/* Build narration (builder-narrate-build) — one warm, design-framed line + a spinning coral ring,
   in place of the old technical stage/check list. Lines cross-fade as the real build progresses. */
@keyframes build-spin { to { transform: rotate(360deg); } }
.narrate { display: flex; flex-wrap: wrap; align-items: center; gap: 0.7rem; margin: 0.6rem 0 0; min-height: 1.7rem; }
.narrate[hidden] { display: none; }
/* build-timeout-resilience: a calm reassurance line shown below the narration only when a build runs long. */
.narrate__slow {
  flex-basis: 100%; margin-top: 0.15rem;
  font-size: 0.82rem; font-weight: 500; color: var(--muted); line-height: 1.4;
}
.narrate__slow[hidden] { display: none; }
.narrate__dot {
  flex: none; width: 1.15rem; height: 1.15rem;
  border-radius: 999px;
  border: 2px solid var(--line-2);
  border-top-color: var(--accent);
  animation: build-spin 0.8s linear infinite;
}
.narrate__line {
  font-weight: 700; letter-spacing: -0.01em; color: var(--ink);
  opacity: 0; transform: translateY(2px);
  transition: opacity 0.3s ease, transform 0.3s ease;
}
.narrate__line.is-in { opacity: 1; transform: none; }

/* "Here's the plan" card (builder-surface-the-plan) — a restrained glass card surfacing the plan the
   expander already drafted, shown while the app builds. Informational + dismissible; never blocks. */
.plancard {
  margin: 0.8rem 0 0;
  padding: 0.9rem 1rem;
  border: 1px solid var(--line);
  border-radius: 14px;
  background: color-mix(in srgb, var(--accent) 4%, #fff);
  box-shadow: var(--e1);
}
.plancard[hidden] { display: none; }
.plancard__head { display: flex; align-items: baseline; gap: 0.4rem; }
.plancard__kicker {
  font-size: 0.72rem; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase;
  color: var(--accent);
}
.plancard__name { font-weight: 800; letter-spacing: -0.01em; color: var(--ink); }
.plancard__dismiss {
  margin-left: auto; flex: none;
  width: 1.5rem; height: 1.5rem; line-height: 1;
  border: 0; border-radius: 999px; background: transparent;
  color: var(--faint); font-size: 1.1rem; cursor: pointer;
  transition: color 0.15s ease, background 0.15s ease;
}
.plancard__dismiss:hover { color: var(--ink); background: var(--line); }
.plancard__sections {
  list-style: none; margin: 0.6rem 0 0; padding: 0;
  display: flex; flex-wrap: wrap; gap: 0.4rem;
}
.plancard__section {
  font-size: 0.82rem; font-weight: 600; color: var(--ink);
  padding: 0.2rem 0.6rem;
  border: 1px solid var(--line-2); border-radius: 999px;
  background: #fff;
}
.plancard__feel {
  margin: 0.6rem 0 0; font-size: 0.86rem; color: var(--muted); font-style: italic;
}

/* plan-first (PR 3/3) — the "Plan first" toggle by the build prompt (default OFF). */
.wb__planfirst {
  display: inline-flex; align-items: center; gap: 0.5rem;
  margin: 0 0 0.5rem; cursor: pointer; user-select: none;
  font-size: 0.85rem; font-weight: 600; color: var(--muted);
}
.wb__planfirst-input { position: absolute; opacity: 0; width: 0; height: 0; }
.wb__planfirst-track {
  position: relative; flex: none; width: 2.1rem; height: 1.2rem;
  border-radius: 999px; background: var(--line-2);
  transition: background 0.2s ease;
}
.wb__planfirst-track::after {
  content: ""; position: absolute; top: 2px; left: 2px;
  width: calc(1.2rem - 4px); height: calc(1.2rem - 4px);
  border-radius: 999px; background: #fff; box-shadow: 0 1px 2px rgba(40, 30, 25, 0.25);
  transition: transform 0.2s ease;
}
.wb__planfirst-input:checked + .wb__planfirst-track { background: var(--accent); }
.wb__planfirst-input:checked + .wb__planfirst-track::after { transform: translateX(0.9rem); }
.wb__planfirst-input:focus-visible + .wb__planfirst-track {
  outline: 2px solid var(--accent); outline-offset: 2px;
}
.wb__planfirst-input:checked ~ .wb__planfirst-label { color: var(--ink); }

/* plan-first — the guided interview + plan-approval flow (rendered in the conversation rail). */
.pf { margin: 0.4rem 0; }
.pf__bar {
  display: flex; align-items: center; gap: 0.5rem;
  padding: 0 0.1rem 0.4rem;
}
.pf__title {
  font-size: 0.72rem; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase;
  color: var(--accent);
}
.pf__spacer { flex: 1 1 auto; }
.pf__close {
  flex: none; width: 1.5rem; height: 1.5rem; line-height: 1;
  border: 0; border-radius: 999px; background: transparent;
  color: var(--faint); font-size: 1.1rem; cursor: pointer;
}
.pf__close:hover { color: var(--ink); background: var(--line); }
.pf__card {
  padding: 1rem 1.1rem;
  border: 1px solid var(--line);
  border-radius: 14px;
  background: color-mix(in srgb, var(--accent) 4%, #fff);
  box-shadow: var(--e1);
}
.pf__progress {
  font-size: 0.72rem; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase;
  color: var(--faint); margin: 0 0 0.35rem;
}
.pf__q { font-size: 1.02rem; letter-spacing: -0.01em; color: var(--ink); margin: 0 0 0.8rem; }
.pf__chips { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.pf__chip {
  font-size: 0.88rem; font-weight: 600; color: var(--ink);
  padding: 0.45rem 0.8rem;
  border: 1.5px solid var(--line-2); border-radius: 999px;
  background: #fff; cursor: pointer;
  transition: border-color 0.15s ease, background 0.15s ease, color 0.15s ease;
}
.pf__chip:hover { border-color: var(--accent); }
.pf__chip.is-on { background: var(--accent); border-color: var(--accent); color: #fff; }
.pf__free {
  display: block; width: 100%; margin-top: 0.7rem;
  padding: 0.6rem 0.75rem;
  border: 1px solid var(--line-2); border-radius: 10px;
  font: inherit; color: var(--ink); background: #fff;
}
.pf__free--area { resize: vertical; min-height: 2.6rem; }
.pf__free:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; border-color: var(--accent); }
.pf__actions { display: flex; align-items: center; gap: 0.6rem; margin-top: 0.9rem; }
.pf__link {
  border: 0; background: transparent; cursor: pointer;
  font-size: 0.85rem; font-weight: 600; color: var(--muted); padding: 0.3rem 0.2rem;
}
.pf__link:hover { color: var(--ink); }
.pf__next { margin-left: auto; }
.pf__loading { display: flex; align-items: center; gap: 0.7rem; }
.pf__loading-label { font-weight: 700; color: var(--ink); }
/* plan-approval card */
.pf__plan-head { display: flex; align-items: baseline; gap: 0.4rem; }
.pf__kicker {
  font-size: 0.72rem; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase;
  color: var(--accent);
}
.pf__name { font-weight: 800; letter-spacing: -0.01em; color: var(--ink); }
.pf__intent { margin: 0.5rem 0 0; color: var(--ink); font-size: 0.95rem; }
.pf__sections { list-style: none; margin: 0.6rem 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: 0.4rem; }
.pf__section {
  font-size: 0.82rem; font-weight: 600; color: var(--ink);
  padding: 0.2rem 0.6rem; border: 1px solid var(--line-2); border-radius: 999px; background: #fff;
}
.pf__feel { margin: 0.6rem 0 0; font-size: 0.86rem; color: var(--muted); font-style: italic; }
.pf__creditnote { margin: 0.7rem 0 0; font-size: 0.78rem; color: var(--faint); }

/* Faux code stream (preview of "Writing your app") */
.codestream {
  margin: 1.1rem 0 0;
  background: var(--dark);
  color: var(--cream);
  border-radius: 14px;
  padding: 1rem 1.1rem;
  font-family: "SF Mono", ui-monospace, "Menlo", monospace;
  font-size: 0.78rem; line-height: 1.6;
  white-space: pre-wrap; word-break: break-word;
  max-height: 11rem; overflow: hidden;
  position: relative;
}
.codestream[hidden] { display: none; }
.codestream::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 2.5rem;
  background: linear-gradient(transparent, var(--dark));
}
.codestream .tok-key { color: #FF9C85; }
.codestream .tok-str { color: #8FE3A6; }
.codestream .tok-cmp { color: #FFD9CC; }

/* Action row (paywall + auth gate). */
.build__actions { display: flex; flex-wrap: wrap; gap: 0.7rem; }
.build__actions .btn { flex: 1 1 auto; }

@media (prefers-reduced-motion: reduce) {
  .narrate__dot { animation: none; }
  .narrate__line { transition: none; opacity: 1; transform: none; }
}

/* ============================================================
   AppPreview slot — the device-framed seam (apps/site/app-preview.js)
   The spike's real renderer replaces what lives in .appprev__screen;
   the frame, captions, and state faces below are the stub.
   ============================================================ */
.appprev { display: flex; flex-direction: column; align-items: center; gap: 0.65rem; }
/* site-preview-toggle-layout-jump: the stage holds the active frame and (in the /build pane, below) reserves
   a stable height so a Web↔Phone toggle swaps in place. Base rule is NEUTRAL — no reserved height — so
   app-home / manage / dashboard / .mc-preview collapse to the frame's own height exactly as before. */
.appprev__stage { display: flex; align-items: center; justify-content: center; width: 100%; }
.appprev__phone {
  /* Per-context knobs (overridden for the large /build phone below) so the
     bezel, screen radius, top safe area and status-bar type all scale with the
     device instead of staying a fixed pixel size that looks wrong when large. */
  --appprev-radius: 32px;       /* outer shell corner radius */
  --appprev-bezel: 8px;         /* black bezel thickness */
  --appprev-safe-top: 9.5%;     /* iOS top safe area (status bar + Island zone) */
  /* Status-bar type scales WITH the phone width (cqw resolves against this
     element — see container-type below), so the right icon cluster stays the
     same fraction of width at every preview size and never drifts into the
     Island. The rem cap only ever shrinks the font on the largest previews,
     which can only add clearance — never remove it. Do NOT add a lower clamp
     bound: a rem floor would re-introduce the fixed-unit drift this fixes. */
  --appprev-sb-fz: min(0.92rem, 4cqw);

  /* Establish a query container so the status bar's cqw units measure this
     phone's width rather than the viewport. */
  container-type: inline-size;
  position: relative;
  width: 100%; max-width: 200px;
  aspect-ratio: 9 / 19.3;
  background: #0d0d0f;
  border-radius: var(--appprev-radius);
  padding: var(--appprev-bezel);
  box-shadow: var(--shadow-lg);
}
.appprev__screen {
  position: relative;
  height: 100%;
  border-radius: calc(var(--appprev-radius) - var(--appprev-bezel) + 1px);
  overflow: hidden;
  background: var(--bg);
}

/* ── iOS safe areas: faux status bar + Dynamic Island + home indicator ──
   The status bar paints in the screen background so the device reads like a
   real screenshot, never a toy. The Island is centered in the top safe zone. */
.appprev__statusbar {
  position: absolute; top: 0; left: 0; right: 0; z-index: 4;
  height: var(--appprev-safe-top);
  display: flex; align-items: center; justify-content: space-between;
  /* Slightly tighter than the 8% it was: pushes the right cluster a touch
     closer to the edge (more iOS-like) and adds a little Island clearance. */
  padding: 0 7%;
  color: var(--ink);
  font-size: var(--appprev-sb-fz);
  font-weight: 600; letter-spacing: -0.01em;
  pointer-events: none;
}
.appprev__time { font-weight: 700; font-variant-numeric: tabular-nums; }
.appprev__sys { display: inline-flex; align-items: center; gap: 0.35em; }
.appprev__sys-ic { height: 0.86em; width: auto; display: block; }
.appprev__sys-ic--batt { height: 0.92em; }

.appprev__island {
  position: absolute; z-index: 5;
  top: calc(var(--appprev-safe-top) * 0.46); left: 50%;
  transform: translate(-50%, -50%);
  /* 30% (right edge at 65%) leaves a clear gap to the width-scaled right
     cluster while still reading as a real Dynamic Island. */
  width: 30%; aspect-ratio: 3.35 / 1;
  background: #000; border-radius: 999px;
}

/* The swappable content area — every state face + the live web-app iframe mount
   here, inset below the status bar so nothing paints under the Island. */
.appprev__content {
  position: absolute; left: 0; right: 0; bottom: 0;
  top: var(--appprev-safe-top);
  overflow: hidden;
}

/* Bottom home indicator — floats over content like real iOS. */
.appprev__home {
  position: absolute; z-index: 5; left: 50%; bottom: 1.6%;
  transform: translateX(-50%);
  width: 33%; height: 0.32rem; min-height: 3px; max-height: 5px;
  background: var(--ink); opacity: 0.28; border-radius: 999px;
}
.appprev__caption {
  min-height: 1.1em;
  font-size: 0.8rem; color: var(--faint); text-align: center;
  max-width: 18rem;
}

.appprev__state {
  height: 100%;
  display: flex; flex-direction: column;
  padding: 1.05rem 0.9rem;
  text-align: center;
}
.appprev__state.appprev__idle,
.appprev__state.appprev__ready,
.appprev__state.appprev__failed { justify-content: center; gap: 0.45rem; }

.appprev__glyph {
  width: 2.4rem; height: 2.4rem; margin: 0 auto 0.3rem;
  display: grid; place-items: center;
  border-radius: 14px;
  background: var(--peach); color: var(--accent);
  font-size: 1.2rem; font-weight: 800;
}
.appprev__glyph--warn { background: var(--accent-tint); color: var(--accent-2); }
.appprev__big { font-weight: 800; letter-spacing: -0.02em; font-size: 0.98rem; color: var(--ink); }
.appprev__small { font-size: 0.78rem; line-height: 1.4; color: var(--muted); }

/* Building face — skeleton + progress bar.
   fix-builder-building-skeleton-fill: the face is a full-height flex column; the skeleton block now
   GROWS to fill it (flex:1) with its rows distributed through the space, so a tall Web frame reads as a
   deliberate loading state instead of a top-clustered cluster over a dead gap. The progress bar stays
   pinned at the bottom (auto height, no grow). */
.appprev__building { justify-content: flex-start; gap: 0.55rem; }
.appprev__skel {
  flex: 1 1 auto; min-height: 0;
  display: flex; flex-direction: column; justify-content: space-evenly; gap: 0.55rem;
}
.appprev__skel-bar,
.appprev__skel-card,
.appprev__skel-row span {
  border-radius: 7px;
  background: linear-gradient(100deg, var(--line) 30%, var(--line-2) 50%, var(--line) 70%);
  background-size: 220% 100%;
  animation: appprev-shimmer 1.3s ease-in-out infinite;
}
.appprev__skel-bar { height: 0.7rem; }
.appprev__skel-bar--lg { height: 1.05rem; width: 72%; }
.appprev__skel-bar--sm { width: 52%; }
.appprev__skel-card { height: 3.4rem; border-radius: 12px; margin: 0.15rem 0; }
.appprev__skel-row { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0.45rem; margin-top: 0.2rem; }
.appprev__skel-row span { height: 2.1rem; }

.appprev__progress { margin-top: 0.9rem; }
.appprev__progress-track {
  height: 0.4rem; border-radius: 999px;
  background: var(--line); overflow: hidden;
}
.appprev__progress-fill {
  height: 100%; border-radius: 999px;
  background: var(--accent);
  transition: width 0.5s cubic-bezier(0.22, 1, 0.36, 1);
}
.appprev__progress-fill.is-indeterminate {
  width: 40%;
  animation: appprev-indeterminate 1.2s ease-in-out infinite;
}

/* Ready face — honest "preview coming" + a real payload summary */
.appprev__badge {
  align-self: center;
  font-size: 0.66rem; font-weight: 700; letter-spacing: 0.04em;
  color: var(--accent-2); background: var(--accent-tint);
  border-radius: 999px; padding: 0.28rem 0.6rem;
  margin-bottom: 0.25rem;
}
.appprev__summary {
  margin: 0.55rem 0 0; padding: 0.6rem 0.7rem;
  background: var(--peach); border-radius: 11px;
  display: flex; flex-direction: column; gap: 0.35rem;
  text-align: left;
}
.appprev__summary div { display: flex; justify-content: space-between; gap: 0.5rem; }
.appprev__summary dt { font-size: 0.68rem; color: var(--faint); margin: 0; }
.appprev__summary dd {
  font-size: 0.68rem; font-weight: 600; color: var(--ink); margin: 0;
  text-align: right; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Live preview — the sandboxed web renderer (app-runtime.js). The iframe is
   rendered at device resolution and scaled to fit the screen (transform set
   inline by JS); this box clips it to the rounded screen. */
/* fix-preview-and-served-dead-white (A): the sandbox mount + iframe fill was pure #fff, so when the app's
   content is shorter than the frame a dead-WHITE slab showed inside the preview card. Match the app canvas
   cream (same var(--bg) as .appprev__screen) so the fill below/around the content reads as the app's page. */
.appruntime {
  position: absolute; inset: 0; overflow: hidden; background: var(--bg);
  opacity: 0; transition: opacity 0.3s ease;
}
.appruntime.is-live { opacity: 1; }
.appruntime__frame {
  position: absolute; top: 0; left: 0;
  border: 0; transform-origin: 0 0; background: var(--bg);
}

/* Loading face while the renderer boots (CDN modules + in-browser transpile). */
.appprev__loading {
  height: 100%;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 0.7rem;
}
.appprev__spinner {
  width: 26px; height: 26px; border-radius: 50%;
  border: 3px solid var(--line); border-top-color: var(--accent);
  animation: appprev-spin 0.8s linear infinite;
}

@keyframes appprev-spin { to { transform: rotate(360deg); } }
@keyframes appprev-shimmer { from { background-position: 220% 0; } to { background-position: -220% 0; } }
@keyframes appprev-indeterminate {
  0%   { transform: translateX(-120%); }
  100% { transform: translateX(320%); }
}
@media (prefers-reduced-motion: reduce) {
  .appprev__skel-bar, .appprev__skel-card, .appprev__skel-row span { animation: none; }
  .appprev__progress-fill.is-indeterminate { animation: none; }
  .appprev__spinner { animation: none; }
}

@media (max-width: 520px) {
  .build__actions .btn { flex-basis: 100%; }
}

/* Hero marketing opt-in (landing) — subtle, under the prompt. */
.prompt__optin {
  display: flex; align-items: flex-start; gap: 0.5rem;
  margin: 0.7rem 0 0; max-width: 32rem;
  font-size: 0.85rem; color: var(--muted); cursor: pointer;
}
.prompt__optin input {
  margin-top: 0.18rem; accent-color: var(--accent);
  width: 0.95rem; height: 0.95rem; flex: none;
}

/* ============================================================
   Builder workspace — the dedicated two-pane page (build.html)
   Conversation rail (left) + large live preview (right). Follows
   DESIGN.md: Inter, warm paper, single coral accent, mobile-first.
   ============================================================ */
.wb-body {
  height: 100dvh;
  display: flex; flex-direction: column;
  overflow: hidden;
  background: var(--bg);
}

/* Top bar — brand · app name · account chip · Ship it */
.wb-top {
  flex: none;
  display: flex; align-items: center; gap: 1rem;
  padding: 0.7rem clamp(1rem, 3vw, 1.6rem);
  border-bottom: 1px solid var(--line);
  background: rgba(251, 250, 248, 0.92);
  backdrop-filter: blur(8px);
}
.wb-top .brand { flex: none; }
.wb-top__app {
  flex: 1 1 auto; min-width: 0;
  text-align: center;
  font-weight: 700; letter-spacing: -0.01em; color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* builder-rename-app-inline: the header app name is click-to-rename for a signed-in owner with an app —
   a quiet hover cue + pencil hint; while editing it gets a clear accent outline and the ellipsis is lifted. */
.wb-top__app[data-rename] { cursor: text; border-radius: 6px; padding: 0 0.35rem; transition: background-color 0.12s ease; }
.wb-top__app[data-rename]:hover { background: rgba(0,0,0,0.05); }
.wb-top__app[data-rename]:hover::after { content: "✎"; font-size: 0.72em; opacity: 0.55; margin-left: 0.35rem; }
.wb-top__app[data-editing] { overflow: visible; text-overflow: clip; outline: 2px solid var(--accent); outline-offset: 2px; background: #fff; color: var(--ink); }
.wb-top__app[data-editing]::after { content: none; }
.wb-top__right { flex: none; display: flex; align-items: center; gap: 0.7rem; }
/* The signed-in top bar overflowed at ~1600px windows and CLIPPED the Ship CTA (founder screenshot,
   2026-07-08). The email is the least load-bearing element — it yields before the primary action ever
   does. */
@media (max-width: 1760px) { .wb-top .account__email { display: none; } }
/* builder-manage-content-link: the "Manage content" button is a .btn, whose `display` overrides the
   UA [hidden] rule — so guard it explicitly (same pattern as .meter[hidden]/.account[hidden]) or it
   would show on a fresh unbound build. builder.js toggles the attribute on/off. */
[data-wb-manage][hidden] { display: none; }

.wb-ship-note {
  flex: none; margin: 0;
  padding: 0.6rem clamp(1rem, 3vw, 1.6rem);
  background: var(--peach); color: var(--accent-2);
  font-size: 0.85rem; font-weight: 600;
  border-bottom: 1px solid var(--accent-tint);
}
.wb-ship-note[hidden] { display: none; }

/* Mobile Preview / Chat tabs — hidden on desktop. */
.wb-tabs { display: none; }

/* Two-pane grid filling the remaining height. */
.wb {
  flex: 1 1 auto; min-height: 0;
  position: relative;
  display: grid;
  grid-template-columns: minmax(360px, 440px) 1fr;
  overflow: hidden;
}

/* LEFT RAIL — conversation + meter + chat */
.wb__rail {
  display: flex; flex-direction: column;
  min-height: 0;
  border-right: 1px solid var(--line);
  background: var(--bg);
  /* Safety net (founder-hit 2026-07-08): if the rail's stacked chrome ever exceeds the viewport
     (tall ladder + transcript + meter), the RAIL scrolls rather than clipping content off-screen.
     The convo keeps its own inner scroll for the chat; this only engages on overflow. */
  overflow-y: auto;
}
.wb__convo {
  flex: 1 1 auto; min-height: 0; overflow-y: auto;
  padding: clamp(1rem, 2.5vw, 1.5rem);
  display: flex; flex-direction: column; gap: 0.9rem;
}

/* fix-builder-chat-scroll-hijack: the quiet "↓ New messages" re-pin affordance. Shown only while the
   reader has scrolled up during a live build; sticks to the bottom of the transcript viewport and
   re-pins on click. Removed from the DOM whenever pinned, so it never leaves a resting row. */
.wb__new-activity {
  position: sticky; bottom: 0.25rem; align-self: center; z-index: 5;
  display: inline-flex; align-items: center; gap: 0.35rem;
  margin-top: -1rem; /* overlay the last message rather than pushing a full gap-row */
  padding: 0.4rem 0.9rem; border-radius: 999px;
  background: var(--accent); color: #fff;
  font: inherit; font-size: 0.8rem; font-weight: 600; line-height: 1;
  border: none; cursor: pointer; box-shadow: var(--shadow-acc);
}
.wb__new-activity:hover { filter: brightness(1.06); }
.wb__new-activity span { font-size: 0.9rem; }

/* Chat messages */
.msg { font-size: 0.95rem; line-height: 1.55; }
.msg--user {
  align-self: flex-end; max-width: 85%;
  background: var(--accent); color: #fff;
  border-radius: 16px 16px 4px 16px;
  padding: 0.65rem 0.9rem;
  white-space: pre-wrap; word-break: break-word;
  box-shadow: var(--shadow-acc);
}
.msg--assistant {
  align-self: flex-start; max-width: 96%;
  background: var(--card); border: 1px solid var(--line);
  border-radius: 16px 16px 16px 4px;
  padding: 0.9rem 1rem;
}
.msg--assistant h3 { font-size: 1.05rem; letter-spacing: -0.02em; margin-bottom: 0.3rem; }
.msg--assistant > p { color: var(--muted); font-size: 0.9rem; }
.wb-booting { color: var(--faint); font-size: 0.9rem; margin: 0; }

.turn__result { margin-top: 0.9rem; }
.turn__result[hidden] { display: none; }
.turn__result h3 { font-size: 1.05rem; letter-spacing: -0.02em; margin-bottom: 0.3rem; }
.turn__result > p { color: var(--muted); font-size: 0.9rem; }
/* #35 — the Cancel control while building + the Retry button on a recoverable failure. */
.turn__live { margin: 0.6rem 0 0; }
.turn__live[hidden] { display: none; }
.turn__retry { margin-top: 0.7rem; }

/* Post-build "what next" suggestion chips (builder-post-gen-suggestions). */
.suggest { margin-top: 0.9rem; }
.suggest__label {
  font-size: 0.72rem; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase;
  color: var(--faint); margin: 0 0 0.45rem;
}
.suggest__chips { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.suggest__chip {
  font-size: 0.85rem; font-weight: 600; color: var(--ink);
  padding: 0.4rem 0.8rem;
  border: 1.5px solid var(--line-2); border-radius: 999px;
  background: #fff; cursor: pointer;
  transition: border-color 0.15s ease, background 0.15s ease, color 0.15s ease;
}
.suggest__chip:hover { border-color: var(--accent); color: var(--accent); }
.suggest__chip:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Credits meter sits between the transcript and the chat input. */
.wb__meter { flex: none; margin: 0; padding: 0.85rem clamp(1rem, 2.5vw, 1.5rem) 0; }

/* Chat input — describe first, then iterate. */
.wb__chat {
  flex: none;
  padding: 0.8rem clamp(1rem, 2.5vw, 1.5rem) clamp(0.9rem, 2.5vw, 1.3rem);
  border-top: 1px solid var(--line);
  background: var(--bg);
}
.wb__chat-hint { margin: 0 0 0.5rem; font-size: 0.82rem; color: var(--muted); }
.wb__chat-hint[hidden] { display: none; }
/* #32 — empty-submit nudge: the hint turns accent + flashes once. */
.wb__chat-hint--nudge { color: var(--accent); font-weight: 600; animation: hs-nudge 0.32s ease; }

/* #30 — builder cold first-run: a compact "what now" + starter-idea chips. */
.wb-steps {
  list-style: none; counter-reset: wbstep;
  display: flex; flex-wrap: wrap; gap: 0.35rem 1rem;
  margin: 0.7rem 0 0; padding: 0;
  font-size: 0.82rem; font-weight: 600; color: var(--muted);
}
.wb-steps li { counter-increment: wbstep; display: flex; align-items: center; gap: 0.4rem; }
.wb-steps li::before {
  content: counter(wbstep);
  display: inline-flex; align-items: center; justify-content: center;
  width: 1.25rem; height: 1.25rem; border-radius: 999px;
  background: var(--peach); color: var(--accent);
  font-size: 0.72rem; font-weight: 700;
}
.wb-starters { display: flex; flex-wrap: wrap; align-items: center; gap: 0.45rem; margin-top: 0.85rem; }
.wb-starters__try { font-size: 0.82rem; color: var(--faint); font-weight: 600; margin-right: 0.1rem; }

/* Shared one-shot flash for the empty-prompt nudges (#32). */
@keyframes hs-nudge {
  0% { transform: translateX(0); }
  25% { transform: translateX(-3px); }
  75% { transform: translateX(3px); }
  100% { transform: translateX(0); }
}
@media (prefers-reduced-motion: reduce) {
  .wb__chat-hint--nudge, .prompt__hint--nudge { animation: none; }
}
.wb__chat-field {
  display: flex; align-items: flex-end; gap: 0.5rem;
  background: var(--card); border: 1px solid var(--line-2);
  border-radius: 20px; padding: 0.4rem 0.4rem 0.4rem 0.95rem;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.wb__chat-field:focus-within { border-color: var(--accent); box-shadow: var(--shadow-acc); }
.wb__chat-input {
  flex: 1 1 auto; min-width: 0; resize: none;
  border: 0; background: transparent; outline: none;
  font-family: var(--font); font-size: 1rem; line-height: 1.5; color: var(--ink);
  max-height: 7rem; padding: 0.45rem 0;
}
.wb__chat-input::placeholder { color: var(--faint); }
.wb__chat-input:disabled { opacity: 0.6; }
.wb__chat-field .btn {
  flex: none; width: 2.5rem; height: 2.5rem; padding: 0; border-radius: 50%;
}
.wb__chat-field .btn .btn__arrow { font-size: 1.15rem; }
.wb__chat-field .btn:disabled { opacity: 0.55; transform: none; }

/* RIGHT PANE — the live preview is the hero: large + central. */
.wb__preview {
  display: flex; align-items: center; justify-content: center;
  /* builder-edit-ui-polish: wrap so the Preview|Edit toggle (a full-width item, below) sits on its OWN
     row centered ABOVE the phone — a clean header over the device, not floating to its side. align-content
     keeps the toggle+phone block vertically centered. The IG caption/adjust stay flanking the phone (they
     are NOT full-width, so they wrap onto the phone's row). */
  flex-wrap: wrap; align-content: center;
  /* builder-edit-toggle-clip: when the wrapped content is taller than the pane, plain `center`
     spills it BOTH ways — the Preview|Edit toggle row (order -1, above the frame) gets shoved
     under the sticky top bar with no way to reach it. `safe` falls back to start-alignment on
     overflow so the toggle is always visible; supporting browsers only (harmless where ignored). */
  align-content: safe center;
  padding: clamp(1rem, 3vw, 2.5rem);
  background: var(--peach);
  min-height: 0; overflow: auto;
}
/* fix-builder-postbuild-screen-polish (defect 3): the container is capped to the SAME width in BOTH views
   (was 360 phone / 960 web) so the in-flow Web|Phone toggle right-aligns to a STABLE edge and never jumps
   sideways on a view switch — the reason it was previously absolute-anchored to the pane. The phone frame
   stays centered within it (align-items:center); only the container's outer cap changed. */
.wb__preview .appprev { width: 100%; max-width: min(100%, 960px); gap: 0.9rem; margin-inline: auto;
  /* site-preview-toggle-layout-jump: one source of truth for the stage height (the taller PHONE frame).
     Both frames cap to it and the stage reserves it, so a Web↔Phone toggle never changes the column
     height → the toggle above and caption below hold still (the founder-hit ~44px jump). */
  --wb-stage-h: min(74vh, 680px);
}
/* Reserve the stage height and center whichever frame is active within it (Web is shorter than Phone). */
.wb__preview .appprev__stage { min-height: var(--wb-stage-h); }
/* builder-webview-width: the preview slot is a shrink-to-content flex item in this wrapping row, so in
   Web view (which drops the phone's height×aspect-ratio) the frame collapsed to a ~phone-width sliver.
   Let the slot fill the pane; `.appprev` then caps itself (360 phone / 960 web) and centres via margin. */
.wb__preview [data-app-preview] { width: 100%; }
.wb__preview .appprev__phone {
  /* Larger device → thicker bezel, bigger radius, and a status bar sized to
     real iOS proportions with legible type. */
  --appprev-radius: 46px;
  --appprev-bezel: 11px;
  --appprev-safe-top: 8.2%;
  /* Inherit the base width-relative formula (min(0.92rem, 4cqw)) rather than a
     vw-based size: vw tracks the window, not the phone, so it drifted into the
     Island. cqw keeps the cluster proportional to THIS phone at any size. */

  width: auto; max-width: 100%;
  height: var(--wb-stage-h);
}
.wb__preview .appprev__caption { font-size: 0.85rem; }

/* Auth gate — covers both panes for a signed-out / direct hit. */
.wb-auth {
  position: absolute; inset: 0; z-index: 20;
  display: flex; align-items: center; justify-content: center;
  padding: clamp(1rem, 4vw, 2rem);
  overflow-y: auto;
  background: rgba(251, 250, 248, 0.86);
  backdrop-filter: blur(6px);
}
.wb-auth[hidden] { display: none; }
.wb-auth__card {
  width: min(30rem, 100%);
  background: var(--card); border: 1px solid var(--line-2);
  border-radius: 22px; box-shadow: var(--shadow-lg);
  padding: clamp(1.5rem, 4vw, 2.2rem);
}
.wb-auth__card h2 { font-size: clamp(1.4rem, 3vw, 1.8rem); letter-spacing: -0.03em; margin-bottom: 0.6rem; }
.wb-auth__card > p { color: var(--muted); margin-bottom: 1.1rem; }
.wb-auth__card .build__actions { margin-top: 0; }

/* ── Mobile: stack to Preview/Chat tabs (no cramped side-by-side) ── */
@media (max-width: 860px) {
  .wb-tabs {
    display: flex; flex: none;
    border-bottom: 1px solid var(--line);
    background: var(--bg);
  }
  .wb-tabs__btn {
    flex: 1 1 0; padding: 0.8rem 0.75rem;
    border: 0; background: transparent;
    font-family: var(--font); font-weight: 700; font-size: 0.92rem; color: var(--muted);
    cursor: pointer; border-bottom: 2px solid transparent;
    transition: color 0.15s ease, border-color 0.15s ease;
  }
  .wb-tabs__btn.is-active { color: var(--accent); border-bottom-color: var(--accent); }

  .wb { grid-template-columns: 1fr; }
  .wb__rail { border-right: 0; }
  .wb-top__app { display: none; }

  /* One pane at a time, driven by the active tab. */
  .wb[data-tab="preview"] .wb__rail { display: none; }
  .wb[data-tab="chat"] .wb__preview { display: none; }
  /* site-preview-toggle-layout-jump: shrink the reserved stage (and both frames) together on narrow. */
  .wb__preview .appprev { --wb-stage-h: min(60vh, 560px); }
  /* fix-ig-reveal-spacing: on a narrow (single-column) builder, STACK the reveal caption + adjust
     under the phone instead of flanking it — no horizontal overflow at phone widths. */
  .wb__preview { flex-direction: column; }
  .ig-caption, .ig-adjust { max-width: 100%; }
}

/* #fix-mobile-overflow (H5) — the builder top bar must FIT a phone with the primary "Ship it" CTA
   reachable (it was being pushed off-screen, scrollWidth ~700 @ 390). Drop the redundant Dashboard
   link (the brand logo already routes to /dashboard) and the account email, tighten gaps, and let the
   controls group shrink/wrap so nothing sits off-screen. Insights collapses to its icon. */
@media (max-width: 560px) {
  .wb-top { gap: 0.5rem; }
  .wb-top__right { gap: 0.4rem; min-width: 0; flex: 0 1 auto; flex-wrap: wrap; justify-content: flex-end; }
  .wb-top [data-wb-dashboard] { display: none; }
  .wb-top .account__email { display: none; }
}

/* Very narrow: collapse Insights to its live dot so the top bar stays one clean row. */
@media (max-width: 480px) {
  .wb-top__insights-text { display: none; }
  .wb-top__insights { padding-left: 0.7rem; padding-right: 0.7rem; }
}

/* ============================================================
   Pricing overlay — Free + Builder (100/200) credit plans
   ============================================================ */
.pricing-overlay {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: grid;
  place-items: center;
  padding: clamp(1rem, 4vw, 2.5rem);
  background: rgba(23, 18, 14, 0.55);
  backdrop-filter: blur(3px);
  overflow-y: auto;
}
.pricing-overlay[hidden] { display: none; }

.pricing {
  position: relative;
  width: 100%;
  max-width: 720px;
  background: var(--bg);
  border: 1px solid var(--line-2);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
  padding: clamp(1.5rem, 4vw, 2.5rem);
}
.pricing__close {
  position: absolute;
  top: 0.85rem;
  right: 0.95rem;
  width: 2rem;
  height: 2rem;
  border: 0;
  border-radius: 999px;
  background: var(--card);
  border: 1px solid var(--line-2);
  color: var(--muted);
  font-size: 1.25rem;
  line-height: 1;
  cursor: pointer;
}
.pricing__close:hover { color: var(--ink); border-color: var(--accent); }
.pricing__eyebrow {
  display: inline-block;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--accent-2);
  margin-bottom: 0.5rem;
}
.pricing__title { font-size: clamp(1.5rem, 3.4vw, 2rem); letter-spacing: -0.03em; margin-bottom: 0.4rem; }
.pricing__sub { color: var(--muted); margin-bottom: 0.6rem; font-size: 0.95rem; }
.pricing__meter {
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--ink);
  background: var(--peach);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 0.5rem 0.8rem;
  margin-bottom: 1.2rem;
  font-variant-numeric: tabular-nums;
}

.pricing__cards {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1rem;
}
.pcard {
  background: var(--card);
  border: 1px solid var(--line-2);
  border-radius: 16px;
  padding: 1.3rem 1.2rem;
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
}
.pcard--accent { border-color: var(--accent); box-shadow: var(--shadow-acc); }
.pcard.is-current { outline: 2px solid var(--accent-tint); }
.pcard__head { display: flex; align-items: center; justify-content: space-between; }
.pcard__name { font-weight: 800; letter-spacing: -0.02em; font-size: 1.05rem; }
.pcard__badge {
  font-size: 0.66rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--accent-2);
  background: var(--accent-tint);
  border-radius: 999px;
  padding: 0.15rem 0.5rem;
}
.pcard__price { display: flex; align-items: baseline; gap: 0.2rem; }
.pcard__amount { font-size: 2rem; font-weight: 800; letter-spacing: -0.03em; }
.pcard__per { color: var(--faint); font-weight: 600; font-size: 0.9rem; }
.pcard__blurb { color: var(--muted); font-size: 0.9rem; min-height: 2.4em; }
.pcard__cta { margin-top: auto; justify-content: center; }
.pcard__cta:disabled { opacity: 0.55; cursor: default; box-shadow: none; transform: none; }
.pcard__err { color: var(--accent-2); font-size: 0.8rem; margin-top: 0.4rem; }
.pcard__err[hidden] { display: none; }

/* Builder capacity toggle (100 / 200) */
.pcap {
  display: inline-flex;
  align-self: flex-start;
  background: var(--peach);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 3px;
  gap: 2px;
}
.pcap__btn {
  border: 0;
  background: transparent;
  color: var(--muted);
  font-weight: 700;
  font-size: 0.85rem;
  padding: 0.3rem 0.85rem;
  border-radius: 999px;
  cursor: pointer;
  font-variant-numeric: tabular-nums;
}
.pcap__btn.is-active { background: var(--accent); color: #fff; box-shadow: var(--shadow-acc); }

@media (max-width: 560px) {
  .pricing__cards { grid-template-columns: 1fr; }
  .pcard__blurb { min-height: 0; }
}

/* ============================================================
   Analytics dashboard — real usage → a real management view
   (DESIGN.md: Inter, coral, warm paper, premium, mobile-clean)
   ============================================================ */
/* Insights button in the workspace top bar */
.wb-top__insights { display: inline-flex; align-items: center; gap: 0.45rem; }
.wb-top__insights-dot {
  width: 0.5rem; height: 0.5rem; border-radius: 50%;
  background: var(--accent); flex: none;
  box-shadow: 0 0 0 0 rgba(244, 89, 58, 0.5);
  animation: dash-pulse 2.4s ease-out infinite;
}
@media (prefers-reduced-motion: reduce) { .wb-top__insights-dot { animation: none; } }

.dash-overlay {
  position: fixed;
  inset: 0;
  z-index: 55;
  display: grid;
  place-items: start center;
  padding: clamp(0.75rem, 4vw, 2.5rem);
  background: rgba(23, 18, 14, 0.55);
  backdrop-filter: blur(3px);
  overflow-y: auto;
}
.dash-overlay[hidden] { display: none; }

.dash {
  position: relative;
  width: 100%;
  max-width: 880px;
  background: var(--bg);
  border: 1px solid var(--line-2);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
  padding: clamp(1.25rem, 3.5vw, 2.2rem);
}
.dash__close {
  position: absolute;
  top: 0.85rem; right: 0.95rem;
  width: 2rem; height: 2rem;
  border: 1px solid var(--line-2);
  border-radius: 999px;
  background: var(--card);
  color: var(--muted);
  font-size: 1.25rem; line-height: 1;
  cursor: pointer;
}
.dash__close:hover { color: var(--ink); border-color: var(--accent); }

.dash__head {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 1rem; margin-bottom: 1.4rem; padding-right: 2rem;
}
.dash__eyebrow {
  display: inline-block;
  font-size: 0.72rem; font-weight: 700; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--accent-2);
  margin-bottom: 0.45rem;
}
.dash__title { font-size: clamp(1.45rem, 3.2vw, 1.95rem); letter-spacing: -0.03em; margin: 0; }
.dash__sub { color: var(--muted); font-size: 0.92rem; margin-top: 0.35rem; }

.dash__live {
  flex: none;
  display: inline-flex; align-items: center; gap: 0.4rem;
  font-size: 0.78rem; font-weight: 700; letter-spacing: 0.02em;
  color: var(--accent-2);
  background: var(--peach);
  border: 1px solid var(--accent-tint);
  border-radius: 999px;
  padding: 0.3rem 0.7rem;
  white-space: nowrap;
}
.dash__live.is-stale { color: var(--faint); background: var(--card); border-color: var(--line-2); }
.dash__live-dot {
  width: 0.5rem; height: 0.5rem; border-radius: 50%;
  background: var(--accent);
  animation: dash-pulse 2s ease-out infinite;
}
.dash__live.is-stale .dash__live-dot { background: var(--faint); animation: none; }
@media (prefers-reduced-motion: reduce) { .dash__live-dot { animation: none; } }

@keyframes dash-pulse {
  0%   { box-shadow: 0 0 0 0 rgba(244, 89, 58, 0.5); }
  70%  { box-shadow: 0 0 0 6px rgba(244, 89, 58, 0); }
  100% { box-shadow: 0 0 0 0 rgba(244, 89, 58, 0); }
}

/* Loading / empty / error center states */
.dash__center {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center; gap: 0.5rem;
  min-height: 320px; padding: 2rem 1rem;
}
.dash__glyph {
  font-size: 2rem; width: 3.4rem; height: 3.4rem;
  display: grid; place-items: center;
  background: var(--peach); border-radius: 18px; margin-bottom: 0.4rem;
}
.dash__big { font-size: 1.2rem; font-weight: 800; letter-spacing: -0.02em; margin: 0; }
.dash__muted { color: var(--muted); font-size: 0.92rem; max-width: 34ch; margin: 0; }
.dash__spinner {
  width: 2rem; height: 2rem; border-radius: 50%;
  border: 3px solid var(--line-2); border-top-color: var(--accent);
  animation: dash-spin 0.8s linear infinite; margin-bottom: 0.6rem;
}
@keyframes dash-spin { to { transform: rotate(360deg); } }

/* Stat cards */
.dash__stats {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 0.85rem;
  margin-bottom: 1.1rem;
}
.dash__stat {
  display: flex; flex-direction: column; gap: 0.15rem;
  background: var(--card); border: 1px solid var(--line);
  border-radius: 16px; padding: 1rem 1.1rem;
}
.dash__stat-num {
  font-size: clamp(1.7rem, 4vw, 2.2rem); font-weight: 800;
  letter-spacing: -0.03em; color: var(--ink);
  font-variant-numeric: tabular-nums; line-height: 1.05;
}
.dash__stat-label { font-size: 0.9rem; font-weight: 700; color: var(--ink); margin-top: 0.2rem; }
.dash__stat-sub { font-size: 0.78rem; color: var(--faint); }

/* Panels */
.dash__panel {
  background: var(--card); border: 1px solid var(--line);
  border-radius: 16px; padding: 1.1rem 1.2rem; margin-bottom: 1.1rem;
}
.dash__panel-head {
  display: flex; align-items: baseline; justify-content: space-between;
  margin-bottom: 0.9rem;
}
.dash__panel-head h3 { font-size: 0.95rem; font-weight: 700; letter-spacing: -0.01em; margin: 0; }
.dash__panel-total { font-size: 0.8rem; color: var(--faint); font-variant-numeric: tabular-nums; }

/* Sessions bar chart */
.dash__chart {
  display: flex; align-items: flex-end; gap: 0.5rem;
  height: 132px;
}
.dash__bar {
  flex: 1 1 0; min-width: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: flex-end;
  gap: 0.3rem; height: 100%;
}
.dash__bar-val {
  font-size: 0.72rem; font-weight: 700; color: var(--muted);
  font-variant-numeric: tabular-nums; min-height: 0.9rem;
}
.dash__bar-fill {
  width: 100%; max-width: 38px;
  background: linear-gradient(180deg, var(--accent), var(--accent-2));
  border-radius: 7px 7px 3px 3px;
  transition: height 0.45s cubic-bezier(0.22, 1, 0.36, 1);
}
.dash__bar-x { font-size: 0.7rem; color: var(--faint); white-space: nowrap; }

/* Top screens / features columns */
.dash__cols { display: grid; grid-template-columns: 1fr 1fr; gap: 1.1rem; }
.dash__panel--col { margin-bottom: 0; }
.dash__list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.45rem; }
.dash__row {
  position: relative;
  display: flex; align-items: center; gap: 0.6rem;
  padding: 0.5rem 0.7rem;
  border-radius: 10px;
  overflow: hidden;
  background: var(--bg);
  border: 1px solid var(--line);
}
.dash__row-bar {
  position: absolute; inset: 0 auto 0 0;
  background: var(--accent-tint);
  opacity: 0.55;
  border-radius: 10px;
  transition: width 0.45s cubic-bezier(0.22, 1, 0.36, 1);
  z-index: 0;
}
.dash__row-name {
  position: relative; z-index: 1;
  flex: 1 1 auto; min-width: 0;
  font-size: 0.88rem; font-weight: 600; color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.dash__row-count {
  position: relative; z-index: 1; flex: none;
  font-size: 0.85rem; font-weight: 700; color: var(--accent-2);
  font-variant-numeric: tabular-nums;
}
.dash__list-empty { padding: 0.5rem 0.2rem; font-size: 0.85rem; }

@media (max-width: 640px) {
  .dash__stats { grid-template-columns: 1fr; gap: 0.6rem; }
  .dash__stat { flex-direction: row; align-items: baseline; gap: 0.6rem; justify-content: space-between; }
  .dash__stat-sub { display: none; }
  .dash__cols { grid-template-columns: 1fr; }
  .dash__chart { height: 110px; }
  .dash__bar-fill { max-width: 26px; }
}

/* ============================================================
   PWA SHIP MECHANIC
   Standalone published-app host (/a/<id>), install bar, the add-to-home-screen
   help sheet, and the builder "Ship it" sheet. DESIGN.md: Inter, coral, warm
   paper, premium. The fan installs the CREATOR'S app — clean, never hypey.
   ============================================================ */

/* ── Standalone host (app.html) ───────────────────────────── */
.standalone-body { margin: 0; background: var(--bg); overflow: hidden; }
.standalone {
  position: fixed; inset: 0;
  display: flex; flex-direction: column;
  background: var(--bg);
}
/* The app renders full-bleed on a phone; on wide screens it's centred in a
   phone-width column so the shared 393-logical renderer stays ~native scale. */
.standalone__stage {
  position: relative;
  flex: 1 1 auto;
  width: 100%;
  margin: 0 auto;
  /* fix-preview-and-served-dead-white (B): the stage fill was pure #fff → a dead-white slab under a short
     app. Continue the app's own canvas: --served-canvas (app.js sets it from the record's backgroundColor)
     with the cream near-white as the fallback. */
  background: var(--served-canvas, var(--bg));
  overflow: hidden;
}
@media (min-width: 600px) {
  /* site-demo-fix-batch (Frame C): a phone-width app on desktop sat on RAW BLACK gutters (HIGH-severity
     audit finding). Present it deliberately instead — the centered column on a WARM DIMMED canvas that
     matches the site background, with subtle device framing (radius + soft shadow). Honest "phone app",
     not a letterboxed accident. (Responsive-fill desktop art-direction is a later slice.) */
  .standalone { background: #E7E1D9; }
  .standalone__stage {
    max-width: 440px;
    width: 100%;
    margin: max(0px, env(safe-area-inset-top)) auto 0;
    border-radius: 22px;
    box-shadow: 0 30px 70px -28px rgba(40, 25, 15, 0.30), var(--shadow-lg);
  }
  /* site-demo-fix-batch (Frame C state 1 / Q6): a RESPONSIVE app FILLS the desktop viewport — its own
     breakpoints express the layout (app-runtime unpins the mount off the same flag), so drop the warm
     phone-column canvas + the 440 cap + the device framing and let the stage run wide. */
  /* fix-preview-and-served-dead-white (B): a responsive app is capped at 1180 on a wide desktop; its side
     margins were pure #fff ("this should be like a web page"). Continue the app canvas instead of dead-white
     (full-width desktop art-direction stays a separate design decision). */
  .standalone[data-responsive="true"] { background: var(--served-canvas, var(--bg)); }
  .standalone[data-responsive="true"] .standalone__stage {
    max-width: min(1180px, 100%); border-radius: 0; box-shadow: none; margin-top: 0;
  }
}
/* Frame D: the unavailable/dead-end overlay — the brand line + the "Build your own app" CTA sit below the
   honest copy with clear separation; 44px target inherited from .btn. */
.standalone__errnote { margin-top: 0.35rem; font-size: 0.85rem; color: var(--muted); max-width: 22rem; }
.standalone__boot--error .standalone__errcta { margin-top: 0.9rem; text-decoration: none; }
.standalone__boot--error .btn + .standalone__errcta { margin-top: 0.6rem; }

/* Branded boot / error overlay over the app stage. */
.standalone__overlay {
  position: fixed; inset: 0; z-index: 30;
  display: grid; place-items: center;
  background: var(--bg);
  /* fix-served-app-blank-mount: `visibility` rides the transition (0s delay) so it flips to `hidden` only
     AFTER the opacity fade — the loading overlay is then FULLY non-rendering once the app is live, not just
     transparent. Guards the "app mounted but a residual opaque overlay covers it" blank class if opacity
     compositing is ever beaten (a stale-CSS/client edge); the fade in/out is unchanged. */
  visibility: visible;
  transition: opacity 0.35s ease, visibility 0s;
  padding: 1.5rem;
}
.standalone__overlay.is-hidden {
  opacity: 0; pointer-events: none;
  visibility: hidden; transition: opacity 0.35s ease, visibility 0s linear 0.35s;
}
.standalone__boot { display: flex; flex-direction: column; align-items: center; gap: 0.9rem; text-align: center; }
.standalone__mark {
  width: 3rem; height: 3rem; border-radius: 14px;
  display: grid; place-items: center; box-shadow: var(--shadow-acc);
  animation: hs-pulse 1.6s ease-in-out infinite;
}
.standalone__mark img { display: block; }
.standalone__bootmsg { color: var(--muted); font-size: 0.95rem; font-weight: 500; }
.standalone__boot--error { gap: 0.6rem; max-width: 22rem; }
.standalone__boot--error .standalone__mark { animation: none; }
.standalone__errhead { font-size: 1.25rem; font-weight: 800; letter-spacing: -0.02em; }
.standalone__errsub { color: var(--muted); font-size: 0.95rem; margin-bottom: 0.4rem; }
@keyframes hs-pulse { 0%,100% { transform: scale(1); } 50% { transform: scale(1.07); } }
@media (prefers-reduced-motion: reduce) { .standalone__mark { animation: none; } }

/* ── Install / notifications bar (bottom, in-browser) ─────── */
.installbar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 40;
  padding: 0.75rem clamp(0.75rem, 4vw, 1.25rem);
  padding-bottom: calc(0.75rem + env(safe-area-inset-bottom));
  background: rgba(251, 250, 248, 0.92);
  backdrop-filter: saturate(180%) blur(12px);
  border-top: 1px solid var(--line-2);
}
.installbar[hidden] { display: none; }
.installbar__inner {
  max-width: 560px; margin: 0 auto;
  display: flex; align-items: center; gap: 0.8rem;
}
.installbar__icon { width: 44px; height: 44px; border-radius: 11px; flex: none; box-shadow: var(--shadow-sm); }
.installbar__icon--brand { display: grid; place-items: center; background: var(--accent); }
.installbar__text { flex: 1 1 auto; min-width: 0; }
.installbar__title { font-weight: 700; font-size: 0.95rem; letter-spacing: -0.01em; }
.installbar__sub { color: var(--muted); font-size: 0.8rem; line-height: 1.35; }
.installbar__actions { flex: none; }
.installbar__close {
  flex: none; width: 1.6rem; height: 1.6rem; border: 0; background: transparent;
  color: var(--faint); font-size: 1.25rem; line-height: 1; cursor: pointer; border-radius: 999px;
}
.installbar__close:hover { color: var(--ink); }
@media (max-width: 460px) {
  .installbar__sub { display: none; }
}

/* ── Add-to-home-screen help sheet (iOS / desktop manual flow) ─ */
.sheet-overlay {
  position: fixed; inset: 0; z-index: 60;
  display: grid; place-items: end center;
  background: rgba(23, 18, 14, 0.55); backdrop-filter: blur(3px);
  padding: 0;
}
.sheet {
  position: relative;
  width: 100%; max-width: 520px;
  background: var(--bg);
  border-radius: 22px 22px 0 0;
  border: 1px solid var(--line-2);
  box-shadow: var(--shadow-lg);
  padding: clamp(1.4rem, 5vw, 2rem);
  padding-bottom: calc(1.6rem + env(safe-area-inset-bottom));
}
@media (min-width: 560px) {
  .sheet-overlay { place-items: center; padding: 2rem; }
  .sheet { border-radius: 22px; }
}
.sheet__close {
  position: absolute; top: 0.85rem; right: 0.95rem;
  width: 2rem; height: 2rem; border-radius: 999px;
  background: var(--card); border: 1px solid var(--line-2);
  color: var(--muted); font-size: 1.25rem; line-height: 1; cursor: pointer;
}
.sheet__eyebrow {
  display: inline-block; font-size: 0.72rem; font-weight: 700;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--accent-2); margin-bottom: 0.5rem;
}
.sheet__title { font-size: clamp(1.3rem, 3.4vw, 1.7rem); letter-spacing: -0.03em; margin-bottom: 1rem; }
.sheet__steps { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 1rem; counter-reset: step; }
.sheet__steps li { display: flex; gap: 0.85rem; align-items: flex-start; }
.sheet__stepnum {
  flex: none; counter-increment: step;
  width: 1.7rem; height: 1.7rem; border-radius: 999px;
  background: var(--accent); color: #fff; font-weight: 800; font-size: 0.85rem;
  display: grid; place-items: center;
}
.sheet__stepnum::before { content: counter(step); }
.sheet__steph { font-weight: 700; font-size: 0.98rem; }
.sheet__stepp { color: var(--muted); font-size: 0.88rem; line-height: 1.4; }
.sheet__note { margin-top: 1.1rem; color: var(--faint); font-size: 0.82rem; }
.sheet__lead { color: var(--muted); font-size: 0.92rem; line-height: 1.5; margin-bottom: 1.1rem; }
.sheet__actions { display: flex; flex-wrap: wrap; gap: 0.6rem; margin-bottom: 0.85rem; }
.sheet__divider {
  margin: 1.25rem 0 0.9rem; color: var(--faint);
  font-size: 0.72rem; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
}
.sheet__qr {
  width: 180px; max-width: 60%; margin: 0.25rem auto 0;
  background: #fff; padding: 0.6rem; border-radius: 14px; border: 1px solid var(--line-2);
}
.sheet__qr svg { display: block; width: 100%; height: auto; }
.sheet__shareic { display: inline-block; vertical-align: -0.18em; color: var(--accent-2); }

/* ── Builder "Ship it" sheet ──────────────────────────────── */
.ship-overlay {
  position: fixed; inset: 0; z-index: 50;
  display: grid; place-items: center;
  padding: clamp(1rem, 4vw, 2.5rem);
  background: rgba(23, 18, 14, 0.55); backdrop-filter: blur(3px);
  overflow-y: auto;
}
.ship-overlay[hidden] { display: none; }
.ship {
  position: relative; width: 100%; max-width: 640px;
  background: var(--bg); border: 1px solid var(--line-2);
  border-radius: var(--radius); box-shadow: var(--shadow-lg);
  padding: clamp(1.5rem, 4vw, 2.5rem);
}
.ship__close {
  position: absolute; top: 0.85rem; right: 0.95rem;
  width: 2rem; height: 2rem; border-radius: 999px;
  background: var(--card); border: 1px solid var(--line-2);
  color: var(--muted); font-size: 1.25rem; line-height: 1; cursor: pointer;
}
.ship__close:hover { color: var(--ink); border-color: var(--accent); }
.ship__eyebrow {
  display: inline-block; font-size: 0.72rem; font-weight: 700;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--accent-2); margin-bottom: 0.5rem;
}
.ship__title { font-size: clamp(1.4rem, 3.4vw, 1.9rem); letter-spacing: -0.03em; margin-bottom: 0.45rem; }
.ship__sub { color: var(--muted); font-size: 0.95rem; margin-bottom: 1.3rem; max-width: 38rem; }
/* fix-ship-publishes-sample-content: the honest "content didn't attach" banner. A calm amber caution card
   (not alarm-red — the app IS live, only the content needs a retry), on the glass system. */
.ship__warn {
  display: flex; flex-direction: column; align-items: flex-start; gap: 0.7rem;
  margin: 0 0 1.3rem; padding: 0.85rem 1rem; border-radius: 14px;
  background: color-mix(in srgb, #E8A317 12%, var(--glass-row));
  border: 1px solid color-mix(in srgb, #E8A317 40%, var(--glass-line));
}
.ship__warn p { margin: 0; font-size: 0.9rem; line-height: 1.45; color: var(--ink); }
.ship__warn strong { color: var(--title); }
/* fix-ship-empty-feed-guard: the empty-feed interstitial pairs two actions (Choose what to show / Ship anyway). */
.ship__warn-actions { display: flex; flex-wrap: wrap; gap: 0.6rem; }
.ship__spinner {
  width: 30px; height: 30px; border-radius: 50%;
  border: 3px solid var(--line); border-top-color: var(--accent);
  animation: appprev-spin 0.8s linear infinite; margin: 1rem 0;
}
.ship__grid {
  display: grid; grid-template-columns: auto 1fr; gap: 1.4rem; align-items: center;
  background: var(--card); border: 1px solid var(--line); border-radius: 16px;
  padding: 1.2rem; margin-bottom: 1.1rem;
}
.ship__qr {
  width: 148px; height: 148px; flex: none;
  background: #fff; border: 1px solid var(--line); border-radius: 12px; padding: 8px;
}
.ship__qr svg { width: 100%; height: 100%; display: block; }
.ship__detail { min-width: 0; display: flex; flex-direction: column; gap: 0.6rem; }
.ship__label { font-weight: 700; font-size: 0.9rem; }
.ship__url { display: flex; gap: 0.4rem; }
.ship__url-input {
  flex: 1 1 auto; min-width: 0;
  font-family: var(--font); font-size: 0.82rem; color: var(--muted);
  background: var(--bg); border: 1px solid var(--line-2); border-radius: 10px;
  padding: 0.5rem 0.7rem;
}
.ship__cta { justify-content: center; }
.ship__open { color: var(--accent-2); font-weight: 700; font-size: 0.88rem; }
.ship__open:hover { color: var(--accent); }
.ship__hint { color: var(--faint); font-size: 0.8rem; line-height: 1.4; }
.ship__push {
  display: flex; gap: 0.7rem; align-items: flex-start;
  background: var(--peach); border: 1px solid var(--accent-tint); border-radius: 14px;
  padding: 0.85rem 1rem; font-size: 0.88rem; color: var(--ink); margin-bottom: 1.1rem;
}
.ship__push-ic { font-size: 1.1rem; flex: none; line-height: 1.3; }
.ship__appstore {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  border: 1px dashed var(--line-2); border-radius: 14px; padding: 0.9rem 1.1rem;
}
.ship__as-title { font-weight: 700; font-size: 0.95rem; }
.ship__as-sub { color: var(--muted); font-size: 0.82rem; line-height: 1.4; }
.ship__appstore .btn { flex: none; }

/* ── One editing door (site-one-edit-door): link to the real content editor at /manage/<id> ── */
.ship__manage {
  display: flex; align-items: center; gap: 0.8rem;
  border: 1px solid var(--line-2); border-radius: 14px;
  padding: 0.85rem 1rem; margin-bottom: 1.1rem; background: var(--bg);
  text-decoration: none; color: var(--ink); transition: border-color 0.15s ease, background 0.15s ease;
}
.ship__manage:hover { border-color: var(--accent); background: var(--peach); }
.ship__manage:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.ship__manage-ic { font-size: 1.1rem; flex: none; color: var(--accent-2); line-height: 1.2; }
.ship__manage-copy { display: flex; flex-direction: column; gap: 0.15rem; flex: 1; min-width: 0; }
.ship__manage-title { font-weight: 700; font-size: 0.92rem; }
.ship__manage-sub { color: var(--muted); font-size: 0.82rem; line-height: 1.4; }
.ship__manage-arrow { flex: none; color: var(--accent-2); font-size: 1rem; }
@media (max-width: 540px) {
  .ship__grid { grid-template-columns: 1fr; justify-items: center; text-align: center; }
  .ship__detail { align-items: stretch; width: 100%; }
  .ship__appstore { flex-direction: column; align-items: stretch; text-align: left; }
}

/* ============================================================
   GLASS-FORWARD · SOFT LIGHT — material pass (DESIGN.md §2)
   Promotes Homescreen's OWN chrome + content cards to Liquid Glass on the
   near-white canvas: high-opacity frosted glass, a 1px specular light edge,
   an inner top highlight, and layered (ambient + key) elevation — never the
   old flat single-shadow look. Coral stays the one accent. This block is last
   so it wins over the earlier flat definitions; modifiers are re-asserted after
   each group so accent cues (e.g. the highlighted plan) survive.
   NOTE: this restyles CHROME only. The generated app inside the preview /
   standalone stage is app-runtime.js — untouched here.
   ============================================================ */

/* ── Frosted content cards & rows (sit on the near-white canvas) ── */
.step-card,
.qa,
.pcard,
.msg--assistant,
.dash__stat,
.dash__panel,
.wb-auth__card {
  background: var(--glass-row);
  backdrop-filter: var(--blur);
  -webkit-backdrop-filter: var(--blur);
  border: 1px solid var(--glass-line);
  box-shadow: var(--e2), var(--glass-inset);
}
/* Keep the highlighted-plan + assistant-bubble cues after the group. */
.pcard--accent {
  border-color: color-mix(in srgb, var(--accent) 45%, var(--glass-line));
  box-shadow: var(--e-accent), var(--e2);
}
.pcard.is-current { outline: 2px solid var(--accent-tint); }
.msg--assistant { border-radius: 16px 16px 16px 4px; }

/* ── Floating chrome — the builder top bar sits over the near-white canvas,
      so lighter glass keeps body-AA. ── */
.wb-top {
  background: var(--glass-chrome);
  backdrop-filter: var(--blur-chrome);
  -webkit-backdrop-filter: var(--blur-chrome);
  border-bottom: 1px solid var(--glass-line);
  box-shadow: var(--e1);
}
/* The install bar floats over UNKNOWN content (the live app, dark headers, or
   the dark desktop margins), and it carries body text — so it must be a
   near-opaque frosted surface (≥0.7), never see-through low-opacity glass. */
.installbar {
  background: color-mix(in srgb, var(--bg) 92%, transparent);
  backdrop-filter: var(--blur-chrome);
  -webkit-backdrop-filter: var(--blur-chrome);
  border-top: 1px solid var(--glass-line);
  box-shadow: 0 -10px 30px -18px rgba(40,30,25,.3);
}

/* ── Elevated modal shells (sit on a dark scrim) — solid near-white so body
      copy stays AA, but with a specular edge + inner highlight + layered key
      shadow so they read as crafted glass panes, not flat 2020 cards. ── */
.pricing,
.ship,
.sheet,
.dash {
  border: 1px solid var(--glass-line);
  box-shadow: var(--shadow-lg), var(--glass-inset);
}

/* ── The builder rail + preview pane: keep the calm canvas behind the glass. ── */
.wb-body,
.wb__rail,
.wb__chat,
.wb__meter { background: transparent; }
.wb-body { background: var(--app-bg); background-color: var(--bg); }
.wb__preview {
  background:
    radial-gradient(90% 60% at 50% 0%, color-mix(in srgb, var(--accent) 8%, transparent), transparent 60%),
    var(--bg);
}

/* ── Chat input field → glass, matching the hero prompt. ── */
.wb__chat-field {
  background: var(--glass-row);
  backdrop-filter: var(--blur);
  -webkit-backdrop-filter: var(--blur);
  border: 1px solid var(--glass-line);
  box-shadow: var(--e1), var(--glass-inset);
}
.wb__chat-field:focus-within { border-color: var(--accent); box-shadow: var(--e-accent); }

/* ── Standalone PWA host: calm canvas + frosted boot/error overlay.
      Near-opaque so it still masks the load flash (incl. the dark desktop
      margins) while reading as frosted glass. ── */
.standalone__overlay {
  background: color-mix(in srgb, var(--bg) 92%, transparent);
  backdrop-filter: var(--blur-chrome);
  -webkit-backdrop-filter: var(--blur-chrome);
}
.standalone__mark { border-radius: 14px; box-shadow: var(--e-accent); }

/* ============================================================
   CREATOR DASHBOARD (logged-in) — "Rail + Scalable Stream" (D3 + D2 metric).
   Net-new shapes (left rail · Recents mini-card · horizontal app card) assembled ENTIRELY
   from the locked Glass-Forward · Soft Light tokens. One coral accent; depth from the glass
   shadow/light system, never borders/fills. Figures use --ink / --accent-2 (AA on glass).
   ============================================================ */
.dboard-body { background: var(--app-bg); min-height: 100vh; }
.dboard-root { min-height: 100vh; }

/* Signed-out gate (auth-first) */
.dboard-gate {
  min-height: 100vh; display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 1rem; text-align: center; padding: 2rem;
}
.dboard-gate .brand { font-size: 1.4rem; margin-bottom: 0.5rem; }
.dboard-gate__title { font-family: var(--font); font-weight: 800; letter-spacing: -0.03em; font-size: 2rem; color: var(--title); }
.dboard-gate__sub { color: var(--muted); max-width: 28rem; }

/* Shell grid: rail + main */
.dboard { display: grid; grid-template-columns: 260px minmax(0, 1fr); min-height: 100vh; }
.dboard__main { padding: clamp(1.25rem, 3vw, 2.5rem); padding-bottom: calc(2.5rem + env(safe-area-inset-bottom)); min-width: 0; }

/* ---- 1. Left rail (frosted chrome) ---- */
.rail {
  position: sticky; top: 0; align-self: start; height: 100vh; box-sizing: border-box;
  display: flex; flex-direction: column; gap: 1.1rem; padding: 1.4rem 1.1rem;
  padding-top: calc(1.4rem + env(safe-area-inset-top));
  background: var(--glass-chrome); -webkit-backdrop-filter: var(--blur-chrome); backdrop-filter: var(--blur-chrome);
  border-right: 1px solid var(--glass-line); box-shadow: var(--e1);
}
.rail__brand { padding: 0.1rem 0.35rem 0.2rem; }
.rail__nav { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.15rem; }
.rail__link {
  display: flex; align-items: center; gap: 0.6rem; width: 100%; box-sizing: border-box;
  font-family: var(--font); font-weight: 700; font-size: 0.94rem; color: var(--muted);
  background: transparent; border: 0; border-radius: 12px; padding: 0.6rem 0.7rem; cursor: pointer;
  text-decoration: none; text-align: left; transition: background 0.15s ease, color 0.15s ease;
}
.rail__link:hover { color: var(--ink); background: color-mix(in srgb, var(--accent) 7%, transparent); }
.rail__link.is-active { color: var(--accent-2); background: var(--peach); }
.rail__ico { width: 1.1rem; text-align: center; opacity: 0.85; }
.rail__search { padding: 0 0.15rem; }
.rail__search-input {
  width: 100%; box-sizing: border-box; font-family: var(--font); font-size: 0.9rem; color: var(--ink);
  background: var(--glass-row); border: 1px solid var(--glass-line); border-radius: 12px;
  padding: 0.55rem 0.75rem; box-shadow: var(--glass-inset);
}
.rail__search-input:focus { outline: none; border-color: var(--accent); box-shadow: var(--e-accent); }
.rail__section { display: flex; flex-direction: column; gap: 0.45rem; }
.rail__label { font-size: 0.72rem; font-weight: 800; letter-spacing: 0.06em; text-transform: uppercase; color: var(--faint); margin: 0 0.35rem; }
.rail__recents { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.35rem; }
.rail__recent {
  display: flex; align-items: center; gap: 0.6rem; padding: 0.4rem 0.45rem; border-radius: 12px; cursor: pointer;
  transition: background 0.15s ease;
}
.rail__recent:hover { background: color-mix(in srgb, var(--accent) 7%, transparent); }
.rail__recent-thumb { width: 1.9rem; height: 1.9rem; flex: none; border-radius: 9px; font-size: 0.8rem; }
.rail__recent-name { font-size: 0.88rem; font-weight: 600; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rail__recent-empty, .rail__recent--skel { color: var(--faint); font-size: 0.82rem; padding: 0.35rem 0.45rem; list-style: none; }
.rail__recent--skel .appprev__skel-card { height: 1.9rem; width: 100%; }
.rail__build { width: 100%; margin-top: auto; }
.rail__account { padding-top: 0.4rem; border-top: 1px solid var(--line); }
.dboard-account { display: flex; align-items: center; gap: 0.55rem; }
.dboard-account__avatar {
  width: 2rem; height: 2rem; flex: none; border-radius: 50%; display: grid; place-items: center;
  font-weight: 800; font-size: 0.85rem; color: #fff;
  background: linear-gradient(150deg, var(--accent-hi), var(--accent) 60%, var(--accent-2));
}
.dboard-account .account__email { flex: 1 1 auto; }
.dboard-account__settings { flex: none; }
.dboard-account__signout { flex: none; }

/* ---- 2. Describe→Build hero ---- */
.dhero { display: flex; flex-direction: column; gap: 0.9rem; margin-bottom: 1.8rem; }
.dhero__title { font-family: var(--font); font-weight: 800; letter-spacing: -0.03em; font-size: clamp(2rem, 4vw, 3rem); color: var(--title); margin: 0; }
.dhero__prompt { max-width: 40rem; margin: 0; }
.dhero__prompt .prompt__input { min-height: 3.2rem; }
.dhero__chips { margin-top: 0; }

/* ---- 3. Your-apps gallery (two-up scalable grid) ---- */
.gallery { display: flex; flex-direction: column; gap: 0.9rem; }
.gallery__head { display: flex; align-items: baseline; gap: 0.5rem; }
.gallery__title { font-family: var(--font); font-weight: 800; font-size: 0.95rem; letter-spacing: 0.01em; color: var(--title); margin: 0; }
.gallery__count { color: var(--faint); font-weight: 700; }
.gallery__grid { list-style: none; margin: 0; padding: 0; display: grid; gap: 1rem; grid-template-columns: repeat(auto-fill, minmax(340px, 1fr)); }
.gallery__notice {
  grid-column: 1 / -1; background: var(--glass-row); border: 1px solid var(--glass-line); border-radius: var(--r-card);
  box-shadow: var(--e1), var(--glass-inset); padding: 1rem 1.2rem; color: var(--muted);
  -webkit-backdrop-filter: var(--blur); backdrop-filter: var(--blur);
}

/* ---- the horizontal app card (fused PROUD + MANAGEMENT + RE-ENGAGEMENT) ---- */
.appcard { list-style: none; }
.appcard__inner {
  display: grid; grid-template-columns: 92px minmax(0, 1fr); gap: 1rem; height: 100%; box-sizing: border-box;
  background: var(--glass-row); -webkit-backdrop-filter: var(--blur); backdrop-filter: var(--blur);
  border: 1px solid var(--glass-line); border-radius: var(--r-card); box-shadow: var(--e2), var(--glass-inset);
  padding: 1rem;
}
/* LEFT — small supporting branded preview (NOT the focal point) */
.appcard__preview { align-self: start; }
.appcard__thumb { width: 92px; height: 122px; border-radius: var(--r-thumb); }
/* RIGHT — focal: name + metric */
.appcard__body { min-width: 0; display: flex; flex-direction: column; gap: 0.6rem; }
.appcard__head { display: flex; flex-direction: column; gap: 0.15rem; }
.appcard__name { font-family: var(--font); font-weight: 800; letter-spacing: -0.02em; font-size: 1.18rem; color: var(--title); margin: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.appcard__live { font-size: 0.78rem; font-weight: 600; color: var(--muted); text-decoration: none; display: inline-flex; align-items: center; gap: 0.35rem; }
.appcard__live:hover { color: var(--accent-2); }
.appcard__dot { width: 0.45rem; height: 0.45rem; border-radius: 50%; background: var(--accent); flex: none; box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent); }
/* metric — the focal figure (AA on glass) */
.appcard__stats { display: flex; align-items: flex-end; gap: 1.1rem; }
.appcard__stat { display: flex; flex-direction: column; }
.appcard__stat-num { font-family: var(--font); font-weight: 800; font-size: 1.75rem; line-height: 1; color: var(--ink); letter-spacing: -0.02em; }
.appcard__stat-label { font-size: 0.72rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--faint); margin-top: 0.2rem; }
.appcard__spark { display: flex; align-items: flex-end; gap: 2px; height: 2.2rem; margin-left: auto; min-width: 70px; }
.appcard__spark-bar { width: 5px; flex: 1 1 auto; max-width: 7px; border-radius: 2px; background: color-mix(in srgb, var(--accent) 78%, #fff); }
.appcard__metric-sub { font-size: 0.74rem; color: var(--faint); margin: -0.15rem 0 0; }
.appcard__stale { color: var(--accent-2); font-weight: 700; }
.appcard__metric-note { font-size: 0.84rem; color: var(--muted); margin: 0.1rem 0; line-height: 1.4; }
.appcard__stats--skel { gap: 0.5rem; flex-direction: column; align-items: stretch; }
/* locked paid-loop slot — leaves room, ships later WITHOUT reflow */
.appcard__grow {
  display: flex; align-items: center; gap: 0.45rem; font-size: 0.8rem; font-weight: 600; color: var(--faint);
  background: color-mix(in srgb, var(--accent) 5%, transparent); border: 1px dashed var(--line-2);
  border-radius: 12px; padding: 0.5rem 0.7rem; margin-top: auto;
}
.appcard__lock { opacity: 0.7; }
/* icon-only quick actions (aria-label + tooltip on each — a11y mitigation) */
/* #fix-mobile-overflow (H4) — wrap the icon-action row so the rightmost actions (Manage / Share /
   Analytics) never run off a narrow card; every action stays on-screen + tappable on a phone. */
.appcard__actions { display: flex; flex-wrap: wrap; gap: 0.3rem; }

/* M4 — branded 404 page (404.html). Centered brand lockup + message + a way home. */
.notfound {
  min-height: 100vh; box-sizing: border-box;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 0.9rem; text-align: center; padding: 2rem 1.2rem;
  background: var(--app-bg, #FBF8F5);
}
/* glass card so the 404 speaks the same material language as the site */
.notfound__panel {
  display: flex; flex-direction: column; align-items: center; gap: 0.9rem;
  background: var(--glass-row);
  backdrop-filter: var(--blur);
  -webkit-backdrop-filter: var(--blur);
  border: 1px solid var(--glass-line);
  border-radius: var(--r-card);
  box-shadow: var(--e2), var(--glass-inset);
  padding: clamp(2rem, 6vw, 3.2rem) clamp(1.6rem, 6vw, 3.6rem);
  max-width: 34rem;
}
.notfound__actions { display: flex; gap: 0.8rem; flex-wrap: wrap; justify-content: center; }
.notfound .brand { font-size: 1.4rem; margin-bottom: 0.4rem; }
.notfound__title {
  font-family: var(--font); font-weight: 800; letter-spacing: -0.03em;
  font-size: clamp(1.8rem, 5vw, 2.6rem); color: var(--title); margin: 0;
}
.notfound__sub { color: var(--muted); max-width: 26rem; margin: 0 0 0.6rem; line-height: 1.55; }

/* C1 — checkout confirm/summary step (before the live Stripe redirect). */
.pricing--confirm { max-width: 30rem; }
.pconfirm { display: flex; flex-direction: column; gap: 0.5rem; margin: 0.9rem 0 0.2rem; }
.pconfirm__row { display: flex; justify-content: space-between; align-items: baseline; gap: 1rem; }
.pconfirm__k { color: var(--muted); font-weight: 600; font-size: 0.92rem; }
.pconfirm__v { color: var(--ink); font-weight: 700; }
.pricing__fineprint { color: var(--faint); font-size: 0.85rem; line-height: 1.5; margin: 0.3rem 0 1rem; }
.pconfirm__actions { display: flex; justify-content: flex-end; gap: 0.6rem; }
.iaction {
  width: 2.1rem; height: 2.1rem; min-width: 44px; min-height: 44px; display: grid; place-items: center;
  border: 1px solid var(--glass-line); border-radius: 11px; background: var(--card); color: var(--muted);
  cursor: pointer; font-size: 1rem; transition: color 0.15s ease, border-color 0.15s ease, background 0.15s ease;
}
.iaction:hover { color: var(--accent-2); border-color: var(--accent); background: var(--peach); }

/* skeleton card */
.appcard--skel .appcard__inner { box-shadow: var(--e1), var(--glass-inset); }
.appcard--skel .appprev__skel-card { height: 122px; width: 92px; }

/* the in-grid "+ New app" tile (dashed) */
.appcard--new .appcard__new {
  width: 100%; height: 100%; min-height: 9rem; box-sizing: border-box;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 0.4rem; text-align: center;
  background: transparent; border: 1.5px dashed var(--line-2); border-radius: var(--r-card); cursor: pointer;
  color: var(--muted); font-family: var(--font); padding: 1.25rem; transition: border-color 0.15s ease, color 0.15s ease, background 0.15s ease;
}
.appcard--new .appcard__new:hover { border-color: var(--accent); color: var(--accent-2); background: color-mix(in srgb, var(--accent) 5%, transparent); }
.appcard__new-plus { font-size: 1.6rem; font-weight: 700; line-height: 1; color: var(--accent); }
.appcard__new-label { font-weight: 800; font-size: 1rem; }
.appcard__new-sub { font-size: 0.82rem; color: var(--faint); max-width: 18rem; }
.appcard--new-lg { grid-column: 1 / -1; }
.appcard--new-lg .appcard__new { min-height: 13rem; }

/* shared thumb (icon over the app's accent, or a monogram chip) */
.thumb {
  display: grid; place-items: center; overflow: hidden;
  background: linear-gradient(150deg, color-mix(in srgb, var(--app-accent, var(--accent)) 22%, #fff), color-mix(in srgb, var(--app-accent, var(--accent)) 7%, #fff));
  border: 1px solid var(--glass-line);
}
.thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.thumb--shot { background: #fff; } /* a self-captured screenshot sits on white, not the accent */
.thumb--mono { font-family: var(--font); font-weight: 800; color: var(--app-accent, var(--accent)); }

/* text-button link + toast */
.dlink { background: none; border: 0; padding: 0; color: var(--accent-2); font: inherit; font-weight: 700; cursor: pointer; text-decoration: underline; }
.dtoast {
  position: fixed; left: 50%; bottom: 1.5rem; transform: translate(-50%, 1rem); opacity: 0; pointer-events: none;
  background: var(--glass-chrome); -webkit-backdrop-filter: var(--blur-chrome); backdrop-filter: var(--blur-chrome);
  border: 1px solid var(--glass-line); box-shadow: var(--e2); border-radius: 999px; padding: 0.6rem 1.1rem;
  font-weight: 700; font-size: 0.88rem; color: var(--ink); transition: opacity 0.2s ease, transform 0.2s ease; z-index: 1000;
}
.dtoast.is-on { opacity: 1; transform: translate(-50%, 0); }

/* focus-visible rings (keyboard) — coral accent, not just hover */
.rail__link:focus-visible, .rail__recent:focus-visible, .iaction:focus-visible, .appcard__new:focus-visible,
.chip:focus-visible, .dlink:focus-visible, .appcard__live:focus-visible, .rail__search-input:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 2px;
}

/* responsive: rail → top bar on mobile; gallery → one column */
@media (max-width: 880px) {
  .dboard { grid-template-columns: 1fr; }
  /* #38 — the rail is a slim, NON-sticky top bar on a phone: it must not eat the
     viewport. (Sticky here would pin the whole chrome over the content.) */
  .rail {
    position: static; height: auto; flex-direction: row; flex-wrap: wrap; align-items: center; gap: 0.5rem;
    padding: 0.7rem 0.9rem; border-right: 0; border-bottom: 1px solid var(--glass-line);
  }
  .rail__brand { padding: 0.1rem 0.3rem; }
  .rail__nav { flex-direction: row; flex: 1 1 auto; gap: 0.1rem; }
  .rail__link { font-size: 0.86rem; padding: 0.4rem 0.5rem; }
  .rail__build { width: auto; margin: 0 0 0 auto; }
  /* #38 — collapse Recents on mobile: the gallery below already lists every app, so
     the rail no longer pushes the hero + first cards below the fold. */
  .rail__section { display: none; }
  /* #38 — compact the account to one slim row (email truncates; upgrade lives in Settings). */
  .rail__account { width: 100%; order: 6; border-top: 0; padding-top: 0.2rem; }
  .rail__account .account__email { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  /* #37 — search is the mobile entry point (no `/` shortcut on touch): an
     always-visible field, with the toggle button dropped. */
  .rail__search { width: 100%; order: 5; }
  .rail__search[hidden] { display: block; }
  [data-search-toggle] { display: none; }
  .gallery__grid { grid-template-columns: 1fr; }
}

@media (prefers-reduced-motion: reduce) {
  .rail__link, .iaction, .appcard__new, .chip, .dtoast, .appcard__inner { transition: none; }
}

/* ─────────────── Dashboard rename modal (Glass / Soft Light) ─────────────── */
.rnm {
  position: fixed; inset: 0; z-index: 200;
  display: grid; place-items: center; padding: 1.2rem;
  background: rgba(40,30,25,0.32);
  backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px);
}
.rnm__sheet {
  width: min(28rem, 100%);
  background: var(--glass-row);
  border: 1px solid var(--glass-line);
  border-radius: var(--r-card);
  box-shadow: var(--shadow-lg), var(--glass-inset);
  padding: 1.4rem 1.4rem 1.2rem;
  display: flex; flex-direction: column; gap: 0.85rem;
}
.rnm__title { font-family: var(--font); font-weight: 800; font-size: 1.15rem; color: var(--title); margin: 0; }
.rnm__field { display: flex; flex-direction: column; gap: 0.35rem; }
.rnm__label { font-size: 0.82rem; font-weight: 600; color: var(--muted); }
.rnm__input {
  font-family: var(--font); font-size: 1rem; color: var(--ink);
  padding: 0.7rem 0.85rem; border-radius: var(--r-btn);
  border: 1px solid var(--line); background: rgba(255,255,255,0.7);
}
.rnm__input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--peach); }
.rnm__input:disabled { opacity: 0.6; }
.rnm__help { font-size: 0.8rem; color: var(--faint); margin: 0; line-height: 1.45; }
.rnm__error { font-size: 0.85rem; color: #c0392b; margin: 0; font-weight: 600; }
.rnm__actions { display: flex; justify-content: flex-end; gap: 0.6rem; margin-top: 0.3rem; }
@media (prefers-reduced-motion: reduce) { .rnm__input { transition: none; } }

/* ─────────────── Pricing (Glass / Soft Light) ─────────────── */
.pricing { max-width: var(--maxw); margin: 0 auto; padding: var(--section-y) var(--pad-x); }
/* The LANDING pricing section (`section#pricing`) sits directly on the calm
   canvas — undo the modal-shell background/border/shadow that `.pricing` also
   carries for the builder paywall (line ~1766). ID-scoped so the modal keeps its
   shell. */
#pricing.pricing { background: none; border: 0; border-radius: 0; box-shadow: none; }
.pricing__head { text-align: center; max-width: 42rem; margin: 0 auto 2.4rem; }
.pricing__title { font-family: var(--font); font-weight: 800; letter-spacing: -0.03em; font-size: clamp(1.8rem, 4vw, 2.6rem); color: var(--title); margin: 0 0 0.7rem; }
.pricing__sub { color: var(--muted); font-size: 1.05rem; line-height: 1.55; margin: 0; }
.pricing__grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.2rem; align-items: stretch; }
.price-card {
  position: relative; display: flex; flex-direction: column; gap: 0.25rem;
  background: var(--glass-row); border: 1px solid var(--glass-line); border-radius: var(--r-card);
  backdrop-filter: var(--blur); -webkit-backdrop-filter: var(--blur);
  box-shadow: var(--e2), var(--glass-inset); padding: 1.7rem 1.5rem 1.5rem;
  transition: transform 0.3s var(--ease-out), box-shadow 0.3s var(--ease-out);
}
.price-card:hover { transform: translateY(-5px); box-shadow: var(--shadow-lg), var(--glass-inset); }
@media (prefers-reduced-motion: reduce) { .price-card:hover { transform: none; } }
.price-card--featured {
  border-color: var(--accent);
  background:
    radial-gradient(90% 55% at 50% -10%, color-mix(in srgb, var(--accent) 10%, transparent), transparent 70%),
    var(--glass-row);
  box-shadow: var(--shadow-lg), var(--glass-inset);
}
.price-card__badge {
  position: absolute; top: -0.7rem; left: 1.4rem; background: var(--accent); color: #fff;
  font-size: 0.72rem; font-weight: 700; letter-spacing: 0.02em; padding: 0.22rem 0.65rem; border-radius: 999px;
}
.price-card__name { font-family: var(--font); font-weight: 800; font-size: 1.12rem; color: var(--title); margin: 0; }
.price-card__for { margin: 0.15rem 0 0; font-size: 0.85rem; color: var(--muted); }
.price-card__price { margin: 0.35rem 0 0; display: flex; align-items: baseline; gap: 0.15rem; }
.price-card__amt { font-family: var(--font); font-weight: 800; font-size: 2.3rem; color: var(--ink); letter-spacing: -0.03em; }
.price-card__per { color: var(--muted); font-weight: 600; }
.price-card__credits { color: var(--ink); font-weight: 700; margin: 0.45rem 0 0; }
.price-card__note { color: var(--faint); font-size: 0.9rem; margin: 0.1rem 0 0; }
.price-card__cta { margin-top: 1.1rem; align-self: flex-start; }
.pricing__fine { text-align: center; color: var(--faint); font-size: 0.9rem; margin: 1.4rem 0 0; }
@media (max-width: 760px) { .pricing__grid { grid-template-columns: 1fr; } }

/* ─────────────── Dashboard boot skeleton (#34 — never a blank #dboard-root) ─────────────── */
.dboard-boot {
  min-height: 100vh; display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 1.4rem; padding: 2rem;
}
.dboard-boot .brand { transform: scale(1.1); }
.dboard-boot__bars { display: flex; flex-direction: column; gap: 0.7rem; width: min(22rem, 80vw); }
.dboard-boot__bar {
  height: 0.9rem; border-radius: 999px;
  background: linear-gradient(90deg, var(--glass-row) 25%, rgba(244,89,58,0.10) 37%, var(--glass-row) 63%);
  background-size: 400% 100%; animation: dboard-boot-shimmer 1.4s ease-in-out infinite;
}
.dboard-boot__bar--sm { width: 60%; }
.dboard-boot__msg { color: var(--faint); font-size: 0.9rem; }
@keyframes dboard-boot-shimmer { 0% { background-position: 100% 0; } 100% { background-position: 0 0; } }
@media (prefers-reduced-motion: reduce) { .dboard-boot__bar { animation: none; } }
/* ─────────────── Settings / Billing panel (#11) ─────────────── */
.settings { position: relative; gap: 0.9rem; }
.settings__close {
  position: absolute; top: 0.9rem; right: 1rem; border: none; background: none; cursor: pointer;
  font-size: 1.5rem; line-height: 1; color: var(--muted); padding: 0.2rem;
}
.settings__close:hover { color: var(--ink); }
.settings__tabs { display: flex; gap: 0.4rem; border-bottom: 1px solid var(--line); }
.settings__tab {
  background: none; border: none; cursor: pointer; font-family: var(--font); font-weight: 600;
  font-size: 0.92rem; color: var(--muted); padding: 0.5rem 0.7rem; border-bottom: 2px solid transparent;
  margin-bottom: -1px;
}
.settings__tab:hover { color: var(--ink); }
.settings__tab.is-active { color: var(--accent); border-bottom-color: var(--accent); }
.settings__body { display: flex; flex-direction: column; gap: 0.7rem; min-height: 7rem; }
.settings__row { display: flex; justify-content: space-between; align-items: baseline; gap: 1rem; }
.settings__k { font-size: 0.9rem; color: var(--muted); font-weight: 600; }
.settings__v { font-size: 1rem; color: var(--ink); font-weight: 700; }
.settings__note { font-size: 0.85rem; color: var(--faint); margin: 0.2rem 0 0.4rem; line-height: 1.45; }
.settings__err { font-size: 0.9rem; color: #c0392b; font-weight: 600; margin: 0; }
.settings__loading { font-size: 0.9rem; color: var(--faint); padding: 1.2rem 0; }
.settings__soon { display: flex; gap: 0.8rem; align-items: flex-start; padding: 0.4rem 0; }
.settings__soon-ic { font-size: 1.5rem; }
.settings__soon-title { font-family: var(--font); font-weight: 800; color: var(--title); margin: 0; }
.settings__body .btn { align-self: flex-start; }

/* ─────────────── Per-app detail / manage panel (#12/#16/#14) ─────────────── */
.appdetail { position: relative; gap: 1rem; }
.appdetail__close {
  position: absolute; top: 0.9rem; right: 1rem; border: none; background: none; cursor: pointer;
  font-size: 1.5rem; line-height: 1; color: var(--muted); padding: 0.2rem;
}
.appdetail__close:hover { color: var(--ink); }
.appdetail__head { display: flex; align-items: center; gap: 0.85rem; }
.appdetail__mono {
  width: 2.6rem; height: 2.6rem; flex: none; border-radius: 0.8rem; display: grid; place-items: center;
  font-weight: 800; font-size: 1.05rem; color: #fff;
  background: linear-gradient(150deg, var(--accent-hi, var(--accent)), var(--accent) 60%, var(--accent-2));
}
.appdetail__status { display: inline-block; margin-top: 0.2rem; font-size: 0.78rem; font-weight: 700; }
.appdetail__status.is-live { color: #1e9e48; }
.appdetail__status.is-off { color: var(--faint); }
.appdetail__actions { display: grid; grid-template-columns: 1fr 1fr; gap: 0.5rem; }
.appdetail__act {
  display: flex; align-items: center; gap: 0.55rem; text-align: left; cursor: pointer;
  font-family: var(--font); font-size: 0.92rem; font-weight: 600; color: var(--ink);
  padding: 0.7rem 0.8rem; border-radius: var(--r-btn); border: 1px solid var(--line);
  background: rgba(255,255,255,0.6); transition: border-color 0.15s ease, background 0.15s ease;
}
.appdetail__act:hover { border-color: var(--accent); background: var(--peach); }
.appdetail__act-ic { font-size: 1rem; width: 1.2rem; text-align: center; flex: none; }
.appdetail__danger { border-top: 1px solid var(--line); padding-top: 0.85rem; }
.appdetail__delete {
  background: none; border: none; cursor: pointer; font-family: var(--font); font-weight: 700;
  font-size: 0.9rem; color: #c0392b; padding: 0.2rem;
}
.appdetail__delete:hover { text-decoration: underline; }
.appdetail__confirm { display: flex; flex-direction: column; gap: 0.85rem; }
.appdetail__confirm-msg { margin: 0; font-size: 0.95rem; color: var(--ink); line-height: 1.5; }
.appdetail__confirm-row { display: flex; justify-content: flex-end; gap: 0.6rem; }
.appdetail__danger-cta { background: #c0392b; color: #fff; }
.appdetail__danger-cta:hover { background: #a83226; }
.appcard__live--off { color: var(--faint); }
.appcard__live--off .appcard__dot { background: var(--faint); }
@media (max-width: 520px) { .appdetail__actions { grid-template-columns: 1fr; } }

/* ─────────────── Monetization tab (Phase 2 — Payouts + Tiers + Earnings) ─────────────── */
.mon { display: flex; flex-direction: column; gap: 0.85rem; max-height: 66vh; overflow-y: auto; margin: -0.2rem -0.3rem 0; padding: 0.2rem 0.3rem; }
.mon__pick { display: flex; align-items: center; gap: 0.6rem; }
.mon__pick-k { font-size: 0.82rem; font-weight: 600; color: var(--muted); flex: none; }
.mon__select {
  flex: 1 1 auto; font-family: var(--font); font-size: 0.95rem; color: var(--ink);
  padding: 0.55rem 0.7rem; border-radius: var(--r-btn); border: 1px solid var(--line);
  background: rgba(255,255,255,0.7);
}
.mon__select:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--peach); }
.mon-card {
  background: var(--glass-row); border: 1px solid var(--glass-line); border-radius: var(--r-card);
  box-shadow: var(--glass-inset); padding: 1rem 1.05rem; display: flex; flex-direction: column; gap: 0.55rem;
}
.mon-card__head { display: flex; align-items: center; gap: 0.55rem; }
.mon-card__ic { font-size: 1.15rem; }
/* site-emoji-icons-to-svg: the money/app-card emoji glyphs are now drawn line icons (currentColor,
   consistent with RAIL_SVG / hsGlyph). Alignment + a warm money-accent on the card heads. */
.mon-card__ic svg { display: block; color: var(--accent-2); }
.mon-locked svg { vertical-align: -0.15em; }
.appdetail__act-ic svg, .iaction svg { vertical-align: middle; }
.mon-card__title { font-family: var(--font); font-weight: 800; font-size: 1rem; color: var(--title); margin: 0; flex: 1 1 auto; }
.mon-card__actions { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; margin-top: 0.15rem; }
.mon-pill { flex: none; font-size: 0.7rem; font-weight: 700; letter-spacing: 0.02em; padding: 0.2rem 0.55rem; border-radius: 999px; }
.mon-pill--active { background: color-mix(in srgb, #1e9e48 14%, #fff); color: #1a8a40; }
.mon-pill--pending { background: var(--peach); color: var(--accent-2); }
.mon-pill--restricted { background: color-mix(in srgb, #c0392b 12%, #fff); color: #c0392b; }
.mon-locked { font-size: 0.85rem; color: var(--faint); margin: 0; font-weight: 600; }

.mon-tiers { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.5rem; }
.mon-tier {
  display: flex; align-items: flex-start; gap: 0.6rem; padding: 0.6rem 0.7rem;
  border: 1px solid var(--line); border-radius: var(--r-btn); background: rgba(255,255,255,0.55);
}
.mon-tier__main { flex: 1 1 auto; min-width: 0; }
.mon-tier__name { font-family: var(--font); font-weight: 700; color: var(--ink); margin: 0; font-size: 0.95rem; }
.mon-tier__desc { margin: 0.15rem 0 0; font-size: 0.82rem; color: var(--muted); line-height: 1.4; }
.mon-tier__price { margin: 0.25rem 0 0; font-size: 0.85rem; font-weight: 700; color: var(--accent-2); font-variant-numeric: tabular-nums; }
.mon-tier__acts { display: flex; flex-direction: column; gap: 0.3rem; flex: none; }
.mon-tier__act {
  background: none; border: none; cursor: pointer; font-family: var(--font); font-weight: 600;
  font-size: 0.82rem; color: var(--accent-2); padding: 0.15rem 0.3rem; border-radius: 6px; text-align: right;
}
.mon-tier__act:hover { background: var(--peach); }
.mon-tier__act--danger { color: #c0392b; }
.mon-tier__act--danger:hover { background: color-mix(in srgb, #c0392b 9%, #fff); }
.mon-danger { background: #c0392b; }
.mon-danger:hover { background: #a83226; }

.mon-form { display: flex; flex-direction: column; gap: 0.6rem; }
.mon-stats { display: flex; gap: 0.8rem; }
.mon-stat {
  flex: 1 1 0; display: flex; flex-direction: column; gap: 0.1rem; padding: 0.6rem 0.7rem;
  border: 1px solid var(--line); border-radius: var(--r-btn); background: rgba(255,255,255,0.55);
}
.mon-stat__n { font-family: var(--font); font-weight: 800; font-size: 1.3rem; color: var(--ink); letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }
.mon-stat__l { font-size: 0.78rem; font-weight: 600; color: var(--muted); }
@media (max-width: 520px) { .mon-stats { flex-direction: column; } }

/* ─────────────── Phase 3 fan paywall sheet (§8) ─────────────── */
.paywall {
  position: fixed; inset: 0; z-index: 1000; display: flex; align-items: flex-end; justify-content: center;
  background: rgba(33,26,21,0.42); backdrop-filter: blur(2px); -webkit-backdrop-filter: blur(2px);
}
.paywall__sheet {
  width: min(30rem, 100%); max-height: 86vh; overflow-y: auto;
  background: var(--glass-row); border: 1px solid var(--glass-line);
  border-radius: var(--r-card) var(--r-card) 0 0; box-shadow: var(--shadow-lg), var(--glass-inset);
  padding: 1.5rem 1.4rem calc(1.4rem + env(safe-area-inset-bottom, 0px)); position: relative;
}
@media (min-width: 560px) { .paywall { align-items: center; } .paywall__sheet { border-radius: var(--r-card); } }
.paywall__close {
  position: absolute; top: 0.8rem; right: 1rem; border: none; background: none; cursor: pointer;
  font-size: 1.6rem; line-height: 1; color: var(--muted); padding: 0.2rem;
}
.paywall__close:hover { color: var(--ink); }
.paywall__title { font-family: var(--font); font-weight: 800; font-size: 1.3rem; color: var(--title); margin: 0 0 0.4rem; letter-spacing: -0.02em; }
.paywall__sub { color: var(--muted); font-size: 0.95rem; line-height: 1.5; margin: 0 0 1rem; }
.paywall__loading { color: var(--faint); font-size: 0.95rem; padding: 1.6rem 0; text-align: center; }
.paywall__toggle { display: inline-flex; gap: 0.2rem; padding: 0.25rem; border-radius: 999px; background: rgba(255,255,255,0.5); border: 1px solid var(--line); margin-bottom: 1rem; }
.paywall__toggle button { border: none; background: none; cursor: pointer; font-family: var(--font); font-weight: 700; font-size: 0.85rem; color: var(--muted); padding: 0.4rem 0.9rem; border-radius: 999px; }
.paywall__toggle button.is-on { background: var(--accent); color: #fff; box-shadow: var(--shadow-acc); }
.paywall__tiers { display: flex; flex-direction: column; gap: 0.7rem; }
.paywall__tier { border: 1px solid var(--line); border-radius: var(--r-card); padding: 1rem 1.05rem; background: rgba(255,255,255,0.55); }
.paywall__tier-head { display: flex; align-items: baseline; justify-content: space-between; gap: 0.8rem; }
.paywall__tier-name { font-family: var(--font); font-weight: 800; color: var(--title); font-size: 1.02rem; }
.paywall__tier-price { font-family: var(--font); font-weight: 800; color: var(--accent-2); font-variant-numeric: tabular-nums; }
.paywall__tier-desc { margin: 0.35rem 0 0.8rem; font-size: 0.88rem; color: var(--muted); line-height: 1.45; }
.paywall__sub-btn { margin-top: 0.8rem; width: 100%; justify-content: center; }
.paywall__actions { display: flex; flex-direction: column; gap: 0.6rem; margin-top: 0.4rem; }
.paywall__err { color: #c0392b; font-size: 0.88rem; font-weight: 600; margin: 0.8rem 0 0; }
.paywall__spinner { width: 1.8rem; height: 1.8rem; margin: 1.4rem auto 0.4rem; border-radius: 50%; border: 3px solid var(--line); border-top-color: var(--accent); animation: paywall-spin 0.8s linear infinite; }
@keyframes paywall-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .paywall__spinner { animation: none; } }

/* ═══════════════════════════ "Start from your Instagram" (ig-inc1) ═══════════════════════════ */
/* Entry sits alongside the prompt box in the rail; the panel/loading/error/adjust reuse the glass +
   accent design system (DESIGN.md). The D4 reveal reuses the §8 reveal motion + honors reduced-motion. */

.wb__ig { margin-bottom: 0.7rem; }

/* recipe-url-import — the compact "paste a recipe link" entry in the builder rail. */
.wb__recipe-import { margin-bottom: 0.7rem; }
.wb__recipe-import[hidden] { display: none; }
.recipe-import__label { display: block; font-size: 0.8rem; font-weight: 600; color: var(--muted); margin-bottom: 0.4rem; }
.recipe-import__row { display: flex; gap: 0.5rem; }
.recipe-import__input {
  flex: 1 1 auto; min-width: 0;
  padding: 0.55rem 0.7rem;
  border: 1px solid var(--line-2); border-radius: 10px;
  font: inherit; color: var(--ink); background: #fff;
}
.recipe-import__input:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; border-color: var(--accent); }
.recipe-import__btn { flex: none; }
.recipe-import__msg { margin: 0.45rem 0 0; font-size: 0.8rem; color: var(--muted); }
.recipe-import__msg--err { color: var(--accent); }

/* ══════════ site-build-rail-redesign — the Guided Ladder (fresh-build rail face) ══════════ */
.wb-ladder {
  position: relative;
  margin: clamp(0.75rem, 2vw, 1.1rem);
  padding: 1.1rem 1.15rem 1.2rem;
  border: 1px solid var(--line);
  border-radius: 22px;
  background: var(--bg-elev, #fff);
  box-shadow: var(--e1);
}
/* hairline spine down the left, threading the numbered nodes */
.wb-ladder__spine {
  position: absolute; left: calc(1.15rem + 14px); top: 3.1rem; bottom: 1.5rem; width: 1px;
  background: var(--line); z-index: 0;
}
.wb-ladder__step { position: relative; display: flex; gap: 0.85rem; z-index: 1; }
.wb-ladder__node {
  flex: none; width: 30px; height: 30px; border-radius: 50%;
  display: grid; place-items: center; font-size: 0.85rem; font-weight: 700;
  color: var(--muted); background: var(--bg-elev, #fff); border: 1px solid var(--line-2);
}
.wb-ladder__node--active {
  color: #fff; background: var(--accent); border-color: var(--accent);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent) 18%, transparent);
}
.wb-ladder__body { flex: 1 1 auto; min-width: 0; }
.wb-ladder__title { margin: 0.2rem 0 0.7rem; font-size: 1.26rem; font-weight: 800; letter-spacing: -0.02em; color: var(--title, var(--ink)); }
.wb-ladder__card { border: 1px solid var(--line-2); border-radius: 16px; background: var(--glass-row, rgba(255,255,255,.7)); padding: 1.1rem 1.15rem; }
.wb-ladder__card .wb__chat { margin: 0; }
/* Founder-reported (2026-07-08, post-#295): the compact one-line chat pill clipped its own wrapping
   placeholder inside the narrower ladder card. Per the LOCKED mock the ladder input is a LARGE
   rounded-rect box, not a pill — give it room. Scoped to the EXPANDED ladder only: the post-build
   collapsed state ([data-collapsed]) keeps the classic compact pill. */
.wb-ladder[data-ladder]:not([data-collapsed]) .wb-ladder__card .wb__chat-field {
  border-radius: 14px; padding: 0.75rem 0.75rem 0.75rem 1rem;
}
.wb-ladder[data-ladder]:not([data-collapsed]) .wb-ladder__card .wb__chat-input {
  min-height: 6rem; max-height: 12rem; font-size: 1.02rem;
}
/* Founder polish pass (2026-07-08 evening): the chat FORM carries its old bottom-bar chrome (border-top
   + solid bg + chunky padding) — inside the ladder card that read as a stray hairline and a cramped,
   double-padded well. Strip it in the card context; the card is the chrome now. */
.wb-ladder[data-ladder]:not([data-collapsed]) .wb-ladder__card .wb__chat {
  border-top: 0; background: transparent; padding: 0;
}
.wb-ladder[data-ladder]:not([data-collapsed]) .wb-ladder__card .wb__chat-field .btn {
  width: 2.25rem; height: 2.25rem; align-self: flex-end; margin: 0 0.1rem 0.1rem 0;
}
.wb-ladder__examples { margin-top: 0.9rem; }
.wb-ladder__examples-label,
.wb-ladder__from-label { display: block; font-size: 0.78rem; color: var(--muted); margin-bottom: 0.5rem; }
.wb-ladder__pills { display: grid; grid-template-columns: 1fr 1fr; gap: 0.5rem; }
.wb-ladder__pill {
  display: inline-flex; align-items: center; gap: 0.45rem;
  padding: 0.5rem 0.7rem; border-radius: 999px; cursor: pointer;
  font: inherit; font-size: 0.84rem; font-weight: 600; color: var(--ink);
  background: #fff; border: 1px solid var(--line-2); text-align: left;
  transition: border-color .15s ease, box-shadow .15s ease;
}
.wb-ladder__pill::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: var(--accent); flex: none; }
.wb-ladder__pill:hover { border-color: var(--accent); box-shadow: var(--e1); }
.wb-ladder__pill:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.wb-ladder__divider { height: 1px; background: var(--line); margin: 0.9rem 0; }
.wb-ladder__chips { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 0.5rem; }
.wb-ladder__chips > .wb__ig, .wb-ladder__chips > .wb__recipe-import { margin: 0; }
/* the three alternate entries become COMPACT CHIPS (existing flow elements, restyled per the mock) */
.wb-ladder__chips .ig-entry,
.wb-ladder__chips .recipe-import__chip {
  display: inline-flex; flex-direction: row; align-items: center; gap: 0.4rem; width: auto;
  padding: 0.42rem 0.72rem; border-radius: 999px; list-style: none; cursor: pointer;
  font-size: 0.83rem; font-weight: 600; color: var(--ink);
  background: #fff; border: 1px solid var(--line-2);
  box-shadow: none; -webkit-backdrop-filter: none; backdrop-filter: none;
}
.wb-ladder__chips .ig-entry:hover, .wb-ladder__chips .recipe-import__chip:hover {
  transform: none; border-color: var(--accent); box-shadow: var(--e1);
}
.wb-ladder__chips .ig-entry__sub { display: none; }
.wb-ladder__chips .recipe-import__chip::-webkit-details-marker { display: none; }
.wb-ladder__chips .recipe-import[open] .recipe-import__chip { border-color: var(--accent); }
.wb-ladder__chips .recipe-import__row { margin-top: 0.5rem; }
.recipe-import__glyph { color: var(--accent); line-height: 1; }
/* steps 2·3·4 — smaller rungs (founder adjustment: smaller nodes/text, tighter rhythm, still present) */
.wb-ladder__rungs { position: relative; z-index: 1; margin-top: 0.55rem; display: flex; flex-direction: column; gap: 0.3rem; }
.wb-ladder__rung { display: flex; align-items: center; gap: 0.85rem; padding: 0.12rem 0; }
.wb-ladder__rung .wb-ladder__node { width: 22px; height: 22px; font-size: 0.72rem; }
.wb-ladder__rung-label { font-size: 0.85rem; color: var(--muted); }
/* COLLAPSE post-build (builder.js sets data-collapsed): the card becomes today's plain chat */
.wb-ladder[data-collapsed] { border: none; box-shadow: none; padding: 0; background: transparent; }
.wb-ladder[data-collapsed] .wb-ladder__spine,
.wb-ladder[data-collapsed] .wb-ladder__title,
.wb-ladder[data-collapsed] .wb-ladder__examples,
.wb-ladder[data-collapsed] .wb-ladder__divider,
.wb-ladder[data-collapsed] .wb-ladder__from,
.wb-ladder[data-collapsed] .wb-ladder__rungs,
.wb-ladder[data-collapsed] .wb-ladder__step > .wb-ladder__node { display: none; }
.wb-ladder[data-collapsed] .wb-ladder__card { border: none; background: transparent; padding: 0; }
@media (prefers-reduced-motion: reduce) {
  .wb-ladder__pill, .wb-ladder__chips .ig-entry, .wb-ladder__chips .recipe-import__chip { transition: none; }
}

/* ══════════ site-builder-content-first — import-first Guided Ladder (approved mock SCREEN 1) ══════════ */
/* Step 1 promise + the content sources (Instagram primary, Substack, recipe/site link). */
.wb-ladder__promise { margin: -0.35rem 0 0.9rem; font-size: 0.9rem; line-height: 1.45; color: var(--muted); }
.wb-sources { display: flex; flex-direction: column; gap: 0.6rem; }
.wb-sources > .wb__ig, .wb-sources > .wb__recipe-import { margin: 0; }
/* A non-primary source row (Substack) + the IG panel's own source header share this look. */
.wb-source, .wb-source__head { display: flex; align-items: center; gap: 0.7rem; text-align: left; }
.wb-source {
  width: 100%; cursor: pointer; font: inherit;
  padding: 0.72rem 0.9rem; border-radius: 14px;
  background: var(--glass-row, #fff); border: 1px solid var(--line-2);
  box-shadow: var(--e1); transition: transform .15s ease, box-shadow .15s ease, border-color .15s ease;
}
.wb-source:hover { transform: translateY(-1px); box-shadow: var(--e2); border-color: var(--accent); }
.wb-source:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.wb-source__ic { color: var(--accent); flex: none; display: inline-flex; }
.wb-source__txt { display: flex; flex-direction: column; line-height: 1.3; min-width: 0; }
.wb-source__txt b { font-weight: 700; color: var(--title, var(--ink)); font-size: 0.98rem; }
.wb-source__txt span { color: var(--muted); font-size: 0.82rem; }
.wb-source__head { margin-bottom: 0.1rem; }
/* IG is the PRIMARY source: the handle field carries an inline Import button. */
.ig-panel__field .btn { flex: none; margin-left: 0.35rem; }
/* Step 2 "Add direction (optional)" — quieter than step 1. */
.wb-ladder__title--sm { font-size: 1rem; margin-bottom: 0.55rem; }
.wb-ladder__opt { font-weight: 600; font-size: 0.82rem; color: var(--faint, var(--muted)); }
.wb-ladder__node--opt { background: var(--line-2); color: var(--muted); }
/* Fresh state has NO send button (import is the entry point) + no "Ship it" (nothing to ship yet). The
   `hidden` attribute must win over `.btn { display: inline-flex }` — assert it for buttons that toggle. */
.btn[hidden] { display: none; }
/* Post-build: collapse step 1 (sources) entirely; step 2's card becomes the plain iterate chat. */
.wb-ladder[data-collapsed] .wb-ladder__step:not(.wb-ladder__step--direction),
.wb-ladder[data-collapsed] .wb-ladder__promise { display: none; }

.ig-entry {
  display: flex; flex-direction: column; align-items: flex-start; gap: 0.1rem;
  width: 100%; text-align: left; cursor: pointer;
  padding: 0.72rem 0.9rem; border-radius: var(--r-card, 18px);
  background: var(--glass-row, rgba(255,255,255,.74));
  border: 1px solid var(--glass-line, rgba(255,255,255,.85));
  box-shadow: var(--e1); -webkit-backdrop-filter: var(--blur); backdrop-filter: var(--blur);
  transition: transform .15s ease, box-shadow .15s ease;
}
.ig-entry:hover { transform: translateY(-1px); box-shadow: var(--e2); }
.ig-entry:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.ig-entry__glyph { color: var(--accent); font-size: 1.1rem; line-height: 1; }
.ig-entry__label { font-weight: 700; color: var(--title, #26190f); font-size: 0.98rem; }
.ig-entry__sub { color: var(--muted, #6a5d54); font-size: 0.82rem; }

.ig-panel {
  padding: 0.9rem; border-radius: var(--r-card, 18px);
  border: 1px solid var(--glass-line, rgba(255,255,255,.85));
  background: var(--glass-row, rgba(255,255,255,.74));
  box-shadow: var(--e1); display: flex; flex-direction: column; gap: 0.6rem;
}
.ig-panel__label { font-weight: 700; color: var(--title, #26190f); font-size: 0.9rem; }
.ig-panel__field {
  display: flex; align-items: center; gap: 0.35rem; min-width: 0;
  border: 1px solid var(--line, #ECE3DC); border-radius: 12px; background: #fff; padding: 0 0.7rem;
}
.ig-panel__at { flex: none; color: var(--muted, #6a5d54); font-weight: 700; }
/* fix-builder-import-button-overflow: min-width:0 lets the flex:1 input SHRINK so the flex:none Import
   button stays inside the field. Without it the input's intrinsic min-width pushed Import past the
   sub-card + ladder pane edge on the narrow two-pane layout (founder screenshot, #421 builder). */
.ig-panel__input { flex: 1; min-width: 0; border: 0; outline: none; padding: 0.6rem 0; font: inherit; background: transparent; color: var(--ink, #211a15); }
.ig-panel__error { color: #c0392b; font-size: 0.84rem; font-weight: 600; margin: 0; }
.ig-panel__actions { display: flex; justify-content: flex-end; gap: 0.5rem; }

.ig-loading { align-items: center; text-align: center; }
.ig-loading__spinner {
  width: 1.9rem; height: 1.9rem; margin: 0.3rem auto; border-radius: 50%;
  border: 3px solid var(--line, #ECE3DC); border-top-color: var(--accent);
  animation: ig-spin 0.8s linear infinite;
}
.ig-loading__label { font-weight: 700; color: var(--title, #26190f); margin: 0.2rem 0 0; }
.ig-loading__sub { color: var(--muted, #6a5d54); font-size: 0.84rem; margin: 0; }
@keyframes ig-spin { to { transform: rotate(360deg); } }

.ig-error__msg { color: var(--ink, #211a15); font-size: 0.9rem; margin: 0 0 0.2rem; }

/* fix-ig-reveal-spacing: the reveal caption (left) + adjust panel (right) are flex siblings of the
   centered phone (.appprev) inside .wb__preview — give them clear horizontal breathing room from the
   phone, and cap their width so they never squeeze it. INERT for a normal build: caption/adjust are
   [hidden] → not flex items → the phone stays centered exactly as before (gap needs ≥2 items). */
.wb__preview { gap: clamp(1.25rem, 4vw, 3rem); }
.ig-adjust { flex: 0 1 auto; max-width: 220px; }
/* fix-builder-preview-chrome-glitches (Defect A): the "Built from your Instagram." banner used to FLANK the
   phone (flex:0 1 auto; max-width:220px) — on the IG build it wrapped onto the phone's row, squeezing the
   app-preview and knocking the #272/#304-pinned Web|Phone toggle INSIDE the browser frame. Make the banner a
   full-width row of its OWN (order:-1 → above the phone, next to the Preview|Edit toggle row) so it never
   shares/reflows the preview's row: the pinned-toggle contract now holds with AND without the banner. */
.ig-caption { flex: 0 0 100%; max-width: 100%; order: -1; }

/* D4 reveal caption + the staged reveal on the preview slot. */
.ig-caption { text-align: center; font-weight: 700; color: var(--accent-2, #C03623); margin: 0 0 0.5rem; font-size: 0.95rem; }
.ig-reveal-in { animation: ig-reveal 0.6s cubic-bezier(0.22,1,0.36,1) both; }
@keyframes ig-reveal { from { opacity: 0; transform: translateY(16px) scale(0.985); } to { opacity: 1; transform: none; } }

/* D3 bounded accent adjust. */
.ig-adjust { margin-top: 0.8rem; text-align: center; }
.ig-adjust__title { font-weight: 700; color: var(--title, #26190f); margin: 0; font-size: 0.92rem; }
.ig-adjust__sub { color: var(--muted, #6a5d54); font-size: 0.82rem; margin: 0.1rem 0 0.55rem; }
.ig-adjust__swatches { display: flex; justify-content: center; gap: 0.55rem; flex-wrap: wrap; }
.ig-swatch {
  width: 2rem; height: 2rem; border-radius: 50%; cursor: pointer; padding: 0;
  background: var(--sw); border: 2px solid #fff;
  box-shadow: 0 0 0 1px var(--line, #E0D5CC), var(--e1);
  transition: transform .12s ease, box-shadow .12s ease;
}
.ig-swatch:hover { transform: scale(1.08); }
.ig-swatch:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.ig-swatch.is-active { box-shadow: 0 0 0 2px var(--sw), 0 0 0 4px #fff, var(--e1); transform: scale(1.06); }

@media (prefers-reduced-motion: reduce) {
  .ig-loading__spinner { animation: none; }
  .ig-reveal-in { animation: none; }
  .ig-entry, .ig-swatch { transition: none; }
}

/* ═══════════════════ Inline text editing (builder-inline-edit PR 3/3) ═══════════════════ */
/* Owner-only "Edit text" toggle on the preview chrome + an ephemeral save status. Hidden until an owned
   app is generated (data-edit-chrome[hidden]); glass + accent, matches the builder surface. */
/* site-builder-preview-toggle-row: the preview-pane control ROW is the full-width slot above the phone
   (order -1). Preview|Edit (owner) sits left, Web|Phone (once there's something to preview) sits right on
   ONE baseline — the founder-hit alignment. The wrapper owns the row; .wb-edit is now a normal flex child. */
.wb-controls { order: -1; flex-basis: 100%; display: flex; align-items: center; gap: 0.6rem; justify-content: space-between; margin-bottom: 0.5rem; }
.wb-edit:not([hidden]) { display: flex; align-items: center; gap: 0.6rem; }
/* Web|Phone mirrors the retired in-frame toggle's visibility: hidden while the preview is idle (nothing to
   view yet), shown once a build is building/ready/failed. Pure CSS off the shared component's data-state. */
.wb__preview:has(.appprev[data-state="idle"]) .wb-view { display: none; }
/* Idle + non-owner = both controls hidden; remove the row entirely (display:none, like the old hidden
   .wb-edit) so it adds no flex line — otherwise an empty full-width row perturbs the pane's wrap/align and
   makes .wb__preview scrollable (a serious a11y scrollable-region violation on the idle /build). */
.wb__preview:has(.appprev[data-state="idle"]) .wb-controls:not(:has(.wb-edit:not([hidden]))) { display: none; }
/* builder-preview-edit-toggle: a Preview|Edit segmented control (glass pill, two segments). */
.wb-edit__toggle {
  display: inline-flex; align-items: center; gap: 2px; padding: 3px; border-radius: 999px;
  background: var(--glass-row, rgba(255,255,255,.74)); border: 1px solid var(--glass-line, rgba(255,255,255,.85));
  box-shadow: var(--e1); -webkit-backdrop-filter: var(--blur); backdrop-filter: var(--blur);
}
.wb-edit__seg {
  font: inherit; font-weight: 700; font-size: 0.85rem; cursor: pointer;
  padding: 0.32rem 0.9rem; border-radius: 999px; border: 0; background: transparent;
  color: var(--muted, #6a5d54); transition: color .12s ease, background-color .12s ease;
}
.wb-edit__seg:hover { color: var(--ink, #211a15); }
.wb-edit__seg.is-active { color: #fff; background: var(--accent); }
.wb-edit__seg:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.wb-edit__status { font-size: 0.8rem; font-weight: 600; color: var(--muted, #6a5d54); }
.wb-edit__status--err { color: #c0392b; cursor: pointer; text-decoration: underline; }
@media (prefers-reduced-motion: reduce) { .wb-edit__seg { transition: none; } }

/* ============================================================
   Manage content (/manage/<id>) — the focused no-AI content editor (site-manage-content).
   Two-pane: content list + add/edit drawer (left), live iPhone preview (right). Built on the LOCKED
   Glass-Forward · Soft Light tokens (:root above). All classes are `mc-` prefixed so nothing collides
   with the dashboard / builder chrome. The approved mockup lives at athens/.context/manage-content-mockup.html.
   ============================================================ */
.mc-body { margin: 0; min-height: 100%; background: var(--app-bg); background-attachment: fixed; color: var(--ink); }
.mc-root { min-height: 100vh; }

/* wordmark (matches the dashboard lockup vibe) */
.mc-wordmark { display: inline-flex; align-items: center; gap: 0.3em; font-weight: 800; letter-spacing: -0.025em; font-size: 18px; text-decoration: none; }
.mc-wordmark__mk { width: 1.08em; height: 1.08em; border-radius: 6px; background: linear-gradient(46deg, #F4593A, #F0726B 68%, #FB8A60); box-shadow: var(--e1); }
.mc-wordmark__h { background: linear-gradient(46deg, #F4593A, #FB8A60); -webkit-background-clip: text; background-clip: text; color: transparent; }
.mc-wordmark__s { color: #2B211C; }

/* top chrome */
.mc-topbar { position: sticky; top: 0; z-index: 40; display: flex; align-items: center; gap: 16px; padding: 14px 26px;
  background: var(--glass-chrome); backdrop-filter: var(--blur-chrome); -webkit-backdrop-filter: var(--blur-chrome);
  border-bottom: 1px solid rgba(255,255,255,.6); box-shadow: 0 8px 24px -18px rgba(60,45,35,.4); }
.mc-back { display: inline-flex; align-items: center; gap: 7px; border: 1px solid rgba(120,90,70,.16); background: rgba(255,255,255,.6);
  padding: 8px 13px; border-radius: 12px; font-weight: 600; font-size: 13.5px; color: var(--muted); cursor: pointer; text-decoration: none; }
.mc-back:hover { background: #fff; }
.mc-crumb { font-weight: 800; letter-spacing: -0.02em; font-size: 15px; color: var(--title); }
.mc-crumb__app { color: var(--faint); font-weight: 600; }
.mc-spacer { flex: 1; }
.mc-saved { display: inline-flex; align-items: center; gap: 7px; font-size: 12.5px; font-weight: 600; color: #1B7A4B; }
.mc-saved.is-saving { color: var(--muted); }
.mc-saved.is-flash { animation: mc-flash 0.9s var(--ease-out); }
@keyframes mc-flash { 0% { transform: scale(1.06); } 100% { transform: scale(1); } }
.mc-saved__dot { width: 7px; height: 7px; border-radius: 50%; background: #1B7A4B; box-shadow: 0 0 0 3px rgba(27,122,75,.14); }
.mc-saved__spin { width: 12px; height: 12px; border-radius: 50%; border: 2px solid rgba(120,90,70,.25); border-top-color: var(--accent); animation: mc-spin 0.7s linear infinite; }
@keyframes mc-spin { to { transform: rotate(360deg); } }

.mc-btn { display: inline-flex; align-items: center; justify-content: center; gap: 8px; border-radius: 12px; font-weight: 700; font-size: 13.5px;
  cursor: pointer; border: 1px solid transparent; padding: 9px 15px; font-family: inherit; text-decoration: none; }
.mc-btn--ghost { border-color: rgba(120,90,70,.18); background: rgba(255,255,255,.6); color: var(--ink); }
.mc-btn--ghost:hover { background: #fff; }
.mc-btn--primary { background: linear-gradient(155deg, var(--accent-hi), var(--accent) 60%, var(--accent-2)); color: #fff; border-color: rgba(255,255,255,.4);
  box-shadow: 0 12px 26px -12px color-mix(in srgb, var(--accent) 60%, transparent); font-weight: 800; padding: 11px 20px; font-size: 14px; }
.mc-btn--primary:hover { filter: brightness(1.04); }
.mc-btn--danger { background: #C0392B; color: #fff; font-weight: 800; padding: 11px 20px; font-size: 14px; }
.mc-btn--danger:hover { filter: brightness(1.06); }
.mc-btn:disabled { opacity: 0.55; cursor: default; filter: none; }
.mc-link { display: inline-block; margin-top: 10px; color: var(--accent-2); font-weight: 700; font-size: 13px; text-decoration: none; }
.mc-link:hover { text-decoration: underline; }

/* layout */
/* site-manage-content-clip-container-query: mc-wrap mounts in TWO widths — standalone #mc-root (full page)
   and the embedded Content tab .ah-managehost (inside the ~246px app-home rail). Make both QUERY CONTAINERS
   so the Web-view expansion below keys off the WRAP's real available width, not the viewport (a viewport gate
   fired the wide grid in the rail-narrowed embed → the preview clipped, same class as #413). */
.mc-root, .ah-managehost { container-type: inline-size; }
.mc-wrap { max-width: 1240px; margin: 0 auto; padding: 26px; display: grid; grid-template-columns: 1fr 392px; gap: 30px; align-items: start; }
/* Founder-reported (2026-07-08): the Web-view browser frame was capped by the 392px preview column and
   read as a phone-width sliver. In Web view, widen the pane (and the page cap) so the frame breathes;
   :has() keys the layout off the preview's own view toggle — no JS. Phone view keeps the classic grid.
   @container: the wide grid's column minimums need ~1110px + mc-wrap padding, so only expand when the wrap's
   own container is ≥1180 — standalone (full width) expands; the rail-narrowed embed keeps the 1fr/392 grid. */
@container (min-width: 1180px) {
  .mc-wrap:has(.appprev[data-view="web"]) { max-width: 1500px; grid-template-columns: minmax(560px, 1fr) minmax(520px, 640px); }
  .mc-wrap:has(.appprev[data-view="web"]) .mc-preview .appprev { max-width: 100%; }
}
/* fix-apphub-content-390-overflow: a bare `1fr` track is minmax(auto,1fr) — it refuses to shrink below
   its content's min-content (the recipe rows + Add buttons), so the collapsed single column rendered at
   ~675px inside a 358px phone container (body scrollWidth 707 > 390 → half of every row + the Add buttons
   offscreen right). minmax(0,1fr) lets the track shrink to the container; the editor col + its inner
   content then reflow to width (item titles already ellipsis via .mc-item__main min-width:0). */
@media (max-width: 1040px) { .mc-wrap { grid-template-columns: minmax(0, 1fr); } .mc-preview-col { display: none; } }
/* the editor column is a grid item — min-width:0 (grid default is auto=min-content) is required for the
   track's minmax(0,1fr) to actually take effect and for the fluid children below to reflow. */
.mc-editor-col { min-width: 0; }

/* fix-residence-content-tab-layout (founder video 1 F, sec_0188-0192 + audit-1 #4): the Content tab was the
   odd one out — the embedded Manage editor is a STANDALONE full-page layout (max-width:1240 + margin:0 auto +
   its own 26px padding), so inside the residence it floated mid-page with the live-preview phone centered and
   a dead right half. Make Content join the STANDARD residence grid: span the managehost across BOTH .ah-wrap
   tracks and drop the standalone centering so .mc-wrap fills the width — its own two-pane grid then docks the
   recipe list LEFT (the freed main width, which also relieves audit-1's cramped rows) and the "Live preview"
   panel FAR RIGHT under its cap, matching Overview/Deals/Audience. Preview column + collapse breakpoint
   aligned to the residence (360px / ≤1080). Scoped to the embed (.ah-managehost) so a lingering standalone
   .mc-root is untouched. */
.ah-managehost { grid-column: 1 / -1; }
.ah-managehost .mc-wrap { max-width: none; margin: 0; padding: 0; grid-template-columns: minmax(0, 1fr) 360px; }
@media (max-width: 1080px) {
  .ah-managehost .mc-wrap { grid-template-columns: minmax(0, 1fr); }
  .ah-managehost .mc-preview-col { display: none; }
}

/* editor card */
.mc-card { background: var(--glass-row); backdrop-filter: var(--blur); -webkit-backdrop-filter: var(--blur);
  border: 1px solid var(--glass-line); border-radius: var(--r-card); box-shadow: var(--e2); padding: 22px; }
.mc-eyebrow { font-size: 12px; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; color: var(--accent-2); }
.mc-card__title { margin: 6px 0 0; font-size: 21px; font-weight: 800; letter-spacing: -.03em; color: var(--title); }
.mc-count { font-size: 13px; font-weight: 600; color: var(--faint); }
.mc-list-head { display: flex; align-items: flex-end; justify-content: space-between; margin-bottom: 16px; gap: 14px; }
.mc-btn-add { display: inline-flex; align-items: center; gap: 8px; background: linear-gradient(155deg, var(--accent-hi), var(--accent) 60%, var(--accent-2));
  color: #fff; border: 1px solid rgba(255,255,255,.4); padding: 11px 17px; border-radius: 14px; font-weight: 800; font-size: 14px; cursor: pointer;
  font-family: inherit; box-shadow: 0 12px 26px -12px color-mix(in srgb, var(--accent) 60%, transparent); }
.mc-btn-add:hover { filter: brightness(1.04); }
.mc-btn-add:disabled { opacity: 0.5; cursor: default; filter: none; }

/* item rows */
.mc-items { display: flex; flex-direction: column; gap: 12px; }
.mc-item { display: flex; align-items: center; gap: 14px; background: var(--glass-row); backdrop-filter: var(--blur); -webkit-backdrop-filter: var(--blur);
  border: 1px solid var(--glass-line); border-radius: 20px; box-shadow: var(--e1); padding: 12px 14px; position: relative; transition: box-shadow .15s, transform .15s; }
.mc-item:hover { box-shadow: var(--e2); transform: translateY(-1px); }
.mc-item.is-dragging { opacity: .5; }
.mc-grip { color: #b9a89c; font-size: 17px; cursor: grab; padding: 0 2px; user-select: none; }
.mc-thumb { width: 58px; height: 58px; border-radius: 14px; flex: none; background-size: cover; background-position: center; box-shadow: inset 0 0 0 1px rgba(0,0,0,.05); }
.mc-thumb--empty { background: linear-gradient(150deg, #f6d9c9, #eab79f); }
.mc-item__main { flex: 1; min-width: 0; }
.mc-item__title { font-size: 15.5px; font-weight: 800; letter-spacing: -.02em; color: var(--title); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mc-item__meta { font-size: 12.5px; color: var(--faint); margin-top: 2px; display: flex; align-items: center; gap: 9px; }
.mc-badge { display: inline-flex; align-items: center; gap: 5px; font-size: 11px; font-weight: 800; letter-spacing: .02em; padding: 3px 8px; border-radius: 999px;
  background: color-mix(in srgb, var(--accent) 14%, #fff); color: var(--accent-2); }
.mc-item__actions { display: flex; align-items: center; gap: 4px; }
.mc-icon-btn { width: 34px; height: 34px; border-radius: 10px; border: 1px solid transparent; background: transparent; color: var(--muted); cursor: pointer;
  font-size: 15px; display: grid; place-items: center; }
.mc-icon-btn:hover { background: rgba(255,255,255,.85); border-color: rgba(120,90,70,.14); }
.mc-cap-note { font-size: 12.5px; color: var(--faint); margin: 12px 2px 0; }

/* site-social-links — the Links card (second editor card, below Recipes) */
.mc-card--links { margin-top: 18px; }
.mc-soc-add { display: flex; align-items: center; gap: 10px; margin-bottom: 14px; flex-wrap: wrap; }
.mc-soc-add__url { flex: 1 1 240px; min-width: 0; }
.mc-soc-add__label { flex: 0 1 150px; min-width: 0; }
/* the paste-preview + row platform chip: a hairline glyph tile that tints per platform */
.mc-soc-chip { flex: none; width: 40px; height: 40px; border-radius: 12px; display: grid; place-items: center;
  color: var(--accent-2); background: color-mix(in srgb, var(--accent) 9%, #fff);
  box-shadow: inset 0 0 0 1px rgba(120,90,70,.12); transition: color .15s, background .15s; }
.mc-soc-add__chip { width: 44px; height: 44px; }
.mc-soc-glyph { width: 22px; height: 22px; display: block; }
.mc-soc-item .mc-soc-chip { width: 46px; height: 46px; border-radius: 13px; }
/* recognizable tints for the marks with a strong brand colour (still monochrome glyphs) */
.mc-soc-chip[data-platform="instagram"] { color: #C13584; background: color-mix(in srgb, #C13584 10%, #fff); }
.mc-soc-chip[data-platform="youtube"] { color: #C4302B; background: color-mix(in srgb, #C4302B 9%, #fff); }
.mc-soc-chip[data-platform="tiktok"] { color: #111; background: color-mix(in srgb, #111 6%, #fff); }
.mc-soc-chip[data-platform="x"] { color: #111; background: color-mix(in srgb, #111 6%, #fff); }
.mc-soc-chip[data-platform="facebook"] { color: #1877F2; background: color-mix(in srgb, #1877F2 9%, #fff); }
.mc-soc-chip[data-platform="pinterest"] { color: #BD081C; background: color-mix(in srgb, #BD081C 9%, #fff); }
.mc-soc-chip[data-platform="threads"] { color: #111; background: color-mix(in srgb, #111 6%, #fff); }
.mc-soc-chip[data-platform="spotify"] { color: #1DB954; background: color-mix(in srgb, #1DB954 12%, #fff); }
.mc-soc-chip[data-platform="twitch"] { color: #9146FF; background: color-mix(in srgb, #9146FF 10%, #fff); }
.mc-soc-chip[data-platform="substack"] { color: #FF6719; background: color-mix(in srgb, #FF6719 10%, #fff); }
.mc-soc-url { font-variant-numeric: tabular-nums; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; display: block; }
.mc-soc-err { font-size: 12.5px; color: #C0392B; margin: -6px 2px 12px; }
.mc-icon-btn--danger:hover { color: #C0392B; }
@media (max-width: 560px) {
  .mc-soc-add__label { flex-basis: 100%; }
}

/* per-item overflow menu */
.mc-menu { position: absolute; right: 12px; top: 52px; z-index: 30; min-width: 190px; background: rgba(255,255,255,.9);
  backdrop-filter: var(--blur); -webkit-backdrop-filter: var(--blur); border: 1px solid var(--glass-line); border-radius: 16px; box-shadow: var(--e2); padding: 6px; display: none; }
.mc-menu.is-open { display: block; }
.mc-menu button { display: flex; width: 100%; align-items: center; gap: 10px; background: none; border: none; padding: 9px 11px; border-radius: 10px;
  font-size: 13.5px; font-weight: 600; color: var(--ink); cursor: pointer; text-align: left; font-family: inherit; }
.mc-menu button:hover { background: color-mix(in srgb, var(--accent) 10%, #fff); }
.mc-menu button:disabled { opacity: .4; cursor: default; background: none; }
.mc-menu__danger { color: #C0392B; }
.mc-menu__danger:hover { background: rgba(192,57,43,.09) !important; }
.mc-menu__sep { height: 1px; background: rgba(120,90,70,.12); margin: 5px 6px; }
.mc-glyph { width: 18px; text-align: center; opacity: .85; }

/* empty state */
.mc-empty { text-align: center; padding: 48px 24px; }
.mc-empty__emoji { font-size: 34px; }
/* site-emoji-icons-to-svg (Slice B): the management-surface emoji glyphs are now drawn line icons
   (ui-icons.js, currentColor). Big empty/gate marks center + take the accent; inline icons align to text. */
.mc-gate__emoji svg, .mc-empty__emoji svg, .ah-gate__emoji svg { display: block; margin: 0 auto; color: var(--accent); }
.dash__glyph svg { color: var(--accent); }
.mc-glyph svg, .mc-icon-btn svg, .mc-btn svg { vertical-align: middle; }
.mc-badge svg, .mc-pair-note svg, .mc-crop__note svg, .recipe-import__glyph svg { vertical-align: -0.14em; }
.mc-empty__title { margin: 12px 0 4px; font-size: 20px; font-weight: 800; letter-spacing: -.02em; color: var(--title); }
.mc-empty__sub { margin: 0 auto 18px; max-width: 340px; font-size: 14px; color: var(--muted); }

/* skeleton */
.mc-skel { border-radius: 12px; background: linear-gradient(90deg, rgba(120,90,70,.08), rgba(120,90,70,.14), rgba(120,90,70,.08)); background-size: 200% 100%;
  animation: mc-shimmer 1.4s ease-in-out infinite; }
.mc-skel--head { height: 26px; width: 45%; margin-bottom: 20px; }
.mc-skel--row { height: 58px; margin-bottom: 12px; }
@keyframes mc-shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }

/* auth / not-found / error gate */
.mc-gate { display: grid; place-items: center; padding: 8vh 20px; }
.mc-gate__card { background: var(--glass-row); backdrop-filter: var(--blur); -webkit-backdrop-filter: var(--blur); border: 1px solid var(--glass-line);
  border-radius: var(--r-card); box-shadow: var(--e2); padding: 34px 32px; text-align: center; max-width: 440px; }
.mc-gate__emoji { font-size: 34px; margin-bottom: 6px; }
.mc-gate__title { margin: 0 0 8px; font-size: 22px; font-weight: 800; letter-spacing: -.03em; color: var(--title); }
.mc-gate__sub { margin: 0 0 20px; font-size: 14.5px; color: var(--muted); line-height: 1.5; }
/* site-authed-polish-slice (item 1): stack the gate CTA + "Back to dashboard" so they never crowd onto one
   line; the link gets a real 44px tap target with clear spacing. Applies to both the manage + app-home gates. */
.mc-gate__card, .ah-gate__card { display: flex; flex-direction: column; align-items: center; }
.mc-gate__card .mc-btn--primary, .ah-gate__card .ah-btn--primary { min-height: 44px; }
.mc-gate__card .mc-link, .ah-gate__card .ah-link {
  margin-top: 14px; min-height: 44px; display: inline-flex; align-items: center; padding: 4px 10px;
}

/* live preview column — mountAppPreview builds the iPhone frame; we just size the slot */
.mc-preview-col { position: sticky; top: 96px; }
.mc-preview-cap { font-size: 12px; font-weight: 700; color: var(--faint); text-align: center; margin-bottom: 12px; display: flex; align-items: center; justify-content: center; gap: 7px; }
.mc-live-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 20%, transparent); animation: mc-pulse 2s infinite; }
@keyframes mc-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }
.mc-preview .appprev { width: 100%; max-width: 340px; margin: 0 auto; gap: 0.9rem; }
/* Founder-reported (2026-07-08): a hard 620px height on a ~200px-wide phone stretched it to a 3.1
   ratio (a real iPhone is ~2.14). Let the base aspect-ratio govern; widening the phone to 290px keeps
   the same ~620px visual height WITHOUT the distortion. Web view overrides aspect-ratio to auto and
   fills the (wider, see below) column — unaffected by the phone max-width. */
.mc-preview .appprev__phone { max-width: 290px; margin-inline: auto; }

/* add / edit drawer */
.mc-scrim { position: fixed; inset: 0; background: rgba(40,25,15,.34); backdrop-filter: blur(3px); z-index: 60; opacity: 0; pointer-events: none; transition: opacity .2s; }
.mc-scrim.is-on { opacity: 1; pointer-events: auto; }
.mc-drawer { position: fixed; top: 0; right: 0; height: 100%; width: 480px; max-width: 94vw; z-index: 70; transform: translateX(100%);
  transition: transform .26s cubic-bezier(.4,0,.2,1); background: linear-gradient(180deg, #FCF9F6, #F4ECE6); border-left: 1px solid rgba(255,255,255,.7);
  box-shadow: -30px 0 70px -30px rgba(40,25,15,.4); display: flex; flex-direction: column; }
.mc-drawer.is-on { transform: translateX(0); }
.mc-drawer__head { padding: 20px 24px 14px; border-bottom: 1px solid rgba(120,90,70,.12); display: flex; align-items: center; justify-content: space-between; }
.mc-drawer__head h3 { margin: 0; font-size: 20px; font-weight: 800; letter-spacing: -.03em; color: var(--title); }
.mc-drawer__x { border: none; background: rgba(255,255,255,.6); width: 34px; height: 34px; border-radius: 11px; font-size: 17px; cursor: pointer; color: var(--muted); }
.mc-drawer__body { flex: 1; overflow: auto; padding: 20px 24px; }
.mc-drawer__foot { padding: 16px 24px; border-top: 1px solid rgba(120,90,70,.12); display: flex; gap: 12px; justify-content: flex-end; background: rgba(255,255,255,.4); }
.mc-drawer__note { font-size: 12px; color: var(--faint); margin-top: 14px; display: flex; gap: 8px; align-items: flex-start; }
.mc-drawer__error { margin: 0 24px 12px; padding: 10px 12px; border-radius: 10px; background: rgba(192,57,43,.09); color: #C0392B; font-size: 13px; font-weight: 600; }

.mc-photo { width: 100%; height: 120px; border-radius: 16px; background: linear-gradient(150deg, #f6d9c9, #eab79f); box-shadow: var(--e1);
  display: flex; align-items: center; justify-content: center; color: #fff; font-weight: 700; font-size: 13px; margin-bottom: 16px; cursor: pointer;
  background-size: cover; background-position: center; border: none; font-family: inherit; }
.mc-photo.has-photo { color: transparent; }

/* manage-photo-crop: the 4:5 framing overlay (sits above the drawer, z-index 70) */
.mc-crop { position: fixed; inset: 0; z-index: 90; display: flex; align-items: center; justify-content: center;
  padding: 20px; background: rgba(40,25,15,.5); backdrop-filter: blur(4px); opacity: 0; pointer-events: none; transition: opacity .2s; }
.mc-crop.is-on { opacity: 1; pointer-events: auto; }
.mc-crop__panel { background: var(--card, #fffdfb); border-radius: 20px; box-shadow: var(--e2, 0 20px 60px rgba(60,40,25,.28));
  padding: 18px 18px 16px; width: min(400px, 94vw); max-height: 94vh; overflow: auto; transform: translateY(10px); transition: transform .2s; }
.mc-crop.is-on .mc-crop__panel { transform: translateY(0); }
.mc-crop__title { font-size: 17px; font-weight: 800; letter-spacing: -.02em; color: var(--title); text-align: center; }
.mc-crop__hint { font-size: 12px; color: var(--faint); text-align: center; margin: 3px 0 13px; }
.mc-crop__stage { position: relative; margin: 0 auto; overflow: hidden; border-radius: 14px; background: #efe7df;
  touch-action: none; cursor: grab; user-select: none; box-shadow: inset 0 0 0 1px rgba(120,90,70,.12); }
.mc-crop__stage:active { cursor: grabbing; }
.mc-crop__stage:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.mc-crop__img { position: absolute; top: 0; left: 0; max-width: none; user-select: none; -webkit-user-drag: none; will-change: transform; }
.mc-crop__frameline { position: absolute; inset: 0; pointer-events: none; border-radius: 14px;
  box-shadow: inset 0 0 0 2px rgba(255,255,255,.85), inset 0 0 0 3px rgba(0,0,0,.12); }
.mc-crop__zoom { display: flex; align-items: center; gap: 10px; margin: 14px 4px 4px; }
.mc-crop__zbtn { flex: none; width: 34px; height: 34px; border-radius: 10px; border: 1px solid rgba(120,90,70,.18);
  background: rgba(255,255,255,.75); color: var(--muted); font-size: 18px; line-height: 1; cursor: pointer; font-family: inherit; }
.mc-crop__zbtn:hover { border-color: var(--accent); color: var(--accent-2); }
.mc-crop__slider { flex: 1; accent-color: var(--accent); }
.mc-crop__foot { display: flex; gap: 12px; justify-content: flex-end; margin-top: 16px; }
.mc-crop__note { font-size: 11.5px; color: var(--faint); margin-top: 12px; display: flex; gap: 7px; align-items: flex-start; }
@media (prefers-reduced-motion: reduce) {
  .mc-crop, .mc-crop__panel { transition: none; }
  .mc-crop__panel { transform: none; }
}

.mc-field { margin-bottom: 15px; }
.mc-field label { display: block; font-size: 12.5px; font-weight: 700; color: var(--muted); margin-bottom: 6px; }
.mc-lbl-hint { font-weight: 500; color: var(--faint); text-transform: none; letter-spacing: 0; }
.mc-input { width: 100%; border: 1px solid rgba(120,90,70,.18); background: rgba(255,255,255,.75); border-radius: 12px; padding: 11px 13px;
  font-size: 14.5px; font-family: inherit; color: var(--ink); }
.mc-input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent); }
.mc-input--err { border-color: #C0392B; }
textarea.mc-input { resize: vertical; min-height: 82px; line-height: 1.5; }
.mc-row2 { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }

/* ingredients live parse */
.mc-parsed { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 9px; }
.mc-parsed__cnt { font-size: 11.5px; font-weight: 700; color: var(--faint); width: 100%; margin-bottom: 1px; }
.mc-chip { font-size: 12px; font-weight: 600; color: var(--accent-2); background: color-mix(in srgb, var(--accent) 11%, #fff);
  border: 1px solid color-mix(in srgb, var(--accent) 20%, #fff); border-radius: 999px; padding: 4px 10px; }
.mc-chip--warn { color: #9C6B1A; background: #fbf1de; border-color: #f0dcb4; }
.mc-link-btn { background: none; border: none; color: var(--accent-2); font-weight: 700; font-size: 12.5px; cursor: pointer; padding: 8px 0 0; display: inline-flex; gap: 5px; align-items: center; font-family: inherit; }
.mc-link-btn:hover { text-decoration: underline; }

/* method steps */
.mc-steps { display: flex; flex-direction: column; gap: 9px; }
.mc-step-row { display: flex; gap: 9px; align-items: flex-start; }
.mc-step-n { flex: none; width: 26px; height: 26px; margin-top: 9px; border-radius: 8px; background: color-mix(in srgb, var(--accent) 14%, #fff);
  color: var(--accent-2); font-weight: 800; font-size: 13px; display: grid; place-items: center; }
.mc-step-in { flex: 1; min-height: 44px; min-width: 0; }
.mc-step-x { flex: none; width: 30px; height: 30px; margin-top: 7px; border: none; background: none; color: #b9a89c; font-size: 14px; cursor: pointer; border-radius: 8px; }
.mc-step-x:hover { background: rgba(192,57,43,.09); color: #C0392B; }
.mc-add-step { margin-top: 10px; background: rgba(255,255,255,.6); border: 1px dashed rgba(120,90,70,.28); color: var(--muted); font-weight: 700; font-size: 13px;
  padding: 9px 14px; border-radius: 12px; cursor: pointer; width: 100%; font-family: inherit; }
.mc-add-step:hover { background: #fff; border-color: var(--accent); }
.mc-pair-note { font-size: 12px; color: #9C6B1A; background: #fbf1de; border: 1px solid #f0dcb4; border-radius: 10px; padding: 9px 11px; margin-top: 12px; }
.mc-pair-note--err { color: #9b1c1c; background: #fdecec; border-color: #f3c2c2; font-weight: 600; }

/* members switch */
.mc-toggle-row { display: flex; align-items: center; justify-content: space-between; background: rgba(255,255,255,.6); border: 1px solid rgba(120,90,70,.14);
  border-radius: 14px; padding: 13px 15px; margin-top: 4px; }
.mc-toggle__tl { font-size: 14px; font-weight: 700; color: var(--title); }
.mc-toggle__ts { font-size: 12px; color: var(--muted); margin-top: 2px; }
.mc-switch { width: 46px; height: 27px; border-radius: 999px; background: #d7c9bd; position: relative; cursor: pointer; flex: none; transition: background .18s; border: none; padding: 0; }
.mc-switch::after { content: ""; position: absolute; top: 3px; left: 3px; width: 21px; height: 21px; border-radius: 50%; background: #fff; box-shadow: var(--e1); transition: left .18s; }
.mc-switch.is-on { background: var(--accent); }
.mc-switch.is-on::after { left: 22px; }

/* delete confirm */
.mc-confirm { position: fixed; left: 50%; top: 50%; transform: translate(-50%, -50%); z-index: 71; width: 400px; max-width: 92vw;
  background: linear-gradient(180deg, #FCF9F6, #F4ECE6); border: 1px solid var(--glass-line); border-radius: var(--r-card); box-shadow: var(--e2); padding: 24px; }
.mc-confirm__title { margin: 0 0 8px; font-size: 18px; font-weight: 800; letter-spacing: -.02em; color: var(--title); }
.mc-confirm__msg { margin: 0 0 18px; font-size: 14px; color: var(--muted); line-height: 1.5; }
.mc-confirm__row { display: flex; gap: 12px; justify-content: flex-end; }

/* toast */
.mc-toast { position: fixed; left: 50%; bottom: 26px; transform: translate(-50%, 12px); z-index: 90; background: var(--dark); color: var(--cream);
  padding: 11px 18px; border-radius: 12px; font-size: 13.5px; font-weight: 600; box-shadow: var(--e2); opacity: 0; pointer-events: none; transition: opacity .2s, transform .2s; }
.mc-toast.is-on { opacity: 1; transform: translate(-50%, 0); }

@media (max-width: 640px) {
  .mc-topbar { padding: 12px 16px; gap: 10px; }
  .mc-crumb__app { display: none; }
  .mc-wrap { padding: 16px; }
  .mc-card { padding: 16px; }
  .mc-saved { display: none; }
  /* fix-apphub-content-390-overflow: let the list header wrap so the "Add recipe" button drops under the
     title instead of forcing the card wider than the phone viewport (it has no min-width to shrink to). */
  .mc-list-head { flex-wrap: wrap; }
}
@media (prefers-reduced-motion: reduce) {
  .mc-skel, .mc-live-dot, .mc-saved__spin, .mc-saved.is-flash { animation: none; }
  .mc-drawer, .mc-scrim, .mc-toast { transition: none; }
}

/* ============================================================
   builder-live-narration-p1a — the REAL build events: an append-driven live action list (base44-style
   "Writing… ✓ / Reading… ✓") replacing the canned single-line timer, plus a collapsible code disclosure.
   Reuses .narrate (the per-turn container) + .narrate__dot (spinner) + the locked tokens.
   ============================================================ */
/* The live action list stacks full-width inside the flex .narrate container. */
.narrate__actions { flex-basis: 100%; display: flex; flex-direction: column; gap: 0.35rem; }
.narrate__actions:empty { display: none; }
.narrate__fallback { display: flex; align-items: center; gap: 0.7rem; }
.narrate__fallback[hidden] { display: none; }
.narrate__row { display: flex; align-items: center; gap: 0.6rem; font-size: 0.9rem; }
.narrate__row-ic {
  flex: none; width: 1.15rem; height: 1.15rem; display: grid; place-items: center;
  font-size: 0.82rem; font-weight: 800; color: var(--accent);
}
/* Active row: the icon slot holds the spinning .narrate__dot; label is emphasized ink. */
.narrate__row.is-active .narrate__row-label { font-weight: 700; color: var(--ink); }
/* Done row: checkmark + calm, de-emphasized label (it's finished). */
.narrate__row.is-done .narrate__row-label { font-weight: 600; color: var(--muted); }
.narrate__row.is-done .narrate__row-ic { color: #1B7A4B; }
.narrate__row-label { letter-spacing: -0.01em; }

/* "Show code" disclosure — the raw token stream, tucked away (collapsed by default). */
.codebox { margin: 0.6rem 0 0; }
.codebox[hidden] { display: none; }
.codebox__summary {
  display: inline-flex; align-items: center; gap: 0.4rem; cursor: pointer;
  min-height: 44px; padding: 0.2rem 0; list-style: none;
  font-size: 0.82rem; font-weight: 700; color: var(--muted); user-select: none;
}
.codebox__summary::-webkit-details-marker { display: none; }
.codebox__summary::before { content: "▸"; font-size: 0.7rem; transition: transform 0.15s ease; color: var(--faint); }
.codebox[open] > .codebox__summary::before { transform: rotate(90deg); }
.codebox__summary:hover { color: var(--ink); }
.codebox__summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 6px; }
.codebox .codestream { margin-top: 0.4rem; }

/* ============================================================
   App Home (/app/<id>) — the per-app management hub (site-app-home). One metrics strip + tabs +
   two-pane body with the live preview. Locked Glass-Forward · Soft Light tokens; matches the approved
   app-home mock (hairline-divided strip, hairline rows, stroke glyphs, tabular numerals). ah- prefixed.
   ============================================================ */
.ah-body { margin: 0; min-height: 100%; background: var(--app-bg); background-attachment: fixed; color: var(--ink); }
.ah-root { min-height: 100vh; padding-bottom: 40px; }
.ah-gl { width: 18px; height: 18px; display: inline-block; vertical-align: middle; color: currentColor; }

.ah-wordmark { display: inline-flex; align-items: center; gap: 0.3em; font-weight: 800; letter-spacing: -0.025em; font-size: 18px; text-decoration: none; }
.ah-wordmark__mk { width: 1.08em; height: 1.08em; border-radius: 6px; background: linear-gradient(46deg, #F4593A, #F0726B 68%, #FB8A60); box-shadow: var(--e1); }
.ah-wordmark__h { background: linear-gradient(46deg, #F4593A, #FB8A60); -webkit-background-clip: text; background-clip: text; color: transparent; }
.ah-wordmark__s { color: #2B211C; }

/* top chrome */
.ah-topbar { position: sticky; top: 0; z-index: 40; display: flex; align-items: center; gap: 14px; padding: 12px 26px;
  background: rgba(255,255,255,.92); backdrop-filter: var(--blur-chrome); -webkit-backdrop-filter: var(--blur-chrome);
  border-bottom: 1px solid rgba(255,255,255,.6); box-shadow: 0 8px 24px -18px rgba(60,45,35,.4); }
.ah-back { display: inline-flex; align-items: center; gap: 5px; border: 1px solid rgba(120,90,70,.16); background: rgba(255,255,255,.6);
  padding: 7px 12px 7px 9px; border-radius: 11px; font-weight: 600; font-size: 13px; color: var(--muted); cursor: pointer; text-decoration: none; }
.ah-back .ah-gl { width: 15px; height: 15px; transform: rotate(180deg); }
.ah-back:hover { background: #fff; }
.ah-appname { font-weight: 800; letter-spacing: -0.02em; font-size: 15px; color: var(--title); }
.ah-crumb { font-weight: 800; letter-spacing: -0.02em; font-size: 15px; color: var(--title); }
.ah-livepill { display: inline-flex; align-items: center; gap: 6px; font-size: 11.5px; font-weight: 800; letter-spacing: 0.02em;
  color: #1B7A4B; background: color-mix(in srgb, #1B7A4B 10%, #fff); border-radius: 999px; padding: 3px 10px; }
.ah-livepill__d { width: 6px; height: 6px; border-radius: 50%; background: #1B7A4B; box-shadow: 0 0 0 3px rgba(27,122,75,.14); }
.ah-livepill--off { color: var(--faint); background: var(--line); }
.ah-spacer { flex: 1; }

.ah-btn { display: inline-flex; align-items: center; justify-content: center; gap: 6px; border: 1px solid rgba(120,90,70,.18);
  background: rgba(255,255,255,.7); color: var(--ink); padding: 8px 14px; border-radius: 11px; font-weight: 700; font-size: 13px;
  cursor: pointer; font-family: inherit; text-decoration: none; }
.ah-btn:hover { background: #fff; }
.ah-btn--quiet { border-color: transparent; background: transparent; color: var(--muted); }
.ah-btn--quiet:hover { background: rgba(255,255,255,.7); color: var(--ink); }
.ah-btn--primary { background: linear-gradient(155deg, var(--accent-hi), var(--accent) 60%, var(--accent-2)); color: #fff;
  border-color: rgba(255,255,255,.4); font-weight: 800; box-shadow: 0 12px 26px -12px color-mix(in srgb, var(--accent) 60%, transparent); }
.ah-btn--primary:hover { filter: brightness(1.04); background: linear-gradient(155deg, var(--accent-hi), var(--accent) 60%, var(--accent-2)); }
.ah-btn--danger { background: #C0392B; color: #fff; border-color: transparent; font-weight: 800; }
.ah-btn--danger:hover { filter: brightness(1.06); background: #C0392B; }
.ah-btn--disabled { opacity: 0.5; cursor: default; }
.ah-link { display: inline-block; margin-top: 10px; color: var(--accent-2); font-weight: 700; font-size: 13px; text-decoration: none; }
.ah-link:hover { text-decoration: underline; }

/* metrics strip — ONE glass strip divided by hairlines */
.ah-metrics { max-width: 1180px; margin: 22px auto 0; padding: 0 clamp(1.25rem, 4vw, 2.5rem); }
.ah-metrics__bar { display: grid; grid-template-columns: repeat(4, 1fr); background: var(--glass-row); backdrop-filter: var(--blur);
  -webkit-backdrop-filter: var(--blur); border: 1px solid var(--glass-line); border-radius: 18px; box-shadow: var(--e2); overflow: hidden; }
.ah-metric { padding: 16px 20px 14px; position: relative; min-height: 84px; }
.ah-metric + .ah-metric { border-left: 1px solid var(--line); }
.ah-metric__k { font-size: 12.5px; font-weight: 600; color: var(--muted); }
.ah-metric__v { font-size: 28px; font-weight: 800; letter-spacing: -0.035em; color: var(--title); margin-top: 6px; font-variant-numeric: tabular-nums; line-height: 1.05; }
.ah-metric__d { font-size: 12px; font-weight: 600; margin-top: 5px; color: var(--faint); font-variant-numeric: tabular-nums; }
.ah-metric__d--flat { color: var(--faint); display: block; }
/* site-authed-polish-slice (item 2): align the bolt to the FIRST line when the chip label wraps to two
   lines (was center-aligned across both lines → the icon floated in the gutter between them). */
.ah-chip-connect { display: inline-flex; align-items: flex-start; gap: 5px; font-size: 11px; font-weight: 700; color: var(--accent-2);
  margin-top: 8px; background: color-mix(in srgb, var(--accent) 12%, #fff); border-radius: 999px; padding: 4px 9px; line-height: 1.35; }
.ah-chip-connect .ah-gl { flex: none; margin-top: 1px; }

/* tabs */
.ah-tabs { max-width: 1180px; margin: 22px auto 0; padding: 0 clamp(1.25rem, 4vw, 2.5rem); display: flex; gap: 2px;
  border-bottom: 1px solid var(--line); overflow-x: auto; }
.ah-tab { background: none; border: none; padding: 11px 16px; font-size: 14px; font-weight: 700; color: var(--muted);
  border-bottom: 2px solid transparent; margin-bottom: -1px; cursor: pointer; font-family: inherit; white-space: nowrap; min-height: 44px; }
.ah-tab:hover { color: var(--title); }
.ah-tab.is-on { color: var(--title); border-bottom-color: var(--accent); }
.ah-tab:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; border-radius: 6px; }

/* layout */
.ah-wrap { max-width: 1180px; margin: 22px auto 0; padding: 0 clamp(1.25rem, 4vw, 2.5rem);
  display: grid; grid-template-columns: 1fr 360px; gap: 30px; align-items: start; }
@media (max-width: 1080px) {
  .ah-wrap { grid-template-columns: 1fr; }
  .ah-preview-col { display: none; }
  .ah-metrics__bar { grid-template-columns: 1fr 1fr; }
  .ah-metric:nth-child(3) { border-left: none; border-top: 1px solid var(--line); }
  .ah-metric:nth-child(4) { border-top: 1px solid var(--line); }
}

/* ============================================================
   site-creator-shell-ia SLICE 1 — the LEFT RAIL creator shell (atlas.html look-locked). Replaces the top
   tab bar in renderShell(); the section bodies (metrics/tabs/wrap) are unchanged and live in .ah-content.
   ============================================================ */
.ah-shell { display: flex; align-items: flex-start; gap: 0; min-height: 100vh; }
.ah-content { flex: 1 1 auto; min-width: 0; padding-bottom: 40px; }
.ah-rail { flex: none; width: 246px; position: sticky; top: 0; height: 100vh; box-sizing: border-box;
  display: flex; flex-direction: column; gap: 16px; padding: 20px 14px;
  background: rgba(255,255,255,.55); backdrop-filter: var(--blur-chrome); -webkit-backdrop-filter: var(--blur-chrome);
  border-right: 1px solid var(--line); }
/* wordmark */
.ah-rwm { display: inline-flex; align-items: center; gap: 0.34em; font-weight: 800; letter-spacing: -0.025em;
  font-size: 19px; text-decoration: none; padding: 2px 8px; }
/* fix-dashboard-logo-mark: render the REAL mark (brand/mark.png), mirroring the landing's .brand__mark
   (natural aspect, no gradient chip). Keeps the ~1.05em rail sizing; radius is harmless on the
   transparent PNG. */
.ah-rwm__mk { display: inline-flex; align-items: center; border-radius: 6px; }
.ah-rwm__mk img { display: block; height: 1.05em; width: auto; }
.ah-rwm__h { background: linear-gradient(46deg, #F4593A, #FB8A60); -webkit-background-clip: text; background-clip: text; color: transparent; }
.ah-rwm__s { color: #2B211C; }
/* app switcher */
.ah-sw { position: relative; }
.ah-swbtn { width: 100%; display: flex; align-items: center; gap: 9px; padding: 8px 10px; border-radius: 13px;
  border: 1px solid var(--glass-line); background: var(--glass-row); box-shadow: var(--e1); cursor: pointer; font-family: inherit; text-align: left; }
.ah-swbtn:hover { background: #fff; }
.ah-swic, .ah-switem__ic { flex: none; width: 30px; height: 30px; border-radius: 9px; display: grid; place-items: center;
  background: linear-gradient(150deg, var(--accent-hi), var(--accent-2)); color: #fff; }
.ah-mono { font-size: 14px; font-weight: 800; }
.ah-swlab { flex: 1; min-width: 0; display: flex; flex-direction: column; line-height: 1.2; }
.ah-swlab b { font-size: 13.5px; font-weight: 700; color: var(--title); letter-spacing: -0.01em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ah-swlab span { font-size: 11px; color: var(--faint); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ah-swchev { flex: none; color: var(--muted); display: grid; place-items: center; }
/* fix-account-row-identity: the workspace switcher's loading SKELETON — a neutral shimmer until the real app
   loads, never the wrong "Your apps / Not published yet" intermediate. Same footprint as the real .ah-swbtn. */
.ah-swbtn--skel { width: 100%; display: flex; align-items: center; gap: 9px; padding: 8px 10px; border-radius: 13px;
  border: 1px solid var(--glass-line); background: var(--glass-row); box-shadow: var(--e1); }
.ah-swic--skel { flex: none; width: 30px; height: 30px; border-radius: 9px; }
.ah-swskel { display: block; height: 10px; border-radius: 6px; }
.ah-swskel--name { width: 62%; margin-bottom: 5px; }
.ah-swskel--sub { width: 42%; height: 8px; }
.ah-swic--skel, .ah-swskel {
  background: linear-gradient(100deg, var(--line) 30%, var(--line-2) 50%, var(--line) 70%);
  background-size: 220% 100%; animation: appprev-shimmer 1.3s ease-in-out infinite;
}
/* fix-account-row-identity: the phone compact bar's loading skeleton (mirrors the switcher). */
.db-compact__mono--skel { width: 30px; height: 30px; border-radius: 9px; flex: none; }
.db-compact__skel { display: block; height: 11px; border-radius: 6px; }
.db-compact__skel--name { width: 108px; }
.db-compact__mono--skel, .db-compact__skel {
  background: linear-gradient(100deg, var(--line) 30%, var(--line-2) 50%, var(--line) 70%);
  background-size: 220% 100%; animation: appprev-shimmer 1.3s ease-in-out infinite;
}
/* fix-account-row-identity: the rail-foot live-status loading skeleton (the third piece of the wrong
   "...Unpublished" transient). Neutral shimmer until the current app's real status loads. */
.ah-rlive--skel { display: flex; flex-direction: column; gap: 8px; }
.ah-rskel { display: block; border-radius: 7px; }
.ah-rskel--pill { width: 96px; height: 20px; border-radius: 999px; }
.ah-rskel--url { width: 70%; height: 11px; }
.ah-rskel {
  background: linear-gradient(100deg, var(--line) 30%, var(--line-2) 50%, var(--line) 70%);
  background-size: 220% 100%; animation: appprev-shimmer 1.3s ease-in-out infinite;
}
@media (prefers-reduced-motion: reduce) { .ah-swic--skel, .ah-swskel, .db-compact__mono--skel, .db-compact__skel, .ah-rskel { animation: none; } }
.ah-swpop { position: absolute; left: 0; right: 0; top: calc(100% + 6px); z-index: 60; padding: 7px;
  background: rgba(255,255,255,.97); backdrop-filter: var(--blur-chrome); -webkit-backdrop-filter: var(--blur-chrome);
  border: 1px solid var(--glass-line); border-radius: 15px; box-shadow: var(--e3, var(--e2)); display: none; }
.ah-swpop.is-on { display: block; }
.ah-swpop__lab { font-size: 10px; font-weight: 800; text-transform: uppercase; letter-spacing: 0.09em; color: var(--faint); padding: 5px 9px 4px; }
.ah-switem { display: flex; align-items: center; gap: 9px; padding: 7px 9px; border-radius: 11px; text-decoration: none; cursor: pointer; }
.ah-switem:hover { background: rgba(255,255,255,.6); }
.ah-switem.cur { background: var(--glass-row); }
.ah-switem__l { flex: 1; min-width: 0; display: flex; flex-direction: column; line-height: 1.2; }
.ah-switem__l b { font-size: 13px; font-weight: 700; color: var(--title); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ah-switem__l span { font-size: 10.5px; color: var(--faint); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ah-switem__v { font-size: 10.5px; font-weight: 700; color: var(--accent-2); }
.ah-switem__pill { font-size: 10px; font-weight: 800; color: var(--muted); background: var(--line); border-radius: 999px; padding: 2px 8px; }
.ah-swpop__foot { border-top: 1px solid var(--line); margin-top: 5px; padding-top: 5px; }
.ah-swfoot { display: flex; align-items: center; gap: 9px; padding: 8px 9px; border-radius: 11px; text-decoration: none;
  font-size: 13px; font-weight: 700; color: var(--muted); }
.ah-swfoot svg { width: 17px; height: 17px; }
.ah-swfoot:hover { background: rgba(255,255,255,.6); color: var(--title); }
.ah-swfoot--new { color: var(--accent-2); }
/* rail nav */
.ah-railnav { display: flex; flex-direction: column; gap: 2px; }
.ah-navlab { font-size: 10px; font-weight: 800; text-transform: uppercase; letter-spacing: 0.09em; color: var(--faint); padding: 8px 12px 4px; }
.ah-navlab--app { color: var(--accent-2); display: flex; align-items: center; gap: 7px; margin-top: 8px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ah-navlab--app i { flex: none; width: 6px; height: 6px; border-radius: 50%; background: #1B7A4B; box-shadow: 0 0 0 3px rgba(27,122,75,.14); }
.ah-navitem { display: flex; align-items: center; gap: 11px; padding: 9px 12px; border-radius: 13px; text-decoration: none;
  color: var(--muted); font-size: 13.5px; font-weight: 600; letter-spacing: -0.01em; cursor: pointer; }
.ah-navitem svg { flex: none; width: 17px; height: 17px; opacity: 0.85; }
.ah-navitem:hover { background: rgba(255,255,255,.55); color: var(--title); }
.ah-navitem.on { background: var(--glass-row); border: 1px solid var(--glass-line); box-shadow: var(--e1); color: var(--accent-2); }
.ah-navitem:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.ah-navnew { margin-left: auto; font-size: 9.5px; font-weight: 800; letter-spacing: 0.04em; color: var(--accent-2);
  background: color-mix(in srgb, var(--accent) 14%, #fff); border-radius: 999px; padding: 2px 7px; }
/* rail foot */
.ah-railfoot { margin-top: auto; display: flex; flex-direction: column; gap: 9px; padding-top: 8px; }
.ah-rlive { display: flex; flex-direction: column; gap: 8px; padding: 12px; border-radius: 15px;
  background: var(--glass-row); border: 1px solid var(--glass-line); box-shadow: var(--e1); }
.ah-rlive__pill { display: inline-flex; align-items: center; gap: 6px; font-size: 11.5px; font-weight: 800; color: #1B7A4B; }
.ah-rlive__pill i { width: 6px; height: 6px; border-radius: 50%; background: #1B7A4B; box-shadow: 0 0 0 3px rgba(27,122,75,.14); }
.ah-rlive__pill--off { color: var(--faint); }
.ah-rlive__url { font-size: 11.5px; color: var(--muted); word-break: break-all; }
/* fix-rail-unpublished-midword-wrap: the --muted variant is PROSE ("Not on your fans' home screens
   yet"), not a share URL, so it must wrap at word boundaries — the base .ah-rlive__url's
   `word-break: break-all` (correct for long URLs) otherwise split "yet" mid-word ("ye/t"). Only the
   prose variant is relaxed; real URLs on .ah-rlive__url keep break-all. */
.ah-rlive__url--muted { color: var(--faint); word-break: normal; overflow-wrap: normal; }
/* site-your-app-residence-epic S3 (pt.3): the rail-foot account chip (monogram + email + Sign out). */
.ah-acct { display: flex; align-items: center; gap: 8px; padding: 7px 8px; border-radius: 12px;
  background: var(--glass-row); border: 1px solid var(--glass-line); }
.ah-acct__mk { flex: none; width: 26px; height: 26px; border-radius: 8px; display: grid; place-items: center;
  font-size: 12px; font-weight: 800; color: #fff; background: linear-gradient(150deg, var(--accent-hi), var(--accent-2)); }
.ah-acct__email { flex: 1; min-width: 0; font-size: 12px; font-weight: 600; color: var(--muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ah-acct__out { flex: none; font: inherit; font-size: 11.5px; font-weight: 700; color: var(--muted);
  background: transparent; border: 0; padding: 4px 6px; border-radius: 8px; cursor: pointer; }
.ah-acct__out:hover { background: rgba(255,255,255,.7); color: var(--ink); }
.ah-acct__out:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.ah-btn--full { width: 100%; }
/* the rail collapses to a horizontal top strip on narrow surfaces — every section stays reachable */
@media (max-width: 900px) {
  .ah-shell { flex-direction: column; }
  .ah-rail { width: 100%; height: auto; position: static; flex-direction: column;
    border-right: none; border-bottom: 1px solid var(--line); }
  .ah-railnav { flex-direction: row; flex-wrap: wrap; }
  .ah-navlab { width: 100%; }
  .ah-railfoot { margin-top: 8px; }
}

/* ============================================================
   site-demo-fix-batch (Frame A) — DASHBOARD phone: compact top bar + bottom SHEET.
   Scoped to .ah-shell--dash so the shared /app-hub rail is byte-identical. On phone the utility rail is a
   bottom sheet behind the compact bar's "Menu"; "Welcome back" + fan stats lead the first viewport. Desktop
   is untouched (the bar + backdrop are display:none; the rail is the normal sidebar).
   ============================================================ */
.db-compact, .db-sheet-backdrop { display: none; }
.db-compact__id { display: flex; align-items: center; gap: 0.6rem; min-width: 0; }
.db-compact__meta { display: flex; flex-direction: column; min-width: 0; }
.db-compact__name { font-size: 0.95rem; font-weight: 800; letter-spacing: -0.01em; color: var(--title);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.db-compact__live { font-size: 0.72rem; font-weight: 700; color: #1e7a4a; display: inline-flex; align-items: center; gap: 4px; }
.db-compact__live i { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.db-compact__live--off { color: var(--faint); }
.db-compact__menu { display: inline-flex; align-items: center; gap: 5px; flex: none; font-family: var(--font);
  font-weight: 700; font-size: 0.85rem; color: var(--ink); background: var(--card, #fff); border: 1px solid var(--line);
  border-radius: 999px; padding: 0.5rem 0.9rem; min-height: 40px; cursor: pointer; }
.db-compact__menu:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
@media (max-width: 900px) {
  .ah-shell--dash .db-compact {
    display: flex; align-items: center; justify-content: space-between; gap: 0.75rem;
    padding: 0.7rem clamp(0.9rem, 4vw, 1.4rem);
    background: var(--bg); border-bottom: 1px solid var(--line); position: sticky; top: 0; z-index: 5;
  }
  /* the full rail (utilities) becomes an off-canvas bottom sheet */
  /* site-mobile-dashboard-rail (kickback #443-a): CLOSED = display:none so the rail can NEVER sit in the
     page flow at ≤900px (the founder-reported inline-rail). The prior translateY(105%) off-canvas left the
     rail as a fixed element that leaks into flow if a fixed containing block is ever established on an
     ancestor; display:none removes it from layout entirely. It becomes the bottom sheet ONLY on Menu tap. */
  .ah-shell--dash .ah-rail {
    display: none;
    position: fixed; left: 0; right: 0; bottom: 0; top: auto; width: 100%; height: auto;
    max-height: 86vh; overflow-y: auto; z-index: 60; border: none; border-radius: 20px 20px 0 0;
    box-shadow: 0 -20px 50px -20px rgba(20, 15, 10, 0.4); background: var(--card, #fff);
    padding: 1.1rem clamp(0.9rem, 4vw, 1.4rem) calc(1.2rem + env(safe-area-inset-bottom));
    flex-direction: column; gap: 0.5rem;
  }
  .ah-shell--dash.sheet-open .ah-rail { display: flex; animation: dash-sheet-up 0.28s var(--ease-out, ease); }
  .ah-shell--dash .ah-rail .ah-rwm { display: none; } /* the compact bar already carries the wordmark/brand */
  .ah-shell--dash .ah-railnav { flex-direction: column; flex-wrap: nowrap; }
  .ah-shell--dash .db-sheet-backdrop {
    display: block; position: fixed; inset: 0; z-index: 55; background: rgba(20, 15, 10, 0.42);
  }
  .ah-shell--dash .db-sheet-backdrop[hidden] { display: none; }
  @media (prefers-reduced-motion: reduce) { .ah-shell--dash.sheet-open .ah-rail { animation: none; } }
}
@keyframes dash-sheet-up { from { transform: translateY(100%); } to { transform: translateY(0); } }

/* ============================================================
   site-creator-shell-ia SLICE 2a — the /dashboard body: two-pane (home/gallery + preview) + glass app cards.
   Reuses the .ah-rail / .ah-preview / .ah-btn chrome from slice 1; adds only the dashboard-specific pieces.
   ============================================================ */
/* clause-8 reachability: the account chip injected at the rail bottom (sign-out + billing). */
.ah-railacct { margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--line); }
/* site-dashboard-audit-fixes (part 2): the foot used a wrapping flex, so in the ~246px rail the avatar,
   email, Upgrade and Sign out wrapped onto ragged lines (founder: misaligned). Lay them on ONE grid — an
   identity row (avatar + email) then each action chip full-width on its own row, so all actions share the
   same left/right edges. Auto-placement handles any number of chips (Upgrade / Sign out / a Test chip). */
.ah-railacct .dboard-account { display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: center; gap: 8px; }
.ah-railacct .dboard-account__avatar { grid-column: 1; }
.ah-railacct .dboard-account .account__email { grid-column: 2; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ah-railacct .dboard-account .chip { grid-column: 1 / -1; width: 100%; }
/* two-pane: main (hero + gallery) + a sticky preview column, mirroring the hub's .ah-wrap. */
.dash-wrap { max-width: 1180px; margin: 22px auto 0; padding: 0 clamp(1.25rem, 4vw, 2.5rem);
  display: grid; grid-template-columns: 1fr 320px; gap: 30px; align-items: start; }
.dash-main { min-width: 0; }
.dash-preview-col { position: sticky; top: 22px; }
/* fix-dashboard-toggle-layout-stability (founder video ruling 2026-07-21): the Web|Phone toggle swaps ONLY
   the preview frame; the LEFT content column + the page NEVER reflow. This OVERRULES + DELETES the #436-era
   `.dash-wrap:has(.appprev[data-view="web"])` widening (it grew the page to 1440px and re-flowed the grid to
   `minmax(520px,1fr) minmax(460px,600px)`, shrinking the left column ~750->520px on every toggle — the exact
   founder hit; it also pushed the preview past PHONE_MIN_W, flipping the runtime pin->unpin and thrashing the
   frame into the "collapsed blank / Starting your live preview" flash). The grid now stays a constant
   `1fr 320px` in both views; the Web browser-chrome frame fits INSIDE the reserved 320px column (reserve,
   don't reflow — the /build `--wb-stage-h` philosophy), so the sandbox stays pinned + alive across a switch. */
.gallery2a { margin-top: 26px; }
.gallery2a__head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 14px; flex-wrap: wrap; }
.section-lab { font-size: 13px; font-weight: 800; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); }
.gallery2a__count { color: var(--faint); font-weight: 700; }
.gallery2a__filter-input { border: 1px solid var(--glass-line); background: var(--glass-row); border-radius: 11px;
  padding: 8px 12px; font: inherit; font-size: 13px; color: var(--ink); min-width: 180px; }
.gallery2a__filter-input:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.appgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 14px; }
.appcard2a { display: flex; flex-direction: column; gap: 12px; padding: 16px; border-radius: 20px; text-decoration: none;
  background: var(--glass-row); border: 1px solid var(--glass-line); box-shadow: var(--e1); transition: transform .15s, box-shadow .15s; }
.appcard2a:hover { transform: translateY(-2px); box-shadow: var(--e2); }
.appcard2a .top { display: flex; align-items: center; gap: 11px; }
.appcard2a .amono { flex: none; width: 38px; height: 38px; border-radius: 11px; display: grid; place-items: center; color: #fff;
  font-weight: 800; font-size: 16px; background: linear-gradient(150deg, var(--accent-hi), var(--accent-2)); }
.appcard2a.draft .amono { background: linear-gradient(150deg, #b8a99d, #8a7d73); }
.appcard2a .al { flex: 1; min-width: 0; }
/* site-design-polish-batch item 4: on a LIVE card the "Live" pill squeezed the name to ~81px, so
   "The Strong Cook Table" ellipsized on one line despite ample card width. Let the name breathe over up to
   TWO lines (clamped) instead of a single truncated line — common 2-4 word app names now show in full. */
.appcard2a .al b { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden;
  font-size: 14.5px; font-weight: 700; color: var(--title); letter-spacing: -0.01em; line-height: 1.25; }
.appcard2a .stat { flex: none; font-size: 10.5px; font-weight: 800; border-radius: 999px; padding: 3px 9px; }
.appcard2a .stat.live { color: #1B7A4B; background: color-mix(in srgb, #1B7A4B 12%, #fff); }
.appcard2a .stat.draft { color: var(--muted); background: var(--line); }
.appcard2a .link { font-size: 11.5px; color: var(--faint); overflow-wrap: anywhere; }
.appcard2a.new { align-items: center; justify-content: center; gap: 8px; min-height: 118px; background: transparent;
  border: 1.5px dashed var(--line-2); color: var(--muted); }
.appcard2a.new:hover { border-color: color-mix(in srgb, var(--accent) 45%, transparent); color: var(--accent-2); transform: none; box-shadow: none; }
.appcard2a.new .plus { font-size: 20px; font-weight: 800; line-height: 1; }
.appcard2a.new span { font-size: 13px; font-weight: 700; }
.appcard2a.skel { min-height: 96px; background: var(--glass-row); border-color: var(--line); opacity: 0.6; }
.gallery__notice { grid-column: 1 / -1; color: var(--muted); font-size: 14px; padding: 12px 2px; }

/* site-draft-delete: a DRAFT card's ⋯ menu (Delete draft…). The wrapper is the grid cell; the <a> card
   fills it, and the ⋯ button + popover overlay the top-right (kept OUT of the <a> to avoid nested
   interactives). LIVE cards render as a bare <a> — no wrapper, no menu. */
.appcard2a-wrap { position: relative; display: flex; }
.appcard2a-wrap > .appcard2a { flex: 1 1 auto; min-width: 0; }
.appcard2a-wrap .appcard2a .top { padding-right: 26px; } /* clear the ⋯ button */
.appcard2a__menubtn {
  position: absolute; top: 10px; right: 10px; z-index: 2;
  width: 26px; height: 26px; border-radius: 8px; border: 1px solid transparent;
  background: transparent; color: var(--muted); cursor: pointer; line-height: 1;
  font-size: 16px; display: grid; place-items: center;
}
.appcard2a__menubtn:hover { background: color-mix(in srgb, var(--ink) 6%, transparent); color: var(--ink); }
.appcard2a__menubtn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.appcard2a__menu {
  position: absolute; top: 40px; right: 10px; z-index: 5; min-width: 210px;
  background: #fff; border: 1px solid var(--line-2); border-radius: 12px; box-shadow: var(--e2); padding: 6px;
}
.appcard2a__menu[hidden] { display: none; }
.appcard2a__menuitem {
  display: block; width: 100%; text-align: left; border: 0; background: none; cursor: pointer;
  font: inherit; font-size: 13.5px; padding: 8px 10px; border-radius: 8px; color: var(--ink);
}
.appcard2a__menuitem:hover { background: var(--glass-row, #f6f1ec); }
.appcard2a__menuitem--danger { color: #C0392B; font-weight: 700; }
.appcard2a__confirm { margin: 4px 6px 8px; font-size: 13px; color: var(--ink); line-height: 1.4; }
.appcard2a__confirmrow { display: flex; justify-content: flex-end; gap: 8px; }
@media (max-width: 1080px) {
  .dash-wrap { grid-template-columns: 1fr; }
  .dash-preview-col { display: none; }
}

/* cards + rows */
.ah-card { background: var(--glass-row); backdrop-filter: var(--blur); -webkit-backdrop-filter: var(--blur);
  border: 1px solid var(--glass-line); border-radius: 20px; box-shadow: var(--e2); padding: 18px 20px; margin-bottom: 18px; }
.ah-card--danger { border-color: color-mix(in srgb, #C0392B 22%, var(--glass-line)); }
.ah-card__head { display: flex; align-items: flex-end; justify-content: space-between; gap: 14px; margin-bottom: 14px; }
.ah-card__head h2 { margin: 0; font-size: 17px; font-weight: 800; letter-spacing: -0.02em; color: var(--title); }
.ah-sub { margin: 3px 0 0; font-size: 12.5px; color: var(--muted); }
/* site-archive-return-telemetry: the retention count. Number carries the metric-strip's numeric voice
   (tabular, tight, ink), the label sits quietly beside its baseline. A real 0 renders exactly like any other. */
.ah-archret { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.ah-archret__n { font-size: 32px; font-weight: 800; letter-spacing: -0.035em; color: var(--title); font-variant-numeric: tabular-nums; line-height: 1; }
.ah-archret__l { font-size: 13px; font-weight: 600; color: var(--muted); }
.ah-rows { display: flex; flex-direction: column; }
.ah-row { display: flex; align-items: center; gap: 13px; padding: 12px 4px; text-align: left; text-decoration: none;
  border: none; background: none; border-top: 1px solid var(--line); font-family: inherit; color: inherit; width: 100%; cursor: default; }
.ah-rows > .ah-row:first-child { border-top: none; }
.ah-row--act { cursor: pointer; border-radius: 10px; }
.ah-row--act:hover { background: color-mix(in srgb, var(--accent) 6%, #fff); }
a.ah-row { cursor: pointer; }
a.ah-row:hover { background: color-mix(in srgb, var(--accent) 6%, #fff); border-radius: 10px; }
.ah-row__g { flex: none; width: 34px; height: 34px; display: grid; place-items: center; border-radius: 10px;
  background: var(--accent-tint); color: var(--accent-2); }
.ah-row__main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.ah-row__t { font-size: 14px; font-weight: 700; letter-spacing: -0.01em; color: var(--title); }
.ah-row__m { font-size: 12.5px; color: var(--muted); }
.ah-row__end { flex: none; color: var(--faint); display: inline-flex; align-items: center; }
.ah-row--q .ah-row__t { font-weight: 700; }
.ah-th { flex: none; width: 44px; height: 44px; border-radius: 11px; background-size: cover; background-position: center;
  box-shadow: inset 0 0 0 1px rgba(0,0,0,.05); }
.ah-th--empty { background: linear-gradient(150deg, #f6d9c9, #eab79f); }
.ah-editlink { display: inline-flex; align-items: center; gap: 4px; margin-top: 12px; color: var(--accent-2);
  font-weight: 700; font-size: 13px; text-decoration: none; }
.ah-editlink:hover { text-decoration: underline; }

/* money band */
.ah-band { background: linear-gradient(155deg, #fff, var(--peach)); border: 1px solid var(--glass-line); border-radius: 20px;
  box-shadow: var(--e2); padding: 22px; margin-bottom: 18px; }
.ah-band--live { background: linear-gradient(155deg, #fff, color-mix(in srgb, #1B7A4B 8%, #fff)); }
.ah-band__k { font-size: 11.5px; font-weight: 800; letter-spacing: 0.06em; text-transform: uppercase; color: var(--accent-2); }
.ah-band h2 { margin: 6px 0 6px; font-size: 21px; font-weight: 800; letter-spacing: -0.03em; color: var(--title); }
.ah-band p { margin: 0 0 16px; font-size: 13.5px; color: var(--muted); line-height: 1.5; max-width: 52ch; }
.ah-price { flex: none; min-width: 70px; font-size: 19px; font-weight: 800; letter-spacing: -0.03em; color: var(--title); font-variant-numeric: tabular-nums; }
.ah-price small { font-size: 12px; font-weight: 700; color: var(--faint); margin-left: 3px; }

/* settings rows */
.ah-srow { display: flex; align-items: center; justify-content: space-between; gap: 14px; padding: 13px 4px; border-top: 1px solid var(--line); }
.ah-srow:first-child { border-top: none; }
.ah-sl { font-size: 14px; font-weight: 700; color: var(--title); }
.ah-sl--danger { color: #C0392B; }
.ah-sd { font-size: 12.5px; color: var(--muted); margin-top: 2px; }

/* empty / dlink */
.ah-empty { font-size: 13.5px; color: var(--muted); padding: 6px 4px; }
.ah-empty--pad { text-align: center; padding: 30px 20px; }
.ah-empty--pad p { margin: 0 0 14px; }
.ah-dlink { background: none; border: none; color: var(--accent-2); font-weight: 700; font-size: inherit; cursor: pointer; padding: 0; font-family: inherit; }
.ah-dlink:hover { text-decoration: underline; }

/* preview column */
.ah-preview-col { position: sticky; top: 92px; }
.ah-preview-cap { font-size: 12px; font-weight: 700; color: var(--faint); text-align: center; margin-bottom: 12px; }
/* fix-residence-preview-edit-mode: the Preview|Edit control row above the residence live preview (reuses the
   builder's .wb-edit__toggle / .wb-edit__seg / .wb-edit__status glass pill). Centered to match the caption.
   The explicit [hidden] guard beats the author display (an author display:flex otherwise wins over the UA
   [hidden] display:none at equal specificity — the same trap the builder's stale view-toggle hit). */
.ah-preview-edit { display: flex; align-items: center; justify-content: center; gap: 0.6rem; flex-wrap: wrap; margin-bottom: 12px; }
.ah-preview-edit[hidden] { display: none; }
/* the one-time Edit hint / Saved tick wraps onto its own centered line under the pill, never ragged-left. */
.ah-preview-edit .wb-edit__status { flex-basis: 100%; text-align: center; }
.ah-preview .appprev { width: 100%; max-width: 340px; margin: 0 auto; gap: 0.9rem; }
/* fix-dashboard-live-preview-frame DEFECT 2 (the "long phone", founder-hit 07-09/07-18/07-21): a hard
   600px height on a 200px-max-width frame pinned BOTH dimensions, so the base 9/19.3 aspect-ratio was
   ignored and the phone rendered ~1:3.0. Same bug class + same accepted cure as .mc-preview (2026-07-08):
   drop the hard height, let the aspect govern, and widen so the visual height stays ~600px (280px x
   19.3/9 = 600px) at true iPhone proportions. Web view keeps its own aspect-auto sizing; the min-height
   below preserves the column height it had from the old 600px rule (no toggle jump). */
.ah-preview .appprev__phone { max-width: 280px; margin-inline: auto; }
.ah-preview .appprev[data-view="web"] .appprev__phone { min-height: 600px; }
/* site-demo-fix-batch (Frame B, state 2): the graceful empty preview — one honest sentence + one CTA,
   a considered card instead of an empty well of repeated reassurance badges. */
.ah-preview-empty {
  display: flex; flex-direction: column; align-items: center; text-align: center;
  max-width: 340px; margin: 0 auto; gap: 0.55rem;
  background: var(--card); border: 1px solid var(--line-2); border-radius: 20px;
  padding: clamp(1.5rem, 4vw, 2.4rem) 1.4rem;
}
.ah-preview-empty__glyph {
  display: grid; place-items: center; width: 46px; height: 46px; border-radius: 14px;
  background: var(--peach); color: var(--accent-2); margin-bottom: 0.2rem;
}
.ah-preview-empty__title { font-size: 1rem; color: var(--title); letter-spacing: -0.01em; }
.ah-preview-empty__sub { font-size: 0.88rem; color: var(--muted); line-height: 1.5; margin: 0 0 0.4rem; }

/* gate / not-found / error */
.ah-gate { display: grid; place-items: center; padding: 8vh 20px; }
.ah-gate__card { background: var(--glass-row); backdrop-filter: var(--blur); -webkit-backdrop-filter: var(--blur);
  border: 1px solid var(--glass-line); border-radius: var(--r-card); box-shadow: var(--e2); padding: 34px 32px; text-align: center; max-width: 440px; }
.ah-gate__emoji { font-size: 34px; margin-bottom: 6px; }
.ah-gate__title { margin: 0 0 8px; font-size: 22px; font-weight: 800; letter-spacing: -0.03em; color: var(--title); }
.ah-gate__sub { margin: 0 0 20px; font-size: 14.5px; color: var(--muted); line-height: 1.5; }

/* skeletons */
.ah-skel { border-radius: 10px; background: linear-gradient(90deg, rgba(120,90,70,.08), rgba(120,90,70,.14), rgba(120,90,70,.08));
  background-size: 200% 100%; animation: ah-shimmer 1.4s ease-in-out infinite; }
.ah-skel--k { height: 12px; width: 55%; }
.ah-skel--v { height: 26px; width: 45%; margin-top: 8px; }
.ah-skel--row { height: 46px; margin: 8px 0; }
@keyframes ah-shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }

/* confirm / rename dialog */
.ah-scrim { position: fixed; inset: 0; background: rgba(40,25,15,.34); backdrop-filter: blur(3px); z-index: 60;
  opacity: 0; pointer-events: none; transition: opacity .18s; display: grid; place-items: center; }
.ah-scrim.is-on { opacity: 1; pointer-events: auto; }
.ah-confirm { width: 420px; max-width: 92vw; background: linear-gradient(180deg, #FCF9F6, #F4ECE6);
  border: 1px solid var(--glass-line); border-radius: var(--r-card); box-shadow: var(--e2); padding: 24px; }
.ah-confirm__t { margin: 0 0 8px; font-size: 18px; font-weight: 800; letter-spacing: -0.02em; color: var(--title); }
.ah-confirm__m { margin: 0 0 18px; font-size: 14px; color: var(--muted); line-height: 1.5; }
.ah-confirm__err { margin: 8px 0 0; font-size: 13px; font-weight: 600; color: #C0392B; }
.ah-confirm__err[hidden] { display: none; }
.ah-confirm__row { display: flex; gap: 12px; justify-content: flex-end; margin-top: 16px; }
.ah-input { width: 100%; border: 1px solid rgba(120,90,70,.2); background: rgba(255,255,255,.8); border-radius: 12px;
  padding: 11px 13px; font-size: 15px; font-family: inherit; color: var(--ink); }
.ah-input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent); }

/* toast */
.ah-toast { position: fixed; left: 50%; bottom: 26px; transform: translate(-50%, 12px); z-index: 90; background: var(--dark);
  color: var(--cream); padding: 11px 18px; border-radius: 12px; font-size: 13.5px; font-weight: 600; box-shadow: var(--e2);
  opacity: 0; pointer-events: none; transition: opacity .2s, transform .2s; }
.ah-toast.is-on { opacity: 1; transform: translate(-50%, 0); }

@media (max-width: 640px) {
  .ah-topbar { padding: 10px 16px; gap: 10px; }
  .ah-appname { display: none; }
  .ah-metrics, .ah-tabs, .ah-wrap { padding-left: 16px; padding-right: 16px; }
  .ah-metric__v { font-size: 24px; }
}
@media (prefers-reduced-motion: reduce) { .ah-skel { animation: none; } .ah-scrim, .ah-toast { transition: none; } }

/* ============================================================
   builder-webview-toggle — a Web | Phone segmented toggle on the shared preview (default Web).
   Web = a browser-chrome frame (dots + address bar) at column width; Phone = the iPhone frame. ONLY the
   outer frame changes — the sandbox mount (.appprev__content / the runtime iframe) is the SAME element in
   both, and app-runtime.js's ResizeObserver re-scales it when the frame resizes (no remount). Matches the
   approved app-home mock (peach-active seg, hairline pill, browser bar).
   ============================================================ */
/* The segmented toggle — top-right, above the frame. */
.appprev__viewtoggle {
  align-self: flex-end;
  display: inline-flex; gap: 2px; padding: 3px;
  background: #fff; border: 1px solid var(--line); border-radius: 11px; box-shadow: var(--e1);
}
/* No app yet → nothing to preview → hide the toggle (rubric #2 no-app state). */
.appprev[data-state="idle"] .appprev__viewtoggle { display: none; }
.appprev__viewseg {
  border: none; background: none; cursor: pointer; font-family: var(--font);
  font-size: 0.78rem; font-weight: 700; color: var(--faint);
  min-height: 32px; padding: 4px 14px; border-radius: 8px;
  transition: color 0.15s var(--ease-out), background 0.15s var(--ease-out);
}
.appprev__viewseg[aria-pressed="true"] { background: var(--peach); color: var(--accent-2); }
.appprev__viewseg:hover:not([aria-pressed="true"]) { color: var(--ink); }
.appprev__viewseg:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* The browser chrome — hidden in Phone view, shown in Web view (absolute top bar inside the screen). */
.appprev__browserbar {
  display: none;
  position: absolute; top: 0; left: 0; right: 0; z-index: 4;
  height: 34px; align-items: center; gap: 10px; padding: 0 12px;
  background: #F6F1EC; border-bottom: 1px solid var(--line);
}
.appprev__dots { display: inline-flex; gap: 5px; flex: none; }
.appprev__dots i { width: 8px; height: 8px; border-radius: 50%; background: #D9CCC0; display: block; }
.appprev__addr {
  flex: 1; min-width: 0; background: #fff; border: 1px solid var(--line); border-radius: 7px;
  font-size: 0.66rem; color: var(--faint); padding: 4px 10px; font-variant-numeric: tabular-nums;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* fix-builder-postbuild-screen-polish (defect 4): the source eyebrow badge, anchored in the frame header
   row next to the URL bar (reads as metadata about the artifact, not a caption floating in whitespace).
   Only visible in Web view — the browser bar itself is hidden in Phone view. */
.appprev__srcbadge {
  flex: none; display: inline-flex; align-items: center; gap: 5px;
  font-size: 0.62rem; font-weight: 700; letter-spacing: 0.01em;
  color: var(--accent-2, #C03623); background: var(--peach);
  border: 1px solid var(--line); border-radius: 999px; padding: 3px 9px;
  white-space: nowrap; max-width: 46%; overflow: hidden; text-overflow: ellipsis;
}
.appprev__srcbadge[hidden] { display: none; }
.appprev__srcbadge::before {
  content: ""; width: 5px; height: 5px; border-radius: 50%; flex: none;
  background: var(--accent-2, #C03623);
}

/* ── WEB view: reshape the outer frame into a browser window (same sandbox content inside). ── */
.appprev[data-view="web"] .appprev__phone {
  width: 100%; max-width: 100%;
  aspect-ratio: auto;                 /* let the surface height define the box; fill the column width */
  min-height: 420px;                  /* fallback so the frame never collapses if a surface sets no height */
  background: #fff;
  border: 1px solid var(--line);
  border-radius: 16px;
  padding: 0;                          /* no phone bezel */
  box-shadow: 0 34px 70px -32px rgba(40, 25, 15, 0.34), var(--e1);
}
.appprev[data-view="web"] .appprev__screen { border-radius: 15px; }
/* fix-served-app-blank-mount (S2/C3): in web view .appprev__phone has min-height but NO definite height,
   so the screen's height:100% resolved to 0 (percentage-height needs a definite parent) and the
   overflow:hidden screen clipped the mount to 0px → the sandbox booted at 0 and never posted "mounted"
   (dashboard-web churn, #458 class). Floor the screen so [data-appprev-screen] can never collapse to 0.
   /build is unaffected (its phone sets a definite height); phone view unaffected (not [data-view=web]). */
.appprev[data-view="web"] .appprev__screen { min-height: 420px; }
.appprev[data-view="web"] .appprev__browserbar { display: flex; }
/* Content clears the browser bar (34px) instead of the iOS safe area; phone chrome hidden. */
.appprev[data-view="web"] .appprev__content { top: 34px; }
.appprev[data-view="web"] .appprev__statusbar,
.appprev[data-view="web"] .appprev__island,
.appprev[data-view="web"] .appprev__home { display: none; }

/* ── builder-webview-width: a browser window FILLS the pane; the app stays mobile-width ──
   Web view is a real browser window, so its outer frame fills the preview pane's width up to a
   sane desktop cap — instead of the 360px phone column it was capped to on /build, which made
   the browser render as a narrow phone-width sliver (the founder-reported defect). Scoped to the
   /build pane (`.wb__preview`); the ~420px manage / App-Home columns already fill and are left
   untouched (there min(100%, 960px) collapses to the column width anyway). */
.wb__preview .appprev[data-view="web"] { max-width: min(100%, 960px); }
/* fix-builder-postbuild-screen-polish (defect 3): the Web|Phone toggle sits IN FLOW directly above the
   frame, right-aligned to the frame's own edge — a control that visibly belongs to the frame below it,
   never overlapping the chrome. (Supersedes the 2026-07-08 absolute-to-pane anchor: that was a workaround
   for the sideways jump on a view switch, which the width-stable container above now removes at the root.)
   base `.appprev__viewtoggle { align-self: flex-end }` does the right-alignment; we only re-assert static. */
.wb__preview { position: relative; }
.wb__preview .appprev__viewtoggle { position: static; align-self: flex-end; }
/* builder-edit-toggle-clip + site-preview-toggle-layout-jump: cap the (content-driven) web frame to the
   SAME reserved stage height as the phone frame. This keeps two invariants at once: (a) the web frame never
   exceeds the pane and clips the Preview|Edit toggle under the top bar; (b) it never grows TALLER than the
   phone frame, which on tall viewports would make toggling back to Phone shrink the column (the jump). The
   web frame stays content-driven up to this cap and is vertically centered in the stage; the runtime's
   ResizeObserver re-fits the sandbox when the frame changes. min-height (420px) still wins on tiny windows. */
.wb__preview .appprev[data-view="web"] .appprev__phone { max-height: var(--wb-stage-h); }
/* The generated app is a FIXED mobile-width layout — the sandbox pins a 393px viewport (app-runtime),
   so widening the frame must NOT blow the app up to fill it (that scales a phone UI ~2.4×). Instead we
   render it at ~native width in a CENTERED content column — exactly how a mobile-first site looks in a
   desktop browser: wide chrome + address bar, phone-width page centered. On narrow surfaces (phone
   view, or the ~420px columns) min(100%, 460px) collapses to 100%, so those are byte-identical to today. */
.appprev[data-view="web"] .appprev__content {
  left: 50%; right: auto; transform: translateX(-50%);
  width: min(100%, 460px);
}

/* ── fix-builder-postbuild-screen-polish (defect 2): responsive vs legacy Web-view presentation ──
   A RESPONSIVE (skeleton) app carries real desktop breakpoints and the sandbox unpins it to the frame's
   real width (app-runtime isSkeletonCode) — so let its content column FILL the frame instead of the
   phone-width 460 cap, and its own media queries express the desktop layout. This ONLY loosens the cap for
   apps flagged responsive; a LEGACY (pinned, fixed-mobile-width) app keeps the 460 cap — widening its
   frame must never blow the phone UI up (the documented builder-webview-width rule). */
.appprev[data-view="web"][data-responsive="true"] .appprev__content {
  left: 0; right: 0; transform: none; width: auto;
}
/* A LEGACY app in Web view is a phone-width column stranded in a wide browser frame — rather than let it
   read as broken, present it DELIBERATELY: a subtly dimmed canvas with the app column sitting on it as a
   considered card, plus an honest one-line note (no em dash). */
.appprev[data-view="web"][data-responsive="false"] .appprev__phone { background: #ECE6DF; }
.appprev[data-view="web"][data-responsive="false"] .appprev__content {
  box-shadow: 0 12px 34px -14px rgba(40, 25, 15, 0.28);
}
/* site-demo-fix-batch (Frame C / Q3): the legacy rebuild note was removed — the dimmed canvas alone
   communicates "phone app" without an apology. (.appprev__legacynote styles retired with the element.) */

@media (prefers-reduced-motion: reduce) { .appprev__viewseg { transition: none; } }

/* ============ SLICE 2b — the /dashboard home story ============
   Look-locked to docs/design-mocks/creator-shell/dashboard-slice2.html (#315). Every rule is SCOPED under
   `.dash-home` so the mock's generic class names (.card/.step/.metric/.note/.trow/.bar/.tick) cannot collide
   with the many unrelated global rules of the same name. The `.ah-btn` family + `.section-lab` are reused
   from the shared shell (slice 1/2a). Two local tokens the global :root lacks are defined on the scope. */
.dash-home { --accent-soft: color-mix(in srgb, var(--accent) 9%, #fff); --live-2: #1B7A4B; }
.dash-home h1, .dash-home h3, .dash-home h4 { margin: 0; color: var(--title); font-weight: 800; letter-spacing: -.03em; }
.dash-home p { margin: 0; }
.dash-home__skel { height: 220px; border-radius: var(--r-card); background: var(--glass-row); border: 1px solid var(--glass-line); box-shadow: var(--e2); opacity: .5; }

.dash-home .ctop { display: flex; align-items: flex-start; justify-content: space-between; gap: 18px; margin-bottom: 24px; }
.dash-home .ctop h1 { font-size: 29px; line-height: 1.05; }
.dash-home .ctop .sub { margin-top: 8px; font-size: 14.5px; color: var(--muted); max-width: 52ch; line-height: 1.5; }
.dash-home .acts { display: flex; gap: 9px; flex: none; flex-wrap: wrap; }
/* site-dashboard-one-level (SLICE 1a): the ONE share surface — the header link chip. */
/* site-dashboard-one-level SLICE 1b — app-home's header link chip (the ONE share surface here), mirroring
   the dashboard chip below. Sits above the metrics bar; wraps on phones. */
.ah-topline { padding: 4px 0 2px; }
/* fix-audience-share-pulse: a one-shot calm accent highlight so the one-door share is perceptible when the
   Live panel is already in view. A soft coral ring + wash that expands and fades once (not a flash); the JS
   adds this class on a share-CTA route and self-clears it. Reduced-motion drops the animation (focus stays). */
.ah-topline--pulse { animation: ah-topline-pulse 1.1s ease-out 1; border-radius: 14px; }
@keyframes ah-topline-pulse {
  0%   { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 42%, transparent); background: color-mix(in srgb, var(--accent) 9%, transparent); }
  60%  { box-shadow: 0 0 0 7px color-mix(in srgb, var(--accent) 0%, transparent); background: color-mix(in srgb, var(--accent) 4%, transparent); }
  100% { box-shadow: 0 0 0 0 transparent; background: transparent; }
}
@media (prefers-reduced-motion: reduce) { .ah-topline--pulse { animation: none; } }
.ah-topline .linkchip { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.ah-topline .linkchip__url { font-size: 12.5px; font-weight: 700; color: var(--muted);
  background: var(--glass-row, #f6f1ec); border: 1px solid var(--line); border-radius: 999px; padding: 6px 12px;
  max-width: 240px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ah-topline .linkchip .ah-btn { flex: none; }
.ah-topline .linkchip--off .linkchip__note { font-size: 12.5px; color: var(--faint); }
/* site-your-app-residence-epic S3: the Live panel's QR popover (revealed by the QR-code toggle). Full-width
   row that wraps below the chip; the drawn QR from qrcode.js sits beside a scan caption. */
.ah-topline .linkchip__qr { flex-basis: 100%; margin-top: 8px; display: flex; align-items: center; gap: 12px; }
.ah-topline .linkchip__qr[hidden] { display: none; }
.ah-topline .linkchip__qrimg { flex: none; width: 108px; height: 108px; padding: 6px; background: #fff;
  border: 1px solid var(--glass-line); border-radius: 12px; box-shadow: var(--e1); }
.ah-topline .linkchip__qrimg svg { display: block; width: 100%; height: 100%; }
.ah-topline .linkchip__qrcap { font-size: 12.5px; color: var(--faint); }

.dash-home .linkchip { display: flex; align-items: center; gap: 10px; flex: none; flex-wrap: wrap; }
.dash-home .linkchip__url { font-size: 12.5px; font-weight: 700; color: var(--muted);
  background: var(--glass-row, #f6f1ec); border: 1px solid var(--line); border-radius: 999px; padding: 6px 12px;
  max-width: 240px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dash-home .linkchip .ah-btn { flex: none; }
.dash-home .linkchip--off .linkchip__note { font-size: 12.5px; color: var(--faint); }
.dash-home .eyebrow { font-size: 12.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .11em; color: var(--accent-2); }
.dash-home .section-lab { font-size: 13px; font-weight: 800; letter-spacing: -.01em; color: var(--title); }
.dash-home .stack { display: flex; flex-direction: column; gap: 18px; }

.dash-home .card { background: var(--glass-row); backdrop-filter: var(--blur); -webkit-backdrop-filter: var(--blur); border: 1px solid var(--glass-line); border-radius: var(--r-card); box-shadow: var(--e2); }
/* site-checklist-toggle-and-completion: the slim "earning-ready" row the checklist retires to at 5/5 (a
   .card button). Tap to re-expand; unchecking a step brings the full card back. */
.dash-home .dash-earndone { display: flex; align-items: center; gap: 11px; width: 100%; text-align: left; cursor: pointer; font: inherit; color: inherit; padding: 15px 18px; }
.dash-home .dash-earndone__ic { flex: none; width: 30px; height: 30px; border-radius: 999px; display: grid; place-items: center; color: #fff; background: var(--ok, #1b7a4b); }
.dash-home .dash-earndone__ic svg { width: 15px; height: 15px; }
.dash-home .dash-earndone__tx { display: flex; flex-direction: column; min-width: 0; }
.dash-home .dash-earndone__tx b { font-size: 14.5px; font-weight: 800; letter-spacing: -.01em; color: var(--title); }
.dash-home .dash-earndone__tx span { font-size: 12px; color: var(--muted); }
.dash-home .dash-earndone:hover { border-color: color-mix(in srgb, var(--ok, #1b7a4b) 40%, var(--glass-line)); }
.dash-home .card-h { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 17px 20px 0; }
.dash-home .card-h h3 { font-size: 15.5px; letter-spacing: -.02em; }
.dash-home .card-h .hint { font-size: 12px; color: var(--faint); }

.dash-home .step { display: flex; gap: 13px; padding: 14px 4px; border-top: 1px solid var(--line); }
.dash-home .step:first-of-type { border-top: 0; }
.dash-home .tick { width: 25px; height: 25px; border-radius: 50%; flex: none; display: grid; place-items: center; margin-top: 1px; }
.dash-home .tick.done { background: linear-gradient(150deg, var(--accent-hi), var(--accent-2)); color: #fff; }
.dash-home .tick.done svg { width: 14px; height: 14px; }
.dash-home .tick.todo { background: #fff; border: 1.5px dashed color-mix(in srgb, var(--accent) 45%, #d9cabf); }
.dash-home .tick.todo b { font-size: 11.5px; font-weight: 800; color: var(--accent-2); }
/* site-dashboard-audit-fixes (part 3): a manually-checkable step's circle is a real <button> — reset the UA
   chrome (the .tick.done/.todo fill above wins on specificity) and show it's interactive. */
.dash-home button.tick { font: inherit; padding: 0; border: 0; }
.dash-home .tick--toggle { cursor: pointer; }
.dash-home .tick--toggle:focus-visible { outline: 2px solid var(--accent-2); outline-offset: 2px; }
.dash-home .step .body { flex: 1; min-width: 0; }
.dash-home .step .body h4 { font-size: 14px; font-weight: 700; letter-spacing: -.015em; }
.dash-home .step .body p { font-size: 12.5px; color: var(--muted); margin-top: 3px; line-height: 1.45; }
.dash-home .step .act { align-self: center; flex: none; }
/* fix-site-mobile-audit-sweep CRITICAL #2: step 3's long CTA ("Put your link in your bio") is flex:none,
   so at phone widths it held its ~360px intrinsic width and starved the flex:1 text column to one word
   per line. Below 560px, wrap the CTA onto its own row under the body (indented past the tick). */
@media (max-width: 560px) {
  .dash-home .step { flex-wrap: wrap; }
  .dash-home .step .act { flex-basis: 100%; align-self: stretch; margin: 8px 0 0 38px; }
}
.dash-home .bar { height: 8px; border-radius: 20px; background: rgba(80,50,35,.09); overflow: hidden; margin-bottom: 6px; }
.dash-home .bar i { display: block; height: 100%; border-radius: 20px; background: linear-gradient(90deg, var(--accent-hi), var(--accent)); }

.dash-home .metrics { display: grid; grid-template-columns: repeat(4, 1fr); gap: 13px; }
.dash-home .metric { padding: 15px; position: relative; }
.dash-home .metric .ic { width: 29px; height: 29px; border-radius: 10px; display: grid; place-items: center; background: var(--accent-soft); color: var(--accent-2); margin-bottom: 10px; }
.dash-home .metric .ic svg { width: 15px; height: 15px; }
.dash-home .metric .n { font-size: 24px; font-weight: 800; letter-spacing: -.03em; color: var(--title); line-height: 1; }
.dash-home .metric .k { font-size: 12px; font-weight: 600; color: var(--muted); margin-top: 4px; }
.dash-home .metric .d { font-size: 11px; color: var(--faint); margin-top: 7px; line-height: 1.4; }
.dash-home .metric .wk { font-size: 11px; font-weight: 700; color: var(--live-2); margin-top: 5px; }
.dash-home .metric.empty .n { color: color-mix(in srgb, var(--faint) 60%, #c9bcb0); }

.dash-home .trow { display: flex; align-items: center; gap: 13px; padding: 12px 20px; border-top: 1px solid var(--line); }
.dash-home .trow:first-of-type { border-top: 0; }
.dash-home .trow .tg { width: 34px; height: 34px; border-radius: 10px; flex: none; display: grid; place-items: center; background: var(--accent-tint); color: var(--accent-2); }
.dash-home .trow .tg svg { width: 16px; height: 16px; }
.dash-home .trow .tl { flex: 1; min-width: 0; }
.dash-home .trow .tl b { font-size: 13.5px; font-weight: 700; color: var(--title); letter-spacing: -.01em; display: block; }
.dash-home .trow .tl span { font-size: 11.5px; color: var(--faint); }
.dash-home .trow .tv { text-align: right; font-size: 12.5px; font-weight: 700; color: var(--accent-2); flex: none; }
.dash-home .trow .tv small { display: block; font-size: 10.5px; font-weight: 600; color: var(--faint); }

.dash-home .note { display: flex; gap: 10px; align-items: flex-start; padding: 13px 15px; border-radius: 16px; background: var(--accent-soft); border: 1px solid color-mix(in srgb, var(--accent) 16%, transparent); }
.dash-home .note svg { width: 16px; height: 16px; color: var(--accent-2); flex: none; margin-top: 1px; }
.dash-home .note p { font-size: 12.5px; color: var(--ink); line-height: 1.5; }
.dash-home .note b { color: var(--accent-2); }

.dash-home .dash-toast { position: fixed; left: 50%; bottom: 26px; transform: translate(-50%, 10px); background: var(--title); color: #fff; font-size: 13px; font-weight: 600; padding: 9px 16px; border-radius: 999px; box-shadow: var(--e2); opacity: 0; pointer-events: none; transition: opacity .18s ease, transform .18s ease; z-index: 60; }
.dash-home .dash-toast[data-on="1"] { opacity: 1; transform: translate(-50%, 0); }

@media (max-width: 1000px) {
  .dash-home .metrics { grid-template-columns: 1fr 1fr; }
  .dash-home .ctop { flex-direction: column; }
}
/* fix-site-mobile-audit-sweep MEDIUM #4: several dashboard strings sat below the 14px legibility bar on
   phones (step bodies 12.5px, metric label 12 / desc 11 / wk 11, live-URL 11.5). Nudge them up at phone
   widths so the logged-in home reads as designed, not cramped. */
@media (max-width: 560px) {
  .dash-home .step .body p { font-size: 13px; }
  .dash-home .metric .k { font-size: 12.5px; }
  .dash-home .metric .d { font-size: 12px; }
  .dash-home .metric .wk { font-size: 12px; }
  .ah-rlive__url { font-size: 12.5px; }
}

/* ============================================================================
   site-push-management — the creator push surface (app-home Audience › Notifications).
   Ported 1:1 from the founder-approved look-lock docs/design-mocks/push-management-mock.html
   (tokens already defined above). The mock's hard "frequency cap" card is intentionally NOT
   ported — superseded by the founder amendment (no marketed cap; soft >3/7d confirm + silent
   server ceiling instead).
   ============================================================================ */
/* toggle switch */
.pn-toggle{position:relative;display:inline-flex;align-items:center;gap:10px;cursor:pointer;user-select:none}
/* Transparent but FILLS the toggle (on top) so the whole control is the click target — a fan tap and a
   programmatic click both land on it. The `+ .pn-toggle__track` state styling still applies (adjacency
   is DOM-order, not stacking). */
.pn-toggle input{position:absolute;inset:0;width:100%;height:100%;opacity:0;margin:0;cursor:pointer;z-index:1}
.pn-toggle__track{width:42px;height:25px;border-radius:999px;background:rgba(120,90,70,.18);position:relative;
  transition:background .15s;flex:none}
.pn-toggle__track::after{content:"";position:absolute;top:2.5px;left:2.5px;width:20px;height:20px;border-radius:50%;
  background:#fff;box-shadow:0 1px 3px rgba(40,30,25,.3);transition:transform .15s}
.pn-toggle input:checked + .pn-toggle__track{background:linear-gradient(150deg,var(--accent-hi),var(--accent-2))}
.pn-toggle input:checked + .pn-toggle__track::after{transform:translateX(17px)}
.pn-toggle input:disabled + .pn-toggle__track{opacity:.45;cursor:not-allowed}
.pn-toggle input:focus-visible + .pn-toggle__track{outline:2px solid var(--accent);outline-offset:2px}
.pn-toggle__lab{display:flex;flex-direction:column;gap:2px}
.pn-toggle__lab b{font-size:14px;font-weight:700;color:var(--title);letter-spacing:-.01em}
.pn-toggle__lab span{font-size:12.5px;color:var(--muted)}
/* PRO pill */
.pn-pro{display:inline-flex;align-items:center;font-size:9.5px;font-weight:800;letter-spacing:.07em;
  color:#fff;background:linear-gradient(150deg,var(--accent-hi),var(--accent-2));padding:2.5px 8px;border-radius:999px}
.pn-pro--quiet{color:var(--accent-2);background:var(--accent-tint)}
/* section row w/ toggle */
.pn-optrow{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:14px 2px}
.pn-optrow + .pn-optrow{border-top:1px solid var(--line)}
/* subscriber count */
.pn-subcount{display:flex;align-items:center;gap:16px;padding:4px 4px 6px}
.pn-subcount__n{font-size:30px;font-weight:800;letter-spacing:-.03em;color:var(--title);font-variant-numeric:tabular-nums;line-height:1}
.pn-subcount__l{font-size:12.5px;color:var(--muted);margin-top:3px}
/* lockscreen notification preview */
.pn-lock{width:100%;max-width:300px;border-radius:26px;padding:26px 14px 18px;position:relative;overflow:hidden;
  background:linear-gradient(165deg,#2a2f3d,#14161e);box-shadow:0 20px 44px -18px rgba(20,15,10,.55);margin:0 auto}
.pn-lock__time{text-align:center;color:#fff;font-weight:700;font-size:34px;letter-spacing:-.02em;margin-bottom:2px}
.pn-lock__date{text-align:center;color:rgba(255,255,255,.65);font-size:12px;font-weight:600;margin-bottom:16px}
.pn-notif{display:flex;gap:10px;align-items:flex-start;background:rgba(255,255,255,.14);backdrop-filter:blur(20px);
  border:1px solid rgba(255,255,255,.18);border-radius:16px;padding:11px 12px;box-shadow:0 8px 20px -10px rgba(0,0,0,.4)}
.pn-notif__ic{flex:none;width:32px;height:32px;border-radius:9px;display:grid;place-items:center;color:#fff;
  font-size:14px;font-weight:800;background:linear-gradient(150deg,var(--accent-hi),var(--accent-2));box-shadow:var(--e1)}
.pn-notif__body{flex:1;min-width:0}
.pn-notif__top{display:flex;align-items:baseline;justify-content:space-between;gap:8px}
.pn-notif__app{font-size:11px;font-weight:800;letter-spacing:.03em;color:rgba(255,255,255,.75);text-transform:uppercase}
.pn-notif__now{font-size:10.5px;color:rgba(255,255,255,.5);flex:none}
.pn-notif__title{font-size:13.5px;font-weight:700;color:#fff;margin-top:2px;letter-spacing:-.01em}
.pn-notif__msg{font-size:12.5px;color:rgba(255,255,255,.82);margin-top:2px;line-height:1.35}
.pn-lockcap{text-align:center;font-size:11.5px;font-weight:700;color:var(--faint);margin-top:12px}
/* composer */
.pn-field{display:flex;flex-direction:column;gap:6px;margin-bottom:14px}
.pn-field label{font-size:12px;font-weight:700;color:var(--muted)}
.pn-field select,.pn-field textarea,.pn-field input[type=text]{font-family:inherit;font-size:13.5px;color:var(--ink);
  border:1px solid var(--glass-line);background:rgba(255,255,255,.7);border-radius:11px;padding:9px 12px;resize:vertical}
.pn-field select:focus,.pn-field textarea:focus,.pn-field input:focus{outline:2px solid var(--accent);outline-offset:1px}
.pn-radios{display:flex;flex-direction:column;gap:9px;margin-bottom:16px}
.pn-radio{display:flex;align-items:flex-start;gap:9px;padding:10px 11px;border-radius:12px;border:1px solid var(--glass-line);
  background:rgba(255,255,255,.5);cursor:pointer}
.pn-radio input{margin-top:2px}
.pn-radio__lab b{display:block;font-size:13px;font-weight:700;color:var(--title)}
.pn-radio__lab span{font-size:12px;color:var(--muted)}
.pn-composer-grid{display:grid;grid-template-columns:minmax(0,1fr) 260px;gap:26px;align-items:start}
@media (max-width:840px){.pn-composer-grid{grid-template-columns:1fr}}
.pn-sendrow{display:flex;gap:9px;flex-wrap:wrap;margin-top:4px}
/* history table */
.pn-hist{display:flex;flex-direction:column}
.pn-hrow{display:grid;grid-template-columns:minmax(0,1fr) 108px 84px 84px;gap:12px;align-items:center;
  padding:12px 4px;border-top:1px solid var(--line);font-size:13px}
.pn-hist>.pn-hrow:first-child{border-top:none}
.pn-hrow--head{font-size:11px;font-weight:800;text-transform:uppercase;letter-spacing:.06em;color:var(--faint);padding-bottom:8px}
.pn-hmsg{font-weight:700;color:var(--title);letter-spacing:-.01em}
.pn-hwhen{color:var(--muted);font-size:12px}
.pn-hstat{font-variant-numeric:tabular-nums;color:var(--muted)}
.pn-hstat b{color:var(--title);font-weight:800}
@media (max-width:700px){.pn-hrow{grid-template-columns:minmax(0,1fr) 1fr}.pn-hrow>*:nth-child(3),.pn-hrow>*:nth-child(4){grid-column:span 1}}
/* lock scrim over Pro-only content when viewing as Free */
.pn-lockwrap{position:relative}
/* site-design-polish-batch item 7: blur only the SAMPLE CONTENT of a Pro-locked card, never its heading —
   filtering the whole __inner smudged the "Send a push / Sent history" <h2> into a grey blob @390. The
   heading (+ its PRO tag) stays sharp so the lock card leads; the demo fields/preview below dim + blur. */
.pn-lockwrap.is-locked .pn-lockwrap__inner{pointer-events:none;user-select:none}
.pn-lockwrap.is-locked .pn-lockwrap__inner > :not(.ah-card__head){filter:blur(3px) saturate(70%);opacity:.55}
.pn-lockscrim{display:none;position:absolute;inset:0;z-index:5;align-items:center;justify-content:center;text-align:center;
  padding:24px;border-radius:18px}
.pn-lockwrap.is-locked .pn-lockscrim{display:flex}
.pn-lockscrim__card{max-width:340px;display:flex;flex-direction:column;align-items:center;gap:10px;
  background:rgba(255,255,255,.92);backdrop-filter:var(--blur-chrome);border:1px solid var(--glass-line);
  border-radius:18px;padding:20px 22px;box-shadow:var(--e2)}
.pn-lockscrim__ic{width:36px;height:36px;border-radius:11px;display:grid;place-items:center;color:#fff;
  background:linear-gradient(150deg,var(--accent-hi),var(--accent-2));box-shadow:var(--e1)}
.pn-lockscrim__card p{font-size:13px;color:var(--muted);line-height:1.5}
.pn-lockscrim__card b{color:var(--title)}
/* honest note */
.pn-note{display:flex;gap:10px;align-items:flex-start;padding:13px 15px;border-radius:16px;background:var(--accent-soft);
  border:1px solid color-mix(in srgb,var(--accent) 16%,transparent)}
.pn-note svg{width:16px;height:16px;color:var(--accent-2);flex:none;margin-top:1px}
.pn-note p{font-size:12.5px;color:var(--ink);line-height:1.5}
.pn-note b{color:var(--accent-2)}

/* ============================================================================
   site-paywall-redesign-annual — the Pro/Studio paywall modal (mock v2). Adds the Monthly/Annual toggle,
   the "Most popular" badge, and the honest annual strikethrough (struck 12x total + annual price + Save
   pill) to the existing .pricing/.pcard chrome. Mock-token-mapped to the site's design tokens.
   ============================================================================ */
.pcard { position: relative; }
.pricing__cards { margin-top: 0.5rem; } /* room for the Most-popular badge that sits above the card */
/* billing period toggle */
.bperiod { display: flex; gap: 0.25rem; background: var(--card, #fff); border: 1px solid var(--line-2); border-radius: 999px; padding: 0.28rem; margin-bottom: 1.1rem; }
.bperiod__btn { flex: 1; border: 0; background: transparent; font-family: inherit; font-weight: 700; font-size: 0.88rem; color: var(--muted); padding: 0.55rem 0.7rem; border-radius: 999px; cursor: pointer; display: flex; align-items: center; justify-content: center; gap: 0.4rem; min-height: 44px; }
.bperiod__btn.is-active { background: var(--accent); color: #fff; box-shadow: var(--shadow-acc); }
.bperiod__btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.bperiod__save { font-size: 0.64rem; font-weight: 800; background: rgba(255,255,255,.25); color: #fff; padding: 0.1rem 0.4rem; border-radius: 999px; text-transform: uppercase; letter-spacing: 0.03em; }
.bperiod__btn:not(.is-active) .bperiod__save { background: var(--peach); color: var(--accent-2); }
/* Most-popular badge (the accent card) */
.pcard--accent { border-width: 2px; }
.pcard__popular { position: absolute; top: -0.65rem; left: 50%; transform: translateX(-50%); background: var(--accent); color: #fff; font-size: 0.62rem; font-weight: 800; text-transform: uppercase; letter-spacing: 0.05em; padding: 0.28rem 0.7rem; border-radius: 999px; box-shadow: 0 6px 14px -6px rgba(244,89,58,.55); white-space: nowrap; }
/* honest annual strikethrough */
.pcard__discount { display: flex; align-items: baseline; gap: 0.5rem; flex-wrap: wrap; margin: 0.2rem 0 0; }
.pcard__was { font-size: 0.98rem; color: var(--faint); text-decoration: line-through; text-decoration-color: var(--faint); font-weight: 600; }
.pcard__savebadge { font-size: 0.64rem; font-weight: 800; text-transform: uppercase; letter-spacing: 0.04em; background: var(--peach); color: var(--accent-2); padding: 0.16rem 0.5rem; border-radius: 999px; white-space: nowrap; }
.pcard--accent .pcard__savebadge { background: rgba(255,255,255,.9); }
.pricing__footnote { margin: 1rem 0 0; font-size: 0.83rem; color: var(--muted); line-height: 1.5; text-align: center; }
.pricing__footnote strong { color: var(--title); }

/* ============================================================================
   onboarding-l2-preview-flow-ui SLICE 1 — the anonymous content-first preview (/preview, hidden route).
   Adapted 1:1 from the founder look-gate mock (memphis-v1/.context/onboarding-mock/index.html, S2/S3),
   .opv- prefixed so nothing collides with the landing (which already owns `.phone`, `.beat`, etc.).
   PHONE-ONLY: the anonymous stage never shows a web/desktop preview frame.
   ============================================================================ */
.opv { max-width: 980px; margin: 0 auto; padding: 22px clamp(1rem, 4vw, 2rem) 80px; }
.opv-top { display: flex; align-items: center; margin-bottom: clamp(1.5rem, 5vw, 3rem); }
.opv-entry { max-width: 34rem; margin: clamp(1rem, 6vw, 3rem) auto 0; text-align: center; }
.opv-entry__h1 { font-size: clamp(1.7rem, 5vw, 2.4rem); color: var(--title); font-weight: 800; letter-spacing: -0.03em; line-height: 1.1; }
.opv-entry__sub { margin: 0.9rem auto 0; color: var(--muted); font-size: 1.02rem; line-height: 1.5; max-width: 30rem; }
.opv-entry__form { position: relative; display: flex; gap: 0.5rem; margin: 1.6rem auto 0; max-width: 26rem; align-items: stretch; }
.opv-entry__at { position: absolute; left: 0.85rem; top: 50%; transform: translateY(-50%); color: var(--faint); font-weight: 700; pointer-events: none; }
.opv-entry__input { flex: 1; min-width: 0; padding: 0.7rem 0.9rem 0.7rem 1.7rem; border: 1px solid var(--line); border-radius: 12px; background: #fff; font: inherit; font-size: 1rem; color: var(--ink); }
.opv-entry__input:focus { outline: 2px solid var(--accent); outline-offset: 1px; }
.opv-entry__hint { margin: 0.7rem 0 0; color: var(--accent-2); font-size: 0.9rem; font-weight: 600; }

.opv-stage { display: flex; flex-direction: column; align-items: center; gap: 26px; }
/* device frame (mock .phone) */
.opv-phone { width: 320px; max-width: 100%; border-radius: 44px; background: #12100e; padding: 12px; box-shadow: var(--e2), 0 30px 60px -20px rgba(20,10,5,.4); position: relative; }
.opv-phone__notch { position: absolute; top: 12px; left: 50%; transform: translateX(-50%); width: 90px; height: 22px; background: #12100e; border-radius: 0 0 16px 16px; z-index: 5; }
.opv-phone__screen { background: #FBF8F5; border-radius: 32px; overflow: hidden; height: 640px; position: relative; display: flex; flex-direction: column; }

.opv-beats { display: flex; flex-direction: column; gap: 10px; padding: 40px 20px 24px; }
.opv-beat { display: flex; align-items: center; gap: 10px; font-size: 14px; font-weight: 600; color: var(--faint); }
.opv-beat.is-done { color: var(--ink); }
.opv-beat.is-active { color: var(--accent-2); }
.opv-beat__dot { width: 8px; height: 8px; border-radius: 50%; background: rgba(38,25,15,.2); flex: none; }
.opv-beat.is-done .opv-beat__dot { background: #1B7A4B; }
.opv-beat.is-active .opv-beat__dot { background: var(--accent); box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent) 22%, transparent); }
.opv-beat__check { margin-left: auto; color: #1B7A4B; font-weight: 800; font-size: 12px; }
.opv-beats__foot { margin-top: auto; padding: 18px; text-align: center; color: var(--faint); font-size: 12px; }

.opv-banner { margin: 40px 16px 4px; padding: 10px 12px; background: var(--accent-tint); border-radius: 12px; font-size: 11.5px; line-height: 1.4; color: var(--accent-2); font-weight: 600; }
.opv-scroll { flex: 1; overflow-y: auto; padding: 0 16px 16px; }
.opv-uhead { padding: 12px 0 4px; }
.opv-uhead__found { font-size: 15px; font-weight: 800; color: var(--ink); }
.opv-uhead__handle { font-size: 12.5px; color: var(--faint); margin-top: 2px; }
.opv-rgrid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-top: 12px; }
.opv-rcard { border-radius: 12px; overflow: hidden; background: #fff; box-shadow: var(--e1); }
.opv-rcard img { width: 100%; height: 84px; object-fit: cover; display: block; }
.opv-rcard__title { font-size: 11.5px; font-weight: 700; padding: 7px 8px; line-height: 1.25; color: var(--ink); }
.opv-rexp { margin-top: 14px; border-radius: var(--r-card); background: #fff; box-shadow: var(--e2); overflow: hidden; }
.opv-rexp img { width: 100%; height: 140px; object-fit: cover; display: block; }
.opv-rexp__body { padding: 14px 16px 16px; }
.opv-rexp__title { font-size: 16px; font-weight: 800; letter-spacing: -0.01em; color: var(--title); }
.opv-rexp__meta { font-size: 12px; color: var(--faint); margin-top: 3px; font-weight: 600; }
.opv-rexp h4 { font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: .06em; color: var(--accent-2); margin: 14px 0 6px; }
.opv-ings { margin: 0; padding: 0; list-style: none; }
.opv-ings li { display: flex; justify-content: space-between; font-size: 13.5px; padding: 5px 0; border-bottom: 1px solid rgba(38,25,15,.06); color: var(--ink); }
.opv-ings li span:last-child { color: var(--muted); font-weight: 600; }
.opv-caps { padding: 4px 0 8px; }
.opv-caps__label { font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: .06em; color: var(--faint); margin: 12px 0 8px; }
.opv-caps__row { display: flex; flex-direction: column; gap: 8px; }
.opv-cap { display: flex; align-items: center; gap: 10px; background: #fff; border-radius: 12px; padding: 10px 12px; box-shadow: var(--e1); font-size: 13px; font-weight: 700; color: var(--ink); }
.opv-cap__ic { width: 26px; height: 26px; border-radius: 8px; background: var(--accent-tint); color: var(--accent-2); display: flex; align-items: center; justify-content: center; flex: none; }
.opv-cap__ic svg { width: 14px; height: 14px; }
.opv-cap.is-coming { opacity: .6; }
.opv-cap__tag { margin-left: auto; font-size: 10.5px; font-weight: 800; text-transform: uppercase; letter-spacing: .04em; color: var(--faint); background: rgba(38,25,15,.06); padding: 3px 8px; border-radius: 999px; }

/* S3 ask card */
.opv-ask { width: 100%; max-width: 30rem; background: var(--glass-row); backdrop-filter: var(--blur); -webkit-backdrop-filter: var(--blur); border: 1px solid var(--glass-line); border-radius: var(--r-card); box-shadow: var(--e2); padding: 22px 24px 24px; text-align: center; }
.opv-ask__title { font-size: 20px; font-weight: 800; color: var(--title); letter-spacing: -0.02em; }
.opv-ask__sub { margin: 0.7rem 0 0; font-size: 14px; color: var(--muted); line-height: 1.5; }
.opv-ask .btn { margin-top: 18px; width: 100%; }
.opv-ask__honesty { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px 18px; margin-top: 14px; font-size: 12.5px; color: var(--muted); }
.opv-ask__honesty b { color: var(--title); }
.opv-ask__free { margin-top: 16px; text-align: left; background: var(--peach); border-radius: 12px; padding: 12px 14px; font-size: 12.5px; color: var(--ink); }
.opv-ask__free b { color: var(--title); }
.opv-ask__free ul { margin: 6px 0 0; padding-left: 18px; }
.opv-ask__free li { margin-bottom: 4px; }
@media (max-width: 420px) { .opv-phone { width: 100%; } .opv-phone__screen { height: 74vh; min-height: 480px; } }
