*, ::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: var(--font-mono), 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 {
    --font-display: "Space Grotesk", sans-serif;
    --font-body: "Satoshi", sans-serif;
    --font-mono: "JetBrains Mono", monospace;
    --radius: 0.75rem;

    --background: 0.12 0.0 0;
    --foreground: 0.92 0.0 0;
    --card: 0.16 0.012 260;
    --card-foreground: 0.92 0.0 0;
    --popover: 0.18 0.012 260;
    --popover-foreground: 0.92 0.0 0;

    --primary: 0.72 0.17 70;
    --primary-foreground: 0.12 0.0 0;

    --secondary: 0.2 0.015 260;
    --secondary-foreground: 0.82 0.0 0;
    --muted: 0.2 0.015 260;
    --muted-foreground: 0.52 0.01 260;

    --accent: 0.58 0.14 25;
    --accent-foreground: 0.95 0.0 0;

    --destructive: 0.55 0.22 25;
    --destructive-foreground: 0.92 0.0 0;

    --border: 0.25 0.015 260;
    --input: 0.25 0.015 260;
    --ring: 0.72 0.17 70;

    --chart-1: 0.49 0.24 264;
    --chart-2: 0.7 0.17 162;
    --chart-3: 0.77 0.19 70;
    --chart-4: 0.63 0.27 304;
    --chart-5: 0.65 0.25 16;

    --sidebar: 0.14 0.015 260;
    --sidebar-foreground: 0.92 0.0 0;
    --sidebar-primary: 0.72 0.17 70;
    --sidebar-primary-foreground: 0.12 0.0 0;
    --sidebar-accent: 0.2 0.015 260;
    --sidebar-accent-foreground: 0.82 0.0 0;
    --sidebar-border: 0.25 0.015 260;
    --sidebar-ring: 0.72 0.17 70;

    --success: 0.6 0.16 150;
    --warning: 0.72 0.15 85;

    /* Rarity tokens — strong text contrast against each badge background.
       Backgrounds are deep, low-lightness tints; foregrounds are bright,
       high-lightness hues so the label reads clearly in dark mode. */
    --rarity-common-bg: 0.42 0.0 0;
    --rarity-common-fg: 0.95 0.0 0;
    --rarity-common-border: 0.52 0.0 0;

    --rarity-uncommon-bg: 0.55 0.14 150;
    --rarity-uncommon-fg: 0.92 0.22 150;
    --rarity-uncommon-border: 0.65 0.18 150;

    --rarity-rare-bg: 0.5 0.16 250;
    --rarity-rare-fg: 0.92 0.2 250;
    --rarity-rare-border: 0.6 0.2 250;

    --rarity-epic-bg: 0.52 0.16 305;
    --rarity-epic-fg: 0.92 0.22 305;
    --rarity-epic-border: 0.62 0.2 305;

    --rarity-legendary-bg: 0.58 0.14 85;
    --rarity-legendary-fg: 0.95 0.18 85;
    --rarity-legendary-border: 0.68 0.18 85;

    /* Pass 5 — offline fallback page + maskable icon support.
       Tuned for the offline shell: a slightly warmer elevated surface
       so the "you are offline" page reads as a deliberate state, not
       an error. Amber primary and coral accent are unchanged. */
    --offline-background: 0.12 0.0 0;
    --offline-surface: 0.16 0.012 260;
    --offline-foreground: 0.92 0.0 0;
    --offline-muted-foreground: 0.52 0.01 260;
    --offline-border: 0.25 0.015 260;

    /* Skeleton shimmer — three stops for the diagonal sweep.
       Base = muted fill, peak = warm-tinted highlight that lifts the
       surface without introducing a new hue. Consumed by the
       skeleton-shimmer keyframe background gradient. */
    --skeleton-base: 0.2 0.015 260;
    --skeleton-peak: 0.28 0.02 70;
    --skeleton-edge: 0.16 0.012 260;

    /* Bloodlines showcase — warm amber scrim that rises from the
       bottom of each representative image so the bloodline name
       stays legible over any dog photo. Two stops: transparent at
       the top of the scrim, near-OLED-black at the base. No new hue
       introduced — uses the background token's lightness. */
    --bloodline-scrim-top: 0.12 0.0 0 / 0;
    --bloodline-scrim-bottom: 0.12 0.0 0 / 0.78;

    /* Signature-look trait chip — a faintly warm-tinted muted
       surface with a hairline border and amber-tinted label text.
       Distinct from the rarity badges (gaming tiers) and the
       generic muted pills: slightly warmer, with a primary-tinted
       leading dot so the trait list reads as curated, not
       auto-generated. */
    --trait-chip-bg: 0.2 0.018 70;
    --trait-chip-border: 0.3 0.02 70;
    --trait-chip-fg: 0.82 0.03 70;
    --trait-chip-dot: 0.72 0.17 70;

    /* Bloodline carousel — chevron control surface. Reuses the
       --card token at high opacity with a backdrop blur so the
       controls read as part of the same curated overlay family as
       the count badge (same blur, same warm card tint). The border
       uses --trait-chip-border so the chevrons tie visually to the
       trait chips below. Icon color is --primary (amber) so the
       controls feel like the active accent on the card. */
    --bloodline-carousel-control-bg: 0.16 0.012 260 / 0.72;
    --bloodline-carousel-control-border: 0.3 0.02 70;
    --bloodline-carousel-control-fg: 0.72 0.17 70;
    --bloodline-carousel-control-fg-muted: 0.82 0.03 70 / 0.55;

    /* Pass 6 — Dashboard, Marketplace & My Dogs tokens. Extends the
       existing warm-darkness palette; no new hue families. The
       conditioning-low tint reuses the destructive hue (25) at lower
       chroma so a sub-40% meter reads as "needs work" without
       screaming error. The listing-sold muted variant desaturates
       the primary amber to a near-neutral so a sold badge clearly
       differs from an active amber listing. The burn-fee token
       tints the 2% platform-fee line item with a faint destructive
       hue so the "burned" label reads as a real cost, not a
       decorative row. */
    --conditioning-low-bg: 0.32 0.08 25;
    --conditioning-low-fg: 0.72 0.16 25;
    --conditioning-low-border: 0.45 0.12 25;

    --listing-sold-bg: 0.28 0.01 260;
    --listing-sold-fg: 0.62 0.01 260;
    --listing-sold-border: 0.38 0.01 260;

    --burn-fee-fg: 0.7 0.12 25;
    --burn-fee-border: 0.4 0.08 25 / 0.4;

    /* Milestone amber gradient stops — reuse primary + accent so
       the milestone bar ties to the existing gradient-primary. */
    --milestone-fill-from: 0.72 0.17 70;
    --milestone-fill-to: 0.58 0.14 25;

    /* Pass 7 — Show System v1 gameplay tokens. Extends the
       warm-darkness palette; no new hue families. Energy uses a
       cool cyan-teal hue (220) to distinguish it from the warm
       conditioning bar (amber→coral) so the two gauges never
       read as the same meter. Conditioning medium/high reuse the
       existing amber/coral gradient; low reuses the destructive
       hue. Stat bars use a muted amber fill so six bars in a row
       don't overpower the screen. XP/level uses the primary amber
       gradient. NPC opponent uses a desaturated violet (290) at
       low chroma so the rival reads as neutral-foreign, not
       aggressive. Show result win = success green tint, loss =
       destructive coral tint. */
    --energy-fill-from: 0.62 0.13 220;
    --energy-fill-to: 0.72 0.1 200;
    --energy-low-fg: 0.55 0.14 25;

    --conditioning-medium-fg: 0.72 0.15 85;
    --conditioning-high-fg: 0.6 0.16 150;

    --stat-bar-fill: 0.68 0.12 70;
    --stat-bar-fill-strong: 0.72 0.17 70;

    --xp-fill-from: 0.72 0.17 70;
    --xp-fill-to: 0.62 0.13 220;

    --npc-opponent-bg: 0.18 0.02 290;
    --npc-opponent-border: 0.3 0.04 290;
    --npc-opponent-fg: 0.82 0.03 290;
    --npc-opponent-accent: 0.62 0.1 290;

    --show-win-bg: 0.2 0.03 150;
    --show-win-border: 0.4 0.1 150;
    --show-win-fg: 0.82 0.16 150;
    --show-loss-bg: 0.2 0.03 25;
    --show-loss-border: 0.4 0.1 25;
    --show-loss-fg: 0.78 0.14 25;

    /* Breakthrough golden treatment — a rare, premium moment. Warm
       gold (hue 85) at higher chroma than the primary amber so it
       reads as distinct from a normal success. Used on the
       training-result breakthrough callout, headline glow, and the
       stat-gain popups when a breakthrough fires. */
    --breakthrough-bg: 0.22 0.05 85;
    --breakthrough-border: 0.55 0.14 85;
    --breakthrough-fg: 0.92 0.16 85;
    --breakthrough-glow: 0.85 0.18 85;
    --breakthrough-accent: 0.78 0.16 85;

    --training-activity-bg: 0.2 0.018 70;
    --training-activity-border: 0.3 0.02 70;
    --training-activity-hover: 0.25 0.025 70;

    --level-badge-bg: 0.72 0.17 70;
    --level-badge-fg: 0.12 0.0 0;

    /* Pass 8 — Training intensity selector + fatigue badge tokens.
       Three intensity tiers reuse existing hue families so the
       toggle reads as part of the warm-darkness system: light uses
       the cool energy hue (220) for a "gentle" read, standard uses
       the primary amber (70), intense uses the destructive coral
       (25) to signal higher cost + fatigue risk. The fatigue badge
       reuses the warning hue (85) so a fatigued dog reads as
       "needs rest" without reading as an error. */
    --intensity-light-bg: 0.2 0.02 220;
    --intensity-light-border: 0.3 0.04 220;
    --intensity-light-fg: 0.82 0.06 220;
    --intensity-standard-bg: 0.2 0.025 70;
    --intensity-standard-border: 0.32 0.04 70;
    --intensity-standard-fg: 0.82 0.06 70;
    --intensity-intense-bg: 0.2 0.03 25;
    --intensity-intense-border: 0.34 0.06 25;
    --intensity-intense-fg: 0.82 0.08 25;
    --intensity-active-bg: 0.3 0.05 70;
    --intensity-active-border: 0.55 0.1 70;

    --fatigue-badge-bg: 0.3 0.08 85;
    --fatigue-badge-border: 0.5 0.12 85;
    --fatigue-badge-fg: 0.9 0.14 85;

    /* Pass 9 — Daily Streak / Flame system tokens. Introduces a
       flame-orange hue (35) distinct from the primary amber (70),
       accent coral (25), and warning gold (85). The flame reads as
       a lit match — warmer than amber, more orange than coral. The
       ember variant is a deeper, lower-chroma flame tone used for
       the gentle broken-streak state (no shaming). Track tokens
       cover the 7-day reward track states: claimed (muted),
       current (flame-tinted, active), locked (very dim). */
    --flame-fg: 0.75 0.19 35;
    --flame-bg: 0.22 0.05 35;
    --flame-border: 0.42 0.1 35;
    --flame-glow: 0.78 0.21 35;
    --flame-ember: 0.5 0.08 35;
    --flame-track-bg: 0.2 0.015 260;
    --flame-track-claimed: 0.28 0.01 260;
    --flame-track-current: 0.3 0.06 35;
    --flame-track-locked: 0.18 0.008 260;
    --streak-broken-fg: 0.62 0.04 35;

    /* Grace toast — a calm sage-green hue (160) distinct from the
       flame-orange (35), reward amber (70), and destructive coral
       (25) families. Used for grace-period / second-chance toasts
       (e.g. "Streak safe — grace window active"). Reads as gentle
       reassurance, not a reward or a warning. */
    --grace-toast-bg: 0.22 0.04 160;
    --grace-toast-border: 0.4 0.1 160;
    --grace-toast-fg: 0.82 0.12 160;
    --grace-toast-accent: 0.72 0.14 160;
  }

  .dark {
    --background: 0.12 0.0 0;
    --foreground: 0.92 0.0 0;
    --card: 0.16 0.012 260;
    --card-foreground: 0.92 0.0 0;
    --popover: 0.18 0.012 260;
    --popover-foreground: 0.92 0.0 0;

    --primary: 0.72 0.17 70;
    --primary-foreground: 0.12 0.0 0;

    --secondary: 0.2 0.015 260;
    --secondary-foreground: 0.82 0.0 0;
    --muted: 0.2 0.015 260;
    --muted-foreground: 0.52 0.01 260;

    --accent: 0.58 0.14 25;
    --accent-foreground: 0.95 0.0 0;

    --destructive: 0.55 0.22 25;
    --destructive-foreground: 0.92 0.0 0;

    --border: 0.25 0.015 260;
    --input: 0.25 0.015 260;
    --ring: 0.72 0.17 70;

    --chart-1: 0.49 0.24 264;
    --chart-2: 0.7 0.17 162;
    --chart-3: 0.77 0.19 70;
    --chart-4: 0.63 0.27 304;
    --chart-5: 0.65 0.25 16;

    --sidebar: 0.14 0.015 260;
    --sidebar-foreground: 0.92 0.0 0;
    --sidebar-primary: 0.72 0.17 70;
    --sidebar-primary-foreground: 0.12 0.0 0;
    --sidebar-accent: 0.2 0.015 260;
    --sidebar-accent-foreground: 0.82 0.0 0;
    --sidebar-border: 0.25 0.015 260;
    --sidebar-ring: 0.72 0.17 70;

    --success: 0.6 0.16 150;
    --warning: 0.72 0.15 85;

    --rarity-common-bg: 0.42 0.0 0;
    --rarity-common-fg: 0.95 0.0 0;
    --rarity-common-border: 0.52 0.0 0;

    --rarity-uncommon-bg: 0.55 0.14 150;
    --rarity-uncommon-fg: 0.92 0.22 150;
    --rarity-uncommon-border: 0.65 0.18 150;

    --rarity-rare-bg: 0.5 0.16 250;
    --rarity-rare-fg: 0.92 0.2 250;
    --rarity-rare-border: 0.6 0.2 250;

    --rarity-epic-bg: 0.52 0.16 305;
    --rarity-epic-fg: 0.92 0.22 305;
    --rarity-epic-border: 0.62 0.2 305;

    --rarity-legendary-bg: 0.58 0.14 85;
    --rarity-legendary-fg: 0.95 0.18 85;
    --rarity-legendary-border: 0.68 0.18 85;

    /* Pass 5 — offline fallback page + maskable icon support (dark). */
    --offline-background: 0.12 0.0 0;
    --offline-surface: 0.16 0.012 260;
    --offline-foreground: 0.92 0.0 0;
    --offline-muted-foreground: 0.52 0.01 260;
    --offline-border: 0.25 0.015 260;

    /* Skeleton shimmer stops (dark). */
    --skeleton-base: 0.2 0.015 260;
    --skeleton-peak: 0.28 0.02 70;
    --skeleton-edge: 0.16 0.012 260;

    /* Bloodlines showcase (dark) — same warm amber scrim and
       trait-chip tokens as :root. Re-declared here so .dark
       remains the single source of truth when the class is
       toggled, matching the existing pattern for other tokens. */
    --bloodline-scrim-top: 0.12 0.0 0 / 0;
    --bloodline-scrim-bottom: 0.12 0.0 0 / 0.78;
    --trait-chip-bg: 0.2 0.018 70;
    --trait-chip-border: 0.3 0.02 70;
    --trait-chip-fg: 0.82 0.03 70;
    --trait-chip-dot: 0.72 0.17 70;

    /* Bloodline carousel controls (dark) — same tokens as :root. */
    --bloodline-carousel-control-bg: 0.16 0.012 260 / 0.72;
    --bloodline-carousel-control-border: 0.3 0.02 70;
    --bloodline-carousel-control-fg: 0.72 0.17 70;
    --bloodline-carousel-control-fg-muted: 0.82 0.03 70 / 0.55;

    /* Pass 6 — Dashboard, Marketplace & My Dogs tokens. Extends the
       existing warm-darkness palette; no new hue families. The
       conditioning-low tint reuses the destructive hue (25) at lower
       chroma so a sub-40% meter reads as "needs work" without
       screaming error. The listing-sold muted variant desaturates
       the primary amber to a near-neutral so a sold badge clearly
       differs from an active amber listing. The burn-fee token
       tints the 2% platform-fee line item with a faint destructive
       hue so the "burned" label reads as a real cost, not a
       decorative row. */
    --conditioning-low-bg: 0.32 0.08 25;
    --conditioning-low-fg: 0.72 0.16 25;
    --conditioning-low-border: 0.45 0.12 25;

    --listing-sold-bg: 0.28 0.01 260;
    --listing-sold-fg: 0.62 0.01 260;
    --listing-sold-border: 0.38 0.01 260;

    --burn-fee-fg: 0.7 0.12 25;
    --burn-fee-border: 0.4 0.08 25 / 0.4;

    /* Milestone amber gradient stops — reuse primary + accent so
       the milestone bar ties to the existing gradient-primary. */
    --milestone-fill-from: 0.72 0.17 70;
    --milestone-fill-to: 0.58 0.14 25;

    /* Pass 7 — Show System v1 gameplay tokens (dark). Mirrors the
       :root block so .dark remains the single source of truth when
       the class is toggled, matching the existing pattern. */
    --energy-fill-from: 0.62 0.13 220;
    --energy-fill-to: 0.72 0.1 200;
    --energy-low-fg: 0.55 0.14 25;

    --conditioning-medium-fg: 0.72 0.15 85;
    --conditioning-high-fg: 0.6 0.16 150;

    --stat-bar-fill: 0.68 0.12 70;
    --stat-bar-fill-strong: 0.72 0.17 70;

    --xp-fill-from: 0.72 0.17 70;
    --xp-fill-to: 0.62 0.13 220;

    --npc-opponent-bg: 0.18 0.02 290;
    --npc-opponent-border: 0.3 0.04 290;
    --npc-opponent-fg: 0.82 0.03 290;
    --npc-opponent-accent: 0.62 0.1 290;

    --show-win-bg: 0.2 0.03 150;
    --show-win-border: 0.4 0.1 150;
    --show-win-fg: 0.82 0.16 150;
    --show-loss-bg: 0.2 0.03 25;
    --show-loss-border: 0.4 0.1 25;
    --show-loss-fg: 0.78 0.14 25;

    /* Breakthrough golden treatment — a rare, premium moment. Warm
       gold (hue 85) at higher chroma than the primary amber so it
       reads as distinct from a normal success. Used on the
       training-result breakthrough callout, headline glow, and the
       stat-gain popups when a breakthrough fires. */
    --breakthrough-bg: 0.22 0.05 85;
    --breakthrough-border: 0.55 0.14 85;
    --breakthrough-fg: 0.92 0.16 85;
    --breakthrough-glow: 0.85 0.18 85;
    --breakthrough-accent: 0.78 0.16 85;

    --training-activity-bg: 0.2 0.018 70;
    --training-activity-border: 0.3 0.02 70;
    --training-activity-hover: 0.25 0.025 70;

    --level-badge-bg: 0.72 0.17 70;
    --level-badge-fg: 0.12 0.0 0;

    /* Pass 8 — Training intensity selector + fatigue badge tokens
       (dark). Mirrors the :root block so .dark remains the single
       source of truth when the class is toggled. */
    --intensity-light-bg: 0.2 0.02 220;
    --intensity-light-border: 0.3 0.04 220;
    --intensity-light-fg: 0.82 0.06 220;
    --intensity-standard-bg: 0.2 0.025 70;
    --intensity-standard-border: 0.32 0.04 70;
    --intensity-standard-fg: 0.82 0.06 70;
    --intensity-intense-bg: 0.2 0.03 25;
    --intensity-intense-border: 0.34 0.06 25;
    --intensity-intense-fg: 0.82 0.08 25;
    --intensity-active-bg: 0.3 0.05 70;
    --intensity-active-border: 0.55 0.1 70;

    --fatigue-badge-bg: 0.3 0.08 85;
    --fatigue-badge-border: 0.5 0.12 85;
    --fatigue-badge-fg: 0.9 0.14 85;

    /* Pass 9 — Daily Streak / Flame system tokens (dark). Mirrors
       the :root block so .dark remains the single source of truth
       when the class is toggled, matching the existing pattern. */
    --flame-fg: 0.75 0.19 35;
    --flame-bg: 0.22 0.05 35;
    --flame-border: 0.42 0.1 35;
    --flame-glow: 0.78 0.21 35;
    --flame-ember: 0.5 0.08 35;
    --flame-track-bg: 0.2 0.015 260;
    --flame-track-claimed: 0.28 0.01 260;
    --flame-track-current: 0.3 0.06 35;
    --flame-track-locked: 0.18 0.008 260;
    --streak-broken-fg: 0.62 0.04 35;

    /* Grace toast (dark) — mirrors the :root block so .dark remains
       the single source of truth when the class is toggled. */
    --grace-toast-bg: 0.22 0.04 160;
    --grace-toast-border: 0.4 0.1 160;
    --grace-toast-fg: 0.82 0.12 160;
    --grace-toast-accent: 0.72 0.14 160;
  }

  * {
  border-color: oklch(var(--border));
}
  body {
  background-color: oklch(var(--background));
  font-family: var(--font-body), sans-serif;
  color: oklch(var(--foreground));
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

  /* Global focus-visible ring for interactive elements that don't
     define their own. Uses the --primary OKLCH token via --ring.
     Honors prefers-reduced-motion (no transition on the outline).
     The stat-slider and filter-switch rules below keep their own
     focus-visible styles intact. */
  :focus-visible {
    outline: 2px solid oklch(var(--ring));
    outline-offset: 2px;
  }

  @media (prefers-reduced-motion: reduce) {
    :focus-visible {
      transition: none;
    }
  }
.container {
  width: 100%;
  margin-right: auto;
  margin-left: auto;
  padding-right: 2rem;
  padding-left: 2rem;
}
@media (min-width: 1400px) {

  .container {
    max-width: 1400px;
  }
}
.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-12 {
  bottom: -3rem;
}
.-left-12 {
  left: -3rem;
}
.-right-12 {
  right: -3rem;
}
.-top-12 {
  top: -3rem;
}
.bottom-0 {
  bottom: 0px;
}
.left-0 {
  left: 0px;
}
.left-1\/2 {
  left: 50%;
}
.left-10 {
  left: 2.5rem;
}
.left-2 {
  left: 0.5rem;
}
.left-3 {
  left: 0.75rem;
}
.left-\[50\%\] {
  left: 50%;
}
.right-0 {
  right: 0px;
}
.right-1 {
  right: 0.25rem;
}
.right-11 {
  right: 2.75rem;
}
.right-2 {
  right: 0.5rem;
}
.right-3 {
  right: 0.75rem;
}
.right-4 {
  right: 1rem;
}
.top-0 {
  top: 0px;
}
.top-1\/2 {
  top: 50%;
}
.top-14 {
  top: 3.5rem;
}
.top-2 {
  top: 0.5rem;
}
.top-3 {
  top: 0.75rem;
}
.top-4 {
  top: 1rem;
}
.top-\[1px\] {
  top: 1px;
}
.top-\[50\%\] {
  top: 50%;
}
.top-\[60\%\] {
  top: 60%;
}
.top-full {
  top: 100%;
}
.isolate {
  isolation: isolate;
}
.-z-10 {
  z-index: -10;
}
.z-10 {
  z-index: 10;
}
.z-30 {
  z-index: 30;
}
.z-40 {
  z-index: 40;
}
.z-50 {
  z-index: 50;
}
.z-\[1\] {
  z-index: 1;
}
.z-\[2\] {
  z-index: 2;
}
.z-auto {
  z-index: auto;
}
.col-span-1 {
  grid-column: span 1 / span 1;
}
.col-span-2 {
  grid-column: span 2 / span 2;
}
.col-span-3 {
  grid-column: span 3 / span 3;
}
.col-span-4 {
  grid-column: span 4 / span 4;
}
.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;
}
.-mx-1 {
  margin-left: -0.25rem;
  margin-right: -0.25rem;
}
.mx-1 {
  margin-left: 0.25rem;
  margin-right: 0.25rem;
}
.mx-6 {
  margin-left: 1.5rem;
  margin-right: 1.5rem;
}
.mx-auto {
  margin-left: auto;
  margin-right: auto;
}
.my-0\.5 {
  margin-top: 0.125rem;
  margin-bottom: 0.125rem;
}
.my-1 {
  margin-top: 0.25rem;
  margin-bottom: 0.25rem;
}
.-ml-4 {
  margin-left: -1rem;
}
.-mr-1 {
  margin-right: -0.25rem;
}
.-mt-4 {
  margin-top: -1rem;
}
.mb-1 {
  margin-bottom: 0.25rem;
}
.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-8 {
  margin-bottom: 2rem;
}
.ml-0\.5 {
  margin-left: 0.125rem;
}
.ml-1 {
  margin-left: 0.25rem;
}
.ml-2 {
  margin-left: 0.5rem;
}
.ml-auto {
  margin-left: auto;
}
.mr-1 {
  margin-right: 0.25rem;
}
.mr-2 {
  margin-right: 0.5rem;
}
.mt-0\.5 {
  margin-top: 0.125rem;
}
.mt-1 {
  margin-top: 0.25rem;
}
.mt-1\.5 {
  margin-top: 0.375rem;
}
.mt-10 {
  margin-top: 2.5rem;
}
.mt-2 {
  margin-top: 0.5rem;
}
.mt-3 {
  margin-top: 0.75rem;
}
.mt-4 {
  margin-top: 1rem;
}
.mt-6 {
  margin-top: 1.5rem;
}
.mt-8 {
  margin-top: 2rem;
}
.mt-auto {
  margin-top: auto;
}
.line-clamp-1 {
  overflow: hidden;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 1;
}
.block {
  display: block;
}
.inline-block {
  display: inline-block;
}
.inline {
  display: inline;
}
.flex {
  display: flex;
}
.inline-flex {
  display: inline-flex;
}
.table {
  display: table;
}
.table-caption {
  display: table-caption;
}
.table-cell {
  display: table-cell;
}
.table-row {
  display: table-row;
}
.grid {
  display: grid;
}
.contents {
  display: contents;
}
.hidden {
  display: none;
}
.aspect-\[4\/3\] {
  aspect-ratio: 4/3;
}
.aspect-square {
  aspect-ratio: 1 / 1;
}
.aspect-video {
  aspect-ratio: 16 / 9;
}
.size-11 {
  width: 2.75rem;
  height: 2.75rem;
}
.size-12 {
  width: 3rem;
  height: 3rem;
}
.size-14 {
  width: 3.5rem;
  height: 3.5rem;
}
.size-16 {
  width: 4rem;
  height: 4rem;
}
.size-2 {
  width: 0.5rem;
  height: 0.5rem;
}
.size-2\.5 {
  width: 0.625rem;
  height: 0.625rem;
}
.size-3 {
  width: 0.75rem;
  height: 0.75rem;
}
.size-3\.5 {
  width: 0.875rem;
  height: 0.875rem;
}
.size-4 {
  width: 1rem;
  height: 1rem;
}
.size-5 {
  width: 1.25rem;
  height: 1.25rem;
}
.size-6 {
  width: 1.5rem;
  height: 1.5rem;
}
.size-7 {
  width: 1.75rem;
  height: 1.75rem;
}
.size-8 {
  width: 2rem;
  height: 2rem;
}
.size-9 {
  width: 2.25rem;
  height: 2.25rem;
}
.size-auto {
  width: auto;
  height: auto;
}
.size-full {
  width: 100%;
  height: 100%;
}
.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-3 {
  height: 0.75rem;
}
.h-3\.5 {
  height: 0.875rem;
}
.h-32 {
  height: 8rem;
}
.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-\[120\%\] {
  height: 120%;
}
.h-\[140\%\] {
  height: 140%;
}
.h-\[calc\(100\%-1px\)\] {
  height: calc(100% - 1px);
}
.h-\[var\(--radix-navigation-menu-viewport-height\)\] {
  height: var(--radix-navigation-menu-viewport-height);
}
.h-\[var\(--radix-select-trigger-height\)\] {
  height: var(--radix-select-trigger-height);
}
.h-auto {
  height: auto;
}
.h-full {
  height: 100%;
}
.h-px {
  height: 1px;
}
.max-h-48 {
  max-height: 12rem;
}
.max-h-64 {
  max-height: 16rem;
}
.max-h-\[280px\] {
  max-height: 280px;
}
.max-h-\[300px\] {
  max-height: 300px;
}
.max-h-\[60vh\] {
  max-height: 60vh;
}
.max-h-\[88vh\] {
  max-height: 88vh;
}
.max-h-\[90dvh\] {
  max-height: 90dvh;
}
.max-h-\[90vh\] {
  max-height: 90vh;
}
.max-h-\[92vh\] {
  max-height: 92vh;
}
.min-h-0 {
  min-height: 0px;
}
.min-h-11 {
  min-height: 2.75rem;
}
.min-h-12 {
  min-height: 3rem;
}
.min-h-16 {
  min-height: 4rem;
}
.min-h-24 {
  min-height: 6rem;
}
.min-h-4 {
  min-height: 1rem;
}
.min-h-8 {
  min-height: 2rem;
}
.min-h-\[11rem\] {
  min-height: 11rem;
}
.min-h-\[180px\] {
  min-height: 180px;
}
.min-h-\[2\.75rem\] {
  min-height: 2.75rem;
}
.min-h-\[40vh\] {
  min-height: 40vh;
}
.min-h-\[44px\] {
  min-height: 44px;
}
.min-h-\[60vh\] {
  min-height: 60vh;
}
.min-h-screen {
  min-height: 100vh;
}
.w-0 {
  width: 0px;
}
.w-1 {
  width: 0.25rem;
}
.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-2\/3 {
  width: 66.666667%;
}
.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-3\/5 {
  width: 60%;
}
.w-32 {
  width: 8rem;
}
.w-4 {
  width: 1rem;
}
.w-40 {
  width: 10rem;
}
.w-48 {
  width: 12rem;
}
.w-5 {
  width: 1.25rem;
}
.w-5\/6 {
  width: 83.333333%;
}
.w-56 {
  width: 14rem;
}
.w-6 {
  width: 1.5rem;
}
.w-64 {
  width: 16rem;
}
.w-72 {
  width: 18rem;
}
.w-8 {
  width: 2rem;
}
.w-9 {
  width: 2.25rem;
}
.w-\[100px\] {
  width: 100px;
}
.w-\[120\%\] {
  width: 120%;
}
.w-\[140\%\] {
  width: 140%;
}
.w-fit {
  width: -moz-fit-content;
  width: fit-content;
}
.w-full {
  width: 100%;
}
.w-max {
  width: -moz-max-content;
  width: max-content;
}
.w-px {
  width: 1px;
}
.min-w-0 {
  min-width: 0px;
}
.min-w-10 {
  min-width: 2.5rem;
}
.min-w-11 {
  min-width: 2.75rem;
}
.min-w-8 {
  min-width: 2rem;
}
.min-w-9 {
  min-width: 2.25rem;
}
.min-w-\[1\.25rem\] {
  min-width: 1.25rem;
}
.min-w-\[12rem\] {
  min-width: 12rem;
}
.min-w-\[200px\] {
  min-width: 200px;
}
.min-w-\[640px\] {
  min-width: 640px;
}
.min-w-\[860px\] {
  min-width: 860px;
}
.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-7xl {
  max-width: 80rem;
}
.max-w-\[160px\] {
  max-width: 160px;
}
.max-w-\[180px\] {
  max-width: 180px;
}
.max-w-\[200px\] {
  max-width: 200px;
}
.max-w-\[320px\] {
  max-width: 320px;
}
.max-w-\[560px\] {
  max-width: 560px;
}
.max-w-\[calc\(100\%-2rem\)\] {
  max-width: calc(100% - 2rem);
}
.max-w-lg {
  max-width: 32rem;
}
.max-w-max {
  max-width: -moz-max-content;
  max-width: max-content;
}
.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-shrink-0 {
  flex-shrink: 0;
}
.shrink-0 {
  flex-shrink: 0;
}
.grow {
  flex-grow: 1;
}
.grow-0 {
  flex-grow: 0;
}
.basis-full {
  flex-basis: 100%;
}
.caption-bottom {
  caption-side: bottom;
}
.border-collapse {
  border-collapse: collapse;
}
.-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-0\.5 {
  --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));
}
.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-90 {
  --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));
}
.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 bar-fill {

  from {
    width: 0%;
  }
}
.animate-bar-fill {
  animation: bar-fill 0.5s cubic-bezier(0.4, 0, 0.2, 1) both;
}
@keyframes level-up-flash {

  0% {
    box-shadow: 0 0 0 0 oklch(0.72 0.17 70 / 0.6);
  }

  50% {
    box-shadow: 0 0 0 12px oklch(0.72 0.17 70 / 0.25);
  }

  100% {
    box-shadow: 0 0 0 0 oklch(0.72 0.17 70 / 0);
  }
}
.animate-level-up-flash {
  animation: level-up-flash 0.6s ease-out;
}
@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 win-celebration {

  0% {
    transform: scale(0.96);
    opacity: 0;
  }

  60% {
    transform: scale(1.02);
    opacity: 1;
  }

  100% {
    transform: scale(1);
    opacity: 1;
  }
}
.animate-win-celebration {
  animation: win-celebration 0.5s cubic-bezier(0.16, 1, 0.3, 1) both;
}
.cursor-default {
  cursor: default;
}
.cursor-not-allowed {
  cursor: not-allowed;
}
.cursor-pointer {
  cursor: pointer;
}
.touch-none {
  touch-action: none;
}
.select-none {
  -webkit-user-select: none;
     -moz-user-select: none;
          user-select: none;
}
.resize-none {
  resize: none;
}
.resize-y {
  resize: vertical;
}
.resize {
  resize: both;
}
.scroll-my-1 {
  scroll-margin-top: 0.25rem;
  scroll-margin-bottom: 0.25rem;
}
.scroll-py-1 {
  scroll-padding-top: 0.25rem;
  scroll-padding-bottom: 0.25rem;
}
.list-none {
  list-style-type: none;
}
.auto-rows-min {
  grid-auto-rows: min-content;
}
.grid-cols-1 {
  grid-template-columns: repeat(1, minmax(0, 1fr));
}
.grid-cols-12 {
  grid-template-columns: repeat(12, 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-\[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;
}
.flex-nowrap {
  flex-wrap: nowrap;
}
.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-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-6 {
  gap: 1.5rem;
}
.gap-x-3 {
  -moz-column-gap: 0.75rem;
       column-gap: 0.75rem;
}
.gap-x-4 {
  -moz-column-gap: 1rem;
       column-gap: 1rem;
}
.gap-y-0\.5 {
  row-gap: 0.125rem;
}
.gap-y-2 {
  row-gap: 0.5rem;
}
.gap-y-3 {
  row-gap: 0.75rem;
}
.space-y-0\.5 > :not([hidden]) ~ :not([hidden]) {
  --tw-space-y-reverse: 0;
  margin-top: calc(0.125rem * calc(1 - var(--tw-space-y-reverse)));
  margin-bottom: calc(0.125rem * 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-10 > :not([hidden]) ~ :not([hidden]) {
  --tw-space-y-reverse: 0;
  margin-top: calc(2.5rem * calc(1 - var(--tw-space-y-reverse)));
  margin-bottom: calc(2.5rem * 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));
}
.divide-y > :not([hidden]) ~ :not([hidden]) {
  --tw-divide-y-reverse: 0;
  border-top-width: calc(1px * calc(1 - var(--tw-divide-y-reverse)));
  border-bottom-width: calc(1px * var(--tw-divide-y-reverse));
}
.divide-border > :not([hidden]) ~ :not([hidden]) {
  border-color: oklch(var(--border));
}
.self-start {
  align-self: flex-start;
}
.justify-self-end {
  justify-self: end;
}
.overflow-auto {
  overflow: auto;
}
.overflow-hidden {
  overflow: hidden;
}
.overflow-x-auto {
  overflow-x: auto;
}
.overflow-y-auto {
  overflow-y: auto;
}
.overflow-x-hidden {
  overflow-x: hidden;
}
.truncate {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.whitespace-nowrap {
  white-space: nowrap;
}
.whitespace-pre-wrap {
  white-space: pre-wrap;
}
.text-balance {
  text-wrap: balance;
}
.break-words {
  overflow-wrap: break-word;
}
.break-all {
  word-break: break-all;
}
.rounded {
  border-radius: 0.25rem;
}
.rounded-2xl {
  border-radius: 1rem;
}
.rounded-\[2px\] {
  border-radius: 2px;
}
.rounded-\[4px\] {
  border-radius: 4px;
}
.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-none {
  border-radius: 0px;
}
.rounded-sm {
  border-radius: calc(var(--radius) - 4px);
}
.rounded-xl {
  border-radius: 0.75rem;
}
.rounded-l-md {
  border-top-left-radius: calc(var(--radius) - 2px);
  border-bottom-left-radius: calc(var(--radius) - 2px);
}
.rounded-r-md {
  border-top-right-radius: calc(var(--radius) - 2px);
  border-bottom-right-radius: calc(var(--radius) - 2px);
}
.rounded-tl-sm {
  border-top-left-radius: calc(var(--radius) - 4px);
}
.border {
  border-width: 1px;
}
.border-0 {
  border-width: 0px;
}
.border-2 {
  border-width: 2px;
}
.border-\[1\.5px\] {
  border-width: 1.5px;
}
.border-\[3px\] {
  border-width: 3px;
}
.border-y {
  border-top-width: 1px;
  border-bottom-width: 1px;
}
.border-b {
  border-bottom-width: 1px;
}
.border-l {
  border-left-width: 1px;
}
.border-r {
  border-right-width: 1px;
}
.border-t {
  border-top-width: 1px;
}
.border-dashed {
  border-style: dashed;
}
.border-accent {
  --tw-border-opacity: 1;
  border-color: oklch(var(--accent) / var(--tw-border-opacity, 1));
}
.border-accent\/30 {
  border-color: oklch(var(--accent) / 0.3);
}
.border-accent\/40 {
  border-color: oklch(var(--accent) / 0.4);
}
.border-border {
  border-color: oklch(var(--border));
}
.border-destructive {
  --tw-border-opacity: 1;
  border-color: oklch(var(--destructive) / var(--tw-border-opacity, 1));
}
.border-destructive\/30 {
  border-color: oklch(var(--destructive) / 0.3);
}
.border-destructive\/40 {
  border-color: oklch(var(--destructive) / 0.4);
}
.border-input {
  border-color: oklch(var(--input));
}
.border-muted-foreground\/30 {
  border-color: oklch(var(--muted-foreground) / 0.3);
}
.border-primary {
  --tw-border-opacity: 1;
  border-color: oklch(var(--primary) / var(--tw-border-opacity, 1));
}
.border-primary\/20 {
  border-color: oklch(var(--primary) / 0.2);
}
.border-primary\/30 {
  border-color: oklch(var(--primary) / 0.3);
}
.border-primary\/40 {
  border-color: oklch(var(--primary) / 0.4);
}
.border-transparent {
  border-color: transparent;
}
.border-l-transparent {
  border-left-color: transparent;
}
.border-t-muted-foreground {
  --tw-border-opacity: 1;
  border-top-color: oklch(var(--muted-foreground) / var(--tw-border-opacity, 1));
}
.border-t-primary {
  --tw-border-opacity: 1;
  border-top-color: oklch(var(--primary) / var(--tw-border-opacity, 1));
}
.border-t-transparent {
  border-top-color: transparent;
}
.bg-accent {
  --tw-bg-opacity: 1;
  background-color: oklch(var(--accent) / var(--tw-bg-opacity, 1));
}
.bg-accent\/10 {
  background-color: oklch(var(--accent) / 0.1);
}
.bg-accent\/15 {
  background-color: oklch(var(--accent) / 0.15);
}
.bg-background {
  background-color: oklch(var(--background));
}
.bg-black\/50 {
  background-color: rgb(0 0 0 / 0.5);
}
.bg-border {
  background-color: oklch(var(--border));
}
.bg-card {
  background-color: oklch(var(--card));
}
.bg-destructive {
  --tw-bg-opacity: 1;
  background-color: oklch(var(--destructive) / var(--tw-bg-opacity, 1));
}
.bg-destructive\/10 {
  background-color: oklch(var(--destructive) / 0.1);
}
.bg-destructive\/20 {
  background-color: oklch(var(--destructive) / 0.2);
}
.bg-destructive\/5 {
  background-color: oklch(var(--destructive) / 0.05);
}
.bg-foreground {
  background-color: oklch(var(--foreground));
}
.bg-muted {
  --tw-bg-opacity: 1;
  background-color: oklch(var(--muted) / var(--tw-bg-opacity, 1));
}
.bg-muted\/20 {
  background-color: oklch(var(--muted) / 0.2);
}
.bg-muted\/30 {
  background-color: oklch(var(--muted) / 0.3);
}
.bg-muted\/40 {
  background-color: oklch(var(--muted) / 0.4);
}
.bg-muted\/50 {
  background-color: oklch(var(--muted) / 0.5);
}
.bg-muted\/60 {
  background-color: oklch(var(--muted) / 0.6);
}
.bg-popover {
  background-color: oklch(var(--popover));
}
.bg-primary {
  --tw-bg-opacity: 1;
  background-color: oklch(var(--primary) / var(--tw-bg-opacity, 1));
}
.bg-primary\/10 {
  background-color: oklch(var(--primary) / 0.1);
}
.bg-primary\/20 {
  background-color: oklch(var(--primary) / 0.2);
}
.bg-primary\/5 {
  background-color: oklch(var(--primary) / 0.05);
}
.bg-secondary {
  --tw-bg-opacity: 1;
  background-color: oklch(var(--secondary) / var(--tw-bg-opacity, 1));
}
.bg-transparent {
  background-color: transparent;
}
.bg-\[linear-gradient\(135deg\2c oklch\(var\(--destructive\)\)\2c oklch\(var\(--accent\)\)\)\] {
  background-image: linear-gradient(135deg,oklch(var(--destructive)),oklch(var(--accent)));
}
.bg-\[radial-gradient\(ellipse_at_center\2c oklch\(var\(--destructive\)\/0\.12\)\2c transparent_65\%\)\] {
  background-image: radial-gradient(ellipse at center,oklch(var(--destructive)/0.12),transparent 65%);
}
.bg-\[radial-gradient\(ellipse_at_center\2c oklch\(var\(--primary\)\/0\.12\)\2c transparent_65\%\)\] {
  background-image: radial-gradient(ellipse at center,oklch(var(--primary)/0.12),transparent 65%);
}
.bg-\[radial-gradient\(ellipse_at_center\2c oklch\(var\(--primary\)\/0\.14\)\2c transparent_65\%\)\] {
  background-image: radial-gradient(ellipse at center,oklch(var(--primary)/0.14),transparent 65%);
}
.fill-current {
  fill: currentColor;
}
.fill-destructive {
  fill: oklch(var(--destructive) / 1);
}
.fill-primary {
  fill: oklch(var(--primary) / 1);
}
.fill-transparent {
  fill: transparent;
}
.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-2 {
  padding: 0.5rem;
}
.p-3 {
  padding: 0.75rem;
}
.p-4 {
  padding: 1rem;
}
.p-6 {
  padding: 1.5rem;
}
.p-8 {
  padding: 2rem;
}
.p-\[3px\] {
  padding: 3px;
}
.p-px {
  padding: 1px;
}
.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-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-8 {
  padding-left: 2rem;
  padding-right: 2rem;
}
.py-0 {
  padding-top: 0px;
  padding-bottom: 0px;
}
.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-2 {
  padding-top: 0.5rem;
  padding-bottom: 0.5rem;
}
.py-3 {
  padding-top: 0.75rem;
  padding-bottom: 0.75rem;
}
.py-4 {
  padding-top: 1rem;
  padding-bottom: 1rem;
}
.py-6 {
  padding-top: 1.5rem;
  padding-bottom: 1.5rem;
}
.py-8 {
  padding-top: 2rem;
  padding-bottom: 2rem;
}
.pb-2 {
  padding-bottom: 0.5rem;
}
.pb-28 {
  padding-bottom: 7rem;
}
.pb-3 {
  padding-bottom: 0.75rem;
}
.pb-4 {
  padding-bottom: 1rem;
}
.pb-5 {
  padding-bottom: 1.25rem;
}
.pb-6 {
  padding-bottom: 1.5rem;
}
.pb-\[max\(0\.75rem\2c env\(safe-area-inset-bottom\)\)\] {
  padding-bottom: max(0.75rem, env(safe-area-inset-bottom));
}
.pl-10 {
  padding-left: 2.5rem;
}
.pl-2 {
  padding-left: 0.5rem;
}
.pl-4 {
  padding-left: 1rem;
}
.pl-8 {
  padding-left: 2rem;
}
.pr-1 {
  padding-right: 0.25rem;
}
.pr-12 {
  padding-right: 3rem;
}
.pr-2 {
  padding-right: 0.5rem;
}
.pr-2\.5 {
  padding-right: 0.625rem;
}
.pr-8 {
  padding-right: 2rem;
}
.pt-0 {
  padding-top: 0px;
}
.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-8 {
  padding-top: 2rem;
}
.text-left {
  text-align: left;
}
.text-center {
  text-align: center;
}
.text-right {
  text-align: right;
}
.align-middle {
  vertical-align: middle;
}
.font-body {
  font-family: var(--font-body), sans-serif;
}
.font-display {
  font-family: var(--font-display), serif;
}
.font-mono {
  font-family: var(--font-mono), monospace;
}
.text-2xl {
  font-size: 1.5rem;
  line-height: 2rem;
}
.text-3xl {
  font-size: 1.875rem;
  line-height: 2.25rem;
}
.text-\[0\.8rem\] {
  font-size: 0.8rem;
}
.text-\[10px\] {
  font-size: 10px;
}
.text-\[11px\] {
  font-size: 11px;
}
.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-bold {
  font-weight: 700;
}
.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;
}
.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\(--conditioning-low-fg\)\)\] {
  color: oklch(var(--conditioning-low-fg));
}
.text-accent {
  --tw-text-opacity: 1;
  color: oklch(var(--accent) / var(--tw-text-opacity, 1));
}
.text-accent-foreground {
  color: oklch(var(--accent-foreground));
}
.text-card-foreground {
  color: oklch(var(--card-foreground));
}
.text-current {
  color: currentColor;
}
.text-destructive {
  --tw-text-opacity: 1;
  color: oklch(var(--destructive) / var(--tw-text-opacity, 1));
}
.text-destructive-foreground {
  color: oklch(var(--destructive-foreground));
}
.text-foreground {
  color: oklch(var(--foreground));
}
.text-muted-foreground {
  --tw-text-opacity: 1;
  color: oklch(var(--muted-foreground) / var(--tw-text-opacity, 1));
}
.text-muted-foreground\/40 {
  color: oklch(var(--muted-foreground) / 0.4);
}
.text-muted-foreground\/70 {
  color: oklch(var(--muted-foreground) / 0.7);
}
.text-muted-foreground\/80 {
  color: oklch(var(--muted-foreground) / 0.8);
}
.text-popover-foreground {
  color: oklch(var(--popover-foreground));
}
.text-primary {
  --tw-text-opacity: 1;
  color: oklch(var(--primary) / var(--tw-text-opacity, 1));
}
.text-primary-foreground {
  color: oklch(var(--primary-foreground));
}
.text-secondary-foreground {
  color: oklch(var(--secondary-foreground));
}
.underline {
  text-decoration-line: underline;
}
.underline-offset-2 {
  text-underline-offset: 2px;
}
.underline-offset-4 {
  text-underline-offset: 4px;
}
.antialiased {
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
.opacity-0 {
  opacity: 0;
}
.opacity-100 {
  opacity: 1;
}
.opacity-50 {
  opacity: 0.5;
}
.opacity-70 {
  opacity: 0.7;
}
.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-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-xl {
  --tw-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
  --tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px 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-xs {
  --tw-shadow: 0 1px 2px 0 rgba(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);
}
.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-border {
  --tw-ring-color: oklch(var(--border));
}
.ring-destructive\/30 {
  --tw-ring-color: oklch(var(--destructive) / 0.3);
}
.ring-primary {
  --tw-ring-opacity: 1;
  --tw-ring-color: oklch(var(--primary) / var(--tw-ring-opacity, 1));
}
.ring-primary\/30 {
  --tw-ring-color: oklch(var(--primary) / 0.3);
}
.ring-primary\/50 {
  --tw-ring-color: oklch(var(--primary) / 0.5);
}
.ring-ring\/50 {
  --tw-ring-color: oklch(var(--ring) / 0.5);
}
.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);
}
.\!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) !important;
}
.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-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);
}
.backdrop-filter {
  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-none {
  transition-property: none;
}
.transition-opacity {
  transition-property: opacity;
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
  transition-duration: 150ms;
}
.transition-shadow {
  transition-property: box-shadow;
  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-1000 {
  transition-duration: 1000ms;
}
.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);
}
.\@container\/card-header {
  container-type: inline-size;
  container-name: card-header;
}
@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;
}
.zoom-in-95 {
  --tw-enter-scale: .95;
}
.duration-1000 {
  animation-duration: 1000ms;
}
.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);
}
.running {
  animation-play-state: running;
}
.transition-smooth {
    transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  }
/* Skip-to-content link — visually hidden by default (sr-only-style),
     becomes visible and positioned at top-left on :focus. High-contrast
     background/text, 44px min height, z-index above the header. */
.skip-link {
    position: absolute;
    top: 0.5rem;
    left: 0.5rem;
    z-index: 100;
    min-height: 2.75rem; /* 44px touch target */
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0.5rem 1rem;
    border-radius: var(--radius);
    background-color: oklch(var(--primary));
    color: oklch(var(--primary-foreground));
    font-family: var(--font-body);
    font-size: 0.875rem;
    font-weight: 600;
    text-decoration: none;
    /* Visually hidden until focused. */
    transform: translateY(-150%);
    opacity: 0;
    pointer-events: none;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
  }
.skip-link:focus {
    transform: translateY(0);
    opacity: 1;
    pointer-events: auto;
    clip: auto;
    clip-path: none;
    outline: 2px solid oklch(var(--ring));
    outline-offset: 2px;
  }
/* Rarity badge utilities — semantic OKLCH tokens, bolder text, distinct
     backgrounds and borders per tier. Use via RARITY_BADGE_CLASSES in
     types/index.ts so DogCard and DogDetailModal share one source of truth. */
.badge-rarity-common {
    background-color: oklch(var(--rarity-common-bg));
    color: oklch(var(--rarity-common-fg));
    border-color: oklch(var(--rarity-common-border));
  }
.badge-rarity-uncommon {
    background-color: oklch(var(--rarity-uncommon-bg));
    color: oklch(var(--rarity-uncommon-fg));
    border-color: oklch(var(--rarity-uncommon-border));
  }
.badge-rarity-rare {
    background-color: oklch(var(--rarity-rare-bg));
    color: oklch(var(--rarity-rare-fg));
    border-color: oklch(var(--rarity-rare-border));
  }
.badge-rarity-epic {
    background-color: oklch(var(--rarity-epic-bg));
    color: oklch(var(--rarity-epic-fg));
    border-color: oklch(var(--rarity-epic-border));
  }
.badge-rarity-legendary {
    background-color: oklch(var(--rarity-legendary-bg));
    color: oklch(var(--rarity-legendary-fg));
    border-color: oklch(var(--rarity-legendary-border));
  }
/* Fade-in entrance for staggered cards/elements. Pair with the
     .stagger-* helpers below or inline `animation-delay`. */
.animate-fade-in {
    animation: fade-in 0.4s cubic-bezier(0.4, 0, 0.2, 1) both;
  }
/* Slide-up entrance for modals, drawers, and bottom sheets. */
.animate-slide-up {
    animation: slide-up 0.35s cubic-bezier(0.16, 1, 0.3, 1) both;
  }
/* Expanding ring used on FABs and pulse affordances. Apply to an
     element with a primary-colored background or border. */
.animate-pulse-ring {
    animation: pulse-ring 1.8s cubic-bezier(0.4, 0, 0.2, 1) infinite;
  }
/* Breakthrough / show-win celebration — golden glow + scale pulse.
     Runs once over 1.2s. Pair with a golden-tinted headline. */
.animate-win-celebration {
    animation: win-celebration 1.2s cubic-bezier(0.4, 0, 0.2, 1) both;
  }
/* Level-up indicator flash — quick border/bg pulse, two cycles. */
.animate-level-up-flash {
    animation: level-up-flash 0.9s cubic-bezier(0.4, 0, 0.2, 1) 2;
  }
/* +X stat-gain popup entrance — pops up in sync with the bar fill. */
.animate-bar-fill {
    animation: bar-fill 0.5s cubic-bezier(0.16, 1, 0.3, 1) both;
  }
/* Skeleton pulse — subtle opacity + scale. Use on skeleton surfaces
     to keep motion consistent with ui/skeleton.tsx's `animate-pulse`. */
.animate-skeleton-pulse {
    animation: skeleton-pulse 1.6s ease-in-out infinite;
  }
/* Pass 5 — premium shimmer sweep. Apply to skeleton surfaces that
     should read as "loading with life" rather than a flat pulse.
     Sets a 200%-wide diagonal gradient (muted → warm peak → muted →
     dark edge) and sweeps it across the surface in 1.6s. The peak
     stop carries a faint amber hue so the shimmer feels warm on the
     OLED background without introducing a new color. Pair with
     rounded corners and the same border-radius as the real content. */
.animate-skeleton-shimmer {
    background-image: linear-gradient(
      100deg,
      oklch(var(--skeleton-base)) 30%,
      oklch(var(--skeleton-peak)) 50%,
      oklch(var(--skeleton-base)) 70%
    );
    background-size: 200% 100%;
    background-repeat: no-repeat;
    animation: skeleton-shimmer 1.6s ease-in-out infinite;
  }
/* ───────────────────────────────────────────────────────────────
     Pass 5 — EmptyState variants. Each variant composes the same
     layout (illustration → headline → message → primary action) but
     shifts the accent surface and action button treatment. All colors
     are OKLCH tokens; no new palette introduced.
     ─────────────────────────────────────────────────────────────── */
/* Base shared by every empty state. Stacked, centered, 44px-friendly
     action area. Illustration zone is 64px tall, headline uses the
     display font, message uses muted-foreground. */
.empty-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.75rem;
    padding: 2rem 1.5rem;
    text-align: center;
  }
.empty-state-illustration {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 4rem;
    height: 4rem;
    margin-bottom: 0.25rem;
    color: oklch(var(--muted-foreground));
  }
.empty-state-title {
    font-family: var(--font-display);
    font-size: 1.25rem;
    font-weight: 600;
    letter-spacing: -0.01em;
    color: oklch(var(--foreground));
  }
.empty-state-message {
    font-family: var(--font-body);
    font-size: 0.875rem;
    line-height: 1.5;
    color: oklch(var(--muted-foreground));
    max-width: 32ch;
  }
.empty-state-action {
    margin-top: 0.5rem;
    min-height: 2.75rem; /* 44px touch target */
    width: 100%;
    max-width: 20rem;
  }
/* DEFAULT — neutral illustration, primary amber action button.
     Used for "no dogs yet" / first-run states. */
.empty-state-default .empty-state-illustration {
    color: oklch(var(--muted-foreground));
  }
.empty-state-default .empty-state-action {
    background-color: oklch(var(--primary));
    color: oklch(var(--primary-foreground));
    border-radius: var(--radius);
  }
/* PRIMARY — amber-tinted illustration, gradient-primary action.
     Used for the unauthenticated welcome / sign-in state. */
.empty-state-primary .empty-state-illustration {
    color: oklch(var(--primary));
  }
.empty-state-primary .empty-state-action {
    border-radius: var(--radius);
  }
/* ACCENT — coral-tinted illustration, accent-bordered action.
     Used for "no results" with active filters; secondary action. */
.empty-state-accent .empty-state-illustration {
    color: oklch(var(--accent));
  }
.empty-state-accent .empty-state-action {
    background-color: transparent;
    color: oklch(var(--accent));
    border: 1px solid oklch(var(--accent));
    border-radius: var(--radius);
  }
/* DESTRUCTIVE — destructive-tinted illustration, destructive action.
     Used for hard-empty / error-adjacent states. */
.empty-state-destructive .empty-state-illustration {
    color: oklch(var(--destructive));
  }
.empty-state-destructive .empty-state-action {
    background-color: oklch(var(--destructive));
    color: oklch(var(--destructive-foreground));
    border-radius: var(--radius);
  }
/* ───────────────────────────────────────────────────────────────
     Pass 5 — Offline fallback page. A deliberate, branded "you are
     offline" surface using the offline-* tokens. Not an error screen;
     a calm vault state with amber primary intact for the retry CTA.
     ─────────────────────────────────────────────────────────────── */
.offline-page {
    min-height: 100vh;
    min-height: 100dvh;
    background-color: oklch(var(--offline-background));
    color: oklch(var(--offline-foreground));
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 1rem;
    padding: 1.5rem;
    padding-top: max(1.5rem, env(safe-area-inset-top));
    padding-bottom: max(1.5rem, env(safe-area-inset-bottom));
    text-align: center;
  }
.offline-card {
    background-color: oklch(var(--offline-surface));
    border: 1px solid oklch(var(--offline-border));
    border-radius: var(--radius);
    padding: 2rem 1.5rem;
    max-width: 28rem;
    width: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.75rem;
  }
.offline-illustration {
    width: 4rem;
    height: 4rem;
    color: oklch(var(--primary));
  }
.offline-title {
    font-family: var(--font-display);
    font-size: 1.25rem;
    font-weight: 600;
    letter-spacing: -0.01em;
    color: oklch(var(--offline-foreground));
  }
.offline-message {
    font-family: var(--font-body);
    font-size: 0.875rem;
    line-height: 1.5;
    color: oklch(var(--offline-muted-foreground));
    max-width: 36ch;
  }
.offline-action {
    margin-top: 0.5rem;
    min-height: 2.75rem; /* 44px touch target */
    width: 100%;
    max-width: 20rem;
    background-color: oklch(var(--primary));
    color: oklch(var(--primary-foreground));
    border-radius: var(--radius);
  }
/* ───────────────────────────────────────────────────────────────
     LQIP blur-up — low-quality image placeholder. When a
     `placeholderSrc` is provided to LazyImage, the placeholder is
     rendered first with a heavy blur + slight overscale (so the
     blur edges don't show the container edges) and reduced opacity.
     Once the full image loads, the placeholder crossfades out (and
     the full image fades in via .animate-fade-in). The
     `.blur-up-loaded` modifier is applied to the placeholder once
     the full image is ready, which transitions opacity to 0 and
     removes the blur so the placeholder cleanly disappears.
     Honors prefers-reduced-motion via the override at the bottom
     of this file (no blur filter, no transition — static opacity
     swap only).
     ─────────────────────────────────────────────────────────────── */
.blur-up-placeholder {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    -o-object-fit: cover;
       object-fit: cover;
    /* Heavy blur + slight overscale so the blurred edges extend past
       the container and the blur doesn't reveal the box edges. */
    filter: blur(20px) saturate(1.1);
    transform: scale(1.1);
    opacity: 0.85;
    /* Crossfade the placeholder out when the full image is ready. */
    transition: opacity 0.4s ease, filter 0.4s ease;
    /* Avoid layout shift + keep the placeholder above the shimmer
       skeleton but below the final image. Caller controls z-index
       via stacking order in the DOM. */
    z-index: 1;
    pointer-events: none;
    -webkit-user-select: none;
       -moz-user-select: none;
            user-select: none;
  }
/* Applied to the placeholder once the full image has loaded:
     fade out and remove the blur so the placeholder cleanly
     disappears behind the sharp image. */
.blur-up-loaded {
    opacity: 0;
    filter: blur(0) saturate(1);
  }
/* Stagger helpers — apply alongside .animate-fade-in to delay
      successive children by 80ms each (max ~0.4s). */
.stagger-1 {
    animation-delay: 0.08s;
  }
.stagger-2 {
    animation-delay: 0.16s;
  }
.stagger-3 {
    animation-delay: 0.24s;
  }
.stagger-4 {
    animation-delay: 0.32s;
  }
.stagger-5 {
    animation-delay: 0.40s;
  }
.stagger-6 {
    animation-delay: 0.48s;
  }
/* ───────────────────────────────────────────────────────────────
     Bloodlines showcase — responsive card grid, bloodline card
     surface, image scrim, and signature-look trait chips. Extends
     the existing dark OLED system; no new palette. All colors are
     OKLCH tokens. Honors prefers-reduced-motion (see bottom of file).
     ─────────────────────────────────────────────────────────────── */
/* Responsive grid: 1 col mobile → 2 col tablet → 3 col small
     desktop → 4 col large desktop. Uses auto-fit minmax so the
     grid degrades gracefully between breakpoints. Gaps match the
     existing card rhythm (12px mobile, 16px desktop). */
.bloodline-grid {
    display: grid;
    gap: 0.75rem;
    grid-template-columns: minmax(0, 1fr);
  }
@media (min-width: 640px) {
    .bloodline-grid {
      gap: 1rem;
      grid-template-columns: repeat(2, minmax(0, 1fr));
    }
  }
@media (min-width: 1024px) {
    .bloodline-grid {
      grid-template-columns: repeat(3, minmax(0, 1fr));
    }
  }
@media (min-width: 1280px) {
    .bloodline-grid {
      grid-template-columns: repeat(4, minmax(0, 1fr));
    }
  }
/* Bloodline card surface — elevated dark card with a hairline
     border, rounded-xl, overflow-hidden for the image. Hover lifts
     to shadow-elevated with a subtle translate; reduced-motion
     drops the transform. The whole card is the tap target so it
     must meet 44px min height (the image alone exceeds this). */
.bloodline-card {
    position: relative;
    display: flex;
    flex-direction: column;
    background-color: oklch(var(--card));
    border: 1px solid oklch(var(--border));
    border-radius: calc(var(--radius) + 0.25rem); /* rounded-xl */
    overflow: hidden;
    box-shadow: 0 2px 8px oklch(0 0 0 / 0.12);
    transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s
      ease;
    cursor: pointer;
  }
.bloodline-card:hover {
    transform: translateY(-2px);
    box-shadow: 0 8px 32px oklch(0 0 0 / 0.24);
    border-color: oklch(var(--primary) / 0.4);
  }
.bloodline-card:focus-visible {
    outline: 2px solid oklch(var(--ring));
    outline-offset: 2px;
  }
/* Image scrim — a warm-amber-tinted dark gradient rising from
     the bottom of the representative image so the bloodline name
     stays legible over any dog photo. Sits above the LazyImage,
     below the name text. Caller wraps LazyImage in a relative
     aspect-square container and layers this as an absolute inset-0
     element. */
.bloodline-image-scrim {
    position: absolute;
    inset: 0;
    background: linear-gradient(
      to top,
      oklch(var(--bloodline-scrim-bottom)) 0%,
      oklch(var(--bloodline-scrim-top)) 55%
    );
    pointer-events: none;
  }
/* Bloodline name overlay — display font, bold, sits over the
     scrim at the bottom-left of the image. Warm white with a faint
     text-shadow for extra legibility on busy photos. */
.bloodline-name {
    position: absolute;
    left: 0.75rem;
    bottom: 0.75rem;
    right: 0.75rem;
    font-family: var(--font-display);
    font-size: 1.25rem;
    font-weight: 700;
    letter-spacing: -0.01em;
    line-height: 1.15;
    color: oklch(var(--foreground));
    text-shadow: 0 1px 8px oklch(0 0 0 / 0.6);
  }
/* Bio text — Satoshi body, muted-foreground, clamped to 2 lines
     so cards in the same row stay height-aligned. */
.bloodline-bio {
    padding: 0.75rem 0.75rem 0;
    font-family: var(--font-body);
    font-size: 0.8125rem;
    line-height: 1.5;
    color: oklch(var(--muted-foreground));
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }
/* Trait chip list — flex-wrap row of signature-look pills with
     a 44px-friendly tap region (chips are non-interactive here,
     but the row padding keeps the card's lower edge comfortable). */
.bloodline-traits {
    display: flex;
    flex-wrap: wrap;
    gap: 0.375rem;
    padding: 0.625rem 0.75rem 0.75rem;
  }
/* Signature-look trait chip — warm-tinted muted pill with a
      hairline border and an amber leading dot. Distinct from rarity
      badges (gaming tiers) and generic muted pills: slightly warmer
      hue (70) so the trait list reads as curated content. */
.trait-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.3125rem;
    padding: 0.25rem 0.5625rem;
    border-radius: 9999px;
    background-color: oklch(var(--trait-chip-bg));
    border: 1px solid oklch(var(--trait-chip-border));
    color: oklch(var(--trait-chip-fg));
    font-family: var(--font-body);
    font-size: 0.6875rem;
    font-weight: 600;
    line-height: 1.4;
    letter-spacing: 0.01em;
  }
.trait-chip::before {
    content: "";
    flex: 0 0 auto;
    width: 0.3125rem;
    height: 0.3125rem;
    border-radius: 9999px;
    background-color: oklch(var(--trait-chip-dot));
  }
/* Per-bloodline dog count badge — small pill pinned to the
     top-right corner of a bloodline card's representative image.
     Reuses the --trait-chip tokens (warm amber hue 70) so it reads
     as part of the card's curated surface, not a foreign overlay.
     pointer-events-none so it never intercepts the 44px card tap
     target. Compact sizing keeps it readable on Micro build cards
     without breaking the card layout. The badge reserves its slot
     in all states (loading / error / ready) so the card layout is
     stable across count fetch transitions. */
.bloodline-count-badge {
    position: absolute;
    top: 0.5rem;
    right: 0.5rem;
    z-index: 2;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 1.5rem;
    padding: 0.1875rem 0.5rem;
    border-radius: 9999px;
    background-color: oklch(var(--card) / 0.82);
    border: 1px solid oklch(var(--trait-chip-border));
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    pointer-events: none;
    /* Fade-in only on the ready transition; honors
       prefers-reduced-motion via the rule at the bottom of the
       file (animation: none under reduced-motion). */
    animation: fade-in 0.3s ease both;
  }
.bloodline-count-badge[data-state="loading"] {
    animation: none;
    opacity: 0.92;
  }
.bloodline-count-badge[data-state="error"] {
    animation: none;
    opacity: 0.8;
  }
.bloodline-count-badge-text {
    font-family: var(--font-body);
    font-size: 0.6875rem;
    font-weight: 600;
    line-height: 1.2;
    letter-spacing: 0.01em;
    color: oklch(var(--trait-chip-fg));
    white-space: nowrap;
  }
/* Loading shimmer pill — a compact version of the
     .animate-skeleton-shimmer surface sized to the badge. Reuses
     the --skeleton-* tokens so it matches the LazyImage placeholder
     aesthetic on the same card. Reduced-motion falls back to a
     static muted fill via the global .animate-skeleton-shimmer
     override. */
.bloodline-count-badge-shimmer {
    display: inline-block;
    width: 2.75rem;
    height: 0.625rem;
    border-radius: 9999px;
    background-image: linear-gradient(
      100deg,
      oklch(var(--skeleton-base)) 30%,
      oklch(var(--skeleton-peak)) 50%,
      oklch(var(--skeleton-base)) 70%
    );
    background-size: 200% 100%;
    background-repeat: no-repeat;
    animation: skeleton-shimmer 1.6s ease-in-out infinite;
  }
/* Bloodlines nav tab — reuses the existing header tab treatment
     but adds an amber underline indicator for the active state.
     Min-height 44px for touch, focus-visible ring via global rule. */
.bloodline-tab {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 2.75rem; /* 44px touch target */
    padding: 0.5rem 0.75rem;
    font-family: var(--font-body);
    font-size: 0.875rem;
    font-weight: 600;
    color: oklch(var(--muted-foreground));
    background: transparent;
    border: none;
    border-radius: var(--radius);
    transition: color 0.2s ease, background-color 0.2s ease;
    cursor: pointer;
  }
.bloodline-tab:hover {
    color: oklch(var(--foreground));
    background-color: oklch(var(--muted) / 0.5);
  }
.bloodline-tab[data-active="true"] {
    color: oklch(var(--primary));
  }
.bloodline-tab[data-active="true"]::after {
    content: "";
    position: absolute;
    left: 0.75rem;
    right: 0.75rem;
    bottom: 0.125rem;
    height: 2px;
    border-radius: 9999px;
    background-color: oklch(var(--primary));
  }
/* Header nav-scroll — horizontally scrollable tab row so all tabs
     (Dashboard, Marketplace, My Dogs, Gallery, Bloodlines, Admin) stay
     reachable by swiping/scrolling on narrow mobile viewports. Tabs
     never wrap (flex-nowrap via the caller's flex + shrink-0 tabs) and
     never clip off-screen. Hidden scrollbars keep the row visually
     clean; momentum scrolling + overscroll containment stop the swipe
     from chaining to the page. This is a scroll behavior, not an
     animation, so it stays fully functional under
     prefers-reduced-motion (only the tab color/bg transitions are
     dropped there, which are already handled by .bloodline-tab). */
.nav-scroll {
    overflow-x: auto;
    overflow-y: hidden;
    flex-wrap: nowrap;
    scrollbar-width: none; /* Firefox */
    -ms-overflow-style: none; /* IE/Edge legacy */
    overscroll-behavior-x: contain;
    -webkit-overflow-scrolling: touch; /* iOS momentum */
  }
.nav-scroll::-webkit-scrollbar {
    display: none; /* Chrome/Safari/Edge */
    height: 0;
    width: 0;
  }
/* ─────────────────────────────────────────────────────────────
     Bloodline recent-dogs carousel — REPLACES the single
     representative image as the card's main image area. A small,
     clean horizontal snap-scroll of 3–4 aspect-square LazyImage
     thumbnails. No autoplay, no pagination dots, no swipe hint.
     Native scroll-snap (not JS-animated slides) so the surface
     stays functional under prefers-reduced-motion — snap is a
     scroll behavior, not an animation, so it is intentionally
     NOT disabled in the reduced-motion block at the bottom of
     this file. Only the chevron hover/focus transitions are
     dropped there.
     ───────────────────────────────────────────────────────────── */
/* Track — the carousel viewport. aspect-square matches the
     previous single-image container so the card's image area
     height is unchanged (no layout shift). Horizontal scroll,
     mandatory snap, hidden scrollbars for a clean minimal look.
     The track is the scroll container; slides snap inside it.
     `overscroll-behavior-x: contain` stops the swipe from
     chaining to the page horizontally. */
.bloodline-carousel {
    position: relative;
    width: 100%;
    aspect-ratio: 1 / 1;
    display: flex;
    overflow-x: auto;
    overflow-y: hidden;
    scroll-snap-type: x mandatory;
    scrollbar-width: none; /* Firefox */
    -ms-overflow-style: none; /* IE/Edge legacy */
    overscroll-behavior-x: contain;
    -webkit-overflow-scrolling: touch; /* iOS momentum */
  }
.bloodline-carousel::-webkit-scrollbar {
    display: none; /* Chrome/Safari/Edge */
    height: 0;
    width: 0;
  }
/* Each slide — full-width of the track, aspect-square, snap-
     aligned to the start. shrink-0 so slides never compress;
     flex-basis 100% so exactly one slide fills the viewport at
     a time. The LazyImage inside fills the slide via the caller's
     `absolute inset-0 h-full w-full` className so shimmer +
     fade-in + error fallback all behave identically to the
     existing dog image surfaces. */
.bloodline-carousel-slide {
    position: relative;
    flex: 0 0 100%;
    width: 100%;
    aspect-ratio: 1 / 1;
    scroll-snap-align: start;
    scroll-snap-stop: always;
  }
/* Previous/next chevron controls — 44px square hit targets
     pinned to the left/right edges, vertically centered. They
     sit ABOVE the scrim and name overlay (z-index 3) so they
     stay reachable, but use pointer-events only on the button
     itself (the wrapper is pointer-events-none so it never
     blocks the card's tap target). Semi-transparent --card fill
     with backdrop blur matches the count-badge treatment; amber
     icon ties to the primary accent. Hidden by the caller when
     fewer than 2 thumbnails are present (data-hidden="true" or
     the caller simply does not render them). */
.bloodline-carousel-controls {
    position: absolute;
    inset: 0;
    z-index: 3;
    pointer-events: none;
  }
.bloodline-carousel-btn {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.75rem; /* 44px touch target */
    height: 2.75rem;
    border-radius: 9999px;
    background-color: oklch(var(--bloodline-carousel-control-bg));
    border: 1px solid oklch(var(--bloodline-carousel-control-border));
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    color: oklch(var(--bloodline-carousel-control-fg));
    pointer-events: auto;
    cursor: pointer;
    transition: opacity 0.15s ease, transform 0.15s ease, box-shadow 0.15s ease;
  }
.bloodline-carousel-btn:hover {
    box-shadow: 0 0 0 4px oklch(var(--primary) / 0.18);
  }
.bloodline-carousel-btn:focus-visible {
    outline: 2px solid oklch(var(--ring));
    outline-offset: 2px;
  }
.bloodline-carousel-btn[data-side="prev"] {
    left: 0.5rem;
  }
.bloodline-carousel-btn[data-side="next"] {
    right: 0.5rem;
  }
/* Caller sets data-hidden="true" when fewer than 2 thumbnails —
     removes the control from the tab order and the visual flow. */
.bloodline-carousel-btn[data-hidden="true"] {
    display: none;
  }
/* When the carousel is present, the scrim + name + count badge
     must layer above the slides but below the chevron controls.
     The caller keeps the existing .bloodline-image-scrim and
     .bloodline-name elements as siblings of the carousel inside
     the same relative wrapper; bumping their z-index here keeps
     them legible over the active slide without re-styling them. */
.bloodline-card:has(.bloodline-carousel) .bloodline-image-scrim {
    z-index: 1;
  }
.bloodline-card:has(.bloodline-carousel) .bloodline-name {
    z-index: 2;
  }
.bloodline-card:has(.bloodline-carousel) .bloodline-count-badge {
    z-index: 2;
  }
/* ───────────────────────────────────────────────────────────────
     Pass 6 — Dashboard, Marketplace & My Dogs utilities. Extends the
     existing dark OLED system; no new palette. All colors are OKLCH
     tokens. Honors prefers-reduced-motion (see bottom of file).
     ─────────────────────────────────────────────────────────────── */
/* Currency — mono numerals for ICP amounts, amber primary so the
     value reads as the active figure; label is muted small caps. */
.currency-value {
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    color: oklch(var(--primary));
    font-weight: 600;
    letter-spacing: -0.01em;
  }
.currency-label {
    font-family: var(--font-body);
    font-size: 0.75rem;
    color: oklch(var(--muted-foreground));
    text-transform: uppercase;
    letter-spacing: 0.06em;
  }
/* Stat grid — 2x2 on mobile, scales to 4-col on sm+ via caller.
     Card surface reuses --card with a hairline border. */
.stat-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.75rem;
  }
@media (min-width: 640px) {
    .stat-grid {
      gap: 1rem;
    }
  }
.stat-card {
    background-color: oklch(var(--card));
    border: 1px solid oklch(var(--border));
    border-radius: var(--radius);
    padding: 0.875rem 1rem;
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
  }
.stat-card__label {
    font-family: var(--font-body);
    font-size: 0.6875rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: oklch(var(--muted-foreground));
  }
.stat-card__value {
    font-family: var(--font-display);
    font-size: 1.5rem;
    font-weight: 700;
    letter-spacing: -0.02em;
    color: oklch(var(--foreground));
    line-height: 1.1;
  }
/* Quick actions — flex-wrap row of 44px touch-target buttons.
     Full-width on mobile, auto-width on sm+. */
.quick-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.625rem;
  }
.quick-action-btn {
    min-height: 2.75rem; /* 44px touch target */
    padding: 0.5rem 1rem;
    border-radius: var(--radius);
    background-color: oklch(var(--primary));
    color: oklch(var(--primary-foreground));
    font-family: var(--font-body);
    font-size: 0.875rem;
    font-weight: 600;
    border: none;
    cursor: pointer;
    width: 100%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    transition: background-color 0.2s ease, transform 0.15s ease;
  }
.quick-action-btn:hover {
    background-color: oklch(var(--primary) / 0.88);
  }
.quick-action-btn:active {
    transform: scale(0.98);
  }
@media (min-width: 640px) {
    .quick-action-btn {
      width: auto;
    }
  }
.quick-action-btn--disabled {
    background-color: oklch(var(--muted));
    color: oklch(var(--muted-foreground));
    opacity: 0.6;
    cursor: not-allowed;
    pointer-events: none;
  }
/* Conditioning bar — track + gradient fill (amber-to-coral).
     Low variant (<40%) tints toward the destructive hue so the
     meter reads as "needs work" without a separate error state. */
.conditioning-bar {
    width: 100%;
    height: 0.5rem;
    border-radius: 9999px;
    background-color: oklch(var(--muted));
    border: 1px solid oklch(var(--border));
    overflow: hidden;
  }
.conditioning-bar__fill {
    height: 100%;
    border-radius: 9999px;
    background: linear-gradient(
      90deg,
      oklch(var(--primary)),
      oklch(var(--accent))
    );
    transition: width 0.4s cubic-bezier(0.4, 0, 0.2, 1);
  }
.conditioning-bar--low {
    background-color: oklch(var(--conditioning-low-bg));
    border-color: oklch(var(--conditioning-low-border));
  }
.conditioning-bar--low .conditioning-bar__fill {
    background: linear-gradient(
      90deg,
      oklch(var(--conditioning-low-fg)),
      oklch(var(--accent))
    );
  }
/* Listing badge — small mono pill. Listed = amber (active),
     Sold = desaturated near-neutral (clearly inactive). */
.listing-badge {
    display: inline-flex;
    align-items: center;
    padding: 0.1875rem 0.5rem;
    border-radius: 9999px;
    font-family: var(--font-mono);
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    border: 1px solid oklch(var(--border));
  }
.listing-badge--listed {
    background-color: oklch(var(--primary) / 0.16);
    color: oklch(var(--primary));
    border-color: oklch(var(--primary) / 0.4);
  }
.listing-badge--sold {
    background-color: oklch(var(--listing-sold-bg));
    color: oklch(var(--listing-sold-fg));
    border-color: oklch(var(--listing-sold-border));
  }
/* Activity feed — vertical list of timestamped events. */
.activity-feed {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
  }
.activity-item {
    display: flex;
    align-items: flex-start;
    gap: 0.625rem;
    padding: 0.625rem 0;
    border-bottom: 1px solid oklch(var(--border));
  }
.activity-item:last-child {
    border-bottom: none;
  }
.activity-item__icon {
    flex: 0 0 auto;
    width: 1.5rem;
    height: 1.5rem;
    border-radius: 9999px;
    background-color: oklch(var(--card));
    border: 1px solid oklch(var(--border));
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: oklch(var(--primary));
  }
.activity-item__text {
    flex: 1 1 auto;
    font-family: var(--font-body);
    font-size: 0.8125rem;
    line-height: 1.5;
    color: oklch(var(--foreground));
  }
.activity-item__time {
    flex: 0 0 auto;
    font-family: var(--font-mono);
    font-size: 0.6875rem;
    color: oklch(var(--muted-foreground));
    white-space: nowrap;
  }
/* Milestone bar — track + amber gradient fill, mono progress. */
.milestone-bar {
    width: 100%;
    height: 0.5rem;
    border-radius: 9999px;
    background-color: oklch(var(--muted));
    border: 1px solid oklch(var(--border));
    overflow: hidden;
  }
.milestone-bar__fill {
    height: 100%;
    border-radius: 9999px;
    background: linear-gradient(
      90deg,
      oklch(var(--milestone-fill-from)),
      oklch(var(--milestone-fill-to))
    );
    transition: width 0.4s cubic-bezier(0.4, 0, 0.2, 1);
  }
.milestone-label {
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-family: var(--font-body);
    font-size: 0.8125rem;
    color: oklch(var(--muted-foreground));
  }
.milestone-progress {
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    font-size: 0.8125rem;
    font-weight: 600;
    color: oklch(var(--primary));
  }
/* Buy summary — confirmation card with line items. Total row
     gets a top border + bold. Fee row carries the "burned" label
     in the burn-fee token so the 2% platform fee reads as a real
     cost. */
.buy-summary {
    background-color: oklch(var(--card));
    border: 1px solid oklch(var(--border));
    border-radius: var(--radius);
    padding: 0.5rem 1rem;
  }
.buy-summary__row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 0.625rem 0;
    font-family: var(--font-body);
    font-size: 0.875rem;
    color: oklch(var(--foreground));
  }
.buy-summary__row--total {
    font-weight: 700;
    border-top: 1px solid oklch(var(--border));
    margin-top: 0.25rem;
  }
.buy-summary__row--total .currency-value {
    font-size: 1.125rem;
  }
.buy-summary__fee {
    font-family: var(--font-body);
    font-size: 0.6875rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: oklch(var(--burn-fee-fg));
    border: 1px solid oklch(var(--burn-fee-border));
    border-radius: 9999px;
    padding: 0.125rem 0.4375rem;
    margin-left: 0.375rem;
  }
/* Listing card — marketplace browse surface. Rounded, border,
     hover lift to shadow-elevated. Image is aspect-square to
     prevent layout shift. Price is mono amber bold. */
.listing-card {
    position: relative;
    display: flex;
    flex-direction: column;
    background-color: oklch(var(--card));
    border: 1px solid oklch(var(--border));
    border-radius: calc(var(--radius) + 0.25rem);
    overflow: hidden;
    box-shadow: 0 2px 8px oklch(0 0 0 / 0.12);
    transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s
      ease;
    cursor: pointer;
  }
.listing-card:hover {
    transform: translateY(-2px);
    box-shadow: 0 8px 32px oklch(0 0 0 / 0.24);
    border-color: oklch(var(--primary) / 0.4);
  }
.listing-card:focus-visible {
    outline: 2px solid oklch(var(--ring));
    outline-offset: 2px;
  }
.listing-card__image {
    position: relative;
    aspect-ratio: 1 / 1;
    width: 100%;
    overflow: hidden;
  }
.listing-card__price {
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    font-size: 1rem;
    font-weight: 700;
    color: oklch(var(--primary));
    letter-spacing: -0.01em;
  }
.listing-card__seller {
    font-family: var(--font-body);
    font-size: 0.75rem;
    color: oklch(var(--muted-foreground));
  }
/* Kennel grid — responsive 2-col mobile, 3-4 col sm+. Card
     surface reuses --card with a hairline border. Badge is
     absolute top-right for listing status. */
.kennel-grid {
    display: grid;
    gap: 0.75rem;
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
@media (min-width: 640px) {
    .kennel-grid {
      gap: 1rem;
      grid-template-columns: repeat(3, minmax(0, 1fr));
    }
  }
@media (min-width: 1024px) {
    .kennel-grid {
      grid-template-columns: repeat(4, minmax(0, 1fr));
    }
  }
.kennel-card {
    position: relative;
    display: flex;
    flex-direction: column;
    background-color: oklch(var(--card));
    border: 1px solid oklch(var(--border));
    border-radius: calc(var(--radius) + 0.25rem);
    overflow: hidden;
    box-shadow: 0 2px 8px oklch(0 0 0 / 0.12);
    transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s
      ease;
    cursor: pointer;
  }
.kennel-card:hover {
    transform: translateY(-2px);
    box-shadow: 0 8px 32px oklch(0 0 0 / 0.24);
    border-color: oklch(var(--primary) / 0.4);
  }
.kennel-card:focus-visible {
    outline: 2px solid oklch(var(--ring));
    outline-offset: 2px;
  }
.kennel-card__badge {
    position: absolute;
    top: 0.5rem;
    right: 0.5rem;
    z-index: 2;
  }
/* ───────────────────────────────────────────────────────────────
     Pass 7 — Show System v1 gameplay utilities. Extends the
     existing dark OLED system; no new palette. All colors are
     OKLCH tokens. Honors prefers-reduced-motion (see bottom of
     file). 44px touch targets on every interactive element.
     ─────────────────────────────────────────────────────────────── */
/* Level badge — circular amber indicator showing the dog's
     current level (1–10). Display font, bold, sits next to the
     dog name. Uses the primary amber fill so the level reads as
     the active identity marker. */
.level-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.75rem;
    height: 2.75rem;
    border-radius: 9999px;
    background: linear-gradient(
      135deg,
      oklch(var(--level-badge-bg)),
      oklch(var(--accent))
    );
    color: oklch(var(--level-badge-fg));
    font-family: var(--font-display);
    font-size: 0.875rem;
    font-weight: 700;
    letter-spacing: -0.02em;
    flex: 0 0 auto;
    box-shadow: 0 2px 8px oklch(0 0 0 / 0.24);
  }
/* XP bar — level/XP progress. Amber-to-cyan-teal gradient fill
     so the XP meter ties to the primary amber but shifts cool as
     the bar fills, distinguishing it from the warm conditioning
     bar. Mono numeric label shows "current / next-level XP". */
.xp-bar {
    width: 100%;
    height: 0.5rem;
    border-radius: 9999px;
    background-color: oklch(var(--muted));
    border: 1px solid oklch(var(--border));
    overflow: hidden;
  }
.xp-bar__fill {
    height: 100%;
    border-radius: 9999px;
    background: linear-gradient(
      90deg,
      oklch(var(--xp-fill-from)),
      oklch(var(--xp-fill-to))
    );
    transition: width 0.5s cubic-bezier(0.4, 0, 0.2, 1);
  }
/* Conditioning bar — medium and high states extend the existing
     .conditioning-bar / --low pattern. Medium (40–69%) keeps the
     amber-to-coral gradient; high (≥70%) shifts toward the success
     green so a well-conditioned dog reads as "ready to show". */
.conditioning-bar--medium .conditioning-bar__fill {
    background: linear-gradient(
      90deg,
      oklch(var(--conditioning-medium-fg)),
      oklch(var(--accent))
    );
  }
.conditioning-bar--high .conditioning-bar__fill {
    background: linear-gradient(
      90deg,
      oklch(var(--conditioning-high-fg)),
      oklch(var(--success))
    );
  }
/* Energy bar — cool cyan-teal gradient (hue 220→200) so the
     energy gauge never reads as the same meter as the warm
     conditioning bar. Low state (<25%) tints the fill toward the
     destructive hue so an exhausted dog reads as "needs rest". */
.energy-bar {
    width: 100%;
    height: 0.5rem;
    border-radius: 9999px;
    background-color: oklch(var(--muted));
    border: 1px solid oklch(var(--border));
    overflow: hidden;
  }
.energy-bar__fill {
    height: 100%;
    border-radius: 9999px;
    background: linear-gradient(
      90deg,
      oklch(var(--energy-fill-from)),
      oklch(var(--energy-fill-to))
    );
    transition: width 0.5s cubic-bezier(0.4, 0, 0.2, 1);
  }
.energy-bar--low .energy-bar__fill {
    background: linear-gradient(
      90deg,
      oklch(var(--energy-low-fg)),
      oklch(var(--energy-fill-to))
    );
  }
/* Stat bar — six dog stats (Strength, Agility, Stamina,
     Intelligence, Temperance, Courage). Muted amber fill so six
     bars in a row don't overpower the screen; the strong variant
     is used for the dog's highest stat. Mono numeric value on the
     right. */
.stat-bar {
    width: 100%;
    height: 0.4375rem;
    border-radius: 9999px;
    background-color: oklch(var(--muted));
    border: 1px solid oklch(var(--border));
    overflow: hidden;
  }
.stat-bar__fill {
    height: 100%;
    border-radius: 9999px;
    background-color: oklch(var(--stat-bar-fill));
    transition: width 0.4s cubic-bezier(0.4, 0, 0.2, 1);
  }
.stat-bar--strong .stat-bar__fill {
    background-color: oklch(var(--stat-bar-fill-strong));
  }
/* Training activity grid — 2x2 on mobile (4 activities), scaling
     to 4 columns on larger screens so the four activity buttons fill
     a single row when horizontal space allows. Gap tightens on mobile
     (8px) and relaxes on sm+ (12px) to match the existing card rhythm.
     Each cell hosts a .training-activity-btn which carries its own
     44px min-height touch target, warm-tinted surface, and hairline
     amber border — this rule only owns the grid geometry. */
.training-activity-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.5rem;
  }
@media (min-width: 640px) {
    .training-activity-grid {
      grid-template-columns: repeat(4, minmax(0, 1fr));
      gap: 0.75rem;
    }
  }
/* Training activity button — 44px touch target, shows the
      activity name, the stat it trains (e.g. "+AGI"), and the cost
      (energy + currency). Warm-tinted dark surface with a hairline
      amber border; hover lifts the border toward primary amber.
      Disabled state mutes the surface and locks pointer events. */
.training-activity-btn {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    min-height: 2.75rem; /* 44px touch target */
    padding: 0.75rem 0.875rem;
    border-radius: var(--radius);
    background-color: oklch(var(--training-activity-bg));
    border: 1px solid oklch(var(--training-activity-border));
    color: oklch(var(--foreground));
    font-family: var(--font-body);
    text-align: left;
    cursor: pointer;
    transition: background-color 0.2s ease, border-color 0.2s ease, transform
      0.15s ease;
  }
.training-activity-btn:hover {
    background-color: oklch(var(--training-activity-hover));
    border-color: oklch(var(--primary) / 0.5);
  }
.training-activity-btn:active {
    transform: scale(0.98);
  }
.training-activity-btn:focus-visible {
    outline: 2px solid oklch(var(--ring));
    outline-offset: 2px;
  }
.training-activity-btn__name {
    font-size: 0.875rem;
    font-weight: 600;
    color: oklch(var(--foreground));
  }
.training-activity-btn__target {
    font-family: var(--font-mono);
    font-size: 0.6875rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: oklch(var(--primary));
  }
.training-activity-btn__cost {
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    font-size: 0.6875rem;
    color: oklch(var(--muted-foreground));
  }
.training-activity-btn--disabled {
    opacity: 0.5;
    cursor: not-allowed;
    pointer-events: none;
  }
/* Training confirm screen — the second step of the Activity →
     Intensity → Confirm flow. A card surface that reviews the
     chosen activity, per-stat gain ranges (not exact numbers),
     cost, and fatigue risk (if Intense). Reuses the warm-tinted
     training-activity tokens so the confirm reads as part of the
     same training surface family. 44px touch targets on every
     interactive control. */
.training-confirm {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    padding: 0.875rem;
    border-radius: var(--radius);
    background-color: oklch(var(--training-activity-bg));
    border: 1px solid oklch(var(--training-activity-border));
  }
.training-confirm__header {
    display: flex;
    align-items: center;
    gap: 0.5rem;
  }
.training-confirm__back {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    min-height: 2.75rem; /* 44px touch target */
    padding: 0.375rem 0.625rem;
    border-radius: 0.5rem;
    background-color: transparent;
    border: 1px solid oklch(var(--border));
    color: oklch(var(--muted-foreground));
    font-family: var(--font-body);
    font-size: 0.8125rem;
    font-weight: 600;
    cursor: pointer;
    transition: background-color 0.2s ease, color 0.2s ease;
  }
.training-confirm__back:hover {
    background-color: oklch(var(--muted) / 0.5);
    color: oklch(var(--foreground));
  }
.training-confirm__back:focus-visible {
    outline: 2px solid oklch(var(--ring));
    outline-offset: 2px;
  }
.training-confirm__title {
    font-family: var(--font-display);
    font-size: 1rem;
    font-weight: 600;
    color: oklch(var(--foreground));
    letter-spacing: -0.01em;
  }
.training-confirm__stats {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 0.5rem;
  }
.training-confirm__stat {
    display: flex;
    flex-direction: column;
    gap: 0.125rem;
    padding: 0.625rem 0.75rem;
    border-radius: 0.5rem;
    background-color: oklch(var(--card));
    border: 1px solid oklch(var(--border));
  }
.training-confirm__stat-name {
    font-family: var(--font-body);
    font-size: 0.75rem;
    font-weight: 600;
    text-transform: capitalize;
    color: oklch(var(--muted-foreground));
  }
.training-confirm__stat-range {
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    font-size: 1rem;
    font-weight: 700;
    color: oklch(var(--primary));
    letter-spacing: -0.01em;
  }
.training-confirm__cost {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    padding: 0.625rem 0.75rem;
    border-radius: 0.5rem;
    background-color: oklch(var(--card));
    border: 1px solid oklch(var(--border));
  }
.training-confirm__cost-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-family: var(--font-body);
    font-size: 0.8125rem;
    color: oklch(var(--muted-foreground));
  }
.training-confirm__cost-value {
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    font-weight: 600;
    color: oklch(var(--foreground));
  }
.training-confirm__fatigue-risk {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.625rem 0.75rem;
    border-radius: 0.5rem;
    background-color: oklch(var(--fatigue-badge-bg));
    border: 1px solid oklch(var(--fatigue-badge-border));
    color: oklch(var(--fatigue-badge-fg));
    font-family: var(--font-body);
    font-size: 0.8125rem;
    font-weight: 600;
  }
.training-confirm__fatigue-risk svg {
    flex: 0 0 auto;
    color: oklch(var(--fatigue-badge-fg));
  }
/* Intensity selector — a 3-segment toggle placed above the six
     stat buttons. Each segment is a 44px touch target with a tier-
     tinted surface (cool/amber/coral). The active segment lifts to
     the amber active tokens so the selection reads clearly. Cost +
     stat-gain range are shown under each label in mono. */
.intensity-toggle {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 0.375rem;
    width: 100%;
  }
.intensity-toggle__btn {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.125rem;
    min-height: 2.75rem; /* 44px touch target */
    padding: 0.5rem 0.625rem;
    border-radius: var(--radius);
    border: 1px solid oklch(var(--border));
    background-color: oklch(var(--muted));
    color: oklch(var(--foreground));
    font-family: var(--font-body);
    text-align: left;
    cursor: pointer;
    transition: background-color 0.2s ease, border-color 0.2s ease;
  }
/* Hide the native radio circle while keeping the input focusable.
     The tier-tinted <label> surface is the visible affordance. */
.intensity-toggle__input {
    position: absolute;
    opacity: 0;
    width: 1px;
    height: 1px;
    pointer-events: none;
  }
.intensity-toggle__input:focus-visible + .intensity-toggle__label {
    outline: 2px solid oklch(var(--ring));
    outline-offset: 4px;
    border-radius: 0.25rem;
  }
.intensity-toggle__btn:has(.intensity-toggle__input:focus-visible) {
    outline: 2px solid oklch(var(--ring));
    outline-offset: 2px;
  }
.intensity-toggle__btn--light {
    background-color: oklch(var(--intensity-light-bg));
    border-color: oklch(var(--intensity-light-border));
  }
.intensity-toggle__btn--standard {
    background-color: oklch(var(--intensity-standard-bg));
    border-color: oklch(var(--intensity-standard-border));
  }
.intensity-toggle__btn--intense {
    background-color: oklch(var(--intensity-intense-bg));
    border-color: oklch(var(--intensity-intense-border));
  }
.intensity-toggle__btn--active {
    background-color: oklch(var(--intensity-active-bg));
    border-color: oklch(var(--intensity-active-border));
    box-shadow: 0 0 0 1px oklch(var(--intensity-active-border));
  }
.intensity-toggle__label {
    font-size: 0.8125rem;
    font-weight: 600;
    color: oklch(var(--foreground));
  }
.intensity-toggle__btn--light .intensity-toggle__label {
    color: oklch(var(--intensity-light-fg));
  }
.intensity-toggle__btn--standard .intensity-toggle__label {
    color: oklch(var(--intensity-standard-fg));
  }
.intensity-toggle__btn--intense .intensity-toggle__label {
    color: oklch(var(--intensity-intense-fg));
  }
.intensity-toggle__meta {
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    font-size: 0.625rem;
    color: oklch(var(--muted-foreground));
    line-height: 1.2;
  }
.intensity-toggle__meta--risk {
    color: oklch(var(--fatigue-badge-fg));
    font-weight: 600;
  }
/* Fatigue badge — shown on the dog header when fatigue > 0.
     Warning-amber tint so it reads as "needs rest", not an error.
     Includes the numeric fatigue value so the player sees the
     current -energy penalty (capped at 15). */
.fatigue-badge {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    padding: 0.125rem 0.5rem;
    border-radius: 9999px;
    background-color: oklch(var(--fatigue-badge-bg));
    border: 1px solid oklch(var(--fatigue-badge-border));
    color: oklch(var(--fatigue-badge-fg));
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.02em;
  }
/* Show result modal — win/loss result display. Win uses the
     success-green tint; loss uses the destructive-coral tint.
     The headline scales up and uses the display font. Rewards
     are mono amber. The whole card has a hairline tinted border
     matching the outcome. */
.show-result-modal {
    background-color: oklch(var(--card));
    border: 1px solid oklch(var(--border));
    border-radius: calc(var(--radius) + 0.25rem);
    box-shadow: 0 8px 32px oklch(0 0 0 / 0.24);
    overflow: hidden;
  }
.show-result-modal--win {
    background-color: oklch(var(--show-win-bg));
    border-color: oklch(var(--show-win-border));
  }
.show-result-modal--loss {
    background-color: oklch(var(--show-loss-bg));
    border-color: oklch(var(--show-loss-border));
  }
.show-result-modal__headline {
    font-family: var(--font-display);
    font-size: 1.875rem;
    font-weight: 700;
    letter-spacing: -0.02em;
    line-height: 1.1;
  }
.show-result-modal--win .show-result-modal__headline {
    color: oklch(var(--show-win-fg));
  }
.show-result-modal--loss .show-result-modal__headline {
    color: oklch(var(--show-loss-fg));
  }
.show-result-modal__reward {
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    font-size: 0.875rem;
    font-weight: 600;
    color: oklch(var(--primary));
  }
/* ─── 3-phase breakdown ───────────────────────────────────────
     Each phase is a card with a header (phase name + stats tested)
     and a two-column score comparison. Critical moment narratives
     stack under the triggering dog's score column. Phases fade in
     with a staggered reveal; under reduced-motion they show
     immediately (handled via the --revealed modifier + JS). */
.show-result-modal__phase {
    background-color: oklch(var(--card));
    border: 1px solid oklch(var(--border));
    border-radius: var(--radius);
    padding: 0.75rem;
    opacity: 0;
    transform: translateY(8px);
    transition: opacity 0.35s ease, transform 0.35s ease;
  }
.show-result-modal__phase--revealed {
    opacity: 1;
    transform: translateY(0);
  }
.show-result-modal__phase-header {
    display: flex;
    flex-direction: column;
    gap: 0.125rem;
    margin-bottom: 0.625rem;
  }
.show-result-modal__phase-name {
    font-family: var(--font-display);
    font-size: 0.9375rem;
    font-weight: 600;
    color: oklch(var(--foreground));
    letter-spacing: -0.01em;
  }
.show-result-modal__phase-stats {
    font-family: var(--font-body);
    font-size: 0.75rem;
    color: oklch(var(--muted-foreground));
    line-height: 1.4;
  }
.show-result-modal__phase-scores {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0.625rem;
  }
.show-result-modal__phase-col {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    min-width: 0;
  }
.show-result-modal__phase-col--player .show-result-modal__phase-score-block {
    background-color: oklch(var(--card));
    border-color: oklch(var(--primary) / 0.3);
  }
.show-result-modal__phase-col--npc .show-result-modal__phase-score-block {
    background-color: oklch(var(--npc-opponent-bg));
    border-color: oklch(var(--npc-opponent-border));
  }
.show-result-modal__phase-score-block {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.125rem;
    padding: 0.625rem 0.5rem;
    border: 1px solid oklch(var(--border));
    border-radius: calc(var(--radius) - 0.25rem);
  }
.show-result-modal__phase-score-label {
    font-family: var(--font-body);
    font-size: 0.625rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: oklch(var(--muted-foreground));
  }
.show-result-modal__phase-score-value {
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    font-size: 1.5rem;
    font-weight: 700;
    color: oklch(var(--foreground));
    line-height: 1;
  }
/* Critical moment narrative block — sits under the triggering
     dog's phase score. Compact card with the effect badge, actor
     label, narrative text, and optional conditioning bonus chip. */
.show-result-modal__critical-stack {
    display: flex;
    flex-direction: column;
    gap: 0.375rem;
  }
.show-result-modal__critical {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    padding: 0.5rem 0.625rem;
    border-radius: calc(var(--radius) - 0.25rem);
    background-color: oklch(var(--background) / 0.5);
    border: 1px solid oklch(var(--border));
  }
.show-result-modal__critical-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.375rem;
  }
.show-result-modal__critical-effect {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    font-size: 0.6875rem;
    font-weight: 700;
  }
.show-result-modal__critical-effect--pos {
    color: oklch(var(--show-win-fg));
  }
.show-result-modal__critical-effect--neg {
    color: oklch(var(--show-loss-fg));
  }
.show-result-modal__critical-actor {
    font-family: var(--font-body);
    font-size: 0.625rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: oklch(var(--muted-foreground));
  }
.show-result-modal__critical-narrative {
    font-family: var(--font-body);
    font-style: italic;
    font-size: 0.75rem;
    line-height: 1.45;
    color: oklch(var(--foreground));
  }
.show-result-modal__conditioning-bonus {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    align-self: flex-start;
    padding: 0.1875rem 0.5rem;
    border-radius: 9999px;
    background-color: oklch(var(--conditioning-high-fg) / 0.15);
    border: 1px solid oklch(var(--conditioning-high-fg) / 0.4);
    color: oklch(var(--conditioning-high-fg));
    font-family: var(--font-body);
    font-size: 0.625rem;
    font-weight: 600;
    letter-spacing: 0.02em;
  }
/* Final tally — the aggregate playerTotal vs npcTotal. A compact
     centered row with a "vs" divider. */
.show-result-modal__tally {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.5rem;
    padding: 0.75rem;
    border-radius: var(--radius);
    background-color: oklch(var(--muted) / 0.4);
    border: 1px solid oklch(var(--border));
  }
.show-result-modal__tally-label {
    font-family: var(--font-body);
    font-size: 0.6875rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: oklch(var(--muted-foreground));
  }
.show-result-modal__tally-scores {
    display: flex;
    align-items: center;
    gap: 0.75rem;
  }
.show-result-modal__tally-side {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.125rem;
  }
.show-result-modal__tally-side-label {
    font-family: var(--font-body);
    font-size: 0.625rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: oklch(var(--muted-foreground));
  }
.show-result-modal__tally-value {
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    font-size: 1.75rem;
    font-weight: 700;
    color: oklch(var(--foreground));
    line-height: 1;
  }
.show-result-modal__tally-divider {
    font-family: var(--font-body);
    font-size: 0.75rem;
    font-weight: 600;
    color: oklch(var(--muted-foreground));
  }
/* Reward breakdown — stacked rows for Base / Upset Bonus /
     Critical Moment Bonus / Total. Each row has a label (with icon)
     and a value or reason. Bonus rows get a faint primary tint;
     the Total row is emphasized. */
.show-result-modal__rewards {
    display: flex;
    flex-direction: column;
    gap: 0.375rem;
  }
.show-result-modal__reward-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    padding: 0.5rem 0.625rem;
    border-radius: calc(var(--radius) - 0.25rem);
    background-color: oklch(var(--card));
    border: 1px solid oklch(var(--border));
  }
.show-result-modal__reward-row--bonus {
    background-color: oklch(var(--primary) / 0.08);
    border-color: oklch(var(--primary) / 0.25);
  }
.show-result-modal__reward-row--total {
    background-color: oklch(var(--primary) / 0.12);
    border-color: oklch(var(--primary) / 0.4);
    margin-top: 0.125rem;
  }
.show-result-modal__reward-row-label {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    font-family: var(--font-body);
    font-size: 0.8125rem;
    font-weight: 600;
    color: oklch(var(--foreground));
  }
.show-result-modal__reward-row-label svg {
    color: oklch(var(--primary));
  }
.show-result-modal__reward-row-value {
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    font-size: 0.8125rem;
    font-weight: 600;
    color: oklch(var(--primary));
    text-align: right;
  }
.show-result-modal__reward-row--total .show-result-modal__reward-row-value {
    font-size: 0.875rem;
    font-weight: 700;
  }
.show-result-modal__reward-row-reason {
    font-family: var(--font-body);
    font-style: italic;
    font-size: 0.75rem;
    color: oklch(var(--muted-foreground));
    text-align: right;
    line-height: 1.4;
  }
/* NPC opponent card — vertical variant for the show result modal
     so the 6-stat grid stacks below the label/name header. */
.npc-opponent-card--vertical {
    flex-direction: column;
    align-items: stretch;
    gap: 0.5rem;
  }
/* Training result modal — the mandatory results screen shown
     after every training session. Mirrors the show-result-modal
     pattern (mobile drawer / desktop dialog, body scroll lock,
     single-tap dismiss). The base container uses card bg + border;
     the breakthrough modifier swaps in the golden --breakthrough-*
     tokens for a rare, premium feel. Stat rows reuse .stat-bar so
     the fill animation is consistent with the dog detail view. */
.training-result-modal {
    background-color: oklch(var(--card));
    border: 1px solid oklch(var(--border));
    border-radius: calc(var(--radius) + 0.25rem);
    box-shadow: 0 8px 32px oklch(0 0 0 / 0.24);
    overflow: hidden;
  }
.training-result-modal--breakthrough {
    background-color: oklch(var(--breakthrough-bg));
    border-color: oklch(var(--breakthrough-border));
    box-shadow: 0 8px 32px oklch(0 0 0 / 0.24), 0 0 24px
      oklch(var(--breakthrough-glow) / 0.35);
  }
.training-result-modal__headline {
    font-family: var(--font-display);
    font-size: 1.875rem;
    font-weight: 700;
    letter-spacing: -0.02em;
    line-height: 1.1;
    color: oklch(var(--foreground));
  }
.training-result-modal--breakthrough .training-result-modal__headline {
    color: oklch(var(--breakthrough-fg));
    text-shadow: 0 0 18px oklch(var(--breakthrough-glow) / 0.7);
  }
.training-result-modal__activity {
    font-family: var(--font-body);
    font-size: 0.875rem;
    font-weight: 500;
    color: oklch(var(--muted-foreground));
    text-transform: uppercase;
    letter-spacing: 0.04em;
  }
.training-result-modal__stat-row {
    display: flex;
    align-items: center;
    gap: 0.625rem;
    position: relative;
  }
.training-result-modal__stat-name {
    flex: 0 0 5.5rem;
    font-size: 0.8125rem;
    font-weight: 500;
    color: oklch(var(--foreground));
    text-transform: capitalize;
  }
.training-result-modal__stat-bar {
    flex: 1 1 auto;
  }
.training-result-modal__stat-value {
    flex: 0 0 auto;
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    font-size: 0.8125rem;
    font-weight: 600;
    color: oklch(var(--foreground));
    min-width: 2.5rem;
    text-align: right;
  }
.training-result-modal__stat-gain-popup {
    position: absolute;
    right: 2.75rem;
    top: -0.75rem;
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    font-size: 0.875rem;
    font-weight: 700;
    color: oklch(var(--breakthrough-fg));
    text-shadow: 0 0 8px oklch(var(--breakthrough-glow) / 0.6);
    pointer-events: none;
  }
.training-result-modal--breakthrough .training-result-modal__stat-gain-popup {
    color: oklch(var(--breakthrough-fg));
  }
.training-result-modal__breakthrough-callout {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    padding: 0.75rem 1rem;
    border-radius: var(--radius);
    background-color: oklch(var(--breakthrough-bg));
    border: 1px solid oklch(var(--breakthrough-border));
    color: oklch(var(--breakthrough-fg));
    font-family: var(--font-display);
    font-size: 1rem;
    font-weight: 700;
    text-align: center;
  }
.training-result-modal__fatigue-warning {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.625rem 0.875rem;
    border-radius: var(--radius);
    background-color: oklch(0.3 0.12 50 / 0.18);
    border: 1px solid oklch(0.55 0.14 50 / 0.5);
    color: oklch(0.82 0.14 50);
    font-size: 0.8125rem;
    font-weight: 500;
  }
.training-result-modal__xp-section {
    display: flex;
    flex-direction: column;
    gap: 0.375rem;
  }
.training-result-modal__xp-label {
    display: flex;
    align-items: justify-between;
    justify-content: space-between;
    font-size: 0.75rem;
    color: oklch(var(--muted-foreground));
  }
.training-result-modal__daily-count {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    padding: 0.375rem 0.75rem;
    border-radius: 9999px;
    background-color: oklch(var(--muted));
    border: 1px solid oklch(var(--border));
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    font-size: 0.8125rem;
    font-weight: 600;
    color: oklch(var(--foreground));
  }
.training-result-modal__flavor-text {
    font-family: var(--font-body);
    font-style: italic;
    font-size: 0.875rem;
    color: oklch(var(--muted-foreground));
    text-align: center;
  }
.training-result-modal__close {
    min-height: 2.75rem;
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--radius);
    font-weight: 600;
  }
.training-result-modal__level-up {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.375rem;
    padding: 0.625rem 0.875rem;
    border-radius: var(--radius);
    background-color: oklch(var(--primary) / 0.12);
    border: 1px solid oklch(var(--primary) / 0.4);
    color: oklch(var(--primary));
    font-size: 0.9375rem;
    font-weight: 600;
  }
/* NPC opponent card — the rival in a local show. Desaturated
     violet (hue 290) at low chroma so the rival reads as
     neutral-foreign, not aggressive. Compact card with the
     opponent name and a stat summary. */
.npc-opponent-card {
    background-color: oklch(var(--npc-opponent-bg));
    border: 1px solid oklch(var(--npc-opponent-border));
    border-radius: var(--radius);
    padding: 0.75rem 1rem;
    display: flex;
    align-items: center;
    gap: 0.625rem;
  }
.npc-opponent-card__label {
    font-family: var(--font-body);
    font-size: 0.6875rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: oklch(var(--npc-opponent-fg));
  }
.npc-opponent-card__name {
    font-family: var(--font-display);
    font-size: 1rem;
    font-weight: 600;
    color: oklch(var(--foreground));
  }
.npc-opponent-card__accent {
    color: oklch(var(--npc-opponent-accent));
  }
/* Daily counter — sessions used today out of 4. A row of four
     dots (filled amber for used, muted for remaining) plus a mono
     "n / 4" label. Reused for the daily training cap. */
.daily-counter {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.375rem 0.75rem;
    border-radius: 9999px;
    background-color: oklch(var(--muted));
    border: 1px solid oklch(var(--border));
  }
.daily-counter__dots {
    display: inline-flex;
    gap: 0.3125rem;
  }
.daily-counter__dot {
    width: 0.5rem;
    height: 0.5rem;
    border-radius: 9999px;
    background-color: oklch(var(--muted-foreground) / 0.4);
  }
.daily-counter__dot--filled {
    background-color: oklch(var(--primary));
  }
.daily-counter__label {
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    font-size: 0.75rem;
    font-weight: 600;
    color: oklch(var(--foreground));
  }
/* History entry — training/show/practice history items. A row
     with a circular icon, a label, and a mono timestamp. Win
     entries get a faint success-green left-border accent; loss
     entries get a destructive-coral accent. */
.history-entry {
    display: flex;
    align-items: center;
    gap: 0.625rem;
    padding: 0.625rem 0.75rem;
    border-bottom: 1px solid oklch(var(--border));
  }
.history-entry:last-child {
    border-bottom: none;
  }
.history-entry__icon {
    flex: 0 0 auto;
    width: 1.75rem;
    height: 1.75rem;
    border-radius: 9999px;
    background-color: oklch(var(--card));
    border: 1px solid oklch(var(--border));
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: oklch(var(--primary));
  }
.history-entry__text {
    flex: 1 1 auto;
    font-family: var(--font-body);
    font-size: 0.8125rem;
    line-height: 1.5;
    color: oklch(var(--foreground));
  }
.history-entry__time {
    flex: 0 0 auto;
    font-family: var(--font-mono);
    font-size: 0.6875rem;
    color: oklch(var(--muted-foreground));
    white-space: nowrap;
  }
.history-entry--win {
    border-left: 2px solid oklch(var(--show-win-border));
    padding-left: 0.625rem;
  }
.history-entry--win .history-entry__icon {
    color: oklch(var(--show-win-fg));
    border-color: oklch(var(--show-win-border));
  }
.history-entry--loss {
    border-left: 2px solid oklch(var(--show-loss-border));
    padding-left: 0.625rem;
  }
.history-entry--loss .history-entry__icon {
    color: oklch(var(--show-loss-fg));
    border-color: oklch(var(--show-loss-border));
  }
/* ─────────────────────────────────────────────────────────────
     Shows page — dog gameplay status grid + card surface. Extends
     the existing dark OLED system; no new palette. All colors are
     OKLCH tokens. Honors prefers-reduced-motion (see bottom of
     file). 44px touch targets on every interactive element.
     ───────────────────────────────────────────────────────────── */
/* Responsive grid: 1 col mobile → 2 col tablet → 3 col small
     desktop → 4 col large desktop. Matches the kennel-grid rhythm
     so the Shows page reads as part of the same family. */
.shows-grid {
    display: grid;
    gap: 0.75rem;
    grid-template-columns: minmax(0, 1fr);
  }
@media (min-width: 640px) {
    .shows-grid {
      gap: 1rem;
      grid-template-columns: repeat(2, minmax(0, 1fr));
    }
  }
@media (min-width: 1024px) {
    .shows-grid {
      grid-template-columns: repeat(3, minmax(0, 1fr));
    }
  }
@media (min-width: 1280px) {
    .shows-grid {
      grid-template-columns: repeat(4, minmax(0, 1fr));
    }
  }
/* Show dog card — elevated dark card with a hairline border,
     rounded-xl, overflow-hidden for the image. The header button
     (image + name + level badge) is the primary tap target that
     opens the gameplay modal. Hover lifts to shadow-elevated with
     a subtle translate; reduced-motion drops the transform. */
.show-dog-card {
    position: relative;
    display: flex;
    flex-direction: column;
    background-color: oklch(var(--card));
    border: 1px solid oklch(var(--border));
    border-radius: calc(var(--radius) + 0.25rem);
    overflow: hidden;
    box-shadow: 0 2px 8px oklch(0 0 0 / 0.12);
    transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s
      ease;
  }
.show-dog-card:hover {
    transform: translateY(-2px);
    box-shadow: 0 8px 32px oklch(0 0 0 / 0.24);
    border-color: oklch(var(--primary) / 0.4);
  }
/* Card header — the clickable region (image + name + level).
     Full-width button reset so the whole header is a 44px-friendly
     tap target that opens the gameplay modal. */
.show-dog-card__header {
    display: flex;
    flex-direction: column;
    width: 100%;
    padding: 0;
    border: none;
    background: transparent;
    cursor: pointer;
    text-align: left;
    transition: background-color 0.2s ease;
  }
.show-dog-card__header:hover {
    background-color: oklch(var(--muted) / 0.3);
  }
.show-dog-card__header:focus-visible {
    outline: 2px solid oklch(var(--ring));
    outline-offset: -2px;
  }
/* ============================================================
     Pass 9 — Daily Streak / Flame System
     Streak indicator pill, flame icon, 7-day reward track nodes,
     tiered reward display, and gentle broken-streak messaging.
     All tokens (--flame-*, --streak-broken-fg) are defined in the
     :root and .dark blocks above. Mobile-first, 44px targets.
     ============================================================ */
/* Streak indicator pill — sits in the dashboard header. A
     compact flame-tinted pill: flame icon + streak number +
     optional countdown. Min-height 44px for touch. Hairline
     flame border, very dim flame surface so it doesn't compete
     with the primary amber CTAs. */
.streak-flame {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    min-height: 44px;
    padding: 0.25rem 0.75rem;
    background-color: oklch(var(--flame-bg));
    border: 1px solid oklch(var(--flame-border) / 0.6);
    border-radius: 9999px;
    color: oklch(var(--flame-fg));
    font-family: var(--font-body);
    font-size: 0.875rem;
    font-weight: 600;
    line-height: 1;
    transition: border-color 0.2s ease, background-color 0.2s ease;
  }
.streak-flame:hover {
    border-color: oklch(var(--flame-border));
    background-color: oklch(var(--flame-bg) / 0.85);
  }
.streak-flame:focus-visible {
    outline: 2px solid oklch(var(--ring));
    outline-offset: 2px;
  }
/* Streak flame icon — the lucide Flame glyph wrapped so it
     carries the flicker animation + ambient glow. The icon itself
     is sized at 1.25rem (20px) for clear visibility in the pill.
     The flicker is subtle (see @keyframes flame-flicker) and is
     disabled under prefers-reduced-motion. */
.streak-flame__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.25rem;
    height: 1.25rem;
    color: oklch(var(--flame-fg));
    animation: flame-flicker 2.4s ease-in-out infinite;
    transform-origin: 50% 80%;
  }
/* Streak number — display font, bold, the focal value. Sits
     next to the flame icon. Mono digits would feel cold here;
     Space Grotesk gives the count warmth and weight. */
.streak-flame__count {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 1rem;
    line-height: 1;
    letter-spacing: -0.02em;
    color: oklch(var(--flame-fg));
  }
/* Countdown text — "Next reward in Xh Ym" shown when a reward
     is pending before UTC midnight reset. Muted flame tone so
     it reads as secondary info inside the pill. Hidden on the
     smallest screens via the component (truncate). */
.streak-flame__countdown {
    font-family: var(--font-mono);
    font-size: 0.6875rem;
    font-weight: 500;
    color: oklch(var(--flame-fg) / 0.7);
    white-space: nowrap;
  }
/* Today's reward preview — a tiny inline chip inside the pill
     showing what today's claim yields (e.g. "◎ 50"). Mono so
     it reads as a quantity, separated by a hairline divider. */
.streak-flame__reward-preview {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    padding-left: 0.5rem;
    margin-left: 0.25rem;
    border-left: 1px solid oklch(var(--flame-border) / 0.4);
    font-family: var(--font-mono);
    font-size: 0.6875rem;
    font-weight: 600;
    color: oklch(var(--flame-fg) / 0.85);
  }
/* Broken-streak state — when the streak is 0 the pill swaps to
     the ember tone (lower chroma, dimmer) and the icon stops
     flickering. No red, no warning hue — just a quiet ember so
     the reset reads as "the fire went out, relight it" rather
     than "you failed". Gentle, no shaming. */
.streak-flame--broken {
    background-color: oklch(var(--flame-bg) / 0.5);
    border-color: oklch(var(--flame-ember) / 0.4);
    color: oklch(var(--streak-broken-fg));
  }
.streak-flame--broken .streak-flame__icon {
    color: oklch(var(--streak-broken-fg));
    animation: none;
    filter: drop-shadow(0 0 3px oklch(var(--flame-ember) / 0.3));
  }
.streak-flame--broken .streak-flame__count,
  .streak-flame--broken .streak-flame__reward-preview {
    color: oklch(var(--streak-broken-fg));
  }
/* Increment pulse — a one-shot scale bump when the streak
     increments (e.g. claiming today's reward). Reuses the
     flame-flicker glow but as a single 0.5s pulse via the
     win-celebration animation pattern. Applied momentarily by
     the component, then removed. */
.streak-flame--increment {
    animation: win-celebration 0.5s cubic-bezier(0.16, 1, 0.3, 1) both;
  }
/* ---- 7-day reward track (modal) ---- */
/* Track container — horizontal scroll on mobile, wraps to a
     tidy grid on sm+. Each node is a day on the track. The
     connecting line between nodes is drawn by the container's
     ::before (a hairline behind the nodes). */
.streak-track {
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
    padding: 0.5rem 0;
    overflow-x: auto;
    scrollbar-width: none;
  }
.streak-track::-webkit-scrollbar {
    display: none;
  }
@media (min-width: 640px) {
    .streak-track {
      display: grid;
      grid-template-columns: repeat(7, minmax(0, 1fr));
      gap: 0.5rem;
      overflow: visible;
    }
  }
/* Track node — one day on the 7-day track. Circular 44px
     target (touch-safe), with the day number and reward icon.
     States: claimed (muted, check), current (flame-tinted,
     active ring), locked (very dim, lock icon). */
.streak-track__node {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.375rem;
    flex: 0 0 auto;
    width: 3.5rem;
  }
/* Node circle — the 44px tap target. Default (upcoming/
     locked) is very dim. State modifiers below. */
.streak-track__circle {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    border-radius: 9999px;
    border: 1px solid oklch(var(--flame-track-locked) / 0.6);
    background-color: oklch(var(--flame-track-bg));
    color: oklch(var(--muted-foreground));
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 0.875rem;
    transition: background-color 0.2s ease, border-color 0.2s ease, color 0.2s
      ease, box-shadow 0.2s ease;
  }
/* Claimed — muted surface, check icon, no flame. Reads as
     "done, collected". Slightly higher surface than locked. */
.streak-track__circle--claimed {
    background-color: oklch(var(--flame-track-claimed));
    border-color: oklch(var(--flame-track-claimed));
    color: oklch(var(--muted-foreground) / 0.85);
  }
/* Current — flame-tinted active node. Carries the flame glow
     shadow + the flicker animation on its inner icon so the
     "today" node feels lit. This is the claim target. */
.streak-track__circle--current {
    background-color: oklch(var(--flame-track-current));
    border-color: oklch(var(--flame-border));
    color: oklch(var(--flame-fg));
    box-shadow: 0 0 0 3px oklch(var(--flame-glow) / 0.18), 0 0 14px
      oklch(var(--flame-glow) / 0.35);
  }
.streak-track__circle--current .streak-track__circle-icon {
    animation: flame-flicker 2.4s ease-in-out infinite;
    transform-origin: 50% 80%;
  }
/* Locked — very dim, lock icon, not yet claimable. The dimmest
     surface on the track so the eye is drawn to current/claimed. */
.streak-track__circle--locked {
    background-color: oklch(var(--flame-track-locked));
    border-color: oklch(var(--flame-track-locked) / 0.7);
    color: oklch(var(--muted-foreground) / 0.5);
  }
/* Node label — "Day 1".."Day 7" below the circle. Mono so it
     reads as a slot marker. Current day label is flame-tinted. */
.streak-track__label {
    font-family: var(--font-mono);
    font-size: 0.625rem;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: oklch(var(--muted-foreground));
    text-align: center;
    white-space: nowrap;
  }
.streak-track__node--current .streak-track__label {
    color: oklch(var(--flame-fg));
  }
/* Node reward — the reward value under the label (e.g. "◎ 50"
     or a rarity tag). Mono for quantities. Claimed nodes mute
     the reward; current nodes highlight it. */
.streak-track__reward {
    font-family: var(--font-mono);
    font-size: 0.6875rem;
    font-weight: 600;
    color: oklch(var(--flame-fg) / 0.8);
    text-align: center;
    line-height: 1.2;
  }
.streak-track__node--claimed .streak-track__reward {
    color: oklch(var(--muted-foreground) / 0.6);
    text-decoration: line-through;
    text-decoration-color: oklch(var(--muted-foreground) / 0.4);
  }
.streak-track__node--locked .streak-track__reward {
    color: oklch(var(--muted-foreground) / 0.45);
  }
/* ---- Tiered reward display (caps at day 30) ---- */
/* Tier strip — shown below the 7-day track in the modal.
     Displays the tiered reward schedule (days 8, 15, 22, 30)
     as a compact vertical list. Each tier row shows the day
     threshold + reward. Repeat-tier (day 30+) gets a "repeats"
     badge so users know the cap. */
.streak-tiers {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    margin-top: 1rem;
    padding-top: 1rem;
    border-top: 1px solid oklch(var(--border));
  }
/* Tier row — day threshold (mono, flame-fg) + reward value
     (mono, foreground). Hairline divider between rows. */
.streak-tier {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    padding-bottom: 0.5rem;
    border-bottom: 1px solid oklch(var(--border) / 0.5);
  }
.streak-tier:last-child {
    border-bottom: none;
    padding-bottom: 0;
  }
/* Tier day — "Day 8", "Day 15", etc. Display font so the
     milestone thresholds feel like achievements. */
.streak-tier__day {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 0.875rem;
    color: oklch(var(--flame-fg));
    letter-spacing: -0.01em;
  }
/* Tier reward — the reward value, mono. Right-aligned. */
.streak-tier__reward {
    font-family: var(--font-mono);
    font-size: 0.8125rem;
    font-weight: 600;
    color: oklch(var(--foreground));
  }
/* Repeat-tier badge — marks the day-30 cap row as "repeats
     every 7 days" so users understand the schedule continues.
     A small muted pill, no flame tint (it's informational, not
     a claim target). */
.streak-tier__repeat-badge {
    display: inline-flex;
    align-items: center;
    padding: 0.125rem 0.5rem;
    border-radius: 9999px;
    background-color: oklch(var(--muted));
    color: oklch(var(--muted-foreground));
    font-family: var(--font-mono);
    font-size: 0.625rem;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    margin-left: 0.5rem;
  }
/* ---- Gentle broken-streak messaging ---- */
/* Broken-streak message — shown in the modal (and optionally
     inline) when the streak is 0. Ember tone, not destructive.
     Centered, warm, encouraging. No exclamation marks, no red,
     no "you lost your streak" language. Reads as "the flame
     needs relighting" — an invitation, not a penalty. */
.streak-broken-message {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.5rem;
    padding: 1.25rem 1rem;
    text-align: center;
  }
/* Broken-streak icon — a dim ember flame (no flicker). */
.streak-broken-message__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    color: oklch(var(--streak-broken-fg));
    filter: drop-shadow(0 0 6px oklch(var(--flame-ember) / 0.4));
  }
/* Broken-streak headline — display font, ember tone. Short,
     warm, non-judgmental. e.g. "Your flame is waiting". */
.streak-broken-message__title {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 1.125rem;
    color: oklch(var(--streak-broken-fg));
    letter-spacing: -0.02em;
  }
/* Broken-streak body — Satoshi, muted-foreground. One line,
     gentle, action-oriented. e.g. "Claim today's reward to
     relight your streak." */
.streak-broken-message__body {
    font-family: var(--font-body);
    font-size: 0.875rem;
    line-height: 1.5;
    color: oklch(var(--muted-foreground));
    max-width: 20rem;
  }
/* ============================================================
     Grace toast — a calm sage-green toast surface distinct from
     the streak-flame (orange) and reward (amber) toast families.
     Used for grace-period / second-chance messages (e.g. "Streak
     safe — grace window active"). Reads as gentle reassurance:
     not a reward to celebrate, not a warning to fear. The accent
     leading dot ties to the grace-toast-accent token so the toast
     reads as part of the streak system without competing with the
     flame. 44px min-height for touch. Honors prefers-reduced-motion
     (see the override at the bottom of this file).
     ============================================================ */
.grace-toast {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    min-height: 2.75rem; /* 44px touch target */
    padding: 0.5rem 0.875rem;
    border-radius: var(--radius);
    background-color: oklch(var(--grace-toast-bg));
    border: 1px solid oklch(var(--grace-toast-border) / 0.6);
    color: oklch(var(--grace-toast-fg));
    font-family: var(--font-body);
    font-size: 0.8125rem;
    font-weight: 500;
    line-height: 1.4;
    transition: border-color 0.2s ease, background-color 0.2s ease;
  }
.grace-toast:focus-visible {
    outline: 2px solid oklch(var(--ring));
    outline-offset: 2px;
  }
/* Leading accent dot — a small sage-green dot that marks the
     toast as a grace/second-chance message. Distinct from the
     flame icon (streak-flame) and the reward gem (reward toasts)
     so the three streak-system toast families stay visually
     separable. */
.grace-toast__dot {
    flex: 0 0 auto;
    width: 0.5rem;
    height: 0.5rem;
    border-radius: 9999px;
    background-color: oklch(var(--grace-toast-accent));
    box-shadow: 0 0 6px oklch(var(--grace-toast-accent) / 0.4);
  }
.grace-toast__text {
    flex: 1 1 auto;
    min-width: 0;
    color: oklch(var(--grace-toast-fg));
  }
/* Grace indicator — a compact inline-flex pill used in the
     dashboard header to surface an active streak grace period.
     Reuses the grace-toast sage-green tokens so it reads as part
     of the same grace/second-chance visual family as the toast,
     but in a smaller, inline pill form factor suitable for the
     header row. 44px min-height for touch; cursor pointer since
     it opens the streak reward modal. Honors prefers-reduced-motion
     (no animation by default; transition:none reinforced in the
     reduced-motion block at the bottom of this file). */
.grace-indicator {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    min-height: 2.75rem; /* 44px touch target */
    padding: 0 0.75rem;
    border-radius: 9999px;
    background-color: oklch(var(--grace-toast-bg));
    color: oklch(var(--grace-toast-fg));
    border: 1px solid oklch(var(--grace-toast-border));
    font-family: var(--font-body);
    font-size: 0.75rem;
    font-weight: 500;
    line-height: 1.4;
    cursor: pointer;
    transition: border-color 0.2s ease, background-color 0.2s ease;
  }
.grace-indicator:focus-visible {
    outline: 2px solid oklch(var(--ring));
    outline-offset: 2px;
  }
.grace-indicator__icon {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: oklch(var(--grace-toast-accent));
  }
.grace-indicator__label {
    flex: 1 1 auto;
    min-width: 0;
    color: oklch(var(--grace-toast-fg));
    white-space: nowrap;
  }
/* ============================================================
     Streak History — past streak cycle cards.
     Reconstructed client-side from the activity log. Each cycle
     is an expandable card: collapsed summary (flame icon, date
     range, peak day, break reason, quick stats, chevron) and an
     expanded day-by-day reward list. Reuses the flame tokens
     (--flame-*, --streak-broken-fg) so the history reads as part
     of the streak system. Active cycles get a flame-tinted border;
     closed cycles use the neutral card surface. 44px touch targets
     on the summary button. Honors prefers-reduced-motion (the
     flicker is disabled in CSS; expand/collapse is a state toggle).
     ============================================================ */
/* Card surface — elevated dark card with a hairline border.
     Hover lifts the border toward primary amber (closed cycles) so
     the row reads as interactive. The active modifier swaps in the
     flame border so the ongoing cycle stands out. */
.streak-history-card {
    background-color: oklch(var(--card));
    border: 1px solid oklch(var(--border));
    border-radius: calc(var(--radius) + 0.25rem);
    overflow: hidden;
    box-shadow: 0 2px 8px oklch(0 0 0 / 0.12);
    transition: border-color 0.2s ease, box-shadow 0.2s ease;
  }
.streak-history-card:hover {
    border-color: oklch(var(--primary) / 0.4);
    box-shadow: 0 4px 16px oklch(0 0 0 / 0.18);
  }
.streak-history-card--active {
    border-color: oklch(var(--flame-border));
    box-shadow: 0 2px 8px oklch(0 0 0 / 0.12), 0 0 12px
      oklch(var(--flame-glow) / 0.12);
  }
.streak-history-card--active:hover {
    border-color: oklch(var(--flame-border));
    box-shadow: 0 4px 16px oklch(0 0 0 / 0.18), 0 0 16px
      oklch(var(--flame-glow) / 0.2);
  }
/* Summary row — the clickable header of the card. Full-width
     button reset so the whole row is a 44px-friendly tap target.
     Flex layout: icon | meta | stats | chevron. */
.streak-history-card__summary {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    width: 100%;
    min-height: 2.75rem; /* 44px touch target */
    padding: 0.75rem 1rem;
    background: transparent;
    border: none;
    text-align: left;
    cursor: pointer;
    transition: background-color 0.2s ease;
  }
.streak-history-card__summary:hover {
    background-color: oklch(var(--muted) / 0.3);
  }
.streak-history-card__summary:focus-visible {
    outline: 2px solid oklch(var(--ring));
    outline-offset: -2px;
  }
/* Leading flame icon. Default (closed cycle) is muted; the active
     modifier carries the flame color + flicker so the ongoing cycle
     feels lit. */
.streak-history-card__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 2.5rem;
    height: 2.5rem;
    border-radius: 9999px;
    background-color: oklch(var(--flame-bg) / 0.5);
    border: 1px solid oklch(var(--flame-border) / 0.4);
    color: oklch(var(--streak-broken-fg));
  }
.streak-history-card__icon--active {
    background-color: oklch(var(--flame-bg));
    border-color: oklch(var(--flame-border));
    color: oklch(var(--flame-fg));
  }
.streak-history-card__icon--active svg {
    animation: flame-flicker 2.4s ease-in-out infinite;
    transform-origin: 50% 80%;
  }
/* Meta column — date range + sub-line (peak day + reason). */
.streak-history-card__meta {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    flex: 1 1 auto;
  }
.streak-history-card__date-range {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    font-family: var(--font-display);
    font-size: 0.9375rem;
    font-weight: 600;
    color: oklch(var(--foreground));
    letter-spacing: -0.01em;
  }
.streak-history-card__sub {
    display: inline-flex;
    align-items: center;
    gap: 0.625rem;
    flex-wrap: wrap;
  }
.streak-history-card__peak {
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    font-size: 0.75rem;
    font-weight: 600;
    color: oklch(var(--muted-foreground));
  }
/* Break-reason pill — color-coded by reason. Active = flame,
     broken = ember, gap = muted. */
.streak-history-card__reason {
    display: inline-flex;
    align-items: center;
    padding: 0.0625rem 0.5rem;
    border-radius: 9999px;
    font-family: var(--font-body);
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    border: 1px solid oklch(var(--border));
  }
.streak-history-card__reason--active {
    background-color: oklch(var(--flame-bg));
    color: oklch(var(--flame-fg));
    border-color: oklch(var(--flame-border) / 0.6);
  }
.streak-history-card__reason--broken {
    background-color: oklch(var(--flame-bg) / 0.4);
    color: oklch(var(--streak-broken-fg));
    border-color: oklch(var(--flame-ember) / 0.4);
  }
.streak-history-card__reason--gap {
    background-color: oklch(var(--muted));
    color: oklch(var(--muted-foreground));
  }
/* Quick stats — rewards + freezes count badges. */
.streak-history-card__stats {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    flex: 0 0 auto;
  }
.streak-history-card__stat {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    padding: 0.1875rem 0.5rem;
    border-radius: 9999px;
    background-color: oklch(var(--muted));
    border: 1px solid oklch(var(--border));
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    font-size: 0.75rem;
    font-weight: 600;
    color: oklch(var(--foreground));
  }
/* Expand/collapse chevron — rotates 180deg when open. */
.streak-history-card__chevron {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    color: oklch(var(--muted-foreground));
    transition: transform 0.2s ease;
  }
.streak-history-card__chevron--open {
    transform: rotate(180deg);
  }
/* Expanded detail — day-by-day reward list. Sits below the
     summary, separated by a top border. */
.streak-history-card__detail {
    padding: 0.75rem 1rem 1rem;
    border-top: 1px solid oklch(var(--border));
    background-color: oklch(var(--background) / 0.4);
  }
.streak-history-card__detail-header {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    margin-bottom: 0.625rem;
    font-family: var(--font-body);
    font-size: 0.75rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: oklch(var(--muted-foreground));
  }
.streak-history-card__detail-header svg {
    color: oklch(var(--primary));
  }
/* Day list — vertical list of day rows. Each row: day number,
     reward, status. Claimed days get a faint flame tint. */
.streak-history-card__day-list {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    list-style: none;
    margin: 0;
    padding: 0;
  }
.streak-history-card__day {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.5rem 0.625rem;
    border-radius: calc(var(--radius) - 0.25rem);
    background-color: oklch(var(--card));
    border: 1px solid oklch(var(--border));
  }
.streak-history-card__day--claimed {
    background-color: oklch(var(--flame-bg) / 0.25);
    border-color: oklch(var(--flame-border) / 0.4);
  }
.streak-history-card__day-number {
    flex: 0 0 auto;
    font-family: var(--font-display);
    font-size: 0.8125rem;
    font-weight: 700;
    color: oklch(var(--foreground));
    letter-spacing: -0.01em;
    min-width: 3.5rem;
  }
.streak-history-card__day-reward {
    flex: 1 1 auto;
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    font-size: 0.8125rem;
    font-weight: 600;
    color: oklch(var(--primary));
  }
.streak-history-card__day--claimed .streak-history-card__day-reward {
    color: oklch(var(--flame-fg));
  }
.streak-history-card__day-status {
    flex: 0 0 auto;
    font-family: var(--font-body);
    font-size: 0.6875rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: oklch(var(--muted-foreground));
  }
.streak-history-card__day--claimed .streak-history-card__day-status {
    color: oklch(var(--flame-fg));
  }
.\[--cell-size\:--spacing\(8\)\] {
  --cell-size: var(--spacing(8));
}

@font-face {
  font-family: "Space Grotesk";
  src: url("/assets/fonts/SpaceGrotesk.woff2") format("woff2");
  font-display: swap;
}

@font-face {
  font-family: "Satoshi";
  src: url("/assets/fonts/Satoshi.woff2") format("woff2");
  font-display: swap;
}

@font-face {
  font-family: "JetBrains Mono";
  src: url("/assets/fonts/JetBrainsMono.woff2") format("woff2");
  font-display: swap;
}

.shadow-elevated {
  box-shadow: 0 8px 32px oklch(0 0 0 / 0.24);
}

.shadow-subtle {
  box-shadow: 0 2px 8px oklch(0 0 0 / 0.12);
}

.gradient-primary {
  background: linear-gradient(135deg, oklch(0.72 0.17 70), oklch(0.58 0.14 25));
}

.text-gradient {
  background: linear-gradient(135deg, oklch(0.72 0.17 70), oklch(0.58 0.14 25));
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
}

/* ───────────────────────────────────────────────────────────────────
   Stat slider — enlarged thumb for 44px touch target, visible track
   and primary-tinted filled range on the dark OLED background.
   Uses OKLCH tokens (primary, border, background) for full theme sync.
   ─────────────────────────────────────────────────────────────────── */
.stat-slider [data-slot="slider-track"] {
  height: 0.5rem;
  background-color: oklch(var(--muted));
  border: 1px solid oklch(var(--border));
}

.stat-slider [data-slot="slider-range"] {
  background-color: oklch(var(--primary));
}

.stat-slider [data-slot="slider-thumb"] {
  width: 1.125rem;
  height: 1.125rem;
  border: 2px solid oklch(var(--primary));
  background-color: oklch(var(--background));
  box-shadow: 0 0 0 6px oklch(var(--primary) / 0.18);
  cursor: pointer;
  transition: box-shadow 0.15s ease, transform 0.15s ease;
}

.stat-slider [data-slot="slider-thumb"]:hover {
  box-shadow: 0 0 0 9px oklch(var(--primary) / 0.24);
  transform: scale(1.05);
}

.stat-slider [data-slot="slider-thumb"]:focus-visible {
  box-shadow: 0 0 0 9px oklch(var(--primary) / 0.32);
  outline: 2px solid oklch(var(--primary));
  outline-offset: 2px;
}

/* Expand the invisible hit area around the thumb to ~44px without
   changing the visible thumb size. Radix wraps the thumb in a span
   we can pad via ::after. */
.stat-slider [data-slot="slider-thumb"]::after {
  content: "";
  position: absolute;
  inset: -0.75rem;
  border-radius: 9999px;
}

@media (prefers-reduced-motion: reduce) {
  .stat-slider [data-slot="slider-thumb"] {
    transition: none;
  }
}

/* ───────────────────────────────────────────────────────────────────
   Filter favorites toggle — enlarged Radix Switch for a 44px-friendly
   hit area and stronger contrast on the dark OLED background.
   Track grows to 28px tall, thumb to 22px with a primary glow ring.
   ─────────────────────────────────────────────────────────────────── */
.filter-switch {
  width: 3rem;
  height: 1.75rem;
}

.filter-switch [data-slot="switch-thumb"] {
  width: 1.375rem;
  height: 1.375rem;
  box-shadow: 0 0 0 4px oklch(var(--primary) / 0.18);
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}

.filter-switch[data-state="checked"] [data-slot="switch-thumb"] {
  transform: translateX(calc(100% + 0.375rem));
  box-shadow: 0 0 0 5px oklch(var(--primary) / 0.24);
}

.filter-switch[data-state="unchecked"] [data-slot="switch-thumb"] {
  transform: translateX(0.125rem);
}

.filter-switch:focus-visible [data-slot="switch-thumb"] {
  box-shadow: 0 0 0 6px oklch(var(--primary) / 0.32);
}

@media (prefers-reduced-motion: reduce) {
  .filter-switch [data-slot="switch-thumb"] {
    transition: none;
  }
}

/* ───────────────────────────────────────────────────────────────────
   Motion keyframes — DESIGN.md specifies fade-in (0.4s staggered),
   slide-up (0.35s modal/drawer), pulse-ring (FAB affordance), and a
   skeleton shimmer consistent with the existing ui/skeleton.tsx pulse.
   Defined here (not tailwind.config.js) so they compose with the
   OKLCH tokens and the existing custom utilities in this file.
   ─────────────────────────────────────────────────────────────────── */

/* Pass 5 — premium shimmer sweep. A diagonal light band travels
   left-to-right across the skeleton surface, lifting the muted fill
   toward a warm-tinted peak. Background-position animates the band;
   the surface itself never scales, so layout stays stable. */
@keyframes skeleton-shimmer {
  0% {
    background-position: -200% 0;
  }
  100% {
    background-position: 200% 0;
  }
}

/* Legacy pulse kept for backward compatibility with any component
   still referencing animate-skeleton-pulse. Prefer the shimmer. */
@keyframes skeleton-pulse {
  0%,
  100% {
    opacity: 1;
    transform: scale(1);
  }
  50% {
    opacity: 0.55;
    transform: scale(0.995);
  }
}

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

@keyframes slide-up {
  from {
    opacity: 0;
    transform: translateY(24px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes pulse-ring {
  0% {
    box-shadow: 0 0 0 0 oklch(var(--primary) / 0.45);
  }
  70% {
    box-shadow: 0 0 0 12px oklch(var(--primary) / 0);
  }
  100% {
    box-shadow: 0 0 0 0 oklch(var(--primary) / 0);
  }
}

/* Breakthrough / show-win celebration — a golden glow pulse with a
   gentle scale. Used on the training-result headline when a
   breakthrough fires and on the show-result win headline. The glow
   uses the breakthrough golden tokens so it reads as a rare, premium
   moment rather than a generic success tint. Two pulse cycles then
   it settles. */
@keyframes win-celebration {
  0% {
    transform: scale(1);
    text-shadow: 0 0 0 oklch(var(--breakthrough-glow) / 0);
  }
  25% {
    transform: scale(1.06);
    text-shadow: 0 0 18px oklch(var(--breakthrough-glow) / 0.7);
  }
  50% {
    transform: scale(1.02);
    text-shadow: 0 0 10px oklch(var(--breakthrough-glow) / 0.45);
  }
  75% {
    transform: scale(1.04);
    text-shadow: 0 0 14px oklch(var(--breakthrough-glow) / 0.55);
  }
  100% {
    transform: scale(1);
    text-shadow: 0 0 0 oklch(var(--breakthrough-glow) / 0);
  }
}

/* Level-up flash — a quick two-step border/background pulse on the
   level-up indicator. Uses the primary amber so it reads as a
   positive milestone without competing with the breakthrough gold. */
@keyframes level-up-flash {
  0%,
  100% {
    background-color: oklch(var(--primary) / 0.1);
    border-color: oklch(var(--primary) / 0.4);
  }
  50% {
    background-color: oklch(var(--primary) / 0.28);
    border-color: oklch(var(--primary) / 0.7);
  }
}

/* Flame flicker — a subtle scale + opacity wobble evoking a real
   candle flame. Used on the streak-flame icon so the indicator
   feels alive without being distracting. 2.4s loop, gentle easing,
   small amplitude (0.94–1.06 scale, 0.82–1 opacity) so it reads
   as ambient warmth rather than a flashing alert. The glow
   (drop-shadow) pulses in counter-phase to the scale so the
   halo breathes opposite to the flame body — the same trick
   real fire-light plays on a wall. */
@keyframes flame-flicker {
  0% {
    transform: scale(1);
    opacity: 1;
    filter: drop-shadow(0 0 4px oklch(var(--flame-glow) / 0.35));
  }
  25% {
    transform: scale(1.04, 0.98);
    opacity: 0.92;
    filter: drop-shadow(0 0 7px oklch(var(--flame-glow) / 0.5));
  }
  50% {
    transform: scale(0.96, 1.04);
    opacity: 1;
    filter: drop-shadow(0 0 5px oklch(var(--flame-glow) / 0.4));
  }
  75% {
    transform: scale(1.06, 0.96);
    opacity: 0.86;
    filter: drop-shadow(0 0 9px oklch(var(--flame-glow) / 0.58));
  }
  100% {
    transform: scale(1);
    opacity: 1;
    filter: drop-shadow(0 0 4px oklch(var(--flame-glow) / 0.35));
  }
}

/* Bar fill — width animation for stat/XP bars on the results
   screen. The element's width is set inline to the target %; this
   keyframe drives the perceived fill by animating a clip/scale
   wrapper. In practice the bars use the existing .stat-bar__fill /
   .xp-bar__fill width transition (0.4s/0.5s), and this utility is
   applied to the popup +X text so it pops in sync with the bar. */
@keyframes bar-fill {
  0% {
    opacity: 0;
    transform: translateY(6px) scale(0.85);
  }
  60% {
    opacity: 1;
    transform: translateY(-2px) scale(1.08);
  }
  100% {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}

/* Honor reduced-motion: disable non-essential entrance/loop motion.
   Skeletons fall back to a static muted fill (no shimmer, no pulse)
   so they remain legible and stable without animation. */
@media (prefers-reduced-motion: reduce) {
  .animate-fade-in,
  .animate-slide-up,
  .animate-pulse-ring,
  .animate-skeleton-pulse,
  .animate-skeleton-shimmer {
    animation: none;
  }

  /* Static muted fill replaces the shimmer gradient so the skeleton
      still reads as a placeholder surface, just without motion. */
  .animate-skeleton-shimmer {
    background-image: none;
    background-color: oklch(var(--skeleton-base));
  }

  /* Bloodline count badge — drop the fade-in and the shimmer sweep
      so the badge is fully static under reduced-motion. The badge
      still renders (loading pill becomes a static muted fill, ready
      badge shows the count immediately). */
  .bloodline-count-badge {
    animation: none;
  }
  .bloodline-count-badge-shimmer {
    animation: none;
    background-image: none;
    background-color: oklch(var(--skeleton-base));
  }

  .stagger-1,
  .stagger-2,
  .stagger-3,
  .stagger-4,
  .stagger-5,
  .stagger-6 {
    animation-delay: 0s;
  }

  /* Bloodlines showcase — drop hover lift and tab transitions so the
     cards and nav remain fully static under reduced-motion. */
  .bloodline-card {
    transition: none;
    transform: none;
  }

  .bloodline-tab {
    transition: none;
  }

  /* Bloodline carousel — snap-scroll is a scroll behavior, not an
     animation, so it stays functional under reduced-motion. Only
     the chevron hover/focus transitions are dropped so controls
     do not animate. The hidden-scrollbar + snap alignment remain. */
  .bloodline-carousel-btn {
    transition: none;
  }
  .bloodline-carousel-btn:hover {
    box-shadow: none;
  }

  /* Pass 6 — Dashboard, Marketplace & My Dogs. Drop hover lifts on
     listing/kennel cards and the conditioning/milestone bar fill
     transitions so the surfaces remain fully static under
     reduced-motion. Quick-action active-scale is also removed. */
  .listing-card {
    transition: none;
    transform: none;
  }
  .listing-card:hover {
    transform: none;
  }

  .kennel-card {
    transition: none;
    transform: none;
  }
  .kennel-card:hover {
    transform: none;
  }

  .show-dog-card {
    transition: none;
    transform: none;
  }
  .show-dog-card:hover {
    transform: none;
  }
  .show-dog-card__header {
    transition: none;
  }

  .quick-action-btn {
    transition: none;
  }
  .quick-action-btn:active {
    transform: none;
  }

  .conditioning-bar__fill,
  .milestone-bar__fill {
    transition: none;
  }

  /* Pass 7 — Show System v1 gameplay bars. Drop the fill
      transitions on XP, energy, and stat bars so the meters
      remain fully static under reduced-motion. The level-up
      flash and win-celebration animations are also disabled
      (declared via the .animate-* utilities below). */
  .xp-bar__fill,
  .energy-bar__fill,
  .stat-bar__fill {
    transition: none;
  }

  .training-activity-btn {
    transition: none;
  }
  .training-activity-btn:active {
    transform: none;
  }

  .intensity-toggle__btn {
    transition: none;
  }

  .animate-level-up-flash,
  .animate-win-celebration,
  .animate-bar-fill {
    animation: none;
  }

  /* Show result modal — phase reveal is a transition, not an
      animation, so we neutralize it here. Phases render at their
      final opacity/transform immediately under reduced-motion. */
  .show-result-modal__phase {
    opacity: 1;
    transform: none;
    transition: none;
  }

  /* Training result modal — drop the stat-bar fill transition,
      the +X stat-gain popup entrance, the breakthrough callout
      celebration, and the level-up flash so the results screen
      remains fully static under reduced-motion. The values still
      update instantly (the bars render at their final width). */
  .training-result-modal__stat-bar .stat-bar__fill {
    transition: none;
  }
  .training-result-modal__stat-gain-popup {
    animation: none;
  }
  .training-result-modal__breakthrough-callout {
    animation: none;
  }
  .training-result-modal__level-up {
    animation: none;
  }
  .training-result-modal--breakthrough {
    box-shadow: 0 8px 32px oklch(0 0 0 / 0.24);
  }
  .training-result-modal--breakthrough .training-result-modal__headline {
    text-shadow: none;
  }

  /* LQIP blur-up — disable the blur filter and the crossfade
     transition so the placeholder-to-image swap is a static
     opacity change only. No blur, no transform, no transition. */
  .blur-up-placeholder {
    filter: none;
    transform: none;
    transition: none;
    opacity: 0.85;
  }
  .blur-up-loaded {
    transition: none;
    opacity: 0;
  }

  /* Pass 9 — Daily Streak / Flame System. Disable the flame
      flicker loop on the streak-flame icon and the current
      track node so there is no ambient motion. The increment
      pulse (win-celebration) is already disabled above via
      .animate-win-celebration. Broken-streak state already
      has animation:none in its base rule, but we reinforce it
      here so the ember icon never moves. The flame glow shadow
      on the current track node is kept (it's static, not
      motion) so the "today" node still reads as active. */
  .streak-flame__icon,
  .streak-track__circle--current .streak-track__circle-icon,
  .streak-broken-message__icon {
    animation: none;
    filter: drop-shadow(0 0 4px oklch(var(--flame-glow) / 0.3));
  }
  .streak-flame--increment {
    animation: none;
  }

  /* Streak History — the active (ongoing) cycle's flame icon
     uses the flame-flicker loop in its base rule. Disable it
     here so the lit icon stays still under reduced-motion. The
     flame color is kept (it's static, not motion) so the active
     cycle still reads as ongoing. */
  .streak-history-card__icon--active svg {
    animation: none;
  }

  /* Grace toast — drop the border/bg transitions so the toast
      remains fully static under reduced-motion. The accent dot's
      glow shadow is kept (it's static, not motion) so the toast
      still reads as a grace message. */
  .grace-toast {
    transition: none;
  }

  /* Grace indicator — no animation by default, but reinforce
      transition:none so the inline pill stays fully static under
      reduced-motion. */
  .grace-indicator {
    transition: none;
  }
}
.selection\:bg-primary *::-moz-selection {
  --tw-bg-opacity: 1;
  background-color: oklch(var(--primary) / var(--tw-bg-opacity, 1));
}
.selection\:bg-primary *::selection {
  --tw-bg-opacity: 1;
  background-color: oklch(var(--primary) / var(--tw-bg-opacity, 1));
}
.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 {
  --tw-bg-opacity: 1;
  background-color: oklch(var(--primary) / var(--tw-bg-opacity, 1));
}
.selection\:bg-primary::selection {
  --tw-bg-opacity: 1;
  background-color: oklch(var(--primary) / var(--tw-bg-opacity, 1));
}
.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 {
  --tw-text-opacity: 1;
  color: oklch(var(--muted-foreground) / var(--tw-text-opacity, 1));
}
.placeholder\:text-muted-foreground::placeholder {
  --tw-text-opacity: 1;
  color: oklch(var(--muted-foreground) / var(--tw-text-opacity, 1));
}
.after\:absolute::after {
  content: var(--tw-content);
  position: absolute;
}
.after\:inset-y-0::after {
  content: var(--tw-content);
  top: 0px;
  bottom: 0px;
}
.after\:left-1\/2::after {
  content: var(--tw-content);
  left: 50%;
}
.after\:w-1::after {
  content: var(--tw-content);
  width: 0.25rem;
}
.after\:-translate-x-1\/2::after {
  content: var(--tw-content);
  --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));
}
.first\:rounded-l-md:first-child {
  border-top-left-radius: calc(var(--radius) - 2px);
  border-bottom-left-radius: calc(var(--radius) - 2px);
}
.first\:border-l:first-child {
  border-left-width: 1px;
}
.last\:rounded-r-md:last-child {
  border-top-right-radius: calc(var(--radius) - 2px);
  border-bottom-right-radius: calc(var(--radius) - 2px);
}
.last\:border-b-0:last-child {
  border-bottom-width: 0px;
}
.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\:border-primary:hover {
  --tw-border-opacity: 1;
  border-color: oklch(var(--primary) / var(--tw-border-opacity, 1));
}
.hover\:border-primary\/30:hover {
  border-color: oklch(var(--primary) / 0.3);
}
.hover\:border-primary\/40:hover {
  border-color: oklch(var(--primary) / 0.4);
}
.hover\:bg-accent:hover {
  --tw-bg-opacity: 1;
  background-color: oklch(var(--accent) / var(--tw-bg-opacity, 1));
}
.hover\:bg-accent\/10:hover {
  background-color: oklch(var(--accent) / 0.1);
}
.hover\:bg-accent\/20:hover {
  background-color: oklch(var(--accent) / 0.2);
}
.hover\:bg-destructive\/90:hover {
  background-color: oklch(var(--destructive) / 0.9);
}
.hover\:bg-muted:hover {
  --tw-bg-opacity: 1;
  background-color: oklch(var(--muted) / var(--tw-bg-opacity, 1));
}
.hover\:bg-muted\/40:hover {
  background-color: oklch(var(--muted) / 0.4);
}
.hover\:bg-muted\/50:hover {
  background-color: oklch(var(--muted) / 0.5);
}
.hover\:bg-muted\/60:hover {
  background-color: oklch(var(--muted) / 0.6);
}
.hover\:bg-primary\/20:hover {
  background-color: oklch(var(--primary) / 0.2);
}
.hover\:bg-primary\/90:hover {
  background-color: oklch(var(--primary) / 0.9);
}
.hover\:bg-secondary:hover {
  --tw-bg-opacity: 1;
  background-color: oklch(var(--secondary) / var(--tw-bg-opacity, 1));
}
.hover\:bg-secondary\/50:hover {
  background-color: oklch(var(--secondary) / 0.5);
}
.hover\:bg-secondary\/80:hover {
  background-color: oklch(var(--secondary) / 0.8);
}
.hover\:text-accent:hover {
  --tw-text-opacity: 1;
  color: oklch(var(--accent) / var(--tw-text-opacity, 1));
}
.hover\:text-accent-foreground:hover {
  color: oklch(var(--accent-foreground));
}
.hover\:text-foreground:hover {
  color: oklch(var(--foreground));
}
.hover\:text-muted-foreground:hover {
  --tw-text-opacity: 1;
  color: oklch(var(--muted-foreground) / var(--tw-text-opacity, 1));
}
.hover\:text-primary\/80:hover {
  color: oklch(var(--primary) / 0.8);
}
.hover\:underline:hover {
  text-decoration-line: underline;
}
.hover\:opacity-100:hover {
  opacity: 1;
}
.hover\:ring-4:hover {
  --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(4px + 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\:z-10:focus {
  z-index: 10;
}
.focus\:bg-accent:focus {
  --tw-bg-opacity: 1;
  background-color: oklch(var(--accent) / var(--tw-bg-opacity, 1));
}
.focus\:bg-primary:focus {
  --tw-bg-opacity: 1;
  background-color: oklch(var(--primary) / var(--tw-bg-opacity, 1));
}
.focus\:text-accent-foreground:focus {
  color: oklch(var(--accent-foreground));
}
.focus\:text-primary-foreground:focus {
  color: oklch(var(--primary-foreground));
}
.focus\:outline-none:focus {
  outline: 2px solid transparent;
  outline-offset: 2px;
}
.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-opacity: 1;
  --tw-ring-color: oklch(var(--ring) / var(--tw-ring-opacity, 1));
}
.focus\:ring-offset-2:focus {
  --tw-ring-offset-width: 2px;
}
.focus-visible\:z-10:focus-visible {
  z-index: 10;
}
.focus-visible\:border-destructive:focus-visible {
  --tw-border-opacity: 1;
  border-color: oklch(var(--destructive) / var(--tw-border-opacity, 1));
}
.focus-visible\:border-ring:focus-visible {
  --tw-border-opacity: 1;
  border-color: oklch(var(--ring) / var(--tw-border-opacity, 1));
}
.focus-visible\:bg-secondary\/50:focus-visible {
  background-color: oklch(var(--secondary) / 0.5);
}
.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-ring:focus-visible {
  outline-color: oklch(var(--ring) / 1);
}
.focus-visible\:ring-1: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(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);
}
.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-4: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(4px + 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-inset:focus-visible {
  --tw-ring-inset: inset;
}
.focus-visible\:ring-destructive\/20:focus-visible {
  --tw-ring-color: oklch(var(--destructive) / 0.2);
}
.focus-visible\:ring-destructive\/30:focus-visible {
  --tw-ring-color: oklch(var(--destructive) / 0.3);
}
.focus-visible\:ring-primary:focus-visible {
  --tw-ring-opacity: 1;
  --tw-ring-color: oklch(var(--primary) / var(--tw-ring-opacity, 1));
}
.focus-visible\:ring-ring:focus-visible {
  --tw-ring-opacity: 1;
  --tw-ring-color: oklch(var(--ring) / var(--tw-ring-opacity, 1));
}
.focus-visible\:ring-ring\/50:focus-visible {
  --tw-ring-color: oklch(var(--ring) / 0.5);
}
.focus-visible\:ring-offset-1:focus-visible {
  --tw-ring-offset-width: 1px;
}
.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));
}
.disabled\:pointer-events-none:disabled {
  pointer-events: none;
}
.disabled\:cursor-not-allowed:disabled {
  cursor: not-allowed;
}
.disabled\:cursor-wait:disabled {
  cursor: wait;
}
.disabled\:opacity-50:disabled {
  opacity: 0.5;
}
.disabled\:opacity-60:disabled {
  opacity: 0.6;
}
.disabled\:hover\:bg-transparent:hover:disabled {
  background-color: transparent;
}
.disabled\:hover\:text-foreground:hover:disabled {
  color: oklch(var(--foreground));
}
.group:hover .group-hover\: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));
}
.group:hover .group-hover\:scale-\[1\.03\] {
  --tw-scale-x: 1.03;
  --tw-scale-y: 1.03;
  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));
}
.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;
}
.aria-disabled\:opacity-50[aria-disabled="true"] {
  opacity: 0.5;
}
.aria-selected\:text-muted-foreground[aria-selected="true"] {
  --tw-text-opacity: 1;
  color: oklch(var(--muted-foreground) / var(--tw-text-opacity, 1));
}
.data-\[disabled\=true\]\:pointer-events-none[data-disabled="true"] {
  pointer-events: none;
}
.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-\[active\=true\]\:z-10[data-active="true"] {
  z-index: 10;
}
.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-1\.5[data-orientation="horizontal"] {
  height: 0.375rem;
}
.data-\[orientation\=horizontal\]\:h-full[data-orientation="horizontal"] {
  height: 100%;
}
.data-\[orientation\=horizontal\]\:h-px[data-orientation="horizontal"] {
  height: 1px;
}
.data-\[orientation\=vertical\]\:h-full[data-orientation="vertical"] {
  height: 100%;
}
.data-\[panel-group-direction\=vertical\]\:h-px[data-panel-group-direction="vertical"] {
  height: 1px;
}
.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\=vertical\]\:min-h-44[data-orientation="vertical"] {
  min-height: 11rem;
}
.data-\[orientation\=horizontal\]\:w-full[data-orientation="horizontal"] {
  width: 100%;
}
.data-\[orientation\=vertical\]\:w-1\.5[data-orientation="vertical"] {
  width: 0.375rem;
}
.data-\[orientation\=vertical\]\:w-auto[data-orientation="vertical"] {
  width: auto;
}
.data-\[orientation\=vertical\]\:w-full[data-orientation="vertical"] {
  width: 100%;
}
.data-\[orientation\=vertical\]\:w-px[data-orientation="vertical"] {
  width: 1px;
}
.data-\[panel-group-direction\=vertical\]\:w-full[data-panel-group-direction="vertical"] {
  width: 100%;
}
.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));
}
@keyframes accordion-up {

  from {
    height: var(--radix-accordion-content-height);
  }

  to {
    height: 0;
  }
}
.data-\[state\=closed\]\:animate-accordion-up[data-state="closed"] {
  animation: accordion-up 0.2s ease-out;
}
@keyframes accordion-down {

  from {
    height: 0;
  }

  to {
    height: var(--radix-accordion-content-height);
  }
}
.data-\[state\=open\]\:animate-accordion-down[data-state="open"] {
  animation: accordion-down 0.2s ease-out;
}
.data-\[orientation\=vertical\]\:flex-col[data-orientation="vertical"] {
  flex-direction: column;
}
.data-\[panel-group-direction\=vertical\]\:flex-col[data-panel-group-direction="vertical"] {
  flex-direction: column;
}
.data-\[range-end\=true\]\:rounded-md[data-range-end="true"] {
  border-radius: calc(var(--radius) - 2px);
}
.data-\[range-middle\=true\]\:rounded-none[data-range-middle="true"] {
  border-radius: 0px;
}
.data-\[range-start\=true\]\:rounded-md[data-range-start="true"] {
  border-radius: calc(var(--radius) - 2px);
}
.data-\[selected\=true\]\:rounded-none[data-selected="true"] {
  border-radius: 0px;
}
.data-\[range-end\=true\]\:rounded-r-md[data-range-end="true"] {
  border-top-right-radius: calc(var(--radius) - 2px);
  border-bottom-right-radius: calc(var(--radius) - 2px);
}
.data-\[range-start\=true\]\:rounded-l-md[data-range-start="true"] {
  border-top-left-radius: calc(var(--radius) - 2px);
  border-bottom-left-radius: calc(var(--radius) - 2px);
}
.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-\[variant\=outline\]\:border-l-0[data-variant="outline"] {
  border-left-width: 0px;
}
.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-\[active\=true\]\:border-ring[data-active="true"] {
  --tw-border-opacity: 1;
  border-color: oklch(var(--ring) / var(--tw-border-opacity, 1));
}
.data-\[state\=checked\]\:border-primary[data-state="checked"] {
  --tw-border-opacity: 1;
  border-color: oklch(var(--primary) / var(--tw-border-opacity, 1));
}
.data-\[active\=true\]\:bg-accent\/50[data-active="true"] {
  background-color: oklch(var(--accent) / 0.5);
}
.data-\[range-end\=true\]\:bg-primary[data-range-end="true"] {
  --tw-bg-opacity: 1;
  background-color: oklch(var(--primary) / var(--tw-bg-opacity, 1));
}
.data-\[range-middle\=true\]\:bg-accent[data-range-middle="true"] {
  --tw-bg-opacity: 1;
  background-color: oklch(var(--accent) / var(--tw-bg-opacity, 1));
}
.data-\[range-start\=true\]\:bg-primary[data-range-start="true"] {
  --tw-bg-opacity: 1;
  background-color: oklch(var(--primary) / var(--tw-bg-opacity, 1));
}
.data-\[selected-single\=true\]\:bg-primary[data-selected-single="true"] {
  --tw-bg-opacity: 1;
  background-color: oklch(var(--primary) / var(--tw-bg-opacity, 1));
}
.data-\[selected\=true\]\:bg-accent[data-selected="true"] {
  --tw-bg-opacity: 1;
  background-color: oklch(var(--accent) / var(--tw-bg-opacity, 1));
}
.data-\[state\=active\]\:bg-background[data-state="active"] {
  background-color: oklch(var(--background));
}
.data-\[state\=checked\]\:bg-primary[data-state="checked"] {
  --tw-bg-opacity: 1;
  background-color: oklch(var(--primary) / var(--tw-bg-opacity, 1));
}
.data-\[state\=on\]\:bg-accent[data-state="on"] {
  --tw-bg-opacity: 1;
  background-color: oklch(var(--accent) / var(--tw-bg-opacity, 1));
}
.data-\[state\=open\]\:bg-accent[data-state="open"] {
  --tw-bg-opacity: 1;
  background-color: oklch(var(--accent) / var(--tw-bg-opacity, 1));
}
.data-\[state\=open\]\:bg-accent\/50[data-state="open"] {
  background-color: oklch(var(--accent) / 0.5);
}
.data-\[state\=open\]\:bg-secondary[data-state="open"] {
  --tw-bg-opacity: 1;
  background-color: oklch(var(--secondary) / var(--tw-bg-opacity, 1));
}
.data-\[state\=selected\]\:bg-muted[data-state="selected"] {
  --tw-bg-opacity: 1;
  background-color: oklch(var(--muted) / var(--tw-bg-opacity, 1));
}
.data-\[state\=unchecked\]\:bg-input[data-state="unchecked"] {
  background-color: oklch(var(--input));
}
.data-\[inset\]\:pl-8[data-inset] {
  padding-left: 2rem;
}
.data-\[active\=true\]\:text-accent-foreground[data-active="true"] {
  color: oklch(var(--accent-foreground));
}
.data-\[error\=true\]\:text-destructive[data-error="true"] {
  --tw-text-opacity: 1;
  color: oklch(var(--destructive) / var(--tw-text-opacity, 1));
}
.data-\[placeholder\]\:text-muted-foreground[data-placeholder] {
  --tw-text-opacity: 1;
  color: oklch(var(--muted-foreground) / var(--tw-text-opacity, 1));
}
.data-\[range-end\=true\]\:text-primary-foreground[data-range-end="true"] {
  color: oklch(var(--primary-foreground));
}
.data-\[range-middle\=true\]\:text-accent-foreground[data-range-middle="true"] {
  color: oklch(var(--accent-foreground));
}
.data-\[range-start\=true\]\:text-primary-foreground[data-range-start="true"] {
  color: oklch(var(--primary-foreground));
}
.data-\[selected-single\=true\]\:text-primary-foreground[data-selected-single="true"] {
  color: oklch(var(--primary-foreground));
}
.data-\[selected\=true\]\:text-accent-foreground[data-selected="true"] {
  color: oklch(var(--accent-foreground));
}
.data-\[state\=checked\]\:text-primary-foreground[data-state="checked"] {
  color: oklch(var(--primary-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"] {
  --tw-text-opacity: 1;
  color: oklch(var(--muted-foreground) / var(--tw-text-opacity, 1));
}
.data-\[variant\=destructive\]\:text-destructive[data-variant="destructive"] {
  --tw-text-opacity: 1;
  color: oklch(var(--destructive) / var(--tw-text-opacity, 1));
}
.data-\[disabled\=true\]\:opacity-50[data-disabled="true"] {
  opacity: 0.5;
}
.data-\[disabled\]\:opacity-50[data-disabled] {
  opacity: 0.5;
}
.data-\[state\=active\]\:shadow-sm[data-state="active"] {
  --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);
}
.data-\[variant\=outline\]\:shadow-xs[data-variant="outline"] {
  --tw-shadow: 0 1px 2px 0 rgba(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);
}
.data-\[active\=true\]\:ring-\[3px\][data-active="true"] {
  --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);
}
.data-\[active\=true\]\:ring-ring\/50[data-active="true"] {
  --tw-ring-color: oklch(var(--ring) / 0.5);
}
.data-\[state\=closed\]\:duration-300[data-state="closed"] {
  transition-duration: 300ms;
}
.data-\[state\=open\]\:duration-500[data-state="open"] {
  transition-duration: 500ms;
}
.data-\[motion\^\=from-\]\:animate-in[data-motion^="from-"] {
  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\=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\=visible\]\:animate-in[data-state="visible"] {
  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-\[motion\^\=to-\]\:animate-out[data-motion^="to-"] {
  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\]\: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\=hidden\]\:animate-out[data-state="hidden"] {
  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-\[motion\^\=from-\]\:fade-in[data-motion^="from-"] {
  --tw-enter-opacity: 0;
}
.data-\[motion\^\=to-\]\:fade-out[data-motion^="to-"] {
  --tw-exit-opacity: 0;
}
.data-\[state\=closed\]\:fade-out-0[data-state="closed"] {
  --tw-exit-opacity: 0;
}
.data-\[state\=hidden\]\:fade-out[data-state="hidden"] {
  --tw-exit-opacity: 0;
}
.data-\[state\=open\]\:fade-in-0[data-state="open"] {
  --tw-enter-opacity: 0;
}
.data-\[state\=visible\]\:fade-in[data-state="visible"] {
  --tw-enter-opacity: 0;
}
.data-\[state\=closed\]\:zoom-out-95[data-state="closed"] {
  --tw-exit-scale: .95;
}
.data-\[state\=open\]\:zoom-in-90[data-state="open"] {
  --tw-enter-scale: .9;
}
.data-\[state\=open\]\:zoom-in-95[data-state="open"] {
  --tw-enter-scale: .95;
}
.data-\[motion\=from-end\]\:slide-in-from-right-52[data-motion="from-end"] {
  --tw-enter-translate-x: 13rem;
}
.data-\[motion\=from-start\]\:slide-in-from-left-52[data-motion="from-start"] {
  --tw-enter-translate-x: -13rem;
}
.data-\[motion\=to-end\]\:slide-out-to-right-52[data-motion="to-end"] {
  --tw-exit-translate-x: 13rem;
}
.data-\[motion\=to-start\]\:slide-out-to-left-52[data-motion="to-start"] {
  --tw-exit-translate-x: -13rem;
}
.data-\[side\=bottom\]\:slide-in-from-top-2[data-side="bottom"] {
  --tw-enter-translate-y: -0.5rem;
}
.data-\[side\=left\]\:slide-in-from-right-2[data-side="left"] {
  --tw-enter-translate-x: 0.5rem;
}
.data-\[side\=right\]\:slide-in-from-left-2[data-side="right"] {
  --tw-enter-translate-x: -0.5rem;
}
.data-\[side\=top\]\:slide-in-from-bottom-2[data-side="top"] {
  --tw-enter-translate-y: 0.5rem;
}
.data-\[state\=closed\]\:slide-out-to-bottom[data-state="closed"] {
  --tw-exit-translate-y: 100%;
}
.data-\[state\=closed\]\:slide-out-to-left[data-state="closed"] {
  --tw-exit-translate-x: -100%;
}
.data-\[state\=closed\]\:slide-out-to-right[data-state="closed"] {
  --tw-exit-translate-x: 100%;
}
.data-\[state\=closed\]\:slide-out-to-top[data-state="closed"] {
  --tw-exit-translate-y: -100%;
}
.data-\[state\=open\]\:slide-in-from-bottom[data-state="open"] {
  --tw-enter-translate-y: 100%;
}
.data-\[state\=open\]\:slide-in-from-left[data-state="open"] {
  --tw-enter-translate-x: -100%;
}
.data-\[state\=open\]\:slide-in-from-right[data-state="open"] {
  --tw-enter-translate-x: 100%;
}
.data-\[state\=open\]\:slide-in-from-top[data-state="open"] {
  --tw-enter-translate-y: -100%;
}
.data-\[state\=closed\]\:duration-300[data-state="closed"] {
  animation-duration: 300ms;
}
.data-\[state\=open\]\:duration-500[data-state="open"] {
  animation-duration: 500ms;
}
.\*\: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-\[slot\=alert-description\]\:text-destructive\/90[data-slot="alert-description"] > * {
  color: oklch(var(--destructive) / 0.9);
}
.data-\[panel-group-direction\=vertical\]\:after\:left-0[data-panel-group-direction="vertical"]::after {
  content: var(--tw-content);
  left: 0px;
}
.data-\[panel-group-direction\=vertical\]\:after\:h-1[data-panel-group-direction="vertical"]::after {
  content: var(--tw-content);
  height: 0.25rem;
}
.data-\[panel-group-direction\=vertical\]\:after\:w-full[data-panel-group-direction="vertical"]::after {
  content: var(--tw-content);
  width: 100%;
}
.data-\[panel-group-direction\=vertical\]\:after\:-translate-y-1\/2[data-panel-group-direction="vertical"]::after {
  content: var(--tw-content);
  --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));
}
.data-\[panel-group-direction\=vertical\]\:after\:translate-x-0[data-panel-group-direction="vertical"]::after {
  content: var(--tw-content);
  --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-\[variant\=outline\]\:first\:border-l:first-child[data-variant="outline"] {
  border-left-width: 1px;
}
.data-\[active\=true\]\:hover\:bg-accent:hover[data-active="true"] {
  --tw-bg-opacity: 1;
  background-color: oklch(var(--accent) / var(--tw-bg-opacity, 1));
}
.data-\[state\=open\]\:hover\:bg-accent:hover[data-state="open"] {
  --tw-bg-opacity: 1;
  background-color: oklch(var(--accent) / var(--tw-bg-opacity, 1));
}
.data-\[active\=true\]\:focus\:bg-accent:focus[data-active="true"] {
  --tw-bg-opacity: 1;
  background-color: oklch(var(--accent) / var(--tw-bg-opacity, 1));
}
.data-\[state\=open\]\:focus\:bg-accent:focus[data-state="open"] {
  --tw-bg-opacity: 1;
  background-color: oklch(var(--accent) / var(--tw-bg-opacity, 1));
}
.data-\[variant\=destructive\]\:focus\:bg-destructive\/10:focus[data-variant="destructive"] {
  background-color: oklch(var(--destructive) / 0.1);
}
.data-\[variant\=destructive\]\:focus\:text-destructive:focus[data-variant="destructive"] {
  --tw-text-opacity: 1;
  color: oklch(var(--destructive) / var(--tw-text-opacity, 1));
}
.group[data-disabled="true"] .group-data-\[disabled\=true\]\:pointer-events-none {
  pointer-events: none;
}
.group\/day[data-focused="true"] .group-data-\[focused\=true\]\/day\:relative {
  position: relative;
}
.group\/navigation-menu[data-viewport="false"] .group-data-\[viewport\=false\]\/navigation-menu\:top-full {
  top: 100%;
}
.group\/day[data-focused="true"] .group-data-\[focused\=true\]\/day\:z-10 {
  z-index: 10;
}
.group\/navigation-menu[data-viewport="false"] .group-data-\[viewport\=false\]\/navigation-menu\:mt-1\.5 {
  margin-top: 0.375rem;
}
.group\/drawer-content[data-vaul-drawer-direction="bottom"] .group-data-\[vaul-drawer-direction\=bottom\]\/drawer-content\:block {
  display: block;
}
.group[data-state="open"] .group-data-\[state\=open\]\: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));
}
.group\/navigation-menu[data-viewport="false"] .group-data-\[viewport\=false\]\/navigation-menu\:overflow-hidden {
  overflow: hidden;
}
.group\/navigation-menu[data-viewport="false"] .group-data-\[viewport\=false\]\/navigation-menu\:rounded-md {
  border-radius: calc(var(--radius) - 2px);
}
.group\/navigation-menu[data-viewport="false"] .group-data-\[viewport\=false\]\/navigation-menu\:border {
  border-width: 1px;
}
.group\/day[data-focused="true"] .group-data-\[focused\=true\]\/day\:border-ring {
  --tw-border-opacity: 1;
  border-color: oklch(var(--ring) / var(--tw-border-opacity, 1));
}
.group\/navigation-menu[data-viewport="false"] .group-data-\[viewport\=false\]\/navigation-menu\:bg-popover {
  background-color: oklch(var(--popover));
}
.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\/navigation-menu[data-viewport="false"] .group-data-\[viewport\=false\]\/navigation-menu\:text-popover-foreground {
  color: oklch(var(--popover-foreground));
}
.group[data-disabled="true"] .group-data-\[disabled\=true\]\:opacity-50 {
  opacity: 0.5;
}
.group\/navigation-menu[data-viewport="false"] .group-data-\[viewport\=false\]\/navigation-menu\: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);
}
.group\/day[data-focused="true"] .group-data-\[focused\=true\]\/day\:ring-\[3px\] {
  --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);
}
.group\/day[data-focused="true"] .group-data-\[focused\=true\]\/day\:ring-ring\/50 {
  --tw-ring-color: oklch(var(--ring) / 0.5);
}
.group\/navigation-menu[data-viewport="false"] .group-data-\[viewport\=false\]\/navigation-menu\:duration-200 {
  transition-duration: 200ms;
  animation-duration: 200ms;
}
.group\/navigation-menu[data-viewport="false"] .group-data-\[viewport\=false\]\/navigation-menu\: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;
}
.group\/navigation-menu[data-viewport="false"] .group-data-\[viewport\=false\]\/navigation-menu\: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;
}
.group\/navigation-menu[data-viewport="false"] .group-data-\[viewport\=false\]\/navigation-menu\:data-\[state\=closed\]\:fade-out-0[data-state="closed"] {
  --tw-exit-opacity: 0;
}
.group\/navigation-menu[data-viewport="false"] .group-data-\[viewport\=false\]\/navigation-menu\:data-\[state\=open\]\:fade-in-0[data-state="open"] {
  --tw-enter-opacity: 0;
}
.group\/navigation-menu[data-viewport="false"] .group-data-\[viewport\=false\]\/navigation-menu\:data-\[state\=closed\]\:zoom-out-95[data-state="closed"] {
  --tw-exit-scale: .95;
}
.group\/navigation-menu[data-viewport="false"] .group-data-\[viewport\=false\]\/navigation-menu\:data-\[state\=open\]\:zoom-in-95[data-state="open"] {
  --tw-enter-scale: .95;
}
@media (prefers-reduced-motion: no-preference) {

  .motion-safe\:transition-\[color\2c box-shadow\] {
    transition-property: color,box-shadow;
    transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
    transition-duration: 150ms;
  }

  .motion-safe\: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;
  }

  .motion-safe\:transition-transform {
    transition-property: transform;
    transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
    transition-duration: 150ms;
  }
}
@media (prefers-reduced-motion: reduce) {

  .motion-reduce\:animate-none {
    animation: none;
  }

  .motion-reduce\:transition-none {
    transition-property: none;
  }
}
.dark\:border-input:is(.dark *) {
  border-color: oklch(var(--input));
}
.dark\:bg-destructive\/60:is(.dark *) {
  background-color: oklch(var(--destructive) / 0.6);
}
.dark\:text-muted-foreground:is(.dark *) {
  --tw-text-opacity: 1;
  color: oklch(var(--muted-foreground) / var(--tw-text-opacity, 1));
}
.dark\:hover\:bg-accent\/50:hover:is(.dark *) {
  background-color: oklch(var(--accent) / 0.5);
}
.dark\:hover\:text-accent-foreground:hover:is(.dark *) {
  color: oklch(var(--accent-foreground));
}
.dark\:focus-visible\:ring-destructive\/40:focus-visible:is(.dark *) {
  --tw-ring-color: oklch(var(--destructive) / 0.4);
}
.dark\:data-\[state\=active\]\:border-input[data-state="active"]:is(.dark *) {
  border-color: oklch(var(--input));
}
.dark\:data-\[state\=checked\]\:bg-primary[data-state="checked"]:is(.dark *) {
  --tw-bg-opacity: 1;
  background-color: oklch(var(--primary) / var(--tw-bg-opacity, 1));
}
.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));
}
.dark\:data-\[state\=active\]\:text-foreground[data-state="active"]:is(.dark *) {
  color: oklch(var(--foreground));
}
.dark\:data-\[variant\=destructive\]\:focus\:bg-destructive\/20:focus[data-variant="destructive"]:is(.dark *) {
  background-color: oklch(var(--destructive) / 0.2);
}
@media (min-width: 640px) {

  .sm\:mx-2 {
    margin-left: 0.5rem;
    margin-right: 0.5rem;
  }

  .sm\:mb-10 {
    margin-bottom: 2.5rem;
  }

  .sm\:mb-8 {
    margin-bottom: 2rem;
  }

  .sm\:block {
    display: block;
  }

  .sm\:inline {
    display: inline;
  }

  .sm\:flex {
    display: flex;
  }

  .sm\:inline-flex {
    display: inline-flex;
  }

  .sm\:hidden {
    display: none;
  }

  .sm\:aspect-\[4\/3\] {
    aspect-ratio: 4/3;
  }

  .sm\:size-16 {
    width: 4rem;
    height: 4rem;
  }

  .sm\:h-9 {
    height: 2.25rem;
  }

  .sm\:w-40 {
    width: 10rem;
  }

  .sm\:w-56 {
    width: 14rem;
  }

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

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

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

  .sm\:flex-none {
    flex: none;
  }

  .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\:flex-row {
    flex-direction: row;
  }

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

  .sm\:items-end {
    align-items: flex-end;
  }

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

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

  .sm\:justify-between {
    justify-content: space-between;
  }

  .sm\:gap-2\.5 {
    gap: 0.625rem;
  }

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

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

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

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

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

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

  .sm\:px-8 {
    padding-left: 2rem;
    padding-right: 2rem;
  }

  .sm\:py-10 {
    padding-top: 2.5rem;
    padding-bottom: 2.5rem;
  }

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

  .sm\:pl-2\.5 {
    padding-left: 0.625rem;
  }

  .sm\:pr-2\.5 {
    padding-right: 0.625rem;
  }

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

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

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

  .sm\:text-4xl {
    font-size: 2.25rem;
    line-height: 2.5rem;
  }

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

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

  .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\:absolute {
    position: absolute;
  }

  .md\:col-span-1 {
    grid-column: span 1 / span 1;
  }

  .md\:col-span-2 {
    grid-column: span 2 / span 2;
  }

  .md\:col-span-3 {
    grid-column: span 3 / span 3;
  }

  .md\:col-span-4 {
    grid-column: span 4 / span 4;
  }

  .md\:block {
    display: block;
  }

  .md\:flex {
    display: flex;
  }

  .md\:grid {
    display: grid;
  }

  .md\:hidden {
    display: none;
  }

  .md\:max-h-\[300px\] {
    max-height: 300px;
  }

  .md\:max-h-\[85vh\] {
    max-height: 85vh;
  }

  .md\:w-32 {
    width: 8rem;
  }

  .md\:w-\[var\(--radix-navigation-menu-viewport-width\)\] {
    width: var(--radix-navigation-menu-viewport-width);
  }

  .md\:w-auto {
    width: auto;
  }

  .md\:max-w-\[600px\] {
    max-width: 600px;
  }

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

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

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

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

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

  .md\:text-sm {
    font-size: 0.875rem;
    line-height: 1.25rem;
  }
}
@media (min-width: 1024px) {

  .lg\:flex {
    display: flex;
  }

  .lg\:max-h-\[320px\] {
    max-height: 320px;
  }

  .lg\:max-h-\[80vh\] {
    max-height: 80vh;
  }

  .lg\:w-28 {
    width: 7rem;
  }

  .lg\:max-w-\[560px\] {
    max-width: 560px;
  }

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

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

  .lg\:px-8 {
    padding-left: 2rem;
    padding-right: 2rem;
  }
}
@media (min-width: 1280px) {

  .xl\:grid-cols-4 {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}
.\[\&\:first-child\[data-selected\=true\]_button\]\:rounded-l-md:first-child[data-selected=true] button {
  border-top-left-radius: calc(var(--radius) - 2px);
  border-bottom-left-radius: calc(var(--radius) - 2px);
}
.\[\&\:has\(\[role\=checkbox\]\)\]\:pr-0:has([role=checkbox]) {
  padding-right: 0px;
}
.\[\&\:last-child\[data-selected\=true\]_button\]\:rounded-r-md:last-child[data-selected=true] button {
  border-top-right-radius: calc(var(--radius) - 2px);
  border-bottom-right-radius: calc(var(--radius) - 2px);
}
.\[\&\>\[role\=checkbox\]\]\:translate-y-\[2px\]>[role=checkbox] {
  --tw-translate-y: 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));
}
.\[\&\>span\]\:text-xs>span {
  font-size: 0.75rem;
  line-height: 1rem;
}
.\[\&\>span\]\:opacity-70>span {
  opacity: 0.7;
}
.\[\&\>svg\]\:pointer-events-none>svg {
  pointer-events: none;
}
.\[\&\>svg\]\:size-3>svg {
  width: 0.75rem;
  height: 0.75rem;
}
.\[\&\>svg\]\:size-3\.5>svg {
  width: 0.875rem;
  height: 0.875rem;
}
.\[\&\>svg\]\:size-4>svg {
  width: 1rem;
  height: 1rem;
}
.\[\&\>svg\]\:h-2\.5>svg {
  height: 0.625rem;
}
.\[\&\>svg\]\:h-3>svg {
  height: 0.75rem;
}
.\[\&\>svg\]\:w-2\.5>svg {
  width: 0.625rem;
}
.\[\&\>svg\]\:w-3>svg {
  width: 0.75rem;
}
.\[\&\>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;
}
.\[\&\>svg\]\:text-muted-foreground>svg {
  --tw-text-opacity: 1;
  color: oklch(var(--muted-foreground) / var(--tw-text-opacity, 1));
}
.\[\&\>tr\]\:last\:border-b-0:last-child>tr {
  border-bottom-width: 0px;
}
.\[\&\[data-panel-group-direction\=vertical\]\>div\]\:rotate-90[data-panel-group-direction=vertical]>div {
  --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));
}
.\[\&\[data-state\=open\]\>svg\]\:rotate-180[data-state=open]>svg {
  --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));
}
.\[\&_\.recharts-cartesian-axis-tick_text\]\:fill-muted-foreground .recharts-cartesian-axis-tick text {
  fill: oklch(var(--muted-foreground) / 1);
}
.\[\&_\.recharts-curve\.recharts-tooltip-cursor\]\:stroke-border .recharts-curve.recharts-tooltip-cursor {
  stroke: oklch(var(--border));
}
.\[\&_\.recharts-dot\[stroke\=\'\#fff\'\]\]\:stroke-transparent .recharts-dot[stroke='#fff'] {
  stroke: transparent;
}
.\[\&_\.recharts-polar-grid_\[stroke\=\'\#ccc\'\]\]\:stroke-border .recharts-polar-grid [stroke='#ccc'] {
  stroke: oklch(var(--border));
}
.\[\&_\.recharts-radial-bar-background-sector\]\:fill-muted .recharts-radial-bar-background-sector {
  fill: oklch(var(--muted) / 1);
}
.\[\&_\.recharts-rectangle\.recharts-tooltip-cursor\]\:fill-muted .recharts-rectangle.recharts-tooltip-cursor {
  fill: oklch(var(--muted) / 1);
}
.\[\&_\.recharts-reference-line_\[stroke\=\'\#ccc\'\]\]\:stroke-border .recharts-reference-line [stroke='#ccc'] {
  stroke: oklch(var(--border));
}
.\[\&_\.recharts-sector\[stroke\=\'\#fff\'\]\]\:stroke-transparent .recharts-sector[stroke='#fff'] {
  stroke: transparent;
}
.\[\&_\[cmdk-group-heading\]\]\:px-2 [cmdk-group-heading] {
  padding-left: 0.5rem;
  padding-right: 0.5rem;
}
.\[\&_\[cmdk-group-heading\]\]\:py-1\.5 [cmdk-group-heading] {
  padding-top: 0.375rem;
  padding-bottom: 0.375rem;
}
.\[\&_\[cmdk-group-heading\]\]\:text-xs [cmdk-group-heading] {
  font-size: 0.75rem;
  line-height: 1rem;
}
.\[\&_\[cmdk-group-heading\]\]\:font-medium [cmdk-group-heading] {
  font-weight: 500;
}
.\[\&_\[cmdk-group-heading\]\]\:text-muted-foreground [cmdk-group-heading] {
  --tw-text-opacity: 1;
  color: oklch(var(--muted-foreground) / var(--tw-text-opacity, 1));
}
.\[\&_\[cmdk-group\]\:not\(\[hidden\]\)_\~\[cmdk-group\]\]\:pt-0 [cmdk-group]:not([hidden]) ~[cmdk-group] {
  padding-top: 0px;
}
.\[\&_\[cmdk-group\]\]\:px-2 [cmdk-group] {
  padding-left: 0.5rem;
  padding-right: 0.5rem;
}
.\[\&_\[cmdk-input-wrapper\]_svg\]\:h-5 [cmdk-input-wrapper] svg {
  height: 1.25rem;
}
.\[\&_\[cmdk-input-wrapper\]_svg\]\:w-5 [cmdk-input-wrapper] svg {
  width: 1.25rem;
}
.\[\&_\[cmdk-input\]\]\:h-12 [cmdk-input] {
  height: 3rem;
}
.\[\&_\[cmdk-item\]\]\:px-2 [cmdk-item] {
  padding-left: 0.5rem;
  padding-right: 0.5rem;
}
.\[\&_\[cmdk-item\]\]\:py-3 [cmdk-item] {
  padding-top: 0.75rem;
  padding-bottom: 0.75rem;
}
.\[\&_\[cmdk-item\]_svg\]\:h-5 [cmdk-item] svg {
  height: 1.25rem;
}
.\[\&_\[cmdk-item\]_svg\]\:w-5 [cmdk-item] svg {
  width: 1.25rem;
}
@keyframes pulse {

  50% {
    opacity: .5;
  }
}
.\[\&_\[data-slot\=\'progress-indicator\'\]\]\:animate-pulse [data-slot='progress-indicator'] {
  animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}
.\[\&_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\*\=\'text-\'\]\)\]\:text-muted-foreground svg:not([class*='text-']) {
  --tw-text-opacity: 1;
  color: oklch(var(--muted-foreground) / var(--tw-text-opacity, 1));
}
.\[\&_svg\]\:pointer-events-none svg {
  pointer-events: none;
}
.\[\&_svg\]\:shrink-0 svg {
  flex-shrink: 0;
}
.\[\&_tr\:last-child\]\:border-0 tr:last-child {
  border-width: 0px;
}
.\[\&_tr\]\:border-b tr {
  border-bottom-width: 1px;
}
[data-slot=card-content] .\[\[data-slot\=card-content\]_\&\]\:bg-transparent {
  background-color: transparent;
}
[data-slot=popover-content] .\[\[data-slot\=popover-content\]_\&\]\:bg-transparent {
  background-color: transparent;
}
a.\[a\&\]\:hover\:bg-accent:hover {
  --tw-bg-opacity: 1;
  background-color: oklch(var(--accent) / var(--tw-bg-opacity, 1));
}
a.\[a\&\]\:hover\:bg-destructive\/90:hover {
  background-color: oklch(var(--destructive) / 0.9);
}
a.\[a\&\]\:hover\:bg-primary\/90:hover {
  background-color: oklch(var(--primary) / 0.9);
}
a.\[a\&\]\:hover\:bg-secondary\/90:hover {
  background-color: oklch(var(--secondary) / 0.9);
}
a.\[a\&\]\:hover\:text-accent-foreground:hover {
  color: oklch(var(--accent-foreground));
}
