/* Audience morph. Loaded after styles.css.

   Theme values arrive as --t-* custom properties generated by morph-boot.js
   from themes/<id>.js and scoped to html[data-audience="<id>"]. styles.css
   reads only --hive-* tokens (design-kit/tokens.css), so a theme is a set of
   token overrides, scoped to html[data-audience]: the default Hive theme is
   the untouched token layer, identical by construction. The rules further down
   (texture, hero glow, footage framing, the wheel and the wipe choreography)
   are theme art and motion, not overrides of styles.css. */

/* Registered so theme-to-theme changes interpolate in the no-View-Transition
   fallback (the VT wipe covers the swap everywhere else). */
@property --t-bg { syntax: '<color>'; inherits: true; initial-value: #070c12; }
@property --t-surface { syntax: '<color>'; inherits: true; initial-value: #0b121a; }
@property --t-raised { syntax: '<color>'; inherits: true; initial-value: #111c28; }
@property --t-border { syntax: '<color>'; inherits: true; initial-value: #22303e; }
@property --t-ink { syntax: '<color>'; inherits: true; initial-value: #eff4f9; }
@property --t-muted { syntax: '<color>'; inherits: true; initial-value: #9caab8; }
@property --t-accent { syntax: '<color>'; inherits: true; initial-value: #60c8ff; }
@property --t-accent-strong { syntax: '<color>'; inherits: true; initial-value: #24a9f5; }
@property --t-accent-soft { syntax: '<color>'; inherits: true; initial-value: #163d58; }
@property --t-emphasis { syntax: '<color>'; inherits: true; initial-value: #8bd7fe; }
@property --t-cta { syntax: '<color>'; inherits: true; initial-value: #1475ae; }
@property --t-cta-ink { syntax: '<color>'; inherits: true; initial-value: #ffffff; }
@property --t-cta-glow { syntax: '<color>'; inherits: true; initial-value: #0388d312; }
@property --t-hero-glow1 { syntax: '<color>'; inherits: true; initial-value: transparent; }
@property --t-hero-glow2 { syntax: '<color>'; inherits: true; initial-value: transparent; }
@property --t-texture-opacity { syntax: '<number>'; inherits: true; initial-value: 0; }
@property --t-hero-video-opacity { syntax: '<number>'; inherits: true; initial-value: 1; }
/* Footage bloom radius for the particle-to-video match cut (morph.js). */
@property --m-bloom { syntax: '<length>'; inherits: true; initial-value: 0px; }

/* ---------- Theme token overrides (never active for the default Hive theme) ---------- */
html[data-audience] .ca-design {
  /* Canvas, text, rules and the kit bridge. */
  --hive-color-canvas: var(--t-bg);
  --hive-color-text: var(--t-ink);
  --hive-color-muted: var(--t-muted);
  --hive-color-border: var(--t-border);
  --hive-color-cyan: var(--t-accent);
  --hive-focus-ring: 2px solid var(--t-accent);
  --ca-accent: var(--t-accent);
  --hive-selection-bg: color-mix(in oklab, var(--t-accent) 40%, transparent);
  --hive-hairline: color-mix(in oklab, var(--t-ink) 8%, transparent);
  --hive-border-width: var(--t-border-width);
  /* Shape language. */
  --hive-radius-button: var(--t-button-radius);
  --hive-radius-button-small: var(--t-button-radius);
  --hive-radius-card: var(--t-radius-lg);
  --hive-radius-plan: var(--t-radius-lg);
  --hive-radius-ribbon: var(--t-radius-lg);
  --hive-radius-banner: var(--t-radius);
  --hive-radius-input: var(--t-radius);
  /* Type language. Emphasis stays in the display italic (morph-boot.js). */
  --hive-h1-weight: var(--t-heading-weight);
  --hive-h2-weight: var(--t-heading-weight);
  --hive-tracking-display: var(--t-heading-tracking);
  --hive-tracking-heading: var(--t-heading-tracking);
  --hive-em-text: var(--t-emphasis);
  --hive-eyebrow-transform: var(--t-eyebrow-transform);
  --hive-tracking-eyebrow: var(--t-eyebrow-tracking);
  /* Hero, header and glass. */
  --hive-hero-scrim: linear-gradient(90deg, var(--t-bg) 0%, color-mix(in srgb, var(--t-bg) 92%, transparent) 30%, color-mix(in srgb, var(--t-bg) calc(var(--t-hero-scrim, 60%) * .67), transparent) 58%, color-mix(in srgb, var(--t-bg) 12%, transparent) 100%), linear-gradient(180deg, color-mix(in srgb, var(--t-bg) 80%, transparent) 0%, transparent 26%, transparent 68%, var(--t-bg) 100%);
  --hive-hero-scrim-compact: linear-gradient(180deg, color-mix(in srgb, var(--t-bg) 95%, transparent) 0%, color-mix(in srgb, var(--t-bg) 72%, transparent) 40%, color-mix(in srgb, var(--t-bg) 35%, transparent) 72%, var(--t-bg) 100%);
  --hive-hero-video-filter: var(--t-hero-filter);
  --hive-hero-video-opacity: var(--t-hero-video-opacity);
  --hive-hero-glow-1: var(--t-hero-glow1);
  --hive-hero-glow-2: var(--t-hero-glow2);
  --hive-hero-control-bg: color-mix(in oklab, var(--t-bg) 60%, transparent);
  --hive-hero-control-border: color-mix(in oklab, var(--t-ink) 14%, transparent);
  --hive-hero-control-text: color-mix(in oklab, var(--t-ink) 80%, var(--t-muted));
  --hive-header-bg: linear-gradient(180deg, color-mix(in oklab, var(--t-bg) 70%, transparent), transparent);
  --hive-header-scrolled-bg: color-mix(in oklab, var(--t-bg) 78%, transparent);
  --hive-header-scrolled-border: color-mix(in oklab, var(--t-ink) 11%, transparent);
  --hive-glass-fill: color-mix(in oklab, var(--t-ink) 6%, transparent);
  --hive-glass-edge: color-mix(in oklab, var(--t-ink) 14%, transparent);
  --hive-glass-highlight: color-mix(in oklab, var(--t-ink) 22%, transparent);
  --hive-glass-deep: color-mix(in oklab, var(--t-bg) 55%, transparent);
  --hive-lens-position: var(--t-hero-position);
  --hive-hero-eyebrow-text: color-mix(in oklab, var(--t-ink) 70%, var(--t-muted));
  --hive-hero-lede-text: var(--t-muted);
  --hive-hero-note-text: var(--t-muted);
  --hive-nav-link-hover: var(--t-accent);
  --hive-dot-bg: var(--t-accent);
  --hive-shadow-dot: 0 0 12px color-mix(in oklab, var(--t-accent) 40%, transparent);
  /* Buttons: CTA colour pair. */
  --hive-button-bg: var(--t-raised);
  --hive-button-border: var(--t-border);
  --hive-button-text: var(--t-ink);
  --hive-button-hover-border: var(--t-accent);
  --hive-button-outline-bg: var(--t-raised);
  --hive-button-outline-border: var(--t-border);
  --hive-primary-bg: var(--t-cta);
  --hive-primary-text: var(--t-cta-ink);
  --hive-primary-border: color-mix(in oklab, var(--t-cta), white 22%);
  --hive-shadow-primary: inset 0 1px 0 #ffffff26, 0 6px 26px color-mix(in oklab, var(--t-cta-glow) 30%, transparent);
  --hive-primary-hover-bg: color-mix(in oklab, var(--t-cta), white 10%);
  --hive-primary-hover-border: color-mix(in oklab, var(--t-cta), white 35%);
  --hive-shadow-primary-hover: 0 8px 30px color-mix(in oklab, var(--t-cta-glow) 45%, transparent);
  --hive-mobile-cta-bg: var(--t-cta);
  --hive-mobile-cta-border: var(--t-cta);
  --hive-mobile-cta-text: var(--t-cta-ink);
  /* Bands and sections. */
  --hive-promise-bg: var(--t-surface);
  --hive-promise-border: var(--t-border);
  --hive-promise-text: var(--t-ink);
  --hive-promise-em: var(--t-ink);
  --hive-promise-item: var(--t-ink);
  --hive-promise-icon: var(--t-accent);
  --hive-promise-underline: color-mix(in oklab, var(--t-accent) 45%, transparent);
  --hive-example-bg: var(--t-surface);
  --hive-example-border: var(--t-border);
  --hive-example-panel-bg: var(--t-raised);
  --hive-example-label: var(--t-emphasis);
  --hive-example-text: var(--t-ink);
  --hive-step-border: var(--t-border);
  --hive-step-dot: var(--t-accent);
  --hive-shadow-step-dot: 0 0 10px color-mix(in oklab, var(--t-accent) 30%, transparent);
  --hive-step-number: var(--t-emphasis);
  --hive-audit-summary: var(--t-ink);
  --hive-audit-item: var(--t-ink);
  --hive-audit-strong: var(--t-emphasis);
  --hive-plans-bg: var(--t-surface);
  --hive-plans-border: var(--t-border);
  --hive-banner-text: var(--t-ink);
  --hive-banner-border: color-mix(in oklab, var(--t-accent) 45%, var(--t-border));
  --hive-banner-bg: color-mix(in oklab, var(--t-accent) 12%, var(--t-raised));
  --hive-plan-description: var(--t-muted);
  --hive-price-caption: var(--t-muted);
  --hive-price-period: var(--t-muted);
  --hive-ribbon-bg: var(--t-cta);
  --hive-ribbon-border: var(--t-cta);
  --hive-ribbon-text: var(--t-cta-ink);
  --hive-explainer-term: var(--t-ink);
  --hive-faq-link: var(--t-muted);
  --hive-footer-bg: color-mix(in oklab, var(--t-bg), black 25%);
  /* Contact and the form. */
  --hive-contact-bg: radial-gradient(ellipse at 12% 90%, color-mix(in oklab, var(--t-accent) 14%, transparent), transparent 65%), var(--t-surface);
  --hive-contact-border: var(--t-border);
  --hive-offer-note-text: var(--t-ink);
  --hive-offer-note-rule: var(--t-accent);
  --hive-link-text: var(--t-accent);
  --hive-form-alt-link: var(--t-accent);
  --hive-contact-panel-bg: radial-gradient(ellipse at 100% 0%, color-mix(in oklab, var(--t-accent) 20%, transparent), transparent 65%), linear-gradient(145deg, var(--t-raised), var(--t-surface));
  --hive-contact-panel-border: color-mix(in oklab, var(--t-accent) 45%, var(--t-border));
  --hive-contact-panel-text: var(--t-muted);
  --hive-form-note-text: var(--t-muted);
  --hive-form-label: var(--t-ink);
  --hive-input-bg: var(--t-bg);
  --hive-input-border: var(--t-border);
  --hive-input-text: var(--t-ink);
  --hive-input-hover-border: color-mix(in oklab, var(--t-accent) 60%, var(--t-border));
  --hive-input-focus-border: var(--t-accent);
  --hive-input-placeholder: var(--t-muted);
  --hive-result-bg: var(--t-raised);
  --hive-result-border: var(--t-border);
}
/* Elements that set their own tokens (tone tints, the honey panel) are
   overridden at the element, where the theme outranks the tint. */
html[data-audience] .contact-panel {
  --hive-focus-ring: 2px solid var(--t-accent);
  --hive-primary-bg: var(--t-cta);
  --hive-primary-text: var(--t-cta-ink);
  --hive-primary-border: color-mix(in oklab, var(--t-cta), white 22%);
  --hive-shadow-primary: inset 0 1px 0 #ffffff26, 0 6px 26px color-mix(in oklab, var(--t-cta-glow) 30%, transparent);
  --hive-primary-hover-bg: color-mix(in oklab, var(--t-cta), white 10%);
  --hive-primary-hover-border: color-mix(in oklab, var(--t-cta), white 35%);
  --hive-shadow-primary-hover: 0 8px 30px color-mix(in oklab, var(--t-cta-glow) 45%, transparent);
}
html[data-audience] .button-honey {
  --hive-focus-ring: 2px solid var(--t-accent);
  --hive-primary-bg: var(--t-cta);
  --hive-primary-text: var(--t-cta-ink);
  --hive-primary-border: color-mix(in oklab, var(--t-cta), white 22%);
  --hive-shadow-primary: inset 0 1px 0 #ffffff26, 0 6px 26px color-mix(in oklab, var(--t-cta-glow) 30%, transparent);
  --hive-primary-hover-bg: color-mix(in oklab, var(--t-cta), white 10%);
  --hive-primary-hover-border: color-mix(in oklab, var(--t-cta), white 35%);
  --hive-shadow-primary-hover: 0 8px 30px color-mix(in oklab, var(--t-cta-glow) 45%, transparent);
}
html[data-audience] .outcome-card {
  --hive-outcome-accent: var(--t-accent);
  --hive-outcome-border: var(--t-border);
  --hive-outcome-bg: linear-gradient(145deg, color-mix(in oklab, var(--t-accent) 10%, var(--t-raised)), var(--t-surface));
}
html[data-audience] .outcome-card:nth-child(2) {
  --hive-outcome-accent: var(--t-emphasis);
  --hive-outcome-border: color-mix(in oklab, var(--t-accent) 35%, var(--t-border));
  --hive-outcome-bg: linear-gradient(145deg, color-mix(in oklab, var(--t-accent) 18%, var(--t-raised)), var(--t-surface));
}
html[data-audience] .outcome-card:nth-child(3) { --hive-outcome-accent: var(--t-accent-soft); }
html[data-audience] .pricing-card {
  --hive-plan-border: var(--t-border);
  --hive-plan-bg: linear-gradient(150deg, color-mix(in oklab, var(--t-accent) 6%, transparent), transparent 65%), var(--t-raised);
  --hive-plan-highlight-border: var(--t-accent);
  --hive-shadow-plan-highlight: 0 0 30px color-mix(in oklab, var(--t-accent) 20%, transparent);
  --hive-plan-label: var(--t-accent);
  --hive-plan-icon: var(--t-accent);
  --hive-plan-check: var(--t-accent);
  --hive-plan-divider: var(--t-border);
  --hive-plan-button-bg: var(--t-surface);
  --hive-plan-button-border: var(--t-border);
  --hive-plan-button-text: var(--t-ink);
  --hive-plan-button-hover-border: var(--t-accent);
}
html[data-audience] .pricing-card.featured { --hive-plan-border: var(--t-accent); }

/* ---------- Theme art (texture, glow, footage framing) ---------- */
html[data-audience] {
  /* Texture: one seamless single-colour SVG tile per theme, masked so it takes --t-accent. */
  :is(.hero, .section, .promise-strip) { position: relative; }
  /* "Felt more than seen": capped opacity, and a second mask layer keeps the
     tile away from section edges and (in the hero) the header and copy column. */
  :is(.hero, .section, .promise-strip)::before {
    content: ''; position: absolute; inset: 0; z-index: 0; pointer-events: none;
    background-color: var(--t-accent);
    -webkit-mask: var(--t-texture) repeat, linear-gradient(180deg, transparent, #000 22%, #000 78%, transparent);
    -webkit-mask-composite: source-in;
    mask: var(--t-texture) repeat, linear-gradient(180deg, transparent, #000 22%, #000 78%, transparent);
    mask-composite: intersect;
    opacity: min(var(--t-texture-opacity), .045);
  }
  .hero::before {
    -webkit-mask: var(--t-texture) repeat, radial-gradient(ellipse 48% 55% at 74% 56%, #000 20%, transparent 100%);
    -webkit-mask-composite: source-in;
    mask: var(--t-texture) repeat, radial-gradient(ellipse 48% 55% at 74% 56%, #000 20%, transparent 100%);
    mask-composite: intersect;
  }
  :is(.section, .promise-strip) > .container { position: relative; }
}
html[data-audience] .hero-art .morph-art-video { object-position: var(--t-hero-position); transform: scale(var(--t-hero-scale)); transform-origin: var(--t-hero-position); }
/* Audience headlines run longer than "Website, sorted.", and the italic line
   is nowrap in styles.css: on phones they step down one size on the scale. */
@media (max-width: 700px) {
  html[data-audience] .hero h1 { font-size: var(--hive-type-6); }
}

/* ---------- The lens ----------
   The industry chips orbit a circular porthole that previews the industry under
   the pointer (morph-selector.js owns the turning, the preview, the confirm and
   the dock). Geometry: chips sit at cos/sin x orbit, and the orbit is derived
   from the porthole and chip sizes so the two never overlap. Colours follow the
   theme tokens (--t-*), whose @property initial values are the default palette. */
.morph-picker {
  --port: var(--hive-lens-port-size);
  --chip-w: var(--hive-lens-chip-width);
  --orbit: calc(var(--port) / 2 + var(--chip-w) / 2 + var(--hive-lens-ring-gap));
  --lens: calc(var(--orbit) * 2 + var(--hive-lens-margin));
  --dial-ease: cubic-bezier(.4, 0, .2, 1);
  position: relative; z-index: 1; justify-self: end; margin: 0;
  width: var(--lens); padding-bottom: 62px; color: var(--t-ink);
}
.morph-picker[hidden] { display: none; }
.morph-picker[data-state="collapsed"] { visibility: hidden; }
.lens-dial { position: relative; width: var(--lens); height: var(--lens); display: grid; place-items: center; border-radius: 50%; touch-action: none; user-select: none; -webkit-user-select: none; will-change: transform; }
.morph-picker.is-dragging .lens-dial { cursor: grabbing; }
.lens-ticks {
  position: absolute; inset: calc(50% - var(--orbit) - 36px); border-radius: 50%; pointer-events: none; opacity: .7;
  background: repeating-conic-gradient(from -.4deg, color-mix(in oklab, var(--t-accent) 45%, transparent) 0 .8deg, transparent .8deg 7.5deg);
  -webkit-mask: radial-gradient(circle, transparent calc(50% - 7px), #000 calc(50% - 6px), #000 50%, transparent calc(50% + 1px));
  mask: radial-gradient(circle, transparent calc(50% - 7px), #000 calc(50% - 6px), #000 50%, transparent calc(50% + 1px));
}
.lens-ticks::after { content: ''; position: absolute; inset: 6px; border-radius: 50%; border: 1px solid color-mix(in oklab, var(--t-accent) 18%, transparent); }
.morph-pointer {
  position: absolute; left: calc(50% - 5px); top: calc(50% - var(--orbit) - 72px);
  width: 10px; height: 10px; rotate: 45deg; border-radius: 1px;
  background: var(--t-accent); box-shadow: 0 0 18px var(--t-accent);
}
.morph-chips {
  position: absolute; inset: 0; border-radius: 50%; cursor: grab;
  rotate: var(--dial-rotation, 0deg);
  transition: rotate var(--dial-turn-duration, .85s) var(--dial-ease);
}
.morph-picker.is-dragging :is(.morph-chips, .morph-chip) { transition: none; }
.morph-stop {
  position: absolute; inset: 0; display: grid; place-items: center; pointer-events: none;
  translate: calc(var(--stop-x) * var(--orbit)) calc(var(--stop-y) * var(--orbit));
}
.morph-chip {
  pointer-events: auto; width: var(--chip-w); min-height: 46px; padding: 8px 10px;
  border: 1px solid var(--hive-glass-edge); border-radius: 999px;
  background: var(--hive-glass-deep); color: var(--t-ink);
  -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
  font-size: var(--hive-type-0); line-height: 1.25; font-weight: 500; text-wrap: balance; overflow-wrap: normal; cursor: pointer;
  rotate: calc(-1 * var(--dial-rotation, 0deg));
  transition: rotate var(--dial-turn-duration, .85s) var(--dial-ease), background-color .3s, border-color .3s, box-shadow .3s, scale .25s cubic-bezier(.16, 1, .3, 1);
  box-shadow: inset 0 1px 0 var(--hive-glass-highlight), 0 8px 24px -12px #000c;
  -webkit-tap-highlight-color: transparent;
}
.morph-chip:hover { border-color: var(--hive-glass-highlight); scale: 1.04; }
.morph-chip[aria-pressed="true"] {
  border-color: color-mix(in oklab, var(--t-accent) 70%, transparent);
  background: color-mix(in oklab, var(--t-accent) 16%, var(--hive-glass-deep));
  box-shadow: inset 0 1px 0 var(--hive-glass-highlight), 0 0 0 4px color-mix(in oklab, var(--t-accent) 10%, transparent), 0 0 36px color-mix(in oklab, var(--t-accent) 35%, transparent);
}
/* The porthole: a still of the crystals under the two footage slots that
   morph-art.js cross-fades, with a glass highlight and an inner vignette. */
.lens-port {
  position: relative; width: var(--port); height: var(--port); border-radius: 50%; overflow: hidden; isolation: isolate;
  background: var(--t-bg);
  box-shadow: 0 0 0 1px color-mix(in oklab, var(--t-accent) 55%, transparent), 0 0 0 7px color-mix(in oklab, var(--t-bg) 70%, transparent), 0 0 0 8px color-mix(in oklab, var(--t-accent) 18%, transparent),
    0 40px 90px -30px color-mix(in oklab, var(--t-accent) 55%, black), 0 0 140px color-mix(in oklab, var(--t-accent) 16%, transparent);
  transition: box-shadow .6s;
}
.lens-port-still, .lens-port .morph-art-video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: var(--lens-pos, 74% 50%); }
.lens-port .morph-art-video { opacity: 0; transition: opacity .7s var(--dial-ease); }
.lens-port .morph-art-video.is-active { opacity: 1; }
.lens-port::before {
  content: ''; position: absolute; inset: 0; border-radius: 50%; z-index: 2; pointer-events: none; mix-blend-mode: screen;
  background: radial-gradient(ellipse 60% 45% at 30% 18%, color-mix(in oklab, white 28%, transparent), transparent 60%);
}
.lens-port::after {
  content: ''; position: absolute; inset: 0; border-radius: 50%; z-index: 2; pointer-events: none;
  box-shadow: inset 0 0 0 1px color-mix(in oklab, white 14%, transparent), inset 0 -40px 70px -20px color-mix(in oklab, black 75%, transparent), inset 0 30px 60px -30px color-mix(in oklab, black 35%, transparent);
}
/* The caption sits where the circle is still wide enough for the longest
   industry name (a chord 44 px up is 220 px across on the 320 px porthole). */
.lens-cap {
  position: absolute; left: 50%; bottom: 44px; translate: -50%; z-index: 3;
  display: inline-flex; align-items: center; gap: 9px; max-width: calc(var(--port) * .7);
  padding: 8px 14px 8px 11px; border-radius: 999px; white-space: nowrap;
  background: color-mix(in oklab, var(--t-bg) 62%, transparent); border: 1px solid var(--hive-glass-edge);
  -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
  font-family: var(--hive-font-display); font-style: italic; font-weight: 300; font-size: var(--hive-type-1); line-height: 1; color: var(--t-ink);
  box-shadow: inset 0 1px 0 var(--hive-glass-highlight);
}
.lens-cap-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.lens-cap i { flex: none; width: 7px; height: 7px; border-radius: 50%; background: var(--t-accent); box-shadow: 0 0 12px var(--t-accent); }
/* The preview/current state is read to assistive tech (the live region) and
   shown by the confirm button; inside the porthole it never fits beside the name. */
.lens-cap-state { display: none; }
/* Previous, confirm, next. */
.lens-foot { position: absolute; left: 50%; bottom: 0; translate: -50%; display: flex; align-items: center; gap: 14px; white-space: nowrap; }
.lens-arrow, .lens-confirm {
  display: inline-flex; align-items: center; justify-content: center; min-height: 44px; padding: 0;
  border: 1px solid var(--hive-glass-edge); border-radius: 999px; background: var(--hive-glass-fill); color: var(--t-ink);
  -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
  box-shadow: inset 0 1px 0 var(--hive-glass-highlight);
  transition: border-color .3s, background-color .3s, translate .25s cubic-bezier(.16, 1, .3, 1);
}
.lens-arrow { width: 44px; }
.lens-arrow .icon { width: 16px; height: 16px; }
.lens-confirm { gap: 12px; padding: 0 20px; font-size: var(--hive-type-0); font-weight: 500; }
.lens-confirm .icon { width: 16px; height: 16px; transition: transform .25s; }
.lens-arrow:hover, .lens-confirm:hover { border-color: var(--hive-glass-highlight); background: var(--hive-glass-edge); translate: 0 -1px; }
.lens-confirm:hover .icon { transform: translateX(3px); }
.morph-picker button:focus-visible, .lens-dock:focus-visible { outline: 2px solid var(--t-accent); outline-offset: 4px; }
/* Under the copy (laptops and phones): centred, and held at the same height
   for every theme by the lock morph.js measures (--m-slack), so the lens
   never jumps while the headline reflows during a morph. */
@media (max-width: 1199px) {
  .morph-picker { justify-self: center; margin-top: var(--m-slack, 0px); }
}
@media (max-width: 700px) {
  .morph-picker { --port: var(--hive-lens-port-size-phone); --chip-w: var(--hive-lens-chip-width-phone); --orbit: calc(var(--port) / 2 + var(--chip-w) / 2 + var(--hive-lens-ring-gap-phone)); --lens: calc(var(--orbit) * 2 + var(--hive-lens-margin-phone)); padding-bottom: 58px; }
  .morph-chip { min-height: 42px; padding: 6px 5px; }
  .morph-pointer { top: calc(50% - var(--orbit) - 52px); }
  .lens-ticks { inset: calc(50% - var(--orbit) - 28px); }
  .lens-cap { display: none; }
  .lens-foot { gap: 10px; }
  .lens-confirm { padding: 0 16px; }
}
@media (max-width: 370px) {
  .morph-picker { --port: 150px; }
}
@media (prefers-reduced-motion: reduce) {
  .morph-picker, .morph-picker * { animation: none !important; transition: none !important; }
}
/* Keep the lens live while the surrounding page changes: the wipe grows from
   its porthole and it stays put above the wipe until it docks. */
html.morph-vt .morph-picker { view-transition-name: morph-picker; }
::view-transition-old(morph-picker) { display: none; }
::view-transition-new(morph-picker), ::view-transition-group(morph-picker) { animation: none; }

/* ---------- Choreography helpers ---------- */
/* Only the hero canvas, headline and lede render live during the wipe (see
   morph.js); everything else, CTA and chips included, is revealed by the wipe
   itself, so no new style lands before the wipe front reaches it. */
html.morph-vt .hero-particles { view-transition-name: morph-particles; }
/* WebKit (morph-wk): the headline and lede stay in the page and morph inside
   the wipe (their timing already follows the wipe front), so the copy never
   depends on WebKit painting a live layer. */
html.morph-vt:not(.morph-wk) .hero h1 { view-transition-name: morph-h1; }
html.morph-vt:not(.morph-wk) .hero-description { view-transition-name: morph-lede; }
.morph-ring { view-transition-name: morph-ring; }
::view-transition-old(morph-particles) { display: none; }
/* Safety net (WebKit): the old headline/lede snapshots fade out instead of
   vanishing, so the copy is never blank if a live layer fails to paint. The
   live layers start on the same old words, so the handover is invisible. */
::view-transition-old(morph-h1),
::view-transition-old(morph-lede) { animation: m-vt-out 180ms ease-out both; }
@keyframes m-vt-out { to { opacity: 0; } }
::view-transition-new(morph-particles),
::view-transition-new(morph-h1),
::view-transition-new(morph-lede),
::view-transition-new(morph-ring),
::view-transition-group(morph-particles),
::view-transition-group(morph-h1),
::view-transition-group(morph-lede),
::view-transition-group(morph-ring) { animation: none; }
/* Luminous edge riding the wipe, in the incoming accent. It starts as the
   pressed chip's own outline and grows into the wipe circle (morph.js). */
.morph-ring {
  position: fixed; z-index: 60; left: 0; top: 0; width: 0; height: 0; pointer-events: none; border-radius: 50%;
  border: 1.5px solid color-mix(in oklab, var(--t-accent), white 35%);
  box-shadow: 0 0 18px 2px color-mix(in oklab, var(--t-accent) 70%, transparent),
              inset 0 0 26px 2px color-mix(in oklab, var(--t-accent) 45%, transparent);
  box-sizing: border-box;
}
/* Measuring every theme's hero block (morph.js) must not start transitions. */
html.morph-measure *, html.morph-measure *::before, html.morph-measure *::after { transition: none !important; }
/* The root wipe is driven from JS (clip-path circle); switch off the default fade. */
html.morph-vt:not(.morph-rm)::view-transition-old(root),
html.morph-vt:not(.morph-rm)::view-transition-new(root) { animation: none; mix-blend-mode: normal; }
/* Hold the first mask before JS starts the wipe, including snapshot setup. */
html.morph-vt:not(.morph-rm)::view-transition-new(root) { clip-path: var(--m-wipe-start, none); }
/* Reduced motion: keep only a short cross-fade. */
html.morph-rm::view-transition-old(root),
html.morph-rm::view-transition-new(root) { animation-duration: 180ms; }

/* No View Transitions: registered tokens interpolate between themes instead. */
html.morph-tween {
  transition-property: --t-bg, --t-surface, --t-raised, --t-border, --t-ink, --t-muted, --t-accent, --t-accent-strong, --t-accent-soft, --t-emphasis, --t-cta, --t-cta-ink, --t-cta-glow, --t-hero-glow1, --t-hero-glow2, --t-texture-opacity, --t-hero-video-opacity;
  transition-duration: var(--m-tween, .7s);
  transition-timing-function: cubic-bezier(.4, 0, .2, 1);
}

/* Masked line rise for headings. Padding keeps descenders and italic overhang
   inside the mask; the negative margin cancels it in layout. */
.m-stack { display: block; position: relative; }
.m-stack > span { display: block; }
.m-stack > .m-old { position: absolute; inset: 0 0 auto; }
.m-line { display: block; overflow: clip; overflow-clip-margin: .04em; padding-block: .02em .1em; margin-block: -.02em -.1em; }
.m-line > span { display: inline-block; }
.m-word { display: inline-block; }
/* Word morph (headings, eyebrows): the new sentence is in flow; the outgoing
   one sits on top, absolutely positioned, in its own frozen typography. */
.m-wm { display: block; position: relative; }
.m-wm-inline { display: inline-block; position: relative; }
.m-wm-old { position: absolute; left: 0; top: 0; width: 100%; pointer-events: none; }
.m-w { display: inline-block; will-change: transform, opacity; }
.m-wm-old .m-w.m-kept { visibility: hidden; }
/* Crossfade stack for short labels (CTA) and body copy. */
.m-xf { display: inline-grid; justify-items: start; white-space: nowrap; }
.m-xf > span { grid-area: 1 / 1; }
.m-xb { display: block; position: relative; }
.m-xb > .m-old { position: absolute; left: 0; top: 0; width: 100%; pointer-events: none; }
/* Hero art: crystal video plus two theme slots (A/B), stacked and cross-faded.
   They share the crystal's .hero-art sizing, blend mode and scrim (::after). */
.hero-art video { transition: opacity .65s ease; }
.morph-art-video { position: absolute; inset: 0; opacity: 0; }
.morph-art-video.is-active { opacity: 1; }
html[data-audience] .morph-art-video.is-active { filter: var(--t-hero-filter); opacity: var(--t-hero-video-opacity); }
#hero-video.is-hidden { opacity: 0 !important; }
/* While particles hold the motif, the footage steps back to 30%; when they
   release, it blooms from the subject's point outwards (the match cut), as
   part of the same event. --m-bloom and --m-subject-x/y come from morph.js. */
html.morph-bloom .hero-art video {
  -webkit-mask-image: radial-gradient(circle at var(--m-subject-x, 70%) var(--m-subject-y, 50%), #000 calc(var(--m-bloom) * .5), rgb(0 0 0 / .3) var(--m-bloom));
  mask-image: radial-gradient(circle at var(--m-subject-x, 70%) var(--m-subject-y, 50%), #000 calc(var(--m-bloom) * .5), rgb(0 0 0 / .3) var(--m-bloom));
}
