/* kept. marketing widgets: five previews of five real product screens.
   Every measurement below is TRANSCRIBED from the component that draws it in
   apps/web, and the file each block came from is named above it. Nothing here is
   designed for this site: if a number disagrees with the app, the app is right and
   this file is the bug. Canned data, nothing live.

   The dark cards are black regardless of page theme, because the screens they
   preview are the app in its dark theme, so their colors are the app's dark tokens
   written out rather than the page's own vars. The coverage widget is the one
   exception: it previews a light-theme screen and reads the page tokens. */

/* ---------------- shrink-to-fit ---------------- */
/* Renders a widget at the REAL screen's own width and scales it down to the width
   the section gives it: identical layout to the app, just smaller (owner call,
   2026-08-28: the sections keep their current widths, so the screens scale). */
.fit { width: 100%; min-width: 0; max-width: 100%; }
.fit-inner { transform-origin: top left; }

/* ---------------- scroll-progress 3D stage ---------------- */
/* Each widget floats over a blurred ground shadow that slides and tightens as
   the card tilts flat, plus a faint warm ember ambience behind it. */
.fx3d { perspective: 1400px; min-width: 0; max-width: 100%; }
.fx3d-stack { position: relative; min-width: 0; }
.fx3d-glow {
  position: absolute; inset: -10% -14%; pointer-events: none; opacity: 0;
  background: radial-gradient(52% 58% at 50% 62%, rgba(226, 127, 72, 0.12), rgba(226, 127, 72, 0) 72%);
  filter: blur(4px);
}
.fx3d-body { position: relative; transform-origin: 50% 0%; transform-style: preserve-3d; will-change: transform, opacity; opacity: 0.001; }
.fx3d-ground { position: relative; height: 0; }
.fx3d-shadow {
  position: absolute; left: 7%; right: 7%; top: 22px; height: 58px; border-radius: 999px;
  background: radial-gradient(50% 100% at 50% 0%, rgba(17, 24, 39, 0.32), rgba(17, 24, 39, 0) 72%);
  filter: blur(15px); will-change: transform, opacity; pointer-events: none; opacity: 0;
}
/* The hero jar: floats in perspective like a standing artifact, breathing
   gently, and flattens to face the reader as they begin to scroll. */
.fxhero { position: relative; perspective: 1400px; }
.fxhero-glow {
  position: absolute; inset: -14% -18%; pointer-events: none;
  background: radial-gradient(50% 55% at 50% 64%, rgba(226, 127, 72, 0.14), rgba(226, 127, 72, 0) 70%);
  filter: blur(4px);
}
.fxhero-body { position: relative; transform-origin: 50% 34%; will-change: transform; }
.fxhero-shadow {
  position: absolute; left: 9%; right: 9%; top: 24px; height: 60px; border-radius: 999px;
  background: radial-gradient(50% 100% at 50% 0%, rgba(17, 24, 39, 0.30), rgba(17, 24, 39, 0) 72%);
  filter: blur(16px); will-change: transform, opacity; pointer-events: none;
}

/* ---------------- the app's dark tokens, written out ----------------
   Verbatim from apps/web/src/styles/global.css :root[data-theme="dark"]. The dark
   widgets are the app on a light page, so they cannot read the page's vars. */
.pw {
  --w-bg: #000000;
  --w-surface: #000000;
  --w-surface-2: #121212;
  --w-chat-bg: #161616;
  --w-chat-border: #343434;
  --w-text: #f8fafc;
  --w-text-muted: rgba(248, 250, 252, 0.64);
  --w-text-faint: rgba(248, 250, 252, 0.42);
  --w-border: rgba(255, 255, 255, 0.14);
  --w-border-2: rgba(255, 255, 255, 0.24);
  --w-border-faint: rgba(255, 255, 255, 0.09);
  --w-cell-track: rgba(255, 255, 255, 0.05);
  --w-cell-edge: rgba(255, 255, 255, 0.24);
  --w-ember-soft: rgba(226, 127, 72, 0.16);
  --w-bubble-user: #1f1f1f;
  --w-stone: #667085;
  --w-cream: #f8fafc;
  background: var(--w-bg);
  color: var(--w-text);
  border-radius: 16px;
  border: 1px solid rgba(255, 255, 255, 0.14);
  box-shadow: 0 32px 80px rgba(17, 24, 39, 0.16);
}

/* ---------------- pieces the app shares across screens ---------------- */

/* Caps: ui/brand.tsx. 10.5px / 700 / 0.18em, --stone unless a caller recolors it. */
.caps { font-size: 10.5px; font-weight: 700; letter-spacing: 0.18em; text-transform: uppercase; color: var(--w-stone, #667085); }

/* GridCell / LiveJarCells Box: features/jar/JarGrid.tsx and features/calls/LiveJarCells.tsx.
   34px tall, 3px radius, a 1px --cell-edge hairline over --cell-track, clipping a
   bottom-up ember fill. The wrapper is unclipped so the landing ripple can bloom
   past the box edge, exactly as LiveJarCells splits them. */
.mcell-wrap { position: relative; }
.mcell {
  position: relative; display: block; height: 34px; border-radius: 3px;
  border: 1px solid var(--w-cell-edge); background: var(--w-cell-track); overflow: hidden;
}
/* The hairline ember edge marking where the last piece landed. Static: the ripple
   already announced the arrival (LiveJarCells.tsx). */
.mcell.newest { border-color: var(--ember); }
.mcell i {
  position: absolute; left: 0; right: 0; bottom: 0; height: 0; display: block;
  background: var(--ember); transform-origin: bottom;
  transition: height 520ms var(--spring);
}
/* The standing jar fills slower than the live one: STANDING_FILL 560ms (JarGrid.tsx). */
.wjar .mcell i { transition: height 560ms var(--spring); }
/* The k. seal a full box earns, JarGrid.tsx GridCell badge / LiveJarCells SealBadge. */
.mcell b {
  position: absolute; top: 3px; right: 3px; width: 15px; height: 15px; border-radius: 999px;
  background: rgba(0, 0, 0, 0.86); border: 1.3px solid #000000; display: grid; place-items: center;
  animation: seal-pop 360ms var(--spring) both;
  font-weight: 700; font-size: 9.5px; letter-spacing: -0.05em; color: var(--w-cream); line-height: 1;
}
/* FlashRing: the per-unit ripple, global.css live-cell-flash, 700ms ease-out. */
.mcell-flash {
  position: absolute; inset: 0; border-radius: 3px; pointer-events: none;
  animation: live-cell-flash 700ms ease-out;
}

/* The task x region grid's own track: LABEL_W 172, CELL_W 96, 8px gaps. Do not make
   the cells fluid: the product's grid is a fixed one, and a fluid copy of it stops
   being a preview of the same screen (JarGrid.tsx GRID_COLS). */
.wjar-cols, .wjar-row { display: grid; grid-template-columns: 172px repeat(6, 96px); gap: 8px; }
.wjar-cols { margin-bottom: 8px; }
.wjar-col { font-size: 10px; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; color: var(--w-text); text-align: center; line-height: 1.3; }
.wjar-rows { display: flex; flex-direction: column; gap: 8px; }
.wjar-row { align-items: center; }
.wjar-task { font-size: 13px; font-weight: 500; color: var(--w-text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; padding-right: 10px; }

/* ---------------- widget 1: the standing jar ----------------
   features/jar/JarView.tsx (the page header) + JarGrid.tsx (everything below it).
   Card padding is the widget's own frame; every number inside it is the app's. */
.wjar { padding: 30px 38px; overflow: hidden; }

/* SurfaceHeader, ui/cards.tsx: flex-start, space-between, gap 22, 28px under it. */
.wjar-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 22px; margin-bottom: 28px; }
.wjar-heading { min-width: 0; }
.wjar-title { font-size: 30px; font-weight: 500; letter-spacing: -0.015em; margin: 6px 0 0; }
/* No font-weight: the app's copy inherits the body's 400, and 500 here made the
   sentence a step heavier than the screen it previews. */
.wjar-copy { font-size: 14px; line-height: 1.55; color: var(--w-text-muted); margin: 8px 0 0; max-width: 720px; }
/* JarWayOut, JarView.tsx: 38 square, 10px radius, a --border hairline, muted glyph. */
.wjar-ways { display: flex; gap: 10px; flex-shrink: 0; }
.wjar-way {
  width: 38px; height: 38px; display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--w-border); border-radius: 10px; color: var(--w-text-muted);
}
/* The legend: what a box means, and the nothing -> full scale beside it. */
.wjar-legend { display: flex; align-items: center; justify-content: space-between; gap: 18px; flex-wrap: wrap; margin-top: 14px; }
.wjar-legend-note { font-size: 12.5px; font-weight: 500; font-style: italic; color: var(--w-text-muted); margin: 0; max-width: 430px; }
.wjar-scale { display: flex; align-items: center; gap: 10px; margin-left: auto; }
/* JarGrid passes c="var(--text-muted)" here, not the Caps default stone. */
.wjar-scale .caps { color: var(--w-text-muted); letter-spacing: 0.14em; font-size: 10px; }
.wjar-swatches { display: inline-flex; gap: 4px; }
.wjar-sw {
  width: 22px; height: 15px; border-radius: 2px; background: var(--w-cell-track);
  border: 1px solid var(--w-cell-edge); position: relative; overflow: hidden; display: block;
}
.wjar-sw i { position: absolute; left: 0; right: 0; bottom: 0; background: var(--ember); display: block; }
/* The cross-cutting pieces that belong to no single task. */
.wjar-chips { margin-top: 28px; }
.wjar-chiprow { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 14px; }
/* ChipPill, JarGrid.tsx: 36 tall, 4px radius, 0 16 padding. */
.wjar-chip {
  display: inline-flex; align-items: center; height: 36px; padding: 0 16px; border-radius: 4px;
  background: var(--w-cell-track); border: 1px solid var(--w-cell-edge);
  font-size: 13px; font-weight: 500; color: var(--w-text);
}

/* ---------------- widget 2: the live call ----------------
   features/calls/CallsView.tsx, the "listening" stage, at its own LIVE_FRAME_W of
   1160: a left-aligned status row, then the jar beside the reading rail. The old
   portrait card (a centred hero, a "your knowledge, filling in" band with a dot, no
   rail) was not this screen; LiveJar.tsx states in as many words that the in-call jar
   carries "no section chrome, no dot, no label". */
.wcall { padding: 24px 28px 28px; display: flex; flex-direction: column; gap: 20px; overflow: hidden; }
.wcall-status { flex-shrink: 0; }
.wcall-row { display: flex; align-items: center; gap: 14px; }
/* The one live dot on this surface, CallsView.tsx + global.css .kept-live-dot: the
   dot itself never moves; a single soft ring travels out of it on a 2.6s beat. */
.wcall-dot {
  display: inline-block; width: 10px; height: 10px; border-radius: 999px;
  flex-shrink: 0; background: var(--ember);
  animation: kept-live-ring 2.6s var(--spring) infinite;
}
.wcall-state { font-size: 21px; font-weight: 500; letter-spacing: -0.015em; margin: 0; }
.wcall-timer { font-size: 13.5px; font-weight: 600; color: var(--w-text-muted); font-variant-numeric: tabular-nums; }
.wcall-controls { margin-left: auto; display: flex; gap: 12px; justify-content: center; align-items: center; }
/* LiveCallControls `control`: btnGhost (ui/styles.ts) at the call's own height. */
.wcall-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 9px;
  height: 42px; min-width: 104px; padding: 0 20px;
  border: 1px solid var(--w-border-2); border-radius: 8px; background: transparent;
  font-size: 15px; font-weight: 600; color: var(--w-text);
}
.wcall-end {
  height: 42px; padding: 0 14px; display: inline-flex; align-items: center;
  border: none; background: transparent; border-radius: 8px;
  font-size: 14.5px; font-weight: 600; color: var(--w-text-muted);
}
.wcall-note { font-size: 13px; font-weight: 500; color: var(--w-text-faint); margin-top: 8px; }

/* The jar and the rail, side by side. LIVE_FRAME_GUTTER is 24. */
.wcall-body {
  flex: 1; min-height: 0; display: flex; flex-direction: column; gap: 24px;
  align-items: stretch;
  /* The app scrolls this column, because there a transcript grows without limit. Here
     the jar is a fixed five rows and the rail has RAIL_STACKED's definite height, so it
     can never overflow: `auto` only ever bought a 1px rounding artifact and the
     horizontal bar that came with it. */
  overflow: hidden;
}
.wcall-jarcol { flex: 0 0 auto; min-width: 0; display: flex; justify-content: center; align-items: flex-start; }
/* JAR_W = the 796px grid + the scroll window's 16px right padding + its 8px gutter. */
.wcall-jar { width: 820px; }
.wcall-jar .wjar-cols { width: 796px; }
/* .live-jar-scroll, global.css: a five-row window with 14px of glow headroom either
   side, the top headroom reclaimed by a negative margin so the rows stay under the
   headers.
   THE HEIGHT HOLDS ALL FIVE ROWS AND DOES NOT SCROLL. The window is VISIBLE_ROWS tall
   and the widget has exactly VISIBLE_ROWS rows, so a scrollbar here is the window
   failing to hold its own contents, not the jar having more to show. Both paddings are
   inside the box (`* { box-sizing: border-box }`), so the height is the headroom, the
   rows, and the gaps between them: 14 + 5*34 + 4*8 + 14.
   The 8px gutter stays reserved even though nothing scrolls, because JAR_W is the grid
   plus this padding plus that gutter, and giving it back would move the jar 8px out of
   the frame's own arithmetic. Reserved is not drawn: with nothing overflowing there is
   no bar. */
.wcall-jarwin {
  position: relative; display: flex; flex-direction: column; gap: 8px;
  max-height: 230px; max-width: 820px;
  overflow-y: auto; overflow-x: hidden; scrollbar-gutter: stable;
  padding: 14px 16px 14px 0; margin-top: -14px;
}
.wcall-jarwin::-webkit-scrollbar { width: 8px; }
.wcall-jarwin::-webkit-scrollbar-thumb { background: var(--w-border-2); border-radius: 4px; }
.wcall-jarwin::-webkit-scrollbar-track { background: transparent; }
.wcall-jarwin .wjar-row { animation: screen-in 300ms ease-out; }
/* The live jar's role-wide chips: LiveJar.tsx, 22px above, 12px under the label. */
.wcall-chips { margin-top: 22px; }
.wcall-chiprow { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 12px; }
/* LiveJarCells Chip: 34 tall, 4px radius, 0 15 padding, an --ember-soft bottom fill. */
.wcall-chip {
  position: relative; display: inline-flex; align-items: center; height: 34px; padding: 0 15px;
  border-radius: 4px; background: var(--w-cell-track); border: 1px solid var(--w-cell-edge);
  overflow: hidden; font-size: 13px; font-weight: 500; color: var(--w-text);
}
.wcall-chip i {
  position: absolute; left: 0; right: 0; bottom: 0; display: block;
  background: var(--w-ember-soft); transform-origin: bottom;
  transition: height 520ms var(--spring); pointer-events: none;
}
.wcall-chip span { position: relative; }

/* LiveRail.tsx: a fixed 316px column, its own border and 8px radius. */
/* 320px is a readable pane (about eight turns) that still leaves the jar's five-row
   fold on screen, which is RAIL_STACKED's own reasoning. */
.wcall-rail {
  width: 100%; flex-shrink: 0; align-self: auto; height: 320px; display: flex; flex-direction: column;
  min-height: 0; border: 1px solid var(--w-border); border-radius: 8px; background: var(--w-surface);
}
.wcall-tabs { display: flex; align-items: center; gap: 4px; padding: 0 12px; border-bottom: 1px solid var(--w-border); flex-shrink: 0; }
/* A real control, with the product's own `cursor: pointer` on it (LiveRail TAB). */
.wcall-tab {
  font-size: 10.5px; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--w-stone); padding: 12px 6px; border: none; border-bottom: 2px solid transparent;
  background: transparent; font-family: inherit; cursor: pointer;
}
.wcall-tab:focus-visible { outline: 2px solid var(--ember); outline-offset: 1px; }
.wcall-tab.on { color: var(--w-text); border-bottom-color: var(--ember); }
.wcall-count { margin-left: auto; font-size: 12px; font-weight: 600; color: var(--w-text-muted); font-variant-numeric: tabular-nums; }
.wcall-pane { flex: 1; min-height: 0; overflow: hidden; padding: 14px 14px 18px; }
/* LiveTranscript.tsx: a labeled line per turn, never a bubble. */
.wcall-turns { display: flex; flex-direction: column; gap: 12px; }
.wcall-turn { font-size: 13.5px; line-height: 1.5; color: var(--w-text-muted); }
.wcall-turn.you { color: var(--w-text); }
.wcall-turn b { font-weight: 700; text-transform: uppercase; font-size: 10.5px; letter-spacing: 0.08em; margin-right: 8px; }
/* LiveCapturePanel.tsx: a claim in the partner's own words over a task/region tag. */
.wcall-cards { display: flex; flex-direction: column; gap: 10px; }
.wcall-card {
  border: 1px solid var(--w-cell-edge); border-radius: 6px; padding: 11px 12px;
  background: var(--w-cell-track); animation: rise-in 320ms var(--spring);
}
.wcall-card .claim { font-size: 13.5px; font-weight: 500; line-height: 1.5; color: var(--w-text); }
.wcall-card .tag { margin-top: 6px; font-size: 10.5px; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase; color: var(--w-stone); }
.wcall-prov { margin-top: 2px; font-size: 12.5px; font-weight: 500; font-style: italic; color: var(--w-text-faint); }

/* ---------------- shared chat pieces ----------------
   features/chat/messages.tsx, richtext-blocks.tsx, evidence.tsx, message-actions.tsx.
   Used by both the Ask widget and the crux panes, so the two cannot drift. */

/* The sent question: messages.tsx. The row is 82% and holds the bubble plus its
   action row, right-aligned; the bubble itself is --bubble-user with 18px corners. */
.msg-you { align-self: flex-end; max-width: 82%; display: flex; flex-direction: column; align-items: flex-end; }
.msg-you .bubble {
  background: var(--w-bubble-user); color: var(--w-text);
  padding: 12px 16px; border-radius: 18px; font-size: 15px; font-weight: 500; line-height: 1.5;
  white-space: pre-wrap; overflow-wrap: break-word; word-break: break-word;
  animation: kept-part-in 300ms var(--spring) both;
}
/* UserActions: gap 2, 4px under the bubble (message-actions.tsx). */
.msg-youacts { display: flex; align-items: center; gap: 2px; margin-top: 4px; }

/* An ANSWER IS NOT A BUBBLE: flowing text at 94% of the column (messages.tsx). */
.msg-a {
  align-self: flex-start; max-width: 94%; font-size: 15px; line-height: 1.6; color: var(--w-text);
  overflow-wrap: break-word; word-break: break-word;
  animation: kept-part-in 300ms var(--spring) both;
}
/* renderParagraph: BLOCK_GAP above, 1.62 inside, and the body's own 400 weight. */
.msg-a p { margin: 12px 0 0; line-height: 1.62; }
/* renderHeading level 2: 19px / 650 / 1.3 / -0.01em, SECTION_GAP above. */
.msg-a .a-h { font-size: 19px; font-weight: 650; line-height: 1.3; letter-spacing: -0.01em; margin: 22px 0 0; }
.msg-a p.first, .msg-a .a-h.first { margin-top: 0; }
/* The quiet row under an answer: copy, the two ratings, then which seat wrote it. */
.msg-acts { display: flex; align-items: center; gap: 2px; margin-top: 8px; }
.msg-act { width: 28px; height: 28px; border-radius: 7px; display: grid; place-items: center; color: var(--w-text-muted); }
.msg-seat { margin-left: 6px; font-size: 11.5px; font-weight: 500; color: var(--w-text-muted); opacity: 0.8; white-space: nowrap; }
/* SeatName, features/chat/seat-name.tsx: the NAME is heavy in the row's own color and
   the qualifier is thin and mixed back toward the background. */
.msg-seat .nm { font-weight: 600; }
.msg-seat .ql { font-weight: 400; color: color-mix(in srgb, currentColor 64%, transparent); }

/* Evidence, features/chat/evidence.tsx. */
.ev-toggle {
  display: block; margin-top: 10px; border: none; background: transparent; padding: 0; cursor: pointer;
  font-family: inherit; font-size: 10.5px; font-weight: 600; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--w-stone);
}
.ev-body {
  margin-top: 8px; padding-top: 10px; border-top: 1px solid var(--w-border-2);
  display: flex; flex-direction: column; gap: 14px; animation: kept-part-in 300ms var(--spring) both;
}
/* One group per part of the work, the jar's own six columns in the grid's order. */
.ev-group { display: flex; flex-direction: column; gap: 10px; }
.ev-glabel { font-size: 11.5px; font-weight: 600; color: var(--w-text-muted); }
/* A quote carries no source line: sourceLabel() returns "" for the partner's own
   captured words, so the group heading is what says where they came from. */
.ev-quote { font-size: 13.5px; font-weight: 500; font-style: italic; color: var(--w-stone); line-height: 1.5; margin: 0; }

/* The wait, features/chat/thinking-path.tsx + thinking-line.tsx: ONE row, 20px tall,
   the three-dot mark beside the topic the send is on. No wordmark: the app deleted it
   (owner ruling 2026-08-07), and no status pill either. */
.thinking { position: relative; height: 20px; width: 100%; align-self: flex-start; }
.thinking-row {
  display: flex; align-items: flex-start; gap: 9px; font-size: 13.5px; line-height: 1.45;
  color: var(--w-text); animation: kept-part-in 240ms var(--spring) both;
}
.thinking-mark { display: inline-flex; align-items: center; justify-content: center; width: 13px; height: 19px; flex-shrink: 0; }
.thinking-row span.words { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* The ember band travelling through the words, global.css .kept-step-shimmer. */
.kept-step-shimmer {
  --kept-wave: 7em;
  background: linear-gradient(90deg, var(--w-text) 0%, var(--ember) 25%, var(--ember) 50%, var(--w-text) 75%, var(--w-text) 100%);
  background-size: var(--kept-wave) 100%;
  background-repeat: repeat-x;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  animation: kept-shimmer var(--kept-wait-cycle, 0.9s) cubic-bezier(0.3, 0.1, 0.7, 0.9) infinite;
}
.kept-step-trio circle { animation: kept-trio var(--kept-wait-cycle, 0.9s) ease-in-out infinite backwards; }

/* ---------------- widget 3: the crux ----------------
   Two Ask threads at once. The panes are the chat surface above, so nothing here
   restyles a message: only the stage the two sit on. */
.crux { display: grid; grid-template-columns: 1fr 210px 1fr; align-items: center; transform-style: preserve-3d; }
.crux-pane {
  /* 360, measured: a pane's tallest exchange is 276px, and the label and the 24px of
     padding above and below it take the rest. At 330 the top of the question was
     shaved by 24px, which is the same cropped-screen fault the Ask widget had. */
  padding: 24px 26px; height: 360px; overflow: hidden; display: flex; flex-direction: column;
  opacity: 0.72; will-change: transform;
  transition: transform 500ms var(--spring), opacity 500ms var(--spring), border-color 500ms var(--spring), box-shadow 500ms var(--spring);
}
.crux-pane--l { transform: rotateY(7deg) scale(0.975); }
.crux-pane--r { transform: rotateY(-7deg) scale(0.975); }
.crux-pane.on { opacity: 1; border-color: var(--ember); box-shadow: 0 24px 70px rgba(17, 24, 39, 0.22), 0 0 0 4px rgba(226, 127, 72, 0.10); }
.crux-pane--l.on { transform: rotateY(7deg) scale(1); }
.crux-pane--r.on { transform: rotateY(-7deg) scale(1); }
.crux-pane:hover { opacity: 1; transform: rotateY(0deg) scale(1.03); }
/* Whose thread this is. The site's own label, not a control the app draws, so it is
   set apart from the screen below it rather than dressed as part of one. */
.crux-label { flex-shrink: 0; margin-bottom: 14px; text-align: right; font-size: 10.5px; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase; color: var(--w-stone); transition: color 400ms ease; }
.crux-pane.on .crux-label { color: var(--ember); }
/* The thread column, on the app's own rule: `min(760px, 100% - 48px)` centred, so a
   pane narrower than the full measure renders exactly what the app renders in a
   narrow window rather than a measure the product never draws. COLUMN_GAP is 18. */
.crux-feed {
  width: min(760px, 100% - 48px); margin: 0 auto;
  flex: 1; min-height: 0; display: flex; flex-direction: column; gap: 18px;
  justify-content: flex-end; overflow: hidden;
}
/* the connector: an ember light travels to whichever side is asking */
.crux-rail { position: relative; height: 2px; background: rgba(17, 24, 39, 0.14); border-radius: 999px; z-index: 2; }
.crux-light {
  position: absolute; top: -1px; bottom: -1px; width: 76px; border-radius: 999px; left: 2px;
  background: linear-gradient(90deg, rgba(226, 127, 72, 0.15), var(--ember), rgba(226, 127, 72, 0.15));
  box-shadow: 0 0 10px 2px rgba(226, 127, 72, 0.3);
  transition: left 1000ms var(--spring), top 1000ms var(--spring), box-shadow 500ms ease;
}
.crux[data-active="me"] .crux-light { left: calc(100% - 78px); }
.crux-light.flash { box-shadow: 0 0 18px 4px rgba(226, 127, 72, 0.5); }

/* ---------------- widget 4: Ask ----------------
   features/chat/ChatTitleBar.tsx, ThreadMessages.tsx and composer.tsx, at the
   conversation column's own 760px measure plus its 48px of gutter. */
.whon { height: 560px; padding: 0 0 24px; width: 100%; display: flex; flex-direction: column; }
/* ChatTitleBar: the column, 28px above the row and 14px under it. */
.whon-bar { width: min(760px, 100% - 48px); margin: 0 auto; padding: 28px 0 14px; flex-shrink: 0; }
.whon-barrow { display: flex; align-items: center; gap: 10px; justify-content: space-between; }
/* iconBtn("ghost") + an 8px radius: 38 square, a --border-2 hairline, no fill. */
.whon-iconbtn {
  width: 38px; height: 38px; border-radius: 8px; border: 1px solid var(--w-border-2);
  background: transparent; display: grid; place-items: center; color: var(--w-text); flex-shrink: 0;
}
.whon-namewrap { min-width: 0; flex: 1; }
.whon-name {
  font-size: 24px; font-weight: 500; letter-spacing: -0.02em; line-height: 1.28; color: var(--w-text);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* btnGhost at 38 tall with 13px of side padding (ChatTitleBar.tsx New chat). */
.whon-newchat {
  display: inline-flex; align-items: center; gap: 9px; height: 38px; padding: 0 13px; border-radius: 8px;
  border: 1px solid var(--w-border-2); background: transparent; font-size: 13.5px; font-weight: 600;
  color: var(--w-text); flex-shrink: 0;
}
/* The conversation column: 760 wide, 18px between rows (ThreadMessages.tsx). */
.whon-feed {
  width: min(760px, 100% - 48px); margin: 0 auto; padding: 4px 0 10px; flex: 1; min-height: 0;
  display: flex; flex-direction: column; gap: 18px; justify-content: flex-end; overflow: hidden;
}
/* The composer, composer.tsx: --chat-input-bg behind a --chat-input-border hairline.
   Focus brightens the gray hairline, never a color tone (owner ruling, 2026-07-17). */
.whon-boxwrap { width: min(760px, 100% - 48px); margin: 18px auto 0; flex-shrink: 0; }
.whon-box {
  min-width: 380px; background: var(--w-chat-bg); border: 1px solid var(--w-chat-border);
  border-radius: 10px; transition: border-color 180ms var(--spring);
}
.whon-box.is-focus { border-color: var(--w-border-2); }
.whon-row { display: flex; flex-wrap: nowrap; align-items: center; gap: 8px; min-height: 54px; padding: 0 8px; }
/* roundBtn: ROUND_BTN.size 38, a full-round hover target, no border (composer.tsx). */
.whon-round { width: 38px; height: 38px; border-radius: 999px; display: grid; place-items: center; color: var(--w-text); flex-shrink: 0; }
/* ComposerField: a zero flex-basis with a 160px floor, and TEXT_INSET (38-18)/2 of
   padding on each side so the first character lines up under the plus glyph. */
.whon-field {
  flex: 1 1 0; min-width: 160px; display: flex; align-items: center;
  padding: 0 10px; font-size: 15px; font-weight: 500; line-height: 22px; color: var(--w-text);
  white-space: nowrap; overflow: hidden;
}
.whon-ph { color: var(--w-text-faint); }
.whon-typed { white-space: pre; }
.whon-typed:not(:empty)::after {
  content: ''; display: inline-block; width: 1.5px; height: 17px; margin-left: 1px;
  background: var(--ember); vertical-align: -3px; animation: cf-caret 0.9s steps(1) infinite;
}
/* The model chip: 34 tall, no border, the seat name then the chevron (composer.tsx). */
.whon-model {
  display: inline-flex; align-items: center; gap: 5px; height: 34px; padding: 0 8px 0 10px;
  border: none; border-radius: 8px; font-size: 13px; font-weight: 600; color: var(--w-text);
  white-space: nowrap; flex-shrink: 1; min-width: 0;
}
.whon-model .nm { font-weight: 600; }
.whon-model .ql { font-weight: 400; color: color-mix(in srgb, currentColor 64%, transparent); }
.whon-model svg { flex-shrink: 0; color: var(--w-text-muted); }
/* .send-btn: white at rest, --text-faint when there is nothing to send. */
.whon-send { color: var(--w-text-faint); transition: color 180ms var(--spring); }
.whon-send.is-live { color: var(--w-text); }

/* ---------------- widget 5: the manager's team ----------------
   features/manager/ManagerTeamView.tsx with the shared table vocabulary in
   features/admin/teamTable.tsx. The screen's search box and its two filter dropdowns
   are deliberately left out (owner call, 2026-08-28): inert controls in a preview
   invite a click that does nothing. Everything drawn IS the screen. */
.wcov { color: var(--text); padding: 26px 28px 24px; }
/* SurfaceHeader again, in the page's own theme this time. */
.wcov-head { margin-bottom: 28px; }
.wcov-title { font-size: 30px; font-weight: 500; letter-spacing: -0.015em; margin: 6px 0 0; }
.wcov-copy { font-size: 14px; line-height: 1.55; color: var(--text-muted); margin: 8px 0 0; max-width: 720px; }
.wcov-members { display: flex; align-items: baseline; gap: 8px; margin: 0 0 12px; }
.wcov-members b { font-size: 14px; font-weight: 600; color: var(--text); }
.wcov-members span { font-size: 13px; color: var(--text-muted); }
/* The table is a bordered, rounded, clipped box; the rows are hairlines inside it. */
.wcov-table { border: 1px solid var(--border); border-radius: 10px; overflow: hidden; }
.wcov-cols, .wcov-row {
  display: grid;
  grid-template-columns: minmax(0, 2fr) minmax(0, 1.3fr) 140px 130px;
  gap: 12px;
  align-items: center;
  padding: 0 16px;
}
.wcov-cols { height: 40px; border-bottom: 1px solid var(--border); background: var(--bg); }
/* headStatic: plain sentence case at 13/500, NOT letterspaced caps. */
.wcov-col { font-size: 13px; font-weight: 500; color: var(--text-muted); text-align: left; justify-self: start; }
/* Role is fixed and centred, and its header centres over it (HeadCell `centered`). */
.wcov-col--mid { justify-self: center; }
.wcov-row { min-height: 48px; border-top: 1px solid var(--border-faint); }
.wcov-row:first-of-type { border-top: none; }
.wcov-who { display: flex; align-items: center; gap: 11px; min-width: 0; }
/* teamTable `avatar`: 28 square, on --surface-2 behind a --border hairline. */
.wcov-av {
  width: 28px; height: 28px; border-radius: 999px; flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--surface-2); border: 1px solid var(--border); color: var(--text);
  font-size: 10px; font-weight: 700;
}
.wcov-nm { display: block; font-size: 13.5px; font-weight: 600; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wcov-title-cell { font-size: 13px; color: var(--text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wcov-rolecell { justify-self: center; }
/* RoleBadge: a glyph and a word in a pill, and the signed-in person's own row wears
   the ember outline. It carries no status colour: a role says what somebody does,
   never how much (ui/RoleBadge.tsx). */
.wcov-role {
  display: inline-flex; align-items: center; gap: 6px; height: 24px; padding: 0 9px;
  border: 1px solid var(--border); border-radius: 999px; background: var(--surface-2);
  font-size: 12px; font-weight: 600; line-height: 1; color: var(--text-muted);
  white-space: nowrap; flex-shrink: 0;
}
.wcov-role--you { border-color: var(--ember); color: var(--ember-deep); }
/* CaptureBand `dense`: the SHORT word, because that is what a table row shows.
   Never a number: a band is a posture, a number is a score (PROJECT.md, 2026-07-30). */
.wcov-band {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: 12.5px; font-weight: 500; color: var(--text-muted); white-space: nowrap;
  opacity: 0; transform: translateY(4px);
  transition: opacity 520ms var(--spring), transform 520ms var(--spring);
}
.wcov-band.is-in { opacity: 1; transform: none; }
.wcov-band i { width: 8px; height: 8px; border-radius: 999px; flex-shrink: 0; display: block; }
.wcov-band--green i { background: var(--good); }
.wcov-band--amber i { background: var(--ember); }
.wcov-band--red i { background: var(--danger); }
/* The site's own caption under the screen, not part of it. */
.wcov-note { font-size: 12.5px; color: var(--text-muted); line-height: 1.5; margin: 18px 0 0; }

/* ---------------- the narrow layouts the app itself has ----------------
   Keyed off `.is-narrow`, which the shrink-to-fit block sets when it picks the narrow
   authoring, NOT off a media query. The two must be the same decision: a media query
   reads the window, and the widget's width comes from its frame, so on a tablet the
   panes would stack at a width they were never authored for (or fail to stack at one
   they were). */
.fit.is-narrow .crux { display: flex; flex-direction: column; align-items: stretch; }
.fit.is-narrow .crux-pane,
.fit.is-narrow .crux-pane.on,
.fit.is-narrow .crux-pane:hover { transform: none; }
.fit.is-narrow .crux-rail { width: 2px; height: 60px; margin: 0 auto; }
.fit.is-narrow .crux-light {
  width: auto; left: -1px; right: -1px; height: 28px; top: 2px; bottom: auto;
  background: linear-gradient(180deg, rgba(226, 127, 72, 0.15), var(--ember), rgba(226, 127, 72, 0.15));
}
.fit.is-narrow .crux[data-active="me"] .crux-light { left: -1px; top: calc(100% - 30px); }
/* The narrow chat column is 380px rather than 760, so the same answer wraps to roughly
   twice the lines and the screen needs the height to hold it: measured, one exchange
   peaks at 423px against the 380px window a 560px card leaves. A phone screen being
   taller than it is wide is the same fact. */
.fit.is-narrow .whon { height: 620px; }

/* ---------------- reduced motion: settle everything, hide nothing ---------------- */
@media (prefers-reduced-motion: reduce) {
  .mcell i, .wcall-chip i, .wcov-band, .crux-pane, .crux-light, .crux-label { transition: none; }
  .msg-you .bubble, .msg-a, .ev-body, .mcell b, .wcall-card, .wcall-jarwin .wjar-row, .thinking-row { animation: none; }
  .mcell-flash { display: none; }
  /* The live dot holds its lit state instead of sending out a ring. */
  .wcall-dot { animation: none; }
  .kept-step-shimmer { animation: none; background: none; color: var(--w-text); -webkit-text-fill-color: currentColor; }
  .kept-step-trio circle { animation: none; opacity: 1; }
  .whon-typed:not(:empty)::after { animation: none; }
  .fx3d-body { opacity: 1; transform: none !important; }
  .fx3d-glow { opacity: 0.9; }
  .fx3d-shadow { opacity: 0.85; }
  .fxhero-body { transform: none !important; }
  .crux-pane--l, .crux-pane--r, .crux-pane:hover { transform: none; }
}
