  /* ==========================================================
     Huisstijl Woudstra Design
     Kleuren en font komen rechtstreeks uit de merk-svg's.
     ========================================================== */
  :root{
    /* Achtergrond — radial gradient, begint linksboven */
    --grad-1: #092543;
    --grad-2: #050e1c;
    --grad-3: #28181c;

    /* Merkkleuren (uit logo-kit) */
    --charcoal: #27232f;
    --ink: #0d0d0d;
    --neon-green: #39ff88;
    --paper: #ffffff;
    --soft-lavender: #f7f7ff;

    --panel: #211f28;
    /* Glas-achtergrond voor panelen/kaarten/modals — --ink op 30%
       dekking, gecombineerd met backdrop-filter:blur() op elke plek die
       'm gebruikt (zie hieronder). Vervangt het vlakke, ondoorzichtige
       --panel op de meeste plekken — dat blijft alleen nog bestaan voor
       de paar plekken waar transparantie niet gewenst/betrouwbaar is
       (bijv. de native <option>-lijst van een <select>, die negeert
       backdrop-filter toch grotendeels en zou anders onleesbaar kunnen
       worden tegen het systeem-eigen popupvlak). */
    --glass-bg: rgba(13,13,13,0.3);
    --border: rgba(247,247,255,0.10);
    --text: var(--soft-lavender);
    --text-muted: rgba(247,247,255,0.56);
    --accent: var(--neon-green);
    --input-bg: rgba(247,247,255,0.04);

    --mono: "SF Mono", "Menlo", "Consolas", monospace;
    --sans: "Outfit", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
  }

  * { box-sizing: border-box; }

  body{
    margin:0;
    padding:0;
    background: radial-gradient(ellipse 140% 140% at 0% 0%, var(--grad-1) 0%, var(--grad-2) 55%, var(--grad-3) 100%) fixed;
    color:var(--text);
    font-family:var(--sans);
    font-weight:400;
    -webkit-font-smoothing:antialiased;
    /* Vangnet tegen horizontale pagina-scroll — één element dat op een
       smal scherm net te breed uitvalt (voorheen bv. .dashboard-welkom-
       titel/#projectNaam, zie de mobiele-breakpoint-regels verderop)
       schoof anders de HELE pagina breder dan het scherm i.p.v. gewoon
       zichzelf af te knippen. Losse componenten horen zichzelf sowieso
       netjes te begrenzen (zie hieronder); dit is puur de achtervang. */
    overflow-x:hidden;
  }

  /* Nieuwe app-schil: vaste linker icoon-navigatie (.sidebar) + de
     eigenlijke inhoud (.wrap) ernaast — vervangt de vorige opzet met een
     volle bovenste header met daarin de tabs. .wrap zelf is intern
     ONGEWIJZIGD (page-hero, tab-panels, print-only divs) — alleen zijn
     plek (naast i.p.v. onder iets) en zijn eigen padding (voorheen op
     body) zijn anders.
     .sidebar is position:fixed (niet meer sticky) zodat 'm bij hover
     kan UITSCHUIVEN (zie .sidebar:hover hieronder) zonder de rest van de
     pagina te laten meeschuiven — .app-shell reserveert daarvoor gewoon
     zijn rust-breedte (76px) als linker padding; de uitgeschoven stand
     (220px) legt zich als overlay OVER de inhoud ernaast, precies zoals
     dat soort uitklap-navigatie in de meeste apps werkt. */
  .app-shell{
    padding-left:76px;
    min-height:100vh;
  }

  .sidebar{
    position:fixed;
    top:0;
    left:0;
    height:100vh;
    width:76px;
    display:flex;
    flex-direction:column;
    align-items:stretch;
    gap:4px;
    padding:20px 16px;
    border-right:0.5px solid var(--border);
    background:var(--glass-bg);
    backdrop-filter:blur(20px);
    -webkit-backdrop-filter:blur(20px);
    z-index:50;
    transition:width .18s ease;
  }

  /* [hidden] als attribuutselector moet expliciet — anders wint
     "display:flex" hierboven van de browser-standaard [hidden]{display:
     none} (zelfde valkuil als eerder bij .page-hero-nieuw-btn/
     .btn-download-icon/etc.). #appSidebar/#appWrap staan nu standaard
     hidden — pas toonApp() in het script ontgrendelt ze, zie de
     HTML-comment daar (veiligheidsfix: voorheen stond de hele app-schil
     altijd al zichtbaar in de DOM, alleen afgedekt door #inlogScherm). */
  .sidebar[hidden]{
    display:none;
  }

  /* Breder bij hover — de namen naast de iconen (zie .sidebar-label)
     komen dan tevoorschijn. De knoppen zelf hebben width:100% (zie
     .tab-button e.d. verderop), dus die volgen deze breedte vanzelf
     mee, geen aparte transition op de knoppen zelf nodig. */
  .sidebar:hover{
    width:220px;
  }

  .sidebar-logo{
    display:flex;
    align-items:center;
    justify-content:center;
    gap:10px;
    margin-bottom:20px;
  }

  .sidebar-logo .brandmark{
    height:28px;
    width:auto;
    flex-shrink:0;
    display:block;
    color:var(--soft-lavender);
  }

  /* Verborgen (max-width:0) in de rust-stand — er is bij 76px letterlijk
     geen ruimte voor naast het icoon. Bij hover (zie .sidebar:hover
     hieronder) schuift 'm open tot z'n natuurlijke breedte (~92px bij
     16px hoogte), .sidebar-logo's eigen justify-content:center houdt het
     icoon+wordmark-duo daarbij steeds gecentreerd t.o.v. de op dat
     moment actuele sidebar-breedte. */
  .sidebar-logo .wordmark{
    height:16px;
    width:auto;
    flex-shrink:0;
    display:block;
    color:var(--soft-lavender);
    max-width:0;
    opacity:0;
    overflow:hidden;
    transition:max-width .18s ease, opacity .12s ease;
  }

  .sidebar:hover .sidebar-logo .wordmark{
    max-width:120px;
    opacity:1;
  }

  .sidebar-nav{
    display:flex;
    flex-direction:column;
    gap:4px;
  }

  /* Instellingen onderaan (margin-top:auto) — visueel losgezet van de
     hoofdpagina's erboven (Dashboard/Prijscalculator/Facturen/Klanten).
     In de vorige horizontale header maakte onderstreept-vs-omkaderd dat
     onderscheid; in een smalle verticale rail doet positie (boven vs.
     onder) hetzelfde werk, zonder dat de knoppen zelf een ander
     uiterlijk nodig hebben. Geen align-items
     meer hier (was center) — de knoppen erin moeten nu net als bij
     .sidebar-nav de volle (variabele) breedte kunnen vullen, en "stretch"
     is toch al de standaardwaarde voor flex-column-kinderen. */
  .sidebar-bottom{
    margin-top:auto;
    display:flex;
    flex-direction:column;
    gap:4px;
  }


  .wrap{
    max-width:1040px;
    margin:0 auto;
    padding:32px 24px 80px;
  }

  /* Kleine hero bovenaan .wrap: paginatitel, wisselt mee per tab (zie
     wisselTab()). Dit is het "waar ben ik nu"-blok — navigatie zelf zit
     in .sidebar. margin-top klein gehouden (i.p.v. de vorige 28px) —
     .wrap heeft al 32px eigen padding-top, en 32+4=36 sluit daarmee aan
     op de 36px margin-bottom hieronder i.p.v. bovenin merkbaar meer
     ruimte te laten dan onderin. */
  .page-hero{
    margin:4px 0 36px;
  }

  /* Bevat nu alleen nog de acties (Opslaan/Nieuw e.d.) — de titel staat
     er niet meer in, zie .page-hero-titel-rij hieronder. flex-end omdat
     dit voorheen een 2-koloms space-between-rij was (titel links, acties
     rechts); met alleen de acties over blijven die zonder deze regel
     naar links zweven i.p.v. rechts, waar ze hoorden. */
  .page-hero-top{
    display:flex;
    align-items:center;
    justify-content:flex-end;
    flex-wrap:wrap;
    gap:16px;
  }

  /* Meerdere knoppen in de actierij passen niet altijd naast elkaar op
     smalle schermen — zonder wrap werd de laatste knop buiten beeld
     afgesneden. */
  @media (max-width:480px){
    .page-hero-acties{
      width:100%;
    }
  }

  /* Titel + de "Bewerkt: ..."-badge, los bovenaan de hero, links
     uitgelijnd — zelfde uitlijning als de groet op het Dashboard
     (.dashboard-welkom-titel), i.p.v. de vorige gecentreerde variant. */
  .page-hero-titel-rij{
    display:flex;
    flex-direction:column;
    align-items:flex-start;
    gap:6px;
    text-align:left;
    margin-bottom:12px;
  }

  /* [hidden] als attribuutselector moet expliciet — anders wint
     "display:flex" hierboven van de browser-standaard [hidden]{display:
     none} (zelfde valkuil als eerder bij .page-hero-acties/
     .page-hero-nieuw-btn/.bewerkt-banner). Zonder dit bleef de generieke
     "Facturen"-paginatitel gewoon zichtbaar boven de titel van de
     geopende factuur, ondanks dat het hidden-attribuut wél correct gezet
     werd (zie toonFacturenWerkscherm()/wisselTab() in het script). */
  .page-hero-titel-rij[hidden]{
    display:none;
  }

  /* Klein en dik i.p.v. de vorige zware 22px-kop. */
  .page-hero-title{
    margin:0;
    font-size:13.5px;
    font-weight:700;
    color:var(--text);
  }

  /* Toont welk opgeslagen item nu geladen is — zie de HTML-comment bij
     #pageHeroBewerktBadge en verversHuidigGeladenBadge() in het script.
     Zelfde pil-vorm/accentkleur als .saved-indicatie-badge.is-offerte
     (ook daar betekent de accentkleur "dit is een bestaand, bruikbaar
     document"), zodat het leest als hetzelfde soort statuslabel. */
  /* display:inline-block (niet -flex) — puur platte tekst, geen icoon/
     meerdere kinderen die flex-uitlijning nodig hebben. Belangrijk: een
     flex-container geeft zijn tekstinhoud geen "inline formatting
     context", dus text-overflow:ellipsis hieronder zou bij
     display:inline-flex stilletjes NIETS doen (de tekst wordt dan gewoon
     hard afgekapt zonder "…") — zie ook .saved-indicatie-klant elders,
     die om dezelfde reden geen flex-display heeft. */
  .page-hero-bewerkt-badge{
    display:inline-block;
    align-self:flex-start;
    padding:3px 9px;
    border-radius:5px;
    background:rgba(57,255,136,0.12);
    color:var(--accent);
    font-size:11px;
    font-weight:700;
    white-space:nowrap;
    max-width:100%;
    overflow:hidden;
    text-overflow:ellipsis;
  }

  .page-hero-bewerkt-badge[hidden]{
    display:none;
  }

  /* Alleen relevant op de Prijscalculator-tab (zie wisselTab()) — een
     algemene, altijd-zichtbare "begin opnieuw"-actie naast de
     paginatitel, i.p.v. verstopt in een banner die alleen af en toe
     verschijnt. */
  .page-hero-nieuw-btn{
    display:inline-flex;
    align-items:center;
    gap:6px;
    flex-shrink:0;
    padding:8px 14px;
    border:0.5px solid var(--border);
    border-radius:8px;
    background:transparent;
    color:var(--text);
    font-family:var(--sans);
    font-size:12.5px;
    font-weight:700;
    cursor:pointer;
    transition:border-color .15s ease, background-color .15s ease, color .15s ease;
  }

  /* [hidden] als attribuutselector moet expliciet — zelfde valkuil als
     eerder bij .page-hero-acties/.page-hero-opslaan-btn: zonder dit wint
     "display:inline-flex" hierboven altijd van de UA-stylesheet, ongeacht
     het hidden-attribuut. */
  .page-hero-nieuw-btn[hidden]{
    display:none;
  }

  .page-hero-nieuw-btn svg{
    width:14px;
    height:14px;
  }

  .page-hero-nieuw-btn:hover{
    border-color:var(--accent);
    background:var(--accent);
    color:var(--grad-2);
  }

  /* Alle hoofdpagina-knoppen (.tab-button: Dashboard/Prijscalculator/
     Facturen) + Klanten + Instellingen (.historie-btn — generieke naam,
     dateert nog van toen deze class ook de inmiddels verwijderde
     Historie-knop droeg) delen nu dezelfde icoon-knop-stijl — in de
     smalle verticale rail is er geen ruimte (en geen noodzaak) voor het
     onderscheid dat de oude horizontale header had (onderstreept vs.
     omkaderd); positie (boven vs. onder, zie .sidebar-bottom) doet dat
     werk nu. width:100% (niet meer een vast vierkant) zodat de knop
     vanzelf meegroeit met .sidebar bij hover — het label (zie
     .sidebar-label) verschijnt in de zo vrijkomende ruimte ernaast.
     overflow:hidden knipt dat label in de rust-stand (waar het smaller
     is dan de labeltekst) gewoon af, i.p.v. dat de tekst buiten de
     smalle rail zou uitsteken. */
  .tab-button,
  .klanten-btn,
  .historie-btn{
    display:flex;
    align-items:center;
    justify-content:flex-start;
    gap:12px;
    width:100%;
    height:44px;
    padding:0 12px;
    border:none;
    border-radius:10px;
    background:transparent;
    color:var(--text-muted);
    cursor:pointer;
    overflow:hidden;
    white-space:nowrap;
    transition:background-color .15s ease, color .15s ease;
  }

  .tab-button svg,
  .klanten-btn svg,
  .historie-btn svg{
    width:20px;
    height:20px;
    flex-shrink:0;
  }

  .tab-button:hover,
  .klanten-btn:hover,
  .historie-btn:hover{
    background:rgba(247,247,255,0.06);
    color:var(--text);
  }

  .tab-button.is-active,
  .klanten-btn.is-active,
  .historie-btn.is-active{
    background:rgba(57,255,136,0.12);
    color:var(--accent);
  }

  /* Dashboard is de primaire CTA van de sidebar — altijd opgevuld/
     opvallend, ook als een andere tab actief is (i.t.t. de subtiele
     .is-active-tint hierboven), zodat het duidelijk DE centrale plek is
     om naar terug te keren i.p.v. zomaar één van de tabbladen. */
  .sidebar-nav .tab-button[data-tab="dashboard"],
  .sidebar-nav .tab-button[data-tab="dashboard"].is-active{
    background:var(--accent);
    color:var(--grad-2);
  }

  .sidebar-nav .tab-button[data-tab="dashboard"]:hover{
    background:var(--accent);
    color:var(--grad-2);
    opacity:0.85;
  }

  /* Naam naast het icoon — onzichtbaar/afgeknipt in de rust-stand van de
     sidebar (76px, precies genoeg voor het icoon + padding, geen ruimte
     voor deze tekst), komt tevoorschijn zodra .sidebar breder wordt bij
     hover. opacity (i.p.v. alleen op de overflow:hidden van de knop
     vertrouwen) zorgt voor een zachtere, gefadede intrede i.p.v. een
     harde knip. */
  .sidebar-label{
    font-size:13px;
    font-weight:700;
    opacity:0;
    transition:opacity .12s ease;
  }

  .sidebar:hover .sidebar-label{
    opacity:1;
  }

  /* --- Facturen-tab --- */
  /* Terug-naar-overzicht-link bovenaan het werkscherm — zie
     #facturenTerugBtn/toonFacturenOverzicht() in het script. Zelfde
     rustige, niet-primaire tekst-knop-stijl als .page-hero-nieuw-btn qua
     gewicht, maar zonder rand/achtergrond (geen "knop"-doos nodig voor
     een terug-navigatie, die hoort onopvallend te zijn totdat je 'm
     nodig hebt). */
  .facturen-terug-link{
    display:inline-flex;
    align-items:center;
    gap:6px;
    margin-bottom:16px;
    padding:0;
    border:none;
    background:transparent;
    color:var(--text-muted);
    font-family:var(--sans);
    font-size:12.5px;
    font-weight:700;
    cursor:pointer;
    transition:color .15s ease;
  }

  .facturen-terug-link svg{
    width:14px;
    height:14px;
  }

  .facturen-terug-link:hover{
    color:var(--accent);
  }

  /* Gedeelde segmented-control-stijl — gebruikt voor Documenttype
     (Prijsindicatie/Offerte) én Factureringswijze (Facturen-tab). Een
     instelling die het hele document/tabblad bepaalt hoort een
     prominente, expliciete keuze te zijn, geen weggemoffelde <select>. */
  .segmented-toggle{
    display:flex;
    gap:4px;
    padding:4px;
    border:1px solid var(--border);
    border-radius:9px;
    background:rgba(13,13,15,0.3);
  }

  .segmented-toggle-optie{
    flex:1;
    padding:9px 10px;
    border:none;
    border-radius:6px;
    background:transparent;
    color:var(--text-muted);
    font-family:var(--sans);
    font-size:12.5px;
    font-weight:700;
    cursor:pointer;
    transition:background-color .15s ease, color .15s ease;
  }

  .segmented-toggle-optie:hover{
    color:var(--text);
  }

  .segmented-toggle-optie.is-actief{
    background:var(--accent);
    color:var(--grad-2);
  }

  .segmented-toggle-optie.is-actief:hover{
    color:var(--grad-2);
  }

  /* Krapper op een telefoonscherm — vooral relevant voor het 4-opties
     Facturen-statusfilter (Alles/Betaald/Wachtend/Verlopen), dat het
     minst ruimte per optie heeft. flex:1 op elke optie zorgt al dat ze
     nooit buiten de container vallen, maar zonder dit werd de tekst op
     smalle telefoons wel erg dicht opeen gedrukt. */
  @media (max-width:480px){
    .segmented-toggle-optie{
      padding:8px 4px;
      font-size:11px;
    }
  }

  /* Status-filter boven het Facturen-overzicht (zie #facturenFilterToggle)
     — zelfde .segmented-toggle-component als hierboven, alleen begrensd
     in breedte (anders trekt 'ie bij een brede pagina onnodig helemaal
     door) en met wat ruimte eronder tot het zoekveld. De Prijscalculator
     heeft sinds de UX-opdracht "2." geen eigen filter-toggle meer (zie
     .overzicht-horizontaal-sectie in plaats daarvan). */
  .facturen-filter-toggle{
    max-width:580px;
    margin-bottom:20px;
  }

  /* Zichtbaar zodra "Opslaan" écht mislukt is — zie
     schrijfOpgeslagenIndicatie()/opslaanPrijsindicatie() in het
     script. Zonder dit was een mislukte save volledig onzichtbaar: geen
     foutmelding, gewoon stilletjes niks opgeslagen. */
  .page-hero-foutmelding{
    margin-top:14px;
    padding:12px 14px;
    border:1px solid rgba(255,92,92,0.4);
    border-radius:8px;
    background:rgba(255,92,92,0.08);
    color:#ff8a8a;
    font-size:13px;
    line-height:1.5;
  }

  .page-hero-foutmelding[hidden]{
    display:none;
  }

  /* Bij "Aanbetaling + eindfactuur" staan de twee facturen als compact
     vierkantje (.factuur-tile) naast elkaar in #facturenTegelGrid — klik
     erop om 'm te bewerken in het bewerkscherm eronder (zie
     bouwFacturenTegelKiezer() in het script). Bij "1 complete factuur"
     (of een handmatig aangemaakte factuur, zie maakLegeFactuur()) is er
     maar één factuur, dus wordt deze kiesstap overgeslagen en opent het
     bewerkscherm meteen. */
  #facturenTegelGrid{
    display:flex;
    flex-wrap:wrap;
    gap:14px;
    margin-top:20px;
  }

  #facturenTegelGrid[hidden]{
    display:none;
  }

  .factuur-tile{
    width:190px;
    padding:18px;
    border:1px solid var(--border);
    border-radius:10px;
    background:var(--glass-bg);
    backdrop-filter:blur(20px);
    -webkit-backdrop-filter:blur(20px);
    cursor:pointer;
    text-align:left;
    transition:border-color .15s ease, transform .15s ease;
  }

  .factuur-tile:hover{
    border-color:var(--accent);
    transform:translateY(-2px);
  }

  .factuur-tile-icoon{
    color:var(--text-muted);
    margin-bottom:14px;
  }

  .factuur-tile-icoon svg{
    width:20px;
    height:20px;
  }

  .factuur-tile-titel{
    font-size:12px;
    font-weight:700;
    color:var(--text);
    line-height:1.4;
    margin-bottom:10px;
  }

  .factuur-tile-bedrag{
    font-family:var(--mono);
    font-size:17px;
    font-weight:700;
    color:var(--accent);
  }

  .factuur-tile-onder{
    display:flex;
    align-items:flex-end;
    justify-content:space-between;
    gap:8px;
    margin-top:10px;
  }

  .factuur-tile-hint{
    font-size:11px;
    color:var(--text-muted);
  }

  /* Losse downloadknop rechtsonder in de tegel — los klikbaar zodat je
     niet eerst het bewerkscherm hoeft te openen om te downloaden.
     stopPropagation() in de click-listener voorkomt dat de klik ook de
     tegel zelf triggert. */
  .factuur-tile-download{
    display:flex;
    align-items:center;
    justify-content:center;
    flex-shrink:0;
    width:26px;
    height:26px;
    border:1px solid var(--border);
    border-radius:6px;
    background:transparent;
    color:var(--text-muted);
    cursor:pointer;
    transition:border-color .15s ease, background-color .15s ease, color .15s ease;
  }

  .factuur-tile-download svg{
    width:13px;
    height:13px;
  }

  .factuur-tile-download:hover{
    border-color:var(--accent);
    background:var(--accent);
    color:var(--grad-2);
  }

  /* Gedeelde overlay-basis voor losse schermen (Instellingen, Klant
     toevoegen/bewerken, "nieuwe start"-bevestiging) — gecentreerd,
     donkere achtergrond met blur. Facturen gebruiken dit sinds kort NIET
     meer: die worden nu inline bewerkt in #facturenWerkscherm i.p.v.
     in een overlay, zie bouwFactuurEditorPaneel() in het script. */
  .factuur-modal-overlay{
    display:none;
    position:fixed;
    inset:0;
    background:rgba(5,10,20,0.72);
    backdrop-filter:blur(4px);
    -webkit-backdrop-filter:blur(4px);
    z-index:100;
    align-items:flex-start;
    justify-content:center;
    padding:56px 20px;
    overflow-y:auto;
  }

  .factuur-modal-overlay.is-open{
    display:flex;
  }

  .factuur-modal{
    position:relative;
    width:100%;
    max-width:720px;
  }

  .factuur-modal-close{
    position:absolute;
    top:-44px;
    right:0;
    display:flex;
    align-items:center;
    justify-content:center;
    width:32px;
    height:32px;
    border:1.5px solid var(--border);
    border-radius:8px;
    background:var(--glass-bg);
    backdrop-filter:blur(20px);
    -webkit-backdrop-filter:blur(20px);
    color:var(--text);
    cursor:pointer;
    transition:border-color .15s ease, background-color .15s ease, color .15s ease;
  }

  .factuur-modal-close:hover{
    border-color:var(--accent);
    background:var(--accent);
    color:var(--grad-2);
  }

  .factuur-modal-close svg{
    width:16px;
    height:16px;
  }

  /* Titel + potloodje samen, rechts boven IN de sectie (het formulier
     zelf) i.p.v. los boven de modal zoals de sluitknop — zie
     .klant-modal-bewerk-btn hieronder en openKlantModal()/
     zetKlantModalBewerkbaar() in het script. */
  .klant-modal-kop{
    display:flex;
    align-items:center;
    justify-content:space-between;
    margin-bottom:20px;
  }

  .klant-modal-kop .panel-title{
    margin-bottom:0;
  }

  /* Alleen zichtbaar op een BESTAANDE klant (zie openKlantModal() in het
     script; bij "Nieuwe klant" is er niets "nog niet bewerkbaars" om te
     ontgrendelen) — zelfde ronde-icoon-knop-stijl als
     .dashboard-klanten-nieuw-icoon-btn. */
  .klant-modal-bewerk-btn{
    display:flex;
    align-items:center;
    justify-content:center;
    flex-shrink:0;
    width:28px;
    height:28px;
    border:1px solid var(--border);
    border-radius:50%;
    background:none;
    color:var(--text-muted);
    cursor:pointer;
    transition:border-color .15s ease, background-color .15s ease, color .15s ease;
  }

  .klant-modal-bewerk-btn svg{
    width:14px;
    height:14px;
  }

  .klant-modal-bewerk-btn:hover{
    border-color:var(--accent);
    background:rgba(57,255,136,0.1);
    color:var(--accent);
  }

  .klant-modal-bewerk-btn[hidden]{
    display:none;
  }

  /* --- Instellingen-modal (uren-instellingen) --- */
  /* Verticaal nav-menu links + content rechts — zie de HTML-comment bij
     #instellingenModalOverlay. Op smalle schermen stapelt de nav boven de
     content (zelfde soort veiligheidsnet als eerder bij .header-right). */
  .instellingen-layout{
    display:flex;
    gap:24px;
    margin-top:24px;
  }

  .instellingen-nav{
    display:flex;
    flex-direction:column;
    gap:2px;
    flex-shrink:0;
    width:170px;
  }

  .instellingen-nav-item{
    text-align:left;
    padding:10px 12px;
    border:none;
    border-radius:8px;
    background:transparent;
    color:var(--text-muted);
    font-family:var(--sans);
    font-size:13px;
    font-weight:700;
    cursor:pointer;
    transition:background-color .15s ease, color .15s ease;
  }

  .instellingen-nav-item:hover{
    color:var(--text);
    background:rgba(247,247,255,0.05);
  }

  .instellingen-nav-item.is-active{
    color:var(--grad-2);
    background:var(--accent);
  }

  .instellingen-content{
    flex:1;
    min-width:0;
  }

  @media (max-width:560px){
    .instellingen-layout{
      flex-direction:column;
    }
    .instellingen-nav{
      flex-direction:row;
      width:100%;
      overflow-x:auto;
    }
  }

  .instellingen-sectie{
    margin-top:20px;
  }

  .instellingen-sectie:first-of-type{
    margin-top:0;
  }

  .instellingen-rij{
    display:flex;
    align-items:center;
    justify-content:space-between;
    gap:16px;
    padding:8px 0;
    border-top:0.5px solid var(--border);
  }

  .instellingen-rij:first-child{
    border-top:none;
    padding-top:0;
  }

  .instellingen-rij-label{
    font-size:13px;
    color:var(--text);
    flex:1;
    min-width:0;
  }

  .instellingen-rij .number-spinner-wrap{
    max-width:110px;
    flex-shrink:0;
  }

  /* Zelfde opmaak als .page-hero-nieuw-btn ("Nieuw") — dit is ook een
     neutrale, niet-primaire actie. Twee-klikken-bevestiging (zie de
     click-listener in het script) zet 'm kort om naar de rode
     "bevestig"-staat, zelfde patroon als .saved-indicatie-verwijderen. */
  .instellingen-herstel-btn{
    display:inline-flex;
    align-items:center;
    gap:6px;
    margin-top:24px;
    padding:8px 14px;
    border:0.5px solid var(--border);
    border-radius:8px;
    background:transparent;
    color:var(--text);
    font-family:var(--sans);
    font-size:12.5px;
    font-weight:700;
    cursor:pointer;
    transition:border-color .15s ease, background-color .15s ease, color .15s ease;
  }

  .instellingen-herstel-btn svg{
    width:14px;
    height:14px;
    flex-shrink:0;
  }

  .instellingen-herstel-btn:hover{
    border-color:var(--accent);
    background:var(--accent);
    color:var(--grad-2);
  }

  .instellingen-herstel-btn.is-bevestigen{
    border-color:#ff5c5c;
    background:#ff5c5c;
    color:#1a0505;
  }

  .instellingen-herstel-btn.is-bevestigen:hover{
    opacity:0.85;
  }

  .klant-modal-acties{
    display:flex;
    align-items:center;
    justify-content:flex-end;
    margin-top:28px;
  }

  /* [hidden] als attribuutselector moet expliciet — anders wint
     "display:flex" hierboven van de standaard [hidden]-regel van de
     browser (zelfde valkuil als eerder bij .page-hero-acties e.d.). Zonder
     dit zou de Opslaan-knop zichtbaar blijven in de vergrendelde staat
     (zie zetKlantModalBewerkbaar() in het script). */
  .klant-modal-acties[hidden]{
    display:none;
  }

  /* Initialen-avatar in het klantenoverzicht (zie bouwKlantRow() in het
     script) — geen foto-upload, puur een gekleurde cirkel met initialen,
     zelfde ingetogen accent-tint als .saved-indicatie-badge.is-offerte
     elders, i.p.v. een nieuw kleurenpalet te introduceren voor iets wat
     verder geen functie heeft dan herkenbaarheid in de lijst. */
  .klant-avatar{
    position:relative;
    display:flex;
    align-items:center;
    justify-content:center;
    flex-shrink:0;
    width:36px;
    height:36px;
    border-radius:50%;
    overflow:hidden;
    background:rgba(57,255,136,0.12);
    color:var(--accent);
    font-size:12px;
    font-weight:700;
  }

  /* Profielfoto i.p.v. initialen — zie bouwKlantAvatar(): als klant.foto
     gezet is (data-URL, client-side verkleind bij upload, zie
     verwerkGekozenKlantFoto() in het script) komt hier een <img> overheen
     i.p.v. de tekst-initialen. */
  .klant-avatar img{
    position:absolute;
    inset:0;
    width:100%;
    height:100%;
    object-fit:cover;
  }

  /* Foto-rij bovenaan het klant-modal — grotere variant van dezelfde
     .klant-avatar (initialen-fallback blijft identiek werken, alleen de
     afmeting wijkt af), met ernaast de wijzig/verwijder-knopjes. */
  .klant-modal-foto-rij{
    display:flex;
    align-items:center;
    gap:14px;
    margin-bottom:20px;
  }

  .klant-modal-foto-preview{
    width:64px;
    height:64px;
    font-size:18px;
  }

  /* Zelfde foto-rij hergebruikt in de factuur-klantsectie (zie
     bouwFactuurKlantSectie()) — daar zit 'm al in een flex-column met
     gap (.factuur-editor-velden), dus de eigen margin-bottom hierboven
     zou een dubbele afstand geven. */
  .factuur-editor-velden .klant-modal-foto-rij{
    margin-bottom:0;
  }

  .klant-modal-foto-knoppen{
    display:flex;
    flex-direction:column;
    gap:4px;
    align-items:flex-start;
  }

  .klant-modal-foto-btn{
    background:none;
    border:none;
    padding:0;
    font-family:var(--sans);
    font-size:12.5px;
    font-weight:600;
    color:var(--text-muted);
    cursor:pointer;
    text-decoration:underline;
    text-underline-offset:2px;
  }

  .klant-modal-foto-btn:hover{
    color:var(--text);
  }

  .klant-modal-foto-btn.is-verwijder:hover{
    color:#ff6b6b;
  }

  /* Statistiekenbalk boven het klantenoverzicht — zie
     renderKlantenStats() in het script. Bewust maar twee kaarten, beide
     puur afgeleid van bestaande klantdata (aantal + datum), geen
     omzet-/orderstatistieken: klanten zijn nog niet gekoppeld aan
     specifieke offertes/facturen, dus die cijfers zouden verzonnen zijn. */
  .klanten-stats{
    display:flex;
    flex-wrap:wrap;
    gap:16px;
    margin-bottom:24px;
  }

  .stat-kaart{
    flex:1;
    min-width:160px;
    padding:16px 20px;
    border:1px solid var(--border);
    border-radius:10px;
    background:var(--glass-bg);
    backdrop-filter:blur(20px);
    -webkit-backdrop-filter:blur(20px);
  }

  .stat-kaart-label{
    font-size:11.5px;
    font-weight:700;
    text-transform:uppercase;
    letter-spacing:0.04em;
    color:var(--text-muted);
    margin-bottom:6px;
  }

  .stat-kaart-waarde{
    font-family:var(--mono);
    font-size:24px;
    font-weight:700;
    color:var(--text);
  }

  /* Compacte variant voor de Facturen-stats: twee getallen zijn te weinig
     om twee volle kaarten te vullen (zie renderFacturenStats()) — dit is
     een enkele smalle inline balk i.p.v. de grote .stat-kaart-cards die
     Klanten gebruikt. Alleen de Facturen-tab krijgt deze modifier-class
     erbij (naast .klanten-stats), Klanten blijft ongewijzigd. */
  .facturen-stats-compact{
    display:inline-flex;
    gap:20px;
    padding:10px 18px;
    border:1px solid var(--border);
    border-radius:8px;
    background:var(--glass-bg);
    backdrop-filter:blur(20px);
    -webkit-backdrop-filter:blur(20px);
    margin-bottom:20px;
  }

  .facturen-stats-compact .stat-kaart{
    flex:none;
    min-width:0;
    padding:0;
    border:none;
    border-radius:0;
    background:none;
    backdrop-filter:none;
    -webkit-backdrop-filter:none;
    display:flex;
    align-items:baseline;
    gap:7px;
  }

  .facturen-stats-compact .stat-kaart + .stat-kaart{
    padding-left:20px;
    border-left:1px solid var(--border);
  }

  .facturen-stats-compact .stat-kaart-label{
    font-size:11px;
    margin-bottom:0;
  }

  .facturen-stats-compact .stat-kaart-waarde{
    font-size:15px;
  }

  /* Dashboard (landingspagina, zie #tabPanel-dashboard) — welkomstblok
     met sneltoetsen, een echte statistiekenbalk (hergebruikt gewoon
     .klanten-stats/.stat-kaart, geen nieuwe classes nodig daarvoor), dan
     recente activiteit + het Klanten-paneel rechts. */

  /* Twee kolommen: links alle inhoud onder elkaar, rechts het smallere
     Klanten-paneel. GEEN CSS Grid + align-items:stretch meer (dat leek de
     juiste tool, maar Grid's automatische rij-hoogte is altijd het MAX
     van beide kolommen se natuurlijke inhoudshoogte — met veel klanten
     rekte de hele rij, en dus ook de linkerkolom, gewoon mee, precies het
     "loopt voorbij Recente activiteit"-probleem. In plaats daarvan:
     .dashboard-klanten-kolom hangt absoluut gepositioneerd (top/bottom:0)
     aan deze relatief gepositioneerde container — zijn hoogte volgt dan
     puur uit de afstand tussen top en bottom van dit blok, wat op zijn
     beurt puur bepaald wordt door .dashboard-links-kolom (de enige
     kolom die nog gewoon in de document-flow zit). Geen circulaire
     afhankelijkheid meer: de klantenkolom kan nooit meer de hoogte van
     de linkerkolom beïnvloeden, en scrollt intern (zie
     .dashboard-klanten-strook-lijst) als de klantenlijst niet past. */
  .dashboard-hoofdlayout{
    position:relative;
  }

  .dashboard-links-kolom{
    min-width:0;
    margin-right:324px;
  }

  @media (max-width:860px){
    .dashboard-links-kolom{ margin-right:0; }
  }

  .dashboard-welkom{
    margin-bottom:28px;
  }

  /* Groot en met een groene gradient-vlek erdoorheen — "een stuk groter,
     een soort van dynamische tekst" was de letterlijke vraag. De tekst
     zelf is al dynamisch (ochtend/middag/avond, zie dashboardGroetTekst()
     in het script); de gradient geeft 'm ook visueel wat leven zonder
     animatie/JS. background-clip:text i.p.v. een platte kleur. */
  .dashboard-welkom-titel{
    font-size:44px;
    font-weight:700;
    line-height:1.1;
    margin-bottom:10px;
    background:linear-gradient(100deg, var(--text) 40%, var(--accent) 100%);
    -webkit-background-clip:text;
    background-clip:text;
    color:transparent;
  }

  /* Zonder dit liep "Goedemiddag, Joris" op een telefoonbreedte gewoon
     van het scherm af (44px is voor een 1040px-brede .wrap ontworpen,
     niet voor 375px) — clamp schaalt vloeiend mee tussen 28px (heel
     smal) en de oorspronkelijke 44px (vanaf ~460px breed), i.p.v. een
     harde sprong op één vaste breakpoint. */
  .dashboard-welkom-titel{
    font-size:clamp(28px, 9vw, 44px);
  }

  .dashboard-welkom-sub{
    font-size:14px;
    color:var(--text-muted);
    margin-bottom:24px;
  }

  .dashboard-snelstart-grid{
    display:grid;
    grid-template-columns:repeat(auto-fit, minmax(220px, 1fr));
    gap:12px;
  }

  /* Icoon BOVEN titel/subtekst i.p.v. ernaast — maakt elke knop hoger, en
     daarmee Snelstart als geheel een groter, prominenter onderdeel van het
     Dashboard i.p.v. een smalle rij. Elke knop heeft zijn eigen icoon
     (hetzelfde als elders in de tool voor dat onderdeel, zie de svg's) én
     een subtekst die in één oogopslag zegt wát die actie doet. */
  .dashboard-snelstart-btn{
    display:flex;
    flex-direction:column;
    align-items:flex-start;
    gap:16px;
    padding:22px;
    border:1px solid var(--border);
    border-radius:12px;
    background:var(--glass-bg);
    backdrop-filter:blur(20px);
    -webkit-backdrop-filter:blur(20px);
    color:var(--text);
    font-family:var(--sans);
    text-align:left;
    cursor:pointer;
    transition:border-color .15s ease, background .15s ease, transform .15s ease;
  }

  .dashboard-snelstart-btn:hover{
    border-color:var(--accent);
    background:rgba(57,255,136,0.08);
    transform:translateY(-1px);
  }

  .dashboard-snelstart-icoon{
    display:flex;
    align-items:center;
    justify-content:center;
    flex-shrink:0;
    width:48px;
    height:48px;
    border-radius:50%;
    background:rgba(57,255,136,0.12);
  }

  .dashboard-snelstart-icoon svg{
    width:22px;
    height:22px;
    color:var(--accent);
  }

  .dashboard-snelstart-tekst{
    display:flex;
    flex-direction:column;
    gap:4px;
    min-width:0;
  }

  .dashboard-snelstart-titel{
    font-size:15.5px;
    font-weight:700;
    color:var(--text);
  }

  .dashboard-snelstart-sub{
    font-size:12.5px;
    color:var(--text-muted);
  }

  /* Gedeelde paneelbehandeling — Snelstart/Facturen/Recente activiteit
     zijn alle drie een even zware kaart (glas-achtergrond/border/padding),
     dus één basisklasse i.p.v. dezelfde 7 regels drie keer herhalen. De
     specifieke classes (.dashboard-snelstart-paneel e.d.) blijven puur
     voor eventuele eigen overrides/selectors. */
  .dashboard-paneel{
    margin-bottom:24px;
    padding:24px;
    border:1px solid var(--border);
    border-radius:14px;
    background:var(--glass-bg);
    backdrop-filter:blur(20px);
    -webkit-backdrop-filter:blur(20px);
  }

  .dashboard-paneel .panel-title{
    margin-bottom:16px;
  }

  .dashboard-facturen-paneel .klanten-stats{
    margin-bottom:0;
  }

  /* De compacte statsbalk verliest hier zijn EIGEN kader — het omringende
     .dashboard-paneel geeft al een kader, dus anders staat er een klein
     vak in het grote paneel-vak. De verticale scheidingslijnen tussen de
     4 punten (.facturen-stats-compact .stat-kaart + .stat-kaart, zie
     hierboven) blijven gewoon staan — die zijn niet aan dit kader
     gebonden. */
  /* display:flex + width:100% i.p.v. de standaard inline-flex (die zich
     naar de inhoud voegt) — de 4 stats vullen nu de volle breedte van het
     omringende .dashboard-paneel-kader, i.p.v. links op te hopen met lege
     ruimte rechts. Alleen op het Dashboard: de Facturen-tab's eigen
     statsbalk blijft gewoon compact/inline. */
  .dashboard-facturen-paneel .facturen-stats-compact{
    display:flex;
    width:100%;
    padding:0;
    border:none;
    background:none;
    backdrop-filter:none;
    -webkit-backdrop-filter:none;
  }

  .dashboard-facturen-paneel .facturen-stats-compact .stat-kaart{
    flex:1;
  }

  /* Kleurcodering per status — Overdue in een waarschuwingskleur (dat is
     de status die om actie vraagt), Betaald in de groene accentkleur
     (zelfde taal als .saved-indicatie-badge.is-betaald elders), Wachtend
     bewust neutraal (geen alarmerende kleur voor "nog gewoon binnen
     termijn"). */
  .stat-kaart.is-betaald .stat-kaart-waarde{
    color:var(--accent);
  }

  .stat-kaart.is-overdue .stat-kaart-waarde{
    color:#ff6b6b;
  }

  /* Klanten-kolom rechts — volledige verticale lengte van het dashboard
     (zie .dashboard-hoofdlayout hierboven), rijen onder elkaar i.p.v. de
     vorige horizontale chips-strook (paste beter bij een smalle, hoge
     kolom). Zelf de paneelbehandeling (border/achtergrond), flex-column
     zodat de lijst de resterende ruimte vult en de "Alle klanten"-link
     onderaan blijft staan. Zie renderDashboardKlantenStrook()/
     bouwDashboardKlantChip() in het script. */
  .dashboard-klanten-kolom{
    /* Zie de toelichting bij .dashboard-hoofdlayout hierboven — absoluut
       gepositioneerd i.p.v. een gestretchte grid-kolom, zodat de hoogte
       hier zuiver "top:0 tot bottom:0 van de relatieve ouder" is, nooit
       beïnvloed door de eigen inhoud. min-height:0 laat de interne lijst
       (flex:1 + overflow-y:auto hieronder) daadwerkelijk krimpen/scrollen
       i.p.v. de doos op te rekken. */
    position:absolute;
    top:0;
    right:0;
    bottom:0;
    width:300px;
    display:flex;
    flex-direction:column;
    min-height:0;
    padding:20px;
    border:1px solid var(--border);
    border-radius:14px;
    background:var(--glass-bg);
    backdrop-filter:blur(20px);
    -webkit-backdrop-filter:blur(20px);
  }

  @media (max-width:860px){
    .dashboard-klanten-kolom{
      position:static;
      width:auto;
      margin-top:24px;
    }
  }

  .dashboard-klanten-paneel-kop{
    display:flex;
    align-items:center;
    justify-content:space-between;
    margin-bottom:14px;
  }

  .dashboard-klanten-paneel-kop .panel-title{
    margin-bottom:0;
  }

  /* Klein rond icoontje i.p.v. de vorige grote "Nieuwe klant"-knop —
     zelfde soort hover-state als de andere icoon-knoppen elders in de
     tool (accentkleur + lichte glow). */
  .dashboard-klanten-nieuw-icoon-btn{
    display:flex;
    align-items:center;
    justify-content:center;
    flex-shrink:0;
    width:28px;
    height:28px;
    border:1px solid var(--border);
    border-radius:50%;
    background:none;
    color:var(--text-muted);
    cursor:pointer;
    transition:border-color .15s ease, background-color .15s ease, color .15s ease;
  }

  .dashboard-klanten-nieuw-icoon-btn svg{
    width:15px;
    height:15px;
  }

  .dashboard-klanten-nieuw-icoon-btn:hover{
    border-color:var(--accent);
    background:rgba(57,255,136,0.1);
    color:var(--accent);
  }

  .dashboard-klanten-strook-alles-btn{
    align-self:flex-start;
    margin-top:14px;
    border:none;
    background:none;
    color:var(--text-muted);
    font-family:var(--sans);
    font-size:12.5px;
    font-weight:700;
    cursor:pointer;
    transition:color .15s ease;
  }

  .dashboard-klanten-strook-alles-btn:hover{
    color:var(--accent);
  }

  .dashboard-klanten-strook-lijst{
    display:flex;
    flex-direction:column;
    gap:6px;
    flex:1;
    min-height:0;
    overflow-y:auto;
  }

  .dashboard-klanten-strook-chip{
    display:flex;
    align-items:center;
    gap:10px;
    padding:8px;
    border:1px solid transparent;
    border-radius:10px;
    background:rgba(247,247,255,0.03);
    color:var(--text);
    font-family:var(--sans);
    font-size:13px;
    font-weight:600;
    cursor:pointer;
    text-align:left;
    width:100%;
    transition:border-color .15s ease, background-color .15s ease;
  }

  .dashboard-klanten-strook-chip:hover{
    border-color:var(--accent);
    background:rgba(57,255,136,0.08);
  }

  .dashboard-klanten-strook-chip .klant-avatar{
    width:28px;
    height:28px;
    font-size:10.5px;
    flex-shrink:0;
  }

  .dashboard-klanten-strook-chip-naam{
    min-width:0;
    overflow:hidden;
    text-overflow:ellipsis;
    white-space:nowrap;
  }

  /* Compacte rij voor "Recente activiteit" — hergebruikt de bestaande
     info/klant-rij/badge/meta-opmaak (.saved-indicatie-info e.d., zie
     bouwDashboardRecentRij() in het script) binnen een eigen, simpelere
     rij-wrapper, zonder verwijderknop: dit is puur een glanceable
     lijstje dat doorklikt naar het echte overzicht, geen beheerhandeling
     hier. */
  .dashboard-recent-rij{
    display:flex;
    align-items:center;
    justify-content:space-between;
    gap:12px;
    padding:12px 0;
    border-bottom:1px solid var(--border);
  }

  .dashboard-recent-rij:last-child{
    border-bottom:none;
  }

  /* Zoekveld boven het klantenoverzicht — filtert live op naam/e-mail/
     contactpersoon, zie renderKlantenGrid() in het script. Icoon
     absoluut gepositioneerd binnen het invulveld i.p.v. een apart
     element ernaast, zelfde soort truc als .number-spinner-suffix
     elders. */
  .klanten-zoek-wrap{
    position:relative;
    max-width:480px;
    margin-bottom:20px;
  }

  /* Zoekbalk + "Nieuwe ..."-knop(pen) naast elkaar — Prijscalculator-,
     Facturen- en Klanten-overzicht delen deze rij nu allemaal (de knoppen
     stonden voorheen los bovenaan de pagina, in de page-hero). Binnen de
     rij verliest .klanten-zoek-wrap zijn eigen margin-bottom (de rij zelf
     regelt de afstand tot het grid eronder); flex-wrap zodat het op
     smalle schermen niet overloopt. */
  .overzicht-zoek-rij{
    display:flex;
    flex-wrap:wrap;
    align-items:center;
    gap:12px;
    margin-bottom:20px;
  }

  .overzicht-zoek-rij .klanten-zoek-wrap{
    margin-bottom:0;
  }

  /* Duwt de "+ Nieuwe ..."-knop(pen) helemaal naar rechts, los van het
     zoekveld — zo blijft de pagina als geheel uitgelijnd (rechts hoort
     bij de acties, net als .page-hero-top voorheen). Werkt ook met 2
     knoppen achter elkaar (Prijscalculator): margin-left:auto op de
     EERSTE knop na het zoekveld duwt die knop (en daarmee alles wat erna
     komt, in normale flow) als groep naar rechts. */
  .overzicht-zoek-rij > .klanten-zoek-wrap + *{
    margin-left:auto;
  }

  /* input[type="text"] (niet gewoon "input") — nodig om de generieke
     "select, input[type=text], ...{padding:9px 10px}"-regel verderop in
     dit bestand te verslaan: die staat later in de stylesheet en heeft
     dezelfde specificiteit als een kale ".klanten-zoek-wrap input" zou
     hebben, dus zou anders bij een gelijkspel winnen (en padding-left
     terugzetten naar 10px, met het zoekicoontje er middenin). */
  .klanten-zoek-wrap input[type="text"]{
    padding-left:36px;
  }

  .klanten-zoek-icon{
    position:absolute;
    top:50%;
    left:12px;
    transform:translateY(-50%);
    width:15px;
    height:15px;
    color:var(--text-muted);
    pointer-events:none;
  }

  /* Kaart-grid i.p.v. de rijen-lijst die de rest van de tool voor
     opgeslagen items gebruikt — leest sneller bij veel klanten, en elke
     kaart heeft meer ruimte voor contactgegevens dan een enkele
     meta-regel in een rij zou toelaten. auto-fill+minmax laat het aantal
     kolommen vanzelf meeschalen met de beschikbare breedte. */
  .klanten-grid{
    display:grid;
    grid-template-columns:repeat(auto-fill, minmax(240px, 1fr));
    gap:16px;
  }

  .klanten-grid .saved-indicaties-empty{
    grid-column:1 / -1;
  }

  /* Prijscalculator-overzicht: Prijsindicaties/Offertes als twee losse,
     horizontaal scrollende secties i.p.v. één gemengd grid met een
     status-filter erboven — zie de UX-opdracht "2." en
     renderCalculatorGrid() in het script. */
  .overzicht-horizontaal-sectie{
    margin-bottom:28px;
  }

  .overzicht-horizontaal-titel{
    font-size:15px;
    font-weight:700;
    color:var(--text);
    margin:0 0 12px;
  }

  .klanten-grid-horizontaal{
    display:flex;
    gap:16px;
    overflow-x:auto;
    padding-bottom:6px;
  }

  .klanten-grid-horizontaal .klant-kaart{
    flex:0 0 280px;
    width:280px;
  }

  .klant-kaart{
    display:flex;
    flex-direction:column;
    gap:14px;
    padding:20px;
    border:1px solid var(--border);
    border-radius:10px;
    background:var(--glass-bg);
    backdrop-filter:blur(20px);
    -webkit-backdrop-filter:blur(20px);
  }

  /* Hele kaart klikbaar i.p.v. een los "Bekijken"-knopje onderaan (zie
     bouwFactuurOverzichtKaart()) — zelfde hover-taal (accentrand) als de
     andere klikbare elementen op het Dashboard. */
  .klant-kaart-klikbaar{
    cursor:pointer;
    transition:border-color .15s ease;
  }

  .klant-kaart-klikbaar:hover{
    border-color:var(--accent);
  }

  /* Accentrand links op een Prijscalculator-overzichtkaart (zie
     bouwIndicatieKaart()) — bovenop de al bestaande Indicatie/Offerte-
     badge, zodat het onderscheid ook zonder de badgetekst te lezen
     meteen opvalt. */
  .calculator-kaart.is-offerte-kaart{
    border-left:3px solid var(--accent);
  }

  .calculator-kaart.is-indicatie-kaart{
    border-left:3px solid var(--border);
  }

  .klant-kaart-top{
    display:flex;
    align-items:flex-start;
    gap:12px;
  }

  .klant-kaart-info{
    flex:1;
    min-width:0;
  }

  /* Scoped override van .saved-indicatie-klant-rij (elders vast één
     regel breed) — titel links, badge(s) rechts op dezelfde regel (zie
     de UX-opdracht "1. Uniforme overzichtskaarten"), en in een kaart-
     grid-kolom die zo smal als 240px kan zijn, is er niet altijd genoeg
     ruimte voor naam + badge op één regel zonder de naam tot onleesbaars
     af te knippen — laat de badge(s) dan liever naar een eigen regel
     eronder vallen. */
  .klant-kaart-info .saved-indicatie-klant-rij{
    justify-content:space-between;
    flex-wrap:wrap;
  }

  /* Groepeert meerdere badges bij elkaar als één flex-item (i.p.v. los
     los meetellen in de justify-content:space-between hierboven), zodat
     ze samen rechts staan i.p.v. los over de rij verspreid. */
  .klant-kaart-badges{
    display:flex;
    align-items:center;
    gap:6px;
    flex-shrink:0;
  }

  .klant-kaart-naam{
    font-size:14px;
    font-weight:700;
    color:var(--text);
    overflow:hidden;
    text-overflow:ellipsis;
    white-space:nowrap;
  }

  .klant-kaart-meta{
    font-size:11.5px;
    color:var(--text-muted);
    margin-top:2px;
  }

  /* Bedrag onderaan de kaart, rechts uitgelijnd — bewust prominenter dan
     de andere regels (dit is het kerncijfer van de kaart), zie de
     UX-opdracht "1.": "Het bedrag (groot en vet gedrukt) rechtsonder". */
  .klant-kaart-bedrag{
    font-size:15px;
    font-weight:700;
    color:var(--text);
    text-align:right;
    margin-top:2px;
  }

  .klant-kaart-details{
    display:flex;
    flex-direction:column;
  }

  .klant-kaart-detail-rij{
    display:flex;
    justify-content:space-between;
    gap:12px;
    padding:7px 0;
    border-top:0.5px solid var(--border);
    font-size:12.5px;
  }

  .klant-kaart-detail-rij:first-child{
    border-top:none;
    padding-top:0;
  }

  .klant-kaart-detail-label{
    flex-shrink:0;
    color:var(--text-muted);
  }

  .klant-kaart-detail-waarde{
    min-width:0;
    color:var(--text);
    text-align:right;
    overflow:hidden;
    text-overflow:ellipsis;
    white-space:nowrap;
  }

  /* Actierij onderaan een Prijscalculator-overzichtkaart (zie
     bouwIndicatieKaart()) — "Openen" en, bij offertes, "Factureren"/"1x"
     ernaast. .saved-indicatie-acties zelf is van huis uit voor een smalle
     rij bedoeld; hier, in een kaart die zo smal als 240px kan zijn, laten
     de knoppen liever wrappen en gelijk verdelen dan overflowen. */
  .klant-kaart-acties{
    flex-wrap:wrap;
  }

  .klant-kaart-acties .btn-indicatie-laden{
    flex:1;
    text-align:center;
  }

  /* Rood i.p.v. de groene accentkleur van de rest van de rail — bewust
     afwijkend: uitloggen is geen "normale" actie zoals opslaan, dus mag
     er ook anders uitzien. Erft de icoon+label-opbouw/afmetingen van
     .historie-btn (zie hierboven), overschrijft alleen de kleuren. */
  .sidebar-uitloggen-btn{
    color:#ff8080;
  }

  .sidebar-uitloggen-btn:hover{
    background:rgba(255,92,92,0.12);
    color:#ff5c5c;
  }

  /* Bewerkscherm voor één factuur: velden links, compacte live preview
     rechts — exact dezelfde tweekoloms-opzet + kolombreedte als .layout
     op de Prijscalculator-tab (formulier + sticky bon). Zie
     bouwFactuurEditorPaneel()/bouwFactuurCompactPreview() in het
     script — de preview is bewust GEEN wit A4-document, maar een
     donkere .result-panel-achtige samenvatting, zodat dit scherm zich
     als onderdeel van de tool voelt i.p.v. als vroegtijdige PDF-preview.
     Het echte witte document (buildFactuurDocument()) bestaat alleen in
     het verborgen print-only blok en krijgt z'n paginastijl pas bij het
     downloaden zelf, via .print-actief/@media print verderop — niet via
     een eigen "kaart"-class, die was puur voor de oude on-screen
     weergave en is met deze verandering vervallen. */
  .factuur-editor-layout{
    display:grid;
    grid-template-columns: 1fr 360px;
    gap:24px;
    align-items:start;
  }

  @media (max-width: 860px){
    .factuur-editor-layout{ grid-template-columns: 1fr; }
  }

  .factuur-editor-velden{
    display:flex;
    flex-direction:column;
    gap:20px;
    /* Grid-kolommen krijgen impliciet minmax(auto,1fr) — zonder
       min-width:0 weigert deze kolom te krimpen onder de intrinsieke
       breedte van z'n inhoud, met paginabrede overflow tot gevolg zodra
       .factuur-editor-layout bij 860px naar één kolom omschakelt
       (kostte een echte overflow-bug voor dit min-width:0 hier stond). */
    min-width:0;
  }

  .factuur-editor-preview-kolom{
    position:sticky;
    top:24px;
    min-width:0;
  }

  /* Onder de bon i.p.v. tussen de invoervelden (zie bouwFactuurEditorPaneel()
     in het script) — .factuur-editor-preview-kolom is geen flex-container,
     dus zonder eigen marge zou dit vinkje direct tegen de bon aan plakken. */
  .factuur-betaald-toggle{
    margin-top:16px;
  }

  /* "Klant"-kop + gekozen-klant/kiezer eronder samen in een krappere
     eigen gap (zie bouwFactuurKlantSectie() in het script) — anders staan
     kop en inhoud even ver uit elkaar als tussen twee VOLLEDIG losse
     secties (.factuur-editor-velden's eigen gap:20px), terwijl ze
     duidelijk bij elkaar horen. */
  .factuur-klant-sectie{
    display:flex;
    flex-direction:column;
    gap:10px;
  }

  .factuur-editor-koprij{
    display:flex;
    align-items:center;
    gap:12px;
  }

  .factuur-editor-koptitel{
    flex:1;
    min-width:0;
    font-size:15px;
    font-weight:700;
    color:var(--text);
  }

  .factuur-editor-kopbedrag{
    font-family:var(--mono);
    font-size:15px;
    font-weight:700;
    color:var(--accent);
  }

  /* Verzenddatum/betaaldatum met een kalender-icoontje IN het veld —
     zelfde truc als .klanten-zoek-wrap/.klanten-zoek-icon elders (icoon
     absoluut gepositioneerd i.p.v. een apart element ernaast). */
  .factuur-datumveld-wrap{
    position:relative;
  }

  .factuur-datumveld-icoon{
    position:absolute;
    top:50%;
    left:12px;
    transform:translateY(-50%);
    width:15px;
    height:15px;
    color:var(--text-muted);
    pointer-events:none;
  }

  /* Specificiteit-fix, zelfde reden als .klanten-zoek-wrap
     input[type="text"] elders: verslaat de generieke
     "input[type=text]{padding:9px 10px}"-regel bij een gelijkspel. */
  .factuur-datumveld-wrap input[type="text"]{
    padding-left:36px;
  }

  /* Betaaldatum is alleen-lezen (altijd verzenddatum + betaaltermijn,
     zie berekenBetaaldatum() in het script) — geen <input>, maar een
     <div> met dezelfde maat/opmaak als de wél-bewerkbare velden
     ernaast, zodat de rij visueel in balans blijft. Gedempte tekstkleur
     + niet-tekst-cursor signaleren "dit is geen invoerveld". */
  .factuur-datumveld-readonly-waarde{
    padding:9px 10px 9px 36px;
    border:1px solid var(--border);
    border-radius:6px;
    background:var(--input-bg);
    font-family:var(--sans);
    font-size:14px;
    color:var(--text-muted);
    cursor:default;
  }

  /* Compacte on-screen preview — GEEN wit A4-document, maar dezelfde
     donkere "bon"-stijl als .result-panel op de Prijscalculator-tab
     (glass-bg, blur, mono font). Hergebruikt bewust exact dezelfde
     classes als de bon (.receipt-head/.result-price/.breakdown e.d.)
     i.p.v. een nieuw ontwerp — zie bouwFactuurCompactPreview() in het
     script. Het echte, witte PDF-document (buildFactuurDocument) komt
     pas tevoorschijn bij downloaden, via het verborgen print-only blok. */
  .factuur-compact-titel{
    font-size:14px;
    font-weight:700;
    color:var(--text);
    margin-bottom:16px;
  }

  .factuur-compact-klant{
    font-size:13px;
    color:var(--text-muted);
    margin-bottom:18px;
  }

  .factuur-compact-datums{
    display:flex;
    gap:16px;
    margin-bottom:18px;
  }

  .factuur-compact-datum{
    flex:1;
    min-width:0;
    display:flex;
    align-items:flex-start;
    gap:8px;
  }

  .factuur-compact-datum svg{
    width:15px;
    height:15px;
    flex-shrink:0;
    margin-top:2px;
    color:var(--text-muted);
  }

  .factuur-compact-datum-waarde{
    font-size:12.5px;
    color:var(--text);
    overflow:hidden;
    text-overflow:ellipsis;
    white-space:nowrap;
  }

  /* Regels-editor: elke regel als rij met omschrijving/aantal/bedrag +
     verwijderknop, plus een "+ regel toevoegen"-knop eronder — alleen
     getoond als de factuur GEEN gekoppelde offerte heeft (handmatig
     aangemaakt, zie maakLegeFactuur()); is die koppeling er wel, dan
     blijven regels read-only (zie .factuur-regels-readonly hieronder) om
     de garantie te
     behouden dat de factuur exact bij de offerte blijft aansluiten. */
  .factuur-regel-rij{
    display:flex;
    gap:8px;
    align-items:center;
    margin-bottom:8px;
  }

  /* ".factuur-regel-rij input.klasse" i.p.v. kale ".klasse" — nodig om
     de generieke "input[type=text/number]{width:100%}"-regel verderop in
     dit bestand te verslaan: "input.klasse" alléén (0,1,1) is een
     gelijkspel met "input[type=...]" (ook 0,1,1), en zou dan alsnog
     verliezen op source-order. De ouder-klasse ervoor toevoegen tilt de
     specificiteit naar (0,2,1) — zelfde aanpak als .klanten-zoek-wrap
     input[type="text"] elders. */
  .factuur-regel-rij input.factuur-regel-omschrijving{
    flex:1;
    min-width:0;
    width:auto;
  }

  .factuur-regel-rij input.factuur-regel-aantal{
    width:64px;
    flex-shrink:0;
  }

  .factuur-regel-rij input.factuur-regel-bedrag{
    width:96px;
    flex-shrink:0;
  }

  .factuur-regel-toevoegen-btn{
    margin-top:4px;
    padding:0;
    border:none;
    background:none;
    font-family:var(--sans);
    font-size:12.5px;
    font-weight:700;
    color:var(--text-muted);
    cursor:pointer;
  }

  .factuur-regel-toevoegen-btn:hover{
    color:var(--accent);
  }

  .factuur-regels-readonly .factuur-regel-rij{
    display:grid;
    grid-template-columns: 1fr 48px 84px;
    gap:8px;
    padding:8px 0;
    border-bottom:1px solid var(--border);
    font-size:13px;
    color:var(--text);
  }

  .factuur-regels-readonly .factuur-regel-rij span:nth-child(2){
    text-align:center;
    color:var(--text-muted);
  }

  .factuur-regels-readonly .factuur-regel-rij span:nth-child(3){
    text-align:right;
    font-family:var(--mono);
  }

  /* Kleine "andere factuur"-terugknop boven de editor, alleen zichtbaar
     als een factuurset twee facturen heeft (zie bouwFacturenTegelKiezer()
     in het script) — zelfde stijl als .facturen-terug-link naar het
     overzicht, hier één niveau dieper. */
  .factuur-tegel-terug-link{
    margin-bottom:20px;
  }

  .factuur-table{
    width:100%;
    border-collapse:collapse;
    margin:24px 0;
  }

  .factuur-table th,
  .factuur-table td{
    padding:9px 8px;
    border-bottom:1px solid rgba(13,13,13,0.12);
    font-size:13px;
    text-align:right;
  }

  .factuur-table th:first-child,
  .factuur-table td:first-child{
    text-align:center;
  }

  .factuur-table th:nth-child(2),
  .factuur-table td:nth-child(2){
    text-align:left;
  }

  .factuur-table th{
    font-size:11px;
    font-weight:700;
    text-transform:uppercase;
    letter-spacing:0.04em;
    color:rgba(13,13,13,0.55);
    border-bottom:2px solid var(--ink);
  }

  .factuur-table td{
    color:var(--ink);
  }

  .factuur-betaalinfo{
    margin-top:20px;
  }

  .factuur-betaalinfo p{
    margin:0 0 4px;
    font-size:11.5px;
    color:rgba(13,13,13,0.65);
    line-height:1.5;
  }

  .factuur-betaalinfo p:last-child{
    margin-bottom:0;
  }

  .factuur-footer{
    margin-top:32px;
    padding-top:16px;
    border-top:1px solid rgba(13,13,13,0.12);
    font-size:11px;
    line-height:1.6;
    color:rgba(13,13,13,0.55);
  }

  /* Generieke uitklap-sectiestijl (<details>/<summary>) — gebruikt door
     de Instellingen-modal (Projecttypes/Opleveringen/Merkmiddelen/
     Reviserondes, zie .instellingen-sectie ernaast in de HTML). Ondanks
     de naam niet meer factuur-specifiek: de factuurnummer-editor die
     deze classes oorspronkelijk introduceerde is vervangen door het
     altijd-zichtbare .factuur-editor-layout hierboven. */
  .factuur-editor summary{
    cursor:pointer;
    font-size:11.5px;
    font-weight:700;
    text-transform:uppercase;
    letter-spacing:0.04em;
    color:var(--text-muted);
  }

  .factuur-editor summary:hover{
    color:var(--text);
  }

  .factuur-editor-inner{
    margin-top:16px;
  }

  .factuur-editor-inner .field{
    margin-bottom:0;
  }

  .factuur-editor-inner .field-label{
    font-size:11px;
    font-weight:700;
    color:var(--text-muted);
    margin-bottom:4px;
  }

  .factuur-editor-inner input[type="text"]{
    max-width:220px;
  }

  /* Volle-breedte "eerste stap" boven het formulier — zie de HTML-comment
     bij .documenttype-panel. Iets meer verticale ruimte dan de gewone
     .panel + .panel-regel (20px) omdat dit een aparte, voorafgaande
     beslissing is, geen paneel in dezelfde rij/kolom als de rest. */
  .documenttype-panel{
    margin-bottom:28px;
  }

  .layout{
    display:grid;
    grid-template-columns: 1fr 360px;
    gap:24px;
    align-items:start;
  }

  @media (max-width: 860px){
    .layout{ grid-template-columns: 1fr; }
  }

  /* QR Generator-tab (zie js/qr.js) — zelfde 2-koloms/glassmorphism-opzet
     als .layout hierboven (invoer-kolom links, sticky .bon-kolom rechts
     met de live preview), maar als eigen class i.p.v. .layout zelf
     hergebruikt: dit tabblad staat volledig los van de Prijscalculator,
     een gedeelde class zou een schijn-koppeling suggereren die er niet is. */
  .studio-editor-layout{
    display:grid;
    grid-template-columns: 1fr 360px;
    gap:24px;
    align-items:start;
  }

  @media (max-width: 860px){
    .studio-editor-layout{ grid-template-columns: 1fr; }
  }

  /* Kleurenpicker (natief input[type=color], vast vierkant) + hex-
     tekstveld ernaast — zie koppelKleurVelden() in js/qr.js, die de twee
     synchroon houdt. */
  .qr-kleur-rij{
    display:flex;
    align-items:center;
    gap:10px;
  }

  .qr-kleur-rij input[type="color"]{
    flex-shrink:0;
    width:40px;
    height:36px;
    padding:2px;
    border:1px solid var(--border);
    border-radius:6px;
    background:transparent;
    cursor:pointer;
  }

  .qr-kleur-hex{
    flex:1;
    min-width:0;
    font-family:var(--mono);
    text-transform:uppercase;
  }

  .qr-logo-rij{
    display:flex;
    align-items:center;
    gap:10px;
  }

  /* Omkadert de live QR-code in het bonnetje, zelfde glassmorphism-kader
     als de rest — svg/canvas (qr-code-styling kan beide renderen, hier
     bewust type:"svg" voor haarscherpe weergave, zie js/qr.js) krijgt
     zijn eigen maximale breedte zodat 'ie nooit buiten het paneel valt. */
  .qr-preview-wrap{
    display:flex;
    align-items:center;
    justify-content:center;
    min-height:280px;
    margin:20px 0;
  }

  .qr-preview-wrap svg,
  .qr-preview-wrap canvas,
  .qr-preview-wrap img{
    max-width:100%;
    height:auto;
  }

  .qr-download-rij{
    display:flex;
    flex-wrap:wrap;
    gap:8px;
  }

  .qr-download-rij .btn-indicatie-laden{
    flex:1;
    text-align:center;
  }

  /* .panel is nu alleen nog de KALE basis (radius, verder niets) — de
     invoerpanelen in .invoer-kolom/.documenttype-panel gebruiken 'm zo,
     zonder kaart-omlijsting, zodat het formulier als één doorlopende
     kolom "ademt". Panelen die WEL omlijnd moeten blijven (bon, modals,
     Instellingen, inlogscherm) krijgen daarnaast de .panel-framed
     modifier, die de oude achtergrond/blur/rand/padding teruglegt. */
  .panel{
    border-radius:10px;
  }

  /* Oude .panel-opmaak, nu een aparte, expliciet toe te voegen modifier
     i.p.v. de standaard voor élk .panel-element. Zie hierboven. */
  .panel-framed{
    background:var(--glass-bg);
    backdrop-filter:blur(20px);
    -webkit-backdrop-filter:blur(20px);
    border:1px solid var(--border);
    padding:24px;
  }

  .panel + .panel{
    margin-top:20px;
  }

  /* Koptitel voor een hele paneel-sectie (i.t.t. .field-label, dat op
     los-veldniveau werkt) — bijv. "Klantgegevens", "Producttype",
     "Tarieven & instellingen". Zelfde gedempte kleur als .field-hint
     e.d. elders in het bestand, voor een naadloze aansluiting. */
  .panel-title{
    font-family:var(--sans);
    font-weight:700;
    font-size:13px;
    letter-spacing:0.06em;
    text-transform:uppercase;
    color:var(--text-muted);
    margin:0 0 16px 0;
  }

  /* Wrapt de drie linkerkolom-panelen (Klantgegevens, Producttype,
     Tarieven & instellingen) samen zodat .layout nog steeds precies
     twee directe kinderen heeft — deze kolom + .bon-kolom — en de
     bestaande grid-regels van .layout ongewijzigd blijven werken. De
     .panel + .panel-regel hierboven zou bovenop deze gap nog eens
     20px margin toevoegen; die wordt hier dus genulld zodat alleen de
     gap de ruimte tussen de panelen bepaalt. */
  .invoer-kolom{
    display:flex;
    flex-direction:column;
    gap:28px;
  }

  .invoer-kolom > .panel + .panel{
    margin-top:0;
  }

  .field{
    margin-bottom:20px;
  }

  .field:last-child{
    margin-bottom:0;
  }

  /* Conceptualiserings- en productie-uurtarief horen inhoudelijk bij
     elkaar (twee helften van hetzelfde uurtarief) en staan daarom samen
     in een rij — zelfde idee als .optional-fields-row bij KVK/BTW-nummer
     hierboven. Alle andere velden in dit paneel (ook PM/overleg-opslag
     en Starterskorting) zijn simpele, volledige-breedte .field-blokken
     zoals de rest van het formulier, voor een consistent ritme. */
  .field-row-2{
    display:flex;
    gap:16px;
    margin-bottom:20px;
  }

  .field-row-2 .field{
    flex:1;
    min-width:0;
    margin-bottom:0;
  }

  @media (max-width:640px){
    .field-row-2{
      flex-direction:column;
      gap:20px;
    }
  }

  /* Starterskorting: toggle-row (checkbox + label) vervangt hier de
     normale .field-label — het percentageveld verschijnt er pas onder
     zodra de toggle aanstaat (zelfde is-hidden-gedachte als bij het
     Opleveringen-veld hierboven, alleen dan voor het invulveld i.p.v.
     het hele blok), zie starterskortingToggle-a in het script. */
  .field-starterskorting .rate-row{
    display:none;
    margin-top:10px;
  }

  .field-starterskorting.is-actief .rate-row{
    display:flex;
  }

  /* Opleveringen-veld is pas zichtbaar zodra er een projecttype gekozen
     is — zie onProjecttypeChange() onderin het script. */
  .field.is-hidden{
    display:none;
  }

  label.field-label{
    display:block;
    font-size:12.5px;
    font-weight:700;
    color:var(--text);
    margin-bottom:6px;
  }

  /* Ruimte tussen het klantpaneel en het formulier — stond eerst in de
     (inmiddels verwijderde) knoppenrij boven dit blok. */
  #optionsWrap{
    margin-top:32px;
  }


  .field-hint{
    font-size:11.5px;
    color:var(--text-muted);
    font-weight:400;
    margin-top:4px;
  }

  /* Titel + subtekst links, invulbox rechts uitgelijnd — voor velden
     waar de toelichting te veel ruimte inneemt om onder een smalle box
     te blijven staan (bijv. Content/copy-aanlevering). De tekstkolom
     krijgt de vrije ruimte (flex:1), de box blijft compact en plakt
     tegen de rechterkant. */
  .field-inline-hint{
    display:flex;
    align-items:flex-start;
    justify-content:space-between;
    gap:20px;
  }

  .field-inline-hint-text{
    flex:1;
    min-width:0;
  }

  .field-inline-hint-text .field-label{
    margin-bottom:4px;
  }

  .field-inline-hint-text .field-hint{
    margin-top:0;
  }

  .field-inline-hint .rate-row{
    flex:none;
    margin-top:2px;
  }

  @media (max-width:640px){
    .field-inline-hint{
      flex-direction:column;
      align-items:stretch;
      gap:10px;
    }
  }

  select, input[type="text"], input[type="number"], input[type="email"], input[type="password"], input[type="date"]{
    width:100%;
    padding:9px 10px;
    border:1px solid var(--border);
    border-radius:6px;
    background:var(--input-bg);
    font-family:var(--sans);
    font-weight:400;
    font-size:14px;
    color:var(--text);
  }

  /* Vergrendelde staat van het klant-modal (zie zetKlantModalBewerkbaar()
     in het script) — readonly (niet disabled, zie de toelichting daar)
     verliest hier zijn rand/achtergrond en oogt zo als platte tekst i.p.v.
     een invoerveld, maar blijft gewoon selecteerbaar/kopieerbaar. De
     foto-knoppen ZIJN disabled (geen tekst om te kopiëren) en krijgen de
     gebruikelijke gedimde behandeling. */
  #klantModalForm input[readonly]{
    padding-left:0;
    padding-right:0;
    border-color:transparent;
    background:transparent;
    cursor:default;
  }

  #klantModalForm .klant-modal-foto-btn:disabled{
    opacity:0.5;
    cursor:not-allowed;
  }

  /* color-scheme:dark laat de browser zelf een donker kalender-popup +
     wit kalender-icoontje tekenen i.p.v. het standaard donkere icoontje
     dat anders onzichtbaar zou zijn tegen deze donkere achtergrond. */
  input[type="date"]{
    color-scheme:dark;
  }

  /* Eigen pijltje i.p.v. het native browser-pijltje — dat bleef
     ondanks extra padding-right tegen de rand van de box clippen
     (browser-afhankelijk, niet via padding te sturen). Nu volledig
     zelf getekend en gepositioneerd, dus altijd genoeg ruimte. */
  select{
    appearance:none;
    -webkit-appearance:none;
    -moz-appearance:none;
    padding-right:40px;
    background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23f7f7ff' stroke-opacity='0.6' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
    background-repeat:no-repeat;
    background-position:right 12px center;
    background-size:14px 14px;
  }

  select option{
    background:var(--panel);
    color:var(--text);
  }

  select:focus, input:focus{
    outline:2px solid var(--accent);
    outline-offset:-1px;
  }

  /* Eigen omhoog/omlaag-knopjes voor number-inputs i.p.v. de native
     (witte, niet te stylen) spinner-pijltjes — zie voegSpinnerToe() in
     het script, dat elk number-input hierin wrapt. */
  .number-spinner-wrap{
    position:relative;
    display:flex;
    width:100%;
  }

  .number-spinner-wrap input[type="number"]{
    padding-right:28px;
  }

  /* Native spinner-pijltjes verbergen (Chrome/Safari + Firefox). */
  .number-spinner-wrap input[type="number"]::-webkit-inner-spin-button,
  .number-spinner-wrap input[type="number"]::-webkit-outer-spin-button{
    appearance:none;
    -webkit-appearance:none;
    margin:0;
  }
  .number-spinner-wrap input[type="number"]{
    -moz-appearance:textfield;
  }

  .number-spinner-knoppen{
    position:absolute;
    top:1px;
    right:1px;
    bottom:1px;
    width:22px;
    display:flex;
    flex-direction:column;
    border-left:1px solid var(--border);
    border-radius:0 5px 5px 0;
    overflow:hidden;
  }

  .number-spinner-knop{
    flex:1;
    display:flex;
    align-items:center;
    justify-content:center;
    padding:0;
    border:none;
    border-bottom:1px solid var(--border);
    background:transparent;
    color:var(--text-muted);
    cursor:pointer;
    transition:background-color .15s ease, color .15s ease;
  }

  .number-spinner-knop:last-child{
    border-bottom:none;
  }

  .number-spinner-knop svg{
    width:9px;
    height:9px;
    pointer-events:none;
  }

  .number-spinner-knop:hover{
    background:rgba(57,255,136,0.12);
    color:var(--accent);
  }

  .number-spinner-knop:active{
    background:rgba(57,255,136,0.22);
  }

  /* Eenheid ("%") inline in de invulbox zelf i.p.v. als los tekstje
     ernaast — zie voegInlineSuffixToe() in het script. Zo eindigt de box
     zelf rechts (naast de op-/neer-pijltjes), en lijnt de rand netjes
     uit i.p.v. dat er nog los tekst voorbij de rand hangt. */
  .number-spinner-wrap.has-suffix input[type="number"]{
    padding-right:52px;
  }

  .number-spinner-suffix{
    position:absolute;
    top:0;
    bottom:0;
    right:30px;
    display:flex;
    align-items:center;
    font-size:12.5px;
    color:var(--text-muted);
    pointer-events:none;
  }

  .rate-row .number-spinner-wrap{
    max-width:120px;
  }

  /* --- BTW-toggle (gedeeld, geldt voor alle opties) --- */
  .toggle-row{
    display:flex;
    align-items:center;
    gap:8px;
    cursor:pointer;
    font-size:12.5px;
    font-weight:700;
    color:var(--text);
  }

  /* Custom checkbox-uiterlijk (i.p.v. de native browser-checkbox) zodat
     hij bij de rest van de huisstijl past: donkere achtergrond, iets
     afgeronde hoeken, groen vinkje bij :checked. Geldt voor zowel de
     opleveringen-checklist als de toggle-rijen (BTW, KVK). */
  .toggle-row input[type="checkbox"],
  .checklist input[type="checkbox"]{
    appearance:none;
    -webkit-appearance:none;
    width:16px;
    height:16px;
    border-radius:4px;
    border:1px solid var(--border);
    background:var(--input-bg);
    position:relative;
    flex-shrink:0;
    cursor:pointer;
    transition:background-color .15s ease, border-color .15s ease;
  }

  .toggle-row input[type="checkbox"]:checked,
  .checklist input[type="checkbox"]:checked{
    background:var(--accent);
    border-color:var(--accent);
  }

  .toggle-row input[type="checkbox"]:checked::after,
  .checklist input[type="checkbox"]:checked::after{
    content:"";
    position:absolute;
    left:5px;
    top:2px;
    width:4px;
    height:8px;
    border:solid var(--grad-2);
    border-width:0 2px 2px 0;
    transform:rotate(45deg);
  }

  .toggle-row input[type="checkbox"]:focus,
  .checklist input[type="checkbox"]:focus{
    outline:2px solid var(--accent);
    outline-offset:1px;
  }

  .page-hero-acties{
    display:flex;
    align-items:center;
    gap:10px;
    flex-shrink:0;
  }

  /* [hidden] als attribuutselector moet expliciet, anders wint
     "display:flex" hierboven van de UA-stylesheet (zelfde valkuil als
     eerder bij .bewerkt-banner). */
  .page-hero-acties[hidden]{
    display:none;
  }

  /* De titel van de geopende factuur/prijsindicatie/offerte — helemaal
     bovenaan het werkscherm, direct onder "← Overzicht" (zie
     #facturenWerkscherm/#calculatorWerkscherm in de HTML,
     .facturen-terug-link hieronder komt daar meteen boven te staan).
     #projectNaam is hier bewust meegenomen: dat IS de titel op de
     Prijscalculator-tab (verplaatst uit Klantgegevens, zie de
     UX-opdracht "5."), geen los tweede veld. Vervangt de generieke
     paginatitel zodra je een item opent (zie #pageHeroTitelRij/
     wisselTab() in het script). In rust volledig onzichtbaar als veld —
     puur tekst, geen rand/achtergrond/outline. Pas bij hover/focus
     verschijnt een kader OM de tekst (verder niets, geen achtergrond-
     vulling) — dát is het enige signaal dat dit, ondanks de kop-achtige
     opmaak, een bewerkbaar veld is. */
  #facturenTitelInput,
  #projectNaam{
    display:block;
    width:100%;
    margin-bottom:20px;
    padding:6px 10px;
    margin-left:-10px;
    border:1px solid transparent;
    border-radius:8px;
    background:transparent;
    outline:none;
    color:var(--text);
    font-family:var(--sans);
    /* Zelfde reden als .dashboard-welkom-titel — 26px was voor desktop-
       breedte getekend, schaalt hier vloeiend mee naar beneden op een
       telefoonscherm. */
    font-size:clamp(19px, 6vw, 26px);
    font-weight:700;
    transition:border-color .15s ease;
  }

  #facturenTitelInput::placeholder,
  #projectNaam::placeholder{
    color:var(--text-muted);
  }

  #facturenTitelInput:hover,
  #facturenTitelInput:focus,
  #projectNaam:hover,
  #projectNaam:focus{
    border-color:var(--border);
  }

  /* Primaire CTA van de hero: opgevuld groen, altijd (niet pas bij
     hover) — dit is de belangrijkste actie op de Prijscalculator-tab. */
  .page-hero-opslaan-btn{
    display:inline-flex;
    align-items:center;
    gap:7px;
    padding:8px 16px;
    border:0.5px solid var(--accent);
    border-radius:8px;
    background:transparent;
    color:var(--accent);
    font-family:var(--sans);
    font-size:12.5px;
    font-weight:700;
    cursor:pointer;
    transition:background-color .15s ease, color .15s ease;
  }

  .page-hero-opslaan-btn svg{
    width:14px;
    height:14px;
  }

  .page-hero-opslaan-btn:hover{
    background:var(--accent);
    color:var(--grad-2);
  }

  /* [hidden] als attribuutselector moet expliciet — zonder deze regel
     wint display:inline-flex hierboven van de standaard [hidden]-regel
     van de browser, en blijft de knop zichtbaar ook als 'ie hidden is.
     Zelfde valkuil als eerder bij .bevestig-modal-overlay/.page-hero-acties. */
  .page-hero-opslaan-btn[hidden]{
    display:none;
  }

  /* --- Opgeslagen prijsindicaties (Supabase) --- */
  .saved-indicaties-empty{
    font-size:13px;
    color:var(--text-muted);
    margin:0;
  }

  .saved-indicatie-info{
    flex:1;
    min-width:0;
  }

  .saved-indicatie-klant-rij{
    display:flex;
    align-items:center;
    gap:7px;
    min-width:0;
  }

  .saved-indicatie-klant{
    font-size:13.5px;
    font-weight:700;
    color:var(--text);
    overflow:hidden;
    text-overflow:ellipsis;
    white-space:nowrap;
  }

  /* Onderscheidt prijsindicatie/offerte-rijen — nodig zodra "Opslaan"
     bij elke klant automatisch allebei aanmaakt (zie
     opslaanPrijsindicatie()), dus er meestal twee rijen met dezelfde
     klantnaam naast elkaar staan. Offerte iets nadrukkelijker (accent-
     kleur) omdat dat het "echte", bruikbare document is. */
  .saved-indicatie-badge{
    flex-shrink:0;
    padding:2px 7px;
    border-radius:5px;
    background:rgba(247,247,255,0.08);
    color:var(--text-muted);
    font-size:10px;
    font-weight:700;
    text-transform:uppercase;
    letter-spacing:0.03em;
    white-space:nowrap;
  }

  .saved-indicatie-badge.is-offerte{
    background:rgba(57,255,136,0.12);
    color:var(--accent);
  }

  /* Betaalstatus op een factuurkaart (zie bouwFactuurOverzichtKaart()) —
     "Openstaand" blijft de neutrale/grijze standaardstijl hierboven,
     "Betaald" krijgt dezelfde groene accentbehandeling als .is-offerte. */
  .saved-indicatie-badge.is-betaald{
    background:rgba(57,255,136,0.12);
    color:var(--accent);
  }

  /* Overdue-badge op een factuurkaart (zie bouwFactuurOverzichtKaart(),
     berekenFactuurStatus()) — zelfde waarschuwingskleur als de Overdue-
     KPI op het Dashboard. "Wachtend" heeft bewust GEEN eigen kleur —
     valt terug op de neutrale standaardstijl hierboven, want "nog gewoon
     binnen de betaaltermijn" hoeft niet op te vallen. */
  .saved-indicatie-badge.is-overdue{
    background:rgba(255,107,107,0.15);
    color:#ff6b6b;
  }

  /* Factuur-badge in "Recente activiteit" op het Dashboard (zie
     bouwDashboardRecentRij()) — derde, eigen kleur naast de neutrale
     Indicatie-badge (standaardstijl hierboven) en groene Offerte-badge
     (.is-offerte), zodat alle drie de types in één lijst uit elkaar te
     houden zijn zonder de tekst te hoeven lezen. */
  .saved-indicatie-badge.is-factuur{
    background:rgba(96,165,250,0.15);
    color:#7dabf5;
  }

  .saved-indicatie-meta{
    font-size:11.5px;
    color:var(--text-muted);
    margin-top:2px;
  }

  .btn-indicatie-laden{
    flex-shrink:0;
    padding:6px 12px;
    border-radius:6px;
    border:0.5px solid var(--accent);
    background:transparent;
    color:var(--accent);
    font-family:var(--sans);
    font-size:12px;
    font-weight:700;
    cursor:pointer;
    transition:border-color .15s ease, color .15s ease;
  }

  .btn-indicatie-laden:hover{
    opacity:0.8;
  }

  /* Wrapt "Openen" + (bij offertes) "Factureren"/"1x" samen — gebruikt in
     bouwIndicatieKaart() (zie ook .klant-kaart-acties, die er samen met
     deze class op zit voor het kaart-specifieke wrap-/flex:1-gedrag). */
  .saved-indicatie-acties{
    display:flex;
    flex-shrink:0;
    gap:8px;
  }

  /* Opgevuld i.p.v. outline — dit is, zodra een offerte er eenmaal is,
     de logische VERVOLGSTAP (offerte gewonnen → factureren), dus
     nadrukkelijker dan het neutrale "Openen" ernaast. Zelfde accentkleur-
     op-vulling-patroon als .page-hero-opslaan-btn:hover/.inlog-submit-btn
     elders in de tool. */
  .btn-indicatie-factureren{
    border-color:var(--accent);
    background:var(--accent);
    color:var(--grad-2);
  }

  .btn-indicatie-factureren:hover{
    opacity:0.85;
  }

  /* Klein prullenbak-icoontje links van de tekst i.p.v. een losse
     "Verwijderen"-knop rechts — zelfde twee-klikken-bevestiging (zie
     bouwVerwijderKnop() in het script), nu via kleur/title i.p.v. tekst. */
  .saved-indicatie-verwijderen{
    display:flex;
    align-items:center;
    justify-content:center;
    flex-shrink:0;
    width:26px;
    height:26px;
    padding:0;
    border:none;
    border-radius:6px;
    background:transparent;
    color:var(--text-muted);
    cursor:pointer;
    transition:background-color .15s ease, color .15s ease;
  }

  .saved-indicatie-verwijderen svg{
    width:14px;
    height:14px;
  }

  .saved-indicatie-verwijderen:hover{
    background:rgba(255,92,92,0.12);
    color:#ff5c5c;
  }

  .saved-indicatie-verwijderen.is-bevestigen{
    background:#ff5c5c;
    color:#1a0505;
  }

  .saved-indicatie-verwijderen.is-bevestigen:hover{
    background:#ff5c5c;
    color:#1a0505;
    opacity:0.85;
  }

  .checklist{
    display:flex;
    flex-direction:column;
    gap:8px;
  }

  .checklist label{
    display:flex;
    align-items:center;
    gap:8px;
    font-size:14px;
    font-weight:400;
    cursor:pointer;
  }

  .checklist label span{
    flex:1;
    min-width:0;
  }


  .checklist .other-text{
    /* width:100% uit de generieke input-regel + margin-left:24px zou de
       rand 24px voorbij de rest van het paneel laten uitsteken (box-
       sizing:border-box telt de margin niet mee in "100%") — daarom
       hier expliciet 24px van de breedte aftrekken zodat de rechterkant
       gelijk uitlijnt met de rest van het formulier. */
    width:calc(100% - 24px);
    margin-left:24px;
    margin-top:4px;
  }

  /* Aantal-veldje: inline naast de tekst, alleen zichtbaar zodra de
     bijbehorende checkbox is aangevinkt (geen JS nodig voor het
     tonen/verbergen, puur via de :checked-status van de checkbox). */
  .checklist .aantal-input{
    display:none;
    flex-shrink:0;
    width:52px;
    padding:4px 6px;
    font-size:12.5px;
  }

  /* Native spinner-pijltjes verbergen — bij 52px breed is er geen
     ruimte voor de eigen omhoog/omlaag-knopjes (zie voegSpinnerToe()),
     maar de oude witte native pijltjes horen ook niet meer bij de rest
     van de huisstijl. Typen/pijltjestoetsen blijven gewoon werken. */
  .checklist .aantal-input::-webkit-inner-spin-button,
  .checklist .aantal-input::-webkit-outer-spin-button{
    appearance:none;
    -webkit-appearance:none;
    margin:0;
  }
  .checklist .aantal-input{
    -moz-appearance:textfield;
  }

  .checklist input[type="checkbox"]:checked ~ .aantal-input{
    display:inline-block;
  }

  /* De grove-optie-select (indicatie-modus, zie buildChecklist()) deelt
     de .aantal-input-class puur voor de tonen/verbergen-regel hierboven
     (die werkt op class, niet op tag, dus dekt 'm deze select ook) — de
     vaste 52px-breedte daarvan is voor een getal bedoeld, niet voor
     leesbare tekst als "Klein pakket". */
  .checklist select.aantal-input{
    width:auto;
    min-width:130px;
  }

  .rate-row{
    display:flex;
    align-items:center;
    gap:10px;
  }

  .rate-row .prefix{
    font-size:14px;
    color:var(--text-muted);
  }

  .rate-row input{
    max-width:120px;
  }

  /* Gedeelde glassmorphism klant-badge — getoond zodra een klant gekozen
     is in bouwKlantSectie() (Prijscalculator- én Facturen-werkscherm, zie
     de UX-opdracht "3."). Vervangt de vroegere klant-kiezer-rij +
     losstaande, vrij bewerkbare velden. */
  .klant-badge{
    display:flex;
    align-items:flex-start;
    gap:12px;
    padding:14px;
    border:1px solid var(--border);
    border-radius:10px;
    background:var(--glass-bg);
    backdrop-filter:blur(20px);
    -webkit-backdrop-filter:blur(20px);
    position:relative;
  }

  .klant-badge-avatar{
    width:48px;
    height:48px;
    flex-shrink:0;
    border:1.5px solid var(--accent);
  }

  .klant-badge-info{
    flex:1;
    min-width:0;
    padding-right:110px;
  }

  .klant-badge-naam{
    font-size:15px;
    font-weight:700;
    color:var(--text);
    overflow:hidden;
    text-overflow:ellipsis;
    white-space:nowrap;
  }

  .klant-badge-detail{
    font-size:12px;
    color:var(--text-muted);
    margin-top:3px;
    overflow:hidden;
    text-overflow:ellipsis;
    white-space:nowrap;
  }

  .klant-badge-pills{
    display:flex;
    flex-wrap:wrap;
    gap:6px;
    margin-top:8px;
  }

  .klant-badge-pill{
    padding:2px 7px;
    border-radius:5px;
    background:rgba(247,247,255,0.08);
    color:var(--text-muted);
    font-size:10px;
    font-weight:700;
    letter-spacing:0.02em;
    white-space:nowrap;
  }

  /* Rechtsboven in de badge, subtiel (geen volle knop-stijl) — zie de
     UX-opdracht "3.": "RECHTSBOVEN: een subtiele knop". */
  .klant-badge-wijzig-btn{
    position:absolute;
    top:14px;
    right:14px;
    padding:4px 9px;
    border:0.5px solid var(--border);
    border-radius:6px;
    background:transparent;
    color:var(--text-muted);
    font-family:var(--sans);
    font-size:11px;
    font-weight:600;
    cursor:pointer;
    transition:border-color .15s ease, color .15s ease;
  }

  .klant-badge-wijzig-btn:hover{
    border-color:var(--accent);
    color:var(--accent);
  }

  /* Op smalle schermen is er geen ruimte naast de naam/adresgegevens
     voor de absoluut-gepositioneerde knop hierboven (.klant-badge-info's
     vaste padding-right:110px) — dat duwde 'm letterlijk van het scherm
     af. Op mobiel wordt de knop een gewoon, rechts uitgelijnd blokje
     ONDER de klantgegevens i.p.v. ernaast. */
  @media (max-width:480px){
    .klant-badge{
      flex-wrap:wrap;
    }
    .klant-badge-info{
      padding-right:0;
    }
    .klant-badge-wijzig-btn{
      position:static;
      margin-left:auto;
      margin-top:8px;
    }
  }

  /* Downloadknop van de bon (#downloadPdfBtn) — puur icoon, geen tekst,
     geen zichtbare box in rust. Alleen bij hover verschijnt het groene
     vlak, zodat 'm niet als een "echte" knop oogt totdat je 'm nadert. */
  .btn-download-icon{
    display:inline-flex;
    align-items:center;
    justify-content:center;
    width:32px;
    height:32px;
    border:1px solid transparent;
    border-radius:8px;
    background:transparent;
    color:var(--accent);
    cursor:pointer;
    transition:border-color .15s ease, background-color .15s ease, color .15s ease;
  }

  /* [hidden] als attribuutselector moet expliciet — anders wint
     "display:inline-flex" hierboven van de browser-standaard
     [hidden]{display:none} (zelfde valkuil als eerder bij
     .page-hero-nieuw-btn/.page-hero-acties/.bewerkt-banner/etc.). Was tot
     nu toe nooit nodig (deze knop stond altijd vast zichtbaar, bijv.
     #downloadPdfBtn) — #qrLogoVerwijderBtn (js/qr.js) is de eerste die
     'm dynamisch verbergt/toont. */
  .btn-download-icon[hidden]{
    display:none;
  }

  .btn-download-icon svg{
    width:15px;
    height:15px;
  }

  .btn-download-icon:hover{
    border-color:var(--accent);
    background:var(--accent);
    color:var(--grad-2);
  }

  /* Visueel verborgen, maar wel voorgelezen door schermlezers — zie
     https://webaim.org/techniques/css/invisiblecontent/ */
  .sr-only{
    position:absolute;
    width:1px;
    height:1px;
    padding:0;
    margin:-1px;
    overflow:hidden;
    clip:rect(0,0,0,0);
    white-space:nowrap;
    border:0;
  }

  /* --- resultaat kolom (bonnetje) --- */
  /* Documenttype + bonnetje samen: de sticky-regel staat op deze
     wrapper (i.p.v. op .result-col zelf), zodat Documenttype mee omhoog
     "vastklikt" en meescrollt met de bon, als één blok. Zelfde breedte
     als de bon vanzelf, want dit is de tweede kolom van .layout
     (grid-template-columns: 1fr 360px). */
  .bon-kolom{
    position:sticky;
    top:24px;
    display:flex;
    flex-direction:column;
    gap:24px;
  }

  .result-panel{
    position:relative;
    background:var(--glass-bg);
    border:1px solid var(--border);
    color:var(--text);
    font-family:var(--mono);
    padding:26px 26px 30px;
    border-radius:10px;
    box-shadow:0 20px 36px rgba(5,14,28,0.45), 0 2px 6px rgba(5,14,28,0.28);
    backdrop-filter:blur(20px);
    -webkit-backdrop-filter:blur(20px);
  }

  .receipt-head{
    display:flex;
    align-items:center;
    justify-content:space-between;
    gap:12px;
    padding-bottom:16px;
    margin-bottom:18px;
    border-bottom:1px dashed var(--border);
  }

  .receipt-head > svg{
    height:16px;
    width:auto;
    display:block;
    color:var(--soft-lavender);
  }

  .receipt-head-right{
    display:flex;
    align-items:center;
    gap:10px;
  }

  .receipt-head .receipt-date{
    font-family:var(--mono);
    font-size:11px;
    color:var(--text-muted);
    white-space:nowrap;
  }

  .result-block{
    text-align:left;
  }

  .result-label{
    font-size:11.5px;
    font-weight:700;
    text-transform:uppercase;
    letter-spacing:0.04em;
    color:var(--text-muted);
    margin-bottom:2px;
  }

  .result-hours{
    font-size:20px;
    font-weight:700;
    color:var(--text);
    margin-bottom:16px;
  }

  .result-price{
    font-size:27px;
    font-weight:700;
    letter-spacing:-0.02em;
    color:var(--accent);
    margin-bottom:4px;
    line-height:1.2;
  }

  .result-price.is-hidden{
    display:none;
  }

  /* Offerteprijs, rechtstreeks bewerkbaar op de bon (i.p.v. via een los
     invulveld) — als klik-om-te-bewerken: in rust is het niet meer dan
     tekst (exact zelfde lettertype/-grootte/kleur als .result-price
     hierboven), het invulveld zelf verschijnt pas ná een klik erop — zie
     offertePrijsKlikOmTeBewerken() in het script voor de show/hide-
     logica (.is-editing hieronder). */
  .result-price-edit.is-hidden{
    display:none;
  }

  .result-price-display{
    display:inline-block;
    font-size:27px;
    font-weight:700;
    letter-spacing:-0.02em;
    color:var(--accent);
    margin-bottom:4px;
    line-height:1.2;
    cursor:pointer;
    border-bottom:1.5px dashed transparent;
  }

  .result-price-display:hover,
  .result-price-display:focus{
    border-bottom-color:var(--accent);
    outline:none;
  }

  .result-price-edit.is-editing .result-price-display{
    display:none;
  }

  .result-price-input-wrap{
    display:none;
    align-items:baseline;
    gap:3px;
    margin-bottom:4px;
  }

  .result-price-edit.is-editing .result-price-input-wrap{
    display:flex;
  }

  .result-price-input-wrap .prefix{
    font-size:27px;
    font-weight:700;
    color:var(--accent);
  }

  /* Hogere specificiteit dan de generieke "input[type=number]"-regel
     hierboven (die anders wint en de volledige-breedte kader-opmaak
     erdoorheen zou drukken) — vandaar telkens .result-price-input-wrap
     ervoor i.p.v. alleen de klasse op het input-element zelf. Bewust
     compact (geen bon-breedte): dit veld is alleen zichtbaar tijdens
     het bewerken van één kort getal. */
  .result-price-input-wrap input.result-price-input{
    width:5ch;
    max-width:90px;
    font-family:var(--sans);
    font-size:27px;
    font-weight:700;
    letter-spacing:-0.02em;
    color:var(--accent);
    background:transparent;
    border:none;
    border-radius:0;
    padding:0 0 2px;
    border-bottom:1.5px solid var(--accent);
    line-height:1.2;
  }

  .result-price-input-wrap input.result-price-input:focus{
    outline:none;
  }

  .result-price-input-wrap input.result-price-input::-webkit-inner-spin-button,
  .result-price-input-wrap input.result-price-input::-webkit-outer-spin-button{
    appearance:none;
    -webkit-appearance:none;
    margin:0;
  }
  .result-price-input-wrap input.result-price-input{
    -moz-appearance:textfield;
  }

  .result-richtprijs{
    font-size:12.5px;
    font-weight:400;
    color:var(--text-muted);
    margin-bottom:20px;
  }

  .result-empty-hint{
    font-size:12.5px;
    font-weight:400;
    color:var(--text-muted);
    font-style:italic;
  }

  /* Leesbare "wat lever ik op"-lijst — hergebruikt exact dezelfde
     opleveringenLabels-array als de PDF-tabel (zie recalculate()), hier
     als losse labels boven de uitsplitsing i.p.v. verstopt in de
     "Opleveringen (N stuks)"-samenvattingsregel daarin, en i.p.v.
     aaneengeregen tekst die tussen de rest wegvalt. */
  .result-opleveringen-lijst{
    display:flex;
    flex-wrap:wrap;
    gap:6px;
    margin-bottom:20px;
  }

  .result-opleveringen-lijst:empty{
    display:none;
  }

  .result-opleveringen-chip{
    padding:3px 9px;
    border-radius:5px;
    background:rgba(247,247,255,0.08);
    color:var(--text-muted);
    font-size:11px;
    font-weight:600;
    white-space:nowrap;
  }

  .breakdown{
    border-top:1px dashed var(--border);
    padding-top:16px;
  }

  .breakdown-title{
    font-size:11.5px;
    font-weight:700;
    text-transform:uppercase;
    letter-spacing:0.04em;
    color:var(--text-muted);
    margin-bottom:10px;
  }

  .breakdown-list{
    list-style:none;
    margin:0;
    padding:0;
    font-family:var(--mono);
    font-size:12.5px;
  }

  .breakdown-list li{
    display:flex;
    justify-content:space-between;
    gap:12px;
    padding:5px 0;
    border-bottom:1px dashed var(--border);
    color:var(--text);
  }

  .breakdown-list li:last-child{
    border-bottom:none;
  }

  .breakdown-list .val{
    color:var(--text-muted);
    text-align:right;
    white-space:nowrap;
  }

  /* --- PDF-offerte (alleen zichtbaar bij afdrukken/opslaan als PDF) --- */
  /* Drie mogelijke print-documenten (offerte, aanbetalingsfactuur,
     eindfactuur) — allemaal onzichtbaar totdat print_document() vlak
     vóór het printen de class "print-actief" zet op precies degene die
     gedownload wordt (zie het script). */
  #offertePrint, .factuur-print{
    display:none;
  }

  /* Chrome (en de meeste andere browsers) tekent bij "Opslaan als PDF"
     standaard zelf een datum/tijd linksboven en de paginatitel
     rechtsboven, in het systeemlettertype (dus NIET dit ontwerp) — dat
     leest als een storend "ander lettertype bovenin". Die tekst wordt
     alleen in de gereserveerde paginarand getekend; door die rand op 0
     te zetten is er geen ruimte meer om 'm te tonen. De echte marge om
     de inhoud komt gewoon van .print-actief's eigen padding hieronder,
     dus visueel verandert er verder niets. */
  @page{
    margin:0;
  }


  /* Hamburger-knop zelf — position:fixed, ALTIJD boven de rest (ook
     boven de (gesloten) drawer), pas zichtbaar binnen de mobiele
     breakpoint hieronder (display:none als basis-stand, niet [hidden] —
     dit element is al [hidden] tot toonApp(), dat is een aparte,
     eerdere gate, zie de HTML-comment bij #mobielMenuBtn). MOET vóór de
     @media-blok hieronder staan: bij gelijke specificiteit wint de
     LAATSTE regel in de brontekst, dus deze basis-"display:none" zou
     anders de latere "display:flex" in de media query overschrijven
     i.p.v. andersom. */
  .mobiel-menu-btn{
    display:none;
    position:fixed;
    top:16px;
    left:16px;
    z-index:130;
    width:40px;
    height:40px;
    align-items:center;
    justify-content:center;
    border:1px solid var(--border);
    border-radius:8px;
    background:var(--glass-bg);
    backdrop-filter:blur(20px);
    -webkit-backdrop-filter:blur(20px);
    color:var(--text);
    cursor:pointer;
  }

  .mobiel-menu-btn[hidden]{
    display:none;
  }

  .mobiel-menu-btn svg{
    width:20px;
    height:20px;
  }

  /* Mobiele breakpoint: de altijd-zichtbare icoon-rail wordt een
     hamburgermenu — #mobielMenuBtn opent/sluit #appSidebar als een
     drawer die standaard buiten beeld staat (transform, niet
     display:none — zo blijft de sluit-animatie soepel i.p.v. abrupt).
     Zelfde nav-knoppen, geen aparte mobiele markup nodig; alleen de
     PRESENTATIE verandert hier. .app-shell's linker padding (normaal
     gereserveerd voor de vaste 76px-rail) vervalt, want er is nu niets
     meer dat permanent ruimte inneemt. */
  @media (max-width:768px){
    .app-shell{
      padding-left:0;
    }

    /* Zonder dit liep de paginatitel (#pageHeroTitle) of het Dashboard-
       welkomstblok gewoon ONDER de vast-gepositioneerde hamburgerknop
       door (die knop neemt zelf geen ruimte in de flow in, position:
       fixed) — extra top-padding houdt de inhoud er nu netjes onder. */
    .wrap{
      padding-top:72px;
    }

    .mobiel-menu-btn{
      display:flex;
    }

    .sidebar{
      top:0;
      left:0;
      width:min(78vw, 280px);
      transform:translateX(-100%);
      transition:transform .2s ease;
      z-index:120;
    }

    .sidebar:hover{
      /* De hover-uitschuif (76px -> 220px) is een desktop-idee — op
         mobiel is er sowieso geen hover, en de drawer heeft al zijn
         volle .sidebar-breedte (zie hierboven) zodra 'm openstaat. */
      width:min(78vw, 280px);
    }

    .sidebar.is-mobiel-open{
      transform:translateX(0);
    }

    /* Labels/wordmark zijn normaal alleen zichtbaar bij :hover (de
       icoon-rail-logica) — op mobiel is de drawer al breed genoeg voor
       de volledige tekst, dus altijd tonen i.p.v. te wachten op een
       hover-state die op een touchscreen toch niet betrouwbaar bestaat.
       ".sidebar " ervoor is geen typefout — puur om de specificiteit
       gelijk te trekken met de latere basisregel ".sidebar-label{opacity:0}"
       verderop in het bestand (zelfde specificiteit + latere brontekst
       zou anders alsnog winnen, ongeacht deze @media-blok). */
    .sidebar .sidebar-label{
      opacity:1;
    }

    .sidebar .sidebar-logo .wordmark{
      max-width:120px;
      opacity:1;
    }
  }

  /* Donkere overlay achter de open drawer — tikken erop sluit 'm (zie
     mobielMenuSluiten() in het script). pointer-events:none in rust,
     want anders zou dit onzichtbare vlak (opacity:0) toch klikken
     onderscheppen zodra de mobiele breakpoint actief is. */
  .mobiel-menu-backdrop{
    position:fixed;
    inset:0;
    background:rgba(5,10,20,0.6);
    opacity:0;
    pointer-events:none;
    z-index:110;
    transition:opacity .2s ease;
  }

  .mobiel-menu-backdrop.is-open{
    opacity:1;
    pointer-events:auto;
  }

  .mobiel-menu-backdrop[hidden]{
    display:none;
  }

  @media print{
    body{
      background:#ffffff !important;
      padding:0;
      margin:0;
    }
    /* .sidebar zit sinds de app-shell-redesign BUITEN .wrap (zie
       .app-shell hierboven) — deze regel ving 'm dus niet, waardoor de
       vaste icoon-balk (position:fixed, z-index:50) gewoon over elke
       geprinte/gedownloade PDF bleef staan ("raar icoon aan de
       linkerkant"). .app-shell's eigen padding-left (76px, gereserveerd
       voor de sidebar) moet ook mee op 0, anders blijft er een lege
       linkerrand over nu de sidebar zelf weg is. */
    .app-shell{
      padding-left:0 !important;
    }
    .sidebar{
      display:none !important;
    }
    .wrap > *:not(.print-actief){
      display:none !important;
    }
    .print-actief{
      display:block !important;
      max-width:720px;
      margin:0 auto;
      padding:56px 64px;
      color:var(--ink);
      font-family:var(--sans);
    }
    /* Chrome (en de meeste browsers) printen achtergrondkleuren
       standaard NIET mee — alleen tekst/randen — tenzij je dat expliciet
       forceert. Zonder deze regel verdwijnt zowel de grijze TOTAAL-box
       (.offerte-totalbox) als het groene streepje onder het logo
       (.offerte-header-logo::after) uit elke gedownloade PDF, ook al
       zien ze er op scherm (bij het simuleren van deze media-query)
       gewoon goed uit. */
    .print-actief, .print-actief *{
      -webkit-print-color-adjust:exact;
      print-color-adjust:exact;
    }
    /* Voorwaarden mogen nooit direct onder de prijs op dezelfde pagina
       eindigen — altijd een nieuwe pagina, ongeacht hoeveel ruimte er
       nog over is. De scheidingslijn/marge hierboven (zie
       .offerte-voorwaarden, bedoeld om 'm optisch los te zetten VAN de
       prijs erboven op dezelfde pagina) is dan overbodig: bovenaan een
       nieuwe pagina staat er toch niks boven om van te scheiden. */
    .offerte-voorwaarden{
      break-before:page;
      page-break-before:always;
      margin-top:0;
      padding-top:0;
      border-top:none;
    }
  }

  /* Logo links, eigen bedrijfsgegevens rechts (CONFIG.afzender) — beide
     bovenaan uitgelijnd. */
  .offerte-header{
    display:flex;
    justify-content:space-between;
    align-items:flex-start;
    gap:24px;
  }

  .offerte-header-logo svg{
    height:32px;
    width:auto;
    display:block;
    color:var(--ink);
  }

  .offerte-header-logo::after{
    content:"";
    display:block;
    width:48px;
    height:4px;
    margin-top:16px;
    border-radius:2px;
    background:var(--neon-green);
  }

  .offerte-afzender{
    text-align:right;
    font-size:11.5px;
    font-weight:400;
    color:rgba(13,13,13,0.55);
    line-height:1.5;
    white-space:nowrap;
  }

  .offerte-title{
    font-size:28px;
    font-weight:700;
    margin:28px 0 4px;
    color:var(--ink);
  }

  .offerte-client{
    font-size:15px;
    font-weight:700;
    color:var(--ink);
    margin-bottom:6px;
  }

  .offerte-client-details{
    font-size:13px;
    font-weight:400;
    color:rgba(13,13,13,0.6);
    line-height:1.6;
    margin-bottom:6px;
  }

  /* Zet KVK/BTW-nr visueel los van de adresregels erboven — zie
     bouwKlantDetailRegels() in het script. */
  .offerte-client-details-groep{
    margin-top:6px;
  }

  .offerte-meta{
    font-size:13px;
    font-weight:400;
    color:rgba(13,13,13,0.6);
    margin-bottom:28px;
  }

  .offerte-table{
    width:100%;
    border-collapse:collapse;
    margin-bottom:24px;
  }

  .offerte-table td{
    padding:9px 0;
    border-bottom:1px solid rgba(13,13,13,0.12);
    font-size:14px;
    font-weight:400;
    color:var(--ink);
    vertical-align:top;
  }

  .offerte-table td:first-child{
    color:rgba(13,13,13,0.55);
    width:220px;
  }

  .offerte-table td:last-child{
    text-align:right;
  }

  .offerte-totals{
    margin-bottom:32px;
  }

  /* "TOTAAL"-box: label erboven + grote vetgedrukte prijs in een lichte
     kaart, met optioneel een kleine excl./btw/incl.-uitsplitsing ernaast
     — zie bouwTotaalBox() in het script. Neemt de opmaak over van het
     referentie-factuurformat dat als voorbeeld is aangeleverd, gedeeld
     door alle drie de PDF-formats (Prijsindicatie/Offerte/Factuur). */
  .offerte-total-rij{
    display:flex;
    justify-content:space-between;
    align-items:flex-end;
    flex-wrap:wrap;
    gap:24px;
  }

  .offerte-totalbox-label{
    font-size:12px;
    font-weight:700;
    text-transform:uppercase;
    letter-spacing:0.05em;
    color:var(--ink);
    margin-bottom:8px;
  }

  .offerte-totalbox{
    display:inline-block;
    padding:14px 24px;
    border-radius:8px;
    background:#eef1f2;
    font-family:var(--mono);
    font-size:32px;
    font-weight:700;
    color:var(--ink);
    white-space:nowrap;
  }

  .offerte-total-breakdown{
    border-top:1px solid rgba(13,13,13,0.25);
    padding-top:8px;
    min-width:200px;
  }

  .offerte-total-breakdown-rij{
    display:flex;
    justify-content:space-between;
    gap:24px;
    padding:3px 0;
    font-size:13px;
    font-weight:400;
    color:rgba(13,13,13,0.65);
  }

  .offerte-total-breakdown-rij.is-nadruk{
    font-weight:700;
    color:var(--ink);
  }

  .offerte-note{
    font-size:11.5px;
    font-weight:400;
    color:rgba(13,13,13,0.55);
    line-height:1.5;
  }

  .offerte-voorwaarden{
    margin-top:20px;
    padding-top:20px;
    border-top:1px solid rgba(13,13,13,0.12);
  }

  .offerte-voorwaarden-title{
    font-size:11.5px;
    font-weight:700;
    text-transform:uppercase;
    letter-spacing:0.06em;
    color:rgba(13,13,13,0.55);
    margin:0 0 8px;
  }

  .offerte-voorwaarden-list{
    margin:0;
    padding-left:16px;
    list-style:disc;
  }

  .offerte-voorwaarden-list li{
    font-size:11.5px;
    font-weight:400;
    color:rgba(13,13,13,0.55);
    line-height:1.5;
  }

  .offerte-voorwaarden-list li + li{
    margin-top:6px;
  }

  /* Eigendomsoverdracht/annulering-punten: alleen in offerte-modus, zie
     renderOffertePrint() dat de class "is-visible" toevoegt/verwijdert
     op basis van isOfferteModus(). */
  .offerte-voorwaarden--offerte-only{
    display:none;
  }

  .offerte-voorwaarden--offerte-only.is-visible{
    display:list-item;
  }

  /* Betalingscondities (aanbetaling/restbedrag) — per optie, verschijnt
     ná de totaalregel in buildOfferteSection(), alleen in offerte-modus. */
  .offerte-betaling{
    margin-top:20px;
  }

  .offerte-betaling-title{
    font-size:11.5px;
    font-weight:700;
    text-transform:uppercase;
    letter-spacing:0.06em;
    color:rgba(13,13,13,0.55);
    margin:0 0 8px;
  }

  .offerte-betaling-regel{
    font-size:12.5px;
    font-weight:400;
    color:rgba(13,13,13,0.75);
    line-height:1.5;
    margin:0 0 6px;
  }

  .offerte-betaling-regel:last-child{
    margin-bottom:0;
  }

  /* Akkoordblok — statische "print en onderteken"-opmaak, geen
     interactief formulier. Alleen zichtbaar in offerte-modus (zie
     renderOffertePrint()). De regel om te schrijven staat BOVEN de
     lijn (dankzij de gap tussen de blokken); het label staat er vlak
     ONDER, net als bij een fysiek te ondertekenen document. */
  .offerte-akkoord{
    margin-top:32px;
    padding-top:20px;
    border-top:1px solid rgba(13,13,13,0.12);
  }

  .offerte-akkoord-title{
    font-size:11.5px;
    font-weight:700;
    text-transform:uppercase;
    letter-spacing:0.06em;
    color:rgba(13,13,13,0.55);
    margin:0 0 20px;
  }

  .offerte-akkoord-regels{
    display:flex;
    flex-direction:column;
    gap:36px;
    max-width:320px;
  }

  .offerte-akkoord-regel{
    border-top:1px solid rgba(13,13,13,0.3);
    padding-top:6px;
  }

  .offerte-akkoord-regel span{
    font-size:11px;
    font-weight:400;
    color:rgba(13,13,13,0.55);
  }

  /* --- Inlogscherm (Supabase Auth) --- */
  /* Zichtbaar (display:flex) als CSS-default, niet pas via een
     .is-open-klasse — zo staat de overlay er al vóórdat het script is
     ingeladen/uitgevoerd, en kan de rest van de tool nooit even
     onbeschermd zichtbaar flitsen. checkSessieEnStart()/toonApp() in het
     script zetten 'm daarna via inline style.display weer op "none"
     zodra een sessie bevestigd is. */
  .inlog-scherm{
    display:flex;
    position:fixed;
    inset:0;
    z-index:200;
    align-items:center;
    justify-content:center;
    background:rgba(5,10,20,0.86);
    backdrop-filter:blur(4px);
    -webkit-backdrop-filter:blur(4px);
    padding:20px;
  }

  .inlog-panel{
    width:100%;
    max-width:360px;
  }

  .inlog-panel .field:last-of-type{
    margin-bottom:20px;
  }

  .inlog-foutmelding{
    margin:-4px 0 16px;
    padding:12px 14px;
    border:1px solid rgba(255,92,92,0.4);
    border-radius:8px;
    background:rgba(255,92,92,0.08);
    color:#ff8a8a;
    font-size:13px;
    line-height:1.5;
  }

  .inlog-foutmelding[hidden]{
    display:none;
  }

  .inlog-submit-btn{
    width:100%;
    padding:10px 16px;
    border:0.5px solid var(--accent);
    border-radius:8px;
    background:var(--accent);
    color:var(--grad-2);
    font-family:var(--sans);
    font-size:13px;
    font-weight:700;
    cursor:pointer;
    transition:opacity .15s ease;
  }

  .inlog-submit-btn:hover{
    opacity:0.88;
  }
