/* =========================================
   PASTELLE WEBSITE - SHARED STYLES
   Common CSS for all pages
   ========================================= */

/* =========================================
   THEME TOKENS
   Single source of truth for what each theme looks like. Components below
   consume these instead of repeating per-theme colour literals, so one
   rule can serve light / dark / navy / pastel.

   Cascade order matters: navy carries BOTH `.dark` and `.navy`, so
   html.navy must come after html.dark (equal specificity, later wins) and
   only needs to restate what actually differs from dark. Pastel maps onto
   the --pastelle-pastel-* properties js/theme.js writes onto <html>.
   ========================================= */

:root {
  /* ── Motion scale ────────────────────────────────────────────────────────
     One curve family for the whole site. Everything decelerates and settles;
     nothing overshoots. On a page whose subject is the artwork, the interface
     should resolve out of the way rather than spring around.

     --ease-out-expo is the sharp one: a fast departure that lands softly, for
     state changes the pointer is waiting on. --ease-out-soft is gentler, for
     travel the eye follows across distance (panels, sheets, staggered rows).
     --pnav-ease is kept as its alias so the nav rules below read in their own
     vocabulary.

     Durations pair with them by intent, not by element: --motion-fast for a
     change under the cursor, --motion-base for something entering or leaving,
     --motion-slow for content arriving on scroll. */
  --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-out-soft: cubic-bezier(0.22, 1, 0.36, 1);
  --motion-fast: 0.18s;
  --motion-base: 0.28s;
  --motion-slow: 0.42s;

  /* ── Type scale ─────────────────────────────────────────────────────────
     The six steps live in css/tailwind.input.css's @theme so both systems read
     one definition; see the note there. Read them here as var(--type-xs) …
     var(--type-xl):
       xs   metadata, eyebrows      sm   captions, nav, interface labels
       base body copy               md   lead paragraphs, modal titles
       lg   section headings        xl   page titles
     Anything that needs a size off this ladder is a sign the ladder is wrong,
     not a reason to add a seventh step. */

  /* Body copy wants a generous leading; interface labels want a tight one. */
  --leading-body: 1.75;
  --leading-tight: 1.15;

  /* ── Shape ──────────────────────────────────────────────────────────────
     One radius for the whole site. Panels, cards, inputs and buttons are
     square; only genuinely circular things (dots, avatars, icon wells) use
     --radius-round. The previous seven near-identical roundings (6, 8, 9, 10,
     11, 14px) read as noise without reading as a decision. */
  --radius: 0px;
  --radius-round: 50%;

  /* ── Measure ────────────────────────────────────────────────────────────
     The content column. At the previous 2400px the grid ran nearly edge to
     edge on a wide display, which made scan lines long and the gallery read as
     a wall rather than a sequence.

     The value itself lives in tailwind.input.css's @theme, because the markup
     reaches it through the `max-w-measure` utility; this alias just lets
     hand-written CSS say --measure. One number, one place. */
  --measure: var(--container-measure);
  --gutter: 1.5rem;

  /* ── Eyebrow ────────────────────────────────────────────────────────────
     The ONE role allowed to be uppercase with wide tracking. Section
     kickers only. Every other label — filters, buttons, metadata, counts —
     is sentence case at normal tracking. Reach for .eyebrow rather than
     restating these three properties anywhere else. */
  --eyebrow-size: var(--type-xs);
  --eyebrow-tracking: 0.14em;
  --eyebrow-weight: 600;

  --theme-bg: #FFFFFF;
  --theme-leader-ink: #E4E3E0;
  --theme-surface: #E5E5E5;
  --theme-ink: #000;
  --theme-accent: currentColor;
  --theme-hairline: rgba(18, 18, 18, 0.12);

  /* Fixed chrome: navbar shell + mobile sheet */
  --theme-chrome-hairline: rgba(19, 18, 10, 0.1);
  --theme-chrome-saturate: 130%;
  --theme-sheet-shadow: none;
  --theme-sheet-hairline: var(--pnav-rule);
  --theme-menu-bg: #FFFFFF;
  --theme-menu-hairline: var(--pnav-rule);
  /* Menus are opaque on purpose. These float over generative artwork, and at
     even 95% the pattern underneath showed through and read as cheap. The
     inset hairline gives the top edge a lit rim so the panel has an edge of
     its own rather than being a flat rectangle. */
  --theme-menu-shadow: 0 8px 24px rgba(0, 0, 0, 0.10);
  --theme-hover-soft: color-mix(in srgb, currentColor 8%, transparent);
  --theme-hover-strong: color-mix(in srgb, currentColor 12%, transparent);
  --theme-menu-hover: rgba(18, 18, 18, 0.06);
  --theme-menu-rail: currentColor;
  --theme-chip-bg: color-mix(in srgb, currentColor 6%, transparent);

  /* Long-form collection / orbital surfaces */
  --theme-live-bg: #FFFFFF;
  --theme-live-hairline: rgba(18, 18, 18, 0.075);
  --theme-frame-bg: #FFFFFF;
  --theme-frame-hairline: rgba(18, 18, 18, 0.12);
  --theme-frame-shadow: none;
  --theme-modal-bg: #FFFFFF;
  --theme-modal-hairline: rgba(18, 18, 18, 0.1);
  --theme-modal-shadow: 0 12px 40px rgba(0, 0, 0, 0.12);
  --theme-scrim: rgba(255, 255, 255, 0.72);
  --theme-cfooter-bg: #FFFFFF;
  --theme-cfooter-ink: #121212;
  --theme-cfooter-hairline: rgba(18, 18, 18, 0.08);
  --theme-copy-muted: #6C6C6C;
}

html.dark {
  --theme-bg: #13120A;
  --theme-leader-ink: #2B2A24;
  --theme-surface: #121212;
  --theme-ink: #fff;
  --theme-hairline: rgba(255, 255, 255, 0.12);

  --theme-chrome-hairline: rgba(246, 241, 227, 0.1);
  --theme-sheet-shadow: none;
  --theme-menu-bg: #1f1e14;
  --theme-menu-hover: rgba(255, 255, 255, 0.08);
  --theme-menu-shadow: 0 8px 24px rgba(0, 0, 0, 0.10);

  --theme-live-bg: #13120A;
  --theme-live-hairline: rgba(255, 255, 255, 0.085);
  --theme-frame-bg: #050505;
  --theme-frame-hairline: rgba(255, 255, 255, 0.12);
  --theme-frame-shadow: none;
  --theme-modal-bg: #12120f;
  --theme-modal-hairline: rgba(255, 255, 255, 0.1);
  --theme-modal-shadow: 0 12px 40px rgba(0, 0, 0, 0.12);
  --theme-scrim: rgba(16, 16, 13, 0.78);
  --theme-cfooter-bg: #13120a;
  --theme-cfooter-ink: #FFFFFF;
  --theme-cfooter-hairline: rgba(255, 255, 255, 0.08);
  --theme-copy-muted: #AFAEAC;
}

html.navy {
  --theme-bg: #061830;
  --theme-leader-ink: #17273C;
  --theme-surface: #0b2240;
  --theme-accent: #fff;
  --theme-hairline: rgba(220, 235, 255, 0.14);

  --theme-chrome-hairline: rgba(220, 235, 255, 0.12);
  --theme-sheet-hairline: var(--theme-hairline);
  /* Opaque, and a step lighter than --theme-surface so the panel reads as
     lifted off the bar rather than cut out of it. */
  --theme-menu-bg: #102c50;
  --theme-menu-hairline: rgba(220, 235, 255, 0.18);
  --theme-menu-hover: rgba(220, 235, 255, 0.08);
  --theme-menu-shadow: 0 8px 24px rgba(0, 0, 0, 0.10);
  --theme-hover-soft: rgba(220, 235, 255, 0.08);
  --theme-hover-strong: rgba(220, 235, 255, 0.08);
  --theme-chip-bg: rgba(10, 34, 64, 0.88);

  --theme-live-bg: #061830;
  --theme-live-hairline: rgba(220, 235, 255, 0.14);
  --theme-frame-bg: #0b2240;
  --theme-frame-hairline: rgba(220, 235, 255, 0.14);
  --theme-modal-bg: #0b2240;
  --theme-modal-hairline: rgba(220, 235, 255, 0.14);
  --theme-scrim: rgba(6, 24, 48, 0.78);
  --theme-cfooter-bg: #061830;
  --theme-cfooter-ink: #fff;
  --theme-cfooter-hairline: rgba(220, 235, 255, 0.14);
}

html.pastel {
  --theme-bg: var(--pastelle-pastel-bg);
  --theme-leader-ink: color-mix(in srgb, var(--pastelle-pastel-ink) 12%, var(--pastelle-pastel-bg));
  --theme-surface: var(--pastelle-pastel-surface);
  --theme-ink: var(--pastelle-pastel-ink);
  --theme-accent: var(--pastelle-pastel-accent);
  --theme-hairline: var(--pastelle-pastel-hairline);

  /* The pastel backgrounds are highly saturated, so the frosted chrome
     must not push them further or the bar reads as a different colour
     than the page it sits on. */
  --theme-chrome-hairline: color-mix(in srgb, var(--pastelle-pastel-ink) 10%, transparent);
  --theme-chrome-saturate: 100%;
  --theme-sheet-hairline: var(--theme-hairline);
  --theme-menu-bg: var(--pastelle-pastel-surface-strong);
  --theme-menu-hairline: color-mix(in srgb, var(--pastelle-pastel-ink) 15%, transparent);
  --theme-menu-hover: color-mix(in srgb, var(--pastelle-pastel-ink) 8%, transparent);
  --theme-menu-rail: var(--pastelle-pastel-ink);
  --theme-menu-shadow: 0 8px 24px rgba(0, 0, 0, 0.10);
  --theme-hover-soft: var(--pastelle-pastel-accent-soft);
  --theme-hover-strong: color-mix(in srgb, var(--pastelle-pastel-accent) 20%, var(--pastelle-pastel-bg) 80%);
  --theme-chip-bg: var(--pastelle-pastel-accent-soft);

  --theme-live-bg: var(--pastelle-pastel-surface);
  --theme-live-hairline: var(--pastelle-pastel-hairline);
  --theme-frame-bg: var(--pastelle-pastel-surface-strong);
  --theme-frame-hairline: var(--pastelle-pastel-hairline);
  --theme-frame-shadow: none;
  --theme-modal-bg: var(--pastelle-pastel-surface-strong);
  --theme-modal-hairline: var(--pastelle-pastel-hairline);
  --theme-modal-shadow: 0 12px 40px rgba(0, 0, 0, 0.12);
  --theme-scrim: color-mix(in srgb, var(--pastelle-pastel-bg) 78%, transparent);
  --theme-cfooter-bg: var(--pastelle-pastel-bg);
  --theme-cfooter-ink: var(--pastelle-pastel-ink);
  --theme-cfooter-hairline: var(--pastelle-pastel-hairline);
}

/* ========== BASE STYLES ========== */

/* Font Smoothing */
body {
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  scrollbar-gutter: stable;
}

/* ========== PAGE TITLE SCALE ========== */

/* Three title roles, all drawn from the shared ladder.

   Sentence case, not uppercase. A 144px uppercase word did a lot of shouting
   before the viewer reached any artwork; at this size the words are still the
   largest thing on the page without competing with the work itself. The
   selectors are single-class on purpose — the old `html body h1.x.x` stacking
   existed only to out-specify other !important rules, which have since gone. */

.page-title-section,
.page-title-detail {
  font-family: 'Manrope', sans-serif;
  font-weight: 600;
  text-transform: none;
  text-wrap: balance;
}

.page-title-section,
#page-header h1.page-title-section {
  font-size: var(--type-xl);
  line-height: 1.05;
  letter-spacing: -0.03em;
}

.page-title-detail,
#work-title.page-title-detail {
  font-size: var(--type-lg);
  line-height: 1.1;
  letter-spacing: -0.02em;
}

/* ========== EYEBROW ==========

   The single uppercase + wide-tracking role on the site. Section kickers only.
   Filters, buttons, metadata and counts are sentence case at normal tracking;
   if a label wants to shout, it wants to be an eyebrow or it wants nothing. */
.eyebrow {
  font-size: var(--eyebrow-size);
  font-weight: var(--eyebrow-weight);
  letter-spacing: var(--eyebrow-tracking);
  line-height: var(--leading-tight);
  text-transform: uppercase;
}

/* ========== ACCESSIBILITY ========== */

/* Focus Visible Styles - Subtle but clear focus indicators */
button:focus-visible,
a:focus-visible,
[role="button"]:focus-visible,
select:focus-visible,
input:focus-visible,
textarea:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 2px;
}

.dark button:focus-visible,
.dark a:focus-visible,
.dark [role="button"]:focus-visible,
.dark select:focus-visible,
.dark input:focus-visible,
.dark textarea:focus-visible {
  outline-color: #D0D0CE;
}

/* Touch Action - Prevent double-tap zoom */
button,
a,
[role="button"],
label {
  touch-action: manipulation;
}

button,
a[href],
[role="button"] {
  -webkit-tap-highlight-color: transparent;
}

/* Skip to Content Link */
.skip-to-content {
  position: absolute;
  top: -100px;
  left: 0;
  background: #000;
  color: #fff;
  padding: 0.75rem 1.5rem;
  z-index: 9999;
  text-decoration: none;
  font-weight: 500;
  border-radius: var(--radius);
}

.skip-to-content:focus {
  top: 0;
}

.dark .skip-to-content {
  background: #fff;
  color: #000;
}

/* Custom Selection Color */
::selection {
  background: #4B7BE5;
  color: #fff;
}

.dark ::selection {
  background: #4B7BE5;
  color: #fff;
}

/* ========== SCROLLBAR STYLES ========== */

/* Custom Scrollbar */
::-webkit-scrollbar {
  width: 8px;
}

::-webkit-scrollbar-track {
  background: transparent;
}

::-webkit-scrollbar-thumb {
  background: #ccc;
  border-radius: var(--radius);
}

.dark ::-webkit-scrollbar-thumb {
  background: #333;
}

/* Custom Scrollbar for Modal */
.custom-scrollbar::-webkit-scrollbar {
  width: 6px;
}

.custom-scrollbar::-webkit-scrollbar-track {
  background: transparent;
}

.custom-scrollbar::-webkit-scrollbar-thumb {
  background-color: #CCCCCC;
  border-radius: var(--radius);
}

.dark .custom-scrollbar::-webkit-scrollbar-thumb {
  background-color: #42413B;
}

/* ========== IMAGE LOADING - SKELETON LOADERS ========== */

/* Skeleton loading animation */
@keyframes skeleton-loading {
  0% {
    background-position: -200px 0;
  }
  100% {
    background-position: calc(200px + 100%) 0;
  }
}

.skeleton {
  background: linear-gradient(
    90deg,
    #f0f0f0 0px,
    #e0e0e0 40px,
    #f0f0f0 80px
  );
  background-size: 200px 100%;
  animation: skeleton-loading 1.5s infinite linear;
}

.dark .skeleton {
  background: linear-gradient(
    90deg,
    #1a1a1a 0px,
    #2a2a2a 40px,
    #1a1a1a 80px
  );
  background-size: 200px 100%;
}

/* ---- Shared media loading placeholder --------------------------------------
   `.media-frame` goes on the *wrapper* around a grid image (the element that
   already reserves the cell's box). It paints a themed surface plus a soft
   shimmer that sits BEHIND the media, so the treatment is purely additive: the
   image paints over it as soon as it decodes, and a page whose JS never runs
   simply shows the surface — nothing is ever hidden by this rule.

   js/image-optimizer.js adds `.media-ready` on the media's load event and
   `.media-ready .media-failed` on error; both stop the shimmer.

   NOTE: the older `.skeleton` helper above and the previous
   `img[loading="lazy"]:not([src])` rule never applied to the gallery grids —
   no markup carries `.skeleton`, and every grid image is created with its
   `src` already set, so `:not([src])` could not match. `.media-frame`
   replaces that dead selector. */

@keyframes pastelle-media-shimmer {
  from { background-position: 150% 0; }
  to   { background-position: -50% 0; }
}

.media-frame {
  position: relative;
  background-color: var(--theme-surface);
  background-image: linear-gradient(
    90deg,
    transparent 0%,
    color-mix(in srgb, var(--theme-ink) 9%, transparent) 50%,
    transparent 100%
  );
  background-size: 60% 100%;
  background-repeat: no-repeat;
  animation: pastelle-media-shimmer 1.6s linear infinite;
}

.media-frame.media-ready {
  background-image: none;
  animation: none;
}

/* Failed media keeps the plain surface — never a permanent shimmer. */
.media-frame.media-failed {
  background-image: none;
  animation: none;
}

/* Grids whose cells have no intrinsic box until the image arrives can opt into
   a reserved square while loading, so the page has structure to shimmer. */
.media-frame[data-media-reserve]:not(.media-ready) {
  aspect-ratio: 1;
}

@media (prefers-reduced-motion: reduce) {
  .media-frame {
    background-image: none;
    animation: none;
  }
}

/* ========== REVEAL ANIMATIONS ========== */

/* Shared reveal system. Elements tagged .reveal-up rise into view when
   scrolled to; the shared observer in micro-animations.js activates
   them and staggers siblings that arrive together. Image tiles
   (.gallery-item / .p-img-tilt, or opt-in .reveal-focus) additionally
   resolve from a blur, and .reveal-mask headings wipe upward from a
   clipped edge — the same vocabulary as the Onchain page.

   ADDITIVE BY DEFAULT: the hidden starting state is applied only under
   `html.js-anim-ready`, which js/theme.js stamps on <html> from the head —
   before the body is parsed, so there is no flash. If that script never runs
   (JS off, blocked bundle, parse error) every .reveal-up is simply visible
   and the page reads normally. Reduced-motion users never get the hidden
   state at all, so content is instant for them too.

   The gate is written as `:where(html.js-anim-ready)` on purpose: :where()
   contributes zero specificity, so these rules keep the exact weight the
   ungated `.reveal-up { opacity: 0 }` used to have and every per-page
   override (Unique-Works, Projects, SideEffectsMayVary) keeps winning
   exactly as it did before. */
@media (prefers-reduced-motion: no-preference) {
  :where(html.js-anim-ready) .reveal-up {
    opacity: 0;
    transform: translateY(8px);
  }

  :where(html.js-anim-ready) .reveal-mask {
    clip-path: inset(0 0 100% 0);
    transform: translateY(12px);
  }

  .reveal-up {
    transition:
      opacity var(--motion-base) var(--ease-out-expo),
      transform var(--motion-slow) var(--ease-out-soft);
  }

  :where(html.js-anim-ready) .reveal-up.gallery-item {
    filter: none;
  }

  .reveal-mask {
    transition:
      clip-path 0.4s var(--ease-out-expo),
      transform 0.4s var(--ease-out-expo);
  }
}

.reveal-up.active {
  opacity: 1;
  transform: translateY(0);
  filter: none;
}

/* Slight over-clip on reveal so descenders and text shadows never sit
   on a hard clipped edge. */
.reveal-mask.active {
  clip-path: inset(-5% -5% -5% -5%);
  transform: translateY(0);
}

/* Reduced Motion Support - Disable animations for users who prefer it */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ========== BUTTON ANIMATIONS ========== */

/* ========== ENHANCED LINK ANIMATIONS ========== */

/* Animated underline from center */
.link-animated {
  position: relative;
  text-decoration: none;
}

.link-animated::after {
  content: '';
  position: absolute;
  bottom: -2px;
  left: 50%;
  width: 0;
  height: 1px;
  background: currentColor;
  transform: translateX(-50%);
  transition: width 0.3s var(--ease-out-expo);
}

.link-animated:hover::after {
  width: 100%;
}

/* Navigation link animation */
nav a:not(.link-animated) {
  position: relative;
}

nav a:not(.link-animated)::after {
  content: '';
  position: absolute;
  bottom: -4px;
  left: 0;
  width: 0;
  height: 2px;
  background: currentColor;
  transition: width 0.3s var(--ease-out-expo);
  opacity: 0.8;
}

nav a:not(.link-animated):hover::after {
  width: 100%;
}

/* ========== CAROUSEL ANIMATIONS (Homepage) ========== */

/* Carousel Slide Transitions */
.carousel-slide {
  transition: opacity 0.42s var(--ease-out-expo), transform 0.42s var(--ease-out-expo);
}

/* ========== ART CARD STYLES ========== */

/* Card Refinements - Subtle shadows and borders */
.art-card > div:first-child {
  border: 1px solid rgba(0, 0, 0, 0.06);
  box-shadow: none;
}

.dark .art-card > div:first-child {
  border: 1px solid rgba(255, 255, 255, 0.08);
  box-shadow: none;
}

/* Image Hover Effect */
.art-card img {
  transition: filter 0.5s ease;
}

/* ========== CROSS-DOCUMENT VIEW TRANSITIONS ========== */

/* Native navigation moves between full-page scenes. js/theme.js stamps the
   variant on <html data-page-transition> before the incoming page's first
   frame, plus data-page-transition-direction="back" on history traversals:
     luxe  – an arched sheet in the page color sweeps over the old page,
             then dissolves as the new page settles in (default)
     stack – the next page rises over the current one like a sheet
   Everything moves with transform and opacity only, so the motion stays on
   the compositor while the new page is still loading. */
@view-transition {
  navigation: auto;
}

:root {
  --pt-sheet-ease: cubic-bezier(0.32, 0.72, 0, 1);
  --pt-luxe-ease: cubic-bezier(0.77, 0, 0.18, 1);
  --pt-settle-ease: cubic-bezier(0.22, 1, 0.36, 1);
  --pt-stack-duration: 0.72s;
  --pt-luxe-duration: 0.55s;
}

/* Shared artwork morphs travel with the page instead of finishing first. */
::view-transition-group(*) {
  animation-duration: var(--pt-stack-duration);
  animation-timing-function: var(--pt-sheet-ease);
}

::view-transition-old(*) {
  animation: vt-refocus-out 0.08s ease-out both;
}

::view-transition-new(*) {
  animation: vt-refocus-in 0.18s var(--ease-out-expo) both;
}

::view-transition-old(*):only-child {
  animation: vt-fade-out 0.08s ease-out both;
}

::view-transition-new(*):only-child {
  animation: vt-fade-in 0.16s var(--ease-out-expo) both;
}

/* The space a receding page uncovers reads as depth, not a hole. */
::view-transition-group(root) {
  background: var(--theme-bg);
}

/* The UA cross-fade adds the two root images together (plus-lighter), which
   washes out every frame where one page overlaps the other. */
::view-transition-old(root),
::view-transition-new(root) {
  mix-blend-mode: normal;
}

/* The navbar is identical on both ends of the navigation, so pin it:
   hide the outgoing snapshot and show the incoming one immediately,
   and it reads as stationary chrome while the page moves beneath. */
#navbar {
  view-transition-name: site-nav;
}

::view-transition-old(site-nav) {
  animation: none;
  opacity: 0;
}

::view-transition-new(site-nav) {
  animation: none;
}

/* --- stack --------------------------------------------------------------- */

html[data-page-transition="stack"]::view-transition-old(root) {
  animation: pt-stack-recede var(--pt-stack-duration) var(--pt-sheet-ease) both;
}

html[data-page-transition="stack"]::view-transition-new(root) {
  box-shadow: 0 -24px 64px rgb(0 0 0 / 0.22);
  animation: pt-stack-rise var(--pt-stack-duration) var(--pt-sheet-ease) both;
}

html[data-page-transition="stack"][data-page-transition-direction="back"]::view-transition-old(root) {
  z-index: 1;
  box-shadow: 0 -24px 64px rgb(0 0 0 / 0.22);
  animation: pt-stack-drop var(--pt-stack-duration) var(--pt-sheet-ease) both;
}

html[data-page-transition="stack"][data-page-transition-direction="back"]::view-transition-new(root) {
  box-shadow: none;
  animation: pt-stack-recede var(--pt-stack-duration) var(--pt-sheet-ease) reverse both;
}

@keyframes pt-stack-recede {
  to {
    opacity: 0.4;
    transform: translate3d(0, -2.5%, 0) scale(0.94);
  }
}

@keyframes pt-stack-rise {
  from {
    transform: translate3d(0, 100%, 0);
  }
}

@keyframes pt-stack-drop {
  to {
    transform: translate3d(0, 100%, 0);
  }
}

/* --- luxe ---------------------------------------------------------------- */

/* Mounted by theme.js only while a transition runs, and captured once as a
   flat image so the pseudo-element can move it on the compositor. Transition
   groups stack in paint order, so z-index -1 keeps the sheet beneath the
   pinned navbar and any shared artwork. Both stay visible over the sweep. */
.pt-veil {
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
}

html:not([data-page-transition-direction]) .pt-veil {
  display: none;
}

/* Taller than the viewport with half-ellipse ends: at rest the arches sit
   just off screen, in motion the leading one reads as a soft curve. */
.pt-veil-sheet {
  position: fixed;
  top: -12vh;
  left: 0;
  width: 100vw;
  height: 124vh;
  border-radius: 50% / 12vh;
  background: var(--theme-bg);
  box-shadow: 0 0 56px rgb(0 0 0 / 0.16);
  view-transition-name: pt-sheet;
}

html[data-page-transition="luxe"]::view-transition-group(pt-sheet) {
  animation: none;
}

html[data-page-transition="luxe"]::view-transition-new(pt-sheet) {
  animation: pt-luxe-sheet var(--pt-luxe-duration) var(--pt-luxe-ease) both;
}

html[data-page-transition="luxe"]::view-transition-old(root) {
  animation: pt-luxe-sink var(--pt-luxe-duration) var(--pt-luxe-ease) both;
}

html[data-page-transition="luxe"]::view-transition-new(root) {
  animation: pt-luxe-settle var(--pt-luxe-duration) linear both;
}

/* Back runs the same choreography downward. */
html[data-page-transition="luxe"][data-page-transition-direction="back"] {
  --pt-luxe-travel: -1;
}

html[data-page-transition="luxe"] {
  --pt-luxe-travel: 1;
}

/* The sheet covers the old page, then dissolves into the new one. It is the
   page color, so the dissolve reads as the new content arriving. */
@keyframes pt-luxe-sheet {
  0% { transform: translate3d(0, calc(112vh * var(--pt-luxe-travel)), 0); }

  50% {
    opacity: 1;
    transform: translate3d(0, 0, 0);
    animation-timing-function: ease-out;
  }

  100% {
    opacity: 0;
    transform: translate3d(0, 0, 0);
  }
}

@keyframes pt-luxe-sink {
  50%, 100% {
    transform: translate3d(0, calc(-6vh * var(--pt-luxe-travel)), 0) scale(0.97);
  }
}

/* Hidden until the sheet covers the old page, then rises into place as the
   sheet dissolves. */
@keyframes pt-luxe-settle {
  0%, 50% {
    opacity: 0;
    transform: translate3d(0, calc(5vh * var(--pt-luxe-travel)), 0);
  }

  50.1% {
    opacity: 1;
    transform: translate3d(0, calc(5vh * var(--pt-luxe-travel)), 0);
    animation-timing-function: var(--pt-settle-ease);
  }

  100% {
    opacity: 1;
    transform: translate3d(0, 0, 0);
  }
}

/* --- shared -------------------------------------------------------------- */

@keyframes vt-refocus-out {
  to {
    opacity: 0;
  }
}

@keyframes vt-refocus-in {
  from {
    opacity: 0;
  }
}

@keyframes vt-fade-out {
  to { opacity: 0; }
}

@keyframes vt-fade-in {
  from { opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*) {
    animation-duration: 0.01ms !important;
    animation-delay: 0s !important;
  }
}

/* Switcher shown after visiting a page with ?pt=<variant> (page-transitions.js). */
.page-transition-lab {
  position: fixed;
  left: 16px;
  bottom: 16px;
  z-index: 10002;
  display: flex;
  gap: 2px;
  padding: 4px;
  border: 1px solid var(--theme-chrome-hairline, rgb(127 127 127 / 0.3));
  border-radius: 999px;
  background: var(--theme-bg);
  color: var(--theme-ink);
  box-shadow: var(--theme-menu-shadow);
  font: 500 0.8125rem/1 'Manrope', sans-serif;
}

.page-transition-lab button {
  padding: 8px 12px;
  border-radius: 999px;
  color: inherit;
  opacity: 0.6;
  text-transform: capitalize;
  transition: opacity var(--motion-fast) ease, background-color var(--motion-fast) ease;
}

.page-transition-lab button:hover,
.page-transition-lab button:focus-visible {
  opacity: 1;
}

.page-transition-lab button[aria-pressed="true"] {
  background: var(--theme-ink);
  color: var(--theme-bg);
  opacity: 1;
}

.page-transition-lab .page-transition-lab-close {
  padding: 8px 10px;
}

/* Native View Transitions are progressive enhancement. On browsers without
   that API, internal navigation still gets a short color-field exit so a
   page change feels intentional without blocking the browser's navigation. */
@media (prefers-reduced-motion: no-preference) {
  html.page-transitioning-out::after {
    position: fixed;
    inset: 0;
    z-index: 10001;
    content: '';
    pointer-events: none;
    background: var(--theme-bg, #FFFFFF);
    animation: pastelle-page-exit 0.2s var(--ease-out-expo) both;
  }
}

@keyframes pastelle-page-exit {
  from {
    opacity: 0;
    transform: translate3d(0, 0.5rem, 0);
  }

  to {
    opacity: 1;
    transform: translate3d(0, 0, 0);
  }
}

@media (prefers-reduced-motion: no-preference) {
  .shared-artwork-transitioning {
    animation: pastelle-shared-artwork-exit 0.2s var(--ease-out-expo) both;
  }
}

@keyframes pastelle-shared-artwork-exit {
  from {
    opacity: 1;
    transform: translate3d(0, 0, 0) scale(1);
  }

  to {
    opacity: 0.72;
    transform: translate3d(0, -0.25rem, 0) scale(0.985);
  }
}

/* ========== NAVBAR STYLES ========== */

/* One token-driven rule per state, for every theme. Keeping the theme out
   of the selector matters: the old html.navy / html.pastel variants carried
   more specificity than a page's own `#navbar > .absolute`, so page-level
   navbar treatments silently stopped applying in those themes and the bar
   drifted away from the page background it sits on. */
#navbar {
  color: var(--theme-ink);
}

/* Scroll-direction response: the bar slides away as you read downward
   and returns the moment you scroll back up (see navbar.js). */
#navbar {
  transition: transform 0.22s var(--ease-out-expo);
}

#navbar.nav-hidden {
  transform: translateY(-102%);
}

@media (prefers-reduced-motion: reduce) {
  #navbar {
    transition: none;
  }

  #navbar.nav-hidden {
    transform: none;
  }
}

#navbar a,
#navbar button {
  color: inherit !important;
}

#navbar button[aria-label="Toggle theme"] {
  scale: none !important;
}

#navbar .relative.group > button > svg {
  rotate: 0deg !important;
  transform: none !important;
}

#navbar .relative.group:hover > button > svg,
#navbar .relative.group:focus-within > button > svg {
  rotate: 180deg !important;
}

#navbar button[aria-label="Toggle theme"] {
  transition: opacity 0.18s ease !important;
}

#navbar button[aria-label="Toggle theme"]:hover,
#navbar button[aria-label="Toggle theme"]:focus-visible {
  opacity: 0.7;
  transform: none !important;
}

/* ==========================================================================
   NAVIGATION REVAMP
   Restyles the shared navbar markup in place: quieter desktop dropdowns and
   a full-bleed mobile sheet. Everything here targets the existing structure,
   so no per-page markup changes are needed. Theme colour rules live further
   down the file and intentionally still win over the neutral defaults set
   here — this block owns geometry and motion, not palette.
   ========================================================================== */

:root {
  --pnav-ease: var(--ease-out-soft);
  --pnav-rule: color-mix(in srgb, currentColor 12%, transparent);
  --pnav-rule-soft: color-mix(in srgb, currentColor 8%, transparent);
  --pnav-h: 5rem;
}

/* ========== SCROLL PROGRESS INDICATOR ========== */

#scroll-progress {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 1px;
  background: linear-gradient(90deg, #121212, #666);
  z-index: 9998;
  transform: scaleX(0);
  transition: transform 0.08s linear;
  transform-origin: left;
  will-change: transform;
}

.dark #scroll-progress {
  background: linear-gradient(90deg, #FFFFFF, #999);
}

/* ========== BACK TO TOP BUTTON ========== */

#back-to-top {
  position: fixed;
  bottom: 2rem;
  right: 2rem;
  width: 48px;
  height: 48px;
  border-radius: var(--radius-round);
  background: #121212;
  color: #fff;
  border: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  visibility: hidden;
  transform: translateY(20px) scale(0.8);
  transition: opacity 0.18s var(--ease-out-expo),
              visibility 0.18s var(--ease-out-expo),
              transform 0.22s var(--ease-out-expo),
              background 0.16s ease;
  box-shadow: none;
  z-index: 1000;
}

.dark #back-to-top {
  background: #FFFFFF;
  color: #121212;
  box-shadow: none;
}

#back-to-top.visible {
  opacity: 1;
  visibility: visible;
  transform: translateY(0) scale(1);
}

#back-to-top:hover {
  transform: translateY(-2px) scale(1.03);
  box-shadow: none;
}

.dark #back-to-top:hover {
  box-shadow: none;
}

#back-to-top:active {
  transform: translateY(-2px) scale(1);
}

#back-to-top svg {
  width: 20px;
  height: 20px;
  transition: transform 0.18s var(--ease-out-expo);
}

#back-to-top:hover svg {
  transform: translateY(-2px);
}

/* ========== ENHANCED THEME TOGGLE ========== */

.theme-toggle-enhanced {
  position: relative;
  overflow: hidden;
  /* Guarantee a 40x40 tap target without shifting surrounding layout. */
  min-width: 40px;
  min-height: 40px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.theme-toggle-enhanced svg {
  transition: transform 0.24s var(--ease-out-expo),
              opacity 0.18s ease;
}

.theme-toggle-enhanced .sun-icon {
  opacity: 1;
}

.theme-toggle-enhanced .moon-icon,
.theme-toggle-enhanced .palette-icon,
.theme-toggle-enhanced .prism-icon {
  opacity: 0;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%) rotate(-30deg);
}

/* Hover effects: explicit selectors prevent absolute transform/translate overrides */
.theme-toggle-enhanced:hover .sun-icon {
  transform: rotate(20deg) scale(1.1);
}

.theme-toggle-enhanced:hover .moon-icon,
.theme-toggle-enhanced:hover .palette-icon,
.theme-toggle-enhanced:hover .prism-icon {
  transform: translate(-50%, -50%) rotate(20deg) scale(1.1);
}

/* Dark theme toggle state (excluding Navy) */
html.dark:not(.navy) .theme-toggle-enhanced .sun-icon {
  opacity: 0;
  transform: rotate(90deg);
}

html.dark:not(.navy) .theme-toggle-enhanced .moon-icon {
  opacity: 1;
  transform: translate(-50%, -50%) rotate(0deg);
}

/* Navy theme toggle state */
html.navy .theme-toggle-enhanced .sun-icon,
html.navy .theme-toggle-enhanced .moon-icon {
  opacity: 0;
  transform: translate(-50%, -50%) rotate(30deg);
}

html.navy .theme-toggle-enhanced .palette-icon {
  opacity: 1;
  transform: translate(-50%, -50%) rotate(0deg);
}

/* Pastel theme toggle state */
html.pastel .theme-toggle-enhanced .sun-icon,
html.pastel .theme-toggle-enhanced .moon-icon,
html.pastel .theme-toggle-enhanced .palette-icon {
  opacity: 0;
  transform: translate(-50%, -50%) rotate(30deg);
}

html.pastel .theme-toggle-enhanced .prism-icon {
  opacity: 1;
  transform: translate(-50%, -50%) rotate(0deg);
}

html.pastel .theme-toggle-enhanced {
  color: var(--pastelle-pastel-accent) !important;
  background-color: transparent !important;
  box-shadow: none !important;
}

html.pastel .theme-toggle-enhanced:hover {
  color: var(--pastelle-pastel-ink) !important;
  background-color: transparent !important;
  box-shadow: none !important;
}

/* Position indicator: one dot per theme in the light > dark > navy > pastel
   cycle. Absolutely positioned so it never affects the button's box. */
.theme-toggle-enhanced .theme-toggle-dots {
  position: absolute;
  left: 50%;
  bottom: 4px;
  transform: translateX(-50%);
  display: flex;
  gap: 2px;
  pointer-events: none;
  line-height: 0;
}

.theme-toggle-enhanced .theme-toggle-dots i {
  width: 3px;
  height: 3px;
  border-radius: var(--radius-round);
  background-color: currentColor;
  opacity: 0.22;
  transition: opacity 0.18s ease;
}

.theme-toggle-enhanced .theme-toggle-dots[data-active="0"] i:nth-child(1),
.theme-toggle-enhanced .theme-toggle-dots[data-active="1"] i:nth-child(2),
.theme-toggle-enhanced .theme-toggle-dots[data-active="2"] i:nth-child(3),
.theme-toggle-enhanced .theme-toggle-dots[data-active="3"] i:nth-child(4) {
  opacity: 0.9;
}

@media (prefers-reduced-motion: reduce) {
  .theme-toggle-enhanced .theme-toggle-dots i {
    transition: none;
  }
}

/* ========== LONG-FORM COLLECTION PAGES ========== */

/* Long-form pages paint their own page field; one token-driven rule covers
   light, dark, navy and pastel. */
body.collection-page,
body.orbital-page {
  background: var(--theme-bg) !important;
}

.collection-page .collection-hero {
  padding-top: 0 !important;
}

.collection-page .collection-hero h1 {
  font-size: var(--type-xl)!important;
  line-height: 0.95 !important;
  letter-spacing: -0.025em !important;
  text-wrap: balance;
}

.collection-page .collection-hero > div > .flex:first-of-type > span,
.collection-page .collection-hero > div > .flex:last-child > p {
  display: none !important;
}

.collection-page .collection-hero a {
  font-variant-numeric: tabular-nums;
}

.collection-page .collection-hero p {
  max-width: 52rem;
  line-height: 1.45;
}

.collection-page .collection-hero .h-px {
  opacity: 0.16 !important;
}

.collection-page .collection-live {
  margin-top: clamp(1.25rem, 3vw, 3rem);
  padding-top: clamp(2rem, 4vw, 4.5rem) !important;
  padding-bottom: clamp(3rem, 6vw, 6rem) !important;
}

/* Palette is split out and carries the `html body` prefix so it also wins
   against the per-theme `.bg-neutral-*` overrides at the end of this file. */
html body.collection-page .collection-live {
  background: color-mix(in srgb, var(--theme-live-bg) 88%, transparent) !important;
  border-top: 1px solid var(--theme-live-hairline);
  border-bottom: 1px solid var(--theme-live-hairline);
}

.collection-page .collection-gallery {
  scroll-margin-top: 6rem;
}

.collection-scroll-indicator {
  position: fixed;
  left: 50%;
  bottom: 1.2rem;
  z-index: 45;
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  transform: translateX(-50%);
  padding: 0.55rem 0.72rem 0.55rem 0.9rem;
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: 999px;
  background: #55544F;
  color: #D5D4D3;
  box-shadow: none;
  backdrop-filter: blur(18px) saturate(130%);
  -webkit-backdrop-filter: blur(18px) saturate(130%);
  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace;
  font-size: var(--type-xs);
  line-height: 1;
  transition:
    transform 0.25s ease,
    border-color 0.25s ease,
    color 0.25s ease;
}

.collection-scroll-indicator::after {
  content: "";
  width: 0.42rem;
  height: 0.42rem;
  border-right: 1px solid currentColor;
  border-bottom: 1px solid currentColor;
  transform: rotate(45deg);
  animation: collection-scroll-cue 1.4s ease-in-out infinite;
}

.collection-scroll-indicator:hover,
.collection-scroll-indicator:focus-visible {
  color: #fff;
  border-color: #5F5E58;
  transform: translateX(-50%) translateY(-2px);
}

html:not(.dark) .collection-scroll-indicator {
  border-color: #E3E3E3;
  background: rgba(236, 235, 221, 0.82);
  color: #505050;
  box-shadow: none;
}

html:not(.dark) .collection-scroll-indicator:hover,
html:not(.dark) .collection-scroll-indicator:focus-visible {
  color: #121212;
  border-color: #BDBDBD;
}

@keyframes collection-scroll-cue {
  0%,
  100% {
    translate: 0 -1px;
    opacity: 0.65;
  }

  50% {
    translate: 0 3px;
    opacity: 1;
  }
}

.collection-page .collection-live .grid {
  display: flex !important;
  flex-direction: column !important;
  align-items: center !important;
  gap: clamp(1.25rem, 3vw, 2.25rem) !important;
}

.collection-page .collection-live .grid > :first-child {
  order: 2;
  width: 100% !important;
  max-width: min(100%, 980px, calc(100dvh - 5rem)) !important;
  display: flex !important;
  justify-content: center !important;
}

.collection-page .collection-live .grid > :last-child {
  order: 1;
  width: 100% !important;
  display: flex !important;
  justify-content: center !important;
}

.collection-page .collection-live h2 {
  display: none !important;
}

.collection-page .collection-live .grid > :first-child > .p-4 {
  width: min(100%, 32rem);
  text-align: center;
  background: rgba(255, 255, 255, 0.54);
}

.dark .collection-page .collection-live .grid > :first-child > .p-4 {
  background: rgba(255, 255, 255, 0.035);
}

.collection-live-title-page .collection-hero {
  display: none !important;
}

.collection-live-title-page .collection-live {
  margin-top: 0 !important;
  padding-top: 0 !important;
}

.collection-live-title-page .collection-live .grid {
  display: grid !important;
  grid-template-columns: minmax(14rem, 0.55fr) minmax(0, 1.45fr);
  grid-template-rows: auto auto;
  align-items: center !important;
  column-gap: clamp(2rem, 5vw, 6rem) !important;
  row-gap: clamp(1rem, 2vw, 1.75rem) !important;
}

.collection-live-title-page .collection-live-copy {
  grid-column: 1;
  grid-row: 1 / span 2;
  align-self: center;
  justify-self: start;
  width: 100% !important;
  max-width: 38rem !important;
  display: block !important;
}

.collection-live-title-page .collection-live-copy h1 {
  font-size: var(--type-xl)!important;
  line-height: 0.92 !important;
  letter-spacing: -0.03em !important;
  text-wrap: balance;
}

.collection-live-title-page .collection-live .grid > .collection-live-copy + div {
  grid-column: 2;
  grid-row: 2;
  align-self: start;
  justify-self: end;
  width: min(100%, 980px, calc(100dvh - 5rem)) !important;
  max-width: min(100%, 980px, calc(100dvh - 5rem)) !important;
  display: flex !important;
  justify-content: center !important;
}

.collection-live-title-page .collection-live .grid > .collection-live-copy + div:not(:has(.p-4)) {
  display: none !important;
}

.collection-live-title-page .collection-live .grid > :last-child {
  grid-column: 2;
  grid-row: 1;
  align-self: center;
  justify-self: end;
  width: 100% !important;
  display: flex !important;
  justify-content: flex-end !important;
}

.collection-live-title-page .collection-live-frame {
  margin-left: auto !important;
  margin-right: 0 !important;
}

.collection-page .collection-live-frame {
  max-width: min(100%, 980px, calc(100dvh - 5rem)) !important;
  margin-left: auto !important;
  margin-right: auto !important;
  border-radius: var(--radius) !important;
}

/* Palette only — kept off the geometry rule above so the margin overrides
   in .collection-live-title-page and the width media queries still win. */
html body.collection-page .collection-live-frame {
  border: 1px solid var(--theme-frame-hairline) !important;
  background: var(--theme-frame-bg) !important;
  box-shadow: var(--theme-frame-shadow) !important;
}

.collection-page .collection-live-frame iframe {
  display: block;
  background: #fff;
}

.collection-page .collection-gallery {
  padding-top: clamp(5rem, 8vw, 9rem) !important;
  padding-bottom: clamp(6rem, 9vw, 10rem) !important;
}

.collection-page .collection-gallery > .text-center,
.collection-page .collection-gallery > .text-left {
  text-align: left !important;
  max-width: 58rem;
  margin-left: 0 !important;
  margin-right: auto !important;
  margin-bottom: clamp(3rem, 6vw, 6rem) !important;
}

.collection-page .collection-gallery h2 {
  font-size: var(--type-xl)!important;
  line-height: 0.95 !important;
  letter-spacing: -0.035em !important;
  font-weight: 500 !important;
  text-wrap: balance;
}

html body.collection-page .collection-gallery p {
  max-width: 44rem !important;
  margin-left: 0 !important;
  margin-right: auto !important;
  color: var(--theme-copy-muted) !important;
  line-height: 1.65 !important;
}

.collection-page .collection-gallery .grid,
.collection-page .collection-gallery #galleryGrid,
.collection-page .collection-gallery #gallery-grid {
  gap: clamp(1rem, 2vw, 2rem) !important;
}

.collection-page .gallery-item {
  cursor: zoom-in;
  border-radius: var(--radius);
  transition:
    transform 0.42s var(--ease-out-expo),
    opacity 0.25s ease !important;
}

.collection-page .gallery-item:hover,
.collection-page .gallery-item:focus-visible {
  transform: translate3d(0, -9px, 0) scale(1.015);
}

.collection-page .gallery-item > .relative,
.collection-page .gallery-item .aspect-ratio-box {
  border-radius: var(--radius) !important;
  margin-bottom: 0 !important;
  background: #ecebe2 !important;
  border: 1px solid rgba(18, 18, 18, 0.075);
  /* Stacked to match the elevation ramps in the theme tokens — this was the
     last single-blur shadow left on a raised surface. */
  box-shadow: none;
}

.dark .collection-page .gallery-item > .relative,
.dark .collection-page .gallery-item .aspect-ratio-box {
  background: #171713 !important;
  border-color: #26251E;
  box-shadow: none;
}

.collection-page .gallery-item img {
  transform-origin: center;
  transition:
    transform 0.55s var(--ease-out-expo),
    filter 0.45s ease !important;
}

.collection-page .gallery-item:hover img,
.collection-page .gallery-item:focus-visible img {
  transform: scale(1.06) !important;
  filter: contrast(1.02);
}

/* Orbital uses the same quiet, image-first rhythm as the Vasarely study page.
   Its page background is set with body.collection-page further up. */
.orbital-page .collection-hero {
  padding-top: 0 !important;
}

.orbital-page .orbital-title-row {
  display: flex;
  align-items: end;
  justify-content: space-between;
  min-height: 0;
  overflow: visible;
}

.orbital-page .orbital-title {
  position: relative;
  width: max-content;
  max-width: 100%;
  color: #fafafa;
  animation: orbital-title-reveal 900ms var(--ease-out-expo) both;
}

html:not(.dark) .orbital-page .orbital-title {
  color: #111;
}

.orbital-page .orbital-title::before {
  content: "";
  position: absolute;
  left: 0.04em;
  right: -0.12em;
  bottom: -0.16em;
  z-index: -1;
  height: 1px;
  background: currentColor;
  opacity: 0.34;
  transform: scaleX(0);
  transform-origin: left center;
  animation: orbital-title-rule 900ms var(--ease-out-expo) 220ms both;
}

html:not(.dark) .orbital-page .orbital-title::before {
  opacity: 0.26;
}

@keyframes orbital-title-reveal {
  from {
    clip-path: inset(0 100% 0 0);
    letter-spacing: -0.025em;
    opacity: 0.72;
    transform: translateY(0.08em);
  }

  to {
    clip-path: inset(0 0 0 0);
    letter-spacing: -0.06em;
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes orbital-title-rule {
  to {
    transform: scaleX(1);
  }
}

.orbital-page .collection-gallery {
  padding-top: clamp(1.5rem, 3vw, 3rem) !important;
}

.orbital-page .collection-gallery #gallery-grid {
  --orbital-gap: clamp(0.9rem, 1.6vw, 1.75rem);
  display: grid !important;
  grid-template-columns: repeat(12, minmax(0, 1fr)) !important;
  gap: var(--orbital-gap) !important;
}

.orbital-page .gallery-item {
  cursor: pointer;
  min-width: 0;
  position: relative;
  overflow: hidden;
  border: 1px solid rgba(23, 23, 23, 0.075);
  background: rgba(245, 245, 240, 0.72);
}

.orbital-page .gallery-item.orbital-tile-small {
  --orbital-span: 3;
}

.orbital-page .gallery-item.orbital-tile-medium {
  --orbital-span: 4;
}

.orbital-page .gallery-item.orbital-tile-large {
  --orbital-span: 6;
}

.orbital-page .gallery-item.orbital-tile-feature {
  --orbital-span: 6;
}

.orbital-page .gallery-item.orbital-tile-wide {
  --orbital-span: 12;
}

.orbital-page .gallery-item.orbital-slot-1 {
  grid-column: 1 / span 6;
  grid-row: 1 / span 6;
}

.orbital-page .gallery-item.orbital-slot-2 {
  grid-column: 7 / span 3;
  grid-row: 1 / span 3;
}

.orbital-page .gallery-item.orbital-slot-3 {
  grid-column: 10 / span 3;
  grid-row: 1 / span 3;
}

.orbital-page .gallery-item.orbital-slot-4 {
  grid-column: 7 / span 3;
  grid-row: 4 / span 3;
}

.orbital-page .gallery-item.orbital-slot-5 {
  grid-column: 10 / span 3;
  grid-row: 4 / span 3;
}

.orbital-page .gallery-item.orbital-slot-6 {
  grid-column: 1 / span 4;
  grid-row: 7 / span 4;
}

.orbital-page .gallery-item.orbital-slot-7 {
  grid-column: 5 / span 4;
  grid-row: 7 / span 4;
}

.orbital-page .gallery-item.orbital-slot-8 {
  grid-column: 9 / span 4;
  grid-row: 7 / span 4;
}

.orbital-page .gallery-item.orbital-slot-9 {
  grid-column: 1 / span 6;
  grid-row: 11 / span 6;
}

.orbital-page .gallery-item.orbital-slot-10 {
  grid-column: 7 / span 6;
  grid-row: 11 / span 6;
}

.orbital-page .gallery-item > .relative {
  aspect-ratio: 1 / 1 !important;
  height: 100% !important;
  margin-bottom: 0 !important;
  background: rgba(245, 245, 240, 0.72) !important;
  box-shadow: none !important;
  border: 0 !important;
}

.dark .orbital-page .gallery-item {
  border-color: #25251D;
  background: rgba(20, 20, 17, 0.72);
}

.dark .orbital-page .gallery-item > .relative {
  background: rgba(20, 20, 17, 0.72) !important;
  box-shadow: none !important;
}

.orbital-page .gallery-item img {
  object-fit: contain !important;
}

.orbital-page .gallery-item [class*="bg-red-500"] {
  display: none !important;
}

.orbital-page .orbital-card-copy {
  display: flex;
  flex-direction: column;
  gap: 0.65rem;
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 5;
  padding: clamp(0.8rem, 1.2vw, 1.15rem);
  background:
    linear-gradient(180deg, transparent, rgba(250, 250, 250, 0.88) 34%, rgba(250, 250, 250, 0.96));
  opacity: 0;
  transform: translateY(0.4rem);
  transition:
    opacity 0.25s ease,
    transform 0.25s ease;
}

.dark .orbital-page .orbital-card-copy {
  background:
    linear-gradient(180deg, transparent, rgba(10, 10, 10, 0.78) 34%, rgba(10, 10, 10, 0.94));
}

.orbital-page .gallery-item:hover .orbital-card-copy,
.orbital-page .gallery-item:focus-within .orbital-card-copy {
  opacity: 1;
  transform: translateY(0);
}

.orbital-page .orbital-card-heading {
  display: block;
}

.orbital-page .orbital-card-title {
  min-width: 0;
  letter-spacing: 0;
  color: #171717;
  text-wrap: balance;
}

.dark .orbital-page .orbital-card-title {
  color: #fafafa;
}

.orbital-page .orbital-card-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
}

.orbital-page .orbital-edition-label {
  flex: 0 0 auto;
  width: max-content;
  border: 1px solid rgba(212, 212, 212, 1);
  border-radius: var(--radius);
  padding: 0.25rem 0.75rem;
  color: #4F4F4F;
  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace;
  font-size: var(--type-xs);
  line-height: 1.1;
}

.dark .orbital-page .orbital-edition-label {
  border-color: rgba(64, 64, 64, 1);
  color: #949490;
}

.orbital-page .gallery-item a[href*="superrare.com/artwork"] {
  width: max-content;
  border-radius: var(--radius) !important;
  background: transparent;
  line-height: 1.1;
}

.orbital-page .gallery-item a[href*="superrare.com/artwork"]:hover,
.orbital-page .gallery-item a[href*="superrare.com/artwork"]:focus-visible {
  background: #171717 !important;
  color: #fff !important;
}

.dark .orbital-page .gallery-item a[href*="superrare.com/artwork"]:hover,
.dark .orbital-page .gallery-item a[href*="superrare.com/artwork"]:focus-visible {
  background: #fafafa !important;
  color: #0a0a0a !important;
}

@media (min-width: 1024px) {
  .orbital-page .gallery-item.orbital-tile-small .orbital-card-copy {
    padding: 0.8rem;
  }

  .orbital-page .gallery-item.orbital-tile-small .orbital-card-title {
    font-size: var(--type-base)!important;
  }

  .orbital-page .gallery-item.orbital-tile-small .orbital-card-actions {
    align-items: flex-start;
    flex-direction: column;
    gap: 0.5rem;
  }
}

.orbital-page .modal-content {
  max-width: min(1180px, calc(100vw - 2rem)) !important;
}

.orbital-page .modal-image {
  box-shadow: none !important;
}

.orbital-page .modal-title {
  font-weight: 500 !important;
  letter-spacing: -0.02em;
}

.orbital-page .modal-details {
  color: #6F6F6F !important;
}

.dark .orbital-page .modal-details {
  color: #ABABA8 !important;
}

.orbital-page .modal-buttons a {
  border-radius: var(--radius) !important;
  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace;
  font-size: var(--type-xs)!important;
}

html body.collection-page .lightbox,
html body.collection-page .modal-overlay {
  background: var(--theme-scrim) !important;
  backdrop-filter: blur(22px) !important;
}

html body.collection-page .lightbox > div[onclick],
html body.collection-page .lightbox-stage,
html body.collection-page .modal-content {
  border-radius: var(--radius) !important;
  border: 1px solid var(--theme-modal-hairline) !important;
  background: var(--theme-modal-bg) !important;
  box-shadow: var(--theme-modal-shadow) !important;
}

.collection-page footer {
  background: var(--theme-cfooter-bg) !important;
  color: var(--theme-cfooter-ink) !important;
  border-top: 1px solid var(--theme-cfooter-hairline) !important;
}

@media (min-width: 1024px) {
  .collection-page .collection-live-frame {
    margin-left: auto !important;
    margin-right: auto !important;
  }

  .collection-live-title-page .collection-live-frame {
    margin-left: auto !important;
    margin-right: 0 !important;
  }
}

@media (max-width: 767px) {
  .collection-page .collection-hero > div > .flex {
    align-items: flex-start !important;
    flex-direction: column !important;
  }

  .collection-page .collection-hero a {
    align-self: flex-start;
  }

  .collection-page .collection-live h2 {
    max-width: none;
  }

  .collection-page .collection-live-frame {
    max-width: 100% !important;
  }

  .collection-live-title-page .collection-live {
    padding-top: 0 !important;
  }

  .collection-live-title-page .collection-live .grid {
    grid-template-columns: 1fr;
    grid-template-rows: auto auto auto;
    row-gap: 1.25rem !important;
  }

  .collection-live-title-page .collection-live-copy {
    grid-column: 1;
    grid-row: 1;
  }

  .collection-live-title-page .collection-live-copy h1 {
    font-size: var(--type-xl)!important;
  }

  .collection-live-title-page .collection-live .grid > :last-child {
    grid-column: 1;
    grid-row: 2;
    justify-content: center !important;
  }

  .collection-live-title-page .collection-live .grid > .collection-live-copy + div {
    grid-column: 1;
    grid-row: 3;
    justify-self: center;
  }

  .collection-live-title-page .collection-live-frame {
    margin-left: auto !important;
    margin-right: auto !important;
  }

  .collection-scroll-indicator {
    bottom: 0.85rem;
    padding: 0.5rem 0.66rem 0.5rem 0.78rem;
    font-size: var(--type-xs);
  }

  .collection-page .collection-gallery .grid,
  .collection-page .collection-gallery #galleryGrid,
  .collection-page .collection-gallery #gallery-grid {
    gap: 0.9rem !important;
  }

  .orbital-page .collection-gallery {
    padding-top: clamp(3rem, 16vw, 5rem) !important;
  }

  .orbital-page .collection-gallery #gallery-grid {
    --orbital-gap: clamp(1.1rem, 5vw, 1.5rem);
    grid-template-columns: repeat(6, minmax(0, 1fr)) !important;
    gap: clamp(1.5rem, 8vw, 2.25rem) !important;
  }

  .orbital-page .gallery-item,
  .orbital-page .gallery-item.orbital-tile-small,
  .orbital-page .gallery-item.orbital-tile-medium,
  .orbital-page .gallery-item.orbital-tile-large,
  .orbital-page .gallery-item.orbital-tile-feature,
  .orbital-page .gallery-item.orbital-tile-wide,
  .orbital-page .gallery-item[class*="orbital-slot-"] {
    --orbital-span: 6;
    grid-column: 1 / -1;
    grid-row: auto / span 6;
  }

  .orbital-page .orbital-card-actions {
    align-items: flex-start;
    flex-direction: column;
    gap: 0.55rem;
  }
}

/* Reduced Motion Support */
@media (prefers-reduced-motion: reduce) {
  .collection-scroll-indicator::after {
    animation: none;
  }

  .orbital-page .orbital-title,
  .orbital-page .orbital-title::before {
    animation: none;
  }

  .orbital-page .orbital-title {
    clip-path: none;
    opacity: 1;
    transform: none;
  }

  .orbital-page .orbital-title::before {
    transform: scaleX(1);
  }
}

/* =========================================
   NAVY + PASTEL THEME OVERRIDES
   Must be at the end of the file so they win over the Dark mode styles
   (.dark / html.dark) that navy also matches.

   Both themes reskin the same set of Tailwind utilities, so the selectors
   are shared and every value comes from the theme tokens at the top of this
   file. Only genuinely theme-specific declarations are written out per
   theme below.
   ========================================= */

html.navy {
  background-color: #061830 !important;
  color-scheme: dark;

  /* Redefine Tailwind v4 theme variables for Navy mode */
  --color-neutral-50: #061830;
  --color-neutral-100: #0b2240;
  --color-neutral-200: rgba(220, 235, 255, 0.14);
  --color-neutral-300: rgba(220, 235, 255, 0.2);
  --color-neutral-700: rgba(220, 235, 255, 0.6);
  --color-neutral-800: rgba(220, 235, 255, 0.14);
  --color-neutral-900: #0b2240;
  --color-neutral-950: #061830;
}

html.pastel {
  background-color: var(--pastelle-pastel-bg) !important;
  color-scheme: light;

  --color-neutral-50: var(--pastelle-pastel-bg);
  --color-neutral-100: var(--pastelle-pastel-surface);
  --color-neutral-200: var(--pastelle-pastel-hairline);
  --color-neutral-300: color-mix(in srgb, var(--pastelle-pastel-ink) 20%, transparent);
  --color-neutral-700: var(--pastelle-pastel-muted);
  --color-neutral-800: color-mix(in srgb, var(--pastelle-pastel-ink) 74%, var(--pastelle-pastel-bg) 26%);
  --color-neutral-900: var(--pastelle-pastel-ink);
  --color-neutral-950: color-mix(in srgb, var(--pastelle-pastel-ink) 82%, black 18%);
}

html.navy body,
html.pastel body {
  background-color: var(--theme-bg) !important;
}

html.navy body {
  color: #fff;
}

html.pastel body {
  color: var(--pastelle-pastel-ink) !important;
}

@media (prefers-reduced-motion: no-preference) {
  html.pastel body,
  html.pastel .bg-neutral-50,
  html.pastel .bg-neutral-100,
  html.pastel .dark\:bg-neutral-950,
  html.pastel .dark\:bg-neutral-900 {
    transition:
      background-color 260ms var(--ease-out-expo),
      color 260ms var(--ease-out-expo),
      border-color 260ms var(--ease-out-expo),
      box-shadow 260ms var(--ease-out-expo);
  }

  html.pastel.pastel-settling body {
    animation: pastel-color-settle 240ms var(--ease-out-expo) both;
  }
}

@keyframes pastel-color-settle {
  0% {
    filter: saturate(0.9) brightness(1.04);
  }

  55% {
    filter: saturate(1.08) brightness(1.01);
  }

  100% {
    filter: saturate(1) brightness(1);
  }
}

html.pastel ::selection {
  background: color-mix(in srgb, var(--pastelle-pastel-accent) 22%, transparent);
  color: var(--pastelle-pastel-ink);
}

/* ── Long-form page surfaces ─────────────────────────────────────────────
   collection-live, collection-live-frame, the lightbox/modal panels and the
   page footer are all token-driven in the base rules above and need no
   navy/pastel copies. */

html.navy .collection-scroll-indicator,
html.pastel .collection-scroll-indicator {
  background: var(--theme-menu-bg) !important;
  border-color: var(--theme-hairline) !important;
}

html.navy .collection-scroll-indicator {
  color: #B8C4D3 !important;
}

html.pastel .collection-scroll-indicator {
  color: var(--pastelle-pastel-muted) !important;
}

/* ── Tailwind utility reskins ────────────────────────────────────────────
   One rule per utility group per property, shared by both themes. */

html.navy .bg-neutral-50,
html.navy .dark\:bg-neutral-950,
html.navy .bg-neutral-950,
html.navy section.bg-neutral-50,
html.navy section.dark\:bg-neutral-950,
html.pastel .bg-neutral-50,
html.pastel .dark\:bg-neutral-950,
html.pastel .bg-neutral-950,
html.pastel section.bg-neutral-50,
html.pastel section.dark\:bg-neutral-950 {
  background-color: var(--theme-bg) !important;
}

html.navy .bg-neutral-100,
html.navy .dark\:bg-neutral-900,
html.navy .bg-neutral-900,
html.pastel .bg-neutral-100,
html.pastel .dark\:bg-neutral-900,
html.pastel .bg-neutral-900,
html.pastel .bg-white {
  background-color: var(--theme-surface) !important;
}

html.navy .border-neutral-200,
html.navy .dark\:border-neutral-800,
html.navy .dark\:border-neutral-700,
html.navy .border-neutral-200\/50,
html.navy .dark\:border-neutral-800\/50,
html.pastel .border-neutral-200,
html.pastel .dark\:border-neutral-800,
html.pastel .dark\:border-neutral-700,
html.pastel .border-neutral-200\/50,
html.pastel .dark\:border-neutral-800\/50 {
  border-color: var(--theme-hairline) !important;
}

html.navy .bg-neutral-200\/50,
html.navy .dark\:bg-neutral-800\/50,
html.pastel .bg-neutral-200\/50,
html.pastel .dark\:bg-neutral-800\/50 {
  background-color: var(--theme-chip-bg) !important;
}

html.navy .hover\:bg-neutral-200\/50:hover,
html.navy .dark\:hover\:bg-neutral-800\/50:hover,
html.pastel .hover\:bg-neutral-200\/50:hover,
html.pastel .dark\:hover\:bg-neutral-800\/50:hover {
  background-color: var(--theme-hover-strong) !important;
}

html.navy .text-neutral-900,
html.navy .dark\:text-white,
html.pastel .text-neutral-900,
html.pastel .dark\:text-white {
  color: var(--theme-ink) !important;
}

/* .text-neutral-700 / .text-neutral-500 / .text-neutral-400 are handled once
   for every theme by the TEXT READABILITY block at the end of this file
   (html.navy body … / html.pastel body …), which outranks anything written
   here — the old per-theme copies were dead weight. */

html.navy ::-webkit-scrollbar-thumb {
  background: #0f3566;
}

html.pastel ::-webkit-scrollbar-thumb {
  background: color-mix(in srgb, var(--pastelle-pastel-ink) 42%, var(--pastelle-pastel-bg) 58%);
}

html.navy .custom-scrollbar::-webkit-scrollbar-thumb {
  background-color: #3B3D3B;
}

html.pastel .custom-scrollbar::-webkit-scrollbar-thumb {
  background-color: color-mix(in srgb, var(--pastelle-pastel-ink) 22%, transparent);
}

html.navy .skeleton,
html.navy img[loading="lazy"]:not([src]) {
  background: linear-gradient(
    90deg,
    #0b2240 0px,
    #0f3566 40px,
    #0b2240 80px
  );
  background-size: 200px 100%;
}

html.pastel .skeleton,
html.pastel img[loading="lazy"]:not([src]) {
  background: linear-gradient(
    90deg,
    var(--pastelle-pastel-surface) 0px,
    color-mix(in srgb, var(--pastelle-pastel-accent) 14%, var(--pastelle-pastel-bg) 86%) 40px,
    var(--pastelle-pastel-surface) 80px
  );
  background-size: 200px 100%;
}

/* ── Pastel-only accents ─────────────────────────────────────────────── */

html.pastel a:hover,
html.pastel .hover\:text-neutral-900:hover,
html.pastel .dark\:hover\:text-white:hover {
  color: var(--pastelle-pastel-accent) !important;
}

html.pastel :focus-visible {
  outline-color: var(--pastelle-pastel-accent) !important;
}

html.pastel #scroll-progress {
  background: linear-gradient(90deg, var(--pastelle-pastel-ink), var(--pastelle-pastel-accent)) !important;
}

/* =========================================
   SHARED IMAGE MODAL + CAPSULE TABS
   Progressive interaction primitives used by galleries and filters.
   ========================================= */

[data-image-modal-trigger] {
  cursor: pointer;
}

[data-image-modal-overlay] {
  overscroll-behavior: contain;
}

[data-image-modal-overlay] :is(
  [data-image-modal-media],
  .modal-main-image img,
  #modalImage,
  .modal-image-col img
) {
  backface-visibility: hidden;
  transform: translateZ(0);
}

[data-ui-capsule].ui-capsule-group {
  position: relative !important;
  isolation: isolate;
  gap: 0 !important;
  padding: 3px !important;
  border: 1px solid var(--page-hairline, rgba(0, 0, 0, 0.1)) !important;
  border-radius: var(--radius) !important;
  background: color-mix(in srgb, var(--page-panel, #f2f1ea) 86%, transparent) !important;
}

[data-ui-capsule] > .ui-capsule-indicator {
  position: absolute;
  z-index: 0;
  top: 3px;
  bottom: 3px;
  left: 0;
  width: 0;
  border: 1px solid color-mix(
    in srgb,
    var(--page-ink, #13120a) 10%,
    var(--page-hairline, rgba(0, 0, 0, 0.1))
  );
  border-radius: var(--radius);
  background: var(--page-panel-strong, #fff);
  box-shadow: none;
  opacity: 0;
  pointer-events: none;
  transform-origin: left center;
  will-change: transform;
}

[data-ui-capsule][data-ui-capsule] > :is(button, [role="tab"]) {
  position: relative;
  z-index: 1;
  border: 0 !important;
  background: transparent !important;
  transform: none !important;
}

[data-ui-capsule][data-ui-capsule] > :is(button, [role="tab"]):hover {
  background: color-mix(in srgb, var(--page-ink, #13120a) 5%, transparent) !important;
  transform: none !important;
}

[data-ui-capsule][data-ui-capsule] > :is(
  button.active,
  button[aria-pressed="true"],
  [role="tab"][aria-selected="true"]
) {
  background: transparent !important;
  color: var(--page-ink, #13120a) !important;
  transform: none !important;
}

[data-ui-tabs] [role="tabpanel"][hidden] {
  display: none !important;
}

@media (prefers-reduced-motion: reduce) {
  [data-ui-capsule] > .ui-capsule-indicator {
    will-change: auto;
  }
}

/* =========================================
   SHARED SITE FOOTER
   One self-contained, theme-aware footer used across every page
   except the home page. Colours come from per-theme custom props so
   it adapts to light / dark / navy / pastel without page-local vars.
   ========================================= */

#site-footer {
  --footer-ink: #13120A;
  --footer-muted: var(--site-text-muted, #55544F);
  --footer-hairline: rgba(19, 18, 10, 0.12);
  margin-top: clamp(3.5rem, 7vw, 8rem);
  padding: clamp(3.5rem, 7vw, 7rem) 0 clamp(2.5rem, 5vw, 4.5rem);
  background: transparent;
  border-top: 1px solid var(--footer-hairline);
  color: var(--footer-ink);
}

.dark #site-footer {
  --footer-ink: #F6F1E3;
  --footer-muted: var(--site-text-muted, #BBB7AB);
  --footer-hairline: rgba(246, 241, 227, 0.13);
}

html.navy #site-footer {
  --footer-ink: #F4F8FF;
  --footer-muted: var(--site-text-muted, #C0C7D1);
  --footer-hairline: rgba(220, 235, 255, 0.15);
}

html.pastel #site-footer {
  --footer-ink: var(--pastelle-pastel-ink);
  --footer-muted: var(--site-text-muted, var(--pastelle-pastel-ink));
  --footer-hairline: var(--pastelle-pastel-hairline);
}

.site-footer-inner {
  width: 100%;
  margin: 0 auto;
  padding: 0 1.5rem;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: clamp(2rem, 5vw, 6rem);
  align-items: end;
}

@media (min-width: 768px) {
  .site-footer-inner {
    padding-left: 3rem;
    padding-right: 3rem;
  }
}

#site-footer a.footer-mark {
  display: inline-block;
  color: var(--footer-ink);
  font-size: var(--type-xl);
  font-weight: 700;
  line-height: 0.86;
  letter-spacing: -0.02em;
  text-decoration: none;
}

#site-footer .footer-note {
  max-width: 34rem;
  margin-top: 1.25rem;
  color: var(--footer-muted);
  font-size: var(--type-sm);
  line-height: 1.65;
}

#site-footer .footer-links {
  display: grid;
  grid-template-columns: repeat(2, minmax(6rem, auto));
  gap: 0.75rem 2.5rem;
  justify-items: start;
  font-family: 'Manrope', sans-serif;
  font-size: var(--type-xs);
  font-weight: 600;
}

#site-footer .footer-links a {
  color: var(--footer-muted);
  text-decoration: none;
  transition: color 0.18s ease, transform 0.18s ease;
}

#site-footer .footer-links a:hover {
  color: var(--footer-ink);
  transform: translate3d(3px, 0, 0);
}

@media (max-width: 767px) {
  .site-footer-inner {
    grid-template-columns: 1fr;
    align-items: start;
  }
}

/* =========================================
   TEXT READABILITY
   Muted copy uses one readable hierarchy instead of compounded opacity.
   ========================================= */

html {
  --site-text-primary: #13120A;
  --site-text-secondary: #393831;
  --site-text-muted: #55544F;
  --site-chrome-background: #DAE1E1;

  /* Keep page-specific templates on the same readable text tokens. */
  --page-muted: var(--site-text-muted) !important;
  --projects-muted: var(--site-text-muted) !important;
  --about-muted: var(--site-text-muted) !important;
  --res-muted: var(--site-text-muted) !important;
}

html.dark {
  --site-text-primary: #F6F1E3;
  --site-text-secondary: #D6D2C5;
  --site-text-muted: #BBB7AB;
  --site-chrome-background: #0F121B;
}

html.navy {
  --site-text-primary: #F4F8FF;
  --site-text-secondary: #D7DDE6;
  --site-text-muted: #C0C7D1;
  --site-chrome-background: #06142E;
}

html.pastel {
  --site-text-primary: var(--pastelle-pastel-ink);
  --site-text-secondary: var(--pastelle-pastel-ink);
  --site-text-muted: var(--pastelle-pastel-ink);
  --site-chrome-background: color-mix(in srgb, var(--pastelle-pastel-bg) 96%, #000 4%);
  --pastelle-pastel-muted: var(--pastelle-pastel-ink) !important;
}

body {
  isolation: isolate;
}

/* Scroll state classes may add Tailwind's shadow utility to the navbar
   element itself. Keep the shared chrome edge clean in every theme. */
html:root body #navbar {
  box-shadow: none !important;
}

/* Pages with a secondary action bar use a persistent, condensed navbar. Both
   bars share the exact 4rem seam after scrolling, with no translucent gap. */
html body:has(:is(#controls-bar, .collection-controls)) #navbar.nav-hidden {
  transform: none !important;
}

html body:has(#navbar.scrolled) :is(#controls-bar, .collection-controls) {
  top: 4rem !important;
}

/* `overflow-x: hidden` creates a root scroll container on narrow layouts and
   disables position: sticky. Clip the unused horizontal overflow without
   changing the element that owns vertical scrolling. */
html:has(body :is(#controls-bar, .collection-controls)),
html body:has(:is(#controls-bar, .collection-controls)) {
  overflow-x: clip !important;
}

/* Tailwind opacity utilities were being used at several different strengths
   for readable copy. Normalize only text-bearing elements; media, overlays,
   transitions, and decorative SVG opacity remain untouched. */
:is(
  p,
  a,
  button,
  span,
  label,
  li,
  dt,
  dd,
  small,
  time,
  figcaption,
  h1,
  h2,
  h3
)[class~="opacity-40"],
:is(
  p,
  a,
  button,
  span,
  label,
  li,
  dt,
  dd,
  small,
  time,
  figcaption,
  h1,
  h2,
  h3
)[class~="opacity-50"],
:is(
  p,
  a,
  button,
  span,
  label,
  li,
  dt,
  dd,
  small,
  time,
  figcaption,
  h1,
  h2,
  h3
)[class~="opacity-60"],
:is(
  p,
  a,
  button,
  span,
  label,
  li,
  dt,
  dd,
  small,
  time,
  figcaption,
  h1,
  h2,
  h3
)[class~="opacity-70"],
:is(
  p,
  a,
  button,
  span,
  label,
  li,
  dt,
  dd,
  small,
  time,
  figcaption,
  h1,
  h2,
  h3
)[class~="opacity-80"] {
  /* Text is never dimmed with opacity — opacity fades the glyph toward the
     page and takes any border or icon inside the element with it. Secondary
     text gets a secondary COLOUR and stays fully opaque. opacity-0 is left
     alone: that is the reveal-on-scroll start state, not a text treatment. */
  opacity: 1 !important;
  color: var(--site-text-muted) !important;
}

:is(
  p,
  a,
  button,
  span,
  label,
  li,
  dt,
  dd,
  small,
  time,
  figcaption,
  h1,
  h2,
  h3
)[class*="opacity-"]:not([class~="opacity-0"]):is(:hover, :focus-visible) {
  opacity: 1 !important;
  color: var(--site-text-primary) !important;
}

html body .text-neutral-700,
html.dark body .dark\:text-neutral-300,
html.navy body .text-neutral-700,
html.navy body .dark\:text-neutral-300,
html.pastel body .text-neutral-700,
html.pastel body .dark\:text-neutral-300 {
  color: var(--site-text-secondary) !important;
  opacity: 1 !important;
}

html body .text-neutral-500,
html body .text-neutral-400,
html.dark body .dark\:text-neutral-400,
html.dark body .dark\:text-neutral-500,
html.navy body .text-neutral-500,
html.navy body .text-neutral-400,
html.navy body .dark\:text-neutral-400,
html.navy body .dark\:text-neutral-500,
html.pastel body .text-neutral-500,
html.pastel body .text-neutral-400,
html.pastel body .dark\:text-neutral-400,
html.pastel body .dark\:text-neutral-500 {
  color: var(--site-text-muted) !important;
  opacity: 1 !important;
}

html body :is(
  .home-subtitle,
  .modal-subtitle,
  .detail-label,
  .entry-meta,
  .about-eyebrow,
  .about-addr,
  .collection-page .artwork-item p,
  .project-row p,
  #site-footer .footer-note,
  #site-footer .footer-links a
) {
  color: var(--site-text-muted) !important;
  opacity: 1 !important;
}

/* ========================================================================
   Shared navbar interaction refinement
   Keep the established navbar geometry. The shared layer owns the desktop
   hover, panel, row, focus, and reduced-motion interaction without changing
   the markup or the JS state hooks.
   ======================================================================== */

:root {
  --pnav-h: 5rem;
  --pnav-control-h: 2.25rem;
  --pnav-trigger-hover: color-mix(in srgb, var(--theme-ink) 6%, transparent);
  --pnav-trigger-open: color-mix(in srgb, var(--theme-ink) 9%, transparent);
  --pnav-trigger-keyline: color-mix(in srgb, var(--theme-ink) 11%, transparent);
  --pnav-trigger-indicator: color-mix(in srgb, var(--theme-ink) 68%, transparent);
  --pnav-focus-ring: color-mix(in srgb, var(--theme-ink) 46%, transparent);
  --pnav-row-hover: color-mix(in srgb, var(--theme-ink) 7%, transparent);
  --pnav-row-active: color-mix(in srgb, var(--theme-ink) 11%, transparent);
  --pnav-motion-ease: cubic-bezier(0.2, 0.74, 0.24, 1);
  --pnav-hover-duration: 150ms;
  --pnav-panel-duration: 320ms;
  --pnav-row-duration: 260ms;
  --pnav-pointer-grace: 70ms;
}

#navbar {
  height: auto !important;
}

#navbar.scrolled {
  height: 4rem !important;
}

@media (prefers-reduced-motion: reduce) {
  
  html body #navbar .relative.group > button > svg {
    transition: none !important;
    transition-delay: 0ms !important;
  }
}

/* The home page's accordion sub-items own their own resting/hover opacity
   (see the inline styles in index.html). They used to be normalised here as
   well, which outranked the page rule and killed the hover step. */

/* ========================================================================
   Sol Medium UI refresh — final shared chrome overrides
   Keep the existing navbar state hooks and WebGL seam; refine only material,
   control feedback, focus treatment, and touch sizing.
   ======================================================================== */
:root {
  --pnav-control-h: 2.5rem;
  --pnav-hover-duration: 140ms;
  --pnav-panel-duration: 180ms;
  --pnav-row-duration: 150ms;
  --pnav-pointer-grace: 40ms;
}

html body #navbar :is(.theme-toggle-enhanced, [data-mobile-menu-trigger]) {
  min-width: 40px !important;
  min-height: 40px !important;
  border: 1px solid var(--theme-hairline) !important;
  border-radius: var(--radius) !important;
  background: color-mix(in srgb, var(--theme-surface) 72%, transparent) !important;
  color: var(--theme-ink) !important;
  opacity: 1 !important;
  transition:
    color var(--pnav-hover-duration) ease,
    background-color var(--pnav-hover-duration) ease,
    border-color var(--pnav-hover-duration) ease,
    transform var(--pnav-hover-duration) var(--pnav-motion-ease) !important;
}

html body #navbar :is(.theme-toggle-enhanced, [data-mobile-menu-trigger]):hover,
html body #navbar :is(.theme-toggle-enhanced, [data-mobile-menu-trigger]):focus-visible {
  background: var(--theme-hover-soft) !important;
  border-color: var(--theme-menu-hairline) !important;
  transform: translate3d(0, -1px, 0) !important;
}

html body #navbar :is(.theme-toggle-enhanced, [data-mobile-menu-trigger]):active {
  transform: translate3d(0, 1px, 0) scale(0.98) !important;
}

html body #navbar :is(
  .theme-toggle-enhanced,
  [data-mobile-menu-trigger],
  .relative.group > div.absolute a,
  .nav-submenu-trigger
):focus-visible {
  outline: 1px solid var(--pnav-focus-ring) !important;
  outline-offset: 2px !important;
}

@media (prefers-reduced-motion: reduce) {
  html body #navbar :is(.theme-toggle-enhanced, [data-mobile-menu-trigger]) {
    transition: none !important;
    transform: none !important;
  }
}

/* shadcn Sera navigation menu, adapted to Pastelle's theme tokens. */
[data-shadcn-navigation] {
  flex: 0 0 auto;
  min-width: 0;
  min-height: 2.25rem;
}

@media (max-width: 767px) {
  [data-shadcn-navigation] {
    min-width: 0;
    min-height: 0;
  }

  

  

  

  

  

  

  

  
  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  
  

  
  

  

  

  
}

/* Interior-inspired sticky chrome contract. The shared header owns the
   document's sticky edge; secondary action bars dock below its current
   height. Page-specific shells can style their inner surface without having
   to repeat positioning or scroll-state offsets. */
:root {
  --pastelle-nav-height: 5rem;
  --pastelle-nav-height-condensed: 4rem;
  --pastelle-sticky-offset: var(--pastelle-nav-height);
}

#navbar[data-sticky-header] {
  position: sticky !important;
  top: 0 !important;
  right: auto !important;
  left: auto !important;
  width: 100% !important;
  z-index: 50 !important;
}

html body :is(#controls-bar[data-sticky-surface], .collection-controls[data-sticky-surface]) {
  position: sticky !important;
  top: var(--pastelle-sticky-offset) !important;
  z-index: 40 !important;
  isolation: isolate;
}

html body:has(#navbar.scrolled) :is(#controls-bar[data-sticky-surface], .collection-controls[data-sticky-surface]) {
  top: var(--pastelle-nav-height-condensed) !important;
}

@media (prefers-reduced-motion: reduce) {
  #navbar[data-sticky-header],
  html body :is(#controls-bar[data-sticky-surface], .collection-controls[data-sticky-surface]) {
    scroll-behavior: auto;
  }
}

/* Shared home-style navigation. */
#navbar.site-header {
  display: block;
  color: var(--theme-ink);
  background: var(--theme-bg);
  box-shadow: 0 1px 0 var(--theme-chrome-hairline);
}

#navbar.site-header > .site-header-inner {
  position: relative;
  display: flex;
  align-items: center;
  gap: 36px;
  width: 100%;
  max-width: var(--measure);
  min-height: var(--pastelle-nav-height);
  margin: 0 auto;
  padding: 0 48px;
  transition: min-height var(--motion-base) var(--ease-out-expo);
}

#navbar.scrolled > .site-header-inner {
  min-height: var(--pastelle-nav-height-condensed);
}

.site-header-brand-row { display: flex; align-items: center; }
.site-header-brand { display: flex; flex-direction: column; color: inherit; line-height: 1; text-decoration: none; }
.site-header-wordmark { font-size: 1.875rem; font-weight: 700; letter-spacing: -0.01em; }

.deck-nav {
  position: static;
  display: flex;
  align-items: center;
  gap: 36px;
  margin-left: auto;
  margin-right: 80px;
  font-size: 0.9375rem;
  font-weight: 500;
}

.deck-nav-item { position: relative; }
.deck-nav a, .deck-nav button { color: var(--theme-ink); text-decoration: none; }
.deck-nav-link, .deck-menu-trigger {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 8px 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  cursor: pointer;
}

.deck-nav-link::after, .deck-menu-trigger > span:first-child::after {
  position: absolute;
  right: 0;
  bottom: 0.3rem;
  left: 0;
  height: 1px;
  background: currentColor;
  content: '';
  opacity: 0.65;
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform var(--motion-fast) var(--ease-out-expo);
}

.deck-menu-trigger > span:first-child { position: relative; }
.deck-menu-trigger > span:first-child::after { bottom: -0.1rem; }
.deck-nav-link:hover::after, .deck-nav-link:focus-visible::after,
.deck-nav-link[aria-current="page"]::after,
.deck-menu-trigger:hover > span:first-child::after,
.deck-menu-trigger:focus-visible > span:first-child::after { transform: scaleX(1); }
.deck-menu-icon { display: inline-block; color: var(--site-text-muted, var(--theme-ink)); font-size: 0.75rem; font-weight: 400; transition: transform var(--motion-base) var(--ease-out-expo); }
.deck-menu-trigger[aria-expanded="true"] .deck-menu-icon { color: inherit; transform: rotate(135deg); }

.deck-nav-item { perspective: 900px; }
.deck-menu {
  position: absolute;
  top: calc(100% + 8px);
  left: -18px;
  z-index: 60;
  min-width: 232px;
  padding: 10px 0;
  border: 1px solid var(--theme-menu-hairline);
  background: var(--theme-menu-bg);
  box-shadow: var(--theme-menu-shadow);
  opacity: 0;
  visibility: hidden;
  transform: translate3d(0, -12px, 0) scale(0.94) rotateX(-8deg);
  transform-origin: 50% 0;
  transition: opacity 0.24s ease, transform 0.34s var(--ease-out-expo), visibility 0s linear 0.34s;
}

.deck-menu--end { right: -18px; left: auto; transform-origin: 100% 0; }
.deck-menu.is-open { opacity: 1; visibility: visible; transform: translate3d(0, 0, 0) scale(1) rotateX(0); transition: opacity 0.24s ease, transform 0.34s var(--ease-out-expo), visibility 0s; }
.deck-menu a {
  display: block;
  padding: 6px 18px;
  color: var(--site-text-muted, var(--theme-ink));
  font-size: 0.875rem;
  font-weight: 500;
  opacity: 0;
  transform: translate3d(-12px, 0, 0);
  transition:
    opacity 0.26s var(--ease-out-expo),
    transform 0.28s var(--ease-out-expo),
    color var(--motion-fast) ease;
  transition-delay: 0s, 0s, 0s;
}
.deck-menu a:nth-child(1) { --deck-menu-delay: 0ms; }
.deck-menu a:nth-child(2) { --deck-menu-delay: 18ms; }
.deck-menu a:nth-child(3) { --deck-menu-delay: 36ms; }
.deck-menu a:nth-child(4) { --deck-menu-delay: 54ms; }
.deck-menu a:nth-child(5) { --deck-menu-delay: 72ms; }
.deck-menu a:nth-child(6) { --deck-menu-delay: 90ms; }
.deck-menu a:nth-child(7) { --deck-menu-delay: 108ms; }
.deck-menu a:nth-child(8) { --deck-menu-delay: 126ms; }
.deck-menu.is-open > a {
  opacity: 1;
  transform: translate3d(0, 0, 0);
  transition-delay: var(--deck-menu-delay, 0ms), var(--deck-menu-delay, 0ms), 0s;
}
.deck-menu a:hover, .deck-menu a:focus-visible { color: var(--theme-ink); }

.site-header-theme-toggle {
  display: flex;
  width: 44px;
  height: 44px;
  flex: 0 0 44px;
  align-items: center;
  justify-content: center;
}

html body #navbar .site-header-theme-toggle {
  border: 0 !important;
  border-radius: 0 !important;
  background: transparent !important;
  box-shadow: none !important;
}

html body #navbar .site-header-theme-toggle:hover,
html body #navbar .site-header-theme-toggle:focus-visible {
  border-color: transparent !important;
  background: transparent !important;
  box-shadow: none !important;
}

.site-header-actions {
  position: absolute;
  top: 50%;
  right: 32px;
  display: flex;
  align-items: center;
  gap: 8px;
  transform: translateY(-50%);
}
.site-header-menu-toggle { display: none; }

.site-header-theme-toggle:focus-visible, .deck-nav a:focus-visible,
.deck-menu-trigger:focus-visible, .deck-menu a:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 3px;
}

.deck-page #navbar.site-header {
  position: absolute !important;
  inset: 0 0 auto;
  z-index: 30;
  background: transparent;
  box-shadow: none;
}

.deck-page #navbar .site-header-inner { width: 100%; max-width: none; min-height: 0; height: 100%; padding: 0; }
.deck-page .site-header-brand-row { position: absolute; top: 40px; left: 48px; }
.deck-page .deck-nav { position: absolute; top: 36px; right: 48px; margin: 0; }
.deck-page .site-header-actions { position: static; transform: none; }
.deck-page .site-header-theme-toggle { position: fixed; bottom: 32px; left: 36px; }

/* Wide displays: the header spans the full width like the page content, but
   keeps its desktop size (80px bar, 30px wordmark) instead of growing with the
   viewport. */
@media (min-width: 1600px) {
  #navbar.site-header > .site-header-inner {
    max-width: none;
  }

  .deck-page #navbar.site-header > .site-header-inner {
    max-width: none;
    padding: 0;
  }
}

@media (max-width: 767px) {
  :root { --pastelle-nav-height: 0px; --pastelle-nav-height-condensed: 0px; --pastelle-sticky-offset: 0px; }
  #navbar.site-header { position: relative !important; background: var(--theme-bg); box-shadow: none; }
  #navbar.site-header > .site-header-inner, #navbar.scrolled > .site-header-inner { display: block; min-height: 0; padding: 32px 24px 28px; }
  .site-header-brand-row { justify-content: space-between; }
  .site-header-actions, .deck-page .site-header-actions { position: static; top: auto; right: auto; transform: none; }
  .site-header-wordmark { font-size: 2rem; }
  .deck-nav, .deck-page .deck-nav {
    display: flex;
    position: relative;
    top: auto;
    right: auto;
    flex-direction: column;
    align-items: flex-start;
    gap: 0;
    max-height: 0;
    margin: 0;
    overflow: hidden;
    opacity: 0;
    pointer-events: none;
    visibility: hidden;
    transform: translate3d(0, -14px, 0) scale(0.985);
    transform-origin: 50% 0;
    font-size: 1rem;
    transition:
      max-height 0.38s var(--ease-out-expo),
      margin 0.38s var(--ease-out-expo),
      opacity 0.24s ease,
      transform 0.38s var(--ease-out-expo),
      visibility 0s linear 0.38s;
  }
  .deck-nav.is-mobile-open, .deck-page .deck-nav.is-mobile-open {
    max-height: 36rem;
    margin: 24px 0 0;
    opacity: 1;
    pointer-events: auto;
    visibility: visible;
    transform: translate3d(0, 0, 0) scale(1);
    transition:
      max-height 0.38s var(--ease-out-expo),
      margin 0.38s var(--ease-out-expo),
      opacity 0.24s ease,
      transform 0.38s var(--ease-out-expo),
      visibility 0s;
  }
  .deck-nav-item {
    opacity: 0;
    transform: translate3d(-16px, 0, 0);
    transition: opacity 0.24s ease, transform 0.32s var(--ease-out-expo);
  }
  .deck-nav.is-mobile-open .deck-nav-item {
    opacity: 1;
    transform: translate3d(0, 0, 0);
  }
  .deck-nav.is-mobile-open .deck-nav-item:nth-child(2) { transition-delay: 24ms; }
  .deck-nav.is-mobile-open .deck-nav-item:nth-child(3) { transition-delay: 48ms; }
  .deck-nav.is-mobile-open .deck-nav-item:nth-child(4) { transition-delay: 72ms; }
  .deck-nav.is-mobile-open .deck-nav-item:nth-child(5) { transition-delay: 96ms; }
  body.home-page #navbar .deck-nav,
  body.home-page #navbar .deck-nav.is-mobile-open { display: flex; }
  body.home-page #navbar .deck-nav,
  body.home-page #navbar .deck-nav.is-mobile-open {
    max-height: none;
    margin: 24px 0 0;
    overflow: visible;
    opacity: 1;
    pointer-events: auto;
    visibility: visible;
    transform: none;
  }
  body.home-page #navbar .deck-nav .deck-nav-item {
    opacity: 1;
    transform: none;
    transition: none;
  }
  body.home-page #navbar .site-header-menu-toggle { display: none; }
  .deck-nav-item { width: 100%; }
  .deck-menu, .deck-menu--end {
    position: static;
    min-width: 0;
    max-height: 0;
    padding: 0 0 0 16px;
    overflow: hidden;
    border: 0;
    background: none;
    box-shadow: none;
    opacity: 1;
    transform: none;
    transition: max-height 0.24s var(--ease-out-expo), opacity 0.16s ease, visibility 0s linear 0.24s;
  }
  .deck-menu.is-open { max-height: 320px; padding-bottom: 8px; transform: none; transition: max-height 0.24s var(--ease-out-expo), opacity 0.16s ease, visibility 0s; }
  .deck-menu a { padding: 5px 0; }
  .site-header-theme-toggle { margin-right: 0; }
  .site-header-menu-toggle {
    display: flex;
    width: 44px;
    height: 44px;
    flex: 0 0 44px;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 5px;
    padding: 10px;
    border: 0;
    background: none;
    color: var(--theme-ink);
    cursor: pointer;
  }
  .site-header-menu-toggle span {
    display: block;
    width: 22px;
    height: 2px;
    border-radius: 2px;
    background: currentColor;
    transition: transform var(--motion-fast) var(--ease-out-expo), opacity var(--motion-fast) ease;
  }
  .site-header-menu-toggle[aria-expanded="true"] span:first-child { transform: translateY(7px) rotate(45deg); }
  .site-header-menu-toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
  .site-header-menu-toggle[aria-expanded="true"] span:last-child { transform: translateY(-7px) rotate(-45deg); }
  .site-header-menu-toggle:focus-visible { outline: 2px solid currentColor; outline-offset: 3px; }
  .deck-page #navbar.site-header { position: relative !important; inset: auto; background: transparent; }
  .deck-page #navbar.site-header > .site-header-inner, .deck-page #navbar.scrolled > .site-header-inner { padding: 0; }
  .deck-page .site-header-brand-row { position: relative; top: auto; left: auto; }
  .deck-page .site-header-theme-toggle { position: relative; top: auto; right: auto; bottom: auto; left: auto; }
}

@media (prefers-reduced-motion: reduce) {
  .site-header, .site-header-inner, .deck-nav, .deck-nav-item, .deck-nav-link::after,
  .deck-menu-trigger > span:first-child::after, .deck-menu, .deck-menu-icon,
  .site-header-menu-toggle span {
    transition: none !important;
  }
}
