/* =====================================================================
   THE COMMUNITY — a full-bleed animated scene for terminaldeck.dev.

   Self-contained: this file and community-scene.js need nothing but the
   design tokens in app.css. Everything is namespaced `cs-`.

   Two rules, the same two the hero holds:

   1. This file describes SHAPE and REST only. There are no @keyframes
      and no transitions on anything the story touches. Every moving
      value arrives from community-scene.js as a transform, an opacity
      or a custom property, so the frame at t = 9.4s is the same frame
      every time and the loop can be scrubbed, paused and seeked.
   2. The composition is the frame. No card, no border, no rounded box
      around the scene — the person who is stuck, the thread, and the
      people who answer stand at real distances from each other across
      the whole width, which is what makes a reply crossing the field
      read as travel rather than decoration.

   Positions are --x / --y / --w percentages of the field, so the same
   objects re-form for a phone without a second set of components. The
   narrow block at the bottom is a REARRANGEMENT, not a shrink: the
   column runs in the order the story happens — the stuck session, the
   box you type in, the thread, then the people — and the answer travels
   back up the left of the field to the session that was stuck.
   ===================================================================== */

/* ---------------------------------------------------------------------
   THE STAGE
   --------------------------------------------------------------------- */
.cs-stage {
  position: relative;
  padding: var(--s-20) var(--s-8);
  overflow: hidden;              /* things enter and leave the frame */
  display: flex;
  isolation: isolate;
  background: var(--bg);
}
@media (max-width: 900px) { .cs-stage { padding: var(--s-16) var(--s-4) var(--s-12); } }

.cs-fld {
  position: relative;
  width: 100%;
  max-width: 1400px;
  margin-inline: auto;
  min-height: 400px;
}

.cs-scene { position: absolute; inset: 0; pointer-events: none; }
.cs-wires { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; pointer-events: none; }
.cs-packets { position: absolute; inset: 0; pointer-events: none; z-index: 5; }

.cs-obj { z-index: 2; will-change: transform, opacity; }
.cs-say { z-index: 4; }

/* the scene's one line of type — it stands in the field like an object,
   not above it in a column */
.cs-say { --x: 0; --y: 0; --w: 27%; }
.cs-say p {
  margin: 0;
  font-size: clamp(1.2rem, 0.72rem + 1.05vw, 1.8rem);
  line-height: 1.22; letter-spacing: -0.028em; font-weight: 545;
  color: var(--ink);
  max-width: 19ch;
}
.cs-say b { font-weight: 545; color: var(--accent); }

/* ---------------------------------------------------------------------
   WIRES — no line exists unless something is travelling on it. The faint
   resting set is there only to hold the composition together.
   --------------------------------------------------------------------- */
.cs-w-rest { fill: none; stroke: var(--ink); stroke-width: 1; opacity: 0.07; stroke-dasharray: 2 6; stroke-linecap: round; }
.cs-w-live { fill: none; stroke: var(--accent); stroke-width: 1.25; stroke-linecap: round; opacity: 0; }

/* travelling work ------------------------------------------------------ */
.cs-pk { position: absolute; left: 0; top: 0; display: grid; place-items: center; }
.cs-pk-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--accent); box-shadow: 0 0 0 5px var(--accent-soft); }
.cs-pk-chip {
  white-space: nowrap;
  font: 500 var(--t-2xs)/1 var(--font-mono);
  color: var(--accent);
  background: var(--surface);
  border: 1px solid var(--accent-line);
  border-radius: var(--r-pill);
  padding: 5px var(--s-2) 5px 6px;
  display: inline-flex; align-items: center; gap: 6px;
  box-shadow: var(--shadow-2);
}
.cs-pk-chip::before { content: ''; width: 5px; height: 5px; border-radius: 50%; background: var(--accent); flex: none; }

/* ---------------------------------------------------------------------
   PARTS — the same state vocabulary the product uses: working, needs
   you, done. A pip that is alive, a rail that moves, a tick that lands.
   --------------------------------------------------------------------- */
.cs-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-top: 1px solid var(--card-top, var(--line));
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-1);
}
/* DEPTH — one rule for everything that can be raised. --lift comes from
   the timeline: 0 at rest, 1 when the object has just been given work.
   In light that is a shadow lifting off the page; in dark (where the
   palette carries no drop shadows) it is the edge firming up, so an
   arrival reads as physical in both. */
.cs-lift::before {
  content: ''; position: absolute; inset: 0; border-radius: inherit;
  box-shadow: var(--shadow-2); opacity: var(--lift, 0); pointer-events: none;
}
.cs-lift::after {
  content: ''; position: absolute; inset: -1px; border-radius: calc(var(--r-lg) + 1px);
  border: 1px solid var(--line-strong); opacity: calc(var(--lift, 0) * 0.42); pointer-events: none;
}

.cs-pip { width: 7px; height: 7px; border-radius: 50%; position: relative; flex: none; }
.cs-pip::before { content: ''; position: absolute; inset: 0; border-radius: 50%; background: var(--ink-4); opacity: calc(0.42 + 0.28 * var(--live, 0)); }
.cs-pip::after  { content: ''; position: absolute; inset: -0.5px; border-radius: 50%; background: var(--accent); opacity: var(--live, 0); }

.cs-rail { height: 2px; border-radius: 2px; background: var(--line-soft); overflow: hidden; }
.cs-rail > i { display: block; height: 100%; background: var(--accent); transform: scaleX(0); transform-origin: left center; }

.cs-tick { width: 11px; height: 11px; flex: none; stroke: var(--ink-4); fill: none; opacity: 0; }

.cs-flag {
  justify-self: start;
  font: 500 var(--t-2xs)/1 var(--font-mono);
  border-radius: var(--r-pill); padding: 4px var(--s-2);
  color:      color-mix(in srgb, var(--ink-4)    calc(var(--calm, 0) * 100%), var(--accent));
  background: color-mix(in srgb, var(--surface-2) calc(var(--calm, 0) * 100%), var(--accent-soft));
  border: 1px solid color-mix(in srgb, var(--line) calc(var(--calm, 0) * 100%), var(--accent-line));
}

.cs-h {
  display: flex; align-items: center; gap: var(--s-2);
  font: 500 var(--t-xs)/1 var(--font-ui); color: var(--ink-2);
}
.cs-h > svg { width: 14px; height: 14px; flex: none; stroke: var(--ink-4); fill: none; }
.cs-h-note { margin-left: auto; font: 400 var(--t-2xs)/1 var(--font-mono); color: var(--ink-4); white-space: nowrap; }

.cs-agent { font: 500 var(--t-sm)/1.2 var(--font-mono); color: var(--ink); letter-spacing: -0.015em; }
.cs-acct {
  font: 400 var(--t-2xs)/1 var(--font-mono); color: var(--ink-4);
  border: 1px solid var(--line); border-radius: var(--r-pill); padding: 3px 6px; white-space: nowrap;
}
.cs-work {
  display: flex; align-items: center; gap: 6px; min-height: 1.35em;
  font: 400 var(--t-2xs)/1.35 var(--font-mono); color: var(--ink-3);
  white-space: nowrap; overflow: hidden;
}
.cs-work > span { min-width: 0; overflow: hidden; }

.cs-face {
  width: 22px; height: 22px; border-radius: 50%; flex: none; position: relative;
  display: grid; place-items: center;
  font: 500 10px/1 var(--font-ui); color: var(--ink-2);
  background: var(--surface-3); border: 1px solid var(--line);
}
.cs-face-you { font-size: 8px; letter-spacing: -0.02em; }
.cs-face::after {
  content: ''; position: absolute; inset: -3px; border-radius: 50%;
  border: 1.5px solid var(--accent); opacity: var(--ring, 0);
}

/* ---------------------------------------------------------------------
   THE SESSION THAT IS STUCK — the reason anyone asks anything
   --------------------------------------------------------------------- */
.cs-sess { --x: 0; --y: 26%; --w: 28%; padding: var(--s-3) var(--s-4) var(--s-4); display: grid; gap: var(--s-3); }
.cs-id { display: flex; align-items: center; gap: var(--s-2); }
.cs-id .cs-agent { flex: 1 1 auto; }

/* ---------------------------------------------------------------------
   WHERE THE QUESTION IS WRITTEN
   --------------------------------------------------------------------- */
.cs-bar {
  --x: 0; --y: 70%; --w: 28%;
  display: flex; align-items: flex-start; gap: var(--s-2);
  background: var(--surface); border: 1px solid var(--line);
  border-top: 1px solid var(--card-top, var(--line));
  border-radius: var(--r-md); padding: var(--s-3) var(--s-3) var(--s-3) var(--s-4);
  box-shadow: var(--shadow-1);
}
.cs-bar::after {
  content: ''; position: absolute; inset: -3px; border-radius: calc(var(--r-md) + 3px);
  border: 1px solid var(--accent-line); box-shadow: 0 0 0 3px var(--accent-soft);
  opacity: var(--focus, 0); pointer-events: none;
}
.cs-bar-t {
  flex: 1 1 auto; min-width: 0; min-height: 2.9em;
  font: 400 var(--t-md)/1.5 var(--font-mono); color: var(--ink);
  white-space: pre-wrap; overflow-wrap: break-word;
}
.cs-bar-t { position: relative; }
.cs-bar-t em {
  position: absolute; left: 0; top: 0; font-style: normal; color: var(--ink-4);
}
.cs-caret { display: inline-block; width: 1.5px; height: 1.05em; background: var(--accent); vertical-align: -2px; opacity: 0; }
.cs-post {
  flex: none; position: relative; align-self: flex-end; overflow: hidden;
  font: 500 var(--t-xs)/1 var(--font-ui);
  border: 1px solid var(--line-strong); border-radius: var(--r-sm); padding: 7px var(--s-2);
  background: var(--surface-2);
}
.cs-post::before { content: ''; position: absolute; inset: -1px; background: var(--accent); opacity: var(--on, 0); }
.cs-post > span { position: relative; color: color-mix(in srgb, var(--accent-fg) calc(var(--on, 0) * 100%), var(--ink-2)); }

/* ---------------------------------------------------------------------
   THE THREAD
   --------------------------------------------------------------------- */
.cs-feed { --x: 32%; --y: 3%; --w: 36%; padding: var(--s-3) var(--s-4) var(--s-4); display: grid; gap: var(--s-3); }

.cs-q-slot {
  position: absolute; inset: 0; border-radius: var(--r-md);
  background: color-mix(in srgb, var(--ink) 4%, transparent);
}
.cs-q-wrap { position: relative; }
.cs-q {
  display: grid; grid-template-columns: auto 1fr; gap: var(--s-3); align-items: start;
  border: 1px solid var(--line); border-radius: var(--r-md); background: var(--surface-2);
  padding: var(--s-3);
}
.cs-q-t { display: block; font: 500 var(--t-sm)/1.4 var(--font-ui); color: var(--ink); letter-spacing: -0.012em; min-height: 1.4em; }
.cs-q-m { display: block; font: 400 var(--t-2xs)/1 var(--font-mono); color: var(--ink-4); margin-top: 6px; min-height: 1em; }

/* the replies area exists before the replies do, so nothing in this
   scene ever changes layout — and while it is empty it says so, rather
   than sitting as a white hole for three seconds */
.cs-replies { position: relative; display: grid; gap: 7px; align-content: start; }
.cs-slots { position: absolute; inset: 0; display: grid; gap: 7px; align-content: start; pointer-events: none; }
.cs-slots > i {
  display: block; height: var(--slotH, 51px); border-radius: var(--r-md);
  background: color-mix(in srgb, var(--ink) 4%, transparent);
}

.cs-r {
  position: relative;
  display: grid; grid-template-columns: auto 1fr; gap: var(--s-3); align-items: start;
  border: 1px solid var(--line-soft); border-radius: var(--r-md); background: var(--surface);
  padding: 9px var(--s-3);
}
/* the marked reply passes over its neighbour on the way to the top */
.cs-r-ans { z-index: 2; }
.cs-r::before {
  content: ''; position: absolute; inset: -1px; border-radius: calc(var(--r-md) + 1px);
  border: 1px solid var(--accent-line); box-shadow: var(--shadow-2);
  background: var(--surface); opacity: var(--mark, 0); pointer-events: none;
}
.cs-r-txt { min-width: 0; position: relative; }
.cs-r > .cs-face { position: relative; }
.cs-r-who { display: block; font: 400 var(--t-2xs)/1 var(--font-mono); color: var(--ink-4); margin-bottom: 4px; }
.cs-r-t { display: block; font: 400 var(--t-xs)/1.45 var(--font-ui); color: var(--ink-2); }

.cs-badge {
  position: absolute; right: var(--s-3); top: -9px; z-index: 3;
  display: inline-flex; align-items: center; gap: 5px;
  font: 500 9px/1 var(--font-mono); color: var(--accent-fg); background: var(--accent);
  border-radius: var(--r-pill); padding: 4px 7px; white-space: nowrap;
}
.cs-badge svg { width: 9px; height: 9px; stroke: currentColor; fill: none; stroke-width: 3; }

/* ---------------------------------------------------------------------
   THE PEOPLE — every reply leaves one of them and travels
   --------------------------------------------------------------------- */
.cs-people { --x: 78%; --y: 36%; --w: 22%; display: grid; gap: 7px; align-content: start; }
.cs-p {
  display: flex; align-items: center; gap: var(--s-2);
  border: 1px solid var(--line-soft); border-radius: var(--r-pill); background: var(--surface);
  padding: 5px var(--s-3) 5px 5px;
}
.cs-p b { font: 400 var(--t-2xs)/1 var(--font-mono); color: var(--ink-3); font-weight: 400; }
.cs-p-note { margin-left: auto; font: 400 9px/1 var(--font-mono); color: var(--ink-4); white-space: nowrap; }

/* =====================================================================
   NARROW — the same story, re-formed for a tall field. Not the wide
   layout shrunk: the column runs in the order the story happens —
   the session that is stuck, the box you type in, the thread, then the
   people who answer — so replies travel UP into the thread and the
   answer travels back up past the box to the session it unblocks.
   Measured at 390 x 844.
   ===================================================================== */
@media (max-width: 860px) {
  .cs-fld { min-height: 732px; }

  .cs-say    { --x: 0; --y: 0;     --w: 100%; }
  .cs-sess   { --x: 0; --y: 6%;    --w: 100%; }
  .cs-bar    { --x: 0; --y: 27.5%; --w: 100%; }
  .cs-feed   { --x: 0; --y: 42%;   --w: 100%; }
  .cs-people { --x: 0; --y: 91%;   --w: 100%; grid-auto-flow: column; grid-auto-columns: 1fr; gap: 6px; }

  .cs-say p { max-width: none; }
  .cs-sess, .cs-feed { padding: 10px 12px 12px; gap: 10px; }
  .cs-bar-t { min-height: 4.3em; }
  .cs-q-t { font-size: var(--t-xs); }
  .cs-r-t { font-size: var(--t-2xs); }
  .cs-r { padding: 8px 10px; gap: var(--s-2); }

  /* a person becomes a stacked chip so four of them fit a phone */
  .cs-p { flex-direction: column; gap: 4px; padding: 7px 4px; border-radius: var(--r-md); }
  .cs-p b { font-size: 9px; }
  .cs-p-note { margin-left: 0; font-size: 8px; }
}

/* =====================================================================
   REDUCED MOTION — community-scene.js paints one composed still instead
   of running the clock. Nothing here needs to change; this block only
   makes sure the still is never mistaken for a stalled animation.
   ===================================================================== */
@media (prefers-reduced-motion: reduce) {
  .cs-obj, .cs-say { will-change: auto; }
}

/* -----------------------------------------------------------------------
   PLACEMENT, LAST WORD. This rule must outrank any `position: relative` a
   card sets for its own pseudo-elements — same specificity, so order
   decides. If it loses, every object falls back into flow and its --y
   silently becomes an offset instead of a position.
   ----------------------------------------------------------------------- */
.cs-obj, .cs-say {
  position: absolute;
  left: var(--x, 0); top: var(--y, 0); width: var(--w, 22%);
}
