style: light theme and hand-inked logo matching acampada26s.net

The previous pass kept the dark base and the red icons, which did not
read as the acampada. Now:

- Light theme: white page, black ink and borders, black buttons with a
  hard neon offset shadow, neon for focus and the active nav item;
  h1/h2 in Anton with the stepped neon shadow of the site headings.
- Nav, empty-state, spinner and pattern assets in black; platform icons
  keep their dark disc with a neon stroke.
- New mark: three dome tents wired from their doors into a switch with
  an antenna, drawn in the inked style of the acampada logo (curved
  poles, ball ends, hatching) over a neon offset copy. LogoMark renders
  it inline; visible product name is T-HUB.
- docs/brand: t-hub.svg and a lockup with the Anton wordmark converted
  to outlines so it renders without the font.
- Public submission page moved to the light palette.

Checked with headless Chromium screenshots (offline sample data) on
desktop and mobile.
This commit is contained in:
hacklab 2026-10-15 14:40:02 +02:00
parent c7d133c395
commit c423f172d0
49 changed files with 369 additions and 286 deletions

View file

@ -1,6 +1,6 @@
# T-HUB # T-HUB
<p align="center"><img src="docs/brand/t-hub.svg" width="160" alt="T-HUB"></p> <p align="center"><img src="docs/brand/t-hub-lockup.png" width="520" alt="T-HUB"></p>
Copia de trabajo del [Tactical Media Broadcast Hub](https://gitlab.moxexley.com/mediatools/tacticalmediahub) Copia de trabajo del [Tactical Media Broadcast Hub](https://gitlab.moxexley.com/mediatools/tacticalmediahub)
para la red de acampadas: [acampada26s.net](https://acampada26s.net), para la red de acampadas: [acampada26s.net](https://acampada26s.net),
@ -16,7 +16,7 @@ Cambios respecto a upstream:
- Instagram registrado en conexión y publicación; claves de la app de Meta solo en el entorno del servidor. - Instagram registrado en conexión y publicación; claves de la app de Meta solo en el entorno del servidor.
- Panel **Outreach** para escribir por privado a mano, contacto a contacto, con seguimiento. - Panel **Outreach** para escribir por privado a mano, contacto a contacto, con seguimiento.
- RLS forzado en `media_assets` (migración 042). - RLS forzado en `media_assets` (migración 042).
- Estilo de acampada26s.net en la web: negro, blanco, neón `#00e5ff` y títulos en Anton. - Estilo de acampada26s.net en la web: fondo blanco, tinta negra, neón `#00e5ff` en sombras y foco, títulos en Anton. Logo de tres tiendas cableadas a un switch con antena, dibujado como el de la acampada (`docs/brand/`).
| Remoto | URL | | Remoto | URL |
|---|---| |---|---|

View file

@ -1,11 +1,11 @@
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200" viewBox="0 0 1700 1700"> <svg xmlns="http://www.w3.org/2000/svg" width="200" height="200" viewBox="0 0 1700 1700">
<g transform="rotate(-17.5 850 850)" opacity="0.25"> <g transform="rotate(-17.5 850 850)" opacity="0.25">
<circle cx="850" cy="850" r="350" fill="none" stroke="#FF1610" stroke-width="60" stroke-linecap="round"/> <circle cx="850" cy="850" r="350" fill="none" stroke="#000000" stroke-width="60" stroke-linecap="round"/>
<path d="M 850 405 L 464.77 1269.52 M 850 405 L 1235.23 1269.52 M 345 850 L 1355 850" <path d="M 850 405 L 464.77 1269.52 M 850 405 L 1235.23 1269.52 M 345 850 L 1355 850"
fill="none" stroke="#FF1610" stroke-width="75" stroke-linecap="round" stroke-linejoin="round"/> fill="none" stroke="#000000" stroke-width="75" stroke-linecap="round" stroke-linejoin="round"/>
</g> </g>
<g opacity="0.6"> <g opacity="0.6">
<polygon points="1450,850 1550,810 1550,890" fill="#FF1610"/> <polygon points="1450,850 1550,810 1550,890" fill="#000000"/>
<line x1="1280" y1="850" x2="1470" y2="850" stroke="#FF1610" stroke-width="30" stroke-linecap="round"/> <line x1="1280" y1="850" x2="1470" y2="850" stroke="#000000" stroke-width="30" stroke-linecap="round"/>
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 665 B

After

Width:  |  Height:  |  Size: 665 B

Before After
Before After

View file

@ -1,40 +1,44 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 240 240" width="240" height="240" role="img" aria-labelledby="t"> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 400 400" width="400" height="400" role="img" aria-labelledby="t">
<title id="t">T-HUB</title> <title id="t">T-HUB</title>
<circle cx="120" cy="120" r="118" fill="#000"/> <defs>
<circle cx="120" cy="120" r="82" fill="none" stroke="#fff" stroke-width="2" stroke-dasharray="3 7" opacity=".55"/> <!-- Dome tent in the hand-inked style of the acampada26s.net mark:
curved poles with ball ends, centre seam, hatched panel, door.
<!-- cables: each leaves through a tent door and runs to the switch --> Base midpoint at 0,0. -->
<g fill="none" stroke="#00e5ff" stroke-width="4" stroke-linecap="round"> <g id="tienda" stroke-linecap="round" stroke-linejoin="round">
<path d="M49 94 C 52 122, 74 130, 96 130"/> <path fill="none" d="M-58 0 Q-56 -66 -1 -72 Q55 -66 58 0" stroke-width="7"/>
<path d="M191 94 C 188 122, 166 130, 144 130"/> <path fill="none" d="M-64 1 Q0 -3 64 1" stroke-width="6"/>
<path d="M120 216 C 120 196, 120 168, 120 140"/> <path fill="none" d="M-44 0 Q-30 -58 -1 -72" stroke-width="4.5"/>
<path fill="none" d="M44 0 Q30 -58 -1 -72" stroke-width="4.5"/>
<path d="M-15 0 Q-14 -30 0 -33 Q14 -30 15 0 Z" stroke-width="4"/>
<path fill="none" d="M-50 -14 L-41 -25 M-50 -4 L-37 -19 M-43 -1 L-33 -13 M-52 -27 L-45 -36" stroke-width="2.6"/>
<path fill="none" d="M28 -50 L37 -42 M24 -40 L36 -30 M22 -29 L34 -19" stroke-width="2.6"/>
<circle cx="-64" cy="1" r="5.5" stroke="none"/>
<circle cx="64" cy="1" r="5.5" stroke="none"/>
<circle cx="-1" cy="-73" r="5.5" stroke="none"/>
</g>
<g id="marca" stroke-linecap="round" stroke-linejoin="round">
<!-- cables: out of each tent door to the switch -->
<path fill="none" d="M105 150 Q112 206 168 214" stroke-width="5"/>
<path fill="none" d="M295 150 Q288 206 232 214" stroke-width="5"/>
<path fill="none" d="M200 318 Q197 280 200 236" stroke-width="5"/>
<!-- antenna -->
<path fill="none" d="M200 200 Q198 160 200 118" stroke-width="6"/>
<path fill="none" d="M184 98 Q200 82 216 98" stroke-width="5"/>
<path fill="none" d="M171 88 Q200 58 229 88" stroke-width="5"/>
<circle cx="200" cy="112" r="7" stroke="none"/>
<!-- switch -->
<path d="M168 201 L233 200 L234 235 L167 236 Z" stroke-width="6" fill="#fff"/>
<path d="M179 212 h9 v11 h-9 z M196 212 h9 v11 h-9 z M213 212 h9 v11 h-9 z" stroke="none"/>
<use xlink:href="#tienda" transform="translate(105,150)"/>
<use xlink:href="#tienda" transform="translate(295,150)"/>
<use xlink:href="#tienda" transform="translate(200,340)"/>
</g>
</defs>
<!-- neon offset underneath, ink on top, as on acampada26s.net -->
<g transform="translate(7,7)" stroke="#00e5ff" fill="#00e5ff">
<use xlink:href="#marca"/>
</g> </g>
<g stroke="#000" fill="#000">
<!-- tents --> <use xlink:href="#marca"/>
<g stroke="#fff" stroke-width="3" stroke-linejoin="round">
<polygon points="19,99 49,55 79,99" fill="#000"/>
<polygon points="161,99 191,55 221,99" fill="#000"/>
<polygon points="90,221 120,177 150,221" fill="#000"/>
</g>
<g fill="#00e5ff">
<polygon points="40,99 49,80 58,99"/>
<polygon points="182,99 191,80 200,99"/>
<polygon points="111,221 120,202 129,221"/>
</g>
<!-- antenna -->
<line x1="120" y1="120" x2="120" y2="70" stroke="#fff" stroke-width="4" stroke-linecap="round"/>
<circle cx="120" cy="68" r="5" fill="#00e5ff"/>
<g fill="none" stroke="#00e5ff" stroke-width="3" stroke-linecap="round">
<path d="M106 56 A 18 18 0 0 1 134 56"/>
<path d="M97 46 A 30 30 0 0 1 143 46"/>
</g>
<!-- switch -->
<rect x="94" y="118" width="52" height="24" rx="3" fill="#fff"/>
<g fill="#000">
<rect x="101" y="125" width="9" height="9"/>
<rect x="115.5" y="125" width="9" height="9"/>
<rect x="130" y="125" width="9" height="9"/>
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Before After
Before After

View file

@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 1700 1700"> <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 1700 1700">
<title>Bluesky</title> <title>Bluesky</title>
<circle cx="850" cy="850" r="560" fill="#0a0a0b" stroke="#FF1610" stroke-width="38" <circle cx="850" cy="850" r="560" fill="#0a0a0b" stroke="#00E5FF" stroke-width="38"
transform="rotate(-17.5 850 850)"/> transform="rotate(-17.5 850 850)"/>
<path d="M 350 450 Q 400 350 500 400 L 600 480 L 700 400 Q 800 350 850 450 Q 850 550 750 650 L 600 780 L 450 650 Q 350 550 350 450 Z" fill="none" stroke="#FF1610" stroke-width="35" stroke-linecap="round" stroke-linejoin="round"/> <path d="M 350 450 Q 400 350 500 400 L 600 480 L 700 400 Q 800 350 850 450 Q 850 550 750 650 L 600 780 L 450 650 Q 350 550 350 450 Z" fill="none" stroke="#00E5FF" stroke-width="35" stroke-linecap="round" stroke-linejoin="round"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 483 B

After

Width:  |  Height:  |  Size: 483 B

Before After
Before After

View file

@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 1700 1700"> <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 1700 1700">
<title>Discord</title> <title>Discord</title>
<circle cx="850" cy="850" r="560" fill="#0a0a0b" stroke="#FF1610" stroke-width="38" <circle cx="850" cy="850" r="560" fill="#0a0a0b" stroke="#00E5FF" stroke-width="38"
transform="rotate(-17.5 850 850)"/> transform="rotate(-17.5 850 850)"/>
<path d="M 450 450 Q 550 400 600 400 Q 650 400 750 450 L 800 500 Q 850 600 800 700 L 750 750 L 700 700 L 650 720 L 550 720 L 500 700 L 450 750 L 400 700 Q 350 600 400 500 Z" fill="none" stroke="#FF1610" stroke-width="35" stroke-linejoin="round"/><circle cx="520" cy="570" r="18" fill="#FF1610"/><circle cx="680" cy="570" r="18" fill="#FF1610"/> <path d="M 450 450 Q 550 400 600 400 Q 650 400 750 450 L 800 500 Q 850 600 800 700 L 750 750 L 700 700 L 650 720 L 550 720 L 500 700 L 450 750 L 400 700 Q 350 600 400 500 Z" fill="none" stroke="#00E5FF" stroke-width="35" stroke-linejoin="round"/><circle cx="520" cy="570" r="18" fill="#00E5FF"/><circle cx="680" cy="570" r="18" fill="#00E5FF"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 598 B

After

Width:  |  Height:  |  Size: 598 B

Before After
Before After

View file

@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 1700 1700"> <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 1700 1700">
<title>Facebook</title> <title>Facebook</title>
<circle cx="850" cy="850" r="560" fill="#0a0a0b" stroke="#FF1610" stroke-width="38" <circle cx="850" cy="850" r="560" fill="#0a0a0b" stroke="#00E5FF" stroke-width="38"
transform="rotate(-17.5 850 850)"/> transform="rotate(-17.5 850 850)"/>
<path d="M 500 450 L 500 550 L 450 550 L 450 650 L 500 650 L 500 850 L 600 850 L 600 650 L 680 650 L 700 550 L 600 550 L 600 480 Q 600 450 630 450 L 700 450 L 700 380 L 620 380 Q 500 380 500 450 Z" fill="none" stroke="#FF1610" stroke-width="35" stroke-linecap="round" stroke-linejoin="round"/> <path d="M 500 450 L 500 550 L 450 550 L 450 650 L 500 650 L 500 850 L 600 850 L 600 650 L 680 650 L 700 550 L 600 550 L 600 480 Q 600 450 630 450 L 700 450 L 700 380 L 620 380 Q 500 380 500 450 Z" fill="none" stroke="#00E5FF" stroke-width="35" stroke-linecap="round" stroke-linejoin="round"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 548 B

After

Width:  |  Height:  |  Size: 548 B

Before After
Before After

View file

@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 1700 1700"> <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 1700 1700">
<title>Instagram</title> <title>Instagram</title>
<circle cx="850" cy="850" r="560" fill="#0a0a0b" stroke="#FF1610" stroke-width="38" <circle cx="850" cy="850" r="560" fill="#0a0a0b" stroke="#00E5FF" stroke-width="38"
transform="rotate(-17.5 850 850)"/> transform="rotate(-17.5 850 850)"/>
<rect x="350" y="350" width="500" height="500" rx="120" fill="none" stroke="#FF1610" stroke-width="35"/><circle cx="600" cy="600" r="130" fill="none" stroke="#FF1610" stroke-width="35"/><circle cx="770" cy="430" r="25" fill="#FF1610"/> <rect x="350" y="350" width="500" height="500" rx="120" fill="none" stroke="#00E5FF" stroke-width="35"/><circle cx="600" cy="600" r="130" fill="none" stroke="#00E5FF" stroke-width="35"/><circle cx="770" cy="430" r="25" fill="#00E5FF"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 491 B

After

Width:  |  Height:  |  Size: 491 B

Before After
Before After

View file

@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 1700 1700"> <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 1700 1700">
<title>Linkedin</title> <title>Linkedin</title>
<circle cx="850" cy="850" r="560" fill="#0a0a0b" stroke="#FF1610" stroke-width="38" <circle cx="850" cy="850" r="560" fill="#0a0a0b" stroke="#00E5FF" stroke-width="38"
transform="rotate(-17.5 850 850)"/> transform="rotate(-17.5 850 850)"/>
<rect x="350" y="350" width="500" height="100" rx="20" fill="none" stroke="#FF1610" stroke-width="35"/><line x1="400" y1="500" x2="400" y2="750" stroke="#FF1610" stroke-width="35" stroke-linecap="round"/><line x1="500" y1="500" x2="500" y2="750" stroke="#FF1610" stroke-width="35" stroke-linecap="round"/><path d="M 500 500 Q 550 450 600 500 L 600 600 Q 650 550 700 600 Q 750 650 700 700 Q 650 750 500 750" fill="none" stroke="#FF1610" stroke-width="35" stroke-linecap="round" stroke-linejoin="round"/> <rect x="350" y="350" width="500" height="100" rx="20" fill="none" stroke="#00E5FF" stroke-width="35"/><line x1="400" y1="500" x2="400" y2="750" stroke="#00E5FF" stroke-width="35" stroke-linecap="round"/><line x1="500" y1="500" x2="500" y2="750" stroke="#00E5FF" stroke-width="35" stroke-linecap="round"/><path d="M 500 500 Q 550 450 600 500 L 600 600 Q 650 550 700 600 Q 750 650 700 700 Q 650 750 500 750" fill="none" stroke="#00E5FF" stroke-width="35" stroke-linecap="round" stroke-linejoin="round"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 757 B

After

Width:  |  Height:  |  Size: 757 B

Before After
Before After

View file

@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 1700 1700"> <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 1700 1700">
<title>Mastodon</title> <title>Mastodon</title>
<circle cx="850" cy="850" r="560" fill="#0a0a0b" stroke="#FF1610" stroke-width="38" <circle cx="850" cy="850" r="560" fill="#0a0a0b" stroke="#00E5FF" stroke-width="38"
transform="rotate(-17.5 850 850)"/> transform="rotate(-17.5 850 850)"/>
<path d="M 400 500 L 400 700 Q 400 780 480 780 L 520 780 Q 560 780 560 740 L 560 560 Q 560 540 580 540 Q 600 540 600 560 L 600 740 Q 600 780 640 780 L 680 780 Q 760 780 760 700 L 760 500 Q 760 420 680 420 L 520 420 Q 440 420 400 500 Z M 400 500 L 360 460 Q 320 420 320 500 L 320 660 Q 320 740 380 760" fill="none" stroke="#FF1610" stroke-width="35" stroke-linecap="round" stroke-linejoin="round"/> <path d="M 400 500 L 400 700 Q 400 780 480 780 L 520 780 Q 560 780 560 740 L 560 560 Q 560 540 580 540 Q 600 540 600 560 L 600 740 Q 600 780 640 780 L 680 780 Q 760 780 760 700 L 760 500 Q 760 420 680 420 L 520 420 Q 440 420 400 500 Z M 400 500 L 360 460 Q 320 420 320 500 L 320 660 Q 320 740 380 760" fill="none" stroke="#00E5FF" stroke-width="35" stroke-linecap="round" stroke-linejoin="round"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 652 B

After

Width:  |  Height:  |  Size: 652 B

Before After
Before After

View file

@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 1700 1700"> <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 1700 1700">
<title>Peertube</title> <title>Peertube</title>
<circle cx="850" cy="850" r="560" fill="#0a0a0b" stroke="#FF1610" stroke-width="38" <circle cx="850" cy="850" r="560" fill="#0a0a0b" stroke="#00E5FF" stroke-width="38"
transform="rotate(-17.5 850 850)"/> transform="rotate(-17.5 850 850)"/>
<path d="M 400 350 L 400 850 L 800 600 Z" fill="none" stroke="#FF1610" stroke-width="35" stroke-linejoin="round"/> <path d="M 400 350 L 400 850 L 800 600 Z" fill="none" stroke="#00E5FF" stroke-width="35" stroke-linejoin="round"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 369 B

After

Width:  |  Height:  |  Size: 369 B

Before After
Before After

View file

@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 1700 1700"> <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 1700 1700">
<title>Reddit</title> <title>Reddit</title>
<circle cx="850" cy="850" r="560" fill="#0a0a0b" stroke="#FF1610" stroke-width="38" <circle cx="850" cy="850" r="560" fill="#0a0a0b" stroke="#00E5FF" stroke-width="38"
transform="rotate(-17.5 850 850)"/> transform="rotate(-17.5 850 850)"/>
<circle cx="600" cy="500" r="50" fill="#FF1610"/><path d="M 550 500 L 400 450" stroke="#FF1610" stroke-width="25" stroke-linecap="round"/><path d="M 650 500 L 800 450" stroke="#FF1610" stroke-width="25" stroke-linecap="round"/><ellipse cx="600" cy="650" rx="200" ry="140" fill="none" stroke="#FF1610" stroke-width="35"/><circle cx="500" cy="620" r="20" fill="#FF1610"/><circle cx="700" cy="620" r="20" fill="#FF1610"/><path d="M 520 700 Q 600 740 680 700" fill="none" stroke="#FF1610" stroke-width="25" stroke-linecap="round"/> <circle cx="600" cy="500" r="50" fill="#00E5FF"/><path d="M 550 500 L 400 450" stroke="#00E5FF" stroke-width="25" stroke-linecap="round"/><path d="M 650 500 L 800 450" stroke="#00E5FF" stroke-width="25" stroke-linecap="round"/><ellipse cx="600" cy="650" rx="200" ry="140" fill="none" stroke="#00E5FF" stroke-width="35"/><circle cx="500" cy="620" r="20" fill="#00E5FF"/><circle cx="700" cy="620" r="20" fill="#00E5FF"/><path d="M 520 700 Q 600 740 680 700" fill="none" stroke="#00E5FF" stroke-width="25" stroke-linecap="round"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 780 B

After

Width:  |  Height:  |  Size: 780 B

Before After
Before After

View file

@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 1700 1700"> <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 1700 1700">
<title>Slack</title> <title>Slack</title>
<circle cx="850" cy="850" r="560" fill="#0a0a0b" stroke="#FF1610" stroke-width="38" <circle cx="850" cy="850" r="560" fill="#0a0a0b" stroke="#00E5FF" stroke-width="38"
transform="rotate(-17.5 850 850)"/> transform="rotate(-17.5 850 850)"/>
<rect x="450" y="350" width="80" height="140" rx="20" fill="none" stroke="#FF1610" stroke-width="30"/><rect x="670" y="350" width="80" height="140" rx="20" fill="none" stroke="#FF1610" stroke-width="30"/><rect x="350" y="530" width="140" height="80" rx="20" fill="none" stroke="#FF1610" stroke-width="30"/><rect x="710" y="530" width="140" height="80" rx="20" fill="none" stroke="#FF1610" stroke-width="30"/><rect x="450" y="700" width="80" height="140" rx="20" fill="none" stroke="#FF1610" stroke-width="30"/><rect x="670" y="700" width="80" height="140" rx="20" fill="none" stroke="#FF1610" stroke-width="30"/><path d="M 530 570 L 670 570" stroke="#FF1610" stroke-width="30" stroke-linecap="round"/> <rect x="450" y="350" width="80" height="140" rx="20" fill="none" stroke="#00E5FF" stroke-width="30"/><rect x="670" y="350" width="80" height="140" rx="20" fill="none" stroke="#00E5FF" stroke-width="30"/><rect x="350" y="530" width="140" height="80" rx="20" fill="none" stroke="#00E5FF" stroke-width="30"/><rect x="710" y="530" width="140" height="80" rx="20" fill="none" stroke="#00E5FF" stroke-width="30"/><rect x="450" y="700" width="80" height="140" rx="20" fill="none" stroke="#00E5FF" stroke-width="30"/><rect x="670" y="700" width="80" height="140" rx="20" fill="none" stroke="#00E5FF" stroke-width="30"/><path d="M 530 570 L 670 570" stroke="#00E5FF" stroke-width="30" stroke-linecap="round"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 953 B

After

Width:  |  Height:  |  Size: 953 B

Before After
Before After

View file

@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 1700 1700"> <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 1700 1700">
<title>Telegram</title> <title>Telegram</title>
<circle cx="850" cy="850" r="560" fill="#0a0a0b" stroke="#FF1610" stroke-width="38" <circle cx="850" cy="850" r="560" fill="#0a0a0b" stroke="#00E5FF" stroke-width="38"
transform="rotate(-17.5 850 850)"/> transform="rotate(-17.5 850 850)"/>
<path d="M 300 600 L 850 400 L 700 800 L 550 650 L 300 600 Z M 550 650 L 550 750 L 620 680" fill="none" stroke="#FF1610" stroke-width="35" stroke-linecap="round" stroke-linejoin="round"/> <path d="M 300 600 L 850 400 L 700 800 L 550 650 L 300 600 Z M 550 650 L 550 750 L 620 680" fill="none" stroke="#00E5FF" stroke-width="35" stroke-linecap="round" stroke-linejoin="round"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 442 B

After

Width:  |  Height:  |  Size: 442 B

Before After
Before After

View file

@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 1700 1700"> <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 1700 1700">
<title>Threads</title> <title>Threads</title>
<circle cx="850" cy="850" r="560" fill="#0a0a0b" stroke="#FF1610" stroke-width="38" <circle cx="850" cy="850" r="560" fill="#0a0a0b" stroke="#00E5FF" stroke-width="38"
transform="rotate(-17.5 850 850)"/> transform="rotate(-17.5 850 850)"/>
<path d="M 600 350 Q 450 350 400 500 Q 350 650 400 750 Q 450 850 600 850 Q 750 850 800 750 Q 850 650 800 500 Q 750 350 600 350 Z M 550 550 Q 600 500 650 550 Q 700 600 650 650 Q 600 700 550 650 Q 500 600 550 550 Z" fill="none" stroke="#FF1610" stroke-width="35" stroke-linecap="round" stroke-linejoin="round"/> <path d="M 600 350 Q 450 350 400 500 Q 350 650 400 750 Q 450 850 600 850 Q 750 850 800 750 Q 850 650 800 500 Q 750 350 600 350 Z M 550 550 Q 600 500 650 550 Q 700 600 650 650 Q 600 700 550 650 Q 500 600 550 550 Z" fill="none" stroke="#00E5FF" stroke-width="35" stroke-linecap="round" stroke-linejoin="round"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 563 B

After

Width:  |  Height:  |  Size: 563 B

Before After
Before After

View file

@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 1700 1700"> <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 1700 1700">
<title>Twitch</title> <title>Twitch</title>
<circle cx="850" cy="850" r="560" fill="#0a0a0b" stroke="#FF1610" stroke-width="38" <circle cx="850" cy="850" r="560" fill="#0a0a0b" stroke="#00E5FF" stroke-width="38"
transform="rotate(-17.5 850 850)"/> transform="rotate(-17.5 850 850)"/>
<path d="M 400 350 L 800 350 L 800 600 L 650 750 L 500 750 L 400 850 Z" fill="none" stroke="#FF1610" stroke-width="35" stroke-linejoin="round"/><line x1="550" y1="450" x2="550" y2="550" stroke="#FF1610" stroke-width="35" stroke-linecap="round"/><line x1="670" y1="450" x2="670" y2="550" stroke="#FF1610" stroke-width="35" stroke-linecap="round"/> <path d="M 400 350 L 800 350 L 800 600 L 650 750 L 500 750 L 400 850 Z" fill="none" stroke="#00E5FF" stroke-width="35" stroke-linejoin="round"/><line x1="550" y1="450" x2="550" y2="550" stroke="#00E5FF" stroke-width="35" stroke-linecap="round"/><line x1="670" y1="450" x2="670" y2="550" stroke="#00E5FF" stroke-width="35" stroke-linecap="round"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 599 B

After

Width:  |  Height:  |  Size: 599 B

Before After
Before After

View file

@ -1,4 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 1200 1200"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 1200 1200">
<title>Nav Analytics</title> <title>Nav Analytics</title>
<line x1="350" y1="850" x2="850" y2="850" stroke="#FF1610" stroke-width="40" stroke-linecap="round"/><line x1="420" y1="700" x2="420" y2="850" stroke="#FF1610" stroke-width="35" stroke-linecap="round"/><line x1="600" y1="500" x2="600" y2="850" stroke="#FF1610" stroke-width="35" stroke-linecap="round"/><line x1="780" y1="400" x2="780" y2="850" stroke="#FF1610" stroke-width="35" stroke-linecap="round"/> <line x1="350" y1="850" x2="850" y2="850" stroke="#000000" stroke-width="40" stroke-linecap="round"/><line x1="420" y1="700" x2="420" y2="850" stroke="#000000" stroke-width="35" stroke-linecap="round"/><line x1="600" y1="500" x2="600" y2="850" stroke="#000000" stroke-width="35" stroke-linecap="round"/><line x1="780" y1="400" x2="780" y2="850" stroke="#000000" stroke-width="35" stroke-linecap="round"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 532 B

After

Width:  |  Height:  |  Size: 532 B

Before After
Before After

View file

@ -1,4 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 1200 1200"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 1200 1200">
<title>Nav Approvals</title> <title>Nav Approvals</title>
<path d="M 240 640 L 500 880 L 960 320" fill="none" stroke="#FF1610" stroke-width="90" stroke-linecap="round" stroke-linejoin="round"/> <path d="M 240 640 L 500 880 L 960 320" fill="none" stroke="#000000" stroke-width="90" stroke-linecap="round" stroke-linejoin="round"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 264 B

After

Width:  |  Height:  |  Size: 264 B

Before After
Before After

View file

@ -1,4 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 1200 1200"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 1200 1200">
<title>Nav Audit</title> <title>Nav Audit</title>
<path d="M 500 350 L 700 350 L 700 500 L 800 500 L 600 850 L 400 500 L 500 500 Z" fill="none" stroke="#FF1610" stroke-width="35" stroke-linejoin="round"/> <path d="M 500 350 L 700 350 L 700 500 L 800 500 L 600 850 L 400 500 L 500 500 Z" fill="none" stroke="#000000" stroke-width="35" stroke-linejoin="round"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 278 B

After

Width:  |  Height:  |  Size: 278 B

Before After
Before After

View file

@ -1,4 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 1200 1200"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 1200 1200">
<title>Nav Calendar</title> <title>Nav Calendar</title>
<rect x="350" y="400" width="500" height="450" rx="30" fill="none" stroke="#FF1610" stroke-width="40"/><line x1="350" y1="520" x2="850" y2="520" stroke="#FF1610" stroke-width="30"/><line x1="450" y1="400" x2="450" y2="350" stroke="#FF1610" stroke-width="35" stroke-linecap="round"/><line x1="750" y1="400" x2="750" y2="350" stroke="#FF1610" stroke-width="35" stroke-linecap="round"/><circle cx="500" cy="620" r="20" fill="#FF1610"/><circle cx="600" cy="620" r="20" fill="#FF1610"/><circle cx="700" cy="620" r="20" fill="#FF1610"/> <rect x="350" y="400" width="500" height="450" rx="30" fill="none" stroke="#000000" stroke-width="40"/><line x1="350" y1="520" x2="850" y2="520" stroke="#000000" stroke-width="30"/><line x1="450" y1="400" x2="450" y2="350" stroke="#000000" stroke-width="35" stroke-linecap="round"/><line x1="750" y1="400" x2="750" y2="350" stroke="#000000" stroke-width="35" stroke-linecap="round"/><circle cx="500" cy="620" r="20" fill="#000000"/><circle cx="600" cy="620" r="20" fill="#000000"/><circle cx="700" cy="620" r="20" fill="#000000"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 657 B

After

Width:  |  Height:  |  Size: 657 B

Before After
Before After

View file

@ -1,7 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 1200 1200"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 1200 1200">
<title>Nav Chat</title> <title>Nav Chat</title>
<path d="M 220 300 A 80 80 0 0 1 300 220 L 900 220 A 80 80 0 0 1 980 300 L 980 660 A 80 80 0 0 1 900 740 L 520 740 L 340 920 L 340 740 L 300 740 A 80 80 0 0 1 220 660 Z" fill="none" stroke="#FF1610" stroke-width="55" stroke-linejoin="round"/> <path d="M 220 300 A 80 80 0 0 1 300 220 L 900 220 A 80 80 0 0 1 980 300 L 980 660 A 80 80 0 0 1 900 740 L 520 740 L 340 920 L 340 740 L 300 740 A 80 80 0 0 1 220 660 Z" fill="none" stroke="#000000" stroke-width="55" stroke-linejoin="round"/>
<circle cx="450" cy="480" r="45" fill="#FF1610"/> <circle cx="450" cy="480" r="45" fill="#000000"/>
<circle cx="600" cy="480" r="45" fill="#FF1610"/> <circle cx="600" cy="480" r="45" fill="#000000"/>
<circle cx="750" cy="480" r="45" fill="#FF1610"/> <circle cx="750" cy="480" r="45" fill="#000000"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 522 B

After

Width:  |  Height:  |  Size: 522 B

Before After
Before After

View file

@ -1,4 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 1200 1200"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 1200 1200">
<title>Nav Compose</title> <title>Nav Compose</title>
<path d="M 400 800 L 350 850 L 400 850 L 850 400 L 800 350 L 350 800" fill="none" stroke="#FF1610" stroke-width="40" stroke-linecap="round" stroke-linejoin="round"/><line x1="750" y1="400" x2="800" y2="450" stroke="#FF1610" stroke-width="30"/> <path d="M 400 800 L 350 850 L 400 850 L 850 400 L 800 350 L 350 800" fill="none" stroke="#000000" stroke-width="40" stroke-linecap="round" stroke-linejoin="round"/><line x1="750" y1="400" x2="800" y2="450" stroke="#000000" stroke-width="30"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 369 B

After

Width:  |  Height:  |  Size: 369 B

Before After
Before After

View file

@ -1,4 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 1200 1200"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 1200 1200">
<title>Nav Connections</title> <title>Nav Connections</title>
<circle cx="450" cy="500" r="80" fill="none" stroke="#FF1610" stroke-width="35"/><circle cx="750" cy="700" r="80" fill="none" stroke="#FF1610" stroke-width="35"/><line x1="500" y1="550" x2="700" y2="650" stroke="#FF1610" stroke-width="35" stroke-linecap="round"/> <circle cx="450" cy="500" r="80" fill="none" stroke="#000000" stroke-width="35"/><circle cx="750" cy="700" r="80" fill="none" stroke="#000000" stroke-width="35"/><line x1="500" y1="550" x2="700" y2="650" stroke="#000000" stroke-width="35" stroke-linecap="round"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 393 B

After

Width:  |  Height:  |  Size: 393 B

Before After
Before After

View file

@ -1,4 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 1200 1200"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 1200 1200">
<title>Nav Files</title> <title>Nav Files</title>
<path d="M 220 380 L 470 380 L 560 470 L 980 470 L 980 860 A 60 60 0 0 1 920 920 L 280 920 A 60 60 0 0 1 220 860 Z" fill="none" stroke="#FF1610" stroke-width="60" stroke-linejoin="round" stroke-linecap="round"/> <path d="M 220 380 L 470 380 L 560 470 L 980 470 L 980 860 A 60 60 0 0 1 920 920 L 280 920 A 60 60 0 0 1 220 860 Z" fill="none" stroke="#000000" stroke-width="60" stroke-linejoin="round" stroke-linecap="round"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 336 B

After

Width:  |  Height:  |  Size: 336 B

Before After
Before After

View file

@ -1,4 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 1200 1200"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 1200 1200">
<title>Nav Home</title> <title>Nav Home</title>
<path d="M 600 350 L 850 550 L 850 850 L 350 850 L 350 550 Z" fill="none" stroke="#FF1610" stroke-width="40" stroke-linejoin="round"/><line x1="600" y1="350" x2="600" y2="850" stroke="#FF1610" stroke-width="30"/> <path d="M 600 350 L 850 550 L 850 850 L 350 850 L 350 550 Z" fill="none" stroke="#000000" stroke-width="40" stroke-linejoin="round"/><line x1="600" y1="350" x2="600" y2="850" stroke="#000000" stroke-width="30"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 335 B

After

Width:  |  Height:  |  Size: 335 B

Before After
Before After

View file

@ -1,4 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 1200 1200"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 1200 1200">
<title>Nav Inbox</title> <title>Nav Inbox</title>
<path d="M 350 400 L 850 400 L 850 700 L 700 700 L 600 800 L 500 700 L 350 700 Z" fill="none" stroke="#FF1610" stroke-width="40" stroke-linejoin="round"/> <path d="M 350 400 L 850 400 L 850 700 L 700 700 L 600 800 L 500 700 L 350 700 Z" fill="none" stroke="#000000" stroke-width="40" stroke-linejoin="round"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 278 B

After

Width:  |  Height:  |  Size: 278 B

Before After
Before After

View file

@ -1,4 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 1200 1200"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 1200 1200">
<title>Nav More</title> <title>Nav More</title>
<circle cx="500" cy="600" r="30" fill="#FF1610"/><circle cx="600" cy="600" r="30" fill="#FF1610"/><circle cx="700" cy="600" r="30" fill="#FF1610"/> <circle cx="500" cy="600" r="30" fill="#000000"/><circle cx="600" cy="600" r="30" fill="#000000"/><circle cx="700" cy="600" r="30" fill="#000000"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 270 B

After

Width:  |  Height:  |  Size: 270 B

Before After
Before After

View file

@ -1,4 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 1200 1200"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 1200 1200">
<title>Nav Search</title> <title>Nav Search</title>
<circle cx="550" cy="550" r="200" fill="none" stroke="#FF1610" stroke-width="40"/><line x1="700" y1="700" x2="850" y2="850" stroke="#FF1610" stroke-width="40" stroke-linecap="round"/> <circle cx="550" cy="550" r="200" fill="none" stroke="#000000" stroke-width="40"/><line x1="700" y1="700" x2="850" y2="850" stroke="#000000" stroke-width="40" stroke-linecap="round"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 308 B

After

Width:  |  Height:  |  Size: 308 B

Before After
Before After

View file

@ -1,4 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 1200 1200"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 1200 1200">
<title>Nav Settings</title> <title>Nav Settings</title>
<circle cx="600" cy="600" r="150" fill="none" stroke="#FF1610" stroke-width="40"/><g stroke="#FF1610" stroke-width="35" stroke-linecap="round"><line x1="600" y1="350" x2="600" y2="420"/><line x1="600" y1="780" x2="600" y2="850"/><line x1="350" y1="600" x2="420" y2="600"/><line x1="780" y1="600" x2="850" y2="600"/><line x1="420" y1="420" x2="470" y2="470"/><line x1="730" y1="730" x2="780" y2="780"/><line x1="420" y1="780" x2="470" y2="730"/><line x1="730" y1="470" x2="780" y2="420"/></g> <circle cx="600" cy="600" r="150" fill="none" stroke="#000000" stroke-width="40"/><g stroke="#000000" stroke-width="35" stroke-linecap="round"><line x1="600" y1="350" x2="600" y2="420"/><line x1="600" y1="780" x2="600" y2="850"/><line x1="350" y1="600" x2="420" y2="600"/><line x1="780" y1="600" x2="850" y2="600"/><line x1="420" y1="420" x2="470" y2="470"/><line x1="730" y1="730" x2="780" y2="780"/><line x1="420" y1="780" x2="470" y2="730"/><line x1="730" y1="470" x2="780" y2="420"/></g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 618 B

After

Width:  |  Height:  |  Size: 618 B

Before After
Before After

View file

@ -1,4 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 1200 1200"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 1200 1200">
<title>Nav Team</title> <title>Nav Team</title>
<circle cx="500" cy="500" r="70" fill="none" stroke="#FF1610" stroke-width="35"/><circle cx="700" cy="500" r="70" fill="none" stroke="#FF1610" stroke-width="35"/><path d="M 400 750 Q 400 650 500 650 Q 600 650 600 750" fill="none" stroke="#FF1610" stroke-width="35"/><path d="M 600 750 Q 600 650 700 650 Q 800 650 800 750" fill="none" stroke="#FF1610" stroke-width="35"/> <circle cx="500" cy="500" r="70" fill="none" stroke="#000000" stroke-width="35"/><circle cx="700" cy="500" r="70" fill="none" stroke="#000000" stroke-width="35"/><path d="M 400 750 Q 400 650 500 650 Q 600 650 600 750" fill="none" stroke="#000000" stroke-width="35"/><path d="M 600 750 Q 600 650 700 650 Q 800 650 800 750" fill="none" stroke="#000000" stroke-width="35"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 493 B

After

Width:  |  Height:  |  Size: 493 B

Before After
Before After

View file

@ -1,4 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 1200 1200"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 1200 1200">
<title>Nav Video</title> <title>Nav Video</title>
<rect x="260" y="400" width="680" height="400" rx="70" fill="none" stroke="#FF1610" stroke-width="70"/><path d="M 940 600 L 1120 480 L 1120 720 Z" fill="#FF1610"/><path d="M 360 470 L 360 730" stroke="#FF1610" stroke-width="40" stroke-linecap="round"/><path d="M 480 470 L 480 730" stroke="#FF1610" stroke-width="40" stroke-linecap="round"/> <rect x="260" y="400" width="680" height="400" rx="70" fill="none" stroke="#000000" stroke-width="70"/><path d="M 940 600 L 1120 480 L 1120 720 Z" fill="#000000"/><path d="M 360 470 L 360 730" stroke="#000000" stroke-width="40" stroke-linecap="round"/><path d="M 480 470 L 480 730" stroke="#000000" stroke-width="40" stroke-linecap="round"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 466 B

After

Width:  |  Height:  |  Size: 466 B

Before After
Before After

View file

@ -3,8 +3,8 @@
<defs> <defs>
<g id="ca"> <g id="ca">
<g transform="rotate(-17.5 0 0)"> <g transform="rotate(-17.5 0 0)">
<circle cx="0" cy="0" r="45" fill="none" stroke="#FF1610" stroke-width="10"/> <circle cx="0" cy="0" r="45" fill="none" stroke="#000000" stroke-width="10"/>
<path d="M 0 -38 L -28 38 M 0 -38 L 28 38 M -34 0 L 34 0" fill="none" stroke="#FF1610" stroke-width="12" stroke-linecap="round"/> <path d="M 0 -38 L -28 38 M 0 -38 L 28 38 M -34 0 L 34 0" fill="none" stroke="#000000" stroke-width="12" stroke-linecap="round"/>
</g> </g>
</g> </g>
</defs> </defs>

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Before After
Before After

View file

@ -1,8 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 1700 1700"> <svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 1700 1700">
<g transform="rotate(-17.5 850 850)"> <g transform="rotate(-17.5 850 850)">
<path d="M 850 500 A 350 350 0 0 1 1200 850" fill="none" stroke="#FF1610" stroke-width="70" stroke-linecap="round"/> <path d="M 850 500 A 350 350 0 0 1 1200 850" fill="none" stroke="#000000" stroke-width="70" stroke-linecap="round"/>
<path d="M 1200 850 A 350 350 0 0 1 850 1200" fill="none" stroke="#FF1610" stroke-width="70" stroke-linecap="round" opacity="0.2"/> <path d="M 1200 850 A 350 350 0 0 1 850 1200" fill="none" stroke="#000000" stroke-width="70" stroke-linecap="round" opacity="0.2"/>
<path d="M 850 1200 A 350 350 0 0 1 500 850" fill="none" stroke="#FF1610" stroke-width="70" stroke-linecap="round" opacity="0.2"/> <path d="M 850 1200 A 350 350 0 0 1 500 850" fill="none" stroke="#000000" stroke-width="70" stroke-linecap="round" opacity="0.2"/>
<path d="M 500 850 A 350 350 0 0 1 850 500" fill="none" stroke="#FF1610" stroke-width="70" stroke-linecap="round" opacity="0.2"/> <path d="M 500 850 A 350 350 0 0 1 850 500" fill="none" stroke="#000000" stroke-width="70" stroke-linecap="round" opacity="0.2"/>
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 667 B

After

Width:  |  Height:  |  Size: 667 B

Before After
Before After

View file

@ -1,40 +1,44 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 240 240" width="240" height="240" role="img" aria-labelledby="t"> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 400 400" width="400" height="400" role="img" aria-labelledby="t">
<title id="t">T-HUB</title> <title id="t">T-HUB</title>
<circle cx="120" cy="120" r="118" fill="#000"/> <defs>
<circle cx="120" cy="120" r="82" fill="none" stroke="#fff" stroke-width="2" stroke-dasharray="3 7" opacity=".55"/> <!-- Dome tent in the hand-inked style of the acampada26s.net mark:
curved poles with ball ends, centre seam, hatched panel, door.
<!-- cables: each leaves through a tent door and runs to the switch --> Base midpoint at 0,0. -->
<g fill="none" stroke="#00e5ff" stroke-width="4" stroke-linecap="round"> <g id="tienda" stroke-linecap="round" stroke-linejoin="round">
<path d="M49 94 C 52 122, 74 130, 96 130"/> <path fill="none" d="M-58 0 Q-56 -66 -1 -72 Q55 -66 58 0" stroke-width="7"/>
<path d="M191 94 C 188 122, 166 130, 144 130"/> <path fill="none" d="M-64 1 Q0 -3 64 1" stroke-width="6"/>
<path d="M120 216 C 120 196, 120 168, 120 140"/> <path fill="none" d="M-44 0 Q-30 -58 -1 -72" stroke-width="4.5"/>
<path fill="none" d="M44 0 Q30 -58 -1 -72" stroke-width="4.5"/>
<path d="M-15 0 Q-14 -30 0 -33 Q14 -30 15 0 Z" stroke-width="4"/>
<path fill="none" d="M-50 -14 L-41 -25 M-50 -4 L-37 -19 M-43 -1 L-33 -13 M-52 -27 L-45 -36" stroke-width="2.6"/>
<path fill="none" d="M28 -50 L37 -42 M24 -40 L36 -30 M22 -29 L34 -19" stroke-width="2.6"/>
<circle cx="-64" cy="1" r="5.5" stroke="none"/>
<circle cx="64" cy="1" r="5.5" stroke="none"/>
<circle cx="-1" cy="-73" r="5.5" stroke="none"/>
</g>
<g id="marca" stroke-linecap="round" stroke-linejoin="round">
<!-- cables: out of each tent door to the switch -->
<path fill="none" d="M105 150 Q112 206 168 214" stroke-width="5"/>
<path fill="none" d="M295 150 Q288 206 232 214" stroke-width="5"/>
<path fill="none" d="M200 318 Q197 280 200 236" stroke-width="5"/>
<!-- antenna -->
<path fill="none" d="M200 200 Q198 160 200 118" stroke-width="6"/>
<path fill="none" d="M184 98 Q200 82 216 98" stroke-width="5"/>
<path fill="none" d="M171 88 Q200 58 229 88" stroke-width="5"/>
<circle cx="200" cy="112" r="7" stroke="none"/>
<!-- switch -->
<path d="M168 201 L233 200 L234 235 L167 236 Z" stroke-width="6" fill="#fff"/>
<path d="M179 212 h9 v11 h-9 z M196 212 h9 v11 h-9 z M213 212 h9 v11 h-9 z" stroke="none"/>
<use xlink:href="#tienda" transform="translate(105,150)"/>
<use xlink:href="#tienda" transform="translate(295,150)"/>
<use xlink:href="#tienda" transform="translate(200,340)"/>
</g>
</defs>
<!-- neon offset underneath, ink on top, as on acampada26s.net -->
<g transform="translate(7,7)" stroke="#00e5ff" fill="#00e5ff">
<use xlink:href="#marca"/>
</g> </g>
<g stroke="#000" fill="#000">
<!-- tents --> <use xlink:href="#marca"/>
<g stroke="#fff" stroke-width="3" stroke-linejoin="round">
<polygon points="19,99 49,55 79,99" fill="#000"/>
<polygon points="161,99 191,55 221,99" fill="#000"/>
<polygon points="90,221 120,177 150,221" fill="#000"/>
</g>
<g fill="#00e5ff">
<polygon points="40,99 49,80 58,99"/>
<polygon points="182,99 191,80 200,99"/>
<polygon points="111,221 120,202 129,221"/>
</g>
<!-- antenna -->
<line x1="120" y1="120" x2="120" y2="70" stroke="#fff" stroke-width="4" stroke-linecap="round"/>
<circle cx="120" cy="68" r="5" fill="#00e5ff"/>
<g fill="none" stroke="#00e5ff" stroke-width="3" stroke-linecap="round">
<path d="M106 56 A 18 18 0 0 1 134 56"/>
<path d="M97 46 A 30 30 0 0 1 143 46"/>
</g>
<!-- switch -->
<rect x="94" y="118" width="52" height="24" rx="3" fill="#fff"/>
<g fill="#000">
<rect x="101" y="125" width="9" height="9"/>
<rect x="115.5" y="125" width="9" height="9"/>
<rect x="130" y="125" width="9" height="9"/>
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Before After
Before After

View file

@ -49,7 +49,7 @@ function Shell({ children }: { children: ReactNode }): React.ReactElement {
scrollPositions.set(pathname, { main: main.scrollTop, nested: scrollableChildren(main).map((element) => element.scrollTop) }); scrollPositions.set(pathname, { main: main.scrollTop, nested: scrollableChildren(main).map((element) => element.scrollTop) });
}; };
}, [pathname, mobile]); }, [pathname, mobile]);
const title = titles[pathname.split("/")[1] ?? ""] ?? "Tactical Media Broadcast Hub"; const title = titles[pathname.split("/")[1] ?? ""] ?? "T-HUB";
return ( return (
<div className="flex h-dvh min-w-0 overflow-hidden lg:h-screen"> <div className="flex h-dvh min-w-0 overflow-hidden lg:h-screen">
<Sidebar /> <Sidebar />

View file

@ -48,7 +48,7 @@ export default function MorePage(): React.ReactElement {
<section className="flex items-center gap-4 px-5 py-5"> <section className="flex items-center gap-4 px-5 py-5">
<div className="scale-125"><Avatar handle={session?.user.displayName || session?.user.username || "AP"} /></div> <div className="scale-125"><Avatar handle={session?.user.displayName || session?.user.username || "AP"} /></div>
<div className="min-w-0 flex-1 pl-2"> <div className="min-w-0 flex-1 pl-2">
<h1 className="truncate text-xl font-bold">{session?.user.displayName || session?.user.username || "Tactical Media Broadcast Hub"}</h1> <h1 className="truncate text-xl font-bold">{session?.user.displayName || session?.user.username || "T-HUB"}</h1>
<p className="truncate text-xs text-text-faint">@{session?.user.username || "offline"}{session?.user.email ? ` · ${session.user.email}` : ""}</p> <p className="truncate text-xs text-text-faint">@{session?.user.username || "offline"}{session?.user.email ? ` · ${session.user.email}` : ""}</p>
<div className="mt-2 flex items-center gap-2"><span className="rounded-full bg-accent px-2.5 py-1 text-[11px] font-bold uppercase text-white">{session?.role || "Preview"}</span><span className="truncate text-xs text-text-dim">{session?.workspace.name || "Studio"}</span></div> <div className="mt-2 flex items-center gap-2"><span className="rounded-full bg-accent px-2.5 py-1 text-[11px] font-bold uppercase text-white">{session?.role || "Preview"}</span><span className="truncate text-xs text-text-dim">{session?.workspace.name || "Studio"}</span></div>
</div> </div>

View file

@ -221,15 +221,15 @@ export default function OnboardingPage(): React.ReactElement {
<div className="mb-5"> <div className="mb-5">
<div className="-m-6 mb-5 overflow-hidden bg-black"> <div className="-m-6 mb-5 overflow-hidden bg-black">
<div className="flex items-center gap-5 px-8 py-8"> <div className="flex items-center gap-5 px-8 py-8">
<LogoMark size={96} className="shrink-0 text-accent" /> <LogoMark size={96} className="shrink-0 text-white" />
<div className="min-w-0"> <div className="min-w-0">
<div className="text-xl font-semibold leading-tight text-white">Horizontal Collaborative Broadcast System</div> <div className="text-xl font-semibold leading-tight text-white">Horizontal Collaborative Broadcast System</div>
<div className="mt-1 text-xs uppercase tracking-wider text-text-faint">Tactical Media Broadcast Hub</div> <div className="mt-1 text-xs uppercase tracking-wider text-[#00e5ff]">T-HUB</div>
</div> </div>
</div> </div>
</div> </div>
<div className="text-center"> <div className="text-center">
<h1 className="text-2xl font-semibold tracking-tight">Tactical Media Broadcast Hub</h1> <h1 className="text-2xl font-semibold tracking-tight">T-HUB</h1>
<p className="mt-1 text-2xs text-text-faint">Your platform. Their feeds. No algorithm in between.</p> <p className="mt-1 text-2xs text-text-faint">Your platform. Their feeds. No algorithm in between.</p>
</div> </div>
</div> </div>

View file

@ -8,23 +8,25 @@
} }
@theme { @theme {
/* T-HUB: the acampada26s.net palette (black, white, neon) on a dark base. */ /* T-HUB: the acampada26s.net palette. White page, black ink and borders,
--color-bg: #000; neon #00e5ff for hover, focus and the offset shadows. */
--color-surface: #0d0d0d; --color-bg: #fff;
--color-surface-2: #181818; --color-surface: #fff;
--color-border: #3d3d3d; --color-surface-2: #f2f2f2;
--color-border-subtle: #262626; --color-border: #000;
--color-text: #fff; --color-border-subtle: #d4d4d4;
--color-text-dim: #b3b3b3; --color-text: #000;
--color-text-faint: #808080; --color-text-dim: #333;
--color-accent: #00e5ff; --color-text-faint: #666;
--color-accent-hover: #5cefff; --color-accent: #000;
--color-accent-dim: rgb(0 229 255 / 0.15); --color-accent-hover: #222;
--color-live: oklch(0.72 0.19 145); --color-accent-dim: rgb(0 229 255 / 0.28);
--color-warn: oklch(0.78 0.16 85); --color-neon: #00e5ff;
--color-danger: oklch(0.55 0.24 15); --color-live: #007a3d;
--color-added: oklch(0.72 0.16 145); --color-warn: #8a5a00;
--color-removed: oklch(0.55 0.24 15); --color-danger: #c4001a;
--color-added: #007a3d;
--color-removed: #c4001a;
--font-sans: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; --font-sans: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
--font-mono: ui-monospace, "SF Mono", Menlo, monospace; --font-mono: ui-monospace, "SF Mono", Menlo, monospace;
@ -51,7 +53,7 @@
} }
html { html {
color-scheme: dark; color-scheme: light;
} }
body { body {
@ -72,13 +74,20 @@ h1, h2 {
letter-spacing: 0.01em; letter-spacing: 0.01em;
} }
h1 { h1 {
text-shadow: 0.04em 0.04em 0 var(--color-accent); font-size: 1.75rem;
line-height: 1.05;
text-shadow: 0.01em 0.01em 0 var(--color-neon), 0.02em 0.02em 0 var(--color-neon), 0.03em 0.03em 0 var(--color-neon), 0.04em 0.04em 0 var(--color-neon);
} }
/* Neon fills need dark text; unlayered so it outranks the text-white utility. */ /* Buttons as on acampada26s.net: hard offset shadow, neon on hover. */
.bg-accent.text-white, button.bg-accent, a.bg-accent {
.bg-accent .text-white { box-shadow: 0 3px 0 var(--color-neon);
color: #000; }
button.bg-accent:hover, a.bg-accent:hover, button.bg-accent:focus-visible, a.bg-accent:focus-visible {
box-shadow: 0 5px 0 var(--color-neon);
}
:focus-visible {
outline-color: var(--color-neon);
} }
@media (max-width: 1023px) { @media (max-width: 1023px) {

View file

@ -324,11 +324,11 @@ export default function JoinWorkspacePage({ params }: { params: { token: string
<Card className="w-[520px] max-w-full p-6"> <Card className="w-[520px] max-w-full p-6">
<div className="mb-5 text-center"> <div className="mb-5 text-center">
<img <img
src="/brand/hero.png" src="/brand/t-hub.svg"
alt="Tactical Media Broadcast Hub — arrows from a circle, warm red on black" alt="T-HUB: three tents wired to a switch with an antenna"
width={1024} width={400}
height={1024} height={400}
className="mx-auto mb-3 h-20 w-20 rounded-lg object-cover" className="mx-auto mb-3 h-20 w-20"
/> />
<h1 className="text-xl font-semibold tracking-tight">Join {info.workspaceName}</h1> <h1 className="text-xl font-semibold tracking-tight">Join {info.workspaceName}</h1>
<p className="mt-1 text-2xs text-text-faint"> <p className="mt-1 text-2xs text-text-faint">

View file

@ -3,8 +3,8 @@ import type { Metadata, Viewport } from "next";
import "./globals.css"; import "./globals.css";
export const metadata: Metadata = { export const metadata: Metadata = {
title: "Tactical Media Broadcast Hub", title: "T-HUB",
description: "Tactical Media Broadcast Hub — post, schedule and amplify across every network you refuse to be owned by.", description: "T-HUB — post, schedule and amplify across every network you refuse to be owned by. Based on Tactical Media Broadcast Hub.",
icons: { icon: "/brand/favicon.svg" }, icons: { icon: "/brand/favicon.svg" },
}; };
@ -13,7 +13,7 @@ export const viewport: Viewport = {
initialScale: 1, initialScale: 1,
viewportFit: "cover", viewportFit: "cover",
interactiveWidget: "resizes-content", interactiveWidget: "resizes-content",
themeColor: "#000000", themeColor: "#ffffff",
}; };
export default function RootLayout({ children }: { children: ReactNode }): React.ReactNode { export default function RootLayout({ children }: { children: ReactNode }): React.ReactNode {

View file

@ -40,7 +40,7 @@ export default function LoginPage(): React.ReactElement {
<Card className="w-[420px] max-w-full p-6"> <Card className="w-[420px] max-w-full p-6">
<div className="mb-5 text-center"> <div className="mb-5 text-center">
<h1 className="text-xl font-semibold tracking-tight">Sign in</h1> <h1 className="text-xl font-semibold tracking-tight">Sign in</h1>
<p className="mt-1 text-2xs text-text-faint">Tactical Media Broadcast Hub</p> <p className="mt-1 text-2xs text-text-faint">T-HUB</p>
</div> </div>
<form onSubmit={(e) => void submit(e)}> <form onSubmit={(e) => void submit(e)}>
<div className="space-y-2"> <div className="space-y-2">

View file

@ -116,7 +116,7 @@ function ManualLanding(): React.ReactElement {
<header className="sticky top-0 z-10 border-b border-border-subtle bg-surface"> <header className="sticky top-0 z-10 border-b border-border-subtle bg-surface">
<div className="mx-auto flex max-w-2xl items-center gap-3 px-4 py-4"> <div className="mx-auto flex max-w-2xl items-center gap-3 px-4 py-4">
<Logo size={26} withText={false} /> <Logo size={26} withText={false} />
<span className="flex-1 truncate text-xs font-bold tracking-tight text-accent">Tactical Media Broadcast Hub</span> <span className="flex-1 truncate text-xs font-bold tracking-tight text-accent">T-HUB</span>
<div className="flex shrink-0 items-center rounded-md border border-border bg-surface-2 p-0.5" role="group" aria-label={t({ es: "Idioma", en: "Language" })}> <div className="flex shrink-0 items-center rounded-md border border-border bg-surface-2 p-0.5" role="group" aria-label={t({ es: "Idioma", en: "Language" })}>
{(["es", "en"] as const).map((code) => ( {(["es", "en"] as const).map((code) => (
<button <button

View file

@ -119,10 +119,10 @@ export default function SubmitPage({ params }: { params: { token: string } }): R
if (phase === "checking") { if (phase === "checking") {
return ( return (
<main className="flex min-h-dvh items-center justify-center bg-[#060403] px-6"> <main className="flex min-h-dvh items-center justify-center bg-white px-6">
<div className="flex flex-col items-center gap-3"> <div className="flex flex-col items-center gap-3">
<Loading size={32} label="Opening the box…" /> <Loading size={32} label="Opening the box…" />
<span className="text-2xs text-[#a4a09e]">Opening the box…</span> <span className="text-2xs text-[#555]">Opening the box…</span>
</div> </div>
</main> </main>
); );
@ -130,7 +130,7 @@ export default function SubmitPage({ params }: { params: { token: string } }): R
if (phase === "unreachable") { if (phase === "unreachable") {
return ( return (
<main className="flex min-h-dvh items-center justify-center bg-[#060403] p-6"> <main className="flex min-h-dvh items-center justify-center bg-white p-6">
<DeadCard <DeadCard
tone="warn" tone="warn"
title="Can't reach the server" title="Can't reach the server"
@ -143,7 +143,7 @@ export default function SubmitPage({ params }: { params: { token: string } }): R
if (phase === "gone" || box === null) { if (phase === "gone" || box === null) {
return ( return (
<main className="flex min-h-dvh items-center justify-center bg-[#060403] p-6"> <main className="flex min-h-dvh items-center justify-center bg-white p-6">
<DeadCard <DeadCard
tone="danger" tone="danger"
title="This box isn't open" title="This box isn't open"
@ -154,7 +154,7 @@ export default function SubmitPage({ params }: { params: { token: string } }): R
} }
return ( return (
<main className="min-h-dvh bg-[#060403] px-4 py-10 sm:px-6"> <main className="min-h-dvh bg-white px-4 py-10 sm:px-6">
<SubmitForm key={token} token={token} box={box} /> <SubmitForm key={token} token={token} box={box} />
</main> </main>
); );
@ -162,16 +162,16 @@ export default function SubmitPage({ params }: { params: { token: string } }): R
function DeadCard({ tone, title, body, action }: { tone: "warn" | "danger"; title: string; body: string; action?: React.ReactNode }): React.ReactElement { function DeadCard({ tone, title, body, action }: { tone: "warn" | "danger"; title: string; body: string; action?: React.ReactNode }): React.ReactElement {
return ( return (
<div className="w-full max-w-md rounded-lg border border-[#2a2320] bg-[#0F0A09] p-6 text-center"> <div className="w-full max-w-md rounded-lg border border-[#d4d4d4] bg-[#f2f2f2] p-6 text-center">
<div <div
className={`mx-auto mb-4 flex h-12 w-12 items-center justify-center rounded-full text-lg ${ className={`mx-auto mb-4 flex h-12 w-12 items-center justify-center rounded-full text-lg ${
tone === "warn" ? "bg-[#00E5FF]/15 text-[#00E5FF]" : "bg-[#00E5FF]/15 text-[#00E5FF]" tone === "warn" ? "bg-[#00E5FF]/15 text-[#00798a]" : "bg-[#00E5FF]/15 text-[#00798a]"
}`} }`}
> >
{tone === "warn" ? "!" : "✕"} {tone === "warn" ? "!" : "✕"}
</div> </div>
<h1 className="text-base font-semibold text-[#f5efed]">{title}</h1> <h1 className="text-base font-semibold text-black">{title}</h1>
<p className="mt-2 text-xs leading-relaxed text-[#a4a09e]">{body}</p> <p className="mt-2 text-xs leading-relaxed text-[#555]">{body}</p>
{action} {action}
</div> </div>
); );
@ -282,13 +282,13 @@ function SubmitForm({ token, box }: { token: string; box: SubmissionBoxInfo }):
if (phase === "sent" && done !== null) { if (phase === "sent" && done !== null) {
return ( return (
<div className="mx-auto flex w-full max-w-xl flex-col items-center gap-4 rounded-lg border border-[#2a2320] bg-[#0F0A09] p-8 text-center"> <div className="mx-auto flex w-full max-w-xl flex-col items-center gap-4 rounded-lg border border-[#d4d4d4] bg-[#f2f2f2] p-8 text-center">
<LogoMark size={44} className="text-[#00E5FF]" title="" /> <LogoMark size={44} className="text-black" title="" />
<h1 className="text-xl font-semibold tracking-tight text-[#f5efed]">Received</h1> <h1 className="text-xl font-semibold tracking-tight text-black">Received</h1>
<p className="max-w-sm text-sm leading-relaxed text-[#c7c3c1]"> <p className="max-w-sm text-sm leading-relaxed text-[#333]">
Received — the collective will review it. Nothing is published until they approve it. Received — the collective will review it. Nothing is published until they approve it.
</p> </p>
<p className="max-w-sm text-2xs leading-relaxed text-[#a4a09e]"> <p className="max-w-sm text-2xs leading-relaxed text-[#555]">
Your footage stays under {box.licenseDefault}: it may be shared and remixed with attribution. Your footage stays under {box.licenseDefault}: it may be shared and remixed with attribution.
</p> </p>
</div> </div>
@ -301,13 +301,13 @@ function SubmitForm({ token, box }: { token: string; box: SubmissionBoxInfo }):
return ( return (
<form <form
onSubmit={(event) => void submit(event)} onSubmit={(event) => void submit(event)}
className="mx-auto flex w-full max-w-xl flex-col gap-6 rounded-lg border border-[#2a2320] bg-[#0F0A09] p-6 sm:p-8" className="mx-auto flex w-full max-w-xl flex-col gap-6 rounded-lg border border-[#d4d4d4] bg-[#f2f2f2] p-6 sm:p-8"
> >
<header className="flex flex-col items-center gap-3 text-center"> <header className="flex flex-col items-center gap-3 text-center">
<LogoMark size={36} className="text-[#00E5FF]" title="Tactical Media Broadcast Hub" /> <LogoMark size={36} className="text-black" />
<div> <div>
<h1 className="text-xl font-semibold tracking-tight text-[#f5efed]">Send footage to the collective</h1> <h1 className="text-xl font-semibold tracking-tight text-black">Send footage to the collective</h1>
<p className="mt-1 text-xs leading-relaxed text-[#a4a09e]"> <p className="mt-1 text-xs leading-relaxed text-[#555]">
No account needed. mp4 or webm video up to 200 MiB, jpeg or png photo up to 50 MiB. No account needed. mp4 or webm video up to 200 MiB, jpeg or png photo up to 50 MiB.
</p> </p>
</div> </div>
@ -339,13 +339,13 @@ function SubmitForm({ token, box }: { token: string; box: SubmissionBoxInfo }):
}} }}
className={`flex min-h-[180px] flex-col items-center justify-center gap-2 rounded-lg border-2 border-dashed px-4 py-8 text-center transition-colors duration-150 ${ className={`flex min-h-[180px] flex-col items-center justify-center gap-2 rounded-lg border-2 border-dashed px-4 py-8 text-center transition-colors duration-150 ${
uploading uploading
? "cursor-not-allowed border-[#3a312e] opacity-60" ? "cursor-not-allowed border-black opacity-60"
: "cursor-pointer border-[#3a312e] hover:border-[#00E5FF] focus-visible:border-[#00E5FF]" : "cursor-pointer border-black hover:border-[#00E5FF] focus-visible:border-[#00E5FF]"
}`} }`}
> >
{uploading ? ( {uploading ? (
<div className="w-full max-w-md space-y-2"> <div className="w-full max-w-md space-y-2">
<span className="inline-flex items-center gap-2 text-xs text-[#c7c3c1]"> <span className="inline-flex items-center gap-2 text-xs text-[#333]">
<Loading size={14} label="Uploading" /> <Loading size={14} label="Uploading" />
{progress < 100 ? `Uploading ${progress}%` : "Upload sent — the collective's server is taking it in…"}{" "} {progress < 100 ? `Uploading ${progress}%` : "Upload sent — the collective's server is taking it in…"}{" "}
{file !== null && `${file.name} (${formatBytes(file.size)})`} {file !== null && `${file.name} (${formatBytes(file.size)})`}
@ -354,15 +354,15 @@ function SubmitForm({ token, box }: { token: string; box: SubmissionBoxInfo }):
</div> </div>
) : file !== null && kind !== null ? ( ) : file !== null && kind !== null ? (
<> <>
<span className="text-sm font-medium text-[#f5efed]">{file.name}</span> <span className="text-sm font-medium text-black">{file.name}</span>
<span className="text-2xs text-[#a4a09e]"> <span className="text-2xs text-[#555]">
{kind === "video" ? "video" : "photo"} · {formatBytes(file.size)} · click or drop to choose another {kind === "video" ? "video" : "photo"} · {formatBytes(file.size)} · click or drop to choose another
</span> </span>
</> </>
) : ( ) : (
<> <>
<span className="text-sm text-[#c7c3c1]">Drop your video or photo here</span> <span className="text-sm text-[#333]">Drop your video or photo here</span>
<span className="text-2xs leading-relaxed text-[#a4a09e]"> <span className="text-2xs leading-relaxed text-[#555]">
or browse your device, or paste a file. Nothing is sent until you press Send. or browse your device, or paste a file. Nothing is sent until you press Send.
</span> </span>
<span className="mt-2 rounded-md bg-[#00E5FF] px-3 py-1.5 text-xs font-medium text-black">Browse files</span> <span className="mt-2 rounded-md bg-[#00E5FF] px-3 py-1.5 text-xs font-medium text-black">Browse files</span>
@ -381,11 +381,11 @@ function SubmitForm({ token, box }: { token: string; box: SubmissionBoxInfo }):
/> />
</div> </div>
{fileError !== null && <p role="alert" className="text-xs text-[#ff6f6b]">{fileError}</p>} {fileError !== null && <p role="alert" className="text-xs text-[#c4001a]">{fileError}</p>}
{error !== null && <p role="alert" className="rounded-md border border-[#00E5FF]/30 bg-[#00E5FF]/10 px-3 py-2 text-xs text-[#ff9b97]">{error}</p>} {error !== null && <p role="alert" className="rounded-md border border-[#00E5FF]/30 bg-[#00E5FF]/10 px-3 py-2 text-xs text-[#c4001a]">{error}</p>}
<div className="space-y-4"> <div className="space-y-4">
<label className="flex cursor-pointer items-start gap-2.5 rounded-lg border border-[#3a312e] bg-[#060403] p-3"> <label className="flex cursor-pointer items-start gap-2.5 rounded-lg border border-black bg-white p-3">
<input <input
type="checkbox" type="checkbox"
checked={licence} checked={licence}
@ -393,12 +393,12 @@ function SubmitForm({ token, box }: { token: string; box: SubmissionBoxInfo }):
disabled={uploading} disabled={uploading}
className="mt-0.5 h-4 w-4 shrink-0 accent-[#00E5FF]" className="mt-0.5 h-4 w-4 shrink-0 accent-[#00E5FF]"
/> />
<span className="text-xs leading-relaxed text-[#c7c3c1]"> <span className="text-xs leading-relaxed text-[#333]">
{SUBMISSION_LICENSE_TEXT} <span className="text-[#00E5FF]">(required)</span> {SUBMISSION_LICENSE_TEXT} <span className="text-[#00798a]">(required)</span>
</span> </span>
</label> </label>
<label className="block text-2xs text-[#a4a09e]"> <label className="block text-2xs text-[#555]">
Credit name (optional, max {SUBMISSION_CREDIT_MAX}) Credit name (optional, max {SUBMISSION_CREDIT_MAX})
<input <input
type="text" type="text"
@ -407,12 +407,12 @@ function SubmitForm({ token, box }: { token: string; box: SubmissionBoxInfo }):
onChange={(event) => setCreditName(event.target.value)} onChange={(event) => setCreditName(event.target.value)}
disabled={uploading} disabled={uploading}
placeholder="How your name should appear in the credit" placeholder="How your name should appear in the credit"
className="mt-1 w-full rounded-md border border-[#3a312e] bg-[#060403] px-3 py-2 text-sm text-[#f5efed] placeholder:text-[#6b6563] focus:border-[#00E5FF] focus:outline-none" className="mt-1 w-full rounded-md border border-black bg-white px-3 py-2 text-sm text-black placeholder:text-[#888] focus:border-[#00E5FF] focus:outline-none"
/> />
{creditTooLong && <span className="mt-1 block text-[#ff6f6b]">Up to {SUBMISSION_CREDIT_MAX} characters.</span>} {creditTooLong && <span className="mt-1 block text-[#c4001a]">Up to {SUBMISSION_CREDIT_MAX} characters.</span>}
</label> </label>
<label className="block text-2xs text-[#a4a09e]"> <label className="block text-2xs text-[#555]">
Contact (optional, max {SUBMISSION_CONTACT_MAX}) Contact (optional, max {SUBMISSION_CONTACT_MAX})
<textarea <textarea
value={contact} value={contact}
@ -421,9 +421,9 @@ function SubmitForm({ token, box }: { token: string; box: SubmissionBoxInfo }):
disabled={uploading} disabled={uploading}
rows={2} rows={2}
placeholder="How licensors can reach you — shown only to admins" placeholder="How licensors can reach you — shown only to admins"
className="mt-1 w-full resize-none rounded-md border border-[#3a312e] bg-[#060403] px-3 py-2 text-sm text-[#f5efed] placeholder:text-[#6b6563] focus:border-[#00E5FF] focus:outline-none" className="mt-1 w-full resize-none rounded-md border border-black bg-white px-3 py-2 text-sm text-black placeholder:text-[#888] focus:border-[#00E5FF] focus:outline-none"
/> />
{contactTooLong && <span className="mt-1 block text-[#ff6f6b]">Up to {SUBMISSION_CONTACT_MAX} characters.</span>} {contactTooLong && <span className="mt-1 block text-[#c4001a]">Up to {SUBMISSION_CONTACT_MAX} characters.</span>}
</label> </label>
</div> </div>
@ -434,7 +434,7 @@ function SubmitForm({ token, box }: { token: string; box: SubmissionBoxInfo }):
> >
{uploading ? `Sending… ${progress}%` : "Send to the collective"} {uploading ? `Sending… ${progress}%` : "Send to the collective"}
</button> </button>
<p className="text-center text-2xs leading-relaxed text-[#a4a09e]"> <p className="text-center text-2xs leading-relaxed text-[#555]">
The collective reviews every submission before anything is used. Your contact details stay with their admins. The collective reviews every submission before anything is used. Your contact details stay with their admins.
</p> </p>
</form> </form>

View file

@ -1,51 +1,62 @@
import type { ReactElement } from "react"; import type { ReactElement } from "react";
/** /**
* The Tactical Media Broadcast Hub mark, inline. * The T-HUB mark, inline: three dome tents in a circle, each with a cable
* * out of its door into a switch with an antenna. Drawn in the hand-inked
* Source of truth: `public/brand/tactical-media-broadcast-hub.svg` — the arrows-from-circle * style of the acampada26s.net mark, ink in `currentColor` over a neon
* mark, tilted −17.5° counterclockwise so the top arrow points upper-left * offset copy. Source: docs/brand/t-hub.svg (same 400×400 geometry).
* (nothing static; everything points outward). The strokes use `currentColor`
* so the mark always rides the workspace accent, which in the warm palette
* lands within a hair of the brand red (#FF1610 ≈ oklch(0.63 0.24 29) vs the
* token's oklch(0.62 0.22 30)). Geometry is copied 1:1 from the asset on its
* 1700×1700 grid, minus the black plate and the screen-print distress paths
* (those only read on pure black at full size).
*/ */
const TENTS: ReadonlyArray<readonly [number, number]> = [[105, 150], [295, 150], [200, 340]];
function Tent({ x, y }: { x: number; y: number }): ReactElement {
return (
<g transform={`translate(${x},${y})`}>
<path fill="none" d="M-58 0 Q-56 -66 -1 -72 Q55 -66 58 0" strokeWidth="7" />
<path fill="none" d="M-64 1 Q0 -3 64 1" strokeWidth="6" />
<path fill="none" d="M-44 0 Q-30 -58 -1 -72" strokeWidth="4.5" />
<path fill="none" d="M44 0 Q30 -58 -1 -72" strokeWidth="4.5" />
<path d="M-15 0 Q-14 -30 0 -33 Q14 -30 15 0 Z" strokeWidth="4" />
<path fill="none" d="M-50 -14 L-41 -25 M-50 -4 L-37 -19 M-43 -1 L-33 -13 M-52 -27 L-45 -36" strokeWidth="2.6" />
<path fill="none" d="M28 -50 L37 -42 M24 -40 L36 -30 M22 -29 L34 -19" strokeWidth="2.6" />
<circle cx="-64" cy="1" r="5.5" stroke="none" />
<circle cx="64" cy="1" r="5.5" stroke="none" />
<circle cx="-1" cy="-73" r="5.5" stroke="none" />
</g>
);
}
function Mark({ paper }: { paper: string }): ReactElement {
return (
<>
<path fill="none" d="M105 150 Q112 206 168 214" strokeWidth="5" />
<path fill="none" d="M295 150 Q288 206 232 214" strokeWidth="5" />
<path fill="none" d="M200 318 Q197 280 200 236" strokeWidth="5" />
<path fill="none" d="M200 200 Q198 160 200 118" strokeWidth="6" />
<path fill="none" d="M184 98 Q200 82 216 98" strokeWidth="5" />
<path fill="none" d="M171 88 Q200 58 229 88" strokeWidth="5" />
<circle cx="200" cy="112" r="7" stroke="none" />
<path d="M168 201 L233 200 L234 235 L167 236 Z" strokeWidth="6" fill={paper} />
<path d="M179 212 h9 v11 h-9 z M196 212 h9 v11 h-9 z M213 212 h9 v11 h-9 z" stroke="none" />
{TENTS.map(([x, y]) => <Tent key={`${x}-${y}`} x={x} y={y} />)}
</>
);
}
export function LogoMark({ export function LogoMark({
size = 32, size = 32,
className = "text-accent", className = "text-text",
title = "Tactical Media Broadcast Hub", title = "T-HUB",
}: { }: {
size?: number; size?: number;
className?: string; className?: string;
title?: string; title?: string;
}): ReactElement { }): ReactElement {
return ( return (
<svg <svg width={size} height={size} viewBox="0 0 400 400" role="img" aria-label={title} className={className}>
width={size} <g strokeLinecap="round" strokeLinejoin="round">
height={size} <g transform="translate(7,7)" stroke="#00e5ff" fill="#00e5ff"><Mark paper="#fff" /></g>
viewBox="0 0 1700 1700" <g stroke="currentColor" fill="currentColor"><Mark paper="#fff" /></g>
role="img"
aria-label={title}
className={className}
>
<g transform="rotate(-17.5 850 850)">
<g fill="none" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round">
<circle cx="850" cy="850" r="350" strokeWidth="74" />
<path d="M 850 405 L 464.77 1269.52" strokeWidth="88" />
<path d="M 850 405 L 1235.23 1269.52" strokeWidth="88" />
<path d="M 850 405 L 850 350" strokeWidth="88" />
<path d="M 345 850 L 1355 850" strokeWidth="88" />
</g>
<g fill="currentColor">
<polygon points="850,240 925,385 775,385" />
<polygon points="235,850 380,775 380,925" />
<polygon points="1465,850 1320,925 1320,775" />
<polygon points="420,1370 410.51,1207.03 547.52,1268.08" />
<polygon points="1280,1370 1152.48,1268.08 1289.49,1207.03" />
</g>
</g> </g>
</svg> </svg>
); );
@ -112,10 +123,14 @@ export function Logo({ size = 32, withText = true }: { size?: number; withText?:
<span className={`inline-flex ${stacked ? "flex-col items-center gap-3" : "items-center gap-2.5"}`}> <span className={`inline-flex ${stacked ? "flex-col items-center gap-3" : "items-center gap-2.5"}`}>
<LogoMark size={size} /> <LogoMark size={size} />
<span <span
className={`font-semibold tracking-tight text-text ${stacked ? "text-2xl" : ""}`} className={`uppercase tracking-wide text-text ${stacked ? "text-4xl" : ""}`}
style={stacked ? undefined : { fontSize: `${Math.max(13, Math.round(size * 0.45))}px` }} style={{
fontFamily: "var(--font-title)",
textShadow: "0.04em 0.04em 0 var(--color-neon)",
...(stacked ? {} : { fontSize: `${Math.max(16, Math.round(size * 0.6))}px` }),
}}
> >
Tactical Media Broadcast Hub T-HUB
</span> </span>
</span> </span>
); );

View file

@ -46,7 +46,7 @@ export function CommandPalette(): React.ReactElement {
onClick={(e: React.MouseEvent) => e.stopPropagation()} onClick={(e: React.MouseEvent) => e.stopPropagation()}
> >
<div className="flex items-center gap-2.5 border-b border-border-subtle px-4"> <div className="flex items-center gap-2.5 border-b border-border-subtle px-4">
<LogoMark size={16} title="Tactical Media Broadcast Hub" /> <LogoMark size={16} />
<Command.Input <Command.Input
autoFocus autoFocus
placeholder="Type a command or search…" placeholder="Type a command or search…"

View file

@ -55,7 +55,7 @@ export function Sidebar(): React.ReactElement {
className="mt-0.5 h-[30px] w-[30px] shrink-0 rounded object-contain" className="mt-0.5 h-[30px] w-[30px] shrink-0 rounded object-contain"
/> />
) : ( ) : (
<LogoMark size={30} title="Tactical Media Broadcast Hub" /> <LogoMark size={30} />
)} )}
<div className="min-w-0 flex-1"> <div className="min-w-0 flex-1">
<div className="text-xs font-semibold leading-tight tracking-tight" title={workspaceName}> <div className="text-xs font-semibold leading-tight tracking-tight" title={workspaceName}>
@ -67,7 +67,7 @@ export function Sidebar(): React.ReactElement {
</div> </div>
) : ( ) : (
<div className="truncate text-2xs text-text-faint" title={workspaceName}> <div className="truncate text-2xs text-text-faint" title={workspaceName}>
Tactical Media Broadcast Hub T-HUB
</div> </div>
)} )}
</div> </div>

View file

@ -139,15 +139,21 @@ Verificación
4. ESTILO Y LOGO 4. ESTILO Y LOGO
---------------- ----------------
- apps/web/src/app/globals.css: paleta de acampada26s.net sobre fondo - apps/web/src/app/globals.css: paleta de acampada26s.net. Fondo
oscuro (negro, blanco, neón #00e5ff), títulos h1/h2 en Anton en blanco, texto y bordes negros, botones negros con sombra neón
mayúsculas. Regla que pone texto negro en botones neón. desplazada, foco y elemento activo en neón #00e5ff. Títulos h1/h2 en
Anton en mayúsculas con la sombra neón escalonada de la web.
- Iconos de navegación en negro; iconos de redes con trazo neón.
- Logo: tres tiendas iglú cableadas a un switch con antena, en el
estilo a tinta del logo de la acampada (docs/brand/t-hub.svg;
t-hub-lockup.svg/png con el nombre en Anton convertido a trazos).
Componente LogoMark sustituido; nombre visible "T-HUB".
- Fuente Anton en apps/web/public/fonts (licencia SIL OFL incluida). - Fuente Anton en apps/web/public/fonts (licencia SIL OFL incluida).
- Logo: docs/brand/t-hub.svg, también como favicon. - Página pública de buzón (/submit/[token]) en claro.
- Página pública de buzón (/submit/[token]) con el mismo color. Revisado con capturas (Chromium sin interfaz, modo offline con datos de
Comprobar visualmente: login, Compose, Approvals, Channels, Outreach, ejemplo): Streams, Compose, Outreach, Channels, Approvals, Onboarding,
Control Room y /submit/<token>, en escritorio y móvil. Buscar textos /submit en escritorio y móvil. Falta revisar Control Room y Calendar con
blancos sobre neón o bloques que hayan quedado con el rojo anterior. datos reales.
5. SEGURIDAD 5. SEGURIDAD

BIN
docs/brand/t-hub-lockup.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 17 KiB

View file

@ -1,40 +1,44 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 240 240" width="240" height="240" role="img" aria-labelledby="t"> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 400 400" width="400" height="400" role="img" aria-labelledby="t">
<title id="t">T-HUB</title> <title id="t">T-HUB</title>
<circle cx="120" cy="120" r="118" fill="#000"/> <defs>
<circle cx="120" cy="120" r="82" fill="none" stroke="#fff" stroke-width="2" stroke-dasharray="3 7" opacity=".55"/> <!-- Dome tent in the hand-inked style of the acampada26s.net mark:
curved poles with ball ends, centre seam, hatched panel, door.
<!-- cables: each leaves through a tent door and runs to the switch --> Base midpoint at 0,0. -->
<g fill="none" stroke="#00e5ff" stroke-width="4" stroke-linecap="round"> <g id="tienda" stroke-linecap="round" stroke-linejoin="round">
<path d="M49 94 C 52 122, 74 130, 96 130"/> <path fill="none" d="M-58 0 Q-56 -66 -1 -72 Q55 -66 58 0" stroke-width="7"/>
<path d="M191 94 C 188 122, 166 130, 144 130"/> <path fill="none" d="M-64 1 Q0 -3 64 1" stroke-width="6"/>
<path d="M120 216 C 120 196, 120 168, 120 140"/> <path fill="none" d="M-44 0 Q-30 -58 -1 -72" stroke-width="4.5"/>
<path fill="none" d="M44 0 Q30 -58 -1 -72" stroke-width="4.5"/>
<path d="M-15 0 Q-14 -30 0 -33 Q14 -30 15 0 Z" stroke-width="4"/>
<path fill="none" d="M-50 -14 L-41 -25 M-50 -4 L-37 -19 M-43 -1 L-33 -13 M-52 -27 L-45 -36" stroke-width="2.6"/>
<path fill="none" d="M28 -50 L37 -42 M24 -40 L36 -30 M22 -29 L34 -19" stroke-width="2.6"/>
<circle cx="-64" cy="1" r="5.5" stroke="none"/>
<circle cx="64" cy="1" r="5.5" stroke="none"/>
<circle cx="-1" cy="-73" r="5.5" stroke="none"/>
</g>
<g id="marca" stroke-linecap="round" stroke-linejoin="round">
<!-- cables: out of each tent door to the switch -->
<path fill="none" d="M105 150 Q112 206 168 214" stroke-width="5"/>
<path fill="none" d="M295 150 Q288 206 232 214" stroke-width="5"/>
<path fill="none" d="M200 318 Q197 280 200 236" stroke-width="5"/>
<!-- antenna -->
<path fill="none" d="M200 200 Q198 160 200 118" stroke-width="6"/>
<path fill="none" d="M184 98 Q200 82 216 98" stroke-width="5"/>
<path fill="none" d="M171 88 Q200 58 229 88" stroke-width="5"/>
<circle cx="200" cy="112" r="7" stroke="none"/>
<!-- switch -->
<path d="M168 201 L233 200 L234 235 L167 236 Z" stroke-width="6" fill="#fff"/>
<path d="M179 212 h9 v11 h-9 z M196 212 h9 v11 h-9 z M213 212 h9 v11 h-9 z" stroke="none"/>
<use xlink:href="#tienda" transform="translate(105,150)"/>
<use xlink:href="#tienda" transform="translate(295,150)"/>
<use xlink:href="#tienda" transform="translate(200,340)"/>
</g>
</defs>
<!-- neon offset underneath, ink on top, as on acampada26s.net -->
<g transform="translate(7,7)" stroke="#00e5ff" fill="#00e5ff">
<use xlink:href="#marca"/>
</g> </g>
<g stroke="#000" fill="#000">
<!-- tents --> <use xlink:href="#marca"/>
<g stroke="#fff" stroke-width="3" stroke-linejoin="round">
<polygon points="19,99 49,55 79,99" fill="#000"/>
<polygon points="161,99 191,55 221,99" fill="#000"/>
<polygon points="90,221 120,177 150,221" fill="#000"/>
</g>
<g fill="#00e5ff">
<polygon points="40,99 49,80 58,99"/>
<polygon points="182,99 191,80 200,99"/>
<polygon points="111,221 120,202 129,221"/>
</g>
<!-- antenna -->
<line x1="120" y1="120" x2="120" y2="70" stroke="#fff" stroke-width="4" stroke-linecap="round"/>
<circle cx="120" cy="68" r="5" fill="#00e5ff"/>
<g fill="none" stroke="#00e5ff" stroke-width="3" stroke-linecap="round">
<path d="M106 56 A 18 18 0 0 1 134 56"/>
<path d="M97 46 A 30 30 0 0 1 143 46"/>
</g>
<!-- switch -->
<rect x="94" y="118" width="52" height="24" rx="3" fill="#fff"/>
<g fill="#000">
<rect x="101" y="125" width="9" height="9"/>
<rect x="115.5" y="125" width="9" height="9"/>
<rect x="130" y="125" width="9" height="9"/>
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Before After
Before After