@hanology/cham-browser 0.4.27 → 0.4.29
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.
- package/package.json +1 -1
- package/template/src/components/AnnotationTooltip.vue +66 -41
- package/template/src/components/BackToTop.vue +8 -6
- package/template/src/components/HorizontalDisplay.vue +29 -9
- package/template/src/components/PoemCard.vue +7 -4
- package/template/src/components/ReadingProgress.vue +7 -7
- package/template/src/components/SectionBlock.vue +2 -2
- package/template/src/components/VerticalScroll.vue +29 -9
- package/template/src/styles/main.css +19 -1
- package/template/src/views/LibraryHome.vue +6 -3
- package/template/src/views/PieceView.vue +25 -10
package/package.json
CHANGED
|
@@ -155,21 +155,27 @@ onBeforeUnmount(() => {
|
|
|
155
155
|
<button class="ann-sheet-handle" @click="dismiss">
|
|
156
156
|
<span class="ann-handle-bar" />
|
|
157
157
|
</button>
|
|
158
|
-
<div
|
|
159
|
-
<
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
<div
|
|
164
|
-
<div class="ann-entry
|
|
165
|
-
<
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
<div
|
|
170
|
-
|
|
158
|
+
<div class="ann-sheet-body" :class="{ vertical }">
|
|
159
|
+
<div v-if="headword" class="ann-sheet-head" :class="dominantKind()">
|
|
160
|
+
<span class="ann-headword">{{ headword }}</span>
|
|
161
|
+
<span class="ann-badge-count" v-if="annotations.length > 1">{{ annotations.length }}</span>
|
|
162
|
+
</div>
|
|
163
|
+
<div class="ann-sheet-scroll">
|
|
164
|
+
<div v-for="ann in annotations" :key="ann.id" class="ann-entry">
|
|
165
|
+
<div class="ann-entry-header">
|
|
166
|
+
<span class="ann-kind" :class="ann.kind">{{ kindLabel(ann) }}</span>
|
|
167
|
+
<span v-if="layerLabel(ann)" class="ann-layer">{{ layerLabel(ann) }}</span>
|
|
168
|
+
</div>
|
|
169
|
+
<div class="ann-entry-body">
|
|
170
|
+
<div v-if="getSegment(ann)" class="ann-pron-h"><PronunciationGroup :segment="getSegment(ann)!" /></div>
|
|
171
|
+
<div v-if="ann.text && ann.kind !== 'pronunciation'" class="ann-text">{{ ann.text }}</div>
|
|
172
|
+
</div>
|
|
171
173
|
</div>
|
|
172
174
|
</div>
|
|
175
|
+
<div v-if="headword" class="ann-sheet-v-head" :class="dominantKind()">
|
|
176
|
+
<span class="ann-sheet-v-word">{{ headword }}</span>
|
|
177
|
+
<span v-if="annotations.length > 1" class="ann-badge-count-v">{{ annotations.length }}</span>
|
|
178
|
+
</div>
|
|
173
179
|
</div>
|
|
174
180
|
</div>
|
|
175
181
|
</Transition>
|
|
@@ -467,50 +473,69 @@ onBeforeUnmount(() => {
|
|
|
467
473
|
line-height: 2;
|
|
468
474
|
}
|
|
469
475
|
|
|
470
|
-
.ann-sheet
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
flex-direction:
|
|
476
|
+
.ann-sheet-body {
|
|
477
|
+
flex: 1;
|
|
478
|
+
display: flex;
|
|
479
|
+
flex-direction: column;
|
|
480
|
+
overflow: hidden;
|
|
481
|
+
min-height: 0;
|
|
474
482
|
}
|
|
475
483
|
|
|
476
|
-
.ann-sheet.vertical
|
|
477
|
-
|
|
478
|
-
position: absolute;
|
|
479
|
-
top: 0;
|
|
480
|
-
left: 0;
|
|
481
|
-
right: 0;
|
|
482
|
-
padding: 6px 0 0;
|
|
483
|
-
z-index: 1;
|
|
484
|
+
.ann-sheet-body.vertical {
|
|
485
|
+
flex-direction: row-reverse;
|
|
484
486
|
}
|
|
485
487
|
|
|
486
|
-
.ann-sheet.vertical .ann-sheet-head {
|
|
487
|
-
|
|
488
|
+
.ann-sheet-body.vertical > .ann-sheet-head {
|
|
489
|
+
display: none;
|
|
488
490
|
}
|
|
489
491
|
|
|
490
|
-
.ann-sheet.vertical .ann-sheet-
|
|
491
|
-
display:
|
|
492
|
-
flex-direction: column;
|
|
493
|
-
overflow-x: auto;
|
|
494
|
-
overflow-y: hidden;
|
|
495
|
-
padding: 8px 0 24px;
|
|
492
|
+
.ann-sheet-body:not(.vertical) > .ann-sheet-v-head {
|
|
493
|
+
display: none;
|
|
496
494
|
}
|
|
497
495
|
|
|
498
|
-
.ann-sheet
|
|
496
|
+
.ann-sheet-v-head {
|
|
497
|
+
writing-mode: vertical-rl;
|
|
498
|
+
text-orientation: upright;
|
|
499
|
+
display: flex;
|
|
500
|
+
flex-direction: row;
|
|
501
|
+
align-items: center;
|
|
502
|
+
gap: 8px;
|
|
503
|
+
padding: 12px 10px;
|
|
504
|
+
border-left: 1px solid var(--border-light);
|
|
499
505
|
flex-shrink: 0;
|
|
500
|
-
border-bottom: none;
|
|
501
|
-
padding: 0 14px;
|
|
502
|
-
border-right: 1px solid var(--border-light);
|
|
503
506
|
}
|
|
504
507
|
|
|
505
|
-
.ann-sheet
|
|
506
|
-
|
|
508
|
+
.ann-sheet-v-word {
|
|
509
|
+
font-family: var(--serif);
|
|
510
|
+
font-size: 20px;
|
|
511
|
+
font-weight: 900;
|
|
512
|
+
letter-spacing: 6px;
|
|
513
|
+
color: var(--ink);
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
.ann-badge-count-v {
|
|
517
|
+
font-family: var(--sans);
|
|
518
|
+
font-size: 11px;
|
|
519
|
+
font-weight: 700;
|
|
520
|
+
color: var(--ink-faint);
|
|
521
|
+
background: var(--surface-warm);
|
|
522
|
+
border: 1px solid var(--border-light);
|
|
523
|
+
border-radius: 10px;
|
|
524
|
+
padding: 2px 8px;
|
|
525
|
+
letter-spacing: 0;
|
|
526
|
+
writing-mode: horizontal-tb;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
.ann-sheet-body.vertical .ann-sheet-scroll {
|
|
530
|
+
flex: 1;
|
|
531
|
+
min-width: 0;
|
|
507
532
|
}
|
|
508
533
|
|
|
509
|
-
.ann-sheet.vertical .ann-pron-h {
|
|
534
|
+
.ann-sheet-body.vertical .ann-pron-h {
|
|
510
535
|
writing-mode: horizontal-tb;
|
|
511
536
|
}
|
|
512
537
|
|
|
513
|
-
.ann-sheet.vertical .ann-text {
|
|
538
|
+
.ann-sheet-body.vertical .ann-text {
|
|
514
539
|
white-space: pre-line;
|
|
515
540
|
line-height: 2;
|
|
516
541
|
}
|
|
@@ -48,18 +48,20 @@ onUnmounted(() => window.removeEventListener('scroll', onScroll))
|
|
|
48
48
|
align-items: center;
|
|
49
49
|
justify-content: center;
|
|
50
50
|
box-shadow: 0 4px 16px rgba(var(--shadow-rgb), 0.1);
|
|
51
|
-
transition: all 0.
|
|
51
|
+
transition: all 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
|
|
52
|
+
backdrop-filter: blur(8px);
|
|
53
|
+
-webkit-backdrop-filter: blur(8px);
|
|
52
54
|
}
|
|
53
55
|
|
|
54
56
|
@media (max-width: 768px) {
|
|
55
57
|
.btt { bottom: 88px; right: 16px; width: 36px; height: 36px; }
|
|
56
58
|
}
|
|
57
59
|
.btt:hover {
|
|
58
|
-
background: var(--
|
|
59
|
-
color:
|
|
60
|
-
border-color: var(--
|
|
61
|
-
transform: translateY(-
|
|
62
|
-
box-shadow: 0 8px 24px rgba(
|
|
60
|
+
background: var(--vermillion);
|
|
61
|
+
color: #fff;
|
|
62
|
+
border-color: var(--vermillion);
|
|
63
|
+
transform: translateY(-3px);
|
|
64
|
+
box-shadow: 0 8px 24px rgba(194, 58, 43, 0.2);
|
|
63
65
|
}
|
|
64
66
|
|
|
65
67
|
.btt-enter-active { transition: all 0.3s cubic-bezier(0.34, 1.56, 0.64, 1); }
|
|
@@ -44,7 +44,8 @@ function onTap(event: MouseEvent) {
|
|
|
44
44
|
<div
|
|
45
45
|
v-for="(_, i) in verses"
|
|
46
46
|
:key="i"
|
|
47
|
-
class="h-display-line"
|
|
47
|
+
class="h-display-line h-verse-anim"
|
|
48
|
+
:style="{ animationDelay: (0.15 + i * 0.08) + 's' }"
|
|
48
49
|
v-html="verseHtml(i)"
|
|
49
50
|
/>
|
|
50
51
|
</div>
|
|
@@ -59,6 +60,7 @@ function onTap(event: MouseEvent) {
|
|
|
59
60
|
padding: 40px 56px;
|
|
60
61
|
box-shadow: 0 4px 16px rgba(var(--shadow-rgb), 0.08);
|
|
61
62
|
text-align: center;
|
|
63
|
+
animation: poemReveal 0.5s var(--ease-out-expo, cubic-bezier(0.16, 1, 0.3, 1)) both;
|
|
62
64
|
}
|
|
63
65
|
.h-display-title {
|
|
64
66
|
font-size: 32px; font-weight: 900;
|
|
@@ -73,18 +75,30 @@ function onTap(event: MouseEvent) {
|
|
|
73
75
|
font-size: var(--main-font-size, 24px); line-height: 2.6;
|
|
74
76
|
letter-spacing: 4px; color: var(--ink);
|
|
75
77
|
}
|
|
78
|
+
.h-verse-anim {
|
|
79
|
+
animation: verseFade 0.45s var(--ease-out-expo, cubic-bezier(0.16, 1, 0.3, 1)) both;
|
|
80
|
+
}
|
|
81
|
+
@keyframes poemReveal {
|
|
82
|
+
from { opacity: 0; transform: translateY(16px) scale(0.98); }
|
|
83
|
+
to { opacity: 1; transform: translateY(0) scale(1); }
|
|
84
|
+
}
|
|
85
|
+
@keyframes verseFade {
|
|
86
|
+
from { opacity: 0; transform: translateY(8px); }
|
|
87
|
+
to { opacity: 1; transform: translateY(0); }
|
|
88
|
+
}
|
|
76
89
|
|
|
77
90
|
:deep(.ann-target) {
|
|
78
91
|
border-bottom: 2px solid var(--vermillion);
|
|
79
92
|
cursor: help;
|
|
80
|
-
transition: background 0.
|
|
93
|
+
transition: background 0.2s ease, box-shadow 0.2s ease;
|
|
81
94
|
}
|
|
82
95
|
:deep(.ann-target.ann-overlap) {
|
|
83
96
|
border-bottom-width: 3px;
|
|
84
97
|
border-bottom-style: double;
|
|
85
98
|
}
|
|
86
99
|
:deep(.ann-target:hover) {
|
|
87
|
-
background: rgba(194, 58, 43, 0.
|
|
100
|
+
background: rgba(194, 58, 43, 0.1);
|
|
101
|
+
box-shadow: 0 2px 8px rgba(194, 58, 43, 0.08);
|
|
88
102
|
}
|
|
89
103
|
:deep(.ann-num) {
|
|
90
104
|
font-size: 10px;
|
|
@@ -96,7 +110,8 @@ function onTap(event: MouseEvent) {
|
|
|
96
110
|
letter-spacing: 0;
|
|
97
111
|
}
|
|
98
112
|
:deep(.ann-target.pronunciation:hover) {
|
|
99
|
-
background: rgba(58, 107, 94, 0.
|
|
113
|
+
background: rgba(58, 107, 94, 0.1);
|
|
114
|
+
box-shadow: 0 2px 8px rgba(58, 107, 94, 0.08);
|
|
100
115
|
}
|
|
101
116
|
:deep(.ann-target.pronunciation) {
|
|
102
117
|
border-bottom-color: var(--jade);
|
|
@@ -117,19 +132,24 @@ function onTap(event: MouseEvent) {
|
|
|
117
132
|
border-bottom-color: var(--ann-allusion);
|
|
118
133
|
}
|
|
119
134
|
:deep(.ann-target.person:hover) {
|
|
120
|
-
background: rgba(58, 90, 140, 0.
|
|
135
|
+
background: rgba(58, 90, 140, 0.1);
|
|
136
|
+
box-shadow: 0 2px 8px rgba(58, 90, 140, 0.08);
|
|
121
137
|
}
|
|
122
138
|
:deep(.ann-target.place:hover) {
|
|
123
|
-
background: rgba(139, 105, 20, 0.
|
|
139
|
+
background: rgba(139, 105, 20, 0.1);
|
|
140
|
+
box-shadow: 0 2px 8px rgba(139, 105, 20, 0.08);
|
|
124
141
|
}
|
|
125
142
|
:deep(.ann-target.event:hover) {
|
|
126
|
-
background: rgba(107, 76, 138, 0.
|
|
143
|
+
background: rgba(107, 76, 138, 0.1);
|
|
144
|
+
box-shadow: 0 2px 8px rgba(107, 76, 138, 0.08);
|
|
127
145
|
}
|
|
128
146
|
:deep(.ann-target.date:hover) {
|
|
129
|
-
background: rgba(42, 122, 122, 0.
|
|
147
|
+
background: rgba(42, 122, 122, 0.1);
|
|
148
|
+
box-shadow: 0 2px 8px rgba(42, 122, 122, 0.08);
|
|
130
149
|
}
|
|
131
150
|
:deep(.ann-target.allusion:hover) {
|
|
132
|
-
background: rgba(181, 101, 29, 0.
|
|
151
|
+
background: rgba(181, 101, 29, 0.1);
|
|
152
|
+
box-shadow: 0 2px 8px rgba(181, 101, 29, 0.08);
|
|
133
153
|
}
|
|
134
154
|
|
|
135
155
|
@media (max-width: 768px) {
|
|
@@ -40,15 +40,16 @@ const preview = computed(() => {
|
|
|
40
40
|
position: absolute;
|
|
41
41
|
top: 0; left: 0;
|
|
42
42
|
width: 3px; height: 0;
|
|
43
|
-
background: var(--vermillion);
|
|
44
|
-
transition: height 0.
|
|
43
|
+
background: linear-gradient(180deg, var(--vermillion), var(--gold));
|
|
44
|
+
transition: height 0.35s var(--ease-out-expo, cubic-bezier(0.16, 1, 0.3, 1));
|
|
45
45
|
}
|
|
46
46
|
.pc-root:hover {
|
|
47
|
-
transform: translateY(-
|
|
48
|
-
box-shadow: 0 8px
|
|
47
|
+
transform: translateY(-3px);
|
|
48
|
+
box-shadow: 0 8px 28px rgba(var(--shadow-rgb), 0.1);
|
|
49
49
|
border-color: var(--gold);
|
|
50
50
|
}
|
|
51
51
|
.pc-root:hover .pc-accent { height: 100%; }
|
|
52
|
+
.pc-root:hover .pc-title { color: var(--vermillion); }
|
|
52
53
|
.pc-root:active { transform: scale(0.98); }
|
|
53
54
|
.pc-body { padding: 24px; }
|
|
54
55
|
.pc-num {
|
|
@@ -67,6 +68,7 @@ const preview = computed(() => {
|
|
|
67
68
|
font-size: 20px; font-weight: 700;
|
|
68
69
|
letter-spacing: 2px; margin-bottom: 6px;
|
|
69
70
|
color: var(--ink);
|
|
71
|
+
transition: color 0.25s ease;
|
|
70
72
|
}
|
|
71
73
|
.pc-author {
|
|
72
74
|
font-size: 13px; color: var(--ink-light);
|
|
@@ -130,6 +132,7 @@ const preview = computed(() => {
|
|
|
130
132
|
.pc-vertical .pc-accent {
|
|
131
133
|
top: auto; left: 0; bottom: 0;
|
|
132
134
|
width: 0; height: 3px;
|
|
135
|
+
background: linear-gradient(90deg, var(--gold), var(--vermillion));
|
|
133
136
|
transition: width 0.35s ease;
|
|
134
137
|
}
|
|
135
138
|
.pc-vertical:hover {
|
|
@@ -69,18 +69,18 @@ onUnmounted(detach)
|
|
|
69
69
|
z-index: 1001;
|
|
70
70
|
pointer-events: none;
|
|
71
71
|
will-change: width, height;
|
|
72
|
-
transition: width 0.
|
|
72
|
+
transition: width 0.08s linear, height 0.08s linear;
|
|
73
73
|
}
|
|
74
74
|
.rp:not(.rp-v) {
|
|
75
75
|
top: 0; left: 0;
|
|
76
|
-
height:
|
|
77
|
-
background: var(--vermillion);
|
|
78
|
-
box-shadow: 0 0 8px rgba(194, 58, 43, 0.
|
|
76
|
+
height: 3px;
|
|
77
|
+
background: linear-gradient(90deg, var(--vermillion), var(--gold));
|
|
78
|
+
box-shadow: 0 0 8px rgba(194, 58, 43, 0.2);
|
|
79
79
|
}
|
|
80
80
|
.rp-v {
|
|
81
81
|
top: 0; left: 0;
|
|
82
|
-
width:
|
|
83
|
-
background: var(--vermillion);
|
|
84
|
-
box-shadow: 0 0 8px rgba(194, 58, 43, 0.
|
|
82
|
+
width: 3px;
|
|
83
|
+
background: linear-gradient(180deg, var(--vermillion), var(--gold));
|
|
84
|
+
box-shadow: 0 0 8px rgba(194, 58, 43, 0.2);
|
|
85
85
|
}
|
|
86
86
|
</style>
|
|
@@ -89,8 +89,8 @@ const paragraphsHtml = computed(() => {
|
|
|
89
89
|
.sb-root {
|
|
90
90
|
margin-bottom: 40px;
|
|
91
91
|
opacity: 0;
|
|
92
|
-
transform: translateY(
|
|
93
|
-
transition: opacity 0.
|
|
92
|
+
transform: translateY(16px);
|
|
93
|
+
transition: opacity 0.6s ease, transform 0.6s var(--ease-out-expo, cubic-bezier(0.16, 1, 0.3, 1));
|
|
94
94
|
}
|
|
95
95
|
.sb-root.sb-visible {
|
|
96
96
|
opacity: 1;
|
|
@@ -47,7 +47,8 @@ function onTap(event: MouseEvent) {
|
|
|
47
47
|
<span
|
|
48
48
|
v-for="(_, i) in verses"
|
|
49
49
|
:key="i"
|
|
50
|
-
class="v-scroll-line"
|
|
50
|
+
class="v-scroll-line v-verse-anim"
|
|
51
|
+
:style="{ animationDelay: (0.2 + i * 0.06) + 's' }"
|
|
51
52
|
v-html="verseHtml(i)"
|
|
52
53
|
/>
|
|
53
54
|
</div>
|
|
@@ -68,6 +69,7 @@ function onTap(event: MouseEvent) {
|
|
|
68
69
|
position: relative;
|
|
69
70
|
scrollbar-width: thin;
|
|
70
71
|
scrollbar-color: var(--gold) transparent;
|
|
72
|
+
animation: poemRevealV 0.5s var(--ease-out-expo, cubic-bezier(0.16, 1, 0.3, 1)) both;
|
|
71
73
|
}
|
|
72
74
|
.v-scroll::-webkit-scrollbar { height: 3px; }
|
|
73
75
|
.v-scroll::-webkit-scrollbar-thumb { background: var(--gold); border-radius: 2px; }
|
|
@@ -89,12 +91,23 @@ function onTap(event: MouseEvent) {
|
|
|
89
91
|
font-size: var(--main-font-size, 24px); line-height: 2.4; letter-spacing: 6px;
|
|
90
92
|
color: var(--ink); display: block;
|
|
91
93
|
}
|
|
94
|
+
.v-verse-anim {
|
|
95
|
+
animation: verseFadeV 0.4s var(--ease-out-expo, cubic-bezier(0.16, 1, 0.3, 1)) both;
|
|
96
|
+
}
|
|
97
|
+
@keyframes poemRevealV {
|
|
98
|
+
from { opacity: 0; transform: translateX(12px); }
|
|
99
|
+
to { opacity: 1; transform: translateX(0); }
|
|
100
|
+
}
|
|
101
|
+
@keyframes verseFadeV {
|
|
102
|
+
from { opacity: 0; }
|
|
103
|
+
to { opacity: 1; }
|
|
104
|
+
}
|
|
92
105
|
|
|
93
106
|
:deep(.ann-target) {
|
|
94
107
|
border-left: 2px solid var(--vermillion);
|
|
95
108
|
padding-left: 2px;
|
|
96
109
|
cursor: help;
|
|
97
|
-
transition: background 0.
|
|
110
|
+
transition: background 0.2s ease, box-shadow 0.2s ease;
|
|
98
111
|
}
|
|
99
112
|
:deep(.ann-target.ann-overlap) {
|
|
100
113
|
border-left-width: 3px;
|
|
@@ -115,10 +128,12 @@ function onTap(event: MouseEvent) {
|
|
|
115
128
|
letter-spacing: -1px;
|
|
116
129
|
}
|
|
117
130
|
:deep(.ann-target:hover) {
|
|
118
|
-
background: rgba(194, 58, 43, 0.
|
|
131
|
+
background: rgba(194, 58, 43, 0.1);
|
|
132
|
+
box-shadow: 0 -2px 8px rgba(194, 58, 43, 0.08);
|
|
119
133
|
}
|
|
120
134
|
:deep(.ann-target.pronunciation:hover) {
|
|
121
|
-
background: rgba(58, 107, 94, 0.
|
|
135
|
+
background: rgba(58, 107, 94, 0.1);
|
|
136
|
+
box-shadow: 0 -2px 8px rgba(58, 107, 94, 0.08);
|
|
122
137
|
}
|
|
123
138
|
:deep(.ann-target.pronunciation) {
|
|
124
139
|
border-left-color: var(--jade);
|
|
@@ -142,18 +157,23 @@ function onTap(event: MouseEvent) {
|
|
|
142
157
|
border-left-color: var(--ann-allusion);
|
|
143
158
|
}
|
|
144
159
|
:deep(.ann-target.person:hover) {
|
|
145
|
-
background: rgba(58, 90, 140, 0.
|
|
160
|
+
background: rgba(58, 90, 140, 0.1);
|
|
161
|
+
box-shadow: 0 -2px 8px rgba(58, 90, 140, 0.08);
|
|
146
162
|
}
|
|
147
163
|
:deep(.ann-target.place:hover) {
|
|
148
|
-
background: rgba(139, 105, 20, 0.
|
|
164
|
+
background: rgba(139, 105, 20, 0.1);
|
|
165
|
+
box-shadow: 0 -2px 8px rgba(139, 105, 20, 0.08);
|
|
149
166
|
}
|
|
150
167
|
:deep(.ann-target.event:hover) {
|
|
151
|
-
background: rgba(107, 76, 138, 0.
|
|
168
|
+
background: rgba(107, 76, 138, 0.1);
|
|
169
|
+
box-shadow: 0 -2px 8px rgba(107, 76, 138, 0.08);
|
|
152
170
|
}
|
|
153
171
|
:deep(.ann-target.date:hover) {
|
|
154
|
-
background: rgba(42, 122, 122, 0.
|
|
172
|
+
background: rgba(42, 122, 122, 0.1);
|
|
173
|
+
box-shadow: 0 -2px 8px rgba(42, 122, 122, 0.08);
|
|
155
174
|
}
|
|
156
175
|
:deep(.ann-target.allusion:hover) {
|
|
157
|
-
background: rgba(181, 101, 29, 0.
|
|
176
|
+
background: rgba(181, 101, 29, 0.1);
|
|
177
|
+
box-shadow: 0 -2px 8px rgba(181, 101, 29, 0.08);
|
|
158
178
|
}
|
|
159
179
|
</style>
|
|
@@ -141,6 +141,23 @@ html[dir="rtl"] ::-webkit-scrollbar-thumb { background: var(--gold); }
|
|
|
141
141
|
a { color: inherit; text-decoration: none; }
|
|
142
142
|
button { font-family: inherit; }
|
|
143
143
|
|
|
144
|
+
/* ===== FOCUS STYLES ===== */
|
|
145
|
+
:focus-visible {
|
|
146
|
+
outline: 2px solid var(--vermillion);
|
|
147
|
+
outline-offset: 2px;
|
|
148
|
+
}
|
|
149
|
+
button:focus-visible {
|
|
150
|
+
outline: 2px solid var(--vermillion);
|
|
151
|
+
outline-offset: 2px;
|
|
152
|
+
border-radius: 4px;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/* ===== ACTIVE ANNOTATION FLASH ===== */
|
|
156
|
+
@keyframes ann-flash-anim {
|
|
157
|
+
0% { background: rgba(194, 58, 43, 0.25); box-shadow: 0 0 12px rgba(194, 58, 43, 0.15); }
|
|
158
|
+
100% { background: transparent; box-shadow: none; }
|
|
159
|
+
}
|
|
160
|
+
|
|
144
161
|
/* ===== LOADING SCREEN ===== */
|
|
145
162
|
#app-loading {
|
|
146
163
|
position: fixed; inset: 0;
|
|
@@ -148,10 +165,11 @@ button { font-family: inherit; }
|
|
|
148
165
|
display: flex; flex-direction: column;
|
|
149
166
|
align-items: center; justify-content: center;
|
|
150
167
|
z-index: 9999;
|
|
151
|
-
transition: opacity 0.
|
|
168
|
+
transition: opacity 0.5s ease, transform 0.5s ease;
|
|
152
169
|
}
|
|
153
170
|
#app-loading.fade-out {
|
|
154
171
|
opacity: 0;
|
|
172
|
+
transform: scale(1.02);
|
|
155
173
|
pointer-events: none;
|
|
156
174
|
}
|
|
157
175
|
#app-loading .seal {
|
|
@@ -354,15 +354,17 @@ function openBook(bookId: string) {
|
|
|
354
354
|
from { opacity: 0; transform: translateY(12px); }
|
|
355
355
|
to { opacity: 1; transform: translateY(0); }
|
|
356
356
|
}
|
|
357
|
-
.lib-card:hover { border-color: var(--gold); box-shadow: 0
|
|
357
|
+
.lib-card:hover { border-color: var(--gold); box-shadow: 0 6px 24px rgba(var(--shadow-rgb), 0.1); transform: translateY(-2px); }
|
|
358
|
+
.lib-card:active { transform: scale(0.98); }
|
|
358
359
|
.lib-card-accent {
|
|
359
360
|
position: absolute;
|
|
360
361
|
top: 0; left: 0;
|
|
361
362
|
width: 3px; height: 0;
|
|
362
|
-
background: var(--vermillion);
|
|
363
|
-
transition: height 0.35s ease;
|
|
363
|
+
background: linear-gradient(180deg, var(--vermillion), var(--gold));
|
|
364
|
+
transition: height 0.35s var(--ease-out-expo, cubic-bezier(0.16, 1, 0.3, 1));
|
|
364
365
|
}
|
|
365
366
|
.lib-card:hover .lib-card-accent { height: 100%; }
|
|
367
|
+
.lib-card:hover .lib-card-title { color: var(--vermillion); }
|
|
366
368
|
.lib-card-top {
|
|
367
369
|
display: flex;
|
|
368
370
|
align-items: baseline;
|
|
@@ -372,6 +374,7 @@ function openBook(bookId: string) {
|
|
|
372
374
|
.lib-card-title {
|
|
373
375
|
font-size: 22px; font-weight: 900;
|
|
374
376
|
letter-spacing: 4px; color: var(--ink);
|
|
377
|
+
transition: color 0.25s ease;
|
|
375
378
|
}
|
|
376
379
|
.lib-card-genre {
|
|
377
380
|
font-size: 11px;
|
|
@@ -846,13 +846,26 @@ function tcy(n: number): string {
|
|
|
846
846
|
border: 1px solid var(--border-light);
|
|
847
847
|
border-radius: 6px;
|
|
848
848
|
cursor: pointer;
|
|
849
|
-
transition: all 0.
|
|
849
|
+
transition: all 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
|
|
850
850
|
line-height: 1.6;
|
|
851
|
+
position: relative;
|
|
852
|
+
overflow: hidden;
|
|
853
|
+
}
|
|
854
|
+
.v-nav-btn::after {
|
|
855
|
+
content: '';
|
|
856
|
+
position: absolute;
|
|
857
|
+
right: 0; top: 0; bottom: 0;
|
|
858
|
+
width: 2px;
|
|
859
|
+
background: linear-gradient(180deg, var(--gold), var(--vermillion));
|
|
860
|
+
transform: scaleY(0);
|
|
861
|
+
transition: transform 0.35s var(--ease-out-expo, cubic-bezier(0.16, 1, 0.3, 1));
|
|
851
862
|
}
|
|
852
863
|
.v-nav-btn:hover {
|
|
853
864
|
border-color: var(--gold);
|
|
854
|
-
box-shadow: 0 4px
|
|
865
|
+
box-shadow: 0 4px 20px rgba(var(--shadow-rgb), 0.1);
|
|
855
866
|
}
|
|
867
|
+
.v-nav-btn:hover::after { transform: scaleY(1); }
|
|
868
|
+
.v-nav-btn:hover .v-nav-title { color: var(--vermillion); }
|
|
856
869
|
.v-nav-dir {
|
|
857
870
|
font-size: 16px; color: var(--vermillion);
|
|
858
871
|
margin-bottom: 0.5em;
|
|
@@ -865,6 +878,7 @@ function tcy(n: number): string {
|
|
|
865
878
|
.v-nav-title {
|
|
866
879
|
font-size: 18px; font-weight: 700;
|
|
867
880
|
letter-spacing: 3px; color: var(--ink);
|
|
881
|
+
transition: color 0.25s ease;
|
|
868
882
|
}
|
|
869
883
|
|
|
870
884
|
/* ═══════ 橫排模式 ═══════ */
|
|
@@ -950,7 +964,7 @@ function tcy(n: number): string {
|
|
|
950
964
|
.h-nav-arrow {
|
|
951
965
|
width: 32px; height: 32px;
|
|
952
966
|
border: 1px solid var(--border);
|
|
953
|
-
border-radius:
|
|
967
|
+
border-radius: 6px;
|
|
954
968
|
background: none;
|
|
955
969
|
font-family: var(--sans);
|
|
956
970
|
font-size: 16px;
|
|
@@ -1026,20 +1040,21 @@ function tcy(n: number): string {
|
|
|
1026
1040
|
position: absolute;
|
|
1027
1041
|
bottom: 0; left: 0; right: 0;
|
|
1028
1042
|
height: 2px;
|
|
1029
|
-
background: var(--vermillion);
|
|
1043
|
+
background: linear-gradient(90deg, var(--vermillion), var(--gold));
|
|
1030
1044
|
transform: scaleX(0);
|
|
1031
|
-
transition: transform 0.
|
|
1045
|
+
transition: transform 0.35s var(--ease-out-expo, cubic-bezier(0.16, 1, 0.3, 1));
|
|
1032
1046
|
}
|
|
1033
1047
|
.h-nav-btn:hover {
|
|
1034
1048
|
border-color: var(--gold);
|
|
1035
1049
|
box-shadow: 0 8px 32px rgba(var(--shadow-rgb), 0.1);
|
|
1036
|
-
transform: translateY(-
|
|
1050
|
+
transform: translateY(-3px);
|
|
1037
1051
|
}
|
|
1038
1052
|
.h-nav-btn:hover::after { transform: scaleX(1); }
|
|
1053
|
+
.h-nav-btn:hover .h-nav-title { color: var(--vermillion); }
|
|
1039
1054
|
.h-nav-btn:active { transform: scale(0.98); }
|
|
1040
1055
|
.h-nav-btn.h-nav-next { text-align: right; }
|
|
1041
1056
|
.h-nav-label { font-size: 11px; color: var(--ink-faint); font-family: var(--sans); letter-spacing: 2px; margin-bottom: 4px; }
|
|
1042
|
-
.h-nav-title { font-size: 16px; font-weight: 600; letter-spacing: 1px; color: var(--ink); }
|
|
1057
|
+
.h-nav-title { font-size: 16px; font-weight: 600; letter-spacing: 1px; color: var(--ink); transition: color 0.25s ease; }
|
|
1043
1058
|
|
|
1044
1059
|
.h-overlay {
|
|
1045
1060
|
position: fixed; inset: 0;
|
|
@@ -1335,11 +1350,11 @@ function tcy(n: number): string {
|
|
|
1335
1350
|
|
|
1336
1351
|
/* ─── 注釋閃爍 ─── */
|
|
1337
1352
|
:deep(.ann-flash) {
|
|
1338
|
-
animation: ann-flash-anim 1.
|
|
1353
|
+
animation: ann-flash-anim 1.5s ease-out;
|
|
1339
1354
|
}
|
|
1340
1355
|
@keyframes ann-flash-anim {
|
|
1341
|
-
0% { background: rgba(194, 58, 43, 0.
|
|
1342
|
-
100% { background: transparent; }
|
|
1356
|
+
0% { background: rgba(194, 58, 43, 0.25); box-shadow: 0 0 12px rgba(194, 58, 43, 0.15); }
|
|
1357
|
+
100% { background: transparent; box-shadow: none; }
|
|
1343
1358
|
}
|
|
1344
1359
|
|
|
1345
1360
|
/* ═══════ 行動裝置適配 ═══════ */
|