/* Velvetmoth Lash & Brow — "Neon Bloom".
   Every ratio below was computed, not judged. The one rule that governs this palette:

     neon #FF2D95 is a FILL on light grounds, never text — 3.46:1 on white, 3.14:1 on blush.
     It becomes legitimate body text only on --night (#140B18), where it measures 5.56:1.
     On light grounds the text-safe pink is --neon-deep #C4006B (5.9:1 white, 5.35:1 blush).

   The other trap: --glow #FF8CC6 reads beautifully on night (9:1) and fails on white (2.14:1).
   It is a dark-band colour only. --line #F6D9E9 is 1.31:1 — decoration, never a meaningful edge.

   Type: Dancing Script Variable for display, Quicksand Variable for everything else. Both OFL,
   both one file, so every weight in range is real and faux-bold is impossible (rule 10).
   Dancing Script was chosen over Sacramento/Parisienne/Great Vibes for a measurable reason:
   it is the only script of the four that ships real weights (400–700), and this page's
   headings sit on near-black, where a single-weight monoline script goes fragile. The
   reference site can use Sacramento because its background is light — that is its problem,
   not this one's.

   RULE: never put negative letter-spacing on the script. It is a CONNECTED face; tightening
   the tracking pulls the joins apart and the word stops reading as handwriting. Display
   tracking here is 0, deliberately, and that is not an oversight to "fix" later.

   Both fallback stacks are chosen so the layout survives the swap — nothing relies on nowrap
   or a fixed text width, and every heading is free to wrap. */
@font-face { font-family: "Dancing Script"; src: url("/assets/fonts/dancing-script-wght-normal.woff2") format("woff2"); font-weight: 400 700; font-display: swap; }
@font-face { font-family: "Quicksand"; src: url("/assets/fonts/quicksand-wght-normal.woff2") format("woff2"); font-weight: 300 700; font-display: swap; }

/* Zero-specificity resets (rule 14): component colours must always outrank these. */
:where(.vm) *, :where(.vm) *::before, :where(.vm) *::after { box-sizing: border-box; }
:where(.vm) :where(h1, h2, h3, p, ol, ul, dl, dd, figure, table, blockquote) { margin: 0; }
:where(.vm) :where(ol, ul) { list-style: none; padding: 0; }
:where(.vm) a { color: inherit; }
:where(.vm) :where(input, select, textarea, button) { font: inherit; color: inherit; }

.vm { --white: #FFFFFF; --blush: #FFF0F7; --line: #F6D9E9; --night: #140B18;
  --ink: #241528; --muted: #6B5B6E; --neon: #FF2D95; --neon-deep: #C4006B; --glow: #FF8CC6;
  --display: "Dancing Script", "Segoe Script", "Brush Script MT", cursive;
  --text: "Quicksand", "Century Gothic", "Avenir Next", "Segoe UI", system-ui, sans-serif;
  --pad: clamp(20px, 5vw, 72px); --t: 160ms cubic-bezier(.4, 0, .6, 1);
  background: var(--white); color: var(--ink);
  font-family: var(--text); font-size: 17px; line-height: 1.6; font-weight: 500; }
.vm :focus-visible { outline: 2px solid var(--neon-deep); outline-offset: 2px; }
.vm-hero :focus-visible, .vm-book :focus-visible, .vm-footer :focus-visible, .vm-header :focus-visible { outline-color: var(--glow); }
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.vm [hidden] { display: none !important; }

/* ---------- header: on night, so the neon wordmark is allowed to be type ---------- */
.vm-header { display: flex; align-items: center; gap: clamp(12px, 3vw, 40px); padding: 14px var(--pad); background: var(--night); color: var(--white); }
.vm-logo { display: inline-flex; align-items: center; gap: 12px; text-decoration: none; }
.vm-logo__mark { display: inline-flex; color: var(--neon); }
.vm-logo__text { display: grid; line-height: 1.05; }
.vm-logo__text b { font-family: var(--display); font-size: 27px; font-weight: 700; letter-spacing: 0; }
.vm-logo__text small { font-size: 11px; font-weight: 500; letter-spacing: 0.22em; text-transform: uppercase; color: var(--glow); }
.vm-nav { margin-left: auto; }
.vm-nav ul { display: flex; gap: clamp(14px, 2.4vw, 30px); }
.vm-nav a { font-size: 15px; font-weight: 500; text-decoration: none; color: #E9DCE6; transition: color var(--t); }
.vm-nav a:hover { color: var(--neon); }
/* Phone menu (2026-09-24): the nav's links below 960px, where the nav hides. The real site's pattern and script
   (src/scripts/menu.js); only the look is Velvetmoth's: the night header runs on down into the panel, neon on hover.
   It is inside .vm-header, so its focus ring is the header's glow, not neon-deep, which is a light-ground colour. */
.vm-header { position: relative; z-index: 30; }
.vm-menu-toggle { display: none; align-items: center; justify-content: center; flex: none; width: 44px; height: 44px; padding: 0; border: 1px solid rgba(255, 140, 198, 0.55); border-radius: 99px; background: transparent; color: var(--white); cursor: pointer; transition: border-color var(--t); }
.vm-menu-toggle:hover { border-color: var(--neon); }
.vm-menu { position: absolute; top: 100%; left: 0; right: 0; max-height: 70dvh; overflow-y: auto; overscroll-behavior: contain; padding: 4px var(--pad) 20px; background: var(--night); border-top: 1px solid rgba(255, 255, 255, 0.12); border-bottom: 2px solid var(--neon); }
.vm-menu a:not([class]) { display: flex; align-items: center; min-height: 48px; border-bottom: 1px solid rgba(255, 255, 255, 0.08); font-size: 17px; font-weight: 500; text-decoration: none; color: #E9DCE6; transition: color var(--t); }
.vm-menu__cta { display: none; padding-top: 16px; }
.vm-menu a:not([class]):hover { color: var(--neon); }

/* ---------- buttons: ink on neon measures 5:1, so the label is near-black, never white ---------- */
.vm-btn { display: inline-flex; align-items: center; justify-content: center; gap: 8px; min-height: 46px; padding: 0 22px; border: 2px solid transparent; border-radius: 999px; font-size: 16px; font-weight: 600; line-height: 1; text-decoration: none; cursor: pointer; transition: transform var(--t), background-color var(--t), color var(--t); }
.vm-btn--neon { background: var(--neon); color: var(--ink); border-color: var(--neon); }
.vm-btn--neon:hover { background: #FF5AAB; transform: translateY(-1px); }
.vm-btn--outline { background: transparent; color: var(--white); border-color: rgba(255, 255, 255, .55); }
.vm-btn--outline:hover { border-color: var(--neon); color: var(--neon); }

/* ---------- hero: the neon sign. This is the one place neon is type. ---------- */
.vm-hero { background: var(--night); color: var(--white); padding: clamp(56px, 11vw, 140px) var(--pad) clamp(52px, 9vw, 120px); }
.vm-kicker { font-size: 13px; font-weight: 600; letter-spacing: 0.22em; text-transform: uppercase; color: var(--neon-deep); }
.vm-kicker--glow { color: var(--neon); }
.vm-h1 { margin-top: 12px; font-family: var(--display); font-size: clamp(54px, 10.5vw, 136px); line-height: 1.02; font-weight: 700; letter-spacing: 0; max-width: 15ch; }
.vm-hero__lede { margin-top: 22px; max-width: 46ch; font-size: clamp(18px, 2vw, 21px); color: #E4D6E2; }
.vm-hero__actions { display: flex; flex-wrap: wrap; gap: 14px; margin-top: 34px; }
.vm-hero__meta { margin-top: 30px; font-size: 14px; letter-spacing: 0.04em; color: var(--glow); }

/* ---------- the work: the archetype this page exists to show ---------- */
.vm-work { padding: clamp(56px, 8vw, 110px) var(--pad); }
.vm-h2 { font-family: var(--display); font-size: clamp(36px, 5vw, 64px); line-height: 1.08; font-weight: 700; letter-spacing: 0; margin-top: 10px; max-width: 19ch; }
.vm-h2--onnight { color: var(--white); }
.vm-lede { margin-top: 16px; max-width: 54ch; color: var(--muted); }
.vm-filter { display: flex; flex-wrap: wrap; gap: 10px; margin-top: clamp(28px, 4vw, 44px); }
/* The radio stays focusable — clipped, not display:none — so the chips are keyboard-reachable. Each radio covers its own
   chip's box, inside a wrapper with the chip (2026-10-20), so focusing a chip brings that chip into view: the four radios
   sat at one point, the filter's corner (where an absolute box with no inset sits in a flex row), and where that point was
   in view and a chip was not, focus scrolled nothing and the chip's ring was drawn below the fold (390 wide, English). */
.vm-filter__item { position: relative; display: flex; }
.vm-filter__input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; overflow: hidden; clip: rect(0 0 0 0); }
.vm-filter__chip { display: inline-flex; align-items: center; min-height: 40px; padding: 0 18px; border: 1.5px solid var(--line); border-radius: 999px; font-size: 15px; font-weight: 500; color: var(--muted); cursor: pointer; transition: border-color var(--t), color var(--t), background-color var(--t); }
.vm-filter__chip:hover { border-color: var(--neon); color: var(--neon-deep); }
/* neon as a FILL with an ink label — 5:1 — which is the only compliant way to mark the active chip */
.vm-filter__input:checked + .vm-filter__chip { background: var(--neon); border-color: var(--neon); color: var(--ink); font-weight: 600; }
.vm-filter__input:focus-visible + .vm-filter__chip { outline: 2px solid var(--neon-deep); outline-offset: 2px; }

.vm-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: clamp(20px, 2.6vw, 34px); margin-top: clamp(28px, 4vw, 44px); }
.vm-card__media { overflow: hidden; border-radius: 14px; background: var(--blush); }
.vm-card__media img, .vm-card__media .ph { display: block; width: 100%; border-radius: 14px; }
.vm-card__title { margin-top: 14px; font-family: var(--text); font-size: 19px; font-weight: 600; letter-spacing: -0.01em; }
.vm-card__note { margin-top: 6px; font-size: 15px; color: var(--muted); }
/* CSS-only filter. If :has() is unsupported every card shows, which is the right failure. */
.vm-work:has(#vm-cat-lashes:checked) .vm-card:not([data-cat="lashes"]),
.vm-work:has(#vm-cat-lifts:checked) .vm-card:not([data-cat="lifts"]),
.vm-work:has(#vm-cat-brows:checked) .vm-card:not([data-cat="brows"]) { display: none; }

/* ---------- prices ---------- */
.vm-prices { padding: clamp(56px, 8vw, 110px) var(--pad); background: var(--blush); }
.vm-table { width: 100%; border-collapse: collapse; margin-top: clamp(28px, 4vw, 44px); }
.vm-table tr { border-top: 1.5px solid var(--line); }
.vm-table tr:last-child { border-bottom: 1.5px solid var(--line); }
.vm-table th, .vm-table td { padding: 18px 0; text-align: left; vertical-align: baseline; font-weight: 400; }
.vm-table__name { display: block; font-family: var(--text); font-size: 19px; font-weight: 600; letter-spacing: -0.01em; }
.vm-table__note { display: block; margin-top: 4px; font-size: 15px; color: var(--muted); max-width: 46ch; }
.vm-table__time { width: 22%; padding-left: 16px; color: var(--muted); font-size: 15px; }
.vm-table__price { width: 20%; text-align: right; font-size: 21px; font-weight: 600; color: var(--neon-deep); letter-spacing: -0.01em; }
.vm-prices__note { margin-top: 22px; font-size: 14px; color: var(--muted); }

/* ---------- booking: back on night, so neon is type again ---------- */
.vm-book { display: grid; grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr); gap: clamp(32px, 5vw, 72px); align-items: start; padding: clamp(56px, 8vw, 110px) var(--pad); background: var(--night); color: var(--white); }
.vm-book__lede { margin-top: 16px; max-width: 42ch; color: #E4D6E2; }
.vm-book__contact { display: flex; flex-wrap: wrap; gap: 10px 26px; margin-top: 26px; }
.vm-book__contact a { display: inline-flex; align-items: center; gap: 8px; color: var(--glow); text-decoration: none; border-bottom: 1px solid rgba(255, 140, 198, .45); transition: color var(--t); }
.vm-book__contact a:hover { color: var(--neon); }
.vm-form { display: grid; gap: 16px; padding: clamp(22px, 3vw, 34px); border: 1.5px solid rgba(255, 140, 198, .32); border-radius: 18px; background: rgba(255, 255, 255, .04); }
.vm-form__row { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 16px; }
.vm-field { display: grid; gap: 7px; font-size: 14px; font-weight: 500; letter-spacing: 0.02em; color: var(--glow); }
/* .36, not .28: a field border is a user-interface component boundary, so WCAG 1.4.11 wants 3:1 against what it
   sits on. Measured on the rendered page (2026-09-22): .28 over the night fill gives 2.44:1; .36 gives 3.06:1. */
.vm-field input, .vm-field select, .vm-field textarea { min-height: 46px; padding: 10px 14px; border: 1.5px solid rgba(255, 255, 255, .36); border-radius: 10px; background: var(--night); color: var(--white); font-size: 16px; font-weight: 400; }
.vm-field textarea { min-height: 88px; resize: vertical; }
.vm-field input:focus, .vm-field select:focus, .vm-field textarea:focus { border-color: var(--neon); }
.vm-field__hint { font-size: 13px; font-weight: 400; color: #C6B4C4; }
.vm-check { display: flex; align-items: center; gap: 10px; font-size: 15px; color: #E4D6E2; }
.vm-check input { width: 24px; height: 24px; accent-color: var(--neon); } /* 20px failed the adopted 24x24 target size (2.5.8). Andy, 2026-09-21 */
.vm-form__actions { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px; margin-top: 4px; }
.vm-form .demo-note { color: var(--glow); margin-top: 0; }

/* ---------- studio ---------- */
.vm-studio { display: grid; grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr); gap: clamp(28px, 5vw, 64px); align-items: center; padding: clamp(56px, 8vw, 110px) var(--pad); }
.vm-studio__photo img, .vm-studio__photo .ph { display: block; width: 100%; border-radius: 18px; }
.vm-studio__photo figcaption { margin-top: 10px; font-size: 14px; color: var(--muted); }
.vm-facts { display: grid; gap: 22px; margin-top: 30px; }
.vm-facts dt { font-size: 13px; font-weight: 600; letter-spacing: 0.16em; text-transform: uppercase; color: var(--neon-deep); }
.vm-facts dd { margin-top: 8px; }
.vm-hours { border-collapse: collapse; }
.vm-hours th, .vm-hours td { padding: 3px 0; text-align: left; font-weight: 400; }
.vm-hours th { padding-right: 22px; color: var(--muted); }

/* ---------- footer ---------- */
.vm-footer { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 12px 24px; padding: 26px var(--pad); background: var(--night); color: #C6B4C4; font-size: 14px; }
.vm-footer__brand { display: inline-flex; align-items: center; gap: 10px; color: var(--white); }
.vm-footer__brand .vm-mark { color: var(--neon); }
.vm-footer b { font-weight: 600; }
.vm .ph { --ph-bg: #F3E2EC; }

@media (max-width: 960px) {
  .vm-book, .vm-studio { grid-template-columns: minmax(0, 1fr); }
  .vm-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .vm-nav { display: none; }
  .vm-menu-toggle { display: inline-flex; }
  .vm-header .vm-btn { margin-left: auto; min-height: 40px; padding: 0 16px; font-size: 15px; }
}
@media (max-width: 600px) {
  .vm-grid { grid-template-columns: minmax(0, 1fr); }
  .vm-form__row { grid-template-columns: minmax(0, 1fr); }
  .vm-table__time { display: none; }
  .vm-table__price { width: 30%; }
  .vm-header { gap: 10px; }
  .vm-header .vm-btn { padding: 0 12px; }
  .vm-form__actions { justify-content: flex-start; }
}
@media (max-width: 359px) {
  /* Logo + CTA + menu toggle ran 5-34px past the screen at 320px (2026-09-24): the CTA moves into the menu, as the real
     site's does; the hero's own "Book a visit" is the first thing under the header. */
  .vm-header > .vm-btn { display: none; } .vm-menu-toggle { margin-left: auto; } .vm-menu__cta { display: block; }
}
@media (prefers-reduced-motion: reduce) { .vm * { transition: none !important; } }
/* Nothing below the media queries — an unconditional rule here would outrank every
   breakpoint above it at equal specificity. That is the bug that put the Pinewhistle form
   140px off a phone screen (docs/DECISIONS.md, 2026-09-14). */
