From b7ca8013cc0676436c8643bc97da425988ee7bc4 Mon Sep 17 00:00:00 2001 From: Ilja Heitlager Date: Fri, 7 Aug 2026 13:16:32 +0200 Subject: [PATCH] Restyle to the Lab271 design refresh palette MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remaps Starlight's --sl-color-* tokens from the retired Navy/Primary Blue/Teal (labs-branding) system onto the design refresh: near-black #020C17 anchors dark surfaces (nav bar in both modes), cyan #1EE8ED/#18B9BD is the signature accent, orange #FF7000/#FF8D33 is the one "spark" per composition (the badge), and light mode moves onto a warm paper canvas instead of a cool off-white. Fonts (Inter + JetBrains Mono, standing in for the licensed TT Interphases faces) are unchanged. Vendors the new logo.svg/badge.svg artwork directly from the design team's final export, retiring the Inter-outlined-to-paths generator (scripts/refresh-marks.py, mise run docs-marks) now that the marks are finished artwork rather than something a script can reproduce. Favicons re-exported from the new badge via the existing refresh-icons.sh. Content (repos.json-driven repo list, intro.md, hero copy) is untouched — this is a restyle, not a content change. "Lab271" stays sentence-case in prose per house style; the all-caps treatment lives only in the wordmark graphic. --- .mise.toml | 5 -- AGENTS.md | 48 ++++++----- docs/public/apple-touch-icon.png | Bin 6190 -> 3745 bytes docs/public/favicon-32x32.png | Bin 1117 -> 765 bytes docs/public/favicon.png | Bin 18005 -> 11712 bytes docs/scripts/refresh-marks.py | 135 ------------------------------- docs/src/assets/badge.svg | 21 ++--- docs/src/assets/logo.svg | 17 ++-- docs/src/styles/custom.css | 84 ++++++++++--------- 9 files changed, 96 insertions(+), 214 deletions(-) delete mode 100755 docs/scripts/refresh-marks.py diff --git a/.mise.toml b/.mise.toml index 30f67a4..8fff695 100644 --- a/.mise.toml +++ b/.mise.toml @@ -31,11 +31,6 @@ description = "Regenerate docs/src/data/repos.json from the Lab271 GitHub org" dir = "docs" run = "node scripts/refresh-repos.mjs" -[tasks.docs-marks] -description = "Regenerate src/assets/logo.svg and badge.svg (Inter outlined to paths)" -dir = "docs" -run = "uv run scripts/refresh-marks.py" - [tasks.docs-icons] description = "Re-export the favicon/apple-touch-icon PNGs from src/assets/badge.svg" dir = "docs" diff --git a/AGENTS.md b/AGENTS.md index 4dc7161..eef9649 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -23,7 +23,6 @@ mise run docs-dev # dev server at http://localhost:4321/ mise run docs-check # astro check (type/content check) mise run docs-build # static build into docs/dist mise run docs-repos # regenerate docs/src/data/repos.json from the Lab271 org (needs `gh` auth) -mise run docs-marks # regenerate the logo/badge SVGs (needs uv) mise run docs-icons # re-export the favicon PNGs from src/assets/badge.svg (needs librsvg) ``` @@ -38,11 +37,12 @@ When starting the dev server directly (not via mise), use background mode: - `src/intro.md`: the intro paragraphs, imported into the landing page. - `src/styles/custom.css`: Lab271 brand theme (colors, fonts) mapped onto Starlight's CSS custom properties. - - `src/assets/logo.svg`: the horizontal wordmark used in the nav bar. + - `src/assets/logo.svg`: the horizontal wordmark used in the nav bar. Vendored + from the design team's final artwork (the Lab271 design refresh) rather than + generated - see Branding below. - `src/assets/badge.svg`: the badge mark, and the master for the favicon PNGs - in `public/`. Both SVGs are generated by `scripts/refresh-marks.py` - (`mise run docs-marks`); the PNGs by `scripts/refresh-icons.sh` - (`mise run docs-icons`). + in `public/`. Also vendored artwork. The PNGs are re-exported from it with + `scripts/refresh-icons.sh` (`mise run docs-icons`). - `src/assets/hero.jpg`: the hero photo. - `src/data/repos.json`: committed, auto-generated list of public `Lab271` repos that carry an open source license. Regenerate with `mise run @@ -63,23 +63,33 @@ When starting the dev server directly (not via mise), use background mode: ## Branding -The theme implements the Lab271 brand kit (`labs-branding`, in particular -`brand/visual-identity.md` and `brand/tokens/lab271.tokens.json`). When touching -colors, type or the marks, read those first. The rules that shaped what is here: +The theme implements the Lab271 design refresh (see ADR-0005 in +`Lab271/www.lab271.io`), which supersedes the `labs-branding` +(`brand/visual-identity.md`, `brand/tokens/lab271.tokens.json`) Navy/Primary +Blue/Teal system this site carried before. `labs-branding` has not been +re-derived from the refresh yet, so it is temporarily stale - treat this +repo's `custom.css` and its `www.lab271.io` sibling as authoritative in the +meantime. The rules that shaped what is here: -- **Palette.** Navy `#1A1F36` anchors dark surfaces, including the nav bar in - both color modes. Primary Blue `#6C8EEF` is the signature, Blue Light - `#A8C0FF` its gradient partner. Teal `#36C5B0` is a spark: at most one per - composition, which here is the rule in the badge. Never pure black. +- **Palette.** Near-black `#020C17` anchors dark surfaces, including the nav + bar in both color modes (never pure black). Cyan `#1EE8ED` (dark mode) / + `#18B9BD` (light mode, darkened for contrast) is the signature accent. + Orange `#FF7000`/`#FF8D33` is a spark: at most one per composition, which + here is the rule in the badge. Light mode's canvas is a warm paper off-white + (`#FAF9F5`), not a cool gray. - **Type.** Inter and JetBrains Mono are the open stand-ins for TT Interphases and TT Interphases Mono, the licensed SBP faces that cannot ship on a public - build. Sentence case headings with tight tracking. Mono is "a pinch of tech", - so it is limited to the `e = 2.71828` motif and the language labels. -- **Marks.** `logo.svg` and `badge.svg` set Inter outlined to paths, so they - render without the font installed. The badge follows the brand kit's concept A, - "the door plate". Change them by editing `scripts/refresh-marks.py` and - re-running it, not by editing the path data. -- **Written "Lab271"**, sentence case, no space. Never "LAB271". + build - unchanged by the refresh. Sentence case headings with tight + tracking. Mono is "a pinch of tech", so it is limited to the `e = 2.71828` + motif and the language labels. +- **Marks.** `logo.svg` and `badge.svg` are vendored directly from the design + team's final artwork for the refresh, not generated - the previous + Inter-outlined-to-paths approach (`scripts/refresh-marks.py`) is retired. + Update them by replacing the SVG file with a new export from the design + source, not by hand-editing the path data. +- **Written "Lab271"**, sentence case, no space, in all prose and copy. Never + "LAB271" in running text - the all-caps treatment is reserved for the + wordmark graphic itself (`logo.svg`). - US English throughout. - No em dashes in the copy. `docs/scripts/refresh-repos.mjs` normalizes them out of upstream GitHub descriptions too. diff --git a/docs/public/apple-touch-icon.png b/docs/public/apple-touch-icon.png index 17006ee040ee4397862895c6fc3d046fd25201c5..042d963e2097b6406812152095e4776dbbaf0d79 100644 GIT binary patch delta 3728 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 r3|I{x0?;A90&ZWOxq0Mb0`GC&%Z4a` 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 diff --git a/docs/public/favicon-32x32.png b/docs/public/favicon-32x32.png index c5c2aa7e6661f3273fe2924095320ee38922ee1f..d09d114a787e50b55033ec36919f436bbacaf0bd 100644 GIT binary patch delta 724 zcmV;_0xSL92>k_+HGcxKNklcN28+v(AsmrR!IN>CVv5x9j8+2sx-iBIN%W~ ziXuLruhcfg4h#?qg+xRo5D1j|I*JeUcs#PczAhpn(P&ia>gq~?C_X3>iO61!jg1{0 zKrk2-tumR6`2GIF2XH!_5|77q03ssG%gf?$I1U$JW@bj0_)~gQ7Sm~2Os8dVd^~6U z+2hDHC(`B0T7QjIzh@N%s=K?Jo}M1v_(PH=&9De@yai(%IR`{QNwM5k4?C5yG;S z0${bFnGY>D)w$})CnVoatNzp%*!WWffWzTnX=w?s*MGY&VCq2~_H+_}kKXGH_UDhKBMc*Gk0rl=5lcSJ2khMqgi_=?3X4JKHtcI#M=!(Ex@mu-R-Z zEG*F4+NzIuc@N${Q{5}gPucjJz5UM9cHVs(QRg1s2=mo@S@qxeF0i$>mb0B<3;O%} zjguS5x_<{>(X>D$w>HJ9KX4s@+wEpxV4$Gn0J8UWD0v^0;YXlDN+c2t4-aFv8~3wi z<2Nmhek?nkYiw-dq+$Vqh7(r8p2zCipWoxeKF_LtW;1PEM7gY~y+Z=g71cbwLDQIm ze!_xf(cFRje_S>Mlb^5{X@5&aF|SVnR)L0c08JdLt;OLv2Y|Jvn$*e)saVW3Zk96M zgJR7JB!OEc7GJWasN5+4Pz_8}0zmsUT?K9fmnhT4G}AxSDT;FdcHGc#WNkl?*c`w#B+qn6GMMj!IRLVZSrUj0r4wRj8pCqx zSRIn2jx*6svm!T$C!S6@=&&^~6c|)oQ>4s)Mt_bZM6?mn8<-BLCL)bS1Gz6Q zXV$DFy1IHe{^Ke7`ub6+R1~avdE7a6dnc#QGy<@6$zm2hoQku@#ZNz<8CM^63)0gU z^6lXY5={xAv0j&(wd>#DhP{(()>GpaJaO_@%69GHgZIkVv>_iM1Wo5Il4ssJu0HG* z>@F`O(SMY{M;}*`we%JCAE+TIF@f^8OBom(q+mnYnD+e-zW{Lkx`Qp7*Rr8-6~|AE zA96IpZb4(?c`jdW!BSPr(9jSy2kY6n<27c_PG)#G$eD(wkXEnLV%fi!!9gFEs>5VI zm&NLW?fCrxUdqjxT7b_hYsU0P3N@TW`iPAoGbwCo~6z zr(orZW$Z5BNn4wpeV=|chSTeHY}-=Ez`!7tmT#1li!4Cit1GZn?4_%_mvtMzEE@K8O@9#?b&yuN8QpY8h)hog&C=55$-bdKQ-20bN31$ey!Q(8St@C}r1 z-+##a@9rcR4080llPq7h1OQov+PY%^Y%N}g!Jy~B7l-I|xuY8(KW`-fk|eR~&EnAb z@NkgYx?>m&dWtu%!RsBs^5vl^nZpD>qQy@>hE}V&Yh0FP8qS_0ImtwNdKzwbAAee} zjayu=(~_CFh?_V2x%kJGumOTh@lFs0$bTxp1td+Tj7@(K^;~7Qoq)rI@2Xviv_}P8 z0+vsvj4#Y#M%r9O0sJivoO@~}7s4fxGC!*nM1`WtQHCtoE@{;6Y5{-U2Y;JM>-k!; z*=#-;$qabzq4_N#WV6+3^-BO9?Z5pF!EB)Q9+=yNkh2|spSu7Mxbe@vdmJ5y%;y?8nS||Mngv|f|002ovPDHLkV1nq`65#*< diff --git a/docs/public/favicon.png b/docs/public/favicon.png index a14ea238d454ff0f8e0c63b641a4c53821ad49fd..5c375c8414eba0d57d64fffc551f169a4d4a5ae8 100644 GIT binary patch literal 11712 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 OKLuG8Siw^h|NjN}$n>QE diff --git a/docs/scripts/refresh-marks.py b/docs/scripts/refresh-marks.py deleted file mode 100755 index 5be3c51..0000000 --- a/docs/scripts/refresh-marks.py +++ /dev/null @@ -1,135 +0,0 @@ -#!/usr/bin/env -S uv run --script -# /// script -# requires-python = ">=3.12" -# dependencies = ["fonttools>=4.60", "brotli>=1.1"] -# /// -"""Generate the Lab271 wordmark and badge SVGs. - -Both marks set text in Inter, the brand kit's open stand-in for TT Interphases. -Rather than relying on Inter being installed wherever the SVG is rendered, this -outlines the glyphs to paths, which is what labs-branding's logo/README.md asks -for before an SVG ships. - -Run via `mise run docs-marks`, then `mise run docs-icons` to re-export the -favicon PNGs from the new badge. - -Palette and lockup rules: labs-branding, brand/visual-identity.md sections 1-3. -""" - -from __future__ import annotations - -import urllib.request -from pathlib import Path - -from fontTools.misc.transform import Transform -from fontTools.pens.boundsPen import BoundsPen -from fontTools.pens.svgPathPen import SVGPathPen -from fontTools.pens.transformPen import TransformPen -from fontTools.ttLib import TTFont - -# Inter, latin subset, one file per weight. Pinned to a major version so the -# outlines don't shift under us without a deliberate bump. -FONT_URLS = { - 600: "https://cdn.jsdelivr.net/npm/@fontsource/inter@5/files/inter-latin-600-normal.woff2", - 700: "https://cdn.jsdelivr.net/npm/@fontsource/inter@5/files/inter-latin-700-normal.woff2", -} - -NAVY = "#1A1F36" -BLUE = "#6C8EEF" -BLUE_LIGHT = "#A8C0FF" -TEAL = "#36C5B0" -WHITE = "#FFFFFF" - -HERE = Path(__file__).resolve().parent -ASSETS = HERE.parent / "src" / "assets" -CACHE = HERE / ".font-cache" - - -def font(weight: int) -> TTFont: - CACHE.mkdir(exist_ok=True) - path = CACHE / f"inter-{weight}.woff2" - if not path.exists(): - print(f"downloading {FONT_URLS[weight]}") - with urllib.request.urlopen(FONT_URLS[weight]) as response: - path.write_bytes(response.read()) - return TTFont(path) - - -def run(weight: int, text: str, size: float, tracking: float = 0.0, x: float = 0.0, y: float = 0.0): - """Outline `text` at `size`, returning (path data, advance width, ink bounds). - - `y` is the baseline; `tracking` is extra space per glyph, in the same units - as `size`. No shaping or kerning: the marks are short and set with explicit - tracking anyway. - """ - face = font(weight) - scale = size / face["head"].unitsPerEm - cmap = face.getBestCmap() - glyphs = face.getGlyphSet() - widths = face["hmtx"] - - pen_x = x - paths = [] - bounds = BoundsPen(glyphs) - for char in text: - name = cmap[ord(char)] - placement = Transform(scale, 0, 0, -scale, pen_x, y) - svg = SVGPathPen(glyphs, ntos=lambda value: f"{value:.2f}") - glyphs[name].draw(TransformPen(svg, placement)) - if svg.getCommands(): - paths.append(svg.getCommands()) - glyphs[name].draw(TransformPen(bounds, placement)) - pen_x += widths[name][0] * scale + tracking - # the trailing tracking is space after the last glyph, not part of the run - return " ".join(paths), pen_x - x - tracking, bounds.bounds - - -def wordmark() -> str: - """Horizontal lockup: white "Lab", blue-light "271", tight tracking.""" - size, tracking, baseline = 56, -1.1, 100.0 - lab, lab_width, lab_bounds = run(700, "Lab", size, tracking, 0, baseline) - num, _, num_bounds = run(700, "271", size, tracking, lab_width + tracking, baseline) - - x0 = min(lab_bounds[0], num_bounds[0]) - y0 = min(lab_bounds[1], num_bounds[1]) - x1 = max(lab_bounds[2], num_bounds[2]) - y1 = max(lab_bounds[3], num_bounds[3]) - - return f""" - - - - -""" - - -def badge() -> str: - """Concept A, "the door plate": tracked "Lab" over a large "271", teal rule.""" - side, radius = 512, 117 # radius keeps concept A's 32-at-140px proportion - _, lab_width, _ = run(600, "Lab", 80, 14.6) - _, num_width, _ = run(700, "271", 212, -4) - # centre both lines, ignoring the trailing tracking on "Lab" - lab, _, _ = run(600, "Lab", 80, 14.6, (side - lab_width) / 2, 168) - num, _, _ = run(700, "271", 212, -4, (side - num_width) / 2, 372) - - rule_width, rule_height = 190, 22 - return f""" - - - - - - -""" - - -for name, svg in (("logo.svg", wordmark()), ("badge.svg", badge())): - (ASSETS / name).write_text(svg) - print(f"wrote {ASSETS / name}") diff --git a/docs/src/assets/badge.svg b/docs/src/assets/badge.svg index 3530118..c4aaa18 100644 --- a/docs/src/assets/badge.svg +++ b/docs/src/assets/badge.svg @@ -1,11 +1,12 @@ - - - - - - + + + + + + + + + + + diff --git a/docs/src/assets/logo.svg b/docs/src/assets/logo.svg index cd09630..8cdecb0 100644 --- a/docs/src/assets/logo.svg +++ b/docs/src/assets/logo.svg @@ -1,8 +1,11 @@ - - - - + + + + + + + + + + diff --git a/docs/src/styles/custom.css b/docs/src/styles/custom.css index e1c6f35..0b69d83 100644 --- a/docs/src/styles/custom.css +++ b/docs/src/styles/custom.css @@ -1,47 +1,54 @@ /* Lab271 theme, mapped onto Starlight's design tokens. Palette source: the - Lab271 brand kit (labs-branding, brand/tokens/lab271.tokens.json) - Navy - #1A1F36 (anchor), Primary Blue #6C8EEF (the signature), Blue Light #A8C0FF - (gradient partner), Teal #36C5B0 (the one "spark" per composition), Off-white - #F8F9FB. Dark mode's page background is SBP Full black #020C17, the near-black - the brand kit sanctions in place of pure black, with Navy on top of it as the - nav bar. Starlight derives all surfaces/text/borders from an accent ramp - (low/accent/high), a gray ramp (1=lightest..6/7=darkest in dark mode, - inverted in light) and black/white, so overriding those restyles the whole - site. Dark mode is `:root`; light mode is `:root[data-theme='light']`. */ + Lab271 design refresh (see ADR-0005 in Lab271/www.lab271.io, which supersedes + the Navy/Primary Blue/Teal system this file used to carry from labs-branding) + - near-black #020C17 anchors dark surfaces including both the nav bar and the + canvas itself, cyan #1EE8ED/#18B9BD is the signature accent, orange + #FF7000/#FF8D33 is the one "spark" per composition (the badge's accent rule), + and light mode moves off cool off-white onto the refresh's warm paper canvas + (#FAF9F5). NOTE: labs-branding's brand/tokens/lab271.tokens.json still + reflects the old Navy/Blue/Teal system as of this change - it has not been + re-derived yet, so it is temporarily NOT the source of truth for this + palette; treat this file and its www.lab271.io sibling as authoritative + until labs-branding catches up. Starlight derives all surfaces/text/borders + from an accent ramp (low/accent/high), a gray ramp (1=lightest..6/7=darkest + in dark mode, inverted in light) and black/white, so overriding those + restyles the whole site. Dark mode is `:root`; light mode is + `:root[data-theme='light']`. */ :root { /* Lab271 Dark */ - --sl-color-accent-low: #232a52; - --sl-color-accent: #6c8eef; - --sl-color-accent-high: #a8c0ff; + --sl-color-accent-low: #0d2f34; + --sl-color-accent: #1ee8ed; + --sl-color-accent-high: #8ff3f6; --sl-color-white: #ffffff; /* headings */ --sl-color-gray-1: #eef1f8; --sl-color-gray-2: #c5cbdb; /* body text (fg) */ - --sl-color-gray-3: #9ba3b5; /* muted (grey-400) */ - --sl-color-gray-4: #5f6878; /* dim (grey-600) */ - --sl-color-gray-5: #333a55; /* borders / hairlines */ - --sl-color-gray-6: #1a1f36; /* nav & sidebar bg (Navy) */ - --sl-color-black: #020c17; /* page bg - SBP Full black, the sanctioned near-black */ + --sl-color-gray-3: #8aa0b8; /* muted */ + --sl-color-gray-4: #5f6878; /* dim */ + --sl-color-gray-5: #12263f; /* borders / hairlines */ + --sl-color-gray-6: #020c17; /* nav & sidebar bg - same near-black as the canvas */ + --sl-color-black: #020c17; /* page bg - SBP Full black */ } :root[data-theme='light'] { /* Lab271 Light */ - --sl-color-accent-low: #e9eefc; /* soft periwinkle wash */ - --sl-color-accent: #6c8eef; - --sl-color-accent-high: #3a57c0; /* darkened from blue-dark for link contrast on white */ - --sl-color-white: #1a1f36; /* headings (fg), Navy */ - --sl-color-gray-1: #232942; - --sl-color-gray-2: #2d3142; /* body text (grey-800) */ - --sl-color-gray-3: #5f6878; /* dim (grey-600) */ - --sl-color-gray-4: #9ba3b5; /* faint (grey-400) */ - --sl-color-gray-5: #e2e5eb; /* borders (grey-200) */ - --sl-color-gray-6: #eef1f8; - --sl-color-gray-7: #f8f9fb; /* Off-white */ - --sl-color-black: #ffffff; /* page bg */ + --sl-color-accent-low: #e8f2fd; /* soft blue wash */ + --sl-color-accent: #18b9bd; /* darkened cyan for AA text contrast on white/paper */ + --sl-color-accent-high: #128b8e; + --sl-color-white: #020c17; /* headings (fg) - near-black, not navy */ + --sl-color-gray-1: #1c2b3a; + --sl-color-gray-2: #3d4c5c; /* body text */ + --sl-color-gray-3: #6b7280; /* dim */ + --sl-color-gray-4: #9ba3b5; /* faint */ + --sl-color-gray-5: #e5e0d3; /* borders - warm-tinted, matching the paper canvas */ + --sl-color-gray-6: #f7f5ef; /* panel */ + --sl-color-gray-7: #faf9f5; /* canvas-2 */ + --sl-color-black: #faf9f5; /* page bg - warm paper canvas, not cool off-white */ } /* Fonts: Inter and JetBrains Mono are the brand kit's open stand-ins for TT Interphases and TT Interphases Mono (licensed faces that can't ship on a - public repo/build). Bold headings with tight tracking, 1.5 line-height body, - mono as "a pinch of tech". Webfonts loaded in astro.config.mjs's `head`. */ + public repo/build) - unchanged by the refresh. Bold headings with tight + tracking, 1.5 line-height body, mono as "a pinch of tech". Webfonts loaded + in astro.config.mjs's `head`. */ :root { --sl-font: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; --sl-font-mono: 'JetBrains Mono', 'Fira Code', Consolas, monospace; @@ -53,15 +60,16 @@ h3 { letter-spacing: -0.02em; } -/* Brandbook: Navy is the anchor for dark surfaces, so the nav bar is Navy in - both color modes and the logo has a single variant (white wordmark, blue +/* Near-black is the anchor for dark surfaces, so the nav bar stays near-black + in both color modes and the logo has a single variant (white wordmark, cyan "271" - see src/assets/logo.svg). Scoped to the header so descendants (social icons, theme select) pick up these overridden tokens instead of the page's - light/dark ones, which would otherwise be low-contrast against a navy bar. */ + light/dark ones, which would otherwise be low-contrast against a near-black + bar. */ header.header { - --sl-color-bg-nav: #1a1f36; - --sl-color-hairline-shade: rgba(255, 255, 255, 0.2); - --sl-color-text-accent: #a8c0ff; + --sl-color-bg-nav: #020c17; + --sl-color-hairline-shade: rgba(255, 255, 255, 0.14); + --sl-color-text-accent: #1ee8ed; --sl-color-white: #ffffff; --sl-color-gray-1: #ffffff; --sl-color-gray-2: #eef1f8; @@ -136,7 +144,7 @@ header.header { .card-link:hover .card { transform: translateY(-3px); border-color: var(--sl-color-text-accent); - box-shadow: 0 0.5rem 1rem -0.5rem rgba(26, 31, 54, 0.35); + box-shadow: 0 0.5rem 1rem -0.5rem rgba(2, 12, 23, 0.35); } /* The repository list: two columns of name / language / description, denser