ChatView.module.css 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. /* Chat flow: one 16px rhythm everywhere — between blocks (prose <-> tool
  2. runs) via the column gap and between consecutive tool rows via the group
  3. gap. Input padding cap rides the skeleton. Under
  4. `[data-conversation-scroll]` the column host owns overflow and this view
  5. is ordinary flow (see ConversationRoot active-phase rules). */
  6. .root {
  7. position: relative;
  8. display: flex;
  9. flex-direction: column;
  10. min-height: 0;
  11. flex: 1 1 auto;
  12. }
  13. .scroll {
  14. flex: 1 1 auto;
  15. min-height: 0;
  16. overflow-y: auto;
  17. padding: 16px 24px;
  18. }
  19. :global([data-conversation-scroll]) .root {
  20. flex: 0 0 auto;
  21. min-height: auto;
  22. height: auto;
  23. }
  24. :global([data-conversation-scroll]) .scroll {
  25. overflow: visible;
  26. flex: 0 0 auto;
  27. min-height: auto;
  28. }
  29. /* Message column: 736px fixed width, centered on the same axis as the
  30. input box; the scroller itself stays full-bleed. */
  31. .column {
  32. max-width: 736px;
  33. width: 100%;
  34. margin: 0 auto;
  35. display: flex;
  36. flex-direction: column;
  37. gap: 16px;
  38. }
  39. .toolGroup {
  40. display: flex;
  41. flex-direction: column;
  42. gap: 16px;
  43. }
  44. .callRow {
  45. border-radius: 6px;
  46. }
  47. /* Selection still sets data-selected for details linkage; no outline —
  48. tool rows match Think chrome (no selected ring). */
  49. /* run_code sub-dispatch rows: indented under the parent row, left-edged so
  50. the code turn reads as one unit; each nested row is itself a .callRow. */
  51. .subCalls {
  52. display: flex;
  53. flex-direction: column;
  54. gap: 4px;
  55. margin: 4px 0 2px 22px;
  56. padding-left: 8px;
  57. border-left: 1px solid var(--dsw-alias-border-l2);
  58. }
  59. /* Turn loader: one row of four 2.5px pixels (StateDot blue) chasing left to
  60. right with a stepped trail — flat keyframe holds, no tweening. Phase
  61. offsets come from per-rect animation-delay (index * -250ms) set inline
  62. by the component. */
  63. .turnDots {
  64. align-self: flex-start;
  65. flex: none;
  66. display: flex;
  67. align-items: center;
  68. /* One message line box: the dots center inside the text line height. */
  69. height: 26px;
  70. /* Same pin as StateDot: ongoing blue has no alias token (business-primary
  71. is the 500 step, not this 450). */
  72. color: var(--dsw-static-deepseek-450);
  73. }
  74. .turnDotCell {
  75. fill: currentColor;
  76. opacity: 0.15;
  77. animation: dsh-turn-dots-chase 1s infinite;
  78. }
  79. @keyframes dsh-turn-dots-chase {
  80. 0%, 24.9% { opacity: 1; }
  81. 25%, 49.9% { opacity: 0.6; }
  82. 50%, 74.9% { opacity: 0.35; }
  83. 75%, 100% { opacity: 0.15; }
  84. }
  85. .hint {
  86. color: var(--dsw-alias-label-tertiary);
  87. font-size: 12px;
  88. line-height: 18px;
  89. }
  90. .openError {
  91. color: var(--dsw-alias-state-error-primary);
  92. font-size: 12px;
  93. line-height: 18px;
  94. }
  95. .older {
  96. display: flex;
  97. justify-content: center;
  98. }
  99. .older button {
  100. border: none;
  101. border-radius: 14px;
  102. padding: 4px 12px;
  103. font-size: 12px;
  104. color: var(--dsw-alias-label-secondary);
  105. background: var(--dsw-alias-interactive-bg-hover-solid);
  106. cursor: pointer;
  107. }
  108. .older button:disabled {
  109. cursor: default;
  110. opacity: 0.6;
  111. }
  112. /* Back-to-bottom: zero-height sticky slot so the control does not extend
  113. scrollHeight; the button translates up into the viewport. Under the
  114. conversation host, clearance sits above the sticky composer stack. */
  115. .toBottomSlot {
  116. position: sticky;
  117. bottom: 16px;
  118. /* Above the sticky composer (z-index 7) so the control stays clickable and
  119. visible over the input card. */
  120. z-index: 8;
  121. height: 0;
  122. display: flex;
  123. justify-content: flex-end;
  124. padding-right: max(0px, calc((100% - 736px) / 2));
  125. pointer-events: none;
  126. }
  127. :global([data-conversation-scroll]) .toBottomSlot {
  128. /* Clears the sticky composer stack (docks + input card + stats): the live
  129. height rides --dsh-composer-height (ConversationRoot's seat observer) so
  130. the control follows a growing textarea; the fallback covers the first
  131. paint before the observer fires. */
  132. bottom: calc(var(--dsh-composer-height, 152px) + 16px);
  133. }
  134. .toBottom {
  135. display: flex;
  136. align-items: center;
  137. justify-content: center;
  138. width: 34px;
  139. height: 34px;
  140. margin-top: -34px;
  141. padding: 0;
  142. border: 1px solid var(--dsw-alias-border-l2);
  143. border-radius: 100px;
  144. color: var(--dsw-alias-label-primary);
  145. background: var(--dsw-alias-button-floating-fill);
  146. box-shadow: var(--dsw-shadow-lv2);
  147. cursor: pointer;
  148. pointer-events: auto;
  149. }
  150. .toBottom:hover {
  151. background: var(--dsw-alias-button-floating-hover);
  152. }