dreative 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ *{box-sizing:border-box}html,body,#root{height:100%;margin:0}body{font-family:ui-sans-serif,system-ui,Segoe UI,sans-serif;background:#0f1117;color:#e6e8ee;font-size:14px}.app{display:flex;flex-direction:column;height:100%}.topbar{display:flex;align-items:center;gap:12px;padding:10px 16px;border-bottom:1px solid #23262f;background:#14161d}.topbar .logo{font-weight:700;letter-spacing:.5px;color:#a5b4fc}.topbar input{flex:1;max-width:560px;background:#0f1117;border:1px solid #2c2f3a;border-radius:8px;color:#e6e8ee;padding:8px 12px;outline:none}.topbar input:focus{border-color:#6366f1}button{background:#6366f1;color:#fff;border:0;border-radius:8px;padding:8px 14px;cursor:pointer;font-weight:600;font-size:13px}button:hover{background:#575ae0}button:disabled{opacity:.5;cursor:default}button.ghost{background:transparent;border:1px solid #2c2f3a;color:#c7cad4}button.ghost:hover{border-color:#6366f1;color:#fff}button.danger{background:#3a2030;color:#f7a6b8}.main{flex:1;display:flex;min-height:0}.workspace{flex:1;min-width:0;position:relative}.inspector{width:320px;border-left:1px solid #23262f;background:#14161d;padding:16px;overflow-y:auto;display:flex;flex-direction:column;gap:12px}.inspector h3{margin:0;font-size:13px;text-transform:uppercase;letter-spacing:1px;color:#8b8fa3}.inspector textarea,.inspector input[type=text]{width:100%;background:#0f1117;border:1px solid #2c2f3a;border-radius:8px;color:#e6e8ee;padding:8px 10px;outline:none;resize:vertical;font-family:inherit}.inspector textarea:focus,.inspector input:focus{border-color:#6366f1}.inspector .hint{color:#8b8fa3;font-size:12px;line-height:1.5}.inspector .intent{background:#1c1f29;border-radius:6px;padding:6px 10px;font-size:12px;color:#c4b5fd;display:flex;align-items:center;gap:6px}.inspector .intent .intent-x{margin-left:auto;cursor:pointer;color:#8b8fa3;font-weight:700}.inspector .intent .intent-x:hover{color:#f87171}.inspector .btn-row{display:flex;gap:8px}.inspector .btn-row>*{flex:1}.inspector select{background:#0f1117;border:1px solid #2c2f3a;border-radius:8px;color:#e6e8ee;padding:8px 10px;outline:none}.hint-inline{color:#8b8fa3;font-size:12px}.inspector .steps{margin:0;padding-left:18px;color:#c7cad4;font-size:13px;line-height:1.7}.inspector kbd{background:#23262f;border-radius:4px;padding:1px 5px;font-size:11px}.empty-state{height:100%;display:flex;align-items:center;justify-content:center}.empty-card{max-width:520px;text-align:center;padding:32px}.empty-logo{font-size:40px;color:#6366f1;margin-bottom:8px}.empty-card h1{margin:0 0 10px;font-size:24px}.empty-card p{color:#9aa0b4;line-height:1.6}.empty-examples{display:flex;flex-wrap:wrap;gap:8px;justify-content:center;margin-top:18px}.breadcrumb{display:flex;gap:4px;align-items:center;font-size:12px;color:#8b8fa3;margin-left:8px}.breadcrumb .crumb{cursor:pointer;padding:2px 6px;border-radius:4px}.breadcrumb .crumb:hover{background:#23262f;color:#fff}.breadcrumb .crumb.current{color:#a5b4fc;font-weight:600}.crumb-sep{color:#3b3f4d}.wf-block.has-ref:before{content:"๐Ÿ–ผ";position:absolute;top:3px;right:20px;font-size:10px;z-index:2}.page-node header .open-btn{padding:3px 10px;font-size:11px;background:#2c2f3a;color:#c7cad4;opacity:0;transition:opacity .12s}.page-node:hover header .open-btn{opacity:1}.page-node header .open-btn:hover{background:#6366f1;color:#fff}.statusbar{position:fixed;bottom:16px;left:50%;transform:translate(-50%);background:#1c1f29;border:1px solid #6366f1;border-radius:999px;padding:8px 20px;z-index:50;display:flex;gap:10px;align-items:center}.statusbar .spinner{width:14px;height:14px;border:2px solid #6366f1;border-top-color:transparent;border-radius:50%;animation:spin .8s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}.errorbar{position:fixed;bottom:16px;left:50%;transform:translate(-50%);background:#2a1420;border:1px solid #e11d48;color:#fda4af;border-radius:8px;padding:8px 16px;z-index:50;max-width:70vw;cursor:pointer}.page-node{width:420px;background:#171a22;border:1px solid #2c2f3a;border-radius:12px;overflow:hidden;box-shadow:0 8px 30px #00000059}.page-node.selected{border-color:#6366f1}.page-node header{display:flex;align-items:center;justify-content:space-between;padding:8px 12px;background:#1c1f29;cursor:grab}.page-node header .name{font-weight:600}.page-node header .badge{font-size:11px;padding:2px 8px;border-radius:999px;background:#2c2f3a;color:#8b8fa3}.page-node header .badge.designed{background:#14321f;color:#6ee7a0}.page-node .mini{padding:10px;pointer-events:none}.wf-paper{--fg: var(--wfp-fg, #35507a);--accent: var(--wfp-accent, #4f6ef7);background:var(--wfp-bg, linear-gradient(180deg, #f4f8ff, #e9f0fc));color:var(--fg);border:1px solid color-mix(in srgb,var(--fg) 25%,transparent);border-radius:14px;padding:14px;box-shadow:0 10px 40px #1e40af1f}.wf-block{position:relative;border-radius:10px;padding:10px;display:flex;flex-direction:column;gap:8px;background:color-mix(in srgb,var(--fg) 7%,transparent);border:1.5px solid transparent;min-height:30px}.wf-block.leaf{background:transparent;padding:4px;justify-content:center}.wf-children{display:flex;gap:10px;flex:1;min-width:0}.wf-children>.wf-block,.wf-children>.wf-sortable{flex:1;min-width:0}.wf-block.selected{border-color:#4f6ef7;background:#6366f11f}.wf-block.has-intents:after{content:"โšก";position:absolute;top:3px;right:6px;font-size:10px;z-index:2}.wf-tag{position:absolute;top:-8px;left:8px;z-index:2;font-size:9px;font-weight:700;letter-spacing:.4px;background:#4f6ef7;color:#fff;border-radius:4px;padding:1px 6px;opacity:0;transition:opacity .12s;pointer-events:none}.wf-block:hover>.wf-tag,.wf-block.selected>.wf-tag{opacity:1}.wf-block:hover{outline:1px dashed rgba(79,110,247,.5);outline-offset:-1px}.g-line{height:5px;border-radius:3px;background:color-mix(in srgb,var(--fg) 40%,transparent);margin:3px 0}.g-real{font-size:10px;line-height:1.35;color:color-mix(in srgb,var(--fg) 92%,transparent);overflow-wrap:anywhere}.g-real-lg{font-size:13px;font-weight:700}.g-hero-text{font-size:19px;font-weight:800;letter-spacing:-.3px;margin-bottom:8px;color:var(--fg)}.g-text{display:flex;flex-direction:column;justify-content:center}.g-button{width:96px;max-width:70%;height:22px;border-radius:7px;background:var(--accent)}.g-image{width:100%;min-height:64px;flex:1;border-radius:8px;background:color-mix(in srgb,var(--fg) 22%,transparent)}.g-button-labeled{width:auto;padding:0 12px;display:inline-flex;align-items:center;justify-content:center;color:#fff;font-size:10px;font-weight:600;white-space:nowrap}.g-nav{display:flex;align-items:center;gap:10px;width:100%;background:color-mix(in srgb,var(--accent) 85%,#1c1c22);border-radius:8px;padding:8px 12px}.g-nav-dot{width:18px;height:18px;border-radius:5px;background:#ffffffd9}.g-nav-links{display:flex;gap:8px;flex:1;justify-content:center}.g-nav-links span{width:34px;height:6px;border-radius:3px;background:#ffffffa6}.g-nav-cta{width:46px;height:16px;border-radius:6px;background:#ffffffe6}.g-hero{width:100%;min-height:110px;border-radius:10px;padding:18px;background:color-mix(in srgb,var(--fg) 10%,transparent);display:flex;flex-direction:column;justify-content:center}.g-hero-title{width:60%;height:16px;border-radius:6px;background:color-mix(in srgb,var(--fg) 45%,transparent);margin-bottom:8px}.g-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;width:100%}.g-card{background:color-mix(in srgb,var(--fg) 8%,transparent);border:1px solid color-mix(in srgb,var(--fg) 18%,transparent);border-radius:9px;padding:8px;display:flex;flex-direction:column}.g-card-media{height:34px;border-radius:6px;background:color-mix(in srgb,var(--accent) 35%,transparent);margin-bottom:7px}.g-list{display:flex;flex-direction:column;gap:8px;width:100%}.g-list-row{display:flex;gap:10px;align-items:center;background:color-mix(in srgb,var(--fg) 8%,transparent);border-radius:8px;padding:7px 9px}.g-list-thumb{width:30px;height:30px;border-radius:6px;background:color-mix(in srgb,var(--accent) 40%,transparent);flex:none}.g-form{display:flex;flex-direction:column;gap:8px;width:100%}.g-input{height:22px;border-radius:6px;background:color-mix(in srgb,var(--fg) 6%,transparent);border:1px solid color-mix(in srgb,var(--fg) 25%,transparent)}.g-footer{width:100%;border-radius:8px;padding:12px;background:color-mix(in srgb,var(--accent) 85%,#1c1c22);display:flex;align-items:center;justify-content:space-between;gap:16px}.g-footer .g-line{background:#fff9}.g-footer .g-nav-links{flex:none}.editor-view{height:100%;display:flex;flex-direction:column}.editor-toolbar{display:flex;gap:8px;padding:10px 16px;border-bottom:1px solid #23262f;align-items:center}.editor-scroll{flex:1;overflow:auto;padding:24px;display:flex;justify-content:center}.editor-page{width:760px}.preview-frame{flex:1;border:0;width:100%;background:#fff}.drop-ref{border:1.5px dashed #2c2f3a;border-radius:8px;padding:14px;text-align:center;color:#8b8fa3;cursor:pointer}.drop-ref:hover{border-color:#6366f1}.drop-ref img{max-width:100%;border-radius:6px}.dial{display:flex;flex-direction:column;gap:2px;margin-bottom:6px;font-size:12px;color:#8b8fa3}.dial span{display:flex;justify-content:space-between}.dial em{font-style:normal;color:#c9cbe0}.dial input[type=range]{width:100%;accent-color:#6366f1}.lint{font-size:12px;color:#fbbf24;background:#fbbf2414;border:1px solid rgba(251,191,36,.25);border-radius:6px;padding:6px 8px;margin:4px 0}.react-flow{direction:ltr;--xy-edge-stroke-default: #b1b1b7;--xy-edge-stroke-width-default: 1;--xy-edge-stroke-selected-default: #555;--xy-connectionline-stroke-default: #b1b1b7;--xy-connectionline-stroke-width-default: 1;--xy-attribution-background-color-default: rgba(255, 255, 255, .5);--xy-minimap-background-color-default: #fff;--xy-minimap-mask-background-color-default: rgba(240, 240, 240, .6);--xy-minimap-mask-stroke-color-default: transparent;--xy-minimap-mask-stroke-width-default: 1;--xy-minimap-node-background-color-default: #e2e2e2;--xy-minimap-node-stroke-color-default: transparent;--xy-minimap-node-stroke-width-default: 2;--xy-background-color-default: transparent;--xy-background-pattern-dots-color-default: #91919a;--xy-background-pattern-lines-color-default: #eee;--xy-background-pattern-cross-color-default: #e2e2e2;background-color:var(--xy-background-color, var(--xy-background-color-default));--xy-node-color-default: inherit;--xy-node-border-default: 1px solid #1a192b;--xy-node-background-color-default: #fff;--xy-node-group-background-color-default: rgba(240, 240, 240, .25);--xy-node-boxshadow-hover-default: 0 1px 4px 1px rgba(0, 0, 0, .08);--xy-node-boxshadow-selected-default: 0 0 0 .5px #1a192b;--xy-node-border-radius-default: 3px;--xy-handle-background-color-default: #1a192b;--xy-handle-border-color-default: #fff;--xy-selection-background-color-default: rgba(0, 89, 220, .08);--xy-selection-border-default: 1px dotted rgba(0, 89, 220, .8);--xy-controls-button-background-color-default: #fefefe;--xy-controls-button-background-color-hover-default: #f4f4f4;--xy-controls-button-color-default: inherit;--xy-controls-button-color-hover-default: inherit;--xy-controls-button-border-color-default: #eee;--xy-controls-box-shadow-default: 0 0 2px 1px rgba(0, 0, 0, .08);--xy-edge-label-background-color-default: #ffffff;--xy-edge-label-color-default: inherit;--xy-resize-background-color-default: #3367d9}.react-flow.dark{--xy-edge-stroke-default: #3e3e3e;--xy-edge-stroke-width-default: 1;--xy-edge-stroke-selected-default: #727272;--xy-connectionline-stroke-default: #b1b1b7;--xy-connectionline-stroke-width-default: 1;--xy-attribution-background-color-default: rgba(150, 150, 150, .25);--xy-minimap-background-color-default: #141414;--xy-minimap-mask-background-color-default: rgba(60, 60, 60, .6);--xy-minimap-mask-stroke-color-default: transparent;--xy-minimap-mask-stroke-width-default: 1;--xy-minimap-node-background-color-default: #2b2b2b;--xy-minimap-node-stroke-color-default: transparent;--xy-minimap-node-stroke-width-default: 2;--xy-background-color-default: #141414;--xy-background-pattern-dots-color-default: #555;--xy-background-pattern-lines-color-default: #333;--xy-background-pattern-cross-color-default: #333;--xy-node-color-default: #f8f8f8;--xy-node-border-default: 1px solid #3c3c3c;--xy-node-background-color-default: #1e1e1e;--xy-node-group-background-color-default: rgba(240, 240, 240, .25);--xy-node-boxshadow-hover-default: 0 1px 4px 1px rgba(255, 255, 255, .08);--xy-node-boxshadow-selected-default: 0 0 0 .5px #999;--xy-handle-background-color-default: #bebebe;--xy-handle-border-color-default: #1e1e1e;--xy-selection-background-color-default: rgba(200, 200, 220, .08);--xy-selection-border-default: 1px dotted rgba(200, 200, 220, .8);--xy-controls-button-background-color-default: #2b2b2b;--xy-controls-button-background-color-hover-default: #3e3e3e;--xy-controls-button-color-default: #f8f8f8;--xy-controls-button-color-hover-default: #fff;--xy-controls-button-border-color-default: #5b5b5b;--xy-controls-box-shadow-default: 0 0 2px 1px rgba(0, 0, 0, .08);--xy-edge-label-background-color-default: #141414;--xy-edge-label-color-default: #f8f8f8}.react-flow__background{background-color:var(--xy-background-color-props, var(--xy-background-color, var(--xy-background-color-default)));pointer-events:none;z-index:-1}.react-flow__container{position:absolute;width:100%;height:100%;top:0;left:0}.react-flow__pane{z-index:1;touch-action:none}.react-flow__pane.draggable{cursor:grab}.react-flow__pane.dragging{cursor:grabbing}.react-flow__pane.selection{cursor:pointer}.react-flow__viewport{transform-origin:0 0;z-index:2;pointer-events:none}.react-flow__renderer{z-index:4}.react-flow__selection{z-index:6}.react-flow__nodesselection-rect:focus,.react-flow__nodesselection-rect:focus-visible{outline:none}.react-flow__edge-path{stroke:var(--xy-edge-stroke, var(--xy-edge-stroke-default));stroke-width:var(--xy-edge-stroke-width, var(--xy-edge-stroke-width-default));fill:none}.react-flow__connection-path{stroke:var(--xy-connectionline-stroke, var(--xy-connectionline-stroke-default));stroke-width:var(--xy-connectionline-stroke-width, var(--xy-connectionline-stroke-width-default));fill:none}.react-flow .react-flow__edges{position:absolute}.react-flow .react-flow__edges svg{overflow:visible;position:absolute;pointer-events:none}.react-flow__edge{pointer-events:visibleStroke}.react-flow__edge.selectable{cursor:pointer}.react-flow__edge.animated path{stroke-dasharray:5;animation:dashdraw .5s linear infinite}.react-flow__edge.animated path.react-flow__edge-interaction{stroke-dasharray:none;animation:none}.react-flow__edge.inactive{pointer-events:none}.react-flow__edge.selected,.react-flow__edge:focus,.react-flow__edge:focus-visible{outline:none}.react-flow__edge.selected .react-flow__edge-path,.react-flow__edge.selectable:focus .react-flow__edge-path,.react-flow__edge.selectable:focus-visible .react-flow__edge-path{stroke:var(--xy-edge-stroke-selected, var(--xy-edge-stroke-selected-default))}.react-flow__edge-textwrapper{pointer-events:all}.react-flow__edge .react-flow__edge-text{pointer-events:none;-webkit-user-select:none;-moz-user-select:none;user-select:none}.react-flow__arrowhead polyline{stroke:var(--xy-edge-stroke, var(--xy-edge-stroke-default))}.react-flow__arrowhead polyline.arrowclosed{fill:var(--xy-edge-stroke, var(--xy-edge-stroke-default))}.react-flow__connection{pointer-events:none}.react-flow__connection .animated{stroke-dasharray:5;animation:dashdraw .5s linear infinite}svg.react-flow__connectionline{z-index:1001;overflow:visible;position:absolute}.react-flow__nodes{pointer-events:none;transform-origin:0 0}.react-flow__node{position:absolute;-webkit-user-select:none;-moz-user-select:none;user-select:none;pointer-events:all;transform-origin:0 0;box-sizing:border-box;cursor:default}.react-flow__node.selectable{cursor:pointer}.react-flow__node.draggable{cursor:grab;pointer-events:all}.react-flow__node.draggable.dragging{cursor:grabbing}.react-flow__nodesselection{z-index:3;transform-origin:left top;pointer-events:none}.react-flow__nodesselection-rect{position:absolute;pointer-events:all;cursor:grab}.react-flow__handle{position:absolute;pointer-events:none;min-width:5px;min-height:5px;width:6px;height:6px;background-color:var(--xy-handle-background-color, var(--xy-handle-background-color-default));border:1px solid var(--xy-handle-border-color, var(--xy-handle-border-color-default));border-radius:100%}.react-flow__handle.connectingfrom{pointer-events:all}.react-flow__handle.connectionindicator{pointer-events:all;cursor:crosshair}.react-flow__handle-bottom{top:auto;left:50%;bottom:0;transform:translate(-50%,50%)}.react-flow__handle-top{top:0;left:50%;transform:translate(-50%,-50%)}.react-flow__handle-left{top:50%;left:0;transform:translate(-50%,-50%)}.react-flow__handle-right{top:50%;right:0;transform:translate(50%,-50%)}.react-flow__edgeupdater{cursor:move;pointer-events:all}.react-flow__pane.selection .react-flow__panel{pointer-events:none}.react-flow__panel{position:absolute;z-index:5;margin:15px}.react-flow__panel.top{top:0}.react-flow__panel.bottom{bottom:0}.react-flow__panel.top.center,.react-flow__panel.bottom.center{left:50%;transform:translate(-15px) translate(-50%)}.react-flow__panel.left{left:0}.react-flow__panel.right{right:0}.react-flow__panel.left.center,.react-flow__panel.right.center{top:50%;transform:translateY(-15px) translateY(-50%)}.react-flow__attribution{font-size:10px;background:var(--xy-attribution-background-color, var(--xy-attribution-background-color-default));padding:2px 3px;margin:0}.react-flow__attribution a{text-decoration:none;color:#999}@keyframes dashdraw{0%{stroke-dashoffset:10}}.react-flow__edgelabel-renderer{position:absolute;width:100%;height:100%;pointer-events:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;left:0;top:0}.react-flow__viewport-portal{position:absolute;width:100%;height:100%;left:0;top:0;-webkit-user-select:none;-moz-user-select:none;user-select:none}.react-flow__minimap{background:var( --xy-minimap-background-color-props, var(--xy-minimap-background-color, var(--xy-minimap-background-color-default)) )}.react-flow__minimap-svg{display:block}.react-flow__minimap-mask{fill:var( --xy-minimap-mask-background-color-props, var(--xy-minimap-mask-background-color, var(--xy-minimap-mask-background-color-default)) );stroke:var( --xy-minimap-mask-stroke-color-props, var(--xy-minimap-mask-stroke-color, var(--xy-minimap-mask-stroke-color-default)) );stroke-width:var( --xy-minimap-mask-stroke-width-props, var(--xy-minimap-mask-stroke-width, var(--xy-minimap-mask-stroke-width-default)) )}.react-flow__minimap-node{fill:var( --xy-minimap-node-background-color-props, var(--xy-minimap-node-background-color, var(--xy-minimap-node-background-color-default)) );stroke:var( --xy-minimap-node-stroke-color-props, var(--xy-minimap-node-stroke-color, var(--xy-minimap-node-stroke-color-default)) );stroke-width:var( --xy-minimap-node-stroke-width-props, var(--xy-minimap-node-stroke-width, var(--xy-minimap-node-stroke-width-default)) )}.react-flow__background-pattern.dots{fill:var( --xy-background-pattern-color-props, var(--xy-background-pattern-color, var(--xy-background-pattern-dots-color-default)) )}.react-flow__background-pattern.lines{stroke:var( --xy-background-pattern-color-props, var(--xy-background-pattern-color, var(--xy-background-pattern-lines-color-default)) )}.react-flow__background-pattern.cross{stroke:var( --xy-background-pattern-color-props, var(--xy-background-pattern-color, var(--xy-background-pattern-cross-color-default)) )}.react-flow__controls{display:flex;flex-direction:column;box-shadow:var(--xy-controls-box-shadow, var(--xy-controls-box-shadow-default))}.react-flow__controls.horizontal{flex-direction:row}.react-flow__controls-button{display:flex;justify-content:center;align-items:center;height:26px;width:26px;padding:4px;border:none;background:var(--xy-controls-button-background-color, var(--xy-controls-button-background-color-default));border-bottom:1px solid var( --xy-controls-button-border-color-props, var(--xy-controls-button-border-color, var(--xy-controls-button-border-color-default)) );color:var( --xy-controls-button-color-props, var(--xy-controls-button-color, var(--xy-controls-button-color-default)) );cursor:pointer;-webkit-user-select:none;-moz-user-select:none;user-select:none}.react-flow__controls-button svg{width:100%;max-width:12px;max-height:12px;fill:currentColor}.react-flow__edge.updating .react-flow__edge-path{stroke:#777}.react-flow__edge-text{font-size:10px}.react-flow__node.selectable:focus,.react-flow__node.selectable:focus-visible{outline:none}.react-flow__node-input,.react-flow__node-default,.react-flow__node-output,.react-flow__node-group{padding:10px;border-radius:var(--xy-node-border-radius, var(--xy-node-border-radius-default));width:150px;font-size:12px;color:var(--xy-node-color, var(--xy-node-color-default));text-align:center;border:var(--xy-node-border, var(--xy-node-border-default));background-color:var(--xy-node-background-color, var(--xy-node-background-color-default))}.react-flow__node-input.selectable:hover,.react-flow__node-default.selectable:hover,.react-flow__node-output.selectable:hover,.react-flow__node-group.selectable:hover{box-shadow:var(--xy-node-boxshadow-hover, var(--xy-node-boxshadow-hover-default))}.react-flow__node-input.selectable.selected,.react-flow__node-input.selectable:focus,.react-flow__node-input.selectable:focus-visible,.react-flow__node-default.selectable.selected,.react-flow__node-default.selectable:focus,.react-flow__node-default.selectable:focus-visible,.react-flow__node-output.selectable.selected,.react-flow__node-output.selectable:focus,.react-flow__node-output.selectable:focus-visible,.react-flow__node-group.selectable.selected,.react-flow__node-group.selectable:focus,.react-flow__node-group.selectable:focus-visible{box-shadow:var(--xy-node-boxshadow-selected, var(--xy-node-boxshadow-selected-default))}.react-flow__node-group{background-color:var(--xy-node-group-background-color, var(--xy-node-group-background-color-default))}.react-flow__nodesselection-rect,.react-flow__selection{background:var(--xy-selection-background-color, var(--xy-selection-background-color-default));border:var(--xy-selection-border, var(--xy-selection-border-default))}.react-flow__nodesselection-rect:focus,.react-flow__nodesselection-rect:focus-visible,.react-flow__selection:focus,.react-flow__selection:focus-visible{outline:none}.react-flow__controls-button:hover{background:var( --xy-controls-button-background-color-hover-props, var(--xy-controls-button-background-color-hover, var(--xy-controls-button-background-color-hover-default)) );color:var( --xy-controls-button-color-hover-props, var(--xy-controls-button-color-hover, var(--xy-controls-button-color-hover-default)) )}.react-flow__controls-button:disabled{pointer-events:none}.react-flow__controls-button:disabled svg{fill-opacity:.4}.react-flow__controls-button:last-child{border-bottom:none}.react-flow__controls.horizontal .react-flow__controls-button{border-bottom:none;border-right:1px solid var( --xy-controls-button-border-color-props, var(--xy-controls-button-border-color, var(--xy-controls-button-border-color-default)) )}.react-flow__controls.horizontal .react-flow__controls-button:last-child{border-right:none}.react-flow__resize-control{position:absolute}.react-flow__resize-control.left,.react-flow__resize-control.right{cursor:ew-resize}.react-flow__resize-control.top,.react-flow__resize-control.bottom{cursor:ns-resize}.react-flow__resize-control.top.left,.react-flow__resize-control.bottom.right{cursor:nwse-resize}.react-flow__resize-control.bottom.left,.react-flow__resize-control.top.right{cursor:nesw-resize}.react-flow__resize-control.handle{width:5px;height:5px;border:1px solid #fff;border-radius:1px;background-color:var(--xy-resize-background-color, var(--xy-resize-background-color-default));translate:-50% -50%}.react-flow__resize-control.handle.left{left:0;top:50%}.react-flow__resize-control.handle.right{left:100%;top:50%}.react-flow__resize-control.handle.top{left:50%;top:0}.react-flow__resize-control.handle.bottom{left:50%;top:100%}.react-flow__resize-control.handle.top.left,.react-flow__resize-control.handle.bottom.left{left:0}.react-flow__resize-control.handle.top.right,.react-flow__resize-control.handle.bottom.right{left:100%}.react-flow__resize-control.line{border-color:var(--xy-resize-background-color, var(--xy-resize-background-color-default));border-width:0;border-style:solid}.react-flow__resize-control.line.left,.react-flow__resize-control.line.right{width:1px;transform:translate(-50%);top:0;height:100%}.react-flow__resize-control.line.left{left:0;border-left-width:1px}.react-flow__resize-control.line.right{left:100%;border-right-width:1px}.react-flow__resize-control.line.top,.react-flow__resize-control.line.bottom{height:1px;transform:translateY(-50%);left:0;width:100%}.react-flow__resize-control.line.top{top:0;border-top-width:1px}.react-flow__resize-control.line.bottom{border-bottom-width:1px;top:100%}.react-flow__edge-textbg{fill:var(--xy-edge-label-background-color, var(--xy-edge-label-background-color-default))}.react-flow__edge-text{fill:var(--xy-edge-label-color, var(--xy-edge-label-color-default))}
@@ -0,0 +1,13 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Dreative</title>
7
+ <script type="module" crossorigin src="/assets/index--vztc_MR.js"></script>
8
+ <link rel="stylesheet" crossorigin href="/assets/index-y0gVjC7u.css">
9
+ </head>
10
+ <body>
11
+ <div id="root"></div>
12
+ </body>
13
+ </html>
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "dreative",
3
+ "version": "0.1.0",
4
+ "description": "Layout-first visual editor skill for coding CLIs: extract your app's UI into editable wireframes, tweak with drag-drop + ref images, then the agent applies the diff back to your code.",
5
+ "type": "module",
6
+ "bin": {
7
+ "dreative": "dist/cli/index.js"
8
+ },
9
+ "files": [
10
+ "dist",
11
+ "skill"
12
+ ],
13
+ "scripts": {
14
+ "build": "npm run build:server && npm run build:ui",
15
+ "prepublishOnly": "npm run build",
16
+ "build:server": "tsc -p tsconfig.json",
17
+ "build:ui": "vite build",
18
+ "dev": "concurrently \"tsx watch src/cli/index.ts --no-open\" \"vite\"",
19
+ "start": "node dist/cli/index.js"
20
+ },
21
+ "dependencies": {
22
+ "esbuild": "^0.24.0",
23
+ "express": "^4.21.0",
24
+ "open": "^10.1.0",
25
+ "react": "^18.3.1",
26
+ "react-dom": "^18.3.1"
27
+ },
28
+ "devDependencies": {
29
+ "@dnd-kit/core": "^6.3.1",
30
+ "@dnd-kit/sortable": "^10.0.0",
31
+ "@dnd-kit/utilities": "^3.2.2",
32
+ "@types/express": "^4.17.21",
33
+ "@types/node": "^22.0.0",
34
+ "@types/react": "^18.3.0",
35
+ "@types/react-dom": "^18.3.0",
36
+ "@vitejs/plugin-react": "^4.3.0",
37
+ "@xyflow/react": "^12.3.0",
38
+ "concurrently": "^9.0.0",
39
+ "tsx": "^4.19.0",
40
+ "typescript": "^5.6.0",
41
+ "vite": "^5.4.0",
42
+ "zustand": "^5.0.0"
43
+ }
44
+ }
@@ -0,0 +1,358 @@
1
+ # Dreative Design Doctrine
2
+
3
+ You MUST read this file before servicing any `propose-skeletons`, `propose-variants`,
4
+ `design-page`, or `edit-element` request, and run ยง12 before every respond. It exists
5
+ because LLM-designed UIs converge on one templated look. Every rule corrects a known
6
+ model default; none is a suggestion. Requests may carry a `plan` (Dreative's
7
+ pre-computed decision: dials, per-section layout families, budgets, lints) โ€” execute
8
+ the plan, apply this doctrine to everything the plan doesn't specify. When
9
+ `plan.skills` names specialist skills (`motion`, `3d`, `interaction`), the matching
10
+ `skills/<name>.md` files extend this doctrine for that request โ€” read them first;
11
+ where they go deeper than a section here, they win.
12
+
13
+ ## 1. Register: the first decision
14
+
15
+ Every page is one of two registers. Misclassifying it is the biggest single error.
16
+
17
+ **BRAND** (design IS the product): landing pages, marketing, portfolios, campaign
18
+ pages, about pages, long-form content. Bar = distinctiveness. A visitor should ask
19
+ "how was this made?", not "which AI made this?". Average is no longer findable;
20
+ restraint without intent reads as mediocre. Go big or go home.
21
+
22
+ **PRODUCT** (design SERVES the product): app UI, dashboards, settings, tables, tools,
23
+ authenticated surfaces. Bar = earned familiarity. Would a user fluent in Linear,
24
+ Figma, Notion, Stripe trust this instantly, or pause at every subtly-off component?
25
+ Failure mode is not flatness, it is strangeness without purpose. The tool should
26
+ disappear into the task.
27
+
28
+ Pick by the page's job, not the project. One app can hold both registers.
29
+
30
+ ## 2. The design read and the slop tests
31
+
32
+ Before generating, state a one-line read: "<page kind> for <audience>, <vibe>
33
+ language, leaning <aesthetic family>". If the request carries a `brief`, obey it โ€”
34
+ it is the user's explicit direction.
35
+
36
+ Then run three tests on your intended output; restart if any fails:
37
+
38
+ 1. **First-order reflex**: could someone guess your palette + theme from the category
39
+ alone ("cookware โ†’ cream + brass", "devtool โ†’ dark + mono")? That's the
40
+ training-data default. Rework. The three most-shipped default aesthetics: warm
41
+ cream + high-contrast serif + terracotta accent; near-black + acid-green/vermilion;
42
+ broadsheet hairline-rules-and-columns. Where the brief leaves an axis free, never
43
+ spend that freedom on one of these.
44
+ 2. **Second-order reflex**: could someone guess it from category + anti-reference
45
+ ("fintech that's not navy โ†’ terminal-dark", "SaaS that's not cream โ†’ editorial
46
+ serif + mono labels")? The trap one tier deeper. Rework again.
47
+ 3. **Competitor sentence**: describe what you're about to build as a competitor would
48
+ describe theirs. If the sentence fits the modal page in the category, restart.
49
+
50
+ ### The working process: commit before code
51
+
52
+ Never design by accretion. Two passes:
53
+
54
+ 1. **Commit** โ€” before any code, write a compact spec: 4-6 named colors (hex/OKLCH),
55
+ 2+ type roles with actual font names, a one-sentence layout description per
56
+ section, and ONE **signature element** โ€” the single memorable move (an
57
+ interaction, a typographic device, a composition) that carries the page's
58
+ distinctiveness. Spend your boldness there; keep everything around it disciplined
59
+ and quiet. Ground choices in the subject's world: its materials, instruments,
60
+ artifacts, and vernacular ("a coffee brand's world: burlap, roast curves,
61
+ thermometers, cupping notes") โ€” not in web-design tropes.
62
+ 2. **Review** โ€” test the spec against the slop tests below. If any part could apply
63
+ to any similar project, revise that part. Only then build.
64
+
65
+ **Hero thesis:** open with the most characteristic thing in the subject's world โ€”
66
+ a headline, an image, a live demo, an interactive moment. Whatever form fits.
67
+
68
+ ### Aesthetic presets (brief.aesthetic)
69
+
70
+ - `minimal` โ€” Linear-clean: restrained neutrals, one accent, generous space.
71
+ - `editorial` โ€” magazine: strong type hierarchy, asymmetric grid, real imagery.
72
+ NOTE: editorial is ONE lane, not the default "tasteful" answer. The
73
+ serif-italic + mono-labels + ruled-columns look is now saturated AI grammar.
74
+ - `premium` โ€” confident type, rich imagery, refined motion, zero clutter.
75
+ - `playful` โ€” bold committed color, springy motion, asymmetry, still disciplined.
76
+ - `brutalist` โ€” raw 1px borders, mono, flat color, radius 0, no shadows/gradients.
77
+ - `dark-tech` โ€” off-black surfaces, restrained neon, terminal cues used sparingly.
78
+ - `trust` โ€” public-sector/regulated: symmetric, motion โ‰ค2, maximum legibility.
79
+
80
+ ### The three dials (1-10, resolved in `plan.dials`)
81
+
82
+ - `variance` โ€” 1 symmetry โ†’ 10 masonry/offsets/20vw empty zones. >4 forbids the
83
+ centered-hero default. Any asymmetry collapses to clean single-column < 768px.
84
+ - `motion` โ€” 1 static โ†’ 10 scroll choreography. >3 requires reduced-motion fallbacks.
85
+ - `density` โ€” 1 art-gallery (py-32+) โ†’ 10 cockpit (hairlines, tabular-nums, no cards).
86
+
87
+ ## 3. Typography
88
+
89
+ **Font selection procedure (brand register, never skip):**
90
+ 1. Write three physical-object brand-voice words ("warm, mechanical, opinionated" โ€”
91
+ never "modern" or "elegant").
92
+ 2. List the three fonts you'd reach for by reflex. Reject any on the ban list below.
93
+ 3. Pick for the brand as a physical object (museum caption, 1970s terminal manual,
94
+ concert poster, mid-century receipt). Reject the first thing that "looks designy".
95
+ 4. If the final pick matches the original reflex, start over.
96
+
97
+ **Reflex-reject fonts (training-data defaults, banned as defaults):** Fraunces,
98
+ Newsreader, Lora, Crimson (all), Playfair Display, Cormorant (all), Syne, IBM Plex
99
+ (all), Space Mono, Space Grotesk, Inter, DM Sans/Serif, Outfit, Plus Jakarta Sans,
100
+ Instrument Sans/Serif. Inter/system stacks ARE legitimate in the product register
101
+ and for trust briefs. When an existing app already uses one, identity-preservation
102
+ wins โ€” keep it.
103
+
104
+ **Serif discipline:** "creative/premium brief = serif" is the most-tested AI tell.
105
+ Default is sans display. Serif only when the brief is genuinely editorial/luxury/
106
+ publication AND you can articulate why this serif fits this brand. Emphasis inside a
107
+ headline = italic/bold of the SAME family, never a serif word dropped into a sans
108
+ headline. Italic display words with descenders (y g j p q) need `leading-[1.1]`+ and
109
+ bottom padding reserve.
110
+
111
+ **Scale โ€” pick by register:**
112
+ - Brand: fluid `clamp()` headings, ratio โ‰ฅ1.25 between steps, clamp max โ‰ค 6rem and
113
+ โ‰ค 2.5ร— its min. Display tracking floor โˆ’0.04em (tighter = letters touch).
114
+ - Product: fixed rem scale, ratio 1.125โ€“1.2, one family in 3-4 weights is usually
115
+ right. No fluid type in app UI โ€” no major design system uses it.
116
+ - Both: body โ‰ฅ 16px and fixed; 45โ€“75ch measure (`max-width: 65ch`); headings
117
+ `text-wrap: balance`, prose `text-wrap: pretty`; โ‰ค 2-3 families total; never pair
118
+ two similar sans โ€” contrast on a real axis (serif+sans, geometric+humanist) or use
119
+ one family.
120
+
121
+ **Details that read as craft:** line-height 1.1โ€“1.2 headings, 1.5โ€“1.7 body; ALL-CAPS
122
+ labels get `letter-spacing: 0.05โ€“0.12em`; `tabular-nums` on data columns; vertical
123
+ rhythm = spacing in multiples of the body line-box (16px ร— 1.5 โ†’ 24px grid);
124
+ light-on-dark text compensates on three axes: +0.05โ€“0.1 line-height, +0.01โ€“0.02em
125
+ tracking, one weight step down (400โ†’350 effect). `font-display: swap`, preload only
126
+ the critical weight, variable font when using 3+ weights.
127
+
128
+ ## 4. Color
129
+
130
+ **Use OKLCH.** `oklch(L C H)` is perceptually uniform. Build ramps by holding
131
+ chroma+hue and varying lightness; reduce chroma near white/black. The hue is a brand
132
+ decision โ€” never blue-250 or warm-60 by reflex.
133
+
134
+ **Pick a color strategy before picking colors:**
135
+ - **Restrained** โ€” tinted neutrals + one accent โ‰ค10% visual weight. Product floor.
136
+ - **Committed** โ€” one saturated color carries 30-60% of the surface. Brand default
137
+ for identity-driven pages.
138
+ - **Full palette** โ€” 3-4 named roles used deliberately. Campaigns, data viz.
139
+ - **Drenched** โ€” the surface IS the color. Brand heroes.
140
+
141
+ Name a real reference before committing ("Stripe purple-on-white restraint", "Klim
142
+ #ff4500 drench", "Vercel pure-black monochrome"). Unnamed ambition becomes beige.
143
+ On brand surfaces, palette IS voice โ€” don't hedge a Committed palette with neutral
144
+ edges. On product surfaces, accent = primary action + selection + state, never
145
+ decoration, with a full semantic state vocabulary (hover/focus/active/disabled/
146
+ selected/loading/error/warning/success/info) and a second neutral layer for
147
+ sidebars/panels.
148
+
149
+ **Mechanics:**
150
+ - Tinted neutrals: chroma 0.005โ€“0.015 toward THIS brand's hue. Pure gray is dead;
151
+ reflex-warm or reflex-cool tinting is the monoculture move.
152
+ - 60-30-10 by visual weight: 60% neutral surface, 30% text/borders, 10% accent.
153
+ Accents work because they are rare.
154
+ - One accent, one neutral family, locked page-wide and project-wide. No blue CTA
155
+ appearing in section 7 of a warm-gray page.
156
+ - Contrast: body 4.5:1 (AAA 7:1 target for hero copy), large text 3:1, UI components
157
+ 3:1, placeholders 4.5:1. Gray text on colored backgrounds looks washed out โ€” use a
158
+ darker shade of the background's own hue or alpha of the text color. Audit every
159
+ CTA and form before responding.
160
+ - No pure #000/#fff. Dark mode is not inverted light mode: depth from a 3-step
161
+ surface-lightness scale (โ‰ˆ15/20/25% L, brand hue, chroma constant), desaturate
162
+ accents slightly, reduce body weight. Redefine only semantic tokens for dark.
163
+ - Heavy alpha usage = incomplete palette. Define explicit overlay colors.
164
+
165
+ **Banned palettes as default reaches:** AI-purple/violet gradients + glow; the
166
+ premium-artisan cream/sand/beige bg (#f5f1ea family, OKLCH L .84-.97 C<.06 hue
167
+ 40-100) + brass/clay/oxblood accents + espresso text โ€” token names like --cream,
168
+ --sand, --bone are tells in themselves. Alternatives to rotate: cold luxury
169
+ (silver/chrome/smoke), forest + bone + amber, true black + tan, cobalt + cream,
170
+ terracotta + slate, olive + brick + paper, monochrome + one saturated pop. "Warmth"
171
+ is carried by accent, type, and imagery โ€” not by a beige body background.
172
+ Override: a palette is fine when the existing brand or explicit brief names it.
173
+ When redesigning an extracted app, its `theme` colors are the brand โ€” preserve.
174
+
175
+ ## 5. Layout
176
+
177
+ **Hard rules (failing any = broken work):**
178
+ - Hero fits the initial viewport: headline โ‰ค 2 lines, subtext โ‰ค 20 words, CTA visible
179
+ without scroll, top padding โ‰ค pt-24. 4-line headline is a font-size error. Max 4
180
+ text elements (one eyebrow OR brand strip, headline, subtext, CTAs 1+1). Trust
181
+ strips, pricing teasers, feature bullets, avatar rows: all move below the hero.
182
+ - Hero needs a real visual. Text + gradient blob is a placeholder, not a hero.
183
+ - variance > 4 forbids centered-hero-over-gradient: split 50/50, left-content/
184
+ right-asset, or asymmetric whitespace. Centered is fine for manifesto/launch copy.
185
+ - Nav: one line at desktop, height 64โ€“72px (cap 80px).
186
+ - A layout family appears at most ONCE per page; 8 sections need โ‰ฅ 4 families. Max 2
187
+ consecutive image+text zigzags. No 3-identical-cards row, ever โ€” asymmetric grid,
188
+ 2-col, bento, or horizontal scroll instead.
189
+ - Bento: exactly as many cells as content (no filler tiles); 2-3 cells carry real
190
+ visual variation (image/tint/pattern), never all white-on-white text.
191
+ - Cards only when elevation = hierarchy; otherwise border-t/divide-y/whitespace.
192
+ Nested cards are always wrong. Tint shadows to the background hue.
193
+ - Lists > 5 items: group into chunks, 2-col card grid, tabs, or marquee โ€” never one
194
+ hairline-divided stack, never border-t AND border-b per row.
195
+ - Split-header pattern (big left headline + small floating right paragraph) banned
196
+ as default; stack vertically at 65ch.
197
+ - Grid over flex-math (`grid-cols-3 gap-6`, never `w-[calc(33%-1rem)]`);
198
+ `repeat(auto-fit, minmax(280px, 1fr))` for breakpoint-free card grids;
199
+ `min-h-[100dvh]` never `h-screen`; explicit mobile collapse per section; contain
200
+ at `max-w-7xl mx-auto`; semantic z-index scale, no z-[999].
201
+ - ONE radius system: all-sharp, all-soft (12-16px), or documented mixed rule
202
+ ("buttons pill, cards 16, inputs 8"). Cards never above 16px radius.
203
+ - Spacing has rhythm: vary generous separations against tight groupings on a
204
+ consistent base unit; brand surfaces use fluid `clamp()` spacing that breathes.
205
+ - Structure encodes truth, never decoration: numbering, eyebrows, dividers, and
206
+ labels appear only when they say something true about the content (a real
207
+ sequence, a real category). If removing the device loses nothing, remove it.
208
+ - Product register: responsive behavior is structural (collapse sidebar, responsive
209
+ table), not fluid type.
210
+
211
+ ## 6. Motion
212
+
213
+ Every animation answers "what does this communicate?" โ€” hierarchy, storytelling,
214
+ feedback, or state change. "It looked cool" = delete it.
215
+
216
+ **The 100/300/500 rule:** 100-150ms instant feedback (press, toggle) ยท 200-300ms
217
+ state changes (menu, tooltip, hover) ยท 300-500ms layout changes (accordion, modal)
218
+ ยท 500-800ms entrances (hero reveal, brand only). Exits run ~75% of enter duration.
219
+ Feedback over 500ms feels laggy. Micro-interactions target the 80ms "feels instant"
220
+ threshold.
221
+
222
+ **Easing:** ease-out exponential only โ€” `cubic-bezier(0.25,1,0.5,1)` quart,
223
+ `cubic-bezier(0.22,1,0.36,1)` quint, `cubic-bezier(0.16,1,0.3,1)` expo. Bounce and
224
+ elastic are dated; banned.
225
+
226
+ **Register:** brand = one well-orchestrated hero entrance beats scattered
227
+ micro-interactions; the uniform fade-and-rise on every scrolled section is the
228
+ saturated AI tell. Some brands skip entrance motion entirely โ€” restraint as voice.
229
+ Product = 150-250ms, state-conveying only, zero page-load choreography.
230
+
231
+ **Mechanics:** animate transform/opacity by default; blur/backdrop-filter/clip-path/
232
+ masks/shadow allowed when they materially improve the effect, bounded to small areas,
233
+ verified smooth. Never casually animate width/height/top/left/margins (use FLIP or
234
+ grid-template-rows). Sibling stagger `calc(var(--i) * 50ms)` capped at ~500ms total.
235
+ IntersectionObserver (unobserve after firing), CSS scroll-driven animations, or
236
+ Motion/GSAP scroll tools โ€” `window.addEventListener("scroll")` is a hard ban. Reveals
237
+ enhance an already-visible default; never gate content visibility on a JS-triggered
238
+ class (hidden tabs and headless renderers ship blank sections). Max one marquee per
239
+ page. `prefers-reduced-motion: reduce` alternative for everything. Optimistic UI for
240
+ low-stakes actions; never for payments or destructive ops.
241
+
242
+ ## 7. Imagery
243
+
244
+ When the brief implies imagery (restaurant, hotel, product, travel, fashion,
245
+ portfolio), zero images is a bug, not restraint. Even a minimalist page needs 2-3
246
+ real images. Priority: (1) image-gen tool if available in your environment, at the
247
+ section's aspect ratio; (2) real photography โ€”
248
+ `https://picsum.photos/seed/<descriptive-seed>/<w>/<h>` always resolves; Unsplash
249
+ only with verified photo IDs (guessed IDs 404 into broken placeholders); (3)
250
+ clearly-labeled placeholder slots + tell the user what's needed. Search for the
251
+ brand's physical object ("hand-cut pasta on a scratched wooden table"), not the
252
+ category ("Italian food"). One decisive photo beats five mediocre ones. Alt text
253
+ carries voice.
254
+
255
+ Banned: div-built fake screenshots/terminals/dashboards (the #1 AI tell), hand-drawn
256
+ "sketchy" SVG illustrations, `feTurbulence` paper-grain, repeating-gradient stripe
257
+ backgrounds, decorative grid-line overlays, hand-rolled icon paths. Icons from ONE
258
+ library (Phosphor/Radix/Tabler/HugeIcons; Lucide only on request), one strokeWidth
259
+ globally. Logo walls: real SVG marks (`https://cdn.simpleicons.org/<slug>`) or
260
+ generated monograms โ€” logos only, no category captions, below the hero.
261
+
262
+ ## 8. Content and copy
263
+
264
+ โ‰ค 8-word section headlines, โ‰ค 25-word subtext, one copy register per page, quotes
265
+ โ‰ค 3 lines with name + role attribution. No filler verbs (elevate, seamless, unleash,
266
+ revolutionize). No fake-precise numbers unless real or labeled mock; use believable
267
+ messy data ("47.2%", not "99.99%"). No "Jane Doe"/"Acme"/generic avatars โ€” realistic
268
+ locale-appropriate names, credible invented brands. Re-read every visible string
269
+ before responding; rewrite anything grammatically broken, cutely meta, or
270
+ performative-craftsman ("From the field", "We respect the French ones"). Plain
271
+ beats clever. Data-dump tables on marketing pages โ†’ top 3-5 + "view all".
272
+
273
+ **UX writing:** write from the user's side of the screen โ€” name things by what
274
+ people control and recognize, never by how the system is built. Active voice ("Save
275
+ changes", not "Submit"). Action names stay consistent through the flow (button
276
+ "Publish" โ†’ toast "Published"). Errors and empty states are direction, not mood:
277
+ say what happened and what to do next; never apologize vaguely. Sentence case,
278
+ plain verbs, no filler.
279
+
280
+ ## 9. States and interaction (product floor)
281
+
282
+ Every interactive component ships default/hover/focus/active/disabled/loading/error.
283
+ Skeletons shaped like the final layout, not centered spinners. Empty states teach
284
+ the interface. Errors inline for forms, toasts only for transient events. Labels
285
+ above inputs; placeholder-as-label never; helper text present. `:active` gives
286
+ tactile press (`scale-[0.98]`). Same button shape, form vocabulary, and icon style
287
+ on every screen โ€” if "save" looks different in two places, one is wrong. Modals are
288
+ usually laziness; exhaust inline/progressive first. Dropdowns escape
289
+ overflow-hidden ancestors via popover API/position-fixed/portal. Touch targets
290
+ โ‰ฅ 44px. Never disable zoom.
291
+
292
+ ## 10. Banned AI tells (match-and-refuse)
293
+
294
+ - **Em-dash (โ€”) and en-dash separators (โ€“): zero anywhere visible.** Periods,
295
+ commas, colons, plain hyphens.
296
+ - Eyebrow kickers (small caps tracked labels above headings) on every section โ€” max
297
+ 1 per 3 sections, and only as a deliberate system. Numbered section markers
298
+ (`01 ยท About`) unless the content is a real sequence.
299
+ - Side-stripe borders (border-left > 1px as accent) โ€” full hairline border, 4-8%
300
+ background tint, or leading glyph instead.
301
+ - Gradient text (background-clip). Glassmorphism as default. Hero-metric template
302
+ (big number + label + gradient accent). Identical icon+heading+text card grids.
303
+ - 1px border + soft โ‰ฅ16px drop shadow on the same element ("ghost card") โ€” pick one.
304
+ - Hero version labels (BETA, V0.6), scroll cues ("โ†“ scroll to explore"),
305
+ locale/weather strips, decoration strips (`DESIGN ยท BUILD ยท SHIP`), vertical
306
+ rotated text, custom cursors, decorative status dots, pills overlaid on photos,
307
+ fake photo credits, version footers on marketing pages, "Quietly trusted by".
308
+ - Duplicate CTA intent: one label per intent per page ("Get in touch" + "Let's
309
+ talk" = fail). CTA labels never wrap at desktop; 1-3 words.
310
+ - Middle-dot separators rationed to 1 per line. Never hover-scale on `<img>`
311
+ elements (animate the card's border/background/shadow instead).
312
+ - Headline text that overflows its container at any breakpoint โ€” test the actual
313
+ copy; the viewport is part of the design.
314
+
315
+ ## 11. Redesign and preservation (extracted apps)
316
+
317
+ Dreative pages usually come FROM a real app. Detect the mode: preserve (evolve the
318
+ existing brand) vs overhaul (new language, same content/IA). When preserving: keep
319
+ route slugs, nav labels, form field names, logo, legal copy; extract brand tokens
320
+ before applying ยง4 (a purple brand stays purple); apply modernisation levers in
321
+ order โ€” typography โ†’ spacing/rhythm โ†’ color recalibration โ†’ motion layer โ†’ hero
322
+ recomposition โ†’ full replacement only when unsalvageable. Honor existing
323
+ accessibility wins and analytics hooks. Preserve prior element-level edits when
324
+ `previousFile` is set.
325
+
326
+ ## 12. Pre-flight checklist (run before EVERY respond)
327
+
328
+ Mentally verify; fix failures, then respond. If a box cannot be honestly ticked,
329
+ the output is not done.
330
+
331
+ 0. Commit pass done: named palette, named fonts, one signature element, subject-
332
+ grounded. The quality floor (responsive to mobile, visible keyboard focus,
333
+ reduced motion) is built silently โ€” never announced in copy or comments.
334
+ 1. Register named (brand/product); design read stated; brief and plan obeyed.
335
+ 2. All three slop tests pass (first-order, second-order, competitor sentence).
336
+ 3. Zero em/en-dashes visible. Zero banned tells from ยง10.
337
+ 4. One accent + one tinted-neutral family + one theme + one radius system + one
338
+ icon family, locked page-wide; matches sibling pages of this project.
339
+ 5. Fonts: not on the reflex-reject list (or justified by existing brand); scale
340
+ ratio committed; body โ‰ฅ16px at 45-75ch; caps tracked; data tabular.
341
+ 6. Every CTA/form/placeholder passes WCAG AA; no CTA wraps; no duplicate CTA intent.
342
+ 7. Hero: โ‰ค2-line headline, โ‰ค20-word subtext, โ‰ค4 elements, real visual, CTA above
343
+ fold; centered only if variance โ‰ค 4 or manifesto brief.
344
+ 8. Eyebrows โ‰ค ceil(sections/3); no two sections share a layout family; โ‰ค2
345
+ consecutive zigzags; no 3-identical-cards; bento cells = content count.
346
+ 9. Real images or labeled slots; no div fake-screenshots; no sketchy SVG; logos are
347
+ real marks.
348
+ 10. Motion: each animation justified in one sentence; durations per 100/300/500;
349
+ ease-out curves; exits faster; reduced-motion safe; content visible without JS;
350
+ โ‰ค1 marquee; no scroll-listener.
351
+ 11. States complete (loading/empty/error/disabled); labels above inputs; tactile
352
+ :active.
353
+ 12. Mobile collapse explicit; 100dvh; no text overflow at any breakpoint; semantic
354
+ z-index.
355
+ 13. Copy self-audit done: no broken/AI-cute strings, realistic data, one register.
356
+ 14. Every block id from the layout appears as `data-dreative-id` (design-page only).
357
+ 15. Dark mode (when in scope): semantic-token swap, surface-lightness depth,
358
+ desaturated accents, tested both modes.
@@ -0,0 +1,108 @@
1
+ ---
2
+ name: dreative
3
+ description: Frontend design skill + optional visual round-trip editor. Use for ANY frontend design work โ€” redesign/restyle/build pages, landing pages, animations, motion, 3D, micro-interactions, "make my UI look good" โ€” and for visual editing when the user says "open dreative" or "let me edit the layout visually". Default is direct design: apply the design doctrine straight to the codebase. The browser editor (extract โ†’ wireframes โ†’ edit โ†’ apply diff) is an optional mode the user can ask for.
4
+ ---
5
+
6
+ # Dreative โ€” frontend design skill (+ optional visual editor)
7
+
8
+ You (the coding agent) are the intelligence. Dreative has **two modes**:
9
+
10
+ - **Mode A โ€” Direct design (default).** The user asks you to design, redesign, restyle, animate, or build UI. Read `DESIGN.md` (and any specialist `skills/<name>.md` the work calls for โ€” motion, 3d, interaction), then design/edit the real code directly. No server, no extraction, no wireframes. When you finish, add one closing note: *"Tip: run `dreative start` / say 'open dreative' if you want to tweak this visually โ€” I'll extract the pages into an editable canvas."* That's the only place the editor should come up; never force the round-trip on a plain design request.
11
+ - **Mode B โ€” Visual round-trip (only when asked).** The user explicitly wants the visual editor ("open dreative", "let me edit visually"). Flow: **extract โ†’ baseline โ†’ serve requests โ†’ finish โ†’ apply**. Be token-frugal at every step: read only the files you need, never re-read the whole app, and keep JSON compact.
12
+
13
+ Everything below ยง0 describes Mode B; the design doctrine paragraphs apply to both modes.
14
+
15
+ **Design quality is a hard requirement.** `DESIGN.md` (same folder as this file) is the design doctrine. Read it ONCE before servicing the first `propose-skeletons`, `propose-variants`, `design-page`, or `edit-element` request, keep it in mind for all later ones, and run its pre-flight checklist (ยง12) before every respond. Requests may carry a `brief` object (aesthetic preset + vibe + dials set by the user in the UI); when present it is the user's explicit direction and overrides doctrine defaults. Before writing any `design-page` code, state (to yourself, one line) the register, the design read, and the signature element โ€” if you cannot name all three, you are about to produce the generic default; stop and commit first.
16
+
17
+ **Specialist skills.** The `skills/` folder next to this file holds expert playbooks for advanced work: `motion.md` (animation & scroll choreography), `3d.md` (WebGL/three.js/shaders), `interaction.md` (micro-interactions & effect craft). When a request's `plan.skills` lists names, read each listed `skills/<name>.md` ONCE before writing code (then keep it in mind, like DESIGN.md); when `plan.sections[].skills` tags a section, that section gets that treatment (e.g. "this hero has 3d"). If the brief/prompt clearly calls for one of these but the plan missed it, read it anyway. If a listed file isn't installed, proceed on DESIGN.md alone and note it to the user (`dreative install-skill` installs all).
18
+
19
+ ## 0. Setup
20
+
21
+ Requires `dreative` on PATH (`npm i -g dreative` or `npx dreative`). All commands run from the user's project root. State lives in `.dreative/` (paths in payloads are relative to `.dreative/`).
22
+
23
+ ## 1. Extract (code โ†’ layout + replica)
24
+
25
+ Goal: replicate the app's current UI **view-by-view** so the user recognizes every screen. Do this **one page at a time** โ€” find the routes/pages first (router config, pages/ dir, app/ dir), then open only each page's component files. **Single pass per page:** while the source is in front of you, produce all three outputs at once (layout JSON, replica file, summaries) โ€” never revisit a file for a second output.
26
+
27
+ **One Dreative page per VIEW, not per route file.** If a route renders mutually-exclusive views โ€” tab panels, admin vs viewer modes, auth states, wizard steps, a modal that fills the screen โ€” each view becomes its own Dreative page. A page's layout must show exactly what the user sees at one moment; never stack multiple tab panels' content into one layout. Name split views `"<Screen> โ€” <View>"` (e.g. "Admin Studio โ€” Library", "Admin Studio โ€” Ranking Board"), give them the same `source`, the same `group` (e.g. `"group": "Admin Studio"`), and cluster them on the canvas. Shared chrome (header, tab bar) repeats in each view's layout, with the active tab noted in its `text`.
28
+
29
+ **Expose hidden UI.** UI that exists but isn't visible by default must still surface, or the user gets a wrong picture of their app:
30
+ - *Full-screen or view-sized* hidden UI (modals, dialogs, drawers, overlay panels with real content) โ†’ its own Dreative page, grouped with its parent screen (e.g. "Library โ€” Edit Show modal").
31
+ - *Small* hidden UI (dropdown menus, tooltips-with-actions, hover-revealed buttons, expandable rows) โ†’ model it as a block **inside its trigger's parent**, labeled for what it is (e.g. label "Sort dropdown (opens on click)"), with a `summary` saying when it appears. Don't invent open-state visuals in the replica โ€” the replica shows the default state; the layout is where hidden things are enumerated.
32
+
33
+ **Fidelity is the whole point.** The wireframe and replica must be recognizable as *that* page at a glance. Model every visible major section in order โ€” hero/banner, search+filter bars, stat/KPI rows, each shelf/carousel with its cards, footers. A real page with 8 visible sections must yield ~8 top-level children, not 3 generic boxes. Card grids get realistic counts (a shelf showing 7 posters โ†’ a card-grid the user reads as a row of posters, with real show titles in `text`). Before moving on, self-check: *would the user, seeing only this wireframe, name which page of their app it is?* If not, you under-extracted โ€” fix it before the next page.
34
+
35
+ Per page, produce:
36
+
37
+ 1. **Layout** โ€” the block tree in `project.json` (schema below).
38
+ 2. **Replica** โ€” `.dreative/replica/<pageId>.tsx`: a stripped, non-functional **1:1 visual copy** of the real page. Single file, default export, no imports beyond react, Tailwind classes (translate other styling to Tailwind or inline styles). Strip everything behavioral: no handlers, no hooks, no data fetching; replace dynamic state/props with representative literal values (the ones a real user would see). It only needs to LOOK identical, not work. Every block id from the layout appears as `data-dreative-id="<id>"` on the matching element. Set `replicaFile` on the page.
39
+ 3. **Summaries** โ€” on each meaningful block, `summary`: one plain line of what it shows or does ("Submits the signup form and redirects to /dashboard", "Lists the 6 most recent orders from the API"). These render as hover tooltips in the replica so the user understands behavior without you re-reading code later, and they are your own re-entry notes at apply time. Keep each under ~120 chars.
40
+
41
+ Write `.dreative/project.json`:
42
+
43
+ ```json
44
+ { "version": 1, "brief": { "aesthetic": "minimal", "vibe": "", "audience": "", "variance": 7, "motion": 5, "density": 4, "notes": "" }, "pages": [ {
45
+ "id": "pg_home", "name": "Home", "canvasPos": {"x": 40, "y": 40},
46
+ "theme": { "bg": "#0d0d0f", "fg": "#e8e8ea", "accent": "#f59e0b" },
47
+ "status": "skeleton", "source": "src/pages/Home.tsx",
48
+ "layout": { "id": "blk_root", "type": "section", "label": "Home", "direction": "column", "children": [ โ€ฆ ] }
49
+ } ] }
50
+ ```
51
+
52
+ (page objects also take `"replicaFile": "replica/pg_home.tsx"` and `"group": "Admin Studio"` for split views of one screen)
53
+
54
+ Block: `{ id, type, label, text?, summary?, direction?, sizeHint?, source?, children? }`
55
+ - `type`: section | row | column | nav | hero | card-grid | list | form | footer | text | image | button
56
+ - `label`: short recognizable name (shown on hover/inspector).
57
+ - `text`: the **actual visible copy** (heading text, button caption, first ~80 chars of a paragraph) โ€” set it on every text/button/hero leaf; it renders verbatim in the wireframe so the user recognizes the page.
58
+ - Page `theme` `{bg, fg, accent}`: pull the real CSS colors (page background, main text color, brand accent) so the wireframe card matches the app's look. Set it on every page.
59
+ - `source`: the real file that owns this block (component path). Set it on every block whose owner differs from its parent's โ€” this is what lets you apply the diff later without re-searching.
60
+ - Keep depth sensible (3โ€“5 levels); every meaningful visible element should exist, but don't model every span.
61
+ - Ids must be unique and stable; prefix `pg_`/`blk_` plus a slug.
62
+ - Space pages on the canvas: x += 480 per page.
63
+ - Top-level `brief` is optional at extraction time (the user edits it in the UI); if the app has an obvious existing aesthetic, seed it so redesigns preserve the brand.
64
+
65
+ Then snapshot the baseline: `dreative baseline` (start the server first, step 2, if not running).
66
+
67
+ ## 2. Launch
68
+
69
+ ```
70
+ dreative start # serves http://localhost:4820, opens browser (background this)
71
+ ```
72
+
73
+ Tell the user the UI is open: they can view the **Replica** tab (1:1 copy of their real page, hover shows your summaries), drag elements in **Layout**, add/remove blocks, set the **Design brief** (preset + dials), attach reference images and prompts, hit **๐ŸŽจ Design all**, and click **Finish** when done.
74
+
75
+ ## 3. Service requests (the wait loop)
76
+
77
+ Repeat until finish:
78
+
79
+ ```
80
+ dreative wait # blocks up to ~8 min; prints ONE event as JSON
81
+ ```
82
+
83
+ - `{"kind":"none"}` โ†’ just run `dreative wait` again.
84
+ - `{"kind":"request","id","type","payload"}` โ†’ handle per table below, then
85
+ `dreative respond <id> <resultFile>` (write the result JSON to a temp file) or `dreative respond <id> --error "why"`.
86
+ - `{"kind":"finish","diff":โ€ฆ}` โ†’ go to step 4.
87
+
88
+ | type | payload | result to respond with |
89
+ |---|---|---|
90
+ | `propose-skeletons` | `{prompt, brief?}` | Array of 1โ€“3 `{name, layout}` page proposals (block schema above), structured per DESIGN.md layout rules |
91
+ | `propose-variants` | `{pageName, layout, brief?}` | Array of 1โ€“3 `{name, layout}` variants |
92
+ | `edit-block` | `{block, instruction}` | The updated block JSON (same id) |
93
+ | `design-page` | `{pageName, layout, brief?, plan?, refImage?, blockRefs, designPrompt?, previousFile?, siblingPages, outFile}` | Write a single-file React+Tailwind component (default export, no imports beyond react) to `.dreative/<outFile>`; every block id in layout must appear as `data-dreative-id="<id>"`. **`plan` is Dreative's pre-computed design decision โ€” execute it, don't re-decide:** it carries resolved dials, a layout family per section (`plan.sections`, sections may carry `skills` tags like `["3d"]`), spacing/motion budgets (`plan.directives`), doctrine violations to fix (`plan.lints`), and required specialist skills (`plan.skills` โ†’ read `skills/<name>.md` first). DESIGN.md still governs everything the plan doesn't specify. Read `refImage`/`blockRefs[].refImage` (paths under `.dreative/`) with your image tools; if `previousFile` set, read it and preserve prior element edits. Respond `{"ok":true}` |
94
+ | `edit-element` | `{file, elementId, instruction, refImage?}` | Edit `.dreative/<file>` in place, only the element with `data-dreative-id=elementId`, keeping DESIGN.md rules intact. Respond `{"ok":true}` |
95
+
96
+ A "Design all pages" click in the UI arrives as one `design-page` request per page, back to back: keep visual consistency across them (same accent, type scale, radius system โ€” the first page you design sets the system for the rest).
97
+
98
+ Token rules: only read ref images when a request names them; never dump whole files into responses; for edits, edit files directly instead of returning code.
99
+
100
+ ## 4. Apply (finish)
101
+
102
+ The finish event's `diff` (also saved at `.dreative/finish.json`) contains only what changed vs the baseline:
103
+
104
+ - `pagesAdded` โ€” full layouts; create real pages/components for them.
105
+ - `pagesRemoved` โ€” confirm with the user before deleting real code.
106
+ - `pagesChanged` โ€” per page: `blocksMoved` (reorder in the source), `blocksAdded`, `blocksRemoved`, `blocksChanged` (only differing props listed; `refImage` = style reference to match, `intents` = behavior notes), plus page-level `refImage`/`designPrompt`.
107
+
108
+ Use each block's/page's `source` pointer to open **only the owning files**, and each block's `summary` to recall what an element does **without re-reading unrelated code**. Read annotated ref images now (paths relative to `.dreative/`). Make the real code match the final layout and annotations, run the project's checks, and summarize what you changed.