/* Synapse app — shared styles for the clickable browser prototype.
   White VisionOS surfaces, brand orange accent, EB Garamond + Lato (Google
   Fonts, loaded per-page <link>). These mirror the real @synapse/ui screens
   so the flow can be clicked through. */
:root {
  --brand: #121212;          /* crypt.ee monochrome — near-black accents, no terracotta */
  --brand-dim: #000000;
  --brand-deep: #121212;
  --brand-text: #363636;
  --bg: #f5f5f5;
  --surface: #ffffff;
  --ink: #1e1e1e;
  --ink-muted: rgba(54,54,54,0.62);
  --ink-dim: rgba(54,54,54,0.42);
  --border: rgba(20,20,20,0.10);
  --glass: rgba(255,255,255,0.72);
  --success: #2e7d4f;
  --gold: #9c7a1e;
  --radius: 10px;
  --radius-sm: 8px;
  --f-sans: 'Josefin Sans', system-ui, sans-serif;
  --f-serif: 'Josefin Sans', system-ui, sans-serif;
  --f-accent: 'Josefin Sans', system-ui, sans-serif; /* all-caps eyebrows/kickers/chips:
                                                Lato 700, uppercase, +0.14em — a recipe, not a face */
  --brand-text: #363636; /* terracotta for small text on --bg — 5.3:1, AA */
}
* { box-sizing: border-box; margin: 0; padding: 0; }
body {
  font-family: var(--f-sans);
  font-size: 15px;
  line-height: 1.6;
  background: var(--bg);
  color: var(--ink);
  -webkit-font-smoothing: antialiased;
}
a { color: inherit; text-decoration: none; }
::-webkit-scrollbar { width: 8px; }
::-webkit-scrollbar-thumb { background: rgba(0,0,0,0.12); border-radius: 4px; }

/* App top bar */
.appbar {
  position: sticky; top: 0; z-index: 50;
  display: flex; align-items: center; gap: 22px;
  padding: 14px 22px;
  background: rgba(245,245,245,0.82);
  backdrop-filter: blur(20px) saturate(1.4);
  -webkit-backdrop-filter: blur(20px) saturate(1.4);
  border-bottom: 1px solid var(--border);
}
.appbar .brand {
  display: flex; align-items: center; gap: 9px; font-weight: 700;
  letter-spacing: 0.34em; text-transform: uppercase; font-size: 12px;   /* crypt.ee wordmark — expanded at top */
  transition: letter-spacing 0.5s cubic-bezier(.22,1,.36,1);
}
.appbar.scrolled .brand { letter-spacing: 0.12em; }   /* contracts on scroll */
@media (prefers-reduced-motion: reduce){ .appbar .brand { transition: none; letter-spacing: 0.2em; } }
.appbar .brand svg { width: 20px; height: 29px; }   /* real mark is 64×92 — keep its aspect */
.appbar nav { display: flex; gap: 4px; margin-left: 8px; }
.appbar nav a {
  font-size: 13px; color: var(--ink-muted); padding: 7px 13px; border-radius: 100px;
  transition: all .2s;
}
.appbar nav a:hover { color: var(--ink); background: rgba(0,0,0,0.04); }
.appbar nav a.active { color: var(--brand); background: rgba(54,54,54,0.08); }
.appbar .spacer { flex: 1; }
.appbar .home { font-size: 12.5px; color: var(--ink-dim); }
.appbar .home:hover { color: var(--ink); }

.wrap { max-width: none; margin: 0 auto; padding: 28px 34px 80px; }
.phone { max-width: 440px; }

/* Headings */
.h1 { font-family: var(--f-serif); font-weight: 500; font-size: 37px; line-height: 1.12; letter-spacing: -0.01em; }
.eyebrow { font-family: var(--f-accent); font-size: 11.5px; font-weight: 700; letter-spacing: 0.14em; line-height: 1.2; text-transform: uppercase; color: var(--brand-text); }
.muted { color: var(--ink-muted); }
.dim { color: var(--ink-dim); }

/* Glass card — frosted: translucent fill, blur, thin luminous rim, top highlight.
   Same glass language as the Toju chat, tuned for light backgrounds. */
.card {
  background: linear-gradient(135deg, rgba(255,255,255,0.78), rgba(255,255,255,0.55));
  backdrop-filter: blur(24px) saturate(1.5);
  -webkit-backdrop-filter: blur(24px) saturate(1.5);
  border: 1px solid rgba(255,255,255,0.75);
  border-radius: var(--radius);
  box-shadow: 0 16px 40px rgba(20,26,38,0.09), inset 0 1px 0 rgba(255,255,255,0.9);
}

/* Buttons */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  font-family: var(--f-sans); font-weight: 700; font-size: 14px;
  padding: 13px 22px; border-radius: 100px; border: none; cursor: pointer;
  transition: all .25s;
}
.btn-primary { background: var(--brand); color: #fff; box-shadow: 0 0 30px rgba(54,54,54,0.28); }
.btn-primary:hover { background: var(--brand-dim); transform: translateY(-1px); }
.btn-ghost { background: rgba(0,0,0,0.04); color: var(--ink); }
.btn-ghost:hover { background: rgba(0,0,0,0.07); }
.btn-block { width: 100%; }

/* ── Logo page-load animation ─────────────────────────────────────────────
   A brief splash: the Synapse mark's bars build in sequence (like a synapse
   firing), then the veil lifts to reveal the page. Pure CSS so it paints
   instantly with no flash-of-content and needs no JS. The overlay auto-clears
   even if scripts fail; reduced-motion skips it entirely. */
#syn-load {
  position: fixed; inset: 0; z-index: 9999;
  display: flex; align-items: center; justify-content: center;
  background: var(--bg);
  animation: synLoadOut .55s ease .82s forwards;
}
#syn-load .syn-load-mark { width: 46px; height: 66px; color: #15171a; }
#syn-load rect {
  opacity: 0; transform-box: fill-box; transform-origin: center;
  animation: synBar .5s cubic-bezier(.22,1,.36,1) forwards;
}
#syn-load rect:nth-child(1) { animation-delay: .02s; }
#syn-load rect:nth-child(2) { animation-delay: .06s; }
#syn-load rect:nth-child(3) { animation-delay: .10s; }
#syn-load rect:nth-child(4) { animation-delay: .14s; }
#syn-load rect:nth-child(5) { animation-delay: .18s; }
#syn-load rect:nth-child(6) { animation-delay: .22s; }
#syn-load rect:nth-child(7) { animation-delay: .26s; }
#syn-load rect:nth-child(8) { animation-delay: .30s; }
@keyframes synBar { from { opacity: 0; transform: scale(.35) translateY(4px); } to { opacity: 1; transform: none; } }
@keyframes synLoadOut { to { opacity: 0; visibility: hidden; } }
@media (prefers-reduced-motion: reduce){ #syn-load { display: none; } }

/* ── Proximity opt-in ─────────────────────────────────────────────────────
   Location is the most sensitive permission we ask for, so the control says
   plainly what it does, what it will not do, and how to stop it. */
.prox-card { display: flex; align-items: flex-start; gap: 13px; padding: 15px 17px; margin-bottom: 16px;
  border-radius: var(--radius); border: 1px solid var(--border);
  background: linear-gradient(135deg, rgba(255,255,255,0.78), rgba(255,255,255,0.55));
  backdrop-filter: blur(20px) saturate(1.4); }
.prox-card.on { border-color: rgba(46,125,79,0.35); background: rgba(46,125,79,0.05); }
.prox-pin { flex: none; width: 32px; height: 32px; border-radius: 50%; display: flex; align-items: center;
  justify-content: center; background: rgba(20,20,20,0.06); }
.prox-pin i { width: 9px; height: 9px; border-radius: 50%; background: var(--ink-dim); }
.prox-card.on .prox-pin { background: rgba(46,125,79,0.14); }
.prox-card.on .prox-pin i { background: var(--success); animation: proxPulse 2.4s ease-in-out infinite; }
@keyframes proxPulse { 0%,100% { box-shadow: 0 0 0 0 rgba(46,125,79,0.45); } 50% { box-shadow: 0 0 0 6px rgba(46,125,79,0); } }
@media (prefers-reduced-motion: reduce) { .prox-card.on .prox-pin i { animation: none; } }
.prox-txt { flex: 1; min-width: 0; }
.prox-txt b { display: block; font-size: 14px; font-weight: 700; }
.prox-txt span { display: block; font-size: 13px; line-height: 1.6; color: var(--ink-muted); margin-top: 3px; }
.prox-txt .prox-note { font-size: 12px; color: var(--ink-dim); margin-top: 7px; font-style: italic; }
.prox-btn { flex: none; align-self: center; font: 600 12.5px var(--f-sans); border-radius: 100px;
  padding: 9px 16px; cursor: pointer; border: 1px solid var(--border);
  background: #121212; color: #f5f5f5; transition: opacity .2s, transform .15s; }
.prox-card.on .prox-btn { background: none; color: var(--ink-muted); }
.prox-btn:hover:not(:disabled) { transform: translateY(-1px); }
.prox-btn:disabled { opacity: .5; cursor: not-allowed; transform: none; }

/* ── Auth chip (appbar) ───────────────────────────────────────────────────
   Painted by auth.js into any <span data-auth-slot>. Signed out shows a quiet
   link; signed in shows initials + sign out. No email is ever rendered in the
   bar itself — it sits in the title attribute only. */
.auth-chip { display: inline-flex; align-items: center; gap: 9px; }
.auth-av { width: 27px; height: 27px; border-radius: 50%; background: #121212; color: #f5f5f5;
  font: 700 11px var(--f-sans); display: flex; align-items: center; justify-content: center; flex: none; }
.auth-out { background: none; border: none; cursor: pointer; font: 600 12.5px var(--f-sans);
  color: var(--ink-dim); padding: 0; }
.auth-out:hover { color: var(--ink); }
.auth-in { font-size: 12.5px; font-weight: 600; color: var(--ink-muted); }
.auth-in:hover { color: var(--ink); }

/* ── Map pins ──────────────────────────────────────────────────────────────
   A price pill on a pointer tail, so the pin points AT the property instead of
   floating beside it. The ring keeps it readable over any tile, and a verified
   dot carries the same trust signal the cards do. Josefin Sans has no ₦ glyph,
   so the pin explicitly falls back to a face that does — otherwise ₦ renders
   as a mangled N and prices become unreadable at pin size. */
.pin-wrap { position: relative; width: 0 !important; height: 0 !important; overflow: visible; }
.price-pin {
  position: absolute; left: 0; bottom: 9px; transform: translateX(-50%);
  display: inline-flex; align-items: center; gap: 5px;
  background: #121212; color: #fff; white-space: nowrap;
  font: 700 11.5px/1 'Josefin Sans', 'Segoe UI', system-ui, sans-serif;
  padding: 6px 10px; border-radius: 100px;
  border: 1.5px solid #fff;
  box-shadow: 0 5px 14px rgba(20,20,20,0.38);
  transition: transform .16s cubic-bezier(.22,1,.36,1), background .16s;
}
.price-pin .pv { font-variant-numeric: lining-nums; font-feature-settings: "lnum" 1; }
/* the verified dot */
.price-pin.ok::before {
  content: ''; width: 6px; height: 6px; border-radius: 50%;
  background: #5fd08a; flex: none;
}
.price-pin.dim { background: #7a7a7a; }
.pin-tail {
  position: absolute; left: 0; bottom: 1px; transform: translateX(-50%);
  width: 0; height: 0; border-left: 5px solid transparent; border-right: 5px solid transparent;
  border-top: 9px solid #fff;
  filter: drop-shadow(0 2px 3px rgba(20,20,20,0.3));
}
.pin-wrap:hover { z-index: 1000; }
.pin-wrap:hover .price-pin { transform: translateX(-50%) translateY(-3px); background: #000; }
@media (prefers-reduced-motion: reduce) { .price-pin { transition: none; } }

/* Unified line-icons (app/icons.js). Size to the current font unless a
   data-size is given; inherit colour via currentColor. */
.syn-i { width: 1em; height: 1em; display: inline-block; vertical-align: -0.14em; flex: none; }
[data-icon].has-icon { display: inline-flex; align-items: center; justify-content: center; line-height: 0; }
/* icons inside small uppercase section labels read better a step larger */
.lbl .syn-i, .eyebrow .syn-i { width: 14px; height: 14px; vertical-align: -3px; }
.chip .syn-i { width: 12px; height: 12px; }
.appbar nav a { display: inline-flex; align-items: center; gap: 7px; }
.appbar nav .nav-i { width: 15px; height: 15px; opacity: .75; }
.appbar nav a.active .nav-i, .appbar nav a:hover .nav-i { opacity: 1; }

/* ── Interaction layer (21st.dev-grade polish) ───────────────────────────────
   One consistent set of interactive states across every control, so the app
   feels crafted rather than assembled. Three rules:
     1. Keyboard focus is ALWAYS visible (:focus-visible only — never punishes
        mouse users with a ring, never leaves keyboard users lost). Drawn with
        box-shadow so it hugs rounded corners and is never clipped by overflow.
     2. Hover lifts, press settles — same easing everywhere.
     3. Disabled and busy states look unmistakably inert.
   This intentionally overrides the scattered `outline: none` rules. */
:root { --ring: rgba(18,18,18,0.62); --ring-offset: var(--bg); }

/* `!important` is deliberate: components set their own box-shadow (buttons,
   cards, chips), and `:where()` carries zero specificity — without it the ring
   silently loses and keyboard users get nothing. Focus visibility is a
   guarantee, not a suggestion. */
:where(a, button, input, select, textarea, summary, [tabindex], .listing, .pcard, .hist-row, .pal, .tile):focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px var(--ring-offset), 0 0 0 4px var(--ring) !important;
  position: relative; z-index: 2;
}
/* press feedback — hover lifts, active settles */
:where(.btn, .btn-primary, .btn-ghost):not(:disabled) { transition: transform .16s cubic-bezier(.22,1,.36,1), background .2s, box-shadow .2s, opacity .2s; }
:where(.btn, .btn-primary, .btn-ghost):not(:disabled):active { transform: translateY(0) scale(.985); }

/* inert states read as inert */
:where(button, .btn, input, select, textarea):disabled,
:where(button, .btn)[aria-disabled="true"] {
  opacity: .55; cursor: not-allowed; transform: none !important; box-shadow: none;
}
:where(button, .btn):disabled:hover { transform: none; }

/* a control mid-flight says so */
[data-busy="true"] { cursor: progress; opacity: .75; }

@media (prefers-reduced-motion: reduce) {
  :where(.btn, .btn-primary, .btn-ghost) { transition: background .2s, box-shadow .2s; }
  :where(.btn, .btn-primary, .btn-ghost):not(:disabled):active { transform: none; }
}

/* Error surface — a sentence under the control that failed. Names the cause,
   never blames the user. (Page-level failures are shown as an empty state
   instead: nothing found is shown as nothing, never as placeholder content.) */
.inline-err { margin-top: 10px; font-size: 12.5px; line-height: 1.55; color: #7a271a; }

/* Feedback toast — shared. Speaks to the user; auto-dismisses. */
#synToast {
  position: fixed; left: 50%; bottom: 26px; transform: translate(-50%, 14px);
  z-index: 200; max-width: min(440px, calc(100vw - 32px));
  background: #121212; color: #f5f5f5;
  font-family: var(--f-sans); font-size: 13.5px; font-weight: 500; line-height: 1.5;
  padding: 13px 18px; border-radius: 12px;
  box-shadow: 0 18px 44px rgba(20,20,20,0.32);
  opacity: 0; pointer-events: none; transition: opacity .28s, transform .28s cubic-bezier(.22,1,.36,1);
}
#synToast.show { opacity: 1; transform: translate(-50%, 0); }
#synToast.err { background: #7a271a; }
@media (prefers-reduced-motion: reduce){ #synToast { transition: opacity .2s; transform: translate(-50%,0); } }

/* Trust chip */
.chip {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 11px; font-weight: 700; padding: 4px 10px; border-radius: 100px;
}
.chip-pass { background: rgba(46,125,79,0.1); color: var(--success); border: 1px solid rgba(46,125,79,0.2); }
.chip-pending { background: rgba(176,125,43,0.1); color: #a8742b; border: 1px solid rgba(176,125,43,0.2); }
.chip-gold { background: rgba(156,122,30,0.1); color: var(--gold); border: 1px solid rgba(156,122,30,0.3); }

/* ── No-backdrop-filter fallback ─────────────────────────────────────────
   Older Android WebViews (mid-range devices — our median) render the glass
   surfaces as bare transparency: unreadable text over the page behind it.
   When blur isn't available, give those surfaces a solid near-white fill.
   The `or -webkit-` clause keeps iOS Safari ≤17 (prefixed-only support) on
   real glass. Selectors are deliberately over-specified (.card.card,
   .msg.toju .bubble) so this out-ranks the page-level <style> blocks that
   re-skin the same surfaces after app.css loads — without !important. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .card.card,
  .appbar.appbar,
  .chatbox.chatbox,
  .msg.toju .bubble {
    background: rgba(255,255,255,0.92);
  }
}

/* ── Typing should not be framed ────────────────────────────────────────
   The ring above is right for buttons, links and cards, which only show it
   on keyboard navigation. Text fields are different: browsers treat them as
   always :focus-visible, so the 4px halo appears the moment you click into
   one and stays there the whole time you type — a rectangle drawn around
   your own sentence. Text inputs and textareas get a quiet border shift
   instead; the caret already says where focus is. Everything else keeps the
   ring, so keyboard accessibility is untouched. */
input[type="text"]:focus,
input[type="email"]:focus,
input[type="password"]:focus,
input[type="search"]:focus,
input[type="url"]:focus,
input[type="tel"]:focus,
input[type="number"]:focus,
input:not([type]):focus,
textarea:focus,
input[type="text"]:focus-visible,
input[type="email"]:focus-visible,
input[type="password"]:focus-visible,
input[type="search"]:focus-visible,
input[type="url"]:focus-visible,
input[type="tel"]:focus-visible,
input[type="number"]:focus-visible,
input:not([type]):focus-visible,
textarea:focus-visible {
  box-shadow: none !important;
  outline: none !important;
  border-color: rgba(20, 20, 20, 0.34);
}
