/* ZwemApp — eigen stylesheet, geen externe afhankelijkheden.
   Werkt in licht en donker thema; volgt de voorkeur van het systeem. */

:root {
  --blue-50:  #eff6ff;
  --blue-100: #dbeafe;
  --blue-200: #bfdbfe;
  --blue-500: #3b82f6;
  --blue-600: #2563eb;
  --blue-700: #1d4ed8;
  --blue-900: #1e3a5f;

  --bg:            #f4f6fa;
  --bg-raised:     #ffffff;
  --bg-sunken:     #eaeef5;
  --bg-hover:      #f1f5fb;
  --border:        #dde3ec;
  --border-strong: #c3ccdb;

  --text:        #16202e;
  --text-muted:  #5a6779;
  --text-subtle: #8b96a7;
  --text-invert: #ffffff;

  --accent:       var(--blue-600);
  --accent-hover: var(--blue-700);
  --accent-soft:  var(--blue-50);

  --ok:      #15803d;
  --ok-bg:   #dcfce7;
  --warn:    #b45309;
  --warn-bg: #fef3c7;
  --bad:     #b91c1c;
  --bad-bg:  #fee2e2;
  --info:    #0369a1;
  --info-bg: #e0f2fe;
  /* Oranje staat tussen geel en rood in, en moet van allebei te
     onderscheiden zijn: het protocol gebruikt vier kleuren als vier niveaus. */
  --oranje:    #c2410c;
  --oranje-bg: #ffedd5;

  --radius:    10px;
  --radius-sm: 6px;
  --shadow:    0 1px 2px rgba(16, 32, 55, .06), 0 4px 12px rgba(16, 32, 55, .05);
  --shadow-lg: 0 8px 32px rgba(16, 32, 55, .14);

  --sidebar-w: 232px;
  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg:            #0f151f;
    --bg-raised:     #18202d;
    --bg-sunken:     #131a25;
    --bg-hover:      #1f2938;
    --border:        #2a3547;
    --border-strong: #3a4759;

    --text:        #e8edf5;
    --text-muted:  #9aa7ba;
    --text-subtle: #6b7a8f;

    --accent:       #4f8ef7;
    --accent-hover: #6da2f9;
    --accent-soft:  #182741;

    --ok:      #4ade80;  --ok-bg:   #10291a;
    --warn:    #fbbf24;  --warn-bg: #2c2410;
    --bad:     #f87171;  --bad-bg:  #2c1517;
    --info:    #38bdf8;  --info-bg: #10222e;
    --oranje:  #fb923c;  --oranje-bg: #2e1c0f;

    --shadow:    0 1px 2px rgba(0, 0, 0, .3), 0 4px 12px rgba(0, 0, 0, .25);
    --shadow-lg: 0 8px 32px rgba(0, 0, 0, .45);
  }
}

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  font-family: var(--font);
  font-size: 15px;
  line-height: 1.5;
  color: var(--text);
  background: var(--bg);
}

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }

h1, h2, h3, h4 { margin: 0 0 .5rem; line-height: 1.25; font-weight: 650; }
h1 { font-size: 1.5rem; letter-spacing: -.01em; }
h2 { font-size: 1.15rem; }
h3 { font-size: 1rem; }
p  { margin: 0 0 .75rem; }

/* ---------------------------------------------------------------- layout */

.layout { display: flex; min-height: 100vh; }

.sidebar {
  width: var(--sidebar-w);
  flex: 0 0 var(--sidebar-w);
  background: var(--blue-900);
  color: #cdd9ea;
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
}

.sidebar__brand {
  display: flex;
  align-items: center;
  gap: .625rem;
  padding: 1.125rem 1rem;
  color: #fff;
  font-weight: 700;
  font-size: 1.05rem;
  letter-spacing: -.01em;
  border-bottom: 1px solid rgba(255, 255, 255, .1);
}
.sidebar__brand:hover { text-decoration: none; }
/* Het clublogo is donkerblauw en zou wegvallen tegen de donkere zijbalk;
   vandaar het witte tegeltje eronder. */
.sidebar__logo {
  width: 30px; height: 30px;
  display: grid; place-items: center;
  border-radius: 8px;
  background: #fff;
  padding: 3px;
  flex: none;
}
.sidebar__logo img { width: 100%; height: 100%; object-fit: contain; display: block; }

/* De draaiende versie, altijd in beeld. Klein en grijs: het is geen boodschap
   voor de gebruiker maar een antwoord op 'welke versie zie jij?'. Buiten
   productie staat er een gekleurd vlaggetje bij, want dát is de verwarring die
   je wil voorkomen. */
.sidebar__actief {
  display: flex;
  align-items: center;
  gap: .35rem;
  margin-top: .5rem;
  font-size: .72rem;
  color: #9fb6d6;
  text-decoration: none;
}
.sidebar__actief:hover { color: #fff; }

.sidebar__versie {
  margin-top: .35rem;
  font-size: .68rem;
  color: #7b93b5;
  font-variant-numeric: tabular-nums;
}
.versie-voet {
  margin: 1rem 0 0;
  text-align: center;
  font-size: .7rem;
  color: var(--text-subtle);
  font-variant-numeric: tabular-nums;
}
.versie-vlag {
  display: inline-block;
  background: var(--warn);
  color: #fff;
  border-radius: 3px;
  padding: 0 .3rem;
  font-weight: 700;
  letter-spacing: .04em;
  margin-right: .25rem;
}

.login__logo { width: 150px; height: auto; margin: 0 auto .5rem; display: block; }

/* Clubprijzen: het rondje naast de stand betekent 'hier volgt een beeldje uit'.
   Het staat in dezelfde cel als de stand, want een aparte kolom per prijs én
   een kolom met alle beeldjes maakte de tabel onleesbaar breed. */
.beeldje {
  display: inline-block;
  margin-left: .3rem;
  font-weight: 700;
  color: var(--warn);
}
.beeldje.is-done { color: var(--ok); }
/* Deze koppen zijn breder dan hun inhoud en bepalen dus de kolombreedte.
   Zonder kapitalen en letterspatiëring past de tabel op één scherm. */
table.data th.prijs-kop {
  white-space: nowrap;
  text-transform: none;
  letter-spacing: 0;
  padding-left: .5rem;
  padding-right: .5rem;
}
table.data td.prijs { padding-left: .5rem; padding-right: .5rem; }

/* Lijst met vinkjes die langer kan worden dan het scherm, bv. alle zwemmers
   die aan een ouderaccount hangen. */
.keuzelijst {
  max-height: 15rem;
  overflow-y: auto;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: .5rem .6rem;
  background: var(--bg-raised);
}
.keuzelijst .check { margin-bottom: .15rem; }

/* Wel voorlezen, niet tonen: voor tekst die het beeld al vertelt. */
.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  overflow: hidden; clip-path: inset(50%);
  white-space: nowrap;
}
.sidebar__sub { font-size: .72rem; font-weight: 500; color: #8fa6c4; display: block; }

.sidebar__nav { padding: .75rem .5rem; flex: 1; }
.sidebar__group { margin-bottom: 1rem; }
.sidebar__label {
  font-size: .68rem;
  text-transform: uppercase;
  letter-spacing: .07em;
  color: #7b93b5;
  padding: 0 .625rem .3rem;
  font-weight: 600;
}
.sidebar__link {
  display: flex;
  align-items: center;
  gap: .55rem;
  padding: .44rem .625rem;
  border-radius: var(--radius-sm);
  color: #cdd9ea;
  font-size: .875rem;
  font-weight: 500;
}
.sidebar__link:hover { background: rgba(255, 255, 255, .07); color: #fff; text-decoration: none; }
.sidebar__link.is-active { background: var(--blue-600); color: #fff; }
.sidebar__icon { width: 1.1rem; text-align: center; font-size: .95rem; opacity: .95; }

.sidebar__footer {
  padding: .75rem;
  border-top: 1px solid rgba(255, 255, 255, .1);
  font-size: .8rem;
}
.sidebar__user { display: flex; align-items: center; gap: .55rem; margin-bottom: .5rem; }
.avatar {
  width: 30px; height: 30px;
  border-radius: 50%;
  background: var(--blue-600);
  color: #fff;
  display: grid; place-items: center;
  font-size: .72rem; font-weight: 700;
  flex: 0 0 auto;
}
.sidebar__username { color: #fff; font-weight: 600; line-height: 1.2; }
.sidebar__role { color: #8fa6c4; font-size: .72rem; }

.main { flex: 1; min-width: 0; display: flex; flex-direction: column; }

.topbar {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: .875rem 1.5rem;
  background: var(--bg-raised);
  border-bottom: 1px solid var(--border);
  position: sticky; top: 0; z-index: 20;
}
.topbar h1 { margin: 0; font-size: 1.2rem; }
.topbar__actions { margin-left: auto; display: flex; gap: .5rem; align-items: center; flex-wrap: wrap; }
/* Twee klassen, zodat deze regel wint van .btn verderop in dit bestand. */
.topbar .menu-toggle { display: none; }

.content { padding: 1.5rem; max-width: 1500px; width: 100%; }

/* ----------------------------------------------------------------- cards */

/* Zolang er een paneeltje openstaat, mag de kaart niet knippen: anders valt de
   rand van dat paneel weg zodra het buiten de kaart komt. */
.card:has(.inline-actie[open]) { overflow: visible; }
.card {
  background: var(--bg-raised);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  margin-bottom: 1.25rem;
  overflow: hidden;
}
.card__header {
  display: flex; align-items: center; gap: .75rem;
  padding: .75rem 1rem;
  border-bottom: 1px solid var(--border);
  background: var(--bg-sunken);
}
.card__header h2, .card__header h3 { margin: 0; font-size: .95rem; }
.card__header .spacer { margin-left: auto; }
.card__body { padding: 1rem; }
.card__body--flush { padding: 0; }
.card__footer {
  padding: .625rem 1rem;
  border-top: 1px solid var(--border);
  background: var(--bg-sunken);
  font-size: .85rem;
}

.grid { display: grid; gap: 1.25rem; }
.grid--2 { grid-template-columns: repeat(auto-fit, minmax(340px, 1fr)); }
.grid--3 { grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }
.grid--4 { grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); }

/* -------------------------------------------------------------- stat tile */

.stat {
  background: var(--bg-raised);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: .875rem 1rem;
  box-shadow: var(--shadow);
}
.stat__label {
  font-size: .74rem; text-transform: uppercase; letter-spacing: .05em;
  color: var(--text-muted); font-weight: 600;
}
.stat__value { font-size: 1.7rem; font-weight: 700; letter-spacing: -.02em; line-height: 1.15; }
.stat__hint { font-size: .78rem; color: var(--text-subtle); }

/* ---------------------------------------------------------------- tables */

.table-wrap { overflow-x: auto; }

table.data {
  width: 100%;
  border-collapse: collapse;
  font-size: .875rem;
}
table.data th {
  text-align: left;
  padding: .5rem .75rem;
  background: var(--bg-sunken);
  border-bottom: 1px solid var(--border);
  font-weight: 600;
  font-size: .76rem;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--text-muted);
  white-space: nowrap;
  position: sticky; top: 0;
}
table.data td {
  padding: .5rem .75rem;
  border-bottom: 1px solid var(--border);
  vertical-align: middle;
}
table.data tbody tr:hover { background: var(--bg-hover); }

/* Sorteerbare kolomkoppen. De pijl staat er altijd, maar pas zichtbaar
   zodra je erover gaat of de kolom gesorteerd is. */
table.data th.is-sortable {
  cursor: pointer;
  user-select: none;
  padding-right: 1.25rem;
  position: relative;
}
table.data th.is-sortable:hover { color: var(--text); background: var(--bg-hover); }
table.data th.is-sortable::after {
  content: "↕";
  position: absolute;
  right: .4rem;
  opacity: 0;
  font-weight: 400;
}
table.data th.is-sortable:hover::after { opacity: .45; }
table.data th.is-asc::after  { content: "↑"; opacity: 1; color: var(--accent); }
table.data th.is-desc::after { content: "↓"; opacity: 1; color: var(--accent); }
table.data th.is-sortable:focus-visible {
  outline: 2px solid color-mix(in srgb, var(--accent) 45%, transparent);
  outline-offset: -2px;
}
table.data tbody tr:last-child td { border-bottom: none; }
table.data .num, .num { text-align: right; font-variant-numeric: tabular-nums; }
table.data .nowrap, .nowrap { white-space: nowrap; }
.time { font-variant-numeric: tabular-nums; font-weight: 600; }
.mono { font-family: var(--mono); font-size: .85em; }

tr.is-dim td { opacity: .55; }
/* Een bewaarde inschrijftijd die niet meer overeenkomt met de besttijd van nu.
   De pijl ernaast toont wat er zou komen te staan na 'tijden verversen'. */
td.is-stale { background: color-mix(in srgb, var(--warn-bg) 70%, transparent); }
tr.is-ok  td { background: color-mix(in srgb, var(--ok-bg) 55%, transparent); }
tr.is-bad td { background: color-mix(in srgb, var(--bad-bg) 40%, transparent); }

.empty {
  padding: 2rem 1rem;
  text-align: center;
  color: var(--text-muted);
}
.empty__icon { font-size: 1.75rem; display: block; margin-bottom: .5rem; opacity: .6; }

/* ---------------------------------------------------------------- badges */

.badge {
  display: inline-flex; align-items: center; gap: .25rem;
  padding: .1rem .45rem;
  border-radius: 100px;
  font-size: .74rem;
  font-weight: 600;
  background: var(--bg-sunken);
  color: var(--text-muted);
  border: 1px solid var(--border);
  white-space: nowrap;
}
.badge--ok   { background: var(--ok-bg);   color: var(--ok);   border-color: transparent; }
.badge--warn { background: var(--warn-bg); color: var(--warn); border-color: transparent; }
.badge--bad  { background: var(--bad-bg);  color: var(--bad);  border-color: transparent; }
.badge--info { background: var(--info-bg); color: var(--info); border-color: transparent; }
.badge--accent { background: var(--accent-soft); color: var(--accent); border-color: transparent; }
.badge--oranje { background: var(--oranje-bg); color: var(--oranje); border-color: transparent; }

.dot { width: .5rem; height: .5rem; border-radius: 50%; display: inline-block; }
.dot--ok { background: var(--ok); } .dot--warn { background: var(--warn); }
.dot--bad { background: var(--bad); } .dot--muted { background: var(--text-subtle); }

/* --------------------------------------------------------------- buttons */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .4rem;
  padding: .42rem .85rem;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border-strong);
  background: var(--bg-raised);
  color: var(--text);
  font-size: .875rem;
  font-weight: 550;
  font-family: inherit;
  cursor: pointer;
  white-space: nowrap;
  transition: background .12s, border-color .12s;
}
.btn:hover { background: var(--bg-hover); text-decoration: none; }
.btn:disabled { opacity: .5; cursor: not-allowed; }
.btn--primary {
  background: var(--accent); border-color: var(--accent); color: #fff;
}
.btn--primary:hover { background: var(--accent-hover); border-color: var(--accent-hover); }
.btn--danger { color: var(--bad); border-color: color-mix(in srgb, var(--bad) 40%, transparent); }
.btn--danger:hover { background: var(--bad-bg); }
.btn--ghost { border-color: transparent; background: transparent; }
.btn--ghost:hover { background: var(--bg-hover); }
.btn--sm { padding: .22rem .55rem; font-size: .8rem; }
.btn--block { width: 100%; }

.btn-row { display: flex; gap: .5rem; flex-wrap: wrap; align-items: center; }

/* ----------------------------------------------------------------- forms */

.field { margin-bottom: .875rem; }
.field > label,
.label {
  display: block;
  font-size: .8rem;
  font-weight: 600;
  margin-bottom: .25rem;
  color: var(--text-muted);
}
.field__hint { font-size: .78rem; color: var(--text-subtle); margin-top: .2rem; }
.field__error { font-size: .78rem; color: var(--bad); margin-top: .2rem; }

input[type="text"], input[type="email"], input[type="password"], input[type="number"],
input[type="date"], input[type="time"], input[type="search"], input[type="url"],
input[type="file"], select, textarea {
  width: 100%;
  padding: .42rem .6rem;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--bg-raised);
  color: var(--text);
  font-family: inherit;
  font-size: .875rem;
}
input:focus, select:focus, textarea:focus {
  outline: 2px solid color-mix(in srgb, var(--accent) 40%, transparent);
  outline-offset: 0;
  border-color: var(--accent);
}
input[type="checkbox"], input[type="radio"] { accent-color: var(--accent); width: auto; }
textarea { min-height: 5rem; resize: vertical; }
select { cursor: pointer; }

/* Het vinkje hoort bij de eerste regel van zijn label, niet bij het midden:
   loopt een label over twee regels, dan zakte het vinkje anders een halve
   regel en stond het niet meer gelijk met een buur met een kort label. */
.check { display: flex; align-items: flex-start; gap: .45rem; font-size: .875rem; margin-bottom: .4rem; }
.check input { flex: none; margin-top: .3rem; }
.check label { margin: 0; font-weight: 500; color: var(--text); }

.form-grid { display: grid; gap: 0 1rem; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
.form-grid--3 { grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); }
.span-2 { grid-column: span 2; }

.filters {
  display: flex; gap: .625rem; flex-wrap: wrap; align-items: flex-end;
  padding: .75rem 1rem;
  background: var(--bg-raised);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  margin-bottom: 1.25rem;
  box-shadow: var(--shadow);
}
.filters .field { margin: 0; min-width: 130px; }
.filters .field--wide { flex: 1; min-width: 200px; }

/* -------------------------------------------------------------- messages */

.flash {
  display: flex; align-items: flex-start; gap: .55rem;
  padding: .625rem .875rem;
  border-radius: var(--radius-sm);
  margin-bottom: .75rem;
  font-size: .875rem;
  border: 1px solid transparent;
}
.flash--success { background: var(--ok-bg);   color: var(--ok);   border-color: color-mix(in srgb, var(--ok) 25%, transparent); }
.flash--warning { background: var(--warn-bg); color: var(--warn); border-color: color-mix(in srgb, var(--warn) 25%, transparent); }
.flash--error   { background: var(--bad-bg);  color: var(--bad);  border-color: color-mix(in srgb, var(--bad) 25%, transparent); }
.flash--info    { background: var(--info-bg); color: var(--info); border-color: color-mix(in srgb, var(--info) 25%, transparent); }
/* De balk die zegt dat je in het portaal van een gezin meekijkt. Opvallender
   dan een gewone melding, want ze mag niet wegvallen tussen de rest: ze staat
   op élk scherm en verdwijnt pas als je stopt. */
.doorkijk {
  display: flex; align-items: center; gap: .6rem;
  padding: .625rem .875rem;
  margin-bottom: .75rem;
  font-size: .875rem;
  border-radius: var(--radius-sm);
  background: var(--warn-bg);
  color: var(--warn);
  border: 2px solid var(--warn);
}
.doorkijk__oog { font-size: 1.05rem; line-height: 1; }
.doorkijk .btn { white-space: nowrap; }

/* Een verjaardag mag opvallen, maar niet zo hard dat ze op een fout lijkt. */
.flash--jarig {
  background: linear-gradient(90deg, var(--accent-soft), var(--warn-bg));
  color: var(--text);
  border-color: color-mix(in srgb, var(--warn) 30%, transparent);
  align-items: center;
}
.flash--jarig .muted { color: var(--text-muted); }
.flash__weg { margin-left: auto; }

.note {
  padding: .625rem .875rem;
  border-left: 3px solid var(--accent);
  background: var(--accent-soft);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  font-size: .85rem;
  margin-bottom: 1rem;
}
.note--warn { border-color: var(--warn); background: var(--warn-bg); color: var(--warn); }
.note--ok   { border-color: var(--ok);   background: var(--ok-bg);   color: var(--ok); }
.note--bad  { border-color: var(--bad);  background: var(--bad-bg);  color: var(--bad); }

/* ------------------------------------------------------------------ tabs */

.tabs {
  display: flex; gap: .25rem; flex-wrap: wrap;
  border-bottom: 1px solid var(--border);
  margin-bottom: 1.25rem;
}
.tabs a {
  padding: .45rem .8rem;
  font-size: .875rem;
  font-weight: 550;
  color: var(--text-muted);
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
}
.tabs a:hover { color: var(--text); text-decoration: none; }
.tabs a.is-active { color: var(--accent); border-bottom-color: var(--accent); }

/* ------------------------------------------------------------ breadcrumb */

.crumbs { font-size: .8rem; color: var(--text-muted); margin-bottom: .35rem; }
.crumbs a { color: var(--text-muted); }
.crumbs span { margin: 0 .35rem; opacity: .5; }

/* ----------------------------------------------------------------- chart */

.chart { width: 100%; height: auto; }
.chart__line { fill: none; stroke: var(--accent); stroke-width: 2; }
.chart__area { fill: color-mix(in srgb, var(--accent) 14%, transparent); }
.chart__dot { fill: var(--bg-raised); stroke: var(--accent); stroke-width: 2; }
.chart__dot--pb { fill: var(--ok); stroke: var(--ok); }
.chart__grid { stroke: var(--border); stroke-width: 1; }
.chart__text { fill: var(--text-muted); font-size: 10px; font-family: var(--font); }

.bar {
  height: .5rem;
  background: var(--bg-sunken);
  border-radius: 100px;
  overflow: hidden;
  min-width: 60px;
}
.bar__fill { height: 100%; background: var(--accent); border-radius: 100px; }
.bar__fill--ok { background: var(--ok); }
.bar__fill--warn { background: var(--warn); }
.bar__fill--bad { background: var(--bad); }

/* -------------------------------------------------------------- timeline */

/* De seizoenslijn. Elke rij is een eigen laag over dezelfde schaal: de
   badperiode bovenaan, daaronder de fasen, en onderaan de maanden. De blokjes
   staan absoluut op hun datum en niet achter elkaar — anders verdwijnt een gat
   tussen twee fasen en komt overlap ernaast te staan alsof het volgorde was. */
.lijn { display: grid; gap: 3px; position: relative; }
/* Waar we vandaag staan: één streep over alle lagen heen, want de vraag
   'welke fase loopt er nu' gaat over alle lagen tegelijk. */
.lijn__nu {
  position: absolute;
  top: -.15rem;
  bottom: -.15rem;
  width: 2px;
  margin-left: -1px;
  background: var(--text);
  opacity: .55;
  z-index: 2;
  pointer-events: none;
}
.lijn__rij { position: relative; height: 1.5rem; }
.lijn__bad, .lijn__fase, .lijn__maand {
  position: absolute;
  top: 0;
  bottom: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: .72rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  border-radius: var(--radius-sm);
}
.lijn__baden { height: 1.25rem; }
.lijn__bad { font-weight: 700; letter-spacing: .03em; color: #fff; }
/* Twee baden, twee kleuren — maar geen van beide mag met een fasekleur
   verward worden, dus grijsblauw en leisteen in plaats van iets fels. */
.lijn__bad--25m { background: #475569; }
.lijn__bad--50m { background: #0f766e; }
.lijn__fase { font-weight: 600; color: #fff; padding: 0 .35rem; }
.lijn__maanden { height: 1.15rem; }
.lijn__maand {
  color: var(--text-subtle);
  border-left: 1px solid var(--border);
  border-radius: 0;
  justify-content: flex-start;
  padding-left: .2rem;
}
/* Het begin van een kwartaal: een volle streep in plaats van een haarlijn. */
.lijn__maand--kwartaal { border-left: 2px solid var(--text-subtle); color: var(--text); font-weight: 600; }

/* Een piekmoment: een bol op zijn dag. De naam staat ernaast zolang er plaats
   is en verdwijnt nooit helemaal — de titel van de bol draagt ze altijd, ook
   op een telefoon waar aanwijzen niet bestaat. */
.lijn__pieken { height: 1.4rem; overflow: visible; }
.lijn__piek {
  position: absolute;
  top: 50%;
  width: .7rem;
  height: .7rem;
  margin: -.35rem 0 0 -.35rem;
  border-radius: 50%;
  /* Karmijn, bewust buiten zowel het fase- als het badpalet: een piek is geen
     periode en mag er ook niet als één lezen. Een vaste kleur en geen
     variabele — ze moet in de lichte én de donkere stand opvallen. */
  background: #dc2626;
  box-shadow: 0 0 0 2px var(--bg-raised);
  cursor: help;
}

/* De opstelling van een aflossingsploeg: één zwemmer per regel. Achter elkaar
   op één lijn duwt een viertal die kolom breder dan de hele tabel aankan. */
.opstelling { display: grid; gap: .1rem; }
.opstelling__leg { display: flex; gap: .35rem; align-items: baseline; white-space: nowrap; }
.opstelling__nr { color: var(--text-subtle); min-width: 1.1rem; }
/* De pijltjes om de volgorde te wijzigen: klein en achteraan, zodat de namen
   in één kolom blijven staan. */
.opstelling__pijlen { margin-left: auto; display: inline-flex; gap: .1rem; }
.opstelling__pijlen .btn { padding: 0 .3rem; line-height: 1.3; font-size: .7rem; }

/* De letter van een ploeg is aanpasbaar ter plaatse: een smal vakje met een
   vinkje ernaast, zodat de tabel er niet breder van wordt. */
.ploegnaam { display: inline-flex; gap: .25rem; align-items: center; }
.ploegnaam input { width: 3.5rem; text-align: center; text-transform: uppercase; }

/* ----------------------------------------------------------------- misc  */

.muted { color: var(--text-muted); }
.subtle { color: var(--text-subtle); }
.small { font-size: .8rem; }
.strong { font-weight: 650; }
.right { text-align: right; }
.center { text-align: center; }
.stack > * + * { margin-top: .75rem; }
.inline-list { display: flex; gap: .375rem; flex-wrap: wrap; }
hr { border: none; border-top: 1px solid var(--border); margin: 1rem 0; }

.page-actions { display: flex; gap: .5rem; flex-wrap: wrap; margin-bottom: 1.25rem; }

details.disclosure > summary {
  cursor: pointer;
  font-weight: 600;
  font-size: .875rem;
  padding: .4rem 0;
  color: var(--text-muted);
}
details.disclosure > summary:hover { color: var(--text); }

.pill-row { display: flex; gap: .3rem; flex-wrap: wrap; }

/* De kindkeuze in het portaal. Ze staat bóven de tabbladen en stuurt wat
   eronder gebeurt, dus mag ze niet als een filtertje wegvallen: een eigen
   regel met een label ervoor, en lucht tot aan de tabbladen. */
.kindkeuze {
  display: flex; align-items: center; gap: .6rem; flex-wrap: wrap;
  margin-bottom: .85rem;
}
.kindkeuze__label {
  font-size: .78rem; text-transform: uppercase; letter-spacing: .04em;
  color: var(--text-muted);
}
.pill {
  padding: .2rem .55rem;
  border-radius: 100px;
  border: 1px solid var(--border-strong);
  font-size: .8rem;
  color: var(--text-muted);
  background: var(--bg-raised);
}
.pill.is-active { background: var(--accent); border-color: var(--accent); color: #fff; }
.pill:hover { text-decoration: none; }

.htmx-request { opacity: .6; pointer-events: none; }

/* Een knopje dat openklapt naar een klein formuliertje, bijvoorbeeld om een
   datum te kiezen bij het uit een groep halen. */
.inline-actie { display: inline-block; position: relative; }
.inline-actie > summary { list-style: none; cursor: pointer; }
.inline-actie > summary::-webkit-details-marker { display: none; }
.inline-actie[open] > summary { background: var(--bad-bg); }
.inline-actie > form {
  position: absolute; right: 0; z-index: 20; width: 15rem;
  margin-top: .35rem; padding: .7rem;
  background: var(--bg-raised); border: 1px solid var(--border-strong);
  border-radius: var(--radius); box-shadow: var(--shadow-lg);
  text-align: left;
}
.inline-actie > form input[type="date"] { margin-bottom: .5rem; }
.inline-actie > form select,
.inline-actie > form input[type="number"] { margin-bottom: .5rem; }
.inline-actie > form.breed, .inline-actie > form:has(select) { width: 18rem; }
/* Hetzelfde uitklapblok, maar met inhoud in plaats van een formulier: de
   mailknop zet er een rijtje koppelingen in.

   Naar réchts open, en niet naar links zoals de formuliertjes hierboven: die
   staan achteraan een tabelrij, de mailknop staat vooraan in een kaartkop. Met
   right:0 liep het paneel de kaart uit, en omdat een kaart haar inhoud afknipt
   (afgeronde hoeken) viel de linkerhelft van de tekst weg. */
.inline-actie > .paneel {
  position: absolute; left: 0; right: auto; z-index: 20; width: 17rem;
  margin-top: .35rem; padding: .7rem;
  background: var(--bg-raised); border: 1px solid var(--border-strong);
  border-radius: var(--radius); box-shadow: var(--shadow-lg);
  text-align: left;
}

/* De verdeling van de oordelen in het trainingsrapport: rood, geel, groen. */
/* Gekleurde vlakjes en niet enkel gekleurde cijfers: het amber van 'gewoon'
   en het rood van 'zwak' liggen als kale tekst te dicht bij elkaar. Dit is
   dezelfde beeldtaal als de knoppen op het aanwezigheidsscherm. */
.verdeling {
  display: inline-flex; gap: .2rem; margin-left: .4rem;
  font-size: .7rem; font-weight: 700; white-space: nowrap;
}
.verdeling span {
  min-width: 1.15rem; padding: .05rem .2rem;
  border-radius: 4px; text-align: center;
}
.verdeling .is-zwak { background: var(--bad-bg); color: var(--bad); }
.verdeling .is-gewoon { background: var(--warn-bg); color: var(--warn); }
.verdeling .is-sterk { background: var(--ok-bg); color: var(--ok); }
/* Gezwommen maar niet beoordeeld: telt niet mee in het gemiddelde, maar hoort
   er wel bij — anders valt de som niet na te rekenen. */
.verdeling .is-geenoordeel { background: var(--bg-sunken); color: var(--text-subtle); }

/* De vijf trainingsniveaus, met dezelfde kleuren als op het kaartje in de PDF.
   Loopt gelijk met ZONEKLEUREN in app/services/pdfio.py: wie hier iets wijzigt,
   wijzigt het daar ook, anders ziet het kaartje aan het bad er anders uit dan
   het scherm waar het vandaan komt.

   Het vlak is een tint donkerder dan voorheen — de trainers vonden het te bleek
   op een telefoon in een zwembad — en de tekst schoof mee, zodat elke zone
   boven de 4,5:1 blijft die gewone tekst nodig heeft. Gemeten: wit 8,4 ·
   roze 5,7 · rood 5,7 · blauw 6,1 · paars 6,5. */
table.tempos td.time { font-size: 1rem; font-weight: 600; }
.zone--white  td { background: #e2e8f0; color: #334155; }
.zone--pink   td { background: #fbcfe8; color: #9d174d; }
.zone--red    td { background: #fecaca; color: #991b1b; }
.zone--blue   td { background: #bfdbfe; color: #1e40af; }
.zone--purple td { background: #ddd6fe; color: #5b21b6; }
.is-sneller { color: var(--ok); font-weight: 600; }
.is-trager { color: var(--bad); font-weight: 600; }

/* Hoeveel procent van de verwachting van de groep gehaald is. Klein onder het
   cijfer zelf: het cijfer is het antwoord, dit is de maatstaf ernaast. */
.norm { font-size: .68rem; font-weight: 600; color: var(--text-subtle); line-height: 1.3; }
.norm.is-onder { color: var(--bad); }
.norm.is-boven { color: var(--ok); }

/* Het totaal van een wedstrijd: mag opvallen, het is waar je voor kwam. */
.kostprijs { font-size: 1.15rem; font-variant-numeric: tabular-nums; }

/* Het driemaandenoverzicht in het portaal: één groep, wat er van hem verwacht
   wordt, en wat ervan terechtkwam. Bij een groepswissel staan er twee blokken
   onder elkaar, vandaar de scheidingslijn. */
.card__body + .card__body .periodekop { border-top: 1px solid var(--border); padding-top: .9rem; }
.periodekop { display: flex; align-items: baseline; gap: .6rem; flex-wrap: wrap; margin-bottom: .75rem; }
.feiten { display: flex; gap: .4rem 1.25rem; flex-wrap: wrap; margin: .6rem 0 0; padding: 0; list-style: none; font-size: .82rem; }
.feiten li { color: var(--text-subtle); }

/* De documenten van een wedstrijd in het portaal: naast elkaar, want het zijn
   er meestal twee of drie en ze horen bij de kaart erboven. */
.documenten { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; margin-bottom: 1rem; }

/* Het dagscherm: alle trainingen van één dag onder elkaar. De kop draagt de
   pijlen naar gisteren en morgen, want wie een achterstand wegwerkt, loopt de
   dagen af. */
.dagkop { display: flex; align-items: center; gap: .75rem; flex-wrap: wrap; margin-bottom: 1rem; }
.momentkop {
  display: flex; align-items: baseline; gap: .6rem; flex-wrap: wrap;
  margin: 1.25rem 0 .5rem; padding-bottom: .35rem;
  border-bottom: 1px solid var(--border);
}
/* Ruim onder de balk bovenaan: springt het scherm naar een groep, dan hoort
   haar naam zichtbaar te zijn en niet onder die balk te verdwijnen. */
.dagblok { margin-bottom: .75rem; scroll-margin-top: 6rem; }
/* De groep waarvoor je klikte, licht even op. Zonder dat zie je na het
   springen vier blokken die er allemaal hetzelfde uitzien. */
.dagblok.is-aangewezen { outline: 2px solid var(--accent); outline-offset: 2px; }
.dagblok__kop { cursor: pointer; list-style: none; gap: .5rem; flex-wrap: wrap; }
.dagblok__kop::-webkit-details-marker { display: none; }
.dagblok__kop::before {
  content: "\25B8"; color: var(--text-subtle); font-size: .8rem; transition: transform .15s;
}
.dagblok[open] > .dagblok__kop::before { transform: rotate(90deg); }
.dagblok__kop h2 { margin: 0; font-size: 1rem; }
.dagblok__knoppen { display: flex; gap: .5rem; flex-wrap: wrap; padding-bottom: .25rem; }

/* Trainingen per week in het portaal. Een lijst van twintig achter elkaar
   leest niemand uit; per week is het wat een ouder in zijn hoofd heeft. */
.week { border-top: 1px solid var(--border); }
.week:first-of-type { border-top: 0; }
.week__kop {
  display: flex; align-items: baseline; gap: .6rem; flex-wrap: wrap;
  padding: .7rem 1rem; cursor: pointer; list-style: none;
  background: var(--bg-sunken);
}
.week__kop::-webkit-details-marker { display: none; }
.week__kop::before {
  content: "▸"; color: var(--text-subtle); font-size: .8rem;
  transition: transform .15s;
}
.week[open] > .week__kop::before { content: "▾"; }
.week__kop:hover { background: var(--bg-hover); }
.week__naam { font-weight: 650; }

/* De balk die verschijnt zodra er iets aangevinkt is.

   Vast aan het vénster, niet aan het formulier: met sticky verdween hij zodra
   je boven of onder het formulier stond, en op een telefoon met tien weken
   trainingen is dat het grootste deel van de tijd. */
.actiebalk {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 40;
  display: flex; align-items: center; gap: .75rem; justify-content: center;
  padding: .7rem 1rem calc(.7rem + env(safe-area-inset-bottom));
  background: var(--bg-raised);
  border-top: 1px solid var(--border);
  box-shadow: 0 -4px 20px rgba(16, 32, 55, .16);
}
.actiebalk[hidden] { display: none; }
.actiebalk .btn { padding-left: 1.4rem; padding-right: 1.4rem; }
/* Op een breed scherm begint hij naast de zijbalk, anders dekt hij die af. */
@media (min-width: 900px) {
  .actiebalk { left: var(--sidebar-w); }
}
/* Zodat de laatste rij niet onder de balk verdwijnt. */
body.heeft-actiebalk .content { padding-bottom: 5.5rem; }

/* Wat verder in het seizoen ligt, staat achter één klik. Twintig weken
   uitrollen op een telefoon is scrollen zonder doel. */
.week--rest > .week__kop { background: var(--bg-raised); font-style: italic; }

/* ------------------------------------------------ selectiematrix */
/* Zwemmers als rijen, programmanummers als kolommen — de vorm waarin een
   trainer zijn hele voorstel in één blik ziet. De naamkolom en de kopregel
   blijven staan bij het scrollen, anders ben je bij nummer 30 kwijt wie je
   voor je hebt. */

.matrix-wrap { overflow: auto; max-height: 78vh; }
table.matrix {
  border-collapse: separate;
  border-spacing: 0;
  font-size: .8rem;
  white-space: nowrap;
}
table.matrix th, table.matrix td {
  border-bottom: 1px solid var(--border);
  border-right: 1px solid var(--border);
  padding: 0;
}
table.matrix thead th {
  position: sticky; top: 0; z-index: 3;
  background: var(--bg-sunken);
  padding: .3rem .25rem;
  font-size: .68rem; font-weight: 600; color: var(--text-muted);
  vertical-align: bottom;
}
.matrix__naam {
  position: sticky; left: 0; z-index: 2;
  background: var(--bg-raised);
  text-align: left; font-weight: 500;
  padding: .2rem .5rem !important;
  min-width: 11rem;
}
table.matrix thead th.matrix__naam { z-index: 4; }
.matrix__kop { min-width: 3.2rem; }
.matrix__nummer { display: block; font-weight: 700; color: var(--text); }
.matrix__afstand { display: block; }
.matrix__geslacht { display: block; opacity: .7; }
.matrix__telling {
  text-align: center; min-width: 2rem;
  font-weight: 600; color: var(--text-muted);
  background: var(--bg-sunken);
}
.matrix__telling.is-vol { background: var(--bad-bg); color: var(--bad); }
.matrix__jaar th {
  position: sticky; left: 0;
  background: var(--bg-sunken);
  text-align: left; padding: .2rem .5rem !important;
  font-size: .7rem; letter-spacing: .05em; color: var(--text-subtle);
}
table.matrix tbody tr:hover td.cel { outline: 1px solid var(--border-strong); outline-offset: -1px; }

/* De overgang naar een ander dagdeel of een andere dag. Uit de nummers alleen
   valt niet af te lezen waar de middagpauze zit; drie nummers na elkaar is iets
   heel anders dan drie nummers over twee dagen. Een streep links van de eerste
   kolom van elk nieuw deel, en een zwaardere bij een nieuwe dag. */
table.matrix th.is-sessie, table.matrix td.is-sessie {
  border-left: 3px solid var(--text-muted);
}
table.matrix th.is-dag, table.matrix td.is-dag {
  border-left: 3px solid var(--accent);
}
.matrix-legende-streep {
  display: inline-block; width: 0; height: .75rem;
  border-left: 3px solid var(--text-muted);
  vertical-align: -2px; margin: 0 .35rem 0 .15rem;
}
.matrix-legende-streep.is-dag { border-left-color: var(--accent); }

/* De cellen zelf: aanklikbaar en groen, of geblokkeerd en rood. */
.cel { position: relative; text-align: center; }
.cel--leeg { background: var(--bg-sunken); }
.cel__vink { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.cel__vlak {
  display: block; min-width: 3.2rem; height: 1.9rem; line-height: 1.9rem;
  cursor: pointer; color: var(--text-subtle);
  -webkit-tap-highlight-color: transparent;
  transition: background .1s ease, color .1s ease;
}
.cel__vlak:hover { background: var(--bg-hover); }
.cel__tijd { font-size: .68rem; }
.cel__vink:checked + .cel__vlak {
  background: var(--ok-bg); color: var(--ok); font-weight: 700;
}
.cel__vink:checked + .cel__vlak::before { content: "✓ "; }
.cel__vink:focus-visible + .cel__vlak { outline: 2px solid var(--accent); outline-offset: -2px; }
/* Geblokkeerd is geblokkeerd. LIM, CAT, NT en NB zeggen elk iets anders over
   de réden, maar de uitkomst is telkens dezelfde: deze zwemmer kan hier niet
   aangevinkt worden. Ze verschillend inkleuren suggereerde een verschil in
   ernst dat er niet is — enkel de letters verschillen. */
.cel--niet {
  background: var(--bad-bg); color: var(--bad);
  font-size: .66rem; font-weight: 700; letter-spacing: .03em;
  height: 1.9rem;
}
/* CAT komt veruit het vaakst voor: één damesnummer weert in één keer alle
   jongens. Op volle sterkte kleurt daarmee het halve scherm rood en valt niet
   meer op wáár je moet kijken. Zelfde rood, halve sterkte — het blijft
   hetzelfde formalisme, alleen rustiger. */
.cel--zacht {
  background: color-mix(in srgb, var(--bad-bg) 45%, var(--bg-raised));
  color: color-mix(in srgb, var(--bad) 55%, var(--text-subtle));
}
/* Het bonusnummer. De B verschijnt pas in een aangevinkt vakje — een bonus op
   een nummer waar hij niet op staat, betekent niets — en een vakje dat bonus
   is, krijgt een streepjesrand: zo zie je over de hele rij welke start als
   eerste kan wegvallen. */
.cel__bonus { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.cel__b {
  display: none;
  position: absolute; top: 1px; right: 1px;
  padding: 0 .2rem; border-radius: 3px;
  font-size: .58rem; font-weight: 700; line-height: 1.1;
  color: var(--text-subtle); background: var(--bg-raised);
  border: 1px solid var(--border);
  cursor: pointer;
}
.cel__vink:checked ~ .cel__b { display: block; }
.cel__bonus:checked + .cel__b { color: #fff; background: var(--accent); border-color: var(--accent); }
.cel__bonus:disabled + .cel__b { cursor: default; }
.cel__bonus:focus-visible + .cel__b { outline: 2px solid var(--accent); outline-offset: 1px; }
.cel:has(.cel__vink:checked):has(.cel__bonus:checked) .cel__vlak {
  outline: 2px dashed var(--accent); outline-offset: -3px;
}
/* Wat de zwemmer zelf vroeg, in de hoek van het vakje waar je erover beslist.
   Linksonder, tegenover de B van een bonus: de twee kunnen samen voorkomen en
   mogen elkaar niet overdekken. Altijd zichtbaar, ook op een leeg vakje —
   anders zie je juist de vraag niet die nog beantwoord moet worden. */
.cel__wens {
  position: absolute; left: 1px; bottom: 1px;
  padding: 0 .2rem; border-radius: 3px;
  font-size: .62rem; font-weight: 700; line-height: 1.1;
  color: #fff; background: var(--ok); pointer-events: none;
}
.cel__wens.is-weg { background: var(--bad); }

.cel-legende.is-bonus { background: var(--accent); color: #fff; }
.cel-legende.is-wens { background: var(--ok); color: #fff; }
.cel-legende.is-wens-weg { background: var(--bad); color: #fff; }
.cel-legende {
  display: inline-block; padding: 0 .25rem; border-radius: 3px;
  font-size: .66rem; font-weight: 700;
  background: var(--bad-bg); color: var(--bad);
}
.cel-legende.cel--zacht {
  background: color-mix(in srgb, var(--bad-bg) 45%, var(--bg-raised));
  color: color-mix(in srgb, var(--bad) 55%, var(--text-subtle));
}

/* --------------------------------------------- aanwezigheid aan het bad */
/* Dit scherm wordt op een telefoon ingevuld, met natte handen, naast het
   water. Geen tabel dus, maar per zwemmer twee regels en tikvlakken van een
   goede vinger breed. */

.aanw-lijst { display: flex; flex-direction: column; }
.aanw-rij { padding: .65rem .9rem; border-bottom: 1px solid var(--border); }
.aanw-rij:last-child { border-bottom: 0; }
.aanw-rij.is-bad { background: color-mix(in srgb, var(--bad-bg) 40%, transparent); }
.aanw-regel { display: flex; align-items: center; gap: .55rem; }
.aanw-regel--onder { margin-top: .45rem; }
.aanw-naam { flex: 1 1 auto; min-width: 0; font-weight: 600; }
.aanw-status { flex: 0 0 9.5rem; }
.aanw-notitie { flex: 1 1 9rem; min-width: 0; }
.aanw-melding { margin-top: .3rem; }

/* Kop boven de gasten: geen eigen kaart, wel een duidelijke scheiding. */
.aanw-kop {
  display: flex; align-items: baseline; gap: .5rem; flex-wrap: wrap;
  padding: .6rem .9rem;
  border-top: 1px solid var(--border);
  background: var(--bg-sunken);
  font-size: .76rem; font-weight: 600;
  text-transform: uppercase; letter-spacing: .04em;
  color: var(--text-muted);
}
.aanw-kop .subtle { text-transform: none; letter-spacing: 0; font-weight: 400; }
.aanw-weg { flex: 0 0 auto; padding: .1rem .5rem; font-size: 1.1rem; line-height: 1.2; }
.aanw-gast select { max-width: 18rem; }

.blokjes { display: flex; gap: .3rem; flex: 0 0 auto; position: relative; }
/* De radio zelf is onzichtbaar; het label is het blokje dat je aantikt. */
.blokje-radio {
  position: absolute; width: 1px; height: 1px;
  opacity: 0; pointer-events: none;
}
.blokje {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 2.75rem; height: 2.75rem; padding: 0 .3rem;
  border: 1px solid var(--blue-600); border-radius: var(--radius-sm);
  background: var(--blue-500); color: #fff;
  font-size: .85rem; font-weight: 600; line-height: 1;
  cursor: pointer; user-select: none;
  -webkit-tap-highlight-color: transparent;
  transition: background .12s ease, color .12s ease, border-color .12s ease;
}
/* Het blokje 'niet in het water geweest'. Iets losser van de rest, want het
   zegt iets anders dan 'tot hier gezwommen'. */
.blokje--nul {
  background: var(--bg-sunken); color: var(--text-muted);
  border-color: var(--border-strong);
  margin-right: .25rem;
}
.blokje--nul:hover { background: var(--bad-bg); color: var(--bad); border-color: var(--bad); }

/* Alles ná het aangetikte blokje is niet gezwommen. Puur CSS, geen javascript:
   elk blokje dat in de rij achter het aangevinkte rondje staat, kleurt rood.
   Elk label staat daarom vóór zijn eigen rondje — met het rondje eerst zou
   hier een tweede ~ nodig zijn, en die herrekent de browser niet betrouwbaar. */
.blokje-radio:checked ~ .blokje {
  background: var(--bad-bg); border-color: var(--bad); color: var(--bad);
}
.blokjes:has(.blokje-radio:focus-visible) {
  outline: 2px solid var(--accent); outline-offset: 3px; border-radius: var(--radius-sm);
}
/* Wie er niet was, hoeft geen blokjes of oordeel: die zakken naar de
   achtergrond. */
.aanw-rij:has(option.is-weg:checked) .blokjes,
.aanw-rij:has(option.is-weg:checked) .oordeel { opacity: .4; }

/* ------------------------------------------ hoe er getraind werd */
/* Drie standen en een streepje om niets te zeggen. Alleen het aangetikte
   gezichtje krijgt kleur; de rest blijft grijs, zodat je in één oogopslag
   ziet wie er beoordeeld is en wie niet. */

.oordeel { display: flex; gap: .25rem; flex: 0 0 auto; position: relative; }
.oordeel-radio { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.smiley {
  display: inline-flex; align-items: center; justify-content: center;
  width: 2.5rem; height: 2.75rem;
  border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
  background: var(--bg-raised); color: var(--text-subtle);
  cursor: pointer; user-select: none;
  -webkit-tap-highlight-color: transparent;
  transition: background .12s ease, color .12s ease, border-color .12s ease;
}
.smiley--geen { width: 1.9rem; font-weight: 700; }
.smiley svg { width: 1.55rem; height: 1.55rem; fill: none; stroke: currentColor; stroke-width: 1.6; }
.smiley svg .oog { fill: currentColor; stroke: none; }
.smiley svg path { stroke-linecap: round; }

.oordeel-radio:checked + .smiley--geen {
  background: var(--bg-sunken); border-color: var(--border-strong); color: var(--text-muted);
}
.oordeel-radio:checked + .smiley--zwak {
  background: var(--bad-bg); border-color: var(--bad); color: var(--bad);
}
.oordeel-radio:checked + .smiley--gewoon {
  background: var(--warn-bg); border-color: var(--warn); color: var(--warn);
}
.oordeel-radio:checked + .smiley--sterk {
  background: var(--ok-bg); border-color: var(--ok); color: var(--ok);
}
.oordeel:has(.oordeel-radio:focus-visible) {
  outline: 2px solid var(--accent); outline-offset: 3px; border-radius: var(--radius-sm);
}

/* ------------------------------------------------------------ responsive */

@media (max-width: 900px) {
  .layout { flex-direction: column; }
  .sidebar {
    position: static; width: 100%; flex: none; height: auto;
  }
  .sidebar__nav { display: none; padding: .5rem; }
  .sidebar.is-open .sidebar__nav { display: block; }
  .sidebar.is-open .sidebar__footer { display: block; }
  .sidebar__footer { display: none; }
  .topbar .menu-toggle { display: inline-flex; }
  .content { padding: 1rem; }
  .topbar { padding: .75rem 1rem; flex-wrap: wrap; gap: .625rem; }
  .topbar h1 { font-size: 1.05rem; }
  /* Knoppen op een eigen rij, anders lopen ze buiten beeld. */
  .topbar__actions { width: 100%; margin-left: 0; }
  .topbar__actions .btn { flex: 1 1 auto; }
  .grid--2, .grid--3 { grid-template-columns: 1fr; }
  /* Kerncijfers blijven twee per rij, anders scrol je eindeloos. */
  .grid--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .75rem; }
  .stat__value { font-size: 1.35rem; }
  .filters .field, .filters .field--wide { min-width: 100%; }
  .filters { gap: .5rem; }

  /* Aanwezigheid op de telefoon: twee regels per zwemmer, met de naam en de
     status naast elkaar. 16px op de invulvelden, anders zoomt Safari bij elke
     tik in en sta je te scrollen aan de rand van het bad. */
  .aanw-rij { padding: .6rem .75rem; }
  .aanw-regel { flex-wrap: wrap; gap: .4rem; }
  .aanw-naam { flex: 1 1 7rem; }
  .aanw-status { flex: 0 0 7.5rem; font-size: 16px; padding: .42rem .35rem; }
  /* Bij een lange training gaan de blokjes op een tweede rij in plaats van
     smaller te worden: ze moeten aantikbaar blijven. */
  .blokjes { flex: 0 1 auto; flex-wrap: wrap; }
  /* Op een telefoon is er ruimte voor de blokjes óf voor de gezichtjes, niet
     voor allebei op één regel. Ze mogen dus onder elkaar; de tikvlakken op 44
     pixels houden weegt zwaarder dan één regel scrollen minder. */
  .oordeel { flex: 0 1 auto; }
  .aanw-notitie { flex: 1 1 5rem; font-size: 16px; }
}

@media print {
  .sidebar, .topbar, .page-actions, .filters, .btn { display: none !important; }
  .content { padding: 0; }
  .card { box-shadow: none; border: 1px solid #ccc; break-inside: avoid; }
  body { background: #fff; }
}

/* Het maximablok in het wedstrijdformulier: een rij per zin uit het
   reglement, met de velden zelf in de cellen. Smal gehouden, zodat vijf
   kolommen naast elkaar passen zonder dat de tabel gaat schuiven. */
table.maxima { table-layout: fixed; width: 100%; }
table.maxima th { white-space: normal; vertical-align: bottom; }
table.maxima td { padding: .3rem .4rem; }
table.maxima input { width: 100%; min-width: 4.5rem; }

/* Het logboek van de oudercontacten: één verslag per regel, dichtgeklapt.
   Een gesprek van vorig jaar hoort niet even lang op het scherm te staan als
   dat van vorige week — open staat enkel het jongste, de rest wacht achter
   zijn eigen regel. De tekst zelf behoudt de regelovergangen die de
   hoofdtrainer tikte; die zeggen vaak waar een nieuw punt begint. */
.gesprek { border-top: 1px solid var(--border); padding: .5rem 0; }
.gesprek:first-child { border-top: none; }
.gesprek > summary { cursor: pointer; padding: .3rem 0; }
.gesprek > summary:hover { color: var(--text); }
.gesprek__body { padding: .4rem 0 .6rem 1.1rem; }
.gesprek__tekst { white-space: pre-wrap; margin: 0 0 .5rem; }
.gesprek__wijzig { margin-top: .6rem; border-top: 1px dashed var(--border); padding-top: .5rem; }
.gesprek__wijzig > summary { cursor: pointer; color: var(--text-muted); }

/* De stand van een schakelaar in Beheer: wat er nú geldt, leest zwaarder dan
   wat er zou gelden. Anders lijken beide zinnen even waar en klikt een
   beheerder op goed geluk. */
.schakelaar__stand { margin: .4rem 0 .3rem; }

/* De honderdlijn in de puntenwolk van belasting tegenover resultaat: precies
   even snel als voordien. Zonder die lijn lijkt de onderste stip een zwakke
   zwemmer, ook als hij een halve procent onder zijn besttijd bleef. */
.chart__nul { stroke: var(--text-muted); stroke-width: 1.5; stroke-dasharray: 4 3; }

/* De baanagenda. Eén blok is één regel met losse velden naast elkaar, en geen
   tabel: vijf invoervelden in een tabelcel lopen buiten hun kolom zodra er een
   reden bij staat, en dan ligt het scherm over zichzelf heen. Met flex-wrap
   schuift de reden netjes naar de volgende regel wanneer het smal wordt. */
.baanregel {
  display: flex; align-items: center; gap: .4rem; flex-wrap: wrap;
  margin-bottom: .4rem;
}
/* De breedtes moeten het winnen van de basisregel voor invoervelden, en die
   selecteert op [type=...]. Vandaar overal het type erbij: anders krijgt elk
   veld width:100% en breekt één blok over drie regels. */
.baanregel input[type="time"] { width: 7.5rem; flex: none; }
.baanregel input[type="number"].baanregel__aantal { width: 4.5rem; flex: none; text-align: right; }
.baanregel select { width: 5.5rem; flex: none; }
.baanregel__label { font-size: .8rem; color: var(--text-muted); flex: none; }
.baanregel input[type="text"].baanregel__reden { flex: 1 1 12rem; width: auto; min-width: 0; }

/* De trainingen boven het invulveld: wat er die avond in het water lag. Ze
   staan er niet ter versiering — wie ziet dat er vier groepen trainen, vult
   het aantal banen met meer aandacht in. */
.baandag__trainingen { padding-bottom: .4rem; }
.baantraining {
  display: flex; align-items: baseline; gap: .75rem; flex-wrap: wrap;
  padding: .3rem 0; border-top: 1px solid var(--border);
  font-size: .875rem;
}
.baandag__trainingen .baantraining:first-child { border-top: none; }
.baantraining.is-bad { color: var(--bad); }
.baantraining__uur { font-weight: 600; flex: 0 0 7.5rem; }
.baantraining__groepen { flex: 1 1 10rem; color: var(--text-muted); }
.baantraining__cijfer { flex: 0 0 auto; }

.baandag__anders > summary { cursor: pointer; color: var(--text-muted); }
.baandag__anders > summary:hover { color: var(--text); }
.baandag__anders[open] > summary { margin-bottom: .6rem; }

.baanstandaard > summary { cursor: pointer; padding: .85rem 1rem; }
.baanstandaard__dag {
  display: flex; align-items: baseline; gap: .75rem;
  padding: .45rem 0; border-top: 1px solid var(--border);
}
.baanstandaard__dag:first-child { border-top: none; }
.baanstandaard__naam { flex: 0 0 6rem; font-weight: 600; font-size: .875rem; }
.baanstandaard__regels { flex: 1 1 auto; min-width: 0; }

@media (max-width: 720px) {
  /* Een paneeltje van 17rem past niet meer naast de knop: op 375 pixels liep
     het er tweeëntwintig naast. Dan valt het gewoon ónder de knop en duwt het
     de rest naar beneden — niets afgeknipt, en de duim raakt alles. */
  /* Het paneeltje hangt zich niet meer op aan de knop maar aan de bladzijde:
     zonder positioned ouder valt het terug op de linkerrand van het scherm, en
     dan past het altijd. Verticaal blijft het staan waar de knop staat.
     Meelopen met de knop ging niet — die staat in een flexrij die niet
     afbreekt, en dan duwt het paneel de hele bladzijde breder. */
  .inline-actie:has(> .paneel) { position: static; }
  .inline-actie > .paneel {
    left: .5rem; right: .5rem; width: auto;
  }

  /* Op een telefoon past de dagnaam niet naast de velden. */
  .baanstandaard__dag { flex-direction: column; gap: .25rem; }
  .baanstandaard__naam { flex: none; }
  .baantraining__uur { flex: 0 0 auto; }
}

/* 'Toch verwachten' bij een zwemmer met rust op het dagscherm: de knop hoort
   bij de naam en niet aan het eind van de regel, want bij zeven namen weet je
   anders niet welke je aanklikt. */
.baandag__rust { display: flex; align-items: baseline; gap: .5rem; flex-wrap: wrap; }
.rustnaam { display: inline-flex; align-items: baseline; gap: .25rem; font-size: .875rem; }
.rustnaam .btn { padding: .05rem .35rem; font-size: .72rem; }
