/* Reset & base */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

:root {
  /* Flint Hills palette */
  --prairie-gold: #D6A44C;
  --deep-amber:   #B27C2C;
  --prairie-sky:  #7CB0D6;
  --deep-sky:     #3F6E97;
  --limestone:    #EDE4D1;
  --warm-gray:    #B7AC90;
  --charcoal:     #14181E;

  /* Semantic tokens — Light theme (default, Limestone base) */
  --bg:       #FAF6EC;
  --surface:  #F1E8D6;
  --border:   #E0D4B9;
  /* Middle wave stripe: the hero's own field colour, so the notch between the
     gold and amber bands reads as the hero showing through. */
  --wave-mid: var(--surface);
  --accent:   var(--deep-amber);   /* readable gold-brown on cream */
  --accent2:  var(--deep-sky);
  --text:     var(--charcoal);
  --muted:    #756B52;             /* dark warm gray for contrast */

  --radius:   8px;
  --max-w:    1100px;
  /* The home card grid runs wider than the reading-width container: three
     cards need the room, and prose does not. One variable because the strip on
     the wave band aligns to this same edge. */
  --home-max-w: min(1480px, 94vw);

  /* Bricolage Grotesque ties the site to the logo — headings only */
  --font-display: "Bricolage Grotesque", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  --font-body:    -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
}

/* Dark theme — Charcoal base */
:root[data-theme="dark"] {
  --bg:       var(--charcoal);
  --surface:  #1b2029;
  --border:   #2c333f;
  --accent:   var(--prairie-gold);
  --accent2:  var(--prairie-sky);
  --text:     var(--limestone);
  --muted:    var(--warm-gray);
}

html { font-size: 16px; scroll-behavior: smooth; }

body {
  font-family: var(--font-body);
  background: var(--bg);
  color: var(--text);
  line-height: 1.6;
  transition: background-color 0.2s ease, color 0.2s ease;
}

h1, h2, h3, h4 {
  font-family: var(--font-display);
}

.container {
  max-width: var(--max-w);
  margin: 0 auto;
  padding: 0 1.5rem;
}

/* Header */
.site-header {
  padding: 1.25rem 0;
  border-bottom: 1px solid var(--border);
  background: var(--bg);
  position: sticky;
  top: 0;
  z-index: 100;
}

.logo {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  text-decoration: none;
}

/* Nav */
.nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
}

.nav-links {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  flex-wrap: wrap;
}

.nav-links a {
  color: var(--muted);
  text-decoration: none;
  font-size: 0.92rem;
  font-weight: 500;
  transition: color 0.2s;
}

.nav-links a:hover,
.nav-links a.active {
  color: var(--text);
}

.nav-cta {
  padding: 0.4rem 1rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
}

.nav-cta:hover {
  border-color: var(--accent);
  color: var(--accent) !important;
}

/* Theme toggle */
.theme-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.1rem;
  height: 2.1rem;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: transparent;
  color: var(--muted);
  cursor: pointer;
  transition: color 0.2s, border-color 0.2s;
}

.theme-toggle:hover {
  color: var(--accent);
  border-color: var(--accent);
}

.theme-toggle svg {
  width: 1.05rem;
  height: 1.05rem;
  display: block;
}

/* Show moon in light mode (switch to dark), sun in dark mode */
.theme-toggle .icon-sun { display: none; }
.theme-toggle .icon-moon { display: block; }
:root[data-theme="dark"] .theme-toggle .icon-sun { display: block; }
:root[data-theme="dark"] .theme-toggle .icon-moon { display: none; }

/* Header logo lockup: light/dark-bg SVG variants swapped by theme, same
   show/hide technique as the theme-toggle sun/moon icons. */
.logo-lockup {
  height: 2.25rem;
  width: auto;
  display: none;
}

.logo-lockup--light { display: block; }
:root[data-theme="dark"] .logo-lockup--light { display: none; }
:root[data-theme="dark"] .logo-lockup--dark { display: block; }

/* Footer brand mark: small square variant, swapped by theme. */
.logo-mark-img {
  height: 2rem;
  width: 2rem;
  display: none;
}

.logo-mark-img--light { display: block; }
:root[data-theme="dark"] .logo-mark-img--light { display: none; }
:root[data-theme="dark"] .logo-mark-img--dark { display: block; }

/* Hero */
.hero {
  padding: 6rem 0 5rem;
  text-align: center;
  background: radial-gradient(ellipse 80% 50% at 50% -10%, rgba(214,164,76,0.13) 0%, transparent 70%);
}

.hero h1 {
  font-size: clamp(2.4rem, 6vw, 4rem);
  font-weight: 800;
  letter-spacing: -0.03em;
  line-height: 1.1;
  background: linear-gradient(135deg, var(--text) 40%, var(--accent));
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
  margin-bottom: 1rem;
}

/* ── Single-screen home (design variant 6a) ─────────────────────────────────
   Wordmark, cards, wave band. Targets one viewport without *guaranteeing* it:
   min-height fills the screen and the waves pin to the bottom when there is
   slack, but if the content is taller the page simply scrolls.

   That distinction is the whole design. Enforcing no-scroll made height an
   input rather than an output, which took three viewport-height tiers of
   hardcoded padding to fake — and still failed by silently clipping content
   off the bottom. Letting it scroll deletes all of that. */
.home-screen {
  min-height: 100dvh;      /* dvh, not vh: vh ignores mobile browser chrome */
  display: flex;
  flex-direction: column;
}

.home-masthead {
  padding-top: clamp(1.5rem, 5vh, 4rem);
  text-align: center;
}

.wordmark {
  /* vmin so the wordmark answers to height as well as width — on a short
     window this is what stops it crowding the cards out of the screen. */
  font-size: clamp(2.5rem, 9vmin, 7.5rem);
  letter-spacing: -0.04em;
  line-height: 0.95;
  background: none;                        /* beat .hero h1's gradient clip */
  -webkit-text-fill-color: currentColor;
  color: var(--text);
  margin-bottom: 0.75rem;
}

.wordmark span { color: var(--accent); }

/* Contact call to action, in the tagline's old slot under the wordmark. */
.home-cta { margin-top: clamp(0.75rem, 2.5vh, 1.5rem); }

/* Deliberately well below the wordmark's scale — it sits directly beneath a
   display-size lockup and should not compete with it. */
.home-cta h2 {
  font-size: clamp(1.1rem, 2.4vmin, 1.4rem);
  font-weight: 700;
  color: var(--text);
  margin-bottom: 0.4rem;
}

.home-cta p {
  font-size: clamp(0.88rem, 1.9vh, 1rem);
  color: var(--muted);
  max-width: 34rem;
  margin: 0 auto clamp(0.6rem, 1.5vh, 1.1rem);
}

/* Takes the leftover height and centres the cards in it. `1 0 auto` — grow into
   slack, but never shrink below the cards' own height: shrinking is what would
   clip them when the viewport is short. Past that point the parent outgrows
   100dvh and the page scrolls, which is the intended escape hatch. */
.home-cards {
  flex: 1 0 auto;
  /* width:100% is load-bearing. .container's `margin: 0 auto` gives this flex
     item auto cross-axis margins, which suppress stretch and make it
     shrink-to-fit — so it would sit at its content width and ignore the wider
     cap below. */
  width: 100%;
  max-width: var(--home-max-w);   /* wider than .container's --max-w */
  display: flex;
  align-items: center;
  padding-top: clamp(1.5rem, 4vh, 3rem);
  padding-bottom: clamp(1.5rem, 4vh, 3rem);
}

.home-cards .service-grid { width: 100%; }

.home-waves {
  position: relative;
  margin-top: auto;        /* pinned to the bottom of the screen */
  flex-shrink: 0;
}

.hero-waves {
  display: block;
  width: 100%;
  height: clamp(80px, 13vh, 155px);
}

.hero-waves .wave-1 { fill: var(--prairie-gold); }
.hero-waves .wave-2 { fill: var(--wave-mid); }
.hero-waves .wave-3 { fill: var(--accent); }

/* Footer essentials riding the amber band. Limestone on --accent, since the
   band is the darkest wave. */
.home-strip {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  display: flex;
  align-items: center;
  justify-content: flex-start;
  flex-wrap: wrap;
  gap: 0.6rem;
  /* Left-aligned to the card grid's gutter, so it lines up with the cards above
     rather than floating at the raw viewport edge. */
  padding-left: max(1.5rem, calc((100% - var(--home-max-w)) / 2 + 1.5rem));
  padding-right: 1.5rem;
  /* Sits low: the amber band is at its *shortest* on the left (the wave crests
     upward toward the centre), so this is the tightest point vertically. */
  padding-bottom: 0.7rem;
  font-size: 0.8rem;
  color: var(--limestone);
}

.home-strip-sep { opacity: 0.55; }
.home-strip-copy { opacity: 0.85; }

.home-strip-version {
  opacity: 0.6;
  font-variant-numeric: tabular-nums;
  font-size: 0.7rem;
}

/* Inherit the band's colour rather than the page's --muted, which would be
   near-invisible on amber. */
.home-strip .theme-toggle {
  color: var(--limestone);
  border-color: rgba(233, 224, 205, 0.45);
  width: 1.8rem;
  height: 1.8rem;
  margin-right: 0.3rem;   /* leads the strip, so the gap goes after it */
}

.home-strip .theme-toggle:hover {
  color: #fff;
  border-color: var(--limestone);
}

.home-strip .theme-toggle svg { width: 0.9rem; height: 0.9rem; }

/* The toggle also lives in the footer on every non-home page. */
.footer-theme {
  display: flex;
  justify-content: center;
}

.hero-waves .wave-1 { fill: var(--prairie-gold); }
.hero-waves .wave-2 { fill: var(--wave-mid); }
.hero-waves .wave-3 { fill: var(--accent); }

.tagline {
  font-size: 1.2rem;
  color: var(--muted);
  max-width: 480px;
  margin: 0 auto;
}

/* Services */
.services {
  padding: 5rem 0;
}

.services h2 {
  text-align: center;
  font-size: 1.75rem;
  font-weight: 700;
  margin-bottom: 3rem;
  color: var(--text);
}

.service-grid {
  display: grid;
  /* 300px, not 340: three tracks plus gaps must fit the 1100px container, or
     auto-fit drops to two columns and orphans the third card. */
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 1.5rem;
}

/* Column layout so .card-link can be pinned to the bottom via margin-top:auto,
   keeping the "Explore research →" affordance aligned across cards whose
   bodies differ in height. */
.service-card {
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  /* Vertical padding is height-aware so cards compress smoothly on short
     viewports — one fluid rule, rather than a stack of max-height overrides. */
  padding: clamp(1.4rem, 3vh, 2.75rem) 2.25rem;
  transition: border-color 0.2s, transform 0.2s;
  text-decoration: none;
  color: inherit;
}

.card-link {
  display: inline-block;
  margin-top: auto;
  padding-top: clamp(0.8rem, 1.8vh, 1.5rem);
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--accent);
}

/* Third-party project marks */
.card-logos {
  margin-top: clamp(0.9rem, 2vh, 1.75rem);
  padding-top: clamp(0.8rem, 1.8vh, 1.5rem);
  border-top: 1px solid var(--border);
}

.card-logo-row {
  display: flex;
  align-items: center;
  gap: 1.25rem 1.5rem;
  flex-wrap: wrap;
}

/* Several of these marks are dark-on-transparent (Django, the AWS and
   Cloudflare wordmarks) and disappear against the dark card. Rather than
   maintain a negative variant of each, the row sits on a light plate in dark
   mode — every logo is then on the background it was drawn for. */
:root[data-theme="dark"] .card-logo-row {
  background: var(--limestone);
  border-radius: var(--radius);
  padding: 0.75rem 0.9rem;
  gap: 1rem 1.25rem;
}

/* Height-normalised, not width: these two marks have very different aspect
   ratios (Tor is a wide lockup, Shadow nearly square), so matching widths
   would make Shadow tower over Tor. */
.card-logo {
  height: 1.9rem;
  width: auto;
  max-width: 40%;
  object-fit: contain;
}

.service-card:hover {
  border-color: var(--accent);
  transform: translateY(-2px);
}

/* Not a link yet, so it must not offer a link's affordances — no lift, no
   border highlight, nothing that invites a click that goes nowhere. */
.service-card--soon:hover {
  border-color: var(--border);
  transform: none;
}

.card-link--soon {
  color: var(--muted);
  font-style: italic;
}

.service-icon {
  font-size: 1.5rem;
  margin-bottom: 1rem;
  color: var(--accent);
  line-height: 1;
}

.service-card h3 {
  font-size: 1.05rem;
  font-weight: 700;
  margin-bottom: 0.6rem;
}

.service-card p {
  font-size: 0.92rem;
  color: var(--muted);
  line-height: 1.6;
}

/* Contact */
.contact {
  padding: 5rem 0;
  text-align: center;
  border-top: 1px solid var(--border);
}

.contact h2 {
  font-size: 1.75rem;
  font-weight: 700;
  margin-bottom: 0.75rem;
}

.contact p {
  color: var(--muted);
  margin-bottom: 1.75rem;
}

.btn {
  display: inline-block;
  padding: 0.75rem 2rem;
  background: linear-gradient(135deg, var(--prairie-gold), var(--deep-amber));
  color: var(--charcoal);
  text-decoration: none;
  border-radius: var(--radius);
  font-weight: 700;
  font-size: 0.95rem;
  transition: opacity 0.2s, transform 0.2s;
}

.btn:hover {
  opacity: 0.9;
  transform: translateY(-1px);
}

/* Footer */
.site-footer {
  padding: 1.5rem 0;
  border-top: 1px solid var(--border);
  text-align: center;
}

.site-footer p {
  font-size: 0.85rem;
  color: var(--muted);
}

/* Page hero (sub-pages) */
.page-hero {
  padding: 4.5rem 0 3rem;
  border-bottom: 1px solid var(--border);
  background: radial-gradient(ellipse 80% 60% at 50% -20%, rgba(214,164,76,0.10) 0%, transparent 70%);
}

.eyebrow {
  text-transform: uppercase;
  letter-spacing: 0.12em;
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--accent);
  margin-bottom: 0.75rem;
}

.page-hero h1 {
  font-size: clamp(2rem, 5vw, 3rem);
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 1.1;
  margin-bottom: 1rem;
}

.lead {
  font-size: 1.15rem;
  color: var(--muted);
  max-width: 640px;
}

/* Generic sections */
.section {
  padding: 4rem 0;
}

.section-alt {
  background: var(--surface);
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
}

.section-title {
  font-size: 1.6rem;
  font-weight: 700;
  margin-bottom: 0.75rem;
}

.section-intro {
  color: var(--muted);
  margin-bottom: 2rem;
  max-width: 640px;
}

/* Prose */
.prose {
  max-width: 760px;
}

.prose p { margin-bottom: 1.1rem; color: var(--text); }
.prose h2 { margin: 2rem 0 0.75rem; font-size: 1.6rem; }
.prose h3 { margin: 1.5rem 0 0.5rem; font-size: 1.15rem; }
.prose a { color: var(--accent); }

.feature-list {
  list-style: none;
  margin-top: 1rem;
}

.feature-list li {
  position: relative;
  padding-left: 1.5rem;
  margin-bottom: 0.9rem;
  color: var(--muted);
}

.feature-list li strong { color: var(--text); }

.feature-list li::before {
  content: "▸";
  position: absolute;
  left: 0;
  color: var(--accent);
}

/* Member */
.member {
  display: flex;
  gap: 1.5rem;
  align-items: flex-start;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1.75rem;
  max-width: 780px;
}

.member-photo {
  flex-shrink: 0;
  width: 130px;
  aspect-ratio: 4 / 5;
  border-radius: var(--radius);
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
}

.member-photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.member-photo-placeholder {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  font-size: 0.78rem;
  line-height: 1.35;
  color: var(--muted);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background:
    repeating-linear-gradient(45deg, transparent, transparent 10px, rgba(183,172,144,0.06) 10px, rgba(183,172,144,0.06) 20px),
    var(--bg);
}

.member-body h3 { font-size: 1.15rem; margin-bottom: 0.2rem; }
.member-role { color: var(--accent); font-size: 0.9rem; font-weight: 600; margin-bottom: 0.6rem; }
.member-body p:last-child { color: var(--muted); }

/* Publications */
.pub-group { margin-bottom: 2.5rem; }

.pub-group-title {
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  margin-bottom: 1rem;
  padding-bottom: 0.5rem;
  border-bottom: 1px solid var(--border);
}

.pub-list { list-style: none; }

.pub {
  display: flex;
  justify-content: space-between;
  gap: 1.5rem;
  padding: 1.1rem 0;
  border-bottom: 1px solid var(--border);
  flex-wrap: wrap;
}

.pub-title { font-weight: 700; margin-bottom: 0.25rem; }
.pub-authors { color: var(--muted); font-size: 0.92rem; }
.pub-venue { color: var(--muted); font-size: 0.88rem; font-style: italic; }
.pub-note {
  margin-top: 0.5rem;
  font-size: 0.9rem;
  color: var(--text);
  border-left: 2px solid var(--accent);
  padding-left: 0.75rem;
}

.pub-main { flex: 1 1 320px; }

.pub-links {
  display: flex;
  align-items: flex-start;
  gap: 0.5rem;
  flex-wrap: wrap;
}

.pub-pdf, .pub-ext {
  display: inline-block;
  padding: 0.35rem 0.85rem;
  border-radius: var(--radius);
  font-size: 0.82rem;
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
}

.pub-pdf {
  background: linear-gradient(135deg, var(--prairie-gold), var(--deep-amber));
  color: var(--charcoal);
}

.pub-ext {
  border: 1px solid var(--border);
  color: var(--muted);
}

.pub-ext:hover { border-color: var(--accent); color: var(--text); }

/* Portfolio grid */
.portfolio-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 1.25rem;
}

.portfolio-card {
  display: block;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1.75rem 1.5rem;
  text-decoration: none;
  color: inherit;
  transition: border-color 0.2s ease;
}

.portfolio-card:hover { border-color: var(--accent); }

.portfolio-logo {
  height: 120px;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 1rem;
  /* Fixed (not theme-swapped) so it matches --bg's light-mode value in both
     themes: blends in on light, gives dark-text logos a legible backdrop on dark. */
  /*background: #FAF6EC; */
  background: var(--limestone);
  border-radius: var(--radius);
  padding: 0.5rem 1rem;
}

.portfolio-logo img {
  max-height: 100%;
  max-width: 100%;
  object-fit: contain;
}

.portfolio-card h3 { font-size: 1.05rem; margin-bottom: 0.5rem; }
.portfolio-card p { color: var(--muted); font-size: 0.92rem; }

/* Feature grid */
.feature-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 1.25rem;
}

.feature-item {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1.75rem 1.5rem;
}

.feature-item h3 { font-size: 1.05rem; margin-bottom: 0.5rem; }
.feature-item p { color: var(--muted); font-size: 0.92rem; }

/* Options grid */
.options-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 1.25rem;
}

.option-card {
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius);
  padding: 1.5rem;
  background: var(--surface);
}

.option-card h3 { font-size: 1.1rem; margin-bottom: 0.5rem; }
.option-card p { color: var(--muted); font-size: 0.93rem; }

/* Feature figure */
.feature-figure {
  margin: 0 0 2rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--surface);
}

.feature-figure img {
  display: block;
  width: 100%;
  height: auto;
}

.feature-figure figcaption {
  padding: 0.75rem 1rem;
  font-size: 0.85rem;
  color: var(--muted);
}

/* Gallery */
.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 1.5rem;
}

.gallery-item {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
}

.gallery-photo {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  display: block;
}

.gallery-photo--placeholder {
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--muted);
  font-size: 0.85rem;
  letter-spacing: 0.03em;
  background:
    repeating-linear-gradient(45deg, transparent, transparent 12px, rgba(183,172,144,0.06) 12px, rgba(183,172,144,0.06) 24px),
    var(--bg);
  border-bottom: 1px solid var(--border);
}

.gallery-caption { padding: 1.25rem; }
.gallery-caption h3 { font-size: 1.05rem; margin-bottom: 0.4rem; }
.gallery-caption p { color: var(--muted); font-size: 0.9rem; margin-bottom: 0.75rem; }

.gallery-tag {
  display: inline-block;
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--accent);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 0.2rem 0.7rem;
}

/* CTA */
.cta {
  padding: 4.5rem 0;
  text-align: center;
  background: radial-gradient(ellipse 70% 60% at 50% 120%, rgba(124,176,214,0.12) 0%, transparent 70%);
  border-top: 1px solid var(--border);
}

.cta h2 { font-size: 1.6rem; font-weight: 700; margin-bottom: 0.6rem; }
.cta p { color: var(--muted); margin-bottom: 1.75rem; }

/* Footer */
.footer-inner {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  align-items: center;
  text-align: center;
}

.footer-brand {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-weight: 700;
}

.footer-links {
  display: flex;
  gap: 1.25rem;
  flex-wrap: wrap;
  justify-content: center;
}

.footer-links a {
  color: var(--muted);
  text-decoration: none;
  font-size: 0.88rem;
}

.footer-links a:hover { color: var(--text); }

.footer-copy { font-size: 0.82rem; color: var(--muted); }

/* Build version -- admin/debugging visibility only, so keep it quiet.
   Qualified with .site-footer to outrank `.site-footer p`'s font-size. */
.site-footer .footer-version {
  font-size: 0.7rem;
  color: var(--muted);
  opacity: 0.7;
  font-variant-numeric: tabular-nums;
}

/* Mobile */
@media (max-width: 600px) {
  .hero { padding: 4rem 0 3rem; }
  /* Stacked cards outgrow a phone screen, so the waves land below the fold —
     which the layout now handles on its own, no lock to lift. */
  .home-cards { display: block; padding-top: 2.5rem; padding-bottom: 2.5rem; }
  .home-masthead { padding-top: 3rem; }
  .wordmark { font-size: clamp(2.5rem, 13vw, 4rem); }
  .hero-waves { height: 90px; }
  .home-strip { font-size: 0.72rem; gap: 0.45rem; padding-bottom: 0.6rem; }
  .services, .contact { padding: 3rem 0; }
  /* Single column: a 340px min track would overflow a narrow viewport. */
  .service-grid { grid-template-columns: 1fr; gap: 1.25rem; }
  .service-card { padding: 2rem 1.5rem; }
  .card-logo { height: 2.1rem; }
  .section { padding: 3rem 0; }
  .nav { flex-direction: column; align-items: flex-start; gap: 0.75rem; }
  .nav-links { gap: 1rem; }
  .member { flex-direction: column; }
  .pub { flex-direction: column; gap: 0.75rem; }
}

/* ============================================================
   Storefront (3D print listings)
   ============================================================ */

.store-page { padding: 3rem 0 4rem; }

.store-hero { margin-bottom: 2.5rem; }
.store-hero .eyebrow { color: var(--accent); font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; font-size: 0.8rem; }
.store-hero h1 { font-size: clamp(2rem, 4vw, 2.8rem); margin: 0.3rem 0 0.6rem; }
.store-hero .lead { color: var(--muted); max-width: 40rem; font-size: 1.1rem; }

.store-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)); gap: 1.25rem; }

.store-card {
  display: block; padding: 1.5rem; border: 1px solid var(--border);
  border-radius: var(--radius); background: var(--surface);
  color: var(--text); text-decoration: none; transition: border-color 0.15s ease;
}
.store-card:hover { border-color: var(--accent); }
.store-card h3 { margin-bottom: 0.4rem; }
.store-card p { color: var(--muted); font-size: 0.95rem; }

.qty-input { width: 4.5rem; padding: 0.4rem 0.5rem; border: 1px solid var(--border); border-radius: 6px; background: var(--bg); color: var(--text); font: inherit; }

.store-note { color: var(--muted); font-size: 0.9rem; margin-top: 1rem; }

.nav-cart { position: relative; }
.cart-count {
  display: inline-block; margin-left: 0.35rem; min-width: 1.25rem;
  padding: 0 0.35rem; border-radius: 999px; background: var(--accent);
  color: var(--bg); font-size: 0.75rem; font-weight: 700; text-align: center; line-height: 1.35rem;
}
.cart-count[hidden] { display: none; }

/* /bins: the filter form beside a sticky live preview; stacks on narrow screens. */
.bin-layout { display: flex; flex-wrap: wrap; gap: 2rem; align-items: flex-start; }
.bin-config { flex: 2 1 22rem; min-width: 0; }
.bin-preview-pane { flex: 1 1 16rem; position: sticky; top: 1.5rem; }
.bin-preview-figure { margin: 0; }
.bin-preview-figure img { display: block; width: 100%; max-width: 24rem; height: auto; border-radius: var(--radius); border: 1px solid var(--border); background: var(--surface); }
.bin-preview-figure img[hidden] { display: none; }
@media (max-width: 700px) { .bin-preview-pane { position: static; } }

/* Hover-zoom: a floating full-size preview beside any .preview-thumb (mirrors the
   dashboard's catalog/print-list hover). See js/preview-hover.js. */
.preview-thumb { cursor: zoom-in; }
.preview-pop { position: fixed; z-index: 1000; pointer-events: none; padding: 4px;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.25); }
.preview-pop img { display: block; width: 20rem; max-width: 45vw; height: auto; }
.preview-pop[hidden] { display: none; }

.bin-form { max-width: 46rem; }
.bin-axes { display: grid; grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr)); gap: 1rem; }
.bin-axis { display: flex; flex-direction: column; gap: 0.3rem; font-size: 0.9rem; }
.bin-axis select { padding: 0.45rem 0.5rem; border: 1px solid var(--border); border-radius: 6px; background: var(--bg); color: var(--text); font: inherit; }

.bin-colorway { margin: 1.5rem 0; border: 1px solid var(--border); border-radius: var(--radius); padding: 1rem; }
.bin-colorway legend { padding: 0 0.4rem; color: var(--muted); font-size: 0.85rem; }
.bin-colorways { display: grid; grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr)); gap: 0.5rem; }
.bin-colorway-opt { display: flex; align-items: center; gap: 0.5rem; font-size: 0.9rem; }
/* Split top/bottom so it reads unambiguously which color is which: base color
   (the body — only ever gray or black) on the bottom, accent on top, matching
   how the colors sit on the printed bin. */
.cw-swatch { width: 1.4rem; height: 1.4rem; border-radius: 4px; border: 1px solid var(--border); background: linear-gradient(to bottom, var(--accent) 0 50%, var(--base) 50% 100%); }

.bin-add-row { display: flex; align-items: end; gap: 1rem; margin-top: 1rem; }
.bin-add-row label { display: flex; flex-direction: column; gap: 0.3rem; font-size: 0.9rem; }
.bin-summary { margin-top: 1rem; color: var(--muted); }

.bp-form { max-width: 40rem; }
.bp-dims { display: flex; flex-wrap: wrap; gap: 1rem; margin-bottom: 1.25rem; }
.bp-dims label { display: flex; flex-direction: column; gap: 0.3rem; font-size: 0.9rem; }

.kit-price { color: var(--accent); font-weight: 700; margin-top: 0.5rem; }
.kit-price--big { font-size: 1.6rem; }
.kit-contents { margin: 1rem 0 1.5rem 1.2rem; color: var(--muted); }
.kit-contents li { margin: 0.2rem 0; }
.kit-contents li.kit-bin { display: flex; align-items: center; gap: 0.75rem; margin: 0.5rem 0; }
.kit-bin-img { width: 3rem; height: 3rem; flex: none; object-fit: contain; background: var(--surface); border-radius: var(--radius); border: 1px solid var(--border); }
.kit-bin-img[hidden] { display: none; }
.kit-actions { display: flex; flex-wrap: wrap; gap: 0.75rem; }
.btn--ghost { background: transparent; border: 1px solid var(--accent); color: var(--accent); }

.cart-table { width: 100%; border-collapse: collapse; margin-bottom: 1.5rem; }
.cart-table th { text-align: left; color: var(--muted); font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.03em; border-bottom: 1px solid var(--border); padding: 0.5rem 0.5rem; }
.cart-table td { padding: 0.65rem 0.5rem; border-bottom: 1px solid var(--border); vertical-align: middle; }
.cart-remove { background: none; border: none; color: var(--muted); cursor: pointer; text-decoration: underline; font: inherit; }
.cart-item { display: flex; align-items: center; gap: 0.7rem; }
/* min-width:0 lets a long description wrap instead of forcing the row wide. */
.cart-item-text { min-width: 0; }
.cart-thumb { width: 2.75rem; height: 2.75rem; flex: none; object-fit: contain; background: var(--surface); border-radius: 6px; border: 1px solid var(--border); }
.cart-remove:hover { color: var(--accent); }
.cart-actions { display: flex; flex-wrap: wrap; gap: 0.75rem; }

.order-text { width: 100%; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.85rem; line-height: 1.5; padding: 1rem; border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface); color: var(--text); resize: vertical; }
.checkout-actions { display: flex; flex-wrap: wrap; gap: 0.75rem; margin-top: 1rem; }

/* Listing pages: grouped shop hub, photo gallery, rendered pricing, order box. */
.store-group { margin: 2rem 0 0.75rem; font-size: 1rem; letter-spacing: 0.06em; text-transform: uppercase; color: var(--muted); }

.listing-gallery { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 1rem; margin: 1.5rem 0; }
.listing-shot { margin: 0; }
.listing-shot--lead { grid-column: 1 / -1; }
/* height:auto honors the intrinsic width/height, so the row does not jump. */
.listing-shot img { width: 100%; height: auto; display: block; border-radius: var(--radius); border: 1px solid var(--border); }

.listing-pricing { margin: 1.5rem 0; }
.listing-price { font-size: 1.5rem; font-weight: 600; margin: 0; }
.listing-tier { margin: 0.25rem 0 0; color: var(--muted); }

.listing-order { display: flex; flex-direction: column; gap: 0.75rem; align-items: flex-start; max-width: 32rem; margin-top: 1.5rem; }
.listing-field { display: flex; flex-direction: column; gap: 0.25rem; width: 100%; }
.listing-note { width: 100%; font: inherit; padding: 0.5rem; border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface); color: var(--text); resize: vertical; }
.listing-total { font-size: 1.2rem; font-weight: 600; margin: 0; }

/* The note's own line breaks are meaningful. */
.cart-note { display: block; margin-top: 0.25rem; white-space: pre-wrap; color: var(--muted); }
