From 4b54ea4a12616c30adcfca37741d39d709ccecf9 Mon Sep 17 00:00:00 2001 From: Ramon Date: Tue, 14 Jul 2026 09:59:13 +0200 Subject: [PATCH] v0.3.00-beta: nieuw ontwerp \"teachus.today\" - minimalistisch, nieuw logo, licht+donker MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Nieuw logo: low-poly uil als SVG (transparant, vlakke merk-kleuren) + woordmerk \"teachus.today\" in de menubalk; op kleine schermen alleen de uil. Ook favicon en inlogscherm gebruiken het nieuwe logo. - Nieuwe huisstijl afgeleid van het logo: teal als primaire actiekleur, navy inkt, Quicksand-font (zelf gehost, ~28 KB), dunne lijnen, vlakke minimale chrome-laag; het glas-effect blijft alleen op de bord-laag (widgets/HUD). - Token-systeem herschreven: semantische kleuren (--surface/--line/--accent/...), radius-/schaduwschaal en één control-hoogte (--control-h) zodat alle vakken (inputs, selects, knoppen) in elke rij even hoog zijn; op aanraakschermen groeit alles mee naar 44px. Galerij-tegels hebben nu gelijke hoogtes. - Modern tabsysteem: underline-tabs die overlopen in hun paneel (geen gele file-folder-tabs en omrande panelen meer); kleine keuzegroepen (taal, niveaus, timer, chips) delen één segmented-control-stijl. - Donker thema: schakelbaar (licht/donker/auto volgt het OS), alle panelen, bordpatronen en widgets doen mee; hoog contrast wint altijd van donker. - Nieuw tabblad Instellingen -> Weergave: thema, hoog contrast (verhuisd uit de menubalk), taal NL/EN (verhuisd uit de menubalk), menubalk-positie (boven/links/rechts), animaties aan/uit en glas-effect aan/uit - allemaal apparaat-gebonden en ook als gast bereikbaar via het inlogscherm. - Menubalk: rustiger (transparante knoppen, hairline i.p.v. schaduw) en verplaatsbaar naar links of rechts als verticale kolom; bord, leerling- weergave en zwevende knoppen schuiven mee. - Taalkeuze wordt nu onthouden (localStorage). Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01DuxHJtk5aHe2pA3xwCLEAk --- VERSION | 2 +- public/css/teach.css | 582 ++++++++++++++++++----------- public/fonts/LICENSE-Quicksand.txt | 4 + public/fonts/quicksand.woff2 | Bin 0 -> 28244 bytes public/img/logo.svg | 48 +++ public/index.html | 71 +++- public/js/app.js | 62 ++- public/js/core.js | 32 +- 8 files changed, 555 insertions(+), 246 deletions(-) create mode 100644 public/fonts/LICENSE-Quicksand.txt create mode 100644 public/fonts/quicksand.woff2 create mode 100644 public/img/logo.svg diff --git a/VERSION b/VERSION index 109a20f..b8522ca 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.2.22 +0.3.00 diff --git a/public/css/teach.css b/public/css/teach.css index e683997..8a9f691 100644 --- a/public/css/teach.css +++ b/public/css/teach.css @@ -1,68 +1,106 @@ -/* teach - alle opmaak */ +/* teach - alle opmaak + Ontwerptaal "teachus.today": minimalistisch, vlakke kleuren uit het uil-logo, + ronde typografie (Quicksand), dunne lijnen, uniforme control-hoogtes. */ + @font-face{ + font-family:"Quicksand"; + src:url("../fonts/quicksand.woff2") format("woff2"); + font-weight:300 700; font-display:swap; + } :root{ - --bg:#eef3f8; --panel:#ffffff; --ink:#26344a; --muted:#7b8aa3; - --blue:#3b7dd8; --blue-d:#2b62b0; --red:#e0554d; --green:#3fae6a; - --yellow:#f7c948; --purple:#9b59b6; --orange:#f28c38; + /* logo-palet (vlakke kleuren, geen neon) */ + --navy:#1d3461; --blue:#2f6fe4; --blue-d:#2456b8; --teal:#18c5c0; + --cyan:#3ac2e8; --pink:#e83e8c; --purple:#8b5cf6; --orange:#f28c38; + --red:#e0554d; --green:#3fae6a; --yellow:#f7c948; --wood:#f6e7c9; --wood-d:#e8d2a4; - --radius:16px; --shadow:0 10px 30px rgba(30,50,90,.18); + /* semantisch (licht thema) */ + --bg:#f4f7fb; --surface:#ffffff; --surface-2:#eef2f8; --surface-3:#e3e9f4; + --panel:var(--surface); + --ink:#1d3461; --muted:#71809b; --line:#e2e8f2; + --accent:var(--teal); --accent-ink:#0d6e6b; --accent-soft:#e2f8f7; + --red-soft:#fbe3e1; + /* glas-laag (bord/widgets) */ + --glass:rgba(255,255,255,.55); --glass-strong:rgba(255,255,255,.92); + --glass-line:rgba(255,255,255,.6); + /* maten: alle "vakken" even hoog */ + --control-h:40px; --radius-s:8px; --radius:12px; --radius-l:18px; + --shadow-1:0 1px 3px rgba(29,52,97,.08); --shadow-2:0 12px 32px rgba(29,52,97,.16); + --shadow:var(--shadow-2); + --tbar:58px; /* minimale tikzones voor touch (WCAG/iOS-richtlijn) */ --tap:44px; --tap-sm:36px; } + /* donker thema: zelfde tokens, andere waarden (schakelbaar in Instellingen) */ + body.dark{ + --bg:#0f1626; --surface:#18213a; --surface-2:#202b49; --surface-3:#2a3757; + --ink:#e8edf7; --muted:#8fa0bf; --line:#2c3a5e; + --accent-ink:#7fe6e2; --accent-soft:#153a44; --red-soft:#4a2330; + --glass:rgba(24,33,58,.6); --glass-strong:rgba(24,33,58,.92); + --glass-line:rgba(255,255,255,.08); + --shadow-1:0 1px 3px rgba(0,0,0,.35); --shadow-2:0 12px 32px rgba(0,0,0,.5); + } *{box-sizing:border-box; -webkit-tap-highlight-color:transparent;} *::-webkit-scrollbar{width:8px; height:8px;} *::-webkit-scrollbar-thumb{background:#c3cfde; border-radius:4px;} + body.dark ::-webkit-scrollbar-thumb{background:#3a4a70;} *::-webkit-scrollbar-track{background:transparent;} html,body{height:100%; margin:0; overflow:hidden;} body{ - font-family:"Segoe UI Rounded","Arial Rounded MT Bold",ui-rounded,"Segoe UI",Verdana,sans-serif; + font-family:"Quicksand","Segoe UI Rounded","Arial Rounded MT Bold",ui-rounded,"Segoe UI",Verdana,sans-serif; background:var(--bg); color:var(--ink); user-select:none; } input,textarea{user-select:text;} - /* ---------- Toolbar ---------- */ + /* weergave-instelling "minder beweging" */ + body.no-motion *,body.no-motion *::before,body.no-motion *::after{ + transition-duration:0s !important; animation-duration:0s !important; + } + /* ---------- Menubalk ---------- */ #toolbar{ - position:fixed; top:0; left:0; right:0; height:58px; z-index:5000; - background:var(--panel); box-shadow:0 2px 10px rgba(30,50,90,.10); - display:flex; align-items:center; gap:10px; padding:0 16px; + position:fixed; top:0; left:0; right:0; height:var(--tbar); z-index:5000; + background:var(--surface); border-bottom:1px solid var(--line); + display:flex; align-items:center; gap:8px; padding:0 14px; overflow-x:auto; overflow-y:hidden; scrollbar-width:none; } #toolbar::-webkit-scrollbar{display:none;} - #zoomPct{min-width:58px; padding:9px 8px; font-size:13px; text-align:center;} - #zoomPct.on{background:var(--yellow); color:#6b5200;} + #zoomPct{min-width:56px; padding:0 8px; font-size:13px; text-align:center;} + #zoomPct.on{background:var(--accent-soft); color:var(--accent-ink);} #btnZoomIn:disabled,#btnZoomOut:disabled{opacity:.35; cursor:default;} - .logo{display:flex; align-items:baseline; gap:1px; font-size:30px; font-weight:900; line-height:1;} - .logo span{display:inline-block; transform-origin:bottom center;} - .logo .l1{color:var(--red); transform:rotate(-6deg);} - .logo .l2{color:var(--orange); transform:rotate(4deg) translateY(-2px);} - .logo .l3{color:var(--green); transform:rotate(-3deg);} - .logo .l4{color:var(--blue); transform:rotate(5deg) translateY(-1px);} - .logo .l5{color:var(--purple); transform:rotate(-4deg);} - .logo .crayon{font-size:24px; margin-left:6px; transform:rotate(10deg);} + /* logo: uil (SVG) + woordmerk "teachus.today" in merk-kleuren */ + .logo{display:flex; align-items:center; gap:9px; line-height:1; flex:none;} + .logo-owl{width:34px; height:30px; display:block;} + .logo-word{font-size:21px; font-weight:700; letter-spacing:.2px; white-space:nowrap;} + .logo-word .lw-teach{color:var(--ink);} + .logo-word .lw-us{color:var(--teal);} + .logo-word .lw-dot{color:var(--orange);} + .logo-word .lw-today{ + background:linear-gradient(90deg,var(--blue),var(--purple),var(--pink),var(--orange)); + -webkit-background-clip:text; background-clip:text; color:transparent; + } #verTag{font-size:10.5px; font-weight:700; color:var(--muted);} - #verTag.beta{color:#fff; background:var(--orange); padding:1px 7px; border-radius:8px;} - .logo:hover span:not(.crayon){animation:bounce .5s;} - .logo .l2{animation-delay:.05s;} .logo .l3{animation-delay:.1s;} - .logo .l4{animation-delay:.15s;} .logo .l5{animation-delay:.2s;} - @keyframes bounce{0%,100%{transform:translateY(0);} 40%{transform:translateY(-8px);}} + #verTag.beta{color:#fff; background:var(--orange); padding:1px 7px; border-radius:var(--radius-s);} #toolbar .spacer{flex:1;} .tbtn{ - border:none; border-radius:12px; padding:9px 14px; font:inherit; font-weight:700; - background:var(--blue); color:#fff; cursor:pointer; font-size:14.5px; + border:none; border-radius:var(--radius); min-height:var(--control-h); + padding:0 14px; font:inherit; font-weight:700; + background:var(--accent); color:#fff; cursor:pointer; font-size:14.5px; } - .tbtn:hover{background:var(--blue-d);} - .tbtn.ghost{background:#e8eef6; color:var(--ink);} - .tbtn.ghost:hover{background:#dbe5f1;} + .tbtn:hover{filter:brightness(.94);} + .tbtn.ghost{background:var(--surface); color:var(--ink); border:1px solid var(--line);} + .tbtn.ghost:hover{background:var(--surface-3); filter:none;} + /* in de menubalk zelf zijn ghost-knoppen transparant (rustiger beeld) */ + #toolbar .tbtn.ghost{background:transparent; border:none;} + #toolbar .tbtn.ghost:hover{background:var(--surface-2);} .tbtn:disabled{opacity:.55; cursor:default;} - #btnSave{min-width:158px; text-align:center;} + #btnSave{min-width:150px; text-align:center;} #btnSave.ok{background:var(--green); color:#fff;} - #btnUser.on{background:var(--green); color:#fff;} - #langToggle{display:flex; background:#e8eef6; border-radius:12px; overflow:hidden;} + #btnUser.on{background:var(--accent-soft); color:var(--accent-ink);} + #langToggle{display:flex; background:var(--surface-2); border-radius:999px; padding:3px; gap:2px;} #langToggle button{ - border:none; padding:9px 13px; font:inherit; font-weight:700; cursor:pointer; - background:transparent; color:var(--muted); font-size:13.5px; + border:none; border-radius:999px; padding:6px 13px; font:inherit; font-weight:700; + cursor:pointer; background:transparent; color:var(--muted); font-size:13.5px; } - #langToggle button.active{background:var(--blue); color:#fff;} + #langToggle button.active{background:var(--surface); color:var(--ink); box-shadow:var(--shadow-1);} /* ---------- Board ---------- */ - #board{position:absolute; inset:58px 0 0 0; overflow:hidden;} + #board{position:absolute; inset:var(--tbar) 0 0 0; overflow:hidden;} #board.bg-dots{ background-image:radial-gradient(circle,#c9d6e5 1.4px,transparent 1.4px); background-size:26px 26px; @@ -93,7 +131,7 @@ body.pupil-mode #hud,body.pupil-mode #btnFolders,body.pupil-mode #btnSave{display:none !important;} body.pupil-mode #pupilView{ display:flex; flex-wrap:wrap; gap:18px; align-content:flex-start; - position:absolute; inset:58px 0 0 0; overflow:auto; padding:18px; box-sizing:border-box; + position:absolute; inset:var(--tbar) 0 0 0; overflow:auto; padding:18px; box-sizing:border-box; } #pupilView .pupil-card{ position:static; max-width:100%; box-shadow:0 6px 20px rgba(30,50,90,.12); @@ -135,19 +173,19 @@ } #boardStrip.open{display:flex;} .bs-card{ - width:168px; flex:none; background:#fff; border-radius:12px; - border:2.5px solid #e3eaf3; cursor:pointer; overflow:hidden; + width:168px; flex:none; background:var(--surface); border-radius:12px; + border:2.5px solid var(--line); cursor:pointer; overflow:hidden; } .bs-card:hover{border-color:var(--blue);} - .bs-card.active{border-color:var(--yellow);} - .bs-card canvas{display:block; width:168px; height:105px; background:#fff;} + .bs-card.active{border-color:var(--accent);} + .bs-card canvas{display:block; width:168px; height:105px; background:var(--surface);} .bs-name{ font-size:12px; font-weight:800; padding:5px 8px; display:flex; justify-content:space-between; align-items:center; gap:6px; } .bs-name span{overflow:hidden; text-overflow:ellipsis; white-space:nowrap;} .bs-x{ - border:none; background:#fbe3e1; color:var(--red); border-radius:7px; + border:none; background:var(--red-soft); color:var(--red); border-radius:7px; min-width:26px; height:24px; font-size:11px; font-weight:900; cursor:pointer; flex:none; } .bs-x:hover{background:var(--red); color:#fff;} @@ -168,24 +206,24 @@ .bp-folder{display:flex; align-items:center; gap:6px; font-weight:800; font-size:14px; margin-top:4px;} .bp-folder .bpf-name{flex:1; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;} .bp-folder button{ - border:none; background:#e8eef6; border-radius:8px; padding:4px 8px; font:inherit; + border:none; background:var(--surface-2); border-radius:8px; padding:4px 8px; font:inherit; font-weight:800; font-size:11.5px; cursor:pointer; color:var(--muted); flex:none; } - .bp-folder button:hover{background:#dbe5f1; color:var(--ink);} + .bp-folder button:hover{background:var(--surface-3); color:var(--ink);} .bp-boards{display:flex; flex-wrap:wrap; gap:6px;} .bp-board{ - display:flex; align-items:center; gap:5px; border:2px solid #e3eaf3; background:#fff; + display:flex; align-items:center; gap:5px; border:1px solid var(--line); background:var(--surface); border-radius:10px; padding:5px 10px; font:inherit; font-weight:700; font-size:12.5px; cursor:pointer; color:var(--muted); } - .bp-board.active{border-color:var(--yellow); background:var(--yellow); color:#6b5200;} + .bp-board.active{border-color:var(--accent); background:var(--accent-soft); color:var(--accent-ink);} .bp-board .bpb-x{border:none; background:transparent; color:var(--red); font-weight:900; cursor:pointer; padding:0; font-size:11px; opacity:.8;} .bp-board:hover .bpb-x{opacity:1;} .bp-board input{border:none; outline:none; font:inherit; width:80px; background:transparent;} .bp-new{display:flex; gap:6px; margin-top:6px;} .bp-new input{ - flex:1; min-width:0; border:2px solid #cdd9e8; border-radius:10px; padding:7px 9px; + flex:1; min-width:0; border:1px solid var(--line); border-radius:10px; padding:7px 9px; font:inherit; font-size:13px; outline:none; } .bp-hint{font-size:11px; color:var(--muted); font-weight:700;} @@ -196,13 +234,13 @@ border-radius:14px; padding:11px 16px; font:inherit; font-weight:800; font-size:14px; color:var(--ink); cursor:pointer; box-shadow:0 6px 18px rgba(30,50,90,.22); } - .fab-item:hover{background:#fff; transform:translateX(-4px);} - .fab-item.on{background:var(--yellow);} + .fab-item:hover{background:var(--surface); transform:translateX(-4px);} + .fab-item.on{background:var(--accent-soft); color:var(--accent-ink);} .fab-item .fi{font-size:18px;} /* pen palette (section inside #hud, always visible) */ #penbar{display:flex; gap:6px; align-items:center; flex-wrap:wrap;} - .pen-close{background:#e8eef6 !important; color:var(--ink) !important;} - .pen-close.on{background:var(--yellow) !important; color:#6b5200 !important;} + .pen-close{background:var(--surface-2) !important; color:var(--ink) !important;} + .pen-close.on{background:var(--accent-soft) !important; color:var(--accent-ink) !important;} body:not(.pen) .pen-tools button.on{background:transparent; box-shadow:none;} .pen-grip{cursor:grab; font-size:15px; color:var(--muted); padding:0 2px; touch-action:none;} .pen-grip:active{cursor:grabbing;} @@ -249,18 +287,18 @@ } .mm-node:hover .mm-cog{display:block;} .mm-pop{ - position:absolute; z-index:20; background:#fff; border-radius:12px; padding:9px 10px; + position:absolute; z-index:20; background:var(--surface); border-radius:12px; padding:9px 10px; box-shadow:0 10px 26px rgba(30,50,90,.3); display:flex; flex-direction:column; gap:7px; } .mm-pop .mp-row{display:flex; gap:5px; align-items:center;} .mm-pop .mp-lbl{font-size:11px; font-weight:800; color:var(--muted); width:16px; text-align:center;} .mm-pop button{border:none; cursor:pointer; padding:0; background:transparent;} - .mm-pop .mp-sw{width:19px; height:19px; border-radius:50%; border:2px solid #fff; box-shadow:0 0 0 1.5px #cdd9e8;} + .mm-pop .mp-sw{width:19px; height:19px; border-radius:50%; border:2px solid #fff; box-shadow:0 0 0 1.5px var(--line);} .mm-pop .mp-sw.on{box-shadow:0 0 0 2.5px var(--ink);} - .mm-pop .mp-fs{font-weight:900; color:var(--ink); width:24px; height:24px; border-radius:7px; background:#e8eef6;} - .mm-pop .mp-fs.on{background:var(--yellow);} - .mm-pop .mp-ls{width:34px; height:24px; border-radius:7px; background:#e8eef6; position:relative;} - .mm-pop .mp-ls.on{background:var(--yellow);} + .mm-pop .mp-fs{font-weight:900; color:var(--ink); width:24px; height:24px; border-radius:7px; background:var(--surface-2);} + .mm-pop .mp-fs.on{background:var(--accent-soft);} + .mm-pop .mp-ls{width:34px; height:24px; border-radius:7px; background:var(--surface-2); position:relative;} + .mm-pop .mp-ls.on{background:var(--accent-soft);} .mm-pop .mp-ls i{display:block; border-top:2.5px solid var(--ink); width:24px; margin:0 auto;} .mm-pop .mp-ls[data-ls=dash] i{border-top-style:dashed;} .mm-pop .mp-ls[data-ls=dot] i{border-top-style:dotted;} @@ -270,7 +308,7 @@ .dtool:active{cursor:grabbing;} .dtool .dtool-x{ position:absolute; top:-10px; right:-10px; width:24px; height:24px; border-radius:50%; - border:none; background:#fbe3e1; color:var(--red); font-weight:900; cursor:pointer; + border:none; background:var(--red-soft); color:var(--red); font-weight:900; cursor:pointer; font-size:12px; line-height:1; box-shadow:0 2px 6px rgba(0,0,0,.2); z-index:2; } .dtool .dtool-rot{ @@ -282,15 +320,15 @@ .dtool-geo{width:340px; height:184px;} .dtool-opts{position:absolute; top:-12px; left:8px; display:flex; gap:5px;} .dtool-opts button{ - width:24px; height:24px; border-radius:50%; border:none; background:#fff; + width:24px; height:24px; border-radius:50%; border:none; background:var(--surface); color:var(--ink); font-size:12px; font-weight:900; cursor:pointer; line-height:1; box-shadow:0 2px 6px rgba(0,0,0,.25); } - .dtool-opts button:hover{background:var(--yellow);} + .dtool-opts button:hover{background:var(--accent-soft);} .dtool-lens{z-index:4500;} /* the glass sits above the ink sheet */ .dtool-lens canvas{ border:5px solid #5a6c85; box-shadow:0 8px 22px rgba(0,0,0,.3); - background:#fff; display:block; + background:var(--surface); display:block; } /* =========== Mindmap widget =========== */ .mm{flex:1; min-height:0; display:flex; flex-direction:column; position:relative;} @@ -302,10 +340,10 @@ .mm-grip{cursor:grab; color:var(--muted); font-size:14px; padding:0 2px; touch-action:none; user-select:none;} .mm-grip:active{cursor:grabbing;} .mm-hint{font-size:12px; font-weight:700; color:var(--muted); max-width:180px;} - .mm-stage{flex:1; min-height:0; position:relative; overflow:hidden; background:#fff;} + .mm-stage{flex:1; min-height:0; position:relative; overflow:hidden; background:var(--surface);} .mm-stage svg{position:absolute; inset:0; width:100%; height:100%; pointer-events:none;} .mm-node{ - position:absolute; transform:translate(-50%,-50%); background:#fff; + position:absolute; transform:translate(-50%,-50%); background:var(--surface); border:2.5px solid var(--blue); padding:8px 16px; font-weight:800; font-size:15px; cursor:grab; touch-action:none; min-width:64px; text-align:center; box-shadow:0 3px 10px rgba(30,50,90,.15); border-radius:50px; @@ -322,7 +360,7 @@ } .mm-node:hover .mm-add,.mm-node:hover .mm-del{display:block;} .mm-add{right:-11px; top:50%; transform:translateY(-50%); background:var(--green); color:#fff;} - .mm-del{left:-9px; top:-9px; background:#fbe3e1; color:var(--red);} + .mm-del{left:-9px; top:-9px; background:var(--red-soft); color:var(--red);} /* ---------- Widget windows ---------- */ .widget{ position:absolute; background:rgba(255,255,255,.55); border-radius:var(--radius); @@ -366,14 +404,14 @@ #hud.has-dock #dock{display:flex;} /* collapse + orientation */ .hud-btn{ - border:none; background:#e8eef6; border-radius:8px; width:26px; height:26px; + border:none; background:var(--surface-2); border-radius:8px; width:26px; height:26px; cursor:pointer; font-size:13px; line-height:1; padding:0; flex:none; font-weight:900; color:var(--ink); } - .hud-btn:hover{background:#dbe5f1;} + .hud-btn:hover{background:var(--surface-3);} #hud.min #penbar,#hud.min #dock,#hud.min .hud-div{display:none !important;} #hud.vert{ flex-direction:column; align-items:center; flex-wrap:nowrap; - max-height:calc(100vh - 84px); overflow-y:auto; overflow-x:hidden; + max-height:calc(100vh - var(--tbar) - 26px); overflow-y:auto; overflow-x:hidden; max-width:none; width:92px; } #hud.vert #penbar{flex-direction:column; flex-wrap:nowrap; align-items:center;} @@ -381,11 +419,11 @@ #hud.vert .hud-div{width:26px; height:1.5px;} #hud.vert #dock{flex-direction:column; flex-wrap:nowrap;} .dock-item{ - border:none; display:flex; align-items:center; gap:7px; background:#fff; + border:none; display:flex; align-items:center; gap:7px; background:var(--surface); border-radius:10px; padding:6px 12px; font:inherit; font-weight:700; font-size:13px; color:var(--ink); cursor:pointer; box-shadow:0 2px 6px rgba(30,50,90,.12); } - .dock-item:hover{background:#eef3f9; transform:translateY(-2px);} + .dock-item:hover{background:var(--surface-2); transform:translateY(-2px);} .dock-item .di{font-size:16px; line-height:1;} .widget-head{ display:flex; align-items:center; gap:10px; padding:10px 14px; @@ -396,49 +434,58 @@ .widget-head .wicon{font-size:20px;} .widget-head .wtitle{font-weight:800; font-size:15px; flex:1; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;} .wclose{ - border:none; background:#fbe3e1; color:var(--red); width:28px; height:28px; + border:none; background:var(--red-soft); color:var(--red); width:28px; height:28px; border-radius:9px; font-weight:900; cursor:pointer; font-size:14px; line-height:1; flex:none; } .wclose:hover{background:var(--red); color:#fff;} .wmin{ - border:none; background:#e8eef6; color:var(--ink); width:28px; height:28px; + border:none; background:var(--surface-2); color:var(--ink); width:28px; height:28px; border-radius:9px; font-weight:900; cursor:pointer; font-size:15px; line-height:1; flex:none; } - .wmin:hover{background:#dbe5f1;} + .wmin:hover{background:var(--surface-3);} .wz{font-size:10.5px; width:auto; min-width:30px; padding:0 5px;} - .wz.on{background:var(--yellow); color:#6b5200;} + .wz.on{background:var(--accent-soft); color:var(--accent-ink);} .widget-body{flex:1; overflow:hidden; position:relative; display:flex; flex-direction:column; min-height:0;} /* ---------- Modals ---------- */ .modalwrap{ - position:fixed; inset:0; z-index:6000; background:rgba(30,45,70,.45); + position:fixed; inset:0; z-index:6000; background:rgba(15,22,38,.4); display:none; align-items:center; justify-content:center; } .modalwrap.open{display:flex;} .modal{ - background:var(--panel); border-radius:20px; padding:26px; width:min(680px,92vw); - max-height:88vh; overflow:auto; box-shadow:var(--shadow); + background:var(--surface); border-radius:var(--radius-l); padding:24px 26px; + width:min(680px,92vw); max-height:88vh; overflow:auto; + box-shadow:var(--shadow-2); border:1px solid var(--line); } - .modal h2{margin:0 0 18px; font-size:21px;} - .gallery{display:grid; grid-template-columns:repeat(auto-fill,minmax(180px,1fr)); gap:14px;} + .modal h2{margin:0 0 14px; font-size:20px; font-weight:700;} + /* galerij: gelijke tegel-hoogtes (grid-rijen strekken mee, vaste inhoud-zones) */ + .gallery{display:grid; grid-template-columns:repeat(auto-fill,minmax(180px,1fr)); grid-auto-rows:1fr; gap:12px;} .gcard{ - border:2px solid #e3eaf3; border-radius:16px; padding:18px 14px; text-align:center; - cursor:pointer; transition:all .15s; background:#fbfdff; + border:1px solid var(--line); border-radius:var(--radius); padding:16px 14px; + text-align:center; cursor:pointer; transition:border-color .15s, box-shadow .15s; + background:var(--surface); display:flex; flex-direction:column; + align-items:center; justify-content:flex-start; min-height:132px; } - .gcard:hover{border-color:var(--blue); transform:translateY(-2px); box-shadow:0 6px 18px rgba(59,125,216,.18);} - .gcard .gi{font-size:38px;} - .gcard .gn{font-weight:800; margin-top:8px; font-size:15px;} + .gcard:hover{border-color:var(--accent); box-shadow:var(--shadow-1);} + .gcard .gi{font-size:36px; line-height:1;} + .gcard .gn{font-weight:700; margin-top:9px; font-size:15px;} .gcard .gd{font-size:12.5px; color:var(--muted); margin-top:4px; line-height:1.35;} /* login + instellingen modals */ #loginModal{width:min(400px,92vw);} + .login-logo{display:flex; align-items:center; justify-content:center; gap:10px; margin:2px 0 18px;} + .login-logo .logo-owl{width:46px; height:40px;} + .login-logo .logo-word{font-size:24px;} /* instellingen is breder dan het inlogscherm: het beheerpaneel (tabblad) heeft de ruimte nodig van wat vroeger een eigen, brede modal was (#adminModal) */ #settingsModal{width:min(760px,94vw); max-height:86vh; overflow:auto;} #settingsAccountPanel{max-width:400px;} #loginModal input,#settingsModal input{ - width:100%; border:2px solid #cdd9e8; border-radius:12px; padding:11px 12px; - font:inherit; font-size:16px; outline:none; margin-bottom:10px; + width:100%; border:1px solid var(--line); border-radius:var(--radius); + height:var(--control-h); padding:0 12px; + font:inherit; font-size:15px; outline:none; margin-bottom:10px; + background:var(--surface); color:var(--ink); } - #loginModal input:focus,#settingsModal input:focus{border-color:var(--blue);} + #loginModal input:focus,#settingsModal input:focus{border-color:var(--accent);} .lrow{display:flex; gap:8px;} .lrow .tbtn{flex:1;} .lrow input{flex:1; min-width:0; margin-bottom:0;} @@ -453,7 +500,7 @@ #settingsModal .am-reset .guestnote{margin-top:2px;} .st-footer{ display:flex; justify-content:space-between; align-items:center; gap:8px; - margin-top:16px; padding-top:12px; border-top:1.5px solid #e3eaf3; + margin-top:16px; padding-top:12px; border-top:1.5px solid var(--line); font-size:11px; color:var(--muted); } #settingsModal .am-name{font-size:16px;} @@ -462,30 +509,30 @@ ==========================================================*/ .lg{display:flex; flex-direction:column; flex:1; min-height:0; padding:12px 14px; gap:10px;} .lg-top{display:flex; gap:8px; align-items:center; flex-wrap:wrap;} - .lg-levels{display:flex; background:#e8eef6; border-radius:12px; overflow:hidden;} + .lg-levels{display:flex; background:var(--surface-2); border-radius:999px; padding:3px; gap:2px;} .lg-levels button{ - border:none; background:transparent; padding:8px 13px; font:inherit; font-weight:800; - font-size:13.5px; color:var(--muted); cursor:pointer; + border:none; border-radius:999px; background:transparent; padding:6px 12px; + font:inherit; font-weight:700; font-size:13.5px; color:var(--muted); cursor:pointer; } - .lg-levels button.active{background:var(--green); color:#fff;} + .lg-levels button.active{background:var(--surface); color:var(--ink); box-shadow:var(--shadow-1);} .lg-cards{display:flex; gap:5px; flex-wrap:wrap;} .lg-cards button{ - border:2px solid #e3eaf3; background:#fff; width:34px; height:34px; border-radius:10px; + border:1px solid var(--line); background:var(--surface); width:34px; height:34px; border-radius:10px; font:inherit; font-weight:800; color:var(--muted); cursor:pointer; font-size:14px; } - .lg-cards button.active{border-color:var(--yellow); background:var(--yellow); color:#6b5200;} + .lg-cards button.active{border-color:var(--accent); background:var(--accent-soft); color:var(--accent-ink);} .lg-cards .lg-theme{ width:auto; padding:0 11px; max-width:120px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; } .lg-num{ - border:2px solid #e3eaf3; border-radius:10px; height:34px; font:inherit; - font-weight:800; font-size:13px; color:var(--muted); background:#fff; + border:1px solid var(--line); border-radius:10px; height:34px; font:inherit; + font-weight:800; font-size:13px; color:var(--muted); background:var(--surface); padding:0 4px; outline:none; cursor:pointer; } .lg-snd,.lg-mode{ - border:2px solid #e3eaf3; border-radius:10px; width:34px; height:34px; - background:#fff; cursor:pointer; font-size:15px; line-height:1; padding:0; flex:none; + border:1px solid var(--line); border-radius:10px; width:34px; height:34px; + background:var(--surface); cursor:pointer; font-size:15px; line-height:1; padding:0; flex:none; } .lg-snd.off{opacity:.55;} /* small digit blocks/slots for the maths widgets */ @@ -515,29 +562,29 @@ .lg:not(.typemode) .lg-kbd{display:none;} .lg-ed-themerow{display:flex; gap:8px; align-items:center;} .ed-theme-sel{ - flex:1; min-width:0; border:2px solid #cdd9e8; border-radius:10px; padding:9px 10px; - font:inherit; font-weight:700; font-size:15px; outline:none; background:#fff; cursor:pointer; + flex:1; min-width:0; border:1px solid var(--line); border-radius:10px; padding:9px 10px; + font:inherit; font-weight:700; font-size:15px; outline:none; background:var(--surface); cursor:pointer; } .ed-theme-name{ border:2px solid var(--blue); border-radius:10px; padding:9px 10px; font:inherit; font-size:15px; outline:none; width:180px; } .ed-theme-del{ - border:none; background:#fbe3e1; color:var(--red); border-radius:10px; + border:none; background:var(--red-soft); color:var(--red); border-radius:10px; width:40px; height:40px; cursor:pointer; font-size:15px; flex:none; } .ed-theme-del:hover{background:var(--red); color:#fff;} .lg-progress{margin-left:auto; font-size:13.5px; font-weight:700; color:var(--muted); display:flex; align-items:center; gap:8px; white-space:nowrap;} .lg-stars{color:#d9a400; font-size:14px; min-width:34px; text-align:right;} .lg-instr{ - background:#f1f7ff; border:1.5px dashed #bcd4f2; + background:var(--surface-2); border:1.5px dashed #bcd4f2; border-radius:12px; padding:6px 14px; font-size:14.5px; font-weight:700; color:#37588a; text-align:center; min-height:42px; display:flex; align-items:center; justify-content:center; flex:none; } .lg-card{ flex:1; display:flex; flex-direction:column; align-items:center; justify-content:center; - gap:16px; background:linear-gradient(#ffffff,#f6fafe); border:2px solid #e3eaf3; + gap:16px; background:var(--surface); border:1px solid var(--line); border-radius:18px; padding:12px; min-height:0; position:relative; overflow:hidden; } .lg-pic{font-size:64px; line-height:1; filter:drop-shadow(0 4px 6px rgba(0,0,0,.12));} @@ -582,7 +629,7 @@ .slot .dots i.off{background:transparent; border:1px dotted #ccd7e4; width:7px; height:7px;} .lg-tray{ display:flex; gap:12px; justify-content:center; flex-wrap:wrap; - background:#eef3f9; border-radius:16px; padding:14px 12px; min-height:130px; flex:none; + background:var(--surface-2); border-radius:16px; padding:14px 12px; min-height:130px; flex:none; } .lg-bottom{display:flex; align-items:center; justify-content:center; gap:12px; min-height:46px; flex:none;} .lg-next{ @@ -606,7 +653,7 @@ } /* ---------- custom words editor ---------- */ .lg-editor{ - position:absolute; inset:0; z-index:20; background:#fff; display:none; + position:absolute; inset:0; z-index:20; background:var(--surface); display:none; flex-direction:column; gap:10px; padding:14px 16px; overflow:auto; } .lg-editor.open{display:flex;} @@ -614,65 +661,76 @@ .lg-ed-head b{font-size:17px;} .lg-ed-form{ display:flex; gap:10px; align-items:center; flex-wrap:wrap; - background:#f1f7ff; border-radius:14px; padding:12px; + background:var(--surface-2); border-radius:14px; padding:12px; } .lg-ed-form input[type=text]{ - border:2px solid #cdd9e8; border-radius:10px; padding:9px 10px; font:inherit; + border:1px solid var(--line); border-radius:10px; padding:9px 10px; font:inherit; font-size:16px; outline:none; } .lg-ed-form input.ed-word{width:170px; text-transform:lowercase;} .ed-preview{width:52px; height:52px; display:flex; align-items:center; justify-content:center; - font-size:34px; background:#fff; border-radius:10px; border:2px dashed #cdd9e8; overflow:hidden; flex:none;} + font-size:34px; background:var(--surface); border-radius:10px; border:2px dashed var(--line); overflow:hidden; flex:none;} .ed-preview img{width:100%; height:100%; object-fit:contain;} .ed-add{border:none; border-radius:10px; padding:11px 20px; font:inherit; font-weight:800; background:var(--green); color:#fff; cursor:pointer; font-size:14.5px;} .ed-msg{width:100%; color:var(--red); font-weight:700; font-size:13.5px; min-height:16px;} - /* picture picker tabs */ - .ed-tabs{display:flex; gap:6px;} - .ed-tabs button{ - border:none; border-radius:10px 10px 0 0; padding:9px 16px; font:inherit; font-weight:800; - font-size:13.5px; background:#e8eef6; color:var(--muted); cursor:pointer; + /* modern tabsysteem: underline-tabs die overlopen in hun paneel. + De tabbalk deelt de ondergrond met de inhoud; alleen een hairline scheidt ze + en de accentlijn van de actieve tab valt daaroverheen. */ + .ed-tabs{ + display:flex; gap:2px; border-bottom:1px solid var(--line); margin-bottom:14px; } - .ed-tabs button.active{background:var(--yellow); color:#6b5200;} - .ed-pane{background:#fbfdff; border:2px solid #e3eaf3; border-radius:0 12px 12px 12px; padding:12px; min-height:120px;} + .ed-tabs button{ + border:none; border-radius:0; padding:10px 15px 11px; font:inherit; font-weight:700; + font-size:14px; background:transparent; color:var(--muted); cursor:pointer; + position:relative; margin-bottom:-1px; + } + .ed-tabs button:hover{color:var(--ink);} + .ed-tabs button.active{color:var(--ink);} + .ed-tabs button.active::after{ + content:""; position:absolute; left:10px; right:10px; bottom:0; + height:2.5px; border-radius:2px; background:var(--accent); + } + .ed-pane{padding:2px 0 0; min-height:120px;} + /* uniforme segmented control (kleine keuzegroepen: taal, niveau, timer, chips) */ .ed-cats{display:flex; gap:5px; flex-wrap:wrap; margin-bottom:10px;} .ed-cats button{ - border:none; background:#e8eef6; border-radius:9px; padding:6px 11px; font:inherit; - font-weight:800; font-size:12.5px; color:var(--muted); cursor:pointer; + border:none; background:var(--surface-2); border-radius:999px; padding:6px 12px; font:inherit; + font-weight:700; font-size:12.5px; color:var(--muted); cursor:pointer; } - .ed-cats button.active{background:var(--blue); color:#fff;} + .ed-cats button.active{background:var(--surface); color:var(--ink); box-shadow:var(--shadow-1); outline:1.5px solid var(--accent);} .ed-grid{display:flex; gap:4px; flex-wrap:wrap; max-height:170px; overflow:auto;} .ed-grid button{ border:none; background:transparent; border-radius:9px; font-size:26px; width:42px; height:42px; cursor:pointer; padding:0; line-height:1; } .ed-grid button:hover{background:#dbe8f8;} - .ed-grid button.sel{background:var(--yellow);} + .ed-grid button.sel{background:var(--accent-soft); outline:1.5px solid var(--accent);} .ed-pictorow{display:flex; gap:8px; margin-bottom:10px;} - .ed-pictorow input{flex:1; border:2px solid #cdd9e8; border-radius:10px; padding:9px 10px; font:inherit; font-size:15px; outline:none;} + .ed-pictorow input{flex:1; border:1px solid var(--line); border-radius:10px; padding:9px 10px; font:inherit; font-size:15px; outline:none;} .ed-pictorow .tbtn{flex:none;} .ed-pgrid{display:flex; gap:8px; flex-wrap:wrap; max-height:180px; overflow:auto;} .ed-pgrid button{ - border:2px solid #e3eaf3; background:#fff; border-radius:12px; width:74px; height:74px; + border:1px solid var(--line); background:var(--surface); border-radius:12px; width:74px; height:74px; cursor:pointer; padding:5px; } .ed-pgrid button:hover{border-color:var(--blue);} - .ed-pgrid button.sel{border-color:var(--yellow); background:#fff8e1;} + .ed-pgrid button.sel{border-color:var(--accent); background:var(--accent-soft);} .ed-pgrid img{width:100%; height:100%; object-fit:contain;} .ed-credit{font-size:11.5px; color:var(--muted); margin-top:8px; line-height:1.4;} .ed-credit a{color:var(--blue);} .ed-status{font-size:13.5px; font-weight:700; color:var(--muted); padding:6px 0;} - .ed-upload{background:#e8eef6; border-radius:10px; padding:11px 16px; font-weight:700; + .ed-upload{background:var(--surface-2); border-radius:10px; padding:11px 16px; font-weight:700; font-size:14px; cursor:pointer; display:inline-block;} .ed-upload input{display:none;} .ed-uphint{font-size:12.5px; color:var(--muted); margin-top:10px; line-height:1.45;} .lg-ed-list{display:flex; flex-direction:column; gap:6px;} .lg-ed-list .empty{color:var(--muted); font-weight:700; text-align:center; padding:18px 0;} - .ed-row{display:flex; align-items:center; gap:12px; background:#f7fafd; border-radius:12px; padding:7px 12px;} + .ed-row{display:flex; align-items:center; gap:12px; background:var(--surface-2); border-radius:12px; padding:7px 12px;} .ed-row .ep{width:40px; height:40px; font-size:28px; display:flex; align-items:center; justify-content:center;} .ed-row .ep img{width:100%; height:100%; object-fit:contain; border-radius:8px;} .ed-row .ew{font-weight:800; font-size:17px; letter-spacing:2px; flex:1;} - .ed-row .edel{border:none; background:#fbe3e1; color:var(--red); border-radius:8px; + .ed-row .edel{border:none; background:var(--red-soft); color:var(--red); border-radius:8px; width:30px; height:30px; cursor:pointer; font-weight:900;} .ed-row .edel:hover{background:var(--red); color:#fff;} .ed-row.base{opacity:.65;} @@ -683,15 +741,15 @@ .wp{flex:1; min-height:0; display:flex; flex-direction:column;} .wp-bar{ display:flex; gap:10px; padding:8px 10px; flex-wrap:wrap; align-items:center; - flex:none; background:#f7fafd; border-bottom:1px solid #e3eaf3; + flex:none; background:var(--surface-2); border-bottom:1px solid var(--line); } - .wp-group{display:flex; gap:4px; align-items:center; background:#e8eef6; border-radius:10px; padding:3px;} + .wp-group{display:flex; gap:4px; align-items:center; background:var(--surface-2); border-radius:10px; padding:3px;} .wp-group button{ border:none; background:transparent; border-radius:8px; width:32px; height:32px; cursor:pointer; font-size:16px; line-height:1; padding:0; display:flex; align-items:center; justify-content:center; } - .wp-group button.on{background:#fff; box-shadow:0 1px 4px rgba(30,50,90,.2);} + .wp-group button.on{background:var(--surface); box-shadow:0 1px 4px rgba(30,50,90,.2);} .wp-color{border-radius:50% !important; position:relative;} .wp-color i{width:18px; height:18px; border-radius:50%; display:block;} .wp-color.on{outline:2.5px solid var(--ink); outline-offset:-3px;} @@ -707,10 +765,10 @@ .wp-bg[data-bg=write] i{background-image:repeating-linear-gradient(#0000 0 2px, #c3d5ec 2px 3px, #0000 3px 5px, #6d92c4 5px 6px);} .wp-bg[data-bg=grid-s] i{background-image:repeating-linear-gradient(#0000 0 4px, #9db6d8 4px 5px),repeating-linear-gradient(90deg,#0000 0 4px, #9db6d8 4px 5px);} .wp-bg[data-bg=grid-b] i{background-image:repeating-linear-gradient(#0000 0 8px, #9db6d8 8px 9px),repeating-linear-gradient(90deg,#0000 0 8px, #9db6d8 8px 9px);} - .wp-clear{border:none; background:#fbe3e1; color:var(--red); border-radius:10px; + .wp-clear{border:none; background:var(--red-soft); color:var(--red); border-radius:10px; width:34px; height:34px; cursor:pointer; font-size:15px; margin-left:auto;} .wp-clear:hover{background:var(--red); color:#fff;} - .wp-stage{flex:1; min-height:0; position:relative; background:#fff;} + .wp-stage{flex:1; min-height:0; position:relative; background:var(--surface);} .wp-stage canvas{position:absolute; inset:0; touch-action:none; cursor:crosshair;} .wp-stage.t-text canvas{cursor:text;} .wp-text-input{ @@ -732,10 +790,10 @@ .media{flex:1; min-height:0; display:flex; flex-direction:column;} .media-bar{ display:flex; gap:8px; padding:8px 10px; flex:none; - background:#f7fafd; border-bottom:1px solid #e3eaf3; + background:var(--surface-2); border-bottom:1px solid var(--line); } .media-bar input{ - flex:1; min-width:0; border:2px solid #cdd9e8; border-radius:10px; + flex:1; min-width:0; border:1px solid var(--line); border-radius:10px; padding:8px 10px; font:inherit; font-size:14px; outline:none; } .media-bar input:focus{border-color:var(--blue);} @@ -761,13 +819,13 @@ .mt-score{margin-left:auto; font-size:13.5px; font-weight:700; color:var(--muted); white-space:nowrap;} .mt-card{ flex:1; min-height:0; display:flex; flex-direction:column; align-items:center; - justify-content:center; gap:12px; background:linear-gradient(#fff,#f6fafe); - border:2px solid #e3eaf3; border-radius:18px; position:relative; padding:10px; overflow:hidden; + justify-content:center; gap:12px; background:var(--surface); + border:1px solid var(--line); border-radius:18px; position:relative; padding:10px; overflow:hidden; } .mt-q{font-size:40px; font-weight:900; letter-spacing:1px; text-align:center;} .mt-a{ min-width:110px; height:56px; border-radius:14px; border:2.5px dashed #b9c7d9; - background:#eef3f9; font-size:32px; font-weight:900; display:flex; align-items:center; + background:var(--surface-2); font-size:32px; font-weight:900; display:flex; align-items:center; justify-content:center; color:var(--blue); padding:0 16px; } .mt-a.ok{border-style:solid; border-color:var(--green); background:#e3f6ea; color:var(--green);} @@ -776,10 +834,10 @@ .mt-fb.ans{color:var(--red);} .mt-pad{display:grid; grid-template-columns:repeat(4,1fr); gap:8px; flex:none;} .mt-pad button{ - border:none; border-radius:12px; background:#e8eef6; font:inherit; font-weight:900; + border:none; border-radius:12px; background:var(--surface-2); font:inherit; font-weight:900; font-size:22px; padding:12px 0; cursor:pointer; color:var(--ink); } - .mt-pad button:hover{background:#dbe5f1;} + .mt-pad button:hover{background:var(--surface-3);} .mt-pad .ok{background:var(--green); color:#fff;} .mt-done{ position:absolute; inset:0; border-radius:18px; display:none; flex-direction:column; @@ -795,38 +853,44 @@ color:#fff; font:inherit; font-weight:800; font-size:15px; cursor:pointer; margin-top:6px; } /* =========== high-contrast accessibility mode =========== */ - body.hc{--bg:#fff; --ink:#000; --muted:#2b2b2b; --blue:#0047ab; --red:#c40000; - --green:#006b2d; --yellow:#ffd400; --wood:#ffe9b0; --wood-d:#8a6a00;} + /* wint óók van body.dark: hoog contrast is altijd zwart-op-wit */ + body.hc,body.dark.hc{ + --bg:#fff; --ink:#000; --muted:#2b2b2b; --blue:#0047ab; --red:#c40000; + --green:#006b2d; --yellow:#ffd400; --wood:#ffe9b0; --wood-d:#8a6a00; + --surface:#fff; --surface-2:#f2f2f2; --surface-3:#e2e2e2; --line:#000; + --accent:#0047ab; --accent-ink:#00306f; --accent-soft:#d6e4ff; + --red-soft:#ffd9d6; + --glass:#fff; --glass-strong:#fff; --glass-line:#000; + } body.hc #board.bg-dots{background-image:radial-gradient(circle,#7d8ea3 1.7px,transparent 1.7px);} - body.hc .widget{background:#fff; border:2.5px solid #000; box-shadow:0 4px 14px rgba(0,0,0,.35); backdrop-filter:none;} - body.hc .widget:hover,.body.hc .widget:focus-within{background:#fff;} + body.hc .widget{background:var(--surface); border:2.5px solid #000; box-shadow:0 4px 14px rgba(0,0,0,.35); backdrop-filter:none;} + body.hc .widget:hover,.body.hc .widget:focus-within{background:var(--surface);} body.hc .widget .wmin,body.hc .widget .wclose{opacity:1;} body.hc .widget-rs{opacity:1; border:3px solid #000;} body.hc .widget-head{background:#f2f2f2; border-bottom:2px solid #000;} - body.hc .slot{border-color:#000; background:#fff;} + body.hc .slot{border-color:#000; background:var(--surface);} body.hc .slot .ghost{color:#666;} body.hc .slot .dots i.on{background:#333;} body.hc .blok .dots i.on{background:#6a4a00;} - body.hc .lg-instr{background:#fff; border-color:#000; color:#000;} - body.hc #hud,body.hc .dock-item,body.hc .fab-item,body.hc #penbar .wp-group{border:2px solid #000; background:#fff;} + body.hc .lg-instr{background:var(--surface); border-color:#000; color:#000;} + body.hc #hud,body.hc .dock-item,body.hc .fab-item,body.hc #penbar .wp-group{border:2px solid #000; background:var(--surface);} body.hc #fab{background:#0047ab;} body.hc :focus-visible{outline:3px solid #0047ab; outline-offset:2px;} body.hc .mm-node{box-shadow:0 3px 10px rgba(0,0,0,.4); border-width:3px;} - #btnHC.on{background:var(--yellow); color:#000;} /* high contrast inside every widget */ - body.hc .lg-levels,body.hc .tseg{background:#fff; border:2px solid #000; border-radius:12px;} + body.hc .lg-levels,body.hc .tseg{background:var(--surface); border:2px solid #000; border-radius:12px;} body.hc .lg-levels button,body.hc .tseg button{color:#000;} body.hc .lg-levels button.active{background:#006b2d; color:#fff;} body.hc .lg-cards button,body.hc .lg-num,body.hc .fl-sel,body.hc .lg-snd,body.hc .lg-mode{ - border-color:#000; color:#000; background:#fff; + border-color:#000; color:#000; background:var(--surface); } body.hc .lg-cards button.active{background:#ffd400; border-color:#000; color:#000;} - body.hc .lg-tray{background:#fff; border:2px dashed #000;} - body.hc .lg-card,body.hc .mt-card{background:#fff; border-color:#000;} + body.hc .lg-tray{background:var(--surface); border:2px dashed #000;} + body.hc .lg-card,body.hc .mt-card{background:var(--surface); border-color:#000;} body.hc .lg-progress,body.hc .mt-score,body.hc .mm-hint,body.hc .dc-sum{color:#000;} body.hc .lg-stars{color:#7a5d00;} - body.hc .mt-a{border-color:#000; background:#fff;} - body.hc .mt-pad button{background:#fff; border:2px solid #000; color:#000;} + body.hc .mt-a{border-color:#000; background:var(--surface);} + body.hc .mt-pad button{background:var(--surface); border:2px solid #000; color:#000;} body.hc .mt-pad .ok{background:#006b2d; border-color:#006b2d; color:#fff;} body.hc .mt-fb{color:#006b2d;} body.hc .mt-fb.ans{color:#c40000;} @@ -838,17 +902,17 @@ body.hc .np-result{background:#0047ab;} body.hc .np-row label,body.hc .thint,body.hc .guestnote,body.hc .ed-credit, body.hc .bp-hint,body.hc .gcard .gd,body.hc .st-footer{color:#222;} - body.hc .gcard{border-color:#000; background:#fff;} + body.hc .gcard{border-color:#000; background:var(--surface);} body.hc .gcat-title{color:#000;} - body.hc .tbtn.ghost{background:#fff; border:2px solid #000; color:#000;} - body.hc .wmin,body.hc .wclose{border:1.5px solid #000; background:#fff;} + body.hc .tbtn.ghost{background:var(--surface); border:2px solid #000; color:#000;} + body.hc .wmin,body.hc .wclose{border:1.5px solid #000; background:var(--surface);} body.hc .wclose{color:#c40000;} body.hc .wz.on,body.hc #zoomPct.on{background:#ffd400; color:#000;} - body.hc .ed-tabs button,body.hc .ed-cats button{color:#000; background:#fff; border:1.5px solid #000;} + body.hc .ed-tabs button,body.hc .ed-cats button{color:#000; background:var(--surface); border:1.5px solid #000;} body.hc .ed-tabs button.active,body.hc .ed-cats button.active{background:#ffd400;} - body.hc .ed-pane{border-color:#000; background:#fff;} + body.hc .ed-pane{border-color:#000; background:var(--surface);} body.hc .timer .presets button,body.hc .timer .main button,body.hc .ticon, - body.hc .hud-btn,body.hc .mm-seg button{background:#fff; border:1.5px solid #000; color:#000;} + body.hc .hud-btn,body.hc .mm-seg button{background:var(--surface); border:1.5px solid #000; color:#000;} body.hc .timer .main .bstart{background:#006b2d; border-color:#006b2d; color:#fff;} body.hc .bp-board{border-color:#000; color:#000;} body.hc .bp-board.active{background:#ffd400;} @@ -860,8 +924,8 @@ .fl-pic{font-size:46px; min-height:56px; display:flex; align-items:center;} .fl-pic img{width:56px; height:56px; object-fit:contain;} .fl-sel{ - border:2px solid #e3eaf3; border-radius:10px; height:34px; font:inherit; - font-weight:800; font-size:13px; color:var(--muted); background:#fff; + border:1px solid var(--line); border-radius:10px; height:34px; font:inherit; + font-weight:800; font-size:13px; color:var(--muted); background:var(--surface); padding:0 6px; outline:none; cursor:pointer; } /* =========== Chop & blend widget =========== */ @@ -882,9 +946,9 @@ .an{flex:1; min-height:0; display:flex; flex-direction:column;} .an-hint{ flex:none; font-size:11.5px; font-weight:700; color:var(--muted); - padding:6px 10px; background:#f7fafd; border-bottom:1px solid #e3eaf3; + padding:6px 10px; background:var(--surface-2); border-bottom:1px solid var(--line); } - .an-stage{flex:1; min-height:0; position:relative; overflow:hidden; background:#fff; cursor:grab; touch-action:none;} + .an-stage{flex:1; min-height:0; position:relative; overflow:hidden; background:var(--surface); cursor:grab; touch-action:none;} .an-stage:active{cursor:grabbing;} .an-layer{position:absolute; inset:0;} .an-cell{ @@ -893,7 +957,7 @@ color:var(--ink); padding:2px 8px; overflow:hidden; text-align:center; cursor:pointer; } .an-cell:hover{border-color:#b6c6dc;} - .an-cell.filled{border-style:solid; border-color:#cdd7e4; background:#fff; box-shadow:0 3px 8px rgba(30,50,90,.12);} + .an-cell.filled{border-style:solid; border-color:#cdd7e4; background:var(--surface); box-shadow:0 3px 8px rgba(30,50,90,.12);} .an-cell.root{border:2.5px solid #d9a400; background:#fff8dd;} .an-cell.root.filled{background:var(--yellow); font-size:16px;} .an-cell input{width:100%; border:none; outline:none; font:inherit; text-align:center; background:transparent;} @@ -921,7 +985,7 @@ .dc{flex:1; min-height:0; display:flex; flex-direction:column; gap:10px; padding:12px; align-items:center;} .dc-row{flex:1; display:flex; gap:14px; align-items:center; justify-content:center; flex-wrap:wrap; cursor:pointer;} .die{ - width:92px; height:92px; background:#fff; border:3.5px solid var(--ink); border-radius:18px; + width:92px; height:92px; background:var(--surface); border:3.5px solid var(--ink); border-radius:18px; display:grid; grid-template-columns:repeat(3,1fr); grid-template-rows:repeat(3,1fr); padding:10px; box-shadow:0 5px 0 rgba(0,0,0,.15); } @@ -945,7 +1009,7 @@ /* =========== Name picker widget =========== */ .np{flex:1; min-height:0; display:flex; flex-direction:column; gap:10px; padding:12px;} .np textarea{ - flex:1; min-height:0; border:2px solid #cdd9e8; border-radius:12px; padding:10px; + flex:1; min-height:0; border:1px solid var(--line); border-radius:12px; padding:10px; font:inherit; font-size:14.5px; resize:none; outline:none; } .np-result{ @@ -970,12 +1034,12 @@ align-items:center; justify-content:center; gap:8px; } .topts{display:flex; justify-content:space-between; align-items:center; width:100%; flex:none;} - .tseg{display:flex; background:#e8eef6; border-radius:10px; overflow:hidden;} - .tseg button{border:none; background:transparent; padding:7px 13px; font-size:15px; cursor:pointer; line-height:1;} - .tseg button.on{background:var(--blue); color:#fff;} - .mm-seg button{font:inherit; font-weight:800; font-size:13px;} - .ticon{border:none; background:#e8eef6; border-radius:10px; padding:7px 11px; font-size:15px; cursor:pointer; line-height:1;} - .ticon.on{background:var(--yellow);} + .tseg{display:flex; background:var(--surface-2); border-radius:999px; padding:3px; gap:2px;} + .tseg button{border:none; border-radius:999px; background:transparent; padding:6px 12px; font-size:15px; cursor:pointer; line-height:1; color:var(--muted);} + .tseg button.on{background:var(--surface); color:var(--ink); box-shadow:var(--shadow-1);} + .mm-seg button{font:inherit; font-weight:700; font-size:13px;} + .ticon{border:none; background:var(--surface-2); border-radius:var(--radius); padding:7px 11px; font-size:15px; cursor:pointer; line-height:1;} + .ticon.on{background:var(--accent-soft); color:var(--accent-ink);} .timer .tpie{ flex:1 1 0; min-height:80px; aspect-ratio:1/1; width:auto; max-width:100%; max-height:220px; display:none; cursor:grab; touch-action:none; @@ -990,13 +1054,13 @@ .timer .trow{display:flex; gap:8px; flex-wrap:wrap; justify-content:center; flex:none;} .thint{flex:none;} .timer .presets button{ - border:none; border-radius:999px; padding:6px 13px; background:#e8eef6; font:inherit; + border:none; border-radius:999px; padding:6px 13px; background:var(--surface-2); font:inherit; font-weight:800; font-size:12.5px; color:var(--muted); cursor:pointer; } - .timer .presets button:hover{background:#dbe5f1; color:var(--ink);} + .timer .presets button:hover{background:var(--surface-3); color:var(--ink);} .timer .main button{ border:none; border-radius:12px; padding:10px 26px; font:inherit; font-weight:800; - font-size:15.5px; cursor:pointer; background:#e8eef6; color:var(--ink); + font-size:15.5px; cursor:pointer; background:var(--surface-2); color:var(--ink); } .timer .main .bstart{background:var(--green); color:#fff; min-width:110px;} .thint{font-size:11.5px; color:var(--muted); text-align:center; line-height:1.4;} @@ -1005,80 +1069,90 @@ /* ---------- login-extra's (school, koppelcode) ---------- */ #liSchool{ - width:100%; border:2px solid #cdd9e8; border-radius:12px; padding:11px 12px; - font:inherit; font-size:15px; outline:none; margin-bottom:10px; background:#fff; + width:100%; border:1px solid var(--line); border-radius:var(--radius); + height:var(--control-h); padding:0 12px; color:var(--ink); + font:inherit; font-size:15px; outline:none; margin-bottom:10px; background:var(--surface); } .lisub{font-size:13px; font-weight:700; color:var(--muted); margin-bottom:8px;} #ownPwBlock .lrow{margin-bottom:10px;} -#ownPwBlock input{ - flex:1; min-width:0; border:2px solid #cdd9e8; border-radius:12px; - padding:10px 12px; font:inherit; font-size:15px; outline:none; +#ownPwBlock input{flex:1; min-width:0;} +/* ---------- weergave-instellingen (tabblad "Weergave") ---------- */ +.vw-row{ + display:flex; align-items:center; justify-content:space-between; gap:12px; + min-height:var(--control-h); padding:7px 0; border-bottom:1px solid var(--line); } -/* ---------- beheerpaneel (tabblad "Beheer" binnen Instellingen) ---------- */ +.vw-row:last-of-type{border-bottom:none;} +.vw-lbl{font-weight:700; font-size:14.5px;} +.seg{display:flex; background:var(--surface-2); border-radius:999px; padding:3px; gap:2px; flex:none;} +.seg button{ + border:none; border-radius:999px; padding:6px 13px; font:inherit; font-weight:700; + cursor:pointer; background:transparent; color:var(--muted); font-size:13.5px; +} +.seg button.active{background:var(--surface); color:var(--ink); box-shadow:var(--shadow-1);} +/* ---------- beheerpaneel (tabblad "Beheer" binnen Instellingen) ---------- + alle velden/knoppen in een rij zijn even hoog: var(--control-h) */ .am-head{display:flex; align-items:center; justify-content:space-between; margin-bottom:8px;} .am-head h2{margin:0; font-size:20px;} .am-h3{margin:14px 0 6px; font-size:14px; color:var(--muted); text-transform:uppercase; letter-spacing:.5px;} .am-msg{ - min-height:20px; font-size:13.5px; font-weight:800; color:var(--green); margin:4px 0; + min-height:20px; font-size:13.5px; font-weight:700; color:var(--green); margin:4px 0; display:flex; align-items:center; gap:8px; flex-wrap:wrap; } .am-add{display:flex; gap:8px; align-items:center; flex-wrap:wrap; margin:8px 0;} -.am-inp,.am-sel{ - border:2px solid #cdd9e8; border-radius:10px; padding:8px 10px; font:inherit; - font-size:14px; outline:none; background:#fff; min-width:0; +.am-inp,.am-sel,.am-pw{ + border:1px solid var(--line); border-radius:var(--radius); height:var(--control-h); + padding:0 11px; font:inherit; font-size:14px; outline:none; + background:var(--surface); color:var(--ink); min-width:0; } +.am-inp:focus,.am-sel:focus,.am-pw:focus{border-color:var(--accent);} +/* de generieke settings-input-regel (width:100%/marge) geldt niet in het beheerpaneel: + daar bepalen de am-*-regels de maat, zodat alles in een rij gelijk uitlijnt */ +#settingsModal #adminModal input{margin-bottom:0;} .am-inp{flex:1; min-width:140px;} +.am-pw{width:120px;} .am-list{display:flex; flex-direction:column; gap:5px;} -.am-group{font-weight:900; font-size:13px; margin-top:10px; color:var(--ink);} +.am-group{font-weight:700; font-size:13px; margin-top:10px; color:var(--muted); text-transform:uppercase; letter-spacing:.4px;} .am-row{ - display:flex; gap:8px; align-items:center; background:#f7fafd; - border-radius:10px; padding:6px 10px; flex-wrap:wrap; + display:flex; gap:8px; align-items:center; background:var(--surface-2); + border-radius:var(--radius); padding:7px 10px; flex-wrap:wrap; } -.am-name{font-weight:800; font-size:14px; flex:1; min-width:120px;} +.am-name{font-weight:700; font-size:14px; flex:1; min-width:120px;} .am-role{font-size:12px; font-weight:700; color:var(--muted);} -.am-pw{ - border:2px solid #cdd9e8; border-radius:8px; padding:5px 8px; font:inherit; - font-size:13px; width:110px; outline:none; -} -.am-code{font-size:12.5px; font-weight:800; color:var(--orange);} +.am-code{font-size:12.5px; font-weight:700; color:var(--orange);} .am-actions{display:flex; align-items:center; gap:8px; flex-wrap:wrap;} -.am-btn{ - border:none; background:#e8eef6; border-radius:8px; padding:6px 10px; - font:inherit; font-weight:800; font-size:12px; cursor:pointer; color:var(--ink); +.am-btn,.am-copy{ + background:var(--surface); border-radius:var(--radius); + height:var(--control-h); padding:0 12px; border:1px solid var(--line); + font:inherit; font-weight:700; font-size:12.5px; cursor:pointer; color:var(--ink); line-height:1; } -.am-btn:hover{background:#dbe5f1;} +.am-btn:hover,.am-copy:hover{background:var(--surface-3);} .am-del{ - border:none; background:#fbe3e1; border-radius:8px; width:28px; height:28px; - cursor:pointer; font-size:13px; + border:1px solid var(--line); background:var(--red-soft); border-radius:var(--radius); + width:var(--control-h); height:var(--control-h); cursor:pointer; font-size:13px; flex:none; } .am-del:hover{background:var(--red);} -.am-classes{display:flex; gap:6px; flex-wrap:wrap;} +.am-classes{display:flex; gap:6px; flex-wrap:wrap; align-items:center;} .am-chip{ - display:inline-flex; gap:6px; align-items:center; background:#fff; - border:2px solid #e3eaf3; border-radius:999px; padding:5px 12px; - font-weight:800; font-size:13px; + display:inline-flex; gap:6px; align-items:center; background:var(--surface); + border:1px solid var(--line); border-radius:999px; padding:5px 12px; + font-weight:700; font-size:13px; } button.am-chip{cursor:pointer; color:var(--muted);} -button.am-chip.on{border-color:var(--blue); background:#eaf1fc; color:var(--blue-d);} +button.am-chip.on{border-color:var(--accent); background:var(--accent-soft); color:var(--accent-ink);} .am-chipx{border:none; background:transparent; color:var(--red); font-weight:900; cursor:pointer; padding:0; font-size:11px;} -.am-copy{ - border:none; background:#e8eef6; border-radius:8px; padding:5px 8px; - font:inherit; font-size:13px; cursor:pointer; color:var(--ink); line-height:1; -} -.am-copy:hover{background:#dbe5f1;} .am-reset{ - background:#f7fafd; border:2px solid #cdd9e8; border-radius:12px; + background:var(--surface-2); border:1px solid var(--line); border-radius:12px; padding:10px 12px; margin:6px 0; display:flex; flex-direction:column; gap:8px; } .am-reset-head{display:flex; align-items:center; justify-content:space-between; gap:8px;} .am-reset-list{display:flex; flex-direction:column; gap:5px; max-height:260px; overflow:auto;} .am-reset-row{ - display:flex; gap:8px; align-items:center; background:#fff; + display:flex; gap:8px; align-items:center; background:var(--surface); border-radius:8px; padding:5px 8px; flex-wrap:wrap; } .am-reset-pw{font-weight:800; font-family:monospace; font-size:13px; color:var(--green);} -body.hc .am-row,body.hc .am-chip{border:1.5px solid #000; background:#fff;} -body.hc .am-reset,body.hc .am-reset-row{border:1.5px solid #000; background:#fff;} +body.hc .am-row,body.hc .am-chip{border:1.5px solid #000; background:var(--surface);} +body.hc .am-reset,body.hc .am-reset-row{border:1.5px solid #000; background:var(--surface);} /* ============================================================ Mobiel & tablet: responsieve aanpassingen. Alles hieronder is @@ -1095,10 +1169,10 @@ body.hc .am-reset,body.hc .am-reset-row{border:1.5px solid #000; background:#fff /* ---------- telefoon (≤600px) ---------- */ @media (max-width:600px){ #toolbar{padding:0 8px; gap:6px;} - .logo{font-size:22px;} - .logo .crayon{font-size:18px; margin-left:4px;} - .tbtn{padding:8px 10px; font-size:13px;} - #boardsPanel{top:60px; max-height:min(66vh,480px);} + /* alleen de uil op kleine schermen, woordmerk verdwijnt */ + .logo-word{display:none;} + .tbtn{padding:0 10px; font-size:13px;} + #boardsPanel{top:calc(var(--tbar) + 2px); max-height:min(66vh,480px);} /* beheerpaneel: dichte rijen worden gestapeld i.p.v. verdrukt */ .am-row{flex-direction:column; align-items:stretch;} @@ -1110,16 +1184,84 @@ body.hc .am-reset,body.hc .am-reset-row{border:1.5px solid #000; background:#fff /* ---------- aanraakschermen (los van breedte) ---------- */ @media (pointer:coarse){ - .tbtn{min-height:var(--tap-sm);} - #langToggle button{min-height:var(--tap-sm);} + /* alle controls (ook invoervelden) groeien mee naar tikformaat */ + :root{--control-h:44px;} .hud-btn{width:var(--tap-sm); height:var(--tap-sm); font-size:15px;} #penbar .wp-group button{width:var(--tap-sm); height:var(--tap-sm);} #hud.vert{width:104px;} #hud.vert #penbar .wp-group{grid-template-columns:repeat(2,36px);} - .am-btn,.am-copy{min-height:var(--tap-sm); padding:8px 12px;} - .am-del{width:var(--tap-sm); height:var(--tap-sm);} .am-chip{padding:7px 14px;} .am-chipx{padding:4px;} /* geen hover op aanraakschermen: de greep moet altijd zichtbaar zijn */ .widget-rs{opacity:.7; width:38px; height:38px;} } + +/* ============================================================ + Menubalk-positie: links of rechts (Weergave-instelling). + De balk wordt een verticale kolom; bord en zwevende elementen + schuiven mee via dezelfde body-class. + ============================================================ */ +body.tb-left #toolbar,body.tb-right #toolbar{ + top:0; bottom:0; width:var(--tbar); height:auto; + flex-direction:column; padding:12px 0; gap:10px; + overflow-y:auto; overflow-x:hidden; +} +body.tb-left #toolbar{left:0; right:auto; border-right:1px solid var(--line); border-bottom:none;} +body.tb-right #toolbar{right:0; left:auto; border-left:1px solid var(--line); border-bottom:none;} +body.tb-left .logo-word,body.tb-right .logo-word, +body.tb-left #verTag,body.tb-right #verTag, +body.tb-left #btnSave span,body.tb-right #btnSave span, +body.tb-left #userLbl,body.tb-right #userLbl{display:none;} +body.tb-left #toolbar .tbtn,body.tb-right #toolbar .tbtn{padding:0; width:var(--control-h); min-width:0; flex:none;} +body.tb-left #btnSave,body.tb-right #btnSave{min-width:0;} +body.tb-left #zoomPct,body.tb-right #zoomPct{min-width:0; font-size:11.5px;} +body.tb-left #board,body.tb-left #pupilView{inset:0 0 0 var(--tbar);} +body.tb-right #board,body.tb-right #pupilView{inset:0 var(--tbar) 0 0;} +body.tb-right #fab{right:calc(var(--tbar) + 16px);} +body.tb-right #fabBoardsBtn{right:calc(var(--tbar) + 88px);} +body.tb-right #boardStrip,body.tb-right #boardsPanel{right:calc(var(--tbar) + 12px);} +body.tb-left #boardsPanel,body.tb-right #boardsPanel{top:12px;} +body.tb-left #fabmenu{right:24px;} +body.tb-right #fabmenu{right:calc(var(--tbar) + 16px);} + +/* ============================================================ + Weergave-instelling "glas-effect uit": ondoorzichtige panelen + i.p.v. blur - rustiger en lichter voor oudere digiborden. + ============================================================ */ +body.no-glass .widget,body.no-glass #hud,body.no-glass .fab-item, +body.no-glass #boardStrip,body.no-glass #boardsPanel,body.no-glass .mm-top, +body.no-glass .widget.bare .widget-head{ + backdrop-filter:none; -webkit-backdrop-filter:none; + background:var(--surface); +} +body.no-glass .widget-head{background:var(--surface-2);} + +/* ============================================================ + Donker thema: bord-achtergrondpatronen en glas-laag. + (De chrome-laag volgt automatisch via de tokens in body.dark.) + ============================================================ */ +body.dark #board.bg-dots{background-image:radial-gradient(circle,#2c3a5e 1.4px,transparent 1.4px);} +body.dark #board.bg-lines{background-image:repeating-linear-gradient(#0000 0 39px,#2c3a5e 39px 40px);} +body.dark #board.bg-write{background-image:repeating-linear-gradient( + #0000 0 19px,#243052 19px 20px,#0000 20px 39px,#3a4a70 39px 40.5px,#0000 40.5px 59px,#243052 59px 60px,#0000 60px 79px);} +body.dark #board.bg-grid-s{background-image: + repeating-linear-gradient(#0000 0 24px,#243052 24px 25px), + repeating-linear-gradient(90deg,#0000 0 24px,#243052 24px 25px);} +body.dark #board.bg-grid-b{background-image: + repeating-linear-gradient(#0000 0 49px,#2c3a5e 49px 50px), + repeating-linear-gradient(90deg,#0000 0 49px,#2c3a5e 49px 50px);} +body.dark .widget{background:var(--glass); border-color:var(--glass-line);} +body.dark .widget:hover,body.dark .widget:focus-within{background:var(--glass-strong); border-color:rgba(255,255,255,.14);} +body.dark .widget-head{background:rgba(255,255,255,.04); border-bottom-color:rgba(255,255,255,.08);} +body.dark #hud{background:var(--glass); border-color:var(--glass-line);} +body.dark .fab-item{background:var(--glass-strong); color:var(--ink);} +body.dark .fab-item:hover{background:var(--surface-3);} +body.dark #boardStrip,body.dark #boardsPanel{background:var(--glass-strong); border-color:var(--glass-line);} +body.dark .widget.bare .widget-head{background:var(--glass-strong);} +body.dark .mm-top{background:var(--glass-strong);} +body.dark .mm-pop{background:var(--surface); box-shadow:var(--shadow-2);} +body.dark .dock-item{background:var(--surface-2); color:var(--ink);} +body.dark .dock-item:hover{background:var(--surface-3);} +body.dark .wp-group button.on{background:var(--surface-3); box-shadow:none;} +body.dark .lg-kbd button,body.dark .blok{filter:saturate(.9) brightness(.96);} +body.dark .bs-card canvas{background:#fff;} /* bord-preview blijft de echte (witte) bordkleur tonen */ diff --git a/public/fonts/LICENSE-Quicksand.txt b/public/fonts/LICENSE-Quicksand.txt new file mode 100644 index 0000000..2c90211 --- /dev/null +++ b/public/fonts/LICENSE-Quicksand.txt @@ -0,0 +1,4 @@ +Quicksand - ontworpen door Andrew Paglinawan e.a. +Gelicenseerd onder de SIL Open Font License 1.1 (https://openfontlicense.org). +Bron: Google Fonts (https://fonts.google.com/specimen/Quicksand). +Dit bestand (quicksand.woff2) is het latin-subset van de variabele font (gewichten 300-700). diff --git a/public/fonts/quicksand.woff2 b/public/fonts/quicksand.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..b29be8d0ef8caac5c9cdf359c600ae4aca081ef6 GIT binary patch literal 28244 zcmV(@K-Rx^Pew8T0RR910B%$O6951J0ONQ70Bz*}0RR9100000000000000000000 z0000Qf-oD>92|)(KS)+VQi~763r5w6ZlywI#7f203wsR<3=KcjROdXJed9e zf6me&Lj&p(ptV-({`mw&8^{VIt4a;ovskJVLXNy`Hm#DNCh`QV)o+nIjoEawY#zy)) zF8AYp%ji>t*Fg-AM|t%7ojKS|E(!;@~l|1Wn* zF4=^Tgya&E2w|)k8CwJgDr`#?HwwDjB2`?RxK{VV4qO`-+Kpo`Ky<^y^ZWa6?Q`Gz z)DYQ>lA9Wc5~eBsI7l-|jkv?pHvc(6z+j3=sDzS7-5nh59UL5RRM=qToKcH%oqzjT zwO_gYjIDY8`>|)g_P&VebV4^vnJ)GsL)JuyL^A#*Rq=j!;(yxj&b%bM%a5be<~VUOklCF_;1WA*DbC*)vK2k^e?f320TVc>dsU}=VT_W-C*$f!8oKL{!nArr-@Vq9E|>%p9wlnkZ%P*8*c z!0U)@%Zb~$oNhVb0oh;aD_aA^tYZ!g)n)%R*<|;D{DQ9V;X-Zlb>j`fg3)A?VGmoV zhN`7$1ps)i4F2P3ZU2tj-8b`gFYq{y=;Ksuq;0Yc%AyR6XsiY)D{%2g!mZU{1!8mz z&S__RyRp>Q=+y0RhmZpB7y<+1wD;wOxOGT8yi-GK?tVYaEwRvvX~db?zYkMu(BOIU z_Q$r#a3GoVZc14icHI>x3Dgo36jA;E*Y*2$cJ{l7pA{tFgLxK315=eW)x0F5XD;G- z!7NWKh*sjO=TSjR#iFRJ8bm8yz1TOg(x&a|WnKd&(R^j|DcF~iLP%96ed(*Ev%hSf zRwW1%j7k+2rQ2q9lH(|?%Ho+E_jUh6*G1zk&fyFwWcWW*({?_^l>kLhetd7%aaKC| z28xTyHP87vh1j}EuU{gF07&Wp26@2)r2&t$7EB)S$n%mHc}gS|k4hm_vkdm|bb1<| z_+%(kjxly2HJ#fs{y+%{5Fd3x3*P9*;*CtDH(H zC0n{CYeE&Ga5}|RU*+k#)Ubh!j%77YW458y|9fWh2KA@{(6|(~3^&P8lg2FVJhW@^xGJyPW>4Vu@7NBv&Za8c3_t8;mB*YIC&^ zUSA+cC)1hMw)U=EzMs%dCoGQ;1Ttg*0q{Hu(FtFsThtrBUulT@ zNbJUXf5T-j2GE68mhu7e>TGp+c~Y5RN*pbMM-Xk5Cz>dKJN3S{*evg=G)S&AK5iC_ znLWLZUB1NlXE|0s9#FgiM$@WV*WIOIyt{(eH}Qb}+Vq{}TAweMz=HLwY|XsOdD8Da zeQ)>D2V+m?z5U!C*@4==Yb}4f3TblZuC*=Yefr^Ay;V+=`^pj$f zeIzVWcr@K$KwI(V;2~+nSEeBtbE#wP0wmEw<9ZnpY2Q*?Ge#Bx-!`NPB zhdzgP&hgzbdd^u*Ykx4mcPob?02^e@IY&9j<*)rxN1p8xU_;6g3+(yO?wX%$YYW2{ znQMm0#vxDI>_(AC2ENq1Y-oJ@x>2S<+xpdd(Y>yeZm5pxDk-akPK#l5Bhs9#t!0B6 z<=Q9vK>TF3vJgBzD8K*$AOIf(2p)5?peVFc#4uWB*ZV^3VFmQ71?;fS60=P3n0wvo zh)H0B0b`Ko%iYBtmd(#NVT%QDBDgRhBhP`vIJyym3n{-Sg zkR8zpRE-w202Acs~FX0Diz15a|Y%S7<`-Gm7mX7bEdf~Uwd#*oc67hcvKGOmU{JmO0 zR^beb*+Vvcp*vN9ZhtK4!o7ZJy4klu`Vd~yy8CwDMg`fq*z#kk-fI!W9T2n`n0N!u z--8rsyx{vMFt>>7U`|#cW zt`)*BU^fHa>-o8SR~D6*2X-^k9Q++fyGQCOfA2REE{E+h1IB`6Yk<36 zyW$ai0MIj*W74+keyZv`d^g9{e*DO)v~gcN^xkr=Ns-8$kW-kope5es|L-c(LOg$d((KS?v`3e z*bVxhG7`+?j$6G^pVxBg2TFzkx_iGrNgvM5c9*nud~WjB@1Wi@e%0J=ZaF>zr)(o| zeL&>z`OC$DC_1hq%AAwBrIPLV?CDswTC#xsS3pMQ@6&GQ0m8_PLYNu8`4jb}9wzsf zv3-D7cON+22~qV3YVG*xlhwY2@oM+CsQQLAJv{Bjt zX#E%Nu~SX4&p>2?{YW^E+j!!KrH%-`&;&?zfqouY3p#m8-%D%WLV#H*-IAj}ZtmF+ zfs-d0a`s3GIO)}}{Lveq^#sTee~%nx{dVMvW=%hyW-Wa%zv;2bD{q1Bml(-bBaFfa zgz@e=8u4Jy{serF zepl9xs^hR!yg7NGsbnqJ!LYF&Hy?D7?fT+8|xjz+Y&MG^3(0J zc(xVP*{^I-*|rS1+3W;p%f_JDBTg;;eQ8RDJsee!94(!u4h?vu#ek9ML4&ewfVUVb zdw54@!e!0FGc4hJbN<6aTGU;iIC7uoIz_M7|6|9)hE0kaav`vX8Z*qo$vEX})=&ef z0MG`w0Qd*61@I%{bHIGS48V9mIUpC1g-F6Efxs^S7&G(qdA&-Ef4V3f>@(eY;E>fu zRgm4IALHE$JcL1Y-h89Vc~hQe=A83M_+*htxTfLcc-PKP=G0 zgY9=!?=*OUy|yo~z~R}xaizR=54yYq1l&Qx1JJF%R~UdrU}KT-V}QpZzt4bo2XW7; z_kb`6sGegfU3D^m2?6*oOMzInWxX4W?%8J4l&T{Ea0gMy-PvBYinOox0UKNPib65# z6!d5E=^>4$AvqaODICnBkY9GO;dnPa9E)HC8FX0PT^1@~48JeeB3FuuB-1l(fB0jt zj~5FIzr?9OvEhn^lpvTg#9cFo|Pw@f# zklB|pKIEp8bVw-0t$v)6wCN|+yKV!6m{Mi-PrM51v|O@z?s)|pW3z~=(?SQ^IMGgL zpudkP?WCrgMrA7J=G*p?HZ6&v)4D69{#S(cV_?bJabg|-1)~%S=lP5pX(@DGJ5`6R zp-2+?2UN9`baU3`{I<8{=d@sM2E#4GQC=qDl5t8DIu-O&@iRYbaFH8HgR)~b%K=jAV6sjL77e(^*3=r zDU~=)jlL))tl&?8s>v)AM9)v3w-1a?v`kqd9eiSvQXgvpfWN84Z<6uP?cgdTBtF?8!IN`{bm!qhfyUKlO#~J z-|Br+aB9S+K?8W`(xV~+t?>~BmB?v?We_EQQL&1eAR6||wef(isK`Z$UbOg$Q3EIB z=uaa9C^M#j4VoE9hF02QUO`k4uoo4FG8@E9zy_Uk(albz3}y&Dlxk>VP`;oAF;-R_ zyXBwyv^S>Z)3iy=+!~k0U*pS>HtME-`mEQwuZ>;R>W*)5yEmbRD$6Eqxsg-Zk`J>m z(}qV4OaJsqS_~1L#a!H4Nf$cf$m{=$h^68ZE<&U@J>?l~oGR63sWaPL^USxvLW?w5 zX`S^p*l3f@w%TTgU3S}}$v^(}pZ_)6@0jCmxaqdL9w6#~R@EN~89=fhB;sbmq35K4 zs^M7d%_owvQR|%=?U;eq1J#+)j4^j0|KRyEUOO!sa$Q1~AOj`aj3_0=hdBUpwCo>6 z!>jzX?ckG9WWN2UYe1=S*}568K}a3v<9cPg&9K~Yvudv8k?LtuZ`=GHz;01wELHZ+ zLMzKwQ0P5X47uA&-?&ja15^9RRvX5K4k~NMS6Fml>vcf`AY}vjHL{AJPT1MkW;E!4 zb~~vat@rgya~-Ra*&_I~*aB_fDp@&5R2L+ZSL76``tRssWLF(;NBOn$U8UR6ZR5`M z;Q`L9XQ-HHh&KB=8?cy%Pgak*2ogXM(cIkiHLdp6sR8lJ;b2dY;06GA0rd6`4xpo4Ar_ZPPxtd09)g&+j=>G35um=pO%%)NFL$>8V>ZfuX8%vhswx^$Alm<`}SKp4q zS;Qn}u>`6twP3nx=?5`EdRD0lFP~^W$6CCsV6VsK+Pk-EyE@PxM^o@nj+D@6gnF7jIVZN}uu&l7OFlX3t0qIgg0;~rks~VoS zbP`;o(`xW zPYvaiQAsIGS%x12e-(O_v=a_jM@?$(%4S`JBX=h3%bI3Y8JW^p!p0+49Jt1FO;&x} zDcNdV{l2VV0uw!@nW!=|Pz9!S6vYvWu`s1u>yy_+t7;2?~#1`4_ z0JN=DOclo)-K5HFBMw&*s-~E1MD;@0qn!eFlp!z>P*E2a8CZalG$x%9hk*44T~&g+ z**?9APAh`+KZkagi)NNSzZjw zsveCe)7gBnT&*|Ty?qe4MVk&?dh{7EWW<;WQ)bLruw=!W4O@2XIq-v@{Ngu%_{%>e zWE501bPP-^Y#dxXd;&ruViHm^atcZ+Y8o?w!xM-kGKET`Gngzkhs)y&gd(v-Dw8Xe zDz!$d(;JK?v&Cw&JDe`J$LsS4f}wCE8jB~AsdOfr%NL5Ja-~|UH=3<>r`zifhNJOh zI-4(+tMz8P+aFF&&(1F{udZ)y?~eBmk5A7puW#=kpI_fUzkmN}Q7_;nyn@&8208?g z07)PjNCBh>QUX#6QU+2EQUOv4QUy{CQUg*8Qis$dK!+dzW#|zEfR68*#A?V-u{kFy zx5idYJv48-fqyhw<(U+}b)Kc^%}eAA8b9-bFbjX zL@1Mr3XT*<#Z)=4j>B3#lTLwwOt9k!MiS=fr4G0k3Fi0)i?Z;`*g&sPD1#UZDtYRp zOHePzFnzrzs~ue}ukz4#OYj1a8DQ*Iex_36OeA#Oxtm;1KB-b<0Ayff@Q#HzKeaK! zcb0?}8Y@gDW^g+5Bs`RZhTn|l${Z??E=f1kd!pwGl~{3%=IN}rIkUpZQ6b!1-E~oY z@&ys2>dc{sv`I9lH5>6GH5-;BTOcgZ!z~5$uCJRc=8cXdwNPQJ9N|ZSxl!z<>i)3x z!*(1bHxhjY!aMxxs<0+TVai|*TsZ7jcFQ`(824LV{T z2H?$zH}RY3^+U-4Ucd4i`m|qY zp>O+FYaOx0Wi5_7s>xoP-LTRQ4YpckwR`TkYrSL0h?3G2w6ReD>v-NN4ng~eixeeV zOk#eqcnK0E`^z?edt^_5lu^Fx_RveNJo&10JPcMa!gtDOWB%WbH$jz2s=cqqKIi@E zf#0li(N&jRbHPa+UaED#Lpz-gi?ib*c8fCjNq+&Umx3#X9Z2*Aw{04Pkz6tiz0Fw8>%me@onpcB`AqH#TnzL82Rs=djE0(Yo8)$l9+CAl!K=Z)xF3^vlQX)kN zsj(4)H^MieV#v#A@V4ZFW*d(fT^cACcV*Eq1hfHRXlG2vKLabn^fp5b$`c(Ya*pz? z1x2+fh+&iv*#g5Ia7am{k}ohrVmqL0Eyozlf-Ym68&CE08Lm{Rnu#fydZPI-?pC$# zQocH-D9z9l2E!+|O)$i&St+*GB4890_h#ONk}crGBs7a4%#F0c3}Kr@`eHTzAyvll zlnBD*M$-&KQ3!-@W6QF56B7wxh%%u4GF zjLq}rr{iKigIRVPfVa7f>f(ToR8e`}xnF}Oc9UC|{qDR7&nHAS08sxjRMzYD0 zQr;M>8k-FuY>C%+O;$r*7S6y(yRrK1AUF*|`Pvkf!6-#C24OP$(|QT3JzX;*w}4TD zrB)YK#ZzowwMPg$s`9D?LilDL8BmMb+=uE?wfOM^BkZ9c)nm06m)FKI z(REh9NWvBXA*w3ZQq!Puog7=(Na6%wL>N{me|FHa^oEgaLT1kxBe824AwGr$oOG+> zPju%Won@h?MBiwI#j!pZbAS+q)euz*T{NuwVR8)ylNzH=Af2?ZO9rj_DgoUaeX=~~ z#0~*HPp?*i>DpIG8Cd*Hvf-&iSPj7{wsy)7Hs;JoPbBIM$Rm#U%YiG?Av82d z0ow7*ro-`zi9QR(z?7dt9TpQ|`Np{-@i-RFO`9$;_excGr= z(fvb*nnYwQ^#uz98vIU(rx1x4OIN479cv!PUv^BHvh}qD$u5tp{hQ1>HIWc)qxQX_?4-Y)c zORnHoQvtH4JKH(M6W3?t&e)?g|8gJ&MXLlGYO9*OSFLpzWLY>6=M!+X);eT_8QT~; zUd{4mV{Nv(mc`zeyUHg=dx&qYPtK44N%-E3yx6N?f;#A?dXyOZ(>P&5uc+?VUH~i%z#|E}L?SzG`6z$ok3CWQx46o9r4FuJ_XN`08FG2X3}= zs=s&j`uTKL44>2c?U!9P?_kLmHH=1GM|-1sF#>HlV+3AV9XVT3H-MAy%##~BEyeQZ z8m0*c$27Ocn*=&xNsEhxBCg)O-QFj4?~Pg-4b3` zIKhubXWJPw6?N?8V(B&+$+A-&uG>Tos>UUU)ERZsnT5_c4hz60OW-VXYBjK`{!omt zz--{v$)o!+qH|qSa$dSTV*sr1@hsl5<5wjmyj4rjIYbv@sqICt6>chrNXD2m*z;uQr7McZW=a@wB#HEF|T*>c_(cLJ#z4RKk&BWj&J$}G+UC?2X5K47) z6?R5mAG}sGY@w{_`v=*QRLmK;FvWl>ro^{+Dsqrmx?i; z_dPl>_0&BIdyf4vkyk6Ip;>{$Ntb@9jRuHh9ISKyKF_4QBu9>)< z*^`$6mxRRc3!H;3qtUsfX{GMGXxVQESbQPWSsl`7DP{gr(7>__@0aRftU6$(jhyh5 zH?p;_A;G9AL7hN>DJ@GWez!Car6AtcK>KzHkDyR0ah+4M@}8&Nu_ zd9xoGeAUn8v?Mv|^0S`H))1$aSuMpKlGZ@UyX2U1CO|CeByJE$`8u)oQpBAwO-M!K zqhH;VD~Bd`!}$x}BjSYE`bcuLjft3>>;TY;6Ptq(qzx;ss>4Z>uS0+&-vW0_A7F!k z2c9Q8X>>B1mnXgY<@+(n-Hqo@WS!ZU4Y3W0-^%qJlK!G(3v78S`(e_lkNPBwJdU94 z6k`jV!g1}2Av`y4WTmuOkf^7GiHmUY>a7AJL0DOM)Y%(Fc#h)p;5-&bQ%1=-T#ek1 zs}*vwTXi8#5QxpPd!$Z6iOEj_gI>GJ ztqKAKT5QpNhzDUqf)+Q7$!oVk4g42Gc1wyGwV4yEI#krb4M@vT*A`*06Z^pQHY968 zj)<2H8h^;bna0idxrGple9JUYY7lSN@hew%>rTfjKJPOBbbJ09;*r|!?|h>9%2-Qp z_RVCN&R3eKTl?DQ4#ovZTktaTV55cp{^yzQ@}y9rYb?H(2mI(k6%YfrAAJY(EO? zWz65C7*&r({Or0=Ctn_mP!}lfQk4~bpA14#^U7(QIuXA{9hA9TNf_w^P1DbgDLEXmQv(*4=_ zAEQM6a#m#hTnOM#Z@#XYbiG{qC2|i3f7C)XV@uTSqG$T&b8x!xQe^v*{a7-ytJbpT zw-gA=6dyk68T`uOQBqewVvpqZ*&}pheJQU2T06HsJ+?cIcJYtu2N;q0vD-FpNZsU-^kn{!0P6vlLT@q)VX7h=!YCgA zD#s?RgtRY~rrN7DFkoGo514-2Tq}5T_7W^_AC{9>o?W3OpV*Nb<-_&hT#)KC63qYb z&6fOC5O?{G5*txmbXx3e>|u3yusXfIIJ!c#a4QquYpi*e?`%xovy?dTCNu4Is6MSX zg>v%A0Y|Oa3IYgZ0d{N=%>oihF7>%&4eLstv zkM_Dz5h%Jq;=0#X(Y}Z`%5rNm*x#MJ-H%1f+bDNCbn~!)+UuENIW?}-MAv{ zn&yHwIsaqFec!)NrfD1HvlHh7EYyYQoG*fE2)Y4`%pBWLl6}>8d9K8QkL!|Y{TxMs z#g-I-TY4my<^LJwYwVx&H^zA?{~A*+Z{Cm;K?^Mu`JIz8uu6$vYVm!!@)|PlxN>^; z0AtKqe_7RQGJ)<&bBZRMnI5C}r|g z1Xdty$!ICK$S0Z)?wysKNpDQXL^fKGNoO{IkhB_DrBsLte>i=^>9fpsfV9r{2HY}e zidNP}l=5ycA%CHdppioVX)JnrrO;frh;Do88dK(fIe-^r^cX!2CeX06OJ#m8( zjr8hB>k{P;->~Qlgh-S0FSjw;cqUvIjLYxp6>NCJTZx3D!FF|Yj3a3?&z`EdL8BsNjeo)3Y@XxfaQoF zY%?xirZO_XN_E54Bmdw=4*}NPC$XAw#_v9=zLBR}>>s@%vt9|lp7O;gSIC~wA9{Z{ zHviCB|05N7B`EFj@R*N@CqayUbPQ#ol^$S=cs}~2 z*Z6%R132sXF-MCb&#>3Nj1D)7 zlVUAyum%Ggz0>a><&hRD+N5b91oP6Q#c3GGJ1OadAFfa4&@xK>PY$u$>6sRMHk!ic z237k1r(4GWf*ky{Wap|B~v>feF$zPy1Z+lYa2~)u4;$ZRQ`G4dk|X3FICo z9rHBpm>>4IRl$Z!JPphW`8ys+KB^+2H*pB_;{x#pP@)h8j|cor`hKdOaL=h-dkanKgC0KZ+3)Qcoq1x&H6`dZ?e z6nS8`PK34NPuK~sS-hkQ#TrUF*|ZEdUMIRfU#|GM`z_HmvD6+=#;S5W_5xsh#;hls zgt@WV?!JB2hM)2B2JaZzGEdWFk9mA2qtlA^6RA$ygX^%E`aK?;v;zas=adK{&zhPh z{rJ5#LhmDOHE|W{)ilB16up;u%ZO{EMPMZ?mNv|W%nQ+ee#wPXMs1)nJNd$oo&x6T z$=IIZL*%1A_0%%;4bm@5-00@^kUm5IH>&#AzjnyJkR#B}mV|sx=ya6hFT0<{kywM= z5k{Ian2d_IJ0$YIYShHls2^%fBm6#vzlf@|?6kOw!2!(PkzkR%~#a{El^ErJe|6heipBkVzjCQ$vrff{VeE)A$STs_; z!C`UZPZFW~e7IpA1y@;V%G)f3f|Yh;%M^A3aeut^UGuo^{tY>RGN327M53!GEu%QZ zw&=FUYN!Mh@*3=O=AN;9dmA|~jY%{)eM#b4cIk}UA<4h%}%C2=fB1l6@v%cG!K6z(XUGryP4GP7^Lnn2+`~Llq zIGSB`ptcWi{NOVNeuT0>2AoiE9A#lGRnclj{qMXxHi_drkQ?4YfjX?+{ zzhucS%Sty{6#I?mEIi^livRfF+OlQJHRiQEbsvZ3`iuz!T1e`B*kUAc*C{WV<{xNP zNzno4%#|DdZEbhkEn|?<=7v!y0NmbMxzD52sNG5yXmxVRtyXJ1YBR9Qp)^DbP0M6^)MY-maaO;%?Lg))d%9ZSIA78R`r&bWALbspP_XoYcN zCJ2U_y~Z0!Umsb?NG~shn$z8|-QESW8VX6s$#aI=U)gZE2~K7WCR4^>WG4Ar522`q ziXfX53Qv>aAR-ZSd&oKLO?M=t0xe0)wGhO~;$_;CfOkZK9ZsU-!QSqO|1|KgP7KGl zN>Og|6MgHUmJY%&XtkO9N&-P~vpzth783%c5uG|3_dJHpMg@LIE1*WzADhxbk$d!D zGYyHEG``HDlnIj$Ik1e!av*mKbmBxIEu*YBQr*8ldnKDtnM{1RL*!y2lijK-oyw0o zS7C$9QlQ%fG3KnIen3)Lzuo41M4Z|LH9)OE7NPy`%DEzxgD`GP@{Dc6eNF#uqf zV%MWtqQmK|h+-GmCt1WTlmze6T)q7o9_;oAm>PGAMdJtv!ScHMoZg&qj>mKiNmfg`& zz}LN2-r)Y1vGy%%jkdPt5P4Q!iGt;U(v0G-UqK+OIj1pk&uTdBeyyqOfR-$j96w)N z$=W80cRo3&%DHtwFNUKu(|NzX=0${dbRAXwD@6u+umwGki>%T%eSn%UV%6%nbJ}c; zCR@vAq|;fSt!7DxPm{AnjwW`rj%)R+lbr0wR^VPNr1nFIGDxa4x`^gL)N?bNJbWMb zqL{hWfOZhgjns}Tmgbb_+G`*hZwCy2s&m~+5QkYIlHVp zP?TI=$yC!4)UU*(cXJV~A(6%zQ+6jj{O~6E_c%4ksxb?z*(Z!6#a3`NCK%eJVEvj0 zR>PjsT!F$!&Ov6^G{yAJkh^+yIc^@av#ZX{gfb9|;uNDBgRkzEG+)afPeSuX4V^^v z2c$b|1J?}N)V)c9i8$Q2vv;TC*0(t=3?`2)@>rB?n=lDOa8yx6IrT-L0Mvls>*P_2 zC|d8fcm$)2CA=_kq`T6iT5Y6pZSSM{pCft*+AvP4+`KAD;auW5Ry;}Hd_j(Hjlt3N z-J<`r%Z1a%r5?4X0zS^Fxgwi31u6Qtd7Q1O)vH-{bF6X+D8%qRwM18{eX?MQZx!R6 zpR#uYRe-qRFzdrrZxYg1@Y&bApz)uhzOqw0yzfWanc~Kiyk>4l30{rmOep*-y%^Kp z$%)pGWB(a{wBGoq+02lh5Kmq4z}khTl|XvKwDbvW{ZgN-Aym`p#p^`PD@c(H_NrC#*b|PhS2D8&=n@9u zDVO^+y!W+S67JByms{KJ{{FJZe6DJUlgQ$XKYdn@&ROz?D{$0Q7UG^=dy|?@RoH}52^b>@!xW(z}zqLT{fiJGpCozjY zVFW0e&>0dI%#bvb0Ph;GQmBDv*}{XF7{V!swsM#)-x|nV<-hf%;owW(p)Qk`LYFg* zHUnqo)g51I)mL0+R(V-Dbh*cu{cgFTWs_WcgGGLWOLMdChDe27DYq-$vtat~w7jcLql#?oQIy<3vje-yCd|c*4f`?}(&OOu9pHG$<&uv_rSNJrWbp}9>chrd z;bHi}DLWY}ZZw{BNq>j|+7D+O%!)~B^dpQ?h>JR`A(xrj^6-YF2w7-J7l{qY*8QJD z9BPxmu??x=eSN#b`>`tqw@T>$aSVzPjX@spB@ORTZ~-dh-td==>bA;Mm9$awTEzxV z9KvIn*Ftu!_?Ju1J)T~C`^<9-890R(Ce6&88Y7K&9X>v|S;mbpP~5J*0dzEPBlcV~ z-Ghbx!Kic0*QTq@rm#WP>VUc34FPVLXLBbF^4nS0a>vLm#7|1#v3<;TK4UdsC^T&( zqS;b4$*$OBwD#~b z45}ba)Au6lnBMv<3(67un{@*m@i9-ytu~!MR~wUJy+P9s7bvZZ6cj)CCK39lK{vH0Z@gTXoH)ECW;HwYp z7R4J|yI(X;GnQL{O&s0xd||KsAC?wVnS_f3NN+2FT3`8)@8UfpiV-ykYeZJ9>~*U8 zQgWuz;;#K`ZWL%C==cQJYVglJ~8_BcZ%!v!ua~_t>qD$OA~=~@|ex3 z2|u}{#rhUcgAf!K0)^K}v*vNC)5~S$Y&}xW{a9CaFXjfR=yC}cw7zlprf5%a%!gGU z;fu)3MWVt)tGBb0Vshyu=gCax_-Oo1wCPn|e5MfsWx){n3b=JmChghG^8+}wMH)-5 zDldkA0%Iv@b0If?=ZeDHec+(wAEX-qL_F8lu+U&C7o&fu)IXuFk&YVsna6c+y4W(& z0OAd(s;aK~gMN`zfxhY+1=XVeE~*>R0106Wb16&|AmG>yqS2=6w3FwKD@gM%BgN$+ zsizk6LM>oK=2DS+>oDMb&q^4UvJDL4_(_wlt!?V)SzcTx>Fa)OImE3F&FhY9IloDC zOWQU#>|=7#BzTAw&GAvV>v}5vhBzp%2N8n`*ud0S& zU&X5d7AN9tlyr_4hjcfzHv*7`9B+7(`3fwD`8(0gNBjV) zl=J58CadwpmsW$#UyO!d8x6N3;1(|AUNM0`_jQ8wD3P_iYgl~@Cv`T67=N=aJrk|V zKd%}W⪇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 literal 0 HcmV?d00001 diff --git a/public/img/logo.svg b/public/img/logo.svg new file mode 100644 index 0000000..b77b8da --- /dev/null +++ b/public/img/logo.svg @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/index.html b/public/index.html index 680fbe4..249501b 100644 --- a/public/index.html +++ b/public/index.html @@ -3,19 +3,19 @@ -teach - +teachus.today + +
- @@ -68,7 +64,10 @@
+
@@ -106,6 +106,7 @@
+
@@ -137,6 +138,54 @@
+ + diff --git a/public/js/app.js b/public/js/app.js index 3f3ec04..33db8f5 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -23,17 +23,59 @@ zoomPct.addEventListener("click", ()=>setZoom(100)); /* tap the % to reset */ document.addEventListener("langchange", ()=>{ btnZoomIn.title = btnZoomOut.title = zoomPct.title = T("zoomUI"); }); try{ const z = +localStorage.getItem("teach.zoom"); if(z>100) setZoom(z); else setZoom(100); }catch(e){ setZoom(100); } -/* high-contrast accessibility mode (device setting, persists) */ -const btnHC = document.getElementById("btnHC"); -function setHC(on){ - document.body.classList.toggle("hc", on); - btnHC.classList.toggle("on", on); - btnHC.title = T("a11y"); - try{ localStorage.setItem("teach.hc", on ? "1" : ""); }catch(e){} +/* weergave-instellingen (Instellingen → Weergave): apparaat-gebonden voorkeuren. + Elke seg-groep: knopjes met data-v, keuze in localStorage, body-class toepassen. */ +function initSeg(id, key, def, apply){ + const seg = document.getElementById(id); + let val = def; + try{ val = localStorage.getItem(key) || def; }catch(e){} + if(![...seg.querySelectorAll("button")].some(b=>b.dataset.v===val)) val = def; + const set = v=>{ + seg.querySelectorAll("button").forEach(b=>b.classList.toggle("active", b.dataset.v===v)); + apply(v); + try{ localStorage.setItem(key, v); }catch(e){} + }; + seg.querySelectorAll("button").forEach(b=>b.addEventListener("click", ()=>set(b.dataset.v))); + set(val); } -btnHC.addEventListener("click", ()=>setHC(!document.body.classList.contains("hc"))); -document.addEventListener("langchange", ()=>{ btnHC.title = T("a11y"); }); -try{ if(localStorage.getItem("teach.hc")==="1") setHC(true); }catch(e){} +/* thema: licht / donker / automatisch (volgt het OS) */ +const darkMq = window.matchMedia("(prefers-color-scheme: dark)"); +const applyTheme = v=>{ + document.body.classList.toggle("dark", v==="dark" || (v==="auto" && darkMq.matches)); +}; +initSeg("segTheme", "teach.theme", "light", applyTheme); +darkMq.addEventListener("change", ()=>{ + try{ if((localStorage.getItem("teach.theme")||"light")==="auto") applyTheme("auto"); }catch(e){} +}); +/* hoog contrast (voorheen de 👁-knop in de menubalk; zelfde localStorage-sleutel) */ +(function(){ + let init = "off"; + try{ if(localStorage.getItem("teach.hc")==="1") init = "on"; }catch(e){} + const seg = document.getElementById("segHC"); + const set = v=>{ + seg.querySelectorAll("button").forEach(b=>b.classList.toggle("active", b.dataset.v===v)); + document.body.classList.toggle("hc", v==="on"); + try{ localStorage.setItem("teach.hc", v==="on" ? "1" : ""); }catch(e){} + }; + seg.querySelectorAll("button").forEach(b=>b.addEventListener("click", ()=>set(b.dataset.v))); + set(init); +})(); +/* menubalk-positie: boven / links / rechts */ +initSeg("segTbar", "teach.tbar", "top", v=>{ + document.body.classList.toggle("tb-left", v==="left"); + document.body.classList.toggle("tb-right", v==="right"); +}); +/* minder beweging: standaard uit als het OS erom vraagt */ +const motionDef = window.matchMedia("(prefers-reduced-motion: reduce)").matches ? "off" : "on"; +initSeg("segMotion", "teach.motion", motionDef, v=>document.body.classList.toggle("no-motion", v==="off")); +/* glas-effect (transparantie/blur van widgets en balken) */ +initSeg("segGlass", "teach.glass", "on", v=>document.body.classList.toggle("no-glass", v==="off")); + +/* taalkeuze onthouden (de schakelaar staat nu onder Weergave) */ +try{ + const l = localStorage.getItem("teach.lang"); + if(l && I18N[l]) LANG = l; +}catch(e){} applyI18n(); updateEmptyHint(); diff --git a/public/js/core.js b/public/js/core.js index 1241889..cc10548 100644 --- a/public/js/core.js +++ b/public/js/core.js @@ -2,7 +2,7 @@ "use strict"; /* version — shown until /api/version resolves (or if the fetch fails, e.g. offline). Kept in sync by hand with the VERSION file at the repo root on every release. */ -const VERSION = "0.2.22"; +const VERSION = "0.3.00"; (function(){ const tag = document.getElementById("verTag"); tag.textContent = "v"+VERSION; @@ -120,6 +120,11 @@ const I18N = { login:"Inloggen", loginBtn:"Inloggen", registerBtn:"Account maken", logout:"Uitloggen", settingsTitle:"Instellingen", tabLogin:"Inloggen", tabLinkCode:"Koppelcode", busy:"Bezig…", stAccount:"Account", stPassword:"Wachtwoord", stSession:"Sessie", + stView:"Weergave", vwTheme:"Thema", vwLight:"Licht", vwDark:"Donker", vwAuto:"Auto", + vwContrast:"Hoog contrast", vwOn:"Aan", vwOff:"Uit", vwLang:"Taal", + vwTbar:"Menubalk", vwTop:"Boven", vwLeft:"Links", vwRight:"Rechts", + vwMotion:"Animaties", vwGlass:"Glas-effect", + vwNote:"Deze voorkeuren gelden voor dit apparaat.", pwChanged:"Wachtwoord gewijzigd ✓", namePh:"naam", passPh:"wachtwoord", guestNote:"Zonder inloggen wordt niets bewaard. Log in met je schoolaccount om alles op de server te bewaren.", @@ -254,6 +259,11 @@ const I18N = { login:"Log in", loginBtn:"Log in", registerBtn:"Create account", logout:"Log out", settingsTitle:"Settings", tabLogin:"Log in", tabLinkCode:"Link code", busy:"Please wait…", stAccount:"Account", stPassword:"Password", stSession:"Session", + stView:"Display", vwTheme:"Theme", vwLight:"Light", vwDark:"Dark", vwAuto:"Auto", + vwContrast:"High contrast", vwOn:"On", vwOff:"Off", vwLang:"Language", + vwTbar:"Menu bar", vwTop:"Top", vwLeft:"Left", vwRight:"Right", + vwMotion:"Animations", vwGlass:"Glass effect", + vwNote:"These preferences apply to this device.", pwChanged:"Password changed ✓", namePh:"name", passPh:"password", guestNote:"Without logging in nothing is saved. Log in with your school account to keep everything on the server.", @@ -321,7 +331,11 @@ function applyI18n(){ document.dispatchEvent(new CustomEvent("langchange")); } document.querySelectorAll("#langToggle button").forEach(b=>{ - b.addEventListener("click", ()=>{ LANG=b.dataset.lang; applyI18n(); }); + b.addEventListener("click", ()=>{ + LANG=b.dataset.lang; + try{ localStorage.setItem("teach.lang", LANG); }catch(e){} + applyI18n(); + }); }); document.getElementById("btnFs").addEventListener("click", ()=>{ if(document.fullscreenElement) document.exitFullscreen(); else document.documentElement.requestFullscreen(); @@ -427,14 +441,16 @@ function switchLoginTab(tab){ document.querySelectorAll("#loginModal .ed-tabs button").forEach(b=>{ b.addEventListener("click", ()=>switchLoginTab(b.dataset.tab)); }); -/* instellingen-tabs: "account" vs "beheer" - alles in één overzicht i.p.v. een los venster */ +/* instellingen-tabs: "account" / "weergave" / "beheer" - alles in één overzicht */ function switchSettingsTab(tab){ document.querySelectorAll("#settingsTabs button").forEach(b=>b.classList.toggle("active", b.dataset.tab===tab)); document.getElementById("settingsAccountPanel").style.display = tab==="account" ? "block" : "none"; + document.getElementById("settingsViewPanel").style.display = tab==="view" ? "block" : "none"; document.getElementById("settingsAdminPanel").style.display = tab==="admin" ? "block" : "none"; } /* het "beheer"-tabblad heeft zijn eigen klik-handler in admin.js (moet eerst data laden) */ document.querySelector('#settingsTabs button[data-tab="account"]').addEventListener("click", ()=>switchSettingsTab("account")); +document.querySelector('#settingsTabs button[data-tab="view"]').addEventListener("click", ()=>switchSettingsTab("view")); async function loadSchools(){ const sel = document.getElementById("liSchool"); try{ @@ -445,7 +461,10 @@ async function loadSchools(){ } function openSettings(){ settingsMsg.textContent = ""; settingsMsg.classList.remove("ok"); - switchSettingsTab("account"); + /* zonder account is er geen Account-tab: dan direct naar Weergave + (zo blijven taal/contrast/thema ook als gast bereikbaar) */ + document.querySelector('#settingsTabs button[data-tab="account"]').style.display = currentUser ? "" : "none"; + switchSettingsTab(currentUser ? "account" : "view"); settingsWrap.classList.add("open"); } document.getElementById("btnUser").addEventListener("click", ()=>{ @@ -455,6 +474,11 @@ document.getElementById("btnUser").addEventListener("click", ()=>{ loadSchools(); loginWrap.classList.add("open"); }); +/* gast-ingang naar de weergave-instellingen vanuit het inlogscherm */ +document.getElementById("btnGuestView").addEventListener("click", ()=>{ + loginWrap.classList.remove("open"); + openSettings(); +}); document.getElementById("btnSettingsClose").addEventListener("click", ()=>settingsWrap.classList.remove("open")); loginWrap.addEventListener("click", e=>{ if(e.target===loginWrap) loginWrap.classList.remove("open"); }); settingsWrap.addEventListener("click", e=>{ if(e.target===settingsWrap) settingsWrap.classList.remove("open"); });