atuq: la marca de verdad — el zorro en medallón, y la paleta muestreada del propio logo
El operador pasó un tablero de identidad: zorro en medallón con cenefa andina, disco teal, anillo noche. Se adapta la FORMA y el COLOR. Los eslóganes NO — los descartó explícitamente, y de todos modos `brand.ftl` no es sitio para copy: lleva el nombre y nada más. EL ICONO DEJA DE DIBUJARSE EN CÓDIGO. Hasta la v0.2 `rebrand.py` generaba una marca geométrica en Python puro, con el argumento de que un PNG en el árbol no se puede revisar en un diff. Ese argumento valía mientras el icono era un marcador de posición inventado por falta de arte. Ya hay arte, así que el criterio se invierte: un asset de diseño ES la fuente, no un derivado. Lo que se conserva es la disciplina — los seis tamaños salen del MISMO master (recorte del medallón con máscara circular y alfa, LANCZOS desde 1024 px), se generan una vez y se copian, así que dos builds ponen los mismos bytes. LA PALETA SE MIDIÓ, NO SE ESTIMÓ. Los cuatro tokens salen del color más frecuente de cada zona del medallón: #c15728 el zorro, #1b6470 el disco, #04161d el anillo, #f5ecde los reflejos. Escribirlos «parecidos» a ojo es cómo una identidad se desalinea de su propio logo en tres ediciones. Con eso el CSS suma `accent-color` —un solo cambio alcanza decenas de widgets nativos del chrome sin enumerar ninguno— y el fondo de la barra de pestañas verticales, para que marco e icono cuenten lo mismo. ⚠ Anotado y no escondido: a 16 px el medallón pierde el detalle y queda como una mancha cálida redonda. Es intrínseco a un logo con cenefa; la salida sería un dibujo simplificado para ese tamaño y lo decide quien dibujó el zorro, no este script. Construido y sellado EN LOCAL en 3 segundos (b3:97328d1c), hidratado y abierto: 8 procesos vivos, anunciándose como `(atuq:9581)`.
This commit is contained in:
+19
-2
@@ -23,10 +23,27 @@ navegador tiene que verse como atuq la primera vez que arranca, con un perfil re
|
||||
que sí funciona a nivel de aplicación es el `nsIStyleSheetService` desde autoconfig, que es lo que
|
||||
hace `atuq.cfg`.
|
||||
|
||||
## La marca
|
||||
|
||||
El arte viene de un tablero de identidad del operador (2026-09-05): un **zorro en medallón** con
|
||||
cenefa andina, sobre disco teal y anillo noche.
|
||||
|
||||
- `branding/icons/atuq{16,32,48,64,128,256}.png` — el medallón recortado del tablero, con máscara
|
||||
circular y alfa, reducido con LANCZOS desde un master de 1024 px. Se generan una vez y se copian;
|
||||
no se dibujan en cada build.
|
||||
- La **paleta del chrome se muestreó del propio medallón**, tomando el color más frecuente de cada
|
||||
zona, en vez de estimarla a ojo: `#c15728` el zorro, `#1b6470` el disco, `#04161d` el anillo,
|
||||
`#f5ecde` los reflejos. Un token escrito «parecido» es cómo una identidad se desalinea de su logo
|
||||
en tres ediciones.
|
||||
- **Del tablero se toman la forma y el color; los eslóganes NO** — el operador los descartó
|
||||
explícitamente. `brand.ftl` lleva el nombre y nada más.
|
||||
|
||||
⚠ A 16 px el medallón pierde el detalle y queda como una mancha cálida redonda. Es intrínseco a un
|
||||
logo con cenefa, no un defecto del escalado: la salida sería un dibujo simplificado para ese tamaño,
|
||||
y eso lo decide quien dibujó el zorro.
|
||||
|
||||
## Lo que TODAVÍA no está
|
||||
|
||||
- **Branding** (nombre, iconos, `application.ini`): v0.2. Necesita mirar el artefacto real de
|
||||
`firefox` para no adivinar la forma del árbol.
|
||||
- **Re-empaque de `omni.ja`**: es donde va el chrome de verdad (split view, dientes propios). Trae
|
||||
dos condiciones ya sabidas: re-empacar determinista, y **preservar el orden del `jarlog`** cuando
|
||||
el PGO exista, o se tira a la basura la optimización de arranque.
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 31 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 983 B |
Binary file not shown.
|
After Width: | Height: | Size: 100 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 3.1 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 6.1 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 10 KiB |
@@ -1,29 +1,49 @@
|
||||
/* atuq.css — el aspecto de atuq. Se registra como USER_SHEET desde `atuq.cfg`.
|
||||
*
|
||||
* ⚠ TODO lo de acá va acotado con @-moz-document a la ventana del navegador. Una hoja de nivel
|
||||
* USER sin acotar alcanza CUALQUIER documento chrome —el visor de PDF, el inspector, los diálogos—
|
||||
* y un selector genérico como `toolbar` termina pintando ventanas que nadie miró nunca.
|
||||
* ── LA PALETA SALE DEL ARTE, MEDIDA, NO ESTIMADA A OJO ─────────────────────────────────────────
|
||||
* Los cuatro tokens se muestrearon del propio medallón (`branding/icons/atuq256.png`) tomando el
|
||||
* color más frecuente de cada zona: el cuerpo del zorro, el disco de fondo, el anillo exterior y
|
||||
* los reflejos. Escribirlos «parecidos» a ojo es cómo una identidad se desalinea de su logo en tres
|
||||
* ediciones.
|
||||
*
|
||||
* v0.1: deliberadamente conservador. El chrome de verdad (dientes propios, split view) vive en el
|
||||
* re-empaque de `omni.ja`, que es la v0.2 y necesita el artefacto real de firefox delante.
|
||||
* ⚠ Del tablero de marca se toman la FORMA y el COLOR. Los eslóganes NO: el usuario los descartó
|
||||
* explícitamente, y esta hoja no es sitio para copy de todos modos.
|
||||
*
|
||||
* ⚠ TODO va acotado con @-moz-document a la ventana del navegador. Una hoja de nivel USER sin
|
||||
* acotar alcanza CUALQUIER documento chrome —el visor de PDF, el inspector, los diálogos— y un
|
||||
* selector genérico como `toolbar` termina pintando ventanas que nadie miró nunca.
|
||||
*/
|
||||
|
||||
@-moz-document url("chrome://browser/content/browser.xhtml") {
|
||||
:root {
|
||||
/* El acento de la distro. Un solo token para que el resto cuelgue de acá y no haya seis
|
||||
* literales de color desperdigados que se desincronizan en la primera edición. */
|
||||
--atuq-acento: #b5651d;
|
||||
--atuq-naranja: #c15728; /* el zorro */
|
||||
--atuq-teal: #1b6470; /* el disco */
|
||||
--atuq-noche: #04161d; /* el anillo */
|
||||
--atuq-crema: #f5ecde; /* los reflejos */
|
||||
--atuq-radio: 8px;
|
||||
}
|
||||
|
||||
/* La pestaña activa: identidad visible sin reescribir la barra entera. */
|
||||
#tabbrowser-tabs .tabbrowser-tab[selected] .tab-background {
|
||||
border-radius: var(--atuq-radio);
|
||||
box-shadow: inset 0 -2px 0 0 var(--atuq-acento);
|
||||
box-shadow: inset 0 -2px 0 0 var(--atuq-naranja);
|
||||
}
|
||||
|
||||
/* La barra de direcciones enfocada usa el acento en vez del azul de Firefox. */
|
||||
/* La barra de direcciones enfocada usa el naranja del zorro en vez del azul de Firefox. */
|
||||
#urlbar[focused="true"] > #urlbar-background {
|
||||
outline-color: var(--atuq-acento);
|
||||
outline-color: var(--atuq-naranja);
|
||||
}
|
||||
|
||||
/* El acento del sistema (botones activos, selección de menú, foco) pasa a ser el de la marca.
|
||||
* `accent-color` es lo que Gecko usa para los widgets nativos del chrome: un solo cambio alcanza
|
||||
* a decenas de controles sin enumerar ninguno. */
|
||||
:root {
|
||||
accent-color: var(--atuq-naranja);
|
||||
}
|
||||
|
||||
/* La barra lateral de pestañas verticales —los «dientes» que prende `atuq.cfg`— con el fondo del
|
||||
* medallón, para que el marco de la ventana y el icono cuenten lo mismo. */
|
||||
#sidebar-main {
|
||||
background-color: color-mix(in srgb, var(--atuq-noche) 92%, var(--atuq-teal));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,17 +22,13 @@ bien (regla 3 del CLAUDE.md).
|
||||
"""
|
||||
import hashlib
|
||||
import os
|
||||
import struct
|
||||
import sys
|
||||
import zlib
|
||||
import zipfile
|
||||
|
||||
APPDIR, OVERLAY, OUTROOT = sys.argv[1], sys.argv[2], sys.argv[3]
|
||||
|
||||
MARCA = "atuq"
|
||||
VENDOR = "tawasuyu"
|
||||
ACENTO = (0xB5, 0x65, 0x1D) # el mismo token que chrome/atuq.css
|
||||
CREMA = (0xF2, 0xE8, 0xD5)
|
||||
TAMANOS = (16, 32, 48, 64, 128)
|
||||
|
||||
|
||||
@@ -147,77 +143,28 @@ def repack_omni(ruta_ja, reemplazos):
|
||||
|
||||
|
||||
# ── 4. El icono ────────────────────────────────────────────────────────────────────────────────
|
||||
# Se DIBUJA acá, en vez de commitear cinco PNG, por una razón práctica: un binario en el árbol de
|
||||
# fuentes no se puede revisar en un diff. El código sí, y el resultado es idéntico en cada build.
|
||||
# Hasta la v0.2 esto DIBUJABA una marca geométrica en código, con el argumento de que un PNG en el
|
||||
# árbol no se puede revisar en un diff. El argumento valía mientras el icono era un marcador de
|
||||
# posición inventado por falta de arte. **Ya hay arte** —el zorro en medallón con cenefa andina— y
|
||||
# entonces el criterio se invierte: un asset de diseño ES la fuente, no un derivado, y meterlo en el
|
||||
# repo es lo correcto. Lo que se conserva es la disciplina: los tamaños salen del MISMO master, se
|
||||
# generan una vez y se copian, así que dos builds ponen los mismos bytes.
|
||||
#
|
||||
# ⚠ ES UN MARCADOR DE POSICIÓN, y conviene que se note: una marca geométrica plana, no un intento de
|
||||
# logo. Lo correcto es que alguien dibuje el zorro; hasta entonces esto cumple la única función que
|
||||
# no puede quedar vacía —que la ventana y el lanzador NO muestren el icono de otro producto—.
|
||||
def _en_rect_redondeado(px, py, n, r):
|
||||
cx = min(max(px, r), n - r)
|
||||
cy = min(max(py, r), n - r)
|
||||
dx, dy = px - cx, py - cy
|
||||
return dx * dx + dy * dy <= r * r
|
||||
|
||||
|
||||
def _en_triangulo(px, py, a, b, c):
|
||||
def signo(p, q, r):
|
||||
return (p[0] - r[0]) * (q[1] - r[1]) - (q[0] - r[0]) * (p[1] - r[1])
|
||||
d1, d2, d3 = signo((px, py), a, b), signo((px, py), b, c), signo((px, py), c, a)
|
||||
neg = d1 < 0 or d2 < 0 or d3 < 0
|
||||
pos = d1 > 0 or d2 > 0 or d3 > 0
|
||||
return not (neg and pos)
|
||||
|
||||
|
||||
def dibujar(size, ss=3):
|
||||
n = size * ss
|
||||
r = n * 0.22
|
||||
# La «oreja»: un triángulo centrado, con la punta arriba. A 16 px cualquier cosa con más de
|
||||
# tres vértices se convierte en barro, así que la forma es deliberadamente una sola.
|
||||
a = (n * 0.50, n * 0.26)
|
||||
b = (n * 0.74, n * 0.72)
|
||||
c = (n * 0.26, n * 0.72)
|
||||
filas = []
|
||||
for y in range(size):
|
||||
fila = []
|
||||
for x in range(size):
|
||||
acc = [0, 0, 0, 0]
|
||||
for sy in range(ss):
|
||||
for sx in range(ss):
|
||||
px, py = x * ss + sx + 0.5, y * ss + sy + 0.5
|
||||
if not _en_rect_redondeado(px, py, n, r):
|
||||
continue
|
||||
col = CREMA if _en_triangulo(px, py, a, b, c) else ACENTO
|
||||
acc[0] += col[0]
|
||||
acc[1] += col[1]
|
||||
acc[2] += col[2]
|
||||
acc[3] += 255
|
||||
m = ss * ss
|
||||
fila.append((acc[0] // m, acc[1] // m, acc[2] // m, acc[3] // m))
|
||||
filas.append(fila)
|
||||
return filas
|
||||
|
||||
|
||||
def png(filas):
|
||||
size = len(filas)
|
||||
crudo = b"".join(b"\x00" + bytes(v for px in f for v in px) for f in filas)
|
||||
|
||||
def trozo(tipo, datos):
|
||||
cuerpo = tipo + datos
|
||||
return struct.pack(">I", len(datos)) + cuerpo + struct.pack(">I", zlib.crc32(cuerpo) & 0xFFFFFFFF)
|
||||
|
||||
ihdr = struct.pack(">IIBBBBB", size, size, 8, 6, 0, 0, 0)
|
||||
return (b"\x89PNG\r\n\x1a\n" + trozo(b"IHDR", ihdr)
|
||||
+ trozo(b"IDAT", zlib.compress(crudo, 9)) + trozo(b"IEND", b""))
|
||||
|
||||
|
||||
# ⚠ A 16 px el medallón pierde el detalle y queda como una mancha cálida redonda. Es intrínseco a un
|
||||
# logo con cenefa, no un defecto del escalado: si molesta, la salida es un dibujo SIMPLIFICADO para
|
||||
# 16 px, y eso lo decide quien dibujó el zorro, no este script.
|
||||
def escribir_iconos():
|
||||
origen = os.path.join(OVERLAY, "branding", "icons")
|
||||
dir_app = os.path.join(APPDIR, "browser", "chrome", "icons", "default")
|
||||
if not os.path.isdir(dir_app):
|
||||
fatal(f"no está {dir_app} — el árbol de firefox no tiene la forma esperada")
|
||||
escritos = []
|
||||
for s in TAMANOS:
|
||||
datos = png(dibujar(s))
|
||||
src = os.path.join(origen, f"atuq{s}.png")
|
||||
if not os.path.isfile(src) or os.path.getsize(src) == 0:
|
||||
fatal(f"falta o está vacío el icono {src}")
|
||||
with open(src, "rb") as fh:
|
||||
datos = fh.read()
|
||||
# (a) el icono de la VENTANA, que Gecko lee del appdir
|
||||
p = os.path.join(dir_app, f"default{s}.png")
|
||||
with open(p, "wb") as fh:
|
||||
|
||||
Reference in New Issue
Block a user