/* ============================================================
   Sets · premium product polish

   Eén laatste, bewuste laag bovenop de schermspecifieke styles. Deze file
   harmoniseert contrast, typografie, oppervlakken, focus en motion zonder
   de bestaande mobiele flows of component-markup te herschrijven.
   ============================================================ */

/* ── Accent als VLAK versus accent als TEKST ────────────────────────────
   Dit is de kern van defect D4 en het is één regel:

     een accentkleur die je als VLAK gebruikt en een accentkleur die je als
     TEKST gebruikt zijn in lichte modus NIET dezelfde kleur.

   Waarom: helder lime is per definitie licht. In donkere modus is dat precies
   wat je wilt (#c8f83f haalt 15:1 op #08090b), maar op wit haalt hetzelfde
   lime 1,2:1 en de lichte variant #91bd11 nog altijd maar 2,21:1 — WCAG AA
   vraagt 4,5:1 voor gewone tekst. Ook --sets-accent-strong (#759b0c) is niet
   genoeg: dat is 3,26:1, dus alleen bruikbaar voor GROTE tekst (≥24px, of
   ≥18,66px vet). Eén "iets donkerder accent" lost D4 dus niet op: er is een
   apart TEKST-token nodig, met een naam die verwarring uitsluit.

   Gebruik daarom:

     --sets-accent-fill / --sets-gold-fill
       Alleen voor VLAKKEN en LIJNEN: knopvullingen (met --sets-accent-ink
       erop), voortgangsbalken, ringstroken, randen, iconen die geen
       informatie dragen. Nooit als `color:` op leesbare tekst.

     --sets-accent-text / --sets-gold-text / --sets-warn-text
       Alleen voor TEKST, en veilig op élk formaat: ≥4,7:1 op alle vier de
       lichte oppervlakken (#ffffff, #f8f8fa, #f1f2f5, #eceef2) en ≥8,6:1 op
       alle donkere. Ook als je "maar" een groot getal kleurt hoor je hier te
       zitten — één tekstkleur, geen formaatafhankelijke uitzondering die de
       volgende keer op de verkeerde plek belandt.

   Amber ("let op") krijgt een eigen token en wordt niet op goud gestapeld —
   zie G3: goud is voor het zeldzame.

   De lichte waarden zijn gekozen binnen dezelfde tint als het heldere lime
   (~74° in HSL) respectievelijk hetzelfde goud (~44°), zodat het merk niet
   verschuift; alleen de helderheid zakt tot waar AA gehaald wordt. In donkere
   modus zijn tekst- en vlakkleur wél dezelfde kleur — daar is het heldere
   lime al ruim contrastrijk genoeg.

   Regressie hierop staat vastgepind in tests/light-accent-contrast.test.ts. */

:root {
  --sets-accent: #c8f83f;
  --sets-accent-strong: #d8ff69;
  --sets-accent-ink: #111706;
  --sets-button-from: #dcff72;
  --sets-button-to: #b9f20d;
  --sets-gold: #e5bd4b;
  /* Donkere modus: tekst en vlak vallen samen — helder lime haalt hier 15:1. */
  --sets-accent-text: #c8f83f;
  --sets-gold-text: #e5bd4b;
  --sets-warn-text: #fbbf24;
  /* Vlakkleuren zijn een alias, geen kopie: var() wordt per element ná de
     cascade opgelost, dus op <html> pakt dit vanzelf de waarde die
     html:not(.dark) hieronder wint. Eén bron voor de vlakkleur. */
  --sets-accent-fill: var(--sets-accent);
  --sets-gold-fill: var(--sets-gold);
  /* Accentkleur voor tekst op een vlak dat in BEIDE thema's licht is — de
     toast-pill en de voedings-thumbnails staan altijd op wit. Die mogen dus
     niet meebewegen met het thema: doe je dat wel, dan wordt het vinkje na
     elke opgeslagen sessie in donkere modus onzichtbaar (gemeten 1,09:1).
     Deze waarde staat bewust buiten de html:not(.dark)-blokken. */
  --sets-accent-on-light: #587009;
  --sets-bg: #08090b;
  --sets-surface-1: #111318;
  --sets-surface-2: #171a20;
  --sets-surface-3: #20242c;
  --sets-border: rgba(226, 232, 240, 0.11);
  --sets-border-strong: rgba(226, 232, 240, 0.18);
  --sets-text: #f5f7fa;
  --sets-text-2: #b8bec8;
  --sets-text-3: #929aa7;
  --sets-focus: #ccfa47;
  --sets-shadow-card: 0 18px 46px rgba(0, 0, 0, 0.22), 0 1px 0 rgba(255, 255, 255, 0.025) inset;
  --sets-shadow-raised: 0 24px 70px rgba(0, 0, 0, 0.34), 0 0 0 1px rgba(255, 255, 255, 0.035) inset;
  /* Alias naar het bewegingssysteem: js/motion.js publiceert --m-ease-* op
     <html> (inline, wint dus van deze :root-regel); de literal hierachter is
     alleen de terugval vóór boot en in tests zonder JS. Één bron dus. */
  --sets-ease-out: var(--m-ease-out, cubic-bezier(0.22, 1, 0.36, 1));
  --sets-ease-spring: var(--m-ease-pop, cubic-bezier(0.2, 0.9, 0.3, 1.18));
}

html:not(.dark) {
  --sets-accent: #91bd11;
  --sets-accent-strong: #759b0c;
  --sets-accent-ink: #172004;
  --sets-button-from: #d8ff66;
  --sets-button-to: #b4ed09;
  --sets-gold: #9f6308;
  /* Gemeten (relatieve luminantie, WCAG 2.x) op de vier lichte oppervlakken:
     #587009 → 5,62 / 5,30 / 5,02 / 4,84 · #8a6205 → 5,48 / 5,17 / 4,90 / 4,72.
     Beide halen AA voor gewone tekst met marge, ook op de donkerste kaart. */
  --sets-accent-text: #587009;
  --sets-gold-text: #8a6205;
  /* Amber-waarschuwing is géén goud: G3 reserveert goud voor het zeldzame
     (PR's, gouden badges) en dit is de kleur van "let op". Eigen token dus,
     anders verwatert goud alsnog. #a35405 → 5,49 / 5,17 / 4,90 / 4,72. */
  --sets-warn-text: #a35405;
  --sets-bg: #f1f2f5;
  --sets-surface-1: #ffffff;
  --sets-surface-2: #f8f8fa;
  --sets-surface-3: #eceef2;
  --sets-border: rgba(24, 28, 36, 0.12);
  --sets-border-strong: rgba(24, 28, 36, 0.2);
  --sets-text: #16181c;
  --sets-text-2: #535a65;
  /* #686f7a haalde 4,36:1 op --sets-surface-3 (#eceef2) — genoeg op wit, net
     niet op een getinte kaart. #636a75 haalt overal ≥4,70:1. */
  --sets-text-3: #636a75;
  --sets-focus: #739b0b;
  --sets-shadow-card: 0 14px 38px rgba(35, 39, 47, 0.07), 0 1px 2px rgba(35, 39, 47, 0.05);
  --sets-shadow-raised: 0 24px 70px rgba(35, 39, 47, 0.14), 0 1px 2px rgba(35, 39, 47, 0.06);
}

html {
  color-scheme: dark;
  background: var(--sets-bg);
}

html:not(.dark) {
  color-scheme: light;
}

body {
  color: var(--sets-text);
  font-kerning: normal;
  font-optical-sizing: auto;
  font-synthesis: none;
  line-height: 1.5;
  background:
    radial-gradient(circle at 12% -8%, rgba(200, 248, 63, 0.075), transparent 34rem),
    radial-gradient(circle at 92% 2%, rgba(139, 92, 246, 0.045), transparent 30rem),
    var(--sets-bg);
}

html:not(.dark) body {
  background:
    radial-gradient(circle at 12% -8%, rgba(145, 189, 17, 0.11), transparent 34rem),
    radial-gradient(circle at 92% 2%, rgba(94, 92, 230, 0.045), transparent 30rem),
    var(--sets-bg) !important;
}

#app {
  isolation: isolate;
}

/* ── Type hierarchy and readable metadata ───────────────────── */

.font-serif,
.welcome-wordmark,
.login-topbar-brand span,
.plan-page-title,
.workout-title,
.nutrition-page-header h1,
.profile-completion-card h2,
.sets-loading-wordmark {
  font-family: "Instrument Serif", Georgia, serif;
}

.font-mono,
.settings-section-header,
.nutrition-eyebrow,
.nutrition-sync-copy,
.plan-eyebrow,
.plan-page-subtitle {
  font-variant-numeric: tabular-nums;
  text-rendering: geometricPrecision;
}

html.dark .text-zinc-300 { color: #dde1e7 !important; }
html.dark .text-zinc-400 { color: #bac0ca !important; }
html.dark .text-zinc-500 { color: #979faa !important; }
html.dark .text-zinc-600 { color: #858e9b !important; }
html.dark .text-zinc-700 { color: #747d89 !important; }

html:not(.dark) .text-zinc-400 { color: #4e5560 !important; }
html:not(.dark) .text-zinc-500 { color: #626974 !important; }
html:not(.dark) .text-zinc-600 { color: #636a75 !important; }
html:not(.dark) .text-zinc-700 { color: #7c838d !important; }

.text-\[8px\],
.text-\[8\.5px\] {
  font-size: 9px;
}

.text-\[9px\] {
  font-size: 10px;
}

.text-\[10px\] {
  font-size: 10.5px;
}

/* ── Keyboard focus and control feedback ────────────────────── */

:where(button, a, [role="button"], [role="tab"]):focus-visible {
  outline: 2px solid var(--sets-focus) !important;
  outline-offset: 3px !important;
  box-shadow: 0 0 0 5px color-mix(in srgb, var(--sets-focus) 18%, transparent);
}

:where(input, select, textarea):focus-visible {
  border-color: var(--sets-focus) !important;
  outline: 0;
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--sets-focus) 20%, transparent) !important;
}

:where(button, a, input, select, textarea) {
  transition-timing-function: var(--sets-ease-out);
}

button:disabled,
[aria-disabled="true"] {
  cursor: not-allowed;
  filter: saturate(0.7);
}

svg,
.lucide-asset-icon {
  shape-rendering: geometricPrecision;
}

/* ── Screen and sheet motion ─────────────────────────────────── */

#app > section:not(.hidden) {
  animation: sets-screen-enter 320ms var(--sets-ease-out) both;
}

@keyframes sets-screen-enter {
  from { opacity: 0; }
  to { opacity: 1; }
}

/* ── Shared dark surfaces ────────────────────────────────────── */

html.dark .bg-zinc-900,
html.dark .bg-zinc-900\/60,
html.dark .bg-zinc-900\/50,
html.dark .bg-zinc-900\/40 {
  background-color: var(--sets-surface-1) !important;
}

html.dark .bg-zinc-900\/30,
html.dark .bg-zinc-900\/20,
html.dark .bg-zinc-900\/10 {
  background-color: rgba(23, 26, 32, 0.72) !important;
}

html.dark .bg-zinc-800,
html.dark .bg-zinc-800\/60,
html.dark .bg-zinc-800\/40 {
  background-color: var(--sets-surface-3) !important;
}

html.dark .border-zinc-900,
html.dark .border-zinc-900\/60,
html.dark .border-zinc-900\/40,
html.dark .border-zinc-800,
html.dark .border-zinc-800\/80,
html.dark .border-zinc-800\/60,
html.dark .border-zinc-800\/40 {
  border-color: var(--sets-border) !important;
}

html.dark .border-zinc-700,
html.dark .border-zinc-700\/80 {
  border-color: var(--sets-border-strong) !important;
}

html.dark input::placeholder,
html.dark textarea::placeholder {
  color: #7f8793 !important;
  opacity: 1;
}

/* ── Cards, buttons and interactive tiles ───────────────────── */

.home-ring,
#dashboard-templates > div,
.momentum-card,
.plan-card,
.plan-advice-hero,
.nutrition-hero-card,
.nutrition-section,
.exercise-card,
.achievement-card,
.achievements-hero,
.rounded-2xl.bg-zinc-900\/60,
.rounded-2xl.bg-zinc-900\/40 {
  border-color: var(--sets-border);
}

html.dark .home-ring,
html.dark #dashboard-templates > div,
html.dark .momentum-card,
html.dark .exercise-card,
html.dark .achievement-card,
html.dark .achievements-hero {
  background: linear-gradient(145deg, rgba(25, 28, 35, 0.96), rgba(14, 16, 20, 0.96));
  box-shadow: var(--sets-shadow-card);
}

html:not(.dark) .home-ring,
html:not(.dark) #dashboard-templates > div,
html:not(.dark) .momentum-card,
html:not(.dark) .exercise-card,
html:not(.dark) .achievement-card,
html:not(.dark) .achievements-hero {
  border-color: var(--sets-border) !important;
  background: rgba(255, 255, 255, 0.94) !important;
  box-shadow: var(--sets-shadow-card);
}

.btn-pill,
#btn-start-workout,
.nutrition-button.is-primary,
.profile-completion-primary {
  position: relative;
  overflow: hidden;
  border: 1px solid rgba(224, 255, 117, 0.72);
  background: linear-gradient(135deg, var(--sets-button-from), var(--sets-button-to) 72%);
  color: var(--sets-accent-ink);
  box-shadow: 0 12px 30px rgba(158, 214, 16, 0.16), 0 1px 0 rgba(255, 255, 255, 0.42) inset;
}

.btn-pill::after,
#btn-start-workout::after,
.nutrition-button.is-primary::after,
.profile-completion-primary::after {
  position: absolute;
  height: 45%;
  border-radius: inherit;
  background: linear-gradient(to bottom, rgba(255, 255, 255, 0.24), transparent);
  content: "";
  pointer-events: none;
  inset: 0 1px auto;
}

.btn-ghost-pill,
.nutrition-button:not(.is-primary),
.workout-bottombar-btn {
  border-color: var(--sets-border-strong);
  background: color-mix(in srgb, var(--sets-surface-2) 88%, transparent);
  color: var(--sets-text);
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.035) inset;
}

html:not(.dark) .btn-ghost-pill,
html:not(.dark) .nutrition-button:not(.is-primary),
html:not(.dark) .workout-bottombar-btn {
  border-color: var(--sets-border-strong);
  background: rgba(255, 255, 255, 0.88);
  color: var(--sets-text);
  box-shadow: 0 1px 2px rgba(35, 39, 47, 0.06);
}

/* ── Dashboard clarity ───────────────────────────────────────── */

.home-ring {
  border-radius: 22px;
}

html.dark .home-ring-track {
  stroke: #303640;
}

html.dark .home-ring-figure,
html.dark .home-ring.is-empty .home-ring-figure {
  color: #f4f6f8;
}

html.dark .home-ring-sub {
  color: #959daa;
}

html.dark .home-ring-label {
  color: #b5bbc5;
  font-size: 10.5px;
}

html:not(.dark) .home-ring-sub,
html:not(.dark) .home-ring.is-empty .home-ring-figure {
  color: #666d77;
}

#dashboard-schedule button {
  min-height: 51px;
  border-color: var(--sets-border);
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.025) inset;
}

#dashboard-schedule button[aria-label*="today"],
#dashboard-schedule button[aria-label*="vandaag"] {
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--sets-accent) 58%, transparent), 0 8px 22px rgba(154, 210, 16, 0.08);
}

#dashboard-templates > div {
  min-height: 112px;
  border-radius: 18px;
  transition: transform 180ms var(--sets-ease-out), border-color 180ms ease, box-shadow 180ms ease;
}

#dashboard-templates h3 {
  color: var(--sets-text);
  font-size: 15px;
}

#dashboard-templates > div > div {
  color: var(--sets-text-2) !important;
  font-size: 11.5px;
}

.momentum-kicker,
.settings-section-header,
.plan-page-subtitle,
.plan-next-step-label,
.plan-weight-route span,
.plan-progress-meta,
.plan-metric span,
.nutrition-eyebrow,
.nutrition-sync-copy {
  color: var(--sets-text-3);
}

.momentum-sub,
.plan-advice-summary,
.plan-card-note,
.plan-insight-row p,
.coach-entry-subtitle {
  color: var(--sets-text-2);
}

/* ── Nutrition and progress ──────────────────────────────────── */

html.dark .nutrition-screen,
html.dark .plan-page {
  background:
    radial-gradient(circle at 86% 1%, rgba(200, 248, 63, 0.09), transparent 24rem),
    var(--sets-bg);
}

html.dark .nutrition-hero-card {
  border-color: rgba(200, 248, 63, 0.22);
  background: linear-gradient(145deg, rgba(200, 248, 63, 0.115), rgba(17, 19, 24, 0.96) 58%);
  box-shadow: var(--sets-shadow-card);
}

.nutrition-section-heading span,
.nutrition-empty-state p,
.nutrition-entry-copy p {
  color: var(--sets-text-3);
}

.nutrition-empty-state {
  border-color: var(--sets-border-strong);
  background: color-mix(in srgb, var(--sets-surface-1) 54%, transparent);
}

.nutrition-empty-state h3,
.nutrition-section-heading h2 {
  color: var(--sets-text);
}

html.dark .plan-card,
html.dark .plan-metric {
  border-color: var(--sets-border);
  background: linear-gradient(145deg, rgba(24, 27, 33, 0.96), rgba(15, 17, 21, 0.96));
  box-shadow: var(--sets-shadow-card);
}

html.dark .plan-advice-hero {
  border-color: rgba(200, 248, 63, 0.28);
  background: linear-gradient(145deg, rgba(136, 191, 22, 0.2), rgba(17, 19, 24, 0.96) 60%);
  box-shadow: var(--sets-shadow-raised);
}

.plan-next-step-label,
.plan-weight-route span,
.plan-metric span,
.plan-version-badge {
  font-size: 9px;
}

.plan-disclaimer {
  color: var(--sets-text-3);
}

/* ── Navigation and icon visibility ─────────────────────────── */

#bottom-tab-bar > div {
  border-color: var(--sets-border);
  background: rgba(8, 9, 11, 0.86);
  box-shadow: 0 -14px 40px rgba(0, 0, 0, 0.2);
  backdrop-filter: blur(24px) saturate(165%);
  -webkit-backdrop-filter: blur(24px) saturate(165%);
}

.tab-item {
  color: #959daa;
  font-size: 11px;
  font-weight: 650;
  border-radius: 12px;
  transition: color 180ms ease, background-color 180ms ease, transform 140ms var(--sets-ease-spring);
}

.tab-item svg {
  opacity: 0.92;
  filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 0.18));
}

.tab-item.active {
  color: var(--sets-accent-text);
}

.tab-item.active svg {
  opacity: 1;
  filter: drop-shadow(0 0 8px rgba(200, 248, 63, 0.2));
}

html:not(.dark) #bottom-tab-bar > div {
  border-color: var(--sets-border) !important;
  background: rgba(250, 250, 251, 0.9) !important;
  box-shadow: 0 -12px 34px rgba(35, 39, 47, 0.08);
}

html:not(.dark) .tab-item {
  color: #656c77;
}

.notification-bell,
.nutrition-icon-button,
.plan-icon-button,
.notification-header-button {
  border-color: var(--sets-border-strong);
  background: color-mix(in srgb, var(--sets-surface-2) 90%, transparent);
  color: var(--sets-text-2);
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.04) inset;
}

html:not(.dark) .notification-bell,
html:not(.dark) .nutrition-icon-button,
html:not(.dark) .plan-icon-button,
html:not(.dark) .notification-header-button {
  border-color: var(--sets-border);
  background: rgba(255, 255, 255, 0.9);
  color: #4e5560;
  box-shadow: 0 8px 22px rgba(35, 39, 47, 0.07);
}

/* ── Segments, social and settings ───────────────────────────── */

.tabs-segmented {
  border: 1px solid var(--sets-border);
  background: color-mix(in srgb, var(--sets-surface-3) 82%, transparent);
}

.tabs-segmented-item {
  color: var(--sets-text-2);
}

html.dark .tabs-segmented-item-active {
  background: #333842;
  color: #ffffff;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.22), 0 1px 0 rgba(255, 255, 255, 0.07) inset;
}

html:not(.dark) .tabs-segmented {
  border-color: var(--sets-border);
  background: #e5e7eb;
}

html:not(.dark) .tabs-segmented-item {
  color: #535a65;
}

.settings-section-header {
  font-size: 10.5px;
}

html.dark .settings-row-value {
  color: #adb4bf;
}

html:not(.dark) .settings-row-value {
  color: #5f6670;
}

.settings-row-value.is-muted {
  opacity: 0.75;
}

.settings-row {
  border-bottom-color: var(--sets-border);
  transition: background-color 160ms ease, transform 160ms var(--sets-ease-out);
}

html:not(.dark) .settings-section-header {
  color: #666d77;
}

html:not(.dark) .settings-row {
  border-bottom-color: var(--sets-border);
}

/* ── G5 · glas alleen op tijdelijke lagen ────────────────────────────────
   "Glas" is hier precies één ding: `backdrop-filter: blur()`. Een halfdoor-
   zichtige rgba-vulling op een kaart is dat níet — die composit over de
   paginakleur en leest als een egale tint; die laten we met rust.

   Toegestaan (tijdelijke lagen — ze verschijnen, je handelt ze af, ze gaan
   weer weg, en het blurren vertelt je dat er iets ónder ligt):
     · modals en hun scrims — .sheet-modal, #modal-*, .legal-consent-modal,
       .profile-completion-modal, .nutrition-sheet-modal, .tutorial-modal,
       .celebrate-backdrop, de first-run-overlay
     · .nutrition-sheet-action — de vaste actiebalk bínnen een sheet
     · #toast en .pwa-install-banner

   Ook toegestaan, maar bewust apart benoemd: chrome dat over scrollende
   inhoud zweeft — #bottom-tab-bar > div, .status-bar-blur, .login-topbar,
   .plan-header, .workout-bottom-bar. Dat zijn geen kaarten maar randen van
   het venster; zonder blur schuift de inhoud er leesbaar dwars doorheen.

   Niet toegestaan: elk element in de hoofdlaag — kaarten, tegels, knoppen,
   chips. Weggehaald bij .nutrition-icon-button.is-on-dark (styles.css).

   Er is in deze build géén rusttimer-overlay: de rusttimer is een inline
   balk in #rest-timer-bar, dus daar valt niets te verglazen. */

/* ── Toasts and overlays ─────────────────────────────────────── */

#toast {
  width: max-content;
  max-width: min(350px, calc(100vw - 32px));
  bottom: calc(82px + env(safe-area-inset-bottom));
  padding: 11px 15px;
  border: 1px solid rgba(255, 255, 255, 0.7);
  border-radius: 15px;
  background: rgba(248, 250, 252, 0.96);
  color: #17191d;
  font-size: 13px;
  font-weight: 700;
  line-height: 1.4;
  text-align: center;
  box-shadow: 0 18px 50px rgba(0, 0, 0, 0.28);
  backdrop-filter: blur(18px) saturate(150%);
  -webkit-backdrop-filter: blur(18px) saturate(150%);
}

body[data-screen="dashboard"] #toast {
  bottom: calc(162px + env(safe-area-inset-bottom));
}

.sheet-modal > div,
#modal-exercise > div:last-child,
#modal-1rm-calc > div:last-child,
#modal-plate-calc > div:last-child {
  border-color: var(--sets-border-strong);
  background: color-mix(in srgb, var(--sets-surface-1) 96%, transparent);
  box-shadow: var(--sets-shadow-raised);
}

/* ── Welcome and workout legibility ──────────────────────────── */

.welcome-tagline {
  color: var(--sets-text-2);
}

.dark .welcome-tagline {
  color: var(--sets-text-2);
}

.welcome-demo-note,
.workout-subtitle,
.exercise-tag,
.set-row-header {
  color: var(--sets-text-3);
}

.workout-kpi-tile {
  border-color: var(--sets-border);
  background: var(--sets-surface-2);
  box-shadow: var(--sets-shadow-card);
}

.set-check-btn[aria-pressed="false"],
.set-check-btn.is-unchecked {
  border-color: var(--sets-border-strong);
  color: var(--sets-text-3);
}

html:not(.dark) .welcome-tagline,
html:not(.dark) .welcome-demo-note,
html:not(.dark) .workout-subtitle,
html:not(.dark) .exercise-tag,
html:not(.dark) .set-row-header,
html:not(.dark) .set-check-btn[aria-pressed="false"],
html:not(.dark) .set-check-btn.is-unchecked {
  color: var(--sets-text-3);
}

html:not(.dark) .workout-kpi-tile {
  border-color: var(--sets-border);
  background: var(--sets-surface-1);
}

/* ── Pointer precision and responsive refinement ─────────────── */

@media (hover: hover) and (pointer: fine) {
  .home-ring:hover,
  #dashboard-templates > div:hover,
  .momentum-card:hover,
  .exercise-card:hover,
  .achievement-card:hover {
    z-index: 1;
    border-color: var(--sets-border-strong);
    transform: translateY(-2px);
    box-shadow: var(--sets-shadow-raised);
  }

  .btn-pill:hover,
  #btn-start-workout:hover,
  .nutrition-button.is-primary:hover:not(:disabled) {
    border-color: rgba(237, 255, 174, 0.9);
    background: linear-gradient(135deg, #e2ff7d, #c5f51d 72%);
    transform: translateY(-1px);
    box-shadow: 0 16px 36px rgba(158, 214, 16, 0.22), 0 1px 0 rgba(255, 255, 255, 0.48) inset;
  }

  .btn-ghost-pill:hover,
  .nutrition-button:not(.is-primary):hover:not(:disabled),
  .workout-bottombar-btn:hover {
    border-color: var(--sets-border-strong);
    background: var(--sets-surface-3);
  }

  .settings-row:hover {
    background: rgba(255, 255, 255, 0.055);
  }

  html:not(.dark) .settings-row:hover,
  html:not(.dark) .nutrition-button:not(.is-primary):hover:not(:disabled),
  html:not(.dark) .workout-bottombar-btn:hover {
    border-color: var(--sets-border-strong);
    background: #f0f1f4;
  }

  .tab-item:hover {
    color: var(--sets-text);
  }

  html:not(.dark) .tab-item:hover {
    color: #24272d;
  }
}

@media (min-width: 700px) {
  #app {
    border-color: var(--sets-border);
    box-shadow: 0 0 90px rgba(0, 0, 0, 0.22);
  }

  html:not(.dark) #app {
    border-color: var(--sets-border);
    box-shadow: 0 0 90px rgba(35, 39, 47, 0.09);
  }
}

/* ── Avatar cropper ─────────────────────────────────────────── */

.avatar-crop-modal {
  z-index: 1320;
  width: 100vw;
  height: 100dvh;
  padding-top: env(safe-area-inset-top);
  padding-bottom: env(safe-area-inset-bottom);
  background: #08090b;
}

.avatar-crop-shell {
  width: min(100%, 480px);
  height: 100%;
  margin-inline: auto;
  display: flex;
  flex-direction: column;
}

.avatar-crop-header {
  min-height: 68px;
  display: grid;
  grid-template-columns: minmax(76px, 1fr) auto minmax(76px, 1fr);
  align-items: center;
  gap: 8px;
  padding: 8px 16px;
  border-bottom: 1px solid var(--sets-border);
}

.avatar-crop-header h3 {
  color: #f7f8fa;
  font-size: 15px;
  font-weight: 750;
  text-align: center;
  white-space: nowrap;
}

.avatar-crop-text-button {
  min-height: 44px;
  color: #b8bec8;
  font-size: 13px;
  font-weight: 650;
  text-align: left;
}

.avatar-crop-text-button.is-primary {
  color: var(--sets-accent-text);
  text-align: right;
}

.avatar-crop-text-button:disabled {
  opacity: 0.45;
}

.avatar-crop-body {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 22px;
  padding: 22px 20px 30px;
}

.avatar-crop-body > p {
  color: #929aa7;
  font-size: 12px;
  line-height: 1.5;
  text-align: center;
}

.avatar-crop-stage {
  position: relative;
  width: min(100%, 410px);
  aspect-ratio: 1;
  margin-inline: auto;
  overflow: hidden;
  touch-action: none;
  user-select: none;
  background: #111318;
  cursor: grab;
}

.avatar-crop-stage.is-dragging {
  cursor: grabbing;
}

#avatar-crop-image {
  position: absolute;
  top: 50%;
  left: 50%;
  max-width: none;
  max-height: none;
  pointer-events: none;
  transform-origin: center;
  will-change: width, height, transform;
}

.avatar-crop-mask {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  box-shadow: 0 0 0 100vmax rgba(0, 0, 0, 0.58);
  outline: 1px solid rgba(255, 255, 255, 0.72);
  outline-offset: -1px;
  pointer-events: none;
}

.avatar-crop-loading {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  background: rgba(8, 9, 11, 0.78);
}

.avatar-crop-loading.hidden {
  display: none;
}

.avatar-crop-loading svg {
  width: 32px;
  height: 32px;
  fill: none;
  stroke: var(--sets-accent-fill);
  stroke-width: 2.5;
  stroke-linecap: round;
  animation: spin 0.9s linear infinite;
}

.avatar-crop-zoom {
  display: grid;
  grid-template-columns: 28px minmax(0, 1fr) 28px;
  align-items: center;
  gap: 10px;
  color: #929aa7;
  font-size: 20px;
  text-align: center;
}

.avatar-crop-zoom input {
  width: 100%;
  accent-color: var(--sets-accent-fill);
}

@media (max-height: 720px) {
  .avatar-crop-body {
    gap: 12px;
    padding-block: 12px 18px;
  }

  .avatar-crop-body > p {
    display: none;
  }

  .avatar-crop-stage {
    width: min(100%, calc(100dvh - 174px - env(safe-area-inset-top) - env(safe-area-inset-bottom)));
  }
}

@media (min-width: 1024px) {
  body {
    padding-left: 0;
  }

  body:not(.workout-active):has(#bottom-tab-bar:not(.hidden)) {
    padding-left: var(--desktop-nav-width);
  }

  /* Zonder zijbalk mag de kolom breder, maar de landings- en inlogschermen
     zijn geen app-kolom: die vullen de pagina zelf. */
  body.workout-active #app,
  body:has(#bottom-tab-bar.hidden):not([data-screen="welcome"]):not([data-screen="login"]):not([data-screen="update-password"]) #app {
    width: min(var(--desktop-content-width), calc(100vw - 64px));
  }

  #bottom-tab-bar {
    border-color: var(--sets-border);
    background: rgba(8, 9, 11, 0.9);
    box-shadow: 18px 0 54px rgba(0, 0, 0, 0.16);
  }

  html:not(.dark) #bottom-tab-bar {
    border-color: var(--sets-border);
    background: rgba(249, 250, 251, 0.92);
    box-shadow: 18px 0 54px rgba(35, 39, 47, 0.07);
  }

  #toast {
    left: calc(var(--desktop-nav-width) + (100vw - var(--desktop-nav-width)) / 2);
    bottom: 28px;
  }

  body[data-screen="dashboard"] #toast {
    bottom: 98px;
  }
}

/* ── Compact phone quality and safe touch geometry ───────────── */

.sets-dialog-open {
  overflow: hidden;
  overscroll-behavior: none;
}

.notification-empty-icon {
  width: 36px;
  height: 36px;
  margin-inline: auto;
  color: var(--sets-text-3);
  filter: none !important;
}

.btn-pill-sm {
  min-height: 44px;
}

.legal-inline-links a {
  min-height: 44px;
  display: inline-flex;
  align-items: center;
}

.tabs-segmented-item {
  min-height: 44px;
  height: 44px;
}

.plan-inline-link {
  min-width: 44px;
  min-height: 44px;
  padding-block: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.plan-tqs-help {
  width: 44px;
  height: 44px;
}

@media (max-width: 699px) {
  :where(input, select, textarea) {
    font-size: 16px;
  }

  #dashboard-schedule {
    display: flex !important;
    gap: 6px;
    overflow-x: auto;
    padding: 2px 1px 5px;
    scroll-padding-inline: 1px;
    scroll-snap-type: x proximity;
  }

  #dashboard-schedule > button {
    min-width: 44px;
    flex: 1 0 44px;
    scroll-snap-align: start;
  }
}

/* ─── Setrij: breedte voor het gewicht ──────────────────────────────────
   De setrij is de enige inhoud van .exercise-card die écht breedte nodig
   heeft: een gewicht als "102.5" is vijf mono-tekens (48px bij 16px, de
   Courier-fallback op iOS) en die pasten niet in de 53px-kolom die er op een
   375px-telefoon overbleef. De rij leent daarom 8px van de 14px kaartpadding
   aan beide kanten; de titel, de knoppenrij en de notities houden hun eigen
   inspringing, zodat de kaart niet ineens smal oogt.

   Alleen onder `sm` (640px). Vanaf daar zet activeSetGrid() de gewichtskolom
   terug op 1fr en is er ruimte zat; op tablet en desktop hing de rij anders
   8px buiten de rest van de kaartinhoud, wat er als een uitlijnfout uitziet.

   De lime-accentbalk van de kaart staat op 0–3px vanaf de padding-rand, dus
   met 14px padding min 8px marge blijft er precies 3px vrij. Waar de padding
   naar 12px zakt (≤360px) leent de rij 6px, zodat die 3px blijft kloppen. */
@media (max-width: 639.98px) {
  .exercise-card .active-set-header,
  .exercise-card .active-set-row {
    margin-inline: -8px;
  }
}

/* Het schijvenknopje neemt zijn tikdoel uit zijn eigen doos: 28x44, en geen
   pixel meer. Er heeft hier een `::after { inset: 0 -8px }` gestaan om er
   44x44 van te maken — een gepositioneerd pseudo-element schildert over de
   statische buren heen en wint dus ook het hit-testen. Gemeten op 375px pakte
   het de rechterste 8px van het gewichtsveld én de linkerste 6px van het
   repsveld af: tikken naast het reps-getal opende de schijvencalculator
   midden in een set.

   44x44 teruggeven kan niet zonder ergens anders te stelen. Op 375px is de
   rij 317px breed en vraagt de inhoud al 44 (setnr) + 58 (gewichtsveld) + 44
   (schijven) + 44 (reps) + 38 (1RM) + 44 (vink) + 44 (verwijder) + 5×2 gap =
   326px. Van die zeven is de schijvencalculator de enige die geen invoer of
   bevestiging is, dus die levert de breedte in. 28x44 haalt WCAG 2.5.8 (AA,
   24x24) ruim, en beide invoervelden houden nu elke pixel van hun eigen doos. */

/* De "zelfde als vorige keer"-snelkoppeling is bewust een tekstregel en geen
   knop met kader: hij mag de rij niet zwaarder maken dan de hint die er al
   stond. Alleen het pijltje verklapt dat je erop kunt tikken. */
.set-repeat-prev {
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
}

@media (max-width: 390px) {
  .rest-timer-rest-label,
  .rest-timer-unit-label {
    display: none;
  }
}

@media (max-width: 360px) {
  #screen-dashboard > header,
  #screen-workout > header {
    padding-inline: 16px;
  }

  #dash-date {
    white-space: nowrap;
    font-size: 8px;
    letter-spacing: 0.14em;
  }

  #workout-blocks {
    padding-inline: 16px;
  }

  #rest-timer-bar {
    padding-inline: 16px;
  }

  #rest-timer-bar > div {
    flex-direction: column;
    align-items: stretch;
    gap: 8px;
    padding: 10px;
  }

  .rest-timer-summary,
  .rest-timer-controls {
    width: 100%;
  }

  .rest-timer-controls {
    justify-content: space-between;
  }

  .rest-timer-rest-label,
  .rest-timer-unit-label {
    display: none;
  }

  .exercise-card {
    padding-inline: 12px;
  }

  /* Met 12px kaartpadding zou de standaard -8px de rij tot op 1px van de
     lime-accentbalk duwen; -6px houdt dezelfde 3px vrij als hierboven. */
  .exercise-card .active-set-header,
  .exercise-card .active-set-row {
    margin-inline: -6px;
  }

  .exercise-card-header {
    flex-wrap: wrap;
  }

  .exercise-card-header > :first-child {
    width: 100%;
    flex: 1 0 100%;
  }

  .exercise-card-actions {
    width: 100%;
    justify-content: flex-end;
    margin-top: 2px;
  }
}

/* Alleen de setrij loopt door tot 374px, de rest van de smalle-schermregels
   niet. Op 361–374px (iPhone SE/12 mini met een smallere layoutviewport, of
   een 375px-scherm minus scrollbar) is de gewichtskolom nog maar ~43px
   tekstruimte breed, terwijl "102.5" in de Courier-fallback van iOS 48px
   vraagt — dus daar hoort de tweeregelige indeling. De schermchrome eromheen
   (headers, #dash-date, #workout-blocks, de rusttimer, de kaartpadding) heeft
   dat niet nodig en houdt zijn eigen 360px-grens hierboven: die band met één
   mediaquery meeslepen veranderde de layout van elk toestel tussen 361 en
   374px zonder dat daar een reden voor was. */
@media (max-width: 374px) {
  .active-set-header.has-load.has-performance,
  .active-set-row.has-load.has-performance {
    grid-template-columns: 44px minmax(0, 1fr) minmax(0, 1fr) !important;
  }

  .active-set-header.has-load.has-performance {
    grid-template-rows: auto auto;
    row-gap: 4px;
  }

  .active-set-row.has-load.has-performance {
    grid-template-rows: 44px auto;
    row-gap: 4px;
    padding-block: 5px;
  }

  .active-set-header.has-load:not(.has-performance),
  .active-set-row.has-load:not(.has-performance) {
    grid-template-columns: 44px minmax(0, 1fr) minmax(0, 1fr) 44px 44px !important;
  }

  .active-set-header.no-load,
  .active-set-row.no-load {
    grid-template-columns: 44px minmax(0, 1fr) 44px 44px !important;
  }

  .active-set-row .set-number-control,
  .active-set-header .set-col-number {
    grid-column: 1;
    grid-row: 1;
  }

  .active-set-row.has-load .set-weight-control,
  .active-set-header.has-load .set-col-weight {
    grid-column: 2;
    grid-row: 1;
  }

  .active-set-row.has-load .set-reps-input,
  .active-set-header.has-load .set-col-reps {
    grid-column: 3;
    grid-row: 1;
  }

  .active-set-row.no-load .set-reps-input,
  .active-set-header.no-load .set-col-reps {
    grid-column: 2;
    grid-row: 1;
  }

  .active-set-row.has-performance .set-performance-cell,
  .active-set-row.has-performance .set-performance-input,
  .active-set-header.has-performance .set-col-performance {
    grid-column: 1;
    grid-row: 2;
    justify-self: stretch;
    text-align: left;
  }

  .active-set-row.has-performance .set-performance-cell {
    height: 26px;
    justify-content: flex-start;
    padding-inline: 8px;
    border-radius: 7px;
    background: color-mix(in srgb, var(--sets-surface-3) 42%, transparent);
  }

  .active-set-row.has-performance .set-performance-input {
    height: 44px;
  }

  .active-set-row.has-load.has-performance .set-check-btn,
  .active-set-header.has-load.has-performance .set-col-check {
    grid-column: 2;
    grid-row: 2;
    justify-self: center;
  }

  .active-set-row.has-load.has-performance .set-delete-btn,
  .active-set-header.has-load.has-performance .set-col-delete {
    grid-column: 3;
    grid-row: 2;
    justify-self: end;
  }

  .active-set-row.has-load:not(.has-performance) .set-check-btn,
  .active-set-header.has-load:not(.has-performance) .set-col-check {
    grid-column: 4;
    grid-row: 1;
  }

  .active-set-row.has-load:not(.has-performance) .set-delete-btn,
  .active-set-header.has-load:not(.has-performance) .set-col-delete {
    grid-column: 5;
    grid-row: 1;
  }

  .active-set-row.no-load .set-check-btn,
  .active-set-header.no-load .set-col-check {
    grid-column: 3;
    grid-row: 1;
  }

  .active-set-row.no-load .set-delete-btn,
  .active-set-header.no-load .set-col-delete {
    grid-column: 4;
    grid-row: 1;
  }
}

@media (prefers-reduced-motion: reduce) {
  #app > section:not(.hidden) {
    animation: none;
  }

  *,
  *::before,
  *::after {
    scroll-behavior: auto !important;
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
  }
}

/* ── Populated mobile states ───────────────────────────────────
   These rules deliberately target the real, data-filled layouts. Empty
   browser states do not expose overflow between the schedule, carousels and
   fixed navigation, which is why these components get explicit geometry. */

.plan-header-spacer {
  width: 44px;
  height: 44px;
  flex: 0 0 44px;
}

.plan-advice-hero h2 {
  max-width: 100%;
  text-wrap: balance;
}

.plan-inline-link {
  color: var(--sets-accent-text);
}

#dashboard-schedule {
  display: block !important;
  overflow: visible !important;
  padding: 2px 0 0 !important;
}

#dashboard-schedule .schedule-days {
  display: grid !important;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 6px;
  width: 100%;
}

#dashboard-schedule .schedule-days > button {
  width: 100%;
  min-width: 0;
  padding-inline: 1px;
  box-shadow: none;
}

#dashboard-schedule .schedule-days > button.ring-1 {
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--sets-accent) 62%, transparent),
    0 8px 22px rgba(154, 210, 16, 0.08);
}

.schedule-stale {
  width: 100%;
  margin-top: 10px !important;
}

html.dark .schedule-stale {
  border-color: rgba(245, 158, 11, 0.34) !important;
  background: rgba(120, 53, 15, 0.18) !important;
}

html.dark .schedule-stale .text-amber-500\/80 {
  color: #fbbf24 !important;
}

/* De lichte kant had hier helemaal geen tegenhanger: de regel hierboven hangt
   aan html.dark, dus in lichte modus bleef de kale Tailwind-utility staan —
   #f59e0b op 80% dekking over wit is 2,4:1. */
html:not(.dark) .schedule-stale .text-amber-500\/80 {
  color: var(--sets-warn-text) !important;
}

#dashboard-templates {
  scroll-padding-inline: 0;
}

#dashboard-templates > div {
  width: calc((100% - 12px) / 2) !important;
  flex-basis: calc((100% - 12px) / 2) !important;
  min-width: 0;
}

.momentum-card {
  width: auto;
  flex: 0 0 calc((100% - 12px) / 2);
}

.momentum-card:only-child {
  flex-basis: 100%;
}

.exercise-search-field {
  width: 100%;
  min-height: 48px;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0 14px;
  border: 1px solid var(--sets-border);
  border-radius: 15px;
  background: color-mix(in srgb, var(--sets-surface-2) 92%, transparent);
  color: var(--sets-text-3);
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.035) inset;
  transition: border-color 160ms ease, box-shadow 160ms ease, background-color 160ms ease;
}

.exercise-search-field:focus-within {
  border-color: color-mix(in srgb, var(--sets-focus) 58%, var(--sets-border));
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--sets-focus) 12%, transparent);
}

.exercise-search-field .lucide-asset-icon {
  width: 18px;
  height: 18px;
  flex: 0 0 18px;
}

.exercise-search-field input {
  width: 100%;
  min-width: 0;
  height: 46px;
  padding: 0;
  border: 0;
  outline: 0;
  background: transparent;
  color: var(--sets-text);
  font-size: 16px;
}

.exercise-search-field input::placeholder {
  color: var(--sets-text-3);
  opacity: 0.9;
}

html:not(.dark) .exercise-search-field {
  background: rgba(255, 255, 255, 0.94);
  box-shadow: var(--sets-shadow-card);
}

.top-exercise-row {
  background: var(--sets-surface-2) !important;
}

.top-exercise-metrics {
  display: flex;
  align-items: center;
  gap: 12px;
}

.top-exercise-metric {
  min-width: 42px;
  display: grid;
  justify-items: end;
  gap: 1px;
}

.top-exercise-metric-label {
  color: var(--sets-text-3);
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: 8px;
  font-weight: 700;
  letter-spacing: 0.1em;
  line-height: 1;
  text-transform: uppercase;
}

.top-exercise-value {
  color: var(--sets-accent-text);
}

#history-exercises-container > .overflow-y-auto {
  padding-bottom: calc(124px + env(safe-area-inset-bottom)) !important;
}

.history-subtabs .tabs-segmented {
  padding: 3px;
  border-radius: 14px;
}

.history-subtabs .tabs-segmented-item {
  min-height: 40px;
  height: 40px;
}

@media (max-width: 390px) {
  #dashboard-schedule .schedule-days {
    gap: 4px;
  }

  #dashboard-schedule .schedule-days > button span:first-child {
    font-size: 9px;
    letter-spacing: 0.04em;
  }

  #dashboard-templates > div {
    width: 100% !important;
    flex-basis: 100% !important;
  }

  .momentum-card {
    flex-basis: 82%;
  }

  .momentum-card:only-child {
    flex-basis: 100%;
  }

  .progress-segmented .tabs-segmented-item {
    font-size: 10.5px;
  }

  .plan-advice-hero h2 {
    font-size: 21px;
  }

  .top-exercise-metrics {
    gap: 8px;
  }
}

@media (max-width: 699px) {
  #screen-history:not(.hidden) {
    height: calc(100dvh - env(safe-area-inset-top));
    min-height: 0;
    overflow: hidden;
    padding-bottom: calc(76px + env(safe-area-inset-bottom));
  }

  #history-sessions-container,
  #history-exercises-container {
    min-height: 0;
  }
}

@media (min-width: 700px) {
  #dashboard-templates > div {
    width: 192px !important;
    flex-basis: 192px !important;
  }

  .momentum-card,
  .momentum-card:only-child {
    width: 152px;
    flex: 0 0 auto;
  }
}

/* ════════════════════════════════════════════════════════════════
   Motion-polish: schermentrance, sheet-harmonisatie en tikfeedback
   (zie ook js/celebrate.js voor de celebratielaag zelf)
   ════════════════════════════════════════════════════════════════ */

/* Eerste bezoek per scherm: de blokken schuiven gestaggerd omhoog binnen.
   js/app.js zet .screen-first-enter alleen bij het eerste bezoek en haalt
   hem daarna weer weg, zodat tabwissels de iOS-overgang houden.

   Op de lange schermen komt hij er niet op: daar onthult js/screen-reveal.js
   de blokken op het moment dat je ze bereikt, in plaats van ze allemaal
   tegelijk te laten starten bij het openen van het scherm. */
.screen-first-enter > * {
  animation: screenBlockIn 380ms var(--sets-ease-out) both;
}
.screen-first-enter > *:nth-child(1) { animation-delay: 0ms; }
.screen-first-enter > *:nth-child(2) { animation-delay: 45ms; }
.screen-first-enter > *:nth-child(3) { animation-delay: 90ms; }
.screen-first-enter > *:nth-child(4) { animation-delay: 135ms; }
.screen-first-enter > *:nth-child(5) { animation-delay: 180ms; }
.screen-first-enter > *:nth-child(6) { animation-delay: 225ms; }
.screen-first-enter > *:nth-child(n+7) { animation-delay: 260ms; }

@keyframes screenBlockIn {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* Bottom-sheets die nog geen entrance hadden krijgen dezelfde beweging
   als #modal-exercise: backdrop fade, sheet veert omhoog. */
#modal-1rm-calc:not(.hidden) > div:first-child,
#modal-plate-calc:not(.hidden) > div:first-child,
#modal-avatar-actions:not(.hidden) > div:first-child {
  animation: sheetBackdropIn 200ms ease-out both;
}
#modal-1rm-calc:not(.hidden) > div:last-child,
#modal-plate-calc:not(.hidden) > div:last-child,
#modal-avatar-actions:not(.hidden) > div:last-child {
  animation: sheetCardIn 340ms var(--sets-ease-out) both;
}
/* .sheet-modal beweegt via zijn eigen transitions in styles.css; hier ook
   nog keyframes overheen leggen gaf een dubbele, vechtende entrance. */

@keyframes sheetBackdropIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}
@keyframes sheetCardIn {
  from { opacity: 0.4; transform: translateY(48px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* Tikfeedback op de segmentknoppen; kaarten en pills hebben al een eigen
   :active-schaal, deze twee misten hem nog. */
.tabs-segmented-item:active { transform: scale(0.96); }
.schedule-days button:active { transform: scale(0.94); }

@media (prefers-reduced-motion: reduce) {
  .screen-first-enter > * { animation: none; }
  #modal-1rm-calc:not(.hidden) > div:first-child,
  #modal-plate-calc:not(.hidden) > div:first-child,
  #modal-avatar-actions:not(.hidden) > div:first-child,
  #modal-1rm-calc:not(.hidden) > div:last-child,
  #modal-plate-calc:not(.hidden) > div:last-child,
  #modal-avatar-actions:not(.hidden) > div:last-child { animation: none; }
}

/* ── Tabbalk: iconen lager en minder loze ruimte onder de labels ──
   De home-indicator-inset (34px op moderne iPhones) gaf zoveel padding
   onderaan dat het icoonblok bovenin de balk hing. We verdelen die ruimte
   nu: iets meer lucht boven, minder eronder. */
@media (max-width: 1023px) {
  #bottom-tab-bar > div {
    padding-top: 10px;
    padding-bottom: max(6px, calc(env(safe-area-inset-bottom) - 20px));
  }

  .tab-item {
    min-height: 50px;
    padding-top: 4px;
    padding-bottom: 4px;
  }

  .tab-indicator { top: 6px; }
}

/* ── Safe-area zit nu in het scherm zelf, niet in #app ───────────
   Stond de padding op #app, dan werd de strook onder de statusbalk door
   de body-achtergrond gevuld terwijl het scherm eronder zijn eigen kleur
   of verloop heeft: een zichtbare naad. Elk scherm reserveert de ruimte
   nu zelf, dus zijn eigen achtergrond loopt door tot achter tijd/batterij. */
#app > section {
  padding-top: env(safe-area-inset-top);
}

/* Deze schermen verrekenen de inset al in hun eigen kopbalk; nog een keer
   padding zou ze dubbel naar beneden duwen. */
#app > #screen-welcome,
#app > #screen-login,
#app > #screen-notifications {
  padding-top: 0;
}


/* ── Eén kopbalk voor elk tabblad ────────────────────────────────
   Elk tabblad had zijn eigen kop: de een gecentreerd met een eigen
   achtergrond en rand, de ander links uitgelijnd, weer een ander met
   logo. Ze delen nu het patroon van Voeding: kleine bovenregel,
   serif-titel, icoonknoppen rechts, geen balk of rand. */
.app-page-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 18px 20px 12px;
  border: 0;
  background: transparent;
}

.app-page-header h1 {
  margin: 0;
  color: var(--sets-text);
  font-family: "Instrument Serif", Georgia, serif;
  font-size: 30px;
  font-style: italic;
  font-weight: 500;
  line-height: 1;
  letter-spacing: 0.01em;
}

.app-page-header .app-page-eyebrow {
  margin-bottom: 4px;
  color: var(--sets-text-3);
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.app-page-actions {
  display: flex;
  align-items: center;
  gap: 10px;
}

/* Op een tabblad is de tabbalk de navigatie: een terugknop wijst nergens
   heen. Hij blijft in de DOM staan voor subschermen — Instellingen gebruikt
   dezelfde knop om uit Profiel of Voorkeuren terug te keren. */
.app-page-header .app-page-back {
  display: none;
}

#screen-settings[data-settings-view]:not([data-settings-view="main"]) .app-page-back {
  display: inline-flex;
}

/* De instellingen-subpagina's schuiven over elkaar en hebben dus een dekkende
   achtergrond nodig. Geef het scherm eronder dezelfde kleur, anders eindigt
   de kopbalk in een zichtbare rand. */
#screen-settings,
#settings-view-main,
#settings-view-account,
#settings-view-preferences,
#settings-view-data {
  background: var(--sets-bg);
}

/* ── Vragenlijst voor het trainingsblok ──────────────────────────
   Bewust geen chatvorm: geen bubbels, geen typende cursor, geen
   afzender. Eén vraag per keer, met de keuzes als volwaardige knoppen —
   je leest de opties en tikt er een aan, zoals bij de rest van de app. */
.intake-progress {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 8px;
  color: var(--sets-text-3);
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.intake-progress-back {
  color: var(--sets-text-2);
  font: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  background: none;
  border: 0;
  padding: 2px 0;
  cursor: pointer;
}

.intake-progress-back:active { opacity: 0.6; }

.intake-progress-track {
  height: 2px;
  margin-bottom: 14px;
  border-radius: 99px;
  background: var(--sets-surface-3);
  overflow: hidden;
}

.intake-progress-track span {
  display: block;
  height: 100%;
  border-radius: inherit;
  background: var(--sets-accent);
  transition: width 320ms var(--sets-ease-out);
}

.intake-question {
  margin-bottom: 4px;
  color: var(--sets-text);
  font-size: 17px;
  font-weight: 650;
  line-height: 1.25;
}

.intake-hint {
  margin-bottom: 14px;
  color: var(--sets-text-3);
  font-size: 12px;
  line-height: 1.4;
}

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

/* Tijdens het bepalen van de volgende vraag blijft de vraag staan en
   dimt alleen de keuze: een spinner zou suggereren dat er iets aan het
   nadenken is, en dat is precies de indruk die we niet willen wekken. */
.intake-options.is-busy { opacity: 0.5; pointer-events: none; }

.intake-option {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-height: 52px;
  padding: 11px 14px;
  border: 1px solid var(--sets-border);
  border-radius: 14px;
  background: var(--sets-surface-1);
  color: var(--sets-text);
  text-align: left;
  cursor: pointer;
  transition: transform 140ms var(--sets-ease-spring), border-color 160ms ease, background-color 160ms ease;
}

.intake-option:active {
  transform: scale(0.985);
  border-color: var(--sets-accent);
  background: var(--sets-surface-2);
}

.intake-option-label {
  font-size: 14px;
  font-weight: 650;
  line-height: 1.25;
}

.intake-option-detail {
  color: var(--sets-text-3);
  font-size: 11.5px;
  line-height: 1.35;
}

/* ── Voeding bij het trainingsblok ───────────────────────────────
   Onderdeel van de programmakaart, niet een kaart op zichzelf: het
   hoort bij dit blok en verdwijnt er ook mee. */
.block-nutrition {
  margin-top: 12px;
  padding: 12px 14px;
  border: 1px solid var(--sets-border);
  border-radius: 14px;
  background: var(--sets-surface-2);
}

.block-nutrition-eyebrow {
  margin-bottom: 8px;
  color: var(--sets-text-3);
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.block-nutrition-row {
  display: flex;
  flex-wrap: wrap;
  gap: 14px 20px;
  margin-bottom: 8px;
}

.block-nutrition-row > div {
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.block-nutrition-row strong {
  color: var(--sets-text);
  font-size: 16px;
  font-weight: 700;
  line-height: 1.1;
}

.block-nutrition-row span {
  color: var(--sets-text-3);
  font-size: 11px;
}

.block-nutrition-missing,
.block-nutrition-tip {
  color: var(--sets-text-2);
  font-size: 12px;
  line-height: 1.45;
}

.block-nutrition-tip { margin-top: 6px; }

/* ── Tip van de dag op de home ───────────────────────────────── */
.home-tip-card {
  padding: 14px 16px;
  border: 1px solid var(--sets-border);
  border-radius: 18px;
  background: var(--sets-surface-1);
  box-shadow: var(--sets-shadow-card);
}

.home-tip-eyebrow {
  margin-bottom: 6px;
  color: var(--sets-accent-text);
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.home-tip-title {
  margin-bottom: 4px;
  color: var(--sets-text);
  font-size: 15px;
  font-weight: 650;
  line-height: 1.3;
}

.home-tip-body {
  color: var(--sets-text-2);
  font-size: 12.5px;
  line-height: 1.5;
}

/* ── Uitleg over het programma ───────────────────────────────────
   Midden op het scherm en niet als bottom sheet: dit is geen keuze
   maar een korte uitleg, en die hoort in het midden te staan waar je
   hem leest voordat je verder klikt. */
.tutorial-modal {
  position: fixed;
  inset: 0;
  z-index: 70;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: rgba(6, 8, 11, 0.62);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  opacity: 0;
  transition: opacity 200ms var(--sets-ease-out);
}

.tutorial-modal.is-open { opacity: 1; }
.tutorial-modal.hidden { display: none; }

.tutorial-panel {
  width: min(100%, 380px);
  max-height: min(80vh, 620px);
  overflow-y: auto;
  padding: 22px 20px 20px;
  border: 1px solid var(--sets-border);
  border-radius: 24px;
  background: var(--sets-surface-1);
  box-shadow: var(--sets-shadow-raised);
  transform: scale(0.96);
  transition: transform 220ms var(--sets-ease-spring);
}

.tutorial-modal.is-open .tutorial-panel { transform: scale(1); }

.tutorial-eyebrow {
  margin-bottom: 4px;
  color: var(--sets-accent-text);
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.tutorial-title {
  margin-bottom: 14px;
  color: var(--sets-text);
  font-family: "Instrument Serif", Georgia, serif;
  font-size: 26px;
  font-style: italic;
  line-height: 1.05;
}

.tutorial-steps {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin: 0 0 18px;
  padding: 0;
  list-style: none;
  counter-reset: tutorial;
}

.tutorial-steps li {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding-left: 30px;
  position: relative;
  counter-increment: tutorial;
}

.tutorial-steps li::before {
  content: counter(tutorial);
  position: absolute;
  left: 0;
  top: 1px;
  width: 20px;
  height: 20px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 999px;
  background: var(--sets-accent);
  color: var(--sets-accent-ink);
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: 11px;
  font-weight: 700;
}

.tutorial-steps strong {
  color: var(--sets-text);
  font-size: 14px;
  font-weight: 650;
  line-height: 1.3;
}

.tutorial-steps span {
  color: var(--sets-text-2);
  font-size: 12.5px;
  line-height: 1.45;
}

.tutorial-button {
  width: 100%;
  min-height: 44px;
  border: 0;
  border-radius: 14px;
  background: var(--sets-accent);
  color: var(--sets-accent-ink);
  font-size: 14px;
  font-weight: 700;
  cursor: pointer;
  transition: transform 140ms var(--sets-ease-spring);
}

.tutorial-button:active { transform: scale(0.985); }

/* Het vraagteken op de programmakaart dat de uitleg terughaalt. */
.program-help-button {
  width: 28px;
  height: 28px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--sets-border);
  border-radius: 999px;
  background: transparent;
  color: var(--sets-text-3);
  font-size: 13px;
  font-weight: 700;
  cursor: pointer;
}

.program-help-button:active { background: var(--sets-surface-2); }

.program-card-heading {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
}

/* ── Meldingen ───────────────────────────────────────────────────
   De kop stond tegen de statusbalk aan sinds de safe-area per scherm
   wordt gezet, de items plakten aan elkaar en het lime icoon was in
   light mode nauwelijks te zien op een lichte achtergrond. */
#screen-notifications .notification-header {
  padding-top: calc(env(safe-area-inset-top) + 10px);
}

.notification-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 12px 16px;
}

.notification-item {
  padding: 14px 10px;
  border: 0;
  border-radius: 14px;
}

/* De scheiding tussen items komt van de ruimte ertussen, niet van een
   lijn: met afgeronde kaarten leest een streep als een fout. */
.notification-item + .notification-item {
  border-top: 1px solid var(--sets-border);
  border-radius: 14px;
}

html:not(.dark) .notification-item {
  background: var(--sets-surface-1);
  box-shadow: 0 1px 2px rgba(35, 39, 47, 0.05);
}

html:not(.dark) .notification-item + .notification-item { border-top: 0; }

html:not(.dark) .notification-item-icon {
  background: rgba(145, 189, 17, 0.14);
  color: var(--sets-accent-text);
}

html:not(.dark) .notification-item-heading time { color: #71767f; }

html:not(.dark) .notification-item.is-unread {
  padding-inline: 10px;
  background: rgba(145, 189, 17, 0.1);
  box-shadow: inset 3px 0 0 #7ea70c;
}

html:not(.dark) .notification-header-button { color: #3d424a; }
html:not(.dark) .notification-unread-dot { background: #7ea70c; }

/* ── Caloriebalans ───────────────────────────────────────────────
   De cijfers in de grafiek volgen de tekstkleur van het thema; in
   light mode was wit op wit onleesbaar. */
.calorie-balance-svg {
  display: block;
  color: var(--sets-text);
  overflow: visible;
}

.calorie-balance-legend {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-bottom: 4px;
  color: var(--sets-text-3);
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.calorie-balance-legend span.swatch {
  width: 8px;
  height: 8px;
  border-radius: 3px;
}

.calorie-balance-legend > span {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

/* ── Dagkiezer bij Voeding ───────────────────────────────────── */
.nutrition-day-nav {
  display: grid;
  grid-template-columns: 40px minmax(0, 1fr) 40px;
  align-items: center;
  gap: 8px;
  margin-bottom: 10px;
}

.nutrition-day-nav h2 {
  color: var(--sets-text);
  font-size: 15px;
  font-weight: 700;
  text-align: center;
}

.nutrition-day-arrow {
  width: 40px;
  height: 40px;
  display: grid;
  place-items: center;
  border: 1px solid var(--sets-border);
  border-radius: 999px;
  background: var(--sets-surface-1);
  color: var(--sets-text-2);
  cursor: pointer;
}

.nutrition-day-arrow svg { width: 18px; height: 18px; }
.nutrition-day-arrow:active { background: var(--sets-surface-2); }

.nutrition-day-arrow[disabled] {
  opacity: 0.35;
  pointer-events: none;
}

/* ── Kop van de TQS-kaart ────────────────────────────────────────
   Het vraagteken en het versielabel stonden allebei in een kadertje.
   Twee vierkantjes naast een titel lezen als knoppen met gewicht,
   terwijl het om een icoon en een voetnoot gaat. De rand gaat eruit;
   het raakvlak van de knop blijft even groot. */
.plan-tqs-help {
  border: 0;
  border-radius: 999px;
  color: var(--sets-text-3);
}

.plan-tqs-help:active { background: var(--sets-surface-2); }

.plan-version-badge {
  padding: 0;
  border: 0;
  color: var(--sets-text-3);
  opacity: 0.75;
}

/* ── De landingspagina is geen app-scherm ────────────────────────
   Op een breed scherm krijgt #app de vorm van een telefoonkolom: 720
   tot 760 pixels breed, met randen, een eigen achtergrond en links
   ruimte voor de zijbalk. Dat klopt voor de app, maar de
   landingspagina en de inlogschermen zijn gewone webpagina's. Daar
   leverde het een witte baan midden op het scherm op, met de hero
   ernaast uit het lood omdat de zijbalkruimte wel werd gereserveerd
   terwijl de zijbalk verborgen is.

   `data-screen` staat al op de body (js/app.js zet hem bij elke
   schermwissel), dus we kunnen het kader daar precies uitzetten. */
@media (min-width: 700px) {
  body[data-screen="welcome"] #app,
  body[data-screen="login"] #app,
  body[data-screen="update-password"] #app {
    width: 100%;
    max-width: none;
    border-inline: 0;
    background: transparent;
    box-shadow: none;
  }

  html:not(.dark) body[data-screen="welcome"] #app,
  html:not(.dark) body[data-screen="login"] #app,
  html:not(.dark) body[data-screen="update-password"] #app {
    border-inline-color: transparent;
    background: transparent;
    box-shadow: none;
  }
}

@media (min-width: 1024px) {
  /* De uitbraak naar volle breedte was nodig binnen de smalle kolom;
     nu de kolom weg is, zou hij de pagina juist scheeftrekken. */
  body[data-screen="welcome"] #screen-welcome,
  body[data-screen="login"] #screen-login {
    width: 100%;
    margin-left: 0;
  }
}

/* ── Landingspagina · wat Sets voor je uitrekent ─────────────────
   Drie blokken die het zware werk van de app verkopen: programma,
   voeding en coach. Op smal onder elkaar, vanaf tablet naast elkaar
   zodat ze als één aanbod lezen in plaats van als drie losse claims. */
.welcome-value-grid {
  display: grid;
  gap: 22px;
  margin-top: 26px;
  grid-template-columns: 1fr;
}

.welcome-value-grid article {
  padding-top: 18px;
  border-top: 1px solid var(--sets-border);
}

.welcome-value-grid h3 {
  margin-bottom: 6px;
  color: var(--sets-text);
  font-size: 17px;
  font-weight: 650;
  line-height: 1.25;
}

.welcome-value-grid p {
  color: var(--sets-text-2);
  font-size: 14px;
  line-height: 1.55;
}

@media (min-width: 880px) {
  .welcome-value-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 32px;
  }
}

/* ── D4 · restjes die geen eigen kleurregel hadden ───────────────────────
   Deze twee stonden nergens in lichte modus opgeschreven en vielen dus terug
   op wat ze toevallig erfden. Ze horen bij dezelfde audit als de accenttokens
   hierboven: gemeten, niet gegokt. */

/* De dagletters van de weekstrook. `opacity-70` bovenop een toch al gedempt
   grijs bracht "MA" op ~2,6:1 tegen de chipvulling; de chip vertelt zijn
   staat al via rand, vulling en het bolletje, dus de letters mogen gewoon
   voluit. De naam eronder erft --sets-text-3 en haalt daarmee 4,70:1.
   Geldt voor beide thema's: in donkere modus zakte dezelfde letter naar
   3,33:1, ook door die 0,7.
   (De getrainde dag houdt zijn lime: die regel staat met !important in
   styles.css en wint hier bewust van.) */
.schedule-days button > span {
  opacity: 1;
}

/* .home-today-eyebrow heeft alleen een `html.dark`-regel in
   styles/home-today.css, dus in lichte modus stond er geen kleur — hij erfde
   #8a8a8e (3,44:1). polish.css laadt ná home-today.css, dus dit is de
   plek om dat recht te zetten zonder een bestand van een andere stream aan
   te raken. */
html:not(.dark) .home-today-eyebrow {
  color: var(--sets-text-3);
}

html:not(.dark) .home-today-card.is-planned .home-today-eyebrow {
  color: var(--sets-accent-text);
}

/* ── D4 · gedempte tekst mag niet via `opacity` gedempt worden ───────────
   Een grijs dat op zichzelf net AA haalt, zakt er met `opacity: 0.75`
   dwars doorheen: de dekking vermenigvuldigt met de kleur en de meting
   volgt de gerenderde pixel, niet de opgeschreven hex. In lichte modus
   dempen we daarom met een kleur en niet met dekking. */
html:not(.dark) .settings-row-value.is-muted {
  color: #5b626c;
  opacity: 1;
}

html:not(.dark) .plan-version-badge {
  color: #5b626c;
  opacity: 1;
}

/* ── D4 · gevaar-rood had geen lichte tegenhanger ────────────────────────
   Van de Tailwind-utilities heeft alleen de zinc-familie een
   `html:not(.dark)`-variant gekregen; text-red-400 (#f87171 → 2,77:1) en
   text-red-500 (#ef4444 → 2,86:1 op de eigen rode chip) bleven staan zoals
   ze voor een donkere achtergrond bedoeld waren. #a51f1f haalt ≥6,4:1 op
   elk licht oppervlak en ≥5,6:1 op de lichte rode chipvulling. */
html:not(.dark) .text-red-400,
html:not(.dark) .text-red-500 {
  color: #a51f1f !important;
}
