/* ============================================================
相册边框样式(全局)
- 前台 PhotoGallery 按 page.borderStyle 套用
- 后台 AdminEditor 预览复用同一套类
结构约定:
gf-frame 只负责裁切,gf-xxx 负责边框/卡纸/投影
注意:绝不能在此设置 position/width/height —— 本文件在
Tailwind 工具类之后加载,会覆盖元素上的 absolute/尺寸工具类
(position:relative 曾把 overlap 版的 absolute 静默冲掉)
============================================================ */
.gf-frame {
background: #fff;
overflow: hidden;
}
.gf-frame > img {
display: block;
width: 100%;
height: 100%;
object-fit: cover;
}
/* 无边框 */
.gf-none {
padding: 0;
border: 0;
box-shadow: none;
border-radius: 0;
background: transparent;
}
/* 细金线 */
.gf-thin {
padding: 0;
border: 1px solid #cdb89c;
border-radius: 4px;
box-shadow: 0 2px 10px rgba(120, 90, 60, 0.08);
background: #fff;
}
/* 白卡纸(经典裱框) */
.gf-mat {
padding: 8px;
border-radius: 2px;
box-shadow: 0 6px 20px rgba(120, 90, 60, 0.12);
background: #fff;
}
/* 柔圆角 */
.gf-rounded {
padding: 0;
border: 1px solid rgba(168, 140, 107, 0.4);
border-radius: 20px;
box-shadow: 0 8px 24px rgba(120, 90, 60, 0.1);
background: #fff;
}
/* 双线框 */
.gf-double {
padding: 6px;
border: 3px double #b89a78;
border-radius: 3px;
box-shadow: 0 4px 16px rgba(120, 90, 60, 0.1);
background: #fff;
}
/* 古典金框(外白 + 金线双层) */
.gf-gold {
padding: 7px;
border: 2px solid #c9a978;
border-radius: 3px;
box-shadow: 0 0 0 4px #fff, 0 0 0 5px #e7d6bb, 0 8px 22px rgba(120, 90, 60, 0.12);
background: #fff;
}
/* 阴影浮起(无边框,大柔影悬浮感) */
.gf-shadow {
padding: 0;
border: 0;
border-radius: 10px;
box-shadow: 0 18px 44px rgba(96, 72, 50, 0.2), 0 4px 12px rgba(96, 72, 50, 0.1);
background: #fff;
}
/* 墨黑描边(简约深色细框) */
.gf-ink {
padding: 6px;
border: 1.5px solid #3a3733;
border-radius: 2px;
box-shadow: 0 4px 14px rgba(0, 0, 0, 0.1);
background: #fff;
}
/* 悬浮卡片(厚白边 + 大圆角 + 层叠影) */
.gf-card {
padding: 12px;
border: 1px solid rgba(168, 140, 107, 0.18);
border-radius: 16px;
box-shadow: 0 2px 6px rgba(120, 90, 60, 0.08), 0 16px 36px rgba(120, 90, 60, 0.16);
background: #fff;
}
/* 虚线文艺(dashed 描边 + 内白边) */
.gf-lace {
padding: 7px;
border: 1.5px dashed #b89a78;
border-radius: 8px;
box-shadow: 0 3px 12px rgba(120, 90, 60, 0.08);
background: #fff;
}
/* 柔光金晕(浅金边 + 外发光) */
.gf-glow {
padding: 5px;
border: 1px solid #e7d3ae;
border-radius: 6px;
box-shadow: 0 0 0 3px rgba(231, 211, 174, 0.35), 0 0 26px rgba(201, 169, 120, 0.45), 0 6px 16px rgba(120, 90, 60, 0.1);
background: #fff;
}
/* ============================================================
明信片 · 异形边框(group: postcard)
- mask/clip 裁切类(stamp/scallop/torn/ticket/heart)box-shadow 会被
mask 一并裁掉,投影统一由父级 .gf-shape-shadow 的 drop-shadow 提供
- 装饰伪元素需要定位上下文:用零优先级 :where() 设 relative,
模板里 Tailwind 的 .absolute(0,1,0)永远能赢,不违背头部约定
============================================================ */
:where(.gf-postcard, .gf-film, .gf-stamp, .gf-arch, .gf-oval, .gf-circle, .gf-leaf,
.gf-heart, .gf-flower, .gf-hexagon, .gf-scallop, .gf-wave, .gf-zigzag,
.gf-torn, .gf-ticket, .gf-bevel,
.gf-cloud, .gf-mist, .gf-bloom, .gf-panorama, .gf-ovalwide) {
position: relative;
}
/* 边缘渐隐内晕:照片边缘向纸色柔和过渡,与边框/裁切形状融为一体
(mask/clip 类的伪元素会随形状一并裁切,晕自动贴合轮廓) */
.gf-heart::after, .gf-flower::after, .gf-scallop::after, .gf-wave::after,
.gf-zigzag::after, .gf-torn::after, .gf-stamp::after, .gf-ticket::after,
.gf-hexagon::after, .gf-bevel::after, .gf-arch::after, .gf-oval::after,
.gf-circle::after, .gf-leaf::after, .gf-cloud::after, .gf-ovalwide::after {
content: '';
position: absolute;
inset: 0;
background: radial-gradient(ellipse 62% 62% at 50% 50%, rgba(255, 252, 246, 0) 55%, rgba(255, 252, 246, 0.48) 100%);
pointer-events: none;
}
/* 邮票齿孔(四边半圆打孔,经典邮票纸边) */
.gf-stamp {
--gf-r: 5px;
padding: 12px;
border: 0;
border-radius: 0;
box-shadow: none;
background: #fff;
-webkit-mask:
radial-gradient(var(--gf-r), #0000 98%, #000) calc(-1.5 * var(--gf-r)) calc(-1.5 * var(--gf-r)) / calc(3 * var(--gf-r)) calc(3 * var(--gf-r)) round,
linear-gradient(#000 0 0) 50% / calc(100% - 3 * var(--gf-r)) calc(100% - 3 * var(--gf-r)) no-repeat;
mask:
radial-gradient(var(--gf-r), #0000 98%, #000) calc(-1.5 * var(--gf-r)) calc(-1.5 * var(--gf-r)) / calc(3 * var(--gf-r)) calc(3 * var(--gf-r)) round,
linear-gradient(#000 0 0) 50% / calc(100% - 3 * var(--gf-r)) calc(100% - 3 * var(--gf-r)) no-repeat;
}
/* 邮票内框线(贴照片边缘内侧,经典邮票图框) */
.gf-stamp::before {
content: '';
position: absolute;
inset: 15px;
border: 1px solid rgba(255, 255, 255, 0.65);
pointer-events: none;
z-index: 1;
}
/* 复古明信片(暖白卡 + POST CARD 字样 + 邮戳/邮票装饰) */
.gf-postcard {
padding: 10px 10px 40px;
border: 1px solid rgba(184, 154, 120, 0.28);
border-radius: 4px;
box-shadow: 0 10px 26px rgba(120, 90, 60, 0.16);
background: #fffdf6;
}
.gf-postcard::before {
content: 'POST CARD';
position: absolute;
left: 14px;
bottom: 14px;
/* 窄格(九宫格/爱心拼贴)里给右侧邮戳让位,calc 为负时按 0 处理自动隐藏 */
max-width: calc(100% - 118px);
overflow: hidden;
white-space: nowrap;
font-family: Georgia, 'Times New Roman', serif;
font-size: 9px;
line-height: 1;
letter-spacing: 0.35em;
color: #b89a78;
pointer-events: none;
}
.gf-postcard::after {
content: '';
position: absolute;
right: 8px;
bottom: 3px;
width: 96px;
height: 36px;
background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 120 48'%3E%3Cg fill='none' stroke='%23b89a78' stroke-width='1.5'%3E%3Ccircle cx='24' cy='24' r='15'/%3E%3Ccircle cx='24' cy='24' r='10.5'/%3E%3Cpath d='M48 14c5-3 9 3 14 0M48 22c5-3 9 3 14 0M48 30c5-3 9 3 14 0' stroke-width='1.2'/%3E%3C/g%3E%3Cg transform='translate(76,6)'%3E%3Crect width='30' height='36' fill='none' stroke='%23c9a978' stroke-width='1.5' stroke-dasharray='3 2.4'/%3E%3Cpath d='M15 26c-5-3.6-9-7-9-11a5 5 0 0 1 9-2.6a5 5 0 0 1 9 2.6c0 4-4 7.4-9 11z' fill='%23d9a0a5'/%3E%3C/g%3E%3C/svg%3E") no-repeat right center / contain;
opacity: 0.9;
pointer-events: none;
}
/* 拱门(顶部全圆,婚礼穹顶造型) */
.gf-arch {
padding: 8px;
border: 1px solid rgba(201, 169, 120, 0.5);
border-radius: 999px 999px 14px 14px;
box-shadow: 0 0 0 4px rgba(255, 255, 255, 0.65), 0 14px 32px rgba(120, 90, 60, 0.16);
background: #fff;
}
.gf-arch > img {
border-radius: 992px 992px 8px 8px;
}
/* 拱顶花饰圆章(呼应尾页门框 keystone) */
.gf-arch::before {
content: '❀';
position: absolute;
top: 12px;
left: 50%;
transform: translateX(-50%);
width: 26px;
height: 26px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 12px;
line-height: 1;
color: #b08e63;
background: rgba(253, 251, 247, 0.92);
box-shadow: 0 0 0 1px rgba(201, 169, 120, 0.45), 0 2px 6px rgba(120, 90, 60, 0.18);
pointer-events: none;
z-index: 1;
}
/* 椭圆相框 */
.gf-oval {
padding: 7px;
border: 1px solid rgba(201, 169, 120, 0.55);
border-radius: 50%;
box-shadow: 0 0 0 4px rgba(255, 255, 255, 0.7), 0 12px 30px rgba(120, 90, 60, 0.16);
background: #fff;
}
.gf-oval > img {
border-radius: 50%;
}
/* 正圆相框(推荐 1:1) */
.gf-circle {
padding: 8px;
border: 1px solid rgba(201, 169, 120, 0.55);
border-radius: 50%;
box-shadow: 0 0 0 4px rgba(255, 255, 255, 0.7), 0 0 0 5px rgba(201, 169, 120, 0.35), 0 12px 30px rgba(120, 90, 60, 0.16);
background: #fff;
}
.gf-circle > img {
border-radius: 50%;
}
/* 椭圆/正圆:底部花饰小章 */
.gf-oval::before,
.gf-circle::before {
content: '❀';
position: absolute;
bottom: 10px;
left: 50%;
transform: translateX(-50%);
width: 24px;
height: 24px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 11px;
line-height: 1;
color: #b08e63;
background: rgba(253, 251, 247, 0.92);
box-shadow: 0 0 0 1px rgba(201, 169, 120, 0.4), 0 2px 5px rgba(120, 90, 60, 0.15);
pointer-events: none;
z-index: 1;
}
/* 叶形花瓣(两对角大圆两对角小圆,推荐 1:1) */
.gf-leaf {
padding: 7px;
border: 1px solid rgba(201, 169, 120, 0.5);
border-radius: 60% 12% 60% 12%;
box-shadow: 0 0 0 4px rgba(255, 255, 255, 0.6), 0 12px 30px rgba(120, 90, 60, 0.15);
background: #fff;
}
.gf-leaf > img {
border-radius: 58% 9% 58% 9%;
}
/* 六边形(clip 直裁,推荐 1:1) */
.gf-hexagon {
padding: 0;
border: 0;
border-radius: 0;
box-shadow: none;
clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
-webkit-clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
}
/* 八瓣花(多层 radial mask 合成花形,推荐 1:1) */
.gf-flower {
padding: 0;
border: 0;
border-radius: 0;
box-shadow: none;
-webkit-mask:
radial-gradient(19% 19% at 50% 19%, #000 98%, #0000 100%),
radial-gradient(19% 19% at 71.9% 28.1%, #000 98%, #0000 100%),
radial-gradient(19% 19% at 81% 50%, #000 98%, #0000 100%),
radial-gradient(19% 19% at 71.9% 71.9%, #000 98%, #0000 100%),
radial-gradient(19% 19% at 50% 81%, #000 98%, #0000 100%),
radial-gradient(19% 19% at 28.1% 71.9%, #000 98%, #0000 100%),
radial-gradient(19% 19% at 19% 50%, #000 98%, #0000 100%),
radial-gradient(19% 19% at 28.1% 28.1%, #000 98%, #0000 100%),
radial-gradient(34% 34% at 50% 50%, #000 98%, #0000 100%);
mask:
radial-gradient(19% 19% at 50% 19%, #000 98%, #0000 100%),
radial-gradient(19% 19% at 71.9% 28.1%, #000 98%, #0000 100%),
radial-gradient(19% 19% at 81% 50%, #000 98%, #0000 100%),
radial-gradient(19% 19% at 71.9% 71.9%, #000 98%, #0000 100%),
radial-gradient(19% 19% at 50% 81%, #000 98%, #0000 100%),
radial-gradient(19% 19% at 28.1% 71.9%, #000 98%, #0000 100%),
radial-gradient(19% 19% at 19% 50%, #000 98%, #0000 100%),
radial-gradient(19% 19% at 28.1% 28.1%, #000 98%, #0000 100%),
radial-gradient(34% 34% at 50% 50%, #000 98%, #0000 100%);
}
/* 心形(SVG mask 裁切,推荐 1:1) */
.gf-heart {
padding: 0;
border: 0;
border-radius: 0;
box-shadow: none;
-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='%23000' d='M462.3 62.6C407.5 15.9 326 24.3 275.7 76.2L256 96.5l-19.7-20.3C186.1 24.3 104.5 15.9 49.7 62.6c-62.8 53.6-66.1 149.8-9.9 207.9l193.5 199.8c12.5 12.9 32.8 12.9 45.3 0l193.5-199.8c56.3-58.1 53-154.3-9.8-207.9z'/%3E%3C/svg%3E") no-repeat 50% 50% / 100% 100%;
mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='%23000' d='M462.3 62.6C407.5 15.9 326 24.3 275.7 76.2L256 96.5l-19.7-20.3C186.1 24.3 104.5 15.9 49.7 62.6c-62.8 53.6-66.1 149.8-9.9 207.9l193.5 199.8c12.5 12.9 32.8 12.9 45.3 0l193.5-199.8c56.3-58.1 53-154.3-9.8-207.9z'/%3E%3C/svg%3E") no-repeat 50% 50% / 100% 100%;
}
/* 扇贝花边(四边外凸圆弧波浪) */
.gf-scallop {
--gf-r: 7px;
padding: 14px;
border: 0;
border-radius: 0;
box-shadow: none;
background: #fff;
-webkit-mask:
radial-gradient(var(--gf-r), #000 98%, #0000) 0 0 / calc(2 * var(--gf-r)) calc(2 * var(--gf-r)) round,
linear-gradient(#000 0 0) 50% / calc(100% - 2 * var(--gf-r)) calc(100% - 2 * var(--gf-r)) no-repeat;
mask:
radial-gradient(var(--gf-r), #000 98%, #0000) 0 0 / calc(2 * var(--gf-r)) calc(2 * var(--gf-r)) round,
linear-gradient(#000 0 0) 50% / calc(100% - 2 * var(--gf-r)) calc(100% - 2 * var(--gf-r)) no-repeat;
}
/* 蕾丝缝线(内圈虚线) */
.gf-scallop::before {
content: '';
position: absolute;
inset: 17px;
border: 1px dashed rgba(255, 255, 255, 0.7);
border-radius: 2px;
pointer-events: none;
z-index: 1;
}
/* 蕾丝波浪(四边相切凹圆弧,剪纸蕾丝垫感) */
.gf-wave {
--gf-r: 9px;
padding: 15px;
border: 0;
border-radius: 0;
box-shadow: none;
background: #fff;
-webkit-mask:
radial-gradient(var(--gf-r), #0000 98%, #000) calc(-1 * var(--gf-r)) calc(-1 * var(--gf-r)) / calc(2 * var(--gf-r)) calc(2 * var(--gf-r)) round,
linear-gradient(#000 0 0) 50% / calc(100% - 2 * var(--gf-r)) calc(100% - 2 * var(--gf-r)) no-repeat;
mask:
radial-gradient(var(--gf-r), #0000 98%, #000) calc(-1 * var(--gf-r)) calc(-1 * var(--gf-r)) / calc(2 * var(--gf-r)) calc(2 * var(--gf-r)) round,
linear-gradient(#000 0 0) 50% / calc(100% - 2 * var(--gf-r)) calc(100% - 2 * var(--gf-r)) no-repeat;
}
/* 蕾丝点状缝线 */
.gf-wave::before {
content: '';
position: absolute;
inset: 18px;
border: 1px dotted rgba(255, 255, 255, 0.75);
border-radius: 3px;
pointer-events: none;
z-index: 1;
}
/* 锯齿花边(四边三角齿,花边剪刀裁切的相纸;齿深须为齿宽一半) */
.gf-zigzag {
--gf-z: 16px;
--gf-zd: 8px;
padding: 14px;
border: 0;
border-radius: 0;
box-shadow: none;
background: #fff;
-webkit-mask:
conic-gradient(from 135deg at 50% 0, #000 90deg, #0000 0) 50% 0 / var(--gf-z) var(--gf-zd) repeat-x,
conic-gradient(from -45deg at 50% 100%, #000 90deg, #0000 0) 50% 100% / var(--gf-z) var(--gf-zd) repeat-x,
conic-gradient(from 45deg at 0 50%, #000 90deg, #0000 0) 0 50% / var(--gf-zd) var(--gf-z) repeat-y,
conic-gradient(from 225deg at 100% 50%, #000 90deg, #0000 0) 100% 50% / var(--gf-zd) var(--gf-z) repeat-y,
linear-gradient(#000 0 0) 50% / calc(100% - 2 * var(--gf-zd) + 2px) calc(100% - 2 * var(--gf-zd) + 2px) no-repeat;
mask:
conic-gradient(from 135deg at 50% 0, #000 90deg, #0000 0) 50% 0 / var(--gf-z) var(--gf-zd) repeat-x,
conic-gradient(from -45deg at 50% 100%, #000 90deg, #0000 0) 50% 100% / var(--gf-z) var(--gf-zd) repeat-x,
conic-gradient(from 45deg at 0 50%, #000 90deg, #0000 0) 0 50% / var(--gf-zd) var(--gf-z) repeat-y,
conic-gradient(from 225deg at 100% 50%, #000 90deg, #0000 0) 100% 50% / var(--gf-zd) var(--gf-z) repeat-y,
linear-gradient(#000 0 0) 50% / calc(100% - 2 * var(--gf-zd) + 2px) calc(100% - 2 * var(--gf-zd) + 2px) no-repeat;
}
/* 剪纸内线 */
.gf-zigzag::before {
content: '';
position: absolute;
inset: 17px;
border: 1px solid rgba(255, 255, 255, 0.55);
pointer-events: none;
z-index: 1;
}
/* 切角相纸(八边形切角,复古照片角) */
.gf-bevel {
padding: 10px;
border: 0;
border-radius: 0;
box-shadow: none;
background: #fff;
clip-path: polygon(18px 0, calc(100% - 18px) 0, 100% 18px, 100% calc(100% - 18px), calc(100% - 18px) 100%, 18px 100%, 0 calc(100% - 18px), 0 18px);
-webkit-clip-path: polygon(18px 0, calc(100% - 18px) 0, 100% 18px, 100% calc(100% - 18px), calc(100% - 18px) 100%, 18px 100%, 0 calc(100% - 18px), 0 18px);
}
/* 撕纸边(不规则毛边,像从相纸上撕下来) */
.gf-torn {
padding: 12px;
border: 0;
border-radius: 0;
box-shadow: none;
background: #fff;
-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' preserveAspectRatio='none'%3E%3Cpath fill='%23000' d='M0 3L6 1.4L13 3.4L19 1.2L26 3L33 1.6L40 3.2L47 1.3L54 2.8L61 1.5L68 3.3L75 1.4L82 2.9L89 1.6L96 3.1L98.6 8L96.9 14L98.4 20L96.8 27L98.5 34L97 41L98.6 48L96.9 55L98.3 62L97 69L98.5 76L96.8 83L98.4 90L97.1 96L94 98.6L87 97L80 98.7L73 96.9L66 98.5L59 97.1L52 98.6L45 96.8L38 98.4L31 97L24 98.6L17 96.9L10 98.5L4 97.2L1.5 92L3.2 85L1.4 78L3 71L1.6 64L3.3 57L1.3 50L2.9 43L1.5 36L3.2 29L1.4 22L3 15L1.7 8Z'/%3E%3C/svg%3E") no-repeat 50% 50% / 100% 100%;
mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' preserveAspectRatio='none'%3E%3Cpath fill='%23000' d='M0 3L6 1.4L13 3.4L19 1.2L26 3L33 1.6L40 3.2L47 1.3L54 2.8L61 1.5L68 3.3L75 1.4L82 2.9L89 1.6L96 3.1L98.6 8L96.9 14L98.4 20L96.8 27L98.5 34L97 41L98.6 48L96.9 55L98.3 62L97 69L98.5 76L96.8 83L98.4 90L97.1 96L94 98.6L87 97L80 98.7L73 96.9L66 98.5L59 97.1L52 98.6L45 96.8L38 98.4L31 97L24 98.6L17 96.9L10 98.5L4 97.2L1.5 92L3.2 85L1.4 78L3 71L1.6 64L3.3 57L1.3 50L2.9 43L1.5 36L3.2 29L1.4 22L3 15L1.7 8Z'/%3E%3C/svg%3E") no-repeat 50% 50% / 100% 100%;
}
/* 撕纸:顶部半透明胶带贴纸 */
.gf-torn::before {
content: '';
position: absolute;
top: 4px;
left: 50%;
width: 72px;
height: 20px;
transform: translateX(-50%) rotate(-2.5deg);
background: linear-gradient(rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0.36));
box-shadow: 0 1px 4px rgba(96, 72, 50, 0.18);
pointer-events: none;
z-index: 1;
}
/* 车票票根(两侧半圆缺口,缺口自带撕票线意象;
不画横穿虚线——会压在照片主体/人脸上) */
.gf-ticket {
--gf-n: 11px;
padding: 10px 16px 26px;
border: 0;
border-radius: 14px;
box-shadow: none;
background: #fff;
-webkit-mask:
radial-gradient(var(--gf-n) at 0 50%, #0000 98%, #000) 0 0 / 51% 100% no-repeat,
radial-gradient(var(--gf-n) at 100% 50%, #0000 98%, #000) 100% 0 / 51% 100% no-repeat;
mask:
radial-gradient(var(--gf-n) at 0 50%, #0000 98%, #000) 0 0 / 51% 100% no-repeat,
radial-gradient(var(--gf-n) at 100% 50%, #0000 98%, #000) 100% 0 / 51% 100% no-repeat;
}
/* 票面字样(位于底部票边区,窄格自动截断居中) */
.gf-ticket::before {
content: 'ADMIT ONE';
position: absolute;
left: 0;
right: 0;
bottom: 8px;
text-align: center;
font-family: Georgia, 'Times New Roman', serif;
font-size: 9px;
line-height: 1;
letter-spacing: 0.4em;
text-indent: 0.4em;
color: #b89a78;
white-space: nowrap;
overflow: hidden;
pointer-events: none;
}
/* 复古胶片(深色框 + 上下齿孔) */
.gf-film {
padding: 15px 6px;
border: 0;
border-radius: 6px;
box-shadow: 0 12px 28px rgba(30, 24, 18, 0.3);
background: #26231f;
}
.gf-film > img {
border-radius: 2px;
}
.gf-film::before,
.gf-film::after {
content: '';
position: absolute;
left: 8px;
right: 8px;
height: 7px;
background-image: repeating-linear-gradient(90deg, rgba(253, 251, 247, 0.85) 0 9px, transparent 9px 18px);
pointer-events: none;
}
.gf-film::before {
top: 4px;
}
.gf-film::after {
bottom: 4px;
}
/* ============================================================
横幅 · 云雾花(group: scenic)—— 横向比例的风景明信片
装饰主题:云朵 / 晨雾 / 花卉;推荐 4:3 或 16:9
============================================================ */
/* 云朵相框(大小圆交替蓬松云边,推荐 4:3) */
.gf-cloud {
--gf-c: 14px;
padding: 16px;
border: 0;
border-radius: 0;
box-shadow: none;
background: #fff;
-webkit-mask:
radial-gradient(var(--gf-c), #000 98%, #0000) 0 0 / calc(3.4 * var(--gf-c)) calc(3.4 * var(--gf-c)) round,
radial-gradient(calc(0.68 * var(--gf-c)), #000 98%, #0000) calc(1.7 * var(--gf-c)) calc(1.7 * var(--gf-c)) / calc(3.4 * var(--gf-c)) calc(3.4 * var(--gf-c)) round,
linear-gradient(#000 0 0) 50% / calc(100% - 2.4 * var(--gf-c)) calc(100% - 2.4 * var(--gf-c)) no-repeat;
mask:
radial-gradient(var(--gf-c), #000 98%, #0000) 0 0 / calc(3.4 * var(--gf-c)) calc(3.4 * var(--gf-c)) round,
radial-gradient(calc(0.68 * var(--gf-c)), #000 98%, #0000) calc(1.7 * var(--gf-c)) calc(1.7 * var(--gf-c)) / calc(3.4 * var(--gf-c)) calc(3.4 * var(--gf-c)) round,
linear-gradient(#000 0 0) 50% / calc(100% - 2.4 * var(--gf-c)) calc(100% - 2.4 * var(--gf-c)) no-repeat;
}
/* 右上飘着的小云 */
.gf-cloud::before {
content: '';
position: absolute;
top: 22px;
right: 24px;
width: 52px;
height: 22px;
background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 26'%3E%3Cpath d='M13 22a7 7 0 1 1 1.6-13.8A10 10 0 0 1 34 5a8 8 0 0 1 8.6 8A6.5 6.5 0 0 1 41 22z' fill='%23ffffff' fill-opacity='.92'/%3E%3Cellipse cx='54' cy='19' rx='8' ry='4.6' fill='%23ffffff' fill-opacity='.72'/%3E%3C/svg%3E") no-repeat center / contain;
filter: drop-shadow(0 2px 3px rgba(120, 90, 60, 0.14));
pointer-events: none;
z-index: 1;
}
/* 晨雾朦胧(四周羽化渐隐 + 底部飘雾,推荐 4:3;无边框无投影更空灵) */
.gf-mist {
padding: 0;
border: 0;
border-radius: 0;
box-shadow: none;
background: transparent;
-webkit-mask: radial-gradient(112% 112% at 50% 48%, #000 56%, #0000 90%);
mask: radial-gradient(112% 112% at 50% 48%, #000 56%, #0000 90%);
}
/* 底部两团晨雾 */
.gf-mist::before {
content: '';
position: absolute;
left: 6%;
right: 6%;
bottom: 4%;
height: 30%;
background:
radial-gradient(58% 100% at 30% 100%, rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0) 70%),
radial-gradient(48% 88% at 72% 100%, rgba(255, 255, 255, 0.38), rgba(255, 255, 255, 0) 72%);
filter: blur(6px);
pointer-events: none;
z-index: 1;
}
/* 花语卡纸(暖白卡 + 对角花枝,推荐 4:3) */
.gf-bloom {
padding: 14px;
border: 1px solid rgba(201, 169, 120, 0.4);
border-radius: 10px;
box-shadow: 0 10px 26px rgba(120, 90, 60, 0.14);
background: linear-gradient(160deg, #fffdf8, #fdf7ec);
}
.gf-bloom > img {
border-radius: 5px;
}
/* 左上 / 右下花枝(同一 SVG,右下旋转 180°) */
.gf-bloom::before,
.gf-bloom::after {
content: '';
position: absolute;
width: 56px;
height: 56px;
background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'%3E%3Cg fill='none' stroke='%23b8a078' stroke-width='1.4' stroke-linecap='round'%3E%3Cpath d='M6 58C16 46 26 36 46 24'/%3E%3Cpath d='M22 42c7 1 12-2 14-8'/%3E%3Cpath d='M14 50c5 2 10 1 13-3'/%3E%3C/g%3E%3Cg fill='%23a8bfa0'%3E%3Cpath d='M30 33c-1-5 1-8 5-9 1 4-1 7-5 9z'/%3E%3Cpath d='M20 44c-4-2-5-6-3-9 3 2 4 5 3 9z'/%3E%3C/g%3E%3Cg transform='translate(48,20)'%3E%3Cg fill='%23e4aeb6'%3E%3Ccircle cx='0' cy='-5.2' r='3.6'/%3E%3Ccircle cx='4.9' cy='-1.6' r='3.6'/%3E%3Ccircle cx='3.1' cy='4.2' r='3.6'/%3E%3Ccircle cx='-3.1' cy='4.2' r='3.6'/%3E%3Ccircle cx='-4.9' cy='-1.6' r='3.6'/%3E%3C/g%3E%3Ccircle r='2.4' fill='%23c9a24a'/%3E%3C/g%3E%3Cg transform='translate(30,52) scale(.62)'%3E%3Cg fill='%23edc3ca'%3E%3Ccircle cx='0' cy='-5.2' r='3.6'/%3E%3Ccircle cx='4.9' cy='-1.6' r='3.6'/%3E%3Ccircle cx='3.1' cy='4.2' r='3.6'/%3E%3Ccircle cx='-3.1' cy='4.2' r='3.6'/%3E%3Ccircle cx='-4.9' cy='-1.6' r='3.6'/%3E%3C/g%3E%3Ccircle r='2.4' fill='%23c9a24a'/%3E%3C/g%3E%3C/svg%3E") no-repeat center / contain;
pointer-events: none;
z-index: 1;
}
.gf-bloom::before {
top: 2px;
left: 2px;
}
.gf-bloom::after {
bottom: 2px;
right: 2px;
transform: rotate(180deg);
}
/* 宽幅全景(16:9 电影画幅白卡 + 云与飞鸟 + 手写落款) */
.gf-panorama {
padding: 16px 14px 34px;
border: 1px solid rgba(184, 154, 120, 0.3);
border-radius: 4px;
box-shadow: 0 12px 30px rgba(120, 90, 60, 0.16);
background: #fffdf6;
}
/* 顶部白边区:淡云 + 三只飞鸟 */
.gf-panorama::before {
content: '';
position: absolute;
top: 3px;
left: 14px;
right: 12px;
height: 12px;
background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 124 14'%3E%3Cpath d='M8 11a4 4 0 1 1 1-7.9A5.5 5.5 0 0 1 19 2a4.5 4.5 0 0 1 5 4.5A3.8 3.8 0 0 1 22 11z' fill='%23d8c8b0' fill-opacity='.55'/%3E%3Cg fill='none' stroke='%23a08a6a' stroke-width='1.3' stroke-linecap='round'%3E%3Cpath d='M78 8c2.5-2.6 4.5-2.6 7 0M85 8c2.5-2.6 4.5-2.6 7 0'/%3E%3Cpath d='M96 5c2-2.2 3.8-2.2 5.8 0M101.8 5c2-2.2 3.8-2.2 5.8 0'/%3E%3Cpath d='M110 10c1.6-1.8 3-1.8 4.6 0M114.6 10c1.6-1.8 3-1.8 4.6 0'/%3E%3C/g%3E%3C/svg%3E") no-repeat center / contain;
opacity: 0.9;
pointer-events: none;
z-index: 1;
}
/* 底部白边区:手写体落款 */
.gf-panorama::after {
content: 'with love';
position: absolute;
left: 0;
right: 0;
bottom: 9px;
text-align: center;
font-family: 'Great Vibes', 'Segoe Script', cursive;
font-size: 15px;
line-height: 1;
color: #b89a78;
letter-spacing: 0.06em;
white-space: nowrap;
overflow: hidden;
pointer-events: none;
}
/* 横椭圆框(椭圆随 4:3 容器自然拉宽 + 底部花饰小章) */
.gf-ovalwide {
padding: 7px;
border: 1px solid rgba(201, 169, 120, 0.55);
border-radius: 50%;
box-shadow: 0 0 0 4px rgba(255, 255, 255, 0.7), 0 12px 30px rgba(120, 90, 60, 0.16);
background: #fff;
}
.gf-ovalwide > img {
border-radius: 50%;
}
.gf-ovalwide::before {
content: '❀';
position: absolute;
bottom: 6px;
left: 50%;
transform: translateX(-50%);
width: 24px;
height: 24px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 11px;
line-height: 1;
color: #b08e63;
background: rgba(253, 251, 247, 0.92);
box-shadow: 0 0 0 1px rgba(201, 169, 120, 0.4), 0 2px 5px rgba(120, 90, 60, 0.15);
pointer-events: none;
z-index: 1;
}
/* 异形裁切类的投影:mask 会裁掉 box-shadow,由父级 drop-shadow 跟随轮廓补投影 */
.gf-shape-shadow {
filter: drop-shadow(0 10px 18px rgba(96, 72, 50, 0.22));
}
/* 辅助:图片保持原始宽高比(单图铺满+保比例时使用,覆盖 gf-frame 的 height:100%) */
.gf-natural {
height: auto !important;
}
.gf-natural > img {
height: auto;
object-fit: contain;
}