slipway-theme 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. checksums.yaml +4 -4
  2. data/_includes/blocks/annotations.html +18 -0
  3. data/_includes/blocks/audio.html +22 -0
  4. data/_includes/blocks/badge.html +2 -0
  5. data/_includes/blocks/chart.html +32 -0
  6. data/_includes/blocks/citation.html +12 -0
  7. data/_includes/blocks/code-group.html +10 -0
  8. data/_includes/blocks/compare.html +64 -0
  9. data/_includes/blocks/diff.html +31 -0
  10. data/_includes/blocks/download.html +28 -0
  11. data/_includes/blocks/endpoint.html +50 -0
  12. data/_includes/blocks/file-tree.html +52 -0
  13. data/_includes/blocks/gallery.html +18 -0
  14. data/_includes/blocks/hero.html +30 -0
  15. data/_includes/blocks/kbd.html +27 -0
  16. data/_includes/blocks/logos.html +21 -0
  17. data/_includes/blocks/people.html +47 -0
  18. data/_includes/blocks/pricing.html +28 -0
  19. data/_includes/blocks/pull-quote.html +22 -0
  20. data/_includes/blocks/stats.html +14 -0
  21. data/_includes/blocks/steps.html +24 -0
  22. data/_includes/blocks/terminal.html +14 -0
  23. data/_includes/blocks/testimonial.html +23 -0
  24. data/_includes/blocks/timeline.html +23 -0
  25. data/_includes/breadcrumbs.html +16 -0
  26. data/_includes/changelog-version.html +6 -0
  27. data/_includes/comments.html +19 -0
  28. data/_includes/edit-sources.html +11 -2
  29. data/_includes/head.html +5 -0
  30. data/_includes/i18n/ar.html +35 -0
  31. data/_includes/i18n/az.html +78 -0
  32. data/_includes/i18n/bn.html +78 -0
  33. data/_includes/i18n/ckb.html +78 -0
  34. data/_includes/i18n/cs.html +78 -0
  35. data/_includes/i18n/da.html +78 -0
  36. data/_includes/i18n/de.html +35 -0
  37. data/_includes/i18n/dv.html +78 -0
  38. data/_includes/i18n/el.html +78 -0
  39. data/_includes/i18n/en.html +35 -0
  40. data/_includes/i18n/es.html +35 -0
  41. data/_includes/i18n/fa.html +35 -0
  42. data/_includes/i18n/fi.html +78 -0
  43. data/_includes/i18n/fr.html +35 -0
  44. data/_includes/i18n/he.html +36 -0
  45. data/_includes/i18n/hi.html +78 -0
  46. data/_includes/i18n/hu.html +78 -0
  47. data/_includes/i18n/id.html +78 -0
  48. data/_includes/i18n/it.html +35 -0
  49. data/_includes/i18n/ja.html +35 -0
  50. data/_includes/i18n/ko.html +78 -0
  51. data/_includes/i18n/ms.html +78 -0
  52. data/_includes/i18n/nb.html +78 -0
  53. data/_includes/i18n/nl.html +35 -0
  54. data/_includes/i18n/pl.html +78 -0
  55. data/_includes/i18n/ps.html +78 -0
  56. data/_includes/i18n/pt.html +35 -0
  57. data/_includes/i18n/ro.html +78 -0
  58. data/_includes/i18n/ru.html +35 -0
  59. data/_includes/i18n/sd.html +78 -0
  60. data/_includes/i18n/sv.html +78 -0
  61. data/_includes/i18n/sw.html +78 -0
  62. data/_includes/i18n/ta.html +78 -0
  63. data/_includes/i18n/th.html +78 -0
  64. data/_includes/i18n/tr.html +35 -0
  65. data/_includes/i18n/ug.html +78 -0
  66. data/_includes/i18n/uk.html +78 -0
  67. data/_includes/i18n/ur.html +78 -0
  68. data/_includes/i18n/vi.html +78 -0
  69. data/_includes/i18n/yi.html +78 -0
  70. data/_includes/i18n/zh.html +35 -0
  71. data/_includes/i18n-builtin.html +1 -1
  72. data/_includes/jsonld.html +5 -3
  73. data/_includes/last-updated.html +12 -0
  74. data/_includes/page-status.html +19 -0
  75. data/_includes/schema-table.html +122 -0
  76. data/_includes/seo.html +23 -3
  77. data/_includes/snippet.html +20 -0
  78. data/_layouts/adr-index.html +32 -0
  79. data/_layouts/adr.html +45 -0
  80. data/_layouts/changelog-feed.html +28 -0
  81. data/_layouts/changelog.html +40 -0
  82. data/_layouts/doc.html +28 -6
  83. data/_layouts/feed.html +2 -2
  84. data/_layouts/links.html +31 -0
  85. data/_layouts/not-found.html +8 -0
  86. data/_layouts/page.html +7 -2
  87. data/_layouts/post.html +33 -0
  88. data/_layouts/search-index.html +32 -2
  89. data/_layouts/sitemap.html +1 -1
  90. data/assets/css/components/adr.css +11 -0
  91. data/assets/css/components/annotations.css +6 -0
  92. data/assets/css/components/audio.css +8 -0
  93. data/assets/css/components/badge.css +13 -0
  94. data/assets/css/components/changelog.css +11 -0
  95. data/assets/css/components/chart.css +7 -0
  96. data/assets/css/components/citation.css +5 -0
  97. data/assets/css/components/code-group.css +9 -0
  98. data/assets/css/components/compare.css +8 -0
  99. data/assets/css/components/diff.css +9 -0
  100. data/assets/css/components/download.css +7 -0
  101. data/assets/css/components/endpoint.css +1 -0
  102. data/assets/css/components/file-tree.css +12 -0
  103. data/assets/css/components/gallery.css +6 -0
  104. data/assets/css/components/hero.css +11 -0
  105. data/assets/css/components/kbd.css +4 -0
  106. data/assets/css/components/logos.css +8 -0
  107. data/assets/css/components/mirror.css +1 -0
  108. data/assets/css/components/page-status.css +5 -0
  109. data/assets/css/components/people.css +7 -0
  110. data/assets/css/components/pricing.css +9 -0
  111. data/assets/css/components/pull-quote.css +6 -0
  112. data/assets/css/components/schema-table.css +13 -0
  113. data/assets/css/components/stats.css +1 -0
  114. data/assets/css/components/steps.css +10 -0
  115. data/assets/css/components/terminal.css +17 -0
  116. data/assets/css/components/testimonial.css +8 -0
  117. data/assets/css/components/timeline.css +11 -0
  118. data/assets/css/lang/ckb.css +6 -0
  119. data/assets/css/lang/dv.css +6 -0
  120. data/assets/css/lang/ps.css +3 -0
  121. data/assets/css/lang/sd.css +10 -0
  122. data/assets/css/lang/ug.css +3 -0
  123. data/assets/css/lang/ur.css +10 -0
  124. data/assets/css/lang/yi.css +5 -0
  125. data/assets/css/slipway.css +54 -1
  126. data/assets/js/copy-code.js +1 -1
  127. data/assets/js/search.js +12 -10
  128. data/assets/og/template.svg +39 -0
  129. metadata +99 -2
@@ -1,4 +1,4 @@
1
- /* Base styles. Every value comes from assets/css/tokens.css. Logical properties only. */
1
+ /* Base styles from tokens.css. Logical properties. */
2
2
  @layer base {
3
3
  html {
4
4
  background: var(--sl-color-canvas);
@@ -503,6 +503,47 @@
503
503
  }
504
504
  }
505
505
 
506
+ /* Post reading progress: a scroll-driven bar at the top of the viewport, pure CSS with no JavaScript.
507
+ Without `animation-timeline` support the fill stays at scaleX(0) and nothing shows. */
508
+ @layer components {
509
+ .sl-progress {
510
+ position: fixed;
511
+ inset-block-start: 0;
512
+ inset-inline: 0;
513
+ block-size: 2px;
514
+ z-index: 10;
515
+ pointer-events: none;
516
+ }
517
+
518
+ .sl-progress-fill {
519
+ block-size: 100%;
520
+ background: var(--sl-color-rose);
521
+ transform: scaleX(0);
522
+ transform-origin: 0 50%;
523
+ }
524
+
525
+ [dir="rtl"] .sl-progress-fill {
526
+ transform-origin: 100% 50%;
527
+ }
528
+
529
+ @supports (animation-timeline: scroll()) {
530
+ .sl-progress-fill {
531
+ animation: sl-progress linear both;
532
+ animation-timeline: scroll(root block);
533
+ }
534
+ }
535
+ }
536
+
537
+ @keyframes sl-progress {
538
+ from {
539
+ transform: scaleX(0);
540
+ }
541
+
542
+ to {
543
+ transform: scaleX(1);
544
+ }
545
+ }
546
+
506
547
  /* Post series: the box after the post header with the parts and the previous and next part. */
507
548
  @layer components {
508
549
  .sl-series {
@@ -557,6 +598,18 @@
557
598
  }
558
599
  }
559
600
 
601
+ /* Comments: the giscus embed at the end of a post. */
602
+ @layer components {
603
+ .sl-comments {
604
+ margin-block-start: var(--sl-space-12);
605
+ }
606
+
607
+ .sl-comments h2 {
608
+ margin-block-end: var(--sl-space-4);
609
+ font-size: var(--sl-step-lg);
610
+ }
611
+ }
612
+
560
613
  /* Authors: the byline, the author box after a post, and the author page. */
561
614
  @layer components {
562
615
  .sl-authors {
@@ -30,7 +30,7 @@
30
30
  btn.type = "button";
31
31
  btn.className = "sl-copy";
32
32
  var orig = btn.textContent = label(lang, "copy", data);
33
- bind(btn, lang, data, orig, function(c) { return c.writeText(pre.textContent); });
33
+ bind(btn, lang, data, orig, function(c) { var m=pre.querySelector(".sl-commands");return c.writeText(m?m.textContent:pre.textContent) });
34
34
  pre.parentNode.insertBefore(wrap, pre);
35
35
  wrap.appendChild(pre);
36
36
  wrap.appendChild(btn);
data/assets/js/search.js CHANGED
@@ -1,6 +1,7 @@
1
- /* Client-side search over the language's search.json. The field is hidden until this script runs, so a page
2
- needs no JavaScript to be read. Persian-aware: ي/ك become ی/ک, ZWNJ and diacritics are dropped, digits are
3
- Latin. */
1
+ /* Client-side search over the language's search.json. The field is hidden until this script runs, and the
2
+ index is fetched only when the field is first focused or typed in, so a page needs no JavaScript to be
3
+ read and pays for the index only when search is used. Persian-aware: ي/ك become ی/ک, ZWNJ and diacritics
4
+ are dropped, digits are Latin. */
4
5
  (function () {
5
6
  function normalize(text) {
6
7
  return String(text || "")
@@ -22,7 +23,7 @@
22
23
  return item[key];
23
24
  }
24
25
 
25
- /* Every query word must appear somewhere; title beats description beats text, and word starts beat the middle. */
26
+ /* Every query word must appear somewhere; title beats headings beats text, and word starts beat the middle. */
26
27
  function search(index, query, limit) {
27
28
  var terms = words(query);
28
29
  if (!terms.length) return [];
@@ -32,7 +33,7 @@
32
33
  var score = 0;
33
34
  for (var t = 0; t < terms.length; t++) {
34
35
  var s = 0;
35
- var parts = [["title", 6], ["description", 3], ["text", 1]];
36
+ var parts = [["title", 6], ["headings", 3], ["text", 1]];
36
37
  for (var p = 0; p < parts.length; p++) {
37
38
  var haystack = field(item, parts[p][0]);
38
39
  if (haystack.indexOf(" " + terms[t]) >= 0) s += parts[p][1] * 2;
@@ -62,7 +63,7 @@
62
63
  if (!loading) {
63
64
  loading = fetch(form.getAttribute("data-search"))
64
65
  .then(function (r) { return r.json(); })
65
- .then(function (data) { index = data; form.hidden = false; return data; });
66
+ .then(function (data) { index = data; return data; });
66
67
  }
67
68
  return loading;
68
69
  }
@@ -82,7 +83,7 @@
82
83
  var note = document.createElement("span");
83
84
  a.href = item.url;
84
85
  a.textContent = item.title;
85
- note.textContent = item.description || item.text.slice(0, 100);
86
+ note.textContent = item.text.slice(0, 100);
86
87
  li.appendChild(a);
87
88
  li.appendChild(note);
88
89
  list.appendChild(li);
@@ -91,8 +92,8 @@
91
92
 
92
93
  function links() { return Array.prototype.slice.call(list.querySelectorAll("a")); }
93
94
 
94
- input.addEventListener("input", function () { show(index ? search(index, input.value) : []); });
95
- input.addEventListener("focus", function () { load().then(function () { show(search(index, input.value)); }, function () {}); });
95
+ input.addEventListener("input", firstUse);
96
+ input.addEventListener("focus", firstUse);
96
97
  form.addEventListener("submit", function (event) {
97
98
  event.preventDefault();
98
99
  var first = links()[0];
@@ -106,7 +107,8 @@
106
107
  else if (event.key === "ArrowUp" && at >= 0) { event.preventDefault(); (items[at - 1] || input).focus(); }
107
108
  });
108
109
  document.addEventListener("click", function (event) { if (!form.contains(event.target)) panel.hidden = true; });
109
- load().then(function () {}, function () {});
110
+ form.hidden = false;
111
+ function firstUse() { load().then(function () { show(search(index, input.value)); }, function () {}); }
110
112
  }
111
113
 
112
114
  globalThis.slipwaySearch = { normalize: normalize, search: search };
@@ -0,0 +1,39 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="1200" height="630" viewBox="0 0 1200 630" role="img" aria-labelledby="title">
2
+ <title id="title">Slipway social card template</title>
3
+ <!-- Placeholders: ${site}, ${section}, ${title.line1}, ${title.line2}, ${title.line3}, ${url}.
4
+ Fill them with XML-escaped values and remove the title lines a page does not need.
5
+ The three line positions are the maximum; a filler moves the remaining lines down so the last sits at y=468.
6
+ RTL pages: direction="rtl" text-anchor="start" (the right edge) on the title, x=1120 on every tspan, and no letter-spacing on the title or the section.
7
+ Colors and the mark come from brand/tokens.json and tools/brand/mark.mjs; see docs/adr/0020-social-cards.md. -->
8
+ <defs>
9
+ <clipPath id="og-above"><polygon points="-112.6,-51.4 378.9,292.7 545.8,54.3 54.3,-289.8"/></clipPath>
10
+ <clipPath id="og-below"><polygon points="-122.9,-36.7 368.6,307.4 201.7,545.8 -289.8,201.7"/></clipPath>
11
+ </defs>
12
+
13
+ <rect width="1200" height="630" fill="#17130F"/>
14
+
15
+ <g transform="translate(80 64) scale(0.46)" fill="none" stroke-width="16">
16
+ <g clip-path="url(#og-above)" stroke="#F4EFE4">
17
+ <circle cx="128" cy="128" r="88"/>
18
+ <circle cx="128" cy="128" r="58"/>
19
+ </g>
20
+ <g clip-path="url(#og-below)" stroke="#B8975A">
21
+ <circle cx="128" cy="128" r="88"/>
22
+ <circle cx="128" cy="128" r="58"/>
23
+ </g>
24
+ </g>
25
+
26
+ <text x="224" y="120" fill="#F4EFE4" font-family="Inter, Vazirmatn, ui-sans-serif, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif" font-size="34" font-weight="700" letter-spacing="1.2">${site}</text>
27
+
28
+ <text x="1120" y="120" fill="#B8975A" font-family="'IBM Plex Mono', Vazirmatn, 'SFMono-Regular', Consolas, 'Liberation Mono', monospace" font-size="22" letter-spacing="3" text-anchor="end">${section}</text>
29
+
30
+ <text fill="#F4EFE4" font-family="Inter, Vazirmatn, ui-sans-serif, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif" font-size="72" font-weight="700" letter-spacing="-1">
31
+ <tspan x="80" y="300">${title.line1}</tspan>
32
+ <tspan x="80" y="384">${title.line2}</tspan>
33
+ <tspan x="80" y="468">${title.line3}</tspan>
34
+ </text>
35
+
36
+ <line x1="80" y1="508" x2="1120" y2="508" stroke="#B8975A" stroke-opacity="0.35" stroke-width="2"/>
37
+
38
+ <text x="80" y="545" fill="#A39880" font-family="'IBM Plex Mono', Vazirmatn, 'SFMono-Regular', Consolas, 'Liberation Mono', monospace" font-size="22">${url}</text>
39
+ </svg>
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: slipway-theme
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Slipway contributors
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-10-27 00:00:00.000000000 Z
11
+ date: 2026-10-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: jekyll
@@ -41,8 +41,33 @@ files:
41
41
  - _includes/author-card.html
42
42
  - _includes/author-ids.html
43
43
  - _includes/author-url.html
44
+ - _includes/blocks/annotations.html
45
+ - _includes/blocks/audio.html
46
+ - _includes/blocks/badge.html
47
+ - _includes/blocks/chart.html
48
+ - _includes/blocks/citation.html
49
+ - _includes/blocks/code-group.html
50
+ - _includes/blocks/compare.html
51
+ - _includes/blocks/diff.html
52
+ - _includes/blocks/download.html
53
+ - _includes/blocks/endpoint.html
54
+ - _includes/blocks/file-tree.html
55
+ - _includes/blocks/gallery.html
56
+ - _includes/blocks/hero.html
57
+ - _includes/blocks/kbd.html
58
+ - _includes/blocks/logos.html
59
+ - _includes/blocks/people.html
60
+ - _includes/blocks/pricing.html
61
+ - _includes/blocks/pull-quote.html
62
+ - _includes/blocks/stats.html
63
+ - _includes/blocks/steps.html
64
+ - _includes/blocks/terminal.html
65
+ - _includes/blocks/testimonial.html
66
+ - _includes/blocks/timeline.html
44
67
  - _includes/breadcrumbs.html
45
68
  - _includes/byline.html
69
+ - _includes/changelog-version.html
70
+ - _includes/comments.html
46
71
  - _includes/compat.html
47
72
  - _includes/component-css.html
48
73
  - _includes/copy-page.html
@@ -57,18 +82,45 @@ files:
57
82
  - _includes/header.html
58
83
  - _includes/i18n-builtin.html
59
84
  - _includes/i18n/ar.html
85
+ - _includes/i18n/az.html
86
+ - _includes/i18n/bn.html
87
+ - _includes/i18n/ckb.html
88
+ - _includes/i18n/cs.html
89
+ - _includes/i18n/da.html
60
90
  - _includes/i18n/de.html
91
+ - _includes/i18n/dv.html
92
+ - _includes/i18n/el.html
61
93
  - _includes/i18n/en.html
62
94
  - _includes/i18n/es.html
63
95
  - _includes/i18n/fa.html
96
+ - _includes/i18n/fi.html
64
97
  - _includes/i18n/fr.html
65
98
  - _includes/i18n/he.html
99
+ - _includes/i18n/hi.html
100
+ - _includes/i18n/hu.html
101
+ - _includes/i18n/id.html
66
102
  - _includes/i18n/it.html
67
103
  - _includes/i18n/ja.html
104
+ - _includes/i18n/ko.html
105
+ - _includes/i18n/ms.html
106
+ - _includes/i18n/nb.html
68
107
  - _includes/i18n/nl.html
108
+ - _includes/i18n/pl.html
109
+ - _includes/i18n/ps.html
69
110
  - _includes/i18n/pt.html
111
+ - _includes/i18n/ro.html
70
112
  - _includes/i18n/ru.html
113
+ - _includes/i18n/sd.html
114
+ - _includes/i18n/sv.html
115
+ - _includes/i18n/sw.html
116
+ - _includes/i18n/ta.html
117
+ - _includes/i18n/th.html
71
118
  - _includes/i18n/tr.html
119
+ - _includes/i18n/ug.html
120
+ - _includes/i18n/uk.html
121
+ - _includes/i18n/ur.html
122
+ - _includes/i18n/vi.html
123
+ - _includes/i18n/yi.html
72
124
  - _includes/i18n/zh.html
73
125
  - _includes/icons/github.svg
74
126
  - _includes/icons/linkedin.svg
@@ -78,29 +130,38 @@ files:
78
130
  - _includes/icons/youtube.svg
79
131
  - _includes/jsonld.html
80
132
  - _includes/lang-switcher.html
133
+ - _includes/last-updated.html
81
134
  - _includes/layout-url.html
82
135
  - _includes/llms-item.html
83
136
  - _includes/num.html
137
+ - _includes/page-status.html
84
138
  - _includes/post-item.html
85
139
  - _includes/related-posts.html
140
+ - _includes/schema-table.html
86
141
  - _includes/search.html
87
142
  - _includes/seo.html
88
143
  - _includes/series.html
89
144
  - _includes/skip-link.html
145
+ - _includes/snippet.html
90
146
  - _includes/t.html
91
147
  - _includes/taxonomy.html
92
148
  - _includes/term.html
93
149
  - _includes/theme-init.html
94
150
  - _includes/theme-var.html
95
151
  - _includes/theme-vars.html
152
+ - _layouts/adr-index.html
153
+ - _layouts/adr.html
96
154
  - _layouts/archive.html
97
155
  - _layouts/author.html
98
156
  - _layouts/base.html
157
+ - _layouts/changelog-feed.html
158
+ - _layouts/changelog.html
99
159
  - _layouts/default.html
100
160
  - _layouts/doc.html
101
161
  - _layouts/feed.html
102
162
  - _layouts/glossary.html
103
163
  - _layouts/home.html
164
+ - _layouts/links.html
104
165
  - _layouts/llms-full.html
105
166
  - _layouts/llms.html
106
167
  - _layouts/not-found.html
@@ -111,8 +172,43 @@ files:
111
172
  - _layouts/sourcemap.html
112
173
  - _layouts/tags.html
113
174
  - _layouts/translation-status.html
175
+ - assets/css/components/adr.css
176
+ - assets/css/components/annotations.css
177
+ - assets/css/components/audio.css
178
+ - assets/css/components/badge.css
179
+ - assets/css/components/changelog.css
180
+ - assets/css/components/chart.css
181
+ - assets/css/components/citation.css
182
+ - assets/css/components/code-group.css
183
+ - assets/css/components/compare.css
184
+ - assets/css/components/diff.css
185
+ - assets/css/components/download.css
186
+ - assets/css/components/endpoint.css
187
+ - assets/css/components/file-tree.css
188
+ - assets/css/components/gallery.css
114
189
  - assets/css/components/glossary.css
190
+ - assets/css/components/hero.css
191
+ - assets/css/components/kbd.css
192
+ - assets/css/components/logos.css
193
+ - assets/css/components/mirror.css
194
+ - assets/css/components/page-status.css
195
+ - assets/css/components/people.css
196
+ - assets/css/components/pricing.css
197
+ - assets/css/components/pull-quote.css
198
+ - assets/css/components/schema-table.css
199
+ - assets/css/components/stats.css
200
+ - assets/css/components/steps.css
201
+ - assets/css/components/terminal.css
202
+ - assets/css/components/testimonial.css
203
+ - assets/css/components/timeline.css
115
204
  - assets/css/fonts.css
205
+ - assets/css/lang/ckb.css
206
+ - assets/css/lang/dv.css
207
+ - assets/css/lang/ps.css
208
+ - assets/css/lang/sd.css
209
+ - assets/css/lang/ug.css
210
+ - assets/css/lang/ur.css
211
+ - assets/css/lang/yi.css
116
212
  - assets/css/nav.css
117
213
  - assets/css/print.css
118
214
  - assets/css/slipway.css
@@ -130,6 +226,7 @@ files:
130
226
  - assets/js/edit-prompt.js
131
227
  - assets/js/search.js
132
228
  - assets/js/theme-toggle.js
229
+ - assets/og/template.svg
133
230
  homepage: https://github.com/arminazimi/slipway
134
231
  licenses:
135
232
  - MIT