Files
crm/static/style.css
T
MachielandClaude Opus 5.5 bffa053c05 v0.0.1: eerste versie van de Van Emous CRM
Flask + SQLite, in de Van Emous-huisstijl (tokens uit het design system, GSAP-effecten
volgens de motion-regels, uit bij prefers-reduced-motion).

- Leads en contactpersonen: status, toewijzen, verwachte waarde, omzetten naar klant,
  tijdlijn, bestanden, taken/opvolging
- Relaties (zoals accounts in EspoCRM): klantbundels (huishouden/familie) en partners met
  type (leverancier, aannemer, ...); leveranciers van producten worden automatisch partners
- API voor formulieren (POST /api/leads) met dubbele-leaddetectie, bestanden en
  configurator-ontwerpen (house-design JSON)
- Import van CSV/JSON (leads, relaties, producten) met kolomkoppeling; configurator-formaat
- Producten met SKU als vaste sleutel, mutatiehistorie, POST /api/products, CSV-export;
  offerteregels houden hun eigen prijs
- Offertes met btw per tarief en afdrukversie (PDF via de browser)
- Inbox via IMAP/SMTP, gekoppeld aan contacten
- Gebruikers (beheerder/medewerker) en klantportaal (offertes accepteren, bestanden, berichten)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 21:56:55 +02:00

216 lines
14 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* Van Emous huisstijl — tokens uit het design system */
:root {
--orange: #b95913;
--orange-dark: #a24e11;
--orange-tint: rgba(185, 89, 19, 0.1);
--orange-tint-soft: rgba(185, 89, 19, 0.06);
--orange-line: rgba(185, 89, 19, 0.35);
--orange-focus: rgba(185, 89, 19, 0.25);
--ink: #212121;
--ink-muted: #5c6670;
--white: #ffffff;
--ultra-light: #f9faf5;
--light: #f0f1ec;
--blue: #dce4ee;
--blue-light: #f1f4f8;
--blue-dark: #a8bbd5;
--line: rgba(0, 0, 0, 0.08);
--control: #8f969c;
--font-body: "Mukta", system-ui, -apple-system, sans-serif;
--font-heading: "Kantumruy Pro", sans-serif;
--radius-sm: 0.5rem;
--radius-md: 1rem;
--radius-lg: 1.25rem;
--radius-pill: 50px;
}
* { box-sizing: border-box; }
html { font-variant-numeric: lining-nums tabular-nums; }
body { margin: 0; font-family: var(--font-body); font-size: 16px; line-height: 1.6; color: var(--ink); background: var(--ultra-light); display: flex; min-height: 100vh; }
h1, h2, h3 { font-family: var(--font-heading); font-weight: 500; line-height: 1.2; margin: 0 0 0.75rem; }
h1 { font-size: 2rem; line-height: 1.1; letter-spacing: -0.01em; }
h2 { font-size: 1.3rem; }
h3 { font-size: 1.05rem; margin-top: 1.25rem; }
a { color: var(--orange); font-weight: 600; text-decoration: none; }
a:hover { text-decoration: underline; }
a:focus-visible, button:focus-visible, .btn:focus-visible { outline: 3px solid var(--orange); outline-offset: 2px; }
/* zijbalk */
.side { width: 240px; flex: none; background: var(--white); border-right: 1px solid var(--line); padding: 1.5rem 1rem; display: flex; flex-direction: column; position: sticky; top: 0; height: 100vh; }
.brand img { width: 170px; display: block; margin: 0 0.75rem 2rem; }
.side nav { display: flex; flex-direction: column; gap: 0.25rem; flex: 1; }
.side nav a, .logout { color: var(--ink); padding: 0.6rem 1rem; border-radius: var(--radius-pill); display: flex; justify-content: space-between; align-items: center; gap: 0.5rem; white-space: nowrap; }
.side nav a:hover { background: var(--orange-tint-soft); text-decoration: none; }
.side nav a.active { background: var(--orange); color: var(--white); }
.count { background: var(--orange-tint); color: var(--orange-dark); font-size: 0.75rem; padding: 0 0.5rem; border-radius: 999px; }
.active .count { background: var(--white); }
.logout { color: var(--ink-muted); }
main { flex: 1; min-width: 0; padding: 2rem 2.5rem; max-width: 1400px; }
.head { display: flex; justify-content: space-between; align-items: flex-end; gap: 1rem; flex-wrap: wrap; margin-bottom: 1.5rem; }
.head h1 { margin: 0; }
.kicker { font-size: 0.75rem; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--orange); }
.label { font-size: 0.8125rem; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: var(--ink-muted); }
.muted { color: var(--ink-muted); }
.empty { color: var(--ink-muted); padding: 1rem 0; }
.card { background: var(--white); border: 1px solid var(--line); border-radius: var(--radius-lg); padding: 1.5rem; margin-bottom: 1.5rem; }
.grid { display: grid; gap: 1.5rem; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); margin-bottom: 1.5rem; }
.grid .card { margin: 0; }
.two { display: grid; grid-template-columns: minmax(0, 1fr) 380px; gap: 1.5rem; align-items: start; }
.kpis { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); margin-bottom: 1.5rem; }
.kpi { background: var(--white); border: 1px solid var(--line); border-radius: var(--radius-lg); padding: 1.25rem 1.5rem; }
.kpi .value { font-family: var(--font-heading); font-weight: 600; font-size: 2rem; line-height: 1.1; margin: 0.35rem 0 0.15rem; }
/* knoppen en formulieren */
.btn { display: inline-flex; align-items: center; gap: 0.5rem; font: 600 15px/1 var(--font-body); padding: 0.75rem 1.4rem; border-radius: var(--radius-pill); border: 1px solid var(--orange); background: var(--orange); color: var(--white); cursor: pointer; white-space: nowrap; }
.btn:hover { background: var(--orange-dark); text-decoration: none; }
.btn.ghost { background: var(--white); color: var(--orange); border-color: var(--orange-line); }
.btn.ghost:hover { background: var(--orange-tint-soft); border-color: var(--orange); }
.btn.quiet { background: var(--white); color: var(--ink-muted); border-color: var(--line); }
.btn.small { padding: 0.45rem 0.9rem; font-size: 14px; }
form.inline { display: inline; }
label { display: block; font-weight: 600; font-size: 0.9rem; margin-bottom: 0.3rem; }
input, select, textarea { width: 100%; font: 16px/1.4 var(--font-body); color: var(--ink); padding: 0.6rem 0.9rem; border: 1px solid var(--control); border-radius: var(--radius-sm); background: var(--white); }
input[type=checkbox] { width: auto; margin-right: 0.4rem; accent-color: var(--orange); }
input[type=file] { border-style: dashed; }
textarea { min-height: 110px; resize: vertical; }
input:focus, select:focus, textarea:focus { outline: none; border-color: var(--orange); box-shadow: 0 0 0 0.25rem var(--orange-focus); }
.fields { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
.fields .full { grid-column: 1 / -1; }
.actions { display: flex; gap: 0.75rem; flex-wrap: wrap; align-items: center; margin-top: 1.25rem; }
.head .actions { margin: 0; }
.hint { font-size: 0.875rem; color: var(--ink-muted); margin: 0.3rem 0 0; }
/* tabellen */
.table-wrap { overflow-x: auto; }
table { width: 100%; border-collapse: collapse; }
th { text-align: left; font-size: 0.8125rem; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: var(--ink-muted); padding: 0.5rem 0.75rem; border-bottom: 1px solid var(--line); white-space: nowrap; }
td { padding: 0.7rem 0.75rem; border-bottom: 1px solid var(--line); vertical-align: top; }
tbody tr:last-child td { border-bottom: 0; }
tr.link { cursor: pointer; }
tr.link:hover td { background: var(--orange-tint-soft); }
.num { text-align: right; white-space: nowrap; }
.thumb-sm { width: 48px; height: 48px; border-radius: 10px; object-fit: cover; background: var(--blue); display: block; }
.chip { display: inline-block; font-size: 0.75rem; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; padding: 0.15rem 0.65rem; border-radius: 999px; background: var(--blue); color: var(--ink); white-space: nowrap; }
.chip.nieuw, .chip.concept { background: var(--orange-tint); color: var(--orange-dark); }
.chip.offerte, .chip.verzonden { background: var(--blue-dark); }
.chip.gewonnen, .chip.geaccepteerd { background: var(--orange); color: var(--white); }
.chip.verloren, .chip.afgewezen { background: var(--light); color: var(--ink-muted); }
.filters { display: flex; gap: 0.5rem; flex-wrap: wrap; margin-bottom: 1rem; align-items: center; }
.filters a { padding: 0.35rem 0.9rem; border-radius: 999px; border: 1px solid var(--line); color: var(--ink); background: var(--white); font-size: 0.9rem; }
.filters a:hover { border-color: var(--orange-line); text-decoration: none; }
.filters a.on { background: var(--orange); border-color: var(--orange); color: var(--white); }
.search { display: flex; gap: 0.5rem; }
.search input { width: 260px; }
.flash { padding: 0.8rem 1.2rem; border-radius: var(--radius-md); background: var(--blue-light); border: 1px solid var(--blue); margin-bottom: 1rem; }
.flash.error { background: var(--orange-tint-soft); border-color: var(--orange-line); }
/* grafieken */
.bars { display: flex; flex-direction: column; gap: 0.6rem; }
.bar { display: grid; grid-template-columns: 110px 1fr 40px; gap: 0.75rem; align-items: center; color: var(--ink); font-weight: 400; }
a.bar:hover { text-decoration: none; color: var(--orange); }
.bar .track { display: block; background: var(--blue-light); border-radius: 999px; height: 10px; overflow: hidden; }
.bar .fill { display: block; background: var(--orange); height: 100%; border-radius: 999px; }
.cols { display: flex; align-items: flex-end; gap: 6px; height: 170px; }
.cols > div { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: flex-end; height: 100%; gap: 4px; font-size: 0.75rem; color: var(--ink-muted); }
.cols .c { width: 100%; background: var(--orange); border-radius: 6px 6px 0 0; min-height: 2px; }
/* contactpagina */
dl.props { display: grid; grid-template-columns: max-content 1fr; gap: 0.4rem 1rem; margin: 0; }
dl.props dt { color: var(--ink-muted); }
dl.props dd { margin: 0; word-break: break-word; white-space: pre-line; }
.timeline { list-style: none; margin: 0; padding: 0; }
.timeline li { padding: 0.8rem 0; border-bottom: 1px solid var(--line); }
.timeline li:last-child { border: 0; }
.timeline .meta { font-size: 0.8125rem; color: var(--ink-muted); margin-bottom: 0.15rem; }
.timeline .body { white-space: pre-wrap; word-break: break-word; }
.files { display: grid; grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)); gap: 0.75rem; margin-bottom: 1rem; }
.file { border: 1px solid var(--line); border-radius: var(--radius-md); overflow: hidden; font-size: 0.8rem; background: var(--white); }
.file .thumb { aspect-ratio: 1; background: var(--blue); display: flex; align-items: center; justify-content: center; color: var(--ink); font-weight: 600; text-transform: uppercase; }
.file img { width: 100%; height: 100%; object-fit: cover; display: block; }
.file .name { padding: 0.35rem 0.5rem 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--ink); }
.file form { padding: 0 0.5rem 0.35rem; }
.linkbtn { background: none; border: 0; padding: 0; color: var(--ink-muted); font: 600 0.8rem var(--font-body); cursor: pointer; text-decoration: underline; }
details summary { cursor: pointer; font-family: var(--font-heading); font-size: 1.3rem; font-weight: 500; }
details[open] summary { margin-bottom: 1rem; }
/* inbox */
.mailbody { white-space: pre-wrap; word-break: break-word; font-size: 15px; line-height: 1.7; }
tr.unread td { font-weight: 600; }
.dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; background: var(--orange); margin-right: 0.4rem; vertical-align: middle; }
/* offerte-editor */
.lines td { padding: 0.4rem 0.3rem; vertical-align: middle; }
.lines input, .lines select, .lines textarea { padding: 0.45rem 0.6rem; font-size: 15px; }
.lines textarea { min-height: 42px; height: 42px; }
.totals { margin-left: auto; width: 320px; max-width: 100%; margin-top: 1rem; }
.totals td { padding: 0.3rem 0.75rem; border: 0; }
.totals tr.grand td { font-family: var(--font-heading); font-weight: 600; font-size: 1.2rem; border-top: 1px solid var(--line); padding-top: 0.6rem; }
code, pre { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.85rem; background: var(--blue-light); border-radius: var(--radius-sm); }
code { padding: 0.1rem 0.35rem; word-break: break-all; }
pre { padding: 1rem; overflow-x: auto; }
/* inloggen */
.auth { margin: auto; width: 100%; max-width: 420px; padding: 16px; }
.auth .card { padding: 2rem; }
.auth img { width: 200px; margin-bottom: 1.5rem; }
@media (max-width: 900px) {
body { flex-direction: column; }
.side { width: auto; height: auto; position: static; flex-direction: row; align-items: center; padding: 0.75rem 16px; gap: 0.75rem; overflow-x: auto; border-right: 0; border-bottom: 1px solid var(--line); }
.brand img { width: 110px; margin: 0; }
.side nav { flex-direction: row; }
.side nav a, .logout { padding: 0.45rem 0.8rem; }
main { padding: 1.25rem 16px; }
.two { grid-template-columns: 1fr; }
.search, .search input { width: 100%; }
h1 { font-size: 1.6rem; }
}
/* taken */
.task { display: flex; gap: 0.75rem; align-items: flex-start; padding: 0.6rem 0; border-bottom: 1px solid var(--line); }
.task:last-of-type { border-bottom: 0; }
.task.done > div:first-of-type, .task.done .title { text-decoration: line-through; color: var(--ink-muted); }
.check { flex: none; width: 22px; height: 22px; margin-top: 2px; border-radius: 50%; border: 2px solid var(--orange); background: var(--white); cursor: pointer; padding: 0; }
.check:hover, .task.done .check { background: var(--orange); }
.overdue { color: var(--orange-dark); font-weight: 600; }
.inline-fields { display: grid; grid-template-columns: 1fr 160px; gap: 0.5rem; }
/* portaal */
.portal-top { background: var(--white); border-bottom: 1px solid var(--line); padding: 1rem 16px; }
.portal-top .wrap, .portal-main { max-width: 1000px; margin: 0 auto; }
.portal-top .wrap { display: flex; justify-content: space-between; align-items: center; gap: 1rem; }
.portal-top img { width: 160px; display: block; }
.portal-main { padding: 2rem 16px; width: 100%; }
body.portal { flex-direction: column; }
/* dialoog */
.dialog { border: 0; border-radius: var(--radius-lg); padding: 1.75rem; width: min(480px, calc(100vw - 32px)); box-shadow: var(--shadow-menu, 0 10px 30px rgba(0,0,0,.1)); }
.dialog::backdrop { background: rgba(255, 255, 255, 0.6); backdrop-filter: blur(2px); }
.dialog label { font-weight: 600; }
/* relaties */
.members { display: grid; gap: 0.5rem; }
.member { display: flex; justify-content: space-between; align-items: center; gap: 1rem; padding: 0.6rem 0; border-bottom: 1px solid var(--line); }
.member:last-child { border-bottom: 0; }
/* beweging (huisstijl: lift 4–6px met shadow-hover en oranje rand, beeld schaalt 1.03–1.06) */
.fx-wait main, .fx-wait .portal-main, .fx-wait .auth { opacity: 0; }
.kpi, .file, a.bar, .btn, .side nav a { transition: transform 0.6s cubic-bezier(0.22, 1, 0.36, 1), box-shadow 0.6s cubic-bezier(0.22, 1, 0.36, 1), border-color 0.4s, background-color 0.25s, color 0.25s; }
.kpi:hover, .file:hover { transform: translateY(-5px); box-shadow: 0 1.25rem 2.5rem -1rem rgba(0, 0, 0, 0.18); border-color: var(--orange-line); }
.file img { transition: transform 0.8s cubic-bezier(0.22, 1, 0.36, 1); }
.file:hover img { transform: scale(1.05); }
.btn:hover { transform: translateY(-1px); }
.btn:active { transform: translateY(0); }
.side nav a:not(.active):hover { transform: translateX(4px); }
a.bar:hover .fill { background: var(--orange-dark); }
tr.link td { transition: background-color 0.2s; }
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after { transition: none !important; animation: none !important; }
}