/* =========================================================================
   Gym 74 — designsysteem
   Donkere, premium uitstraling: bijna zwart oppervlak, één warm accent,
   kaarten met zachte randen, uppercase koppen met ruime letterafstand en een
   vaste tabbalk onderin. Alle kleuren staan als variabele bovenaan, zodat het
   accent in één plek te wisselen is.
   ========================================================================= */

:root {
  /* Oppervlakken — bijna zwart, met een paar stappen hoogte. */
  --bg: #0a0a0c;
  --bg-deep: #060607;
  --surface: #131317;
  --surface-hi: #1a1a20;
  --line: rgb(255 255 255 / 8%);
  --line-strong: rgb(255 255 255 / 16%);

  /* Tekst */
  --text: #f4f4f7;
  --muted: #9b9ba7;
  --muted-dim: #6f6f7c;

  /* Accent — warm goud. Eén kleur draagt de hele app: knoppen, actieve tab,
     kerncijfers. Wissel deze drie waarden om de app een andere kleur te geven. */
  --accent: #d9a441;
  --accent-hi: #f3d489;
  --accent-ink: #17120a;
  --accent-glow: rgb(217 164 65 / 18%);
  --accent-line: rgb(217 164 65 / 35%);
  --accent-grad: linear-gradient(135deg, var(--accent-hi), var(--accent));

  /* Status */
  --success: #4ade80;
  --success-bg: rgb(74 222 128 / 12%);
  --error: #f87171;
  --error-bg: rgb(248 113 113 / 12%);

  /* Vorm */
  --radius: 16px;
  --radius-sm: 10px;
  --radius-pill: 999px;
  --tabbar-h: 4.5rem;

  --shadow: 0 8px 28px rgb(0 0 0 / 45%);
}

* {
  box-sizing: border-box;
}

/* Een klassenselector met `display` is specifieker dan de browserregel voor
   [hidden]; zonder deze regel blijven verborgen elementen zichtbaar. */
[hidden] {
  display: none !important;
}

html {
  scroll-behavior: smooth;
}

body {
  margin: 0;
  min-height: 100vh;
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  color: var(--text);
  background:
    radial-gradient(120% 60% at 50% 0%, rgb(217 164 65 / 6%), transparent 60%),
    var(--bg);
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

/* --- Appbalk boven ------------------------------------------------------ */

.appbar {
  position: sticky;
  top: 0;
  z-index: 30;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  height: 3.5rem;
  padding: 0 1rem;
  background: rgb(10 10 12 / 82%);
  backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--line);
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-weight: 800;
  font-size: 1rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  text-decoration: none;
  background: var(--accent-grad);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* Het beeldmerk draagt zijn eigen goudverloop; het hoeft geen kleur van de
   tekst te erven. Ruim groter dan de letters: het logo heeft een vierkant
   kader met lucht eromheen, dus op tekstgrootte valt de "74" weg. */
.brand img {
  width: 2rem;
  height: 2rem;
  display: block;
  flex: 0 0 auto;
}

.appbar-action {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: var(--radius-pill);
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--muted);
  text-decoration: none;
}

.appbar-action svg {
  width: 1.1rem;
  height: 1.1rem;
  stroke: currentcolor;
  fill: none;
  stroke-width: 1.8;
}

/* --- Pagina ------------------------------------------------------------- */

.page {
  max-width: 30rem;
  margin: 0 auto;
  padding: 1.5rem 1rem calc(var(--tabbar-h) + 2rem);
}

.page--wide {
  max-width: 44rem;
}

/* Zonder tabbalk (inlogschermen) is die onderruimte niet nodig. */
body:not(.has-tabbar) .page {
  padding-bottom: 3rem;
}

header.bar {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 0.35rem;
}

/* Bovenschrift boven de kop in plaats van een link ernaast. */
header.bar--stacked {
  display: block;
  margin-bottom: 0.5rem;
}

h1 {
  font-size: 1.65rem;
  font-weight: 800;
  letter-spacing: 0.01em;
  text-transform: uppercase;
  margin: 0;
  line-height: 1.15;
}

h2 {
  font-size: 1rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  margin: 0 0 0.85rem;
}

h3 {
  font-size: 0.9rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  margin: 1.1rem 0 0.4rem;
}

.subtitle {
  color: var(--muted);
  margin: 0 0 1.5rem;
  font-size: 0.92rem;
}

/* Klein bovenschrift boven een kop. */
.eyebrow {
  display: block;
  color: var(--muted-dim);
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  margin-bottom: 0.3rem;
}

/* --- Kaarten ------------------------------------------------------------ */

.card {
  position: relative;
  background: linear-gradient(180deg, var(--surface-hi), var(--surface));
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.15rem;
  margin-bottom: 1rem;
}

/* Kaart die om aandacht vraagt: lopende sessie, records. */
.card--accent {
  border-color: var(--accent-line);
  background:
    linear-gradient(180deg, rgb(217 164 65 / 10%), transparent 55%),
    linear-gradient(180deg, var(--surface-hi), var(--surface));
  box-shadow: 0 0 0 1px rgb(217 164 65 / 8%), var(--shadow);
}

/* --- Knoppen ------------------------------------------------------------ */

button,
.btn,
.links a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  width: 100%;
  padding: 0.85rem 1.1rem;
  font-family: inherit;
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--accent-ink);
  background: var(--accent-grad);
  border: 0;
  border-radius: var(--radius-pill);
  cursor: pointer;
  transition: filter 0.15s ease, transform 0.06s ease;
}

button:hover,
.btn:hover {
  filter: brightness(1.08);
}

button:active,
.btn:active,
.links a:active {
  transform: translateY(1px);
}

button:disabled {
  opacity: 0.45;
  cursor: not-allowed;
  filter: none;
}

/* Terughoudende variant: rand in plaats van vlak. Een lijst met navigatielinks
   (.links) krijgt dezelfde look als "Lege training starten" op de
   trainingspagina: genoeg links per scherm om ze niet allemaal als primaire
   actie (het volle vlak) te laten schreeuwen. */
button.secondary,
.btn--ghost,
.links a {
  background: transparent;
  color: var(--text);
  border: 1px solid var(--line-strong);
}

button.secondary:hover,
.links a:hover {
  background: var(--surface-hi);
  filter: none;
  text-decoration: none;
}

button.inline {
  width: auto;
  padding: 0.42rem 0.8rem;
  font-size: 0.7rem;
  letter-spacing: 0.1em;
}

/* --- Formulieren -------------------------------------------------------- */

label {
  display: block;
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 0.4rem;
}

input,
select,
textarea {
  width: 100%;
  padding: 0.8rem 0.85rem;
  font-family: inherit;
  font-size: 1rem;
  color: var(--text);
  background: var(--bg-deep);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  transition: border-color 0.15s ease;
}

input::placeholder,
textarea::placeholder {
  color: var(--muted-dim);
}

input:hover,
select:hover,
textarea:hover {
  border-color: var(--line-strong);
}

/* Een omschrijvingsveld groeit alleen in de hoogte; zijwaarts rekken breekt
   de kolom waar het in staat. */
textarea {
  resize: vertical;
  line-height: 1.5;
}

input[type="file"] {
  padding: 0.6rem;
  color: var(--muted);
}

/* Een datumveld krijgt op iOS een eigen minimumbreedte en een eigen opmaak, en
   trekt zich niets aan van de kolom waar het in staat: op een telefoon liep het
   daardoor over de rand van het blok eromheen. `appearance: none` haalt die
   opgelegde opmaak eraf en `min-width: 0` laat het veld meekrimpen met zijn
   kolom, zoals elk ander veld hierboven al doet. */
input[type="date"] {
  appearance: none;
  -webkit-appearance: none;
  min-width: 0;
  max-width: 100%;
}

.field {
  margin-bottom: 1rem;
}

/* Een toelichting boven een veld hoort niet tegen het label te plakken. */
.hint + .field,
.hint + form,
p + .field {
  margin-top: 1rem;
}

.hint {
  color: var(--muted);
  font-size: 0.78rem;
  margin: 0.4rem 0 0;
}

ul.rules {
  margin: 0.5rem 0 0;
  padding-left: 1.1rem;
  color: var(--muted-dim);
  font-size: 0.75rem;
}

ul.errors {
  margin: 0 0 1rem;
  padding-left: 1.1rem;
  color: var(--error);
  font-size: 0.82rem;
}

ul.errors:empty {
  display: none;
}

details summary {
  cursor: pointer;
  margin-bottom: 0.85rem;
  color: var(--muted);
  font-size: 0.78rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* --- Links en meldingen ------------------------------------------------- */

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

a:hover {
  text-decoration: underline;
}

.links {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  margin-top: 1.1rem;
  text-align: center;
  font-size: 0.9rem;
}

.message {
  padding: 0.75rem 0.9rem;
  border-radius: var(--radius-sm);
  margin-bottom: 1rem;
  font-size: 0.85rem;
  border: 1px solid transparent;
}

.message:empty {
  display: none;
}

.message.error {
  background: var(--error-bg);
  border-color: rgb(248 113 113 / 30%);
  color: var(--error);
}

.message.success {
  background: var(--success-bg);
  border-color: rgb(74 222 128 / 25%);
  color: var(--success);
}

/* --- Taalkeuze ---------------------------------------------------------- */

.lang {
  width: auto;
  padding: 0.4rem 0.6rem;
  font-size: 0.78rem;
  border-radius: var(--radius-pill);
  background: var(--surface);
}

/* --- Tabellen ----------------------------------------------------------- */

.table-scroll {
  overflow-x: auto;
  margin: 0 -0.25rem;
}

table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.88rem;
}

th,
td {
  text-align: left;
  padding: 0.75rem 0.5rem;
  border-bottom: 1px solid var(--line);
  vertical-align: middle;
}

tbody tr:last-child td {
  border-bottom: 0;
}

th {
  font-size: 0.66rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--muted-dim);
}

td.actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
}

/* --- Trainingsklokken --------------------------------------------------- */

.clockbar {
  position: sticky;
  top: 3.5rem;
  z-index: 20;
  display: flex;
  gap: 0.9rem;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  padding: 0.55rem 0.75rem;
  background: rgb(10 10 12 / 88%);
  backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--accent-line);
}

.clock {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  font-variant-numeric: tabular-nums;
}

.clock strong {
  font-size: 1.2rem;
  font-weight: 800;
}

.clockbar button {
  padding: 0.3rem 0.65rem;
  font-size: 0.6rem;
  width: auto;
}

.clock.rest strong {
  background: var(--accent-grad);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.clock-label {
  color: var(--muted-dim);
  font-size: 0.6rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.16em;
}

/* --- Setregels ---------------------------------------------------------- */

.setrow {
  display: grid;
  grid-template-columns: 1fr 4.25rem 4.25rem 2rem 1.6rem;
  gap: 0.5rem;
  align-items: center;
  padding: 0.6rem 0;
  border-bottom: 1px solid var(--line);
}

.setrow:last-child {
  border-bottom: 0;
}

.setrow.done {
  opacity: 0.5;
}

.setrow .target {
  font-size: 0.85rem;
  font-variant-numeric: tabular-nums;
}

input.small {
  padding: 0.5rem 0.5rem;
  font-size: 0.9rem;
  text-align: center;
}

/* Eigen vinkje: een wit systeemvakje valt uit de toon in een donkere app. */
input.tick {
  appearance: none;
  width: 1.6rem;
  height: 1.6rem;
  justify-self: end;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  background: var(--bg-deep);
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease;
}

input.tick:hover {
  border-color: var(--accent-line);
}

input.tick:checked {
  background:
    /* vinkje */
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2317120a' stroke-width='3.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 12.5 9.5 18 20 6.5'/%3E%3C/svg%3E")
      center / 68% no-repeat,
    var(--accent-grad);
  border-color: transparent;
}

/* Superset/megaset als één blok. */
.card.group {
  border-left: 3px solid var(--accent);
}

.badge {
  display: inline-block;
  margin: 0 0 0.6rem;
  padding: 0.2rem 0.6rem;
  border-radius: var(--radius-pill);
  background: var(--accent-glow);
  border: 1px solid var(--accent-line);
  color: var(--accent-hi);
  font-size: 0.64rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.14em;
}

/* --- Agenda ------------------------------------------------------------- */

/* Datum en naam op één regel, acties compact eronder — anders vult één
   agendaregel op een telefoon het halve scherm. */
.agenda-item {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: baseline;
  column-gap: 0.85rem;
  row-gap: 0.5rem;
  padding: 0.85rem 0;
  border-bottom: 1px solid var(--line);
}

.agenda-item .actions {
  grid-column: 1 / -1;
}

.agenda-item .actions button {
  padding: 0.32rem 0.7rem;
  font-size: 0.64rem;
  letter-spacing: 0.08em;
}

.agenda-item:last-child {
  border-bottom: 0;
}

.agenda-item.done {
  opacity: 0.5;
}

.agenda-item .when,
.today-item .when,
.today-macro .when {
  min-width: 5.5rem;
  color: var(--muted);
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.agenda-item .what {
  flex: 1;
  font-weight: 700;
  letter-spacing: 0.02em;
}

.agenda-item .actions {
  display: flex;
  gap: 0.35rem;
  flex-wrap: wrap;
}

/* --- Lopende sessie ----------------------------------------------------- */

.live-session {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  flex-wrap: wrap;
  margin-bottom: 0.9rem;
}

.live-session .what {
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.live-session .meta {
  color: var(--muted);
  font-size: 0.8rem;
  font-variant-numeric: tabular-nums;
}

/* Klein pulserend puntje: er loopt iets. */
.live-dot {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.15rem 0.6rem;
  border-radius: var(--radius-pill);
  border: 1px solid var(--accent-line);
  color: var(--accent-hi);
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.live-dot::before {
  content: "";
  width: 0.45rem;
  height: 0.45rem;
  border-radius: 50%;
  background: var(--accent-hi);
  animation: pulse 1.6s ease-in-out infinite;
}

@keyframes pulse {
  50% {
    opacity: 0.25;
  }
}

/* --- Streak ------------------------------------------------------------- */

.streak {
  display: flex;
  gap: 0.75rem;
  justify-content: space-around;
  text-align: center;
}

.streak-item {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
}

.streak-item strong {
  font-size: 1.9rem;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  background: var(--accent-grad);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.streak-item span {
  color: var(--muted-dim);
  font-size: 0.66rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

/* --- Samenvatting na afloop --------------------------------------------- */

.summary-title {
  margin-bottom: 0.2rem;
}

.summary-cheer {
  margin: 0 0 1rem;
  color: var(--muted);
  font-size: 0.85rem;
}

/* De cijfers van de training als losse tegels: hetzelfde gewicht op het
   scherm als de records, want afronden is op zichzelf al goed. */
.summary-stats {
  display: grid;
  /* Twee bij twee op een telefoon — vier naast elkaar laat "1.500 kg" over
     twee regels breken. Vanaf een breder scherm passen ze wel op één rij. */
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.6rem;
  margin: 0 0 1.1rem;
  padding: 0;
  list-style: none;
}

@media (min-width: 30rem) {
  .summary-stats {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

.summary-stat {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  padding: 0.7rem 0.5rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface);
  text-align: center;
}

.summary-stat strong {
  font-size: 1.35rem;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  background: var(--accent-grad);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.summary-stat span {
  color: var(--muted-dim);
  font-size: 0.62rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

/* --- Records na afloop -------------------------------------------------- */

.records-title {
  margin: 0 0 0.4rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.record {
  margin: 0.15rem 0;
  color: var(--accent-hi);
  font-weight: 700;
}

/* Drie assen (gewicht, volume, 1RM) vragen om kolommen: wat het was en wat
   het nu is, naast elkaar. */
.record-table {
  width: 100%;
  margin-bottom: 1.1rem;
  border-collapse: collapse;
  font-size: 0.82rem;
}

.record-table th {
  padding: 0.3rem 0.4rem;
  border-bottom: 1px solid var(--line);
  color: var(--muted-dim);
  font-size: 0.6rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-align: left;
  text-transform: uppercase;
}

.record-table td {
  padding: 0.45rem 0.4rem;
  border-bottom: 1px solid var(--line);
  vertical-align: top;
}

.record-table tbody:last-child tr:last-child td {
  border-bottom: 0;
}

/* De oefeningsnaam boven zijn eigen records, niet naast elke regel. */
.record-table .record-exercise {
  padding-top: 0.8rem;
  border-bottom: 0;
  color: var(--text);
  font-size: 0.82rem;
  letter-spacing: 0.02em;
  text-transform: none;
}

.record-table tbody:first-of-type .record-exercise {
  padding-top: 0.5rem;
}

.record-table .record-from {
  color: var(--muted-dim);
  font-variant-numeric: tabular-nums;
  text-decoration: line-through;
}

/* De eerste keer is er niets om door te strepen. */
.record-table .record-first {
  color: var(--muted-dim);
  font-style: italic;
}

.record-table .record-to {
  color: var(--accent-hi);
  font-variant-numeric: tabular-nums;
  font-weight: 700;
}

/* De set achter een 1RM-schatting: kleiner, onder het getal. */
.record-table .record-to small {
  display: block;
  color: var(--muted-dim);
  font-size: 0.7rem;
  font-weight: 500;
  white-space: nowrap;
}

/* --- Leuk feitje -------------------------------------------------------- */

.fun-fact {
  padding: 0.9rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface);
  margin-bottom: 1rem;
}

.fun-fact-title {
  margin: 0 0 0.3rem;
  color: var(--muted-dim);
  font-size: 0.62rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.fun-fact-text {
  margin: 0;
  font-size: 0.95rem;
  font-weight: 600;
}

/* Een vast kader met de verhouding van de app: wat de beheerder ook uploadt,
   het plaatje schaalt erbinnen mee en de kaart houdt zijn vorm. */
.fun-fact-figure {
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: 16 / 9;
  width: 100%;
  margin-top: 0.7rem;
  overflow: hidden;
  border-radius: var(--radius-sm);
  background: var(--bg-deep);
}

.fun-fact-figure img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}

/* --- Feitjes beheren ---------------------------------------------------- */

/* Meer dan twee bestemmingen naast een kop: op een telefoon breken ze netjes
   af in plaats van de kop weg te duwen. */
.bar-links {
  display: flex;
  flex-wrap: wrap;
  gap: 0.9rem;
}

.fact-body {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 0.9rem;
}

@media (min-width: 40rem) {
  .fact-body {
    grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
    align-items: start;
  }
}

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

/* Het voorbeeld in hetzelfde kader als in de app: wat de beheerder hier ziet,
   ziet de gebruiker straks ook. */
.fact-preview {
  margin-top: 0;
  margin-bottom: 0.6rem;
}

.fact-preview .hint {
  margin: 0;
}

/* Drie knoppen naast elkaar passen niet op een telefoon; ze breken af in
   plaats van de kaart breder te maken dan het scherm. */
.fact-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin-top: 1rem;
}

/* --- Grafiek ------------------------------------------------------------ */

.chart {
  width: 100%;
  height: 160px;
  overflow: visible;
}

.chart-line {
  stroke: var(--accent);
  stroke-width: 2;
  stroke-linejoin: round;
  stroke-linecap: round;
  vector-effect: non-scaling-stroke;
}

.chart-dot {
  fill: var(--accent-hi);
}

.chart-empty {
  fill: var(--muted-dim);
  font-size: 12px;
}

/* --- Progresfoto's ------------------------------------------------------ */

/* De buitenste lijst van dagen: geen grid, gewoon blocks die onder elkaar
   stapelen via .photo-day + .photo-day hieronder. */
#photos {
  margin-top: 1rem;
}

.photos {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(8.5rem, 1fr));
  gap: 0.75rem;
  margin-top: 1rem;
}

.photos figure {
  margin: 0;
}

.photos img {
  width: 100%;
  aspect-ratio: 3 / 4;
  object-fit: cover;
  border-radius: var(--radius-sm);
  border: 1px solid var(--line);
}

.photos figcaption {
  color: var(--muted-dim);
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  margin: 0.35rem 0;
}

/* --- Tabbalk onder ------------------------------------------------------ */

.tabbar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 30;
  display: flex;
  justify-content: space-around;
  gap: 0.15rem;
  padding: 0.5rem 0.4rem calc(0.5rem + env(safe-area-inset-bottom, 0px));
  background: rgb(8 8 10 / 92%);
  backdrop-filter: blur(14px);
  border-top: 1px solid var(--line);
}

.tab {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.25rem;
  flex: 1;
  padding: 0.45rem 0.2rem;
  border-radius: var(--radius-sm);
  color: var(--muted-dim);
  text-decoration: none;
  font-size: 0.6rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.tab:hover {
  text-decoration: none;
  color: var(--muted);
}

.tab svg {
  width: 1.35rem;
  height: 1.35rem;
  stroke: currentcolor;
  fill: none;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Actieve tab draagt het accent. */
.tab.is-active {
  color: var(--accent-hi);
  background: var(--accent-glow);
}

.tab.is-active svg {
  stroke: var(--accent-hi);
}

/* --- Offline-melding ---------------------------------------------------- */

.offline-badge {
  position: fixed;
  left: 50%;
  bottom: calc(var(--tabbar-h) + 0.75rem);
  transform: translateX(-50%);
  z-index: 25;
  padding: 0.5rem 0.95rem;
  border-radius: var(--radius-pill);
  background: var(--surface-hi);
  border: 1px solid var(--line-strong);
  color: var(--text);
  font-size: 0.78rem;
  box-shadow: var(--shadow);
}

.offline-badge:empty,
.offline-badge[hidden] {
  display: none;
}

/* --- Toegankelijkheid --------------------------------------------------- */

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  padding: 0.6rem 1rem;
  background: var(--accent);
  color: var(--accent-ink);
  font-weight: 700;
  border-radius: 0 0 var(--radius-sm) 0;
}

.skip-link:focus {
  left: 0;
}

.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;
}

a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
summary:focus-visible,
.tab:focus-visible {
  outline: 2px solid var(--accent-hi);
  outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

/* --- Wat ruimer op een groot scherm ------------------------------------- */

@media (min-width: 48rem) {
  .page {
    padding-top: 2.25rem;
  }

  /* De tabbalk houdt zijn volle achtergrond, maar de knoppen blijven bij de
     inhoud in plaats van uit te rekken over het hele scherm. */
  .tabbar {
    padding-inline: max(1rem, calc((100% - 32rem) / 2));
  }

  .appbar {
    padding-inline: max(1rem, calc((100% - 44rem) / 2));
  }

  h1 {
    font-size: 2rem;
  }

  .card {
    padding: 1.4rem;
  }
}

/* Afgevinkt maar zonder getal: laat zien wáár nog iets mist. */
.setrow.needs-value {
  opacity: 1;
}

.setrow.needs-value input.small:first-of-type {
  border-color: var(--error);
  background: var(--error-bg);
}

.setrow.needs-value .target::after {
  content: " !";
  color: var(--error);
  font-weight: 800;
}

/* Wel afgevinkt, maar de server heeft hem niet. Een vinkje dat blijft staan
   terwijl er niets is opgeslagen, is misleidend; dit merkt de regel zichtbaar. */
.setrow.unsaved .target::before {
  content: "⚠ ";
  color: var(--error);
}

.setrow.unsaved {
  border-left: 3px solid var(--error);
  padding-left: 0.4rem;
}

/* --- Uitlegpagina --- */
.help-list {
  margin: 0;
  padding-left: 1.1rem;
  font-size: 0.9rem;
}

.help-list li + li {
  margin-top: 0.4rem;
}

.help-dl {
  margin: 0;
  font-size: 0.9rem;
}

.help-dl dt {
  font-weight: 700;
  letter-spacing: 0.04em;
  margin-top: 0.7rem;
}

.help-dl dd {
  margin: 0.15rem 0 0;
  color: var(--muted);
}

/* Voorbeeldnotaties: iets losser en met cijferbreedte, zodat ze opvallen. */
.example {
  margin: 0.6rem 0 0;
  padding: 0.6rem 0.75rem;
  border-radius: var(--radius-sm);
  background: var(--bg-deep);
  border: 1px solid var(--line);
  font-variant-numeric: tabular-nums;
  font-size: 0.9rem;
}

.help-links {
  flex-direction: row;
  flex-wrap: wrap;
  justify-content: flex-start;
  gap: 1rem;
  margin-top: 0.75rem;
  text-align: left;
}

/* Korte, secundaire linkjes ("Hoe wordt dit berekend?") naast elkaar in een
   rij: de rustige rand-variant en compacter dan een primaire .links-knop,
   anders overheerst een rijtje uitleglinkjes de rest van de kaart. */
.help-links a {
  width: auto;
  padding: 0.42rem 0.8rem;
  font-size: 0.7rem;
  letter-spacing: 0.1em;
  background: transparent;
  color: var(--text);
  border: 1px solid var(--line-strong);
}

.help-links a:hover {
  background: var(--surface-hi);
  filter: none;
}

/* Het bestandspad onder een berekening op /docs-berekeningen.html. Monospace
   omdat het een pad is, maar op dezelfde grootte als de regel eromheen: de
   standaardletter van de browser valt anders een slag kleiner uit. */
.hint code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 1em;
  color: var(--text);
}

/* Notitie onder een set: de instructie uit het schema. */
.setblock {
  border-bottom: 1px solid var(--line);
}

.setblock:last-child {
  border-bottom: 0;
}

.setblock .setrow {
  border-bottom: 0;
}

.setnote {
  margin: 0 0 0.6rem;
  padding-left: 0.1rem;
  color: var(--muted);
  font-size: 0.78rem;
  line-height: 1.4;
}

/* --- 1RM-uitleg ----------------------------------------------------------- */

.formula {
  margin: 0 0 0.75rem;
  padding: 0.75rem 1rem;
  border-radius: var(--radius-sm);
  background: var(--surface-hi);
  font-size: 1.05rem;
  letter-spacing: 0.02em;
  text-align: center;
}

.sources {
  margin: 0.5rem 0 0;
  padding-left: 1.2rem;
  color: var(--text);
  font-size: 0.86rem;
  line-height: 1.55;
}

.sources li + li {
  margin-top: 0.9rem;
}

.sources .hint {
  display: block;
  margin-top: 0.2rem;
}

/* Een schatting uit een lange set: wel tonen, maar niet met dezelfde stelligheid. */
.estimate-weak {
  color: var(--muted);
}

/* --- Bodymap -------------------------------------------------------------- */

.bodymap-figures {
  display: flex;
  gap: 1rem;
  justify-content: center;
  flex-wrap: wrap;
}

.bodymap-figure {
  flex: 1 1 140px;
  max-width: 210px;
  text-align: center;
}

.bodymap-svg {
  width: 100%;
  height: auto;
  touch-action: manipulation;
}

.bodymap-caption {
  margin: 0.25rem 0 0;
  color: var(--muted);
  font-size: 0.72rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

/* De omtrek is achtergrond: hij toont het lichaam maar vangt geen klikken. */
.bm-outline {
  fill: var(--surface-hi);
  stroke: var(--line);
  stroke-width: 1;
  pointer-events: none;
}

.bm-region {
  cursor: pointer;
}

.bm-region > rect,
.bm-region > ellipse {
  fill: var(--surface-hi);
  stroke: var(--line-strong);
  stroke-width: 1.2;
  transition: fill 0.12s ease, stroke 0.12s ease;
}

.bm-region:hover > rect,
.bm-region:hover > ellipse {
  fill: var(--line-strong);
}

.bm-region:focus-visible {
  outline: none;
}

.bm-region:focus-visible > rect,
.bm-region:focus-visible > ellipse {
  stroke: var(--accent);
  stroke-width: 2;
}

.bm-region.is-selected > rect,
.bm-region.is-selected > ellipse {
  fill: var(--accent);
  stroke: var(--accent);
}

/* Een spiergroep zonder oefeningen: nog steeds aanwijsbaar, maar gedempt. */
.bm-region.is-empty > rect,
.bm-region.is-empty > ellipse {
  opacity: 0.4;
}

/* Dezelfde primair/secundair-notatie als de alleen-kijken-variant hieronder
   (.bm-region--static), maar dan op de klikbare picker bij het toevoegen van
   een oefening. */
.bm-region.is-primary > rect,
.bm-region.is-primary > ellipse {
  fill: var(--accent);
  stroke: var(--accent);
}

.bm-region.is-secondary > rect,
.bm-region.is-secondary > ellipse {
  fill: rgb(217 164 65 / 32%);
  stroke: var(--accent-line);
}

/* --- De bodymap als plaatje ------------------------------------------------
   Bij één oefening is de map geen filter maar een antwoord op "wat train ik
   hiermee". Er valt dus niets aan te klikken, en het verschil dat er wél toe
   doet is primair tegenover secundair. */

.bm-region--static {
  cursor: default;
  pointer-events: none;
}

.bm-region--static.is-primary > rect,
.bm-region--static.is-primary > ellipse {
  fill: var(--accent);
  stroke: var(--accent);
}

/* Secundair: dezelfde kleur, maar doorzichtig. Een ándere kleur zou als een
   tweede soort informatie lezen; dit leest als "hetzelfde, maar minder". */
.bm-region--static.is-secondary > rect,
.bm-region--static.is-secondary > ellipse {
  fill: rgb(217 164 65 / 32%);
  stroke: var(--accent-line);
}

/* Kleur alleen is geen uitleg — en wie kleuren slecht onderscheidt heeft aan
   het figuur zonder deze regel niets. */
.bodymap-legend {
  display: flex;
  gap: 1rem;
  justify-content: center;
  margin: 0.6rem 0 0;
  font-size: 0.72rem;
  color: var(--muted);
}

.bodymap-legend-item {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
}

.bodymap-legend-item::before {
  content: '';
  width: 0.7rem;
  height: 0.7rem;
  border-radius: 3px;
  background: var(--accent);
}

.bodymap-legend-item.is-secondary::before {
  background: rgb(217 164 65 / 32%);
  border: 1px solid var(--accent-line);
}

.bodymap-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  margin-top: 0.9rem;
  flex-wrap: wrap;
}

.bodymap-chosen {
  margin: 0;
  color: var(--text);
  font-size: 0.85rem;
}

/* --- Catalogus ------------------------------------------------------------ */

/* Een aanvinkvakje naast zijn tekst: het vakje mag niet meekrimpen als het
   label over twee regels loopt. */
.checkbox {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-top: 0.9rem;
  font-size: 0.85rem;
  color: var(--text);
  cursor: pointer;
}

.checkbox input {
  flex: 0 0 auto;
  width: 1.05rem;
  height: 1.05rem;
  accent-color: var(--accent);
}

.filters {
  display: flex;
  gap: 0.75rem;
  flex-wrap: wrap;
}

.filters .field {
  flex: 1 1 160px;
}

/* Eiwit, koolhydraat en vet horen bij elkaar en staan daarom altijd naast
   elkaar — ook op een telefoon. Met de gewone .filters-verdeling paste er
   telkens net eentje niet meer bij en viel vet als enige op een nieuwe regel;
   calorieën (of gram) krijgen daarom een eigen regel erboven. */
.filters--macros {
  display: grid;
  /* minmax(0, …) en niet 1fr: anders maakt een lange naam als "Koolhydraat"
     zijn eigen kolom breder dan de andere twee. */
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

/* Valt een naam toch over twee regels — een langere vertaling, of een grotere
   letter in de browserinstellingen — dan mag dat de invulvelden niet ongelijk
   maken; die lijnen onderaan uit. */
.filters--macros .field {
  display: flex;
  flex-direction: column;
}

.filters--macros .field input {
  margin-top: auto;
}

.catalog-list {
  list-style: none;
  margin: 0.5rem 0 0;
  padding: 0;
}

.catalog-item + .catalog-item {
  border-top: 1px solid var(--line);
}

.catalog-open {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  width: 100%;
  padding: 0.7rem 0.2rem;
  border: 0;
  border-radius: var(--radius-sm);
  background: none;
  color: var(--text);
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.catalog-open:hover {
  background: var(--surface-hi);
}

.catalog-name {
  font-weight: 600;
}

.catalog-meta {
  color: var(--muted);
  font-size: 0.78rem;
}

/* Een regel in de moderatie-wachtrij: de gegevens onder elkaar, de knop
   ernaast — en op een smal scherm eronder. */
.queue-item {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.6rem;
  padding: 0.7rem 0.2rem;
}

.queue-text {
  display: flex;
  flex: 1 1 12rem;
  flex-direction: column;
  gap: 0.15rem;
}

/* Een hele kaart die één link is: de tekst blijft gewoon tekst, alleen de
   kaart reageert. Zonder deze regel kleurt de browser alles goud en
   onderstreept hij het. */
.card--link {
  display: block;
  color: inherit;
  text-decoration: none;
}

/* De hele kaart is één link, maar hij hoort zich niet als een link te gedragen
   bij het aanwijzen: `a:hover` onderstreept anders élk woord in de kaart, tot
   de cijfers in de balken aan toe. */
.card--link:hover {
  border-color: var(--accent-line);
  text-decoration: none;
}

/* --- Dagboek -------------------------------------------------------------- */

.tracker + .tracker {
  margin-top: 0.7rem;
}

.tracker-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 0.5rem;
  font-size: 0.78rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 0.3rem;
}

.tracker-value {
  color: var(--text);
  font-variant-numeric: tabular-nums;
  text-transform: none;
  letter-spacing: normal;
}

/* Twee stukken naast elkaar: wat je gegeten hebt en wat er nog klaarstaat. */
.tracker-bar {
  display: flex;
  height: 0.5rem;
  background: var(--line);
  border-radius: var(--radius-pill);
  overflow: hidden;
}

/* Wat vandaag klaarstaat maar nog niet afgevinkt is. Lichter dan de balk
   eronder maar duidelijk geen accentkleur: het telt niet mee als gegeten, het
   laat alleen zien waar je uitkomt als je de dag eet zoals hij staat. */
.tracker-bar-planned {
  width: 0;
  height: 100%;
  flex: 0 0 auto;
  background: var(--muted-dim);
  border-radius: var(--radius-pill);
  transition: width 0.25s ease;
}

@media (prefers-reduced-motion: reduce) {
  .tracker-bar-planned {
    transition: none;
  }
}

.tracker-bar-fill {
  height: 100%;
  width: 0;
  /* Als flexitem naast het geplande stuk: niet meekrimpen, de breedte in
     procenten is precies wat hij moet zijn. */
  flex: 0 0 auto;
  background: var(--accent-grad);
  border-radius: var(--radius-pill);
  transition: width 0.25s ease;
}

/* Over je doel heen: dat hoor je te zien zonder het getal te lezen. */
.tracker-bar-fill.is-over {
  background: var(--error);
}

/* "Voeding vandaag" op de startpagina houdt hetzelfde ritme aan als het
   weekoverzicht eronder: naam links, cijfers rechts, één regel per waarde.
   De balk ligt op de plek van de scheidingslijn — zo staat in dezelfde hoogte
   én hoe je ervoor staat én waar de volgende regel begint. In het dagboek zelf
   blijft de balk breed: daar is het de hoofdzaak, hier een samenvatting. */
.today-item {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: baseline;
  column-gap: 0.85rem;
  /* Even klein als de naam ernaast: het zijn hier vier regels onder elkaar,
     en op leesgrootte zou de kaart het halve scherm vullen. */
  font-size: 0.78rem;
  padding-top: 0.55rem;
}

.today-item .tracker-value {
  text-align: right;
}

.today-item .tracker-bar,
.today-macro .tracker-bar {
  height: 0.2rem;
  margin-top: 0.45rem;
}

.today-item .tracker-bar {
  grid-column: 1 / -1;
}

/* Eiwit, koolhydraat en vet naast elkaar. Ze blijven ook op een telefoon
   naast elkaar staan: het gaat om de verhouding tussen de drie, en die lees je
   niet als ze onder elkaar komen. */
.today-macros {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0.75rem;
  margin-top: 0.9rem;
}

.today-macro {
  display: flex;
  flex-direction: column;
}

.today-macro .when {
  /* De vaste minimumbreedte van een agendaregel zou hier op een smalle
     telefoon breder zijn dan de kolom zelf. */
  min-width: 0;
}

.today-macro .tracker-value {
  font-size: 0.78rem;
  margin-top: 0.2rem;
}

/* De balkjes op één lijn, ook als een naam toch over twee regels valt. */
.today-macro .tracker-bar {
  margin-top: auto;
}

@media (prefers-reduced-motion: reduce) {
  .tracker-bar-fill {
    transition: none;
  }
}

.daypart + .daypart {
  margin-top: 1.5rem;
  padding-top: 1.2rem;
  border-top: 1px solid var(--line);
}

.daypart-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 0.5rem;
}

.daypart-head h2 {
  margin-bottom: 0;
}

.daypart-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 0.6rem;
}

/* Naam en waarden links, de tekenknopjes en het vinkje aan de rechterkant van
   diezelfde regel. Een knop met een woord erin ("bewaar als product") zou de
   naam verdringen en staat daarom op een eigen regel eronder. */
.entry {
  display: grid;
  grid-template-columns: 1fr auto auto;
  align-items: center;
  column-gap: 0.7rem;
  row-gap: 0.5rem;
}

.entry .entry-extra {
  grid-column: 1 / -1;
}

.entry .entry-extra:empty {
  display: none;
}

.entry-check {
  width: 1.35rem;
  height: 1.35rem;
  flex: 0 0 auto;
  accent-color: var(--accent);
}

/* Een knopje met alleen een teken erin: rond, en zo breed als het hoog is.
   Rond in plaats van de pilvorm van de knoppen met tekst, zodat je in één
   oogopslag ziet dat er geen woord in staat maar een teken. */
/* `button.` en niet alleen `.icon-button`: `button.inline` hierboven zet
   breedte en padding, en zonder even veel gewicht blijft dat winnen — dan wordt
   het knopje een ovaal in plaats van een rondje. */
button.icon-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: 50%;
}

.icon-button svg {
  width: 1.1rem;
  height: 1.1rem;
  stroke: currentcolor;
  fill: none;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.entry-actions {
  display: flex;
  gap: 0.4rem;
  flex: 0 0 auto;
}

/* Nog niet afgevinkt: je ziet het staan, maar het telt niet mee. */
.entry--planned {
  opacity: 0.55;
}

/* De gekozen soort in het toevoegformulier. */
.is-active {
  border-color: var(--accent);
  color: var(--accent-hi);
}

/* De sportenlijst bij "andere sport". Zesentwintig sporten onder elkaar maken
   de pagina eindeloos; in een eigen vakje blader je erdoorheen zonder de knop
   eronder uit beeld te duwen. Zoeken kan ook, maar bladeren moet werken zonder
   te weten hoe de app jouw sport noemt. */
#activity-list {
  max-height: 13rem;
  overflow-y: auto;
  margin-bottom: 0.9rem;
}

/* De drie macro's van je doel in grammen, naast elkaar zoals de streak-cijfers
   op de startpagina. */
.goal-grams {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  justify-content: space-around;
  text-align: center;
  list-style: none;
  margin: 0;
  padding: 0;
}

/* Vier getallen naast elkaar passen niet op een telefoon; met een basis
   vouwen ze netjes naar twee rijen in plaats van dat "266 g" halverwege
   afbreekt. */
.goal-grams li {
  display: flex;
  flex: 1 1 7rem;
  flex-direction: column;
  gap: 0.15rem;
}

.goal-grams strong {
  font-size: 1.5rem;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  background: var(--accent-grad);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.goal-grams span {
  color: var(--muted-dim);
  font-size: 0.66rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

/* De som van de percentages: pas groen als hij op 100 staat. Tijdens het typen
   is 90 een tussenstand, geen fout. */
.is-ok {
  color: var(--success);
}

/* De omschrijving van een maaltijd is een groot tekstveld met stappen erin;
   zonder pre-wrap plakt de browser die tot één lap tekst aan elkaar.
   De regel staat in een <button> (de aanklikbare rij) en zou daarvan de
   kapitalen en de brede letterafstand erven — voor een label prima, voor een
   recept van drie regels niet. */
.meal-description {
  white-space: pre-wrap;
  text-transform: none;
  letter-spacing: normal;
}

/* "Nog gepland" en "Totaal gepland" onder elkaar. Vaste tabelbreedte en
   cijfers op tabelbreedte: alleen dan staan de honderdtallen boven elkaar en is
   het verschil in één blik te zien in plaats van na te rekenen. */
.planned-table {
  width: 100%;
  margin-top: 0.8rem;
  border-collapse: collapse;
  font-size: 0.74rem;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

.planned-table th {
  text-align: left;
  font-weight: 600;
  color: var(--muted-dim);
  white-space: nowrap;
  padding: 0.2rem 0.5rem 0.2rem 0;
}

.planned-table td {
  text-align: right;
  padding: 0.2rem 0;
}

/* De totaalregel is waar je uitkomt; die mag zwaarder wegen dan de restregel
   erboven. */
#planned-total th,
#planned-total td {
  color: var(--text);
}

/* De foto bovenaan de maaltijdpagina: zo breed als de kaart, met de
   verhouding van de foto zelf. Een vaste hoogte zou elke maaltijd in hetzelfde
   raampje persen en juist het gerecht eruit snijden. */
#meal-photo {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--radius-sm);
}

/* Vanaf een dagboekregel naar het recept: bij een maaltijd is de naam zelf de
   link. Een gestippelde onderlijn zegt dat er iets achter zit zonder de regel
   in accentkleur te zetten — dan zou elke maaltijd uit de lijst springen. */
a.catalog-name {
  color: inherit;
  text-decoration: underline dotted var(--muted-dim);
  text-underline-offset: 0.2em;
}

a.catalog-name:hover {
  color: var(--accent-hi);
  text-decoration: underline solid currentcolor;
}

/* Het merk achter de productnaam: het hoort erbij, maar de naam zegt wát het
   is. Kleiner en gedempt, zodat de lijst op naam leesbaar blijft. */
.product-brand {
  color: var(--muted);
  font-size: 0.82em;
  font-weight: 500;
}

/* Waar een product vandaan komt: online opgehaald in plaats van zelf
   ingevuld. */
.badge--online {
  background: var(--accent-glow);
  color: var(--accent-hi);
}

.badge--pending {
  background: var(--line-strong);
  color: var(--muted);
}

/* Privé: alleen van jou. Duidelijk anders van kleur dan "online" en "wacht op
   goedkeuring", want het zegt iets over wie het mag zien. */
.badge--private {
  background: var(--surface-hi);
  color: var(--text);
  border: 1px solid var(--line-strong);
}

/* Een vinkje met zijn tekst ernaast in plaats van eronder, zoals bij de velden
   waar het label bovenaan staat. */
.field--check {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  margin-bottom: 0.4rem;
}

.field--check input {
  width: 1.15rem;
  height: 1.15rem;
  flex: 0 0 auto;
  accent-color: var(--accent);
}

.field--check span {
  text-transform: none;
  letter-spacing: normal;
  font-size: 0.85rem;
  color: var(--text);
}

/* --- Oefeningen koppelen bij een import ---------------------------------- */

.mapping-row {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0.4rem;
  padding: 0.75rem 0;
}

.mapping-row + .mapping-row {
  border-top: 1px solid var(--line);
}

.mapping-name {
  margin: 0;
  font-weight: 600;
  font-size: 0.9rem;
}

.mapping-select {
  font-size: 0.88rem;
}

.mapping-row button {
  justify-self: start;
}

/* Naast de voorgestelde koppeling kun je ook zelf door de hele catalogus
   zoeken — voor als de suggestie er niet bij staat. */
.mapping-search {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}

.mapping-search-input {
  font-size: 0.85rem;
  padding: 0.35rem 0.5rem;
}

.mapping-search-results {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.mapping-actions {
  display: flex;
  gap: 0.6rem;
  margin-top: 1rem;
}

/* De startkeuze bij een import: een omkaderd groepje, zodat duidelijk is dat
   de twee opties bij elkaar horen en samen één keuze zijn. */
.start-choice {
  margin-top: 1.2rem;
  padding: 0.8rem 1rem 1rem;
  border: 1px solid var(--line);
  border-radius: 10px;
}

.start-choice legend {
  padding: 0 0.4rem;
  font-size: 0.85rem;
  font-weight: 600;
}

.start-choice .hint {
  margin-top: 0;
}

/* Herkend, voorstel of onbekend: de kleur zegt hoe zeker de app is. */
.badge--exact {
  background: var(--success-bg);
  color: var(--success);
}

.badge--suggested {
  background: var(--accent-glow);
  color: var(--accent-hi);
}

.badge--none {
  background: var(--error-bg);
  color: var(--error);
}

@media (min-width: 34rem) {
  .mapping-row {
    grid-template-columns: minmax(9rem, 1fr) minmax(12rem, 1.4fr) auto;
    align-items: center;
    gap: 0.75rem;
  }

  /* Het zoekveld hoort niet in de naam/select/knop-rij, maar eronder over de
     volle breedte. */
  .mapping-search {
    grid-column: 1 / -1;
    align-self: start;
  }
}

/* --- Trainingsscherm: kopregel, rondes, getalvelden ---------------------- */

/* De op-en-neerknopjes in een getalveld zijn in de zaal onbruikbaar: je mikt
   met een zweterige duim op een pijltje van vier pixels. Weg ermee; op de
   telefoon komt het cijfertoetsenbord op via inputmode. */
input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button {
  appearance: none;
  margin: 0;
}

input[type="number"] {
  appearance: textfield;
}

.exercise-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  margin-bottom: 0.35rem;
}

.exercise-head h2 {
  margin: 0;
  flex: 1 1 auto;
}

.exercise-head button {
  flex: 0 0 auto;
}

/* Bij een superset wisselen de oefeningen elkaar per ronde af. */
.round-label {
  margin: 0.9rem 0 0.2rem;
  color: var(--muted-dim);
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}

/* --- Weekoverzicht en kalenderpopup -------------------------------------- */

.week-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  flex-wrap: wrap;
}

.week-head h2 {
  margin: 0;
}

.week-nav {
  display: flex;
  gap: 0.35rem;
}

.week-nav button {
  min-width: 2.4rem;
}

#week-label {
  margin: 0.2rem 0 0.8rem;
}

.dialog {
  width: min(24rem, calc(100vw - 2rem));
  padding: 1.15rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  background: linear-gradient(180deg, var(--surface-hi), var(--surface));
  color: var(--text);
}

/* Een venster met een lichaam, uitleg én een tabel erin heeft meer breedte
   nodig dan een venster met één datumveld. Op een telefoon verandert er niets:
   allebei zijn ze zo breed als het scherm toelaat. */
.dialog--wide {
  width: min(34rem, calc(100vw - 2rem));
  max-height: calc(100vh - 3rem);
  overflow-y: auto;
}

.dialog::backdrop {
  background: rgb(0 0 0 / 65%);
}

.dialog h2 {
  margin-top: 0;
}

.dialog-actions {
  display: flex;
  gap: 0.6rem;
  margin-top: 1rem;
  /* Drie knoppen naast elkaar passen niet op een telefoon; zonder wrap schuift
     de hele pagina zijwaarts mee. */
  flex-wrap: wrap;
}

/* Een portie is een omschrijving, een gewicht en een knop om hem weg te halen.
   Die knop hoort op de regel van de velden te staan en niet mee te rekken —
   net als de knop naast het barcodeveld. */
.portion-row,
.barcode-row {
  align-items: end;
}

.portion-row button,
.barcode-row button {
  flex: 0 0 auto;
}

/* Het rijtje waarmee je een product in een maaltijd zet: zoeken, portie of
   gram, en de knop. Die knop hoort op de regel van de velden te staan en niet
   mee te rekken met de hoogste — net als naast het barcodeveld. */
#picker {
  align-items: end;
}

#picker button {
  flex: 0 0 auto;
}

/* Op een telefoon passen een veld en twee knoppen niet naast elkaar: het veld
   neemt dan de hele regel en de knoppen staan er samen onder, in plaats van
   dat er eentje alleen achterblijft. */
@media (max-width: 40rem) {
  .barcode-row .field {
    flex-basis: 100%;
  }
}

/* --- Barcode scannen ------------------------------------------------------ */

/* Het camerabeeld heeft meer breedte nodig dan een gewone dialoog: je moet een
   streepjescode kunnen richten, en dat lukt niet in een kolom van 24rem. */
.scanner-dialog {
  width: min(34rem, calc(100vw - 2rem));
}

.scanner-view {
  position: relative;
  margin: 0.8rem 0;
  border-radius: var(--radius);
  overflow: hidden;
  background: #000;
}

.scanner-view video {
  display: block;
  width: 100%;
  /* Een liggend vlak: een barcode is breed en laag, en zo blijft de dialoog op
     een telefoon binnen het scherm. */
  aspect-ratio: 4 / 3;
  object-fit: cover;
}

/* Het richtkader wijst waar de code moet staan. Puur uitleg: we lezen het hele
   beeld, want een gebruiker die net buiten het kader richt hoort niet
   afgestraft te worden. */
.scanner-frame {
  position: absolute;
  inset: 25% 8%;
  border: 2px solid var(--accent);
  border-radius: calc(var(--radius) / 2);
  box-shadow: 0 0 0 100vmax rgb(0 0 0 / 35%);
  pointer-events: none;
}

/* --- Grafiek met assen ---------------------------------------------------- */

.chart {
  width: 100%;
  height: auto;
  overflow: visible;
}

.chart-grid {
  stroke: var(--line);
  stroke-width: 1;
}

.chart-axis {
  stroke: var(--line-strong);
  stroke-width: 1;
}

.chart-tick {
  fill: var(--muted);
  font-size: 9px;
  font-family: inherit;
}

.chart-tick--y {
  text-anchor: end;
}

.chart-tick--x {
  text-anchor: middle;
}

.chart-unit {
  fill: var(--muted-dim);
  font-size: 8px;
  font-family: inherit;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* Het verschil van meting naar meting. Cijfers op tabelbreedte, zodat de kolom
   niet danst bij "+0,4" naast "−1,25". Geen groen of rood: omhoog of omlaag is
   niet vanzelf goed of fout — afvallen en aankomen zijn allebei een doel. */
.progress-delta {
  font-variant-numeric: tabular-nums;
}

.metric-picker select {
  width: auto;
  min-width: 9rem;
  padding: 0.45rem 0.6rem;
  font-size: 0.85rem;
}

/* De meting en de periode staan naast elkaar boven de grafiek, en breken
   allebei naar een eigen regel zodra het scherm te smal wordt. */
.metric-pickers {
  display: flex;
  gap: 0.5rem;
  flex-wrap: wrap;
  justify-content: flex-end;
}

/* --- Progresfoto's per dag ------------------------------------------------ */

.poses {
  display: grid;
  gap: 0.5rem;
}

.photo-day + .photo-day {
  margin-top: 1.4rem;
  padding-top: 1.1rem;
  border-top: 1px solid var(--line);
}

.photo-day h3 {
  margin-top: 0;
}

@media (min-width: 34rem) {
  .poses {
    grid-template-columns: repeat(3, 1fr);
  }
}

/* --- Aanpassen tijdens de training --------------------------------------- */

.exercise-actions {
  display: flex;
  gap: 0.35rem;
  flex-wrap: wrap;
  justify-content: flex-end;
}

/* De bewerkknoppen op een oefening zijn secundair: kleiner en gedempt, zodat
   "Alles afvinken" de knop blijft waar je oog op valt. */
.exercise-actions .editbtn {
  padding: 0.3rem 0.6rem;
  font-size: 0.62rem;
  color: var(--muted);
  border-color: var(--line);
}

.exercise-actions .editbtn:hover {
  color: var(--text);
}

/* Afvinken, informatie, set erbij, aanpassen en weghalen staan naast elkaar in
   de kopregel. Even groot, anders leest die rij als losse knopjes in plaats van
   als één balkje — en 2rem is met natte handen nog te raken. */
.exercise-actions .iconbtn,
.exercise-actions button.icon-button {
  width: 2rem;
  height: 2rem;
}

/* De uitvoering in het informatievenster: genummerd, want het zijn stappen en
   geen losse tips. */
.info-steps {
  margin: 0.6rem 0 0;
  padding-left: 1.2rem;
  color: var(--muted);
  font-size: 0.82rem;
  line-height: 1.55;
}

.info-steps li + li {
  margin-top: 0.4rem;
}

#info-dialog h3 {
  margin-bottom: 0.2rem;
}

/* Klein rond knopje aan het eind van een setregel, om die set weg te halen. */
.iconbtn {
  width: 1.6rem;
  height: 1.6rem;
  padding: 0;
  flex: 0 0 auto;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--muted);
  font-size: 1rem;
  line-height: 1;
}

.iconbtn:hover {
  background: var(--surface-hi);
  color: var(--text);
  filter: none;
}

#picker-results {
  max-height: 40vh;
  overflow-y: auto;
}

/* Plusje tussen twee oefeningen: een smalle strook in de tussenruimte, rechts
   uitgelijnd. Het staat binnen dezelfde kolombreedte als de kaarten, dus de
   uitlijning verandert niet. */
.add-between {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  min-height: 1.75rem;
  margin: -0.35rem 0 0.35rem;
  padding-right: 0.3rem;
}

.add-between .iconbtn {
  background: var(--surface);
  border-color: var(--line-strong);
}

/* Het vinkje om een hele oefening af te vinken is de knop waar je oog op valt. */
.iconbtn--tick {
  color: var(--accent);
  border-color: var(--accent-line);
}

.iconbtn--tick:hover {
  background: var(--accent-glow);
  color: var(--accent-hi);
}

/* --- Beheerpagina van één account ---------------------------------------- */

.detail-list {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.35rem 1rem;
  margin: 0;
  font-size: 0.88rem;
}

.detail-list dt {
  color: var(--muted);
}

.detail-list dd {
  margin: 0;
}

.admin-actions {
  display: flex;
  gap: 0.5rem;
  flex-wrap: wrap;
}

/* --- Geen inzoomen op een aanraakscherm ------------------------------------
   iOS zoomt in zodra je een invoerveld aanraakt waarvan de letters kleiner zijn
   dan 16 pixels. De pagina schuift dan half uit beeld en komt niet vanzelf
   terug: midden in een training tikte je op het repsveld en zag je de helft van
   je oefening niet meer.

   De voor de hand liggende oplossing — `user-scalable=no` in de viewport — zet
   ook het knijpzoomen uit, en dat is voor wie slecht ziet het verschil tussen
   bruikbaar en onbruikbaar. Dus niet de zoom uit, maar de velden groot genoeg.

   Alleen op een aanraakscherm: op een desktop mogen de kleine velden klein
   blijven, want daar zoomt niets. Staat hier onderaan zodat het van de regels
   hierboven wint zonder de selectors zwaarder te hoeven maken. Nieuwe kleine
   velden horen erbij; `unit/formZoom.test.js` wordt rood als er één ontbreekt. */
@media (hover: none) and (pointer: coarse) {
  input,
  select,
  textarea,
  input.small,
  .metric-picker select {
    font-size: 16px;
  }

  /* De reps- en gewichtvelden blijven smal: ze staan met z'n tweeën naast het
     doel en het vinkje op één regel. Minder padding houdt ze even breed als
     voorheen, nu de letters groter zijn. */
  input.small {
    padding: 0.4rem 0.3rem;
  }
}

/* Op een smal scherm past een oefeningnaam van drie regels niet naast vijf
   knopjes: de naam werd een smalle kolom en de knopjes stapelden zich ernaast
   op. De naam krijgt daar zijn eigen regel en de knoppen staan er in één rij
   onder. */
@media (max-width: 30rem) {
  .exercise-head {
    flex-wrap: wrap;
  }

  .exercise-head h2 {
    flex: 1 1 100%;
  }
}
