/*
 * The Oni greeter — site-wide.
 *
 * Loaded on every chromed page by the <!-- greeterdock --> block (see
 * scripts/render-chrome.mjs), not just /contact — so it can NOT assume
 * legal.css (and therefore tokens.css) is present.
 *
 * It deliberately does NOT `@import "/tokens.css"`. An @import can't start
 * downloading until this file has been fetched AND parsed, so on the homepage
 * — the one page with no other route to tokens.css — it measured as a 1,038 ms
 * serialized two-hop chain on slow-4G, for a 15 KB sheet whose ~15 relevant
 * declarations are copied below instead. On every other page the import was
 * simply redundant (legal.css already pulls the same URL).
 *
 * These MIRROR public/tokens.css — if a value changes there, change it here.
 * Only the handful the dock actually consumes lives here; the rest of the
 * palette is none of the dock's business.
 *
 * Progressive enhancement: this file styles markup that only ever exists if
 * greeter.js ran. With no JS nothing renders anywhere, and /contact's cards
 * are the whole story — also the fallback when the greeter is over budget.
 */

/* Self-hosted wordmark face for the pop-over heading on pages that don't load
   legal.css/main.css. Same file those sheets point at — cached once. */
@font-face {
  font-family: 'Audiowide';
  src: url('/fonts/audiowide-latin.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

/* The /contact intro card mount (the mascot is gone — just the panel now). */
.greeter {
  margin: 18px 0 30px;
}

.greeter-panel {
  background: var(--panel);
  border: 1px solid var(--border);
  border-top: 3px solid var(--accent);
  border-radius: 16px;
  padding: 22px 22px 18px;
  min-width: 0;
}

.greeter-panel h2 {
  font-family: 'Audiowide', sans-serif;
  color: var(--heading);
  font-size: 1.16rem;
  margin: 0 0 8px;
  padding: 0;
}

.greeter-sub {
  font-size: 0.92rem;
  color: var(--text-dim);
  line-height: 1.6;
  margin: 0 0 16px;
}
.greeter-sub strong { color: var(--heading); font-weight: 600; }
.greeter-sub a { color: var(--accent); }

/* ── Consent gate ──────────────────────────────────────────────────────── */

.greeter-consent ul {
  list-style: none;
  margin: 0 0 16px;
  padding: 0;
  font-size: 0.9rem;
  color: var(--text-dim);
  line-height: 1.6;
}
.greeter-consent li {
  padding-left: 20px;
  position: relative;
  margin: 6px 0;
}
.greeter-consent li::before {
  content: '·';
  position: absolute;
  left: 6px;
  color: var(--accent);
  font-weight: 700;
}

.greeter-turnstile { margin: 0 0 14px; }
.greeter-turnstile:empty { margin: 0; }

/* ── Transcript ────────────────────────────────────────────────────────── */

.greeter-log {
  display: flex;
  flex-direction: column;
  gap: 12px;
  max-height: 52vh;
  overflow-y: auto;
  margin: 0 0 14px;
  scroll-behavior: smooth;
}
.greeter-log:empty { display: none; }

.greeter-msg {
  font-size: 0.96rem;
  line-height: 1.6;
  max-width: 46ch;
}
.greeter-msg p { margin: 0 0 8px; }
.greeter-msg p:last-child { margin: 0; }
.greeter-msg a { color: var(--accent); }

.greeter-msg-you {
  align-self: flex-end;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid var(--border);
  border-radius: 14px 14px 4px 14px;
  padding: 9px 14px;
  color: var(--heading);
}
.greeter-msg-oni { align-self: flex-start; color: var(--text); }

/* The cited pages under an answer — the whole point of grounding is that the
   reader can go check. */
.greeter-cites {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 8px;
}
.greeter-cites a {
  font-size: 0.74rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--text-dim);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 3px 10px;
  transition: color 0.2s, border-color 0.2s;
}
.greeter-cites a:hover,
.greeter-cites a:focus-visible {
  color: var(--heading);
  border-color: var(--accent);
}

/* Typing indicator — three dots that don't animate under reduced motion. */
.greeter-typing { display: inline-flex; gap: 4px; align-items: center; height: 1.4em; }
.greeter-typing i {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--text-dim);
  animation: greeter-blink 1.3s infinite both;
}
.greeter-typing i:nth-child(2) { animation-delay: 0.18s; }
.greeter-typing i:nth-child(3) { animation-delay: 0.36s; }
@keyframes greeter-blink {
  0%, 80%, 100% { opacity: 0.25; }
  40% { opacity: 1; }
}

/* ── Composer — one glass capsule, field and send button share it ────────
   The capsule owns the border and radius; the textarea is a bare well inside
   it and the send button is a circle. Nothing to misalign, one radius. */

.greeter-form {
  display: flex;
  align-items: flex-end;
  gap: 8px;
  background: rgba(255, 255, 255, 0.07);
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: 22px;
  padding: 5px;
  transition: border-color 0.2s;
}
.greeter-form:focus-within {
  border-color: var(--accent);
  border-color: color-mix(in srgb, var(--accent) 65%, transparent);
}

.greeter-form textarea {
  flex: 1;
  min-width: 0;
  resize: none;
  background: transparent;
  border: none;
  padding: 8px 0;
  color: var(--heading);
  font-family: inherit;
  font-size: 0.96rem;
  line-height: 1.5;
  outline: none;
  field-sizing: content;
  max-height: 6em;
}
.greeter-form textarea::placeholder { color: var(--text-dim); }

.greeter-send {
  flex: none;
  width: 36px;
  height: 36px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  border: none;
  background: var(--accent);
  color: var(--accent-ink);
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
  transition: filter 0.16s;
}
.greeter-send:hover,
.greeter-send:focus-visible { filter: brightness(1.12); }
.greeter-send[disabled] { opacity: 0.45; cursor: not-allowed; }

/* ── Header, bottom bar + the glass button ───────────────────────────────
   Inside the pop the PANEL is the scroll container, so the header pins to
   its top and the composer bar to its bottom with position:sticky — both
   carry their own glass fill so the transcript frosts as it passes under.
   The negative margins span the panel's padding (22px sides, 22px top,
   18px bottom) so the bars run edge-to-edge. */

.greeter-head {
  position: sticky;
  top: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin: 0 -22px 10px;
  padding: 16px 18px 10px 22px;
  background: var(--glass-bar);
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 22px 22px 0 0;
}
.greeter-head h2 { margin: 0; }

.greeter-dockbar {
  position: sticky;
  bottom: 0;
  z-index: 2;
  margin: 12px -22px 0;
  padding: 10px 22px 14px;
  background: var(--glass-bar);
  border-top: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 0 0 22px 22px;
}
.greeter-dockbar .greeter-glass-btn { display: block; margin: 0 auto; }

.greeter-tool {
  min-width: 30px;
  height: 30px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.14);
  color: var(--text-dim);
  font-family: inherit;
  font-size: 0.92rem;
  line-height: 1;
  cursor: pointer;
  transition: color 0.16s, background 0.16s;
}
.greeter-tool:hover,
.greeter-tool:focus-visible {
  color: var(--heading);
  background: rgba(255, 255, 255, 0.15);
}
/* Clear — the ghost button leading the composer capsule. */
.greeter-clear {
  flex: none;
  width: 36px;
  height: 36px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 999px;
  background: transparent;
  border: none;
  color: var(--text-dim);
  font-family: inherit;
  font-size: 1.05rem;
  line-height: 1;
  cursor: pointer;
  transition: color 0.16s, background 0.16s;
}
.greeter-clear:hover,
.greeter-clear:focus-visible {
  color: var(--heading);
  background: rgba(255, 255, 255, 0.1);
}
/* The armed "Sure?" state — widened, warning-tinted, disarms on timeout. */
.greeter-clear[data-armed='1'] {
  width: auto;
  padding: 0 10px;
  color: #ff9a7a;
  border: 1px solid currentColor;
  font-size: 0.7rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

/* Translucent accent-tinted pill — the liquid counterpart of .cta-btn, used
   for the in-pop actions (consent accept, start-fresh). The /contact intro
   opener is deliberately NOT glass: it's a page-level primary, so it uses the
   site's shared filled .cta-btn. */
.greeter-glass-btn {
  display: inline-block;
  font-family: inherit;
  font-size: 0.82rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--heading);
  /* Same optics as the FAB: light smoked base + baked-in top sheen, tinted
     toward the page accent. Plain declarations first as color-mix fallback. */
  background:
    linear-gradient(170deg, rgba(255, 255, 255, 0.24), rgba(255, 255, 255, 0.05) 55%),
    rgba(110, 116, 134, 0.2);
  background:
    linear-gradient(170deg, rgba(255, 255, 255, 0.24), rgba(255, 255, 255, 0.05) 55%),
    color-mix(in srgb, var(--accent) 16%, rgba(110, 116, 134, 0.16));
  -webkit-backdrop-filter: blur(14px) saturate(1.4);
  backdrop-filter: blur(14px) saturate(1.4);
  border: 1px solid rgba(255, 255, 255, 0.3);
  border: 1px solid color-mix(in srgb, var(--accent) 40%, rgba(255, 255, 255, 0.24));
  border-radius: 999px;
  padding: 11px 22px;
  cursor: pointer;
  box-shadow:
    inset 0 1px 1px rgba(255, 255, 255, 0.4),
    inset 0 -6px 10px rgba(0, 0, 0, 0.2);
  transition: background 0.16s, border-color 0.16s, filter 0.16s;
}
.greeter-glass-btn:hover,
.greeter-glass-btn:focus-visible { filter: brightness(1.15); }
.greeter-glass-btn[disabled] { opacity: 0.55; cursor: not-allowed; }

/* The /contact intro card joins the material — the same shared --glass-*
   variables as the pop, so the opener button sits on identical glass. */
.greeter .greeter-panel {
  background: var(--glass-fill);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  border: var(--glass-border);
  box-shadow: var(--glass-light);
}

.greeter-foot {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  margin: 10px 2px 0;
  font-size: 0.76rem;
  color: var(--text-dim);
  line-height: 1.5;
}
.greeter-foot a { color: var(--text-dim); }
.greeter-foot a:hover { color: var(--heading); }
/* The bar's status line: normally an empty aria-live span (zero height — no
   line box), so the composer bar stays minimal; it only takes space when a
   status is actually announced (turn cap, follow-the-cite). */
.greeter-foot--bar { margin: 0; }
.greeter-foot--bar:has(#greeter-status:not(:empty)) { margin-top: 8px; }

.greeter-status { color: #ff9a7a; }

@media (max-width: 640px) {
  .greeter-msg { max-width: none; }
}

@media (prefers-reduced-motion: reduce) {
  .greeter-log { scroll-behavior: auto; }
  .greeter-typing i { animation: none; opacity: 0.6; }
  .greeter-cites a, .greeter-form, .greeter-tool, .greeter-clear,
  .greeter-glass-btn, .greeter-send { transition: none; }
}

/* ── The dock — 鬼 on every page ───────────────────────────────────────────
   The accent is DYNAMIC: the dock inherits whatever `--accent` the page's
   [data-theme] sets (gold on /duels/, teal on /worldwright/, …), so the glass
   takes on the host page's identity. Only themeless pages (the React
   homepage's bare <body>) fall back to white. In-text links inside the pop
   keep underlines — on a white-accent page color alone can't separate them. */

.greeter-dock {
  /* Literals, not var(--ref-*) — see the tokens note in the file header. */
  --panel: #141418;
  --border: rgba(255, 255, 255, 0.1);
  --heading: #fff;
  --text: rgba(255, 255, 255, 0.88);
  --text-dim: rgba(255, 255, 255, 0.5);
  --accent-ink: #14100a;
  --dock-z: 1000;
  font-family: -apple-system, BlinkMacSystemFont, 'Inter', 'Helvetica Neue', Arial, sans-serif;
  font-variant-numeric: slashed-zero;
}
/* --accent is inherited from the page's [data-theme] where tokens.css is
   loaded; themeless pages (the React homepage) fall back to white. */
body:not([data-theme]) .greeter-dock { --accent: #fff; }

/* ── ONE glass material ────────────────────────────────────────────────────
   The chat pane defines the glass; everything else consumes these variables
   verbatim — the open-state button and the /contact intro card render from
   EXACTLY the same declarations, so the material can never drift apart.
   Change the glass here and nowhere else. */
.greeter-dock,
.greeter {
  /* 0.88, not 0.58. The pop is position:fixed while the page scrolls, so ANY
     bright page art (a journal cover, a game hero) can pass behind it — and at
     0.58 body text measured 3.9:1 and accent links 1.8:1 against that, well
     under the 4.5:1 AA floor. The blur+saturate still reads as glass through
     the remaining 12%; legibility is not negotiable for a text surface. */
  --glass-fill:
    linear-gradient(180deg, rgba(255, 255, 255, 0.07), rgba(255, 255, 255, 0.02) 42%),
    rgba(13, 15, 21, 0.88);
  --glass-blur: blur(26px) saturate(1.5);
  --glass-border: 1px solid rgba(255, 255, 255, 0.16);
  --glass-light: inset 0 1px 0 rgba(255, 255, 255, 0.22);
  /* The sticky bars need to hide the TRANSCRIPT sliding under them, which is a
     different job from frosting the page: they can't use --glass-blur at all,
     because an ancestor with backdrop-filter (the panel) is a backdrop ROOT —
     a nested backdrop-filter has nothing left to sample and silently does
     nothing. That no-op is why answer text used to render straight through the
     header and composer. Opacity is the only thing that actually occludes. */
  --glass-bar:
    linear-gradient(180deg, rgba(255, 255, 255, 0.07), rgba(255, 255, 255, 0.02) 42%),
    rgba(13, 15, 21, 0.985);
}

/* Liquid glass: translucent fills + backdrop blur/saturate, so the dock takes
   its tint from whatever the page puts behind it — gold on /duels/, neon over
   a journal cover — with hairline specular edges instead of hard borders. */
.greeter-fab {
  position: fixed;
  right: max(18px, env(safe-area-inset-right));
  bottom: max(18px, env(safe-area-inset-bottom));
  z-index: var(--dock-z);
  width: 58px;
  height: 58px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 16px;
  /* CLOSED (the default state): a flat accent tile — solid page-accent fill,
     bold black kanji, no glass at all. The button wears the page's color like
     an app icon. OPEN it becomes the neutral smoked glass of the pane it
     summoned (see [aria-expanded] below). */
  background: var(--accent);
  border: none;
  color: #000;
  cursor: pointer;
  box-shadow: 0 8px 28px rgba(0, 0, 0, 0.45);
  transition: transform 0.16s ease, filter 0.16s ease;
}
.greeter-fab svg { display: block; }
/* Open: the pop carries the conversation (and the accent) now — the button
   becomes a small square of the EXACT pane material (the shared --glass-*
   variables), with the kanji taking the accent. Only the drop shadow is its
   own (it floats; the pane's elevation lives on .greeter-pop). */
.greeter-fab[aria-expanded='true'] {
  background: var(--glass-fill);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  border: var(--glass-border);
  color: var(--accent);
  box-shadow: 0 8px 28px rgba(0, 0, 0, 0.45), var(--glass-light);
}

.greeter-fab:hover,
.greeter-fab:focus-visible {
  transform: translateY(-2px);
  filter: brightness(1.1);
}
.greeter-fab:focus-visible {
  outline: 2px solid var(--focus-ring, #fff);
  outline-offset: 3px;
}

.greeter-pop {
  position: fixed;
  right: max(16px, env(safe-area-inset-right));
  bottom: calc(max(18px, env(safe-area-inset-bottom)) + 70px);
  z-index: var(--dock-z);
  width: min(400px, calc(100vw - 32px));
  max-height: min(620px, calc(100dvh - 120px));
  display: flex;
  border-radius: 22px;
  box-shadow: 0 24px 64px rgba(0, 0, 0, 0.55);
  transform-origin: 100% 100%;
}
.greeter-pop[hidden] { display: none; }
/* A soft bloom out of the corner when it opens — display:none → flex restarts
   the animation each time, which is exactly what we want. */
.greeter-pop:not([hidden]) { animation: greeter-bloom 0.22s ease; }
@keyframes greeter-bloom {
  from { opacity: 0; transform: translateY(10px) scale(0.96); }
}

/* Inside the pop the panel is the scroll container (consent AND transcript),
   so the log gives up its own cap — greeter.js scrolls the panel instead.
   The glass: a dark translucent base for contrast, a faint top-lit sheen, and
   the blurred, over-saturated page bleeding through from behind. */
.greeter-pop .greeter-panel {
  width: 100%;
  overflow-y: auto;
  overscroll-behavior: contain;
  background: var(--glass-fill);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  border: var(--glass-border);
  border-radius: 22px;
  box-shadow: var(--glass-light);
  /* Vertical padding is owned by the sticky bars — position:sticky cannot pin
     into a scroll container's padding zone, so any top/bottom padding here
     would let the transcript peek out above/below the bars. */
  padding: 0 22px;
}
/* Screens without the bottom bar (consent, resting) end flush otherwise. */
.greeter-pop .greeter-panel > :not(.greeter-dockbar):last-child { margin-bottom: 18px; }
/* (The base .greeter-panel look — solid fill, 3px accent top bar — now belongs
   only to the /contact intro card; the border shorthand above replaces all four
   sides for the glass pop.) */

/* Glassier innards: translucent bubbles and composer over the blurred pane. */
.greeter-pop .greeter-msg-you {
  background: rgba(255, 255, 255, 0.09);
  border-color: rgba(255, 255, 255, 0.14);
}

/* No backdrop-filter → no glass: keep every pane effectively solid so text
   never floats on raw page content. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .greeter-pop .greeter-panel,
  .greeter .greeter-panel { background: rgba(15, 15, 18, 0.97); }
  /* Closed is already a flat solid — only the open (glass) state needs it. */
  .greeter-fab[aria-expanded='true'] { background: rgba(15, 15, 18, 0.95); }
  .greeter-glass-btn { background: rgba(58, 60, 70, 0.95); }
}
.greeter-pop .greeter-log { max-height: none; overflow-y: visible; }

/* White accent means in-text links need a second signal beyond color. */
.greeter-pop .greeter-msg a,
.greeter-pop .greeter-sub a,
.greeter-pop .greeter-consent a,
.greeter-pop .greeter-foot a {
  text-decoration: underline;
  text-underline-offset: 2px;
}

@media (max-width: 640px) {
  .greeter-pop {
    right: max(10px, env(safe-area-inset-right));
    left: max(10px, env(safe-area-inset-left));
    width: auto;
    max-height: min(70vh, calc(100dvh - 110px));
  }
}

@media (prefers-reduced-motion: reduce) {
  .greeter-fab { transition: none; }
  .greeter-fab:hover, .greeter-fab:focus-visible { transform: none; }
  .greeter-pop:not([hidden]) { animation: none; }
}
