PluginProbe
ZIP AI – AI Website Builder & AI Agent (Beta) / 0.0.4
ZIP AI – AI Website Builder & AI Agent (Beta) v0.0.4
0.0.10 0.0.9 trunk 0.0.4 0.0.5 0.0.6 0.0.7 0.0.8
zip-ai / src / styles / main.css

main.css in ZIP AI – AI Website Builder & AI Agent (Beta) 0.0.4, at src/styles/main.css

884 lines 23.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 @tailwind base;
2 @tailwind components;
3 @tailwind utilities;
4
5 /* ── Spectra-style purple theme (shadcn HSL tokens) + legacy aliases ── */
6 @layer base {
7 /* Light — Era design tokens (bundle: era.html) */
8 #chat-assistant-root {
9 --background: 0 0% 98%; /* --bg-app #FAFAFA */
10 --foreground: 240 7% 4%; /* --ink-1 #0A0A0C */
11 --card: 0 0% 100%; /* --bg-panel */
12 --card-foreground: 240 7% 4%;
13 --popover: 0 0% 100%;
14 --popover-foreground: 240 7% 4%;
15 --primary: 250 91% 60%; /* --accent #5B3DF5 */
16 --primary-foreground: 0 0% 100%;
17 --secondary: 240 4% 97%; /* --bg-sunken #F7F7F8 */
18 --secondary-foreground: 240 3% 17%; /* --ink-2 #2A2A2E */
19 --muted: 240 4% 97%;
20 --muted-foreground: 240 4% 38%; /* --ink-3 #5E5E66 */
21 --accent: 250 100% 97%; /* --accent-soft #F2EFFF */
22 --accent-foreground: 251 76% 51%; /* --accent-ink #4A2EDB */
23 --destructive: 5 75% 56%; /* --stop #E24C3B */
24 --destructive-foreground: 0 0% 100%;
25 --border: 240 5% 93%; /* --line #EDEDEF */
26 --input: 240 5% 93%;
27 --ring: 250 91% 60%;
28 --radius: 0.625rem;
29 /* Era extra tokens */
30 --ink-2: 240 3% 17%;
31 --ink-4: 234 5% 57%; /* #8E8E96 */
32 --ink-5: 235 6% 73%; /* #B5B5BC */
33 --line-2: 240 5% 89%; /* #E0E0E3 */
34 --line-3: 240 4% 82%; /* #CECED2 */
35 --bg-sunken: 240 4% 97%;
36 --ok: 146 75% 36%; /* #17A05B */
37 --ok-soft: 144 47% 93%; /* #E8F6EE */
38 --warn: 34 90% 41%; /* #C77A0A */
39 --warn-soft: 40 84% 94%; /* #FBF2E1 */
40 --accent-50: 248 100% 98%; /* #F7F5FF */
41 --chart-1: 12 76% 61%;
42 --chart-2: 173 58% 39%;
43 --chart-3: 197 37% 24%;
44 --chart-4: 43 74% 66%;
45 --chart-5: 27 87% 67%;
46
47 /* Legacy semantic tokens (markdown, inline styles, older components) */
48 --color-heading: hsl(var(--foreground));
49 --color-body: hsl(var(--foreground));
50 --color-medium: hsl(var(--muted-foreground));
51 --color-muted: hsl(var(--muted-foreground));
52 --color-faint: hsl(var(--muted-foreground));
53 --color-brand: hsl(var(--primary));
54 --color-brand-hover: hsl(262.1 83.3% 52%);
55 --color-brand-dark: hsl(262.1 83.3% 44%);
56 --color-surface: hsl(var(--background));
57 --color-surface-secondary: hsl(var(--muted));
58 --color-surface-hover: hsl(var(--accent));
59 --color-border-main: hsl(var(--border));
60 --color-border-light: hsl(var(--border));
61 --color-glass-border: hsl(var(--border) / 0.45);
62 --font-mono: "JetBrains Mono", "Fira Code", Consolas, monospace;
63 --font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen,
64 Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
65 --radius-sm: 6px;
66 --radius-md: 8px;
67 --radius-lg: 10px;
68 --radius-xl: 12px;
69 --radius-2xl: 16px;
70 --color-surface-active: hsl(var(--accent));
71 --color-surface-blue: hsl(var(--primary) / 0.1);
72 /* Legacy — prefer border + bg-card / bg-primary in components */
73 --shadow-bubble-user: none;
74 --shadow-bubble-assistant: none;
75 }
76
77 /* Dark — Era tokens (elevated ink-1 + accent with contrast lift) */
78 #chat-assistant-root.dark {
79 --background: 240 6% 9%;
80 --foreground: 240 5% 92%;
81 --card: 240 5% 12%;
82 --card-foreground: 240 5% 92%;
83 --popover: 240 5% 13%;
84 --popover-foreground: 240 5% 92%;
85 --primary: 250 85% 70%;
86 --primary-foreground: 0 0% 100%;
87 --secondary: 240 5% 15%;
88 --secondary-foreground: 240 5% 85%;
89 --muted: 240 5% 15%;
90 --muted-foreground: 240 4% 55%;
91 --accent: 250 30% 22%;
92 --accent-foreground: 250 100% 85%;
93 --destructive: 5 70% 58%;
94 --destructive-foreground: 0 0% 100%;
95 --border: 240 5% 18%;
96 --input: 240 5% 18%;
97 --ring: 250 85% 70%;
98 --ink-2: 240 5% 85%;
99 --ink-4: 240 4% 55%;
100 --ink-5: 240 4% 40%;
101 --line-2: 240 5% 22%;
102 --line-3: 240 5% 28%;
103 --bg-sunken: 240 5% 12%;
104 --ok: 146 60% 50%;
105 --ok-soft: 146 40% 16%;
106 --warn: 34 85% 58%;
107 --warn-soft: 34 45% 18%;
108 --accent-50: 250 25% 15%;
109 --chart-1: 220 70% 50%;
110 --chart-2: 160 60% 45%;
111 --chart-3: 30 80% 55%;
112 --chart-4: 280 65% 60%;
113 --chart-5: 340 75% 55%;
114 }
115 }
116
117 #chat-assistant-root [data-message-list] {
118 scrollbar-width: thin;
119 scrollbar-color: hsl(var(--muted-foreground) / 0.35) transparent;
120 overflow-anchor: auto;
121 }
122
123 /* Native browser scroll anchoring — pin only the chosen anchor element. */
124 #chat-assistant-root [data-message-list] [data-msg-role] {
125 overflow-anchor: none;
126 }
127 #chat-assistant-root [data-message-list] [data-msg-role][data-anchor="true"] {
128 overflow-anchor: auto;
129 scroll-margin-top: 16px;
130 }
131
132 /* ── Keyframe animations (minimal) ── */
133 @keyframes spin {
134 to {
135 transform: rotate(360deg);
136 }
137 }
138
139 @keyframes fadeIn {
140 from {
141 opacity: 0;
142 }
143 to {
144 opacity: 1;
145 }
146 }
147
148 @keyframes dotPulse {
149 0%,
150 80%,
151 100% {
152 opacity: 0.25;
153 transform: scale(0.7);
154 }
155 40% {
156 opacity: 1;
157 transform: scale(1.1);
158 }
159 }
160
161 /* ── Spinner classes ── */
162 .spinner {
163 width: 24px;
164 height: 24px;
165 border: 3px solid hsl(var(--line-2));
166 border-top-color: hsl(var(--foreground));
167 border-radius: 50%;
168 animation: spin 0.8s linear infinite;
169 }
170
171 .spinner-small {
172 width: 16px;
173 height: 16px;
174 border: 2px solid hsl(var(--line-2));
175 border-top-color: hsl(var(--foreground));
176 border-radius: 50%;
177 animation: spin 0.8s linear infinite;
178 }
179
180 .spinner-tiny {
181 width: 12px;
182 height: 12px;
183 border: 2px solid hsl(var(--line-2));
184 border-top-color: hsl(var(--foreground));
185 border-radius: 50%;
186 animation: spin 0.8s linear infinite;
187 }
188
189 /* ── Scoped base styles (inside #chat-assistant-root only) ── */
190 .sr-only {
191 position: absolute;
192 width: 1px;
193 height: 1px;
194 padding: 0;
195 margin: -1px;
196 overflow: hidden;
197 clip: rect(0, 0, 0, 0);
198 white-space: nowrap;
199 border: 0;
200 }
201
202 /* ── Root container reset ── */
203 #chat-assistant-root {
204 /* Isolate from WP admin styles without using `all: initial`
205 which breaks Tailwind utility specificity on child elements */
206 position: absolute;
207 inset: 0;
208 overflow: hidden;
209 background-color: hsl(var(--background));
210 font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen,
211 Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
212 font-size: 14px;
213 line-height: 1.5;
214 -webkit-font-smoothing: antialiased;
215 -moz-osx-font-smoothing: grayscale;
216 color: hsl(var(--foreground));
217 box-sizing: border-box;
218 /* Reset common inherited WP admin styles */
219 text-align: left;
220 letter-spacing: normal;
221 word-spacing: normal;
222 text-transform: none;
223 text-indent: 0;
224 text-decoration: none;
225 direction: ltr;
226
227 /* Scoped preflight — replaces @import "tailwindcss/preflight" which leaks globally.
228 Uses :where() for zero specificity so Tailwind utility classes always win. */
229 & :where(*),
230 & :where(::before, ::after) {
231 box-sizing: border-box;
232 margin: 0;
233 padding: 0;
234 border: 0 solid;
235 }
236
237 & :where(h1, h2, h3, h4, h5, h6) {
238 font-size: inherit;
239 font-weight: inherit;
240 line-height: inherit;
241 }
242
243 & :where(a) {
244 color: inherit;
245 text-decoration: inherit;
246 }
247
248 & :where(img, svg, video, canvas) {
249 display: block;
250 max-width: 100%;
251 height: auto;
252 }
253
254 & :where(button) {
255 font-family: inherit;
256 font-size: inherit;
257 line-height: inherit;
258 color: inherit;
259 cursor: pointer;
260 background: transparent;
261 border: none;
262 }
263
264 & :where(input, textarea, select) {
265 font-family: inherit;
266 font-size: inherit;
267 line-height: inherit;
268 color: inherit;
269 background: transparent;
270 }
271
272 & :where(ul, ol) {
273 list-style: none;
274 padding: 0;
275 margin: 0;
276 }
277
278 & :where(table) {
279 border-collapse: collapse;
280 }
281 }
282
283 /* ── Frontend theme isolation ──
284 On the frontend, theme stylesheets often target plain element selectors
285 (e.g. `body p { font-family: ... }`, `body { font-size: 18px }`) which beat
286 the zero-specificity `:where()` preflight and the inherited root rules.
287 Force every descendant of `#chat-assistant-root` to inherit typography from
288 the root so theme rules can't leak in. Tailwind utilities (`.font-mono`,
289 `.text-sm`, etc.) keep higher specificity (class beats `*`), so they still
290 override these baselines where needed. */
291 #chat-assistant-root * {
292 font-family: inherit;
293 font-size: inherit;
294 line-height: inherit;
295 letter-spacing: inherit;
296 }
297
298 /* ── Tooltip system (data-attribute based, needs global CSS) ── */
299 [data-tooltip] {
300 position: relative;
301
302 &::after {
303 content: attr(data-tooltip);
304 position: absolute;
305 bottom: calc(100% + 8px);
306 left: 50%;
307 transform: translateX(-50%) scale(0.9);
308 padding: 5px 10px;
309 background: hsl(var(--foreground));
310 color: hsl(var(--background));
311 font-size: 11px;
312 font-weight: 500;
313 line-height: 1.3;
314 white-space: nowrap;
315 border-radius: var(--radius-md);
316 pointer-events: none;
317 opacity: 0;
318 transition:
319 opacity 0.15s ease,
320 transform 0.15s ease;
321 z-index: 100001;
322 }
323
324 &::before {
325 content: "";
326 position: absolute;
327 bottom: calc(100% + 2px);
328 left: 50%;
329 transform: translateX(-50%) scale(0.9);
330 border: 5px solid transparent;
331 border-top-color: hsl(var(--foreground));
332 pointer-events: none;
333 opacity: 0;
334 transition:
335 opacity 0.15s ease,
336 transform 0.15s ease;
337 z-index: 100001;
338 }
339
340 &:hover::after,
341 &:hover::before {
342 opacity: 1;
343 transform: translateX(-50%) scale(1);
344 }
345 }
346
347 [data-tooltip-pos="below"] {
348 &::after {
349 bottom: auto;
350 top: calc(100% + 8px);
351 }
352 &::before {
353 bottom: auto;
354 top: calc(100% + -2px);
355 border-top-color: transparent;
356 border-bottom-color: var(--color-heading);
357 }
358 }
359
360 [data-tooltip-pos="left"] {
361 &::after {
362 bottom: auto;
363 top: 50%;
364 left: auto;
365 right: calc(100% + 10px);
366 transform: translateY(-50%) scale(0.9);
367 }
368 &::before {
369 bottom: auto;
370 top: 50%;
371 left: auto;
372 right: calc(100% + 0px);
373 transform: translateY(-50%) scale(0.9);
374 border-top-color: transparent;
375 border-left-color: var(--color-heading);
376 }
377 &:hover::after,
378 &:hover::before {
379 transform: translateY(-50%) scale(1);
380 }
381 }
382
383 [data-tooltip-pos="right"] {
384 &::after {
385 bottom: auto;
386 top: 50%;
387 left: calc(100% + 10px);
388 right: auto;
389 transform: translateY(-50%) scale(0.9);
390 }
391 &::before {
392 bottom: auto;
393 top: 50%;
394 left: calc(100% + 0px);
395 right: auto;
396 transform: translateY(-50%) scale(0.9);
397 border-top-color: transparent;
398 border-right-color: var(--color-heading);
399 }
400 &:hover::after,
401 &:hover::before {
402 transform: translateY(-50%) scale(1);
403 }
404 }
405
406 /* ── Message markdown styles now handled by SmartMarkdown.jsx (Tailwind) ── */
407
408 /* ── Message fade-in ── */
409 @keyframes msg-in {
410 from {
411 opacity: 0;
412 transform: translateY(6px);
413 }
414 to {
415 opacity: 1;
416 transform: translateY(0);
417 }
418 }
419 .animate-msg-in {
420 animation: msg-in 0.25s ease-out both;
421 }
422
423 /* ── Tool calls summary — SSE-driven choreography ── */
424 @keyframes tool-row-in {
425 from {
426 opacity: 0;
427 transform: translateX(-6px);
428 filter: blur(2px);
429 }
430 to {
431 opacity: 1;
432 transform: translateX(0);
433 filter: blur(0);
434 }
435 }
436
437 .animate-tool-row-in {
438 animation: tool-row-in 0.32s cubic-bezier(0.22, 1, 0.36, 1) both;
439 }
440
441 /* Respect reduced-motion: skip row entrance + stagger transitions */
442 @media (prefers-reduced-motion: reduce) {
443 .animate-tool-row-in {
444 animation: none;
445 }
446 }
447
448 /* ── Resize handle states (outside #chat-assistant-root, needs plain CSS) ── */
449 .zip-ai-resize-handle .resize-dots {
450 opacity: 0;
451 }
452 .zip-ai-resize-handle:hover {
453 background-color: hsl(262.1 83.3% 57.8% / 0.12);
454 }
455 .zip-ai-resize-handle:hover .resize-dots,
456 .zip-ai-resize-handle.dragging .resize-dots {
457 opacity: 1;
458 }
459 .zip-ai-resize-handle.dragging {
460 background-color: hsl(262.1 83.3% 57.8% / 0.22);
461 }
462
463 /* ══════════════════════════════════════════════════════════════════
464 WP DOM targeting styles — these MUST be global CSS because they
465 style WordPress elements (body, admin bar, block editor) that
466 live outside the React app. Toggled by vanilla JS in wp-bridge-host.js.
467 ══════════════════════════════════════════════════════════════════ */
468
469 :root {
470 --zip-ai-sidebar-width: 550px;
471 }
472
473 /* ── Full-page assistant admin screen ──────────────────────────────────── */
474
475 /* Strip WP admin content-area chrome so chat can go edge-to-edge */
476 body.zip-ai-fullpage-page #wpcontent {
477 padding-left: 0 !important;
478 }
479
480 body.zip-ai-fullpage-page #wpbody-content {
481 padding-top: 0 !important;
482 padding-bottom: 0 !important;
483 }
484
485 /* Hide WP footer version text on the fullpage assistant screen */
486 body.zip-ai-fullpage-page #wpfooter {
487 display: none !important;
488 }
489
490 /* Hide all WP admin notices on the fullpage assistant screen */
491 body.zip-ai-fullpage-page .notice,
492 body.zip-ai-fullpage-page .error,
493 body.zip-ai-fullpage-page .updated,
494 body.zip-ai-fullpage-page .update-nag,
495 body.zip-ai-fullpage-page .wp-header-end ~ .notice,
496 body.zip-ai-fullpage-page #wpbody-content > .notice,
497 body.zip-ai-fullpage-page #wpbody-content > .error,
498 body.zip-ai-fullpage-page #wpbody-content > .updated {
499 display: none !important;
500 }
501
502 /* Outer screen wrapper — fills available viewport below the admin bar */
503 .zip-ai-fullpage-screen {
504 margin: 0;
505 padding: 0;
506 height: calc(100vh - 32px); /* 32px = WP admin bar height */
507 overflow: hidden;
508 }
509
510 /* Without admin bar (e.g. ?noheader or custom screens) */
511 body:not(.admin-bar) .zip-ai-fullpage-screen {
512 height: 100vh;
513 }
514
515 /* Inner container: fills the screen wrapper, no radius at this level */
516 .zip-ai-fullpage-container {
517 position: relative;
518 height: 100%;
519 min-height: 480px;
520 border-radius: 0;
521 overflow: hidden;
522 background: transparent;
523 padding: 0;
524 }
525
526 /* Hide trigger when sidebar is open (trigger is React portal on body) */
527 body.zip-ai-assistant-open .zip-ai-floating-trigger {
528 opacity: 0;
529 visibility: hidden;
530 pointer-events: none;
531 transform: scale(0.5);
532 transition:
533 transform 0.2s ease,
534 opacity 0.2s ease,
535 visibility 0s 0.2s;
536 }
537
538 /* Sidebar container (PHP-rendered, toggled by vanilla JS) */
539 .zip-ai-panel-container {
540 position: fixed;
541 right: calc(-1 * var(--zip-ai-sidebar-width));
542 /* Hidden by default, slides in from right */
543 top: 32px;
544 /* WordPress admin bar height */
545 width: var(--zip-ai-sidebar-width);
546 height: calc(100vh - 32px);
547 background: white;
548 box-shadow: -2px 0 10px rgba(0, 0, 0, 0.1);
549 z-index: 99999;
550 display: flex;
551 flex-direction: column;
552 transition:
553 right 0.3s ease-in-out,
554 width 0.05s ease-out;
555 visibility: hidden;
556 /* Hide when off-screen */
557 opacity: 0;
558 }
559
560 /* Visible state - slide in */
561 .zip-ai-panel-container.zip-ai-panel-visible {
562 right: 0;
563 visibility: visible;
564 opacity: 1;
565 transition:
566 right 0.3s ease-in-out,
567 opacity 0.3s ease-in-out;
568 }
569
570 /* Push WordPress content to the left when assistant is open */
571 /* Default: no margin (hidden state) */
572 body {
573 margin-right: 0;
574 transition: margin-right 0.3s ease-in-out;
575 }
576
577 body.zip-ai-assistant-open {
578 margin-right: var(--zip-ai-sidebar-width);
579 overflow-x: clip;
580 width: calc(100vw - var(--zip-ai-sidebar-width));
581 }
582
583 /* Fix for alignfull blocks - recalculate width accounting for assistant panel */
584 /* These blocks use calc(-50vw + 50%) which doesn't account for body margin */
585 body.zip-ai-assistant-open .alignfull,
586 body.zip-ai-assistant-open .uagb-is-root-container.alignfull,
587 body.zip-ai-assistant-open .spectra-is-root-container.alignfull,
588 body.zip-ai-assistant-open .wp-block-uagb-container.alignfull,
589 body.zip-ai-assistant-open .wp-block-spectra-container.alignfull,
590 body.zip-ai-assistant-open .wp-block-cover.alignfull,
591 body.zip-ai-assistant-open .wp-block-group.alignfull {
592 width: 100% !important;
593 max-width: 100% !important;
594 margin-left: 0 !important;
595 margin-right: 0 !important;
596 }
597
598 /* Astra theme header - constrain to available width */
599 body.zip-ai-assistant-open .site-header,
600 body.zip-ai-assistant-open .ast-primary-header-bar,
601 body.zip-ai-assistant-open .ast-main-header-wrap,
602 body.zip-ai-assistant-open .site-primary-header-wrap {
603 max-width: 100% !important;
604 width: 100% !important;
605 }
606
607 /* Main content containers */
608 body.zip-ai-assistant-open #page,
609 body.zip-ai-assistant-open .site,
610 body.zip-ai-assistant-open #content,
611 body.zip-ai-assistant-open .site-content,
612 body.zip-ai-assistant-open .ast-container {
613 max-width: 100% !important;
614 overflow-x: clip !important;
615 }
616
617 /* Also transition the admin bar */
618 #wpadminbar {
619 right: 0;
620 transition: right 0.3s ease-in-out;
621 }
622
623 body.zip-ai-assistant-open #wpadminbar {
624 right: var(--zip-ai-sidebar-width);
625 }
626
627 /* Adjust for frontend (no admin bar) */
628 body:not(.admin-bar) .zip-ai-panel-container {
629 top: 0;
630 height: 100vh;
631 }
632
633 /* Block Editor (Gutenberg) specific adjustments */
634 /* Always apply transition to skeleton, not just when open */
635 .block-editor-page .interface-interface-skeleton,
636 .edit-post .interface-interface-skeleton,
637 body.block-editor-page .interface-interface-skeleton {
638 margin-right: 0;
639 transition: margin-right 0.3s ease-in-out;
640 }
641
642 /* Apply margin when assistant is open */
643 .block-editor-page body.zip-ai-assistant-open .interface-interface-skeleton,
644 .edit-post body.zip-ai-assistant-open .interface-interface-skeleton,
645 body.block-editor-page.zip-ai-assistant-open .interface-interface-skeleton {
646 margin-right: var(--zip-ai-sidebar-width);
647 }
648
649 /* Reset body margin in block editor (let skeleton handle it) */
650 .block-editor-page body.zip-ai-assistant-open,
651 .edit-post body.zip-ai-assistant-open,
652 body.block-editor-page.zip-ai-assistant-open {
653 margin-right: 0 !important;
654 }
655
656 /* Adjust editor content area */
657 .block-editor-page .interface-interface-skeleton__content,
658 .edit-post .interface-interface-skeleton__content {
659 transition: margin-right 0.3s ease-in-out;
660 }
661
662 /* Full height iframe in block editor */
663 .block-editor-page .zip-ai-panel-container,
664 .edit-post .zip-ai-panel-container,
665 body.block-editor-page .zip-ai-panel-container {
666 top: 0;
667 height: 100vh;
668 }
669
670 /* Post-publish panel — shift left so it doesn't hide under chat sidebar.
671 Gutenberg slides `.editor-post-publish-panel` in from viewport right.
672 In some versions it's portal'd to body (position: fixed; right: 0), so the
673 skeleton's margin-right doesn't push it. Only applies in sidebar mode —
674 popover mode is a floating card that doesn't occupy the full right edge. */
675 body.zip-ai-assistant-open:not(.zip-ai-popover-mode)
676 .editor-post-publish-panel {
677 right: var(--zip-ai-sidebar-width) !important;
678 transition: right 0.3s ease-in-out;
679 }
680
681 /* ── Popover / Floating card mode (see src/styles/popover.css) ────────────── */
682 @import "./popover.css";
683
684 /* Prevent text selection during resize */
685 body.zip-ai-resizing {
686 cursor: ew-resize !important;
687 user-select: none !important;
688 -webkit-user-select: none !important;
689 }
690
691 body.zip-ai-resizing iframe {
692 pointer-events: none;
693 }
694
695 /* Fullscreen mode - iframe takes over entire viewport */
696 .zip-ai-panel-container.zip-ai-panel-fullscreen {
697 width: 100vw !important;
698 height: 100vh !important;
699 top: 0 !important;
700 right: 0 !important;
701 box-shadow: none !important;
702 transition:
703 width 0.4s cubic-bezier(0.16, 1, 0.3, 1),
704 height 0.4s cubic-bezier(0.16, 1, 0.3, 1),
705 top 0.4s cubic-bezier(0.16, 1, 0.3, 1),
706 box-shadow 0.3s ease;
707 }
708
709 /* Hide resize handle in fullscreen */
710 .zip-ai-panel-container.zip-ai-panel-fullscreen .zip-ai-resize-handle {
711 opacity: 0;
712 pointer-events: none;
713 transition: opacity 0.15s ease;
714 }
715
716 /* Smooth exit back to sidebar */
717 .zip-ai-panel-container.zip-ai-panel-visible:not(.zip-ai-panel-fullscreen) {
718 transition:
719 right 0.3s ease-in-out,
720 opacity 0.3s ease-in-out,
721 width 0.35s cubic-bezier(0.33, 1, 0.68, 1),
722 height 0.35s cubic-bezier(0.33, 1, 0.68, 1),
723 top 0.35s cubic-bezier(0.33, 1, 0.68, 1),
724 box-shadow 0.3s ease;
725 }
726
727 /* Remove body margin push in fullscreen */
728 body.zip-ai-assistant-fullscreen,
729 body.zip-ai-panel-fullscreen {
730 margin-right: 0 !important;
731 width: 100vw !important;
732 overflow: hidden;
733 }
734
735 body.zip-ai-assistant-fullscreen #wpadminbar,
736 body.zip-ai-panel-fullscreen #wpadminbar {
737 right: 0 !important;
738 transition: right 0.4s cubic-bezier(0.16, 1, 0.3, 1);
739 }
740
741 /* Block editor: remove skeleton margin in fullscreen */
742 body.zip-ai-assistant-fullscreen .interface-interface-skeleton,
743 body.zip-ai-panel-fullscreen .interface-interface-skeleton {
744 margin-right: 0 !important;
745 transition: margin-right 0.4s cubic-bezier(0.16, 1, 0.3, 1);
746 }
747
748 /* ===== Block Context Picker ===== */
749
750 /* Floating "+" pin button — repositions on hover over blocks */
751 .zip-ai-context-pin {
752 display: none;
753 position: absolute;
754 z-index: 100000;
755 align-items: center;
756 justify-content: center;
757 width: 28px;
758 height: 28px;
759 padding: 0;
760 border: none;
761 border-radius: 12px;
762 background: hsl(262.1 83.3% 57.8%);
763 color: #fff;
764 cursor: pointer;
765 box-shadow: 0 2px 8px hsl(262.1 83.3% 57.8% / 0.35);
766 transition:
767 background-color 0.15s ease,
768 box-shadow 0.15s ease;
769 }
770
771 .zip-ai-context-pin:hover {
772 background: hsl(262.1 83.3% 50%);
773 box-shadow: 0 4px 12px hsl(262.1 83.3% 57.8% / 0.4);
774 }
775
776 .zip-ai-context-pin svg {
777 width: 16px;
778 height: 16px;
779 display: block;
780 pointer-events: none;
781 }
782
783 /* Active state — block already pinned, show checkmark */
784 .zip-ai-context-pin--active {
785 background: #16a34a;
786 }
787
788 .zip-ai-context-pin--active:hover {
789 background: #dc2626;
790 }
791
792 /* Highlight on pinned blocks — uses box-shadow
793 so it doesn't conflict with Gutenberg's outline */
794 .zip-ai-context-selected {
795 box-shadow: 0 0 0 2px hsl(var(--primary, 250 91% 60%)) !important;
796 border-radius: 2px;
797 }
798
799 /* Count badge on ERA FAB button */
800 .zip-ai-context-badge {
801 position: absolute;
802 top: -4px;
803 right: -4px;
804 min-width: 20px;
805 height: 20px;
806 padding: 0 5px;
807 background: #ef4444;
808 color: #fff;
809 font-size: 11px;
810 font-weight: 700;
811 line-height: 20px;
812 text-align: center;
813 border-radius: 10px;
814 pointer-events: none;
815 box-shadow: 0 1px 4px rgba(0, 0, 0, 0.15);
816 font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen,
817 Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
818 }
819
820 /* Mobile responsive */
821 @media (max-width: 768px) {
822 .zip-ai-fullpage-screen.wrap {
823 margin: 8px 10px 0 0;
824 height: calc(100vh - 48px);
825 }
826
827 .zip-ai-fullpage-container {
828 min-height: 520px;
829 border-radius: 16px;
830 }
831
832 .zip-ai-panel-container {
833 width: 100%;
834 max-width: 360px;
835 }
836
837 /* On mobile, use overlay instead of pushing content */
838 body.zip-ai-assistant-open {
839 margin-right: 0;
840 overflow: hidden;
841 /* Prevent scrolling when assistant is open */
842 }
843
844 body.zip-ai-assistant-open #wpadminbar {
845 right: 0;
846 }
847 }
848
849 /* Tablet and larger screens - slightly wider assistant panel */
850 @media (min-width: 1024px) {
851 .zip-ai-panel-container {
852 width: var(--zip-ai-sidebar-width);
853 right: calc(-1 * var(--zip-ai-sidebar-width));
854 /* Keep hidden position in sync with persisted resized widths */
855 }
856
857 .zip-ai-panel-container.zip-ai-panel-visible {
858 right: 0;
859 }
860
861 body.zip-ai-assistant-open {
862 margin-right: var(--zip-ai-sidebar-width);
863 width: calc(100vw - var(--zip-ai-sidebar-width));
864 }
865
866 body.zip-ai-assistant-open #wpadminbar {
867 right: var(--zip-ai-sidebar-width);
868 }
869
870 /* Block editor adjustments for larger screens */
871 .block-editor-page body.zip-ai-assistant-open .interface-interface-skeleton,
872 .edit-post body.zip-ai-assistant-open .interface-interface-skeleton,
873 body.block-editor-page.zip-ai-assistant-open .interface-interface-skeleton {
874 margin-right: var(--zip-ai-sidebar-width);
875 }
876
877 /* Ensure skeleton still has transition on larger screens */
878 .block-editor-page .interface-interface-skeleton,
879 .edit-post .interface-interface-skeleton,
880 body.block-editor-page .interface-interface-skeleton {
881 margin-right: 0;
882 }
883 }
884