diff --git a/src/pages/saju/_shell/OrnamentBloom.jsx b/src/pages/saju/_shell/OrnamentBloom.jsx
new file mode 100644
index 0000000..11fbc75
--- /dev/null
+++ b/src/pages/saju/_shell/OrnamentBloom.jsx
@@ -0,0 +1,13 @@
+import React from 'react';
+
+export default function OrnamentBloom({ size = 18, color = '#D4AF37' }) {
+ return (
+
+ );
+}
diff --git a/src/pages/saju/_shell/OrnateFrame.jsx b/src/pages/saju/_shell/OrnateFrame.jsx
new file mode 100644
index 0000000..e5f3ae7
--- /dev/null
+++ b/src/pages/saju/_shell/OrnateFrame.jsx
@@ -0,0 +1,36 @@
+import React from 'react';
+import hexA from './helpers/hexA';
+
+export default function OrnateFrame({
+ children, color = '#D4AF37', bg = 'transparent', radius = 14, padding = '20px',
+ style = {}, double = false,
+}) {
+ return (
+
+ {double && (
+
+ )}
+ {[[0,0,0],[0,1,90],[1,1,180],[1,0,270]].map(([x,y,r], i) => (
+
+ ))}
+
{children}
+
+ );
+}
diff --git a/src/pages/saju/_shell/TitleBlock.jsx b/src/pages/saju/_shell/TitleBlock.jsx
new file mode 100644
index 0000000..026c719
--- /dev/null
+++ b/src/pages/saju/_shell/TitleBlock.jsx
@@ -0,0 +1,37 @@
+import React from 'react';
+import OrnamentBloom from './OrnamentBloom';
+
+export default function TitleBlock({
+ title, subtitle, color = '#1F2A44', subColor = '#6B6B6B',
+ center = true, withBloom = true, gold = '#D4AF37',
+}) {
+ return (
+
+ {withBloom && center && (
+
+ )}
+
{title}
+ {subtitle && (
+
{subtitle}
+ )}
+
+ );
+}
diff --git a/src/pages/saju/_shell/TopRibbon.jsx b/src/pages/saju/_shell/TopRibbon.jsx
new file mode 100644
index 0000000..c6fe98a
--- /dev/null
+++ b/src/pages/saju/_shell/TopRibbon.jsx
@@ -0,0 +1,21 @@
+import React from 'react';
+
+function CloudOrnament({ width = 90, color = '#D4AF37', opacity = 0.85 }) {
+ return (
+
+ );
+}
+
+export default function TopRibbon({ color = '#D4AF37', opacity = 0.5 }) {
+ return (
+
+
+
+ );
+}