You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1852 lines
31 KiB

Revamp post filtering system (#18058) * Add model for custom filter keywords * Use CustomFilterKeyword internally Does not change the API * Fix /filters/edit and /filters/new * Add migration tests * Remove whole_word column from custom_filters (covered by custom_filter_keywords) * Redesign /filters Instead of a list, present a card that displays more information and handles multiple keywords per filter. * Redesign /filters/new and /filters/edit to add and remove keywords This adds a new gem dependency: cocoon, as well as a npm dependency: cocoon-js-vanilla. Those are used to easily populate and remove form fields from the user interface when manipulating multiple keyword filters at once. * Add /api/v2/filters to edit filter with multiple keywords Entities: - `Filter`: `id`, `title`, `filter_action` (either `hide` or `warn`), `context` `keywords` - `FilterKeyword`: `id`, `keyword`, `whole_word` API endpoits: - `GET /api/v2/filters` to list filters (including keywords) - `POST /api/v2/filters` to create a new filter `keywords_attributes` can also be passed to create keywords in one request - `GET /api/v2/filters/:id` to read a particular filter - `PUT /api/v2/filters/:id` to update a new filter `keywords_attributes` can also be passed to edit, delete or add keywords in one request - `DELETE /api/v2/filters/:id` to delete a particular filter - `GET /api/v2/filters/:id/keywords` to list keywords for a filter - `POST /api/v2/filters/:filter_id/keywords/:id` to add a new keyword to a filter - `GET /api/v2/filter_keywords/:id` to read a particular keyword - `PUT /api/v2/filter_keywords/:id` to edit a particular keyword - `DELETE /api/v2/filter_keywords/:id` to delete a particular keyword * Change from `irreversible` boolean to `action` enum * Remove irrelevent `irreversible_must_be_within_context` check * Fix /filters/new and /filters/edit with update for filter_action * Fix Rubocop/Codeclimate complaining about task names * Refactor FeedManager#phrase_filtered? This moves regexp building and filter caching to the `CustomFilter` class. This does not change the functional behavior yet, but this changes how the cache is built, doing per-custom_filter regexps so that filters can be matched independently, while still offering caching. * Perform server-side filtering and output result in REST API * Fix numerous filters_changed events being sent when editing multiple keywords at once * Add some tests * Use the new API in the WebUI - use client-side logic for filters we have fetched rules for. This is so that filter changes can be retroactively applied without reloading the UI. - use server-side logic for filters we haven't fetched rules for yet (e.g. network error, or initial timeline loading) * Minor optimizations and refactoring * Perform server-side filtering on the streaming server * Change the wording of filter action labels * Fix issues pointed out by linter * Change design of “Show anyway” link in accordence to review comments * Drop “irreversible” filtering behavior * Move /api/v2/filter_keywords to /api/v1/filters/keywords * Rename `filter_results` attribute to `filtered` * Rename REST::LegacyFilterSerializer to REST::V1::FilterSerializer * Fix systemChannelId value in streaming server * Simplify code by removing client-side filtering code The simplifcation comes at a cost though: filters aren't retroactively applied anymore.
1 year ago
Revamp post filtering system (#18058) * Add model for custom filter keywords * Use CustomFilterKeyword internally Does not change the API * Fix /filters/edit and /filters/new * Add migration tests * Remove whole_word column from custom_filters (covered by custom_filter_keywords) * Redesign /filters Instead of a list, present a card that displays more information and handles multiple keywords per filter. * Redesign /filters/new and /filters/edit to add and remove keywords This adds a new gem dependency: cocoon, as well as a npm dependency: cocoon-js-vanilla. Those are used to easily populate and remove form fields from the user interface when manipulating multiple keyword filters at once. * Add /api/v2/filters to edit filter with multiple keywords Entities: - `Filter`: `id`, `title`, `filter_action` (either `hide` or `warn`), `context` `keywords` - `FilterKeyword`: `id`, `keyword`, `whole_word` API endpoits: - `GET /api/v2/filters` to list filters (including keywords) - `POST /api/v2/filters` to create a new filter `keywords_attributes` can also be passed to create keywords in one request - `GET /api/v2/filters/:id` to read a particular filter - `PUT /api/v2/filters/:id` to update a new filter `keywords_attributes` can also be passed to edit, delete or add keywords in one request - `DELETE /api/v2/filters/:id` to delete a particular filter - `GET /api/v2/filters/:id/keywords` to list keywords for a filter - `POST /api/v2/filters/:filter_id/keywords/:id` to add a new keyword to a filter - `GET /api/v2/filter_keywords/:id` to read a particular keyword - `PUT /api/v2/filter_keywords/:id` to edit a particular keyword - `DELETE /api/v2/filter_keywords/:id` to delete a particular keyword * Change from `irreversible` boolean to `action` enum * Remove irrelevent `irreversible_must_be_within_context` check * Fix /filters/new and /filters/edit with update for filter_action * Fix Rubocop/Codeclimate complaining about task names * Refactor FeedManager#phrase_filtered? This moves regexp building and filter caching to the `CustomFilter` class. This does not change the functional behavior yet, but this changes how the cache is built, doing per-custom_filter regexps so that filters can be matched independently, while still offering caching. * Perform server-side filtering and output result in REST API * Fix numerous filters_changed events being sent when editing multiple keywords at once * Add some tests * Use the new API in the WebUI - use client-side logic for filters we have fetched rules for. This is so that filter changes can be retroactively applied without reloading the UI. - use server-side logic for filters we haven't fetched rules for yet (e.g. network error, or initial timeline loading) * Minor optimizations and refactoring * Perform server-side filtering on the streaming server * Change the wording of filter action labels * Fix issues pointed out by linter * Change design of “Show anyway” link in accordence to review comments * Drop “irreversible” filtering behavior * Move /api/v2/filter_keywords to /api/v1/filters/keywords * Rename `filter_results` attribute to `filtered` * Rename REST::LegacyFilterSerializer to REST::V1::FilterSerializer * Fix systemChannelId value in streaming server * Simplify code by removing client-side filtering code The simplifcation comes at a cost though: filters aren't retroactively applied anymore.
1 year ago
Revamp post filtering system (#18058) * Add model for custom filter keywords * Use CustomFilterKeyword internally Does not change the API * Fix /filters/edit and /filters/new * Add migration tests * Remove whole_word column from custom_filters (covered by custom_filter_keywords) * Redesign /filters Instead of a list, present a card that displays more information and handles multiple keywords per filter. * Redesign /filters/new and /filters/edit to add and remove keywords This adds a new gem dependency: cocoon, as well as a npm dependency: cocoon-js-vanilla. Those are used to easily populate and remove form fields from the user interface when manipulating multiple keyword filters at once. * Add /api/v2/filters to edit filter with multiple keywords Entities: - `Filter`: `id`, `title`, `filter_action` (either `hide` or `warn`), `context` `keywords` - `FilterKeyword`: `id`, `keyword`, `whole_word` API endpoits: - `GET /api/v2/filters` to list filters (including keywords) - `POST /api/v2/filters` to create a new filter `keywords_attributes` can also be passed to create keywords in one request - `GET /api/v2/filters/:id` to read a particular filter - `PUT /api/v2/filters/:id` to update a new filter `keywords_attributes` can also be passed to edit, delete or add keywords in one request - `DELETE /api/v2/filters/:id` to delete a particular filter - `GET /api/v2/filters/:id/keywords` to list keywords for a filter - `POST /api/v2/filters/:filter_id/keywords/:id` to add a new keyword to a filter - `GET /api/v2/filter_keywords/:id` to read a particular keyword - `PUT /api/v2/filter_keywords/:id` to edit a particular keyword - `DELETE /api/v2/filter_keywords/:id` to delete a particular keyword * Change from `irreversible` boolean to `action` enum * Remove irrelevent `irreversible_must_be_within_context` check * Fix /filters/new and /filters/edit with update for filter_action * Fix Rubocop/Codeclimate complaining about task names * Refactor FeedManager#phrase_filtered? This moves regexp building and filter caching to the `CustomFilter` class. This does not change the functional behavior yet, but this changes how the cache is built, doing per-custom_filter regexps so that filters can be matched independently, while still offering caching. * Perform server-side filtering and output result in REST API * Fix numerous filters_changed events being sent when editing multiple keywords at once * Add some tests * Use the new API in the WebUI - use client-side logic for filters we have fetched rules for. This is so that filter changes can be retroactively applied without reloading the UI. - use server-side logic for filters we haven't fetched rules for yet (e.g. network error, or initial timeline loading) * Minor optimizations and refactoring * Perform server-side filtering on the streaming server * Change the wording of filter action labels * Fix issues pointed out by linter * Change design of “Show anyway” link in accordence to review comments * Drop “irreversible” filtering behavior * Move /api/v2/filter_keywords to /api/v1/filters/keywords * Rename `filter_results` attribute to `filtered` * Rename REST::LegacyFilterSerializer to REST::V1::FilterSerializer * Fix systemChannelId value in streaming server * Simplify code by removing client-side filtering code The simplifcation comes at a cost though: filters aren't retroactively applied anymore.
1 year ago
  1. @use "sass:math";
  2. $no-columns-breakpoint: 600px;
  3. $sidebar-width: 240px;
  4. $content-width: 840px;
  5. .admin-wrapper {
  6. display: flex;
  7. justify-content: center;
  8. width: 100%;
  9. min-height: 100vh;
  10. .sidebar-wrapper {
  11. min-height: 100vh;
  12. overflow: hidden;
  13. pointer-events: none;
  14. flex: 1 1 auto;
  15. &__inner {
  16. display: flex;
  17. justify-content: flex-end;
  18. background: $ui-base-color;
  19. height: 100%;
  20. }
  21. }
  22. .sidebar {
  23. width: $sidebar-width;
  24. padding: 0;
  25. pointer-events: auto;
  26. &__toggle {
  27. display: none;
  28. background: darken($ui-base-color, 4%);
  29. border-bottom: 1px solid lighten($ui-base-color, 4%);
  30. align-items: center;
  31. &__logo {
  32. flex: 1 1 auto;
  33. a {
  34. display: block;
  35. padding: 15px;
  36. }
  37. }
  38. &__icon {
  39. display: block;
  40. color: $darker-text-color;
  41. text-decoration: none;
  42. flex: 0 0 auto;
  43. font-size: 18px;
  44. padding: 10px;
  45. margin: 5px 10px;
  46. border-radius: 4px;
  47. &:focus {
  48. background: $ui-base-color;
  49. }
  50. .fa-times {
  51. display: none;
  52. }
  53. &.active {
  54. .fa-times {
  55. display: block;
  56. }
  57. .fa-bars {
  58. display: none;
  59. }
  60. }
  61. }
  62. }
  63. .logo {
  64. display: block;
  65. margin: 40px auto;
  66. width: 100px;
  67. height: 100px;
  68. }
  69. .logo--wordmark {
  70. display: inherit;
  71. margin: inherit;
  72. width: inherit;
  73. height: 25px;
  74. }
  75. @media screen and (max-width: $no-columns-breakpoint) {
  76. & > a:first-child {
  77. display: none;
  78. }
  79. }
  80. ul {
  81. list-style: none;
  82. border-radius: 4px 0 0 4px;
  83. overflow: hidden;
  84. margin-bottom: 20px;
  85. @media screen and (max-width: $no-columns-breakpoint) {
  86. margin-bottom: 0;
  87. }
  88. a {
  89. display: block;
  90. padding: 15px;
  91. color: $darker-text-color;
  92. text-decoration: none;
  93. transition: all 200ms linear;
  94. transition-property: color, background-color;
  95. border-radius: 4px 0 0 4px;
  96. white-space: nowrap;
  97. overflow: hidden;
  98. text-overflow: ellipsis;
  99. i.fa {
  100. margin-right: 5px;
  101. }
  102. &:hover {
  103. color: $primary-text-color;
  104. background-color: darken($ui-base-color, 5%);
  105. transition: all 100ms linear;
  106. transition-property: color, background-color;
  107. }
  108. &.selected {
  109. background: darken($ui-base-color, 2%);
  110. border-radius: 4px 0 0;
  111. }
  112. }
  113. ul {
  114. background: darken($ui-base-color, 4%);
  115. border-radius: 0 0 0 4px;
  116. margin: 0;
  117. a {
  118. border: 0;
  119. padding: 15px 35px;
  120. }
  121. }
  122. .simple-navigation-active-leaf a {
  123. color: $primary-text-color;
  124. background-color: darken($ui-highlight-color, 2%);
  125. border-bottom: 0;
  126. border-radius: 0;
  127. &:hover {
  128. background-color: $ui-highlight-color;
  129. }
  130. }
  131. }
  132. & > ul > .simple-navigation-active-leaf a {
  133. border-radius: 4px 0 0 4px;
  134. }
  135. }
  136. .content-wrapper {
  137. box-sizing: border-box;
  138. width: 100%;
  139. max-width: $content-width;
  140. flex: 1 1 auto;
  141. }
  142. @media screen and (max-width: $content-width + $sidebar-width) {
  143. .sidebar-wrapper--empty {
  144. display: none;
  145. }
  146. .sidebar-wrapper {
  147. width: $sidebar-width;
  148. flex: 0 0 auto;
  149. }
  150. }
  151. @media screen and (max-width: $no-columns-breakpoint) {
  152. .sidebar-wrapper {
  153. width: 100%;
  154. }
  155. }
  156. .content {
  157. padding: 55px 15px 20px 25px;
  158. @media screen and (max-width: $no-columns-breakpoint) {
  159. max-width: none;
  160. padding: 15px;
  161. padding-top: 30px;
  162. }
  163. &__heading {
  164. margin-bottom: 45px;
  165. &__row {
  166. display: flex;
  167. flex-wrap: wrap;
  168. align-items: center;
  169. justify-content: space-between;
  170. margin: -15px -15px 0 0;
  171. & > * {
  172. margin-top: 15px;
  173. margin-right: 15px;
  174. }
  175. }
  176. &__tabs {
  177. margin-top: 30px;
  178. width: 100%;
  179. & > div {
  180. display: flex;
  181. flex-wrap: wrap;
  182. gap: 5px;
  183. }
  184. a {
  185. font-size: 14px;
  186. display: inline-flex;
  187. align-items: center;
  188. padding: 7px 10px;
  189. border-radius: 4px;
  190. color: $darker-text-color;
  191. text-decoration: none;
  192. font-weight: 500;
  193. gap: 5px;
  194. white-space: nowrap;
  195. &:hover,
  196. &:focus,
  197. &:active {
  198. background: lighten($ui-base-color, 4%);
  199. }
  200. &.selected {
  201. font-weight: 700;
  202. color: $primary-text-color;
  203. background: $ui-highlight-color;
  204. &:hover,
  205. &:focus,
  206. &:active {
  207. background: lighten($ui-highlight-color, 4%);
  208. }
  209. }
  210. }
  211. }
  212. &__actions {
  213. display: inline-flex;
  214. & > :not(:first-child) {
  215. margin-left: 5px;
  216. }
  217. }
  218. h2 small {
  219. font-size: 12px;
  220. display: block;
  221. font-weight: 500;
  222. color: $darker-text-color;
  223. line-height: 18px;
  224. }
  225. @media screen and (max-width: $no-columns-breakpoint) {
  226. border-bottom: 0;
  227. padding-bottom: 0;
  228. }
  229. }
  230. h2 {
  231. color: $secondary-text-color;
  232. font-size: 24px;
  233. line-height: 36px;
  234. font-weight: 700;
  235. }
  236. h3 {
  237. color: $secondary-text-color;
  238. font-size: 20px;
  239. line-height: 28px;
  240. font-weight: 400;
  241. margin-bottom: 30px;
  242. }
  243. h4 {
  244. text-transform: uppercase;
  245. font-size: 13px;
  246. font-weight: 700;
  247. color: $darker-text-color;
  248. padding-bottom: 8px;
  249. margin-bottom: 8px;
  250. border-bottom: 1px solid lighten($ui-base-color, 8%);
  251. }
  252. h6 {
  253. font-size: 16px;
  254. color: $secondary-text-color;
  255. line-height: 28px;
  256. font-weight: 500;
  257. }
  258. .fields-group h6 {
  259. color: $primary-text-color;
  260. font-weight: 500;
  261. }
  262. .directory__tag > a,
  263. .directory__tag > div {
  264. box-shadow: none;
  265. }
  266. .directory__tag .table-action-link .fa {
  267. color: inherit;
  268. }
  269. .directory__tag h4 {
  270. font-size: 18px;
  271. font-weight: 700;
  272. color: $primary-text-color;
  273. text-transform: none;
  274. padding-bottom: 0;
  275. margin-bottom: 0;
  276. border-bottom: 0;
  277. }
  278. & > p {
  279. font-size: 14px;
  280. line-height: 21px;
  281. color: $secondary-text-color;
  282. margin-bottom: 20px;
  283. strong {
  284. color: $primary-text-color;
  285. font-weight: 500;
  286. @each $lang in $cjk-langs {
  287. &:lang(#{$lang}) {
  288. font-weight: 700;
  289. }
  290. }
  291. }
  292. }
  293. hr {
  294. width: 100%;
  295. height: 0;
  296. border: 0;
  297. border-bottom: 1px solid rgba($ui-base-lighter-color, 0.6);
  298. margin: 20px 0;
  299. &.spacer {
  300. height: 1px;
  301. border: 0;
  302. }
  303. }
  304. }
  305. @media screen and (max-width: $no-columns-breakpoint) {
  306. display: block;
  307. .sidebar-wrapper {
  308. min-height: 0;
  309. }
  310. .sidebar {
  311. width: 100%;
  312. padding: 0;
  313. height: auto;
  314. &__toggle {
  315. display: flex;
  316. }
  317. & > ul {
  318. display: none;
  319. &.visible {
  320. display: block;
  321. position: fixed;
  322. z-index: 10;
  323. width: 100%;
  324. height: calc(100vh - 56px);
  325. left: 0;
  326. bottom: 0;
  327. overflow-y: auto;
  328. background: $ui-base-color;
  329. }
  330. }
  331. ul a,
  332. ul ul a {
  333. border-radius: 0;
  334. border-bottom: 1px solid lighten($ui-base-color, 4%);
  335. transition: none;
  336. &:hover {
  337. transition: none;
  338. }
  339. }
  340. ul ul {
  341. border-radius: 0;
  342. }
  343. ul .simple-navigation-active-leaf a {
  344. border-bottom-color: $ui-highlight-color;
  345. }
  346. }
  347. }
  348. }
  349. hr.spacer {
  350. width: 100%;
  351. border: 0;
  352. margin: 20px 0;
  353. height: 1px;
  354. }
  355. body,
  356. .admin-wrapper .content {
  357. .muted-hint {
  358. color: $darker-text-color;
  359. a {
  360. color: $highlight-text-color;
  361. }
  362. }
  363. .positive-hint,
  364. .negative-hint,
  365. .neutral-hint {
  366. a {
  367. color: inherit;
  368. text-decoration: underline;
  369. &:focus,
  370. &:hover,
  371. &:active {
  372. text-decoration: none;
  373. }
  374. }
  375. }
  376. .positive-hint {
  377. color: $valid-value-color;
  378. font-weight: 500;
  379. }
  380. .negative-hint {
  381. color: $error-value-color;
  382. font-weight: 500;
  383. }
  384. .neutral-hint {
  385. color: $dark-text-color;
  386. font-weight: 500;
  387. }
  388. .warning-hint {
  389. color: $gold-star;
  390. font-weight: 500;
  391. }
  392. }
  393. .filters {
  394. display: flex;
  395. flex-wrap: wrap;
  396. .filter-subset {
  397. flex: 0 0 auto;
  398. margin: 0 40px 20px 0;
  399. &:last-child {
  400. margin-bottom: 30px;
  401. }
  402. ul {
  403. margin-top: 5px;
  404. list-style: none;
  405. li {
  406. display: inline-block;
  407. margin-right: 5px;
  408. }
  409. }
  410. & > div {
  411. display: flex;
  412. gap: 5px;
  413. }
  414. strong {
  415. font-weight: 500;
  416. text-transform: uppercase;
  417. font-size: 12px;
  418. @each $lang in $cjk-langs {
  419. &:lang(#{$lang}) {
  420. font-weight: 700;
  421. }
  422. }
  423. }
  424. &--with-select strong {
  425. display: block;
  426. margin-bottom: 10px;
  427. }
  428. a {
  429. display: inline-block;
  430. color: $darker-text-color;
  431. text-decoration: none;
  432. text-transform: uppercase;
  433. font-size: 12px;
  434. font-weight: 500;
  435. border-bottom: 2px solid $ui-base-color;
  436. &:hover {
  437. color: $primary-text-color;
  438. border-bottom: 2px solid lighten($ui-base-color, 5%);
  439. }
  440. &.selected {
  441. color: $highlight-text-color;
  442. border-bottom: 2px solid $ui-highlight-color;
  443. }
  444. }
  445. }
  446. }
  447. .flavour-screen {
  448. display: block;
  449. margin: 10px auto;
  450. max-width: 100%;
  451. }
  452. .flavour-description {
  453. display: block;
  454. font-size: 16px;
  455. margin: 10px 0;
  456. & > p {
  457. margin: 10px 0;
  458. }
  459. }
  460. .report-accounts {
  461. display: flex;
  462. flex-wrap: wrap;
  463. margin-bottom: 20px;
  464. }
  465. .report-accounts__item {
  466. display: flex;
  467. flex: 250px;
  468. flex-direction: column;
  469. margin: 0 5px;
  470. & > strong {
  471. display: block;
  472. margin: 0 0 10px -5px;
  473. font-weight: 500;
  474. font-size: 14px;
  475. line-height: 18px;
  476. color: $secondary-text-color;
  477. @each $lang in $cjk-langs {
  478. &:lang(#{$lang}) {
  479. font-weight: 700;
  480. }
  481. }
  482. }
  483. .account-card {
  484. flex: 1 1 auto;
  485. }
  486. }
  487. .report-status,
  488. .account-status {
  489. display: flex;
  490. margin-bottom: 10px;
  491. .activity-stream {
  492. flex: 2 0 0;
  493. margin-right: 20px;
  494. max-width: calc(100% - 60px);
  495. .entry {
  496. border-radius: 4px;
  497. }
  498. }
  499. }
  500. .report-status__actions,
  501. .account-status__actions {
  502. flex: 0 0 auto;
  503. display: flex;
  504. flex-direction: column;
  505. .icon-button {
  506. font-size: 24px;
  507. width: 24px;
  508. text-align: center;
  509. margin-bottom: 10px;
  510. }
  511. }
  512. .simple_form.new_report_note,
  513. .simple_form.new_account_moderation_note {
  514. max-width: 100%;
  515. }
  516. .simple_form {
  517. .actions {
  518. margin-top: 15px;
  519. }
  520. .button {
  521. font-size: 15px;
  522. }
  523. }
  524. .batch-form-box {
  525. display: flex;
  526. flex-wrap: wrap;
  527. margin-bottom: 5px;
  528. #form_status_batch_action {
  529. margin: 0 5px 5px 0;
  530. font-size: 14px;
  531. }
  532. input.button {
  533. margin: 0 5px 5px 0;
  534. }
  535. .media-spoiler-toggle-buttons {
  536. margin-left: auto;
  537. .button {
  538. overflow: visible;
  539. margin: 0 0 5px 5px;
  540. float: right;
  541. }
  542. }
  543. }
  544. .back-link {
  545. margin-bottom: 10px;
  546. font-size: 14px;
  547. a {
  548. color: $highlight-text-color;
  549. text-decoration: none;
  550. &:hover {
  551. text-decoration: underline;
  552. }
  553. }
  554. }
  555. .special-action-button,
  556. .back-link {
  557. text-align: right;
  558. flex: 1 1 auto;
  559. }
  560. .action-buttons {
  561. display: flex;
  562. overflow: hidden;
  563. justify-content: space-between;
  564. }
  565. .spacer {
  566. flex: 1 1 auto;
  567. }
  568. .log-entry {
  569. display: block;
  570. line-height: 20px;
  571. padding: 15px;
  572. padding-left: 15px * 2 + 40px;
  573. background: $ui-base-color;
  574. border-bottom: 1px solid darken($ui-base-color, 8%);
  575. position: relative;
  576. text-decoration: none;
  577. color: $darker-text-color;
  578. font-size: 14px;
  579. &:first-child {
  580. border-top-left-radius: 4px;
  581. border-top-right-radius: 4px;
  582. }
  583. &:last-child {
  584. border-bottom-left-radius: 4px;
  585. border-bottom-right-radius: 4px;
  586. border-bottom: 0;
  587. }
  588. &:hover,
  589. &:focus,
  590. &:active {
  591. background: lighten($ui-base-color, 4%);
  592. }
  593. &__avatar {
  594. position: absolute;
  595. left: 15px;
  596. top: 15px;
  597. .avatar {
  598. border-radius: 4px;
  599. width: 40px;
  600. height: 40px;
  601. }
  602. }
  603. &__title {
  604. word-wrap: break-word;
  605. }
  606. &__timestamp {
  607. color: $dark-text-color;
  608. }
  609. a,
  610. .username,
  611. .target {
  612. color: $secondary-text-color;
  613. text-decoration: none;
  614. font-weight: 500;
  615. }
  616. a {
  617. &:hover,
  618. &:focus,
  619. &:active {
  620. text-decoration: underline;
  621. }
  622. }
  623. }
  624. a.name-tag,
  625. .name-tag,
  626. a.inline-name-tag,
  627. .inline-name-tag {
  628. text-decoration: none;
  629. color: $secondary-text-color;
  630. .username {
  631. font-weight: 500;
  632. }
  633. &.suspended {
  634. .username {
  635. text-decoration: line-through;
  636. color: lighten($error-red, 12%);
  637. }
  638. .avatar {
  639. filter: grayscale(100%);
  640. opacity: 0.8;
  641. }
  642. }
  643. }
  644. a.name-tag,
  645. .name-tag {
  646. display: inline-flex;
  647. align-items: center;
  648. vertical-align: top;
  649. .avatar {
  650. display: block;
  651. margin: 0;
  652. margin-right: 5px;
  653. border-radius: 50%;
  654. }
  655. &.suspended {
  656. .avatar {
  657. filter: grayscale(100%);
  658. opacity: 0.8;
  659. }
  660. }
  661. }
  662. .speech-bubble {
  663. margin-bottom: 20px;
  664. border-left: 4px solid $ui-highlight-color;
  665. &.positive {
  666. border-left-color: $success-green;
  667. }
  668. &.negative {
  669. border-left-color: lighten($error-red, 12%);
  670. }
  671. &.warning {
  672. border-left-color: $gold-star;
  673. }
  674. &__bubble {
  675. padding: 16px;
  676. padding-left: 14px;
  677. font-size: 15px;
  678. line-height: 20px;
  679. border-radius: 4px 4px 4px 0;
  680. position: relative;
  681. font-weight: 500;
  682. a {
  683. color: $darker-text-color;
  684. }
  685. }
  686. &__owner {
  687. padding: 8px;
  688. padding-left: 12px;
  689. }
  690. time {
  691. color: $dark-text-color;
  692. }
  693. }
  694. .report-card {
  695. background: $ui-base-color;
  696. border-radius: 4px;
  697. margin-bottom: 20px;
  698. &__profile {
  699. display: flex;
  700. justify-content: space-between;
  701. align-items: center;
  702. padding: 15px;
  703. .account {
  704. padding: 0;
  705. border: 0;
  706. &__avatar-wrapper {
  707. margin-left: 0;
  708. }
  709. }
  710. &__stats {
  711. flex: 0 0 auto;
  712. font-weight: 500;
  713. color: $darker-text-color;
  714. text-transform: uppercase;
  715. text-align: right;
  716. a {
  717. color: inherit;
  718. text-decoration: none;
  719. &:focus,
  720. &:hover,
  721. &:active {
  722. color: lighten($darker-text-color, 8%);
  723. }
  724. }
  725. .red {
  726. color: $error-value-color;
  727. }
  728. }
  729. }
  730. &__summary {
  731. &__item {
  732. display: flex;
  733. justify-content: flex-start;
  734. border-top: 1px solid darken($ui-base-color, 4%);
  735. &:hover {
  736. background: lighten($ui-base-color, 2%);
  737. }
  738. &__reported-by,
  739. &__assigned {
  740. padding: 15px;
  741. flex: 0 0 auto;
  742. box-sizing: border-box;
  743. width: 150px;
  744. color: $darker-text-color;
  745. &,
  746. .username {
  747. white-space: nowrap;
  748. overflow: hidden;
  749. text-overflow: ellipsis;
  750. }
  751. }
  752. &__content {
  753. flex: 1 1 auto;
  754. max-width: calc(100% - 300px);
  755. &__icon {
  756. color: $dark-text-color;
  757. margin-right: 4px;
  758. font-weight: 500;
  759. }
  760. }
  761. &__content a {
  762. display: block;
  763. box-sizing: border-box;
  764. width: 100%;
  765. padding: 15px;
  766. text-decoration: none;
  767. color: $darker-text-color;
  768. }
  769. }
  770. }
  771. }
  772. .one-line {
  773. white-space: nowrap;
  774. overflow: hidden;
  775. text-overflow: ellipsis;
  776. }
  777. .ellipsized-ip {
  778. display: inline-block;
  779. max-width: 120px;
  780. overflow: hidden;
  781. text-overflow: ellipsis;
  782. vertical-align: middle;
  783. }
  784. .admin-account-bio {
  785. display: flex;
  786. flex-wrap: wrap;
  787. margin: 0 -5px;
  788. margin-top: 20px;
  789. > div {
  790. box-sizing: border-box;
  791. padding: 0 5px;
  792. margin-bottom: 10px;
  793. flex: 1 0 50%;
  794. max-width: 100%;
  795. }
  796. .account__header__fields,
  797. .account__header__content {
  798. background: lighten($ui-base-color, 8%);
  799. border-radius: 4px;
  800. height: 100%;
  801. }
  802. .account__header__fields {
  803. margin: 0;
  804. border: 0;
  805. a {
  806. color: $highlight-text-color;
  807. }
  808. dl:first-child .verified {
  809. border-radius: 0 4px 0 0;
  810. }
  811. .verified a {
  812. color: $valid-value-color;
  813. }
  814. }
  815. .account__header__content {
  816. box-sizing: border-box;
  817. padding: 20px;
  818. color: $primary-text-color;
  819. }
  820. }
  821. .center-text {
  822. text-align: center;
  823. }
  824. .applications-list__item,
  825. .filters-list__item {
  826. padding: 15px 0;
  827. background: $ui-base-color;
  828. border: 1px solid lighten($ui-base-color, 4%);
  829. border-radius: 4px;
  830. margin-top: 15px;
  831. }
  832. .user-role {
  833. color: var(--user-role-accent);
  834. }
  835. .announcements-list,
  836. .filters-list {
  837. border: 1px solid lighten($ui-base-color, 4%);
  838. border-radius: 4px;
  839. &__item {
  840. padding: 15px 0;
  841. background: $ui-base-color;
  842. border-bottom: 1px solid lighten($ui-base-color, 4%);
  843. &__title {
  844. padding: 0 15px;
  845. display: block;
  846. font-weight: 500;
  847. font-size: 18px;
  848. line-height: 1.5;
  849. color: $secondary-text-color;
  850. text-decoration: none;
  851. margin-bottom: 10px;
  852. .account-role {
  853. vertical-align: middle;
  854. }
  855. }
  856. a.announcements-list__item__title {
  857. &:hover,
  858. &:focus,
  859. &:active {
  860. color: $primary-text-color;
  861. }
  862. }
  863. &__meta {
  864. padding: 0 15px;
  865. color: $dark-text-color;
  866. a {
  867. color: inherit;
  868. text-decoration: underline;
  869. &:hover,
  870. &:focus,
  871. &:active {
  872. text-decoration: none;
  873. }
  874. }
  875. }
  876. &__action-bar {
  877. display: flex;
  878. justify-content: space-between;
  879. align-items: center;
  880. }
  881. &__permissions {
  882. margin-top: 10px;
  883. }
  884. &:last-child {
  885. border-bottom: 0;
  886. }
  887. }
  888. }
  889. .filters-list__item {
  890. &__title {
  891. display: flex;
  892. justify-content: space-between;
  893. margin-bottom: 0;
  894. }
  895. &__permissions {
  896. margin-top: 0;
  897. margin-bottom: 10px;
  898. }
  899. .expiration {
  900. font-size: 13px;
  901. }
  902. &.expired {
  903. .expiration {
  904. color: lighten($error-red, 12%);
  905. }
  906. .permissions-list__item__icon {
  907. color: $dark-text-color;
  908. }
  909. }
  910. }
  911. .dashboard__counters.admin-account-counters {
  912. margin-top: 10px;
  913. }
  914. .account-badges {
  915. margin: -2px 0;
  916. }
  917. .retention {
  918. overflow: auto;
  919. > h4 {
  920. position: sticky;
  921. left: 0;
  922. }
  923. &__table {
  924. &__number {
  925. color: $secondary-text-color;
  926. padding: 10px;
  927. }
  928. &__date {
  929. white-space: nowrap;
  930. padding: 10px 0;
  931. text-align: left;
  932. min-width: 120px;
  933. &.retention__table__average {
  934. font-weight: 700;
  935. }
  936. }
  937. &__size {
  938. text-align: center;
  939. padding: 10px;
  940. }
  941. &__label {
  942. font-weight: 700;
  943. color: $darker-text-color;
  944. }
  945. &__box {
  946. box-sizing: border-box;
  947. background: $ui-highlight-color;
  948. padding: 10px;
  949. font-weight: 500;
  950. color: $primary-text-color;
  951. width: 52px;
  952. margin: 1px;
  953. @for $i from 0 through 10 {
  954. &--#{10 * $i} {
  955. background-color: rgba($ui-highlight-color, 1 * (math.div(max(1, $i), 10)));
  956. }
  957. }
  958. }
  959. }
  960. }
  961. .sparkline {
  962. display: block;
  963. text-decoration: none;
  964. background: lighten($ui-base-color, 4%);
  965. border-radius: 4px;
  966. padding: 0;
  967. position: relative;
  968. padding-bottom: 55px + 20px;
  969. overflow: hidden;
  970. &__value {
  971. display: flex;
  972. line-height: 33px;
  973. align-items: flex-end;
  974. padding: 20px;
  975. padding-bottom: 10px;
  976. &__total {
  977. display: block;
  978. margin-right: 10px;
  979. font-weight: 500;
  980. font-size: 28px;
  981. color: $primary-text-color;
  982. }
  983. &__change {
  984. display: block;
  985. font-weight: 500;
  986. font-size: 18px;
  987. color: $darker-text-color;
  988. margin-bottom: -3px;
  989. &.positive {
  990. color: $valid-value-color;
  991. }
  992. &.negative {
  993. color: $error-value-color;
  994. }
  995. }
  996. }
  997. &__label {
  998. padding: 0 20px;
  999. padding-bottom: 10px;
  1000. text-transform: uppercase;
  1001. color: $darker-text-color;
  1002. font-weight: 500;
  1003. }
  1004. &__graph {
  1005. position: absolute;
  1006. bottom: 0;
  1007. width: 100%;
  1008. svg {
  1009. display: block;
  1010. margin: 0;
  1011. }
  1012. path:first-child {
  1013. fill: rgba($highlight-text-color, 0.25) !important;
  1014. fill-opacity: 100% !important;
  1015. }
  1016. path:last-child {
  1017. stroke: lighten($highlight-text-color, 6%) !important;
  1018. fill: none !important;
  1019. }
  1020. }
  1021. }
  1022. a.sparkline {
  1023. &:hover,
  1024. &:focus,
  1025. &:active {
  1026. background: lighten($ui-base-color, 6%);
  1027. }
  1028. }
  1029. .skeleton {
  1030. background-color: lighten($ui-base-color, 8%);
  1031. background-image: linear-gradient(90deg, lighten($ui-base-color, 8%), lighten($ui-base-color, 12%), lighten($ui-base-color, 8%));
  1032. background-size: 200px 100%;
  1033. background-repeat: no-repeat;
  1034. border-radius: 4px;
  1035. display: inline-block;
  1036. line-height: 1;
  1037. width: 100%;
  1038. animation: skeleton 1.2s ease-in-out infinite;
  1039. }
  1040. @keyframes skeleton {
  1041. 0% {
  1042. background-position: -200px 0;
  1043. }
  1044. 100% {
  1045. background-position: calc(200px + 100%) 0;
  1046. }
  1047. }
  1048. .dimension {
  1049. table {
  1050. width: 100%;
  1051. }
  1052. &__item {
  1053. border-bottom: 1px solid lighten($ui-base-color, 4%);
  1054. &__key {
  1055. font-weight: 500;
  1056. padding: 11px 10px;
  1057. }
  1058. &__value {
  1059. text-align: right;
  1060. color: $darker-text-color;
  1061. padding: 11px 10px;
  1062. }
  1063. &__indicator {
  1064. display: inline-block;
  1065. width: 8px;
  1066. height: 8px;
  1067. border-radius: 50%;
  1068. background: $ui-highlight-color;
  1069. margin-right: 10px;
  1070. @for $i from 0 through 10 {
  1071. &--#{10 * $i} {
  1072. background-color: rgba($ui-highlight-color, 1 * (math.div(max(1, $i), 10)));
  1073. }
  1074. }
  1075. }
  1076. &:last-child {
  1077. border-bottom: 0;
  1078. }
  1079. }
  1080. }
  1081. .report-reason-selector {
  1082. border-radius: 4px;
  1083. background: $ui-base-color;
  1084. margin-bottom: 20px;
  1085. &__category {
  1086. cursor: pointer;
  1087. border-bottom: 1px solid darken($ui-base-color, 8%);
  1088. &:last-child {
  1089. border-bottom: 0;
  1090. }
  1091. &__label {
  1092. padding: 15px;
  1093. }
  1094. &__rules {
  1095. margin-left: 30px;
  1096. }
  1097. }
  1098. &__rule {
  1099. cursor: pointer;
  1100. padding: 15px;
  1101. }
  1102. }
  1103. .report-header {
  1104. display: grid;
  1105. grid-gap: 15px;
  1106. grid-template-columns: minmax(0, 1fr) 300px;
  1107. &__details {
  1108. &__item {
  1109. border-bottom: 1px solid lighten($ui-base-color, 8%);
  1110. padding: 15px 0;
  1111. &:last-child {
  1112. border-bottom: 0;
  1113. }
  1114. &__header {
  1115. font-weight: 600;
  1116. padding: 4px 0;
  1117. }
  1118. }
  1119. &--horizontal {
  1120. display: grid;
  1121. grid-auto-columns: minmax(0, 1fr);
  1122. grid-auto-flow: column;
  1123. .report-header__details__item {
  1124. border-bottom: 0;
  1125. }
  1126. }
  1127. }
  1128. @media screen and (max-width: 930px) {
  1129. grid-template-columns: minmax(0, 1fr);
  1130. }
  1131. }
  1132. .account-card {
  1133. background: $ui-base-color;
  1134. border-radius: 4px;
  1135. &__permalink {
  1136. color: inherit;
  1137. text-decoration: none;
  1138. }
  1139. &__header {
  1140. padding: 4px;
  1141. border-radius: 4px;
  1142. height: 128px;
  1143. img {
  1144. display: block;
  1145. margin: 0;
  1146. width: 100%;
  1147. height: 100%;
  1148. object-fit: cover;
  1149. background: darken($ui-base-color, 8%);
  1150. }
  1151. }
  1152. &__title {
  1153. margin-top: -(15px + 8px);
  1154. display: flex;
  1155. align-items: flex-end;
  1156. &__avatar {
  1157. padding: 14px;
  1158. img,
  1159. .account__avatar {
  1160. display: block;
  1161. margin: 0;
  1162. width: 56px;
  1163. height: 56px;
  1164. background-color: darken($ui-base-color, 8%);
  1165. border-radius: 8px;
  1166. border: 1px solid $ui-base-color;
  1167. }
  1168. }
  1169. .display-name {
  1170. color: $darker-text-color;
  1171. padding-bottom: 15px;
  1172. font-size: 15px;
  1173. line-height: 20px;
  1174. bdi {
  1175. display: block;
  1176. color: $primary-text-color;
  1177. font-weight: 700;
  1178. }
  1179. }
  1180. }
  1181. &__bio {
  1182. padding: 0 15px;
  1183. margin: 8px 0;
  1184. overflow: hidden;
  1185. text-overflow: ellipsis;
  1186. word-wrap: break-word;
  1187. max-height: 21px * 2;
  1188. position: relative;
  1189. font-size: 15px;
  1190. line-height: 21px;
  1191. &::after {
  1192. display: block;
  1193. content: "";
  1194. width: 50px;
  1195. height: 21px;
  1196. position: absolute;
  1197. bottom: 0;
  1198. right: 15px;
  1199. background: linear-gradient(to left, $ui-base-color, transparent);
  1200. pointer-events: none;
  1201. }
  1202. a {
  1203. color: $secondary-text-color;
  1204. text-decoration: none;
  1205. unicode-bidi: isolate;
  1206. &:hover {
  1207. text-decoration: underline;
  1208. }
  1209. &.mention {
  1210. &:hover {
  1211. text-decoration: none;
  1212. span {
  1213. text-decoration: underline;
  1214. }
  1215. }
  1216. }
  1217. }
  1218. }
  1219. &__actions {
  1220. display: flex;
  1221. justify-content: space-between;
  1222. align-items: center;
  1223. &__button {
  1224. flex-shrink: 1;
  1225. padding: 0 15px;
  1226. overflow: hidden;
  1227. .button {
  1228. min-width: 0;
  1229. white-space: nowrap;
  1230. text-overflow: ellipsis;
  1231. overflow: hidden;
  1232. max-width: 100%;
  1233. }
  1234. }
  1235. }
  1236. &__counters {
  1237. flex: 1 1 auto;
  1238. display: grid;
  1239. grid-auto-columns: minmax(0, 1fr);
  1240. grid-auto-flow: column;
  1241. max-width: 340px;
  1242. min-width: 65px * 3;
  1243. &__item {
  1244. padding: 15px 0;
  1245. text-align: center;
  1246. color: $primary-text-color;
  1247. font-weight: 600;
  1248. font-size: 15px;
  1249. line-height: 21px;
  1250. small {
  1251. display: block;
  1252. color: $darker-text-color;
  1253. font-weight: 400;
  1254. font-size: 13px;
  1255. line-height: 18px;
  1256. }
  1257. }
  1258. }
  1259. }
  1260. .report-notes {
  1261. margin-bottom: 20px;
  1262. &__item {
  1263. background: $ui-base-color;
  1264. position: relative;
  1265. padding: 15px;
  1266. padding-left: 15px * 2 + 40px;
  1267. border-bottom: 1px solid darken($ui-base-color, 8%);
  1268. &:first-child {
  1269. border-top-left-radius: 4px;
  1270. border-top-right-radius: 4px;
  1271. }
  1272. &:last-child {
  1273. border-bottom-left-radius: 4px;
  1274. border-bottom-right-radius: 4px;
  1275. border-bottom: 0;
  1276. }
  1277. &:hover {
  1278. background-color: lighten($ui-base-color, 4%);
  1279. }
  1280. &__avatar {
  1281. position: absolute;
  1282. left: 15px;
  1283. top: 15px;
  1284. border-radius: 4px;
  1285. width: 40px;
  1286. height: 40px;
  1287. }
  1288. &__header {
  1289. color: $darker-text-color;
  1290. font-size: 15px;
  1291. line-height: 20px;
  1292. margin-bottom: 4px;
  1293. .username {
  1294. color: $primary-text-color;
  1295. font-weight: 500;
  1296. margin-right: 5px;
  1297. a {
  1298. color: inherit;
  1299. text-decoration: none;
  1300. &:hover,
  1301. &:focus,
  1302. &:active {
  1303. text-decoration: underline;
  1304. }
  1305. }
  1306. }
  1307. time {
  1308. margin-left: 5px;
  1309. vertical-align: baseline;
  1310. }
  1311. }
  1312. &__content {
  1313. font-size: 15px;
  1314. line-height: 20px;
  1315. word-wrap: break-word;
  1316. font-weight: 400;
  1317. color: $primary-text-color;
  1318. p {
  1319. margin-bottom: 20px;
  1320. white-space: pre-wrap;
  1321. unicode-bidi: plaintext;
  1322. &:last-child {
  1323. margin-bottom: 0;
  1324. }
  1325. }
  1326. }
  1327. &__actions {
  1328. position: absolute;
  1329. top: 15px;
  1330. right: 15px;
  1331. text-align: right;
  1332. }
  1333. }
  1334. }
  1335. .report-actions {
  1336. border: 1px solid darken($ui-base-color, 8%);
  1337. &__item {
  1338. display: flex;
  1339. align-items: center;
  1340. line-height: 18px;
  1341. border-bottom: 1px solid darken($ui-base-color, 8%);
  1342. &:last-child {
  1343. border-bottom: 0;
  1344. }
  1345. &__button {
  1346. box-sizing: border-box;
  1347. flex: 0 0 auto;
  1348. width: 200px;
  1349. padding: 15px;
  1350. padding-right: 0;
  1351. .button {
  1352. display: block;
  1353. width: 100%;
  1354. }
  1355. }
  1356. &__description {
  1357. padding: 15px;
  1358. font-size: 14px;
  1359. color: $dark-text-color;
  1360. }
  1361. }
  1362. @media screen and (max-width: 800px) {
  1363. border: 0;
  1364. &__item {
  1365. flex-direction: column;
  1366. border: 0;
  1367. &__button {
  1368. width: 100%;
  1369. padding: 15px 0;
  1370. }
  1371. &__description {
  1372. padding: 0;
  1373. padding-bottom: 15px;
  1374. }
  1375. }
  1376. }
  1377. }
  1378. .section-skip-link {
  1379. float: right;
  1380. a {
  1381. color: $ui-highlight-color;
  1382. text-decoration: none;
  1383. &:hover,
  1384. &:focus,
  1385. &:active {
  1386. text-decoration: underline;
  1387. }
  1388. }
  1389. }
  1390. .strike-card {
  1391. padding: 15px;
  1392. border-radius: 4px;
  1393. background: $ui-base-color;
  1394. font-size: 15px;
  1395. line-height: 20px;
  1396. word-wrap: break-word;
  1397. font-weight: 400;
  1398. color: $primary-text-color;
  1399. box-sizing: border-box;
  1400. min-height: 100%;
  1401. a {
  1402. color: $highlight-text-color;
  1403. text-decoration: none;
  1404. &:hover {
  1405. text-decoration: underline;
  1406. }
  1407. }
  1408. p {
  1409. margin-bottom: 20px;
  1410. unicode-bidi: plaintext;
  1411. &:last-child {
  1412. margin-bottom: 0;
  1413. }
  1414. strong {
  1415. font-weight: 700;
  1416. }
  1417. }
  1418. &__rules {
  1419. list-style: disc;
  1420. padding-left: 15px;
  1421. margin-bottom: 20px;
  1422. color: $darker-text-color;
  1423. &:last-child {
  1424. margin-bottom: 0;
  1425. }
  1426. &__text {
  1427. color: $primary-text-color;
  1428. }
  1429. }
  1430. &__statuses-list {
  1431. border-radius: 4px;
  1432. border: 1px solid darken($ui-base-color, 8%);
  1433. font-size: 13px;
  1434. line-height: 18px;
  1435. overflow: hidden;
  1436. &__item {
  1437. padding: 16px;
  1438. background: lighten($ui-base-color, 2%);
  1439. border-bottom: 1px solid darken($ui-base-color, 8%);
  1440. &:last-child {
  1441. border-bottom: 0;
  1442. }
  1443. &__meta {
  1444. color: $darker-text-color;
  1445. }
  1446. a {
  1447. color: inherit;
  1448. text-decoration: none;
  1449. &:hover,
  1450. &:focus,
  1451. &:active {
  1452. text-decoration: underline;
  1453. }
  1454. }
  1455. }
  1456. }
  1457. }
  1458. .availability-indicator {
  1459. display: flex;
  1460. align-items: center;
  1461. margin-bottom: 30px;
  1462. font-size: 14px;
  1463. line-height: 21px;
  1464. &__hint {
  1465. padding: 0 15px;
  1466. }
  1467. &__graphic {
  1468. display: flex;
  1469. margin: 0 -2px;
  1470. &__item {
  1471. display: block;
  1472. flex: 0 0 auto;
  1473. width: 4px;
  1474. height: 21px;
  1475. background: lighten($ui-base-color, 8%);
  1476. margin: 0 2px;
  1477. border-radius: 2px;
  1478. &.positive {
  1479. background: $valid-value-color;
  1480. }
  1481. &.negative {
  1482. background: $error-value-color;
  1483. }
  1484. }
  1485. }
  1486. }
  1487. .history {
  1488. counter-reset: step 0;
  1489. font-size: 15px;
  1490. line-height: 22px;
  1491. li {
  1492. counter-increment: step 1;
  1493. padding-left: 2.5rem;
  1494. padding-bottom: 8px;
  1495. position: relative;
  1496. margin-bottom: 8px;
  1497. &::before {
  1498. position: absolute;
  1499. content: counter(step);
  1500. font-size: 0.625rem;
  1501. font-weight: 500;
  1502. left: 0;
  1503. display: flex;
  1504. justify-content: center;
  1505. align-items: center;
  1506. width: calc(1.375rem + 1px);
  1507. height: calc(1.375rem + 1px);
  1508. background: $ui-base-color;
  1509. border: 1px solid $highlight-text-color;
  1510. color: $highlight-text-color;
  1511. border-radius: 8px;
  1512. }
  1513. &::after {
  1514. position: absolute;
  1515. content: "";
  1516. width: 1px;
  1517. background: $highlight-text-color;
  1518. bottom: 0;
  1519. top: calc(1.875rem + 1px);
  1520. left: 0.6875rem;
  1521. }
  1522. &:last-child {
  1523. margin-bottom: 0;
  1524. &::after {
  1525. display: none;
  1526. }
  1527. }
  1528. }
  1529. &__entry {
  1530. h5 {
  1531. font-weight: 500;
  1532. color: $primary-text-color;
  1533. line-height: 25px;
  1534. margin-bottom: 16px;
  1535. }
  1536. .status {
  1537. border: 1px solid lighten($ui-base-color, 4%);
  1538. background: $ui-base-color;
  1539. border-radius: 4px;
  1540. }
  1541. }
  1542. }