*, ::before, ::after {
  --tw-border-spacing-x: 0;
  --tw-border-spacing-y: 0;
  --tw-translate-x: 0;
  --tw-translate-y: 0;
  --tw-rotate: 0;
  --tw-skew-x: 0;
  --tw-skew-y: 0;
  --tw-scale-x: 1;
  --tw-scale-y: 1;
  --tw-pan-x:  ;
  --tw-pan-y:  ;
  --tw-pinch-zoom:  ;
  --tw-scroll-snap-strictness: proximity;
  --tw-gradient-from-position:  ;
  --tw-gradient-via-position:  ;
  --tw-gradient-to-position:  ;
  --tw-ordinal:  ;
  --tw-slashed-zero:  ;
  --tw-numeric-figure:  ;
  --tw-numeric-spacing:  ;
  --tw-numeric-fraction:  ;
  --tw-ring-inset:  ;
  --tw-ring-offset-width: 0px;
  --tw-ring-offset-color: #fff;
  --tw-ring-color: rgb(59 130 246 / 0.5);
  --tw-ring-offset-shadow: 0 0 #0000;
  --tw-ring-shadow: 0 0 #0000;
  --tw-shadow: 0 0 #0000;
  --tw-shadow-colored: 0 0 #0000;
  --tw-blur:  ;
  --tw-brightness:  ;
  --tw-contrast:  ;
  --tw-grayscale:  ;
  --tw-hue-rotate:  ;
  --tw-invert:  ;
  --tw-saturate:  ;
  --tw-sepia:  ;
  --tw-drop-shadow:  ;
  --tw-backdrop-blur:  ;
  --tw-backdrop-brightness:  ;
  --tw-backdrop-contrast:  ;
  --tw-backdrop-grayscale:  ;
  --tw-backdrop-hue-rotate:  ;
  --tw-backdrop-invert:  ;
  --tw-backdrop-opacity:  ;
  --tw-backdrop-saturate:  ;
  --tw-backdrop-sepia:  ;
  --tw-contain-size:  ;
  --tw-contain-layout:  ;
  --tw-contain-paint:  ;
  --tw-contain-style:  ;
}

::backdrop {
  --tw-border-spacing-x: 0;
  --tw-border-spacing-y: 0;
  --tw-translate-x: 0;
  --tw-translate-y: 0;
  --tw-rotate: 0;
  --tw-skew-x: 0;
  --tw-skew-y: 0;
  --tw-scale-x: 1;
  --tw-scale-y: 1;
  --tw-pan-x:  ;
  --tw-pan-y:  ;
  --tw-pinch-zoom:  ;
  --tw-scroll-snap-strictness: proximity;
  --tw-gradient-from-position:  ;
  --tw-gradient-via-position:  ;
  --tw-gradient-to-position:  ;
  --tw-ordinal:  ;
  --tw-slashed-zero:  ;
  --tw-numeric-figure:  ;
  --tw-numeric-spacing:  ;
  --tw-numeric-fraction:  ;
  --tw-ring-inset:  ;
  --tw-ring-offset-width: 0px;
  --tw-ring-offset-color: #fff;
  --tw-ring-color: rgb(59 130 246 / 0.5);
  --tw-ring-offset-shadow: 0 0 #0000;
  --tw-ring-shadow: 0 0 #0000;
  --tw-shadow: 0 0 #0000;
  --tw-shadow-colored: 0 0 #0000;
  --tw-blur:  ;
  --tw-brightness:  ;
  --tw-contrast:  ;
  --tw-grayscale:  ;
  --tw-hue-rotate:  ;
  --tw-invert:  ;
  --tw-saturate:  ;
  --tw-sepia:  ;
  --tw-drop-shadow:  ;
  --tw-backdrop-blur:  ;
  --tw-backdrop-brightness:  ;
  --tw-backdrop-contrast:  ;
  --tw-backdrop-grayscale:  ;
  --tw-backdrop-hue-rotate:  ;
  --tw-backdrop-invert:  ;
  --tw-backdrop-opacity:  ;
  --tw-backdrop-saturate:  ;
  --tw-backdrop-sepia:  ;
  --tw-contain-size:  ;
  --tw-contain-layout:  ;
  --tw-contain-paint:  ;
  --tw-contain-style:  ;
}/*
! tailwindcss v3.4.19 | MIT License | https://tailwindcss.com
*//*
1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4)
2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116)
*/

*,
::before,
::after {
  box-sizing: border-box; /* 1 */
  border-width: 0; /* 2 */
  border-style: solid; /* 2 */
  border-color: #e5e7eb; /* 2 */
}

::before,
::after {
  --tw-content: '';
}

/*
1. Use a consistent sensible line-height in all browsers.
2. Prevent adjustments of font size after orientation changes in iOS.
3. Use a more readable tab size.
4. Use the user's configured `sans` font-family by default.
5. Use the user's configured `sans` font-feature-settings by default.
6. Use the user's configured `sans` font-variation-settings by default.
7. Disable tap highlights on iOS
*/

html,
:host {
  line-height: 1.5; /* 1 */
  -webkit-text-size-adjust: 100%; /* 2 */
  -moz-tab-size: 4; /* 3 */
  -o-tab-size: 4;
     tab-size: 4; /* 3 */
  font-family: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; /* 4 */
  font-feature-settings: normal; /* 5 */
  font-variation-settings: normal; /* 6 */
  -webkit-tap-highlight-color: transparent; /* 7 */
}

/*
1. Remove the margin in all browsers.
2. Inherit line-height from `html` so users can set them as a class directly on the `html` element.
*/

body {
  margin: 0; /* 1 */
  line-height: inherit; /* 2 */
}

/*
1. Add the correct height in Firefox.
2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655)
3. Ensure horizontal rules are visible by default.
*/

hr {
  height: 0; /* 1 */
  color: inherit; /* 2 */
  border-top-width: 1px; /* 3 */
}

/*
Add the correct text decoration in Chrome, Edge, and Safari.
*/

abbr:where([title]) {
  -webkit-text-decoration: underline dotted;
          text-decoration: underline dotted;
}

/*
Remove the default font size and weight for headings.
*/

h1,
h2,
h3,
h4,
h5,
h6 {
  font-size: inherit;
  font-weight: inherit;
}

/*
Reset links to optimize for opt-in styling instead of opt-out.
*/

a {
  color: inherit;
  text-decoration: inherit;
}

/*
Add the correct font weight in Edge and Safari.
*/

b,
strong {
  font-weight: bolder;
}

/*
1. Use the user's configured `mono` font-family by default.
2. Use the user's configured `mono` font-feature-settings by default.
3. Use the user's configured `mono` font-variation-settings by default.
4. Correct the odd `em` font sizing in all browsers.
*/

code,
kbd,
samp,
pre {
  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; /* 1 */
  font-feature-settings: normal; /* 2 */
  font-variation-settings: normal; /* 3 */
  font-size: 1em; /* 4 */
}

/*
Add the correct font size in all browsers.
*/

small {
  font-size: 80%;
}

/*
Prevent `sub` and `sup` elements from affecting the line height in all browsers.
*/

sub,
sup {
  font-size: 75%;
  line-height: 0;
  position: relative;
  vertical-align: baseline;
}

sub {
  bottom: -0.25em;
}

sup {
  top: -0.5em;
}

/*
1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297)
2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016)
3. Remove gaps between table borders by default.
*/

table {
  text-indent: 0; /* 1 */
  border-color: inherit; /* 2 */
  border-collapse: collapse; /* 3 */
}

/*
1. Change the font styles in all browsers.
2. Remove the margin in Firefox and Safari.
3. Remove default padding in all browsers.
*/

button,
input,
optgroup,
select,
textarea {
  font-family: inherit; /* 1 */
  font-feature-settings: inherit; /* 1 */
  font-variation-settings: inherit; /* 1 */
  font-size: 100%; /* 1 */
  font-weight: inherit; /* 1 */
  line-height: inherit; /* 1 */
  letter-spacing: inherit; /* 1 */
  color: inherit; /* 1 */
  margin: 0; /* 2 */
  padding: 0; /* 3 */
}

/*
Remove the inheritance of text transform in Edge and Firefox.
*/

button,
select {
  text-transform: none;
}

/*
1. Correct the inability to style clickable types in iOS and Safari.
2. Remove default button styles.
*/

button,
input:where([type='button']),
input:where([type='reset']),
input:where([type='submit']) {
  -webkit-appearance: button; /* 1 */
  background-color: transparent; /* 2 */
  background-image: none; /* 2 */
}

/*
Use the modern Firefox focus style for all focusable elements.
*/

:-moz-focusring {
  outline: auto;
}

/*
Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737)
*/

:-moz-ui-invalid {
  box-shadow: none;
}

/*
Add the correct vertical alignment in Chrome and Firefox.
*/

progress {
  vertical-align: baseline;
}

/*
Correct the cursor style of increment and decrement buttons in Safari.
*/

::-webkit-inner-spin-button,
::-webkit-outer-spin-button {
  height: auto;
}

/*
1. Correct the odd appearance in Chrome and Safari.
2. Correct the outline style in Safari.
*/

[type='search'] {
  -webkit-appearance: textfield; /* 1 */
  outline-offset: -2px; /* 2 */
}

/*
Remove the inner padding in Chrome and Safari on macOS.
*/

::-webkit-search-decoration {
  -webkit-appearance: none;
}

/*
1. Correct the inability to style clickable types in iOS and Safari.
2. Change font properties to `inherit` in Safari.
*/

::-webkit-file-upload-button {
  -webkit-appearance: button; /* 1 */
  font: inherit; /* 2 */
}

/*
Add the correct display in Chrome and Safari.
*/

summary {
  display: list-item;
}

/*
Removes the default spacing and border for appropriate elements.
*/

blockquote,
dl,
dd,
h1,
h2,
h3,
h4,
h5,
h6,
hr,
figure,
p,
pre {
  margin: 0;
}

fieldset {
  margin: 0;
  padding: 0;
}

legend {
  padding: 0;
}

ol,
ul,
menu {
  list-style: none;
  margin: 0;
  padding: 0;
}

/*
Reset default styling for dialogs.
*/
dialog {
  padding: 0;
}

/*
Prevent resizing textareas horizontally by default.
*/

textarea {
  resize: vertical;
}

/*
1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300)
2. Set the default placeholder color to the user's configured gray 400 color.
*/

input::-moz-placeholder, textarea::-moz-placeholder {
  opacity: 1; /* 1 */
  color: #9ca3af; /* 2 */
}

input::placeholder,
textarea::placeholder {
  opacity: 1; /* 1 */
  color: #9ca3af; /* 2 */
}

/*
Set the default cursor for buttons.
*/

button,
[role="button"] {
  cursor: pointer;
}

/*
Make sure disabled buttons don't get the pointer cursor.
*/
:disabled {
  cursor: default;
}

/*
1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14)
2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210)
   This can trigger a poorly considered lint error in some tools but is included by design.
*/

img,
svg,
video,
canvas,
audio,
iframe,
embed,
object {
  display: block; /* 1 */
  vertical-align: middle; /* 2 */
}

/*
Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14)
*/

img,
video {
  max-width: 100%;
  height: auto;
}

/* Make elements with the HTML hidden attribute stay hidden by default */
[hidden]:where(:not([hidden="until-found"])) {
  display: none;
}
  :root {
    --radius: 1rem;
    /* Enhanced High-Contrast Accessible Light Theme: #FAF9F7 / #F6F4F2 */
    --background: 0.98 0.005 60;
    --foreground: 0.15 0 0; /* Darkened from 0.22 to #222 equivalent for better contrast */
    --card: 0.965 0.005 60;
    --card-foreground: 0.15 0 0; /* Darkened for better contrast */
    --popover: 0.965 0.005 60;
    --popover-foreground: 0.15 0 0; /* Darkened for better contrast */
    --primary: 0.15 0 0; /* Darkened for better contrast */
    --primary-foreground: 0.985 0 0;
    --secondary: 0.95 0.005 60;
    --secondary-foreground: 0.15 0 0; /* Darkened for better contrast */
    --muted: 0.93 0.005 60;
    --muted-foreground: 0.45 0 0; /* Darkened from 0.55 for better contrast */
    --accent: 0.65 0.2 40; /* Strengthened chroma from 0.19 to 0.20 for better visibility */
    --accent-foreground: 0.985 0 0;
    /* FASE 1 accent variables — central orange accent (#E8630A) and its variants.
       --accent-hex: solid fills. --accent-rgb: rgb triplet for rgba()/glow usage.
       --accent-dim: dark orange (#4a2400) for filled backgrounds. */
    --accent-hex: #e8630a;
    --accent-rgb: 232, 99, 10;
    --accent-dim: #4a2400;
    --destructive: 0.577 0.245 27.325;
    --destructive-foreground: 0.985 0 0;
    --border: 0.8 0.005 60; /* Darkened from 0.86 for better definition */
    --input: 0.94 0.005 60; /* Light background for inputs in light theme */
    --ring: 0.65 0.2 40; /* Strengthened to match accent */
    --chart-1: 0.65 0.2 40; /* Strengthened to match accent */
    --chart-2: 0.6 0.15 220;
    --chart-3: 0.65 0.18 140;
    --chart-4: 0.55 0.2 280;
    --chart-5: 0.7 0.16 60;

    /* Enhanced High-Contrast Neumorphic Light Mode Shadows with Improved Depth */
    --neomorph-shadow-sm: 3px 3px 8px rgba(0, 0, 0, 0.18), -3px -3px 8px
      rgba(255, 255, 255, 0.95);
    --neomorph-shadow: 5px 5px 14px rgba(0, 0, 0, 0.22), -5px -5px 14px
      rgba(255, 255, 255, 0.95);
    --neomorph-shadow-lg: 8px 8px 18px rgba(0, 0, 0, 0.25), -8px -8px 18px
      rgba(255, 255, 255, 0.98);
    --neomorph-shadow-xl: 10px 10px 22px rgba(0, 0, 0, 0.2), -10px -10px 22px
      rgba(255, 255, 255, 1);
    --neomorph-inset: inset 4px 4px 9px rgba(0, 0, 0, 0.16), inset -4px -4px 9px
      rgba(255, 255, 255, 0.85);
    --neomorph-inset-sm: inset 3px 3px 7px rgba(0, 0, 0, 0.14), inset -3px -3px
      7px rgba(255, 255, 255, 0.75);
    --neomorph-hover: 6px 6px 14px rgba(0, 0, 0, 0.18), -6px -6px 14px
      rgba(255, 255, 255, 0.98);
    --neomorph-pressed: inset 3px 3px 7px rgba(0, 0, 0, 0.18), inset -3px -3px
      7px rgba(255, 255, 255, 0.8);

    /* Enhanced High-Contrast Template Card Glass Effect with Better Depth */
    --template-card-shadow:
      inset 2px 2px 5px rgba(255, 255, 255, 0.6),
      inset -2px -2px 5px rgba(0, 0, 0, 0.12),
      4px 4px 10px rgba(0, 0, 0, 0.15),
      -4px -4px 10px rgba(255, 255, 255, 0.9);
    --template-card-hover-shadow:
      inset 2px 2px 5px rgba(255, 255, 255, 0.7),
      inset -2px -2px 5px rgba(0, 0, 0, 0.14),
      5px 5px 12px rgba(0, 0, 0, 0.17),
      -5px -5px 12px rgba(255, 255, 255, 0.95);

    /* Subtle orange accent ring for light theme cards */
    --neomorph-accent-ring: 0 0 0 1px rgba(var(--accent-rgb), 0.25);

    /* ════════════════════════════════════════════════════════════════════════
       FASE 1 STATS — Monthly Calendar + Goal ring + Week bars + Insight card
       Additive tokens (light theme). Mirror the .wq-ring-well engraved pattern
       but tuned for light mode: lighter inset shadows so the tiles read as
       sculpted recesses on a light surface. Orange glow uses --accent-rgb
       (232,99,10) which is theme-agnostic. Today's tile uses a ring (not a
       glow) so it stays distinct from trained days.
       ════════════════════════════════════════════════════════════════════════ */
    /* Engraved calendar day tile — square/rounded-lg variant of .wq-ring-well.
       5px inset (light-tuned) + 1px hairline rim = sculpted recess for day
       numbers. Same depth language as the weekly quest ring well. */
    --mw-tile-well:
      inset 5px 5px 9px rgba(0, 0, 0, 0.16),
      inset -5px -5px 9px rgba(255, 255, 255, 0.7),
      inset 0 0 0 1px rgba(0, 0, 0, 0.04);
    /* Orange glow for trained days — soft warm halo using --accent-rgb. Tuned
       for light bg: slightly lower alpha so it doesn't blow out on light. */
    --mw-tile-trained-glow: 0 0 6px rgba(var(--accent-rgb), 0.4), 0 0 12px
      rgba(var(--accent-rgb), 0.18);
    /* Ring for today's tile — thin accent outline (not a glow) so today reads
       distinct from trained days. */
    --mw-tile-today-ring: 0 0 0 1.5px rgba(var(--accent-rgb), 0.6);
    /* Subtle inset for rest days (non-trained in-month days) — lighter than
       --mw-tile-well so rest days read as quieter empty engraved tiles. */
    --mw-tile-rest: inset 3px 3px 6px rgba(0, 0, 0, 0.12), inset -3px -3px 6px
      rgba(255, 255, 255, 0.6);
    /* Monthly goal ring well — mirrors .wq-ring-well (100px, 5px inset) but
       light-tuned. Hosts ProgressRing size=88 strokeWidth=8. */
    --mw-ring-well:
      inset 5px 5px 9px rgba(0, 0, 0, 0.16),
      inset -5px -5px 9px rgba(255, 255, 255, 0.7),
      inset 0 0 0 1px rgba(0, 0, 0, 0.04);
    /* Orange arc glow for the monthly goal ring — same halo as .wq-arc-glow
       but light-tuned alpha. */
    --mw-ring-glow: 0 0 6px rgba(var(--accent-rgb), 0.45), 0 0 14px
      rgba(var(--accent-rgb), 0.2);

    /* Starter plan accent colors — light-theme-optimized: slightly darker chroma
       so the thin strips and icon squares stay visible on a light background.
       Mirrors the .dark definitions (regels 122-132) but tuned for light mode. */
    --plan-orange: 0.55 0.19 45;
    --plan-blue: 0.5 0.16 240;
    --plan-green: 0.5 0.16 145;
    --plan-purple: 0.48 0.17 290;

    /* Plan accent color utilities — light-theme variants */
    --plan-chest-push: 0.55 0.19 45; /* Orange */
    --plan-back-pull: 0.5 0.16 240; /* Blue */
    --plan-legs-core: 0.5 0.16 145; /* Green */
    --plan-shoulders-arms: 0.48 0.17 290; /* Purple */

    /* ════════════════════════════════════════════════════════════════════════
       FASE 3 STATS — Fatigue vs Fitness + Push/Pull/Legs donut + Overload nav
       Additive tokens (light theme). Fitness = blauw (--chart-2 family),
       Vermoeidheid = rood (new --ff-fatigue). TSB alert = groen/oranje/rood.
       PPL donut = oranje/blauw/groen (--chart-1/2/3). Reuses --accent-hex /
       --accent-rgb for orange. Engraved wells mirror --wq-ring-well /
       --mw-ring-well pattern (light-tuned insets).
       ════════════════════════════════════════════════════════════════════════ */
    /* Fitness (blauw) — rgb triplet for gradient/glow usage in SVG + CSS.
       Matches --chart-2 light value (0.6 0.15 220). */
    --ff-fitness-rgb: 64, 140, 220;
    /* Vermoeidheid (rood) — distinct from --destructive; a fatigue red tuned
       for chart lines + KPI accent on light bg. */
    --ff-fatigue-rgb: 220, 80, 70;
    /* KPI inset well — engraved recess for the Fitness/Vermoeidheid value
       cards. Light-tuned (lighter insets than dark). Mirrors --mw-ring-well
       language but rectangular (rounded-xl). */
    --ff-kpi-well:
      inset 5px 5px 9px rgba(0, 0, 0, 0.16),
      inset -5px -5px 9px rgba(255, 255, 255, 0.7),
      inset 0 0 0 1px rgba(0, 0, 0, 0.04);
    /* TSB alert colors — groen (fresh) / oranje (moderate) / rood (overtrained).
       Light-tuned OKLCH values for sufficient contrast on light bg. */
    --ff-alert-green: 0.6 0.16 145;
    --ff-alert-green-rgb: 80, 180, 110;
    --ff-alert-amber: 0.7 0.17 60;
    --ff-alert-amber-rgb: 210, 145, 50;
    --ff-alert-red: 0.55 0.2 25;
    --ff-alert-red-rgb: 200, 70, 60;
    /* PPL donut ring well — mirrors --wq-ring-well / --mw-ring-well (light
       tuned). 100px+ circular recess hosting the donut SVG. */
    --ppl-ring-well:
      inset 5px 5px 9px rgba(0, 0, 0, 0.16),
      inset -5px -5px 9px rgba(255, 255, 255, 0.7),
      inset 0 0 0 1px rgba(0, 0, 0, 0.04);
    /* PPL arc glow — soft drop-shadow halo on the donut arcs. Reads the
       per-arc color via --ppl-arc-rgb set on each arc element. */
    --ppl-arc-glow: 0 0 6px rgba(var(--ppl-arc-rgb, var(--accent-rgb)), 0.45), 0
      0 14px rgba(var(--ppl-arc-rgb, var(--accent-rgb)), 0.2);
    /* Overload nav-card sparkline preview area — inset well hosting the mini
       sparkline SVG so it reads as a sculpted recess, not a flat sticker. */
    --ol-nav-spark: inset 3px 3px 6px rgba(0, 0, 0, 0.14), inset -3px -3px 6px
      rgba(255, 255, 255, 0.6);

    /* ════════════════════════════════════════════════════════════════════════
       OVERLOAD PROGRESSION DETAIL PAGE — engraved KPI wells + pill selectors
       Additive tokens (light theme). Mirror the FASE 3 engraved well pattern
       (--wq-ring-well / --ff-kpi-well / --ppl-ring-well: 5px deep inset +
       hairline rim) so the Overload page shares the same sculpted-recess
       language as the rest of the Stats tab. Orange accent (#E8630A /
       --accent-rgb) is theme-agnostic. Light-tuned insets (lighter than dark)
       so the wells read as sculpted recesses on the light FAF9F7 surface.
       ════════════════════════════════════════════════════════════════════════ */
    /* KPI inset well — engraved recess for the Overload page KPI cards
       (Average Load, Total Load). Light-tuned mirror of --ff-kpi-well /
       --wq-ring-well (5px deep inset + hairline rim). */
    --op-kpi-well:
      inset 5px 5px 9px rgba(0, 0, 0, 0.16),
      inset -5px -5px 9px rgba(255, 255, 255, 0.7),
      inset 0 0 0 1px rgba(0, 0, 0, 0.04);
    /* Chart container well — larger engraved recess hosting the Overload
       curve SVG so the chart reads as sunk into the page surface. Same depth
       language as --op-kpi-well (light-tuned 5px inset + hairline rim). */
    --op-chart-well:
      inset 5px 5px 9px rgba(0, 0, 0, 0.16),
      inset -5px -5px 9px rgba(255, 255, 255, 0.7),
      inset 0 0 0 1px rgba(0, 0, 0, 0.04);
    /* Hero KPI well — deeper engraved recess for the hero KPI card (larger
       6px inset) so the trend value reads as the most prominent sculpted
       element on the page. Light-tuned. */
    --op-hero-well:
      inset 6px 6px 11px rgba(0, 0, 0, 0.18),
      inset -6px -6px 11px rgba(255, 255, 255, 0.72),
      inset 0 0 0 1px rgba(0, 0, 0, 0.05);
    /* Trend arrow accent glow — soft warm halo on the hero trend arrow
       (uses --accent-rgb). Light-tuned alpha so it doesn't blow out on
       FAF9F7. */
    --op-trend-glow: 0 0 6px rgba(var(--accent-rgb), 0.4), 0 0 14px
      rgba(var(--accent-rgb), 0.18);
    /* Pill raised shadow — subtle neumorphic raised surface for inactive
       time-filter + exercise selector pills. Light-tuned (lighter than dark). */
    --op-pill-raised: 3px 3px 6px rgba(0, 0, 0, 0.14), -3px -3px 6px
      rgba(255, 255, 255, 0.85);
    /* Pill active glow — soft warm halo on the active pill (uses --accent-rgb).
       Light-tuned alpha. */
    --op-pill-active-glow: 0 0 6px rgba(var(--accent-rgb), 0.4), 0 0 14px
      rgba(var(--accent-rgb), 0.18);
    /* Empty-state container well — subtle inset for the compact empty-state
       variant. Lighter than --op-kpi-well so it reads as a quiet recess. */
    --op-empty-well: inset 3px 3px 7px rgba(0, 0, 0, 0.12), inset -3px -3px 7px
      rgba(255, 255, 255, 0.65);
    /* PR star glow — soft warm halo on PR star markers in the chart (uses
       --accent-rgb). Light-tuned alpha. */
    --op-star-glow: 0 0 4px rgba(var(--accent-rgb), 0.55), 0 0 10px
      rgba(var(--accent-rgb), 0.25);
    /* Fase 1 — Buddy Tab Challenges. Outer card engraved well (6px deeper,
       mirrors --op-hero-well light values). */
    --wvc-card-well:
      inset 6px 6px 11px rgba(0, 0, 0, 0.18), inset -6px -6px 11px
      rgba(255, 255, 255, 0.7), inset 0 0 0 1px rgba(0, 0, 0, 0.04);
    /* Split-view sub-kaartje engraved well (5px, mirrors --wq-ring-well light). */
    --wvc-sub-well:
      inset 5px 5px 9px rgba(0, 0, 0, 0.16), inset -5px -5px 9px
      rgba(255, 255, 255, 0.7), inset 0 0 0 1px rgba(0, 0, 0, 0.04);
    /* Comparison bar track engraved well (5px, mirrors --wq-ring-well light). */
    --wvc-bar-well:
      inset 5px 5px 9px rgba(0, 0, 0, 0.16), inset -5px -5px 9px
      rgba(255, 255, 255, 0.7), inset 0 0 0 1px rgba(0, 0, 0, 0.04);
    /* LIVE pill orange glow (uses --accent-rgb). */
    --wvc-live-glow: 0 0 12px rgba(var(--accent-rgb), 0.45);
    /* Winning sub-kaartje stronger orange glow (uses --accent-rgb). */
    --wvc-winner-glow: 0 0 18px rgba(var(--accent-rgb), 0.55);
    /* Leaderboard segmented control track (5px, mirrors --wq-ring-well light). */
    --lb-seg-well:
      inset 5px 5px 9px rgba(0, 0, 0, 0.16), inset -5px -5px 9px
      rgba(255, 255, 255, 0.7), inset 0 0 0 1px rgba(0, 0, 0, 0.04);
    /* Leaderboard row engraved well (5px, mirrors --wq-ring-well light). */
    --lb-row-well:
      inset 5px 5px 9px rgba(0, 0, 0, 0.16), inset -5px -5px 9px
      rgba(255, 255, 255, 0.7), inset 0 0 0 1px rgba(0, 0, 0, 0.04);
    /* #1 leaderboard row stronger orange glow (uses --accent-rgb). */
    --lb-rank1-glow: 0 0 20px rgba(var(--accent-rgb), 0.6);
    /* Group average comparison card engraved well (5px, mirrors --wq-ring-well
       light). */
    --lb-avg-well:
      inset 5px 5px 9px rgba(0, 0, 0, 0.16), inset -5px -5px 9px
      rgba(255, 255, 255, 0.7), inset 0 0 0 1px rgba(0, 0, 0, 0.04);
    /* PR Ladder outer card engraved well (6px deeper, mirrors --wvc-card-well
       light). */
    --pr-card-well:
      inset 6px 6px 11px rgba(0, 0, 0, 0.18), inset -6px -6px 11px
      rgba(255, 255, 255, 0.7), inset 0 0 0 1px rgba(0, 0, 0, 0.04);
    /* PR Ladder segmented control track (5px, mirrors --lb-seg-well light). */
    --pr-seg-well:
      inset 5px 5px 9px rgba(0, 0, 0, 0.16), inset -5px -5px 9px
      rgba(255, 255, 255, 0.7), inset 0 0 0 1px rgba(0, 0, 0, 0.04);
    /* PR Ladder row engraved well (5px, mirrors --lb-row-well light). */
    --pr-row-well:
      inset 5px 5px 9px rgba(0, 0, 0, 0.16), inset -5px -5px 9px
      rgba(255, 255, 255, 0.7), inset 0 0 0 1px rgba(0, 0, 0, 0.04);
    /* #1 PR Ladder row stronger orange glow (uses --accent-rgb). */
    --pr-rank1-glow: 0 0 20px rgba(var(--accent-rgb), 0.6);
    /* #2 PR Ladder row softer orange glow (uses --accent-rgb). */
    --pr-rank2-glow: 0 0 14px rgba(var(--accent-rgb), 0.4);
    /* #3 PR Ladder row subtle orange glow (uses --accent-rgb). */
    --pr-rank3-glow: 0 0 10px rgba(var(--accent-rgb), 0.3);
    /* PR Ladder trophy warm orange glow (uses --accent-rgb). */
    --pr-trophy-glow: 0 0 16px rgba(var(--accent-rgb), 0.55);
    /* Fase 3 — Your Streak outer card engraved well (6px deeper, mirrors
       --wvc-card-well / --pr-card-well light). */
    --streak-card-well:
      inset 6px 6px 11px rgba(0, 0, 0, 0.18), inset -6px -6px 11px
      rgba(255, 255, 255, 0.7), inset 0 0 0 1px rgba(0, 0, 0, 0.04);
    /* Streak day-circle engraved well (5px, mirrors --wq-ring-well light). */
    --streak-ring-well:
      inset 5px 5px 9px rgba(0, 0, 0, 0.16), inset -5px -5px 9px
      rgba(255, 255, 255, 0.7), inset 0 0 0 1px rgba(0, 0, 0, 0.04);
    /* Streak counter + trained day orange glow (uses --accent-rgb, mirrors
       --wvc-live-glow). */
    --streak-glow: 0 0 12px rgba(var(--accent-rgb), 0.45);
    /* Fase 3 — Muscle Balance Race outer card engraved well (6px deeper,
       mirrors --wvc-card-well / --pr-card-well light). */
    --mbr-card-well:
      inset 6px 6px 11px rgba(0, 0, 0, 0.18), inset -6px -6px 11px
      rgba(255, 255, 255, 0.7), inset 0 0 0 1px rgba(0, 0, 0, 0.04);
    /* Muscle Balance progress bar track engraved well (5px, mirrors
       --wvc-bar-well light). */
    --mbr-bar-well:
      inset 5px 5px 9px rgba(0, 0, 0, 0.16), inset -5px -5px 9px
      rgba(255, 255, 255, 0.7), inset 0 0 0 1px rgba(0, 0, 0, 0.04);
    /* Muscle Balance Week/All-time segmented control track (5px, mirrors
       --lb-seg-well / --pr-seg-well light). */
    --mbr-seg-well:
      inset 5px 5px 9px rgba(0, 0, 0, 0.16), inset -5px -5px 9px
      rgba(255, 255, 255, 0.7), inset 0 0 0 1px rgba(0, 0, 0, 0.04);
    /* Muscle Balance YOU/BUDDY sub-section engraved well (5px, mirrors
       --wvc-sub-well light). */
    --mbr-sub-well:
      inset 5px 5px 9px rgba(0, 0, 0, 0.16), inset -5px -5px 9px
      rgba(255, 255, 255, 0.7), inset 0 0 0 1px rgba(0, 0, 0, 0.04);
    /* Winning PPL category stronger orange glow (uses --accent-rgb, mirrors
       --wvc-winner-glow). */
    --mbr-winner-glow: 0 0 18px rgba(var(--accent-rgb), 0.55);
    /* Ideal ratio dashed reference line color at 33% (muted). */
    --mbr-ideal-line: rgba(0, 0, 0, 0.18);

    /* ════════════════════════════════════════════════════════════════════════
       FASE 1 — BUDDY HUB OWN PLAYER CARD (closed + detail view)
       Additive tokens (light theme). The OwnPlayerCard is restyled from a flat
       mint-green card to a neumorphic engraved card with orange accent
       (#E8630A / --accent-rgb). Closed state: engraved card surface, orange-
       glow avatar ring, orange-gradient level medal with lightning icon,
       engraved XP bar track with orange glowing fill, 3 engraved stat pills
       (dumbbell/flame/star). Open state: detail view with 6-axis spider chart
       in engraved container, PPL donut in engraved well, 5 key-stat cells, and
       a rule-based insight card (30-workout threshold). All wells mirror the
       --wq-ring-well / --op-hero-well / --op-chart-well lineage (5px deep inset
       + hairline rim for wells, 6px deeper for the outer card). All glows use
       --accent-rgb (232,99,10) — theme-agnostic. Light-tuned insets.
       ════════════════════════════════════════════════════════════════════════ */
    /* Outer card engraved well — 6px deeper, mirrors --op-hero-well light.
       Hosts the whole closed card surface as a sculpted recess. */
    --op-card-well:
      inset 6px 6px 11px rgba(0, 0, 0, 0.18),
      inset -6px -6px 11px rgba(255, 255, 255, 0.72),
      inset 0 0 0 1px rgba(0, 0, 0, 0.05);
    /* XP bar track engraved well — 5px inset, mirrors --wq-ring-well light.
       Hosts the orange XP fill so the bar reads as a sunk-in track. */
    --op-xp-well:
      inset 5px 5px 9px rgba(0, 0, 0, 0.16),
      inset -5px -5px 9px rgba(255, 255, 255, 0.7),
      inset 0 0 0 1px rgba(0, 0, 0, 0.04);
    /* Stat pill engraved well — 5px inset, mirrors --wq-ring-well light.
       Hosts the 3 stat values (volume / streak / level) as sculpted pills. */
    --op-stat-well:
      inset 5px 5px 9px rgba(0, 0, 0, 0.16),
      inset -5px -5px 9px rgba(255, 255, 255, 0.7),
      inset 0 0 0 1px rgba(0, 0, 0, 0.04);
    /* Detail view chart container engraved well — 5px inset, mirrors
       --op-chart-well light. Hosts the spider chart + PPL donut + key-stat
       cells in the open detail view. */
    --op-detail-well:
      inset 5px 5px 9px rgba(0, 0, 0, 0.16),
      inset -5px -5px 9px rgba(255, 255, 255, 0.7),
      inset 0 0 0 1px rgba(0, 0, 0, 0.04);
    /* Orange XP fill glow — soft warm halo on the XP bar fill (uses
       --accent-rgb). Light-tuned alpha so it doesn't blow out on FAF9F7. */
    --op-xp-glow: 0 0 6px rgba(var(--accent-rgb), 0.4), 0 0 14px
      rgba(var(--accent-rgb), 0.18);
    /* Avatar ring orange glow — soft warm halo on the avatar ring (uses
       --accent-rgb). Light-tuned alpha. */
    --op-avatar-glow: 0 0 6px rgba(var(--accent-rgb), 0.45), 0 0 14px
      rgba(var(--accent-rgb), 0.2);
    /* Level medal orange glow — soft warm halo on the orange-gradient medal
       (uses --accent-rgb). Light-tuned alpha. */
    --op-medal-glow: 0 0 6px rgba(var(--accent-rgb), 0.45), 0 0 14px
      rgba(var(--accent-rgb), 0.2);
    /* Spider chart fill orange glow — soft warm halo on the radar fill area
        (uses --accent-rgb). Light-tuned alpha so it doesn't blow out on FAF9F7. */
    --op-spider-glow: 0 0 6px rgba(var(--accent-rgb), 0.4), 0 0 14px
      rgba(var(--accent-rgb), 0.18);

    /* ════════════════════════════════════════════════════════════════════════
       YOUR STATS REFINEMENT — OwnPlayerCardDetail 7-point upgrade
       Additive tokens (light theme). Formalizes consistent neumorphic depth
       for the Your Stats page: stat cells / donut / radar share the SAME 5px
       deep inset + hairline rim language (mirror --op-detail-well). Toggle
       pills use raised neumorph (--op-pill-raised already exists). New tokens
       cover: hero metric typography, secondary stat typography, PPL donut 0%
       grey fill + legend colors, radar axis numeric value display, and the
       orange accent border for the coaching section connection.
       ════════════════════════════════════════════════════════════════════════ */
    /* Stat cell well — 5px deep inset, mirrors --op-detail-well light exactly.
       Same depth language for ALL stat cells (hero + secondary) + donut +
       radar so neumorphic depth reads consistently across the page. */
    --op-stat-cell-well:
      inset 5px 5px 9px rgba(0, 0, 0, 0.16),
      inset -5px -5px 9px rgba(255, 255, 255, 0.7),
      inset 0 0 0 1px rgba(0, 0, 0, 0.04);
    /* Radar container well — 5px deep inset, mirrors --op-stat-cell-well.
       Hosts the 6-axis spider chart so the radar reads as sunk into the
       page surface at the same depth as the stat cells and donut. */
    --op-radar-well:
      inset 5px 5px 9px rgba(0, 0, 0, 0.16),
      inset -5px -5px 9px rgba(255, 255, 255, 0.7),
      inset 0 0 0 1px rgba(0, 0, 0, 0.04);
    /* Hero metric typography — large prominent number for the hero stat
       (Total Workouts). Space Grotesk, ~3rem, bold, accent color. */
    --op-hero-metric-size: 3rem;
    --op-hero-metric-line: 1.05;
    --op-hero-metric-weight: 700;
    --op-hero-metric-tracking: -0.02em;
    /* Secondary stat typography — compact number for the 4 secondary stats.
       Space Grotesk, ~1.25rem, semibold, foreground. Visually quieter than
       the hero via smaller size + foreground (not accent) color. */
    --op-stat-secondary-size: 1.25rem;
    --op-stat-secondary-line: 1.2;
    --op-stat-secondary-weight: 600;
    /* Stat label typography — tiny uppercase muted label above each stat
       value (hero + secondary share this label style). */
    --op-stat-label-size: 0.625rem;
    --op-stat-label-tracking: 0.08em;
    --op-stat-label-weight: 600;
    /* PPL donut 0% grey fill — flat muted fill for empty/0% slices so they
       render as a visible quiet arc, NOT a thin sliver. Distinct from the
       3 colored arcs (push/pull/legs). */
    --ppl-empty-fill: rgba(0, 0, 0, 0.12);
    /* PPL legend colors — formalized rgb triplets for the 3 PPL categories.
       Push = orange (accent), Pull = blue (buddy/fitness blue), Legs = green
       (alert green). Used for arc fills + legend dots + percentage labels. */
    --ppl-push-rgb: 232, 99, 10;
    --ppl-pull-rgb: 64, 140, 220;
    --ppl-legs-rgb: 120, 200, 140;
    /* Radar axis numeric value — smaller muted number displayed next to each
       axis NAME (e.g. "Volume 84"). Reads as supporting context, not primary. */
    --op-radar-axis-value-size: 0.5625rem;
    --op-radar-axis-value-weight: 500;
    /* Coaching accent border — thin orange ring + soft outer glow that
       visually connects the coaching section as the page's insight
       conclusion. Uses --accent-rgb (theme-agnostic). */
    --op-coaching-ring: 0 0 0 1.5px rgba(var(--accent-rgb), 0.55);
    --op-coaching-glow: 0 0 12px rgba(var(--accent-rgb), 0.18), 0 0 24px
      rgba(var(--accent-rgb), 0.08);

    /* ════════════════════════════════════════════════════════════════════════
        FASE 2 — BUDDY HUB VS-COMPARISON SHEET
       Additive tokens (light theme). Formalizes the buddy-blue contrast color
       (RGB 0,146,189 — already used as PPL_RGB.pull) as a first-class CSS
       custom property so the VS spider chart, PPL donuts, and key-stats can
       reference it consistently in both dark and light themes. VS-sheet
       specific wells + glows mirror the Fase 1 OwnPlayerCard lineage
       (--op-card-well 6px deep for the sheet, --wq-ring-well 5px for stat
       rows). All glows use either --accent-rgb (orange, user side / winner)
       or --buddy-rgb (blue, buddy side). Light-tuned insets.
       ════════════════════════════════════════════════════════════════════════ */
    /* Buddy-blue contrast color — formalized from PPL_RGB.pull (0,146,189).
       Strongest contrast vs orange #E8630A. --buddy-rgb for rgba()/glow
       usage, --buddy-hex for solid fills. Theme-agnostic. */
    --buddy-rgb: 0, 146, 189;
    --buddy-hex: #0092bd;
    /* VS sheet background well — 6px deep engraved well, mirrors --op-card-well
       light. Hosts the whole VS sheet surface as a sculpted recess. */
    --vs-sheet-well:
      inset 6px 6px 11px rgba(0, 0, 0, 0.18),
      inset -6px -6px 11px rgba(255, 255, 255, 0.72),
      inset 0 0 0 1px rgba(0, 0, 0, 0.05);
    /* VS spider buddy glow — soft blue halo on the buddy radar polygon (uses
       --buddy-rgb). Light-tuned alpha so it doesn't blow out on FAF9F7. */
    --vs-spider-glow-buddy: 0 0 6px rgba(var(--buddy-rgb), 0.4), 0 0 14px
      rgba(var(--buddy-rgb), 0.18);
    /* VS stat winner glow — soft orange halo on the winning stat/category
       (uses --accent-rgb). Light-tuned alpha. */
    --vs-stat-winner-glow: 0 0 6px rgba(var(--accent-rgb), 0.45), 0 0 14px
      rgba(var(--accent-rgb), 0.2);
    /* VS stat row well — 5px engraved well, mirrors --wq-ring-well light.
       Hosts each key-stat row as a sculpted recess. */
    --vs-stat-well:
      inset 5px 5px 9px rgba(0, 0, 0, 0.16),
      inset -5px -5px 9px rgba(255, 255, 255, 0.7),
      inset 0 0 0 1px rgba(0, 0, 0, 0.04);

    --blueprint-exercises-well:
      inset 4px 4px 8px rgba(0, 0, 0, 0.18), inset -4px -4px 8px rgba(
        255,
        255,
        255,
        0.65
      ), inset 0 0 0 1px rgba(0, 0, 0, 0.04);
    /* Profile card neumorphic shadow + gradient end — theme-aware so the
       hardcoded rgba(18,18,18,0) gradient end and rgba(255,255,255,0.04)
       highlight adapt to light/dark. Light theme: deeper dark shadow + bright
       white highlight. Gradient end fades to transparent background. */
    --profile-card-shadow: 6px 6px 16px rgba(0, 0, 0, 0.45), -3px -3px 10px
      rgba(255, 255, 255, 0.04), 0 0 0 1px rgba(var(--accent-rgb), 0.12);
    --profile-hero-shadow: 8px 8px 20px rgba(0, 0, 0, 0.5), -4px -4px 12px
      rgba(255, 255, 255, 0.04), 0 0 0 1px rgba(var(--accent-rgb), 0.15);
    --profile-gradient-end: oklch(var(--background) / 0);
    --font-display: "Space Grotesk", sans-serif;
    --font-body: "General Sans", sans-serif;
    --font-mono: "JetBrains Mono", monospace;
  }

  .dark {
    /* Refined Dark Mode Backgrounds with Better Contrast: #1A1A1A / #202020 */
    --background: 0.21 0 0;
    --foreground: 0.98 0 0;
    --card: 0.25 0 0;
    --card-foreground: 0.98 0 0;
    --popover: 0.29 0 0;
    --popover-foreground: 0.98 0 0;
    --primary: 0.92 0 0;
    --primary-foreground: 0.21 0 0;
    --secondary: 0.29 0 0;
    --secondary-foreground: 0.98 0 0;
    --muted: 0.33 0 0;
    --muted-foreground: 0.72 0 0;
    --accent: 0.65 0.19 40;
    --accent-foreground: 0.98 0 0;
    /* FASE 1 accent variables — central orange accent (#E8630A) and its variants.
       Mirrored from :root so dark theme uses the same accent values. */
    --accent-hex: #e8630a;
    --accent-rgb: 232, 99, 10;
    --accent-dim: #4a2400;
    --destructive: 0.577 0.245 27.325;
    --destructive-foreground: 0.98 0 0;
    --border: 0.33 0 0;
    --input: 0.33 0 0;
    --ring: 0.65 0.19 40;
    --chart-1: 0.65 0.19 40;
    --chart-2: 0.6 0.15 220;
    --chart-3: 0.65 0.18 140;
    --chart-4: 0.55 0.2 280;
    --chart-5: 0.7 0.16 60;

    /* Starter plan accent colors — used only for thin strips and icon squares */
    --plan-orange: 0.65 0.2 45;
    --plan-blue: 0.6 0.15 240;
    --plan-green: 0.65 0.18 145;
    --plan-purple: 0.58 0.18 290;

    /* Plan accent color utilities */
    --plan-chest-push: 0.65 0.2 45; /* Orange */
    --plan-back-pull: 0.6 0.15 240; /* Blue */
    --plan-legs-core: 0.65 0.18 145; /* Green */
    --plan-shoulders-arms: 0.58 0.18 290; /* Purple */

    /* Subtle Neumorphic Dark Mode Shadows — zachte diepte zonder
       heldere witte highlights. Donkere schaduw blijft aanwezig voor
       diepte, witte highlight zeer subtiel (0.03-0.05) om verhevening
       te suggereren zonder te helder/verheven te lijken. Licht thema
       (boven) blijft ongewijzigd. */
    --neomorph-shadow-sm: 3px 3px 5px rgba(0, 0, 0, 0.48), -3px -3px 5px
      rgba(255, 255, 255, 0.04);
    --neomorph-shadow: 6px 6px 10px rgba(0, 0, 0, 0.58), -6px -6px 10px
      rgba(255, 255, 255, 0.04);
    --neomorph-shadow-lg: 8px 8px 13px rgba(0, 0, 0, 0.62), -8px -8px 13px
      rgba(255, 255, 255, 0.05);
    --neomorph-shadow-xl: 11px 11px 18px rgba(0, 0, 0, 0.65), -11px -11px 18px
      rgba(255, 255, 255, 0.05);
    --neomorph-inset: inset 4px 4px 7px rgba(0, 0, 0, 0.58), inset -4px -4px 7px
      rgba(255, 255, 255, 0.04);
    --neomorph-inset-sm: inset 3px 3px 5px rgba(0, 0, 0, 0.48), inset -3px -3px
      5px rgba(255, 255, 255, 0.03);
    --neomorph-hover: 7px 7px 12px rgba(0, 0, 0, 0.62), -7px -7px 12px
      rgba(255, 255, 255, 0.05);
    --neomorph-pressed: inset 3px 3px 5px rgba(0, 0, 0, 0.62), inset -3px -3px
      5px rgba(255, 255, 255, 0.03);

    /* Subtle Template Card Glass Effect — minder alpha, minder spreiding */
    --template-card-shadow:
      inset 2px 2px 4px rgba(255, 255, 255, 0.04),
      inset -2px -2px 4px rgba(0, 0, 0, 0.3),
      4px 4px 8px rgba(0, 0, 0, 0.45),
      -4px -4px 8px rgba(255, 255, 255, 0.03);
    --template-card-hover-shadow:
      inset 2px 2px 4px rgba(255, 255, 255, 0.05),
      inset -2px -2px 4px rgba(0, 0, 0, 0.35),
      5px 5px 9px rgba(0, 0, 0, 0.52),
      -5px -5px 9px rgba(255, 255, 255, 0.04);

    /* No accent ring in dark theme */
    --neomorph-accent-ring: 0 0 0 transparent;

    /* ════════════════════════════════════════════════════════════════════════
       WEEKLY QUEST — compacted card tokens (Phase: Compacted Weekly Quest)
       Engraved ring well: deeper inset than --neomorph-inset-sm so the
       ProgressRing SVG appears sunk into the card surface. Soft dark inner
       shadow + subtle outer highlight = sculpted recess. The progress arc
       carries a soft warm glow tuned for near-black (no blowout).
       State colors are applied via --wq-state-color on the card root; the
       arc glow utility reads that variable so all 3 states share one rule.
       ════════════════════════════════════════════════════════════════════════ */
    --blueprint-exercises-well:
      inset 5px 5px 9px rgba(0, 0, 0, 0.68), inset -5px -5px 9px rgba(
        255,
        255,
        255,
        0.05
      ), inset 0 0 0 1px rgba(255, 255, 255, 0.02);
    /* Profile card neumorphic shadow + gradient end — dark theme mirror of the
       :root tokens. Darker alpha for the dark shadow (deeper on near-black),
       subtle white highlight (0.05) so the card still reads as raised without
       blowing out. Gradient end fades to transparent background. */
    --profile-card-shadow: 6px 6px 16px rgba(0, 0, 0, 0.68), -3px -3px 10px
      rgba(255, 255, 255, 0.05), 0 0 0 1px rgba(var(--accent-rgb), 0.18);
    --profile-hero-shadow: 8px 8px 20px rgba(0, 0, 0, 0.74), -4px -4px 12px
      rgba(255, 255, 255, 0.05), 0 0 0 1px rgba(var(--accent-rgb), 0.2);
    --profile-gradient-end: oklch(var(--background) / 0);
    --wq-ring-well:
      inset 5px 5px 9px rgba(0, 0, 0, 0.68),
      inset -5px -5px 9px rgba(255, 255, 255, 0.05),
      inset 0 0 0 1px rgba(255, 255, 255, 0.02);
    --wq-arc-glow: 0 0 6px rgba(var(--accent-rgb), 0.55), 0 0 14px
      rgba(var(--accent-rgb), 0.28);
    --wq-state-color: var(--accent-hex);
    --wq-state-rgb: var(--accent-rgb);

    /* ════════════════════════════════════════════════════════════════════════
       FASE 1 STATS — Monthly Calendar + Goal ring + Week bars + Insight card
       Additive tokens (dark theme). Mirror the .wq-ring-well engraved pattern
       exactly (5px deep inset + hairline rim) so calendar tiles and the
       monthly goal ring share the same sculpted-recess language as the weekly
       quest ring. Orange glow uses --accent-rgb (232,99,10). Today's tile uses
       a ring (not a glow) so it stays distinct from trained days.
       ════════════════════════════════════════════════════════════════════════ */
    /* Engraved calendar day tile — square/rounded-lg variant of .wq-ring-well.
       Same 5px deep inset + 1px hairline rim = sculpted recess on near-black. */
    --mw-tile-well:
      inset 5px 5px 9px rgba(0, 0, 0, 0.68),
      inset -5px -5px 9px rgba(255, 255, 255, 0.05),
      inset 0 0 0 1px rgba(255, 255, 255, 0.02);
    /* Orange glow for trained days — soft warm halo using --accent-rgb. Tuned
       for near-black: matches .wq-arc-glow alpha so it doesn't blow out. */
    --mw-tile-trained-glow: 0 0 6px rgba(var(--accent-rgb), 0.55), 0 0 14px
      rgba(var(--accent-rgb), 0.28);
    /* Ring for today's tile — thin accent outline (not a glow) so today reads
       distinct from trained days. */
    --mw-tile-today-ring: 0 0 0 1.5px rgba(var(--accent-rgb), 0.7);
    /* Subtle inset for rest days (non-trained in-month days) — lighter than
       --mw-tile-well so rest days read as quieter empty engraved tiles. */
    --mw-tile-rest: inset 3px 3px 5px rgba(0, 0, 0, 0.48), inset -3px -3px 5px
      rgba(255, 255, 255, 0.03);
    /* Monthly goal ring well — mirrors .wq-ring-well exactly (100px, 5px
       inset, hairline rim). Hosts ProgressRing size=88 strokeWidth=8. */
    --mw-ring-well:
      inset 5px 5px 9px rgba(0, 0, 0, 0.68),
      inset -5px -5px 9px rgba(255, 255, 255, 0.05),
      inset 0 0 0 1px rgba(255, 255, 255, 0.02);
    /* Orange arc glow for the monthly goal ring — same halo as .wq-arc-glow. */
    --mw-ring-glow: 0 0 6px rgba(var(--accent-rgb), 0.55), 0 0 14px
      rgba(var(--accent-rgb), 0.28);

    /* ════════════════════════════════════════════════════════════════════════
       FASE 3 STATS — Fatigue vs Fitness + Push/Pull/Legs donut + Overload nav
       Additive tokens (dark theme). Mirror the :root FASE 3 tokens with dark-
       tuned insets. --ff-kpi-well and --ppl-ring-well copy the exact
       --wq-ring-well dark shadow values (5px deep inset + hairline rim) so the
       KPI cards and PPL donut share the same sculpted-recess language as the
       weekly quest / monthly goal rings on near-black.
       ════════════════════════════════════════════════════════════════════════ */
    /* Fitness (blauw) — rgb triplet for gradient/glow usage in SVG + CSS.
       Matches --chart-2 dark value (0.6 0.15 220). */
    --ff-fitness-rgb: 64, 140, 220;
    /* Vermoeidheid (rood) — distinct from --destructive; a fatigue red tuned
       for chart lines + KPI accent on near-black. */
    --ff-fatigue-rgb: 220, 80, 70;
    /* KPI inset well — engraved recess for the Fitness/Vermoeidheid value
       cards. Copies the exact --wq-ring-well dark shadow values (5px deep
       inset + hairline rim) so KPI cards share the same sculpted language. */
    --ff-kpi-well:
      inset 5px 5px 9px rgba(0, 0, 0, 0.68),
      inset -5px -5px 9px rgba(255, 255, 255, 0.05),
      inset 0 0 0 1px rgba(255, 255, 255, 0.02);
    /* TSB alert colors — groen (fresh) / oranje (moderate) / rood (overtrained).
       Dark-tuned OKLCH values for sufficient contrast on near-black. */
    --ff-alert-green: 0.65 0.18 145;
    --ff-alert-green-rgb: 120, 200, 140;
    --ff-alert-amber: 0.75 0.18 60;
    --ff-alert-amber-rgb: 220, 160, 60;
    --ff-alert-red: 0.6 0.22 25;
    --ff-alert-red-rgb: 210, 90, 80;
    /* PPL donut ring well — copies the exact --wq-ring-well dark shadow values
       (5px deep inset + hairline rim). 100px+ circular recess hosting the
       donut SVG. */
    --ppl-ring-well:
      inset 5px 5px 9px rgba(0, 0, 0, 0.68),
      inset -5px -5px 9px rgba(255, 255, 255, 0.05),
      inset 0 0 0 1px rgba(255, 255, 255, 0.02);
    /* PPL arc glow — soft drop-shadow halo on the donut arcs. Reads the
       per-arc color via --ppl-arc-rgb set on each arc element. */
    --ppl-arc-glow: 0 0 6px rgba(var(--ppl-arc-rgb, var(--accent-rgb)), 0.55), 0
      0 14px rgba(var(--ppl-arc-rgb, var(--accent-rgb)), 0.28);
    /* Overload nav-card sparkline preview area — inset well hosting the mini
       sparkline SVG so it reads as a sculpted recess, not a flat sticker. */
    --ol-nav-spark: inset 3px 3px 5px rgba(0, 0, 0, 0.48), inset -3px -3px 5px
      rgba(255, 255, 255, 0.03);

    /* ════════════════════════════════════════════════════════════════════════
       OVERLOAD PROGRESSION DETAIL PAGE — engraved KPI wells + pill selectors
       Additive tokens (dark theme). Mirror the :root Overload tokens with
       dark-tuned insets. --op-kpi-well and --op-chart-well copy the exact
       --wq-ring-well dark shadow values (5px deep inset + hairline rim) so
       the Overload page shares the same sculpted-recess language as the
       weekly quest / monthly goal / PPL donut wells on near-black. Orange
       accent (#E8630A / --accent-rgb) is theme-agnostic.
       ════════════════════════════════════════════════════════════════════════ */
    /* KPI inset well — engraved recess for the Overload page KPI cards.
       Copies the exact --wq-ring-well dark shadow values (5px deep inset +
       hairline rim). */
    --op-kpi-well:
      inset 5px 5px 9px rgba(0, 0, 0, 0.68),
      inset -5px -5px 9px rgba(255, 255, 255, 0.05),
      inset 0 0 0 1px rgba(255, 255, 255, 0.02);
    /* Chart container well — larger engraved recess hosting the Overload
       curve SVG. Same depth language as --op-kpi-well (copies exact
       --wq-ring-well dark shadow values). */
    --op-chart-well:
      inset 5px 5px 9px rgba(0, 0, 0, 0.68),
      inset -5px -5px 9px rgba(255, 255, 255, 0.05),
      inset 0 0 0 1px rgba(255, 255, 255, 0.02);
    /* Hero KPI well — deeper engraved recess for the hero KPI card (larger
       6px inset) so the trend value reads as the most prominent sculpted
       element on the page. Dark-tuned (deeper than --op-kpi-well). */
    --op-hero-well:
      inset 6px 6px 11px rgba(0, 0, 0, 0.74),
      inset -6px -6px 11px rgba(255, 255, 255, 0.05),
      inset 0 0 0 1px rgba(255, 255, 255, 0.025);
    /* Trend arrow accent glow — soft warm halo on the hero trend arrow
       (uses --accent-rgb). Tuned for near-black (matches .wq-arc-glow alpha). */
    --op-trend-glow: 0 0 6px rgba(var(--accent-rgb), 0.55), 0 0 14px
      rgba(var(--accent-rgb), 0.28);
    /* Pill raised shadow — subtle neumorphic raised surface for inactive
       time-filter + exercise selector pills. Dark-tuned (subtle white
       highlight). */
    --op-pill-raised: 3px 3px 6px rgba(0, 0, 0, 0.5), -3px -3px 6px
      rgba(255, 255, 255, 0.04);
    /* Pill active glow — soft warm halo on the active pill (uses --accent-rgb).
       Tuned for near-black (matches .wq-arc-glow alpha). */
    --op-pill-active-glow: 0 0 6px rgba(var(--accent-rgb), 0.55), 0 0 14px
      rgba(var(--accent-rgb), 0.28);
    /* Empty-state container well — subtle inset for the compact empty-state
       variant. Dark-tuned (lighter than --op-kpi-well). */
    --op-empty-well: inset 3px 3px 6px rgba(0, 0, 0, 0.5), inset -3px -3px 6px
      rgba(255, 255, 255, 0.03);
    /* PR star glow — soft warm halo on PR star markers in the chart (uses
       --accent-rgb). Tuned for near-black. */
    --op-star-glow: 0 0 4px rgba(var(--accent-rgb), 0.6), 0 0 10px
      rgba(var(--accent-rgb), 0.32);
    /* Fase 1 — Buddy Tab Challenges. Outer card engraved well (6px deeper,
       mirrors --op-hero-well dark values). */
    --wvc-card-well:
      inset 6px 6px 11px rgba(0, 0, 0, 0.7), inset -6px -6px 11px
      rgba(255, 255, 255, 0.05), inset 0 0 0 1px rgba(255, 255, 255, 0.02);
    /* Split-view sub-kaartje engraved well (5px, mirrors --wq-ring-well dark). */
    --wvc-sub-well:
      inset 5px 5px 9px rgba(0, 0, 0, 0.68), inset -5px -5px 9px
      rgba(255, 255, 255, 0.05), inset 0 0 0 1px rgba(255, 255, 255, 0.02);
    /* Comparison bar track engraved well (5px, mirrors --wq-ring-well dark). */
    --wvc-bar-well:
      inset 5px 5px 9px rgba(0, 0, 0, 0.68), inset -5px -5px 9px
      rgba(255, 255, 255, 0.05), inset 0 0 0 1px rgba(255, 255, 255, 0.02);
    /* LIVE pill orange glow (uses --accent-rgb). */
    --wvc-live-glow: 0 0 12px rgba(var(--accent-rgb), 0.45);
    /* Winning sub-kaartje stronger orange glow (uses --accent-rgb). */
    --wvc-winner-glow: 0 0 18px rgba(var(--accent-rgb), 0.55);
    /* Leaderboard segmented control track (5px, mirrors --wq-ring-well dark). */
    --lb-seg-well:
      inset 5px 5px 9px rgba(0, 0, 0, 0.68), inset -5px -5px 9px
      rgba(255, 255, 255, 0.05), inset 0 0 0 1px rgba(255, 255, 255, 0.02);
    /* Leaderboard row engraved well (5px, mirrors --wq-ring-well dark). */
    --lb-row-well:
      inset 5px 5px 9px rgba(0, 0, 0, 0.68), inset -5px -5px 9px
      rgba(255, 255, 255, 0.05), inset 0 0 0 1px rgba(255, 255, 255, 0.02);
    /* #1 leaderboard row stronger orange glow (uses --accent-rgb). */
    --lb-rank1-glow: 0 0 20px rgba(var(--accent-rgb), 0.6);
    /* Group average comparison card engraved well (5px, mirrors --wq-ring-well
       dark). */
    --lb-avg-well:
      inset 5px 5px 9px rgba(0, 0, 0, 0.68), inset -5px -5px 9px
      rgba(255, 255, 255, 0.05), inset 0 0 0 1px rgba(255, 255, 255, 0.02);
    /* PR Ladder outer card engraved well (6px deeper, mirrors --wvc-card-well
       dark). */
    --pr-card-well:
      inset 6px 6px 11px rgba(0, 0, 0, 0.68), inset -6px -6px 11px
      rgba(255, 255, 255, 0.05), inset 0 0 0 1px rgba(255, 255, 255, 0.02);
    /* PR Ladder segmented control track (5px, mirrors --lb-seg-well dark). */
    --pr-seg-well:
      inset 5px 5px 9px rgba(0, 0, 0, 0.68), inset -5px -5px 9px
      rgba(255, 255, 255, 0.05), inset 0 0 0 1px rgba(255, 255, 255, 0.02);
    /* PR Ladder row engraved well (5px, mirrors --lb-row-well dark). */
    --pr-row-well:
      inset 5px 5px 9px rgba(0, 0, 0, 0.68), inset -5px -5px 9px
      rgba(255, 255, 255, 0.05), inset 0 0 0 1px rgba(255, 255, 255, 0.02);
    /* #1 PR Ladder row stronger orange glow (uses --accent-rgb). */
    --pr-rank1-glow: 0 0 20px rgba(var(--accent-rgb), 0.6);
    /* #2 PR Ladder row softer orange glow (uses --accent-rgb). */
    --pr-rank2-glow: 0 0 14px rgba(var(--accent-rgb), 0.4);
    /* #3 PR Ladder row subtle orange glow (uses --accent-rgb). */
    --pr-rank3-glow: 0 0 10px rgba(var(--accent-rgb), 0.3);
    /* PR Ladder trophy warm orange glow (uses --accent-rgb). */
    --pr-trophy-glow: 0 0 16px rgba(var(--accent-rgb), 0.55);
    /* Fase 3 — Your Streak outer card engraved well (6px deeper, mirrors
       --wvc-card-well / --pr-card-well dark). */
    --streak-card-well:
      inset 6px 6px 11px rgba(0, 0, 0, 0.7), inset -6px -6px 11px
      rgba(255, 255, 255, 0.05), inset 0 0 0 1px rgba(255, 255, 255, 0.02);
    /* Streak day-circle engraved well (5px, mirrors --wq-ring-well dark). */
    --streak-ring-well:
      inset 5px 5px 9px rgba(0, 0, 0, 0.68), inset -5px -5px 9px
      rgba(255, 255, 255, 0.05), inset 0 0 0 1px rgba(255, 255, 255, 0.02);
    /* Streak counter + trained day orange glow (uses --accent-rgb, mirrors
       --wvc-live-glow). */
    --streak-glow: 0 0 12px rgba(var(--accent-rgb), 0.45);
    /* Fase 3 — Muscle Balance Race outer card engraved well (6px deeper,
       mirrors --wvc-card-well / --pr-card-well dark). */
    --mbr-card-well:
      inset 6px 6px 11px rgba(0, 0, 0, 0.7), inset -6px -6px 11px
      rgba(255, 255, 255, 0.05), inset 0 0 0 1px rgba(255, 255, 255, 0.02);
    /* Muscle Balance progress bar track engraved well (5px, mirrors
       --wvc-bar-well dark). */
    --mbr-bar-well:
      inset 5px 5px 9px rgba(0, 0, 0, 0.68), inset -5px -5px 9px
      rgba(255, 255, 255, 0.05), inset 0 0 0 1px rgba(255, 255, 255, 0.02);
    /* Muscle Balance Week/All-time segmented control track (5px, mirrors
       --lb-seg-well / --pr-seg-well dark). */
    --mbr-seg-well:
      inset 5px 5px 9px rgba(0, 0, 0, 0.68), inset -5px -5px 9px
      rgba(255, 255, 255, 0.05), inset 0 0 0 1px rgba(255, 255, 255, 0.02);
    /* Muscle Balance YOU/BUDDY sub-section engraved well (5px, mirrors
       --wvc-sub-well dark). */
    --mbr-sub-well:
      inset 5px 5px 9px rgba(0, 0, 0, 0.68), inset -5px -5px 9px
      rgba(255, 255, 255, 0.05), inset 0 0 0 1px rgba(255, 255, 255, 0.02);
    /* Winning PPL category stronger orange glow (uses --accent-rgb, mirrors
       --wvc-winner-glow). */
    --mbr-winner-glow: 0 0 18px rgba(var(--accent-rgb), 0.55);
    /* Ideal ratio dashed reference line color at 33% (muted, dark-tuned). */
    --mbr-ideal-line: rgba(255, 255, 255, 0.18);

    /* ════════════════════════════════════════════════════════════════════════
       FASE 1 — BUDDY HUB OWN PLAYER CARD (closed + detail view)
       Additive tokens (dark theme). Mirror the :root FASE 1 OwnPlayerCard
       tokens with dark-tuned insets. --op-card-well copies the exact
       --op-hero-well dark shadow values (6px deep inset + hairline rim) so
       the closed card shares the same sculpted-recess language as the hero
       KPI / WVC / PR / streak outer cards. --op-xp-well / --op-stat-well /
       --op-detail-well copy the exact --wq-ring-well dark shadow values (5px
       deep inset + hairline rim). All glows use --accent-rgb (232,99,10)
       tuned for near-black (matches .wq-arc-glow / --op-trend-glow alpha).
       ════════════════════════════════════════════════════════════════════════ */
    /* Outer card engraved well — 6px deeper, mirrors --op-hero-well dark. */
    --op-card-well:
      inset 6px 6px 11px rgba(0, 0, 0, 0.74),
      inset -6px -6px 11px rgba(255, 255, 255, 0.05),
      inset 0 0 0 1px rgba(255, 255, 255, 0.025);
    /* XP bar track engraved well — 5px inset, mirrors --wq-ring-well dark. */
    --op-xp-well:
      inset 5px 5px 9px rgba(0, 0, 0, 0.68),
      inset -5px -5px 9px rgba(255, 255, 255, 0.05),
      inset 0 0 0 1px rgba(255, 255, 255, 0.02);
    /* Stat pill engraved well — 5px inset, mirrors --wq-ring-well dark. */
    --op-stat-well:
      inset 5px 5px 9px rgba(0, 0, 0, 0.68),
      inset -5px -5px 9px rgba(255, 255, 255, 0.05),
      inset 0 0 0 1px rgba(255, 255, 255, 0.02);
    /* Detail view chart container engraved well — 5px inset, mirrors
       --op-chart-well dark. Hosts spider chart + PPL donut + key-stat cells. */
    --op-detail-well:
      inset 5px 5px 9px rgba(0, 0, 0, 0.68),
      inset -5px -5px 9px rgba(255, 255, 255, 0.05),
      inset 0 0 0 1px rgba(255, 255, 255, 0.02);
    /* Orange XP fill glow — soft warm halo on the XP bar fill (uses
       --accent-rgb). Tuned for near-black (matches .wq-arc-glow alpha). */
    --op-xp-glow: 0 0 6px rgba(var(--accent-rgb), 0.55), 0 0 14px
      rgba(var(--accent-rgb), 0.28);
    /* Avatar ring orange glow — soft warm halo on the avatar ring (uses
       --accent-rgb). Tuned for near-black. */
    --op-avatar-glow: 0 0 6px rgba(var(--accent-rgb), 0.55), 0 0 14px
      rgba(var(--accent-rgb), 0.28);
    /* Level medal orange glow — soft warm halo on the orange-gradient medal
       (uses --accent-rgb). Tuned for near-black. */
    --op-medal-glow: 0 0 6px rgba(var(--accent-rgb), 0.55), 0 0 14px
      rgba(var(--accent-rgb), 0.28);
    /* Spider chart fill orange glow — soft warm halo on the radar fill area
        (uses --accent-rgb). Tuned for near-black (matches .wq-arc-glow alpha). */
    --op-spider-glow: 0 0 6px rgba(var(--accent-rgb), 0.55), 0 0 14px
      rgba(var(--accent-rgb), 0.28);

    /* ════════════════════════════════════════════════════════════════════════
       YOUR STATS REFINEMENT — OwnPlayerCardDetail 7-point upgrade
       Additive tokens (dark theme). Mirror the :root tokens with dark-tuned
       insets (5px deep inset + hairline rim, copies exact --wq-ring-well /
       --op-detail-well dark shadow values) so stat cells / donut / radar
       share the SAME sculpted-recess depth language on near-black. Toggle
       pills reuse existing --op-pill-raised / --op-pill-active-glow. All
       glows use --accent-rgb tuned for near-black.
       ════════════════════════════════════════════════════════════════════════ */
    /* Stat cell well — 5px deep inset, mirrors --op-detail-well dark exactly.
       Same depth for ALL stat cells (hero + secondary) + donut + radar. */
    --op-stat-cell-well:
      inset 5px 5px 9px rgba(0, 0, 0, 0.68),
      inset -5px -5px 9px rgba(255, 255, 255, 0.05),
      inset 0 0 0 1px rgba(255, 255, 255, 0.02);
    /* Radar container well — 5px deep inset, mirrors --op-stat-cell-well. */
    --op-radar-well:
      inset 5px 5px 9px rgba(0, 0, 0, 0.68),
      inset -5px -5px 9px rgba(255, 255, 255, 0.05),
      inset 0 0 0 1px rgba(255, 255, 255, 0.02);
    /* Hero metric typography — large prominent number for the hero stat. */
    --op-hero-metric-size: 3rem;
    --op-hero-metric-line: 1.05;
    --op-hero-metric-weight: 700;
    --op-hero-metric-tracking: -0.02em;
    /* Secondary stat typography — compact number for the 4 secondary stats. */
    --op-stat-secondary-size: 1.25rem;
    --op-stat-secondary-line: 1.2;
    --op-stat-secondary-weight: 600;
    /* Stat label typography — tiny uppercase muted label. */
    --op-stat-label-size: 0.625rem;
    --op-stat-label-tracking: 0.08em;
    --op-stat-label-weight: 600;
    /* PPL donut 0% grey fill — flat muted fill for empty slices (dark-tuned:
       lighter than light theme so it reads on near-black). */
    --ppl-empty-fill: rgba(255, 255, 255, 0.08);
    /* PPL legend colors — formalized rgb triplets (theme-agnostic). */
    --ppl-push-rgb: 232, 99, 10;
    --ppl-pull-rgb: 64, 140, 220;
    --ppl-legs-rgb: 120, 200, 140;
    /* Radar axis numeric value — smaller muted number next to axis name. */
    --op-radar-axis-value-size: 0.5625rem;
    --op-radar-axis-value-weight: 500;
    /* Coaching accent border — orange ring + soft glow (dark-tuned alpha). */
    --op-coaching-ring: 0 0 0 1.5px rgba(var(--accent-rgb), 0.6);
    --op-coaching-glow: 0 0 14px rgba(var(--accent-rgb), 0.22), 0 0 28px
      rgba(var(--accent-rgb), 0.1);

    /* ════════════════════════════════════════════════════════════════════════
        FASE 2 — BUDDY HUB VS-COMPARISON SHEET
       Additive tokens (dark theme). Mirror the :root Fase 2 tokens with
       dark-tuned insets. --vs-sheet-well copies the exact --op-card-well dark
       shadow values (6px deep inset + hairline rim) so the VS sheet shares
       the same sculpted-recess language as the OwnPlayerCard outer card.
       --vs-stat-well copies the exact --wq-ring-well dark shadow values (5px
       deep inset + hairline rim). Glows use --accent-rgb (orange, user side
       / winner) and --buddy-rgb (blue, buddy side) tuned for near-black
       (matches .wq-arc-glow / --op-spider-glow alpha).
       ════════════════════════════════════════════════════════════════════════ */
    /* Buddy-blue contrast color — formalized from PPL_RGB.pull (0,146,189).
       Mirrored from :root; theme-agnostic. */
    --buddy-rgb: 0, 146, 189;
    --buddy-hex: #0092bd;
    /* VS sheet background well — 6px deep engraved well, mirrors --op-card-well
       dark. Hosts the whole VS sheet surface as a sculpted recess. */
    --vs-sheet-well:
      inset 6px 6px 11px rgba(0, 0, 0, 0.74),
      inset -6px -6px 11px rgba(255, 255, 255, 0.05),
      inset 0 0 0 1px rgba(255, 255, 255, 0.025);
    /* VS spider buddy glow — soft blue halo on the buddy radar polygon (uses
       --buddy-rgb). Tuned for near-black (matches --op-spider-glow alpha). */
    --vs-spider-glow-buddy: 0 0 6px rgba(var(--buddy-rgb), 0.55), 0 0 14px
      rgba(var(--buddy-rgb), 0.28);
    /* VS stat winner glow — soft orange halo on the winning stat/category
       (uses --accent-rgb). Tuned for near-black. */
    --vs-stat-winner-glow: 0 0 6px rgba(var(--accent-rgb), 0.55), 0 0 14px
      rgba(var(--accent-rgb), 0.28);
    /* VS stat row well — 5px engraved well, mirrors --wq-ring-well dark.
       Hosts each key-stat row as a sculpted recess. */
    --vs-stat-well:
      inset 5px 5px 9px rgba(0, 0, 0, 0.68),
      inset -5px -5px 9px rgba(255, 255, 255, 0.05),
      inset 0 0 0 1px rgba(255, 255, 255, 0.02);
  }

  * {
  border-color: oklch(var(--border));
}

  html,
  body,
  #root {
    height: 100%;
    height: 100dvh;
  }

  body {
  background-color: oklch(var(--background));
  color: oklch(var(--foreground));
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto",
      "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans",
      "Helvetica Neue", sans-serif;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    -webkit-tap-highlight-color: transparent;
    /* PWA safe area support — bottom inset. Full-screen fixed pages (e.g.
       HomePage) cover this padding with their own bg-background, so it is
       invisible there; for non-full-screen pages it serves as the body
       fallback so content clears the home indicator. */
    padding-bottom: env(safe-area-inset-bottom);
}

  /* Enhanced Typography Hierarchy with Better Contrast */
  h1 {
  font-size: 1.5rem;
  line-height: 2rem;
  font-weight: 700;
  letter-spacing: -0.025em;
    line-height: 1.2;
    color: oklch(var(--foreground));
}

  h2 {
  font-size: 1.25rem;
  line-height: 1.75rem;
  font-weight: 600;
  letter-spacing: -0.025em;
    line-height: 1.3;
    color: oklch(var(--foreground));
}

  h3 {
  font-size: 1.125rem;
  line-height: 1.75rem;
  font-weight: 600;
    line-height: 1.4;
    color: oklch(var(--foreground));
}

  h4 {
  font-size: 1rem;
  line-height: 1.5rem;
  font-weight: 600;
    line-height: 1.4;
    color: oklch(var(--foreground));
}

  /* Improved Text Contrast Hierarchy */

  /* Prevent zoom on input focus for mobile */
  input[type="text"],
  input[type="number"],
  input[type="email"],
  input[type="tel"],
  input[type="password"],
  textarea,
  select {
    font-size: 16px;
  }

  /* PWA standalone mode adjustments */
  @media (display-mode: standalone) {
    body {
      -moz-user-select: none;
           user-select: none;
      -webkit-user-select: none;
    }
  }

  /* Mobile scroll optimizations — apply only to scrollable containers, not globally */
  .scrollable {
    -webkit-overflow-scrolling: touch;
    overflow-y: auto;
  }

  /* Hide scrollbar while keeping scroll functional (touch/swipe only) */
.container {
  width: 100%;
}
@media (min-width: 640px) {

  .container {
    max-width: 640px;
  }
}
@media (min-width: 768px) {

  .container {
    max-width: 768px;
  }
}
@media (min-width: 1024px) {

  .container {
    max-width: 1024px;
  }
}
@media (min-width: 1280px) {

  .container {
    max-width: 1280px;
  }
}
@media (min-width: 1536px) {

  .container {
    max-width: 1536px;
  }
}
/* Remove all animations from AlertDialog components for instant open/close */
[role="alertdialog"] {
    animation: none !important;
    transition: none !important;
  }
[role="alertdialog"] * {
    animation: none !important;
    transition: none !important;
  }
/* Target Radix UI AlertDialog overlay specifically */
[data-radix-alert-dialog-overlay] {
    animation: none !important;
    transition: none !important;
  }
/* Target Radix UI AlertDialog content specifically */
[data-radix-alert-dialog-content] {
    animation: none !important;
    transition: none !important;
  }
/* Override any data-state animations for AlertDialog */
[role="alertdialog"][data-state="open"],
  [role="alertdialog"][data-state="closed"] {
    animation: none !important;
    transition: none !important;
  }
[data-radix-alert-dialog-overlay][data-state="open"],
  [data-radix-alert-dialog-overlay][data-state="closed"] {
    animation: none !important;
    transition: none !important;
  }
[data-radix-alert-dialog-content][data-state="open"],
  [data-radix-alert-dialog-content][data-state="closed"] {
    animation: none !important;
    transition: none !important;
  }
/* Analytics chart placeholder styles */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border-width: 0;
}
.pointer-events-none {
  pointer-events: none;
}
.pointer-events-auto {
  pointer-events: auto;
}
.visible {
  visibility: visible;
}
.invisible {
  visibility: hidden;
}
.collapse {
  visibility: collapse;
}
.static {
  position: static;
}
.fixed {
  position: fixed;
}
.absolute {
  position: absolute;
}
.relative {
  position: relative;
}
.sticky {
  position: sticky;
}
.inset-0 {
  inset: 0px;
}
.inset-x-0 {
  left: 0px;
  right: 0px;
}
.inset-y-0 {
  top: 0px;
  bottom: 0px;
}
.-bottom-0\.5 {
  bottom: -0.125rem;
}
.-bottom-1\.5 {
  bottom: -0.375rem;
}
.-right-0\.5 {
  right: -0.125rem;
}
.-right-1 {
  right: -0.25rem;
}
.-right-1\.5 {
  right: -0.375rem;
}
.-right-10 {
  right: -2.5rem;
}
.-right-12 {
  right: -3rem;
}
.-right-4 {
  right: -1rem;
}
.-top-1 {
  top: -0.25rem;
}
.-top-10 {
  top: -2.5rem;
}
.-top-12 {
  top: -3rem;
}
.-top-4 {
  top: -1rem;
}
.bottom-0 {
  bottom: 0px;
}
.bottom-2 {
  bottom: 0.5rem;
}
.bottom-20 {
  bottom: 5rem;
}
.bottom-4 {
  bottom: 1rem;
}
.left-0 {
  left: 0px;
}
.left-1\/2 {
  left: 50%;
}
.left-2 {
  left: 0.5rem;
}
.left-3 {
  left: 0.75rem;
}
.left-5 {
  left: 1.25rem;
}
.left-\[50\%\] {
  left: 50%;
}
.right-0 {
  right: 0px;
}
.right-1\.5 {
  right: 0.375rem;
}
.right-2 {
  right: 0.5rem;
}
.right-3 {
  right: 0.75rem;
}
.right-4 {
  right: 1rem;
}
.top-0 {
  top: 0px;
}
.top-1 {
  top: 0.25rem;
}
.top-1\.5 {
  top: 0.375rem;
}
.top-1\/2 {
  top: 50%;
}
.top-12 {
  top: 3rem;
}
.top-2 {
  top: 0.5rem;
}
.top-24 {
  top: 6rem;
}
.top-3 {
  top: 0.75rem;
}
.top-4 {
  top: 1rem;
}
.top-5 {
  top: 1.25rem;
}
.top-\[50\%\] {
  top: 50%;
}
.top-\[calc\(env\(safe-area-inset-top\)\+0\.75rem\)\] {
  top: calc(env(safe-area-inset-top) + 0.75rem);
}
.top-\[calc\(env\(safe-area-inset-top\)\+1rem\)\] {
  top: calc(env(safe-area-inset-top) + 1rem);
}
.top-full {
  top: 100%;
}
.z-10 {
  z-index: 10;
}
.z-20 {
  z-index: 20;
}
.z-30 {
  z-index: 30;
}
.z-40 {
  z-index: 40;
}
.z-50 {
  z-index: 50;
}
.z-\[110\] {
  z-index: 110;
}
.z-\[120\] {
  z-index: 120;
}
.z-\[130\] {
  z-index: 130;
}
.z-\[140\] {
  z-index: 140;
}
.z-\[200\] {
  z-index: 200;
}
.z-\[60\] {
  z-index: 60;
}
.z-\[9999\] {
  z-index: 9999;
}
.col-span-2 {
  grid-column: span 2 / span 2;
}
.col-span-full {
  grid-column: 1 / -1;
}
.col-start-2 {
  grid-column-start: 2;
}
.row-span-2 {
  grid-row: span 2 / span 2;
}
.row-start-1 {
  grid-row-start: 1;
}
.m-0 {
  margin: 0px;
}
.m-auto {
  margin: auto;
}
.-mx-1 {
  margin-left: -0.25rem;
  margin-right: -0.25rem;
}
.-mx-3 {
  margin-left: -0.75rem;
  margin-right: -0.75rem;
}
.-my-1 {
  margin-top: -0.25rem;
  margin-bottom: -0.25rem;
}
.mx-4 {
  margin-left: 1rem;
  margin-right: 1rem;
}
.mx-6 {
  margin-left: 1.5rem;
  margin-right: 1.5rem;
}
.mx-auto {
  margin-left: auto;
  margin-right: auto;
}
.my-1 {
  margin-top: 0.25rem;
  margin-bottom: 0.25rem;
}
.-ml-0\.5 {
  margin-left: -0.125rem;
}
.-mr-1 {
  margin-right: -0.25rem;
}
.-mt-1 {
  margin-top: -0.25rem;
}
.-mt-2 {
  margin-top: -0.5rem;
}
.mb-0\.5 {
  margin-bottom: 0.125rem;
}
.mb-1 {
  margin-bottom: 0.25rem;
}
.mb-1\.5 {
  margin-bottom: 0.375rem;
}
.mb-10 {
  margin-bottom: 2.5rem;
}
.mb-2 {
  margin-bottom: 0.5rem;
}
.mb-3 {
  margin-bottom: 0.75rem;
}
.mb-4 {
  margin-bottom: 1rem;
}
.mb-5 {
  margin-bottom: 1.25rem;
}
.mb-6 {
  margin-bottom: 1.5rem;
}
.mb-7 {
  margin-bottom: 1.75rem;
}
.mb-8 {
  margin-bottom: 2rem;
}
.ml-0\.5 {
  margin-left: 0.125rem;
}
.ml-1 {
  margin-left: 0.25rem;
}
.ml-2 {
  margin-left: 0.5rem;
}
.ml-6 {
  margin-left: 1.5rem;
}
.ml-auto {
  margin-left: auto;
}
.mr-1 {
  margin-right: 0.25rem;
}
.mr-1\.5 {
  margin-right: 0.375rem;
}
.mr-2 {
  margin-right: 0.5rem;
}
.mt-0 {
  margin-top: 0px;
}
.mt-0\.5 {
  margin-top: 0.125rem;
}
.mt-1 {
  margin-top: 0.25rem;
}
.mt-1\.5 {
  margin-top: 0.375rem;
}
.mt-12 {
  margin-top: 3rem;
}
.mt-16 {
  margin-top: 4rem;
}
.mt-2 {
  margin-top: 0.5rem;
}
.mt-3 {
  margin-top: 0.75rem;
}
.mt-4 {
  margin-top: 1rem;
}
.mt-5 {
  margin-top: 1.25rem;
}
.mt-6 {
  margin-top: 1.5rem;
}
.mt-8 {
  margin-top: 2rem;
}
.mt-auto {
  margin-top: auto;
}
.mt-px {
  margin-top: 1px;
}
.line-clamp-1 {
  overflow: hidden;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 1;
}
.line-clamp-2 {
  overflow: hidden;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
}
.block {
  display: block;
}
.inline-block {
  display: inline-block;
}
.inline {
  display: inline;
}
.flex {
  display: flex;
}
.inline-flex {
  display: inline-flex;
}
.table {
  display: table;
}
.grid {
  display: grid;
}
.hidden {
  display: none;
}
.aspect-\[3\/4\] {
  aspect-ratio: 3/4;
}
.aspect-square {
  aspect-ratio: 1 / 1;
}
.size-2 {
  width: 0.5rem;
  height: 0.5rem;
}
.size-2\.5 {
  width: 0.625rem;
  height: 0.625rem;
}
.size-3\.5 {
  width: 0.875rem;
  height: 0.875rem;
}
.size-4 {
  width: 1rem;
  height: 1rem;
}
.size-5 {
  width: 1.25rem;
  height: 1.25rem;
}
.size-9 {
  width: 2.25rem;
  height: 2.25rem;
}
.size-full {
  width: 100%;
  height: 100%;
}
.\!h-7 {
  height: 1.75rem !important;
}
.\!h-\[34px\] {
  height: 34px !important;
}
.h-1 {
  height: 0.25rem;
}
.h-1\.5 {
  height: 0.375rem;
}
.h-10 {
  height: 2.5rem;
}
.h-11 {
  height: 2.75rem;
}
.h-12 {
  height: 3rem;
}
.h-14 {
  height: 3.5rem;
}
.h-16 {
  height: 4rem;
}
.h-2 {
  height: 0.5rem;
}
.h-2\.5 {
  height: 0.625rem;
}
.h-20 {
  height: 5rem;
}
.h-24 {
  height: 6rem;
}
.h-28 {
  height: 7rem;
}
.h-3 {
  height: 0.75rem;
}
.h-3\.5 {
  height: 0.875rem;
}
.h-4 {
  height: 1rem;
}
.h-40 {
  height: 10rem;
}
.h-5 {
  height: 1.25rem;
}
.h-6 {
  height: 1.5rem;
}
.h-7 {
  height: 1.75rem;
}
.h-8 {
  height: 2rem;
}
.h-9 {
  height: 2.25rem;
}
.h-\[1\.15rem\] {
  height: 1.15rem;
}
.h-\[100px\] {
  height: 100px;
}
.h-\[14px\] {
  height: 14px;
}
.h-\[180px\] {
  height: 180px;
}
.h-\[85vh\] {
  height: 85vh;
}
.h-\[calc\(100vh-120px\)\] {
  height: calc(100vh - 120px);
}
.h-\[calc\(100vh-180px\)\] {
  height: calc(100vh - 180px);
}
.h-\[var\(--radix-select-trigger-height\)\] {
  height: var(--radix-select-trigger-height);
}
.h-auto {
  height: auto;
}
.h-full {
  height: 100%;
}
.h-px {
  height: 1px;
}
.h-screen {
  height: 100vh;
}
.max-h-56 {
  max-height: 14rem;
}
.max-h-64 {
  max-height: 16rem;
}
.max-h-72 {
  max-height: 18rem;
}
.max-h-\[50vh\] {
  max-height: 50vh;
}
.max-h-\[800px\] {
  max-height: 800px;
}
.max-h-\[85vh\] {
  max-height: 85vh;
}
.max-h-\[90vh\] {
  max-height: 90vh;
}
.max-h-\[92vh\] {
  max-height: 92vh;
}
.min-h-0 {
  min-height: 0px;
}
.min-h-16 {
  min-height: 4rem;
}
.min-h-4 {
  min-height: 1rem;
}
.min-h-\[120px\] {
  min-height: 120px;
}
.min-h-\[14px\] {
  min-height: 14px;
}
.min-h-\[2\.5rem\] {
  min-height: 2.5rem;
}
.min-h-\[20px\] {
  min-height: 20px;
}
.min-h-\[44px\] {
  min-height: 44px;
}
.min-h-\[68px\] {
  min-height: 68px;
}
.min-h-\[80px\] {
  min-height: 80px;
}
.min-h-screen {
  min-height: 100vh;
}
.\!w-7 {
  width: 1.75rem !important;
}
.w-1 {
  width: 0.25rem;
}
.w-1\.5 {
  width: 0.375rem;
}
.w-1\/2 {
  width: 50%;
}
.w-10 {
  width: 2.5rem;
}
.w-11 {
  width: 2.75rem;
}
.w-12 {
  width: 3rem;
}
.w-14 {
  width: 3.5rem;
}
.w-16 {
  width: 4rem;
}
.w-2 {
  width: 0.5rem;
}
.w-2\.5 {
  width: 0.625rem;
}
.w-20 {
  width: 5rem;
}
.w-24 {
  width: 6rem;
}
.w-28 {
  width: 7rem;
}
.w-3 {
  width: 0.75rem;
}
.w-3\.5 {
  width: 0.875rem;
}
.w-3\/4 {
  width: 75%;
}
.w-32 {
  width: 8rem;
}
.w-4 {
  width: 1rem;
}
.w-40 {
  width: 10rem;
}
.w-44 {
  width: 11rem;
}
.w-48 {
  width: 12rem;
}
.w-5 {
  width: 1.25rem;
}
.w-6 {
  width: 1.5rem;
}
.w-7 {
  width: 1.75rem;
}
.w-72 {
  width: 18rem;
}
.w-8 {
  width: 2rem;
}
.w-9 {
  width: 2.25rem;
}
.w-\[100px\] {
  width: 100px;
}
.w-\[14px\] {
  width: 14px;
}
.w-\[180px\] {
  width: 180px;
}
.w-\[90\%\] {
  width: 90%;
}
.w-\[98\%\] {
  width: 98%;
}
.w-\[calc\(100vw-2rem\)\] {
  width: calc(100vw - 2rem);
}
.w-fit {
  width: -moz-fit-content;
  width: fit-content;
}
.w-full {
  width: 100%;
}
.w-px {
  width: 1px;
}
.min-w-0 {
  min-width: 0px;
}
.min-w-10 {
  min-width: 2.5rem;
}
.min-w-8 {
  min-width: 2rem;
}
.min-w-9 {
  min-width: 2.25rem;
}
.min-w-\[140px\] {
  min-width: 140px;
}
.min-w-\[44px\] {
  min-width: 44px;
}
.min-w-\[8rem\] {
  min-width: 8rem;
}
.min-w-\[var\(--radix-select-trigger-width\)\] {
  min-width: var(--radix-select-trigger-width);
}
.max-w-2xl {
  max-width: 42rem;
}
.max-w-5xl {
  max-width: 64rem;
}
.max-w-\[220px\] {
  max-width: 220px;
}
.max-w-\[280px\] {
  max-width: 280px;
}
.max-w-\[340px\] {
  max-width: 340px;
}
.max-w-\[360px\] {
  max-width: 360px;
}
.max-w-\[600px\] {
  max-width: 600px;
}
.max-w-\[calc\(100\%-2rem\)\] {
  max-width: calc(100% - 2rem);
}
.max-w-\[calc\(100vw-2rem\)\] {
  max-width: calc(100vw - 2rem);
}
.max-w-lg {
  max-width: 32rem;
}
.max-w-md {
  max-width: 28rem;
}
.max-w-sm {
  max-width: 24rem;
}
.max-w-xs {
  max-width: 20rem;
}
.flex-1 {
  flex: 1 1 0%;
}
.flex-\[2\] {
  flex: 2;
}
.flex-shrink {
  flex-shrink: 1;
}
.flex-shrink-0 {
  flex-shrink: 0;
}
.shrink {
  flex-shrink: 1;
}
.shrink-0 {
  flex-shrink: 0;
}
.grow {
  flex-grow: 1;
}
.-translate-x-1\/2 {
  --tw-translate-x: -50%;
  transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.-translate-y-1\/2 {
  --tw-translate-y: -50%;
  transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.translate-x-\[-50\%\] {
  --tw-translate-x: -50%;
  transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.translate-y-\[-50\%\] {
  --tw-translate-y: -50%;
  transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.translate-y-\[calc\(-50\%_-_2px\)\] {
  --tw-translate-y: calc(-50% - 2px);
  transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.rotate-180 {
  --tw-rotate: 180deg;
  transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.rotate-45 {
  --tw-rotate: 45deg;
  transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.rotate-\[-90deg\] {
  --tw-rotate: -90deg;
  transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.scale-105 {
  --tw-scale-x: 1.05;
  --tw-scale-y: 1.05;
  transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.scale-\[1\.02\] {
  --tw-scale-x: 1.02;
  --tw-scale-y: 1.02;
  transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.transform {
  transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
@keyframes ping {

  75%, 100% {
    transform: scale(2);
    opacity: 0;
  }
}
.animate-ping {
  animation: ping 1s cubic-bezier(0, 0, 0.2, 1) infinite;
}
@keyframes pulse {

  50% {
    opacity: .5;
  }
}
.animate-pulse {
  animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}
@keyframes spin {

  to {
    transform: rotate(360deg);
  }
}
.animate-spin {
  animation: spin 1s linear infinite;
}
@keyframes wvc-live-pulse {

  0%, 100% {
    opacity: 0.6;
    transform: scale(0.97);
  }

  50% {
    opacity: 1;
    transform: scale(1);
  }
}
.animate-wvc-live-pulse {
  animation: wvc-live-pulse 2s ease-in-out infinite;
}
.cursor-default {
  cursor: default;
}
.cursor-help {
  cursor: help;
}
.cursor-not-allowed {
  cursor: not-allowed;
}
.cursor-pointer {
  cursor: pointer;
}
.touch-none {
  touch-action: none;
}
.touch-manipulation {
  touch-action: manipulation;
}
.select-none {
  -webkit-user-select: none;
     -moz-user-select: none;
          user-select: none;
}
.resize-none {
  resize: none;
}
.resize {
  resize: both;
}
.scroll-my-1 {
  scroll-margin-top: 0.25rem;
  scroll-margin-bottom: 0.25rem;
}
.scroll-mt-4 {
  scroll-margin-top: 1rem;
}
.auto-rows-min {
  grid-auto-rows: min-content;
}
.grid-cols-1 {
  grid-template-columns: repeat(1, minmax(0, 1fr));
}
.grid-cols-2 {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
.grid-cols-3 {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}
.grid-cols-4 {
  grid-template-columns: repeat(4, minmax(0, 1fr));
}
.grid-cols-7 {
  grid-template-columns: repeat(7, minmax(0, 1fr));
}
.grid-cols-\[0_1fr\] {
  grid-template-columns: 0 1fr;
}
.grid-rows-\[auto_auto\] {
  grid-template-rows: auto auto;
}
.flex-row {
  flex-direction: row;
}
.flex-col {
  flex-direction: column;
}
.flex-col-reverse {
  flex-direction: column-reverse;
}
.flex-wrap {
  flex-wrap: wrap;
}
.content-start {
  align-content: flex-start;
}
.items-start {
  align-items: flex-start;
}
.items-end {
  align-items: flex-end;
}
.items-center {
  align-items: center;
}
.items-baseline {
  align-items: baseline;
}
.items-stretch {
  align-items: stretch;
}
.justify-end {
  justify-content: flex-end;
}
.justify-center {
  justify-content: center;
}
.justify-between {
  justify-content: space-between;
}
.justify-around {
  justify-content: space-around;
}
.justify-items-start {
  justify-items: start;
}
.gap-0 {
  gap: 0px;
}
.gap-0\.5 {
  gap: 0.125rem;
}
.gap-1 {
  gap: 0.25rem;
}
.gap-1\.5 {
  gap: 0.375rem;
}
.gap-2 {
  gap: 0.5rem;
}
.gap-2\.5 {
  gap: 0.625rem;
}
.gap-3 {
  gap: 0.75rem;
}
.gap-4 {
  gap: 1rem;
}
.gap-5 {
  gap: 1.25rem;
}
.gap-6 {
  gap: 1.5rem;
}
.gap-x-2 {
  -moz-column-gap: 0.5rem;
       column-gap: 0.5rem;
}
.gap-x-4 {
  -moz-column-gap: 1rem;
       column-gap: 1rem;
}
.gap-y-0\.5 {
  row-gap: 0.125rem;
}
.gap-y-1 {
  row-gap: 0.25rem;
}
.space-y-0 > :not([hidden]) ~ :not([hidden]) {
  --tw-space-y-reverse: 0;
  margin-top: calc(0px * calc(1 - var(--tw-space-y-reverse)));
  margin-bottom: calc(0px * var(--tw-space-y-reverse));
}
.space-y-1 > :not([hidden]) ~ :not([hidden]) {
  --tw-space-y-reverse: 0;
  margin-top: calc(0.25rem * calc(1 - var(--tw-space-y-reverse)));
  margin-bottom: calc(0.25rem * var(--tw-space-y-reverse));
}
.space-y-1\.5 > :not([hidden]) ~ :not([hidden]) {
  --tw-space-y-reverse: 0;
  margin-top: calc(0.375rem * calc(1 - var(--tw-space-y-reverse)));
  margin-bottom: calc(0.375rem * var(--tw-space-y-reverse));
}
.space-y-2 > :not([hidden]) ~ :not([hidden]) {
  --tw-space-y-reverse: 0;
  margin-top: calc(0.5rem * calc(1 - var(--tw-space-y-reverse)));
  margin-bottom: calc(0.5rem * var(--tw-space-y-reverse));
}
.space-y-2\.5 > :not([hidden]) ~ :not([hidden]) {
  --tw-space-y-reverse: 0;
  margin-top: calc(0.625rem * calc(1 - var(--tw-space-y-reverse)));
  margin-bottom: calc(0.625rem * var(--tw-space-y-reverse));
}
.space-y-3 > :not([hidden]) ~ :not([hidden]) {
  --tw-space-y-reverse: 0;
  margin-top: calc(0.75rem * calc(1 - var(--tw-space-y-reverse)));
  margin-bottom: calc(0.75rem * var(--tw-space-y-reverse));
}
.space-y-4 > :not([hidden]) ~ :not([hidden]) {
  --tw-space-y-reverse: 0;
  margin-top: calc(1rem * calc(1 - var(--tw-space-y-reverse)));
  margin-bottom: calc(1rem * var(--tw-space-y-reverse));
}
.space-y-5 > :not([hidden]) ~ :not([hidden]) {
  --tw-space-y-reverse: 0;
  margin-top: calc(1.25rem * calc(1 - var(--tw-space-y-reverse)));
  margin-bottom: calc(1.25rem * var(--tw-space-y-reverse));
}
.space-y-6 > :not([hidden]) ~ :not([hidden]) {
  --tw-space-y-reverse: 0;
  margin-top: calc(1.5rem * calc(1 - var(--tw-space-y-reverse)));
  margin-bottom: calc(1.5rem * var(--tw-space-y-reverse));
}
.space-y-7 > :not([hidden]) ~ :not([hidden]) {
  --tw-space-y-reverse: 0;
  margin-top: calc(1.75rem * calc(1 - var(--tw-space-y-reverse)));
  margin-bottom: calc(1.75rem * var(--tw-space-y-reverse));
}
.space-y-8 > :not([hidden]) ~ :not([hidden]) {
  --tw-space-y-reverse: 0;
  margin-top: calc(2rem * calc(1 - var(--tw-space-y-reverse)));
  margin-bottom: calc(2rem * var(--tw-space-y-reverse));
}
.self-start {
  align-self: flex-start;
}
.self-stretch {
  align-self: stretch;
}
.justify-self-end {
  justify-self: end;
}
.overflow-hidden {
  overflow: hidden;
}
.overflow-y-auto {
  overflow-y: auto;
}
.overflow-x-hidden {
  overflow-x: hidden;
}
.overscroll-contain {
  overscroll-behavior: contain;
}
.truncate {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.whitespace-normal {
  white-space: normal;
}
.whitespace-nowrap {
  white-space: nowrap;
}
.text-balance {
  text-wrap: balance;
}
.break-words {
  overflow-wrap: break-word;
}
.break-all {
  word-break: break-all;
}
.\!rounded-lg {
  border-radius: var(--radius) !important;
}
.rounded {
  border-radius: 0.25rem;
}
.rounded-2xl {
  border-radius: 1rem;
}
.rounded-3xl {
  border-radius: 1.5rem;
}
.rounded-\[10px\] {
  border-radius: 10px;
}
.rounded-\[2px\] {
  border-radius: 2px;
}
.rounded-\[inherit\] {
  border-radius: inherit;
}
.rounded-full {
  border-radius: 9999px;
}
.rounded-lg {
  border-radius: var(--radius);
}
.rounded-md {
  border-radius: calc(var(--radius) - 2px);
}
.rounded-sm {
  border-radius: calc(var(--radius) - 4px);
}
.rounded-xl {
  border-radius: 0.75rem;
}
.rounded-l-full {
  border-top-left-radius: 9999px;
  border-bottom-left-radius: 9999px;
}
.rounded-r-full {
  border-top-right-radius: 9999px;
  border-bottom-right-radius: 9999px;
}
.rounded-t-2xl {
  border-top-left-radius: 1rem;
  border-top-right-radius: 1rem;
}
.rounded-t-3xl {
  border-top-left-radius: 1.5rem;
  border-top-right-radius: 1.5rem;
}
.border {
  border-width: 1px;
}
.border-0 {
  border-width: 0px;
}
.border-2 {
  border-width: 2px;
}
.border-4 {
  border-width: 4px;
}
.border-b {
  border-bottom-width: 1px;
}
.border-l {
  border-left-width: 1px;
}
.border-l-2 {
  border-left-width: 2px;
}
.border-l-\[3px\] {
  border-left-width: 3px;
}
.border-r {
  border-right-width: 1px;
}
.border-t {
  border-top-width: 1px;
}
.border-solid {
  border-style: solid;
}
.border-none {
  border-style: none;
}
.border-\[oklch\(var\(--accent\)\)\] {
  border-color: oklch(var(--accent));
}
.border-accent {
  border-color: oklch(var(--accent));
}
.border-border {
  border-color: oklch(var(--border));
}
.border-current {
  border-color: currentColor;
}
.border-green-500 {
  --tw-border-opacity: 1;
  border-color: rgb(34 197 94 / var(--tw-border-opacity, 1));
}
.border-input {
  border-color: oklch(var(--input));
}
.border-red-500\/30 {
  border-color: rgb(239 68 68 / 0.3);
}
.border-transparent {
  border-color: transparent;
}
.border-l-transparent {
  border-left-color: transparent;
}
.border-r-transparent {
  border-right-color: transparent;
}
.border-t-transparent {
  border-top-color: transparent;
}
.bg-\[oklch\(0\.75_0\.05_40\/0\.15\)\] {
  background-color: oklch(0.75 0.05 40/0.15);
}
.bg-\[oklch\(var\(--accent\)\)\] {
  background-color: oklch(var(--accent));
}
.bg-\[oklch\(var\(--accent\)\/0\.08\)\] {
  background-color: oklch(var(--accent)/0.08);
}
.bg-\[rgba\(120\2c 200\2c 140\2c 0\.18\)\] {
  background-color: rgba(120,200,140,0.18);
}
.bg-\[rgba\(210\2c 90\2c 80\2c 0\.18\)\] {
  background-color: rgba(210,90,80,0.18);
}
.bg-\[rgba\(64\2c 140\2c 220\2c 0\.18\)\] {
  background-color: rgba(64,140,220,0.18);
}
.bg-\[rgba\(var\(--accent-rgb\)\2c 0\.18\)\] {
  background-color: rgba(var(--accent-rgb),0.18);
}
.bg-\[var\(--accent-hex\)\] {
  background-color: var(--accent-hex);
}
.bg-\[var\(--background\)\] {
  background-color: var(--background);
}
.bg-accent {
  background-color: oklch(var(--accent));
}
.bg-background {
  background-color: oklch(var(--background));
}
.bg-black\/50 {
  background-color: rgb(0 0 0 / 0.5);
}
.bg-black\/60 {
  background-color: rgb(0 0 0 / 0.6);
}
.bg-black\/70 {
  background-color: rgb(0 0 0 / 0.7);
}
.bg-blue-500\/20 {
  background-color: rgb(59 130 246 / 0.2);
}
.bg-border {
  background-color: oklch(var(--border));
}
.bg-card {
  background-color: oklch(var(--card));
}
.bg-cyan-500\/20 {
  background-color: rgb(6 182 212 / 0.2);
}
.bg-destructive {
  background-color: oklch(var(--destructive));
}
.bg-emerald-400 {
  --tw-bg-opacity: 1;
  background-color: rgb(52 211 153 / var(--tw-bg-opacity, 1));
}
.bg-emerald-500\/15 {
  background-color: rgb(16 185 129 / 0.15);
}
.bg-gray-500\/20 {
  background-color: rgb(107 114 128 / 0.2);
}
.bg-green-400 {
  --tw-bg-opacity: 1;
  background-color: rgb(74 222 128 / var(--tw-bg-opacity, 1));
}
.bg-green-500 {
  --tw-bg-opacity: 1;
  background-color: rgb(34 197 94 / var(--tw-bg-opacity, 1));
}
.bg-green-500\/20 {
  background-color: rgb(34 197 94 / 0.2);
}
.bg-muted {
  background-color: oklch(var(--muted));
}
.bg-orange-500\/20 {
  background-color: rgb(249 115 22 / 0.2);
}
.bg-pink-500\/20 {
  background-color: rgb(236 72 153 / 0.2);
}
.bg-popover {
  background-color: oklch(var(--popover));
}
.bg-primary {
  background-color: oklch(var(--primary));
}
.bg-purple-500\/20 {
  background-color: rgb(168 85 247 / 0.2);
}
.bg-red-500\/20 {
  background-color: rgb(239 68 68 / 0.2);
}
.bg-red-600\/20 {
  background-color: rgb(220 38 38 / 0.2);
}
.bg-secondary {
  background-color: oklch(var(--secondary));
}
.bg-teal-500\/20 {
  background-color: rgb(20 184 166 / 0.2);
}
.bg-transparent {
  background-color: transparent;
}
.bg-yellow-400 {
  --tw-bg-opacity: 1;
  background-color: rgb(250 204 21 / var(--tw-bg-opacity, 1));
}
.bg-yellow-500\/20 {
  background-color: rgb(234 179 8 / 0.2);
}
.bg-gradient-to-br {
  background-image: linear-gradient(to bottom right, var(--tw-gradient-stops));
}
.fill-accent {
  fill: oklch(var(--accent));
}
.fill-current {
  fill: currentColor;
}
.fill-primary {
  fill: oklch(var(--primary));
}
.fill-white {
  fill: #fff;
}
.object-contain {
  -o-object-fit: contain;
     object-fit: contain;
}
.object-cover {
  -o-object-fit: cover;
     object-fit: cover;
}
.p-0 {
  padding: 0px;
}
.p-0\.5 {
  padding: 0.125rem;
}
.p-1 {
  padding: 0.25rem;
}
.p-1\.5 {
  padding: 0.375rem;
}
.p-10 {
  padding: 2.5rem;
}
.p-12 {
  padding: 3rem;
}
.p-2 {
  padding: 0.5rem;
}
.p-2\.5 {
  padding: 0.625rem;
}
.p-3 {
  padding: 0.75rem;
}
.p-3\.5 {
  padding: 0.875rem;
}
.p-4 {
  padding: 1rem;
}
.p-5 {
  padding: 1.25rem;
}
.p-6 {
  padding: 1.5rem;
}
.p-8 {
  padding: 2rem;
}
.p-px {
  padding: 1px;
}
.\!px-2 {
  padding-left: 0.5rem !important;
  padding-right: 0.5rem !important;
}
.px-0\.5 {
  padding-left: 0.125rem;
  padding-right: 0.125rem;
}
.px-1 {
  padding-left: 0.25rem;
  padding-right: 0.25rem;
}
.px-1\.5 {
  padding-left: 0.375rem;
  padding-right: 0.375rem;
}
.px-2 {
  padding-left: 0.5rem;
  padding-right: 0.5rem;
}
.px-2\.5 {
  padding-left: 0.625rem;
  padding-right: 0.625rem;
}
.px-3 {
  padding-left: 0.75rem;
  padding-right: 0.75rem;
}
.px-3\.5 {
  padding-left: 0.875rem;
  padding-right: 0.875rem;
}
.px-4 {
  padding-left: 1rem;
  padding-right: 1rem;
}
.px-5 {
  padding-left: 1.25rem;
  padding-right: 1.25rem;
}
.px-6 {
  padding-left: 1.5rem;
  padding-right: 1.5rem;
}
.px-7 {
  padding-left: 1.75rem;
  padding-right: 1.75rem;
}
.py-0\.5 {
  padding-top: 0.125rem;
  padding-bottom: 0.125rem;
}
.py-1 {
  padding-top: 0.25rem;
  padding-bottom: 0.25rem;
}
.py-1\.5 {
  padding-top: 0.375rem;
  padding-bottom: 0.375rem;
}
.py-10 {
  padding-top: 2.5rem;
  padding-bottom: 2.5rem;
}
.py-12 {
  padding-top: 3rem;
  padding-bottom: 3rem;
}
.py-16 {
  padding-top: 4rem;
  padding-bottom: 4rem;
}
.py-2 {
  padding-top: 0.5rem;
  padding-bottom: 0.5rem;
}
.py-2\.5 {
  padding-top: 0.625rem;
  padding-bottom: 0.625rem;
}
.py-3 {
  padding-top: 0.75rem;
  padding-bottom: 0.75rem;
}
.py-3\.5 {
  padding-top: 0.875rem;
  padding-bottom: 0.875rem;
}
.py-4 {
  padding-top: 1rem;
  padding-bottom: 1rem;
}
.py-5 {
  padding-top: 1.25rem;
  padding-bottom: 1.25rem;
}
.py-6 {
  padding-top: 1.5rem;
  padding-bottom: 1.5rem;
}
.py-8 {
  padding-top: 2rem;
  padding-bottom: 2rem;
}
.pb-10 {
  padding-bottom: 2.5rem;
}
.pb-2 {
  padding-bottom: 0.5rem;
}
.pb-24 {
  padding-bottom: 6rem;
}
.pb-28 {
  padding-bottom: 7rem;
}
.pb-3 {
  padding-bottom: 0.75rem;
}
.pb-32 {
  padding-bottom: 8rem;
}
.pb-4 {
  padding-bottom: 1rem;
}
.pb-5 {
  padding-bottom: 1.25rem;
}
.pb-6 {
  padding-bottom: 1.5rem;
}
.pb-8 {
  padding-bottom: 2rem;
}
.pb-\[env\(safe-area-inset-bottom\)\] {
  padding-bottom: env(safe-area-inset-bottom);
}
.pl-10 {
  padding-left: 2.5rem;
}
.pl-2 {
  padding-left: 0.5rem;
}
.pl-6 {
  padding-left: 1.5rem;
}
.pl-7 {
  padding-left: 1.75rem;
}
.pl-8 {
  padding-left: 2rem;
}
.pl-9 {
  padding-left: 2.25rem;
}
.pl-\[52px\] {
  padding-left: 52px;
}
.pr-1 {
  padding-right: 0.25rem;
}
.pr-10 {
  padding-right: 2.5rem;
}
.pr-12 {
  padding-right: 3rem;
}
.pr-2 {
  padding-right: 0.5rem;
}
.pr-4 {
  padding-right: 1rem;
}
.pr-8 {
  padding-right: 2rem;
}
.pt-0\.5 {
  padding-top: 0.125rem;
}
.pt-1 {
  padding-top: 0.25rem;
}
.pt-2 {
  padding-top: 0.5rem;
}
.pt-3 {
  padding-top: 0.75rem;
}
.pt-4 {
  padding-top: 1rem;
}
.pt-5 {
  padding-top: 1.25rem;
}
.pt-6 {
  padding-top: 1.5rem;
}
.pt-\[calc\(env\(safe-area-inset-top\)\+1\.5rem\)\] {
  padding-top: calc(env(safe-area-inset-top) + 1.5rem);
}
.pt-\[env\(safe-area-inset-top\)\] {
  padding-top: env(safe-area-inset-top);
}
.text-left {
  text-align: left;
}
.text-center {
  text-align: center;
}
.text-right {
  text-align: right;
}
.font-mono {
  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
}
.\!text-\[0\.8125rem\] {
  font-size: 0.8125rem !important;
}
.text-2xl {
  font-size: 1.5rem;
  line-height: 2rem;
}
.text-3xl {
  font-size: 1.875rem;
  line-height: 2.25rem;
}
.text-4xl {
  font-size: 2.25rem;
  line-height: 2.5rem;
}
.text-5xl {
  font-size: 3rem;
  line-height: 1;
}
.text-\[0\.625rem\] {
  font-size: 0.625rem;
}
.text-\[10px\] {
  font-size: 10px;
}
.text-\[11px\] {
  font-size: 11px;
}
.text-\[15px\] {
  font-size: 15px;
}
.text-\[7px\] {
  font-size: 7px;
}
.text-\[8px\] {
  font-size: 8px;
}
.text-\[9px\] {
  font-size: 9px;
}
.text-base {
  font-size: 1rem;
  line-height: 1.5rem;
}
.text-lg {
  font-size: 1.125rem;
  line-height: 1.75rem;
}
.text-sm {
  font-size: 0.875rem;
  line-height: 1.25rem;
}
.text-xl {
  font-size: 1.25rem;
  line-height: 1.75rem;
}
.text-xs {
  font-size: 0.75rem;
  line-height: 1rem;
}
.\!font-medium {
  font-weight: 500 !important;
}
.font-black {
  font-weight: 900;
}
.font-bold {
  font-weight: 700;
}
.font-extrabold {
  font-weight: 800;
}
.font-medium {
  font-weight: 500;
}
.font-normal {
  font-weight: 400;
}
.font-semibold {
  font-weight: 600;
}
.uppercase {
  text-transform: uppercase;
}
.lowercase {
  text-transform: lowercase;
}
.capitalize {
  text-transform: capitalize;
}
.italic {
  font-style: italic;
}
.tabular-nums {
  --tw-numeric-spacing: tabular-nums;
  font-variant-numeric: var(--tw-ordinal) var(--tw-slashed-zero) var(--tw-numeric-figure) var(--tw-numeric-spacing) var(--tw-numeric-fraction);
}
.leading-none {
  line-height: 1;
}
.leading-relaxed {
  line-height: 1.625;
}
.leading-snug {
  line-height: 1.375;
}
.leading-tight {
  line-height: 1.25;
}
.tracking-\[0\.25em\] {
  letter-spacing: 0.25em;
}
.tracking-\[0\.2em\] {
  letter-spacing: 0.2em;
}
.tracking-tight {
  letter-spacing: -0.025em;
}
.tracking-wide {
  letter-spacing: 0.025em;
}
.tracking-wider {
  letter-spacing: 0.05em;
}
.tracking-widest {
  letter-spacing: 0.1em;
}
.text-\[oklch\(var\(--accent\)\)\] {
  color: oklch(var(--accent));
}
.text-\[oklch\(var\(--accent-foreground\)\)\] {
  color: oklch(var(--accent-foreground));
}
.text-\[rgb\(120\2c 200\2c 140\)\] {
  --tw-text-opacity: 1;
  color: rgb(120 200 140 / var(--tw-text-opacity, 1));
}
.text-\[rgb\(210\2c 90\2c 80\)\] {
  --tw-text-opacity: 1;
  color: rgb(210 90 80 / var(--tw-text-opacity, 1));
}
.text-\[rgb\(64\2c 140\2c 220\)\] {
  --tw-text-opacity: 1;
  color: rgb(64 140 220 / var(--tw-text-opacity, 1));
}
.text-\[var\(--accent-hex\)\] {
  color: var(--accent-hex);
}
.text-accent {
  color: oklch(var(--accent));
}
.text-accent-foreground {
  color: oklch(var(--accent-foreground));
}
.text-blue-400 {
  --tw-text-opacity: 1;
  color: rgb(96 165 250 / var(--tw-text-opacity, 1));
}
.text-card-foreground {
  color: oklch(var(--card-foreground));
}
.text-cyan-400 {
  --tw-text-opacity: 1;
  color: rgb(34 211 238 / var(--tw-text-opacity, 1));
}
.text-destructive {
  color: oklch(var(--destructive));
}
.text-destructive-foreground {
  color: oklch(var(--destructive-foreground));
}
.text-emerald-400 {
  --tw-text-opacity: 1;
  color: rgb(52 211 153 / var(--tw-text-opacity, 1));
}
.text-foreground {
  color: oklch(var(--foreground));
}
.text-gray-400 {
  --tw-text-opacity: 1;
  color: rgb(156 163 175 / var(--tw-text-opacity, 1));
}
.text-green-400 {
  --tw-text-opacity: 1;
  color: rgb(74 222 128 / var(--tw-text-opacity, 1));
}
.text-green-500 {
  --tw-text-opacity: 1;
  color: rgb(34 197 94 / var(--tw-text-opacity, 1));
}
.text-lime-500 {
  --tw-text-opacity: 1;
  color: rgb(132 204 22 / var(--tw-text-opacity, 1));
}
.text-muted {
  color: oklch(var(--muted));
}
.text-muted-foreground {
  color: oklch(var(--muted-foreground));
}
.text-orange-400 {
  --tw-text-opacity: 1;
  color: rgb(251 146 60 / var(--tw-text-opacity, 1));
}
.text-orange-500 {
  --tw-text-opacity: 1;
  color: rgb(249 115 22 / var(--tw-text-opacity, 1));
}
.text-pink-400 {
  --tw-text-opacity: 1;
  color: rgb(244 114 182 / var(--tw-text-opacity, 1));
}
.text-popover-foreground {
  color: oklch(var(--popover-foreground));
}
.text-primary {
  color: oklch(var(--primary));
}
.text-primary-foreground {
  color: oklch(var(--primary-foreground));
}
.text-purple-400 {
  --tw-text-opacity: 1;
  color: rgb(192 132 252 / var(--tw-text-opacity, 1));
}
.text-red-400 {
  --tw-text-opacity: 1;
  color: rgb(248 113 113 / var(--tw-text-opacity, 1));
}
.text-red-500 {
  --tw-text-opacity: 1;
  color: rgb(239 68 68 / var(--tw-text-opacity, 1));
}
.text-secondary-foreground {
  color: oklch(var(--secondary-foreground));
}
.text-teal-400 {
  --tw-text-opacity: 1;
  color: rgb(45 212 191 / var(--tw-text-opacity, 1));
}
.text-transparent {
  color: transparent;
}
.text-white {
  --tw-text-opacity: 1;
  color: rgb(255 255 255 / var(--tw-text-opacity, 1));
}
.text-yellow-400 {
  --tw-text-opacity: 1;
  color: rgb(250 204 21 / var(--tw-text-opacity, 1));
}
.text-yellow-500 {
  --tw-text-opacity: 1;
  color: rgb(234 179 8 / var(--tw-text-opacity, 1));
}
.underline {
  text-decoration-line: underline;
}
.line-through {
  text-decoration-line: line-through;
}
.underline-offset-4 {
  text-underline-offset: 4px;
}
.opacity-0 {
  opacity: 0;
}
.opacity-100 {
  opacity: 1;
}
.opacity-40 {
  opacity: 0.4;
}
.opacity-50 {
  opacity: 0.5;
}
.opacity-60 {
  opacity: 0.6;
}
.opacity-70 {
  opacity: 0.7;
}
.opacity-75 {
  opacity: 0.75;
}
.opacity-80 {
  opacity: 0.8;
}
.opacity-90 {
  opacity: 0.9;
}
.shadow {
  --tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
  --tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);
  box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
}
.shadow-2xl {
  --tw-shadow: 0 25px 50px -12px rgb(0 0 0 / 0.25);
  --tw-shadow-colored: 0 25px 50px -12px var(--tw-shadow-color);
  box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
}
.shadow-\[0_0_12px_rgba\(232\2c 99\2c 10\2c 0\.5\)\] {
  --tw-shadow: 0 0 12px rgba(232,99,10,0.5);
  --tw-shadow-colored: 0 0 12px var(--tw-shadow-color);
  box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
}
.shadow-\[0_0_14px_rgba\(239\2c 68\2c 68\2c 0\.18\)\] {
  --tw-shadow: 0 0 14px rgba(239,68,68,0.18);
  --tw-shadow-colored: 0 0 14px var(--tw-shadow-color);
  box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
}
.shadow-\[0_0_20px_rgba\(var\(--accent-rgb\)\2c 0\.4\)\] {
  --tw-shadow: 0 0 20px rgba(var(--accent-rgb),0.4);
  --tw-shadow-colored: 0 0 20px var(--tw-shadow-color);
  box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
}
.shadow-\[0_0_4px_rgba\(250\2c 204\2c 21\2c 0\.6\)\] {
  --tw-shadow: 0 0 4px rgba(250,204,21,0.6);
  --tw-shadow-colored: 0 0 4px var(--tw-shadow-color);
  box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
}
.shadow-\[0_0_4px_rgba\(74\2c 222\2c 128\2c 0\.6\)\] {
  --tw-shadow: 0 0 4px rgba(74,222,128,0.6);
  --tw-shadow-colored: 0 0 4px var(--tw-shadow-color);
  box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
}
.shadow-lg {
  --tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
  --tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);
  box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
}
.shadow-md {
  --tw-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
  --tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);
  box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
}
.shadow-none {
  --tw-shadow: 0 0 #0000;
  --tw-shadow-colored: 0 0 #0000;
  box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
}
.shadow-sm {
  --tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);
  --tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);
  box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
}
.\!shadow-\[var\(--neomorph-inset-sm\)\2c 0_0_0_1\.5px_rgba\(var\(--destructive-rgb\)\2c 0\.55\)\] {
  --tw-shadow-color: var(--neomorph-inset-sm),0 0 0 1.5px rgba(var(--destructive-rgb),0.55) !important;
  --tw-shadow: var(--tw-shadow-colored) !important;
}
.outline-none {
  outline: 2px solid transparent;
  outline-offset: 2px;
}
.outline {
  outline-style: solid;
}
.ring {
  --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
  --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color);
  box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
}
.ring-0 {
  --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
  --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color);
  box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
}
.ring-1 {
  --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
  --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
  box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
}
.ring-2 {
  --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
  --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);
  box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
}
.ring-\[rgba\(120\2c 200\2c 140\2c 0\.35\)\] {
  --tw-ring-color: rgba(120,200,140,0.35);
}
.ring-\[rgba\(210\2c 90\2c 80\2c 0\.4\)\] {
  --tw-ring-color: rgba(210,90,80,0.4);
}
.ring-\[rgba\(64\2c 140\2c 220\2c 0\.4\)\] {
  --tw-ring-color: rgba(64,140,220,0.4);
}
.ring-\[rgba\(var\(--accent-rgb\)\2c 0\.4\)\] {
  --tw-ring-color: rgba(var(--accent-rgb),0.4);
}
.ring-accent {
  --tw-ring-color: oklch(var(--accent));
}
.ring-border {
  --tw-ring-color: oklch(var(--border));
}
.ring-emerald-400\/30 {
  --tw-ring-color: rgb(52 211 153 / 0.3);
}
.ring-emerald-500\/20 {
  --tw-ring-color: rgb(16 185 129 / 0.2);
}
.ring-offset-background {
  --tw-ring-offset-color: oklch(var(--background));
}
.blur {
  --tw-blur: blur(8px);
  filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
}
.drop-shadow {
  --tw-drop-shadow: drop-shadow(0 1px 2px rgb(0 0 0 / 0.1)) drop-shadow(0 1px 1px rgb(0 0 0 / 0.06));
  filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
}
.drop-shadow-\[0_0_12px_rgba\(var\(--accent-rgb\)\2c 0\.6\)\] {
  --tw-drop-shadow: drop-shadow(0 0 12px rgba(var(--accent-rgb),0.6));
  filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
}
.drop-shadow-\[0_1px_2px_rgba\(0\2c 0\2c 0\2c 0\.6\)\] {
  --tw-drop-shadow: drop-shadow(0 1px 2px rgba(0,0,0,0.6));
  filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
}
.filter {
  filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
}
.backdrop-blur {
  --tw-backdrop-blur: blur(8px);
  backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);
}
.backdrop-blur-md {
  --tw-backdrop-blur: blur(12px);
  backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);
}
.backdrop-blur-sm {
  --tw-backdrop-blur: blur(4px);
  backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);
}
.transition {
  transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
  transition-duration: 150ms;
}
.transition-\[color\2c box-shadow\] {
  transition-property: color,box-shadow;
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
  transition-duration: 150ms;
}
.transition-all {
  transition-property: all;
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
  transition-duration: 150ms;
}
.transition-colors {
  transition-property: color, background-color, border-color, text-decoration-color, fill, stroke;
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
  transition-duration: 150ms;
}
.transition-opacity {
  transition-property: opacity;
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
  transition-duration: 150ms;
}
.transition-transform {
  transition-property: transform;
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
  transition-duration: 150ms;
}
.duration-150 {
  transition-duration: 150ms;
}
.duration-200 {
  transition-duration: 200ms;
}
.duration-300 {
  transition-duration: 300ms;
}
.duration-500 {
  transition-duration: 500ms;
}
.ease-in-out {
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
}
.ease-out {
  transition-timing-function: cubic-bezier(0, 0, 0.2, 1);
}
.will-change-scroll {
  will-change: scroll-position;
}
.will-change-transform {
  will-change: transform;
}
@keyframes enter {

  from {
    opacity: var(--tw-enter-opacity, 1);
    transform: translate3d(var(--tw-enter-translate-x, 0), var(--tw-enter-translate-y, 0), 0) scale3d(var(--tw-enter-scale, 1), var(--tw-enter-scale, 1), var(--tw-enter-scale, 1)) rotate(var(--tw-enter-rotate, 0));
  }
}
@keyframes exit {

  to {
    opacity: var(--tw-exit-opacity, 1);
    transform: translate3d(var(--tw-exit-translate-x, 0), var(--tw-exit-translate-y, 0), 0) scale3d(var(--tw-exit-scale, 1), var(--tw-exit-scale, 1), var(--tw-exit-scale, 1)) rotate(var(--tw-exit-rotate, 0));
  }
}
.animate-in {
  animation-name: enter;
  animation-duration: 150ms;
  --tw-enter-opacity: initial;
  --tw-enter-scale: initial;
  --tw-enter-rotate: initial;
  --tw-enter-translate-x: initial;
  --tw-enter-translate-y: initial;
}
.fade-in {
  --tw-enter-opacity: 0;
}
.fade-in-0 {
  --tw-enter-opacity: 0;
}
.fade-in-50 {
  --tw-enter-opacity: 0.5;
}
.zoom-in-95 {
  --tw-enter-scale: .95;
}
.slide-in-from-bottom {
  --tw-enter-translate-y: 100%;
}
.slide-in-from-bottom-2 {
  --tw-enter-translate-y: 0.5rem;
}
.duration-150 {
  animation-duration: 150ms;
}
.duration-200 {
  animation-duration: 200ms;
}
.duration-300 {
  animation-duration: 300ms;
}
.duration-500 {
  animation-duration: 500ms;
}
.ease-in-out {
  animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
}
.ease-out {
  animation-timing-function: cubic-bezier(0, 0, 0.2, 1);
}
.running {
  animation-play-state: running;
}
.paused {
  animation-play-state: paused;
}
/* Neumorphic Raised Elements — no will-change on static cards to reduce GPU overhead */
.neomorph {
    box-shadow: var(--neomorph-shadow), var(--neomorph-accent-ring);
    transition: box-shadow 200ms cubic-bezier(0.4, 0, 0.2, 1);
  }
.neomorph-sm {
    box-shadow: var(--neomorph-shadow-sm);
    transition: box-shadow 200ms cubic-bezier(0.4, 0, 0.2, 1);
  }
.neomorph-lg {
    box-shadow: var(--neomorph-shadow-lg), var(--neomorph-accent-ring);
    transition: box-shadow 200ms cubic-bezier(0.4, 0, 0.2, 1);
  }
.neomorph-xl {
    box-shadow: var(--neomorph-shadow-xl);
    transition: box-shadow 200ms cubic-bezier(0.4, 0, 0.2, 1);
  }
/* Neumorphic Inset Elements — no box-shadow transition: the box-shadow IS
     the visible background/border of inputs in this design. A 200ms transition
      re-interpolates on every keystroke re-render, causing the input to briefly
      disappear. Keep the shadow static so the inset look stays visible. */
.neomorph-inset {
    box-shadow: var(--neomorph-inset);
  }
.neomorph-inset-sm {
    box-shadow: var(--neomorph-inset-sm);
  }
/* ═══════════════════════════════════════════════════════════════════════════
     WEEKLY QUEST — compacted card utilities (Phase: Compacted Weekly Quest)
     Additive only — reuses --accent-hex / --accent-rgb / --muted / --foreground
     tokens. The ring well is a dedicated engraved treatment (deeper inset than
     .neomorph-inset-sm) so the ProgressRing SVG appears sunk into the card.
     State color is driven by --wq-state-color / --wq-state-rgb on the card root;
     state 1 = orange (default), state 2 = amber, state 3 = soft green. All three
     states share the same well + glow rules — only the CSS vars change.
     ═══════════════════════════════════════════════════════════════════════════ */
/* Card shell — compact horizontal layout. Tight padding, rounded-2xl, raised
     neumorphic-sm surface. Whole card is tappable (state 1 & 2) → opens Drawer;
     state 3 adds .wq-card--static to disable interaction. */
.wq-card {
    display: flex;
    align-items: center;
    gap: 0.875rem;
    padding: 0.75rem 0.875rem;
    border-radius: 1rem;
    background-color: oklch(var(--card));
    box-shadow: var(--neomorph-shadow-sm);
    transition: box-shadow 200ms cubic-bezier(0.4, 0, 0.2, 1), transform 200ms
      cubic-bezier(0.4, 0, 0.2, 1);
    cursor: pointer;
    contain: layout style;
  }
.wq-card:active {
    transform: scale(0.99) translateZ(0);
    box-shadow: var(--neomorph-pressed);
  }
/* State 3 (recovery) — non-interactive, no tap action, default cursor. */
.wq-card--static {
    cursor: default;
  }
.wq-card--static:active {
    transform: none;
    box-shadow: var(--neomorph-shadow-sm);
  }
/* Ring well — circular recessed area hosting the ProgressRing SVG.
     Deeper inset than .neomorph-inset-sm: 5px dark inner shadow + 5px subtle
     white highlight + 1px hairline rim = engraved look. Sized to wrap an
     88px ring with ~6px breathing room (100px well). */
.blueprint-engraved-field {
    box-shadow: var(--neomorph-inset-sm);
    border-radius: 0.75rem;
    padding: 14px 18px;
    width: 100%;
    background: transparent;
    transition: box-shadow 0.2s ease;
  }
.blueprint-engraved-field:focus-within,
  .blueprint-engraved-field input:focus,
  .blueprint-engraved-field textarea:focus {
    box-shadow: var(--neomorph-inset-sm), 0 0 0 1.5px
      rgba(var(--accent-rgb), 0.55), 0 0 12px rgba(var(--accent-rgb), 0.18);
  }
.blueprint-engraved-field input,
  .blueprint-engraved-field textarea {
    background: transparent;
    border: none;
    outline: none;
    color: inherit;
    width: 100%;
  }
@keyframes blueprint-save-pulse {
    0%,
    100% {
      box-shadow: var(--neomorph-shadow), 0 0 18px rgba(var(--accent-rgb), 0.35);
    }
    50% {
      box-shadow: var(--neomorph-shadow), 0 0 24px rgba(var(--accent-rgb), 0.6);
    }
  }
.blueprint-add-exercise svg,
  .blueprint-add-exercise .lucide {
    color: var(--accent-hex);
  }
.blueprint-exercises-well {
    box-shadow: var(--blueprint-exercises-well);
    border-radius: 0.75rem;
    padding: 20px;
    background: transparent;
  }
/* ═══════════════════════════════════════════════════════════════════════════
     BLUEPRINT BUILDER — FASE 2 SURFACES (bp2- prefix)
     Additive only — does NOT modify any existing .blueprint-* Fase 1 classes.
     Reuses shadow patterns from .blueprint-engraved-field (inset + orange focus
     glow) and .neomorph-inset / .neomorph-button. All orange accents use
     --accent-hex / --accent-rgb tokens (theme-agnostic). No new @keyframes —
     reuses blueprint-save-pulse where a pulse is needed.
     ═══════════════════════════════════════════════════════════════════════════ */
/* Search bar — neomorph-inset engraved field with orange focus glow.
     Mirrors .blueprint-engraved-field pattern. Full width, rounded, padded
     for a leading icon + text input. The wrapper carries the inset shadow;
     the inner input is transparent/borderless. */
.bp2-search-input {
    box-shadow: var(--neomorph-inset-sm);
    border-radius: 0.75rem;
    padding: 8px 12px;
    width: 100%;
    background: transparent;
    transition: box-shadow 0.2s ease;
  }
.bp2-search-input:focus-within,
  .bp2-search-input input:focus,
  .bp2-search-input textarea:focus {
    box-shadow: var(--neomorph-inset-sm), 0 0 0 1.5px
      rgba(var(--accent-rgb), 0.55), 0 0 12px rgba(var(--accent-rgb), 0.18);
  }
.bp2-search-input input,
  .bp2-search-input textarea {
    background: transparent;
    border: none;
    outline: none;
    color: inherit;
    width: 100%;
  }
/* Muscle-group filter chip — neomorph-button base, small rounded pill.
     Quiet raised surface; tap to toggle. */
.bp2-chip {
    box-shadow: var(--neomorph-shadow);
    border-radius: 9999px;
    padding: 6px 14px;
    font-size: 0.875rem;
    line-height: 1.25rem;
    background-color: oklch(var(--card));
    color: oklch(var(--foreground));
    transition: box-shadow 150ms cubic-bezier(0.4, 0, 0.2, 1), transform 150ms
      cubic-bezier(0.4, 0, 0.2, 1), background-color 150ms ease;
    will-change: transform;
    contain: layout style;
  }
.bp2-chip:hover:not(:disabled) {
    box-shadow: var(--neomorph-hover);
    transform: scale(1.02) translateZ(0);
  }
.bp2-chip:active:not(:disabled) {
    box-shadow: var(--neomorph-pressed);
    transform: scale(0.98) translateZ(0);
  }
.bp2-chip:focus-visible {
    outline: 2px solid oklch(var(--accent));
    outline-offset: 2px;
  }
/* Active chip — orange accent fill + glow using --accent-hex / --accent-rgb.
     Overrides the quiet raised surface with a warm filled pill. */
.bp2-chip--active {
    background-color: var(--accent-hex);
    color: #fff;
    box-shadow: var(--neomorph-shadow), 0 0 14px rgba(var(--accent-rgb), 0.45);
  }
.bp2-chip--active:hover:not(:disabled) {
    background-color: var(--accent-hex);
    box-shadow: var(--neomorph-hover), 0 0 18px rgba(var(--accent-rgb), 0.6);
  }
/* Collapsible category panel — smooth slide-down via the
     grid-template-rows: 0fr → 1fr trick. The outer .bp2-collapsible element
     animates its grid row height; the inner .bp2-collapsible__inner div carries
     overflow-hidden so chips don't bleed out while collapsing. Opacity fades
     the inner content for a softer reveal. Honors prefers-reduced-motion via
     the global rule at the bottom of this file. */
.bp2-collapsible {
    display: grid;
    grid-template-rows: 0fr;
    opacity: 0;
    transition: grid-template-rows 220ms cubic-bezier(0.4, 0, 0.2, 1), opacity
      200ms cubic-bezier(0.4, 0, 0.2, 1);
  }
.bp2-collapsible[data-state="open"] {
    grid-template-rows: 1fr;
    opacity: 1;
  }
.bp2-collapsible__inner {
    overflow: hidden;
    min-height: 0;
  }
/* Top-3 recent suggestion card — compact neumorph raised, tappable.
     Tight padding, rounded, touch-manipulation for low-latency taps. */
/* Starter suggestion card (Push/Pull/Leg Day) — larger neumorph raised
     with hover orange glow. More generous padding than .bp2-recent-card. */
/* Mini-illustration container for empty state — centered, subtle opacity
     so the illustration reads as a quiet decorative hint, not a focal point. */
/* 'Start from scratch' button — neomorph-button base with an orange accent
     outline/border. Quiet raised surface with a warm rim to signal the primary
     creation path. */
/* Sticky bottom mini-preview bar — neomorph-inset, tappable, rounded top.
     Sits pinned to the bottom of the viewport; opens the full preview modal. */
/* Compact exercise row inside the mini-preview — flex row, name + sets x reps.
     Truncates long exercise names so the bar stays a single line. */
/* ════════════════════════════════════════════════════════════════════════
     bp2-type-badge — per-exercise type pill (strength / cardio / mobility)
     Inline-flex pill with small padding + rounded-full + subtle background
     tint. Strength uses the user's accent color (var(--accent-hex) /
     var(--accent-rgb)) so it follows the instellingen accent keuze — NO
     hardcoded orange #E8630A. Cardio gets a rose/red tint (#ef4444), mobility
     gets an emerald/green tint (#10b981). The icon is 12px currentColor; the
     label is small uppercase letter-spaced text. Consistent with the existing
     neumorphic pill language (bp2-chip) but smaller and type-tinted.
     ════════════════════════════════════════════════════════════════════════ */
/* Strength — user accent color. Reads --accent-hex for the solid text/icon
     color and --accent-rgb for the subtle 12% background tint. This means the
     badge follows the instellingen accent keuze (blauw, oranje, etc.) instead
     of forcing orange #E8630A. */
/* Cardio — rose/red tint. Distinct from strength accent and from
     --destructive so it reads as an exercise-type indicator, not an error. */
/* Mobility — emerald/green tint. Distinct from strength and cardio so the
     three exercise types are visually separable at a glance. */
/* 12px SVG icon — inherits currentColor from the badge modifier. */
/* Small uppercase letter-spaced label — sits next to the icon. */
/* Full-screen modal overlay — dark scrim with a subtle orange tint and
     backdrop-blur. Sits above all content; clicking it dismisses the modal. */
/* The preview modal card — neumorph raised, rounded-2xl, max-height 80vh,
     scrollable. Slides up from the bottom on mobile, centers on desktop. */
@keyframes bp2-modal-rise {
    from {
      transform: translateY(24px);
      opacity: 0;
    }
    to {
      transform: translateY(0);
      opacity: 1;
    }
  }
@media (min-width: 640px) {
    .bp2-preview-modal-overlay {
      align-items: center;
      padding: 1rem;
    }
    .bp2-preview-modal {
      animation: bp2-modal-fade 200ms cubic-bezier(0.16, 1, 0.3, 1);
    }
    @keyframes bp2-modal-fade {
      from {
        opacity: 0;
        transform: scale(0.98);
      }
      to {
        opacity: 1;
        transform: scale(1);
      }
    }
  }
.wq-ring-well {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100px;
    height: 100px;
    border-radius: 9999px;
    background-color: oklch(var(--background));
    box-shadow: var(--wq-ring-well);
    flex-shrink: 0;
  }
/* Soft glow on the active progress arc — applied to the SVG element (or the
     arc path) so the orange (or amber/green) stroke carries a warm halo.
     Reads --wq-state-color / --wq-state-rgb so all 3 states share one rule. */
.wq-arc-glow {
    filter: drop-shadow(0 0 5px rgba(var(--wq-state-rgb), 0.55))
      drop-shadow(0 0 12px rgba(var(--wq-state-rgb), 0.22));
  }
/* Text column — tight hierarchy. Header on one line, sessions prominent,
     subtext 1 line, badge top-right. */
.wq-text {
    display: flex;
    flex-direction: column;
    gap: 0.125rem;
    flex: 1 1 auto;
    min-width: 0;
  }
.wq-header {
    display: flex;
    align-items: baseline;
    gap: 0.4rem;
    line-height: 1.15;
  }
.wq-header__label {
    font-family: var(--font-body);
    font-size: 0.625rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: oklch(var(--muted-foreground));
  }
.wq-header__name {
    font-family: var(--font-display);
    font-size: 0.9375rem;
    font-weight: 600;
    color: oklch(var(--foreground));
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
.wq-sessions {
    font-family: var(--font-display);
    font-size: 1.0625rem;
    font-weight: 700;
    color: oklch(var(--foreground));
    line-height: 1.2;
  }
/* Rest-days integrated — small inline icon + label, muted, sits on the same
     line as the sessions count (flex row) so it never becomes a 4th text line. */
.wq-rest {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    margin-left: 0.5rem;
    color: oklch(var(--muted-foreground));
    font-family: var(--font-body);
    font-size: 0.6875rem;
    font-weight: 500;
    vertical-align: middle;
  }
.wq-rest__icon {
    width: 12px;
    height: 12px;
    flex-shrink: 0;
    opacity: 0.8;
  }
.wq-subtext {
    font-family: var(--font-body);
    font-size: 0.75rem;
    font-weight: 400;
    color: oklch(var(--muted-foreground));
    line-height: 1.3;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
/* Reward badge — pill, accent-tinted bg + accent text, top-right corner.
     Uses --wq-state-color so state 2/3 badges match the ring tint. */
.wq-reward {
    position: absolute;
    top: 0.5rem;
    right: 0.625rem;
    display: inline-flex;
    align-items: center;
    gap: 0.2rem;
    padding: 0.1875rem 0.5rem;
    border-radius: 9999px;
    background-color: rgba(var(--wq-state-rgb), 0.14);
    color: var(--wq-state-color);
    font-family: var(--font-body);
    font-size: 0.625rem;
    font-weight: 700;
    letter-spacing: 0.02em;
    line-height: 1;
  }
/* State color overrides — set --wq-state-color / --wq-state-rgb on the card
     root. State 1 inherits the defaults (orange). */
.wq-card--state-2 {
    --wq-state-color: oklch(0.82 0.13 80);
    --wq-state-rgb: 232, 178, 60;
  }
.wq-card--state-3 {
    --wq-state-color: oklch(0.78 0.1 145);
    --wq-state-rgb: 120, 200, 140;
  }
/* ═══════════════════════════════════════════════════════════════════════════
     FASE 1 STATS — Monthly Calendar + Goal ring + Week bars + Insight card
     Additive utilities (Phase: Fase 1 Stats tab upgrade). Reuses existing
     --accent-hex / --accent-rgb / --neomorph-shadow / --neomorph-inset-sm
     tokens plus the new --mw-* tokens defined above. Mirrors the .wq-ring-well
     engraved pattern for both calendar tiles and the monthly goal ring well so
     the Stats tab shares the same sculpted-recess language as the Weekly Quest
     card. All classes are additive — no existing classes or tokens modified.
     ═══════════════════════════════════════════════════════════════════════════ */
/* ─── Monthly calendar grid ─────────────────────────────────────────────────
     7-column grid for the days of the week. Tight gap (0.375rem) so the
     engraved tiles sit close together and read as a single sculpted surface. */
.mw-grid {
    display: grid;
    grid-template-columns: repeat(7, minmax(0, 1fr));
    gap: 0.375rem;
  }
/* ─── Base engraved day tile ────────────────────────────────────────────────
     Square (aspect-square) rounded-lg tile with the --mw-tile-well engraved
     inset. Flex-centered so the day number sits in the visual middle of the
     recess. Background = bg-background so the tile reads as a hole sunk into
     the card surface (same language as .wq-ring-well). */
.mw-tile {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    aspect-ratio: 1 / 1;
    border-radius: 0.5rem;
    background-color: oklch(var(--background));
    box-shadow: var(--mw-tile-well);
    color: oklch(var(--muted-foreground));
    font-family: var(--font-body);
    font-size: 0.75rem;
    font-weight: 600;
    line-height: 1;
    -webkit-user-select: none;
       -moz-user-select: none;
            user-select: none;
  }
/* ─── Trained day ───────────────────────────────────────────────────────────
     Orange glow halo + accent-colored day number + a small checkmark icon
     top-right. The glow layers ON TOP of the engraved well (box-shadow can
     hold multiple layers — well + glow). Reads as "this day is lit". */
.mw-tile--trained {
    color: var(--accent-hex);
    font-weight: 700;
    box-shadow: var(--mw-tile-well), var(--mw-tile-trained-glow);
  }
/* ─── Today ─────────────────────────────────────────────────────────────────
     Thin accent ring around the tile (not a glow) so today stays distinct
     from trained days. Ring layers on top of the engraved well. */
.mw-tile--today {
    box-shadow: var(--mw-tile-well), var(--mw-tile-today-ring);
  }
/* Today + trained combo: well + glow + ring all layered so today's trained
     day reads as the most prominent tile on the grid. */
.mw-tile--today.mw-tile--trained {
    box-shadow: var(--mw-tile-well), var(--mw-tile-trained-glow),
      var(--mw-tile-today-ring);
  }
/* ─── Rest day (non-trained in-month) ──────────────────────────────────────
     Subtle lighter inset (--mw-tile-rest) so rest days read as quieter empty
     engraved tiles — still part of the month, just not trained. Muted day
     number, no glow, no checkmark. */
.mw-tile--rest {
    box-shadow: var(--mw-tile-rest);
  }
/* ─── Out-of-month day ──────────────────────────────────────────────────────
     Dimmed to 30% opacity, no interaction, no engraved well (flat) so it
     recedes visually behind the in-month tiles. Pointer-events disabled so
     taps pass through. */
.mw-tile--out {
    opacity: 0.3;
    box-shadow: none;
    background-color: transparent;
    pointer-events: none;
  }
/* ─── Trained-day checkmark indicator ───────────────────────────────────────
     Small checkmark icon top-right of a trained tile. Accent color, tiny
     (10px), absolute positioned so it doesn't shift the centered day number. */
.mw-tile-check {
    position: absolute;
    top: 0.1875rem;
    right: 0.1875rem;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 10px;
    height: 10px;
    color: var(--accent-hex);
    pointer-events: none;
  }
.mw-tile-check svg {
    width: 10px;
    height: 10px;
  }
/* ─── Monthly Goal ring well ────────────────────────────────────────────────
     Mirrors .wq-ring-well exactly: 100px circular recess with the --mw-ring-well
     engraved inset (5px deep + hairline rim). Hosts a ProgressRing SVG
     (size=88, strokeWidth=8) centered inside. Background = bg-background so the
     ring reads as sunk into the card surface. */
.mw-ring-well {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100px;
    height: 100px;
    border-radius: 9999px;
    background-color: oklch(var(--background));
    box-shadow: var(--mw-ring-well);
    flex-shrink: 0;
  }
/* ─── Monthly goal arc glow ─────────────────────────────────────────────────
     Soft warm drop-shadow halo on the progress arc SVG. Same alpha as
     .wq-arc-glow so the monthly ring breathes the same way as the weekly
     quest ring. Applied to the SVG element (or arc path). */
.mw-ring-glow {
    filter: drop-shadow(0 0 5px rgba(var(--accent-rgb), 0.55))
      drop-shadow(0 0 12px rgba(var(--accent-rgb), 0.22));
  }
/* ─── Monthly goal centered text ────────────────────────────────────────────
     Centered X/Y fraction overlaid on the ring well. Display font, the
     fraction in accent color, a small muted label underneath. Absolute
     positioned so it sits dead-center over the ProgressRing. */
.mw-ring-text {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.0625rem;
    pointer-events: none;
    text-align: center;
  }
.mw-ring-text__fraction {
    font-family: var(--font-display);
    font-size: 1.0625rem;
    font-weight: 700;
    color: var(--accent-hex);
    line-height: 1.1;
    letter-spacing: 0.01em;
  }
.mw-ring-text__label {
    font-family: var(--font-body);
    font-size: 0.5625rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: oklch(var(--muted-foreground));
    line-height: 1;
  }
/* ─── Compact week breakdown row ────────────────────────────────────────────
     Horizontal flex row hosting 4 mini-bars (W1-W4). gap-2 (0.5rem) so the
     mini-bars have breathing room. */
.mw-week-row {
    display: flex;
    align-items: stretch;
    gap: 0.5rem;
    width: 100%;
  }
/* ─── Mini-bar container (one per week) ─────────────────────────────────────
     flex-1 so 4 mini-bars share the row equally. flex-col, items-center so
     the label sits above the bar and the value below. */
.mw-week-mini {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.25rem;
    flex: 1 1 0;
    min-width: 0;
  }
/* ─── Week label (W1-W4) ────────────────────────────────────────────────────
     Tiny uppercase letter-spaced muted label above each mini-bar. */
.mw-week-label {
    font-family: var(--font-body);
    font-size: 0.5625rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: oklch(var(--muted-foreground));
    line-height: 1;
  }
/* ─── Progress bar track ────────────────────────────────────────────────────
     h-1.5 (6px) rounded-full inset track. Neomorph-inset-sm so the fill
     appears to sit inside a sculpted groove. Background = bg-background. */
.mw-week-bar {
    position: relative;
    width: 100%;
    height: 6px;
    border-radius: 9999px;
    background-color: oklch(var(--background));
    box-shadow: var(--neomorph-inset-sm);
    overflow: hidden;
  }
/* ─── Progress bar fill ─────────────────────────────────────────────────────
     Accent-colored fill with a soft orange glow. Width driven inline by the
     component. Sits inside the inset track so it reads as a lit bar in a
     groove. */
.mw-week-bar-fill {
    position: absolute;
    top: 0;
    left: 0;
    height: 100%;
    border-radius: 9999px;
    background-color: var(--accent-hex);
    box-shadow: 0 0 4px rgba(var(--accent-rgb), 0.55);
    transition: width 300ms cubic-bezier(0.4, 0, 0.2, 1);
  }
/* ─── Compact week value ────────────────────────────────────────────────────
     Small value text below each mini-bar — "gehaald/doel" or remaining count.
     Muted, tiny, centered. */
.mw-week-value {
    font-family: var(--font-body);
    font-size: 0.625rem;
    font-weight: 500;
    color: oklch(var(--muted-foreground));
    line-height: 1;
    text-align: center;
  }
/* ─── Insight card ──────────────────────────────────────────────────────────
     Neumorphic raised card (rounded-xl) hosting the rule-based insight. Thin
     orange left border (3px accent) + a small accent icon so the insight
     reads as a distinct, highlighted callout. Padding matches .card-compact. */
.mw-insight {
    position: relative;
    display: flex;
    align-items: flex-start;
    gap: 0.625rem;
    padding: 0.75rem 0.875rem 0.75rem 0.875rem;
    border-radius: 0.75rem;
    background-color: oklch(var(--card));
    box-shadow: var(--neomorph-shadow-sm);
    border-left: 3px solid var(--accent-hex);
    overflow: hidden;
  }
/* Insight accent icon — small square (28px) accent-tinted background with
     accent-colored icon. Sits at the top-left next to the left border. */
.mw-insight__icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border-radius: 8px;
    background-color: rgba(var(--accent-rgb), 0.14);
    color: var(--accent-hex);
    flex-shrink: 0;
  }
/* Insight text column — header + body. Tight gap. */
.mw-insight__text {
    display: flex;
    flex-direction: column;
    gap: 0.1875rem;
    flex: 1 1 auto;
    min-width: 0;
  }
.mw-insight__header {
    font-family: var(--font-display);
    font-size: 0.8125rem;
    font-weight: 600;
    color: oklch(var(--foreground));
    line-height: 1.2;
  }
.mw-insight__body {
    font-family: var(--font-body);
    font-size: 0.6875rem;
    font-weight: 400;
    color: oklch(var(--muted-foreground));
    line-height: 1.35;
  }
/* ═══════════════════════════════════════════════════════════════════════════ */
/* ─── Solid field container (ExerciseCard redesign) ───────────────────
     Replaces the neumorphic-inset look for exercise set inputs. Solid dark
     fill, 1px border, fully-rounded pill (border-radius:9999px), ~44px
     height, centered value. NO inset shadows, NO transition/animation on the
     container. On focus ONLY the border color changes to orange (#E8630A) —
     nothing else changes. Pill shape matches the landing-page card reference
     style. */
.solid-field {
    background-color: #232327;
    border: 1px solid #38383c;
    border-radius: 9999px;
    height: 44px;
    color: oklch(var(--foreground));
    text-align: center;
    box-shadow: none;
    transition: none;
  }
.solid-field:focus {
    border-color: var(--accent-hex);
    outline: none;
    box-shadow: none;
  }
.solid-field:disabled {
    opacity: 0.5;
    cursor: not-allowed;
  }
.solid-field::-moz-placeholder {
    color: oklch(var(--muted-foreground) / 0.5);
    opacity: 1;
  }
.solid-field::placeholder {
    color: oklch(var(--muted-foreground) / 0.5);
    opacity: 1;
  }
/* Variant for taller cardio inputs (matches the previous h-12 footprint) */
.solid-field-lg {
    background-color: #232327;
    border: 1px solid #38383c;
    border-radius: 9999px;
    height: 44px;
    color: oklch(var(--foreground));
    box-shadow: none;
    transition: none;
  }
.solid-field-lg:focus {
    border-color: var(--accent-hex);
    outline: none;
    box-shadow: none;
  }
.solid-field-lg:disabled {
    opacity: 0.5;
    cursor: not-allowed;
  }
.solid-field-lg::-moz-placeholder {
    color: oklch(var(--muted-foreground) / 0.5);
    opacity: 1;
  }
.solid-field-lg::placeholder {
    color: oklch(var(--muted-foreground) / 0.5);
    opacity: 1;
  }
/* ─── Solid checkmark (ExerciseCard redesign) ────────────────────────
     Round, default = gray with a border (not filled); completed = filled
     with full-orange background and white check icon. NO neumorphic
     shadows. Only the color/border changes — no layout-affecting transition
     on the container (uses color/border-color transition only). */
/* ─── Muted field labels (ExerciseCard redesign) ─────────────────────
     Small uppercase letter-spaced muted-grey labels above each set input
     field (SET / KG / REPS / DURATION / DISTANCE). Matches the landing-page
     card reference style. */
/* ─── Ghost "+ Add Set" button (ExerciseCard redesign) ────────────────
     Subtle ghost-style button: transparent background, muted border, muted
     text. On hover the border + text shift to the orange accent. No
     neumorphic shadow — keeps the button quiet per the landing reference. */
/* ─── Light-theme overrides for solid-field / solid-field-lg / solid-check ──
     The base rules above use hardcoded dark-mode colors (#232327 fill,
     #38383c/#4a4a50 border). In the light theme these stay dark, making the
     dark foreground text unreadable. These :root:not(.dark) overrides swap
     the fill to #f0edea and the border to #c8c4be — matching the existing
     .modal-exercise-search light-mode pattern (regels 933-943). Focus state
     keeps --accent-hex (orange) which works in both themes. The .dark theme
     is NOT touched — base rules keep applying unchanged in dark mode. */
:root:not(.dark) .solid-field,
  :root:not(.dark) .solid-field-lg {
    background-color: #f0edea !important;
    border-color: #c8c4be !important;
  }
:root:not(.dark) .solid-field::-moz-placeholder, :root:not(.dark) .solid-field-lg::-moz-placeholder {
    /* oklch(var(--muted-foreground) / 0.5) is too light on #f0edea — use a
       darker gray for sufficient contrast in light mode. */
    color: #6b6b6b !important;
    opacity: 1 !important;
  }
:root:not(.dark) .solid-field::placeholder,
  :root:not(.dark) .solid-field-lg::placeholder {
    /* oklch(var(--muted-foreground) / 0.5) is too light on #f0edea — use a
       darker gray for sufficient contrast in light mode. */
    color: #6b6b6b !important;
    opacity: 1 !important;
  }
/* Light-theme completed check = same orange fill + white check as dark
     mode (per requirement: oranje gevulde cirkel met witte check in both
     themes). */
/* ═══════════════════════════════════════════════════════════════════════════
     EXERCISE CARD REDESIGN — landing-page reference style
     Compact, clean, non-bulky exercise cards. Header sits ABOVE the card (slim
     row, no card background); the card hosts a single header-row set table with
     pill-shaped borderless inputs and orange-filled checkmarks. An inline rest
     timer strip (thin orange progress bar) appears under a completed set row.
     A ghost "+ Add Set" button (no dashed border) closes the card.
     All classes reuse existing OKLCH tokens (--background, --card, --foreground,
     --muted, --muted-foreground, --border, --accent, --accent-hex, --accent-rgb)
     and the --font-display / --font-body variables. Both :root (light) and .dark
     themes are handled via inherited variables plus explicit light overrides at
     the bottom of this block. Existing .solid-field / .solid-check /
     .solid-add-set classes are NOT touched — these classes are additive.
     ═══════════════════════════════════════════════════════════════════════════ */
/* ─── Header row above the card ─────────────────────────────────────────────
     Slim ~40px row, no card background, no shadow. Icon + exercise name on the
     left, timer pill + delete button on the right. Subtle spacing only. */
.ex-card-header {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    min-height: 40px;
    padding: 0 0.25rem 0.375rem;
    background: transparent;
    box-shadow: none;
  }
.ex-card-header__icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border-radius: 8px;
    background-color: oklch(var(--muted));
    color: oklch(var(--muted-foreground));
    flex-shrink: 0;
  }
.ex-card-header__name {
    font-family: var(--font-display);
    font-weight: 600;
    font-size: 0.9375rem;
    line-height: 1.2;
    color: oklch(var(--foreground));
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
.ex-card-header__actions {
    display: flex;
    align-items: center;
    gap: 0.25rem;
    flex-shrink: 0;
  }
/* ─── Collapsible action buttons container ─────────────────────────────────
     Wraps the rest-stepper (timer pill), RPE (pulse) button, and clock (timer
     mode) button. Slides in from right-to-left when the header expands, and
     collapses back when it contracts. Driven by the local isExpanded state in
     ExerciseCard — only the expand button toggles it.

     Animation strategy: animate max-width + opacity + margin-left. width:auto
     is not animatable, so we use max-width (0 → 240px, enough for the three
     28px buttons + gaps + the rest-stepper label). overflow:hidden clips the
     buttons during the slide. pointer-events disabled while collapsed so the
     hidden buttons can't be tapped accidentally. */
.ex-card-header__collapsible-actions {
    display: flex;
    align-items: center;
    gap: 0.25rem;
    overflow: hidden;
    max-width: 0;
    margin-left: 0;
    opacity: 0;
    pointer-events: none;
    transition: max-width 250ms ease-in-out, opacity 250ms ease-in-out,
      margin-left 250ms ease-in-out;
  }
.ex-card-header__collapsible-actions.is-open {
    max-width: 240px;
    opacity: 1;
    pointer-events: auto;
  }
/* ─── Expand / collapse button ─────────────────────────────────────────────
     28px neomorph pill button matching .ex-card-header__rpe-btn base styling
     (same size, border-radius, background, box-shadow, hover/active states).
     Sits directly LEFT of the trash button. Shows ChevronLeft when collapsed
     (pointing toward the name) and ChevronRight when expanded. */
.ex-card-header__expand-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border-radius: 9999px;
    background-color: oklch(var(--muted));
    color: oklch(var(--muted-foreground));
    border: none;
    box-shadow: var(--neomorph-inset-sm);
    transition: color 150ms ease, background-color 150ms ease, box-shadow 150ms
      ease;
    cursor: pointer;
  }
.ex-card-header__expand-btn:hover {
    color: oklch(var(--accent));
    background-color: rgba(var(--accent-rgb), 0.1);
  }
.ex-card-header__expand-btn:focus-visible {
    outline: none;
    box-shadow: var(--neomorph-inset-sm), 0 0 0 1.5px
      rgba(var(--accent-rgb), 0.6);
  }
/* Timer pill button — small, quiet, accent on hover/active only */
.ex-card-header__timer-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    height: 28px;
    padding: 0 0.625rem;
    border-radius: 9999px;
    background-color: oklch(var(--muted));
    color: oklch(var(--muted-foreground));
    font-family: var(--font-body);
    font-size: 0.6875rem;
    font-weight: 600;
    border: none;
    box-shadow: none;
    transition: color 150ms ease, background-color 150ms ease;
  }
.ex-card-header__timer-btn:hover {
    color: oklch(var(--accent));
    background-color: rgba(var(--accent-rgb), 0.1);
  }
.ex-card-header__timer-btn.is-active {
    background-color: var(--accent-hex);
    color: #ffffff;
  }
/* Delete button — small ghost icon button */
.ex-card-header__delete-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border-radius: 9999px;
    background: transparent;
    color: oklch(var(--muted-foreground));
    border: none;
    box-shadow: none;
    transition: color 150ms ease, background-color 150ms ease;
  }
.ex-card-header__delete-btn:hover {
    color: oklch(var(--destructive));
    background-color: oklch(var(--muted));
  }
/* ─── Rest-tijd stepper — subtiele compacte dropdown in card header ───────
     Hergebruik de 28px pill-stijl van de timer-btn. Inset neumorphic shadow
     op de trigger, oranje accent op de geselecteerde waarde. Dutch label
     "Rest" + duur in seconden. Geen modals, volledig inline. */
.ex-rest-stepper {
    display: inline-flex;
    align-items: center;
  }
.ex-rest-stepper__trigger {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    height: 28px;
    padding: 0 0.5rem;
    border-radius: 9999px;
    background-color: oklch(var(--muted));
    color: oklch(var(--muted-foreground));
    font-family: var(--font-body);
    font-size: 0.6875rem;
    font-weight: 600;
    border: none;
    box-shadow: var(--neomorph-inset-sm);
    transition: color 150ms ease, background-color 150ms ease, box-shadow 150ms
      ease;
    cursor: pointer;
  }
.ex-rest-stepper__trigger:hover {
    color: oklch(var(--accent));
    background-color: rgba(var(--accent-rgb), 0.1);
  }
.ex-rest-stepper__trigger:focus-visible {
    outline: none;
    box-shadow: var(--neomorph-inset-sm), 0 0 0 1.5px
      rgba(var(--accent-rgb), 0.6);
  }
.ex-rest-stepper__trigger[data-state="open"] {
    color: oklch(var(--accent));
    background-color: rgba(var(--accent-rgb), 0.12);
  }
.ex-rest-stepper__label {
    line-height: 1;
    white-space: nowrap;
  }
/* ─── Smalle schermen (≤380px) ─────────────────────────────────────────────
     Op hele smalle schermen verbergen we de "Rest " prefix zodat alleen de
     minuutwaarde (bv. "2 min") overblijft en de oefening-naam ruimte houdt.
     De prefix zit in een eigen <span class="ex-rest-stepper__prefix"> in
      ExerciseCard.tsx, dus alleen die prefix verdwijnt — de minuutwaarde
     blijft altijd zichtbaar. */
@media (max-width: 380px) {
    .ex-rest-stepper__prefix {
      display: none;
    }
  }
/* RPE toggle — subtiel icoon-knop, accent wanneer actief. Matcht de
     28px pill-stijl van de timer-btn en delete-btn. */
.ex-card-header__rpe-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border-radius: 9999px;
    background-color: oklch(var(--muted));
    color: oklch(var(--muted-foreground));
    border: none;
    box-shadow: var(--neomorph-inset-sm);
    transition: color 150ms ease, background-color 150ms ease, box-shadow 150ms
      ease;
    cursor: pointer;
  }
.ex-card-header__rpe-btn:hover {
    color: oklch(var(--accent));
    background-color: rgba(var(--accent-rgb), 0.1);
  }
.ex-card-header__rpe-btn:focus-visible {
    outline: none;
    box-shadow: var(--neomorph-inset-sm), 0 0 0 1.5px
      rgba(var(--accent-rgb), 0.6);
  }
.ex-card-header__rpe-btn.is-active {
    background-color: var(--accent-hex);
    color: #ffffff;
    box-shadow: var(--neomorph-shadow-sm);
  }
/* ─── Per-exercise override indicator ──────────────────────────────────────
     Subtiele oranje stip rechtsboven op de RPE knop wanneer er een per-exercise
     override actief is. Zo is zichtbaar dat de oefening afwijkt van de globale
     standaard. Werkt in beide thema's via --accent-hex / --accent-rgb. */
.ex-card-header__rpe-btn.is-override {
    position: relative;
  }
.ex-card-header__rpe-btn.is-override::after {
    content: "";
    position: absolute;
    top: 2px;
    right: 2px;
    width: 6px;
    height: 6px;
    border-radius: 9999px;
    background-color: var(--accent-hex);
    box-shadow: 0 0 4px rgba(var(--accent-rgb), 0.7);
    pointer-events: none;
    z-index: 1;
  }
/* ─── Set table inside the card ─────────────────────────────────────────────
     Single header row (SET / KG / REPS, or SET / DURATION / DISTANCE, or
     SET / DURATION). No repeated labels per row. Tight, compact stack.
     NOTE: Each row (header + set rows) owns its own self-contained FLEXBOX
     column layout — mirroring the landing-page SetRowMini pattern. This avoids
     the display:contents grid-context bug where rows wrapped in non-grid
     parents lost their grid alignment and stacked vertically. */
.ex-card-table {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    width: 100%;
  }
/* Header row — tiny uppercase muted letter-spaced labels.
     Uses the same flex row pattern as set rows so column widths match. */
.ex-card-table-head-row {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0 0.25rem 0.0625rem;
  }
.ex-card-table-head {
    font-family: var(--font-body);
    font-size: 0.625rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: oklch(var(--muted-foreground));
    line-height: 1;
    text-align: center;
    flex: 1 1 0;
    min-width: 0;
  }
.ex-card-table-head--index {
    flex: 0 0 28px;
    text-align: center;
  }
.ex-card-table-head--check {
    flex: 0 0 32px;
    text-align: center;
  }
/* Set row — self-contained flex row (one row per set). Index column +
     input columns + check column. Owns its own column widths so it never
     breaks alignment regardless of wrapper nesting (swipe wrapper, relative
     parent, etc.). Replaces the previous display:contents grid row which
     silently fell back to block flow when wrapped in non-grid parents.

     touch-action: pan-y lets the browser handle vertical scrolling natively
     (no double-tap-zoom delay, smooth scroll) while leaving horizontal
     panning to the JS swipe-to-delete handlers. Without this the browser
     would try to interpret both axes and the swipe would jitter. */
.ex-card-row {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    width: 100%;
    touch-action: pan-y;
  }
/* Value column — flex-1 so two value columns share the row equally.
      Holds the pill input (or countdown timer / unit select). Centered
      text alignment matches the header labels. */
.ex-card-row__col {
    flex: 1 1 0;
    min-width: 0;
    text-align: center;
  }
/* Set index — small centered number, fixed width matching the header. */
.ex-card-row__index {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 28px;
    font-family: var(--font-display);
    font-size: 0.75rem;
    font-weight: 600;
    color: oklch(var(--muted-foreground));
    line-height: 1;
  }
/* Check column wrapper — fixed width matching the header check column,
      centers the checkmark button. */
.ex-card-row__check {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 32px;
  }
/* ─── Set row background distinction ────────────────────────────────────────
     Completed sets carry a light orange row background (subtle accent tint) so
     the user can scan completed vs pending sets at a glance. Pending sets use
     a neutral/muted background. The tint is applied to the .ex-card-row flex
     box itself (now a real box, not display:contents) with rounded corners and
     tight horizontal padding so the inputs/checkmark sit inside the tint. */
.ex-card-row {
    border-radius: 0.5rem;
    padding: 0.25rem 0.375rem;
    transition: background-color 200ms ease;
  }
.ex-card-row--pending {
    background-color: oklch(var(--muted) / 0.35);
  }
.ex-card-row--done {
    background-color: rgba(var(--accent-rgb), 0.14);
  }
/* Light-theme tuning: the muted tint is barely visible on a light bg, so
     bump the pending tint slightly and keep the completed orange tint. */
:root:not(.dark) .ex-card-row--pending {
    background-color: oklch(var(--muted) / 0.55);
  }
:root:not(.dark) .ex-card-row--done {
    background-color: rgba(var(--accent-rgb), 0.12);
  }
/* ─── Pill-shaped input fields ──────────────────────────────────────────────
     Fully rounded (border-radius pill), subtle low-contrast solid fill, NO hard
     borders (transparent), compact ~32-36px height, small centered font. Focus
     state shifts fill slightly + adds a faint accent ring — no border change. */
.ex-pill-input {
    width: 100%;
    height: 30px;
    border-radius: 9999px;
    border: 1px solid transparent;
    background-color: oklch(0.26 0 0);
    color: oklch(var(--foreground));
    font-family: var(--font-body);
    font-size: 0.8125rem;
    font-weight: 500;
    text-align: center;
    box-shadow: var(--neomorph-inset-sm);
    transition: background-color 150ms ease, box-shadow 150ms ease;
    padding: 0 0.5rem;
  }
.ex-pill-input:focus {
    outline: none;
    background-color: oklch(0.3 0 0);
    /* Preserve the inset shadow and layer the accent ring on top of it. */
    box-shadow: var(--neomorph-inset-sm), 0 0 0 1.5px
      rgba(var(--accent-rgb), 0.55);
  }
.ex-pill-input:disabled {
    opacity: 0.5;
    cursor: not-allowed;
  }
.ex-pill-input::-moz-placeholder {
    color: oklch(var(--muted-foreground) / 0.55);
    opacity: 1;
  }
.ex-pill-input::placeholder {
    color: oklch(var(--muted-foreground) / 0.55);
    opacity: 1;
  }
/* ─── Checkmarks ────────────────────────────────────────────────────────────
     Completed = solid orange (#E8630A) filled circle with white check icon.
     Pending = empty circle, 2px muted-gray border, transparent fill. */
.ex-check {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    border-radius: 9999px;
    flex-shrink: 0;
    border: 2px solid oklch(var(--muted-foreground) / 0.45);
    background-color: transparent;
    color: transparent;
    box-shadow: var(--neomorph-shadow-sm);
    transition: background-color 150ms ease, border-color 150ms ease, color
      150ms ease;
    cursor: pointer;
  }
.ex-check-pending {
    /* Toon altijd een vinkje — ook op pending sets. Subtiele grijze kleur
       zodat het Check icoon zichtbaar blijft zonder de oranje "voltooid"
       state na te bootsen. De base .ex-check heeft color: transparent; deze
       override maakt het icoon zichtbaar. Werkt in beide thema's via de
       geërfde --muted-foreground variabele. */
    color: oklch(var(--muted-foreground) / 0.55);
  }
.ex-check-done {
    border-color: var(--accent-hex);
    background-color: var(--accent-hex);
    color: #ffffff;
    /* Keep the raised neumorphic shadow on the completed orange state. */
    box-shadow: var(--neomorph-shadow-sm);
  }
.ex-check:hover:not(.ex-check-done) {
    border-color: oklch(var(--muted-foreground) / 0.75);
  }
/* ─── Inline rest timer strip ───────────────────────────────────────────────
      A thick (~36px) orange progress bar that appears UNDER the completed set
      row, with the countdown (mm:ss) centered INSIDE the bar. The bar fill
      advances behind the text. Auto-starts on set completion, disappears when
      timer elapses. NO controls — the timer simply counts down and vanishes. */
.ex-rest-strip {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.25rem 0.25rem 0.125rem;
    animation: ex-rest-strip-in 200ms cubic-bezier(0.4, 0, 0.2, 1);
  }
.ex-rest-bar {
    flex: 1 1 auto;
    height: 36px;
    border-radius: 9999px;
    background-color: oklch(var(--muted) / 0.5);
    overflow: hidden;
    position: relative;
  }
.ex-rest-bar__fill {
    /* LEEGLOOP van rechts naar links: de fill start vol (pct=100%, hele bar
       oranje) en krimpt aan de linkerkant naarmate de tijd verstrijkt, tot
       pct=0% (bar leeg) bij afloop.

       ROBUSTE aanpak (drie verzekeringen gecombineerd):
       1. .ex-rest-bar heeft direction: rtl — absolute right-anchoring
          (right: 0; width: 100%) is deterministisch rechts-geankerd,
          onafhankelijk van de omringende LTR context.
       2. De fill heeft een VASTE width: 100% (altijd de hele bar breed)
          en wordt visueel gekrompen via een inline transform:
          scaleX(pct/100). transform-origin: 100% 50% (expliciete
          percentage-vorm, niet `right center` wat sommige browsers
          interpreteren als de rechterkant van de geschaalde box) anker
          de schaal aan de rechterkant van de originele box, dus bij
          afname van scaleX krimpt de fill aan de linkerkant en verschijnt
          er steeds meer lege ruimte rechts — een echte countdown-richting,
          thema-onafhankelijk en immuun voor box-model/positionering
          quirks die een width-aanpak kunnen breken.
       3. .ex-rest-bar__countdown heeft direction: ltr zodat de mm:ss
          tekst de rtl van de parent niet erft en gecentreerd blijft.

       De scaleX-waarde in ExerciseCard.tsx volgt de leegloop-formule:
       pct = 100 - Math.min(100, (liveElapsed / duration) * 100) — start bij
       1.0 (vol) en daalt naar 0.0 (leeg). right: 0 houdt de fill aan de
       rechterkant verankerd tijdens het schalen. */
    position: absolute;
    top: 0;
    right: 0;
    height: 100%;
    width: 100%;
    border-radius: 9999px;
    background-color: var(--accent-hex);
    /* transform-origin: 100% 50% is de expliciete percentage-vorm van
       `right center` en is deterministisch — sommige browsers
       interpreteren `right center` als de rechterkant van de
       getransformeerde (geschaalde) box in plaats van de originele box,
       waardoor de leegloop-richting kan omdraaien. 100% 50% verwijst
       altijd naar de originele box. */
    transform-origin: 100% 50%;
    /* scaleX wordt inline gezet door de component (leegloop-formule). */
  }
/* Countdown text — centered INSIDE the bar, over the fill. Uses mix-blend
     so the digits stay readable whether the orange fill has reached them or
     not (white text on the muted track, white on the orange fill). */
.ex-rest-bar__countdown {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-family: var(--font-display);
    font-size: 0.875rem;
    font-weight: 700;
    letter-spacing: 0.02em;
    color: #ffffff;
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.45);
    pointer-events: none;
    z-index: 1;
    /* direction: ltr voorkomt dat de countdown-tekst de rtl-richting van
       de parent .ex-rest-bar erft — de mm:ss tekst moet gecentreerd en in
       normale LTR-volgorde blijven, ongeacht de rtl op de container die
       de fill-anchoring verzekert. */
    direction: ltr;
  }
/* ─── "Start rest" knop ────────────────────────────────────────────────────
      Compacte knop die verschijnt onder een voltooide set wanneer de globale
      auto-start setting uit staat. Visueel consistent met de rest-strip:
      accent-kleur, touch-manipulation voor directe tap-response, compacte
      padding. Alleen zichtbaar via JS-gating in SetRowComponent. */
.ex-rest-start-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.375rem;
    padding: 0.375rem 0.75rem;
    margin: 0.25rem 0 0.125rem;
    border: 1px solid oklch(var(--accent) / 0.45);
    border-radius: 9999px;
    background-color: oklch(var(--accent) / 0.12);
    color: var(--accent-hex);
    font-family: var(--font-display);
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    line-height: 1;
    cursor: pointer;
    touch-action: manipulation;
    -webkit-tap-highlight-color: transparent;
    transition: background-color 150ms ease, border-color 150ms ease, transform
      120ms ease;
  }
.ex-rest-start-btn:hover {
    background-color: oklch(var(--accent) / 0.2);
    border-color: oklch(var(--accent) / 0.65);
  }
.ex-rest-start-btn:active {
    transform: scale(0.97);
  }
.ex-rest-start-btn:focus-visible {
    outline: 2px solid var(--accent-hex);
    outline-offset: 2px;
  }
@keyframes ex-rest-strip-in {
    from {
      opacity: 0;
      transform: translateY(-2px);
    }
    to {
      opacity: 1;
      transform: translateY(0);
    }
  }
/* ─── Ghost "+ Add Set" button ──────────────────────────────────────────────
      No dashed border. Subtle pill container with a light gray fill so the
      action is visible but not dominant. Full-width, centered, compact. */
.ex-add-set-wrap {
    display: flex;
    justify-content: center;
    width: 100%;
    padding: 0 0.25rem;
  }
.ex-add-set-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.375rem;
    width: 100%;
    height: 30px;
    padding: 0 0.75rem;
    margin-top: 0.375rem;
    background-color: oklch(0.26 0 0);
    border: none;
    border-radius: 9999px;
    color: oklch(var(--muted-foreground));
    font-family: var(--font-body);
    font-size: 0.75rem;
    font-weight: 600;
    box-shadow: none;
    transition: color 150ms ease, background-color 150ms ease;
    cursor: pointer;
  }
.ex-add-set-btn:hover:not(:disabled) {
    color: oklch(var(--foreground));
    background-color: oklch(var(--muted) / 0.6);
  }
.ex-add-set-btn:disabled {
    opacity: 0.5;
    cursor: not-allowed;
  }
/* ─── Card shell shared by all three card types ─────────────────────────────
     The actual card surface that hosts the table + add-set button. Subtle
     raised neumorphic-sm surface, rounded-xl, tight padding. */
.ex-card-shell {
  border-radius: 0.75rem;
  background-color: oklch(var(--background));
    box-shadow: var(--neomorph-shadow-sm);
    transition: box-shadow 200ms cubic-bezier(0.4, 0, 0.2, 1);
}
@media (prefers-reduced-motion: reduce) {

  .ex-card-shell {
    transition: none;
    transform: none;
  }
}
@media (prefers-contrast: high) {
  .ex-card-shell {
    border: 1px solid oklch(var(--border));
  }
}
.ex-card-shell {
    padding: 0.625rem 0.625rem 0.5rem;
  }
/* ─── Light-theme overrides for ex-pill-input ────────────────────────────────
      The base .ex-pill-input uses oklch(0.22 0 0) (dark fill) which is unreadable
      in light mode with dark text. These :root:not(.dark) overrides swap the fill
      to a subtle light gray (oklch(0.96 0 0)) and keep the focus accent ring.
      The inset neumorphic shadow is inherited from the base rule (var(--neomorph-inset-sm)
      resolves to the light-theme token here) and is preserved on focus alongside
      the accent ring. */
:root:not(.dark) .ex-pill-input {
    background-color: oklch(0.94 0 0) !important;
    color: oklch(0.15 0 0) !important;
    box-shadow: var(--neomorph-inset-sm) !important;
  }
:root:not(.dark) .ex-pill-input:focus {
    background-color: oklch(0.92 0 0) !important;
    box-shadow: var(--neomorph-inset-sm), 0 0 0 1.5px
      rgba(var(--accent-rgb), 0.55) !important;
  }
:root:not(.dark) .ex-pill-input::-moz-placeholder {
    color: oklch(0.45 0 0 / 0.6) !important;
    opacity: 1 !important;
  }
:root:not(.dark) .ex-pill-input::placeholder {
    color: oklch(0.45 0 0 / 0.6) !important;
    opacity: 1 !important;
  }
/* Light-theme check pending border — darker gray for visibility on light bg */
:root:not(.dark) .ex-check {
    border-color: oklch(0.55 0 0 / 0.5);
  }
/* Light-theme add-set button — subtle light gray fill matching the pill
     inputs so the ghost container reads as a quiet action surface. */
:root:not(.dark) .ex-add-set-btn {
    background-color: oklch(0.94 0 0) !important;
  }
:root:not(.dark) .ex-add-set-btn:hover:not(:disabled) {
    background-color: oklch(var(--muted) / 0.6) !important;
  }
/* ─────────────────────────────────────────────────────────────────────────── */
/* Neumorphic Hover States — scale only, no translateY to avoid layout shifts */
.neomorph-hover {
    transition: box-shadow 200ms cubic-bezier(0.4, 0, 0.2, 1), transform 200ms
      cubic-bezier(0.4, 0, 0.2, 1);
  }
.neomorph-hover:hover {
    box-shadow: var(--neomorph-hover);
    transform: scale(1.01) translateZ(0);
  }
.neomorph-hover:active {
    box-shadow: var(--neomorph-pressed);
    transform: scale(0.99) translateZ(0);
  }
/* Neumorphic Button States — scale only, contain layout to prevent shift */
.neomorph-button {
    box-shadow: var(--neomorph-shadow);
    transition: box-shadow 150ms cubic-bezier(0.4, 0, 0.2, 1), transform 150ms
      cubic-bezier(0.4, 0, 0.2, 1), opacity 150ms cubic-bezier(0.4, 0, 0.2, 1);
    will-change: transform;
    contain: layout style;
  }
.neomorph-button:hover:not(:disabled) {
    box-shadow: var(--neomorph-hover);
    transform: scale(1.02) translateZ(0);
  }
.neomorph-button:active:not(:disabled) {
    box-shadow: var(--neomorph-pressed);
    transform: scale(0.98) translateZ(0);
  }
.neomorph-button:focus-visible {
    outline: 2px solid oklch(var(--accent));
    outline-offset: 2px;
  }
.neomorph-button:disabled {
    opacity: 0.5;
    cursor: not-allowed;
  }
/* Neumorphic Accent Glow — scale only */
.neomorph-accent {
    box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.16), -4px -4px 10px
      rgba(255, 255, 255, 0.9), 0 0 22px oklch(var(--accent) / 0.5);
    transition: box-shadow 400ms cubic-bezier(0.4, 0, 0.2, 1), transform 400ms
      cubic-bezier(0.4, 0, 0.2, 1);
    will-change: transform;
  }
.neomorph-accent:hover {
    box-shadow: 5px 5px 12px rgba(0, 0, 0, 0.18), -5px -5px 12px
      rgba(255, 255, 255, 0.95), 0 0 26px oklch(var(--accent) / 0.6);
    transform: scale(1.02) translateZ(0);
  }
.dark .neomorph-accent {
    box-shadow: 4px 4px 8px rgba(0, 0, 0, 0.45), -4px -4px 8px
      rgba(255, 255, 255, 0.04), 0 0 16px oklch(var(--accent) / 0.4);
  }
.dark .neomorph-accent:hover {
    box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.52), -5px -5px 10px
      rgba(255, 255, 255, 0.05), 0 0 18px oklch(var(--accent) / 0.48);
    transform: scale(1.02) translateZ(0);
  }
/* Neumorphic Pressed State */
/* Template Card — slower transition is fine for card hover */
/* Legacy glass utilities for compatibility */
/* Enhanced Touch Interactions */
.touch-manipulation {
    touch-action: manipulation;
    -webkit-tap-highlight-color: transparent;
    min-height: 44px;
    min-width: 44px;
  }
/* Scroll-list container — disables pull-to-refresh and scroll chaining so
     vertical scroll inside the list (History, Templates, Exercises) doesn't
     trigger the browser's native pull-to-refresh gesture or bubble up to a
     parent scroller. This prevents conflicts with swipe-to-delete on
     ExerciseCard set rows: the page can scroll vertically without the
     browser hijacking the gesture for a refresh, and the JS swipe handlers
     own horizontal panning via touch-action: pan-y on .ex-card-row. */
.scroll-list {
    overscroll-behavior-y: contain;
  }
/* Icon Button Consistent Sizing */
/* Template Card Action Button — contain layout to prevent press from shifting siblings */
.template-action-button {
  flex-shrink: 0;
  touch-action: manipulation;
  border-radius: var(--radius);
  background-color: oklch(var(--background));
    box-shadow: var(--neomorph-shadow);
    transition: box-shadow 150ms cubic-bezier(0.4, 0, 0.2, 1), transform 150ms
      cubic-bezier(0.4, 0, 0.2, 1), opacity 150ms cubic-bezier(0.4, 0, 0.2, 1);
    will-change: transform;
    contain: layout style;
}
.template-action-button:hover:not(:disabled) {
    box-shadow: var(--neomorph-hover);
    transform: scale(1.02) translateZ(0);
  }
.template-action-button:active:not(:disabled) {
    box-shadow: var(--neomorph-pressed);
    transform: scale(0.98) translateZ(0);
  }
.template-action-button:focus-visible {
    outline: 2px solid oklch(var(--accent));
    outline-offset: 2px;
  }
.template-action-button:disabled {
    opacity: 0.5;
    cursor: not-allowed;
  }
.template-action-button {
    touch-action: manipulation;
    -webkit-tap-highlight-color: transparent;
    min-height: 44px;
    min-width: 44px;
  }
@media (prefers-reduced-motion: reduce) {

  .template-action-button {
    transition: none;
    transform: none;
  }
}
.template-action-button {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    padding: 0;
    transition: box-shadow 150ms cubic-bezier(0.4, 0, 0.2, 1), transform 150ms
      cubic-bezier(0.4, 0, 0.2, 1);
    contain: layout style;
  }
.template-action-button:active {
    transform: scale(0.95) translateZ(0);
  }
/* Uniform Input Field Sizing */
/* Consistent Card Sizing */
/* ═══════════════════════════════════════════════════════════════════════════
     PWA INSTALL-FUNNEL LANDING PAGE
     Marketing/install surface shown only to browser visitors. Purely additive
     utilities — reuses existing neumorphic + accent tokens (--accent,
     --accent-hex, --accent-rgb, --neomorph-shadow, --neomorph-hover,
     --neomorph-pressed). No existing tokens modified; works in both :root
     (light) and .dark themes via inherited variables. Style rules: veel
     witruimte, max 2 accent-momenten per scherm, subtiele fade-in bij scrollen,
     snelle laadtijd, mobiel-eerst.
     ═══════════════════════════════════════════════════════════════════════════ */
/* ─── Hero spacing helpers ─────────────────────────────────────────────────
      Generous vertical rhythm for the landing hero and section gaps. Mobile-
      first base values scale up at sm/md/lg via the responsive utilities. */
.landing-hero {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
    min-height: 70vh;
    padding-top: clamp(3rem, 10vh, 6rem);
    padding-bottom: clamp(3rem, 10vh, 6rem);
}
.landing-section {
  width: 100%;
    padding-top: clamp(2.5rem, 7vw, 4rem);
    padding-bottom: clamp(2.5rem, 7vw, 4rem);
}
/* ─── Fade-in-on-scroll utility ────────────────────────────────────────────
      Subtle entrance: opacity 0 → 1 + translateY(12px → 0) over 500ms with a
      soft cubic-bezier. Triggered by an IntersectionObserver adding
      .is-visible (frontend responsibility). Honors prefers-reduced-motion via
      the global rule. No heavy animations, no bounce. */
.fade-in-up {
    opacity: 0;
    transform: translateY(12px);
    transition: opacity 500ms cubic-bezier(0.4, 0, 0.2, 1), transform 500ms
      cubic-bezier(0.4, 0, 0.2, 1);
    will-change: opacity, transform;
  }
.fade-in-up.is-visible {
    opacity: 1;
    transform: translateY(0);
  }
/* Staggered children: apply .fade-in-up-stagger to a parent and
     .fade-in-up to children; each child delays by its index × 80ms (capped at
     6 via the nth-child rules below). Keeps the cascade subtle and fast. */
.fade-in-up-stagger > .fade-in-up:nth-child(1) {
    transition-delay: 0ms;
  }
.fade-in-up-stagger > .fade-in-up:nth-child(2) {
    transition-delay: 80ms;
  }
.fade-in-up-stagger > .fade-in-up:nth-child(3) {
    transition-delay: 160ms;
  }
.fade-in-up-stagger > .fade-in-up:nth-child(4) {
    transition-delay: 240ms;
  }
.fade-in-up-stagger > .fade-in-up:nth-child(5) {
    transition-delay: 320ms;
  }
.fade-in-up-stagger > .fade-in-up:nth-child(6) {
    transition-delay: 400ms;
  }
/* ─── Feature card hover state ─────────────────────────────────────────────
      A landing-specific variant of .neomorph for the 3 feature cards. Reuses
      the existing --neomorph-shadow / --neomorph-hover tokens but adds a
      faint accent ring on hover to signal interactivity without breaking the
      "max 2 accent moments" rule (hover is transient, not a static accent).
      Scale only — no translateY, no layout shift. */
.landing-feature-card {
  border-radius: 1rem;
  background-color: oklch(var(--background));
  padding: 1.25rem;
    box-shadow: var(--neomorph-shadow), var(--neomorph-accent-ring);
    transition: box-shadow 200ms cubic-bezier(0.4, 0, 0.2, 1);
}
@media (prefers-reduced-motion: reduce) {

  .landing-feature-card {
    transition: none;
    transform: none;
  }
}
@media (prefers-contrast: high) {
  .landing-feature-card {
    border: 1px solid oklch(var(--border));
  }
}
@media (min-width: 640px) {

  .landing-feature-card {
    padding: 1.5rem;
  }
}
.landing-feature-card {
    transition: box-shadow 250ms cubic-bezier(0.4, 0, 0.2, 1), transform 250ms
      cubic-bezier(0.4, 0, 0.2, 1), border-color 250ms
      cubic-bezier(0.4, 0, 0.2, 1);
    border: 1px solid transparent;
    will-change: transform;
  }
.landing-feature-card:hover {
    box-shadow: var(--neomorph-hover), 0 0 0 1px rgba(var(--accent-rgb), 0.18);
    transform: scale(1.015) translateZ(0);
  }
.landing-feature-card:active {
    box-shadow: var(--neomorph-pressed);
    transform: scale(0.99) translateZ(0);
  }
/* Signature feature card — the ONE feature card allowed to carry a static
     accent moment (subtle corner glow). Reuses the existing .accent-glow
     radial pattern but tuned softer for the landing context. */
.dark .landing-feature-card--signature::before {
    background: radial-gradient(
      circle,
      rgba(var(--accent-rgb), 0.18) 0%,
      transparent 70%
    );
  }
/* ─── Feature icon well ────────────────────────────────────────────────────
      Small recessed neumorphic circle hosting the feature icon. Reuses
      --neomorph-inset-sm. 44px touch-target-friendly, centered icon. */
.landing-feature-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 9999px;
  background-color: oklch(var(--background));
    box-shadow: var(--neomorph-inset-sm);
    width: 44px;
    height: 44px;
    color: oklch(var(--accent));
    flex-shrink: 0;
}
/* ─── Hero CTA cluster ────────────────────────────────────────────────────
      Primary = neomorph-accent (orange glow, the hero's single accent moment).
      Secondary = flat muted text link, no card, no shadow — keeps the second
      accent slot free for the signature feature card. */
.landing-cta-primary {
  touch-action: manipulation;
  border-radius: 1rem;
    box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.16), -4px -4px 10px
      rgba(255, 255, 255, 0.9), 0 0 22px oklch(var(--accent) / 0.5);
    transition: box-shadow 400ms cubic-bezier(0.4, 0, 0.2, 1), transform 400ms
      cubic-bezier(0.4, 0, 0.2, 1);
    will-change: transform;
}
.landing-cta-primary:hover {
    box-shadow: 5px 5px 12px rgba(0, 0, 0, 0.18), -5px -5px 12px
      rgba(255, 255, 255, 0.95), 0 0 26px oklch(var(--accent) / 0.6);
    transform: scale(1.02) translateZ(0);
  }
.dark .landing-cta-primary {
    box-shadow: 4px 4px 8px rgba(0, 0, 0, 0.45), -4px -4px 8px
      rgba(255, 255, 255, 0.04), 0 0 16px oklch(var(--accent) / 0.4);
  }
.dark .landing-cta-primary:hover {
    box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.52), -5px -5px 10px
      rgba(255, 255, 255, 0.05), 0 0 18px oklch(var(--accent) / 0.48);
    transform: scale(1.02) translateZ(0);
  }
.landing-cta-primary {
    touch-action: manipulation;
    -webkit-tap-highlight-color: transparent;
    min-width: 44px;
    background-color: var(--accent-hex);
    color: #ffffff;
    font-family: var(--font-display);
    font-weight: 700;
    padding: 0.875rem 2rem;
    min-height: 52px;
    box-shadow: 0 0 0 1px rgba(var(--accent-rgb), 0.4), 0 8px 24px
      rgba(var(--accent-rgb), 0.35), 0 0 22px oklch(var(--accent) / 0.5);
  }
.dark .landing-cta-primary {
    background-color: var(--accent-hex);
    color: #ffffff;
    box-shadow: 0 0 0 1px rgba(var(--accent-rgb), 0.5), 0 8px 24px
      rgba(var(--accent-rgb), 0.4), 0 0 18px oklch(var(--accent) / 0.45);
  }
.landing-cta-secondary {
    touch-action: manipulation;
    -webkit-tap-highlight-color: transparent;
    min-width: 44px;
    background: transparent;
    color: oklch(var(--muted-foreground));
    font-family: var(--font-body);
    font-weight: 500;
    padding: 0.75rem 1.25rem;
    min-height: 44px;
    transition: color 200ms cubic-bezier(0.4, 0, 0.2, 1);
}
.landing-cta-secondary:hover {
    color: oklch(var(--foreground));
  }
/* ─── Accent CTA pill (accountability block) ──────────────────────────────
      A compact accent pill for mid-page conversion nudges. Smaller than the
      hero CTA so it doesn't compete — uses accent-dim fill + accent text,
      no glow, keeping the "max 2 accent moments" budget intact. */
/* ─── FAQ collapsible row ─────────────────────────────────────────────────
      Minimal neumorphic-sm row for the FAQ section. Privacy lives here as a
      single FAQ question (per user preference) — not in the emotional core.
      Uses .neomorph-sm for a quiet raised surface; chevron rotates on open. */
.landing-faq-row {
  border-radius: 0.75rem;
  background-color: oklch(var(--background));
  padding-left: 1rem;
  padding-right: 1rem;
  padding-top: 0.75rem;
  padding-bottom: 0.75rem;
    box-shadow: var(--neomorph-shadow-sm);
    transition: box-shadow 200ms cubic-bezier(0.4, 0, 0.2, 1);
}
@media (prefers-reduced-motion: reduce) {

  .landing-faq-row {
    transition: none;
    transform: none;
  }
}
@media (prefers-contrast: high) {
  .landing-faq-row {
    border: 1px solid oklch(var(--border));
  }
}
.landing-faq-row {
    transition: box-shadow 200ms cubic-bezier(0.4, 0, 0.2, 1);
  }
.landing-faq-row[aria-expanded="true"] {
    box-shadow: var(--neomorph-inset-sm);
  }
/* ─── Footer ──────────────────────────────────────────────────────────────
      Quiet, low-contrast footer. Privacy link + minimal nav. No card, no
      shadow — sits flat on bg-background with a top border for separation. */
.landing-footer {
  width: 100%;
  border-top-width: 1px;
    border-color: oklch(var(--border) / 0.5);
    padding-top: clamp(2rem, 5vw, 3rem);
    padding-bottom: clamp(2rem, 5vw, 3rem);
}
/* ═══════════════════════════════════════════════════════════════════════════
     PREMIUM LANDING — gravl.ai-level marketing page utilities.
     Purely additive — reuses existing --accent / --accent-hex / --accent-rgb /
     --accent-dim / --neomorph-* tokens and inherited :root + .dark variables.
     No existing tokens modified. Mobile-first; clamp-based scaling for desktop.
     Rules: veel witruimte, max 2 accent-momenten per scherm, subtiele fade-in,
     mobiel-eerst, werkt in licht én donker.
     ═══════════════════════════════════════════════════════════════════════════ */
/* ─── Premium hero typography scale ────────────────────────────────────────
     Very bold display with breathing room. Space Grotesk, tight tracking,
     clamp-based so it scales from mobile (~2.5rem) to desktop (~5.5rem) without
     overflowing. Line-height 1.05 keeps the three-word headline tight. The
     .landing-hero-headline--accent span carries the single accent word ("Groei.")
     — counts as accent moment #1 alongside the hero CTA. */
.landing-hero-headline {
    font-family: var(--font-display);
    font-weight: 700;
    letter-spacing: -0.03em;
    line-height: 1.05;
    font-size: clamp(2.5rem, 7vw, 5.5rem);
    color: oklch(var(--foreground));
  }
.landing-hero-subline {
    font-family: var(--font-body);
    font-weight: 400;
    line-height: 1.55;
    font-size: clamp(1rem, 2.2vw, 1.25rem);
    color: oklch(var(--muted-foreground));
    max-width: 42ch;
  }
/* ─── Section headline scale (feature/accountability/install) ──────────────
     Slightly smaller than hero but still bold and confident. Tight tracking,
     clamp 1.75rem→2.75rem. Used for feature section titles, accountability
     block headline, and install section headline. */
.landing-section-headline {
    font-family: var(--font-display);
    font-weight: 700;
    letter-spacing: -0.02em;
    line-height: 1.15;
    font-size: clamp(1.75rem, 4vw, 2.75rem);
    color: oklch(var(--foreground));
  }
.landing-section-body {
    font-family: var(--font-body);
    font-weight: 400;
    line-height: 1.6;
    font-size: clamp(0.95rem, 1.8vw, 1.0625rem);
    color: oklch(var(--muted-foreground));
    max-width: 52ch;
  }
/* ─── CSS phone-frame device mockup ───────────────────────────────────────
     A pure-CSS phone frame with rounded corners, notch, and an inner scrollable
     viewport that hosts read-only rendered app components (ExerciseCard,
     OverloadCurveChart). The frame is a fixed-aspect bezel; the inner viewport
     scrolls vertically with momentum scrolling (like gravl.ai). The
     .landing-phone-glow sibling/parent provides the accent radial behind it.

     .landing-phone            — outer bezel (dark, rounded-[2.5rem], border)
     .landing-phone__notch     — top centered pill notch
     .landing-phone__screen    — inner viewport, overflow-y auto, momentum scroll
     .landing-phone-glow        — absolute radial accent glow positioned behind

     Sizes are clamp-based: ~280px wide on mobile, ~340px on desktop. Aspect
     ratio ~9/19.5 kept via aspect-ratio so it never collapses. */
.landing-phone {
    position: relative;
    width: clamp(260px, 32vw, 340px);
    aspect-ratio: 9 / 19.5;
    border-radius: 2.5rem;
    background-color: oklch(var(--card));
    border: 1px solid oklch(var(--border) / 0.7);
    box-shadow: var(--neomorph-shadow-xl);
    padding: 0.5rem;
    overflow: hidden;
    flex-shrink: 0;
  }
.dark .landing-phone {
    background-color: #161616;
    border-color: oklch(var(--border) / 0.5);
  }
.landing-phone__notch {
    position: absolute;
    top: 0.5rem;
    left: 50%;
    transform: translateX(-50%);
    width: 32%;
    height: 1.25rem;
    border-radius: 0 0 1rem 1rem;
    background-color: #0a0a0a;
    z-index: 2;
    pointer-events: none;
  }
.landing-phone__screen {
    position: relative;
    width: 100%;
    height: 100%;
    border-radius: 2rem;
    background-color: oklch(var(--background));
    overflow-y: auto;
    overflow-x: hidden;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    padding: 2rem 0.75rem 0.75rem;
  }
.landing-phone__screen::-webkit-scrollbar {
    display: none;
  }
/* ─── Accent glow behind the phone ─────────────────────────────────────────
     A large, soft radial accent glow positioned behind the phone frame. Uses
     --accent-rgb so it tints correctly in both themes. This is a decorative
     ambient element — does NOT count as an accent "moment" (it's diffuse, not a
     solid fill). Pointer-events none so it never blocks interaction. */
.landing-phone-glow {
    position: absolute;
    inset: -10% -10% auto auto;
    width: 70%;
    height: 70%;
    border-radius: 50%;
    background: radial-gradient(
      circle,
      rgba(var(--accent-rgb), 0.16) 0%,
      transparent 65%
    );
    pointer-events: none;
    z-index: 0;
    filter: blur(8px);
    transform: translateZ(0);
  }
.dark .landing-phone-glow {
    background: radial-gradient(
      circle,
      rgba(var(--accent-rgb), 0.22) 0%,
      transparent 65%
    );
  }
/* ─── Alternating feature-section layout helpers ──────────────────────────
     Mobile-first: every feature section stacks text-above-mini-render (per user
     preference — text first on mobile). On md+ desktop, sections alternate
     left/right via .landing-feature-row--reverse (row-reverse). The mini-render
     lives in a neomorph-sm well so it reads as a real product snippet, not a
     screenshot.

     .landing-feature-row            — grid, 1 col mobile, 2 col md+
     .landing-feature-row--reverse   — md+ row-reverse for alternation
     .landing-feature-row__text      — text column (headline + body + icon)
     .landing-feature-row__render    — mini-render column
     .landing-mini-render            — neomorph-sm well hosting the mini-render
  */
.landing-feature-row {
    display: grid;
    grid-template-columns: 1fr;
    gap: clamp(1.5rem, 3vw, 2.5rem);
    align-items: center;
  }
@media (min-width: 768px) {
    .landing-feature-row {
      grid-template-columns: 1fr 1fr;
      gap: clamp(2.5rem, 5vw, 4rem);
    }
    .landing-feature-row--reverse {
      direction: rtl;
    }
    .landing-feature-row--reverse > * {
      direction: ltr;
    }
  }
.landing-feature-row__text {
    display: flex;
    flex-direction: column;
    gap: 0.875rem;
  }
.landing-feature-row__render {
    display: flex;
    justify-content: center;
    align-items: center;
  }
.landing-mini-render {
  border-radius: 1rem;
  background-color: oklch(var(--background));
    box-shadow: var(--neomorph-shadow-sm);
    transition: box-shadow 200ms cubic-bezier(0.4, 0, 0.2, 1);
}
@media (prefers-reduced-motion: reduce) {

  .landing-mini-render {
    transition: none;
    transform: none;
  }
}
@media (prefers-contrast: high) {
  .landing-mini-render {
    border: 1px solid oklch(var(--border));
  }
}
.landing-mini-render {
    width: 100%;
    max-width: 360px;
    padding: 1rem;
  }
/* ─── Accountability block (emotional core) ──────────────────────────────
     A large, wide neomorph card carrying the emotional headline. Generous
     padding (clamp 2.5rem→4rem), centered text, the headline in display font,
     and three short muted lines beneath. This is the page's emotional anchor —
     no accent fill here (keeps the 2-accent budget for hero CTA + signature
     feature card). The .landing-cta-pill can appear centered below if desired. */
/* ─── Privacy manifest block (replaces accountability) ───────────────────
     Same neomorph card treatment as the former accountability block so the
     page rhythm is preserved. Shield icon in an inset circle, display
     headline, three short lines, and one closing muted line. No accent fill —
     keeps the 2-accent budget for hero CTA + signature feature card. */
.landing-privacy {
  border-radius: 1.5rem;
  background-color: oklch(var(--background));
    box-shadow: var(--neomorph-shadow), var(--neomorph-accent-ring);
    transition: box-shadow 200ms cubic-bezier(0.4, 0, 0.2, 1);
}
@media (prefers-reduced-motion: reduce) {

  .landing-privacy {
    transition: none;
    transform: none;
  }
}
@media (prefers-contrast: high) {
  .landing-privacy {
    border: 1px solid oklch(var(--border));
  }
}
.landing-privacy {
    padding: clamp(2.5rem, 6vw, 4rem) clamp(1.5rem, 5vw, 3.5rem);
    text-align: center;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1.25rem;
  }
.landing-privacy__headline {
    font-family: var(--font-display);
    font-weight: 700;
    letter-spacing: -0.02em;
    line-height: 1.2;
    font-size: clamp(1.5rem, 4vw, 2.5rem);
    color: oklch(var(--foreground));
    max-width: 24ch;
  }
.landing-privacy__lines {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    font-family: var(--font-body);
    font-size: clamp(0.875rem, 1.8vw, 1rem);
    color: oklch(var(--muted-foreground));
  }
.landing-privacy__closing {
    font-family: var(--font-body);
    font-size: clamp(0.8125rem, 1.6vw, 0.9375rem);
    color: oklch(var(--muted-foreground) / 0.85);
    max-width: 38ch;
    line-height: 1.5;
  }
/* ─── Premium install section card ────────────────────────────────────────
     A centered, elevated neomorph card hosting the platform-detected install
     flow. Larger radius (rounded-3xl) and extra padding to feel premium. The
     install headline uses .landing-section-headline. The accent CTA pill
     (.landing-cta-pill) appears here — does not count against the 2-accent
     budget because it's a tint, not a glow. */
.landing-install-card {
  border-radius: 1.5rem;
  background-color: oklch(var(--background));
    box-shadow: var(--neomorph-shadow-lg), var(--neomorph-accent-ring);
    transition: box-shadow 200ms cubic-bezier(0.4, 0, 0.2, 1);
}
@media (prefers-reduced-motion: reduce) {

  .landing-install-card {
    transition: none;
    transform: none;
  }
}
@media (prefers-contrast: high) {
  .landing-install-card {
    border: 1px solid oklch(var(--border));
  }
}
.landing-install-card {
    padding: clamp(2rem, 5vw, 3.5rem) clamp(1.5rem, 5vw, 3rem);
    max-width: 640px;
    margin-inline: auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1.5rem;
    text-align: center;
  }
.landing-install-steps {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    width: 100%;
    max-width: 360px;
  }
.landing-install-step {
  border-radius: 0.75rem;
  background-color: oklch(var(--background));
    box-shadow: var(--neomorph-shadow-sm);
    transition: box-shadow 200ms cubic-bezier(0.4, 0, 0.2, 1);
}
@media (prefers-reduced-motion: reduce) {

  .landing-install-step {
    transition: none;
    transform: none;
  }
}
@media (prefers-contrast: high) {
  .landing-install-step {
    border: 1px solid oklch(var(--border));
  }
}
.landing-install-step {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.75rem 1rem;
    text-align: left;
  }
.landing-install-step__number {
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 9999px;
  background-color: oklch(var(--background));
    box-shadow: var(--neomorph-inset-sm);
    width: 28px;
    height: 28px;
    flex-shrink: 0;
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 0.8125rem;
    color: oklch(var(--accent));
}
/* ─── Inline Privacy / Voorwaarden collapsibles (footer) ──────────────────
     Compact collapsible summaries living inline in the footer. A summary line
     + "Lees meer" expander that reveals 3-5 lines of inline text. Uses a
     <details>-friendly styling pattern but works with any toggle. The
     [aria-expanded] attribute drives the chevron rotation. No accent fill —
     keeps the footer quiet. */
.landing-inline-legal {
    border-top: 1px solid oklch(var(--border) / 0.4);
    padding-top: 1rem;
    margin-top: 1rem;
  }
.landing-inline-legal__summary {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    cursor: pointer;
    font-family: var(--font-body);
    font-weight: 600;
    font-size: 0.875rem;
    color: oklch(var(--foreground));
    padding: 0.25rem 0;
    list-style: none;
  }
.landing-inline-legal__summary::-webkit-details-marker {
    display: none;
  }
.landing-inline-legal__chevron {
    flex-shrink: 0;
    color: oklch(var(--muted-foreground));
    transition: transform 200ms cubic-bezier(0.4, 0, 0.2, 1);
  }
.landing-inline-legal[open] .landing-inline-legal__chevron,
  .landing-inline-legal__summary[aria-expanded="true"]
    .landing-inline-legal__chevron {
    transform: rotate(180deg);
  }
.landing-inline-legal__body {
    font-family: var(--font-body);
    font-weight: 400;
    font-size: 0.8125rem;
    line-height: 1.6;
    color: oklch(var(--muted-foreground));
    padding: 0.5rem 0 0.75rem;
    max-width: 60ch;
  }
/* ─── Footer brand + tagline ──────────────────────────────────────────────
     The footer brand line: Repstat name in display font + tagline "Log. Train
     samen. Groei." in muted body. Sits above the inline legal collapsibles. */
.landing-footer__brand {
    font-family: var(--font-display);
    font-weight: 700;
    letter-spacing: -0.01em;
    font-size: 1.125rem;
    color: oklch(var(--foreground));
  }
.landing-footer__tagline {
    font-family: var(--font-body);
    font-weight: 400;
    font-size: 0.8125rem;
    color: oklch(var(--muted-foreground));
    margin-top: 0.25rem;
  }
/* ─── Extended fade-in-up variants for premium landing ───────────────────
     The base .fade-in-up (opacity 0→1, translateY 12px→0, 500ms) already exists.
     These variants add a slightly larger translate for hero/headline elements
     (more dramatic entrance) and a smaller translate for inline rows (subtler).
     All honor prefers-reduced-motion via the existing global guard. */
.fade-in-up--lg {
    opacity: 0;
    transform: translateY(20px);
    transition: opacity 600ms cubic-bezier(0.4, 0, 0.2, 1), transform 600ms
      cubic-bezier(0.4, 0, 0.2, 1);
    will-change: opacity, transform;
  }
.fade-in-up--lg.is-visible {
    opacity: 1;
    transform: translateY(0);
  }
.fade-in-up--sm {
    opacity: 0;
    transform: translateY(8px);
    transition: opacity 400ms cubic-bezier(0.4, 0, 0.2, 1), transform 400ms
      cubic-bezier(0.4, 0, 0.2, 1);
    will-change: opacity, transform;
  }
.fade-in-up--sm.is-visible {
    opacity: 1;
    transform: translateY(0);
  }
/* ─── Reduced motion guard ────────────────────────────────────────────────
      Landing fade-in-up is decorative — disable it entirely for users who
      prefer reduced motion. Content appears instantly. */
@media (prefers-reduced-motion: reduce) {
    .fade-in-up,
    .fade-in-up--lg,
    .fade-in-up--sm {
      opacity: 1;
      transform: none;
      transition: none;
    }
    .landing-feature-card,
    .landing-cta-primary,
    .landing-cta-pill,
    .landing-cta-secondary,
    .landing-inline-legal__chevron {
      transition: none;
    }
  }
/* ═══════════════════════════════════════════════════════════════════════════
     EXTENDED LANDING — sticky nav, feature grid, social proof, pricing.
     Purely additive — reuses existing --accent-hex / --accent-rgb /
     --accent-dim / --neomorph-* / --font-display / --font-body tokens.
     No existing tokens modified. Mobile-first; clamp-based scaling.
     Rules: neumorphic dark + oranje accent, max 2 accent-momenten per scherm,
     subtiele fade-in, premium gamified look consistent met de app.
     ═══════════════════════════════════════════════════════════════════════════ */
/* ─── Sticky header / nav ──────────────────────────────────────────────────
      Sticky top header met REPSTAT logo links, anker-links naar secties in
      het midden (verborgen op mobile), en een oranje accent CTA rechts.
      Neumorphic dark bg met backdrop-blur voor premium feel. Blijft zichtbaar
      bij scrollen. Mobile: alleen logo + CTA; md+: logo + links + CTA. */
.landing-nav {
    position: sticky;
    top: 0;
    z-index: 50;
    width: 100%;
    background-color: oklch(var(--background) / 0.82);
    backdrop-filter: blur(14px) saturate(140%);
    -webkit-backdrop-filter: blur(14px) saturate(140%);
    border-bottom: 1px solid oklch(var(--border) / 0.4);
    padding: 0.75rem clamp(1rem, 4vw, 2rem);
    transition: box-shadow 250ms cubic-bezier(0.4, 0, 0.2, 1), background-color
      250ms cubic-bezier(0.4, 0, 0.2, 1);
  }
.landing-nav.is-scrolled {
    box-shadow: var(--neomorph-shadow-sm);
    background-color: oklch(var(--background) / 0.92);
  }
.dark .landing-nav {
    background-color: oklch(var(--background) / 0.78);
    border-bottom-color: oklch(var(--border) / 0.5);
  }
.dark .landing-nav.is-scrolled {
    background-color: oklch(var(--background) / 0.9);
  }
.landing-nav__inner {
    max-width: 1120px;
    margin-inline: auto;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
  }
.landing-nav__logo {
    background: none;
    border: none;
    padding: 0;
    cursor: pointer;
    font-family: var(--font-display);
    font-weight: 700;
    letter-spacing: -0.02em;
    font-size: 1.125rem;
    color: oklch(var(--accent));
    text-decoration: none;
    flex-shrink: 0;
  }
.landing-nav__links {
    display: none;
    align-items: center;
    gap: 1.75rem;
    margin-inline: auto;
  }
.landing-nav__links button {
    font-family: var(--font-body);
    font-weight: 500;
    font-size: 0.875rem;
    color: oklch(var(--muted-foreground));
    text-decoration: none;
    background: none;
    border: none;
    padding: 0;
    cursor: pointer;
    transition: color 200ms cubic-bezier(0.4, 0, 0.2, 1);
  }
.landing-nav__links button:hover {
    color: oklch(var(--foreground));
  }
.landing-nav__cta {
  touch-action: manipulation;
  border-radius: 9999px;
    box-shadow: var(--neomorph-shadow);
    transition: box-shadow 150ms cubic-bezier(0.4, 0, 0.2, 1), transform 150ms
      cubic-bezier(0.4, 0, 0.2, 1), opacity 150ms cubic-bezier(0.4, 0, 0.2, 1);
    will-change: transform;
    contain: layout style;
}
.landing-nav__cta:hover:not(:disabled) {
    box-shadow: var(--neomorph-hover);
    transform: scale(1.02) translateZ(0);
  }
.landing-nav__cta:active:not(:disabled) {
    box-shadow: var(--neomorph-pressed);
    transform: scale(0.98) translateZ(0);
  }
.landing-nav__cta:focus-visible {
    outline: 2px solid oklch(var(--accent));
    outline-offset: 2px;
  }
.landing-nav__cta:disabled {
    opacity: 0.5;
    cursor: not-allowed;
  }
.landing-nav__cta {
    touch-action: manipulation;
    -webkit-tap-highlight-color: transparent;
    min-height: 44px;
    min-width: 44px;
  }
.landing-nav__cta:focus-visible {
    outline: 2px solid oklch(var(--accent));
    outline-offset: 2px;
    border-radius: inherit;
  }
@media (prefers-reduced-motion: reduce) {

  .landing-nav__cta {
    transition: none;
    transform: none;
  }
}
.landing-nav__cta {
    background-color: var(--accent-hex);
    color: #ffffff;
    font-family: var(--font-display);
    font-weight: 600;
    font-size: 0.875rem;
    padding: 0.5rem 1.25rem;
    min-height: 40px;
    box-shadow: 0 0 0 1px rgba(var(--accent-rgb), 0.35), 0 4px 14px
      rgba(var(--accent-rgb), 0.28), 0 0 14px oklch(var(--accent) / 0.35);
    transition: box-shadow 250ms cubic-bezier(0.4, 0, 0.2, 1), transform 250ms
      cubic-bezier(0.4, 0, 0.2, 1);
    flex-shrink: 0;
  }
.landing-nav__cta:hover {
    box-shadow: 0 0 0 1px rgba(var(--accent-rgb), 0.5), 0 6px 18px
      rgba(var(--accent-rgb), 0.38), 0 0 18px oklch(var(--accent) / 0.5);
    transform: translateY(-1px) translateZ(0);
  }
.landing-nav__cta:active {
    box-shadow: var(--neomorph-pressed);
    transform: translateY(0) translateZ(0);
  }
@media (min-width: 768px) {
    .landing-nav__links {
      display: flex;
    }
  }
/* ─── Extended feature grid (6 compact cards) ──────────────────────────────
      Responsive CSS grid: 1 col mobile, 2 col tablet (md), 3 col desktop (lg).
      Elke card is een raised neumorphic surface met een oranje accent icon
      well, titel in Space Grotesk en beschrijving in General Sans (muted).
      Hover: subtiele accent ring (transient, telt niet mee als accent moment). */
.landing-feature-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: clamp(1rem, 2.5vw, 1.5rem);
    max-width: 1120px;
    margin-inline: auto;
    width: 100%;
  }
@media (min-width: 640px) {
    .landing-feature-grid {
      grid-template-columns: repeat(2, 1fr);
    }
  }
@media (min-width: 1024px) {
    .landing-feature-grid {
      grid-template-columns: repeat(3, 1fr);
    }
  }
.landing-feature-card {
  border-radius: 1rem;
  background-color: oklch(var(--background));
    box-shadow: var(--neomorph-shadow), var(--neomorph-accent-ring);
    transition: box-shadow 200ms cubic-bezier(0.4, 0, 0.2, 1);
}
@media (prefers-reduced-motion: reduce) {

  .landing-feature-card {
    transition: none;
    transform: none;
  }
}
@media (prefers-contrast: high) {
  .landing-feature-card {
    border: 1px solid oklch(var(--border));
  }
}
.landing-feature-card {
    padding: clamp(1.25rem, 2.5vw, 1.75rem);
    display: flex;
    flex-direction: column;
    gap: 0.875rem;
    border: 1px solid transparent;
    transition: box-shadow 250ms cubic-bezier(0.4, 0, 0.2, 1), transform 250ms
      cubic-bezier(0.4, 0, 0.2, 1), border-color 250ms
      cubic-bezier(0.4, 0, 0.2, 1);
    will-change: transform;
  }
.landing-feature-card:hover {
    box-shadow: var(--neomorph-hover), 0 0 0 1px rgba(var(--accent-rgb), 0.18);
    transform: translateY(-2px) translateZ(0);
  }
.landing-feature-card:active {
    box-shadow: var(--neomorph-pressed);
    transform: translateY(0) translateZ(0);
  }
.landing-feature-card__icon {
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 0.75rem;
    box-shadow: var(--neomorph-inset-sm);
    width: 48px;
    height: 48px;
    color: oklch(var(--accent));
    flex-shrink: 0;
    background-color: oklch(var(--background));
}
.landing-feature-card__title {
    font-family: var(--font-display);
    font-weight: 700;
    letter-spacing: -0.01em;
    font-size: clamp(1rem, 2vw, 1.125rem);
    line-height: 1.25;
    color: oklch(var(--foreground));
  }
.landing-feature-card__desc {
    font-family: var(--font-body);
    font-weight: 400;
    font-size: 0.875rem;
    line-height: 1.55;
    color: oklch(var(--muted-foreground));
  }
/* ─── Social proof sectie ──────────────────────────────────────────────────
      Sectie met gebruikersaantal (groot oranje getal), gemiddelde rating
      (sterren + waarde + count) en drie placeholder testimonials in een
      responsive grid (1 col mobile, 3 col desktop). Testimonials in
      neumorphic cards met avatar-initialen in oranje accent cirkel. */
.landing-social-proof {
  width: 100%;
    padding-top: clamp(2.5rem, 7vw, 4rem);
    padding-bottom: clamp(2.5rem, 7vw, 4rem);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: clamp(2rem, 5vw, 3.5rem);
    max-width: 1120px;
    margin-inline: auto;
}
.landing-social-proof__stat {
    font-family: var(--font-display);
    font-weight: 700;
    letter-spacing: -0.03em;
    line-height: 1;
    font-size: clamp(2.5rem, 7vw, 4rem);
    color: oklch(var(--accent));
  }
.landing-social-proof__stat-label {
    font-family: var(--font-body);
    font-weight: 500;
    font-size: clamp(0.875rem, 1.8vw, 1rem);
    color: oklch(var(--muted-foreground));
    margin-top: 0.5rem;
    text-align: center;
  }
.landing-rating {
    display: flex;
    align-items: center;
    gap: 0.625rem;
    flex-wrap: wrap;
    justify-content: center;
  }
.landing-rating__stars {
    display: inline-flex;
    align-items: center;
    gap: 0.125rem;
    color: oklch(var(--accent));
    filter: drop-shadow(0 0 6px rgba(var(--accent-rgb), 0.35));
  }
.landing-rating__value {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 1.0625rem;
    color: oklch(var(--foreground));
  }
.landing-rating__count {
    font-family: var(--font-body);
    font-weight: 400;
    font-size: 0.875rem;
    color: oklch(var(--muted-foreground));
  }
.landing-testimonials {
    display: grid;
    grid-template-columns: 1fr;
    gap: clamp(1rem, 2.5vw, 1.5rem);
    width: 100%;
  }
@media (min-width: 1024px) {
    .landing-testimonials {
      grid-template-columns: repeat(3, 1fr);
    }
  }
.landing-testimonial {
  border-radius: 1rem;
  background-color: oklch(var(--background));
    box-shadow: var(--neomorph-shadow), var(--neomorph-accent-ring);
    transition: box-shadow 200ms cubic-bezier(0.4, 0, 0.2, 1);
}
@media (prefers-reduced-motion: reduce) {

  .landing-testimonial {
    transition: none;
    transform: none;
  }
}
@media (prefers-contrast: high) {
  .landing-testimonial {
    border: 1px solid oklch(var(--border));
  }
}
.landing-testimonial {
    padding: clamp(1.25rem, 2.5vw, 1.75rem);
    display: flex;
    flex-direction: column;
    gap: 1rem;
    transition: box-shadow 250ms cubic-bezier(0.4, 0, 0.2, 1), transform 250ms
      cubic-bezier(0.4, 0, 0.2, 1);
  }
.landing-testimonial:hover {
    box-shadow: var(--neomorph-hover);
    transform: translateY(-2px) translateZ(0);
  }
.landing-testimonial__avatar {
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 9999px;
    box-shadow: var(--neomorph-inset-sm);
    width: 44px;
    height: 44px;
    flex-shrink: 0;
    background-color: rgba(var(--accent-rgb), 0.14);
    color: oklch(var(--accent));
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 0.9375rem;
    letter-spacing: 0.02em;
}
.landing-testimonial__quote {
    font-family: var(--font-body);
    font-weight: 400;
    font-style: italic;
    font-size: 0.9375rem;
    line-height: 1.6;
    color: oklch(var(--foreground));
  }
.landing-testimonial__name {
    font-family: var(--font-display);
    font-weight: 600;
    font-size: 0.875rem;
    color: oklch(var(--foreground));
    margin-top: auto;
  }
/* ─── Pricing sectie ───────────────────────────────────────────────────────
      Eén pricing card die duidelijk maakt dat Repstat gratis is, gehost op
      Internet Computer. Neumorphic card met oranje accent rand/glow (dit is
      het tweede accent moment naast de hero CTA). Bevat badge "Gratis",
      grote prijs, korte uitleg, feature-lijst met checkmarks en CTA. */
.landing-pricing {
  width: 100%;
    padding-top: clamp(2.5rem, 7vw, 4rem);
    padding-bottom: clamp(2.5rem, 7vw, 4rem);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
}
.landing-pricing-card {
  border-radius: 1.5rem;
  background-color: oklch(var(--background));
    box-shadow: var(--neomorph-shadow-lg), var(--neomorph-accent-ring);
    transition: box-shadow 200ms cubic-bezier(0.4, 0, 0.2, 1);
}
@media (prefers-reduced-motion: reduce) {

  .landing-pricing-card {
    transition: none;
    transform: none;
  }
}
@media (prefers-contrast: high) {
  .landing-pricing-card {
    border: 1px solid oklch(var(--border));
  }
}
.landing-pricing-card {
    position: relative;
    max-width: 480px;
    width: 100%;
    padding: clamp(2rem, 5vw, 3rem) clamp(1.5rem, 4vw, 2.5rem);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1.25rem;
    text-align: center;
    border: 1px solid rgba(var(--accent-rgb), 0.35);
    box-shadow: var(--neomorph-shadow-xl), 0 0 0 1px
      rgba(var(--accent-rgb), 0.2), 0 0 32px rgba(var(--accent-rgb), 0.18);
  }
.dark .landing-pricing-card {
    border-color: rgba(var(--accent-rgb), 0.45);
    box-shadow: var(--neomorph-shadow-xl), 0 0 0 1px
      rgba(var(--accent-rgb), 0.3), 0 0 36px rgba(var(--accent-rgb), 0.22);
  }
.landing-pricing-card__badge {
    touch-action: manipulation;
    -webkit-tap-highlight-color: transparent;
    min-height: 44px;
    min-width: 44px;
    display: inline-flex;
    align-items: center;
    padding: 0.375rem 1rem;
    border-radius: 9999px;
    background-color: var(--accent-hex);
    color: #ffffff;
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 0.75rem;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    box-shadow: 0 0 0 1px rgba(var(--accent-rgb), 0.4), 0 4px 12px
      rgba(var(--accent-rgb), 0.3), 0 0 14px oklch(var(--accent) / 0.35);
}
.landing-pricing-card__price {
    font-family: var(--font-display);
    font-weight: 700;
    letter-spacing: -0.03em;
    line-height: 1;
    font-size: clamp(3rem, 8vw, 4.5rem);
    color: oklch(var(--foreground));
  }
.landing-pricing-card__price-desc {
    font-family: var(--font-body);
    font-weight: 400;
    font-size: clamp(0.9375rem, 2vw, 1.0625rem);
    line-height: 1.55;
    color: oklch(var(--muted-foreground));
    max-width: 36ch;
  }
.landing-pricing-card__features {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    width: 100%;
    max-width: 360px;
    margin-top: 0.5rem;
  }
.landing-pricing-card__feature {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    font-family: var(--font-body);
    font-weight: 500;
    font-size: 0.9375rem;
    color: oklch(var(--foreground));
    text-align: left;
  }
.landing-pricing-card__feature::before {
    content: "✓";
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 9999px;
    box-shadow: var(--neomorph-inset-sm);
    width: 24px;
    height: 24px;
    flex-shrink: 0;
    color: oklch(var(--accent));
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 0.75rem;
    background-color: oklch(var(--background));
  }
.landing-pricing-card__cta {
  touch-action: manipulation;
  border-radius: 1rem;
    box-shadow: var(--neomorph-shadow);
    transition: box-shadow 150ms cubic-bezier(0.4, 0, 0.2, 1), transform 150ms
      cubic-bezier(0.4, 0, 0.2, 1), opacity 150ms cubic-bezier(0.4, 0, 0.2, 1);
    will-change: transform;
    contain: layout style;
}
.landing-pricing-card__cta:hover:not(:disabled) {
    box-shadow: var(--neomorph-hover);
    transform: scale(1.02) translateZ(0);
  }
.landing-pricing-card__cta:active:not(:disabled) {
    box-shadow: var(--neomorph-pressed);
    transform: scale(0.98) translateZ(0);
  }
.landing-pricing-card__cta:focus-visible {
    outline: 2px solid oklch(var(--accent));
    outline-offset: 2px;
  }
.landing-pricing-card__cta:disabled {
    opacity: 0.5;
    cursor: not-allowed;
  }
.landing-pricing-card__cta {
    touch-action: manipulation;
    -webkit-tap-highlight-color: transparent;
    min-height: 44px;
    min-width: 44px;
  }
.landing-pricing-card__cta:focus-visible {
    outline: 2px solid oklch(var(--accent));
    outline-offset: 2px;
    border-radius: inherit;
  }
@media (prefers-reduced-motion: reduce) {

  .landing-pricing-card__cta {
    transition: none;
    transform: none;
  }
}
.landing-pricing-card__cta {
    background-color: var(--accent-hex);
    color: #ffffff;
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 0.9375rem;
    padding: 0.875rem 2rem;
    min-height: 52px;
    width: 100%;
    max-width: 320px;
    margin-top: 0.5rem;
    box-shadow: 0 0 0 1px rgba(var(--accent-rgb), 0.4), 0 8px 24px
      rgba(var(--accent-rgb), 0.35), 0 0 22px oklch(var(--accent) / 0.5);
    transition: box-shadow 250ms cubic-bezier(0.4, 0, 0.2, 1), transform 250ms
      cubic-bezier(0.4, 0, 0.2, 1);
  }
.landing-pricing-card__cta:hover {
    box-shadow: 0 0 0 1px rgba(var(--accent-rgb), 0.55), 0 10px 28px
      rgba(var(--accent-rgb), 0.42), 0 0 26px oklch(var(--accent) / 0.6);
    transform: translateY(-2px) translateZ(0);
  }
.landing-pricing-card__cta:active {
    box-shadow: var(--neomorph-pressed);
    transform: translateY(0) translateZ(0);
  }
.landing-pricing-card__note {
    font-family: var(--font-body);
    font-weight: 400;
    font-size: 0.8125rem;
    line-height: 1.5;
    color: oklch(var(--muted-foreground) / 0.85);
    max-width: 40ch;
    margin-top: 0.25rem;
  }
/* ─── Reduced motion guard for extended landing ────────────────────────────
      Disable transitions for users who prefer reduced motion. Content appears
      instantly. Mirrors the existing landing reduced-motion guard. */
@media (prefers-reduced-motion: reduce) {
    .landing-nav,
    .landing-nav__cta,
    .landing-feature-card,
    .landing-testimonial,
    .landing-pricing-card__cta {
      transition: none;
    }
  }
/* Focus States for Accessibility */
.focus-ring:focus-visible {
    outline: 2px solid oklch(var(--accent));
    outline-offset: 2px;
    border-radius: inherit;
  }
.will-change-transform {
    will-change: transform;
  }
.will-change-scroll {
    will-change: scroll-position;
  }
.safe-area-inset-top {
    padding-top: env(safe-area-inset-top);
  }
.safe-area-inset-bottom {
    padding-bottom: env(safe-area-inset-bottom);
  }
/* ─── PostWorkoutModal overlay safe-area guard ────────────────────────────
     The shadcn DialogOverlay is `fixed inset-0 z-50 bg-black/50`. When the
     modal closes, the overlay's fade-out animation can race with page
     navigation, leaving a residual semi-transparent overlay over the status
     bar (which only has body hex bg, not covered by HomePage's fixed oklch
     container). This override makes the overlay start BELOW the
     safe-area-inset-top so the status bar region always shows the themed
     background, never the overlay's bg-black/50. Applied globally to all
     Radix Dialog/Sheet/Drawer overlays as defense-in-depth — every modal
     should respect the status bar safe area in a PWA. */
[data-slot="dialog-overlay"],
  [data-slot="sheet-overlay"],
  [data-slot="drawer-overlay"] {
    top: env(safe-area-inset-top) !important;
  }
/* Plan accent color utilities */
/* Optimized fade transitions */
@keyframes fade-in-50 {
    from {
      opacity: 0;
    }
    to {
      opacity: 1;
    }
  }
.fade-in-50 {
    animation: fade-in-50 400ms cubic-bezier(0.4, 0, 0.2, 1);
    will-change: opacity;
  }
/* Zoom animation for modals */
@keyframes zoom-in-95 {
    from {
      transform: scale(0.95) translateZ(0);
      opacity: 0;
    }
    to {
      transform: scale(1) translateZ(0);
      opacity: 1;
    }
  }
.zoom-in-95 {
    animation: zoom-in-95 400ms cubic-bezier(0.4, 0, 0.2, 1);
    will-change: transform, opacity;
  }
/* Neumorphic shimmer animation for loading states */
@keyframes neomorph-shimmer {
    0% {
      background-position: -200% 0;
    }
    100% {
      background-position: 200% 0;
    }
  }
.neomorph-shimmer {
    background: linear-gradient(
      90deg,
      oklch(var(--muted) / 0.3) 0%,
      oklch(var(--muted) / 0.5) 50%,
      oklch(var(--muted) / 0.3) 100%
    );
    background-size: 200% 100%;
    animation: neomorph-shimmer 1.5s cubic-bezier(0.4, 0, 0.2, 1) infinite;
  }
/* Accent Glow — Buddy-tab inspired card styling: subtle orange radial glow in top-right corner */
.accent-glow {
    position: relative;
    overflow: hidden;
  }
.accent-glow::before {
    content: "";
    position: absolute;
    top: -40px;
    right: -40px;
    width: 120px;
    height: 120px;
    border-radius: 50%;
    background: radial-gradient(
      circle,
      oklch(var(--accent) / 0.1) 0%,
      transparent 70%
    );
    pointer-events: none;
    z-index: 0;
    transform: translateZ(0);
  }
/* Trained Exercise Card Accent — left border + subtle glow for exercises performed this month */
.accent-glow-trained {
    position: relative;
    border-left: 4px solid oklch(var(--accent));
  }
.accent-glow-trained::before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    border-radius: inherit;
    box-shadow: inset 0 0 20px oklch(var(--accent) / 0.08);
    pointer-events: none;
    z-index: 0;
  }
.accent-glow-trained::after {
    content: "";
    position: absolute;
    top: -20px;
    left: -20px;
    width: 80px;
    height: 80px;
    border-radius: 50%;
    background: radial-gradient(
      circle,
      oklch(var(--accent) / 0.15) 0%,
      transparent 70%
    );
    pointer-events: none;
    z-index: 0;
  }
/* Dark theme adjustments for trained accent — subtler glow */
.dark .accent-glow-trained {
    border-left: 4px solid oklch(var(--accent));
  }
.dark .accent-glow-trained::before {
    box-shadow: inset 0 0 14px oklch(var(--accent) / 0.08);
  }
.dark .accent-glow-trained::after {
    background: radial-gradient(
      circle,
      oklch(var(--accent) / 0.13) 0%,
      transparent 70%
    );
  }
/* Tooltip Styles */
.tooltip {
  border-radius: var(--radius);
  background-color: oklch(var(--popover));
  padding-left: 0.75rem;
  padding-right: 0.75rem;
  padding-top: 0.5rem;
  padding-bottom: 0.5rem;
  font-size: 0.75rem;
  line-height: 1rem;
  font-weight: 500;
  color: oklch(var(--popover-foreground));
    box-shadow: var(--neomorph-shadow-sm);
    transition: box-shadow 200ms cubic-bezier(0.4, 0, 0.2, 1);
}
@media (prefers-reduced-motion: reduce) {

  .tooltip {
    transition: none;
    transform: none;
  }
}
@media (prefers-contrast: high) {
  .tooltip {
    border: 1px solid oklch(var(--border));
  }
}
.tooltip {
    box-shadow: var(--neomorph-shadow-lg);
    z-index: 9999;
  }
/* ─── Light-theme search input fix (multi-layer override) ─────────────────
     These rules ensure search bars are always light with dark text in the
     light theme, regardless of CSS variable inheritance or specificity issues. */
:root .exercises-search-input,
  :root input.exercises-search-input {
    background-color: #f0edea !important;
    color: #1a1a1a !important;
    caret-color: #1a1a1a !important;
  }
:root .exercises-search-input::-moz-placeholder {
    color: #888888 !important;
    opacity: 1 !important;
  }
:root .exercises-search-input::placeholder {
    color: #888888 !important;
    opacity: 1 !important;
  }
:root .history-search-input,
  :root input.history-search-input {
    background-color: #f0edea !important;
    color: #1a1a1a !important;
    caret-color: #1a1a1a !important;
  }
:root .history-search-input::-moz-placeholder {
    color: #888888 !important;
    opacity: 1 !important;
  }
:root .history-search-input::placeholder {
    color: #888888 !important;
    opacity: 1 !important;
  }
/* Dark theme must remain unchanged — restore dark values */
.dark .exercises-search-input,
  .dark input.exercises-search-input,
  .dark .history-search-input,
  .dark input.history-search-input {
    background-color: oklch(var(--input)) !important;
    color: oklch(var(--foreground)) !important;
    caret-color: oklch(var(--foreground)) !important;
  }
.dark .exercises-search-input::-moz-placeholder, .dark .history-search-input::-moz-placeholder {
    color: oklch(var(--muted-foreground)) !important;
    opacity: 1 !important;
  }
.dark .exercises-search-input::placeholder,
  .dark .history-search-input::placeholder {
    color: oklch(var(--muted-foreground)) !important;
    opacity: 1 !important;
  }
/* ─────────────────────────────────────────────────────────────────────────── */
/* ═══════════════════════════════════════════════════════════════════════════
     FASE 2 — ACHIEVEMENT REVEAL
     Card-flip reveal sequence, rarity hierarchy, celebration moments, countdown
     ring, and haptic-style visual feedback. ALL classes here reuse the existing
     neumorphic + accent tokens (--accent, --accent-hex, --accent-rgb,
     --accent-dim, --neomorph-shadow-*, --neomorph-inset, --neomorph-pressed)
     and work in both :root (light) and .dark themes via the inherited variables.
     No existing tokens are modified — this block is purely additive.
     ═══════════════════════════════════════════════════════════════════════════ */
/* ─── 3D card-flip foundation ───────────────────────────────────────────────
     The reveal card is a .reveal-card wrapper with perspective; the inner
     .reveal-card-inner carries the rotateY transform. .is-revealed flips it.
     backface-visibility hides the back face once flipped. transform-style:
     preserve-3d keeps the two faces in the same 3D space. */
.reveal-card {
    perspective: 1200px;
    -webkit-perspective: 1200px;
  }
.reveal-card.is-revealed .reveal-card-inner {
    transform: rotateY(180deg);
  }
/* Pre-reveal back face: a sealed neumorphic card with a question-mark motif.
     Uses the existing neomorphic raised shadow + accent ring. */
/* ─── Staggered reveal delays (150ms increments) ────────────────────────────
     Applied to .reveal-card to delay the flip start; the 6th step caps a
     6-card batch. Higher indexes wait longer so cards flip in sequence. */
.reveal-delay-1 {
    transition-delay: 0ms;
  }
.reveal-delay-2 {
    transition-delay: 150ms;
  }
.reveal-delay-3 {
    transition-delay: 300ms;
  }
.reveal-delay-4 {
    transition-delay: 450ms;
  }
.reveal-delay-5 {
    transition-delay: 600ms;
  }
.reveal-delay-6 {
    transition-delay: 750ms;
  }
/* ─── Haptic-style visual feedback (scale pulse on flip completion) ─────────
     A short scale pulse plays when a card finishes flipping, simulating a
     haptic "thunk". Applied alongside .is-revealed via the .reveal-pulse
     helper. */
@keyframes reveal-scale-pulse {
    0% {
      transform: rotateY(180deg) scale(1);
    }
    40% {
      transform: rotateY(180deg) scale(1.04);
    }
    100% {
      transform: rotateY(180deg) scale(1);
    }
  }
/* ─── Rarity visual hierarchy ───────────────────────────────────────────────
     Four tiers, escalating accent intensity. All reuse --accent / --accent-hex
     / --accent-rgb so a single token change re-tints the whole hierarchy. */
/* COMMON — subtle ring only, no glow. Recessive tier. */
.rarity-common {
    box-shadow: var(--neomorph-shadow), 0 0 0 1px oklch(var(--border) / 0.6);
  }
/* RARE — accent ring, no glow. The accent first appears. */
.rarity-rare {
    box-shadow: var(--neomorph-shadow), 0 0 0 1.5px
      rgba(var(--accent-rgb), 0.45);
  }
/* EPIC — accent glow (radial corner) + shimmer sweep. */
.rarity-epic {
    position: relative;
    box-shadow: var(--neomorph-shadow-lg), 0 0 0 1.5px
      rgba(var(--accent-rgb), 0.6), 0 0 18px rgba(var(--accent-rgb), 0.25);
  }
.rarity-epic::after {
    content: "";
    position: absolute;
    top: -40px;
    right: -40px;
    width: 120px;
    height: 120px;
    border-radius: 50%;
    background: radial-gradient(
      circle,
      rgba(var(--accent-rgb), 0.22) 0%,
      transparent 70%
    );
    pointer-events: none;
    z-index: 0;
  }
.rarity-epic .reveal-shimmer {
    background: linear-gradient(
      110deg,
      transparent 0%,
      transparent 40%,
      rgba(var(--accent-rgb), 0.18) 50%,
      transparent 60%,
      transparent 100%
    );
    background-size: 250% 100%;
    animation: achievement-shimmer 2.4s cubic-bezier(0.4, 0, 0.2, 1) infinite;
  }
/* LEGENDARY — accent-glow-trained left border + pulsing accent glow. The
     apex tier; the only rarity with continuous motion. */
.rarity-legendary {
    position: relative;
    border-left: 4px solid oklch(var(--accent));
    box-shadow: var(--neomorph-shadow-xl), 0 0 0 1.5px
      rgba(var(--accent-rgb), 0.7), 0 0 26px rgba(var(--accent-rgb), 0.4);
    animation: legendary-pulse 2.2s cubic-bezier(0.4, 0, 0.2, 1) infinite;
  }
.rarity-legendary::before {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: inherit;
    box-shadow: inset 0 0 22px rgba(var(--accent-rgb), 0.12);
    pointer-events: none;
    z-index: 0;
  }
.rarity-legendary::after {
    content: "";
    position: absolute;
    top: -24px;
    left: -24px;
    width: 100px;
    height: 100px;
    border-radius: 50%;
    background: radial-gradient(
      circle,
      rgba(var(--accent-rgb), 0.28) 0%,
      transparent 70%
    );
    pointer-events: none;
    z-index: 0;
    animation: legendary-glow 2.2s cubic-bezier(0.4, 0, 0.2, 1) infinite;
  }
/* Dark-theme tuning: subtler glow so legendary doesn't blow out on near-black. */
.dark .rarity-epic {
    box-shadow: var(--neomorph-shadow-lg), 0 0 0 1.5px
      rgba(var(--accent-rgb), 0.55), 0 0 14px rgba(var(--accent-rgb), 0.2);
  }
.dark .rarity-epic::after {
    background: radial-gradient(
      circle,
      rgba(var(--accent-rgb), 0.18) 0%,
      transparent 70%
    );
  }
.dark .rarity-legendary {
    box-shadow: var(--neomorph-shadow-xl), 0 0 0 1.5px
      rgba(var(--accent-rgb), 0.65), 0 0 20px rgba(var(--accent-rgb), 0.32);
  }
.dark .rarity-legendary::before {
    box-shadow: inset 0 0 16px rgba(var(--accent-rgb), 0.1);
  }
.dark .rarity-legendary::after {
    background: radial-gradient(
      circle,
      rgba(var(--accent-rgb), 0.22) 0%,
      transparent 70%
    );
  }
/* ─── Rarity badges ─────────────────────────────────────────────────────────
     Small pill labels. Color intensity escalates with rarity. */
.rarity-badge {
  display: inline-flex;
  align-items: center;
  border-radius: 9999px;
  padding-left: 0.625rem;
  padding-right: 0.625rem;
  padding-top: 0.125rem;
  padding-bottom: 0.125rem;
  font-size: 0.75rem;
  line-height: 1rem;
  font-weight: 600;
  letter-spacing: 0.025em;
    font-family: var(--font-display);
}
.rarity-badge--common {
    background-color: oklch(var(--muted));
    color: oklch(var(--muted-foreground));
  }
.rarity-badge--rare {
    background-color: rgba(var(--accent-rgb), 0.16);
    color: oklch(var(--accent));
  }
.rarity-badge--epic {
    background-color: rgba(var(--accent-rgb), 0.22);
    color: oklch(var(--accent));
    box-shadow: 0 0 10px rgba(var(--accent-rgb), 0.3);
  }
.rarity-badge--legendary {
    background-color: rgba(var(--accent-rgb), 0.28);
    color: oklch(var(--accent));
    box-shadow: 0 0 14px rgba(var(--accent-rgb), 0.45);
    animation: legendary-pulse 2.2s cubic-bezier(0.4, 0, 0.2, 1) infinite;
  }
/* ─── NEW indicator (first-time reveal) ─────────────────────────────────────
     A small accent dot in the card corner for achievements seen for the first
     time. */
.reveal-new-indicator {
    position: absolute;
    top: 10px;
    right: 10px;
    width: 8px;
    height: 8px;
    border-radius: 9999px;
    background-color: oklch(var(--accent));
    box-shadow: 0 0 8px rgba(var(--accent-rgb), 0.6);
    z-index: 2;
    animation: new-dot-pulse 1.6s cubic-bezier(0.4, 0, 0.2, 1) infinite;
  }
/* ─── Celebration pulse / glow keyframes ────────────────────────────────────
     Used by legendary rarity and rare reward moments. */
@keyframes legendary-pulse {
    0%,
    100% {
      box-shadow: var(--neomorph-shadow-xl), 0 0 0 1.5px
        rgba(var(--accent-rgb), 0.7), 0 0 26px rgba(var(--accent-rgb), 0.4);
    }
    50% {
      box-shadow: var(--neomorph-shadow-xl), 0 0 0 1.5px
        rgba(var(--accent-rgb), 0.85), 0 0 38px rgba(var(--accent-rgb), 0.6);
    }
  }
@keyframes legendary-glow {
    0%,
    100% {
      opacity: 0.7;
      transform: scale(1);
    }
    50% {
      opacity: 1;
      transform: scale(1.12);
    }
  }
@keyframes new-dot-pulse {
    0%,
    100% {
      opacity: 1;
      transform: scale(1);
    }
    50% {
      opacity: 0.6;
      transform: scale(1.3);
    }
  }
/* Celebration burst — a one-shot radial flash played when a legendary/epic
     card flips. Applied to a transparent overlay element inside the card. */
@keyframes celebration-burst {
    0% {
      opacity: 0;
      transform: scale(0.6);
    }
    35% {
      opacity: 0.8;
      transform: scale(1.4);
    }
    100% {
      opacity: 0;
      transform: scale(2.2);
    }
  }
/* Achievement shimmer sweep (used by epic rarity .reveal-shimmer child). */
@keyframes achievement-shimmer {
    0% {
      background-position: 250% 0;
    }
    100% {
      background-position: -250% 0;
    }
  }
/* ─── Countdown ring (auto-dismiss) ─────────────────────────────────────────
     An SVG circle whose stroke-dashoffset animates from 0 → circumference
      over the auto-dismiss duration (45s — MUST match AUTO_DISMISS_MS in
      PostWorkoutModal.tsx). The ring depletes visually to signal remaining
      time. Pause-on-hover: when the dialog carries data-paused="true" the
      animation freezes via animation-play-state: paused so it stays in sync
      with the JS timer (which is also paused on hover). */
@keyframes countdown-ring-deplete {
    from {
      stroke-dashoffset: 0;
    }
    to {
      stroke-dashoffset: var(--countdown-circumference, 188.5);
    }
  }
.countdown-ring__progress {
    fill: none;
    stroke: oklch(var(--accent));
    stroke-width: 3;
    stroke-linecap: round;
    animation: countdown-ring-deplete 45s linear forwards;
  }
/* Pause the countdown ring when the dialog is hovered — keeps the visual
     ring in lockstep with the paused JS close timer. */
[data-paused="true"] .countdown-ring__progress {
    animation-play-state: paused;
  }
.countdown-ring__track {
    fill: none;
    stroke: oklch(var(--muted));
    stroke-width: 3;
    opacity: 0.4;
  }
/* ─── Reveal overlay container ──────────────────────────────────────────────
     The full-screen overlay that hosts the reveal grid. Builds on the existing
     neomorphic + accent tokens; uses bg-background so it inherits theme. */
/* ─── AchievementsPage grid states ──────────────────────────────────────────
     Revealed = full color + accent-glow; unrevealed = grayscale + ??? lock.
     Reuses the existing .accent-glow utility for revealed cards. */
.achievement-card--locked {
    filter: grayscale(1);
    opacity: 0.55;
  }
.achievement-card--locked .achievement-card__icon,
  .achievement-card--locked .achievement-card__title,
  .achievement-card--locked .achievement-card__description {
    filter: blur(2px);
    -webkit-user-select: none;
       -moz-user-select: none;
            user-select: none;
  }
.achievement-card__placeholder {
  display: flex;
  align-items: center;
  justify-content: center;
    font-family: var(--font-display);
    color: oklch(var(--muted-foreground));
    letter-spacing: 0.1em;
}
/* ─── Filter bar pills (AchievementsPage) ───────────────────────────────────
     Reuses .neomorph-button base; active state gets accent ring + tint. */
.filter-pill {
  border-radius: 9999px;
  background-color: oklch(var(--background));
  padding-left: 1rem;
  padding-right: 1rem;
  padding-top: 0.5rem;
  padding-bottom: 0.5rem;
  font-size: 0.875rem;
  line-height: 1.25rem;
  font-weight: 500;
    box-shadow: var(--neomorph-shadow);
    transition: box-shadow 150ms cubic-bezier(0.4, 0, 0.2, 1), transform 150ms
      cubic-bezier(0.4, 0, 0.2, 1), opacity 150ms cubic-bezier(0.4, 0, 0.2, 1);
    will-change: transform;
    contain: layout style;
}
.filter-pill:hover:not(:disabled) {
    box-shadow: var(--neomorph-hover);
    transform: scale(1.02) translateZ(0);
  }
.filter-pill:active:not(:disabled) {
    box-shadow: var(--neomorph-pressed);
    transform: scale(0.98) translateZ(0);
  }
.filter-pill:focus-visible {
    outline: 2px solid oklch(var(--accent));
    outline-offset: 2px;
  }
.filter-pill:disabled {
    opacity: 0.5;
    cursor: not-allowed;
  }
@media (prefers-reduced-motion: reduce) {

  .filter-pill {
    transition: none;
    transform: none;
  }
}
.filter-pill {
    color: oklch(var(--muted-foreground));
  }
.filter-pill.is-active {
    background-color: rgba(var(--accent-rgb), 0.14);
    color: oklch(var(--accent));
    box-shadow: var(--neomorph-shadow), 0 0 0 1.5px rgba(var(--accent-rgb), 0.5);
  }
/* ─── Statistics header (AchievementsPage) ──────────────────────────────────
     Mini rarity-distribution bar. Each segment uses the rarity's accent
     intensity so the chart doubles as a rarity legend. */
.rarity-bar {
  display: flex;
  height: 0.5rem;
  width: 100%;
  overflow: hidden;
  border-radius: 9999px;
    background-color: oklch(var(--muted) / 0.4);
}
.rarity-bar__segment--common {
    background-color: oklch(var(--muted-foreground) / 0.5);
  }
.rarity-bar__segment--rare {
    background-color: rgba(var(--accent-rgb), 0.45);
  }
.rarity-bar__segment--epic {
    background-color: rgba(var(--accent-rgb), 0.7);
  }
.rarity-bar__segment--legendary {
    background-color: oklch(var(--accent));
    box-shadow: 0 0 6px rgba(var(--accent-rgb), 0.5);
  }
/* ═══════════════════════════════════════════════════════════════════════════
     FASE 6 — BUDDY KUDOS
     Strava-style kudos from the buddy activity feed: one kudos per buddy per
     workout. All classes reuse existing neumorphic + accent tokens
     (--accent, --accent-hex, --accent-rgb, --accent-dim, --neomorph-shadow,
     --neomorph-pressed, --neomorph-hover) and work in both :root (light) and
     .dark themes via inherited variables. NO new keyframes or animations —
     native feel only (subtle 200ms box-shadow transitions inherited from
     .neomorph-button). No existing tokens are modified; this block is purely
     additive.
     ═══════════════════════════════════════════════════════════════════════════ */
/* ─── Kudos button ─────────────────────────────────────────────────────────
      Compact 44px touch-target button hosting a heart/thumbs-up icon. Default
      state = recessed neumorphic-button (raised). Active state (.is-active) =
      filled accent with .neomorph-accent glow (Strava-style). One kudos per
      buddy per workout — disabled state (.is-disabled) greys out and locks. */
.kudos-button {
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 9999px;
  background-color: oklch(var(--background));
    box-shadow: var(--neomorph-shadow);
    transition: box-shadow 150ms cubic-bezier(0.4, 0, 0.2, 1), transform 150ms
      cubic-bezier(0.4, 0, 0.2, 1), opacity 150ms cubic-bezier(0.4, 0, 0.2, 1);
    will-change: transform;
    contain: layout style;
}
.kudos-button:hover:not(:disabled) {
    box-shadow: var(--neomorph-hover);
    transform: scale(1.02) translateZ(0);
  }
.kudos-button:active:not(:disabled) {
    box-shadow: var(--neomorph-pressed);
    transform: scale(0.98) translateZ(0);
  }
.kudos-button:focus-visible {
    outline: 2px solid oklch(var(--accent));
    outline-offset: 2px;
  }
.kudos-button:disabled {
    opacity: 0.5;
    cursor: not-allowed;
  }
@media (prefers-reduced-motion: reduce) {

  .kudos-button {
    transition: none;
    transform: none;
  }
}
.kudos-button {
    width: 44px;
    height: 44px;
    padding: 0;
    color: oklch(var(--muted-foreground));
    contain: layout style;
  }
.kudos-button.is-active {
    box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.16), -4px -4px 10px
      rgba(255, 255, 255, 0.9), 0 0 22px oklch(var(--accent) / 0.5);
    transition: box-shadow 400ms cubic-bezier(0.4, 0, 0.2, 1), transform 400ms
      cubic-bezier(0.4, 0, 0.2, 1);
    will-change: transform;
  }
.kudos-button.is-active:hover {
    box-shadow: 5px 5px 12px rgba(0, 0, 0, 0.18), -5px -5px 12px
      rgba(255, 255, 255, 0.95), 0 0 26px oklch(var(--accent) / 0.6);
    transform: scale(1.02) translateZ(0);
  }
.dark .kudos-button.is-active {
    box-shadow: 4px 4px 8px rgba(0, 0, 0, 0.45), -4px -4px 8px
      rgba(255, 255, 255, 0.04), 0 0 16px oklch(var(--accent) / 0.4);
  }
.dark .kudos-button.is-active:hover {
    box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.52), -5px -5px 10px
      rgba(255, 255, 255, 0.05), 0 0 18px oklch(var(--accent) / 0.48);
    transform: scale(1.02) translateZ(0);
  }
.kudos-button.is-active {
    background-color: var(--accent-dim);
    color: var(--accent-hex);
  }
.dark .kudos-button.is-active {
    background-color: rgba(var(--accent-rgb), 0.18);
    color: oklch(var(--accent));
  }
.kudos-button.is-disabled,
  .kudos-button:disabled {
    opacity: 0.45;
    cursor: not-allowed;
    box-shadow: var(--neomorph-shadow-sm);
  }
/* ─── Kudos count badge ────────────────────────────────────────────────────
      Orange pill showing total kudos received. Reuses the established orange
      badge pattern: bg-accent, text-[10px], font-bold, text-accent-foreground,
      rounded-full. Sits next to the kudos button or on a feed card header. */
.kudos-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 9999px;
  background-color: oklch(var(--accent));
  padding-left: 0.5rem;
  padding-right: 0.5rem;
  padding-top: 0.125rem;
  padding-bottom: 0.125rem;
  font-size: 10px;
  font-weight: 700;
  color: oklch(var(--accent-foreground));
    min-width: 20px;
    height: 18px;
    line-height: 1;
    letter-spacing: 0.02em;
    box-shadow: 0 0 8px rgba(var(--accent-rgb), 0.35);
}
.kudos-badge.is-zero {
    background-color: oklch(var(--muted));
    color: oklch(var(--muted-foreground));
    box-shadow: none;
  }
/* ─── Buddy activity feed card ─────────────────────────────────────────────
      Variant of the standard .neomorph card for the buddy activity feed. Adds
      a subtle accent ring on the left edge when the workout has received
      kudos from the current user (visual cue for "already kudos'd"). Layout:
      avatar + buddy name + workout summary + kudos button + count badge. */
.kudos-feed-card {
  border-radius: 1rem;
  background-color: oklch(var(--background));
  padding: 1rem;
    box-shadow: var(--neomorph-shadow), var(--neomorph-accent-ring);
    transition: box-shadow 200ms cubic-bezier(0.4, 0, 0.2, 1);
}
@media (prefers-reduced-motion: reduce) {

  .kudos-feed-card {
    transition: none;
    transform: none;
  }
}
@media (prefers-contrast: high) {
  .kudos-feed-card {
    border: 1px solid oklch(var(--border));
  }
}
.kudos-feed-card {
    position: relative;
  }
.kudos-feed-card.is-kudosd {
    border-left: 3px solid oklch(var(--accent));
    padding-left: calc(1rem - 3px);
  }
.dark .kudos-feed-card.is-kudosd {
    border-left: 3px solid oklch(var(--accent));
  }
/* Avatar slot inside the feed card — round neumorph-sm recessed circle. */
.kudos-feed-card__avatar {
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 9999px;
  background-color: oklch(var(--background));
    box-shadow: var(--neomorph-shadow-sm);
    transition: box-shadow 200ms cubic-bezier(0.4, 0, 0.2, 1);
}
@media (prefers-reduced-motion: reduce) {

  .kudos-feed-card__avatar {
    transition: none;
    transform: none;
  }
}
@media (prefers-contrast: high) {
  .kudos-feed-card__avatar {
    border: 1px solid oklch(var(--border));
  }
}
.kudos-feed-card__avatar {
    width: 40px;
    height: 40px;
    flex-shrink: 0;
    color: oklch(var(--muted-foreground));
    font-family: var(--font-display);
    font-weight: 600;
    font-size: 14px;
  }
/* Workout summary line inside the feed card. */
.kudos-feed-card__summary {
  min-width: 0px;
  flex: 1 1 0%;
}
.kudos-feed-card__name {
  font-size: 0.875rem;
  line-height: 1.25rem;
  font-weight: 600;
    color: oklch(var(--foreground));
}
.kudos-feed-card__workout {
  font-size: 0.75rem;
  line-height: 1rem;
    color: oklch(var(--muted-foreground));
}
.kudos-feed-card__meta {
  font-size: 11px;
    color: oklch(var(--muted-foreground) / 0.7);
}
/* Kudos action cluster: button + badge, right-aligned in the card. */
.kudos-feed-card__action {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.25rem;
    flex-shrink: 0;
}
/* ─── Friends-tab orange badge ─────────────────────────────────────────────
      Small orange dot badge overlaid on the Friends tab in the bottom nav to
      signal pending kudos / new buddy activity. Reuses the orange badge
      pattern (bg-accent, text-[10px], font-bold, text-accent-foreground,
      rounded-full) but smaller — a count pill or a plain dot when count is
      just "new". Positioned absolutely by the parent nav item. */
/* ═══════════════════════════════════════════════════════════════════════════
     FASE 7 — MASTERY METER (per oefening)
     Mastery tab on the Exercise pop-up: a 0-100 mastery score, level name, and
     a round SVG progress ring toward the next level. Reuses existing neumorphic
     + accent tokens (--accent, --accent-hex, --accent-rgb, --accent-dim,
     --neomorph-shadow, --neomorph-inset-sm, --neomorph-shadow-sm) additively.
     The SVG ring mirrors the established quest/season ring pattern (round, not
     linear bar) — same approach as .countdown-ring (rotate -90deg, round
     stroke-linecap, accent stroke, muted track). Level badge intensity scales
     across 5 tiers (Beginner → Master) via escalating accent tint + glow,
     mirroring the rarity-badge hierarchy. Breakdown rows reuse
     .neomorph-inset-sm recessed surfaces. No existing tokens modified; this
     block is purely additive. The only new motion is a subtle functional
     "calculating" pulse on the score during recalc on tab-open (respects
     prefers-reduced-motion via the global rule above).
     ═══════════════════════════════════════════════════════════════════════════ */
/* ─── Mastery score card ──────────────────────────────────────────────────
      Hero card hosting the score, ring, and level badge. Builds on .neomorph
      rounded-2xl bg-background with a subtle accent corner glow (reuses
      .accent-glow ::before radial). The score is the focal point — Space
      Grotesk, large, accent-tinted only when fully calculated. */
.mastery-card {
  border-radius: 1rem;
  background-color: oklch(var(--background));
  padding: 1.25rem;
    box-shadow: var(--neomorph-shadow), var(--neomorph-accent-ring);
    transition: box-shadow 200ms cubic-bezier(0.4, 0, 0.2, 1);
}
@media (prefers-reduced-motion: reduce) {

  .mastery-card {
    transition: none;
    transform: none;
  }
}
@media (prefers-contrast: high) {
  .mastery-card {
    border: 1px solid oklch(var(--border));
  }
}
.mastery-card {
    position: relative;
    overflow: hidden;
  }
/* ─── Mastery SVG progress ring ────────────────────────────────────────────
      Round ring (NOT a linear bar) — mirrors .countdown-ring: rotate -90deg so
      the arc starts at 12 o'clock, round stroke-linecap, accent stroke on a
      muted track. The progress is set via stroke-dasharray / stroke-dashoffset
      inline (computed from the score fraction toward next level). The ring
      container is recessed (.neomorph-inset-sm) so the ring sits in a sculpted
      well. Track = muted/40, progress = accent with a soft accent glow. */
.mastery-ring {
    transform: rotate(-90deg);
    transform-origin: center;
  }
.mastery-ring__track {
    fill: none;
    stroke: oklch(var(--muted));
    stroke-width: 8;
    opacity: 0.4;
  }
.mastery-ring__progress {
    fill: none;
    stroke: oklch(var(--accent));
    stroke-width: 8;
    stroke-linecap: round;
    transition: stroke-dashoffset 600ms cubic-bezier(0.4, 0, 0.2, 1);
    filter: drop-shadow(0 0 4px rgba(var(--accent-rgb), 0.35));
  }
.dark .mastery-ring__progress {
    filter: drop-shadow(0 0 3px rgba(var(--accent-rgb), 0.28));
  }
/* Ring container well — recessed neumorphic circle behind the SVG so the
      ring reads as sculpted depth, not a flat sticker. */
.mastery-ring-well {
  border-radius: 9999px;
    box-shadow: var(--neomorph-inset-sm);
    display: flex;
    align-items: center;
    justify-content: center;
}
/* Center score stack — absolutely positioned over the ring well so the
      number sits dead-center inside the ring. */
.mastery-ring-center {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    pointer-events: none;
  }
.mastery-score {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 2.75rem;
    line-height: 1;
    color: oklch(var(--foreground));
    letter-spacing: -0.02em;
  }
.mastery-level-name {
    font-family: var(--font-display);
    font-weight: 600;
    font-size: 0.875rem;
    color: oklch(var(--accent));
    margin-top: 4px;
    letter-spacing: 0.02em;
  }
/* ─── Level badge — intensity scaling across 5 tiers ──────────────────────
      Mirrors the .rarity-badge--* hierarchy: same pill shape, escalating
      accent tint + glow from Beginner (dimmest) to Master (full accent).
      Intensity scales via background alpha, text color, and box-shadow glow. */
.mastery-level-badge {
  display: inline-flex;
  align-items: center;
  border-radius: 9999px;
  padding-left: 0.625rem;
  padding-right: 0.625rem;
  padding-top: 0.125rem;
  padding-bottom: 0.125rem;
  font-size: 0.75rem;
  line-height: 1rem;
  font-weight: 600;
  letter-spacing: 0.025em;
    font-family: var(--font-display);
}
/* Beginner — most recessive: muted bg, muted-foreground text, no glow */
.mastery-level-badge--beginner {
    background-color: oklch(var(--muted));
    color: oklch(var(--muted-foreground));
  }
/* Novice — faint accent tint, accent text, no glow */
.mastery-level-badge--novice {
    background-color: rgba(var(--accent-rgb), 0.1);
    color: oklch(var(--accent));
  }
/* Intermediate — moderate accent tint, subtle ring */
.mastery-level-badge--intermediate {
    background-color: rgba(var(--accent-rgb), 0.16);
    color: oklch(var(--accent));
    box-shadow: 0 0 0 1px rgba(var(--accent-rgb), 0.25);
  }
/* Advanced — stronger tint + soft glow */
.mastery-level-badge--advanced {
    background-color: rgba(var(--accent-rgb), 0.22);
    color: oklch(var(--accent));
    box-shadow: 0 0 10px rgba(var(--accent-rgb), 0.3);
  }
/* Master — full accent, brightest glow (apex tier) */
.mastery-level-badge--master {
    background-color: rgba(var(--accent-rgb), 0.28);
    color: oklch(var(--accent));
    box-shadow: 0 0 14px rgba(var(--accent-rgb), 0.45);
  }
/* ─── Breakdown list rows ──────────────────────────────────────────────────
      Each row is a recessed .neomorph-inset-sm surface with a label, a score
      chip, and a thin mini segment bar whose orange fill intensity matches the
      factor's contribution. Reuses the rarity-bar segment intensity pattern. */
.mastery-breakdown-row {
  border-radius: 0.75rem;
  padding-left: 0.75rem;
  padding-right: 0.75rem;
  padding-top: 0.625rem;
  padding-bottom: 0.625rem;
    box-shadow: var(--neomorph-inset-sm);
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.mastery-breakdown-row__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
  }
.mastery-breakdown-row__label {
    font-family: var(--font-body);
    font-size: 0.8125rem;
    font-weight: 500;
    color: oklch(var(--foreground) / 0.88);
  }
.mastery-breakdown-row__value {
    font-family: var(--font-display);
    font-size: 0.8125rem;
    font-weight: 600;
    color: oklch(var(--muted-foreground));
    letter-spacing: 0.01em;
  }
/* Mini segment bar — thin (4px) rounded track with an accent fill whose
      width = the factor's percentage. Fill intensity scales with the value:
      low scores use a dimmer accent, high scores use full accent + glow. */
.mastery-breakdown-bar {
  display: flex;
  height: 0.25rem;
  width: 100%;
  overflow: hidden;
  border-radius: 9999px;
    background-color: oklch(var(--muted) / 0.4);
}
.mastery-breakdown-bar__fill {
    background-color: oklch(var(--accent));
    border-radius: 9999px;
    transition: width 500ms cubic-bezier(0.4, 0, 0.2, 1);
  }
/* Low-contribution fill (< 40%) — dimmer accent, no glow */
.mastery-breakdown-bar__fill--low {
    background-color: rgba(var(--accent-rgb), 0.45);
  }
/* Mid-contribution fill (40-70%) — accent, no glow */
.mastery-breakdown-bar__fill--mid {
    background-color: oklch(var(--accent));
  }
/* High-contribution fill (> 70%) — accent + soft glow */
.mastery-breakdown-bar__fill--high {
    background-color: oklch(var(--accent));
    box-shadow: 0 0 6px rgba(var(--accent-rgb), 0.5);
  }
/* ─── Calculating indicator ────────────────────────────────────────────────
      A subtle functional pulse shown on the score while the mastery is being
      recalculated on tab-open. The ONLY new motion in this block — mirrors
      the user preference for "no fancy custom UI, no animaties" with the
      explicit exception that a subtle pulse during recalc is functional.
      Respects prefers-reduced-motion via the global rule at the bottom of this
      file. */
.mastery-calculating .mastery-score {
    animation: mastery-calculating-pulse 1.2s cubic-bezier(0.4, 0, 0.2, 1)
      infinite;
  }
.mastery-calculating-dot {
    display: inline-block;
    width: 6px;
    height: 6px;
    border-radius: 9999px;
    background-color: oklch(var(--accent));
    box-shadow: 0 0 6px rgba(var(--accent-rgb), 0.5);
    animation: mastery-calculating-pulse 1.2s cubic-bezier(0.4, 0, 0.2, 1)
      infinite;
  }
@keyframes mastery-calculating-pulse {
    0%,
    100% {
      opacity: 0.55;
    }
    50% {
      opacity: 1;
    }
  }
/* ═══════════════════════════════════════════════════════════════════════════
     FASE 3 STATS — Fatigue vs Fitness + Push/Pull/Legs donut + Overload nav
     Additive utilities (Phase: Fase 3 Stats tab upgrade). Reuses existing
     --accent-hex / --accent-rgb / --neomorph-shadow / --neomorph-inset-sm
     tokens plus the new --ff-* / --ppl-* / --ol-* tokens defined above. Mirrors
     the .mw-* Fase 1 block structure for consistency: KPI cards (inset well),
     gradient fills under chart lines, TSB indicator, color-coded alert box,
     donut ring well + arc glow + in-ring percentage labels, nav-card + sparkline
     preview area. All classes are additive — no existing classes or tokens
     modified.
     ═══════════════════════════════════════════════════════════════════════════ */
/* ─── KPI card (Fitness / Vermoeidheid value card) ───────────────────────────
     Neumorphic raised card (rounded-xl) hosting an icon + label + value + trend
     pijl. The value sits inside an inset well (--ff-kpi-well) so it reads as a
     sculpted recess — same depth language as .mw-ring-well / .wq-ring-well.
     Padding matches .mw-insight for visual rhythm. */
.ff-kpi {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    padding: 0.75rem 0.875rem;
    border-radius: 0.75rem;
    background-color: oklch(var(--card));
    box-shadow: var(--neomorph-shadow-sm);
    overflow: hidden;
  }
/* KPI header row — icon + label left, trend pijl right. */
.ff-kpi__header {
    display: flex;
    align-items: center;
    gap: 0.5rem;
  }
/* KPI icon — small square (28px) accent-tinted background with colored icon.
     Color driven by --ff-kpi-rgb set on the card root (fitness=blauw,
     fatigue=rood). Mirrors .mw-insight__icon shape. */
.ff-kpi__icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border-radius: 8px;
    background-color: rgba(var(--ff-kpi-rgb, var(--accent-rgb)), 0.14);
    color: rgb(var(--ff-kpi-rgb, var(--accent-rgb)));
    flex-shrink: 0;
  }
/* KPI label — tiny uppercase letter-spaced muted. */
.ff-kpi__label {
    font-family: var(--font-body);
    font-size: 0.625rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: oklch(var(--muted-foreground));
    line-height: 1;
    flex: 1 1 auto;
    min-width: 0;
  }
/* KPI trend pijl — small ↑/↓/→ indicator + delta value. Color reflects
     direction: green for positive fitness / reduced fatigue, red for negative. */
.ff-kpi__trend {
    display: inline-flex;
    align-items: center;
    gap: 0.2rem;
    font-family: var(--font-display);
    font-size: 0.6875rem;
    font-weight: 700;
    line-height: 1;
    flex-shrink: 0;
  }
.ff-kpi__trend--up {
    color: rgb(var(--ff-alert-green-rgb));
  }
.ff-kpi__trend--down {
    color: rgb(var(--ff-alert-red-rgb));
  }
.ff-kpi__trend--flat {
    color: oklch(var(--muted-foreground));
  }
/* KPI value well — inset recess hosting the big number. Mirrors .mw-ring-well
     / .wq-ring-well depth language (rectangular, rounded-lg). */
.ff-kpi__value-well {
    display: flex;
    align-items: baseline;
    gap: 0.25rem;
    padding: 0.5rem 0.75rem;
    border-radius: 0.5rem;
    background-color: oklch(var(--background));
    box-shadow: var(--ff-kpi-well);
  }
.ff-kpi__value {
    font-family: var(--font-display);
    font-size: 1.25rem;
    font-weight: 700;
    color: oklch(var(--foreground));
    line-height: 1.1;
    letter-spacing: -0.01em;
  }
.ff-kpi__unit {
    font-family: var(--font-body);
    font-size: 0.6875rem;
    font-weight: 500;
    color: oklch(var(--muted-foreground));
    line-height: 1;
  }
/* ─── Fatigue vs Fitness chart gradient fills ───────────────────────────────
     Applied to the SVG <defs> linearGradient stops under the ATL (fitness) and
     CTL (fatigue) lines. The gradient fades from the line color (top, opaque)
     to transparent (bottom) so the fill reads as a soft area under the curve.
     Stop colors read --ff-fitness-rgb / --ff-fatigue-rgb via CSS vars set on
     the gradient element (or inherited from the chart root). */
.ff-fill-fitness {
    stop-color: rgb(var(--ff-fitness-rgb));
    stop-opacity: 0.32;
  }
.ff-fill-fitness--bottom {
    stop-color: rgb(var(--ff-fitness-rgb));
    stop-opacity: 0;
  }
.ff-fill-fatigue {
    stop-color: rgb(var(--ff-fatigue-rgb));
    stop-opacity: 0.28;
  }
.ff-fill-fatigue--bottom {
    stop-color: rgb(var(--ff-fatigue-rgb));
    stop-opacity: 0;
  }
/* Chart line stroke classes — applied to the ATL/CTL <path> elements so the
     line colors match the gradient fills. */
.ff-line-fitness {
    stroke: rgb(var(--ff-fitness-rgb));
  }
.ff-line-fatigue {
    stroke: rgb(var(--ff-fatigue-rgb));
  }
/* ─── TSB (Training Stress Balance) indicator ───────────────────────────────
     Compact pill showing the TSB value with a color-coded dot. Color reflects
     the zone: green (fresh, TSB > +5), amber (moderate, -10..+5), red
     (overtrained, < -10). Reuses the .ff-alert-* tokens. */
.ff-tsb {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    padding: 0.375rem 0.75rem;
    border-radius: 9999px;
    background-color: oklch(var(--card));
    box-shadow: var(--neomorph-shadow-sm);
    font-family: var(--font-display);
    font-size: 0.75rem;
    font-weight: 600;
    color: oklch(var(--foreground));
    line-height: 1;
  }
/* TSB zone dot — small 8px circle, color reflects the zone. */
.ff-tsb__dot {
    width: 8px;
    height: 8px;
    border-radius: 9999px;
    flex-shrink: 0;
  }
.ff-tsb--fresh .ff-tsb__dot {
    background-color: oklch(var(--ff-alert-green));
    box-shadow: 0 0 6px rgba(var(--ff-alert-green-rgb), 0.5);
  }
.ff-tsb--moderate .ff-tsb__dot {
    background-color: oklch(var(--ff-alert-amber));
    box-shadow: 0 0 6px rgba(var(--ff-alert-amber-rgb), 0.5);
  }
.ff-tsb--overtrained .ff-tsb__dot {
    background-color: oklch(var(--ff-alert-red));
    box-shadow: 0 0 6px rgba(var(--ff-alert-red-rgb), 0.5);
  }
/* ─── Color-coded alert box (rule-based recommendation) ──────────────────────
     Neumorphic raised card with a colored left border + tinted icon + header +
     body. Color reflects the recommendation zone (green/amber/red). Mirrors
     .mw-insight structure but with zone-driven color instead of fixed accent. */
.ff-alert {
    position: relative;
    display: flex;
    align-items: flex-start;
    gap: 0.625rem;
    padding: 0.75rem 0.875rem;
    border-radius: 0.75rem;
    background-color: oklch(var(--card));
    box-shadow: var(--neomorph-shadow-sm);
    border-left: 3px solid oklch(var(--ff-alert-color, var(--accent)));
    overflow: hidden;
  }
.ff-alert--fresh {
    --ff-alert-color: var(--ff-alert-green);
    --ff-alert-rgb: var(--ff-alert-green-rgb);
  }
.ff-alert--moderate {
    --ff-alert-color: var(--ff-alert-amber);
    --ff-alert-rgb: var(--ff-alert-amber-rgb);
  }
.ff-alert--overtrained {
    --ff-alert-color: var(--ff-alert-red);
    --ff-alert-rgb: var(--ff-alert-red-rgb);
  }
/* Alert icon — small square (28px) zone-tinted background with zone-colored icon. */
.ff-alert__icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border-radius: 8px;
    background-color: rgba(var(--ff-alert-rgb, var(--accent-rgb)), 0.14);
    color: oklch(var(--ff-alert-color, var(--accent)));
    flex-shrink: 0;
  }
/* Alert text column — header + body. Tight gap. Mirrors .mw-insight__text. */
.ff-alert__text {
    display: flex;
    flex-direction: column;
    gap: 0.1875rem;
    flex: 1 1 auto;
    min-width: 0;
  }
.ff-alert__header {
    font-family: var(--font-display);
    font-size: 0.8125rem;
    font-weight: 600;
    color: oklch(var(--foreground));
    line-height: 1.2;
  }
.ff-alert__body {
    font-family: var(--font-body);
    font-size: 0.6875rem;
    font-weight: 400;
    color: oklch(var(--muted-foreground));
    line-height: 1.35;
  }
/* ─── PPL donut ring well ───────────────────────────────────────────────────
     Mirrors .mw-ring-well / .wq-ring-well: circular recessed area hosting the
     donut SVG. Deeper inset than .neomorph-inset-sm (5px dark + hairline rim)
     = engraved look. Sized to wrap the donut with breathing room. */
.ppl-ring-well {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 9999px;
    background-color: oklch(var(--background));
    box-shadow: var(--ppl-ring-well);
    flex-shrink: 0;
  }
/* ─── PPL arc glow ──────────────────────────────────────────────────────────
     Soft drop-shadow halo on the donut arcs. Reads the per-arc color via
     --ppl-arc-rgb set on each arc element (orange/blauw/groen). Mirrors
     .mw-ring-glow / .wq-arc-glow. */
.ppl-arc-glow {
    filter: drop-shadow(
        0 0 5px rgba(var(--ppl-arc-rgb, var(--accent-rgb)), 0.55)
      )
      drop-shadow(0 0 12px rgba(var(--ppl-arc-rgb, var(--accent-rgb)), 0.22));
  }
/* ─── PPL in-ring percentage labels ─────────────────────────────────────────
     Percentage labels positioned IN the ring (not outside). Each label sits
     along its arc segment, centered. Display font, bold, color matches the arc.
     --ppl-arc-rgb is set per-label to match the parent arc color. */
.ppl-ring-label {
    font-family: var(--font-display);
    font-size: 0.75rem;
    font-weight: 700;
    color: rgb(var(--ppl-arc-rgb, var(--accent-rgb)));
    line-height: 1;
    pointer-events: none;
    text-anchor: middle;
    dominant-baseline: middle;
  }
/* ─── PPL per-spiergroep mini-stats ─────────────────────────────────────────
     Compact row per spiergroep: colored dot + name + percentage. Reuses the
     .ppl-arc-rgb per row so the dot color matches the donut segment. */
.ppl-mini-stat {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.5rem 0.75rem;
    border-radius: 0.5rem;
    background-color: oklch(var(--card));
    box-shadow: var(--neomorph-shadow-sm);
  }
.ppl-mini-stat__dot {
    width: 10px;
    height: 10px;
    border-radius: 9999px;
    background-color: rgb(var(--ppl-arc-rgb, var(--accent-rgb)));
    box-shadow: 0 0 5px rgba(var(--ppl-arc-rgb, var(--accent-rgb)), 0.45);
    flex-shrink: 0;
  }
.ppl-mini-stat__name {
    font-family: var(--font-body);
    font-size: 0.75rem;
    font-weight: 500;
    color: oklch(var(--foreground));
    flex: 1 1 auto;
    min-width: 0;
    line-height: 1.2;
  }
.ppl-mini-stat__pct {
    font-family: var(--font-display);
    font-size: 0.8125rem;
    font-weight: 700;
    color: rgb(var(--ppl-arc-rgb, var(--accent-rgb)));
    line-height: 1;
    flex-shrink: 0;
  }
/* ─── Overload nav-card ─────────────────────────────────────────────────────
     Neumorphic raised card (rounded-xl) hosting a mini-sparkline preview of the
     current week volume + a trend pijl (↑/↓/→) + delta cijfer vs vorige week.
     Whole card is clickable → navigeert naar volledige Overload Progression
     view. Mirrors .wq-card / .mw-insight structure. */
.ol-nav-card {
    position: relative;
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.75rem 0.875rem;
    border-radius: 0.75rem;
    background-color: oklch(var(--card));
    box-shadow: var(--neomorph-shadow-sm);
    transition: box-shadow 200ms cubic-bezier(0.4, 0, 0.2, 1), transform 200ms
      cubic-bezier(0.4, 0, 0.2, 1);
    cursor: pointer;
    contain: layout style;
  }
.ol-nav-card:active {
    transform: scale(0.99) translateZ(0);
    box-shadow: var(--neomorph-pressed);
  }
/* ─── Overload sparkline preview area ───────────────────────────────────────
     Inset well hosting the mini sparkline SVG so it reads as a sculpted recess,
     not a flat sticker. Mirrors .mw-tile-well depth language (lighter inset). */
.ol-nav-spark {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 64px;
    height: 40px;
    border-radius: 0.5rem;
    background-color: oklch(var(--background));
    box-shadow: var(--ol-nav-spark);
    flex-shrink: 0;
    overflow: hidden;
  }
/* Sparkline SVG stroke — accent color with a soft glow. */
.ol-nav-spark-line {
    stroke: var(--accent-hex);
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
    fill: none;
    filter: drop-shadow(0 0 3px rgba(var(--accent-rgb), 0.45));
  }
/* ─── Overload text column ───────────────────────────────────────────────────
     Header label + name on one line, trend pijl + delta on the next. Mirrors
     .wq-text / .mw-insight__text structure. */
.ol-nav-text {
    display: flex;
    flex-direction: column;
    gap: 0.1875rem;
    flex: 1 1 auto;
    min-width: 0;
  }
.ol-nav-header {
    display: flex;
    align-items: baseline;
    gap: 0.4rem;
    line-height: 1.15;
  }
.ol-nav-header__label {
    font-family: var(--font-body);
    font-size: 0.625rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: oklch(var(--muted-foreground));
  }
.ol-nav-header__name {
    font-family: var(--font-display);
    font-size: 0.9375rem;
    font-weight: 600;
    color: oklch(var(--foreground));
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
/* Trend row — pijl + delta cijfer. Color reflects direction. */
.ol-nav-trend {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    font-family: var(--font-display);
    font-size: 0.8125rem;
    font-weight: 700;
    line-height: 1.2;
  }
/* ─────────────────────────────────────────────────────────────────────────── */
.op-stat-cell {
    box-shadow: var(--op-stat-cell-well);
  }
.op-radar-well {
    box-shadow: var(--op-radar-well);
  }
.op-hero-metric {
    font-size: var(--op-hero-metric-size);
    font-weight: var(--op-hero-metric-weight);
    line-height: var(--op-hero-metric-line);
    letter-spacing: var(--op-hero-metric-tracking);
    color: oklch(var(--accent));
  }
.op-stat-secondary {
    font-size: var(--op-stat-secondary-size);
    font-weight: var(--op-stat-secondary-weight);
    line-height: var(--op-stat-secondary-line);
    color: var(--foreground);
  }
.op-stat-label {
    font-size: var(--op-stat-label-size);
    font-weight: var(--op-stat-label-weight);
    letter-spacing: var(--op-stat-label-tracking);
    text-transform: uppercase;
    color: var(--muted-foreground);
  }
.op-radar-axis-value {
    font-size: var(--op-radar-axis-value-size);
    font-weight: var(--op-radar-axis-value-weight);
    color: var(--muted-foreground);
  }
.op-coaching {
    box-shadow: var(--op-coaching-ring), var(--op-coaching-glow);
  }
.\[color-scheme\:light\] {
  color-scheme: light;
}

/* font-display: optional — eliminates FOUT/swap layout shift on first
   render. Browsers that already have the font cached use it immediately;
   uncached fonts are fetched with a tiny low-priority window and only
   applied if ready in time, otherwise the fallback stays for the session.
   This trades a one-time "no custom font" render (on very slow first
   loads) for a stable, jump-free layout on every open. */
@font-face {
  font-family: "Space Grotesk";
  src: url("/assets/fonts/SpaceGrotesk.woff2") format("woff2");
  font-display: optional;
}

@font-face {
  font-family: "General Sans";
  src: url("/assets/fonts/GeneralSans.woff2") format("woff2");
  font-display: optional;
}

/* ─────────────────────────────────────────────────────────────────────────── */
/* Start Workout button — slow neon glow pulse (10s per cycle).
   Defined directly in CSS (not via Tailwind theme.extend) to bypass any
   bundling/caching layer that could ship a stale or differently-tuned
   animation. Uses a unique name (repstatSlowGlowPulse / .repstat-slow-glow-pulse)
   that does not match the old start-workout-button-glow name, so a cached
   old stylesheet cannot accidentally reapply the previous fast pulse.

   Rhythm over the 10s cycle (1s = 10%):
     - 0%   → 30%  : 3s ease-in-out rise  (dim  → bright)
     - 30%  → 50%  : 2s rest at bright   (rustpauze na oplichten)
     - 50%  → 80%  : 3s ease-in-out fall  (bright → dim)
     - 80%  → 100% : 2s rest at dim       (rustpauze voor volgende slag)
   The inner neumorphic shadow (8px 8px 16px / -8px -8px 16px / inset) is
   preserved on every phase so the button keeps its tactile depth; only the
   outer orange halo breathes 18px @ 0.45 → 34px @ 0.8. Reads --accent-rgb
   directly (theme-agnostic). Active only in rest state (no active workout) —
   HomePage.tsx toggles the class based on !hasActiveWorkout.
   Reduced-motion users get a static glow via the override in the
   @media (prefers-reduced-motion: reduce) block below. */
@keyframes repstatSlowGlowPulse {
  0%,
  100% {
    box-shadow:
      8px 8px 16px rgba(0, 0, 0, 0.4), -8px -8px 16px rgba(255, 255, 255, 0.05),
      inset 0 1px 0 rgba(255, 255, 255, 0.15),
      0 0 18px rgba(var(--accent-rgb), 0.45);
  }
  30%,
  50% {
    box-shadow:
      8px 8px 16px rgba(0, 0, 0, 0.4), -8px -8px 16px rgba(255, 255, 255, 0.05),
      inset 0 1px 0 rgba(255, 255, 255, 0.15),
      0 0 34px rgba(var(--accent-rgb), 0.8);
  }
  80% {
    box-shadow:
      8px 8px 16px rgba(0, 0, 0, 0.4), -8px -8px 16px rgba(255, 255, 255, 0.05),
      inset 0 1px 0 rgba(255, 255, 255, 0.15),
      0 0 18px rgba(var(--accent-rgb), 0.45);
  }
}

.repstat-slow-glow-pulse {
  animation: repstatSlowGlowPulse 10s cubic-bezier(0.4, 0, 0.2, 1) infinite;
}

/* Reduced motion support */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }

  .neomorph,
  .neomorph-sm,
  .neomorph-lg,
  .neomorph-xl,
  .neomorph-button,
  .neomorph-hover,
  .template-card-refined,
  .template-action-button {
    transition: none !important;
    transform: none !important;
  }

  /* Start Workout button glow — essential visual signal for the primary
     action. The global rule above would fully kill the animation, leaving
     the button with no orange glow on the light theme. Instead, override
     locally: keep a static orange box-shadow glow (no motion) so
     reduced-motion users still see the call-to-action emphasis. The
     animation class (.repstat-slow-glow-pulse) and its keyframes
     (repstatSlowGlowPulse) are defined at the top level of index.css so
     they bypass Tailwind's theme.extend pipeline entirely. The text itself
     is always static — only the button's box-shadow pulses. */
  .repstat-slow-glow-pulse {
    animation: none !important;
    box-shadow:
      8px 8px 16px rgba(0, 0, 0, 0.4), -8px -8px 16px
      rgba(255, 255, 255, 0.05), inset 0 1px 0 rgba(255, 255, 255, 0.15),
      0 0 26px rgba(var(--accent-rgb), 0.65) !important;
  }
}

/* Mobile-specific optimizations */
@media (max-width: 640px) {
  /* Ensure minimum touch target sizes — iOS/Android HIG 44x44px.
     Includes text/number/email/tel/password inputs and textareas so every
     form control is comfortably tappable on mobile. min-width: 44px only
     applies to tap targets (buttons/links/checkboxes/radios); inputs keep
     their full-width layout and only get the height floor. */
  button,
  a,
  input[type="checkbox"],
  input[type="radio"] {
    min-height: 44px;
    min-width: 44px;
  }

  input[type="text"],
  input[type="number"],
  input[type="email"],
  input[type="tel"],
  input[type="password"],
  input[type="date"],
  input[type="time"],
  input[type="datetime-local"],
  textarea,
  select {
    min-height: 44px;
  }

  /* Optimize spacing for mobile */
  .mobile-compact {
    padding: 0.75rem;
  }

  /* Better readability on small screens */
  body {
    font-size: 16px;
    line-height: 1.5;
  }
}

/* High contrast mode support */
@media (prefers-contrast: high) {
  :root {
    --foreground: 0.08 0 0;
    --muted-foreground: 0.38 0 0;
  }

  .dark {
    --foreground: 0.99 0 0;
    --muted-foreground: 0.82 0 0;
  }

  /* Enhance borders in high contrast mode */
  .neomorph,
  .neomorph-sm,
  .neomorph-lg,
  .neomorph-xl,
  .template-card-refined,
  .template-action-button {
    border: 1px solid oklch(var(--border));
  }
}

/* Modal search input — placeholder + caret colors so it works in both themes regardless of
   overlay context. Background is intentionally NOT set here so the .bp2-search-input wrapper's
   single subtle inset neumorph is the only background layer (inner Input stays transparent). */
:root:not(.dark) .modal-exercise-search,
:root:not(.dark) input.modal-exercise-search {
  color: #1a1a1a !important;
  caret-color: #1a1a1a !important;
  border-color: #c8c4be !important;
}
:root:not(.dark) .modal-exercise-search::-moz-placeholder {
  color: #6b6b6b !important;
  opacity: 1 !important;
}
:root:not(.dark) .modal-exercise-search::placeholder {
  color: #6b6b6b !important;
  opacity: 1 !important;
}

.dark .modal-exercise-search,
.dark input.modal-exercise-search {
  color: #f0f0f0 !important;
  caret-color: #f0f0f0 !important;
  border-color: #404040 !important;
}
.dark .modal-exercise-search::-moz-placeholder {
  color: #888888 !important;
  opacity: 1 !important;
}
.dark .modal-exercise-search::placeholder {
  color: #888888 !important;
  opacity: 1 !important;
}

/* ===== Overload Progression detail page utility classes ===== */
.op-pill {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0.5rem 1rem;
  border-radius: 9999px;
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--muted);
  background: var(--card);
  box-shadow: var(--op-pill-raised);
  transition: box-shadow 0.2s ease, color 0.2s ease, background 0.2s ease;
  cursor: pointer;
  border: none;
}
.op-pill:hover {
  color: var(--accent);
}
.op-pill--active {
  color: #fff;
  background: var(--accent);
  box-shadow: var(--op-pill-active-glow);
}
.op-pill--active:hover {
  color: #fff;
}
.op-hero {
  position: relative;
  padding: 1.5rem;
  border-radius: 1rem;
  background: var(--card);
  box-shadow: var(--op-hero-well);
}
.op-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.75rem;
  padding: 1.5rem 1rem;
  border-radius: 1rem;
  background: var(--card);
  box-shadow: var(--op-empty-well);
  text-align: center;
}
.op-avg-line {
  stroke: oklch(var(--accent-rgb) / 0.55);
  stroke-width: 1.5;
  stroke-dasharray: 5 4;
  fill: none;
}
.op-star-glow {
  filter: drop-shadow(0 0 4px oklch(var(--accent-rgb) / 0.65));
}

/* Fase 1 — Buddy Tab Challenges. LIVE pill breathing animation: opacity
   0.6↔1 + scale 0.97↔1, 2s ease-in-out infinite. Respects the global
   prefers-reduced-motion guard at index.css line 4340 plus the local block
   below. */
@keyframes wvc-live-pulse {
  0%,
  100% {
    opacity: 0.6;
    transform: scale(0.97);
  }
  50% {
    opacity: 1;
    transform: scale(1);
  }
}
.neomorph-wvc-card {
  box-shadow: var(--wvc-card-well);
}
.neomorph-wvc-sub {
  box-shadow: var(--wvc-sub-well);
}
.neomorph-lb-seg {
  box-shadow: var(--lb-seg-well);
}
.neomorph-lb-row {
  box-shadow: var(--lb-row-well);
}
.neomorph-lb-avg {
  box-shadow: var(--lb-avg-well);
}
.neomorph-pr-card {
  background: var(--card);
  box-shadow: var(--pr-card-well);
  border-radius: 1rem;
}
.neomorph-pr-seg {
  background: var(--card);
  box-shadow: var(--pr-seg-well);
  border-radius: 9999px;
}
.neomorph-pr-row {
  background: var(--card);
  box-shadow: var(--pr-row-well);
  border-radius: 0.75rem;
}
.neomorph-streak-card {
  background: var(--card);
  box-shadow: var(--streak-card-well);
  border-radius: 1rem;
}
.neomorph-streak-ring {
  box-shadow: var(--streak-ring-well);
}
.neomorph-mbr-card {
  background: var(--card);
  box-shadow: var(--mbr-card-well);
  border-radius: 1rem;
}
.neomorph-mbr-bar {
  box-shadow: var(--mbr-bar-well);
}
.neomorph-mbr-seg {
  background: var(--card);
  box-shadow: var(--mbr-seg-well);
  border-radius: 9999px;
}
.neomorph-mbr-sub {
  box-shadow: var(--mbr-sub-well);
}
@media (prefers-reduced-motion: reduce) {
  .wvc-live-pulse {
    animation: none;
  }
}

/* ═══════════════════════════════════════════════════════════════════════════
   SETTINGS PAGE NEUMORPHIC REFINEMENT
   Additive component classes for the SettingsPage upgrade. Reuse existing
   tokens only — --accent, --accent-hex, --accent-rgb, --accent-foreground,
   --destructive, --foreground, --muted-foreground, --neomorph-shadow-sm,
   --neomorph-inset, --neomorph-inset-sm, --neomorph-hover, --neomorph-pressed,
   --neomorph-accent-ring, --font-display, --font-body. No existing tokens,
   accent presets, or theme variables are modified. All classes work in both
   :root (light) and .dark themes via inherited variables. 44px tap targets
   enforced where the element is a primary interactive control.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ─── Keyboard focus ring ─────────────────────────────────────────────────
   Accent-colored outline for keyboard navigation. Uses var(--accent) so it
   follows the active accent preset (Ember/Volt/Venom/Coral). Apply on any
   focusable element via class or compose with &:focus-visible. */
.neomorph-focus-ring:focus-visible {
  outline: 2px solid oklch(var(--accent));
  outline-offset: 2px;
  border-radius: inherit;
}

/* ─── Settings section header ──────────────────────────────────────────────
   Flex row: icon + title. Space Grotesk semibold title (1.25rem), 1.5rem icon,
   margin-bottom for breathing room. Works in both themes via --foreground. */
.settings-section-header {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  margin-bottom: 0.875rem;
}

.settings-section-header__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.5rem;
  height: 1.5rem;
  flex-shrink: 0;
  color: oklch(var(--accent));
}

.settings-section-header__title {
  font-family: var(--font-display);
  font-size: 1.25rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 1.2;
  color: oklch(var(--foreground));
}

/* ─── Large toggle switch ──────────────────────────────────────────────────
   Larger track (52×30px) with a 24px thumb that slides right and turns accent
   when checked. Wrapper enforces a 44px tap target via padding. Driven by
   aria-checked on the track or a sibling checkbox + label pattern. */
.neomorph-toggle-lg {
  position: relative;
  display: inline-flex;
  align-items: center;
  width: 52px;
  min-width: 52px;
  height: 30px;
  min-height: 30px;
  border-radius: 9999px;
  background-color: oklch(var(--muted));
  box-shadow: var(--neomorph-inset-sm);
  transition: background-color 200ms cubic-bezier(0.4, 0, 0.2, 1), box-shadow
    200ms cubic-bezier(0.4, 0, 0.2, 1);
  cursor: pointer;
  flex-shrink: 0;
}

.neomorph-toggle-lg__thumb {
  position: absolute;
  top: 3px;
  left: 3px;
  width: 24px;
  height: 24px;
  border-radius: 9999px;
  background-color: oklch(var(--card));
  box-shadow: var(--neomorph-shadow-sm);
  transition: transform 200ms cubic-bezier(0.4, 0, 0.2, 1), background-color
    200ms cubic-bezier(0.4, 0, 0.2, 1);
  will-change: transform;
}

.neomorph-toggle-lg[aria-checked="true"],
.neomorph-toggle-lg.is-checked {
  background-color: oklch(var(--accent));
  box-shadow: var(--neomorph-inset-sm), 0 0 0 1px rgba(var(--accent-rgb), 0.45);
}

.neomorph-toggle-lg[aria-checked="true"] .neomorph-toggle-lg__thumb,
.neomorph-toggle-lg.is-checked .neomorph-toggle-lg__thumb {
  transform: translateX(22px);
  background-color: oklch(var(--accent-foreground));
}

/* Wrapper that guarantees the 44px tap target around the toggle. */
.neomorph-toggle-lg__wrap {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  padding: 7px 4px;
  cursor: pointer;
}

/* ─── Danger button (raised neumorphic, red accent) ─────────────────────────
   Raised look via --neomorph-shadow-sm, 1px destructive border, destructive
   text. Hover/active swap to neumorph-hover / neomorph-pressed. NOT flat. */
.neomorph-button-danger {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 0.625rem 1.25rem;
  min-height: 44px;
  border-radius: var(--radius);
  background-color: oklch(var(--card));
  border: 1px solid oklch(var(--destructive));
  color: oklch(var(--destructive));
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 0.875rem;
  box-shadow: var(--neomorph-shadow-sm);
  transition: box-shadow 150ms cubic-bezier(0.4, 0, 0.2, 1), transform 150ms
    cubic-bezier(0.4, 0, 0.2, 1), opacity 150ms cubic-bezier(0.4, 0, 0.2, 1);
  cursor: pointer;
  will-change: transform;
  contain: layout style;
}

.neomorph-button-danger:hover:not(:disabled) {
  box-shadow: var(--neomorph-hover);
  transform: scale(1.02) translateZ(0);
}

.neomorph-button-danger:active:not(:disabled) {
  box-shadow: var(--neomorph-pressed);
  transform: scale(0.98) translateZ(0);
}

.neomorph-button-danger:focus-visible {
  outline: 2px solid oklch(var(--destructive));
  outline-offset: 2px;
  border-radius: inherit;
}

.neomorph-button-danger:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* ─── Training day toggle button ───────────────────────────────────────────
   44×44 tap target. Neumorphic-inset when unselected; accent fill + accent-
   foreground text when aria-pressed="true". Rounded. */
.neomorph-day-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  width: 100%;
  min-height: 44px;
  padding: 0.5rem 0.625rem;
  border-radius: var(--radius);
  background-color: oklch(var(--card));
  border: none;
  color: oklch(var(--foreground));
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 0.875rem;
  box-shadow: var(--neomorph-inset-sm);
  transition: box-shadow 150ms cubic-bezier(0.4, 0, 0.2, 1), background-color
    150ms cubic-bezier(0.4, 0, 0.2, 1), color 150ms cubic-bezier(0.4, 0, 0.2, 1),
    transform 150ms cubic-bezier(0.4, 0, 0.2, 1);
  cursor: pointer;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}

.neomorph-day-btn:hover:not(:disabled) {
  color: oklch(var(--accent));
}

.neomorph-day-btn:active:not(:disabled) {
  transform: scale(0.97) translateZ(0);
  box-shadow: var(--neomorph-pressed);
}

.neomorph-day-btn[aria-pressed="true"],
.neomorph-day-btn.is-pressed {
  background-color: oklch(var(--accent));
  color: oklch(var(--accent-foreground));
  box-shadow: var(--neomorph-shadow-sm), 0 0 0 1px rgba(var(--accent-rgb), 0.4);
}

.neomorph-day-btn[aria-pressed="true"]:active:not(:disabled),
.neomorph-day-btn.is-pressed:active:not(:disabled) {
  box-shadow: var(--neomorph-pressed);
}

.neomorph-day-btn:focus-visible {
  outline: 2px solid oklch(var(--accent));
  outline-offset: 2px;
  border-radius: inherit;
}

.neomorph-day-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* ─── Rest timer preset pill ───────────────────────────────────────────────
   44px tap target, neumorphic-inset unselected, accent fill when selected.
   Rounded pill shape (full radius). */
.neomorph-preset-pill {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding: 0.5rem 1.25rem;
  border-radius: 9999px;
  background-color: oklch(var(--card));
  border: none;
  color: oklch(var(--foreground));
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 0.875rem;
  box-shadow: var(--neomorph-inset-sm);
  transition: box-shadow 150ms cubic-bezier(0.4, 0, 0.2, 1), background-color
    150ms cubic-bezier(0.4, 0, 0.2, 1), color 150ms cubic-bezier(0.4, 0, 0.2, 1),
    transform 150ms cubic-bezier(0.4, 0, 0.2, 1);
  cursor: pointer;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}

.neomorph-preset-pill:hover:not(:disabled) {
  color: oklch(var(--accent));
}

.neomorph-preset-pill:active:not(:disabled) {
  transform: scale(0.97) translateZ(0);
  box-shadow: var(--neomorph-pressed);
}

.neomorph-preset-pill[aria-pressed="true"],
.neomorph-preset-pill.is-pressed {
  background-color: oklch(var(--accent));
  color: oklch(var(--accent-foreground));
  box-shadow: var(--neomorph-shadow-sm), 0 0 0 1px rgba(var(--accent-rgb), 0.4);
}

.neomorph-preset-pill:focus-visible {
  outline: 2px solid oklch(var(--accent));
  outline-offset: 2px;
  border-radius: inherit;
}

.neomorph-preset-pill:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* ─── Accent color swatch ───────────────────────────────────────────────────
   44×44 tap target, neumorphic-inset base, accent ring when aria-checked. */
.neomorph-swatch {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  width: 44px;
  height: 44px;
  border-radius: 9999px;
  background-color: oklch(var(--card));
  border: none;
  box-shadow: var(--neomorph-inset-sm);
  transition: box-shadow 150ms cubic-bezier(0.4, 0, 0.2, 1), transform 150ms
    cubic-bezier(0.4, 0, 0.2, 1);
  cursor: pointer;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
  padding: 0;
}

.neomorph-swatch__dot {
  width: 28px;
  height: 28px;
  border-radius: 9999px;
  background-color: var(--swatch-color, oklch(var(--accent)));
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.08);
  flex-shrink: 0;
}

.neomorph-swatch:hover:not(:disabled) {
  transform: scale(1.04) translateZ(0);
}

.neomorph-swatch:active:not(:disabled) {
  transform: scale(0.96) translateZ(0);
  box-shadow: var(--neomorph-pressed);
}

.neomorph-swatch[aria-checked="true"],
.neomorph-swatch.is-checked {
  box-shadow: var(--neomorph-inset-sm), 0 0 0 2px oklch(var(--accent)), 0 0 0
    4px rgba(var(--accent-rgb), 0.25);
}

.neomorph-swatch:focus-visible {
  outline: 2px solid oklch(var(--accent));
  outline-offset: 2px;
  border-radius: inherit;
}

.neomorph-swatch:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.selection\:bg-primary *::-moz-selection {
  background-color: oklch(var(--primary));
}

.selection\:bg-primary *::selection {
  background-color: oklch(var(--primary));
}

.selection\:text-primary-foreground *::-moz-selection {
  color: oklch(var(--primary-foreground));
}

.selection\:text-primary-foreground *::selection {
  color: oklch(var(--primary-foreground));
}

.selection\:bg-primary::-moz-selection {
  background-color: oklch(var(--primary));
}

.selection\:bg-primary::selection {
  background-color: oklch(var(--primary));
}

.selection\:text-primary-foreground::-moz-selection {
  color: oklch(var(--primary-foreground));
}

.selection\:text-primary-foreground::selection {
  color: oklch(var(--primary-foreground));
}

.file\:inline-flex::file-selector-button {
  display: inline-flex;
}

.file\:h-7::file-selector-button {
  height: 1.75rem;
}

.file\:border-0::file-selector-button {
  border-width: 0px;
}

.file\:bg-transparent::file-selector-button {
  background-color: transparent;
}

.file\:text-sm::file-selector-button {
  font-size: 0.875rem;
  line-height: 1.25rem;
}

.file\:font-medium::file-selector-button {
  font-weight: 500;
}

.file\:text-foreground::file-selector-button {
  color: oklch(var(--foreground));
}

.placeholder\:text-muted-foreground::-moz-placeholder {
  color: oklch(var(--muted-foreground));
}

.placeholder\:text-muted-foreground::placeholder {
  color: oklch(var(--muted-foreground));
}

.last\:mb-0:last-child {
  margin-bottom: 0px;
}

.hover\:translate-y-\[-1px\]:hover {
  --tw-translate-y: -1px;
  transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}

.hover\:scale-105:hover {
  --tw-scale-x: 1.05;
  --tw-scale-y: 1.05;
  transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}

.hover\:scale-110:hover {
  --tw-scale-x: 1.1;
  --tw-scale-y: 1.1;
  transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}

.hover\:scale-\[1\.01\]:hover {
  --tw-scale-x: 1.01;
  --tw-scale-y: 1.01;
  transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}

.hover\:scale-\[1\.02\]:hover {
  --tw-scale-x: 1.02;
  --tw-scale-y: 1.02;
  transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}

.hover\:bg-\[rgba\(var\(--accent-rgb\)\2c 0\.85\)\]:hover {
  background-color: rgba(var(--accent-rgb),0.85);
}

.hover\:bg-accent:hover {
  background-color: oklch(var(--accent));
}

.hover\:bg-destructive:hover {
  background-color: oklch(var(--destructive));
}

.hover\:bg-muted:hover {
  background-color: oklch(var(--muted));
}

.hover\:text-\[var\(--accent-hex\)\]:hover {
  color: var(--accent-hex);
}

.hover\:text-accent:hover {
  color: oklch(var(--accent));
}

.hover\:text-accent-foreground:hover {
  color: oklch(var(--accent-foreground));
}

.hover\:text-destructive:hover {
  color: oklch(var(--destructive));
}

.hover\:text-destructive-foreground:hover {
  color: oklch(var(--destructive-foreground));
}

.hover\:text-foreground:hover {
  color: oklch(var(--foreground));
}

.hover\:text-muted-foreground:hover {
  color: oklch(var(--muted-foreground));
}

.hover\:text-red-400:hover {
  --tw-text-opacity: 1;
  color: rgb(248 113 113 / var(--tw-text-opacity, 1));
}

.hover\:underline:hover {
  text-decoration-line: underline;
}

.hover\:opacity-100:hover {
  opacity: 1;
}

.hover\:opacity-80:hover {
  opacity: 0.8;
}

.hover\:opacity-90:hover {
  opacity: 0.9;
}

.focus\:bg-accent:focus {
  background-color: oklch(var(--accent));
}

.focus\:text-accent-foreground:focus {
  color: oklch(var(--accent-foreground));
}

.focus\:text-destructive:focus {
  color: oklch(var(--destructive));
}

.focus\:outline-none:focus {
  outline: 2px solid transparent;
  outline-offset: 2px;
}

.focus\:ring-0:focus {
  --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
  --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color);
  box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
}

.focus\:ring-2:focus {
  --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
  --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);
  box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
}

.focus\:ring-ring:focus {
  --tw-ring-color: oklch(var(--ring));
}

.focus\:ring-offset-2:focus {
  --tw-ring-offset-width: 2px;
}

.focus-visible\:border-ring:focus-visible {
  border-color: oklch(var(--ring));
}

.focus-visible\:outline-none:focus-visible {
  outline: 2px solid transparent;
  outline-offset: 2px;
}

.focus-visible\:outline-1:focus-visible {
  outline-width: 1px;
}

.focus-visible\:outline-2:focus-visible {
  outline-width: 2px;
}

.focus-visible\:outline-offset-2:focus-visible {
  outline-offset: 2px;
}

.focus-visible\:outline-\[oklch\(var\(--accent\)\)\]:focus-visible {
  outline-color: oklch(var(--accent));
}

.focus-visible\:ring-2:focus-visible {
  --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
  --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);
  box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
}

.focus-visible\:ring-\[3px\]:focus-visible {
  --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
  --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color);
  box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
}

.focus-visible\:ring-\[var\(--accent-rgb\)\]:focus-visible {
  --tw-ring-color: var(--accent-rgb);
}

.focus-visible\:ring-accent:focus-visible {
  --tw-ring-color: oklch(var(--accent));
}

.focus-visible\:ring-offset-2:focus-visible {
  --tw-ring-offset-width: 2px;
}

.focus-visible\:ring-offset-background:focus-visible {
  --tw-ring-offset-color: oklch(var(--background));
}

.active\:scale-95:active {
  --tw-scale-x: .95;
  --tw-scale-y: .95;
  transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}

.active\:scale-\[0\.98\]:active {
  --tw-scale-x: 0.98;
  --tw-scale-y: 0.98;
  transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}

.active\:scale-\[0\.99\]:active {
  --tw-scale-x: 0.99;
  --tw-scale-y: 0.99;
  transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}

.enabled\:hover\:text-\[var\(--accent-hex\)\]:hover:enabled {
  color: var(--accent-hex);
}

.disabled\:pointer-events-none:disabled {
  pointer-events: none;
}

.disabled\:cursor-not-allowed:disabled {
  cursor: not-allowed;
}

.disabled\:opacity-40:disabled {
  opacity: 0.4;
}

.disabled\:opacity-50:disabled {
  opacity: 0.5;
}

.disabled\:opacity-60:disabled {
  opacity: 0.6;
}

.disabled\:hover\:scale-100:hover:disabled {
  --tw-scale-x: 1;
  --tw-scale-y: 1;
  transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}

.disabled\:active\:scale-100:active:disabled {
  --tw-scale-x: 1;
  --tw-scale-y: 1;
  transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}

.group:hover .group-hover\:text-accent {
  color: oklch(var(--accent));
}

.group:hover .group-hover\:opacity-100 {
  opacity: 1;
}

.peer:disabled ~ .peer-disabled\:cursor-not-allowed {
  cursor: not-allowed;
}

.peer:disabled ~ .peer-disabled\:opacity-50 {
  opacity: 0.5;
}

.has-\[\>svg\]\:grid-cols-\[calc\(var\(--spacing\)\*4\)_1fr\]:has(>svg) {
  grid-template-columns: calc(var(--spacing) * 4) 1fr;
}

.has-\[\>svg\]\:gap-x-3:has(>svg) {
  -moz-column-gap: 0.75rem;
       column-gap: 0.75rem;
}

.has-\[\>svg\]\:px-2\.5:has(>svg) {
  padding-left: 0.625rem;
  padding-right: 0.625rem;
}

.has-\[\>svg\]\:px-3:has(>svg) {
  padding-left: 0.75rem;
  padding-right: 0.75rem;
}

.has-\[\>svg\]\:px-4:has(>svg) {
  padding-left: 1rem;
  padding-right: 1rem;
}

.data-\[disabled\]\:pointer-events-none[data-disabled] {
  pointer-events: none;
}

.data-\[vaul-drawer-direction\=bottom\]\:inset-x-0[data-vaul-drawer-direction="bottom"] {
  left: 0px;
  right: 0px;
}

.data-\[vaul-drawer-direction\=left\]\:inset-y-0[data-vaul-drawer-direction="left"] {
  top: 0px;
  bottom: 0px;
}

.data-\[vaul-drawer-direction\=right\]\:inset-y-0[data-vaul-drawer-direction="right"] {
  top: 0px;
  bottom: 0px;
}

.data-\[vaul-drawer-direction\=top\]\:inset-x-0[data-vaul-drawer-direction="top"] {
  left: 0px;
  right: 0px;
}

.data-\[vaul-drawer-direction\=bottom\]\:bottom-0[data-vaul-drawer-direction="bottom"] {
  bottom: 0px;
}

.data-\[vaul-drawer-direction\=left\]\:left-0[data-vaul-drawer-direction="left"] {
  left: 0px;
}

.data-\[vaul-drawer-direction\=right\]\:right-0[data-vaul-drawer-direction="right"] {
  right: 0px;
}

.data-\[vaul-drawer-direction\=top\]\:top-0[data-vaul-drawer-direction="top"] {
  top: 0px;
}

.data-\[vaul-drawer-direction\=bottom\]\:mt-24[data-vaul-drawer-direction="bottom"] {
  margin-top: 6rem;
}

.data-\[vaul-drawer-direction\=top\]\:mb-24[data-vaul-drawer-direction="top"] {
  margin-bottom: 6rem;
}

.data-\[orientation\=horizontal\]\:h-px[data-orientation="horizontal"] {
  height: 1px;
}

.data-\[orientation\=vertical\]\:h-full[data-orientation="vertical"] {
  height: 100%;
}

.data-\[size\=default\]\:h-9[data-size="default"] {
  height: 2.25rem;
}

.data-\[size\=sm\]\:h-8[data-size="sm"] {
  height: 2rem;
}

.data-\[vaul-drawer-direction\=bottom\]\:max-h-\[80vh\][data-vaul-drawer-direction="bottom"] {
  max-height: 80vh;
}

.data-\[vaul-drawer-direction\=top\]\:max-h-\[80vh\][data-vaul-drawer-direction="top"] {
  max-height: 80vh;
}

.data-\[orientation\=horizontal\]\:w-full[data-orientation="horizontal"] {
  width: 100%;
}

.data-\[orientation\=vertical\]\:w-px[data-orientation="vertical"] {
  width: 1px;
}

.data-\[vaul-drawer-direction\=left\]\:w-3\/4[data-vaul-drawer-direction="left"] {
  width: 75%;
}

.data-\[vaul-drawer-direction\=right\]\:w-3\/4[data-vaul-drawer-direction="right"] {
  width: 75%;
}

.data-\[side\=bottom\]\:translate-y-1[data-side="bottom"] {
  --tw-translate-y: 0.25rem;
  transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}

.data-\[side\=left\]\:-translate-x-1[data-side="left"] {
  --tw-translate-x: -0.25rem;
  transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}

.data-\[side\=right\]\:translate-x-1[data-side="right"] {
  --tw-translate-x: 0.25rem;
  transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}

.data-\[side\=top\]\:-translate-y-1[data-side="top"] {
  --tw-translate-y: -0.25rem;
  transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}

.data-\[state\=checked\]\:translate-x-\[calc\(100\%-2px\)\][data-state="checked"] {
  --tw-translate-x: calc(100% - 2px);
  transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}

.data-\[state\=unchecked\]\:translate-x-0[data-state="unchecked"] {
  --tw-translate-x: 0px;
  transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}

.data-\[state\=closed\]\:animate-none[data-state="closed"] {
  animation: none;
}

.data-\[state\=open\]\:animate-none[data-state="open"] {
  animation: none;
}

.data-\[vaul-drawer-direction\=bottom\]\:rounded-t-lg[data-vaul-drawer-direction="bottom"] {
  border-top-left-radius: var(--radius);
  border-top-right-radius: var(--radius);
}

.data-\[vaul-drawer-direction\=top\]\:rounded-b-lg[data-vaul-drawer-direction="top"] {
  border-bottom-right-radius: var(--radius);
  border-bottom-left-radius: var(--radius);
}

.data-\[vaul-drawer-direction\=bottom\]\:border-t[data-vaul-drawer-direction="bottom"] {
  border-top-width: 1px;
}

.data-\[vaul-drawer-direction\=left\]\:border-r[data-vaul-drawer-direction="left"] {
  border-right-width: 1px;
}

.data-\[vaul-drawer-direction\=right\]\:border-l[data-vaul-drawer-direction="right"] {
  border-left-width: 1px;
}

.data-\[vaul-drawer-direction\=top\]\:border-b[data-vaul-drawer-direction="top"] {
  border-bottom-width: 1px;
}

.data-\[state\=checked\]\:bg-accent[data-state="checked"] {
  background-color: oklch(var(--accent));
}

.data-\[state\=checked\]\:bg-primary[data-state="checked"] {
  background-color: oklch(var(--primary));
}

.data-\[state\=on\]\:bg-accent[data-state="on"] {
  background-color: oklch(var(--accent));
}

.data-\[state\=open\]\:bg-accent[data-state="open"] {
  background-color: oklch(var(--accent));
}

.data-\[state\=open\]\:bg-secondary[data-state="open"] {
  background-color: oklch(var(--secondary));
}

.data-\[state\=unchecked\]\:bg-input[data-state="unchecked"] {
  background-color: oklch(var(--input));
}

.data-\[inset\]\:pl-8[data-inset] {
  padding-left: 2rem;
}

.data-\[placeholder\]\:text-muted-foreground[data-placeholder] {
  color: oklch(var(--muted-foreground));
}

.data-\[state\=on\]\:text-accent-foreground[data-state="on"] {
  color: oklch(var(--accent-foreground));
}

.data-\[state\=open\]\:text-accent-foreground[data-state="open"] {
  color: oklch(var(--accent-foreground));
}

.data-\[state\=open\]\:text-muted-foreground[data-state="open"] {
  color: oklch(var(--muted-foreground));
}

.data-\[variant\=destructive\]\:text-destructive[data-variant="destructive"] {
  color: oklch(var(--destructive));
}

.data-\[disabled\]\:opacity-50[data-disabled] {
  opacity: 0.5;
}

.data-\[state\=closed\]\:duration-200[data-state="closed"] {
  transition-duration: 200ms;
}

.data-\[state\=open\]\:duration-200[data-state="open"] {
  transition-duration: 200ms;
}

.data-\[state\=open\]\:animate-in[data-state="open"] {
  animation-name: enter;
  animation-duration: 150ms;
  --tw-enter-opacity: initial;
  --tw-enter-scale: initial;
  --tw-enter-rotate: initial;
  --tw-enter-translate-x: initial;
  --tw-enter-translate-y: initial;
}

.data-\[state\=closed\]\:animate-out[data-state="closed"] {
  animation-name: exit;
  animation-duration: 150ms;
  --tw-exit-opacity: initial;
  --tw-exit-scale: initial;
  --tw-exit-rotate: initial;
  --tw-exit-translate-x: initial;
  --tw-exit-translate-y: initial;
}

.data-\[state\=closed\]\:fade-out-0[data-state="closed"] {
  --tw-exit-opacity: 0;
}

.data-\[state\=open\]\:fade-in-0[data-state="open"] {
  --tw-enter-opacity: 0;
}

.data-\[state\=closed\]\:zoom-out-95[data-state="closed"] {
  --tw-exit-scale: .95;
}

.data-\[state\=open\]\:zoom-in-95[data-state="open"] {
  --tw-enter-scale: .95;
}

.data-\[state\=closed\]\:duration-200[data-state="closed"] {
  animation-duration: 200ms;
}

.data-\[state\=open\]\:duration-200[data-state="open"] {
  animation-duration: 200ms;
}

.data-\[state\=open\]\:zoom-in-95[data-state="open"] {
    animation: zoom-in-95 400ms cubic-bezier(0.4, 0, 0.2, 1);
    will-change: transform, opacity;
  }

.\*\:data-\[slot\=select-value\]\:line-clamp-1[data-slot="select-value"] > * {
  overflow: hidden;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 1;
}

.\*\:data-\[slot\=select-value\]\:flex[data-slot="select-value"] > * {
  display: flex;
}

.\*\:data-\[slot\=select-value\]\:items-center[data-slot="select-value"] > * {
  align-items: center;
}

.\*\:data-\[slot\=select-value\]\:gap-2[data-slot="select-value"] > * {
  gap: 0.5rem;
}

.data-\[variant\=destructive\]\:focus\:text-destructive:focus[data-variant="destructive"] {
  color: oklch(var(--destructive));
}

.group[data-disabled="true"] .group-data-\[disabled\=true\]\:pointer-events-none {
  pointer-events: none;
}

.group\/drawer-content[data-vaul-drawer-direction="bottom"] .group-data-\[vaul-drawer-direction\=bottom\]\/drawer-content\:block {
  display: block;
}

.group\/drawer-content[data-vaul-drawer-direction="bottom"] .group-data-\[vaul-drawer-direction\=bottom\]\/drawer-content\:text-center {
  text-align: center;
}

.group\/drawer-content[data-vaul-drawer-direction="top"] .group-data-\[vaul-drawer-direction\=top\]\/drawer-content\:text-center {
  text-align: center;
}

.group[data-disabled="true"] .group-data-\[disabled\=true\]\:opacity-50 {
  opacity: 0.5;
}

@supports (backdrop-filter:blur(4px)) {

  .supports-\[backdrop-filter\:blur\(4px\)\]\:bg-black\/50 {
    background-color: rgb(0 0 0 / 0.5);
  }

  .supports-\[backdrop-filter\:blur\(4px\)\]\:backdrop-blur-sm {
    --tw-backdrop-blur: blur(4px);
    backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);
  }
}

.dark\:border-input:is(.dark *) {
  border-color: oklch(var(--input));
}

.dark\:bg-\[oklch\(0\.45_0\.08_40\/0\.12\)\]:is(.dark *) {
  background-color: oklch(0.45 0.08 40/0.12);
}

.dark\:\[color-scheme\:dark\]:is(.dark *) {
  color-scheme: dark;
}

.dark\:data-\[state\=checked\]\:bg-primary-foreground[data-state="checked"]:is(.dark *) {
  background-color: oklch(var(--primary-foreground));
}

.dark\:data-\[state\=unchecked\]\:bg-foreground[data-state="unchecked"]:is(.dark *) {
  background-color: oklch(var(--foreground));
}

@media (min-width: 360px) {

  .min-\[360px\]\:grid-cols-3 {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

@media (min-width: 640px) {

  .sm\:w-\[90\%\] {
    width: 90%;
  }

  .sm\:max-w-2xl {
    max-width: 42rem;
  }

  .sm\:max-w-lg {
    max-width: 32rem;
  }

  .sm\:max-w-md {
    max-width: 28rem;
  }

  .sm\:max-w-sm {
    max-width: 24rem;
  }

  .sm\:grid-cols-2 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .sm\:grid-cols-3 {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  .sm\:grid-cols-4 {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }

  .sm\:grid-cols-7 {
    grid-template-columns: repeat(7, minmax(0, 1fr));
  }

  .sm\:flex-row {
    flex-direction: row;
  }

  .sm\:flex-col {
    flex-direction: column;
  }

  .sm\:items-center {
    align-items: center;
  }

  .sm\:justify-end {
    justify-content: flex-end;
  }

  .sm\:gap-2 {
    gap: 0.5rem;
  }

  .sm\:p-4 {
    padding: 1rem;
  }

  .sm\:p-5 {
    padding: 1.25rem;
  }

  .sm\:p-6 {
    padding: 1.5rem;
  }

  .sm\:text-left {
    text-align: left;
  }

  .sm\:text-5xl {
    font-size: 3rem;
    line-height: 1;
  }

  .data-\[vaul-drawer-direction\=left\]\:sm\:max-w-sm[data-vaul-drawer-direction="left"] {
    max-width: 24rem;
  }

  .data-\[vaul-drawer-direction\=right\]\:sm\:max-w-sm[data-vaul-drawer-direction="right"] {
    max-width: 24rem;
  }
}

@media (min-width: 768px) {

  .md\:-mx-4 {
    margin-left: -1rem;
    margin-right: -1rem;
  }

  .md\:mb-2 {
    margin-bottom: 0.5rem;
  }

  .md\:mb-3 {
    margin-bottom: 0.75rem;
  }

  .md\:mt-3 {
    margin-top: 0.75rem;
  }

  .md\:h-5 {
    height: 1.25rem;
  }

  .md\:w-5 {
    width: 1.25rem;
  }

  .md\:grid-cols-2 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .md\:grid-cols-3 {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  .md\:grid-cols-4 {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }

  .md\:gap-1\.5 {
    gap: 0.375rem;
  }

  .md\:gap-2 {
    gap: 0.5rem;
  }

  .md\:gap-3 {
    gap: 0.75rem;
  }

  .md\:gap-4 {
    gap: 1rem;
  }

  .md\:space-y-2 > :not([hidden]) ~ :not([hidden]) {
    --tw-space-y-reverse: 0;
    margin-top: calc(0.5rem * calc(1 - var(--tw-space-y-reverse)));
    margin-bottom: calc(0.5rem * var(--tw-space-y-reverse));
  }

  .md\:space-y-4 > :not([hidden]) ~ :not([hidden]) {
    --tw-space-y-reverse: 0;
    margin-top: calc(1rem * calc(1 - var(--tw-space-y-reverse)));
    margin-bottom: calc(1rem * var(--tw-space-y-reverse));
  }

  .md\:space-y-6 > :not([hidden]) ~ :not([hidden]) {
    --tw-space-y-reverse: 0;
    margin-top: calc(1.5rem * calc(1 - var(--tw-space-y-reverse)));
    margin-bottom: calc(1.5rem * var(--tw-space-y-reverse));
  }

  .md\:rounded-lg {
    border-radius: var(--radius);
  }

  .md\:p-2 {
    padding: 0.5rem;
  }

  .md\:p-4 {
    padding: 1rem;
  }

  .md\:p-6 {
    padding: 1.5rem;
  }

  .md\:px-4 {
    padding-left: 1rem;
    padding-right: 1rem;
  }

  .md\:px-6 {
    padding-left: 1.5rem;
    padding-right: 1.5rem;
  }

  .md\:py-6 {
    padding-top: 1.5rem;
    padding-bottom: 1.5rem;
  }

  .md\:text-left {
    text-align: left;
  }

  .md\:text-2xl {
    font-size: 1.5rem;
    line-height: 2rem;
  }

  .md\:text-base {
    font-size: 1rem;
    line-height: 1.5rem;
  }

  .md\:text-lg {
    font-size: 1.125rem;
    line-height: 1.75rem;
  }

  .md\:text-sm {
    font-size: 0.875rem;
    line-height: 1.25rem;
  }

  .md\:text-xl {
    font-size: 1.25rem;
    line-height: 1.75rem;
  }

  .md\:text-xs {
    font-size: 0.75rem;
    line-height: 1rem;
  }
}

.\[\&\>svg\]\:pointer-events-none>svg {
  pointer-events: none;
}

.\[\&\>svg\]\:size-3>svg {
  width: 0.75rem;
  height: 0.75rem;
}

.\[\&\>svg\]\:size-4>svg {
  width: 1rem;
  height: 1rem;
}

.\[\&\>svg\]\:translate-y-0\.5>svg {
  --tw-translate-y: 0.125rem;
  transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}

.\[\&\>svg\]\:text-current>svg {
  color: currentColor;
}

.\[\&_p\]\:leading-relaxed p {
  line-height: 1.625;
}

.\[\&_svg\:not\(\[class\*\=\'size-\'\]\)\]\:size-4 svg:not([class*='size-']) {
  width: 1rem;
  height: 1rem;
}

.\[\&_svg\:not\(\[class\*\=\'size-\'\]\)\]\:size-5 svg:not([class*='size-']) {
  width: 1.25rem;
  height: 1.25rem;
}

.\[\&_svg\:not\(\[class\*\=\'text-\'\]\)\]\:text-muted-foreground svg:not([class*='text-']) {
  color: oklch(var(--muted-foreground));
}

.\[\&_svg\]\:pointer-events-none svg {
  pointer-events: none;
}

.\[\&_svg\]\:shrink-0 svg {
  flex-shrink: 0;
}

a.\[a\&\]\:hover\:bg-accent:hover {
  background-color: oklch(var(--accent));
}

a.\[a\&\]\:hover\:text-accent-foreground:hover {
  color: oklch(var(--accent-foreground));
}
