LanderKitv1

AI Answer Citation Row

Decorative chat / answer-UI skeleton graphic. Restyle via --lk-* CSS variables.

PLATE 14chatpanelfeature:ai-answershero:aeosection:how-it-workssocial-proof:citationsdecor:chat
Chat answer graphic Decorative chat answer graphic. Illustrative shape only; any implied data is fictional.

Install

npx shadcn@latest add https://visual-blocks.akiho.dev/r/chat-answer-row.json
npx skills add akifo/landerkit

Blocks work with zero setup thanks to baked defaults. Set --lk-accent(and optionally --lk-bg / --lk-radius /--lk-font / --lk-grid) on :rootor any wrapper to restyle.

Source

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 320" role="img" aria-label="Chat answer mockup graphic — decorative" class="lk-block" data-lk="chat-answer-row" data-lk-contract="1">
  <title>Chat answer graphic</title>
  <desc>Decorative chat answer graphic. Illustrative shape only; any implied data is fictional.</desc>
  <style>
    /* lk-contract v1 — synced from blocks/_contract/header.css */
    [data-lk="chat-answer-row"] {
      --_accent: var(--lk-accent, #4BE0C3);
      --_bg: var(--lk-bg, #0A0F14);
      --_radius: var(--lk-radius, 12px);
      --_i: oklch(from var(--_bg) clamp(0.14, (0.68 - l) * 999, 0.93) min(c, 0.03) h);
      --_i2: color-mix(in oklab, var(--_i) 62%, transparent);
      --_i3: color-mix(in oklab, var(--_i) 42%, transparent);
      --_hair: color-mix(in oklab, var(--_i) 8%, transparent);
      --_g: var(--lk-grid, color-mix(in oklab, var(--_i) 9%, transparent));
      --_surf: color-mix(in oklab, var(--_accent) 3%, var(--_bg));
      --_soft: color-mix(in oklab, var(--_accent) 24%, transparent);
      --_faint: color-mix(in oklab, var(--_accent) 12%, transparent);
      --_glow: color-mix(in oklab, var(--_accent) 55%, var(--_bg));
      color: var(--_accent);
      font-family: var(--lk-font, 'Inter','Neue Haas Grotesk','Helvetica Neue',Arial,sans-serif);
    }
    /* base ink: text flips with the bg via --_i; dim/semantic classes override (see CONVENTIONS.md) */
    [data-lk="chat-answer-row"] text,
    [data-lk="chat-answer-row"] tspan { fill: var(--_i); }


    /* Layer 3: block-specific — every selector MUST start with [data-lk="chat-answer-row"] */
    [data-lk="chat-answer-row"] .bubble { fill: var(--_bg); stroke: var(--_hair); stroke-width: 1; rx: calc(var(--_radius) * 1.3); }
    [data-lk="chat-answer-row"] .card   { fill: var(--_surf); stroke: var(--_hair); stroke-width: 1; rx: var(--_radius); }
    [data-lk="chat-answer-row"] .grid   { fill: none; stroke: var(--_g); stroke-width: 1; }
    [data-lk="chat-answer-row"] .hair   { stroke: var(--_hair); stroke-width: 1; }
    [data-lk="chat-answer-row"] .glyph  { fill: var(--_accent); }
    [data-lk="chat-answer-row"] .line   { fill: color-mix(in oklab, var(--_i) 20%, transparent); rx: calc(var(--_radius) * .375); }
    [data-lk="chat-answer-row"] .linef  { fill: color-mix(in oklab, var(--_i) 12%, transparent); rx: calc(var(--_radius) * .375); }
    [data-lk="chat-answer-row"] .pill   { fill: var(--_soft); stroke: var(--_accent); stroke-width: 1; rx: calc(var(--_radius) * .5); }
    [data-lk="chat-answer-row"] .cchip  { fill: none; stroke: color-mix(in oklab, var(--_accent) 40%, transparent); stroke-width: 1; rx: calc(var(--_radius) * .5); }
    [data-lk="chat-answer-row"] .fav    { fill: var(--_i3); }

    /* Hover motion (opt-out): 2 stages. (1) the user bubble, then the answer card,
       rise + fade in (each riser carries its own skeleton copy so nothing desyncs);
       the card follows the bubble by ~.12s. (2) staggered: the answer's skeleton
       text-bars fade in top→down at a typing cadence, then the citation chips pop
       left→right. Off for reduced-motion visitors; set the motion token to 0 to
       force off. */
    [data-lk="chat-answer-row"] .rise-bubble,
    [data-lk="chat-answer-row"] .rise-card { transform-box: fill-box; }
    [data-lk="chat-answer-row"] .chip { transform-box: fill-box; }
    @media (prefers-reduced-motion: no-preference) {
      [data-lk="chat-answer-row"]:hover .rise-bubble { animation: lk-chat-answer-row-rise calc(var(--lk-motion, 1) * .48s) cubic-bezier(.22,.61,.36,1) both; }
      [data-lk="chat-answer-row"]:hover .rise-card   { animation: lk-chat-answer-row-rise calc(var(--lk-motion, 1) * .48s) cubic-bezier(.22,.61,.36,1) both; animation-delay: calc(var(--lk-motion, 1) * .12s); }
      [data-lk="chat-answer-row"]:hover .typeline    { animation: lk-chat-answer-row-type calc(var(--lk-motion, 1) * .24s) ease-out both; animation-delay: calc(var(--lk-motion, 1) * .6s); }
      [data-lk="chat-answer-row"]:hover .tl2         { animation-delay: calc(var(--lk-motion, 1) * .68s); }
      [data-lk="chat-answer-row"]:hover .tl3         { animation-delay: calc(var(--lk-motion, 1) * .76s); }
      [data-lk="chat-answer-row"]:hover .chip        { animation: lk-chat-answer-row-pop calc(var(--lk-motion, 1) * .38s) ease-out both; animation-delay: calc(var(--lk-motion, 1) * 1s); }
      [data-lk="chat-answer-row"]:hover .chip2       { animation-delay: calc(var(--lk-motion, 1) * 1.06s); }
      [data-lk="chat-answer-row"]:hover .chip3       { animation-delay: calc(var(--lk-motion, 1) * 1.12s); }
    }
    @keyframes lk-chat-answer-row-rise { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } }
    @keyframes lk-chat-answer-row-type { from { opacity: 0; } to { opacity: 1; } }
    @keyframes lk-chat-answer-row-pop { 0% { opacity: 0; transform: scale(1); } 20% { opacity: 1; transform: scale(1); } 55% { transform: scale(1.4); } 100% { opacity: 1; transform: scale(1); } }
  </style>

  <!-- user turn: right-aligned bubble, hairline border + bg fill (quieter than the AI surface below), holding skeleton copy — one riser, rises + fades in together -->
  <g class="rise-bubble">
    <rect class="bubble" x="350" y="20" width="270" height="52" rx="15.6" fill="#0A0F14" stroke="#1A2128" stroke-width="1"/>
    <rect class="line" x="368" y="34" width="234" height="8" rx="4" fill="#E6EDEE33"/>
    <rect class="line" x="452" y="52" width="150" height="8" rx="4" fill="#E6EDEE33"/>
  </g>

  <!-- réseau cross: sparse calibration mark in the top-left dead zone, on the grid token (silenced when lk-grid is transparent) -->
  <path class="grid" d="M37 40h6M40 37v6" fill="none" stroke="#1C262C" stroke-width="1"/>

  <!-- AI answer turn: its own card (the block itself carries no outer frame) — rises + fades in as one riser, following the bubble -->
  <g class="rise-card">
    <rect class="card" x="20" y="92" width="600" height="208" rx="12" fill="#0E141B" stroke="#1A2128" stroke-width="1"/>

    <!-- réseau cross: sparse calibration mark in the card's dead zone, on the grid token (silenced when lk-grid is transparent) -->
    <path class="grid" d="M596 280h6M599 277v6" fill="none" stroke="#1C262C" stroke-width="1"/>

    <!-- header: the one permitted decorative icon, a 4-point sparkle glyph marking the AI answer, beside a skeleton label bar -->
    <polygon class="glyph" points="50,120 51.6,124.4 56,126 51.6,127.6 50,132 48.4,127.6 44,126 48.4,124.4" fill="#4BE0C3"/>
    <rect class="line" x="64" y="122" width="88" height="8" rx="4" fill="#E6EDEE33"/>

    <!-- answer body: skeleton text lines fade in sequentially top→down at a typing cadence; cited term as an accent pill, last line faded to suggest continuation -->
    <g class="typeline tl1">
      <rect class="line" x="44" y="163.5" width="118" height="9" rx="4.5" fill="#E6EDEE33"/>
      <rect class="pill" x="170" y="160" width="66" height="16" rx="6" fill="#4BE0C33D" stroke="#4BE0C3" stroke-width="1"/>
      <rect class="line" x="244" y="163.5" width="176" height="9" rx="4.5" fill="#E6EDEE33"/>
    </g>
    <g class="typeline tl2">
      <rect class="line" x="44" y="187.5" width="486" height="9" rx="4.5" fill="#E6EDEE33"/>
    </g>
    <g class="typeline tl3">
      <rect class="linef" x="44" y="211.5" width="300" height="9" rx="4.5" fill="#E6EDEE1F"/>
    </g>

    <!-- sources divider: hairline separating the answer body from the citation row -->
    <line class="hair" x1="44" y1="232" x2="596" y2="232" stroke="#1A2128" stroke-width="1"/>

    <!-- citation chips: rounded, accent 40% 1px border, achromatic favicon dot + skeleton label — pop once the answer has typed out, left→right -->
    <g class="chip chip1">
      <rect class="cchip" x="44" y="244" width="96" height="24" rx="6" fill="none" stroke="#4BE0C366" stroke-width="1"/>
      <circle class="fav" cx="59" cy="256" r="3" fill="#E6EDEE6B"/>
      <rect class="line" x="68" y="252.5" width="60" height="7" rx="3.5" fill="#E6EDEE33"/>
    </g>
    <g class="chip chip2">
      <rect class="cchip" x="152" y="244" width="132" height="24" rx="6" fill="none" stroke="#4BE0C366" stroke-width="1"/>
      <circle class="fav" cx="167" cy="256" r="3" fill="#E6EDEE6B"/>
      <rect class="line" x="176" y="252.5" width="96" height="7" rx="3.5" fill="#E6EDEE33"/>
    </g>
    <g class="chip chip3">
      <rect class="cchip" x="296" y="244" width="104" height="24" rx="6" fill="none" stroke="#4BE0C366" stroke-width="1"/>
      <circle class="fav" cx="311" cy="256" r="3" fill="#E6EDEE6B"/>
      <rect class="line" x="320" y="252.5" width="68" height="7" rx="3.5" fill="#E6EDEE33"/>
    </g>
  </g>
</svg>