/* VGR Food · Platform — portaal (login-scherm + kale post-login shell)
   Ontwerprichting: volvlak VGR-navy, traag levende gradient-gloed, glazig paneel.
   Hoogwaardig en rustig — geen template-look, geen drukte. */

/* IBM Plex — de huisstijlfamilie van het hele platform (restyle aug 2026; hiervoor stond
   hier Inter, als enige pagina). Gewicht 300 doet mee: de login-sub gebruikt 'm. */
@import url("https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:wght@300;400;500;600;700&family=IBM+Plex+Mono:wght@400;500;600;700&display=swap");

:root {
  color-scheme: dark;
  /* navy-familie (zelfde stam als dashboards --navy:#2f3a5b) */
  --navy-0: #1b2338;
  --navy-1: #232c47;
  --navy-2: #2f3a5b;
  --navy-3: #3c4a72;
  --ink: #f3f5fa;
  --ink-dim: #b7c0d6;
  --ink-faint: #7e88a3;
  --line: rgba(255, 255, 255, 0.16);
  /* Liquid-glass laag — iteratie 2: veel transparanter ("erdoorheen kijken"), gecombineerd
     met een MATIGE blur (10-14px) i.p.v. de zware 20-26px uit iteratie 1: te veel blur maakt
     melkglas, het doel is dat de bewegende achtergrond-gloed zichtbaar door de tegels heen
     beweegt. Saturate blijft hoog zodat het glas "levendig" blijft i.p.v. grijs. */
  --glass-top: rgba(255, 255, 255, 0.1);
  --glass-bottom: rgba(255, 255, 255, 0.07);
  --glass-blur: blur(12px) saturate(180%);
  /* specular rim: 1px randhighlight, links-boven fel, rechts-onder uitdovend naar transparant */
  --rim-bright: rgba(255, 255, 255, 0.7);
  --rim-dim: rgba(255, 255, 255, 0.08);
  /* accenten uit de dashboards: blauw + koraal */
  --accent-blauw: #4f86ff;
  --accent-koraal: #ff7a59;
  /* licht rood voor op de donkere glass-achtergrond. Heette --st-rood, maar dat is de naam
     van het status-rood in de dashboards (#cf4444) — zelfde naam, andere waarde was een
     stille valkuil (audit 29-08). */
  --rood-zacht: #ff6161;
  --sans: "IBM Plex Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
  --mono: "IBM Plex Mono", ui-monospace, "Cascadia Code", Consolas, monospace;
  --ease-out-soft: cubic-bezier(0.16, 1, 0.3, 1);
}

/* ---------------------------------------------------------------------------
   Liquid-glass specular rim — gedeelde ringtechniek (Apple's "Liquid Glass":
   gelaagde vulling + een felle diagonale randhighlight die rechtsonder wegvalt).
   Gebruikt door .panel, .tegel, .user-menu-dropdown en .tegels-leeg (zelfde
   dekkende gradient-border-truc: padding=ringdikte, mask-composite exclude laat
   alleen de rand staan). Puur decoratief (pointer-events:none), degradeert
   overal netjes (geen @supports nodig — mask-composite heeft brede steun). */
.panel::before,
.tegel::before,
.user-menu-dropdown::before,
.tegels-leeg::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  padding: 1px;
  background: linear-gradient(135deg, var(--rim-bright), var(--rim-dim) 40%, transparent 70%);
  -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  mask-composite: exclude;
  pointer-events: none;
}

* { box-sizing: border-box; }
html, body { margin: 0; height: 100%; }
body {
  background: var(--navy-0);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 15px;
  line-height: 1.45;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}
.hidden { display: none !important; }
[data-lucide] { width: 1em; height: 1em; stroke-width: 2; vertical-align: -0.125em; }

/* ---------------------------------------------------------------------------
   Levende achtergrond: drie grote, traag bewegende radiale gloeden. Puur decor
   (aria-hidden), vast achter alle inhoud, GPU-vriendelijk (transform+opacity). */
.bg-ambient {
  position: fixed;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  /* Puur decor, mag nooit kliks vangen. Zonder dit onderschept een
     position:fixed element met z-index>=0 kliks over NIET-gepositioneerde
     content (CSS-stackingregel: niet-gepositioneerde in-flow content stapelt
     altijd ONDER gepositioneerde content met z-index 0, ongeacht DOM-volgorde
     — bug: /admin-header (Portaal-link/Uitloggen) niet klikbaar). */
  pointer-events: none;
  background:
    radial-gradient(120% 90% at 50% 0%, var(--navy-2) 0%, var(--navy-0) 62%);
}
.bg-ambient .glow {
  position: absolute;
  border-radius: 50%;
  filter: blur(90px);
  opacity: 0.5;
  will-change: transform;
}
/* Iteratie 2: de glazen tegels zijn nu veel transparanter, dus de achtergrond mag iets meer
   visuele interesse hebben zodat er ook echt iets is om doorheen te breken (blauw + koraal
   subtiel sterker/groter dan iteratie 1; --navy blijft ongewijzigd, geeft weinig kleur-contrast). */
.bg-ambient .glow--blauw {
  width: 66vmax;
  height: 66vmax;
  left: -16vmax;
  top: -18vmax;
  background: radial-gradient(circle, var(--accent-blauw) 0%, transparent 70%);
  opacity: 0.6;
  animation: driftA 34s var(--ease-out-soft) infinite alternate;
}
.bg-ambient .glow--koraal {
  width: 54vmax;
  height: 54vmax;
  right: -14vmax;
  bottom: -12vmax;
  background: radial-gradient(circle, var(--accent-koraal) 0%, transparent 72%);
  opacity: 0.44;
  animation: driftB 40s var(--ease-out-soft) infinite alternate;
}
.bg-ambient .glow--navy {
  width: 44vmax;
  height: 44vmax;
  left: 58%;
  top: 34%;
  background: radial-gradient(circle, var(--navy-3) 0%, transparent 74%);
  opacity: 0.55;
  animation: driftC 46s var(--ease-out-soft) infinite alternate;
}
@keyframes driftA {
  0%   { transform: translate(0, 0) scale(1); }
  100% { transform: translate(6vmax, 8vmax) scale(1.12); }
}
@keyframes driftB {
  0%   { transform: translate(0, 0) scale(1); }
  100% { transform: translate(-7vmax, -5vmax) scale(1.08); }
}
@keyframes driftC {
  0%   { transform: translate(-4vmax, 2vmax) scale(1); }
  100% { transform: translate(3vmax, -6vmax) scale(1.15); }
}
@media (prefers-reduced-motion: reduce) {
  .bg-ambient .glow { animation: none !important; }
}

/* ---------------------------------------------------------------------------
   Splash — zichtbaar tot de Supabase-sessie async is hersteld. */
#splash {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 26px;
  background: var(--navy-0);
  transition: opacity 0.4s ease;
}
#splash.out { opacity: 0; pointer-events: none; }
.splash-logo { width: 180px; height: auto; }
.splash-spin {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  border: 3px solid rgba(255, 255, 255, 0.18);
  border-top-color: #fff;
  animation: splashrot 0.8s linear infinite;
}
.splash-sub { margin: 0; font-size: 13px; letter-spacing: 0.02em; color: var(--ink-dim); }
@keyframes splashrot { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .splash-spin { animation: none; } }

/* ---------------------------------------------------------------------------
   Login-scherm */
#login, #wijzigScherm {
  position: relative;
  z-index: 1;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 2rem 1.25rem;
}
.brandmark { display: flex; justify-content: center; margin-bottom: 34px; }
.brandmark img { width: 168px; height: auto; }

/* Glazig paneel — entree: fade-up bij eerste render (display:none → block herstart 'm).
   Liquid Glass: gelaagde witte vulling (lichter bovenin), sterkere blur+saturate, een
   specular rim (::before, zie boven) en een zachte inner sheen bovenin (inset box-shadow). */
.panel {
  position: relative;
  width: 100%;
  max-width: 25rem;
  background: linear-gradient(180deg, var(--glass-top), var(--glass-bottom));
  border: 1px solid transparent;
  border-radius: 28px;
  padding: 2.1rem 2rem 1.9rem;
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  box-shadow:
    0 24px 60px -20px rgba(0, 0, 0, 0.55),
    0 1px 0 rgba(255, 255, 255, 0.14) inset,
    0 -18px 30px -24px rgba(255, 255, 255, 0.3) inset;
  animation: panelIn 0.65s var(--ease-out-soft) both;
}
@keyframes panelIn {
  0%   { opacity: 0; transform: translateY(22px) scale(0.985); }
  100% { opacity: 1; transform: translateY(0) scale(1); }
}
@media (prefers-reduced-motion: reduce) {
  .panel { animation: none; }
}

.panel h2 { margin: 0 0 4px; font-size: 18px; font-weight: 700; color: var(--ink); }
.panel .sub { margin: 0 0 1.5rem; font-size: 13px; color: var(--ink-faint); }

.field { margin-bottom: 1.05rem; }
.field label {
  display: block;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--ink-dim);
  margin-bottom: 0.4rem;
  letter-spacing: 0.01em;
}
.field-input-wrap { position: relative; }
.field input {
  width: 100%;
  padding: 0.72rem 0.85rem;
  /* Glass-on-glass vermijden (Apple-antipatroon): géén eigen backdrop-filter hier — het
     paneel eromheen is al de enige glaslaag, dit is gewoon een effen translucente vulling.
     Radius volgt de concentrische-nesting-regel: buiten-radius (paneel 28px) - padding ≈ deze
     ~12px, kleiner dan de kaart eromheen. */
  background: rgba(10, 16, 32, 0.42);
  border: 1px solid var(--line);
  border-radius: 12px;
  color: var(--ink);
  font: inherit;
  transition: border-color 0.16s ease, box-shadow 0.16s ease, background 0.16s ease;
}
.field input::placeholder { color: var(--ink-faint); }
.field input:focus {
  outline: none;
  border-color: var(--accent-blauw);
  background: rgba(10, 16, 32, 0.6);
  box-shadow: 0 0 0 4px rgba(79, 134, 255, 0.22);
}
.field input[type="password"] { padding-right: 2.6rem; }
/* Secundaire knop (Apple "plain glass"): witte tint ~.08, capsulevorm — geen eigen
   backdrop-filter (zit al op een enkel-glas input, geen tweede blur-laag nodig). */
.pw-toggle {
  position: absolute;
  right: 0.4rem;
  top: 50%;
  transform: translateY(-50%);
  background: rgba(255, 255, 255, 0.08);
  border: 0;
  color: var(--ink-faint);
  cursor: pointer;
  padding: 0.4rem;
  border-radius: 999px;
  display: flex;
  align-items: center;
  transition: color 0.15s ease, background 0.15s ease;
}
.pw-toggle:hover { color: var(--ink); background: rgba(255, 255, 255, 0.14); }
.pw-toggle:focus-visible { outline: 2px solid var(--accent-blauw); outline-offset: 2px; }

/* Knop — Apple "glassProminent": een capsule met een TRANSLUCENTE blauwe tint over glas-blur
   (niet meer een dekkende gradient-balk). Specular rim (::before) blijft. Hover = tint iets
   op + zachte buitenglow, press = scale(.97) (spinner-gedrag ongewijzigd). */
.submit-btn {
  position: relative;
  width: 100%;
  margin-top: 0.6rem;
  padding: 0.85rem;
  border: 1px solid transparent;
  border-radius: 999px;
  background: linear-gradient(135deg, rgba(79, 141, 240, 0.38), rgba(79, 141, 240, 0.3));
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  color: #fff;
  font: inherit;
  font-weight: 600;
  font-size: 14.5px;
  letter-spacing: 0.01em;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  box-shadow:
    0 10px 24px -10px rgba(79, 134, 255, 0.4),
    0 1px 0 rgba(255, 255, 255, 0.4) inset;
  transition: transform 0.16s var(--ease-out-soft), box-shadow 0.2s ease, background 0.16s ease;
}
.submit-btn::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  padding: 1px;
  background: linear-gradient(135deg, rgba(255, 255, 255, 0.75), rgba(255, 255, 255, 0.05) 45%, transparent 70%);
  -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  mask-composite: exclude;
  pointer-events: none;
}
a.submit-btn { text-decoration: none; }
.submit-btn:hover {
  background: linear-gradient(135deg, rgba(79, 141, 240, 0.5), rgba(79, 141, 240, 0.4));
  transform: translateY(-1px);
  box-shadow:
    0 16px 34px -10px rgba(79, 134, 255, 0.55),
    0 1px 0 rgba(255, 255, 255, 0.45) inset;
}
.submit-btn:active { transform: scale(0.97); }
.submit-btn:disabled { cursor: default; opacity: 0.82; }
.submit-btn .spin {
  width: 16px;
  height: 16px;
  animation: btnspin 0.7s linear infinite;
}
@keyframes btnspin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .submit-btn { transition: none; }
  .submit-btn .spin { animation-duration: 1.4s; }
}

#loginError, #wijzigError, #wwError {
  display: none;
  align-items: center;
  gap: 0.5rem;
  margin: 1rem 0 0;
  padding: 0.6rem 0.75rem;
  border-radius: 9px;
  background: rgba(255, 97, 97, 0.12);
  border: 1px solid rgba(255, 97, 97, 0.32);
  color: #ffb4b4;
  font-size: 13px;
}
#loginError.show, #wijzigError.show, #wwError.show { display: flex; }
#loginError [data-lucide], #wijzigError [data-lucide], #wwError [data-lucide] { flex: none; color: #ff8a8a; }

/* shake bij foutieve login: korte horizontale trilling op het paneel */
.panel.shake { animation: panelIn 0.65s var(--ease-out-soft) both, shake 0.42s ease; }
@keyframes shake {
  10%, 90% { transform: translateX(-1px); }
  20%, 80% { transform: translateX(2px); }
  30%, 50%, 70% { transform: translateX(-6px); }
  40%, 60% { transform: translateX(6px); }
}
@media (prefers-reduced-motion: reduce) {
  .panel.shake { animation: none; }
}

.panel-footer {
  margin-top: 1.3rem;
  text-align: center;
}
/* Secundaire knop (Apple "plain glass"): capsulevorm, witte tint ~.08, geen eigen
   backdrop-filter (staat al op het paneel-glas — één glaslaag per stapel). */
.forgot-link {
  background: rgba(255, 255, 255, 0.08);
  border: 0;
  color: var(--ink-dim);
  font: inherit;
  font-size: 13px;
  cursor: pointer;
  padding: 0.35rem 0.9rem;
  border-radius: 999px;
  transition: color 0.15s ease, background 0.15s ease;
}
.forgot-link:hover { color: var(--accent-koraal); background: rgba(255, 255, 255, 0.14); }
.forgot-link:focus-visible { outline: 2px solid var(--accent-blauw); outline-offset: 2px; }

/* mini-formulier "wachtwoord vergeten?" — klapt open onder de link */
.forgot-form {
  margin-top: 0.9rem;
  text-align: left;
}
.forgot-form .field { margin-bottom: 0.7rem; }
.forgot-submit {
  width: 100%;
  padding: 0.6rem;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.08);
  border: 0;
  color: var(--ink);
  font: inherit;
  font-size: 13.5px;
  font-weight: 600;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.45rem;
  transition: background 0.15s ease, transform 0.12s ease;
}
.forgot-submit:hover { background: rgba(255, 255, 255, 0.16); }
.forgot-submit:active { transform: scale(0.98); }
.forgot-submit:disabled { cursor: default; opacity: 0.75; }

#forgotNote {
  display: none;
  margin: 0.7rem 0 0;
  font-size: 12.5px;
  color: var(--ink-faint);
}
#forgotNote.show { display: block; }
#forgotNote.show.error { color: #ffb4b4; }

/* ---------------------------------------------------------------------------
   Portaal-shell: topbar + welkom + tegel-grid (taak 2.3). De levende achtergrond
   uit .bg-ambient blijft actief maar toont zich rustiger zodra het portaal de
   hoofdweergave is (de tegels moeten de aandacht trekken, niet de achtergrond). */
#portalShell {
  position: relative;
  z-index: 1;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}
body.portaal-actief .bg-ambient { opacity: 0.5; transition: opacity 0.5s ease; }

.portal-topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 18px 30px;
  border-bottom: 1px solid var(--line);
}
.portal-topbar img { width: 108px; height: auto; }

/* ---------- gebruikersmenu ---------- */
.user-menu { position: relative; }
.user-menu-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid var(--line);
  color: var(--ink);
  font: inherit;
  font-size: 13.5px;
  font-weight: 600;
  padding: 8px 14px 8px 10px;
  border-radius: 999px;
  cursor: pointer;
  transition: background 0.15s ease, transform 0.12s ease;
}
.user-menu-btn:hover { background: rgba(255, 255, 255, 0.16); }
.user-menu-btn:active { transform: scale(0.97); }
.user-menu-btn [data-lucide]:first-child { width: 19px; height: 19px; color: var(--ink-dim); }
.user-menu-caret { width: 15px; height: 15px; color: var(--ink-faint); transition: transform 0.15s ease; }
.user-menu-btn[aria-expanded="true"] .user-menu-caret { transform: rotate(180deg); }

.user-menu-dropdown {
  position: absolute;
  right: 0;
  top: calc(100% + 8px);
  min-width: 15rem;
  background: linear-gradient(180deg, var(--glass-top), var(--glass-bottom));
  border: 1px solid transparent;
  border-radius: 20px;
  padding: 6px;
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  box-shadow:
    0 20px 44px -16px rgba(0, 0, 0, 0.6),
    0 1px 0 rgba(255, 255, 255, 0.12) inset;
  animation: menuIn 0.16s var(--ease-out-soft) both;
  z-index: 5;
}
@keyframes menuIn {
  0% { opacity: 0; transform: translateY(-6px) scale(0.98); }
  100% { opacity: 1; transform: translateY(0) scale(1); }
}
@media (prefers-reduced-motion: reduce) {
  .user-menu-dropdown { animation: none; }
}
.user-menu-item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  background: none;
  border: 0;
  color: var(--ink);
  font: inherit;
  font-size: 13.5px;
  text-decoration: none;
  padding: 9px 10px;
  border-radius: 14px;
  cursor: pointer;
  text-align: left;
  transition: background 0.12s ease;
}
.user-menu-item:hover { background: rgba(255, 255, 255, 0.1); }
.user-menu-item [data-lucide] { width: 16px; height: 16px; color: var(--ink-dim); }
.user-menu-item--danger:hover { background: rgba(255, 97, 97, 0.14); }
.user-menu-item--danger:hover [data-lucide] { color: var(--rood-zacht); }

/* ---------- welkom ---------- */
.portal-main {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1.6rem;
  padding: 1.8rem 1.5rem 2.4rem;
}
.portal-welkom { text-align: center; }
.portal-groet {
  margin: 0 0 6px;
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-faint);
  animation: welkomIn 0.6s var(--ease-out-soft) both;
}
.portal-welkomtekst {
  margin: 0;
  font-size: clamp(1.6rem, 3vw, 2.4rem);
  font-weight: 300;
  letter-spacing: -0.01em;
  line-height: 1.1;
  background: linear-gradient(135deg, #ffffff 0%, #eef1fa 45%, #aab3c9 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  animation: welkomIn 0.7s 0.05s var(--ease-out-soft) both;
}
@keyframes welkomIn {
  0% { opacity: 0; transform: translateY(16px); }
  100% { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
  .portal-groet, .portal-welkomtekst { animation: none; }
}

/* ---------- tegel-grid ---------- */
.portal-tegels {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 176px));
  justify-content: center;
  gap: 16px;
  width: 100%;
  max-width: 1360px;
}
/* Lege-staat: geen tegel-tracks nodig, de kaart mag gewoon z'n eigen (bredere) breedte kiezen. */
.portal-tegels.leeg { display: flex; justify-content: center; }
.tegels-leeg { max-width: 26rem; }

/* Gegroepeerde weergave (tegels verdeeld over categorieën, admin/instelbaar).
   De groepen staan NIET als volle-breedte rijen onder elkaar — dat kostte per groep een
   hele schermhoogte en dwong tot scrollen. In plaats daarvan is de buitenlaag zelf een
   fijnmazig raster waarin elke groep een blok is dat precies zo breed is als hij tegels
   heeft (data-n, gezet door portal.js). Zo schuiven kleine groepen naast elkaar en vult
   het bord de breedte i.p.v. de hoogte. Alleen actief zolang minstens één zichtbare tegel
   een categorie heeft (portal.js) — zonder categorieën blijft het de platte grid. */
.portal-tegels.gegroepeerd {
  display: grid;
  grid-template-columns: repeat(auto-fit, 164px);
  align-items: start;
  gap: 30px 32px;
  max-width: 1360px;
  justify-content: center;
}
.tegel-groep {
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-width: 0;
  /* Standaard één kolom; de spans hieronder verbreden 'm naar het aantal tegels. */
  grid-column: span 1;
}
/* Boven de vier kappen we af: een grotere categorie wordt dan een blok van vier breed
   waarin de tegels zelf doorlopen naar een volgende regel. */
.tegel-groep[data-n="2"] { grid-column: span 2; }
.tegel-groep[data-n="3"] { grid-column: span 3; }
.tegel-groep[data-n="4"],
.tegel-groep[data-n="veel"] { grid-column: span 4; }
.tegel-groep-grid {
  display: grid;
  /* minmax(0,1fr) leverde tientallen tracks op: alle tegels van een groep bleven dan op één
     regel staan en werden smaller naarmate de groep groeide. Met een echte minimumbreedte
     wikkelen ze zoals bedoeld zodra het blok te smal wordt. */
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 14px;
}
.tegel-groep-titel {
  margin: 0;
  font-size: 11.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--ink-faint);
  padding-left: 2px;
}
/* Smal scherm: de spans zouden breder worden dan het raster zelf. Alle groepen op volle
   breedte, de tegels erbinnen wikkelen vanzelf. */
@media (max-width: 720px) {
  .portal-tegels.gegroepeerd { grid-template-columns: 1fr; }
  .tegel-groep,
  .tegel-groep[data-n="2"],
  .tegel-groep[data-n="3"],
  .tegel-groep[data-n="4"],
  .tegel-groep[data-n="veel"] { grid-column: span 1; }
}

.tegel {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding: 1.35rem 1rem;
  min-height: 132px;
  background: linear-gradient(180deg, var(--glass-top), var(--glass-bottom));
  border: 1px solid transparent;
  border-radius: 18px;
  color: var(--ink);
  text-decoration: none;
  cursor: pointer;
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  /* fill-mode is bewust "backwards", NIET "both": "both" zou de eind-transform van de
     animatie voor altijd laten "hangen" en zo hover/press-transforms permanent
     overstemmen (Web Animations-effecten wegen zwaarder dan normale cascade-regels
     zolang ze "in effect" zijn). "backwards" toont alleen de 0%-startframe tijdens de
     stagger-delay; zodra de animatie klaar is, valt het element terug op de gewone
     cascade (opacity:1/geen transform hieronder) — identiek aan de 100%-keyframe, dus
     geen visuele sprong, en :hover/:active krijgen de transform daarna weer volledig. */
  animation: tegelIn 0.5s var(--ease-out-soft) backwards;
  animation-delay: calc(var(--i, 0) * 60ms);
  transition: transform 0.2s var(--ease-out-soft), box-shadow 0.2s var(--ease-out-soft),
    border-color 0.2s ease;
}
@keyframes tegelIn {
  0% { opacity: 0; transform: translateY(18px) scale(0.97); }
  100% { opacity: 1; transform: translateY(0) scale(1); }
}
.tegel:hover {
  transform: translateY(-5px);
  border-color: rgba(79, 134, 255, 0.4);
  box-shadow: 0 22px 40px -18px rgba(79, 134, 255, 0.45), 0 0 0 1px rgba(79, 134, 255, 0.15) inset;
}
.tegel:hover .tegel-media { transform: scale(1.08); color: var(--accent-blauw); }
.tegel:active, .tegel.tegel--pressed {
  transform: scale(0.97);
  box-shadow: 0 10px 20px -12px rgba(79, 134, 255, 0.4);
}

/* Muisvolgende border-glow: portal.js zet --mx/--my (px, relatief aan de tegel) op elke
   pointermove. Dit ::after-laagje hergebruikt dezelfde mask-exclude-ringtechniek als de
   ::before-rim hierboven, maar met een radiale gloed die met de cursor meebeweegt i.p.v.
   een vaste diagonaal — alleen zichtbaar op hover (opacity 0→1). */
.tegel::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  padding: 1px;
  background: radial-gradient(130px circle at var(--mx, 50%) var(--my, 50%), rgba(255, 255, 255, 0.85), transparent 70%);
  -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  mask-composite: exclude;
  opacity: 0;
  transition: opacity 0.2s ease;
  pointer-events: none;
}
.tegel:hover::after { opacity: 1; }
.tegel-media {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 46px;
  height: 46px;
  color: var(--ink-dim);
  transition: transform 0.2s var(--ease-out-soft), color 0.2s ease;
}
.tegel-media [data-lucide] { width: 33px; height: 33px; stroke-width: 1.65; }
.tegel-media img {
  width: 46px;
  height: 46px;
  object-fit: contain;
  border-radius: 10px;
}
.tegel-naam {
  font-size: 14px;
  font-weight: 600;
  text-align: center;
  color: var(--ink);
}
@media (prefers-reduced-motion: reduce) {
  .tegel {
    opacity: 1;
    animation: none;
    transition: none;
  }
  .tegel:hover, .tegel:active, .tegel.tegel--pressed { transform: none; box-shadow: none; }
  .tegel:hover .tegel-media { transform: none; }
  /* K8: de muisvolgende glow mag bij reduced-motion niet meebewegen/faden — geen
     transition en nooit zichtbaar i.p.v. instant meespringen met de cursor. */
  .tegel::after { transition: none; }
  .tegel:hover::after { opacity: 0; }
}

.tegels-leeg {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  padding: 2.5rem 2rem;
  text-align: center;
  color: var(--ink-faint);
  background: linear-gradient(180deg, var(--glass-top), var(--glass-bottom));
  border: 1px solid transparent;
  border-radius: 26px;
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.12) inset;
}
.tegels-leeg [data-lucide] { width: 34px; height: 34px; }
.tegels-leeg p { margin: 0; font-size: 14px; max-width: 26rem; }

@media (max-width: 480px) {
  .panel { padding: 1.7rem 1.4rem 1.5rem; }
}

/* ---------- beheer-tegels (buiten je groepen) ----------
   Een hoofdbeheerder ziet standaard het portaal van zijn eigen groepen; wat hij alleen via
   zijn beheerrol mag, staat hierachter (migr. 20260731100000). Bewust een eigen sectie en
   niet tussen de gewone tegels: je dagelijkse beeld blijft op dezelfde plek staan, en je
   ziet welke pet je op hebt. Puur weergave — met de sectie dicht zijn die tegels nog steeds
   bereikbaar via hun URL. */
.portal-beheer {
  width: 100%;
  max-width: 1360px;
  margin-top: 34px;
  padding-top: 22px;
  border-top: 1px solid var(--line);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 20px;
}
.beheer-schakel {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 8px 15px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: linear-gradient(180deg, var(--glass-top), var(--glass-bottom));
  color: var(--ink-dim);
  font: 600 13px inherit;
  cursor: pointer;
  transition: color 0.15s ease, border-color 0.15s ease;
}
.beheer-schakel:hover { color: var(--ink); border-color: var(--accent-blauw); }
.beheer-schakel:focus-visible { outline: 2px solid var(--accent-blauw); outline-offset: 2px; }
.beheer-schakel [data-lucide] { width: 15px; height: 15px; }
.beheer-chevron { transition: transform 0.18s ease; }
.beheer-schakel[aria-expanded="true"] .beheer-chevron { transform: rotate(180deg); }
@media (prefers-reduced-motion: reduce) {
  .beheer-chevron { transition: none; }
}
