style: acampada26s.net palette, Anton titles and T-HUB logo
Black/white/neon (#00e5ff) on the existing dark base, h1/h2 in Anton uppercase with the neon offset used on acampada26s.net. Neon fills get dark text. The public submission page and the control-room focus ring follow the same accent. Anton ships under the SIL OFL (license copied next to the font). New logo in docs/brand/t-hub.svg, also the favicon.
This commit is contained in:
parent
fb81fab7bb
commit
f6840ff69b
9 changed files with 264 additions and 32 deletions
|
|
@ -1,7 +1,40 @@
|
||||||
<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" viewBox="0 0 240 240" width="240" height="240" role="img" aria-labelledby="t">
|
||||||
<g transform="rotate(-17.5 850 850)">
|
<title id="t">T-HUB</title>
|
||||||
<circle cx="850" cy="850" r="350" fill="none" stroke="#FF1610" stroke-width="74" stroke-linecap="round"/>
|
<circle cx="120" cy="120" r="118" fill="#000"/>
|
||||||
<path d="M 850 405 L 464.77 1269.52 M 850 405 L 1235.23 1269.52 M 345 850 L 1355 850"
|
<circle cx="120" cy="120" r="82" fill="none" stroke="#fff" stroke-width="2" stroke-dasharray="3 7" opacity=".55"/>
|
||||||
fill="none" stroke="#FF1610" stroke-width="88" stroke-linecap="round" stroke-linejoin="round"/>
|
|
||||||
|
<!-- cables: each leaves through a tent door and runs to the switch -->
|
||||||
|
<g fill="none" stroke="#00e5ff" stroke-width="4" stroke-linecap="round">
|
||||||
|
<path d="M49 94 C 52 122, 74 130, 96 130"/>
|
||||||
|
<path d="M191 94 C 188 122, 166 130, 144 130"/>
|
||||||
|
<path d="M120 216 C 120 196, 120 168, 120 140"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- tents -->
|
||||||
|
<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: 447 B After Width: | Height: | Size: 1.6 KiB |
40
apps/web/public/brand/t-hub.svg
Normal file
40
apps/web/public/brand/t-hub.svg
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 240 240" width="240" height="240" role="img" aria-labelledby="t">
|
||||||
|
<title id="t">T-HUB</title>
|
||||||
|
<circle cx="120" cy="120" r="118" fill="#000"/>
|
||||||
|
<circle cx="120" cy="120" r="82" fill="none" stroke="#fff" stroke-width="2" stroke-dasharray="3 7" opacity=".55"/>
|
||||||
|
|
||||||
|
<!-- cables: each leaves through a tent door and runs to the switch -->
|
||||||
|
<g fill="none" stroke="#00e5ff" stroke-width="4" stroke-linecap="round">
|
||||||
|
<path d="M49 94 C 52 122, 74 130, 96 130"/>
|
||||||
|
<path d="M191 94 C 188 122, 166 130, 144 130"/>
|
||||||
|
<path d="M120 216 C 120 196, 120 168, 120 140"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- tents -->
|
||||||
|
<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>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.6 KiB |
93
apps/web/public/fonts/Anton-OFL.txt
Normal file
93
apps/web/public/fonts/Anton-OFL.txt
Normal file
|
|
@ -0,0 +1,93 @@
|
||||||
|
Copyright 2020 The Anton Project Authors (https://github.com/googlefonts/AntonFont.git)
|
||||||
|
|
||||||
|
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||||
|
This license is copied below, and is also available with a FAQ at:
|
||||||
|
http://scripts.sil.org/OFL
|
||||||
|
|
||||||
|
|
||||||
|
-----------------------------------------------------------
|
||||||
|
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||||
|
-----------------------------------------------------------
|
||||||
|
|
||||||
|
PREAMBLE
|
||||||
|
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||||
|
development of collaborative font projects, to support the font creation
|
||||||
|
efforts of academic and linguistic communities, and to provide a free and
|
||||||
|
open framework in which fonts may be shared and improved in partnership
|
||||||
|
with others.
|
||||||
|
|
||||||
|
The OFL allows the licensed fonts to be used, studied, modified and
|
||||||
|
redistributed freely as long as they are not sold by themselves. The
|
||||||
|
fonts, including any derivative works, can be bundled, embedded,
|
||||||
|
redistributed and/or sold with any software provided that any reserved
|
||||||
|
names are not used by derivative works. The fonts and derivatives,
|
||||||
|
however, cannot be released under any other type of license. The
|
||||||
|
requirement for fonts to remain under this license does not apply
|
||||||
|
to any document created using the fonts or their derivatives.
|
||||||
|
|
||||||
|
DEFINITIONS
|
||||||
|
"Font Software" refers to the set of files released by the Copyright
|
||||||
|
Holder(s) under this license and clearly marked as such. This may
|
||||||
|
include source files, build scripts and documentation.
|
||||||
|
|
||||||
|
"Reserved Font Name" refers to any names specified as such after the
|
||||||
|
copyright statement(s).
|
||||||
|
|
||||||
|
"Original Version" refers to the collection of Font Software components as
|
||||||
|
distributed by the Copyright Holder(s).
|
||||||
|
|
||||||
|
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||||
|
or substituting -- in part or in whole -- any of the components of the
|
||||||
|
Original Version, by changing formats or by porting the Font Software to a
|
||||||
|
new environment.
|
||||||
|
|
||||||
|
"Author" refers to any designer, engineer, programmer, technical
|
||||||
|
writer or other person who contributed to the Font Software.
|
||||||
|
|
||||||
|
PERMISSION & CONDITIONS
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||||
|
redistribute, and sell modified and unmodified copies of the Font
|
||||||
|
Software, subject to the following conditions:
|
||||||
|
|
||||||
|
1) Neither the Font Software nor any of its individual components,
|
||||||
|
in Original or Modified Versions, may be sold by itself.
|
||||||
|
|
||||||
|
2) Original or Modified Versions of the Font Software may be bundled,
|
||||||
|
redistributed and/or sold with any software, provided that each copy
|
||||||
|
contains the above copyright notice and this license. These can be
|
||||||
|
included either as stand-alone text files, human-readable headers or
|
||||||
|
in the appropriate machine-readable metadata fields within text or
|
||||||
|
binary files as long as those fields can be easily viewed by the user.
|
||||||
|
|
||||||
|
3) No Modified Version of the Font Software may use the Reserved Font
|
||||||
|
Name(s) unless explicit written permission is granted by the corresponding
|
||||||
|
Copyright Holder. This restriction only applies to the primary font name as
|
||||||
|
presented to the users.
|
||||||
|
|
||||||
|
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||||
|
Software shall not be used to promote, endorse or advertise any
|
||||||
|
Modified Version, except to acknowledge the contribution(s) of the
|
||||||
|
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||||
|
permission.
|
||||||
|
|
||||||
|
5) The Font Software, modified or unmodified, in part or in whole,
|
||||||
|
must be distributed entirely under this license, and must not be
|
||||||
|
distributed under any other license. The requirement for fonts to
|
||||||
|
remain under this license does not apply to any document created
|
||||||
|
using the Font Software.
|
||||||
|
|
||||||
|
TERMINATION
|
||||||
|
This license becomes null and void if any of the above conditions are
|
||||||
|
not met.
|
||||||
|
|
||||||
|
DISCLAIMER
|
||||||
|
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||||
|
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||||
|
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||||
|
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||||
|
OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||||
BIN
apps/web/public/fonts/anton.woff2
Normal file
BIN
apps/web/public/fonts/anton.woff2
Normal file
Binary file not shown.
|
|
@ -13,4 +13,4 @@
|
||||||
}
|
}
|
||||||
.control-room label { max-width: 100%; }
|
.control-room label { max-width: 100%; }
|
||||||
.control-room button { min-width: 44px; }
|
.control-room button { min-width: 44px; }
|
||||||
.control-room :focus-visible { outline: 2px solid #ff1610; outline-offset: 3px; }
|
.control-room :focus-visible { outline: 2px solid #00e5ff; outline-offset: 3px; }
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,25 @@
|
||||||
@import "tailwindcss";
|
@import "tailwindcss";
|
||||||
|
|
||||||
|
/* Anton (SIL OFL 1.1, public/fonts/Anton-OFL.txt) — same title face as acampada26s.net. */
|
||||||
|
@font-face {
|
||||||
|
font-family: "Anton";
|
||||||
|
src: url("/fonts/anton.woff2") format("woff2");
|
||||||
|
font-display: swap;
|
||||||
|
}
|
||||||
|
|
||||||
@theme {
|
@theme {
|
||||||
--color-bg: oklch(0.11 0.008 25);
|
/* T-HUB: the acampada26s.net palette (black, white, neon) on a dark base. */
|
||||||
--color-surface: oklch(0.15 0.01 25);
|
--color-bg: #000;
|
||||||
--color-surface-2: oklch(0.19 0.012 25);
|
--color-surface: #0d0d0d;
|
||||||
--color-border: oklch(0.26 0.02 25);
|
--color-surface-2: #181818;
|
||||||
--color-border-subtle: oklch(0.22 0.015 25);
|
--color-border: #3d3d3d;
|
||||||
--color-text: oklch(0.93 0.005 25);
|
--color-border-subtle: #262626;
|
||||||
--color-text-dim: oklch(0.62 0.02 25);
|
--color-text: #fff;
|
||||||
--color-text-faint: oklch(0.46 0.02 25);
|
--color-text-dim: #b3b3b3;
|
||||||
--color-accent: #ff1610;
|
--color-text-faint: #808080;
|
||||||
--color-accent-hover: #e3130e;
|
--color-accent: #00e5ff;
|
||||||
--color-accent-dim: rgb(255 22 16 / 0.15);
|
--color-accent-hover: #5cefff;
|
||||||
|
--color-accent-dim: rgb(0 229 255 / 0.15);
|
||||||
--color-live: oklch(0.72 0.19 145);
|
--color-live: oklch(0.72 0.19 145);
|
||||||
--color-warn: oklch(0.78 0.16 85);
|
--color-warn: oklch(0.78 0.16 85);
|
||||||
--color-danger: oklch(0.55 0.24 15);
|
--color-danger: oklch(0.55 0.24 15);
|
||||||
|
|
@ -20,6 +28,7 @@
|
||||||
|
|
||||||
--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;
|
||||||
|
--font-title: "Anton", Impact, "Arial Narrow", sans-serif;
|
||||||
|
|
||||||
--radius-sm: 0.375rem;
|
--radius-sm: 0.375rem;
|
||||||
--radius-md: 0.5rem;
|
--radius-md: 0.5rem;
|
||||||
|
|
@ -55,6 +64,23 @@ body {
|
||||||
|
|
||||||
html, body { max-width: 100%; }
|
html, body { max-width: 100%; }
|
||||||
|
|
||||||
|
/* Titles as on acampada26s.net: Anton, uppercase, hard neon offset. */
|
||||||
|
h1, h2 {
|
||||||
|
font-family: var(--font-title);
|
||||||
|
font-weight: 400;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.01em;
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
text-shadow: 0.04em 0.04em 0 var(--color-accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Neon fills need dark text; unlayered so it outranks the text-white utility. */
|
||||||
|
.bg-accent.text-white,
|
||||||
|
.bg-accent .text-white {
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
@media (max-width: 1023px) {
|
@media (max-width: 1023px) {
|
||||||
body { overflow-x: hidden; }
|
body { overflow-x: hidden; }
|
||||||
[data-mobile-main] :is(button, a[href], input, select, textarea, [role="tab"]) {
|
[data-mobile-main] :is(button, a[href], input, select, textarea, [role="tab"]) {
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ export const viewport: Viewport = {
|
||||||
initialScale: 1,
|
initialScale: 1,
|
||||||
viewportFit: "cover",
|
viewportFit: "cover",
|
||||||
interactiveWidget: "resizes-content",
|
interactiveWidget: "resizes-content",
|
||||||
themeColor: "#FF1610",
|
themeColor: "#000000",
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function RootLayout({ children }: { children: ReactNode }): React.ReactNode {
|
export default function RootLayout({ children }: { children: ReactNode }): React.ReactNode {
|
||||||
|
|
|
||||||
|
|
@ -135,7 +135,7 @@ export default function SubmitPage({ params }: { params: { token: string } }): R
|
||||||
tone="warn"
|
tone="warn"
|
||||||
title="Can't reach the server"
|
title="Can't reach the server"
|
||||||
body="Your link is still fine — the server isn't answering. Try again in a moment."
|
body="Your link is still fine — the server isn't answering. Try again in a moment."
|
||||||
action={<button type="button" onClick={() => setAttempt((n) => n + 1)} className="mt-6 rounded-md bg-[#FF1610] px-3 py-1.5 text-xs font-medium text-white hover:bg-[#e3130e]">Retry</button>}
|
action={<button type="button" onClick={() => setAttempt((n) => n + 1)} className="mt-6 rounded-md bg-[#00E5FF] px-3 py-1.5 text-xs font-medium text-black hover:bg-[#5cefff]">Retry</button>}
|
||||||
/>
|
/>
|
||||||
</main>
|
</main>
|
||||||
);
|
);
|
||||||
|
|
@ -165,7 +165,7 @@ function DeadCard({ tone, title, body, action }: { tone: "warn" | "danger"; titl
|
||||||
<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-[#2a2320] bg-[#0F0A09] 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-[#FF1610]/15 text-[#FF1610]" : "bg-[#FF1610]/15 text-[#FF1610]"
|
tone === "warn" ? "bg-[#00E5FF]/15 text-[#00E5FF]" : "bg-[#00E5FF]/15 text-[#00E5FF]"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{tone === "warn" ? "!" : "✕"}
|
{tone === "warn" ? "!" : "✕"}
|
||||||
|
|
@ -283,7 +283,7 @@ 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-[#2a2320] bg-[#0F0A09] p-8 text-center">
|
||||||
<LogoMark size={44} className="text-[#FF1610]" title="" />
|
<LogoMark size={44} className="text-[#00E5FF]" title="" />
|
||||||
<h1 className="text-xl font-semibold tracking-tight text-[#f5efed]">Received</h1>
|
<h1 className="text-xl font-semibold tracking-tight text-[#f5efed]">Received</h1>
|
||||||
<p className="max-w-sm text-sm leading-relaxed text-[#c7c3c1]">
|
<p className="max-w-sm text-sm leading-relaxed text-[#c7c3c1]">
|
||||||
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.
|
||||||
|
|
@ -304,7 +304,7 @@ function SubmitForm({ token, box }: { token: string; box: SubmissionBoxInfo }):
|
||||||
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-[#2a2320] bg-[#0F0A09] 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-[#FF1610]" title="Tactical Media Broadcast Hub" />
|
<LogoMark size={36} className="text-[#00E5FF]" title="Tactical Media Broadcast Hub" />
|
||||||
<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-[#f5efed]">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-[#a4a09e]">
|
||||||
|
|
@ -340,7 +340,7 @@ 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-[#3a312e] opacity-60"
|
||||||
: "cursor-pointer border-[#3a312e] hover:border-[#FF1610] focus-visible:border-[#FF1610]"
|
: "cursor-pointer border-[#3a312e] hover:border-[#00E5FF] focus-visible:border-[#00E5FF]"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{uploading ? (
|
{uploading ? (
|
||||||
|
|
@ -350,7 +350,7 @@ function SubmitForm({ token, box }: { token: string; box: SubmissionBoxInfo }):
|
||||||
{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)})`}
|
||||||
</span>
|
</span>
|
||||||
<progress className="h-2 w-full accent-[#FF1610]" aria-label="Upload progress" value={progress} max={100} />
|
<progress className="h-2 w-full accent-[#00E5FF]" aria-label="Upload progress" value={progress} max={100} />
|
||||||
</div>
|
</div>
|
||||||
) : file !== null && kind !== null ? (
|
) : file !== null && kind !== null ? (
|
||||||
<>
|
<>
|
||||||
|
|
@ -365,7 +365,7 @@ function SubmitForm({ token, box }: { token: string; box: SubmissionBoxInfo }):
|
||||||
<span className="text-2xs leading-relaxed text-[#a4a09e]">
|
<span className="text-2xs leading-relaxed text-[#a4a09e]">
|
||||||
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-[#FF1610] px-3 py-1.5 text-xs font-medium text-white">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>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
<input
|
<input
|
||||||
|
|
@ -382,7 +382,7 @@ 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-[#ff6f6b]">{fileError}</p>}
|
||||||
{error !== null && <p role="alert" className="rounded-md border border-[#FF1610]/30 bg-[#FF1610]/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-[#ff9b97]">{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-[#3a312e] bg-[#060403] p-3">
|
||||||
|
|
@ -391,10 +391,10 @@ function SubmitForm({ token, box }: { token: string; box: SubmissionBoxInfo }):
|
||||||
checked={licence}
|
checked={licence}
|
||||||
onChange={(event) => setLicence(event.target.checked)}
|
onChange={(event) => setLicence(event.target.checked)}
|
||||||
disabled={uploading}
|
disabled={uploading}
|
||||||
className="mt-0.5 h-4 w-4 shrink-0 accent-[#FF1610]"
|
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-[#c7c3c1]">
|
||||||
{SUBMISSION_LICENSE_TEXT} <span className="text-[#FF1610]">(required)</span>
|
{SUBMISSION_LICENSE_TEXT} <span className="text-[#00E5FF]">(required)</span>
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
|
|
@ -407,7 +407,7 @@ 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-[#FF1610] focus:outline-none"
|
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"
|
||||||
/>
|
/>
|
||||||
{creditTooLong && <span className="mt-1 block text-[#ff6f6b]">Up to {SUBMISSION_CREDIT_MAX} characters.</span>}
|
{creditTooLong && <span className="mt-1 block text-[#ff6f6b]">Up to {SUBMISSION_CREDIT_MAX} characters.</span>}
|
||||||
</label>
|
</label>
|
||||||
|
|
@ -421,7 +421,7 @@ 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-[#FF1610] focus:outline-none"
|
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"
|
||||||
/>
|
/>
|
||||||
{contactTooLong && <span className="mt-1 block text-[#ff6f6b]">Up to {SUBMISSION_CONTACT_MAX} characters.</span>}
|
{contactTooLong && <span className="mt-1 block text-[#ff6f6b]">Up to {SUBMISSION_CONTACT_MAX} characters.</span>}
|
||||||
</label>
|
</label>
|
||||||
|
|
@ -430,7 +430,7 @@ function SubmitForm({ token, box }: { token: string; box: SubmissionBoxInfo }):
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={!ready || uploading}
|
disabled={!ready || uploading}
|
||||||
className="w-full rounded-md bg-[#FF1610] px-4 py-2.5 text-sm font-semibold text-white transition-colors duration-150 hover:bg-[#e3130e] disabled:cursor-not-allowed disabled:opacity-40"
|
className="w-full rounded-md bg-[#00E5FF] px-4 py-2.5 text-sm font-semibold text-black transition-colors duration-150 hover:bg-[#5cefff] disabled:cursor-not-allowed disabled:opacity-40"
|
||||||
>
|
>
|
||||||
{uploading ? `Sending… ${progress}%` : "Send to the collective"}
|
{uploading ? `Sending… ${progress}%` : "Send to the collective"}
|
||||||
</button>
|
</button>
|
||||||
|
|
|
||||||
40
docs/brand/t-hub.svg
Normal file
40
docs/brand/t-hub.svg
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 240 240" width="240" height="240" role="img" aria-labelledby="t">
|
||||||
|
<title id="t">T-HUB</title>
|
||||||
|
<circle cx="120" cy="120" r="118" fill="#000"/>
|
||||||
|
<circle cx="120" cy="120" r="82" fill="none" stroke="#fff" stroke-width="2" stroke-dasharray="3 7" opacity=".55"/>
|
||||||
|
|
||||||
|
<!-- cables: each leaves through a tent door and runs to the switch -->
|
||||||
|
<g fill="none" stroke="#00e5ff" stroke-width="4" stroke-linecap="round">
|
||||||
|
<path d="M49 94 C 52 122, 74 130, 96 130"/>
|
||||||
|
<path d="M191 94 C 188 122, 166 130, 144 130"/>
|
||||||
|
<path d="M120 216 C 120 196, 120 168, 120 140"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- tents -->
|
||||||
|
<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>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.6 KiB |
Loading…
Add table
Add a link
Reference in a new issue