/* vovaauer.com — page skeleton + cards.
 *
 * Two layers: #bliss is the wallpaper (bottom of this file), #overlay is a
 * full-viewport scroller that centres the card grid over it. No menu.
 */

:root {
  --bg: #0b0b0e;
  --fg: #e8e8ea;
  --muted: #9a9aa2;
  --line: rgba(255, 255, 255, 0.10);
  --card-bg-fallback: rgba(15, 15, 18, 0.85);
  --accent: #c9c9d4;
  --radius: 14px;
  --pad: 1.25rem;
  --maxw: 76rem;
  --font: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

*, *::before, *::after { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  min-height: 100%;
  background: var(--bg);
  color: var(--fg);
  font: 16px/1.55 var(--font);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

a { color: var(--fg); text-decoration: underline; text-underline-offset: 3px; text-decoration-color: var(--line); }
a:hover { text-decoration-color: currentColor; }

h1, h2, h3 { margin: 0 0 .35em; line-height: 1.2; letter-spacing: -0.01em; }
h1 { font-size: 1.6rem; }
h2 { font-size: 1.1rem; }

p { margin: 0 0 .8em; }
.muted { color: var(--muted); }

/* ── overlay grid ──────────────────────────────────────────────────── */
#overlay {
  position: fixed;
  inset: 0;
  z-index: 1;
  display: grid;
  place-items: center;
  padding: 1.5rem;
  overflow: auto;
}

/* Header row, then 3 columns side-by-side: payments | contacts | security.
 *
 *   ┌──────────────────────────────────────────┐
 *   │             header (hdr)                 │   ← logo + name + email
 *   ├──────────┬─────────────────┬─────────────┤
 *   │ payments │    contacts     │  security   │
 *   │   chat   │     (soc)       │   games     │
 *   │  (left)  │                 │   (other)   │
 *   └──────────┴─────────────────┴─────────────┘
 *
 * Payments and Chat form one independent left stack, Security and Games one
 * right stack, so the taller Contacts card cannot create gaps between them. */
.grid {
  display: grid;
  gap: 1rem;
  width: 100%;
  max-width: var(--maxw);
  grid-template-columns: 1fr;
  grid-template-areas:
    "hdr"
    "soc"
    "left"
    "other";
}
@media (min-width: 860px) {
  .grid {
    grid-template-columns: 1fr 1.3fr 1fr;
    grid-template-areas:
      "hdr hdr hdr"
      "left soc other";
    align-items: start;
  }
}
.is-header  { grid-area: hdr; }
.is-socials { grid-area: soc; }
.stack-left  { grid-area: left; }
.stack-right { grid-area: other; }
.stack-left,
.stack-right {
  display: grid;
  gap: 1rem;
  align-content: start;
}

/* Header card: square SVG mark on the left, name+email on the right.
 * Card padding stays at the default var(--pad) so the layout matches before.
 * overflow:hidden on the card + overflow:visible on the SVG = the V/A strokes
 * extend out of the SVG's small box, through the padding, and get clipped at
 * the card's actual border. */
.is-header {
  display: flex;
  align-items: center;
  gap: 1.1rem;
  width: max-content;
  max-width: 100%;
  justify-self: center;
  overflow: hidden;
}
.is-header .logo {
  width: 5rem;
  height: 5rem;
  flex: 0 0 auto;
  display: block;
  color: #ffffff;       /* feeds the stroke="currentColor" on the path */
  overflow: visible;    /* let the path extensions render past the 5rem box */
}
.is-header .who {
  display: flex;
  flex-direction: column;
  gap: .15rem;
  min-width: 0;
}
.is-header h1 { margin: 0; font-size: 1.7rem; }
.is-header .email { margin: 0; font-size: .95rem; color: var(--muted); }
.is-header .email a { color: inherit; }
.is-header .tz {
  margin: 0;
  font-size: .82rem;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

/* ── card ──────────────────────────────────────────────────────────── */
.card {
  background: var(--card-bg-fallback);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: var(--pad);
  box-shadow: 0 12px 40px -12px rgba(0, 0, 0, 0.5);
}
/* No backdrop-filter: the wallpaper behind the cards animates now and then
 * (clouds, grass, rain), and a blur would be recomputed on every frame. */

.card > header { margin-bottom: .6rem; display: flex; gap: .75rem; align-items: baseline; flex-wrap: wrap; }

/* ── search input ──────────────────────────────────────────────────── */
.search {
  flex: 1 1 auto;
  min-width: 8rem;
  background: rgba(0, 0, 0, 0.25);
  color: var(--fg);
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: .35rem .6rem;
  font: inherit;
  outline: none;
}
.search:focus { border-color: var(--accent); }

/* ── socials list (icon + name + copy button per row) ──────────────── */
.links {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  /* fits 1 col in narrow contacts column, 2 when there's room */
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  gap: .4rem;
}
.links li[hidden] { display: none; }
.links li {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: stretch;
  border: 1px solid var(--line);
  border-radius: 9px;
  background: rgba(0, 0, 0, 0.20);
  overflow: hidden;
  transition: background .12s ease, border-color .12s ease;
}
.links li:hover { background: rgba(255, 255, 255, 0.04); border-color: rgba(255, 255, 255, 0.18); }
.links a.link {
  display: flex;
  align-items: center;
  gap: .55rem;
  padding: .45rem .6rem;
  color: var(--fg);
  text-decoration: none;
  min-width: 0;
}
.links a.link span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.links .icon {
  width: 18px;
  height: 18px;
  flex: 0 0 auto;
  color: var(--fg);
}

/* ── payments list (key + value + copy button per row) ─────────────── */
.pay {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: .35rem;
}
.pay li {
  display: grid;
  grid-template-columns: 5rem minmax(0, 1fr) auto;
  align-items: stretch;
  border: 1px solid var(--line);
  border-radius: 9px;
  background: rgba(0, 0, 0, 0.20);
  overflow: hidden;
  transition: background .12s ease, border-color .12s ease;
}
.pay li:hover { background: rgba(255, 255, 255, 0.04); border-color: rgba(255, 255, 255, 0.18); }
.pay .pay-k {
  display: flex;
  align-items: center;
  padding: .4rem .6rem;
  color: var(--muted);
  font-size: .85rem;
  border-right: 1px solid var(--line);
  background: rgba(0, 0, 0, 0.15);
}
.pay .pay-v {
  display: flex;
  align-items: center;
  padding: .4rem .6rem;
  min-width: 0;
  color: var(--fg);
  text-decoration: none;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.pay a.pay-v { text-decoration: underline; text-underline-offset: 3px; text-decoration-color: var(--line); }
.pay a.pay-v:hover { text-decoration-color: currentColor; }
.pay code.pay-v { font-family: var(--mono); font-size: .8rem; }

.small { font-size: .78rem; margin-top: .6rem; }

/* ── chat ─────────────────────────────────────────────────────────── */
.chat-feed {
  height: 7.5rem;
  overflow: auto;
  display: flex;
  flex-direction: column;
  gap: .35rem;
  padding-right: .15rem;
  scrollbar-width: thin;
}
.chat-message {
  align-self: flex-start;
  width: fit-content;
  max-width: 85%;
  padding: .4rem .6rem;
  border: 1px solid var(--line);
  border-radius: 9px;
  background: rgba(0, 0, 0, 0.20);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.chat-message.mine {
  align-self: flex-end;
  background: rgba(255, 255, 255, 0.07);
}
.chat-time {
  display: block;
  margin-top: .15rem;
  color: var(--muted);
  font: .66rem/1.3 var(--mono);
  white-space: nowrap;
}
.chat-message.mine .chat-time { text-align: right; }
.chat-form {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  margin-top: .6rem;
}
.chat-form input {
  min-width: 0;
  background: rgba(0, 0, 0, 0.25);
  color: var(--fg);
  border: 1px solid var(--line);
  border-right: 0;
  border-radius: 8px 0 0 8px;
  padding: .45rem .6rem;
  font: inherit;
  outline: none;
}
.chat-form input:focus { border-color: var(--accent); }
.chat-form button {
  appearance: none;
  border: 1px solid var(--line);
  border-radius: 0 8px 8px 0;
  background: rgba(255, 255, 255, 0.06);
  color: var(--fg);
  padding: 0 .75rem;
  font: inherit;
  cursor: pointer;
}
.chat-form button:hover { background: rgba(255, 255, 255, 0.10); }
.chat-form button:disabled { color: var(--muted); cursor: default; }
.chat-form.failed input { border-color: #e07a7a; }

/* On this machine the card shows either the thread list or one conversation. */
.owner-threads {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: .35rem;
  align-content: start;
  max-height: 18rem;
  overflow: auto;
}
.owner-threads[hidden],
.owner-conversation[hidden] { display: none; }
.owner-threads li {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 2rem;
  gap: .3rem;
}
.owner-open {
  width: 100%;
  min-width: 0;
  display: grid;
  grid-template-columns: 3.8rem minmax(0, 1fr);
  gap: .55rem;
  border: 1px solid var(--line);
  border-radius: 9px;
  background: rgba(0, 0, 0, 0.20);
  color: var(--fg);
  padding: .45rem .6rem;
  text-align: left;
  font: inherit;
  cursor: pointer;
}
.owner-open:hover { background: rgba(255, 255, 255, 0.07); }
/* Someone wrote and you haven't opened it yet: sorted to the top, dot + bold. */
.owner-open.unread { border-color: rgba(255, 255, 255, 0.28); }
.owner-open.unread .owner-label { color: var(--fg); }
.owner-open.unread .owner-label::before {
  content: "";
  display: inline-block;
  width: .45rem;
  height: .45rem;
  margin-right: .3rem;
  border-radius: 50%;
  background: #6fb3ff;
  vertical-align: .08em;
}
.owner-open.unread .owner-preview { font-weight: 600; }
.owner-threads li.owner-divider {
  display: block;
  height: 1px;
  margin: .3rem .2rem;
  background: rgba(255, 255, 255, 0.22);
}
.owner-delete {
  appearance: none;
  width: 2rem;
  border: 1px solid var(--line);
  border-radius: 9px;
  background: rgba(0, 0, 0, 0.20);
  color: var(--muted);
  cursor: pointer;
  display: grid;
  place-items: center;
}
.owner-delete::before {
  content: "";
  width: 13px;
  height: 13px;
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M4 7h16M9 7V4h6v3m3 0-1 14H7L6 7m4 4v6m4-6v6' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/></svg>") center / contain no-repeat;
          mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M4 7h16M9 7V4h6v3m3 0-1 14H7L6 7m4 4v6m4-6v6' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/></svg>") center / contain no-repeat;
}
.owner-delete:hover { color: #e07a7a; background: rgba(224, 122, 122, 0.08); }
.owner-delete:disabled { opacity: .45; cursor: default; }
.owner-label { font: .78rem/1.55 var(--mono); color: var(--muted); }
.owner-preview { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.owner-back {
  appearance: none;
  border: 0;
  background: transparent;
  color: var(--muted);
  padding: 0;
  font: 1.1rem/1 var(--font);
  cursor: pointer;
}
.owner-back:hover { color: var(--fg); }
.owner-ips {
  margin-left: auto;
  color: var(--muted);
  font: .68rem/1.4 var(--mono);
  overflow-wrap: anywhere;
}
.owner-conversation {
  display: grid;
  grid-template-rows: minmax(0, 1fr) auto;
  min-width: 0;
}
.owner-conversation .chat-feed { height: 12rem; }
@media (max-width: 600px) {
  .owner-threads { max-height: 14rem; }
}

/* ── key/value blocks (security card) ──────────────────────────────── */
.kv {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: .35rem .9rem;
  margin: 0;
}
.kv dt { color: var(--muted); }
.kv dd { margin: 0; }
.fpr, .addr {
  font-family: var(--mono);
  font-size: .85rem;
  word-break: break-all;
}

/* ── copy button (shared by socials + payments) ────────────────────── */
.copy {
  appearance: none;
  background: transparent;
  border: 0;
  border-left: 1px solid var(--line);
  color: var(--muted);
  cursor: pointer;
  padding: 0 .65rem;
  display: grid;
  place-items: center;
  position: relative;
  transition: color .12s ease, background .12s ease;
}
.copy:hover { color: var(--fg); background: rgba(255, 255, 255, 0.05); }
.copy:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
/* The two icons live as backgrounds so we don't have to edit every <button>'s
 * markup. SVGs encoded inline; on .copy.ok we swap to the checkmark. */
.copy::before {
  content: "";
  width: 16px; height: 16px;
  background-color: currentColor;
  -webkit-mask: var(--icon-copy) center / contain no-repeat;
          mask: var(--icon-copy) center / contain no-repeat;
}
.copy.ok::before {
  -webkit-mask-image: var(--icon-check);
          mask-image: var(--icon-check);
  color: #6fdc8c;
}
.copy.fail::before { color: #e07a7a; }
:root {
  --icon-copy: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'><rect x='9' y='9' width='11' height='11' rx='2'/><path d='M5 15V5a2 2 0 0 1 2-2h10'/></svg>");
  --icon-check: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'><polyline points='20 6 9 17 4 12'/></svg>");
}

/* ── Bliss wallpaper (scripts/bliss; sky.js sets the --vars) ─────────── */
#bliss { position: fixed; top: 0; left: 0; width: 100%; height: 100vh; overflow: hidden; background: var(--k1, #8db8f4); } /* 100vh: the tallest viewport, so a sliding URL bar doesn't resize it */
#bliss svg { position: absolute; left: var(--bx); top: var(--by); width: var(--bw); height: var(--bh); overflow: visible; }
#sun { transform: translate(var(--sx), var(--sy)); opacity: var(--so); }
#bliss canvas { position: absolute; top: 0; left: 0; width: 100%; }
#bliss .b-d { position: absolute; inset: 0; opacity: 0; transition: opacity .5s; }
#bliss .b-d.on { opacity: 1; }
#bliss .b-c { position: absolute; top: 0; left: 0; will-change: transform; } /* the drifting cloud layer */
#bliss .b-stars { height: 100%; transition: opacity 3s; }
.b-wet { position: absolute; inset: 0; opacity: 0; transition: opacity 3s, background-color 3s; } /* rain makes the scene wetter */
.b-wx { position: absolute; inset: 0; overflow: hidden; transition: opacity 3s; }
.b-wx div { position: absolute; will-change: transform; }
#bliss.flash::after { content: ""; position: absolute; inset: 0; background: #e8ecff; opacity: 0; animation: b-flash 1.2s ease-out; }
@keyframes b-flash { 0%, 12% { opacity: .5; } 6% { opacity: .15; } 100% { opacity: 0; } }

