/* ==========================================================================
   chrome.css — Apex Holding
   PURPOSE: The persistent furniture that wraps every page — site header, mark,
   primary nav, header icon buttons, scroll-progress hairline, site footer, the
   full-viewport world switcher, the founder seal, and the portal-transition
   wipe. All of this markup is INJECTED BY JAVASCRIPT, so this file doubles as
   the markup specification those modules must produce.

   Loaded FOURTH, after components.css.

   ==========================================================================
   MARKUP CONTRACT — chrome.js must inject exactly this into
   [data-chrome="header"]:

     <header class="site-header" data-elevated="false">
       <div class="site-header__inner">
         <a class="site-header__mark" href="{root}index.html">
           <svg class="site-header__mark-glyph" aria-hidden="true" …></svg>
           <span class="sr-only">Apex Holding — home</span>
         </a>
         <nav class="site-nav" aria-label="Primary">
           <ul class="site-nav__list">
             <li><a class="site-nav__link" href="…" [aria-current="page"]>…</a></li>
           </ul>
         </nav>
         <div class="site-header__actions">
           <button class="icon-btn" id="world-switcher-btn" …>…</button>
           <button class="icon-btn" id="support-btn" …>…</button>
         </div>
       </div>
       <div class="scroll-progress" role="presentation">
         <span class="scroll-progress__bar"></span>
       </div>
     </header>

   and into [data-chrome="footer"]:

     <footer class="site-footer">
       <div class="site-footer__inner">
         <div class="site-footer__brand">…mark + line…</div>
         <nav class="site-footer__col" aria-label="Worlds">
           <h2 class="site-footer__title">…</h2>
           <ul class="site-footer__links"><li><a href="…">…</a></li></ul>
         </nav>
         <div class="site-footer__col site-footer__contact">…tel + mailto…</div>
         <ul class="site-footer__social">…placeholders…</ul>
       </div>
       <div class="site-footer__legal">
         <p>…</p>
         <a class="site-footer__founder" href="…">Founder</a>
       </div>
     </footer>

   TWO JS-DRIVEN CUSTOM PROPERTIES, documented at their rules below:
     --scroll-progress   0 → 1, written on .scroll-progress by chrome.js
     --wipe-accent       destination accent, written on .portal-wipe by
                         transitions.js
   ========================================================================== */


/* --------------------------------------------------------------------------
   1. SITE HEADER
   Fixed and fully transparent so it floats over hero art. Once the page has
   scrolled past 24px, chrome.js sets data-elevated="true" and the bar earns a
   glass ground plus a hairline. backdrop-filter is applied only in the
   elevated state and is NOT transitioned — a compositor-expensive filter has
   no business animating on a scroll path.
   -------------------------------------------------------------------------- */

.site-header {
  position: fixed;
  inset-block-start: 0;
  inset-inline: 0;
  z-index: var(--z-header);
  background-color: transparent;
  border-block-end: 1px solid transparent;
  transition:
    background-color var(--dur-micro) var(--ease-out-soft),
    border-color var(--dur-micro) var(--ease-out-soft);
}

.site-header[data-elevated="true"] {
  background-color: color-mix(in srgb, var(--w-base) 78%, transparent);
  border-block-end-color: var(--w-line);
  backdrop-filter: blur(var(--glass-blur)) saturate(1.25);
}

.site-header__inner {
  display: grid;
  grid-template-columns: auto 1fr auto;
  grid-template-areas: "mark nav actions";
  align-items: center;
  gap: var(--space-5);
  block-size: var(--header-h);
  max-inline-size: var(--maxw-wide);
  margin-inline: auto;
  padding-inline: var(--gutter);
}


/* --------------------------------------------------------------------------
   2. THE MARK
   -------------------------------------------------------------------------- */

.site-header__mark {
  grid-area: mark;
  display: inline-flex;
  align-items: center;
  min-block-size: 2.75rem;
  padding-inline-end: var(--space-2);
  color: var(--w-text);
  text-decoration: none;
  transition: color var(--dur-micro) var(--ease-out-soft);
}

.site-header__mark-glyph {
  inline-size: auto;
  block-size: 1.75rem;
}

.site-header__mark:hover,
.site-header__mark:focus-visible {
  color: var(--w-accent);
}


/* --------------------------------------------------------------------------
   3. PRIMARY NAV
   Links are utility-face, uppercase, with an accent rule that draws from the
   left on hover/focus and stays drawn on the current page.
   -------------------------------------------------------------------------- */

.site-nav {
  grid-area: nav;
  min-inline-size: 0;
}

.site-nav__list {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin: 0;
}

.site-nav__list > li {
  margin: 0;
}

.site-nav__link {
  position: relative;
  display: inline-flex;
  align-items: center;
  min-block-size: 2.75rem;
  padding-inline: var(--space-3);
  color: var(--w-text-dim);
  font-family: var(--font-utility);
  font-size: var(--step--1);
  letter-spacing: var(--track-wide);
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
  transition: color var(--dur-micro) var(--ease-out-soft);
}

.site-nav__link::after {
  content: "";
  position: absolute;
  inset-inline: var(--space-3);
  inset-block-end: 0.625rem;
  block-size: 1px;
  background-color: var(--w-accent);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform var(--dur-micro) var(--ease-out-soft);
}

.site-nav__link:hover,
.site-nav__link:focus-visible {
  color: var(--w-text);
}

.site-nav__link:hover::after,
.site-nav__link:focus-visible::after {
  transform: scaleX(1);
}

.site-nav__link[aria-current="page"] {
  color: var(--w-text);
}

.site-nav__link[aria-current="page"]::after {
  transform: scaleX(1);
}


/* --------------------------------------------------------------------------
   4. HEADER ACTIONS
   The two icon buttons. Their base treatment is .icon-btn in components.css;
   this only places them.
   -------------------------------------------------------------------------- */

.site-header__actions {
  grid-area: actions;
  display: flex;
  align-items: center;
  gap: var(--space-1);
  justify-self: end;
}


/* --------------------------------------------------------------------------
   5. SCROLL PROGRESS

   *** JS CONTRACT — READ THIS ***
   chrome.js must express scroll position as a custom property, NOT as a width:

       progressEl.style.setProperty("--scroll-progress", fraction);  // 0 → 1

   The bar is a full-width element scaled on the X axis. Driving it with
   transform keeps the whole scroll path on the compositor, which is the
   difference between a smooth 60fps hairline and a janky one. Setting
   style.width instead will leave the bar permanently invisible, because the
   scaleX factor would still be 0.
   -------------------------------------------------------------------------- */

.scroll-progress {
  position: absolute;
  inset-inline: 0;
  inset-block-end: -1px;
  block-size: 2px;
  overflow: hidden;
  pointer-events: none;
}

.scroll-progress__bar {
  display: block;
  inline-size: 100%;
  block-size: 100%;
  background-image: linear-gradient(
    to right,
    var(--w-accent),
    var(--w-accent-soft)
  );
  transform: scaleX(var(--scroll-progress, 0));
  transform-origin: left center;
}

/* Nothing drives the bar without script, so hide the rail entirely rather
   than leave an empty groove under the header. */
html:not(.js) .scroll-progress {
  display: none;
}


/* --------------------------------------------------------------------------
   6. SITE FOOTER
   -------------------------------------------------------------------------- */

.site-footer {
  margin-block-start: var(--space-12);
  border-block-start: 1px solid var(--w-line);
  background-color: var(--w-base-2);
  color: var(--w-text-dim);
}

.site-footer__inner {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr));
  gap: var(--space-8);
  max-inline-size: var(--maxw-wide);
  margin-inline: auto;
  padding: var(--space-10) var(--gutter) var(--space-8);
}

.site-footer__brand {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  color: var(--w-text);
}

.site-footer__brand p {
  color: var(--w-text-dim);
  font-size: var(--step--1);
  max-inline-size: 28ch;
}

.site-footer__col {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.site-footer__title {
  font-family: var(--font-utility);
  font-size: var(--step--1);
  font-weight: 400;
  letter-spacing: var(--track-widest);
  text-transform: uppercase;
  color: var(--w-text);
}

.site-footer__links {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  margin: 0;
}

.site-footer__links a,
.site-footer__contact a {
  display: inline-flex;
  align-items: center;
  min-block-size: 2.75rem;
  color: var(--w-text-dim);
  font-size: var(--step--1);
  text-decoration: none;
  transition: color var(--dur-micro) var(--ease-out-soft);
}

.site-footer__links a:hover,
.site-footer__links a:focus-visible {
  color: var(--w-accent-soft);
}

.site-footer__contact a {
  font-family: var(--font-utility);
  letter-spacing: var(--track-wide);
  color: var(--w-text);
}

.site-footer__contact a:hover,
.site-footer__contact a:focus-visible {
  color: var(--w-accent-soft);
}

.site-footer__social {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin: 0;
}

.site-footer__legal {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  max-inline-size: var(--maxw-wide);
  margin-inline: auto;
  padding: var(--space-5) var(--gutter);
  border-block-start: 1px solid var(--w-line);
  font-size: var(--step--1);
}

.site-footer__legal p {
  color: var(--w-text-dim);
  margin: 0;
}

/* Exactly one small, quiet founder link. Never a button, never a card. */
.site-footer__founder {
  display: inline-flex;
  align-items: center;
  min-block-size: 2.75rem;
  color: var(--w-text-dim);
  font-family: var(--font-utility);
  font-size: var(--step--1);
  letter-spacing: var(--track-wide);
  text-decoration: none;
  transition: color var(--dur-micro) var(--ease-out-soft);
}

.site-footer__founder:hover,
.site-footer__founder:focus-visible {
  color: var(--w-accent-soft);
}


/* --------------------------------------------------------------------------
   7. WORLD SWITCHER
   Full-viewport dialog. Six tiles. Each tile previews its DESTINATION world:
   at rest it is a hairline surface in the world you are standing in; on hover
   or focus it fills with that destination's own ground and accent, and washes
   the whole overlay in the same palette.

   Cross-world colour comes from the --world-*-{base,accent,text} lookup table
   in tokens.css — never a raw hex, and never --w-* (which would only ever
   give you the palette you are already looking at).

   MARKUP CONTRACT — world-switcher.js:
     <div class="world-switcher" id="world-switcher" role="dialog"
          aria-modal="true" aria-labelledby="world-switcher-title" hidden>
       <div class="world-switcher__wash" aria-hidden="true"></div>
       <div class="world-switcher__bar">
         <h2 class="world-switcher__title" id="world-switcher-title">…</h2>
         <button class="icon-btn" data-switcher-close>…</button>
       </div>
       <ul class="world-switcher__grid">
         <li><a class="world-switcher__tile" data-tile-world="greppo" href="…">
           <span class="world-switcher__tile-name">Greppo Winery</span>
           <span class="world-switcher__tile-essence">…</span>
         </a></li>
         … six total …
       </ul>
     </div>
   -------------------------------------------------------------------------- */

.world-switcher {
  position: fixed;
  inset: 0;
  z-index: var(--z-switcher);
  display: grid;
  grid-template-rows: auto 1fr;
  gap: var(--space-6);
  padding: var(--space-6) var(--gutter) var(--space-9);
  overflow-y: auto;
  overscroll-behavior: contain;
  background-color: color-mix(in srgb, var(--w-base) 92%, transparent);
  backdrop-filter: blur(calc(var(--glass-blur) * 1.5));
  opacity: 0;
  transition: opacity var(--dur-reveal) var(--ease-out-soft);
}

.world-switcher.is-open {
  opacity: 1;
}

/* The palette wash. Sits behind the tiles, tinted by whichever tile is
   currently engaged. world-switcher.js may also write --switcher-tint /
   --switcher-ground directly to animate the token change; an inline value
   overrides the :has() rules below. */
.world-switcher__wash {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-color: color-mix(in srgb, var(--switcher-ground, transparent) 60%, transparent);
  background-image: radial-gradient(
    130% 100% at 50% 100%,
    color-mix(in srgb, var(--switcher-tint, transparent) 38%, transparent),
    transparent 68%
  );
  opacity: 0;
  transition:
    opacity var(--dur-world) var(--ease-out-soft),
    background-color var(--dur-world) var(--ease-out-soft);
}

.world-switcher:has(.world-switcher__tile:is(:hover, :focus-visible)) .world-switcher__wash {
  opacity: 1;
}

/* Per-destination tint. Six rules, one per world, resolved purely in CSS so
   the overlay still responds correctly if the JS tint hook never fires. */
.world-switcher:has([data-tile-world="portal"]:is(:hover, :focus-visible)) {
  --switcher-tint: var(--world-portal-accent);
  --switcher-ground: var(--world-portal-base);
}

.world-switcher:has([data-tile-world="greppo"]:is(:hover, :focus-visible)) {
  --switcher-tint: var(--world-greppo-accent);
  --switcher-ground: var(--world-greppo-base);
}

.world-switcher:has([data-tile-world="arz-faraya"]:is(:hover, :focus-visible)) {
  --switcher-tint: var(--world-arz-faraya-accent);
  --switcher-ground: var(--world-arz-faraya-base);
}

.world-switcher:has([data-tile-world="zaarour"]:is(:hover, :focus-visible)) {
  --switcher-tint: var(--world-zaarour-accent);
  --switcher-ground: var(--world-zaarour-base);
}

.world-switcher:has([data-tile-world="portfolio"]:is(:hover, :focus-visible)) {
  --switcher-tint: var(--world-portfolio-accent);
  --switcher-ground: var(--world-portfolio-base);
}

.world-switcher:has([data-tile-world="support"]:is(:hover, :focus-visible)) {
  --switcher-tint: var(--world-support-accent);
  --switcher-ground: var(--world-support-base);
}

.world-switcher__bar {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  max-inline-size: var(--maxw-wide);
  inline-size: 100%;
  margin-inline: auto;
  block-size: var(--header-h);
}

.world-switcher__title {
  font-family: var(--font-utility);
  font-size: var(--step--1);
  font-weight: 400;
  letter-spacing: var(--track-widest);
  text-transform: uppercase;
  color: var(--w-text-dim);
}

.world-switcher__grid {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-4);
  align-content: center;
  max-inline-size: var(--maxw-wide);
  inline-size: 100%;
  margin: 0 auto;
}

.world-switcher__grid > li {
  margin: 0;
  display: flex;
}

/* --- Tile ------------------------------------------------------------- */

.world-switcher__tile {
  /* Destination palette, assigned per world just below. */
  --tile-base: var(--w-surface);
  --tile-accent: var(--w-accent);
  --tile-text: var(--w-text);

  position: relative;
  display: flex;
  flex: 1;
  flex-direction: column;
  justify-content: flex-end;
  gap: var(--space-2);
  min-block-size: clamp(9rem, 22vh, 14rem);
  padding: var(--space-5);
  overflow: hidden;
  border: 1px solid var(--w-line);
  border-radius: var(--radius-md);
  background-color: color-mix(in srgb, var(--w-surface) 55%, transparent);
  color: var(--w-text);
  text-decoration: none;
  transition:
    background-color var(--dur-world) var(--ease-out-soft),
    border-color var(--dur-micro) var(--ease-out-soft),
    color var(--dur-world) var(--ease-out-soft),
    transform var(--dur-micro) var(--ease-out-soft);
}

.world-switcher__tile[data-tile-world="portal"] {
  --tile-base: var(--world-portal-base);
  --tile-accent: var(--world-portal-accent);
  --tile-text: var(--world-portal-text);
}

.world-switcher__tile[data-tile-world="greppo"] {
  --tile-base: var(--world-greppo-base);
  --tile-accent: var(--world-greppo-accent);
  --tile-text: var(--world-greppo-text);
}

.world-switcher__tile[data-tile-world="arz-faraya"] {
  --tile-base: var(--world-arz-faraya-base);
  --tile-accent: var(--world-arz-faraya-accent);
  --tile-text: var(--world-arz-faraya-text);
}

.world-switcher__tile[data-tile-world="zaarour"] {
  --tile-base: var(--world-zaarour-base);
  --tile-accent: var(--world-zaarour-accent);
  --tile-text: var(--world-zaarour-text);
}

.world-switcher__tile[data-tile-world="portfolio"] {
  --tile-base: var(--world-portfolio-base);
  --tile-accent: var(--world-portfolio-accent);
  --tile-text: var(--world-portfolio-text);
}

.world-switcher__tile[data-tile-world="support"] {
  --tile-base: var(--world-support-base);
  --tile-accent: var(--world-support-accent);
  --tile-text: var(--world-support-text);
}

/* Destination accent rising from the foot of the tile. */
.world-switcher__tile::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: linear-gradient(
    to top,
    color-mix(in srgb, var(--tile-accent) 30%, transparent),
    transparent 60%
  );
  opacity: 0;
  transition: opacity var(--dur-world) var(--ease-out-soft);
}

.world-switcher__tile:hover,
.world-switcher__tile:focus-visible {
  background-color: var(--tile-base);
  border-color: var(--tile-accent);
  color: var(--tile-text);
  transform: translateY(-3px);
}

.world-switcher__tile:hover::before,
.world-switcher__tile:focus-visible::before {
  opacity: 1;
}

/* The world you are already in. Marked, but still travellable. */
.world-switcher__tile[aria-current="page"] {
  border-color: var(--tile-accent);
}

.world-switcher__tile-name {
  position: relative;
  font-family: var(--font-display);
  font-size: var(--step-2);
  line-height: var(--lh-snug);
  letter-spacing: var(--track-tight);
}

/* Essence line is legible at rest and simply strengthens on engagement —
   never hidden, so touch users and screen readers get the same content. */
.world-switcher__tile-essence {
  position: relative;
  font-family: var(--font-utility);
  font-size: var(--step--1);
  letter-spacing: var(--track-wide);
  color: currentColor;
  opacity: 0.7;
  transition: opacity var(--dur-micro) var(--ease-out-soft);
}

.world-switcher__tile:hover .world-switcher__tile-essence,
.world-switcher__tile:focus-within .world-switcher__tile-essence {
  opacity: 1;
}

html:not(.js) .world-switcher {
  display: none;
}


/* --------------------------------------------------------------------------
   8. FOUNDER SEAL
   A small, quiet circular mark pinned bottom-left with a slow pulse ring.
   Capped at 56px so it never competes with content. Its tooltip appears on
   hover AND on focus-within, so a tap (which focuses) reveals it too.
   The apex-pulse-ring keyframe lives in motion.css.

   MARKUP CONTRACT — chrome.js:
     <a class="founder-seal" href="{root}portfolio/index.html#founder">
       <span class="founder-seal__ring" aria-hidden="true"></span>
       <svg class="founder-seal__glyph" aria-hidden="true" …></svg>
       <span class="founder-seal__tooltip" aria-hidden="true">Founder</span>
       <span class="sr-only">About the founder</span>
     </a>
   -------------------------------------------------------------------------- */

.founder-seal {
  position: fixed;
  inset-block-end: var(--space-5);
  inset-inline-start: var(--space-5);
  z-index: var(--z-sticky);
  display: grid;
  place-items: center;
  inline-size: 3.5rem;
  block-size: 3.5rem;
  border: 1px solid var(--w-line);
  border-radius: 50%;
  background-color: color-mix(in srgb, var(--w-surface) 88%, transparent);
  backdrop-filter: blur(var(--glass-blur));
  color: var(--w-accent);
  text-decoration: none;
  transition:
    border-color var(--dur-micro) var(--ease-out-soft),
    color var(--dur-micro) var(--ease-out-soft),
    transform var(--dur-micro) var(--ease-out-soft);
}

.founder-seal:hover,
.founder-seal:focus-visible {
  border-color: var(--w-accent);
  color: var(--w-accent-soft);
  transform: scale(1.06);
}

.founder-seal__glyph {
  inline-size: 1.5rem;
  block-size: 1.5rem;
}

/* Slow breathing ring. Scale + opacity only. */
.founder-seal__ring {
  position: absolute;
  inset: -1px;
  border: 1px solid var(--w-accent);
  border-radius: 50%;
  opacity: 0;
  pointer-events: none;
  animation: apex-pulse-ring 6s var(--ease-out-soft) infinite;
}

.founder-seal__tooltip {
  position: absolute;
  inset-inline-start: calc(100% + var(--space-3));
  inset-block-end: 50%;
  transform: translateY(50%) translateX(-4px);
  padding: var(--space-2) var(--space-4);
  border: 1px solid var(--w-line);
  border-radius: var(--radius-sm);
  background-color: var(--w-surface);
  color: var(--w-text);
  font-family: var(--font-utility);
  font-size: var(--step--1);
  letter-spacing: var(--track-wide);
  text-transform: uppercase;
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition:
    opacity var(--dur-micro) var(--ease-out-soft),
    transform var(--dur-micro) var(--ease-out-soft);
}

.founder-seal:hover .founder-seal__tooltip,
.founder-seal:focus-within .founder-seal__tooltip {
  opacity: 1;
  transform: translateY(50%) translateX(0);
}


/* --------------------------------------------------------------------------
   9. PORTAL TRANSITION WIPE
   A single light sweep in the DESTINATION world's accent, played over real
   navigation. transitions.js sets --wipe-accent from the link's
   data-portal-accent, adds .is-active, then sets location.href.

   Hard ceiling of --dur-wipe (700ms). If anything goes wrong, the element is
   inert and pointer-events:none, so default navigation is never blocked.

   MARKUP CONTRACT — transitions.js:
     <div class="portal-wipe" aria-hidden="true"></div>
   -------------------------------------------------------------------------- */

.portal-wipe {
  position: fixed;
  inset: 0;
  z-index: var(--z-wipe);
  pointer-events: none;
  background-color: var(--wipe-accent, var(--w-accent));
  background-image: linear-gradient(
    100deg,
    color-mix(in srgb, var(--wipe-accent, var(--w-accent)) 55%, transparent),
    var(--wipe-accent, var(--w-accent)) 45%
  );
  transform: translate3d(-101%, 0, 0);
  will-change: transform;
}

.portal-wipe.is-active {
  transform: translate3d(0, 0, 0);
  transition: transform var(--dur-wipe) var(--ease-in-out-cinema);
}

html:not(.js) .portal-wipe {
  display: none;
}


/* --------------------------------------------------------------------------
   10. NARROW VIEWPORTS
   The header takes a second row so the nav keeps its full 44px targets rather
   than being crushed. The nav scrolls horizontally if it still overflows, and
   the switcher grid steps 3-up → 2-up → 1-up.
   -------------------------------------------------------------------------- */

@media (max-width: 62em) {
  .world-switcher__grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (max-width: 52em) {
  .site-header__inner {
    grid-template-columns: 1fr auto;
    grid-template-areas:
      "mark actions"
      "nav  nav";
    align-items: center;
    gap: var(--space-1) var(--space-4);
    padding-block-end: var(--space-2);
  }

  .site-nav {
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scrollbar-width: none;
    /* Bleed to the gutter edges so the scroll affordance reads correctly. */
    margin-inline: calc(var(--gutter) * -1);
    padding-inline: var(--gutter);
  }

  .site-nav::-webkit-scrollbar {
    display: none;
  }

  .site-nav__list {
    inline-size: max-content;
  }

  .site-footer__inner {
    gap: var(--space-7);
    padding-block-start: var(--space-8);
  }
}

@media (max-width: 34em) {
  .world-switcher__grid {
    grid-template-columns: 1fr;
  }

  .world-switcher__tile {
    min-block-size: 7rem;
  }

  .founder-seal {
    inline-size: 3rem;
    block-size: 3rem;
    inset-block-end: var(--space-4);
    inset-inline-start: var(--space-4);
  }

  .site-footer__legal {
    justify-content: flex-start;
  }
}
