/* ===================================================================
   Rex Walrond — personal site
   Design system: alpine mist palette, editorial serif + mono data type,
   elevation-line as the recurring signature device (a trail profile
   reads the same as a performance chart — the visual thread between
   the mountain pages and the quant pages).
   =================================================================== */

@import url('https://fonts.googleapis.com/css2?family=Fraunces:ital,opsz,wght@0,9..144,400..600;1,9..144,400..500&family=Inter:wght@400..600&family=IBM+Plex+Mono:wght@400;500&display=swap');

/* ------------------------------ design tokens ------------------------------ */
/* Two themes off one set of names. Light is the original alpine-mist paper;
   dusk is the same landscape after sundown, not a mechanical inversion — the
   ridges go to silhouette, the sunrise glow becomes moonlight, and the stars
   that are always in the markup finally have somewhere dark to show up.
   Scene colours are tokens too, so the four backgrounds re-theme for free.
   Which sky is showing is decided by where the sun actually is over St.
   Petersburg, Florida — see assets/sky.js. Ten phases, cut on solar altitude
   rather than clock time, so the site tracks the seasons. */

:root {
  color-scheme: light;

  --bg: #eef0ea;
  --paper: #f6f7f2;
  --ink: #1e2b26;
  --ink-soft: #52605a;
  --ink-faint: #8a9791;
  --line: #cdd3c6;
  --blue: #3c5a73;
  --ember: #b5652f;
  --pine: #2f5c4a;
  --gold: #c99a35;

  /* surfaces derived from the palette rather than re-stated per component */
  --panel: rgba(246, 247, 242, 0.72);
  --panel-solid: #f6f7f2;
  --shade: var(--shade);
  --hairline: var(--line);

  /* --- scene: sky and ridges --- */
  --sky-top: #e7ebe4;
  --sky-mid: #eef0ea;
  --sky-low: #f2efe6;
  --ridge-1: color-mix(in srgb, var(--pine) 34%, var(--bg));
  --scrim: rgba(238, 240, 234, 0.74);
  --ridge-2: color-mix(in srgb, var(--blue) 44%, var(--bg));
  --ridge-3: color-mix(in srgb, var(--blue) 64%, var(--bg));
  --ridge-4: color-mix(in srgb, var(--blue) 42%, var(--ink));
  --tree: color-mix(in srgb, var(--ink) 90%, var(--blue));
  --glow-hot: rgba(201, 154, 53, 0.42);
  --glow-mid: rgba(181, 101, 47, 0.16);
  --mist-color: rgba(246, 247, 242, 0.85);
  --star-alpha: 0;
  --celestial: radial-gradient(circle, rgba(255, 244, 222, 0.95) 0%, rgba(240, 206, 140, 0.55) 46%, rgba(240, 206, 140, 0) 70%);
  --celestial-top: 58%;
  --celestial-left: 74%;
  --celestial-size: 13vh;
  --veil: linear-gradient(180deg, var(--bg) 0%, rgba(238, 240, 234, 0.4) 28%, rgba(238, 240, 234, 0.05) 56%, rgba(238, 240, 234, 0.3) 100%);
  --grain-alpha: 0.032;

  /* --- scene: underwater --- */
  --water-hi: #bcd6db;
  --water-lo: #5d8d9c;
  --shaft-color: rgba(255, 255, 255, 0.5);
  --mote-color: rgba(255, 255, 255, 0.72);

  /* --- scene: snow --- */
  --snow-flake: rgba(255, 255, 255, 0.92);

  /* --- map --- */
  --fmap-sea-hi: color-mix(in srgb, var(--blue) 46%, var(--paper));
  --fmap-sea-lo: color-mix(in srgb, var(--blue) 72%, var(--ink));
  --fmap-land: color-mix(in srgb, var(--gold) 9%, var(--paper));
  --fmap-coast: color-mix(in srgb, var(--pine) 90%, var(--bg));
  --fmap-state: color-mix(in srgb, var(--pine) 40%, transparent);
  --fmap-grat: color-mix(in srgb, var(--paper) 17%, transparent);
  --plot-grid: color-mix(in srgb, var(--blue) 13%, transparent);

  --font-display: 'Fraunces', Georgia, serif;
  --font-body: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --font-mono: 'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, monospace;

  --measure: 640px;
}

* { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  background: var(--bg);
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 17px;
  line-height: 1.6;
  min-height: 100vh;
  position: relative;
  transition: background-color 0.5s ease, color 0.5s ease;
}

::selection { background: color-mix(in srgb, var(--ember) 26%, transparent); }

:focus-visible {
  outline: 2px solid var(--ember);
  outline-offset: 3px;
  border-radius: 2px;
}

/* ------------------------- background scene system ------------------------- */
/* Markup is generated by assets/chrome.js from <body data-scene>. Scenes stack
   in the same fixed layer and cross-fade, so a page can change weather without
   a reload — Field Notes swaps alpine / depth / snow with its tabs.
   Every animation in here sits behind prefers-reduced-motion. */

.topo-bg {
  position: fixed;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
  background: linear-gradient(180deg, var(--sky-top) 0%, var(--sky-mid) 46%, var(--sky-low) 100%);
  transition: background 0.6s ease;
}

.scene {
  position: absolute;
  inset: 0;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.72s ease, visibility 0.72s;
}
.scene.is-active { opacity: 1; visibility: visible; }

/* the readability veil and the paper grain sit above every scene */
.topo-bg::after {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--veil);
  z-index: 3;
}

.topo-bg::before {
  content: '';
  position: absolute;
  inset: -20%;
  z-index: 5;
  opacity: var(--grain-alpha);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.82' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='220' height='220' filter='url(%23n)'/%3E%3C/svg%3E");
  mix-blend-mode: overlay;
}

/* ------------------------------ scene: alpine ------------------------------ */

.ridges {
  position: absolute;
  inset: auto 0 0 0;
  height: 50vh;
  min-height: 290px;
  z-index: 2;
}

.ridge-layer,
.treeline {
  position: absolute;
  bottom: -2px;
  left: -2%;
  width: 104%;
  height: 100%;
  will-change: transform;
}

.ridge-layer--1 path { fill: var(--ridge-1); }
.ridge-layer--2 path { fill: var(--ridge-2); }
.ridge-layer--3 path { fill: var(--ridge-3); }
.ridge-layer--4 path { fill: var(--ridge-4); }
.treeline path     { fill: var(--tree); }

/* The treeline rides the nearest ridge, so it shares its parallax depth. */
.treeline { z-index: 1; }

/* The disc is placed by chrome.js from the sun's (or moon's) real azimuth and
   altitude, so it sits where the body actually is in the sky over Florida. The
   left/top custom properties are only the no-JS fallback. */
.celestial {
  position: absolute;
  left: var(--celestial-left, 50%);
  top: var(--celestial-top, 40%);
  width: var(--celestial-size);
  height: var(--celestial-size);
  transform: translate(-50%, -50%);
  background: var(--celestial);
  border-radius: 50%;
  z-index: 1;
  transition: top 1.2s ease, left 1.2s ease, width 1.2s ease, height 1.2s ease,
              opacity 1.2s ease, background 1.2s ease;
}

/* The moon carries its real phase, drawn by chrome.js as two arcs: the outer
   limb and the elliptical terminator. The div keeps its radial gradient as the
   halo; the SVG inside is the disc itself. */
.celestial.is-moon {
  background: radial-gradient(circle, rgba(226, 238, 242, 0.16) 0%, rgba(226, 238, 242, 0) 66%);
  /* Above the atmospheric veil. It cannot get above the reading column's
     scrim — .wrap is a higher stacking context than the whole background — so
     the dark phases keep their scrim light instead. A heavy night scrim turns
     a white lunar disc into grey and the phase stops reading. */
  z-index: 4;
}

.moon-disc {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
}

/* the unlit disc stays faintly visible — earthshine, and it keeps the moon
   from looking like a bite has been taken out of the sky */
.moon-dark {
  fill: color-mix(in srgb, var(--sky-mid) 72%, #cfe0ea);
  opacity: 0.32;
}

.moon-lit {
  fill: #f2f6f6;
  filter: drop-shadow(0 0 2.5px rgba(232, 242, 246, 0.6));
  transition: d 1.2s ease;
}

@media (prefers-reduced-motion: reduce) {
  .celestial, .moon-lit { transition: none; }
}

.glow {
  position: absolute;
  left: 50%;
  bottom: 2vh;
  width: 58vw;
  height: 30vh;
  max-width: 620px;
  max-height: 280px;
  transform: translateX(-50%);
  background: radial-gradient(closest-side, var(--glow-hot), var(--glow-mid) 46%, transparent 74%);
  filter: blur(6px);
  opacity: 0.75;
  z-index: 1;
}

.glow--cold { background: radial-gradient(closest-side, rgba(200, 222, 232, 0.5), rgba(126, 169, 201, 0.14) 48%, transparent 76%); }
.glow--cool { background: radial-gradient(closest-side, var(--glow-mid), transparent 72%); }

.mist {
  position: absolute;
  width: 132%;
  left: -16%;
  height: 24vh;
  border-radius: 50%;
  background: radial-gradient(ellipse at center, var(--mist-color), transparent 72%);
  filter: blur(24px);
  opacity: 0.55;
  z-index: 2;
}

.mist--a { top: 30%; height: 20vh; }
.mist--b { top: 44%; height: 26vh; opacity: 0.45; }
.mist--c { top: 58%; height: 22vh; opacity: 0.5; }

.sky-stars {
  position: absolute;
  inset: 0;
  opacity: var(--star-alpha);
  transition: opacity 0.8s ease;
  z-index: 0;
}

.star {
  position: absolute;
  border-radius: 50%;
  background: #f2f6f4;
  opacity: var(--star-o, 0.5);
}

/* ------------------------------ scene: depth ------------------------------ */
/* A spring cavern rather than open blue water: light enters from above in
   hard-edged shafts, particulate rises through it, walls close at the edges. */

.scene--depth { background: linear-gradient(180deg, var(--water-hi) 0%, var(--water-lo) 78%); }

.caustics {
  position: absolute;
  inset: -10% 0 auto 0;
  height: 46%;
  background:
    repeating-linear-gradient(74deg, transparent 0 18px, var(--shaft-color) 18px 20px, transparent 20px 44px),
    repeating-linear-gradient(-66deg, transparent 0 26px, var(--shaft-color) 26px 27px, transparent 27px 58px);
  opacity: 0.16;
  filter: blur(2px);
}

.shafts { position: absolute; inset: 0; overflow: hidden; }

.shaft {
  position: absolute;
  top: -12%;
  width: var(--shaft-w, 9vw);
  height: 96%;
  transform-origin: top center;
  transform: rotate(var(--shaft-r, 0deg));
  background: linear-gradient(180deg, var(--shaft-color), transparent 76%);
  filter: blur(10px);
  opacity: 0.6;
}

.motes { position: absolute; inset: 0; overflow: hidden; }

.mote {
  position: absolute;
  border-radius: 50%;
  background: var(--mote-color);
  opacity: 0.55;
}

.cavern-walls {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(ellipse 42% 100% at -6% 50%, color-mix(in srgb, var(--water-lo) 85%, #000) 0%, transparent 70%),
    radial-gradient(ellipse 42% 100% at 106% 50%, color-mix(in srgb, var(--water-lo) 85%, #000) 0%, transparent 70%),
    radial-gradient(ellipse 120% 44% at 50% 118%, color-mix(in srgb, var(--water-lo) 92%, #000) 0%, transparent 72%);
  opacity: 0.75;
}

/* ------------------------------- scene: snow ------------------------------- */

.scene--snow { background: linear-gradient(180deg, color-mix(in srgb, var(--blue) 12%, var(--sky-top)) 0%, var(--sky-low) 72%); }

.ridges--snow .ridge-layer--1 path { fill: color-mix(in srgb, var(--blue) 26%, var(--bg)); }
.ridges--snow .ridge-layer--2 path { fill: color-mix(in srgb, var(--blue) 42%, var(--bg)); }
.ridges--snow .ridge-layer--3 path { fill: color-mix(in srgb, var(--ink) 62%, var(--blue)); }

.snowfall { position: absolute; inset: 0; overflow: hidden; z-index: 3; }

.flake {
  position: absolute;
  top: -6%;
  border-radius: 50%;
  background: var(--snow-flake);
  opacity: 0.8;
}

/* ------------------------------- scene: plot ------------------------------- */
/* The ridge, redrawn as a chart. Same line, different reading. */

.plot-grid {
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(to right, var(--plot-grid) 1px, transparent 1px),
    linear-gradient(to bottom, var(--plot-grid) 1px, transparent 1px);
  background-size: 74px 74px;
  opacity: 0.55;
  mask-image: linear-gradient(180deg, transparent, #000 22%, #000 72%, transparent);
}

.ridges--plot .ridge-layer--2 path { fill: color-mix(in srgb, var(--blue) 18%, transparent); }

.plot-line {
  position: absolute;
  bottom: -2px;
  left: -2%;
  width: 104%;
  height: 100%;
}
.plot-line path {
  fill: none;
  stroke: color-mix(in srgb, var(--blue) 70%, var(--ink));
  stroke-width: 2;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
  opacity: 0.5;
}

/* ------------------------------- scene motion ------------------------------- */
/* Parallax reads two custom properties set by chrome.js on <body>:
   --parallax-x / --parallax-y (pointer, fine pointers only) and --scroll-y
   (0 at the top of the page, 1 at the bottom). Far layers barely move, near
   layers move most — the ridges hold still while the page slides over them. */

@media (prefers-reduced-motion: no-preference) {
  .glow { animation: glow-breathe 9s ease-in-out infinite; }
  .mist--a { animation: drift-a 64s ease-in-out infinite alternate; }
  .mist--b { animation: drift-b 84s ease-in-out infinite alternate; }
  .mist--c { animation: drift-c 100s ease-in-out infinite alternate; }
  .star { animation: twinkle 6s ease-in-out infinite; }
  .shaft { animation: shaft-sway 17s ease-in-out infinite alternate; }
  .mote { animation: mote-rise linear infinite; }
  .flake { animation: flake-fall linear infinite; }
  .caustics { animation: caustic-slide 26s linear infinite; }

  .ridge-layer,
  .treeline,
  .plot-line {
    transition: transform 0.28s ease-out;
  }

  .ridge-layer--1 { transform: translate3d(calc(var(--parallax-x, 0) * 3px),  calc(var(--parallax-y, 0) * 2px  + var(--scroll-y, 0) * -14px), 0); }
  .ridge-layer--2 { transform: translate3d(calc(var(--parallax-x, 0) * 7px),  calc(var(--parallax-y, 0) * 4px  + var(--scroll-y, 0) * -30px), 0); }
  .ridge-layer--3 { transform: translate3d(calc(var(--parallax-x, 0) * 13px), calc(var(--parallax-y, 0) * 6px  + var(--scroll-y, 0) * -52px), 0); }
  .ridge-layer--4,
  .treeline       { transform: translate3d(calc(var(--parallax-x, 0) * 20px), calc(var(--parallax-y, 0) * 9px  + var(--scroll-y, 0) * -80px), 0); }

  .celestial { transform: translate(-50%, calc(-50% + var(--scroll-y, 0) * 34px)); }
  .sky-stars { transform: translateY(calc(var(--scroll-y, 0) * 18px)); }
}

@keyframes glow-breathe {
  0%, 100% { opacity: 0.52; }
  50%      { opacity: 0.86; }
}
@keyframes drift-a { from { transform: translateX(-4%); } to { transform: translateX(4%); } }
@keyframes drift-b { from { transform: translateX(3%); }  to { transform: translateX(-5%); } }
@keyframes drift-c { from { transform: translateX(-3%); } to { transform: translateX(6%); } }

@keyframes twinkle {
  0%, 100% { opacity: calc(var(--star-o, 0.5) * 0.45); }
  50%      { opacity: var(--star-o, 0.5); }
}
@keyframes shaft-sway {
  from { transform: rotate(var(--shaft-r, 0deg)); opacity: 0.4; }
  to   { transform: rotate(calc(var(--shaft-r, 0deg) + 5deg)); opacity: 0.72; }
}
@keyframes mote-rise {
  from { transform: translateY(0) translateX(0); opacity: 0; }
  12%  { opacity: 0.6; }
  88%  { opacity: 0.5; }
  to   { transform: translateY(-130vh) translateX(16px); opacity: 0; }
}
@keyframes flake-fall {
  from { transform: translate3d(0, -10vh, 0); opacity: 0; }
  10%  { opacity: 0.85; }
  90%  { opacity: 0.7; }
  to   { transform: translate3d(var(--drift, 20px), 112vh, 0); opacity: 0; }
}
@keyframes caustic-slide {
  from { background-position: 0 0, 0 0; }
  to   { background-position: 220px 0, -180px 0; }
}

@media (max-width: 640px) {
  .ridges { height: 48vh; min-height: 240px; }
  .glow { width: 86vw; height: 30vh; }
  .celestial { --celestial-size: 11vh; }
}

/* ------------------------------- theme toggle ------------------------------- */

.theme-toggle {
  position: fixed;
  right: 18px;
  top: 18px;
  z-index: 40;
  width: 38px;
  height: 38px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 50%;
  background: var(--panel);
  backdrop-filter: blur(9px);
  -webkit-backdrop-filter: blur(9px);
  color: var(--ink-soft);
  cursor: pointer;
  transition: color 0.2s ease, border-color 0.2s ease, transform 0.2s ease, background 0.3s ease;
}
.theme-toggle:hover {
  color: var(--ember);
  border-color: color-mix(in srgb, var(--ember) 48%, var(--line));
  transform: translateY(-1px);
}
.theme-toggle svg { width: 17px; height: 17px; fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; }

/* system → sun with rays; light → bare sun; dusk → moon */
/* auto → sun with rays (the sky is running); day → bare sun; night → moon */
.theme-toggle .t-moon { display: none; }
.theme-toggle[data-mode="day"] .t-rays { opacity: 0.32; }
.theme-toggle[data-mode="night"] .t-sun,
.theme-toggle[data-mode="night"] .t-rays { display: none; }
.theme-toggle[data-mode="night"] .t-moon { display: block; }

/* On a phone the toggle stops being fixed and scrolls away with the header.
   A 34px disc pinned to the corner of a 390px screen lands on whatever is
   right-aligned further down the page — the unit on a chart, the rating on a
   coverage row — and covers it. There is nowhere on a narrow screen it can
   float without hitting something, so it rides the page instead. */
@media (max-width: 640px) {
  .theme-toggle { position: absolute; right: 12px; top: 12px; width: 36px; height: 36px; }
}

/* ---------------------------- reveal-on-scroll ---------------------------- */
/* Shared with assets/reveal.js. Elements start offset+transparent and settle
   into place when they cross into view; instant and fully visible for
   anyone with prefers-reduced-motion set. */

@media (prefers-reduced-motion: no-preference) {
  [data-reveal] {
    opacity: 0;
    transform: translateY(16px);
    transition: opacity 0.7s cubic-bezier(.2,.6,.2,1), transform 0.7s cubic-bezier(.2,.6,.2,1);
  }
  [data-reveal].is-visible {
    opacity: 1;
    transform: none;
  }
  [data-reveal-group] > [data-reveal]:nth-child(1) { transition-delay: 0.02s; }
  [data-reveal-group] > [data-reveal]:nth-child(2) { transition-delay: 0.08s; }
  [data-reveal-group] > [data-reveal]:nth-child(3) { transition-delay: 0.14s; }
  [data-reveal-group] > [data-reveal]:nth-child(4) { transition-delay: 0.2s; }
  [data-reveal-group] > [data-reveal]:nth-child(5) { transition-delay: 0.26s; }
  [data-reveal-group] > [data-reveal]:nth-child(n+6) { transition-delay: 0.3s; }
}

/* -------------------------------- layout -------------------------------- */

/* The reading column carries its own scrim rather than the background being
   flattened everywhere. Art stays at full strength out in the margins, where
   there is nothing to read; text sits on a quiet band that tracks the column
   at any viewport width. */
.wrap::before {
  content: '';
  position: absolute;
  top: -4vh;
  bottom: -4vh;
  /* Reach 13vw past the column for a soft edge, but never past the viewport:
     an absolutely positioned box still counts toward scrollable overflow, and
     once the column is as wide as the screen the overhang becomes a sideways
     scrollbar on every page. calc(-50vw + 50%) is exactly the viewport edge. */
  left: max(-13vw, calc(-50vw + 50%));
  right: max(-13vw, calc(-50vw + 50%));
  z-index: -1;
  pointer-events: none;
  background: linear-gradient(90deg, transparent 0%, var(--scrim) 26%, var(--scrim) 74%, transparent 100%);
  -webkit-mask-image: linear-gradient(180deg, transparent 0, #000 3%, #000 97%, transparent 100%);
  mask-image: linear-gradient(180deg, transparent 0, #000 3%, #000 97%, transparent 100%);
}

.wrap {
  position: relative;
  z-index: 1;
  max-width: var(--measure);
  margin: 0 auto;
  padding: 12vh 28px 14vh;
}

@media (max-width: 640px) {
  .wrap { padding: 14vw 22px 16vw; }

  /* The fade is a percentage of the scrim's own width, so on a phone the
     26% ramp ate 100px of a 390px screen at each end and the text nearest
     the margins sat on bare background — legible over sky, not over the
     hub's treeline. Narrow the ramp; the column needs the cover more than
     it needs the soft edge. */
  .wrap::before {
    background: linear-gradient(90deg, transparent 0%, var(--scrim) 7%, var(--scrim) 93%, transparent 100%);
  }
}

.eyebrow {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin: 0 0 18px;
}

h1.name {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(44px, 8vw, 68px);
  line-height: 1.02;
  letter-spacing: -0.022em;
  margin: 0 0 10px;
  color: var(--ink);
  /* display optical size: tighter apertures and finer hairlines than the text
     cut, which is what Fraunces gives you at 144 and not at its default */
  font-variation-settings: 'opsz' 144;
}

.name-accent {
  width: 64px;
  height: 3px;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--gold), var(--ember));
  margin: 2px 0 22px;
  transform-origin: left center;
}

@media (prefers-reduced-motion: no-preference) {
  .name-accent {
    transform: scaleX(0);
    animation: accent-draw 0.7s cubic-bezier(.4,0,.2,1) 0.5s forwards;
  }
}

@keyframes accent-draw {
  to { transform: scaleX(1); }
}

p.tagline {
  font-family: var(--font-body);
  font-size: 16px;
  color: var(--ink-soft);
  margin: 0 0 46px;
}

section.bio p {
  max-width: 54ch;
  color: var(--ink);
  margin: 0 0 14px;
}

section.bio a { color: var(--blue); }

/* -------------------------- elevation divider -------------------------- */

.elevation {
  margin: 48px 0 46px;
}

.elevation svg { width: 100%; height: auto; display: block; }

.elevation path.line {
  fill: none;
  stroke: var(--ember);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  filter: drop-shadow(0 0 5px color-mix(in srgb, var(--gold) 50%, transparent));
}

.elevation path.fill {
  fill: var(--gold);
  opacity: 0.1;
}

@media (prefers-reduced-motion: no-preference) {
  .elevation path.line {
    stroke-dasharray: 1400;
    stroke-dashoffset: 1400;
    animation: draw 1.6s cubic-bezier(.4,0,.2,1) 0.15s forwards;
  }
}

@keyframes draw {
  to { stroke-dashoffset: 0; }
}

.elevation-cap {
  display: flex;
  justify-content: space-between;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  color: var(--ink-faint);
  margin-top: 6px;
}

/* --------------------------------- links --------------------------------- */

nav.links {
  display: flex;
  flex-direction: column;
  border-top: 1px solid var(--line);
}

a.link-row {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 20px 0 20px 16px;
  margin-left: -16px;
  border-bottom: 1px solid var(--line);
  text-decoration: none;
  color: inherit;
  transition: padding-left 0.25s cubic-bezier(.2,.7,.3,1);
}

a.link-row::before {
  content: '';
  position: absolute;
  left: 0;
  top: 8px;
  bottom: 8px;
  width: 3px;
  border-radius: 2px;
  background: var(--gold);
  transform: scaleY(0);
  transform-origin: bottom;
  transition: transform 0.3s cubic-bezier(.2,.7,.3,1);
}

a.link-row:hover,
a.link-row:focus-visible {
  padding-left: 24px;
}

a.link-row:hover::before,
a.link-row:focus-visible::before {
  transform: scaleY(1);
}

@media (prefers-reduced-motion: reduce) {
  a.link-row, a.link-row::before { transition: none; }
}

a.link-row:focus-visible {
  outline: 2px solid var(--blue);
  outline-offset: 4px;
}

.link-title {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 20px;
  letter-spacing: -0.006em;
  color: var(--ink);
  font-variation-settings: 'opsz' 40;
}

a.link-row:hover .link-title,
a.link-row:focus-visible .link-title {
  color: var(--ember);
}

.link-desc {
  font-size: 14.5px;
  color: var(--ink-soft);
  max-width: 52ch;
}

.link-meta {
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-top: 2px;
}

/* -------------------------------- footer -------------------------------- */

footer {
  margin-top: 56px;
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--ink-soft);
  display: flex;
  gap: 10px;
  align-items: center;
}

footer a { color: var(--ink); text-decoration: none; border-bottom: 1px solid var(--line); }
footer a:hover { color: var(--ember); border-color: var(--ember); }
footer .dot { color: var(--ink-faint); }

/* ---------------------------- sub-page shell ---------------------------- */

.back-link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-soft);
  text-decoration: none;
  margin-bottom: 40px;
}
.back-link:hover { color: var(--ember); }

@media (max-width: 640px) {
  /* 12px of mono is a 19px-tall tap target; give it the padding to clear 40. */
  .back-link { padding: 11px 2px; margin: -11px 0 30px; }
}

.page-head h1 {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(34px, 6.5vw, 52px);
  letter-spacing: -0.01em;
  margin: 0 0 8px;
  font-variation-settings: 'opsz' 144;
  letter-spacing: -0.018em;
}

.page-head p {
  color: var(--ink-soft);
  max-width: 54ch;
  margin: 0 0 40px;
}

.status-tag {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--blue);
  border: 1px solid var(--blue);
  border-radius: 3px;
  padding: 4px 8px;
  margin-bottom: 22px;
}

.stub-body {
  border-top: 1px solid var(--line);
  padding-top: 28px;
  color: var(--ink-soft);
  max-width: 56ch;
}

.stub-body ul {
  padding-left: 18px;
  margin: 16px 0 0;
}

.stub-body li {
  margin-bottom: 8px;
}

/* =====================================================================
   Field Notes — mountain / dive split
   Two visual identities sharing one page: alpine (ember, contour rings,
   paper grain) and dive (blue, depth-gauge rings, rising bubbles). A
   toggle with a sliding thumb swaps which is active; both panels live in
   the same grid cell so the crossfade never jumps the layout.
   ===================================================================== */

.trip-toggle {
  position: relative;
  display: inline-flex;
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 3px;
  margin: 4px 0 40px;
  background: var(--paper);
}

/* Width and offset are set by JS from the active button — the three labels
   are different lengths, so equal-thirds math would misalign the thumb. */
.trip-toggle-thumb {
  position: absolute;
  top: 3px;
  left: 3px;
  width: 0;
  height: calc(100% - 6px);
  border-radius: 999px;
  background: var(--ink);
  transition: transform 0.45s cubic-bezier(.65,0,.35,1),
              width 0.45s cubic-bezier(.65,0,.35,1),
              background 0.45s ease;
  z-index: 0;
}

.trip-toggle[data-scene="dive"] .trip-toggle-thumb { background: var(--blue); }
.trip-toggle[data-scene="ski"] .trip-toggle-thumb { background: var(--pine); }

.trip-toggle-btn {
  position: relative;
  z-index: 1;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-soft);
  background: transparent;
  border: none;
  border-radius: 999px;
  padding: 10px 22px;
  cursor: pointer;
  transition: color 0.3s ease;
  min-width: 130px;
}

.trip-toggle-btn.is-active { color: var(--paper); }

@media (prefers-reduced-motion: no-preference) {
  .trip-toggle-btn { transition: color 0.45s cubic-bezier(.65,0,.35,1); }
}

.trip-stage {
  position: relative;
  display: grid;
}

.trip-stage-bg {
  position: absolute;
  top: -32px;
  bottom: -32px;
  /* The 24px bleed is clamped to the viewport for the same reason the column
     scrim is: it overhangs, and an overhang past the screen edge is a
     horizontal scrollbar on narrow phones. */
  left: max(-24px, calc(-50vw + 50%));
  right: max(-24px, calc(-50vw + 50%));
  border-radius: 10px;
  z-index: -1;
  background: radial-gradient(120% 100% at 15% 0%, color-mix(in srgb, var(--ember) 11%, transparent), transparent 60%),
              linear-gradient(180deg, color-mix(in srgb, var(--ember) 6%, transparent), transparent 70%);
  transition: background 0.7s ease;
}

.trip-stage[data-scene="dive"] .trip-stage-bg {
  background: radial-gradient(120% 100% at 85% 0%, color-mix(in srgb, var(--blue) 16%, transparent), transparent 60%),
              linear-gradient(180deg, color-mix(in srgb, var(--blue) 9%, transparent), transparent 70%);
}

.trip-stage[data-scene="ski"] .trip-stage-bg {
  background: radial-gradient(120% 100% at 50% 0%, color-mix(in srgb, var(--pine) 15%, transparent), transparent 62%),
              linear-gradient(180deg, color-mix(in srgb, var(--pine) 8%, transparent), transparent 70%);
}

.trip-panel {
  grid-row: 1;
  grid-column: 1;
  position: relative;
  opacity: 1;
  transform: none;
  transition: opacity 0.5s ease, transform 0.5s ease;
}

/* Three panels share one grid cell. Only the active scene is visible and
   interactive; the other two sit hidden underneath it. */
.trip-panel--dive,
.trip-panel--ski { opacity: 0; transform: translateY(10px); pointer-events: none; }

.trip-stage[data-scene="dive"] .trip-panel--mountain,
.trip-stage[data-scene="ski"] .trip-panel--mountain { opacity: 0; transform: translateY(-10px); pointer-events: none; }

.trip-stage[data-scene="ski"] .trip-panel--dive { opacity: 0; transform: translateY(-10px); pointer-events: none; }
.trip-stage[data-scene="dive"] .trip-panel--ski { opacity: 0; transform: translateY(10px); pointer-events: none; }

.trip-stage[data-scene="dive"] .trip-panel--dive,
.trip-stage[data-scene="ski"] .trip-panel--ski { opacity: 1; transform: none; pointer-events: auto; }

.trip-panel--mountain { pointer-events: auto; }

@media (prefers-reduced-motion: reduce) {
  .trip-toggle-thumb, .trip-toggle-btn, .trip-stage-bg, .trip-panel { transition: none; }
}

/* motif corner marks */

.trip-motif {
  position: absolute;
  top: -34px;
  right: 0;
  width: 64px;
  height: 64px;
  opacity: 0.55;
  pointer-events: none;
  z-index: -1;
}

.trip-motif .m-line { fill: none; stroke: var(--ember); stroke-width: 1; }
.trip-panel--dive .trip-motif .m-line { stroke: var(--blue); }
.trip-panel--ski .trip-motif .m-line { stroke: var(--pine); }

.bubble {
  position: absolute;
  border-radius: 50%;
  background: color-mix(in srgb, var(--blue) 30%, transparent);
  bottom: 6%;
}

@media (prefers-reduced-motion: no-preference) {
  .bubble { animation: bubble-rise linear infinite; }
}

@keyframes bubble-rise {
  0% { transform: translateY(0) translateX(0); opacity: 0; }
  10% { opacity: 0.65; }
  90% { opacity: 0.35; }
  100% { transform: translateY(-320px) translateX(6px); opacity: 0; }
}

/* ski: the dive panel's ambient particles, inverted — falling instead of
   rising, and drifting sideways on the way down */
.flake {
  position: absolute;
  top: 0;
  border-radius: 50%;
  background: color-mix(in srgb, var(--pine) 32%, transparent);
  pointer-events: none;
}

@media (prefers-reduced-motion: no-preference) {
  .flake { animation: flake-fall linear infinite; }
}

@keyframes flake-fall {
  0% { transform: translateY(-20px) translateX(0); opacity: 0; }
  12% { opacity: 0.6; }
  88% { opacity: 0.32; }
  100% { transform: translateY(340px) translateX(-14px); opacity: 0; }
}

.trip-section-label {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin: 0 0 18px;
}

.trip-panel--dive .trip-section-label { color: var(--blue); }

.trip-cards {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.trip-card {
  padding: 24px 0;
  border-top: 1px solid var(--line);
}

.trip-card:last-child { border-bottom: 1px solid var(--line); }

.trip-card-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}

.trip-card-head h3 {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 22px;
  margin: 0;
  color: var(--ink);
}

.trip-tag {
  flex: 0 0 auto;
  font-family: var(--font-mono);
  font-size: 9.5px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
  border: 1px solid var(--line);
  border-radius: 2px;
  padding: 2px 6px;
  white-space: nowrap;
}

.trip-tag--summited {
  background: var(--gold);
  border-color: var(--gold);
  color: var(--ink);
  font-weight: 600;
}

.trip-card {
  transition: transform 0.25s ease, box-shadow 0.25s ease;
}

.trip-card:hover {
  transform: translateY(-3px);
  box-shadow: 0 14px 28px -20px var(--shadow);
}

@media (prefers-reduced-motion: reduce) {
  .trip-card { transition: none; }
  .trip-card:hover { transform: none; }
}

.trip-loc {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--ink-faint);
  margin: 4px 0 14px;
}

.trip-stats {
  display: flex;
  flex-wrap: wrap;
  gap: 22px;
  margin-bottom: 14px;
}

.trip-stats span {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.trip-stats strong {
  font-family: var(--font-mono);
  font-size: 15px;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  font-weight: 500;
}

.trip-panel--dive .trip-stats strong { color: var(--blue); }

.trip-stats small {
  font-family: var(--font-mono);
  font-size: 9.5px;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.trip-blurb {
  max-width: 56ch;
  color: var(--ink-soft);
  margin: 0 0 10px;
}

.trip-conditions {
  font-family: var(--font-mono);
  font-size: 11.5px;
  color: var(--ink-faint);
}

/* ---------------------------- dive site lists ---------------------------- */
/* Two groups (logged / wishlist) as compact hairline rows rather than full
   cards — there are no per-dive stats yet, so a list reads honestly where a
   card would look like it's withholding something. */

.site-group { margin-bottom: 40px; }
.site-group:last-of-type { margin-bottom: 0; }

.site-group-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 14px;
  border-bottom: 1px solid var(--ink);
  padding-bottom: 8px;
  margin-bottom: 2px;
}

.site-group-head h3 {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 21px;
  margin: 0;
  color: var(--ink);
}

.site-count {
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
  white-space: nowrap;
}

.site-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.site-row {
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr) auto;
  gap: 14px;
  align-items: baseline;
  padding: 13px 6px;
  margin: 0 -6px;
  border-bottom: 1px solid var(--line);
  transition: background 0.18s ease, padding-left 0.18s ease;
}

.site-row:hover {
  background: var(--shade);
  padding-left: 12px;
}

.trip-panel--dive .site-row:hover { background: color-mix(in srgb, var(--blue) 7%, transparent); }
.trip-panel--ski .site-row:hover { background: color-mix(in srgb, var(--pine) 7%, transparent); }

@media (prefers-reduced-motion: reduce) {
  .site-row { transition: none; }
  .site-row:hover { padding-left: 6px; }
}

.site-name {
  font-weight: 600;
  font-size: 15.5px;
  color: var(--ink);
}

.site-loc {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--ink-soft);
}

.site-type {
  font-family: var(--font-mono);
  font-size: 9.5px;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--ink-soft);
  border: 1px solid var(--line);
  border-radius: 2px;
  padding: 3px 7px;
  white-space: nowrap;
  justify-self: end;
}

/* the accent follows the panel, so the shared list reads as part of
   whichever scene it's in */
.trip-panel--dive .site-type { color: var(--blue); }
.trip-panel--ski .site-type { color: var(--pine); }

/* The wishlist reads as intent, not record. Distinguish it by weight and a
   hollow marker rather than by fading the text — these rows scroll over the
   darker ridge art, where low-contrast type stops being legible. */
.site-group--wish .site-name {
  font-weight: 500;
  color: var(--ink);
  position: relative;
  padding-left: 16px;
}

.site-group--wish .site-name::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.45em;
  width: 7px;
  height: 7px;
  border: 1px solid var(--ember);
  border-radius: 50%;
}

/* the marker follows the panel's accent, same as the type badge */
.trip-panel--dive .site-group--wish .site-name::before { border-color: var(--blue); }
.trip-panel--ski .site-group--wish .site-name::before { border-color: var(--pine); }

.site-group--wish .site-type { color: var(--ink-soft); }

.site-note {
  font-family: var(--font-mono);
  font-size: 10.5px;
  color: var(--ink-soft);
  line-height: 1.7;
  max-width: 58ch;
  margin: 16px 0 0;
}

@media (max-width: 640px) {
  .site-row {
    grid-template-columns: 1fr auto;
    row-gap: 4px;
  }
  .site-name { grid-column: 1; }
  .site-type { grid-column: 2; grid-row: 1; }
  .site-loc { grid-column: 1 / -1; }
}

.trip-note {
  margin-top: 28px;
  font-family: var(--font-mono);
  font-size: 10.5px;
  color: var(--ink-soft);
  line-height: 1.7;
  max-width: 56ch;
}

@media (max-width: 640px) {
  .trip-motif { display: none; }
  .trip-stats { gap: 16px; }

  /* three fixed-width pills overflow the content column on phones, so let
     the toggle fill the width and split into equal thirds instead */
  .trip-toggle { display: flex; width: 100%; }
  .trip-toggle-btn {
    flex: 1 1 0;
    min-width: 0;
    padding: 13px 4px;
    font-size: 11.5px;
    letter-spacing: 0.02em;
  }
}

/* =====================================================================
   The Work — analyst coverage sheet
   A screener-style list (ticker / sector / rating / thesis / trend) that
   expands in place on click via the 0fr->1fr grid-template-rows trick —
   no JS height measuring needed. Personal quant projects reuse the same
   card language as Field Notes but with backtest-flavored stats.
   ===================================================================== */

.cov-disclaimer {
  font-family: var(--font-mono);
  font-size: 10.5px;
  color: var(--ink-faint);
  border: 1px solid var(--line);
  border-radius: 4px;
  padding: 10px 14px;
  margin: 0 0 34px;
  line-height: 1.6;
  max-width: 60ch;
}

.cov-section-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 6px;
}

.cov-section-head h2 {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 24px;
  margin: 0;
}

.cov-meta {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--ink-faint);
  white-space: nowrap;
}

.cov-col-head {
  display: grid;
  grid-template-columns: 64px 1fr 122px minmax(0,1.6fr) 64px 18px;
  gap: 14px;
  align-items: center;
  padding: 20px 10px 8px;
  margin-top: 10px;
  border-top: 1px solid var(--ink);
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.cov-list { display: flex; flex-direction: column; }

.cov-row { border-bottom: 1px solid var(--line); border-left: 3px solid transparent; transition: border-color 0.25s ease; }

.cov-row:hover, .cov-row.is-open { border-left-color: var(--gold); }

.cov-row-summary {
  width: 100%;
  display: grid;
  grid-template-columns: 64px 1fr 122px minmax(0,1.6fr) 64px 18px;
  gap: 14px;
  align-items: center;
  padding: 14px 10px 14px 13px;
  margin: 0;
  background: transparent;
  border: none;
  cursor: pointer;
  text-align: left;
  font-family: var(--font-body);
  transition: background 0.15s ease;
}

.cov-row-summary:hover { background: var(--shade); }

@media (prefers-reduced-motion: reduce) {
  .cov-row { transition: none; }
}

.cov-ticker {
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: 13.5px;
  color: var(--ink);
}

.cov-sector {
  font-size: 13.5px;
  color: var(--ink-soft);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.cov-rating {
  justify-self: start;
  font-family: var(--font-mono);
  font-size: 9.5px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-faint);
  border: 1px solid var(--line);
  border-radius: 2px;
  padding: 3px 7px;
  white-space: nowrap;
}

.cov-rating--buy { color: var(--ember); border-color: var(--ember); }
.cov-rating--watch { color: var(--blue); border-color: var(--blue); }

.cov-thesis-snip {
  font-size: 12.5px;
  color: var(--ink-faint);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.cov-spark { width: 64px; height: 24px; display: block; }
.cov-spark path {
  fill: none;
  stroke: var(--ember);
  stroke-width: 1.4;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.cov-rating--watch ~ .cov-spark path,
.cov-row-summary:has(.cov-rating--watch) .cov-spark path { stroke: var(--blue); }

@media (prefers-reduced-motion: no-preference) {
  .cov-spark path {
    stroke-dasharray: 200;
    stroke-dashoffset: 200;
    animation: draw 1.2s cubic-bezier(.4,0,.2,1) forwards;
    animation-play-state: paused;
  }
  [data-reveal].is-visible .cov-spark path { animation-play-state: running; }
}

.cov-chevron {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--ink-faint);
  transition: transform 0.3s ease;
  justify-self: end;
}

.cov-row.is-open .cov-chevron { transform: rotate(180deg); }

.cov-detail {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 0.4s cubic-bezier(.4,0,.2,1);
}

.cov-row.is-open .cov-detail { grid-template-rows: 1fr; }

.cov-detail-inner { overflow: hidden; }

.cov-detail-body {
  padding: 4px 10px 22px;
  max-width: 64ch;
}

.cov-detail-body p { color: var(--ink-soft); margin: 0 0 14px; }

.cov-detail-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 28px;
}

.cov-detail-grid strong {
  display: block;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-bottom: 4px;
}

.cov-detail-grid span { font-size: 13px; color: var(--ink); }

@media (prefers-reduced-motion: reduce) {
  .cov-chevron, .cov-detail { transition: none; }
}

/* personal quant project cards — reuses trip-card rhythm */

.qp-cards {
  display: flex;
  flex-direction: column;
}

.qp-card {
  padding: 22px 0;
  border-top: 1px solid var(--line);
  transition: transform 0.25s ease, box-shadow 0.25s ease;
}

.qp-card:hover {
  transform: translateY(-3px);
  box-shadow: 0 14px 28px -20px var(--shadow);
}

@media (prefers-reduced-motion: reduce) {
  .qp-card { transition: none; }
  .qp-card:hover { transform: none; }
}

.qp-card:last-child { border-bottom: 1px solid var(--line); }

.qp-card-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}

.qp-card-head h3 {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 19px;
  margin: 0;
  color: var(--ink);
}

.qp-stats {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
  margin: 10px 0 10px;
}

.qp-stats span { display: flex; flex-direction: column; gap: 2px; }
.qp-stats strong {
  font-family: var(--font-mono);
  font-size: 14px;
  color: var(--blue);
  font-variant-numeric: tabular-nums;
}
.qp-stats small {
  font-family: var(--font-mono);
  font-size: 9.5px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.qp-card p.qp-blurb { color: var(--ink-soft); max-width: 58ch; margin: 0; }

@media (max-width: 640px) {
  .cov-col-head { display: none; }
  .cov-row-summary {
    grid-template-columns: 1fr auto;
    grid-template-areas: "ticker rating" "sector rating" "spark chevron";
    row-gap: 6px;
  }
  .cov-ticker { grid-area: ticker; }
  .cov-sector { grid-area: sector; white-space: normal; }
  .cov-rating { grid-area: rating; }
  .cov-thesis-snip { display: none; }
  .cov-spark { grid-area: spark; }
  .cov-chevron { grid-area: chevron; }
}

/* =====================================================================
   The Log — instrument panel / lab notebook
   A cluster of dial gauges (conic-gradient rings animated via a
   registered custom property) standing in for a sensor readout, plus a
   dated notebook list below. Sample data throughout — the page is
   explicit that it's waiting on a real backend.
   ===================================================================== */

/* ---------------------- The Log: range bar + charts ---------------------- */

.range-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 16px;
  margin: 4px 0 34px;
}

.range-seg {
  display: inline-flex;
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 2px;
  gap: 2px;
  background: var(--paper);
}

.range-btn {
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--ink-soft);
  background: transparent;
  border: none;
  border-radius: 999px;
  padding: 7px 15px;
  cursor: pointer;
  transition: background 0.2s ease, color 0.2s ease;
}

.range-btn:hover { color: var(--ink); }
.range-btn.is-active { background: var(--ink); color: var(--paper); }

@media (prefers-reduced-motion: reduce) {
  .range-btn { transition: none; }
}

.range-meta {
  font-family: var(--font-mono);
  font-size: 10.5px;
  color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
}

.log-section { margin-bottom: 8px; }

.chart-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 26px 30px;
  margin-top: 22px;
}

.chart-card {
  margin: 0;
  border-top: 1px solid var(--line);
  padding-top: 12px;
}

.chart-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 6px;
}

.chart-title {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 14.5px;
  color: var(--ink);
}

.chart-unit {
  font-family: var(--font-mono);
  font-size: 9.5px;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.chart {
  width: 100%;
  height: 118px;
  display: block;
  overflow: visible;
}

.chart-area { opacity: 0.12; stroke: none; }

.chart-line {
  fill: none;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}

/* the mean, so each series is readable against its own baseline */
.chart-avg {
  stroke: var(--ink-faint);
  stroke-width: 1;
  stroke-dasharray: 3 4;
  opacity: 0.5;
  vector-effect: non-scaling-stroke;
}

.chart-dot { stroke: var(--paper); stroke-width: 1.5; }

.sleep-pending {
  border: 1px dashed var(--line);
  border-radius: 6px;
  padding: 18px 20px;
  margin: 22px 0 0;
  color: var(--ink-soft);
  font-size: 14.5px;
  max-width: 62ch;
}

.chart-empty {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--ink-faint);
  padding: 42px 0;
  text-align: center;
  margin: 0;
}

.chart-stats {
  display: flex;
  flex-wrap: wrap;
  gap: 14px 18px;
  margin-top: 10px;
  padding-top: 9px;
  border-top: 1px solid var(--line);
}

.chart-stats span { display: flex; flex-direction: column; gap: 1px; }

.chart-stats strong {
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 500;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}

.chart-stats small {
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

@media (max-width: 640px) {
  .chart-grid { grid-template-columns: 1fr; gap: 22px; }
  .range-bar { gap: 8px; }
  .range-btn { padding: 11px 14px; font-size: 11px; }
  .chart { height: 104px; }
  .chart-stats { gap: 10px 14px; }
}

@property --pct {
  syntax: '<number>';
  inherits: true;
  initial-value: 0;
}

.gauge-rack {
  display: flex;
  flex-wrap: wrap;
  gap: 34px;
  margin: 8px 0 10px;
}

.gauge {
  --pct: 0;
  --gauge-color: var(--ember);
  width: 116px;
  height: 116px;
  border-radius: 50%;
  background: conic-gradient(var(--gauge-color) calc(var(--pct) * 1%), var(--line) 0);
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
  flex: 0 0 auto;
}

@media (prefers-reduced-motion: no-preference) {
  .gauge { transition: --pct 1.2s cubic-bezier(.4,0,.2,1); }
}

.gauge::before {
  content: '';
  position: absolute;
  inset: 11px;
  border-radius: 50%;
  background: var(--paper);
  box-shadow: inset 0 0 0 1px var(--line);
}

.gauge-readout {
  position: relative;
  z-index: 1;
  text-align: center;
}

.gauge-value {
  display: block;
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: 19px;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}

.gauge-unit {
  display: block;
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-top: 2px;
}

.gauge-label {
  text-align: center;
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin-top: 10px;
}

.gauge-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.log-list {
  border-top: 1px solid var(--line);
  margin-top: 8px;
}

.log-entry {
  display: flex;
  gap: 20px;
  padding: 18px 0;
  border-bottom: 1px solid var(--line);
}

.log-date {
  flex: 0 0 58px;
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--ink-faint);
  padding-top: 2px;
  white-space: nowrap;
}

.log-body { flex: 1 1 auto; min-width: 0; }

.log-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 8px;
}

.log-tag {
  font-family: var(--font-mono);
  font-size: 9.5px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-faint);
  border: 1px solid var(--line);
  border-radius: 2px;
  padding: 2px 6px;
}

.log-tag--training { color: var(--ember); border-color: var(--ember); }
.log-tag--nutrition { color: var(--blue); border-color: var(--blue); }

.log-note { color: var(--ink-soft); max-width: 56ch; margin: 0; }

@media (max-width: 640px) {
  .gauge-rack { display: grid; grid-template-columns: repeat(2, 1fr); justify-items: center; gap: 28px 8px; }
  .gauge { width: 108px; height: 108px; }
  .gauge-value { font-size: 17px; }
  .log-entry { gap: 14px; }
  .log-date { flex-basis: 46px; font-size: 11px; }
}

/* ====================== On Repeat: primary tab bar ====================== */
/* Two top-level sections. Deliberately an underline/ink-bar treatment
   rather than another pill, so it reads as a level above the pill
   toggles nested inside each pane. */

.tabbar {
  position: relative;
  display: flex;
  gap: 34px;
  border-bottom: 1px solid var(--line);
  margin: 6px 0 0;
}

.tabbar-btn {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 4px;
  align-items: flex-start;
  background: none;
  border: none;
  padding: 4px 0 16px;
  cursor: pointer;
  text-align: left;
  color: var(--ink-faint);
  transition: color 0.25s ease;
}

.tabbar-btn:hover { color: var(--ink-soft); }
.tabbar-btn.is-active { color: var(--ink); }

.tabbar-btn:focus-visible {
  outline: 2px solid var(--blue);
  outline-offset: 3px;
  border-radius: 2px;
}

.tabbar-label {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(19px, 2.6vw, 24px);
  line-height: 1.1;
  color: inherit;
}

.tabbar-meta {
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
}

/* sliding ink bar; JS sets --ink-x / --ink-w from the active button */
.tabbar-ink {
  position: absolute;
  left: 0;
  bottom: -1px;
  height: 2px;
  border-radius: 2px;
  background: var(--ember);
  transform: translateX(var(--ink-x, 0));
  width: var(--ink-w, 0);
  transition: transform 0.42s cubic-bezier(.65,0,.35,1), width 0.42s cubic-bezier(.65,0,.35,1);
}

.tabbar[data-tab="listening"] .tabbar-ink { background: var(--blue); }

.tabpane { animation: tab-in 0.4s cubic-bezier(.2,.7,.3,1); }

@keyframes tab-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .tabbar-ink, .tabbar-btn { transition: none; }
  .tabpane { animation: none; }
}

@media (max-width: 640px) {
  .tabbar { gap: 20px; }
  .tabbar-label { font-size: 17px; }
  .tabbar-meta { font-size: 10.5px; letter-spacing: 0.04em; }
}

/* ==================== On Repeat: listening snapshot ==================== */
/* A hairline stat strip under the page head — real counts pulled from the
   Spotify export, not decoration. Tabular numerals so the row reads as data. */

.listen-strip {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 34px;
  padding: 20px 0 22px;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  margin: 4px 0 0;
}

.listen-stat { display: flex; flex-direction: column; gap: 3px; }

.listen-stat strong {
  font-family: var(--font-mono);
  font-size: 21px;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  line-height: 1;
}

.listen-stat small {
  font-family: var(--font-mono);
  font-size: 9.5px;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.listen-stat--accent strong { color: var(--ember); }

.listen-window {
  flex: 1 1 100%;
  font-family: var(--font-mono);
  font-size: 10.5px;
  color: var(--ink-faint);
  margin: 4px 0 0;
}

@media (max-width: 640px) {
  .listen-strip { gap: 20px 26px; }
  .listen-stat strong { font-size: 18px; }
}

/* ==================== On Repeat: top-artists list ==================== */
/* The minutes bar is a real proportion of the top entry, so row length
   encodes listening time at a glance. */

.rota-lede {
  color: var(--ink-soft);
  max-width: 60ch;
  margin: 10px 0 22px;
}

.rota-list {
  list-style: none;
  margin: 0;
  padding: 0;
  border-top: 1px solid var(--ink);
}

.rota-row {
  position: relative;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 12px 8px;
  margin: 0 -8px;
  border-bottom: 1px solid var(--line);
  overflow: hidden;
}

/* proportional listening-time bar behind the row content */
.rota-bar {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  background: linear-gradient(90deg, color-mix(in srgb, var(--ember) 18%, transparent), color-mix(in srgb, var(--gold) 8%, transparent));
  width: 0;
  z-index: 0;
  transition: width 0.9s cubic-bezier(.2,.7,.3,1);
}


@media (prefers-reduced-motion: reduce) {
  .rota-bar { transition: none; }
}

.rota-rank {
  position: relative;
  z-index: 1;
  flex: 0 0 26px;
  font-family: var(--font-mono);
  font-size: 12.5px;
  font-variant-numeric: tabular-nums;
  color: var(--ink-faint);
  text-align: center;
}

.rota-row--top .rota-rank {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 17px;
  color: var(--ember);
}


.rota-art {
  position: relative;
  z-index: 1;
  flex: 0 0 44px;
  width: 44px;
  height: 44px;
  border-radius: 4px;
  object-fit: cover;
  display: block;
  background: var(--line);
}

.rota-art--artist { border-radius: 50%; }

.rota-art--fallback {
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-display);
  font-size: 16px;
  color: var(--ink-faint);
  background: var(--paper);
  border: 1px solid var(--line);
}

.rota-info {
  position: relative;
  z-index: 1;
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.rota-name {
  display: block;
  font-weight: 600;
  font-size: 15px;
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.rota-sub {
  display: block;
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--ink-faint);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.rota-metric {
  position: relative;
  z-index: 1;
  flex: 0 0 auto;
  text-align: right;
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
}

.rota-metric strong {
  display: block;
  font-size: 14px;
  font-weight: 500;
  color: var(--ink);
}

.rota-metric small {
  font-size: 9.5px;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

@media (max-width: 640px) {
  .rota-art { flex-basis: 38px; width: 38px; height: 38px; }
  .rota-name { font-size: 14px; }
  .rota-row { gap: 11px; }
}

/* -------------------- On Repeat: open-plains mood -------------------- */
/* Same ridge/mist/glow system, tuned for this page only: flatter horizon
   instead of peaks (open space over dramatic terrain), a cooler dusk
   glow instead of warm sunrise, slower drift. Structure and every
   rank-* class below is untouched — mood is a background swap, not a
   rebuild. */

body.mood-repeat .ridge-layer--1 { fill: color-mix(in srgb, var(--ink) 10%, var(--bg)); }
body.mood-repeat .ridge-layer--2 { fill: color-mix(in srgb, var(--ink) 16%, var(--bg)); }
body.mood-repeat .ridge-layer--3 { fill: color-mix(in srgb, var(--ink) 26%, var(--bg)); }

body.mood-repeat .glow {
  background: radial-gradient(closest-side, color-mix(in srgb, var(--blue) 24%, transparent), transparent 72%);
  width: 78vw;
  height: 30vh;
}

@media (prefers-reduced-motion: no-preference) {
  body.mood-repeat .glow { animation-duration: 13s; }
  body.mood-repeat .mist--a { animation-duration: 90s; }
  body.mood-repeat .mist--b { animation-duration: 120s; }
  body.mood-repeat .mist--c { animation-duration: 150s; }
}

/* =====================================================================
   On Repeat — ranked coverage list
   Treated like an analyst's ranking sheet: tabular numerals, a hairline
   column header, a live "current pick" callout that echoes a top-pick
   note, and reorder motion that actually shows the list resettling.
   ===================================================================== */

.wrap--wide {
  max-width: 840px;
}

.rank-section {
  border-top: 1px solid var(--line);
  padding-top: 26px;
  margin-top: 40px;
}

.rank-section:first-of-type {
  margin-top: 0;
}

/* inside a tab pane the tab label is already the heading, so the section
   sheds its own top rule and title */
.rank-section--flush {
  border-top: none;
  padding-top: 0;
  margin-top: 0;
}

.rank-section-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 6px;
}

.rank-section-head h2 {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 25px;
  margin: 0;
  color: var(--ink);
}

.rank-meta-count {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  color: var(--ink-faint);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

/* ------------------------------ pick hero ------------------------------ */

.pick-hero {
  display: flex;
  align-items: center;
  gap: 22px;
  margin: 26px 0 46px;
  padding: 34px 0 36px;
  border-top: 1px solid var(--ink);
  border-bottom: 1px solid var(--line);
}

.pick-art-wrap {
  flex: 0 0 auto;
  width: 88px;
  height: 88px;
  border-radius: 8px;
  overflow: hidden;
  background: var(--line);
  box-shadow: 0 10px 24px -14px var(--shadow-strong);
}

.pick-art {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: opacity 0.22s ease;
}

.pick-text { min-width: 0; flex: 1 1 auto; }

@media (max-width: 640px) {
  .pick-hero { gap: 16px; }
  .pick-art-wrap { width: 64px; height: 64px; border-radius: 6px; }
}

.pick-eyebrow {
  display: block;
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ember);
  margin-bottom: 10px;
}

.pick-name {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(30px, 5.4vw, 46px);
  line-height: 1.16;
  letter-spacing: -0.005em;
  color: var(--ink);
  margin: 0 0 10px;
  transition: opacity 0.22s ease;
}

.pick-meta {
  font-family: var(--font-mono);
  font-size: 12.5px;
  color: var(--ink-soft);
  transition: opacity 0.22s ease;
}

.pick-swap { opacity: 0; }

@media (prefers-reduced-motion: reduce) {
  .pick-name, .pick-meta { transition: none; }
}

/* -------------------------------- controls -------------------------------- */

.rank-controls-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 16px;
  margin: 22px 0 4px;
}

.rank-search {
  flex: 1 1 180px;
  min-width: 140px;
  font-family: var(--font-body);
  font-size: 14px;
  color: var(--ink);
  background: transparent;
  border: none;
  border-bottom: 1px solid var(--line);
  padding: 7px 2px;
  outline: none;
  transition: border-color 0.15s ease;
}

.rank-search::placeholder { color: var(--ink-faint); }
.rank-search:focus { border-color: var(--ember); }

.rank-seg {
  display: inline-flex;
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 2px;
  gap: 2px;
}

.rank-seg button {
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--ink-soft);
  background: transparent;
  border: none;
  border-radius: 999px;
  padding: 5px 12px;
  cursor: pointer;
  transition: background 0.18s ease, color 0.18s ease;
}

.rank-seg button:hover { color: var(--ink); }

.rank-seg button.is-active {
  background: var(--ink);
  color: var(--paper);
}

.rank-actions {
  display: flex;
  gap: 14px;
  margin-left: auto;
}

.rank-text-btn {
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-soft);
  background: transparent;
  border: none;
  padding: 4px 0;
  cursor: pointer;
  border-bottom: 1px solid var(--line);
}

.rank-text-btn:hover { color: var(--ember); border-color: var(--ember); }

.rank-filter-note {
  font-family: var(--font-mono);
  font-size: 10.5px;
  color: var(--ink-faint);
  margin: 10px 0 0;
  min-height: 14px;
}

/* ------------------------------ column head ------------------------------ */

.rank-col-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0 0 8px;
  margin-top: 20px;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.ch-handle { flex: 0 0 16px; }
.ch-rank { flex: 0 0 30px; text-align: center; }
.ch-art { flex: 0 0 40px; }
.ch-track { flex: 1 1 auto; }
.ch-dur { flex: 0 0 40px; text-align: right; }
.ch-move { flex: 0 0 22px; }

/* ---------------------------------- list ---------------------------------- */

.rank-list {
  border-top: 1px solid var(--ink);
}

.rank-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 6px;
  margin: 0 -6px;
  border-bottom: 1px solid var(--line);
  background: transparent;
  border-radius: 4px;
  transition: background 0.15s ease;
}

.rank-row:hover {
  background: var(--shade);
}

.rank-row.is-hidden { display: none; }

.rank-row.is-dragging { opacity: 0.35; }

.rank-row.is-drop-target {
  box-shadow: inset 0 2px 0 var(--ember);
}

.rank-row--top {
  background: color-mix(in srgb, var(--ember) 7%, transparent);
}

.rank-row--top:hover {
  background: color-mix(in srgb, var(--ember) 11%, transparent);
}

.rank-handle {
  flex: 0 0 16px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--ink-faint);
  background: none;
  border: none;
  cursor: grab;
  padding: 4px 0;
  line-height: 0;
  opacity: 0.55;
  transition: opacity 0.15s ease, color 0.15s ease;
}

.rank-row:hover .rank-handle { opacity: 1; }
.rank-handle:hover { color: var(--ink-soft); }
.rank-handle:active { cursor: grabbing; }

.rank-num {
  flex: 0 0 30px;
  font-family: var(--font-mono);
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  text-align: center;
  color: var(--ink-faint);
  background: transparent;
  border: 1px solid transparent;
  border-radius: 3px;
  padding: 3px 0;
  -moz-appearance: textfield;
}

.rank-num::-webkit-outer-spin-button,
.rank-num::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

.rank-num:focus {
  outline: none;
  border-color: var(--line);
  background: var(--paper);
  color: var(--ink);
}

.rank-row--top .rank-num {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 17px;
  color: var(--ember);
  border: none;
}

.rank-art {
  flex: 0 0 40px;
  width: 40px;
  height: 40px;
  border-radius: 4px;
  object-fit: cover;
  display: block;
  background: var(--line);
}

.rank-art--fallback {
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 15px;
  color: var(--ink-faint);
  background: var(--paper);
  border: 1px solid var(--line);
}

.rank-info {
  flex: 1 1 auto;
  min-width: 0;
}

.rank-name {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 14.5px;
  color: var(--ink);
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
}

.rank-row--top .rank-name { font-size: 15.5px; }

.rank-tag {
  font-family: var(--font-mono);
  font-size: 9.5px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 1px 5px;
  border-radius: 2px;
  border: 1px solid var(--line);
  color: var(--ink-faint);
  font-weight: 400;
}

.rank-tag--live { color: var(--blue); border-color: var(--blue); }

.rank-sub {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--ink-faint);
  margin-top: 2px;
}

.rank-dur {
  flex: 0 0 40px;
  font-family: var(--font-mono);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  color: var(--ink-faint);
  text-align: right;
}

.rank-move {
  flex: 0 0 22px;
  display: flex;
  flex-direction: column;
  opacity: 0.5;
  transition: opacity 0.15s ease;
}

.rank-row:hover .rank-move { opacity: 1; }

.rank-move button {
  background: none;
  border: none;
  color: var(--ink-faint);
  cursor: pointer;
  font-size: 9px;
  line-height: 1;
  padding: 2px 3px;
}

.rank-move button:hover { color: var(--ember); }
.rank-move button:disabled { opacity: 0.25; cursor: default; }
.rank-move button:disabled:hover { color: var(--ink-faint); }

.rank-del {
  flex: 0 0 auto;
  background: none;
  border: none;
  color: var(--ink-faint);
  cursor: pointer;
  font-size: 14px;
  padding: 2px 4px;
  opacity: 0.5;
}

.rank-row:hover .rank-del { opacity: 1; }
.rank-del:hover { color: var(--ember); }

.rank-empty {
  padding: 24px 0;
  color: var(--ink-faint);
  font-size: 14px;
  text-align: center;
}

/* ------------------------------- add-track form ------------------------------- */

.rank-add {
  margin-top: 22px;
}

.rank-add summary {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-soft);
  cursor: pointer;
  list-style: none;
}

.rank-add summary::-webkit-details-marker { display: none; }
.rank-add summary:hover { color: var(--ember); }
.rank-add summary::before { content: '+ '; color: var(--ember); }
.rank-add[open] summary::before { content: '– '; }

.rank-add-form {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 12px;
}

.rank-add-form input {
  flex: 1 1 160px;
  font-family: var(--font-body);
  font-size: 13.5px;
  color: var(--ink);
  background: transparent;
  border: none;
  border-bottom: 1px solid var(--line);
  padding: 6px 2px;
  outline: none;
}

.rank-add-form input:focus { border-color: var(--ember); }

.rank-add-form button {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--blue);
  background: transparent;
  border: 1px solid var(--blue);
  border-radius: 3px;
  padding: 6px 12px;
  cursor: pointer;
}

.rank-add-form button:hover { background: var(--blue); color: var(--paper); }

/* ---------------------------------- auth ---------------------------------- */

.rank-auth {
  margin: 14px 0 0;
  padding: 14px 16px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--paper);
}

.rank-auth-form {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

.rank-auth-form input {
  flex: 1 1 200px;
  font-family: var(--font-body);
  font-size: 13.5px;
  color: var(--ink);
  background: transparent;
  border: none;
  border-bottom: 1px solid var(--line);
  padding: 6px 2px;
  outline: none;
}

.rank-auth-form input:focus { border-color: var(--gold); }

.rank-auth-form button {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--gold);
  background: transparent;
  border: 1px solid var(--gold);
  border-radius: 3px;
  padding: 6px 12px;
  cursor: pointer;
}

.rank-auth-form button:hover { background: var(--gold); color: var(--ink); }

.rank-auth-note {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--ink-faint);
  margin: 10px 0 0;
}

.rank-auth-note.is-editor { color: var(--pine); font-weight: 600; }

/* --------------------------------- export --------------------------------- */

.rank-export {
  width: 100%;
  font-family: var(--font-mono);
  font-size: 11.5px;
  color: var(--ink-soft);
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: 4px;
  padding: 12px;
  margin-top: 12px;
  resize: vertical;
  min-height: 120px;
}

.rank-storage-note {
  font-family: var(--font-mono);
  font-size: 10.5px;
  color: var(--ink-faint);
  line-height: 1.7;
  margin-top: 20px;
  max-width: 54ch;
}

/* --------------------------- small elevation divider --------------------------- */

.elevation--sm { margin: 44px 0; }
.elevation--sm svg { height: 44px; }

@media (max-width: 640px) {
  .rank-handle { display: none; }
  .rank-dur { display: none; }
  .rank-col-head { display: none; }
  .rank-actions { margin-left: 0; }
  .rank-controls-bar { row-gap: 12px; }
  .rank-move { opacity: 1; }
  .rank-del { opacity: 1; }

  /* Dragging is off on touch, so these arrows are the only way to reorder a
     track on a phone — and they were 22x13. Give each one a proper target and
     let the pair span the row. */
  .rank-move { flex: 0 0 38px; justify-content: center; gap: 2px; }
  .rank-move button { font-size: 12px; padding: 10px 0; width: 38px; }

  .rank-seg button { font-size: 11px; padding: 10px 14px; }
  .rank-text-btn { font-size: 11px; padding: 10px 0; }
  .rank-search { font-size: 16px; padding-block: 10px; }
  .rank-num { font-size: 14px; min-height: 34px; }
}

/* ------------------------- Field Notes: the map ------------------------- */
/* Built by assets/map.js from assets/places.js + assets/geo.js. Everything
   here is palette tokens, so the map re-themes with the rest of the site. */

/* The map breaks out of the reading column: it's the single place this page
   spends its visual boldness, and 584px is not enough to read a map in. */
.map-section {
  /* Negative margin rather than a transform: a transform moves the box
     visually but leaves its layout width where it was, which pushed the
     document wider than the viewport and gave every page a sideways scroll. */
  --bleed: min(1140px, calc(100vw - 52px));
  width: var(--bleed);
  margin: 0 0 44px calc(50% - var(--bleed) / 2);
}

@media (max-width: 640px) {
  .map-section { --bleed: calc(100vw - 16px); margin-bottom: 34px; }
}

.map-intro {
  margin: 0 0 20px;
  color: var(--ink-soft);
  font-size: 15.5px;
  max-width: 58ch;
}

.fmap-bar {
  display: flex;
  flex-wrap: wrap;
  gap: 12px 18px;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 14px;
}

.fmap-chips,
.fmap-views { display: flex; flex-wrap: wrap; gap: 7px; }

.fmap-chip,
.fmap-view {
  font-family: var(--font-mono);
  font-size: 11.5px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 6px 12px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--panel);
  color: var(--ink-faint);
  cursor: pointer;
  transition: color 0.18s ease, border-color 0.18s ease, background 0.18s ease;
}

.fmap-chip:hover,
.fmap-view:hover { color: var(--ink); border-color: color-mix(in srgb, var(--ink) 30%, var(--line)); }

.fmap-chip.is-active {
  color: var(--paper);
  background: var(--ink);
  border-color: var(--ink);
}

.fmap-view.is-active {
  color: var(--ember);
  border-color: color-mix(in srgb, var(--ember) 55%, var(--line));
  background: color-mix(in srgb, var(--ember) 9%, transparent);
}

/* the wishlist toggle reads as a switch, not a filter — hollow when off */
.fmap-chip--wish { display: inline-flex; align-items: center; gap: 7px; }
.fmap-chip--wish.is-active { background: var(--panel); color: var(--ink); border-color: var(--line); }
.fmap-chip-dot {
  width: 9px; height: 9px;
  border-radius: 50%;
  border: 1.5px solid var(--ember);
  background: transparent;
  transition: background 0.18s ease, opacity 0.18s ease;
}
.fmap-chip--wish:not(.is-active) { opacity: 0.55; }
.fmap-chip--wish:not(.is-active) .fmap-chip-dot { border-color: var(--ink-faint); }

/* ------------------------------- the canvas ------------------------------- */

.fmap-stage {
  position: relative;
  border: 1px solid var(--line);
  border-radius: 3px;
  overflow: hidden;
  background: var(--fmap-sea-lo);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--paper) 22%, transparent),
              inset 0 22px 44px -26px rgba(0, 0, 0, 0.5);
}

.fmap-stage::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(ellipse 92% 90% at 50% 46%, transparent 62%, rgba(0, 0, 0, 0.13) 100%);
}

.fmap-svg { display: block; width: 100%; height: auto; }

.fmap-grat {
  fill: none;
  stroke: var(--fmap-grat);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
}

.fmap-land {
  fill: var(--fmap-land);
  stroke: var(--fmap-coast);
  stroke-width: 1;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}

/* State lines only appear once the frame is tight enough for them to mean
   something — at world scale they're noise. */
.fmap-states {
  fill: none;
  stroke: var(--fmap-state);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
  opacity: 0;
  transition: opacity 0.45s ease;
  pointer-events: none;
}
.fmap-geo.show-states .fmap-states { opacity: 1; }

/* -------------------------------- markers -------------------------------- */

.fmap-pin { cursor: pointer; }
.fmap-hit { fill: transparent; }

.fmap-glyph {
  fill: var(--pine);
  stroke: var(--paper);
  stroke-width: 1.7;
  paint-order: stroke fill;
  stroke-linejoin: round;
  transition: fill 0.2s ease, transform 0.2s ease;
  transform-box: fill-box;
  transform-origin: center;
}

.fmap-pin--dive .fmap-glyph { fill: var(--blue); }
.fmap-pin--ski  .fmap-glyph { fill: var(--gold); }

/* on the list: hollow, in ember, so ambition reads differently from record */
.fmap-pin.is-wish .fmap-glyph {
  fill: color-mix(in srgb, var(--fmap-land) 55%, var(--ember));
  stroke: var(--ember);
  stroke-width: 2.1;
}

.fmap-halo {
  fill: none;
  stroke: var(--gold);
  stroke-width: 1.6;
  opacity: 0.85;
}

.fmap-pin.is-offscreen { opacity: 0.16; pointer-events: none; }

.fmap-pin:hover .fmap-glyph,
.fmap-pin.is-hot .fmap-glyph { transform: scale(1.32); }

.fmap-pin.is-selected .fmap-glyph {
  transform: scale(1.42);
  stroke: var(--ember);
  stroke-width: 2;
}
.fmap-pin.is-selected.is-wish .fmap-glyph { stroke-width: 2.6; }

.fmap-pin:focus { outline: none; }
.fmap-pin:focus-visible .fmap-glyph {
  stroke: var(--ember);
  stroke-width: 2.4;
  transform: scale(1.42);
}

@media (prefers-reduced-motion: reduce) {
  .fmap-glyph, .fmap-states { transition: none; }
}

/* -------------------------------- tooltip -------------------------------- */

.fmap-tip {
  position: absolute;
  transform: translate(-50%, calc(-100% - 15px));
  pointer-events: none;
  padding: 7px 11px;
  border: 1px solid var(--line);
  border-radius: 3px;
  background: var(--panel-solid);
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.14);
  white-space: nowrap;
  z-index: 3;
  display: grid;
  gap: 1px;
}
.fmap-tip[hidden] { display: none; }
.fmap-tip.is-low { transform: translate(-50%, 15px); }
.fmap-tip strong { font-size: 13.5px; font-weight: 600; }
.fmap-tip span { font-family: var(--font-mono); font-size: 10.5px; color: var(--ink-faint); }
.fmap-tip-wish { color: var(--ember) !important; letter-spacing: 0.06em; text-transform: uppercase; }

/* ------------------------------- readout card ------------------------------- */

.fmap-card {
  margin-top: 16px;
  padding: 16px 18px;
  border: 1px solid var(--line);
  border-left: 2px solid var(--line);
  border-radius: 3px;
  background: var(--panel);
  transition: border-color 0.3s ease;
}
.fmap-card--backcountry.is-open { border-left-color: var(--pine); }
.fmap-card--dive.is-open        { border-left-color: var(--blue); }
.fmap-card--ski.is-open         { border-left-color: var(--gold); }

.fmap-summary {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 12.5px;
  color: var(--ink);
}
.fmap-hint { margin: 5px 0 0; font-size: 14px; color: var(--ink-faint); }

.fmap-card-kind {
  margin: 0 0 4px;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.fmap-card h3 {
  margin: 0 0 3px;
  font-family: var(--font-display);
  font-size: 21px;
  font-weight: 500;
  line-height: 1.25;
}
.fmap-card-where { margin: 0 0 12px; font-size: 14.5px; color: var(--ink-soft); }

.fmap-card-stats { display: flex; flex-wrap: wrap; gap: 22px; margin-bottom: 12px; }
.fmap-card-stats span { display: grid; }
.fmap-card-stats strong { font-family: var(--font-mono); font-size: 15px; font-weight: 500; }
.fmap-card-stats small {
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.fmap-card-note { margin: 0 0 12px; font-size: 15px; color: var(--ink-soft); }

.fmap-card-coord {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 11.5px;
  color: var(--ink-faint);
  letter-spacing: 0.05em;
}

.fmap-card-jump {
  margin-top: 12px;
  padding: 0;
  border: 0;
  background: none;
  font-family: var(--font-mono);
  font-size: 11.5px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ember);
  cursor: pointer;
  border-bottom: 1px solid color-mix(in srgb, var(--ember) 40%, transparent);
  transition: border-color 0.2s ease;
}
.fmap-card-jump:hover { border-bottom-color: var(--ember); }

/* -------------------------------- legend -------------------------------- */

.fmap-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 20px;
  margin: 12px 0 0;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.fmap-legend span { display: inline-flex; align-items: center; gap: 6px; }
.fmap-legend svg { width: 13px; height: 13px; overflow: visible; }
.fmap-legend span:nth-child(1) svg * { fill: var(--pine); }
.fmap-legend span:nth-child(2) svg * { fill: var(--blue); }
.fmap-legend span:nth-child(3) svg * { fill: var(--gold); }
.fmap-legend .is-wish svg * {
  fill: none;
  stroke: var(--ember);
  stroke-width: 2.4;
}

/* The entry a marker sent you to gets flagged briefly so you land on it
   rather than somewhere near it. */
.is-flagged {
  animation: flag-entry 2.2s ease-out;
}
@keyframes flag-entry {
  0%, 62%  { background: color-mix(in srgb, var(--ember) 13%, transparent); }
  100%     { background: transparent; }
}
@media (prefers-reduced-motion: reduce) {
  .is-flagged { animation: none; outline: 2px solid var(--ember); outline-offset: 4px; }
}

@media (max-width: 640px) {
  .fmap-bar { gap: 10px 12px; }
  /* These were shrunk for the narrow column and came out 24px tall, which is
     a hard thing to hit with a thumb and a hard thing to read at 10.5px.
     Touch wants them bigger than the desktop version, not smaller. */
  .fmap-chip, .fmap-view {
    font-size: 11.5px;
    padding: 10px 14px;
    letter-spacing: 0.06em;
  }
  .fmap-card-stats { gap: 16px; }
  .fmap-legend { gap: 8px 14px; font-size: 10.5px; }
  .fmap-tip { display: none; }
}

/* Displacement leaders: when the separation pass moves a pin off its true
   position, a hairline shows where it actually sits. */
.fmap-leader {
  stroke: var(--ink-faint);
  stroke-width: 1;
  opacity: 0;
  vector-effect: non-scaling-stroke;
  transition: opacity 0.25s ease;
}
.fmap-anchor { fill: var(--ink-faint); opacity: 0; transition: opacity 0.25s ease; }
.fmap-pin.is-shifted .fmap-leader { opacity: 0.4; }
.fmap-pin.is-shifted .fmap-anchor { opacity: 0.55; }
.fmap-pin.is-shifted:hover .fmap-leader,
.fmap-pin.is-shifted.is-hot .fmap-leader,
.fmap-pin.is-shifted.is-selected .fmap-leader { opacity: 0.9; stroke: var(--ember); }
.fmap-pin.is-shifted.is-selected .fmap-anchor { opacity: 1; fill: var(--ember); }
.fmap-pin-body { transition: transform 0.3s cubic-bezier(.2,.7,.3,1); }

@media (prefers-reduced-motion: reduce) {
  .fmap-pin-body, .fmap-leader, .fmap-anchor { transition: none; }
}

/* Clusters: what a group of places collapses into when the frame is too wide
   to give each one its own spot. Activating one flies in until they resolve. */

.fmap-cluster { cursor: pointer; }

.fmap-cluster-disc {
  fill: color-mix(in srgb, var(--pine) 78%, var(--paper));
  stroke: var(--paper);
  stroke-width: 1.6;
  transition: transform 0.2s ease, fill 0.2s ease;
  transform-box: fill-box;
  transform-origin: center;
}
.fmap-cluster--dive  .fmap-cluster-disc { fill: color-mix(in srgb, var(--blue) 80%, var(--paper)); }
.fmap-cluster--ski   .fmap-cluster-disc { fill: color-mix(in srgb, var(--gold) 82%, var(--ink)); }
.fmap-cluster--mixed .fmap-cluster-disc { fill: color-mix(in srgb, var(--ink) 70%, var(--paper)); }
.fmap-cluster.is-wish .fmap-cluster-disc {
  fill: color-mix(in srgb, var(--fmap-land) 48%, var(--ember));
  stroke: var(--ember);
}

.fmap-cluster-ring {
  fill: none;
  stroke: currentColor;
  stroke-width: 1;
  color: var(--paper);
  opacity: 0.4;
  transition: opacity 0.2s ease, stroke-width 0.2s ease;
}

.fmap-cluster-n {
  text-anchor: middle;
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 600;
  fill: var(--paper);
  pointer-events: none;
}
.fmap-cluster--ski .fmap-cluster-n { fill: var(--ink); }
.fmap-cluster.is-wish .fmap-cluster-n { fill: var(--ember); }

.fmap-cluster:hover .fmap-cluster-disc,
.fmap-cluster:focus-visible .fmap-cluster-disc { transform: scale(1.12); }
.fmap-cluster:hover .fmap-cluster-ring,
.fmap-cluster:focus-visible .fmap-cluster-ring { opacity: 0.95; stroke-width: 1.6; color: var(--ember); }
.fmap-cluster:focus { outline: none; }

@media (prefers-reduced-motion: reduce) {
  .fmap-cluster-disc, .fmap-cluster-ring { transition: none; }
}

/* Zoom / reset cluster, bottom-right of the plate. */
.fmap-zoom {
  position: absolute;
  right: 10px;
  bottom: 10px;
  display: grid;
  gap: 5px;
  z-index: 2;
}

.fmap-zoom-btn {
  width: 30px;
  height: 30px;
  display: grid;
  place-items: center;
  padding: 0;
  font-family: var(--font-mono);
  font-size: 15px;
  line-height: 1;
  border: 1px solid color-mix(in srgb, var(--paper) 34%, transparent);
  border-radius: 3px;
  background: color-mix(in srgb, var(--fmap-sea-lo) 78%, var(--ink));
  color: var(--paper);
  cursor: pointer;
  transition: background 0.18s ease, color 0.18s ease, border-color 0.18s ease, opacity 0.18s ease;
}
.fmap-zoom-btn--reset { font-size: 13px; }

.fmap-zoom-btn:hover:not(:disabled) {
  background: var(--ember);
  border-color: var(--ember);
}
.fmap-zoom-btn:disabled { opacity: 0.32; cursor: default; }

/* The canvas is draggable, so say so with the cursor. */
.fmap-stage { cursor: grab; touch-action: pan-y; }
.fmap-stage.is-panning { cursor: grabbing; }
.fmap-stage.is-panning .fmap-pin,
.fmap-stage.is-panning .fmap-cluster { cursor: grabbing; }

/* Mid-drag, the per-marker easing fights the pan and everything smears. */
.fmap-stage.is-panning .fmap-pin-body { transition: none; }

@media (max-width: 640px) {
  /* Stacked, these were 132px of a 256px plate and sat over Africa with two
     markers behind them. In a row along the bottom edge they stay thumb-sized
     and cover a strip of sea instead. */
  .fmap-zoom {
    right: 8px;
    bottom: 8px;
    grid-auto-flow: column;
    gap: 7px;
  }
  .fmap-zoom-btn { width: 38px; height: 38px; font-size: 17px; }
}

/* ------------------------------ hub: intro ------------------------------ */

.intro {
  margin: 20px 0 0;
  max-width: 50ch;
  font-size: 16.5px;
  line-height: 1.68;
  color: var(--ink-soft);
  text-wrap: pretty;
}

/* --------------------- hub: live figures on each row --------------------- */
/* Each row reports a real number from its own page's data. The hub describes
   the site rather than just linking to it. */

.link-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 18px;
}

.link-stat {
  display: flex;
  align-items: baseline;
  gap: 12px;
  flex-shrink: 0;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  color: var(--ink-faint);
  text-align: right;
}

.link-stat strong {
  font-weight: 500;
  color: var(--ink-soft);
  transition: color 0.25s ease;
}
.link-stat span { margin-left: -8px; }

a.link-row:hover .link-stat strong,
a.link-row:focus-visible .link-stat strong { color: var(--ember); }

.link-flag {
  font-style: normal;
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-faint);
  border: 1px solid var(--line);
  border-radius: 2px;
  padding: 2px 7px;
}

@media (max-width: 640px) {
  /* stacked, because a row that wraps mid-figure reads worse than two lines */
  .link-head { flex-direction: column; gap: 6px; }
  .link-stat { font-size: 11px; gap: 10px; }
}

/* ========================= the sky, by time of day ========================= */
/* assets/sky.js puts the current phase on <html data-sky> and a coarse
   light/dark flag on <html data-dark>. Everything below is token overrides.
   Two base palettes carry the text and surfaces; ten sky blocks carry the
   atmosphere. Nothing here reads the clock — the phase is a function of the
   sun's real altitude over St. Petersburg.
   Keep the two concerns separate: if you find yourself writing a text colour
   inside a sky block, it probably belongs in one of the two base blocks. */

/* ------------------------------ base: daylight ------------------------------ */

:root[data-dark="false"] {
  color-scheme: light;
  --ink: #1e2b26;
  --ink-soft: #52605a;
  --ink-faint: #8a9791;
  --line: #cdd3c6;
  --paper: #f6f7f2;
  --panel: rgba(246, 247, 242, 0.72);
  --panel-solid: #f6f7f2;
  --shade: rgba(30, 43, 38, 0.045);
  --shadow: rgba(30, 43, 38, 0.35);
  --shadow-strong: rgba(30, 43, 38, 0.45);
  --grain-alpha: 0.032;
}

/* ------------------------------- base: dark ------------------------------- */

:root[data-dark="true"] {
  color-scheme: dark;
  --ink: #e6ece7;
  --ink-soft: #a6b4ad;
  --ink-faint: #6d7c76;
  --line: #2b3a38;
  --paper: #182125;
  --panel: rgba(24, 33, 37, 0.66);
  --panel-solid: #182125;
  --shade: rgba(230, 236, 231, 0.05);
  --shadow: rgba(0, 0, 0, 0.55);
  --shadow-strong: rgba(0, 0, 0, 0.68);
  --grain-alpha: 0.05;
  --blue: #7ea9c9;
  --ember: #e08a4e;
  --pine: #5ea07f;
  --gold: #dfb75c;
  --fmap-sea-hi: #123845;
  --fmap-sea-lo: #030d12;
  --fmap-land: #27453c;
  --fmap-coast: color-mix(in srgb, var(--pine) 75%, var(--bg));
  --fmap-state: color-mix(in srgb, var(--pine) 46%, transparent);
  --fmap-grat: color-mix(in srgb, var(--blue) 20%, transparent);
  --plot-grid: color-mix(in srgb, var(--blue) 17%, transparent);
}

/* --------------------------------- night --------------------------------- */
/* Sun more than 18° down: astronomical night. Full stars, moon, ridges read as
   cut paper against the sky. */

:root[data-sky="night"] {
  --cloud-lit: rgba(150, 172, 196, 0.16);
  --cloud-shade: rgba(90, 110, 134, 0.10);
  --windbreak: #04080c;
  --bg: #080d12;
  --sky-top: #05090d;
  --sky-mid: #080d12;
  --sky-low: #0d1620;
  --ridge-1: #16242c;
  --ridge-2: #111c24;
  --ridge-3: #0b141b;
  --ridge-4: #060b10;
  --tree: #04080c;
  --glow-hot: rgba(126, 169, 201, 0.08);
  --glow-mid: rgba(126, 169, 201, 0.04);
  --mist-color: rgba(126, 169, 201, 0.10);
  --star-alpha: 1;
  --celestial: radial-gradient(circle, rgba(236, 242, 242, 0.95) 0%, rgba(198, 216, 224, 0.34) 42%, rgba(198, 216, 224, 0) 68%);
  --celestial-size: 8vh;
  --veil: linear-gradient(180deg, var(--bg) 0%, rgba(8, 13, 18, 0.52) 28%, rgba(8, 13, 18, 0.06) 56%, rgba(8, 13, 18, 0.46) 100%);
  --scrim: rgba(8, 13, 18, 0.26);
}

/* ---------------------------------- dawn ---------------------------------- */
/* Astronomical and nautical dawn. The east edge is just going indigo; most of
   the stars are still up. */

:root[data-sky="dawn"] {
  --cloud-lit: rgba(150, 168, 206, 0.20);
  --cloud-shade: rgba(70, 88, 128, 0.14);
  --windbreak: #050911;
  --bg: #0b1220;
  --sky-top: #070c17;
  --sky-mid: #0d1526;
  --sky-low: #1e2a42;
  --ridge-1: #1c2940;
  --ridge-2: #151f33;
  --ridge-3: #0e1726;
  --ridge-4: #070c16;
  --tree: #050911;
  --glow-hot: rgba(94, 132, 186, 0.22);
  --glow-mid: rgba(94, 132, 186, 0.09);
  --mist-color: rgba(120, 150, 190, 0.13);
  --star-alpha: 0.72;
  --celestial: radial-gradient(circle, rgba(228, 236, 240, 0.8) 0%, rgba(190, 210, 224, 0.26) 42%, rgba(190, 210, 224, 0) 68%);
  --celestial-size: 7vh;
  --veil: linear-gradient(180deg, var(--bg) 0%, rgba(11, 18, 32, 0.5) 28%, rgba(11, 18, 32, 0.06) 56%, rgba(11, 18, 32, 0.44) 100%);
  --scrim: rgba(10, 16, 28, 0.3);
}

/* ------------------------------- first light ------------------------------- */
/* Civil dawn: the blue hour turning rose at the horizon, last stars going. */

:root[data-sky="first-light"] {
  --cloud-lit: rgba(226, 176, 180, 0.34);
  --cloud-shade: rgba(110, 96, 140, 0.24);
  --windbreak: #0a0d18;
  --bg: #17223a;
  --sky-top: #101a30;
  --sky-mid: #1d2a45;
  --sky-low: #6b5566;
  --ridge-1: #3b4462;
  --ridge-2: #2a3250;
  --ridge-3: #1b2138;
  --ridge-4: #0e1220;
  --tree: #0a0d18;
  --glow-hot: rgba(206, 124, 128, 0.34);
  --glow-mid: rgba(150, 110, 150, 0.16);
  --mist-color: rgba(168, 168, 200, 0.16);
  --star-alpha: 0.26;
  --celestial: radial-gradient(circle, rgba(255, 214, 186, 0.7) 0%, rgba(226, 150, 130, 0.3) 44%, rgba(226, 150, 130, 0) 70%);
  --celestial-size: 9vh;
  --veil: linear-gradient(180deg, var(--bg) 0%, rgba(23, 34, 58, 0.5) 28%, rgba(23, 34, 58, 0.07) 56%, rgba(40, 32, 46, 0.46) 100%);
  --scrim: rgba(18, 26, 44, 0.36);
}

/* -------------------------------- sunrise -------------------------------- */
/* Golden hour, rising. The horizon is the brightest thing on screen and the
   ridges take a warm rim. */

:root[data-sky="sunrise"] {
  --cloud-lit: rgba(255, 216, 178, 0.82);
  --cloud-shade: rgba(186, 128, 118, 0.6);
  --windbreak: #23262f;
  --bg: #e7dfd5;
  --sky-top: #7f97b8;
  --sky-mid: #d3b79f;
  --sky-low: #f0c79a;
  --ridge-1: color-mix(in srgb, #6d7f92 70%, var(--bg));
  --ridge-2: color-mix(in srgb, #55637a 76%, var(--bg));
  --ridge-3: #3d4557;
  --ridge-4: #2a2e3c;
  --tree: #23262f;
  --glow-hot: rgba(255, 176, 92, 0.6);
  --glow-mid: rgba(226, 122, 70, 0.26);
  --mist-color: rgba(255, 226, 198, 0.5);
  --star-alpha: 0;
  --celestial: radial-gradient(circle, rgba(255, 238, 206, 0.98) 0%, rgba(255, 186, 108, 0.6) 40%, rgba(255, 168, 92, 0) 72%);
  --celestial-size: 14vh;
  --veil: linear-gradient(180deg, rgba(231, 223, 213, 0.92) 0%, rgba(231, 223, 213, 0.42) 28%, rgba(231, 223, 213, 0.06) 56%, rgba(226, 190, 156, 0.36) 100%);
  --scrim: rgba(243, 238, 230, 0.8);
}

/* -------------------------------- morning -------------------------------- */
/* Sun up and climbing. Clear, cool, the haze not yet built. */

:root[data-sky="morning"] {
  --cloud-lit: rgba(248, 252, 253, 0.84);
  --cloud-shade: rgba(146, 172, 194, 0.62);
  --windbreak: color-mix(in srgb, var(--ink) 88%, var(--blue));
  --bg: #e0e7e8;
  --sky-top: #97b9d6;
  --sky-mid: #ccdce0;
  --sky-low: #dee7e8;
  --ridge-1: color-mix(in srgb, var(--pine) 30%, var(--bg));
  --ridge-2: color-mix(in srgb, var(--blue) 40%, var(--bg));
  --ridge-3: color-mix(in srgb, var(--blue) 60%, var(--bg));
  --ridge-4: color-mix(in srgb, var(--blue) 40%, var(--ink));
  --tree: color-mix(in srgb, var(--ink) 88%, var(--blue));
  --glow-hot: rgba(214, 234, 244, 0.34);
  --glow-mid: rgba(186, 212, 230, 0.12);
  --mist-color: rgba(228, 240, 244, 0.78);
  --star-alpha: 0;
  --celestial: radial-gradient(circle, rgba(247, 252, 254, 0.94) 0%, rgba(206, 230, 244, 0.42) 42%, rgba(206, 230, 244, 0) 70%);
  --celestial-size: 10vh;
  --veil: linear-gradient(180deg, var(--bg) 0%, rgba(224, 231, 232, 0.4) 28%, rgba(224, 231, 232, 0.05) 56%, rgba(224, 231, 232, 0.3) 100%);
  --scrim: rgba(226, 233, 234, 0.78);
}

/* --------------------------------- midday --------------------------------- */
/* High sun. Flat, bright, high-key; distance washes out in haze and the
   ridges lose contrast rather than gaining it. */

:root[data-sky="midday"] {
  --cloud-lit: rgba(250, 253, 255, 0.86);
  --cloud-shade: rgba(138, 166, 190, 0.6);
  --windbreak: color-mix(in srgb, var(--ink) 80%, var(--blue));
  --bg: #dce4e7;
  --sky-top: #8cb2d3;
  --sky-mid: #c3d6dd;
  --sky-low: #dae3e6;
  --ridge-1: color-mix(in srgb, var(--pine) 18%, var(--bg));
  --ridge-2: color-mix(in srgb, var(--blue) 26%, var(--bg));
  --ridge-3: color-mix(in srgb, var(--blue) 44%, var(--bg));
  --ridge-4: color-mix(in srgb, var(--blue) 30%, var(--ink));
  --tree: color-mix(in srgb, var(--ink) 80%, var(--blue));
  --glow-hot: rgba(206, 230, 244, 0.34);
  --glow-mid: rgba(178, 206, 228, 0.12);
  --mist-color: rgba(222, 236, 242, 0.76);
  --star-alpha: 0;
  --celestial: radial-gradient(circle, rgba(246, 252, 255, 0.95) 0%, rgba(200, 226, 244, 0.4) 36%, rgba(200, 226, 244, 0) 68%);
  --celestial-size: 7vh;
  --veil: linear-gradient(180deg, var(--bg) 0%, rgba(220, 228, 231, 0.42) 28%, rgba(220, 228, 231, 0.06) 56%, rgba(220, 228, 231, 0.3) 100%);
  --scrim: rgba(222, 231, 234, 0.78);
}

/* ------------------------------- afternoon ------------------------------- */
/* Falling sun, warmer than the morning it mirrors. */

:root[data-sky="afternoon"] {
  --cloud-lit: rgba(252, 251, 244, 0.84);
  --cloud-shade: rgba(162, 166, 162, 0.6);
  --windbreak: color-mix(in srgb, var(--ink) 86%, var(--blue));
  --bg: #e2e5e1;
  --sky-top: #9db8cc;
  --sky-mid: #d1d9d8;
  --sky-low: #e3e3da;
  --ridge-1: color-mix(in srgb, var(--pine) 26%, var(--bg));
  --ridge-2: color-mix(in srgb, var(--blue) 36%, var(--bg));
  --ridge-3: color-mix(in srgb, var(--blue) 56%, var(--bg));
  --ridge-4: color-mix(in srgb, var(--blue) 38%, var(--ink));
  --tree: color-mix(in srgb, var(--ink) 86%, var(--blue));
  --glow-hot: rgba(240, 226, 190, 0.34);
  --glow-mid: rgba(206, 178, 140, 0.13);
  --mist-color: rgba(234, 240, 240, 0.76);
  --star-alpha: 0;
  --celestial: radial-gradient(circle, rgba(253, 250, 238, 0.95) 0%, rgba(240, 214, 164, 0.42) 42%, rgba(240, 214, 164, 0) 70%);
  --celestial-size: 11vh;
  --veil: linear-gradient(180deg, var(--bg) 0%, rgba(226, 229, 225, 0.4) 28%, rgba(226, 229, 225, 0.05) 56%, rgba(226, 229, 225, 0.32) 100%);
  --scrim: rgba(228, 231, 227, 0.78);
}

/* --------------------------------- sunset --------------------------------- */
/* Golden hour, falling. The loudest the palette gets all day. */

:root[data-sky="sunset"] {
  --cloud-lit: rgba(255, 198, 150, 0.84);
  --cloud-shade: rgba(138, 96, 118, 0.62);
  --windbreak: #241f2b;
  --bg: #ecdccd;
  --sky-top: #6e7396;
  --sky-mid: #cf9b83;
  --sky-low: #f2b076;
  --ridge-1: color-mix(in srgb, #7a7286 72%, var(--bg));
  --ridge-2: color-mix(in srgb, #5d5570 78%, var(--bg));
  --ridge-3: #423c52;
  --ridge-4: #2c2736;
  --tree: #241f2b;
  --glow-hot: rgba(255, 150, 66, 0.68);
  --glow-mid: rgba(214, 88, 62, 0.3);
  --mist-color: rgba(255, 214, 186, 0.48);
  --star-alpha: 0;
  --celestial: radial-gradient(circle, rgba(255, 234, 192, 0.98) 0%, rgba(255, 158, 74, 0.66) 38%, rgba(246, 126, 66, 0) 72%);
  --celestial-size: 15vh;
  --veil: linear-gradient(180deg, rgba(236, 220, 205, 0.92) 0%, rgba(236, 220, 205, 0.42) 28%, rgba(236, 220, 205, 0.06) 56%, rgba(226, 168, 122, 0.36) 100%);
  --scrim: rgba(245, 236, 226, 0.8);
}

/* -------------------------------- twilight -------------------------------- */
/* Civil dusk. Magenta over the horizon, the first stars, the ridges going to
   silhouette. */

:root[data-sky="twilight"] {
  --cloud-lit: rgba(214, 160, 172, 0.32);
  --cloud-shade: rgba(96, 82, 124, 0.24);
  --windbreak: #0b0a14;
  --bg: #1d2038;
  --sky-top: #171a30;
  --sky-mid: #2c2b48;
  --sky-low: #7a4f5c;
  --ridge-1: #443f60;
  --ridge-2: #302c4c;
  --ridge-3: #1f1d34;
  --ridge-4: #11101e;
  --tree: #0b0a14;
  --glow-hot: rgba(226, 118, 104, 0.34);
  --glow-mid: rgba(150, 90, 140, 0.18);
  --mist-color: rgba(176, 160, 200, 0.15);
  --star-alpha: 0.34;
  --celestial: radial-gradient(circle, rgba(255, 196, 160, 0.66) 0%, rgba(226, 122, 110, 0.28) 44%, rgba(226, 122, 110, 0) 70%);
  --celestial-size: 10vh;
  --veil: linear-gradient(180deg, var(--bg) 0%, rgba(29, 32, 56, 0.5) 28%, rgba(29, 32, 56, 0.07) 56%, rgba(52, 34, 44, 0.46) 100%);
  --scrim: rgba(24, 26, 46, 0.52);
}

/* -------------------------------- nightfall -------------------------------- */
/* Nautical and astronomical dusk. Colour drains out, stars come up. */

:root[data-sky="nightfall"] {
  --cloud-lit: rgba(140, 156, 196, 0.20);
  --cloud-shade: rgba(70, 84, 124, 0.14);
  --windbreak: #050911;
  --bg: #0c1322;
  --sky-top: #070c16;
  --sky-mid: #0e1626;
  --sky-low: #202a44;
  --ridge-1: #1e2942;
  --ridge-2: #162034;
  --ridge-3: #0f1726;
  --ridge-4: #080d16;
  --tree: #050911;
  --glow-hot: rgba(150, 110, 150, 0.2);
  --glow-mid: rgba(110, 100, 160, 0.09);
  --mist-color: rgba(130, 145, 190, 0.13);
  --star-alpha: 0.7;
  --celestial: radial-gradient(circle, rgba(232, 238, 240, 0.82) 0%, rgba(196, 212, 224, 0.28) 42%, rgba(196, 212, 224, 0) 68%);
  --celestial-size: 8vh;
  --veil: linear-gradient(180deg, var(--bg) 0%, rgba(12, 19, 34, 0.5) 28%, rgba(12, 19, 34, 0.06) 56%, rgba(12, 19, 34, 0.44) 100%);
  --scrim: rgba(11, 17, 30, 0.3);
}

/* ------------------------- scenes, under either sky ------------------------- */
/* Field Notes' Dive and Ski panels re-cast the whole page. They only need to
   know whether it is light or dark out, not which of the ten phases. */

:root[data-dark="false"][data-scene="depth"] {
  --veil: linear-gradient(180deg, rgba(188, 214, 219, 0.88) 0%, rgba(188, 214, 219, 0.3) 26%, rgba(120, 160, 172, 0.08) 54%, rgba(93, 141, 156, 0.42) 100%);
  --scrim: rgba(224, 238, 240, 0.78);
}
:root[data-dark="true"][data-scene="depth"] {
  --veil: linear-gradient(180deg, rgba(10, 34, 43, 0.82) 0%, rgba(8, 28, 36, 0.34) 30%, rgba(7, 24, 32, 0.06) 58%, rgba(4, 16, 22, 0.66) 100%);
  --scrim: rgba(7, 26, 34, 0.66);
}
:root[data-dark="false"][data-scene="snow"] {
  --veil: linear-gradient(180deg, rgba(228, 236, 238, 0.9) 0%, rgba(228, 236, 238, 0.42) 28%, rgba(210, 224, 228, 0.1) 56%, rgba(196, 213, 219, 0.4) 100%);
  --scrim: rgba(238, 243, 244, 0.78);
}
:root[data-dark="true"][data-scene="snow"] {
  --veil: linear-gradient(180deg, rgba(14, 24, 30, 0.74) 0%, rgba(14, 24, 30, 0.3) 30%, rgba(14, 24, 30, 0.04) 58%, rgba(12, 20, 26, 0.56) 100%);
  --scrim: rgba(14, 24, 30, 0.62);
}

/* No JS, no data-sky: fall back to honouring the operating system rather than
   pinning everyone to a daylight palette. */
@media (prefers-color-scheme: dark) {
  :root:not([data-sky]) {
    color-scheme: dark;
    --bg: #080d12;
    --ink: #e6ece7;
    --ink-soft: #a6b4ad;
    --ink-faint: #6d7c76;
    --line: #2b3a38;
    --paper: #182125;
    --panel: rgba(24, 33, 37, 0.66);
    --panel-solid: #182125;
    --shade: rgba(230, 236, 231, 0.05);
    --sky-top: #05090d;
    --sky-mid: #080d12;
    --sky-low: #0d1620;
    --ridge-1: #16242c;
    --ridge-2: #111c24;
    --ridge-3: #0b141b;
    --ridge-4: #060b10;
    --tree: #04080c;
    --star-alpha: 1;
    --scrim: rgba(8, 13, 18, 0.66);
  }
}

/* Phase changes are a slow fade, not a cut — the sky moves in real time and a
   hard switch at a boundary would be jarring. */
@media (prefers-reduced-motion: no-preference) {
  .topo-bg,
  .scene--alpine .glow,
  .scene--alpine .celestial,
  .sky-stars,
  .ridge-layer path,
  .treeline path {
    transition: background 1.2s ease, fill 1.2s ease, opacity 1.2s ease,
                left 1.2s ease, top 1.2s ease, width 1.2s ease, height 1.2s ease;
  }
}

/* ============================ ambient: the hub ============================ */
/* The home page runs weather; the rest of the site does not. Clouds cross the
   sky on three depth bands and a near treeline moves in the wind. All of it is
   CSS keyframes on a fixed, composited layer — no JS frame loop — so it costs
   effectively nothing to leave running, and it stops completely under
   prefers-reduced-motion. */

.clouds {
  position: absolute;
  inset: 0 0 34% 0;
  overflow: hidden;
  z-index: 4;
  pointer-events: none;
  /* the veil would erase them against a pale midday sky; mask them out towards
     the horizon instead so they still fade into the distance */
  -webkit-mask-image: linear-gradient(180deg, #000 0 58%, transparent 100%);
  mask-image: linear-gradient(180deg, #000 0 58%, transparent 100%);
}

.cloud {
  position: absolute;
  left: 0;
  width: 26vw;
  height: 9vh;
  transform: translateX(var(--cloud-x, 20vw)) scale(var(--cloud-scale, 1));
  will-change: transform;
}

/* far clouds are thinner and paler, near ones heavier and softer-edged */
.cloud--0 { filter: blur(7px); }
.cloud--1 { filter: blur(11px); }
.cloud--2 { filter: blur(16px); }

.puff {
  position: absolute;
  border-radius: 50%;
  background: radial-gradient(ellipse at 44% 26%,
              var(--cloud-lit, rgba(255,255,255,0.8)) 0%,
              var(--cloud-lit, rgba(255,255,255,0.8)) 30%,
              var(--cloud-shade, rgba(190,205,215,0.4)) 66%,
              transparent 80%);
}

/* ------------------------------ the windbreak ------------------------------ */

.windbreak {
  position: absolute;
  left: -2%;
  bottom: -1px;
  width: 104%;
  height: 16vh;
  min-height: 96px;
  /* above the readability veil: this is foreground, and letting the veil wash
     it flattens it into the distant ridges */
  z-index: 4;
  pointer-events: none;
  opacity: 0.9;
}

.wb-tree {
  fill: var(--windbreak, #1b2a24);
  transform-box: fill-box;
  transform-origin: 50% 100%;
}

@media (prefers-reduced-motion: no-preference) {
  .cloud {
    animation-name: drift-cloud;
    animation-timing-function: linear;
    animation-iteration-count: infinite;
  }

  /* Each tree leans on its own clock, so the row reads as wind moving through
     rather than one object rocking. */
  .wb-tree {
    animation-name: rustle;
    animation-timing-function: ease-in-out;
    animation-iteration-count: infinite;
    animation-direction: alternate;
  }
}

@keyframes drift-cloud {
  from { transform: translateX(-46vw) scale(var(--cloud-scale, 1)); }
  to   { transform: translateX(146vw) scale(var(--cloud-scale, 1)); }
}

@keyframes rustle {
  from { transform: rotate(calc(var(--sway, 1.4deg) * -1)); }
  to   { transform: rotate(var(--sway, 1.4deg)); }
}

/* The near trees sit in front of everything, so they take the strongest
   parallax of any layer. */
@media (prefers-reduced-motion: no-preference) {
  .windbreak {
    transform: translate3d(calc(var(--parallax-x, 0) * 26px),
                           calc(var(--parallax-y, 0) * 11px + var(--scroll-y, 0) * -104px), 0);
    transition: transform 0.28s ease-out;
  }
}

@media (max-width: 640px) {
  /* fewer, bigger, slower: a phone doesn't need nine clouds and shouldn't pay
     for nine composited layers */
  .cloud--0 { display: none; }
  .cloud { width: 46vw; }
  .windbreak { height: 15vh; min-height: 84px; }
}

/* ---------------------- phones: legibility floors ----------------------- */
/* Mono runs small by design here — eyebrows, units, tags and column heads are
   meant to sit under the thing they label, not compete with it. Several had
   drifted to 9.5 and 10px, which is fine on a desktop at arm's length and not
   fine on a phone. These lift the smallest of them to 11px without touching
   the desktop sizes, and widen the letter-spacing back out so the extra size
   does not make them look crowded. */
@media (max-width: 640px) {
  .chart-unit,
  .cov-rating,
  .cov-disclaimer,
  .range-meta,
  .status-tag,
  .link-flag,
  .pick-eyebrow { font-size: 11px; }

  /* The figure captions under a stat run smaller still — 9px on The Log's
     avg/median/low/high and 9.5px on a trip's distance/gain/high point. */
  .chart-stats small,
  .trip-stats small,
  .trip-tag,
  .rank-tag,
  .rank-storage-note,
  .trip-note,
  .ch-rank, .ch-track, .ch-dur { font-size: 10.5px; }

  /* Footer links are a 22px target, and the two sit 10px apart. */
  footer { gap: 4px; }
  footer a { padding: 10px 6px; }

  /* iOS zooms the whole page in when a focused field is under 16px, which on
     the ranking search left the reader scrolled sideways into a layout they
     did not ask for. */
  .rank-add summary { padding: 10px 0; }
  .rank-add-form input { font-size: 16px; padding-block: 10px; }
  .rank-add-form button { padding-block: 11px; }
}

/* ---------------------------- kit.html: the shelf ---------------------------- */
/* Nothing on this page uses --ink-faint. Everywhere else that token labels
   something the reader can ignore, and it is decorative-grade on purpose —
   measured, it is about 2.6:1 on the light background, well under AA. Here the
   small mono carries the category, the price and the destination, which is the
   whole content of the page, so it all sits on --ink-soft (5.8:1) instead. */
/* Built by assets/kit.js from assets/kit-data.js. The product tiles are drawn,
   not photographed — see the note at the top of kit.js for why. Everything is
   palette tokens, so the shelf re-themes with the sky like the rest. */

.kit-note {
  margin: 20px 0 42px;
  max-width: 62ch;
  font-family: var(--font-mono);
  font-size: 11.5px;
  line-height: 1.85;
  letter-spacing: 0.03em;
  color: var(--ink-soft);
}
.kit-meta {
  display: block;
  color: var(--ink-soft);
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.kit-group + .kit-group { margin-top: 10px; }

.kit-blurb {
  margin: 10px 0 30px;
  max-width: 54ch;
  font-size: 15.5px;
  color: var(--ink-soft);
  text-wrap: pretty;
}

/* A shelf, not a card grid. There are no borders or panels around an item —
   the hairline the object stands on is drawn inside its own tile, so the
   rhythm comes from the objects themselves. */
.kit-grid {
  --kit-accent: var(--pine);
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(164px, 1fr));
  gap: 40px 26px;
  /* stretch, not start: the cells have to be equal height so every price line
     sits on the same baseline across the row. A ragged row of prices reads as
     a broken table, which on a page of prices is the wrong first impression. */
  align-items: stretch;
}
.kit-grid--hiking { --kit-accent: var(--ember); }

.kit-item {
  display: flex;
  flex-direction: column;
  text-decoration: none;
  color: inherit;
  padding: 4px 2px 10px;
  border-radius: 3px;
}

.kit-art { display: block; margin-bottom: 14px; }

.kit-tile {
  display: block;
  width: 100%;
  height: auto;
  max-width: 150px;
  overflow: visible;
}

/* The object. Paper body, soft outline, one band of the group's accent —
   the same restraint the elevation motif uses. */
.k-body {
  fill: var(--paper);
  stroke: var(--ink-soft);
  stroke-width: 2.1;
  stroke-linejoin: round;
}
.k-fill {
  fill: color-mix(in srgb, var(--kit-accent) 38%, transparent);
  stroke: none;
}
.k-line {
  fill: none;
  stroke: var(--ink-soft);
  stroke-width: 2.1;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.k-cap {
  fill: color-mix(in srgb, var(--kit-accent) 62%, var(--paper));
  stroke: var(--ink-soft);
  stroke-width: 2.1;
  stroke-linejoin: round;
}
.kit-shelf {
  stroke: var(--line);
  stroke-width: 1.4;
}

.kit-what {
  display: block;
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin-bottom: 5px;
}

.kit-name {
  display: block;
  font-size: 15px;
  line-height: 1.4;
  color: var(--ink-soft);
}
.kit-name strong {
  display: block;
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 18px;
  line-height: 1.22;
  letter-spacing: -0.012em;
  color: var(--ink);
}

.kit-variant {
  display: block;
  margin-top: 4px;
  font-size: 13.5px;
  color: var(--ink-soft);
}

/* Pushed to the bottom of the cell by the auto margin, so the rule and the
   price line up across a row whatever the name does above them. The
   destination sits under the price rather than beside it: a column this narrow
   cannot hold "$69" and "blueprint.bryanjohnson.com" on one line, and
   truncating the domain is worse than stacking it. */
.kit-foot {
  display: flex;
  flex-direction: column;
  gap: 3px;
  margin-top: auto;
  padding-top: 9px;
  border-top: 1px solid var(--line);
}

.kit-price {
  font-family: var(--font-mono);
  font-size: 14px;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}
/* No confirmed figure, so say so rather than print a number that reads real. */
.kit-price em {
  font-style: normal;
  font-size: 11.5px;
  letter-spacing: 0.06em;
  color: var(--ink-soft);
}
.kit-from {
  font-size: 10.5px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

/* Wraps rather than nowraps: "blueprint.bryanjohnson.com" is wider than a
   168px column, and nowrap pushed 41px of sideways scroll onto every phone.
   Two lines of domain is fine; a horizontally scrolling page is not. */
.kit-go {
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: 0.05em;
  line-height: 1.5;
  color: var(--ink-soft);
  overflow-wrap: anywhere;
  transition: color 0.18s ease;
}

/* Hover moves colour only, never position: a grid of tiles that lift on
   hover is exactly the card treatment this site is trying not to be. */
.kit-item:hover .kit-name strong,
.kit-item:focus-visible .kit-name strong { color: var(--ember); }
.kit-item:hover .kit-go,
.kit-item:focus-visible .kit-go { color: var(--ember); }
.kit-item:hover .k-fill,
.kit-item:focus-visible .k-fill {
  fill: color-mix(in srgb, var(--kit-accent) 60%, transparent);
}
.kit-item:hover .kit-shelf,
.kit-item:focus-visible .kit-shelf { stroke: var(--ember); }

.kit-item:focus { outline: none; }
.kit-item:focus-visible {
  outline: 2px solid var(--ember);
  outline-offset: 6px;
}

@media (prefers-reduced-motion: reduce) {
  .kit-go, .k-fill, .kit-shelf { transition: none; }
}

/* The hiking list is one item deep on purpose; the placeholder says so rather
   than leaving a lone tile looking like a loading failure. */
.kit-pending {
  align-self: start;
  margin: 0;
  padding: 44px 0 0 2px;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
.kit-pending::before {
  content: '';
  display: block;
  width: 34px;
  height: 1px;
  margin-bottom: 12px;
  background: var(--line);
}

@media (max-width: 640px) {
  /* Two to a row still reads on a phone, and one huge tile per row would make
     a ten-item page an awful lot of scrolling. */
  .kit-grid { grid-template-columns: repeat(2, 1fr); gap: 30px 18px; }
  .kit-tile { max-width: 112px; }
  .kit-name strong { font-size: 16px; }
  .kit-name { font-size: 14px; }
  .kit-variant { font-size: 12.5px; }
  .kit-note { font-size: 11px; }
  .kit-blurb { font-size: 15px; }
}

@media (max-width: 360px) {
  .kit-grid { grid-template-columns: 1fr; }
  .kit-tile { max-width: 130px; }
}
