Make WordPress Themes

Changeset 353530


Ignore:
Timestamp:
10/13/2026 12:00:01 PM (2 weeks ago)
Author:
themedropbox
Message:

New version of Postfolio Blocks - 1.2.0

Location:
postfolio-blocks/1.2.0
Files:
41 added
24 edited
1 copied

Legend:

Unmodified
Added
Removed
  • postfolio-blocks/1.2.0/assets/css/admin-dashboard.css

    r352228 r353530  
    326326}
    327327
    328 /* Starter Sites Cards */
    329 .postfolio-starter-grid {
    330         display: grid;
    331         grid-template-columns: repeat(auto-fill, minmax(min(100%, 320px), 1fr));
    332         gap: 24px;
    333         margin-top: 20px;
    334 }
    335 
    336 .postfolio-starter-card {
    337         background: #ffffff;
    338         border: 1px solid #e2e8f0;
    339         border-radius: 10px;
    340         overflow: hidden;
    341         box-shadow: 0 1px 3px rgba(0,0,0,0.03);
    342         display: flex;
    343         flex-direction: column;
    344         position: relative;
    345         transition: transform 0.2s ease, box-shadow 0.2s ease;
    346 }
    347 
    348 .postfolio-starter-card:hover {
    349         transform: translateY(-2px);
    350         box-shadow: 0 8px 24px rgba(0,0,0,0.06);
    351 }
    352 
    353 .postfolio-starter-preview-wrap {
    354         width: 100%;
    355         height: 220px;
    356         background: #f8fafc;
    357         position: relative;
    358         overflow: hidden;
    359         border-bottom: 1px solid #f1f5f9;
    360 }
    361 
    362 .postfolio-starter-preview-wrap img,
    363 .postfolio-starter-preview-wrap svg {
    364         width: 100%;
    365         height: 100%;
    366         object-fit: cover;
    367         display: block;
    368 }
    369 
    370 .postfolio-pro-badge {
    371         position: absolute;
    372         top: 12px;
    373         right: 12px;
    374         background: #ea580c;
    375         color: #ffffff;
    376         font-size: 11px;
    377         font-weight: 700;
    378         padding: 3px 8px;
    379         border-radius: 4px;
    380         letter-spacing: 0.5px;
    381         text-transform: uppercase;
    382 }
    383 
    384 .postfolio-starter-footer {
    385         padding: 16px 20px;
    386         display: flex;
    387         align-items: center;
    388         justify-content: space-between;
    389         background: #ffffff;
    390 }
    391 
    392 .postfolio-starter-title {
    393         font-size: 16px;
    394         font-weight: 600;
    395         color: #0f172a;
    396 }
    397 
    398 .postfolio-starter-actions {
    399         display: flex;
    400         gap: 8px;
    401 }
    402 
    403328.postfolio-btn-outline {
    404329        background: #ffffff;
    … …  
    648573}
    649574
    650 .postfolio-starter-desc {
    651         margin: 4px 0 12px;
    652         font-size: 13px;
    653         color: #64748b;
    654         line-height: 1.5;
    655 }
    656 
    657 .postfolio-starter-footer {
    658         flex-direction: column;
    659         align-items: flex-start;
    660 }
    661 
    662 .postfolio-starter-actions {
    663         width: 100%;
    664 }
    665 
    666 .postfolio-starter-actions .postfolio-btn-import {
    667         width: 100%;
    668         justify-content: center;
    669 }
     575/* starter cards: see the end of this file */
    670576
    671577.postfolio-comparison-table tbody th {
    … …  
    698604        }
    699605}
     606
     607/* ==========================================================================
     608   Starter sites
     609   Each card carries its starter site's design tokens as custom properties
     610   (--pf-bg, --pf-fg, --pf-ac, --pf-hf, --pf-r …) and paints a mini mockup
     611   of the homepage with them, using the theme's own bundled fonts.
     612   ========================================================================== */
     613
     614@font-face { font-family: "Poppins"; src: url(../fonts/poppins-latin-700-normal.woff2) format("woff2"); font-weight: 700; font-display: swap; }
     615@font-face { font-family: "Poppins"; src: url(../fonts/poppins-latin-600-normal.woff2) format("woff2"); font-weight: 600; font-display: swap; }
     616@font-face { font-family: "Montserrat"; src: url(../fonts/montserrat-latin-300-800-normal.woff2) format("woff2"); font-weight: 300 800; font-display: swap; }
     617@font-face { font-family: "Manrope"; src: url(../fonts/manrope-latin-wght-normal.woff2) format("woff2"); font-weight: 200 800; font-display: swap; }
     618@font-face { font-family: "Lora"; src: url(../fonts/lora-latin-400-700-normal.woff2) format("woff2"); font-weight: 400 700; font-display: swap; }
     619@font-face { font-family: "Playfair Display"; src: url(../fonts/playfair-display-latin-400-900-normal.woff2) format("woff2"); font-weight: 400 900; font-display: swap; }
     620@font-face { font-family: "Playfair Display"; src: url(../fonts/playfair-display-latin-400-900-italic.woff2) format("woff2"); font-weight: 400 900; font-style: italic; font-display: swap; }
     621
     622.postfolio-starter-grid {
     623        display: grid;
     624        grid-template-columns: repeat(auto-fill, minmax(min(100%, 300px), 1fr));
     625        gap: 24px;
     626        margin-top: 20px;
     627}
     628
     629.postfolio-starter-card {
     630        display: flex;
     631        flex-direction: column;
     632        background: #ffffff;
     633        border: 1px solid #e2e8f0;
     634        border-radius: 14px;
     635        overflow: hidden;
     636        box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04);
     637        transition: transform 0.25s ease, box-shadow 0.25s ease, border-color 0.25s ease;
     638}
     639
     640.postfolio-starter-card:hover,
     641.postfolio-starter-card:focus-within {
     642        transform: translateY(-3px);
     643        border-color: color-mix(in srgb, var(--pf-ac) 45%, #e2e8f0);
     644        box-shadow: 0 14px 34px -12px color-mix(in srgb, var(--pf-ac) 40%, transparent);
     645}
     646
     647/* Preview stage: tinted with the site's own accent colors. */
     648.postfolio-starter-preview-wrap {
     649        padding: 18px 18px 0;
     650        background:
     651                radial-gradient(120% 80% at 100% 0%, color-mix(in srgb, var(--pf-ac) 22%, transparent), transparent 60%),
     652                radial-gradient(90% 70% at 0% 100%, color-mix(in srgb, var(--pf-ac2) 18%, transparent), transparent 60%),
     653                color-mix(in srgb, var(--pf-ac) 6%, #f8fafc);
     654        border-bottom: 1px solid #eef2f7;
     655}
     656
     657/* ---------- Mini browser ---------- */
     658.pfm-chrome {
     659        display: flex;
     660        align-items: center;
     661        gap: 5px;
     662        height: 22px;
     663        padding: 0 10px;
     664        background: #ffffff;
     665        border: 1px solid rgba(15, 23, 42, 0.08);
     666        border-bottom: 0;
     667        border-radius: 9px 9px 0 0;
     668}
     669
     670.pfm-chrome i {
     671        width: 7px;
     672        height: 7px;
     673        border-radius: 50%;
     674        background: #e2e8f0;
     675}
     676
     677.pfm-chrome i:first-child { background: #fca5a5; }
     678.pfm-chrome i:nth-child(2) { background: #fcd34d; }
     679.pfm-chrome i:nth-child(3) { background: #86efac; }
     680
     681.pfm-url {
     682        flex: 1;
     683        max-width: 55%;
     684        height: 9px;
     685        margin-left: 8px;
     686        border-radius: 9px;
     687        background: #f1f5f9;
     688}
     689
     690.pfm-screen {
     691        container-type: inline-size;
     692        position: relative;
     693        aspect-ratio: 16 / 10;
     694        overflow: hidden;
     695        background: var(--pf-bg);
     696        border: 1px solid rgba(15, 23, 42, 0.08);
     697        border-bottom: 0;
     698        box-shadow: 0 -2px 18px -6px rgba(15, 23, 42, 0.18);
     699}
     700
     701/* The page is taller than the screen and scrolls into view on hover. */
     702.pfm-page {
     703        display: flex;
     704        flex-direction: column;
     705        gap: 5cqw;
     706        padding: 0 5cqw 6cqw;
     707        color: var(--pf-fg);
     708        background: var(--pf-bg);
     709        font-family: var(--pf-bf);
     710        transition: transform 2.4s cubic-bezier(0.45, 0, 0.25, 1);
     711}
     712
     713.postfolio-starter-card:hover .pfm-page,
     714.postfolio-starter-card:focus-within .pfm-page {
     715        transform: translateY(-38%);
     716}
     717
     718@media (prefers-reduced-motion: reduce) {
     719        .postfolio-starter-card,
     720        .pfm-page {
     721                transition: none;
     722        }
     723
     724        .postfolio-starter-card:hover .pfm-page,
     725        .postfolio-starter-card:focus-within .pfm-page {
     726                transform: none;
     727        }
     728}
     729
     730/* ---------- Mockup atoms ---------- */
     731.pfm-header {
     732        display: flex;
     733        align-items: center;
     734        gap: 3cqw;
     735        padding: 3.4cqw 0;
     736        border-bottom: 1px solid color-mix(in srgb, var(--pf-fg) 10%, transparent);
     737}
     738
     739.pfm-header.is-ruled {
     740        border-bottom: 2px solid var(--pf-fg);
     741}
     742
     743.pfm-header.is-transparent {
     744        border-color: color-mix(in srgb, var(--pf-bg) 25%, transparent);
     745        color: var(--pf-bg);
     746}
     747
     748.pfm-logo {
     749        max-width: 32%;
     750        overflow: hidden;
     751        white-space: nowrap;
     752        text-overflow: ellipsis;
     753        font-family: var(--pf-hf);
     754        font-size: 3.6cqw;
     755        font-weight: 800;
     756        letter-spacing: -0.01em;
     757}
     758
     759.pfm-nav {
     760        display: flex;
     761        gap: 2.4cqw;
     762        margin-left: auto;
     763}
     764
     765.pfm-nav i {
     766        width: 6cqw;
     767        height: 1.2cqw;
     768        border-radius: 2cqw;
     769        background: currentColor;
     770        opacity: 0.35;
     771}
     772
     773.pfm-btn {
     774        display: inline-block;
     775        width: 16cqw;
     776        height: 5.4cqw;
     777        border-radius: var(--pf-r);
     778        background: var(--pf-ac);
     779}
     780
     781.pfm-btn.is-small { width: 11cqw; height: 4cqw; }
     782.pfm-btn.is-ghost { background: transparent; box-shadow: inset 0 0 0 1.5px currentColor; opacity: 0.6; }
     783.pfm-btn.is-block { width: 100%; height: 4.4cqw; margin-top: auto; }
     784
     785.pfm-actions {
     786        display: flex;
     787        gap: 2cqw;
     788        margin-top: 1cqw;
     789}
     790
     791.pfm-kicker {
     792        width: 14cqw;
     793        height: 1.4cqw;
     794        border-radius: 2cqw;
     795        background: var(--pf-ac);
     796}
     797
     798.pfm-title {
     799        display: block;
     800        font-family: var(--pf-hf);
     801        font-size: 6.4cqw;
     802        font-weight: 700;
     803        line-height: 1.12;
     804        letter-spacing: -0.015em;
     805        color: inherit;
     806}
     807
     808.pfm-title.is-lg { font-size: 7.6cqw; }
     809.pfm-title.is-md { font-size: 4.2cqw; }
     810.pfm-title.is-sm { font-size: 3.8cqw; }
     811
     812.pfm-title em {
     813        font-style: italic;
     814        color: var(--pf-ac);
     815}
     816
     817.pfm-line {
     818        display: block;
     819        height: 1.3cqw;
     820        border-radius: 2cqw;
     821        background: var(--pf-fg2);
     822        opacity: 0.35;
     823}
     824
     825.pfm-line.is-strong {
     826        height: 1.7cqw;
     827        background: var(--pf-fg);
     828        opacity: 0.8;
     829}
     830
     831.pfm-tag {
     832        display: block;
     833        width: 9cqw;
     834        height: 1.2cqw;
     835        border-radius: 2cqw;
     836        background: var(--pf-ac);
     837        opacity: 0.85;
     838}
     839
     840.pfm-img {
     841        display: block;
     842        aspect-ratio: 4 / 3;
     843        border-radius: calc(min(var(--pf-r), 12px) * 0.6);
     844        background:
     845                radial-gradient(circle at 72% 30%, color-mix(in srgb, var(--pf-bg) 70%, transparent) 0 9%, transparent 10%),
     846                linear-gradient(160deg, transparent 55%, color-mix(in srgb, var(--pf-fg) 22%, transparent) 56%),
     847                linear-gradient(135deg, var(--pf-ac), var(--pf-ac2));
     848}
     849
     850.pfm-grid .pfm-card:nth-child(2) .pfm-img { filter: hue-rotate(-18deg); }
     851.pfm-grid .pfm-card:nth-child(3) .pfm-img { filter: saturate(0.7) brightness(1.1); }
     852.pfm-img.is-tall { aspect-ratio: 16 / 10; }
     853.pfm-img.is-thumb { flex: none; width: 15cqw; aspect-ratio: 1; }
     854
     855.pfm-hero,
     856.pfm-card,
     857.pfm-lead,
     858.pfm-list {
     859        display: flex;
     860        flex-direction: column;
     861        gap: 1.8cqw;
     862}
     863
     864.pfm-list { gap: 3cqw; }
     865.pfm-hero { gap: 2.4cqw; padding-top: 3cqw; }
     866.pfm-hero.is-center { align-items: center; text-align: center; }
     867
     868.pfm-grid {
     869        display: grid;
     870        gap: 3cqw;
     871}
     872
     873.pfm-grid.is-3 { grid-template-columns: repeat(3, 1fr); }
     874.pfm-grid.is-4 { grid-template-columns: repeat(4, 1fr); gap: 2.4cqw; }
     875
     876.pfm-card.is-boxed {
     877        padding: 3cqw;
     878        border-radius: min(var(--pf-r), 12px);
     879        background: var(--pf-bg2);
     880}
     881
     882.pfm-row {
     883        display: flex;
     884        align-items: center;
     885        gap: 2.4cqw;
     886}
     887
     888.pfm-row > div {
     889        display: flex;
     890        flex: 1;
     891        flex-direction: column;
     892        gap: 1.4cqw;
     893}
     894
     895.pfm-row.is-list {
     896        padding-bottom: 3cqw;
     897        border-bottom: 1px solid color-mix(in srgb, var(--pf-fg) 12%, transparent);
     898}
     899
     900.pfm-band {
     901        display: flex;
     902        flex-direction: column;
     903        align-items: center;
     904        gap: 2.4cqw;
     905        padding: 5cqw;
     906        border-radius: min(var(--pf-r), 14px);
     907        background: var(--pf-bg2);
     908        text-align: center;
     909}
     910
     911.pfm-band.is-split {
     912        flex-direction: row;
     913        justify-content: space-between;
     914        background: var(--pf-ac);
     915        color: var(--pf-bg);
     916}
     917
     918.pfm-band.is-split .pfm-btn { background: var(--pf-bg); }
     919
     920.pfm-input {
     921        width: 60%;
     922        height: 5cqw;
     923        border-radius: var(--pf-r);
     924        background: var(--pf-bg);
     925        box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--pf-fg) 15%, transparent);
     926}
     927
     928.pfm-label {
     929        width: 22cqw;
     930        height: 2cqw;
     931        margin-bottom: -2cqw;
     932        border-radius: 2cqw;
     933        background: var(--pf-fg);
     934}
     935
     936/* Magazine */
     937.pfm-feature {
     938        display: grid;
     939        grid-template-columns: 1.4fr 1fr;
     940        gap: 3.4cqw;
     941        padding-top: 1cqw;
     942}
     943
     944.pfm-side {
     945        display: flex;
     946        flex-direction: column;
     947        gap: 2.6cqw;
     948}
     949
     950.pfm-magazine .pfm-img { border-radius: 0; }
     951
     952/* Portfolio */
     953.pfm-projects { gap: 2.4cqw; }
     954
     955.pfm-tile {
     956        aspect-ratio: 1;
     957        border-radius: min(var(--pf-r), 12px);
     958        background: linear-gradient(140deg, var(--pf-ac), color-mix(in srgb, var(--pf-ac) 30%, var(--pf-bg2)));
     959}
     960
     961.pfm-tile:nth-child(2n) { background: linear-gradient(140deg, var(--pf-ac2), color-mix(in srgb, var(--pf-ac2) 30%, var(--pf-bg2))); }
     962.pfm-tile:nth-child(3n) { background: var(--pf-bg2); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--pf-fg) 12%, transparent); }
     963
     964/* Business */
     965.pfm-cover {
     966        display: flex;
     967        flex-direction: column;
     968        gap: 2.4cqw;
     969        margin: 0 -5cqw;
     970        padding: 0 5cqw 11cqw;
     971        color: var(--pf-bg);
     972        background:
     973                radial-gradient(80% 90% at 100% 100%, color-mix(in srgb, var(--pf-ac2) 70%, transparent), transparent 60%),
     974                linear-gradient(135deg, var(--pf-ac), color-mix(in srgb, var(--pf-ac) 55%, var(--pf-fg)));
     975}
     976
     977.pfm-cover .pfm-header { margin-bottom: 4cqw; }
     978.pfm-cover .pfm-kicker,
     979.pfm-cover .pfm-line,
     980.pfm-cover .pfm-btn:not(.is-ghost) { background: var(--pf-bg); }
     981.pfm-services { margin-top: -9cqw; }
     982.pfm-services .pfm-card { background: var(--pf-bg); box-shadow: 0 2cqw 5cqw -2cqw rgba(0, 0, 0, 0.25); }
     983
     984.pfm-icon {
     985        width: 6cqw;
     986        height: 6cqw;
     987        border-radius: 30%;
     988        background: var(--pf-ac);
     989        box-shadow: 0 0 0 1.4cqw color-mix(in srgb, var(--pf-ac) 18%, var(--pf-bg));
     990        margin: 1.4cqw;
     991}
     992
     993.pfm-pricing .pfm-card { min-height: 34cqw; }
     994.pfm-pricing .is-featured { background: var(--pf-fg); color: var(--pf-bg); }
     995.pfm-pricing .is-featured .pfm-line { background: var(--pf-bg); }
     996
     997.pfm-price {
     998        display: block;
     999        width: 50%;
     1000        height: 4.4cqw;
     1001        border-radius: 1cqw;
     1002        background: currentColor;
     1003}
     1004
     1005/* ---------- Card body ---------- */
     1006.postfolio-starter-footer {
     1007        display: flex;
     1008        flex: 1;
     1009        flex-direction: column;
     1010        gap: 12px;
     1011        padding: 18px 20px 20px;
     1012}
     1013
     1014.postfolio-starter-head {
     1015        display: flex;
     1016        align-items: center;
     1017        justify-content: space-between;
     1018        gap: 12px;
     1019}
     1020
     1021.postfolio-starter-title {
     1022        margin: 0;
     1023        font-size: 16px;
     1024        font-weight: 600;
     1025        color: #0f172a;
     1026}
     1027
     1028.postfolio-starter-status {
     1029        display: inline-flex;
     1030        align-items: center;
     1031        padding: 2px 8px 2px 4px;
     1032        border-radius: 999px;
     1033        background: #dcfce7;
     1034        color: #166534;
     1035        font-size: 11px;
     1036        font-weight: 600;
     1037        white-space: nowrap;
     1038}
     1039
     1040.postfolio-starter-status .dashicons {
     1041        width: 16px;
     1042        height: 16px;
     1043        font-size: 16px;
     1044}
     1045
     1046.postfolio-starter-desc {
     1047        margin: 0;
     1048        font-size: 13px;
     1049        line-height: 1.55;
     1050        color: #64748b;
     1051}
     1052
     1053.postfolio-starter-meta {
     1054        display: grid;
     1055        gap: 8px;
     1056        margin: 0;
     1057        padding: 12px 0 0;
     1058        border-top: 1px dashed #e2e8f0;
     1059        font-size: 12px;
     1060}
     1061
     1062.postfolio-starter-meta > div {
     1063        display: grid;
     1064        grid-template-columns: 48px 1fr;
     1065        align-items: center;
     1066        gap: 8px;
     1067}
     1068
     1069.postfolio-starter-meta dt {
     1070        color: #94a3b8;
     1071        font-weight: 500;
     1072}
     1073
     1074.postfolio-starter-meta dd {
     1075        display: flex;
     1076        flex-wrap: wrap;
     1077        align-items: center;
     1078        gap: 6px;
     1079        margin: 0;
     1080        color: #334155;
     1081        font-weight: 600;
     1082}
     1083
     1084.postfolio-starter-swatches {
     1085        display: inline-flex;
     1086}
     1087
     1088.postfolio-starter-swatches i {
     1089        width: 14px;
     1090        height: 14px;
     1091        margin-right: -4px;
     1092        border-radius: 50%;
     1093        box-shadow: 0 0 0 2px #ffffff, inset 0 0 0 1px rgba(15, 23, 42, 0.12);
     1094}
     1095
     1096.postfolio-starter-swatches i:last-child {
     1097        margin-right: 4px;
     1098}
     1099
     1100.postfolio-starter-font {
     1101        font-size: 13px;
     1102}
     1103
     1104.postfolio-starter-font.is-heading {
     1105        font-family: var(--pf-hf);
     1106        font-weight: 700;
     1107}
     1108
     1109.postfolio-starter-font.is-body {
     1110        font-family: var(--pf-bf);
     1111        font-weight: 500;
     1112}
     1113
     1114.postfolio-starter-pages {
     1115        display: flex;
     1116        flex-wrap: wrap;
     1117        gap: 4px;
     1118        margin: 0;
     1119        padding: 0;
     1120        list-style: none;
     1121}
     1122
     1123.postfolio-starter-pages li {
     1124        margin: 0;
     1125        padding: 1px 7px;
     1126        border-radius: 5px;
     1127        background: #f1f5f9;
     1128        color: #475569;
     1129        font-weight: 500;
     1130}
     1131
     1132/* The button sits at the bottom so every card lines up. */
     1133.postfolio-starter-actions {
     1134        display: flex;
     1135        margin-top: auto;
     1136        padding-top: 4px;
     1137}
     1138
     1139.postfolio-starter-actions .postfolio-btn-import {
     1140        width: 100%;
     1141        justify-content: center;
     1142        gap: 6px;
     1143        padding: 9px 16px;
     1144        border-radius: 8px;
     1145        font-size: 13px;
     1146}
     1147
     1148.postfolio-starter-actions .postfolio-btn-import:focus-visible {
     1149        outline: 2px solid #2563eb;
     1150        outline-offset: 2px;
     1151}
     1152
     1153.postfolio-starter-card.is-imported .postfolio-btn-import {
     1154        background: #ffffff;
     1155        color: #1d4ed8;
     1156}
     1157
     1158.postfolio-starter-card.is-imported .postfolio-btn-import:hover {
     1159        background: #eff6ff;
     1160}
     1161
     1162/* ==========================================================================
     1163   Recommended plugins
     1164   ========================================================================== */
     1165.postfolio-plugin-grid {
     1166        display: grid;
     1167        grid-template-columns: repeat(auto-fill, minmax(min(100%, 380px), 1fr));
     1168        gap: 24px;
     1169        margin-top: 20px;
     1170}
     1171
     1172.postfolio-plugin-card {
     1173        display: flex;
     1174        flex-direction: column;
     1175        gap: 14px;
     1176        padding: 24px;
     1177        background: #ffffff;
     1178        border: 1px solid #e2e8f0;
     1179        border-radius: 14px;
     1180        box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04);
     1181        transition: box-shadow 0.25s ease, border-color 0.25s ease;
     1182}
     1183
     1184.postfolio-plugin-card:hover {
     1185        border-color: #c7d2fe;
     1186        box-shadow: 0 14px 34px -14px rgba(37, 99, 235, 0.35);
     1187}
     1188
     1189.postfolio-plugin-card.is-active {
     1190        border-color: #bbf7d0;
     1191}
     1192
     1193.postfolio-plugin-head {
     1194        display: flex;
     1195        align-items: center;
     1196        gap: 14px;
     1197}
     1198
     1199.postfolio-plugin-icon {
     1200        flex: none;
     1201        width: 56px;
     1202        height: 56px;
     1203}
     1204
     1205.postfolio-plugin-icon svg {
     1206        display: block;
     1207        width: 100%;
     1208        height: 100%;
     1209}
     1210
     1211.postfolio-plugin-head h3 {
     1212        margin: 0 0 2px;
     1213        font-size: 17px;
     1214        color: #0f172a;
     1215}
     1216
     1217.postfolio-plugin-tagline {
     1218        margin: 0;
     1219        color: #64748b;
     1220        font-size: 13px;
     1221}
     1222
     1223.postfolio-plugin-free {
     1224        margin-left: auto;
     1225        align-self: flex-start;
     1226        padding: 2px 10px;
     1227        border-radius: 999px;
     1228        background: #dcfce7;
     1229        color: #166534;
     1230        font-size: 11px;
     1231        font-weight: 700;
     1232        letter-spacing: 0.04em;
     1233        text-transform: uppercase;
     1234}
     1235
     1236.postfolio-plugin-desc {
     1237        margin: 0;
     1238        color: #334155;
     1239        font-size: 14px;
     1240        line-height: 1.6;
     1241}
     1242
     1243.postfolio-plugin-features {
     1244        display: grid;
     1245        grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
     1246        gap: 6px 16px;
     1247        margin: 0;
     1248        padding: 12px 0;
     1249        border-top: 1px dashed #e2e8f0;
     1250        border-bottom: 1px dashed #e2e8f0;
     1251}
     1252
     1253.postfolio-plugin-features li {
     1254        display: flex;
     1255        align-items: center;
     1256        gap: 4px;
     1257        margin: 0;
     1258        color: #334155;
     1259        font-size: 13px;
     1260}
     1261
     1262.postfolio-plugin-features .dashicons {
     1263        color: #16a34a;
     1264}
     1265
     1266.postfolio-plugin-bestfor {
     1267        margin: 0;
     1268        color: #64748b;
     1269        font-size: 13px;
     1270}
     1271
     1272.postfolio-plugin-bestfor strong {
     1273        color: #0f172a;
     1274}
     1275
     1276.postfolio-plugin-actions {
     1277        display: flex;
     1278        flex-wrap: wrap;
     1279        align-items: center;
     1280        gap: 8px;
     1281        margin-top: auto;
     1282}
     1283
     1284.postfolio-plugin-actions .button {
     1285        min-height: 36px;
     1286        padding: 0 16px;
     1287        line-height: 34px;
     1288        border-radius: 8px;
     1289}
     1290
     1291.postfolio-plugin-active {
     1292        display: inline-flex;
     1293        align-items: center;
     1294        gap: 4px;
     1295        padding: 6px 12px;
     1296        border-radius: 8px;
     1297        background: #dcfce7;
     1298        color: #166534;
     1299        font-weight: 600;
     1300}
     1301
     1302.postfolio-plugin-actions .button {
     1303        display: inline-flex;
     1304        align-items: center;
     1305        border: 1px solid #cbd5e1;
     1306        background: #ffffff;
     1307        color: #0f172a;
     1308        font-weight: 600;
     1309        text-decoration: none;
     1310}
     1311
     1312.postfolio-plugin-actions .button-primary {
     1313        border-color: #2563eb;
     1314        background: #2563eb;
     1315        color: #ffffff;
     1316}
     1317
     1318.postfolio-plugin-actions .button-primary:hover,
     1319.postfolio-plugin-actions .button-primary:focus {
     1320        border-color: #1d4ed8;
     1321        background: #1d4ed8;
     1322        color: #ffffff;
     1323}
     1324
     1325.postfolio-plugin-actions .button:focus-visible {
     1326        outline: 2px solid #2563eb;
     1327        outline-offset: 2px;
     1328}
  • postfolio-blocks/1.2.0/assets/css/custom.css

    r352228 r353530  
    396396}
    397397
     398/* ---------- Single post: centered header ---------- */
     399.postfolio-post-header {
     400        text-align: center;
     401}
     402
     403.postfolio-post-header > * {
     404        max-width: 100%;
     405}
     406
     407.postfolio-post-header .wp-block-post-title {
     408        text-wrap: balance;
     409}
     410
     411/* ---------- Single post: share card ---------- */
     412.postfolio-share-row {
     413        background: var(--wp--preset--color--base);
     414        box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04);
     415}
     416
     417.postfolio-share-row > p {
     418        margin: 0;
     419}
     420
     421.postfolio-share .wp-social-link {
     422        border-radius: 0.5rem;
     423        transition: transform 0.2s ease;
     424}
     425
     426.postfolio-share .wp-social-link:hover {
     427        transform: translateY(-2px);
     428}
     429
     430/* ---------- Single post: author box ---------- */
     431.postfolio-author-box {
     432        background: var(--wp--preset--color--base);
     433        box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04);
     434}
     435
     436.postfolio-author-ring {
     437        flex: none;
     438}
     439
     440.postfolio-author-ring img {
     441        padding: 3px;
     442        border: 2px solid var(--wp--preset--color--accent);
     443        background: var(--wp--preset--color--base);
     444}
     445
     446.postfolio-author-name {
     447        font-weight: 700;
     448        line-height: 1.2;
     449}
     450
     451.postfolio-author-name a {
     452        color: var(--wp--preset--color--accent);
     453        text-decoration: none;
     454}
     455
     456.postfolio-author-name a:hover {
     457        text-decoration: underline;
     458}
     459
     460.postfolio-author-bio {
     461        margin: 0;
     462        line-height: 1.7;
     463}
     464
     465@media (max-width: 600px) {
     466        .postfolio-author-box {
     467                flex-direction: column;
     468                align-items: flex-start !important;
     469        }
     470}
     471
     472/* ---------- Comment form: breathing room above the footer ---------- */
     473.wp-block-post-comments-form .form-submit {
     474        margin-bottom: 0;
     475}
     476
     477.postfolio-comments-area {
     478        padding-bottom: var(--wp--preset--spacing--40);
     479}
     480
     481/* ---------- Header search: never wider than the screen ---------- */
     482.postfolio-header .wp-block-search,
     483.postfolio-header .wp-block-search__inside-wrapper,
     484.postfolio-header .wp-block-search__input {
     485        min-width: 0;
     486        max-width: 100%;
     487}
     488
     489@media (max-width: 781px) {
     490        .postfolio-header .wp-block-search {
     491                flex: 1 0 100%;
     492                order: 3;
     493        }
     494
     495        .postfolio-header .wp-block-search__inside-wrapper {
     496                width: 100% !important;
     497        }
     498}
     499
     500/* ---------- Magazine home ---------- */
     501.postfolio-kicker {
     502        margin: 0;
     503        font-weight: 700;
     504        letter-spacing: 0.08em;
     505        text-transform: uppercase;
     506}
     507
     508.postfolio-kicker a {
     509        color: inherit;
     510        text-decoration: none;
     511}
     512
     513.postfolio-badge-accent {
     514        display: inline-flex;
     515        gap: 0.4em;
     516        margin: 0;
     517}
     518
     519.postfolio-badge-accent a {
     520        padding: 0.3em 0.85em;
     521        border-radius: 999px;
     522        background: var(--wp--preset--color--accent);
     523        color: var(--wp--preset--color--base);
     524        font-size: var(--wp--preset--font-size--small);
     525        font-weight: 700;
     526        letter-spacing: 0.06em;
     527        text-decoration: none;
     528        text-transform: uppercase;
     529}
     530
     531.postfolio-badge-accent .wp-block-post-terms__separator {
     532        display: none;
     533}
     534
     535/* Spotlight lead story: the whole card scales gently on hover. */
     536.postfolio-spotlight-primary {
     537        overflow: hidden;
     538}
     539
     540.postfolio-spotlight-primary .wp-block-cover__image-background {
     541        transition: transform 0.6s ease;
     542}
     543
     544.postfolio-spotlight-primary:hover .wp-block-cover__image-background {
     545        transform: scale(1.04);
     546}
     547
     548.postfolio-spotlight-primary .wp-block-cover__inner-container {
     549        max-width: 40rem;
     550}
     551
     552.postfolio-spotlight-excerpt {
     553        opacity: 0.85;
     554}
     555
     556.postfolio-spotlight-primary .wp-block-post-date,
     557.postfolio-spotlight-primary .wp-block-post-author-name {
     558        color: var(--wp--preset--color--base);
     559        opacity: 0.85;
     560}
     561
     562.postfolio-story-card .wp-block-post-featured-image,
     563.postfolio-dark-row .wp-block-post-featured-image,
     564.postfolio-row-item .wp-block-post-featured-image {
     565        flex: none;
     566        overflow: hidden;
     567}
     568
     569.postfolio-story-card .wp-block-post-featured-image img {
     570        transition: transform 0.5s ease;
     571}
     572
     573.postfolio-story-card:hover .wp-block-post-featured-image img {
     574        transform: scale(1.04);
     575}
     576
     577.postfolio-story-card .wp-block-post-title a,
     578.postfolio-dark-row .wp-block-post-title a,
     579.postfolio-row-item .wp-block-post-title a {
     580        color: inherit;
     581        text-decoration: none;
     582}
     583
     584.postfolio-story-card .wp-block-post-title a:hover,
     585.postfolio-dark-row .wp-block-post-title a:hover,
     586.postfolio-row-item .wp-block-post-title a:hover {
     587        text-decoration: underline;
     588        text-decoration-thickness: 2px;
     589        text-underline-offset: 0.15em;
     590}
     591
     592.postfolio-dark-row:last-child {
     593        margin-bottom: 0 !important;
     594        border-bottom: 0 !important;
     595}
     596
     597.postfolio-more-link {
     598        margin: 0;
     599        font-weight: 600;
     600        white-space: nowrap;
     601}
     602
     603.postfolio-more-link a {
     604        text-decoration: none;
     605}
     606
     607.postfolio-topic-pills .wp-block-button__link {
     608        padding: 0.4em 1.1em;
     609}
     610
     611/* ---------- Personal blog home ---------- */
     612.postfolio-blog-hero-image img {
     613        box-shadow: 0 24px 48px -20px rgba(15, 23, 42, 0.35);
     614}
     615
     616.postfolio-feature-card .wp-block-columns {
     617        margin-bottom: 0;
     618}
     619
     620.postfolio-list-card {
     621        height: 100%;
     622}
     623
     624.postfolio-list-card .wp-block-post-excerpt__excerpt {
     625        margin: 0;
     626}
     627
     628/* ---------- Editorial home ---------- */
     629.postfolio-topic-nav .wp-block-navigation-item__content {
     630        font-weight: 600;
     631        text-transform: uppercase;
     632        letter-spacing: 0.06em;
     633}
     634
     635.postfolio-live-dot {
     636        display: inline-flex;
     637        align-items: center;
     638        gap: 0.4em;
     639        margin: 0;
     640}
     641
     642.postfolio-live-dot::before {
     643        content: "";
     644        width: 0.5em;
     645        height: 0.5em;
     646        border-radius: 50%;
     647        background: currentColor;
     648        box-shadow: 0 0 0 0.25em color-mix(in srgb, currentColor 25%, transparent);
     649}
     650
     651.postfolio-headline-item .wp-block-post-title a,
     652.postfolio-numbered-item .wp-block-post-title a {
     653        color: inherit;
     654        text-decoration: none;
     655}
     656
     657.postfolio-headline-item .wp-block-post-title a:hover,
     658.postfolio-numbered-item .wp-block-post-title a:hover {
     659        color: var(--wp--preset--color--accent);
     660}
     661
     662.postfolio-news-row > .wp-block-group {
     663        flex: 1;
     664}
     665
     666.postfolio-news-row .wp-block-post-excerpt__excerpt {
     667        margin: 0;
     668}
     669
     670.postfolio-sticky-sidebar {
     671        position: sticky;
     672        top: 6rem;
     673}
     674
     675/* Numbered "most discussed" list. */
     676.postfolio-numbered .wp-block-post-template {
     677        counter-reset: postfolio-rank;
     678}
     679
     680.postfolio-numbered-item {
     681        position: relative;
     682        padding-left: 2.6rem !important;
     683        counter-increment: postfolio-rank;
     684}
     685
     686.postfolio-numbered-item::before {
     687        content: counter(postfolio-rank, decimal-leading-zero);
     688        position: absolute;
     689        top: 0.85rem;
     690        left: 0;
     691        color: var(--wp--preset--color--accent);
     692        font-family: var(--wp--preset--font-family--poppins, inherit);
     693        font-size: 1.35rem;
     694        font-weight: 700;
     695        line-height: 1;
     696}
     697
     698.postfolio-numbered-item:last-child,
     699.postfolio-headline-item:last-child {
     700        border-bottom: 0 !important;
     701}
     702
     703.postfolio-comment-count {
     704        margin: 0;
     705}
     706
     707.postfolio-topic-list {
     708        margin: 0;
     709        padding: 0;
     710        list-style: none;
     711}
     712
     713.postfolio-topic-list li {
     714        display: flex;
     715        justify-content: space-between;
     716        padding: 0.55rem 0;
     717        border-bottom: 1px solid var(--wp--preset--color--base-2);
     718        color: var(--wp--preset--color--contrast-2);
     719}
     720
     721.postfolio-topic-list li a {
     722        color: var(--wp--preset--color--contrast);
     723        font-weight: 600;
     724        text-decoration: none;
     725}
     726
     727.postfolio-topic-list li a:hover {
     728        color: var(--wp--preset--color--accent);
     729}
     730
     731@media (max-width: 781px) {
     732        .postfolio-sticky-sidebar {
     733                position: static;
     734        }
     735
     736        .postfolio-list-card .wp-block-post-featured-image {
     737                width: 112px !important;
     738                height: 96px !important;
     739        }
     740
     741        .postfolio-news-row .wp-block-post-featured-image {
     742                width: 112px !important;
     743                height: 84px !important;
     744        }
     745
     746        .postfolio-news-row .wp-block-post-excerpt {
     747                display: none;
     748        }
     749}
     750
     751@media (max-width: 781px) {
     752        .postfolio-spotlight-primary {
     753                min-height: 420px !important;
     754        }
     755
     756        .postfolio-dark-row .wp-block-post-featured-image {
     757                width: 104px !important;
     758                height: 80px !important;
     759        }
     760}
     761
     762/* ---------- Agency landing ---------- */
     763.postfolio-agency-hero {
     764        position: relative;
     765        overflow: hidden;
     766        background-image:
     767                radial-gradient(60% 70% at 85% 20%, color-mix(in srgb, var(--wp--preset--color--accent) 45%, transparent), transparent 70%),
     768                radial-gradient(45% 60% at 0% 100%, color-mix(in srgb, var(--wp--preset--color--accent-2) 30%, transparent), transparent 70%);
     769}
     770
     771.postfolio-hero-pill {
     772        display: inline-flex;
     773        align-self: flex-start;
     774        padding: 0.4em 1em;
     775        border: 1px solid color-mix(in srgb, currentColor 30%, transparent);
     776        border-radius: 999px;
     777        font-weight: 600;
     778        letter-spacing: 0.06em;
     779        text-transform: uppercase;
     780}
     781
     782.postfolio-avatar-stack figure {
     783        margin: 0 0 0 -10px !important;
     784}
     785
     786.postfolio-avatar-stack figure:first-child {
     787        margin-left: 0 !important;
     788}
     789
     790.postfolio-avatar-stack img {
     791        border: 2px solid var(--wp--preset--color--contrast);
     792}
     793
     794.postfolio-stars {
     795        color: #f5b400;
     796        letter-spacing: 0.1em;
     797}
     798
     799.postfolio-hero-visual {
     800        position: relative;
     801}
     802
     803.postfolio-hero-visual .wp-block-image img {
     804        box-shadow: 0 40px 80px -30px rgba(0, 0, 0, 0.6);
     805}
     806
     807.postfolio-hero-float {
     808        position: absolute;
     809        bottom: 2rem;
     810        left: -2rem;
     811        box-shadow: var(--wp--preset--shadow--elevated);
     812}
     813
     814.postfolio-hero-float p {
     815        margin: 0;
     816}
     817
     818.postfolio-service-card {
     819        transition: border-color 0.25s ease, box-shadow 0.25s ease, transform 0.25s ease;
     820}
     821
     822.postfolio-service-card:hover {
     823        border-color: var(--wp--preset--color--accent) !important;
     824        box-shadow: var(--wp--preset--shadow--card);
     825        transform: translateY(-4px);
     826}
     827
     828.postfolio-service-icon {
     829        display: inline-flex;
     830        align-items: center;
     831        justify-content: center;
     832        width: 3rem;
     833        height: 3rem;
     834        border-radius: 0.9rem;
     835        background: color-mix(in srgb, var(--wp--preset--color--accent) 14%, var(--wp--preset--color--base));
     836        color: var(--wp--preset--color--accent);
     837        font-weight: 800;
     838}
     839
     840.postfolio-work-card .wp-block-image {
     841        overflow: hidden;
     842        border-radius: 1.25rem;
     843}
     844
     845.postfolio-work-card .wp-block-image img {
     846        transition: transform 0.5s ease;
     847}
     848
     849.postfolio-work-card:hover .wp-block-image img {
     850        transform: scale(1.04);
     851}
     852
     853.postfolio-work-card h3,
     854.postfolio-work-card p {
     855        margin: 0;
     856}
     857
     858.postfolio-result-pill {
     859        padding: 0.25em 0.8em;
     860        border-radius: 999px;
     861        background: var(--wp--preset--color--base);
     862        color: var(--wp--preset--color--accent);
     863        font-weight: 700;
     864}
     865
     866/* Process: numbered steps joined by a line on wide screens. */
     867.postfolio-step {
     868        position: relative;
     869        padding-top: 1rem;
     870}
     871
     872.postfolio-step__number {
     873        position: relative;
     874        z-index: 1;
     875        display: inline-flex;
     876        align-items: center;
     877        justify-content: center;
     878        width: 3.25rem;
     879        height: 3.25rem;
     880        margin-bottom: 0.75rem !important;
     881        border: 2px solid var(--wp--preset--color--accent);
     882        border-radius: 50%;
     883        background: var(--wp--preset--color--base);
     884        color: var(--wp--preset--color--accent);
     885        font-weight: 800;
     886}
     887
     888@media (min-width: 900px) {
     889        .postfolio-step:not(:last-child)::after {
     890                content: "";
     891                position: absolute;
     892                top: calc(1rem + 1.625rem);
     893                left: 3.5rem;
     894                right: -1rem;
     895                height: 2px;
     896                background: linear-gradient(90deg, var(--wp--preset--color--accent), color-mix(in srgb, var(--wp--preset--color--accent) 15%, transparent));
     897        }
     898}
     899
     900/* Pricing: equal-height cards, the featured plan lifted. */
     901.postfolio-pricing {
     902        align-items: stretch;
     903}
     904
     905.postfolio-plan {
     906        height: 100%;
     907}
     908
     909.postfolio-plan.is-featured {
     910        box-shadow: var(--wp--preset--shadow--elevated);
     911}
     912
     913/* Headings default to the contrast color, which is this card's background. */
     914.postfolio-plan.is-featured :is(h1, h2, h3, h4) {
     915        color: inherit;
     916}
     917
     918.postfolio-trust p,
     919.postfolio-hero-pill {
     920        margin: 0;
     921}
     922
     923@media (min-width: 900px) {
     924        .postfolio-plan.is-featured {
     925                transform: scale(1.04);
     926        }
     927}
     928
     929.postfolio-plan__badge {
     930        padding: 0.2em 0.75em;
     931        border-radius: 999px;
     932        background: var(--wp--preset--color--accent);
     933        color: var(--wp--preset--color--base);
     934        font-weight: 700;
     935}
     936
     937.postfolio-plan__price strong {
     938        font-size: clamp(2.2rem, 1.8rem + 1.2vw, 2.8rem);
     939        font-weight: 800;
     940        letter-spacing: -0.02em;
     941}
     942
     943.postfolio-plan__price span {
     944        opacity: 0.72;
     945}
     946
     947.postfolio-checklist {
     948        flex: 1;
     949        margin: 0;
     950        padding: 1rem 0 0;
     951        border-top: 1px solid color-mix(in srgb, currentColor 15%, transparent);
     952        list-style: none;
     953}
     954
     955.postfolio-checklist li {
     956        position: relative;
     957        padding: 0.4rem 0 0.4rem 1.75rem;
     958}
     959
     960.postfolio-checklist li::before {
     961        content: "";
     962        position: absolute;
     963        top: 0.75rem;
     964        left: 0;
     965        width: 1.1rem;
     966        height: 1.1rem;
     967        border-radius: 50%;
     968        background: color-mix(in srgb, var(--wp--preset--color--accent) 18%, transparent) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M4 8.5l2.5 2.5L12 5.5' fill='none' stroke='%23888' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / 0.8rem no-repeat;
     969}
     970
     971.postfolio-plan.is-featured .postfolio-checklist li::before {
     972        background-color: var(--wp--preset--color--accent);
     973}
     974
     975.postfolio-plan__cta {
     976        width: 100%;
     977}
     978
     979@media (max-width: 781px) {
     980        .postfolio-agency-hero {
     981                padding-top: 8rem !important;
     982        }
     983
     984        .postfolio-hero-float {
     985                left: 1rem;
     986                bottom: 1rem;
     987        }
     988
     989        .postfolio-hero-visual .wp-block-image img {
     990                aspect-ratio: 4 / 3 !important;
     991        }
     992}
     993
     994@media (prefers-reduced-motion: reduce) {
     995        .postfolio-service-card,
     996        .postfolio-work-card .wp-block-image img {
     997                transition: none;
     998                transform: none !important;
     999        }
     1000}
     1001
     1002/* ---------- Portfolio ---------- */
     1003.postfolio-availability {
     1004        display: inline-flex;
     1005        align-items: center;
     1006        align-self: flex-start;
     1007        gap: 0.55em;
     1008        margin: 0;
     1009        padding: 0.35em 0.95em 0.35em 0.8em;
     1010        border: 1px solid color-mix(in srgb, currentColor 20%, transparent);
     1011        border-radius: 999px;
     1012        font-weight: 600;
     1013}
     1014
     1015.postfolio-availability::before {
     1016        content: "";
     1017        width: 0.55em;
     1018        height: 0.55em;
     1019        border-radius: 50%;
     1020        background: #16a34a;
     1021        box-shadow: 0 0 0 0.25em rgba(22, 163, 74, 0.2);
     1022}
     1023
     1024.postfolio-hero-stats p {
     1025        margin: 0;
     1026        color: var(--wp--preset--color--contrast-2);
     1027}
     1028
     1029.postfolio-hero-stats strong {
     1030        display: block;
     1031        color: var(--wp--preset--color--contrast);
     1032        font-size: clamp(1.6rem, 1.3rem + 1vw, 2.1rem);
     1033        line-height: 1.1;
     1034}
     1035
     1036.postfolio-tag-row {
     1037        display: flex;
     1038        flex-wrap: wrap;
     1039        gap: 0.4rem;
     1040}
     1041
     1042.postfolio-tag-row a {
     1043        padding: 0.2em 0.75em;
     1044        border: 1px solid color-mix(in srgb, var(--wp--preset--color--contrast) 18%, transparent);
     1045        border-radius: 999px;
     1046        color: var(--wp--preset--color--contrast-2);
     1047        text-decoration: none;
     1048}
     1049
     1050.postfolio-tag-row a:hover {
     1051        border-color: var(--wp--preset--color--accent);
     1052        color: var(--wp--preset--color--accent);
     1053}
     1054
     1055.postfolio-tag-row .wp-block-post-terms__separator {
     1056        display: none;
     1057}
     1058
     1059.postfolio-work-card .wp-block-post-featured-image {
     1060        overflow: hidden;
     1061}
     1062
     1063.postfolio-work-card .wp-block-post-featured-image img {
     1064        transition: transform 0.5s ease;
     1065}
     1066
     1067.postfolio-work-card:hover .wp-block-post-featured-image img {
     1068        transform: scale(1.04);
     1069}
     1070
     1071.postfolio-work-card .wp-block-post-title a {
     1072        color: inherit;
     1073        text-decoration: none;
     1074}
     1075
     1076.postfolio-work-card .wp-block-post-title a:hover {
     1077        color: var(--wp--preset--color--accent);
     1078}
     1079
     1080.postfolio-lede {
     1081        max-width: 42rem;
     1082}
     1083
     1084.postfolio-experience-row p {
     1085        margin: 0;
     1086}
     1087
     1088@media (prefers-reduced-motion: reduce) {
     1089        .postfolio-work-card .wp-block-post-featured-image img {
     1090                transition: none;
     1091                transform: none !important;
     1092        }
     1093}
     1094
     1095/* Secondary text that must work on any background, light or dark. */
     1096.postfolio-muted {
     1097        opacity: 0.72;
     1098}
     1099
     1100/* ---------- Breaking news ticker ---------- */
     1101.postfolio-ticker {
     1102        position: relative;
     1103        overflow: hidden;
     1104        min-height: 2.75rem;
     1105}
     1106
     1107.postfolio-ticker__label {
     1108        position: relative;
     1109        z-index: 2;
     1110        flex: none;
     1111        align-self: stretch;
     1112        display: flex;
     1113        align-items: center;
     1114        gap: 0.5em;
     1115        margin: 0;
     1116        padding: 0 1.1rem;
     1117        font-weight: 700;
     1118        letter-spacing: 0.08em;
     1119        text-transform: uppercase;
     1120}
     1121
     1122.postfolio-ticker__label::before {
     1123        content: "";
     1124        width: 0.5em;
     1125        height: 0.5em;
     1126        border-radius: 50%;
     1127        background: currentColor;
     1128        animation: postfolio-pulse 1.6s ease-in-out infinite;
     1129}
     1130
     1131.postfolio-ticker__track {
     1132        flex: 1;
     1133        min-width: 0;
     1134        overflow: hidden;
     1135        -webkit-mask-image: linear-gradient(90deg, transparent, #000 2rem, #000 calc(100% - 3rem), transparent);
     1136        mask-image: linear-gradient(90deg, transparent, #000 2rem, #000 calc(100% - 3rem), transparent);
     1137}
     1138
     1139.postfolio-ticker .wp-block-post-template {
     1140        display: flex;
     1141        flex-wrap: nowrap;
     1142        width: max-content;
     1143        margin: 0;
     1144        padding: 0;
     1145        list-style: none;
     1146}
     1147
     1148.postfolio-ticker .wp-block-post-template > li {
     1149        display: flex;
     1150        align-items: center;
     1151        margin: 0;
     1152        padding: 0.7rem 1.5rem;
     1153        white-space: nowrap;
     1154}
     1155
     1156.postfolio-ticker .wp-block-post-template > li::after {
     1157        content: "";
     1158        width: 0.35rem;
     1159        height: 0.35rem;
     1160        margin-left: 3rem;
     1161        border-radius: 50%;
     1162        background: var(--wp--preset--color--accent);
     1163}
     1164
     1165.postfolio-ticker .wp-block-post-title {
     1166        margin: 0;
     1167        color: inherit; /* headings default to "contrast", which matches the bar */
     1168        font-weight: 600;
     1169        line-height: 1.3;
     1170}
     1171
     1172.postfolio-ticker .wp-block-post-title a {
     1173        color: inherit;
     1174        text-decoration: none;
     1175}
     1176
     1177.postfolio-ticker .wp-block-post-title a:hover,
     1178.postfolio-ticker .wp-block-post-title a:focus-visible {
     1179        text-decoration: underline;
     1180}
     1181
     1182.postfolio-ticker.is-ready .wp-block-post-template {
     1183        animation: postfolio-ticker var(--postfolio-ticker-duration, 40s) linear infinite;
     1184}
     1185
     1186.postfolio-ticker.is-ready:hover .wp-block-post-template,
     1187.postfolio-ticker.is-ready:focus-within .wp-block-post-template,
     1188.postfolio-ticker.is-paused .wp-block-post-template {
     1189        animation-play-state: paused;
     1190}
     1191
     1192.postfolio-ticker__toggle {
     1193        position: relative;
     1194        z-index: 2;
     1195        flex: none;
     1196        width: 2.75rem;
     1197        align-self: stretch;
     1198        border: 0;
     1199        border-left: 1px solid color-mix(in srgb, currentColor 20%, transparent);
     1200        background: transparent;
     1201        color: inherit;
     1202        cursor: pointer;
     1203}
     1204
     1205.postfolio-ticker__toggle span {
     1206        display: block;
     1207        width: 10px;
     1208        height: 12px;
     1209        margin: auto;
     1210        border-left: 3px solid currentColor;
     1211        border-right: 3px solid currentColor;
     1212}
     1213
     1214.postfolio-ticker__toggle[aria-pressed="true"] span {
     1215        width: 0;
     1216        height: 0;
     1217        border-top: 6px solid transparent;
     1218        border-bottom: 6px solid transparent;
     1219        border-left: 10px solid currentColor;
     1220        border-right: 0;
     1221}
     1222
     1223.postfolio-ticker__toggle:focus-visible {
     1224        outline: 2px solid var(--wp--preset--color--accent);
     1225        outline-offset: -4px;
     1226}
     1227
     1228@keyframes postfolio-ticker {
     1229        to {
     1230                transform: translateX(-50%);
     1231        }
     1232}
     1233
     1234@keyframes postfolio-pulse {
     1235        50% {
     1236                opacity: 0.35;
     1237        }
     1238}
     1239
     1240/* ---------- News top bar ---------- */
     1241.postfolio-top-bar p {
     1242        margin: 0;
     1243}
     1244
     1245.postfolio-top-bar__date {
     1246        font-weight: 600;
     1247}
     1248
     1249.postfolio-trending-tags {
     1250        display: flex;
     1251        flex-wrap: wrap;
     1252        gap: 0.25rem 1rem;
     1253        margin: 0;
     1254}
     1255
     1256.postfolio-trending-tags a {
     1257        color: var(--wp--preset--color--contrast);
     1258        text-decoration: none;
     1259        white-space: nowrap;
     1260}
     1261
     1262.postfolio-trending-tags a::before {
     1263        content: "#";
     1264        color: var(--wp--preset--color--accent);
     1265}
     1266
     1267.postfolio-trending-tags a:hover {
     1268        color: var(--wp--preset--color--accent);
     1269}
     1270
     1271.postfolio-top-bar__toggle .wp-block-button__link {
     1272        display: inline-flex;
     1273        align-items: center;
     1274        gap: 0.4em;
     1275        padding: 0.3em 0.9em;
     1276        border: 1px solid color-mix(in srgb, var(--wp--preset--color--contrast) 25%, transparent);
     1277        background: transparent;
     1278        color: var(--wp--preset--color--contrast);
     1279}
     1280
     1281.postfolio-top-bar__toggle .wp-block-button__link::before {
     1282        content: "\263E";
     1283}
     1284
     1285.postfolio-is-dark .postfolio-top-bar__toggle .wp-block-button__link::before {
     1286        content: "\2600";
     1287}
     1288
     1289/* The switch only works when the Dark mode module is on. */
     1290body:not(.postfolio-has-dark-mode) .wp-block-button.is-style-theme-toggle {
     1291        display: none;
     1292}
     1293
     1294@media (max-width: 781px) {
     1295        .postfolio-top-bar__trending,
     1296        .postfolio-top-bar__social {
     1297                display: none !important;
     1298        }
     1299}
     1300
     1301/* ---------- Ad slots: space is reserved so the page never jumps ---------- */
     1302.postfolio-ad {
     1303        margin-left: auto;
     1304        margin-right: auto;
     1305}
     1306
     1307.postfolio-ad__label {
     1308        margin: 0;
     1309        color: var(--wp--preset--color--contrast-2);
     1310        font-size: 0.6875rem;
     1311        letter-spacing: 0.12em;
     1312        text-align: center;
     1313        text-transform: uppercase;
     1314}
     1315
     1316.postfolio-ad__slot {
     1317        width: 100%;
     1318        overflow: hidden;
     1319        border: 1px dashed color-mix(in srgb, var(--wp--preset--color--contrast) 25%, transparent);
     1320        border-radius: 0.5rem;
     1321        background: var(--wp--preset--color--base-2);
     1322}
     1323
     1324/* Once real ad code is inside, drop the placeholder look. */
     1325.postfolio-ad__slot:has(iframe, ins, script, img) {
     1326        border: 0;
     1327        background: transparent;
     1328}
     1329
     1330.postfolio-ad__size {
     1331        margin: 0;
     1332        color: var(--wp--preset--color--contrast-2);
     1333        font-size: var(--wp--preset--font-size--small);
     1334}
     1335
     1336.postfolio-ad--leaderboard .postfolio-ad__slot {
     1337        max-width: 728px;
     1338        min-height: 90px;
     1339}
     1340
     1341.postfolio-ad--rectangle .postfolio-ad__slot {
     1342        max-width: 300px;
     1343        min-height: 250px;
     1344}
     1345
     1346.postfolio-ad--in-article {
     1347        padding: 1rem 0;
     1348        border-top: 1px solid var(--wp--preset--color--base-2);
     1349        border-bottom: 1px solid var(--wp--preset--color--base-2);
     1350}
     1351
     1352.postfolio-ad--in-article .postfolio-ad__slot {
     1353        min-height: 250px;
     1354}
     1355
     1356@media (max-width: 781px) {
     1357        .postfolio-ad--leaderboard .postfolio-ad__slot {
     1358                max-width: 320px;
     1359                min-height: 100px;
     1360        }
     1361}
     1362
     1363/* ---------- Live blog ---------- */
     1364.postfolio-live__badge {
     1365        display: inline-flex;
     1366        align-items: center;
     1367        gap: 0.45em;
     1368        margin: 0;
     1369        padding: 0.25em 0.75em;
     1370        border-radius: 999px;
     1371        background: #dc2626;
     1372        color: #fff;
     1373        font-size: var(--wp--preset--font-size--small);
     1374        font-weight: 700;
     1375        letter-spacing: 0.08em;
     1376        text-transform: uppercase;
     1377}
     1378
     1379.postfolio-live__badge::before {
     1380        content: "";
     1381        width: 0.5em;
     1382        height: 0.5em;
     1383        border-radius: 50%;
     1384        background: currentColor;
     1385        animation: postfolio-pulse 1.4s ease-in-out infinite;
     1386}
     1387
     1388.postfolio-live__summary ul {
     1389        margin: 0;
     1390        padding-left: 1.2em;
     1391}
     1392
     1393.postfolio-live__timeline {
     1394        position: relative;
     1395        padding-left: 2rem;
     1396}
     1397
     1398.postfolio-live__timeline::before {
     1399        content: "";
     1400        position: absolute;
     1401        top: 0.5rem;
     1402        bottom: 0.5rem;
     1403        left: 0.45rem;
     1404        width: 2px;
     1405        background: var(--wp--preset--color--base-2);
     1406}
     1407
     1408.postfolio-live__entry {
     1409        position: relative;
     1410        padding-bottom: var(--wp--preset--spacing--30);
     1411}
     1412
     1413.postfolio-live__entry + .postfolio-live__entry {
     1414        margin-top: 0;
     1415        padding-top: var(--wp--preset--spacing--30);
     1416        border-top: 1px solid var(--wp--preset--color--base-2);
     1417}
     1418
     1419.postfolio-live__entry::before {
     1420        content: "";
     1421        position: absolute;
     1422        top: 0.35rem;
     1423        left: -1.95rem;
     1424        width: 0.85rem;
     1425        height: 0.85rem;
     1426        border: 3px solid var(--wp--preset--color--base);
     1427        border-radius: 50%;
     1428        background: var(--wp--preset--color--accent);
     1429        box-shadow: 0 0 0 1px var(--wp--preset--color--accent);
     1430}
     1431
     1432.postfolio-live__entry + .postfolio-live__entry::before {
     1433        top: calc(var(--wp--preset--spacing--30) + 0.35rem);
     1434}
     1435
     1436.postfolio-live__entry.is-pinned::before {
     1437        box-shadow: 0 0 0 1px var(--wp--preset--color--accent), 0 0 0 6px color-mix(in srgb, var(--wp--preset--color--accent) 25%, transparent);
     1438}
     1439
     1440.postfolio-live__time {
     1441        margin: 0;
     1442        font-weight: 700;
     1443        font-variant-numeric: tabular-nums;
     1444}
     1445
     1446/* ---------- Category archive ---------- */
     1447.postfolio-subcategories {
     1448        display: flex;
     1449        flex-wrap: wrap;
     1450        align-items: center;
     1451        gap: 0.6rem 1rem;
     1452        margin-top: 0.5rem;
     1453}
     1454
     1455.postfolio-subcategories ul {
     1456        display: flex;
     1457        flex-wrap: wrap;
     1458        gap: 0.5rem;
     1459        margin: 0;
     1460        padding: 0;
     1461        list-style: none;
     1462}
     1463
     1464.postfolio-subcategories a {
     1465        display: inline-flex;
     1466        gap: 0.4em;
     1467        padding: 0.35em 0.9em;
     1468        border: 1px solid color-mix(in srgb, var(--wp--preset--color--contrast) 20%, transparent);
     1469        border-radius: 999px;
     1470        color: var(--wp--preset--color--contrast);
     1471        font-size: var(--wp--preset--font-size--small);
     1472        font-weight: 600;
     1473        text-decoration: none;
     1474}
     1475
     1476.postfolio-subcategories a span {
     1477        color: var(--wp--preset--color--contrast-2);
     1478        font-weight: 400;
     1479}
     1480
     1481.postfolio-subcategories a:hover {
     1482        border-color: var(--wp--preset--color--accent);
     1483        color: var(--wp--preset--color--accent);
     1484}
     1485
     1486.postfolio-category-lead .wp-block-post-title a {
     1487        color: inherit;
     1488        text-decoration: none;
     1489}
     1490
     1491/* ---------- Post formats ---------- */
     1492.postfolio-format-badge {
     1493        display: inline-flex;
     1494        align-items: center;
     1495        gap: 0.45em;
     1496        margin: 0;
     1497        padding: 0.3em 0.9em;
     1498        border-radius: 999px;
     1499        background: var(--wp--preset--color--accent);
     1500        color: var(--wp--preset--color--base);
     1501        font-size: var(--wp--preset--font-size--small);
     1502        font-weight: 700;
     1503        letter-spacing: 0.08em;
     1504        text-transform: uppercase;
     1505}
     1506
     1507p.has-text-align-center.postfolio-format-badge {
     1508        display: table;
     1509        margin-left: auto;
     1510        margin-right: auto;
     1511}
     1512
     1513/* Video: the first video or embed fills the wide width of the dark stage. */
     1514.postfolio-format-video .wp-block-post-content > :is(.wp-block-video, .wp-block-embed):first-child {
     1515        max-width: var(--wp--style--global--wide-size);
     1516        margin-left: auto;
     1517        margin-right: auto;
     1518}
     1519
     1520.postfolio-format-video .wp-block-post-content > :is(.wp-block-video, .wp-block-embed):first-child :is(video, iframe) {
     1521        border-radius: 1rem;
     1522        box-shadow: 0 30px 60px -20px rgba(0, 0, 0, 0.6);
     1523}
     1524
     1525.postfolio-format-video .wp-block-post-terms a,
     1526.postfolio-format-video .wp-block-post-author-name a {
     1527        color: inherit;
     1528}
     1529
     1530/* Gallery: galleries and images break out to the wide width. */
     1531.postfolio-format-gallery .wp-block-post-content > :is(.wp-block-gallery, .wp-block-image) {
     1532        max-width: var(--wp--style--global--wide-size);
     1533        margin-left: auto;
     1534        margin-right: auto;
     1535}
     1536
     1537.postfolio-format-gallery .wp-block-gallery img {
     1538        border-radius: 0.75rem;
     1539}
     1540
     1541/* Quote: the quote is the hero. */
     1542.postfolio-format-quote .wp-block-quote {
     1543        position: relative;
     1544        margin: 0;
     1545        padding: 4.5rem 0 0;
     1546        border: 0;
     1547        text-align: center;
     1548}
     1549
     1550.postfolio-format-quote .wp-block-quote::before {
     1551        content: "\201C";
     1552        position: absolute;
     1553        top: 0;
     1554        left: 50%;
     1555        transform: translateX(-50%);
     1556        color: var(--wp--preset--color--accent);
     1557        font-family: Georgia, serif;
     1558        font-size: 6rem;
     1559        line-height: 1;
     1560}
     1561
     1562.postfolio-format-quote .wp-block-quote p {
     1563        font-family: var(--wp--preset--font-family--playfair-display, Georgia, serif);
     1564        font-size: clamp(1.6rem, 1.1rem + 2vw, 2.75rem);
     1565        font-style: italic;
     1566        line-height: 1.3;
     1567}
     1568
     1569.postfolio-format-quote .wp-block-quote cite {
     1570        display: block;
     1571        margin-top: 1rem;
     1572        color: var(--wp--preset--color--contrast-2);
     1573        font-style: normal;
     1574        font-weight: 600;
     1575}
     1576
     1577/* Audio: podcast-style cover art and a full-width player. */
     1578.postfolio-cover-art img {
     1579        box-shadow: 0 20px 40px -18px rgba(15, 23, 42, 0.45);
     1580}
     1581
     1582.postfolio-format-audio .wp-block-audio audio {
     1583        width: 100%;
     1584}
     1585
     1586.postfolio-format-audio .wp-block-audio {
     1587        padding: 1rem;
     1588        border: 1px solid var(--wp--preset--color--base-2);
     1589        border-radius: 999px;
     1590}
     1591
     1592/* ---------- Author archive hero ---------- */
     1593.postfolio-author-hero p {
     1594        margin: 0;
     1595}
     1596
     1597.postfolio-author-hero-avatar {
     1598        flex: none;
     1599}
     1600
     1601.postfolio-author-hero-stats {
     1602        display: flex;
     1603        flex-wrap: wrap;
     1604        gap: 0.4rem 1.25rem;
     1605        color: var(--wp--preset--color--contrast-2);
     1606}
     1607
     1608.postfolio-author-hero-stats strong {
     1609        color: var(--wp--preset--color--contrast);
     1610        font-size: 1.1em;
     1611}
     1612
     1613.postfolio-author-social .wp-social-link {
     1614        background: var(--wp--preset--color--contrast) !important;
     1615        color: var(--wp--preset--color--base) !important;
     1616}
     1617
     1618@media (max-width: 600px) {
     1619        .postfolio-author-hero__inner {
     1620                flex-direction: column;
     1621                align-items: flex-start !important;
     1622        }
     1623
     1624        .postfolio-author-hero-avatar img {
     1625                width: 96px !important;
     1626                height: 96px !important;
     1627        }
     1628}
     1629
     1630/* ---------- Case study ---------- */
     1631.postfolio-case-study__lede {
     1632        max-width: 46rem;
     1633}
     1634
     1635.postfolio-case-heading {
     1636        margin-top: var(--wp--preset--spacing--50) !important;
     1637}
     1638
     1639.postfolio-case-facts p {
     1640        margin: 0;
     1641}
     1642
     1643.postfolio-case-quote {
     1644        margin: var(--wp--preset--spacing--40) 0;
     1645        padding-left: 1.25rem;
     1646        border-left: 4px solid var(--wp--preset--color--accent);
     1647}
     1648
     1649.postfolio-case-quote p {
     1650        font-size: var(--wp--preset--font-size--x-large);
     1651        font-weight: 600;
     1652        line-height: 1.35;
     1653}
     1654
     1655.postfolio-case-quote cite {
     1656        color: var(--wp--preset--color--contrast-2);
     1657        font-style: normal;
     1658}
     1659
     1660.postfolio-next-project a {
     1661        color: inherit;
     1662        text-decoration: none;
     1663}
     1664
     1665.postfolio-next-project a:hover {
     1666        text-decoration: underline;
     1667}
     1668
     1669.postfolio-case-study__cta .postfolio-kicker {
     1670        opacity: 0.72;
     1671}
     1672
    3981673/* ---------- Reduced motion ---------- */
    3991674@media (prefers-reduced-motion: reduce) {
     1675        /* The ticker becomes a static list visitors can scroll sideways. */
     1676        .postfolio-ticker__track {
     1677                overflow-x: auto;
     1678                -webkit-mask-image: none;
     1679                mask-image: none;
     1680        }
     1681
     1682        .postfolio-ticker .wp-block-post-template,
     1683        .postfolio-ticker__label::before,
     1684        .postfolio-live__badge::before {
     1685                animation: none !important;
     1686        }
     1687
    4001688        .is-style-card,
    4011689        .is-style-card .wp-block-post-featured-image img,
     1690        .postfolio-spotlight-primary .wp-block-cover__image-background,
     1691        .postfolio-story-card .wp-block-post-featured-image img,
    4021692        .postfolio-row-item,
    4031693        .postfolio-logo-cloud img,
    … …  
    4161706}
    4171707
     1708.postfolio-meta-row > :first-child::before {
     1709        content: none !important;
     1710}
     1711
    4181712.postfolio-logo-cloud .wp-block-image img {
    4191713        width: 100%;
  • postfolio-blocks/1.2.0/assets/css/modules.css

    r352228 r353530  
    3333        background: var(--wp--preset--color--contrast, #101014);
    3434        color: var(--wp--preset--color--base, #fff);
    35         box-shadow: var(--wp--preset--shadow--elevated, 0 12px 24px rgba(0, 0, 0, 0.2));
     35        /* The thin ring keeps the button visible over a footer of the same color. */
     36        box-shadow: 0 0 0 1px color-mix(in srgb, var(--wp--preset--color--base, #fff) 22%, transparent), var(--wp--preset--shadow--elevated, 0 12px 24px rgba(0, 0, 0, 0.2));
    3637        cursor: pointer;
    3738        text-decoration: none;
    … …  
    146147/* ---------- Footer reveal ---------- */
    147148.postfolio-footer-reveal-ready .wp-site-blocks > :not(footer) {
     149        /* flow-root keeps the last section's bottom margin inside this painted
     150           area, so content never sits flush against the revealed footer. */
     151        display: flow-root;
    148152        position: relative;
    149153        z-index: 1;
  • postfolio-blocks/1.2.0/assets/js/admin-dashboard.js

    r352228 r353530  
    4848                } );
    4949
     50                // Recommended plugins: install with core's wp.updates, then activate,
     51                // all without leaving the page. Without JS the link opens core's installer.
     52                function markActive( $btn ) {
     53                        $btn.closest( '.postfolio-plugin-card' ).removeClass( 'is-install is-activate' ).addClass( 'is-active' );
     54                        $btn.replaceWith(
     55                                $( '<span class="postfolio-plugin-active">' )
     56                                        .append( '<span class="dashicons dashicons-yes-alt" aria-hidden="true"></span>' )
     57                                        .append( document.createTextNode( i18n.active || '' ) )
     58                        );
     59                }
     60
     61                function activate( $btn, url ) {
     62                        $btn.addClass( 'updating-message' ).text( i18n.activating || '…' );
     63                        $.get( url )
     64                                .done( function () {
     65                                        markActive( $btn );
     66                                } )
     67                                .fail( function () {
     68                                        window.location.href = url;
     69                                } );
     70                }
     71
     72                $( document ).on( 'click', '.postfolio-plugin-install', function ( e ) {
     73                        var $btn = $( this );
     74
     75                        if ( ! window.wp || ! window.wp.updates ) {
     76                                return; // Follow the link to core's install screen.
     77                        }
     78
     79                        e.preventDefault();
     80                        $btn.addClass( 'updating-message disabled' ).attr( 'aria-disabled', 'true' ).text( i18n.installing || '…' );
     81
     82                        window.wp.updates
     83                                .installPlugin( { slug: $btn.data( 'slug' ) } )
     84                                .done( function ( response ) {
     85                                        if ( response && response.activateUrl ) {
     86                                                activate( $btn, response.activateUrl );
     87                                        } else {
     88                                                markActive( $btn );
     89                                        }
     90                                } )
     91                                .fail( function () {
     92                                        $btn.removeClass( 'updating-message disabled' ).text( i18n.installFail || '' );
     93                                        window.location.href = $btn.attr( 'href' );
     94                                } );
     95                } );
     96
     97                // Activate links stay on this page too.
     98                $( document ).on( 'click', '.postfolio-plugin-card.is-activate .postfolio-plugin-btn', function ( e ) {
     99                        e.preventDefault();
     100                        activate( $( this ), $( this ).attr( 'href' ) );
     101                } );
     102
    50103                // AJAX starter site import.
    51104                $( document ).on( 'click', '.postfolio-btn-import', function ( e ) {
    … …  
    74127                                        demo_slug: demoSlug,
    75128                                        apply_style: $( '#postfolio-apply-style' ).is( ':checked' ) ? 1 : 0,
     129                                        demo_content: $( '#postfolio-demo-content' ).is( ':checked' ) ? 1 : 0,
    76130                                        security: vars.nonce,
    77131                                },
    … …  
    80134                                        if ( response && response.success ) {
    81135                                                $btn.prop( 'disabled', false ).text( i18n.imported || '' );
     136                                                $btn.closest( '.postfolio-starter-card' ).addClass( 'is-imported' );
    82137                                                $notice
    83138                                                        .addClass( 'success' )
  • postfolio-blocks/1.2.0/functions.php

    r352228 r353530  
    4444                wp_enqueue_style( 'postfolio-blocks-style', get_stylesheet_uri(), array(), $version );
    4545                wp_enqueue_style( 'postfolio-blocks-custom', get_theme_file_uri( 'assets/css/custom.css' ), array( 'postfolio-blocks-style' ), $version );
     46                wp_add_inline_style( 'postfolio-blocks-custom', postfolio_blocks_footer_palette_css() );
    4647        }
    4748}
    … …  
    8283                                'label'       => _x( 'Postfolio — Author & Contact', 'Block pattern category', 'postfolio-blocks' ),
    8384                                'description' => __( 'Author bio cards, social link profiles and contact blocks.', 'postfolio-blocks' ),
     85                        ),
     86                        'postfolio-blocks-news'         => array(
     87                                'label'       => _x( 'Postfolio — News & Ads', 'Block pattern category', 'postfolio-blocks' ),
     88                                'description' => __( 'Breaking news ticker, top bar, live blog and ad slots.', 'postfolio-blocks' ),
    8489                        ),
    8590                        'postfolio-blocks-pages'        => array(
    … …  
    165170require_once get_template_directory() . '/inc/modules.php';
    166171require_once get_template_directory() . '/inc/blog-features.php';
     172require_once get_template_directory() . '/inc/news-features.php';
     173require_once get_template_directory() . '/inc/demo-content.php';
    167174require_once get_template_directory() . '/inc/starter-sites.php';
     175require_once get_template_directory() . '/inc/recommended-plugins.php';
    168176require_once get_template_directory() . '/inc/admin-dashboard.php';
  • postfolio-blocks/1.2.0/inc/admin-dashboard.php

    r352228 r353530  
    6666                                'error'     => __( 'An unexpected server error occurred during import.', 'postfolio-blocks' ),
    6767                                'visit'     => __( 'View site', 'postfolio-blocks' ),
     68                                'installing'  => __( 'Installing…', 'postfolio-blocks' ),
     69                                'activating'  => __( 'Activating…', 'postfolio-blocks' ),
     70                                'active'      => __( 'Active', 'postfolio-blocks' ),
     71                                'installFail' => __( 'Could not install. Opening the WordPress installer…', 'postfolio-blocks' ),
    6872                        ),
    6973                )
    … …  
    134138
    135139/**
     140 * Render a decorative mini mockup of a starter site's homepage.
     141 *
     142 * The markup is plain divs painted with the site's own design tokens
     143 * (see postfolio_blocks_starter_site_tokens()), so no preview images ship
     144 * with the theme and the cards follow any palette or font change.
     145 *
     146 * @param string $layout Starter site layout key.
     147 * @param string $logo   Short brand name shown in the mock header.
     148 */
     149function postfolio_blocks_starter_mockup( $layout, $logo ) {
     150        $lines = function ( $widths, $class = '' ) {
     151                foreach ( $widths as $width ) {
     152                        printf( '<span class="pfm-line %1$s" style="width:%2$d%%"></span>', esc_attr( $class ), (int) $width );
     153                }
     154        };
     155        $card  = function ( $img = 'pfm-img' ) use ( $lines ) {
     156                echo '<div class="pfm-card"><span class="' . esc_attr( $img ) . '"></span><span class="pfm-tag"></span>';
     157                $lines( array( 92, 70 ), 'is-strong' );
     158                $lines( array( 55 ) );
     159                echo '</div>';
     160        };
     161        $header = function ( $class = '' ) use ( $logo ) {
     162                echo '<div class="pfm-header ' . esc_attr( $class ) . '"><b class="pfm-logo">' . esc_html( $logo ) . '</b><span class="pfm-nav"><i></i><i></i><i></i><i></i></span><span class="pfm-btn is-small"></span></div>';
     163        };
     164        ?>
     165        <div class="pfm-chrome"><i></i><i></i><i></i><span class="pfm-url"></span></div>
     166        <div class="pfm-screen">
     167                <div class="pfm-page pfm-<?php echo esc_attr( $layout ); ?>">
     168                        <?php if ( 'blog' === $layout ) : ?>
     169                                <?php $header(); ?>
     170                                <div class="pfm-hero">
     171                                        <span class="pfm-kicker"></span>
     172                                        <b class="pfm-title"><?php esc_html_e( 'Notes on design, code & life', 'postfolio-blocks' ); ?></b>
     173                                        <?php $lines( array( 74, 52 ) ); ?>
     174                                        <span class="pfm-btn"></span>
     175                                </div>
     176                                <div class="pfm-grid is-3"><?php $card(); $card(); $card(); ?></div>
     177                                <div class="pfm-grid is-3"><?php $card(); $card(); $card(); ?></div>
     178                                <div class="pfm-band"><b class="pfm-title is-sm"><?php esc_html_e( 'Join the newsletter', 'postfolio-blocks' ); ?></b><span class="pfm-input"></span></div>
     179
     180                        <?php elseif ( 'magazine' === $layout ) : ?>
     181                                <?php $header( 'is-ruled' ); ?>
     182                                <div class="pfm-feature">
     183                                        <div class="pfm-lead">
     184                                                <span class="pfm-img is-tall"></span>
     185                                                <span class="pfm-tag"></span>
     186                                                <b class="pfm-title is-md"><?php esc_html_e( 'The stories shaping this week', 'postfolio-blocks' ); ?></b>
     187                                                <?php $lines( array( 86, 60 ) ); ?>
     188                                        </div>
     189                                        <div class="pfm-side">
     190                                                <?php for ( $i = 0; $i < 3; $i++ ) : ?>
     191                                                        <div class="pfm-row"><span class="pfm-img is-thumb"></span><div><span class="pfm-tag"></span><?php $lines( array( 95, 70 ), 'is-strong' ); ?></div></div>
     192                                                <?php endfor; ?>
     193                                        </div>
     194                                </div>
     195                                <div class="pfm-label"></div>
     196                                <div class="pfm-grid is-4"><?php $card(); $card(); $card(); $card(); ?></div>
     197                                <div class="pfm-grid is-4"><?php $card(); $card(); $card(); $card(); ?></div>
     198
     199                        <?php elseif ( 'editorial' === $layout ) : ?>
     200                                <?php $header(); ?>
     201                                <div class="pfm-hero is-center">
     202                                        <span class="pfm-kicker"></span>
     203                                        <b class="pfm-title"><?php esc_html_e( 'The Daily Edition', 'postfolio-blocks' ); ?></b>
     204                                        <?php $lines( array( 60 ) ); ?>
     205                                </div>
     206                                <div class="pfm-list">
     207                                        <?php for ( $i = 0; $i < 6; $i++ ) : ?>
     208                                                <div class="pfm-row is-list"><div><span class="pfm-tag"></span><?php $lines( array( 88, 64 ), 'is-strong' ); ?><?php $lines( array( 40 ) ); ?></div><span class="pfm-img is-thumb"></span></div>
     209                                        <?php endfor; ?>
     210                                </div>
     211
     212                        <?php elseif ( 'portfolio' === $layout ) : ?>
     213                                <?php $header(); ?>
     214                                <div class="pfm-hero">
     215                                        <span class="pfm-kicker"></span>
     216                                        <b class="pfm-title is-lg"><?php esc_html_e( 'I design calm, useful', 'postfolio-blocks' ); ?> <em><?php esc_html_e( 'digital products.', 'postfolio-blocks' ); ?></em></b>
     217                                        <span class="pfm-actions"><span class="pfm-btn"></span><span class="pfm-btn is-ghost"></span></span>
     218                                </div>
     219                                <div class="pfm-grid is-3 pfm-projects">
     220                                        <?php for ( $i = 0; $i < 6; $i++ ) : ?>
     221                                                <span class="pfm-tile"></span>
     222                                        <?php endfor; ?>
     223                                </div>
     224                                <div class="pfm-band is-split"><b class="pfm-title is-sm"><?php esc_html_e( 'Let’s work together', 'postfolio-blocks' ); ?></b><span class="pfm-btn"></span></div>
     225
     226                        <?php else : ?>
     227                                <div class="pfm-cover">
     228                                        <?php $header( 'is-transparent' ); ?>
     229                                        <span class="pfm-kicker"></span>
     230                                        <b class="pfm-title"><?php esc_html_e( 'We help brands grow online', 'postfolio-blocks' ); ?></b>
     231                                        <?php $lines( array( 62 ) ); ?>
     232                                        <span class="pfm-actions"><span class="pfm-btn"></span><span class="pfm-btn is-ghost"></span></span>
     233                                </div>
     234                                <div class="pfm-grid is-3 pfm-services">
     235                                        <?php for ( $i = 0; $i < 3; $i++ ) : ?>
     236                                                <div class="pfm-card is-boxed"><span class="pfm-icon"></span><?php $lines( array( 70 ), 'is-strong' ); ?><?php $lines( array( 92, 80 ) ); ?></div>
     237                                        <?php endfor; ?>
     238                                </div>
     239                                <div class="pfm-grid is-3 pfm-pricing">
     240                                        <?php for ( $i = 0; $i < 3; $i++ ) : ?>
     241                                                <div class="pfm-card is-boxed<?php echo 1 === $i ? ' is-featured' : ''; ?>"><?php $lines( array( 40 ) ); ?><b class="pfm-price"></b><?php $lines( array( 80, 70, 75 ) ); ?><span class="pfm-btn is-block"></span></div>
     242                                        <?php endfor; ?>
     243                                </div>
     244                        <?php endif; ?>
     245                </div>
     246        </div>
     247        <?php
     248}
     249
     250/**
    136251 * Render the main theme dashboard admin page.
    137252 */
    … …  
    153268                                <li><button type="button" role="tab" class="nav-tab" data-tab="modules"><?php esc_html_e( 'Modules', 'postfolio-blocks' ); ?></button></li>
    154269                                <li><button type="button" role="tab" class="nav-tab" data-tab="starter-sites"><?php esc_html_e( 'Starter Sites', 'postfolio-blocks' ); ?></button></li>
     270                                <li><button type="button" role="tab" class="nav-tab" data-tab="recommended-plugins"><?php esc_html_e( 'Recommended Plugins', 'postfolio-blocks' ); ?></button></li>
    155271                                <li><button type="button" role="tab" class="nav-tab" data-tab="features"><?php esc_html_e( 'All Features', 'postfolio-blocks' ); ?></button></li>
    156272                        </ul>
    … …  
    278394                                <?php esc_html_e( 'Also apply the matching style variation (replaces your current Global Styles colors and fonts)', 'postfolio-blocks' ); ?>
    279395                        </label>
     396                        <label class="postfolio-apply-style">
     397                                <input type="checkbox" id="postfolio-demo-content" value="1" checked>
     398                                <?php esc_html_e( 'Add demo posts, categories, featured images and a menu where the starter site includes them (marked "Demo content")', 'postfolio-blocks' ); ?>
     399                        </label>
    280400
    281401                        <div class="postfolio-starter-grid">
    282                                 <?php foreach ( postfolio_blocks_starter_sites() as $slug => $site ) : ?>
    283                                         <div class="postfolio-starter-card">
    284                                                 <?php if ( $site['style'] ) : ?>
    285                                                         <div class="postfolio-pro-badge"><?php echo esc_html( $site['style'] ); ?></div>
    286                                                 <?php endif; ?>
    287                                                 <div class="postfolio-starter-preview-wrap">
    288                                                         <img src="<?php echo esc_url( get_theme_file_uri( 'assets/images/' . $site['image'] ) ); ?>" alt="" loading="lazy">
     402                                <?php
     403                                $imported_sites = get_option( 'postfolio_blocks_imported_pages', array() );
     404                                $imported_sites = is_array( $imported_sites ) ? $imported_sites : array();
     405
     406                                foreach ( postfolio_blocks_starter_sites() as $slug => $site ) :
     407                                        $tokens   = postfolio_blocks_starter_site_tokens( $site['style'] );
     408                                        $imported = ! empty( $imported_sites[ $slug ] );
     409                                        $pages    = wp_list_pluck( $site['pages'], 0 );
     410
     411                                        if ( ! $site['front'] ) {
     412                                                array_unshift( $pages, __( 'Latest posts', 'postfolio-blocks' ) );
     413                                        }
     414
     415                                        if ( ! empty( $site['demo'] ) ) {
     416                                                /* translators: %d: number of demo posts. */
     417                                                $pages[] = sprintf( __( 'Demo content: %d posts', 'postfolio-blocks' ), count( postfolio_blocks_demo_posts() ) + ( empty( $site['projects'] ) ? 0 : count( postfolio_blocks_demo_projects() ) ) );
     418                                        }
     419
     420                                        $vars = sprintf(
     421                                                '--pf-bg:%1$s;--pf-bg2:%2$s;--pf-fg:%3$s;--pf-fg2:%4$s;--pf-ac:%5$s;--pf-ac2:%6$s;--pf-hf:%7$s;--pf-bf:%8$s;--pf-r:%9$s',
     422                                                $tokens['base'],
     423                                                $tokens['base-2'],
     424                                                $tokens['contrast'],
     425                                                $tokens['contrast-2'],
     426                                                $tokens['accent'],
     427                                                $tokens['accent-2'],
     428                                                $tokens['heading'],
     429                                                $tokens['body'],
     430                                                $tokens['radius']
     431                                        );
     432                                        ?>
     433                                        <article class="postfolio-starter-card<?php echo $imported ? ' is-imported' : ''; ?>" style="<?php echo esc_attr( $vars ); ?>" aria-labelledby="postfolio-starter-<?php echo esc_attr( $slug ); ?>">
     434                                                <div class="postfolio-starter-preview-wrap" aria-hidden="true">
     435                                                        <?php postfolio_blocks_starter_mockup( $site['layout'], get_bloginfo( 'name' ) ? get_bloginfo( 'name' ) : 'Postfolio' ); ?>
    289436                                                </div>
    290437                                                <div class="postfolio-starter-footer">
    291                                                         <span class="postfolio-starter-title"><?php echo esc_html( $site['title'] ); ?></span>
     438                                                        <div class="postfolio-starter-head">
     439                                                                <h3 class="postfolio-starter-title" id="postfolio-starter-<?php echo esc_attr( $slug ); ?>"><?php echo esc_html( $site['title'] ); ?></h3>
     440                                                                <?php if ( $imported ) : ?>
     441                                                                        <span class="postfolio-starter-status"><span class="dashicons dashicons-yes" aria-hidden="true"></span><?php esc_html_e( 'Imported', 'postfolio-blocks' ); ?></span>
     442                                                                <?php endif; ?>
     443                                                        </div>
    292444                                                        <p class="postfolio-starter-desc"><?php echo esc_html( $site['description'] ); ?></p>
     445
     446                                                        <dl class="postfolio-starter-meta">
     447                                                                <div>
     448                                                                        <dt><?php esc_html_e( 'Style', 'postfolio-blocks' ); ?></dt>
     449                                                                        <dd>
     450                                                                                <span class="postfolio-starter-swatches" aria-hidden="true"><i style="background:var(--pf-bg)"></i><i style="background:var(--pf-fg)"></i><i style="background:var(--pf-ac)"></i><i style="background:var(--pf-ac2)"></i></span>
     451                                                                                <?php echo esc_html( $site['style'] ? $site['style'] : __( 'Default', 'postfolio-blocks' ) ); ?>
     452                                                                        </dd>
     453                                                                </div>
     454                                                                <div>
     455                                                                        <dt><?php esc_html_e( 'Fonts', 'postfolio-blocks' ); ?></dt>
     456                                                                        <dd>
     457                                                                                <span class="postfolio-starter-font is-heading"><?php echo esc_html( $tokens['heading-name'] ); ?></span>
     458                                                                                <?php if ( $tokens['body-name'] !== $tokens['heading-name'] ) : ?>
     459                                                                                        <span aria-hidden="true">+</span>
     460                                                                                        <span class="postfolio-starter-font is-body"><?php echo esc_html( $tokens['body-name'] ); ?></span>
     461                                                                                <?php endif; ?>
     462                                                                        </dd>
     463                                                                </div>
     464                                                                <div>
     465                                                                        <dt><?php esc_html_e( 'Pages', 'postfolio-blocks' ); ?></dt>
     466                                                                        <dd>
     467                                                                                <ul class="postfolio-starter-pages">
     468                                                                                        <?php foreach ( $pages as $page_title ) : ?>
     469                                                                                                <li><?php echo esc_html( $page_title ); ?></li>
     470                                                                                        <?php endforeach; ?>
     471                                                                                </ul>
     472                                                                        </dd>
     473                                                                </div>
     474                                                        </dl>
     475
    293476                                                        <div class="postfolio-starter-actions">
    294477                                                                <button type="button" class="postfolio-btn-import" data-demo="<?php echo esc_attr( $slug ); ?>" data-title="<?php echo esc_attr( $site['title'] ); ?>">
    295                                                                         <span class="dashicons dashicons-download" aria-hidden="true"></span>
    296                                                                         <?php esc_html_e( 'Import', 'postfolio-blocks' ); ?>
     478                                                                        <span class="dashicons dashicons-<?php echo $imported ? 'update' : 'download'; ?>" aria-hidden="true"></span>
     479                                                                        <?php $imported ? esc_html_e( 'Re-import', 'postfolio-blocks' ) : esc_html_e( 'Import', 'postfolio-blocks' ); ?>
    297480                                                                </button>
    298481                                                        </div>
    299482                                                </div>
    300                                         </div>
     483                                        </article>
    301484                                <?php endforeach; ?>
    302485                        </div>
    303486                </div>
    304487
    305                 <!-- TAB 4: ALL FEATURES -->
     488                <!-- TAB 4: RECOMMENDED PLUGINS -->
     489                <div id="recommended-plugins" class="postfolio-tab-panel" role="tabpanel">
     490                        <?php postfolio_blocks_render_recommended_plugins(); ?>
     491                </div>
     492
     493                <!-- TAB 5: ALL FEATURES -->
    306494                <div id="features" class="postfolio-tab-panel" role="tabpanel">
    307495                        <div class="postfolio-section-header">
  • postfolio-blocks/1.2.0/inc/blog-features.php

    r352228 r353530  
    5050                        $parsed_block['attrs']['query']['inherit']       = false;
    5151                        $parsed_block['attrs']['query']['postfolioMode'] = 'popular';
     52                } elseif ( postfolio_blocks_block_has_class( $parsed_block, 'postfolio-current-term' ) ) {
     53                        $parsed_block['attrs']['query']['inherit']       = false;
     54                        $parsed_block['attrs']['query']['postfolioMode'] = 'current-term';
    5255                }
    5356        }
    … …  
    6063}
    6164add_filter( 'render_block_data', 'postfolio_blocks_render_block_data' );
     65
     66/**
     67 * Pass the related/popular mode from a tagged Query Loop to its Post Template.
     68 *
     69 * render_block_data only reaches the post template's context when the Query
     70 * Loop is a top-level block; inside groups or columns the context is built
     71 * from the parent block, so set it here from the parent's class name.
     72 *
     73 * @param array         $context      Block context.
     74 * @param array         $parsed_block Block being rendered.
     75 * @param WP_Block|null $parent_block Parent block.
     76 * @return array
     77 */
     78function postfolio_blocks_query_mode_context( $context, $parsed_block, $parent_block = null ) {
     79        if ( ! $parent_block || 'core/query' !== $parent_block->name || ! isset( $context['query'] ) ) {
     80                return $context;
     81        }
     82
     83        $parent = $parent_block->parsed_block;
     84
     85        if ( postfolio_blocks_block_has_class( $parent, 'postfolio-related-posts' ) ) {
     86                $context['query']['inherit']       = false;
     87                $context['query']['postfolioMode'] = 'related';
     88        } elseif ( postfolio_blocks_block_has_class( $parent, 'postfolio-popular-posts' ) ) {
     89                $context['query']['inherit']       = false;
     90                $context['query']['postfolioMode'] = 'popular';
     91        } elseif ( postfolio_blocks_block_has_class( $parent, 'postfolio-current-term' ) ) {
     92                $context['query']['inherit']       = false;
     93                $context['query']['postfolioMode'] = 'current-term';
     94        }
     95
     96        return $context;
     97}
     98add_filter( 'render_block_context', 'postfolio_blocks_query_mode_context', 10, 3 );
    6299
    63100/**
    … …  
    82119                                $query['category__in'] = $categories;
    83120                        }
     121                }
     122        } elseif ( 'current-term' === $mode ) {
     123                // Archive sections (lead story, grid) scoped to the term being viewed.
     124                $term = get_queried_object();
     125                if ( $term instanceof WP_Term ) {
     126                        $query['tax_query'] = array(
     127                                array(
     128                                        'taxonomy'         => $term->taxonomy,
     129                                        'field'            => 'term_id',
     130                                        'terms'            => array( $term->term_id ),
     131                                        'include_children' => true,
     132                                ),
     133                        );
     134                        $query['ignore_sticky_posts'] = true;
    84135                }
    85136        } elseif ( 'popular' === $mode ) {
    … …  
    176227}
    177228add_filter( 'render_block_core/group', 'postfolio_blocks_maybe_enqueue_toc', 10, 2 );
     229
     230/**
     231 * Give the author box a short fallback bio, with a link to the author's
     232 * archive, when the author has not filled in their biography yet.
     233 *
     234 * @param string $block_content Rendered block.
     235 * @param array  $block         Parsed block.
     236 * @return string
     237 */
     238function postfolio_blocks_author_bio_fallback( $block_content, $block ) {
     239        if ( '' !== trim( $block_content ) || empty( $block['attrs']['className'] ) || false === strpos( $block['attrs']['className'], 'postfolio-author-bio' ) ) {
     240                return $block_content;
     241        }
     242
     243        $author_id = (int) get_post_field( 'post_author', get_the_ID() );
     244        if ( ! $author_id ) {
     245                return $block_content;
     246        }
     247
     248        return sprintf(
     249                '<div class="wp-block-post-author-biography postfolio-author-bio has-contrast-2-color has-text-color">%1$s <a href="%2$s">%3$s</a></div>',
     250                /* translators: 1: author name, 2: site name. */
     251                esc_html( sprintf( __( '%1$s writes for %2$s.', 'postfolio-blocks' ), get_the_author_meta( 'display_name', $author_id ), get_bloginfo( 'name' ) ) ),
     252                esc_url( get_author_posts_url( $author_id ) ),
     253                esc_html__( 'Read all their stories →', 'postfolio-blocks' )
     254        );
     255}
     256add_filter( 'render_block_core/post-author-biography', 'postfolio_blocks_author_bio_fallback', 10, 2 );
  • postfolio-blocks/1.2.0/inc/modules.php

    r352228 r353530  
    243243
    244244        return sprintf( 'html[data-postfolio-scheme="%1$s"]{%2$scolor-scheme:%1$s;}', $scheme, $declarations );
     245}
     246
     247/**
     248 * CSS that keeps the footers readable with any palette.
     249 *
     250 * The footers have a fixed dark background, so inside them "base" must
     251 * always be the light color and "contrast" the dark one — whether the
     252 * active palette is light, dark (e.g. Midnight) or switched by dark mode.
     253 *
     254 * @return string
     255 */
     256function postfolio_blocks_footer_palette_css() {
     257        $palette = wp_get_global_settings( array( 'color', 'palette' ) );
     258        $colors  = array();
     259
     260        foreach ( array( 'default', 'theme', 'custom' ) as $origin ) {
     261                if ( ! empty( $palette[ $origin ] ) ) {
     262                        foreach ( $palette[ $origin ] as $entry ) {
     263                                $colors[ $entry['slug'] ] = $entry['color'];
     264                        }
     265                }
     266        }
     267
     268        foreach ( array( 'base', 'contrast' ) as $slug ) {
     269                if ( empty( $colors[ $slug ] ) || '#' !== substr( $colors[ $slug ], 0, 1 ) ) {
     270                        return '';
     271                }
     272        }
     273
     274        $light = $colors['base'];
     275        $dark  = $colors['contrast'];
     276
     277        if ( postfolio_blocks_luminance( $light ) < postfolio_blocks_luminance( $dark ) ) {
     278                list( $light, $dark ) = array( $dark, $light );
     279        }
     280
     281        return sprintf(
     282                '.postfolio-footer{--wp--preset--color--base:%1$s;--wp--preset--color--base-2:%2$s;--wp--preset--color--contrast:%3$s;--wp--preset--color--contrast-2:%4$s;color-scheme:dark;}',
     283                $light,
     284                postfolio_blocks_mix_hex( $dark, $light, 0.12 ),
     285                $dark,
     286                postfolio_blocks_mix_hex( $light, $dark, 0.35 )
     287        );
    245288}
    246289
    … …  
    339382 */
    340383function postfolio_blocks_module_body_class( $classes ) {
    341         foreach ( array( 'smart_header', 'footer_reveal', 'animations' ) as $key ) {
     384        foreach ( array( 'smart_header', 'footer_reveal', 'animations', 'dark_mode' ) as $key ) {
    342385                if ( postfolio_blocks_module_enabled( $key ) ) {
    343386                        $classes[] = 'postfolio-has-' . str_replace( '_', '-', $key );
  • postfolio-blocks/1.2.0/inc/starter-sites.php

    r352228 r353530  
    2424                'blog'      => array(
    2525                        'title'       => __( 'Personal Blog', 'postfolio-blocks' ),
    26                         'description' => __( 'Latest posts on the homepage, plus About and Contact pages.', 'postfolio-blocks' ),
     26                        'description' => __( 'Personal homepage with an intro, featured story and recent writing, plus Blog, About and Contact.', 'postfolio-blocks' ),
    2727                        'style'       => '',
    28                         'image'       => 'photo-1.svg',
    29                         'front'       => '',
     28                        'layout'      => 'blog',
     29                        'demo'        => true,
     30                        'front'       => 'home',
     31                        'posts'       => 'blog',
    3032                        'pages'       => array(
     33                                'home'    => array( __( 'Home', 'postfolio-blocks' ), 'postfolio-blocks/page-blog-starter', 'page-no-title' ),
     34                                'blog'    => array( __( 'Blog', 'postfolio-blocks' ), '', '' ),
    3135                                'about'   => array( __( 'About', 'postfolio-blocks' ), 'postfolio-blocks/page-about-content', '' ),
    3236                                'contact' => array( __( 'Contact', 'postfolio-blocks' ), 'postfolio-blocks/page-contact-starter', '' ),
    … …  
    3741                        'description' => __( 'Spotlight homepage with featured stories and a separate blog page.', 'postfolio-blocks' ),
    3842                        'style'       => 'Retro',
    39                         'image'       => 'photo-5.svg',
     43                        'layout'      => 'magazine',
     44                        'demo'        => true,
    4045                        'front'       => 'home',
    4146                        'posts'       => 'blog',
    4247                        'pages'       => array(
    43                                 'home'    => array( __( 'Home', 'postfolio-blocks' ), '', 'home-2' ),
     48                                'home'    => array( __( 'Home', 'postfolio-blocks' ), 'postfolio-blocks/page-magazine-starter', 'page-no-title' ),
    4449                                'blog'    => array( __( 'Blog', 'postfolio-blocks' ), '', '' ),
    4550                                'about'   => array( __( 'About', 'postfolio-blocks' ), 'postfolio-blocks/page-about-content', '' ),
    … …  
    4954                'editorial' => array(
    5055                        'title'       => __( 'Editorial News', 'postfolio-blocks' ),
    51                         'description' => __( 'Clean editorial list homepage in the Nordic style.', 'postfolio-blocks' ),
     56                        'description' => __( 'Lead story, latest headlines and a news list with sidebar, in the Nordic style.', 'postfolio-blocks' ),
    5257                        'style'       => 'Nordic',
    53                         'image'       => 'photo-6.svg',
     58                        'layout'      => 'editorial',
     59                        'demo'        => true,
    5460                        'front'       => 'home',
    5561                        'posts'       => 'blog',
    5662                        'pages'       => array(
    57                                 'home'    => array( __( 'Home', 'postfolio-blocks' ), '', 'home-3' ),
     63                                'home'    => array( __( 'Home', 'postfolio-blocks' ), 'postfolio-blocks/page-editorial-starter', 'page-no-title' ),
    5864                                'blog'    => array( __( 'Latest', 'postfolio-blocks' ), '', '' ),
    5965                                'about'   => array( __( 'About', 'postfolio-blocks' ), 'postfolio-blocks/page-about-content', '' ),
    … …  
    6369                'portfolio' => array(
    6470                        'title'       => __( 'Creative Portfolio', 'postfolio-blocks' ),
    65                         'description' => __( 'Portfolio homepage, project grid, case study and contact page.', 'postfolio-blocks' ),
     71                        'description' => __( 'Portfolio homepage, 4 demo case studies, work grid, journal and contact page.', 'postfolio-blocks' ),
    6672                        'style'       => 'Midnight',
    67                         'image'       => 'photo-7.svg',
     73                        'layout'      => 'portfolio',
     74                        'demo'        => true,
     75                        'projects'    => true,
    6876                        'front'       => 'home',
    6977                        'posts'       => 'journal',
    … …  
    7785                'business'  => array(
    7886                        'title'       => __( 'Business & Agency', 'postfolio-blocks' ),
    79                         'description' => __( 'Landing page with transparent header, services, pricing and contact.', 'postfolio-blocks' ),
     87                        'description' => __( 'Agency homepage with split hero, services, selected work, process, team, pricing and FAQ.', 'postfolio-blocks' ),
    8088                        'style'       => 'Sunset',
    81                         'image'       => 'photo-2.svg',
     89                        'layout'      => 'business',
    8290                        'front'       => 'home',
    8391                        'posts'       => 'news',
    … …  
    94102
    95103/**
     104 * Design tokens (colors, fonts, button radius) for a starter site preview.
     105 *
     106 * Read from theme.json and the starter site's style variation, so the
     107 * dashboard card always matches what the import will actually look like.
     108 *
     109 * @param string $style Style variation title, or '' for the default style.
     110 * @return array<string, string>
     111 */
     112function postfolio_blocks_starter_site_tokens( $style ) {
     113        static $base = null;
     114
     115        if ( null === $base ) {
     116                $base = wp_json_file_decode( get_theme_file_path( 'theme.json' ), array( 'associative' => true ) );
     117                $base = is_array( $base ) ? $base : array();
     118        }
     119
     120        $data = $base;
     121
     122        if ( $style ) {
     123                foreach ( WP_Theme_JSON_Resolver::get_style_variations() as $variation ) {
     124                        if ( isset( $variation['title'] ) && $variation['title'] === $style ) {
     125                                $data = array_replace_recursive( $base, $variation );
     126
     127                                // Presets are replaced, not merged; newer WordPress versions also
     128                                // key them by origin ("theme"), like Global Styles does.
     129                                if ( isset( $variation['settings']['color']['palette'] ) ) {
     130                                        $palette = $variation['settings']['color']['palette'];
     131                                        $data['settings']['color']['palette'] = isset( $palette['theme'] ) ? $palette['theme'] : $palette;
     132                                }
     133                                break;
     134                        }
     135                }
     136        }
     137
     138        $colors = array();
     139        foreach ( isset( $data['settings']['color']['palette'] ) ? $data['settings']['color']['palette'] : array() as $color ) {
     140                if ( isset( $color['slug'], $color['color'] ) ) {
     141                        $colors[ $color['slug'] ] = $color['color'];
     142                }
     143        }
     144
     145        $fonts = array();
     146        foreach ( isset( $base['settings']['typography']['fontFamilies'] ) ? $base['settings']['typography']['fontFamilies'] : array() as $font ) {
     147                $fonts[ $font['slug'] ] = array( $font['name'], $font['fontFamily'] );
     148        }
     149
     150        $font_for = function ( $value, $fallback ) use ( $fonts ) {
     151                if ( is_string( $value ) && preg_match( '/font-family--([a-z0-9-]+)/', $value, $match ) && isset( $fonts[ $match[1] ] ) ) {
     152                        return $fonts[ $match[1] ];
     153                }
     154                return isset( $fonts[ $fallback ] ) ? $fonts[ $fallback ] : array( '', 'sans-serif' );
     155        };
     156
     157        $styles  = isset( $data['styles'] ) ? $data['styles'] : array();
     158        $body    = $font_for( isset( $styles['typography']['fontFamily'] ) ? $styles['typography']['fontFamily'] : '', 'montserrat' );
     159        $heading = $font_for( isset( $styles['elements']['heading']['typography']['fontFamily'] ) ? $styles['elements']['heading']['typography']['fontFamily'] : '', 'poppins' );
     160        $radius  = isset( $styles['elements']['button']['border']['radius'] ) ? $styles['elements']['button']['border']['radius'] : '999px';
     161
     162        return array(
     163                'base'         => isset( $colors['base'] ) ? $colors['base'] : '#ffffff',
     164                'base-2'       => isset( $colors['base-2'] ) ? $colors['base-2'] : '#f3f3f6',
     165                'contrast'     => isset( $colors['contrast'] ) ? $colors['contrast'] : '#101014',
     166                'contrast-2'   => isset( $colors['contrast-2'] ) ? $colors['contrast-2'] : '#54545e',
     167                'accent'       => isset( $colors['accent'] ) ? $colors['accent'] : '#4f46e5',
     168                'accent-2'     => isset( $colors['accent-2'] ) ? $colors['accent-2'] : '#ff5a36',
     169                'heading'      => $heading[1],
     170                'heading-name' => $heading[0],
     171                'body'         => $body[1],
     172                'body-name'    => $body[0],
     173                'radius'       => is_string( $radius ) ? $radius : '999px',
     174        );
     175}
     176
     177/**
     178 * URL of a page in the starter site being imported (by page key, such as
     179 * "blog" or "about"). Outside an import, falls back to the page with that
     180 * slug, then to the posts page or home URL.
     181 *
     182 * @param string $key Page key.
     183 * @return string
     184 */
     185function postfolio_blocks_starter_page_url( $key ) {
     186        if ( ! empty( $GLOBALS['postfolio_blocks_starter_pages'][ $key ] ) ) {
     187                return get_permalink( $GLOBALS['postfolio_blocks_starter_pages'][ $key ] );
     188        }
     189
     190        $page = get_page_by_path( $key );
     191        if ( $page ) {
     192                return get_permalink( $page );
     193        }
     194
     195        $posts_page = (int) get_option( 'page_for_posts' );
     196        return $posts_page ? get_permalink( $posts_page ) : home_url( '/' );
     197}
     198
     199/**
    96200 * Get the registered content of a theme pattern.
    97201 *
    … …  
    182286 * @param string $slug        Starter site key.
    183287 * @param bool   $apply_style Whether to apply the matching style variation.
     288 * @param bool   $with_demo   Whether to add demo posts, images and a menu.
    184289 * @return array|WP_Error Summary on success.
    185290 */
    186 function postfolio_blocks_import_starter_site( $slug, $apply_style = false ) {
     291function postfolio_blocks_import_starter_site( $slug, $apply_style = false, $with_demo = true ) {
    187292        $sites = postfolio_blocks_starter_sites();
    188293
    … …  
    191296        }
    192297
    193         $site     = $sites[ $slug ];
     298        $site       = $sites[ $slug ];
     299        $with_demo  = $with_demo && ! empty( $site['demo'] );
     300        $demo_posts = 0;
     301
     302        // Demo terms must exist before the pages are built: page patterns look them up.
     303        if ( $with_demo ) {
     304                $demo       = postfolio_blocks_import_demo_content();
     305                $demo_posts = $demo['posts'];
     306
     307                if ( ! empty( $site['projects'] ) ) {
     308                        $demo_posts += postfolio_blocks_import_demo_projects();
     309                }
     310        }
     311
    194312        $imported = get_option( 'postfolio_blocks_imported_pages', array() );
    195313        $imported = is_array( $imported ) ? $imported : array();
    196314        $page_ids = array();
    197315
     316        // Pass 1: make sure every page exists, so page patterns can link to each
     317        // other (see postfolio_blocks_starter_page_url()) when they are built.
     318        foreach ( $site['pages'] as $key => $page ) {
     319                $existing = isset( $imported[ $slug ][ $key ] ) ? get_post( $imported[ $slug ][ $key ] ) : null;
     320
     321                if ( $existing && 'page' === $existing->post_type && 'trash' !== $existing->post_status ) {
     322                        $page_ids[ $key ] = (int) $existing->ID;
     323                        continue;
     324                }
     325
     326                $page_id = wp_insert_post(
     327                        array(
     328                                'post_title'  => $page[0],
     329                                'post_status' => 'publish',
     330                                'post_type'   => 'page',
     331                        ),
     332                        true
     333                );
     334
     335                if ( is_wp_error( $page_id ) ) {
     336                        return $page_id;
     337                }
     338
     339                $page_ids[ $key ] = (int) $page_id;
     340        }
     341
     342        $GLOBALS['postfolio_blocks_starter_pages'] = $page_ids;
     343
     344        // Pass 2: fill in content and templates.
    198345        foreach ( $site['pages'] as $key => $page ) {
    199346                list( $title, $pattern, $template ) = $page;
    200347
    201348                $content  = postfolio_blocks_pattern_content( $pattern );
    202                 $existing = isset( $imported[ $slug ][ $key ] ) ? get_post( $imported[ $slug ][ $key ] ) : null;
     349                $existing = get_post( $page_ids[ $key ] );
    203350                $postarr  = array(
    204351                        'post_title'   => $title,
    … …  
    227374                $page_ids[ $key ] = (int) $page_id;
    228375        }
     376
     377        unset( $GLOBALS['postfolio_blocks_starter_pages'] );
    229378
    230379        $imported[ $slug ] = $page_ids;
    … …  
    241390        }
    242391
     392        if ( $with_demo ) {
     393                postfolio_blocks_import_demo_menu( $page_ids, empty( $site['projects'] ) );
     394        }
     395
    243396        $style_applied = false;
    244397        if ( $apply_style && $site['style'] ) {
    … …  
    248401        return array(
    249402                'pages'         => count( $page_ids ),
     403                'posts'         => $demo_posts,
    250404                'style_applied' => $style_applied,
    251405        );
    … …  
    264418        $slug        = isset( $_POST['demo_slug'] ) ? sanitize_key( wp_unslash( $_POST['demo_slug'] ) ) : '';
    265419        $apply_style = ! empty( $_POST['apply_style'] );
    266         $result      = postfolio_blocks_import_starter_site( $slug, $apply_style );
     420        $with_demo   = ! isset( $_POST['demo_content'] ) || ! empty( $_POST['demo_content'] );
     421        $result      = postfolio_blocks_import_starter_site( $slug, $apply_style, $with_demo );
    267422
    268423        if ( is_wp_error( $result ) ) {
    … …  
    277432        );
    278433
     434        $demo_count = (int) $result['posts'];
     435
     436        if ( $demo_count ) {
     437                $message .= ' ' . sprintf(
     438                        /* translators: %d: number of demo posts. */
     439                        _n( '%d demo post with images and a menu were added.', '%d demo posts with images and a menu were added.', $demo_count, 'postfolio-blocks' ),
     440                        $demo_count
     441                );
     442        }
     443
    279444        if ( $result['style_applied'] ) {
    280445                $message .= ' ' . __( 'The matching style variation was applied.', 'postfolio-blocks' );
  • postfolio-blocks/1.2.0/patterns/featured-split.php

    r352228 r353530  
    1414}
    1515?>
    16 <!-- wp:group {"align":"wide","style":{"spacing":{"margin":{"top":"var:preset|spacing|50","bottom":"var:preset|spacing|50"}}},"layout":{"type":"constrained"}} -->
     16<!-- wp:group {"align":"wide","style":{"spacing":{"margin":{"top":"var:preset|spacing|50","bottom":"var:preset|spacing|50"}}},"layout":{"type":"default"}} -->
    1717<div class="wp-block-group alignwide" style="margin-top:var(--wp--preset--spacing--50);margin-bottom:var(--wp--preset--spacing--50)"><!-- wp:heading {"fontSize":"xx-large","style":{"spacing":{"margin":{"bottom":"var:preset|spacing|30"}}}} -->
    1818<h2 class="wp-block-heading has-xx-large-font-size" style="margin-bottom:var(--wp--preset--spacing--30)"><?php esc_html_e( 'Spotlight', 'postfolio-blocks' ); ?></h2>
    … …  
    2424<div class="wp-block-query"><!-- wp:post-template -->
    2525<!-- wp:cover {"useFeaturedImage":true,"dimRatio":40,"minHeight":460,"minHeightUnit":"px","className":"postfolio-spotlight-primary","style":{"border":{"radius":"1.25rem"}}} -->
    26 <div class="wp-block-cover postfolio-spotlight-primary" style="border-radius:1.25rem;min-height:460px"><span aria-hidden="true" class="wp-block-cover__background has-background-dim-40 has-background-dim"></span><div class="wp-block-cover__inner-container"><!-- wp:post-terms {"term":"category","className":"postfolio-badge","textColor":"base"} /-->
     26<div class="wp-block-cover postfolio-spotlight-primary" style="border-radius:1.25rem;min-height:460px"><span aria-hidden="true" class="wp-block-cover__background has-background-dim-40 has-background-dim"></span><div class="wp-block-cover__inner-container"><!-- wp:post-terms {"term":"category","className":"postfolio-badge-accent"} /-->
    2727
    2828<!-- wp:post-title {"isLink":true,"fontSize":"xx-large"} /-->
  • postfolio-blocks/1.2.0/patterns/page-landing-starter.php

    r352228 r353530  
    11<?php
    22/**
    3  * Title: Page: business landing
     3 * Title: Page: Agency landing
    44 * Slug: postfolio-blocks/page-landing-starter
    55 * Categories: postfolio-blocks, postfolio-blocks-pages
    6  * Keywords: landing, business, agency, homepage
    7  * Description: A complete landing page: hero, logos, features, process, stats, testimonial, pricing, FAQ and a call to action. Pairs with the "Landing Page" template.
    8  * Block Types: core/post-content
    9  * Post Types: page
    10  * Viewport Width: 1400
     6 * Keywords: agency, business, landing, services, pricing, team, portfolio
     7 * Description: A complete agency homepage for the Landing Page template: split hero with social proof, client logos, services, selected work, process, numbers, team, testimonial, pricing, FAQ and a closing call to action.
    118 * Inserter: true
    129 *
    … …  
    1714        exit; // Exit if accessed directly.
    1815}
     16
     17$postfolio_img = function ( $file ) {
     18        return esc_url( get_theme_file_uri( 'assets/images/' . $file ) );
     19};
     20
     21$postfolio_services = array(
     22        array( '01', __( 'Brand strategy', 'postfolio-blocks' ), __( 'Positioning, naming and messaging that make you the obvious choice.', 'postfolio-blocks' ) ),
     23        array( '02', __( 'Visual identity', 'postfolio-blocks' ), __( 'Logos, type and colour systems that work on every surface.', 'postfolio-blocks' ) ),
     24        array( '03', __( 'Website design', 'postfolio-blocks' ), __( 'Fast, accessible sites designed to turn visitors into customers.', 'postfolio-blocks' ) ),
     25        array( '04', __( 'Development', 'postfolio-blocks' ), __( 'WordPress and headless builds your team can edit with confidence.', 'postfolio-blocks' ) ),
     26        array( '05', __( 'Content & SEO', 'postfolio-blocks' ), __( 'Copy, structure and search strategy that bring the right traffic.', 'postfolio-blocks' ) ),
     27        array( '06', __( 'Growth marketing', 'postfolio-blocks' ), __( 'Campaigns, landing pages and testing that compound month after month.', 'postfolio-blocks' ) ),
     28);
     29
     30$postfolio_work = array(
     31        array( 'demo/design-studio.jpg', __( 'Northwind Coffee', 'postfolio-blocks' ), __( 'Branding · Website', 'postfolio-blocks' ), __( '+140% online orders', 'postfolio-blocks' ) ),
     32        array( 'demo/business-city.jpg', __( 'Civic Downtown', 'postfolio-blocks' ), __( 'Strategy · Campaign', 'postfolio-blocks' ), __( '3× event sign-ups', 'postfolio-blocks' ) ),
     33        array( 'demo/tech-workspace.jpg', __( 'Localfirst App', 'postfolio-blocks' ), __( 'Product · Web app', 'postfolio-blocks' ), __( '42k users in 6 months', 'postfolio-blocks' ) ),
     34        array( 'demo/culture-gallery.jpg', __( 'The Small Museum', 'postfolio-blocks' ), __( 'Identity · Website', 'postfolio-blocks' ), __( '+65% ticket sales', 'postfolio-blocks' ) ),
     35);
     36
     37$postfolio_steps = array(
     38        array( '01', __( 'Discover', 'postfolio-blocks' ), __( 'We listen, research and agree on what success looks like.', 'postfolio-blocks' ) ),
     39        array( '02', __( 'Define', 'postfolio-blocks' ), __( 'A clear plan, scope and timeline — no surprises later.', 'postfolio-blocks' ) ),
     40        array( '03', __( 'Design', 'postfolio-blocks' ), __( 'We sketch, prototype and test until it feels obvious.', 'postfolio-blocks' ) ),
     41        array( '04', __( 'Deliver', 'postfolio-blocks' ), __( 'Launch, measure and keep improving together.', 'postfolio-blocks' ) ),
     42);
     43
     44$postfolio_team = array(
     45        array( 'portrait-1.svg', __( 'Maya Chen', 'postfolio-blocks' ), __( 'Founder & Strategy', 'postfolio-blocks' ) ),
     46        array( 'portrait-2.svg', __( 'Daniel Okafor', 'postfolio-blocks' ), __( 'Design Director', 'postfolio-blocks' ) ),
     47        array( 'portrait-3.svg', __( 'Sofia Rossi', 'postfolio-blocks' ), __( 'Lead Developer', 'postfolio-blocks' ) ),
     48        array( 'portrait-4.svg', __( 'Leo Fischer', 'postfolio-blocks' ), __( 'Growth & Content', 'postfolio-blocks' ) ),
     49);
     50
     51$postfolio_plans = array(
     52        array(
     53                'name'     => __( 'Launch', 'postfolio-blocks' ),
     54                'desc'     => __( 'For new brands that need a strong start.', 'postfolio-blocks' ),
     55                'price'    => '$2,900',
     56                'unit'     => __( 'per project', 'postfolio-blocks' ),
     57                'features' => array( __( 'Brand essentials & logo', 'postfolio-blocks' ), __( '5-page website', 'postfolio-blocks' ), __( 'Basic SEO setup', 'postfolio-blocks' ), __( '2 rounds of revisions', 'postfolio-blocks' ) ),
     58                'featured' => false,
     59        ),
     60        array(
     61                'name'     => __( 'Growth', 'postfolio-blocks' ),
     62                'desc'     => __( 'Our most popular plan for growing teams.', 'postfolio-blocks' ),
     63                'price'    => '$5,900',
     64                'unit'     => __( 'per project', 'postfolio-blocks' ),
     65                'features' => array( __( 'Full identity system', 'postfolio-blocks' ), __( 'Up to 15 pages + blog', 'postfolio-blocks' ), __( 'Content & SEO strategy', 'postfolio-blocks' ), __( 'Analytics & conversion setup', 'postfolio-blocks' ), __( '30 days of launch support', 'postfolio-blocks' ) ),
     66                'featured' => true,
     67        ),
     68        array(
     69                'name'     => __( 'Partner', 'postfolio-blocks' ),
     70                'desc'     => __( 'An embedded team for ongoing work.', 'postfolio-blocks' ),
     71                'price'    => __( 'Custom', 'postfolio-blocks' ),
     72                'unit'     => __( 'monthly retainer', 'postfolio-blocks' ),
     73                'features' => array( __( 'Dedicated design & dev team', 'postfolio-blocks' ), __( 'Unlimited requests', 'postfolio-blocks' ), __( 'Monthly growth reports', 'postfolio-blocks' ), __( 'Priority support', 'postfolio-blocks' ) ),
     74                'featured' => false,
     75        ),
     76);
     77
     78$postfolio_contact  = postfolio_blocks_starter_page_url( 'contact' );
     79$postfolio_services_url = postfolio_blocks_starter_page_url( 'services' );
    1980?>
    20 <!-- wp:cover {"url":"<?php echo esc_url( get_template_directory_uri() . '/assets/images/photo-7.svg' ); ?>","alt":"<?php echo esc_attr__( 'Purple abstract landscape', 'postfolio-blocks' ); ?>","dimRatio":50,"overlayColor":"contrast","minHeight":640,"minHeightUnit":"px","align":"full","style":{"spacing":{"padding":{"top":"var:preset|spacing|70","bottom":"var:preset|spacing|70","left":"var:preset|spacing|20","right":"var:preset|spacing|20"}}}} -->
    21 <div class="wp-block-cover alignfull" style="padding-top:var(--wp--preset--spacing--70);padding-right:var(--wp--preset--spacing--20);padding-bottom:var(--wp--preset--spacing--70);padding-left:var(--wp--preset--spacing--20);min-height:640px"><img class="wp-block-cover__image-background" alt="<?php echo esc_attr__( 'Purple abstract landscape', 'postfolio-blocks' ); ?>" src="<?php echo esc_url( get_template_directory_uri() . '/assets/images/photo-7.svg' ); ?>" data-object-fit="cover"/><span aria-hidden="true" class="wp-block-cover__background has-contrast-background-color has-background-dim"></span><div class="wp-block-cover__inner-container"><!-- wp:group {"style":{"spacing":{"blockGap":"1.5rem"}},"layout":{"type":"constrained","contentSize":"820px"}} -->
    22 <div class="wp-block-group"><!-- wp:paragraph {"align":"center","textColor":"base","fontSize":"small","style":{"typography":{"textTransform":"uppercase","letterSpacing":"0.1em","fontWeight":"600"}}} -->
    23 <p class="has-text-align-center has-base-color has-text-color has-small-font-size" style="font-weight:600;letter-spacing:0.1em;text-transform:uppercase"><?php esc_html_e( 'Strategy · Design · Development', 'postfolio-blocks' ); ?></p>
    24 <!-- /wp:paragraph -->
    25 
    26 <!-- wp:heading {"textAlign":"center","level":1,"textColor":"base","style":{"typography":{"fontSize":"clamp(2.25rem, 1.5rem + 3vw, 4rem)","fontWeight":"800","lineHeight":"1.08"}}} -->
    27 <h1 class="wp-block-heading has-text-align-center has-base-color has-text-color" style="font-size:clamp(2.25rem, 1.5rem + 3vw, 4rem);font-weight:800;line-height:1.08"><?php esc_html_e( 'We build brands and websites people remember.', 'postfolio-blocks' ); ?></h1>
    28 <!-- /wp:heading -->
    29 
    30 <!-- wp:paragraph {"align":"center","textColor":"base","fontSize":"large"} -->
    31 <p class="has-text-align-center has-base-color has-text-color has-large-font-size"><?php esc_html_e( 'An independent studio helping ambitious teams launch faster with clear strategy and beautiful design.', 'postfolio-blocks' ); ?></p>
    32 <!-- /wp:paragraph -->
    33 
    34 <!-- wp:buttons {"layout":{"type":"flex","justifyContent":"center"}} -->
    35 <div class="wp-block-buttons"><!-- wp:button {"backgroundColor":"base","textColor":"contrast"} -->
    36 <div class="wp-block-button"><a class="wp-block-button__link has-contrast-color has-base-background-color has-text-color has-background wp-element-button" href="<?php echo esc_url( home_url( '/contact/' ) ); ?>"><?php esc_html_e( 'Start a project', 'postfolio-blocks' ); ?></a></div>
     81<!-- wp:group {"align":"full","className":"postfolio-agency-hero","backgroundColor":"contrast","textColor":"base","style":{"spacing":{"padding":{"top":"11rem","bottom":"var:preset|spacing|60","left":"var:preset|spacing|20","right":"var:preset|spacing|20"}}},"layout":{"type":"constrained"}} -->
     82<div class="wp-block-group alignfull postfolio-agency-hero has-base-color has-contrast-background-color has-text-color has-background" style="padding-top:11rem;padding-right:var(--wp--preset--spacing--20);padding-bottom:var(--wp--preset--spacing--60);padding-left:var(--wp--preset--spacing--20)"><!-- wp:columns {"verticalAlignment":"center","align":"wide","style":{"spacing":{"blockGap":{"left":"var:preset|spacing|50"}}}} -->
     83<div class="wp-block-columns alignwide are-vertically-aligned-center"><!-- wp:column {"verticalAlignment":"center","width":"54%","style":{"spacing":{"blockGap":"1.5rem"}}} -->
     84<div class="wp-block-column is-vertically-aligned-center" style="flex-basis:54%"><!-- wp:paragraph {"className":"postfolio-hero-pill","fontSize":"small"} -->
     85<p class="postfolio-hero-pill has-small-font-size"><?php esc_html_e( 'Strategy · Design · Development', 'postfolio-blocks' ); ?></p>
     86<!-- /wp:paragraph -->
     87
     88<!-- wp:heading {"level":1,"textColor":"base","style":{"typography":{"fontSize":"clamp(2.5rem, 1.5rem + 3.6vw, 4.6rem)","fontWeight":"800","lineHeight":"1.04","letterSpacing":"-0.03em"}}} -->
     89<h1 class="wp-block-heading has-base-color has-text-color" style="font-size:clamp(2.5rem, 1.5rem + 3.6vw, 4.6rem);font-weight:800;letter-spacing:-0.03em;line-height:1.04"><?php esc_html_e( 'We build brands and websites people remember.', 'postfolio-blocks' ); ?></h1>
     90<!-- /wp:heading -->
     91
     92<!-- wp:paragraph {"className":"postfolio-muted","fontSize":"large"} -->
     93<p class="postfolio-muted has-large-font-size"><?php esc_html_e( 'An independent studio helping ambitious teams launch faster — with clear strategy, beautiful design and websites that actually convert.', 'postfolio-blocks' ); ?></p>
     94<!-- /wp:paragraph -->
     95
     96<!-- wp:buttons {"style":{"spacing":{"blockGap":"0.75rem"}}} -->
     97<div class="wp-block-buttons"><!-- wp:button {"backgroundColor":"accent","textColor":"base"} -->
     98<div class="wp-block-button"><a class="wp-block-button__link has-base-color has-accent-background-color has-text-color has-background wp-element-button" href="<?php echo esc_url( $postfolio_contact ); ?>"><?php esc_html_e( 'Start a project', 'postfolio-blocks' ); ?></a></div>
    3799<!-- /wp:button -->
    38100
    39101<!-- wp:button {"textColor":"base","className":"is-style-outline"} -->
    40 <div class="wp-block-button is-style-outline"><a class="wp-block-button__link has-base-color has-text-color wp-element-button" href="<?php echo esc_url( home_url( '/services/' ) ); ?>"><?php esc_html_e( 'See our work', 'postfolio-blocks' ); ?></a></div>
     102<div class="wp-block-button is-style-outline"><a class="wp-block-button__link has-base-color has-text-color wp-element-button" href="#work"><?php esc_html_e( 'See our work', 'postfolio-blocks' ); ?></a></div>
     103<!-- /wp:button --></div>
     104<!-- /wp:buttons -->
     105
     106<!-- wp:group {"className":"postfolio-trust","style":{"spacing":{"blockGap":"0.9rem","margin":{"top":"var:preset|spacing|20"}}},"layout":{"type":"flex","flexWrap":"wrap","verticalAlignment":"center"}} -->
     107<div class="wp-block-group postfolio-trust" style="margin-top:var(--wp--preset--spacing--20)"><!-- wp:group {"className":"postfolio-avatar-stack","style":{"spacing":{"blockGap":"0"}},"layout":{"type":"flex","flexWrap":"nowrap"}} -->
     108<div class="wp-block-group postfolio-avatar-stack"><?php foreach ( array_slice( $postfolio_team, 0, 4 ) as $postfolio_person ) : ?><!-- wp:image {"width":"40px","height":"40px","scale":"cover","sizeSlug":"full","style":{"border":{"radius":"999px"}}} -->
     109<figure class="wp-block-image size-full is-resized has-custom-border"><img src="<?php echo $postfolio_img( $postfolio_person[0] ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>" alt="" style="border-radius:999px;object-fit:cover;width:40px;height:40px"/></figure>
     110<!-- /wp:image --><?php endforeach; ?></div>
     111<!-- /wp:group -->
     112
     113<!-- wp:paragraph {"fontSize":"small"} -->
     114<p class="has-small-font-size"><span class="postfolio-stars" aria-hidden="true">★★★★★</span><br><?php esc_html_e( 'Rated 4.9/5 by 120+ teams', 'postfolio-blocks' ); ?></p>
     115<!-- /wp:paragraph --></div>
     116<!-- /wp:group --></div>
     117<!-- /wp:column -->
     118
     119<!-- wp:column {"verticalAlignment":"center","width":"46%","className":"postfolio-hero-visual"} -->
     120<div class="wp-block-column is-vertically-aligned-center postfolio-hero-visual" style="flex-basis:46%"><!-- wp:image {"aspectRatio":"4/5","scale":"cover","sizeSlug":"full","style":{"border":{"radius":"1.75rem"}}} -->
     121<figure class="wp-block-image size-full has-custom-border"><img src="<?php echo $postfolio_img( 'demo/design-studio.jpg' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>" alt="<?php esc_attr_e( 'Colour swatches and design tools on a studio desk', 'postfolio-blocks' ); ?>" style="border-radius:1.75rem;aspect-ratio:4/5;object-fit:cover"/></figure>
     122<!-- /wp:image -->
     123
     124<!-- wp:group {"className":"postfolio-hero-float","backgroundColor":"base","textColor":"contrast","style":{"spacing":{"padding":{"top":"1rem","bottom":"1rem","left":"1.25rem","right":"1.25rem"},"blockGap":"0.15rem"},"border":{"radius":"1rem"}},"layout":{"type":"default"}} -->
     125<div class="wp-block-group postfolio-hero-float has-contrast-color has-base-background-color has-text-color has-background" style="border-radius:1rem;padding-top:1rem;padding-right:1.25rem;padding-bottom:1rem;padding-left:1.25rem"><!-- wp:paragraph {"textColor":"accent","style":{"typography":{"fontSize":"1.75rem","fontWeight":"800","lineHeight":"1.1"}}} -->
     126<p class="has-accent-color has-text-color" style="font-size:1.75rem;font-weight:800;line-height:1.1">+140%</p>
     127<!-- /wp:paragraph -->
     128
     129<!-- wp:paragraph {"fontSize":"small"} -->
     130<p class="has-small-font-size"><?php esc_html_e( 'average growth in online sales', 'postfolio-blocks' ); ?></p>
     131<!-- /wp:paragraph --></div>
     132<!-- /wp:group --></div>
     133<!-- /wp:column --></div>
     134<!-- /wp:columns --></div>
     135<!-- /wp:group -->
     136
     137<!-- wp:pattern {"slug":"postfolio-blocks/logo-cloud"} /-->
     138
     139<!-- wp:group {"align":"full","style":{"spacing":{"padding":{"top":"var:preset|spacing|60","bottom":"var:preset|spacing|60","left":"var:preset|spacing|20","right":"var:preset|spacing|20"},"blockGap":"var:preset|spacing|40"}},"layout":{"type":"constrained"}} -->
     140<div class="wp-block-group alignfull" style="padding-top:var(--wp--preset--spacing--60);padding-right:var(--wp--preset--spacing--20);padding-bottom:var(--wp--preset--spacing--60);padding-left:var(--wp--preset--spacing--20)"><!-- wp:group {"style":{"spacing":{"blockGap":"0.75rem"}},"layout":{"type":"flex","orientation":"vertical","justifyContent":"center"}} -->
     141<div class="wp-block-group"><!-- wp:paragraph {"className":"postfolio-badge"} -->
     142<p class="postfolio-badge"><?php esc_html_e( 'What we do', 'postfolio-blocks' ); ?></p>
     143<!-- /wp:paragraph -->
     144
     145<!-- wp:heading {"textAlign":"center","fontSize":"huge"} -->
     146<h2 class="wp-block-heading has-text-align-center has-huge-font-size"><?php esc_html_e( 'Services built around your goals', 'postfolio-blocks' ); ?></h2>
     147<!-- /wp:heading -->
     148
     149<!-- wp:paragraph {"align":"center","textColor":"contrast-2","fontSize":"large"} -->
     150<p class="has-text-align-center has-contrast-2-color has-text-color has-large-font-size"><?php esc_html_e( 'One senior team from the first workshop to launch day — and beyond.', 'postfolio-blocks' ); ?></p>
     151<!-- /wp:paragraph --></div>
     152<!-- /wp:group -->
     153
     154<!-- wp:group {"align":"wide","className":"postfolio-services","style":{"spacing":{"blockGap":"1.25rem"}},"layout":{"type":"grid","columnCount":3,"minimumColumnWidth":"16rem"}} -->
     155<div class="wp-block-group alignwide postfolio-services"><?php foreach ( $postfolio_services as $postfolio_service ) : ?><!-- wp:group {"className":"postfolio-service-card","style":{"spacing":{"padding":{"top":"var:preset|spacing|30","bottom":"var:preset|spacing|30","left":"var:preset|spacing|30","right":"var:preset|spacing|30"},"blockGap":"0.75rem"},"border":{"radius":"1.25rem","width":"1px","color":"var:preset|color|base-2"}},"layout":{"type":"default"}} -->
     156<div class="wp-block-group postfolio-service-card has-border-color" style="border-color:var(--wp--preset--color--base-2);border-width:1px;border-radius:1.25rem;padding-top:var(--wp--preset--spacing--30);padding-right:var(--wp--preset--spacing--30);padding-bottom:var(--wp--preset--spacing--30);padding-left:var(--wp--preset--spacing--30)"><!-- wp:paragraph {"className":"postfolio-service-icon"} -->
     157<p class="postfolio-service-icon"><?php echo esc_html( $postfolio_service[0] ); ?></p>
     158<!-- /wp:paragraph -->
     159
     160<!-- wp:heading {"level":3,"fontSize":"x-large"} -->
     161<h3 class="wp-block-heading has-x-large-font-size"><?php echo esc_html( $postfolio_service[1] ); ?></h3>
     162<!-- /wp:heading -->
     163
     164<!-- wp:paragraph {"textColor":"contrast-2"} -->
     165<p class="has-contrast-2-color has-text-color"><?php echo esc_html( $postfolio_service[2] ); ?></p>
     166<!-- /wp:paragraph -->
     167
     168<!-- wp:paragraph {"className":"postfolio-more-link","fontSize":"small"} -->
     169<p class="postfolio-more-link has-small-font-size"><a href="<?php echo esc_url( $postfolio_services_url ); ?>"><?php esc_html_e( 'Learn more →', 'postfolio-blocks' ); ?></a></p>
     170<!-- /wp:paragraph --></div>
     171<!-- /wp:group --><?php endforeach; ?></div>
     172<!-- /wp:group --></div>
     173<!-- /wp:group -->
     174
     175<!-- wp:group {"anchor":"work","align":"full","backgroundColor":"base-2","style":{"spacing":{"padding":{"top":"var:preset|spacing|60","bottom":"var:preset|spacing|60","left":"var:preset|spacing|20","right":"var:preset|spacing|20"},"blockGap":"var:preset|spacing|40"}},"layout":{"type":"constrained"}} -->
     176<div id="work" class="wp-block-group alignfull has-base-2-background-color has-background" style="padding-top:var(--wp--preset--spacing--60);padding-right:var(--wp--preset--spacing--20);padding-bottom:var(--wp--preset--spacing--60);padding-left:var(--wp--preset--spacing--20)"><!-- wp:group {"align":"wide","layout":{"type":"flex","flexWrap":"wrap","justifyContent":"space-between","verticalAlignment":"bottom"}} -->
     177<div class="wp-block-group alignwide"><!-- wp:group {"style":{"spacing":{"blockGap":"0.75rem"}},"layout":{"type":"flex","orientation":"vertical"}} -->
     178<div class="wp-block-group"><!-- wp:paragraph {"className":"postfolio-badge","backgroundColor":"base"} -->
     179<p class="postfolio-badge has-base-background-color has-background"><?php esc_html_e( 'Selected work', 'postfolio-blocks' ); ?></p>
     180<!-- /wp:paragraph -->
     181
     182<!-- wp:heading {"fontSize":"huge"} -->
     183<h2 class="wp-block-heading has-huge-font-size"><?php esc_html_e( 'Results we are proud of', 'postfolio-blocks' ); ?></h2>
     184<!-- /wp:heading --></div>
     185<!-- /wp:group -->
     186
     187<!-- wp:buttons -->
     188<div class="wp-block-buttons"><!-- wp:button {"className":"is-style-outline"} -->
     189<div class="wp-block-button is-style-outline"><a class="wp-block-button__link wp-element-button" href="<?php echo esc_url( $postfolio_services_url ); ?>"><?php esc_html_e( 'All case studies', 'postfolio-blocks' ); ?></a></div>
    41190<!-- /wp:button --></div>
    42191<!-- /wp:buttons --></div>
    43 <!-- /wp:group --></div></div>
    44 <!-- /wp:cover -->
    45 
    46 <!-- wp:pattern {"slug":"postfolio-blocks/logo-cloud"} /-->
    47 
    48 <!-- wp:pattern {"slug":"postfolio-blocks/features-grid"} /-->
    49 
    50 <!-- wp:pattern {"slug":"postfolio-blocks/process-steps"} /-->
     192<!-- /wp:group -->
     193
     194<!-- wp:group {"align":"wide","className":"postfolio-work-grid","style":{"spacing":{"blockGap":"var:preset|spacing|40"}},"layout":{"type":"grid","columnCount":2,"minimumColumnWidth":"20rem"}} -->
     195<div class="wp-block-group alignwide postfolio-work-grid"><?php foreach ( $postfolio_work as $postfolio_project ) : ?><!-- wp:group {"className":"postfolio-work-card postfolio-story-card","style":{"spacing":{"blockGap":"0.6rem"}},"layout":{"type":"default"}} -->
     196<div class="wp-block-group postfolio-work-card postfolio-story-card"><!-- wp:image {"aspectRatio":"4/3","scale":"cover","sizeSlug":"full","className":"wp-block-post-featured-image","style":{"border":{"radius":"1.25rem"}}} -->
     197<figure class="wp-block-image size-full has-custom-border wp-block-post-featured-image"><img src="<?php echo $postfolio_img( $postfolio_project[0] ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>" alt="<?php echo esc_attr( $postfolio_project[1] ); ?>" style="border-radius:1.25rem;aspect-ratio:4/3;object-fit:cover"/></figure>
     198<!-- /wp:image -->
     199
     200<!-- wp:group {"style":{"spacing":{"blockGap":"0.5rem","margin":{"top":"0.5rem"}}},"layout":{"type":"flex","flexWrap":"wrap","justifyContent":"space-between","verticalAlignment":"center"}} -->
     201<div class="wp-block-group" style="margin-top:0.5rem"><!-- wp:heading {"level":3,"fontSize":"x-large"} -->
     202<h3 class="wp-block-heading has-x-large-font-size"><?php echo esc_html( $postfolio_project[1] ); ?></h3>
     203<!-- /wp:heading -->
     204
     205<!-- wp:paragraph {"className":"postfolio-result-pill","fontSize":"small"} -->
     206<p class="postfolio-result-pill has-small-font-size"><?php echo esc_html( $postfolio_project[3] ); ?></p>
     207<!-- /wp:paragraph --></div>
     208<!-- /wp:group -->
     209
     210<!-- wp:paragraph {"textColor":"contrast-2"} -->
     211<p class="has-contrast-2-color has-text-color"><?php echo esc_html( $postfolio_project[2] ); ?></p>
     212<!-- /wp:paragraph --></div>
     213<!-- /wp:group --><?php endforeach; ?></div>
     214<!-- /wp:group --></div>
     215<!-- /wp:group -->
     216
     217<!-- wp:group {"align":"full","style":{"spacing":{"padding":{"top":"var:preset|spacing|60","bottom":"var:preset|spacing|60","left":"var:preset|spacing|20","right":"var:preset|spacing|20"},"blockGap":"var:preset|spacing|40"}},"layout":{"type":"constrained"}} -->
     218<div class="wp-block-group alignfull" style="padding-top:var(--wp--preset--spacing--60);padding-right:var(--wp--preset--spacing--20);padding-bottom:var(--wp--preset--spacing--60);padding-left:var(--wp--preset--spacing--20)"><!-- wp:group {"style":{"spacing":{"blockGap":"0.75rem"}},"layout":{"type":"flex","orientation":"vertical","justifyContent":"center"}} -->
     219<div class="wp-block-group"><!-- wp:paragraph {"className":"postfolio-badge"} -->
     220<p class="postfolio-badge"><?php esc_html_e( 'How we work', 'postfolio-blocks' ); ?></p>
     221<!-- /wp:paragraph -->
     222
     223<!-- wp:heading {"textAlign":"center","fontSize":"huge"} -->
     224<h2 class="wp-block-heading has-text-align-center has-huge-font-size"><?php esc_html_e( 'A clear path from idea to launch', 'postfolio-blocks' ); ?></h2>
     225<!-- /wp:heading --></div>
     226<!-- /wp:group -->
     227
     228<!-- wp:group {"align":"wide","className":"postfolio-steps","style":{"spacing":{"blockGap":"1.25rem"}},"layout":{"type":"grid","minimumColumnWidth":"14rem"}} -->
     229<div class="wp-block-group alignwide postfolio-steps"><?php foreach ( $postfolio_steps as $postfolio_step ) : ?><!-- wp:group {"className":"postfolio-step","style":{"spacing":{"blockGap":"0.6rem"}},"layout":{"type":"default"}} -->
     230<div class="wp-block-group postfolio-step"><!-- wp:paragraph {"className":"postfolio-step__number"} -->
     231<p class="postfolio-step__number"><?php echo esc_html( $postfolio_step[0] ); ?></p>
     232<!-- /wp:paragraph -->
     233
     234<!-- wp:heading {"level":3,"fontSize":"x-large"} -->
     235<h3 class="wp-block-heading has-x-large-font-size"><?php echo esc_html( $postfolio_step[1] ); ?></h3>
     236<!-- /wp:heading -->
     237
     238<!-- wp:paragraph {"textColor":"contrast-2"} -->
     239<p class="has-contrast-2-color has-text-color"><?php echo esc_html( $postfolio_step[2] ); ?></p>
     240<!-- /wp:paragraph --></div>
     241<!-- /wp:group --><?php endforeach; ?></div>
     242<!-- /wp:group --></div>
     243<!-- /wp:group -->
    51244
    52245<!-- wp:pattern {"slug":"postfolio-blocks/stats-counters"} /-->
    53246
     247<!-- wp:group {"align":"full","style":{"spacing":{"padding":{"top":"var:preset|spacing|60","bottom":"var:preset|spacing|50","left":"var:preset|spacing|20","right":"var:preset|spacing|20"},"blockGap":"var:preset|spacing|40"}},"layout":{"type":"constrained"}} -->
     248<div class="wp-block-group alignfull" style="padding-top:var(--wp--preset--spacing--60);padding-right:var(--wp--preset--spacing--20);padding-bottom:var(--wp--preset--spacing--50);padding-left:var(--wp--preset--spacing--20)"><!-- wp:group {"style":{"spacing":{"blockGap":"0.75rem"}},"layout":{"type":"flex","orientation":"vertical","justifyContent":"center"}} -->
     249<div class="wp-block-group"><!-- wp:paragraph {"className":"postfolio-badge"} -->
     250<p class="postfolio-badge"><?php esc_html_e( 'Our team', 'postfolio-blocks' ); ?></p>
     251<!-- /wp:paragraph -->
     252
     253<!-- wp:heading {"textAlign":"center","fontSize":"huge"} -->
     254<h2 class="wp-block-heading has-text-align-center has-huge-font-size"><?php esc_html_e( 'The people behind the work', 'postfolio-blocks' ); ?></h2>
     255<!-- /wp:heading -->
     256
     257<!-- wp:paragraph {"align":"center","textColor":"contrast-2","fontSize":"large"} -->
     258<p class="has-text-align-center has-contrast-2-color has-text-color has-large-font-size"><?php esc_html_e( 'Small on purpose: you always work with the senior people you meet.', 'postfolio-blocks' ); ?></p>
     259<!-- /wp:paragraph --></div>
     260<!-- /wp:group -->
     261
     262<!-- wp:group {"align":"wide","className":"postfolio-team","style":{"spacing":{"blockGap":"1.25rem"}},"layout":{"type":"grid","minimumColumnWidth":"13rem"}} -->
     263<div class="wp-block-group alignwide postfolio-team"><?php foreach ( $postfolio_team as $postfolio_person ) : ?><!-- wp:group {"className":"postfolio-team-card","style":{"spacing":{"blockGap":"0.25rem"}},"layout":{"type":"default"}} -->
     264<div class="wp-block-group postfolio-team-card"><!-- wp:image {"aspectRatio":"4/5","scale":"cover","sizeSlug":"full","style":{"border":{"radius":"1.25rem"},"spacing":{"margin":{"bottom":"0.75rem"}}}} -->
     265<figure class="wp-block-image size-full has-custom-border" style="margin-bottom:0.75rem"><img src="<?php echo $postfolio_img( $postfolio_person[0] ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>" alt="<?php echo esc_attr( $postfolio_person[1] ); ?>" style="border-radius:1.25rem;aspect-ratio:4/5;object-fit:cover"/></figure>
     266<!-- /wp:image -->
     267
     268<!-- wp:heading {"level":3,"fontSize":"large"} -->
     269<h3 class="wp-block-heading has-large-font-size"><?php echo esc_html( $postfolio_person[1] ); ?></h3>
     270<!-- /wp:heading -->
     271
     272<!-- wp:paragraph {"textColor":"contrast-2","fontSize":"small"} -->
     273<p class="has-contrast-2-color has-text-color has-small-font-size"><?php echo esc_html( $postfolio_person[2] ); ?></p>
     274<!-- /wp:paragraph --></div>
     275<!-- /wp:group --><?php endforeach; ?></div>
     276<!-- /wp:group --></div>
     277<!-- /wp:group -->
     278
    54279<!-- wp:pattern {"slug":"postfolio-blocks/testimonial-spotlight"} /-->
    55280
    56 <!-- wp:pattern {"slug":"postfolio-blocks/pricing-simple"} /-->
     281<!-- wp:group {"align":"full","style":{"spacing":{"padding":{"top":"var:preset|spacing|60","bottom":"var:preset|spacing|60","left":"var:preset|spacing|20","right":"var:preset|spacing|20"},"blockGap":"var:preset|spacing|40"}},"layout":{"type":"constrained"}} -->
     282<div class="wp-block-group alignfull" style="padding-top:var(--wp--preset--spacing--60);padding-right:var(--wp--preset--spacing--20);padding-bottom:var(--wp--preset--spacing--60);padding-left:var(--wp--preset--spacing--20)"><!-- wp:group {"style":{"spacing":{"blockGap":"0.75rem"}},"layout":{"type":"flex","orientation":"vertical","justifyContent":"center"}} -->
     283<div class="wp-block-group"><!-- wp:paragraph {"className":"postfolio-badge"} -->
     284<p class="postfolio-badge"><?php esc_html_e( 'Pricing', 'postfolio-blocks' ); ?></p>
     285<!-- /wp:paragraph -->
     286
     287<!-- wp:heading {"textAlign":"center","fontSize":"huge"} -->
     288<h2 class="wp-block-heading has-text-align-center has-huge-font-size"><?php esc_html_e( 'Simple, honest pricing', 'postfolio-blocks' ); ?></h2>
     289<!-- /wp:heading -->
     290
     291<!-- wp:paragraph {"align":"center","textColor":"contrast-2","fontSize":"large"} -->
     292<p class="has-text-align-center has-contrast-2-color has-text-color has-large-font-size"><?php esc_html_e( 'Fixed prices, clear scope. No hourly surprises.', 'postfolio-blocks' ); ?></p>
     293<!-- /wp:paragraph --></div>
     294<!-- /wp:group -->
     295
     296<!-- wp:group {"align":"wide","className":"postfolio-pricing","style":{"spacing":{"blockGap":"1.25rem"}},"layout":{"type":"grid","minimumColumnWidth":"17rem"}} -->
     297<div class="wp-block-group alignwide postfolio-pricing"><?php foreach ( $postfolio_plans as $postfolio_plan ) : ?><!-- wp:group {"className":"postfolio-plan<?php echo $postfolio_plan['featured'] ? ' is-featured' : ''; ?>",<?php echo $postfolio_plan['featured'] ? '"backgroundColor":"contrast","textColor":"base",' : ''; ?>"style":{"spacing":{"padding":{"top":"var:preset|spacing|40","bottom":"var:preset|spacing|40","left":"var:preset|spacing|30","right":"var:preset|spacing|30"},"blockGap":"1rem"},"border":{"radius":"1.5rem","width":"1px","color":"var:preset|color|base-2"}},"layout":{"type":"flex","orientation":"vertical","justifyContent":"stretch"}} -->
     298<div class="wp-block-group postfolio-plan<?php echo $postfolio_plan['featured'] ? ' is-featured has-base-color has-contrast-background-color has-text-color has-background' : ''; ?> has-border-color" style="border-color:var(--wp--preset--color--base-2);border-width:1px;border-radius:1.5rem;padding-top:var(--wp--preset--spacing--40);padding-right:var(--wp--preset--spacing--30);padding-bottom:var(--wp--preset--spacing--40);padding-left:var(--wp--preset--spacing--30)"><!-- wp:group {"layout":{"type":"flex","flexWrap":"wrap","justifyContent":"space-between","verticalAlignment":"center"}} -->
     299<div class="wp-block-group"><!-- wp:heading {"level":3,"fontSize":"x-large"} -->
     300<h3 class="wp-block-heading has-x-large-font-size"><?php echo esc_html( $postfolio_plan['name'] ); ?></h3>
     301<!-- /wp:heading --><?php if ( $postfolio_plan['featured'] ) : ?>
     302
     303<!-- wp:paragraph {"className":"postfolio-plan__badge","fontSize":"small"} -->
     304<p class="postfolio-plan__badge has-small-font-size"><?php esc_html_e( 'Most popular', 'postfolio-blocks' ); ?></p>
     305<!-- /wp:paragraph --><?php endif; ?></div>
     306<!-- /wp:group -->
     307
     308<!-- wp:paragraph {"className":"postfolio-muted"} -->
     309<p class="postfolio-muted"><?php echo esc_html( $postfolio_plan['desc'] ); ?></p>
     310<!-- /wp:paragraph -->
     311
     312<!-- wp:paragraph {"className":"postfolio-plan__price"} -->
     313<p class="postfolio-plan__price"><strong><?php echo esc_html( $postfolio_plan['price'] ); ?></strong> <span><?php echo esc_html( $postfolio_plan['unit'] ); ?></span></p>
     314<!-- /wp:paragraph -->
     315
     316<!-- wp:list {"className":"postfolio-checklist"} -->
     317<ul class="wp-block-list postfolio-checklist"><?php foreach ( $postfolio_plan['features'] as $postfolio_feature ) : ?><!-- wp:list-item -->
     318<li><?php echo esc_html( $postfolio_feature ); ?></li>
     319<!-- /wp:list-item --><?php endforeach; ?></ul>
     320<!-- /wp:list -->
     321
     322<!-- wp:buttons {"className":"postfolio-plan__cta"} -->
     323<div class="wp-block-buttons postfolio-plan__cta"><!-- wp:button {"width":100<?php echo $postfolio_plan['featured'] ? ',"backgroundColor":"accent","textColor":"base"' : ',"className":"is-style-outline"'; ?>} -->
     324<div class="wp-block-button has-custom-width wp-block-button__width-100<?php echo $postfolio_plan['featured'] ? '' : ' is-style-outline'; ?>"><a class="wp-block-button__link<?php echo $postfolio_plan['featured'] ? ' has-base-color has-accent-background-color has-text-color has-background' : ''; ?> wp-element-button" href="<?php echo esc_url( $postfolio_contact ); ?>"><?php echo $postfolio_plan['featured'] ? esc_html__( 'Get started', 'postfolio-blocks' ) : esc_html__( 'Talk to us', 'postfolio-blocks' ); ?></a></div>
     325<!-- /wp:button --></div>
     326<!-- /wp:buttons --></div>
     327<!-- /wp:group --><?php endforeach; ?></div>
     328<!-- /wp:group --></div>
     329<!-- /wp:group -->
    57330
    58331<!-- wp:pattern {"slug":"postfolio-blocks/faq-modern"} /-->
  • postfolio-blocks/1.2.0/patterns/page-portfolio-starter.php

    r352228 r353530  
    11<?php
    22/**
    3  * Title: Page: portfolio
     3 * Title: Page: Portfolio work
    44 * Slug: postfolio-blocks/page-portfolio-starter
    5  * Categories: postfolio-blocks, postfolio-blocks-pages
    6  * Keywords: portfolio, work, projects
    7  * Description: A portfolio page with an intro, project grid, case study, client logos and a call to action.
    8  * Block Types: core/post-content
    9  * Post Types: page
    10  * Viewport Width: 1400
     5 * Categories: postfolio-blocks, postfolio-blocks-pages, postfolio-blocks-showcase
     6 * Keywords: portfolio, work, projects, case studies, grid
     7 * Description: A work index page: intro, a grid of every post in the "Work" category (each opens as a case study), client logos, a testimonial and a closing call to action.
    118 * Inserter: true
    129 *
    … …  
    1714        exit; // Exit if accessed directly.
    1815}
     16
     17$postfolio_work_id  = postfolio_blocks_demo_term_id( 'work' );
     18$postfolio_work_tax = $postfolio_work_id ? ',"taxQuery":{"category":[' . $postfolio_work_id . ']}' : '';
    1919?>
    20 <!-- wp:group {"align":"full","style":{"spacing":{"padding":{"top":"var:preset|spacing|60","bottom":"var:preset|spacing|20","left":"var:preset|spacing|20","right":"var:preset|spacing|20"}}},"layout":{"type":"constrained"}} -->
    21 <div class="wp-block-group alignfull" style="padding-top:var(--wp--preset--spacing--60);padding-right:var(--wp--preset--spacing--20);padding-bottom:var(--wp--preset--spacing--20);padding-left:var(--wp--preset--spacing--20)"><!-- wp:group {"style":{"spacing":{"blockGap":"1.25rem"}},"layout":{"type":"constrained","contentSize":"760px"}} -->
    22 <div class="wp-block-group"><!-- wp:paragraph {"align":"center","className":"postfolio-badge"} -->
    23 <p class="has-text-align-center postfolio-badge"><?php esc_html_e( 'Portfolio', 'postfolio-blocks' ); ?></p>
     20<!-- wp:group {"align":"full","style":{"spacing":{"padding":{"top":"var:preset|spacing|60","bottom":"var:preset|spacing|60","left":"var:preset|spacing|20","right":"var:preset|spacing|20"},"blockGap":"var:preset|spacing|50"}},"layout":{"type":"constrained"}} -->
     21<div class="wp-block-group alignfull" style="padding-top:var(--wp--preset--spacing--60);padding-right:var(--wp--preset--spacing--20);padding-bottom:var(--wp--preset--spacing--60);padding-left:var(--wp--preset--spacing--20)"><!-- wp:group {"align":"wide","style":{"spacing":{"blockGap":"1rem","padding":{"bottom":"var:preset|spacing|40"}},"border":{"bottom":{"color":"var:preset|color|base-2","width":"1px"}}},"layout":{"type":"flex","orientation":"vertical"}} -->
     22<div class="wp-block-group alignwide" style="border-bottom-color:var(--wp--preset--color--base-2);border-bottom-width:1px;padding-bottom:var(--wp--preset--spacing--40)"><!-- wp:paragraph {"className":"postfolio-badge"} -->
     23<p class="postfolio-badge"><?php esc_html_e( 'Portfolio', 'postfolio-blocks' ); ?></p>
    2424<!-- /wp:paragraph -->
    2525
    26 <!-- wp:heading {"textAlign":"center","level":1,"fontSize":"huge"} -->
    27 <h1 class="wp-block-heading has-text-align-center has-huge-font-size"><?php esc_html_e( 'Work that speaks for itself.', 'postfolio-blocks' ); ?></h1>
     26<!-- wp:heading {"level":1,"style":{"typography":{"fontSize":"clamp(2.4rem, 1.5rem + 3.2vw, 4.4rem)","lineHeight":"1.05","letterSpacing":"-0.03em"}}} -->
     27<h1 class="wp-block-heading" style="font-size:clamp(2.4rem, 1.5rem + 3.2vw, 4.4rem);letter-spacing:-0.03em;line-height:1.05"><?php esc_html_e( 'Work that speaks for itself.', 'postfolio-blocks' ); ?></h1>
    2828<!-- /wp:heading -->
    2929
    30 <!-- wp:paragraph {"align":"center","textColor":"contrast-2","fontSize":"large"} -->
    31 <p class="has-text-align-center has-contrast-2-color has-text-color has-large-font-size"><?php esc_html_e( 'A selection of projects for startups, studios and established brands.', 'postfolio-blocks' ); ?></p>
     30<!-- wp:paragraph {"className":"postfolio-lede","textColor":"contrast-2","fontSize":"large"} -->
     31<p class="postfolio-lede has-contrast-2-color has-text-color has-large-font-size"><?php esc_html_e( 'Selected projects for startups, studios and established brands. Open any project to read the full case study — the challenge, the process and the results.', 'postfolio-blocks' ); ?></p>
    3232<!-- /wp:paragraph --></div>
    33 <!-- /wp:group --></div>
    3433<!-- /wp:group -->
    3534
    36 <!-- wp:pattern {"slug":"postfolio-blocks/portfolio-grid"} /-->
     35<!-- wp:query {"queryId":96,"query":{"perPage":12,"pages":0,"offset":0,"postType":"post","order":"desc","orderBy":"date","sticky":"","inherit":false<?php echo $postfolio_work_tax; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>},"align":"wide","layout":{"type":"default"}} -->
     36<div class="wp-block-query alignwide"><!-- wp:post-template {"layout":{"type":"grid","columnCount":2,"minimumColumnWidth":"20rem"}} -->
     37<!-- wp:group {"className":"postfolio-work-card postfolio-story-card","style":{"spacing":{"blockGap":"0.6rem"}},"layout":{"type":"default"}} -->
     38<div class="wp-block-group postfolio-work-card postfolio-story-card"><!-- wp:post-featured-image {"isLink":true,"aspectRatio":"4/3","style":{"border":{"radius":"1.25rem"}}} /-->
    3739
    38 <!-- wp:pattern {"slug":"postfolio-blocks/portfolio-case-study"} /-->
     40<!-- wp:post-terms {"term":"post_tag","className":"postfolio-tag-row","fontSize":"small","style":{"spacing":{"margin":{"top":"0.75rem"}}}} /-->
     41
     42<!-- wp:post-title {"level":2,"isLink":true,"fontSize":"x-large","style":{"typography":{"lineHeight":"1.2"}}} /-->
     43
     44<!-- wp:post-excerpt {"excerptLength":24,"textColor":"contrast-2"} /--></div>
     45<!-- /wp:group -->
     46<!-- /wp:post-template -->
     47
     48<!-- wp:query-no-results -->
     49<!-- wp:paragraph {"textColor":"contrast-2"} -->
     50<p class="has-contrast-2-color has-text-color"><?php esc_html_e( 'Add posts to the “Work” category to show your projects here.', 'postfolio-blocks' ); ?></p>
     51<!-- /wp:paragraph -->
     52<!-- /wp:query-no-results -->
     53
     54<!-- wp:query-pagination {"style":{"spacing":{"margin":{"top":"var:preset|spacing|40"}}},"layout":{"type":"flex","justifyContent":"space-between"}} -->
     55<!-- wp:query-pagination-previous /-->
     56
     57<!-- wp:query-pagination-numbers /-->
     58
     59<!-- wp:query-pagination-next /-->
     60<!-- /wp:query-pagination --></div>
     61<!-- /wp:query --></div>
     62<!-- /wp:group -->
    3963
    4064<!-- wp:pattern {"slug":"postfolio-blocks/logo-cloud"} /-->
    … …  
    4266<!-- wp:pattern {"slug":"postfolio-blocks/testimonial-spotlight"} /-->
    4367
    44 <!-- wp:pattern {"slug":"postfolio-blocks/cta-split-image"} /-->
     68<!-- wp:pattern {"slug":"postfolio-blocks/cta-portfolio"} /-->
  • postfolio-blocks/1.2.0/patterns/post-footer.php

    r352228 r353530  
    1717<div class="wp-block-group"><!-- wp:post-terms {"term":"post_tag","className":"is-style-pill"} /-->
    1818
    19 <!-- wp:group {"className":"postfolio-share-row","style":{"spacing":{"blockGap":"1rem"}},"layout":{"type":"flex","flexWrap":"wrap","verticalAlignment":"center"}} -->
    20 <div class="wp-block-group postfolio-share-row"><!-- wp:paragraph {"fontSize":"small"} -->
    21 <p class="has-small-font-size"><strong><?php esc_html_e( 'Share this post', 'postfolio-blocks' ); ?></strong></p>
     19<!-- wp:group {"className":"postfolio-share-row","style":{"spacing":{"padding":{"top":"1.25rem","bottom":"1.25rem","left":"var:preset|spacing|30","right":"var:preset|spacing|30"},"blockGap":"1rem"},"border":{"radius":"1.25rem","width":"1px","color":"var:preset|color|base-2"}},"layout":{"type":"flex","flexWrap":"wrap","justifyContent":"space-between","verticalAlignment":"center"}} -->
     20<div class="wp-block-group postfolio-share-row has-border-color" style="border-color:var(--wp--preset--color--base-2);border-width:1px;border-radius:1.25rem;padding-top:1.25rem;padding-right:var(--wp--preset--spacing--30);padding-bottom:1.25rem;padding-left:var(--wp--preset--spacing--30)"><!-- wp:paragraph {"style":{"typography":{"fontWeight":"700"}}} -->
     21<p style="font-weight:700"><?php esc_html_e( 'Share this post', 'postfolio-blocks' ); ?></p>
    2222<!-- /wp:paragraph -->
    2323
    24 <!-- wp:social-links {"openInNewTab":true,"size":"has-normal-icon-size","className":"postfolio-share"} -->
    25 <ul class="wp-block-social-links has-normal-icon-size postfolio-share"><!-- wp:social-link {"url":"https://x.com/","service":"x"} /-->
     24<!-- wp:social-links {"openInNewTab":true,"size":"has-normal-icon-size","className":"postfolio-share","style":{"spacing":{"blockGap":{"left":"0.6rem"}}}} -->
     25<ul class="wp-block-social-links has-normal-icon-size postfolio-share"><!-- wp:social-link {"url":"https://www.facebook.com/","service":"facebook"} /-->
    2626
    27 <!-- wp:social-link {"url":"https://www.facebook.com/","service":"facebook"} /-->
     27<!-- wp:social-link {"url":"https://x.com/","service":"x"} /-->
    2828
    2929<!-- wp:social-link {"url":"https://www.linkedin.com/","service":"linkedin"} /-->
    3030
    31 <!-- wp:social-link {"url":"https://www.whatsapp.com/","service":"whatsapp"} /-->
     31<!-- wp:social-link {"url":"https://www.pinterest.com/","service":"pinterest"} /-->
    3232
    33 <!-- wp:social-link {"url":"mailto:hello@example.com","service":"mail"} /--></ul>
     33<!-- wp:social-link {"url":"https://www.reddit.com/","service":"reddit"} /-->
     34
     35<!-- wp:social-link {"url":"https://www.whatsapp.com/","service":"whatsapp"} /--></ul>
    3436<!-- /wp:social-links --></div>
    3537<!-- /wp:group -->
    3638
    37 <!-- wp:group {"backgroundColor":"base-2","style":{"spacing":{"padding":{"top":"var:preset|spacing|30","bottom":"var:preset|spacing|30","left":"var:preset|spacing|30","right":"var:preset|spacing|30"},"blockGap":"1.25rem"},"border":{"radius":"1.25rem"}},"layout":{"type":"flex","flexWrap":"nowrap","verticalAlignment":"top"}} -->
    38 <div class="wp-block-group has-base-2-background-color has-background" style="border-radius:1.25rem;padding-top:var(--wp--preset--spacing--30);padding-right:var(--wp--preset--spacing--30);padding-bottom:var(--wp--preset--spacing--30);padding-left:var(--wp--preset--spacing--30)"><!-- wp:avatar {"size":64,"style":{"border":{"radius":"999px"}}} /-->
     39<!-- wp:group {"className":"postfolio-author-box","style":{"spacing":{"padding":{"top":"var:preset|spacing|30","bottom":"var:preset|spacing|30","left":"var:preset|spacing|30","right":"var:preset|spacing|30"},"blockGap":"1.5rem"},"border":{"radius":"1.25rem","width":"1px","color":"var:preset|color|base-2"}},"layout":{"type":"flex","flexWrap":"nowrap","verticalAlignment":"top"}} -->
     40<div class="wp-block-group postfolio-author-box has-border-color" style="border-color:var(--wp--preset--color--base-2);border-width:1px;border-radius:1.25rem;padding-top:var(--wp--preset--spacing--30);padding-right:var(--wp--preset--spacing--30);padding-bottom:var(--wp--preset--spacing--30);padding-left:var(--wp--preset--spacing--30)"><!-- wp:avatar {"size":72,"className":"postfolio-author-ring","style":{"border":{"radius":"999px"}}} /-->
    3941
    40 <!-- wp:group {"style":{"spacing":{"blockGap":"0.35rem"}},"layout":{"type":"constrained"}} -->
    41 <div class="wp-block-group"><!-- wp:paragraph {"textColor":"contrast-2","fontSize":"small"} -->
    42 <p class="has-contrast-2-color has-text-color has-small-font-size"><?php esc_html_e( 'Written by', 'postfolio-blocks' ); ?></p>
    43 <!-- /wp:paragraph -->
     42<!-- wp:group {"style":{"spacing":{"blockGap":"0.5rem"}},"layout":{"type":"flex","orientation":"vertical"}} -->
     43<div class="wp-block-group"><!-- wp:post-author-name {"isLink":true,"className":"postfolio-author-name","fontSize":"large"} /-->
    4444
    45 <!-- wp:post-author-name {"isLink":true,"fontSize":"large"} /-->
    46 
    47 <!-- wp:post-author-biography {"fontSize":"small"} /--></div>
     45<!-- wp:post-author-biography {"className":"postfolio-author-bio","textColor":"contrast-2"} /--></div>
    4846<!-- /wp:group --></div>
    4947<!-- /wp:group -->
  • postfolio-blocks/1.2.0/patterns/post-grid-cards.php

    r352228 r353530  
    1515?>
    1616<!-- wp:group {"align":"wide","style":{"spacing":{"margin":{"top":"var:preset|spacing|50","bottom":"var:preset|spacing|50"},"blockGap":"var:preset|spacing|30"}},"layout":{"type":"constrained"}} -->
    17 <div class="wp-block-group alignwide" style="margin-top:var(--wp--preset--spacing--50);margin-bottom:var(--wp--preset--spacing--50)"><!-- wp:group {"layout":{"type":"flex","justifyContent":"space-between","flexWrap":"wrap"}} -->
    18 <div class="wp-block-group"><!-- wp:heading {"fontSize":"xx-large"} -->
     17<div class="wp-block-group alignwide" style="margin-top:var(--wp--preset--spacing--50);margin-bottom:var(--wp--preset--spacing--50)"><!-- wp:group {"align":"wide","layout":{"type":"flex","justifyContent":"space-between","flexWrap":"wrap"}} -->
     18<div class="wp-block-group alignwide"><!-- wp:heading {"fontSize":"xx-large"} -->
    1919<h2 class="wp-block-heading has-xx-large-font-size"><?php esc_html_e( 'Latest stories', 'postfolio-blocks' ); ?></h2>
    2020<!-- /wp:heading -->
  • postfolio-blocks/1.2.0/patterns/post-meta.php

    r352228 r353530  
    1414}
    1515?>
    16 <!-- wp:group {"style":{"spacing":{"blockGap":"0.85rem"}},"layout":{"type":"constrained"}} -->
    17 <div class="wp-block-group"><!-- wp:post-terms {"term":"category","className":"is-style-pill"} /-->
     16<!-- wp:group {"className":"postfolio-post-header","style":{"spacing":{"blockGap":"1rem"}},"layout":{"type":"flex","orientation":"vertical","justifyContent":"center"}} -->
     17<div class="wp-block-group postfolio-post-header"><!-- wp:post-terms {"term":"category","textAlign":"center","className":"is-style-pill"} /-->
    1818
    19 <!-- wp:post-title {"level":1,"fontSize":"huge"} /-->
     19<!-- wp:post-title {"textAlign":"center","level":1,"fontSize":"huge"} /-->
    2020
    21 <!-- wp:group {"className":"postfolio-meta-row","style":{"spacing":{"blockGap":"0.6rem"}},"layout":{"type":"flex","flexWrap":"wrap","verticalAlignment":"center"}} -->
     21<!-- wp:group {"className":"postfolio-meta-row","style":{"spacing":{"blockGap":"0.6rem"}},"layout":{"type":"flex","flexWrap":"wrap","justifyContent":"center","verticalAlignment":"center"}} -->
    2222<div class="wp-block-group postfolio-meta-row"><!-- wp:avatar {"size":32,"style":{"border":{"radius":"999px"}}} /-->
    2323
  • postfolio-blocks/1.2.0/patterns/starter-portfolio-landing.php

    r352228 r353530  
    11<?php
    22/**
    3  * Title: Starter Site — Portfolio Landing Page
     3 * Title: Page: Portfolio home
    44 * Slug: postfolio-blocks/starter-portfolio-landing
    5  * Categories: postfolio-blocks-pages, postfolio-blocks
    6  * Description: Complete Portfolio landing page layout with Hero Banner, About, Services, Team and FAQ.
    7  * Keywords: starter, portfolio, landing page, agency, showcase
    8  * Block Types: core/post-content
    9  * Post Types: page
    10  * Viewport Width: 1400
     5 * Categories: postfolio-blocks, postfolio-blocks-pages, postfolio-blocks-showcase
     6 * Keywords: portfolio, designer, freelancer, homepage, work, case study
     7 * Description: A complete portfolio homepage: intro with availability and key numbers, client logos, selected work from the "Work" category, services, about and experience, a testimonial and a closing call to action. Every section shares the same wide width.
     8 * Inserter: true
    119 *
    1210 * @package Postfolio_Blocks
    … …  
    1614        exit; // Exit if accessed directly.
    1715}
     16
     17$postfolio_work_id  = postfolio_blocks_demo_term_id( 'work' );
     18$postfolio_work_tax = $postfolio_work_id ? ',"taxQuery":{"category":[' . $postfolio_work_id . ']}' : '';
     19
     20$postfolio_services = array(
     21        array( '01', __( 'Product design', 'postfolio-blocks' ), __( 'Research, flows and interfaces for apps and web products people enjoy using.', 'postfolio-blocks' ) ),
     22        array( '02', __( 'Brand identity', 'postfolio-blocks' ), __( 'Logos, type and colour systems with guidelines your team can actually follow.', 'postfolio-blocks' ) ),
     23        array( '03', __( 'Web design & build', 'postfolio-blocks' ), __( 'Fast, accessible WordPress sites that are easy to edit after launch.', 'postfolio-blocks' ) ),
     24);
     25
     26$postfolio_experience = array(
     27        array( __( '2023 — Now', 'postfolio-blocks' ), __( 'Independent designer', 'postfolio-blocks' ), __( 'Studio of one', 'postfolio-blocks' ) ),
     28        array( '2019 — 2023', __( 'Design lead', 'postfolio-blocks' ), 'Harbor Finance' ),
     29        array( '2016 — 2019', __( 'Senior product designer', 'postfolio-blocks' ), 'Northwind Labs' ),
     30        array( '2014 — 2016', __( 'Visual designer', 'postfolio-blocks' ), 'Atlas Studio' ),
     31);
    1832?>
    19 <!-- wp:pattern {"slug":"postfolio-blocks/hero-portfolio-intro"} /-->
     33<!-- wp:group {"align":"full","className":"postfolio-portfolio-hero","style":{"spacing":{"padding":{"top":"var:preset|spacing|60","bottom":"var:preset|spacing|60","left":"var:preset|spacing|20","right":"var:preset|spacing|20"}}},"layout":{"type":"constrained"}} -->
     34<div class="wp-block-group alignfull postfolio-portfolio-hero" style="padding-top:var(--wp--preset--spacing--60);padding-right:var(--wp--preset--spacing--20);padding-bottom:var(--wp--preset--spacing--60);padding-left:var(--wp--preset--spacing--20)"><!-- wp:columns {"verticalAlignment":"center","align":"wide","style":{"spacing":{"blockGap":{"left":"var:preset|spacing|50"}}}} -->
     35<div class="wp-block-columns alignwide are-vertically-aligned-center"><!-- wp:column {"verticalAlignment":"center","width":"58%","style":{"spacing":{"blockGap":"1.5rem"}}} -->
     36<div class="wp-block-column is-vertically-aligned-center" style="flex-basis:58%"><!-- wp:paragraph {"className":"postfolio-availability","fontSize":"small"} -->
     37<p class="postfolio-availability has-small-font-size"><?php esc_html_e( 'Available for new projects', 'postfolio-blocks' ); ?></p>
     38<!-- /wp:paragraph -->
    2039
    21 <!-- wp:pattern {"slug":"postfolio-blocks/about-me-skills-grid"} /-->
     40<!-- wp:heading {"level":1,"style":{"typography":{"fontSize":"clamp(2.4rem, 1.5rem + 3.2vw, 4.4rem)","lineHeight":"1.05","letterSpacing":"-0.03em"}}} -->
     41<h1 class="wp-block-heading" style="font-size:clamp(2.4rem, 1.5rem + 3.2vw, 4.4rem);letter-spacing:-0.03em;line-height:1.05"><?php esc_html_e( 'Hi, I’m Jordan — I design calm, useful', 'postfolio-blocks' ); ?> <mark class="has-inline-color has-accent-color" style="background-color:rgba(0,0,0,0)"><?php esc_html_e( 'digital products.', 'postfolio-blocks' ); ?></mark></h1>
     42<!-- /wp:heading -->
    2243
    23 <!-- wp:pattern {"slug":"postfolio-blocks/services-grid"} /-->
     44<!-- wp:paragraph {"textColor":"contrast-2","fontSize":"large"} -->
     45<p class="has-contrast-2-color has-text-color has-large-font-size"><?php esc_html_e( 'Product and brand designer helping startups and studios turn messy ideas into clear, beautiful work — from the first sketch to launch.', 'postfolio-blocks' ); ?></p>
     46<!-- /wp:paragraph -->
    2447
    25 <!-- wp:pattern {"slug":"postfolio-blocks/team-members-grid"} /-->
     48<!-- wp:buttons {"style":{"spacing":{"blockGap":"0.75rem"}}} -->
     49<div class="wp-block-buttons"><!-- wp:button {"backgroundColor":"accent","textColor":"base"} -->
     50<div class="wp-block-button"><a class="wp-block-button__link has-base-color has-accent-background-color has-text-color has-background wp-element-button" href="<?php echo esc_url( postfolio_blocks_starter_page_url( 'work' ) ); ?>"><?php esc_html_e( 'View my work', 'postfolio-blocks' ); ?></a></div>
     51<!-- /wp:button -->
    2652
    27 <!-- wp:pattern {"slug":"postfolio-blocks/faq-accordion"} /-->
     53<!-- wp:button {"className":"is-style-outline"} -->
     54<div class="wp-block-button is-style-outline"><a class="wp-block-button__link wp-element-button" href="<?php echo esc_url( postfolio_blocks_starter_page_url( 'contact' ) ); ?>"><?php esc_html_e( 'Get in touch', 'postfolio-blocks' ); ?></a></div>
     55<!-- /wp:button --></div>
     56<!-- /wp:buttons -->
     57
     58<!-- wp:group {"className":"postfolio-hero-stats","style":{"spacing":{"blockGap":"var:preset|spacing|40","padding":{"top":"var:preset|spacing|30"}},"border":{"top":{"color":"var:preset|color|base-2","width":"1px"}}},"layout":{"type":"flex","flexWrap":"wrap"}} -->
     59<div class="wp-block-group postfolio-hero-stats" style="border-top-color:var(--wp--preset--color--base-2);border-top-width:1px;padding-top:var(--wp--preset--spacing--30)"><?php foreach ( array( array( '10+', __( 'years designing', 'postfolio-blocks' ) ), array( '60+', __( 'projects shipped', 'postfolio-blocks' ) ), array( '12', __( 'design awards', 'postfolio-blocks' ) ) ) as $postfolio_stat ) : ?><!-- wp:paragraph -->
     60<p><strong><?php echo esc_html( $postfolio_stat[0] ); ?></strong> <?php echo esc_html( $postfolio_stat[1] ); ?></p>
     61<!-- /wp:paragraph --><?php endforeach; ?></div>
     62<!-- /wp:group --></div>
     63<!-- /wp:column -->
     64
     65<!-- wp:column {"verticalAlignment":"center","width":"42%","className":"postfolio-hero-visual"} -->
     66<div class="wp-block-column is-vertically-aligned-center postfolio-hero-visual" style="flex-basis:42%"><!-- wp:image {"aspectRatio":"4/5","scale":"cover","sizeSlug":"full","style":{"border":{"radius":"1.75rem"}}} -->
     67<figure class="wp-block-image size-full has-custom-border"><img src="<?php echo esc_url( get_theme_file_uri( 'assets/images/portrait-3.svg' ) ); ?>" alt="<?php esc_attr_e( 'Illustrated portrait of Jordan', 'postfolio-blocks' ); ?>" width="800" height="1000" style="border-radius:1.75rem;aspect-ratio:4/5;object-fit:cover"/></figure>
     68<!-- /wp:image -->
     69
     70<!-- wp:group {"className":"postfolio-hero-float","backgroundColor":"base","textColor":"contrast","style":{"spacing":{"padding":{"top":"0.9rem","bottom":"0.9rem","left":"1.1rem","right":"1.1rem"},"blockGap":"0.1rem"},"border":{"radius":"1rem"}},"layout":{"type":"default"}} -->
     71<div class="wp-block-group postfolio-hero-float has-contrast-color has-base-background-color has-text-color has-background" style="border-radius:1rem;padding-top:0.9rem;padding-right:1.1rem;padding-bottom:0.9rem;padding-left:1.1rem"><!-- wp:paragraph {"className":"postfolio-kicker","textColor":"accent","fontSize":"small"} -->
     72<p class="postfolio-kicker has-accent-color has-text-color has-small-font-size"><?php esc_html_e( 'Currently', 'postfolio-blocks' ); ?></p>
     73<!-- /wp:paragraph -->
     74
     75<!-- wp:paragraph {"style":{"typography":{"fontWeight":"600"}}} -->
     76<p style="font-weight:600"><?php esc_html_e( 'Designing a calmer banking app', 'postfolio-blocks' ); ?></p>
     77<!-- /wp:paragraph --></div>
     78<!-- /wp:group --></div>
     79<!-- /wp:column --></div>
     80<!-- /wp:columns --></div>
     81<!-- /wp:group -->
     82
     83<!-- wp:pattern {"slug":"postfolio-blocks/logo-cloud"} /-->
     84
     85<!-- wp:group {"align":"full","style":{"spacing":{"padding":{"top":"var:preset|spacing|60","bottom":"var:preset|spacing|60","left":"var:preset|spacing|20","right":"var:preset|spacing|20"},"blockGap":"var:preset|spacing|40"}},"layout":{"type":"constrained"}} -->
     86<div class="wp-block-group alignfull" style="padding-top:var(--wp--preset--spacing--60);padding-right:var(--wp--preset--spacing--20);padding-bottom:var(--wp--preset--spacing--60);padding-left:var(--wp--preset--spacing--20)"><!-- wp:group {"align":"wide","layout":{"type":"flex","flexWrap":"wrap","justifyContent":"space-between","verticalAlignment":"bottom"}} -->
     87<div class="wp-block-group alignwide"><!-- wp:group {"style":{"spacing":{"blockGap":"0.75rem"}},"layout":{"type":"flex","orientation":"vertical"}} -->
     88<div class="wp-block-group"><!-- wp:paragraph {"className":"postfolio-badge"} -->
     89<p class="postfolio-badge"><?php esc_html_e( 'Selected work', 'postfolio-blocks' ); ?></p>
     90<!-- /wp:paragraph -->
     91
     92<!-- wp:heading {"fontSize":"huge"} -->
     93<h2 class="wp-block-heading has-huge-font-size"><?php esc_html_e( 'Projects I’m proud of', 'postfolio-blocks' ); ?></h2>
     94<!-- /wp:heading --></div>
     95<!-- /wp:group -->
     96
     97<!-- wp:buttons -->
     98<div class="wp-block-buttons"><!-- wp:button {"className":"is-style-outline"} -->
     99<div class="wp-block-button is-style-outline"><a class="wp-block-button__link wp-element-button" href="<?php echo esc_url( postfolio_blocks_starter_page_url( 'work' ) ); ?>"><?php esc_html_e( 'All projects', 'postfolio-blocks' ); ?></a></div>
     100<!-- /wp:button --></div>
     101<!-- /wp:buttons --></div>
     102<!-- /wp:group -->
     103
     104<!-- wp:query {"queryId":95,"query":{"perPage":4,"pages":0,"offset":0,"postType":"post","order":"desc","orderBy":"date","sticky":"","inherit":false<?php echo $postfolio_work_tax; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>},"align":"wide","layout":{"type":"default"}} -->
     105<div class="wp-block-query alignwide"><!-- wp:post-template {"layout":{"type":"grid","columnCount":2,"minimumColumnWidth":"20rem"}} -->
     106<!-- wp:group {"className":"postfolio-work-card postfolio-story-card","style":{"spacing":{"blockGap":"0.6rem"}},"layout":{"type":"default"}} -->
     107<div class="wp-block-group postfolio-work-card postfolio-story-card"><!-- wp:post-featured-image {"isLink":true,"aspectRatio":"4/3","style":{"border":{"radius":"1.25rem"}}} /-->
     108
     109<!-- wp:post-terms {"term":"post_tag","className":"postfolio-tag-row","fontSize":"small","style":{"spacing":{"margin":{"top":"0.75rem"}}}} /-->
     110
     111<!-- wp:post-title {"level":3,"isLink":true,"fontSize":"x-large","style":{"typography":{"lineHeight":"1.2"}}} /-->
     112
     113<!-- wp:post-excerpt {"excerptLength":20,"textColor":"contrast-2"} /--></div>
     114<!-- /wp:group -->
     115<!-- /wp:post-template --></div>
     116<!-- /wp:query --></div>
     117<!-- /wp:group -->
     118
     119<!-- wp:group {"align":"full","backgroundColor":"base-2","style":{"spacing":{"padding":{"top":"var:preset|spacing|60","bottom":"var:preset|spacing|60","left":"var:preset|spacing|20","right":"var:preset|spacing|20"},"blockGap":"var:preset|spacing|40"}},"layout":{"type":"constrained"}} -->
     120<div class="wp-block-group alignfull has-base-2-background-color has-background" style="padding-top:var(--wp--preset--spacing--60);padding-right:var(--wp--preset--spacing--20);padding-bottom:var(--wp--preset--spacing--60);padding-left:var(--wp--preset--spacing--20)"><!-- wp:group {"align":"wide","style":{"spacing":{"blockGap":"0.75rem"}},"layout":{"type":"flex","orientation":"vertical"}} -->
     121<div class="wp-block-group alignwide"><!-- wp:paragraph {"className":"postfolio-badge","backgroundColor":"base"} -->
     122<p class="postfolio-badge has-base-background-color has-background"><?php esc_html_e( 'What I do', 'postfolio-blocks' ); ?></p>
     123<!-- /wp:paragraph -->
     124
     125<!-- wp:heading {"fontSize":"huge"} -->
     126<h2 class="wp-block-heading has-huge-font-size"><?php esc_html_e( 'Ways we can work together', 'postfolio-blocks' ); ?></h2>
     127<!-- /wp:heading --></div>
     128<!-- /wp:group -->
     129
     130<!-- wp:group {"align":"wide","className":"postfolio-services","style":{"spacing":{"blockGap":"1.25rem"}},"layout":{"type":"grid","columnCount":3,"minimumColumnWidth":"16rem"}} -->
     131<div class="wp-block-group alignwide postfolio-services"><?php foreach ( $postfolio_services as $postfolio_service ) : ?><!-- wp:group {"className":"postfolio-service-card","backgroundColor":"base","style":{"spacing":{"padding":{"top":"var:preset|spacing|30","bottom":"var:preset|spacing|30","left":"var:preset|spacing|30","right":"var:preset|spacing|30"},"blockGap":"0.75rem"},"border":{"radius":"1.25rem","width":"1px","color":"var:preset|color|base-2"}},"layout":{"type":"default"}} -->
     132<div class="wp-block-group postfolio-service-card has-border-color has-base-background-color has-background" style="border-color:var(--wp--preset--color--base-2);border-width:1px;border-radius:1.25rem;padding-top:var(--wp--preset--spacing--30);padding-right:var(--wp--preset--spacing--30);padding-bottom:var(--wp--preset--spacing--30);padding-left:var(--wp--preset--spacing--30)"><!-- wp:paragraph {"className":"postfolio-service-icon"} -->
     133<p class="postfolio-service-icon"><?php echo esc_html( $postfolio_service[0] ); ?></p>
     134<!-- /wp:paragraph -->
     135
     136<!-- wp:heading {"level":3,"fontSize":"x-large"} -->
     137<h3 class="wp-block-heading has-x-large-font-size"><?php echo esc_html( $postfolio_service[1] ); ?></h3>
     138<!-- /wp:heading -->
     139
     140<!-- wp:paragraph {"textColor":"contrast-2"} -->
     141<p class="has-contrast-2-color has-text-color"><?php echo esc_html( $postfolio_service[2] ); ?></p>
     142<!-- /wp:paragraph --></div>
     143<!-- /wp:group --><?php endforeach; ?></div>
     144<!-- /wp:group --></div>
     145<!-- /wp:group -->
     146
     147<!-- wp:group {"align":"full","style":{"spacing":{"padding":{"top":"var:preset|spacing|60","bottom":"var:preset|spacing|60","left":"var:preset|spacing|20","right":"var:preset|spacing|20"}}},"layout":{"type":"constrained"}} -->
     148<div class="wp-block-group alignfull" style="padding-top:var(--wp--preset--spacing--60);padding-right:var(--wp--preset--spacing--20);padding-bottom:var(--wp--preset--spacing--60);padding-left:var(--wp--preset--spacing--20)"><!-- wp:columns {"align":"wide","style":{"spacing":{"blockGap":{"left":"var:preset|spacing|50"}}}} -->
     149<div class="wp-block-columns alignwide"><!-- wp:column {"width":"50%","style":{"spacing":{"blockGap":"1.25rem"}}} -->
     150<div class="wp-block-column" style="flex-basis:50%"><!-- wp:paragraph {"className":"postfolio-badge"} -->
     151<p class="postfolio-badge"><?php esc_html_e( 'About', 'postfolio-blocks' ); ?></p>
     152<!-- /wp:paragraph -->
     153
     154<!-- wp:heading {"fontSize":"huge"} -->
     155<h2 class="wp-block-heading has-huge-font-size"><?php esc_html_e( 'Design that feels obvious — afterwards.', 'postfolio-blocks' ); ?></h2>
     156<!-- /wp:heading -->
     157
     158<!-- wp:paragraph {"textColor":"contrast-2","fontSize":"large"} -->
     159<p class="has-contrast-2-color has-text-color has-large-font-size"><?php esc_html_e( 'For over ten years I have helped teams simplify complicated products. I start with the people who will use the thing, keep the process open, and ship work that holds up long after launch.', 'postfolio-blocks' ); ?></p>
     160<!-- /wp:paragraph -->
     161
     162<!-- wp:paragraph {"textColor":"contrast-2"} -->
     163<p class="has-contrast-2-color has-text-color"><?php esc_html_e( 'When I am not designing, I am usually walking somewhere with a camera, or teaching a workshop on design systems.', 'postfolio-blocks' ); ?></p>
     164<!-- /wp:paragraph --></div>
     165<!-- /wp:column -->
     166
     167<!-- wp:column {"width":"50%","style":{"spacing":{"blockGap":"0"}}} -->
     168<div class="wp-block-column" style="flex-basis:50%"><!-- wp:paragraph {"className":"postfolio-kicker","fontSize":"small","style":{"spacing":{"padding":{"bottom":"0.75rem"}},"border":{"bottom":{"color":"var:preset|color|contrast","width":"2px"}}}} -->
     169<p class="postfolio-kicker has-small-font-size" style="border-bottom-color:var(--wp--preset--color--contrast);border-bottom-width:2px;padding-bottom:0.75rem"><?php esc_html_e( 'Experience', 'postfolio-blocks' ); ?></p>
     170<!-- /wp:paragraph --><?php foreach ( $postfolio_experience as $postfolio_job ) : ?>
     171
     172<!-- wp:group {"className":"postfolio-experience-row","style":{"spacing":{"padding":{"top":"1.1rem","bottom":"1.1rem"}},"border":{"bottom":{"color":"var:preset|color|base-2","width":"1px"}}},"layout":{"type":"flex","flexWrap":"wrap","justifyContent":"space-between","verticalAlignment":"center"}} -->
     173<div class="wp-block-group postfolio-experience-row" style="border-bottom-color:var(--wp--preset--color--base-2);border-bottom-width:1px;padding-top:1.1rem;padding-bottom:1.1rem"><!-- wp:group {"style":{"spacing":{"blockGap":"0.15rem"}},"layout":{"type":"flex","orientation":"vertical"}} -->
     174<div class="wp-block-group"><!-- wp:paragraph {"style":{"typography":{"fontWeight":"700"}}} -->
     175<p style="font-weight:700"><?php echo esc_html( $postfolio_job[1] ); ?></p>
     176<!-- /wp:paragraph -->
     177
     178<!-- wp:paragraph {"textColor":"contrast-2","fontSize":"small"} -->
     179<p class="has-contrast-2-color has-text-color has-small-font-size"><?php echo esc_html( $postfolio_job[2] ); ?></p>
     180<!-- /wp:paragraph --></div>
     181<!-- /wp:group -->
     182
     183<!-- wp:paragraph {"textColor":"contrast-2","fontSize":"small"} -->
     184<p class="has-contrast-2-color has-text-color has-small-font-size"><?php echo esc_html( $postfolio_job[0] ); ?></p>
     185<!-- /wp:paragraph --></div>
     186<!-- /wp:group --><?php endforeach; ?></div>
     187<!-- /wp:column --></div>
     188<!-- /wp:columns --></div>
     189<!-- /wp:group -->
     190
     191<!-- wp:pattern {"slug":"postfolio-blocks/testimonial-spotlight"} /-->
     192
     193<!-- wp:pattern {"slug":"postfolio-blocks/cta-portfolio"} /-->
  • postfolio-blocks/1.2.0/patterns/template-body-author.php

    r352228 r353530  
    1717
    1818<!-- wp:group {"tagName":"main","align":"full","layout":{"type":"constrained"}} -->
    19 <main class="wp-block-group alignfull"><!-- wp:pattern {"slug":"postfolio-blocks/author-bio-card"} /-->
     19<main class="wp-block-group alignfull"><!-- wp:group {"align":"full","className":"postfolio-author-hero","backgroundColor":"base-2","style":{"spacing":{"padding":{"top":"var:preset|spacing|50","bottom":"var:preset|spacing|50","left":"var:preset|spacing|20","right":"var:preset|spacing|20"}}},"layout":{"type":"constrained","contentSize":"860px"}} -->
     20<div class="wp-block-group alignfull postfolio-author-hero has-base-2-background-color has-background" style="padding-top:var(--wp--preset--spacing--50);padding-right:var(--wp--preset--spacing--20);padding-bottom:var(--wp--preset--spacing--50);padding-left:var(--wp--preset--spacing--20)"><!-- wp:group {"style":{"spacing":{"blockGap":"var:preset|spacing|40"}},"className":"postfolio-author-hero__inner","layout":{"type":"flex","flexWrap":"nowrap","verticalAlignment":"center"}} -->
     21<div class="wp-block-group postfolio-author-hero__inner"><!-- wp:avatar {"size":144,"className":"postfolio-author-hero-avatar postfolio-author-ring","style":{"border":{"radius":"999px"}}} /-->
     22
     23<!-- wp:group {"style":{"spacing":{"blockGap":"0.75rem"}},"layout":{"type":"flex","orientation":"vertical"}} -->
     24<div class="wp-block-group"><!-- wp:paragraph {"className":"postfolio-kicker","textColor":"accent","fontSize":"small"} -->
     25<p class="postfolio-kicker has-accent-color has-text-color has-small-font-size"><?php esc_html_e( 'Author', 'postfolio-blocks' ); ?></p>
     26<!-- /wp:paragraph -->
     27
     28<!-- wp:query-title {"type":"archive","showPrefix":false,"style":{"typography":{"fontSize":"clamp(2.2rem, 1.6rem + 2.4vw, 3.5rem)","lineHeight":"1.05"}}} /-->
     29
     30<!-- wp:paragraph {"className":"postfolio-author-hero-bio","textColor":"contrast-2","fontSize":"large"} -->
     31<p class="postfolio-author-hero-bio has-contrast-2-color has-text-color has-large-font-size"><?php esc_html_e( 'The author biography from the user profile appears here.', 'postfolio-blocks' ); ?></p>
     32<!-- /wp:paragraph -->
     33
     34<!-- wp:paragraph {"className":"postfolio-author-hero-stats","fontSize":"small"} -->
     35<p class="postfolio-author-hero-stats has-small-font-size"><?php esc_html_e( 'Post count and reader comments appear here.', 'postfolio-blocks' ); ?></p>
     36<!-- /wp:paragraph -->
     37
     38<!-- wp:social-links {"className":"postfolio-author-social","style":{"spacing":{"blockGap":{"left":"0.5rem"}}}} -->
     39<ul class="wp-block-social-links postfolio-author-social"><!-- wp:social-link {"url":"#","service":"chain"} /--></ul>
     40<!-- /wp:social-links --></div>
     41<!-- /wp:group --></div>
     42<!-- /wp:group --></div>
     43<!-- /wp:group -->
    2044
    2145<!-- wp:group {"align":"wide","style":{"spacing":{"margin":{"top":"var:preset|spacing|50"}}},"layout":{"type":"constrained"}} -->
    2246<div class="wp-block-group alignwide" style="margin-top:var(--wp--preset--spacing--50)"><!-- wp:heading {"fontSize":"large"} -->
    23 <h2 class="wp-block-heading has-large-font-size"><?php esc_html_e( 'Posts by this author', 'postfolio-blocks' ); ?></h2>
     47<h2 class="wp-block-heading has-large-font-size"><?php esc_html_e( 'Latest stories', 'postfolio-blocks' ); ?></h2>
    2448<!-- /wp:heading -->
    2549
  • postfolio-blocks/1.2.0/patterns/template-body-home-2.php

    r352228 r353530  
    1919<main class="wp-block-group alignfull"><!-- wp:group {"align":"wide","style":{"spacing":{"margin":{"top":"var:preset|spacing|50","bottom":"0"}}},"layout":{"type":"constrained","contentSize":"680px"}} -->
    2020<div class="wp-block-group alignwide" style="margin-top:var(--wp--preset--spacing--50);margin-bottom:0"><!-- wp:paragraph {"align":"center","className":"postfolio-badge"} -->
    21 <p class="has-text-align-center postfolio-badge"><?php esc_html_e( 'Home 2 · Spotlight', 'postfolio-blocks' ); ?></p>
     21<p class="has-text-align-center postfolio-badge"><?php esc_html_e( 'Spotlight', 'postfolio-blocks' ); ?></p>
    2222<!-- /wp:paragraph -->
    2323
  • postfolio-blocks/1.2.0/patterns/template-body-home-3.php

    r352228 r353530  
    1919<main class="wp-block-group alignfull"><!-- wp:group {"align":"wide","style":{"spacing":{"margin":{"top":"var:preset|spacing|50","bottom":"0"}}},"layout":{"type":"constrained","contentSize":"680px"}} -->
    2020<div class="wp-block-group alignwide" style="margin-top:var(--wp--preset--spacing--50);margin-bottom:0"><!-- wp:paragraph {"align":"center","className":"postfolio-badge"} -->
    21 <p class="has-text-align-center postfolio-badge"><?php esc_html_e( 'Home 3 · Editorial', 'postfolio-blocks' ); ?></p>
     21<p class="has-text-align-center postfolio-badge"><?php esc_html_e( 'Editorial', 'postfolio-blocks' ); ?></p>
    2222<!-- /wp:paragraph -->
    2323
  • postfolio-blocks/1.2.0/readme.txt

    r352228 r353530  
    44Tested up to: 7.1
    55Requires PHP: 7.4
    6 Version: 1.1.0
     6Version: 1.2.0
    77License: GPLv2 or later
    88License URI: https://www.gnu.org/licenses/gpl-2.0.html
    9 Tags: blog, news, portfolio, one-column, two-columns, three-columns, four-columns, right-sidebar, grid-layout, custom-colors, custom-logo, custom-menu, editor-style, featured-images, full-site-editing, full-width-template, block-patterns, block-styles, style-variations, template-editing, theme-options, threaded-comments, rtl-language-support, translation-ready, wide-blocks
    10 
    11 A bold, contemporary block theme for blogs, online magazines and portfolios — with 57 patterns, 22 templates, one-click starter sites, dark mode and a full set of blog tools built from core blocks.
     9Tags: blog, news, portfolio, one-column, two-columns,block-theme, gutenberg-theme,block-editor, three-columns, four-columns, right-sidebar, grid-layout, custom-colors, custom-logo, custom-menu, editor-style, featured-images, full-site-editing, post-formats, full-width-template, block-patterns, block-styles, style-variations, template-editing, theme-options, threaded-comments, rtl-language-support, translation-ready, wide-blocks
     10
     11Free FSE block theme for blogs, news magazines, portfolios and agencies — 5 starter sites with demo content, 68 patterns and dark mode.
    1212
    1313== Description ==
    1414
    15 Postfolio Blocks is a full-site-editing (FSE) block theme for independent blogs, online magazines, news sites and creative portfolios that want a modern, editorial look without installing a page builder. Everything is built from core WordPress blocks, so your content keeps working with any block theme.
    16 
    17 = Layouts =
    18 
    19 * **Three homepage layouts**: Home 1 (Statement), Home 2 (Spotlight) and Home 3 (Editorial List).
    20 * **22 templates**: blog index, front page, three homepages, four single-post layouts (default, with sidebar, cover hero, wide), five page layouts (default, no title, full width, with sidebar, landing page with transparent header), blank canvas, category, tag, date, author, archive, search and 404.
    21 * **15 template parts**: 7 headers (including sticky and transparent), 5 footers, sidebar, post meta and comments — swap them in the Site Editor.
    22 * **57 block patterns**: post grids and lists, heroes, calls to action, services, pricing, team, testimonials, FAQ, portfolio grid, case study, logo cloud, stats, timeline, gallery, events, careers, process steps and features.
    23 * **Page starters**: when you create a new page, pick a ready-made Landing, Services, Portfolio, About, Contact, Blog or Portfolio landing layout.
    24 
    25 = Styles =
    26 
    27 * 7 complete style variations (Midnight, Cyberpunk, Forest, Lavender, Nordic, Retro, Sunset) that change colors, fonts and button shapes.
    28 * 8 extra color palettes and 6 font pairings that can be mixed with any style.
    29 * 5 section styles (Dark, Accent, Muted, Gradient, Bordered) for Group, Columns and Column blocks, plus Card, Rounded, Dot and Pill block styles.
    30 * Shadow presets, custom aspect ratios and a fluid type scale.
    31 * Six self-hosted fonts (Poppins, Montserrat, Manrope, Lora, Playfair Display) — no requests to third-party font services.
    32 * Every palette meets WCAG AA contrast for text, muted text and links.
     15**Postfolio Blocks is a free WordPress block theme (full site editing) for blogs, news and magazine websites, creative portfolios and small agencies.** It is built only from core WordPress blocks, so it needs no page builder, and your content keeps working if you ever change themes.
     16
     17Import one of five starter sites, replace the demo content with your own, and publish. Everything — templates, headers, footers, colors and fonts — can be edited visually in the Site Editor.
     18
     19= Who is Postfolio Blocks for? =
     20
     21* **Bloggers and writers** who want a clean, fast personal blog with reading time, an author box and a table of contents.
     22* **News sites and online magazines** that need a breaking news ticker, live blog coverage, category pages, ad slots and magazine-style homepages.
     23* **Designers and freelancers** who want a portfolio with real case study pages.
     24* **Agencies and small businesses** that need a landing page with services, selected work, team, pricing and FAQ.
     25
     26= What is included? =
     27
     28* **5 one-click starter sites with demo content:** Personal Blog, Online Magazine, Editorial News, Creative Portfolio and Business & Agency. Each import adds the pages, demo posts with featured images, categories, tags, reader comments and a menu, and sets your homepage. Importing again updates the same content instead of duplicating it.
     29* **68 block patterns:** magazine and editorial homepages, post grids and lists, spotlight and bento layouts, heroes, calls to action, services, pricing, team, testimonials, FAQ, portfolio grids, case studies, logo cloud, stats, timeline, gallery, events and careers.
     30* **News and magazine tools:** a breaking news ticker (pausable, and static for visitors who prefer reduced motion), a top bar with today's date and trending tags, a live blog timeline, and leaderboard (728×90), sidebar (300×250) and in-article ad slots that reserve their space so the page does not jump.
     31* **27 templates:** blog index, front page, three homepage layouts, single posts (default, sidebar, cover hero, wide), dedicated layouts for video, gallery, quote and audio post formats, a case study template for portfolio work, page layouts (no title, full width, sidebar, landing page, blank canvas), category pages with a lead story and sub-categories, author pages with bio and stats, tag, date, archive, search and 404.
     32* **15 template parts:** 7 headers (including sticky and transparent), 5 footers, sidebar, post meta and comments.
     33* **Portfolio case studies:** posts in the "Work" category open in the case study template — project facts, challenge, process, result and impact in numbers.
     34
     35= Design and styles =
     36
     37* 7 style variations (Midnight, Cyberpunk, Forest, Lavender, Nordic, Retro, Sunset), 8 color palettes, 6 font pairings and 5 section styles.
     38* Optional dark mode with a visitor switch; the dark palette is generated from your colors, and footers stay readable in every palette.
     39* Self-hosted fonts (Poppins, Montserrat, Manrope, Lora, Playfair Display) — no requests to Google Fonts.
     40* Fluid type scale, shadow presets and custom aspect ratios.
     41
     42= Speed, SEO and accessibility =
     43
     44* **Lightweight:** no page builder and no jQuery on the front end. Scripts such as the ticker and the table of contents load only on pages that use them.
     45* **SEO-friendly structure:** semantic HTML landmarks, one H1 per page and a logical heading order, descriptive link text, image alt text in patterns, and internal linking through related posts, popular posts and category pages.
     46* **Accessible:** keyboard-friendly navigation, visible focus styles, readable color contrast and reduced-motion support.
    3347
    3448= Blog tools =
    3549
    36 * Reading time, author box, category pills and previous/next links on every post.
    37 * Related posts (same categories), popular posts (most commented), share buttons for the current post and an automatic table of contents.
    38 * A sidebar with search, about card, popular posts, categories, tags and a newsletter box.
     50Reading time, author box, related posts (same category), most discussed posts, share buttons, previous/next links and an automatic table of contents.
    3951
    4052= Modules (Appearance → Postfolio Blocks → Modules) =
    4153
    42 All modules are off by default. Turn on only what you need — each module loads its small script and stylesheet only when enabled:
    43 
    44 * Dark mode toggle (the dark palette is generated from your current colors)
    45 * Back to top button
    46 * Reading progress bar
    47 * Smart sticky header
    48 * Scroll animations (respects reduced-motion settings)
    49 * Footer reveal effect
    50 * Floating call / email / WhatsApp buttons
    51 
    52 = One-click starter sites =
    53 
    54 Personal Blog, Online Magazine, Editorial News, Creative Portfolio and Business & Agency. Each creates its pages from the theme patterns, sets the homepage and can optionally apply a matching style. Importing again updates the same pages instead of duplicating them.
     54All modules are off by default and load nothing until you turn them on: dark mode, back to top, reading progress bar, smart sticky header, scroll animations, footer reveal and floating call / email / WhatsApp buttons.
     55
     56= Works great with =
     57
     58Postfolio Blocks works fully on its own. For extra layouts you can optionally install two free plugins from WordPress.org: **Advanced Post Block** (post grids, sliders, masonry and news tickers) and **bBlocks** (80+ blocks such as pricing tables, countdowns and sliders). See Appearance → Postfolio Blocks → Recommended Plugins.
    5559
    5660== Installation ==
    … …  
    58621. Go to Appearance → Themes → Add New.
    59632. Search for "Postfolio Blocks", click Install, then Activate.
    60 3. Open Appearance → Postfolio Blocks to import a starter site or turn on modules.
     643. Open Appearance → Postfolio Blocks to import a starter site, turn on modules or see the recommended plugins.
    6165
    6266== Frequently Asked Questions ==
    6367
     68= What is Postfolio Blocks? =
     69
     70Postfolio Blocks is a free full-site-editing WordPress theme for blogs, news magazines, portfolios and agencies. It includes five starter sites with demo content, 68 block patterns and 27 templates, all built from core blocks.
     71
     72= Is Postfolio Blocks free? =
     73
     74Yes. Every feature, starter site and pattern is free. There is nothing to unlock.
     75
    6476= Does this theme require any plugin? =
    6577
    66 No. Every template and pattern is built from WordPress core blocks only.
     78No. Every template and pattern uses WordPress core blocks only. Advanced Post Block and bBlocks are optional extras.
     79
     80= Is Postfolio Blocks good for a news or magazine website? =
     81
     82Yes. The Online Magazine and Editorial News starter sites include a spotlight homepage, category sections, editor's picks and a most discussed list. You also get a breaking news ticker, a top bar with today's date, a live blog pattern and ad slots.
     83
     84= How do I make a portfolio with case studies? =
     85
     86Import the Creative Portfolio starter site, or add posts to a category with the slug "work". Those posts open in the Case Study template automatically, and you can insert the "Case study" pattern to add the challenge, process, result and metrics sections.
     87
     88= How do I use the video, gallery, quote and audio layouts? =
     89
     90Set the post format in the post editor (Post → Format). The matching layout is used automatically. You can also choose it in the Template setting of any post.
    6791
    6892= How do I switch between Home 1, Home 2 and Home 3? =
    … …  
    76100= How do I put a dark mode switch in my header? =
    77101
    78 Turn on the Dark mode module, then add a Button block to your header and choose the "Dark mode toggle" style for it. A floating switch is also shown by default.
     102Turn on the Dark mode module, then add the "News top bar" pattern, or add a Button block and choose its "Dark mode toggle" style. A floating switch is also shown by default.
    79103
    80104= Can I change the colors and fonts? =
    … …  
    87111
    88112== Changelog ==
     113
     114= 1.2.0 =
     115* Feature: Starter sites now import demo content — 12 posts with original illustrations, categories, tags, reader comments and a menu — so every site looks complete right away. Importing again updates the same content.
     116* Feature: New homepages for Online Magazine, Editorial News, Personal Blog, Business & Agency and Creative Portfolio, with every section aligned to the same width.
     117* Feature: Creative Portfolio imports four case study projects in a new "Work" category, plus a Work page that lists them.
     118* Feature: New patterns — breaking news ticker, news top bar (today's date, trending tags, dark mode switch), live blog timeline, leaderboard, sidebar and in-article ad slots, case study, and a portfolio call to action.
     119* Feature: New templates — video, gallery, quote and audio post formats (with post format support) and a case study template used automatically for posts in "Work".
     120* Feature: Category pages show a lead story, a grid of the latest posts in that category and sub-category links. Author pages show a large avatar, bio, post count and social links.
     121* Feature: "Recommended Plugins" tab in the dashboard for Advanced Post Block and bBlocks — optional, installed only when you click, with one dismissible notice.
     122* Enhancement: Starter site cards preview each site with its own colors, fonts and layout, list the pages they create and show what is already imported.
     123* Enhancement: Single posts have a centered header, a redesigned author box (with a fallback bio) and a share card.
     124* Enhancement: The Business & Agency homepage is redesigned with a split hero, services, selected work, process, team and three-plan pricing.
     125* Fix: Footer text no longer disappears when dark mode is switched on, with any style variation (including Midnight).
     126* Fix: The floating dark mode and back-to-top buttons stay visible on top of the footer.
     127* Fix: The comment form no longer touches the footer when the footer reveal module is on.
     128* Fix: Related posts and "most discussed" lists now work when they are placed inside groups or columns.
     129* Fix: The header search field no longer overflows on phones.
     130* Fix: Spotlight and "Latest stories" headings line up with their grids; category badges on cover images are readable.
     131* Fix: Removed internal labels ("Home 2 · Spotlight", "Home 3 · Editorial") from the homepage layouts.
     132* Fix: Hard-coded white text replaced with palette colors, so dark sections stay readable in dark mode.
     133* Fix: A translation function had an incorrect argument, which also made a second text domain appear.
     134* Performance: The ticker script loads only on pages with a ticker; dashboard preview fonts load only on the theme dashboard.
     135* Tweak: Removed a leftover zip file from the theme folder.
    89136
    90137= 1.1.0 =
  • postfolio-blocks/1.2.0/style.css

    r352228 r353530  
    33Author: bPlugins
    44Author URI: https://bplugins.com
    5 Description: A bold, contemporary full-site-editing block theme for blogs, online magazines and portfolios. Postfolio Blocks ships with three switchable homepage layouts, 22 templates (including post layouts with sidebar, cover hero and wide content, a landing page with transparent header and a blank canvas), 57 block patterns and one-click starter sites — all built from core WordPress blocks. Seven style variations, eight color palettes, six font pairings and five section styles re-skin the site in one click, with self-hosted fonts and accessible contrast. Blog tools include reading time, related and popular posts, share buttons and an automatic table of contents, and optional modules add dark mode, a reading progress bar, a smart sticky header and more.
     5Description: Postfolio Blocks is a free, lightweight full-site-editing (FSE) WordPress block theme for blogs, news and magazine sites, portfolios and agencies, built only from core blocks. It includes 5 one-click starter sites with demo content (Personal Blog, Online Magazine, Editorial News, Creative Portfolio, Business & Agency), 68 block patterns, 27 templates and 15 template parts: a breaking news ticker, live blog, ad slots, magazine homepages, category pages with a lead story, author pages, case study pages for portfolio work, and dedicated layouts for video, gallery, quote and audio post formats. Seven style variations, eight color palettes, six font pairings and an optional dark mode restyle the site in one click. Fonts are self-hosted, scripts load only where they are used, and every palette is designed for readable contrast. Blog tools include reading time, related and popular posts, an author box and an automatic table of contents.
    66Requires at least: 6.9
    77Tested up to: 7.1
    88Requires PHP: 7.4
    9 Version: 1.1.0
     9Version: 1.2.0
    1010License: GNU General Public License v2 or later
    1111License URI: https://www.gnu.org/licenses/gpl-2.0.html
    1212Text Domain: postfolio-blocks
    13 Tags: blog, news, portfolio, one-column, two-columns, three-columns, four-columns, right-sidebar, grid-layout, custom-colors, custom-logo, custom-menu, editor-style, featured-images, full-site-editing, full-width-template, block-patterns, block-styles, style-variations, template-editing, theme-options, threaded-comments, rtl-language-support, translation-ready, wide-blocks
     13Tags: blog, news, portfolio, one-column, two-columns, three-columns, four-columns, right-sidebar, grid-layout, custom-colors, custom-logo, custom-menu, editor-style, featured-images, full-site-editing, post-formats, full-width-template, block-patterns, block-styles, style-variations, template-editing, theme-options, threaded-comments, rtl-language-support, translation-ready, wide-blocks
    1414
    1515Postfolio Blocks WordPress Theme, Copyright (C) 2026 bPlugins
  • postfolio-blocks/1.2.0/templates/category.html

    r352228 r353530  
    1 <!-- wp:template-part {"slug":"header","tagName":"header","area":"header"} /-->
    2 
    3 <!-- wp:group {"tagName":"main","align":"full","style":{"spacing":{"padding":{"bottom":"var:preset|spacing|50"}}},"layout":{"type":"constrained"}} -->
    4 <main class="wp-block-group alignfull" style="padding-bottom:var(--wp--preset--spacing--50)"><!-- wp:group {"align":"wide","style":{"spacing":{"margin":{"top":"var:preset|spacing|50","bottom":"var:preset|spacing|40"},"blockGap":"0.6rem"}},"layout":{"type":"default"}} -->
    5 <div class="wp-block-group alignwide" style="margin-top:var(--wp--preset--spacing--50);margin-bottom:var(--wp--preset--spacing--40)"><!-- wp:query-title {"type":"archive","showPrefix":false,"fontSize":"huge"} /-->
    6 
    7 <!-- wp:term-description {"textColor":"contrast-2"} /--></div>
    8 <!-- /wp:group -->
    9 
    10 <!-- wp:query {"queryId":51,"query":{"perPage":9,"pages":0,"offset":0,"postType":"post","order":"desc","orderBy":"date","inherit":true},"align":"wide","layout":{"type":"default"}} -->
    11 <div class="wp-block-query alignwide"><!-- wp:post-template {"align":"wide","layout":{"type":"grid","columnCount":3,"minimumColumnWidth":"16rem"}} -->
    12 <!-- wp:group {"className":"is-style-card","style":{"spacing":{"blockGap":"0.75rem"}},"layout":{"type":"constrained"}} -->
    13 <div class="wp-block-group is-style-card"><!-- wp:post-featured-image {"isLink":true,"aspectRatio":"3/2","style":{"border":{"radius":"1rem"}}} /-->
    14 
    15 <!-- wp:post-terms {"term":"category","className":"is-style-pill"} /-->
    16 
    17 <!-- wp:post-title {"level":3,"isLink":true,"fontSize":"large"} /-->
    18 
    19 <!-- wp:post-excerpt {"moreText":"","excerptLength":16,"textColor":"contrast-2"} /-->
    20 
    21 <!-- wp:group {"style":{"spacing":{"blockGap":"0.6rem"}},"layout":{"type":"flex","flexWrap":"wrap"}} -->
    22 <div class="wp-block-group"><!-- wp:post-date {"textColor":"contrast-2","fontSize":"small"} /-->
    23 
    24 <!-- wp:post-time-to-read {"textColor":"contrast-2","fontSize":"small"} /--></div>
    25 <!-- /wp:group --></div>
    26 <!-- /wp:group -->
    27 <!-- /wp:post-template -->
    28 
    29 <!-- wp:query-no-results -->
    30 <!-- wp:pattern {"slug":"postfolio-blocks/hidden-no-results"} /-->
    31 <!-- /wp:query-no-results -->
    32 
    33 <!-- wp:query-pagination {"align":"wide","style":{"spacing":{"margin":{"top":"var:preset|spacing|40"}}},"layout":{"type":"flex","justifyContent":"space-between"}} -->
    34 <!-- wp:query-pagination-previous /-->
    35 
    36 <!-- wp:query-pagination-numbers /-->
    37 
    38 <!-- wp:query-pagination-next /-->
    39 <!-- /wp:query-pagination --></div>
    40 <!-- /wp:query --></main>
    41 <!-- /wp:group -->
    42 
    43 <!-- wp:template-part {"slug":"footer","tagName":"footer","area":"footer"} /-->
     1<!-- wp:pattern {"slug":"postfolio-blocks/template-body-category"} /-->
  • postfolio-blocks/1.2.0/theme.json

    r352228 r353530  
    783783                                "post"
    784784                        ]
     785                },
     786                {
     787                        "name": "single-case-study",
     788                        "title": "Post – Case Study (Work)",
     789                        "postTypes": [
     790                                "post"
     791                        ]
     792                },
     793                {
     794                        "name": "single-format-video",
     795                        "title": "Post – Video",
     796                        "postTypes": [
     797                                "post"
     798                        ]
     799                },
     800                {
     801                        "name": "single-format-gallery",
     802                        "title": "Post – Gallery",
     803                        "postTypes": [
     804                                "post"
     805                        ]
     806                },
     807                {
     808                        "name": "single-format-quote",
     809                        "title": "Post – Quote",
     810                        "postTypes": [
     811                                "post"
     812                        ]
     813                },
     814                {
     815                        "name": "single-format-audio",
     816                        "title": "Post – Audio / Podcast",
     817                        "postTypes": [
     818                                "post"
     819                        ]
    785820                }
    786821        ],
Note: See TracChangeset for help on using the changeset viewer.