/* ============================================================================
   VISITOR OS - design system
   29 Sep 2026. Static mockups, Tailwind CDN for layout, this file for identity.

   WHAT THIS PRODUCT IS. A pixel identifies a share of the people already on a
   customer's website - name, postal address, often an email, a phone after the
   append - and hands them on to wherever that customer wants them: an email
   list, an ad audience, a direct-mail run, a call queue, their CRM. It is an
   identity and activation layer. It is deliberately NOT a CRM.

   THE BRAND NAME IS A PLACEHOLDER. Tom is naming it. "Visitor OS" appears in
   exactly two places - the .wordmark rule below and the <title> of each page -
   so renaming is a find-and-replace, not a redesign.

   TWO SKINS, ONE SYSTEM.
     Marketing pages (index, pricing) are dark and cinematic. That is the cue
     Suresh sent us in b2brocket.ai and it is the right register for selling.
     App pages are light and dense. People work in them for an hour at a time
     reading tables and charts; a dark app would be a style choice charged to
     the user. Both skins share the type, the accent and the geometry, so the
     product still reads as one thing.

   COLOUR, MEASURED NOT EYEBALLED. Every pair below was run through a WCAG
   contrast check before it was written down.
     #22d3ee on #070b14 ....... 10.89  headline accent on dark
     #06b6d4 on #070b14 ........ 8.11
     #070b14 on #22d3ee ....... 10.89  CYAN IS A FILL. Ink type sits on it.
     #ffffff on #06b6d4 ........ 2.43  <- FAILS. Never white type on cyan.
     #0e7490 on #ffffff ........ 5.36  text-weight cyan in the app
     #0891b2 on #ffffff ........ 3.68  icons, borders, large type only
     #5d6d84 on #ffffff ........ 5.27  secondary body copy (--t3), and
     #5d6d84 on #eef2f7 ........ 4.69  the darkest tint it sits on. It was
                                       #64748b, which is 4.34 on the #f1f5f9
                                       chip behind every .facts label - AA fail.
     #94a3b8 on #ffffff ........ 2.56  <- FAILS. Borders and icons only.
     #047857 / #b45309 / #e11d48 on #ffffff ... 5.48 / 5.02 / 4.70  semantics
     #be123c on #f1f5f9 / #fff1f2 .. 5.74 / 5.72  red text on a tint (--stop-ink);
                                       #e11d48 there is 4.29 / 4.28 and fails
     #7d8fab on #0e1626 ........ 5.50  quiet text on dark (--on-ink-3; was
                                       #6b7d99, 4.32)
   ==========================================================================*/

:root {
  /* dark skin */
  --ink:#070b14; --ink-2:#0e1626; --ink-3:#16203a;
  --on-ink:#ffffff; --on-ink-2:#a8b6cc; --on-ink-3:#7d8fab;
  --hair:rgba(255,255,255,.09); --hair-2:rgba(255,255,255,.16);

  /* light skin */
  --page:#f6f8fb; --card:#ffffff; --line:#e4e9f0; --line-2:#eef2f7;
  --t1:#0f172a; --t2:#475569; --t3:#5d6d84; --t4:#94a3b8;

  /* accent - cyan is a FILL colour, see the note above */
  --acc:#06b6d4; --acc-glow:#22d3ee; --acc-ink:#0e7490; --acc-deep:#155e75;
  --acc-wash:#ecfeff; --acc-line:#a5f3fc;

  /* semantics */
  --ok:#047857; --ok-fill:#10b981; --ok-wash:#ecfdf5;
  --warn:#b45309; --warn-fill:#f59e0b; --warn-wash:#fffbeb;
  --stop:#e11d48; --stop-fill:#f43f5e; --stop-wash:#fff1f2; --stop-ink:#be123c;
  --gold:#fbbf24;

  --r:.6rem; --r-lg:.9rem; --r-xl:1.25rem;
  --shadow:0 1px 2px rgba(15,23,42,.04), 0 4px 14px rgba(15,23,42,.05);
  --shadow-lg:0 8px 30px rgba(15,23,42,.10);
}

/* ---------- foundations ---------------------------------------------------*/
*{ -webkit-font-smoothing:antialiased; }
body{ font-family:'Inter',system-ui,sans-serif; color:var(--t1); background:var(--page); }
body.dark{ background:var(--ink); color:var(--on-ink); }
.display{ font-family:'Sora',system-ui,sans-serif; letter-spacing:-.025em; font-weight:700; }
.wrap{ max-width:80rem; margin:0 auto; padding:0 1.5rem; }
.wrap-tight{ max-width:64rem; margin:0 auto; padding:0 1.5rem; }
a{ color:inherit; }
::-webkit-scrollbar{ width:8px; height:8px; }
::-webkit-scrollbar-thumb{ background:#cbd5e1; border-radius:4px; }
.dark ::-webkit-scrollbar-thumb{ background:#243149; }
.mono{ font-family:ui-monospace,Menlo,monospace; font-variant-numeric:tabular-nums; }
.num{ font-variant-numeric:tabular-nums; }

/* ---------- the mark and wordmark -----------------------------------------
   Rename the product here. Nowhere else in the CSS names it.                */
.mark{ display:inline-flex; align-items:center; justify-content:center;
       width:1.9rem; height:1.9rem; border-radius:.5rem; flex:none;
       background:linear-gradient(140deg,var(--acc-glow),var(--acc));
       color:var(--ink); font-size:.8rem; }
.mark-lg{ width:2.6rem; height:2.6rem; border-radius:.7rem; font-size:1.05rem; }
.wordmark{ font-family:'Sora',sans-serif; font-weight:700; letter-spacing:-.03em; }
.wordmark::after{ content:'Visitor OS'; }

/* ============================================================================
   MARKETING SKIN
   ==========================================================================*/
.glow{ position:relative; overflow:hidden; }
.glow::before{ content:''; position:absolute; pointer-events:none; z-index:0;
  width:min(56rem,120vw); height:32rem; left:50%; top:-14rem; transform:translateX(-50%);
  background:radial-gradient(closest-side, rgba(34,211,238,.20), rgba(34,211,238,0) 72%); }
.glow > *{ position:relative; z-index:1; }

.grid-bg{ background-image:
   linear-gradient(to right, rgba(255,255,255,.045) 1px, transparent 1px),
   linear-gradient(to bottom, rgba(255,255,255,.045) 1px, transparent 1px);
   background-size:60px 60px; }
.fade-b{ -webkit-mask-image:linear-gradient(to bottom,#000 55%,transparent);
         mask-image:linear-gradient(to bottom,#000 55%,transparent); }

.nav{ position:sticky; top:0; z-index:50; background:rgba(7,11,20,.82);
      backdrop-filter:blur(14px); border-bottom:1px solid var(--hair); }
.nav a.lnk{ font-size:14.5px; font-weight:500; color:var(--on-ink-2); transition:color .12s; }
.nav a.lnk:hover{ color:#fff; }

.glass{ background:linear-gradient(180deg, rgba(255,255,255,.055), rgba(255,255,255,.02));
        border:1px solid var(--hair); border-radius:var(--r-xl);
        backdrop-filter:blur(8px); }
.glass-2{ background:var(--ink-2); border:1px solid var(--hair); border-radius:var(--r-xl); }

.eyebrow{ display:inline-flex; align-items:center; gap:.5rem; font-size:12px; font-weight:700;
          letter-spacing:.09em; text-transform:uppercase; color:var(--acc-glow); }
.eyebrow-pill{ display:inline-flex; align-items:center; gap:.55rem; padding:.35rem .8rem .35rem .45rem;
          border-radius:9999px; border:1px solid var(--hair-2); background:rgba(255,255,255,.04);
          font-size:12.5px; font-weight:600; color:var(--on-ink-2); }
.eyebrow-pill b{ color:var(--ink); background:var(--acc-glow); border-radius:9999px;
          padding:.1rem .5rem; font-size:11px; font-weight:800; letter-spacing:.02em; }

h1.hero{ font-size:clamp(2.6rem,6.2vw,4.6rem); line-height:1.02; letter-spacing:-.04em; }
.hero-sub{ font-size:clamp(1.05rem,1.7vw,1.3rem); line-height:1.55; color:var(--on-ink-2); }
.grad{ background:linear-gradient(100deg,var(--acc-glow) 10%,#7dd3fc 55%,#c4b5fd);
       -webkit-background-clip:text; background-clip:text; color:transparent; }

/* metric cards - the b2brocket cue: numbers, not adjectives */
.kpi{ padding:1.15rem 1.25rem; border-radius:var(--r-lg);
      background:linear-gradient(180deg, rgba(255,255,255,.06), rgba(255,255,255,.015));
      border:1px solid var(--hair); }
.kpi .k{ font-size:11.5px; font-weight:700; letter-spacing:.07em; text-transform:uppercase; color:var(--on-ink-3); }
.kpi .v{ font-family:'Sora',sans-serif; font-weight:700; font-size:1.9rem; letter-spacing:-.03em; margin-top:.3rem; }
.kpi .d{ font-size:12.5px; font-weight:600; color:var(--ok-fill); margin-top:.15rem; }

.logo-row{ display:flex; flex-wrap:wrap; align-items:center; gap:2.25rem;
           opacity:.7; filter:grayscale(1); font-weight:700; color:var(--on-ink-2); }

/* ---------- buttons (shared) ---------------------------------------------*/
.b{ display:inline-flex; align-items:center; justify-content:center; gap:.5rem; white-space:nowrap;
    height:2.55rem; padding:0 1.1rem; border-radius:var(--r); font-size:14px; font-weight:650;
    transition:transform .1s, box-shadow .14s, background .14s, border-color .14s; }
.b:active{ transform:translateY(1px); }
.b-lg{ height:3.1rem; padding:0 1.6rem; font-size:15.5px; border-radius:.7rem; }
.b-sm{ height:2.1rem; padding:0 .7rem; font-size:13px; }
.b-icon{ width:2.1rem; padding:0; }

/* cyan is a fill; the type on it is ink. Never white on cyan. */
.b-acc{ background:var(--acc-glow); color:var(--ink); font-weight:750;
        box-shadow:0 6px 22px -8px rgba(34,211,238,.75); }
.b-acc:hover{ background:#67e8f9; box-shadow:0 10px 30px -8px rgba(34,211,238,.9); }
.b-ink{ background:var(--t1); color:#fff; }
.b-ink:hover{ background:#1e293b; }
.b-ghost-d{ border:1px solid var(--hair-2); color:#fff; }
.b-ghost-d:hover{ background:rgba(255,255,255,.06); border-color:rgba(255,255,255,.3); }
.b-out{ border:1px solid var(--line); background:var(--card); color:var(--t1); box-shadow:var(--shadow); }
.b-out:hover{ border-color:#cbd5e1; background:#fbfdff; }
.b-quiet{ color:var(--t2); }
.b-quiet:hover{ background:#eef2f7; color:var(--t1); }

/* ---------- pricing -------------------------------------------------------*/
.plan{ border-radius:var(--r-xl); padding:1.6rem; border:1px solid var(--hair); background:var(--ink-2); }
.plan.feature{ border-color:rgba(34,211,238,.45);
   background:linear-gradient(180deg, rgba(34,211,238,.10), rgba(14,22,38,1) 45%);
   box-shadow:0 0 0 1px rgba(34,211,238,.18), 0 24px 60px -30px rgba(34,211,238,.55); }
.plan .price{ font-family:'Sora',sans-serif; font-weight:700; font-size:2.6rem; letter-spacing:-.04em; }
.plan li{ display:flex; gap:.6rem; font-size:14px; color:var(--on-ink-2); padding:.3rem 0; }
.plan li i{ color:var(--acc-glow); margin-top:.28rem; font-size:12px; }

/* ============================================================================
   APP SKIN
   ==========================================================================*/
.bar{ background:var(--ink); position:sticky; top:0; z-index:50; }
.tab{ position:relative; display:inline-flex; align-items:center; gap:.5rem; height:3.4rem;
      font-size:14px; font-weight:600; color:rgba(255,255,255,.62); white-space:nowrap; transition:color .12s; }
.tab:hover{ color:#fff; }
.tab.on{ color:#fff; font-weight:700; }
.tab.on::after, .gear.on::after{ content:''; position:absolute; left:0; right:0; bottom:0; height:3px;
      border-radius:2px 2px 0 0; background:var(--acc-glow); }
.tab .cnt, .navmenu .cnt{ font-size:10.5px; font-weight:800; padding:.05rem .4rem; border-radius:9999px;
      background:var(--acc-glow); color:var(--ink); }
/* The gear is Settings' tab, so it lights the same way when you are there.
   Display stays with the markup's Tailwind classes (hidden below lg). */
.gear{ position:relative; align-items:center; justify-content:center; min-width:1.75rem; height:3.4rem; font-size:13px;
      color:rgba(255,255,255,.55); transition:color .12s; }
.gear:hover, .gear.on{ color:#fff; }

/* Below lg the shell shows this menu instead of the tab row, which does not
   fit there (see _shell.js). The button names the page you are on. */
.navmenu{ position:relative; }
.navmenu > summary{ list-style:none; display:inline-flex; align-items:center; gap:.5rem; height:2.3rem;
      padding:0 .85rem; border-radius:9999px; cursor:pointer; white-space:nowrap;
      background:rgba(255,255,255,.08); border:1px solid rgba(255,255,255,.14);
      color:#fff; font-size:14px; font-weight:700; }
.navmenu > summary::-webkit-details-marker{ display:none; }
.navmenu[open] > summary{ background:rgba(255,255,255,.14); }
.navmenu-list{ position:absolute; left:0; top:calc(100% + .55rem); z-index:60; min-width:14.5rem; padding:.35rem;
      background:var(--ink-2); border:1px solid var(--hair-2); border-radius:var(--r-lg);
      box-shadow:0 18px 44px -12px rgba(0,0,0,.55); }
.navmenu-list a{ display:flex; align-items:center; gap:.7rem; padding:.62rem .75rem; border-radius:.5rem;
      font-size:14.5px; font-weight:600; color:rgba(255,255,255,.72); }
.navmenu-list a i{ width:1rem; text-align:center; font-size:12px; opacity:.7; }
.navmenu-list a .cnt{ margin-left:auto; }
.navmenu-list a:hover{ background:rgba(255,255,255,.06); color:#fff; }
.navmenu-list a.on{ background:rgba(34,211,238,.13); color:#fff; font-weight:700; }
.navmenu-list.right{ left:auto; right:0; }   /* the marketing header's menu sits at the far right */
.subbar{ background:var(--card); border-bottom:1px solid var(--line); }

.page-h{ font-family:'Sora',sans-serif; font-weight:700; letter-spacing:-.03em; font-size:1.6rem; }
.page-sub{ font-size:14px; color:var(--t3); margin-top:.15rem; }

.card{ background:var(--card); border:1px solid var(--line); border-radius:var(--r-lg); box-shadow:var(--shadow); }
.card-h{ padding:.95rem 1.15rem; border-bottom:1px solid var(--line-2); display:flex; flex-wrap:wrap;
         align-items:center; justify-content:space-between; gap:.6rem 1rem; }  /* actions drop below the title on a phone */
.card-t{ font-weight:700; font-size:14.5px; letter-spacing:-.01em; }
.card-note{ font-size:12.5px; color:var(--t3); }
/* Something switched off or kept out - a paused destination, a suppressed
   record. It goes quiet with a tint, never with opacity, which took its text
   below AA (3.3:1) when it was faded instead. */
.card.quiet{ background:#fafcfe; box-shadow:none; }

.stat{ background:var(--card); border:1px solid var(--line); border-radius:var(--r-lg); padding:1rem 1.1rem; box-shadow:var(--shadow); }
.stat .k{ font-size:11.5px; font-weight:700; letter-spacing:.06em; text-transform:uppercase; color:var(--t3); }
.stat .v{ font-family:'Sora',sans-serif; font-weight:700; font-size:1.75rem; letter-spacing:-.03em; margin-top:.25rem; }
.stat .d{ font-size:12.5px; color:var(--t3); margin-top:.1rem; }

/* pills - reachability, status, source */
.pill{ display:inline-flex; align-items:center; gap:.35rem; padding:.15rem .55rem; border-radius:9999px;
       font-size:11.5px; font-weight:700; letter-spacing:.01em; white-space:nowrap; }
.pill i{ font-size:9.5px; }
.p-ok{ background:var(--ok-wash); color:var(--ok); }
.p-acc{ background:var(--acc-wash); color:var(--acc-ink); }
.p-warn{ background:var(--warn-wash); color:var(--warn); }
.p-stop{ background:var(--stop-wash); color:var(--stop-ink); }
.p-mute{ background:#f1f5f9; color:var(--t2); }
.p-ink{ background:var(--t1); color:#fff; }

/* tables */
table.t{ width:100%; border-collapse:collapse; }
table.t th{ text-align:left; font-size:11.5px; font-weight:700; letter-spacing:.055em;
       text-transform:uppercase; color:var(--t3); padding:.6rem 1.15rem; background:#fafcfe;
       border-bottom:1px solid var(--line); white-space:nowrap; }
table.t td{ padding:.8rem 1.15rem; border-bottom:1px solid var(--line-2); font-size:14px; vertical-align:middle; }
table.t tbody tr:hover{ background:#fafcff; }
table.t tbody tr:last-child td{ border-bottom:0; }
@media (max-width:639px){ table.t th, table.t td{ padding-left:.75rem; padding-right:.75rem; } }  /* a phone has no room for desktop gutters */

/* forms */
.inp, .sel{ height:2.4rem; padding:0 .7rem; border:1px solid var(--line); border-radius:var(--r);
       font-size:14px; background:var(--card); color:var(--t1); width:100%; max-width:100%; }
.inp:focus, .sel:focus{ outline:2px solid var(--acc-line); outline-offset:-1px; border-color:var(--acc); }
.lbl{ font-size:12px; font-weight:700; color:var(--t2); letter-spacing:.02em; display:block; margin-bottom:.3rem; }
.sw{ position:relative; width:2.35rem; height:1.3rem; border-radius:9999px; background:#cbd5e1; flex:none; transition:background .14s; }
.sw::after{ content:''; position:absolute; top:.15rem; left:.15rem; width:1rem; height:1rem;
       border-radius:9999px; background:#fff; box-shadow:0 1px 3px rgba(0,0,0,.25); transition:transform .14s; }
.sw.on{ background:var(--acc); } .sw.on::after{ transform:translateX(1.05rem); }

/* the compliance layer - deliberately unmissable, never dismissible.
   This exists because M1 lost real-time delivery and phone numbers after a
   dealer rang two consumers who were still on the site. See the README.      */
.rule{ border-left:3px solid var(--warn-fill); background:var(--warn-wash);
       border-radius:0 var(--r) var(--r) 0; padding:.75rem .95rem; font-size:13px; color:#78350f; }
.rule b{ color:#78350f; }
.say{ background:var(--acc-wash); border:1px solid var(--acc-line); border-radius:var(--r);
      padding:.7rem .9rem; font-size:14px; color:#083344; line-height:1.5; }
.fence{ border:1px dashed #cbd5e1; border-radius:var(--r); background:#fafcfe; }
.fence > summary{ cursor:pointer; padding:.55rem .8rem; font-size:12.5px; font-weight:650; color:var(--t2); list-style:none; }
.fence > summary::-webkit-details-marker{ display:none; }
.fence[open] > summary{ border-bottom:1px dashed #cbd5e1; }

/* slide-out record panel: a native <dialog> opened with showModal(). The browser
   moves focus into it, keeps Tab inside, closes it on Escape and hands focus back
   to the button that opened it; ::backdrop dims the page. The first rule undoes a
   dialog's default centred box. The page behind stays put while a record is open. */
.panel{ position:fixed; inset:0 0 0 auto; margin:0; padding:0; border:0; width:min(34rem,100%);
        max-width:100%; height:100%; max-height:100%; background:var(--card); color:inherit;
        box-shadow:-12px 0 40px rgba(15,23,42,.18); flex-direction:column; }
.panel[open]{ display:flex; }
.panel::backdrop{ background:rgba(15,23,42,.45); }
body:has(.panel[open]){ overflow:hidden; }

/* destination / integration tiles */
.tile{ background:var(--card); border:1px solid var(--line); border-radius:var(--r-lg); padding:1rem;
       box-shadow:var(--shadow); transition:border-color .14s, box-shadow .14s, transform .1s; }
.tile:hover{ border-color:#cbd5e1; box-shadow:var(--shadow-lg); transform:translateY(-1px); }
.tile.live{ border-color:var(--acc-line); background:linear-gradient(180deg,var(--acc-wash),var(--card) 60%); }
.logo-sq{ width:2.4rem; height:2.4rem; border-radius:.55rem; display:inline-flex; align-items:center;
       justify-content:center; font-size:1rem; color:#fff; flex:none; }

/* ---------- compact facts, instead of prose -------------------------------
   THE RULE FOR APP PAGES: an app is scanned, not read. A number with a label
   beats a sentence every time. Where an earlier draft wrote "68 records are
   held and none have reached your CRM - of the 589 routed there this month,
   31 of them from last night alone", the page now says:
       <div class="facts"><span>Held <b>68</b></span><span>Since <b>Sun 06:12</b></span></div>
   Same information, read in a glance instead of a paragraph. Reserve sentences
   for the two places they are the product: the opening line on a record, and
   the compliance rule.                                                       */
/* A chip keeps to one line wherever it fits on one (the row wraps first); only
   a chip wider than the whole row, on a narrow phone, breaks inside itself.
   It used to be nowrap, which pushed those chips past the edge of the page. */
.facts{ display:flex; flex-wrap:wrap; gap:.3rem .4rem; }
.facts > span{ display:inline-flex; align-items:baseline; gap:.3rem; min-width:0;
       font-size:12.5px; padding:.12rem .5rem; border-radius:.4rem;
       background:#f1f5f9; color:var(--t3); }
.facts b{ font-weight:700; color:var(--t1); font-variant-numeric:tabular-nums; }
.facts .bad b{ color:var(--stop-ink); }
.facts .good b{ color:var(--ok); }

/* the long explanation, available but never in the way. Hover or tap. */
.info{ display:inline-grid; place-items:center; width:.95rem; height:.95rem; flex:none;
       border-radius:9999px; background:#e2e8f0; color:var(--t2); font-size:8.5px;
       font-weight:800; cursor:help; vertical-align:middle; }
.info:hover{ background:var(--acc-glow); color:var(--ink); }

/* empty states */
.empty{ text-align:center; padding:3rem 1.5rem; }
.empty i{ font-size:1.6rem; color:var(--t4); }
.empty h4{ font-weight:700; margin-top:.7rem; font-size:15px; }
.empty p{ font-size:13.5px; color:var(--t3); margin-top:.25rem; max-width:26rem; margin-inline:auto; }

/* the navy strip. Never at the top of a page - it closes one. */
.strip{ background:var(--ink); border-radius:var(--r-xl); color:#fff; }

/* step rail for onboarding */
.step{ display:flex; gap:.9rem; }
.step .dot{ width:1.6rem; height:1.6rem; border-radius:9999px; flex:none; display:inline-flex;
       align-items:center; justify-content:center; font-size:12px; font-weight:800;
       background:#e2e8f0; color:var(--t2); }
.step.done .dot{ background:var(--ok-fill); color:#fff; }
.step.now .dot{ background:var(--acc); color:var(--ink); box-shadow:0 0 0 4px var(--acc-wash); }

@media print{
  .no-print{ display:none !important; }
  body{ background:#fff; }
  .card{ box-shadow:none; border-color:#cbd5e1; break-inside:avoid; }
}
