
Netresearch Branding
- 39 installs
- 2 repo stars
- Updated August 2, 2026
- netresearch/netresearch-branding-skill
Helps with ai & agent building tasks.
About
netresearch-branding is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted coding.
- netresearch-branding
- AI & Agent Building
- AI-coding skill
Netresearch Branding by the numbers
- 39 all-time installs (skills.sh)
- Ranked #8,347 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 4, 2026 (Skillselion catalog sync)
npx skills add https://github.com/netresearch/netresearch-branding-skill --skill netresearch-brandingAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 39 |
|---|---|
| repo stars | ★ 2 |
| Last updated | August 2, 2026 |
| Repository | netresearch/netresearch-branding-skill ↗ |
What it does
Helps with ai & agent building tasks.
Files
Netresearch Brand Guidelines (Strict)
Apply Netresearch brand identity to web outputs, documentation, and TYPO3 extensions.
Auto-Trigger Conditions
Apply automatically when any of the following is true:
- GitHub org is
netresearchor composer vendor isnetresearch/ - Creating/modifying HTML pages, dashboards, reports, docs pages, or component demos
- Creating extension icons or branded UI assets
- Prompt contains branding terms (e.g. logo, style guide, brand colors)
- Another skill generates user-facing visual content
Hard Validity Rules
Output is invalid if any item is missing: 1. Header logo (assets/logos/netresearch-symbol-only.svg, or fallback from references/logo-svg.md) 2. Brand colors: #2F99A4 (primary), #FF4D00 (accent only), #585961 (text) 3. Typography intent: Raleway for headlines/UI emphasis, Open Sans for body/forms 4. Footer includes link to https://www.netresearch.de/ and text Netresearch DTT GmbH
If user instructions conflict, keep these rules and explain constraints.
Mandatory Logo Rendering Behavior
Logo source priority: 1. assets/logos/netresearch-symbol-only.svg 2. references/logo-svg.md (inline SVG fallback) 3. references/logo.md (text fallback for SVG-limited agents)
Rules:
- Include logo exactly once in top header/nav for branded pages
- Minimum size
32x32px; recommended40–56pxin headers - Preserve aspect ratio
- No recolor, distortion, filters, shadows, outlines, or substitutions
- If clickable, link to
https://www.netresearch.de/
Active Reference Workflow
Operationalize references in every branded output: 1. references/colors.md for palette/token mapping 2. references/typography.md for font roles and scale 3. references/web-design.md for layout/components/spacing 4. references/logo.md and references/logo-svg.md for logo fallback behavior 5. references/typo3-extension-branding.md for TYPO3 context
Core Brand System
- CSS variables preferred:
--nr-primary,--nr-accent,--nr-text,--nr-border,--nr-bg - Accent orange is highlight-only and must not dominate surfaces
- Accessibility: WCAG AA minimum contrast and semantic structure
- Footer branding is mandatory in user-facing branded pages
TYPO3 Extension Requirements
- Icon path:
Resources/Public/Icons/Extension.svg(teal#2F99A4) - Composer vendor prefix:
netresearch/ author_company:Netresearch DTT GmbH- Description suffix:
- by Netresearch - Contact:
typo3@netresearch.de
Brand Assets
assets/markdown-pdf.css— branded stylesheet formarkdown-to-pdf-skill; apply via--cssfor branded PDFs.assets/markdown-pdf-logo.svg— standalone Netresearch logo (brand-teal/grey); for the running header against the teal background, the CSS expects a white-fill variant supplied via the calling skill's HTML or as a base64 data URI.
References
references/colors.mdreferences/typography.mdreferences/web-design.mdreferences/logo.mdreferences/logo-svg.mdreferences/typo3-extension-branding.mdreferences/README-branding.md
<?xml version="1.0" encoding="UTF-8"?>
<svg
viewBox="-75 -75 440 440"
zoomAndPan="disable"
version="1.2"
baseProfile="tiny-ps"
xmlns="http://www.w3.org/2000/svg">
<title>Netresearch DTT GmbH</title>
<g>
<path
fill="#2999a4"
d="M209.6,0V31.62h32.77a26.38,26.38,0,0,1,26.44,26.43V242a26.38,26.38,0,0,1-26.44,26.44H209.6V300h47.93a42.77,42.77,0,0,0,42.86-42.86V42.89A42.76,42.76,0,0,0,257.53,0ZM43.25,0A42.76,42.76,0,0,0,.39,42.89V257.18A42.76,42.76,0,0,0,43.25,300H91.18V268.46H58.4A26.38,26.38,0,0,1,32,242v-184A26.37,26.37,0,0,1,58.4,31.62H91.18V0Z"
transform="translate(-0.39 -0.04)" />
<path
fill="#595a62"
d="M221.44,120.41c0-34.48-13.94-57.82-48.93-57.82-26.62,0-48.54,7.74-64.17,26.56l-.7-22.06-28.31.06V232.94h31.59V124.69c7.14-18.38,32.14-34.8,53-34.5,27.38.4,25.2,26.24,26,45.81v96.94h31.58"
transform="translate(-0.39 -0.04)" />
</g>
</svg>
/*
* Netresearch markdown-to-PDF brand stylesheet.
*
* Pair with the public markdown-to-pdf-skill via:
* convert.py doc.md --css path/to/this/markdown-pdf.css
*
* Brand colors are exposed as CSS custom properties for easy override
* (per skill rule "Brand Debt Prevention" — use var(--nr-*) over hardcoded hex).
*/
:root {
/* Brand palette */
--nr-primary: #2F99A4; /* Turquoise — primary, links, headings */
--nr-primary-dark: #257880; /* Darker turquoise — h3 */
--nr-accent: #FF4D00; /* Orange — emphasis, accents */
--nr-text: #585961; /* Anthracite — body text */
--nr-text-strong: #3D3D45; /* Strong text */
--nr-text-muted: #999; /* Muted/secondary text — page footer */
--nr-border: #CCCDCC; /* Light grey — borders */
--nr-row-alt: #F5F5F5; /* Even-row table background */
--nr-bg-quote: #EFF9FA; /* Blockquote background */
--nr-bg: #FFFFFF; /* Page / odd-row background */
--nr-code-bg: #1a202c; /* Code block background */
--nr-code-fg: #e2e8f0; /* Code block foreground */
/* Typography */
--nr-font-headline: 'Raleway', Helvetica, Arial, sans-serif;
--nr-font-body: 'Open Sans', Helvetica, Arial, sans-serif;
--nr-font-mono: monospace;
}
@font-face {
font-family: 'Raleway';
font-style: normal;
font-weight: 600;
src: url('https://fonts.gstatic.com/s/raleway/v34/1Ptxg8zYS_SKggPN4iEgvnHyvveLxVs9pYCPNLA3JC9c.ttf') format('truetype');
}
@font-face {
font-family: 'Raleway';
font-style: normal;
font-weight: 700;
src: url('https://fonts.gstatic.com/s/raleway/v34/1Ptxg8zYS_SKggPN4iEgvnHyvveLxVsEpYCPNLA3JC9c.ttf') format('truetype');
}
@font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 400;
src: url('https://fonts.gstatic.com/s/opensans/v40/memSYaGs126MiZpBA-UvWbX2vVnXBbObj2OVZyOOSr4dVJWUgsjZ0C4nY1M2xLER.ttf') format('truetype');
}
@font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 600;
src: url('https://fonts.gstatic.com/s/opensans/v40/memSYaGs126MiZpBA-UvWbX2vVnXBbObj2OVZyOOSr4dVJWUgsg-1y4nY1M2xLER.ttf') format('truetype');
}
/* ── Running header element ── */
.page-header {
position: running(pageHeader);
background: var(--nr-primary);
color: var(--nr-bg);
font-family: var(--nr-font-headline);
font-size: 14px;
font-weight: 700;
padding: 0.3cm 2cm;
border-bottom: 3px solid var(--nr-accent);
margin: 0;
line-height: 1;
}
.header-logo {
vertical-align: middle;
margin-right: 0.15cm;
width: 24px;
height: 24px;
}
/* ── Running footer element ── */
.page-footer {
position: running(pageFooter);
border-top: 1px solid var(--nr-border);
padding: 0.3cm 2cm 0;
margin: 0;
font-family: var(--nr-font-body);
font-size: 8px;
color: var(--nr-text-muted);
display: flex;
justify-content: space-between;
}
.footer-info {
flex: 1;
text-align: center;
}
/*
* Page label is intentionally English ("Page N").
* For German output, override after this stylesheet:
* .footer-page::after { content: "Seite " counter(page); }
*/
.footer-page::after {
content: "Page " counter(page);
}
@page {
size: A4;
margin: 1.8cm 0 1.4cm 0;
/* ── Header: running element fills full margin — no gaps ── */
@top-left {
content: element(pageHeader);
width: 100%;
padding: 0;
margin: 0;
vertical-align: top;
}
/* ── Footer: running element fills full margin — no gaps ── */
@bottom-left {
content: element(pageFooter);
width: 100%;
padding: 0;
margin: 0;
}
}
body {
font-family: var(--nr-font-body);
font-size: 11px;
line-height: 1.5;
color: var(--nr-text);
/* Horizontal padding replaces zero page side margins; top adds header gap */
padding: 0.4cm 2cm 0;
}
h1, h2, h3, h4 {
font-family: var(--nr-font-headline);
}
h1 {
font-size: 22px;
font-weight: 700;
color: var(--nr-primary);
border-bottom: 2px solid var(--nr-accent);
padding-bottom: 6px;
margin-top: 24px;
margin-bottom: 12px;
}
h2 {
font-size: 17px;
font-weight: 600;
color: var(--nr-primary);
border-bottom: 1px solid var(--nr-border);
padding-bottom: 4px;
margin-top: 20px;
margin-bottom: 10px;
}
h3 {
font-size: 14px;
font-weight: 600;
color: var(--nr-primary-dark);
margin-top: 16px;
margin-bottom: 8px;
}
h4 {
font-size: 12px;
font-weight: 600;
color: var(--nr-text);
margin-top: 12px;
margin-bottom: 6px;
}
h2, h3, h4 { page-break-after: avoid; }
table {
border-collapse: collapse;
width: 100%;
margin: 10px 0;
font-size: 10px;
page-break-inside: avoid;
}
thead { display: table-header-group; }
tr { page-break-inside: avoid; }
th {
background-color: var(--nr-primary);
color: var(--nr-bg);
font-weight: 600;
padding: 6px 8px;
text-align: left;
border: 1px solid var(--nr-primary);
}
td {
padding: 5px 8px;
border: 1px solid var(--nr-border);
}
tr:nth-child(even) td {
background-color: var(--nr-row-alt);
}
tr:nth-child(odd) td {
background-color: var(--nr-bg);
}
code {
background-color: var(--nr-row-alt);
padding: 1px 4px;
border-radius: 3px;
font-family: var(--nr-font-mono);
font-size: 10px;
color: var(--nr-accent);
}
/*
* pre: wrap long lines instead of clipping with overflow:hidden, which
* silently drops content past the right margin in PDF output.
* white-space: pre-wrap preserves indentation and line breaks while
* wrapping long lines. overflow-wrap: anywhere handles tokens longer
* than the printable width (standard CSS3 property; replaces the
* non-standard word-break: break-word).
*/
pre {
background-color: var(--nr-code-bg);
color: var(--nr-code-fg);
padding: 12px;
border-radius: 4px;
font-size: 10px;
line-height: 1.4;
white-space: pre-wrap;
overflow-wrap: anywhere;
margin: 10px 0;
page-break-inside: avoid;
}
pre code {
background-color: transparent;
color: var(--nr-code-fg);
padding: 0;
}
blockquote {
border-left: 3px solid var(--nr-primary);
margin: 10px 0;
padding: 8px 12px;
background-color: var(--nr-bg-quote);
color: var(--nr-text);
font-style: italic;
page-break-inside: avoid;
}
img {
page-break-inside: avoid;
max-width: 100%;
}
strong {
color: var(--nr-text-strong);
}
hr {
border: none;
border-top: 1px solid var(--nr-border);
margin: 16px 0;
}
ul, ol {
margin: 6px 0;
padding-left: 20px;
}
li {
margin-bottom: 3px;
}
/*
* Note: deliberately do NOT apply page-break-inside: avoid to <p> or
* <ul>/<ol>. Forcing every paragraph and list to stay on one page causes
* large unsightly empty gaps at the bottom of pages when the next
* paragraph is long. Let WeasyPrint break naturally inside body prose;
* keep page-break-inside only on visually-bounded blocks (tables, pre,
* blockquote, img) where mid-element breaks are jarring.
*/
# Checkpoints for netresearch-branding skill
# Validates Netresearch brand compliance for extensions
version: 1
skill_id: netresearch-branding
mechanical:
# ============================================================
# TYPO3-EXTENSION-SPECIFIC CHECKS (NB-01..NB-03, NB-09..NB-14)
# ============================================================
# The runner only supports a single top-level `preconditions:` block,
# which would gate the entire skill (including the universal README
# checks below). To keep the README checks running on ALL Netresearch
# repos while skipping TYPO3 plumbing on non-TYPO3 ones, each TYPO3
# check below is rewritten as a `type: command` with an inline guard
# pipeline of the form:
#
# cat composer.json ext_emconf.php 2>/dev/null \
# | grep -E "typo3-cms-(extension|framework)|EM_CONF\[" \
# | head -1 \
# | xargs -r -I{} <actual-check>
#
# Detection logic (matches user spec):
# - composer.json containing the substring `typo3-cms-extension` or
# `typo3-cms-framework` (only TYPO3 composer types use that prefix), OR
# - ext_emconf.php existing (every ext_emconf.php contains `EM_CONF[`).
#
# Behaviour on non-TYPO3 repos: the grep produces no output, xargs -r
# runs nothing, the pipeline exits 0, the checkpoint passes trivially
# (= correctly N/A). On TYPO3 repos, the actual check runs and its
# exit code drives pass/fail.
#
# Single-pipeline construction is required by the runner allowlist
# (no `;`, `&&`, `||`, `$()`, or backticks).
# === EXTENSION ICON CHECKS (TYPO3-only) ===
- id: NB-01
type: command
pattern: 'cat composer.json ext_emconf.php 2>/dev/null | grep -E "typo3-cms-(extension|framework)|EM_CONF\[" | head -1 | xargs -r -I{} test -f Resources/Public/Icons/Extension.svg'
severity: error
desc: "Extension icon (SVG) must exist (TYPO3 extensions only)"
- id: NB-02
type: command
pattern: 'cat composer.json ext_emconf.php 2>/dev/null | grep -E "typo3-cms-(extension|framework)|EM_CONF\[" | head -1 | xargs -r -I{} grep -qF "#2F99A4" Resources/Public/Icons/Extension.svg'
severity: error
desc: "Extension icon must use Netresearch teal #2F99A4 (TYPO3 extensions only)"
# PNG fallback was needed for TYPO3 v11 and earlier. v12+ renders SVG
# icons natively in the BE; PNG is dead weight on modern projects.
# Pass when PNG is ABSENT (recommended for v12+ projects). If a project
# also targets v11 or older, it can opt-in to keep the PNG by ignoring
# this rule. Skipped on non-TYPO3 repos.
- id: NB-03
type: command
pattern: 'cat composer.json ext_emconf.php 2>/dev/null | grep -E "typo3-cms-(extension|framework)|EM_CONF\[" | head -1 | xargs -r -I{} test ! -f Resources/Public/Icons/Extension.png'
severity: info
desc: "Extension.png should NOT exist for TYPO3 v12+ projects (SVG renders natively; PNG is dead weight). Only keep PNG if extension targets TYPO3 v11 or older."
# === README BRANDING CHECKS (universal) ===
- id: NB-04
type: regex
target: README.md
pattern: "[Nn]etresearch"
severity: error
desc: "README must credit Netresearch"
- id: NB-05
type: contains
target: README.md
pattern: "netresearch.de"
severity: warning
desc: "README should link to netresearch.de"
# === BRAND COLOR CHECKS (in CSS/SCSS files) ===
# Glob-based; auto-skips with status=skip when no CSS files match.
- id: NB-06
type: not_contains
target: Resources/Public/Css/*.css
pattern: "#2f99a4"
severity: info
desc: "CSS should use uppercase brand color #2F99A4 (not lowercase)"
- id: NB-07
type: not_contains
target: Resources/Public/Css/*.css
pattern: "#ff4d00"
severity: info
desc: "CSS should use uppercase brand color #FF4D00 (not lowercase)"
- id: NB-08
type: not_contains
target: Resources/Public/Css/*.css
pattern: "#585961"
severity: info
desc: "CSS should use uppercase brand color #585961 (not lowercase)"
# === COMPOSER.JSON BRANDING (TYPO3-only) ===
- id: NB-09
type: command
pattern: 'cat composer.json ext_emconf.php 2>/dev/null | grep -E "typo3-cms-(extension|framework)|EM_CONF\[" | head -1 | xargs -r -I{} grep -qE "\"name\".*\"netresearch/" composer.json'
severity: error
desc: "Composer package name must use netresearch/ vendor prefix (TYPO3 extensions only)"
- id: NB-10
type: command
pattern: 'cat composer.json ext_emconf.php 2>/dev/null | grep -E "typo3-cms-(extension|framework)|EM_CONF\[" | head -1 | xargs -r -I{} jq -e ".authors[] | select(.name == \"Netresearch DTT GmbH\")" composer.json'
severity: warning
desc: "Composer should list Netresearch DTT GmbH as author (TYPO3 extensions only)"
# === NETRESEARCH LOGO ([n]) CHECKS (TYPO3-only) ===
# SVG-only on TYPO3 v12+. The brand asset gives extensions visual
# identity in About pages, README rendering, and any custom UI.
- id: NB-11
type: command
pattern: 'cat composer.json ext_emconf.php 2>/dev/null | grep -E "typo3-cms-(extension|framework)|EM_CONF\[" | head -1 | xargs -r -I{} test -f Resources/Public/Images/netresearch-logo.svg'
severity: info
desc: "Netresearch [n] logo (SVG) should be present for brand identity (TYPO3 extensions only)"
# PNG fallback obsolete on v12+ (same logic as NB-03). Pass when absent.
- id: NB-12
type: command
pattern: 'cat composer.json ext_emconf.php 2>/dev/null | grep -E "typo3-cms-(extension|framework)|EM_CONF\[" | head -1 | xargs -r -I{} test ! -f Resources/Public/Images/netresearch-logo.png'
severity: info
desc: "Netresearch logo PNG fallback should NOT exist on TYPO3 v12+ projects (SVG renders natively). Only keep PNG if targeting v11 or older."
# === EXT_EMCONF BRANDING (TYPO3-only) ===
- id: NB-13
type: command
pattern: 'cat composer.json ext_emconf.php 2>/dev/null | grep -E "typo3-cms-(extension|framework)|EM_CONF\[" | head -1 | xargs -r -I{} grep -qF "Netresearch DTT GmbH" ext_emconf.php'
severity: error
desc: "ext_emconf.php author_company must be 'Netresearch DTT GmbH' (TYPO3 extensions only)"
- id: NB-14
type: command
pattern: 'cat composer.json ext_emconf.php 2>/dev/null | grep -E "typo3-cms-(extension|framework)|EM_CONF\[" | head -1 | xargs -r -I{} grep -qE -- "- by Netresearch" ext_emconf.php'
severity: warning
desc: "ext_emconf.php description should end with '- by Netresearch' (TYPO3 extensions only)"
# === TYPOGRAPHY CHECK ===
- id: NB-15
type: regex
target: "Resources/Public/Css/*.css"
pattern: "Raleway|Open.Sans"
severity: info
desc: "CSS should reference Raleway and/or Open Sans fonts per brand guidelines"
# === CSS VARIABLES ===
- id: NB-16
type: regex
target: "Resources/Public/Css/*.css"
pattern: "--nr-(primary|accent|text)"
severity: info
desc: "CSS should use brand CSS variables (--nr-primary, --nr-accent, --nr-text)"
# === FOOTER LINK ===
- id: NB-17
type: regex
target: "Resources/Private/Templates/**/*.html"
pattern: "netresearch\\.de"
severity: info
desc: "Templates with footer should link to netresearch.de"
- id: NB-18
type: regex
target: "Resources/Private/Templates/**/*.html"
pattern: "netresearch-(symbol-only|logo)\\.svg|aria-label=\"Netresearch symbol logo\"|<title>Netresearch DTT GmbH</title>"
severity: warning
desc: "Branded templates should include the Netresearch logo (NB-11 SVG asset path or an inline SVG with the brand-labeled aria-label/title)"
- id: NB-19
type: regex
target: "Resources/Private/Templates/**/*.html"
pattern: "Netresearch DTT GmbH"
severity: warning
desc: "Footer should include exact company name 'Netresearch DTT GmbH'"
# ============================================================
# README HEADLINE & FOOTER BRANDING (universal, non-TYPO3 too)
# ============================================================
# These apply to ANY Netresearch repo (TYPO3 extension, Claude skill,
# internal tool, etc.). Implemented as `type: command` single
# pipelines that pass the runner allowlist (no `;`, `&&`, `||`,
# `$()`, backticks). See references/README-branding.md for the
# human-readable spec, examples, and rationale.
# === README HEADLINE ===
# Case-insensitive match. Accepts:
# - a `netresearch.de` link
# - the company name "Netresearch DTT"
# - the TYPO3 ext_emconf convention "by Netresearch" (description suffix)
- id: NB-30
type: command
pattern: "head -30 README.md | grep -qiE 'netresearch\\.de|Netresearch DTT|by Netresearch'"
severity: warning
desc: "README headline references Netresearch in first 30 lines (netresearch.de link, 'Netresearch DTT', or 'by Netresearch')"
# === README FOOTER: COMPANY NAME ===
- id: NB-31
type: command
pattern: "tail -20 README.md | grep -qiE 'Netresearch DTT'"
severity: warning
desc: "README footer credits Netresearch DTT GmbH (last 20 lines)"
# === README FOOTER: WEBSITE LINK ===
- id: NB-32
type: command
pattern: "tail -20 README.md | grep -qiE 'netresearch\\.de'"
severity: info
desc: "README footer links to https://www.netresearch.de/ (last 20 lines)"
# === README LICENSE MENTION ===
# Case-insensitive — accepts "License", "LICENSE", "licensed under",
# SPDX badges with `/license/` in the URL, etc.
- id: NB-33
type: command
pattern: "grep -qi 'license' README.md"
severity: info
desc: "README mentions licensing (case-insensitive — accepts License/LICENSE heading, 'licensed under', SPDX license badge URLs, etc.)"
llm_reviews:
# === REPOSITORY DESCRIPTION CHECK ===
- id: NB-20
domain: branding
prompt: |
Check the GitHub repository description (via gh api repos/{owner}/{repo} --jq '.description').
The description MUST end with "- by Netresearch".
Examples of COMPLIANT descriptions:
- "TYPO3 extension for newsletter management - by Netresearch"
- "Modern address validation service integration - by Netresearch"
Examples of NON-COMPLIANT descriptions:
- "TYPO3 extension for newsletters" (missing suffix)
- "by Netresearch - Newsletter extension" (suffix not at end)
- null or empty description
Report PASS if compliant, FAIL if not.
severity: error
desc: "Repository description must end with '- by Netresearch'"
# === EXTENSION ICON VISUAL CHECK ===
- id: NB-21
domain: branding
prompt: |
Visually inspect the extension icon at Resources/Public/Icons/Extension.svg or Extension.png.
Check for:
1. Primary color is Netresearch teal (#2F99A4)
2. Icon is clean and professional
3. Icon represents the extension's purpose
4. Icon works at small sizes (16x16, 32x32)
The icon should be immediately recognizable as a Netresearch product
through its use of the brand teal color.
severity: warning
desc: "Extension icon should visually reflect Netresearch branding"
# === BRAND COLORS CONSISTENCY ===
- id: NB-22
domain: branding
prompt: |
Review CSS, SCSS, and template files for brand color usage.
Netresearch brand colors:
- Primary Teal: #2F99A4 (main brand color)
- Accent Orange: #FF4D00 (highlights, CTAs)
- Neutral Gray: #585961 (text, secondary elements)
Check for:
1. Brand colors used consistently (not random colors)
2. Correct hex values (case-insensitive match is OK)
3. No conflicting brand colors from other organizations
4. Appropriate color contrast for accessibility
Report any incorrect or inconsistent brand color usage.
severity: warning
desc: "Brand colors should be used consistently (#2F99A4, #FF4D00, #585961)"
# === README CREDITS SECTION ===
- id: NB-23
domain: branding
prompt: |
Check the README.md for proper Netresearch credits.
The README should include:
1. Mention of "Netresearch" or "Netresearch DTT GmbH"
2. Link to https://www.netresearch.de
3. Ideally a "Credits" or "About" section at the bottom
Example acceptable credits:
- "Developed by [Netresearch DTT GmbH](https://www.netresearch.de)"
- "This extension is maintained by Netresearch."
- A footer with Netresearch logo and link
Report PASS if adequately credited, FAIL if not.
severity: error
desc: "README must properly credit Netresearch"
# === [n] LOGO PLACEMENT ===
- id: NB-24
domain: branding
prompt: |
Check if the Netresearch [n] logo is appropriately used where applicable.
Appropriate placements:
1. Backend module headers (if extension has backend modules)
2. Documentation pages
3. README footer
4. Configuration screens (if applicable)
The [n] logo should be:
- Used sparingly (not overwhelming)
- Properly sized and positioned
- Linking to netresearch.de when clickable
Note: Not all extensions need the [n] logo. This is more
relevant for user-facing features.
Report appropriate usage or suggest improvements.
severity: info
desc: "Netresearch [n] logo should be used where appropriate"
# === HARD VALIDITY ENFORCEMENT ===
- id: NB-25
domain: branding
prompt: |
Validate generated user-facing visual outputs against strict Netresearch requirements.
Mark FAIL if ANY of the following are missing:
1. Header logo (symbol-only [n], SVG preferred)
2. Brand colors #2F99A4, #FF4D00 (accent only), #585961
3. Typography intent: Raleway for headlines/UI emphasis, Open Sans for body
4. Footer containing both "Netresearch DTT GmbH" and a link to the
Netresearch website. Accept either `https://www.netresearch.de/`
or `https://www.netresearch.de` (trailing slash optional).
This is a hard validity gate: partial compliance is FAIL.
severity: error
desc: "Outputs are invalid unless core brand constraints are all satisfied"
# === REFERENCE WORKFLOW ENFORCEMENT ===
- id: NB-26
domain: branding
prompt: |
Check whether the implementation actively followed brand references instead of treating them as passive docs.
Required references for branded web output:
- references/colors.md
- references/typography.md
- references/web-design.md
- references/logo.md or references/logo-svg.md
PASS only if output decisions clearly align with these references
(color tokens, typography roles, component patterns, logo behavior).
severity: warning
desc: "Brand references must be operationalized in implementation decisions"
Netresearch Brand Colors Reference
Complete color palette with technical specifications and usage guidelines.
Primary Brand Colors
Turquoise (Primary)
Technical Specifications:
- Hex:
#2F99A4 - RGB:
rgb(47, 153, 164) - CMYK:
C71 M7 Y17 K36 - Pantone: 7709 C (approximate)
- NCS: S 3040-B30G
Usage:
- Primary brand color for all digital and print materials
- Main CTA buttons and interactive elements
- Headers and key visual elements
- Links in default state
- Primary navigation highlights
- Brand identity elements
Contrast Ratios (WCAG AA):
- On white background: 3.8:1 (Meets AA for large text)
- On #F5F5F5: 4.2:1 (Meets AA for large text)
- White text on turquoise: 4.5:1 (Meets AA for all text)
Web Implementation:
:root {
--color-primary: #2F99A4;
--color-primary-rgb: 47, 153, 164;
}
.btn-primary {
background-color: var(--color-primary);
color: #FFFFFF;
}
.link-primary {
color: var(--color-primary);
}---
Orange (Accent)
Technical Specifications:
- Hex:
#FF4D00 - RGB:
rgb(255, 77, 0) - CMYK:
C0 M70 Y100 K0 - Pantone: 172 C (approximate)
- NCS: S 1080-Y60R
Usage:
- Accent color for emphasis and highlights
- Secondary CTA buttons
- Important notifications and alerts
- Hover states on primary elements
- Call-out boxes and highlights
- Limited use - accent only, not dominant
Contrast Ratios (WCAG AA):
- On white background: 3.9:1 (Meets AA for large text)
- On #F5F5F5: 4.3:1 (Meets AA for large text)
- White text on orange: 3.2:1 (Meets AA for large text only)
Web Implementation:
:root {
--color-accent: #FF4D00;
--color-accent-rgb: 255, 77, 0;
}
.btn-secondary {
background-color: var(--color-accent);
color: #FFFFFF;
}
.highlight {
border-left: 4px solid var(--color-accent);
}---
Neutral Colors
Anthracite (Text Primary)
Technical Specifications:
- Hex:
#585961 - RGB:
rgb(88, 89, 97) - CMYK: C9 M2 Y0 K62`
- NCS: S 5502-B
Usage:
- Primary text color for body copy
- Headlines and subheadings
- Navigation text
- Form labels
- Default icon color
Contrast Ratios (WCAG AA):
- On white background: 8.3:1 (Meets AAA for all text)
- On #F5F5F5: 7.8:1 (Meets AAA for all text)
Web Implementation:
:root {
--color-text-primary: #585961;
}
body, p, h1, h2, h3 {
color: var(--color-text-primary);
}---
Light Grey (Backgrounds)
Technical Specifications:
- Hex:
#CCCDCC - RGB:
rgb(204, 205, 204) - CMYK: C0 M0 Y0 K20`
- NCS: S 2000-N
Usage:
- Background sections and cards
- Subtle borders and dividers
- Disabled states
- Alternating table rows
- Input field borders
Contrast Note:
- Not suitable for text on white background
- Use for backgrounds and UI elements only
Web Implementation:
:root {
--color-background-light: #CCCDCC;
--color-border-light: #CCCDCC;
}
.card {
background-color: #F5F5F5;
border: 1px solid var(--color-border-light);
}---
White (Background)
Technical Specifications:
- Hex:
#FFFFFF - RGB:
rgb(255, 255, 255)
Usage:
- Primary background color
- Text on dark backgrounds
- Card backgrounds
- Clean, spacious layouts
---
Color Combinations
Approved Combinations
Primary Palette:
/* Turquoise on white - Primary brand */
.combination-1 {
background: #FFFFFF;
color: #2F99A4;
}
/* White text on turquoise - High impact */
.combination-2 {
background: #2F99A4;
color: #FFFFFF;
}
/* Orange accent with turquoise */
.combination-3 {
background: #2F99A4;
border-color: #FF4D00;
color: #FFFFFF;
}Text Combinations:
/* Body text on white - Standard */
.text-standard {
background: #FFFFFF;
color: #585961;
}
/* Body text on light grey - Sections */
.text-section {
background: #F5F5F5;
color: #585961;
}Avoid These Combinations
❌ Never Use:
- Orange on turquoise (poor contrast)
- Light grey text on white (fails WCAG)
- Turquoise text smaller than 18px on white (AA compliance)
- Orange text on white for small text (fails AA)
---
Accessibility Guidelines
WCAG AA Compliance
Minimum Contrast Ratios:
- Normal text (< 18px): 4.5:1
- Large text (≥ 18px): 3:1
- UI components: 3:1
Approved Text Combinations:
✅ Pass AA for All Text Sizes:
- Anthracite (#585961) on white: 8.3:1 ✓
- Anthracite (#585961) on #F5F5F5: 7.8:1 ✓
- White on turquoise (#2F99A4): 4.5:1 ✓
✅ Pass AA for Large Text Only:
- Turquoise (#2F99A4) on white: 3.8:1 ✓
- Orange (#FF4D00) on white: 3.9:1 ✓
- White on orange (#FF4D00): 3.2:1 ✓
❌ Fail AA (Do Not Use):
- Light grey (#CCCDCC) on white: 1.6:1 ✗
---
Usage Guidelines by Context
Websites
- Primary color: Turquoise for headers, links, CTAs
- Accent color: Orange sparingly for emphasis
- Background: White (#FFFFFF) or subtle off-white (#F5F5F5)
- Text: Anthracite (#585961)
- High white space: Let colors breathe
Social Media
- Header images: Turquoise primary with orange accents
- Profile elements: Turquoise logo on white
- Post graphics: Maximum 2 brand colors per graphic
Documents
- Headers: Turquoise or anthracite
- Highlights: Orange for key information
- Body text: Anthracite
- Backgrounds: White primary, light grey for emphasis
Presentations
- Title slides: Turquoise background with white text
- Content slides: White background with turquoise accents
- Emphasis: Orange for key points
---
CSS Custom Properties (Complete Set)
:root {
/* Primary Colors */
--color-primary: #2F99A4;
--color-primary-rgb: 47, 153, 164;
--color-primary-light: rgba(47, 153, 164, 0.1);
--color-primary-dark: #257880;
/* Accent Colors */
--color-accent: #FF4D00;
--color-accent-rgb: 255, 77, 0;
--color-accent-light: rgba(255, 77, 0, 0.1);
--color-accent-dark: #CC3D00;
/* Neutral Colors */
--color-text-primary: #585961;
--color-text-secondary: #8A8B93;
--color-background: #FFFFFF;
--color-background-alt: #F5F5F5;
--color-border: #CCCDCC;
--color-border-light: #E5E5E5;
/* Semantic Colors */
--color-success: #28A745;
--color-warning: #FFC107;
--color-error: #DC3545;
--color-info: var(--color-primary);
}---
Sass/SCSS Variables
// Primary Colors
$color-primary: #2F99A4;
$color-accent: #FF4D00;
// Neutral Colors
$color-anthracite: #585961;
$color-light-grey: #CCCDCC;
$color-white: #FFFFFF;
// Backgrounds
$color-bg-primary: $color-white;
$color-bg-secondary: #F5F5F5;
// Text
$color-text-primary: $color-anthracite;
$color-text-secondary: lighten($color-anthracite, 15%);
// Borders
$color-border: $color-light-grey;
$color-border-light: #E5E5E5;---
Color Testing Checklist
Before deploying any brand materials:
- [ ] All text meets WCAG AA contrast requirements
- [ ] Turquoise is primary, orange is accent only
- [ ] No unapproved color combinations used
- [ ] Colors match exact hex values
- [ ] High white space maintained
- [ ] Tested on multiple displays for color accuracy
- [ ] Print materials use CMYK values
- [ ] Digital materials use RGB/Hex values
---
Last updated: 2025-10-18 Maintained by: Netresearch DTT GmbH
Netresearch Logo SVG Reference
Use this file when agents cannot open files from assets/ directly.
Canonical source
- Preferred source:
assets/logos/netresearch-symbol-only.svg - This copy mirrors the symbol geometry and preserves the original structure.
Inline SVG (brand-normalized colors)
<svg
viewBox="-75 -75 440 440"
xmlns="http://www.w3.org/2000/svg"
role="img"
aria-label="Netresearch symbol logo">
<title>Netresearch DTT GmbH</title>
<g>
<path
fill="#2F99A4"
d="M209.6,0V31.62h32.77a26.38,26.38,0,0,1,26.44,26.43V242a26.38,26.38,0,0,1-26.44,26.44H209.6V300h47.93a42.77,42.77,0,0,0,42.86-42.86V42.89A42.76,42.76,0,0,0,257.53,0ZM43.25,0A42.76,42.76,0,0,0,.39,42.89V257.18A42.76,42.76,0,0,0,43.25,300H91.18V268.46H58.4A26.38,26.38,0,0,1,32,242v-184A26.37,26.37,0,0,1,58.4,31.62H91.18V0Z"
transform="translate(-0.39 -0.04)" />
<path
fill="#585961"
d="M221.44,120.41c0-34.48-13.94-57.82-48.93-57.82-26.62,0-48.54,7.74-64.17,26.56l-.7-22.06-28.31.06V232.94h31.59V124.69c7.14-18.38,32.14-34.8,53-34.5,27.38.4,25.2,26.24,26,45.81v96.94h31.58"
transform="translate(-0.39 -0.04)" />
</g>
</svg>Usage contract
- Minimum rendered size:
32×32px - Recommended header size:
40–56px - Keep aspect ratio
- Do not apply filters, shadows, or recoloring
- If clickable, link to
https://www.netresearch.de/
HTML embed example
<a href="https://www.netresearch.de/" aria-label="Netresearch DTT GmbH">
<!-- paste inline SVG here -->
</a>Netresearch Logo Specification (Agent-Readable)
This document describes the Netresearch symbol-only logo in pure text for agents that cannot parse SVG files.
Purpose
Use this reference whenever logo placement or reconstruction is needed but assets/logos/netresearch-symbol-only.svg cannot be opened.
Canonical Asset
- Primary logo file:
assets/logos/netresearch-symbol-only.svg - Logo type: symbol-only
[n]mark (without wordmark) - Title metadata:
Netresearch DTT GmbH
Visual Construction
The symbol is composed of two combined shapes:
1. Outer bracket/frame shape (turquoise)
- Creates a geometric frame with open inner area
- Has a left and right vertical structure with top/bottom caps
- Looks like a stylized enclosing form around the inner character
2. Inner lowercase "n" shape (dark gray)
- Compact, rounded-corner geometric letterform
- Starts with a vertical stem and transitions into an arch/shoulder
- Proportioned to sit centered inside the outer frame
Together, both paths form the recognizable Netresearch symbol.
Colors
Use exact brand colors:
- Outer frame:
#2F99A4(Primary Turquoise) - Inner "n":
#585961(Brand Text Gray)
These are the only valid brand color values for the symbol. Any rendered output that uses different hex codes — even close approximations — is a brand-debt violation; correct it before shipping.
Geometry and Proportions
- Native canvas intent: square-like icon area
- SVG viewBox:
-75 -75 440 440 - Effective symbol dimensions are centered and balanced for icon usage
- Keep aspect ratio fixed (no stretching)
- Maintain clear space around symbol (minimum 0.25× of logo width on each side)
Minimum Sizes
- Absolute minimum icon size:
32×32px - Recommended digital size:
>=120pxwidth when logo is a visual anchor - For favicon-like use, simplify context, not the logo geometry
Background Rules
- Preferred: white or very light neutral background
- Dark background allowed only with sufficient contrast
- Never place on noisy imagery without a solid backing area
Do / Don’t
Do
- Use symbol-only logo in headers, cards, extension icons, and branded UI elements
- Keep turquoise shape dominant and gray inner letter clearly visible
- Link clickable logo instances to
https://www.netresearch.de/
Don’t
- Don’t recolor with non-brand colors
- Don’t add gradients, strokes, glows, drop-shadows, or effects to the logo itself
- Don’t rotate, skew, or distort
- Don’t crop the mark
- Don’t replace with generic placeholder icons
Placement Requirements
For branded HTML output, all of the following are mandatory:
1. Header includes the symbol-only logo 2. Footer includes text Netresearch DTT GmbH and link to https://www.netresearch.de/ 3. Typography and colors follow the skill references
Fallback Strategy for Non-SVG Agents
If SVG cannot be rendered:
1. Use this document to describe and validate the logo appearance 2. Prefer embedding the inline SVG from references/logo-svg.md 3. If inline SVG is impossible, use a high-fidelity PNG export derived from the canonical SVG 4. Never omit logo usage in branded outputs
Netresearch README Branding Requirements
Required headline and footer branding for every Netresearch repository README — TYPO3 extensions, Claude skills, internal tools, anything public or private under the Netresearch GitHub/GitLab orgs.
These rules are enforced by the netresearch-branding skill via checkpoints NB-04, NB-05, and NB-30..NB-33.
Why
Readers who land on a repo READ ONLY THE TOP — the badges, the project description, maybe the "what is this" paragraph. They scan to the bottom for license and credits. If the org affiliation is missing from both ends, the project looks orphaned. Mentioning "Netresearch" once in the middle of an ## About section three screens down doesn't make it discoverable.
The existing NB-04 (any mention of "Netresearch") and NB-05 (any netresearch.de link anywhere in the file) catch the worst case — total absence — but pass on a README where the only Netresearch reference is buried in line 412. NB-30..NB-33 enforce placement: visible at the top, visible at the bottom, with the legal license mention near it.
Required structure
Headline (first 30 lines) — NB-30 (warning)
The first 30 lines must contain at least one of:
1. A link to netresearch.de (the regex matches the domain literally, so https://www.netresearch.de/, <https://www.netresearch.de>, and bare netresearch.de all qualify). 2. The string Netresearch DTT (the company short-name, with or without the GmbH suffix). 3. The phrase by Netresearch — the suffix used by the TYPO3 extension ext_emconf.php description convention (... - by Netresearch).
Match is case-insensitive.
In practice this means one of:
- A badge linking to the org page (e.g. an "About" badge).
- A logo image whose alt-text or surrounding markdown contains the
link.
- A one-line lead paragraph like
> Maintained by [Netresearch DTT GmbH](https://www.netresearch.de/).
- The project description itself naming the company:
# rte-ckeditor-image — by Netresearch DTT GmbH.
- TYPO3 extension descriptions ending with
- by Netresearch.
The check is a single pipeline:
head -30 README.md | grep -qiE 'netresearch\.de|Netresearch DTT|by Netresearch'Footer (last 20 lines) — NB-31, NB-32
The last 20 lines must contain BOTH:
- NB-31 (warning): the company name
Netresearch DTT(with or
without GmbH).
- NB-32 (info): a link to
netresearch.de.
A standard footer block looks like:
## License
Code is licensed under [MIT](LICENSE-MIT).
Documentation and skill content are licensed under
[CC-BY-SA-4.0](LICENSE-CC-BY-SA-4.0).
Copyright (c) 2026 [Netresearch DTT GmbH](https://www.netresearch.de/).That single Copyright line satisfies NB-31, NB-32, and (with the license heading two lines up) NB-33 in one place.
License mention — NB-33 (info)
The README must reference licensing somewhere. The check is case-insensitive — matches License, LICENSE, ## License, Licensed under, SPDX badge URLs containing /license/, etc.:
grep -qi 'license' README.mdReal Netresearch repos use one of:
## Licenseheading near the bottom with a paragraph describing
the licence and linking to LICENSE / LICENSE-MIT / LICENSE-CC-BY-SA-4.0.
- An SPDX shield/badge near the top
(e.g. ) — this also satisfies NB-33 because the badge URL contains license.
Examples
Compliant — TYPO3 extension
# rte-ckeditor-image
[](LICENSE)
Image support for CKEditor 5 in TYPO3 — by [Netresearch DTT GmbH](https://www.netresearch.de/).
...
## License
GPL-2.0-or-later. See [LICENSE](LICENSE).
Copyright (c) 2026 [Netresearch DTT GmbH](https://www.netresearch.de/).- NB-04 ✓ ("Netresearch" present)
- NB-05 ✓ (
netresearch.delink) - NB-30 ✓ (headline:
Netresearch DTT GmbHand link in the lead line) - NB-31 ✓ (footer:
Netresearch DTT) - NB-32 ✓ (footer:
netresearch.de) - NB-33 ✓ (
Licensementioned)
Compliant — Claude skill / non-TYPO3 repo
# Agent Harness Skill — by Netresearch DTT GmbH
[](https://github.com/netresearch/agent-harness-skill/actions/workflows/lint.yml)
A Claude Agent Skill for bootstrapping and verifying agent-harness
infrastructure. Maintained by [Netresearch DTT GmbH](https://www.netresearch.de/).
...
## License
Split licensing: code under [MIT](LICENSE-MIT), content under
[CC-BY-SA-4.0](LICENSE-CC-BY-SA-4.0).
Copyright (c) 2026 [Netresearch DTT GmbH](https://www.netresearch.de/).All six checks pass.
Non-compliant — common gaps
# Agent Harness Skill ← NB-30 FAIL
[](.../ci.yml)
A skill for bootstrapping agent-ready repos. ... (no "Netresearch DTT", no netresearch.de link)
...
## Contributing
...
## License
Split licensing:
- Code: MIT
- Content: CC-BY-SA-4.0
Copyright (c) 2026 Netresearch DTT GmbH. ← NB-32 FAIL (no netresearch.de link)NB-30 fails because the headline mentions only "Agent Harness Skill" — no netresearch.de link, no Netresearch DTT. NB-32 fails because the footer copyright line doesn't link the company name to its website.
The minimal fix is two text changes:
-# Agent Harness Skill
+# Agent Harness Skill — by Netresearch DTT GmbH-Copyright (c) 2026 Netresearch DTT GmbH.
+Copyright (c) 2026 [Netresearch DTT GmbH](https://www.netresearch.de/).Both checks pass after that.
Relationship to NB-04 / NB-05
NB-04 and NB-05 remain in place as broader baseline checks (any mention of Netresearch / any netresearch.de link anywhere in the README). NB-30..NB-32 are stricter overlays that require placement at the top and bottom. A README that passes NB-30..NB-32 automatically passes NB-04 and NB-05.
Relationship to TYPO3 extension branding
For TYPO3 extensions, see references/typo3-extension-branding.md, section "README Badge Standards", for the full badge ordering template including required CI/Quality, Security (OpenSSF Scorecard, OpenSSF Best Practices, SLSA), Standards (PHPStan, PHP version, TYPO3 version), and TER badges. The badge templates in that file are already compatible with NB-30 — most include a license badge that satisfies NB-33 and a description line that satisfies NB-30 if it includes the - by Netresearch suffix.
TYPO3 Extension Branding
Purpose: Ensure consistent Netresearch branding across all TYPO3 extensions developed by or for Netresearch.
Extension Icon
Standard: Use the Netresearch symbol-only logo as the extension icon.
File Location: Resources/Public/Icons/Extension.svg
SVG Source:
<svg id="netresearch-logo" data-name="Netresearch Logo" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 300 300">
<defs>
<style>
.nr-frame{fill:#2F99A4;}
.nr-letter{fill:#585961;}
</style>
</defs>
<title>Netresearch DTT GmbH</title>
<g>
<path class="nr-frame"
d="M209.6,0V31.62h32.77a26.38,26.38,0,0,1,26.44,26.43V242a26.38,26.38,0,0,1-26.44,26.44H209.6V300h47.93a42.77,42.77,0,0,0,42.86-42.86V42.89A42.76,42.76,0,0,0,257.53,0ZM43.25,0A42.76,42.76,0,0,0,.39,42.89V257.18A42.76,42.76,0,0,0,43.25,300H91.18V268.46H58.4A26.38,26.38,0,0,1,32,242v-184A26.37,26.37,0,0,1,58.4,31.62H91.18V0Z"
transform="translate(-0.39 -0.04)"/>
<path class="nr-letter"
d="M221.44,120.41c0-34.48-13.94-57.82-48.93-57.82-26.62,0-48.54,7.74-64.17,26.56l-.7-22.06-28.31.06V232.94h31.59V124.69c7.14-18.38,32.14-34.8,53-34.5,27.38.4,25.2,26.24,26,45.81v96.94h31.58"
transform="translate(-0.39 -0.04)"/>
</g>
</svg>Color Values:
- Frame (brackets): Turquoise
#2F99A4 - Letter "n": Anthracite Grey
#585961
Module Icon
The backend module icon should differ from the extension icon: the extension icon (Extension.svg, the symbol-only [n] logo) identifies the package, while the module icon identifies the feature (e.g. a passkey, a dashboard). Do not reuse the [n] logo for a feature module.
Standard:
- Use the feature glyph in brand turquoise `#2F99A4` combined with
currentColor, so the icon adapts to the v14 light/dark backend. - Use SVG presentation attributes (
fill="#2F99A4",fill="currentColor",fill-rule="evenodd"), never the `style="..."` attribute — thestyleattribute breaks under a hardened TYPO3 backend CSP (style-src-attr). - Register in
Configuration/Icons.php. When the colored v12/v13 variant (e.g. teal tile) and the flat v14 variant differ, version-split the source viaTypo3Version.
Example (v14 flat variant — teal key + currentColor body):
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
<path fill="#2F99A4" fill-rule="evenodd" d="..."/> <!-- feature accent -->
<path fill="currentColor" d="..."/> <!-- adapts to light/dark -->
</svg>Description Field Requirements
CRITICAL: Both composer.json and ext_emconf.php description fields MUST mention the company name.
Format: <What extension does> - by Netresearch or include "Netresearch" naturally in the description.
Examples:
✅ "Adds image support to CKEditor5 - by Netresearch"
✅ "Netresearch extension for image handling in CKEditor5"
✅ "Image support for CKEditor5 RTE. Developed and maintained by Netresearch DTT GmbH."
❌ "Adds image support to CKEditor5" (missing company name)
❌ "Image extension" (too vague, missing company name)Why this matters:
- Brand visibility in extension listings
- Clear attribution in TYPO3 Extension Repository (TER)
- Professional identification in Packagist search results
composer.json Requirements
All Netresearch extensions MUST include:
{
"name": "netresearch/<extension-name>",
"type": "typo3-cms-extension",
"description": "<Clear description> - by Netresearch",
"homepage": "https://github.com/netresearch/<repo-name>",
"license": "AGPL-3.0-or-later",
"authors": [
{
"name": "<Developer Name>",
"email": "typo3@netresearch.de",
"role": "Developer",
"homepage": "https://www.netresearch.de/"
}
],
"extra": {
"typo3/cms": {
"extension-key": "<extension_key>"
}
}
}Mandatory Fields:
| Field | Format | Example |
|---|---|---|
name | netresearch/<dashed-extension-key> | netresearch/rte-ckeditor-image |
description | Must mention "Netresearch" | Image support for CKEditor5 - by Netresearch |
homepage | GitHub repository URL | https://github.com/netresearch/t3x-rte_ckeditor_image |
license | SPDX identifier | AGPL-3.0-or-later or GPL-2.0-or-later |
authors[].email | Netresearch TYPO3 email | typo3@netresearch.de |
authors[].homepage | Company website | https://www.netresearch.de/ |
ext_emconf.php Requirements
All Netresearch extensions MUST include:
<?php
$EM_CONF[$_EXTKEY] = [
'title' => '<Extension Title>',
'description' => '<Clear description> - by Netresearch',
'category' => '<be|fe|plugin|misc>',
'author' => '<Developer Name(s)>',
'author_email' => 'typo3@netresearch.de',
'author_company' => 'Netresearch DTT GmbH',
'state' => 'stable',
'version' => '<x.y.z>',
'constraints' => [
'depends' => [
'php' => '<min>-<max>',
'typo3' => '<min>-<max>',
],
'conflicts' => [],
'suggests' => [],
],
];Mandatory Fields:
| Field | Value | Notes |
|---|---|---|
description | Must mention "Netresearch" | Include company name in description text |
author_company | Netresearch DTT GmbH | Exact spelling required |
author_email | *@netresearch.de | Must use Netresearch email domain |
author | Developer name(s) | Comma-separated for multiple |
Configuration Files Checklist
When creating or auditing a Netresearch TYPO3 extension:
1. Extension Icon
- [ ]
Resources/Public/Icons/Extension.svgexists - [ ] Uses official Netresearch symbol-only logo
- [ ] Colors: Frame
#2F99A4, Letter#585961
2. composer.json
- [ ]
namestarts withnetresearch/ - [ ]
descriptionmentions "Netresearch" - [ ]
homepagepoints to GitHub repository - [ ]
authors[].homepageishttps://www.netresearch.de/ - [ ]
authors[].emailuses@netresearch.dedomain - [ ]
licenseis specified (AGPL-3.0-or-later recommended)
3. ext_emconf.php
- [ ]
descriptionmentions "Netresearch" - [ ]
author_companyis exactlyNetresearch DTT GmbH - [ ]
author_emailuses@netresearch.dedomain - [ ]
authorlists developer name(s) - [ ] All mandatory fields are populated
4. LICENSE file
- [ ] LICENSE or LICENSE.txt exists in extension root
- [ ] Contains full license text matching composer.json license
5. README.md
- [ ] Mentions "Netresearch DTT GmbH" in credits/author section
- [ ] Links to https://www.netresearch.de/
- [ ] Follows badge ordering standard (see below)
- [ ] Includes required security badges
README Badge Standards
All Netresearch TYPO3 extension READMEs MUST follow this badge ordering:
Badge Order Template
<!-- Row 1: CI/Quality badges -->
[](https://github.com/netresearch/REPO/actions/workflows/ci.yml)
[](https://codecov.io/gh/netresearch/REPO)
<!-- Row 2: Security badges (REQUIRED for production extensions) -->
[](https://securityscorecards.dev/viewer/?uri=github.com/netresearch/REPO)
[](https://www.bestpractices.dev/projects/PROJECT_ID)
[](https://slsa.dev)
<!-- Row 3: Standards badges -->
[](https://phpstan.org/)
[](https://www.php.net/)
[](https://typo3.org/)
[](https://github.com/netresearch/REPO/blob/main/LICENSE)
[](https://github.com/netresearch/REPO/releases)
[](CODE_OF_CONDUCT.md)
<!-- Row 4: TYPO3 TER badges (if published to TER) -->






<!-- Generated with 🧡 at typo3-badges.dev -->Badge Categories
| Category | Badges | Required |
|---|---|---|
| CI/Quality | CI workflow, codecov | ✅ Yes |
| Security | OpenSSF Scorecard, Best Practices, SLSA | ✅ Production |
| Standards | PHPStan, PHP version, TYPO3 version, License | ✅ Yes |
| TER | typo3-badges.dev badges | If on TER |
Security Badge Requirements
Production-ready extensions MUST have:
| Badge | Source | How to Get |
|---|---|---|
| OpenSSF Scorecard | Auto-generated | Enable .github/workflows/scorecard.yml |
| OpenSSF Best Practices | Manual registration | Register at bestpractices.dev |
| SLSA 3 | CI workflow | Enable .github/workflows/slsa-provenance.yml |
Getting OpenSSF Best Practices Badge: 1. Go to https://www.bestpractices.dev/ 2. Sign in with GitHub 3. Add your project 4. Complete the questionnaire 5. Copy the badge URL with your PROJECT_ID
TYPO3 TER Badges
For extensions published to TYPO3 Extension Repository:
Generate badges at https://typo3-badges.dev/ using your extension key.






<!-- Generated with 🧡 at typo3-badges.dev -->Real-World Examples
t3x-rte_ckeditor_image (gold standard):
- All 4 badge rows present
- OpenSSF Scorecard + Best Practices + SLSA
- 6 TYPO3 TER badges
t3x-nr-llm (good):
- 3 badge rows (no TER badges - not published to TER)
- OpenSSF Scorecard + Best Practices + SLSA
t3x-cowriter (good):
- 3 badge rows (CI/Quality, Standards, TER)
- Missing security badges (backlog - requires enrollment)
- TER badges present ✅
Documentation Branding (docs.typo3.org)
Subtle branding elements for rendered TYPO3 extension documentation:
Required Elements
1. Teal underline SVG below the main heading:
.. image:: /Images/netresearch-underline.svg
:alt:
:width: 200px
:class: no-borderSVG source (200x4px teal rounded rectangle):
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="4" viewBox="0 0 200 4">
<rect width="200" height="4" rx="2" fill="#2F99A4"/>
</svg>2. Emoji icons on card-grid navigation cards (plain UTF-8, not RST substitutions):
.. card:: 📘 Introduction
.. card:: 🛠️ Administration guide
.. card:: 🚀 Integration guideNote: RST |substitution| references do NOT work inside directive arguments.
3. Footer card with [n] brand identity:
.. card:: [n] A Netresearch extension
.. image:: /Images/netresearch-underline.svg
:alt:
:width: 120px
:class: no-border
Professional TYPO3 development, AI integration,
and enterprise consulting since 2002.
.. card-footer:: `netresearch.de <https://www.netresearch.de>`__
:button-style: btn btn-secondary stretched-link4. Documentation license: CC BY 4.0 (separate from code license)
guides.xml Required Attributes
All Netresearch extensions MUST configure these in Documentation/guides.xml:
<extension
class="\T3Docs\Typo3DocsTheme\DependencyInjection\Typo3DocsThemeExtension"
project-home="https://github.com/netresearch/REPO"
project-contact="https://github.com/netresearch/REPO/discussions"
project-repository="https://github.com/netresearch/REPO"
project-issues="https://github.com/netresearch/REPO/issues"
project-discussions="https://github.com/netresearch/REPO/discussions"
edit-on-github="netresearch/REPO"
edit-on-github-branch="main"
edit-on-github-directory="Documentation"
interlink-shortcode="netresearch/PACKAGE"
/>NEVER use mailto: for project-contact. Use GitHub Discussions or Issues.
RST card-footer Syntax
The link text MUST be on the same line as .. card-footer:::
.. card-footer:: `Link text <URL>`__
:button-style: btn btn-secondary stretched-linkA line break before :button-style: causes it to render as literal text.
Validation Commands
# Check composer.json vendor
jq -r '.name' composer.json | grep -q "^netresearch/" && echo "✅ Correct vendor" || echo "❌ Wrong vendor"
# Check composer.json description mentions Netresearch
jq -r '.description' composer.json | grep -qi "netresearch" && echo "✅ Description mentions Netresearch" || echo "❌ Description missing Netresearch"
# Check author homepage
jq -r '.authors[].homepage' composer.json | grep -q "netresearch.de" && echo "✅ Correct homepage" || echo "❌ Wrong homepage"
# Check ext_emconf.php description mentions Netresearch
grep "'description' =>" ext_emconf.php | grep -qi "netresearch" && echo "✅ Description mentions Netresearch" || echo "❌ Description missing Netresearch"
# Check ext_emconf.php author_company
grep -q "'author_company' => 'Netresearch DTT GmbH'" ext_emconf.php && echo "✅ Correct company" || echo "❌ Wrong company"
# Check extension icon exists
test -f Resources/Public/Icons/Extension.svg && echo "✅ Extension icon exists" || echo "❌ Missing extension icon"Netresearch Typography Reference
Complete typography system with font specifications, hierarchy, and implementation guidelines.
Font Family Overview
| Context | Typeface | Purpose |
|---|---|---|
| Web Headlines | Raleway | Digital headers, navigation, buttons |
| Web Body Text | Open Sans | Digital body copy, captions, lists |
| Documents | Calibri | Word, PowerPoint, Excel, email |
| Raleway + Open Sans | Brochures, flyers, business cards |
---
Raleway (Headlines & Display)
Font Specifications
Family: Raleway Designer: Matt McInerney, Pablo Impallari, Rodrigo Fuenzalida License: Open Font License (free for commercial use) Classification: Sans-serif, Geometric
Recommended Weights for Netresearch:
- Regular (400) - Secondary headlines, navigation
- Semi-Bold (600) - Buttons, emphasized text
- Bold (700) - Primary headlines, h1-h2
Web Font Loading
Google Fonts CDN:
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Raleway:wght@400;600;700&display=swap" rel="stylesheet">CSS @import:
@import url('https://fonts.googleapis.com/css2?family=Raleway:wght@400;600;700&display=swap');Self-Hosted (Recommended for Performance):
@font-face {
font-family: 'Raleway';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url('/fonts/raleway-regular.woff2') format('woff2'),
url('/fonts/raleway-regular.woff') format('woff');
}
@font-face {
font-family: 'Raleway';
font-style: normal;
font-weight: 600;
font-display: swap;
src: url('/fonts/raleway-semibold.woff2') format('woff2'),
url('/fonts/raleway-semibold.woff') format('woff');
}
@font-face {
font-family: 'Raleway';
font-style: normal;
font-weight: 700;
font-display: swap;
src: url('/fonts/raleway-bold.woff2') format('woff2'),
url('/fonts/raleway-bold.woff') format('woff');
}Usage Guidelines
Use Raleway For:
- ✅ Page headlines (h1, h2, h3)
- ✅ Navigation menu items
- ✅ Button labels
- ✅ Section headers
- ✅ Pull quotes and callouts
- ✅ Hero text and taglines
Do Not Use Raleway For:
- ❌ Body paragraphs (use Open Sans)
- ❌ Long-form content (readability issues)
- ❌ Small text below 14px (legibility)
- ❌ Dense information tables
---
Open Sans (Body Text)
Font Specifications
Family: Open Sans Designer: Steve Matteson License: Apache License 2.0 (free for commercial use) Classification: Sans-serif, Humanist
Recommended Weights for Netresearch:
- Regular (400) - Body text, lists, captions
- Semi-Bold (600) - Emphasized body text, labels
- Bold (700) - Strong emphasis, sub-headers
Web Font Loading
Google Fonts CDN:
<link href="https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;600;700&display=swap" rel="stylesheet">CSS @import:
@import url('https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;600;700&display=swap');Self-Hosted:
@font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url('/fonts/opensans-regular.woff2') format('woff2'),
url('/fonts/opensans-regular.woff') format('woff');
}
@font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 600;
font-display: swap;
src: url('/fonts/opensans-semibold.woff2') format('woff2'),
url('/fonts/opensans-semibold.woff') format('woff');
}
@font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 700;
font-display: swap;
src: url('/fonts/opensans-bold.woff2') format('woff2'),
url('/fonts/opensans-bold.woff') format('woff');
}Usage Guidelines
Use Open Sans For:
- ✅ All body copy and paragraphs
- ✅ Lists (ordered and unordered)
- ✅ Form input text
- ✅ Captions and metadata
- ✅ Table content
- ✅ Footer text
Do Not Use Open Sans For:
- ❌ Main page headlines (use Raleway)
- ❌ Large display text above 48px (use Raleway)
---
Calibri (Documents)
Font Specifications
Family: Calibri Designer: Luc(as) de Groot License: Microsoft bundled (available on Windows/Office) Classification: Sans-serif, Humanist
Weights Available:
- Regular (400)
- Bold (700)
- Italic (400)
- Bold Italic (700)
Usage Guidelines
Use Calibri For:
- ✅ Microsoft Word documents
- ✅ PowerPoint presentations
- ✅ Excel spreadsheets
- ✅ Outlook emails
- ✅ Internal documentation
Fallback for Non-Microsoft Platforms:
font-family: Calibri, 'Open Sans', Arial, sans-serif;Document Templates:
- Headings: Calibri Bold, Turquoise (#2F99A4)
- Body Text: Calibri Regular, Anthracite (#585961)
- Emphasis: Calibri Bold or Calibri Italic
---
Typography Scale
Web Typography Hierarchy
/* h1 - Page Title */
h1 {
font-family: 'Raleway', sans-serif;
font-size: 48px;
font-weight: 700;
line-height: 1.2;
color: #585961;
margin-bottom: 24px;
}
/* h2 - Section Header */
h2 {
font-family: 'Raleway', sans-serif;
font-size: 36px;
font-weight: 700;
line-height: 1.3;
color: #585961;
margin-bottom: 20px;
}
/* h3 - Subsection Header */
h3 {
font-family: 'Raleway', sans-serif;
font-size: 28px;
font-weight: 600;
line-height: 1.4;
color: #585961;
margin-bottom: 16px;
}
/* h4 - Minor Header */
h4 {
font-family: 'Raleway', sans-serif;
font-size: 22px;
font-weight: 600;
line-height: 1.4;
color: #585961;
margin-bottom: 12px;
}
/* h5 - Small Header */
h5 {
font-family: 'Raleway', sans-serif;
font-size: 18px;
font-weight: 600;
line-height: 1.5;
color: #585961;
margin-bottom: 12px;
}
/* Body Text */
body, p {
font-family: 'Open Sans', sans-serif;
font-size: 16px;
font-weight: 400;
line-height: 1.6;
color: #585961;
margin-bottom: 16px;
}
/* Small Text / Captions */
.text-small, small {
font-family: 'Open Sans', sans-serif;
font-size: 14px;
font-weight: 400;
line-height: 1.6;
color: #585961;
}
/* Lead Paragraph */
.lead {
font-family: 'Open Sans', sans-serif;
font-size: 20px;
font-weight: 400;
line-height: 1.6;
color: #585961;
}Responsive Typography
/* Mobile First Approach */
/* Base (Mobile) */
h1 { font-size: 32px; }
h2 { font-size: 26px; }
h3 { font-size: 22px; }
h4 { font-size: 18px; }
body, p { font-size: 16px; }
/* Tablet (768px+) */
@media (min-width: 768px) {
h1 { font-size: 40px; }
h2 { font-size: 32px; }
h3 { font-size: 26px; }
h4 { font-size: 20px; }
}
/* Desktop (1024px+) */
@media (min-width: 1024px) {
h1 { font-size: 48px; }
h2 { font-size: 36px; }
h3 { font-size: 28px; }
h4 { font-size: 22px; }
}
/* Large Desktop (1440px+) */
@media (min-width: 1440px) {
h1 { font-size: 56px; }
h2 { font-size: 40px; }
}---
Line Height & Spacing
Line Height Guidelines
/* Headlines - Tighter Leading */
h1, h2, h3 {
line-height: 1.2;
}
h4, h5, h6 {
line-height: 1.4;
}
/* Body Text - Comfortable Reading */
p, li, td {
line-height: 1.6;
}
/* Small Text */
small, .caption {
line-height: 1.5;
}Vertical Rhythm
/* Consistent spacing system */
:root {
--spacing-xs: 8px;
--spacing-sm: 12px;
--spacing-md: 16px;
--spacing-lg: 24px;
--spacing-xl: 32px;
--spacing-xxl: 48px;
}
/* Apply to typography */
h1 { margin-bottom: var(--spacing-lg); }
h2 { margin-bottom: var(--spacing-lg); }
h3 { margin-bottom: var(--spacing-md); }
h4, h5 { margin-bottom: var(--spacing-sm); }
p { margin-bottom: var(--spacing-md); }---
Special Typography Elements
Buttons
.btn {
font-family: 'Raleway', sans-serif;
font-size: 16px;
font-weight: 600;
line-height: 1;
letter-spacing: 0.5px;
text-transform: none;
}
.btn-large {
font-size: 18px;
}
.btn-small {
font-size: 14px;
}Navigation
.nav-link {
font-family: 'Raleway', sans-serif;
font-size: 16px;
font-weight: 400;
letter-spacing: 0.3px;
}
.nav-link:hover,
.nav-link.active {
font-weight: 600;
}Blockquotes / Pull Quotes
blockquote {
font-family: 'Raleway', sans-serif;
font-size: 24px;
font-weight: 400;
line-height: 1.5;
font-style: italic;
color: #2F99A4;
border-left: 4px solid #FF4D00;
padding-left: 24px;
margin: 32px 0;
}
blockquote cite {
font-family: 'Open Sans', sans-serif;
font-size: 14px;
font-weight: 600;
font-style: normal;
color: #585961;
display: block;
margin-top: 12px;
}Lists
ul, ol {
font-family: 'Open Sans', sans-serif;
font-size: 16px;
line-height: 1.6;
margin-bottom: 16px;
padding-left: 24px;
}
li {
margin-bottom: 8px;
}
/* Custom bullet points using brand color */
ul.branded {
list-style: none;
padding-left: 0;
}
ul.branded li::before {
content: '●';
color: #2F99A4;
font-weight: bold;
display: inline-block;
width: 1em;
margin-left: -1em;
}---
Font Loading Strategy
Performance Optimization
<!-- Critical CSS with system font fallback -->
<style>
body {
font-family: -apple-system, BlinkMacSystemFont,
'Segoe UI', sans-serif;
}
</style>
<!-- Preload critical fonts -->
<link rel="preload"
href="/fonts/raleway-bold.woff2"
as="font"
type="font/woff2"
crossorigin>
<link rel="preload"
href="/fonts/opensans-regular.woff2"
as="font"
type="font/woff2"
crossorigin>Font Display Strategy
@font-face {
font-family: 'Raleway';
font-display: swap; /* Show fallback immediately, swap when loaded */
/* ... other properties */
}Fallback Stack
/* Complete fallback chain */
--font-headlines: 'Raleway', 'Helvetica Neue', Arial, sans-serif;
--font-body: 'Open Sans', -apple-system, BlinkMacSystemFont,
'Segoe UI', Roboto, sans-serif;
--font-documents: Calibri, 'Open Sans', Arial, sans-serif;---
Accessibility Considerations
Minimum Font Sizes
- Body text: Never below 16px (1rem)
- Small text: Never below 14px (0.875rem)
- Buttons: Minimum 16px for touch targets
Contrast Requirements
All text must meet WCAG AA:
- Normal text: 4.5:1 contrast ratio
- Large text (≥18px): 3:1 contrast ratio
Readability
Line Length:
- Optimal: 50-75 characters per line
- Maximum: 90 characters per line
.content {
max-width: 75ch; /* Character-based width */
}Paragraph Spacing:
p + p {
margin-top: 16px; /* Clear paragraph separation */
}---
CSS Custom Properties (Complete Set)
:root {
/* Font Families */
--font-headline: 'Raleway', sans-serif;
--font-body: 'Open Sans', sans-serif;
--font-document: Calibri, 'Open Sans', sans-serif;
/* Font Sizes */
--font-size-xs: 12px;
--font-size-sm: 14px;
--font-size-base: 16px;
--font-size-lg: 18px;
--font-size-xl: 20px;
--font-size-2xl: 24px;
--font-size-3xl: 28px;
--font-size-4xl: 36px;
--font-size-5xl: 48px;
--font-size-6xl: 56px;
/* Font Weights */
--font-weight-normal: 400;
--font-weight-semibold: 600;
--font-weight-bold: 700;
/* Line Heights */
--line-height-tight: 1.2;
--line-height-snug: 1.4;
--line-height-normal: 1.6;
--line-height-relaxed: 1.8;
/* Letter Spacing */
--letter-spacing-tight: -0.5px;
--letter-spacing-normal: 0;
--letter-spacing-wide: 0.5px;
}---
Typography Testing Checklist
Before deploying:
- [ ] Fonts load correctly on all major browsers
- [ ] Fallback fonts provide acceptable experience
- [ ] All text meets WCAG AA contrast requirements
- [ ] Font files optimized (woff2 format preferred)
- [ ] Font-display: swap implemented
- [ ] Line lengths within 50-90 character range
- [ ] Responsive typography scales appropriately
- [ ] No text smaller than 14px in production
- [ ] Headlines use Raleway, body uses Open Sans
- [ ] Documents use Calibri with proper fallbacks
---
Last updated: 2025-10-18 Maintained by: Netresearch DTT GmbH
Netresearch Web Design Guidelines
Comprehensive web design patterns, layouts, components, and responsive design standards.
Core Design Principles
1. High White Space
Philosophy: Clean, uncluttered layouts that prioritize content and readability.
/* Generous spacing throughout */
:root {
--spacing-xs: 8px;
--spacing-sm: 12px;
--spacing-md: 16px;
--spacing-lg: 24px;
--spacing-xl: 32px;
--spacing-xxl: 48px;
--spacing-3xl: 64px;
--spacing-4xl: 96px;
}
/* Section spacing */
section {
padding: var(--spacing-4xl) 0;
}
/* Content spacing */
.content {
padding: var(--spacing-xxl);
}Guidelines:
- Minimum 48px padding around major sections
- Minimum 24px margin between content blocks
- Generous line-height (1.6) for readability
- Never crowd elements - let designs breathe
---
2. Responsive Grid System
12-Column Flexible Grid:
.grid {
display: grid;
grid-template-columns: repeat(12, 1fr);
gap: var(--spacing-lg);
padding: 0 var(--spacing-lg);
}
/* Content within container */
.container {
max-width: 1200px;
margin: 0 auto;
padding: 0 var(--spacing-lg);
}
/* Responsive columns */
.col-12 { grid-column: span 12; }
.col-6 { grid-column: span 6; }
.col-4 { grid-column: span 4; }
.col-3 { grid-column: span 3; }
@media (max-width: 768px) {
.col-6, .col-4, .col-3 {
grid-column: span 12;
}
}---
3. Design Hierarchy
- Primary: Turquoise (#2F99A4) for key elements
- Secondary: Orange (#FF4D00) for accents only
- Typography: Clear hierarchy with Raleway headers and Open Sans body
- Visual Flow: Top to bottom, left to right reading patterns
---
Responsive Breakpoints
Standard Breakpoints
/* Mobile First Approach */
/* Extra Small (Mobile Portrait) */
/* Default: 0px - 599px */
/* Small (Mobile Landscape) */
@media (min-width: 600px) {
/* Adjustments for landscape phones */
}
/* Medium (Tablet) */
@media (min-width: 768px) {
/* Two-column layouts start here */
}
/* Large (Desktop) */
@media (min-width: 1024px) {
/* Full desktop layouts */
}
/* Extra Large (Wide Desktop) */
@media (min-width: 1440px) {
/* Maximum content width, larger typography */
}
/* Ultra Wide */
@media (min-width: 1920px) {
/* Optional: Enhanced spacing for ultra-wide displays */
}Container Widths
.container {
width: 100%;
margin: 0 auto;
padding: 0 16px;
}
@media (min-width: 600px) {
.container { max-width: 580px; }
}
@media (min-width: 768px) {
.container { max-width: 750px; }
}
@media (min-width: 1024px) {
.container { max-width: 1000px; }
}
@media (min-width: 1440px) {
.container { max-width: 1200px; }
}---
Component Library
Buttons
/* Primary Button */
.btn-primary {
display: inline-block;
font-family: 'Raleway', sans-serif;
font-size: 16px;
font-weight: 600;
line-height: 1;
text-align: center;
text-decoration: none;
padding: 12px 32px;
border: none;
border-radius: 4px;
background-color: #2F99A4;
color: #FFFFFF;
cursor: pointer;
transition: all 0.3s ease;
}
.btn-primary:hover {
background-color: #257880;
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(47, 153, 164, 0.3);
}
.btn-primary:active {
transform: translateY(0);
}
/* Secondary Button */
.btn-secondary {
background-color: #FF4D00;
color: #FFFFFF;
}
.btn-secondary:hover {
background-color: #CC3D00;
box-shadow: 0 4px 12px rgba(255, 77, 0, 0.3);
}
/* Outline Button */
.btn-outline {
background-color: transparent;
color: #2F99A4;
border: 2px solid #2F99A4;
}
.btn-outline:hover {
background-color: #2F99A4;
color: #FFFFFF;
}
/* Button Sizes */
.btn-small {
padding: 8px 24px;
font-size: 14px;
}
.btn-large {
padding: 16px 48px;
font-size: 18px;
}
/* Button States */
.btn:disabled,
.btn[disabled] {
opacity: 0.5;
cursor: not-allowed;
pointer-events: none;
}Button Usage:
<!-- Primary action -->
<button class="btn-primary">Get Started</button>
<!-- Secondary action -->
<button class="btn-secondary">Learn More</button>
<!-- Tertiary action -->
<button class="btn-outline">Contact Us</button>
<!-- Sizes -->
<button class="btn-primary btn-small">Small</button>
<button class="btn-primary">Default</button>
<button class="btn-primary btn-large">Large</button>---
Cards
.card {
background: #FFFFFF;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
overflow: hidden;
transition: all 0.3s ease;
}
.card:hover {
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
transform: translateY(-4px);
}
.card-image {
width: 100%;
height: 240px;
object-fit: cover;
}
.card-content {
padding: var(--spacing-lg);
}
.card-title {
font-family: 'Raleway', sans-serif;
font-size: 22px;
font-weight: 600;
color: #585961;
margin-bottom: var(--spacing-sm);
}
.card-text {
font-family: 'Open Sans', sans-serif;
font-size: 16px;
line-height: 1.6;
color: #585961;
margin-bottom: var(--spacing-md);
}
.card-footer {
padding: var(--spacing-md) var(--spacing-lg);
border-top: 1px solid #E5E5E5;
background-color: #F5F5F5;
}Card Usage:
<div class="card">
<img src="image.jpg" alt="Card image" class="card-image">
<div class="card-content">
<h3 class="card-title">Card Title</h3>
<p class="card-text">Card description goes here.</p>
<a href="#" class="btn-primary">Read More</a>
</div>
<div class="card-footer">
<span class="card-meta">Posted: January 1, 2025</span>
</div>
</div>---
Navigation
/* Main Navigation */
.navbar {
position: sticky;
top: 0;
z-index: 1000;
background: #FFFFFF;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
padding: var(--spacing-md) 0;
}
.navbar-container {
display: flex;
justify-content: space-between;
align-items: center;
max-width: 1200px;
margin: 0 auto;
padding: 0 var(--spacing-lg);
}
.navbar-logo {
height: 48px;
}
.navbar-menu {
display: flex;
gap: var(--spacing-lg);
list-style: none;
margin: 0;
padding: 0;
}
.navbar-link {
font-family: 'Raleway', sans-serif;
font-size: 16px;
font-weight: 400;
color: #585961;
text-decoration: none;
padding: 8px 16px;
transition: all 0.3s ease;
}
.navbar-link:hover,
.navbar-link.active {
color: #2F99A4;
font-weight: 600;
}
/* Mobile Menu Toggle */
.navbar-toggle {
display: none;
flex-direction: column;
gap: 4px;
background: none;
border: none;
cursor: pointer;
}
.navbar-toggle span {
display: block;
width: 24px;
height: 3px;
background: #2F99A4;
transition: all 0.3s ease;
}
@media (max-width: 768px) {
.navbar-toggle {
display: flex;
}
.navbar-menu {
position: absolute;
top: 100%;
left: 0;
right: 0;
flex-direction: column;
background: #FFFFFF;
padding: var(--spacing-lg);
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.1);
transform: translateY(-100%);
opacity: 0;
visibility: hidden;
transition: all 0.3s ease;
}
.navbar-menu.active {
transform: translateY(0);
opacity: 1;
visibility: visible;
}
}---
Forms
.form-group {
margin-bottom: var(--spacing-lg);
}
.form-label {
display: block;
font-family: 'Open Sans', sans-serif;
font-size: 14px;
font-weight: 600;
color: #585961;
margin-bottom: var(--spacing-xs);
}
.form-input,
.form-textarea,
.form-select {
width: 100%;
font-family: 'Open Sans', sans-serif;
font-size: 16px;
color: #585961;
padding: 12px 16px;
border: 1px solid #CCCDCC;
border-radius: 4px;
background: #FFFFFF;
transition: all 0.3s ease;
}
.form-input:focus,
.form-textarea:focus,
.form-select:focus {
outline: none;
border-color: #2F99A4;
box-shadow: 0 0 0 3px rgba(47, 153, 164, 0.1);
}
.form-input::placeholder {
color: #8A8B93;
}
.form-textarea {
min-height: 120px;
resize: vertical;
}
.form-error {
color: #DC3545;
font-size: 14px;
margin-top: var(--spacing-xs);
}
.form-input.error {
border-color: #DC3545;
}
.form-help {
font-size: 14px;
color: #8A8B93;
margin-top: var(--spacing-xs);
}Form Example:
<form class="form">
<div class="form-group">
<label for="name" class="form-label">Name*</label>
<input type="text" id="name" class="form-input" placeholder="Your name" required>
</div>
<div class="form-group">
<label for="email" class="form-label">Email*</label>
<input type="email" id="email" class="form-input" placeholder="your@email.com" required>
<small class="form-help">We'll never share your email.</small>
</div>
<div class="form-group">
<label for="message" class="form-label">Message*</label>
<textarea id="message" class="form-textarea" placeholder="Your message" required></textarea>
</div>
<button type="submit" class="btn-primary">Send Message</button>
</form>---
Links
/* Body Links */
a {
color: #2F99A4;
text-decoration: none;
transition: all 0.3s ease;
border-bottom: 1px solid transparent;
}
a:hover {
color: #257880;
border-bottom-color: #2F99A4;
}
/* External Links */
a[target="_blank"]::after {
content: ' ↗';
font-size: 0.9em;
}
/* Download Links */
a[download]::before {
content: '⬇ ';
}
/* Standalone Links */
.link-standalone {
font-family: 'Raleway', sans-serif;
font-weight: 600;
display: inline-flex;
align-items: center;
gap: 8px;
}
.link-standalone::after {
content: '→';
transition: transform 0.3s ease;
}
.link-standalone:hover::after {
transform: translateX(4px);
}---
Hero Sections
.hero {
position: relative;
display: flex;
align-items: center;
justify-content: center;
min-height: 600px;
padding: var(--spacing-4xl) var(--spacing-lg);
background: linear-gradient(135deg, #2F99A4 0%, #257880 100%);
color: #FFFFFF;
text-align: center;
}
.hero-content {
max-width: 800px;
z-index: 1;
}
.hero-title {
font-family: 'Raleway', sans-serif;
font-size: 56px;
font-weight: 700;
margin-bottom: var(--spacing-lg);
}
.hero-subtitle {
font-family: 'Open Sans', sans-serif;
font-size: 20px;
line-height: 1.6;
margin-bottom: var(--spacing-xl);
opacity: 0.9;
}
.hero-cta {
display: flex;
gap: var(--spacing-md);
justify-content: center;
flex-wrap: wrap;
}
@media (max-width: 768px) {
.hero {
min-height: 400px;
padding: var(--spacing-xxl) var(--spacing-lg);
}
.hero-title {
font-size: 36px;
}
.hero-subtitle {
font-size: 18px;
}
.hero-cta {
flex-direction: column;
}
}---
Tables
.table {
width: 100%;
border-collapse: collapse;
margin-bottom: var(--spacing-lg);
background: #FFFFFF;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}
.table thead {
background-color: #2F99A4;
color: #FFFFFF;
}
.table th {
font-family: 'Raleway', sans-serif;
font-weight: 600;
text-align: left;
padding: 16px;
}
.table td {
font-family: 'Open Sans', sans-serif;
padding: 12px 16px;
border-bottom: 1px solid #E5E5E5;
}
.table tbody tr:hover {
background-color: #F5F5F5;
}
.table tbody tr:last-child td {
border-bottom: none;
}
/* Responsive Table */
@media (max-width: 768px) {
.table {
display: block;
overflow-x: auto;
}
}---
Footer
.footer {
background-color: #585961;
color: #FFFFFF;
padding: var(--spacing-4xl) 0 var(--spacing-lg);
}
.footer-content {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: var(--spacing-xl);
max-width: 1200px;
margin: 0 auto;
padding: 0 var(--spacing-lg);
margin-bottom: var(--spacing-xl);
}
.footer-section h4 {
font-family: 'Raleway', sans-serif;
font-size: 18px;
font-weight: 600;
color: #FFFFFF;
margin-bottom: var(--spacing-md);
}
.footer-section ul {
list-style: none;
padding: 0;
margin: 0;
}
.footer-section li {
margin-bottom: var(--spacing-sm);
}
.footer-section a {
color: rgba(255, 255, 255, 0.8);
text-decoration: none;
transition: color 0.3s ease;
}
.footer-section a:hover {
color: #2F99A4;
}
.footer-bottom {
border-top: 1px solid rgba(255, 255, 255, 0.1);
padding-top: var(--spacing-lg);
text-align: center;
color: rgba(255, 255, 255, 0.6);
font-size: 14px;
}---
Layout Patterns
Two-Column Layout
.two-column {
display: grid;
grid-template-columns: 2fr 1fr;
gap: var(--spacing-xl);
}
@media (max-width: 768px) {
.two-column {
grid-template-columns: 1fr;
}
}Three-Column Layout
.three-column {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: var(--spacing-lg);
}
@media (max-width: 1024px) {
.three-column {
grid-template-columns: repeat(2, 1fr);
}
}
@media (max-width: 768px) {
.three-column {
grid-template-columns: 1fr;
}
}Content + Sidebar
.content-sidebar {
display: grid;
grid-template-columns: 3fr 1fr;
gap: var(--spacing-xxl);
}
@media (max-width: 1024px) {
.content-sidebar {
grid-template-columns: 1fr;
}
}---
Animations & Transitions
/* Smooth transitions */
* {
transition-timing-function: ease-in-out;
}
/* Fade In */
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.fade-in {
animation: fadeIn 0.6s ease-out;
}
/* Slide In */
@keyframes slideIn {
from {
transform: translateX(-100%);
}
to {
transform: translateX(0);
}
}
/* Pulse (for emphasis) */
@keyframes pulse {
0%, 100% {
transform: scale(1);
}
50% {
transform: scale(1.05);
}
}---
Web Design Checklist
Before launching any web project:
Layout:
- [ ] High white space maintained throughout
- [ ] Responsive grid implemented correctly
- [ ] All breakpoints tested (mobile, tablet, desktop)
- [ ] Content max-width appropriate (≤1200px)
Components:
- [ ] Buttons follow brand styles (Raleway font, correct colors)
- [ ] Cards have appropriate shadows and hover states
- [ ] Navigation sticky/fixed and accessible
- [ ] Forms styled consistently with validation
Typography:
- [ ] Headlines use Raleway
- [ ] Body text uses Open Sans
- [ ] Font sizes scale responsively
- [ ] Line-heights appropriate for readability
Colors:
- [ ] Turquoise primary, orange accent only
- [ ] WCAG AA contrast compliance verified
- [ ] Brand colors match exactly (no variations)
Performance:
- [ ] Images optimized and responsive
- [ ] Fonts loaded efficiently (preload critical)
- [ ] CSS minified for production
- [ ] Animations use transform/opacity (GPU-accelerated)
Accessibility:
- [ ] All interactive elements keyboard accessible
- [ ] ARIA labels where needed
- [ ] Focus states visible
- [ ] Screen reader tested
---
Last updated: 2025-10-18 Maintained by: Netresearch DTT GmbH
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Netresearch - Landing Page Template</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Raleway:wght@400;600;700&family=Open+Sans:wght@400;600;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="styles.css">
</head>
<body>
<!-- Navigation -->
<nav class="navbar">
<div class="navbar-container">
<img src="logo.svg" alt="Netresearch Logo" class="navbar-logo">
<button class="navbar-toggle" aria-label="Toggle navigation">
<span></span>
<span></span>
<span></span>
</button>
<ul class="navbar-menu">
<li><a href="#services" class="navbar-link active">Services</a></li>
<li><a href="#about" class="navbar-link">About</a></li>
<li><a href="#portfolio" class="navbar-link">Portfolio</a></li>
<li><a href="#contact" class="navbar-link">Contact</a></li>
</ul>
</div>
</nav>
<!-- Hero Section -->
<section class="hero">
<div class="hero-content">
<h1 class="hero-title">Your Digital Transformation Partner</h1>
<p class="hero-subtitle">
We create innovative digital solutions that drive business growth and enhance user experiences.
</p>
<div class="hero-cta">
<a href="#contact" class="btn-primary btn-large">Get Started</a>
<a href="#services" class="btn-outline btn-large">Learn More</a>
</div>
</div>
</section>
<!-- Services Section -->
<section id="services" class="section">
<div class="container">
<h2 class="section-title">Our Services</h2>
<p class="section-subtitle">
Comprehensive digital solutions tailored to your needs
</p>
<div class="three-column">
<div class="card">
<div class="card-content">
<h3 class="card-title">Web Development</h3>
<p class="card-text">
Modern, responsive websites built with the latest technologies and best practices.
</p>
<a href="#" class="link-standalone">Learn more</a>
</div>
</div>
<div class="card">
<div class="card-content">
<h3 class="card-title">E-Commerce Solutions</h3>
<p class="card-text">
Powerful online stores that drive sales and provide exceptional shopping experiences.
</p>
<a href="#" class="link-standalone">Learn more</a>
</div>
</div>
<div class="card">
<div class="card-content">
<h3 class="card-title">Digital Strategy</h3>
<p class="card-text">
Strategic consulting to help your business thrive in the digital landscape.
</p>
<a href="#" class="link-standalone">Learn more</a>
</div>
</div>
</div>
</div>
</section>
<!-- About Section -->
<section id="about" class="section section-alt">
<div class="container">
<div class="two-column">
<div>
<h2>About Netresearch</h2>
<p class="lead">
With over 20 years of experience, we've been helping businesses succeed online through innovative digital solutions.
</p>
<p>
Our team of experts combines technical excellence with creative thinking to deliver projects that exceed expectations. We specialize in TYPO3, e-commerce, and custom web applications.
</p>
<p>
Based in Leipzig, Germany, we serve clients across Europe and beyond, providing end-to-end digital services from strategy to implementation and support.
</p>
<a href="#contact" class="btn-primary">Work with us</a>
</div>
<div>
<img src="about-image.jpg" alt="Netresearch team" style="width: 100%; border-radius: 8px;">
</div>
</div>
</div>
</section>
<!-- Portfolio Section -->
<section id="portfolio" class="section">
<div class="container">
<h2 class="section-title">Our Work</h2>
<p class="section-subtitle">
Recent projects we're proud of
</p>
<div class="three-column">
<div class="card">
<img src="project-1.jpg" alt="Project 1" class="card-image">
<div class="card-content">
<h3 class="card-title">E-Commerce Platform</h3>
<p class="card-text">
Complete redesign and development of a multi-vendor marketplace.
</p>
<div class="card-footer">
<span class="card-meta">TYPO3 • Magento • 2024</span>
</div>
</div>
</div>
<div class="card">
<img src="project-2.jpg" alt="Project 2" class="card-image">
<div class="card-content">
<h3 class="card-title">Corporate Website</h3>
<p class="card-text">
Modern website with multilingual content and advanced integrations.
</p>
<div class="card-footer">
<span class="card-meta">TYPO3 • API • 2024</span>
</div>
</div>
</div>
<div class="card">
<img src="project-3.jpg" alt="Project 3" class="card-image">
<div class="card-content">
<h3 class="card-title">Custom Web Application</h3>
<p class="card-text">
Bespoke solution for complex business requirements and workflows.
</p>
<div class="card-footer">
<span class="card-meta">Laravel • Vue.js • 2024</span>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- Contact Section -->
<section id="contact" class="section section-alt">
<div class="container">
<div class="two-column">
<div>
<h2>Get in Touch</h2>
<p class="lead">
Ready to start your next project? Let's talk about how we can help.
</p>
<p>
<strong>Netresearch DTT GmbH</strong><br>
Nonnenstraße 11d<br>
04229 Leipzig, Germany
</p>
<p>
<strong>Phone:</strong> +49 341 49288-0<br>
<strong>GitHub:</strong> <a href="https://github.com/netresearch/netresearch-branding-skill">https://github.com/netresearch/netresearch-branding-skill</a>
</p>
</div>
<div>
<form class="form">
<div class="form-group">
<label for="name" class="form-label">Name*</label>
<input type="text" id="name" class="form-input" placeholder="Your name" required>
</div>
<div class="form-group">
<label for="email" class="form-label">Email*</label>
<input type="email" id="email" class="form-input" placeholder="your@email.com" required>
</div>
<div class="form-group">
<label for="subject" class="form-label">Subject*</label>
<input type="text" id="subject" class="form-input" placeholder="Project inquiry" required>
</div>
<div class="form-group">
<label for="message" class="form-label">Message*</label>
<textarea id="message" class="form-textarea" placeholder="Tell us about your project" required></textarea>
</div>
<button type="submit" class="btn-primary btn-large">Send Message</button>
</form>
</div>
</div>
</div>
</section>
<!-- Footer -->
<footer class="footer">
<div class="footer-content">
<div class="footer-section">
<h4>Company</h4>
<ul>
<li><a href="#about">About Us</a></li>
<li><a href="#services">Services</a></li>
<li><a href="#portfolio">Portfolio</a></li>
<li><a href="#careers">Careers</a></li>
</ul>
</div>
<div class="footer-section">
<h4>Services</h4>
<ul>
<li><a href="#web-dev">Web Development</a></li>
<li><a href="#ecommerce">E-Commerce</a></li>
<li><a href="#typo3">TYPO3</a></li>
<li><a href="#consulting">Consulting</a></li>
</ul>
</div>
<div class="footer-section">
<h4>Resources</h4>
<ul>
<li><a href="#blog">Blog</a></li>
<li><a href="#case-studies">Case Studies</a></li>
<li><a href="#documentation">Documentation</a></li>
<li><a href="#support">Support</a></li>
</ul>
</div>
<div class="footer-section">
<h4>Legal</h4>
<ul>
<li><a href="#imprint">Imprint</a></li>
<li><a href="#privacy">Privacy Policy</a></li>
<li><a href="#terms">Terms of Service</a></li>
</ul>
</div>
</div>
<div class="footer-bottom">
<div class="container">
<p>© 2025 Netresearch DTT GmbH. All rights reserved.</p>
</div>
</div>
</footer>
<script>
// Mobile menu toggle
const toggle = document.querySelector('.navbar-toggle');
const menu = document.querySelector('.navbar-menu');
toggle.addEventListener('click', () => {
menu.classList.toggle('active');
});
// Smooth scrolling
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function (e) {
e.preventDefault();
const target = document.querySelector(this.getAttribute('href'));
if (target) {
target.scrollIntoView({ behavior: 'smooth' });
menu.classList.remove('active');
}
});
});
</script>
</body>
</html>
/*
* Netresearch Brand Styles
* Complete CSS template following brand guidelines
*/
/* ============================================
CSS CUSTOM PROPERTIES
============================================ */
:root {
/* Brand Colors */
--color-primary: #2F99A4;
--color-primary-rgb: 47, 153, 164;
--color-primary-dark: #257880;
--color-accent: #FF4D00;
--color-accent-rgb: 255, 77, 0;
--color-accent-dark: #CC3D00;
/* Neutral Colors */
--color-text-primary: #585961;
--color-text-secondary: #8A8B93;
--color-background: #FFFFFF;
--color-background-alt: #F5F5F5;
--color-border: #CCCDCC;
--color-border-light: #E5E5E5;
/* Typography */
--font-headline: 'Raleway', sans-serif;
--font-body: 'Open Sans', sans-serif;
/* Font Sizes */
--font-size-xs: 12px;
--font-size-sm: 14px;
--font-size-base: 16px;
--font-size-lg: 18px;
--font-size-xl: 20px;
--font-size-2xl: 24px;
--font-size-3xl: 28px;
--font-size-4xl: 36px;
--font-size-5xl: 48px;
--font-size-6xl: 56px;
/* Spacing */
--spacing-xs: 8px;
--spacing-sm: 12px;
--spacing-md: 16px;
--spacing-lg: 24px;
--spacing-xl: 32px;
--spacing-xxl: 48px;
--spacing-3xl: 64px;
--spacing-4xl: 96px;
/* Shadows */
--shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.08);
--shadow-md: 0 4px 12px rgba(0, 0, 0, 0.12);
--shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.16);
}
/* ============================================
RESET & BASE STYLES
============================================ */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html {
scroll-behavior: smooth;
}
body {
font-family: var(--font-body);
font-size: var(--font-size-base);
line-height: 1.6;
color: var(--color-text-primary);
background-color: var(--color-background);
}
/* ============================================
TYPOGRAPHY
============================================ */
h1, h2, h3, h4, h5, h6 {
font-family: var(--font-headline);
font-weight: 700;
line-height: 1.2;
color: var(--color-text-primary);
}
h1 {
font-size: var(--font-size-5xl);
margin-bottom: var(--spacing-lg);
}
h2 {
font-size: var(--font-size-4xl);
margin-bottom: var(--spacing-lg);
}
h3 {
font-size: var(--font-size-3xl);
font-weight: 600;
margin-bottom: var(--spacing-md);
}
h4 {
font-size: var(--font-size-2xl);
font-weight: 600;
margin-bottom: var(--spacing-sm);
}
p {
margin-bottom: var(--spacing-md);
}
.lead {
font-size: var(--font-size-xl);
font-weight: 400;
line-height: 1.6;
}
a {
color: var(--color-primary);
text-decoration: none;
transition: all 0.3s ease;
}
a:hover {
color: var(--color-primary-dark);
}
/* ============================================
LAYOUT
============================================ */
.container {
width: 100%;
max-width: 1200px;
margin: 0 auto;
padding: 0 var(--spacing-lg);
}
.section {
padding: var(--spacing-4xl) 0;
}
.section-alt {
background-color: var(--color-background-alt);
}
.section-title {
text-align: center;
margin-bottom: var(--spacing-md);
}
.section-subtitle {
text-align: center;
font-size: var(--font-size-xl);
color: var(--color-text-secondary);
margin-bottom: var(--spacing-xxl);
}
.two-column {
display: grid;
grid-template-columns: 1fr 1fr;
gap: var(--spacing-xl);
align-items: center;
}
.three-column {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: var(--spacing-lg);
}
/* ============================================
NAVIGATION
============================================ */
.navbar {
position: sticky;
top: 0;
z-index: 1000;
background: var(--color-background);
box-shadow: var(--shadow-sm);
padding: var(--spacing-md) 0;
}
.navbar-container {
display: flex;
justify-content: space-between;
align-items: center;
max-width: 1200px;
margin: 0 auto;
padding: 0 var(--spacing-lg);
}
.navbar-logo {
height: 48px;
}
.navbar-menu {
display: flex;
gap: var(--spacing-lg);
list-style: none;
}
.navbar-link {
font-family: var(--font-headline);
font-size: var(--font-size-base);
font-weight: 400;
color: var(--color-text-primary);
padding: var(--spacing-xs) var(--spacing-md);
transition: all 0.3s ease;
}
.navbar-link:hover,
.navbar-link.active {
color: var(--color-primary);
font-weight: 600;
}
.navbar-toggle {
display: none;
flex-direction: column;
gap: 4px;
background: none;
border: none;
cursor: pointer;
}
.navbar-toggle span {
display: block;
width: 24px;
height: 3px;
background: var(--color-primary);
transition: all 0.3s ease;
}
/* ============================================
HERO SECTION
============================================ */
.hero {
position: relative;
display: flex;
align-items: center;
justify-content: center;
min-height: 600px;
padding: var(--spacing-4xl) var(--spacing-lg);
background: linear-gradient(135deg, var(--color-primary) 0%, var(--color-primary-dark) 100%);
color: var(--color-background);
text-align: center;
}
.hero-content {
max-width: 800px;
z-index: 1;
}
.hero-title {
color: var(--color-background);
margin-bottom: var(--spacing-lg);
}
.hero-subtitle {
font-size: var(--font-size-xl);
line-height: 1.6;
margin-bottom: var(--spacing-xl);
opacity: 0.95;
}
.hero-cta {
display: flex;
gap: var(--spacing-md);
justify-content: center;
flex-wrap: wrap;
}
/* ============================================
BUTTONS
============================================ */
.btn-primary,
.btn-secondary,
.btn-outline {
display: inline-block;
font-family: var(--font-headline);
font-size: var(--font-size-base);
font-weight: 600;
line-height: 1;
text-align: center;
text-decoration: none;
padding: 12px 32px;
border: none;
border-radius: 4px;
cursor: pointer;
transition: all 0.3s ease;
}
.btn-primary {
background-color: var(--color-primary);
color: var(--color-background);
}
.btn-primary:hover {
background-color: var(--color-primary-dark);
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(47, 153, 164, 0.3);
}
.btn-secondary {
background-color: var(--color-accent);
color: var(--color-background);
}
.btn-secondary:hover {
background-color: var(--color-accent-dark);
box-shadow: 0 4px 12px rgba(255, 77, 0, 0.3);
}
.btn-outline {
background-color: transparent;
color: var(--color-background);
border: 2px solid var(--color-background);
}
.btn-outline:hover {
background-color: var(--color-background);
color: var(--color-primary);
}
.btn-large {
padding: 16px 48px;
font-size: var(--font-size-lg);
}
.btn-small {
padding: 8px 24px;
font-size: var(--font-size-sm);
}
/* ============================================
CARDS
============================================ */
.card {
background: var(--color-background);
border-radius: 8px;
box-shadow: var(--shadow-sm);
overflow: hidden;
transition: all 0.3s ease;
height: 100%;
}
.card:hover {
box-shadow: var(--shadow-md);
transform: translateY(-4px);
}
.card-image {
width: 100%;
height: 240px;
object-fit: cover;
}
.card-content {
padding: var(--spacing-lg);
}
.card-title {
font-size: var(--font-size-2xl);
font-weight: 600;
margin-bottom: var(--spacing-sm);
}
.card-text {
font-size: var(--font-size-base);
line-height: 1.6;
color: var(--color-text-primary);
margin-bottom: var(--spacing-md);
}
.card-footer {
padding: var(--spacing-md) var(--spacing-lg);
border-top: 1px solid var(--color-border-light);
background-color: var(--color-background-alt);
}
.card-meta {
font-size: var(--font-size-sm);
color: var(--color-text-secondary);
}
/* ============================================
LINKS
============================================ */
.link-standalone {
font-family: var(--font-headline);
font-weight: 600;
display: inline-flex;
align-items: center;
gap: 8px;
color: var(--color-primary);
}
.link-standalone::after {
content: '→';
transition: transform 0.3s ease;
}
.link-standalone:hover::after {
transform: translateX(4px);
}
/* ============================================
FORMS
============================================ */
.form-group {
margin-bottom: var(--spacing-lg);
}
.form-label {
display: block;
font-size: var(--font-size-sm);
font-weight: 600;
color: var(--color-text-primary);
margin-bottom: var(--spacing-xs);
}
.form-input,
.form-textarea {
width: 100%;
font-family: var(--font-body);
font-size: var(--font-size-base);
color: var(--color-text-primary);
padding: 12px 16px;
border: 1px solid var(--color-border);
border-radius: 4px;
background: var(--color-background);
transition: all 0.3s ease;
}
.form-input:focus,
.form-textarea:focus {
outline: none;
border-color: var(--color-primary);
box-shadow: 0 0 0 3px rgba(47, 153, 164, 0.1);
}
.form-input::placeholder,
.form-textarea::placeholder {
color: var(--color-text-secondary);
}
.form-textarea {
min-height: 120px;
resize: vertical;
}
/* ============================================
FOOTER
============================================ */
.footer {
background-color: var(--color-text-primary);
color: var(--color-background);
padding: var(--spacing-4xl) 0 var(--spacing-lg);
}
.footer-content {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: var(--spacing-xl);
max-width: 1200px;
margin: 0 auto;
padding: 0 var(--spacing-lg);
margin-bottom: var(--spacing-xl);
}
.footer-section h4 {
font-size: var(--font-size-lg);
font-weight: 600;
color: var(--color-background);
margin-bottom: var(--spacing-md);
}
.footer-section ul {
list-style: none;
padding: 0;
margin: 0;
}
.footer-section li {
margin-bottom: var(--spacing-sm);
}
.footer-section a {
color: rgba(255, 255, 255, 0.8);
text-decoration: none;
transition: color 0.3s ease;
}
.footer-section a:hover {
color: var(--color-primary);
}
.footer-bottom {
border-top: 1px solid rgba(255, 255, 255, 0.1);
padding-top: var(--spacing-lg);
text-align: center;
}
.footer-bottom p {
color: rgba(255, 255, 255, 0.6);
font-size: var(--font-size-sm);
margin: 0;
}
/* ============================================
RESPONSIVE DESIGN
============================================ */
/* Tablet (768px and below) */
@media (max-width: 1024px) {
.three-column {
grid-template-columns: repeat(2, 1fr);
}
}
@media (max-width: 768px) {
/* Typography */
h1 { font-size: var(--font-size-4xl); }
h2 { font-size: var(--font-size-3xl); }
h3 { font-size: var(--font-size-2xl); }
/* Layout */
.two-column,
.three-column {
grid-template-columns: 1fr;
}
/* Hero */
.hero {
min-height: 400px;
padding: var(--spacing-xxl) var(--spacing-lg);
}
.hero-title {
font-size: var(--font-size-4xl);
}
.hero-subtitle {
font-size: var(--font-size-lg);
}
.hero-cta {
flex-direction: column;
}
/* Navigation */
.navbar-toggle {
display: flex;
}
.navbar-menu {
position: absolute;
top: 100%;
left: 0;
right: 0;
flex-direction: column;
background: var(--color-background);
padding: var(--spacing-lg);
box-shadow: var(--shadow-md);
transform: translateY(-100%);
opacity: 0;
visibility: hidden;
transition: all 0.3s ease;
}
.navbar-menu.active {
transform: translateY(0);
opacity: 1;
visibility: visible;
}
/* Sections */
.section {
padding: var(--spacing-xxl) 0;
}
}
/* Mobile (600px and below) */
@media (max-width: 600px) {
h1 { font-size: var(--font-size-3xl); }
h2 { font-size: var(--font-size-2xl); }
.hero {
min-height: 300px;
}
.btn-large {
padding: 12px 32px;
font-size: var(--font-size-base);
}
}
/* ============================================
UTILITIES
============================================ */
.text-center {
text-align: center;
}
.mb-0 { margin-bottom: 0; }
.mb-sm { margin-bottom: var(--spacing-sm); }
.mb-md { margin-bottom: var(--spacing-md); }
.mb-lg { margin-bottom: var(--spacing-lg); }
.mb-xl { margin-bottom: var(--spacing-xl); }