nio-cat 0.1.0 → 0.1.1

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,76 @@
1
+ <!doctype html>
2
+ <html lang="ca">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover, interactive-widget=resizes-content">
6
+ <title>nio // Panell</title>
7
+ <meta name="description" content="Dona feina als agents d’IA del teu ordinador des del mòbil, segueix-los en directe i aprova cada pas.">
8
+ <meta name="robots" content="noindex">
9
+ <meta name="theme-color" content="#f0ede7">
10
+ <meta name="apple-mobile-web-app-capable" content="yes">
11
+ <meta name="mobile-web-app-capable" content="yes">
12
+ <meta name="apple-mobile-web-app-status-bar-style" content="default">
13
+ <meta name="apple-mobile-web-app-title" content="nio">
14
+ <meta property="og:type" content="website">
15
+ <meta property="og:site_name" content="nio">
16
+ <meta property="og:locale" content="ca_ES">
17
+ <meta property="og:url" content="https://www.nio.cat/app">
18
+ <meta property="og:title" content="nio // Panell">
19
+ <meta property="og:description" content="Dona feina als agents d’IA del teu ordinador des del mòbil, segueix-los en directe i aprova cada pas.">
20
+ <meta property="og:image" content="https://www.nio.cat/og.png">
21
+ <meta property="og:image:width" content="1200">
22
+ <meta property="og:image:height" content="630">
23
+ <meta property="og:image:alt" content="nio">
24
+ <meta name="twitter:card" content="summary_large_image">
25
+ <meta name="twitter:title" content="nio // Panell">
26
+ <meta name="twitter:description" content="Dona feina als agents d’IA del teu ordinador des del mòbil, segueix-los en directe i aprova cada pas.">
27
+ <meta name="twitter:image" content="https://www.nio.cat/og.png">
28
+ <link rel="manifest" href="/manifest.webmanifest">
29
+ <meta name="format-detection" content="telephone=no">
30
+ <link rel="icon" href="/favicon.svg" type="image/svg+xml">
31
+ <link rel="apple-touch-icon" href="/apple-touch-icon.png">
32
+ <link rel="preconnect" href="https://fonts.googleapis.com">
33
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
34
+ <link href="https://fonts.googleapis.com/css2?family=Manrope:wght@400;500;600&family=Caveat:wght@500;600&display=swap" rel="stylesheet">
35
+ <link rel="stylesheet" href="/bot.css">
36
+ <link rel="stylesheet" href="/board.css">
37
+ <link rel="stylesheet" href="/app/style.css">
38
+ </head>
39
+ <body>
40
+ <header class="mbar">
41
+ <button class="icon-btn burger" id="burger" type="button" aria-label="Obre el menú" aria-expanded="false" aria-controls="side"><span></span><span></span><span></span></button>
42
+ <a href="/" class="word" aria-label="nio">ni<span class="bot" data-mood="idle" aria-hidden="true"><span class="eyes"><i></i><i></i></span></span></a>
43
+ <span class="here" id="here"></span>
44
+ <span class="grow"></span>
45
+ <span id="mRight"></span>
46
+ </header>
47
+ <div class="scrim" id="scrim"></div>
48
+ <div class="shell">
49
+ <aside class="side" id="side">
50
+ <div class="brand"><a href="/" class="word" aria-label="nio">ni<span class="bot" data-mood="idle" aria-hidden="true"><span class="eyes"><i></i><i></i></span></span></a><button class="icon-btn collapse" id="collapse" type="button" aria-label="Plega el menú" aria-expanded="true"><svg class="ico" viewBox="0 0 24 24" aria-hidden="true"><rect x="3.5" y="4.5" width="17" height="15" rx="2.5"/><path d="M9.5 4.5v15M15.5 10l-2 2 2 2"/></svg></button></div>
51
+ <nav id="nav" aria-label="Seccions"></nav>
52
+ <div class="foot">
53
+ <div class="conn" id="sideConn"></div>
54
+ <button class="kbd" data-act="tour" type="button" title="Tutorial"><svg class="ico" viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M9.6 9.3a2.5 2.5 0 0 1 4.8.9c0 1.7-2.4 2.2-2.4 3.6M12 17.2v.1"/></svg><span class="l">Tutorial</span></button>
55
+ <button class="kbd" data-act="palette" type="button" title="Cerca o fes una acció (⌘K)"><svg class="ico" viewBox="0 0 24 24" aria-hidden="true"><circle cx="11" cy="11" r="7"/><path d="m20 20-3.5-3.5"/></svg><span class="l">Cerca o fes una acció</span><kbd>⌘K</kbd></button>
56
+ </div>
57
+ </aside>
58
+ <main class="main" id="main"><div id="view"></div></main>
59
+ </div>
60
+
61
+ <dialog class="sheet" id="sheet"><div class="sheet-in" id="sheetIn"></div></dialog>
62
+ <dialog id="palette" aria-label="Ordres">
63
+ <input type="search" id="palQ" placeholder="Escriu una ordre…" autocomplete="off" aria-controls="palList">
64
+ <ul id="palList" role="listbox"></ul>
65
+ </dialog>
66
+ <div class="tour" id="tour" hidden>
67
+ <div class="tour-spot" id="tourSpot"></div>
68
+ <div class="tour-card" id="tourCard" role="dialog" aria-modal="false" aria-labelledby="tourT"></div>
69
+ </div>
70
+ <div class="toasts" id="toasts" aria-live="polite"></div>
71
+
72
+ <script src="/bot.js"></script>
73
+ <script src="/board.js"></script>
74
+ <script src="/app/app.js" type="module"></script>
75
+ </body>
76
+ </html>
@@ -0,0 +1,366 @@
1
+ /* nio · app */
2
+ :root {
3
+ --bg: #f0ede7;
4
+ --bg-2: #e6e1d8;
5
+ --panel: #f8f6f2;
6
+ --fg: #272224;
7
+ --fg-muted: #69615c;
8
+ --accent: #f46a3b;
9
+ --border: #cec7bd;
10
+ --white: #fffefd;
11
+ --moss: #5b6551;
12
+ --lemon: #e7e66a;
13
+ --red: #e2382b;
14
+ --blue: #2b5bd8;
15
+ --code: #ebe7df;
16
+ --font: "Manrope", system-ui, sans-serif;
17
+ --mono: ui-monospace, "SF Mono", "JetBrains Mono", Menlo, Consolas, monospace;
18
+ --radius: 12px;
19
+ --safe-t: env(safe-area-inset-top, 0px);
20
+ --safe-b: env(safe-area-inset-bottom, 0px);
21
+ --ease: cubic-bezier(.22, 1, .36, 1);
22
+ }
23
+ * { box-sizing: border-box; margin: 0; padding: 0; }
24
+ [hidden] { display: none !important; }
25
+ html { -webkit-text-size-adjust: 100%; }
26
+ body { background: var(--bg); color: var(--fg); font: 400 15px/1.5 var(--font); letter-spacing: -.015em; -webkit-font-smoothing: antialiased; overscroll-behavior-y: none; }
27
+ a { color: inherit; }
28
+ button, input, select, textarea { font: inherit; color: inherit; letter-spacing: inherit; }
29
+ button { cursor: pointer; }
30
+ ::selection { background: var(--lemon); }
31
+ :focus-visible { outline: 2px solid var(--fg); outline-offset: 2px; border-radius: 6px; }
32
+ .muted { color: var(--fg-muted); }
33
+ .small { font-size: 13px; }
34
+ .mono { font-family: var(--mono); font-size: .9em; letter-spacing: 0; }
35
+ .ico { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; flex: none; }
36
+ .row { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
37
+ .between { justify-content: space-between; }
38
+ .grow { flex: 1; min-width: 0; }
39
+ .stack { display: grid; gap: 10px; }
40
+ .stack-lg { display: grid; gap: 20px; }
41
+
42
+ /* ---------- Estructura ---------- */
43
+ * { -webkit-tap-highlight-color: transparent; }
44
+ .shell { transition: grid-template-columns .34s var(--ease); display: grid; grid-template-columns: 236px minmax(0, 1fr); min-height: 100vh; min-height: 100dvh; }
45
+ .side { overflow: hidden; white-space: nowrap; position: sticky; top: 0; height: 100vh; height: 100dvh; display: flex; flex-direction: column; gap: 24px; padding: 22px 14px; border-right: 1px solid var(--border); }
46
+ .brand { display: flex; align-items: baseline; justify-content: space-between; }
47
+ .brand .word { font-size: 26px; font-weight: 600; letter-spacing: -.07em; line-height: 1; text-decoration: none; }
48
+ .side nav { display: grid; gap: 2px; }
49
+ .side nav a { position: relative; overflow: hidden; display: flex; align-items: center; gap: 10px; padding: 9px 13px; border-radius: 10px; font-size: 14px; font-weight: 500; color: var(--fg-muted); text-decoration: none; transition: background-color .2s, color .2s; }
50
+ .side nav a .ico { width: 18px; height: 18px; }
51
+ .side nav a span.l { flex: 1 0 auto; }
52
+ .side nav a:hover { color: var(--fg); background: color-mix(in srgb, var(--bg-2) 60%, transparent); }
53
+ .side nav a[aria-current="page"] { color: var(--fg); background: var(--bg-2); }
54
+ .badge { min-width: 20px; height: 20px; padding: 0 6px; border-radius: 999px; background: var(--lemon); color: var(--fg); font-size: 11px; font-weight: 600; display: inline-grid; place-items: center; }
55
+ .side .foot { margin-top: auto; display: grid; gap: 8px; }
56
+ .conn { display: flex; align-items: center; gap: 8px; padding-left: 18px; overflow: hidden; font-size: 13px; color: var(--fg-muted); min-width: 0; }
57
+ .conn span { flex: none; white-space: nowrap; }
58
+ .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--border); flex: none; }
59
+ .dot.on { background: var(--moss); box-shadow: 0 0 0 3px color-mix(in srgb, var(--moss) 18%, transparent); }
60
+ .dot.wait { background: var(--accent); }
61
+ .kbd { display: flex; gap: 8px; align-items: center; overflow: hidden; width: 100%; padding: 9px 12px; border: 1px solid var(--border); border-radius: 10px; background: var(--white); color: var(--fg-muted); font-size: 13px; text-align: left; }
62
+ .kbd .ico { width: 16px; height: 16px; }
63
+ .kbd .l { flex: 1 0 auto; white-space: nowrap; }
64
+ kbd { font: 600 11px var(--font); padding: 1px 6px; border: 1px solid var(--border); border-radius: 6px; background: var(--white); color: var(--fg-muted); }
65
+ .main { min-width: 0; display: flex; flex-direction: column; }
66
+ .page { padding: 32px 40px 96px; max-width: 1080px; width: 100%; }
67
+ .top { display: flex; align-items: flex-end; justify-content: space-between; gap: 16px; flex-wrap: wrap; margin-bottom: 24px; }
68
+ .top h1 { font-size: 30px; font-weight: 500; letter-spacing: -.05em; line-height: 1.1; }
69
+ .top p { margin-top: 4px; color: var(--fg-muted); }
70
+ .mbar, .scrim { display: none; }
71
+
72
+ /* Menú plegable (escriptori): només es mou l'amplada de la barra. El contingut no s'anima: la vora el talla i el botó viatja amb ella. */
73
+ .main { min-width: 0; }
74
+ .brand { position: relative; align-items: center; height: 34px; padding: 0; }
75
+ .brand .word { margin-left: 13px; }
76
+ .brand .collapse { position: absolute; left: 0; top: 0; width: 34px; height: 34px; color: var(--fg-muted); transform: translateX(163px); transition: transform .34s var(--ease), color .2s; }
77
+ .brand .collapse svg { transition: transform .34s var(--ease); }
78
+ .brand .collapse:hover { color: var(--fg); }
79
+ @media (min-width: 821px) {
80
+ body.side-collapsed .shell { grid-template-columns: 72px minmax(0, 1fr); }
81
+ body.side-collapsed .brand .collapse { transform: translateX(4px); }
82
+ body.side-collapsed .brand .collapse svg { transform: scaleX(-1); }
83
+ body.side-collapsed .brand .word, body.side-collapsed .side nav .grp { visibility: hidden; }
84
+ body.side-collapsed .side nav a .badge { position: absolute; top: 2px; right: 2px; min-width: 16px; height: 16px; font-size: 9px; padding: 0 4px; }
85
+ }
86
+
87
+ /* ---------- Controls ---------- */
88
+ .btn { text-decoration: none; display: inline-flex; align-items: center; justify-content: center; gap: 7px; height: 38px; padding: 0 15px; border: 1px solid var(--border); border-radius: 10px; background: var(--white); font-size: 14px; font-weight: 600; white-space: nowrap; transition: background-color .2s, border-color .2s, transform .12s; }
89
+ .btn:hover { border-color: var(--fg); }
90
+ .btn:active { transform: scale(.98); }
91
+ .btn .ico { width: 17px; height: 17px; }
92
+ .btn.ink { background: var(--fg); color: var(--bg); border-color: var(--fg); }
93
+ .btn.ink:hover { background: color-mix(in srgb, var(--fg) 86%, var(--bg)); }
94
+ .btn.ok { background: var(--moss); color: var(--white); border-color: var(--moss); }
95
+ .btn.danger { color: var(--red); }
96
+ .btn.danger:hover { border-color: var(--red); }
97
+ .btn.ghost { background: transparent; border-color: transparent; }
98
+ .btn.ghost:hover { border-color: var(--border); }
99
+ .btn.sm { height: 30px; padding: 0 10px; font-size: 12px; }
100
+ .btn.block { width: 100%; }
101
+ .btn:disabled { opacity: .45; cursor: not-allowed; }
102
+ .icon-btn { position: relative; display: grid; place-items: center; width: 40px; height: 40px; border: 0; border-radius: 12px; background: none; color: var(--fg); }
103
+ .icon-btn:hover { background: color-mix(in srgb, var(--bg-2) 80%, transparent); }
104
+ .icon-btn .badge { position: absolute; top: 3px; right: 1px; min-width: 18px; height: 18px; font-size: 10px; }
105
+ input[type="text"], input[type="url"], input[type="search"], select, textarea.field { width: 100%; min-width: 0; height: 42px; padding: 0 12px; border: 1px solid var(--border); border-radius: 10px; background: var(--white); outline: none; }
106
+ textarea.field { height: auto; padding: 10px 12px; resize: vertical; line-height: 1.45; }
107
+ input:focus, select:focus, textarea:focus { border-color: var(--fg); }
108
+ select { appearance: none; -webkit-appearance: none; padding-right: 40px; cursor: pointer; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2369615c' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right 12px center; background-size: 16px 16px; }
109
+ label.f { display: grid; gap: 6px; font-size: 13px; color: var(--fg-muted); align-content: start; }
110
+ .seg { display: flex; padding: 3px; border-radius: 11px; background: var(--bg-2); }
111
+ .seg button { flex: 1; display: inline-flex; align-items: center; justify-content: center; gap: 6px; height: 34px; border: 0; border-radius: 8px; background: none; font-size: 13px; font-weight: 600; color: var(--fg-muted); white-space: nowrap; }
112
+ .seg button[aria-pressed="true"] { background: var(--white); color: var(--fg); }
113
+
114
+ .panel { background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius); }
115
+ .panel > header { display: flex; justify-content: space-between; align-items: center; gap: 12px; padding: 16px 18px; }
116
+ .panel > header h2 { font-size: 15px; font-weight: 600; letter-spacing: -.02em; }
117
+ .panel .body { padding: 0 18px 18px; }
118
+ .card { display: block; width: 100%; text-align: left; padding: 16px 18px; border: 1px solid var(--border); border-radius: var(--radius); background: var(--panel); transition: border-color .2s, transform .12s; }
119
+ button.card:hover, a.card:hover { border-color: var(--fg); }
120
+ button.card:active { transform: scale(.995); }
121
+ .list { display: grid; gap: 10px; }
122
+ .card.row { display: flex; }
123
+ .sheet-foot { position: sticky; bottom: -24px; margin: 0 -24px -24px; padding: 14px 24px 24px; background: linear-gradient(to bottom, transparent, var(--bg) 30%); }
124
+ .section-title { font-size: 12px; font-weight: 600; color: var(--fg-muted); margin: 22px 0 8px; }
125
+ .chip { display: inline-flex; align-items: center; gap: 6px; height: 26px; padding: 0 10px; border-radius: 999px; border: 1px solid var(--border); background: var(--white); font-size: 12px; font-weight: 600; white-space: nowrap; color: var(--fg); }
126
+ button.chip:hover { border-color: var(--fg); }
127
+ .chip.running { background: var(--fg); color: var(--bg); border-color: var(--fg); }
128
+ .chip.waiting { background: var(--lemon); border-color: var(--lemon); }
129
+ .chip.error { color: var(--red); border-color: color-mix(in srgb, var(--red) 40%, transparent); }
130
+ .chip.beta { height: 20px; padding: 0 7px; font-size: 10px; color: var(--fg-muted); }
131
+ .pulse { width: 6px; height: 6px; border-radius: 50%; background: currentColor; animation: pulse 1.2s ease-in-out infinite; }
132
+ @keyframes pulse { 50% { opacity: .3; } }
133
+ .agent-tag { display: inline-flex; align-items: center; gap: 7px; font-size: 13px; font-weight: 600; }
134
+ .agent-tag::before { content: ""; width: 8px; height: 8px; border-radius: 3px; background: var(--c, var(--fg-muted)); }
135
+ [data-agent="claude"] { --c: var(--accent); } [data-agent="codex"] { --c: var(--moss); } [data-agent="grok"] { --c: var(--fg); }
136
+ [data-agent="antigravity"] { --c: var(--blue); } [data-agent="ollama"] { --c: #b08a5a; } [data-agent="demo"] { --c: var(--lemon); } [data-agent="browser"] { --c: #8a5cf6; }
137
+ .empty { padding: 48px 20px; text-align: center; color: var(--fg-muted); display: grid; justify-items: center; gap: 8px; }
138
+ .empty .bot { --s: 56px; --bw: .13; color: var(--fg); margin-bottom: 8px; }
139
+ .empty h2 { font-size: 20px; font-weight: 500; letter-spacing: -.04em; color: var(--fg); }
140
+ .empty p { max-width: 42ch; }
141
+ .kv { display: grid; grid-template-columns: auto 1fr; gap: 6px 16px; font-size: 14px; }
142
+ .kv dt { color: var(--fg-muted); }
143
+ .kv dd { overflow-wrap: anywhere; }
144
+
145
+ /* ---------- Connecta ---------- */
146
+ .connect { display: grid; gap: 24px; min-width: 0; }
147
+ .connect-head h1 { font-size: clamp(30px, 4vw, 40px); font-weight: 500; letter-spacing: -.05em; line-height: 1.08; }
148
+ .connect-head .lead { color: var(--fg-muted); font-size: 16px; max-width: 58ch; margin-top: 10px; }
149
+ .connect-grid { display: grid; grid-template-columns: minmax(0, 1.6fr) minmax(260px, 1fr); gap: 16px; align-items: start; }
150
+ .conn-main { padding: 22px; display: grid; gap: 16px; min-width: 0; }
151
+ .stepper { list-style: none; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; }
152
+ .stepper li { display: flex; gap: 10px; align-items: flex-start; }
153
+ .stepper .n { flex: none; width: 26px; height: 26px; border-radius: 50%; background: var(--fg); color: var(--bg); display: grid; place-items: center; font-size: 12px; font-weight: 600; }
154
+ .stepper b { display: block; font-weight: 600; font-size: 14px; }
155
+ .stepper p { font-size: 13px; color: var(--fg-muted); margin-top: 2px; line-height: 1.4; }
156
+ .cmd { display: flex; align-items: center; gap: 8px; padding: 6px 6px 6px 14px; border-radius: 12px; background: var(--code); font-family: var(--mono); font-size: 14px; min-width: 0; }
157
+ .cmd code { flex: 1; min-width: 0; overflow-wrap: anywhere; line-height: 1.4; padding: 6px 0; }
158
+ .cmd .btn { flex: none; font-family: var(--font); }
159
+ .cmd.big { font-size: 16px; padding: 8px 8px 8px 18px; }
160
+ .reqs { display: flex; gap: 6px; flex-wrap: wrap; }
161
+ .chip.ghost { background: transparent; color: var(--fg-muted); }
162
+ .paste { border-top: 1px solid var(--border); padding-top: 12px; }
163
+ .paste summary { cursor: pointer; font-size: 14px; font-weight: 600; list-style: none; display: flex; justify-content: space-between; align-items: center; }
164
+ .paste summary::-webkit-details-marker { display: none; }
165
+ .paste summary::after { content: "+"; font-size: 18px; font-weight: 400; color: var(--fg-muted); }
166
+ .paste[open] summary::after { content: "−"; }
167
+ .paste .pair-form { display: flex; gap: 8px; margin: 12px 0 6px; }
168
+ .try { padding: 22px; display: grid; gap: 12px; justify-items: start; }
169
+ .try .bot { --s: 44px; --bw: .13; }
170
+ .try h2 { font-size: 18px; font-weight: 600; letter-spacing: -.03em; }
171
+ .side nav .grp { display: block; padding: 14px 13px 4px; font-size: 11px; font-weight: 600; color: var(--fg-muted); letter-spacing: .02em; }
172
+ .side nav .grp:first-child { padding-top: 0; }
173
+
174
+ /* ---------- Sessions ---------- */
175
+ .session-card .title { font-size: 16px; font-weight: 500; letter-spacing: -.02em; margin-top: 8px; }
176
+ .session-card .last { color: var(--fg-muted); font-size: 14px; margin-top: 4px; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
177
+ .session-card .meta { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 10px; font-size: 12px; color: var(--fg-muted); }
178
+ .fab { position: fixed; right: 24px; bottom: calc(24px + var(--safe-b)); z-index: 15; display: inline-flex; align-items: center; gap: 8px; height: 50px; padding: 0 20px 0 16px; border: 0; border-radius: 16px; background: var(--fg); color: var(--bg); font-weight: 600; box-shadow: 0 14px 30px -14px color-mix(in srgb, var(--fg) 70%, transparent); transition: transform .15s; }
179
+ .fab:active { transform: scale(.97); }
180
+
181
+ /* ---------- Xat de sessió ---------- */
182
+ .chat { display: flex; flex-direction: column; height: 100vh; height: 100dvh; }
183
+ .chat-head { display: flex; align-items: center; gap: 12px; padding: 14px 24px; border-bottom: 1px solid var(--border); }
184
+ .chat-head .bot { --s: 30px; --bw: .14; }
185
+ .chat-head h1 { font-size: 17px; font-weight: 600; letter-spacing: -.03em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
186
+ .chat-head .sub { font-size: 12px; color: var(--fg-muted); }
187
+ .mode-bar { display: flex; gap: 6px; padding: 10px 24px; overflow-x: auto; scrollbar-width: none; border-bottom: 1px solid color-mix(in srgb, var(--border) 60%, transparent); }
188
+ .mode-bar::-webkit-scrollbar { display: none; }
189
+ .feed { flex: 1; overflow-y: auto; padding: 22px 24px 30px; display: flex; flex-direction: column; gap: 12px; overscroll-behavior: contain; }
190
+ .feed > * { max-width: 760px; width: 100%; margin-left: auto; margin-right: auto; }
191
+ .msg-user { align-self: flex-end; width: auto !important; max-width: min(85%, 620px) !important; margin-right: max(0px, calc((100% - 760px) / 2)) !important; padding: 10px 14px; border-radius: 16px 16px 4px 16px; background: var(--fg); color: var(--bg); white-space: pre-wrap; overflow-wrap: anywhere; animation: rise .25s var(--ease); }
192
+ .msg-ai { line-height: 1.6; overflow-wrap: anywhere; animation: rise .25s var(--ease); }
193
+ .msg-ai p + p, .msg-ai ul, .msg-ai ol, .msg-ai pre, .msg-ai h3 { margin-top: .6em; }
194
+ .msg-ai ul, .msg-ai ol { padding-left: 1.3em; }
195
+ .msg-ai h3 { font-size: 16px; font-weight: 600; }
196
+ .msg-ai code { font-family: var(--mono); font-size: .88em; padding: 1px 5px; border-radius: 6px; background: var(--code); }
197
+ .msg-ai pre { padding: 12px 14px; border-radius: 10px; background: var(--code); overflow-x: auto; }
198
+ .msg-ai pre code { padding: 0; background: none; font-size: 13px; }
199
+ .msg-ai a { text-underline-offset: 3px; text-decoration-color: var(--accent); }
200
+ .msg-ai.cursor > :last-child::after, .msg-ai.cursor:empty::after { content: ""; display: inline-block; width: 7px; height: 1.05em; margin-left: 2px; vertical-align: -.15em; background: var(--accent); animation: pulse 1s steps(1) infinite; }
201
+ .tool { border: 1px solid var(--border); border-radius: 10px; background: var(--panel); font-size: 13px; }
202
+ .tool summary { display: flex; align-items: center; gap: 10px; padding: 9px 12px; cursor: pointer; list-style: none; }
203
+ .tool summary::-webkit-details-marker { display: none; }
204
+ .tool .name { font-weight: 600; flex: none; }
205
+ .tool .arg { flex: 1; min-width: 0; font-family: var(--mono); font-size: 12px; color: var(--fg-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
206
+ .tool .st { flex: none; font-size: 12px; font-weight: 700; color: var(--fg-muted); }
207
+ .tool .st.ok { color: var(--moss); } .tool .st.err { color: var(--red); }
208
+ .tool pre { margin: 0 12px 12px; padding: 10px 12px; max-height: 320px; overflow: auto; border-radius: 8px; background: var(--code); font: 12px/1.5 var(--mono); white-space: pre-wrap; overflow-wrap: anywhere; }
209
+ .ev-info, .ev-result { text-align: center; font-size: 12px; color: var(--fg-muted); }
210
+ .ev-result { display: flex; justify-content: center; gap: 6px; }
211
+ .ev-error { padding: 10px 14px; border-radius: 10px; border: 1px solid color-mix(in srgb, var(--red) 35%, transparent); background: color-mix(in srgb, var(--red) 6%, var(--white)); color: var(--red); font-size: 14px; white-space: pre-wrap; }
212
+ .ev-logs { font-size: 12px; color: var(--fg-muted); }
213
+ .ev-logs summary { cursor: pointer; }
214
+ .ev-logs pre { margin-top: 6px; padding: 10px; border-radius: 8px; background: var(--code); font: 11px/1.5 var(--mono); max-height: 220px; overflow: auto; white-space: pre-wrap; }
215
+ .typing { display: flex; align-items: center; gap: 10px; color: var(--fg-muted); font-size: 13px; }
216
+ .typing .bot { --s: 22px; --bw: .15; color: var(--fg); }
217
+ @keyframes rise { from { opacity: 0; transform: translateY(6px); } }
218
+
219
+ .approval { padding: 16px; border-radius: var(--radius); border: 1.5px solid var(--accent); background: var(--white); display: grid; gap: 10px; animation: rise .25s var(--ease); }
220
+ .approval.done { border-color: var(--border); background: var(--panel); }
221
+ .approval .q { font-weight: 600; }
222
+ .approval pre { padding: 10px 12px; border-radius: 8px; background: var(--code); font: 12px/1.5 var(--mono); max-height: 260px; overflow: auto; white-space: pre-wrap; overflow-wrap: anywhere; }
223
+ .approval .actions { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
224
+ .approval .actions .btn { height: 44px; font-size: 15px; }
225
+ .verdict { font-size: 13px; font-weight: 600; }
226
+ #feed .approval.done { display: flex; align-items: center; gap: 10px; padding: 9px 12px; border-radius: 10px; border: 1px solid var(--border); background: var(--panel); font-size: 13px; animation: none; }
227
+ #feed .approval.done .verdict { flex: none; padding: 2px 8px; border-radius: 999px; background: color-mix(in srgb, currentColor 10%, transparent); }
228
+ #feed .approval.done .what { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
229
+ #feed .approval.done .what .mono { color: var(--fg-muted); font-size: 12px; }
230
+ .approval.leaving { transition: opacity .4s .7s, transform .4s .7s; opacity: 0; transform: translateY(-4px); }
231
+ .verdict.allowed { color: var(--moss); } .verdict.denied { color: var(--red); }
232
+
233
+ .composer { display: flex; gap: 8px; align-items: flex-end; padding: 12px 24px calc(14px + var(--safe-b)); border-top: 1px solid var(--border); background: var(--bg); }
234
+ .composer > * { max-width: 760px; }
235
+ .composer .inner { flex: 1; display: flex; gap: 8px; align-items: flex-end; max-width: 760px; margin: 0 auto; width: 100%; }
236
+ .composer textarea { flex: 1; min-height: 46px; max-height: 180px; padding: 12px 14px; border: 1px solid var(--border); border-radius: 14px; background: var(--white); resize: none; outline: none; line-height: 1.4; }
237
+ .composer textarea:focus { border-color: var(--fg); }
238
+ .send { display: grid; place-items: center; width: 46px; height: 46px; flex: none; border: 0; border-radius: 14px; background: var(--fg); color: var(--bg); transition: transform .12s, background-color .2s; }
239
+ .send:active { transform: scale(.95); }
240
+ .send.stop { background: var(--red); }
241
+
242
+ /* ---------- Full (nova sessió, opcions) ---------- */
243
+ dialog.sheet { border: 0; padding: 0; margin: auto; width: min(560px, 100% - 32px); max-height: min(86vh, 860px); border-radius: 18px; background: var(--bg); color: var(--fg); overflow: auto; }
244
+ dialog.sheet::backdrop { background: color-mix(in srgb, var(--fg) 40%, transparent); -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px); }
245
+ dialog.sheet[open] { animation: pop .22s var(--ease); }
246
+ @keyframes pop { from { opacity: 0; transform: translateY(10px) scale(.98); } }
247
+ .sheet-in { padding: 24px; display: grid; gap: 18px; }
248
+ .sheet-in h2 { font-size: 22px; font-weight: 500; letter-spacing: -.045em; }
249
+ .sheet-in .grab { display: none; }
250
+ .picker { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 8px; }
251
+ .pick { display: grid; gap: 2px; padding: 12px; border: 1px solid var(--border); border-radius: 12px; background: var(--white); text-align: left; }
252
+ .pick .sub { font-size: 12px; color: var(--fg-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
253
+ .pick[aria-pressed="true"] { border-color: var(--fg); box-shadow: inset 0 0 0 1px var(--fg); }
254
+ .pick.off { opacity: .5; }
255
+ .proj-list { display: grid; gap: 6px; max-height: 220px; overflow-y: auto; }
256
+ .proj { display: flex; gap: 10px; align-items: center; padding: 10px 12px; border: 1px solid var(--border); border-radius: 10px; background: var(--white); text-align: left; }
257
+ .proj .p { font: 11px var(--mono); color: var(--fg-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
258
+ .proj[aria-pressed="true"] { border-color: var(--fg); box-shadow: inset 0 0 0 1px var(--fg); }
259
+ .proj .ic { flex: none; width: 26px; height: 26px; border-radius: 8px; display: grid; place-items: center; background: var(--bg-2); font-size: 11px; font-weight: 700; }
260
+
261
+ /* ---------- Al mòbil ---------- */
262
+ .progress { height: 6px; border-radius: 999px; background: var(--bg-2); overflow: hidden; }
263
+ .progress i { display: block; height: 100%; background: var(--fg); border-radius: inherit; transition: width .2s; }
264
+ .model-card[aria-pressed="true"] { border-color: var(--fg); box-shadow: inset 0 0 0 1px var(--fg); }
265
+
266
+ /* ---------- Màquina ---------- */
267
+ .agent-row { display: flex; align-items: center; gap: 12px; padding: 12px 0; border-top: 1px solid color-mix(in srgb, var(--border) 70%, transparent); }
268
+ .agent-row:first-child { border-top: 0; }
269
+ .grid2 { display: grid; grid-template-columns: 1.2fr 1fr; gap: 16px; align-items: start; }
270
+
271
+ /* ---------- Avisos, paleta, tutorial ---------- */
272
+ .toasts { position: fixed; right: 20px; bottom: calc(20px + var(--safe-b)); display: grid; gap: 8px; z-index: 60; }
273
+ .toast { max-width: 380px; padding: 12px 16px; border-radius: 12px; background: var(--fg); color: var(--bg); font-size: 14px; animation: rise .25s var(--ease); }
274
+ #palette { border: 0; padding: 0; width: min(560px, 100% - 32px); margin: 12vh auto auto; border-radius: 16px; background: var(--bg); color: var(--fg); }
275
+ #palette::backdrop { background: color-mix(in srgb, var(--fg) 40%, transparent); }
276
+ #palette input { height: 52px; border: 0; border-bottom: 1px solid var(--border); border-radius: 16px 16px 0 0; padding: 0 18px; font-size: 16px; }
277
+ #palette ul { list-style: none; max-height: 340px; overflow: auto; padding: 6px; }
278
+ #palette li { display: flex; justify-content: space-between; gap: 12px; padding: 10px 12px; border-radius: 10px; cursor: pointer; font-size: 14px; }
279
+ #palette li[aria-selected="true"] { background: var(--bg-2); }
280
+ #palette li span { color: var(--fg-muted); font-size: 12px; }
281
+
282
+ .tour { position: fixed; inset: 0; z-index: 40; pointer-events: none; }
283
+ .tour-spot { position: fixed; border-radius: 12px; box-shadow: 0 0 0 9999px color-mix(in srgb, var(--fg) 42%, transparent), 0 0 0 2px var(--white) inset; transition: left .35s var(--ease), top .35s var(--ease), width .35s var(--ease), height .35s var(--ease); }
284
+ .tour-card { position: fixed; width: 340px; pointer-events: auto; background: var(--bg); border-radius: 16px; padding: 18px; display: grid; gap: 10px; transition: left .35s var(--ease), top .35s var(--ease); }
285
+ .tour-card.center { width: min(420px, calc(100% - 32px)); padding: 28px; gap: 14px; text-align: center; justify-items: center; }
286
+ .tour-head { display: flex; align-items: center; gap: 12px; width: 100%; }
287
+ .tour-head .bot { --s: 34px; --bw: .13; }
288
+ .tour-card.center .tour-head { flex-direction: column; }
289
+ .tour-card.center .tour-head .bot { --s: 72px; }
290
+ .tour-step { font-size: 12px; color: var(--fg-muted); }
291
+ .tour-x { margin-left: auto; width: 28px; height: 28px; border: 0; border-radius: 8px; background: none; font-size: 18px; line-height: 1; color: var(--fg-muted); }
292
+ .tour-card.center .tour-x { position: absolute; top: 12px; right: 12px; }
293
+ .tour-card h3 { font-size: 19px; font-weight: 500; letter-spacing: -.035em; line-height: 1.2; }
294
+ .tour-card.center h3 { font-size: 26px; letter-spacing: -.045em; }
295
+ .tour-card p { font-size: 14px; color: var(--fg-muted); }
296
+ .tour-foot { display: flex; align-items: center; justify-content: space-between; gap: 8px; width: 100%; padding-top: 4px; }
297
+ .tour-card.center .tour-foot { justify-content: center; }
298
+
299
+ /* ---------- Pissarra ---------- */
300
+ body.board-mode .page { padding: 0; max-width: none; }
301
+
302
+ @media (prefers-reduced-motion: no-preference) {
303
+ .view-enter { animation: view-in .25s var(--ease); }
304
+ @keyframes view-in { from { opacity: 0; transform: translateY(10px); } }
305
+ }
306
+ @media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation: none !important; transition: none !important; } }
307
+
308
+ @media (max-width: 1000px) { .grid2, .connect-grid { grid-template-columns: minmax(0, 1fr); } }
309
+ @media (max-width: 820px) {
310
+ .shell { grid-template-columns: minmax(0, 1fr); }
311
+ body.side-collapsed .shell { grid-template-columns: minmax(0, 1fr); }
312
+ .brand .collapse { display: none; }
313
+ .mbar { position: sticky; top: 0; z-index: 30; display: flex; align-items: center; gap: 6px; min-height: calc(56px + var(--safe-t)); padding: var(--safe-t) 8px 0; background: color-mix(in srgb, var(--bg) 72%, transparent); -webkit-backdrop-filter: blur(18px) saturate(160%); backdrop-filter: blur(18px) saturate(160%); border-bottom: 1px solid color-mix(in srgb, var(--border) 65%, transparent); }
314
+ .mbar .word { font-size: 24px; font-weight: 600; letter-spacing: -.07em; line-height: 1; text-decoration: none; padding-left: 4px; }
315
+ .mbar .here { font-size: 14px; color: var(--fg-muted); padding-left: 10px; margin-left: 2px; border-left: 1px solid var(--border); line-height: 1.2; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
316
+ .burger span { position: absolute; left: 11px; width: 18px; height: 2px; border-radius: 2px; background: currentColor; transition: transform .4s var(--ease), opacity .2s; }
317
+ .burger span:nth-child(1) { transform: translateY(-5px); } .burger span:nth-child(3) { transform: translateY(5px); }
318
+ body.nav-open .burger span:nth-child(1) { transform: rotate(45deg); }
319
+ body.nav-open .burger span:nth-child(2) { opacity: 0; }
320
+ body.nav-open .burger span:nth-child(3) { transform: rotate(-45deg); }
321
+ .side { position: fixed; z-index: 50; top: 0; left: 0; bottom: 0; width: min(304px, 86vw); padding: calc(20px + var(--safe-t)) 14px calc(20px + var(--safe-b)); overflow-y: auto; overscroll-behavior: contain; border-right: 1px solid color-mix(in srgb, var(--border) 60%, transparent); background: color-mix(in srgb, var(--bg) 70%, transparent); -webkit-backdrop-filter: blur(20px) saturate(160%); backdrop-filter: blur(20px) saturate(160%); transform: translateX(-104%); transition: transform .3s var(--ease), box-shadow .3s; will-change: transform; }
322
+ body.nav-open .side { transform: none; box-shadow: 24px 0 60px -30px color-mix(in srgb, var(--fg) 45%, transparent); }
323
+ .side.dragging { transition: none; }
324
+ .side nav a { padding: 12px; font-size: 16px; }
325
+ .side .foot .kbd kbd { display: none; }
326
+ .scrim { display: block; position: fixed; inset: 0; z-index: 45; background: color-mix(in srgb, var(--fg) 30%, transparent); opacity: 0; pointer-events: none; transition: opacity .3s ease-out; }
327
+ body.nav-open .scrim { opacity: 1; pointer-events: auto; }
328
+ body.nav-open { overflow: hidden; }
329
+ .page { padding: 20px 16px calc(100px + var(--safe-b)); }
330
+ .stepper { grid-template-columns: minmax(0, 1fr); }
331
+ .conn-main, .try { padding: 18px; }
332
+ .cmd.big { flex-direction: column; align-items: stretch; gap: 8px; padding: 12px; font-size: 13.5px; }
333
+ .cmd.big code { white-space: nowrap; overflow-x: auto; padding: 4px 2px; }
334
+ .cmd.big .btn { height: 38px; }
335
+ .paste .pair-form { flex-direction: column; }
336
+ .side nav .grp { padding: 16px 12px 4px; }
337
+ .top h1 { font-size: 26px; }
338
+ .chat { height: calc(100dvh - 56px - var(--safe-t)); }
339
+ body.chat-mode { overflow: hidden; }
340
+ body.chat-mode .shell { min-height: 0; }
341
+ body.chat-mode .mbar { position: fixed; left: 0; right: 0; transform: translateY(var(--vvt, 0px)); }
342
+ body.chat-mode .chat { position: fixed; left: 0; right: 0; top: calc(56px + var(--safe-t) + var(--vvt, 0px)); height: calc(var(--vvh, 100dvh) - 56px - var(--safe-t)); }
343
+ body.chat-mode.kb .composer { padding-bottom: 10px; }
344
+ .composer textarea, input[type="text"], input[type="url"], input[type="search"], select, textarea.field { font-size: 16px; }
345
+ .chat-head { display: none; }
346
+ .mode-bar { padding: 10px 16px; }
347
+ .feed { padding: 18px 16px 24px; }
348
+ .composer { padding: 10px 12px calc(10px + var(--safe-b)); }
349
+ .fab { right: 16px; bottom: calc(16px + var(--safe-b)); }
350
+ dialog.sheet { width: 100%; max-width: none; max-height: 92dvh; margin: auto 0 0; border-radius: 20px 20px 0 0; }
351
+ dialog.sheet[open] { animation: sheet-up .3s var(--ease); }
352
+ @keyframes sheet-up { from { transform: translateY(100%); } }
353
+ .sheet-in { padding: 10px 18px calc(22px + var(--safe-b)); }
354
+ .sheet-foot { bottom: calc(-22px - var(--safe-b)); margin: 0 -18px calc(-22px - var(--safe-b)); padding: 14px 18px calc(22px + var(--safe-b)); }
355
+ .sheet-in .grab { display: block; width: 36px; height: 4px; margin: 0 auto 4px; border-radius: 4px; background: var(--border); }
356
+ .toasts { left: 12px; right: 12px; bottom: calc(12px + var(--safe-b)); }
357
+ .toast { max-width: none; }
358
+ body.chat-mode .toasts { bottom: calc(84px + var(--safe-b)); }
359
+ .tour-card.top, .tour-card.bottom { left: 12px; right: 12px; width: auto; max-height: 46vh; overflow-y: auto; padding: 16px; transition: none; }
360
+ .tour-card.bottom { top: auto; bottom: calc(12px + var(--safe-b)); }
361
+ .tour-card.top { top: calc(12px + var(--safe-t)); bottom: auto; }
362
+ .tour-card.center { max-height: calc(100dvh - 32px); overflow-y: auto; }
363
+ .tour-card h3 { font-size: 18px; }
364
+ .tour-foot .btn { height: 36px; padding: 0 14px; font-size: 13px; }
365
+ .board-root { height: calc(100dvh - 56px - var(--safe-t)) !important; }
366
+ }
Binary file
package/web/board.css ADDED
@@ -0,0 +1,167 @@
1
+ /* Nio · Pissarra */
2
+ .board-root { position: relative; height: 100vh; height: 100dvh; --bd-bg: var(--bg); --bd-blue: #2b5bd8; }
3
+ .bd { display: flex; height: 100%; min-height: 0; }
4
+ .bd-stage { container: stage / inline-size; position: relative; flex: 1; min-width: 0; overflow: hidden; background-color: var(--bg); background-image: radial-gradient(circle, color-mix(in srgb, var(--fg) 16%, transparent) 1px, transparent 1.3px); user-select: none; -webkit-user-select: none; }
5
+ .bd-stage.nogrid { background-image: none; }
6
+ .bd-svg { position: absolute; inset: 0; width: 100%; height: 100%; display: block; touch-action: none; cursor: crosshair; }
7
+ .bd-stage[data-tool="select"] .bd-svg { cursor: default; }
8
+ .bd-stage[data-tool="select"] g[data-id] { cursor: move; }
9
+ .bd-stage[data-tool="hand"] .bd-svg, .bd-stage.space .bd-svg { cursor: grab; }
10
+ .bd-stage.panning .bd-svg { cursor: grabbing; }
11
+ .bd-stage[data-tool="text"] .bd-svg { cursor: text; }
12
+ .bd-stage[data-tool="eraser"] .bd-svg { cursor: cell; }
13
+ .bd-svg .hit { fill: transparent; stroke: none; pointer-events: all; }
14
+ .bd-svg .hit.line { fill: none; stroke: transparent; stroke-width: 16; pointer-events: stroke; }
15
+ .bd-svg g[data-id] { transition: opacity .15s; }
16
+ .bd-svg g.erasing { opacity: .22; }
17
+ .bd-svg g.editing text { opacity: 0; }
18
+ .bd-selg .selbox { fill: none; stroke: var(--bd-blue); }
19
+ .bd-selg .marq { fill: color-mix(in srgb, var(--bd-blue) 7%, transparent); stroke: var(--bd-blue); }
20
+ .bd-selg .bindhint { fill: none; stroke: var(--bd-blue); opacity: .45; }
21
+ .bd-selg .hdl { fill: #fff; stroke: var(--bd-blue); }
22
+ .bd-selg [data-h="nw"], .bd-selg [data-h="se"] { cursor: nwse-resize; }
23
+ .bd-selg [data-h="ne"], .bd-selg [data-h="sw"] { cursor: nesw-resize; }
24
+ .bd-selg [data-h="n"], .bd-selg [data-h="s"] { cursor: ns-resize; }
25
+ .bd-selg [data-h="e"], .bd-selg [data-h="w"] { cursor: ew-resize; }
26
+ .bd-selg [data-ep] { cursor: grab; }
27
+
28
+ .bd .ico { width: 19px; height: 19px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; flex: none; }
29
+ .bd-bar { position: absolute; z-index: 4; display: flex; align-items: center; gap: 2px; padding: 4px; border-radius: 14px; border: 1px solid color-mix(in srgb, var(--border) 80%, transparent); background: color-mix(in srgb, var(--white) 80%, transparent); -webkit-backdrop-filter: blur(16px) saturate(160%); backdrop-filter: blur(16px) saturate(160%); box-shadow: 0 10px 30px -18px color-mix(in srgb, var(--fg) 40%, transparent); }
30
+ .bd-bar .sep { width: 1px; align-self: stretch; margin: 6px 4px; background: var(--border); }
31
+ .bd-tools { top: 14px; left: 50%; transform: translateX(-50%); }
32
+ .bd .tb, .bd .ib { position: relative; display: grid; place-items: center; width: 38px; height: 38px; border: 0; border-radius: 10px; background: none; color: var(--fg); cursor: pointer; -webkit-tap-highlight-color: transparent; transition: background-color .15s, color .15s, transform .12s; }
33
+ .bd .ib { width: 34px; height: 34px; }
34
+ .bd .tb:hover, .bd .ib:hover { background: color-mix(in srgb, var(--bg-2) 85%, transparent); }
35
+ .bd .tb:active, .bd .ib:active { transform: scale(.94); }
36
+ .bd .tb[aria-pressed="true"] { background: var(--fg); color: var(--bg); }
37
+ .bd .tb small { position: absolute; right: 4px; bottom: 2px; font-size: 9px; font-weight: 600; opacity: .5; line-height: 1; }
38
+ .bd .ib.danger { color: var(--red); }
39
+ .bd .pct { min-width: 54px; height: 34px; border: 0; border-radius: 10px; background: none; font-size: 12px; font-weight: 600; font-variant-numeric: tabular-nums; cursor: pointer; }
40
+ .bd .pct:hover { background: color-mix(in srgb, var(--bg-2) 85%, transparent); }
41
+ .bd-zoom { left: 14px; bottom: 14px; }
42
+ .bd-right { top: 14px; right: 14px; }
43
+ .bd .chat-t { width: auto; display: flex; gap: 8px; padding: 0 12px 0 9px; font-size: 13px; font-weight: 600; }
44
+ .bd .chat-t .tbbot { --s: 20px; --bw: .15; }
45
+ .only-m { display: none !important; }
46
+
47
+ .bd-menuwrap { position: relative; }
48
+ .bd-menu { position: absolute; top: 44px; right: 0; z-index: 8; min-width: 230px; padding: 6px; display: grid; border-radius: 14px; border: 1px solid var(--border); background: color-mix(in srgb, var(--white) 92%, transparent); -webkit-backdrop-filter: blur(16px); backdrop-filter: blur(16px); box-shadow: 0 16px 40px -20px color-mix(in srgb, var(--fg) 45%, transparent); animation: bd-pop .16s cubic-bezier(.22,1,.36,1); }
49
+ .bd-menu[hidden] { display: none; }
50
+ .bd-menu button, .bd-menu label { display: flex; justify-content: space-between; align-items: center; gap: 12px; width: 100%; padding: 9px 10px; border: 0; border-radius: 9px; background: none; font-size: 13px; font-weight: 500; text-align: left; cursor: pointer; color: var(--fg); }
51
+ .bd-menu button:hover, .bd-menu label:hover { background: var(--bg-2); }
52
+ .bd-menu .danger { color: var(--red); }
53
+ .bd-menu hr { border: 0; border-top: 1px solid var(--border); margin: 4px 6px; }
54
+ .bd kbd { font: 600 10px var(--font); padding: 2px 6px; border: 1px solid var(--border); border-radius: 6px; background: var(--white); color: var(--fg-muted); white-space: nowrap; }
55
+ @keyframes bd-pop { from { opacity: 0; transform: translateY(-4px) scale(.98); } }
56
+
57
+ .bd-style { position: absolute; z-index: 4; left: 14px; top: 70px; width: 216px; padding: 14px; display: grid; gap: 14px; border-radius: 14px; border: 1px solid color-mix(in srgb, var(--border) 80%, transparent); background: color-mix(in srgb, var(--white) 84%, transparent); -webkit-backdrop-filter: blur(16px) saturate(160%); backdrop-filter: blur(16px) saturate(160%); box-shadow: 0 10px 30px -18px color-mix(in srgb, var(--fg) 40%, transparent); animation: bd-pop .18s cubic-bezier(.22,1,.36,1); }
58
+ .bd-style[hidden] { display: none; }
59
+ .bd-style .grp { display: grid; gap: 7px; }
60
+ .bd-style .grp > span { font-size: 11px; font-weight: 600; color: var(--fg-muted); }
61
+ .bd-style .row { display: flex; gap: 6px; flex-wrap: wrap; }
62
+ .bd-style .sw-c { width: 26px; height: 26px; padding: 0; border-radius: 8px; border: 1px solid color-mix(in srgb, var(--fg) 14%, transparent); background: var(--c); cursor: pointer; transition: transform .12s; }
63
+ .bd-style .sw-c:hover { transform: scale(1.08); }
64
+ .bd-style .sw-c[aria-pressed="true"] { outline: 2px solid var(--fg); outline-offset: 2px; }
65
+ .bd-style .sw-c.none { background: linear-gradient(135deg, transparent 45%, var(--red) 46%, var(--red) 54%, transparent 55%), var(--white); }
66
+ .bd-style .seg2 { display: flex; padding: 2px; border-radius: 9px; background: var(--bg-2); }
67
+ .bd-style .seg2 button { flex: 1; display: grid; place-items: center; height: 28px; border: 0; border-radius: 7px; background: none; font-size: 12px; font-weight: 600; color: var(--fg-muted); cursor: pointer; }
68
+ .bd-style .seg2 button[aria-pressed="true"] { background: var(--white); color: var(--fg); }
69
+ .bd-style .seg2 i { display: block; width: 20px; border-radius: 2px; background: currentColor; }
70
+ .bd-style .acts { gap: 2px; }
71
+
72
+ .bd-empty { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); width: min(380px, calc(100% - 48px)); display: grid; gap: 6px; text-align: center; color: var(--fg-muted); pointer-events: none; }
73
+ .bd-empty b { font-size: 17px; font-weight: 600; color: var(--fg); }
74
+ .bd-empty[hidden] { display: none; }
75
+ .bd-edit { position: absolute; left: 0; top: 0; z-index: 5; margin: 0; padding: 0; border: 0; outline: none; background: transparent; resize: none; overflow: hidden; white-space: pre-wrap; word-break: break-word; caret-color: var(--accent); }
76
+
77
+ .bd-help { position: absolute; inset: 0; z-index: 10; display: grid; place-items: center; padding: 16px; background: color-mix(in srgb, var(--fg) 22%, transparent); -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px); }
78
+ .bd-help[hidden] { display: none; }
79
+ .bd-help-in { width: min(820px, 100%); max-height: 100%; overflow: auto; padding: 22px; border-radius: 18px; background: var(--bg); box-shadow: 0 30px 80px -30px color-mix(in srgb, var(--fg) 60%, transparent); animation: bd-pop .2s cubic-bezier(.22,1,.36,1); }
80
+ .bd-help header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 14px; }
81
+ .bd-help h3 { font-size: 20px; font-weight: 500; letter-spacing: -.04em; }
82
+ .bd-help .cols { display: grid; grid-template-columns: repeat(3, 1fr); gap: 24px; }
83
+ .bd-help dt { font-size: 12px; font-weight: 600; color: var(--fg-muted); margin-bottom: 8px; }
84
+ .bd-help dl div { display: flex; align-items: center; gap: 6px; padding: 6px 0; border-top: 1px solid color-mix(in srgb, var(--border) 70%, transparent); font-size: 13px; }
85
+ .bd-help dd { flex: 1; }
86
+
87
+ .bd-chat { position: relative; z-index: 6; display: flex; flex-direction: column; width: 0; min-height: 0; overflow: hidden; border-left: 1px solid transparent; background: var(--panel); transition: width .38s cubic-bezier(.22,1,.36,1), border-color .38s; }
88
+ .chat-open .bd-chat { width: 360px; border-left-color: var(--border); }
89
+ .bd-chat > * { width: 360px; flex: none; }
90
+ .bd-chat header { display: flex; justify-content: space-between; align-items: center; padding: 14px 14px 12px 16px; border-bottom: 1px solid var(--border); }
91
+ .bd-chat .who { display: flex; align-items: center; gap: 10px; }
92
+ .bd-chat .hbot { --s: 30px; --bw: .14; }
93
+ .bd-chat .who b { display: block; font-size: 15px; font-weight: 600; }
94
+ .bd-chat .who small { display: block; font-size: 12px; color: var(--fg-muted); }
95
+ .bd-chat .brain { display: flex; align-items: center; gap: 8px; padding: 10px 16px; border-bottom: 1px solid var(--border); font-size: 12px; font-weight: 600; color: var(--fg-muted); }
96
+ .bd-chat .brain select { flex: 1; min-width: 0; height: 32px; padding: 0 34px 0 10px; border: 1px solid var(--border); border-radius: 9px; background-color: var(--white); font-size: 13px; color: var(--fg); background-position: right 9px center; }
97
+ .bd-chat .m .dim { color: var(--fg-muted); font-size: 12px; }
98
+ .bd-chat .msgs { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 16px; display: flex; flex-direction: column; gap: 12px; scroll-behavior: smooth; }
99
+ .bd-chat .m { max-width: 88%; font-size: 14px; line-height: 1.45; animation: bd-msg .28s cubic-bezier(.22,1,.36,1); }
100
+ .bd-chat .m.me { align-self: flex-end; padding: 9px 13px; border-radius: 16px 16px 4px 16px; background: var(--fg); color: var(--bg); white-space: pre-wrap; }
101
+ .bd-chat .m.nio { display: flex; gap: 8px; align-items: flex-end; }
102
+ .bd-chat .m.nio > div { padding: 10px 13px; border-radius: 16px 16px 16px 4px; background: var(--white); border: 1px solid color-mix(in srgb, var(--border) 70%, transparent); }
103
+ .bd-chat .m.nio b { font-weight: 600; }
104
+ .bd-chat .mav { --s: 24px; --bw: .15; margin-bottom: 4px; }
105
+ @keyframes bd-msg { from { opacity: 0; transform: translateY(6px); } }
106
+ .bd-chat .chips { display: flex; gap: 6px; overflow-x: auto; padding: 0 16px 10px; scrollbar-width: none; }
107
+ .bd-chat .chips::-webkit-scrollbar { display: none; }
108
+ .bd-chat .chip-s { flex: none; max-width: 260px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; padding: 7px 11px; border: 1px solid var(--border); border-radius: 999px; background: var(--white); font-size: 12px; font-weight: 500; cursor: pointer; }
109
+ .bd-chat .chip-s:hover { border-color: var(--fg); }
110
+ .bd-chat .cin { display: flex; gap: 8px; align-items: flex-end; padding: 12px 14px calc(14px + env(safe-area-inset-bottom)); border-top: 1px solid var(--border); }
111
+ .bd-chat .cin textarea { flex: 1; min-height: 42px; max-height: 140px; padding: 10px 12px; border: 1px solid var(--border); border-radius: 12px; background: var(--white); resize: none; font: inherit; font-size: 14px; line-height: 1.4; outline: none; }
112
+ .bd-chat .cin textarea:focus { border-color: var(--fg); }
113
+ .bd-chat .send { display: grid; place-items: center; width: 42px; height: 42px; flex: none; border: 0; border-radius: 12px; background: var(--fg); color: var(--bg); cursor: pointer; }
114
+
115
+ @media (prefers-reduced-motion: reduce) { .bd *, .bd *::before { animation: none !important; transition: none !important; } }
116
+
117
+ @media (max-width: 1100px) { .chat-open .bd-chat, .bd-chat > * { width: 320px; } }
118
+ @media (max-width: 820px) {
119
+ .board-root { height: calc(100dvh - 56px - env(safe-area-inset-top)); }
120
+ .bd { display: block; position: relative; }
121
+ .bd-stage { position: absolute; inset: 0; }
122
+ .bd-tools { top: auto; bottom: calc(12px + env(safe-area-inset-bottom)); left: 10px; right: 10px; transform: none; overflow-x: auto; scrollbar-width: none; }
123
+ .bd-tools::-webkit-scrollbar { display: none; }
124
+ .bd .tb { width: 40px; height: 40px; flex: none; }
125
+ .bd .tb small { display: none; }
126
+ .bd-zoom { top: 10px; bottom: auto; left: 10px; }
127
+ .bd-zoom [data-bd="zin"], .bd-zoom [data-bd="zout"] { display: none; }
128
+ .bd-right { top: 10px; right: 10px; }
129
+ .bd .chat-t { padding: 0 9px; }
130
+ .bd .chat-t > span:not(.bot) { display: none; }
131
+ .only-m { display: grid !important; }
132
+ .bd-style { display: none; }
133
+ .style-open .bd-style:not([hidden]) { display: grid; left: 10px; right: 10px; top: auto; bottom: calc(70px + env(safe-area-inset-bottom)); width: auto; grid-template-columns: 1fr 1fr; }
134
+ .bd-help .cols { grid-template-columns: 1fr; }
135
+ .bd-chat { position: absolute; left: 0; right: 0; bottom: 0; z-index: 9; width: auto !important; height: min(72%, 560px); border: 0; border-top: 1px solid var(--border); border-radius: 20px 20px 0 0; transform: translateY(105%); transition: transform .42s cubic-bezier(.22,1,.36,1); box-shadow: 0 -20px 50px -30px color-mix(in srgb, var(--fg) 55%, transparent); }
136
+ .chat-open .bd-chat { transform: none; }
137
+ .bd-chat > * { width: auto !important; }
138
+ .bd-chat header::before { content: ""; position: absolute; top: 6px; left: 50%; width: 36px; height: 4px; margin-left: -18px; border-radius: 4px; background: var(--border); }
139
+ .bd-empty { top: 42%; }
140
+ }
141
+
142
+ /* El llenç s'adapta a la seva amplada real (tauleta, xat obert, mòbil) */
143
+ @container stage (max-width: 720px) {
144
+ .bd-tools { top: auto; bottom: calc(12px + env(safe-area-inset-bottom)); left: 10px; right: 10px; transform: none; overflow-x: auto; scrollbar-width: none; justify-content: flex-start; }
145
+ .bd-tools::-webkit-scrollbar { display: none; }
146
+ .bd .tb { flex: none; }
147
+ .bd .tb small { display: none; }
148
+ .bd-zoom { top: 10px; bottom: auto; left: 10px; }
149
+ .bd-zoom [data-bd="zin"], .bd-zoom [data-bd="zout"] { display: none; }
150
+ .bd-right { top: 10px; right: 10px; }
151
+ .bd .chat-t { padding: 0 9px; }
152
+ .bd .chat-t > span:not(.bot) { display: none; }
153
+ .bd .tb.only-m { display: grid !important; }
154
+ .bd-style { display: none; }
155
+ .style-open .bd-style:not([hidden]) { display: grid; left: 10px; right: 10px; top: auto; bottom: calc(70px + env(safe-area-inset-bottom)); width: auto; grid-template-columns: 1fr 1fr; }
156
+ }
157
+ @container stage (max-width: 440px) {
158
+ .bd .tb[data-tool="hand"], .bd .tb[data-tool="line"], .bd .tb[data-bd="lock"] { display: none; }
159
+ .bd .tb { width: 38px; height: 38px; }
160
+ .bd-tools { justify-content: space-between; }
161
+ .style-open .bd-style:not([hidden]) { grid-template-columns: 1fr; max-height: 55%; overflow-y: auto; }
162
+ }
163
+ @container stage (max-width: 400px) {
164
+ .bd-tools { gap: 0; padding: 3px; left: 6px; right: 6px; }
165
+ .bd-tools .sep { display: none; }
166
+ .bd-tools .tb { flex: 1 1 0; min-width: 30px; width: auto; height: 38px; }
167
+ }