/* contacts — the public PWA.
   Follows the repo style-guide (apps/local/style-guide): shadcn/ui look, warm
   off-white, Figtree, teal primary, --radius 0.625rem. The local app pulled
   these tokens from the style-guide dev server at localhost:4300; a cloud-hosted
   app can't, so they are inlined here. Keep them in sync with
   apps/local/style-guide/src/index.css if that file moves.

   Sizing follows the repo's touch minimums: tap targets ≥44px (the app's own
   rows are larger), body text ≥15px, never below 13px for metadata. */

:root {
  --app-font: "Figtree", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  --background: oklch(0.985 0.006 85);
  --foreground: oklch(0.145 0 0);
  --card: oklch(1 0 0);
  --card-foreground: oklch(0.145 0 0);
  --primary: oklch(0.64 0.11 200);
  --primary-foreground: oklch(0.985 0.01 200);
  --secondary: oklch(0.97 0 0);
  --muted: oklch(0.97 0 0);
  --muted-foreground: oklch(0.556 0 0);
  --accent: oklch(0.97 0 0);
  --destructive: oklch(0.577 0.245 27.325);
  --border: oklch(0.922 0 0);
  --input: oklch(0.922 0 0);
  --ring: oklch(0.64 0.11 200);
  --radius: 0.625rem;
  --radius-sm: calc(var(--radius) * 0.6);
  --radius-md: calc(var(--radius) * 0.8);
  --radius-lg: var(--radius);
  --radius-xl: calc(var(--radius) * 1.4);
  --good: oklch(0.62 0.13 155);
  --warn: oklch(0.72 0.14 75);
  --bad: oklch(0.6 0.19 27);
  /* Safe areas, so a standalone PWA clears the notch and the home indicator. */
  --sat: env(safe-area-inset-top, 0px);
  --sab: env(safe-area-inset-bottom, 0px);
}

* { box-sizing: border-box; }
[hidden] { display: none !important; }

html, body { height: 100%; }
body {
  margin: 0;
  font-family: var(--app-font);
  font-size: 15px;
  line-height: 1.5;
  color: var(--foreground);
  background: var(--background);
  -webkit-font-smoothing: antialiased;
  /* Standalone PWAs shouldn't rubber-band the whole document. */
  overscroll-behavior-y: none;
}

button, input, select, textarea { font: inherit; color: inherit; }
button { cursor: pointer; border: none; background: none; }
a { color: var(--primary); }

/* ── buttons ── */
.primary, .outline, .danger {
  height: 44px;
  padding: 0 16px;
  border-radius: var(--radius-md);
  font-size: 15px;
  font-weight: 600;
  border: 1px solid transparent;
}
.primary { background: var(--primary); color: var(--primary-foreground); }
.outline { background: var(--card); border-color: var(--border); }
.danger { background: transparent; color: var(--destructive); border-color: var(--border); }
.block { width: 100%; }
.linkish { font-size: 15px; color: var(--primary); padding: 8px 4px; min-height: 44px; }
.linkish.strong { font-weight: 600; }
.icon-btn {
  width: 44px; height: 44px;
  border-radius: var(--radius-md);
  font-size: 20px; line-height: 1;
  color: var(--muted-foreground);
}
.icon-btn:hover { background: var(--muted); }

/* ── sign-in / no-access gates ── */
.gate {
  position: fixed; inset: 0;
  display: grid; place-items: center;
  padding: 24px;
  background: var(--background);
  z-index: 50;
}
.gate-card {
  width: 100%; max-width: 360px;
  display: flex; flex-direction: column; gap: 12px;
  padding: 28px 24px 24px;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
}
.gate-mark { color: var(--primary); }
.gate-card h1 { margin: 0; font-size: 24px; font-weight: 700; letter-spacing: -0.02em; }
.gate-sub { margin: -6px 0 6px; color: var(--muted-foreground); font-size: 14px; }
.gate-card label { display: flex; flex-direction: column; gap: 6px; font-size: 13px; font-weight: 500; color: var(--muted-foreground); }
.gate-msg { margin: 0; padding: 10px 12px; border-radius: var(--radius-sm); background: color-mix(in oklch, var(--destructive) 12%, transparent); color: var(--bad); font-size: 14px; }

input, select, textarea {
  width: 100%;
  min-height: 44px;
  padding: 9px 12px;
  border: 1px solid var(--input);
  border-radius: var(--radius-md);
  background: var(--card);
  /* 16px stops iOS Safari zooming the page when a field takes focus. */
  font-size: 16px;
}
textarea { min-height: 80px; resize: vertical; line-height: 1.55; }
input:focus-visible, select:focus-visible, textarea:focus-visible, button:focus-visible {
  outline: 2px solid var(--ring); outline-offset: 1px;
}

/* ── shell ── */
.app { display: flex; flex-direction: column; min-height: 100%; }

.topbar {
  position: sticky; top: 0; z-index: 5;
  padding: calc(10px + var(--sat)) 14px 10px;
  display: flex; flex-direction: column; gap: 10px;
  border-bottom: 1px solid var(--border);
  background: color-mix(in oklch, var(--background) 88%, transparent);
  backdrop-filter: blur(10px);
}
.topbar-row { display: flex; align-items: center; gap: 10px; }
.topbar h1 { margin: 0; font-size: 21px; font-weight: 700; letter-spacing: -0.02em; }
/* Search gets its own full-width row on a phone — cramming it in beside four
   filter selects left about eight readable characters. The filters get the
   horizontally-scrolling row instead. */
.search-row #search { flex: 1; }
.tools { overflow-x: auto; scrollbar-width: none; }
.tools::-webkit-scrollbar { display: none; }
.tools > * { flex: 0 0 auto; width: auto; min-width: 0; }
.tools select { height: 44px; padding-right: 28px; font-size: 14px; }

.tabs { display: flex; gap: 3px; padding: 3px; border-radius: var(--radius-md); background: var(--muted); margin-left: auto; }
.tabs .tab {
  height: 34px; padding: 0 12px;
  font-size: 13px; font-weight: 500;
  color: var(--muted-foreground);
  border-radius: calc(var(--radius) * 0.55);
}
.tabs .tab.on { background: var(--card); color: var(--foreground); box-shadow: 0 1px 2px oklch(0 0 0 / 0.06); }
.tab-count { opacity: 0.55; font-variant-numeric: tabular-nums; }

.layout { flex: 1; display: flex; min-height: 0; }
.list-pane { flex: 1; min-width: 0; padding: 12px 14px calc(96px + var(--sab)); }
.count { margin: 2px 2px 10px; font-size: 13px; color: var(--muted-foreground); }
.empty { margin: 40px 8px; text-align: center; color: var(--muted-foreground); }

/* ── cards ── */
.cards { display: flex; flex-direction: column; gap: 8px; }
.card {
  display: flex; gap: 12px; align-items: flex-start;
  width: 100%; padding: 12px;
  text-align: left;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
}
.card:hover { border-color: color-mix(in oklch, var(--primary) 35%, var(--border)); }
.card.on { border-color: var(--primary); box-shadow: 0 0 0 1px var(--primary); }
/* A follow-up owed: a left rail rather than a full yellow wash, which stayed
   readable and stopped the list looking alarmed. */
.card.recontact { border-left: 3px solid var(--warn); }
.card-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.card-top { display: flex; align-items: center; gap: 8px; }
.card-name { font-weight: 600; letter-spacing: -0.01em; flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.card-meta { font-size: 13px; color: var(--muted-foreground); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.card-tags { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 3px; }
.card-help {
  margin-top: 4px;
  font-size: 13px; line-height: 1.45;
  color: var(--muted-foreground);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}
.card-help b { color: var(--foreground); font-weight: 600; }

/* ── avatars ── */
.avatar-wrap { position: relative; width: 44px; height: 44px; flex: 0 0 auto; }
.avatar-wrap.lg { width: 64px; height: 64px; }
.avatar {
  position: absolute; inset: 0;
  display: grid; place-items: center;
  border-radius: 999px;
  font-size: 15px; font-weight: 600; color: oklch(0.3 0.02 250);
  overflow: hidden;
}
.avatar.lg { font-size: 21px; }
/* An absolutely-positioned REPLACED element with inset:0 and width:auto resolves
   to its intrinsic size, not the containing block — so an <img> here needs an
   explicit 100%/100% or it renders at the photo's own 256px. The initials <span>
   next to it stretches on its own because it isn't a replaced element. */
.avatar.photo { width: 100%; height: 100%; object-fit: cover; background: var(--muted); }

/* ── chips ── */
.skill, .interest, .pill {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 12px; font-weight: 500;
  white-space: nowrap;
}
.skill { background: color-mix(in oklch, var(--primary) 12%, transparent); color: oklch(0.42 0.09 200); }
.interest { background: color-mix(in oklch, #4a3aa7 12%, transparent); color: #4a3aa7; }
.pill { background: var(--muted); color: var(--muted-foreground); }

.badge {
  padding: 2px 7px; border-radius: 999px;
  font-size: 11px; font-weight: 600;
  font-variant-numeric: tabular-nums;
  flex: 0 0 auto;
}
.badge.fresh { background: color-mix(in oklch, var(--good) 14%, transparent); color: oklch(0.42 0.11 155); }
.badge.warn  { background: color-mix(in oklch, var(--warn) 18%, transparent); color: oklch(0.45 0.1 75); }
.badge.stale { background: color-mix(in oklch, var(--bad) 12%, transparent); color: var(--bad); }
.badge.never { background: var(--muted); color: var(--muted-foreground); }

/* ── detail ── */
.detail-pane {
  position: fixed; inset: 0; z-index: 20;
  background: var(--background);
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: 0 16px calc(24px + var(--sab));
}
.d-head {
  position: sticky; top: 0; z-index: 2;
  display: flex; align-items: center; gap: 8px;
  margin: 0 -16px 14px; padding: calc(6px + var(--sat)) 10px 10px;
  background: color-mix(in oklch, var(--background) 92%, transparent);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--border);
}
.back { width: 44px; height: 44px; font-size: 30px; line-height: 1; color: var(--primary); }
.d-id { flex: 1; min-width: 0; display: flex; gap: 12px; align-items: center; }
.d-id h2 { margin: 0; font-size: 19px; font-weight: 700; letter-spacing: -0.02em; }
.d-sub { margin: 1px 0 0; font-size: 14px; color: var(--muted-foreground); }
.d-role { margin: 2px 0 0; font-size: 13px; color: var(--muted-foreground); opacity: 0.85; }

.d-acts { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 16px; }
.act {
  flex: 1 1 auto; min-width: 84px;
  display: grid; place-items: center;
  height: 44px; padding: 0 14px;
  border: 1px solid var(--border); border-radius: var(--radius-md);
  background: var(--card);
  font-size: 14px; font-weight: 600;
  text-decoration: none;
}

.d-block { margin-bottom: 16px; }
.d-block h3 {
  margin: 0 0 7px;
  font-size: 12px; font-weight: 600;
  letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--muted-foreground);
}
.d-block p { margin: 0; }
.d-block .pre { white-space: pre-wrap; }
/* The point of the app: what I can do for this person, given the most weight. */
.d-block.hero {
  padding: 14px;
  background: var(--card);
  border: 1px solid var(--border);
  border-left: 3px solid var(--primary);
  border-radius: var(--radius-lg);
}
.d-block.hero h3 { color: var(--primary); }
.help-text { font-size: 15px; line-height: 1.6; }

/* ── inline bullet lists (skills / interests / how I can help) ──
   Always-editable rather than click-to-edit: these three are the point of the
   app, so they're changed in place with no Edit round trip. The controls are
   styled to read as plain bullets until focused, so the detail view still looks
   like a document rather than a form. */
.list-block { position: relative; }
.list-block.saving { opacity: 0.6; }
.list-block.save-failed { outline: 1px solid var(--destructive); outline-offset: 6px; border-radius: var(--radius-md); }
.bullets { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }
.bullet { display: flex; align-items: flex-start; gap: 8px; border-radius: var(--radius-sm); }
.bullet:hover { background: color-mix(in oklch, var(--muted) 55%, transparent); }
.bullet-dot {
  flex: 0 0 auto;
  width: 5px; height: 5px; margin-top: 13px; margin-left: 3px;
  border-radius: 999px; background: var(--muted-foreground);
}
.bullet-input {
  flex: 1; min-width: 0;
  min-height: 0; padding: 5px 6px;
  border: 1px solid transparent; border-radius: var(--radius-sm);
  background: transparent;
  font-size: 15px; line-height: 1.55;
  overflow: hidden; resize: none;
}
.bullet-input:hover { border-color: var(--border); }
.bullet-input:focus,
.bullet-input:focus-visible {
  background: var(--card);
  border-color: var(--ring);
  outline: none;
}
.bullet-input::placeholder { color: var(--muted-foreground); opacity: 0.7; }
/* The delete affordance stays out of the way until the row is engaged — but is
   always present on touch, where there is no hover to reveal it. */
.bullet-del {
  flex: 0 0 auto;
  width: 30px; height: 30px; margin-top: 2px;
  border-radius: var(--radius-sm);
  color: var(--muted-foreground); font-size: 17px; line-height: 1;
  opacity: 0;
}
.bullet:hover .bullet-del,
.bullet:focus-within .bullet-del { opacity: 1; }
.bullet-del:hover { background: color-mix(in oklch, var(--destructive) 12%, transparent); color: var(--destructive); }
@media (hover: none) { .bullet-del { opacity: 0.55; } }

.add-bullet {
  margin-top: 6px; margin-left: 16px;
  padding: 7px 10px;
  border-radius: var(--radius-sm);
  color: var(--primary); font-size: 14px; font-weight: 600;
  min-height: 38px;
}
.add-bullet:hover { background: color-mix(in oklch, var(--primary) 10%, transparent); }

.card-help .more { color: var(--muted-foreground); font-weight: 500; }
.edit-note { margin: 0; padding: 10px 12px; background: var(--muted); border-radius: var(--radius-md); }

.chips-view { display: flex; flex-wrap: wrap; gap: 5px; }
.src { font-size: 13px; word-break: break-all; }
.d-foot { margin-top: 22px; }
.d-foot .primary { height: 52px; display: flex; flex-direction: column; gap: 1px; justify-content: center; }
.foot-sub { font-size: 12px; font-weight: 500; opacity: 0.8; }

/* ── fab ── */
.fab {
  position: fixed; right: 18px; bottom: calc(18px + var(--sab)); z-index: 15;
  width: 56px; height: 56px;
  border-radius: 999px;
  background: var(--primary); color: var(--primary-foreground);
  font-size: 28px; line-height: 1;
  box-shadow: 0 6px 20px oklch(0 0 0 / 0.18);
}
body.detail-open .fab { display: none; }

.offline-bar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 30;
  margin: 0; padding: 10px 14px calc(10px + var(--sab));
  background: var(--warn); color: oklch(0.2 0.05 75);
  font-size: 13px; font-weight: 500; text-align: center;
}
body.is-offline .fab { opacity: 0.4; pointer-events: none; }

/* ── dialogs ── */
dialog {
  border: none; padding: 0;
  background: var(--background); color: var(--foreground);
  max-width: 100vw; max-height: 100dvh;
  width: 100%; height: 100dvh;
}
dialog::backdrop { background: oklch(0 0 0 / 0.45); }
.sheet-head {
  position: sticky; top: 0; z-index: 2;
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding: calc(6px + var(--sat)) 10px 8px;
  border-bottom: 1px solid var(--border);
  background: color-mix(in oklch, var(--background) 92%, transparent);
  backdrop-filter: blur(10px);
}
.sheet-head h2 { margin: 0; font-size: 16px; font-weight: 600; }

.grid { display: grid; grid-template-columns: 1fr; gap: 14px; padding: 16px 16px calc(40px + var(--sab)); }
.grid label { display: flex; flex-direction: column; gap: 6px; font-size: 13px; font-weight: 500; color: var(--muted-foreground); }
.grid label.check { flex-direction: row; align-items: center; gap: 10px; font-size: 14px; color: var(--foreground); }
.grid label.check input { width: 22px; height: 22px; min-height: 0; flex: 0 0 auto; }
.hint { font-size: 12px; font-weight: 400; color: var(--muted-foreground); }
.hero-field textarea { border-left: 3px solid var(--primary); }
.section-rule {
  margin-top: 6px; padding-top: 14px;
  border-top: 1px solid var(--border);
  font-size: 12px; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--muted-foreground);
}
.form-actions { margin-top: 10px; }
.chips { display: flex; flex-wrap: wrap; gap: 6px; }
.chip {
  padding: 7px 12px; min-height: 36px;
  border: 1px solid var(--border); border-radius: 999px;
  background: var(--card);
  font-size: 13px; color: var(--muted-foreground);
}
.chip.on { background: var(--primary); border-color: var(--primary); color: var(--primary-foreground); font-weight: 600; }
.chip-add { display: flex; gap: 8px; margin-top: 8px; }
.chip-add input { flex: 1; }
.chip-add .outline { flex: 0 0 auto; }

#menu { width: 100%; height: auto; max-height: none; margin: auto auto 0; background: transparent; }
.menu-card {
  display: flex; flex-direction: column; gap: 6px;
  margin: 12px; padding: 10px;
  background: var(--card); border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  margin-bottom: calc(12px + var(--sab));
}
.menu-card button { height: 50px; border-radius: var(--radius-md); font-size: 16px; text-align: center; }
.menu-card button:hover { background: var(--muted); }
.menu-card .outline { color: var(--muted-foreground); }

/* ── wide screens: list + detail side by side ── */
@media (min-width: 860px) {
  .topbar { padding: 14px 24px; flex-direction: row; align-items: center; flex-wrap: wrap; }
  /* Wide enough for one line: search and the filters share a row again. */
  .topbar-row.search-row { flex: 1 1 340px; min-width: 240px; order: 2; }
  .topbar-row.tools { flex: 2 1 420px; order: 3; }
  .tabs { margin-left: 0; }
  #menuBtn { margin-left: auto; }

  .layout { align-items: flex-start; }
  .list-pane {
    flex: 0 0 420px;
    max-width: 420px;
    height: calc(100dvh - 118px);
    overflow-y: auto;
    padding-bottom: 24px;
    border-right: 1px solid var(--border);
  }
  .detail-pane {
    position: sticky; top: 118px; inset: auto;
    flex: 1; min-width: 0;
    height: calc(100dvh - 118px);
    padding: 0 28px 28px;
  }
  /* The detail is a pane, not a sheet — nothing to go "back" from. */
  .back { display: none; }
  .d-head { margin-inline: -28px; padding-inline: 28px; }
  body.detail-open .fab { display: block; }
  .detail { max-width: 680px; }

  dialog { width: min(720px, 96vw); height: auto; max-height: 92dvh; border-radius: var(--radius-xl); overflow: auto; }
  .grid { grid-template-columns: 1fr 1fr; }
  .grid .full { grid-column: 1 / -1; }
  #menu { width: min(320px, 92vw); margin: auto; }
}

@media (prefers-reduced-motion: no-preference) {
  .card, .chip, .act { transition: border-color 0.12s ease, background 0.12s ease; }
}
