diff options
Diffstat (limited to 'brand')
| -rw-r--r-- | brand/README.es.md | 52 | ||||
| -rw-r--r-- | brand/README.md | 70 | ||||
| -rw-r--r-- | brand/make_logo.py | 246 |
3 files changed, 211 insertions, 157 deletions
diff --git a/brand/README.es.md b/brand/README.es.md new file mode 100644 index 0000000..dc9ab53 --- /dev/null +++ b/brand/README.es.md @@ -0,0 +1,52 @@ +# Marca 100cIA + +[English](README.md) + +El nombre se lee **"ciencia"** (100 = cien, + c + IA) y a la vez deja a la vista +que los videos los hace una IA. El logo apoya las dos lecturas: `100c` en blanco y el `IA` dentro de un chip ámbar +—el mismo recurso que usan los videos—, con un pelín de aire entre medio para que la I +no se lea como barra. + +## Archivos + +| Archivo | Para qué | +|---|---| +| `avatar.svg` / `avatar-1024.png` | **foto de perfil** | +| `avatar-plano.svg` / `avatar-plano-1024.png` | alternativa sin chip | +| `wordmark.svg` / `wordmark-2400.png` | logotipo sobre fondo oscuro | +| `wordmark-claro.svg` | logotipo sobre fondo claro | +| `wordmark-mono.svg` | una sola tinta con el `IA` calado — marca de agua sobre video | +| `wordmark-plano.svg` | logotipo sin chip | +| `banner.svg` / `banner-1920.png` | placa de cierre del video y miniatura | + +El chip alrededor del `IA` es la marca y va en todas las piezas. La versión mono +usa una máscara: el chip es de un solo color y las letras quedan caladas, así que +funciona encima de cualquier fondo. + +**TikTok e Instagram no aceptan SVG para la foto de perfil**: subí los `.png`. +Los `.svg` son para imprimir, escalar o editar. + +## Paleta (la misma de los videos) + +| | | +|---|---| +| fondo | `#0B0F1A` | +| puntitos | `#243050` | +| texto | `#FFFFFF` | +| ámbar (IA, barra de progreso) | `#FFD166` | +| ámbar oscuro (sobre fondo claro) | `#D98C00` | +| track de la barra | `#1B2233` | +| verde | `#06D6A0` · rosa `#EF476F` · celeste `#4CC9F0` | + +Tipografía: **Roboto Black**, tracking −3,5 %. En los SVG el texto ya está +convertido a curvas, así que se ven igual en cualquier máquina. + +El anillo del avatar es la barra de progreso de los videos, curvada: mismo ámbar, +misma proporción (62 %). Es lo que hace reconocible la miniatura a 44 px, donde +el texto ya no se lee. + +## Regenerar + +```bash +python3 brand/make_logo.py # necesita Inkscape y Roboto Black instalados +``` diff --git a/brand/README.md b/brand/README.md index 498efca..18c6058 100644 --- a/brand/README.md +++ b/brand/README.md @@ -1,50 +1,52 @@ -# Marca 100cIA +# 100cIA brand -El nombre se lee **"ciencia"** (100 = cien, + c + IA) y a la vez deja a la vista -que los videos los hace una IA. El logo apoya las dos lecturas: `100c` en blanco y el `IA` dentro de un chip ámbar -—el mismo recurso que usan los videos—, con un pelín de aire entre medio para que la I -no se lea como barra. +[Español](README.es.md) -## Archivos +The name reads **"ciencia"** (science: 100 = cien, + c + IA) and at the same time +makes it clear the videos are made by an AI (IA in Spanish). The logo supports +both readings: `100c` in white and the `IA` inside an amber chip (the same device +the videos use), with a hair of space in between so the I does not read as a bar. -| Archivo | Para qué | +## Files + +| File | What for | |---|---| -| `avatar.svg` / `avatar-1024.png` | **foto de perfil** | -| `avatar-plano.svg` / `avatar-plano-1024.png` | alternativa sin chip | -| `wordmark.svg` / `wordmark-2400.png` | logotipo sobre fondo oscuro | -| `wordmark-claro.svg` | logotipo sobre fondo claro | -| `wordmark-mono.svg` | una sola tinta con el `IA` calado — marca de agua sobre video | -| `wordmark-plano.svg` | logotipo sin chip | -| `banner.svg` / `banner-1920.png` | placa de cierre del video y miniatura | +| `avatar.svg` / `avatar-1024.png` | **profile picture** | +| `avatar-plano.svg` / `avatar-plano-1024.png` | chip-less alternative | +| `wordmark.svg` / `wordmark-2400.png` | wordmark on a dark background | +| `wordmark-claro.svg` | wordmark on a light background | +| `wordmark-mono.svg` | single ink with the `IA` knocked out — watermark over video | +| `wordmark-plano.svg` | chip-less wordmark | +| `banner.svg` / `banner-1920.png` | video end card and thumbnail | -El chip alrededor del `IA` es la marca y va en todas las piezas. La versión mono -usa una máscara: el chip es de un solo color y las letras quedan caladas, así que -funciona encima de cualquier fondo. +The chip around the `IA` is the brand and goes on every piece. The mono version +uses a mask: the chip is a single color and the letters are knocked out, so it +works over any background. -**TikTok e Instagram no aceptan SVG para la foto de perfil**: subí los `.png`. -Los `.svg` son para imprimir, escalar o editar. +**TikTok and Instagram do not accept SVG for the profile picture**: upload the +`.png` files. The `.svg` files are for printing, scaling or editing. -## Paleta (la misma de los videos) +## Palette (the same as the videos) | | | |---|---| -| fondo | `#0B0F1A` | -| puntitos | `#243050` | -| texto | `#FFFFFF` | -| ámbar (IA, barra de progreso) | `#FFD166` | -| ámbar oscuro (sobre fondo claro) | `#D98C00` | -| track de la barra | `#1B2233` | -| verde | `#06D6A0` · rosa `#EF476F` · celeste `#4CC9F0` | +| background | `#0B0F1A` | +| dots | `#243050` | +| text | `#FFFFFF` | +| amber (IA, progress bar) | `#FFD166` | +| dark amber (on light backgrounds) | `#D98C00` | +| bar track | `#1B2233` | +| green | `#06D6A0` · pink `#EF476F` · sky blue `#4CC9F0` | -Tipografía: **Roboto Black**, tracking −3,5 %. En los SVG el texto ya está -convertido a curvas, así que se ven igual en cualquier máquina. +Typeface: **Roboto Black**, −3.5 % tracking. In the SVGs the text is already +converted to curves, so they look the same on any machine. -El anillo del avatar es la barra de progreso de los videos, curvada: mismo ámbar, -misma proporción (62 %). Es lo que hace reconocible la miniatura a 44 px, donde -el texto ya no se lee. +The avatar ring is the videos' progress bar, curved: same amber, same proportion +(62 %). It is what makes the thumbnail recognizable at 44 px, where the text can +no longer be read. -## Regenerar +## Regenerating ```bash -python3 brand/make_logo.py # necesita Inkscape y Roboto Black instalados +python3 brand/make_logo.py # needs Inkscape and Roboto Black installed ``` diff --git a/brand/make_logo.py b/brand/make_logo.py index dac08b5..658e921 100644 --- a/brand/make_logo.py +++ b/brand/make_logo.py @@ -1,30 +1,30 @@ # -*- coding: utf-8 -*- -"""Genera el kit de marca de 100cIA. El texto se convierte a curvas con Inkscape, -asi que los SVG no dependen de que la fuente este instalada.""" +"""Generates the 100cIA brand kit. Text is converted to curves with Inkscape, +so the SVGs do not depend on the font being installed.""" import os, re, subprocess, tempfile import xml.etree.ElementTree as ET HERE = os.path.dirname(os.path.abspath(__file__)) BG = "#0B0F1A" -PUNTOS = "#243050" -BLANCO = "#FFFFFF" -AMBAR = "#FFD166" +POINTS = "#243050" +WHITE_C = "#FFFFFF" +AMBER = "#FFD166" TRACK = "#1B2233" -GRIS = "#8D99AE" +C_GRAY = "#8D99AE" -FUENTE = "Roboto Black" +FONT_NAME = "Roboto Black" TRACKING = -0.035 # em -def curvas(partes, size=400, tracking=TRACKING): - """partes = [(texto, color), ...] -> (svg_interno, x, y, w, h) ya en curvas.""" +def curve_list(parts, size=400, tracking=TRACKING): + """parts = [(text, color), ...] -> (inner_svg, x, y, w, h) already as curves.""" tspans = "".join( f'<tspan fill="{c}"{f" dx=\'{0.045 * size:g}\'" if i else ""}>{t}</tspan>' - for i, (t, c) in enumerate(partes)) + for i, (t, c) in enumerate(parts)) src = (f'<svg xmlns="http://www.w3.org/2000/svg" width="6000" height="1200" ' f'viewBox="0 0 6000 1200"><text id="w" x="60" y="800" ' - f'font-family="{FUENTE}" font-weight="900" font-size="{size}" ' + f'font-family="{FONT_NAME}" font-weight="900" font-size="{size}" ' f'letter-spacing="{tracking * size:g}">{tspans}</text></svg>') with tempfile.TemporaryDirectory() as d: a, b = os.path.join(d, "a.svg"), os.path.join(d, "b.svg") @@ -40,192 +40,192 @@ def curvas(partes, size=400, tracking=TRACKING): NS = "http://www.w3.org/2000/svg" ET.register_namespace("", NS) root = ET.fromstring(raw) - nodo = next(e for e in root.iter() if e.get("id") == "w") - for e in nodo.iter(): + node = next(e for e in root.iter() if e.get("id") == "w") + for e in node.iter(): e.attrib.pop("id", None) e.attrib.pop("aria-label", None) - cuerpo = ET.tostring(nodo, encoding="unicode") - cuerpo = cuerpo.replace(f' xmlns="{NS}"', "") - if not cuerpo.lstrip().startswith("<g"): - cuerpo = f"<g>{cuerpo}</g>" - return cuerpo, q["x"], q["y"], q["width"], q["height"] + body_obj = ET.tostring(node, encoding="unicode") + body_obj = body_obj.replace(f' xmlns="{NS}"', "") + if not body_obj.lstrip().startswith("<g"): + body_obj = f"<g>{body_obj}</g>" + return body_obj, q["x"], q["y"], q["width"], q["height"] -def colocar(g, bx, by, bw, bh, cx, cy, ancho): - s = ancho / bw +def place(g, bx, by, bw, bh, cx, cy, width_px): + s = width_px / bw tx = cx - s * (bx + bw / 2) ty = cy - s * (by + bh / 2) return f'<g transform="translate({tx:.3f},{ty:.3f}) scale({s:.5f})">{g}</g>' -def puntos(id_, sep=118, r=4.2, color=PUNTOS, op=0.55): +def point_list(id_, sep=118, r=4.2, color=POINTS, op=0.55): return (f'<pattern id="{id_}" width="{sep}" height="{sep}" ' f'patternUnits="userSpaceOnUse">' f'<circle cx="{sep/2}" cy="{sep/2}" r="{r}" fill="{color}" ' f'opacity="{op}"/></pattern>') -def arco(cx, cy, r, desde, hasta, color, w): - """Arco en grados, 0 = arriba, sentido horario.""" +def arc_m(cx, cy, r, since, until, color, w): + """Arc in degrees, 0 = up, clockwise.""" import math def p(a): t = math.radians(a - 90) return cx + r * math.cos(t), cy + r * math.sin(t) - x0, y0 = p(desde) - x1, y1 = p(hasta) - largo = 1 if (hasta - desde) % 360 > 180 else 0 + x0, y0 = p(since) + x1, y1 = p(until) + largo = 1 if (until - since) % 360 > 180 else 0 return (f'<path d="M {x0:.2f} {y0:.2f} A {r} {r} 0 {largo} 1 {x1:.2f} {y1:.2f}" ' f'fill="none" stroke="{color}" stroke-width="{w}" stroke-linecap="round"/>') # ---------------------------------------------------------------- avatar -def avatar(archivo, chip=False, pct=0.62): +def avatar(file_path, chip=False, pct=0.62): D = 1024 R = D / 2 - anillo_r, anillo_w = R - 26, 20 + ring_r, ring_w = R - 26, 20 if chip: - g1, x1, y1, w1, h1 = curvas([("100c", BLANCO)]) - g2, x2, y2, w2, h2 = curvas([("IA", "#0B0F1A")]) + g1, x1, y1, w1, h1 = curve_list([("100c", WHITE_C)]) + g2, x2, y2, w2, h2 = curve_list([("IA", "#0B0F1A")]) else: - g1, x1, y1, w1, h1 = curvas([("100c", BLANCO), ("IA", AMBAR)]) + g1, x1, y1, w1, h1 = curve_list([("100c", WHITE_C), ("IA", AMBER)]) - cuerpo = [ + body_obj = [ f'<circle cx="{R}" cy="{R}" r="{R}" fill="{BG}"/>', f'<circle cx="{R}" cy="{R}" r="{R}" fill="url(#dots)"/>', - f'<circle cx="{R}" cy="{R}" r="{anillo_r}" fill="none" ' - f'stroke="{TRACK}" stroke-width="{anillo_w}"/>', - arco(R, R, anillo_r, 0, 360 * pct, AMBAR, anillo_w), + f'<circle cx="{R}" cy="{R}" r="{ring_r}" fill="none" ' + f'stroke="{TRACK}" stroke-width="{ring_w}"/>', + arc_m(R, R, ring_r, 0, 360 * pct, AMBER, ring_w), ] if chip: - ancho_total = 760 - # el chip de "IA" ocupa ~38% del ancho, como los chips de los videos - w_txt = ancho_total * 0.60 - cuerpo.append(colocar(g1, x1, y1, w1, h1, R - ancho_total / 2 + w_txt / 2, R, w_txt)) - esc = w_txt / w1 - cw, ch = w2 * esc * 1.0 + 70, h1 * esc + 62 - cxc = R - ancho_total / 2 + w_txt + 26 + cw / 2 - cuerpo.append(f'<rect x="{cxc - cw/2:.1f}" y="{R - ch/2:.1f}" width="{cw:.1f}" ' - f'height="{ch:.1f}" rx="{ch*0.30:.1f}" fill="{AMBAR}"/>') - cuerpo.append(colocar(g2, x2, y2, w2, h2, cxc, R, w2 * esc)) + total_width = 760 + # the "IA" chip takes ~38% of the width, like the chips in the videos + w_text = total_width * 0.60 + body_obj.append(place(g1, x1, y1, w1, h1, R - total_width / 2 + w_text / 2, R, w_text)) + scale_f = w_text / w1 + cw, ch = w2 * scale_f * 1.0 + 70, h1 * scale_f + 62 + cxc = R - total_width / 2 + w_text + 26 + cw / 2 + body_obj.append(f'<rect x="{cxc - cw/2:.1f}" y="{R - ch/2:.1f}" width="{cw:.1f}" ' + f'height="{ch:.1f}" rx="{ch*0.30:.1f}" fill="{AMBER}"/>') + body_obj.append(place(g2, x2, y2, w2, h2, cxc, R, w2 * scale_f)) else: - cuerpo.append(colocar(g1, x1, y1, w1, h1, R, R, 740)) + body_obj.append(place(g1, x1, y1, w1, h1, R, R, 740)) svg = (f'<svg xmlns="http://www.w3.org/2000/svg" width="{D}" height="{D}" ' - f'viewBox="0 0 {D} {D}"><defs>{puntos("dots")}</defs>' - + "".join(cuerpo) + '</svg>') - open(os.path.join(HERE, archivo), "w", encoding="utf-8").write(svg) - return archivo - - -# ---------------------------------------------------------------- logotipo -# El chip alrededor del "IA" es la marca: va en todas las variantes menos en la -# "plana", que queda como alternativa. -MODOS = { - # tinta fondo del chip letra del chip - "oscuro": (BLANCO, AMBAR, "#0B0F1A"), + f'viewBox="0 0 {D} {D}"><defs>{point_list("dots")}</defs>' + + "".join(body_obj) + '</svg>') + open(os.path.join(HERE, file_path), "w", encoding="utf-8").write(svg) + return file_path + + +# ---------------------------------------------------------------- wordmark +# The chip around "IA" is the brand: it goes on every variant except the +# "flat" one, kept as an alternative. +MODES = { + # ink chip background chip letter + "oscuro": (WHITE_C, AMBER, "#0B0F1A"), "claro": ("#0B0F1A", "#D98C00", "#FFFFFF"), - "mono": (BLANCO, BLANCO, None), # letras caladas + "mono": (WHITE_C, WHITE_C, None), # knocked-out letters } -def _lockup(modo, alto=520): - """Devuelve (piezas_svg, ancho, alto) del lockup '100c' + chip 'IA'.""" - tinta, fondo_chip, letra = MODOS[modo] - g1, x1, y1, w1, h1 = curvas([("100c", tinta)]) - g2, x2, y2, w2, h2 = curvas([("IA", letra or "#000000")]) +def _lockup(mode, alto=520): + """Returns (svg_pieces, width, height) of the '100c' lockup + 'IA' chip.""" + ink, chip_bg, letter = MODES[mode] + g1, x1, y1, w1, h1 = curve_list([("100c", ink)]) + g2, x2, y2, w2, h2 = curve_list([("IA", letter or "#000000")]) - esc = alto / h1 - wt = w1 * esc - cw = w2 * esc + 0.68 * alto + scale_f = alto / h1 + wt = w1 * scale_f + cw = w2 * scale_f + 0.68 * alto ch = alto + 0.60 * alto - hueco = 0.13 * alto - W = wt + hueco + cw + gap_m = 0.13 * alto + W = wt + gap_m + cw cy = ch / 2 rx = ch * 0.28 - cx_chip = wt + hueco + cw / 2 - chip_x = wt + hueco + cx_chip = wt + gap_m + cw / 2 + chip_x = wt + gap_m - piezas = [colocar(g1, x1, y1, w1, h1, wt / 2, cy, wt)] - if letra is None: # una sola tinta: el IA se cala + pieces = [place(g1, x1, y1, w1, h1, wt / 2, cy, wt)] + if letter is None: # a single ink: the IA is knocked out mascara = (f'<mask id="cala">' f'<rect x="{chip_x:.1f}" y="0" width="{cw:.1f}" height="{ch:.1f}" ' f'rx="{rx:.1f}" fill="#FFFFFF"/>' - + colocar(g2, x2, y2, w2, h2, cx_chip, cy, w2 * esc) + + place(g2, x2, y2, w2, h2, cx_chip, cy, w2 * scale_f) + '</mask>') - piezas.append(f'<defs>{mascara}</defs>') - piezas.append(f'<rect x="{chip_x:.1f}" y="0" width="{cw:.1f}" height="{ch:.1f}" ' - f'rx="{rx:.1f}" fill="{fondo_chip}" mask="url(#cala)"/>') + pieces.append(f'<defs>{mascara}</defs>') + pieces.append(f'<rect x="{chip_x:.1f}" y="0" width="{cw:.1f}" height="{ch:.1f}" ' + f'rx="{rx:.1f}" fill="{chip_bg}" mask="url(#cala)"/>') else: - piezas.append(f'<rect x="{chip_x:.1f}" y="0" width="{cw:.1f}" height="{ch:.1f}" ' - f'rx="{rx:.1f}" fill="{fondo_chip}"/>') - piezas.append(colocar(g2, x2, y2, w2, h2, cx_chip, cy, w2 * esc)) - return piezas, W, ch + pieces.append(f'<rect x="{chip_x:.1f}" y="0" width="{cw:.1f}" height="{ch:.1f}" ' + f'rx="{rx:.1f}" fill="{chip_bg}"/>') + pieces.append(place(g2, x2, y2, w2, h2, cx_chip, cy, w2 * scale_f)) + return pieces, W, ch -def wordmark(archivo, modo="oscuro", margen=0.10): - piezas, W0, H0 = _lockup(modo) - m = margen * H0 +def wordmark(file_path, mode="oscuro", margin=0.10): + pieces, W0, H0 = _lockup(mode) + m = margin * H0 W, H = int(round(W0 + 2 * m)), int(round(H0 + 2 * m)) svg = (f'<svg xmlns="http://www.w3.org/2000/svg" width="{W}" height="{H}" ' f'viewBox="0 0 {W} {H}"><g transform="translate({m:.1f},{m:.1f})">' - + "".join(piezas) + '</g></svg>') - open(os.path.join(HERE, archivo), "w", encoding="utf-8").write(svg) - return archivo + + "".join(pieces) + '</g></svg>') + open(os.path.join(HERE, file_path), "w", encoding="utf-8").write(svg) + return file_path -def wordmark_plano(archivo): - """Alternativa sin chip: '100cIA' de corrido, el IA en ambar.""" - g, x, y, w, h = curvas([("100c", BLANCO), ("IA", AMBAR)]) +def wordmark_plano(file_path): + """Chip-less alternative: '100cIA' in one run, the IA in amber.""" + g, x, y, w, h = curve_list([("100c", WHITE_C), ("IA", AMBER)]) W = 2400 - ancho = W * 0.88 - H = int(round(h / w * ancho + 2 * 0.06 * W)) + width_px = W * 0.88 + H = int(round(h / w * width_px + 2 * 0.06 * W)) svg = (f'<svg xmlns="http://www.w3.org/2000/svg" width="{W}" height="{H}" ' f'viewBox="0 0 {W} {H}">' - + colocar(g, x, y, w, h, W / 2, H / 2, ancho) + '</svg>') - open(os.path.join(HERE, archivo), "w", encoding="utf-8").write(svg) - return archivo + + place(g, x, y, w, h, W / 2, H / 2, width_px) + '</svg>') + open(os.path.join(HERE, file_path), "w", encoding="utf-8").write(svg) + return file_path # ---------------------------------------------------------------- banner -def banner(archivo, tagline="ciencia en 40 segundos"): +def banner(file_path, tagline="ciencia en 40 segundos"): W, H = 1920, 1080 - g, x, y, w, h = curvas([("100c", BLANCO)]) - t, tx, ty, tw, th = curvas([(tagline, "#C9D3E5")], size=200, tracking=0.012) - cuerpo = [ + g, x, y, w, h = curve_list([("100c", WHITE_C)]) + t, tx, ty, tw, th = curve_list([(tagline, "#C9D3E5")], size=200, tracking=0.012) + body_obj = [ f'<rect width="{W}" height="{H}" fill="{BG}"/>', f'<rect width="{W}" height="{H}" fill="url(#dots)"/>', f'<rect x="0" y="0" width="{W}" height="12" fill="{TRACK}"/>', - f'<rect x="0" y="0" width="{int(W*0.62)}" height="12" fill="{AMBAR}"/>', - None, # el lockup se arma abajo (con chip, igual que el avatar) - colocar(t, tx, ty, tw, th, W / 2, H / 2 + 205, 830), + f'<rect x="0" y="0" width="{int(W*0.62)}" height="12" fill="{AMBER}"/>', + None, # the lockup is built below (with the chip, like the avatar) + place(t, tx, ty, tw, th, W / 2, H / 2 + 205, 830), ] - # lockup con chip, centrado, a 1150 px de ancho total - g2, x2, y2, w2, h2 = curvas([("IA", "#0B0F1A")]) - ANCHO, cy = 1150, H / 2 - 95 + # lockup with chip, centred, 1150 px total width + g2, x2, y2, w2, h2 = curve_list([("IA", "#0B0F1A")]) + WIDTH, cy = 1150, H / 2 - 95 alto = 210 - esc = alto / h - wt = w * esc - cw, ch = w2 * esc + 0.68 * alto, alto + 0.60 * alto - hueco = 0.13 * alto - total = wt + hueco + cw - k = ANCHO / total - wt, cw, ch, hueco = wt * k, cw * k, ch * k, hueco * k - izq = W / 2 - ANCHO / 2 - cuerpo[cuerpo.index(None)] = ( - colocar(g, x, y, w, h, izq + wt / 2, cy, wt) - + f'<rect x="{izq + wt + hueco:.1f}" y="{cy - ch/2:.1f}" width="{cw:.1f}" ' - f'height="{ch:.1f}" rx="{ch*0.28:.1f}" fill="{AMBAR}"/>' - + colocar(g2, x2, y2, w2, h2, izq + wt + hueco + cw / 2, cy, w2 * esc * k)) + scale_f = alto / h + wt = w * scale_f + cw, ch = w2 * scale_f + 0.68 * alto, alto + 0.60 * alto + gap_m = 0.13 * alto + total = wt + gap_m + cw + k = WIDTH / total + wt, cw, ch, gap_m = wt * k, cw * k, ch * k, gap_m * k + left_part = W / 2 - WIDTH / 2 + body_obj[body_obj.index(None)] = ( + place(g, x, y, w, h, left_part + wt / 2, cy, wt) + + f'<rect x="{left_part + wt + gap_m:.1f}" y="{cy - ch/2:.1f}" width="{cw:.1f}" ' + f'height="{ch:.1f}" rx="{ch*0.28:.1f}" fill="{AMBER}"/>' + + place(g2, x2, y2, w2, h2, left_part + wt + gap_m + cw / 2, cy, w2 * scale_f * k)) svg = (f'<svg xmlns="http://www.w3.org/2000/svg" width="{W}" height="{H}" ' - f'viewBox="0 0 {W} {H}"><defs>{puntos("dots", sep=140, r=5)}</defs>' - + "".join(cuerpo) + '</svg>') - open(os.path.join(HERE, archivo), "w", encoding="utf-8").write(svg) - return archivo + f'viewBox="0 0 {W} {H}"><defs>{point_list("dots", sep=140, r=5)}</defs>' + + "".join(body_obj) + '</svg>') + open(os.path.join(HERE, file_path), "w", encoding="utf-8").write(svg) + return file_path if __name__ == "__main__": - # la variante con chip es la marca: se queda con los nombres principales + # the chip variant is the brand: it keeps the main file names for f in (avatar("avatar.svg", chip=True), avatar("avatar-plano.svg"), wordmark("wordmark.svg", "oscuro"), wordmark("wordmark-claro.svg", "claro"), |