gioser-graph: fix edge UUID mapping, index 4 docs, unify page bg
1/* === Tokens === */
2:root {
3 --bg: #06050d;
4 --fg: #e8eaf5;
5 --gold: #d8a85d;
6 --gold-deep: #b77e34;
7 --aire: #d0dbff;
8 --agua: #6cd0f3;
9 --fuego: #f59056;
10 --tierra: #d49873;
11
12 --ease-emerge: cubic-bezier(0.22, 0.61, 0.20, 1);
13 --ease-magma: cubic-bezier(0.32, 0, 0.05, 1);
14 --ease-page: cubic-bezier(0.22, 0.61, 0.36, 1);
15
16 --taskbar-height: 52px;
17}
18
19* { box-sizing: border-box; }
20
21html, body {
22 margin: 0;
23 padding: 0;
24 width: 100%;
25 height: 100%;
26 background: var(--bg);
27 color: var(--fg);
28 font-family: 'Inter', system-ui, -apple-system, sans-serif;
29 font-weight: 300;
30 overflow: hidden;
31}
32
33/* === Canvas WebGL === */
34#gioser-canvas {
35 position: fixed;
36 inset: 0;
37 width: 100vw;
38 height: 100vh;
39 display: block;
40 z-index: 0;
41 transition: opacity 600ms var(--ease-emerge), filter 600ms var(--ease-emerge);
42}
43body.deck-visible #gioser-canvas {
44 opacity: 0.30;
45 filter: blur(4px) saturate(80%);
46}
47
48/* === Tips (botones cardinales sobre el aro) === */
49#tips {
50 position: fixed;
51 inset: 0;
52 pointer-events: none;
53 z-index: 5;
54 transition: opacity 250ms ease;
55}
56body.deck-visible #tips {
57 opacity: 0;
58 pointer-events: none;
59}
60
61.tip {
62 position: absolute;
63 top: 0; left: 0;
64 pointer-events: auto;
65 text-decoration: none;
66 color: var(--fg);
67 user-select: none;
68 cursor: pointer;
69
70 display: flex;
71 flex-direction: column;
72 align-items: center;
73 gap: 0.55rem;
74 padding: 1.1rem 1.6rem 0.95rem;
75 min-width: 168px;
76
77 background:
78 radial-gradient(ellipse at top, rgba(255, 255, 255, 0.04), transparent 65%),
79 rgba(8, 6, 22, 0.55);
80 backdrop-filter: blur(12px) saturate(140%);
81 -webkit-backdrop-filter: blur(12px) saturate(140%);
82 border-radius: 20px;
83 border: 1px solid rgba(216, 168, 93, 0.25);
84
85 box-shadow:
86 0 12px 36px rgba(0, 0, 0, 0.40),
87 inset 0 0 0 1px rgba(255, 255, 255, 0.04);
88
89 transition:
90 box-shadow 350ms var(--ease-emerge),
91 border-color 350ms var(--ease-emerge),
92 background 350ms var(--ease-emerge);
93}
94.tip::before {
95 content: "";
96 position: absolute;
97 inset: -10px;
98 border-radius: 26px;
99 border: 1px solid currentColor;
100 opacity: 0;
101 transition: opacity 400ms ease, inset 400ms var(--ease-emerge);
102 pointer-events: none;
103}
104.tip:hover {
105 border-color: currentColor;
106 background:
107 radial-gradient(ellipse at top, rgba(255, 255, 255, 0.07), transparent 65%),
108 rgba(20, 14, 40, 0.72);
109}
110.tip:hover::before {
111 opacity: 0.45;
112 inset: -16px;
113}
114.tip-glyph {
115 width: 54px;
116 height: 54px;
117 color: currentColor;
118 filter: drop-shadow(0 0 6px currentColor) drop-shadow(0 0 16px currentColor);
119 transition: filter 320ms ease, transform 350ms var(--ease-emerge);
120}
121.tip:hover .tip-glyph {
122 filter: drop-shadow(0 0 14px currentColor) drop-shadow(0 0 28px currentColor);
123 transform: translateY(-3px);
124}
125.tip-label {
126 font-family: 'Cinzel', serif;
127 font-size: 0.95rem;
128 letter-spacing: 0.42em;
129 font-weight: 600;
130 text-indent: 0.42em;
131 margin-top: 0.15rem;
132}
133.tip-sub {
134 font-family: 'Inter', sans-serif;
135 font-size: 0.7rem;
136 letter-spacing: 0.22em;
137 font-weight: 300;
138 color: rgba(232, 234, 245, 0.62);
139 text-transform: uppercase;
140 text-indent: 0.22em;
141}
142.tip-aire { color: var(--aire); }
143.tip-fuego { color: var(--fuego); }
144.tip-agua { color: var(--agua); }
145.tip-tierra { color: var(--tierra); }
146
147/* === DECK: contenedor único de páginas swipeable === */
148.deck {
149 position: fixed;
150 top: 0;
151 left: 0;
152 right: 0;
153 bottom: var(--taskbar-height);
154 z-index: 100;
155 pointer-events: none;
156 opacity: 0;
157 visibility: hidden;
158 transform-origin: var(--origin-x, 50%) var(--origin-y, 50%);
159 transform: scale(0.0);
160 overflow: hidden;
161 touch-action: pan-y;
162 background:
163 radial-gradient(ellipse at center, var(--deck-glow, rgba(216, 168, 93, 0.15)), transparent 65%),
164 rgba(6, 5, 13, 0.96);
165 backdrop-filter: blur(28px) saturate(140%);
166 -webkit-backdrop-filter: blur(28px) saturate(140%);
167 transition:
168 transform 600ms var(--ease-magma),
169 opacity 450ms ease,
170 visibility 0s 600ms;
171}
172.deck.open {
173 pointer-events: auto;
174 opacity: 1;
175 visibility: visible;
176 transform: scale(1);
177 transition:
178 transform 600ms var(--ease-magma),
179 opacity 450ms ease,
180 visibility 0s;
181}
182/* Acento del deck según elemento activo: glow radial del color. */
183body.deck-active-aire .deck { --deck-glow: rgba(208, 219, 255, 0.22); }
184body.deck-active-fuego .deck { --deck-glow: rgba(245, 144, 86, 0.28); }
185body.deck-active-agua .deck { --deck-glow: rgba(108, 208, 243, 0.22); }
186body.deck-active-tierra .deck { --deck-glow: rgba(212, 152, 115, 0.24); }
187
188/* Strip horizontal con páginas — vista-web traslada esto.
189 touch-action: pan-y declara al browser "yo manejo horizontal, el
190 vertical (scroll interno de cada página) lo dejas pasar". Sin esto
191 el navegador móvil se traga el gesto horizontal antes de que JS
192 pueda capturarlo. */
193.deck-strip {
194 display: flex;
195 flex-direction: row;
196 width: 100%;
197 height: 100%;
198 transform: translate3d(var(--vista-offset, 0px), 0, 0);
199 transition: transform 360ms var(--ease-page);
200 will-change: transform;
201 touch-action: pan-y;
202}
203/* Asegurar que TODOS los descendientes del strip hereden el contrato
204 touch-action — si el toque llega a un párrafo o <a>, el browser
205 chequea el touch-action del target, no del padre. */
206.deck-strip * {
207 touch-action: pan-y;
208}
209.deck-strip.vista-dragging,
210.deck-strip.vista-instant {
211 transition: none;
212}
213
214.deck-page {
215 flex: 0 0 100%;
216 width: 100%;
217 height: 100%;
218 position: relative;
219 overflow-y: auto;
220 overflow-x: hidden;
221 touch-action: pan-y;
222}
223.deck-page[data-element="aire"] { --page-accent: var(--aire); }
224.deck-page[data-element="fuego"] { --page-accent: var(--fuego); }
225.deck-page[data-element="agua"] { --page-accent: var(--agua); }
226.deck-page[data-element="tierra"] { --page-accent: var(--tierra); }
227
228/* Ambience por página */
229.page-ambience {
230 position: absolute;
231 inset: 0;
232 pointer-events: none;
233 z-index: 0;
234 transition: opacity 2s ease;
235}
236.deck-page[data-element="aire"] .page-ambience {
237 background: radial-gradient(circle at 50% 60%, rgba(208,219,255,0.18), transparent 70%);
238 animation: page-breathe 8s ease-in-out infinite alternate;
239}
240.deck-page[data-element="fuego"] .page-ambience {
241 background: radial-gradient(circle at 50% 80%, rgba(245,144,86,0.22), transparent 70%);
242 animation: page-breathe 6s ease-in-out infinite alternate;
243}
244.deck-page[data-element="agua"] .page-ambience {
245 background: radial-gradient(circle at 50% 80%, rgba(108,208,243,0.18), transparent 70%);
246 animation: page-breathe 10s ease-in-out infinite alternate;
247}
248.deck-page[data-element="tierra"] .page-ambience {
249 background: radial-gradient(circle at 50% 85%, rgba(140,100,60,0.22), transparent 70%);
250 animation: page-breathe 7s ease-in-out infinite alternate;
251}
252@keyframes page-breathe {
253 from { opacity: 0.35; }
254 to { opacity: 0.80; }
255}
256
257/* Head + controls */
258.page-controls {
259 position: absolute;
260 top: 1.8vh;
261 right: 1.8vw;
262 z-index: 5;
263 display: flex;
264 gap: 0.5rem;
265}
266.page-control-btn {
267 width: 40px;
268 height: 40px;
269 border-radius: 50%;
270 background: rgba(255, 255, 255, 0.04);
271 border: 1px solid rgba(255, 255, 255, 0.18);
272 color: var(--page-accent, var(--gold));
273 font-size: 1.2rem;
274 line-height: 1;
275 cursor: pointer;
276 display: inline-flex;
277 align-items: center;
278 justify-content: center;
279 padding: 0;
280 font-family: 'Inter', sans-serif;
281 transition:
282 background 200ms ease,
283 border-color 200ms ease,
284 transform 250ms var(--ease-emerge);
285}
286.page-control-btn:hover {
287 background: rgba(255, 255, 255, 0.10);
288 border-color: currentColor;
289}
290.page-minimize svg {
291 width: 18px;
292 height: 18px;
293}
294.page-close {
295 font-size: 1.6rem;
296}
297.page-close:hover { transform: rotate(90deg); }
298
299.page-head {
300 position: relative;
301 z-index: 2;
302 text-align: center;
303 padding: 7vh 8vw 2vh;
304 color: var(--page-accent, var(--gold));
305}
306.page-mark {
307 display: inline-block;
308 font-family: 'Inter', sans-serif;
309 font-size: 0.7rem;
310 letter-spacing: 0.55em;
311 text-transform: uppercase;
312 color: rgba(232, 234, 245, 0.6);
313 margin-bottom: 0.4rem;
314 text-indent: 0.55em;
315}
316.page-title {
317 font-family: 'Cinzel', serif;
318 font-weight: 700;
319 font-size: clamp(2.4rem, 6vw, 4.6rem);
320 margin: 0;
321 letter-spacing: 0.08em;
322 color: var(--page-accent, var(--gold));
323 text-shadow: 0 0 28px currentColor, 0 0 56px rgba(255, 255, 255, 0.10);
324}
325.page-tag {
326 display: block;
327 font-family: 'Inter', sans-serif;
328 font-size: 0.78rem;
329 letter-spacing: 0.32em;
330 text-transform: uppercase;
331 color: rgba(232, 234, 245, 0.55);
332 margin-top: 0.7rem;
333 text-indent: 0.32em;
334}
335.page-content {
336 position: relative;
337 z-index: 2;
338 padding: 1vh 10vw 8vh;
339 opacity: 0;
340 transition: opacity 400ms ease 250ms;
341}
342.deck.open .deck-page .page-content {
343 opacity: 1;
344}
345
346/* === pluma-doc dentro de la página === */
347.pluma-doc {
348 max-width: 760px;
349 margin: 0 auto;
350 font-family: 'Inter', sans-serif;
351 font-weight: 300;
352 font-size: 1.05rem;
353 line-height: 1.78;
354 color: rgba(232, 234, 245, 0.92);
355}
356.pluma-doc > * + * { margin-top: 1.0em; }
357.pluma-doc h1 {
358 font-family: 'Cinzel', serif;
359 font-weight: 700;
360 font-size: clamp(1.7rem, 3vw, 2.4rem);
361 color: var(--page-accent);
362 text-shadow: 0 0 18px currentColor;
363 letter-spacing: 0.04em;
364 margin-top: 1.4em;
365}
366.pluma-doc h2 {
367 font-family: 'Cinzel', serif;
368 font-weight: 500;
369 font-size: 1.5rem;
370 color: var(--page-accent);
371 letter-spacing: 0.04em;
372 margin-top: 1.6em;
373 padding-bottom: 0.3em;
374 border-bottom: 1px solid rgba(255, 255, 255, 0.10);
375}
376.pluma-doc h3 {
377 font-family: 'Inter', sans-serif;
378 font-weight: 600;
379 font-size: 1.18rem;
380 color: rgba(255, 255, 255, 0.92);
381 letter-spacing: 0.03em;
382 margin-top: 1.6em;
383}
384.pluma-doc p { margin: 0; }
385.pluma-doc a {
386 color: var(--page-accent);
387 text-decoration: none;
388 border-bottom: 1px solid currentColor;
389 transition: opacity 200ms ease;
390}
391.pluma-doc a:hover { opacity: 0.7; }
392.pluma-doc strong { color: rgba(255, 255, 255, 0.98); font-weight: 600; }
393.pluma-doc em { color: rgba(255, 255, 255, 0.92); }
394.pluma-doc code {
395 font-family: 'JetBrains Mono', ui-monospace, monospace;
396 background: rgba(255, 255, 255, 0.06);
397 padding: 0.12em 0.45em;
398 border-radius: 4px;
399 font-size: 0.92em;
400 color: var(--page-accent);
401}
402.pluma-doc pre {
403 background: rgba(0, 0, 0, 0.45);
404 border: 1px solid rgba(255, 255, 255, 0.08);
405 border-left: 3px solid var(--page-accent);
406 border-radius: 8px;
407 padding: 1rem 1.2rem;
408 overflow-x: auto;
409 font-size: 0.92rem;
410}
411.pluma-doc pre code {
412 background: transparent;
413 color: rgba(232, 234, 245, 0.92);
414 padding: 0;
415}
416.pluma-doc blockquote {
417 border-left: 3px solid var(--page-accent);
418 padding: 0.4em 1.2em;
419 color: rgba(232, 234, 245, 0.75);
420 font-style: italic;
421 background: rgba(255, 255, 255, 0.03);
422 border-radius: 0 6px 6px 0;
423}
424.pluma-doc ul, .pluma-doc ol { padding-left: 1.6em; }
425.pluma-doc li { margin: 0.4em 0; }
426.pluma-doc li::marker { color: var(--page-accent); }
427.pluma-doc hr {
428 border: none;
429 height: 1px;
430 background: linear-gradient(to right, transparent, var(--page-accent), transparent);
431 margin: 2em 0;
432}
433.pluma-doc table {
434 border-collapse: collapse;
435 width: 100%;
436 font-size: 0.95rem;
437}
438.pluma-doc th, .pluma-doc td {
439 padding: 0.55em 0.9em;
440 border-bottom: 1px solid rgba(255, 255, 255, 0.08);
441 text-align: left;
442}
443.pluma-doc th {
444 color: var(--page-accent);
445 font-weight: 600;
446 letter-spacing: 0.04em;
447}
448.pluma-loading, .pluma-error {
449 display: flex;
450 align-items: center;
451 justify-content: center;
452 min-height: 30vh;
453 color: rgba(232, 234, 245, 0.55);
454 font-family: 'Cinzel', serif;
455 letter-spacing: 0.4em;
456 font-size: 0.9rem;
457}
458.pluma-loading::before {
459 content: "";
460 width: 28px;
461 height: 28px;
462 margin-right: 1rem;
463 border: 1px solid var(--page-accent);
464 border-top-color: transparent;
465 border-radius: 50%;
466 animation: pluma-spin 1s linear infinite;
467}
468.pluma-error { color: var(--fuego); font-style: italic; }
469@keyframes pluma-spin { to { transform: rotate(360deg); } }
470
471/* === Taskbar estilo Windows === */
472.taskbar {
473 position: fixed;
474 left: 0;
475 right: 0;
476 bottom: 0;
477 height: var(--taskbar-height);
478 z-index: 200;
479 display: flex;
480 align-items: center;
481 gap: 0.5rem;
482 padding: 0 0.8rem;
483 background: linear-gradient(to top, rgba(6, 5, 13, 0.94), rgba(8, 6, 22, 0.80));
484 backdrop-filter: blur(24px) saturate(140%);
485 -webkit-backdrop-filter: blur(24px) saturate(140%);
486 border-top: 1px solid rgba(216, 168, 93, 0.22);
487 box-shadow: 0 -10px 36px rgba(0, 0, 0, 0.45);
488}
489
490.taskbar-home {
491 width: 40px;
492 height: 40px;
493 display: inline-flex;
494 align-items: center;
495 justify-content: center;
496 background: transparent;
497 border: 1px solid rgba(216, 168, 93, 0.32);
498 color: var(--gold);
499 border-radius: 9px;
500 cursor: pointer;
501 padding: 0;
502 transition: all 220ms var(--ease-emerge);
503}
504.taskbar-home:hover {
505 border-color: var(--gold);
506 background: rgba(216, 168, 93, 0.12);
507 box-shadow: 0 0 16px rgba(216, 168, 93, 0.35);
508 transform: translateY(-1px);
509}
510.taskbar-home-glyph {
511 width: 22px;
512 height: 22px;
513 filter: drop-shadow(0 0 6px currentColor);
514}
515
516.taskbar-brand {
517 font-family: 'Cinzel', serif;
518 font-weight: 700;
519 font-size: 1.30rem;
520 letter-spacing: 0.07em;
521 color: #f4eedf;
522 text-decoration: none;
523 text-shadow: 0 0 14px rgba(216, 168, 93, 0.45);
524 padding: 0 0.55rem;
525 user-select: none;
526 transition: text-shadow 220ms ease, color 220ms ease;
527 white-space: nowrap;
528}
529.taskbar-brand:hover {
530 color: #ffffff;
531 text-shadow: 0 0 20px rgba(216, 168, 93, 0.7), 0 0 36px rgba(245, 144, 86, 0.30);
532}
533.taskbar-brand .brand-dot {
534 color: var(--gold);
535 margin: 0 0.05em;
536}
537
538.taskbar-divider {
539 display: inline-block;
540 width: 1px;
541 height: 26px;
542 background: rgba(255, 255, 255, 0.12);
543 margin: 0 0.25rem;
544}
545
546.taskbar-list {
547 list-style: none;
548 margin: 0;
549 padding: 0;
550 display: flex;
551 gap: 0.4rem;
552 overflow-x: auto;
553 scrollbar-width: none;
554 -ms-overflow-style: none;
555}
556.taskbar-list::-webkit-scrollbar { display: none; }
557
558.taskbar-item {
559 height: 38px;
560 padding: 0 1.0rem;
561 display: inline-flex;
562 align-items: center;
563 gap: 0.55rem;
564 background: rgba(255, 255, 255, 0.04);
565 border: 1px solid rgba(255, 255, 255, 0.10);
566 border-radius: 9px;
567 color: var(--task-color, var(--fg));
568 font-family: 'Cinzel', serif;
569 font-size: 0.72rem;
570 letter-spacing: 0.36em;
571 text-indent: 0.36em;
572 font-weight: 600;
573 cursor: pointer;
574 transition: all 260ms var(--ease-emerge);
575 white-space: nowrap;
576}
577.taskbar-item:hover {
578 background: rgba(255, 255, 255, 0.09);
579 border-color: var(--task-color, currentColor);
580 transform: translateY(-1px);
581}
582.taskbar-item.active {
583 background: rgba(255, 255, 255, 0.11);
584 border-color: var(--task-color);
585 box-shadow:
586 0 0 18px var(--task-color),
587 inset 0 -2px 0 0 var(--task-color);
588}
589.taskbar-item-dot {
590 width: 8px;
591 height: 8px;
592 border-radius: 50%;
593 background: var(--task-color, var(--gold));
594 box-shadow: 0 0 8px currentColor;
595}
596.taskbar-item[data-task="aire"] { --task-color: var(--aire); }
597.taskbar-item[data-task="fuego"] { --task-color: var(--fuego); }
598.taskbar-item[data-task="tierra"] { --task-color: var(--tierra); }
599.taskbar-item[data-task="agua"] { --task-color: var(--agua); }
600
601.taskbar-spacer {
602 flex: 1;
603 min-width: 0.6rem;
604}
605
606.taskbar-credit {
607 display: inline-flex;
608 align-items: center;
609 gap: 0.4rem;
610 font-family: 'Inter', sans-serif;
611 font-size: 0.78rem;
612 letter-spacing: 0.04em;
613 color: rgba(216, 168, 93, 0.75);
614 text-decoration: none;
615 padding: 0.35rem 0.7rem;
616 border-radius: 8px;
617 border: 1px solid transparent;
618 transition: all 220ms var(--ease-emerge);
619 white-space: nowrap;
620}
621.taskbar-credit:hover {
622 color: var(--gold);
623 border-color: rgba(216, 168, 93, 0.25);
624 background: rgba(216, 168, 93, 0.06);
625}
626.copyleft-mark {
627 display: inline-block;
628 font-size: 1rem;
629 /* © con escala horizontal -1 = copyleft visual. */
630 transform: scaleX(-1);
631 color: currentColor;
632}
633
634@media (max-width: 720px) {
635 .tip { min-width: 110px; padding: 0.7rem 0.9rem; }
636 .tip-glyph { width: 36px; height: 36px; }
637 .tip-label { font-size: 0.72rem; }
638 .tip-sub { display: none; }
639 .page-head { padding: 5vh 5vw 1vh; }
640 .page-content { padding: 0 5vw 5vh; }
641 .taskbar { height: 46px; padding: 0 0.4rem; gap: 0.3rem; }
642 .taskbar-home { width: 36px; height: 36px; }
643 .taskbar-item { height: 34px; padding: 0 0.7rem; font-size: 0.65rem; }
644 .taskbar-brand { font-size: 1.05rem; padding: 0 0.3rem; }
645 .taskbar-credit-text { display: none; }
646 .deck { bottom: 46px; }
647 :root { --taskbar-height: 46px; }
648}