/* ————————————————————————————————————————————————————————————————
   Observatory log — deep-field minimal.
   Near-black sky, warm starlight ink, one amber star accent.
   Type: Instrument Serif (display) · Newsreader (prose) · Spline Sans Mono (instrument labels)
   ———————————————————————————————————————————————————————————————— */

:root {
  --bg: #06070d;
  --bg-raise: #0b0d18;
  --ink: #e9e4d6;          /* warm starlight, not pure white */
  --ink-dim: #9d98a6;
  --ink-faint: #5c5868;
  --amber: #e3b864;        /* the star */
  --amber-dim: #8a6f3d;
  --teal: #8fd0c6;         /* faint oxygen-III green-blue, used sparingly */
  --line: rgba(233, 228, 214, 0.13);
  --line-soft: rgba(233, 228, 214, 0.07);
  --serif: "Instrument Serif", "Iowan Old Style", Georgia, serif;
  --prose: "Newsreader", Georgia, "Times New Roman", serif;
  --mono: "Spline Sans Mono", "SFMono-Regular", ui-monospace, monospace;
  --measure: 41rem;
  /* top edge of the campsite dirt layer, measured from the viewport bottom.
     campsite ground band = bottom 10vh; grass strip = 45% of it (~4.5vh);
     dirt is the rest, so its top sits ~5.5vh up. the footer rests "contact" here. */
  --dirt-top: 5.5vh;
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--prose);
  font-weight: 350;
  font-size: 1.0625rem;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
  /* footer sits at the viewport bottom even on short pages */
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}
main { flex: 1 0 auto; }

::selection { background: var(--amber); color: #14100a; }

a { color: var(--ink); text-decoration-color: var(--amber-dim); text-underline-offset: 3px; }
a:hover { color: var(--amber); text-decoration-color: var(--amber); }

/* —— touch behaviour —————————————————————————————————————————————
   Kill the grey tap-flash on every control, and stop UI chrome (the nav
   rows, back links, wordmark, toggle, right-click menu) from starting a
   text selection on tap — the bug where tapping a row "selected the whole
   list" with no way to deselect. Prose/article text stays fully selectable.
   touch-action: manipulation also drops the 300ms tap delay + double-tap zoom. */
a, button { -webkit-tap-highlight-color: transparent; }
.nav-list a, .backlink a, .wordmark, .site-head nav a, .camp-toggle, .skymenu,
.nav-arrow, .idx {
  -webkit-user-select: none; -moz-user-select: none; user-select: none;
  -webkit-touch-callout: none; touch-action: manipulation;
}
:focus-visible { outline: 2px solid var(--amber); outline-offset: 3px; border-radius: 1px; }

/* —— sky layers ——————————————————————————————————— */

#starfield {
  position: fixed; inset: 0; width: 100%; height: 100%;
  z-index: -3; pointer-events: none;
}

.nebula {
  position: fixed; inset: -20%;
  z-index: -2; pointer-events: none;
  background:
    radial-gradient(38% 30% at 78% 12%, rgba(46, 48, 102, 0.32), transparent 70%),
    radial-gradient(30% 26% at 12% 78%, rgba(26, 60, 64, 0.25), transparent 70%),
    radial-gradient(20% 18% at 60% 60%, rgba(78, 52, 36, 0.10), transparent 70%);
}
@media (prefers-reduced-motion: no-preference) {
  /* will-change pins it to its own compositor layer up front, so the 90s drift
     is a pure GPU transform (no repaint, no promotion hitch on the first frame) */
  .nebula { animation: nebula-drift 90s ease-in-out infinite alternate; will-change: transform; }
  @keyframes nebula-drift {
    from { transform: translate3d(0, 0, 0) scale(1); }
    to   { transform: translate3d(-1.5%, -1%, 0) scale(1.05); }
  }
}

#campsite {
  position: fixed; left: 0; bottom: 0; width: 100vw; height: 100vh;
  z-index: -1; pointer-events: none;
  image-rendering: pixelated; image-rendering: crisp-edges;
}

.camp-toggle {
  position: fixed; right: 0.9rem; bottom: 0.7rem; z-index: 40;
  font-family: var(--mono); font-size: 0.6rem; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--ink-faint);
  background: rgba(9, 10, 18, 0.6); border: 1px solid var(--line-soft);
  padding: 0.45rem 0.7rem; cursor: pointer;
}
.camp-toggle:hover { color: var(--amber); border-color: var(--amber-dim); }
.camp-toggle .dot {
  display: inline-block; width: 6px; height: 6px; border-radius: 50%;
  background: var(--amber); margin-right: 0.55em; vertical-align: 1px;
}
.camp-toggle[aria-pressed="false"] .dot { background: var(--ink-faint); }

/* —— custom right-click menu (sky & campsite events) ————————————— */
.skymenu {
  position: fixed; z-index: 60; min-width: 11rem;
  background: rgba(9, 10, 18, 0.92); border: 1px solid var(--line);
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.5);
  padding: 0.35rem; backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
}
.skymenu[hidden] { display: none; }
.skymenu-group + .skymenu-group {
  margin-top: 0.3rem; padding-top: 0.3rem; border-top: 1px solid var(--line-soft);
}
.skymenu-head {
  margin: 0.15rem 0.5rem 0.25rem;
  font-family: var(--mono); font-size: 0.58rem; letter-spacing: 0.2em;
  text-transform: uppercase; color: var(--ink-faint);
}
.skymenu-item {
  display: block; width: 100%; text-align: left;
  font-family: var(--mono); font-size: 0.74rem; letter-spacing: 0.04em;
  color: var(--ink-dim); background: none; border: 0;
  padding: 0.34rem 0.5rem; cursor: pointer;
}
.skymenu-item:hover, .skymenu-item:focus-visible {
  color: var(--amber); background: rgba(227, 184, 100, 0.08); outline: none;
}
.skymenu-item::before { content: "✶  "; color: var(--amber-dim); }
.skymenu-item:hover::before { color: var(--amber); }

.grain {
  position: fixed; inset: 0; z-index: -1; pointer-events: none;
  opacity: 0.5; mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3CfeComponentTransfer%3E%3CfeFuncA type='linear' slope='0.08'/%3E%3C/feComponentTransfer%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* —— scaffold ————————————————————————————————————— */

.site-head, main, .site-foot {
  width: min(72rem, 100% - 3rem);
  margin-inline: auto;
}

.site-head {
  display: flex; justify-content: space-between; align-items: baseline;
  padding: 1.6rem 0 1.2rem;
  border-bottom: 1px solid var(--line-soft);
}

.wordmark {
  font-family: var(--mono); font-size: 0.8rem; font-weight: 500;
  letter-spacing: 0.14em; text-transform: uppercase; text-decoration: none;
}
.wordmark .star { color: var(--amber); }

.site-head nav { display: flex; gap: 1.8rem; }
.site-head nav a {
  font-family: var(--mono); font-size: 0.74rem; letter-spacing: 0.16em;
  text-transform: uppercase; text-decoration: none; color: var(--ink-dim);
}
.site-head nav a:hover { color: var(--amber); }

.mono-label {
  font-family: var(--mono); font-size: 0.72rem; font-weight: 400;
  letter-spacing: 0.2em; text-transform: uppercase; color: var(--ink-dim);
}
.mono-label .star { color: var(--amber); letter-spacing: 0; }
.mono-label a { color: inherit; text-decoration: none; }
.mono-label a:hover { color: var(--amber); }

/* —— hero ————————————————————————————————————————— */

.hero { padding: 2rem 0 clamp(2.5rem, 6vh, 4rem); }
.hero h1, .notfound h1 {
  font-family: var(--serif); font-weight: 400;
  font-size: clamp(2.7rem, 6.5vw, 5.2rem);
  line-height: 1.04; letter-spacing: -0.01em;
  margin: 0.9rem 0 1.2rem; max-width: 18ch;
}
.hero h1 em, .notfound h1 em { font-style: italic; color: var(--amber); }

.hero-sub { max-width: var(--measure); color: var(--ink-dim); font-size: 1.12rem; margin: 0; }
.hero-sub a { color: var(--ink); }

/* —— under-construction blocker (terse, small) ———————— */
.construction { padding: 5rem 0 6rem; display: grid; gap: 1.1rem; justify-items: start; }
.construction .uc-msg { color: var(--amber); font-size: 0.78rem; }

/* —— nav list (index page) ———————————————————————— */

.nav-list ol {
  list-style: none; margin: clamp(2.5rem, 8vh, 4.5rem) 0 4rem; padding: 0;
  border-top: 1px solid var(--line);
}
.nav-list li { position: relative; border-bottom: 1px solid var(--line); }
.nav-list li::after {
  /* comet-trail sweep along the row's lower border on hover */
  content: ""; position: absolute; left: 0; bottom: -1px;
  width: 100%; height: 1px; pointer-events: none;
  background: linear-gradient(90deg, var(--amber), rgba(227, 184, 100, 0.25) 55%, transparent);
  transform: scaleX(0); transform-origin: left;
  transition: transform 600ms cubic-bezier(0.2, 0.6, 0.2, 1);
}
.nav-list li:hover::after { transform: scaleX(1); }
.nav-list a {
  display: flex; align-items: baseline; gap: 1.6rem;
  padding: 1.7rem 0.5rem; text-decoration: none;
  transition: background 160ms ease;
}
.nav-list a:hover { background: rgba(227, 184, 100, 0.05); }
.nav-list a:hover .idx { text-shadow: 0 0 8px rgba(227, 184, 100, 0.8); }
.nav-text { flex: 1; min-width: 0; }
.nav-title {
  display: block; font-family: var(--serif); font-weight: 400;
  font-size: clamp(1.7rem, 3.6vw, 2.5rem); line-height: 1.1;
  transition: color 200ms ease;
}
.nav-list a:hover .nav-title { color: var(--amber); }
.nav-blurb { display: block; color: var(--ink-dim); margin-top: 0.35rem; }
.nav-arrow {
  color: var(--amber); font-size: 1.3rem; opacity: 0;
  transform: translateX(-6px); transition: opacity 160ms ease, transform 160ms ease;
}
.nav-list a:hover .nav-arrow { opacity: 1; transform: none; }

/* index page: compact section rows — smaller font + shorter height,
   same full-width layout */
[data-page="home"] .nav-list a { padding: 0.95rem 0.5rem; }
[data-page="home"] .nav-title { font-size: clamp(1.15rem, 2.1vw, 1.5rem); }

.idx { font-family: var(--mono); font-size: 0.7rem; color: var(--amber); letter-spacing: 0.1em; }

.lede {
  max-width: var(--measure); color: var(--ink-dim);
  font-size: 1.13rem; line-height: 1.6; margin: 0 0 1.4rem;
}

/* —— stats ———————————————————————————————————————— */

.stats {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(9.5rem, 1fr));
  gap: 0; margin: 1.8rem 0; padding: 0;
  border-block: 1px solid var(--line);
}
.stat { padding: 1.1rem 1.2rem 1.2rem; border-left: 1px solid var(--line-soft); }
.stat:first-child { border-left: none; padding-left: 0.2rem; }
.stat dd {
  margin: 0; font-family: var(--serif); font-size: clamp(1.9rem, 3vw, 2.6rem);
  line-height: 1.1; color: var(--amber);
}
.stat dt {
  font-family: var(--mono); font-size: 0.66rem; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--ink-dim); margin-top: 0.45rem;
}
.stat { display: flex; flex-direction: column-reverse; }

/* —— tags & links ————————————————————————————————— */

.tags { list-style: none; display: flex; flex-wrap: wrap; gap: 0.45rem; padding: 0; margin: 1rem 0 0; }
.tags li {
  font-family: var(--mono); font-size: 0.66rem; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--ink-dim);
  border: 1px solid var(--line); padding: 0.22rem 0.55rem;
}
.proj-links { margin: 1rem 0 0; }
.proj-links a {
  font-family: var(--mono); font-size: 0.74rem; letter-spacing: 0.12em;
  margin-right: 1.2rem; color: var(--teal); text-decoration: none;
}
.proj-links a:hover { color: var(--amber); }

/* —— project / prose pages ———————————————————————— */

.backlink { padding-top: 2.2rem; display: block; }

.proj-head { padding: 1.6rem 0 0.4rem; }
.proj-head h1, .about h1 {
  font-family: var(--serif); font-weight: 400;
  font-size: clamp(2.6rem, 6vw, 4.4rem); line-height: 1.03;
  margin: 0.7rem 0 1rem; letter-spacing: -0.01em;
}

.project .stats { max-width: 52rem; }

.prose { max-width: var(--measure); }
.prose-section { margin: 3.2rem 0; }
.prose-section h2 {
  font-family: var(--serif); font-weight: 400; font-size: 2rem;
  line-height: 1.15; margin: 0 0 1rem;
  display: flex; gap: 0.9rem; align-items: baseline;
}
.prose p { margin: 0 0 1.1rem; }
.prose ul { padding-left: 1.2rem; margin: 0 0 1.1rem; }
.prose li { margin-bottom: 0.55rem; }
.prose li::marker { content: "✶  "; color: var(--amber-dim); font-size: 0.75em; }
.prose strong { font-weight: 560; color: var(--ink); }
.prose em { font-family: var(--serif); letter-spacing: 0.01em; }
.prose code {
  font-family: var(--mono); font-size: 0.84em; font-weight: 400;
  color: var(--teal); background: rgba(143, 208, 198, 0.07);
  padding: 0.08em 0.3em; border-radius: 2px;
}
.prose a { color: var(--amber); }

.about { padding-bottom: 3rem; }
.about h1 { margin-top: 1.4rem; }
.about h2, .cv-section h2 {
  font-family: var(--serif); font-weight: 400; font-size: 1.7rem;
  margin: 2.4rem 0 0.9rem;
}

.contact-list { list-style: none; padding: 0; margin: 0; }
.contact-list li {
  display: flex; gap: 1.4rem; align-items: center;
  padding: 0.6rem 0.2rem; border-bottom: 1px solid var(--line-soft);
}
.contact-list .mono-label { min-width: 7.5rem; }
.contact-list .icon { color: var(--amber-dim); flex: none; }

.icon {
  width: 1.05em; height: 1.05em; fill: currentColor;
  vertical-align: -0.18em; margin-right: 0.45em;
}
.contact-list a { text-decoration: none; }
.contact-list a:hover { color: var(--amber); }

/* —— gallery —————————————————————————————————————— */

.gallery {
  display: grid; gap: 1.2rem; margin: 2rem 0 0.6rem; max-width: 64rem;
  grid-template-columns: repeat(auto-fit, minmax(min(22rem, 100%), 1fr));
}
.gallery figure { margin: 0; }
.gallery a { display: block; border: 1px solid var(--line); }
.gallery a:hover { border-color: var(--amber-dim); }
.gallery img { display: block; width: 100%; height: auto; }
.gallery figcaption {
  font-size: 0.88rem; color: var(--ink-dim); margin-top: 0.5rem;
  line-height: 1.45;
}

/* —— plate viewer (gallery lightbox) ——————————————— */

dialog.plate {
  position: fixed; inset: 0; width: 100%; height: 100%;
  max-width: none; max-height: none; margin: 0; border: 0;
  padding: clamp(1rem, 5vw, 3.5rem);
  background: transparent; color: var(--ink);
  align-items: center; justify-content: center;
}
dialog.plate[open] { display: flex; }
dialog.plate::backdrop {
  background: rgba(6, 7, 13, 0.88);
  backdrop-filter: blur(9px); -webkit-backdrop-filter: blur(9px);
}
body:has(dialog.plate[open]), body.plate-open { overflow: hidden; }

.plate-frame { margin: 0; max-width: min(100%, 68rem); }

.plate-stage { position: relative; border: 1px solid var(--line); background: var(--bg); }
.plate-stage img {
  display: block; max-width: 100%; max-height: min(74vh, 50rem);
  width: auto; height: auto;
  transition: opacity 180ms ease;
}
.plate-stage.is-loading img { opacity: 0; }

/* astrometric fiducial ticks just off the plate corners */
.plate-stage::before, .plate-stage::after,
.plate-ticks::before, .plate-ticks::after {
  content: ""; position: absolute; width: 10px; height: 10px;
  pointer-events: none; border: 0 solid var(--amber-dim);
}
.plate-ticks { position: absolute; inset: 0; pointer-events: none; }
.plate-stage::before { top: -7px; left: -7px; border-top-width: 1px; border-left-width: 1px; }
.plate-stage::after  { bottom: -7px; right: -7px; border-bottom-width: 1px; border-right-width: 1px; }
.plate-ticks::before { top: -7px; right: -7px; border-top-width: 1px; border-right-width: 1px; }
.plate-ticks::after  { bottom: -7px; left: -7px; border-bottom-width: 1px; border-left-width: 1px; }

.plate-meta {
  display: flex; gap: 1.4rem; align-items: baseline;
  padding: 0.75rem 0.1rem 0;
}
.plate-count { color: var(--amber-dim); white-space: nowrap; }
.plate-cap { font-size: 0.92rem; color: var(--ink-dim); line-height: 1.45; }

.plate-btn {
  position: absolute; appearance: none; background: none; cursor: pointer;
  border: 1px solid transparent; color: var(--ink-dim);
  font-family: var(--mono); font-size: 1.05rem; line-height: 1;
  padding: 0.55rem 0.8rem;
  transition: color 160ms ease, border-color 160ms ease;
}
.plate-btn:hover { color: var(--amber); border-color: var(--amber-dim); }
.plate-close { top: 1.1rem; right: 1.3rem; font-size: 0.9rem; }
.plate-prev { left: 0.9rem; top: 50%; translate: 0 -50%; }
.plate-next { right: 0.9rem; top: 50%; translate: 0 -50%; }
dialog.plate.single .plate-prev,
dialog.plate.single .plate-next,
dialog.plate.single .plate-count { display: none; }

@media (max-width: 44rem) {
  dialog.plate { padding: 0.8rem; }
  .plate-prev, .plate-next { background: rgba(6, 7, 13, 0.6); }
  .plate-prev { left: 0.3rem; }
  .plate-next { right: 0.3rem; }
  .plate-meta { flex-direction: column; gap: 0.3rem; }
}

@media (prefers-reduced-motion: no-preference) {
  dialog.plate[open] .plate-frame {
    animation: plate-in 320ms cubic-bezier(0.2, 0.6, 0.2, 1);
  }
  dialog.plate[open]::backdrop { animation: backdrop-in 280ms ease; }
  @keyframes plate-in { from { opacity: 0; transform: translateY(10px) scale(0.985); } }
  @keyframes backdrop-in { from { opacity: 0; } }
}

/* —— cv ——————————————————————————————————————————— */

.cv { padding-bottom: 3rem; }
.cv h1 { font-family: var(--serif); font-weight: 400; font-size: clamp(2.4rem, 5vw, 3.6rem); margin: 1.2rem 0 0.4rem; }
.cv-contact { letter-spacing: 0.08em; }
.cv-contact a { text-decoration: none; }
.cv-contact a:hover { color: var(--amber); }
.cv-section { margin: 2.2rem 0; }

@media print {
  #starfield, .nebula, .grain, .site-head, .site-foot, .no-print { display: none !important; }
  body { background: #fff; color: #111; font-size: 11pt; }
  .cv a { color: #111; text-decoration: none; }
  .cv .mono-label { color: #444; }
  .cv h1, .cv-section h2 { color: #000; }
  .prose strong { color: #000; }
  [data-reveal] { opacity: 1 !important; transform: none !important; animation: none !important; }
}

.notfound { min-height: 50vh; }

/* —— footer ——————————————————————————————————————— */

.site-foot {
  /* the email + social block (~2.5rem tall at line-height 1.6) is centred
     vertically within the dirt band, whose top edge sits --dirt-top above the
     viewport bottom: equal gaps above and below drop it onto the middle of the
     dirt. (clamped at 0 so it never pulls up on very short viewports.) */
  padding: 1.5rem 0 max(0px, calc((var(--dirt-top) - 2.5rem) / 2)); margin-top: 1rem;
  text-align: center; color: var(--ink-dim);
}
.foot-rule {
  color: var(--amber-dim); letter-spacing: 0.6em; font-size: 0.7rem;
  margin-bottom: 1.4rem;
  -webkit-user-select: none; user-select: none;
}
.foot-rule .moon { vertical-align: -2px; margin: 0 0.1em; }
.site-foot p { margin: 0; line-height: 1.6; }
.foot-note { font-size: 0.85rem; color: var(--ink-faint); }
.foot-links { font-family: var(--mono); font-size: 0.78rem; letter-spacing: 0.08em; }
.foot-links a { text-decoration: none; color: var(--ink-dim); }
.foot-links a:hover { color: var(--amber); }
.foot-links span { color: var(--ink-faint); }
.foot-visits {
  margin-top: 0.7rem !important; font-size: 0.66rem; letter-spacing: 0.1em;
  color: var(--ink-faint);
}
.foot-visits .star { color: var(--amber-dim); }
.foot-visits span { color: var(--ink-faint); }
.foot-visits [data-visits-total], .foot-visits [data-visits-unique] { color: var(--ink-dim); }

/* —— page swap (client router) ———————————————————— */

/* Only <main> cross-fades on swap; the sky layers and chrome hold still.
   ::view-transition is a no-op in browsers without the API. */
main { view-transition-name: page-main; }
@media (prefers-reduced-motion: no-preference) {
  ::view-transition-old(page-main) { animation: vt-out 160ms ease both; }
  ::view-transition-new(page-main) { animation: vt-in 240ms ease 60ms both; }
  @keyframes vt-out { to { opacity: 0; } }
  @keyframes vt-in { from { opacity: 0; transform: translateY(6px); } }
}
@media (prefers-reduced-motion: reduce) {
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*) { animation: none !important; }
}

/* —— reveal on load ——————————————————————————————— */

@media (prefers-reduced-motion: no-preference) {
  [data-reveal] {
    opacity: 0; transform: translateY(14px);
    animation: reveal 700ms cubic-bezier(0.2, 0.6, 0.2, 1) forwards;
    animation-delay: calc(var(--i, 0) * 110ms);
  }
  @keyframes reveal { to { opacity: 1; transform: none; } }
}
