@morphika/andami 0.2.1 → 0.2.3
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/app/admin/pages/[slug]/page.tsx +9 -3
- package/components/blocks/ProjectGridBlockRenderer.tsx +12 -2
- package/components/blocks/TextBlockRenderer.tsx +1 -1
- package/components/builder/ReadOnlyFrame.tsx +2 -2
- package/components/builder/SectionV2Column.tsx +41 -7
- package/components/builder/SettingsPanel.tsx +0 -3
- package/components/builder/SortableBlock.tsx +13 -9
- package/components/builder/SortableRow.tsx +16 -10
- package/components/builder/live-preview/LiveTextEditor.tsx +1 -1
- package/package.json +1 -1
- package/styles/base.css +2 -9
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
verticalListSortingStrategy,
|
|
20
20
|
} from "@dnd-kit/sortable";
|
|
21
21
|
import type { Page, PageSectionV2, ParallaxGroup, SectionColumn, CustomSectionInstance, CustomSectionListItem } from "../../../../lib/sanity/types";
|
|
22
|
-
import { isPageSectionV2, isCustomSectionInstance,
|
|
22
|
+
import { isPageSectionV2, isCustomSectionInstance, isParallaxGroup } from "../../../../lib/sanity/types";
|
|
23
23
|
import SectionEditorBar from "../../../../components/builder/SectionEditorBar";
|
|
24
24
|
import CustomSectionInstanceCard from "../../../../components/builder/CustomSectionInstanceCard";
|
|
25
25
|
import { ColumnDragProvider } from "../../../../components/builder/ColumnDragContext";
|
|
@@ -666,7 +666,7 @@ export default function PageEditorPage() {
|
|
|
666
666
|
{store.rows.map((item, rowIndex) => {
|
|
667
667
|
const isV2Section = isPageSectionV2(item);
|
|
668
668
|
const isInstance = isCustomSectionInstance(item);
|
|
669
|
-
const isParallax =
|
|
669
|
+
const isParallax = isParallaxGroup(item);
|
|
670
670
|
const v2Section = isV2Section ? (item as PageSectionV2) : null;
|
|
671
671
|
|
|
672
672
|
// Custom Section Instance — rendered directly without SortableRow chrome
|
|
@@ -783,7 +783,13 @@ export default function PageEditorPage() {
|
|
|
783
783
|
e.stopPropagation();
|
|
784
784
|
setShowSectionPicker(true);
|
|
785
785
|
}}
|
|
786
|
-
className="w-full rounded-xl py-3 text-xs font-medium
|
|
786
|
+
className="w-full rounded-xl py-3 text-xs font-medium transition-colors"
|
|
787
|
+
style={{
|
|
788
|
+
background: "linear-gradient(170deg, rgba(38,38,48,0.95) 0%, rgba(28,28,36,0.97) 100%)",
|
|
789
|
+
color: "rgba(200,160,220,0.8)",
|
|
790
|
+
boxShadow: "0 2px 8px rgba(0,0,0,0.2), inset 0 1px 0 rgba(255,255,255,0.04)",
|
|
791
|
+
border: "1px solid rgba(255,255,255,0.06)",
|
|
792
|
+
}}
|
|
787
793
|
>
|
|
788
794
|
+ Add Section
|
|
789
795
|
</button>
|
|
@@ -226,8 +226,14 @@ export default function ProjectGridBlockRenderer({
|
|
|
226
226
|
// animations at once (with stagger). No per-card observer needed.
|
|
227
227
|
const [gridVisible, setGridVisible] = useState(false);
|
|
228
228
|
|
|
229
|
+
// Track whether we have projects loaded — needed as a dep so the
|
|
230
|
+
// IntersectionObserver effect re-runs after the async fetch populates
|
|
231
|
+
// resolvedProjects (on the first render the grid div isn't mounted yet
|
|
232
|
+
// because the component returns null when resolvedProjects is empty).
|
|
233
|
+
const hasProjects = resolvedProjects.length > 0;
|
|
234
|
+
|
|
229
235
|
useEffect(() => {
|
|
230
|
-
if (!entranceEnabled || gridVisible) return;
|
|
236
|
+
if (!entranceEnabled || gridVisible || !hasProjects) return;
|
|
231
237
|
const el = containerRef.current;
|
|
232
238
|
if (!el) return;
|
|
233
239
|
|
|
@@ -249,7 +255,7 @@ export default function ProjectGridBlockRenderer({
|
|
|
249
255
|
|
|
250
256
|
observer.observe(el);
|
|
251
257
|
return () => observer.disconnect();
|
|
252
|
-
}, [entranceEnabled, gridVisible]);
|
|
258
|
+
}, [entranceEnabled, gridVisible, hasProjects]);
|
|
253
259
|
|
|
254
260
|
// ─── Compute stagger indices sorted by vertical position ───
|
|
255
261
|
// Cards at similar y positions (within half of gapV) share the same rank.
|
|
@@ -330,6 +336,10 @@ export default function ProjectGridBlockRenderer({
|
|
|
330
336
|
top: item.y,
|
|
331
337
|
width: item.width,
|
|
332
338
|
height: item.height,
|
|
339
|
+
// Clip the card when hover scale-up overflows the cell bounds
|
|
340
|
+
// so border-radius is preserved visually.
|
|
341
|
+
overflow: "hidden",
|
|
342
|
+
borderRadius: borderRadius > 0 ? borderRadius : undefined,
|
|
333
343
|
}}
|
|
334
344
|
>
|
|
335
345
|
{entranceEnabled && entranceAnimConfig ? (
|
|
@@ -87,7 +87,7 @@ export default function TextBlockRenderer({ block }: { block: TextBlock }) {
|
|
|
87
87
|
return (
|
|
88
88
|
<div
|
|
89
89
|
className={`${className} space-y-[0.75em]`}
|
|
90
|
-
style={
|
|
90
|
+
style={style}
|
|
91
91
|
>
|
|
92
92
|
<PortableText value={block.text} />
|
|
93
93
|
</div>
|
|
@@ -20,11 +20,11 @@ import { memo, useMemo, useState, useEffect } from "react";
|
|
|
20
20
|
import { useBuilderStore } from "../../lib/builder/store";
|
|
21
21
|
import type { DeviceViewport } from "../../lib/builder/types";
|
|
22
22
|
import type { ContentItem, PageSectionV2, CustomSectionInstance, ParallaxGroup, ParallaxSlideV2 } from "../../lib/sanity/types";
|
|
23
|
-
import { isPageSectionV2, isCustomSectionInstance,
|
|
23
|
+
import { isPageSectionV2, isCustomSectionInstance, isParallaxGroup } from "../../lib/sanity/types";
|
|
24
24
|
import { DEVICE_HEIGHTS } from "../../lib/builder/types";
|
|
25
25
|
import { getEffectiveColumnsV2, getSectionV2SettingValue } from "./settings-panel/responsive-helpers";
|
|
26
26
|
import BlockLivePreview from "./BlockLivePreview";
|
|
27
|
-
import { getColumnVerticalAlign } from "../../lib/builder/layout-styles";
|
|
27
|
+
import { getColumnVerticalAlign, getRowLayoutStyles } from "../../lib/builder/layout-styles";
|
|
28
28
|
|
|
29
29
|
// Layout keys that support responsive overrides for V2 sections
|
|
30
30
|
const OVERRIDABLE_KEYS = [
|
|
@@ -10,6 +10,7 @@ import { useBuilderStore } from "../../lib/builder/store";
|
|
|
10
10
|
import { makeBlockId, makeColumnDroppableId } from "./DndWrapper";
|
|
11
11
|
import type { SectionColumn, ContentBlock, PageSectionV2 } from "../../lib/sanity/types";
|
|
12
12
|
import { getColumnVerticalAlign } from "../../lib/builder/layout-styles";
|
|
13
|
+
import { isSectionBlockType } from "../../lib/builder/types";
|
|
13
14
|
import { BUILDER_BLUE } from "../../lib/builder/constants";
|
|
14
15
|
|
|
15
16
|
// ============================================
|
|
@@ -174,10 +175,26 @@ export default function SectionV2Column({
|
|
|
174
175
|
);
|
|
175
176
|
|
|
176
177
|
// ---- Stable callbacks ----
|
|
178
|
+
|
|
179
|
+
// When the column contains a single section-level block (e.g. projectGridBlock),
|
|
180
|
+
// that block fills the entire column visually. Clicking anywhere in the column
|
|
181
|
+
// should select the block — not the column — because users expect to reach the
|
|
182
|
+
// block's settings panel (Settings / Layout / Animation tabs).
|
|
183
|
+
const selectBlock = useBuilderStore((s) => s.selectBlock);
|
|
184
|
+
const singleSectionBlock = (() => {
|
|
185
|
+
const blocks = column.blocks || [];
|
|
186
|
+
if (blocks.length === 1 && isSectionBlockType(blocks[0]._type)) return blocks[0];
|
|
187
|
+
return null;
|
|
188
|
+
})();
|
|
189
|
+
|
|
177
190
|
const handleClick = useCallback((e: React.MouseEvent) => {
|
|
178
191
|
e.stopPropagation();
|
|
179
|
-
|
|
180
|
-
|
|
192
|
+
if (singleSectionBlock) {
|
|
193
|
+
selectBlock(singleSectionBlock._key);
|
|
194
|
+
} else {
|
|
195
|
+
onSelect();
|
|
196
|
+
}
|
|
197
|
+
}, [onSelect, singleSectionBlock, selectBlock]);
|
|
181
198
|
|
|
182
199
|
const handleMouseEnter = useCallback(() => setIsHovered(true), []);
|
|
183
200
|
const handleMouseLeave = useCallback(() => setIsHovered(false), []);
|
|
@@ -450,12 +467,23 @@ export default function SectionV2Column({
|
|
|
450
467
|
aria-label="Add block to empty column"
|
|
451
468
|
className={`w-full py-2 rounded-lg text-xs font-medium transition-all flex items-center justify-center ${
|
|
452
469
|
showChrome
|
|
453
|
-
? "
|
|
470
|
+
? "opacity-100"
|
|
454
471
|
: showFaintOutline
|
|
455
|
-
? "
|
|
472
|
+
? "opacity-40"
|
|
456
473
|
: "bg-transparent text-transparent opacity-0 pointer-events-none"
|
|
457
474
|
}`}
|
|
458
|
-
style={{
|
|
475
|
+
style={{
|
|
476
|
+
pointerEvents: showChrome || showFaintOutline ? "auto" : "none",
|
|
477
|
+
...(showChrome ? {
|
|
478
|
+
background: "linear-gradient(170deg, rgba(38,38,48,0.95) 0%, rgba(28,28,36,0.97) 100%)",
|
|
479
|
+
color: "rgba(100,220,170,0.8)",
|
|
480
|
+
boxShadow: "0 2px 8px rgba(0,0,0,0.2), inset 0 1px 0 rgba(255,255,255,0.04)",
|
|
481
|
+
border: "1px solid rgba(255,255,255,0.06)",
|
|
482
|
+
} : showFaintOutline ? {
|
|
483
|
+
background: "rgba(38,38,48,0.3)",
|
|
484
|
+
color: "rgba(100,220,170,0.4)",
|
|
485
|
+
} : {}),
|
|
486
|
+
}}
|
|
459
487
|
>
|
|
460
488
|
+ Add Block
|
|
461
489
|
</button>
|
|
@@ -476,8 +504,14 @@ export default function SectionV2Column({
|
|
|
476
504
|
<button
|
|
477
505
|
onClick={handleAddBlockBelow}
|
|
478
506
|
aria-label="Add block below existing blocks"
|
|
479
|
-
className="w-full py-1.5 text-[11px] font-medium rounded
|
|
480
|
-
style={{
|
|
507
|
+
className="w-full py-1.5 text-[11px] font-medium rounded transition-all"
|
|
508
|
+
style={{
|
|
509
|
+
pointerEvents: showChrome ? "auto" : "none",
|
|
510
|
+
background: "linear-gradient(170deg, rgba(38,38,48,0.95) 0%, rgba(28,28,36,0.97) 100%)",
|
|
511
|
+
color: "rgba(100,220,170,0.8)",
|
|
512
|
+
boxShadow: "0 2px 8px rgba(0,0,0,0.2), inset 0 1px 0 rgba(255,255,255,0.04)",
|
|
513
|
+
border: "1px solid rgba(255,255,255,0.06)",
|
|
514
|
+
}}
|
|
481
515
|
>
|
|
482
516
|
+ Add Block
|
|
483
517
|
</button>
|
|
@@ -144,9 +144,6 @@ export default function SettingsPanel() {
|
|
|
144
144
|
} else if (selectedSectionV2) {
|
|
145
145
|
onDelete = () => store.deleteSection(selectedSectionV2._key);
|
|
146
146
|
deleteTitle = "Delete Section";
|
|
147
|
-
} else if (selectedSection) {
|
|
148
|
-
onDelete = () => store.deleteSection(selectedSection._key);
|
|
149
|
-
deleteTitle = "Delete Section";
|
|
150
147
|
}
|
|
151
148
|
|
|
152
149
|
if (!onDelete) return null;
|
|
@@ -149,14 +149,18 @@ export default function SortableBlock({
|
|
|
149
149
|
className="flex items-center gap-1.5"
|
|
150
150
|
style={{ transform: `scale(${Math.min(2, 1 / canvasZoom)})`, transformOrigin: "top center" }}
|
|
151
151
|
>
|
|
152
|
-
<div className="flex items-center
|
|
152
|
+
<div className="flex items-center rounded-[5px] overflow-hidden" style={{
|
|
153
|
+
background: "linear-gradient(170deg, rgba(38,38,48,0.97) 0%, rgba(28,28,36,0.98) 100%)",
|
|
154
|
+
boxShadow: "0 4px 12px rgba(0,0,0,0.3), inset 0 1px 0 rgba(255,255,255,0.06)",
|
|
155
|
+
border: "1px solid rgba(255,255,255,0.06)",
|
|
156
|
+
}}>
|
|
153
157
|
{/* Move up arrow */}
|
|
154
158
|
<button
|
|
155
159
|
onClick={() => canMoveUp && reorderBlocks(rowKey, colKey, blockIndex, blockIndex - 1)}
|
|
156
160
|
className={`transition-colors px-1 py-0.5 text-[11px] ${
|
|
157
161
|
canMoveUp
|
|
158
|
-
? "text-white/
|
|
159
|
-
: "text-white/
|
|
162
|
+
? "text-white/45 hover:text-white/80 hover:bg-white/10 cursor-pointer"
|
|
163
|
+
: "text-white/20 cursor-default"
|
|
160
164
|
}`}
|
|
161
165
|
title="Move block up"
|
|
162
166
|
aria-label="Move block up"
|
|
@@ -169,10 +173,10 @@ export default function SortableBlock({
|
|
|
169
173
|
{/* Move down arrow */}
|
|
170
174
|
<button
|
|
171
175
|
onClick={() => canMoveDown && reorderBlocks(rowKey, colKey, blockIndex, blockIndex + 1)}
|
|
172
|
-
className={`transition-colors px-1 py-0.5 text-[11px] border-l border-white/
|
|
176
|
+
className={`transition-colors px-1 py-0.5 text-[11px] border-l border-white/10 ${
|
|
173
177
|
canMoveDown
|
|
174
|
-
? "text-white/
|
|
175
|
-
: "text-white/
|
|
178
|
+
? "text-white/45 hover:text-white/80 hover:bg-white/10 cursor-pointer"
|
|
179
|
+
: "text-white/20 cursor-default"
|
|
176
180
|
}`}
|
|
177
181
|
title="Move block down"
|
|
178
182
|
aria-label="Move block down"
|
|
@@ -183,12 +187,12 @@ export default function SortableBlock({
|
|
|
183
187
|
</svg>
|
|
184
188
|
</button>
|
|
185
189
|
{/* Block type label */}
|
|
186
|
-
<span className="text-[11px]
|
|
190
|
+
<span className="text-[11px] px-1.5 py-0.5 border-l border-white/10 font-medium" style={{ color: "rgba(100,220,170,0.9)" }}>
|
|
187
191
|
{info?.icon || "▪"} {info?.label || block._type}
|
|
188
192
|
</span>
|
|
189
193
|
{/* Enter animation badge */}
|
|
190
194
|
{block.enter_animation?.preset && block.enter_animation.preset !== "none" && (
|
|
191
|
-
<span className="text-[10px] text-white/
|
|
195
|
+
<span className="text-[10px] text-white/35 px-1 py-0.5 border-l border-white/10" title={`Animation: ${block.enter_animation.preset}`}>
|
|
192
196
|
✦
|
|
193
197
|
</span>
|
|
194
198
|
)}
|
|
@@ -196,7 +200,7 @@ export default function SortableBlock({
|
|
|
196
200
|
{onDuplicate && (
|
|
197
201
|
<button
|
|
198
202
|
onClick={onDuplicate}
|
|
199
|
-
className="text-white/
|
|
203
|
+
className="text-white/45 hover:text-white/80 transition-colors px-1.5 py-0.5 text-[11px] border-l border-white/10 hover:bg-white/10"
|
|
200
204
|
title="Duplicate block (Ctrl+D)"
|
|
201
205
|
aria-label="Duplicate block"
|
|
202
206
|
>
|
|
@@ -253,12 +253,18 @@ export default function SortableRow({
|
|
|
253
253
|
>
|
|
254
254
|
{/* Main toolbar — drag + actions */}
|
|
255
255
|
<div
|
|
256
|
-
className="flex flex-col items-stretch
|
|
256
|
+
className="flex flex-col items-stretch rounded-l-lg py-2 px-2.5 gap-1 cursor-grab active:cursor-grabbing"
|
|
257
|
+
style={{
|
|
258
|
+
background: "linear-gradient(170deg, rgba(38,38,48,0.97) 0%, rgba(28,28,36,0.98) 100%)",
|
|
259
|
+
boxShadow: "0 4px 16px rgba(0,0,0,0.3), inset 0 1px 0 rgba(255,255,255,0.06)",
|
|
260
|
+
border: "1px solid rgba(255,255,255,0.06)",
|
|
261
|
+
borderRight: "none",
|
|
262
|
+
}}
|
|
257
263
|
{...attributes}
|
|
258
264
|
{...listeners}
|
|
259
265
|
>
|
|
260
266
|
{/* Section label — shows specific type for page sections */}
|
|
261
|
-
<span className="text-[11px]
|
|
267
|
+
<span className="text-[11px] select-none leading-tight pointer-events-none font-medium tracking-wide" style={{ color: "rgba(200,160,220,0.9)" }}>
|
|
262
268
|
{sectionLabel || "Section"}
|
|
263
269
|
</span>
|
|
264
270
|
|
|
@@ -267,7 +273,7 @@ export default function SortableRow({
|
|
|
267
273
|
<button
|
|
268
274
|
onClick={(e) => { e.stopPropagation(); onDuplicate(); }}
|
|
269
275
|
onPointerDown={(e) => e.stopPropagation()}
|
|
270
|
-
className="flex items-center justify-center text-[12px] text-white/
|
|
276
|
+
className="flex items-center justify-center text-[12px] text-white/50 hover:text-white/85 transition-colors"
|
|
271
277
|
title="Duplicate section"
|
|
272
278
|
aria-label="Duplicate section"
|
|
273
279
|
>
|
|
@@ -277,7 +283,7 @@ export default function SortableRow({
|
|
|
277
283
|
onClick={(e) => { e.stopPropagation(); onMoveUp(); }}
|
|
278
284
|
onPointerDown={(e) => e.stopPropagation()}
|
|
279
285
|
disabled={isFirst}
|
|
280
|
-
className="flex items-center justify-center text-[12px] text-white/
|
|
286
|
+
className="flex items-center justify-center text-[12px] text-white/50 hover:text-white/85 transition-colors disabled:opacity-30 disabled:cursor-not-allowed"
|
|
281
287
|
title="Move up"
|
|
282
288
|
aria-label="Move section up"
|
|
283
289
|
>
|
|
@@ -287,7 +293,7 @@ export default function SortableRow({
|
|
|
287
293
|
onClick={(e) => { e.stopPropagation(); onMoveDown(); }}
|
|
288
294
|
onPointerDown={(e) => e.stopPropagation()}
|
|
289
295
|
disabled={isLast}
|
|
290
|
-
className="flex items-center justify-center text-[12px] text-white/
|
|
296
|
+
className="flex items-center justify-center text-[12px] text-white/50 hover:text-white/85 transition-colors disabled:opacity-30 disabled:cursor-not-allowed"
|
|
291
297
|
title="Move down"
|
|
292
298
|
aria-label="Move section down"
|
|
293
299
|
>
|
|
@@ -300,11 +306,11 @@ export default function SortableRow({
|
|
|
300
306
|
<button
|
|
301
307
|
onClick={(e) => { e.stopPropagation(); onAddColumn(); }}
|
|
302
308
|
onPointerDown={(e) => e.stopPropagation()}
|
|
303
|
-
className="flex items-center gap-1 text-[11px] text-white/
|
|
309
|
+
className="flex items-center gap-1 text-[11px] text-white/50 hover:text-white/85 transition-colors py-0.5"
|
|
304
310
|
title="Add column"
|
|
305
311
|
aria-label="Add column"
|
|
306
312
|
>
|
|
307
|
-
<span className="text-white/
|
|
313
|
+
<span className="text-white/30">+</span> Col
|
|
308
314
|
</button>
|
|
309
315
|
)}
|
|
310
316
|
|
|
@@ -312,11 +318,11 @@ export default function SortableRow({
|
|
|
312
318
|
<button
|
|
313
319
|
onClick={(e) => { e.stopPropagation(); onDelete(); }}
|
|
314
320
|
onPointerDown={(e) => e.stopPropagation()}
|
|
315
|
-
className="flex items-center gap-1 text-[11px] text-white/
|
|
321
|
+
className="flex items-center gap-1 text-[11px] text-white/50 hover:text-red-300 transition-colors py-0.5"
|
|
316
322
|
title="Delete section"
|
|
317
323
|
aria-label="Delete section"
|
|
318
324
|
>
|
|
319
|
-
<span className="text-white/
|
|
325
|
+
<span className="text-white/30">-</span> Delete
|
|
320
326
|
</button>
|
|
321
327
|
</div>
|
|
322
328
|
</div>
|
|
@@ -333,7 +339,7 @@ export default function SortableRow({
|
|
|
333
339
|
)}
|
|
334
340
|
|
|
335
341
|
{/* Content — same layout as Preview */}
|
|
336
|
-
<div style={coverRow ? undefined : { maxWidth, margin: "0 auto", paddingLeft: maxWidth !== "100%" ? gridPadding : undefined, paddingRight: maxWidth !== "100%" ? gridPadding : undefined }} className="relative
|
|
342
|
+
<div style={coverRow ? undefined : { maxWidth, margin: "0 auto", paddingLeft: maxWidth !== "100%" ? gridPadding : undefined, paddingRight: maxWidth !== "100%" ? gridPadding : undefined }} className="relative">
|
|
337
343
|
{children}
|
|
338
344
|
</div>
|
|
339
345
|
</div>
|
|
@@ -149,7 +149,7 @@ export default function LiveTextEditor({ block, editable = false }: { block: Tex
|
|
|
149
149
|
fontFamily: "inherit",
|
|
150
150
|
outline: "none",
|
|
151
151
|
whiteSpace: "pre-wrap",
|
|
152
|
-
wordBreak: "
|
|
152
|
+
wordBreak: "break-word",
|
|
153
153
|
minHeight: "1em",
|
|
154
154
|
// Multi-column layout: gap inherits global grid gutter
|
|
155
155
|
...(cols ? {
|
package/package.json
CHANGED
package/styles/base.css
CHANGED
|
@@ -57,21 +57,14 @@ body {
|
|
|
57
57
|
overflow-x: clip;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
/* Prevent text overflow in grid columns on narrow viewports
|
|
61
|
-
* overflow-wrap: break-word — breaks mid-word ONLY when the entire word
|
|
62
|
-
* cannot fit on a fresh line. Does NOT affect min-content intrinsic sizing,
|
|
63
|
-
* so CSS Grid columns keep their proper width (unlike 'anywhere' which
|
|
64
|
-
* collapses min-content to a single character width).
|
|
65
|
-
* word-break: normal — wraps at natural word boundaries first, preventing
|
|
66
|
-
* ugly mid-word splits like "Collecti" + "on". */
|
|
60
|
+
/* Prevent text overflow in grid columns on narrow viewports */
|
|
67
61
|
[data-site] p,
|
|
68
62
|
[data-site] h1,
|
|
69
63
|
[data-site] h2,
|
|
70
64
|
[data-site] h3,
|
|
71
65
|
[data-site] h4,
|
|
72
66
|
[data-site] span {
|
|
73
|
-
|
|
74
|
-
word-break: normal;
|
|
67
|
+
word-break: break-word;
|
|
75
68
|
}
|
|
76
69
|
|
|
77
70
|
[data-custom-cursor] {
|