/* ============================================================
   Handshake v1 → v2 bridge

   The migration problem: 19 pages and ~1.5 MB of CSS reference v1 token
   names (--hair 289x, --ink-3 283x, --panel, --accent, --r-md, --sp-*).
   Rewriting that markup page by page would take weeks and break flows.

   But v1 already routes almost everything through custom properties. So
   instead of rewriting pages, this file REDEFINES the v1 names in terms of
   v2 roles. Every rule that says `color: var(--ink-2)` starts resolving to
   the v2 secondary foreground with no markup change at all.

   What this file deliberately does NOT do:
     - it does not load hs-base.css (its reset would restyle v1 layout)
     - it does not restyle any v1 class, only tokens
     - it does not touch spacing scales that already agree between versions

   Load order on a bridged page:
       ds/hs-fonts.css
       ds/hs-tokens.css      ← v2 values, scoped to [data-hs="2"]
       ds/hs-bridge.css      ← this file, maps v1 names onto them
       ...the page's own v1 stylesheets...

   The page's <html> needs data-hs="2" plus a surface, or the v2 tokens this
   file references will not resolve.
   ============================================================ */

/* ---------------------------------------------------------------------------
   The v1 → v2 token map.

   This was written twice: once on [data-hs="2"], then again, verbatim, on
   .surface-admin / .surface-user — because surfaces.css declares the same
   names on those classes and out-specifies the root. Sixty-two of sixty-two
   declarations were byte-identical, so every token change had to be made in
   two places or the app went half-converted.

   A selector list fixes it. `[data-hs="2"] .surface-admin` still carries the
   specificity needed to beat surfaces.css; it just no longer needs its own
   copy of the map to do it.
   --------------------------------------------------------------------------- */
[data-hs="2"],
[data-hs="2"] .surface-admin,
[data-hs="2"] .surface-user {
  /* ---- Surfaces ------------------------------------------------------ */
  --canvas: var(--hs-bg-canvas);
  --panel: var(--hs-glass-card);
  --panel-2: var(--hs-glass-recessed);
  --panel-3: var(--hs-accent-subtle);
  --hs-bg: var(--hs-bg-canvas);
  --hs-bg-sunken: var(--hs-glass-sunken);
  --hs-bg-raised: var(--hs-glass-card);

  /* ---- Hairlines ----------------------------------------------------- */
  --hair: var(--hs-border-subtle);
  --hair-2: var(--hs-border-default);
  --hs-border: var(--hs-border-default);
  --border-hair: var(--hs-border-subtle);
  --hs-neutral-200: var(--hs-border-default);

  /* ---- Ink ----------------------------------------------------------- */
  --ink: var(--hs-fg-primary);
  --ink-2: var(--hs-fg-secondary);
  --ink-3: var(--hs-fg-tertiary);
  --hs-text: var(--hs-fg-primary);
  --hs-text-muted: var(--hs-fg-secondary);
  --hs-neutral-800: var(--hs-fg-primary);
  --hs-neutral-500: var(--hs-fg-tertiary);
  --fg-on-light: var(--hs-fg-primary);
  --fg-muted: var(--hs-fg-tertiary);
  --v2-text-primary: var(--hs-fg-primary);
  --v2-text-secondary: var(--hs-fg-secondary);

  /* ---- Accent -------------------------------------------------------- */
  --accent: var(--hs-accent-solid);
  --accent-ink: var(--hs-fg-on-accent);
  --accent-tint: var(--hs-accent-muted);
  --accent-tint-2: var(--hs-accent-subtle);
  --hs-aqua: var(--hs-aqua-400);
  --hs-aqua-bright: var(--hs-aqua-300);
  --hs-aqua-deep: var(--hs-aqua-600);

  /* --accent-2 means Everglade on the admin surface and Jasmine on the
     consumer one. Console keeps the purple reading; everything else takes
     the deep green so the mapping is never wrong, only conservative. */
  --accent-2: var(--hs-accent-ink);
  --hs-jasmine: var(--hs-accent2-solid);
  --hs-indigo: var(--hs-accent2-ink);

  /* ---- Status -------------------------------------------------------- */
  --pass: var(--hs-success-fg);
  --pass-tint: var(--hs-success-bg);
  --fail: var(--hs-danger-fg);
  --fail-tint: var(--hs-danger-bg);
  --hs-red: var(--hs-danger-solid);
  --hs-amber: var(--hs-warning-solid);
  --hs-blue: var(--hs-info-solid);

  /* ---- Radii — v1 and v2 agree on every step ------------------------- */
  --r-xs: var(--hs-radius-xs);
  --r-sm: var(--hs-radius-sm);
  --r-md: var(--hs-radius-md);
  --r-lg: var(--hs-radius-lg);
  --r-xl: var(--hs-radius-xl);
  --r-2xl: var(--hs-radius-2xl);
  --r-pill: var(--hs-radius-pill);

  /* ---- Elevation ----------------------------------------------------- */
  --shadow: var(--hs-glass-lift);
  --shadow-sm: var(--hs-elevation-raised);
  --shadow-card: var(--hs-glass-lift);
  --hs-shadow-card: var(--hs-glass-lift);

  /* ---- Type ---------------------------------------------------------- */
  --font: var(--hs-font-body);
  --hs-font: var(--hs-font-body);
  --font-body: var(--hs-font-body);
  --font-ui: var(--hs-font-ui);
  --font-display: var(--hs-font-display);
  --font-mono: var(--hs-font-mono);

  /* ---- Dock ----------------------------------------------------------
     52px, matching what the dock actually measures. A size token that
     disagrees with the thing it names is worse than no token. */
  --hs-dock-h: 52px;

  /* ---- Motion -------------------------------------------------------- */
  --hs-ease: var(--hs-ease-standard);
  --hs-dur: var(--hs-duration-base);
  --hs-dur-fast: var(--hs-duration-fast);
  --hs-dur-slow: var(--hs-duration-slow);
}

/* Root-only. The scroll-lander declares these on <body>, so they never need
   the surface-class escalation the map above does. */
[data-hs="2"] {
  --v2-font-display: var(--hs-font-display);
  --v2-font-ui: var(--hs-font-ui);
  --hero-display: var(--hs-font-display);
  --sans: var(--hs-font-body);
  --mono: var(--hs-font-mono);
}

/* v1's --sp-* scale is identical to v2's --hs-space-*, so it is aliased
   rather than remapped — no visual change, just one source of truth. */
[data-hs="2"] {
  --sp-1: var(--hs-space-1);
  --sp-2: var(--hs-space-2);
  --sp-3: var(--hs-space-3);
  --sp-4: var(--hs-space-4);
  --sp-5: var(--hs-space-5);
  --sp-6: var(--hs-space-6);
  --sp-8: var(--hs-space-8);
  --sp-10: var(--hs-space-10);
  --sp-12: var(--hs-space-12);
  --sp-16: var(--hs-space-16);
}

/* ---- Page canvas ----------------------------------------------------
   v1 pages paint their own background. Give bridged pages the v2 wash and
   texture, matching the surface they declare.

   When --hs-bg-photo is set (brand texture PNGs), the baked photo replaces the
   CSS wash/texture layers — those are already composited into the image. */
[data-hs="2"] body,
[data-hs="2"] body.hs-portal-body {
  background-color: var(--hs-bg-canvas) !important;
  /* Wash first: --hs-bg-texture is TWO gradients, so a two-value position list
     gets repeated and the wash never receives its own offset. */
  background-image: var(--hs-bg-tint, none), var(--hs-bg-texture, none) !important;
  /* Every one of these needs !important, not just the image. v1 paints the body
     with a `background:` SHORTHAND, which resets each longhand it omits back to
     its initial value — so repeat fell to `repeat` and size to `auto`, and the
     wash TILED at its natural size instead of stretching. On a short page one
     tile covers the viewport and it looks fine; on a long page you get a hard
     horizontal seam at every tile boundary. The layer set only works intact. */
  background-repeat: no-repeat, no-repeat, no-repeat !important;
  background-size: 100% var(--hs-wash-scale, 320%), var(--hs-texture-scale, 150% 150%) !important;
  background-position: 0% var(--hs-wash-shift, 0%), var(--hs-texture-pos, 0% 0%), var(--hs-texture-pos, 0% 0%) !important;
  background-attachment: fixed, fixed !important;
  font-family: var(--hs-font-body);
  color: var(--hs-fg-primary);
}

[data-hs="2"][data-hs-bg="photo"] body,
[data-hs="2"][data-hs-bg="photo"] body.hs-portal-body {
  background-color: var(--hs-bg-canvas) !important;
  background-image: var(--hs-bg-photo, none) !important;
  background-repeat: no-repeat !important;
  background-size: cover !important;
  background-position: center !important;
  background-attachment: fixed !important;
}

/* Mobile photo canvas — avoid the zoom flash.
   iOS/WebKit often ignores background-attachment:fixed, so `cover` on <body>
   resolves against the growing document instead of the viewport: first paint
   looks viewport-fit, then content mounts and the image snaps. Paint the
   photo on a real position:fixed layer sized to the viewport with cover so
   it stays edge-to-edge as a true background. */
@media (max-width: 720px) {
  [data-hs="2"][data-hs-bg="photo"] {
    background-color: var(--hs-bg-canvas);
  }

  [data-hs="2"][data-hs-bg="photo"] body,
  [data-hs="2"][data-hs-bg="photo"] body.hs-portal-body {
    background-image: none !important;
    background-color: transparent !important;
    background-attachment: scroll !important;
    /* Stacking context so z-index:-1 ::before stays behind UI, not behind <html>. */
    isolation: isolate;
  }

  [data-hs="2"][data-hs-bg="photo"] body::before,
  [data-hs="2"][data-hs-bg="photo"] body.hs-portal-body::before {
    content: "";
    position: fixed;
    inset: 0;
    z-index: -1;
    pointer-events: none;
    background-color: var(--hs-bg-canvas);
    background-image: var(--hs-bg-photo, none);
    background-repeat: no-repeat;
    background-position: center;
    background-size: cover;
  }
}

/* Glass panels need something behind them, so any v1 surface that used to
   be opaque white becomes translucent along with the token swap. */
[data-hs="2"] .surface-admin,
[data-hs="2"] .surface-user {
  background: transparent;
}

/* ---- Lander scope --------------------------------------------------
   scroll-lander-ux.css declares its font tokens on `body.scroll-lander-page`,
   which out-specifies any root-level mapping — the lander hero kept rendering
   Instrument Serif. Redeclare them at that scope so the lander uses the
   system display face like every other page. */
[data-hs="2"] body.scroll-lander-page {
  --v2-font-ui: var(--hs-font-ui);
  --v2-font-display: var(--hs-font-display);
  --v2-text-primary: var(--hs-fg-primary);
  --v2-text-secondary: var(--hs-fg-secondary);
}

/* ============================================================
   Repairs — things the token bridge cannot reach

   The bridge only works where v1 routed a value through a custom property.
   These are the places v1 hardcoded a literal, so they keep rendering the
   old value no matter what the tokens say. Each one is a targeted override,
   not a rewrite of the page.
   ============================================================ */

/* Display serifs were written as literals in eight stylesheets (PT Serif in
   the lander and legal pages, Instrument Serif in scroll-lander-polish). The
   system settled on Lexend, so anything asking for those faces is redirected. */
[data-hs="2"] :is(h1, h2, h3, .hs-h1, .hs-h2, .display-hero, .hero-title,
  [class*="hero__title"], [class*="narr-line"], [class*="-display"]) {
  font-family: var(--hs-font-display);
}

/* legal.css sets its own serif on headings with no token in between. */
[data-hs="2"] .legal h1,
[data-hs="2"] .legal h2,
[data-hs="2"] .legal h3,
[data-hs="2"] main h1,
[data-hs="2"] article h1 {
  font-family: var(--hs-font-display);
}

/* lander.css paints an opaque white body, which hides the wash entirely. */
[data-hs="2"] body {
  background-color: var(--hs-bg-canvas) !important;
}
