{"product_id":"personalized-custom-t-shirts-copy-copy-copy","title":"PERSONALIZED CUSTOM T-SHIRTS  1)","description":"\u003cdiv id=\"usf-custom-studio\" data-demo=\"false\" class=\"uf-v3\"\u003e\n  \u003cstyle\u003e\n\/* USASTARFASHION STUDIO 03 — independent visual system, not a theme override. *\/\n#usf-custom-studio{--uf-ink:#17243b;--uf-muted:#7c899f;--uf-line:#e4e9f1;--uf-accent:#315cf4;--uf-accent-light:#edf2ff;--uf-paper:#f5f7fb;font-family:Inter,'Segoe UI',Arial,sans-serif;color:var(--uf-ink);font-size:14px;line-height:1.5;max-width:1320px;margin:24px auto}\n#usf-custom-studio *,#usf-custom-studio *:before,#usf-custom-studio *:after{box-sizing:border-box}\n#usf-custom-studio [hidden]{display:none!important}\n#usf-custom-studio :is(h2,h3,p){margin:0}\n#usf-custom-studio :is(button,input,textarea,select){font:inherit;letter-spacing:normal}\n#usf-custom-studio button{cursor:pointer;text-transform:none;line-height:1.35;transition:background .16s,border-color .16s,box-shadow .16s;appearance:none;box-shadow:none}\n#usf-custom-studio button:disabled{opacity:.4;cursor:not-allowed}\n#usf-custom-studio :is(button,input,textarea,select):focus-visible{outline:3px solid #82a2ff;outline-offset:3px}\n#usf-custom-studio .uf-primary,#usf-custom-studio .uf-secondary{min-height:44px;border:1px solid transparent;border-radius:9px;padding:11px 16px;display:inline-flex;align-items:center;justify-content:center;gap:10px;font-size:12px;font-weight:650;white-space:normal}\n#usf-custom-studio .uf-primary{background:#315cf4;color:#fff}\n#usf-custom-studio .uf-primary:hover:not(:disabled){background:#234bd8;box-shadow:0 4px 12px #315cf428}\n#usf-custom-studio .uf-secondary{background:#fff;border-color:#dce3ef;color:#354762}\n#usf-custom-studio .uf-secondary:hover:not(:disabled){background:#f1f5ff;border-color:#b5c8f7}\n#usf-custom-studio .uf-wide{width:100%}\n#usf-custom-studio .uf-icon{display:inline-grid;place-items:center;width:36px;height:36px;flex:0 0 auto;padding:0;border:1px solid #e0e6ef;border-radius:8px;background:#fff;color:#65758e;font-size:20px}\n#usf-custom-studio .uf-icon:hover:not(:disabled){background:#ecf2ff;color:#315cf4}\n#usf-custom-studio .uf-link{border:0;background:transparent;color:#315cf4;font-size:11px;font-weight:600;min-height:38px;padding:8px;white-space:nowrap}\n#usf-custom-studio .uf-eyebrow{display:block;font-size:9px;font-weight:700;letter-spacing:.15em;color:#8a98ad}\n#usf-custom-studio .uf-launch{display:flex;justify-content:space-between;align-items:center;gap:30px;padding:44px;background:#111d33;color:#fff;border-radius:18px;position:relative;overflow:hidden}\n#usf-custom-studio .uf-launch:after{content:'';position:absolute;width:400px;height:400px;right:150px;top:-150px;border:1px solid #263654;border-radius:50%;pointer-events:none}\n#usf-custom-studio .uf-launch h2{font-size:clamp(28px,3.6vw,46px);line-height:1.08;letter-spacing:-.055em;font-weight:650;color:#fff;margin:14px 0}\n#usf-custom-studio .uf-launch p{font-size:13px;color:#a3b1c7;max-width:420px;line-height:1.7}\n#usf-custom-studio .uf-launch .uf-eyebrow{color:#83a0ff}\n#usf-custom-studio .uf-launch-right{display:flex;flex-direction:column;gap:14px;align-items:stretch;flex-shrink:0;z-index:1}\n#usf-custom-studio .uf-launch-right .uf-primary{padding:15px 24px;font-size:14px}\n#usf-custom-studio .uf-launch-right small{font-size:10px;color:#8090aa;text-align:center}\n#usf-custom-studio .uf-launch-label{font-size:9px;letter-spacing:.1em;color:#8e9eb8}\n#usf-custom-studio .uf-dialog{position:fixed;inset:0;margin:auto;padding:0;width:min(1440px,calc(100vw - 32px));height:min(960px,calc(100dvh - 32px));max-width:none;max-height:none;overflow:hidden;border:1px solid #cbd5e3;border-radius:16px;background:#fff;color:var(--uf-ink);box-shadow:0 26px 100px #0b193855;font-family:inherit}\n#usf-custom-studio .uf-dialog[open]{display:grid;grid-template-rows:68px 78px minmax(0,1fr) 72px}\n#usf-custom-studio .uf-dialog::backdrop{background:#0d193db0;backdrop-filter:blur(6px)}\n#usf-custom-studio .uf-header{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:12px 22px;background:#fff;border-bottom:1px solid var(--uf-line)}\n#usf-custom-studio .uf-identity{display:flex;align-items:center;gap:11px;min-width:0}\n#usf-custom-studio .uf-mark{width:36px;height:36px;display:grid;place-items:center;position:relative;border-radius:10px;background:#182947;color:#fff;font-size:23px;font-weight:800}\n#usf-custom-studio .uf-mark span{position:absolute;right:4px;top:0;color:#a5b9ff;font-size:12px}\n#usf-custom-studio .uf-identity strong{display:block;font-size:11px;font-weight:750;letter-spacing:.08em}\n#usf-custom-studio .uf-identity small{display:flex;align-items:center;gap:7px;font-size:8px;letter-spacing:.1em;color:#94a0b4;margin-top:3px}\n#usf-custom-studio .uf-version{font-size:8px;color:#315cf4;background:#eef2ff;padding:1px 4px;border-radius:3px}\n#usf-custom-studio .uf-document-name{display:flex;gap:9px;align-items:center;color:#485b78;font-size:11px}\n#usf-custom-studio .uf-document-name small{padding-left:11px;border-left:1px solid #e2e7f0;color:#8c98ab;font-size:10px}\n#usf-custom-studio .uf-dot{width:6px;height:6px;background:#5fa68a;border-radius:50%;display:inline-block;flex-shrink:0}\n#usf-custom-studio .uf-header-actions{display:flex;gap:9px;align-items:center}\n#usf-custom-studio .uf-header-actions .uf-secondary{min-height:36px;padding:7px 14px;font-size:11px}\n#usf-custom-studio .uf-methodbar{display:flex;align-items:center;justify-content:space-between;padding:11px 23px;background:#fafbfd;border-bottom:1px solid var(--uf-line);gap:18px}\n#usf-custom-studio .uf-workflow{display:flex;align-items:center;gap:11px;font-size:12px;font-weight:600;min-width:0}\n#usf-custom-studio .uf-step-number{width:29px;height:29px;border:1px solid #dce4f1;background:white;display:grid;place-items:center;border-radius:8px;font-size:10px;color:#315cf4}\n#usf-custom-studio .uf-workflow small{display:block;font-size:9px;color:#98a3b7;font-weight:400;margin-top:2px}\n#usf-custom-studio .uf-methods{display:flex;gap:4px;padding:4px;border:1px solid #e1e6ef;background:#f0f3f8;border-radius:10px}\n#usf-custom-studio .uf-methods button{display:flex;align-items:center;gap:10px;border:1px solid transparent;background:none;border-radius:7px;padding:7px 15px;text-align:left;color:#7c8ba2;min-width:162px}\n#usf-custom-studio .uf-methods button[aria-pressed=true]{background:#172945;color:#fff;border-color:#172945;box-shadow:0 2px 5px #17294515}\n#usf-custom-studio .uf-method-icon{font-size:23px}\n#usf-custom-studio .uf-methods strong{display:block;font-size:11px;font-weight:650}\n#usf-custom-studio .uf-methods small{display:block;font-size:8px;opacity:.7;margin-top:2px}\n#usf-custom-studio .uf-methodbar\u003ep{font-size:10px;max-width:180px;line-height:1.5;color:#97a4b6;text-align:right}\n#usf-custom-studio .uf-layout{display:grid;grid-template-columns:76px 292px minmax(0,1fr);min-width:0;min-height:0}\n#usf-custom-studio .uf-rail{background:#14223a;border-right:1px solid #22334e;padding:14px 7px;display:flex;flex-direction:column;gap:7px;overflow:auto;scrollbar-width:none}\n#usf-custom-studio .uf-rail button{border:1px solid transparent;border-radius:9px;background:transparent;min-height:69px;width:100%;display:flex;flex-direction:column;justify-content:center;align-items:center;gap:8px;color:#8ea0bd;padding:9px 3px;font-size:9px}\n#usf-custom-studio .uf-rail button[aria-selected=true]{background:#2b436b;color:#fff;border-color:#3a5481}\n#usf-custom-studio .uf-rail button:hover{background:#223856;color:#dbe8ff}\n#usf-custom-studio .uf-rail svg{width:22px;height:22px;stroke:currentColor;stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round;fill:none}\n#usf-custom-studio .uf-sidebar{display:flex;flex-direction:column;min-width:0;min-height:0;border-right:1px solid var(--uf-line);background:#fff}\n#usf-custom-studio .uf-panel-heading{display:flex;align-items:center;justify-content:space-between;gap:10px;min-height:75px;padding:16px 19px;border-bottom:1px solid #eef1f6;flex:0 0 auto}\n#usf-custom-studio .uf-panel-heading h2{font-size:17px;font-weight:650;letter-spacing:-.04em;margin-top:4px;line-height:1.3}\n#usf-custom-studio .uf-panel-number{font-size:27px;font-weight:300;color:#e0e6ef}\n#usf-custom-studio .uf-panel-scroll{padding:20px 18px;overflow:auto;min-height:0;overscroll-behavior:contain;scrollbar-width:thin;scrollbar-color:#c9d3e3 transparent}\n#usf-custom-studio h3{font-size:17px;line-height:1.3;font-weight:650;letter-spacing:-.035em;color:#20334f}\n#usf-custom-studio .uf-section-heading{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:14px}\n#usf-custom-studio .uf-section-heading .uf-eyebrow{margin-bottom:6px}\n#usf-custom-studio .uf-section-heading small{font-size:10px;color:#94a1b6}\n#usf-custom-studio .uf-upload{position:relative;display:flex;align-items:center;flex-direction:column;padding:21px 10px;gap:6px;text-align:center;border:1px dashed #b8c9ed;background:#f5f8ff;border-radius:11px;cursor:pointer}\n#usf-custom-studio .uf-upload input{position:absolute;inset:0;width:100%;height:100%;opacity:0;cursor:pointer}\n#usf-custom-studio .uf-upload:focus-within{outline:3px solid #82a2ff;outline-offset:3px}\n#usf-custom-studio .uf-upload.dragover{background:#e5edff;border-color:#315cf4}\n#usf-custom-studio .uf-upload-icon{width:42px;height:42px;border:1px solid #dce6fa;background:#fff;border-radius:12px;display:grid;place-items:center;color:#315cf4;font-size:25px;margin-bottom:3px}\n#usf-custom-studio .uf-upload strong{font-size:12px;font-weight:600}\n#usf-custom-studio .uf-upload\u003espan:not(.uf-upload-icon){font-size:10px;color:#8897b0}\n#usf-custom-studio .uf-upload small{font-size:9px;color:#a1acc0}\n#usf-custom-studio .uf-hint{font-size:10px;line-height:1.65;color:#8796ad;margin:10px 0 14px}\n#usf-custom-studio .uf-library-heading{margin-top:22px;margin-bottom:9px}\n#usf-custom-studio .uf-library-heading h3{font-size:13px}\n#usf-custom-studio .uf-search{display:flex;align-items:center;gap:8px;padding:0 11px;border:1px solid #e0e7f1;background:#fafbfd;border-radius:8px}\n#usf-custom-studio .uf-search span{font-size:23px;color:#8b9cb6}\n#usf-custom-studio .uf-search input{height:42px;border:0;background:transparent;font-size:11px;min-width:0;width:100%;color:#435575}\n#usf-custom-studio .uf-status{font-size:10px;line-height:1.65;color:#748ba2;overflow-wrap:anywhere;margin:10px 0}\n#usf-custom-studio .uf-status.error{color:#ac3c54}\n#usf-custom-studio .uf-library{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}\n#usf-custom-studio .uf-art-card{border:1px solid #e2e8f0;background:#fff;border-radius:10px;overflow:hidden;min-width:0}\n#usf-custom-studio .uf-art-card:hover{border-color:#b2c5f5;box-shadow:0 4px 12px #22437d0a}\n#usf-custom-studio .uf-art-select{display:block;width:100%;border:0;padding:0;background:transparent;color:#54637c;text-align:left}\n#usf-custom-studio .uf-art-card img{display:block;width:100%;aspect-ratio:1.12;object-fit:contain;padding:10px;background:#f3f5f9}\n#usf-custom-studio .uf-art-card span{display:block;font-size:10px;padding:8px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}\n#usf-custom-studio .uf-library-actions{display:flex;gap:4px;padding:0 7px 8px}\n#usf-custom-studio .uf-library-actions button{flex:1;min-width:0;font-size:9px;border:1px solid #dde5f5;background:#f3f6fd;color:#4566a7;border-radius:5px;min-height:32px;padding:5px}\n#usf-custom-studio .uf-field{display:flex;flex-direction:column;gap:7px;font-size:11px;font-weight:600;color:#677a96;margin:14px 0;min-width:0}\n#usf-custom-studio .uf-field :is(input,textarea,select){min-width:0;max-width:100%;width:100%;min-height:42px;border:1px solid #dce4ef;border-radius:7px;background:#fafbfd;color:#354a6a;font-size:12px;font-weight:400;padding:10px}\n#usf-custom-studio .uf-field textarea{resize:vertical;line-height:1.6;min-height:80px}\n#usf-custom-studio .uf-field input[type=color]{padding:5px;cursor:pointer}\n#usf-custom-studio input[type=range],#usf-custom-studio input[type=checkbox]{accent-color:#315cf4}\n#usf-custom-studio .uf-two,#usf-custom-studio .uf-tool-grid,#usf-custom-studio .uf-presets{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:8px}\n#usf-custom-studio .uf-two\u003e.uf-field{margin-top:0}\n#usf-custom-studio .uf-two\u003ebutton,#usf-custom-studio .uf-tool-grid\u003ebutton{font-size:10px;padding:10px 6px}\n#usf-custom-studio .uf-format-row{display:flex;gap:7px;margin:12px 0}\n#usf-custom-studio .uf-format-row button{width:42px;min-height:40px;padding:8px;border:1px solid #dde5f0;background:#fff;color:#587093;border-radius:6px}\n#usf-custom-studio .uf-format-row button[aria-pressed=true]{color:#315cf4;background:#edf3ff;border-color:#adbef1}\n#usf-custom-studio .uf-text-sample{display:grid;place-items:center;min-height:100px;padding:20px 10px;background:#f1f4f9;border-radius:9px;font-size:24px;white-space:pre-wrap;overflow-wrap:anywhere;margin-bottom:12px}\n#usf-custom-studio .uf-details{border:1px solid #e0e7f1;border-radius:9px;padding:12px;margin:16px 0}\n#usf-custom-studio .uf-details summary{font-size:11px;font-weight:600;color:#5f7494;cursor:pointer;min-height:28px}\n#usf-custom-studio .uf-presets{margin-top:10px}\n#usf-custom-studio .uf-presets button{min-height:46px;padding:9px 5px;border:1px solid #e1e7f1;background:#f8faff;border-radius:7px;color:#405477;font-size:13px}\n#usf-custom-studio .uf-ai-card{background:#f4f7ff;border:1px solid #dce5fc;padding:14px;border-radius:12px;margin-top:23px}\n#usf-custom-studio .uf-ai-title{display:flex;align-items:center;gap:10px}\n#usf-custom-studio .uf-ai-title\u003espan{font-size:28px;color:#6b87d8}\n#usf-custom-studio .uf-ai-title strong{display:block;font-size:12px}\n#usf-custom-studio .uf-ai-title small{display:block;font-size:9px;color:#8c9dc3;margin-top:2px}\n#usf-custom-studio .uf-ai-intro{padding:4px 0 12px}\n#usf-custom-studio .uf-ai-orbit{display:grid;place-items:center;width:46px;height:46px;background:#edf2ff;border:1px solid #dce5ff;border-radius:13px;color:#5276e6;font-size:28px;margin-bottom:14px}\n#usf-custom-studio .uf-ai-intro h3{font-size:25px;letter-spacing:-.05em;line-height:1.18;margin:8px 0}\n#usf-custom-studio .uf-ai-intro p{font-size:11px;color:#8c99b0}\n#usf-custom-studio .uf-ai-image-preview{position:relative;aspect-ratio:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;background:repeating-conic-gradient(#f3f6fa 0 25%,#fff 0 50%) 0\/20px 20px;border:1px solid #e2e8f3;border-radius:11px;overflow:hidden;margin-top:17px;text-align:center;padding:16px}\n#usf-custom-studio .uf-ai-image-preview\u003espan{font-size:34px;color:#bdcce9}\n#usf-custom-studio .uf-ai-image-preview p{font-size:10px;color:#94a5bf}\n#usf-custom-studio .uf-ai-image-preview img{width:100%;height:100%;position:absolute;inset:0;object-fit:contain}\n#usf-custom-studio .uf-ai-image-preview[aria-busy=true]:before{content:'';width:30px;height:30px;border:3px solid #dbe5fc;border-top-color:#315cf4;border-radius:50%;animation:uf-rotate 1s linear infinite}\n@keyframes uf-rotate{to{transform:rotate(360deg)}}\n#usf-custom-studio .uf-product{display:flex;align-items:center;gap:12px;background:#f3f6fc;padding:13px;border-radius:10px;margin-top:16px}\n#usf-custom-studio .uf-product img{width:50px;height:60px;object-fit:contain}\n#usf-custom-studio .uf-product strong{display:block;font-size:12px;line-height:1.4}\n#usf-custom-studio .uf-product small{display:block;font-size:11px;color:#8195b4;margin-top:5px}\n#usf-custom-studio .uf-callout{background:#f4f7fd;border-left:2px solid #aec1ed;font-size:10px;color:#8193af;padding:11px;margin:12px 0;line-height:1.65}\n#usf-custom-studio .uf-layers-section{border-top:1px solid #e6ebf3;margin-top:23px;padding-top:20px}\n#usf-custom-studio .uf-layers-section h3{font-size:12px}\n#usf-custom-studio .uf-layer{display:flex;gap:6px;align-items:center;border:1px solid #e1e8f1;border-radius:7px;margin-top:6px;background:#fff;overflow:hidden}\n#usf-custom-studio .uf-layer.selected{background:#f0f5ff;border-color:#bdcff2}\n#usf-custom-studio .uf-layer\u003ebutton{border:0;background:transparent;font-size:12px;color:#607697;padding:9px;min-height:36px}\n#usf-custom-studio .uf-layer\u003ebutton:first-child{flex:1;min-width:0;text-align:left;font-size:10px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}\n#usf-custom-studio .uf-tool-grid{margin:10px 0}\n#usf-custom-studio .uf-downloads{display:grid;gap:7px;margin-top:10px}\n#usf-custom-studio .uf-workspace{display:grid;grid-template-rows:58px minmax(0,1fr) 56px auto;min-width:0;min-height:0;background:#eef2f7}\n#usf-custom-studio .uf-canvas-toolbar{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:10px 20px;background:#f9fbfd;border-bottom:1px solid #e4eaf3;min-width:0}\n#usf-custom-studio .uf-canvas-toolbar\u003ediv:first-child{display:flex;gap:8px;align-items:center;min-width:0}\n#usf-custom-studio .uf-canvas-toolbar strong{font-size:11px;font-weight:650;white-space:nowrap}\n#usf-custom-studio .uf-dimensions{font-size:10px;color:#9aa6b9;white-space:nowrap}\n#usf-custom-studio .uf-history{display:flex;gap:4px;margin-left:auto}\n#usf-custom-studio .uf-history .uf-icon{background:transparent;border-color:transparent;font-size:20px;width:30px}\n#usf-custom-studio .uf-canvas-controls{display:flex;align-items:center;gap:3px;border-left:1px solid #dce4ef;padding-left:10px}\n#usf-custom-studio .uf-canvas-controls .uf-icon{width:29px;height:30px;background:transparent;border-color:transparent;font-size:17px}\n#usf-custom-studio .uf-zoom-value{border:0;background:none;color:#7b8eaa;font-size:10px;min-width:36px;padding:7px 1px}\n#usf-custom-studio .uf-stage{position:relative;min-height:0;min-width:0;display:grid;place-items:center;overflow:hidden;container-type:size;background-color:#edf1f7;background-image:radial-gradient(#c7d1e0 .65px,transparent .65px);background-size:20px 20px}\n#usf-custom-studio .uf-stage.no-grid{background-image:none}\n#usf-custom-studio .uf-scene{width:100%;height:100%;max-width:100%;max-height:100%;display:block;touch-action:none;user-select:none;filter:drop-shadow(0 12px 11px #18345d0c)}\n@supports(width:1cqw){#usf-custom-studio .uf-scene{width:min(100cqw,calc(100cqh * .923));height:min(100cqh,calc(100cqw * 1.0834))}}\n#usf-custom-studio .uf-stage-note{position:absolute;top:22px;left:26px;pointer-events:none}\n#usf-custom-studio .uf-stage-note .uf-eyebrow{font-size:8px;color:#a6b3c9}\n#usf-custom-studio .uf-stage-note p{font-size:16px;font-weight:400;letter-spacing:-.035em;color:#99a9c1;line-height:1.5;margin-top:6px}\n#usf-custom-studio .uf-empty{position:absolute;left:50%;top:48%;transform:translate(-50%,-50%);width:230px;display:flex;flex-direction:column;align-items:center;text-align:center;gap:12px;pointer-events:none}\n#usf-custom-studio .uf-empty-symbol{display:grid;place-items:center;width:36px;height:36px;background:#ffffffc0;border:1px solid #c9d6e9;border-radius:50%;font-size:23px;color:#8ca0bf}\n#usf-custom-studio .uf-empty strong{font-size:19px;font-weight:550;letter-spacing:-.045em;color:#4f6585;line-height:1.35}\n#usf-custom-studio .uf-empty\u003espan:not(.uf-empty-symbol){font-size:9px;color:#93a4bb}\n#usf-custom-studio .uf-empty button{pointer-events:auto;min-height:35px;font-size:10px;background:#ffffffdc;border-color:#ccd9ee;padding:8px 12px;color:#6681ac}\n#usf-custom-studio .uf-preview-disclaimer{position:absolute;bottom:9px;left:17px;font-size:8px;color:#9cabc0;pointer-events:none}\n#usf-custom-studio .uf-viewbar{display:flex;justify-content:space-between;align-items:center;gap:9px;padding:7px 20px;background:#f8fafd;border-top:1px solid #e2e9f2;min-width:0}\n#usf-custom-studio .uf-views{display:flex;gap:5px;overflow:auto;min-width:0;scrollbar-width:thin}\n#usf-custom-studio .uf-views button{min-height:34px;padding:7px 12px;border:1px solid transparent;background:transparent;font-size:10px;color:#93a1b8;border-radius:7px;white-space:nowrap}\n#usf-custom-studio .uf-views button[aria-pressed=true]{background:#fff;border-color:#dce4f1;color:#39547f;box-shadow:0 2px 4px #19305104}\n#usf-custom-studio .uf-inspector{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:12px;padding:13px 20px;background:#fff;border-top:1px solid #e3eaf4}\n#usf-custom-studio .uf-selection-title{min-width:0;flex:1 1 170px}\n#usf-custom-studio .uf-selection-title strong{display:block;font-size:11px;font-weight:600;max-width:230px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}\n#usf-custom-studio .uf-selection-title small{display:block;font-size:9px;color:#9aa7bd;margin-top:4px}\n#usf-custom-studio .uf-inspector-controls{display:flex;gap:7px;flex-wrap:wrap;align-items:center}\n#usf-custom-studio .uf-inspector label{font-size:9px;color:#99a6bb;display:flex;flex-direction:column;gap:4px}\n#usf-custom-studio .uf-inspector label\u003espan{display:flex;align-items:center;gap:3px;padding:5px;height:30px;border:1px solid #e1e7f1;border-radius:6px;font-size:9px}\n#usf-custom-studio .uf-inspector input{width:43px;min-width:0;border:0;background:transparent;font-size:11px;color:#61769a;padding:0;appearance:textfield}\n#usf-custom-studio .uf-inspector .uf-icon{width:31px;height:31px;align-self:flex-end;font-size:18px}\n#usf-custom-studio .uf-delete{color:#a06c7b}\n#usf-custom-studio .uf-footer{display:flex;align-items:center;gap:12px;padding:13px 22px;border-top:1px solid #dfe7f1;background:#fff}\n#usf-custom-studio .uf-footer-seal{color:#a0b2d3;font-size:24px;border-right:1px solid #e5eaf2;padding-right:15px}\n#usf-custom-studio .uf-footer-copy{min-width:0;flex:1}\n#usf-custom-studio .uf-footer-copy strong{display:block;font-size:12px;font-weight:650;white-space:nowrap;text-overflow:ellipsis;overflow:hidden;max-width:340px}\n#usf-custom-studio .uf-footer-copy span{display:block;font-size:9px;color:#98a6bb;margin-top:3px}\n#usf-custom-studio .uf-footer-actions{display:flex;align-items:center;gap:8px;flex-shrink:0}\n#usf-custom-studio .uf-footer-actions\u003e.uf-primary{padding:12px 22px}\n#usf-custom-studio .uf-toast{position:absolute;z-index:15;bottom:86px;left:50%;transform:translateX(-50%);max-width:calc(100% - 24px);background:#182a49f5;color:#edf3ff;padding:12px 18px;border-radius:9px;font-size:12px;text-align:center;box-shadow:0 6px 30px #13244435;pointer-events:none}\n#usf-custom-studio .uf-review-backdrop{position:absolute;inset:0;z-index:20;background:#11233b88;backdrop-filter:blur(3px)}\n#usf-custom-studio .uf-review{position:absolute;inset:0 0 0 auto;width:min(420px,100%);background:#fff;z-index:21;padding:27px;overflow:auto;box-shadow:-12px 0 40px #16294722}\n#usf-custom-studio .uf-review\u003eheader{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:26px}\n#usf-custom-studio .uf-review h3{font-size:25px;letter-spacing:-.05em;margin-top:6px}\n#usf-custom-studio .uf-review-row{display:flex;justify-content:space-between;gap:12px;padding:14px 0;border-bottom:1px solid #e6ecf4;font-size:12px}\n#usf-custom-studio .uf-review-row\u003espan{color:#8c9bb1}\n#usf-custom-studio .uf-review-row strong{font-weight:600;text-align:right;max-width:68%;overflow-wrap:anywhere}\n#usf-custom-studio .uf-review ul{font-size:11px;color:#8196b5;line-height:1.8;padding-left:17px}\n#usf-custom-studio .uf-check{display:flex;align-items:flex-start;gap:9px;font-size:11px;color:#7c90ae;line-height:1.65;margin:20px 0}\n#usf-custom-studio .uf-check input{width:17px;height:17px;flex-shrink:0}\n#usf-custom-studio .uf-shadow-check{margin:4px 0 12px}\n@media(max-width:1180px){#usf-custom-studio .uf-layout{grid-template-columns:66px 274px minmax(0,1fr)}#usf-custom-studio .uf-methodbar\u003ep{display:none}#usf-custom-studio .uf-document-name small{display:none}#usf-custom-studio .uf-stage-note{display:none}#usf-custom-studio .uf-panel-scroll{padding:18px 16px}#usf-custom-studio .uf-dimensions{display:none}#usf-custom-studio .uf-inspector{padding:10px 13px;gap:8px}#usf-custom-studio .uf-selection-title{flex-basis:100%}#usf-custom-studio .uf-canvas-toolbar{padding:9px 11px}#usf-custom-studio .uf-canvas-controls{padding-left:4px;gap:0}}\n@media(max-width:850px){#usf-custom-studio .uf-document-name{display:none}#usf-custom-studio .uf-workflow small{display:none}#usf-custom-studio .uf-layout{grid-template-columns:60px 260px minmax(0,1fr)}#usf-custom-studio .uf-methods button{min-width:140px}#usf-custom-studio .uf-history{display:none}#usf-custom-studio .uf-footer-seal{display:none}}\n@media(max-width:700px){\n  #usf-custom-studio .uf-dialog{width:100%;height:100dvh;max-height:none;inset:0;border:0;border-radius:0}\n  #usf-custom-studio .uf-dialog[open]{grid-template-rows:calc(62px + env(safe-area-inset-top)) 68px minmax(0,1fr) auto}\n  #usf-custom-studio .uf-header{padding:calc(9px + env(safe-area-inset-top)) max(12px,env(safe-area-inset-right)) 9px max(12px,env(safe-area-inset-left));gap:8px}\n  #usf-custom-studio .uf-identity strong{font-size:10px;letter-spacing:.025em}#usf-custom-studio .uf-identity small{font-size:7px}\n  #usf-custom-studio .uf-header-actions .uf-secondary{font-size:10px;padding:8px 10px;min-height:40px}\n  #usf-custom-studio .uf-mark{width:30px;height:32px;font-size:21px}#usf-custom-studio .uf-identity{gap:7px}\n  #usf-custom-studio .uf-header .uf-icon{width:40px;height:40px}\n  #usf-custom-studio .uf-methodbar{padding:7px 12px}#usf-custom-studio .uf-workflow{display:none}\n  #usf-custom-studio .uf-methods{width:100%;padding:3px}#usf-custom-studio .uf-methods button{min-width:0;flex:1;padding:7px 12px}\n  #usf-custom-studio .uf-layout{display:flex;flex-direction:column;overflow:auto;overscroll-behavior:contain}\n  #usf-custom-studio .uf-workspace{order:0;flex-shrink:0;grid-template-rows:48px minmax(215px,36dvh) 52px auto}\n  #usf-custom-studio .uf-history{display:flex}#usf-custom-studio .uf-canvas-controls .uf-icon{width:34px;height:40px}#usf-custom-studio .uf-canvas-toolbar strong{font-size:10px}\n  #usf-custom-studio .uf-rail{order:1;flex-shrink:0;position:sticky;top:0;z-index:4;flex-direction:row;gap:4px;padding:5px 8px;overflow-x:auto;min-height:69px}\n  #usf-custom-studio .uf-rail button{flex:1 0 54px;min-height:57px;min-width:54px;padding:6px 4px;gap:5px;font-size:9px}\n  #usf-custom-studio .uf-rail svg{width:20px;height:20px}\n  #usf-custom-studio .uf-sidebar{order:2;flex-shrink:0;border-right:0}\n  #usf-custom-studio .uf-panel-heading{padding:16px 18px;min-height:69px}#usf-custom-studio .uf-panel-scroll{overflow:visible;padding:22px 18px}\n  #usf-custom-studio .uf-library{grid-template-columns:repeat(3,minmax(0,1fr))}\n  #usf-custom-studio .uf-empty{width:200px;gap:7px}#usf-custom-studio .uf-empty-symbol{display:none}#usf-custom-studio .uf-empty strong{font-size:16px}\n  #usf-custom-studio .uf-viewbar{padding:4px 10px}#usf-custom-studio .uf-views button{min-height:44px;padding:8px 10px;font-size:10px}#usf-custom-studio .uf-link{min-height:44px;font-size:10px}\n  #usf-custom-studio .uf-inspector-controls{width:100%;gap:8px}#usf-custom-studio .uf-inspector label\u003espan{height:40px}#usf-custom-studio .uf-inspector input{font-size:16px;width:44px}#usf-custom-studio .uf-inspector .uf-icon{width:40px;height:40px}\n  #usf-custom-studio .uf-field :is(input,textarea,select),#usf-custom-studio .uf-search input{font-size:16px;min-height:46px}\n  #usf-custom-studio .uf-library-actions button,#usf-custom-studio .uf-format-row button,#usf-custom-studio .uf-tool-grid button{min-height:44px}\n  #usf-custom-studio .uf-layer button{min-height:44px}#usf-custom-studio .uf-tool-grid button{font-size:12px}\n  #usf-custom-studio .uf-footer{gap:7px;padding:10px max(10px,env(safe-area-inset-right)) calc(10px + env(safe-area-inset-bottom)) max(10px,env(safe-area-inset-left))}\n  #usf-custom-studio .uf-footer-copy strong{font-size:10px;max-width:150px}#usf-custom-studio .uf-footer-copy span{font-size:8px}\n  #usf-custom-studio .uf-footer-actions{gap:5px}#usf-custom-studio .uf-footer-actions .uf-secondary{font-size:0;padding:10px;min-width:36px;gap:0}\n  #usf-custom-studio .uf-footer-actions [data-action=downloads]:after{content:'⋯';font-size:18px}#usf-custom-studio .uf-footer-actions [data-action=export-png]:after{content:'↓';font-size:18px}\n  #usf-custom-studio .uf-footer-actions .uf-primary{font-size:10px;padding:10px;max-width:110px;gap:5px}\n  #usf-custom-studio .uf-launch{padding:28px;flex-direction:column;align-items:stretch}#usf-custom-studio .uf-launch h2{font-size:34px}#usf-custom-studio .uf-launch-right{gap:10px}\n  #usf-custom-studio .uf-toast{position:fixed;bottom:84px;font-size:11px}\n}\n@media(max-width:370px){#usf-custom-studio .uf-mark{display:none}#usf-custom-studio .uf-header-actions{gap:5px}#usf-custom-studio .uf-footer-copy{max-width:100px}#usf-custom-studio .uf-footer-actions .uf-primary{max-width:98px;font-size:9px}#usf-custom-studio .uf-library{grid-template-columns:repeat(2,minmax(0,1fr))}#usf-custom-studio .uf-history{display:none}}\n@media(max-height:570px) and (min-width:701px){#usf-custom-studio .uf-dialog{height:calc(100dvh - 12px);width:calc(100vw - 12px)}#usf-custom-studio .uf-dialog[open]{grid-template-rows:54px 62px minmax(0,1fr) 60px}#usf-custom-studio .uf-workspace{grid-template-rows:42px minmax(90px,1fr) 44px auto}#usf-custom-studio .uf-selection-title{display:none}#usf-custom-studio .uf-inspector{padding:7px 10px}#usf-custom-studio .uf-stage-note,#usf-custom-studio .uf-empty\u003espan{display:none}#usf-custom-studio .uf-empty{gap:5px}#usf-custom-studio .uf-empty strong{font-size:13px}#usf-custom-studio .uf-methodbar{padding:4px 18px}}\n@media(prefers-reduced-motion:reduce){#usf-custom-studio *{transition:none!important;animation:none!important;scroll-behavior:auto!important}}\n\n\u003c\/style\u003e\n\u003cscript type=\"application\/json\" data-product=\"\"\u003e{{ product | json | replace: '\u003c', '\\u003c' }}\u003c\/script\u003e\n  \u003cdiv class=\"uf-launch\"\u003e\n\u003cdiv\u003e\n\u003cspan class=\"uf-eyebrow\"\u003eUSASTARFASHION \/ STUDIO 03\u003c\/span\u003e\u003ch2\u003eMake it yours.\u003cbr\u003eMake it extraordinary.\u003c\/h2\u003e\n\u003cp\u003eDesign custom DTF prints and embroidery with your artwork, intelligent tools and a little imagination.\u003c\/p\u003e\n\u003c\/div\u003e\n\u003cdiv class=\"uf-launch-right\"\u003e\n\u003cspan class=\"uf-launch-label\"\u003eYOUR NEXT ORIGINAL STARTS HERE\u003c\/span\u003e\u003cbutton type=\"button\" class=\"uf-primary\" data-action=\"open\"\u003eOpen design studio \u003cspan aria-hidden=\"true\"\u003e↗\u003c\/span\u003e\u003c\/button\u003e\u003csmall\u003eArtwork · AI generation · Personalised text\u003c\/small\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n  \u003cdialog class=\"uf-dialog\" aria-labelledby=\"uf-title\"\u003e\n    \u003cheader class=\"uf-header\"\u003e\u003cdiv class=\"uf-identity\"\u003e\n\u003cspan class=\"uf-mark\" aria-hidden=\"true\"\u003eU\u003cspan\u003e✦\u003c\/span\u003e\u003c\/span\u003e\u003cdiv\u003e\n\u003cstrong\u003eUSASTARFASHION\u003c\/strong\u003e\u003csmall\u003eTHE CUSTOM STUDIO \u003cspan class=\"uf-version\"\u003e03\u003c\/span\u003e\u003c\/small\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv class=\"uf-document-name\"\u003e\n\u003cspan class=\"uf-dot\"\u003e\u003c\/span\u003e\u003cspan id=\"uf-title\"\u003eYour next original\u003c\/span\u003e\u003csmall\u003eDTF \u0026amp; embroidery\u003c\/small\u003e\n\u003c\/div\u003e\n\u003cdiv class=\"uf-header-actions\"\u003e\n\u003cbutton type=\"button\" class=\"uf-secondary\" data-action=\"download-project\"\u003eSave project\u003c\/button\u003e\u003cbutton type=\"button\" class=\"uf-icon\" data-action=\"close\" aria-label=\"Close studio\"\u003e×\u003c\/button\u003e\n\u003c\/div\u003e\u003c\/header\u003e\n    \u003cdiv class=\"uf-methodbar\"\u003e\n\u003cdiv class=\"uf-workflow\"\u003e\n\u003cspan class=\"uf-step-number\"\u003e01\u003c\/span\u003e\u003cspan\u003eCreate your design\u003csmall\u003eStart with a file, an idea or a few words.\u003c\/small\u003e\u003c\/span\u003e\n\u003c\/div\u003e\n      \u003cdiv class=\"uf-methods\" role=\"group\" aria-label=\"Decoration method\"\u003e\n        \u003cbutton type=\"button\" data-method=\"dtf\" aria-pressed=\"true\"\u003e\u003cspan class=\"uf-method-icon\" aria-hidden=\"true\"\u003e▧\u003c\/span\u003e\u003cspan\u003e\u003cstrong\u003eDTF print\u003c\/strong\u003e\u003csmall\u003eFull colour. Fine detail.\u003c\/small\u003e\u003c\/span\u003e\u003c\/button\u003e\n        \u003cbutton type=\"button\" data-method=\"embroidery\" aria-pressed=\"false\"\u003e\u003cspan class=\"uf-method-icon uf-stitch-icon\" aria-hidden=\"true\"\u003e✳\u003c\/span\u003e\u003cspan\u003e\u003cstrong\u003eEmbroidery\u003c\/strong\u003e\u003csmall\u003eThread. Texture. Character.\u003c\/small\u003e\u003c\/span\u003e\u003c\/button\u003e\n      \u003c\/div\u003e\n      \u003cp data-ui=\"method-caption\"\u003eBuild your print with artwork, text, or both.\u003c\/p\u003e\n    \u003c\/div\u003e\n    \u003cdiv class=\"uf-layout\"\u003e\n\u003cdiv class=\"uf-rail\" role=\"tablist\" aria-label=\"Studio tools\" aria-orientation=\"vertical\"\u003e\n          \u003cbutton type=\"button\" id=\"uf-tab-art\" role=\"tab\" aria-selected=\"true\" aria-controls=\"uf-art\" data-tab=\"art\"\u003e\u003csvg viewbox=\"0 0 24 24\" aria-hidden=\"true\"\u003e\u003crect x=\"3\" y=\"3\" width=\"7\" height=\"7\" rx=\"1.5\"\u003e\u003c\/rect\u003e\u003crect x=\"14\" y=\"3\" width=\"7\" height=\"7\" rx=\"1.5\"\u003e\u003c\/rect\u003e\u003crect x=\"3\" y=\"14\" width=\"7\" height=\"7\" rx=\"1.5\"\u003e\u003c\/rect\u003e\u003crect x=\"14\" y=\"14\" width=\"7\" height=\"7\" rx=\"1.5\"\u003e\u003c\/rect\u003e\u003c\/svg\u003e\u003cspan\u003eArtwork\u003c\/span\u003e\u003c\/button\u003e\n          \u003cbutton type=\"button\" id=\"uf-tab-image\" role=\"tab\" aria-selected=\"false\" aria-controls=\"uf-image\" data-tab=\"image\" tabindex=\"-1\"\u003e\u003csvg viewbox=\"0 0 24 24\" aria-hidden=\"true\"\u003e\u003cpath d=\"m12 3 2.6 6.4L21 12l-6.4 2.6L12 21l-2.6-6.4L3 12l6.4-2.6Z\"\u003e\u003c\/path\u003e\u003c\/svg\u003e\u003cspan\u003eAI image\u003c\/span\u003e\u003c\/button\u003e\u003cbutton type=\"button\" id=\"uf-tab-text\" role=\"tab\" aria-selected=\"false\" aria-controls=\"uf-text\" data-tab=\"text\" tabindex=\"-1\"\u003e\u003csvg viewbox=\"0 0 24 24\" aria-hidden=\"true\"\u003e\u003cpath d=\"M4 6V3h16v3M12 3v18M7 21h10\"\u003e\u003c\/path\u003e\u003c\/svg\u003e\u003cspan\u003eText \u0026amp; AI\u003c\/span\u003e\u003c\/button\u003e\n          \u003cbutton type=\"button\" id=\"uf-tab-setup\" role=\"tab\" aria-selected=\"false\" aria-controls=\"uf-setup\" data-tab=\"setup\" tabindex=\"-1\"\u003e\u003csvg viewbox=\"0 0 24 24\" aria-hidden=\"true\"\u003e\u003cpath d=\"M4 6h16M4 12h16M4 18h16\"\u003e\u003c\/path\u003e\u003ccircle cx=\"8\" cy=\"6\" r=\"2\"\u003e\u003c\/circle\u003e\u003ccircle cx=\"16\" cy=\"12\" r=\"2\"\u003e\u003c\/circle\u003e\u003ccircle cx=\"9\" cy=\"18\" r=\"2\"\u003e\u003c\/circle\u003e\u003c\/svg\u003e\u003cspan\u003eProduct\u003c\/span\u003e\u003c\/button\u003e\n          \u003cbutton type=\"button\" id=\"uf-tab-tools\" role=\"tab\" aria-selected=\"false\" aria-controls=\"uf-tools\" data-tab=\"tools\" tabindex=\"-1\"\u003e\u003csvg viewbox=\"0 0 24 24\" aria-hidden=\"true\"\u003e\u003cpath d=\"m4 20 8-8M14 4a6 6 0 0 0 6 6l-3 3-4-1-1-4Z\"\u003e\u003c\/path\u003e\u003cpath d=\"m5 4 4 4-2 2-4-4ZM13 15l6 6 2-2-6-6\"\u003e\u003c\/path\u003e\u003c\/svg\u003e\u003cspan\u003eTools\u003c\/span\u003e\u003c\/button\u003e\n        \u003c\/div\u003e\n      \u003caside class=\"uf-sidebar\" aria-label=\"Design controls\"\u003e\u003cdiv class=\"uf-panel-heading\"\u003e\n\u003cdiv\u003e\n\u003cspan class=\"uf-eyebrow\"\u003eYOUR TOOLKIT\u003c\/span\u003e\u003ch2 data-ui=\"tool-title\"\u003eArtwork library\u003c\/h2\u003e\n\u003c\/div\u003e\n\u003cspan class=\"uf-panel-number\" data-ui=\"tool-number\"\u003e01\u003c\/span\u003e\n\u003c\/div\u003e\n        \n        \u003cdiv class=\"uf-panel-scroll\"\u003e\n\u003csection id=\"uf-image\" hidden=\"\" role=\"tabpanel\" aria-labelledby=\"uf-tab-image\"\u003e\u003cdiv class=\"uf-ai-intro\"\u003e\n\u003cspan class=\"uf-ai-orbit\" aria-hidden=\"true\"\u003e✧\u003c\/span\u003e\u003cspan class=\"uf-eyebrow\"\u003eIMAGINATION, MEET POSSIBILITY\u003c\/span\u003e\u003ch3\u003eFrom an idea\u003cbr\u003eto your next design.\u003c\/h3\u003e\n\u003cp\u003eCreate original artwork for your product.\u003c\/p\u003e\n\u003c\/div\u003e\n\u003clabel class=\"uf-field\"\u003eWhat would you like to create?\u003ctextarea data-input=\"ai-image-prompt\" rows=\"4\" maxlength=\"1200\" placeholder=\"A vintage mountain badge with a rising sun, clean lines and earthy colours…\"\u003e\u003c\/textarea\u003e\u003c\/label\u003e\n\u003cdiv class=\"uf-two\"\u003e\n\u003clabel class=\"uf-field\"\u003eArt direction\u003cselect data-input=\"ai-image-style\"\u003e\u003coption\u003eAuto\u003c\/option\u003e\n\u003coption\u003eVintage\u003c\/option\u003e\n\u003coption\u003eMinimal\u003c\/option\u003e\n\u003coption\u003eBold\u003c\/option\u003e\n\u003coption\u003eBiker\u003c\/option\u003e\n\u003coption\u003eRetro\u003c\/option\u003e\n\u003coption\u003eTypography\u003c\/option\u003e\n\u003coption\u003eIllustration\u003c\/option\u003e\n\u003coption\u003eWatercolour\u003c\/option\u003e\n\u003coption\u003eSports\u003c\/option\u003e\n\u003coption\u003eEmbroidery\u003c\/option\u003e\u003c\/select\u003e\u003c\/label\u003e\u003clabel class=\"uf-field\"\u003eBackground\u003cselect data-input=\"ai-image-background\"\u003e\u003coption value=\"transparent\"\u003eTransparent\u003c\/option\u003e\n\u003coption value=\"light\"\u003eLight\u003c\/option\u003e\u003c\/select\u003e\u003c\/label\u003e\n\u003c\/div\u003e\n\u003cdiv class=\"uf-two\"\u003e\n\u003cbutton type=\"button\" class=\"uf-primary\" data-action=\"generate-image\"\u003e✧ Generate\u003c\/button\u003e\u003cbutton type=\"button\" class=\"uf-secondary\" data-action=\"regenerate-image\" disabled\u003eTry another\u003c\/button\u003e\n\u003c\/div\u003e\n\u003cdiv class=\"uf-ai-image-preview\" data-ui=\"ai-image-preview\"\u003e\n\u003cspan aria-hidden=\"true\"\u003e✦\u003c\/span\u003e\u003cp\u003eYour next creation appears here.\u003c\/p\u003e\n\u003c\/div\u003e\n\u003cp class=\"uf-status\" data-ui=\"ai-image-status\" role=\"status\"\u003eOne original image, ready to customise.\u003c\/p\u003e\n\u003cdiv class=\"uf-two\"\u003e\n\u003cbutton type=\"button\" class=\"uf-primary\" data-action=\"use-ai-image\" disabled\u003eAdd to product\u003c\/button\u003e\u003cbutton type=\"button\" class=\"uf-secondary\" data-action=\"download-ai-image\" disabled\u003eDownload image\u003c\/button\u003e\n\u003c\/div\u003e\n\u003cp class=\"uf-hint\"\u003eTransparency is requested from your image service. Review the result before production.\u003c\/p\u003e\u003c\/section\u003e\n          \u003csection id=\"uf-art\" role=\"tabpanel\" aria-labelledby=\"uf-tab-art\"\u003e\n            \u003cdiv class=\"uf-section-heading\"\u003e\u003cdiv\u003e\n\u003cspan class=\"uf-eyebrow\"\u003e01 \/ ADD YOUR DESIGN\u003c\/span\u003e\u003ch3\u003eStart with artwork\u003c\/h3\u003e\n\u003c\/div\u003e\u003c\/div\u003e\n            \u003clabel class=\"uf-upload\" data-ui=\"dropzone\"\u003e\u003cinput type=\"file\" data-input=\"upload\" accept=\"image\/png,image\/jpeg,image\/webp\" multiple\u003e\u003cspan class=\"uf-upload-icon\" aria-hidden=\"true\"\u003e↥\u003c\/span\u003e\u003cstrong\u003eUpload your artwork\u003c\/strong\u003e\u003cspan\u003eDrop files here or browse\u003c\/span\u003e\u003csmall\u003ePNG, JPG or WebP · up to 15 MB each\u003c\/small\u003e\u003c\/label\u003e\n            \u003cp class=\"uf-hint\" data-ui=\"upload-hint\"\u003eTransparent PNG works well for DTF artwork.\u003c\/p\u003e\n            \u003cdiv class=\"uf-section-heading uf-library-heading\"\u003e\n\u003ch3\u003eFrom your library\u003c\/h3\u003e\n\u003cbutton type=\"button\" class=\"uf-link\" data-action=\"refresh-library\"\u003eRefresh\u003c\/button\u003e\n\u003c\/div\u003e\n            \u003clabel class=\"uf-search\"\u003e\u003cspan aria-hidden=\"true\"\u003e⌕\u003c\/span\u003e\u003cinput type=\"search\" data-input=\"library-search\" aria-label=\"Search Google Drive artwork\" placeholder=\"Search artwork or category\"\u003e\u003c\/label\u003e\n            \u003cp class=\"uf-status\" data-ui=\"library-status\" role=\"status\"\u003eYour Google Drive artwork appears here.\u003c\/p\u003e\n            \u003cdiv class=\"uf-library\" data-ui=\"library\"\u003e\u003c\/div\u003e\n            \u003cbutton type=\"button\" class=\"uf-secondary uf-wide\" data-action=\"more-library\" hidden=\"\"\u003eShow more artwork\u003c\/button\u003e\n          \u003c\/section\u003e\n          \u003csection id=\"uf-text\" role=\"tabpanel\" aria-labelledby=\"uf-tab-text\" hidden=\"\"\u003e\n            \u003cspan class=\"uf-eyebrow\"\u003eWORDS THAT MAKE IT YOURS\u003c\/span\u003e\u003ch3\u003eSay it your way.\u003c\/h3\u003e\n            \u003clabel class=\"uf-field\"\u003eYour text\u003ctextarea data-input=\"text\" rows=\"3\" maxlength=\"180\" placeholder=\"Your name, your team, your message…\"\u003e\u003c\/textarea\u003e\u003c\/label\u003e\n            \u003cdiv class=\"uf-two\"\u003e\n\u003clabel class=\"uf-field\"\u003eFont\u003cselect data-input=\"font\"\u003e\u003coption value=\"Professional\"\u003eModern sans\u003c\/option\u003e\n\u003coption value=\"Bold\"\u003eBold display\u003c\/option\u003e\n\u003coption value=\"Vintage\"\u003eVintage\u003c\/option\u003e\n\u003coption value=\"Biker\"\u003eBiker\u003c\/option\u003e\n\u003coption value=\"Retro\"\u003eRetro\u003c\/option\u003e\n\u003coption value=\"Funny\"\u003eHandwritten\u003c\/option\u003e\n\u003coption value=\"Wedding\"\u003eWedding script\u003c\/option\u003e\n\u003coption value=\"Birthday\"\u003eCelebration\u003c\/option\u003e\n\u003coption value=\"Sports\"\u003eVarsity\u003c\/option\u003e\n\u003coption value=\"Elegant\"\u003eElegant serif\u003c\/option\u003e\n\u003coption value=\"Script\"\u003eScript\u003c\/option\u003e\n\u003coption value=\"Classic\"\u003eClassic slab\u003c\/option\u003e\u003c\/select\u003e\u003c\/label\u003e\u003clabel class=\"uf-field\"\u003eColour\u003cinput type=\"color\" data-input=\"text-colour\" value=\"#172c42\"\u003e\u003c\/label\u003e\n\u003c\/div\u003e\n            \u003clabel class=\"uf-field\"\u003eFind a font\u003cinput type=\"search\" data-input=\"font-search\" placeholder=\"Search 40+ fonts by name or style\"\u003e\u003c\/label\u003e\n            \u003cdiv class=\"uf-format-row\" role=\"group\" aria-label=\"Text style\"\u003e\n\u003cbutton type=\"button\" data-action=\"bold\" aria-pressed=\"true\"\u003e\u003cb\u003eB\u003c\/b\u003e\u003c\/button\u003e\u003cbutton type=\"button\" data-action=\"italic\" aria-pressed=\"false\"\u003e\u003ci\u003eI\u003c\/i\u003e\u003c\/button\u003e\u003cbutton type=\"button\" data-action=\"underline\" aria-pressed=\"false\"\u003e\u003cu\u003eU\u003c\/u\u003e\u003c\/button\u003e\u003cbutton type=\"button\" data-action=\"uppercase\"\u003eABC\u003c\/button\u003e\n\u003c\/div\u003e\n\u003cdiv class=\"uf-two\"\u003e\n\u003clabel class=\"uf-field\"\u003eFont weight\u003cselect data-input=\"font-weight\"\u003e\u003coption value=\"400\"\u003eRegular 400\u003c\/option\u003e\n\u003coption value=\"500\"\u003eMedium 500\u003c\/option\u003e\n\u003coption value=\"600\"\u003eSemibold 600\u003c\/option\u003e\n\u003coption value=\"700\" selected\u003eBold 700\u003c\/option\u003e\n\u003coption value=\"800\"\u003eExtra bold 800\u003c\/option\u003e\n\u003coption value=\"900\"\u003eBlack 900\u003c\/option\u003e\u003c\/select\u003e\u003c\/label\u003e\u003clabel class=\"uf-field\"\u003eText size (%)\u003cinput data-input=\"text-size\" type=\"number\" min=\"10\" max=\"95\" value=\"74\"\u003e\u003c\/label\u003e\n\u003c\/div\u003e\n\u003clabel class=\"uf-check uf-shadow-check\"\u003e\u003cinput type=\"checkbox\" data-input=\"shadow\"\u003eSoft text shadow\u003c\/label\u003e\n            \u003cdiv class=\"uf-two\"\u003e\n\u003clabel class=\"uf-field\"\u003eLetter spacing\u003cinput data-input=\"tracking\" type=\"number\" min=\"-10\" max=\"30\" step=\"1\" value=\"0\"\u003e\u003c\/label\u003e\u003clabel class=\"uf-field\"\u003eLine height\u003cselect data-input=\"leading\"\u003e\u003coption value=\"1\"\u003eCompact\u003c\/option\u003e\n\u003coption value=\"1.2\" selected\u003eNormal\u003c\/option\u003e\n\u003coption value=\"1.5\"\u003eRelaxed\u003c\/option\u003e\n\u003coption value=\"1.8\"\u003eWide\u003c\/option\u003e\u003c\/select\u003e\u003c\/label\u003e\n\u003c\/div\u003e\n            \u003cdiv class=\"uf-two\"\u003e\n\u003clabel class=\"uf-field\"\u003eText alignment\u003cselect data-input=\"text-align\"\u003e\u003coption value=\"center\"\u003eCentre\u003c\/option\u003e\n\u003coption value=\"left\"\u003eLeft\u003c\/option\u003e\n\u003coption value=\"right\"\u003eRight\u003c\/option\u003e\u003c\/select\u003e\u003c\/label\u003e\u003clabel class=\"uf-field\"\u003eOutline (mm)\u003cinput data-input=\"outline\" type=\"number\" min=\"0\" max=\"4\" step=\"0.1\" value=\"0\"\u003e\u003c\/label\u003e\n\u003c\/div\u003e\n            \u003clabel class=\"uf-field\"\u003eOutline colour\u003cinput data-input=\"outline-colour\" type=\"color\" value=\"#ffffff\"\u003e\u003c\/label\u003e\n            \u003cdetails class=\"uf-details\"\u003e\u003csummary\u003eReady-made font styles\u003c\/summary\u003e\u003cdiv class=\"uf-presets\" data-ui=\"font-presets\"\u003e\u003c\/div\u003e\u003c\/details\u003e\n            \u003cdiv class=\"uf-text-sample\" data-ui=\"text-sample\"\u003eYOUR TEXT\u003c\/div\u003e\n            \u003cdiv class=\"uf-two\"\u003e\n\u003cbutton type=\"button\" class=\"uf-primary\" data-action=\"add-text\"\u003eAdd text\u003c\/button\u003e\u003cbutton type=\"button\" class=\"uf-secondary\" data-action=\"update-text\"\u003eUpdate selected\u003c\/button\u003e\n\u003c\/div\u003e\n            \u003cdiv class=\"uf-ai-card\"\u003e\n\u003cdiv class=\"uf-ai-title\"\u003e\n\u003cspan aria-hidden=\"true\"\u003e✧\u003c\/span\u003e\u003cdiv\u003e\n\u003cstrong\u003eA little inspiration\u003c\/strong\u003e\u003csmall\u003eYour AI text assistant\u003c\/small\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n              \u003clabel class=\"uf-field\"\u003eDescribe your idea\u003ctextarea data-input=\"ai-prompt\" rows=\"3\" maxlength=\"1000\" placeholder=\"A short, bold slogan for our running club\"\u003e\u003c\/textarea\u003e\u003c\/label\u003e\n              \u003clabel class=\"uf-field\"\u003eWriting style\u003cselect data-input=\"ai-style\"\u003e\u003coption\u003eAuto\u003c\/option\u003e\n\u003coption\u003eProfessional\u003c\/option\u003e\n\u003coption\u003eBold\u003c\/option\u003e\n\u003coption\u003eVintage\u003c\/option\u003e\n\u003coption\u003eBiker\u003c\/option\u003e\n\u003coption\u003eRetro\u003c\/option\u003e\n\u003coption\u003eFunny\u003c\/option\u003e\n\u003coption\u003eWedding\u003c\/option\u003e\n\u003coption\u003eBirthday\u003c\/option\u003e\n\u003coption\u003eSports\u003c\/option\u003e\n\u003coption\u003eElegant\u003c\/option\u003e\n\u003coption\u003eScript\u003c\/option\u003e\n\u003coption\u003eClassic\u003c\/option\u003e\u003c\/select\u003e\u003c\/label\u003e\n              \u003cdiv class=\"uf-two\"\u003e\n\u003cbutton type=\"button\" class=\"uf-primary\" data-action=\"generate\"\u003eGenerate text\u003c\/button\u003e\u003cbutton type=\"button\" class=\"uf-secondary\" data-action=\"regenerate\" disabled\u003eTry another\u003c\/button\u003e\n\u003c\/div\u003e\n              \u003cp class=\"uf-status\" role=\"status\" data-ui=\"ai-status\"\u003eOne idea at a time, with a matching font.\u003c\/p\u003e\n              \u003cbutton type=\"button\" class=\"uf-secondary uf-wide\" data-action=\"use-ai\" hidden=\"\"\u003eUse this text\u003c\/button\u003e\n            \u003c\/div\u003e\n          \u003c\/section\u003e\n          \u003csection id=\"uf-tools\" role=\"tabpanel\" aria-labelledby=\"uf-tab-tools\" hidden=\"\"\u003e\n            \u003cspan class=\"uf-eyebrow\"\u003eADVANCED EDITING\u003c\/span\u003e\u003ch3\u003eRefine every detail\u003c\/h3\u003e\n\u003cp class=\"uf-hint\"\u003eSelect a layer on the product or in the layer list.\u003c\/p\u003e\n            \u003cp class=\"uf-status\" data-ui=\"artwork-quality\"\u003e\u003c\/p\u003e\n            \u003cdiv class=\"uf-two\"\u003e\n\u003clabel class=\"uf-field\"\u003ePosition X (mm)\u003cinput data-input=\"position-x\" type=\"number\" step=\"0.5\" disabled\u003e\u003c\/label\u003e\u003clabel class=\"uf-field\"\u003ePosition Y (mm)\u003cinput data-input=\"position-y\" type=\"number\" step=\"0.5\" disabled\u003e\u003c\/label\u003e\n\u003c\/div\u003e\n            \u003clabel class=\"uf-field\"\u003eOpacity \u003cinput data-input=\"opacity\" type=\"range\" min=\"10\" max=\"100\" value=\"100\" disabled\u003e\u003c\/label\u003e\n            \u003cdiv class=\"uf-tool-grid\"\u003e\n\u003cbutton type=\"button\" class=\"uf-secondary\" data-action=\"flip-x\"\u003eFlip horizontal\u003c\/button\u003e\u003cbutton type=\"button\" class=\"uf-secondary\" data-action=\"flip-y\"\u003eFlip vertical\u003c\/button\u003e\u003cbutton type=\"button\" class=\"uf-secondary\" data-action=\"rotate-left\"\u003eRotate −90°\u003c\/button\u003e\u003cbutton type=\"button\" class=\"uf-secondary\" data-action=\"rotate-right\"\u003eRotate +90°\u003c\/button\u003e\u003cbutton type=\"button\" class=\"uf-secondary\" data-action=\"align-left\"\u003eAlign left\u003c\/button\u003e\u003cbutton type=\"button\" class=\"uf-secondary\" data-action=\"align-right\"\u003eAlign right\u003c\/button\u003e\u003cbutton type=\"button\" class=\"uf-secondary\" data-action=\"align-top\"\u003eAlign top\u003c\/button\u003e\u003cbutton type=\"button\" class=\"uf-secondary\" data-action=\"align-bottom\"\u003eAlign bottom\u003c\/button\u003e\u003cbutton type=\"button\" class=\"uf-secondary\" data-action=\"bring-front\"\u003eBring to front\u003c\/button\u003e\u003cbutton type=\"button\" class=\"uf-secondary\" data-action=\"send-back\"\u003eSend to back\u003c\/button\u003e\u003cbutton type=\"button\" class=\"uf-secondary\" data-action=\"lock-layer\"\u003eLock layer\u003c\/button\u003e\u003cbutton type=\"button\" class=\"uf-secondary\" data-action=\"hide-layer\"\u003eHide layer\u003c\/button\u003e\n\u003c\/div\u003e\n            \u003cdetails class=\"uf-details\"\u003e\u003csummary\u003eImage adjustments\u003c\/summary\u003e\u003cp class=\"uf-hint\"\u003eApplies to the selected image. Undo restores the previous version.\u003c\/p\u003e\n\u003clabel class=\"uf-field\"\u003eWhite removal tolerance\u003cinput data-input=\"white-tolerance\" type=\"range\" min=\"0\" max=\"100\" value=\"25\"\u003e\u003c\/label\u003e\u003cdiv class=\"uf-tool-grid\"\u003e\n\u003cbutton type=\"button\" class=\"uf-secondary\" data-action=\"remove-white\"\u003eRemove white\u003c\/button\u003e\u003cbutton type=\"button\" class=\"uf-secondary\" data-action=\"grayscale\"\u003eGreyscale\u003c\/button\u003e\u003cbutton type=\"button\" class=\"uf-secondary\" data-action=\"high-contrast\"\u003eHigh contrast\u003c\/button\u003e\u003cbutton type=\"button\" class=\"uf-secondary\" data-action=\"trim-image\"\u003eTrim transparent\u003c\/button\u003e\n\u003c\/div\u003e\n\u003cp class=\"uf-hint\"\u003eWhite removal removes near-white pixels; it is not AI background removal.\u003c\/p\u003e\u003c\/details\u003e\n            \u003cdetails class=\"uf-details\" open=\"\"\u003e\u003csummary\u003eDownload your work\u003c\/summary\u003e\u003cdiv class=\"uf-downloads\"\u003e\n\u003cbutton type=\"button\" class=\"uf-secondary\" data-action=\"download-artwork\"\u003eSelected artwork file\u003c\/button\u003e\u003cbutton type=\"button\" class=\"uf-secondary\" data-action=\"download-mockup\"\u003eProduct preview PNG\u003c\/button\u003e\u003cbutton type=\"button\" class=\"uf-secondary\" data-action=\"download-package\"\u003eAll designs + sources ZIP\u003c\/button\u003e\n\u003c\/div\u003e\n\u003cp class=\"uf-hint\"\u003eZIP includes every populated placement for the current method, source artwork, and an editable project. Hidden layers are excluded.\u003c\/p\u003e\u003c\/details\u003e\n          \u003c\/section\u003e\n          \u003csection id=\"uf-setup\" role=\"tabpanel\" aria-labelledby=\"uf-tab-setup\" hidden=\"\"\u003e\n            \u003cspan class=\"uf-eyebrow\"\u003e02 \/ MAKE IT FIT\u003c\/span\u003e\u003ch3\u003eProduct \u0026amp; placement\u003c\/h3\u003e\n            \u003cdiv class=\"uf-product\"\u003e\n\u003cimg data-ui=\"product-thumb\" alt=\"\"\u003e\u003cdiv\u003e\n\u003cstrong data-ui=\"product-title\"\u003eLoading product\u003c\/strong\u003e\u003csmall data-ui=\"product-price\"\u003e\u003c\/small\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n            \u003clabel class=\"uf-field\"\u003eProduct option\u003cselect data-input=\"variant\"\u003e\u003c\/select\u003e\u003c\/label\u003e\n            \u003clabel class=\"uf-field\"\u003ePlacement\u003cselect data-input=\"placement\"\u003e\u003c\/select\u003e\u003c\/label\u003e\n            \u003cdiv class=\"uf-two\"\u003e\n\u003clabel class=\"uf-field\"\u003eArea width (mm)\u003cinput data-input=\"area-width\" type=\"number\" min=\"20\" max=\"450\" step=\"1\" value=\"280\"\u003e\u003c\/label\u003e\u003clabel class=\"uf-field\"\u003eArea height (mm)\u003cinput data-input=\"area-height\" type=\"number\" min=\"20\" max=\"450\" step=\"1\" value=\"350\"\u003e\u003c\/label\u003e\n\u003c\/div\u003e\n            \u003cp class=\"uf-hint\"\u003eRequested design dimensions. The garment preview is illustrative; confirm production sizing with your supplier.\u003c\/p\u003e\n            \u003cdiv data-ui=\"embroidery-settings\" hidden=\"\"\u003e\n              \u003clabel class=\"uf-field\"\u003eThread colour for selected text\u003cselect data-input=\"thread\"\u003e\u003coption value=\"#f4eee0\"\u003eIvory\u003c\/option\u003e\n\u003coption value=\"#152d47\"\u003eNavy\u003c\/option\u003e\n\u003coption value=\"#222222\"\u003eBlack\u003c\/option\u003e\n\u003coption value=\"#ffffff\"\u003eWhite\u003c\/option\u003e\n\u003coption value=\"#b18a45\"\u003eGold\u003c\/option\u003e\n\u003coption value=\"#a5233d\"\u003eRed\u003c\/option\u003e\n\u003coption value=\"#316d54\"\u003eForest green\u003c\/option\u003e\u003c\/select\u003e\u003c\/label\u003e\n              \u003clabel class=\"uf-field\"\u003eEmbroidery finish\u003cselect data-input=\"finish\"\u003e\u003coption\u003eFlat embroidery\u003c\/option\u003e\n\u003coption\u003e3D puff request\u003c\/option\u003e\u003c\/select\u003e\u003c\/label\u003e\n              \u003cdiv class=\"uf-callout\"\u003eEmbroidery is a design preview. Stitch files, thread matching, and digitising require production review.\u003c\/div\u003e\n            \u003c\/div\u003e\n            \u003cdiv data-ui=\"dtf-settings\"\u003e\u003cdiv class=\"uf-callout\"\u003eDTF export creates a transparent PNG at the requested dimensions and 300 pixels per inch. Image quality depends on the original artwork.\u003c\/div\u003e\u003c\/div\u003e\n            \u003clabel class=\"uf-field\"\u003eQuantity\u003cinput type=\"number\" data-input=\"quantity\" min=\"1\" max=\"999\" value=\"1\" step=\"1\"\u003e\u003c\/label\u003e\n            \u003clabel class=\"uf-field\"\u003eProduction notes\u003ctextarea data-input=\"notes\" rows=\"3\" maxlength=\"500\" placeholder=\"Placement, thread or finishing requests\"\u003e\u003c\/textarea\u003e\u003c\/label\u003e\n            \u003cdiv class=\"uf-two\"\u003e\n\u003cbutton type=\"button\" class=\"uf-secondary\" data-action=\"download-project\"\u003eSave project\u003c\/button\u003e\u003cbutton type=\"button\" class=\"uf-secondary\" data-action=\"import-project\"\u003eOpen project\u003c\/button\u003e\n\u003c\/div\u003e\n            \u003cinput hidden=\"\" type=\"file\" data-input=\"project-file\" accept=\"application\/json,.json\"\u003e\n          \u003c\/section\u003e\n          \u003csection class=\"uf-layers-section\"\u003e\u003cdiv class=\"uf-section-heading\"\u003e\n\u003ch3\u003eLayers\u003c\/h3\u003e\n\u003csmall data-ui=\"layer-count\"\u003e0 items\u003c\/small\u003e\n\u003c\/div\u003e\n\u003cdiv data-ui=\"layers\" class=\"uf-layers\"\u003e\u003c\/div\u003e\u003c\/section\u003e\n        \u003c\/div\u003e\n      \u003c\/aside\u003e\n      \u003cmain class=\"uf-workspace\"\u003e\n        \u003cdiv class=\"uf-canvas-toolbar\"\u003e\n\u003cdiv\u003e\n\u003cspan class=\"uf-dot\"\u003e\u003c\/span\u003e\u003cstrong data-ui=\"view-label\"\u003eFront print\u003c\/strong\u003e\u003cspan class=\"uf-dimensions\" data-ui=\"dimensions\"\u003e280 × 350 mm\u003c\/span\u003e\n\u003c\/div\u003e\n\u003cdiv class=\"uf-history\"\u003e\n\u003cbutton type=\"button\" class=\"uf-icon\" data-action=\"undo\" aria-label=\"Undo\" title=\"Undo (Ctrl+Z)\" disabled\u003e↶\u003c\/button\u003e\u003cbutton type=\"button\" class=\"uf-icon\" data-action=\"redo\" aria-label=\"Redo\" title=\"Redo (Ctrl+Shift+Z)\" disabled\u003e↷\u003c\/button\u003e\n\u003c\/div\u003e\n\u003cdiv class=\"uf-canvas-controls\"\u003e\n\u003cbutton type=\"button\" class=\"uf-icon\" data-action=\"zoom-out\" aria-label=\"Zoom out\"\u003e−\u003c\/button\u003e\u003cbutton type=\"button\" class=\"uf-zoom-value\" data-action=\"zoom-reset\" title=\"Reset zoom\" data-ui=\"zoom-value\"\u003e100%\u003c\/button\u003e\u003cbutton type=\"button\" class=\"uf-icon\" data-action=\"zoom-in\" aria-label=\"Zoom in\"\u003e+\u003c\/button\u003e\u003cbutton type=\"button\" class=\"uf-icon\" data-action=\"toggle-grid\" aria-label=\"Toggle canvas grid\" aria-pressed=\"true\"\u003e▦\u003c\/button\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n        \u003cdiv class=\"uf-stage\" data-ui=\"stage\"\u003e\n\u003cdiv class=\"uf-stage-note\"\u003e\n\u003cspan class=\"uf-eyebrow\"\u003eTHE DESIGN CANVAS\u003c\/span\u003e\u003cp\u003eA blank canvas.\u003cbr\u003eUnlimited possibilities.\u003c\/p\u003e\n\u003c\/div\u003e\n\u003csvg class=\"uf-scene\" data-ui=\"scene\" viewbox=\"0 0 600 650\" role=\"img\" aria-label=\"Interactive product design preview\"\u003e\u003cdefs\u003e\u003clineargradient id=\"uf-fabric\" x1=\"0\" x2=\"1\"\u003e\u003cstop stop-color=\"#e6e5df\"\u003e\u003c\/stop\u003e\u003cstop offset=\".5\" stop-color=\"#fdfcf6\"\u003e\u003c\/stop\u003e\u003cstop offset=\"1\" stop-color=\"#dddcd4\"\u003e\u003c\/stop\u003e\u003c\/lineargradient\u003e\u003c\/defs\u003e\u003cg data-ui=\"garment\"\u003e\u003cpath d=\"M190 70 100 103 32 216 122 259 152 208 152 589 Q300 615 448 589 L448 208 478 259 568 216 500 103 410 70 Q350 112 300 108 Q250 112 190 70Z\" fill=\"url(#uf-fabric)\" stroke=\"#cecec5\" stroke-width=\"1.5\"\u003e\u003c\/path\u003e\u003cpath d=\"M245 81Q300 150 355 81M158 578Q300 602 442 578M152 208 159 160M448 208 441 160\" fill=\"none\" stroke=\"#c8c9c0\" stroke-width=\"2\"\u003e\u003c\/path\u003e\u003c\/g\u003e\u003cimage data-ui=\"product-image\" x=\"0\" y=\"0\" width=\"600\" height=\"650\" preserveaspectratio=\"xMidYMid meet\"\u003e\u003c\/image\u003e\u003cg data-ui=\"design-scene\"\u003e\u003c\/g\u003e\u003c\/svg\u003e\u003cdiv class=\"uf-empty\" data-ui=\"empty\"\u003e\n\u003cspan class=\"uf-empty-symbol\" aria-hidden=\"true\"\u003e+\u003c\/span\u003e\u003cstrong\u003eSomething original\u003cbr\u003estarts with you.\u003c\/strong\u003e\u003cspan\u003eUpload artwork, add text or create with AI.\u003c\/span\u003e\u003cbutton type=\"button\" class=\"uf-secondary\" data-action=\"start-ai-image\"\u003eCreate with AI \u003cspan aria-hidden=\"true\"\u003e✧\u003c\/span\u003e\u003c\/button\u003e\n\u003c\/div\u003e\n\u003cspan class=\"uf-preview-disclaimer\" data-ui=\"preview-disclaimer\"\u003eIllustrative garment · front\u003c\/span\u003e\n\u003c\/div\u003e\n        \u003cdiv class=\"uf-viewbar\"\u003e\n\u003cdiv data-ui=\"views\" class=\"uf-views\" aria-label=\"Design placement\"\u003e\u003c\/div\u003e\n\u003cbutton type=\"button\" class=\"uf-link\" data-action=\"toggle-guides\" aria-pressed=\"true\"\u003eHide guides\u003c\/button\u003e\n\u003c\/div\u003e\n        \u003csection class=\"uf-inspector\" aria-label=\"Selected design controls\"\u003e\u003cdiv class=\"uf-selection-title\"\u003e\n\u003cstrong data-ui=\"selection-name\"\u003eSelect an artwork or text layer\u003c\/strong\u003e\u003csmall data-ui=\"selection-hint\"\u003eDrag to position. Use the controls to refine.\u003c\/small\u003e\n\u003c\/div\u003e\n\u003cdiv class=\"uf-inspector-controls\"\u003e\n\u003clabel\u003eWidth \u003cspan\u003e\u003cinput data-input=\"object-width\" type=\"number\" min=\"5\" step=\"1\" disabled\u003e mm\u003c\/span\u003e\u003c\/label\u003e\u003clabel\u003eRotate \u003cspan\u003e\u003cinput data-input=\"rotation\" type=\"number\" min=\"-180\" max=\"180\" step=\"1\" disabled\u003e °\u003c\/span\u003e\u003c\/label\u003e\u003cbutton type=\"button\" class=\"uf-icon\" data-action=\"center\" aria-label=\"Centre selected layer\" title=\"Centre\" disabled\u003e⊙\u003c\/button\u003e\u003cbutton type=\"button\" class=\"uf-icon\" data-action=\"duplicate\" aria-label=\"Duplicate selected layer\" title=\"Duplicate\" disabled\u003e⧉\u003c\/button\u003e\u003cbutton type=\"button\" class=\"uf-icon uf-delete\" data-action=\"delete\" aria-label=\"Delete selected layer\" title=\"Delete\" disabled\u003e×\u003c\/button\u003e\n\u003c\/div\u003e\u003c\/section\u003e\n      \u003c\/main\u003e\n    \u003c\/div\u003e\n    \u003cfooter class=\"uf-footer uf-production-bar\"\u003e\u003cdiv class=\"uf-footer-seal\" aria-hidden=\"true\"\u003e✦\u003c\/div\u003e\n\u003cdiv class=\"uf-footer-copy\"\u003e\n\u003cstrong data-ui=\"footer-title\"\u003eYour custom creation\u003c\/strong\u003e\u003cspan data-ui=\"footer-detail\"\u003eDTF print · no artwork yet\u003c\/span\u003e\n\u003c\/div\u003e\n\u003cdiv class=\"uf-footer-actions\"\u003e\n\u003cbutton type=\"button\" class=\"uf-secondary\" data-action=\"downloads\"\u003eDownloads\u003c\/button\u003e\u003cbutton type=\"button\" class=\"uf-secondary\" data-action=\"export-png\"\u003eExport design\u003c\/button\u003e\u003cbutton type=\"button\" class=\"uf-primary\" data-action=\"review\"\u003eReview \u0026amp; add to cart \u003cspan aria-hidden=\"true\"\u003e→\u003c\/span\u003e\u003c\/button\u003e\n\u003c\/div\u003e\u003c\/footer\u003e\n    \u003cdiv class=\"uf-toast\" data-ui=\"toast\" role=\"status\" aria-live=\"polite\" hidden=\"\"\u003e\u003c\/div\u003e\n    \u003cdiv class=\"uf-review-backdrop\" data-ui=\"review-backdrop\" hidden=\"\"\u003e\u003c\/div\u003e\n    \u003csection class=\"uf-review\" data-ui=\"review\" role=\"dialog\" aria-modal=\"true\" aria-labelledby=\"uf-review-title\" hidden=\"\"\u003e\u003cheader\u003e\u003cdiv\u003e\n\u003cspan class=\"uf-eyebrow\"\u003eONE LAST LOOK\u003c\/span\u003e\u003ch3 id=\"uf-review-title\"\u003eYour custom order\u003c\/h3\u003e\n\u003c\/div\u003e\n\u003cbutton type=\"button\" class=\"uf-icon\" data-action=\"close-review\" aria-label=\"Close order review\"\u003e×\u003c\/button\u003e\u003c\/header\u003e\u003cdiv data-ui=\"review-content\"\u003e\u003c\/div\u003e\n\u003cp class=\"uf-hint\"\u003eProduct subtotal uses the selected Shopify variant. Decoration, digitising and shipping charges are not calculated here.\u003c\/p\u003e\n\u003clabel class=\"uf-check\"\u003e\u003cinput type=\"checkbox\" data-input=\"confirm\"\u003eI have checked the spelling, placement and requested dimensions.\u003c\/label\u003e\u003cbutton type=\"button\" class=\"uf-primary uf-wide\" data-action=\"add-cart\" disabled\u003eAdd to cart\u003c\/button\u003e\u003cp class=\"uf-status\" role=\"status\" data-ui=\"cart-status\"\u003e\u003c\/p\u003e\u003c\/section\u003e\n  \u003c\/dialog\u003e\n\u003cscript\u003e\n\/* Pure model helpers shared by the studio and its tests. *\/\nconst USFModel = (() =\u003e {\n  const placements = {\n    dtf: {\n      front:{label:'Front print',side:'front',rect:[210,188,180,230],width:280,height:350},\n      back:{label:'Back print',side:'back',rect:[202,175,196,250],width:300,height:380},\n      leftSleeve:{label:'Left sleeve',side:'leftSleeve',rect:[100,143,53,64],width:90,height:110},\n      rightSleeve:{label:'Right sleeve',side:'rightSleeve',rect:[447,143,53,64],width:90,height:110}\n    },\n    embroidery:{\n      leftChest:{label:'Left chest',side:'front',rect:[333,203,78,72],width:100,height:90},\n      centre:{label:'Centre chest',side:'front',rect:[258,203,84,70],width:110,height:90},\n      back:{label:'Upper back',side:'back',rect:[228,190,144,88],width:200,height:120},\n      sleeve:{label:'Sleeve',side:'leftSleeve',rect:[101,148,50,53],width:80,height:80}\n    }\n  };\n  const clamp=(v,a,b)=\u003eMath.min(b,Math.max(a,Number(v)||0));\n  const blank=()=\u003eObject.fromEntries(Object.entries(placements).map(([method,items])=\u003e[method,Object.fromEntries(Object.entries(items).map(([key,p])=\u003e[key,{width:p.width,height:p.height,objects:[]}]))]));\n  function bounds(o){const a=(Number(o.rotation)||0)*Math.PI\/180;return {w:Math.abs(o.w*Math.cos(a))+Math.abs(o.h*Math.sin(a)),h:Math.abs(o.w*Math.sin(a))+Math.abs(o.h*Math.cos(a))};}\n  function fit(o,area){let b=bounds(o);const scale=Math.min(1,area.width\/b.w,area.height\/b.h);o.w*=scale;o.h*=scale;b=bounds(o);o.x=clamp(o.x,b.w\/2,area.width-b.w\/2);o.y=clamp(o.y,b.h\/2,area.height-b.h\/2);return o;}\n  function rect(placement,area){const[x,y,w,h]=placement.rect,scale=Math.min(w\/area.width,h\/area.height),rw=area.width*scale,rh=area.height*scale;return [x+(w-rw)\/2,y+(h-rh)\/2,rw,rh];}\n  function pngDpi(bytes,dpi=300){\n    const read=(a,i)=\u003enew DataView(a.buffer,a.byteOffset,a.byteLength).getUint32(i);\n    const chunk=new Uint8Array(21),view=new DataView(chunk.buffer);view.setUint32(0,9);chunk.set([112,72,89,115],4);view.setUint32(8,Math.round(dpi\/0.0254));view.setUint32(12,Math.round(dpi\/0.0254));chunk[16]=1;\n    let crc=0xffffffff;for(const byte of chunk.slice(4,17)){crc^=byte;for(let bit=0;bit\u003c8;bit++)crc=(crc\u003e\u003e\u003e1)^((crc\u00261)?0xedb88320:0);}view.setUint32(17,(crc^0xffffffff)\u003e\u003e\u003e0);\n    const parts=[bytes.slice(0,8)];let offset=8,inserted=false;while(offset\u003cbytes.length){const len=read(bytes,offset),type=String.fromCharCode(...bytes.slice(offset+4,offset+8));if(type!=='pHYs')parts.push(bytes.slice(offset,offset+len+12));if(type==='IHDR'){parts.push(chunk);inserted=true;}offset+=len+12;}if(!inserted)throw Error('Invalid PNG image.');const result=new Uint8Array(parts.reduce((n,p)=\u003en+p.length,0));let at=0;for(const p of parts){result.set(p,at);at+=p.length;}return result;\n  }\n  function parseAI(reply){\n    let s=String(reply||'').trim().replace(\/^```(?:json)?\\s*\/i,'').replace(\/\\s*```$\/,'');\n    const block=s.match(\/\\{[\\s\\S]*\\}\/);\n    if(block){try{const j=JSON.parse(block[0]);if(typeof j.text==='string'\u0026\u0026j.text.trim())return {text:j.text.trim().slice(0,180),fontStyle:String(j.fontStyle||'Professional')};}catch{}}\n    const text=s.split(\/\\r?\\n\/).map(x=\u003ex.trim().replace(\/^[\"'`]|[\"'`]$\/g,'')).find(Boolean)||'';\n    return {text:text.slice(0,180),fontStyle:'Professional'};\n  }\n  function normaliseLibrary(data){return (Array.isArray(data?.items)?data.items:[]).map((x,i)=\u003e({id:String(x.libraryId||x.id||i),fileId:String(x.fileId||x.driveId||''),name:String(x.name||'Artwork'),category:String(x.category||'Artwork'),src:String(x.imageUrl||''),downloadUrl:\/^https:\\\/\\\/\/i.test(x.downloadUrl||'')?x.downloadUrl:''})).filter(x=\u003e\/^https:\\\/\\\/\/i.test(x.src));}\n  function style(o={}){const weight=clamp(o.fontWeight??(o.bold===false?400:700),400,900);return {bold:weight\u003e=600,fontWeight:weight,fontSize:clamp(o.fontSize??74,10,95),italic:!!o.italic,underline:!!o.underline,shadow:!!o.shadow,tracking:clamp(o.tracking??o.letterSpacing,-10,30),leading:[1,1.2,1.5,1.8].includes(Number(o.leading))?Number(o.leading):1.2,align:['left','center','right'].includes(o.align)?o.align:'center',outline:clamp(o.outline??o.outlineWidth,0,4),outlineColour:\/^#[\\da-f]{6}$\/i.test(o.outlineColour)?o.outlineColour:'#ffffff',opacity:o.opacity===undefined?1:clamp(o.opacity,.1,1),flipX:!!o.flipX,flipY:!!o.flipY,locked:!!o.locked,hidden:!!o.hidden};}\n  function crc32(bytes){let crc=0xffffffff;for(const b of bytes){crc^=b;for(let i=0;i\u003c8;i++)crc=(crc\u003e\u003e\u003e1)^((crc\u00261)?0xedb88320:0);}return (crc^0xffffffff)\u003e\u003e\u003e0;}\n  function zip(files){const encoder=new TextEncoder(),local=[],central=[];let offset=0;for(const file of files){const name=encoder.encode(file.name),data=file.data,crc=crc32(data),h=new Uint8Array(30+name.length),v=new DataView(h.buffer);v.setUint32(0,0x04034b50,true);v.setUint16(4,20,true);v.setUint16(6,0x800,true);v.setUint32(14,crc,true);v.setUint32(18,data.length,true);v.setUint32(22,data.length,true);v.setUint16(26,name.length,true);h.set(name,30);local.push(h,data);const c=new Uint8Array(46+name.length),cv=new DataView(c.buffer);cv.setUint32(0,0x02014b50,true);cv.setUint16(4,20,true);cv.setUint16(6,20,true);cv.setUint16(8,0x800,true);cv.setUint32(16,crc,true);cv.setUint32(20,data.length,true);cv.setUint32(24,data.length,true);cv.setUint16(28,name.length,true);cv.setUint32(42,offset,true);c.set(name,46);central.push(c);offset+=h.length+data.length;}const size=central.reduce((n,c)=\u003en+c.length,0),end=new Uint8Array(22),ev=new DataView(end.buffer);ev.setUint32(0,0x06054b50,true);ev.setUint16(8,files.length,true);ev.setUint16(10,files.length,true);ev.setUint32(12,size,true);ev.setUint32(16,offset,true);return [...local,...central,end];}\n  function validateProject(data){\n    if(data?.version!==2||!data.projects||!Array.isArray(data.assets)||data.assets.length\u003e80)throw Error('This is not a supported Custom Studio project.');\n    const assets=new Map();\n    for(const a of data.assets){if(typeof a.id!=='string'||typeof a.src!=='string'||!\/^https:\\\/\\\/|^data:image\\\/(png|jpeg|webp);base64,\/i.test(a.src))throw Error('Unsupported artwork in project.');assets.set(a.id,{id:a.id,src:a.src,name:String(a.name||'Artwork').slice(0,180),width:clamp(a.width,1,20000),height:clamp(a.height,1,20000),sourceUrl:\/^https:\\\/\\\/\/i.test(a.sourceUrl||'')?a.sourceUrl:'',libraryId:String(a.libraryId||''),fileId:String(a.fileId||'')});}\n    const projects=blank();let count=0;\n    for(const method of Object.keys(placements))for(const key of Object.keys(placements[method])){\n      const v=data.projects[method]?.[key];if(!v)continue;if(!Array.isArray(v.objects))throw Error('Invalid layer data.');\n      const area=projects[method][key];area.width=clamp(v.width,20,450);area.height=clamp(v.height,20,450);\n      area.objects=v.objects.map((o,i)=\u003e{if(++count\u003e100||!['text','image'].includes(o.type))throw Error('Unsupported layer data.');if(o.type==='image'\u0026\u0026!assets.has(o.assetId))throw Error('Missing artwork file.');return fit({id:method+'-'+key+'-'+i,type:o.type,assetId:o.assetId,text:String(o.text||'').slice(0,180),font:String(o.font||'Professional'),colour:\/^#[\\da-f]{6}$\/i.test(o.colour)?o.colour:'#172c42',x:clamp(o.x,0,450),y:clamp(o.y,0,450),w:clamp(o.w,5,450),h:clamp(o.h,2,450),rotation:clamp(o.rotation,-180,180),...style(o)},area);});\n    }\n    return {projects,assets};\n  }\n  return {placements,clamp,blank,bounds,fit,rect,pngDpi,parseAI,normaliseLibrary,style,crc32,zip,validateProject};\n})();\nif(typeof module!=='undefined'\u0026\u0026module.exports)module.exports=USFModel;\n\n(() =\u003e {\n  'use strict';\n  const root=document.getElementById('usf-custom-studio');\n  if(!root||root.dataset.ready)return;\n  root.dataset.ready='true';\n  const DRIVE_API='https:\/\/script.google.com\/macros\/s\/AKfycbwvSSSZqM3M8--3wfKTXy9mU3gYeBMvnaooIoK-IH9liZOrUSUUGRzY29QeALOO95zb\/exec';\n  const AI_API='https:\/\/node-js-openai-api-route.vercel.app\/api\/design-text';\n  const IMAGE_API='https:\/\/node-js-openai-api-route.vercel.app\/api\/generate-image';\n  const M=USFModel,NS='http:\/\/www.w3.org\/2000\/svg';\n  const ui=name=\u003eroot.querySelector('[data-ui=\"'+name+'\"]');\n  const input=name=\u003eroot.querySelector('[data-input=\"'+name+'\"]');\n  const action=name=\u003eroot.querySelector('[data-action=\"'+name+'\"]');\n  const dialog=root.querySelector('dialog'),demo=root.dataset.demo==='true';\n  const fonts={Professional:\"'Montserrat',Arial,sans-serif\",Bold:\"'Anton',Impact,sans-serif\",Vintage:\"'Bebas Neue',Impact,sans-serif\",Biker:\"'Black Ops One',Impact,sans-serif\",Retro:\"'Bungee',Impact,sans-serif\",Funny:\"'Permanent Marker',cursive\",Wedding:\"'Dancing Script',cursive\",Birthday:\"'Lobster',cursive\",Sports:\"'Graduate',serif\",Elegant:\"'Cinzel',Georgia,serif\",Script:\"'Pacifico',cursive\",Classic:\"'Roboto Slab',Georgia,serif\"};\n  const fontGroups={\n    'System':['Arial','Arial Black','Impact'],\n    'Modern \u0026 clean':['Inter','Roboto','Poppins','Lato','Open Sans','Raleway','Nunito','Quicksand','Josefin Sans','Work Sans'],\n    'Bold \u0026 display':['Oswald','Archivo Black','Alfa Slab One','Righteous','Russo One','Fjalla One','Teko','Squada One'],\n    'Serif \u0026 editorial':['Playfair Display','Merriweather','Bitter','Cormorant Garamond','Libre Baskerville','DM Serif Display','Abril Fatface','Lora'],\n    'Script \u0026 handwritten':['Great Vibes','Sacramento','Satisfy','Caveat','Kalam','Courgette','Yellowtail','Amatic SC'],\n    'Vintage \u0026 character':['Rye','Special Elite','Bangers','Press Start 2P','UnifrakturMaguntia','Orbitron']\n  };\n  for(const group of Object.values(fontGroups))for(const name of group)fonts[name]=\"'\"+name+\"',Arial,sans-serif\";\n  const basicFontLabels={Professional:'Montserrat · Modern',Bold:'Anton · Bold',Vintage:'Bebas Neue · Vintage',Biker:'Black Ops One · Biker',Retro:'Bungee · Retro',Funny:'Permanent Marker',Wedding:'Dancing Script',Birthday:'Lobster',Sports:'Graduate · Varsity',Elegant:'Cinzel · Elegant',Script:'Pacifico',Classic:'Roboto Slab'};\n  const loadedFonts=new Map();\n  let draftStyle=M.style(),imageBusy=false,downloadBusy=false;\n  const state={method:'dtf',placement:'front',projects:M.blank(),assets:new Map(),selected:null,library:[],limit:24,history:[],future:[],product:null,variant:null,aiResult:null,aiImageResult:null,aiImageBusy:false,zoom:1,aiBusy:false,cartBusy:false,exportBusy:false,libraryBusy:false,guides:true,drag:null,lastFocus:null,oldOverflow:'',demo};\n  const area=()=\u003estate.projects[state.method][state.placement];\n  const objects=()=\u003earea().objects;\n  const selected=()=\u003eobjects().find(o=\u003eo.id===state.selected);\n  const uid=()=\u003ecrypto.randomUUID?crypto.randomUUID():'u'+Date.now()+Math.random().toString(36).slice(2);\n  const fit=o=\u003eM.fit(o,area());\n  const allObjects=()=\u003eObject.values(state.projects[state.method]).flatMap(a=\u003ea.objects);\n  const visibleObjects=()=\u003eallObjects().filter(o=\u003e!o.hidden);\n  const clone=v=\u003eJSON.parse(JSON.stringify(v));\n  const snapshot=()=\u003eJSON.stringify({projects:state.projects,method:state.method,placement:state.placement});\n  const svg=(tag,attrs={},text)=\u003e{const e=document.createElementNS(NS,tag);for(const[k,v]of Object.entries(attrs))e.setAttribute(k,v);if(text!==undefined)e.textContent=text;return e;};\n  const el=(tag,cls,text)=\u003e{const e=document.createElement(tag);if(cls)e.className=cls;if(text!==undefined)e.textContent=text;return e;};\n  const status=(name,text,error=false)=\u003e{ui(name).textContent=text;ui(name).classList.toggle('error',error);};\n  function toast(text){ui('toast').textContent=text;ui('toast').hidden=false;clearTimeout(toast.timer);toast.timer=setTimeout(()=\u003eui('toast').hidden=true,6500);}\n  function remember(){state.history.push(snapshot());if(state.history.length\u003e40)state.history.shift();state.future=[];}\n  function history(direction){const from=direction==='undo'?state.history:state.future,to=direction==='undo'?state.future:state.history;if(!from.length)return;to.push(snapshot());Object.assign(state,JSON.parse(from.pop()));state.selected=null;syncMethod();render();}\n  function changed(){action('undo').disabled=!state.history.length;action('redo').disabled=!state.future.length;input('confirm').checked=false;action('add-cart').disabled=true;}\n  function setTab(name,scroll=false){const titles={art:'Artwork library',image:'AI image studio',text:'Typography studio',setup:'Product \u0026 print',tools:'Advanced tools'};ui('tool-title').textContent=titles[name]||'Studio';ui('tool-number').textContent=String(['art','image','text','setup','tools'].indexOf(name)+1).padStart(2,'0');root.querySelectorAll('[data-tab]').forEach(b=\u003e{const active=b.dataset.tab===name;b.setAttribute('aria-selected',active);b.tabIndex=active?0:-1;root.querySelector('#uf-'+b.dataset.tab).hidden=!active;});if(scroll\u0026\u0026matchMedia('(max-width:700px)').matches)root.querySelector('.uf-sidebar').scrollIntoView({block:'start',behavior:'smooth'});}\n  function setMethod(method){if(method===state.method)return;remember();state.method=method;state.placement=Object.keys(M.placements[method])[0];state.selected=null;syncMethod();render();toast('Switched to '+(method==='dtf'?'DTF printing':'embroidery')+'. Each method keeps its own designs.');}\n  function syncMethod(){\n    const embroidery=state.method==='embroidery';root.querySelectorAll('[data-method]').forEach(b=\u003eb.setAttribute('aria-pressed',b.dataset.method===state.method));\n    ui('method-caption').textContent=embroidery?'Create a thread-inspired design with simple, confident detail.':'Build your print with artwork, text, or both.';\n    ui('embroidery-settings').hidden=!embroidery;ui('dtf-settings').hidden=embroidery;\n    ui('upload-hint').textContent=embroidery?'Simple shapes and clear lettering translate well to embroidery.':'Transparent PNG works well for DTF artwork.';\n    input('placement').replaceChildren();ui('views').replaceChildren();\n    for(const[key,p]of Object.entries(M.placements[state.method])){const option=el('option',null,p.label);option.value=key;input('placement').append(option);const b=el('button',null,p.label);b.type='button';b.dataset.placement=key;b.onclick=()=\u003esetPlacement(key);ui('views').append(b);}\n    action('export-png').textContent=embroidery?'Export preview':'Export design';action('export-png').setAttribute('aria-label',embroidery?'Export embroidery design preview PNG':'Export transparent DTF PNG');\n    input('placement').value=state.placement;\n  }\n  function setPlacement(key){if(!M.placements[state.method][key])return;state.placement=key;state.selected=null;render();}\n  function fontCSS(font,style,size=100){return (style.italic?'italic ':'')+(style.fontWeight|| (style.bold===false?400:700))+' '+size+'px '+(fonts[font]||fonts.Professional);}\n  function textMetrics(text,font,style={}){const s=M.style(style),c=document.createElement('canvas').getContext('2d');c.font=fontCSS(font,s);const lines=text.split('\\n'),widths=lines.map(l=\u003eArray.from(l).reduce((n,ch)=\u003en+c.measureText(ch).width,0)+Math.max(0,Array.from(l).length-1)*s.tracking);return {lines,widths,width:Math.max(1,...widths),height:(lines.length-1)*100*s.leading+120,context:c};}\n  function textLayout(o){const s=M.style(o),m=textMetrics(o.text,o.font,s),pad=Math.min(s.outline+(s.shadow?2:0),o.w\/8),scale=Math.max(.01,o.w-2*pad)\/m.width,size=100*scale,rows=m.lines.map((line,i)=\u003e{const width=m.widths[i]*scale,start=s.align==='left'?-o.w\/2+pad:s.align==='right'?o.w\/2-pad-width:-width\/2;let x=start;return {start,width,baseline:-o.h\/2+pad+size*(i*s.leading+.9),glyphs:Array.from(line).map(ch=\u003e{const item={ch,x};x+=(m.context.measureText(ch).width+s.tracking)*scale;return item;})};});return {s,size,pad,rows};}\n  function sizeText(o){const m=textMetrics(o.text,o.font,o),pad=Math.min((o.outline||0)+(o.shadow?2:0),o.w\/8);o.h=Math.max(2,(o.w-2*pad)*m.height\/m.width+2*pad);return fit(o);}\n  function newText(text,font,colour){const width=area().width*M.clamp(input('text-size').value,10,95)\/100;return sizeText({id:uid(),type:'text',text,font,colour,x:area().width\/2,y:area().height\/2,w:width,h:40,rotation:0,...M.style(draftStyle),opacity:1,flipX:false,flipY:false,locked:false,hidden:false});}\n  async function fontReady(font,style={}){try{if(root.dataset.test!=='true'\u0026\u0026!['Arial','Arial Black','Impact'].includes(font)){const family=(fonts[font]||fonts.Professional).match(\/'([^']+)'\/)[1];if(!loadedFonts.has(family)){loadedFonts.set(family,new Promise(resolve=\u003e{const link=document.createElement('link');link.rel='stylesheet';link.href='https:\/\/fonts.googleapis.com\/css2?family='+encodeURIComponent(family).replace(\/%20\/g,'+')+'\u0026display=swap';const timer=setTimeout(resolve,5000);link.onload=link.onerror=()=\u003e{clearTimeout(timer);resolve();};document.head.append(link);}));}await loadedFonts.get(family);}await document.fonts.load(fontCSS(font,M.style(style)));}catch{}}\n  async function addText(update=false){const text=input('text').value.trim();if(!text)return toast('Enter your text first.');const font=input('font').value;readDraftStyle();await fontReady(font,draftStyle);if(update){const o=selected();if(o?.type!=='text')return toast('Select a text layer first.');if(o.locked)return toast('Unlock this layer before editing.');remember();Object.assign(o,{text,font,colour:input('text-colour').value,...draftStyle,w:area().width*M.clamp(input('text-size').value,10,95)\/100});sizeText(o);}else{if(allObjects().length\u003e=40)return toast('This design has reached the 40-layer limit.');remember();const o=newText(text,font,input('text-colour').value);objects().push(o);state.selected=o.id;}render();focusCanvas();}\n  function readDraftStyle(){Object.assign(draftStyle,{fontWeight:Number(input('font-weight').value),bold:Number(input('font-weight').value)\u003e=600,fontSize:Number(input('text-size').value),shadow:input('shadow').checked,tracking:M.clamp(input('tracking').value,-10,30),leading:Number(input('leading').value),align:input('text-align').value,outline:M.clamp(input('outline').value,0,4),outlineColour:input('outline-colour').value});return draftStyle;}\n  function syncDraftControls(){input('font-weight').value=draftStyle.fontWeight||700;input('text-size').value=draftStyle.fontSize||74;input('shadow').checked=!!draftStyle.shadow;for(const n of ['bold','italic','underline'])action(n).setAttribute('aria-pressed',!!draftStyle[n]);input('tracking').value=draftStyle.tracking;input('leading').value=draftStyle.leading;input('text-align').value=draftStyle.align;input('outline').value=draftStyle.outline;input('outline-colour').value=draftStyle.outlineColour;}\n  function previewText(){readDraftStyle();const p=ui('text-sample');p.textContent=input('text').value||'YOUR TEXT';Object.assign(p.style,{fontFamily:fonts[input('font').value],color:input('text-colour').value,fontWeight:String(draftStyle.fontWeight||700),textShadow:draftStyle.shadow?'1px 1px 2px #17243b55':'none',fontStyle:draftStyle.italic?'italic':'normal',textDecoration:draftStyle.underline?'underline':'none',letterSpacing:draftStyle.tracking*.24+'px',lineHeight:draftStyle.leading,textAlign:draftStyle.align,webkitTextStroke:Math.min(2,draftStyle.outline)+'px '+draftStyle.outlineColour,paintOrder:'stroke fill'});}\n  function populateFonts(query=''){const current=input('font').value||'Professional',q=query.toLowerCase();input('font').replaceChildren();const groups={'Popular styles':Object.keys(basicFontLabels),...fontGroups};for(const[name,keys]of Object.entries(groups)){const group=el('optgroup');group.label=name;for(const key of keys){const label=basicFontLabels[key]||key;if(!q||(label+' '+name).toLowerCase().includes(q)||key===current){const option=el('option',null,label);option.value=key;group.append(option);}}if(group.children.length)input('font').append(group);}input('font').value=current;}\n  function setZoom(value){state.zoom=M.clamp(value,.5,2.5);const width=600\/state.zoom,height=650\/state.zoom;ui('scene').setAttribute('viewBox',[(600-width)\/2,(650-height)\/2,width,height].join(' '));ui('zoom-value').textContent=Math.round(state.zoom*100)+'%';}\n  function focusCanvas(){if(matchMedia('(max-width:700px)').matches)root.querySelector('.uf-workspace').scrollIntoView({block:'start',behavior:'smooth'});}\n  async function readImage(src,cors=false){return new Promise((resolve,reject)=\u003e{const image=new Image(),timer=setTimeout(()=\u003e{image.onload=image.onerror=null;reject(Error('The artwork took too long to load. Try again or upload a local copy.'));},20000);if(cors)image.crossOrigin='anonymous';image.onload=()=\u003e{clearTimeout(timer);resolve(image);};image.onerror=()=\u003e{clearTimeout(timer);reject(Error('This artwork could not be loaded. Check its sharing settings or upload the file.'));};image.src=src;});}\n  function fileData(file){return new Promise((resolve,reject)=\u003e{const r=new FileReader();r.onload=()=\u003eresolve(r.result);r.onerror=()=\u003ereject(Error('Could not read the file.'));r.readAsDataURL(file);});}\n  function imageData(image){const c=document.createElement('canvas');c.width=image.naturalWidth||image.width;c.height=image.naturalHeight||image.height;c.getContext('2d').drawImage(image,0,0);const data=c.toDataURL('image\/png');c.width=c.height=1;return data;}\n  function dataBlob(data){const match=data.match(\/^data:(image\\\/(?:png|jpeg|webp));base64,(.+)$\/s);if(!match)throw Error('Unsupported artwork format.');const bytes=Uint8Array.from(atob(match[2]),c=\u003ec.charCodeAt(0));return new Blob([bytes],{type:match[1]});}\n  function fileIdOf(a){if(\/^[\\w-]{20,}$\/.test(a.fileId||''))return a.fileId;const source=a.sourceUrl||a.src;try{const u=new URL(source);if(\/(^|\\.)google(?:usercontent)?\\.com$\/.test(u.hostname)){const id=u.searchParams.get('id')||u.pathname.match(\/\\\/d\\\/([\\w-]+)\/)?.[1];if(id)return id;}}catch{}return \/^[\\w-]{20,}$\/.test(a.libraryId||'')?a.libraryId:'';}\n  function driveBytes(asset){return new Promise((resolve,reject)=\u003e{const fileId=fileIdOf(asset);if(!fileId)return reject(Error('The Drive item does not include an exportable file ID.'));const callback='USF_ASSET_'+Date.now()+'_'+Math.floor(Math.random()*100000),script=document.createElement('script');let done=false;const finish=(error,value)=\u003e{if(done)return;done=true;clearTimeout(timer);script.remove();window[callback]=()=\u003e{};setTimeout(()=\u003edelete window[callback],60000);error?reject(error):resolve(value);};const timer=setTimeout(()=\u003efinish(Error('Drive file download timed out.')),20000);window[callback]=data=\u003e{if(!\/^data:image\\\/(png|jpeg|webp);base64,\/.test(data?.dataUrl||''))return finish(Error(String(data?.error||'The Drive script needs the asset export handler.')));finish(null,data.dataUrl);};script.onerror=()=\u003efinish(Error('Drive file export is unavailable.'));script.src=DRIVE_API+'?action=asset\u0026fileId='+encodeURIComponent(fileId)+'\u0026callback='+callback;document.head.append(script);});}\n  async function ensureAsset(asset){if(asset.src.startsWith('data:image\/'))return asset;try{asset.src=imageData(await readImage(asset.src,true));}catch{try{asset.src=await driveBytes(asset);}catch{throw Error('“'+asset.name+'” is visible but not exportable. Enable the supplied Drive asset handler, or upload a local copy before downloading or ordering.');}}return asset;}\n  async function addArtwork(src,name,assetId,meta={}){try{if(allObjects().length\u003e=40)throw Error('This design has reached the 40-layer limit.');let image;try{image=await readImage(src,true);}catch{image=await readImage(src);}if(image.naturalWidth*image.naturalHeight\u003e80000000)throw Error('This image is too large. Upload an image below 80 megapixels.');const sourceUrl=\/^https:\\\/\\\/\/.test(src)?src:'';try{if(sourceUrl||src.startsWith('data:image\/svg+xml'))src=imageData(image);}catch{}const id=assetId||uid();state.assets.set(id,{id,src,name,width:image.naturalWidth,height:image.naturalHeight,sourceUrl,libraryId:meta.libraryId||'',fileId:meta.fileId||''});remember();const w=area().width*.65,o=fit({id:uid(),type:'image',assetId:id,x:area().width\/2,y:area().height\/2,w,h:w*image.naturalHeight\/image.naturalWidth,rotation:0,...M.style()});objects().push(o);state.selected=o.id;render();focusCanvas();toast(name+' attached to '+M.placements[state.method][state.placement].label+'.');}catch(e){toast(e.message);}}\n  async function uploads(files){for(const file of Array.from(files).slice(0,10)){try{if(!['image\/png','image\/jpeg','image\/webp'].includes(file.type))throw Error('Upload PNG, JPG or WebP artwork.');if(file.size\u003e15*1024*1024)throw Error(file.name+' is above the 15 MB limit.');await addArtwork(await fileData(file),file.name);}catch(e){toast(e.message);}}input('upload').value='';}\n  function nameOf(o){return o.type==='text'?o.text:state.assets.get(o.assetId)?.name||'Artwork';}\n  function renderScene(){\n    const p=M.placements[state.method][state.placement],a=area(),[rx,ry,rw,rh]=M.rect(p,a);\n    const layer=ui('design-scene');layer.replaceChildren();\n    if(state.guides){layer.append(svg('rect',{x:rx,y:ry,width:rw,height:rh,fill:'none',stroke:'#66967e','stroke-dasharray':'4 4','stroke-width':1}));layer.append(svg('text',{x:rx+rw\/2,y:ry-9,'text-anchor':'middle','font-size':7,'font-family':'Arial',fill:'#7b9383'},a.width+' × '+a.height+' mm'));}\n    const content=svg('svg',{x:rx,y:ry,width:rw,height:rh,viewBox:'0 0 '+a.width+' '+a.height,preserveAspectRatio:'none',overflow:'visible'});layer.append(content);\n    for(const o of a.objects){if(o.hidden)continue;const g=svg('g',{'data-object':o.id,transform:'translate('+o.x+' '+o.y+') rotate('+o.rotation+') scale('+(o.flipX?-1:1)+' '+(o.flipY?-1:1)+')',opacity:o.opacity??1,cursor:o.locked?'default':'move'});content.append(g);\n      g.append(svg('rect',{x:-o.w\/2,y:-o.h\/2,width:o.w,height:o.h,fill:'transparent'}));\n      if(o.type==='image'){g.append(svg('image',{href:state.assets.get(o.assetId)?.src||'',x:-o.w\/2,y:-o.h\/2,width:o.w,height:o.h,preserveAspectRatio:'xMidYMid meet','pointer-events':'none'}));}\n      else{const l=textLayout(o);for(const row of l.rows){for(const glyph of row.glyphs){const attrs={x:glyph.x,y:row.baseline,'font-family':fonts[o.font]||fonts.Professional,'font-size':l.size,'font-weight':l.s.fontWeight,'font-style':l.s.italic?'italic':'normal',fill:o.colour,stroke:l.s.outline?l.s.outlineColour:'none','stroke-width':l.s.outline*2,'stroke-linejoin':'round','paint-order':'stroke fill','pointer-events':'none'};if(l.s.shadow)g.append(svg('text',{...attrs,x:glyph.x+.6,y:row.baseline+.8,fill:'#17243b',stroke:'none',opacity:.25},glyph.ch));g.append(svg('text',attrs,glyph.ch));}if(l.s.underline)g.append(svg('line',{x1:row.start,x2:row.start+row.width,y1:row.baseline+l.size*.09,y2:row.baseline+l.size*.09,stroke:o.colour,'stroke-width':l.size*.05,'pointer-events':'none'}));}}\n      if(o.id===state.selected){g.append(svg('rect',{x:-o.w\/2-1,y:-o.h\/2-1,width:o.w+2,height:o.h+2,fill:'none',stroke:'#246d68','stroke-width':.8,'vector-effect':'non-scaling-stroke','pointer-events':'none'}));for(const x of [-o.w\/2,o.w\/2])for(const y of [-o.h\/2,o.h\/2])g.append(svg('circle',{cx:x,cy:y,r:1.4,fill:'#fff',stroke:'#246d68','stroke-width':.7,'vector-effect':'non-scaling-stroke','pointer-events':'none'}));}\n    }\n    ui('empty').hidden=a.objects.some(o=\u003e!o.hidden);\n    const image=productImage(p.side);ui('product-image').setAttribute('href',image||'');ui('product-image').style.display=image?'':'none';ui('garment').style.display=image?'none':'';ui('preview-disclaimer').textContent=image?'Product image · placement is illustrative':'Illustrative garment · '+p.side.replace(\/([A-Z])\/g,' $1').toLowerCase();\n  }\n  function renderLayers(){ui('layers').replaceChildren();ui('layer-count').textContent=objects().length+' item'+(objects().length===1?'':'s');if(!objects().length){ui('layers').append(el('p','uf-hint','Your artwork and text layers will appear here.'));return;}[...objects()].reverse().forEach(o=\u003e{const row=el('div','uf-layer'+(o.id===state.selected?' selected':''));const b=el('button',null,(o.locked?'🔒 ':o.hidden?'◌ ':'')+(o.type==='text'?'T  ':'▧  ')+nameOf(o));b.type='button';b.setAttribute('aria-pressed',o.id===state.selected);b.onclick=()=\u003e{state.selected=o.id;render();};const up=el('button',null,'↑');up.type='button';up.setAttribute('aria-label','Move '+nameOf(o)+' forward');up.onclick=()=\u003e{if(o.locked)return toast('Unlock this layer first.');const list=objects(),i=list.indexOf(o);if(i===list.length-1)return;remember();[list[i],list[i+1]]=[list[i+1],list[i]];render();};row.append(b,up);ui('layers').append(row);});}\n  function render(){\n    const a=area(),o=selected(),p=M.placements[state.method][state.placement];renderScene();renderLayers();\n    input('placement').value=state.placement;input('area-width').value=a.width;input('area-height').value=a.height;ui('view-label').textContent=p.label;ui('dimensions').textContent=a.width+' × '+a.height+' mm';ui('views').querySelectorAll('button').forEach(b=\u003eb.setAttribute('aria-pressed',b.dataset.placement===state.placement));\n    ui('selection-name').textContent=o?nameOf(o):'Select an artwork or text layer';ui('selection-hint').textContent=o?'Drag to position. Arrow keys nudge the selected layer.':'Add artwork or text to start your design.';\n    input('object-width').disabled=input('rotation').disabled=!o;input('object-width').value=o?Math.round(o.w*10)\/10:'';input('object-width').max=a.width;input('rotation').value=o?o.rotation:'';\n    ['center','duplicate','delete'].forEach(x=\u003eaction(x).disabled=!o);\n    if(o?.type==='text'){input('text').value=o.text;populateFonts();input('font').value=fonts[o.font]?o.font:'Professional';input('text-colour').value=o.colour;draftStyle=M.style(o);draftStyle.fontSize=Math.round(o.w\/area().width*100);syncDraftControls();previewText();}\n    input('position-x').value=o?Math.round(o.x*10)\/10:'';input('position-y').value=o?Math.round(o.y*10)\/10:'';input('opacity').value=o?Math.round((o.opacity??1)*100):100;['position-x','position-y','opacity','object-width','rotation'].forEach(n=\u003einput(n).disabled=!o||!!o.locked);\n    action('lock-layer').textContent=o?.locked?'Unlock layer':'Lock layer';action('hide-layer').textContent=o?.hidden?'Show layer':'Hide layer';\n    if(o?.type==='image'){const asset=state.assets.get(o.assetId),dpi=Math.round(Math.min(asset.width\/o.w,asset.height\/o.h)*25.4);status('artwork-quality',(asset.libraryId?'Drive artwork attached · ':'Artwork attached · ')+dpi+' effective PPI'+(dpi\u003c150?' · use a higher-resolution source for a sharper print.':'.'));}else status('artwork-quality',o?'Text layer · '+(basicFontLabels[o.font]||o.font)+(o.locked?' · locked':''):'Choose a layer to use the advanced tools.');\n    const count=allObjects().length;ui('footer-title').textContent=state.product?.title||'Your custom creation';ui('footer-detail').textContent=(state.method==='dtf'?'DTF print':'Embroidery')+' · '+(count?count+' design layer'+(count===1?'':'s'):'no artwork yet');changed();\n  }\n  function point(event){const matrix=ui('scene').getScreenCTM();if(!matrix)return null;const p=new DOMPoint(event.clientX,event.clientY).matrixTransform(matrix.inverse()),r=M.rect(M.placements[state.method][state.placement],area());return {x:(p.x-r[0])\/r[2]*area().width,y:(p.y-r[1])\/r[3]*area().height};}\n  ui('scene').addEventListener('pointerdown',e=\u003e{if(e.button!==0)return;const g=e.target.closest('[data-object]');if(!g){state.selected=null;render();return;}state.selected=g.dataset.object;const o=selected(),p=point(e);if(!o||!p)return;if(o.locked)return toast('Unlock this layer before moving it.');state.drag={id:e.pointerId,start:p,x:o.x,y:o.y,remembered:false};ui('scene').setPointerCapture(e.pointerId);render();e.preventDefault();});\n  ui('scene').addEventListener('pointermove',e=\u003e{if(!state.drag||state.drag.id!==e.pointerId)return;const o=selected(),p=point(e);if(!o||!p)return;if(!state.drag.remembered){remember();state.drag.remembered=true;}o.x=state.drag.x+p.x-state.drag.start.x;o.y=state.drag.y+p.y-state.drag.start.y;fit(o);renderScene();});\n  function endDrag(){if(state.drag){state.drag=null;render();}}\n  ui('scene').addEventListener('pointerup',endDrag);ui('scene').addEventListener('pointercancel',endDrag);ui('scene').addEventListener('lostpointercapture',endDrag);\n  function editSelected(fn){const o=selected();if(!o)return toast('Select a layer first.');if(o.locked)return toast('Unlock this layer before editing.');remember();fn(o);fit(o);render();}\n  function deleteSelected(){if(!selected())return;if(selected().locked)return toast('Unlock this layer before deleting it.');remember();area().objects=objects().filter(o=\u003eo.id!==state.selected);state.selected=null;render();}\n  function changeDimensions(){const a=area(),w=M.clamp(input('area-width').value,20,450),h=M.clamp(input('area-height').value,20,450);remember();a.objects.forEach(o=\u003e{o.x*=w\/a.width;o.y*=h\/a.height;});a.width=w;a.height=h;a.objects.forEach(fit);render();}\n  function renderLibrary(){const q=input('library-search').value.trim().toLowerCase(),list=state.library.filter(x=\u003e(x.name+' '+x.category).toLowerCase().includes(q));ui('library').replaceChildren();list.slice(0,state.limit).forEach(a=\u003e{const card=el('div','uf-art-card'),b=el('button','uf-art-select');b.type='button';const image=el('img');image.src=a.src;image.alt='';image.loading='lazy';image.onerror=()=\u003e{image.alt='Preview unavailable';};b.append(image,el('span',null,a.name));b.title='Attach '+a.name+' to product';const attach=()=\u003eaddArtwork(a.src,a.name,undefined,{libraryId:a.id,fileId:a.fileId});b.onclick=attach;const buttons=el('div','uf-library-actions'),add=el('button',null,'+ Attach'),get=el('button',null,'↓ File');add.type=get.type='button';add.onclick=attach;get.onclick=()=\u003edownloadLibraryArtwork(a);buttons.append(add,get);card.append(b,buttons);ui('library').append(card);});action('more-library').hidden=list.length\u003c=state.limit;if(!list.length\u0026\u0026!state.libraryBusy)status('library-status',q?'No artwork matches your search.':'No artwork found. Upload your own design or refresh the library.');}\n  function loadLibrary(){\n    if(state.libraryBusy)return;state.libraryBusy=true;action('refresh-library').disabled=true;status('library-status','Connecting to your Google Drive library…');\n    const callback='USF_DRIVE_'+Date.now()+'_'+Math.floor(Math.random()*10000),script=document.createElement('script');let done=false;\n    function cleanup(){clearTimeout(timer);script.remove();state.libraryBusy=false;action('refresh-library').disabled=false;window[callback]=()=\u003e{};setTimeout(()=\u003edelete window[callback],60000);}\n    const timer=setTimeout(()=\u003e{if(done)return;done=true;cleanup();status('library-status','The library timed out. Try Refresh or upload your artwork.',true);},18000);\n    window[callback]=data=\u003e{if(done)return;done=true;cleanup();state.library=M.normaliseLibrary(data);state.limit=24;status('library-status',state.library.length+' designs from your Google Drive');renderLibrary();};\n    script.onerror=()=\u003e{if(done)return;done=true;cleanup();status('library-status','Could not load your library. Local artwork upload is still available.',true);};\n    script.src=DRIVE_API+'?callback='+encodeURIComponent(callback)+'\u0026t='+Date.now();document.head.append(script);\n  }\n  function normaliseAI(design){\n    if(!design||typeof design!=='object')throw Error('The AI service returned an invalid design.');\n    const family=String(design.fontFamily||design.fontStyle||'Professional');\n    const font=fonts[family]?family:Object.keys(fonts).find(key=\u003efonts[key].startsWith(\"'\"+family+\"'\"))||'Professional';\n    const style=M.style({fontWeight:design.fontWeight,fontSize:design.fontSize,tracking:design.letterSpacing,outline:design.outlineWidth,outlineColour:design.outlineColor,italic:design.italic,shadow:design.shadow});\n    let text=String(design.text||'').trim().slice(0,180);if(design.uppercase)text=text.toUpperCase();\n    return {text,fontStyle:font,fontFamily:family,colour:\/^#[a-f0-9]{6}$\/i.test(design.textColor||'')?design.textColor:'#172c42',style};\n  }\n  async function generateAI(regenerate=false){\n    const request=input('ai-prompt').value.trim();if(!request){input('ai-prompt').focus();return status('ai-status','Describe the text you would like to create.',true);}if(state.aiBusy)return;\n    state.aiBusy=true;action('generate').disabled=action('regenerate').disabled=true;status('ai-status',regenerate?'Creating a different text design…':'Choosing your words, font and styling…');\n    const controller=new AbortController(),timer=setTimeout(()=\u003econtroller.abort(),45000);\n    try{const response=await fetch(AI_API,{method:'POST',headers:{'Content-Type':'application\/json'},body:JSON.stringify({prompt:request,product:state.product?.title||'Custom clothing',style:input('ai-style').value,previousText:regenerate\u0026\u0026state.aiResult?state.aiResult.text:''}),signal:controller.signal});let data;try{data=await response.json();}catch{throw Error('The AI text service returned invalid JSON.');}if(!response.ok)throw Error(String(data.error||data.detail||data.message||'AI text service unavailable.'));if(!data.success||!data.design)throw Error('The AI service returned no design.');const result=normaliseAI(data.design);if(!result.text)throw Error('The AI service returned no usable text.');state.aiResult=result;status('ai-status','“'+result.text+'” · '+result.fontFamily+' · '+result.style.fontWeight+' weight');action('use-ai').hidden=false;\n    }catch(e){status('ai-status',e.name==='AbortError'?'The AI text service timed out. Please try again.':e.message,true);}finally{clearTimeout(timer);state.aiBusy=false;action('generate').disabled=false;action('regenerate').disabled=!state.aiResult;}\n  }\n  function useAIText(){if(!state.aiResult)return;const r=state.aiResult;populateFonts();input('text').value=r.text;input('font').value=r.fontStyle;input('text-colour').value=r.colour;draftStyle=M.style(r.style);syncDraftControls();fontReady(r.fontStyle,draftStyle).then(previewText);toast('AI font, colour and styling loaded. Add text or update the selected layer.');}\n  function normaliseAIImage(data,prompt){const value=typeof data?.image==='string'?data.image:typeof data?.imageUrl==='string'?data.imageUrl:data?.data?.[0]?.b64_json?'data:image\/png;base64,'+data.data[0].b64_json:data?.images?.[0]?.b64_json?'data:image\/png;base64,'+data.images[0].b64_json:'';if(!\/^https:\\\/\\\/|^data:image\\\/(png|jpeg|webp);base64,\/i.test(value))throw Error('The AI image service returned no supported image.');return {src:value,name:safeFilename(prompt)+'.png',prompt};}\n  function showAIImage(result){const wrap=ui('ai-image-preview');wrap.setAttribute('aria-busy','false');wrap.replaceChildren();if(result){const image=el('img');image.src=result.src;image.alt='AI generated apparel artwork';wrap.append(image);}else{wrap.append(el('span',null,'✦'),el('p',null,'Your next creation appears here.'));}}\n  async function generateAIImage(regenerate=false){\n    const prompt=input('ai-image-prompt').value.trim();if(!prompt){input('ai-image-prompt').focus();return status('ai-image-status','Describe the image you would like to create.',true);}if(state.aiImageBusy)return;\n    state.aiImageBusy=true;['generate-image','regenerate-image','use-ai-image','download-ai-image'].forEach(n=\u003eaction(n).disabled=true);ui('ai-image-preview').replaceChildren(el('p',null,'Creating your artwork…'));ui('ai-image-preview').setAttribute('aria-busy','true');status('ai-image-status','Your image is being generated. This can take a minute or two.');\n    const controller=new AbortController(),timer=setTimeout(()=\u003econtroller.abort(),120000);\n    try{const style=input('ai-image-style').value,background=input('ai-image-background').value,response=await fetch(IMAGE_API,{method:'POST',headers:{'Content-Type':'application\/json'},body:JSON.stringify({prompt,product:state.product?.title||'Custom clothing',style,method:state.method,transparent:background==='transparent',previousPrompt:regenerate\u0026\u0026state.aiImageResult?state.aiImageResult.prompt:''}),signal:controller.signal});let data;try{data=await response.json();}catch{throw Error('The AI image service returned invalid JSON.');}if(!response.ok||!data.success)throw Error(String(data.error||data.detail||data.message||'AI image generation failed.'));const result=normaliseAIImage(data,prompt);await readImage(result.src);state.aiImageResult={...result,style,background};showAIImage(result);status('ai-image-status','Ready · '+style+' · '+(background==='transparent'?'transparent background requested':'light background requested'));toast('Your AI artwork is ready to add or download.');\n    }catch(e){showAIImage(state.aiImageResult);status('ai-image-status',e.name==='AbortError'?'The image service timed out. Try again when you are ready.':e.message,true);}finally{clearTimeout(timer);state.aiImageBusy=false;action('generate-image').disabled=false;['regenerate-image','use-ai-image','download-ai-image'].forEach(n=\u003eaction(n).disabled=!state.aiImageResult);}\n  }\n  async function useAIImage(){if(!state.aiImageResult)return;await addArtwork(state.aiImageResult.src,state.aiImageResult.name,undefined,{origin:'ai'});}\n  async function downloadAIImage(){if(!state.aiImageResult)return;try{const asset={...state.aiImageResult},file=await assetFile(asset);download(file.blob,file.name);toast('AI artwork downloaded.');}catch(e){toast(e.message);}}\n\n  function rootPath(){return window.Shopify?.routes?.root||'\/';}\n  function money(cents){try{return new Intl.NumberFormat(document.documentElement.lang||'en-GB',{style:'currency',currency:window.Shopify?.currency?.active||'GBP'}).format(cents\/100);}catch{return (cents\/100).toFixed(2);}}\n  function imageURL(v){const s=typeof v==='string'?v:v?.src||v?.url||'';return s.startsWith('\/\/')?'https:'+s:s;}\n  function productImage(side){if(!state.product)return '';const images=state.product.images||[],media=state.product.media||[];const alias=side==='back'?\/back|rear\/i:side==='leftSleeve'?\/left.*sleeve\/i:side==='rightSleeve'?\/right.*sleeve\/i:\/front\/i;const matched=media.find(m=\u003ealias.test(m.alt||''));if(matched)return imageURL(matched.preview_image);if(side==='front')return imageURL(state.variant?.featured_image)||imageURL(state.product.featured_image)||imageURL(images[0]);return '';}\n  async function loadProduct(){\n    if(demo){state.product={title:'Signature cotton tee',variants:[{id:1,title:'Natural \/ Medium',available:true,price:2400},{id:2,title:'Natural \/ Large',available:true,price:2400},{id:3,title:'Natural \/ Small',available:false,price:2400}],images:[]};}\n    else{try{const raw=JSON.parse(root.querySelector('[data-product]').textContent);if(raw?.variants?.length)state.product=raw;}catch{}\n      if(!state.product){const match=location.pathname.match(\/\\\/products\\\/([^\/?]+)\/);if(match){try{const r=await fetch(rootPath()+'products\/'+encodeURIComponent(decodeURIComponent(match[1]))+'.js');if(!r.ok)throw Error();state.product=await r.json();}catch{toast('Product data could not load. Reopen this studio from a Shopify product page.');}}}}\n    input('variant').replaceChildren();if(!state.product?.variants?.length){const o=el('option',null,'Open on a Shopify product page');o.value='';input('variant').append(o);ui('product-title').textContent='No Shopify product detected';ui('product-thumb').hidden=true;render();return;}\n    const currentId=new URLSearchParams(location.search).get('variant');state.variant=state.product.variants.find(v=\u003eString(v.id)===currentId)||state.product.variants.find(v=\u003ev.available)||state.product.variants[0];\n    state.product.variants.forEach(v=\u003e{const o=el('option',null,(v.title==='Default Title'?'Standard':v.title)+(v.available?'':' — sold out'));o.value=v.id;input('variant').append(o);});input('variant').value=state.variant.id;updateProduct();render();\n  }\n  function updateProduct(){ui('product-title').textContent=state.product?.title||'Custom product';ui('product-price').textContent=state.variant?money(state.variant.price)+(demo?' · sample price':''):'';const image=productImage('front');ui('product-thumb').hidden=!image;if(image)ui('product-thumb').src=image;}\n  function projectData(){const used=new Set(Object.values(state.projects).flatMap(p=\u003eObject.values(p)).flatMap(a=\u003ea.objects).filter(o=\u003eo.type==='image').map(o=\u003eo.assetId));return {version:2,brand:'USASTARFASHION',method:state.method,placement:state.placement,projects:state.projects,assets:[...state.assets.values()].filter(a=\u003eused.has(a.id)),notes:input('notes').value,finish:input('finish').value,quantity:input('quantity').value};}\n  function download(blob,name){const a=el('a'),url=URL.createObjectURL(blob);a.href=url;a.download=name;document.body.append(a);a.click();a.remove();setTimeout(()=\u003eURL.revokeObjectURL(url),30000);}\n  function saveProject(){download(new Blob([JSON.stringify(projectData(),null,2)],{type:'application\/json'}),'usastarfashion-project.json');toast('Editable project downloaded. Open it here to continue later.');}\n  async function importProject(file){try{if(!file)return;if(file.size\u003e70*1024*1024)throw Error('This project is too large. Maximum 70 MB.');const data=JSON.parse(await file.text()),valid=M.validateProject(data);remember();state.projects=valid.projects;for(const[id,a]of valid.assets)state.assets.set(id,a);state.method=M.placements[data.method]?data.method:'dtf';state.placement=M.placements[state.method][data.placement]?data.placement:Object.keys(M.placements[state.method])[0];for(const p of Object.values(state.projects))for(const a of Object.values(p))for(const o of a.objects)if(o.type==='text'){if(!fonts[o.font])o.font='Professional';await fontReady(o.font);}state.selected=null;input('notes').value=String(data.notes||'').slice(0,500);input('quantity').value=Math.round(M.clamp(data.quantity||1,1,999));input('finish').value=['Flat embroidery','3D puff request'].includes(data.finish)?data.finish:'Flat embroidery';syncMethod();render();toast('Your project is ready. Check the Shopify product option before ordering.');}catch(e){toast(e.message);}finally{input('project-file').value='';}}\n  async function renderPNG(a){\n    const scale=300\/25.4,canvas=document.createElement('canvas');canvas.width=Math.round(a.width*scale);canvas.height=Math.round(a.height*scale);const ctx=canvas.getContext('2d');if(!ctx)throw Error('Your browser could not create the export.');\n    for(const o of a.objects){if(o.hidden)continue;ctx.save();ctx.translate(o.x*scale,o.y*scale);ctx.rotate(o.rotation*Math.PI\/180);ctx.scale(o.flipX?-1:1,o.flipY?-1:1);ctx.globalAlpha=o.opacity??1;if(o.type==='image'){const asset=await ensureAsset(state.assets.get(o.assetId)),image=await readImage(asset.src,true);ctx.drawImage(image,-o.w*scale\/2,-o.h*scale\/2,o.w*scale,o.h*scale);}else{await fontReady(o.font,o);const l=textLayout(o);ctx.font=fontCSS(o.font,l.s,l.size*scale);ctx.fillStyle=o.colour;ctx.strokeStyle=l.s.outlineColour;ctx.lineWidth=l.s.outline*scale*2;ctx.lineJoin='round';ctx.textAlign='left';ctx.textBaseline='alphabetic';for(const row of l.rows){for(const glyph of row.glyphs){if(l.s.shadow){ctx.fillStyle='rgba(23,36,59,0.25)';ctx.fillText(glyph.ch,(glyph.x+.6)*scale,(row.baseline+.8)*scale);ctx.fillStyle=o.colour;}if(l.s.outline)ctx.strokeText(glyph.ch,glyph.x*scale,row.baseline*scale);ctx.fillText(glyph.ch,glyph.x*scale,row.baseline*scale);}if(l.s.underline){ctx.fillRect(row.start*scale,(row.baseline+l.size*.09)*scale,row.width*scale,l.size*.05*scale);}}}ctx.restore();}\n    const blob=await new Promise((resolve,reject)=\u003e{try{canvas.toBlob(blob=\u003eblob?resolve(blob):reject(Error('The image export failed.')),'image\/png');}catch{reject(Error('This artwork provider blocks export. Upload a local copy of the artwork and try again.'));}});\n    canvas.width=canvas.height=1;\n    return new Blob([M.pngDpi(new Uint8Array(await blob.arrayBuffer()))],{type:'image\/png'});\n  }\n  async function exportPNG(){if(state.exportBusy)return;if(!objects().some(o=\u003e!o.hidden))return toast('Add a design to this placement first.');state.exportBusy=true;action('export-png').disabled=true;try{const blob=await renderPNG(area());download(blob,'usastarfashion-'+state.method+'-'+state.placement+'.png');toast(state.method==='dtf'?'Transparent PNG downloaded at 300 pixels per inch.':'Embroidery preview downloaded. This is not a machine stitch file.');}catch(e){toast(e.message);}finally{state.exportBusy=false;action('export-png').disabled=false;}}\n  function safeFilename(name){return String(name||'artwork').replace(\/\\.[a-z0-9]+$\/i,'').replace(\/[^a-z0-9_-]+\/gi,'-').slice(0,65)||'artwork';}\n  async function assetFile(asset){await ensureAsset(asset);const blob=dataBlob(asset.src);return {blob,name:safeFilename(asset.name)+'.'+(blob.type==='image\/jpeg'?'jpg':blob.type==='image\/webp'?'webp':'png')};}\n  async function downloadLibraryArtwork(item){try{toast('Preparing artwork download…');const asset={src:item.src,sourceUrl:item.src,libraryId:item.id,fileId:item.fileId,name:item.name};if(asset.src.startsWith('data:image\/svg+xml'))asset.src=imageData(await readImage(asset.src));const f=await assetFile(asset);download(f.blob,f.name);toast('Artwork downloaded.');}catch(e){toast(e.message);}}\n  async function downloadArtwork(){if(selected()?.type!=='image')return toast('Select an image layer to download its source artwork.');try{const f=await assetFile(state.assets.get(selected().assetId));download(f.blob,f.name);toast('Source artwork downloaded.');}catch(e){toast(e.message);}}\n  async function mockupPNG(){\n    const canvas=document.createElement('canvas');canvas.width=1200;canvas.height=1300;const c=canvas.getContext('2d');c.fillStyle='#f3f5f3';c.fillRect(0,0,1200,1300);let garment;const source=productImage(M.placements[state.method][state.placement].side);\n    if(source){try{garment=await readImage(source,true);}catch{throw Error('The product image blocks preview downloads. You can still download the transparent design.');}}\n    else{const defs=ui('scene').querySelector('defs').outerHTML,g=ui('garment').cloneNode(true);g.style.display='';garment=await readImage('data:image\/svg+xml;charset=utf-8,'+encodeURIComponent('\u003csvg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"600\" height=\"650\" viewBox=\"0 0 600 650\"\u003e'+defs+g.outerHTML+'\u003c\/svg\u003e'));}\n    const gw=garment.naturalWidth,gh=garment.naturalHeight,fitScale=Math.min(1200\/gw,1300\/gh);c.drawImage(garment,(1200-gw*fitScale)\/2,(1300-gh*fitScale)\/2,gw*fitScale,gh*fitScale);\n    const design=await renderPNG(area()),data=await fileData(design),image=await readImage(data),r=M.rect(M.placements[state.method][state.placement],area());c.drawImage(image,r[0]*2,r[1]*2,r[2]*2,r[3]*2);\n    return new Promise((resolve,reject)=\u003e{try{canvas.toBlob(b=\u003eb?resolve(b):reject(Error('Preview download failed.')),'image\/png');}catch{reject(Error('The product image cannot be downloaded from its current source.'));}});\n  }\n  async function downloadMockup(){if(downloadBusy)return;downloadBusy=true;try{toast('Preparing product preview…');download(await mockupPNG(),'usastarfashion-product-preview.png');toast('Product preview downloaded.');}catch(e){toast(e.message);}finally{downloadBusy=false;}}\n  function activeProject(){const project=clone(projectData());delete project.projects[state.method==='dtf'?'embroidery':'dtf'];for(const a of Object.values(project.projects[state.method]))a.objects=a.objects.filter(o=\u003e!o.hidden);const used=new Set(visibleObjects().filter(o=\u003eo.type==='image').map(o=\u003eo.assetId));project.assets=project.assets.filter(a=\u003eused.has(a.id));return project;}\n  async function downloadPackage(){if(downloadBusy)return;if(!visibleObjects().length)return toast('Add a visible design first.');downloadBusy=true;try{toast('Preparing all designs and source artwork…');const files=[];for(const[key,a]of Object.entries(state.projects[state.method]))if(a.objects.some(o=\u003e!o.hidden))files.push({name:'designs\/'+state.method+'-'+key+'.png',data:new Uint8Array(await(await renderPNG(a)).arrayBuffer())});const ids=[...new Set(visibleObjects().filter(o=\u003eo.type==='image').map(o=\u003eo.assetId))];for(let i=0;i\u003cids.length;i++){const f=await assetFile(state.assets.get(ids[i]));files.push({name:'sources\/'+(i+1)+'-'+f.name,data:new Uint8Array(await f.blob.arrayBuffer())});}files.push({name:'project.json',data:new TextEncoder().encode(JSON.stringify(activeProject(),null,2))});files.push({name:'README.txt',data:new TextEncoder().encode('USASTARFASHION '+state.method+' design package. PNG designs contain 300-DPI metadata. Product placement is illustrative. Embroidery PNGs are design previews, not machine stitch files. Open project.json in the studio to continue editing.')} );download(new Blob(M.zip(files),{type:'application\/zip'}),'usastarfashion-'+state.method+'-design-package.zip');toast('Complete design package downloaded.');}catch(e){toast(e.message);}finally{downloadBusy=false;}}\n  async function imageAdjust(kind){const o=selected();if(o?.type!=='image')return toast('Select an image layer first.');if(o.locked)return toast('Unlock the image before editing.');if(imageBusy)return;imageBusy=true;try{const asset=await ensureAsset(state.assets.get(o.assetId)),image=await readImage(asset.src,true);if(image.naturalWidth*image.naturalHeight\u003e24000000)throw Error('Use an image below 24 megapixels for browser image adjustments.');const c=document.createElement('canvas');c.width=image.naturalWidth;c.height=image.naturalHeight;const ctx=c.getContext('2d');ctx.drawImage(image,0,0);const frame=ctx.getImageData(0,0,c.width,c.height),d=frame.data;let left=c.width,top=c.height,right=-1,bottom=-1;const threshold=255-Number(input('white-tolerance').value);for(let i=0;i\u003cd.length;i+=4){if(kind==='remove-white'\u0026\u0026Math.min(d[i],d[i+1],d[i+2])\u003e=threshold)d[i+3]=0;if(kind==='grayscale'){const y=Math.round(.2126*d[i]+.7152*d[i+1]+.0722*d[i+2]);d[i]=d[i+1]=d[i+2]=y;}if(kind==='high-contrast')for(let channel=0;channel\u003c3;channel++)d[i+channel]=M.clamp((d[i+channel]-128)*1.35+128,0,255);if(d[i+3]\u003e0){const x=i\/4%c.width,y=Math.floor(i\/4\/c.width);left=Math.min(left,x);right=Math.max(right,x);top=Math.min(top,y);bottom=Math.max(bottom,y);}}ctx.putImageData(frame,0,0);let result=c;if(kind==='trim-image'){if(right\u003cleft)throw Error('This artwork is fully transparent.');result=document.createElement('canvas');result.width=right-left+1;result.height=bottom-top+1;result.getContext('2d').drawImage(c,left,top,result.width,result.height,0,0,result.width,result.height);}remember();const id=uid();state.assets.set(id,{...asset,id,name:asset.name+' · '+kind,src:result.toDataURL('image\/png'),width:result.width,height:result.height});o.assetId=id;o.h=o.w*result.height\/result.width;fit(o);render();toast('Image adjusted. Use Undo to restore the previous version.');}catch(e){toast(e.message);}finally{imageBusy=false;}}\n  function flagLayer(flag){const o=selected();if(!o)return toast('Select a layer first.');remember();o[flag]=!o[flag];render();}\n  function reorderLayer(front){const o=selected();if(!o)return;if(o.locked)return toast('Unlock this layer before moving it.');remember();const list=objects(),i=list.indexOf(o);list.splice(i,1);front?list.push(o):list.unshift(o);render();}\n  function alignLayer(side){editSelected(o=\u003e{const b=M.bounds(o);if(side==='left')o.x=b.w\/2;if(side==='right')o.x=area().width-b.w\/2;if(side==='top')o.y=b.h\/2;if(side==='bottom')o.y=area().height-b.h\/2;});}\n  function toggleTextStyle(key){draftStyle[key]=!draftStyle[key];if(key==='bold')draftStyle.fontWeight=draftStyle.bold?700:400;syncDraftControls();previewText();}\n  function reviewRow(label,value){const row=el('div','uf-review-row');row.append(el('span',null,label),el('strong',null,value));return row;}\n  function review(){\n    const holder=ui('review-content');holder.replaceChildren();const qty=Math.round(M.clamp(input('quantity').value,1,999));input('quantity').value=qty;\n    holder.append(reviewRow('Product',state.product?.title||'Not connected'),reviewRow('Option',state.variant?.title||'Not selected'),reviewRow('Method',state.method==='dtf'?'DTF print':'Embroidery · '+input('finish').value),reviewRow('Quantity',String(qty)));\n    for(const[key,a]of Object.entries(state.projects[state.method]))if(a.objects.some(o=\u003e!o.hidden)){holder.append(reviewRow(M.placements[state.method][key].label,a.width+' × '+a.height+' mm'));const ul=el('ul');a.objects.filter(o=\u003e!o.hidden).forEach(o=\u003eul.append(el('li',null,nameOf(o))));holder.append(ul);}\n    holder.append(reviewRow('Product subtotal',state.variant?money(state.variant.price*qty):'Unavailable'));\n    if(input('notes').value.trim())holder.append(reviewRow('Notes',input('notes').value.trim()));\n    input('confirm').checked=false;action('add-cart').disabled=true;status('cart-status',demo?'Preview mode: no live order will be placed.':!visibleObjects().length?'Add artwork or text before ordering.':state.variant\u0026\u0026!state.variant.available?'This product option is sold out.':'Your current decoration method and all its placements will be included.');\n    ui('review-backdrop').hidden=false;ui('review').hidden=false;root.querySelectorAll('.uf-header,.uf-methodbar,.uf-layout,.uf-footer').forEach(e=\u003ee.inert=true);action('close-review').focus();\n  }\n  function closeReview(){if(state.cartBusy)return;ui('review').hidden=true;ui('review-backdrop').hidden=true;root.querySelectorAll('.uf-header,.uf-methodbar,.uf-layout,.uf-footer').forEach(e=\u003ee.inert=false);action('review').focus();}\n  async function addCart(){\n    if(state.cartBusy||!input('confirm').checked)return;if(demo)return status('cart-status','This is the working preview. Install the Liquid file on your Shopify product page for live ordering.');if(!state.variant?.available||!visibleObjects().length)return status('cart-status','Choose an available product option and add a design.',true);\n    state.cartBusy=true;action('add-cart').disabled=true;action('close-review').disabled=true;status('cart-status','Preparing your design files…');\n    try{const fd=new FormData();fd.append('id',String(state.variant.id));fd.append('quantity',String(Math.round(M.clamp(input('quantity').value,1,999))));fd.append('properties[Decoration]',state.method==='dtf'?'DTF print':'Embroidery');fd.append('properties[Production notes]',input('notes').value.trim());if(state.method==='embroidery')fd.append('properties[Embroidery finish]',input('finish').value);\n      for(const[key,a]of Object.entries(state.projects[state.method]))if(a.objects.some(o=\u003e!o.hidden)){const label=M.placements[state.method][key].label;fd.append('properties['+label+' size]',a.width+' × '+a.height+' mm');const blob=await renderPNG(a);fd.append('properties['+label+' artwork]',blob,state.method+'-'+key+'.png');}\n      const sourceIds=[...new Set(visibleObjects().filter(o=\u003eo.type==='image').map(o=\u003eo.assetId))];\n      for(let i=0;i\u003csourceIds.length;i++){const asset=state.assets.get(sourceIds[i]),file=await assetFile(asset);fd.append('properties[Source artwork '+(i+1)+']',file.blob,file.name);if(asset.sourceUrl)fd.append('properties[Drive source '+(i+1)+']',asset.sourceUrl);}\n      const active=activeProject();\n      \/\/ Keep all layer positions, fonts, source links and artwork in an attached job file.\n      fd.append('properties[Design project]',new Blob([JSON.stringify(active)],{type:'application\/json'}),'usastarfashion-design.json');\n      status('cart-status','Adding your personalised product to the cart…');const response=await fetch(rootPath()+'cart\/add.js',{method:'POST',headers:{Accept:'application\/json'},body:fd});const data=await response.json();if(!response.ok)throw Error(String(data.description||data.message||'The cart could not be updated.'));status('cart-status','Added to your cart. Opening cart…');location.assign(rootPath()+'cart');\n    }catch(e){status('cart-status',e.message,true);action('add-cart').disabled=false;}finally{state.cartBusy=false;action('close-review').disabled=false;}\n  }\n  function open(){if(dialog.open)return;state.lastFocus=document.activeElement;state.oldOverflow=document.documentElement.style.overflow;dialog.showModal();document.documentElement.style.overflow='hidden';if(!open.loaded){open.loaded=true;loadProduct();if(!demo)loadLibrary();}render();}\n  function close(){if(state.cartBusy)return;dialog.close();}\n  dialog.addEventListener('close',()=\u003e{document.documentElement.style.overflow=state.oldOverflow;state.lastFocus?.focus();});\n  dialog.addEventListener('cancel',e=\u003e{if(state.cartBusy){e.preventDefault();return;}if(!ui('review').hidden){e.preventDefault();closeReview();}});\n  const actions={open,close,'download-project':saveProject,'import-project':()=\u003einput('project-file').click(),'start-artwork':()=\u003e{setTab('art',true);input('upload').focus();},'refresh-library':loadLibrary,'more-library':()=\u003e{state.limit+=24;renderLibrary();},'add-text':()=\u003eaddText(),'update-text':()=\u003eaddText(true),generate:()=\u003egenerateAI(false),regenerate:()=\u003egenerateAI(true),'use-ai':()=\u003e{if(!state.aiResult)return;input('text').value=state.aiResult.text;input('font').value=state.aiResult.fontStyle;previewText();toast('AI text is ready. Choose Add text to place it on your product.');},undo:()=\u003ehistory('undo'),redo:()=\u003ehistory('redo'),center:()=\u003eeditSelected(o=\u003e{o.x=area().width\/2;o.y=area().height\/2;}),duplicate:()=\u003e{if(!selected()||allObjects().length\u003e=40)return;remember();const o=clone(selected());o.id=uid();o.x+=5;o.y+=5;fit(o);objects().push(o);state.selected=o.id;render();},delete:deleteSelected,'toggle-guides':()=\u003e{state.guides=!state.guides;action('toggle-guides').textContent=state.guides?'Hide guides':'Show guides';action('toggle-guides').setAttribute('aria-pressed',state.guides);renderScene();},'export-png':exportPNG,review,'close-review':closeReview,'add-cart':addCart};\n  Object.assign(actions,{\n    'use-ai':useAIText,'generate-image':()=\u003egenerateAIImage(false),'regenerate-image':()=\u003egenerateAIImage(true),'use-ai-image':useAIImage,'download-ai-image':downloadAIImage,\n    'start-ai-image':()=\u003e{setTab('image',true);input('ai-image-prompt').focus();},\n    'zoom-in':()=\u003esetZoom(state.zoom+.25),'zoom-out':()=\u003esetZoom(state.zoom-.25),'zoom-reset':()=\u003esetZoom(1),\n    'toggle-grid':()=\u003e{const off=ui('stage').classList.toggle('no-grid');action('toggle-grid').setAttribute('aria-pressed',!off);},\n    downloads:()=\u003e{setTab('tools',true);ui('artwork-quality').scrollIntoView({block:'nearest'});},\n    'download-artwork':downloadArtwork,'download-mockup':downloadMockup,'download-package':downloadPackage,\n    'flip-x':()=\u003eeditSelected(o=\u003eo.flipX=!o.flipX),'flip-y':()=\u003eeditSelected(o=\u003eo.flipY=!o.flipY),\n    'rotate-left':()=\u003eeditSelected(o=\u003eo.rotation=((o.rotation-90+540)%360)-180),'rotate-right':()=\u003eeditSelected(o=\u003eo.rotation=((o.rotation+90+540)%360)-180),\n    'align-left':()=\u003ealignLayer('left'),'align-right':()=\u003ealignLayer('right'),'align-top':()=\u003ealignLayer('top'),'align-bottom':()=\u003ealignLayer('bottom'),\n    'bring-front':()=\u003ereorderLayer(true),'send-back':()=\u003ereorderLayer(false),'lock-layer':()=\u003eflagLayer('locked'),'hide-layer':()=\u003eflagLayer('hidden'),\n    'remove-white':()=\u003eimageAdjust('remove-white'),grayscale:()=\u003eimageAdjust('grayscale'),'high-contrast':()=\u003eimageAdjust('high-contrast'),'trim-image':()=\u003eimageAdjust('trim-image'),\n    bold:()=\u003etoggleTextStyle('bold'),italic:()=\u003etoggleTextStyle('italic'),underline:()=\u003etoggleTextStyle('underline'),uppercase:()=\u003e{input('text').value=input('text').value.toUpperCase();previewText();}\n  });\n  root.querySelectorAll('[data-action]').forEach(b=\u003eb.addEventListener('click',()=\u003eactions[b.dataset.action]?.()));\n  root.querySelectorAll('[data-method]').forEach(b=\u003eb.onclick=()=\u003esetMethod(b.dataset.method));\n  root.querySelectorAll('[data-tab]').forEach(b=\u003e{b.onclick=()=\u003esetTab(b.dataset.tab);b.onkeydown=e=\u003e{if(!['ArrowLeft','ArrowRight','ArrowUp','ArrowDown','Home','End'].includes(e.key))return;e.preventDefault();const tabs=[...root.querySelectorAll('[data-tab]')],i=tabs.indexOf(b),next=e.key==='Home'?0:e.key==='End'?tabs.length-1:(i+(['ArrowRight','ArrowDown'].includes(e.key)?1:-1)+tabs.length)%tabs.length;setTab(tabs[next].dataset.tab);tabs[next].focus();};});\n  input('upload').onchange=e=\u003euploads(e.target.files);ui('dropzone').addEventListener('dragover',e=\u003e{e.preventDefault();ui('dropzone').classList.add('dragover');});ui('dropzone').addEventListener('dragleave',()=\u003eui('dropzone').classList.remove('dragover'));ui('dropzone').addEventListener('drop',e=\u003e{e.preventDefault();ui('dropzone').classList.remove('dragover');uploads(e.dataTransfer.files);});\n  input('library-search').oninput=()=\u003e{state.limit=24;renderLibrary();};input('placement').onchange=e=\u003esetPlacement(e.target.value);\n  input('variant').onchange=e=\u003e{state.variant=state.product?.variants.find(v=\u003eString(v.id)===e.target.value);updateProduct();render();};\n  ['text','text-colour','font-weight','text-size','shadow','tracking','leading','text-align','outline','outline-colour'].forEach(n=\u003einput(n).oninput=previewText);\n  input('font').onchange=async()=\u003e{const font=input('font').value;await fontReady(font,draftStyle);if(input('font').value===font)previewText();};\n  input('font-search').oninput=()=\u003epopulateFonts(input('font-search').value);\n  input('position-x').onchange=e=\u003eeditSelected(o=\u003eo.x=Number(e.target.value));input('position-y').onchange=e=\u003eeditSelected(o=\u003eo.y=Number(e.target.value));input('opacity').onchange=e=\u003eeditSelected(o=\u003eo.opacity=Number(e.target.value)\/100);\n  input('thread').onchange=e=\u003e{input('text-colour').value=e.target.value;if(selected()?.type==='text')editSelected(o=\u003eo.colour=e.target.value);else previewText();};\n  input('object-width').onchange=e=\u003eeditSelected(o=\u003e{const w=M.clamp(e.target.value,5,450);o.h*=w\/o.w;o.w=w;if(o.type==='text')sizeText(o);});input('rotation').onchange=e=\u003eeditSelected(o=\u003eo.rotation=M.clamp(e.target.value,-180,180));\n  input('area-width').onchange=input('area-height').onchange=changeDimensions;\n  input('project-file').onchange=e=\u003eimportProject(e.target.files[0]);\n  input('confirm').onchange=()=\u003eaction('add-cart').disabled=!input('confirm').checked||!state.variant?.available||!visibleObjects().length;\n  ui('review-backdrop').onclick=closeReview;\n  dialog.addEventListener('keydown',e=\u003e{\n    if(!ui('review').hidden){if(e.key==='Tab'){const list=[...ui('review').querySelectorAll('button:not(:disabled),input:not(:disabled)')];const first=list[0],last=list[list.length-1];if(e.shiftKey\u0026\u0026document.activeElement===first){e.preventDefault();last.focus();}else if(!e.shiftKey\u0026\u0026document.activeElement===last){e.preventDefault();first.focus();}}return;}\n    if(e.target.matches('input,textarea,select')||e.target.isContentEditable)return;\n    if((e.ctrlKey||e.metaKey)\u0026\u0026e.key.toLowerCase()==='z'){e.preventDefault();history(e.shiftKey?'redo':'undo');return;}\n    if(e.key==='Delete'||e.key==='Backspace'){if(selected()){e.preventDefault();deleteSelected();}return;}\n    if(selected()\u0026\u0026['ArrowLeft','ArrowRight','ArrowUp','ArrowDown'].includes(e.key)){e.preventDefault();const step=e.shiftKey?5:1;editSelected(o=\u003e{if(e.key==='ArrowLeft')o.x-=step;if(e.key==='ArrowRight')o.x+=step;if(e.key==='ArrowUp')o.y-=step;if(e.key==='ArrowDown')o.y+=step;});}\n  });\n  \/\/ The preview uses the same editor. Sample artwork is explicitly separate from Drive.\n  if(demo){const sample=(label,shape)=\u003e({name:label,category:'Preview sample',src:'data:image\/svg+xml;charset=utf-8,'+encodeURIComponent('\u003csvg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 300 260\"\u003e'+shape+'\u003c\/svg\u003e')});state.library=[sample('Mountain club','\u003cpath d=\"m30 200 80-145 53 96 35-59 75 108Z\" fill=\"none\" stroke=\"#335e4b\" stroke-width=\"9\"\/\u003e\u003ctext x=\"150\" y=\"239\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"bold\" font-size=\"21\" fill=\"#335e4b\"\u003eEXPLORE MORE\u003c\/text\u003e'),sample('Wild \u0026 free','\u003ctext x=\"150\" y=\"110\" text-anchor=\"middle\" font-family=\"Georgia\" font-size=\"53\" font-style=\"italic\" fill=\"#213a4d\"\u003ewild \u0026amp;\u003c\/text\u003e\u003ctext x=\"150\" y=\"170\" text-anchor=\"middle\" font-family=\"Georgia\" font-size=\"65\" font-style=\"italic\" fill=\"#213a4d\"\u003efree\u003c\/text\u003e'),sample('The everyday club','\u003ccircle cx=\"150\" cy=\"126\" r=\"95\" fill=\"none\" stroke=\"#a67d46\" stroke-width=\"4\"\/\u003e\u003ctext x=\"150\" y=\"125\" text-anchor=\"middle\" font-family=\"Arial\" font-size=\"24\" font-weight=\"bold\" fill=\"#a67d46\"\u003eEVERYDAY\u003c\/text\u003e\u003ctext x=\"150\" y=\"156\" text-anchor=\"middle\" font-family=\"Arial\" letter-spacing=\"8\" font-size=\"15\" fill=\"#a67d46\"\u003eCLUB\u003c\/text\u003e'),sample('Original','\u003ctext x=\"150\" y=\"142\" text-anchor=\"middle\" font-family=\"Georgia\" font-size=\"49\" font-weight=\"bold\" fill=\"#345d4c\"\u003eOriginal.\u003c\/text\u003e')];renderLibrary();status('library-status','Preview samples · Refresh loads your real Drive library.');}\n  populateFonts();syncDraftControls();\n  const presets=[['Modern','Professional',true,false,0,0],['Varsity','Sports',true,false,2,.7],['Retro','Retro',false,false,0,.5],['Signature','Wedding',false,false,0,0],['Bold outline','Bold',true,false,0,1.2],['Elegant','Elegant',false,false,4,0],['Typewriter','Special Elite',false,false,1,0],['Biker','Biker',false,false,0,.6],['Minimal','Inter',false,false,8,0],['Handwritten','Caveat',false,false,0,0],['Neon outline','Righteous',false,false,2,1],['Classic','Classic',true,true,0,0]];\n  for(const[label,font,bold,italic,tracking,outline]of presets){const b=el('button',null,label);b.type='button';b.style.fontFamily=fonts[font];b.onclick=async()=\u003e{populateFonts();input('font').value=font;draftStyle=M.style({bold,italic,tracking,outline});syncDraftControls();await fontReady(font,draftStyle);previewText();toast(label+' style ready. Add text or update the selected text.');};ui('font-presets').append(b);}\n  syncMethod();previewText();render();\n  if(demo)open();\n  if(root.dataset.test==='true')root.__test={state,area,objects,selected,render,setMethod,setPlacement,addText,addArtwork,loadLibrary,generateAI,saveProject,importProject,renderPNG,addCart,review,closeReview,actions,generateAIImage,useAIImage,downloadAIImage,normaliseAI,fonts,textLayout,ensureAsset,driveBytes,downloadPackage,mockupPNG,imageAdjust};\n})();\n\n\u003c\/script\u003e\n\u003c\/div\u003e","brand":"USASTARFASHION","offers":[{"title":"Embroidery \/ White \/ S","offer_id":58586747568459,"sku":null,"price":29.0,"currency_code":"GBP","in_stock":true},{"title":"Embroidery \/ White \/ M","offer_id":58586747601227,"sku":null,"price":29.0,"currency_code":"GBP","in_stock":false},{"title":"Embroidery \/ White \/ L","offer_id":58586747633995,"sku":null,"price":29.0,"currency_code":"GBP","in_stock":false},{"title":"Embroidery \/ White \/ XL","offer_id":58586747666763,"sku":null,"price":29.0,"currency_code":"GBP","in_stock":false},{"title":"Embroidery \/ White \/ 2XL","offer_id":58586747699531,"sku":null,"price":29.0,"currency_code":"GBP","in_stock":false},{"title":"Embroidery \/ White \/ 4XL","offer_id":58586747732299,"sku":null,"price":29.0,"currency_code":"GBP","in_stock":false},{"title":"Embroidery \/ White \/ 3XL","offer_id":58586747765067,"sku":null,"price":29.0,"currency_code":"GBP","in_stock":false},{"title":"Embroidery \/ Red dark \/ S","offer_id":58586747797835,"sku":null,"price":29.0,"currency_code":"GBP","in_stock":true},{"title":"Embroidery \/ Red dark \/ M","offer_id":58586747830603,"sku":null,"price":29.0,"currency_code":"GBP","in_stock":false},{"title":"Embroidery \/ Red dark \/ L","offer_id":58586747863371,"sku":null,"price":29.0,"currency_code":"GBP","in_stock":false},{"title":"Embroidery \/ Red dark \/ XL","offer_id":58586747896139,"sku":null,"price":29.0,"currency_code":"GBP","in_stock":false},{"title":"Embroidery \/ Red dark \/ 2XL","offer_id":58586747928907,"sku":null,"price":29.0,"currency_code":"GBP","in_stock":false},{"title":"Embroidery \/ Red dark \/ 4XL","offer_id":58586747961675,"sku":null,"price":29.0,"currency_code":"GBP","in_stock":false},{"title":"Embroidery \/ Red dark \/ 3XL","offer_id":58586747994443,"sku":null,"price":29.0,"currency_code":"GBP","in_stock":false},{"title":"Embroidery \/ Blue \/ S","offer_id":58586748027211,"sku":null,"price":29.0,"currency_code":"GBP","in_stock":true},{"title":"Embroidery \/ Blue \/ M","offer_id":58586748059979,"sku":null,"price":29.0,"currency_code":"GBP","in_stock":false},{"title":"Embroidery \/ Blue \/ L","offer_id":58586748092747,"sku":null,"price":29.0,"currency_code":"GBP","in_stock":false},{"title":"Embroidery \/ Blue \/ XL","offer_id":58586748125515,"sku":null,"price":29.0,"currency_code":"GBP","in_stock":false},{"title":"Embroidery \/ Blue \/ 2XL","offer_id":58586748158283,"sku":null,"price":29.0,"currency_code":"GBP","in_stock":false},{"title":"Embroidery \/ Blue \/ 4XL","offer_id":58586748191051,"sku":null,"price":29.0,"currency_code":"GBP","in_stock":false},{"title":"Embroidery \/ Blue \/ 3XL","offer_id":58586748223819,"sku":null,"price":29.0,"currency_code":"GBP","in_stock":false},{"title":"Embroidery \/ Yellow \/ S","offer_id":58586748256587,"sku":null,"price":29.0,"currency_code":"GBP","in_stock":true},{"title":"Embroidery \/ Yellow \/ M","offer_id":58586748289355,"sku":null,"price":29.0,"currency_code":"GBP","in_stock":false},{"title":"Embroidery \/ Yellow \/ L","offer_id":58586748322123,"sku":null,"price":29.0,"currency_code":"GBP","in_stock":false},{"title":"Embroidery \/ Yellow \/ XL","offer_id":58586748354891,"sku":null,"price":29.0,"currency_code":"GBP","in_stock":false},{"title":"Embroidery \/ Yellow \/ 2XL","offer_id":58586748387659,"sku":null,"price":29.0,"currency_code":"GBP","in_stock":false},{"title":"Embroidery \/ Yellow \/ 4XL","offer_id":58586748420427,"sku":null,"price":29.0,"currency_code":"GBP","in_stock":false},{"title":"Embroidery \/ Yellow \/ 3XL","offer_id":58586748453195,"sku":null,"price":29.0,"currency_code":"GBP","in_stock":false},{"title":"Embroidery \/ Green \/ S","offer_id":58586748485963,"sku":null,"price":29.0,"currency_code":"GBP","in_stock":true},{"title":"Embroidery \/ Green \/ M","offer_id":58586748518731,"sku":null,"price":29.0,"currency_code":"GBP","in_stock":false},{"title":"Embroidery \/ Green \/ L","offer_id":58586748551499,"sku":null,"price":29.0,"currency_code":"GBP","in_stock":false},{"title":"Embroidery \/ Green \/ XL","offer_id":58586748584267,"sku":null,"price":29.0,"currency_code":"GBP","in_stock":false},{"title":"Embroidery \/ Green \/ 2XL","offer_id":58586748617035,"sku":null,"price":29.0,"currency_code":"GBP","in_stock":false},{"title":"Embroidery \/ Green \/ 4XL","offer_id":58586748649803,"sku":null,"price":29.0,"currency_code":"GBP","in_stock":false},{"title":"Embroidery \/ Green \/ 3XL","offer_id":58586748682571,"sku":null,"price":29.0,"currency_code":"GBP","in_stock":false},{"title":"Embroidery \/ Navy \/ S","offer_id":58586748715339,"sku":null,"price":29.0,"currency_code":"GBP","in_stock":true},{"title":"Embroidery \/ Navy \/ M","offer_id":58586748748107,"sku":null,"price":29.0,"currency_code":"GBP","in_stock":false},{"title":"Embroidery \/ Navy \/ L","offer_id":58586748780875,"sku":null,"price":29.0,"currency_code":"GBP","in_stock":false},{"title":"Embroidery \/ Navy \/ XL","offer_id":58586748813643,"sku":null,"price":29.0,"currency_code":"GBP","in_stock":false},{"title":"Embroidery \/ Navy \/ 2XL","offer_id":58586748846411,"sku":null,"price":29.0,"currency_code":"GBP","in_stock":false},{"title":"Embroidery \/ Navy \/ 4XL","offer_id":58586748879179,"sku":null,"price":29.0,"currency_code":"GBP","in_stock":false},{"title":"Embroidery \/ Navy \/ 3XL","offer_id":58586748911947,"sku":null,"price":29.0,"currency_code":"GBP","in_stock":false},{"title":"Embroidery \/ Black \/ S","offer_id":58586748944715,"sku":null,"price":29.0,"currency_code":"GBP","in_stock":true},{"title":"Embroidery \/ Black \/ M","offer_id":58586748977483,"sku":null,"price":29.0,"currency_code":"GBP","in_stock":false},{"title":"Embroidery \/ Black \/ L","offer_id":58586749010251,"sku":null,"price":29.0,"currency_code":"GBP","in_stock":false},{"title":"Embroidery \/ Black \/ XL","offer_id":58586749043019,"sku":null,"price":29.0,"currency_code":"GBP","in_stock":false},{"title":"Embroidery \/ Black \/ 2XL","offer_id":58586749075787,"sku":null,"price":29.0,"currency_code":"GBP","in_stock":false},{"title":"Embroidery \/ Black \/ 4XL","offer_id":58586749108555,"sku":null,"price":29.0,"currency_code":"GBP","in_stock":false},{"title":"Embroidery \/ Black \/ 3XL","offer_id":58586749141323,"sku":null,"price":29.0,"currency_code":"GBP","in_stock":false},{"title":"DTF PRINT \/ White \/ S","offer_id":58586749174091,"sku":null,"price":16.99,"currency_code":"GBP","in_stock":true},{"title":"DTF PRINT \/ White \/ M","offer_id":58586749206859,"sku":null,"price":16.99,"currency_code":"GBP","in_stock":true},{"title":"DTF PRINT \/ White \/ L","offer_id":58586749239627,"sku":null,"price":16.99,"currency_code":"GBP","in_stock":true},{"title":"DTF PRINT \/ White \/ XL","offer_id":58586749272395,"sku":null,"price":16.99,"currency_code":"GBP","in_stock":true},{"title":"DTF PRINT \/ White \/ 2XL","offer_id":58586749305163,"sku":null,"price":16.99,"currency_code":"GBP","in_stock":true},{"title":"DTF PRINT \/ White \/ 4XL","offer_id":58586749337931,"sku":null,"price":16.99,"currency_code":"GBP","in_stock":true},{"title":"DTF PRINT \/ White \/ 3XL","offer_id":58586749370699,"sku":null,"price":16.99,"currency_code":"GBP","in_stock":true},{"title":"DTF PRINT \/ Red dark \/ S","offer_id":58586749403467,"sku":null,"price":16.99,"currency_code":"GBP","in_stock":true},{"title":"DTF PRINT \/ Red dark \/ M","offer_id":58586749436235,"sku":null,"price":16.99,"currency_code":"GBP","in_stock":true},{"title":"DTF PRINT \/ Red dark \/ L","offer_id":58586749469003,"sku":null,"price":16.99,"currency_code":"GBP","in_stock":true},{"title":"DTF PRINT \/ Red dark \/ XL","offer_id":58586749501771,"sku":null,"price":16.99,"currency_code":"GBP","in_stock":true},{"title":"DTF PRINT \/ Red dark \/ 2XL","offer_id":58586749534539,"sku":null,"price":16.99,"currency_code":"GBP","in_stock":true},{"title":"DTF PRINT \/ Red dark \/ 4XL","offer_id":58586749567307,"sku":null,"price":16.99,"currency_code":"GBP","in_stock":true},{"title":"DTF PRINT \/ Red dark \/ 3XL","offer_id":58586749600075,"sku":null,"price":16.99,"currency_code":"GBP","in_stock":true},{"title":"DTF PRINT \/ Blue \/ S","offer_id":58586749632843,"sku":null,"price":16.99,"currency_code":"GBP","in_stock":true},{"title":"DTF PRINT \/ Blue \/ M","offer_id":58586749665611,"sku":null,"price":16.99,"currency_code":"GBP","in_stock":true},{"title":"DTF PRINT \/ Blue \/ L","offer_id":58586749698379,"sku":null,"price":16.99,"currency_code":"GBP","in_stock":true},{"title":"DTF PRINT \/ Blue \/ XL","offer_id":58586749731147,"sku":null,"price":16.99,"currency_code":"GBP","in_stock":true},{"title":"DTF PRINT \/ Blue \/ 2XL","offer_id":58586749763915,"sku":null,"price":16.99,"currency_code":"GBP","in_stock":true},{"title":"DTF PRINT \/ Blue \/ 4XL","offer_id":58586749796683,"sku":null,"price":16.99,"currency_code":"GBP","in_stock":true},{"title":"DTF PRINT \/ Blue \/ 3XL","offer_id":58586749829451,"sku":null,"price":16.99,"currency_code":"GBP","in_stock":true},{"title":"DTF PRINT \/ Yellow \/ S","offer_id":58586749862219,"sku":null,"price":16.99,"currency_code":"GBP","in_stock":true},{"title":"DTF PRINT \/ Yellow \/ M","offer_id":58586749894987,"sku":null,"price":16.99,"currency_code":"GBP","in_stock":true},{"title":"DTF PRINT \/ Yellow \/ L","offer_id":58586749927755,"sku":null,"price":16.99,"currency_code":"GBP","in_stock":true},{"title":"DTF PRINT \/ Yellow \/ XL","offer_id":58586749960523,"sku":null,"price":16.99,"currency_code":"GBP","in_stock":true},{"title":"DTF PRINT \/ Yellow \/ 2XL","offer_id":58586749993291,"sku":null,"price":16.99,"currency_code":"GBP","in_stock":true},{"title":"DTF PRINT \/ Yellow \/ 4XL","offer_id":58586750026059,"sku":null,"price":16.99,"currency_code":"GBP","in_stock":true},{"title":"DTF PRINT \/ Yellow \/ 3XL","offer_id":58586750058827,"sku":null,"price":16.99,"currency_code":"GBP","in_stock":true},{"title":"DTF PRINT \/ Green \/ S","offer_id":58586750091595,"sku":null,"price":16.99,"currency_code":"GBP","in_stock":true},{"title":"DTF PRINT \/ Green \/ M","offer_id":58586750124363,"sku":null,"price":16.99,"currency_code":"GBP","in_stock":true},{"title":"DTF PRINT \/ Green \/ L","offer_id":58586750157131,"sku":null,"price":16.99,"currency_code":"GBP","in_stock":true},{"title":"DTF PRINT \/ Green \/ XL","offer_id":58586750189899,"sku":null,"price":16.99,"currency_code":"GBP","in_stock":true},{"title":"DTF PRINT \/ Green \/ 2XL","offer_id":58586750222667,"sku":null,"price":16.99,"currency_code":"GBP","in_stock":true},{"title":"DTF PRINT \/ Green \/ 4XL","offer_id":58586750255435,"sku":null,"price":16.99,"currency_code":"GBP","in_stock":true},{"title":"DTF PRINT \/ Green \/ 3XL","offer_id":58586750288203,"sku":null,"price":16.99,"currency_code":"GBP","in_stock":true},{"title":"DTF PRINT \/ Navy \/ S","offer_id":58586750320971,"sku":null,"price":16.99,"currency_code":"GBP","in_stock":true},{"title":"DTF PRINT \/ Navy \/ M","offer_id":58586750353739,"sku":null,"price":16.99,"currency_code":"GBP","in_stock":true},{"title":"DTF PRINT \/ Navy \/ L","offer_id":58586750386507,"sku":null,"price":16.99,"currency_code":"GBP","in_stock":true},{"title":"DTF PRINT \/ Navy \/ XL","offer_id":58586750419275,"sku":null,"price":16.99,"currency_code":"GBP","in_stock":true},{"title":"DTF PRINT \/ Navy \/ 2XL","offer_id":58586750452043,"sku":null,"price":16.99,"currency_code":"GBP","in_stock":true},{"title":"DTF PRINT \/ Navy \/ 4XL","offer_id":58586750484811,"sku":null,"price":16.99,"currency_code":"GBP","in_stock":true},{"title":"DTF PRINT \/ Navy \/ 3XL","offer_id":58586750517579,"sku":null,"price":16.99,"currency_code":"GBP","in_stock":true},{"title":"DTF PRINT \/ Black \/ S","offer_id":58586750550347,"sku":null,"price":16.99,"currency_code":"GBP","in_stock":true},{"title":"DTF PRINT \/ Black \/ M","offer_id":58586750583115,"sku":null,"price":16.99,"currency_code":"GBP","in_stock":true},{"title":"DTF PRINT \/ Black \/ L","offer_id":58586750615883,"sku":null,"price":16.99,"currency_code":"GBP","in_stock":true},{"title":"DTF PRINT \/ Black \/ XL","offer_id":58586750648651,"sku":null,"price":16.99,"currency_code":"GBP","in_stock":true},{"title":"DTF PRINT \/ Black \/ 2XL","offer_id":58586750681419,"sku":null,"price":16.99,"currency_code":"GBP","in_stock":true},{"title":"DTF PRINT \/ Black \/ 4XL","offer_id":58586750714187,"sku":null,"price":16.99,"currency_code":"GBP","in_stock":true},{"title":"DTF PRINT \/ Black \/ 3XL","offer_id":58586750746955,"sku":null,"price":16.99,"currency_code":"GBP","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0818\/3575\/3803\/files\/plain-t-shirt.png?v=1790108626","url":"https:\/\/www.usastarfashion.com\/products\/personalized-custom-t-shirts-copy-copy-copy","provider":"USASTARFASHION","version":"1.0","type":"link"}