/* V0 extras (v0-extras.js): palette, back-to-top ring, footer clock, toast. */

/* ── Command palette ── */
.jfe-palette { width: min(640px, calc(100vw - 24px)); max-height: min(560px, calc(100dvh - 48px)); margin: max(10vh, 24px) auto auto; padding: 0; border: 0; border-radius: 20px; background: transparent; color: #ece7dd; overflow: visible; }
.jfe-palette::backdrop { background: rgba(3, 4, 6, .62); backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px); }
.jfe-palette[open] { animation: jfePop .22s cubic-bezier(.2, .8, .2, 1) both; }
@keyframes jfePop { from { opacity: 0; transform: translateY(-8px) scale(.985); } to { opacity: 1; transform: none; } }
.jfe-palette__box { position: relative; display: flex; flex-direction: column; max-height: inherit; border: 1px solid rgba(255, 255, 255, .12); border-radius: 20px; background: linear-gradient(180deg, #11151c, #0a0c10); box-shadow: 0 40px 100px -30px rgba(0, 0, 0, .9), 0 0 0 1px rgba(4, 207, 254, .08); overflow: hidden; }
.jfe-palette__box::before { content: ""; position: absolute; top: 0; left: 0; right: 0; height: 3px; background: linear-gradient(90deg, #FF5A6E, #FFB35C 19%, #FFF06A 36%, #5CF2C2 56%, #04CFFD 76%, #B69DFF); }
.jfe-palette__field { display: flex; align-items: center; gap: 12px; padding: 18px 18px 14px; border-bottom: 1px solid rgba(255, 255, 255, .08); }
.jfe-palette__icon { display: grid; place-items: center; width: 32px; height: 32px; border-radius: 9px; background: rgba(4, 207, 254, .12); color: #04cffe; font: 600 16px/1 system-ui, sans-serif; flex: none; }
html body .jfe-palette__input { flex: 1; min-width: 0; margin: 0; padding: 6px 0; border: 0; outline: 0; background: transparent; box-shadow: none; color: #fff; -webkit-text-fill-color: #fff; caret-color: #04cffe; font: 500 18px/1.3 "Bricolage Grotesque", system-ui, sans-serif; }
html body .jfe-palette__input::placeholder { color: rgba(236, 231, 221, .4); -webkit-text-fill-color: rgba(236, 231, 221, .4); }
.jfe-palette__esc, .jfe-chip kbd { padding: 3px 7px; border: 1px solid rgba(255, 255, 255, .16); border-radius: 6px; color: rgba(236, 231, 221, .6); font: 600 11px/1 "JetBrains Mono", ui-monospace, monospace; }
.jfe-palette__list { overflow-y: auto; overscroll-behavior: contain; padding: 6px 8px 8px; }
.jfe-palette__group { padding: 12px 10px 6px; color: rgba(236, 231, 221, .45); font: 600 10px/1 "JetBrains Mono", ui-monospace, monospace; letter-spacing: .12em; text-transform: uppercase; }
.jfe-palette__option { display: grid; grid-template-columns: minmax(0, auto) minmax(0, 1fr) auto; align-items: baseline; gap: 12px; padding: 11px 12px; border-radius: 11px; cursor: pointer; }
.jfe-palette__option strong { color: #fff; font: 600 15px/1.3 "Bricolage Grotesque", system-ui, sans-serif; white-space: nowrap; }
.jfe-palette__option span { overflow: hidden; color: rgba(236, 231, 221, .55); font-size: 13px; white-space: nowrap; text-overflow: ellipsis; }
.jfe-palette__option em { color: #04cffe; font-style: normal; }
.jfe-palette__option[aria-selected="true"] { background: rgba(4, 207, 254, .12); box-shadow: inset 3px 0 #04cffe; }
.jfe-palette__empty { padding: 26px 12px; color: rgba(236, 231, 221, .6); text-align: center; }
.jfe-palette__foot { margin: 0; padding: 10px 18px; border-top: 1px solid rgba(255, 255, 255, .08); color: rgba(236, 231, 221, .4); font: 500 11px/1 "JetBrains Mono", ui-monospace, monospace; }
@media (max-width: 560px) {
  .jfe-palette { margin-top: calc(env(safe-area-inset-top, 0px) + 16px); }
  .jfe-palette__option { grid-template-columns: minmax(0, 1fr) auto; }
  .jfe-palette__option span { grid-column: 1; grid-row: 2; }
  .jfe-palette__foot, .jfe-palette__esc { display: none; }
}

/* ── Back-to-top ring ── */
.jfe-top { position: fixed; left: max(18px, env(safe-area-inset-left, 0px)); bottom: max(18px, env(safe-area-inset-bottom, 0px)); z-index: 999998; width: 48px; height: 48px; padding: 0; border: 0; border-radius: 50%; background: rgba(10, 10, 12, .86); box-shadow: 0 12px 34px -12px rgba(0, 0, 0, .8); cursor: pointer; opacity: 0; transform: translateY(12px) scale(.9); pointer-events: none; transition: opacity .25s ease, transform .25s ease; -webkit-tap-highlight-color: transparent; }
.jfe-top.is-on { opacity: 1; transform: none; pointer-events: auto; }
.jfe-top svg { display: block; width: 100%; height: 100%; }
.jfe-top__ring { transition: stroke-dashoffset .12s linear; }
.jfe-top:hover, .jfe-top:focus-visible { transform: translateY(-2px); outline: none; box-shadow: 0 0 0 3px rgba(4, 207, 254, .3), 0 12px 34px -12px rgba(0, 0, 0, .8); }
.jfe-top.is-done { animation: jfeGlow 1.4s ease-in-out 1; }
@keyframes jfeGlow { 50% { box-shadow: 0 0 0 6px rgba(92, 242, 194, .18), 0 12px 34px -12px rgba(0, 0, 0, .8); } }
.lg-on .jfe-top, html.jfe-palette-open .jfe-top, html.jf-loading .jfe-top { opacity: 0; pointer-events: none; }
@media (max-width: 480px) { .jfe-top { width: 44px; height: 44px; left: 12px; bottom: 14px; } }

/* ── Footer clock + chip ── */
.jfe-clock { display: inline-flex; align-items: center; gap: 8px; white-space: nowrap; }
.jfe-clock__dot { width: 7px; height: 7px; border-radius: 50%; background: #6b7280; }
.jfe-clock.is-awake .jfe-clock__dot { background: #5cf2c2; box-shadow: 0 0 0 0 rgba(92, 242, 194, .5); animation: jfePulse 2.4s ease-out infinite; }
@keyframes jfePulse { 70% { box-shadow: 0 0 0 7px rgba(92, 242, 194, 0); } 100% { box-shadow: 0 0 0 0 rgba(92, 242, 194, 0); } }
.jfe-clock__time { color: #ece7dd; font-variant-numeric: tabular-nums; }
html body .jfe-chip { display: inline-flex; align-items: center; gap: 8px; margin: 0; padding: 0; border: 0; background: none; color: #929a99; font: inherit; cursor: pointer; }
html body .jfe-chip:hover, html body .jfe-chip:focus-visible { color: #fff; outline: none; }
@media (pointer: coarse) { .jfe-chip kbd { display: none; } }

/* ── Toast ── */
.jfe-toast { position: fixed; left: 50%; bottom: calc(env(safe-area-inset-bottom, 0px) + 84px); z-index: 1000001; max-width: calc(100vw - 32px); padding: 11px 16px; border: 1px solid rgba(92, 242, 194, .35); border-radius: 12px; background: rgba(10, 12, 14, .94); color: #ece7dd; font: 500 13px/1.4 "Bricolage Grotesque", system-ui, sans-serif; box-shadow: 0 18px 40px -18px rgba(0, 0, 0, .9); transform: translate(-50%, 10px); opacity: 0; pointer-events: none; transition: opacity .2s ease, transform .2s ease; }
.jfe-toast.is-on { opacity: 1; transform: translate(-50%, 0); }

@media (prefers-reduced-motion: reduce) {
  .jfe-palette[open], .jfe-top.is-done, .jfe-clock.is-awake .jfe-clock__dot { animation: none; }
  .jfe-top, .jfe-toast, .jfe-top__ring { transition: none; }
}

/* Skip link: invisible until a keyboard user tabs to it. */
.jfe-skip { position: fixed; left: 12px; top: 12px; z-index: 2147483647; padding: 10px 14px; border-radius: 10px; background: #fff; color: #050607 !important; font: 600 14px/1 "Bricolage Grotesque", system-ui, sans-serif; text-decoration: none; transform: translateY(-160%); transition: transform .15s ease; }
.jfe-skip:focus, .jfe-skip:focus-visible { transform: none; outline: 3px solid #04cffe; outline-offset: 2px; }
#jf-main:focus { outline: none; }

/* Rainbow scroll line docked to the header's bottom edge (always painted). */
html .jf-scroll-progress.is-docked { position: absolute; top: auto; bottom: -1px; left: 0; right: 0; width: 100%; height: 3px; z-index: 5; opacity: 1; box-shadow: none; }
/* One rainbow line, not two: the image-loading rail used the same spot and
   read as a ghost copy of the scroll line. Phones show only the scroll line. */
@media (max-width: 767px) { html #jf-media-progress { display: none !important; } }

/* Home hero wall hover caption. */
.jfe-tile-tip { position: fixed; left: 0; top: 0; z-index: 999997; display: grid; gap: 2px; max-width: 320px; padding: 9px 12px; border: 1px solid rgba(255, 255, 255, .14); border-radius: 12px; background: rgba(8, 10, 14, .88); backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px); box-shadow: 0 16px 40px -18px rgba(0, 0, 0, .9); color: #ece7dd; pointer-events: none; opacity: 0; transition: opacity .15s ease; }
.jfe-tile-tip.is-on { opacity: 1; }
.jfe-tile-tip strong { color: #fff; font: 600 14px/1.25 "Bricolage Grotesque", system-ui, sans-serif; }
.jfe-tile-tip span { color: #5cf2c2; font: 600 10.5px/1.3 "JetBrains Mono", ui-monospace, monospace; letter-spacing: .04em; text-transform: uppercase; }

/* Page to page: a short cross-fade instead of a hard cut (supporting browsers only). */
@view-transition { navigation: auto; }
::view-transition-old(root), ::view-transition-new(root) { animation-duration: .26s; }
@media (prefers-reduced-motion: reduce) { @view-transition { navigation: none; } }

/* The rainbow is the one thing that should not blink between rooms.
   The page already cross-fades on navigation, but the scroll rail and the
   back-to-top ring were being swept up in that fade with everything else —
   so the through-line that ties the loader, the scroll depth and the ring
   together visibly restarted at every door.

   Naming them pulls each out of the root snapshot into its own transition
   group, and killing the old/new animation means they HOLD instead of
   cross-fading: the rail stays lit across the navigation while the page
   behind it changes. The bar resets to zero on the new page, as it should —
   it is the ribbon that persists, not the measurement.

   Both elements are created by JS on every page, so if one side has not
   mounted yet the group simply falls back to the normal root fade. */
.jf-scroll-progress { view-transition-name: jf-rainbow-rail; }
.jfe-top { view-transition-name: jf-rainbow-ring; }

::view-transition-old(jf-rainbow-rail),
::view-transition-new(jf-rainbow-rail),
::view-transition-old(jf-rainbow-ring),
::view-transition-new(jf-rainbow-ring) { animation: none; opacity: 1; }

/* A named group is lifted out of the root snapshot and painted above it, so
   give the pair the same stacking they have in the live page. */
::view-transition-group(jf-rainbow-rail) { z-index: 3; }
::view-transition-group(jf-rainbow-ring) { z-index: 2; }

/* Reduced motion turns navigation transitions off entirely (above), so these
   names would never be captured — but drop them anyway so no engine spends
   snapshot work on elements it will not animate. */
@media (prefers-reduced-motion: reduce) {
  .jf-scroll-progress, .jfe-top { view-transition-name: none; }
}

/* End-of-room navigation. */
.jfe-next { padding: clamp(40px, 6vw, 88px) clamp(16px, 4vw, 64px); background: #050607; border-top: 1px solid rgba(255, 255, 255, .08); }
.jfe-next__inner { display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr); gap: clamp(20px, 4vw, 64px); align-items: end; width: min(1320px, 100%); margin: 0 auto; }
html body a.jfe-next__main { display: grid; gap: 10px; color: #fff; text-decoration: none; }
.jfe-next__eyebrow { color: #5cf2c2; font: 600 11px/1 "JetBrains Mono", ui-monospace, monospace; letter-spacing: .14em; text-transform: uppercase; }
.jfe-next__title { display: inline-flex; align-items: center; gap: .3em; font: 640 clamp(40px, 6vw, 88px)/.95 "Bricolage Grotesque", system-ui, sans-serif; letter-spacing: -.045em; }
.jfe-next__title b { display: inline-grid; place-items: center; width: .82em; height: .82em; border-radius: 50%; background: #fff; color: #050607; font-size: .42em; font-weight: 700; letter-spacing: 0; transition: transform .25s cubic-bezier(.2, .8, .2, 1), background .25s ease; }
html body a.jfe-next__main:hover .jfe-next__title b, html body a.jfe-next__main:focus-visible .jfe-next__title b { transform: translateX(8px); background: #04cffe; }
html body a.jfe-next__main:focus-visible { outline: 3px solid #04cffe; outline-offset: 6px; border-radius: 8px; }
.jfe-next__dek { max-width: 46ch; color: rgba(236, 231, 221, .66); font: 400 clamp(15px, 1.2vw, 18px)/1.5 "Bricolage Grotesque", system-ui, sans-serif; }
.jfe-next__rest { display: flex; flex-wrap: wrap; gap: 8px; margin: 0; padding: 0; list-style: none; justify-content: flex-end; }
html body .jfe-next__rest a { display: inline-block; padding: 9px 14px; border: 1px solid rgba(255, 255, 255, .16); border-radius: 999px; color: #ece7dd; font: 600 13px/1 "Bricolage Grotesque", system-ui, sans-serif; text-decoration: none; transition: border-color .2s ease, background .2s ease; }
html body .jfe-next__rest a:hover, html body .jfe-next__rest a:focus-visible { border-color: #04cffe; background: rgba(4, 207, 254, .1); outline: none; }
@media (max-width: 820px) {
  .jfe-next__inner { grid-template-columns: 1fr; align-items: start; }
  .jfe-next__rest { justify-content: flex-start; }
}

/* ═══ Hero wall jitter: resolved, this file no longer does anything about it ═══
   The whole scroll-fighting approach that lived here through 2026-09-20 (a
   kill-and-freeze reset, briefly a perpetual float that turned out to be our
   own added motion mistaken for the bug) is gone. Root cause: 7 of 11
   Breakdance "Scrolling Animation" galleries across two sections never had
   their native per-gallery "Disable At: Phone Landscape" setting turned on
   in the page builder -- the other 4 already proved the setting works.
   Fixed in the Breakdance editor itself, not in code: every gallery now
   disables its scroll-linked motion below that breakpoint, so Breakdance
   creates zero ScrollTriggers on coarse pointers in the first place. Verified
   live at 375px. Nothing to override from here.

   .jf-hero (below) is still real and still needed -- unrelated to the
   parallax fix, it only exists for the headline-clipping padding. */

/* ── "Creative" was losing its top and bottom edges ──
   Not a font problem, and not a line-height war. With background-clip: text the
   gradient is clipped to the element's BACKGROUND BOX, and the glyphs were
   bigger than that box: measured live at 56px, the box is 52px tall while the
   text paints 67px, overflowing 8px above and 7px below. Those overflowing
   parts have no background to clip against, so with a transparent text fill
   they render as nothing. "Strategic" is unaffected because it is solid cream
   and never needed a background.

   That is also why changing fonts and sizes over the months never fixed it:
   any pairing whose glyphs outgrow a 0.92 line box hits the same wall.

   Padding is the whole fix. It extends the background box without touching
   line-height (which the theme sets in a stylesheet we cannot override from
   here — tested, including with !important) and, measured on the live page,
   it moves nothing below it: the CTA stays at the same offset.

   2026-09-20: same bug, horizontal axis. Jaron flagged the right side of the
   final "e" still reading sliced -- confirmed live: this heading carries
   letter-spacing: -4.26px (theme-set, same cross-origin stylesheet as
   line-height, so not ours to change here either). Negative letter-spacing
   pulls the LAST glyph's painted ink past its own calculated advance-width
   box, and background-clip: text clips to that box, not the ink -- the same
   mismatch as the vertical case, just on the trailing edge instead of top/
   bottom. Verified live: +10px of right padding on the actual DOM element
   (94.72px font-size there) fully restored the curve. 0.12em scales that
   with font-size the same way the vertical padding already does. */
.jf-hero h1.bde-heading {
  padding-top: 0.16em;
  padding-bottom: 0.16em;
  padding-right: 0.12em;
}
