/* ⚠ The served bundle wwwroot/visualspool.css is GENERATED — DO NOT EDIT IT.
   It is concatenated from Styles/*.css (filename order) by the BundleCss
   MSBuild target on every build. Edit the partials in Styles/, not the bundle. */

/* VisualSpool Print Tech
   Modern dark tech aesthetic.
   Bold sans throughout, cards with subtle surface and hairline borders. */

/* Self-hosted Manrope. WOFF2 only — covers all modern browsers (no IE/old Edge).
   font-display:swap lets text render with the system-ui fallback immediately,
   then upgrades when the file lands. font-weight ranges so the browser can
   synthesize intermediate weights if needed. */
@font-face {
  font-family: "Manrope";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/fonts/manrope-v20-latin-regular.woff2") format("woff2");
}
@font-face {
  font-family: "Manrope";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("/fonts/manrope-v20-latin-500.woff2") format("woff2");
}
@font-face {
  font-family: "Manrope";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("/fonts/manrope-v20-latin-600.woff2") format("woff2");
}
@font-face {
  font-family: "Manrope";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("/fonts/manrope-v20-latin-700.woff2") format("woff2");
}
/* Display face for page titles only — a variable font, one file covers 500-700 */
@font-face {
  font-family: "Space Grotesk";
  font-style: normal;
  font-weight: 500 700;
  font-display: swap;
  src: url("/fonts/space-grotesk-v22-latin.woff2") format("woff2");
}
/* Data/mono face — was named in --vs-mono but never shipped; now self-hosted
   so counts and stats render the same on every machine */
@font-face {
  font-family: "Geist Mono";
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url("/fonts/geist-mono-v6-latin.woff2") format("woff2");
}

:root {
  --vs-sans: "Manrope", system-ui, sans-serif;
  --vs-mono: "Geist Mono", "JetBrains Mono", ui-monospace, monospace;
  --vs-display: "Space Grotesk", "Manrope", system-ui, sans-serif;

  /* BACKGROUNDS */
  --vs-bg-deep: #0f1117;
  --vs-bg: #131722;
  --vs-bg-tint: #181d29;

  /* SURFACES */
  --vs-surface: #1d2330;
  --vs-surface-2: #242b3a;
  --vs-surface-3: #2b3445;

  /* HAIRLINES / BORDERS */
  --vs-hair: rgba(255, 255, 255, 0.05);
  --vs-hair-2: rgba(255, 255, 255, 0.08);
  --vs-hair-3: rgba(255, 255, 255, 0.03);

  /* TYPOGRAPHY */
  --vs-text: #edf2fa;
  --vs-text-2: #b6c0d0;
  --vs-muted: #7f8ca3;
  --vs-faint: #76829b; /* lightest text tier that still passes 4.5:1 on the page bg */

  /* ACCENT */
  --vs-accent: #7898bf;
  --vs-blue: #6399de;   /* the D1 brand-logo blue; the wordmark "spool" matches logo.svg */
  --vs-accent-deep: #5f7ea3;
  --vs-accent-soft: rgba(var(--vs-tint), 0.12);
  --vs-accent-glow: rgba(var(--vs-tint), 0.15);
  --vs-secondary: #7cc8a0;

  /* Subtle "brand tint" + "dot" used as faint washes/borders/grids for dashboard
     bands, pegboard dots, weight pills and chart gridlines. Given as "r, g, b" so
     they're used via rgba(var(--vs-tint), <alpha>). Default to the brand blue; a
     theme overrides them to its own accent so all that chrome follows the theme. */
  --vs-tint: 120, 152, 191;
  --vs-dot: 40, 60, 90;

  /* Material-mix donut. Slice 1 = the theme's identity color (--vs-pie-base), which
     defaults to the accent but a theme can override when its accent isn't its "face"
     color — e.g. Sakura's accent is sage-green, but the theme reads as rose, so it
     sets --vs-pie-base to a deep rose below. The rest spin that SAME hue evenly
     around the wheel, keeping its saturation + lightness, so every slice shares one
     tone but a clearly different hue, 45deg apart — none close. Order = base, its
     complement (strongest contrast), then quarter- and eighth-turns, so the biggest
     pieces are always furthest apart. Adapts to any theme, light or dark. */
  --vs-pie-base: var(--vs-accent);
  --vs-pie-1: var(--vs-pie-base);
  --vs-pie-2: hsl(from var(--vs-pie-base) calc(h + 180) s l);
  --vs-pie-3: hsl(from var(--vs-pie-base) calc(h + 90) s l);
  --vs-pie-4: hsl(from var(--vs-pie-base) calc(h + 270) s l);
  --vs-pie-5: hsl(from var(--vs-pie-base) calc(h + 45) s l);
  --vs-pie-6: hsl(from var(--vs-pie-base) calc(h + 225) s l);
  --vs-pie-7: hsl(from var(--vs-pie-base) calc(h + 135) s l);
  --vs-pie-8: hsl(from var(--vs-pie-base) calc(h + 315) s l);

  /* STATUS COLORS */
  --vs-success: #7cc8a0;
  --vs-warning: #e1bb6b;
  --vs-danger: #d97d91;
  --vs-info: #8db7ff;

  /* Spool render flange (the disc the filament winds on). Dark blue-black "chrome"
     by default; light themes swap to a neutral gray so it isn't harsh on a light card. */
  --vs-spool-flange: #1c2535;
  --vs-spool-flange-stroke: #2c3a52;

  /* RADII */
  --vs-radius-sm: 8px;
  --vs-radius: 14px;
  --vs-radius-lg: 20px;
  --vs-gap: 18px;

  /* EASING */
  --vs-ease: cubic-bezier(0.22, 0.61, 0.36, 1);

  /* SHADOWS */
  --vs-shadow-sm:
    0 1px 0 rgba(255, 255, 255, 0.03) inset, 0 2px 6px rgba(0, 0, 0, 0.25);

  --vs-shadow:
    0 1px 0 rgba(255, 255, 255, 0.04) inset, 0 8px 24px rgba(0, 0, 0, 0.3);

  --vs-shadow-lg:
    0 1px 0 rgba(255, 255, 255, 0.05) inset, 0 20px 48px rgba(0, 0, 0, 0.38);

  /* === Semantic pill tints (status / condition / event / state badges) ===
     Tokenized so a future light theme can override them in one place. Values
     here reproduce the current dark look exactly. Two status variants:
     plain = solid (pills sitting on spool renders), -soft = translucent
     (pills on list/pegboard surfaces). */

  /* Status — solid (hero render) */
  --vs-st-storage-bg: #1a2a3a;   --vs-st-storage-fg: #7aaacc;
  --vs-st-printing-bg: #2a3a1a;  --vs-st-printing-fg: #7acc7a;
  --vs-st-drying-bg: #3a331a;    --vs-st-drying-fg: #d9c46a;
  --vs-st-printdry-bg: #2f3a1a;  --vs-st-printdry-fg: #b7cc6a;
  --vs-st-tostore-bg: #3a1f28;   --vs-st-tostore-fg: #d98a9e;

  /* Status — soft (list pills) */
  --vs-st-storage-bg-soft: rgba(18, 36, 58, 0.45);   --vs-st-storage-fg-soft: rgba(126, 168, 200, 0.95);
  --vs-st-printing-bg-soft: rgba(22, 44, 18, 0.45);  --vs-st-printing-fg-soft: rgba(118, 190, 118, 0.95);
  --vs-st-drying-bg-soft: rgba(50, 32, 14, 0.45);    --vs-st-drying-fg-soft: rgba(205, 172, 112, 0.95);
  --vs-st-printdry-bg-soft: rgba(38, 44, 14, 0.45);  --vs-st-printdry-fg-soft: rgba(185, 195, 115, 0.95);
  --vs-st-tostore-bg-soft: rgba(36, 18, 58, 0.45);   --vs-st-tostore-fg-soft: rgba(176, 136, 210, 0.95);

  /* Condition pills */
  --vs-cond-sealed-bg: rgba(18, 40, 58, 0.55);   --vs-cond-sealed-fg: #7fb2d9;
  --vs-cond-opened-bg: rgba(58, 40, 14, 0.55);   --vs-cond-opened-fg: #d9a86a;
  --vs-cond-almost-bg: rgba(90, 46, 16, 0.6);    --vs-cond-almost-fg: #f0b870;
  --vs-cond-depleted-bg: rgba(40, 40, 48, 0.55); --vs-cond-depleted-fg: #8a8aa0;

  /* History event chips */
  --vs-ev-created-bg: #2d5a3d;   --vs-ev-created-fg: #a8e6c0;
  --vs-ev-weight-bg: #2d4a6a;    --vs-ev-weight-fg: #a8c8e6;
  --vs-ev-status-bg: #4a2d6a;    --vs-ev-status-fg: #c8a8e6;
  --vs-ev-location-bg: #6a4a2d;  --vs-ev-location-fg: #e6c8a8;
  --vs-ev-depleted-bg: #6a2d2d;  --vs-ev-depleted-fg: #e6a8a8;
  --vs-ev-restored-bg: #2d5a5a;  --vs-ev-restored-fg: #a8e6e6;
  --vs-ev-dried-bg: #3a2a1a;     --vs-ev-dried-fg: #ccaa7a;
  --vs-ev-default-bg: #3a3a3a;   --vs-ev-default-fg: #c0c0c0;

  /* State badges (on hero render) */
  --vs-badge-empty-bg: #3a3340;     --vs-badge-empty-fg: #c8b8d6;
  --vs-badge-low-bg: #5a2424;       --vs-badge-low-fg: #ffc9c9;
  --vs-badge-depleted-bg: #2c2c38;  --vs-badge-depleted-fg: #9aa3b4;

  /* Weight pill (list) */
  --vs-wpill-bg: rgba(22, 30, 42, 0.72);      --vs-wpill-fg: rgba(105, 122, 142, 0.72);
  --vs-wpill-low-bg: rgba(32, 26, 42, 0.72);  --vs-wpill-low-fg: rgba(118, 105, 138, 0.80);

  /* Drying indicator text */
  --vs-dry-active: #6cb6e3;   /* live drying timer */
  --vs-dry-overdue: #e6a23c;  /* >24h overdue */
}

/* Buttons speak in sentence case, not Material's UPPERCASE shout */
.mud-button-root {
  text-transform: none;
  letter-spacing: 0.01em;
}

/* ── MudBlazor palette sync ─────────────────────────────────────────────────
   Edit the --vs-* tokens above. These bindings push changes into MudBlazor
   components automatically. The !important beats the runtime-injected theme. */
:root {
  --mud-palette-primary: var(--vs-accent) !important;
  --mud-palette-primary-darken: var(--vs-accent-deep) !important;
  --mud-palette-primary-lighten: #9ab2cf !important;
  --mud-palette-primary-text: #ffffff !important;
  --mud-palette-secondary: var(--vs-secondary) !important;
  --mud-palette-secondary-darken: #4db898 !important;
  --mud-palette-secondary-lighten: #a8efda !important;
  --mud-palette-secondary-text: #0e1018 !important;
  --mud-palette-background: var(--vs-bg) !important;
  --mud-palette-background-gray: var(--vs-surface) !important;
  --mud-palette-surface: var(--vs-surface) !important;
  --mud-palette-drawer-background: var(--vs-bg) !important;
  --mud-palette-drawer-text: var(--vs-text) !important;
  --mud-palette-appbar-background: var(--vs-bg) !important;
  --mud-palette-appbar-text: var(--vs-accent) !important;
  --mud-palette-text-primary: var(--vs-text) !important;
  --mud-palette-text-secondary: var(--vs-text-2) !important;
  --mud-palette-action-default: var(--vs-text-2) !important;
  --mud-palette-action-disabled: var(--vs-faint) !important;
  --mud-palette-action-disabled-background: var(--vs-surface-2) !important;
  --mud-palette-divider: var(--vs-hair) !important;
  --mud-palette-divider-light: var(--vs-hair-3) !important;
  --mud-palette-table-lines: var(--vs-hair) !important;
  --mud-palette-table-striped: var(--vs-surface) !important;
  --mud-palette-table-hover: var(--vs-surface-2) !important;
  --mud-palette-lines-default: var(--vs-hair) !important;
  --mud-palette-lines-inputs: var(--vs-hair-2) !important;
  --mud-palette-success: var(--vs-success) !important;
  --mud-palette-warning: var(--vs-warning) !important;
  --mud-palette-error: var(--vs-danger) !important;
  --mud-palette-info: var(--vs-info) !important;
  --mud-palette-dark: var(--vs-bg) !important;
  --mud-palette-dark-text: var(--vs-text) !important;
}

/* =====================================================================
   THEMES
   Two-layer model so each theme is small:
     html[data-mode="light"]  = everything a LIGHT theme shares (dark-on-light
        hairlines, soft shadows, re-tuned status colors, light pill tints, and
        the component overrides for spots that bake in dark rgba). All four
        light themes (Light/Blush/Sepia/Sage) reuse this.
     html[data-theme="X"]     = just that palette's bg/surface/text/accent.
   Dark themes (Dim/Wine) need no shared block — they inherit :root's dark
   hairlines/shadows/pills and only restate the palette.
   The --mud-palette-* bindings reference var(--vs-*), so MudBlazor follows.
   data-theme + data-mode are set pre-paint by the script in App.razor.
   ===================================================================== */

/* ---- shared LIGHT-mode layer ---- */
html[data-mode="light"] {
  --vs-hair: rgba(22, 32, 52, 0.09);
  --vs-hair-2: rgba(22, 32, 52, 0.14);
  --vs-hair-3: rgba(22, 32, 52, 0.05);

  --vs-success: #2e9d6e;
  --vs-warning: #b07d1f;
  --vs-danger: #c4485f;
  --vs-info: #2f6fd0;

  --vs-shadow-sm: 0 1px 2px rgba(22, 32, 52, 0.08);
  --vs-shadow: 0 1px 2px rgba(22, 32, 52, 0.05), 0 10px 26px rgba(22, 32, 52, 0.10);
  --vs-shadow-lg: 0 24px 50px rgba(22, 32, 52, 0.16);

  --vs-st-storage-bg: #e4edf7;   --vs-st-storage-fg: #2d567c;
  --vs-st-printing-bg: #e3f1e2;  --vs-st-printing-fg: #2c7233;
  --vs-st-drying-bg: #f4ecd5;    --vs-st-drying-fg: #856312;
  --vs-st-printdry-bg: #eef3d9;  --vs-st-printdry-fg: #5b6f1c;
  --vs-st-tostore-bg: #f7e2e9;   --vs-st-tostore-fg: #98415c;

  --vs-st-storage-bg-soft: rgba(45, 86, 124, 0.10);   --vs-st-storage-fg-soft: #2d567c;
  --vs-st-printing-bg-soft: rgba(44, 114, 51, 0.10);  --vs-st-printing-fg-soft: #2c7233;
  --vs-st-drying-bg-soft: rgba(133, 99, 18, 0.12);    --vs-st-drying-fg-soft: #856312;
  --vs-st-printdry-bg-soft: rgba(91, 111, 28, 0.13);  --vs-st-printdry-fg-soft: #5b6f1c;
  --vs-st-tostore-bg-soft: rgba(152, 65, 92, 0.10);   --vs-st-tostore-fg-soft: #98415c;

  --vs-cond-sealed-bg: rgba(45, 86, 124, 0.10);   --vs-cond-sealed-fg: #2d567c;
  --vs-cond-opened-bg: rgba(150, 100, 30, 0.13);  --vs-cond-opened-fg: #8a5a16;
  --vs-cond-almost-bg: rgba(170, 90, 20, 0.15);   --vs-cond-almost-fg: #9a5510;
  --vs-cond-depleted-bg: rgba(70, 70, 90, 0.10);  --vs-cond-depleted-fg: #565666;

  --vs-ev-created-bg: #dff0e4;   --vs-ev-created-fg: #256b3f;
  --vs-ev-weight-bg: #dde9f5;    --vs-ev-weight-fg: #2a5586;
  --vs-ev-status-bg: #ece0f5;    --vs-ev-status-fg: #6a3f93;
  --vs-ev-location-bg: #f3e7d6;  --vs-ev-location-fg: #875c2a;
  --vs-ev-depleted-bg: #f5dede;  --vs-ev-depleted-fg: #993c3c;
  --vs-ev-restored-bg: #d9f0f0;  --vs-ev-restored-fg: #246b6b;
  --vs-ev-dried-bg: #f1e7d5;     --vs-ev-dried-fg: #7a5a23;
  --vs-ev-default-bg: #e8e8ee;   --vs-ev-default-fg: #555566;

  --vs-badge-empty-bg: #ece4f0;     --vs-badge-empty-fg: #6a5a78;
  --vs-badge-low-bg: #f7dcdc;       --vs-badge-low-fg: #b03b3b;
  --vs-badge-depleted-bg: #e6e6ee;  --vs-badge-depleted-fg: #5a6072;

  --vs-wpill-bg: rgba(var(--vs-dot), 0.07);      --vs-wpill-fg: #69748a;
  --vs-wpill-low-bg: rgba(120, 60, 90, 0.08); --vs-wpill-low-fg: #8a5a72;

  --vs-dry-active: #2f74a8;
  --vs-dry-overdue: #b9721a;
}
/* Light-mode component overrides (spots that bake in dark rgba, not a token).
   All use var(--vs-*) so they adapt to whichever light theme is active. */
/* Spool flange: a soft neutral gray spool body instead of the dark blue-black,
   so near-empty spools don't read as a harsh dark disc on a light card. */
html[data-mode="light"] {
  --vs-spool-flange: #aab0bb;
  --vs-spool-flange-stroke: #9097a3;
}
html[data-mode="light"] body { background-image: none; }
/* Outlined buttons (Log a print, Log drying, etc.) read as plain text on a light
   card because they have no fill. Give them a subtle raised surface so they look
   like buttons again; deepen + accent the border on hover. */
html[data-mode="light"] .mud-button-outlined {
  background-color: var(--vs-surface-2);
}
html[data-mode="light"] .mud-button-outlined:hover {
  background-color: var(--vs-surface-3);
  border-color: var(--vs-accent);
}
html[data-mode="light"] .vs-nav-tabs,
html[data-mode="light"] .vs-public-tabs {
  background: rgba(255, 255, 255, 0.62);
  border-color: var(--vs-hair-2);
}
/* Active pill on light themes: the dark-glass insets read muddy on a pale
   container, so swap to a crisp accent ring + soft lift over the accent tint. */
html[data-mode="light"] .vs-nav-tab.is-active {
  background: var(--vs-accent-glow);
  box-shadow:
    inset 0 0 0 1px color-mix(in srgb, var(--vs-accent) 42%, transparent),
    0 1px 2px rgba(20, 20, 30, 0.07);
}
/* Sakura: the active nav pill wears the pale sky-blue secondary (not the green
   accent) so the top nav reads as "clear sky" over the blossom canvas. */
html[data-theme="blush"] .vs-nav-tab.is-active {
  background: color-mix(in srgb, var(--vs-secondary) 22%, transparent);
  box-shadow:
    inset 0 0 0 1px color-mix(in srgb, var(--vs-secondary) 44%, transparent),
    0 1px 2px rgba(20, 20, 30, 0.07);
}
html[data-mode="light"] .vs-sd-weightpanel { background: rgba(var(--vs-dot), 0.05); }
html[data-mode="light"] .vs-pegboard-card,
html[data-mode="light"] .vs-widget-card {
  background-color: var(--vs-surface);
  background-image:
    linear-gradient(180deg, rgba(0, 0, 0, 0.015) 0%, transparent 40%, rgba(0, 0, 0, 0.03) 100%),
    radial-gradient(circle, rgba(var(--vs-dot), 0.07) 1.0px, rgba(var(--vs-dot), 0.035) 1.7px, transparent 1.7px);
  box-shadow: inset 0 0 0 1px var(--vs-hair), 0 1px 3px rgba(22, 32, 52, 0.05);
}
/* Studio bands (hero / stat tiles / maker / next-action) use a very faint tinted
   gradient that vanishes against a light page. Lift them onto a clear cream
   surface with a hairline so they read as cards, like the pegboard widgets. */
html[data-mode="light"] .vs-hero,
html[data-mode="light"] .vs-stat-tile,
html[data-mode="light"] .vs-maker,
html[data-mode="light"] .vs-nextaction {
  background: var(--vs-surface);
  border-color: var(--vs-hair-2);
}
/* Gallery (spool) cards bake a dark inset + white reflection into an inline
   box-shadow that reads heavy/invisible on light. Swap to a clean light drop
   shadow + hairline (!important to beat the inline style). The recessed spool
   cavity inset also softens. */
html[data-mode="light"] .vs-gallery-card {
  box-shadow: 0 1px 2px rgba(22, 32, 52, 0.06), 0 4px 14px rgba(22, 32, 52, 0.05),
    inset 0 0 0 1px var(--vs-hair) !important;
}
html[data-mode="light"] .vs-gallery-card .vs-gallery-cavity {
  box-shadow: inset 0 2px 8px rgba(22, 32, 52, 0.10) !important;
}

/* ---- per-theme palettes (bg / surface / text / accent only) ---- */

/* Light — cool gray */
html[data-theme="light"] {
  --vs-bg-deep: #e7ecf3;  --vs-bg: #f4f7fb;  --vs-bg-tint: #eaeff7;
  --vs-surface: #ffffff;  --vs-surface-2: #f1f4f9;  --vs-surface-3: #e6ecf3;
  --vs-text: #1b2433;  --vs-text-2: #455062;  --vs-muted: #5b6678;  --vs-faint: #6c7589;
  --vs-accent: #3f6396;  --vs-blue: #2f6fd0;  --vs-accent-deep: #2f4f7d;
  --vs-accent-soft: rgba(63, 99, 150, 0.12);  --vs-accent-glow: rgba(63, 99, 150, 0.16);
  --vs-secondary: #2f9f74;
}

/* Sakura — soft pastel (PASTEL / SOFT / ELEGANT): flat blush-pink canvas, palest-
   GREEN floating cards (a hint of garden against the pink), muted sage-green accent
   + sky-blue secondary. Canvas is light enough that the green clears AA. The only
   gradient lives on the footer (below); the page itself is a flat solid pink. */
html[data-theme="blush"] {
  --vs-bg-deep: #f6dfe7;  --vs-bg: #fdf3f6;  --vs-bg-tint: #fbecf1;
  --vs-surface: #f1f6ef;  --vs-surface-2: #eaf0e6;  --vs-surface-3: #dee7d8;
  --vs-text: #3a2e33;  --vs-text-2: #8e4f64;  --vs-muted: #8a7079;  --vs-faint: #9b818b;
  --vs-accent: #4d7555;  --vs-blue: #5b94c4;  --vs-accent-deep: #3e6045;
  --vs-accent-soft: rgba(110, 152, 124, 0.15);  --vs-accent-glow: rgba(110, 152, 124, 0.20);
  --vs-secondary: #6aa3c9;
  /* Sakura's accent is sage-green, but the theme's face is rose — so the Material-mix
     donut starts from a deep rose (its main slice + the hues it spins off). */
  --vs-pie-base: #c14e71;
}
/* Sakura footer: a soft, muted blue -> white -> pink -> white -> green wash. The
   colors are semi-transparent (the pink page shows through, softening them) and
   both ends fade to fully transparent so they melt into the page instead of cutting
   off abruptly. Sakura-only for now. */
html[data-theme="blush"] .vs-app-footer {
  background: linear-gradient(90deg,
    rgba(198, 216, 237, 0) 0%,
    rgba(198, 216, 237, 0.60) 13%,
    rgba(233, 227, 232, 0.60) 31%,
    rgba(239, 213, 224, 0.62) 50%,
    rgba(233, 227, 230, 0.60) 69%,
    rgba(205, 221, 200, 0.60) 87%,
    rgba(205, 221, 200, 0) 100%);
}
/* Sakura: all form controls get a pale-blue field + a clearer border so they don't
   vanish into the soft pink page (inputs, textareas, the search box, the filter
   dropdowns / selects, the weight field). */
/* The Shelves staging search box lost its inline fill/border; give it a raised
   surface on all themes (Sakura recolors it pale blue below). */
.vs-filter-search {
  background: var(--vs-surface-2);
  border: 1px solid var(--vs-hair-2);
}
html[data-theme="blush"] .vs-input,
html[data-theme="blush"] .vs-search,
html[data-theme="blush"] .vs-filter-search,
html[data-theme="blush"] .mud-input-outlined,
html[data-theme="blush"] .mud-input-filled {
  background-color: #e7f0fb;
}
html[data-theme="blush"] .vs-search,
html[data-theme="blush"] .vs-filter-search { border-color: rgba(91, 148, 196, 0.40); }
html[data-theme="blush"] .mud-input-outlined .mud-input-outlined-border {
  border-color: rgba(91, 148, 196, 0.40) !important;
}
/* Dropdown options: a clearly different hover so you can see what you're over
   (the default light-theme hover was barely distinct from the popover surface). */
html[data-mode="light"] .mud-list-item:hover {
  background-color: color-mix(in srgb, var(--vs-accent) 18%, var(--vs-surface)) !important;
}

/* Chocolate (id "sepia") — dark chocolate: deep brown (amber lean, low blue so it
   reads brown not wine/burgundy), dark-family (light text, inherits dark pills
   like Lavender). Was the old warm-paper "Sepia". */
/* Latte (id "sepia") — a Medium-tone cocoa-latte (light family): warm tan page, cream
   cards/tables, rich chocolate text + a coffee accent. The palette's dark
   chocolates live in the text/accents; the creamy tans + beiges are the surfaces. */
html[data-theme="sepia"] {
  --vs-bg-deep: #c0a390;  --vs-bg: #cdb1a0;  --vs-bg-tint: #d6bcab;
  --vs-surface: #faf6f3;  --vs-surface-2: #f3eae3;  --vs-surface-3: #ebdfd7;
  --vs-text: #36241c;  --vs-text-2: #543d2e;  --vs-muted: #6b4f3e;  --vs-faint: #856652;
  --vs-accent: #7a5240;  --vs-blue: #8c7468;  --vs-accent-deep: #5a3a2c;
  --vs-accent-soft: rgba(122, 82, 64, 0.10);  --vs-accent-glow: rgba(122, 82, 64, 0.15);
  --vs-secondary: #aa8b7e;
  /* Warm-tint the dashboard chrome (bands, pegboard dots, pills, chart grids). */
  --vs-tint: 122, 82, 64;  --vs-dot: 122, 82, 64;  --vs-wpill-fg: #8a6c58;
  /* Material-mix donut uses the shared contrasting wheel (data-mode="light" block);
     no coffee-ramp override here so the slices stay easy to tell apart. */
}

/* Matcha (id "sage") — warm yellow-green matcha latte (light family). Soft
   matcha-green page with lighter cream cards (so they pop), olive-green text +
   matcha accent. Hue leans warm (G>R>B) like real matcha, not a cool mint. */
html[data-theme="sage"] {
  --vs-bg-deep: #cfd9ba;  --vs-bg: #dfe7cf;  --vs-bg-tint: #d8e1c6;
  --vs-surface: #f0f4e6;  --vs-surface-2: #e7eed9;  --vs-surface-3: #d4ddc0;
  --vs-text: #2d3823;  --vs-text-2: #4c5a3f;  --vs-muted: #5e6e4d;  --vs-faint: #6f7d5e;
  --vs-accent: #57713f;  --vs-blue: #4f7a45;  --vs-accent-deep: #455c33;
  --vs-accent-soft: rgba(87, 113, 63, 0.14);  --vs-accent-glow: rgba(87, 113, 63, 0.18);
  --vs-secondary: #8a7a44;
}

/* Dim — soft slate-navy dark (inherits dark pills/hairlines/shadows) */
html[data-theme="dim"] {
  --vs-bg-deep: #1c2129;  --vs-bg: #232a35;  --vs-bg-tint: #2a313d;
  --vs-surface: #2e3643;  --vs-surface-2: #38414f;  --vs-surface-3: #434d5d;
  --vs-text: #e6ebf2;  --vs-text-2: #b3bccb;  --vs-muted: #8b96a8;  --vs-faint: #7d8799;
  --vs-accent: #88a6cc;  --vs-blue: #7fb0ea;  --vs-accent-deep: #6a89b0;
  --vs-accent-soft: rgba(136, 166, 204, 0.14);  --vs-accent-glow: rgba(136, 166, 204, 0.16);
  --vs-secondary: #84d0aa;
}

/* Wine — deep aubergine + rose-gold (feminine dark; inherits dark pills) */
html[data-theme="wine"] {
  --vs-bg-deep: #1e1420;  --vs-bg: #241823;  --vs-bg-tint: #2c1e2b;
  --vs-surface: #2e2030;  --vs-surface-2: #382838;  --vs-surface-3: #443447;
  --vs-text: #f0e3ea;  --vs-text-2: #cbb3c2;  --vs-muted: #a98ba0;  --vs-faint: #997d92;
  --vs-accent: #d28aa6;  --vs-blue: #cf7d9c;  --vs-accent-deep: #b06a86;
  --vs-accent-soft: rgba(210, 138, 166, 0.15);  --vs-accent-glow: rgba(210, 138, 166, 0.18);
  --vs-secondary: #c8a8e6;
}

/* Lavender — deep muted purple dusk (dark-mode family: light text, inherits dark
   pills). Darker + less saturated than the first cut, with a clearer gap between
   the page bg and the card surfaces so it doesn't read as one flat purple. */
/* Dusk (id "lavender") — a dusky twilight ramp: Space Indigo -> Dusty Grape backgrounds,
   Seashell/Almond/Lilac-Ash text steps, warm Almond Silk accent on the cool indigo. */
html[data-theme="lavender"] {
  --vs-bg-deep: #1b1b2e;  --vs-bg: #22223b;  --vs-bg-tint: #2a2a45;
  --vs-surface: #32324f;  --vs-surface-2: #3d3d5a;  --vs-surface-3: #4a4e69;
  --vs-text: #f2e9e4;  --vs-text-2: #d9cdd0;  --vs-muted: #9a8c98;  --vs-faint: #8b8291;
  --vs-accent: #c9ada7;  --vs-blue: #7c80a8;  --vs-accent-deep: #b39790;
  --vs-accent-soft: rgba(201, 173, 167, 0.15);  --vs-accent-glow: rgba(201, 173, 167, 0.20);
  --vs-secondary: #a896a4;
}

/* Slate (dim) + Dusk (lavender): the light accent makes the filled Save button's
   default white label low-contrast. Use dark text on the accent on those themes. */
html[data-theme="dim"] .vs-material-editor .vs-modal-actions .mud-button-filled-primary,
html[data-theme="lavender"] .vs-material-editor .vs-modal-actions .mud-button-filled-primary {
  background-color: var(--vs-accent);
  color: var(--vs-bg-deep);
}

[data-density="compact"] {
  --vs-gap: 12px;
}
[data-density="comfortable"] {
  --vs-gap: 18px;
}
[data-density="roomy"] {
  --vs-gap: 26px;
}

* {
  box-sizing: border-box;
}
html,
body {
  margin: 0;
  padding: 0;
}
body {
  background: var(--vs-bg);
  background-image:
    radial-gradient(
      1100px 550px at 78% -8%,
      rgba(100, 140, 200, 0.06),
      transparent 55%
    ),
    radial-gradient(
      750px 480px at -8% 92%,
      rgba(80, 60, 150, 0.05),
      transparent 55%
    );
  background-attachment: fixed;
  color: var(--vs-text);
  font-family: var(--vs-sans);
  font-size: 14px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  min-height: 100vh;
}

.vs-mono {
  font-family: var(--vs-mono);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.005em;
}
.vs-muted {
  color: var(--vs-muted);
}

.vs-app {
  min-height: 100vh;
  overflow-x: clip;
}
.vs-shell {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  max-width: 1720px;
  margin: 0 auto;
  padding: 0 28px;
}
.vs-sidebar {
  display: none;
}

/* ====== MASTHEAD ====== */
.vs-topbar {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 28px;
  padding: 6px 0;
  position: sticky;
  top: 0;
  z-index: 20;
  background: linear-gradient(to bottom, var(--vs-bg) 70%, transparent);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
}
.vs-topbar::after {
  content: "";
  position: absolute;
  inset: auto 0 0 0;
  height: 1px;
  background: var(--vs-hair);
}
.vs-topbar-toggle {
  display: none !important;
}
.vs-masthead-brand {
  display: flex;
  align-items: center;
  gap: 10px;
}
.vs-masthead-title {
  font-family: var(--vs-display);
  font-size: 19px;
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 1;
  color: var(--vs-text);
}
.vs-masthead-title em {
  font-style: normal;
  color: var(--vs-blue);
  font-weight: 700;
}
.vs-masthead-meta {
  display: none;
}
.vs-main {
  min-width: 0;
  flex: 1;
  display: flex;
  flex-direction: column;
}

.vs-nav-tabs {
  display: flex;
  align-items: center;
  gap: 4px;
  justify-self: center;
  white-space: nowrap;
  background: rgba(13, 16, 23, 0.80);
  border: 1px solid rgba(255, 255, 255, 0.048);
  border-radius: 999px;
  padding: 4px;
}

.vs-public-nav {
  display: flex;
  align-items: center;
  gap: 22px;
  justify-self: center;
}
.vs-public-nav-link {
  font-family: var(--vs-sans);
  font-size: 13px;
  font-weight: 500;
  color: var(--vs-text-2);
  text-decoration: none;
  transition: color 0.18s;
}
.vs-public-nav-link:hover {
  color: var(--vs-text);
}
@media (max-width: 600px) {
  .vs-public-nav { gap: 12px; }
  .vs-public-nav-link { font-size: 12px; }
}

/* Public catalog pill nav — same pill look as the logged-in nav, but always
   visible (no hamburger collapse) since public pages have no sidebar toggle. */
.vs-public-tabs {
  display: flex;
  align-items: center;
  gap: 4px;
  justify-self: center;
  background: rgba(13, 16, 23, 0.80);
  border: 1px solid rgba(255, 255, 255, 0.048);
  border-radius: 999px;
  padding: 4px;
  max-width: 100%;
  overflow-x: auto;
  scrollbar-width: none;
}
.vs-public-tabs::-webkit-scrollbar { display: none; }
.vs-nav-tab {
  background: transparent;
  border: 0;
  padding: 7px 16px;
  font-family: var(--vs-sans);
  font-size: 13px;
  font-weight: 500;
  color: var(--vs-text-2);
  cursor: pointer;
  letter-spacing: 0;
  text-transform: none;
  position: relative;
  border-radius: 999px;
  transition:
    color 0.15s,
    background 0.15s;
}
.vs-nav-tab {
  position: relative;
  overflow: hidden;
}
.vs-nav-tab:hover {
  color: var(--vs-text);
  background: var(--vs-surface-2);
}
.vs-nav-tab.is-active {
  color: var(--vs-text);
  /* Theme-accent tint (was a hardcoded cool blue that clashed on warm/light
     themes). accent-glow/soft are defined at :root + every theme block. */
  background: var(--vs-accent-glow);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.11),
    inset 0 0 0 1px var(--vs-accent-soft),
    inset 0 -1px 0 rgba(0, 0, 0, 0.18);
  font-weight: 600;
}
.vs-nav-tab.is-active::after {
  display: none;
}
.vs-nav-tab.is-active::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  /* Sheen sweeps via background-position, not element transform, so the
     ::before never extends past the pill (nothing to clip) */
  background-image: linear-gradient(
    120deg,
    transparent 38%,
    rgba(255, 255, 255, 0.10) 50%,
    transparent 62%
  );
  background-size: 300% 100%;
  background-repeat: no-repeat;
  animation: vs-shimmer 3.4s ease-in-out infinite;
}
@keyframes vs-shimmer {
  0% {
    background-position: 200% 0;
  }
  100% {
    background-position: -100% 0;
  }
}

.vs-topbar-actions {
  display: flex;
  gap: 8px;
  align-items: center;
  justify-self: end;
}
/* Command-palette opener — looks like a search field, opens Ctrl/Cmd-K. */
.vs-cmdk-trigger {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 34px;
  padding: 0 9px 0 11px;
  border-radius: 9px;
  /* Raised surface (was var(--vs-bg) = page color, so it vanished into the page). */
  background: var(--vs-surface-2);
  border: 1px solid var(--vs-hair-2);
  color: var(--vs-muted);
  font-size: 13px;
  cursor: pointer;
  transition: border-color 0.15s, color 0.15s, background 0.15s;
}
.vs-cmdk-trigger:hover {
  color: var(--vs-text-2);
  border-color: var(--vs-faint);
}
.vs-cmdk-trigger svg { flex-shrink: 0; }
.vs-cmdk-trigger-label { padding-right: 4px; }
.vs-cmdk-trigger-kbd {
  font: 600 11px/1 ui-monospace, SFMono-Regular, Menlo, monospace;
  color: var(--vs-faint);
  border: 1px solid var(--vs-hair-2);
  border-radius: 5px;
  padding: 3px 5px;
}
/* Collapse to a plain icon button on narrow screens (still tappable on touch). */
@media (max-width: 760px) {
  .vs-cmdk-trigger { width: 34px; padding: 0; justify-content: center; gap: 0; }
  .vs-cmdk-trigger-label,
  .vs-cmdk-trigger-kbd { display: none; }
}
/* Collector mode — full-screen, chrome-free spool showcase (SpoolDetail). */
.vs-collector-overlay {
  position: fixed;
  inset: 0;
  z-index: 1400;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: radial-gradient(circle at 50% 32%, var(--vs-surface) 0%, #0a0a0f 68%, #06060a 100%);
  animation: vs-collector-fade 0.18s ease-out;
}
@keyframes vs-collector-fade { from { opacity: 0; } to { opacity: 1; } }
.vs-collector-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(14px, 3vh, 24px);
  cursor: default;
  max-width: 92vw;
}
/* Big as it can be while still leaving room for the caption — capped by width,
   height, AND the shorter viewport dimension so it never overflows on phones. */
.vs-collector-render svg {
  width: min(560px, 86vw, 62vh);
  height: auto;
  transform-origin: 50% 50%;
  animation: vs-collector-spin 26s linear infinite;
}
@keyframes vs-collector-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .vs-collector-render svg { animation: none; }
}
.vs-collector-close {
  position: absolute;
  top: 16px;
  right: 20px;
  background: none;
  border: none;
  color: #8a8aa0;
  font-size: 30px;
  line-height: 1;
  cursor: pointer;
  transition: color 0.15s;
}
.vs-collector-close:hover { color: #f0f0f5; }
.vs-iconbtn {
  width: 34px;
  height: 34px;
  display: grid;
  place-items: center;
  border-radius: 8px;
  background: var(--vs-surface);
  border: 1px solid var(--vs-hair);
  color: var(--vs-text-2);
  cursor: pointer;
  position: relative;
  transition:
    background 0.15s,
    color 0.15s,
    border-color 0.15s;
}
.vs-iconbtn:hover {
  color: var(--vs-text);
  background: var(--vs-surface-2);
  border-color: var(--vs-hair-2);
}
.vs-iconbtn-dot {
  position: absolute;
  top: 7px;
  right: 7px;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--vs-accent);
  box-shadow: 0 0 0 2px var(--vs-surface);
}
.vs-userchip-mini {
  display: flex;
  align-items: center;
  gap: 8px;
}
.vs-avatar {
  width: 32px;
  height: 32px;
  border-radius: 8px;
  background: linear-gradient(
    135deg,
    var(--vs-accent) 0%,
    var(--vs-accent-deep) 100%
  );
  color: #fff;
  display: grid;
  place-items: center;
  font-weight: 700;
  font-size: 13px;
  letter-spacing: 0;
}

/* ====== PAGE HEAD ====== */
.vs-content {
  padding: 16px 0 80px;
}
.vs-page {
  display: flex;
  flex-direction: column;
  gap: 28px;
}
.vs-page-head {
  display: grid;
  grid-template-columns: 1fr auto;
  /* Center-align the title with whatever sits on the right (actions/stats), and
     give every page the same minimum band height + spacing-to-content so the
     four main pages line their content tops up consistently. */
  align-items: center;
  gap: 24px;
  min-height: 56px;
  margin-bottom: 28px;
  padding-bottom: 0;
  border-bottom: 0;
}
/* Pages wrapped in .vs-page already get a 28px flex gap to the next block, so
   drop the header's own margin there to avoid double spacing. Unwrapped pages
   (no .vs-page parent) keep the 28px margin above. */
.vs-page > .vs-page-head {
  margin-bottom: 0;
}
.vs-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--vs-sans);
  font-size: 12px;
  color: var(--vs-text-2);
  letter-spacing: 0;
  text-transform: none;
  font-weight: 500;
}
.vs-eyebrow::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--vs-accent);
  box-shadow: 0 0 0 3px var(--vs-accent-soft);
}
.vs-page-title {
  /* Unified page-title style across every top-nav and inner page so the
     site reads consistent. Flat solid color (no gradient text-fill) so
     it doesn't visually clash with the section headers on the same page,
     which are also flat white. */
  margin: 0;
  font-family: var(--vs-display);
  /* 28px gives the H1 tier a real jump over the 12-18px body scale now that
     Space Grotesk carries the titles */
  font-size: 28px;
  font-weight: 700;
  letter-spacing: -0.01em; /* Space Grotesk needs less tightening than Manrope */
  line-height: 1.15;
  color: var(--vs-text);
}
.vs-page-title em {
  font-style: normal;
  color: var(--vs-text);
  font-weight: 700;
}
.vs-page-subtitle {
  font-size: 14px;
  color: var(--vs-text-2);
  margin-top: 6px;
  font-family: var(--vs-sans);
  max-width: 60ch;
}
.vs-page-aside {
  display: flex;
  align-items: center;
  gap: 10px;
  text-align: right;
}
.vs-page-aside-tile {
  background: var(--vs-surface);
  border: 1px solid var(--vs-hair);
  border-radius: var(--vs-radius);
  padding: 10px 16px;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  min-width: 120px;
}
.vs-page-aside-big {
  font-family: var(--vs-sans);
  font-size: 22px;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--vs-text);
}
.vs-page-aside-label {
  font-size: 10.5px;
  color: var(--vs-muted);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  margin-top: 2px;
  font-weight: 500;
}

/* ====== SECTION HEAD ====== */
.vs-section-head {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: baseline;
  gap: 16px;
  margin-bottom: 14px;
  padding-bottom: 0;
  border-bottom: 0;
}
.vs-section-title {
  margin: 0;
  font-family: var(--vs-sans);
  font-size: 16px;
  font-weight: 600;
  letter-spacing: -0.005em;
  color: var(--vs-text);
  display: flex;
  align-items: center;
  gap: 8px;
}
.vs-section-sub {
  font-size: 12px;
  font-family: var(--vs-sans);
  color: var(--vs-muted);
  margin-top: 3px;
  letter-spacing: 0;
  text-transform: none;
  font-weight: 400;
}
.vs-section-count {
  font-family: var(--vs-mono);
  font-size: 11px;
  color: var(--vs-muted);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  background: var(--vs-surface-2);
  padding: 3px 8px;
  border-radius: 999px;
}

/* ====== CARD ====== */
.vs-card {
  background: var(--vs-surface);
  border: 1px solid rgba(255, 255, 255, 0.04);
  border-radius: var(--vs-radius-lg);
  position: relative;
  box-shadow:
    var(--vs-shadow-sm),
    inset 0 1px 0 rgba(255, 255, 255, 0.04);
}
.vs-section {
  padding: 20px 22px;
}
.vs-two-col {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 18px;
}
.vs-warn-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--vs-danger);
  display: inline-block;
  box-shadow: 0 0 0 3px rgba(255, 92, 122, 0.15);
}

/* ====== HERO SHELF ====== */
.vs-hero-shelf {
  position: relative;
  padding: 22px;
  background: linear-gradient(
    180deg,
    var(--vs-surface) 0%,
    var(--vs-bg-tint) 100%
  );
  border: 1px solid var(--vs-hair);
  border-radius: var(--vs-radius-lg);
  overflow: hidden;
  box-shadow: var(--vs-shadow);
}
.vs-hero-shelf-glow {
  position: absolute;
  inset: -50% -10% auto -10%;
  height: 180px;
  background: radial-gradient(
    ellipse at center,
    var(--vs-accent-soft),
    transparent 65%
  );
  pointer-events: none;
}
.vs-hero-shelf-rail {
  position: relative;
  display: flex;
  align-items: flex-end;
  gap: 2px;
  padding: 12px 6px 4px;
  min-height: 110px;
  overflow-x: auto;
  scrollbar-width: thin;
  scrollbar-color: var(--vs-hair-2) transparent;
}
.vs-hero-shelf-spool {
  padding: 0 2px;
}
.vs-hero-shelf-plank,
.vs-hero-shelf-bolt {
  display: none;
}
.vs-hero-cap {
  position: relative;
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.vs-hero-rule {
  font-family: var(--vs-sans);
  font-size: 13px;
  color: var(--vs-text);
  font-weight: 600;
  letter-spacing: -0.005em;
}
.vs-hero-rule small {
  display: block;
  color: var(--vs-muted);
  font-size: 12px;
  font-weight: 400;
  margin-top: 2px;
}

/* ====== STAT GRID ====== */
.vs-stat-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 12px;
}
.vs-stat {
  padding: 16px 18px;
  background: var(--vs-surface);
  border: 1px solid var(--vs-hair);
  border-radius: var(--vs-radius);
  position: relative;
  overflow: hidden;
  transition:
    border-color 0.15s,
    transform 0.15s;
  box-shadow: var(--vs-shadow-sm);
  cursor: default;
}
.vs-stat:hover {
  border-color: var(--vs-hair-2);
  transform: translateY(-1px);
}
.vs-stat-glow {
  position: absolute;
  inset: -40% -20% auto auto;
  width: 200px;
  height: 120px;
  border-radius: 50%;
  pointer-events: none;
  opacity: 0.5;
}
.vs-stat-value {
  font-family: var(--vs-sans);
  font-size: 32px;
  font-weight: 700;
  letter-spacing: -0.03em;
  line-height: 1;
  color: var(--vs-text);
  font-variant-numeric: tabular-nums;
}
.vs-stat-label {
  font-family: var(--vs-sans);
  font-size: 12px;
  letter-spacing: 0;
  text-transform: none;
  color: var(--vs-text-2);
  margin-top: 8px;
  font-weight: 500;
}
.vs-stat--primary .vs-stat-value {
  color: var(--vs-accent);
}
.vs-stat--primary .vs-stat-glow {
  background: radial-gradient(circle, var(--vs-accent-glow), transparent 60%);
}
.vs-stat--success .vs-stat-value {
  color: var(--vs-success);
}
.vs-stat--success .vs-stat-glow {
  background: radial-gradient(
    circle,
    rgba(124, 200, 160, 0.3),
    transparent 60%
  );
}
.vs-stat--danger .vs-stat-value {
  color: var(--vs-danger);
}
.vs-stat--danger .vs-stat-glow {
  background: radial-gradient(circle, rgba(217, 125, 145, 0.3), transparent 60%);
}
.vs-stat--warning .vs-stat-value {
  color: var(--vs-warning);
}
.vs-stat--warning .vs-stat-glow {
  background: radial-gradient(
    circle,
    rgba(225, 187, 107, 0.25),
    transparent 60%
  );
}
.vs-stat--muted .vs-stat-value {
  color: var(--vs-text);
}

/* ====== BUTTONS ====== */
.vs-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 12px;
  background: var(--vs-surface-2);
  border: 1px solid var(--vs-hair-2);
  border-radius: 8px;
  color: var(--vs-text);
  font-family: var(--vs-sans);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
  cursor: pointer;
  transition:
    background 0.12s,
    border-color 0.12s;
}
.vs-btn:hover {
  background: var(--vs-surface-3);
  border-color: var(--vs-hair-2);
}
.vs-btn--primary {
  background: var(--vs-accent);
  border-color: var(--vs-accent);
  color: #1a0d05;
  font-weight: 600;
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.18) inset,
    0 4px 14px rgba(255, 125, 63, 0.3);
}
.vs-btn--primary:hover {
  background: #ff8a52;
  border-color: #ff8a52;
}

/* ====== BENCH (recent) ====== */
.vs-bench-list {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.vs-bench-row {
  display: grid;
  grid-template-columns: 36px 1fr 80px 1fr 100px;
  gap: 14px;
  align-items: center;
  padding: 10px 12px;
  border-radius: 8px;
  border: 1px solid transparent;
  background: transparent;
  transition:
    background 0.12s,
    border-color 0.12s;
}
.vs-bench-row:hover {
  background: var(--vs-surface-2);
  border-color: var(--vs-hair);
}
.vs-bench-code {
  font-family: var(--vs-mono);
  font-size: 11px;
  color: var(--vs-muted);
}
.vs-bench-name {
  font-family: var(--vs-sans);
  font-size: 13px;
  color: var(--vs-text);
  font-weight: 500;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.vs-bench-weight {
  text-align: right;
  font-family: var(--vs-sans);
  font-size: 15px;
  color: var(--vs-text);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.vs-bench-weight-unit {
  color: var(--vs-muted);
  font-size: 11px;
  margin-left: 3px;
  font-weight: 500;
}
.vs-bench-pct {
  display: flex;
  align-items: center;
  gap: 10px;
}
.vs-bench-pct-track {
  flex: 1;
  height: 4px;
  border-radius: 999px;
  background: var(--vs-surface-3);
  overflow: hidden;
}
.vs-bench-pct-fill {
  height: 100%;
  background: var(--vs-text-2);
  border-radius: 999px;
}
.vs-bench-pct-fill.is-low {
  background: var(--vs-danger);
}
.vs-bench-pct span {
  font-family: var(--vs-mono);
  font-size: 11px;
  color: var(--vs-text);
  min-width: 36px;
  text-align: right;
}

/* ====== STATUS PILLS ====== */
.vs-status-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 9px;
  border: 1px solid var(--vs-hair);
  border-radius: 999px;
  font-family: var(--vs-sans);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
  background: var(--vs-surface-2);
  color: var(--vs-text-2);
  cursor: pointer;
  transition:
    color 0.15s,
    background 0.15s,
    border-color 0.15s;
}
.vs-status-pill::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--vs-muted);
}
.vs-status-pill:hover {
  background: var(--vs-surface-3);
  color: var(--vs-text);
}
.vs-status--InStorage::before {
  background: var(--vs-success);
  box-shadow: 0 0 0 2px rgba(127, 231, 192, 0.18);
}
.vs-status--InUse::before,
.vs-status--Loaded::before {
  background: var(--vs-accent);
  box-shadow: 0 0 0 2px var(--vs-accent-soft);
}
.vs-status--Drying::before {
  background: var(--vs-warning);
  box-shadow: 0 0 0 2px rgba(255, 206, 91, 0.18);
}
.vs-status--ToBeStored::before {
  background: var(--vs-info);
  box-shadow: 0 0 0 2px rgba(138, 180, 255, 0.18);
}
.vs-status--InStorage {
  color: var(--vs-success);
  border-color: rgba(127, 231, 192, 0.25);
}
.vs-status--InUse,
.vs-status--Loaded {
  color: var(--vs-accent);
  border-color: rgba(232, 74, 90, 0.3);
}
.vs-status--Drying {
  color: var(--vs-warning);
  border-color: rgba(255, 206, 91, 0.25);
}
.vs-status--ToBeStored {
  color: var(--vs-info);
  border-color: rgba(138, 180, 255, 0.25);
}

.vs-statusmenu {
  position: relative;
  display: inline-block;
}
.vs-statusmenu-backdrop {
  position: fixed;
  inset: 0;
  z-index: 9;
}
.vs-statusmenu-pop {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 8px;
  background: var(--vs-surface);
  border: 1px solid var(--vs-hair-2);
  border-radius: var(--vs-radius);
  box-shadow: var(--vs-shadow-lg);
  z-index: 10;
}

/* ====== BARS ====== */
.vs-strand-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.vs-bar-row {
  display: grid;
  grid-template-columns: 110px 1fr 40px;
  align-items: center;
  gap: 14px;
}
.vs-bar-label {
  font-family: var(--vs-sans);
  font-size: 12px;
  color: var(--vs-text-2);
  letter-spacing: 0;
  text-transform: none;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: 500;
}
.vs-bar-track {
  position: relative;
  height: 6px;
  background: var(--vs-surface-3);
  border-radius: 999px;
  overflow: hidden;
}
.vs-bar-fill {
  height: 100%;
  border-radius: 999px;
}
.vs-bar-fill--primary {
  background: linear-gradient(90deg, var(--vs-accent-deep), var(--vs-accent));
}
.vs-bar-fill--secondary {
  background: linear-gradient(90deg, #3d8a72, var(--vs-secondary));
}
.vs-bar-value {
  font-family: var(--vs-mono);
  font-size: 12px;
  color: var(--vs-text);
  text-align: right;
  font-weight: 500;
}

/* ====== LOW STOCK ====== */
.vs-low-grid {
  display: grid;
  gap: 8px;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
}
.vs-low-card {
  display: flex;
  gap: 12px;
  align-items: center;
  padding: 10px 12px;
  background: var(--vs-surface-2);
  border: 1px solid var(--vs-hair);
  border-radius: var(--vs-radius);
  cursor: pointer;
  transition:
    background 0.12s,
    border-color 0.12s,
    transform 0.12s;
}
.vs-low-card:hover {
  background: var(--vs-surface-3);
  border-color: var(--vs-hair-2);
  transform: translateY(-1px);
}
.vs-low-code {
  font-family: var(--vs-mono);
  font-size: 10px;
  color: var(--vs-muted);
  margin-top: 2px;
}
.vs-low-name {
  font-family: var(--vs-sans);
  font-size: 13px;
  color: var(--vs-text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: 500;
}
.vs-low-remaining {
  font-size: 11px;
  margin-top: 4px;
}

/* ====== TOOLBAR ====== */
.vs-toolbar {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 14px 16px;
  background: var(--vs-surface);
  border: 1px solid var(--vs-hair);
  border-radius: var(--vs-radius-lg);
  box-shadow: var(--vs-shadow-sm);
}
.vs-toolbar-row {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}
.vs-search {
  flex: 1;
  min-width: 240px;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 14px;
  background: var(--vs-bg-tint);
  border: 1px solid var(--vs-hair);
  border-radius: 8px;
  color: var(--vs-muted);
  transition:
    border-color 0.15s,
    background 0.15s;
}
.vs-search:focus-within {
  border-color: var(--vs-accent);
  background: var(--vs-surface-2);
  color: var(--vs-text);
  box-shadow: 0 0 0 3px var(--vs-accent-soft);
}
.vs-search input {
  background: transparent;
  border: 0;
  outline: 0;
  color: var(--vs-text);
  font-family: var(--vs-sans);
  font-size: 14px;
  flex: 1;
  min-width: 0;
  font-weight: 500;
}
.vs-search input::placeholder {
  color: var(--vs-muted);
}
.vs-search-clear {
  background: transparent;
  border: 0;
  color: var(--vs-muted);
  cursor: pointer;
  font-size: 18px;
  line-height: 1;
  padding: 0 2px;
}
.vs-select {
  appearance: none;
  padding: 8px 30px 8px 12px;
  background: var(--vs-bg-tint)
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6' fill='none'><path d='M1 1l4 4 4-4' stroke='%236c7280' stroke-width='1.4' stroke-linecap='round'/></svg>")
    no-repeat right 12px center;
  border: 1px solid var(--vs-hair);
  border-radius: 8px;
  color: var(--vs-text);
  font-family: var(--vs-sans);
  font-size: 12.5px;
  font-weight: 500;
  cursor: pointer;
}
.vs-select:hover {
  border-color: var(--vs-hair-2);
}
.vs-view-toggle {
  display: inline-flex;
  padding: 3px;
  background: var(--vs-bg-tint);
  border: 1px solid var(--vs-hair);
  border-radius: 8px;
  gap: 2px;
}
.vs-view-toggle-btn {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 5px 10px;
  background: transparent;
  border: 0;
  border-radius: 6px;
  color: var(--vs-muted);
  font-family: var(--vs-sans);
  font-size: 12px;
  cursor: pointer;
  font-weight: 500;
}
.vs-view-toggle-btn:hover {
  color: var(--vs-text);
}
.vs-view-toggle-btn.is-active {
  color: var(--vs-text);
  background: var(--vs-surface-3);
}

.vs-toolbar-row--chips {
  gap: 6px;
}
.vs-filter-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 11px;
  background: var(--vs-bg-tint);
  border: 1px solid var(--vs-hair);
  border-radius: 999px;
  color: var(--vs-text-2);
  font-family: var(--vs-sans);
  font-size: 12px;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.12s;
}
.vs-filter-chip:hover {
  color: var(--vs-text);
  border-color: var(--vs-hair-2);
}
.vs-filter-chip.is-active {
  color: #1a0d05;
  background: var(--vs-accent);
  border-color: var(--vs-accent);
}
.vs-filter-chip-count {
  font-size: 10.5px;
  color: var(--vs-muted);
}
.vs-filter-chip.is-active .vs-filter-chip-count {
  color: rgba(26, 13, 5, 0.65);
}
.vs-toolbar-spacer {
  flex: 1;
}
.vs-toolbar-count {
  font-family: var(--vs-sans);
  font-size: 12.5px;
  color: var(--vs-text-2);
  margin-right: 10px;
  font-weight: 500;
}

/* ====== LIST ====== */
.vs-list {
  background: var(--vs-surface);
  border: 1px solid var(--vs-hair);
  border-radius: var(--vs-radius-lg);
  overflow: hidden;
  box-shadow: var(--vs-shadow-sm);
}
.vs-list-head,
.vs-list-row {
  display: grid;
  grid-template-columns: 40px 56px minmax(180px, 2fr) minmax(
      80px,
      110px
    ) 140px 1fr 1.2fr 130px;
  gap: 14px;
  align-items: center;
  padding: 12px 18px;
}
.vs-list-head {
  border-bottom: 1px solid var(--vs-hair);
  font-family: var(--vs-sans);
  font-size: 11px;
  letter-spacing: 0;
  text-transform: none;
  color: var(--vs-muted);
  font-weight: 500;
  background: var(--vs-bg-tint);
}
.vs-list-body .vs-list-row {
  border-top: 1px solid var(--vs-hair-3);
}
.vs-list-body .vs-list-row:first-child {
  border-top: 0;
}
.vs-list-body .vs-list-row:hover {
  background: var(--vs-surface-2);
}
.vs-list-cell--spool {
  display: flex;
  align-items: center;
  justify-content: center;
}
.vs-list-id {
  font-family: var(--vs-mono);
  font-size: 11px;
  color: var(--vs-muted);
}
.vs-list-name {
  font-family: var(--vs-sans);
  font-size: 14px;
  color: var(--vs-text);
  font-weight: 500;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.vs-list-sub {
  font-size: 11px;
  color: var(--vs-muted);
  margin-top: 2px;
  display: flex;
  align-items: center;
  gap: 6px;
}
.vs-list-code {
  font-family: var(--vs-mono);
  font-size: 11px;
  color: var(--vs-text-2);
}
.vs-list-shelf {
  font-family: var(--vs-sans);
  font-size: 12px;
  color: var(--vs-text-2);
  display: flex;
  align-items: center;
  gap: 4px;
}
.vs-list-shelf-room {
  color: var(--vs-accent);
  font-weight: 500;
}
.vs-spec-chip {
  font-family: var(--vs-sans);
  font-size: 10.5px;
  letter-spacing: 0;
  text-transform: none;
  padding: 2px 7px;
  border-radius: 999px;
  border: 1px solid var(--vs-hair);
  color: var(--vs-secondary);
  background: rgba(127, 231, 192, 0.06);
  font-weight: 500;
}

.vs-fillbar {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}
.vs-fillbar-track {
  height: 4px;
  background: var(--vs-surface-3);
  border-radius: 999px;
  overflow: hidden;
}
.vs-fillbar-fill {
  height: 100%;
  border-radius: 999px;
  background: var(--vs-text-2);
}
.vs-fillbar-fill--danger {
  background: var(--vs-danger);
}
.vs-fillbar-fill--warning {
  background: var(--vs-warning);
}
.vs-fillbar-fill--success {
  background: var(--vs-success);
}
.vs-fillbar-meta {
  display: flex;
  align-items: center;
  gap: 6px;
  font-family: var(--vs-mono);
  font-size: 11px;
}
.vs-fillbar-pct--danger {
  color: var(--vs-danger);
}
.vs-fillbar-pct--warning {
  color: var(--vs-warning);
}
.vs-fillbar-pct--success {
  color: var(--vs-success);
}

/* ====== CARD GRID ====== */
.vs-card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 12px;
}
[data-cardsize="small"] .vs-card-grid {
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
}
[data-cardsize="large"] .vs-card-grid {
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
}

/* Phone: force 2 columns and scale hero SVG to fit the narrower card */
@media (max-width: 560px) {
  .vs-card-grid,
  [data-cardsize="small"] .vs-card-grid,
  [data-cardsize="large"] .vs-card-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 10px;
  }
  .vs-spool-card {
    padding: 12px 10px 10px;
  }
  .vs-spool-card-hero {
    min-height: 120px;
  }
  .vs-spool-card-hero svg,
  [data-cardsize="small"] .vs-spool-card-hero svg,
  [data-cardsize="large"] .vs-spool-card-hero svg {
    width: 100% !important;
    height: auto !important;
    max-width: 140px;
  }
  .vs-spool-card-pct-num {
    font-size: 22px;
  }
}

.vs-spool-card {
  display: flex;
  flex-direction: column;
  padding: 16px 16px 14px;
  cursor: pointer;
  background: var(--vs-surface);
  border: 1px solid var(--vs-hair);
  border-radius: var(--vs-radius-lg);
  box-shadow: var(--vs-shadow-sm);
  transition:
    transform 0.15s,
    border-color 0.15s,
    box-shadow 0.15s;
}
.vs-spool-card:hover {
  transform: translateY(-2px);
  border-color: var(--vs-hair-2);
  box-shadow: var(--vs-shadow);
}
.vs-spool-card--success {
  border-color: rgba(127, 231, 192, 0.18);
}
.vs-spool-card-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.vs-spool-card-id {
  font-family: var(--vs-mono);
  font-size: 10.5px;
  color: var(--vs-muted);
}
.vs-spool-card-hero {
  margin: 10px auto 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: 180px;
}
[data-cardsize="small"] .vs-spool-card-hero {
  min-height: 130px;
}
[data-cardsize="small"] .vs-spool-card-hero svg {
  width: 130px !important;
  height: 130px !important;
}
[data-cardsize="large"] .vs-spool-card-hero {
  min-height: 230px;
}
[data-cardsize="large"] .vs-spool-card-hero svg {
  width: 220px !important;
  height: 220px !important;
}
.vs-spool-card-pct {
  text-align: center;
}
.vs-spool-card-pct-num {
  font-family: var(--vs-sans);
  font-size: 26px;
  font-weight: 700;
  letter-spacing: -0.03em;
  line-height: 1;
  color: var(--vs-text);
  display: inline-flex;
  align-items: baseline;
  gap: 2px;
  font-variant-numeric: tabular-nums;
}
.vs-spool-card-pct-num--danger {
  color: var(--vs-danger);
}
.vs-spool-card-pct-num--warning {
  color: var(--vs-warning);
}
.vs-spool-card-pct-num--success {
  color: var(--vs-success);
}
.vs-spool-card-pct-unit {
  font-family: var(--vs-sans);
  font-size: 11px;
  font-weight: 500;
  color: var(--vs-muted);
}
.vs-spool-card-pct-sub {
  font-family: var(--vs-mono);
  font-size: 10.5px;
  color: var(--vs-muted);
  margin-top: 4px;
}
.vs-spool-card-meta {
  text-align: center;
  margin-top: 10px;
}
.vs-spool-card-name {
  font-family: var(--vs-sans);
  font-size: 13px;
  font-weight: 500;
  color: var(--vs-text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.vs-spool-card-sub {
  font-family: var(--vs-sans);
  font-size: 11px;
  color: var(--vs-muted);
  margin-top: 4px;
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
}
.vs-spool-card-foot {
  margin-top: 12px;
  padding-top: 10px;
  border-top: 1px solid var(--vs-hair);
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 6px;
}
.vs-spool-card-shelf {
  font-family: var(--vs-sans);
  font-size: 11px;
  color: var(--vs-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ====== GALLERY CARD (Spool View) ====== */
.vs-gallery-card {
  position: relative !important;
  /* Borderless at rest (shadow carries the edge); hover paints a ring via
     box-shadow so no border is needed at all. */
  border: none !important;
  transition:
    transform 0.20s cubic-bezier(0.22, 0.61, 0.36, 1),
    box-shadow 0.20s ease !important;
}
.vs-gallery-card:hover {
  transform: translateY(-6px) !important;
  box-shadow:
    0 0 0 1px rgba(80,130,200,0.38),
    inset 0 2px 20px rgba(0,0,0,0.46),
    0 1px 0 rgba(255,255,255,0.05),
    0 18px 44px rgba(0,0,0,0.56),
    0 4px 14px rgba(50,100,180,0.22) !important;
}
/* Actions bar stays laid out; its pieces reveal contextually. The 3-dot stays
   visible (reachable on touch). The shelf location only shows on hover, and the
   status pill shows at rest only for active (non-In-Storage) spools — an
   In-Storage card rests clean and reveals everything on hover. */
.vs-card-actions {
  opacity: 1;
}
.vs-card-loc {
  opacity: 0;
  transition: opacity 0.18s ease;
}
.vs-gallery-card:hover .vs-card-loc {
  opacity: 1;
}
.vs-card-status {
  opacity: 0;
  transition: opacity 0.18s ease;
}
.vs-card-status.is-shown,
.vs-gallery-card:hover .vs-card-status {
  opacity: 1;
}

/* ====== RACK ====== */
.vs-rack-view {
  padding: 20px;
  background: var(--vs-surface);
  border: 1px solid var(--vs-hair);
  border-radius: var(--vs-radius-lg);
  box-shadow: var(--vs-shadow-sm);
}
.vs-rack-row {
  display: flex;
  align-items: flex-end;
  gap: 4px;
  padding: 16px 12px;
  flex-wrap: wrap;
  background: var(--vs-bg-tint);
  border-radius: var(--vs-radius);
  border: 1px solid var(--vs-hair-3);
  margin-bottom: 4px;
}
.vs-rack-plank {
  display: none;
}
.vs-rack-tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  cursor: pointer;
  padding: 0 3px;
}
.vs-rack-tile-label {
  text-align: center;
  line-height: 1.2;
  padding-bottom: 4px;
}
.vs-rack-tile-brand {
  font-size: 10px;
  color: var(--vs-accent);
  font-weight: 500;
}
.vs-rack-tile-mat {
  font-size: 9.5px;
  color: var(--vs-muted);
}

/* ====== SHELVES PAGE ====== */
.vs-shelves-page {
  gap: 12px;
}

/* Subtle text link that toggles between catalog and custom filament pickers. */
.vs-filament-mode-toggle {
  display: inline-block;
  margin-top: 10px;
  background: transparent;
  border: 0;
  padding: 2px 4px;
  font-size: 12px;
  color: var(--vs-faint);
  cursor: pointer;
  text-decoration: none;
}
.vs-filament-mode-toggle:hover {
  color: var(--vs-accent);
  text-decoration: underline;
}

/* Clamp Add Spool picker popovers so long filament names can't push the panel
   wider than the viewport on mobile. Combined with AnchorOrigin=BottomLeft,
   this keeps the panel pinned to the input's left edge instead of overflowing. */
.vs-picker-popover {
  max-width: calc(100vw - 24px);
}
.vs-picker-popover .mud-list-item {
  white-space: normal;
  word-break: break-word;
}

/* Add/Edit Spool dialog — sized in dvh (dynamic viewport height) so the mobile
   browser's address bar doesn't push the Save button off-screen the way 100vh
   does. Top offset shrinks on small screens since the mobile navbar is shorter. */
.vs-spool-dialog {
  top: 70px;
  max-height: calc(100dvh - 90px);
}
@media (max-width: 600px) {
  .vs-spool-dialog {
    top: 12px;
    max-height: calc(100dvh - 24px);
  }
}

/* Refill checkbox sits next to the weight fields — match its label size to
   the dense numeric labels so it doesn't look oversized. */
.vs-refill-cell .mud-checkbox .mud-typography {
  font-size: 0.85rem;
}

/* Weight cluster (Weight / Net / Empty / Refill) is muted by default — these
   fields auto-populate from the catalog defaults once a filament is picked,
   and most users will never need to touch them. Greyed-out until filament
   selection, then a bit brighter (but still subtle) once ready. Focus brings
   the field to full intensity for editing. */
/* No whole-cell opacity: a parent opacity would cap Total's brightness and
   leave it dim gray. Net/Empty are dimmed individually instead (see .vs-w-net
   / .vs-w-empty), so Total reliably stays full white. */

/* The three weight fields always sit on one line and stay compact — each value
   is only a few digits, so they don't need much width. A short "g" adornment
   carries the unit. Net and Empty default from the catalog and rarely change,
   so they're narrow and dimmed; Total is the one edited most, so it gets a
   little more room and full intensity. */
.vs-weight-row {
  display: flex;
  gap: 8px;
  align-items: center;
  justify-content: flex-start;
  flex-wrap: nowrap;
}

.vs-weight-cell {
  display: flex;
  align-items: center;
  order: 2;
  margin-left: auto;
}

/* Detailed-table sortable headers — drive the same persisted sort as the
   dropdown, so clicking one also updates the dropdown selection. */
.vs-th-sort {
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
}
.vs-th-sort:hover {
  color: var(--vs-text);
}
.vs-th-sort.is-active {
  color: var(--vs-accent);
  font-weight: 600;
}

/* Small "Label" link on the Edit Spool identity line. */
.vs-label-link {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  background: none;
  border: none;
  color: var(--vs-accent);
  font-size: 11px;
  cursor: pointer;
  padding: 0;
}
.vs-label-link:hover {
  text-decoration: underline;
}

/* Read-only "inherited from material/variant" specialty chips in the filament
   editor, so an admin sees what's already covered without re-adding it. */
.vs-inherited-spec {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  background: rgba(255, 255, 255, 0.04);
  border: 1px dashed rgba(255, 255, 255, 0.18);
  color: var(--vs-faint);
  padding: 2px 9px;
  border-radius: 6px;
  font-size: 12px;
}
.vs-inherited-spec-src {
  opacity: 0.6;
  font-size: 11px;
}

/* Single-spool QR label popup (Spool Detail + Edit Spool). The label inside
   uses the shared .print-only / .label-* styles, so it both previews here and
   prints cleanly. */
.vs-label-pop-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.6);
  z-index: 1400;
}
.vs-label-pop {
  position: fixed;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  z-index: 1401;
  background: var(--vs-surface);
  border: 1px solid #ffffff14;
  border-radius: 10px;
  padding: 16px 18px;
  width: min(92vw, 320px);
  box-shadow: 0 18px 50px rgba(0, 0, 0, 0.5);
}
.vs-label-pop-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 13px;
  font-weight: 600;
  color: var(--vs-faint);
  margin-bottom: 12px;
}
.vs-label-pop-x {
  background: none;
  border: none;
  color: var(--vs-faint);
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
  padding: 0 4px;
}
.vs-label-pop-preview {
  display: flex;
  justify-content: center;
  padding: 8px;
  background: #0d0d14;
  border-radius: 8px;
}
.vs-label-pop-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 14px;
}

/* Inline out-of-range weight message under the weight row. */
.vs-weight-error {
  margin-top: 6px;
  font-size: 12px;
  color: #ff9a9a;
}
.vs-weight-row > .mud-input-control {
  min-width: 0;
}
.vs-weight-row .vs-w-net,
.vs-weight-row .vs-w-empty {
  flex: 0 1 72px;
  opacity: 0.5;
}
.vs-weight-row .vs-w-net:focus-within,
.vs-weight-row .vs-w-empty:focus-within {
  opacity: 1;
}
.vs-weight-row .vs-w-total {
  flex: 0 1 104px;
  opacity: 1;
}

/* Weights are right-aligned (so Purchase Cost/Date and Net/Empty/Total form
   one easy-to-scan column down the right edge). Refill/AMS sit to their left
   and wrap onto the next line when there isn't room. A little space above
   separates the cluster from the dates. */
.vs-weight-line {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 16px;
  margin-top: 8px;
}
/* Total is the field updated most often — make its label, value, the "g"
   adornment, and underline the brightest of the three so the eye lands there
   first and it's obviously the editable one. */
.vs-weight-row .vs-w-total .mud-input-label,
.vs-weight-row .vs-w-total input,
.vs-weight-row .vs-w-total .mud-input-adornment-text {
  color: #ffffff !important;
  font-weight: 700;
}
.vs-weight-row .vs-w-total .mud-input-slot::before {
  border-bottom-color: rgba(255, 255, 255, 0.55);
}

/* Date + weight fields: right-align the value AND the floating label so the
   numbers/dates form a clean right-edge column with each label over its value.
   The fields carry a visible placeholder (mm/dd/yy, 0) so MudBlazor keeps the
   label floated even when empty — otherwise a right-aligned resting label
   collides with the unit/calendar icon. */
.vs-date-field input,
.vs-weight-row .mud-input-control input {
  text-align: right;
}
.vs-date-field .mud-input-label,
.vs-weight-row .mud-input-control .mud-input-label {
  left: auto;
  right: 0;
  transform-origin: top right;
}

/* Refill / AMS-compatible flags on their own line, right-aligned, smaller and
   more subtle than the field labels above them. */
.vs-spool-flags {
  display: flex;
  gap: 18px;
  flex-wrap: nowrap;
  order: 1;
  opacity: 0.7;
}
.vs-spool-flags .mud-checkbox .mud-typography {
  font-size: 0.78rem;
  color: var(--vs-faint);
}

/* "MATERIALS THIS BRAND OFFERS": a material the brand already has filaments of is
   shown as a DISABLED (locked) checkbox. MudBlazor's disabled color renders it
   nearly invisible on light/medium themes, so keep locked materials clearly
   readable — muted label + a visible accent checkmark to read as "on, locked". */
html[data-mode="light"] .vs-mat-check .mud-typography { color: var(--vs-text-2) !important; }
html[data-mode="light"] .vs-mat-check.mud-disabled,
html[data-mode="light"] .vs-mat-check .mud-disabled { opacity: 1 !important; }
html[data-mode="light"] .vs-mat-check.mud-disabled .mud-typography,
html[data-mode="light"] .vs-mat-check .mud-disabled .mud-typography { color: var(--vs-muted) !important; }
/* The locked checkmark is drawn via SVG fill (MudBlazor's disabled palette is a
   dark-theme color here), so force both fill + color to the theme accent. */
html[data-mode="light"] .vs-mat-check.mud-disabled svg,
html[data-mode="light"] .vs-mat-check .mud-disabled svg {
  color: var(--vs-accent) !important;
  fill: var(--vs-accent) !important;
}
html[data-mode="light"] .vs-mat-check .mud-disabled.mud-icon-button { color: var(--vs-accent) !important; }

/* "+ Add notes" reveal link — quiet text button shown when Notes is collapsed. */
.vs-add-notes-link {
  background: none;
  border: none;
  padding: 2px 0;
  color: var(--vs-accent);
  font-size: 12px;
  cursor: pointer;
}
.vs-add-notes-link:hover {
  text-decoration: underline;
}

/* Dialog action row — Archive/Trash (secondary, destructive) on the far left;
   Cancel/Save (primary) on the far right, with Save furthest out so it's the
   easiest target. Kept apart so a stray tap can't hit a destructive action.
   When the row is too narrow, the primary group wraps below the secondary. */
.vs-dialog-actions {
  display: flex;
  align-items: center;
  gap: 8px 16px;
  flex-wrap: wrap;
}
.vs-dialog-actions-secondary {
  display: flex;
  align-items: center;
  gap: 8px;
}
.vs-dialog-actions-primary {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 8px;
}

/* Purchase Cost / Date are entered once and rarely revisited, so keep them
   subtle by default; they brighten to full intensity on focus for editing. */
.vs-purchase-field {
  opacity: 0.6;
  transition: opacity 0.2s ease;
}
.vs-purchase-field:focus-within {
  opacity: 1;
}

/* Read-only Filament line: no label, quieter helper text. */
.vs-filament-readonly .mud-input-helper-text {
  font-size: 0.7rem;
  opacity: 0.55;
}

/* Notes is an afterthought field — render it a touch smaller and dimmer than
   the primary inputs so it doesn't compete for attention. */
.vs-notes-field {
  opacity: 0.72;
}
.vs-notes-field .mud-input-slot,
.vs-notes-field input,
.vs-notes-field textarea {
  font-size: 0.82rem;
}

/* Spool card pagination bar — full numbered pages on desktop, a compact
   "Page X / N" with chevrons on mobile (numbered MudPagination is too long
   for narrow viewports even with first/last hidden). */
.vs-spool-pagination {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  margin-top: 24px;
  border-top: 1px solid rgba(255, 255, 255, 0.04);
  padding-top: 12px;
  opacity: 0.78;
}
.vs-pagination-mini {
  display: none;
}
.vs-pagination-mini-label {
  font-size: 13px;
  color: rgba(218, 232, 248, 0.78);
  font-variant-numeric: tabular-nums;
  min-width: 48px;
  text-align: center;
}
@media (max-width: 600px) {
  .vs-pagination-full {
    display: none;
  }
  .vs-pagination-mini {
    display: flex;
    align-items: center;
    gap: 2px;
  }
  .vs-spool-pagesize {
    display: none;
  }
}

/* The card-view pagesize MudSelect is a tiny 12/24/48 picker. In a flex row
   MudBlazor lets the input control stretch to fill, so pin both the control
   and its inner input/slot to 72px (the inline Style on the root alone doesn't
   reach the inner .mud-input). */
.vs-spool-pagesize {
  flex: 0 0 auto;
  width: 72px !important;
}
.vs-spool-pagesize .mud-input-control,
.vs-spool-pagesize .mud-input-slot,
.vs-spool-pagesize .mud-select-input,
.vs-spool-pagesize input {
  width: 72px !important;
  min-width: 0 !important;
}
/* Without constraining the popover panel too, MudBlazor lets the dropdown
   match ancestor width, making the menu look like a giant list. */
.vs-pagesize-popover.mud-popover {
  min-width: 0 !important;
  width: 96px !important;
}

/* "Show depleted spools" — was a chunky MudButton, now a quiet text link so
   it doesn't compete with the pagination above it on mobile. */
.vs-show-depleted-row {
  display: flex;
  justify-content: center;
  margin-top: 16px;
}
.vs-show-depleted-link {
  background: transparent;
  border: 0;
  padding: 4px 10px;
  font-size: 12px;
  color: var(--vs-faint);
  cursor: pointer;
  text-decoration: none;
}
.vs-show-depleted-link:hover {
  color: var(--vs-accent);
  text-decoration: underline;
}

/* Spool table — combined "Filament Name" cell. Brand Material Variant Name
   all read as one bold headline. */
/* Detailed-view name split: muted brand/material prefix + bold name (the
   color), no dot. Inherits the title's 15px size; wraps naturally. */
.vs-fil-prefix {
  font-weight: 400;
  color: #8a8aa8;
  margin-right: 0.35em;
}
.vs-fil-name {
  font-weight: 700;
}
/* Detailed table: borrow the compact header's quiet, low-profile look so it
   stops eating vertical space. */
.vs-detailed-table thead th {
  padding-top: 4px !important;
  padding-bottom: 4px !important;
  font-size: 10px !important;
  font-weight: 600;
  text-transform: uppercase !important;
  letter-spacing: 0.05em;
  color: var(--vs-muted) !important;
}
.vs-detailed-table thead th .mud-table-sort-label {
  font-size: 10px !important;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--vs-muted) !important;
}
.vs-detailed-table thead th .mud-table-sort-label:hover {
  color: var(--vs-info) !important;
}
.vs-detailed-table thead th .mud-table-sort-label .mud-table-sort-label-icon {
  font-size: 14px !important;
}
/* Secondary detailed-table columns (dates, cost, age, cost/g) read smaller and
   quieter than the filament name, which stays the hero. */
.vs-detailed-table td.vs-cell-sm {
  font-size: 12px;
  color: #b4b4c8;
}
/* Right-align numeric columns (Cost, Weight) and the Remaining grams label so
   the digits line up for easy scanning. */
.vs-detailed-table th.vs-num,
.vs-detailed-table td.vs-num {
  text-align: right;
}
.vs-detailed-table .vs-rem-grams {
  justify-content: flex-end;
}
/* Match Compact's quiet header: hide MudBlazor's always-on sort arrows. The
   sorted column keeps its arrow; the rest reveal only on hover. */
.vs-detailed-table thead th .mud-table-sort-label-icon {
  opacity: 0 !important;
  transition: opacity 0.12s;
}
.vs-detailed-table thead th:hover .mud-table-sort-label-icon {
  opacity: 0.4 !important;
}
.vs-detailed-table thead th[aria-sort] .mud-table-sort-label-icon {
  opacity: 1 !important;
}
.vs-spool-title {
  font-size: 15px;
  font-weight: 600;
  color: var(--vs-text);
  letter-spacing: -0.01em;
  line-height: 1.35;
  white-space: normal;
  word-break: break-word;
}

/* Spool detail page — three sections side-by-side on desktop in order
   Hero | Status | Details. On tablets/mobile, Hero and Status pair up on
   the top row (the spool + status are what users need to see first) and
   Details wraps below to full width. Markup order matches both layouts —
   no `order:` overrides needed. */
.vs-detail-row {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  margin-bottom: 16px;
  align-items: stretch;
}
.vs-detail-section {
  flex: 1 1 0;
  min-width: 0;
}
.vs-detail-section--hero {
  display: flex;
  justify-content: center;
  align-items: flex-start;
}
@media (max-width: 900px) {
  .vs-detail-section--hero { flex: 1 1 calc(50% - 8px); }
  .vs-detail-section--status { flex: 1 1 calc(50% - 8px); }
  .vs-detail-section--details { flex: 1 1 100%; }
}

/* Hero spool — recessed circular cavity scaled to fit its flex column. The
   inner SpoolFaceView SVG is capped at the wrapper's max content box via CSS
   so it scales down on narrower viewports. */
.vs-spool-hero {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 240px;
  height: 240px;
  max-width: 100%;
  border-radius: 50%;
  /* Transparent so the spool's punched bore reads as a real see-through hole
     to the page/theme background (the flange covers the rest of this box, so the
     old dark "well" was only ever visible through the core hole). */
  background: transparent;
}
.vs-spool-hero svg {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
}
@media (max-width: 480px) {
  .vs-spool-hero {
    width: 170px;
    height: 170px;
  }
}

/* Spool detail — action-first grid. Desktop: status+weight card and details
   stack on the left, the big render rides a sticky right rail. Mobile: one
   column ordered action -> render -> details (collapsed), History below. */
.vs-sd-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 340px;
  grid-template-areas:
    "action hero"
    "details hero";
  gap: 16px;
  margin-bottom: 16px;
  align-items: start;
}
.vs-sd-action {
  grid-area: action;
  min-width: 0;
}
.vs-sd-details {
  grid-area: details;
  min-width: 0;
}
/* Cap the Ownership/Specs/Settings label-value rows so the label and its value
   don't stretch to opposite edges of a wide details panel (unreadable on big
   screens). Below 560px it falls back to full width. The panel header uses an
   inline justify-content (not this class), so it stays full-width. */
.vs-sd-details .justify-space-between { max-width: 560px; }
.vs-sd-side {
  grid-area: hero;
  position: sticky;
  top: 16px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
}

/* Spool Detail section cards: one consistent surface + hairline + soft radius
   so every section box matches (Status / Prints / Notes / History). */
.vs-section-card {
  background: var(--vs-surface);
  border: 1px solid var(--vs-hair-2);
  border-radius: var(--vs-radius);
}
/* Section header label: leading icon + uppercase, shared across every card. */
.vs-section-title {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--vs-muted);
}
.vs-section-title .mud-icon-root {
  font-size: 15px;
}

/* Reusable pegboard panel surface (the Studio widget-card look) */
.vs-pegboard-card {
  background-color: rgba(12, 16, 26, 0.84);
  background-image:
    linear-gradient(180deg, rgba(255,255,255,0.018) 0%, transparent 40%, rgba(0,0,0,0.10) 100%),
    radial-gradient(circle, rgba(200,215,240,0.030) 1.0px, rgba(200,215,240,0.014) 1.7px, transparent 1.7px);
  background-size: auto, 20px 20px;
  /* Inset shadow alone defines the panel edge; no border at all */
  border: none;
  box-shadow: inset 0 0 30px rgba(0, 0, 0, 0.20);
}

/* Identity pills under the spool title (brand swatch + linked taxonomy) */
.vs-sd-pill {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  background: var(--vs-surface);
  border: 1px solid var(--vs-hair-2);
  border-radius: 20px;
  padding: 6px 14px;
  font-size: 13px;
  color: var(--vs-text-2);
  text-decoration: none;
}
.vs-sd-pill:hover {
  border-color: var(--vs-accent);
  color: var(--vs-text);
}
.vs-sd-pill--accent {
  border-color: var(--vs-accent);
  color: var(--vs-accent);
  font-weight: 600;
}
.vs-sd-pill--accent:hover {
  color: var(--vs-text);
}

/* Physical location, pinned under the render */
.vs-sd-loc {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  flex-wrap: nowrap;
  gap: 8px;
  width: 100%;
  max-width: 300px;
  text-align: left;
  background: var(--vs-surface);
  border: 1px solid var(--vs-hair-2);
  border-radius: 12px;
  padding: 9px 14px;
  font-size: 13px;
  font-weight: 600;
  color: var(--vs-text);
}
.vs-sd-loc > .mud-icon-root {
  flex-shrink: 0;
}
.vs-sd-loc-sep {
  color: var(--vs-faint);
  font-weight: 400;
}
.vs-sd-loc-text {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
}
.vs-sd-loc-shelf {
  font-size: 12px;
  color: var(--vs-muted);
}
.vs-sd-home {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
  margin-top: 5px;
  font-size: 12px;
  color: var(--vs-muted);
  background: none;
  border: none;
  font-family: inherit;
  cursor: pointer;
  transition: color 0.15s ease;
}
.vs-sd-home:hover {
  color: var(--vs-blue);
}

/* Location as a physical nesting tree: Room -> Storage Unit -> Shelf, with
   CSS-drawn elbow connectors (no monospace box-glyphs). The shelf is the
   actual resting spot, so it carries the strongest weight. */
.vs-loc-tree {
  display: flex;
  flex-direction: column;
  gap: 3px;
  width: 100%;
  max-width: 300px;
  text-align: left;
  background: var(--vs-surface);
  border: 1px solid var(--vs-hair-2);
  border-radius: 12px;
  padding: 10px 14px;
  font-size: 13px;
  color: var(--vs-text);
}
.vs-loc-node {
  display: flex;
  align-items: center;
  gap: 7px;
  font-weight: 600;
}
.vs-loc-node .mud-icon-root {
  color: var(--vs-info);
  flex-shrink: 0;
}
.vs-loc-l1,
.vs-loc-l2 {
  position: relative;
  font-weight: 500;
  color: var(--vs-text-2);
}
.vs-loc-l1 {
  padding-left: 20px;
}
.vs-loc-l2 {
  padding-left: 40px;
  font-weight: 600;
  color: var(--vs-text);
}
.vs-loc-l1::before,
.vs-loc-l2::before {
  content: "";
  position: absolute;
  top: -5px;
  width: 9px;
  height: calc(50% + 5px);
  border-left: 1.5px solid var(--vs-hair-2);
  border-bottom: 1.5px solid var(--vs-hair-2);
  border-bottom-left-radius: 5px;
}
.vs-loc-l1::before {
  left: 7px;
}
.vs-loc-l2::before {
  left: 27px;
}
/* Shelf name can run up to 60 chars; keep the tree tidy and reveal the full
   name on hover (shelves carry only a Name field, no separate description). */
.vs-loc-shelf-name {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 220px;
}

/* Sticky-rail identity placard — keeps the filament name visible as you scroll
   the long left column past the page title. */
.vs-sd-identity {
  text-align: center;
  margin-top: 10px;
  line-height: 1.25;
}
.vs-sd-identity-name {
  font-size: 15px;
  font-weight: 700;
  color: var(--vs-text);
}
.vs-sd-identity-sub {
  font-size: 12px;
  color: var(--vs-muted);
  margin-top: 1px;
}

/* "Spool 2 of 4" badge above the render + per-spool breakdown below it */
.vs-sd-count {
  font-size: 13px;
  font-weight: 700;
  color: var(--vs-text);
  background: var(--vs-surface);
  border: 1px solid var(--vs-hair-2);
  border-radius: 20px;
  padding: 7px 16px;
}
.vs-sd-sibs {
  width: 100%;
  max-width: 300px;
}
.vs-sd-sib {
  display: block;
  background: var(--vs-surface);
  border: 1px solid var(--vs-hair-2);
  border-radius: 10px;
  padding: 8px 12px 9px;
  margin-top: 6px;
  font-size: 13px;
  color: var(--vs-text-2);
  text-decoration: none;
}
.vs-sd-sib-row {
  display: flex;
  align-items: center;
  gap: 12px;
}
/* Thin remaining-filament bar under each sibling row */
.vs-sd-sib-bar {
  display: block;
  height: 4px;
  margin-top: 7px;
  border-radius: 2px;
  background: rgba(255, 255, 255, 0.07);
  overflow: hidden;
}
.vs-sd-sib-bar > span {
  display: block;
  height: 100%;
  border-radius: 2px;
}
/* Remaining-filament fill bars: the fill rounds itself, so nothing relies on
   overflow clipping. .vs-fillbar is the small list-row size; .vs-sd-wbar is
   the large weight-panel preview bar on Spool Detail. */
.vs-fillbar,
.vs-sd-wbar {
  display: block;
  height: 6px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.07);
}
.vs-sd-wbar {
  height: 12px;
  /* Faint gray full-capacity track so a partial bar reads against "full" —
     theme-aware (shows on light themes where the white-tint base vanishes). */
  background: color-mix(in srgb, var(--vs-faint) 18%, transparent);
}
.vs-fillbar > span,
.vs-sd-wbar > span {
  display: block;
  height: 100%;
  border-radius: 999px;
  transition: width 0.25s ease;
}
.vs-sd-sib:hover {
  border-color: var(--vs-accent);
}
.vs-sd-sib-name {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.vs-sd-sib-label {
  display: inline-flex;
  align-items: center;
  gap: 7px;
}
/* Where this spool currently lives (gear / shelf / staging) — a quiet second line. */
.vs-sd-sib-loc {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  min-width: 0;
  font-size: 11px;
  font-weight: 400;
  color: var(--vs-muted);
}
.vs-sd-sib-loc .mud-icon-root { color: var(--vs-faint); flex-shrink: 0; }
.vs-sd-sib-loc-text {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* The spool you're currently viewing: accent ring + tint so it's unmistakable
   among its siblings, not just a faint outline. */
.vs-sd-sib.is-current {
  border-color: var(--vs-accent);
  background: var(--vs-accent-soft);
  box-shadow: 0 0 0 1px var(--vs-accent);
  color: var(--vs-text);
  font-weight: 600;
}
.vs-sd-sib-viewing {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--vs-blue);
  background: rgba(99, 153, 222, 0.14);
  border: 1px solid var(--vs-blue);
  border-radius: 999px;
  padding: 1px 7px;
}
/* Prints empty state — teach the feature instead of a flat "nothing here". */
.vs-printlog-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  text-align: center;
  padding: 16px 8px 6px;
}
.vs-printlog-empty-text {
  font-size: 13px;
  color: var(--vs-text-2);
}
.vs-printlog-empty-eg {
  font-size: 12px;
  color: var(--vs-muted);
  margin-top: 3px;
  max-width: 320px;
}

/* Spool Details tab strip — lightweight buttons matching the page's controls,
   not heavyweight MudTabs chrome. */
.vs-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  border-bottom: 1px solid var(--vs-hair-2);
  margin-bottom: 4px;
}
.vs-tab {
  appearance: none;
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  padding: 7px 12px;
  font-family: inherit;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--vs-muted);
  cursor: pointer;
  white-space: nowrap;
  transition: color 0.15s, border-color 0.15s;
}
.vs-tab:hover {
  color: var(--vs-text-2);
}
.vs-tab.is-active {
  color: var(--vs-text);
  border-bottom-color: var(--vs-accent);
}
/* Sub-heading inside a tab panel (e.g. "Activity" within Ownership). */
.vs-tab-subhead {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--vs-faint);
  margin: 14px 0 8px;
}

/* Auto-save confirmation dot (brief, subtle). */
.vs-save-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--vs-success);
  box-shadow: 0 0 0 3px rgba(124, 200, 160, 0.18);
}

/* Weight-panel burn-down sparkline (real consumption over time). */
.vs-wchart {
  flex-shrink: 0;
  line-height: 0;
  opacity: 0.92;
  display: flex;
  align-items: stretch;
  gap: 4px;
}
.vs-wchart svg {
  display: block;
}
/* Tiny y-axis labels beside the burn-down sparkline (full weight top, 0 bottom). */
.vs-wchart-axis {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  text-align: right;
  font-size: 9px;
  line-height: 1;
  color: var(--vs-faint);
  padding: 2px 0;
}

/* Total grams across all spools of this filament, sitting under the cards. */
.vs-sd-sibs-total {
  margin-top: 8px;
  text-align: center;
  font-size: 12px;
  font-weight: 600;
  color: var(--vs-muted);
}
/* Collapsed summary row for archived siblings — one click reveals their cards. */
.vs-sd-sibs-archived-toggle {
  display: flex;
  align-items: center;
  gap: 6px;
  width: 100%;
  margin-top: 8px;
  padding: 7px 10px;
  background: transparent;
  border: 1px dashed var(--vs-hair-2);
  border-radius: 10px;
  color: var(--vs-muted);
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.12s ease, border-color 0.12s ease;
}
.vs-sd-sibs-archived-toggle:hover {
  background: var(--vs-surface);
  border-color: var(--vs-hair);
}
.vs-sd-sibs-archived-toggle .mud-icon-root { color: var(--vs-faint); flex-shrink: 0; }
.vs-sd-sibs-archived-kg {
  margin-left: auto;
  color: var(--vs-faint);
  font-weight: 700;
}
.vs-sd-sib.is-empty {
  opacity: 0.6;
}
.vs-sd-sib.is-empty:hover {
  opacity: 0.9;
}
@media (max-width: 900px) {
  .vs-sd-grid {
    grid-template-columns: 1fr;
    grid-template-areas:
      "action"
      "hero"
      "details";
  }
  .vs-sd-side {
    position: static;
  }
}

/* Segmented status control — one cohesive input, selected segment colored */
.vs-sd-statusbar {
  display: flex;
  flex-wrap: wrap;
  border: 1px solid var(--vs-hair-2);
  border-radius: 12px;
  overflow: hidden;
}
.vs-sd-statusseg {
  flex: 1 1 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  background: transparent;
  border: none;
  border-right: 1px solid var(--vs-hair-2);
  color: var(--vs-muted);
  padding: 10px 10px;
  font-family: inherit;
  font-size: 12.5px;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
  transition: color 0.15s, background-color 0.15s;
}
.vs-sd-statusseg:last-child {
  border-right: none;
}
.vs-sd-statusseg:hover {
  color: var(--vs-text);
  background: rgba(255, 255, 255, 0.03);
}
.vs-spool-hero--big {
  width: 300px;
  height: 300px;
}
@media (max-width: 480px) {
  .vs-spool-hero--big {
    width: 215px;
    height: 215px;
  }
}

/* One-tap status chips (current one carries its status color inline) */
.vs-sd-status-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.vs-sd-status-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: transparent;
  border: 1px solid var(--vs-hair-2);
  color: var(--vs-muted);
  border-radius: 20px;
  padding: 9px 15px;
  font-family: inherit;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  transition: border-color 0.15s, color 0.15s;
}
.vs-sd-status-chip:hover {
  border-color: var(--vs-accent);
  color: var(--vs-text);
}
.vs-sd-status-chip.is-active {
  border-color: transparent;
}

/* Darker band headers for the Details groups (FILAMENT / OWNERSHIP / …).
   They're buttons: each group expands/collapses on tap. */
.vs-sd-grouphead {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: calc(100% + 12px);
  background: rgba(4, 8, 16, 0.6);
  border: none;
  border-radius: 8px;
  padding: 7px 10px;
  margin: 18px -6px 10px;
  font-family: inherit;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  text-align: left;
  color: var(--vs-muted);
  box-shadow: inset 0 0 12px rgba(0, 0, 0, 0.25);
  cursor: pointer;
}
.vs-sd-grouphead:hover {
  color: var(--vs-text);
}
/* Group title with its little icon */
.vs-sd-ghead-title {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
}
/* At-a-glance summary baked into each group header (so most stay collapsed) */
.vs-sd-ghead-sum {
  flex: 1;
  min-width: 0;
  margin-left: auto;
  text-align: right;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  text-transform: none;
  letter-spacing: 0.01em;
  font-size: 12px;
  font-weight: 500;
  color: var(--vs-text-2);
  padding-right: 8px;
}

/* Weight entry: it's THE number on this page — render it big and bold */
.vs-weight-input input {
  font-size: 20px !important;
  font-weight: 600;
}
/* Weight field + its trailing controls. The save checkmark is the field's own
   end adornment; the discard X is parked just inside, to its left, so both sit
   together inside the box instead of the X floating off to the right. */
.vs-weight-field-wrap {
  position: relative;
  display: block;
  width: 100%;
  max-width: 240px;
}
.vs-weight-field-wrap .vs-weight-input {
  width: 100%;
  max-width: none;
}
/* Descendant selector (.vs-weight-field-wrap .vs-weight-discard) so it outranks
   MudBlazor's .mud-button-root { position: relative } — otherwise the X drops into
   normal flow below the field instead of sitting inside it, just left of the check. */
.vs-weight-field-wrap .vs-weight-discard {
  position: absolute;
  right: 52px;
  top: 50%;
  transform: translateY(-50%);
  z-index: 3;
}
/* Make room so the typed number never slides under the two trailing icons. */
.vs-weight-field-wrap.has-discard .vs-weight-input input {
  padding-right: 84px !important;
}

/* Spool notes textarea: short by default, with a visible resize grip so it's
   obviously stretchable (the native corner handle is easy to miss). */
.vs-sd-notes-area {
  /* rows="2" sets the real height; without this, .vs-input--area's
     min-height: 120px wins and the box opens four lines tall. */
  min-height: 0;
  background-image: linear-gradient(
    135deg,
    transparent 0 60%,
    var(--vs-muted) 60% 66%,
    transparent 66% 74%,
    var(--vs-muted) 74% 80%,
    transparent 80% 88%,
    var(--vs-muted) 88% 94%,
    transparent 94%
  );
  background-repeat: no-repeat;
  background-position: right 3px bottom 3px;
  background-size: 13px 13px;
}

/* Weight panel — recessed surface so the weight workflow reads as one unit */
.vs-sd-weightpanel {
  background: rgba(4, 8, 16, 0.35);
  border: 1px solid rgba(var(--vs-tint), 0.08);
  border-radius: 12px;
  padding: 12px 14px;
  margin-top: 18px;
}
/* Weight panel = two columns: a tall side-spool render (left) + the weight
   controls (right). The render fills the panel height as the visual anchor. */
.vs-sd-weight2col {
  display: flex;
  gap: 18px;
  align-items: stretch;
}
.vs-sd-weight-render {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2px 2px 2px 0;
}
.vs-sd-weight-main {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 12px;
}
/* Phones: stays two columns (the render is narrow), but let the input fill. */
@media (max-width: 560px) {
  .vs-sd-weight2col { gap: 12px; }
  .vs-sd-weight-main .vs-weight-input { max-width: none; }
  .vs-sd-weight-main .vs-weight-field-wrap { max-width: none; }
}

/* Collapsible card header (Details) */
.vs-sd-cardhead {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  font-family: inherit;
}

/* Spool face icon sits to the left of the CFN in both Simple and Detailed
   table views, locking the row's identity at a glance. */
.vs-spool-title-row {
  display: flex;
  align-items: center;
  gap: 12px;
}
.vs-spool-title-row > .vs-spool-title {
  flex: 1 1 auto;
  min-width: 0;
}
.vs-spool-specialty-chips {
  display: flex;
  gap: 4px;
  flex-wrap: wrap;
  justify-content: flex-end;
}

/* Specialty pill (SpecialtyTag.razor). Shape only — colors come from the
   canonical Type via SpecialtyTypeColor and are applied inline. */
.vs-spec-tag {
  display: inline-flex;
  align-items: center;
  padding: 2px 10px;
  border-radius: 20px;
  font-size: 12px;
  line-height: 1.5;
  white-space: nowrap;
}
.vs-spec-tag--clickable {
  cursor: pointer;
  transition: filter 0.15s, background 0.15s;
}
.vs-spec-tag--clickable:hover {
  filter: brightness(1.2);
}
.vs-spec-tag--active {
  font-weight: 600;
}
/* Inherited from the filament's material/variant (not set on the filament
   itself) — shown with a dashed border so admins can tell it apart. */
.vs-spec-tag--inherited {
  border-style: dashed !important;
  opacity: 0.7;
}
/* Light themes: the baked pill text is a pale hue tuned for dark backgrounds, so
   it washes out on a light surface. Re-derive a dark, hue-true text plus a touch
   stronger fill from the --spec-rgb the pill carries (per-type color preserved).
   !important beats the element's inline style; dark themes keep the inline. */
html[data-mode="light"] .vs-spec-tag {
  background: rgba(var(--spec-rgb), 0.16) !important;
  border-color: rgba(var(--spec-rgb), 0.45) !important;
  color: color-mix(in srgb, rgb(var(--spec-rgb)), #16161c 58%) !important;
}
html[data-mode="light"] .vs-spec-tag--active {
  background: rgba(var(--spec-rgb), 0.26) !important;
}

/* Right-align numeric input text (e.g. variant Print Settings min/max). */
.vs-num-right input { text-align: right; }

/* Derived-band preview chip next to an exact datasheet input in the Material editor. */
.vs-band-chip { font-size: 13px; font-weight: 600; color: var(--vs-info); }

/* Full-width one-line hint under a row of the Material-editor engineering-specs grid.
   Muted (not blue) so a whole column of them stays easy on the eye — only the derived
   -band chips to the right of each field carry the info-blue accent. */
.vs-spec-hint { grid-column: 1 / -1; font-size: 11px; color: var(--vs-faint); line-height: 1.3; margin: -3px 0 5px; }

/* Global copies of the ScalePicker label/head/hint. The component's own styles live in
   ScalePicker.razor.css and are CSS-isolation-scoped, so the hand-rolled field rows in
   the Material editor (Shrinkage, Recommended max speed) that reuse these class names
   need a global definition to match. */
.vs-scalepick { margin-bottom: 2px; }
.vs-scalepick-head { display: flex; align-items: baseline; gap: 8px; margin-bottom: 5px; }
.vs-scalepick-label { font-size: 13px; font-weight: 600; color: var(--vs-text); }
.vs-scalepick-hint { font-size: 11px; color: var(--vs-faint); margin-top: 4px; line-height: 1.4; }

/* Material editor: a control in the left column with its description to the right, so
   single-pick dropdowns stack in one tidy column instead of a gappy multi-column grid. */
.vs-field-rows { display: grid; grid-template-columns: minmax(0, 210px) 1fr; gap: 12px 16px; align-items: center; }
.vs-field-hint { font-size: 12px; color: var(--vs-muted); line-height: 1.45; }

/* Sticky Save/Cancel bar for the (long) Material editor modal, so the actions stay
   reachable without scrolling back to the bottom. Pinned to the panel's bottom edge,
   spanning its 24px padding, with a matching surface so content scrolls under it. */
.vs-material-editor .vs-modal-actions {
  position: sticky;
  bottom: -24px;
  margin: 16px -24px -24px;
  padding: 14px 24px;
  background: var(--mud-palette-surface);
  border-top: 1px solid var(--vs-hair-2);
  z-index: 2;
}

/* ── Reusable admin-editor chrome ─────────────────────────────────────────────
   Apply to any .vs-modal-panel: a dark sticky header (title + ID chip), a meta box
   directly under it, and a sticky Save/Cancel footer. Negative margins bleed the
   bars to the panel's 24px padding edges. Add .vs-editor to the panel for the
   compact (Material-style) field font. */
.vs-editor-head {
  position: sticky; top: -24px; z-index: 5;
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  margin: -24px -24px 0; padding: 13px 24px;
  /* Themed: the theme's ink colour as the bar, its surface colour as the text —
     a dark header on light themes that stays on-palette instead of a fixed slate. */
  background: var(--vs-text); color: var(--vs-surface);
  border-bottom: 1px solid rgba(127, 127, 127, 0.28);
}
.vs-editor-title { font-size: 1.02rem; font-weight: 600; color: var(--vs-surface); }
.vs-editor-idchip {
  font-family: var(--vs-mono); font-size: 12px; font-weight: 700; color: var(--vs-surface);
  padding: 2px 9px; border-radius: 8px; white-space: nowrap;
  background: transparent; border: 1px solid currentColor;
}
.vs-editor-metabox {
  display: flex; flex-wrap: wrap; gap: 3px 18px;
  margin: 0 -24px 14px; padding: 7px 24px;
  background: rgba(127, 127, 150, 0.08);
  border-bottom: 1px solid var(--vs-hair-2);
  font-size: 11px; color: var(--vs-muted);
}
.vs-editor-metabox b { color: var(--vs-text); font-weight: 600; }
.vs-editor-foot {
  position: sticky; bottom: -24px; z-index: 2;
  display: flex; justify-content: flex-end; gap: 8px;
  margin: 16px -24px -24px; padding: 12px 24px;
  background: var(--mud-palette-surface);
  border-top: 1px solid var(--vs-hair-2);
}
.vs-editor .mud-input,
.vs-editor .mud-input-slot,
.vs-editor .mud-input-label,
.vs-editor .mud-select .mud-select-input,
.vs-editor .mud-checkbox label,
.vs-editor .mud-checkbox .mud-typography { font-size: 0.78rem !important; }

/* Drop the reserved empty helper-text row so fields without a hint (Name, Slug,
   Scientific name) don't render extra-tall. */
.vs-editor .mud-input-helper-text:empty { display: none; }

/* Small editors reusing .vs-editor keep their plain utility action row — make that
   direct-child row a sticky footer too, so every editor gets the sticky Save/Cancel. */
.vs-editor > .d-flex.justify-end {
  position: sticky; bottom: -24px; z-index: 2;
  margin: 16px -24px -24px; padding: 12px 24px;
  background: var(--mud-palette-surface); border-top: 1px solid var(--vs-hair-2);
}

/* Compact field: shrink the label and input text together (e.g. Length). */
.vs-small-field input,
.vs-small-field label,
.vs-small-field .mud-input-helper-text { font-size: 0.78rem !important; }

/* Variant editor: dim the helper text under fields so focus stays on values. */
#variant-edit-panel .mud-input-helper-text { color: #5a5a70 !important; }

/* De-emphasize the spec fields (smaller + slightly dimmer); Brand/Material/
   Variant Name keep full prominence via .vs-keep. */
.vs-secondary-fields input,
.vs-secondary-fields .mud-input-label { font-size: 0.82rem; }
.vs-secondary-fields input { color: #a6a6bc; }
.vs-secondary-fields .mud-input-label { color: #76768e; }
.vs-secondary-fields .vs-keep input { font-size: 1rem; color: var(--vs-text); }
.vs-secondary-fields .vs-keep .mud-input-label { font-size: 1rem; color: #b4b4c6; }

/* Variant editor sections: a subtle raised panel to separate Specialties etc. */
.vs-section { background: var(--vs-surface); border: 1px solid var(--vs-hair-2); border-radius: 8px; padding: 14px 16px; }

/* Variants table: one notch smaller rows, and keep Brand/Material/Variant on a
   single line (Specialties cell still wraps its pills via flex). */
.vs-variants-table th,
.vs-variants-table td { font-size: 0.74rem; }
.vs-variants-table td .mud-typography { font-size: 0.74rem; }
.vs-variants-table td:nth-child(1),
.vs-variants-table td:nth-child(2),
.vs-variants-table td:nth-child(3) { white-space: nowrap; }

/* Subtle vertical divider between Print Settings and the flags/drying column
   in the variant editor. Hidden on phones, where the two columns stack. */
.vs-printcol-divider { display: none; }
@media (min-width: 600px) {
  .vs-printcol-divider {
    display: block;
    align-self: stretch;
    width: 1px;
    background: #2a2a3e;
  }
}

/* Catalog table sits on a surface card (like the Spools tables) so it lifts off
   the page bg instead of blending in. */
.vs-pf-card {
  background: var(--vs-surface);
  border: 1px solid var(--vs-hair-2);
  border-radius: 8px;
}
/* Public filament table: highlight the row under the cursor. */
.vs-pf-row { transition: background-color 0.12s, box-shadow 0.12s; }
/* Subtle filament-color accent on hover: a thin left bar tinted with the row's
   primary color (falls back to the standard accent). Hover-only so it doesn't
   distract while scanning. */
.vs-pf-row:hover {
  background: rgba(120,152,191,0.10);
  box-shadow: inset 3px 0 0 var(--row-accent, var(--vs-accent)), inset -3px 0 0 var(--row-accent, var(--vs-accent));
}
/* Filament-table search field with a leading magnifier icon. */
.vs-pf-search {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 1;
  min-width: 200px;
  background: var(--vs-bg);
  border: 1px solid var(--vs-hair-2);
  border-radius: 8px;
  padding: 0 12px;
  color: var(--vs-muted);
}
.vs-pf-search input {
  flex: 1;
  background: none;
  border: none;
  outline: none;
  padding: 9px 0;
  color: var(--vs-text);
  font-size: 14px;
}
/* Colors column is redundant with the mini spool on small screens. */
@media (max-width: 640px) {
  .vs-col-colors { display: none; }
}

/* Sortable header affordance: faint up/down glyph, accent when active. */
.vs-sort { font-size: 10px; color: var(--vs-muted); margin-left: 2px; }
.vs-sort.is-active { color: var(--vs-info); }
/* "Yours" indicator dot for Brand/Material cells on Browse All. */
.vs-mine-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--vs-info);
  box-shadow: 0 0 0 2px rgba(126, 184, 247, 0.18);
  flex-shrink: 0;
}
/* Tiny square brand swatch for scannability. */
.vs-brand-sw {
  width: 10px;
  height: 10px;
  border-radius: 2px;
  border: 1px solid rgba(255,255,255,0.2);
  flex-shrink: 0;
}

/* Small badge shown when a field's value overrides an inherited default. */
.vs-override-badge {
  display: inline-block;
  font-size: 6.5px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: #9a875f;
  background: rgba(208,168,95,0.07);
  border: 1px solid rgba(208,168,95,0.22);
  border-radius: 3px;
  padding: 0 3px;
  margin-top: 2px;
  cursor: pointer;
}
.vs-override-badge:hover { background: rgba(208,168,95,0.18); color: #d0a85f; }

/* MudTable stacked-on-mobile mode — Simple and Detailed views.
   Each row becomes a card with label/value pairs. DataLabel on each MudTd
   feeds the ::before pseudo-element. Without this CSS the labels are invisible
   and values just float right-aligned on an empty left half. */
@media (max-width: 599.95px) {
  .mud-table-body .mud-table-row {
    display: flex;
    flex-wrap: wrap;
    padding: 10px 0 6px;
    border-bottom: 1px solid rgba(255, 255, 255, 0.08) !important;
  }
  .mud-table-body .mud-table-cell {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 12px;
    padding: 5px 12px !important;
    border-bottom: none !important;
    text-align: right;
    min-width: 0 !important;
    width: auto !important;
    flex: 1 1 100%;
  }
  /* Paired cells share a row — Weight+Remaining, Status+Actions. */
  .mud-table-body .mud-table-cell.vs-cell-half {
    flex: 1 1 calc(50% - 4px);
  }
  /* The remaining bar would otherwise shrink-wrap to a 6px dot in the stacked
     cell — let its wrapper grow so it reads as an actual bar on mobile. */
  .mud-table-body .mud-table-cell[data-label="Remaining"] > div:first-child {
    flex: 1 1 auto;
    min-width: 0;
  }
  .mud-table-body .mud-table-cell[data-label="Remaining"] .vs-fillbar,
  .mud-table-body .mud-table-cell[data-label="Remaining"] .vs-unknown-bar {
    min-width: 56px;
  }
  .mud-table-body .mud-table-cell::before {
    content: attr(data-label);
    flex: 0 0 auto;
    font-size: 10.5px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: rgba(190, 210, 230, 0.55);
    text-align: left;
  }
  /* Cells with no DataLabel (actions column) shouldn't reserve label space. */
  .mud-table-body .mud-table-cell:not([data-label])::before,
  .mud-table-body .mud-table-cell[data-label=""]::before {
    content: none;
  }
  /* Filament title is the row's headline — drop the label/value split and
     let the title span the full cell width. */
  .mud-table-body .mud-table-cell.vs-spool-title-cell {
    display: block;
    text-align: left;
    padding: 10px 12px 6px !important;
  }
  .mud-table-body .mud-table-cell.vs-spool-title-cell::before {
    content: none;
  }
  .vs-spool-table-actions {
    justify-content: flex-end !important;
  }
  /* Action icons stay visible on touch — no hover state to reveal them. */
  .mud-table-body .mud-table-row .mud-icon-button {
    opacity: 0.85;
  }
}

/* Pull the Notes row up so it doesn't have a full grid-gap above it after
   the weights row — the helper-text-less dense fields above leave dead space. */
.vs-spool-grid .vs-notes-cell {
  padding-top: 4px;
}

/* Subheader inside the Variant MudSelect — base material group labels. */
.vs-picker-subheader {
  font-size: 10.5px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--vs-muted);
  font-weight: 600;
  padding: 8px 16px 4px;
  pointer-events: none;
}

/* Filament autocomplete picker rows — items are sorted by base material,
   and each row leads with a small material chip so groups read at a glance. */
.vs-filament-picker-row {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
}
.vs-filament-picker-mat {
  flex: 0 0 auto;
  min-width: 56px;
  padding: 1px 8px;
  font-size: 10.5px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  font-weight: 600;
  color: var(--vs-faint);
  background: var(--vs-surface);
  border: 1px solid var(--vs-hair);
  border-radius: 999px;
  text-align: center;
}
.vs-filament-picker-label {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Stacks the spool-count tile and the reset link vertically. */
.vs-shelves-aside-stack {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 4px;
}

/* Rare power-user action — muted text link, no border, no icon. */
.vs-shelves-reset-link {
  background: transparent;
  border: 0;
  padding: 2px 4px;
  font-size: 11px;
  color: var(--vs-faint);
  cursor: pointer;
  text-decoration: none;
  transition: color 0.15s;
}
.vs-shelves-reset-link:hover {
  color: var(--vs-text);
  text-decoration: underline;
}
.vs-shelves-section {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.vs-shelves-section--sticky {
  position: sticky;
  top: 0;
  z-index: 5;
  background: var(--vs-bg);
  margin-top: 10px; /* clear separation from the tab strip above */
  padding-top: 20px;
  padding-bottom: 12px;
}
/* More air between the Staging title block and its description */
.vs-shelves-section--sticky .vs-shelves-section-head {
  margin-bottom: 4px;
}

/* ── Shelves two-column layout: sticky Staging rail (left) + shelves (right) ──
   Reclaims the vertical space the old top-stacked Staging ate, so the shelves
   get full height. Rail collapses to a full-width block on narrow screens. */
.vs-shelves-layout {
  display: flex;
  align-items: flex-start;
  gap: 20px;
}
.vs-shelves-rail {
  flex: 0 0 304px;
  width: 304px;
  position: sticky;
  top: 12px;
  max-height: calc(100vh - 24px);
  overflow-y: auto;
  overflow-x: hidden;
}
.vs-shelves-main {
  flex: 1 1 auto;
  min-width: 0;
}
.vs-shelves-rail-empty {
  padding: 28px 16px;
  text-align: center;
  font-size: 13px;
  line-height: 1.55;
  color: var(--vs-muted);
  border: 1px dashed var(--vs-hair-2);
  border-radius: 10px;
}

/* Empty Staging that's still a drop target (drag a spool back out of a shelf). */
.vs-staging-empty-drop {
  min-height: 132px;
  align-items: center;
  justify-content: center;
}
.vs-staging-empty-hint {
  text-align: center;
  line-height: 1.6;
  padding: 0 14px;
  max-width: 240px;
}
/* In the rail the Staging section isn't itself sticky (the rail is). The filter
   bar stays a wrapping row: Search shares row 1 with the Hide toggle, and the
   four filter selects pack two-up (Brand|Material, Series|Color). */
.vs-shelves-rail .vs-shelves-section--sticky {
  position: static;
  margin-top: 0;
  padding-top: 0;
}
/* Rail filters get room to breathe: Search, Sort, and Hide each take their own
   full-width row; the four filter selects pack two-up (Brand|Material, then
   Series|Color). Sort sits in a surface box so it reads as a control. */
.vs-shelves-rail .vs-filter-bar .vs-filter-search {
  flex: 1 1 100% !important;
  max-width: none;
}
.vs-shelves-rail .vs-staging-sort {
  flex: 1 1 auto;
  background: var(--vs-surface-2);
  border: 1px solid var(--vs-hair-2);
  border-radius: 6px;
  padding-left: 8px;
}
.vs-shelves-rail .vs-staging-sort .vs-filter-sort { flex: 1 1 auto !important; }
.vs-shelves-rail .vs-staging-sort .mud-input-outlined-border { border: none !important; }
.vs-shelves-rail .vs-filter-toggle {
  flex: 0 0 auto;
}
.vs-shelves-rail .vs-filter-bar > .vs-filter-field {
  flex: 1 1 calc(50% - 3px) !important;
  max-width: none !important;
  min-width: 0 !important;
}
/* Grip + chevron in the Staging head — only meaningful as the mobile dock
   handle, hidden on desktop. */
.vs-dock-grip,
.vs-dock-chevron { display: none; }

/* ── Phones/tablets: the Staging rail becomes a collapsible bottom dock ──
   (VS.shelfdock). Peek state = a slim sheet pinned to the bottom (handle + a
   one-row horizontal strip of spools you press-and-hold then drag UP onto a
   shelf). Expanded = a tall sheet with search + filters, over a scrim. The
   shelves get bottom padding so the last one clears the peek dock. */
@media (max-width: 900px) {
  .vs-shelves-layout {
    flex-direction: column;
  }
  /* Empty rail (every spool shelved) stays a plain static note, not a dock. */
  .vs-shelves-rail {
    flex: none;
    width: 100%;
    position: static;
    max-height: none;
    overflow: visible;
  }
  /* Populated rail → fixed bottom sheet. */
  .vs-shelves-rail[data-vs-dock]:has(.vs-shelves-section--sticky) {
    position: fixed;
    left: 0;
    right: 0;
    top: auto;          /* clear the desktop rail's top:12px so bottom:0 pins it */
    bottom: 0;
    width: 100%;
    z-index: 60;
    margin: 0;
    max-height: 184px;                 /* peek: handle + one spool row */
    background: var(--vs-surface);
    border-top: 1px solid var(--vs-hair-2);
    border-radius: 16px 16px 0 0;
    box-shadow: 0 -10px 30px rgba(0,0,0,0.34);
    overflow: hidden;
    transition: max-height 0.28s var(--vs-ease);
  }
  .vs-shelves-rail[data-vs-dock].is-expanded:has(.vs-shelves-section--sticky) {
    max-height: 82vh;
    overflow-y: auto;
    overflow-x: hidden;
  }
  /* Shelves clear the peek dock. */
  .vs-shelves-main { padding-bottom: 200px; }

  /* The Staging head is the handle: grip on top, count + chevron in a row. */
  .vs-shelves-rail[data-vs-dock] .vs-shelves-section--sticky { padding: 0; }
  .vs-shelves-rail[data-vs-dock] .vs-shelves-section-head {
    position: relative;
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0;
    padding: 16px 16px 10px;
    cursor: pointer;
    user-select: none;
  }
  .vs-shelves-rail[data-vs-dock] .vs-dock-grip {
    display: block;
    position: absolute;
    top: 7px;
    left: 50%;
    transform: translateX(-50%);
    width: 40px;
    height: 5px;
    border-radius: 3px;
    background: var(--vs-faint);
  }
  .vs-shelves-rail[data-vs-dock] .vs-dock-chevron {
    display: block;
    margin-left: auto;
    color: var(--vs-muted);
    transition: transform 0.24s var(--vs-ease);
  }
  .vs-shelves-rail[data-vs-dock].is-expanded .vs-dock-chevron {
    transform: rotate(180deg);
  }
  /* Peek hides the filters + pagination; expand reveals them. The filter bar
     and pagination footer carry inline display:flex, so override !important. */
  .vs-shelves-rail[data-vs-dock]:not(.is-expanded) .vs-filter-bar { display: none !important; }
  /* Peek: the tray is a single horizontally-scrolling row. */
  .vs-shelves-rail[data-vs-dock]:not(.is-expanded) .vs-staging-tray .vs-shelf-area {
    flex-wrap: nowrap;
    overflow-x: auto;
    overflow-y: hidden;
    padding-bottom: 10px;
  }
  /* Peek hides the View-size / pagination footer under the tray. */
  .vs-shelves-rail[data-vs-dock]:not(.is-expanded) .vs-staging-tray .vs-shelf-area ~ div {
    display: none !important;
  }
  .vs-shelves-rail[data-vs-dock] .vs-filter-bar {
    flex-direction: row;
    flex-wrap: wrap;
  }
}
/* Dock scrim (created by VS.shelfdock when expanded). Desktop never shows it. */
.vs-dock-scrim {
  position: fixed;
  inset: 0;
  z-index: 55;
  background: rgba(0,0,0,0.42);
}
@media (min-width: 901px) {
  .vs-dock-scrim { display: none; }
}
.vs-shelf.vs-shelf--no-header {
  display: block;
  grid-template-columns: none;
}

/* Plain Staging tray — a simple flat container, not the recessed bookshelf
   frame the real shelves use. */
/* Fully flat — no recessed/raised 3D anywhere in the tray; just one faint outline. */
.vs-staging-tray,
.vs-staging-tray .vs-shelf,
.vs-staging-tray .vs-shelf-area {
  background: transparent !important;
  box-shadow: none !important;
  border: none !important;
}
.vs-staging-tray .vs-storage-unit-frame {
  background: transparent !important;
  border: 1px solid var(--vs-hair-2) !important;
  border-radius: 10px !important;
  padding: 6px !important;
  box-shadow: none !important;
}
.vs-staging-tray .vs-shelf-area {
  align-items: flex-start;
  min-height: 0;
  padding: 6px;
}

/* Shelves page: tight top spacing — real estate is precious here, so collapse
   the empty band between the nav, the header, the tabs, and the first shelf. */
.vs-page.vs-shelves-page { gap: 10px; }
.vs-page.vs-shelves-page .vs-page-head { min-height: 0; margin-bottom: 0; }
.vs-page.vs-shelves-page .vs-catalog-tabbar { margin-bottom: 8px !important; }
.vs-page.vs-shelves-page .vs-shelves-main > div:first-child { margin-top: 0 !important; }
/* Storage Setup / Back link in the Shelves header (replaces the old tab bar). */
.vs-shelves-setup-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: var(--vs-surface-2);
  border: 1px solid var(--vs-hair-2);
  color: var(--vs-text-2);
  border-radius: 8px;
  padding: 7px 14px;
  cursor: pointer;
  font-family: inherit;
  font-size: 13px;
  font-weight: 500;
  white-space: nowrap;
}
.vs-shelves-setup-btn:hover { border-color: var(--vs-accent); color: var(--vs-text); }
.vs-shelves-section-head {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: baseline;
  padding-bottom: 0;
  border-bottom: 0;
}
.vs-shelves-section-title {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0;
  font-family: var(--vs-sans);
  font-size: 20px;
  font-weight: 600;
  letter-spacing: -0.015em;
  color: var(--vs-text);
}
.vs-shelves-section-title::before {
  content: "";
  width: 5px;
  height: 18px;
  background: var(--vs-accent);
  border-radius: 2px;
}
.vs-shelves-section-glyph {
  display: none;
}
.vs-shelves-section-count {
  font-family: var(--vs-sans);
  font-size: 12px;
  color: var(--vs-muted);
}

.vs-storage-unit {
  display: flex;
  flex-direction: column;
  gap: 0;
}
.vs-storage-unit-head {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: baseline;
  padding: 12px 16px;
  background: var(--vs-surface-2);
  border: none;
  border-radius: var(--vs-radius-lg) var(--vs-radius-lg) 0 0;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04);
}
.vs-storage-unit-name {
  font-family: var(--vs-sans);
  font-size: 15px;
  font-weight: 600;
  color: var(--vs-text);
  display: flex;
  align-items: center;
}
.vs-storage-unit-stats {
  font-family: var(--vs-sans);
  font-size: 12px;
  color: var(--vs-text-2);
  white-space: nowrap;
}
/* Unit head: name + optional description (left), stats + photo cam (right). */
.vs-storage-unit-head { align-items: center; }
.vs-storage-unit-titlewrap { min-width: 0; }
.vs-storage-unit-desc {
  font-family: var(--vs-sans);
  font-size: 12px;
  color: var(--vs-muted);
  margin: 2px 0 0 23px;
}
.vs-storage-unit-headright {
  display: flex;
  align-items: center;
  gap: 6px;
}
/* Storage-unit photo panel sits at the top of the frame, like shelf photos. */
.vs-unit-photos { margin-bottom: 12px; }

.vs-storage-unit-frame {
  position: relative;
  padding: 14px;
  background: var(--vs-surface);
  border: none;
  /* Square bottom: a storage cabinet sits flat on the floor, it doesn't have
     rounded bottom corners. Top stays rounded to meet the unit head. */
  border-radius: 0;
  box-shadow:
    var(--vs-shadow-sm),
    inset 0 3px 12px rgba(0, 0, 0, 0.22),
    inset 0 1px 0 rgba(255, 255, 255, 0.04);
}
.vs-storage-unit-frame-rail {
  display: none;
}
.vs-storage-unit-shelves {
  display: flex;
  flex-flow: row wrap;
  align-items: flex-start;
  gap: 12px;
}
/* Sized shelves pack side by side on the board. Large spans the whole row;
   Medium is about half; Small about a third. flex-grow 0 keeps their true
   proportion (a lone Small stays a third wide rather than stretching). */
.vs-shelf--large  { flex: 1 1 100%; }
.vs-shelf--medium { flex: 0 1 calc(50% - 6px); }
.vs-shelf--small  { flex: 0 1 calc(33.333% - 8px); }
/* Narrow shelves move their header on top so the spool area keeps full width. */
.vs-shelf--medium,
.vs-shelf--small {
  grid-template-columns: 1fr;
}
.vs-shelf--medium > .vs-shelf-header,
.vs-shelf--small > .vs-shelf-header {
  flex-direction: row;
  align-items: baseline;
  gap: 10px;
  border-right: 0;
  border-bottom: 1px solid var(--vs-hair-3);
  padding: 8px 36px 8px 14px;
}
@media (max-width: 820px) {
  /* On narrow screens every shelf is a full-width row again. */
  .vs-shelf--medium,
  .vs-shelf--small { flex-basis: 100%; }
}

/* Native date inputs used for the spool-history From/To filter. Styled to sit
   alongside MudBlazor dense outlined fields without the popover-positioning
   quirks of MudDatePicker. */
.vs-date-filter {
  display: inline-flex;
  flex-direction: column;
  gap: 2px;
}
.vs-date-filter-label {
  font-size: 11px;
  color: var(--vs-muted);
  letter-spacing: 0.02em;
  padding-left: 2px;
}
.vs-date-filter-input {
  height: 38px;
  min-width: 140px;
  background: var(--vs-surface-2);
  border: 1px solid var(--vs-hair-2);
  border-radius: 4px;
  color: var(--vs-text);
  font-family: inherit;
  font-size: 13px;
  padding: 0 10px;
  /* color-scheme follows the document (set per theme in App.razor) so the native
     date text + calendar icon stay legible on light themes too. */
  transition: border-color 0.15s var(--vs-ease);
}
.vs-date-filter-input:hover {
  border-color: var(--vs-hair);
}
.vs-date-filter-input:focus {
  outline: 0;
  border-color: var(--vs-accent);
}
.vs-storage-unit-foot {
  display: none;
}

.vs-shelf {
  position: relative;
  display: grid;
  grid-template-columns: 130px 1fr;
  align-items: stretch;
  gap: 14px;
  padding: 0;
  background: linear-gradient(
    180deg,
    var(--vs-bg-tint) 0%,
    var(--vs-bg-deep) 100%
  );
  /* Borderless bay: the recessed inset + unit frame carry the structure,
     so the shelves read as zones of ONE card, not cards inside a card */
  border: none;
  border-radius: var(--vs-radius);
  box-shadow:
    inset 0 2px 6px rgba(0, 0, 0, 0.22),
    inset 0 1px 0 rgba(255, 255, 255, 0.025);
}
.vs-shelf-header {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  gap: 4px;
  padding: 10px 14px;
  border-right: 1px solid var(--vs-hair-3);
}
.vs-shelf-name {
  font-family: var(--vs-sans);
  font-size: 14px;
  color: var(--vs-text);
  font-weight: 600;
}
.vs-shelf-count {
  font-family: var(--vs-mono);
  color: var(--vs-text-2);
  font-size: 11px;
}
.vs-shelf-count::after {
  content: " spools";
  color: var(--vs-muted);
}
.vs-shelf-stats {
  font-family: var(--vs-mono);
  color: var(--vs-muted);
  font-size: 11px;
  letter-spacing: 0.04em;
}
/* Shelf "# + description": bold label, muted description after a middot. Both
   live inside .vs-shelf-name so they truncate together on a tight board. */
.vs-shelf-num { font-weight: 600; color: var(--vs-text); }
.vs-shelf-desc { font-weight: 400; color: var(--vs-muted); font-size: 12.5px; }
.vs-shelf-desc::before {
  content: "·";
  margin: 0 6px;
  color: var(--vs-faint);
}

/* Compact single-line shelf header (name · count · weight·cost) on top, spools
   below full width — for every shelf size. Long names truncate, not wrap. */
.vs-shelf { grid-template-columns: 1fr; gap: 0; }
.vs-shelf > .vs-shelf-header {
  flex-direction: row;
  align-items: center;
  gap: 10px;
  border-right: 0;
  border-bottom: 1px solid var(--vs-hair-3);
  padding: 8px 40px 8px 14px;
}
.vs-shelf-name {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.vs-shelf-count,
.vs-shelf-stats { flex: 0 0 auto; white-space: nowrap; }
.vs-shelf-area {
  display: flex;
  align-items: flex-end;
  gap: 5px;
  padding: 14px 16px 16px;
  min-height: 126px;
  flex-wrap: wrap;
  border-radius: 0 var(--vs-radius) var(--vs-radius) 0;
  transition:
    background 0.20s var(--vs-ease),
    box-shadow 0.20s var(--vs-ease);
}
.vs-shelf-area.is-over {
  background: var(--vs-accent-soft);
  box-shadow: inset 0 0 0 1px rgba(120,152,191,0.35);
}
.vs-shelf-slot {
  width: 36px;
  height: 104px;
  border: 1px dashed rgba(120,152,191,0.18);
  border-radius: 3px;
  background: rgba(120,152,191,0.03);
  flex: 0 0 auto;
  transition: background 0.18s var(--vs-ease), border-color 0.18s var(--vs-ease), box-shadow 0.18s var(--vs-ease);
}
.vs-shelf-area.is-over .vs-shelf-slot {
  border-color: rgba(120,152,191,0.55);
  background: rgba(120,152,191,0.10);
  box-shadow: 0 0 8px rgba(120,152,191,0.22) inset;
}
.vs-shelf-count.is-over-capacity {
  color: #e0855a;
  font-weight: 600;
}
.vs-shelf-header {
  position: relative;
}
.vs-shelf-toggle {
  position: absolute;
  top: 6px;
  right: 6px;
  background: transparent;
  border: 0;
  padding: 4px;
  cursor: pointer;
  color: var(--vs-muted);
  border-radius: 3px;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: color 0.18s var(--vs-ease), background 0.18s var(--vs-ease);
}
.vs-shelf-toggle:hover {
  color: var(--vs-accent);
  background: rgba(120,152,191,0.10);
}
.vs-shelf-toggle svg {
  display: block;
  transition: transform 0.22s var(--vs-ease);
}
.vs-shelf.is-collapsed .vs-shelf-toggle svg {
  transform: rotate(-90deg);
}
.vs-shelf.is-collapsed .vs-shelf-header {
  border-right: 0;
  border-bottom: 1px solid var(--vs-hair-3);
}

/* Filter bar inside the Unassigned shelf — compact, no reserved helper-text space */
.vs-filter-bar .vs-filter-field {
  margin-top: 0 !important;
  margin-bottom: 0 !important;
}
.vs-filter-bar .vs-filter-field .mud-input-helper-text,
.vs-filter-bar .vs-filter-field .mud-input-helper-container {
  display: none !important;
  min-height: 0 !important;
  height: 0 !important;
}
/* Smaller text inside the filter dropdowns so selected values (e.g. long brand
   names) fit before truncating. */
.vs-filter-field .mud-input-slot,
.vs-filter-field .mud-select-input,
.vs-filter-field input {
  font-size: 11px !important;
}
/* The "spool size unknown" indeterminate bar: dimmed and slowed so it reads as
   a quiet "unknown" signal, not an attention-grabbing animation. */
.vs-unknown-bar {
  opacity: 0.4;
}
.vs-unknown-bar .mud-progress-linear-bar,
.vs-unknown-bar .mud-progress-linear-bar-1,
.vs-unknown-bar .mud-progress-linear-bar-2 {
  animation-duration: 3.6s !important;
}
/* Polite empty state for the detailed/compact lists when filters match nothing. */
.vs-list-empty {
  padding: 28px 16px;
  text-align: center;
  color: var(--vs-muted);
  font-size: 13px;
}
/* Smart Filter quick-preset chips — single-select; active state uses the
   purple accent so the on-state is unmistakable. */
.vs-smart-chip {
  display: inline-flex;
  align-items: center;
  height: 28px;
  padding: 0 12px;
  border-radius: 14px;
  border: 1px solid rgba(255, 255, 255, 0.18);
  background: transparent;
  color: rgba(232, 236, 242, 0.85);
  font-size: 12px;
  font-family: inherit;
  cursor: pointer;
  white-space: nowrap;
  transition: background-color 0.12s, border-color 0.12s, color 0.12s;
}
.vs-smart-chip:hover {
  border-color: rgba(199, 125, 255, 0.6);
  color: #fff;
}
.vs-smart-chip.is-active {
  background: rgba(199, 125, 255, 0.18);
  border-color: #c77dff;
  color: #e6d2ff;
  font-weight: 600;
}
/* Needs-attention chip flags data problems — amber active state, not purple. */
.vs-smart-chip--warn.is-active {
  background: rgba(224, 160, 48, 0.18);
  border-color: #e0a030;
  color: #f0c878;
}

/* ── Compact table: dense, grouped-by-filament list ────────────────────────
   Power-user view that fits many spools on screen. Identical filaments fold
   into a collapsible group; single-spool filaments render as a plain row. */
.vs-compact {
  display: flex;
  flex-direction: column;
  background: var(--vs-surface);
  border: 1px solid var(--vs-hair-2);
  border-radius: 8px;
  overflow: hidden;
  padding: 4px 0 10px;
}

/* Detailed table sits on a surface card (like the Spool Detail panels) instead of
   blending into the page bg. */
.vs-detailed-table.mud-table {
  background: var(--vs-surface);
  border: 1px solid var(--vs-hair-2);
  border-radius: 8px;
  overflow: hidden;
}
/* Detailed table: breathing room on all sides so rows don't sit flush
   against the card edges */
.vs-detailed-table .mud-table-container {
  padding: 6px 10px 12px;
}
.vs-compact-head,
.vs-compact-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 140px 122px 160px 40px;
  align-items: center;
  gap: 8px;
}
/* On phones the 5 fixed-ish columns (~494px) overflow the row; the wrapper
   clips with overflow:hidden, so the Filament column collapses and its spool
   render rides over the remaining bar. Shrink the columns so everything fits
   and the Filament column keeps a real min width. */
@media (max-width: 600px) {
  .vs-compact-head,
  .vs-compact-row {
    grid-template-columns: minmax(60px, 1fr) 58px 90px 46px 22px;
    gap: 6px;
  }
  .vs-compact-row > div { min-width: 0; }
  .vs-compact-row .vs-rem-grams { font-size: 10px; }
}
@media (max-width: 400px) {
  .vs-compact-head,
  .vs-compact-row {
    grid-template-columns: minmax(48px, 1fr) 50px 78px 42px 20px;
    gap: 5px;
  }
}
.vs-compact-head {
  padding: 4px 10px;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--vs-muted);
  border-bottom: 1px solid var(--vs-hair-2);
}
/* Click-to-sort compact headers. */
.vs-compact-sort {
  cursor: pointer;
  user-select: none;
  transition: color 0.12s;
}
.vs-compact-sort:hover {
  color: #aab;
}
.vs-compact-sort.is-active {
  color: var(--vs-info);
}
.vs-compact-sort-arrow {
  font-size: 9px;
}
.vs-compact-row {
  padding: 3px 10px;
  min-height: 34px;
  border-bottom: 1px solid var(--vs-hair);
  transition: background-color 0.12s, box-shadow 0.12s;
}
.vs-compact-row:hover {
  background: rgba(65, 125, 200, 0.07);
}
/* Filament-color end-caps on hover (mirrors the Catalog .vs-pf-row effect): the
   row's primary color rides both edges. --row-accent is set per-row inline; the
   editing rails (.is-editing, below) take over when a row is being edited. */
.vs-compact-row:not(.is-editing):hover {
  box-shadow: inset 3px 0 0 var(--row-accent, var(--vs-accent)),
              inset -3px 0 0 var(--row-accent, var(--vs-accent));
}
/* Detailed table: swap the generic top/bottom hover lift for the same end-caps.
   Scoped to .vs-detailed-table so other MudTables keep their lift; the cell-class
   selectors match the global glow's specificity so the reset actually lands. */
.vs-detailed-table .mud-table-body .mud-table-row:not(.vs-row-editing):hover .mud-table-cell {
  box-shadow: none;
}
.vs-detailed-table .mud-table-body .mud-table-row:not(.vs-row-editing):hover .mud-table-cell:first-child {
  box-shadow: inset 3px 0 0 var(--row-accent, var(--vs-accent));
}
.vs-detailed-table .mud-table-body .mud-table-row:not(.vs-row-editing):hover .mud-table-cell:last-child {
  box-shadow: inset -3px 0 0 var(--row-accent, var(--vs-accent));
}
/* Inline link styling for the filament name / row identifier — only this opens
   the spool detail, so clicking near the weight field no longer navigates. */
.vs-spool-namelink {
  color: inherit;
  text-decoration: none;
  cursor: pointer;
}
.vs-spool-namelink:hover {
  text-decoration: underline;
  color: var(--vs-accent);
}
/* GitHub-style active edit row: brighter tint + blue rails on both edges. */
.vs-compact-row.is-editing {
  background: rgba(79, 155, 255, 0.24);
  box-shadow: inset 4px 0 0 #4f9bff, inset -4px 0 0 #4f9bff;
}
.mud-table-row.vs-row-editing > td {
  background: rgba(79, 155, 255, 0.24) !important;
}
.mud-table-row.vs-row-editing > td:first-child {
  box-shadow: inset 4px 0 0 #4f9bff;
}
.mud-table-row.vs-row-editing > td:last-child {
  box-shadow: inset -4px 0 0 #4f9bff;
}
.vs-compact-group-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 5px 10px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
  background: rgba(255, 255, 255, 0.018);
  cursor: pointer;
  transition: background-color 0.12s;
}
.vs-compact-group-header:hover {
  background: rgba(65, 125, 200, 0.09);
}
.vs-compact-child {
  background: rgba(0, 0, 0, 0.14);
  padding-left: 30px;
}
/* Expanded group children read as secondary, but were too faint to scan —
   lift the location text and the "1 of 2" position marker a notch. */
.vs-compact-child .vs-compact-meta {
  font-size: 12px;
  color: #abacc6;
}
.vs-compact-child .vs-compact-count {
  font-size: 12px;
  color: #c3abe2;
}
/* Child-row filament name: present but not shouting — the group header above
   already carries the bold/bright title, so the per-spool repeat is quieter. */
.vs-compact-child .vs-compact-name-main {
  font-size: 12px;
  font-weight: 500;
  color: var(--vs-text-2);
}
.vs-compact-name {
  font-size: 13px;
  font-weight: 600;
  color: var(--vs-text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Split filament title: muted brand/material prefix + bold name (the color).
   The name never shrinks (flex 0 0 auto) so on a narrow row the prefix clips
   first and the color stays readable. */
.vs-compact-title {
  display: flex;
  align-items: baseline;
  gap: 6px;
  min-width: 0;
  overflow: hidden;
}
.vs-compact-name-prefix {
  flex: 0 1 auto;
  min-width: 0;
  font-size: 13px;
  font-weight: 400;
  color: var(--vs-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.vs-compact-name-main {
  flex: 0 0 auto;
  font-size: 13px;
  font-weight: 700;
  color: var(--vs-text);
  white-space: nowrap;
}
.vs-compact-meta {
  font-size: 11px;
  color: #9a9eba;
}
/* Single-row location hint: quieter than meta — unit only, full path on hover. */
.vs-compact-loc {
  font-size: 10px;
  color: var(--vs-muted);
}
.vs-compact-chev {
  display: inline-block;
  width: 12px;
  font-size: 10px;
  color: #8a8aa8;
  transition: transform 0.15s;
  flex-shrink: 0;
}
.vs-compact-chev.is-open {
  transform: rotate(90deg);
}
.vs-compact-count {
  font-family: monospace;
  font-size: 11px;
  font-weight: 600;
  color: #b594d6; /* desaturated lavender, in step with the muted status colors */
  flex-shrink: 0;
}
/* Sort by — muted label so it reads as a "this is the sort control" hint,
   not a primary control */
.vs-filter-bar .vs-filter-sort .mud-input-label,
.vs-filter-bar .vs-filter-sort label {
  color: rgba(144, 144, 176, 0.65) !important;
  font-weight: 400 !important;
}
.vs-filter-bar .vs-filter-sort .mud-input-outlined-border {
  border-color: rgba(255, 255, 255, 0.10) !important;
}

/* ====== Error pages (/Error, /not-found) + Blazor crash bar ====== */
/* ===== Public series (Variant) page: filaments as side spools on a shelf ===== */
/* One shelving unit; spools flow and wrap to the page width. Every spool reserves
   a 2-line caption so they all stand on the same baseline, and each wrapped row
   gets a continuous "plank" from the items' shared bottom border. */
.vs-series-shelf {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: center;
  row-gap: 20px;
  column-gap: 0;
  padding: 20px 12px;
  background: linear-gradient(180deg, var(--vs-surface) 0%, var(--vs-surface-2) 100%);
  border: 1px solid var(--vs-hair-2);
  border-radius: 12px;
  box-shadow: inset 0 -16px 24px rgba(0, 0, 0, 0.05);
}
.vs-series-spool {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  width: 78px;
  padding: 0 8px 10px;
  border-bottom: 3px solid var(--vs-surface-3);
  text-decoration: none;
  color: var(--vs-text-2);
}
.vs-series-spool-cap {
  min-height: 2.5em;   /* reserve 2 lines so every spool sits on the same baseline */
  font-size: 11px;
  line-height: 1.25;
  text-align: center;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.vs-series-spool:hover .vs-series-spool-cap { color: var(--vs-accent); text-decoration: underline; }

/* ===== Filament page: Buy section ===== */
.vs-fil-buy {
  margin-top: 22px;
  padding: 16px 18px;
  border: 1px solid var(--vs-hair-2);
  border-radius: 12px;
  background: var(--vs-surface);
}
.vs-fil-buy-row {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}
.vs-buy-btn {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-weight: 600;
  font-size: 14px;
  text-decoration: none;
  border-radius: 8px;
  padding: 10px 18px;
  transition: background 0.15s var(--vs-ease, ease), border-color 0.15s var(--vs-ease, ease);
}
.vs-buy-btn--brand { background: var(--vs-accent); color: var(--vs-bg-deep); }
.vs-buy-btn--brand:hover { background: var(--vs-accent-deep); }
.vs-buy-btn--amz { border: 1px solid var(--vs-accent); color: var(--vs-accent); }
.vs-buy-btn--amz:hover { background: var(--vs-accent-soft); }
.vs-buy-btn--alt { border: 1px solid var(--vs-hair-2); color: var(--vs-text-2); }
.vs-buy-btn--alt:hover { border-color: var(--vs-accent); color: var(--vs-accent); }
.vs-fil-buy-prices {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 16px;
  margin-top: 12px;
  font-size: 13px;
  color: var(--vs-muted);
}
.vs-fil-buy-note {
  font-size: 11px;
  color: var(--vs-faint);
  margin-top: 10px;
}

/* Compact text in the admin Material editor (it has a lot of fields). */
.vs-material-editor .mud-input,
.vs-material-editor .mud-input-slot,
.vs-material-editor .mud-input-label,
.vs-material-editor .mud-select .mud-select-input,
.vs-material-editor .mud-checkbox label,
.vs-material-editor .mud-checkbox .mud-typography { font-size: 0.78rem !important; }

.vs-error-page {
  min-height: 60vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 40px 16px;
}
.vs-error-card {
  background: var(--vs-surface);
  border: 1px solid var(--vs-hair-2);
  border-radius: 12px;
  padding: 40px 32px;
  max-width: 540px;
  width: 100%;
  text-align: center;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.32);
}
.vs-error-icon {
  margin-bottom: 16px;
  display: flex;
  justify-content: center;
}
.vs-spaghetti {
  margin-bottom: 16px;
  display: flex;
  justify-content: center;
}
.vs-shelf-404 {
  margin-bottom: 16px;
  display: flex;
  justify-content: center;
}

.vs-empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: 48px 24px 32px;
  max-width: 480px;
  margin: 0 auto;
}

.vs-empty-spool-preview {
  margin-bottom: 24px;
  opacity: 0.55;
  filter: saturate(0.7);
  transition: opacity 0.3s, filter 0.3s;
}

.vs-empty-spool-preview:hover {
  opacity: 0.85;
  filter: saturate(1);
}

.vs-empty-shelf {
  margin-bottom: 24px;
  display: flex;
  justify-content: center;
}

.vs-empty-state .vs-empty-title {
  font-family: var(--vs-sans);
  font-size: 22px;
  font-weight: 600;
  color: var(--vs-text);
  margin: 0 0 12px 0;
  letter-spacing: -0.01em;
}

.vs-empty-state .vs-empty-lead {
  font-size: 14px;
  color: var(--vs-faint);
  line-height: 1.55;
  margin: 0 0 28px 0;
}

.vs-empty-state .vs-empty-actions {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
  justify-content: center;
}
.vs-error-code {
  font-family: var(--vs-mono);
  font-size: 64px;
  font-weight: 700;
  color: #7898bf;
  line-height: 1;
  letter-spacing: -0.02em;
  margin-bottom: 8px;
}
.vs-error-title {
  font-size: 24px;
  font-weight: 700;
  color: var(--vs-text);
  margin: 0 0 12px 0;
  letter-spacing: -0.015em;
}
.vs-error-lead {
  font-size: 15px;
  color: var(--vs-muted);
  line-height: 1.5;
  margin: 0 0 24px 0;
}
.vs-error-id-block {
  /* Recessed code block: deeper than the card on every theme (was a hardcoded
     near-black that looked like a dark slab on light themes). Click to copy. */
  background: var(--vs-bg-deep);
  border: 1px solid var(--vs-hair-2);
  border-radius: 6px;
  padding: 12px 14px;
  margin: 0 0 24px 0;
  width: 100%;
  text-align: left;
  cursor: pointer;
  transition: border-color 0.15s;
}
.vs-error-id-block:hover,
.vs-error-id-block:focus-visible {
  border-color: var(--vs-accent);
  outline: none;
}
.vs-error-id-label {
  font-size: 11px;
  color: var(--vs-faint);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-bottom: 4px;
}
.vs-error-id-value {
  font-family: var(--vs-mono);
  font-size: 12px;
  color: var(--vs-text-2);
  word-break: break-all;
  /* One click selects the whole id (and the block copies it to the clipboard). */
  user-select: all;
  cursor: pointer;
}
.vs-error-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
}
.vs-error-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 10px 18px;
  border-radius: 6px;
  font-size: 14px;
  font-weight: 600;
  text-decoration: none;
  border: 1px solid transparent;
  transition: background 0.15s var(--vs-ease), border-color 0.15s var(--vs-ease);
}
.vs-error-btn-primary {
  background: #7898bf;
  color: #0e1018;
}
.vs-error-btn-primary:hover {
  background: #8aa8cf;
}
.vs-error-btn-secondary {
  background: transparent;
  color: var(--vs-text-2);
  border-color: var(--vs-hair-2);
}
.vs-error-btn-secondary:hover {
  background: rgba(var(--vs-tint), 0.10);
  border-color: #7898bf;
}

/* Blazor crash bar — overrides the framework's default lightyellow ribbon */
#blazor-error-ui {
  background: #1a1a2e;
  border-top: 1px solid #e0855a;
  bottom: 0;
  left: 0;
  width: 100%;
  position: fixed;
  display: none;
  z-index: 10000;
  padding: 12px 56px 12px 18px;
  color: #f2d5c4;
  font-size: 13px;
  line-height: 1.5;
  box-shadow: 0 -4px 16px rgba(0, 0, 0, 0.48);
  align-items: center;
  gap: 10px;
}
#blazor-error-ui .vs-blazor-err-icon {
  color: #e0855a;
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
}
#blazor-error-ui .vs-blazor-err-text {
  flex: 1 1 auto;
}
#blazor-error-ui .vs-blazor-err-btn {
  background: #7898bf;
  color: #0e1018;
  padding: 4px 12px;
  border-radius: 4px;
  font-weight: 600;
  text-decoration: none;
  font-size: 12px;
  flex-shrink: 0;
}
#blazor-error-ui .vs-blazor-err-btn:hover {
  background: #8aa8cf;
}
#blazor-error-ui .vs-blazor-err-dismiss {
  position: absolute;
  right: 16px;
  top: 50%;
  transform: translateY(-50%);
  cursor: pointer;
  color: var(--vs-muted);
  font-size: 20px;
  line-height: 1;
  padding: 4px 8px;
}
#blazor-error-ui .vs-blazor-err-dismiss:hover {
  color: #dae8f8;
}

/* MudTabs — replace MudBlazor's bright cyan primary with the site accent */
.mud-tabs .mud-tab-active,
.mud-tabs .mud-tab.mud-tab-active .mud-icon-root {
  color: #7898bf !important;
}
.mud-tabs .mud-tab:hover {
  color: #aac4e6;
}
.mud-tabs .mud-tabs-tabbar-slider {
  background-color: #7898bf !important;
}
.vs-shelf-empty {
  align-self: center;
  font-family: var(--vs-sans);
  font-size: 13px;
  color: var(--vs-faint);
  padding: 8px;
}
.vs-shelf-spool {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  cursor: grab;
  padding: 0 2px;
  -webkit-touch-callout: none;
  user-select: none;
  touch-action: none;
}
.vs-shelf-spool:active {
  cursor: grabbing;
}
.vs-shelf-spool.is-dragging {
  opacity: 0.22;
}
.vs-shelf-spool.is-dragging .vs-spool-side {
  transform: scale(1.06) translateY(-3px);
  filter: drop-shadow(0 8px 18px rgba(0,0,0,0.55)) drop-shadow(0 2px 6px rgba(120,152,191,0.18));
}
/* Pointer-events drag engine (VS.shelfdrag): the picked-up spool dims in place
   while a floating clone follows the pointer. */
.vs-shelf-spool.vs-drag-source {
  opacity: 0.25 !important;
}
.vs-drag-clone {
  position: fixed;
  left: 0;
  top: 0;
  z-index: 9999;
  margin: 0;
  pointer-events: none;
  opacity: 0.97;
  transform: scale(1.1);
  transform-origin: center bottom;
  filter: drop-shadow(0 14px 24px rgba(0,0,0,0.55)) drop-shadow(0 4px 9px rgba(120,152,191,0.28));
  will-change: left, top;
}
.vs-drag-clone .vs-shelf-spool-label,
.vs-drag-clone .vs-spool-wrap-trigger { display: none; }
.vs-shelf-spool-label {
  text-align: center;
  padding-bottom: 4px;
  line-height: 1.25;
  opacity: 0;
  transform: translateY(3px);
  transition:
    opacity 0.20s ease-out 0.04s,
    transform 0.20s var(--vs-ease) 0.04s;
}
.vs-shelf-spool:hover .vs-shelf-spool-label,
.vs-shelf-spool:focus .vs-shelf-spool-label,
.vs-shelf-spool:focus-within .vs-shelf-spool-label {
  opacity: 1;
  transform: translateY(-4px);
}
.vs-shelf-spool:focus,
.vs-shelf-spool:focus-visible {
  outline: 1px solid rgba(120,152,191,0.55);
  outline-offset: 2px;
  border-radius: 3px;
}
/* Spool tooltip (shelf + Running Low widget). Uses ::before so it appears
   above the spool. Suppressed on touch devices. */
.vs-shelf-spool[data-vs-tip]::before,
.vs-low-spool[data-vs-tip]::before,
.vs-bench-tile[data-vs-tip]::before,
.vs-gear-spool[data-vs-tip]::before,
.vs-desk-spool[data-vs-tip]::before {
  content: attr(data-vs-tip);
  position: absolute;
  bottom: calc(100% + 5px);
  left: 50%;
  transform: translateX(-50%) translateY(4px);
  opacity: 0;
  pointer-events: none;
  white-space: pre-line;
  text-align: center;
  background: var(--vs-surface);
  color: var(--vs-text-2);
  font-size: 11px;
  font-family: var(--vs-sans);
  font-weight: 400;
  line-height: 1.55;
  border-radius: 6px;
  padding: 5px 9px;
  z-index: 200;
  box-shadow: 0 4px 14px rgba(0,0,0,0.22), inset 0 0 0 1px var(--vs-hair-2);
  min-width: 140px;
  max-width: 280px;
  transition: opacity 0.15s ease-out 0.35s, transform 0.15s ease-out 0.35s;
}
.vs-shelf-spool[data-vs-tip]:hover::before,
.vs-low-spool[data-vs-tip]:hover::before,
.vs-bench-tile[data-vs-tip]:hover::before,
.vs-gear-spool[data-vs-tip]:hover::before,
.vs-desk-spool[data-vs-tip]:hover::before {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}
/* The gear column (.vs-bench-right) scrolls within the viewport, so its ::before
   tooltips get clipped by that overflow. There, VS.benchTip renders the tip as a
   fixed-position .vs-floating-tip on <body> instead (escapes the clip); suppress
   the clipped pseudo-element so they don't double up. */
.vs-bench-right .vs-gear-spool[data-vs-tip]::before,
.vs-bench-right .vs-gear-spool[data-vs-tip]:hover::before {
  display: none;
}
.vs-floating-tip {
  position: fixed;
  display: none;
  z-index: 9990;
  pointer-events: none;
  white-space: pre-line;
  text-align: center;
  background: var(--vs-surface);
  color: var(--vs-text-2);
  font-size: 11px;
  font-family: var(--vs-sans);
  font-weight: 400;
  line-height: 1.55;
  border-radius: 6px;
  padding: 5px 9px;
  box-shadow: 0 4px 14px rgba(0,0,0,0.22), inset 0 0 0 1px var(--vs-hair-2);
  min-width: 140px;
  max-width: 280px;
  opacity: 0;
  transition: opacity 0.12s ease-out;
}
/* Outer spools in a strip: a centered tooltip can run off the page on a narrow
   window. Anchor the LEFTMOST spool's tooltip to its left edge (grows right) and
   the RIGHTMOST's to its right edge (grows left) so it stays on screen. Widget
   strips wrap each spool in .vs-widget-spool, so key off that wrapper's position
   (keying off .vs-shelf-spool directly would match every spool); Running Low
   places .vs-low-spool directly. */
.vs-widget-spool:first-child .vs-shelf-spool[data-vs-tip]::before,
.vs-low-spool:first-child[data-vs-tip]::before {
  left: 0;
  transform: translateX(0) translateY(4px);
}
.vs-widget-spool:first-child .vs-shelf-spool[data-vs-tip]:hover::before,
.vs-low-spool:first-child[data-vs-tip]:hover::before {
  transform: translateX(0) translateY(0);
}
.vs-widget-spool:last-child .vs-shelf-spool[data-vs-tip]::before,
.vs-low-spool:last-child[data-vs-tip]::before {
  left: auto;
  right: 0;
  transform: translateX(0) translateY(4px);
}
.vs-widget-spool:last-child .vs-shelf-spool[data-vs-tip]:hover::before,
.vs-low-spool:last-child[data-vs-tip]:hover::before {
  transform: translateX(0) translateY(0);
}
/* Browse/inventory shelves render spools directly inside .vs-shelf-area (no per-spool
   wrapper), so the centered tooltip on the first/last spool runs off the shelf edge and
   gets clipped. Anchor those to the edge so they grow inward and stay on screen. */
.vs-shelf-area > .vs-shelf-spool[data-vs-tip]:first-child::before {
  left: 0;
  transform: translateX(0) translateY(4px);
}
.vs-shelf-area > .vs-shelf-spool[data-vs-tip]:first-child:hover::before {
  transform: translateX(0) translateY(0);
}
.vs-shelf-area > .vs-shelf-spool[data-vs-tip]:last-child::before {
  left: auto;
  right: 0;
  transform: translateX(0) translateY(4px);
}
.vs-shelf-area > .vs-shelf-spool[data-vs-tip]:last-child:hover::before {
  transform: translateX(0) translateY(0);
}
/* On touch-only devices (no real hover), tapping a spool focuses it and
   shows the label; same gesture taps elsewhere to dismiss. */
@media (hover: none) {
  .vs-shelf-spool {
    cursor: pointer;
  }
  .vs-shelf-spool[data-vs-tip]::before,
  .vs-low-spool[data-vs-tip]::before,
  .vs-bench-tile[data-vs-tip]::before,
  .vs-gear-spool[data-vs-tip]::before,
  .vs-desk-spool[data-vs-tip]::before { display: none; }
}
.vs-shelf-spool-label .vs-mono {
  font-size: 9px;
  color: var(--vs-accent);
  font-weight: 500;
}
.vs-shelf-spool-mat {
  font-size: 9px;
  color: var(--vs-muted);
}
.vs-shelf-plank,
.vs-shelf-plank-edge,
.vs-shelf-bolt {
  display: none;
}

/* ====== HOVER MOTION ====== */
[data-hoverspin="on"] .vs-spool-front {
  transition: transform 0.6s cubic-bezier(0.2, 1, 0.3, 1);
}
[data-hoverspin="on"] .vs-spool-card:hover .vs-spool-front {
  transform: rotate(45deg);
}
[data-hoverspin="off"] .vs-spool-front,
[data-hoverspin="off"] .vs-spool-side {
  transition: none;
}

.vs-shelf-spool .vs-spool-side,
.vs-hero-shelf-spool .vs-spool-side,
.vs-rack-tile .vs-spool-side {
  transition:
    transform 0.22s var(--vs-ease),
    filter 0.22s ease-out;
  transform-origin: 50% 100%;
  filter: drop-shadow(0 2px 3px rgba(0,0,0,0.55));
}
.vs-shelf-spool:hover .vs-spool-side {
  transform: translateY(-4px) scale(1.05);
  filter:
    drop-shadow(0 6px 12px rgba(0,0,0,0.52))
    drop-shadow(0 2px 4px rgba(0,0,0,0.40))
    drop-shadow(0 1px 5px rgba(120,152,191,0.16));
}
.vs-hero-shelf-spool:hover .vs-spool-side {
  transform: translateY(-6px) scale(1.08);
}
.vs-rack-tile:hover .vs-spool-side {
  transform: translateY(-5px) scale(1.07);
}

/* ── Progressive enhancement / LOD ─────────────────────────────────────────
   .vs-layer-std: expensive texture detail — hidden by default, revealed on hover.
   .vs-layer-minimal: lightweight specialty hints — shown by default, replaced on hover.
   .vs-detail-full: always show full detail (use for modals/detail panels). */
.vs-layer-std {
  display: none;
}
.vs-shelf-spool:hover .vs-layer-std,
.vs-hero-shelf-spool:hover .vs-layer-std,
.vs-rack-tile:hover .vs-layer-std,
.vs-detail-full .vs-layer-std {
  display: block;
}

.vs-shelf-spool:hover .vs-layer-minimal,
.vs-hero-shelf-spool:hover .vs-layer-minimal,
.vs-rack-tile:hover .vs-layer-minimal,
.vs-detail-full .vs-layer-minimal {
  display: none;
}

/* ====== EMPTY ====== */
.vs-empty {
  text-align: center;
  padding: 60px 30px;
  background: var(--vs-surface);
  border: 1px solid var(--vs-hair);
  border-radius: var(--vs-radius-lg);
}
.vs-empty-title {
  font-family: var(--vs-sans);
  font-size: 20px;
  color: var(--vs-text);
  font-weight: 600;
}
.vs-empty-sub {
  font-family: var(--vs-sans);
  font-size: 13px;
  color: var(--vs-muted);
  margin-top: 8px;
}

/* ====== FORM PAGE ====== */
.vs-form-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 320px;
  gap: 24px;
  align-items: start;
}
.vs-form-main {
  display: flex;
  flex-direction: column;
  gap: 18px;
  min-width: 0;
}
.vs-form-section {
  padding: 22px 24px;
}
.vs-form-section-head {
  display: flex;
  align-items: center;
  gap: 12px;
  padding-bottom: 14px;
  border-bottom: 1px solid var(--vs-hair);
  margin-bottom: 18px;
}
.vs-form-section-num {
  display: inline-grid;
  place-items: center;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--vs-accent), var(--vs-accent-deep));
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.04em;
  box-shadow: 0 4px 12px -4px var(--vs-accent-glow);
}
.vs-form-section-title {
  margin: 0;
  font-family: var(--vs-sans);
  font-size: 15px;
  font-weight: 600;
  color: var(--vs-text);
  letter-spacing: -0.005em;
}
.vs-form-section-body {
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.vs-form-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
}
.vs-field {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
}
.vs-field-label {
  font-family: var(--vs-sans);
  font-size: 11px;
  color: var(--vs-muted);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-weight: 600;
}
.vs-field-hint {
  font-size: 11px;
  color: var(--vs-muted);
}
.vs-input {
  background: var(--vs-surface-2);
  border: 1px solid var(--vs-hair);
  border-radius: var(--vs-radius);
  padding: 10px 12px;
  color: var(--vs-text);
  font-family: var(--vs-sans);
  font-size: 13px;
  outline: none;
  transition:
    border-color 0.15s,
    box-shadow 0.15s;
}
.vs-input:focus {
  border-color: var(--vs-accent);
  box-shadow: 0 0 0 3px var(--vs-accent-glow);
}
.vs-textarea {
  resize: vertical;
  min-height: 64px;
  font-family: var(--vs-sans);
}
.vs-chip-group {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.vs-chip-btn {
  background: var(--vs-surface-2);
  border: 1px solid var(--vs-hair);
  color: var(--vs-text-2);
  padding: 8px 12px;
  border-radius: 999px;
  font-family: var(--vs-sans);
  font-size: 12px;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.15s;
}
.vs-chip-btn:hover {
  color: var(--vs-text);
  border-color: var(--vs-hair-2);
}
.vs-chip-btn.is-active {
  background: linear-gradient(135deg, var(--vs-accent), var(--vs-accent-deep));
  border-color: transparent;
  color: #fff;
  box-shadow: 0 4px 12px -6px var(--vs-accent-glow);
}
.vs-swatch-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(30px, 1fr));
  gap: 6px;
}
.vs-swatch-btn {
  aspect-ratio: 1;
  border-radius: 8px;
  border: 1px solid rgba(255, 255, 255, 0.06);
  cursor: pointer;
  transition:
    transform 0.15s,
    box-shadow 0.15s;
  position: relative;
}
.vs-swatch-btn:hover {
  transform: scale(1.08);
}
.vs-swatch-btn.is-active {
  box-shadow:
    0 0 0 2px var(--vs-bg),
    0 0 0 4px var(--vs-accent);
  transform: scale(1.08);
}
.vs-color-bead {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, 0.1);
  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.4);
}
.vs-range {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 6px;
  background: var(--vs-surface-3);
  border-radius: 999px;
  outline: none;
}
.vs-range::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--vs-accent), var(--vs-accent-deep));
  border: 2px solid var(--vs-bg);
  cursor: pointer;
  box-shadow: 0 0 12px var(--vs-accent-glow);
}
.vs-range::-moz-range-thumb {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--vs-accent);
  border: 2px solid var(--vs-bg);
  cursor: pointer;
}
.vs-range-labels {
  display: flex;
  justify-content: space-between;
  font-size: 11px;
  color: var(--vs-muted);
  margin-top: 4px;
  font-variant-numeric: tabular-nums;
}
.vs-range-current {
  color: var(--vs-accent);
  font-weight: 600;
}

.vs-toggle-row {
  display: flex;
  align-items: center;
  gap: 10px;
  cursor: pointer;
}
.vs-toggle-row input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}
.vs-toggle-track {
  width: 36px;
  height: 20px;
  background: var(--vs-surface-3);
  border-radius: 999px;
  border: 1px solid var(--vs-hair);
  position: relative;
  transition: all 0.18s;
}
.vs-toggle-thumb {
  position: absolute;
  top: 2px;
  left: 2px;
  width: 14px;
  height: 14px;
  background: var(--vs-text-2);
  border-radius: 50%;
  transition: all 0.18s;
}
.vs-toggle-row input:checked + .vs-toggle-track {
  background: linear-gradient(135deg, var(--vs-accent), var(--vs-accent-deep));
  border-color: transparent;
}
.vs-toggle-row input:checked + .vs-toggle-track .vs-toggle-thumb {
  left: 18px;
  background: #fff;
}

.vs-form-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  padding: 16px 0 4px;
  flex-wrap: wrap;
}

.vs-form-preview {
  position: sticky;
  top: 24px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.vs-preview-card {
  padding: 20px;
}
.vs-preview-eyebrow {
  font-size: 10px;
  letter-spacing: 0.12em;
  color: var(--vs-accent);
  text-transform: uppercase;
  font-weight: 700;
  margin-bottom: 14px;
}
.vs-preview-spool-stage {
  display: flex;
  gap: 14px;
  justify-content: center;
  align-items: flex-end;
  padding: 12px 0 18px;
  border-bottom: 1px solid var(--vs-hair);
  margin-bottom: 14px;
  background: radial-gradient(
    ellipse 60% 30% at 50% 95%,
    rgba(0, 0, 0, 0.4),
    transparent 70%
  );
}
.vs-preview-meta {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.vs-preview-sku {
  font-family: var(--vs-mono, ui-monospace, monospace);
  font-size: 11px;
  color: var(--vs-text-2);
  letter-spacing: 0.02em;
}
.vs-preview-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
}
.vs-tag {
  font-size: 10px;
  padding: 3px 8px;
  border-radius: 999px;
  background: var(--vs-surface-2);
  color: var(--vs-text-2);
  border: 1px solid var(--vs-hair);
  font-weight: 500;
  letter-spacing: 0.02em;
}
.vs-tag--accent {
  background: var(--vs-accent-glow);
  color: var(--vs-accent);
  border-color: transparent;
}

/* Material applications panel: one row per category — emoji label on the left,
   wrapping name chips on the right. */
.vs-appuses {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.vs-appuses-row {
  display: grid;
  grid-template-columns: 140px 1fr;
  gap: 12px;
  align-items: start;
}
.vs-appuses-cat {
  font-size: 12px;
  color: var(--vs-text-2);
  font-weight: 600;
  padding-top: 3px;
}
.vs-appuses-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
@media (max-width: 560px) {
  .vs-appuses-row { grid-template-columns: 1fr; gap: 5px; }
}
.vs-preview-fill-track {
  height: 6px;
  background: var(--vs-surface-3);
  border-radius: 999px;
  overflow: hidden;
}
.vs-preview-fill-bar {
  height: 100%;
  background: linear-gradient(90deg, var(--vs-accent), var(--vs-accent-deep));
  border-radius: 999px;
  transition: width 0.3s cubic-bezier(0.2, 1, 0.3, 1);
}
.vs-preview-fill-text {
  display: flex;
  justify-content: space-between;
  font-size: 11px;
  color: var(--vs-muted);
  margin-top: 5px;
  font-variant-numeric: tabular-nums;
}
.vs-preview-fill-pct {
  color: var(--vs-accent);
  font-weight: 600;
}
.vs-preview-row {
  display: flex;
  justify-content: space-between;
  font-size: 12px;
  color: var(--vs-text-2);
  padding: 6px 0;
  border-top: 1px dashed var(--vs-hair);
}
.vs-preview-row > span:first-child {
  color: var(--vs-muted);
}
.vs-preview-hint {
  font-size: 11px;
  color: var(--vs-muted);
  text-align: center;
  padding: 0 8px;
}
.vs-aside-stat-value {
  font-family: var(--vs-mono, ui-monospace, monospace);
  font-size: 13px;
  color: var(--vs-accent);
  letter-spacing: 0.02em;
}
.vs-aside-stat-label {
  font-size: 10px;
  color: var(--vs-muted);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  margin-top: 2px;
}

@media (max-width: 980px) {
  .vs-form-layout {
    grid-template-columns: 1fr;
  }
  .vs-form-preview {
    position: static;
  }
  .vs-form-row {
    grid-template-columns: 1fr;
  }
}

/* ====== MOBILE ====== */
@media (max-width: 980px) {
  .vs-shell {
    padding: 0 16px;
  }
  .vs-topbar {
    grid-template-columns: auto 1fr auto;
    gap: 12px;
    padding: 14px 0;
  }
  .vs-topbar {
    z-index: 200;
  }
  .vs-nav-tabs {
    /* Fixed dropdown card — floats below the topbar, does not push content */
    display: none;
    position: fixed;
    top: 76px;
    left: 12px;
    right: 12px;
    z-index: 100;
    flex-direction: column;
    align-items: stretch;
    padding: 8px;
    gap: 2px;
    border-radius: var(--vs-radius);
    background: var(--vs-surface-2);
    border: 1px solid var(--vs-hair-2);
    box-shadow: 0 16px 40px rgba(0,0,0,0.5), 0 4px 12px rgba(0,0,0,0.3);
    backdrop-filter: blur(24px);
    -webkit-backdrop-filter: blur(24px);
    justify-self: unset;
    white-space: normal;
    margin-top: 0;
  }
  .vs-nav-tab {
    text-align: left;
    padding: 12px 16px;
    border-radius: 8px;
  }
  /* The mobile nav is a dropdown CARD over page content, not a frosted topbar
     pill — so it must be fully opaque. Light themes otherwise inherit the
     desktop pill's translucent 62% white (set globally above) and the page
     bleeds through. Override to a solid surface for both modes here. */
  .vs-nav-tabs,
  html[data-mode="light"] .vs-nav-tabs {
    background: var(--vs-surface);
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }
  /* Fix: check is-sidebar-closed on .vs-app (where the hamburger toggles it) */
  .vs-app:not(.is-sidebar-closed) .vs-nav-tabs {
    display: flex;
  }
  .vs-topbar-toggle {
    display: grid !important;
  }
  .vs-content {
    padding: 22px 0 60px;
  }
  /* Page title kept at base 23px on tablet; no override needed. */
  .vs-stat-grid {
    grid-template-columns: repeat(2, 1fr);
  }
  .vs-stat-value {
    font-size: 24px;
  }
  .vs-two-col {
    grid-template-columns: 1fr;
    gap: 14px;
  }
  .vs-list-head {
    display: none;
  }
  .vs-list-row {
    grid-template-columns: 40px 1fr 80px;
    gap: 12px;
    padding: 10px 14px;
  }
  .vs-list-cell--id,
  .vs-list-cell--colors,
  .vs-list-cell--code,
  .vs-list-cell--shelf {
    display: none;
  }
  .vs-bench-row {
    grid-template-columns: 36px 1fr 80px;
  }
  .vs-bench-pct,
  .vs-bench-row > div:nth-child(5) {
    display: none;
  }
  .vs-shelf {
    grid-template-columns: 1fr;
    gap: 0;
  }
  .vs-shelf-header {
    border-right: 0;
    border-bottom: 1px solid var(--vs-hair-3);
  }
}

@media (max-width: 640px) {
  .vs-page-title {
    font-size: 24px;
  }
  .vs-card-grid {
    grid-template-columns: 1fr 1fr;
  }
}

/* ── Typography & visual refinements ────────────────────────────────────────
   Manrope Medium spacing on small labels, counters, metadata.
   Panel borders softened to reduce visual weight. */
.vs-shelf-name {
  letter-spacing: 0.012em;
}
.vs-shelf-count {
  letter-spacing: 0.05em;
}
.vs-shelves-section-count {
  letter-spacing: 0.05em;
}
.vs-storage-unit-name {
  letter-spacing: 0.01em;
}
.vs-storage-unit-stats {
  letter-spacing: 0.04em;
}
.vs-rack-tile-brand {
  letter-spacing: 0.04em;
}
.vs-rack-tile-mat {
  letter-spacing: 0.04em;
}
.vs-shelf-spool-mat {
  letter-spacing: 0.04em;
}
.vs-nav-tab {
  letter-spacing: 0.01em;
}

.vs-nav-tabs {
  border-color: rgba(255, 255, 255, 0.04);
}
.vs-rack-view {
  border-color: rgba(255, 255, 255, 0.04);
  box-shadow:
    var(--vs-shadow-sm),
    inset 0 1px 0 rgba(255, 255, 255, 0.03);
}
.vs-rack-row {
  box-shadow:
    inset 0 2px 4px rgba(0, 0, 0, 0.18),
    inset 0 1px 0 rgba(255, 255, 255, 0.02);
}
.vs-hero-shelf {
  border-color: rgba(255, 255, 255, 0.04);
}

/* ── Homepage ────────────────────────────────────────────────────────────── */
html {
  /* Reserve the scrollbar gutter on both sides so centered content
     (e.g. the hero) sits at true center, not offset by the scrollbar.
     Match the page background so the reserved left gutter is invisible
     (a deeper color here showed as a strip down the left edge). */
  scrollbar-gutter: stable both-edges;
  background-color: var(--vs-bg);
}

/* Respect reduced-motion: neutralize decorative + looping motion site-wide
   (demo-wall hint pulse, spool hover transforms, spinners, shimmer). State
   changes still apply, just instantly. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}

.vs-home {
  min-height: 100vh;
  overflow-x: clip;
  background: var(--vs-bg);
  background-image:
    radial-gradient(
      1100px 550px at 72% -10%,
      rgba(100, 140, 200, 0.07),
      transparent 55%
    ),
    radial-gradient(
      700px 500px at -5% 90%,
      rgba(80, 60, 150, 0.05),
      transparent 55%
    );
  color: var(--vs-text);
  font-family: var(--vs-sans);
}

/* Nav */
.vs-home-nav {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 14px 36px;
  border-bottom: 1px solid var(--vs-hair);
  position: sticky;
  top: 0;
  /* Frosted theme bg (was a hardcoded dark navy that stayed dark on light themes).
     color-mix keeps the translucency so content blurs through. */
  background: color-mix(in srgb, var(--vs-bg) 88%, transparent);
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
  z-index: 100;
}

.vs-home-logo-link {
  display: flex;
  align-items: center;
  gap: 10px;
  text-decoration: none;
}

.vs-home-logo-text {
  font-family: var(--vs-display);
  font-size: 20px;
  font-weight: 600;
  color: var(--vs-text);
  letter-spacing: -0.01em;
}

.vs-home-logo-text em {
  font-style: normal;
  color: var(--vs-blue);
}

.vs-home-nav-links {
  display: flex;
  align-items: center;
  gap: 18px;
}

.vs-home-mobile-menu {
  display: none;
}

.vs-home-mobile-menu-button {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 12px 16px;
  min-height: 44px;
  box-sizing: border-box;
  border-radius: 999px;
  border: 1px solid var(--vs-hair-2);
  background: var(--vs-surface);
  color: var(--vs-text-2);
  cursor: pointer;
  font-size: 13px;
  line-height: 1;
}

.vs-home-mobile-menu-button::-webkit-details-marker {
  display: none;
}

.vs-home-mobile-menu-panel {
  display: none;
  position: absolute;
  top: calc(100% + 12px);
  right: 36px;
  min-width: 220px;
  background: var(--vs-surface);
  border: 1px solid var(--vs-hair-2);
  border-radius: 18px;
  padding: 14px;
  box-shadow: 0 22px 60px rgba(0, 0, 0, 0.35);
  backdrop-filter: blur(14px);
  z-index: 110;
  display: grid;
  gap: 10px;
}

.vs-home-mobile-menu[open] .vs-home-mobile-menu-panel {
  display: grid;
}

/* Touch targets (~44px) + visible focus for mobile menu & nav (WCAG 2.1 AA) */
.vs-home-mobile-menu-panel .vs-home-nav-link {
  display: flex;
  align-items: center;
  min-height: 44px;
  padding: 4px 8px;
  font-size: 15px;
}
.vs-home-mobile-menu-panel .vs-home-nav-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
}
.vs-home-nav-link:focus-visible,
.vs-home-nav-btn:focus-visible,
.vs-home-mobile-menu-button:focus-visible,
.vs-home-logo-link:focus-visible {
  outline: 2px solid var(--vs-accent);
  outline-offset: 3px;
  border-radius: 8px;
}

.vs-home-nav-link,
.vs-home-nav-btn {
  transition: color 0.15s, opacity 0.15s, transform 0.15s;
}

.vs-home-nav-link {
  font-size: 13px;
  font-weight: 500;
  color: var(--vs-muted);
  text-decoration: none;
}

.vs-home-nav-link:hover {
  color: var(--vs-text);
}

.vs-home-nav-btn {
  font-size: 13px;
  font-weight: 600;
  color: var(--vs-bg-deep);
  background: var(--vs-accent);
  text-decoration: none;
  padding: 7px 17px;
  border-radius: 20px;
  letter-spacing: 0.01em;
  transition: opacity 0.15s;
}

.vs-home-nav-btn:hover {
  opacity: 0.85;
}

/* Hero */
.vs-home-hero {
  padding: 32px 36px 56px;
  max-width: 1200px;
  margin: 0 auto;
  position: relative;
  text-align: center;
}

.vs-home-hero-glow {
  position: absolute;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  width: min(1000px, 95%);
  height: 380px;
  border-radius: 50%;
  background: radial-gradient(
    ellipse,
    rgba(var(--vs-tint), 0.12) 0%,
    transparent 52%
  );
  pointer-events: none;
}

.vs-home-hero-copy {
  max-width: 640px;
  margin: 0 auto 40px;
  text-align: center;
  position: relative;
}

.vs-home-hero-spools {
  position: relative;
}

/* Delight: hero spools roll into place on load — a gentle tilt + rise,
   cascading left to right. Neutralized under prefers-reduced-motion. */
@keyframes vs-spool-rollin {
  from { opacity: 0; transform: translateY(22px) rotate(-14deg) scale(0.92); }
  to   { opacity: 1; transform: none; }
}
.vs-home-hero-spools .vs-home-face-item {
  animation: vs-spool-rollin 0.55s var(--vs-ease) both;
}
.vs-home-hero-spools .vs-home-face-item:nth-child(1) { animation-delay: 0.04s; }
.vs-home-hero-spools .vs-home-face-item:nth-child(2) { animation-delay: 0.10s; }
.vs-home-hero-spools .vs-home-face-item:nth-child(3) { animation-delay: 0.16s; }
.vs-home-hero-spools .vs-home-face-item:nth-child(4) { animation-delay: 0.22s; }
.vs-home-hero-spools .vs-home-face-item:nth-child(5) { animation-delay: 0.28s; }
.vs-home-hero-spools .vs-home-face-item:nth-child(6) { animation-delay: 0.34s; }
.vs-home-hero-spools .vs-home-face-item:nth-child(7) { animation-delay: 0.40s; }
.vs-home-hero-spools .vs-home-face-item:nth-child(8) { animation-delay: 0.46s; }

.vs-home-eyebrow {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--vs-accent);
  margin-bottom: 14px;
}

.vs-home-headline {
  font-size: 50px;
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -0.028em;
  margin: 0 0 18px;
  color: var(--vs-text);
  text-wrap: balance;
}

.vs-home-sub {
  font-size: 16px;
  color: var(--vs-text-2);
  line-height: 1.65;
  margin: 0 auto 30px; /* auto-center the 420px box inside the wider hero column */
  max-width: 420px;
}

.vs-home-bullets {
  list-style: none;
  padding: 0;
  margin: 0 auto 24px;
  max-width: 420px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  text-align: left;
}

.vs-home-bullets li {
  font-size: 13px;
  color: var(--vs-text-2);
  padding-left: 18px;
  position: relative;
}

.vs-home-bullets li::before {
  content: "✦";
  position: absolute;
  left: 0;
  color: var(--vs-accent);
  font-size: 9px;
  top: 3px;
}

.vs-home-cta-row {
  display: flex;
  gap: 14px;
  align-items: center;
  flex-wrap: wrap;
  justify-content: center;
}

/* Social proof stats (real catalog numbers) */
.vs-home-stats {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 20px;
  margin-top: 28px;
}
.vs-home-stat-num {
  font-size: 22px;
  font-weight: 700;
  color: var(--vs-text);
}
.vs-home-stat-label {
  font-size: 13px;
  color: var(--vs-muted);
}
.vs-home-stat-divider {
  width: 1px;
  height: 26px;
  background: var(--vs-hair-2);
}

/* "Live preview" label with a small status dot */
.vs-home-demo-label--live {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
}
.vs-home-demo-label--live::before {
  content: "";
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--vs-secondary);
}

.vs-home-hero .vs-home-cta-row {
  justify-content: center;
}

.vs-home-cta-primary {
  display: inline-block;
  padding: 12px 26px;
  background: var(--vs-accent);
  color: var(--vs-bg-deep);
  text-decoration: none;
  border-radius: 24px;
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.01em;
  transition:
    opacity 0.15s,
    transform 0.12s;
}

.vs-home-cta-primary:hover {
  opacity: 0.86;
  transform: translateY(-1px);
}

.vs-home-cta-primary:focus-visible {
  outline: 2px solid var(--vs-accent);
  outline-offset: 3px;
}

/* Delight: the arrow nudges forward on hover/focus. */
.vs-cta-arrow {
  display: inline-block;
  transition: transform 0.18s var(--vs-ease);
}
.vs-home-cta-primary:hover .vs-cta-arrow,
.vs-home-cta-primary:focus-visible .vs-cta-arrow {
  transform: translateX(4px);
}

/* Delight: a very subtle light sweep across the CTA on hover. */
.vs-home-cta-primary {
  position: relative;
  overflow: hidden;
}
.vs-home-cta-primary::after {
  content: "";
  position: absolute;
  top: 0;
  left: -60%;
  width: 45%;
  height: 100%;
  background: linear-gradient(100deg, transparent, rgba(255, 255, 255, 0.18), transparent);
  transform: skewX(-18deg);
  opacity: 0;
  pointer-events: none;
}
.vs-home-cta-primary:hover::after {
  animation: vs-cta-sheen 0.7s var(--vs-ease);
}
@keyframes vs-cta-sheen {
  0%   { left: -60%; opacity: 0; }
  18%  { opacity: 1; }
  100% { left: 120%; opacity: 0; }
}

/* Delight: sections fade + rise as they scroll into view (armed by JS so they
   never stay hidden when JS is off; reduced-motion shows them instantly). */
@keyframes vs-reveal-up {
  from { opacity: 0; transform: translateY(24px); }
  to   { opacity: 1; transform: none; }
}
.vs-reveal-up.vs-reveal-armed {
  opacity: 0;
  transform: translateY(24px);
}
.vs-reveal-up.vs-revealed {
  animation: vs-reveal-up 0.6s var(--vs-ease) both;
}

/* Delight: the homepage logo spins once on hover (matches the app masthead). */
.vs-home-logo-link img {
  transition: transform 0.2s var(--vs-ease);
}
.vs-home-logo-link:hover img {
  animation: vs-logo-spin 3.5s linear 1;
}

/* Delight: the "Running low" figure gently pulses to draw the eye. */
.vs-home-depletion-pct--low {
  animation: vs-low-nudge 2.2s ease-in-out infinite;
}
@keyframes vs-low-nudge {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.45; }
}

.vs-home-cta-primary--glow {
  box-shadow: 0 14px 26px rgba(22, 44, 80, 0.18);
  transition: opacity 0.15s, transform 0.12s, box-shadow 0.2s;
}

.vs-home-cta-primary--glow:hover {
  box-shadow: 0 16px 32px rgba(22, 44, 80, 0.22);
}

.vs-home-cta-primary--large {
  padding: 14px 34px;
  font-size: 15px;
}

.vs-home-cta-ghost {
  display: inline-block;
  padding: 12px 22px;
  border: 1px solid var(--vs-hair-2);
  color: var(--vs-text-2);
  text-decoration: none;
  border-radius: 24px;
  font-size: 14px;
  font-weight: 500;
  transition:
    border-color 0.15s,
    color 0.15s;
}

.vs-home-cta-ghost:hover {
  border-color: var(--vs-accent);
  color: var(--vs-text);
}

/* Demo shelf wall */
.vs-home-demo-wall {
  position: relative;
  padding: 44px 36px 30px;
  /* Square the bottom corners so it reads like a shelf cabinet on the floor,
     not a floating pill; tighter top corners (was 52px) for a less pill-like,
     more cabinet-like feel. */
  border-radius: 20px 20px 0 0;
  background: rgba(255,255,255,0.055);
  max-width: 1040px;
  width: 100%;
  margin: 0 auto;
  justify-self: center;
}

/* Inner cabinet frame: square its bottom too (scoped to the homepage/Features
   demo only — the real Shelves page keeps its rounded frame). */
.vs-home-demo-wall .vs-storage-unit-frame {
  border-radius: 0;
}

.vs-home-demo-wall::before {
  content: "";
  position: absolute;
  inset: -24px;
  background: radial-gradient(circle at 60% 12%, rgba(120,152,191,0.11), transparent 48%);
  filter: blur(32px);
  opacity: 0.9;
  z-index: -1;
}

/* On load, pulse once to hint that the spools are interactive */
@keyframes vs-demo-hint {
  0%   { opacity: 1;    transform: scale(1); }
  40%  { opacity: 0.72; transform: scale(0.985); }
  100% { opacity: 1;    transform: scale(1); }
}

.vs-home-demo-units {
  animation: vs-demo-hint 1.6s ease-in-out 0.9s 1 both;
}

/* Touch devices: activate specialty textures on tap/click instead of hover.
   We make the demo wall a focus container so clicking inside triggers
   :focus-within, which the spool SVG CSS can key off of. The hover rules
   already handle pointer devices. */
@media (hover: none) {
  .vs-home-demo-units:focus-within .vs-spool-specialty-overlay,
  .vs-home-demo-units:active .vs-spool-specialty-overlay {
    opacity: 1 !important;
  }
}

.vs-home-demo-label {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.14em;
  color: var(--vs-muted);
  text-align: center;
  margin-bottom: 14px;
  text-transform: uppercase;
}

.vs-home-demo-units {
  display: flex;
  gap: 16px;
  align-items: flex-start;
  justify-content: center;
}

/* De-layer the homepage demo: one cabinet, open shelves (no card-in-card).
   Scoped to the homepage demo so the real Shelves page is untouched. */
.vs-home-demo-wall .vs-shelf {
  background: none;
  border: none;
  border-radius: 0;
  box-shadow: none;
}
.vs-home-demo-wall .vs-shelf + .vs-shelf {
  border-top: 1px solid var(--vs-hair);
}

.vs-home-storage-unit .vs-storage-unit-head {
  display: none;
}

/* Homepage demo only: keep each shelf on a single row (scroll if squished)
   instead of wrapping to a second row. Does NOT touch the real Shelves page,
   where wrapping is intended. */
.vs-home-demo-wall .vs-shelf-area {
  flex-wrap: nowrap;
  /* clip (not hidden) on X so the row stays single-line WITHOUT forcing
     overflow-y to auto — that was clipping the spool hover tooltips at the top
     shelf. clip lets overflow-y:visible hold, so tooltips escape upward. */
  overflow-x: clip;
  overflow-y: visible;
  justify-content: center;
}
/* The flex children are .vs-shelf-spool wrappers, which carry an inline
   flex-shrink:0. Override so they shrink to fit; the inner SVG scales via its
   viewBox. Capped at natural size on wide screens (desktop unchanged). */
.vs-home-demo-wall .vs-shelf-spool {
  flex: 0 1 46px !important; /* natural size; shrink only if the row would overflow */
  min-width: 0;
}
.vs-home-demo-wall .vs-shelf-spool .vs-spool-side {
  width: 100%;
  height: auto;
  display: block;
}
@media (max-width: 1280px) {
  /* Narrow: stack the shelf label on top so the spools get the full width
     instead of being squeezed beside the 130px label column. */
  .vs-home-demo-wall .vs-shelf {
    grid-template-columns: 1fr;
    gap: 6px;
  }
  .vs-home-demo-wall .vs-shelf-header {
    border-right: none;
    padding-bottom: 2px;
  }
}

/* Sections */
.vs-home-section {
  padding: 88px 36px;
  position: relative;
}

.vs-home-section-inner {
  max-width: 1200px;
  margin: 0 auto;
}

.vs-home-section-head {
  text-align: center;
  max-width: 560px;
  margin: 0 auto 52px;
}

.vs-home-section-title {
  font-size: 34px;
  font-weight: 700;
  letter-spacing: -0.022em;
  line-height: 1.18;
  margin: 0 0 12px;
  color: var(--vs-text);
}

.vs-home-section-sub {
  font-size: 15px;
  color: var(--vs-text-2);
  line-height: 1.65;
  margin: 0;
}

/* Material Personality */
.vs-home-materials {
  background: linear-gradient(180deg, rgba(120,152,191,0.04) 0%, var(--vs-bg-tint) 60px);
  border-top: 1px solid var(--vs-hair);
  border-bottom: 1px solid var(--vs-hair);
}

.vs-home-mat-grid {
  display: flex;
  gap: 20px;
  justify-content: center;
  flex-wrap: wrap;
}

.vs-home-face-showcase {
  background: var(--vs-bg-deep, #0a0c14);
  border-top: 1px solid var(--vs-hair);
  border-bottom: 1px solid var(--vs-hair);
}

.vs-home-face-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 32px 24px;
  max-width: 1180px;
  margin: 0 auto;
}

/* Mobile: show two spools per row (renders scale down to fit) so users
   don't have to scroll a whole screen height per spool. */
@media (max-width: 640px) {
  .vs-home-face-grid {
    grid-template-columns: 1fr 1fr;
    gap: 24px 12px;
  }
}

/* Depletion before/after — the render empties with the spool. Two states
   (full vs running low) of the same filament so only the fill differs.
   The two states stay side by side at every width; the renders scale
   fluidly (clamp) so they're large on desktop and shrink to fit on mobile. */
.vs-home-depletion-grid {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(6px, 2vw, 28px);
  flex-wrap: nowrap;
}
.vs-home-depletion-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(12px, 2vw, 18px);
  min-width: 0;
  padding: clamp(16px, 2.5vw, 30px) clamp(12px, 3vw, 40px);
  border: 1px solid var(--vs-hair);
  border-radius: 18px;
  background: rgba(255, 255, 255, 0.015);
}
.vs-home-depletion-renders {
  display: flex;
  align-items: center;
  gap: clamp(8px, 2vw, 24px);
}
/* Face render (square) scales by width; side render scales by height so the
   pair stays proportional as they shrink. */
.vs-home-depletion-renders > svg {
  width: clamp(64px, 18vw, 210px);
  height: auto;
}
.vs-home-depletion-renders .vs-shelf-spool {
  flex-shrink: 1 !important;
}
.vs-home-depletion-renders .vs-spool-side {
  height: clamp(64px, 18vw, 210px);
  width: auto;
}
.vs-home-depletion-caption {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
}
.vs-home-depletion-name {
  font-size: clamp(12px, 2.4vw, 14px);
  font-weight: 600;
  color: var(--vs-text);
}
.vs-home-depletion-pct {
  font-family: var(--vs-mono);
  font-size: clamp(10px, 2.2vw, 12px);
  letter-spacing: 0.02em;
  color: var(--vs-text-2);
}
.vs-home-depletion-name--low,
.vs-home-depletion-pct--low {
  color: var(--vs-danger);
}
.vs-home-depletion-arrow {
  color: var(--vs-muted);
  flex-shrink: 0;
}

/* Active nav link (e.g. Features page) */
.vs-home-nav-link--active {
  color: var(--vs-text);
}

/* Features page — "everything else" capability cards */
.vs-feat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 20px;
  max-width: 1000px;
  margin: 0 auto;
}
.vs-feat-card {
  padding: 26px 28px;
  border: 1px solid var(--vs-hair);
  border-radius: 16px;
  background: rgba(255, 255, 255, 0.015);
}
.vs-feat-card h3 {
  font-size: 16px;
  font-weight: 600;
  margin: 0 0 8px;
  color: var(--vs-text);
}
.vs-feat-card p {
  font-size: 14px;
  line-height: 1.6;
  color: var(--vs-text-2);
  margin: 0;
}

/* Features page — live catalog table teaser */
.vs-feat-catalog {
  max-width: 1000px;
  margin: 0 auto;
}
.vs-feat-catalog-more {
  text-align: center;
  margin-top: 22px;
}
.vs-feat-link {
  display: inline-block;
  font-size: 14px;
  font-weight: 600;
  color: var(--vs-accent);
  text-decoration: none;
  padding: 10px 18px;
  border: 1px solid var(--vs-hair);
  border-radius: 10px;
  transition: border-color 0.15s, color 0.15s;
}
.vs-feat-link:hover {
  border-color: var(--vs-accent);
}

/* ── Small utility classes (extracted from repeated inline styles) ──────────
   Each is byte-identical to the inline declarations it replaces, so swapping
   style="..." for the class is a pure refactor with no visual change. */
.vs-link {
  /* Follow the theme accent (was the fixed info-blue, which clashed on warm/light
     themes). Covers brand links, breadcrumbs, "N spools", "View all colors", etc. */
  color: var(--vs-accent);
  text-decoration: none;
}
.vs-meta {
  font-size: 11px;
  color: var(--vs-muted);
}
.vs-field-label {
  display: block;
  color: var(--vs-muted);
  font-size: 12px;
  margin-bottom: 4px;
}
.vs-input {
  width: 100%;
  background: var(--vs-bg-deep);
  border: 1px solid var(--vs-hair-2);
  border-radius: 4px;
  padding: 8px 10px;
  color: var(--vs-text);
  font-size: 14px;
  font-family: inherit;
  box-sizing: border-box;
}
.vs-input--area {
  resize: vertical;
  min-height: 120px;
}

/* Compact spec table (filament detail print/drying settings) */
.vs-spec-table {
  border-collapse: collapse;
  margin-top: 10px;
  font-size: 14px;
  min-width: 280px;
  max-width: 460px;
  width: 100%;
}
.vs-spec-table th,
.vs-spec-table td {
  text-align: left;
  padding: 9px 14px;
  border-bottom: 1px solid var(--vs-hair-2);
}
.vs-spec-table th {
  color: var(--vs-muted);
  font-weight: 500;
  white-space: nowrap;
  width: 40%;
}
.vs-spec-table td {
  color: var(--vs-text);
}
.vs-spec-table tr:last-child th,
.vs-spec-table tr:last-child td {
  border-bottom: none;
}

/* Filament detail — hero: renders left, identity right; stacks on narrow screens */
.vs-fil-hero {
  display: flex;
  flex-wrap: wrap;
  gap: 24px 48px;
  align-items: flex-start;
  margin: 16px 0 32px;
}
.vs-fil-hero-renders {
  display: flex;
  gap: 24px;
  align-items: flex-end;
  flex: 0 1 auto;
  min-width: 0;
  max-width: 100%;
}
/* On narrow screens the whole row shrinks; both renders scale in proportion
   (the SVGs carry viewBoxes). BOTH views ship inline flex-shrink:0 (the face
   svg and the side's .vs-shelf-spool wrapper, needed elsewhere), so each must
   be overridden here or one render hogs the row and the other gets crushed. */
.vs-fil-hero-renders > svg {
  flex-shrink: 1 !important;
  min-width: 0;
  height: auto;
  aspect-ratio: 1 / 1;
}
.vs-fil-hero-renders .vs-shelf-spool {
  flex-shrink: 1 !important;
  min-width: 0;
}
.vs-fil-hero-renders .vs-spool-side {
  max-width: 100%;
  height: auto;
}
/* Phones: keep the face render the star but not edge-to-edge huge; the side
   view takes the leftover width at its natural proportion. */
@media (max-width: 560px) {
  .vs-fil-hero-renders {
    gap: 18px;
  }
  .vs-fil-hero-renders > svg {
    max-width: 64vw;
  }
}
.vs-fil-hero-info {
  flex: 1 1 340px;
  min-width: 280px;
}
/* Long filament names wrap to 2-3 lines; give them comfortable leading */
.vs-fil-hero-info .vs-page-title {
  line-height: 1.3;
}

/* Filament detail — collapsible spec cards (native details/summary: no JS,
   content stays in the HTML for crawlers) */
.vs-fil-card {
  flex: 1 1 340px;
  min-width: 280px;
  background: var(--vs-surface);
  border: 1px solid var(--vs-hair-2);
  border-radius: 14px;
  padding: 18px 20px;
}
.vs-fil-card > summary {
  cursor: pointer;
  list-style: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  user-select: none;
}
.vs-fil-card > summary::-webkit-details-marker {
  display: none;
}
.vs-fil-card > summary h2 {
  margin: 0;
  font-size: 16px;
  color: var(--vs-text);
}
.vs-fil-card > summary::after {
  content: "";
  width: 9px;
  height: 9px;
  border-right: 2px solid var(--vs-accent);
  border-bottom: 2px solid var(--vs-accent);
  transform: rotate(45deg);
  transition: transform 0.15s var(--vs-ease, ease);
  flex-shrink: 0;
}
.vs-fil-card[open] > summary::after {
  transform: rotate(225deg);
}
.vs-fil-card > summary:hover h2 {
  color: var(--vs-accent);
}
.vs-fil-card > summary:hover::after {
  border-color: var(--vs-accent);
}
.vs-fil-card[open] > summary {
  margin-bottom: 12px;
}

/* Filament detail — Your-spools cards. Roomy horizontal cards on desktop;
   two-up compact column cards on phones. */
.vs-fil-own-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  margin: 12px 0 28px;
}
.vs-fil-own {
  display: flex;
  align-items: center;
  gap: 14px;
  background: var(--vs-surface);
  border: 1px solid var(--vs-hair-2);
  border-radius: 14px;
  padding: 12px 16px;
  text-decoration: none;
  min-width: 230px;
}
@media (max-width: 560px) {
  .vs-fil-own-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
  }
  .vs-fil-own {
    min-width: 0;
    gap: 10px;
    padding: 10px 12px;
  }
  /* Shrink the render (it's authored at 84px) so the stats fit beside it
     even in a half-width card. */
  .vs-fil-own > svg {
    width: 56px;
    height: 56px;
  }
}

/* Filament detail — star rating input. Pure CSS so it works on the static-SSR
   public page: stars render 5→1 in a reversed row, so "this label and every
   label after it" lights the chosen star and the ones below it. */
.vs-star-rate {
  display: inline-flex;
  flex-direction: row-reverse;
}
.vs-star-rate label {
  cursor: pointer;
  font-size: 26px;
  line-height: 1;
  padding: 2px 3px;
  color: var(--vs-faint);
  transition: color 0.15s var(--vs-ease, ease);
}
.vs-star-rate input {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}
.vs-star-rate label:has(input:checked),
.vs-star-rate label:has(input:checked) ~ label,
.vs-star-rate label:hover,
.vs-star-rate label:hover ~ label {
  color: var(--vs-warning);
}
.vs-star-rate label:has(input:focus-visible) {
  outline: 2px solid var(--vs-info);
  outline-offset: 1px;
  border-radius: 6px;
}

/* Filament detail — color chip. As a <button> it copies its hex on click; the
   hex value itself stays hidden until hover/keyboard focus. */
.vs-color-chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: var(--vs-surface);
  border: 1px solid var(--vs-hair-2);
  border-radius: 20px;
  padding: 5px 12px 5px 6px;
  font-family: inherit;
  font-size: 13px;
  color: var(--vs-text-2);
}
button.vs-color-chip,
a.vs-color-chip {
  cursor: pointer;
}
a.vs-color-chip {
  text-decoration: none;
}
button.vs-color-chip:hover,
button.vs-color-chip:focus-visible,
a.vs-color-chip:hover,
a.vs-color-chip:focus-visible {
  border-color: var(--vs-accent);
}
.vs-color-chip-dot {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  border: 1px solid #444;
  flex-shrink: 0;
}
.vs-color-chip .vs-hex {
  display: none;
  font-size: 12px;
  color: var(--vs-muted);
  letter-spacing: 0.02em;
}
.vs-color-chip:hover .vs-hex,
.vs-color-chip:focus-visible .vs-hex {
  display: inline;
}
/* Measured translucency (TD) pill on a color chip. Always visible — it's tested
   data worth showing, unlike the hover-only hex. */
.vs-color-chip .vs-td-badge {
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.03em;
  color: var(--vs-muted);
  background: var(--vs-faint-bg, rgba(127, 127, 150, 0.14));
  border-radius: 5px;
  padding: 1px 5px;
  flex-shrink: 0;
}

/* Filament detail — related-filament cards ("More in this series") */
.vs-fil-sib {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  width: 128px;
  padding: 14px 10px;
  background: var(--vs-surface);
  border: 1px solid var(--vs-hair-2);
  border-radius: 14px;
  text-decoration: none;
  text-align: center;
  transition: border-color 0.15s, transform 0.15s;
}
.vs-fil-sib:hover {
  border-color: var(--vs-accent);
  transform: translateY(-2px);
}
.vs-fil-sib span {
  font-size: 12px;
  color: var(--vs-text-2);
  line-height: 1.35;
}
@media (prefers-reduced-motion: reduce) {
  .vs-fil-sib,
  .vs-fil-sib:hover {
    transition: none;
    transform: none;
  }
}

/* Filament detail — auto-generated narrative sections (Print characteristics,
   Strengths, Weaknesses, Best uses…). Driven by Material property fields; each
   renders only when it has data. */
.vs-fil-section {
  margin: 28px 0 0;
}
.vs-fil-section > h2 {
  font-size: 16px;
  color: var(--vs-text);
  margin: 0 0 12px;
}
.vs-fil-section-lead {
  font-size: 14px;
  color: var(--vs-text-2);
  line-height: 1.6;
  max-width: 680px;
  margin: 0 0 14px;
}

/* Low / Medium / High property chips */
.vs-prop-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}
.vs-prop-chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: var(--vs-surface);
  border: 1px solid var(--vs-hair-2);
  border-left-width: 3px;
  border-radius: 10px;
  padding: 7px 13px;
  font-size: 13px;
  color: var(--vs-text-2);
}
.vs-prop-chip .vs-prop-level {
  font-weight: 600;
  color: var(--vs-text);
}
.vs-prop-chip[data-tone="good"] {
  border-left-color: var(--vs-success);
}
.vs-prop-chip[data-tone="good"] .vs-prop-level {
  color: var(--vs-success);
}
.vs-prop-chip[data-tone="caution"] {
  border-left-color: var(--vs-warning);
}
.vs-prop-chip[data-tone="caution"] .vs-prop-level {
  color: var(--vs-warning);
}

/* Strengths / weaknesses bullet lists with a leading icon */
.vs-trait-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 9px;
  max-width: 640px;
}
.vs-trait-list li {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  font-size: 14px;
  color: var(--vs-text-2);
  line-height: 1.5;
}
.vs-trait-list svg {
  flex-shrink: 0;
  margin-top: 2px;
}
.vs-trait-list--good svg {
  color: var(--vs-success);
}
.vs-trait-list--caution svg {
  color: var(--vs-warning);
}

/* Simple tag pills (best uses, finishing options) */
.vs-tag-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.vs-tag {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  color: var(--vs-text-2);
  background: var(--vs-surface-2);
  border: 1px solid var(--vs-hair-2);
  border-radius: 20px;
  padding: 5px 13px;
}
.vs-tag--muted {
  background: transparent;
  color: var(--vs-muted);
}

/* QR label scanner overlay (vs-helpers VSQrScan) */
.vs-qr-overlay {
  position: fixed;
  inset: 0;
  z-index: 4000;
  background: #05070d;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}
.vs-qr-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.vs-qr-top {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 18px;
  color: #e8ecf2;
  font-size: 14px;
  font-weight: 600;
  background: linear-gradient(rgba(5, 7, 13, 0.85), transparent);
}
.vs-qr-close {
  background: rgba(5, 7, 13, 0.6);
  border: 1px solid rgba(255, 255, 255, 0.25);
  color: #e8ecf2;
  border-radius: 50%;
  width: 38px;
  height: 38px;
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
}
.vs-qr-frame {
  position: relative;
  z-index: 1;
  width: min(62vw, 280px);
  aspect-ratio: 1 / 1;
  border-radius: 18px;
  box-shadow: 0 0 0 9999px rgba(5, 7, 13, 0.45);
  outline: 2px solid rgba(255, 255, 255, 0.8);
}
.vs-qr-hint {
  position: absolute;
  bottom: 36px;
  left: 0;
  right: 0;
  z-index: 2;
  text-align: center;
  color: rgba(232, 236, 242, 0.85);
  font-size: 13px;
  padding: 0 24px;
}
@media (max-width: 560px) {
  .vs-qr-btn-label {
    display: none;   /* icon-only scan button on phones */
  }
}

/* Features page — compact header (smaller + tighter than the homepage hero) */
.vs-feat-header {
  max-width: 760px;
  margin: 0 auto;
  padding: 60px 24px 36px;
  text-align: center;
}
.vs-feat-title {
  font-size: 40px;
  font-weight: 700;
  line-height: 1.12;
  letter-spacing: -0.025em;
  margin: 8px 0 16px;
  color: var(--vs-text);
  text-wrap: balance;
}
.vs-feat-lede {
  font-size: 16px;
  line-height: 1.6;
  color: var(--vs-text-2);
  max-width: 560px;
  margin: 0 auto 26px;
}

/* Features page — alternating (zigzag) feature rows */
.vs-feat-rows {
  max-width: 1060px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: 76px;
}
.vs-feat-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 56px;
  align-items: center;
}
/* Copy is first in the DOM (reading order); visual sits left by default and
   right on --rev rows, giving the alternating zigzag on desktop. */
.vs-feat-row-visual {
  display: flex;
  justify-content: center;
  order: -1;
}
.vs-feat-row--rev .vs-feat-row-visual {
  order: 1;
}
.vs-feat-eyebrow {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--vs-accent);
  margin-bottom: 10px;
}
.vs-feat-row-title {
  font-size: 27px;
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.02em;
  margin: 0 0 12px;
  color: var(--vs-text);
}
.vs-feat-row-text {
  font-size: 15px;
  line-height: 1.6;
  color: var(--vs-text-2);
  margin: 0 0 18px;
}
.vs-feat-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.vs-feat-list li {
  position: relative;
  padding-left: 26px;
  font-size: 14px;
  color: var(--vs-text);
  line-height: 1.45;
}
.vs-feat-list li::before {
  content: "✓";
  position: absolute;
  left: 0;
  top: 0;
  color: var(--vs-accent);
  font-weight: 700;
}
.vs-feat-render-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 22px 18px;
}
/* The shelf cabinet sits inside a zigzag half-column; drop the big rounded
   demo-wall chrome and let it fill the column cleanly. */
.vs-feat-shelf-wall {
  padding: 18px;
  border-radius: 14px 14px 0 0;
  width: 100%;
}
.vs-feat-shelf-wall::before {
  display: none;
}

@media (max-width: 820px) {
  .vs-feat-rows {
    gap: 52px;
  }
  .vs-feat-row {
    grid-template-columns: 1fr;
    gap: 28px;
  }
  /* Stack copy first, visual below, on every row. */
  .vs-feat-row-visual,
  .vs-feat-row--rev .vs-feat-row-visual {
    order: 2;
  }
  .vs-feat-title {
    font-size: 32px;
  }
}

.vs-home-face-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
}

.vs-home-face-item svg,
.vs-home-face-item canvas {
  max-width: 100%;
  height: auto;
  transition: filter 0.4s;
  /* Turn only while hovered — paused (not removed) so it holds its angle when
     the cursor leaves instead of snapping back to 0. */
  animation: vs-collector-spin 12s linear infinite;
  animation-play-state: paused;
}

.vs-home-face-item:hover svg,
.vs-home-face-item:hover canvas {
  animation-play-state: running;
}

@media (prefers-reduced-motion: reduce) {
  .vs-home-face-item svg,
  .vs-home-face-item canvas { animation: none; }
}

.vs-home-face-label {
  font-family: var(--vs-sans);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  text-align: center;
}
.vs-home-face-brand {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--vs-muted);
}
.vs-home-face-name {
  font-size: 13px;
  font-weight: 600;
  color: var(--vs-text);
}

.vs-home-mat-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
}

.vs-home-mat-label {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--vs-muted);
}

/* Workflow section */
/* Studio section gets a tinted band so the major sections alternate
   base -> tint -> base -> tint down the page (the depletion section stays
   plain, sandwiched between the tinted Studio and Workflow bands). */
.vs-home-studio-section {
  background: linear-gradient(180deg, var(--vs-bg-tint) 0%, var(--vs-bg) 100%);
  border-top: 1px solid var(--vs-hair);
  border-bottom: 1px solid var(--vs-hair);
}

/* Studio section: two-column (copy left, cabinet right) to break the
   centered rhythm. Stacks on mobile. */
.vs-home-studio-inner {
  display: grid;
  grid-template-columns: minmax(0, 340px) minmax(0, 1fr);
  gap: 56px;
  align-items: center;
}
.vs-home-studio-inner .vs-home-demo-wall {
  max-width: none;
  margin: 0;
}

/* Delight: studio spools drop into their shelves as the section scrolls into
   view (armed by JS so they don't vanish when JS is off). Staggered per shelf. */
@keyframes vs-spool-dropin {
  from { opacity: 0; transform: translateY(-22px); }
  to   { opacity: 1; transform: none; }
}
.vs-home-demo-wall.vs-reveal-armed .vs-shelf-spool {
  opacity: 0;
}
.vs-home-demo-wall.vs-revealed .vs-shelf-spool {
  animation: vs-spool-dropin 0.5s var(--vs-ease) both;
}
.vs-home-demo-wall.vs-revealed .vs-shelf-area .vs-shelf-spool:nth-child(1) { animation-delay: 0.03s; }
.vs-home-demo-wall.vs-revealed .vs-shelf-area .vs-shelf-spool:nth-child(2) { animation-delay: 0.07s; }
.vs-home-demo-wall.vs-revealed .vs-shelf-area .vs-shelf-spool:nth-child(3) { animation-delay: 0.11s; }
.vs-home-demo-wall.vs-revealed .vs-shelf-area .vs-shelf-spool:nth-child(4) { animation-delay: 0.15s; }
.vs-home-demo-wall.vs-revealed .vs-shelf-area .vs-shelf-spool:nth-child(5) { animation-delay: 0.19s; }
.vs-home-demo-wall.vs-revealed .vs-shelf-area .vs-shelf-spool:nth-child(6) { animation-delay: 0.23s; }
.vs-home-demo-wall.vs-revealed .vs-shelf-area .vs-shelf-spool:nth-child(7) { animation-delay: 0.27s; }
.vs-home-demo-wall.vs-revealed .vs-shelf-area .vs-shelf-spool:nth-child(8) { animation-delay: 0.31s; }
.vs-home-demo-wall.vs-revealed .vs-shelf-area .vs-shelf-spool:nth-child(9) { animation-delay: 0.35s; }
@media (max-width: 860px) {
  .vs-home-studio-inner {
    grid-template-columns: 1fr;
    gap: 28px;
  }
}

.vs-home-workflow-section {
  background: linear-gradient(180deg, var(--vs-bg-tint) 0%, var(--vs-bg) 100%);
  border-top: 1px solid var(--vs-hair);
  border-bottom: 1px solid var(--vs-hair);
}

/* Tighter container so the panel + copy sit adjacent and centered (no big gap) */
.vs-home-workflow-section .vs-home-section-inner {
  max-width: 1000px;
}

.vs-home-workflow-inner {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 400px);
  gap: 64px;
  align-items: center;
}

/* Reversed vs the hero: pegboard panel on the left, copy on the right
   (DOM order stays copy-first for reading/SEO). */
.vs-home-workflow-copy {
  max-width: 420px;
  grid-column: 2;
  grid-row: 1;
}

.vs-home-workflow-panel {
  grid-column: 1;
  grid-row: 1;
  display: flex;
  flex-direction: column;
  gap: 24px;
  padding: 24px;
  /* Pegboard panel, matching the Studio sidebar */
  background-color: rgba(12, 16, 26, 0.84);
  background-image:
    radial-gradient(ellipse 90% 70% at 35% 20%, transparent 35%, rgba(0,0,0,0.12) 100%),
    linear-gradient(180deg, rgba(255,255,255,0.018) 0%, transparent 40%, rgba(0,0,0,0.10) 100%),
    linear-gradient(165deg, rgba(255,255,255,0.018) 0%, transparent 45%, rgba(0,0,0,0.055) 100%),
    radial-gradient(circle, rgba(200,215,240,0.030) 1.0px, rgba(200,215,240,0.014) 1.7px, transparent 1.7px);
  background-size: auto, auto, auto, 20px 20px;
  border: none;
  border-radius: var(--vs-radius-lg);
  box-shadow:
    inset 2px 0 0 rgba(200,215,240,0.06),
    inset 0 0 40px rgba(0,0,0,0.22);
}

.vs-home-workflow-panel-head {
  display: grid;
  gap: 12px;
}

.vs-home-workflow-panel-label {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--vs-muted);
}

.vs-home-workflow-panel-eyebrow {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--vs-text-2);
}

.vs-home-workflow-panel-title {
  font-size: 22px;
  line-height: 1.25;
  margin: 0;
  color: var(--vs-text);
}

.vs-home-workflow-panel-sub {
  font-size: 15px;
  line-height: 1.7;
  color: var(--vs-muted);
  margin: 0;
  max-width: 46ch;
}

.vs-home-wf-chips {
  display: grid;
  gap: 0;
}

/* Flattened: open status rows (no nested cards, no side-tab accent border) */
.vs-home-wf-chip {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 12px 2px;
}
.vs-home-wf-chip + .vs-home-wf-chip {
  border-top: 1px solid var(--vs-hair);
}
.vs-home-wf-chip-spools {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 5px;
  flex-shrink: 0;
}

.vs-home-wf-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  flex-shrink: 0;
}

.vs-home-wf-chip--inuse {
  border-left-color: var(--vs-secondary);
}
.vs-home-wf-chip--inuse .vs-home-wf-dot {
  background: var(--vs-secondary);
  color: var(--vs-secondary);
  /* Delight: the "Printing Now" dot softly pulses like a live status light. */
  animation: vs-wf-pulse 2.4s var(--vs-ease) infinite;
}
@keyframes vs-wf-pulse {
  0%   { box-shadow: 0 0 0 0 rgba(124, 200, 160, 0.5); }
  70%  { box-shadow: 0 0 0 6px rgba(124, 200, 160, 0); }
  100% { box-shadow: 0 0 0 0 rgba(124, 200, 160, 0); }
}
.vs-home-wf-chip--drying {
  border-left-color: var(--vs-warning);
}
.vs-home-wf-chip--drying .vs-home-wf-dot {
  background: var(--vs-warning);
  color: var(--vs-warning);
}
.vs-home-wf-chip--tostore {
  border-left-color: var(--vs-accent);
}
.vs-home-wf-chip--tostore .vs-home-wf-dot {
  background: var(--vs-accent);
  color: var(--vs-accent);
}
.vs-home-wf-chip--arrival {
  border-left-color: #80cc60;
}
.vs-home-wf-chip--arrival .vs-home-wf-dot {
  background: #80cc60;
  color: #80cc60;
}
.vs-home-wf-chip--bench {
  border-left-color: var(--vs-text-2);
}
.vs-home-wf-chip--bench .vs-home-wf-dot {
  background: var(--vs-text-2);
  color: var(--vs-text-2);
}

.vs-home-wf-label {
  font-size: 13px;
  font-weight: 600;
  color: var(--vs-text);
  margin-bottom: 2px;
  letter-spacing: 0.01em;
}

.vs-home-wf-desc {
  font-size: 12px;
  color: var(--vs-muted);
}

/* Final CTA */
.vs-home-founder-section {
  position: relative;
  overflow: hidden;
}

.vs-home-founder-photo {
  width: 100%;
  display: block;
  max-height: 420px;
  object-fit: cover;
  object-position: center 40%;
  transition: transform 0.6s var(--vs-ease);
}
/* Delight: gentle Ken-Burns zoom on hover (contained by the section's clip). */
.vs-home-founder-section:hover .vs-home-founder-photo {
  transform: scale(1.04);
}

.vs-home-founder-quote {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  padding: 60px 48px 40px;
  background: linear-gradient(0deg, rgba(13,18,23,1) 0%, rgba(13,18,23,0.92) 50%, rgba(13,18,23,0.4) 80%, transparent 100%);
}

.vs-home-founder-text {
  font-size: 20px;
  font-weight: 500;
  color: var(--vs-text);
  line-height: 1.5;
  margin: 0 0 12px;
  max-width: 680px;
  font-style: italic;
}

.vs-home-founder-attr {
  font-size: 13px;
  color: var(--vs-accent);
  font-weight: 600;
}

.vs-home-faq-section {
  padding: 72px 36px;
  border-top: 1px solid var(--vs-hair);
}

/* FAQ: narrower column + centered eyebrow (moved off inline styles) */
.vs-home-faq-section .vs-home-section-inner {
  max-width: 640px;
}
.vs-home-faq-section .vs-home-eyebrow {
  text-align: center;
  margin-bottom: 32px;
}

.vs-home-faq-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  border: 1px solid var(--vs-hair);
  border-radius: 16px;
  padding: 8px;
}

.vs-home-faq-item {
  background: var(--vs-surface);
  padding: 0;
  border-radius: 10px;
  overflow: hidden;
}

.vs-home-faq-q {
  font-size: 14px;
  font-weight: 600;
  color: var(--vs-text);
  padding: 24px 30px;
  cursor: pointer;
  list-style: none;
  display: flex;
  justify-content: space-between;
  align-items: center;
  user-select: none;
}

.vs-home-faq-q::-webkit-details-marker { display: none; }

.vs-home-faq-q::after {
  content: "+";
  font-size: 18px;
  font-weight: 300;
  color: var(--vs-faint);
  flex-shrink: 0;
  transition: transform 0.2s;
}

.vs-home-faq-item[open] .vs-home-faq-q::after {
  transform: rotate(45deg);
}

.vs-home-faq-a {
  font-size: 13px;
  color: var(--vs-text-2);
  line-height: 1.65;
  padding: 4px 30px 24px;
  margin: 0;
}

.vs-home-cta-section {
  position: relative;
  background: var(--vs-bg-tint);
  border-top: 1px solid var(--vs-hair);
}

.vs-home-cta-glow {
  position: absolute;
  top: -60px;
  left: 50%;
  transform: translateX(-50%);
  width: 700px;
  height: 300px;
  border-radius: 50%;
  background: radial-gradient(
    ellipse,
    rgba(var(--vs-tint), 0.07) 0%,
    transparent 65%
  );
  pointer-events: none;
}

.vs-home-cta-headline {
  font-size: 40px;
  font-weight: 700;
  letter-spacing: -0.022em;
  margin: 0 0 14px;
  color: var(--vs-text);
}

.vs-home-cta-sub {
  font-size: 16px;
  color: var(--vs-text-2);
  line-height: 1.6;
  max-width: 420px;
  margin: 0 auto 32px;
}

.vs-home-cta-fine {
  font-size: 12px;
  color: var(--vs-text-2);
  margin-top: 14px;
  letter-spacing: 0.03em;
}

/* Site footer (public/marketing pages). Prefixed .vs-sf-* so it never collides
   with the in-app workspace footer (.vs-app-footer / .vs-footer-*). */
.vs-sf {
  position: relative;
  border-top: 1px solid var(--vs-hair);
  margin-top: 72px;
}

/* Signature filament strip (SpectrumStrip.razor): a row of rounded spool-end
   bars. The SVG owns its look; this just seats it as a full-width block. */
.vs-strip {
  display: block;
  width: 100%;
}

.vs-sf-inner {
  max-width: 1180px;
  margin: 0 auto;
  padding: 52px 36px 32px;
  display: grid;
  grid-template-columns: 1.3fr 2.7fr;
  gap: 48px;
}

.vs-sf-brand {
  display: flex;
  flex-direction: column;
  gap: 16px;
  max-width: 320px;
}

/* Match the public nav wordmark (.vs-home-logo-text) exactly, just smaller logo:
   single flex gap between logo + wordmark, words kept tight inside one span. */
.vs-sf-mark {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  font-family: var(--vs-display);
  font-size: 20px;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--vs-text);
  text-decoration: none;
  width: fit-content;
}

.vs-sf-mark em {
  font-style: normal;
  color: var(--vs-blue);
}

.vs-sf-tagline {
  font-size: 13px;
  line-height: 1.65;
  color: var(--vs-muted);
  margin: 0;
}

/* Mini "shelf" of rendered spools sitting on a hairline ledge. */
.vs-sf-shelf {
  display: flex;
  align-items: flex-end;
  gap: 8px;
  padding-bottom: 7px;
  border-bottom: 1px solid var(--vs-hair);
  width: fit-content;
}

.vs-sf-social {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  width: fit-content;
  padding: 8px 15px;
  font-size: 13px;
  font-weight: 600;
  color: var(--vs-text-2);
  text-decoration: none;
  border: 1px solid var(--vs-hair-2);
  border-radius: 20px;
  transition: color 0.15s, border-color 0.15s, background 0.15s;
}

.vs-sf-social:hover {
  color: var(--vs-text);
  border-color: var(--vs-accent);
  background: rgba(var(--vs-tint), 0.08);
}

.vs-sf-cols {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 28px 24px;
}

.vs-sf-col {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.vs-sf-col-title {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--vs-faint);
  margin-bottom: 2px;
}

.vs-sf-col a {
  font-size: 13px;
  color: var(--vs-muted);
  text-decoration: none;
  transition: color 0.15s;
  width: fit-content;
}

.vs-sf-col a:hover {
  color: var(--vs-text);
}

/* Social icon links in a footer column (Discord/Instagram) — a small row of
   official glyphs instead of text names. */
.vs-sf-col-socials {
  display: flex;
  gap: 14px;
  margin-top: 4px;
}
.vs-sf-col-socials a {
  display: inline-flex;
  color: var(--vs-muted);
  transition: color 0.15s, transform 0.15s var(--vs-ease);
}
.vs-sf-col-socials a:hover {
  color: var(--vs-accent);
  transform: translateY(-1px);
}
.vs-sf-col-socials svg { display: block; }

.vs-sf-bottom {
  max-width: 1180px;
  margin: 0 auto;
  padding: 18px 36px 30px;
  border-top: 1px solid var(--vs-hair);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px 20px;
  flex-wrap: wrap;
  font-size: 12px;
  color: var(--vs-muted);
}

.vs-sf-built {
  color: var(--vs-faint);
}

.vs-sf-heart {
  display: inline-block;
  line-height: 0;
  /* Flat inline-SVG heart (replaced the glossy emoji), tinted with the theme accent
     so it shifts per theme (rose on Sakura, green on Matcha, blue on Onyx...).
     Override --vs-heart to pin a specific shade. */
  color: var(--vs-heart, var(--vs-accent));
}
.vs-sf-heart svg {
  width: 12px;
  height: 12px;
  fill: currentColor;
  display: inline-block;
  vertical-align: -2px;
}

.vs-sf-built:hover .vs-sf-heart,
.vs-footer-copy:hover .vs-sf-heart {
  animation: vs-footer-beat 0.9s ease-in-out infinite;
}

@keyframes vs-footer-beat {
  0%, 100% { transform: scale(1); }
  30% { transform: scale(1.28); }
}

@media (prefers-reduced-motion: reduce) {
  .vs-sf-built:hover .vs-sf-heart,
  .vs-footer-copy:hover .vs-sf-heart { animation: none; }
}

@media (max-width: 860px) {
  .vs-home-headline {
    font-size: 36px;
  }
  .vs-home-section-title {
    font-size: 26px;
  }
  .vs-home-cta-headline {
    font-size: 30px;
  }
  .vs-home-nav {
    padding: 14px 20px;
  }
  .vs-home-nav-links {
    gap: 12px;
  }
  .vs-home-hero {
    padding: 56px 20px 0;
  }
  .vs-home-section {
    padding: 60px 20px;
  }
  .vs-home-demo-units {
    flex-direction: column;
  }
  .vs-home-hero {
    grid-template-columns: 1fr;
  }
  .vs-home-hero-copy {
    text-align: center;
    margin: 0 auto 36px;
  }
  .vs-home-hero .vs-home-cta-row {
    justify-content: center;
  }
  .vs-home-stats {
    justify-content: center;
  }
  .vs-home-hero-glow {
    left: 50%;
    top: 0;
    width: 520px;
    height: 220px;
  }
  .vs-home-demo-wall {
    width: 100%;
  }
  .vs-home-workflow-inner {
    display: flex;
    flex-direction: column;
    gap: 32px;
    align-items: stretch;
  }
  .vs-sf-inner {
    grid-template-columns: 1fr;
    gap: 36px;
    padding: 40px 24px 28px;
  }
  .vs-sf-cols {
    grid-template-columns: repeat(2, 1fr);
  }
  .vs-sf-bottom {
    padding: 16px 24px 26px;
    justify-content: center;
    text-align: center;
  }
}

@media (max-width: 520px) {
  .vs-home-nav {
    padding: 12px 16px;
  }
  .vs-home-logo-text {
    font-size: 16px;
  }
  .vs-home-nav-links {
    gap: 10px;
    display: none;
  }
  .vs-home-mobile-menu {
    display: inline-flex;
  }
  .vs-home-mobile-menu-panel {
    right: 16px;
    left: 16px;
    min-width: auto;
    width: auto;
  }
  .vs-home-nav-btn {
    padding: 6px 14px;
    font-size: 12px;
  }
}

/* ── Studio page ─────────────────────────────────────────────────────────── */

/* Studio: compact entry — shelves are the primary experience, not the header */
.vs-studio-page {
  position: relative;
  /* No overflow-x:clip here: it would clip hover tooltips on edge spools. The
     app shell (.vs-app) already has overflow-x:clip at the viewport, which
     prevents any horizontal scrollbar from wide widgets while still letting
     tooltips that stay within the viewport show in full. */
  gap: 4px;          /* override .vs-page gap:28px */
  margin-top: -14px; /* pull page up; keeps title clear of 80px sticky topbar */
}
.vs-studio-page::before {
  content: "";
  position: absolute;
  top: 0;
  /* Stay inside the page bounds so overflow-x:clip never cuts the glow */
  left: 0;
  right: 0;
  height: 155px;
  background:
    radial-gradient(ellipse 60% 60% at 25% 0%, rgba(255,255,255,0.020) 0%, transparent 70%),
    radial-gradient(ellipse 40% 40% at 75% 0%, rgba(255,255,255,0.011) 0%, transparent 60%);
  pointer-events: none;
  z-index: 0;
}

.vs-studio-head {
  align-items: center;
  position: relative;
  z-index: 1;
}
.vs-studio-head .vs-studio-subtitle {
  font-size: 11px;
  text-align: right;
  opacity: 0.60;
}

/* Studio collection search */
.vs-studio-search {
  display: flex;
  align-items: center;
  justify-self: end;
}
.vs-studio-search-input {
  background-color: var(--vs-surface);
  border: 1px solid var(--vs-hair-2);
  border-radius: 8px;
  padding: 5px 14px 5px 32px;
  color: var(--vs-text);
  font-family: var(--vs-sans);
  font-size: 12px;
  width: 210px;
  outline: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='13' height='13' viewBox='0 0 24 24' fill='none' stroke='%236a7a90' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='8'/%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: 11px center;
  transition: border-color 0.18s, background-color 0.18s;
}
.vs-studio-search-input::placeholder {
  color: var(--vs-faint);
  opacity: 0.55;
}
.vs-studio-search-input:focus {
  border-color: var(--vs-accent);
  background-color: var(--vs-surface-2);
}
.vs-studio-search-input::-webkit-search-cancel-button {
  opacity: 0.4;
  cursor: pointer;
}

/* Compact eyebrow in studio — small atmospheric label, not a heading */
.vs-studio-head .vs-eyebrow {
  font-size: 10.5px;
  opacity: 0.75;
}

/* Studio title — kept as a no-op alias now that .vs-page-title is unified
   to 23px. Leave the selector so the markup doesn't need to change. */
.vs-studio-head .vs-page-title {
  /* Matches the base .vs-page-title styling. */
}

.vs-studio-subtitle {
  font-size: 13px;
  color: var(--vs-muted);
  margin-top: 0;
  letter-spacing: 0.02em;
}
.vs-studio-hint {
  font-size: 11px;
  font-style: italic;
  color: var(--vs-faint);
  opacity: 0.7;
}

/* Ambient chips — small soft workflow indicators, not KPI cards */
.vs-studio-ambient {
  display: flex;
  flex-wrap: wrap;
  gap: 7px;
  align-items: center;
  padding: 6px 0 0;
  width: 100%;
  position: relative;
  z-index: 1;
}

.vs-ambient-chip {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 5px 11px;
  border-radius: 20px;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.025em;
  background: var(--vs-surface-2);
  border: 1px solid rgba(255, 255, 255, 0.05);
  color: var(--vs-muted);
}

.vs-ambient-dot {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: currentColor;
  flex-shrink: 0;
  opacity: 0.85;
}

.vs-ambient-chip--inuse {
  color: var(--vs-secondary);
}
.vs-ambient-chip--drying {
  color: var(--vs-warning);
}
.vs-ambient-chip--tostore {
  color: var(--vs-accent);
}
.vs-ambient-chip--swatch {
  color: var(--vs-text-2);
}

/* Dot variants for sidebar use */
.vs-ambient-dot--drying {
  background: var(--vs-warning);
}
.vs-ambient-dot--tostore {
  background: var(--vs-accent);
}
.vs-ambient-dot--swatch {
  background: var(--vs-text-2);
}
.vs-ambient-dot--unassigned {
  background: var(--vs-muted);
}
.vs-ambient-dot--printing {
  background: var(--vs-secondary);
}
.vs-ambient-dot--attention {
  background: var(--vs-danger);
}
.vs-ambient-dot--recent {
  background: var(--vs-blue);
}

/* Studio widget customize control */
.vs-widget-customize {
  margin-bottom: 10px;
}
.vs-widget-customize-btn {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  background: var(--vs-surface-2, #171b27);
  border: 1px solid var(--vs-border, #2a3142);
  color: var(--vs-text-2);
  font-size: 12px;
  padding: 5px 10px;
  border-radius: 7px;
  cursor: pointer;
}
.vs-widget-customize-btn:hover {
  color: var(--vs-text);
  border-color: var(--vs-accent);
}
/* Active = panel open / edit mode on: filled accent tint so it clearly reads "on",
   distinct from the plain hover state. */
.vs-widget-customize-btn.is-active {
  color: var(--vs-accent);
  border-color: var(--vs-accent);
  background: color-mix(in srgb, var(--vs-accent) 18%, var(--vs-surface-2, #171b27));
}
.vs-widget-menu { position: relative; }
/* Float the customize list as a dropdown so it overlays content instead of
   pushing the whole page down when opened. Anchored under the Widgets button. */
.vs-widget-customize-panel {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  z-index: 30;
  /* Two columns + scroll so the list scales as more widgets are added (group
     labels and the reset button span the full width). */
  width: max-content;
  min-width: 300px;
  max-width: min(440px, 92vw);
  max-height: min(70vh, 460px);
  overflow-y: auto;
  padding: 8px 12px 10px;
  background: var(--vs-surface-2, #171b27);
  border: 1px solid var(--vs-border, #2a3142);
  border-radius: 8px;
  box-shadow: 0 14px 34px rgba(0, 0, 0, 0.4);
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 2px 16px;
  align-content: start;
}
.vs-widget-customize-panel .vs-widget-group-label,
.vs-widget-customize-panel .vs-widget-selectall,
.vs-widget-customize-panel .vs-widget-reset {
  grid-column: 1 / -1;
}
.vs-widget-selectall {
  display: flex;
  gap: 8px;
  margin-bottom: 4px;
}
.vs-widget-selectall button {
  flex: 1;
  background: none;
  border: 1px solid var(--vs-hair-2);
  border-radius: 6px;
  padding: 5px 8px;
  font-family: inherit;
  font-size: 12px;
  font-weight: 600;
  color: var(--vs-text-2);
  cursor: pointer;
  transition: border-color 0.15s, color 0.15s;
}
.vs-widget-selectall button:hover { border-color: var(--vs-accent); color: var(--vs-text); }
/* Always-on widgets: shown as ticked but not changeable. */
.vs-widget-row--locked { cursor: default; opacity: 0.75; }
.vs-widget-row--locked input { cursor: default; }
.vs-widget-customize-row {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12.5px;
  color: var(--vs-text-2);
  cursor: pointer;
}
.vs-widget-customize-row input {
  accent-color: var(--vs-accent);
  cursor: pointer;
}
.vs-widget-reset {
  margin-top: 6px;
  width: 100%;
  background: none;
  border: 1px solid var(--vs-border, #2a3142);
  color: var(--vs-text-2);
  font-size: 12px;
  border-radius: 6px;
  padding: 6px 8px;
  cursor: pointer;
  transition: border-color 0.15s, color 0.15s;
}
.vs-widget-reset:hover {
  border-color: var(--vs-accent);
  color: var(--vs-text);
}

/* ── Studio hero card: the focal point at the top of the Studio ── */
.vs-hero {
  position: relative;
  display: flex;
  align-items: center;
  gap: 22px;
  padding: 18px 24px;
  margin-bottom: 14px;
  border-radius: 14px;
  background: linear-gradient(120deg, rgba(var(--vs-tint), 0.14), rgba(var(--vs-tint), 0.04));
  border: 1px solid rgba(var(--vs-tint), 0.26);
  box-shadow: 0 6px 22px rgba(0, 0, 0, 0.18);
  text-decoration: none;
  color: inherit;
}
.vs-hero-lead { flex: 1 1 auto; min-width: 0; }
.vs-hero-eyebrow {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--vs-accent);
}
.vs-hero-title {
  font-size: clamp(1.25rem, 2.4vw, 1.7rem);
  font-weight: 800;
  letter-spacing: -0.01em;
  color: var(--vs-text);
  margin-top: 2px;
}
.vs-hero-sub {
  font-size: 13px;
  color: var(--vs-text-2);
  margin-top: 3px;
}

/* Welcome (first-visit) summary stats */
.vs-hero-summary {
  display: flex;
  gap: 26px;
  align-items: flex-start;
  flex-wrap: wrap;
}
.vs-hero-stat { min-width: 64px; }
.vs-hero-stat-num {
  font-size: 28px;
  font-weight: 800;
  line-height: 1;
  color: var(--vs-text);
}
.vs-hero-stat-unit {
  font-size: 12px;
  color: var(--vs-text-2);
  margin-top: 3px;
}
.vs-hero-stat-meta {
  font-size: 11.5px;
  color: var(--vs-faint);
  margin-top: 3px;
}
.vs-hero-stat--last { align-self: center; }
.vs-hero-stat-name {
  font-size: 14px;
  font-weight: 700;
  color: var(--vs-text);
  margin-top: 2px;
}

/* Dynamic hero (later visits) */
.vs-hero--dynamic { cursor: pointer; transition: border-color 0.15s, box-shadow 0.15s; }
.vs-hero--dynamic:hover {
  border-color: rgba(var(--vs-tint), 0.45);
  box-shadow: 0 8px 26px rgba(0, 0, 0, 0.24);
}
.vs-hero-dot {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  flex-shrink: 0;
}
.vs-hero-cta {
  font-size: 13px;
  font-weight: 600;
  color: var(--vs-accent);
  white-space: nowrap;
  flex-shrink: 0;
}

@media (max-width: 760px) {
  .vs-hero { flex-direction: column; align-items: flex-start; gap: 14px; }
  .vs-hero-summary { gap: 18px; }
}

/* ── "Studio by the numbers": a live readout of the collection ── */
.vs-stats { margin-bottom: 14px; }
.vs-stats-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(104px, 1fr));
  gap: 10px;
}
.vs-stat-tile {
  display: flex;
  flex-direction: column;
  gap: 5px;
  padding: 13px 16px;
  border-radius: 12px;
  background: linear-gradient(150deg, rgba(var(--vs-tint), 0.10), rgba(var(--vs-tint), 0.03));
  border: 1px solid rgba(var(--vs-tint), 0.18);
  text-decoration: none;
  color: inherit;
  transition: border-color 0.15s, transform 0.15s, box-shadow 0.15s;
}
.vs-stat-tile:hover {
  border-color: rgba(var(--vs-tint), 0.42);
  transform: translateY(-2px);
  box-shadow: 0 8px 22px rgba(0, 0, 0, 0.20);
}
.vs-stat-num {
  display: flex;
  align-items: baseline;
  gap: 2px;
  font-size: clamp(1.5rem, 2.2vw, 1.95rem);
  font-weight: 800;
  line-height: 1;
  letter-spacing: -0.02em;
  color: var(--vs-text);
  font-variant-numeric: tabular-nums;
}
.vs-stat-unit {
  font-size: 0.5em;
  font-weight: 700;
  letter-spacing: 0;
  color: var(--vs-accent);
}
.vs-stat-label {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--vs-faint);
}
/* Rotating maker-native scale comparison ("≈ N Benchys") */
.vs-stats-fun {
  position: relative;
  height: 1.5em;
  margin-top: 10px;
  padding-left: 2px;
  font-size: 12.5px;
  color: var(--vs-text-2);
}
.vs-stats-fun--rotate .vs-stats-fun-line {
  position: absolute;
  left: 2px;
  top: 0;
  white-space: nowrap;
  opacity: 0;
  animation: vs-fun-cycle 15s infinite both;
  animation-delay: calc(var(--i) * 5s);
}
@keyframes vs-fun-cycle {
  0%        { opacity: 0; transform: translateY(5px); }
  3%, 28%   { opacity: 1; transform: translateY(0); }
  33%, 100% { opacity: 0; transform: translateY(-5px); }
}
@media (prefers-reduced-motion: reduce) {
  .vs-stats-fun--rotate .vs-stats-fun-line { animation: none; opacity: 0; }
  .vs-stats-fun--rotate .vs-stats-fun-line:first-child { opacity: 1; position: relative; }
}

/* ── Maker dashboard: journey, favorites, milestone badges ── */
.vs-maker {
  margin-bottom: 14px;
  padding: 16px 18px;
  border-radius: 14px;
  background: linear-gradient(135deg, rgba(var(--vs-tint), 0.08), rgba(var(--vs-tint), 0.02));
  border: 1px solid rgba(var(--vs-tint), 0.18);
}
.vs-maker-head { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; }
.vs-maker-eyebrow {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--vs-accent);
}
.vs-maker-years {
  font-size: 11px;
  font-weight: 600;
  color: var(--vs-text-2);
  padding: 2px 8px;
  border-radius: 999px;
  background: rgba(var(--vs-tint), 0.14);
}
.vs-maker-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: 12px;
  margin-bottom: 12px;
}
.vs-maker-stat { display: flex; flex-direction: column; gap: 3px; }
.vs-maker-num {
  font-size: 1.5rem;
  font-weight: 800;
  line-height: 1;
  color: var(--vs-text);
  font-variant-numeric: tabular-nums;
}
.vs-maker-lbl { font-size: 11px; color: var(--vs-faint); }
.vs-maker-faves {
  display: flex;
  flex-wrap: wrap;
  gap: 18px;
  padding-top: 12px;
  border-top: 1px solid rgba(var(--vs-tint), 0.14);
}
.vs-maker-fave { display: flex; flex-direction: column; gap: 2px; }
.vs-maker-fave-k {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--vs-faint);
}
.vs-maker-fave-v {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  font-weight: 600;
  color: var(--vs-text);
}
.vs-maker-swatch {
  width: 13px;
  height: 13px;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, 0.18);
  flex-shrink: 0;
}
.vs-maker-badges { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 13px; }
.vs-maker-badge {
  font-size: 12px;
  font-weight: 600;
  color: var(--vs-text);
  padding: 4px 10px;
  border-radius: 999px;
  background: rgba(var(--vs-tint), 0.12);
  border: 1px solid rgba(var(--vs-tint), 0.22);
  white-space: nowrap;
}

/* Widgets customize-panel group headers */
.vs-widget-group-label {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--vs-faint);
  padding: 7px 2px 1px;
}
.vs-widget-customize-panel > .vs-widget-group-label:first-child { padding-top: 2px; }

/* ── Material mix pie widget ── */
.vs-pie-wrap {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  align-items: center;
  padding: 8px 4px 4px;
}
.vs-pie { width: clamp(124px, 30%, 196px); height: auto; aspect-ratio: 1 / 1; flex-shrink: 0; }
.vs-pie circle { transition: stroke-dasharray 0.4s var(--vs-ease, ease); }
/* Legend flows into as many columns as fit, so values sit close to their names
   instead of being stretched to the far edge of a wide widget. */
.vs-pie-legend {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(148px, 1fr));
  gap: 5px 18px;
  flex: 1 1 200px;
  min-width: 140px;
  align-content: center;
}
.vs-pie-leg { display: flex; align-items: center; gap: 8px; font-size: 12px; }
.vs-pie-dot { width: 10px; height: 10px; border-radius: 2px; flex-shrink: 0; }
.vs-pie-leg-name { color: var(--vs-text); flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.vs-pie-leg-val { color: var(--vs-faint); white-space: nowrap; }

/* Collection growth (area chart) */
.vs-growth { padding: 6px 2px 2px; }
.vs-growth-plot { position: relative; }
.vs-growth-svg { width: 100%; height: 110px; display: block; }
.vs-growth-y {
  position: absolute;
  left: 5px;
  font-size: 10.5px;
  color: var(--vs-faint);
  pointer-events: none;
}
.vs-growth-y--top { top: 2px; }
.vs-growth-y--bot { bottom: 4px; }
.vs-growth-axis { position: relative; height: 15px; margin-top: 5px; }
.vs-growth-tick { position: absolute; font-size: 11px; color: var(--vs-faint); white-space: nowrap; }

/* Donut depth (frosting). NB: .vs-donut is taken by the Donut Day graphic. */
.vs-pie-donut { filter: drop-shadow(0 3px 5px rgba(0, 0, 0, 0.28)); }

/* Color wheel (hue + saturation dot scatter) */
.vs-wheel { display: flex; flex-direction: column; align-items: center; gap: 4px; padding: 10px 4px 6px; }
.vs-wheel .vs-pie { width: clamp(140px, 52%, 190px); height: auto; aspect-ratio: 1 / 1; }
.vs-wheel-hint { font-size: 11px; color: var(--vs-faint); }
.vs-wheel--clickable { cursor: pointer; transition: transform 0.15s var(--vs-ease, ease); }
.vs-wheel--clickable:hover { transform: scale(1.02); }
.vs-wheel--clickable:hover .vs-wheel-hint { color: var(--vs-accent); }

/* Color-wheel enlarge overlay */
.vs-wheel-modal {
  position: fixed;
  inset: 0;
  z-index: 9998;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.7);
  backdrop-filter: blur(4px);
  padding: 4vmin;
}
.vs-wheel-modal-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  background: var(--vs-surface, #1b1b27);
  border: 1px solid var(--vs-hair-2, #33333f);
  border-radius: 18px;
  padding: 14px 20px 18px;
  box-shadow: 0 30px 80px rgba(0, 0, 0, 0.6);
  max-width: 94vw;
}
.vs-wheel-modal-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  width: 100%;
  margin-bottom: 6px;
}
.vs-wheel-modal-title { font-size: 15px; font-weight: 700; color: var(--vs-text); }
.vs-wheel-modal-stage { display: flex; justify-content: center; }
.vs-wheel-modal-stage .vs-pie { width: min(78vmin, 660px); height: auto; aspect-ratio: 1 / 1; }
.vs-wheel-modal-sub { margin-top: 10px; font-size: 12px; color: var(--vs-faint); }

/* ── "Your palette": a rainbow band of every spool's color ── */
/* Collapsible "Overview" group: palette signature + profile + stats. */
.vs-studio-top { margin-bottom: 6px; }

/* Studio top two-column row (under the Palette Signature): wider left column for
   Studio Stats + Maker Stats, narrower right column for Recent Activity. */
.vs-studio-cols {
  display: grid;
  grid-template-columns: minmax(0, 1.7fr) minmax(0, 1fr);
  gap: 14px;
  align-items: start;
  margin-top: 10px;
}
.vs-studio-col-main {
  display: flex;
  flex-direction: column;
  gap: 12px;
  min-width: 0;
}
.vs-studio-col-side { min-width: 0; }
.vs-studio-col-main .vs-stats,
.vs-studio-col-main .vs-maker { margin-bottom: 0; }
/* Recent Activity fills its column (it's a normal widget card otherwise). */
.vs-studio-col-side .vs-block { width: 100%; max-width: none; }
@media (max-width: 860px) {
  .vs-studio-cols { grid-template-columns: 1fr; }
}
.vs-studio-top-toggle {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: none;
  border: none;
  cursor: pointer;
  font-family: inherit;
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--vs-faint);
  padding: 2px 0 8px;
}
.vs-studio-top-toggle:hover { color: var(--vs-muted); }
/* Larger, more visible Overview collapse chevron. */
.vs-studio-top-toggle .vs-widget-collapse {
  font-size: 18px;
  line-height: 1;
  color: var(--vs-accent);
  width: auto;
}
.vs-palette { margin-bottom: 14px; }
.vs-palette-band {
  display: flex;
  height: 46px;
  border-radius: 10px;
  overflow: hidden;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.05), 0 4px 16px rgba(0, 0, 0, 0.18);
}
.vs-palette-chip {
  flex: 1 1 0;
  min-width: 2px;
  /* Run your eye along the swatches: the hovered color fans open. */
  transition: flex-grow 0.22s var(--vs-ease);
}
.vs-palette-chip:hover { flex-grow: 7; }
.vs-palette-meta {
  display: flex;
  justify-content: space-between;
  margin-top: 6px;
  font-size: 11px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--vs-faint);
}
/* The palette doubles as a maker's identity "thumbprint" — a faint signature line. */
.vs-palette-id {
  margin-top: 5px;
  font-size: 11px;
  font-style: italic;
  letter-spacing: 0.02em;
  color: var(--vs-faint);
}

/* ── Next best action bar ── */
.vs-nextaction {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 16px;
  margin-bottom: 14px;
  border-radius: 10px;
  background: rgba(var(--vs-tint), 0.08);
  border: 1px solid rgba(var(--vs-tint), 0.20);
  color: var(--vs-text-2);
  text-decoration: none;
  font-size: 13px;
  transition: border-color 0.15s, background 0.15s;
}
.vs-nextaction:hover {
  border-color: rgba(var(--vs-tint), 0.40);
  background: rgba(var(--vs-tint), 0.12);
}
.vs-nextaction-icon { display: inline-flex; color: var(--vs-accent); flex-shrink: 0; }
.vs-nextaction-text { flex: 1 1 auto; color: var(--vs-text); }
.vs-nextaction-cta { color: var(--vs-accent); font-weight: 600; white-space: nowrap; flex-shrink: 0; }

/* Action trigger on a widget spool row */
.vs-queue-row-trigger {
  margin-left: auto;
  background: none;
  border: none;
  color: var(--vs-muted);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  opacity: 0.55;
  padding: 2px;
}
.vs-queue-row:hover .vs-queue-row-trigger {
  opacity: 1;
}

/* Studio toolbar + arrangeable widget grid */
.vs-studio-toolbar {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  align-items: flex-start;
  margin-bottom: 12px;
  position: relative;
}
.vs-widget-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: flex-start;
  margin: 0 0 14px;
}
.vs-block {
  flex: 0 1 100%;
  min-width: 0;
  box-sizing: border-box;
}
.vs-block--s { flex-basis: calc(33.333% - 8px); }
.vs-block--m { flex-basis: calc(50% - 6px); }
.vs-block--l { flex-basis: 100%; }
@media (max-width: 1000px) {
  .vs-block--s, .vs-block--m { flex-basis: 100%; }
}
.vs-widget-grid.is-editing .vs-block {
  outline: 1px dashed var(--vs-border, #2a3142);
  outline-offset: 3px;
  border-radius: 10px;
  cursor: grab;
}
.vs-block-edit {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 2px 2px 6px;
}
.vs-block-drag {
  font-size: 11.5px;
  color: var(--vs-muted, #8a8aa0);
  display: flex;
  gap: 5px;
  align-items: center;
  font-weight: 600;
}
.vs-block-sizes { display: flex; gap: 3px; }
.vs-block-size {
  background: var(--vs-surface-2, #171b27);
  border: 1px solid var(--vs-border, #2a3142);
  color: var(--vs-text-2);
  font-size: 10px;
  font-weight: 700;
  width: 21px;
  height: 19px;
  border-radius: 4px;
  cursor: pointer;
}
.vs-block-size.is-active {
  background: var(--vs-accent);
  color: #fff;
  border-color: var(--vs-accent);
}
.vs-widget-grid-empty {
  flex: 1 1 100%;
  text-align: center;
  color: var(--vs-muted, #8a8aa0);
  font-size: 12px;
  padding: 16px;
  border: 1px dashed var(--vs-border, #2a3142);
  border-radius: 10px;
}

/* Spools laid out as a horizontal wrapping strip inside a widget (names on hover). */
.vs-widget-spools {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  padding-top: 8px;
}
.vs-widget-spool {
  cursor: pointer;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  transition: transform 0.1s ease;
}
.vs-widget-spool:hover {
  transform: translateY(-2px);
}

/* Live drying timer (text filled by VS.dryTimers). */
.vs-dry-timer {
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  font-weight: 600;
}
.vs-widget-spool .vs-dry-timer {
  font-size: 9px;
  line-height: 1;
  color: var(--vs-dry-active);             /* drying blue */
}
.vs-widget-spool .vs-dry-timer.is-overdue {
  color: var(--vs-dry-overdue);             /* past 24h: amber nudge */
}

/* Drying readout on the spool detail status panel. */
.vs-detail-dry {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 12px;
  font-size: 13px;
  color: var(--vs-dry-active);
}
.vs-detail-dry.is-overdue {
  color: var(--vs-dry-overdue);
}
.vs-dry-nudge {
  margin-left: 6px;
  font-size: 11px;
  font-weight: 600;
  color: var(--vs-dry-overdue);
}

/* Live drying timer on an Activities dryer card (Activities.razor). */
.vs-gear-badge { margin: 6px 0 2px; }
.vs-gear-timer {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 12px;
  font-weight: 600;
  color: var(--vs-dry-active);                /* drying blue */
}
.vs-gear-timer.is-overdue { color: var(--vs-dry-overdue); }   /* past 24h: amber */
.vs-gear-timer.is-idle {
  color: var(--vs-faint);
  font-weight: 500;
  font-style: italic;
}
.vs-widget-title {
  cursor: pointer;
  user-select: none;
}
/* Non-collapsible chart header (e.g. the click-to-enlarge Color wheel): no
   collapse affordance, so it shouldn't look clickable. */
.vs-widget-title--static { cursor: default; }
/* Push the spool count to the right so it sits in the top-right, just before
   the collapse arrow. */
.vs-widget-title .vs-queue-count {
  margin-left: auto;
}
.vs-widget-collapse {
  margin-left: 2px;
  flex-shrink: 0;
  font-size: 18px;
  line-height: 1;
  color: var(--vs-text-2, #b5b9c6);
  width: 24px;
  height: 24px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 6px;
  border: 1px solid transparent;
}
.vs-widget-title:hover .vs-widget-collapse {
  color: var(--vs-text, #e6e9f0);
  background: rgba(255, 255, 255, 0.07);
  border-color: rgba(255, 255, 255, 0.10);
}
.vs-studio-main--full { width: 100%; }
.vs-studio-toolbar-search { width: 240px; max-width: 46vw; }

/* Pegboard panel look for each widget card (matches the storage walls). */
.vs-widget-card {
  background-color: rgba(12, 16, 26, 0.84);
  background-image:
    linear-gradient(180deg, rgba(255,255,255,0.018) 0%, transparent 40%, rgba(0,0,0,0.10) 100%),
    radial-gradient(circle, rgba(200,215,240,0.030) 1.0px, rgba(200,215,240,0.014) 1.7px, transparent 1.7px);
  background-size: auto, 20px 20px;
  /* Inset shadow alone defines the panel edge; no border at all */
  border: none;
  border-radius: 10px;
  padding: 10px 12px;
  box-shadow: inset 0 0 30px rgba(0,0,0,0.20);
}
.vs-storage-head {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 6px 0 10px;
  color: var(--vs-text-2);
}
.vs-storage-head-title {
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-size: 11px;
  font-weight: 700;
}

/* Collapsed Storage Locations: a compact room -> unit table of contents. */
.vs-storage-toc {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 4px 2px 12px;
}
.vs-storage-toc-row {
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--vs-text-2);
}
.vs-storage-toc-row--sub {
  padding-left: 18px;
  color: var(--vs-faint);
}
.vs-storage-toc-room {
  font-weight: 600;
  color: var(--vs-text);
}
.vs-storage-toc-sep {
  color: var(--vs-faint);
}
.vs-widget-empty {
  color: var(--vs-muted, #8a8aa0);
  font-size: 12px;
  padding: 10px 2px 4px;
}

/* Loading skeleton — shown while a section's heavier data streams in after the
   page shell has already painted (e.g. Spool Detail history/prints). Theme-safe
   pulse (no gradient) so it reads on every theme. */
.vs-skel {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.vs-skel-row {
  height: 30px;
  border-radius: 8px;
  background: var(--vs-hair);
  animation: vs-skel-pulse 1.2s ease-in-out infinite;
}
@keyframes vs-skel-pulse {
  0%, 100% { opacity: .45; }
  50% { opacity: .9; }
}

/* Donut Day: the Blender-style 3/4 sprinkled donut, gently floating. */
.vs-donut-scene {
  display: inline-block;
}
.vs-donut {
  width: 100%;
  height: 100%;
  animation: vs-donut-float 3.4s ease-in-out infinite;
  transform-origin: center 80%;
}
.vs-donut svg {
  width: 100%;
  height: 100%;
  display: block;
}
@keyframes vs-donut-float {
  0%, 100% { transform: translateY(0) rotate(-1.2deg); }
  50%      { transform: translateY(-7px) rotate(1.2deg); }
}
.vs-donut--static .vs-donut {
  animation: none;
}
@media (prefers-reduced-motion: reduce) {
  .vs-donut { animation: none !important; }
}

.vs-donut-day {
  position: relative;
  display: flex;
  align-items: center;
  gap: 18px;
  padding: 12px 22px 14px;
  margin-bottom: 18px;
  border-radius: 16px;
  background: linear-gradient(120deg, rgba(255,141,187,0.16), rgba(127,184,255,0.10));
  border: 1px solid rgba(255,141,187,0.32);
  box-shadow: 0 6px 24px rgba(255,141,187,0.12);
}
.vs-donut-day-title {
  font-size: 19px;
  font-weight: 800;
  color: #ffd0e2;
}
/* The pale-pink title is tuned for dark themes; on light/medium themes it
   washes out against the light banner, so deepen it to a high-contrast pink. */
html[data-mode="light"] .vs-donut-day-title { color: #c2185b; }
.vs-donut-day-sub {
  font-size: 13px;
  color: var(--vs-text-2);
  margin-top: 3px;
}
.vs-donut-day-x {
  position: absolute;
  top: 8px;
  right: 12px;
  background: none;
  border: none;
  color: var(--vs-muted, #8a8aa0);
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
}
.vs-donut-day-x:hover { color: var(--vs-text, #e6e9f0); }

/* ===== Day-one Studio intro ritual: ceremonial printer warm-up =====
   A fixed, full-viewport overlay. Their spool turns slowly in the background
   while a printer homes, heats (to their material's real temps), oozes their
   filament color, and lays a glowing first layer. A warm-up checklist narrates
   each step (tied to their actual data), then "Layer one looks perfect." lands
   and the overlay dissolves into the live studio. 100% CSS-timed, skippable,
   shown once. ~4.1s build + 0.7s dissolve. */
.vs-ritual {
  position: fixed;
  inset: 0;
  z-index: 1500;                /* above the nav; above collector(1400) too */
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;              /* click anywhere to skip */
  /* Master clock: hold, then dissolve to reveal the live studio. A C# timer
     (~9.8s) unmounts the node once this has visually finished. */
  animation: vs-ritual-dissolve 0.8s var(--vs-ease) 9.0s forwards;
}

/* Dark radial veil over the studio area. */
.vs-ritual-veil {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(120% 90% at 50% 42%,
      rgba(24, 29, 41, 0.92) 0%,
      var(--vs-bg) 55%,
      var(--vs-bg-deep) 100%);
  opacity: 0;
  animation: vs-ritual-veil-in 0.35s ease-out both;
}

.vs-ritual-stage {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(14px, 3vh, 26px);
}

/* Hero: background spool + printer scene + halo, stacked in one grid cell. */
.vs-ritual-hero {
  position: relative;
  display: grid;
  place-items: center;
}
.vs-ritual-hero > * { grid-area: 1 / 1; }

.vs-ritual-halo {
  width: 460px;
  height: 460px;
  max-width: 86vw;
  border-radius: 50%;
  background: radial-gradient(circle,
    rgba(127, 184, 255, 0.38) 0%, rgba(var(--vs-tint), 0.15) 42%, transparent 70%);
  opacity: 0;
  pointer-events: none;
  z-index: 0;
  animation: vs-ritual-halo-in 1.6s var(--vs-ease) 3.6s forwards;
}

/* Their spool: mounted top-right behind the printer (where a real spool holder
   sits), dim + softly blurred, turning slowly. */
.vs-ritual-spool {
  position: absolute;
  top: -4px;
  right: 14px;
  z-index: 0;
  opacity: 0;
  filter: blur(0.4px);
  animation: vs-ritual-spool-in 1.3s var(--vs-ease) 0.1s forwards;
}
.vs-ritual-spin {
  transform-origin: 50% 50%;
  animation: vs-ritual-idle 18s linear infinite;
}

/* Printer scene (foreground). */
.vs-printer {
  z-index: 1;
  width: clamp(330px, 74vw, 440px);
  height: auto;
  overflow: visible;
}
.vs-pr-frame rect {
  fill: #414e6a;
  opacity: 0;
  animation: vs-pr-fade 0.5s ease 0.2s forwards;
}
.vs-pr-bed {
  opacity: 0;
  transform: translateY(16px);
  animation: vs-pr-bed-in 0.7s var(--vs-ease) 0.5s forwards;
}
.vs-pr-bed-heat  { opacity: 0; animation: vs-pr-heat 1.9s ease 1.6s forwards; }
.vs-pr-noz-heat  { opacity: 0; animation: vs-pr-heat 2.1s ease 2.5s forwards; }

.vs-pr-zlift {
  transform: translateY(-150px);
  animation: vs-pr-descend 1.0s var(--vs-ease) 3.0s forwards;
}
.vs-pr-carriage {
  transform: translateX(-50px);
  animation: vs-pr-traverse 1.5s ease-in-out 4.8s forwards;
}
.vs-pr-ooze {
  transform-box: fill-box;
  transform-origin: 50% 0%;
  transform: scaleY(0);
  animation: vs-pr-ooze 0.55s var(--vs-ease) 3.6s forwards;
}
/* Purge poop: a pile of their color, extruded up from the bed before printing. */
.vs-pr-poop {
  transform-box: fill-box;
  transform-origin: 50% 100%;
  transform: scaleY(0);
  animation: vs-pr-poop 2.2s var(--vs-ease) 3.8s forwards;
}
.vs-pr-line {
  stroke-dasharray: 124;
  stroke-dashoffset: 124;
  animation: vs-pr-draw 1.5s ease-in-out 4.8s forwards;
}

/* Printer status screen (mounted on the base): shows one status at a time. */
.vs-pr-screen {
  opacity: 0;
  animation: vs-pr-fade 0.5s ease 0.4s forwards;
}
.vs-scr {
  font-family: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
  font-size: 10px;
  fill: #bfe3cf;
  letter-spacing: 0.2px;
  opacity: 0;
}
.vs-scr-cycle { animation: vs-scr-cycle 1.0s ease var(--d) forwards; }
.vs-scr-last  { animation: vs-scr-in 0.5s ease var(--d) forwards; }
/* The loaded filament name on the screen's second line — appears and holds. */
.vs-scr-name {
  font-family: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
  font-size: 9px;
  fill: #8fb0d8;
  letter-spacing: 0.2px;
  opacity: 0;
  animation: vs-scr-in 0.5s ease var(--d) forwards;
}
@keyframes vs-scr-cycle { 0% { opacity: 0; } 16% { opacity: 1; } 80% { opacity: 1; } 100% { opacity: 0; } }
@keyframes vs-scr-in    { to { opacity: 1; } }

@keyframes vs-pr-fade   { to { opacity: 1; } }
@keyframes vs-pr-bed-in { to { opacity: 1; transform: translateY(0); } }
@keyframes vs-pr-heat   { 0% { opacity: 0; } 60% { opacity: 0.55; } 100% { opacity: 0.32; } }
@keyframes vs-pr-descend  { to { transform: translateY(4px); } }
@keyframes vs-pr-traverse { to { transform: translateX(70px); } }
@keyframes vs-pr-ooze     { to { transform: scaleY(1); } }
/* Purge poop: extrude up, hold a beat, then get flicked off the plate. */
@keyframes vs-pr-poop {
  0%   { transform: scaleY(0) translate(0, 0)        rotate(0deg);   opacity: 1; }
  20%  { transform: scaleY(1) translate(0, 0)        rotate(0deg);   opacity: 1; }   /* extruded */
  58%  { transform: scaleY(1) translate(0, 0)        rotate(0deg);   opacity: 1; }   /* proud sit */
  82%  { transform: scaleY(1) translate(-34px, 12px) rotate(-52deg);  opacity: 1; }   /* tips off the plate */
  100% { transform: scaleY(1) translate(-64px, 41px) rotate(-118deg); opacity: 1; }   /* flops over at an odd angle, stays */
}
@keyframes vs-pr-draw     { to { stroke-dashoffset: 0; } }

@keyframes vs-ritual-spool-in {
  from { opacity: 0;    transform: scale(0.92); }
  to   { opacity: 0.6; transform: scale(1); }
}
@keyframes vs-ritual-idle { from { transform: rotate(0); } to { transform: rotate(360deg); } }
@keyframes vs-ritual-halo-in {
  0%   { opacity: 0;   transform: scale(0.7); }
  50%  { opacity: 1;   transform: scale(1.05); }
  100% { opacity: 0.5; transform: scale(1); }
}

/* Caption: warm-up checklist and payoff line stacked so the crossfade between
   them never shifts layout. */
.vs-ritual-caption {
  position: relative;
  width: min(360px, 86vw);
}

/* Warm-up checklist styled as the printer's status display (a backlit LCD). */
.vs-warm-log {
  display: flex;
  flex-direction: column;
  gap: 9px;
  padding: 13px 16px;
  border-radius: 8px;
  background: linear-gradient(180deg, rgba(12, 16, 24, 0.94), rgba(8, 11, 18, 0.94));
  border: 1px solid rgba(var(--vs-tint), 0.35);
  box-shadow: inset 0 0 16px rgba(60, 90, 140, 0.16), 0 3px 12px rgba(0, 0, 0, 0.45);
  animation: vs-warm-log-out 0.4s var(--vs-ease) 6.5s forwards;
}
.vs-warm-row {
  display: flex;
  align-items: center;
  gap: 10px;
  opacity: 0;
  transform: translateY(4px);
  animation: vs-warm-row-in 0.35s var(--vs-ease) var(--d) both;
}
.vs-warm-label {
  font-size: 0.88rem;
  color: var(--vs-text-2);
  letter-spacing: 0.01em;
}
.vs-warm-label b { color: var(--vs-text); font-weight: 600; }
.vs-warm-ind {
  position: relative;
  width: 16px;
  height: 16px;
  flex-shrink: 0;
}
.vs-warm-ring {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 1.6px solid rgba(var(--vs-tint), 0.30);
  border-top-color: var(--vs-accent);
  animation:
    vs-warm-spin 0.6s linear var(--d) infinite,
    vs-warm-ring-out 0.2s linear calc(var(--d) + 0.7s) forwards;
}
.vs-warm-check {
  position: absolute;
  left: 5px;
  top: 1px;
  width: 4px;
  height: 8px;
  border: solid var(--vs-accent);
  border-width: 0 1.8px 1.8px 0;
  transform: rotate(45deg) scale(0.4);
  opacity: 0;
  animation: vs-warm-check-in 0.3s var(--vs-ease) calc(var(--d) + 0.7s) forwards;
}

@keyframes vs-warm-row-in   { to { opacity: 1; transform: translateY(0); } }
@keyframes vs-warm-spin     { to { transform: rotate(360deg); } }
@keyframes vs-warm-ring-out { to { opacity: 0; } }
@keyframes vs-warm-check-in { to { opacity: 1; transform: rotate(45deg) scale(1); } }
@keyframes vs-warm-log-out  { to { opacity: 0; transform: translateY(-6px); } }

/* The payoff — scales in after the checklist clears. */
/* The payoff — a prominent centered overlay, nudged up from dead center. */
.vs-ritual-payoff {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding-bottom: 16vh;
  z-index: 3;
  pointer-events: none;
}
.vs-ritual-line {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  text-align: center;
  opacity: 0;
  animation: vs-ritual-line-in 0.9s var(--vs-ease) 6.8s both;
}
.vs-ritual-kicker {
  width: 46px;
  height: 1px;
  background: var(--vs-faint);
}
.vs-ritual-text {
  font-size: clamp(1.7rem, 4.4vw, 2.6rem);
  font-weight: 700;
  letter-spacing: 0.01em;
  color: var(--vs-text);
  text-shadow: 0 0 28px rgba(var(--vs-tint), 0.6), 0 2px 10px rgba(0, 0, 0, 0.5);
}
.vs-ritual-sub {
  font-size: clamp(0.95rem, 1.8vw, 1.2rem);
  color: var(--vs-text-2);
}

.vs-ritual-skip {
  position: fixed;
  top: 18px;
  right: 20px;
  background: none;
  border: 0;
  color: var(--vs-faint);
  font-size: 0.82rem;
  letter-spacing: 0.04em;
  cursor: pointer;
  padding: 6px 10px;
  z-index: 2;
}
.vs-ritual-skip:hover { color: var(--vs-text-2); }

@keyframes vs-ritual-veil-in { to { opacity: 1; } }
@keyframes vs-ritual-line-in {
  from { opacity: 0; transform: translateY(10px) scale(0.98); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}
@keyframes vs-ritual-dissolve {
  from { opacity: 1; }
  to   { opacity: 0; pointer-events: none; visibility: hidden; }
}

/* ===== Reduced motion: skip the cinematic. Show a composed final frame
   (printer assembled, first layer laid, payoff line) then a plain fade. The
   C# timer (~5.2s) unmounts the node. ===== */
@media (prefers-reduced-motion: reduce) {
  .vs-ritual { animation: vs-ritual-dissolve-rm 0.5s linear 2.4s forwards; }
  .vs-ritual-veil { animation: none; opacity: 1; }
  .vs-ritual-halo { animation: none; opacity: 0.45; transform: scale(1); }
  .vs-ritual-spool { animation: none; opacity: 0.32; }
  .vs-ritual-spin { animation: none; }
  .vs-pr-frame rect,
  .vs-pr-bed { animation: none; opacity: 1; transform: none; }
  .vs-pr-bed-heat,
  .vs-pr-noz-heat { animation: none; opacity: 0.3; }
  .vs-pr-zlift { animation: none; transform: translateY(0); }
  .vs-pr-carriage { animation: none; transform: translateX(50px); }
  .vs-pr-ooze { animation: none; transform: scaleY(1); }
  .vs-pr-poop { animation: none; transform: none; }
  .vs-pr-line { animation: none; stroke-dashoffset: 0; }
  .vs-pr-screen { animation: none; opacity: 1; }
  .vs-scr-cycle { animation: none; opacity: 0; }
  .vs-scr-last { animation: none; opacity: 1; }
  .vs-scr-name { animation: none; opacity: 1; }
  .vs-warm-log { display: none; }
  .vs-ritual-line { animation: none; opacity: 1; transform: none; }
}
@keyframes vs-ritual-dissolve-rm {
  to { opacity: 0; pointer-events: none; visibility: hidden; }
}

/* Sprinkle "crumbs" resting under the donut (the bits that spilled out). */
.vs-donut-crumbs {
  position: absolute;
  left: 10px;
  bottom: 7px;
  width: 640px;
  max-width: 82%;
  height: 26px;
  pointer-events: none;
}
.vs-crumb {
  position: absolute;
  width: 13px;
  height: 4px;
  border-radius: 2px;
  opacity: 0.9;
  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.25);
}


/* Studio layout: shelf wall + optional sidebar */
.vs-studio-layout {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  margin-top: 0;
}

.vs-studio-main {
  flex: 1 1 0;
  min-width: 0;
}

/* Queue sidebar */
.vs-studio-sidebar {
  width: 260px;
  flex-shrink: 0;
  position: sticky;
  top: 80px;
  background: var(--vs-surface);
  border: 1px solid rgba(255, 255, 255, 0.04);
  border-radius: var(--vs-radius-sm);
  padding: 16px;
  box-shadow: var(--vs-shadow-sm);
}

.vs-queue-header {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--vs-faint);
  margin-bottom: 16px;
}

.vs-queue-group {
  margin-bottom: 20px;
}

.vs-queue-group:last-child {
  margin-bottom: 0;
}

.vs-queue-group-title {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  font-weight: 500;
  color: var(--vs-text-2);
  letter-spacing: 0.015em;
  margin-bottom: 8px;
}

.vs-queue-count {
  margin-left: auto;
  font-size: 11px;
  color: var(--vs-muted);
  font-weight: 500;
}

.vs-queue-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 3px 6px;
  margin: 0 -6px;
  border-radius: 5px;
  transition: background 0.16s var(--vs-ease);
}
.vs-queue-row:hover {
  background: rgba(120,152,191,0.07);
}

.vs-queue-row-name {
  font-size: 11px;
  color: var(--vs-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}

.vs-queue-more {
  font-size: 11px;
  color: var(--vs-faint);
  padding: 2px 0 0 26px;
}

.vs-queue-action {
  padding: 0;
}

.vs-queue-link {
  font-size: 11px;
  color: var(--vs-accent);
  text-decoration: none;
  opacity: 0.75;
  transition: opacity 0.15s;
}

.vs-queue-link:hover {
  opacity: 1;
}

/* ── Studio: display-bay shelf layout ─────────────────────────────────────
   Full-width spool bays. Header becomes a thin exhibit label across the top.
   Shelves feel like illuminated recessed storage bays, not UI cards. */
.vs-studio-main .vs-shelves-section {
  margin-bottom: 32px;
  padding-top: 6px;
}
.vs-studio-main .vs-shelves-section::before {
  display: none;
}
.vs-studio-main .vs-storage-unit {
  margin-bottom: 14px;
}

/* Room label: sits closer to the block below than the separator above */
.vs-studio-main .vs-shelves-section-head {
  margin-top: 4px;
  margin-bottom: -5px;
}

/* Storage unit icon */
.vs-storage-unit-icon {
  display: inline-block;
  vertical-align: middle;
  margin-right: 6px;
  margin-top: -1px;
  opacity: 0.45;
}

/* Room icon */
.vs-room-icon {
  display: inline-block;
  vertical-align: middle;
  margin-right: 6px;
  margin-top: -1px;
  opacity: 0.72;
}

/* Room labels — physical studio zone signage */
.vs-studio-main .vs-shelves-section-title {
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(175, 192, 215, 0.68);
}
.vs-studio-main .vs-shelves-section-title::before {
  display: none;
}
.vs-studio-main .vs-shelves-section-title::after {
  display: none;
}
.vs-studio-main .vs-shelves-section-count {
  display: none;
}

/* Storage unit name: de-emphasised — it's structure, not content */
.vs-studio-main .vs-storage-unit-name {
  color: rgba(155, 175, 205, 0.54);
  font-size: 13px;
}

/* Storage unit head: dotted leader between name and stats */
.vs-studio-main .vs-storage-unit-head {
  display: flex;
  align-items: center;
  overflow: hidden;
  background: rgba(18, 23, 36, 0.96);
}
.vs-studio-main .vs-storage-unit-head::after {
  content: "";
  order: 1;
  flex: 1;
  height: 1px;
  background: repeating-linear-gradient(
    90deg,
    rgba(255,255,255,0.055) 0px,
    rgba(255,255,255,0.055) 2px,
    transparent 2px,
    transparent 8px
  );
  margin: 0 12px;
}
.vs-studio-main .vs-storage-unit-stats {
  order: 3;
  flex-shrink: 0;
}
.vs-storage-unit-hint {
  order: 2;
  flex-shrink: 0;
  font-size: 10px;
  font-style: italic;
  color: var(--vs-muted);
  opacity: 0.55;
  margin-right: 16px;
}

/* Unit frame: deep bay cavity */
.vs-studio-main .vs-storage-unit-frame {
  padding: 16px;
  background: var(--vs-bg-deep);
  box-shadow:
    inset 0 5px 20px rgba(0,0,0,0.38),
    inset 0 1px 0 rgba(255,255,255,0.03),
    0 2px 6px rgba(0,0,0,0.22);
}

/* Shelf: full-width bay with recessed depth */
.vs-studio-main .vs-shelf {
  grid-template-columns: 1fr;
  border: none; /* recessed shadows carry the bay edges on the pegboard wall */
  /* Neutral tints (was steel-blue at 1-3% alpha — invisible but read as
     "glowing accents" by design tooling) */
  background: linear-gradient(
    180deg,
    rgba(0,0,0,0.22) 0%,
    rgba(0,0,0,0.06) 15%,
    rgba(255,255,255,0.00) 50%,
    rgba(255,255,255,0.020) 82%,
    rgba(255,255,255,0.013) 100%
  );
  box-shadow:
    inset 0 4px 16px rgba(0,0,0,0.34),
    inset 0 -1px 0 rgba(255,255,255,0.038),
    inset 0 1px 0 rgba(255,255,255,0.012),
    inset 0 -8px 14px rgba(255,255,255,0.013);
}

/* Shelf header: thin exhibit label bar */
.vs-studio-main .vs-shelf-header {
  flex-direction: row;
  align-items: center;
  gap: 10px;
  border-right: none;
  border-bottom: 1px solid rgba(255,255,255,0.028);
  padding: 7px 20px 6px;
}

.vs-studio-main .vs-shelf-name {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  /* Solid hex (no alpha): contrast scanners can't composite translucent text */
  color: #c0d0e4;
}

.vs-studio-main .vs-shelf-count {
  font-size: 10px;
  font-family: var(--vs-mono);
  color: #a3bad4;
  background: rgba(var(--vs-tint), 0.08);
  border: 1px solid rgba(var(--vs-tint), 0.12);
  border-radius: 4px;
  padding: 1px 6px;
  opacity: 1;
}

.vs-studio-main .vs-shelf-count::before {
  content: "";
}

.vs-studio-main .vs-shelf-count::after {
  content: "";
}

/* Bay area: more vertical room, ambient floor glow */
.vs-studio-main .vs-shelf-area {
  position: relative;
  padding: 26px 22px 18px;
  min-height: 200px;
  gap: 7px;
  border-radius: 0 0 var(--vs-radius) var(--vs-radius);
  box-shadow:
    inset 0 8px 22px rgba(0,0,0,0.16),
    inset 0 -2px 6px rgba(0,0,0,0.07);
  overflow-x: auto;
  overflow-y: visible;
  overscroll-behavior-x: contain;
  flex-wrap: nowrap;
}
.vs-studio-main .vs-shelf-area::-webkit-scrollbar {
  height: 3px;
}
.vs-studio-main .vs-shelf-area::-webkit-scrollbar-track {
  background: transparent;
}
.vs-studio-main .vs-shelf-area::-webkit-scrollbar-thumb {
  background: rgba(120,152,191,0.22);
  border-radius: 2px;
}
.vs-studio-main .vs-shelf-area::-webkit-scrollbar-thumb:hover {
  background: rgba(120,152,191,0.44);
}
.vs-studio-main .vs-shelf-area.is-sparse {
  min-height: 0;
  padding-top: 16px;
  padding-bottom: 14px;
}
.vs-studio-main .vs-shelf-area:has(.vs-shelf-empty) {
  min-height: 52px;
  padding: 0 22px;
}

/* Implied shelf floor — a faint horizontal line at the base of each bay */
.vs-studio-main .vs-shelf-area::after {
  content: "";
  position: absolute;
  bottom: 0;
  left: 8%;
  right: 8%;
  height: 1px;
  background: linear-gradient(
    90deg,
    transparent 0%,
    rgba(214,224,238,0.05) 25%,
    rgba(214,224,238,0.068) 50%,
    rgba(214,224,238,0.05) 75%,
    transparent 100%
  );
  pointer-events: none;
}

/* Shelf bay glows faintly when a spool is hovered — ambient illumination response */
.vs-studio-main .vs-shelf-area:has(.vs-shelf-spool:hover) {
  background: radial-gradient(
    ellipse 80% 60% at 50% 95%,
    rgba(120,152,191,0.07) 0%,
    transparent 62%
  );
}

.vs-studio-main .vs-storage-unit-shelves {
  gap: 10px;
}

/* Spool rhythm — tiny coprime spacing variations break the perfect grid */
.vs-studio-main .vs-shelf-area > .vs-shelf-spool:nth-child(4n) {
  margin-right: 3px;
}
.vs-studio-main .vs-shelf-area > .vs-shelf-spool:nth-child(7n) {
  margin-left: 2px;
}

/* Empty bay — ghost text + faint vertical slot rhythm */
.vs-studio-main .vs-shelf-area:has(.vs-shelf-empty) {
  background-image: repeating-linear-gradient(
    90deg,
    transparent 0px,
    transparent 46px,
    rgba(255,255,255,0.013) 46px,
    rgba(255,255,255,0.013) 48px,
    transparent 48px,
    transparent 56px
  );
}

.vs-studio-main .vs-shelf-empty {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: #84888f; /* solid equivalent of the old translucent white */
  pointer-events: none;
}

/* Sparse bay (1–4 spools) — faint implied capacity rhythm */
.vs-studio-main .vs-shelf-area.is-sparse::before {
  content: "";
  position: absolute;
  inset: 0;
  background: repeating-linear-gradient(
    90deg,
    transparent 0px,
    transparent 46px,
    rgba(120,152,191,0.017) 46px,
    rgba(120,152,191,0.017) 48px,
    transparent 48px,
    transparent 56px
  );
  pointer-events: none;
  border-radius: 0 0 var(--vs-radius) var(--vs-radius);
}

/* Studio drop target — softer than default */
.vs-studio-main .vs-shelf-area.is-over {
  background: rgba(120,152,191,0.09);
  box-shadow: inset 0 0 0 1px rgba(120,152,191,0.22);
}

/* ── Studio bench — two drop zones above the shelf wall ──────────────────── */
.vs-studio-bench {
  display: flex;
  gap: 14px;
  margin-bottom: 14px;
}

.vs-bench-zone {
  flex: 1;
  min-height: 120px;
  border-radius: 14px;
  border: 1.5px dashed rgba(120,152,191,0.18);
  background: rgba(13,17,28,0.55);
  padding: 14px 16px 12px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  transition: border-color 0.18s ease, background 0.18s ease, box-shadow 0.18s ease;
  position: relative;
}

.vs-bench-zone--printing {
  border-color: rgba(225,187,107,0.22);
}
.vs-bench-zone--drying {
  border-color: rgba(120,152,191,0.22);
}

.vs-bench-zone.is-over {
  border-style: solid;
  box-shadow: inset 0 0 0 1px rgba(120,152,191,0.30);
}
.vs-bench-zone--printing.is-over {
  border-color: rgba(225,187,107,0.55);
  background: rgba(225,187,107,0.05);
  box-shadow: inset 0 0 0 1px rgba(225,187,107,0.25);
}
.vs-bench-zone--drying.is-over {
  border-color: rgba(120,152,191,0.55);
  background: rgba(120,152,191,0.06);
}

/* Touch drag-over mirrors the is-over styles */
.vs-studio-main .vs-shelf-area.touch-drag-over {
  background: rgba(120,152,191,0.09);
  box-shadow: inset 0 0 0 1px rgba(120,152,191,0.22);
}
.vs-bench-zone.touch-drag-over {
  border-style: solid;
  box-shadow: inset 0 0 0 1px rgba(120,152,191,0.30);
}
.vs-bench-zone--printing.touch-drag-over {
  border-color: rgba(225,187,107,0.55);
  background: rgba(225,187,107,0.05);
  box-shadow: inset 0 0 0 1px rgba(225,187,107,0.25);
}
.vs-bench-zone--drying.touch-drag-over {
  border-color: rgba(120,152,191,0.55);
  background: rgba(120,152,191,0.06);
}

.vs-bench-zone-label {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(160,178,205,0.70);
}

.vs-bench-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  flex-shrink: 0;
}
.vs-bench-dot--printing {
  background: rgba(225,187,107,0.18);
  box-shadow: none;
}
.vs-bench-dot--drying {
  background: rgba(120,152,191,0.18);
  box-shadow: none;
}
/* Occupied zones — step dots up slightly */
.vs-bench-zone--printing:not(:has(.vs-bench-empty)) .vs-bench-dot--printing {
  background: rgba(225,187,107,0.55);
  box-shadow: 0 0 4px rgba(225,187,107,0.25);
}
.vs-bench-zone--drying:not(:has(.vs-bench-empty)) .vs-bench-dot--drying {
  background: rgba(120,152,191,0.55);
  box-shadow: 0 0 4px rgba(120,152,191,0.25);
}

.vs-bench-spools {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: flex-end;
  min-height: 60px;
}

.vs-bench-empty {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  pointer-events: none;
  padding-top: 28px;
}
.vs-bench-empty-state {
  font-size: 10px;
  font-style: italic;
  color: rgba(120,152,191,0.36);
  letter-spacing: 0.02em;
}

/* Workshop Activity sidebar — pegboard panel with translucent depth.
   Dark semi-transparent base + backdrop blur = physical separation from page.
   Asymmetric vignette + directional lighting = mounted workshop panel feel. */
.vs-studio-sidebar {
  background-color: rgba(12, 16, 26, 0.84);
  background-image:
    radial-gradient(ellipse 90% 70% at 35% 20%, transparent 35%, rgba(0,0,0,0.12) 100%),
    linear-gradient(180deg, rgba(255,255,255,0.018) 0%, transparent 40%, rgba(0,0,0,0.10) 100%),
    linear-gradient(165deg, rgba(255,255,255,0.018) 0%, transparent 45%, rgba(0,0,0,0.055) 100%),
    radial-gradient(circle, rgba(200,215,240,0.030) 1.0px, rgba(200,215,240,0.014) 1.7px, transparent 1.7px);
  background-size: auto, auto, auto, 20px 20px;
  background-position: 0 0, 0 0, 0 0, 0 0;
  border: none;
  border-left: 1px solid rgba(120,152,191,0.08);
  border-radius: 0;
  padding: 12px 14px 24px 16px;
  top: 80px;
  box-shadow:
    inset 2px 0 0 rgba(200,215,240,0.085),
    inset 0 0 40px rgba(0,0,0,0.22);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}

.vs-queue-header {
  font-size: 9px;
  font-weight: 600;
  color: var(--vs-muted);
  letter-spacing: 0.10em;
  margin-bottom: 16px;
}

.vs-queue-group {
  margin-bottom: 22px;
}

.vs-queue-group-title {
  color: var(--vs-muted);
  font-size: 11px;
  font-weight: 400;
  letter-spacing: 0.01em;
  margin-bottom: 10px;
}

.vs-queue-row:hover {
  background: rgba(120,152,191,0.06);
}

.vs-queue-row-name {
  color: rgba(150, 168, 196, 0.80);
  font-size: 10.5px;
}

.vs-queue-count {
  color: var(--vs-faint);
  opacity: 1;
}

.vs-queue-link {
  color: rgba(var(--vs-tint), 1);
  opacity: 0.92;
}

/* Sidebar quick-action footer */
.vs-queue-footer {
  display: flex;
  flex-direction: column;
  gap: 7px;
  padding-top: 18px;
  margin-top: 8px;
  border-top: 1px solid rgba(120,152,191,0.10);
}
.vs-queue-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 5px 14px;
  border-radius: 8px;
  border: 1px solid rgba(120,152,191,0.28);
  background: rgba(120,152,191,0.10);
  color: rgba(185,208,238,1);
  font-size: 11px;
  font-family: var(--vs-sans);
  font-weight: 500;
  letter-spacing: 0.02em;
  text-decoration: none;
  transition: background 0.15s, border-color 0.15s, color 0.15s;
}
.vs-queue-btn:hover {
  background: rgba(120,152,191,0.18);
  border-color: rgba(120,152,191,0.42);
  color: rgba(210,228,255,1);
}

/* Bench zones inside sidebar — stacked vertically, taller spools */
.vs-studio-sidebar .vs-studio-bench {
  flex-direction: column;
  gap: 8px;
  margin-bottom: 22px;
}
.vs-studio-sidebar .vs-bench-zone {
  min-height: 0;
  border-radius: 10px;
  padding: 8px 10px 8px;
  overflow: hidden;
}
.vs-studio-sidebar .vs-bench-zone-label {
  font-size: 9px;
  gap: 5px;
  margin-bottom: 6px;
}
.vs-studio-sidebar .vs-bench-spools {
  flex-wrap: nowrap;
  overflow: hidden;
  gap: 5px;
  align-items: flex-end;
  min-height: 72px;
  -webkit-mask-image: linear-gradient(to right, black 72%, transparent 100%);
  mask-image: linear-gradient(to right, black 72%, transparent 100%);
}
.vs-studio-sidebar .vs-bench-empty {
  position: static;
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding-top: 0;
  align-items: center;
  justify-content: center;
  height: 72px;
}
.vs-studio-sidebar .vs-bench-empty .vs-bench-empty-state {
  font-size: 9px;
}
.vs-studio-sidebar .vs-bench-empty .vs-bench-empty-hint {
  font-size: 8px;
}

/* Search inside sidebar utility rail */
.vs-sidebar-search {
  margin-bottom: 20px;
}
.vs-studio-search-input--sidebar {
  width: 100%;
  box-sizing: border-box;
}

/* Admin library nav links in Settings */
.vs-admin-library {
  display: flex;
  gap: 12px;
  margin-bottom: 20px;
}
.vs-admin-library-link {
  font-size: 13px;
  color: rgba(120,152,191,0.88);
  text-decoration: none;
  padding: 6px 14px;
  border: 1px solid rgba(120,152,191,0.20);
  border-radius: 8px;
  font-family: var(--vs-sans);
  font-weight: 500;
  transition: background 0.15s, border-color 0.15s;
}
.vs-admin-library-link:hover {
  background: rgba(120,152,191,0.08);
  border-color: rgba(120,152,191,0.35);
  color: rgba(150,180,220,1);
}

.vs-ambient-dot--drying,
.vs-ambient-dot--tostore,
.vs-ambient-dot--swatch,
.vs-ambient-dot--unassigned {
  opacity: 0.85;
}

@media (max-width: 900px) {
  .vs-studio-layout {
    flex-direction: column;
  }
  .vs-studio-sidebar {
    width: 100%;
    position: static;
  }
}

/* ── Auth pages (Login / Register) ─────────────────────────────────────── */
.vs-auth-page {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 100vh;
  background: var(--vs-bg-deep);
  font-family: var(--vs-sans);
  padding: 32px 16px;
}

.vs-auth-wrap {
  width: 100%;
  max-width: 380px;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.vs-auth-logo {
  display: flex;
  align-items: center;
  gap: 10px;
  text-decoration: none;
  margin-bottom: 8px;
}

.vs-auth-logo-text {
  font-family: var(--vs-display);
  font-size: 24px;
  font-weight: 500;
  color: var(--vs-text);
  letter-spacing: -0.01em;
}

.vs-auth-logo-text em {
  font-style: normal;
  color: var(--vs-blue);
}

.vs-auth-tagline {
  font-size: 13px;
  color: var(--vs-muted);
  margin: 0 0 16px;
  letter-spacing: 0.01em;
}

/* Decorative spool row above the auth card — a glimpse of what you're collecting. */
.vs-auth-spools {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 11px;
  margin: 0 0 26px;
}
.vs-auth-spools svg {
  filter: drop-shadow(0 4px 10px rgba(0, 0, 0, 0.35));
  transition: transform 0.25s ease;
}
.vs-auth-spools svg:hover {
  transform: translateY(-3px) scale(1.08);
}
@media (max-width: 380px) {
  .vs-auth-spools { gap: 7px; }
  .vs-auth-spools svg { width: 44px; height: 44px; }
}

.vs-auth-card {
  width: 100%;
  background: var(--vs-surface);
  border: 1px solid var(--vs-hair);
  border-radius: var(--vs-radius);
  padding: 28px;
  box-shadow: var(--vs-shadow);
  margin-bottom: 20px;
}

.vs-auth-field {
  margin-bottom: 18px;
}

.vs-auth-label {
  display: block;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--vs-muted);
  margin-bottom: 7px;
}

.vs-auth-label-optional {
  font-size: 10px;
  font-weight: 400;
  text-transform: none;
  letter-spacing: 0;
  color: var(--vs-faint);
  margin-left: 6px;
}

.vs-auth-label-required {
  color: #e88080;
  margin-left: 4px;
  font-weight: 700;
}

.vs-auth-password-wrap {
  position: relative;
}

.vs-auth-password-wrap .vs-auth-input {
  padding-right: 44px;
}

.vs-auth-password-toggle {
  position: absolute;
  top: 50%;
  right: 10px;
  transform: translateY(-50%);
  background: transparent;
  border: none;
  color: var(--vs-faint);
  cursor: pointer;
  padding: 4px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 4px;
}

.vs-auth-password-toggle:hover {
  color: var(--vs-text);
}

.vs-auth-input {
  width: 100%;
  padding: 11px 14px;
  background: var(--vs-bg);
  border: 1px solid var(--vs-hair-2);
  border-radius: var(--vs-radius-sm);
  font-family: var(--vs-sans);
  font-size: 14px;
  color: var(--vs-text);
  box-sizing: border-box;
  outline: none;
  transition: border-color 0.18s;
}

.vs-auth-input:focus {
  border-color: var(--vs-accent);
}

.vs-auth-hint {
  font-size: 11px;
  color: var(--vs-faint);
  margin: 5px 0 0;
  line-height: 1.4;
}

/* Form validation: replaces the browser's default error tooltip with a
   themed inline message. .vs-field-error slots are created by vs-helpers.js
   when an invalid event fires; .is-invalid is added to the input itself. */
.vs-field-error {
  display: none;
  margin-top: 6px;
  font-size: 12px;
  color: #e88080;
  line-height: 1.4;
}

.vs-field-error.is-visible {
  display: block;
}

.vs-auth-input.is-invalid,
input.is-invalid {
  border-color: #e88080;
  background-color: rgba(232, 128, 128, 0.04);
}

.vs-auth-input.is-invalid:focus,
input.is-invalid:focus {
  border-color: #e88080;
}

.vs-auth-btn {
  width: 100%;
  padding: 12px;
  margin-top: 10px;
  background: var(--vs-accent);
  border: none;
  border-radius: var(--vs-radius-sm);
  font-family: var(--vs-sans);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.05em;
  color: #fff;
  cursor: pointer;
  transition: background 0.18s;
}

.vs-auth-btn:hover {
  background: var(--vs-accent-deep);
}

.vs-auth-google-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  width: 100%;
  padding: 11px 12px;
  background: #fff;
  color: #1f1f1f;
  border: 1px solid #dadce0;
  border-radius: var(--vs-radius-sm);
  font-family: var(--vs-sans);
  font-size: 13px;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
  transition: box-shadow 0.18s, background 0.18s;
}

.vs-auth-google-btn:hover {
  background: #f8f9fa;
  box-shadow: 0 1px 3px rgba(0,0,0,0.15);
}

.vs-auth-discord-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  width: 100%;
  padding: 11px 12px;
  margin-top: 8px;
  background: #5865F2;
  color: #fff;
  border: 1px solid #5865F2;
  border-radius: var(--vs-radius-sm);
  font-family: var(--vs-sans);
  font-size: 13px;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
  transition: background 0.18s, box-shadow 0.18s;
}

.vs-auth-discord-btn:hover {
  background: #4752c4;
  box-shadow: 0 1px 3px rgba(0,0,0,0.25);
}

.vs-auth-divider {
  display: flex;
  align-items: center;
  text-align: center;
  margin: 14px 0;
  color: var(--vs-faint);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.1em;
}

.vs-auth-divider::before,
.vs-auth-divider::after {
  content: "";
  flex: 1;
  border-top: 1px solid var(--vs-hair);
}

.vs-auth-divider span {
  padding: 0 12px;
}

.vs-auth-footer-link {
  font-size: 13px;
  color: var(--vs-muted);
  text-align: center;
  margin: 0;
}

.vs-auth-footer-link a {
  color: var(--vs-accent);
  text-decoration: none;
  font-weight: 500;
}

.vs-auth-footer-link a:hover {
  text-decoration: underline;
}

/* ── Onboarding wizard ──────────────────────────────────────────────────── */
.vs-wizard-page {
  min-height: 100vh;
  background: var(--vs-bg-deep);
  font-family: var(--vs-sans);
  color: var(--vs-text);
  padding: 40px 16px 80px;
}

.vs-wizard-wrap {
  max-width: 860px;
  margin: 0 auto;
}

.vs-wizard-steps {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 14px;
}

/* Step-based completion bar — shows how far through the flow the Maker is. */
.vs-wizard-progress {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 36px;
}

.vs-wizard-progress-track {
  flex: 1;
  height: 5px;
  border-radius: 999px;
  background: var(--vs-hair-2);
  overflow: hidden;
}

.vs-wizard-progress-fill {
  height: 100%;
  border-radius: 999px;
  /* Brighter logo-blue (not the muted slate accent, which read too dark here). */
  background: var(--vs-blue);
  transition: width 0.45s cubic-bezier(0.22, 1, 0.36, 1);
}

.vs-wizard-progress-spool {
  flex-shrink: 0;
  display: block;
}

/* Animate the wound filament radius + color change as steps advance. */
.vs-wizard-progress-spool .vs-wound {
  transition: r 0.45s cubic-bezier(0.22, 1, 0.36, 1), fill 0.4s ease;
}

@media (prefers-reduced-motion: reduce) {
  .vs-wizard-progress-spool .vs-wound { transition: fill 0.4s ease; }
}

.vs-wizard-progress-label {
  font-size: 11px;
  font-weight: 600;
  color: var(--vs-faint);
  white-space: nowrap;
  flex-shrink: 0;
}

.vs-wizard-step-dot {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  font-weight: 700;
  background: var(--vs-surface);
  border: 2px solid var(--vs-hair-2);
  color: var(--vs-faint);
  flex-shrink: 0;
}

.vs-wizard-step-dot.is-active {
  background: rgba(120,152,191,0.12);
  border-color: var(--vs-accent);
  color: var(--vs-accent);
}

.vs-wizard-step-dot.is-done {
  background: var(--vs-accent);
  border-color: var(--vs-accent);
  color: #fff;
}

.vs-wizard-step-label {
  font-size: 12px;
  color: rgba(85,96,116,0.7);
}

.vs-wizard-step-label.is-done {
  color: var(--vs-text-2);
}

.vs-wizard-step-label.is-active {
  color: var(--vs-text);
}

.vs-wizard-step-sep {
  color: var(--vs-hair-2);
  margin: 0 2px;
  font-size: 12px;
}

.vs-wizard-heading {
  font-size: 24px;
  font-weight: 700;
  color: var(--vs-text);
  margin: 0 0 8px;
  letter-spacing: -0.02em;
}

.vs-wizard-sub {
  font-size: 14px;
  color: var(--vs-muted);
  margin: 0 0 24px;
  line-height: 1.5;
}

.vs-wizard-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 10px;
  margin-bottom: 24px;
}

.vs-wizard-tile {
  padding: 14px 10px;
  min-height: 72px;
  background: var(--vs-surface);
  border: 1px solid var(--vs-hair);
  border-radius: var(--vs-radius-sm);
  cursor: pointer;
  text-align: center;
  user-select: none;
  transition: background 0.15s, border-color 0.15s;
}

.vs-wizard-tile:hover {
  border-color: var(--vs-hair-2);
}

.vs-wizard-tile.is-selected {
  background: rgba(120,152,191,0.45);
  border-color: #9fc8f5;
  border-width: 3px;
  box-shadow: 0 0 0 1px rgba(159,200,245,0.2), 0 4px 16px rgba(120,152,191,0.3);
}

.vs-wizard-tile-name {
  font-weight: 600;
  font-size: 14px;
  color: var(--vs-text);
  margin-bottom: 2px;
}

.vs-wizard-tile.is-selected .vs-wizard-tile-name {
  color: var(--vs-text);
}

.vs-wizard-tile.is-selected .vs-wizard-tile-sub {
  color: var(--vs-text-2);
}

.vs-wizard-tile-sub {
  font-size: 11px;
  color: var(--vs-faint);
}

.vs-wizard-nav {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.vs-wizard-count {
  font-size: 13px;
  color: var(--vs-muted);
}

/* Step 3: filament groups */
.vs-wizard-filament-group {
  background: var(--vs-surface);
  border: 1px solid var(--vs-hair);
  border-radius: var(--vs-radius-sm);
  margin-bottom: 12px;
  overflow: hidden;
}

.vs-wizard-filament-group-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 16px;
  border-bottom: 1px solid var(--vs-hair-3);
  background: var(--vs-surface-2);
}

.vs-wizard-filament-brand {
  font-size: 13px;
  font-weight: 600;
  color: var(--vs-text);
  flex: 1;
}

.vs-wizard-filament-count {
  font-size: 11px;
  color: var(--vs-faint);
  font-family: var(--vs-mono);
}

.vs-wizard-toggle-all {
  font-size: 11px;
  color: var(--vs-accent);
  background: none;
  border: none;
  cursor: pointer;
  padding: 0;
  font-family: var(--vs-sans);
  opacity: 0.8;
  transition: opacity 0.15s;
}

.vs-wizard-toggle-all:hover {
  opacity: 1;
}

.vs-wizard-filament-cols {
  display: flex;
  gap: 12px;
  padding: 8px;
  align-items: flex-start;
  width: 100%;
}

.vs-wizard-filament-col {
  flex: 1 1 50%;
  min-width: 0;
  max-width: 50%;
}

.vs-wizard-filament-mat-col {
  padding: 4px 6px;
}

@media (max-width: 480px) {
  .vs-wizard-filament-cols { gap: 6px; padding: 4px; }
  .vs-wizard-filament-mat-col { padding: 2px 4px; }
}

.vs-wizard-filament-mat-label {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--vs-faint);
  margin-bottom: 6px;
  padding-bottom: 4px;
  border-bottom: 1px solid var(--vs-hair-3);
}

.vs-wizard-filament-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 5px 6px;
  border-radius: 5px;
  cursor: pointer;
  user-select: none;
  transition: background 0.12s;
}

.vs-wizard-filament-row:hover {
  background: var(--vs-surface-2);
}

.vs-wizard-filament-row.is-selected {
  background: rgba(120,152,191,0.08);
}

.vs-wizard-filament-check {
  flex-shrink: 0;
  display: flex;
  align-items: center;
}

.vs-wizard-filament-name {
  flex: 1;
  font-size: 12px;
  color: var(--vs-text-2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}

.vs-wizard-filament-row.is-selected .vs-wizard-filament-name {
  color: var(--vs-text);
}

.vs-wizard-summary-row {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 14px;
  color: var(--vs-text-2);
}

/* ── App footer ─────────────────────────────────────────────────────────────*/

.vs-topbar-signin {
  font-size: 13px;
  font-weight: 500;
  color: var(--vs-muted);
  padding: 6px 12px;
  transition: color 0.15s;
}

.vs-topbar-signin:hover {
  color: var(--vs-text);
}

.vs-topbar-signup {
  font-size: 13px;
  font-weight: 600;
  color: var(--vs-bg-deep);
  background: var(--vs-accent);
  padding: 7px 16px;
  border-radius: 20px;
  letter-spacing: 0.01em;
  transition: opacity 0.15s;
}

.vs-topbar-signup:hover {
  opacity: 0.85;
}

.vs-app-footer {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 18px 32px;
  /* No border-top: the spectrum strip (absolute, top:0) is the divider. A border
     here renders just above the strip and reads as a stray hairline on light themes. */
  font-size: 12px;
  color: var(--vs-faint);
  font-family: var(--vs-sans);
}

/* Signature spectrum strip seated at the top edge of the workspace footer
   (SpectrumStrip.razor, muted a touch more than the public one). */
.vs-app-footer-strip {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  line-height: 0;
}

/* NFC tag writer (NfcWriteButton.razor) */
.vs-label-pop-nfc {
  padding: 14px 18px 2px;
  border-top: 1px solid var(--vs-hair);
}

.vs-nfc {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 4px;
}

.vs-nfc-head {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  color: var(--vs-faint);
}

.vs-nfc-write {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  align-self: flex-start;
  padding: 9px 16px;
  font-family: inherit;
  font-size: 14px;
  font-weight: 600;
  color: var(--vs-bg-deep);
  background: var(--vs-accent);
  border: none;
  border-radius: 8px;
  cursor: pointer;
  transition: opacity 0.15s;
}

.vs-nfc-write:hover { opacity: 0.9; }
.vs-nfc-write:disabled { opacity: 0.7; cursor: default; }

.vs-nfc-url {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  align-self: flex-start;
  max-width: 100%;
  padding: 6px 6px 6px 12px;
  background: var(--vs-surface);
  border: 1px solid var(--vs-hair-2);
  border-radius: 8px;
}

.vs-nfc-url code {
  font-size: 12px;
  color: var(--vs-text-2);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.vs-nfc-copy {
  flex-shrink: 0;
  padding: 4px 10px;
  font-family: inherit;
  font-size: 12px;
  font-weight: 600;
  color: var(--vs-info);
  background: none;
  border: 1px solid var(--vs-hair-2);
  border-radius: 6px;
  cursor: pointer;
}

.vs-nfc-copy:hover { color: var(--vs-text); border-color: var(--vs-accent); }

.vs-nfc-tip {
  font-size: 12px;
  color: var(--vs-muted);
  line-height: 1.5;
  max-width: 340px;
}

.vs-nfc-tip strong { color: var(--vs-text-2); }
.vs-nfc-ok { font-size: 12px; color: var(--vs-success); }
.vs-nfc-err { font-size: 12px; color: var(--vs-danger); line-height: 1.5; max-width: 340px; }

/* Compact icon button (table rows) */
.vs-nfc-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  color: var(--vs-text-2);
  background: none;
  border: 1px solid var(--vs-hair-2);
  border-radius: 7px;
  cursor: pointer;
  transition: color 0.15s, border-color 0.15s;
}

.vs-nfc-icon:hover { color: var(--vs-accent); border-color: var(--vs-accent); }
.vs-nfc-icon.is-done { color: var(--vs-success); border-color: var(--vs-success); }
.vs-nfc-icon:disabled { opacity: 0.7; cursor: default; }

.vs-nfc-spin {
  width: 13px;
  height: 13px;
  border: 2px solid currentColor;
  border-top-color: transparent;
  border-radius: 50%;
  animation: vs-nfc-spin 0.7s linear infinite;
}

@keyframes vs-nfc-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .vs-nfc-spin { animation: none; }
}

/* Studio Moments banner (StudioMoments.razor): holiday + milestone cards, each
   tinted by its own --moment-accent. */
.vs-moments {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-bottom: 18px;
}
.vs-moment {
  position: relative;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px 44px 14px 16px;
  border: 1px solid var(--vs-hair-2);
  border-left: 3px solid var(--moment-accent, var(--vs-accent));
  border-radius: 14px;
  background:
    linear-gradient(90deg, color-mix(in srgb, var(--moment-accent, var(--vs-accent)) 13%, transparent), transparent 62%),
    var(--vs-surface);
}
.vs-moment-emoji {
  font-size: 30px;
  line-height: 1;
  flex-shrink: 0;
}
.vs-moment-text {
  flex: 1;
  min-width: 0;
}
.vs-moment-eyebrow {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--moment-accent, var(--vs-accent));
}
.vs-moment-title {
  font-size: 16px;
  font-weight: 700;
  color: var(--vs-text);
  margin: 1px 0 2px;
}
.vs-moment-blurb {
  font-size: 13px;
  color: var(--vs-text-2);
  line-height: 1.45;
}
.vs-moment-cta {
  flex-shrink: 0;
  font-size: 13px;
  font-weight: 600;
  color: var(--moment-accent, var(--vs-accent));
  text-decoration: none;
  white-space: nowrap;
}
.vs-moment-x {
  position: absolute;
  top: 10px;
  right: 12px;
  background: none;
  border: none;
  color: var(--vs-faint);
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
  padding: 2px 6px;
}
.vs-moment-x:hover { color: var(--vs-text); }

/* Spool Detail: inline "log a print" editor + prints list */
.vs-printlog {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 10px;
}
.vs-printlog-label {
  display: block;
  font-size: 11px;
  font-weight: 600;
  color: var(--vs-muted);
  margin-bottom: 2px;
}
.vs-printlog-check {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  color: var(--vs-text-2);
}
.vs-printlog-list {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-top: 10px;
}
.vs-printlog-row {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 13px;
  color: var(--vs-text);
  padding: 3px 0;
}
.vs-printlog-row-main {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.vs-printlog-row-meta { color: var(--vs-faint); font-size: 12px; white-space: nowrap; }
.vs-printlog-del {
  background: none;
  border: none;
  color: var(--vs-faint);
  font-size: 16px;
  line-height: 1;
  cursor: pointer;
  padding: 0 2px;
}
.vs-printlog-del:hover { color: #c0392b; }

/* Models library (Models.razor) + repo source badges */
.vs-model-add {
  background: var(--vs-surface);
  border: 1px solid var(--vs-line);
  border-radius: 14px;
  padding: 14px;
  margin-bottom: 18px;
}
.vs-model-add-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
}
.vs-model-add-btn { white-space: nowrap; }
.vs-model-add-preview {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 10px;
  font-size: 12.5px;
}
.vs-model-add-thumb {
  width: 40px;
  height: 40px;
  object-fit: cover;
  border-radius: 6px;
  border: 1px solid var(--vs-hair-2);
  background: var(--vs-bg-deep);
}

.vs-src-badge {
  display: inline-flex;
  align-items: center;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .2px;
  color: #fff;
  background: var(--vs-faint);
}
.vs-src-printables    { background: #fa6831; }
.vs-src-makerworld    { background: #00ae42; }
.vs-src-thingiverse   { background: #2e8bee; }
.vs-src-thangs        { background: #6c5ce7; }
.vs-src-cults3d       { background: #e3256b; }
.vs-src-myminifactory { background: #1aa3a3; }
.vs-src-other         { background: #76829b; }

.vs-model-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 16px;
}
.vs-model-card {
  position: relative;
  background: var(--vs-surface);
  border: 1px solid var(--vs-line);
  border-radius: 14px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}
.vs-model-thumb {
  position: relative;
  aspect-ratio: 4 / 3;
  background: var(--vs-surface-2);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}
.vs-model-thumb img { width: 100%; height: 100%; object-fit: cover; }
.vs-model-thumb-ph { font-size: 38px; opacity: .5; }
.vs-model-thumb .vs-src-badge { position: absolute; top: 8px; left: 8px; }
.vs-model-body { padding: 11px 12px 13px; display: flex; flex-direction: column; gap: 5px; }
.vs-model-title {
  font-weight: 700;
  font-size: 14px;
  color: var(--vs-text);
  line-height: 1.25;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.vs-model-meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  font-size: 12.5px;
  color: var(--vs-muted);
}
.vs-model-prints-toggle {
  align-self: flex-start;
  background: none;
  border: none;
  padding: 2px 0;
  color: var(--vs-accent);
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
}
.vs-model-prints { margin-top: 2px; display: flex; flex-direction: column; gap: 4px; }
.vs-model-print-row {
  display: flex;
  justify-content: space-between;
  gap: 8px;
  font-size: 12px;
  color: var(--vs-text-2);
}
.vs-model-del {
  position: absolute;
  top: 6px;
  right: 6px;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  border: none;
  background: rgba(0,0,0,.45);
  color: #fff;
  font-size: 16px;
  line-height: 1;
  cursor: pointer;
  opacity: 0;
  transition: opacity .12s;
}
.vs-model-card:hover .vs-model-del { opacity: 1; }
.vs-model-del:hover { background: #c0392b; }

/* Activities: tabbed studio shell (Activities.razor) — tabs + misc launcher */
.vs-acts-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  border-bottom: 1px solid var(--vs-line);
  margin-bottom: 18px;
}
.vs-acts-tab {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 9px 16px;
  border: none;
  background: transparent;
  color: var(--vs-muted);
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  border-radius: 8px 8px 0 0;
}
.vs-acts-tab:hover { color: var(--vs-text); background: var(--vs-surface-2); }
.vs-acts-tab.is-active {
  color: var(--vs-text);
  border-bottom-color: var(--vs-accent);
}
.vs-acts-tab-emoji { font-size: 16px; line-height: 1; }
.vs-acts-tab-count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 20px;
  height: 20px;
  padding: 0 6px;
  border-radius: 10px;
  background: var(--vs-surface-2);
  color: var(--vs-text-2);
  font-size: 12px;
  font-weight: 700;
}
.vs-acts-tab.is-active .vs-acts-tab-count {
  background: var(--vs-accent);
  /* on-accent text: dark on dark-theme (light accent), light on light-theme
     (dark accent). A hardcoded near-black read dark-on-dark on light themes. */
  color: var(--vs-bg-deep);
}
.vs-acts-panel { min-height: 200px; }

.vs-acts-misc {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 14px;
}
.vs-acts-misc-card {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 18px;
  border-radius: 14px;
  background: var(--vs-surface);
  border: 1px solid var(--vs-line);
  text-decoration: none;
  transition: border-color .12s, transform .12s;
}
.vs-acts-misc-card:hover {
  border-color: var(--vs-accent);
  transform: translateY(-2px);
}
.vs-acts-misc-icon {
  font-size: 26px;
  width: 26px;
  height: 26px;
  color: var(--vs-accent);
  margin-bottom: 4px;
}
.vs-acts-misc-name { color: var(--vs-text); font-weight: 700; font-size: 15px; }
.vs-acts-misc-desc { color: var(--vs-muted); font-size: 12.5px; }

/* Workbench: two-column "distribute spools into gear" board (Workbench.razor) */
.vs-bench {
  display: grid;
  grid-template-columns: 1fr 340px;
  gap: 20px;
  align-items: start;
}
.vs-bench-left { min-width: 0; }
.vs-bench-filters {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
  margin-bottom: 12px;
}
.vs-bench-search {
  flex: 1;
  min-width: 180px;
  padding: 8px 12px;
  font: inherit;
  font-size: 13px;
  color: var(--vs-text);
  background: var(--vs-surface);
  border: 1px solid var(--vs-hair-2);
  border-radius: 8px;
}
.vs-bench-select {
  padding: 8px 10px;
  font: inherit;
  font-size: 13px;
  color: var(--vs-text);
  background: var(--vs-surface);
  border: 1px solid var(--vs-hair-2);
  border-radius: 8px;
}
.vs-bench-toggle {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--vs-text-2);
  cursor: pointer;
}
.vs-bench-selbar {
  display: flex;
  align-items: center;
  gap: 12px;
  font-size: 12px;
  color: var(--vs-muted);
  margin-bottom: 10px;
}
.vs-bench-selcount { color: var(--vs-accent); font-weight: 600; }
.vs-bench-clear {
  background: none;
  border: none;
  color: var(--vs-info);
  cursor: pointer;
  font: inherit;
  font-size: 12px;
  text-decoration: underline;
}
.vs-bench-selall {
  background: none;
  border: 1px solid var(--vs-hair-2);
  border-radius: 6px;
  padding: 3px 10px;
  font: inherit;
  font-size: 12px;
  color: var(--vs-text-2);
  cursor: pointer;
}
.vs-bench-selall:hover:not(:disabled) { border-color: var(--vs-accent); color: var(--vs-text); }
.vs-bench-selall:disabled { opacity: .5; cursor: default; }
.vs-bench-cb {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  accent-color: var(--vs-accent);
  cursor: pointer;
}
.vs-bench-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 8px;
}
.vs-bench-tile {
  position: relative;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border: 1px solid var(--vs-hair-2);
  border-radius: 10px;
  background: var(--vs-surface);
  cursor: pointer;
  user-select: none;
  transition: border-color .12s, background .12s;
}
.vs-bench-tile:hover { border-color: var(--vs-hair); }
.vs-bench-tile.is-selected {
  border-color: var(--vs-accent);
  background: rgba(var(--vs-tint), 0.12);
}
.vs-bench-tile-text { flex: 1; min-width: 0; }
.vs-bench-tile-name {
  font-size: 13px;
  font-weight: 600;
  color: var(--vs-text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.vs-bench-tile-meta { font-size: 11px; color: var(--vs-muted); margin-top: 2px; }
.vs-bench-check {
  position: absolute;
  top: 6px;
  right: 8px;
  color: var(--vs-accent);
  font-weight: 700;
  font-size: 13px;
}

.vs-bench-right {
  position: sticky;
  top: 12px;
  /* Cap to the viewport and scroll within, so every drop target stays reachable
     however long the spool list on the left gets. */
  max-height: calc(100vh - 24px);
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.vs-bench-right-head {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--vs-faint);
}
.vs-gear-card {
  border: 1px solid var(--vs-hair-2);
  border-radius: 12px;
  background: var(--vs-surface);
  padding: 12px;
  transition: border-color .12s;
}
.vs-gear-card.is-armed { border-style: dashed; border-color: var(--vs-accent); }
.vs-gear-card.is-full { opacity: .85; }
.vs-gear-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 8px;
}
.vs-gear-name { font-size: 14px; font-weight: 700; color: var(--vs-text); }
.vs-gear-kind { font-size: 11px; color: var(--vs-muted); }
.vs-gear-cap {
  flex-shrink: 0;
  font-size: 12px;
  font-weight: 700;
  color: var(--vs-text-2);
  background: var(--vs-bg);
  border: 1px solid var(--vs-hair-2);
  border-radius: 20px;
  padding: 2px 9px;
}
.vs-gear-cap.is-full { color: var(--vs-warning); border-color: var(--vs-warning); }
.vs-gear-spools {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 10px 0;
}
.vs-gear-spool { position: relative; }
.vs-gear-spool-x {
  position: absolute;
  top: -4px;
  right: -4px;
  width: 16px;
  height: 16px;
  padding: 0;
  border-radius: 50%;
  background: var(--vs-bg-deep);
  color: var(--vs-faint);
  border: 1px solid var(--vs-hair-2);
  font-size: 11px;
  line-height: 1;
  cursor: pointer;
  display: none;
}
.vs-gear-spool:hover .vs-gear-spool-x { display: block; }
.vs-gear-empty {
  margin: 10px 0;
  padding: 12px;
  text-align: center;
  font-size: 12px;
  font-style: italic;
  color: var(--vs-faint);
  border: 1px dashed var(--vs-hair-2);
  border-radius: 8px;
}
.vs-gear-load {
  width: 100%;
  padding: 8px;
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  color: var(--vs-bg-deep);
  background: var(--vs-accent);
  border: none;
  border-radius: 8px;
  cursor: pointer;
}
.vs-gear-load:disabled { background: var(--vs-hair-2); color: var(--vs-faint); cursor: default; }
.vs-gear-emptybtn {
  width: 100%;
  margin-bottom: 8px;
  padding: 6px 8px;
  font: inherit;
  font-size: 12px;
  font-weight: 600;
  color: var(--vs-muted);
  background: transparent;
  border: 1px solid var(--vs-hair-2);
  border-radius: 8px;
  cursor: pointer;
}
.vs-gear-emptybtn:hover { color: var(--vs-text); border-color: var(--vs-faint); }

@media (max-width: 820px) {
  .vs-bench { grid-template-columns: 1fr; }
  .vs-bench-right { position: static; }
}

/* ===== Workbench "desk": the spools physically out right now ===== */
.vs-desk {
  margin-bottom: 18px;
  padding: 14px 16px 16px;
  border-radius: 16px;
  background: linear-gradient(180deg, rgba(var(--vs-dot), 0.05), transparent);
  border: 1px solid var(--vs-line);
  transition: border-color .12s, background .12s;
}
.vs-desk.is-armed { border-color: var(--vs-accent); background: rgba(var(--vs-dot), 0.08); }
.vs-desk-head { display: flex; align-items: center; gap: 12px; margin-bottom: 10px; }
.vs-desk-title {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: 14px; font-weight: 700; color: var(--vs-text);
}
.vs-desk-title .vs-icon { background: var(--vs-accent); }
.vs-desk-count { font-size: 12px; color: var(--vs-muted); }
.vs-desk-head .vs-desk-storeall { margin-left: auto; }
.vs-desk-storeall {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 12px; font: inherit; font-size: 12.5px; font-weight: 600;
  border-radius: 8px; cursor: pointer;
  background: var(--vs-accent); border: 1px solid var(--vs-accent); color: var(--vs-bg-deep);
}
.vs-desk-storeall:hover { filter: brightness(1.05); }
.vs-desk-storeall .vs-icon { background: var(--vs-bg-deep); }
/* When the store-all button is present it owns the right-push; clear sits after it. */
.vs-desk-head .vs-desk-storeall ~ .vs-bench-clear { margin-left: 0; }
.vs-desk-empty {
  padding: 18px; text-align: center; font-size: 13px; color: var(--vs-faint);
  border: 1px dashed var(--vs-hair-2); border-radius: 10px;
}
.vs-desk-tray {
  display: flex; flex-wrap: wrap; gap: 10px;
  max-height: 232px; overflow-y: auto;
  padding-right: 4px;
}
.vs-desk-spool {
  position: relative;
  display: flex; align-items: center; gap: 10px;
  padding: 8px 12px 8px 8px;
  border-radius: 12px;
  background: var(--vs-surface);
  border: 1px solid var(--vs-hair-2);
  min-width: 200px;
}
.vs-desk-spool.is-tbs { border-color: var(--vs-warn, #d99a2b); background: rgba(217, 154, 43, 0.08); }
.vs-desk-spool.is-sel { border-color: var(--vs-accent); }
.vs-desk-spool-text { flex: 1; min-width: 0; }
.vs-desk-spool-name {
  font-size: 13px; font-weight: 600; color: var(--vs-text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 150px;
}
.vs-desk-spool-note {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 11px; color: var(--vs-muted); margin-top: 2px;
}
.vs-desk-spool-note.is-tbs { color: var(--vs-warn, #d99a2b); font-weight: 600; }
.vs-desk-spool-note .vs-icon { background: currentColor; }
.vs-desk-act {
  padding: 4px 10px; font: inherit; font-size: 12px; font-weight: 600;
  border-radius: 7px; cursor: pointer;
  background: transparent; border: 1px solid var(--vs-hair-2); color: var(--vs-muted);
}
.vs-desk-act:hover { border-color: var(--vs-faint); color: var(--vs-text); }
.vs-desk-act.is-primary { background: var(--vs-accent); border-color: var(--vs-accent); color: var(--vs-bg-deep); }
.vs-desk-act.is-primary:hover { filter: brightness(1.05); color: var(--vs-bg-deep); }

/* Sort + direction toggle on the bench filters */
.vs-bench-sort { display: inline-flex; align-items: stretch; gap: 4px; }
.vs-bench-sortdir {
  width: 30px; padding: 0; font: inherit; font-size: 15px; line-height: 1;
  border: 1px solid var(--vs-hair-2); border-radius: 6px;
  background: var(--vs-surface); color: var(--vs-text-2); cursor: pointer;
}
.vs-bench-sortdir:hover { border-color: var(--vs-accent); color: var(--vs-text); }

/* Gear pane: search + collapsible Printers / Dryers groups */
.vs-gear-search { width: 100%; margin-bottom: 4px; }
.vs-gear-group { margin-bottom: 6px; }
.vs-gear-group-head {
  display: flex; align-items: center; gap: 7px; width: 100%;
  padding: 8px 6px; font: inherit; cursor: pointer;
  background: none; border: none; border-bottom: 1px solid var(--vs-line);
}
.vs-gear-group-caret { color: var(--vs-muted); font-size: 11px; width: 12px; }
.vs-gear-group-head .vs-icon { background: var(--vs-muted); }
.vs-gear-group-title {
  font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em;
  color: var(--vs-text-2);
}
.vs-gear-group-meta { margin-left: auto; font-size: 11px; color: var(--vs-faint); }
.vs-gear-group-empty { padding: 10px 6px; font-size: 12px; font-style: italic; color: var(--vs-faint); }
.vs-gear-group .vs-gear-card { margin-top: 10px; }
.vs-gear-parent {
  display: flex; align-items: center; gap: 5px; margin: 12px 0 2px;
  font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
  color: var(--vs-muted);
}
.vs-gear-parent .vs-icon { background: var(--vs-muted); }
.vs-gear-icon { background: var(--vs-accent); flex-shrink: 0; }

/* Two small return actions on an in-gear spool chip (home / to-desk) */
.vs-gear-spool-acts {
  position: absolute; top: -6px; right: -6px;
  display: none; gap: 2px;
}
.vs-gear-spool:hover .vs-gear-spool-acts { display: flex; }
.vs-gear-spool-act {
  width: 20px; height: 20px; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 50%; cursor: pointer;
  background: var(--vs-surface); border: 1px solid var(--vs-hair-2); color: var(--vs-muted);
  box-shadow: 0 1px 3px rgba(0,0,0,0.2);
}
.vs-gear-spool-act:hover { border-color: var(--vs-accent); color: var(--vs-accent); }
.vs-gear-spool-act .vs-icon { background: currentColor; }

/* Activities ▸ Workbench tab: a pointer to the standalone /workbench page */
.vs-wb-cta {
  display: flex; align-items: center; gap: 16px;
  padding: 20px 22px; border-radius: 16px; text-decoration: none;
  background: linear-gradient(120deg, rgba(var(--vs-dot), 0.08), transparent);
  border: 1px solid var(--vs-line); transition: border-color .12s, transform .12s;
}
.vs-wb-cta:hover { border-color: var(--vs-accent); transform: translateY(-2px); }
.vs-wb-cta-icon { width: 30px; height: 30px; background: var(--vs-accent); flex-shrink: 0; }
.vs-wb-cta-text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.vs-wb-cta-title { font-size: 16px; font-weight: 700; color: var(--vs-text); }
.vs-wb-cta-sub { font-size: 13px; color: var(--vs-muted); }
.vs-wb-cta-sub strong { color: var(--vs-warn, #d99a2b); }
.vs-wb-cta-go { font-size: 14px; font-weight: 700; color: var(--vs-accent); white-space: nowrap; }

/* Add Spool scope selector: 3 even segments that fill the dialog width, each
   showing its label above a filament count so the active search set is clear. */
.vs-scope-seg {
  display: flex;
  width: 100%;
}
.vs-scope-seg .vs-seg {
  flex: 1;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1px;
  font-size: 11.5px;
  line-height: 1.15;
  padding: 6px 4px;
  text-align: center;
}
.vs-seg-count {
  font-size: 12px;
  font-weight: 700;
  opacity: 0.6;
}
.vs-scope-seg .vs-seg.is-active .vs-seg-count {
  opacity: 0.9;
}

.vs-footer-brand {
  display: flex;
  align-items: center;
  gap: 10px;
  font-family: var(--vs-sans);
  font-size: 14px;
  font-weight: 700;
  color: rgba(175,192,215,0.70);
  letter-spacing: -0.01em;
}

.vs-footer-brand em {
  font-style: normal;
  color: var(--vs-accent);
  font-weight: 700;
}

.vs-footer-tagline {
  font-size: 11px;
  font-weight: 400;
  color: var(--vs-faint);
  letter-spacing: 0.02em;
  font-family: var(--vs-sans);
}

.vs-footer-links {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 12px 20px;
}

@media (max-width: 640px) {
  .vs-app-footer {
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding: 18px 16px;
    gap: 12px;
  }
}

.vs-footer-link {
  color: var(--vs-faint);
  text-decoration: none;
  font-size: 12px;
  letter-spacing: 0.03em;
  transition: color 0.15s;
}

.vs-footer-link:hover {
  color: var(--vs-muted);
}

/* Icon-only social links in the in-app footer (inherit the faint link color +
   hover via currentColor on the SVG fill). */
.vs-footer-social {
  display: inline-flex;
  align-items: center;
}
.vs-footer-social svg { display: block; }

/* ── Spools table ─────────────────────────────────────────── */

/* Alternate row shading — makes MudBlazor's Striped actually show in dark mode */
.mud-table-striped .mud-table-body .mud-table-row:nth-child(even) .mud-table-cell {
  background-color: rgba(100, 140, 200, 0.055);
}

/* Weight chips — scoped to override MudBlazor default pink */
.mud-chip.mud-chip-size-small {
  height: 22px;
  font-size: 12px;
}

/* Back to top */
.vs-back-to-top {
  position: fixed;
  bottom: 28px;
  right: 28px;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  border: 1px solid var(--vs-hair-2);
  background: var(--vs-surface);
  color: var(--vs-muted);
  box-shadow: var(--vs-shadow-sm);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  transform: translateY(10px);
  transition: opacity 0.22s, transform 0.22s, background 0.15s, color 0.15s, border-color 0.15s;
  z-index: 200;
  pointer-events: none;
  backdrop-filter: blur(8px);
}
.vs-back-to-top.is-visible {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}
.vs-back-to-top:hover {
  background: var(--vs-surface-2);
  color: var(--vs-accent);
  border-color: var(--vs-accent);
}

/* Table row hover — soft lift illusion via inset edge glow */
.mud-table-body .mud-table-row .mud-table-cell {
  transition: background-color 0.12s, box-shadow 0.12s;
}
.mud-table-body .mud-table-row:hover .mud-table-cell {
  background-color: rgba(65,125,200,0.07) !important;
  box-shadow: inset 0 1px 0 rgba(65,125,200,0.22), inset 0 -1px 0 rgba(65,125,200,0.10);
}

/* Pagination — more breathing room, softer presence */
.mud-table-pagination {
  border-top: 1px solid rgba(255,255,255,0.04);
  padding: 6px 4px 2px;
  opacity: 0.72;
  transition: opacity 0.2s;
}
.mud-table-pagination:hover {
  opacity: 1;
}
.mud-table-pagination .mud-icon-button {
  opacity: 0.60;
}
.mud-table-pagination .mud-icon-button:hover:not([disabled]) {
  opacity: 1;
}
.mud-table-pagination .mud-icon-button[disabled] {
  opacity: 0.18;
}

/* Table header — dimmed so filament rows own the focus */
.mud-table-head .mud-table-row {
  opacity: 0.62;
}

/* Row dividers — barely-there; spacing + hover carry the separation */
.mud-table-body .mud-table-cell {
  border-bottom-color: rgba(255,255,255,0.032) !important;
}

/* Three-dot / action buttons — invisible at rest, surface on row hover */
.mud-table-body .mud-table-row .mud-icon-button {
  opacity: 0.12;
  transition: opacity 0.18s;
}
.mud-table-body .mud-table-row:hover .mud-icon-button {
  opacity: 0.72;
}

.vs-footer-copy {
  font-size: 12px;
  color: var(--vs-muted);
  letter-spacing: 0.04em;
}

/* Table pagers: inset the controls from the divider above */
.mud-table-pagination .mud-toolbar,
.mud-table-pagination-toolbar {
  padding-top: 8px;
  padding-bottom: 8px;
}

/* Spool Detail history: roomier rows + event pills */
.vs-sd-history .mud-table-root {
  margin-top: 4px;
}
.vs-sd-history .mud-table-cell {
  padding: 14px 18px !important;
}
.vs-sd-history .mud-table-cell:first-child {
  padding-left: 6px !important;
}
.vs-sd-history .mud-table-cell:last-child {
  padding-right: 6px !important;
}
.vs-sd-history .mud-chip {
  height: 28px;
  padding: 0 14px;
  margin: 0;
}
.vs-sd-history .mud-chip .mud-chip-icon {
  margin-right: 5px;
}

/* ── Reconnect modal (global — must not be scoped) ───────────────────────────
   blazor.web.js controls this element's classes and open attribute directly;
   scoped CSS attributes are not present on externally-managed elements. */

.components-reconnect-first-attempt-visible,
.components-reconnect-repeated-attempt-visible,
.components-reconnect-failed-visible,
.components-pause-visible,
.components-resume-failed-visible,
.components-rejoining-animation {
  display: none;
}

#components-reconnect-modal.components-reconnect-show .components-reconnect-first-attempt-visible,
#components-reconnect-modal.components-reconnect-show .components-rejoining-animation,
#components-reconnect-modal.components-reconnect-paused .components-pause-visible,
#components-reconnect-modal.components-reconnect-resume-failed .components-resume-failed-visible,
#components-reconnect-modal.components-reconnect-retrying .components-reconnect-repeated-attempt-visible,
#components-reconnect-modal.components-reconnect-retrying .components-rejoining-animation {
  display: block;
}

#components-reconnect-modal.components-reconnect-failed,
#components-reconnect-modal.components-reconnect-failed .components-reconnect-failed-visible {
  display: block;
}

#components-reconnect-modal {
  background: var(--vs-surface);
  border: 1px solid var(--vs-hair-2);
  border-radius: 14px;
  width: 17rem;
  margin: 22vh auto;
  padding: 2rem 1.75rem;
  box-shadow:
    0 0 0 1px rgba(var(--vs-tint), 0.08),
    0 24px 48px rgba(0, 0, 0, 0.60),
    0 4px 12px rgba(0, 0, 0, 0.35);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  color: var(--vs-text-2);
  font-family: "Manrope", system-ui, sans-serif;
  font-size: 13px;
}

#components-reconnect-modal[open] {
  animation:
    vs-reconnect-slideUp 0.5s cubic-bezier(0.2, 1, 0.3, 1) both,
    vs-reconnect-fadeIn 0.35s ease-out both;
}

/* Blazor adds the state class (components-reconnect-show) a tick after
   showModal() fires. Show spinner + message immediately on [open] so
   the dialog is never blank during that gap. */
#components-reconnect-modal[open] .components-rejoining-animation,
#components-reconnect-modal[open] .components-reconnect-first-attempt-visible {
  display: block;
}

#components-reconnect-modal::backdrop {
  background: rgba(0, 0, 0, 0.55);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
  animation: vs-reconnect-fadeIn 0.35s ease-out;
}

#components-reconnect-modal .components-reconnect-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
}

#components-reconnect-modal p {
  margin: 0;
  text-align: center;
  color: #7f8ca3;
  line-height: 1.55;
  font-size: 13px;
  letter-spacing: 0.01em;
}

#components-reconnect-modal button {
  border: 1px solid rgba(var(--vs-tint), 0.25);
  background: rgba(var(--vs-tint), 0.10);
  color: #7898bf;
  padding: 6px 22px;
  border-radius: 20px;
  font-family: inherit;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.04em;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s;
}

#components-reconnect-modal button:hover {
  background: rgba(var(--vs-tint), 0.18);
  border-color: rgba(var(--vs-tint), 0.40);
}

.vs-reconnect-logo {
  animation: vs-reconnect-spin 3.5s linear infinite;
  opacity: 0.9;
  filter: drop-shadow(0 0 8px rgba(var(--vs-tint), 0.35));
}

@keyframes vs-reconnect-spin {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}

@keyframes vs-reconnect-slideUp {
  from { transform: translateY(18px) scale(0.97); }
  to   { transform: translateY(0) scale(1); }
}

@keyframes vs-reconnect-fadeIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* Logo spin on hover */
@keyframes vs-logo-spin {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}
.vs-logo {
  display: block;
  transform-origin: center;
}
.vs-masthead-brand:hover .vs-logo {
  animation: vs-logo-spin 3.5s linear 1;
}

/* Custom Filament dialog. Desktop: centered modal with max-width.
   Mobile: nearly full-width, anchored near the top so the on-screen
   keyboard doesn't push the dialog off-screen. */
.vs-custom-filament-dialog {
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 92%;
  max-width: 640px;
  max-height: 90vh;
  max-height: 90dvh;
}
@media (max-width: 599.95px) {
  .vs-custom-filament-dialog {
    top: 8px;
    left: 8px;
    right: 8px;
    transform: none;
    width: auto;
    max-width: none;
    max-height: calc(100vh - 16px);
    max-height: calc(100dvh - 16px);
  }
}

/* MudSelect popovers inside the Custom Filament dialog. Mud portals the
   panel into <body>, so without an explicit width constraint the panel
   can overflow the viewport on phones. We cap width and force a solid
   background + high z-index so the popover doesn't visually merge with
   the dialog (which was making it look transparent / broken). */
.vs-custom-filament-popover.mud-popover {
  /* Size to content so short lists (Diameter: 1.75/2.85) get a narrow
     popover, while longer lists (Brand, Material) grow up to 280px. */
  width: max-content !important;
  min-width: 140px !important;
  max-width: min(280px, calc(100vw - 24px)) !important;
  max-height: 60vh;
  background: var(--vs-surface) !important;
  border: 1px solid var(--vs-hair-2) !important;
  box-shadow: 0 8px 24px rgba(0,0,0,0.55) !important;
  z-index: 1400 !important;
}
.vs-custom-filament-popover.mud-popover .mud-list-item {
  background: transparent;
}

/* Admin "Add/Edit Filament" dialog: a disabled input (e.g. Series, greyed until
   Brand + Material are chosen) must still be legible. MudBlazor's default disabled
   label/text color nearly vanishes on light + medium surfaces, so the field looked
   empty. Restore a muted-but-readable contrast across all themes. */
.vs-filament-dialog .mud-input-control.mud-disabled .mud-input-label {
  color: var(--vs-muted) !important;
}
.vs-filament-dialog .mud-input-control.mud-disabled .mud-input-slot,
.vs-filament-dialog .mud-input-control.mud-disabled .mud-select-input,
.vs-filament-dialog .mud-input-control.mud-disabled input {
  color: var(--vs-text-2) !important;
}
/* Checkbox label font sits on .mud-typography, not the control root, so the inline
   font-size:0.78rem on Refill/Discontinued doesn't shrink the label by itself. */
.vs-filament-dialog .mud-checkbox .mud-typography { font-size: 0.78rem; }

/* Edit Filament dialog: trim oversized form text, and make the inherited helper
   notes ("Series default - 200 g") fainter + smaller so they don't compete with
   the field labels. */
.vs-filament-dialog .mud-input-slot,
.vs-filament-dialog .mud-select-input,
.vs-filament-dialog input,
.vs-filament-dialog textarea { font-size: 0.85rem; }
.vs-filament-dialog .mud-input-label { font-size: 0.8rem; }
.vs-filament-dialog .mud-input-helper-text {
  color: var(--vs-faint) !important;
  font-size: 0.68rem;
}
/* Link fields hold long URLs — shrink their text so they fit without dominating. */
.vs-link-field input { font-size: 0.72rem !important; }

/* Admin Filaments filter row: the Series filter is disabled until a Brand +
   Material are picked, and on light/medium themes its label + "Choose Brand &
   Material first" text nearly vanishes. Disabled inputs are greyed via
   -webkit-text-fill-color + reduced opacity (which a plain `color` can't beat),
   so override BOTH, on the .mud-input element too (that's where .mud-disabled
   actually lands), and force full opacity. */
.vs-filter-row .mud-disabled,
.vs-filter-row .mud-input.mud-disabled,
.vs-filter-row .mud-input-control.mud-disabled { opacity: 1 !important; }

/* The label sits in .mud-input-control as a SIBLING of the disabled .mud-input,
   so reach it via :has rather than as a descendant of .mud-disabled. */
.vs-filter-row .mud-input-control:has(.mud-disabled) .mud-input-label,
.vs-filter-row .mud-disabled .mud-input-label,
.vs-filter-row .mud-input-control.mud-disabled .mud-input-label {
  color: var(--vs-muted) !important;
  opacity: 1 !important;
}

.vs-filter-row .mud-disabled .mud-select-input,
.vs-filter-row .mud-disabled .mud-input-slot,
.vs-filter-row .mud-disabled input,
.vs-filter-row .mud-input.mud-disabled .mud-select-input,
.vs-filter-row .mud-input.mud-disabled .mud-input-slot,
.vs-filter-row .mud-input.mud-disabled input,
.vs-filter-row .mud-select-input[disabled],
.vs-filter-row input:disabled {
  color: var(--vs-text-2) !important;
  -webkit-text-fill-color: var(--vs-text-2) !important;
  opacity: 1 !important;
}

/* The dropdown arrow (chevron) on the disabled Series filter, faint on light/
   medium themes. Force a readable colour + full opacity. */
.vs-filter-row .mud-input-control:has(.mud-disabled) svg,
.vs-filter-row .mud-input-control:has(.mud-disabled) .mud-icon-root,
.vs-filter-row .mud-disabled svg,
.vs-filter-row .mud-disabled .mud-icon-root {
  color: var(--vs-muted) !important;
  fill: currentColor !important;
  opacity: 1 !important;
}

/* Same again for the Edit Series modal: the calculated (read-only) Length field
   is a disabled MudTextField, so its label + value vanish on light/medium themes.
   Keep them muted-but-readable (still clearly not-editable). */
.vs-series-editor .mud-input-control.mud-disabled .mud-input-label {
  color: var(--vs-muted) !important;
}
.vs-series-editor .mud-input-control.mud-disabled .mud-input-slot,
.vs-series-editor .mud-input-control.mud-disabled .mud-select-input,
.vs-series-editor .mud-input-control.mud-disabled input {
  color: var(--vs-text-2) !important;
}

/* Calculated, read-only Length field (Series editor). ReadOnly avoids the
   disabled input's unreadable -webkit-text-fill-color; this keeps it muted but
   legible on every theme. */
.vs-calc-field input {
  color: var(--vs-muted) !important;
  -webkit-text-fill-color: var(--vs-muted) !important;
}

/* "Hardened nozzle" trait pill in the public filament table. */
.vs-hardnozzle-tag {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.02em;
  padding: 1px 7px;
  border-radius: 999px;
  white-space: nowrap;
  color: var(--vs-warning);
  border: 1px solid color-mix(in srgb, var(--vs-warning) 45%, transparent);
  background: color-mix(in srgb, var(--vs-warning) 12%, transparent);
}

/* Smaller, denser type on admin data tables. Use a direct class (.vs-admin-table)
   with !important: MudBlazor's own cell rule out-specifies a body:has(...) selector,
   which is why earlier attempts didn't shrink anything. body:has stays as a
   fallback for admin tables that don't carry the class. */
.vs-admin-table .mud-table-cell,
body:has(.vs-admin-nav) .mud-table-cell {
  font-size: 0.75rem !important;
  padding-top: 4px !important;
  padding-bottom: 4px !important;
}
.vs-admin-table .mud-table-head .mud-table-cell,
body:has(.vs-admin-nav) .mud-table-head .mud-table-cell {
  font-size: 0.68rem !important;
}
.vs-admin-table .mud-table-cell .vs-spec-tag,
body:has(.vs-admin-nav) .mud-table-cell .vs-spec-tag {
  font-size: 0.6rem !important;
}

/* Smaller text on the admin filter-row dropdowns/inputs (value + label). */
.vs-filter-row .mud-input-slot,
.vs-filter-row .mud-select-input,
.vs-filter-row input { font-size: 0.78rem !important; }
/* Field labels (Brand/Material/…) were a touch too small — nudge back up. */
.vs-filter-row .mud-input-label { font-size: 0.84rem !important; }
/* Open dropdown option list (3DXTech, AMOLEN…) was oversized — bring it down. */
.vs-filter-popover .mud-list-item { font-size: 0.82rem; min-height: 36px; }

/* Edit Material modal: compact input labels + the base-range min/max grid. */
.vs-material-editor .mud-input-label { font-size: 0.78rem; }
.vs-matrange-grid {
  display: grid;
  grid-template-columns: auto 64px 64px;
  gap: 3px 8px;
  align-items: center;
}
.vs-matrange-h { font-size: 11px; color: var(--vs-muted); text-align: center; }

/* Printing requirements: compact Min/Max table on the left, single-value
   settings + flags filling the column to its right. Wraps on narrow screens. */
.vs-matreq-split {
  display: flex;
  gap: 18px 24px;
  align-items: flex-start;
  flex-wrap: wrap;
}
.vs-matreq-split .vs-matrange-grid { flex: 0 0 auto; }
.vs-matreq-side { flex: 1 1 300px; min-width: 280px; }

/* Admin hub tiles. Used on /admin to surface moderator tools. */
.vs-admin-tile {
  display: block;
  padding: 18px 18px 16px;
  background: var(--vs-surface);
  border: 1px solid var(--vs-hair);
  border-radius: 10px;
  text-decoration: none;
  color: inherit;
  transition: border-color 0.18s, transform 0.12s;
}
.vs-admin-tile:hover {
  border-color: var(--vs-accent);
  transform: translateY(-1px);
}
.vs-admin-tile-title {
  font-size: 15px;
  font-weight: 600;
  color: var(--vs-text);
  flex: 1;
}
.vs-admin-tile-desc {
  font-size: 13px;
  color: var(--vs-faint);
  line-height: 1.5;
}
.vs-admin-tile-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 24px;
  height: 22px;
  padding: 0 8px;
  background: var(--vs-accent);
  color: #0e1018;
  border-radius: 11px;
  font-size: 12px;
  font-weight: 700;
}
.vs-admin-tile-badge--quiet {
  background: rgba(120,152,191,0.18);
  color: var(--vs-accent);
}

/* ── Admin Studio Calendar (holidays + milestone badges) ── */
.vs-cal-row {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  background: var(--vs-surface);
  border: 1px solid var(--vs-hair-2);
  border-radius: 14px;
  padding: 12px 14px;
}
.vs-cal-emoji {
  font-size: 22px;
  line-height: 1;
  flex: 0 0 auto;
  width: 30px;
  text-align: center;
}
.vs-cal-enable {
  align-self: center;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--vs-muted);
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
}
.vs-cal-enable input { cursor: pointer; accent-color: var(--vs-accent); }
.vs-cal-tag {
  align-self: center;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--vs-muted);
  border: 1px solid var(--vs-hair-2);
  border-radius: 20px;
  padding: 1px 8px;
}
.vs-cal-edit {
  background: var(--vs-surface);
  border: 1px solid var(--vs-accent);
  border-radius: 14px;
  padding: 16px;
}
.vs-cal-field {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.vs-cal-field > span {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--vs-faint);
}
.vs-cal-input {
  width: 100%;
  box-sizing: border-box;
  background: var(--vs-bg);
  border: 1px solid var(--vs-hair-2);
  border-radius: 8px;
  padding: 7px 9px;
  font-size: 13px;
  font-family: inherit;
  color: var(--vs-text);
}
.vs-cal-input:focus {
  outline: none;
  border-color: var(--vs-accent);
}
.vs-btn-mini {
  background: none;
  border: 1px solid var(--vs-hair-2);
  border-radius: 7px;
  padding: 5px 12px;
  cursor: pointer;
  font-family: inherit;
  font-size: 12px;
  font-weight: 600;
  color: var(--vs-text-2);
  transition: border-color 0.15s, color 0.15s;
}
.vs-btn-mini:hover:not(:disabled) { border-color: var(--vs-accent); color: var(--vs-text); }
.vs-btn-mini:disabled { opacity: 0.4; cursor: default; }
.vs-btn-mini--primary {
  background: var(--vs-accent);
  border-color: var(--vs-accent);
  /* on-accent text adapts per theme (dark accent -> light ink, and vice versa);
     a hardcoded near-black read dark-on-dark on light themes like Sage. */
  color: var(--vs-bg-deep);
}
.vs-btn-mini--primary:hover:not(:disabled) { color: var(--vs-bg-deep); opacity: 0.9; }
.vs-btn-mini--danger { color: var(--vs-danger); border-color: var(--vs-danger); }
.vs-btn-mini--danger:hover:not(:disabled) { color: #fff; background: var(--vs-danger); }

/* Avatar uploader: a styled wrapper that hides the native file input. */
.vs-avatar-upload {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 14px;
  background: var(--vs-accent);
  color: var(--vs-bg-deep);
  border-radius: 8px;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  transition: opacity 0.15s;
}
.vs-avatar-upload:hover { opacity: 0.9; }
.vs-avatar-upload.is-busy { opacity: 0.6; cursor: default; }
.vs-avatar-upload input[type="file"] {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  overflow: hidden;
  pointer-events: none;
}

/* Month-grid calendar view of the holidays. */
.vs-cal-cal { max-width: 760px; }
.vs-cal-monthbar {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 14px;
}
.vs-cal-monthbar h3 {
  font-size: 16px;
  font-weight: 600;
  color: var(--vs-text);
  margin: 0;
  min-width: 170px;
  text-align: center;
}
.vs-cal-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 6px;
}
.vs-cal-dow {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--vs-faint);
  text-align: center;
  padding-bottom: 2px;
}
.vs-cal-cell {
  min-height: 76px;
  border: 1px solid var(--vs-hair-2);
  border-radius: 10px;
  padding: 5px 6px;
  background: var(--vs-surface);
  display: flex;
  flex-direction: column;
  gap: 3px;
  overflow: hidden;
}
.vs-cal-cell.is-empty { background: transparent; border: none; }
.vs-cal-cell.is-today { border-color: var(--vs-accent); box-shadow: inset 0 0 0 1px var(--vs-accent); }
.vs-cal-daynum { font-size: 12px; font-weight: 600; color: var(--vs-muted); }
.vs-cal-cell.is-today .vs-cal-daynum { color: var(--vs-accent); }
.vs-cal-ev {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 11px;
  line-height: 1.2;
  color: var(--vs-text-2);
  background: var(--vs-bg);
  border-left: 3px solid var(--vs-accent);
  border-radius: 5px;
  padding: 2px 4px;
}
.vs-cal-ev-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
@media (max-width: 560px) {
  .vs-cal-cell { min-height: 56px; }
  .vs-cal-ev-name { display: none; }
}

/* Public filament table pager buttons. */
.vs-pf-pager {
  background: var(--vs-bg);
  border: 1px solid var(--vs-hair-2);
  border-radius: 8px;
  padding: 6px 14px;
  color: var(--vs-text-2);
  font-size: 13px;
  cursor: pointer;
  transition: border-color 0.14s, color 0.14s;
}
.vs-pf-pager:hover:not(:disabled) {
  border-color: var(--vs-accent);
  color: var(--vs-text);
}
.vs-pf-pager:disabled {
  opacity: 0.4;
  cursor: default;
}

/* Darker grouped section at the bottom of every admin editor: descriptions,
   internal notes, and the danger zone live here, set apart from the main fields. */
.vs-editor-meta {
  margin-top: 18px;
  padding: 16px 18px;
  border: 1px solid var(--vs-hair-2);
  border-radius: 8px;
  background: var(--vs-bg-tint);
}

/* Centered popout panel for the admin editors (paired with a MudOverlay), so
   editing happens in a modal instead of an inline form on the table page. */
.vs-modal-panel {
  position: fixed;
  top: 64px;
  left: 50%;
  transform: translateX(-50%);
  width: 92%;
  max-height: calc(100vh - 84px);
  overflow-y: auto;
  /* Above the sticky topbar (z-index:20) so the panel + its overlay aren't
     clipped behind the nav. Stays well below MudBlazor popovers (~1200) so the
     in-panel autocomplete dropdowns still float on top. */
  z-index: 31;
  padding: 24px;
}

/* "Edit Series Specs" dialog (admin Filaments page): smaller, denser text so the
   whole spec form fits without clipping at the top. Shrinks every field's label
   (incl. the long "Speed Min/Max (mm/s)" ones) and value text. */
.vs-variant-specs-dialog .mud-input-control { font-size: 0.82rem; margin-top: 2px; margin-bottom: 2px; }
.vs-variant-specs-dialog .mud-input-slot input,
.vs-variant-specs-dialog .mud-select-input { font-size: 0.82rem; }
.vs-variant-specs-dialog .mud-input-label { font-size: 0.76rem !important; }
.vs-variant-specs-dialog .mud-input-helper-text { font-size: 0.62rem; line-height: 1.25; }
.vs-variant-specs-dialog .mud-checkbox .mud-typography { font-size: 0.78rem; }

/* Admin Add/Edit Series modal: smaller input + checkbox labels, matching the
   Edit Series Specs dialog. (The checkboxes' inline font-size sits on the root,
   not the label, so the label is shrunk here via .mud-typography.) */
.vs-series-editor .mud-input-label { font-size: 0.76rem !important; }
.vs-series-editor .mud-checkbox .mud-typography { font-size: 0.74rem; }

/* Unified admin table-page header: title left, counts + Add button far right. */
.vs-admin-table-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  margin-bottom: 20px;
}
.vs-admin-table-head-right {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
}
.vs-admin-count {
  font-size: 13px;
  color: var(--vs-faint);
  white-space: nowrap;
}

/* Consistent admin sub-nav (AdminNav.razor) — one click between admin sections. */
.vs-admin-nav {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-bottom: 22px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--vs-hair);
}
.vs-admin-nav-link {
  font-size: 13px;
  font-weight: 500;
  color: var(--vs-text-2);
  text-decoration: none;
  padding: 6px 12px;
  border-radius: 7px;
  transition: background 0.14s, color 0.14s;
}
.vs-admin-nav-link:hover {
  background: rgba(120,152,191,0.1);
  color: var(--vs-text);
}
.vs-admin-nav-link.is-active {
  background: var(--vs-accent);
  /* On-accent text: dark on dark-theme (light) accents, light on light-theme
     (dark) accents — so the active tab stays readable on every theme. */
  color: var(--vs-bg-deep);
  font-weight: 600;
}
.vs-admin-nav-sep {
  align-self: stretch;
  width: 1px;
  background: var(--vs-hair-2, rgba(255, 255, 255, 0.1));
  margin: 4px 8px;
  flex-shrink: 0;
}

/* Catalog dropdown in the admin nav — collapses the seven catalog sections into one
   hover/focus menu so the bar stays short. */
.vs-admin-nav-dd { position: relative; display: inline-flex; }
.vs-admin-nav-ddbtn { cursor: pointer; user-select: none; }
.vs-admin-nav-menu {
  display: none; position: absolute; top: 100%; left: 0; z-index: 60;
  margin-top: 4px; padding: 6px; min-width: 168px;
  background: var(--vs-surface); border: 1px solid var(--vs-hair-2); border-radius: 10px;
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.22);
}
.vs-admin-nav-dd:hover .vs-admin-nav-menu,
.vs-admin-nav-dd:focus-within .vs-admin-nav-menu { display: block; }
.vs-admin-nav-menu a {
  display: block; padding: 6px 11px; border-radius: 7px; white-space: nowrap;
  font-size: 13px; color: var(--vs-text-2); text-decoration: none;
}
.vs-admin-nav-menu a:hover { background: var(--vs-bg-tint); color: var(--vs-text); }
.vs-admin-nav-menu a.is-active { color: var(--vs-accent); font-weight: 600; }

/* Spool action menu — floating popup positioned at click coordinates.
   Anchored absolute to the viewport via fixed positioning so it survives
   scroll. Includes a transparent backdrop that swallows the next click
   to dismiss the menu. */
.vs-spool-action-menu-overlay {
  position: fixed;
  inset: 0;
  z-index: 1300;
  background: transparent;
}
.vs-spool-action-menu {
  position: fixed;
  z-index: 1301;
  /* --vs-menu-x and --vs-menu-y are the viewport-space click coordinates.
     Default behavior: popup opens to the LEFT of the click (right edge of
     popup ≈ click x). Then clamp into the viewport: never let the left
     edge go below 8px, and never let the right edge exceed (100vw - 8px). */
  --vs-menu-w: 240px;
  --vs-menu-h: 400px;
  /* Desired left = click_x - popup_width, clamped to [8px, 100vw - popup_w - 8px] */
  left: max(8px,
            min(calc(var(--vs-menu-x, 0px) - var(--vs-menu-w)),
                calc(100vw - var(--vs-menu-w) - 8px)));
  /* Anchor TOP of menu to click Y, growing downward. Clamp so the menu
     never starts above 8px from the top, and never overflows the bottom
     edge (push it up by its own height when the click is low on the page).
     Opening downward keeps the menu attached to the click for clicks high
     on the page (common on Shelves), instead of slamming to the top. */
  top:  clamp(8px, var(--vs-menu-y, 0px), calc(100vh - var(--vs-menu-h) - 8px));
  width: var(--vs-menu-w);
  min-width: 220px;
  max-width: 280px;
  background: var(--vs-surface);
  border: 1px solid var(--vs-hair-2);
  border-radius: 8px;
  box-shadow: 0 8px 28px rgba(0,0,0,0.55);
  padding: 4px 0;
  max-height: var(--vs-menu-h);
  overflow-y: auto;
  font-size: 14px;
}
.vs-spool-action-item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 9px 14px;
  background: none;
  border: none;
  color: var(--vs-text);
  text-align: left;
  font-size: 14px;
  cursor: pointer;
  transition: background 0.1s;
}
.vs-spool-action-item:hover,
.vs-spool-action-item:focus-visible {
  background: rgba(126,184,247,0.10);
  outline: none;
}
.vs-spool-action-item.vs-spool-action-danger {
  color: #e88080;
}
.vs-spool-action-item.vs-spool-action-danger:hover {
  background: rgba(232,128,128,0.10);
}
.vs-spool-action-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  flex-shrink: 0;
  color: var(--vs-muted);
}
.vs-spool-action-label-group {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}
.vs-spool-action-label {
  text-align: left;
  width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.vs-spool-action-sub {
  font-size: 10px;
  color: var(--vs-faint);
  font-weight: 400;
  width: 100%;
  white-space: nowrap;
}
.vs-spool-action-danger .vs-spool-action-sub {
  color: #a06060;
}
.vs-spool-action-danger .vs-spool-action-icon {
  color: #e88080;
}
.vs-spool-action-chev {
  color: var(--vs-faint);
  margin-left: 4px;
}
.vs-spool-action-sep {
  height: 1px;
  background: var(--vs-hair-2);
  margin: 4px 0;
}
.vs-spool-action-header {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  font-size: 12px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--vs-muted);
  border-bottom: 1px solid var(--vs-hair-2);
  margin-bottom: 4px;
}
.vs-spool-action-back {
  background: none;
  border: none;
  color: var(--vs-text-2);
  font-size: 18px;
  line-height: 1;
  padding: 2px 6px;
  border-radius: 4px;
  cursor: pointer;
}
.vs-spool-action-back:hover {
  background: rgba(126,184,247,0.10);
}
.vs-spool-action-group {
  padding: 10px 14px 4px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--vs-accent);
}
.vs-spool-action-subgroup {
  padding: 4px 14px 2px;
  font-size: 11px;
  font-weight: 600;
  color: var(--vs-muted);
}
.vs-spool-action-shelf {
  padding-left: 24px;
}
.vs-spool-action-shelf-dot {
  display: inline-block;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--vs-faint);
  flex-shrink: 0;
}
.vs-spool-action-shelf.is-current .vs-spool-action-shelf-dot {
  width: 7px;
  height: 7px;
  background: #c77dff;
  box-shadow: 0 0 6px 1px rgba(199,125,255,0.85);
}
.vs-spool-action-shelf.is-current {
  color: #e6d2ff;
}
/* A single-compartment unit (a "bin") collapses to one selectable row; align
   it at the unit level rather than the deeper shelf indent. */
.vs-spool-action-shelf.is-binrow {
  padding-left: 14px;
}
/* Inline marker that reads with the name ("Shelf 1 (current)") instead of a
   far-right pill — tiny pills on the edge get missed when scanning. */
.vs-spool-action-current {
  color: #c77dff;
  font-size: 12px;
  font-weight: 500;
  margin-left: 5px;
}

/* Live slot count on a gear row in the "Move to" menu ("2/4"), pinned right. */
.vs-spool-action-cap {
  margin-left: auto;
  padding-left: 8px;
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  color: #8aa3c4;
  flex-shrink: 0;
}
/* A full unit reads dim + struck, and the row can't be clicked. */
.vs-spool-action-item.is-full {
  opacity: 0.5;
  cursor: not-allowed;
}
.vs-spool-action-item.is-full .vs-spool-action-cap {
  color: var(--vs-danger, #e5484d);
}
/* The chevron on a multi-material row sits after the count, not pushed to edge. */
.vs-spool-action-cap + .vs-spool-action-chev {
  margin-left: 6px;
}

/* Per-spool wrapper used on Shelves and Dashboard. Holds the SpoolSideView
   and a three-dot trigger that fades in on hover/focus. The wrapper has
   no layout impact (display:contents would break drag-and-drop, so we use
   relative position instead with the trigger absolutely placed). */
.vs-spool-wrap {
  position: relative;
  display: inline-block;
}
.vs-spool-wrap-trigger {
  position: absolute;
  top: 2px;
  right: 2px;
  width: 20px;
  height: 20px;
  padding: 0;
  background: rgba(10,12,20,0.72);
  border: 1px solid var(--vs-hair-2);
  border-radius: 4px;
  color: var(--vs-text-2);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.15s, background 0.15s, color 0.15s;
  z-index: 2;
}
.vs-spool-wrap:hover .vs-spool-wrap-trigger,
.vs-spool-wrap:focus-within .vs-spool-wrap-trigger,
.vs-spool-wrap-trigger:focus-visible {
  opacity: 1;
}
.vs-spool-wrap-trigger:hover {
  color: var(--vs-info);
  background: rgba(10,12,20,0.92);
}
/* On touch devices, the trigger is always visible since there's no hover. */
@media (hover: none) {
  .vs-spool-wrap-trigger { opacity: 0.85; }
}

/* Ghost spool: belongs on this shelf but is currently out in gear (printing/drying).
   Rendered in its saved slot — the spool art faded behind a dashed outline, with a
   crisp status badge on top — so the shelf reads as "what lives here, and what's away".
   Only the figure is faded (parent opacity would dim the badge too), so the badge and
   the action trigger stay legible. */
.vs-spool-ghost {
  border: 1.5px dashed var(--vs-hair-2);
  border-radius: 9px;
}
.vs-spool-ghost-fig { display: block; }
/* Fade the spool ART only — its hover tooltip is a ::before pseudo of the inner
   .vs-shelf-spool, so dimming the wrapper would dim the tooltip too. Dimming the
   real children (not the pseudo) keeps the tooltip crisp and readable. */
.vs-spool-ghost-fig .vs-shelf-spool > * {
  opacity: 0.38;
  filter: grayscale(0.22);
}
.vs-spool-ghost:hover .vs-spool-ghost-fig .vs-shelf-spool > * {
  opacity: 0.55;
}
.vs-spool-ghost-badge {
  position: absolute;
  top: 3px;
  left: 50%;
  transform: translateX(-50%);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--vs-surface);
  border: 1px solid var(--vs-hair-2);
  color: var(--vs-accent);
  z-index: 2;
}

/* Three-dot trigger button — used inline in tables/cards. Subtle by default,
   visible enough to be discoverable, transitions to accent on hover. */
.vs-spool-action-trigger {
  background: none;
  border: 1px solid transparent;
  color: var(--vs-faint);
  border-radius: 6px;
  padding: 4px 6px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: color 0.15s, background 0.15s, border-color 0.15s;
}
.vs-spool-action-trigger:hover,
.vs-spool-action-trigger:focus-visible {
  color: var(--vs-info);
  background: rgba(126,184,247,0.08);
  border-color: var(--vs-hair-2);
  outline: none;
}

/* Settings page MudTabs: add breathing room between the tab strip
   (Brands/Tracked/Library/Storage/Custom/Account) and the content panel
   below it. MudTabs renders the panel content flush against the slider
   bar by default, which made the brand chips on the Brands tab feel
   cramped against the tab heading. */
.vs-settings-tabs .mud-tabs-panels {
  padding-top: 24px;
}

/* Settings dashboard: left vertical sidebar + content pane. Replaces the
   horizontally-scrolling MudTabs. On mobile the sidebar collapses to a
   wrapping row of pills above the content. */
.vs-settings-shell {
  display: flex;
  gap: 28px;
  align-items: flex-start;
}
.vs-settings-sidebar {
  flex: 0 0 208px;
  position: sticky;
  top: 16px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.vs-settings-content {
  flex: 1 1 auto;
  min-width: 0;
}
.vs-settings-navgroup-label {
  font-size: 10px;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: #505070;
  font-weight: 700;
  padding: 0 10px;
  margin: 18px 0 6px;
}
.vs-settings-navgroup-label:first-child {
  margin-top: 0;
}
.vs-settings-navitem {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 9px 12px;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 8px;
  color: var(--vs-muted);
  font-size: 14px;
  font-weight: 500;
  text-align: left;
  cursor: pointer;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
}
.vs-settings-navitem:hover {
  background: rgba(120,152,191,0.08);
  color: var(--vs-text-2);
}
.vs-settings-navitem.is-active {
  background: rgba(120,152,191,0.16);
  border-color: var(--vs-accent);
  color: var(--vs-info);
  font-weight: 600;
}
.vs-settings-navitem-icon {
  width: 22px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

/* Studio Features panel: tidy on/off list of optional capabilities. */
.vs-feat-panel {
  max-width: 560px;
}
.vs-feat-tier {
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #505070;
  font-weight: 700;
  margin: 22px 0 4px;
}
.vs-feat-row {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  padding: 13px 2px;
  border-bottom: 1px solid var(--vs-hair-2);
}
.vs-feat-row:last-child {
  border-bottom: none;
}
.vs-feat-row.is-soon {
  opacity: 0.6;
}
.vs-feat-icon {
  flex-shrink: 0;
  width: 38px;
  height: 38px;
  border-radius: 9px;
  display: flex;
  align-items: center;
  justify-content: center;
  /* Theme-adaptive tile (a hardcoded near-black read as a dark box on light/dim
     themes). bg-deep + a faint accent wash reads as a soft chip on every theme. */
  background: var(--vs-bg-deep);
  border: 1px solid var(--vs-hair-2);
  color: var(--vs-accent);   /* drives currentColor for the .vs-icon masks */
}
.vs-feat-icon .mud-icon-root {
  font-size: 20px;
  color: var(--vs-accent);
}
.vs-feat-row.is-locked .vs-feat-icon { color: var(--vs-faint); }
.vs-feat-row.is-locked .vs-feat-icon .mud-icon-root {
  color: var(--vs-faint);
}
.vs-feat-body {
  flex: 1 1 auto;
  min-width: 0;
}
.vs-feat-name {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  font-weight: 600;
  color: var(--vs-text);
  font-size: 14px;
}
.vs-feat-blurb {
  font-size: 12px;
  color: var(--vs-faint);
  margin-top: 2px;
}
.vs-feat-switch {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  min-height: 38px;
}
.vs-feat-chip {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  padding: 2px 7px;
  border-radius: 999px;
  border: 1px solid var(--vs-hair-2);
  color: var(--vs-faint);
}
.vs-feat-chip.is-core {
  color: var(--vs-info);
  border-color: var(--vs-accent);
  background: rgba(120,152,191,0.12);
}
.vs-feat-inlinelink {
  background: none;
  border: none;
  padding: 0;
  color: var(--vs-accent);
  font: inherit;
  cursor: pointer;
  text-decoration: underline;
}

/* Avatar dropdown in the top bar (custom, self-contained). */
.vs-usermenu {
  position: relative;
  display: inline-flex;
}
.vs-usermenu-trigger {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  background: none;
  cursor: pointer;
  border-radius: 50%;
  border: 1.5px solid transparent;
  transition: border-color 0.15s;
}
.vs-usermenu-trigger:hover {
  border-color: var(--vs-accent);
}
.vs-usermenu-backdrop {
  position: fixed;
  inset: 0;
  z-index: 1200;
}
.vs-usermenu-panel {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  z-index: 1201;
  min-width: 210px;
  background: var(--vs-surface);
  border: 1px solid var(--vs-hair-2);
  border-radius: 10px;
  box-shadow: var(--vs-shadow);
  padding: 4px;
  overflow: hidden;
}
.vs-usermenu-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px 10px;
  border-bottom: 1px solid var(--vs-hair-2);
  margin-bottom: 4px;
}
.vs-usermenu-name {
  font-weight: 600;
  color: var(--vs-text);
  font-size: 14px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.vs-usermenu-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 10px;
  border-radius: 7px;
  color: var(--vs-text-2);
  font-size: 14px;
  text-decoration: none;
  cursor: pointer;
}
.vs-usermenu-item:hover {
  background: var(--vs-accent-soft);
  color: var(--vs-text);
}
.vs-usermenu-item .mud-icon-root {
  font-size: 18px;
  color: var(--vs-muted);
}
.vs-usermenu-item--signout {
  color: var(--vs-danger);
}
.vs-usermenu-item--signout .mud-icon-root {
  color: var(--vs-danger);
}

/* Theme picker in the user menu. */
.vs-theme-picker {
  padding: 6px 8px 4px;
  margin-top: 4px;
  border-top: 1px solid var(--vs-hair-2);
}
.vs-theme-picker-label {
  font-size: 10.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--vs-faint);
  padding: 2px 4px 6px;
}
.vs-theme-picker-group { margin-bottom: 2px; }
.vs-theme-picker-sublabel {
  font-size: 9.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--vs-faint);
  opacity: 0.85;
  padding: 4px 4px 3px;
}
.vs-theme-picker-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 3px;
}
.vs-theme-chip {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 8px;
  border-radius: 7px;
  background: none;
  border: 1px solid transparent;
  color: var(--vs-text-2);
  font-family: inherit;
  font-size: 12.5px;
  text-align: left;
  cursor: pointer;
}
.vs-theme-chip:hover { background: var(--vs-accent-soft); color: var(--vs-text); }
.vs-theme-swatch {
  width: 16px;
  height: 16px;
  border-radius: 50%;
  flex-shrink: 0;
  background: linear-gradient(135deg, var(--c-bg) 0 50%, var(--c-acc) 50% 100%);
  box-shadow: inset 0 0 0 1px var(--vs-hair-2);
}
/* Active chip ring — pure CSS off html[data-theme], no JS sync needed. */
html[data-theme="dark"] .vs-theme-chip[data-vs-theme="dark"],
html[data-theme="dim"] .vs-theme-chip[data-vs-theme="dim"],
html[data-theme="wine"] .vs-theme-chip[data-vs-theme="wine"],
html[data-theme="lavender"] .vs-theme-chip[data-vs-theme="lavender"],
html[data-theme="light"] .vs-theme-chip[data-vs-theme="light"],
html[data-theme="blush"] .vs-theme-chip[data-vs-theme="blush"],
html[data-theme="sepia"] .vs-theme-chip[data-vs-theme="sepia"],
html[data-theme="sage"] .vs-theme-chip[data-vs-theme="sage"] {
  border-color: var(--vs-accent);
  background: var(--vs-accent-soft);
  color: var(--vs-text);
  font-weight: 600;
}
/* Pro-theme lock badge + upgrade nudge. Dormant while the gate is open (no Pro
   themes yet); lights up when ThemeAccess.HasPro() returns false. */
.vs-theme-chip-name { flex: 1 1 auto; min-width: 0; }
.vs-theme-chip.is-locked { opacity: 0.9; }
.vs-theme-lock {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  color: var(--vs-faint);
}
.vs-theme-chip.is-locked:hover .vs-theme-lock { color: var(--vs-accent); }
.vs-theme-pro-note {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 6px 4px 2px;
  padding: 7px 9px;
  border-radius: 7px;
  background: var(--vs-accent-soft);
  border: 1px solid var(--vs-hair-2);
  color: var(--vs-text-2);
  font-size: 11.5px;
  line-height: 1.35;
}
.vs-theme-pro-note svg { flex-shrink: 0; color: var(--vs-accent); }
.vs-theme-pro-note[hidden] { display: none; }

/* Catalog page tab bar (Library / Browse All). */
.vs-catalog-tab {
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  color: var(--vs-muted);
  font-size: 14px;
  font-weight: 600;
  padding: 10px 16px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  transition: color 0.15s, border-color 0.15s;
}
.vs-catalog-tab:hover {
  color: var(--vs-text-2);
}
.vs-catalog-tab.is-active {
  color: var(--vs-accent);
  border-bottom-color: var(--vs-accent);
}
.vs-catalog-tab-count {
  font-size: 11px;
  font-weight: 700;
  color: var(--vs-muted);
  background: rgba(0, 0, 0, 0.3);
  border-radius: 9px;
  padding: 1px 7px;
}

/* Segmented control — a connected pill group of view-mode options (same data,
   different density). Distinct from the section tab-bar on purpose. */
.vs-segmented {
  display: inline-flex;
  border: 1px solid var(--vs-hair-2);
  border-radius: 8px;
  overflow: hidden;
  background: var(--vs-bg);
}
.vs-seg {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 12px;
  background: none;
  border: none;
  border-right: 1px solid var(--vs-hair-2);
  color: var(--vs-muted);
  font-size: 13px;
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
}
.vs-seg:last-child { border-right: none; }
.vs-seg:hover { background: rgba(var(--vs-tint), 0.08); color: var(--vs-text-2); }
.vs-seg.is-active { background: rgba(var(--vs-tint), 0.16); color: var(--vs-info); font-weight: 600; }
.vs-seg .mud-icon-root { font-size: 16px; }
/* On narrow screens collapse to icons only. */
@media (max-width: 640px) {
  .vs-seg span { display: none; }
  .vs-seg { padding: 7px 10px; }
}

/* Searchable combobox (ComboSelect) used for the filament-table filters. */
.vs-combo {
  position: relative;
  display: inline-block;
}
.vs-combo-trigger {
  display: inline-flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  min-width: 150px;
  max-width: 220px;
  background: var(--vs-bg);
  border: 1px solid var(--vs-hair-2);
  border-radius: 8px;
  padding: 9px 12px;
  color: var(--vs-text);
  font-size: 14px;
  cursor: pointer;
  transition: border-color 0.15s;
}
.vs-combo-trigger:hover { border-color: var(--vs-accent); }
.vs-combo-trigger.is-open { border-color: var(--vs-info); }
.vs-combo-trigger .vs-combo-ph { color: var(--vs-muted); }
.vs-combo-trigger > span:first-child {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.vs-combo-caret { color: var(--vs-muted); flex-shrink: 0; }
.vs-combo-clear {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--vs-muted);
  flex-shrink: 0;
  border-radius: 50%;
  padding: 2px;
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
}
.vs-combo-clear:hover { background: rgba(255, 255, 255, 0.1); color: var(--vs-text); }
.vs-combo-backdrop { position: fixed; inset: 0; z-index: 1200; }
.vs-combo-panel {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  z-index: 1201;
  width: 280px;
  max-width: 90vw;
  background: var(--vs-surface);
  border: 1px solid var(--vs-hair-2);
  border-radius: 10px;
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.5);
  overflow: hidden;
}
.vs-combo-search {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  border-bottom: 1px solid var(--vs-hair-2);
  color: var(--vs-muted);
}
.vs-combo-search input {
  flex: 1;
  background: none;
  border: none;
  outline: none;
  color: var(--vs-text);
  font-size: 14px;
}
.vs-combo-list {
  max-height: 280px;
  overflow-y: auto;
  padding: 4px;
}
.vs-combo-item {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 9px;
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  border-radius: 6px;
  padding: 8px 10px;
  color: var(--vs-text-2);
  font-size: 14px;
  cursor: pointer;
}
.vs-combo-swatch {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 1px solid #555;
  flex-shrink: 0;
}

/* "+N more" specialties overflow tag. */
.vs-more-tag {
  font-size: 11px;
  color: #8a8aa0;
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid var(--vs-hair-2);
  border-radius: 10px;
  padding: 1px 7px;
  white-space: nowrap;
  cursor: help;
}

/* Empty / no-results state for the filament table. */
.vs-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 48px 20px 40px;
  text-align: center;
  color: #3f4458;
}
.vs-empty svg { color: #3a4060; margin-bottom: 6px; }
.vs-empty-title { font-size: 15px; font-weight: 600; color: var(--vs-muted); }
.vs-empty-sub { font-size: 13px; color: var(--vs-faint); max-width: 320px; }

/* Small "?" help badge next to a filter (native-title tooltip). */
.vs-filter-help {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  border: 1px solid var(--vs-hair-2);
  color: var(--vs-muted);
  font-size: 11px;
  font-weight: 700;
  cursor: help;
  flex-shrink: 0;
  user-select: none;
}
.vs-filter-help:hover { color: var(--vs-text-2); border-color: var(--vs-accent); }

/* Sortable filament-table headers. */
.vs-pf-th {
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
  transition: color 0.15s;
}
.vs-pf-th:hover { color: var(--vs-text-2); }
/* Non-interactive headers (static previews): plain label, no sort affordance. */
.vs-pf-th--static { cursor: default; }
.vs-pf-th--static:hover { color: inherit; }

/* "Clear all" filters button shown when any filter is active. */
.vs-clear-all {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  background: none;
  border: 1px solid #3a2a3a;
  border-radius: 8px;
  padding: 0 12px;
  color: #c89090;
  font-size: 13px;
  cursor: pointer;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
}
.vs-clear-all:hover {
  background: rgba(200, 130, 130, 0.1);
  color: #e0a0a0;
  border-color: #5a3a42;
}

/* Filament-table "Hardened nozzle" toggle filter — off = muted outline, on = accent. */
.vs-pf-toggle {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: var(--vs-bg);
  border: 1px solid var(--vs-hair-2);
  border-radius: 8px;
  padding: 0 12px;
  height: 38px;
  color: var(--vs-muted);
  font-size: 14px;
  cursor: pointer;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
}
.vs-pf-toggle:hover { color: var(--vs-text); border-color: var(--vs-accent); }
.vs-pf-toggle.is-on {
  color: var(--vs-accent);
  border-color: var(--vs-accent);
  background: color-mix(in srgb, var(--vs-accent) 12%, transparent);
}
.vs-combo-item:hover { background: var(--vs-accent-soft); color: var(--vs-text); }
.vs-combo-item.is-selected { color: var(--vs-info); font-weight: 600; }
.vs-combo-empty { padding: 12px 10px; color: var(--vs-muted); font-size: 13px; text-align: center; }

/* Catalog "popular" quick-pick chip rows above the Browse All table. */
.vs-pop {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 18px;
}
.vs-pop-toggle {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  align-self: flex-start;
  background: none;
  border: none;
  padding: 2px 0;
  color: var(--vs-muted);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  cursor: pointer;
}
.vs-pop-toggle:hover { color: var(--vs-text-2); }
.vs-pop-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
}
.vs-pop-label {
  font-size: 11px;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--vs-faint);
  font-weight: 700;
  margin-right: 4px;
  min-width: 116px;
}
.vs-pop-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 11px;
  background: var(--vs-bg);
  border: 1px solid var(--vs-hair-2);
  border-radius: 20px;
  color: var(--vs-text-2);
  font-size: 13px;
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s, color 0.15s;
}
.vs-pop-chip:hover {
  border-color: var(--vs-accent);
  color: #e0e0f0;
}
.vs-pop-chip.is-active {
  border-color: var(--vs-info);
  background: rgba(126, 184, 247, 0.12);
  color: var(--vs-info);
}
.vs-pop-count {
  font-size: 11px;
  font-weight: 700;
  color: var(--vs-muted);
  background: rgba(0, 0, 0, 0.3);
  border-radius: 8px;
  padding: 0 6px;
}
.vs-pop-chip.is-active .vs-pop-count {
  color: var(--vs-info);
}
.vs-catalog-tab.is-active .vs-catalog-tab-count {
  color: var(--vs-accent);
  background: var(--vs-accent-soft);
}
/* Contextual meta on the Catalog tab line (description + stats). */
.vs-tabbar-desc {
  font-size: 12px;
  color: var(--vs-faint);
  margin-left: 6px;
}
.vs-tabbar-stats {
  margin-left: auto;
  font-size: 12px;
  color: var(--vs-muted);
  white-space: nowrap;
  font-family: var(--vs-mono);
}
.vs-settings-navitem .mud-icon-root {
  font-size: 18px;
  flex-shrink: 0;
}

@media (max-width: 820px) {
  .vs-settings-shell {
    flex-direction: column;
    gap: 18px;
  }
  .vs-settings-sidebar {
    flex: 1 1 auto;
    position: static;
    flex-direction: row;
    flex-wrap: wrap;
    gap: 6px;
    width: 100%;
  }
  .vs-settings-navgroup-label {
    width: 100%;
    margin: 8px 0 2px;
  }
  .vs-settings-navgroup-label:first-child {
    margin-top: 0;
  }
  .vs-settings-navitem {
    width: auto;
    padding: 7px 12px;
    border-radius: 20px;
    border-color: var(--vs-hair-2);
    font-size: 13px;
  }
}

/* Add Filament dialog Specialty autocomplete popover. Mud portals the
   panel into <body>; without a width cap and proper anchor, the popover
   floats to the left of the trigger and looks broken. Constrain it. */
.vs-specialty-popover.mud-popover {
  width: max-content !important;
  min-width: 200px !important;
  max-width: min(320px, calc(100vw - 24px)) !important;
  max-height: 60vh;
  background: var(--vs-surface) !important;
  border: 1px solid var(--vs-hair-2) !important;
  box-shadow: 0 8px 24px rgba(0,0,0,0.55) !important;
  z-index: 1400 !important;
}

/* Material tile tooltips must float above card tiles and the advanced-
   section divider. MudTooltip portals into <body> but its default z-index
   falls below our tile stack; bump it and cap width for wrapping. */
.mud-tooltip {
  z-index: 1600 !important;
  max-width: 240px !important;
  white-space: normal !important;
  /* Themed surface chip (was MudBlazor's default dark, which read too dark on
     light themes). Matches the data-vs-tip spool tooltips. */
  background: var(--vs-surface) !important;
  color: var(--vs-text-2) !important;
  border: 1px solid var(--vs-hair-2);
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.22);
}

/* ====== ONBOARDING STORAGE UNIT PREVIEW ====== */
.vs-onb-preview {
  margin-top: 10px;
  padding: 10px 12px;
  background: var(--vs-bg-deep);
  border: 1px solid var(--vs-hair);
  border-radius: var(--vs-radius);
}

.vs-onb-preview-hd {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  font-weight: 600;
  color: var(--vs-text-2);
  margin-bottom: 8px;
}

.vs-onb-preview-shelf {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 5px 0;
  border-top: 1px solid var(--vs-hair-3);
}

.vs-onb-preview-shelf--bin {
  border-top-style: dashed;
}

.vs-onb-preview-shelf-label {
  font-family: var(--vs-mono);
  font-size: 10px;
  color: var(--vs-faint);
  min-width: 44px;
  flex-shrink: 0;
}

.vs-onb-preview-slots {
  display: flex;
  align-items: center;
  gap: 4px;
  flex: 1;
}

.vs-onb-preview-slot {
  width: 18px;
  height: 46px;
  border-radius: 3px;
  background: rgba(var(--vs-tint), 0.02);
  border: 1px dashed rgba(var(--vs-tint), 0.12);
  flex-shrink: 0;
}

.vs-onb-preview-shelf--bin .vs-onb-preview-slot {
  opacity: 0.45;
}

.vs-onb-preview-etc {
  font-size: 10px;
  color: var(--vs-faint);
  margin-left: 4px;
  font-style: italic;
}

.vs-onb-preview-more {
  font-size: 10px;
  color: var(--vs-faint);
  padding: 4px 0 0;
  border-top: 1px solid var(--vs-hair-3);
}

/* ====== ONBOARDING STORAGE TYPE SELECTOR ====== */
.vs-onb-type-group {
  margin-bottom: 0;
}

.vs-onb-type-label {
  font-size: 10.5px;
  color: var(--vs-muted);
  letter-spacing: 0.07em;
  text-transform: uppercase;
  font-weight: 600;
  margin-bottom: 10px;
}

.vs-onb-type-option {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 4px 0;
  cursor: pointer;
  font-size: 13px;
  color: var(--vs-text-2);
  user-select: none;
}

.vs-onb-shelf-count {
  margin-left: 25px;
  margin-top: 8px;
}

.vs-onb-form-grid {
  display: grid;
  grid-template-columns: 35% 1fr;
  gap: 24px;
  align-items: start;
  margin-bottom: 12px;
}

@media (max-width: 520px) {
  .vs-onb-form-grid {
    grid-template-columns: 1fr;
  }
}

/* ====== ONBOARDING "CLICK ADD" CUE ====== */
/* When a unit/room name is typed but not yet added, draw the eye to the Add
   button so the name isn't silently lost on Next. */
@keyframes vs-onb-add-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(var(--vs-tint), 0); }
  50%      { box-shadow: 0 0 0 4px rgba(var(--vs-tint), 0.30); }
}

.vs-onb-add-ready {
  animation: vs-onb-add-pulse 1.5s ease-in-out infinite;
}

.vs-onb-add-hint {
  display: flex;
  align-items: center;
  gap: 5px;
  font-size: 11.5px;
  font-weight: 600;
  color: var(--vs-accent);
}

@media (prefers-reduced-motion: reduce) {
  .vs-onb-add-ready { animation: none; box-shadow: 0 0 0 3px rgba(var(--vs-tint), 0.30); }
}

/* ====== ONBOARDING DONE SCREEN ANIMATIONS ====== */
@keyframes vs-spool-spin {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}

@keyframes vs-done-glow {
  0%, 100% { filter: drop-shadow(0 0 6px rgba(var(--vs-tint), 0.2)); }
  50%       { filter: drop-shadow(0 0 20px rgba(var(--vs-tint), 0.55)); }
}

.vs-done-spool-wrap {
  display: inline-block;
  animation: vs-spool-spin 14s linear infinite, vs-done-glow 3s ease-in-out infinite;
}

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

.vs-done-item {
  animation: vs-done-fade-in 0.4s ease both;
}

/* ====== ONBOARDING DELETE BUTTONS (muted at rest, danger on hover) ====== */
.vs-onb-delete {
  color: var(--vs-faint) !important;
  transition: color 0.15s !important;
}
.vs-onb-delete:hover {
  color: var(--vs-danger) !important;
}

/* ====== LOW STOCK INDICATOR (SpoolSideView dot) ====== */
.vs-spool-low-dot {
  position: absolute;
  top: 2px;
  right: 2px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--vs-warning);
  box-shadow: 0 0 0 2px var(--vs-bg-deep), 0 0 6px rgba(225, 187, 107, 0.55);
  pointer-events: none;
  z-index: 1;
}
/* Run-out forecast page + the Reorder-soon widget body. */
.vs-forecast-controls { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 6px; }
.vs-forecast-chips { display: inline-flex; gap: 4px; background: var(--vs-surface-2); border-radius: 9px; padding: 3px; }
.vs-forecast-chip {
  background: none; border: none; border-radius: 7px; color: var(--vs-muted);
  font-family: inherit; font-size: 12.5px; font-weight: 600; padding: 5px 11px; cursor: pointer;
}
.vs-forecast-chip.is-active { background: var(--vs-accent); color: var(--vs-bg-deep); }
.vs-forecast-list { display: flex; flex-direction: column; gap: 8px; margin-top: 16px; }
.vs-forecast-row {
  display: flex; align-items: center; gap: 12px;
  background: var(--vs-surface); border: 1px solid var(--vs-hair-2);
  border-radius: 10px; padding: 11px 14px;
}
.vs-forecast-dot { width: 14px; height: 14px; border-radius: 50%; flex-shrink: 0; box-shadow: inset 0 0 0 1px rgba(0,0,0,0.18); }
.vs-forecast-main { flex: 1 1 auto; min-width: 0; }
.vs-forecast-name { font-size: 14px; font-weight: 600; color: var(--vs-text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.vs-forecast-sub { font-size: 11.5px; color: var(--vs-muted); margin-top: 1px; }
.vs-forecast-stats { text-align: right; flex-shrink: 0; }
.vs-forecast-days { font-size: 14px; font-weight: 700; color: var(--vs-text); }
.vs-forecast-days.is-urgent { color: var(--vs-danger); }
.vs-forecast-meta { font-size: 11px; color: var(--vs-faint); line-height: 1.4; }
.vs-forecast-buy { flex-shrink: 0; display: flex; align-items: center; gap: 4px; }
.vs-forecast-wish {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border: 1px solid transparent;
  border-radius: 8px;
  background: none;
  cursor: pointer;
  color: var(--vs-muted);
  flex-shrink: 0;
}
.vs-forecast-wish:hover { color: var(--vs-accent); border-color: var(--vs-hair-2); background: var(--vs-bg-tint); }
.vs-forecast-wish.is-on { color: var(--vs-accent); }
.vs-forecast-buybtn {
  display: inline-block; background: var(--vs-accent-soft); color: var(--vs-accent);
  border: 1px solid var(--vs-accent); border-radius: 8px;
  font-size: 12px; font-weight: 600; padding: 6px 12px; text-decoration: none; white-space: nowrap;
}
.vs-forecast-buybtn:hover { background: var(--vs-accent); color: var(--vs-bg-deep); }

/* ---- Wishlist (/wishlist shopping list) ---- */
.vs-wish-list { display: flex; flex-direction: column; gap: 8px; }
.vs-wish-row {
  display: flex; align-items: center; gap: 12px;
  background: var(--vs-surface); border: 1px solid var(--vs-hair-2);
  border-radius: 10px; padding: 11px 14px;
}
.vs-wish-dot {
  width: 22px; height: 22px; border-radius: 50%; flex-shrink: 0;
  box-shadow: inset 0 0 0 1px rgba(0,0,0,0.22);
}
.vs-wish-main { flex: 1 1 auto; min-width: 0; }
.vs-wish-name { font-size: 14px; font-weight: 600; color: var(--vs-text); }
.vs-wish-name a { color: var(--vs-text); text-decoration: none; }
.vs-wish-name a:hover { color: var(--vs-accent); text-decoration: underline; }
.vs-wish-sub {
  font-size: 12px; color: var(--vs-muted); margin-top: 2px;
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
}
.vs-wish-kg {
  font-size: 11px; font-weight: 600; color: var(--vs-text-2);
  background: var(--vs-bg); border: 1px solid var(--vs-hair-2); border-radius: 5px; padding: 1px 6px;
}
.vs-wish-disc {
  font-size: 11px; font-weight: 600; color: var(--vs-danger);
  background: rgba(196,84,84,0.12); border-radius: 5px; padding: 1px 6px;
}
.vs-wish-buy { display: flex; gap: 6px; flex-wrap: wrap; justify-content: flex-end; flex-shrink: 0; }
.vs-wish-btn {
  display: inline-block; background: var(--vs-accent-soft); color: var(--vs-accent);
  border: 1px solid var(--vs-accent); border-radius: 8px;
  font-size: 12px; font-weight: 600; padding: 5px 11px; text-decoration: none; white-space: nowrap;
}
.vs-wish-btn:hover { background: var(--vs-accent); color: var(--vs-bg-deep); }
.vs-wish-btn--ghost {
  background: transparent; color: var(--vs-text-2); border-color: var(--vs-hair-2);
}
.vs-wish-btn--ghost:hover { background: var(--vs-bg); color: var(--vs-text); border-color: var(--vs-text-2); }
.vs-wish-nolink { font-size: 11.5px; color: var(--vs-faint); font-style: italic; }
.vs-wish-remove {
  flex-shrink: 0; background: transparent; border: 0; color: var(--vs-faint);
  cursor: pointer; padding: 4px; border-radius: 6px; display: inline-flex;
}
.vs-wish-remove:hover { color: var(--vs-danger); background: rgba(196,84,84,0.10); }
.vs-wish-copy {
  display: inline-flex; align-items: center; gap: 6px;
  background: transparent; border: 1px solid var(--vs-hair-2); color: var(--vs-text-2);
  border-radius: 8px; font-size: 12px; font-weight: 600; padding: 6px 12px; cursor: pointer;
}
.vs-wish-copy:hover { border-color: var(--vs-accent); color: var(--vs-accent); }
@media (max-width: 560px) {
  .vs-wish-row { flex-wrap: wrap; }
  .vs-wish-buy { width: 100%; justify-content: flex-start; }
}

/* ---- Spool states legend (Spools page ? button) ---- */
.vs-legend-sec {
  font-size: 11px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--vs-accent); margin: 16px 0 8px;
}
.vs-legend-row {
  display: flex; align-items: flex-start; gap: 12px; margin-bottom: 9px;
}
.vs-legend-chip {
  flex: 0 0 auto; min-width: 96px; text-align: center;
  padding: 3px 10px; border-radius: 6px; font-size: 11.5px; font-weight: 600; white-space: nowrap;
}
.vs-legend-chip-ghost {
  background: transparent; color: var(--vs-muted);
  border: 1.5px dashed var(--vs-hair-2);
}
.vs-legend-desc { font-size: 13px; color: var(--vs-text-2); line-height: 1.45; padding-top: 1px; }

/* ---- Spectrum color picker (FilamentColorsEditor) ---- */
.vs-cpick { display: flex; flex-direction: column; gap: 9px; margin: 6px 0 12px; max-width: 240px; }
.vs-cpick-field {
  position: relative; border-radius: 8px; cursor: crosshair;
  border: 1px solid var(--vs-hair-2); touch-action: none; user-select: none;
}
.vs-cpick-thumb {
  position: absolute; width: 14px; height: 14px; border-radius: 50%;
  transform: translate(-50%, -50%); pointer-events: none;
  border: 2px solid #fff; box-shadow: 0 0 0 1px rgba(0,0,0,0.55), 0 1px 3px rgba(0,0,0,0.45);
}
.vs-cpick-hue {
  -webkit-appearance: none; appearance: none; width: 240px; height: 14px; border-radius: 7px;
  border: 1px solid var(--vs-hair-2); outline: none; cursor: pointer;
  background: linear-gradient(to right, #f00 0%, #ff0 17%, #0f0 33%, #0ff 50%, #00f 67%, #f0f 83%, #f00 100%);
}
.vs-cpick-hue::-webkit-slider-thumb {
  -webkit-appearance: none; width: 16px; height: 16px; border-radius: 50%;
  background: #fff; border: 1px solid rgba(0,0,0,0.45); box-shadow: 0 1px 3px rgba(0,0,0,0.4); cursor: pointer;
}
.vs-cpick-hue::-moz-range-thumb {
  width: 16px; height: 16px; border-radius: 50%; background: #fff;
  border: 1px solid rgba(0,0,0,0.45); cursor: pointer;
}

/* Reorder-soon widget (Studio dashboard). */
.vs-runoutw { display: flex; flex-direction: column; gap: 2px; padding: 2px 0; }
.vs-runoutw-row {
  display: flex; align-items: center; gap: 9px;
  padding: 7px 8px; border-radius: 8px; text-decoration: none; color: inherit;
}
.vs-runoutw-row:hover { background: var(--vs-accent-soft); }
.vs-runoutw-dot { width: 11px; height: 11px; border-radius: 50%; flex-shrink: 0; box-shadow: inset 0 0 0 1px rgba(0,0,0,0.18); }
.vs-runoutw-main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
.vs-runoutw-name { font-size: 12.5px; font-weight: 600; color: var(--vs-text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.vs-runoutw-sub { font-size: 10.5px; color: var(--vs-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.vs-runoutw-days { font-size: 12px; font-weight: 700; color: var(--vs-text-2); flex-shrink: 0; }
.vs-runoutw-days.is-urgent { color: var(--vs-danger); }
.vs-runoutw-cta { font-size: 11px; font-weight: 600; color: var(--vs-accent); flex-shrink: 0; white-space: nowrap; }
.vs-runoutw-all { display: inline-block; margin-top: 6px; font-size: 11.5px; color: var(--vs-accent); text-decoration: none; padding: 2px 8px; }
.vs-runoutw-all:hover { text-decoration: underline; }

/* Weight-input mode toggle + % quick-set (Spool Detail weight panel). */
.vs-wmode { display: inline-flex; gap: 2px; background: var(--vs-surface-2); border-radius: 8px; padding: 2px; margin-bottom: 8px; }
.vs-wmode-seg {
  background: none;
  border: none;
  border-radius: 6px;
  color: var(--vs-muted);
  font-family: inherit;
  font-size: 11.5px;
  font-weight: 600;
  padding: 4px 12px;
  cursor: pointer;
}
.vs-wmode-seg.is-active { background: var(--vs-surface); color: var(--vs-text); box-shadow: 0 1px 2px rgba(0,0,0,0.18); }
.vs-wmode-seg:disabled { opacity: 0.4; cursor: not-allowed; }
.vs-whelp { font-size: 11px; color: var(--vs-faint); margin-top: 5px; line-height: 1.4; max-width: 280px; }
.vs-wwarn { font-size: 11.5px; color: var(--vs-warning); margin-top: 5px; line-height: 1.4; max-width: 280px; }
.vs-wpct { display: flex; flex-wrap: wrap; align-items: center; gap: 5px; }
.vs-wpct-chip {
  min-width: 38px;
  background: var(--vs-surface-2);
  border: 1px solid var(--vs-hair-2);
  border-radius: 7px;
  color: var(--vs-text-2);
  font-family: inherit;
  font-size: 12px;
  font-weight: 600;
  padding: 6px 8px;
  cursor: pointer;
}
.vs-wpct-chip:hover { border-color: var(--vs-accent); color: var(--vs-text); }
.vs-wpct-chip.is-active { background: var(--vs-accent-soft); border-color: var(--vs-accent); color: var(--vs-text); }
.vs-wpct-save {
  background: var(--vs-accent);
  border: none;
  border-radius: 7px;
  color: var(--vs-bg-deep);
  font-family: inherit;
  font-size: 12px;
  font-weight: 700;
  padding: 6px 14px;
  cursor: pointer;
}
.vs-wpct-saved { font-size: 12px; font-weight: 600; color: var(--vs-accent); display: inline-flex; align-items: center; }

/* Drying-hours field: shrink the input + "Hours" placeholder to match the
   13px date field beside it (MudNumericField defaults to ~16px). Pin its width
   so the field doesn't stretch and shove the pills + check/X off to the right. */
/* Compound selector (.mud-input-control.vs-dry-hours) so it outranks MudBlazor's
   own .mud-input-control { flex: 1 1 auto }, which otherwise lets the field grow
   and shove the pills + check/X to the far right. */
.vs-dry-hours.mud-input-control { flex: 0 0 auto; width: 96px; }
.vs-dry-hours .mud-input-slot,
.vs-dry-hours input { font-size: 13px; }
.vs-dry-hours input::placeholder { font-size: 13px; }

/* Custom inline icons (Noun Project Pro, royalty-free). Rendered as CSS masks so
   the SVG shape inherits the element's text color via background:currentColor —
   the same theme-aware coloring MudIcons get, which a plain <img> can't do.
   Size with inline width/height; color follows the surrounding text. */
.vs-icon {
  display: inline-block;
  flex: none;
  vertical-align: middle;
  background-color: currentColor;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
}
.vs-icon--printing    { -webkit-mask-image: url(/icons/printing.svg);    mask-image: url(/icons/printing.svg); }
.vs-icon--dryer       { -webkit-mask-image: url(/icons/dryer.svg);       mask-image: url(/icons/dryer.svg); }
.vs-icon--drybox      { -webkit-mask-image: url(/icons/drybox.svg);      mask-image: url(/icons/drybox.svg); }
.vs-icon--scale       { -webkit-mask-image: url(/icons/scale.svg);       mask-image: url(/icons/scale.svg); }
.vs-icon--shelf       { -webkit-mask-image: url(/icons/shelf.svg);       mask-image: url(/icons/shelf.svg); }
.vs-icon--thermometer { -webkit-mask-image: url(/icons/thermometer.svg); mask-image: url(/icons/thermometer.svg); }
.vs-icon--calipers    { -webkit-mask-image: url(/icons/calipers.svg);    mask-image: url(/icons/calipers.svg); }
.vs-icon--vacuumbag   { -webkit-mask-image: url(/icons/vacuumbag.svg);   mask-image: url(/icons/vacuumbag.svg); }
.vs-icon--moisture    { -webkit-mask-image: url(/icons/moisture.svg);    mask-image: url(/icons/moisture.svg); }
.vs-icon--search      { -webkit-mask-image: url(/icons/search.svg);      mask-image: url(/icons/search.svg); }
.vs-icon--inventory   { -webkit-mask-image: url(/icons/inventory.svg);   mask-image: url(/icons/inventory.svg); }
.vs-icon--room        { -webkit-mask-image: url(/icons/room.svg);        mask-image: url(/icons/room.svg); }
.vs-icon--bin         { -webkit-mask-image: url(/icons/bin.svg);         mask-image: url(/icons/bin.svg); }
.vs-icon--rack        { -webkit-mask-image: url(/icons/rack.svg);        mask-image: url(/icons/rack.svg); }
.vs-icon--menu        { -webkit-mask-image: url(/icons/menu.svg);        mask-image: url(/icons/menu.svg); }
.vs-icon--swatch      { -webkit-mask-image: url(/icons/swatch.svg);      mask-image: url(/icons/swatch.svg); }
.vs-icon--spool       { -webkit-mask-image: url(/icons/spool.svg);       mask-image: url(/icons/spool.svg); }
.vs-icon--poop        { -webkit-mask-image: url(/icons/poop.svg);        mask-image: url(/icons/poop.svg); }

/* Sticky-note bar on the Spool Detail page. */
.vs-sticky-bar { margin-bottom: 10px; }
.vs-sticky-add {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  background: none;
  border: 1px dashed var(--vs-hair-2);
  border-radius: 8px;
  color: var(--vs-muted);
  font-family: inherit;
  font-size: 12.5px;
  padding: 7px 12px;
  cursor: pointer;
}
.vs-sticky-add:hover { color: var(--vs-text); border-color: var(--vs-accent); }
.vs-sticky-add-mark { display: inline-flex; color: var(--vs-accent); }
.vs-sticky-card {
  position: relative;
  overflow: hidden;
  display: flex;
  align-items: center;
  gap: 9px;
  /* A real sticky note is light paper, whatever the UI theme: the lightest tint
     the palette offers (surface mixed toward white) with dark ink on top. */
  background: color-mix(in srgb, var(--vs-surface) 55%, #ffffff 45%);
  color: #2a2f3a;
  border: 1px solid rgba(0, 0, 0, 0.07);
  border-radius: 8px;
  padding: 8px 10px;
  /* Highlight = a lifted-paper drop shadow (heavier at the bottom), not a colored
     accent bar — reads as a real sticky note pinned over the card. */
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.18), 0 1px 1px rgba(0, 0, 0, 0.10);
}
/* Folded bottom-right corner in a darker shade — the dog-ear of the note. */
.vs-sticky-card::after {
  content: "";
  position: absolute;
  right: 0;
  bottom: 0;
  border-style: solid;
  border-width: 0 0 11px 11px;
  border-color: transparent transparent rgba(0, 0, 0, 0.16) transparent;
}
.vs-sticky-card-mark { display: inline-flex; flex-shrink: 0; color: var(--vs-accent); }
.vs-sticky-input {
  flex: 1 1 auto;
  min-width: 0;
  background: none;
  border: none;
  color: #2a2f3a;
  font-family: inherit;
  font-size: 13px;
  padding: 2px 0;
}
.vs-sticky-input:focus { outline: none; }
.vs-sticky-input::placeholder { color: #8a8f9a; }
.vs-sticky-remove {
  flex-shrink: 0;
  background: none;
  border: none;
  color: #8a8f9a;
  font-family: inherit;
  font-size: 12px;
  cursor: pointer;
  padding: 2px 4px;
}
.vs-sticky-remove:hover { color: var(--vs-danger, #d2607a); }

/* Compact inline variant living in the Spool Status header. */
.vs-sticky-add--mini { padding: 3px 9px; font-size: 12px; border-radius: 7px; }
.vs-sticky-card--mini {
  flex: 1 1 auto;
  min-width: 0;
  max-width: 320px;
  gap: 6px;
  padding: 4px 9px;
  border-radius: 7px;
}
.vs-sticky-card--mini .vs-sticky-input { font-size: 12.5px; }
.vs-sticky-card--mini .vs-sticky-remove { font-size: 16px; line-height: 1; padding: 0 2px; }

/* Sticky-note marker on a spool render: a little note with a peeled-up bottom
   corner (the SVG draws the dog-ear). Top-left so it never clashes with the
   top-right low-stock dot. Tinted with the theme accent. */
/* Sticky Notes widget: a wall of classic yellow post-its (the note + its spool). */
.vs-postit-wrap {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  padding: 6px 2px 2px;
}
.vs-postit {
  display: flex;
  flex-direction: column;
  gap: 4px;
  width: 118px;
  min-height: 96px;
  padding: 10px 11px;
  background: #fef3a0;
  color: #3a3320;
  text-decoration: none;
  border-radius: 2px;
  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.28), inset 0 1px 0 rgba(255, 255, 255, 0.45);
  transform: rotate(-1.4deg);
  transition: transform 0.12s ease, box-shadow 0.12s ease;
}
.vs-postit:nth-child(even) { transform: rotate(1.6deg); background: #fdeb7e; }
.vs-postit:nth-child(3n) { transform: rotate(0.6deg); }
.vs-postit:hover {
  transform: rotate(0) translateY(-2px);
  box-shadow: 0 7px 15px rgba(0, 0, 0, 0.32), inset 0 1px 0 rgba(255, 255, 255, 0.45);
}
.vs-postit-note {
  font-size: 12.5px;
  line-height: 1.35;
  font-weight: 600;
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
}
.vs-postit-spool {
  margin-top: auto;
  font-size: 10.5px;
  opacity: 0.65;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.vs-spool-note-dot {
  position: absolute;
  top: 1px;
  left: 1px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--vs-accent);
  filter: drop-shadow(0 0 1.2px var(--vs-bg-deep)) drop-shadow(0 1px 1px rgba(0, 0, 0, 0.35));
  pointer-events: none;
  z-index: 1;
}

/* ====== NAV LOW STOCK BADGE ====== */
.vs-nav-low-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: 999px;
  background: rgba(225, 187, 107, 0.18);
  border: 1px solid rgba(225, 187, 107, 0.35);
  color: var(--vs-warning);
  font-family: var(--vs-mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0;
  line-height: 1;
}

/* ====== LOW STOCK DASHBOARD WIDGET ====== */
.vs-low-widget {
  background: rgba(225, 187, 107, 0.04);
  border: 1px solid rgba(225, 187, 107, 0.18);
  border-radius: var(--vs-radius-lg);
  padding: 14px 16px;
  margin-top: 12px;
  margin-bottom: 20px;
}

.vs-low-widget-hd {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 12px;
}

.vs-low-widget-title {
  display: flex;
  align-items: center;
  gap: 7px;
  font-family: var(--vs-sans);
  font-size: 12.5px;
  font-weight: 600;
  color: var(--vs-text-2);
  flex: 1;
}

.vs-low-widget-count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 20px;
  height: 20px;
  padding: 0 6px;
  border-radius: 999px;
  background: rgba(225, 187, 107, 0.15);
  border: 1px solid rgba(225, 187, 107, 0.30);
  color: var(--vs-warning);
  font-family: var(--vs-mono);
  font-size: 10.5px;
  font-weight: 700;
}

.vs-low-settings-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  background: transparent;
  border: 1px solid var(--vs-hair);
  border-radius: 6px;
  color: var(--vs-faint);
  cursor: pointer;
  transition: color 0.12s, background 0.12s, border-color 0.12s;
}
.vs-low-settings-btn:hover,
.vs-low-settings-btn.is-active {
  color: var(--vs-text-2);
  background: var(--vs-surface-2);
  border-color: var(--vs-hair-2);
}

.vs-low-settings {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
  padding: 10px 12px;
  background: var(--vs-surface-2);
  border-radius: var(--vs-radius);
  margin-bottom: 12px;
  border: 1px solid var(--vs-hair);
}

.vs-low-settings-row {
  display: flex;
  align-items: center;
  gap: 10px;
}

.vs-low-settings-label {
  font-size: 12px;
  color: var(--vs-text-2);
  white-space: nowrap;
}

.vs-low-slider {
  width: 100px;
  accent-color: var(--vs-warning);
}

.vs-low-select {
  font-size: 12px !important;
  padding: 5px 24px 5px 8px !important;
}

.vs-low-save-btn {
  font-size: 12px !important;
  padding: 5px 14px !important;
  margin-left: auto;
}

.vs-low-widget-list {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  flex-wrap: wrap;
}

.vs-low-spool {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  text-decoration: none;
  cursor: pointer;
  padding: 6px;
  border-radius: var(--vs-radius);
  border: 1px solid transparent;
  transition: background 0.12s, border-color 0.12s;
}
.vs-low-spool:hover {
  background: var(--vs-surface-2);
  border-color: var(--vs-hair);
}

.vs-low-spool-name {
  font-family: var(--vs-sans);
  font-size: 10px;
  line-height: 1.4;
  color: var(--vs-text-2);
  max-width: 64px;
  height: 3em;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  text-align: center;
}

.vs-low-spool-pct {
  font-family: var(--vs-mono);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.02em;
}

.vs-low-more {
  display: flex;
  align-items: center;
  align-self: center;
  padding: 4px 10px;
  font-size: 11px;
  color: var(--vs-faint);
  text-decoration: none;
  transition: color 0.12s;
}
.vs-low-more:hover {
  color: var(--vs-accent);
}

/* ====== STUDIO HEAD STATS (spool count + collection value) ====== */
/* Upper-right cluster on the Studio head: kg/$ pills, then the Widgets + Edit
   layout controls. */
.vs-studio-head-actions {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  justify-content: flex-end;
}
/* The Widgets dropdown now sits near the right edge — open it leftward so it
   doesn't overflow the viewport. */
.vs-studio-head-actions .vs-widget-customize-panel { left: auto; right: 0; }

.vs-studio-head-stats {
  display: flex;
  align-items: center;
  gap: 12px;
}

.vs-studio-value {
  font-family: var(--vs-mono);
  font-size: 12.5px;
  font-weight: 600;
  color: var(--vs-secondary);
  letter-spacing: 0.01em;
  padding: 3px 8px;
  background: rgba(124, 200, 160, 0.08);
  border: 1px solid rgba(124, 200, 160, 0.20);
  border-radius: 999px;
}
.vs-studio-value--weight {
  color: var(--vs-accent);
  background: rgba(var(--vs-tint), 0.08);
  border-color: rgba(var(--vs-tint), 0.20);
}
/* Lavender so the spools/filaments count is distinct from the green cost pill
   and the blue weight pill. */
.vs-studio-value--count {
  color: #cdbcf2;
  background: rgba(170, 130, 235, 0.10);
  border-color: rgba(170, 130, 235, 0.24);
}

/* ── Recent Activity widget (Studio) ── */
.vs-activity {
  display: flex;
  flex-direction: column;
  max-height: 360px;
  overflow-y: auto;
}
.vs-activity-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 4px;
  text-decoration: none;
  border-bottom: 1px solid rgba(255, 255, 255, 0.05);
}
.vs-activity-row:last-child { border-bottom: none; }
.vs-activity-row:hover { background: rgba(255, 255, 255, 0.03); }
.vs-activity-dot {
  width: 16px;
  height: 16px;
  border-radius: 50%;
  flex: 0 0 auto;
  border: 1px solid rgba(255, 255, 255, 0.18);
}
.vs-activity-main { display: flex; flex-direction: column; min-width: 0; flex: 1 1 auto; }
.vs-activity-name {
  font-size: 13px;
  color: var(--vs-text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.vs-activity-act { font-size: 11px; color: var(--vs-faint); }
.vs-activity-time {
  font-size: 11px;
  color: var(--vs-faint);
  flex: 0 0 auto;
  white-space: nowrap;
}

/* ── Match-a-Color tool (/color-match) ── */
.vs-cm-input {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 10px;
}
.vs-cm-swatch-lg {
  width: 44px;
  height: 44px;
  border-radius: 10px;
  border: 1px solid var(--vs-hair-2);
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.04);
}
.vs-cm-swatch-q { color: var(--vs-faint); font-size: 20px; font-weight: 600; }
.vs-cm-picker {
  width: 44px;
  height: 38px;
  padding: 2px;
  background: var(--vs-bg-tint);
  border: 1px solid var(--vs-hair-2);
  border-radius: 8px;
  cursor: pointer;
  flex: 0 0 auto;
}
.vs-cm-presets {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-bottom: 22px;
}
.vs-cm-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px 4px 7px;
  font-size: 12px;
  color: var(--vs-text-2);
  background: var(--vs-bg-tint);
  border: 1px solid var(--vs-hair-2);
  border-radius: 999px;
  cursor: pointer;
}
.vs-cm-chip:hover { border-color: #3a3a4e; color: var(--vs-text); }
.vs-cm-chip-dot {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, 0.18);
}
.vs-cm-materials {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  margin: -10px 0 22px;
}
.vs-cm-mat {
  font-size: 12px;
  color: var(--vs-text-2);
  background: var(--vs-bg-tint);
  border: 1px solid var(--vs-hair-2);
  border-radius: 999px;
  padding: 3px 11px;
  cursor: pointer;
}
.vs-cm-mat:hover { border-color: #3a3a4e; color: var(--vs-text); }
.vs-cm-mat--on {
  color: #0c1220;
  background: var(--vs-secondary);
  border-color: var(--vs-secondary);
  font-weight: 600;
}
.vs-cm-mat-clear {
  font-size: 12px;
  color: var(--vs-faint);
  background: transparent;
  border: none;
  cursor: pointer;
  text-decoration: underline;
  padding: 3px 4px;
}
.vs-cm-mat-clear:hover { color: var(--vs-text-2); }
.vs-cm-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 28px;
}
@media (max-width: 760px) { .vs-cm-grid { grid-template-columns: 1fr; } }
.vs-cm-col-title {
  font-size: 14px;
  font-weight: 600;
  color: var(--vs-text);
  margin: 0 0 10px;
  display: flex;
  align-items: center;
  gap: 8px;
}
.vs-cm-count {
  font-size: 11px;
  font-weight: 600;
  color: var(--vs-faint);
  background: var(--vs-bg-tint);
  border-radius: 999px;
  padding: 1px 8px;
}
.vs-cm-empty { color: var(--vs-faint); font-size: 13px; margin: 6px 0; }
.vs-cm-join {
  border: 1px solid var(--vs-hair-2);
  border-radius: 12px;
  background: linear-gradient(160deg, var(--vs-bg-tint) 0%, var(--vs-bg-deep) 100%);
  padding: 20px 20px 22px;
}
.vs-cm-join-title {
  font-size: 18px;
  font-weight: 700;
  color: var(--vs-text);
  margin: 0 0 8px;
  line-height: 1.25;
}
.vs-cm-join-body {
  font-size: 13px;
  line-height: 1.55;
  color: var(--vs-text-2);
  margin: 0 0 16px;
}
.vs-cm-join-body em { color: var(--vs-text); font-style: normal; font-weight: 600; }
.vs-cm-join-cta { display: inline-block; }
.vs-cm-join-signin {
  display: block;
  margin-top: 10px;
  font-size: 12px;
  color: var(--vs-faint);
  text-decoration: underline;
}
.vs-cm-join-signin:hover { color: var(--vs-text-2); }
.vs-cm-row-wrap { display: flex; align-items: center; gap: 2px; }
.vs-cm-row-wrap .vs-cm-row { flex: 1 1 auto; }
.vs-cm-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 10px;
  border-radius: 8px;
  text-decoration: none;
  border: 1px solid transparent;
}
.vs-cm-row:hover { background: var(--vs-bg-tint); border-color: var(--vs-hair-2); }
/* Wishlist (cart) toggle on buyable color-match rows. */
.vs-cm-wish {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border: 1px solid transparent;
  border-radius: 8px;
  background: none;
  cursor: pointer;
  color: var(--vs-muted);
}
.vs-cm-wish:hover { color: var(--vs-accent); border-color: var(--vs-hair-2); background: var(--vs-bg-tint); }
.vs-cm-wish.is-on { color: var(--vs-accent); }
.vs-cm-swatch {
  width: 30px;
  height: 30px;
  border-radius: 7px;
  flex: 0 0 auto;
  border: 1px solid rgba(255, 255, 255, 0.12);
}
.vs-cm-row-main { display: flex; flex-direction: column; min-width: 0; flex: 1 1 auto; }
.vs-cm-row-label {
  font-size: 13px;
  color: var(--vs-text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.vs-cm-qty {
  font-size: 11px;
  font-weight: 600;
  color: var(--vs-text-2);
  background: rgba(255, 255, 255, 0.07);
  border-radius: 999px;
  padding: 0 6px;
  margin-left: 6px;
  vertical-align: middle;
}
.vs-cm-row-sub { font-size: 11px; color: var(--vs-faint); }
.vs-cm-score { display: flex; align-items: center; gap: 8px; flex: 0 0 auto; }
.vs-cm-bar {
  width: 56px;
  height: 5px;
  border-radius: 3px;
  background: rgba(255, 255, 255, 0.08);
  overflow: hidden;
}
.vs-cm-bar-fill {
  display: block;
  height: 100%;
  border-radius: 3px;
  background: linear-gradient(90deg, #3d8a72, var(--vs-secondary));
}
.vs-cm-pct {
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  color: var(--vs-text-2);
  min-width: 34px;
  text-align: right;
}
.vs-cm-popular { margin-top: 36px; }
.vs-cm-popular-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 12px;
}
.vs-cm-pop {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 5px 12px 5px 8px;
  font-size: 13px;
  color: var(--vs-text-2);
  background: var(--vs-bg-tint);
  border: 1px solid var(--vs-hair-2);
  border-radius: 999px;
  text-decoration: none;
}
.vs-cm-pop:hover { border-color: #3a3a4e; color: var(--vs-text); }
.vs-cm-pop-dot {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, 0.18);
}

/* ── Photos (PhotoPanel + community gallery) ─────────────────────────────── */
.vs-photos { margin: 4px 0; }
.vs-photos-head {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--vs-muted);
  margin-bottom: 10px;
  display: flex;
  align-items: center;
  gap: 8px;
}
.vs-photos-count {
  font-size: 11px;
  font-weight: 600;
  color: var(--vs-text-2);
  background: var(--vs-surface-2);
  border: 1px solid var(--vs-hair-2);
  border-radius: 999px;
  padding: 1px 8px;
}
.vs-photos-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(104px, 1fr));
  gap: 8px;
}
.vs-photos.is-compact .vs-photos-grid {
  grid-template-columns: repeat(auto-fill, minmax(80px, 1fr));
  gap: 6px;
}
.vs-photo-tile { position: relative; aspect-ratio: 1; }
.vs-photo-thumb {
  display: block;
  width: 100%;
  height: 100%;
  padding: 0;
  border: 1px solid var(--vs-hair-2);
  border-radius: 10px;
  overflow: hidden;
  background: var(--vs-surface-2);
  cursor: pointer;
  transition: border-color 0.15s var(--vs-ease), transform 0.15s var(--vs-ease);
}
.vs-photo-thumb:hover { border-color: var(--vs-accent); transform: translateY(-1px); }
.vs-photo-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.vs-photo-tag {
  position: absolute;
  left: 6px;
  bottom: 6px;
  font-size: 10px;
  font-weight: 600;
  color: var(--vs-text);
  background: color-mix(in srgb, var(--vs-surface) 86%, transparent);
  border: 1px solid var(--vs-hair-2);
  border-radius: 6px;
  padding: 1px 6px;
  pointer-events: none;
}
.vs-photo-badge {
  position: absolute;
  top: 6px;
  left: 6px;
  font-size: 10px;
  font-weight: 700;
  border-radius: 6px;
  padding: 1px 6px;
  pointer-events: none;
}
.vs-photo-badge.is-pending { background: var(--vs-st-drying-bg); color: var(--vs-st-drying-fg); }
.vs-photo-badge.is-public { background: var(--vs-accent-glow); color: var(--vs-accent-deep); }
.vs-photo-badge.is-rejected { background: rgba(190, 80, 90, 0.2); color: var(--vs-danger, #d2607a); }
.vs-photo-actions {
  position: absolute;
  top: 6px;
  right: 6px;
  display: flex;
  gap: 4px;
  opacity: 0;
  transition: opacity 0.15s var(--vs-ease);
}
.vs-photo-tile:hover .vs-photo-actions { opacity: 1; }
.vs-photo-actions button {
  font-size: 10px;
  font-weight: 600;
  font-family: inherit;
  color: var(--vs-text);
  background: color-mix(in srgb, var(--vs-surface) 90%, transparent);
  border: 1px solid var(--vs-hair-2);
  border-radius: 6px;
  padding: 2px 7px;
  cursor: pointer;
}
.vs-photo-actions button:hover { border-color: var(--vs-accent); }
.vs-photo-actions .vs-photo-del { color: var(--vs-danger, #d2607a); padding: 2px 6px; }
.vs-photo-add {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  aspect-ratio: 1;
  position: relative;
  border: 1.5px dashed var(--vs-hair);
  border-radius: 10px;
  color: var(--vs-muted);
  cursor: pointer;
  transition: border-color 0.15s var(--vs-ease), color 0.15s var(--vs-ease);
}
.vs-photo-add:hover { border-color: var(--vs-accent); color: var(--vs-accent); }
.vs-photo-add.is-busy { cursor: progress; opacity: 0.7; }
.vs-photo-add input[type="file"] {
  position: absolute;
  inset: 0;
  opacity: 0;
  cursor: pointer;
}
.vs-photo-add.is-busy input[type="file"] { pointer-events: none; }
.vs-photo-add-icon { font-size: 20px; line-height: 1; }
.vs-photo-add-label { font-size: 11px; font-weight: 600; }
.vs-photos-error {
  margin-top: 8px;
  font-size: 12px;
  color: var(--vs-danger, #d2607a);
}
.vs-photos-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 10px;
}
.vs-photos-kind { display: inline-flex; border: 1px solid var(--vs-hair-2); border-radius: 8px; overflow: hidden; }
.vs-photos-kind button {
  font-size: 11px;
  font-weight: 600;
  font-family: inherit;
  color: var(--vs-text-2);
  background: var(--vs-surface);
  border: none;
  padding: 4px 12px;
  cursor: pointer;
}
.vs-photos-kind button.is-active { background: var(--vs-accent-soft); color: var(--vs-text); }
.vs-photos-public {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--vs-text-2);
  cursor: pointer;
}
.vs-photos-public input { accent-color: var(--vs-accent); }

.vs-photo-lightbox {
  position: fixed;
  inset: 0;
  z-index: 11000;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding: 32px;
  background: rgba(8, 9, 14, 0.86);
  cursor: zoom-out;
}
.vs-photo-lightbox img {
  max-width: min(94vw, 1400px);
  max-height: 84vh;
  object-fit: contain;
  border-radius: 10px;
  box-shadow: 0 24px 80px rgba(0, 0, 0, 0.6);
  cursor: default;
}
.vs-photo-lightbox-x {
  position: absolute;
  top: 18px;
  right: 22px;
  font-size: 20px;
  color: #fff;
  background: rgba(255, 255, 255, 0.12);
  border: none;
  border-radius: 50%;
  width: 38px;
  height: 38px;
  cursor: pointer;
}
.vs-photo-lightbox-x:hover { background: rgba(255, 255, 255, 0.24); }
.vs-photo-lightbox-cap {
  color: #eef1f6;
  font-size: 13px;
  max-width: 700px;
  text-align: center;
}
.vs-photo-lightbox-edit {
  display: flex;
  gap: 8px;
  width: min(700px, 92vw);
}
.vs-photo-lightbox-edit input {
  flex: 1 1 auto;
  min-width: 0;
  background: rgba(255, 255, 255, 0.10);
  border: 1px solid rgba(255, 255, 255, 0.22);
  border-radius: 8px;
  color: #eef1f6;
  font-family: inherit;
  font-size: 13px;
  padding: 8px 12px;
}
.vs-photo-lightbox-edit input::placeholder { color: rgba(238, 241, 246, 0.55); }
.vs-photo-lightbox-edit button {
  flex: 0 0 auto;
  background: var(--vs-accent);
  color: var(--vs-bg-deep);
  border: none;
  border-radius: 8px;
  padding: 8px 16px;
  font-family: inherit;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
}
.vs-community-note {
  margin-top: 10px;
  font-size: 12px;
  color: var(--vs-faint);
}
.vs-printlog-cam {
  background: none;
  border: none;
  cursor: pointer;
  font-size: 13px;
  line-height: 1;
  padding: 2px 4px;
  opacity: 0.7;
}
.vs-printlog-cam:hover { opacity: 1; }
.vs-printlog-photos {
  margin: 4px 0 10px 22px;
  padding: 10px 12px;
  border-left: 2px solid var(--vs-hair-2);
  background: var(--vs-surface-2);
  border-radius: 0 8px 8px 0;
}
.vs-shelf-cam.is-active { color: var(--vs-accent); }
.vs-shelf-photos {
  padding: 10px 12px;
  border-top: 1px solid var(--vs-hair-2);
}
