/*
 * Erysweb Portfolio
 *
 * Dark mode is the default token set; Light mode overrides colour tokens only.
 * Shared typography, spacing and mask variables live at the root. Component
 * rules stay explicit where behaviour genuinely differs across breakpoints.
 */

:root {
  /* Typography */
  --font-sans: "Inter", system-ui, sans-serif;
  --font-display: "Caveat", cursive;
  --type-body: 1.65rem;
  --type-body-mobile: 1.25rem;
  --type-reading-compact: clamp(1.35rem, 5.6vw, 1.65rem);
  --type-chapter: clamp(3rem, 5.4vw, 4.5rem);
  --type-chapter-mobile: clamp(2.25rem, 10.5vw, 3.15rem);
  --type-card-copy: clamp(1.05rem, 1.3vw, 1.15rem);
  --type-card-small: 0.98rem;

  /* Shared layout */
  --content-max: 1120px;
  --reading-max: 72ch;

  /* Shared responsive spacing */
  --paper-column-gap: clamp(2rem, 4vw, 4rem);
  --paper-padding: clamp(2rem, 3.4vw, 3.25rem);
  --scroll-guide-offset: clamp(0.85rem, 2vw, 1.4rem);
  --radius-panel: 10px;
  --paper-edge-width: clamp(2.65rem, 3.05vw, 3.45rem);

  /* Sticky-header fade shared by sections and filtered surfaces. */
  --header-mask-clear-end: 58px;
  --header-mask-soft-1: 78px;
  --header-mask-soft-2: 102px;
  --header-mask-soft-3: 128px;
  --header-mask-solid-start: 154px;
  --header-mask-soft-color-1: rgba(0, 0, 0, 0.14);
  --header-mask-soft-color-2: rgba(0, 0, 0, 0.38);

  /* Dark theme is the document default. Light mode only overrides colour tokens. */
  --bg: #08111f;
  --text: #f6f8fb;
  --muted: #b6c2d0;
  --panel: rgba(7, 15, 27, 0.48);
  --panel-strong: rgba(7, 15, 27, 0.62);
  --border: rgba(255, 255, 255, 0.14);
  --accent: #f2c66f;
  --shadow: 0 18px 50px rgba(0, 0, 0, 0.20);
  --story-text-shadow: 0 2px 7px rgba(0, 0, 0, 0.32);

  /* Header / navigation theme tokens */
  --brand-wordmark: rgba(248, 249, 252, 0.94);
  --brand-flower: rgba(248, 249, 252, 0.94);
  --nav-accent: #d7eaf6;
  --nav-active-label: #f6f8fb;
  --nav-rail: rgba(247, 250, 255, 0.14);
  --nav-progress-fill: #d7eaf6;
  --nav-overlay-bg: rgba(0, 0, 0, 0.5);
  --mobile-nav-header-bg: #112444;
  --nav-divider: #f7faff;
  --nav-flower-shadow: drop-shadow(0 0 3px rgba(255, 255, 255, 0.22));
  --nav-flower-shadow-hover: drop-shadow(0 0 4px rgba(255, 255, 255, 0.42));
  --nav-flower-shadow-active: drop-shadow(0 0 5px rgba(255, 255, 255, 0.68)) drop-shadow(0 0 10px rgba(211, 230, 255, 0.24));

  /* Spring petals: shared geometry; only colour changes with theme. */
  --petal-pink: rgba(220, 105, 157, .91);
  --petal-lilac: rgba(228, 130, 169, .89);
  --petal-cream: rgba(228, 144, 116, .87);

  /* Project paper theme tokens. Layout/spacing stays identical across themes. */
  --paper-bg: #0E1422;
  --paper-ink: var(--text);
  --paper-muted: var(--muted);
  --paper-rule: rgba(92, 113, 154, 0.20);
  --paper-shadow-front: 0 24px 52px rgba(0, 0, 0, 0.34), 0 3px 10px rgba(0, 0, 0, 0.20);
  --paper-shadow-back: 0 10px 24px rgba(0, 0, 0, 0.22);
  --paper-media-bg: #243458;
  --paper-placeholder-bg: rgba(255, 255, 255, 0.045);
  --paper-control-hover: #fff;
  --paper-edge-bar: #30456a;
  --paper-edge-border: color-mix(in srgb, var(--paper-edge-bar) 25%, transparent);
  --paper-edge-bar-text: #ffffff;
  --paper-bg-inactive: #1c2844;
}

html[data-theme="light"] {
  --bg: #eff5fb;
  --text: #14284f;
  --muted: #596876;
  --panel: rgba(255, 255, 255, 0.44);
  --panel-strong: rgba(255, 255, 255, 0.62);
  --border: rgba(23, 32, 44, 0.14);
  --accent: #8c6a28;
  --shadow: 0 18px 50px rgba(48, 63, 79, 0.10);
  --story-text-shadow: 0 1px 5px rgba(255, 255, 255, 0.58);

  --brand-wordmark: #3e444e;
  --brand-flower: #3e444e;
  --nav-accent: #3f6682;
  --nav-active-label: #14284f;
  --nav-rail: rgba(126, 136, 148, 0.18);
  --nav-progress-fill: #3f6682;
  --nav-overlay-bg: rgba(255, 255, 255, 0.75);
  --mobile-nav-header-bg: #263F5C;
  --nav-divider: #5e6977;
  --nav-flower-shadow: none;
  --nav-flower-shadow-hover: none;
  --nav-flower-shadow-active: drop-shadow(0 0 3px rgba(68, 103, 136, 0.3));


  --paper-bg: #fffdf8;
  --paper-rule: rgba(36, 51, 67, 0.14);
  --paper-shadow-front: 0 22px 46px rgba(49, 59, 70, 0.14), 0 3px 8px rgba(49, 59, 70, 0.07);
  --paper-shadow-back: 0 9px 22px rgba(49, 59, 70, 0.09);
  --paper-media-bg: transparent;
  --paper-placeholder-bg: rgba(38, 52, 66, 0.035);
  --paper-control-hover: var(--paper-ink);
  --paper-edge-bar: #14284f;
  --paper-bg-inactive: #eeeeee;
}

* {
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
  scroll-padding-top: 90px;
  /* Keep the text column width stable while the loading lock hides/restores
     page overflow, preventing line rewrap and scroll-anchor correction. */
  scrollbar-gutter: stable;
}

body {
  margin: 0;
  overflow-x: hidden;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-sans);
  line-height: 1.7;
}

body.is-loading {
  overflow: hidden;
}

h1,
h2 {
  font-family: var(--font-display);
  font-weight: 600;
}

a {
  color: inherit;
}

button,
a {
  -webkit-tap-highlight-color: transparent;
}

:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 3px;
}

/* Accessibility */

.skip-link {
  position: absolute;
  top: 0.75rem;
  left: 0.75rem;
  z-index: 10000;
  padding: 0.7rem 1rem;
  border-radius: var(--radius-panel);
  transform: translateY(-180%);
  background: var(--text);
  color: var(--bg);
}

.skip-link:focus {
  transform: translateY(0);
}

/* Background scenery */

.landscape {
  position: fixed;
  inset: 0;
  z-index: -2;
  overflow: hidden;
  background: var(--bg);
}

/* Theme transition */

.theme-veil {
  position: fixed;
  inset: 0;
  z-index: 25;
  pointer-events: none;
  background: var(--bg);
  opacity: 0;
  transition: opacity 260ms ease;
}

/* Typography / section layout */

main {
  position: relative;
  z-index: 1;
}

.content-section {
  --local-header-mask-y: -240px;
  display: flex;
  align-items: center;
  min-height: 92vh;
  padding: clamp(5rem, 11vw, 9rem) clamp(1rem, 6vw, 6rem);
}

/*
 * Sections and filtered panels use the same visual fade. Filtered surfaces keep
 * their own viewport-relative offset because backdrop-filter compositing can
 * otherwise escape an ancestor mask in some browsers.
 */
.contact-panel,
.paper-sheet {
  --local-header-mask-y: -240px;
}

.content-section,
.contact-panel,
.paper-sheet {
  -webkit-mask-image: linear-gradient(
    to bottom,
    transparent var(--local-header-mask-y),
    transparent calc(var(--local-header-mask-y) + var(--header-mask-clear-end)),
    var(--header-mask-soft-color-1) calc(var(--local-header-mask-y) + var(--header-mask-soft-1)),
    var(--header-mask-soft-color-2) calc(var(--local-header-mask-y) + var(--header-mask-soft-2)),
    rgba(0, 0, 0, 0.68) calc(var(--local-header-mask-y) + var(--header-mask-soft-3)),
    #000 calc(var(--local-header-mask-y) + var(--header-mask-solid-start)),
    #000 100%
  );
  mask-image: linear-gradient(
    to bottom,
    transparent var(--local-header-mask-y),
    transparent calc(var(--local-header-mask-y) + var(--header-mask-clear-end)),
    var(--header-mask-soft-color-1) calc(var(--local-header-mask-y) + var(--header-mask-soft-1)),
    var(--header-mask-soft-color-2) calc(var(--local-header-mask-y) + var(--header-mask-soft-2)),
    rgba(0, 0, 0, 0.68) calc(var(--local-header-mask-y) + var(--header-mask-soft-3)),
    #000 calc(var(--local-header-mask-y) + var(--header-mask-solid-start)),
    #000 100%
  );
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-size: 100% 100%;
  mask-size: 100% 100%;
}

.work-section {
  min-height: auto;
}

.contact-section {
  min-height: 95vh;
}

.content-panel {
  width: min(100%, var(--content-max));
  margin: 0 auto;
}

.wide {
  max-width: 1180px;
}

.hero-panel {
  max-width: 820px;
  margin-right: auto;
  margin-left: auto;
  text-align: center;
}

p {
  max-width: var(--reading-max);
  font-size: var(--type-body);
  font-weight: 400;
  line-height: 1.44;
  letter-spacing: normal;
}

/* Intro story sections intentionally sit directly on the scenery */

.intro-panel p {
  margin-right: auto;
  margin-left: auto;
}

/* Frosted panels */

.contact-panel {
  max-width: 840px;
  margin: 0 auto;
  padding: clamp(1.6rem, 3.5vw, 2.75rem);
  border: 1px solid var(--border);
  border-radius: var(--radius-panel);
  background: linear-gradient(145deg, rgba(7, 15, 27, 0.70), rgba(7, 15, 27, 0.60));
  box-shadow: var(--shadow);
  text-align: center;
}

/*
 * Progressive enhancement: the translucent panel above is the fallback.
 * Browsers with backdrop-filter support get the intended frosted-glass finish.
 */

@supports ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))) {
  .contact-panel {
    -webkit-backdrop-filter: blur(18px) saturate(135%);
    backdrop-filter: blur(18px) saturate(135%);
  }
}

html[data-theme="light"] .contact-panel {
  background: linear-gradient(145deg, rgba(255, 255, 255, 0.78), rgba(255, 255, 255, 0.68));
}

/* Contact */

.contact-panel h2 {
  max-width: 760px;
  margin: 0 auto 1.5rem;
  font-size: clamp(2.6rem, 4.4vw, 3.8rem);
  line-height: 1.08;
  letter-spacing: -0.025em;
}

.contact-panel p {
  margin-right: auto;
  margin-left: auto;
}

.contact-actions {
  display: flex;
  margin-top: 0;
  justify-content: center;
  flex-wrap: wrap;
  gap: 0.8rem;
}

.button {
  display: inline-flex;
  min-height: 46px;
  padding: 0.65rem 1.1rem;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--border);
  border-radius: var(--radius-panel);
  text-decoration: none;
}

.button.primary {
  border-color: transparent;
  background: var(--text);
  color: var(--bg);
}

.button.ghost {
  background: var(--panel);
}

/* Section reveal */

.reveal-section {
  opacity: 1;
  transform: none;
  will-change: auto;
}

/* Preloader */

.preloader {
  position: fixed;
  inset: 0;
  z-index: 9999;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: 1rem;
  background: var(--bg);
  color: var(--text);
  opacity: 1;
  visibility: visible;
  transition: opacity 520ms ease, visibility 520ms ease;
}

.preloader.is-hidden {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}

.preloader-flower {
  display: block;
  width: 3.25rem;
  height: auto;
  color: var(--brand-flower);
  transform: rotate(0deg);
  transform-box: view-box;
  transform-origin: 50% 50%;
  will-change: transform;
}

/* Tablet / medium screens */

@media (max-width: 1024px) {
  .content-section {
    padding-inline: clamp(1rem, 4vw, 3rem);
  }
}

/* Project gallery lightbox */
.project-lightbox {
  width: min(94vw, 980px, 122.66vh);
  max-width: 980px;
  max-height: 92vh;
  margin: auto;
  padding: 0;
  overflow: hidden;
  border: 1px solid var(--paper-rule);
  border-radius: var(--radius-panel);
  background-color: var(--paper-bg);
  color: var(--paper-ink);
  box-shadow: 0 28px 90px rgba(0, 0, 0, 0.38);
}

.project-lightbox::backdrop {
  background: rgba(5, 10, 18, 0.78);
}

.project-lightbox-inner {
  position: relative;
  width: 100%;
  padding: 0;
  overflow: hidden;
}

.project-lightbox-content {
  display: grid;
  width: 100%;
  min-width: 0;
}

.project-lightbox-content .project-gallery-image {
  width: 100%;
  height: auto;
  min-width: 0;
  min-height: 0;
  aspect-ratio: 16 / 9;
  border: 0;
  border-radius: 0;
  background: var(--paper-media-bg);
}

.project-lightbox-content .project-gallery-image {
  display: grid;
  place-items: center;
}

.project-lightbox-content .project-gallery-image img {
  display: block;
  width: auto;
  max-width: 100%;
  height: auto;
  max-height: 100%;
  object-fit: contain;
}

.project-lightbox-close {
  position: absolute;
  z-index: 3;
  top: 0.75rem;
  right: 0.75rem;
  display: inline-grid;
  place-items: center;
  width: 44px;
  height: 44px;
  margin: 0;
  padding: 0;
  border: 1px solid rgba(255, 255, 255, 0.32);
  border-radius: 999px;
  background: rgba(8, 17, 31, 0.78);
  color: #fff;
  font: inherit;
  font-size: 1.45rem;
  line-height: 1;
  cursor: pointer;
}

.project-gallery-image[data-lightbox-ready="true"] {
  cursor: zoom-in;
}

.project-gallery-image[data-lightbox-ready="true"]:focus-visible {
  outline: 3px solid var(--paper-control-hover);
  outline-offset: -4px;
}


@media (max-width: 820px) {
  .content-section {
    min-height: auto;
    padding-top: 8rem;
    padding-bottom: 8rem;
  }

}

/* Project gallery */

.project-gallery-viewport {
  overflow: hidden;
}

.project-gallery-track {
  display: flex;
  align-items: stretch;
  width: 100%;
  transition: transform 420ms cubic-bezier(.22, .61, .36, 1);
  will-change: transform;
}

.project-gallery-slide {
  display: flex;
  flex: 0 0 100%;
  flex-direction: column;
  align-self: stretch;
  margin: 0;
}

.project-gallery-controls {
  display: flex;
  min-height: 48px;
  padding: 0.4rem 0.75rem 0.7rem;
  align-items: center;
  justify-content: space-between;
  gap: 0.8rem;
}

.gallery-arrow,
.gallery-dot {
  border: 0;
  background: transparent;
  color: var(--text);
  cursor: pointer;
}

.gallery-arrow {
  display: inline-flex;
  width: 40px;
  height: 40px;
  align-items: center;
  justify-content: center;
  font-size: 1.7rem;
  line-height: 1;
}

.gallery-dots {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
}

.gallery-dot {
  position: relative;
  width: 28px;
  height: 28px;
  padding: 0;
  border: 0;
  opacity: 1;
}

.gallery-dot::before {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 14px;
  height: 14px;
  border: 1px solid currentColor;
  border-radius: 50%;
  opacity: 0.54;
  transform: translate(-50%, -50%);
}

.gallery-dot.is-active::before,
.gallery-dot[aria-current="true"]::before {
  background: currentColor;
  opacity: 1;
}

.hero {
  min-height: 94vh;
}

.hero h1 {
  margin: 0 0 1.25rem;
  font-size: clamp(3rem, 6vw, 5rem);
  line-height: 1.02;
  letter-spacing: -0.035em;
  text-shadow: var(--story-text-shadow);
}

.hero-intro {
  max-width: 35ch;
  margin: 0 auto;
  text-shadow: var(--story-text-shadow);
}

/* Quiet early contact access: intentionally secondary to the opening role line. */
.intro-contact-links {
  display: flex;
  margin-top: 1rem;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 0.5rem;
  font-size: 0.95rem;
}

.intro-contact-link {
  display: inline-flex;
  min-height: 24px;
  align-items: center;
  color: inherit;
  opacity: 0.75;
  text-underline-offset: 0.22em;
  text-decoration-thickness: 1px;
}

.intro-contact-link:hover,
.intro-contact-link:focus-visible {
  opacity: 1;
}

.intro-contact-separator {
  opacity: 0.55;
}

/* Narrative sections are continuous prose rather than screen-height slides. */

.narrative-section {
  display: block;
  min-height: auto;
  padding-top: clamp(6rem, 10vw, 9rem);
  padding-bottom: clamp(7rem, 12vw, 11rem);
}

.narrative-section h2 {
  max-width: 13ch;
  margin: 0 0 clamp(2.25rem, 4vw, 3.75rem);
  font-size: var(--type-chapter);
  line-height: 1.06;
  letter-spacing: -0.03em;
}

/* Sentences within one thought sit closer together than separate story beats. */

.story-beat p + p {
  margin-top: clamp(1.7rem, 3.2vw, 2.75rem);
}

.closing-line {
  font-size: clamp(1.3rem, 2.2vw, 1.75rem);
  line-height: 1.45;
}

.availability {
  margin-top: 1.6rem;
  color: var(--muted);
  font-size: 0.92rem;
  font-weight: 600;
  letter-spacing: 0.04em;
}

.story-flow {
  position: relative;
  isolation: isolate;
  width: min(100%, var(--content-max));
  margin-right: auto;
  margin-left: auto;
  text-align: center;
}

/* Narrative copy shares the centered content width used by the rest of the page. */

.story-reveal,
.story-beat {
  max-width: var(--content-max);
}

/*
 * Inter is the default UI/body face everywhere unless an intentional decorative selector
 * explicitly creates a chapter/title voice. Interactive controls inherit it.
 */

/* Story text stays visually clean; atmosphere belongs to the page, not each sentence. */

.story-beat p,
.narrative-section h2.story-reveal {
  max-width: var(--content-max);
  text-shadow: var(--story-text-shadow);
}

/*
 * Each story beat reveals as a readable paragraph or a deliberate single-line thought.
 * The spacing stays editorial rather than slide-like.
 */

.story-beat:last-child {
  margin-bottom: 0;
}

.story-beat p {
  margin: 0 auto;
  text-wrap: pretty;
}

/*
 * Threshold reveal: the scroll decides when the sentence enters, then the
 * transition finishes independently. Keep the movement subtle and quick.
 */

.js .reveal-section:not(.hero) {
  opacity: 0;
  transform: translate3d(0, 15px, 0);
  transition: opacity 650ms cubic-bezier(.22, .61, .36, 1),
    transform 700ms cubic-bezier(.22, .61, .36, 1);
  will-change: opacity, transform;
}

.js .reveal-section.is-revealed {
  opacity: 1;
  transform: none;
}

@media (max-width: 760px) {
  .narrative-section {
    padding-top: clamp(4.5rem, 15vw, 6rem);
    padding-bottom: clamp(5.5rem, 18vw, 7rem);
  }

  .narrative-section h2 {
    font-size: var(--type-chapter-mobile);
    line-height: 1.08;
    margin-bottom: clamp(1.9rem, 7vw, 2.5rem);
  }

  .story-beat p,
  .work-intro {
    max-width: 100%;
    font-size: var(--type-reading-compact);
    line-height: 1.5;
    letter-spacing: -0.006em;
  }

  .hero h1 {
    font-size: clamp(2.8rem, 13vw, 4rem);
    line-height: 1.02;
  }

  .hero-intro {
    font-size: clamp(1.18rem, 5vw, 1.45rem);
    line-height: 1.5;
  }

  .contact-panel h2 {
    font-size: clamp(2.25rem, 10vw, 3.2rem);
  }
}

@media (max-width: 390px) {
  .narrative-section h2 {
    font-size: clamp(2.05rem, 10.5vw, 2.65rem);
  }
}

.sr-only {
  position: absolute !important;
  width: 1px !important;
  height: 1px !important;
  padding: 0 !important;
  margin: -1px !important;
  overflow: hidden !important;
  clip: rect(0, 0, 0, 0) !important;
  clip-path: inset(50%) !important;
  white-space: nowrap !important;
  border: 0 !important;
}

/*
 * Sky atmosphere and semantic landscape are independent layers: the sky stays
 * viewport-bound while the 12000-wide landscape can travel horizontally.
 * Landscape colour roles interpolate through CSS custom properties in JavaScript.
 */

.landscape-track {
  position: absolute;
  inset: 0 auto 0 0;
  width: 750vh;
  min-width: 100vw;
  height: 100vh;
  will-change: transform;
}

.sky-stack {
  position: absolute;
  inset: 0;
  width: 100vw;
  height: 100vh;
  overflow: hidden;
  pointer-events: none;
  z-index: 0;
}

.semantic-scene {
  position: absolute;
  inset: 0 auto 0 0;
  z-index: 2;
  width: 750vh;
  min-width: 100vw;
  height: 100vh;
  pointer-events: none;
}

.sky-layer,
.semantic-landscape-svg {
  position: absolute;
  inset: 0 auto 0 0;
  display: block;
  width: auto;
  max-width: none;
  height: 100vh;
  pointer-events: none;
  user-select: none;
}

.sky-layer {
  left: 0;
  transition: none;
  will-change: transform;
}

.sky-dark {
  opacity: 1;
  transform: translate3d(calc(-1 * var(--dark-sky-shift, 0px)), 0, 0);
}

.sky-light {
  opacity: 0;
  transform: translate3d(calc(-1 * var(--light-sky-shift, 0px)), 0, 0);
}

/* Smooth UI theme changes while the SVG itself is interpolated in JavaScript. */

body,
.project-gallery,
.button {
  transition: color 420ms ease,
    background-color 420ms ease,
    border-color 420ms ease,
    box-shadow 420ms ease;
}

.theme-veil.is-active {
  opacity: 0.10;
}


/*
 * Narrative passages reveal at 64% viewport, remain readable as they travel
 * upward, and only fade once they approach the top edge.
 */

.story-beat {
  margin-bottom: clamp(4rem, 12vh, 7rem);
}

.narrative-section h2.story-reveal {
  margin-bottom: clamp(3rem, 10vh, 5.5rem);
}

.js .story-reveal {
  opacity: 0;
  transform: translate3d(0, 18px, 0);
  transition: opacity 720ms cubic-bezier(.22, .61, .36, 1),
    transform 760ms cubic-bezier(.22, .61, .36, 1);
  will-change: opacity, transform;
}

.js .story-reveal.is-active {
  opacity: 1;
  transform: none;
}

.js .story-reveal.is-past {
  opacity: var(--story-past-opacity, 1);
  transform: none;
  /* Past-line opacity is directly scroll-linked; a CSS time transition here
     would lag behind the visitor and make the fade feel premature. */
  transition: none;
}

.js .story-reveal.is-future {
  opacity: 0;
  transform: translate3d(0, 18px, 0);
}

/*
 * Mobile shows the left-side composition and does not make the visitor travel
 * across the 12000px panorama. JavaScript also removes depth movement here.
 */

@media (max-width: 760px) {
  .story-beat {
    margin-bottom: clamp(3.5rem, 11vh, 5.5rem);
  }

  .narrative-section h2.story-reveal {
    margin-bottom: clamp(2.75rem, 9vh, 4.5rem);
  }
}

/*
 * Work uses the same 1120px chapter-intro geometry and vertical rhythm as the
 * story sections. The project deck remains on the wider project container.
 */

.work-intro-block {
  width: min(100%, var(--content-max));
  margin: 0 auto clamp(4.5rem, 7vw, 6rem);
  text-align: center;
}

.work-intro-block h2 {
  width: 100%;
  max-width: var(--content-max);
  margin: 0 0 clamp(1.4rem, 2.6vw, 2rem);
}

.work-intro {
  max-width: var(--reading-max);
  margin: 0 auto;
  color: var(--text);
  text-align: center;
  text-wrap: pretty;
}

@media (max-width: 760px) {
  .work-intro-block h2 {
    max-width: 100%;
    margin-bottom: clamp(1.4rem, 5vw, 1.9rem);
  }

  .work-intro-block {
    margin-bottom: clamp(3.5rem, 10vw, 4.5rem);
  }
}

/* Contact supporting copy should never drop into caption-sized typography. */

.contact-panel > p:not(.closing-line):not(.availability) {
  max-width: 52ch;
}

.contact-panel .availability {
  font-size: var(--type-card-small);
  font-weight: 400;
  line-height: 1.55;
  letter-spacing: normal;
}

/* Projects */

.project-deck {
  width: 100%;
  min-height: 0;
  margin-top: clamp(2.2rem, 5vw, 3.5rem);
}

.project-deck-sticky {
  position: relative;
  height: auto;
}

.project-paper-stack {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: auto;
  width: min(1080px, calc(100% - 3rem));
  margin: 0 auto;
  padding: 3.2rem 1.2rem 1.25rem 2.4rem;
  isolation: isolate;
}

.paper-sheet {
  position: relative;
  grid-column: 1;
  grid-row: 1;
  display: grid;
  grid-template-columns: minmax(0, 0.94fr) minmax(0, 1.06fr);
  align-items: start;
  gap: 0;
  grid-template-rows: auto auto auto;
  column-gap: var(--paper-column-gap);
  row-gap: 0;
  width: 100%;
  min-width: 0;
  min-height: 0;
  margin: 0;
  padding: var(--paper-padding);
  overflow: hidden;
  border: 1px solid var(--paper-edge-border);
  border-radius: var(--radius-panel);
  background-color: var(--paper-bg);
  color: var(--paper-ink);
  box-shadow: none;
  backface-visibility: hidden;
  transform-origin: 50% 50%;
  transition: none;
}

.paper-sheet .project-copy {
  grid-column: 1 / -1;
  grid-row: 1 / span 2;
  align-self: start;
  display: grid;
  grid-template-columns: minmax(0, 0.94fr) minmax(0, 1.06fr);
  grid-template-rows: auto auto;
  column-gap: var(--paper-column-gap);
  width: 100%;
  min-width: 0;
}

.paper-sheet .project-identity {
  grid-column: 2;
  grid-row: 1;
  min-width: 0;
}

.paper-sheet .project-details {
  grid-column: 2;
  grid-row: 2;
  min-width: 0;
  margin-top: 1.5rem;
}

.paper-sheet .project-media {
  grid-column: 1;
  grid-row: 1 / span 2;
  align-self: start;
  width: 100%;
  min-width: 0;
  margin: 0;
}

.paper-sheet .project-identity > h3 {
  align-self: start;
  max-width: 20ch;
  margin: 0;
  color: var(--paper-ink);
  font-size: clamp(1.9rem, 2.8vw, 2.55rem);
  font-weight: 400;
  line-height: 1.08;
  letter-spacing: normal;
}

.paper-sheet .project-identity > .project-subtitle {
  align-self: start;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.45rem 0.55rem;
  max-width: 52ch;
  margin: 0.85rem 0 0;
  color: var(--paper-muted);
  font-size: var(--type-card-small);
  font-weight: 400;
  line-height: 1.5;
  letter-spacing: normal;
}

.project-type-pill {
  display: inline-flex;
  align-items: center;
  min-height: 1.9rem;
  padding: 0.28rem 0.72rem;
  border: 1px solid var(--paper-edge-bar);
  border-radius: 999px;
  background: var(--paper-edge-bar);
  color: var(--paper-edge-bar-text);
  font-size: inherit;
  font-weight: 600;
  line-height: 1.2;
}

.project-subtitle-detail {
  color: var(--paper-muted);
  font-size: inherit;
  line-height: 1.2;
}

.contact-panel > p:not(.closing-line):not(.availability),
.paper-sheet .project-details > p {
  font-size: var(--type-card-copy);
  font-weight: 400;
  line-height: 1.68;
  letter-spacing: normal;
}

.paper-sheet .project-details > p {
  max-width: 55ch;
  margin: 0;
  color: var(--paper-ink);
  text-wrap: pretty;
}

.paper-sheet .project-details > .project-description-text {
  align-self: start;
  margin: 0;
}

.paper-sheet .project-details > .project-description-text + .project-description-text {
  margin-top: 1.5rem;
}

.paper-sheet .project-facts {
  align-self: stretch;
  display: grid;
  width: 100%;
  max-width: 55ch;
  gap: 1rem;
  margin: 2rem 0 0;
  padding: 1rem 0 0;
  border-top: 1px solid var(--paper-rule);
}

.paper-sheet .project-facts div {
  display: grid;
  grid-template-columns: 4.5rem minmax(0, 1fr);
  gap: 0.65rem;
}

.paper-sheet .project-facts dt {
  margin: 0;
  color: var(--paper-ink);
  font-size: 0.9rem;
  font-weight: 700;
  line-height: 1.55;
  letter-spacing: 0.055em;
  text-transform: uppercase;
}

.paper-sheet .project-facts dd {
  margin: 0;
  color: var(--paper-muted);
  font-size: var(--type-card-small);
  line-height: 1.55;
}

.paper-sheet .project-gallery-viewport,
.paper-sheet .project-media-card {
  overflow: hidden;
  border: 1px solid var(--paper-rule);
  border-radius: var(--radius-panel);
  background: transparent;
}

.paper-sheet .project-gallery-image,
.paper-sheet .project-visual {
  display: flex;
  flex: 0 0 auto;
  width: 100%;
  height: auto;
  min-height: 0;
  align-items: center;
  justify-content: center;
}

.paper-sheet .project-gallery-image {
  aspect-ratio: 16 / 9;
}

.paper-sheet .project-visual {
  aspect-ratio: 4 / 3;
}

.paper-sheet .project-gallery-image.placeholder {
  background: var(--paper-placeholder-bg);
}

.paper-sheet .project-gallery-image img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.paper-sheet .project-gallery-image span {
  color: var(--paper-ink);
  font-size: clamp(1.35rem, 2.5vw, 2.4rem);
  font-weight: 600;
}

.paper-sheet .project-gallery-caption {
  display: grid;
  flex: 1 1 auto;
  align-content: start;
  gap: 0.22rem;
  min-height: 0;
  padding: 0.85rem 0.95rem;
  border-top: 0;
  border-radius: 0;
  background: var(--paper-bg-inactive);
  color: var(--paper-ink);
}

.paper-sheet .project-gallery-caption-title {
  color: var(--paper-ink);
  font-size: 1.02rem;
  font-weight: 700;
}

.paper-sheet .project-gallery-caption-text {
  color: var(--paper-muted);
  font-size: var(--type-card-small);
  line-height: 1.52;
  letter-spacing: normal;
}

.paper-sheet .project-media-caption .project-gallery-caption-text {
  font-style: italic;
}

.paper-sheet .project-gallery-track {
  will-change: auto;
}

.paper-sheet .project-gallery-controls {
  min-height: 42px;
  margin-top: 0;
  padding: 0.35rem 0.75rem 0.55rem;
  border-radius: 0;
  background: transparent;
  color: var(--paper-ink);
}

.paper-sheet .gallery-arrow {
  color: var(--paper-ink);
}

.paper-sheet .gallery-dot {
  background: transparent;
}

.paper-sheet .project-visual {
  flex-direction: column;
  padding: 1.5rem;
  overflow: hidden;
  text-align: center;
}

.paper-sheet .metric-visual .metric {
  display: block;
  font-size: clamp(4.5rem, 8vw, 7rem);
  line-height: 0.8;
}

.paper-sheet .metric-label {
  display: block;
  margin-top: 0.75rem;
  font-size: clamp(1.05rem, 1.6vw, 1.4rem);
}

.paper-sheet .metric-visual p {
  margin-bottom: 0;
  color: var(--paper-muted);
  font-size: var(--type-card-small);
  letter-spacing: normal;
}

.paper-project-nav {
  grid-column: 1 / -1;
  grid-row: 3;
  align-self: end;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  align-items: center;
  gap: 1rem;
  margin-top: 1.2rem;
  padding-top: 0.9rem;
  border-top: 1px solid var(--paper-rule);
}

.paper-project-control {
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  width: max-content;
  max-width: 100%;
  padding: 0.5rem 0;
  border: 0;
  background: transparent;
  color: var(--paper-ink);
  font: inherit;
  font-size: 1rem;
  font-weight: 400;
  line-height: 1.3;
  text-decoration: none;
  cursor: pointer;
}

.paper-project-prev {
  justify-self: start;
}

.paper-project-next {
  justify-self: end;
  text-align: right;
}

.paper-project-control:hover {
  color: var(--paper-control-hover);
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

.paper-project-control:focus-visible {
  color: var(--paper-control-hover);
  outline: 2px solid currentColor;
  outline-offset: 4px;
  border-radius: var(--radius-panel);
}

/* --------------------------------------------------------------------------
   Desktop project fan
   -------------------------------------------------------------------------- */

@media (min-width: 1281px) {
  /*
   * Keep Work broader than the reading column without letting the active sheet
   * become a near-full-viewport slab.
   */
  .work-section {
    padding-inline: clamp(2rem, 4vw, 4.5rem);
  }

  .work-section .content-panel.wide {
    width: 100%;
    max-width: 1400px;
  }

  .project-deck[data-project-layout="desktop"] .project-paper-stack {
    width: min(1320px, calc(100% - clamp(5.5rem, 9vw, 8rem)));
    padding: 4.4rem 2.4rem 2.4rem;
    overflow: visible;
  }

  .project-deck[data-project-layout="desktop"] .paper-sheet {
    --paper-desktop-safe-gutter: max(var(--paper-padding), calc(var(--paper-edge-width) + 1rem));
    grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
    column-gap: clamp(2.5rem, 4.25vw, 3.75rem);
    padding: var(--paper-desktop-safe-gutter);
    pointer-events: auto;
    transform-origin: 50% 116%;
    will-change: transform, box-shadow;
    transform: translate3d(0, -4px, 0) rotate(0deg);
    box-shadow: none;
    transition:
      transform 235ms cubic-bezier(.16, 1, .3, 1),
      box-shadow 180ms ease,
      border-color 190ms linear;
  }

  /*
   * Fan state stays explicitly scoped to desktop mode so stacked cards cannot
   * inherit transforms or rail behaviour. These rules intentionally follow the
   * shared project-sheet styles in source order.
   */
  .project-deck[data-project-layout="desktop"] .paper-sheet.is-fan-open {
    transform:
      translate3d(var(--fan-x, 0px), var(--fan-y, 0px), 0)
      rotate(var(--fan-angle, 0deg));
  }

  .project-deck[data-project-layout="desktop"] .paper-sheet.is-active-project {
    box-shadow: var(--paper-shadow-front);
  }

  .project-deck[data-project-layout="desktop"] .paper-sheet:not(.is-active-project) {
    border-color: var(--paper-edge-border);
  }

  .project-deck[data-project-layout="desktop"] .paper-sheet.is-fan-open:not(.is-active-project) {
    background-color: var(--paper-bg-inactive);
    box-shadow: var(--paper-shadow-back);
  }

  /*
   * Project selection handoff: keep the real paper surface stable and cover
   * the incoming sheet with one uninterrupted blue overlay. The overlay sits
   * above content and both edge rails, holds briefly, then fades away to reveal
   * the already-active paper underneath. Oversizing by 1px prevents a pale
   * anti-aliased seam from flashing around the former rail position.
   */
  @keyframes project-paper-handoff {
    0%, 10% { opacity: 1; }
    100% { opacity: 0; }
  }

  @keyframes project-content-enter {
    from { opacity: 0; }
    to { opacity: 1; }
  }

  .project-deck[data-project-layout="desktop"] .paper-sheet.is-project-handoff {
    border-color: var(--paper-edge-border);
  }

  .project-deck[data-project-layout="desktop"] .paper-sheet.is-project-handoff::after {
    content: "";
    position: absolute;
    z-index: 40;
    inset: -1px;
    border-radius: inherit;
    background: var(--paper-edge-bar);
    pointer-events: none;
    opacity: 0;
    /* Match the established 420ms surface rhythm without animating the paper. */
    animation: project-paper-handoff 420ms linear both;
  }

  .project-deck[data-project-layout="desktop"] .paper-sheet.is-project-handoff .project-media,
  .project-deck[data-project-layout="desktop"] .paper-sheet.is-project-handoff .project-copy > *,
  .project-deck[data-project-layout="desktop"] .paper-sheet.is-project-handoff .paper-project-nav {
    /* Reuse the common 220ms UI fade and let it overlap the paper settle. */
    animation: project-content-enter 220ms ease 160ms both;
  }

  .project-deck[data-project-layout="desktop"] .paper-sheet.is-active-project .project-identity > h3 {
    font-weight: 600;
  }

  .project-deck[data-project-layout="desktop"] .paper-sheet .project-media,
  .project-deck[data-project-layout="desktop"] .paper-sheet .project-copy > *,
  .project-deck[data-project-layout="desktop"] .paper-sheet .paper-project-nav {
    transition: opacity 180ms ease;
  }

  .project-deck[data-project-layout="desktop"] .paper-sheet:not(.is-active-project) .project-media,
  .project-deck[data-project-layout="desktop"] .paper-sheet:not(.is-active-project) .project-copy > *,
  .project-deck[data-project-layout="desktop"] .paper-sheet:not(.is-active-project) .paper-project-nav,
  .project-deck[data-project-layout="desktop"] .paper-sheet.is-content-fading-out .project-media,
  .project-deck[data-project-layout="desktop"] .paper-sheet.is-content-fading-out .project-copy > *,
  .project-deck[data-project-layout="desktop"] .paper-sheet.is-content-fading-out .paper-project-nav {
    opacity: 0;
    pointer-events: none;
  }

  .project-deck[data-project-layout="desktop"] .paper-sheet.is-content-fading-out .project-media,
  .project-deck[data-project-layout="desktop"] .paper-sheet.is-content-fading-out .project-copy > *,
  .project-deck[data-project-layout="desktop"] .paper-sheet.is-content-fading-out .paper-project-nav {
    transition-duration: 80ms;
    transition-timing-function: linear;
  }

  .project-deck[data-project-layout="desktop"] .paper-sheet.is-project-handoff .paper-edge-label {
    opacity: 0;
    transition: none;
  }

  /*
   * Full-height project rails make the inactive papers read as intentional
   * indexed sheets rather than blank cards. Each full-height rail is the
   * button itself; flexbox aligns the vertical label without absolute offsets.
   */
  .paper-edge-label {
    position: absolute;
    z-index: 30;
    top: 0;
    bottom: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-start;
    width: var(--paper-edge-width);
    margin: 0;
    padding: clamp(2.6rem, 5vh, 3.35rem) 0 0;
    overflow: hidden;
    border: 0;
    border-radius: 0;
    background: var(--paper-edge-bar);
    color: var(--paper-edge-bar-text);
    font: inherit;
    font-size: clamp(1.08rem, calc(0.9rem + 0.3vw), 1.4rem);
    font-weight: 600;
    line-height: 1;
    letter-spacing: 0.085em;
    text-transform: uppercase;
    white-space: nowrap;
    cursor: pointer;
    opacity: 0;
    pointer-events: none;
    text-shadow: none;
    transition: opacity 110ms ease;
  }

  .paper-edge-label-text {
    position: static;
    display: block;
    color: inherit;
    line-height: 1;
    writing-mode: vertical-rl;
    text-orientation: mixed;
  }

  /* Both edges carry the rail so whichever side is exposed can identify it. */
  .project-deck[data-project-layout="desktop"]
    .paper-sheet.is-fan-open .paper-edge-label {
    opacity: 1;
  }

  .project-deck[data-project-layout="desktop"]
    .paper-sheet.is-fan-open:not(.is-active-project) .paper-edge-label {
    pointer-events: auto;
  }

  .project-deck[data-project-layout="desktop"]
    .paper-sheet.is-fan-open:not(.is-active-project) {
    cursor: pointer;
  }

  .project-deck[data-project-layout="desktop"]
    .paper-sheet.is-fan-open:not(.is-active-project):hover .paper-edge-label,
  .project-deck[data-project-layout="desktop"]
    .paper-sheet.is-fan-open:not(.is-active-project):focus-within .paper-edge-label {
    filter: brightness(1.18);
  }

  /* The active sheet is the open page, so its edge rails disappear completely. */
  .project-deck[data-project-layout="desktop"] .paper-sheet.is-active-project .paper-edge-label {
    opacity: 0;
    pointer-events: none;
    cursor: default;
  }

  .paper-edge-label[data-fan-side="left"] {
    left: 0;
    transform: rotate(180deg);
    transform-origin: center;
  }

  .paper-edge-label[data-fan-side="right"] {
    right: 0;
  }

  .paper-edge-label:focus-visible {
    outline: 2px solid var(--paper-edge-bar-text);
    outline-offset: -4px;
  }

  /* The active sheet keeps a safe gutter where the two index rails overlap. */

  .project-deck[data-project-layout="desktop"] .paper-sheet .project-media {
    width: 100%;
    max-width: none;
    justify-self: stretch;
  }

  .project-deck[data-project-layout="desktop"] .paper-sheet.is-active-project .project-gallery-viewport {
    cursor: zoom-in;
  }
}

/*
 * Medium desktop tuning: preserve the same fan/card system while keeping the
 * Work deck proportionate on common 1366–1440px laptop displays. The rules
 * remain project-count agnostic so future cards use the same geometry.
 */
@media (min-width: 1281px) and (max-width: 1520px) {
  /*
   * Keep the card's internal layout roomy, then scale the complete fan as one
   * visual unit. Reducing width alone made copy wrap onto extra lines and kept
   * the sheet too tall on common 1440x900 displays. Parent scaling preserves
   * the established proportions, rail exposure and project-count-based fan
   * geometry while fitting the full paper comfortably inside the viewport.
   */
  .project-deck[data-project-layout="desktop"] .project-paper-stack {
    width: min(1080px, calc(100% - 5.5rem));
    padding: 3rem 1.45rem 1.75rem;
    scale: 0.88;
    transform-origin: top center;
    margin-bottom: -5rem;
  }

  .project-deck[data-project-layout="desktop"] .paper-sheet {
    --paper-desktop-safe-gutter: max(2.2rem, calc(var(--paper-edge-width) + 0.8rem));
    column-gap: clamp(2.05rem, 3vw, 2.8rem);
  }

  .project-deck[data-project-layout="desktop"] .paper-edge-label {
    width: clamp(2.35rem, 2.65vw, 2.7rem);
    font-size: clamp(1rem, calc(0.88rem + 0.2vw), 1.18rem);
  }
}

@media (min-width: 1281px) and (prefers-reduced-motion: reduce) {
  .project-deck[data-project-layout="desktop"] .paper-sheet,
  .project-deck[data-project-layout="desktop"] .paper-sheet .project-media,
  .project-deck[data-project-layout="desktop"] .paper-sheet .project-copy > *,
  .project-deck[data-project-layout="desktop"] .paper-sheet .paper-project-nav,
  .paper-edge-label {
    transition: none !important;
  }
}

/*
 * Desktop stack order is assigned in JavaScript relative to the active sheet.
 * The active paper sits above the deck; nearest inactive papers sit above farther
 * ones so their exposed index rails remain visible during project handoff.
 */

/* Mobile-only description expander. Desktop keeps the complete project sheet. */

.mobile-project-more {
  display: none;
}

@media (max-width: 1280px) {
  .paper-edge-label {
    display: none;
  }

  /*
   * Medium desktop and tablet: replace the fan with ordinary document flow.
   * Keep the complete two-column project cards and show all project copy.
   */
  .project-deck {
    margin-top: 2.2rem;
    overflow-x: clip;
  }

  .project-paper-stack {
    display: block;
    width: min(100%, 1040px);
    margin: 0 auto;
    padding: 1rem 0 2rem;
  }

  .project-paper-stack > .paper-sheet {
    grid-row: auto;
    grid-template-columns: minmax(0, 0.94fr) minmax(0, 1.06fr);
    column-gap: var(--paper-column-gap);
    width: calc(100% - 2rem);
    max-width: 1000px;
    margin: 0 auto clamp(1.4rem, 3vw, 2.25rem);
    padding: var(--paper-padding);
    transform: rotate(var(--mobile-paper-rotation, 0deg));
  }

  .project-paper-stack > .paper-sheet:last-child {
    margin-bottom: 0;
  }

  .paper-project-nav {
    display: none;
  }

  .paper-sheet .project-description-text {
    display: block;
  }

  .work-section {
    overflow-x: hidden;
    overflow-x: clip;
  }
}

@media (max-width: 680px) {
  /*
   * Phone layout: use one real column. These selectors intentionally match the
   * stacked-deck specificity above so the two-column grid cannot win.
   */
  .mobile-project-more {
    display: inline-flex;
    width: max-content;
    min-height: 44px;
    margin: 0.65rem 0 0;
    padding: 0;
    align-items: center;
    border: 0;
    background: transparent;
    color: var(--paper-ink);
    font: inherit;
    font-size: 1rem;
    font-weight: 600;
    text-decoration: underline;
    text-decoration-thickness: 1px;
    text-underline-offset: 0.22em;
    cursor: pointer;
  }

  .paper-sheet .project-details {
    display: none;
  }

  .paper-sheet.is-description-open .project-details {
    display: block;
    width: 100%;
    min-width: 0;
  }
  .project-paper-stack > .paper-sheet {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto;
    width: calc(100% - 1.5rem);
    max-width: 720px;
    padding: clamp(1.3rem, 5.5vw, 1.8rem);
    opacity: 0.9;
  }

  /*
   * Phone DOM and visual order match: identity -> media -> disclosure control
   * -> optional detail. Newly revealed copy follows the focused button in
   * source order for clearer keyboard and screen-reader navigation.
   */
  .paper-sheet .project-copy {
    grid-column: 1;
    grid-row: auto;
    display: flex;
    flex-direction: column;
    width: 100%;
    min-width: 0;
  }

  .paper-sheet .project-identity,
  .paper-sheet .project-details,
  .paper-sheet .project-media {
    width: 100%;
    max-width: none;
  }

  .paper-sheet .mobile-project-more {
    width: max-content;
    max-width: 100%;
    margin-inline: auto;
    justify-content: center;
  }

  .paper-sheet .project-identity > h3 {
    margin-top: 0;
    text-align: center;
    font-size: clamp(1.65rem, 7.5vw, 2.15rem);
  }

  .paper-sheet .project-identity > .project-subtitle {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 0.4rem 0.5rem;
    margin-top: 0.8rem;
    text-align: center;
  }

  .paper-sheet .project-gallery-caption {
    text-align: left;
  }

  .paper-sheet .project-media {
    margin-top: 1.25rem;
  }

  .paper-sheet .mobile-project-more {
    align-self: center;
    margin-top: 0.85rem;
    text-align: center;
  }

  .paper-sheet .project-details {
    margin-top: 0;
  }

  .paper-sheet .project-details > .project-description-text {
    margin-top: 0.85rem;
  }

  .paper-sheet .project-facts {
    margin-top: 1.15rem;
  }

  .paper-sheet .project-facts div {
    grid-template-columns: minmax(3.9rem, 4.5rem) minmax(0, 1fr);
  }

  .paper-sheet .project-facts dd {
    min-width: 0;
    overflow-wrap: anywhere;
  }
}

/*
 * Inter is the general reading/UI face. Ordinary page paragraphs share the
 * same reading scale as story beats; project papers and the Contact panel keep
 * their deliberately denser component typography.
 */

button,
input,
select,
textarea {
  font-family: inherit;
}

/* Project controls and metadata use neutral tracking. */

.paper-sheet .project-identity > h3,
.paper-sheet .project-gallery-caption-title,
.paper-sheet .project-gallery-image span,
.paper-sheet .project-facts dd,
.paper-project-control {
  letter-spacing: normal;
}

.contact-panel .closing-line {
  max-width: 42ch;
  margin-top: clamp(1.65rem, 3vw, 2.1rem);
  margin-bottom: clamp(2.8rem, 5vw, 3.6rem);
  font-family: var(--font-sans);
  font-size: clamp(1.2rem, 1.75vw, 1.4rem);
  font-weight: 600;
  line-height: 1.5;
  letter-spacing: -0.01em;
}

.button,
button {
  letter-spacing: normal;
}

/* Mobile typography and compact component exceptions */

@media (max-width: 600px) {
  .hero-intro,
  .work-intro,
  .story-beat p {
    font-size: var(--type-body-mobile);
    line-height: 1.46;
    letter-spacing: normal;
  }
}

@media (max-width: 625px) {
  :root {
    --header-mask-clear-end: 66px;
    --header-mask-soft-1: 86px;
    --header-mask-soft-2: 110px;
    --header-mask-soft-3: 136px;
    --header-mask-solid-start: 166px;
    --header-mask-soft-color-1: rgba(0, 0, 0, 0.10);
    --header-mask-soft-color-2: rgba(0, 0, 0, 0.34);
  }
}

/*
 * Give readers a quiet visual cue that another sentence follows the current
 * story beat. Only the immediate next item is previewed; later beats stay
 * hidden so the page still has a clear reading focus.
 */

.js .story-reveal.is-next {
  opacity: 0.2;
  transform: translate3d(0, 18px, 0);
}

/* ==========================================================================
   Header, logo and primary navigation
   ========================================================================== */
.site-header {
  position: sticky;
  top: 0;
  z-index: 30;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 1rem;
  height: 76px;
  padding: 0 clamp(1rem, 4vw, 4rem);
  background: transparent;
  pointer-events: auto;
}

.mobile-nav-header-surface {
  display: none;
  transition: background-color 180ms ease;
}

.brand {
  display: inline-flex;
  align-items: center;
  width: max-content;
}

.brand-logo {
  position: relative;
  display: block;
  width: 104px;
  aspect-ratio: 120 / 40.8;
}

.brand .brand-logo-base {
  position: absolute;
  left: 0;
  bottom: 0;
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
}

.brand-logo-wordmark {
  color: var(--brand-wordmark);
}

.brand .brand-logo-flower {
  position: absolute;
  top: 0;
  left: 23.58%;
  width: 18.25%;
  height: auto;
  overflow: visible;
  color: var(--brand-flower);
  transform: rotate(0deg);
  transform-box: view-box;
  transform-origin: 50% 50%;
  will-change: transform;
}

.theme-toggle,
.menu-toggle {
  border: 1px solid var(--border);
  background: var(--panel);
  color: var(--text);
  cursor: pointer;
}

.theme-toggle {
  justify-self: end;
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  min-height: 42px;
  padding: 0.45rem 0.8rem;
  border-radius: 30px;
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
}

.theme-toggle:hover,
.theme-toggle:focus-visible {
  background: var(--panel-strong);
}

.theme-icon {
  font-size: 1rem;
}

.menu-toggle {
  display: none;
  width: 44px;
  height: 44px;
  padding: 0;
  border-radius: 999px;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  gap: 4px;
}

.menu-toggle span {
  width: 17px;
  height: 1px;
  background: currentColor;
  transition: transform 220ms ease, opacity 220ms ease;
}

.menu-toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(5px) rotate(45deg); }
.menu-toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.menu-toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-5px) rotate(-45deg); }

.nav {
  --nav-progress: 0;
  position: relative;
  display: grid;
  width: min(500px, 52vw);
  min-width: 390px;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  align-items: start;
  justify-self: center;
  padding: 0.2rem 0;
  border: 0;
  background: transparent;
  box-shadow: none;
}

.nav-progress-rail {
  position: absolute;
  top: 0.675rem;
  right: 10%;
  left: 10%;
  z-index: 0;
  height: 1px;
  overflow: hidden;
  background: var(--nav-rail);
  pointer-events: none;
  -webkit-mask-image: linear-gradient(to right, transparent 0 6%, #000 6% 19%, transparent 19% 31%, #000 31% 44%, transparent 44% 56%, #000 56% 69%, transparent 69% 81%, #000 81% 94%, transparent 94% 100%);
  mask-image: linear-gradient(to right, transparent 0 6%, #000 6% 19%, transparent 19% 31%, #000 31% 44%, transparent 44% 56%, #000 56% 69%, transparent 69% 81%, #000 81% 94%, transparent 94% 100%);
}

.nav-progress-fill {
  display: block;
  width: 100%;
  height: 100%;
  background: var(--nav-progress-fill);
  transform: scaleX(var(--nav-progress));
  transform-origin: left center;
  transition: transform 120ms linear, background-color 420ms ease;
}

.nav a {
  position: relative;
  z-index: 1;
  display: grid;
  min-width: 0;
  padding: 0 0.32rem;
  place-items: center;
  gap: 0.24rem;
  color: var(--nav-accent);
  font-size: clamp(0.76rem, 0.82vw, 0.9rem);
  font-weight: 400;
  line-height: 1.1;
  text-decoration: none;
  text-shadow: var(--story-text-shadow);
}

.nav-label {
  white-space: nowrap;
  opacity: 0;
  transition: color 180ms ease, opacity 180ms ease;
}


.nav a:hover .nav-label,
.nav a:focus-visible .nav-label,
.nav a.is-active .nav-label {
  color: var(--nav-active-label);
  opacity: 1;
}

.nav-flower-marker {
  position: relative;
  display: inline-flex;
  width: 1.6rem;
  height: 0.95rem;
  align-items: center;
  justify-content: center;
}

.nav-flower-glyph {
  display: block;
  width: 1.28rem;
  height: 0.92rem;
  overflow: visible;
  color: var(--nav-accent);
  opacity: 0.4;
  transform: scale(1);
  filter: var(--nav-flower-shadow);
  transition: opacity 180ms ease, transform 220ms cubic-bezier(.22,.61,.36,1), filter 220ms ease;
}

.nav-flower-petal,
.nav-flower-accent { fill: currentColor; }

.nav-flower-accent {
  opacity: 0;
  transform-box: fill-box;
  transform-origin: center;
  transition: opacity 180ms ease, transform 220ms cubic-bezier(.22,.61,.36,1);
}

.nav-flower-accent-left { transform: translateX(2px) scale(0.94); }
.nav-flower-accent-right { transform: translateX(-2px) scale(0.94); }

.nav a.is-passed .nav-flower-glyph,
.nav a:hover .nav-flower-glyph,
.nav a:focus-visible .nav-flower-glyph,
.nav a.is-active .nav-flower-glyph { opacity: 1; }

.nav a:hover .nav-flower-glyph,
.nav a:focus-visible .nav-flower-glyph {
  filter: var(--nav-flower-shadow-hover);
}

.nav a.is-active .nav-flower-glyph {
  filter: var(--nav-flower-shadow-active);
}

.nav a.is-active .nav-flower-accent {
  opacity: 1;
  transform: translateX(0) scale(1);
}

/* Static control for moving to the next major section. */
.scroll-guide {
  position: fixed;
  right: var(--scroll-guide-offset);
  bottom: var(--scroll-guide-offset);
  z-index: 26;
  display: grid;
  width: 48px;
  height: 48px;
  place-items: center;
  border: 1px solid var(--border);
  border-radius: 50%;
  background: var(--panel);
  color: var(--text);
  text-decoration: none;
  opacity: 0.82;
  box-shadow: 0 8px 24px color-mix(in srgb, #000 16%, transparent);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
  transition: opacity 220ms ease, transform 220ms ease, background-color 420ms ease, border-color 420ms ease, color 420ms ease;
}

.scroll-guide:hover,
.scroll-guide:focus-visible {
  opacity: 1;
  transform: translateY(2px);
  background: var(--panel-strong);
}

.scroll-guide:focus-visible { outline: 2px solid currentColor; outline-offset: 3px; }

.scroll-guide.is-hidden {
  opacity: 0;
  pointer-events: none;
  transform: translateY(8px);
}

.scroll-guide-arrow {
  display: block;
  font-size: 1.45rem;
  line-height: 1;
  transform: translateY(-1px);
}

@media (max-width: 760px) {
  .brand-logo { width: 92px; }
  .scroll-guide { bottom: 0.65rem; }
}

@media (max-width: 625px) {
  body.nav-open { overflow: hidden; }

  .site-header {
    position: fixed;
    right: 0;
    left: 0;
    display: grid;
    grid-template-columns: auto 1fr 40px 40px;
    grid-template-rows: 1fr;
    column-gap: 0.6rem;
    width: 100%;
    height: 68px;
    min-height: 68px;
    padding: 0.65rem 1.5rem;
  }

  body.nav-open .site-header {
    z-index: 51;
    background: transparent;
    box-shadow: none;
  }

  body.nav-open .mobile-nav-header-surface {
    position: fixed;
    z-index: 51;
    top: 0;
    right: 0;
    left: 0;
    display: block;
    height: 78px;
    background: var(--mobile-nav-header-bg);
    border-bottom: 1px solid var(--border);
    border-bottom-color: color-mix(in srgb, var(--nav-divider) 15%, transparent);
    pointer-events: none;
  }

  body.nav-open .site-header .brand-logo-base,
  body.nav-open .site-header .brand-logo-wordmark,
  body.nav-open .site-header .brand-logo-flower,
  body.nav-open .site-header .theme-toggle,
  body.nav-open .site-header .menu-toggle {
    color: #ffffff;
  }

  body.nav-open .site-header .theme-toggle,
  body.nav-open .site-header .menu-toggle {
    border-color: rgba(255, 255, 255, 0.28);
    background: rgba(255, 255, 255, 0.06);
  }

  body.nav-open .site-header .theme-toggle:hover,
  body.nav-open .site-header .theme-toggle:focus-visible,
  body.nav-open .site-header .menu-toggle:hover,
  body.nav-open .site-header .menu-toggle:focus-visible {
    background: rgba(255, 255, 255, 0.12);
  }

  .site-header .brand {
    grid-column: 1;
    grid-row: 1;
    justify-self: start;
    margin: 0;
    z-index: 52;
  }

  .site-header .theme-toggle,
  .site-header .menu-toggle {
    position: static;
    width: 40px;
    min-width: 40px;
    max-width: 40px;
    height: 40px;
    min-height: 40px;
    margin: 0;
    padding: 0;
    align-self: center;
  }

  .site-header .theme-toggle {
    grid-column: 3;
    grid-row: 1;
    justify-self: end;
    justify-content: center;
    z-index: 53;
  }

  .site-header .menu-toggle {
    display: inline-flex;
    grid-column: 4;
    grid-row: 1;
    justify-self: end;
    z-index: 54;
  }

  .theme-label { display: none; }

  .theme-icon {
    display: inline-flex;
    width: 1em;
    height: 1em;
    margin: 0;
    align-items: center;
    justify-content: center;
    font-size: 1rem;
    line-height: 1;
  }

  .nav {
    position: fixed;
    inset: 0;
    z-index: 50;
    display: flex;
    width: 100vw;
    min-width: 0;
    height: 100vh;
    height: 100dvh;
    padding: 7.9rem 1.5rem 2rem;
    flex-direction: column;
    align-items: stretch;
    justify-content: flex-start;
    gap: 0.78rem;
    overflow-y: auto;
    background: var(--nav-overlay-bg);
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    -webkit-backdrop-filter: blur(20px) saturate(120%);
    backdrop-filter: blur(20px) saturate(120%);
    transition: opacity 180ms ease, visibility 180ms ease, background-color 220ms ease;
  }

  .nav.is-open {
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
  }

  .nav::before {
    content: "";
    position: absolute;
    top: 77px;
    right: 0;
    left: 0;
    height: 1px;
    background: var(--nav-divider);
    opacity: 0.15;
    pointer-events: none;
  }

  .nav-progress-rail { display: none; }

  .nav a {
    display: flex;
    width: 100%;
    min-height: 64px;
    margin: 0;
    padding: 0.8rem 0;
    align-items: center;
    justify-content: flex-start;
    gap: 1rem;
    color: var(--muted);
    font-size: 1rem;
    line-height: 1.25;
    text-shadow: none;
  }

  .nav a .nav-label {
    color: var(--muted);
    opacity: 0.95;
  }

  html[data-theme="dark"] .nav a,
  html[data-theme="dark"] .nav a .nav-label {
    color: #ffffff;
  }

  .nav a:hover .nav-label,
  .nav a:focus-visible .nav-label,
  .nav a.is-active .nav-label { opacity: 1; }

  .nav-flower-marker {
    width: 2.25rem;
    height: 1.7rem;
    flex: 0 0 2.25rem;
    justify-content: flex-start;
  }

  .nav-flower-glyph {
    width: 2rem;
    height: 1.44rem;
    opacity: 0.4;
    filter: none;
  }

  .nav a:not(.is-active) .nav-flower-glyph { transform: scale(0.75); }

  .nav a:hover .nav-flower-glyph,
  .nav a:focus-visible .nav-flower-glyph,
  .nav a.is-active .nav-flower-glyph {
    opacity: 1;
    transform: scale(1);
  }

  .nav a.is-active .nav-flower-accent {
    opacity: 1;
    transform: translateX(0) scale(1);
  }

  .nav a.is-passed:not(.is-active) .nav-flower-glyph {
    opacity: 0.4;
    transform: scale(0.75);
    filter: none;
  }

  .nav a.is-passed:not(.is-active) .nav-flower-accent {
    opacity: 0;
  }

  .nav,
  .nav a,
  .nav a *,
  .nav .nav-label { text-shadow: none; }
}

@media (hover: none) {
  .paper-sheet.is-fan-open:not(.is-active-project):hover .paper-edge-label {
    filter: none;
  }
}

/* --------------------------------------------------------------------------
   Reduced motion
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  .landscape-track,
  .theme-veil,
  .preloader,
  body,
  .project-gallery,
  .button,
  .theme-toggle,
  .menu-toggle,
  .nav,
  .nav-label,
  .nav-progress-fill {
    animation: none !important;
    transition: none !important;
  }

  .reveal-section,
  .js .reveal-section:not(.hero),
  .js .story-reveal,
  .js .story-reveal.is-active,
  .js .story-reveal.is-past,
  .js .story-reveal.is-future,
  .js .story-reveal.is-next {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
    will-change: auto;
  }

  .content-section,
  .contact-panel,
  .paper-sheet {
    -webkit-mask-image: none;
    mask-image: none;
  }

  .project-gallery-track {
    transition: none;
  }

  .brand-logo-flower,
  .nav-flower-glyph,
  .nav-flower-accent,
  .scroll-guide {
    transition: none !important;
  }

  .brand-logo-flower {
    transform: rotate(0deg) !important;
    will-change: auto;
  }

  .brand:hover .brand-logo-flower,
  .brand:focus-visible .brand-logo-flower,
  .brand:focus-within .brand-logo-flower {
    opacity: 0.78;
  }

  .scroll-guide:hover,
  .scroll-guide:focus-visible,
  .scroll-guide.is-hidden {
    transform: none !important;
  }
}

/* --------------------------------------------------------------------------
 * Scene atmosphere
 * --------------------------------------------------------------------------
 * These effects live inside the same 12000×1600 sky stack as the landscape.
 * The semantic mountains therefore render in front of them, and mobile crops
 * the wide scene instead of compressing the star field.
 */
.sky-effects,
.sky-motion,
.scene-horizon-glow,
.scene-sun-rays,
.scene-star-field,
.scene-dark-deepen,
.scene-dark-cool-shift,
.scene-aurora {
  position: absolute;
  inset: 0;
  height: 100vh;
  pointer-events: none;
}

.sky-effects {
  width: 100vw;
  overflow: hidden;
  transition: opacity 420ms ease;
}

.sky-effects-dark { opacity: 1; }
.sky-effects-light { opacity: 0; }

.sky-motion {
  width: 100vw;
  background-repeat: no-repeat;
  will-change: auto;
  animation-play-state: paused;
}

.sky-motion.is-running {
  will-change: transform, background-position, opacity;
  animation-play-state: running;
}

/* Winter movement is intentionally blue-only. */
.sky-motion-light-cool {
  background-image:
    radial-gradient(16% 72% at 8% 18%, rgba(183, 215, 255, .34), transparent 72%),
    radial-gradient(18% 76% at 24% 28%, rgba(205, 226, 255, .28), transparent 70%),
    radial-gradient(15% 70% at 39% 15%, rgba(194, 214, 250, .22), transparent 70%);
  background-size: 115% 115%, 120% 120%, 112% 112%;
  opacity: .62;
  animation: lightCoolSkyDrift 11s ease-in-out infinite alternate;
}

.sky-motion-light-purple {
  background-image:
    radial-gradient(18% 74% at 46% 18%, rgba(210, 196, 244, .28), transparent 70%),
    radial-gradient(18% 76% at 58% 28%, rgba(225, 199, 239, .24), transparent 72%);
  background-size: 118% 118%, 124% 124%;
  opacity: var(--light-purple-atmosphere-opacity, 0);
  animation: lightPurpleSkyDrift 13s ease-in-out infinite alternate;
}

.sky-motion-light-warm {
  background-image:
    radial-gradient(19% 78% at 68% 18%, rgba(248, 194, 222, .34), transparent 70%),
    radial-gradient(18% 76% at 81% 30%, rgba(255, 207, 204, .28), transparent 70%),
    radial-gradient(17% 72% at 93% 18%, rgba(255, 225, 170, .30), transparent 68%);
  background-size: 118% 118%, 122% 122%, 112% 112%;
  opacity: var(--light-warm-atmosphere-opacity, 0);
  animation: lightWarmSkyDrift 12s ease-in-out infinite alternate;
}

.sky-motion-dark {
  background-image:
    radial-gradient(18% 76% at 12% 18%, rgba(54, 94, 164, .20), transparent 72%),
    radial-gradient(18% 76% at 42% 22%, rgba(92, 81, 156, .19), transparent 72%),
    radial-gradient(17% 74% at 70% 18%, rgba(84, 106, 182, .15), transparent 70%),
    radial-gradient(15% 70% at 92% 24%, rgba(86, 148, 188, .14), transparent 68%);
  background-size: 116% 116%, 122% 122%, 118% 118%, 112% 112%;
  opacity: var(--dark-motion-opacity, 0);
  animation: darkSkyDrift 12s ease-in-out infinite alternate;
}

.scene-dark-deepen {
  width: 100vw;
  background:
    linear-gradient(to bottom,
      rgba(12, 18, 42, .64) 0%,
      rgba(16, 21, 48, .48) 20%,
      rgba(22, 26, 55, .28) 42%,
      rgba(24, 27, 56, .12) 62%,
      transparent 82%);
  opacity: var(--dark-spring-deepen-opacity, 0);
}

.scene-dark-cool-shift {
  width: 100vw;
  background:
    radial-gradient(28% 56% at 78% 16%, rgba(102, 165, 212, .26), transparent 74%),
    radial-gradient(24% 50% at 58% 12%, rgba(118, 136, 214, .18), transparent 74%),
    radial-gradient(18% 44% at 28% 18%, rgba(86, 142, 198, .12), transparent 76%);
  opacity: var(--dark-cool-shift-opacity, 0);
}

/* Independent viewport aurora.
 * It does not inherit landscape travel or the long sky-image width. The parent
 * only controls scroll fade-in; the two ribbons use transform + opacity for
 * lightweight breathing motion.
 */
.scene-aurora {
  position: absolute;
  inset: 0;
  width: 100vw;
  height: 100vh;
  overflow: hidden;
  opacity: var(--dark-aurora-opacity, 0);
  pointer-events: none;
  contain: paint;
}

.scene-aurora::before,
.scene-aurora::after {
  content: "";
  position: absolute;
  inset: -6% -12% 34%;
  will-change: auto;
  transform-origin: 50% 0;
  animation-play-state: paused;
}

.scene-aurora.is-running::before,
.scene-aurora.is-running::after {
  will-change: transform, opacity;
  animation-play-state: running;
}

/* Primary ribbon: broad enough to read across a phone without becoming a
   narrow stripe. Soft edges come from the gradients themselves, so no large
   animated blur/filter is required. */
.scene-aurora::before {
  background:
    linear-gradient(102deg,
      transparent 0%,
      rgba(63, 215, 207, 0) 10%,
      rgba(63, 215, 207, .21) 19%,
      rgba(180, 105, 229, .25) 30%,
      rgba(72, 226, 177, .22) 42%,
      rgba(190, 104, 220, .19) 55%,
      rgba(68, 205, 199, .13) 68%,
      rgba(68, 205, 199, 0) 82%,
      transparent 100%);
  opacity: .96;
  animation: auroraFloatA 18s ease-in-out infinite alternate;
}

/* Secondary ribbon: offset and slower so the aurora gently changes shape and
   brightness instead of moving as one rigid band. */
.scene-aurora::after {
  background:
    linear-gradient(96deg,
      transparent 0%,
      rgba(166, 99, 220, 0) 14%,
      rgba(166, 99, 220, .17) 25%,
      rgba(66, 215, 194, .19) 38%,
      rgba(193, 111, 226, .18) 51%,
      rgba(76, 224, 177, .14) 64%,
      rgba(76, 224, 177, 0) 78%,
      transparent 100%);
  opacity: .78;
  animation: auroraFloatB 24s ease-in-out infinite alternate;
}

/* A horizon band behind the mountains: high enough to read as distant light,
   never a foreground wash over the page or project cards. */
.scene-horizon-glow {
  display: none;
}

.scene-horizon-glow-light {
  background: linear-gradient(to bottom,
    transparent 0%,
    rgba(255, 229, 198, .05) 22%,
    rgba(255, 211, 204, .18) 48%,
    rgba(244, 197, 224, .11) 62%,
    transparent 100%);
  opacity: var(--light-horizon-glow-opacity, 0);
}

.scene-horizon-glow-dark {
  background: linear-gradient(to bottom,
    transparent 0%,
    rgba(106, 118, 190, .04) 18%,
    rgba(128, 111, 182, .23) 46%,
    rgba(101, 92, 158, .16) 62%,
    transparent 100%);
  opacity: var(--dark-horizon-glow-opacity, 0);
}

/* Spring rays are viewport-sized inside the fixed scene stack, so they stay
   anchored at the visible top-right while the wide landscape travels behind them. */
.scene-sun-rays {
  left: 0;
  right: auto;
  width: 100vw;
  height: 100vh;
  background:
    conic-gradient(from 204deg at 100% 0%,
      transparent 0deg 5deg,
      rgba(255, 249, 228, .46) 5deg 13deg,
      transparent 13deg 18deg,
      rgba(255, 239, 198, .28) 18deg 27deg,
      transparent 27deg 32deg,
      rgba(255, 248, 225, .34) 32deg 40deg,
      transparent 40deg 46deg,
      rgba(255, 234, 186, .22) 46deg 54deg,
      transparent 54deg 360deg);
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 58%, rgba(0,0,0,.4) 78%, transparent 100%);
  mask-image: linear-gradient(to bottom, #000 0%, #000 58%, rgba(0,0,0,.4) 78%, transparent 100%);
  opacity: var(--light-rays-opacity, 0);
  transform-origin: 100% 0;
  animation: sceneRayBreath 18s ease-in-out infinite alternate;
  animation-play-state: paused;
  will-change: auto;
}

.scene-sun-rays.is-running {
  animation-play-state: running;
  will-change: transform;
}

.scene-star-field {
  /* Explicit 6000:1600 aspect ratio prevents an oversized intrinsic-SVG first paint. */
  width: 375vh;
  max-width: none;
  overflow: visible;
  left: 0;
  top: 0;
  height: 100vh;
}

.star-group {
  opacity: 0;
}
.star-base { opacity: var(--stars-base-opacity, 0); }
.star-medium { opacity: var(--stars-medium-opacity, 0); }
.star-slow { opacity: var(--stars-slow-opacity, 0); }
.star-blink { opacity: var(--stars-blink-opacity, 0); }

.scene-star-field circle {
  fill: rgba(255,255,255,1);
  opacity: var(--star-base, .65);
  animation-duration: var(--star-duration, 8s);
  animation-delay: var(--star-delay, 0s);
  animation-iteration-count: infinite;
  animation-timing-function: linear;
  animation-play-state: paused;
  transform-box: fill-box;
  transform-origin: center;
  transform: scale(1.33);
}

.star-twinkle-dip { animation-name: sceneStarTwinkleDip; }
.star-twinkle-flash { animation-name: sceneStarTwinkleFlash; }
.star-sleeper { animation-name: sceneStarSleeperBlip; }

/* Timing variants keep one shared star system while giving the sky less
   mechanical twinkle pacing. Fast remains the default; selected stars use
   slightly broader opacity ramps for medium/slow blips. */
.star-twinkle-dip.star-blip-medium { animation-name: sceneStarTwinkleDipMedium; }
.star-twinkle-dip.star-blip-slow { animation-name: sceneStarTwinkleDipSlow; }
.star-twinkle-flash.star-blip-medium { animation-name: sceneStarTwinkleFlashMedium; }
.star-twinkle-flash.star-blip-slow { animation-name: sceneStarTwinkleFlashSlow; }

.scene-star-field.is-running circle {
  animation-play-state: running;
}

/* Snow layer: CSS-only flakes in a dedicated foreground-atmosphere layer.
   It sits above the landscape SVG but remains inside `.landscape`, whose whole
   stacking context is behind the page content. Mobile uses a separate wide
   field with `slice`, so it is cropped rather than compressed. */
.scene-snow {
  position: absolute;
  inset: 0;
  width: 100vw;
  height: 100vh;
  overflow: hidden;
  pointer-events: none;
  contain: paint;
  z-index: 3;
}

.scene-snow-svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: hidden;
}

.scene-snow-mobile { display: none; }

.snow-group { opacity: 0; }
.snow-far { opacity: var(--snow-far-opacity, 0); }
.snow-mid { opacity: var(--snow-mid-opacity, 0); }
.snow-near { opacity: var(--snow-near-opacity, 0); }

.scene-snow circle {
  fill: rgba(255,255,255,.96);
  animation: snowFallWander var(--snow-duration) linear var(--snow-delay) infinite;
  animation-play-state: paused;
  will-change: transform;
  backface-visibility: hidden;
  transform: translateZ(0);
}

.scene-snow.is-running circle {
  animation-play-state: running;
}

/* Five horizontal waypoints give the flakes a loose, wind-shifted path rather
   than one straight diagonal. The browser still only animates transforms. */
@keyframes snowFallWander {
  0%   { transform: translate3d(0, -14vh, 0); }
  18%  { transform: translate3d(var(--snow-x1, 0px), 8vh, 0); }
  38%  { transform: translate3d(var(--snow-x2, 0px), 34vh, 0); }
  60%  { transform: translate3d(var(--snow-x3, 0px), 61vh, 0); }
  80%  { transform: translate3d(var(--snow-x4, 0px), 84vh, 0); }
  100% { transform: translate3d(var(--snow-x5, 0px), 116vh, 0); }
}

@media (max-width: 760px) {
  .scene-snow-desktop { display: none; }
  .scene-snow-mobile { display: block; }
}

@media (prefers-reduced-motion: reduce) {
  .scene-snow circle { animation: none !important; }
}

/* --------------------------------------------------------------------------
 * Spring petal atmosphere
 * --------------------------------------------------------------------------
 * A restrained breeze rather than constant falling confetti. Petals live
 * above the landscape artwork but below all story/page content. The same
 * population is shared by desktop and mobile; the viewport simply crops it.
 */
.scene-petals {
  position: absolute;
  inset: 0;
  width: 100vw;
  height: 100vh;
  overflow: hidden;
  pointer-events: none;
  contain: paint;
  z-index: 4;
  opacity: var(--petal-opacity, 0);
}

.scene-petal {
  position: absolute;
  left: var(--petal-origin-x, calc(100vw + 2vh));
  top: calc(var(--petal-top, 20vh) - 8vh);
  width: var(--petal-w, 8px);
  height: var(--petal-h, 14px);
  border-radius: 78% 22% 72% 28% / 66% 35% 65% 34%;
  opacity: 0;
  transform-origin: 50% 75%;
  animation: springPetalSweep var(--petal-duration, 16s) linear var(--petal-delay, 0s) infinite;
  animation-play-state: paused;
  will-change: transform;
  backface-visibility: hidden;
}

.scene-petal.petal-pink { background: var(--petal-pink); }
.scene-petal.petal-lilac { background: var(--petal-lilac); }
.scene-petal.petal-cream { background: var(--petal-cream); }
.scene-petals.is-running .scene-petal { animation-play-state: running; }

@keyframes springPetalSweep {
  0%   { opacity: 0; transform: translate3d(2vh, -2vh, 0) rotate(var(--petal-rot, 0deg)) scale(var(--petal-scale, 1)); }
  6%   { opacity: .9; }
  22%  { opacity: .9; transform: translate3d(var(--petal-x1, -22vw), 7vh, 0) rotate(calc(var(--petal-rot, 0deg) - 105deg)) scale(var(--petal-scale, 1)); }
  47%  { opacity: .9; transform: translate3d(var(--petal-x2, -47vw), 17vh, 0) rotate(calc(var(--petal-rot, 0deg) - 230deg)) scale(var(--petal-scale, 1)); }
  73%  { opacity: .9; transform: translate3d(var(--petal-x3, -73vw), 29vh, 0) rotate(calc(var(--petal-rot, 0deg) - 355deg)) scale(var(--petal-scale, 1)); }
  94%  { opacity: .9; }
  100% { opacity: 0; transform: translate3d(var(--petal-x4, -118vw), 43vh, 0) rotate(calc(var(--petal-rot, 0deg) - 520deg)) scale(var(--petal-scale, 1)); }
}

@media (prefers-reduced-motion: reduce) {
  .scene-petals { display: none; }
}

@keyframes lightCoolSkyDrift {
  from { transform: translate3d(-1.0%, -.3%, 0); background-position: 0% 10%, 18% 22%, 34% 6%; }
  to   { transform: translate3d(1.4%, .4%, 0); background-position: 9% 20%, 28% 10%, 42% 22%; }
}
@keyframes lightPurpleSkyDrift {
  from { transform: translate3d(-.8%, .2%, 0); background-position: 40% 8%, 54% 24%; }
  to   { transform: translate3d(1.2%, -.3%, 0); background-position: 52% 24%, 63% 10%; }
}
@keyframes lightWarmSkyDrift {
  from { transform: translate3d(-1.2%, -.2%, 0); background-position: 65% 8%, 78% 24%, 89% 12%; }
  to   { transform: translate3d(1.1%, .4%, 0); background-position: 75% 24%, 86% 8%, 96% 22%; }
}
@keyframes darkSkyDrift {
  from { transform: translate3d(-1.0%, -.2%, 0); background-position: 5% 8%, 35% 24%, 65% 8%, 88% 22%; }
  to   { transform: translate3d(1.2%, .3%, 0); background-position: 15% 24%, 48% 8%, 76% 22%, 98% 10%; }
}
@keyframes sceneRayBreath {
  from { transform: translate3d(0,0,0) rotate(-.2deg) scale(1.01); }
  to   { transform: translate3d(-.65%, .4%, 0) rotate(.25deg) scale(1.035); }
}
@keyframes sceneStarTwinkleDip {
  0%, 56% { opacity: var(--star-base, .65); }
  57% { opacity: 0; }
  58% { opacity: var(--star-base, .65); }
  100% { opacity: var(--star-base, .65); }
}

@keyframes sceneStarTwinkleFlash {
  0%, 61% { opacity: var(--star-base, .65); }
  62% { opacity: var(--star-peak, 1); }
  63% { opacity: 0; }
  64% { opacity: var(--star-peak, 1); }
  65% { opacity: var(--star-base, .65); }
  100% { opacity: var(--star-base, .65); }
}

@keyframes sceneStarTwinkleDipMedium {
  0%, 53% { opacity: var(--star-base, .65); }
  56% { opacity: 0; }
  59%, 100% { opacity: var(--star-base, .65); }
}

@keyframes sceneStarTwinkleDipSlow {
  0%, 50% { opacity: var(--star-base, .65); }
  54% { opacity: 0; }
  58%, 100% { opacity: var(--star-base, .65); }
}

@keyframes sceneStarTwinkleFlashMedium {
  0%, 56% { opacity: var(--star-base, .65); }
  59% { opacity: var(--star-peak, 1); }
  62% { opacity: 0; }
  65% { opacity: var(--star-peak, 1); }
  68%, 100% { opacity: var(--star-base, .65); }
}

@keyframes sceneStarTwinkleFlashSlow {
  0%, 52% { opacity: var(--star-base, .65); }
  56% { opacity: var(--star-peak, 1); }
  60% { opacity: 0; }
  64% { opacity: var(--star-peak, 1); }
  68%, 100% { opacity: var(--star-base, .65); }
}

@keyframes sceneStarSleeperBlip {
  0%, 72% { opacity: 0; }
  73% { opacity: var(--star-peak, .7); }
  74%, 100% { opacity: 0; }
}

@keyframes auroraFloatA {
  0%   { transform: translate3d(-3%, -1.2%, 0) skewX(-3deg) scaleY(.96); opacity: .28; }
  18%  { opacity: .76; }
  52%  { opacity: 1; }
  100% { transform: translate3d(3%, 1.0%, 0) skewX(2deg) scaleY(1.05); opacity: .44; }
}
@keyframes auroraFloatB {
  0%   { transform: translate3d(2%, -.8%, 0) skewX(2deg) scaleY(1.02); opacity: .18; }
  28%  { opacity: .56; }
  64%  { opacity: .86; }
  100% { transform: translate3d(-2.5%, .8%, 0) skewX(-2deg) scaleY(.95); opacity: .26; }
}

@media (prefers-reduced-motion: reduce) {
  .sky-motion,
  .scene-sun-rays,
  .scene-aurora::before,
  .scene-aurora::after,
  .star-base circle,
  .scene-star-field circle {
    animation: none !important;
  }
  .scene-aurora::before { opacity: .72; }
  .scene-aurora::after { opacity: .50; }
  .scene-star-field circle { opacity: var(--star-base, .65); }
}

/* Mobile aurora: use a taller, wider composition rather than shrinking the
 * desktop ribbons. This keeps the effect atmospheric instead of stripe-like.
 */
@media (max-width: 760px) {
  .scene-aurora {
    opacity: calc(var(--dark-aurora-opacity, 0) * 1.18);
  }

  .scene-aurora::before,
  .scene-aurora::after {
    inset: -12% -42% 18%;
  }

  .scene-aurora::before {
    background:
      linear-gradient(103deg,
        transparent 0%,
        rgba(63, 215, 207, 0) 4%,
        rgba(63, 215, 207, .23) 16%,
        rgba(180, 105, 229, .27) 32%,
        rgba(72, 226, 177, .24) 50%,
        rgba(190, 104, 220, .21) 66%,
        rgba(68, 205, 199, 0) 88%,
        transparent 100%);
    animation-duration: 16s;
  }

  .scene-aurora::after {
    background:
      linear-gradient(97deg,
        transparent 0%,
        rgba(166, 99, 220, 0) 8%,
        rgba(166, 99, 220, .18) 22%,
        rgba(66, 215, 194, .20) 40%,
        rgba(193, 111, 226, .19) 58%,
        rgba(76, 224, 177, 0) 84%,
        transparent 100%);
    animation-duration: 21s;
  }

}


/* --------------------------------------------------------------------------
   Progressive-enhancement fallback
   -------------------------------------------------------------------------- */

html:not(.js) .project-paper-stack {
  display: block;
  width: min(100%, 1040px);
  margin: 0 auto;
  padding: 1rem 0 2rem;
}

html:not(.js) .project-paper-stack > .paper-sheet {
  position: relative;
  grid-column: auto;
  grid-row: auto;
  width: calc(100% - 2rem);
  max-width: 1000px;
  margin: 0 auto clamp(1.4rem, 3vw, 2.25rem);
  opacity: 1;
  transform: none !important;
}

html:not(.js) .project-paper-stack > .paper-sheet:last-child {
  margin-bottom: 0;
}

html:not(.js) .paper-edge-label,
html:not(.js) .paper-project-nav,
html:not(.js) .mobile-project-more {
  display: none !important;
}

@media (max-width: 680px) {
  html:not(.js) .paper-sheet .project-details {
    display: block;
  }
}
