/* ============================================================
   Framvis — design system
   Light "Apple-grade" aesthetic. Tokens, then base, then components.
   Conventions follow the project rules — compact single-line small selectors,
   multi-line for flex/grid, media queries at the very bottom.
   ============================================================ */

:root{
    /* color */
    --bg:#f5f5f7;
    --bg-grad:radial-gradient(1200px 600px at 50% -10%, #eef0fe 0%, rgba(245,245,247,0) 60%);
    --surface:#ffffff;
    --surface-2:#fbfbfd;
    --fg:#1d1d1f;
    --fg-muted:#54545a;
    --fg-subtle:#86868b;
    --primary:#5b54e8;
    --primary-600:#4840c4;
    --primary-glow:rgba(91,84,232,0.12);
    --success:#157f43;
    --success-bg:#e7f6ee;
    --danger:#d62f34;
    --danger-bg:#fdecec;
    --warn:#9a6a00;
    --warn-bg:#fef6e6;
    --border:rgba(0,0,0,0.10);
    --border-strong:rgba(0,0,0,0.16);
    --ring:rgba(91,84,232,0.32);
    --glass:rgba(255,255,255,0.72);

    /* shape */
    --radius:14px;
    --radius-sm:10px;
    --radius-lg:22px;
    --pill:999px;

    /* elevation */
    --shadow-sm:0 1px 2px rgba(0,0,0,0.04),0 2px 6px rgba(0,0,0,0.05);
    --shadow-md:0 6px 16px rgba(0,0,0,0.06),0 14px 36px rgba(0,0,0,0.07);
    --shadow-lg:0 24px 60px -16px rgba(0,0,0,0.28);

    /* motion */
    --ease:cubic-bezier(0.4,0,0.2,1);
    --spring:cubic-bezier(0.34,1.56,0.64,1);
    --dur:0.22s;

    --maxw:1180px;
    --font:'Plus Jakarta Sans',-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;
    --mono:'SF Mono',ui-monospace,'JetBrains Mono',Menlo,Consolas,monospace;
}

/* ---------- base ---------- */
*{box-sizing:border-box;}
html{-webkit-text-size-adjust:100%;}
body {
    margin:0;
    min-height:100vh;
    background:var(--bg-grad),var(--bg);
    background-attachment:fixed;
    color:var(--fg);
    font-family:var(--font);
    font-size:16px;
    line-height:1.5;
    -webkit-font-smoothing:antialiased;
    text-rendering:optimizeLegibility;
}
a{color:inherit;text-decoration:none;}
h1,h2,h3,h4{margin:0;letter-spacing:-0.02em;line-height:1.15;}
p{margin:0;}
img,svg{display:block;max-width:100%;}
button{font-family:inherit;}
:focus-visible{outline:none;box-shadow:0 0 0 3px var(--ring);border-radius:8px;}
.muted{color:var(--fg-subtle);}
.hidden{display:none!important;}

/* ---------- buttons ---------- */
.btn {
    --bg-btn:transparent;
    --fg-btn:var(--fg);
    display:inline-flex;
    align-items:center;
    justify-content:center;
    gap:0.5rem;
    font-weight:600;
    font-size:0.9rem;
    line-height:1;
    padding:0.65rem 1.1rem;
    border:1px solid transparent;
    border-radius:var(--radius-sm);
    background:var(--bg-btn);
    color:var(--fg-btn);
    cursor:pointer;
    white-space:nowrap;
    transition:transform 0.08s var(--ease),background-color var(--dur),box-shadow var(--dur),border-color var(--dur),opacity var(--dur);
}
.btn:active{transform:scale(0.97);}
.btn:disabled{opacity:0.55;cursor:not-allowed;}
.btn-primary{--bg-btn:var(--primary);--fg-btn:#fff;box-shadow:0 1px 2px rgba(0,0,0,0.08),0 6px 16px var(--primary-glow);}
.btn-primary:hover:not(:disabled){--bg-btn:var(--primary-600);}
.btn-secondary{--bg-btn:var(--surface);--fg-btn:var(--fg);border-color:var(--border);box-shadow:var(--shadow-sm);}
.btn-secondary:hover:not(:disabled){border-color:var(--border-strong);background:var(--surface-2);}
.btn-ghost{--fg-btn:var(--fg-muted);}
.btn-ghost:hover:not(:disabled){background:rgba(0,0,0,0.04);}
.btn-danger{--bg-btn:var(--danger);--fg-btn:#fff;}
.btn-danger:hover:not(:disabled){filter:brightness(0.94);}
.btn-sm{padding:0.42rem 0.7rem;font-size:0.8rem;border-radius:8px;}
.btn-lg{padding:0.85rem 1.6rem;font-size:1rem;}
.btn-block{width:100%;}
.btn.is-loading{color:transparent!important;pointer-events:none;position:relative;}
.btn.is-loading::after {
    content:"";
    position:absolute;
    width:16px;height:16px;
    border:2px solid currentColor;
    border-top-color:transparent;
    border-radius:50%;
    color:#fff;
    animation:spin 0.6s linear infinite;
}
.btn-secondary.is-loading::after,.btn-ghost.is-loading::after{color:var(--fg);}

.spinner {
    width:22px;height:22px;
    border:2.5px solid var(--border);
    border-top-color:var(--primary);
    border-radius:50%;
    animation:spin 0.7s linear infinite;
}
@keyframes spin{to{transform:rotate(360deg);}}

/* ---------- app shell / header ---------- */
.app-header {
    position:sticky;
    top:0;
    z-index:100;
    display:flex;
    align-items:center;
    justify-content:space-between;
    gap:1rem;
    padding:0.85rem clamp(1rem,4vw,3rem);
    background:var(--glass);
    border-bottom:1px solid var(--border);
    backdrop-filter:saturate(180%) blur(18px);
    -webkit-backdrop-filter:saturate(180%) blur(18px);
}
.brand{display:flex;align-items:center;gap:0.55rem;font-weight:800;font-size:1.15rem;letter-spacing:-0.03em;}
/* The mark is a self-coloured SVG asset (assets/img/logo-mark.svg) rendered
   via <img> - no background or icon-font styling here, the artwork brings its
   own tile. border-radius trims the bitmap corners to the tile's own curve. */
.brand-mark{display:block;width:28px;height:28px;border-radius:6px;box-shadow:0 4px 10px var(--primary-glow);}
/* Small inline mark for "Made with Framvis" badges (embed + hub footers). */
.badge-mark{width:14px;height:14px;border-radius:3px;vertical-align:-2px;}
.nav{display:flex;align-items:center;gap:0.6rem;}

.container{width:100%;max-width:var(--maxw);margin:0 auto;padding:0 clamp(1rem,4vw,3rem);}

/* ---------- landing ---------- */
.hero {
    display:flex;
    flex-direction:column;
    align-items:center;
    text-align:center;
    gap:1.4rem;
    padding:clamp(3rem,9vw,7rem) 1rem 2rem;
    max-width:820px;
    margin:0 auto;
}
.eyebrow {
    display:inline-flex;
    align-items:center;
    gap:0.5rem;
    font-size:0.8rem;
    font-weight:600;
    color:var(--primary);
    background:var(--primary-glow);
    border:1px solid rgba(91,84,232,0.20);
    padding:0.35rem 0.8rem;
    border-radius:var(--pill);
}
.hero-title {
    font-size:clamp(2.4rem,6vw,4rem);
    font-weight:800;
    letter-spacing:-0.045em;
    background:linear-gradient(180deg,#1d1d1f 30%,#5b5b61);
    -webkit-background-clip:text;
    background-clip:text;
    -webkit-text-fill-color:transparent;
}
.hero-sub{font-size:clamp(1.05rem,2.2vw,1.3rem);color:var(--fg-subtle);max-width:620px;line-height:1.55;}
.hero-actions{display:flex;gap:0.8rem;flex-wrap:wrap;justify-content:center;}
.features {
    display:grid;
    grid-template-columns:repeat(auto-fit,minmax(240px,1fr));
    gap:1.2rem;
    max-width:var(--maxw);
    margin:0 auto;
    padding:1rem clamp(1rem,4vw,3rem) 5rem;
}
.feature-card {
    background:var(--surface);
    border:1px solid var(--border);
    border-radius:var(--radius);
    padding:1.6rem;
    box-shadow:var(--shadow-sm);
    transition:transform var(--dur) var(--ease),box-shadow var(--dur);
}
.feature-card:hover{transform:translateY(-3px);box-shadow:var(--shadow-md);}
.features .feature-card:last-child{grid-column:span 2;}
.feature-ico {
    display:grid;
    place-items:center;
    width:44px;height:44px;
    border-radius:12px;
    background:var(--primary-glow);
    color:var(--primary);
    font-size:1.1rem;
    margin-bottom:1rem;
}
.feature-card h3{font-size:1.05rem;margin-bottom:0.4rem;}
.feature-card p{font-size:0.9rem;color:var(--fg-subtle);}

/* ---------- cards / forms ---------- */
.card{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:2rem;box-shadow:var(--shadow-sm);}
.auth-wrap{display:grid;place-items:center;padding:clamp(2rem,8vh,5rem) 1rem;}
.auth-card{width:100%;max-width:420px;}
.auth-card h2{font-size:1.5rem;text-align:center;margin-bottom:0.4rem;}
.auth-card .sub{text-align:center;color:var(--fg-subtle);font-size:0.9rem;margin-bottom:1.6rem;}
.field{display:flex;flex-direction:column;gap:0.4rem;margin-bottom:1.1rem;}
.label{font-size:0.82rem;font-weight:600;color:var(--fg-muted);}
.input {
    width:100%;
    background:var(--surface);
    border:1px solid var(--border-strong);
    border-radius:var(--radius-sm);
    padding:0.7rem 0.85rem;
    font-size:0.95rem;
    color:var(--fg);
    font-family:inherit;
    transition:border-color var(--dur),box-shadow var(--dur);
}
.input:focus{outline:none;border-color:var(--primary);box-shadow:0 0 0 3px var(--ring);}
.input::placeholder{color:#b0b0b6;}
textarea.input{resize:vertical;min-height:84px;}
.hint{font-size:0.75rem;color:var(--fg-subtle);}
.swap{text-align:center;font-size:0.88rem;margin-top:1.4rem;color:var(--fg-subtle);}
.swap a{color:var(--primary);font-weight:600;}

/* ---------- dashboard ---------- */
.shell {
    display:grid;
    grid-template-columns:248px 1fr;
    min-height:calc(100vh - 61px);
}
.sidebar {
    display:flex;
    flex-direction:column;
    gap:0.3rem;
    padding:1.6rem 1rem;
    border-right:1px solid var(--border);
    background:rgba(255,255,255,0.5);
}
.side-link {
    display:flex;
    align-items:center;
    gap:0.7rem;
    padding:0.65rem 0.85rem;
    border-radius:var(--radius-sm);
    font-weight:600;
    font-size:0.92rem;
    color:var(--fg-muted);
    transition:background-color var(--dur),color var(--dur);
}
.side-link:hover{background:rgba(0,0,0,0.04);color:var(--fg);}
.side-link.active{background:var(--primary-glow);color:var(--primary);}
.side-link i{width:18px;text-align:center;}
/* The ONE place the signed-in address appears. It used to be duplicated in the
   header as `.nav-email`, now removed — two copies of the same string on one
   screen, and the header copy was already hidden below 560px, so desktop and
   phone disagreed about where identity lived. The rail wins because the
   account nav (Membership, Settings) is already here. Slightly larger and
   rule-separated now that nothing else carries it. */
.side-foot {
    display:flex;
    align-items:center;
    gap:0.5rem;
    margin-top:auto;
    padding:0.75rem 0.85rem;
    border-top:1px solid var(--border);
    font-size:0.8rem;
    color:var(--fg-subtle);
}
.side-foot i{opacity:0.75;}
.side-foot span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
/* Mobile nav drawer. Both are inert above the breakpoint: the toggle is not
   displayed and the scrim has no size, so the desktop shell is untouched. */
.nav-toggle {
    display:none;
    align-items:center;
    justify-content:center;
    width:44px;
    height:44px;
    margin-left:-0.55rem;
    border:0;
    border-radius:var(--radius-sm);
    background:transparent;
    color:var(--fg);
    font-size:1.05rem;
    cursor:pointer;
}
.nav-toggle:hover{background:rgba(0,0,0,0.05);}
.nav-scrim{display:none;}
.app-header-lead{display:flex;align-items:center;gap:0.35rem;min-width:0;}
.main{padding:clamp(1.5rem,4vw,3rem);overflow-x:hidden;}
.page-head{display:flex;align-items:flex-start;justify-content:space-between;gap:1rem;margin-bottom:2rem;flex-wrap:wrap;}
.page-head h2{font-size:1.6rem;}
.page-head .lede{color:var(--fg-subtle);font-size:0.92rem;margin-top:0.3rem;}

.grid-cards {
    display:grid;
    grid-template-columns:repeat(auto-fill,minmax(280px,1fr));
    gap:1.2rem;
}
.proj-card {
    display:flex;
    flex-direction:column;
    gap:0.5rem;
    background:var(--surface);
    border:1px solid var(--border);
    border-radius:var(--radius);
    padding:1.4rem;
    cursor:pointer;
    box-shadow:var(--shadow-sm);
    transition:transform var(--dur) var(--ease),box-shadow var(--dur),border-color var(--dur);
}
.proj-card:hover{transform:translateY(-3px);border-color:rgba(91,84,232,0.45);box-shadow:var(--shadow-md);}
.proj-card h3{font-size:1.1rem;}
.proj-domains{font-size:0.84rem;color:var(--fg-subtle);min-height:1.2em;}
.proj-foot{display:flex;align-items:center;justify-content:space-between;margin-top:0.6rem;padding-top:0.9rem;border-top:1px solid var(--border);}
.proj-foot .meta{font-size:0.8rem;color:var(--fg-subtle);}
.card-actions{display:flex;gap:0.4rem;}

/* recordings */
.rec-list{display:flex;flex-direction:column;gap:0.7rem;}
.rec-row {
    display:flex;
    align-items:center;
    justify-content:space-between;
    gap:1rem;
    background:var(--surface);
    border:1px solid var(--border);
    border-radius:var(--radius-sm);
    padding:0.9rem 1.1rem;
    box-shadow:var(--shadow-sm);
    transition:border-color var(--dur);
}
.rec-row:hover{border-color:var(--border-strong);}
.rec-main{display:flex;flex-direction:column;gap:0.2rem;min-width:0;}
.rec-title{font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.rec-meta{font-size:0.8rem;color:var(--fg-subtle);display:flex;gap:0.8rem;flex-wrap:wrap;}
.rec-actions{display:flex;gap:0.45rem;flex-shrink:0;}
.chip{display:inline-flex;align-items:center;gap:0.3rem;font-size:0.72rem;font-weight:600;padding:0.15rem 0.5rem;border-radius:var(--pill);background:var(--success-bg);color:var(--success);}

.code-box {
    position:relative;
    background:#0f1729;
    border:1px solid rgba(255,255,255,0.08);
    border-radius:var(--radius-sm);
    padding:1.1rem 1.2rem;
    font-family:var(--mono);
    font-size:0.82rem;
    color:#7ee2b8;
    white-space:pre-wrap;
    word-break:break-all;
    line-height:1.5;
}

/* extension-first capture onboarding */
.capture-layout{display:grid;grid-template-columns:minmax(0,1fr) minmax(300px,0.9fr);gap:1.2rem;align-items:start;}
.capture-title{display:flex;align-items:flex-start;gap:0.8rem;margin-bottom:1rem;}
.capture-title-icon{display:grid;place-items:center;width:42px;height:42px;flex:0 0 42px;border-radius:12px;background:var(--primary-glow);color:var(--primary);font-size:1.05rem;}
.capture-title h3{margin:0;}
.capture-title p{margin:0.2rem 0 0;color:var(--fg-subtle);font-size:0.88rem;}
.capture-checklist{display:flex;flex-direction:column;gap:0.15rem;margin:0;padding:0;list-style:none;}
.capture-checklist li{display:flex;align-items:flex-start;gap:0.65rem;padding:0.55rem;border-radius:var(--radius-sm);color:var(--fg-subtle);}
.capture-checklist li.done{color:var(--fg);}
.capture-check{display:grid;place-items:center;width:22px;height:22px;flex:0 0 22px;color:var(--border-strong);}
.capture-checklist .done .capture-check{border-radius:50%;background:var(--success-bg);color:var(--success);}
.capture-checklist small{display:block;margin-top:0.1rem;color:var(--fg-subtle);font-size:0.76rem;}
.capture-connect{padding:1.2rem;}
.capture-status{display:flex;align-items:center;gap:0.65rem;}
.capture-status-dot{width:10px;height:10px;flex:0 0 10px;border-radius:50%;background:var(--border-strong);}
.capture-status-dot.on{background:var(--success);box-shadow:0 0 0 4px var(--success-bg);}
.capture-status small{display:block;color:var(--fg-subtle);font-size:0.76rem;}
.capture-actions{margin-top:1rem;flex-wrap:wrap;}
.pair-code{display:grid;grid-template-columns:1fr auto;gap:0.3rem 0.7rem;align-items:center;margin-top:1rem;padding:0.8rem;border:1px dashed var(--primary);border-radius:var(--radius-sm);background:var(--primary-glow);}
.pair-code span,.pair-code small{font-size:0.72rem;color:var(--fg-subtle);}
.pair-code strong{font-size:1.2rem;letter-spacing:0.08em;}
.pair-code .btn{grid-column:2;grid-row:1 / span 2;}
.capture-devices{margin-top:1.4rem;padding-top:1.2rem;border-top:1px solid var(--border);}
.capture-subhead h4,.capture-subhead p{margin:0;}
.capture-subhead p{color:var(--fg-subtle);font-size:0.8rem;}
.device-list{margin-top:0.7rem;border:1px solid var(--border);border-radius:var(--radius-sm);overflow:hidden;}
.device-row{display:flex;align-items:center;justify-content:space-between;gap:1rem;padding:0.75rem;border-bottom:1px solid var(--border);}
.device-row:last-child{border-bottom:0;}
.device-row small{display:block;margin-top:0.15rem;color:var(--fg-subtle);font-size:0.74rem;}
.capture-revoked{background:var(--danger-bg);color:var(--danger);}
.legacy-capture{margin-top:1.5rem;border:1px solid var(--border);border-radius:var(--radius-sm);background:var(--surface);}
.legacy-capture summary{padding:0.9rem 1rem;cursor:pointer;font-weight:600;}
.legacy-body{padding:0 1rem 1rem;border-top:1px solid var(--border);}
.legacy-body h4{margin:1.1rem 0 0.35rem;}
.legacy-heading{padding-top:1rem;border-top:1px solid var(--border);}
.section{margin-bottom:2.5rem;}
.section h3{font-size:1.05rem;margin-bottom:0.5rem;}
.section .lede{color:var(--fg-subtle);font-size:0.88rem;margin-bottom:1rem;}

/* badges + pricing */
.badge{font-size:0.72rem;padding:0.2rem 0.55rem;border-radius:var(--pill);font-weight:700;display:inline-block;}
.badge-free{background:rgba(0,0,0,0.06);color:var(--fg-muted);}
.badge-pro{background:var(--primary-glow);color:var(--primary);border:1px solid rgba(91,84,232,0.22);}
.badge-warn{background:var(--warn-bg);color:var(--warn);border:1px solid rgba(154,106,0,0.22);}
.profile-grid{display:grid;grid-template-columns:1fr 1fr;gap:1.5rem;align-items:start;}
.kv{display:flex;justify-content:space-between;gap:1rem;padding:0.6rem 0;border-bottom:1px solid var(--border);font-size:0.92rem;}
.kv:last-child{border-bottom:0;}
.mono-sm{font-family:var(--mono);font-size:0.78rem;word-break:break-all;}
.plan-card {
    position:relative;
    display:flex;
    flex-direction:column;
    background:var(--surface);
    border:1px solid var(--border);
    border-radius:var(--radius);
    padding:2rem;
    overflow:hidden;
    box-shadow:var(--shadow-sm);
}
.plan-card.active{border-color:var(--primary);box-shadow:0 0 0 1px var(--primary),var(--shadow-md);}
.plan-tag{align-self:flex-start;font-size:0.7rem;font-weight:800;letter-spacing:0.06em;color:var(--primary);background:var(--primary-glow);padding:0.25rem 0.6rem;border-radius:var(--pill);margin-bottom:0.8rem;}
.price{font-size:1rem;color:var(--fg-subtle);font-weight:500;margin:0.4rem 0 1rem;}
.price b{font-size:2.4rem;font-weight:800;color:var(--fg);letter-spacing:-0.03em;}
.plan-feats{list-style:none;padding:0;margin:0 0 1.6rem;display:flex;flex-direction:column;gap:0.6rem;}
.plan-feats li{display:flex;align-items:center;gap:0.6rem;font-size:0.9rem;color:var(--fg-muted);}
.plan-feats i{color:var(--success);}

/* landing pricing section */
.pricing-section{max-width:var(--maxw);margin:0 auto;padding:1rem clamp(1rem,4vw,3rem) 6rem;}
.pricing-head{text-align:center;margin-bottom:2rem;}
.pricing-head h2{font-size:clamp(1.8rem,4vw,2.4rem);margin-bottom:0.4rem;}
.pricing-grid {
    display:grid;
    grid-template-columns:repeat(auto-fit,minmax(240px,1fr));
    gap:1.2rem;
    align-items:start;
}

/* ---------- modal ---------- */
.modal-overlay {
    position:fixed;
    inset:0;
    z-index:1000;
    display:grid;
    place-items:center;
    padding:1rem;
    background:rgba(20,20,25,0.45);
    backdrop-filter:blur(6px);
    -webkit-backdrop-filter:blur(6px);
    animation:overlay-in var(--dur) var(--ease);
}
.modal {
    width:100%;
    max-width:480px;
    /* Cap to the viewport (overlay adds 1rem top+bottom) and scroll inside, so a
       tall form never pushes its bottom off-screen or scrolls the page behind it. */
    max-height:calc(100vh - 2rem);
    overflow-y:auto;
    background:var(--surface);
    border:1px solid var(--border);
    border-radius:var(--radius-lg);
    box-shadow:var(--shadow-lg);
    padding:1.8rem;
    position:relative;
    animation:modal-in 0.3s var(--spring);
}
.modal-lg{max-width:960px;}
/* Replay/editor opens full-screen: at modal-lg the stage, steps panel and language
   panel were stacked into 960px and the editor was fiddly to work in. */
.modal-full{max-width:none;height:calc(100vh - 2rem);padding:1.2rem;}
/* While any modal is open the page itself must not scroll (openModal toggles this).
   Lock the <html> scroller — on this layout the viewport scrolls on <html>, not
   <body>, so hiding body overflow alone doesn't hold. */
html.modal-open,html.modal-open body{overflow:hidden;}
.modal-md{max-width:600px;}
.modal-close {
    position:absolute;
    top:1rem;right:1rem;
    width:34px;height:34px;
    display:grid;place-items:center;
    border:none;border-radius:50%;
    background:rgba(0,0,0,0.04);
    color:var(--fg-muted);
    font-size:1.1rem;
    cursor:pointer;
    transition:background-color var(--dur);
}
.modal-close:hover{background:rgba(0,0,0,0.09);}
.modal-head{margin-bottom:1.2rem;padding-right:2rem;}
.modal-head h3{font-size:1.3rem;}
.modal-head p{color:var(--fg-subtle);font-size:0.9rem;margin-top:0.3rem;}
@keyframes overlay-in{from{opacity:0;}to{opacity:1;}}
@keyframes modal-in{from{opacity:0;transform:translateY(12px) scale(0.97);}to{opacity:1;transform:none;}}

/* ---------- toast ---------- */
.toast-stack {
    position:fixed;
    bottom:1.5rem;right:1.5rem;
    z-index:2000;
    display:flex;
    flex-direction:column;
    gap:0.6rem;
    max-width:min(380px,92vw);
}
.toast {
    display:flex;
    align-items:center;
    gap:0.7rem;
    padding:0.85rem 1rem;
    border-radius:var(--radius-sm);
    background:var(--surface);
    color:var(--fg);
    border:1px solid var(--border);
    box-shadow:var(--shadow-md);
    font-size:0.9rem;
    font-weight:500;
    cursor:pointer;
    opacity:0;
    transform:translateX(20px);
    transition:opacity var(--dur) var(--ease),transform var(--dur) var(--ease);
}
.toast.show{opacity:1;transform:none;}
.toast-icon{display:grid;place-items:center;width:22px;height:22px;border-radius:50%;flex-shrink:0;font-size:0.75rem;color:#fff;}
.toast-success .toast-icon{background:var(--success);}
.toast-error .toast-icon{background:var(--danger);}
.toast-info .toast-icon{background:var(--primary);}
.toast-success{border-left:3px solid var(--success);}
.toast-error{border-left:3px solid var(--danger);}
.toast-info{border-left:3px solid var(--primary);}
.toast-msg{flex:1;}

/* ---------- skeleton + empty ---------- */
.skel{background:linear-gradient(90deg,#ececf0 25%,#f5f5f8 37%,#ececf0 63%);background-size:400% 100%;border-radius:8px;animation:shimmer 1.3s ease infinite;}
.skel-card{height:150px;border-radius:var(--radius);}
.skel-row{height:64px;border-radius:var(--radius-sm);}
@keyframes shimmer{0%{background-position:100% 0;}100%{background-position:-100% 0;}}
.empty {
    display:flex;
    flex-direction:column;
    align-items:center;
    text-align:center;
    gap:0.7rem;
    padding:4rem 1rem;
    border:1px dashed var(--border-strong);
    border-radius:var(--radius);
    color:var(--fg-subtle);
}
.empty-ico{display:grid;place-items:center;width:60px;height:60px;border-radius:50%;background:var(--primary-glow);color:var(--primary);font-size:1.5rem;}
.empty h3{font-size:1.1rem;color:var(--fg);}
.empty p{font-size:0.9rem;max-width:420px;}

/* analytics */
.stat-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(120px,1fr));gap:0.8rem;}
.stat-card{padding:1rem;text-align:center;background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius-sm);}
.stat-num{font-size:1.7rem;font-weight:800;letter-spacing:-0.02em;color:var(--fg);}
.stat-label{font-size:0.76rem;color:var(--fg-subtle);margin-top:0.2rem;}
.funnel-row{margin-bottom:0.7rem;}
.funnel-meta{display:flex;justify-content:space-between;font-size:0.82rem;margin-bottom:0.25rem;}
.funnel-bar{height:10px;border-radius:var(--pill);background:rgba(0,0,0,0.06);overflow:hidden;}
.funnel-fill{height:100%;border-radius:var(--pill);background:linear-gradient(90deg,var(--primary),#8b7bff);transition:width 0.4s var(--ease);}
/* traffic sources (attribution) — source name flexes, three numeric columns fixed */
.src-table{display:flex;flex-direction:column;font-size:0.85rem;}
.src-row{display:grid;grid-template-columns:1fr 62px 76px 56px;gap:0.5rem;padding:0.42rem 0.2rem;border-bottom:1px solid var(--border);}
.src-row span:not(:first-child){text-align:right;font-variant-numeric:tabular-nums;}
.src-row:last-child{border-bottom:0;}
.src-head{font-weight:600;color:var(--fg-subtle);font-size:0.78rem;}
.src-row span:first-child{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.perf-table{overflow-x:auto;font-size:0.82rem;}
.perf-row{display:grid;grid-template-columns:minmax(130px,1fr) 58px 82px 80px 80px;gap:0.5rem;min-width:500px;padding:0.42rem 0.2rem;border-bottom:1px solid var(--border);}
.perf-row span:not(:first-child){text-align:right;font-variant-numeric:tabular-nums;}
.perf-row:last-child{border-bottom:0;}
.perf-head{color:var(--fg-subtle);font-weight:600;}
.lead-list{display:flex;flex-direction:column;max-height:220px;overflow-y:auto;margin-top:0.6rem;}
.lead-row{display:flex;justify-content:space-between;gap:1rem;font-size:0.85rem;padding:0.45rem 0.2rem;border-bottom:1px solid var(--border);}
.lead-table{overflow-x:auto;max-height:360px;overflow-y:auto;margin-top:0.6rem;font-size:0.82rem;}
.lead-table-row{display:grid;grid-template-columns:repeat(var(--lead-columns),minmax(110px,1fr));gap:.55rem;min-width:520px;padding:.45rem .2rem;border-bottom:1px solid var(--border);}
.lead-table-row>span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.lead-table-head{position:sticky;top:0;background:var(--surface);color:var(--fg-subtle);font-weight:600;font-size:.76rem;z-index:1;}
.lead-page-controls{justify-content:flex-end;align-items:center;}
.lead-builder{margin-top:1rem;padding:.8rem;border:1px solid var(--border);border-radius:var(--radius);background:var(--surface-2);text-align:left;}
.lead-builder-title{display:flex;justify-content:space-between;align-items:baseline;gap:.6rem;margin-bottom:.65rem;}
.lead-builder-row{padding:.7rem 0;border-bottom:1px solid var(--border);}
.lead-builder-row:last-child{border-bottom:0;}
.lead-builder-head{display:flex;align-items:center;justify-content:space-between;gap:.5rem;margin-bottom:.55rem;}
.lead-builder-controls{display:flex;gap:.15rem;}
.lead-builder-grid{display:grid;grid-template-columns:1fr 1.2fr .9fr;gap:.55rem;}
.lead-required{display:flex;align-items:center;gap:.4rem;margin-top:.55rem;}
.lead-options-wrap{margin-top:.55rem;}
.lead-builder-empty{margin:.2rem 0;}
.lead-check{display:flex;align-items:center;gap:.45rem;justify-content:flex-start;font-size:.85rem;}

/* lead gate (email capture overlay) */
.lead-gate {
    position:absolute;
    inset:0;
    z-index:1400;
    display:grid;
    place-items:center;
    padding:1rem;
    background:rgba(20,20,25,0.55);
    backdrop-filter:blur(8px);
    -webkit-backdrop-filter:blur(8px);
}
/* Phase 22 (P18-002). The gate is no longer an overlay sitting on top of an
   already-delivered demo — the server withholds the payload entirely, so there
   is no player underneath to dim. It renders in normal flow instead. */
.lead-gate-standalone{position:static;min-height:min(60vh,420px);background:none;backdrop-filter:none;-webkit-backdrop-filter:none;}
.lead-card {
    width:min(380px,92%);
    padding:1.8rem 1.6rem;
    text-align:center;
    background:var(--surface);
    border-radius:var(--radius-lg);
    box-shadow:var(--shadow-lg);
    animation:modal-in 0.3s var(--spring);
}
.lead-ico{display:grid;place-items:center;width:48px;height:48px;margin:0 auto 0.9rem;border-radius:50%;background:var(--primary-glow);color:var(--primary);font-size:1.2rem;}
.lead-card h3{font-size:1.15rem;line-height:1.3;margin-bottom:1.1rem;}
.lead-form{display:flex;flex-direction:column;gap:0.6rem;}
.lead-fine{font-size:0.72rem;color:var(--fg-subtle);margin-top:0.9rem;}
.lead-error{font-size:0.8rem;color:var(--danger);margin:0;}

/* ---------- player ---------- */
.player-window{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);overflow:hidden;box-shadow:var(--shadow-lg);}
.titlebar {
    display:flex;
    align-items:center;
    position:relative;
    padding:0.7rem 1rem;
    background:var(--surface-2);
    border-bottom:1px solid var(--border);
}
.dots{display:flex;gap:7px;}
.dot{width:12px;height:12px;border-radius:50%;display:inline-block;}
.dot-r{background:#ff5f56;}
.dot-y{background:#ffbd2e;}
.dot-g{background:#27c93f;}
.titlebar-title{position:absolute;left:50%;transform:translateX(-50%);font-size:0.84rem;font-weight:600;color:var(--fg-subtle);}
.player-stage{position:relative;background:#1c1c1e;min-height:360px;}
/* `display:flow-root` is load-bearing: rrweb-player's root is `float:left`, so
   without it .player-view collapses to height 0, .player-stage falls back to its
   min-height, and every absolutely-positioned layer below is sized against a box
   ~175px shorter than the actual replay — which is what made the step editor
   land clicks in the wrong place and go dead near the bottom of the frame. */
.player-view{position:relative;z-index:1;display:flow-root;}
/* Cover exactly the replay frame, which player.js measures into --rr-frame-h at
   mount (the fallback is stage-minus-controller for the pre-measure paint). The
   old hardcoded `100% - 50px` was measured against a collapsed stage and left the
   bottom third of the frame unclickable. */
.tips-layer{position:absolute;top:0;left:0;width:var(--rr-frame-w,100%);height:var(--rr-frame-h,calc(100% - 78px));pointer-events:none;z-index:998;}
.editor-overlay{position:absolute;top:0;left:0;width:var(--rr-frame-w,100%);height:var(--rr-frame-h,calc(100% - 78px));z-index:999;cursor:crosshair;display:none;background:rgba(91,84,232,0.05);}
/* rrweb-player ships its own `.switch` (the skip-inactive toggle). Our .switch is
   a fixed 40x23 pill, and the width leaked in and crushed their label onto two
   lines, shoving the fullscreen button out of the bar. Their Svelte-scoped rules
   handle the rest — we only need to stop imposing our box. */
.rr-player .switch{width:auto;height:auto;flex-shrink:1;}
.editor-overlay.active{display:block;}
.editor-hint{font-size:0.78rem;color:var(--fg-subtle);}

/* tooltip bubble */
.tip {
    position:absolute;
    transform:translate(-50%,-100%);
    margin-top:-12px;
    max-width:240px;
    min-width:120px;
    padding:0.65rem 0.85rem;
    background:#fff;
    color:#1d1d1f;
    border-radius:10px;
    font-size:0.85rem;
    line-height:1.4;
    box-shadow:0 10px 24px rgba(0,0,0,0.22);
    pointer-events:auto;
    word-break:break-word;
    animation:tip-in 0.2s var(--spring);
}
.tip-arrow{position:absolute;bottom:-6px;left:50%;transform:translateX(-50%);width:0;height:0;border-left:6px solid transparent;border-right:6px solid transparent;border-top:6px solid #fff;}
.tip a{color:var(--primary);}
@keyframes tip-in{from{opacity:0;transform:translate(-50%,-100%) scale(0.9);}to{opacity:1;transform:translate(-50%,-100%) scale(1);}}
.tip-form {
    position:absolute;
    transform:translate(-50%,-110%);
    z-index:1001;
    width:250px;
    padding:0.9rem;
    background:#fff;
    border-radius:12px;
    box-shadow:0 20px 40px rgba(0,0,0,0.25);
}
.tip-form textarea{width:100%;height:70px;font-size:0.82rem;margin-bottom:0.5rem;}
.tip-form .row{display:flex;gap:0.5rem;}

/* player toolbar + steps panel + guided tour */
.player-toolbar{display:flex;align-items:center;gap:0.6rem;margin-bottom:0.8rem;}
.steps-panel{margin-top:1rem;border:1px solid var(--border);border-radius:var(--radius-sm);background:var(--surface);overflow:hidden;}
.steps-panel:has(.branch-target-menu:not(.hidden)){overflow:visible;}
.steps-head{display:flex;align-items:center;gap:0.5rem;padding:0.6rem 0.9rem;font-weight:600;font-size:0.85rem;background:var(--surface-2);border-bottom:1px solid var(--border);}
.step-item{display:flex;align-items:center;gap:0.6rem;padding:0.5rem 0.9rem;border-bottom:1px solid var(--border);}
.step-item:last-child{border-bottom:0;}
.step-num{display:grid;place-items:center;width:22px;height:22px;border-radius:50%;background:var(--primary-glow);color:var(--primary);font-size:0.74rem;font-weight:700;flex-shrink:0;}
.step-label{font-size:0.88rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.step-controls{display:flex;gap:0.15rem;flex-shrink:0;}
.step-item.editing{flex-direction:column;align-items:stretch;}
.step-audio{color:var(--primary);font-size:0.78em;margin-left:0.3rem;opacity:0.75;}
.step-branches{color:var(--primary);font-size:0.78em;margin-left:0.3rem;opacity:0.8;}
.voiceover-bar{display:flex;align-items:center;gap:0.5rem;flex-wrap:wrap;padding:0.55rem 0.9rem;border-bottom:1px solid var(--border);background:var(--surface);}
.step-edit{display:flex;flex-direction:column;gap:0.45rem;width:100%;}
.step-edit textarea{min-height:64px;font-size:0.85rem;}
.branch-editor{margin:0;padding:0.75rem;border:1px solid var(--border);border-radius:var(--radius-sm);}
.branch-editor legend{padding:0 0.3rem;font-size:0.84rem;font-weight:700;color:var(--fg-muted);}
.branch-choice-list{display:flex;flex-direction:column;gap:0.65rem;margin-top:0.65rem;}
.branch-choice {
    display:flex;
    flex-direction:column;
    gap:0.45rem;
    padding:0.7rem;
    border:1px solid var(--border);
    border-radius:var(--radius-sm);
    background:var(--surface-2);
}
.branch-choice-head{display:flex;align-items:center;justify-content:space-between;gap:0.5rem;font-size:0.83rem;}
.branch-choice-controls{display:flex;gap:0.15rem;flex-shrink:0;}
.branch-target-wrap{display:flex;flex-direction:column;gap:0.3rem;}
.branch-target-picker{position:relative;display:inline-flex;align-self:flex-start;}
.branch-target-trigger{justify-content:space-between;text-align:left;white-space:normal;}
.branch-target-menu {
    position:absolute;
    top:calc(100% + 4px);
    left:0;
    z-index:30;
    display:flex;
    flex-direction:column;
    gap:0.2rem;
    width:min(300px,calc(100vw - 4rem));
    max-height:220px;
    overflow-y:auto;
    padding:0.4rem;
    background:var(--surface);
    border:1px solid var(--border);
    border-radius:10px;
    box-shadow:0 12px 28px rgba(0,0,0,0.14);
}
.branch-target-option{min-height:36px;padding:0.45rem 0.6rem;border:1px solid transparent;border-radius:7px;background:transparent;color:var(--fg-muted);font:inherit;font-size:0.82rem;font-weight:600;text-align:left;cursor:pointer;}
.branch-target-option:hover:not(:disabled){background:var(--surface-2);border-color:var(--primary);color:var(--fg);}
.branch-target-option.selected{background:var(--primary-glow);color:var(--primary);}
.branch-target-option:disabled{opacity:0.45;cursor:not-allowed;}
.branch-choice-add{align-self:flex-start;}
.branch-choice-empty{margin:0;padding:0.15rem 0;}

/* editor tool selector */
.tool-group{display:inline-flex;gap:0.2rem;padding:2px;background:var(--surface-2);border:1px solid var(--border);border-radius:9px;}
.tool-btn{display:inline-flex;align-items:center;gap:0.35rem;padding:0.32rem 0.6rem;border:none;border-radius:7px;background:transparent;font-size:0.78rem;font-weight:600;color:var(--fg-muted);cursor:pointer;}
.tool-btn.active{background:var(--surface);color:var(--primary);box-shadow:var(--shadow-sm);}

/* redaction regions */
.redactions-layer{position:absolute;top:0;left:0;width:100%;height:calc(100% - 50px);pointer-events:none;z-index:997;}
.redaction-box {
    position:absolute;
    border-radius:6px;
    background:rgba(210,210,216,0.45);
    backdrop-filter:blur(11px);
    -webkit-backdrop-filter:blur(11px);
    box-shadow:inset 0 0 0 1px rgba(0,0,0,0.08);
}
.redaction-box.solid{background:#3a3a3e;backdrop-filter:none;-webkit-backdrop-filter:none;}
.redaction-box.drawing{background:rgba(91,84,232,0.12);backdrop-filter:none;-webkit-backdrop-filter:none;border:1.5px dashed var(--primary);}
.redaction-del {
    position:absolute;
    transform:translate(-50%,-50%);
    width:20px;height:20px;
    display:grid;place-items:center;
    border:none;border-radius:50%;
    background:var(--danger);color:#fff;
    font-size:11px;cursor:pointer;
    pointer-events:auto;z-index:1000;
}
.tour-overlay{position:absolute;top:0;left:0;width:100%;height:calc(100% - 50px);z-index:1200;pointer-events:none;}
.tour-spot {
    position:absolute;
    width:120px;height:120px;
    border-radius:50%;
    transform:translate(-50%,-50%);
    border:2px solid rgba(255,255,255,0.85);
    box-shadow:0 0 0 9999px rgba(15,17,25,0.62);
    transition:left 0.4s var(--ease),top 0.4s var(--ease);
}
.tour-card {
    position:absolute;
    left:50%;bottom:18px;
    transform:translateX(-50%);
    width:min(420px,86%);
    padding:1rem 1.1rem;
    background:#fff;
    border-radius:14px;
    box-shadow:0 20px 44px rgba(0,0,0,0.32);
    pointer-events:auto;
    animation:overlay-in 0.25s var(--ease);
}
.tour-counter{font-size:0.7rem;font-weight:700;letter-spacing:0.05em;text-transform:uppercase;color:var(--primary);margin-bottom:0.3rem;}
.tour-card h4{font-size:1.05rem;margin-bottom:0.3rem;padding-right:2rem;}
.tour-body{font-size:0.9rem;color:var(--fg-muted);line-height:1.5;}
.tour-nav{display:flex;align-items:center;justify-content:space-between;margin-top:0.9rem;}
.tour-choices{margin-top:0.9rem;padding-top:0.8rem;border-top:1px solid var(--border);}
.tour-choice-label{font-size:0.76rem;font-weight:700;color:var(--fg-muted);margin-bottom:0.45rem;}
.tour-choice-list{display:grid;gap:0.45rem;}
.tour-choice{justify-content:flex-start;width:100%;min-height:38px;white-space:normal;text-align:left;}
.tour-completion-icon{color:var(--success);font-size:1.2rem;margin-bottom:0.25rem;}
.tour-completion-nav{gap:0.6rem;}
.tour-mute{position:absolute;top:0.6rem;right:0.7rem;display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;padding:0;border:none;border-radius:8px;background:#f1f4f9;color:var(--fg-muted);cursor:pointer;transition:background 0.15s,color 0.15s;}
.tour-mute:hover{background:#e6ebf3;color:var(--fg);}
.tour-mute[aria-pressed="true"]{color:var(--fg-muted);opacity:0.7;}
/* language switcher (viewer) + editor language management */
.lang-bar{display:inline-flex;align-items:center;gap:0.3rem;flex-wrap:wrap;}
.lang-ico{color:var(--fg-muted);display:inline-flex;margin-right:0.1rem;}
.lang-btn{padding:0.25rem 0.65rem;border:1px solid var(--border);border-radius:999px;background:var(--surface);color:var(--fg-muted);font-size:0.8rem;font-weight:600;cursor:pointer;transition:background 0.15s,color 0.15s,border-color 0.15s;}
.lang-btn:hover{border-color:var(--primary);color:var(--fg);}
.lang-btn.active{background:var(--primary);border-color:var(--primary);color:#fff;}
.lang-panel{display:flex;align-items:center;gap:0.4rem;flex-wrap:wrap;padding:0.55rem 0.9rem;border-bottom:1px solid var(--border);background:var(--surface);}
.lang-chip{display:inline-flex;align-items:center;gap:0.35rem;padding:0.2rem 0.2rem 0.2rem 0.6rem;border:1px solid var(--border);border-radius:999px;font-size:0.8rem;font-weight:600;color:var(--fg-muted);}
.lang-chip .chip-x{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;border:none;border-radius:50%;background:transparent;color:var(--fg-muted);cursor:pointer;}
.lang-chip .chip-x:hover{background:#f1f4f9;color:var(--danger);}
.lang-chip .chip-voice{border:none;background:transparent;color:var(--fg-muted);cursor:pointer;padding:0 0.2rem;}
.lang-chip .chip-voice.on{color:var(--primary);}
.lang-add-menu{position:absolute;top:calc(100% + 4px);left:0;z-index:20;display:flex;flex-direction:column;gap:0.2rem;padding:0.4rem;background:var(--surface);border:1px solid var(--border);border-radius:10px;box-shadow:0 12px 28px rgba(0,0,0,0.14);min-width:150px;}
.lang-add-menu .lang-btn{text-align:left;border-radius:6px;}
/* workspace switcher (sidebar) */
.ws-switch{display:flex;flex-direction:column;gap:0.15rem;padding-bottom:0.6rem;margin-bottom:0.5rem;border-bottom:1px solid var(--border);}
.ws-switch-label{font-size:0.7rem;font-weight:700;letter-spacing:0.05em;text-transform:uppercase;color:var(--fg-muted);padding:0.2rem 0.4rem 0.3rem;}
.ws-opt{text-align:left;padding:0.4rem 0.6rem;border:none;border-radius:8px;background:transparent;color:var(--fg-muted);font-size:0.88rem;font-weight:600;cursor:pointer;transition:background 0.15s,color 0.15s;}
.ws-opt:hover{background:var(--surface-2);color:var(--fg);}
.ws-opt.active{background:var(--primary-glow);color:var(--primary);}
.ws-manage,.ws-new{font-size:0.82rem;}
.ws-members .step-item:last-child{border-bottom:0;}
/* data scrub modal */
.scrub-list{max-height:220px;overflow-y:auto;border:1px solid var(--border);border-radius:var(--radius-sm);}
.scrub-item{display:flex;align-items:center;gap:0.6rem;padding:0.4rem 0.7rem;border-bottom:1px solid var(--border);cursor:pointer;}
.scrub-item:last-child{border-bottom:0;}
.scrub-item:hover{background:var(--surface-2);}
.scrub-text{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:0.88rem;}
.scrub-count{font-size:0.78rem;flex-shrink:0;}
.scrub-chosen{margin:0.4rem 0;line-height:2;}
.ai-assist{display:flex;align-items:center;gap:0.35rem;flex-wrap:wrap;margin-top:0.5rem;}

/* Admin toggle checkbox. Was eight copies of an inline
   `style="width:1rem;height:1rem;accent-color:…"` — a house-style violation, and
   unoverridable besides, because an inline declaration beats every stylesheet
   rule. The mobile touch-size media query below silently did nothing until the
   inline style became this class. */
.check{width:1rem;height:1rem;flex:none;accent-color:var(--primary);cursor:pointer;}

/* switch */
.switch{position:relative;display:inline-block;width:40px;height:23px;flex-shrink:0;}
.switch input{opacity:0;width:0;height:0;}
.slider{position:absolute;inset:0;cursor:pointer;background:#c7c7cc;border-radius:var(--pill);transition:0.2s;}
.slider::before{content:"";position:absolute;height:17px;width:17px;left:3px;bottom:3px;background:#fff;border-radius:50%;box-shadow:0 1px 3px rgba(0,0,0,0.3);transition:0.2s var(--spring);}
.switch input:checked+.slider{background:var(--primary);}
.switch input:checked+.slider::before{transform:translateX(17px);}
/* P18-024. The input is the focusable element, and `opacity:0` above makes it —
   and every decoration painted on it, box-shadow included — fully transparent.
   So the global :focus-visible ring existed and was simply never visible, and
   keyboard users had no indication the editor toggle was focused. (Measured in
   Chrome: the input is NOT collapsed as the `width:0;height:0` suggests — a
   native checkbox has a UA-enforced minimum and computes to 22×22 — so opacity
   is the whole reason, and sizing is a red herring.) Project the house ring onto
   the slider, which is the part that actually paints. */
.switch input:focus-visible+.slider{box-shadow:0 0 0 3px var(--ring);}

/* ---------- demo theme (Phase 18.1) ----------
   Applied only under .vw-themed, which theme.js adds when a payer's PUBLISHED
   theme arrives on a share/embed payload. The variables come from the server
   with the text color already derived, so nothing here can produce an
   unreadable pair; every rule falls back to the stock look when a var is
   absent. */
.vw-themed .btn-primary{background:var(--vw-accent, var(--primary));color:var(--vw-accent-text, #fff);}
.vw-themed .btn-primary:hover{filter:brightness(1.08);}
.vw-themed .tour-card{font-family:var(--vw-font, inherit);}
.vw-themed .tour-card .btn-primary{background:var(--vw-accent, var(--primary));color:var(--vw-accent-text, #fff);}
.vw-themed .lang-btn.active{background:var(--vw-accent, var(--primary));color:var(--vw-accent-text, #fff);}
.theme-logo{max-height:34px;max-width:160px;display:block;margin-bottom:0.4rem;}

/* ---------- share page ---------- */
.share-shell{min-height:100vh;display:flex;flex-direction:column;}
.share-bar {
    display:flex;
    align-items:center;
    justify-content:space-between;
    padding:0.9rem clamp(1rem,4vw,3rem);
    background:var(--glass);
    border-bottom:1px solid var(--border);
    backdrop-filter:blur(16px);
}
.share-body{flex:1;width:100%;max-width:1100px;margin:0 auto;padding:clamp(1.5rem,4vw,3rem);}
.share-cta{display:flex;align-items:center;gap:0.8rem;justify-content:center;margin-top:2rem;padding:1.4rem;border-radius:var(--radius);background:var(--surface);border:1px solid var(--border);box-shadow:var(--shadow-sm);flex-wrap:wrap;}

/* embed surface + branding badge */
.embed-body{background:var(--bg);min-height:100vh;}
.embed-wrap{padding:8px;}
.av-badge {
    position:fixed;
    bottom:10px;right:10px;
    z-index:50;
    display:inline-flex;align-items:center;gap:0.4rem;
    padding:0.32rem 0.62rem;
    font-size:0.72rem;font-weight:600;
    color:var(--fg-muted);
    background:var(--surface);
    border:1px solid var(--border);
    border-radius:var(--pill);
    box-shadow:var(--shadow-sm);
}
.av-badge i{color:var(--primary);}
.av-badge:hover{color:var(--fg);}

/* ---------- view transitions (fallback) ---------- */
.view-enter{animation:view-in 0.32s var(--ease);}
@keyframes view-in{from{opacity:0;transform:translateY(8px);}to{opacity:1;transform:none;}}
.center-screen{display:grid;place-items:center;min-height:60vh;gap:1rem;text-align:center;}

/* announcement banner (server-rendered on public pages, mirrored in the SPA) */
.announce {
    display:flex;
    align-items:center;
    justify-content:center;
    gap:0.8rem;
    padding:0.6rem 1rem;
    background:var(--primary);
    color:#fff;
    font-size:0.86rem;
    font-weight:600;
    text-align:center;
}
.announce-x{background:none;border:0;color:#fff;font-size:1.2rem;line-height:1;cursor:pointer;opacity:0.75;padding:0 0.2rem;}
.announce-x:hover{opacity:1;}
/* Warning variant (email-verification prompt) — amber instead of brand purple. */
.announce-warn{background:#b45309;}

/* plan durations + picker */
.plan-terms{list-style:none;margin:-0.4rem 0 0.9rem;padding:0;font-size:0.78rem;color:var(--fg-subtle);}
.plan-terms li{padding:0.1rem 0;}
.plan-opt {
    display:flex;
    align-items:center;
    gap:0.6rem;
    padding:0.7rem 0.85rem;
    border:1px solid var(--border);
    border-radius:var(--radius-sm);
    cursor:pointer;
    transition:border-color var(--dur),background-color var(--dur);
}
.plan-opt:hover{border-color:var(--border-strong);}
.plan-opt:has(input:checked){border-color:var(--primary);background:var(--primary-glow);}
.plan-opt input{accent-color:var(--primary);cursor:pointer;}
.plan-opt-main{flex:1;min-width:0;font-size:0.85rem;}

/* ---------- support ---------- */
/* The ticket lists reuse .rec-list/.rec-row and the composer reuses
   .field/.input — only the conversation itself needs its own selectors. */
.msg-list{display:flex;flex-direction:column;gap:0.75rem;}
.msg {
    align-self:flex-start;
    max-width:76%;
    padding:0.8rem 1rem;
    background:var(--surface);
    border:1px solid var(--border);
    border-radius:var(--radius);
    box-shadow:var(--shadow-sm);
}
.msg.out{align-self:flex-end;background:var(--primary-glow);border-color:rgba(91,84,232,0.22);}
.msg-meta{font-size:0.72rem;color:var(--fg-subtle);margin-bottom:0.3rem;}
.msg-system{align-self:center;font-size:0.74rem;color:var(--fg-subtle);text-align:center;padding:0.2rem 0.6rem;}
.msg-files{display:flex;flex-direction:column;gap:0.3rem;margin-top:0.5rem;}
.msg-file{display:inline-flex;align-items:center;gap:0.3rem;font-size:0.82rem;color:var(--primary);background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius-sm);padding:0.3rem 0.55rem;text-decoration:none;}
.msg-file:hover{border-color:var(--primary);}
/* Turnstile widget holder on the support forms; margin only once it renders. */
.cf-holder:not(:empty){margin:0.2rem 0;}
.cf-err{font-size:0.78rem;color:var(--danger);margin:0.2rem 0 0;}
/* pre-wrap is what makes plain-text bodies keep their newlines without HTML. */
.msg-body{font-size:0.92rem;line-height:1.55;white-space:pre-wrap;overflow-wrap:anywhere;}
.side-count{margin-left:auto;font-size:0.7rem;font-weight:700;min-width:1.15rem;padding:0.05rem 0.35rem;border-radius:var(--pill);text-align:center;background:var(--primary);color:#fff;}
.unread-dot{font-size:0.5rem;color:var(--primary);vertical-align:middle;}

/* ---------- utilities ---------- */
.row{display:flex;gap:0.6rem;}
.row-wrap{display:flex;gap:0.6rem;flex-wrap:wrap;}
.stack{display:flex;flex-direction:column;gap:0.85rem;}
.modal-actions{display:flex;gap:0.6rem;justify-content:flex-end;margin-top:1.5rem;}
.confirm-text{color:var(--fg-muted);font-size:0.95rem;line-height:1.55;}
.mt-2{margin-top:1rem;}
.grow{flex:1;min-width:0;}

/* comparison pages (/compare) */
.table-wrap{overflow-x:auto;-webkit-overflow-scrolling:touch;}
.compare-table{width:100%;border-collapse:collapse;min-width:520px;font-size:0.95rem;}
.compare-table th,.compare-table td{padding:0.7rem 0.85rem;text-align:left;vertical-align:top;border-bottom:1px solid var(--border);}
.compare-table thead th{font-size:0.78rem;text-transform:uppercase;letter-spacing:0.03em;color:var(--fg-subtle);font-weight:600;}
.compare-table thead th:nth-child(2){color:var(--primary);}
.compare-table tbody th{font-weight:600;width:34%;}
.compare-table .col-us{background:var(--primary-glow);font-weight:600;}
.compare-table.matrix td{text-align:center;}
.compare-table.matrix thead th:not(:first-child){text-align:center;}
.mark-yes{color:#12805c;font-size:1.05rem;}
.mark-no{color:var(--fg-subtle);opacity:0.45;font-size:1.05rem;}

/* landing wedge band (them vs Framvis) */
.wedge{position:relative;display:flex;align-items:stretch;border:1px solid var(--border);border-radius:var(--radius-lg);overflow:hidden;box-shadow:0 12px 34px rgba(31,26,84,0.12);isolation:isolate;}
.wedge-side{
    flex:1;
    display:flex;
    flex-direction:column;
    gap:0.35rem;
    justify-content:center;
    padding:1.75rem 1.6rem;
    text-align:center;
}
.wedge-them{background:var(--surface);color:var(--fg);}
.wedge-us{background:linear-gradient(135deg,var(--primary),var(--primary-600));color:#fff;}
.wedge-cap{font-size:0.78rem;text-transform:uppercase;letter-spacing:0.05em;font-weight:700;opacity:0.72;}
.wedge-price{font-size:2.5rem;font-weight:800;line-height:1;}
.wedge-price span{font-size:1rem;font-weight:600;opacity:0.7;}
.wedge-sub{font-size:0.9rem;opacity:0.85;line-height:1.4;}
/* faint holographic sheen: a static iridescent tint + a slow glare sweep */
.wedge::before{content:"";position:absolute;inset:0;z-index:1;pointer-events:none;background:linear-gradient(125deg,rgba(120,180,255,0.14),rgba(190,120,255,0.12) 38%,rgba(120,255,210,0.10) 68%,rgba(255,190,120,0.12));mix-blend-mode:soft-light;}
.wedge::after{content:"";position:absolute;top:0;bottom:0;width:45%;z-index:1;pointer-events:none;background:linear-gradient(115deg,transparent 42%,rgba(255,255,255,0.25) 50%,transparent 58%);transform:translateX(-160%);animation:wedge-sheen 7s ease-in-out infinite;}
@keyframes wedge-sheen{0%,18%{transform:translateX(-160%);}62%,100%{transform:translateX(360%);}}
/* the "VS" bubble, centered on the seam where the two panels meet */
.wedge-vs{
    position:absolute;
    top:50%;
    left:50%;
    transform:translate(-50%,-50%);
    z-index:3;
    width:64px;
    height:64px;
    display:flex;
    align-items:center;
    justify-content:center;
    border-radius:50%;
    background:var(--surface);
    border:1px solid var(--border);
    box-shadow:0 8px 22px rgba(31,26,84,0.22);
    font-size:1.35rem;
    font-weight:800;
    letter-spacing:0.03em;
    color:var(--primary);
}

/* demo hubs (Phase 7) — the public /hub/<token> page and the SPA editor.
   Two layouts share one tile. Gallery is a responsive grid and list is a single
   column, built with auto-fill + minmax rather than a media query, so the grid
   reflows at whatever width the content actually needs. */
.hub-gallery{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:1rem;}
.hub-list{display:flex;flex-direction:column;gap:0.6rem;}
.hub-item {
    display:flex;
    align-items:center;
    gap:0.9rem;
    padding:1rem 1.1rem;
    border:1px solid var(--border);
    border-radius:var(--radius);
    background:var(--surface);
    box-shadow:var(--shadow-sm);
    transition:border-color var(--dur),box-shadow var(--dur),transform var(--dur);
}
.hub-item:hover{border-color:var(--primary);box-shadow:var(--shadow-md);transform:translateY(-2px);}
.hub-num{flex:none;width:28px;height:28px;border-radius:var(--pill);background:var(--primary-glow);color:var(--primary);font-size:0.8rem;font-weight:700;display:flex;align-items:center;justify-content:center;}
.hub-body{display:flex;flex-direction:column;gap:0.15rem;min-width:0;flex:1;}
.hub-title{font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.hub-meta{font-size:0.8rem;}
.hub-go{flex:none;color:var(--fg-subtle);}
.hub-item:hover .hub-go{color:var(--primary);}
/* Editor row: same tile, plus reorder/remove controls. */
.hub-row{display:flex;align-items:center;gap:0.6rem;padding:0.7rem 0.85rem;border:1px solid var(--border);border-radius:var(--radius-sm);background:var(--surface);}
.hub-row-title{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:600;font-size:0.92rem;}

/* ---------- admin mailbox (Phase 23) — read/reply pane for support@ ----------
   Reuses .rec-list/.rec-row for the message list and .msg-body (pre-wrap) for
   the plain-text body, exactly like the ticket queue above (.empty/.empty-ico
   cover the not-configured and mailbox-unavailable states too) — only what is
   genuinely new to this leaf gets its own selectors. */
/* Unseen-message emphasis, scoped to this leaf's own root so it can never
   bleed into ticket rows elsewhere on the shared .rec-row class. */
#mailbox-root .rec-row.is-unseen{background:var(--primary-glow);border-color:rgba(91,84,232,0.18);}
#mailbox-root .rec-row.is-unseen .rec-title{font-weight:700;}
.mail-detail-meta{font-size:0.8rem;color:var(--fg-subtle);margin-bottom:1rem;}
/* Attachment chips are INERT by design (v1 ships no download affordance) —
   .msg-file's look without the link, so they read as inspectable, not active. */
.mail-attachment{display:inline-flex;align-items:center;gap:0.35rem;font-size:0.82rem;color:var(--fg-muted);background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius-sm);padding:0.3rem 0.55rem;}
.mail-attachment b{font-weight:600;color:var(--fg);}
/* Reply byte counter over SupportMail::REPLY_BODY_MAX (correction round). */
.mail-count-over{color:var(--danger);font-weight:600;}
/* Config-form validation error (Phase 23.1) — inline against the form, never
   the whole-leaf .empty treatment: a bad port number is not an outage. */
.mail-form-error {
    display:flex;
    align-items:center;
    gap:0.4rem;
    font-size:0.85rem;
    color:var(--danger);
    margin:0;
}

/* ============================================================
   media queries
   ============================================================ */
@media (max-width:860px){
    /* THE SIDEBAR BECOMES AN OFF-CANVAS DRAWER, it does not rotate.
       It used to lie down into a horizontal nav strip, which worked (no overflow
       after the 2026-08-03 fix) but cost 220-270px — 23-28% of a 956px phone —
       before any content, wrapped the links onto three rows, and left "Manage
       teams" orphaned on a line of its own. A strip is also the wrong shape for
       the admin shell's seven links.
       Out of flow, so .shell has one in-flow child and needs no row sizing at
       all — the two-auto-rows trap that inflated the old strip cannot arise. */
    .shell{display:block;}
    .sidebar {
        position:fixed;
        top:0;
        bottom:0;
        left:0;
        z-index:120;
        width:min(84vw,300px);
        padding:1rem 0.85rem calc(1rem + env(safe-area-inset-bottom,0px));
        border-right:1px solid var(--border);
        background:var(--surface);
        box-shadow:var(--shadow-lg);
        overflow-y:auto;
        overscroll-behavior:contain;
        transform:translateX(-100%);
        visibility:hidden;
        /* visibility is delayed to the end of the slide-out so the drawer stays
           painted while it animates away, but leaves the tab order the moment it
           is closed. */
        transition:transform var(--dur) var(--ease),visibility 0s linear var(--dur);
    }
    html.nav-open .sidebar{transform:none;visibility:visible;transition:transform var(--dur) var(--ease),visibility 0s;}
    .nav-scrim {
        display:block;
        position:fixed;
        inset:0;
        z-index:110;
        background:rgba(0,0,0,0.38);
        opacity:0;
        pointer-events:none;
        transition:opacity var(--dur) var(--ease);
    }
    html.nav-open .nav-scrim{opacity:1;pointer-events:auto;}
    .nav-toggle{display:inline-flex;}
    /* A drawer has room for what the strip had to hide, and the touch sizes the
       strip could not afford. 44px is the Apple HIG minimum. */
    .side-link{min-height:44px;white-space:nowrap;}
    .side-foot{display:block;margin-top:1rem;}
    .ws-opt{min-height:44px;display:flex;align-items:center;}
    .ws-manage{min-height:44px;}
    /* The header keeps only brand + sign-out: Admin and Dashboard are in the
       drawer, and as bare 34x30 icons here they were both cramped and ambiguous. */
    .app-nav-auth .side-link{display:none;}
    /* Touch sizing for CONTENT controls, not just nav. Measured at 360px before
       this change — the per-project edit/delete buttons were 40x28, every
       .btn-sm 84x28, and the admin settings checkboxes 16x16, all well under the
       44px HIG minimum, on the surfaces where a mis-tap deletes a project. Width
       is left alone so nothing reflows. Only the vertical hit area grows. */
    .btn{min-height:44px;}
    .btn-sm{min-height:40px;padding-block:0.5rem;}
    /* An icon-only button has no text to widen it, so it needs the floor on both
       axes or it stays a 40x40-at-best sliver. */
    .btn-sm:has(> i:only-child){min-width:44px;min-height:44px;padding-inline:0.5rem;}
    .tour-choice,.branch-target-option,.branch-target-trigger,.branch-choice-add{min-height:44px;}
    /* flex:none is load-bearing, not tidiness: these sit in `.row` flex
       containers and were being SHRUNK below their own width — measured at
       13.25px against a 16px box, i.e. a target narrower than it looks. */
    input[type=checkbox],input[type=radio],.check{width:22px;height:22px;flex:none;}
    .profile-grid{grid-template-columns:1fr;}
    .capture-layout{grid-template-columns:1fr;}
    .wedge{flex-direction:column;}
}
@media (max-width:560px){
    .features .feature-card:last-child{grid-column:auto;}
    .msg{max-width:92%;}
    .app-header{padding:.7rem .75rem;gap:.4rem;}
    .app-nav-auth{gap:.15rem;min-width:0;}
    /* The icon-only shrink that used to live here is gone with the header links
       themselves (hidden at 860px, where they moved into the drawer). It made
       Admin and Dashboard 34x30 bare glyphs — under the 44px touch minimum and
       unlabelled. Sign out is the only header control left, so it gets the size. */
    .app-nav-auth .btn{min-height:44px;padding-inline:.85rem;}
    .page-head{flex-direction:column;}
    .rec-row{flex-direction:column;align-items:stretch;}
    .rec-actions{justify-content:flex-end;}
    .device-row{align-items:flex-start;flex-direction:column;}
    .tour-card{width:calc(100% - 1rem);bottom:8px;padding:0.85rem 0.9rem;}
    .tour-nav{align-items:flex-start;flex-wrap:wrap;gap:0.55rem;}
    .toast-stack{left:1rem;right:1rem;bottom:1rem;max-width:none;}
    .lead-builder-grid{grid-template-columns:1fr;}
    .lead-builder-title{align-items:flex-start;flex-direction:column;}
}
@media (max-width:375px){
    .branch-choice-head{align-items:flex-start;flex-direction:column;}
    .branch-choice-controls{width:100%;justify-content:flex-end;}
    .branch-target-picker,.branch-target-trigger{width:100%;}
    .branch-target-menu{width:100%;}
    .tour-completion-nav{flex-direction:column;}
    .tour-completion-nav>span{width:100%;}
    .tour-completion-nav .row{justify-content:flex-end;}
}
@media (prefers-reduced-motion:reduce){
    *{animation-duration:0.001ms!important;animation-iteration-count:1!important;transition-duration:0.001ms!important;}
}
@media print{.app-header,.share-bar,.share-cta,.editor-bar{display:none;}}
