/* ============================================================================
   JustLinks — brand design system
   ============================================================================
   The marketing surface (home, pricing, explore, acceptable use) is a dark,
   editorial canvas. It is deliberately a separate layer from Bootstrap rather
   than a theme on top of it: Bootstrap still paints the authenticated
   dashboard, and a theme override there would drag every owner-facing table
   and form along with it.

   Rules that keep this honest:
   - Tokens live in :root and are the only source of colour, type and rhythm.
   - Nothing here targets a dashboard class. If a dashboard is ever redesigned
     it should get its own system, not inherit this one by accident.
   - Motion is decorative and always respects prefers-reduced-motion.
   ========================================================================== */

:root {
    /* Surfaces — near-black, not pure black, so shadows still read. */
    --jl-canvas: #07080a;
    --jl-canvas-2: #0b0d10;
    --jl-surface: rgba(255, 255, 255, .032);
    --jl-surface-2: rgba(255, 255, 255, .055);
    --jl-line: rgba(255, 255, 255, .09);
    --jl-line-strong: rgba(255, 255, 255, .18);

    /* Ink */
    --jl-ink: #f5f7fa;
    --jl-ink-2: rgba(245, 247, 250, .64);
    --jl-ink-3: rgba(245, 247, 250, .42);

    /* Brand — the existing palette, used sparingly. Cyan is the single accent. */
    --jl-cyan: #00aff0;
    --jl-sky: #7fe0ff;
    --jl-deep: #0a7cc1;
    --jl-navy: #083a52;

    /* Semantic markers for the pricing feature table: a check means included, an X means not. */
    --jl-yes: #34d399;
    --jl-no: #fb7185;

    /* Type */
    --jl-font-body: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
    --jl-font-display: 'Inter Tight', 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    --jl-font-serif: 'Instrument Serif', Georgia, 'Times New Roman', serif;

    /* Rhythm */
    --jl-radius: 18px;
    --jl-radius-sm: 12px;
    --jl-gutter: clamp(1.25rem, 4vw, 3rem);
    --jl-section: clamp(5.5rem, 11vw, 10.5rem);
}

/* ---------------------------------------------------------------------------
   Shell
   ------------------------------------------------------------------------- */

.mkt-shell {
    position: relative;
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    background: var(--jl-canvas);
    color: var(--jl-ink);
    font-family: var(--jl-font-body);
    font-size: 16px;
    line-height: 1.6;
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
    overflow-x: clip;
}

.mkt-shell ::selection {
    background: rgba(0, 175, 240, .32);
    color: #fff;
}

.mkt-main {
    flex: 1;
}

.mkt-container {
    width: min(1180px, 100% - (var(--jl-gutter) * 2));
    margin-inline: auto;
}

.mkt-container--narrow {
    width: min(820px, 100% - (var(--jl-gutter) * 2));
    margin-inline: auto;
}

.mkt-section {
    padding-block: var(--jl-section);
    position: relative;
}

.mkt-hairline {
    height: 1px;
    border: 0;
    margin: 0;
    background: linear-gradient(90deg, transparent, var(--jl-line), transparent);
}

/* ---------------------------------------------------------------------------
   Typography primitives
   ------------------------------------------------------------------------- */

.mkt-display,
.mkt-h1,
.mkt-h2,
.mkt-h3 {
    font-family: var(--jl-font-display);
    font-weight: 700;
    letter-spacing: -.035em;
    line-height: .98;
    margin: 0;
    color: var(--jl-ink);
    text-wrap: balance;
}

.mkt-display {
    font-size: clamp(2.8rem, 7.4vw, 6.4rem);
    line-height: .92;
    letter-spacing: -.045em;
}

.mkt-h1 { font-size: clamp(2.4rem, 5.4vw, 4.4rem); }
.mkt-h2 { font-size: clamp(2rem, 4.4vw, 3.4rem); }
.mkt-h3 { font-size: clamp(1.35rem, 2.4vw, 1.85rem); letter-spacing: -.025em; }

.mkt-serif {
    font-family: var(--jl-font-serif);
    font-style: italic;
    font-weight: 400;
    letter-spacing: 0;
}

.mkt-gradient-text {
    background: linear-gradient(100deg, #ffffff 0%, var(--jl-sky) 55%, var(--jl-cyan) 100%);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
}

.mkt-eyebrow {
    display: inline-flex;
    align-items: center;
    gap: .7rem;
    margin: 0 0 1.6rem;
    font-size: .74rem;
    font-weight: 600;
    letter-spacing: .22em;
    text-transform: uppercase;
    color: var(--jl-ink-3);
}

.mkt-eyebrow::before {
    content: "";
    width: 1.8rem;
    height: 1px;
    background: var(--jl-cyan);
    opacity: .8;
}

.mkt-lede {
    margin: 1.6rem 0 0;
    max-width: 46ch;
    font-size: clamp(1.05rem, 1.5vw, 1.3rem);
    line-height: 1.55;
    color: var(--jl-ink-2);
}

.mkt-note {
    font-size: .9rem;
    color: var(--jl-ink-3);
}

/* Bootstrap's reboot paints headings near-black and links default blue. On the dark
   canvas that is invisible, so the shell re-points the handful of primitives the
   marketing pages actually use. Scoped to .mkt-shell on purpose - the dashboard is
   never inside it and keeps Bootstrap's own defaults.

   Wrapped in :where() so these element-level rules contribute ZERO specificity and
   therefore never out-rank a real component class. Without it, `.mkt-shell a` would
   beat `.mkt-brand` and paint the wordmark accent-cyan. */
:where(.mkt-shell) h1,
:where(.mkt-shell) h2,
:where(.mkt-shell) h3,
:where(.mkt-shell) h4,
:where(.mkt-shell) h5,
:where(.mkt-shell) h6 {
    color: var(--jl-ink);
}

:where(.mkt-shell) p,
:where(.mkt-shell) li,
:where(.mkt-shell) dl,
:where(.mkt-shell) dd {
    color: inherit;
}

:where(.mkt-shell) a {
    color: var(--jl-sky);
}

.mkt-shell .lead {
    color: var(--jl-ink-2);
    font-size: clamp(1.05rem, 1.5vw, 1.28rem);
}

.mkt-shell .text-muted {
    color: var(--jl-ink-3) !important;
}

.mkt-shell code {
    color: var(--jl-sky);
    background: rgba(0, 175, 240, .1);
    padding: .1rem .42rem;
    border-radius: 6px;
}

.mkt-shell hr {
    border-color: var(--jl-line);
    opacity: 1;
}

/* Form controls on the dark surface. */
.mkt-shell .form-control,
.mkt-shell .form-select {
    background: rgba(255, 255, 255, .04);
    border: 1px solid var(--jl-line-strong);
    color: var(--jl-ink);
}

.mkt-shell .form-control::placeholder {
    color: var(--jl-ink-3);
}

.mkt-shell .form-control:focus,
.mkt-shell .form-select:focus {
    background: rgba(255, 255, 255, .06);
    border-color: var(--jl-cyan);
    color: var(--jl-ink);
    box-shadow: none;
}

/* ---------------------------------------------------------------------------
   Buttons — overrides Bootstrap's defaults wherever the marketing shell is
   in scope, so existing markup (.btn-primary) keeps working but reads premium.
   ------------------------------------------------------------------------- */

.mkt-shell .btn {
    --bs-btn-focus-box-shadow: none;
    border-radius: 999px;
    padding: .72rem 1.5rem;
    font-weight: 600;
    font-size: .95rem;
    letter-spacing: -.01em;
    transition: transform .18s ease, background-color .18s ease, border-color .18s ease, box-shadow .18s ease, color .18s ease;
}

.mkt-shell .btn:active {
    transform: translateY(1px);
}

.mkt-shell .btn-primary {
    background: var(--jl-ink);
    border-color: var(--jl-ink);
    color: #07080a;
    box-shadow: 0 0 0 0 rgba(0, 175, 240, .0);
}

.mkt-shell .btn-primary:hover,
.mkt-shell .btn-primary:focus-visible {
    background: #ffffff;
    border-color: #ffffff;
    color: #07080a;
    box-shadow: 0 10px 40px -12px rgba(127, 224, 255, .65);
}

.mkt-shell .btn-accent {
    background: linear-gradient(120deg, var(--jl-sky), var(--jl-cyan));
    border: 0;
    color: #04141c;
    box-shadow: 0 14px 44px -18px rgba(0, 175, 240, .9);
}

.mkt-shell .btn-accent:hover,
.mkt-shell .btn-accent:focus-visible {
    color: #04141c;
    filter: brightness(1.06);
    box-shadow: 0 18px 54px -16px rgba(127, 224, 255, .95);
}

.mkt-shell .btn-outline-primary,
.mkt-shell .btn-outline-secondary {
    background: transparent;
    border: 1px solid var(--jl-line-strong);
    color: var(--jl-ink);
}

.mkt-shell .btn-outline-primary:hover,
.mkt-shell .btn-outline-secondary:hover,
.mkt-shell .btn-outline-primary:focus-visible,
.mkt-shell .btn-outline-secondary:focus-visible {
    background: var(--jl-surface-2);
    border-color: var(--jl-ink-3);
    color: #fff;
}

.mkt-shell .btn-lg {
    padding: .95rem 1.9rem;
    font-size: 1.02rem;
}

/* The base rule above out-ranks Bootstrap's own .btn-sm, so the small variant has to be
   re-stated here or the paging and empty-state buttons inherit full-size padding. */
.mkt-shell .btn-sm {
    padding: .45rem .95rem;
    font-size: .84rem;
}

.mkt-shell a:focus-visible,
.mkt-shell button:focus-visible,
.mkt-shell input:focus-visible,
.mkt-shell select:focus-visible {
    outline: 2px solid var(--jl-sky);
    outline-offset: 3px;
    border-radius: 8px;
}

/* ---------------------------------------------------------------------------
   Navigation
   ------------------------------------------------------------------------- */

.mkt-nav {
    position: sticky;
    top: 0;
    z-index: 50;
    background: rgba(7, 8, 10, .72);
    backdrop-filter: saturate(160%) blur(16px);
    -webkit-backdrop-filter: saturate(160%) blur(16px);
    border-bottom: 1px solid transparent;
    transition: border-color .3s ease, background-color .3s ease;
}

.mkt-nav-inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1.5rem;
    height: 4.5rem;
}

.mkt-brand {
    display: inline-flex;
    align-items: center;
    gap: .6rem;
    color: var(--jl-ink);
    text-decoration: none;
    font-family: var(--jl-font-display);
    font-weight: 700;
    font-size: 1.18rem;
    letter-spacing: -.03em;
}

.mkt-brand:hover { color: #fff; }

.mkt-brand-mark {
    width: 30px;
    height: auto;
    flex: none;
}

.mkt-brand-dot {
    color: var(--jl-cyan);
}

.mkt-nav-links {
    display: flex;
    align-items: center;
    gap: 2rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.mkt-nav-links a {
    position: relative;
    color: var(--jl-ink-2);
    text-decoration: none;
    font-size: .93rem;
    font-weight: 500;
    transition: color .18s ease;
}

.mkt-nav-links a:hover,
.mkt-nav-links a.active {
    color: #fff;
}

.mkt-nav-links a.active::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: -1.55rem;
    height: 1px;
    background: var(--jl-cyan);
}

.mkt-nav-actions {
    display: flex;
    align-items: center;
    gap: .6rem;
}

.mkt-nav-actions .btn {
    padding: .55rem 1.15rem;
    font-size: .9rem;
    white-space: nowrap;
}

.mkt-nav-signin {
    color: var(--jl-ink-2);
    text-decoration: none;
    font-size: .93rem;
    font-weight: 500;
    margin-right: .4rem;
}

.mkt-nav-signin:hover { color: #fff; }

@media (max-width: 767.98px) {
    .mkt-nav-links { display: none; }
    .mkt-nav-signin { display: none; }
    .mkt-nav-inner { height: 4rem; }
}

@media (max-width: 575.98px) {
    .mkt-nav-actions .btn { padding: .5rem .9rem; font-size: .84rem; }
    .mkt-brand { font-size: 1.05rem; }
    .mkt-brand-mark { width: 26px; }
}

/* ---------------------------------------------------------------------------
   Footer
   ------------------------------------------------------------------------- */

.mkt-footer {
    border-top: 1px solid var(--jl-line);
    padding-block: clamp(3.5rem, 7vw, 5.5rem) 2.5rem;
    color: var(--jl-ink-2);
}

.mkt-footer-grid {
    display: grid;
    grid-template-columns: 1.6fr repeat(3, 1fr);
    gap: 2.5rem;
}

.mkt-footer-brand p {
    margin: 1rem 0 0;
    max-width: 30ch;
    font-size: .9rem;
    color: var(--jl-ink-3);
}

.mkt-footer h4 {
    margin: 0 0 1rem;
    font-size: .72rem;
    font-weight: 600;
    letter-spacing: .2em;
    text-transform: uppercase;
    color: var(--jl-ink-3);
}

.mkt-footer ul {
    margin: 0;
    padding: 0;
    list-style: none;
    display: grid;
    gap: .6rem;
}

.mkt-footer a {
    color: var(--jl-ink-2);
    text-decoration: none;
    font-size: .92rem;
}

.mkt-footer a:hover { color: #fff; }

.mkt-footer-base {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    margin-top: 3.5rem;
    padding-top: 1.75rem;
    border-top: 1px solid var(--jl-line);
    font-size: .84rem;
    color: var(--jl-ink-3);
}

@media (max-width: 767.98px) {
    .mkt-footer-grid { grid-template-columns: 1fr 1fr; }
    .mkt-footer-brand { grid-column: 1 / -1; }
}

/* ---------------------------------------------------------------------------
   Hero
   ------------------------------------------------------------------------- */

.mkt-hero {
    position: relative;
    padding-block: clamp(4rem, 9vw, 8rem) clamp(5rem, 9vw, 9rem);
    overflow: hidden;
}

.mkt-hero::before {
    content: "";
    position: absolute;
    inset: -30% -20% auto -20%;
    height: 90%;
    background:
        radial-gradient(48% 60% at 22% 28%, rgba(0, 175, 240, .20), transparent 70%),
        radial-gradient(42% 55% at 82% 12%, rgba(127, 224, 255, .13), transparent 72%),
        radial-gradient(60% 60% at 60% 90%, rgba(10, 124, 193, .12), transparent 75%);
    filter: blur(10px);
    pointer-events: none;
}

.mkt-hero::after {
    content: "";
    position: absolute;
    inset: 0;
    background-image: linear-gradient(rgba(255, 255, 255, .035) 1px, transparent 1px),
        linear-gradient(90deg, rgba(255, 255, 255, .035) 1px, transparent 1px);
    background-size: 64px 64px;
    mask-image: radial-gradient(70% 60% at 50% 30%, #000 0%, transparent 75%);
    -webkit-mask-image: radial-gradient(70% 60% at 50% 30%, #000 0%, transparent 75%);
    pointer-events: none;
}

.mkt-hero-inner {
    position: relative;
    display: grid;
    grid-template-columns: 1.1fr .9fr;
    align-items: center;
    gap: clamp(2.5rem, 6vw, 5rem);
}

.mkt-hero-copy { max-width: 40rem; }

/* Spacing is owned by .jl-claim-stack's gap, so these two rows carry none of their own. */
.mkt-hero-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .8rem;
    margin-top: 0;
}

.mkt-hero-trust {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .5rem 1.4rem;
    margin-top: 0;
    font-size: .85rem;
    color: var(--jl-ink-3);
}

.mkt-hero-trust span {
    display: inline-flex;
    align-items: center;
    gap: .5rem;
}

.mkt-hero-trust i { color: var(--jl-cyan); font-size: .78rem; }

/* ---------------------------------------------------------------------------
   Hero — link availability checker

   One field and one button. The input and the ".justlinks.page" suffix sit
   inside a single bordered field so the whole address reads as one control,
   which is what the visitor is actually choosing.

   Focus lights the OUTER field, not the input: the caret is enough to show
   where typing goes, and a second ring inside the box is noise.
   ------------------------------------------------------------------------- */

/* Wraps the field row and the status line. The padding reserves a band under the field for
   the status, which is positioned into it — so the trust row below never moves when a
   message appears or clears. */
/* A single column with one gap, so the field, the status line, the trust row and the actions
   are all separated by exactly the same space. The status reserves a line's height, so an
   empty status occupies the same space as a filled one and nothing below ever moves. */
.jl-claim-stack {
    display: flex;
    flex-direction: column;
    gap: .8rem;
    margin-top: 2.4rem;
    max-width: 42rem;
}

.jl-claim {
    display: flex;
    flex-wrap: wrap;
    align-items: stretch;
    gap: .75rem;
    margin: 0;
}

.jl-claim-field {
    flex: 1 1 15rem;
    display: flex;
    align-items: center;
    /* Symmetric horizontal padding: the ".justlinks.page" suffix gets the same breathing room
       from the right edge that the placeholder gets from the left. */
    padding: .15rem 1.1rem;
    border: 1px solid var(--jl-line-strong);
    border-radius: 14px;
    background: rgba(255, 255, 255, .04);
    transition: border-color .18s ease, box-shadow .18s ease;
}

/* The outer field is the thing that highlights on focus. */
.jl-claim-field:focus-within {
    border-color: var(--jl-cyan);
    box-shadow: 0 0 0 3px rgba(0, 175, 240, .18);
}

.jl-claim-input {
    flex: 1;
    min-width: 4rem;
    padding: .7rem 0;
    border: 0;
    background: transparent;
    color: var(--jl-ink);
    font-size: 1.02rem;
    outline: none;
}

/* The inner textbox itself must NOT highlight. This has to out-specify the global
   .mkt-shell input:focus-visible rule (which draws a 2px sky outline), or the typing area
   shows a ring of its own inside the already-highlighted field. */
.mkt-shell .jl-claim-input:focus,
.mkt-shell .jl-claim-input:focus-visible {
    outline: none;
    box-shadow: none;
}

.jl-claim-input::placeholder { color: var(--jl-ink-3); }

.jl-claim-suffix {
    color: var(--jl-ink-3);
    font-size: 1.02rem;
    white-space: nowrap;
    user-select: none;
}

.jl-claim-btn { flex: 0 0 auto; }

/* In the flow with a FIXED height. min-height was not enough: the text's inherited line box
   (~1.42rem) is taller than the reserved minimum, so a filled status was a pixel or two taller
   than an empty one and pushed the rows below. An explicit height, with line-height:1 so the
   content always fits inside it, is identical in both states and the stack gap never moves. */
.jl-claim-status {
    display: flex;
    align-items: center;
    gap: .5rem;
    margin: 0;
    height: 1.4rem;
    font-size: .95rem;
    line-height: 1;
    font-weight: 500;
}

.jl-claim-status i { font-size: .85rem; }

/* Green for available, red for refused — distinct from the cyan accent, which
   is decoration rather than a verdict. */
.jl-claim-status--ok { color: #5be5a0; }
.jl-claim-status--bad { color: #ff8b95; }

@media (max-width: 575.98px) {
    /* The button takes the full width under the field so the pair does not wrap
       into a cramped half-row on a phone. */
    .jl-claim-field { flex-basis: 100%; }
    .jl-claim-btn { width: 100%; }
}


@keyframes jl-rise {
    from { opacity: 0; transform: translateY(18px); }
    to { opacity: 1; transform: none; }
}

/* ---------------------------------------------------------------------------
   Entrance animations, gated.

   These play once per document load, not once per element insertion. That
   distinction is load-bearing in a prerendered Blazor app: the circuit's first
   render re-inserts the prerendered markup, and re-inserting an element restarts
   its CSS animations. On a cold load the circuit connects after the browser has
   already painted, so an ungated entrance visibly replays — the hero fades in a
   second time — which reads as the top of the page blinking.

   So the entrance is opted into by a class on <html>, which the framework never
   touches: it is present for the first paint and removed by js/intro.js the
   moment the circuit applies its first render. Markup inserted after that has
   nothing left to replay, and shows its finished state immediately.

   The ungated state is deliberately the FINISHED state (fully opaque, no
   transform), so losing the gate mid-flight snaps to the end rather than hiding
   the content.

   Infinite animations are not gated: replaying one is invisible, and gating it
   would stop it for the rest of the page's life.
   --------------------------------------------------------------------------- */

html.jl-intro .mkt-rise {
    animation: jl-rise .8s cubic-bezier(.22, 1, .36, 1) both;
}

.mkt-rise-1 { animation-delay: .05s; }
.mkt-rise-2 { animation-delay: .14s; }
.mkt-rise-3 { animation-delay: .23s; }
.mkt-rise-4 { animation-delay: .32s; }

/* ---------------------------------------------------------------------------
   Hero product mock — a faithful miniature of a real JustLinks page. Built in
   markup rather than shipped as a screenshot so it stays crisp at any density
   and never goes stale against the live product.
   ------------------------------------------------------------------------- */

.mkt-mock {
    position: relative;
    display: flex;
    justify-content: center;
    perspective: 1400px;
}

.mkt-mock-glow {
    position: absolute;
    inset: 8% 6% -6% 6%;
    background: radial-gradient(60% 70% at 50% 30%, rgba(0, 175, 240, .45), transparent 72%);
    filter: blur(50px);
    z-index: 0;
}

.mkt-phone {
    position: relative;
    z-index: 1;
    width: min(330px, 82%);
    border-radius: 42px;
    padding: 12px;
    background: linear-gradient(160deg, rgba(255, 255, 255, .16), rgba(255, 255, 255, .04));
    border: 1px solid rgba(255, 255, 255, .14);
    box-shadow: 0 50px 120px -40px rgba(0, 0, 0, .9), inset 0 1px 0 rgba(255, 255, 255, .18);
    transform: rotateX(6deg) rotateY(-8deg) rotateZ(1.5deg);
    transition: transform .6s cubic-bezier(.22, 1, .36, 1);
}

.mkt-mock:hover .mkt-phone {
    transform: rotateX(2deg) rotateY(-3deg) rotateZ(0deg);
}

.mkt-phone-screen {
    border-radius: 32px;
    background: #0e1013;
    padding: 1.4rem 1.1rem 1.1rem;
    overflow: hidden;
}

.mock-page-head {
    text-align: center;
    padding-bottom: 1.1rem;
}

.mock-avatar {
    width: 54px;
    height: 54px;
    margin: 0 auto .6rem;
    border-radius: 50%;
    display: grid;
    place-items: center;
    font-family: var(--jl-font-display);
    font-weight: 700;
    font-size: 1.3rem;
    color: #04141c;
    background: linear-gradient(130deg, var(--jl-sky), var(--jl-cyan));
    box-shadow: 0 8px 24px -8px rgba(0, 175, 240, .8);
}

.mock-name {
    font-family: var(--jl-font-display);
    font-weight: 600;
    font-size: .98rem;
    color: #fff;
}

.mock-sub {
    font-size: .72rem;
    color: var(--jl-ink-3);
    letter-spacing: .02em;
}

.mock-links {
    display: grid;
    gap: .5rem;
}

.mock-link {
    display: flex;
    align-items: center;
    gap: .7rem;
    padding: .7rem .8rem;
    border-radius: 12px;
    background: rgba(255, 255, 255, .05);
    border: 1px solid rgba(255, 255, 255, .07);
    font-size: .84rem;
    color: var(--jl-ink);
}

.mock-link i {
    width: 1.6rem;
    text-align: center;
    color: var(--jl-sky);
    font-size: .82rem;
}

.mock-link .mock-chev {
    margin-left: auto;
    color: var(--jl-ink-3);
    font-size: .7rem;
}

.mock-link--pinned {
    background: linear-gradient(120deg, rgba(127, 224, 255, .2), rgba(0, 175, 240, .12));
    border-color: rgba(127, 224, 255, .3);
}

.mock-made {
    margin-top: 1rem;
    text-align: center;
    font-size: .66rem;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--jl-ink-3);
}

.mkt-mock-chip {
    position: absolute;
    z-index: 2;
    padding: .55rem .95rem;
    border-radius: 999px;
    background: rgba(12, 14, 17, .82);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    border: 1px solid var(--jl-line-strong);
    font-size: .78rem;
    font-weight: 600;
    color: var(--jl-ink);
    box-shadow: 0 20px 50px -20px rgba(0, 0, 0, .9);
    white-space: nowrap;
}

.mkt-mock-chip i { color: var(--jl-cyan); margin-right: .35rem; }

.mkt-mock-chip--a { top: 12%; left: -2%; animation: jl-float 7s ease-in-out infinite; }
.mkt-mock-chip--b { bottom: 16%; right: -2%; animation: jl-float 8.5s ease-in-out infinite reverse; }

@keyframes jl-float {
    0%, 100% { transform: translateY(0); }
    50% { transform: translateY(-10px); }
}

@media (max-width: 991.98px) {
    .mkt-hero-inner { grid-template-columns: 1fr; }
    .mkt-hero-copy { max-width: none; }
    .mkt-mock { margin-top: 1rem; }
    .mkt-mock-chip--a { left: 2%; }
    .mkt-mock-chip--b { right: 2%; }
}

/* On a phone the chips sit on top of the mini page instead of beside it, so they are
   dropped rather than made to collide with the mock. */
@media (max-width: 575.98px) {
    .mkt-mock-chip { display: none; }
    .mkt-phone { transform: none; }
}

/* ---------------------------------------------------------------------------
   Editorial rows — numbered convictions, not feature cards.
   ------------------------------------------------------------------------- */

.mkt-rows {
    border-top: 1px solid var(--jl-line);
}

.mkt-row {
    display: grid;
    grid-template-columns: 5rem 1fr 1.1fr;
    gap: clamp(1.5rem, 5vw, 4rem);
    align-items: start;
    padding-block: clamp(2.25rem, 4vw, 3.25rem);
    border-bottom: 1px solid var(--jl-line);
}

.mkt-row-num {
    font-family: var(--jl-font-display);
    font-size: .82rem;
    font-weight: 600;
    letter-spacing: .18em;
    color: var(--jl-cyan);
    padding-top: .5rem;
}

.mkt-row h3 { font-size: clamp(1.6rem, 3.4vw, 2.6rem); }

.mkt-row p {
    margin: 0;
    padding-top: .45rem;
    color: var(--jl-ink-2);
    font-size: clamp(1rem, 1.4vw, 1.12rem);
    max-width: 42ch;
}

@media (max-width: 767.98px) {
    .mkt-row { grid-template-columns: 3rem 1fr; }
    .mkt-row p { grid-column: 2; padding-top: .25rem; }
}

/* ---------------------------------------------------------------------------
   Split feature sections with a product visual.
   ------------------------------------------------------------------------- */

.mkt-split {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: clamp(2.5rem, 7vw, 6rem);
    align-items: center;
}

.mkt-split--reverse .mkt-split-visual { order: -1; }

.mkt-split-copy .mkt-h2 { margin-bottom: 1.4rem; }

.mkt-split-copy p {
    color: var(--jl-ink-2);
    font-size: clamp(1rem, 1.4vw, 1.12rem);
    max-width: 42ch;
}

.mkt-split-list {
    margin: 2rem 0 0;
    padding: 0;
    list-style: none;
    display: grid;
    gap: .9rem;
}

.mkt-split-list li {
    display: flex;
    align-items: center;
    gap: .8rem;
    color: var(--jl-ink-2);
    font-size: .98rem;
}

.mkt-split-list i { color: var(--jl-cyan); }

.mkt-panel {
    position: relative;
    border-radius: var(--jl-radius);
    border: 1px solid var(--jl-line);
    background: linear-gradient(170deg, rgba(255, 255, 255, .055), rgba(255, 255, 255, .015));
    padding: clamp(1.4rem, 3vw, 2.2rem);
    box-shadow: 0 40px 90px -50px rgba(0, 0, 0, .9);
}

.mkt-panel-glow {
    position: absolute;
    inset: -20%;
    background: radial-gradient(45% 45% at 60% 30%, rgba(0, 175, 240, .22), transparent 70%);
    filter: blur(40px);
    z-index: -1;
}

/* Analytics visual */
.mkt-bars {
    display: flex;
    align-items: flex-end;
    gap: .65rem;
    height: 190px;
    padding-top: 1rem;
}

.mkt-bar {
    flex: 1;
    border-radius: 6px 6px 2px 2px;
    background: linear-gradient(180deg, var(--jl-sky), rgba(0, 175, 240, .25));
    position: relative;
    transform-origin: bottom;
}

/* Gated with the rest of the entrance — see the note above jl-rise. The ungated
   state is the grown bar, so the chart is never left empty. */
html.jl-intro .mkt-bar {
    animation: jl-grow 1s cubic-bezier(.22, 1, .36, 1) both;
}

.mkt-bar:nth-child(1) { height: 34%; animation-delay: .0s; }
.mkt-bar:nth-child(2) { height: 52%; animation-delay: .06s; }
.mkt-bar:nth-child(3) { height: 41%; animation-delay: .12s; }
.mkt-bar:nth-child(4) { height: 68%; animation-delay: .18s; }
.mkt-bar:nth-child(5) { height: 57%; animation-delay: .24s; }
.mkt-bar:nth-child(6) { height: 84%; animation-delay: .30s; }
.mkt-bar:nth-child(7) { height: 100%; animation-delay: .36s; background: linear-gradient(180deg, #fff, var(--jl-sky)); }

@keyframes jl-grow {
    from { transform: scaleY(.05); opacity: .3; }
    to { transform: scaleY(1); opacity: 1; }
}

.mkt-panel-stat {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1rem;
    margin-bottom: .25rem;
}

.mkt-panel-stat strong {
    font-family: var(--jl-font-display);
    font-size: clamp(2rem, 4vw, 2.8rem);
    letter-spacing: -.04em;
}

.mkt-panel-stat span { color: var(--jl-ink-3); font-size: .82rem; }

.mkt-panel-caption {
    display: flex;
    justify-content: space-between;
    margin-top: .9rem;
    font-size: .74rem;
    color: var(--jl-ink-3);
    letter-spacing: .04em;
}

/* Subdomain / QR visual */
.mkt-url {
    display: flex;
    align-items: center;
    gap: .75rem;
    padding: .9rem 1.1rem;
    border-radius: var(--jl-radius-sm);
    border: 1px solid var(--jl-line-strong);
    background: rgba(0, 0, 0, .35);
    font-family: var(--jl-font-display);
    font-size: clamp(.95rem, 2vw, 1.2rem);
    letter-spacing: -.02em;
}

.mkt-url .mkt-url-name {
    color: #fff;
    border-bottom: 1px dashed rgba(127, 224, 255, .6);
    padding-bottom: 1px;
}

.mkt-url .mkt-url-suffix { color: var(--jl-ink-3); }

.mkt-qr-row {
    display: flex;
    align-items: center;
    gap: 1.25rem;
    margin-top: 1.4rem;
}

.mkt-qr {
    width: 92px;
    height: 92px;
    flex: none;
    border-radius: 14px;
    background:
        conic-gradient(from 0deg, #fff 0 25%, transparent 0 50%, #fff 0 75%, transparent 0) 0 0 / 18px 18px,
        radial-gradient(circle at 30% 30%, #fff 0 6px, transparent 6px),
        radial-gradient(circle at 70% 30%, #fff 0 6px, transparent 6px),
        radial-gradient(circle at 30% 70%, #fff 0 6px, transparent 6px),
        #0e1013;
    border: 1px solid var(--jl-line-strong);
    box-shadow: inset 0 0 0 8px #0e1013, 0 20px 40px -24px rgba(0, 175, 240, .8);
}

.mkt-qr-copy strong { display: block; font-family: var(--jl-font-display); font-size: 1rem; }
.mkt-qr-copy span { color: var(--jl-ink-3); font-size: .84rem; }

/* SEO / search-result visual — a result card built from the page's own metadata, with the
   signals that make it render that way shown as chips beneath. */
.mkt-serp {
    border-radius: var(--jl-radius-sm);
    border: 1px solid var(--jl-line);
    background: rgba(0, 0, 0, .35);
    padding: 1.15rem 1.25rem;
}

.mkt-serp-source {
    display: flex;
    align-items: center;
    gap: .5rem;
    margin-bottom: .5rem;
    font-size: .82rem;
    color: var(--jl-ink-2);
}

.mkt-serp-source i {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.35rem;
    height: 1.35rem;
    flex: none;
    border-radius: 50%;
    background: linear-gradient(120deg, var(--jl-sky), var(--jl-cyan));
    color: #04141c;
    font-size: .58rem;
}

.mkt-serp-title {
    margin-bottom: .35rem;
    font-family: var(--jl-font-display);
    font-size: clamp(1.05rem, 2vw, 1.3rem);
    font-weight: 600;
    letter-spacing: -.02em;
    color: var(--jl-sky);
}

.mkt-serp-desc {
    color: var(--jl-ink-2);
    font-size: .92rem;
    line-height: 1.5;
    max-width: 46ch;
}

.mkt-serp-chips {
    display: flex;
    flex-wrap: wrap;
    gap: .5rem;
    margin-top: 1.4rem;
}

.mkt-serp-chips span {
    display: inline-flex;
    align-items: center;
    gap: .45rem;
    padding: .4rem .8rem;
    border-radius: 999px;
    border: 1px solid var(--jl-line);
    background: rgba(255, 255, 255, .04);
    font-size: .8rem;
    color: var(--jl-ink-2);
}

.mkt-serp-chips i { color: var(--jl-cyan); font-size: .75rem; }


@media (max-width: 991.98px) {
    .mkt-split { grid-template-columns: 1fr; }
    .mkt-split--reverse .mkt-split-visual { order: 0; }
}

/* ---------------------------------------------------------------------------
   Showcase shelf
   ------------------------------------------------------------------------- */

.mkt-section-head {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    justify-content: space-between;
    gap: 1.5rem;
    margin-bottom: clamp(2.5rem, 5vw, 4rem);
}

.mkt-section-head p {
    margin: 1rem 0 0;
    max-width: 48ch;
    color: var(--jl-ink-2);
    font-size: clamp(1rem, 1.4vw, 1.12rem);
}

.mkt-shelf {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
    gap: 1.1rem;
}

/* ---------------------------------------------------------------------------
   Closing call to action
   ------------------------------------------------------------------------- */

.mkt-cta {
    position: relative;
    text-align: center;
    padding-block: clamp(6rem, 12vw, 11rem);
    overflow: hidden;
}

.mkt-cta::before {
    content: "";
    position: absolute;
    inset: auto -10% -40% -10%;
    height: 80%;
    background: radial-gradient(50% 60% at 50% 100%, rgba(0, 175, 240, .3), transparent 72%);
    filter: blur(30px);
    pointer-events: none;
}

.mkt-cta .mkt-display { font-size: clamp(2.6rem, 8vw, 6.5rem); }

.mkt-cta-actions {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: .8rem;
    margin-top: 2.6rem;
}

.mkt-cta-note {
    margin-top: 1.4rem;
    font-size: .88rem;
    color: var(--jl-ink-3);
}

/* ---------------------------------------------------------------------------
   Pricing — dark editorial tiers
   ------------------------------------------------------------------------- */

.pricing-shell {
    padding-block: clamp(4rem, 8vw, 7rem) clamp(5rem, 9vw, 8rem);
}

.pricing-shell .pricing-head { text-align: center; margin-bottom: clamp(3rem, 6vw, 4.5rem); }

.pricing-shell .pricing-head .mkt-lede { margin-inline: auto; }

.pricing-interval-toggle {
    display: flex;
    width: fit-content;
    gap: .3rem;
    padding: .3rem;
    margin: 2rem auto 0;
    border: 1px solid var(--jl-line);
    border-radius: 999px;
    background: var(--jl-surface);
}

.pricing-interval-toggle .btn {
    padding: .55rem 1.35rem;
    border: 0;
    border-radius: 999px;
    background: transparent;
    color: var(--jl-ink-2);
    font-weight: 600;
}

.pricing-interval-toggle .btn-primary,
.pricing-interval-toggle .btn-primary:hover {
    background: var(--jl-ink);
    color: #07080a;
}

.pricing-interval-note { font-size: .88rem; color: var(--jl-ink-3); }

.pricing-card {
    position: relative;
    height: 100%;
    border: 1px solid var(--jl-line);
    border-radius: var(--jl-radius);
    background: linear-gradient(170deg, rgba(255, 255, 255, .05), rgba(255, 255, 255, .012));
    color: var(--jl-ink);
    box-shadow: 0 40px 90px -60px rgba(0, 0, 0, .9);
    transition: border-color .25s ease, transform .25s ease;
}

.pricing-card:hover { transform: translateY(-4px); border-color: var(--jl-line-strong); }

.pricing-card-featured {
    border-color: rgba(127, 224, 255, .45);
    background: linear-gradient(170deg, rgba(0, 175, 240, .16), rgba(255, 255, 255, .015));
    box-shadow: 0 50px 120px -50px rgba(0, 175, 240, .6);
}

.pricing-card-featured::before {
    content: "Most popular";
    position: absolute;
    top: 1.1rem;
    right: 1.1rem;
    padding: .3rem .75rem;
    border-radius: 999px;
    background: linear-gradient(120deg, var(--jl-sky), var(--jl-cyan));
    color: #04141c;
    font-size: .68rem;
    font-weight: 700;
    letter-spacing: .08em;
    text-transform: uppercase;
}

.pricing-card .card-body { padding: clamp(1.6rem, 3vw, 2.2rem); }

.pricing-tier-name {
    font-family: var(--jl-font-display);
    font-weight: 700;
    letter-spacing: -.03em;
    font-size: 1.5rem;
    margin: 0;
}

.pricing-tier-tagline { color: var(--jl-ink-3); font-size: .92rem; margin: .35rem 0 1.5rem; }

.pricing-price { display: flex; align-items: baseline; gap: .35rem; }

.pricing-price-amount {
    font-family: var(--jl-font-display);
    font-weight: 700;
    font-size: clamp(2.4rem, 5vw, 3.1rem);
    letter-spacing: -.045em;
    line-height: 1;
}

.pricing-price-period { color: var(--jl-ink-3); font-size: .95rem; }

.pricing-features { display: grid; gap: 0; margin: 0 0 1.75rem; }

.pricing-feature {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: .7rem 0;
    border-bottom: 1px solid var(--jl-line);
    font-size: .92rem;
}

.pricing-feature:first-child { border-top: 1px solid var(--jl-line); }

.pricing-feature dt { font-weight: 500; color: var(--jl-ink-2); }
.pricing-feature dd { margin: 0; font-weight: 600; color: var(--jl-ink); text-align: right; }

/* Qualitative subtext under a feature label - the exact URL a capability produces. */
.pricing-feature-note {
    display: block;
    margin-top: .15rem;
    font-size: .78rem;
    font-weight: 400;
    color: var(--jl-ink-3);
    line-height: 1.35;
}

/* Help affordance for a feature whose setup the owner performs (e.g. DNS for a custom
   domain). Native title tooltip, matching the rest of the app - no Bootstrap JS init. */
.pricing-feature-help {
    color: var(--jl-ink-3);
    cursor: help;
    font-size: .85rem;
}

/* Included / not-included markers in the feature table. Colour is the only signal, so the
   words live on in each icon's title and aria-label. Sized a touch above the row text so the
   glyph reads as a status mark rather than an inline character. */
.pricing-feature-yes,
.pricing-feature-no {
    font-size: 1.05rem;
    line-height: 1;
    vertical-align: -.08em;
}

.pricing-feature-yes { color: var(--jl-yes); }
.pricing-feature-no { color: var(--jl-no); }

.pricing-notes {
    max-width: 820px;
    margin: clamp(3.5rem, 7vw, 5rem) auto 0;
    padding-top: clamp(2.5rem, 5vw, 3.5rem);
    border-top: 1px solid var(--jl-line);
}

.pricing-notes h2 { color: var(--jl-ink); font-family: var(--jl-font-display); letter-spacing: -.02em; }
.pricing-notes p { color: var(--jl-ink-2); }
.pricing-notes code { color: var(--jl-sky); background: rgba(0, 175, 240, .1); padding: .1rem .4rem; border-radius: 6px; }

.pricing-shell .alert {
    border: 1px solid var(--jl-line-strong);
    border-radius: var(--jl-radius-sm);
    background: var(--jl-surface);
    color: var(--jl-ink);
}

.pricing-shell .alert-warning { border-color: rgba(255, 193, 7, .4); }
.pricing-shell .alert-success { border-color: rgba(0, 175, 240, .45); }

/* Plan-status card reuses Bootstrap .card */
.pricing-shell .card.bg-white {
    background: linear-gradient(170deg, rgba(255, 255, 255, .05), rgba(255, 255, 255, .015)) !important;
    border: 1px solid var(--jl-line) !important;
    color: var(--jl-ink);
    border-radius: var(--jl-radius);
}

.pricing-shell .text-muted { color: var(--jl-ink-3) !important; }

/* ---------------------------------------------------------------------------
   Public product page — dark canvas so the owner's coloured card reads as the
   one lit object on the page. Global because two layouts render this shell.
   ------------------------------------------------------------------------- */

.public-page-shell {
    display: flex;
    justify-content: center;
    align-items: flex-start;
    min-height: 100vh;
    padding: 2.5rem 1rem 3.5rem;
    background:
        radial-gradient(60% 45% at 50% 0%, rgba(0, 175, 240, .12), transparent 70%),
        var(--jl-canvas);
    color: var(--jl-ink);
    font-family: var(--jl-font-body);
}

.public-brand-banner {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: .5rem;
    margin-bottom: 1rem;
    padding: .7rem 1rem;
    background: rgba(255, 255, 255, .05);
    border: 1px solid var(--jl-line);
    border-radius: 999px;
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    color: var(--jl-ink);
    font-size: .95rem;
    font-weight: 600;
    letter-spacing: -.01em;
    text-decoration: none;
}

.public-brand-banner:hover,
.public-brand-banner:focus {
    color: #fff;
    border-color: var(--jl-line-strong);
    text-decoration: none;
}

.public-message-card {
    background: rgba(255, 255, 255, .04);
    border: 1px solid var(--jl-line);
    color: var(--jl-ink);
}

.public-message-card .alert-danger {
    background: rgba(220, 53, 69, .16);
    border: 1px solid rgba(220, 53, 69, .4);
    color: #ffd9dd;
}

/* The not-found / suspended card is platform chrome, not owner content, so its button
   joins the dark palette. Scoped to the card on purpose: the email-capture button on a
   live owner page is the owner's surface and keeps Bootstrap's default. */
.public-message-card .btn-primary {
    background: var(--jl-ink);
    border-color: var(--jl-ink);
    color: #07080a;
    border-radius: 999px;
    font-weight: 600;
}

.public-message-card .btn-primary:hover,
.public-message-card .btn-primary:focus-visible {
    background: #fff;
    border-color: #fff;
    color: #07080a;
}

/* ---------------------------------------------------------------------------
   Reduced motion
   ------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
    .mkt-rise,
    .mkt-bar,
    .mkt-mock-chip,
    .public-card.animated-gradient-card {
        animation: none !important;
    }

    .mkt-phone,
    .pricing-card,
    .mkt-shell .btn,
    .public-link-row {
        transition: none !important;
    }
}
