/* ---------- Fonts ----------
   Self-hosted (not loaded from Google's servers) so no visitor request or
   IP address ever reaches Google — see datenschutz.html. Inter's variable
   font ships one file per subset covering the whole 400–800 weight range. */
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url("Fonts/inter-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url("Fonts/inter-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

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

:root {
  --bg: #0a0b0d;
  --surface: #14171b;
  --surface-2: #1b1f24;
  --border: #262b31;
  --border-soft: rgba(255, 255, 255, 0.1);
  --text: #f4f2ec;
  --text-muted: #9a9d9f;
  --text-faint: rgba(244, 242, 236, 0.45);

  --amber: #e2a13d;
  --amber-dark: #12100b;
  --green: #12332b;
  --green-light: #6fd7a3;
  --rust: #c1552f;
  --cream: #f2ede2;
  --cream-dark: #1c1a15;

  --danger: #ff6b6b;
  --success: #6fd7a3;

  /* mesh gradient stops — full color values so themes can swap them with a single var() */
  --mesh-1: rgba(226, 161, 61, 0.55);
  --mesh-2: rgba(111, 215, 163, 0.28);
  --mesh-3: rgba(193, 85, 47, 0.5);
  --cta-1: rgba(226, 161, 61, 0.35);
  --cta-2: rgba(111, 215, 163, 0.2);

  /* solid bento-tile fills — same idea as the mesh stops above, but opaque
     since they sit behind flat-colored cards rather than layered gradients */
  --tile-2-bg: #12332b;
  --tile-3-bg: #f2ede2;

  /* frosted-glass pill fill used by the nav chrome (nav links, language
     switch, brightness switch, mobile toggle) — a variable rather than a
     hardcoded rgba() so bright mode can flip it from "faint white on dark"
     to "faint dark on light" */
  --nav-chip-bg: rgba(255, 255, 255, 0.08);
  --nav-chip-bg-hover: rgba(255, 255, 255, 0.06);

  /* solid/base fill layered behind the hero mesh, CTA band, and mobile nav
     dropdown — these panels put var()-driven accent gradients on top, but
     the base tone itself was hardcoded near-black; it needs its own
     bright counterpart so the panels don't stay dark when the rest of the
     page goes light. */
  --panel-base-1: #0d1210;
  --panel-base-2: #0a0c0b;
  --watermark-stroke: rgba(244, 242, 236, 0.14);
  --menu-bg: rgba(10, 12, 11, 0.97);

  /* cursor-follow glow on .tilt-card/.cta-band — a light glow reads as a
     highlight on a dark card; bright mode flips it to a dark glow instead,
     since a light glow would barely show up against an already-light card. */
  --glow-color: rgba(255, 255, 255, 0.16);

  /* .glass-card's frosted fill/border — a light sheen on dark reads as
     glass; bright mode flips it to a dark-tinted sheen on light, same idea
     as --nav-chip-bg above, so the demo doesn't sit on the light page like
     a dark-mode widget that forgot to switch. */
  --glass-bg: rgba(20, 23, 27, 0.35);
  --glass-border: rgba(255, 255, 255, 0.18);

  /* .glass-card's cursor-following specular glint (.glass-card::before) —
     a white highlight blended with mix-blend-mode: overlay lights up the
     glass on a dark card; bright mode flips it to a dark tint instead, so
     the same cursor-follow catch darkens the already-light glass rather
     than blowing it out to a wash of white. */
  --glass-highlight: rgba(255, 255, 255, 0.35);

  --radius-lg: 28px;
  --radius-md: 18px;
  --radius-sm: 12px;
  --radius-pill: 999px;

  /* Soft, raised "3D" box shape used across the site's card-like
     components (fact-card, tilt-card, cta-band, the Visuals page's own
     tiles, etc.) — a light/dark shadow pair standing in for a
     neumorphic emboss, so a box's edge fades into the page instead of a
     hard border line. One value for both themes: on a dark page the
     light side dominates, on a bright page the dark side does, so each
     theme still reads as "raised" without needing its own override. */
  --soft-shadow: 6px 6px 16px rgba(0, 0, 0, 0.35), -6px -6px 16px rgba(255, 255, 255, 0.08);

  --max-width: 1120px;
  --font: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;

  --ease: cubic-bezier(0.22, 1, 0.36, 1);
}

html {
  scroll-behavior: smooth;
}

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

body {
  font-family: var(--font);
  background: var(--bg);
  color: var(--text);
  line-height: 1.6;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  padding: 0.9rem;
}

@media (min-width: 720px) {
  body {
    padding: 1.4rem;
  }
}

.skip-link {
  position: fixed;
  top: -100px;
  left: 1rem;
  z-index: 1000;
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 0.65rem 1.1rem;
  font-size: 0.85rem;
  font-weight: 600;
  transition: top 0.2s var(--ease);
}

.skip-link:focus {
  top: 1rem;
}

img,
svg {
  max-width: 100%;
  display: block;
}

a {
  color: inherit;
  text-decoration: none;
}

ul {
  list-style: none;
}

button {
  font-family: inherit;
}

/* ---------- Layout ---------- */
.container {
  width: 100%;
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 0 1.25rem;
}

main {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: clamp(3rem, 6vw, 5.5rem);
}

.main-gap-sm {
  padding-top: 5mm;
  padding-bottom: 5mm;
}

section {
  padding: 0 0;
}

.section-head {
  margin-bottom: 2.25rem;
  max-width: 600px;
}

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--amber);
  background: rgba(226, 161, 61, 0.12);
  border: 1px solid rgba(226, 161, 61, 0.3);
  border-radius: var(--radius-pill);
  padding: 0.4rem 0.9rem 0.4rem 0.7rem;
  margin-bottom: 1.25rem;
}

.eyebrow::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--amber);
  flex-shrink: 0;
}

.section-title {
  font-size: clamp(1.6rem, 3vw, 2.1rem);
  font-weight: 700;
  letter-spacing: -0.02em;
  margin-bottom: 0.6rem;
}

.section-subtitle {
  color: var(--text-muted);
  max-width: 560px;
}

/* ---------- Reveal animation ---------- */
/* Visible by default — script.js opts elements into the hidden
   pre-animation state (.reveal-pending) only once it's actually set up
   the scroll observer, so a page never renders blank below the hero if
   that script fails to load or run. */
[data-reveal] {
  transition: opacity 0.7s var(--ease), transform 0.7s var(--ease);
}

[data-reveal].reveal-pending {
  opacity: 0;
  transform: translateY(18px);
}

[data-reveal].reveal-pending.in-view {
  opacity: 1;
  transform: translateY(0);
}

@media (prefers-reduced-motion: reduce) {
  [data-reveal] {
    transition: none;
  }
}

/* ---------- Hero (mesh gradient card) ---------- */
.mesh {
  position: relative;
  overflow: hidden;
  border-radius: var(--radius-lg);
  background:
    radial-gradient(ellipse 70% 55% at 12% 15%, var(--mesh-1), transparent 60%),
    radial-gradient(ellipse 65% 55% at 88% 10%, var(--mesh-2), transparent 55%),
    radial-gradient(ellipse 85% 65% at 50% 105%, var(--mesh-3), transparent 60%),
    linear-gradient(160deg, var(--panel-base-1) 0%, var(--panel-base-2) 100%);
  transition: background 0.6s ease;
}

.mesh::before,
.art-tile::before,
.contact-card::before {
  content: "";
  position: absolute;
  inset: 0;
  opacity: 0.06;
  mix-blend-mode: overlay;
  pointer-events: none;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='140' height='140'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
}

.hero-inner {
  position: relative;
  padding: 1.1rem 1.1rem clamp(3rem, 8vw, 5rem);
  display: flex;
  flex-direction: column;
  gap: clamp(2.5rem, 8vw, 4.5rem);
}

@media (min-width: 720px) {
  .hero-inner {
    padding: 1.4rem 1.6rem clamp(3.5rem, 8vw, 5.5rem);
  }
}

/* ---------- Hero nav ---------- */
.hero-nav {
  position: relative;
  z-index: 3;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}

.nav-brand {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-weight: 700;
  font-size: 1rem;
  color: var(--text);
  letter-spacing: -0.01em;
}

.brand-logo {
  height: 160px;
  width: auto;
  display: block;
}

.site-footer .brand-logo {
  height: 88px;
  margin-bottom: 0.4rem;
}

.nav-links {
  display: flex;
  align-items: center;
  gap: 0.25rem;
  background: var(--nav-chip-bg);
  border: 1px solid var(--border-soft);
  backdrop-filter: blur(10px);
  border-radius: var(--radius-pill);
  padding: 0.35rem;
}

.nav-links a {
  color: var(--text-faint);
  font-weight: 500;
  font-size: 0.88rem;
  padding: 0.5rem 1rem;
  border-radius: var(--radius-pill);
  white-space: nowrap;
  transition: color 0.15s ease, background 0.15s ease;
}

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

.nav-links a[aria-current="page"] {
  /* --bg, not a fixed dark color — --text flips dark in bright mode, which
     made this pill dark-text-on-dark-background there. --bg always
     contrasts against --text by definition, in either mode. */
  color: var(--bg);
  background: var(--text);
}

.lang-switch {
  position: relative;
}

.lang-switch-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  background: var(--nav-chip-bg);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-pill);
  padding: 0.5rem 0.8rem;
  color: var(--text);
  font-size: 0.8rem;
  font-weight: 700;
  white-space: nowrap;
  cursor: pointer;
  transition: border-color 0.15s ease;
}

.lang-switch-btn:hover {
  border-color: var(--amber);
}

.lang-switch-btn svg {
  transition: transform 0.2s ease;
}

.lang-switch.open .lang-switch-btn svg {
  transform: rotate(180deg);
}

.lang-switch-menu {
  position: absolute;
  top: calc(100% + 0.6rem);
  right: 0;
  background: var(--menu-bg);
  backdrop-filter: blur(10px);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-md);
  padding: 0.4rem;
  min-width: 150px;
  box-shadow: 0 24px 48px -20px rgba(0, 0, 0, 0.65);
  z-index: 30;
  display: none;
}

.lang-switch.open .lang-switch-menu {
  display: block;
}

.lang-option {
  display: flex;
  width: 100%;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  text-align: left;
  padding: 0.6rem 0.75rem;
  border-radius: var(--radius-sm);
  color: var(--text-muted);
  font-size: 0.88rem;
  font-weight: 500;
  background: none;
  border: none;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
}

.lang-option:hover {
  background: var(--nav-chip-bg-hover);
  color: var(--text);
}

.lang-option[aria-current="true"] {
  color: var(--amber);
  font-weight: 700;
}

.lang-flag {
  font-size: 1.15rem;
  line-height: 1;
}

.brightness-switch {
  display: inline-flex;
  align-items: center;
  gap: 0.15rem;
  background: var(--nav-chip-bg);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-pill);
  padding: 0.3rem;
}

.brightness-option {
  background: none;
  border: none;
  border-radius: var(--radius-pill);
  padding: 0.35rem 0.7rem;
  color: var(--text-faint);
  font-size: 0.78rem;
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
}

.brightness-option:hover {
  color: var(--text);
}

.brightness-option[aria-current="true"] {
  /* --amber/--amber-dark (not --text) — --text flips dark in bright mode,
     which made the active pill dark-text-on-dark-background there */
  background: var(--amber);
  color: var(--amber-dark);
}

.nav-actions {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.6rem;
}

.nav-utility-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.nav-actions-row {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

.nav-toggle {
  display: none;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: var(--radius-pill);
  background: var(--nav-chip-bg);
  border: 1px solid var(--border-soft);
  color: var(--text);
  cursor: pointer;
}

.nav-toggle .burger,
.nav-toggle .burger::before,
.nav-toggle .burger::after {
  content: "";
  display: block;
  width: 16px;
  height: 2px;
  background: currentColor;
  border-radius: 2px;
  transition: transform 0.2s ease, opacity 0.2s ease, background 0.2s ease;
}

.nav-toggle .burger {
  position: relative;
}

.nav-toggle .burger::before,
.nav-toggle .burger::after {
  position: absolute;
  left: 0;
}

.nav-toggle .burger::before {
  top: -5px;
}

.nav-toggle .burger::after {
  top: 5px;
}

.hero-nav.open .nav-toggle .burger {
  background: transparent;
}

.hero-nav.open .nav-toggle .burger::before {
  transform: translateY(5px) rotate(45deg);
}

.hero-nav.open .nav-toggle .burger::after {
  transform: translateY(-5px) rotate(-45deg);
}

/* The full inline nav (logo + 5 links + language switcher + CTA) needs more
   room than a phone-width breakpoint would suggest — collapsing to the
   hamburger menu this early avoids the links squeezing and wrapping
   mid-word, which is especially ugly for CJK labels that have no spaces
   to break at. */
@media (max-width: 899px) {
  .nav-links {
    position: absolute;
    top: calc(100% + 0.75rem);
    left: 0;
    right: 0;
    flex-direction: column;
    align-items: stretch;
    background: var(--panel-base-2);
    border-radius: var(--radius-md);
    padding: 0.6rem;
    box-shadow: 0 24px 48px -20px rgba(0, 0, 0, 0.65);
    display: none;
    gap: 0.25rem;
  }

  .hero-nav.open .nav-links {
    display: flex;
  }

  .nav-links a {
    text-align: center;
    padding: 0.7rem 1rem;
  }

  .nav-toggle {
    display: inline-flex;
  }
}

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.8rem 1.5rem;
  border-radius: var(--radius-pill);
  font-weight: 600;
  font-size: 0.92rem;
  border: 1px solid transparent;
  cursor: pointer;
  transition: transform 0.15s var(--ease), background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
  white-space: nowrap;
}

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

.btn-primary {
  /* --bg, not a fixed dark color — same fix as .nav-links a[aria-current],
     same reason: --text flips dark in bright mode. */
  background: var(--text);
  color: var(--bg);
}

.btn-primary:hover {
  background: var(--amber);
  color: var(--amber-dark);
}

.btn-secondary {
  background: transparent;
  border-color: var(--border-soft);
  color: var(--text);
}

.btn-secondary:hover {
  border-color: var(--amber);
  color: var(--amber);
}

.btn-sm {
  padding: 0.6rem 1.1rem;
  font-size: 0.85rem;
}

/* ---------- Hero content ---------- */
.hero-top {
  position: relative;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: clamp(1.5rem, 4vw, 3rem);
  flex-wrap: wrap-reverse;
}

.hero-portrait {
  flex: none;
  width: clamp(144px, 21vw, 210px);
  height: clamp(144px, 21vw, 210px);
  border-radius: 50%;
  overflow: hidden;
  border: 1px solid var(--border);
  /* Glow is offset up-and-right to echo the mesh gradient's nearest light
     blob (--mesh-2, anchored top-right) rather than sitting as a flat,
     directionless ring. */
  box-shadow:
    0 20px 45px -18px rgba(0, 0, 0, 0.45),
    4px -16px 36px 2px color-mix(in srgb, var(--amber) 24%, transparent),
    0 14px 24px -6px color-mix(in srgb, var(--amber) 12%, transparent);
  transition: box-shadow 0.4s ease, transform 0.3s var(--ease);
}

.hero-portrait:hover {
  transform: scale(1.04);
  box-shadow:
    0 24px 50px -16px rgba(0, 0, 0, 0.5),
    5px -20px 44px 4px color-mix(in srgb, var(--amber) 34%, transparent),
    0 16px 28px -4px color-mix(in srgb, var(--amber) 18%, transparent);
}

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

.hero-content {
  position: relative;
  z-index: 2;
  max-width: 640px;
}

.hero-content h1 {
  font-size: clamp(2.3rem, 5.4vw, 3.6rem);
  font-weight: 700;
  letter-spacing: -0.03em;
  line-height: 1.08;
  margin-bottom: 1.1rem;
}

.hero-content h1 .muted {
  color: var(--text-faint);
}

.hero-content > p {
  color: var(--text-muted);
  font-size: 1.08rem;
  max-width: 500px;
  margin-bottom: 2rem;
}

.hero-actions {
  display: flex;
  gap: 1rem;
  flex-wrap: wrap;
}

.hero-more {
  margin-top: 1.25rem;
  margin-bottom: 0;
  font-size: 0.95rem;
  color: var(--text-muted);
}

.hero-more a {
  color: var(--text-muted);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.hero-more a:hover {
  color: var(--text);
}

/* ---------- Mockup panel (floats below hero) ---------- */
.mockup-wrap {
  margin-top: clamp(-3.5rem, -7vw, -2.5rem);
  position: relative;
  z-index: 3;
}

.browser-mockup {
  background: linear-gradient(160deg, var(--surface), var(--bg));
  border: none;
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--soft-shadow);
}

.bm-topbar {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.75rem 1rem;
  background: var(--surface-2);
  border-bottom: 1px solid var(--border);
}

.bm-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--border);
}

.bm-address {
  flex: 1;
  margin-left: 0.5rem;
  background: var(--bg);
  border-radius: var(--radius-pill);
  padding: 0.35rem 0.9rem;
  font-size: 0.75rem;
  color: var(--text-muted);
}

.bm-body {
  padding: clamp(1.1rem, 3vw, 2rem);
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
}

.bm-chart {
  display: flex;
  align-items: flex-end;
  gap: 0.5rem;
  height: 90px;
  padding: 0 0.2rem;
}

.bm-chart span {
  flex: 1;
  border-radius: 6px 6px 2px 2px;
  background: linear-gradient(180deg, var(--amber), rgba(226, 161, 61, 0.25));
}

.bm-list {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

.bm-list-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  font-size: 0.85rem;
  padding-bottom: 0.75rem;
  border-bottom: 1px solid var(--border);
}

.bm-list-item:last-child {
  border-bottom: none;
  padding-bottom: 0;
}

.bm-list-item .label {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  color: var(--text);
  font-weight: 500;
}

.bm-list-item .icon-dot {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--surface-2);
  border: 1px solid var(--border);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--amber);
}

.bm-list-item .value {
  color: var(--text-muted);
}

/* ---------- Site preview thumbnails ----------
   Most previews are static first-screen stills — cheaper to load than a
   live embed and immune to a sample's own scroll-hijacking or animation
   state. The iframe variant (below) is reserved for the one preview that
   stays a real live page: the iframe is sized to 250% of its wrapper on
   both axes, then scaled back down by 0.4 with a top-left transform-origin,
   so the visible slice always fills the wrapper exactly regardless of its
   actual rendered width. */
.site-preview .bm-body {
  padding: 0;
}

.iframe-preview {
  position: relative;
  overflow: hidden;
  height: 300px;
}

.iframe-preview a {
  display: block;
  width: 100%;
  height: 100%;
}

.iframe-preview img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top;
  transition: transform 0.3s var(--ease);
}

.iframe-preview a:hover img,
.iframe-preview a:focus-visible img {
  transform: scale(1.03);
}

.iframe-preview iframe {
  position: absolute;
  top: 0;
  left: 0;
  width: 250%;
  height: 250%;
  border: 0;
  transform: scale(0.4);
  transform-origin: 0 0;
  pointer-events: none;
}

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

.bento-tile {
  border-radius: var(--radius-lg);
  padding: 1.9rem;
  min-height: 220px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 1.5rem;
  transition: transform 0.2s var(--ease), box-shadow 0.2s ease;
  border: none;
  box-shadow: var(--soft-shadow);
}

.bento-tile:hover {
  transform: translateY(-3px);
}

.bento-tile .icon {
  width: 42px;
  height: 42px;
  border-radius: var(--radius-sm);
  display: flex;
  align-items: center;
  justify-content: center;
}

.bento-tile h3 {
  font-size: 1.15rem;
  margin-bottom: 0.5rem;
}

.bento-tile p {
  font-size: 0.92rem;
}

.bento-amber {
  background: var(--amber);
  color: var(--amber-dark);
}

.bento-amber .icon {
  background: rgba(18, 16, 11, 0.12);
  color: var(--amber-dark);
}

.bento-amber p {
  color: rgba(18, 16, 11, 0.75);
}

.bento-green {
  background: var(--tile-2-bg);
  color: var(--cream);
}

.bento-green .icon {
  background: rgba(255, 255, 255, 0.1);
  color: var(--amber);
}

.bento-green p {
  color: rgba(242, 237, 226, 0.7);
}

.bento-cream {
  background: var(--tile-3-bg);
  color: var(--cream-dark);
}

.bento-cream .icon {
  background: rgba(28, 26, 21, 0.08);
  color: var(--cream-dark);
}

.bento-cream p {
  color: rgba(28, 26, 21, 0.68);
}

.bento-rust {
  background: var(--rust);
  color: var(--cream);
}

.bento-rust .icon {
  background: rgba(255, 255, 255, 0.12);
  color: var(--cream);
}

.bento-rust p {
  color: rgba(242, 237, 226, 0.75);
}

/* ---------- Stats band ---------- */
.stats-band {
  background: linear-gradient(160deg, var(--surface), var(--bg));
  border: none;
  border-radius: var(--radius-lg);
  box-shadow: var(--soft-shadow);
  padding: clamp(2rem, 5vw, 3rem);
  display: flex;
  flex-direction: column;
  gap: 2.5rem;
}

.stats-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
  gap: 1.5rem;
}

.stat-item strong {
  display: block;
  font-size: clamp(1.8rem, 4vw, 2.4rem);
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--amber);
}

.stat-item span {
  color: var(--text-muted);
  font-size: 0.88rem;
}

.pull-quote {
  border-top: 1px solid var(--border);
  padding-top: 2rem;
  font-size: clamp(1.1rem, 2.4vw, 1.4rem);
  font-weight: 500;
  letter-spacing: -0.01em;
  color: var(--text);
  max-width: 680px;
}

.principles-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 1.75rem;
  margin: 2rem 0 2.25rem;
}

.principle-block h3 {
  font-size: 1rem;
  margin: 0 0 0.5rem;
  color: var(--amber);
}

.principle-block p {
  margin: 0;
  color: var(--text-muted);
  font-size: 0.92rem;
  line-height: 1.6;
}

/* ---- About page: "Proof from the floor" story ---- */
.proof-story {
  max-width: 720px;
}

.proof-story h2 {
  font-size: clamp(1.5rem, 3vw, 2rem);
  margin: 0.9rem 0 1.1rem;
  letter-spacing: -0.01em;
}

.proof-story p {
  color: var(--text-muted);
  font-size: 1.05rem;
  line-height: 1.75;
}

/* ---- About page: pull-quote inline with a timeline track ---- */
.timeline-pull-quote {
  border-top: none;
  padding-top: 0;
  margin: 0.5rem 0 2rem;
  font-size: 1.05rem;
}

/* ---- About page: "Who this is for / not" ---- */
.fit-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 2.5rem;
}

.fit-column h3 {
  font-size: 1.1rem;
  margin: 0 0 1rem;
}

.fit-column ul {
  list-style: none;
  margin: 0 0 1.25rem;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.65rem;
}

.fit-column li {
  position: relative;
  padding-left: 1.5rem;
  color: var(--text-muted);
  font-size: 0.95rem;
  line-height: 1.5;
}

.fit-column li::before {
  position: absolute;
  left: 0;
  font-weight: 700;
}

.fit-for li::before {
  content: "✓";
  color: var(--amber);
}

.fit-not li::before {
  content: "✕";
  color: var(--text-faint);
}

/* ---------- Zigzag showcase ---------- */
.zigzag {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2.5rem;
  align-items: center;
}

@media (min-width: 860px) {
  .zigzag {
    grid-template-columns: 1fr 1fr;
    gap: 4rem;
  }

  .zigzag.reverse .zigzag-media {
    order: 2;
  }
}

.zigzag-copy .tag-list {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 1.25rem;
}

.tag {
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--amber);
  background: rgba(226, 161, 61, 0.12);
  border: 1px solid rgba(226, 161, 61, 0.25);
  border-radius: var(--radius-pill);
  padding: 0.3rem 0.8rem;
}

a.tag {
  text-decoration: none;
  transition: background 0.15s ease, border-color 0.15s ease;
}

a.tag:hover,
a.tag:focus-visible {
  background: rgba(226, 161, 61, 0.22);
  border-color: rgba(226, 161, 61, 0.4);
}

.zigzag-copy .index {
  color: var(--text-faint);
  font-size: 0.85rem;
  font-weight: 600;
  margin-bottom: 0.75rem;
  display: block;
}

.zigzag-copy h3 {
  font-size: clamp(1.4rem, 3vw, 1.9rem);
  letter-spacing: -0.02em;
  margin-bottom: 0.9rem;
}

.zigzag-copy p {
  color: var(--text-muted);
}

.zigzag-copy .btn {
  margin-top: 1.25rem;
}

.work-stack {
  display: flex;
  flex-direction: column;
  gap: clamp(3rem, 6vw, 5rem);
}

.work-more {
  margin-top: clamp(2rem, 5vw, 3rem);
}

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

.card {
  background: linear-gradient(160deg, var(--surface), var(--bg));
  border: none;
  border-radius: var(--radius-lg);
  box-shadow: var(--soft-shadow);
  padding: 1.75rem;
  transition: box-shadow 0.15s ease, transform 0.15s var(--ease);
}

.card:hover {
  box-shadow: var(--soft-shadow), 0 0 0 1px var(--amber) inset;
  transform: translateY(-2px);
}

.card h3 {
  font-size: 1.1rem;
  margin-bottom: 0.5rem;
}

.card p {
  color: var(--text-muted);
  font-size: 0.95rem;
}

.card .tag-list {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 1rem;
}

/* ---------- Info box (callout paragraph) ---------- */
.info-box {
  background: linear-gradient(160deg, var(--surface-2), var(--bg));
  border: none;
  border-radius: var(--radius-lg);
  box-shadow: var(--soft-shadow);
  padding: 1.5rem 1.75rem;
  margin-top: 1.25rem;
}

.info-box p {
  margin: 0;
}

.section-lead-in {
  padding-top: 15mm;
}

.section-action {
  margin-top: 1.25rem;
}

.section-action a:not(.btn) {
  color: var(--text-muted);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.section-action a:not(.btn):hover {
  color: var(--text);
}

.timeline-toggle-wrap {
  margin-top: 1.5rem;
}

/* ---------- Fact card (About hero: plain dl replacing the browser mockup) ---------- */
.fact-card {
  background: linear-gradient(160deg, var(--surface), var(--bg));
  border: none;
  border-radius: var(--radius-lg);
  padding: clamp(1.1rem, 3vw, 2rem);
  box-shadow: var(--soft-shadow);
  margin: 0;
}

.fact-card dt,
.fact-card dd {
  margin: 0;
}

/* ---------- Toolbox short stack ---------- */
.stack-groups {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
}

.stack-group h3 {
  font-size: 0.95rem;
  font-weight: 600;
  margin-bottom: 0.75rem;
  color: var(--text-faint);
}

.experience-note {
  margin-top: 1.5rem;
}

/* ---------- CTA / watermark band ---------- */
.cta-band {
  position: relative;
  overflow: hidden;
  container-type: inline-size;
  border-radius: var(--radius-lg);
  background:
    radial-gradient(ellipse 70% 80% at 80% 0%, var(--cta-1), transparent 60%),
    radial-gradient(ellipse 70% 80% at 10% 100%, var(--cta-2), transparent 55%),
    var(--panel-base-1);
  box-shadow: var(--soft-shadow);
  padding: clamp(3rem, 8vw, 5rem) 1.5rem clamp(2rem, 6vw, 3rem);
  text-align: center;
  transition: background 0.6s ease;
}

/* Same cursor-following glare as .tilt-card, minus the tilt itself.
   pointer-events: none — being the only positioned element in here
   without its own z-index, it paints above the plain, unpositioned
   "Get in touch" link and would otherwise swallow its clicks even at
   opacity: 0. */
.cta-band::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: radial-gradient(circle at var(--mx, 50%) var(--my, 50%), var(--glow-color), transparent 45%);
  opacity: 0;
  transition: opacity 0.25s ease;
  pointer-events: none;
}

.cta-band:hover::before,
.cta-band:focus-within::before { opacity: 1; }

.cta-band h2 {
  position: relative;
  z-index: 2;
  font-size: clamp(1.8rem, 4.5vw, 2.8rem);
  font-weight: 700;
  letter-spacing: -0.02em;
  margin-bottom: 1rem;
}

.cta-band p {
  position: relative;
  z-index: 2;
  color: var(--text-muted);
  max-width: 480px;
  margin: 0 auto 2rem;
}

.cta-watermark {
  position: relative;
  z-index: 2;
  margin-top: clamp(2rem, 6vw, 4rem);
  /* fallback for browsers without container query units */
  font-size: clamp(1.8rem, 8vw, 5.5rem);
  /* scales to the band's own width so the full name always fits, however narrow or wide the card is */
  font-size: clamp(1.8rem, 11cqi, 6.5rem);
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 1;
  color: transparent;
  -webkit-text-stroke: 1px var(--watermark-stroke);
  white-space: nowrap;
}

/* ---------- About page specific ---------- */
.timeline {
  border-left: 2px solid var(--border);
  padding-left: 1.75rem;
  display: flex;
  flex-direction: column;
  gap: 2.25rem;
}

.timeline-item {
  position: relative;
}

.timeline-extra {
  display: flex;
  flex-direction: column;
  gap: 2.25rem;
}

/* An author rule setting `display` always beats the UA default
   `[hidden] { display: none }`, regardless of specificity — so without
   this, the `hidden` attribute above does nothing and the section stays
   visible. */
.timeline-extra[hidden] {
  display: none;
}

.timeline-item::before {
  content: "";
  position: absolute;
  left: -2.05rem;
  top: 0.3rem;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--amber);
  border: 3px solid var(--bg);
}

.timeline-item:nth-child(2)::before {
  background: var(--green-light);
}

.timeline-item:nth-child(3)::before {
  background: var(--rust);
}

.timeline-item:nth-child(4)::before {
  background: var(--cream);
}

/* Two-track timeline (About page): a track label sits between .timeline-item
   siblings, which would throw off the nth-child color cycling above (it
   counts ALL children of .timeline, not just .timeline-item ones) — so this
   variant keeps every dot the same accent color instead of guessing at a
   cycle that no longer lines up with position. */
.timeline-tracks .timeline-item::before {
  background: var(--amber);
}

.timeline-track-label {
  color: var(--amber);
  font-size: 0.8rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin: 0;
}

.timeline-item h3,
.timeline-item h4 {
  font-size: 1.05rem;
  margin-bottom: 0.25rem;
}

.timeline-date {
  color: var(--amber);
  font-size: 0.85rem;
  font-weight: 600;
  margin-bottom: 0.4rem;
  display: block;
}

.timeline-item p {
  color: var(--text-muted);
  font-size: 0.95rem;
}

.tag-cloud {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
}

/* ---------- Contact page specific ---------- */
.contact-layout {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.5rem;
}

/* Narrow screens: form first, then the "What you get back" steps, then
   contact details — so a visitor sees the form without scrolling past a
   lecture first, and the steps still land above contact details as on
   desktop. Desktop instead uses named grid areas (steps full-width across
   the top, details/form split below), so this ordering is reset back to
   auto there. */
.form-card {
  order: -1;
}

.contact-steps {
  order: 0;
}

.contact-card {
  order: 1;
}

@media (min-width: 780px) {
  .contact-layout {
    grid-template-columns: 0.85fr 1.15fr;
    grid-template-areas:
      "steps   steps"
      "details form";
    align-items: start;
  }

  .contact-steps { grid-area: steps; order: initial; }
  .contact-card { grid-area: details; order: initial; }
  .form-card { grid-area: form; order: initial; }
}

.contact-card {
  position: relative;
  overflow: hidden;
  border-radius: var(--radius-lg);
  padding: clamp(1.75rem, 4vw, 2.5rem);
  display: flex;
  flex-direction: column;
  gap: 1.75rem;
  /* var(--text)/var(--panel-base-*), not fixed cream/near-black — this
     card was still hardcoded dark-only, unlike .mesh/.cta-band which
     already switch with bright mode. */
  color: var(--text);
  background:
    radial-gradient(ellipse 90% 60% at 8% -10%, var(--cta-1), transparent 60%),
    radial-gradient(ellipse 80% 70% at 105% 115%, var(--cta-2), transparent 55%),
    linear-gradient(165deg, var(--panel-base-1) 0%, var(--panel-base-2) 100%);
  border: none;
  box-shadow: var(--soft-shadow);
  transition: background 0.6s ease;
}

.contact-card h2 {
  position: relative;
  z-index: 2;
  font-size: 1.35rem;
  font-weight: 700;
  letter-spacing: -0.01em;
}

.contact-card > p {
  position: relative;
  z-index: 2;
  color: var(--text-muted);
  font-size: 0.95rem;
}

.contact-card ul {
  position: relative;
  z-index: 2;
  display: flex;
  flex-direction: column;
}

.contact-card li {
  display: flex;
  gap: 1rem;
  align-items: center;
  padding: 1rem 0;
  border-bottom: 1px solid var(--border-soft);
}

.contact-card li:first-child {
  padding-top: 0.25rem;
}

.contact-card li:last-child {
  padding-bottom: 0.25rem;
  border-bottom: none;
}

.contact-card .icon-dot {
  width: 40px;
  height: 40px;
  border-radius: var(--radius-sm);
  background: linear-gradient(135deg, var(--amber), color-mix(in srgb, var(--amber) 45%, black));
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  color: var(--amber-dark);
  box-shadow: 0 10px 20px -10px rgba(0, 0, 0, 0.55);
  transition: background 0.3s ease;
}

.contact-text {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
}

.contact-label {
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-faint);
}

.contact-value {
  font-size: 0.98rem;
  font-weight: 600;
  color: var(--text);
}

.contact-card li a.contact-value:hover {
  color: var(--amber);
}

/* "What you get back" — 3 static boxes sitting above the Contact details
   card (not embedded inside it); each box's raised look comes from the
   same --soft-shadow every other card on the site uses (see .steps-grid /
   .step-box further down), so no card wrapper is needed here. */
.contact-steps > h3 {
  font-size: 0.8rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-faint);
  margin: 0 0 1rem;
}

.contact-steps .section-action {
  margin-top: 1.1rem;
}

.form-card {
  background: linear-gradient(160deg, var(--surface), var(--bg));
  border: none;
  border-radius: var(--radius-lg);
  box-shadow: var(--soft-shadow);
  padding: clamp(1.5rem, 4vw, 2.25rem);
}

form {
  display: flex;
  flex-direction: column;
  gap: 1.25rem;
}

.form-group {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

label {
  font-size: 0.88rem;
  font-weight: 600;
}

input,
textarea {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 0.75rem 1rem;
  color: var(--text);
  font-family: inherit;
  font-size: 0.95rem;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

input:focus,
textarea:focus {
  outline: none;
  border-color: var(--amber);
  box-shadow: 0 0 0 3px rgba(226, 161, 61, 0.15);
}

textarea {
  resize: vertical;
  min-height: 140px;
}

.error-message {
  color: var(--danger);
  font-size: 0.82rem;
  min-height: 1.1em;
}

.form-privacy-note {
  margin: 0.9rem 0 0;
  font-size: 0.8rem;
  color: var(--text-faint);
}

.form-privacy-note a {
  color: var(--text-muted);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.form-privacy-note a:hover {
  color: var(--text);
}

.form-status {
  border-radius: var(--radius-sm);
  padding: 0.9rem 1.1rem;
  font-size: 0.9rem;
  font-weight: 500;
  display: none;
}

.form-status.visible {
  display: block;
}

.form-status.success {
  background: rgba(111, 215, 163, 0.12);
  color: var(--success);
  border: 1px solid rgba(111, 215, 163, 0.3);
}

.form-status.error {
  background: rgba(255, 107, 107, 0.12);
  color: var(--danger);
  border: 1px solid rgba(255, 107, 107, 0.3);
}

input.invalid,
textarea.invalid {
  border-color: var(--danger);
}

/* ---------- Legal page ---------- */
.legal {
  display: flex;
  flex-direction: column;
  gap: 2.5rem;
  max-width: 720px;
}

.legal-block h2 {
  font-size: 1.15rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  margin-bottom: 0.6rem;
}

.legal-block p {
  color: var(--text-muted);
  font-size: 0.95rem;
  line-height: 1.75;
}

.legal-block p a {
  color: var(--amber);
  text-decoration: underline;
  text-underline-offset: 2px;
}

.legal-block p a:hover {
  color: var(--text);
}

/* ---------- AI journey page ---------- */
.tool-cell {
  display: flex;
  align-items: center;
  gap: 0.85rem;
}

.logo-mark {
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 14px 26px -14px rgba(0, 0, 0, 0.7);
}

.tool-cell .logo-mark {
  width: 40px;
  height: 40px;
  border-radius: 12px;
  flex-shrink: 0;
}

.tool-info {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
}

.tool-link {
  font-size: 0.92rem;
  font-weight: 600;
  color: var(--text);
  transition: color 0.15s ease;
}

.tool-link:hover {
  color: var(--amber);
}

.logo-company {
  display: block;
  font-size: 0.7rem;
  color: var(--text-faint);
  font-weight: 500;
}

.mark-claude {
  background: linear-gradient(135deg, #da7756, #b6552f);
}

.mark-chatgpt {
  background: linear-gradient(135deg, #12a37f, #0c7a5f);
}

.mark-grok {
  background: linear-gradient(135deg, #2b2b2f, #050505);
  border: 1px solid rgba(255, 255, 255, 0.15);
}

.mark-cursor {
  background: linear-gradient(135deg, #3a3a3f, #101012);
  border: 1px solid rgba(255, 255, 255, 0.1);
}

.mark-gemini {
  background: linear-gradient(135deg, #4c8dff, #a855f7 60%, #f2a33d);
}

.mark-copilot {
  background: linear-gradient(135deg, #1b8bd0, #7b2ff7 60%, #e0479e);
}

.mark-ollama {
  background: linear-gradient(135deg, #4a5568, #1a202c);
  border: 1px solid rgba(255, 255, 255, 0.1);
}

.usage-badges {
  position: absolute;
  top: 1.25rem;
  right: 1.25rem;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.35rem;
  transform: translateZ(30px);
}

.usage-badge {
  font-size: 0.62rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  padding: 0.22rem 0.55rem;
  border-radius: var(--radius-pill);
  white-space: nowrap;
}

.usage-daily {
  background: rgba(226, 161, 61, 0.15);
  color: var(--amber);
  border: 1px solid rgba(226, 161, 61, 0.3);
}

.usage-referee {
  background: rgba(76, 141, 255, 0.15);
  color: #4c8dff;
  border: 1px solid rgba(76, 141, 255, 0.3);
}

.usage-local {
  background: rgba(111, 215, 163, 0.15);
  color: var(--green-light);
  border: 1px solid rgba(111, 215, 163, 0.3);
}

.disclaimer {
  margin-top: 1.5rem;
  padding-top: 1.25rem;
  border-top: 1px solid var(--border);
  color: var(--text-faint);
  font-size: 0.8rem;
  line-height: 1.7;
  max-width: 760px;
}

.rule-list {
  list-style: none;
  margin: 1.5rem 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

.rule-list li {
  position: relative;
  padding-left: 1.5rem;
  color: var(--text-muted);
}

.rule-list li::before {
  content: "→";
  position: absolute;
  left: 0;
  color: var(--amber);
  font-weight: 700;
}

/* ---------- AI journey: shop-floor workflow strip ---------- */
.workflow-strip {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 1rem;
  margin-top: 1.5rem;
}

.workflow-step {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  background: linear-gradient(160deg, var(--surface-2), var(--bg));
  border: none;
  border-radius: var(--radius-lg);
  box-shadow: var(--soft-shadow);
  padding: 0.9rem 1.25rem;
  font-weight: 600;
  font-size: 0.92rem;
}

.workflow-num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--amber);
  color: var(--bg);
  font-size: 0.75rem;
  font-weight: 700;
  flex-shrink: 0;
}

.workflow-arrow {
  color: var(--text-faint);
  font-size: 1.2rem;
}

@media (max-width: 640px) {
  .workflow-strip {
    flex-direction: column;
    align-items: stretch;
  }

  .workflow-arrow {
    transform: rotate(90deg);
    text-align: center;
  }
}

/* ---------- AI journey: local lab callout ---------- */
.info-box.local-lab h3 {
  font-size: 0.95rem;
  font-weight: 700;
  color: var(--amber);
  margin-bottom: 0.5rem;
}

.info-box.local-lab p {
  margin: 0;
}

/* ---------- AI journey: prompt → result demo ---------- */
.prompt-demo {
  margin-top: 1.5rem;
}

.prompt-demo-prompt {
  font-size: 0.95rem;
  color: var(--text-muted);
  margin-bottom: 1.25rem;
}

.prompt-demo-outputs {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 1rem;
  margin-bottom: 1.25rem;
}

.prompt-demo-output {
  background: linear-gradient(160deg, var(--surface-2), var(--bg));
  border: none;
  border-radius: var(--radius-lg);
  box-shadow: var(--soft-shadow);
  padding: 1rem 1.25rem;
}

.prompt-demo-tag {
  display: block;
  font-size: 0.68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-faint);
  margin-bottom: 0.5rem;
}

.prompt-demo-output p {
  font-size: 0.88rem;
  color: var(--text-muted);
  font-style: italic;
  margin: 0;
}

.prompt-demo-final {
  background: rgba(226, 161, 61, 0.08);
  border: none;
  border-radius: var(--radius-lg);
  box-shadow: var(--soft-shadow), 0 0 0 1px rgba(226, 161, 61, 0.3) inset;
  padding: 1.1rem 1.35rem;
}

.prompt-demo-tag-final {
  color: var(--amber);
}

.prompt-demo-final p {
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--text);
  margin: 0;
  font-style: normal;
}

/* ---------- AI journey: changelog ---------- */
.changelog-list {
  list-style: none;
  margin: 1.5rem 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}

.changelog-list li {
  font-size: 0.92rem;
  color: var(--text-muted);
}

.changelog-date {
  color: var(--amber);
  font-weight: 600;
}

/* ---------- AI journey: closing promise list ---------- */
.promise-list {
  list-style: none;
  margin: 1.25rem auto 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  max-width: 560px;
}

.promise-list li {
  color: var(--text-muted);
}

.promise-list li::before {
  content: "✓ ";
  color: var(--amber);
  font-weight: 700;
}

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

.art-tile-wrap {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}

.art-tile-apply-own {
  width: 100%;
  justify-content: center;
}

.art-tile {
  position: relative;
  aspect-ratio: 1;
  /* Same soft, raised shape as .rgb-row above (see that rule's comment) —
     big rounded corners and a light/dark shadow pair instead of a hard
     border, so the tile's edge fades into the page. The tile's own
     gradient-study background (set inline per tile) still supplies all
     of its color, unlike .rgb-row — this only changes the frame. */
  border-radius: var(--radius-lg);
  overflow: hidden;
  border: none;
  box-shadow: var(--soft-shadow);
  padding: 0;
  font: inherit;
  color: inherit;
  cursor: pointer;
  outline-offset: 3px;
  transition: transform 0.15s var(--ease), outline-color 0.3s ease, box-shadow 0.2s ease;
}

.art-tile:hover {
  transform: translateY(-3px);
}

.art-tile:focus-visible,
.art-tile[aria-pressed="true"] {
  outline: 2px solid var(--amber);
}

.art-tile-hint {
  position: absolute;
  top: 0.6rem;
  right: 0.6rem;
  font-size: 0.7rem;
  font-weight: 600;
  color: rgba(244, 242, 236, 0.85);
  background: rgba(0, 0, 0, 0.45);
  border-radius: var(--radius-pill);
  padding: 0.25rem 0.6rem;
  opacity: 0;
  transition: opacity 0.2s ease;
}

.art-tile:hover .art-tile-hint,
.art-tile:focus-visible .art-tile-hint {
  opacity: 1;
}

.art-tile[aria-pressed="true"] .art-tile-hint {
  opacity: 1;
  background: var(--amber);
  color: #10120f;
}

/* AI Journey page themes are applied via inline custom properties set in
   script.js (see THEME_VARS) rather than CSS attribute selectors — more
   reliably repainted across browsers, Safari included. */

.art-caption {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 0.7rem 0.9rem;
  font-size: 0.78rem;
  font-weight: 600;
  color: rgba(244, 242, 236, 0.9);
  background: linear-gradient(180deg, transparent, rgba(0, 0, 0, 0.6));
}

.custom-study {
  margin-top: 1.25rem;
  display: grid;
  grid-template-columns: minmax(160px, 220px) 1fr;
  gap: 1.5rem;
  align-items: start;
}

/* The Bright group's tiles are light previews (genuinely what each one
   applies), unlike their dark-swatched siblings in the Dark group — the
   caption/hint need a light-side scrim and dark text instead of the
   default light-on-dark. */
.art-tile-light .art-caption {
  color: rgba(28, 26, 21, 0.85);
  background: linear-gradient(180deg, transparent, rgba(255, 255, 255, 0.75));
}

.art-tile-light .art-tile-hint {
  color: rgba(28, 26, 21, 0.8);
  background: rgba(255, 255, 255, 0.55);
}

.art-tile-light[aria-pressed="true"] .art-tile-hint {
  background: var(--amber);
  color: #10120f;
}

.rgb-panel {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 0.85rem;
}

.rgb-note {
  grid-column: 1 / -1;
  color: var(--text-faint);
  font-size: 0.8rem;
  line-height: 1.6;
  margin: 0;
}

.rgb-row {
  /* Soft, raised "channel strip" shape — after the mixer boxes (Vocals,
     Drums, etc.) in sample-sites/107/softdesk4.html: big rounded corners
     and a light/dark shadow pair standing in for its neumorphic --raise-lg,
     so the box's edge fades into the page instead of a hard line. Shape
     only — the palette stays this site's own --surface/--bg. --rgb-frame-color
     (set by script.js from the mixer's current Accent A value, so all three
     frames tint together as that color changes) now rides along as a soft
     inset ring rather than a solid border; the var(--border) fallback
     covers before JS runs. */
  background: linear-gradient(160deg, var(--surface), var(--bg));
  border: none;
  border-radius: var(--radius-lg);
  box-shadow: var(--soft-shadow), 0 0 0 1px var(--rgb-frame-color, var(--border)) inset;
  padding: 1rem 1.1rem 1.25rem;
  margin: 0;
  transition: box-shadow 0.2s ease;
}

.rgb-row legend {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0 0.35rem;
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--text-muted);
}

.rgb-swatch {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 1px solid rgba(244, 242, 236, 0.25);
  display: inline-block;
}

.rgb-sliders {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin-top: 0.5rem;
}

.rgb-slider {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.72rem;
  font-weight: 600;
  color: var(--text-faint);
}

/* "Rocking" sliders — a raised thumb sitting in a grooved, inset track,
   inspired by the neumorphic mixer look in sample-sites/107/softdesk4.html
   (reskinned onto native <input type="range"> rather than that page's
   custom drag-built knobs/faders, so focus, keyboard control, and
   screen-reader semantics all keep working for free). */
.rgb-slider input[type="range"] {
  flex: 1;
  max-width: 88px;
  height: 18px;
  margin: 0;
  padding: 0;
  -webkit-appearance: none;
  appearance: none;
  background: transparent;
  accent-color: var(--amber);
  cursor: pointer;
}

.rgb-slider input[type="range"]::-webkit-slider-runnable-track {
  height: 6px;
  border-radius: var(--radius-pill);
  background: var(--surface-2);
  box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.5), inset 0 -1px 0 rgba(255, 255, 255, 0.05);
}

.rgb-slider input[type="range"]::-moz-range-track {
  height: 6px;
  border-radius: var(--radius-pill);
  background: var(--surface-2);
  box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.5), inset 0 -1px 0 rgba(255, 255, 255, 0.05);
}

.rgb-slider input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 17px;
  height: 17px;
  margin-top: -5.5px;
  border-radius: 50%;
  background: linear-gradient(160deg, #fff6e3, var(--amber));
  border: 1px solid rgba(0, 0, 0, 0.3);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.55), 0 0 0 3px rgba(0, 0, 0, 0.12), inset 0 1px 1px rgba(255, 255, 255, 0.65);
  transition: box-shadow 0.15s ease, transform 0.1s ease;
}

.rgb-slider input[type="range"]::-moz-range-thumb {
  width: 17px;
  height: 17px;
  border-radius: 50%;
  background: linear-gradient(160deg, #fff6e3, var(--amber));
  border: 1px solid rgba(0, 0, 0, 0.3);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.55), 0 0 0 3px rgba(0, 0, 0, 0.12), inset 0 1px 1px rgba(255, 255, 255, 0.65);
  transition: box-shadow 0.15s ease, transform 0.1s ease;
}

.rgb-slider input[type="range"]:hover::-webkit-slider-thumb,
.rgb-slider input[type="range"]:focus-visible::-webkit-slider-thumb {
  transform: scale(1.15);
}

.rgb-slider input[type="range"]:hover::-moz-range-thumb,
.rgb-slider input[type="range"]:focus-visible::-moz-range-thumb {
  transform: scale(1.15);
}

.rgb-slider input[type="range"]:active::-webkit-slider-thumb {
  transform: scale(0.94);
}

.rgb-slider input[type="range"]:active::-moz-range-thumb {
  transform: scale(0.94);
}

/* Per-channel glow, so R/G/B read at a glance rather than just by their
   letter label — fixed red/green/blue, independent of the active theme. */
.rgb-slider input[data-channel="r"]::-webkit-slider-thumb { box-shadow: 0 1px 2px rgba(0, 0, 0, 0.55), 0 0 9px 1px rgba(255, 90, 90, 0.65), inset 0 1px 1px rgba(255, 255, 255, 0.65); }
.rgb-slider input[data-channel="g"]::-webkit-slider-thumb { box-shadow: 0 1px 2px rgba(0, 0, 0, 0.55), 0 0 9px 1px rgba(90, 220, 120, 0.65), inset 0 1px 1px rgba(255, 255, 255, 0.65); }
.rgb-slider input[data-channel="b"]::-webkit-slider-thumb { box-shadow: 0 1px 2px rgba(0, 0, 0, 0.55), 0 0 9px 1px rgba(90, 140, 255, 0.65), inset 0 1px 1px rgba(255, 255, 255, 0.65); }
.rgb-slider input[data-channel="r"]::-moz-range-thumb { box-shadow: 0 1px 2px rgba(0, 0, 0, 0.55), 0 0 9px 1px rgba(255, 90, 90, 0.65), inset 0 1px 1px rgba(255, 255, 255, 0.65); }
.rgb-slider input[data-channel="g"]::-moz-range-thumb { box-shadow: 0 1px 2px rgba(0, 0, 0, 0.55), 0 0 9px 1px rgba(90, 220, 120, 0.65), inset 0 1px 1px rgba(255, 255, 255, 0.65); }
.rgb-slider input[data-channel="b"]::-moz-range-thumb { box-shadow: 0 1px 2px rgba(0, 0, 0, 0.55), 0 0 9px 1px rgba(90, 140, 255, 0.65), inset 0 1px 1px rgba(255, 255, 255, 0.65); }

.rgb-value {
  min-width: 2ch;
  text-align: right;
  font-variant-numeric: tabular-nums;
  color: var(--text-muted);
}

@media (max-width: 640px) {
  .custom-study {
    grid-template-columns: 1fr;
  }

  .custom-study-swatch {
    aspect-ratio: 16 / 9;
  }

  .rgb-panel {
    grid-template-columns: 1fr;
  }
}

/* ---------- Footer ---------- */
.site-footer {
  margin-top: 6mm;
  border-top: 1px solid var(--border);
  padding: 2rem 1.25rem 0.5rem;
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
}

.footer-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1.25rem 2rem;
}

.footer-nav {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.75rem;
}

.footer-nav a {
  color: var(--text-muted);
  font-size: 0.9rem;
  font-weight: 500;
  transition: color 0.15s ease;
}

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

.footer-nav a[aria-current="page"] {
  color: var(--amber);
}

.footer-bottom {
  border-top: 1px solid var(--border);
  padding: 1.25rem 0;
  color: var(--text-faint);
  font-size: 0.82rem;
  text-align: center;
}

/* ---------- Blog ---------- */
.post-date {
  display: block;
  font-size: 0.78rem;
  color: var(--text-faint);
  font-weight: 600;
  margin-bottom: 0.6rem;
}

.back-link {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  color: var(--text-muted);
  font-size: 0.9rem;
  font-weight: 600;
  margin-bottom: 1.5rem;
  transition: color 0.15s ease;
}

.back-link:hover {
  color: var(--amber);
}

.post-meta {
  display: flex;
  gap: 0.5rem;
  flex-wrap: wrap;
  align-items: center;
  color: var(--text-muted);
  font-size: 0.9rem;
  margin-bottom: 1.5rem;
}

.post-meta .sep {
  color: var(--text-faint);
}

.prose {
  max-width: 720px;
  color: var(--text);
  font-size: 1.03rem;
  line-height: 1.85;
}

.prose h2 {
  font-size: 1.5rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  margin: 2.5rem 0 1rem;
}

.prose h3 {
  font-size: 1.2rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  margin: 2rem 0 0.75rem;
}

.prose p {
  margin-bottom: 1.25rem;
  color: var(--text-muted);
}

.prose a {
  color: var(--amber);
  text-decoration: underline;
  text-underline-offset: 2px;
}

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

.prose strong {
  color: var(--text);
  font-weight: 700;
}

.prose ul,
.prose ol {
  margin: 0 0 1.25rem 1.25rem;
  color: var(--text-muted);
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.prose li {
  margin-left: 0.5rem;
}

.prose blockquote {
  border-left: 3px solid var(--amber);
  padding: 0.25rem 0 0.25rem 1.25rem;
  margin: 1.75rem 0;
  color: var(--text-muted);
  font-style: italic;
}

.prose code {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 0.15rem 0.4rem;
  font-size: 0.88em;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  color: var(--amber);
}

.prose pre {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 1.25rem;
  overflow-x: auto;
  margin: 1.75rem 0;
}

.prose pre code {
  background: none;
  border: none;
  padding: 0;
  color: var(--text);
}

.prose hr {
  border: none;
  border-top: 1px solid var(--border);
  margin: 2.5rem 0;
}

.prose img {
  border-radius: var(--radius-md);
  margin: 1.5rem 0;
}

/* ---------- Utility ---------- */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* ---------- Experiment page ---------- */
.mesh-live { min-height: 420px; }

/* WebGL canvases are GPU-composited and can bypass an ancestor's
   overflow:hidden + border-radius clip in some browsers, painting as a
   hard-edged rectangle even though .mesh itself is rounded. Neither
   border-radius nor clip-path applied directly to the canvas reliably
   fixes this (Firefox ignored both), and masking the shape inside the
   fragment shader itself turned out to break in its own way on some real
   GPUs (a corner-radius mismatch shrank the visible paint well below the
   canvas's actual size). What does hold across browsers: clipping via an
   extra wrapper element the canvas merely fills, rather than clipping the
   canvas's own GPU layer directly. */
.mesh-clip {
  position: absolute;
  inset: 0;
  overflow: hidden;
  border-radius: inherit;
  isolation: isolate;
}

#shader-canvas {
  display: block;
  width: 100%;
  height: 100%;
}

.hero-scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(105deg, rgba(10, 11, 13, 0.8) 0%, rgba(10, 11, 13, 0.45) 40%, rgba(10, 11, 13, 0.1) 70%);
  pointer-events: none;
}

/* This hero sits on the shader canvas + the dark .hero-scrim above, which
   stay dark-toned regardless of site theme — but "Bright" mode (the
   default for new visitors) flips --text/--text-muted/--text-faint to
   dark colors meant for the light page background used everywhere else.
   That put dark text on a dark backdrop here. Pin this hero to its own
   light values, a shade brighter than the plain dark-mode defaults for
   extra margin against a busy, moving background. */
.mesh-live .hero-content {
  --text: #f4f2ec;
  --text-muted: #f4f2ec;
  --text-faint: rgba(244, 242, 236, 0.75);
  /* .btn-primary swaps --text/--bg for an inverted look. Bright mode sets
     --bg to a near-white cream on <body>, which combined with the light
     --text pinned above made the button nearly invisible (light-on-light)
     against this always-dark hero. Pin --bg to the site's dark default too,
     so the button stays a light pill with dark text here regardless of
     site-wide brightness mode. */
  --bg: #0a0b0d;
}

/* Dark mode only: mute the hero's two lead paragraphs to a medium-dark
   grey instead of the near-white cream .mesh-live .hero-content pins
   above — that cream reads fine but flattens them to the same brightness
   as the headline. Left alone in Bright mode, where that cream is already
   doing load-bearing contrast work against this hero's always-dark
   backdrop. */
body[data-brightness="dark"] .mesh-live .hero-content .hero-lead {
  color: #8a8a86;
}

.tech-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 1.5rem;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.tech-tags span,
.tech-tags a {
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-pill);
  padding: 0.3rem 0.75rem;
  background: rgba(255, 255, 255, 0.05);
}

/* The linked tags (every technique below the hero shader itself) double as
   an in-page index — a visible hover/focus state is what tells them apart
   from the one plain, unlinked "WebGL / GLSL" label describing the hero. */
.tech-tags a {
  transition: color 0.15s ease, border-color 0.15s ease;
}

.tech-tags a:hover,
.tech-tags a:focus-visible {
  color: var(--amber);
  border-color: var(--amber);
}

.demo-frame {
  position: relative;
  border-radius: var(--radius-lg);
  border: none;
  box-shadow: var(--soft-shadow);
  background: linear-gradient(160deg, var(--surface), var(--bg));
  overflow: hidden;
}

.demo-hint {
  position: absolute;
  top: 0.8rem;
  left: 0.9rem;
  z-index: 3;
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--text-faint);
  background: rgba(10, 11, 13, 0.55);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-pill);
  padding: 0.3rem 0.7rem;
  pointer-events: none;
}

.demo-hint-static {
  position: static;
  display: inline-block;
  background: none;
  border: none;
  padding: 0;
  margin-top: 1.25rem;
}

/* The "when I'd ship this" line under each demo — buyer-facing context,
   not another technical caption, so it's styled like body copy rather
   than the small-caps .demo-hint pills above. */
.demo-ship-note {
  margin: 1.25rem 0 0;
  font-size: 0.88rem;
  color: var(--text-muted);
}

.demo-ship-note strong {
  color: var(--text);
  font-weight: 600;
}

.canvas-demo { position: relative; height: min(56vh, 440px); }
.canvas-demo canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }

/* Tilt cards */
.tilt-stage {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 1.5rem;
  padding: clamp(1.75rem, 4vw, 3rem);
  background:
    radial-gradient(ellipse 60% 50% at 20% 20%, var(--mesh-1), transparent 60%),
    radial-gradient(ellipse 60% 50% at 80% 80%, var(--mesh-2), transparent 60%);
}

.tilt-card {
  position: relative;
  aspect-ratio: 4 / 5;
  border-radius: var(--radius-lg);
  border: none;
  box-shadow: var(--soft-shadow);
  background: linear-gradient(155deg, var(--surface-2), var(--surface));
  padding: 1.25rem;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  transform-style: preserve-3d;
  will-change: transform;
  transition: transform 0.5s var(--ease);
  cursor: pointer;
}

.tilt-card::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: radial-gradient(circle at var(--mx, 50%) var(--my, 50%), var(--glow-color), transparent 45%);
  opacity: 0;
  transition: opacity 0.25s ease;
  pointer-events: none;
}

.tilt-card:hover::before,
.tilt-card:focus-visible::before { opacity: 1; }

.tilt-card .num { font-size: 0.72rem; font-weight: 700; color: var(--amber); transform: translateZ(30px); }
.tilt-card h3 { font-size: 1rem; margin: 0.4rem 0 0.2rem; transform: translateZ(30px); }
.tilt-card .desc { font-size: 0.8rem; color: var(--text-faint); transform: translateZ(20px); }

/* Contact page: "What you get back" steps (see .contact-steps above) as
   plain static boxes — the raised look comes from the same dual-direction
   --soft-shadow every other card on the site uses, not from the
   pointer-tilt .tilt-card mechanic, so nothing moves on hover. */
.steps-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 0.9rem;
}

.step-box {
  border-radius: var(--radius-md);
  background: linear-gradient(155deg, var(--surface-2), var(--surface));
  box-shadow: var(--soft-shadow);
  padding: 1.1rem 1.25rem;
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}

.step-box .num { font-size: 0.72rem; font-weight: 700; color: var(--amber); }
.step-box h3 { font-size: 0.95rem; font-weight: 600; margin: 0; color: var(--text); }
.step-box .desc { font-size: 0.85rem; color: var(--text-muted); line-height: 1.5; }

/* Tool cards (AI Journey page) reuse the same tilt/glare mechanic above,
   just with room for real content instead of a one-line demo caption. */
.tools-stage {
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
}

.tilt-card.tool-card {
  aspect-ratio: auto;
  justify-content: flex-start;
  gap: 1.1rem;
  padding: 1.5rem;
}

.tool-card .tool-cell {
  transform: translateZ(30px);
}

.tool-card-body {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  transform: translateZ(15px);
}

.tool-card-label {
  font-size: 0.68rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-faint);
  margin-top: 0.6rem;
}

.tool-card-label:first-child {
  margin-top: 0;
}

.tool-card-text {
  font-size: 0.86rem;
  color: var(--text-muted);
  line-height: 1.6;
}

/* Kinetic type */
.kinetic-frame { padding: clamp(2rem, 6vw, 3rem) clamp(1.25rem, 5vw, 2.5rem); }

.kinetic-headline {
  font-size: clamp(1.35rem, 3.6vw, 2rem);
  line-height: 1.3;
  margin: 0;
}

.kinetic-word {
  display: inline-block;
  opacity: 0;
  filter: blur(6px);
  transform: translateY(0.35em);
  transition: opacity 0.6s var(--ease), filter 0.6s var(--ease), transform 0.6s var(--ease);
}

.kinetic-frame.in-view .kinetic-word { opacity: 1; filter: blur(0); transform: translateY(0); }

.scramble {
  color: var(--amber);
  cursor: pointer;
  border-bottom: 1px dashed rgba(226, 161, 61, 0.5);
}

/* Glass panel */
.glass-stage {
  position: relative;
  height: min(52vh, 420px);
  display: flex;
  align-items: center;
  justify-content: center;
  background:
    radial-gradient(ellipse 55% 55% at 30% 30%, var(--mesh-1), transparent 60%),
    radial-gradient(ellipse 55% 55% at 75% 70%, var(--mesh-2), transparent 60%),
    radial-gradient(ellipse 60% 60% at 50% 100%, var(--mesh-3), transparent 65%),
    var(--surface);
}

.glass-card {
  position: relative;
  width: min(80%, 360px);
  padding: 1.6rem 1.5rem;
  border-radius: var(--radius-lg);
  border: 1px solid var(--glass-border);
  background: var(--glass-bg);
  backdrop-filter: blur(18px) saturate(140%);
  -webkit-backdrop-filter: blur(18px) saturate(140%);
  box-shadow: var(--soft-shadow);
  overflow: hidden;
}

.glass-card::before {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(220px circle at var(--gx, 50%) var(--gy, 30%), var(--glass-highlight), transparent 60%);
  mix-blend-mode: overlay;
  pointer-events: none;
}

.glass-card .stat-num { margin: 0 0 0.9rem; font-size: 1.9rem; font-weight: 700; color: var(--text); }
.glass-card-copy { margin: 0; font-size: 0.85rem; color: var(--text-muted); }

/* ---- Experiment page: Lab / Shop-floor mode switch ---- */
.experiment-mode-bar {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.65rem;
  text-align: center;
  padding-bottom: 0.5rem;
}

.experiment-mode-switch {
  display: inline-flex;
  gap: 0.15rem;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  padding: 0.3rem;
}

.experiment-mode-option {
  background: none;
  border: none;
  border-radius: var(--radius-pill);
  padding: 0.4rem 1.1rem;
  color: var(--text-faint);
  font-size: 0.82rem;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
}

.experiment-mode-option:hover { color: var(--text); }

.experiment-mode-option[aria-current="true"] {
  background: var(--amber);
  color: var(--amber-dark);
}

.experiment-mode-caption {
  margin: 0;
  max-width: 46ch;
  font-size: 0.85rem;
  color: var(--text-faint);
}

/* Shop-floor mode: every demo below collapses to what I'd actually ship a
   Handwerk/Mittelstand client — static gradient instead of the shader, no
   particles or flow field, cards that lift instead of tilting in 3D, no
   scramble, glass without the pointer-chasing highlight. The canvases'
   own rAF loops also pause underneath this (see isShopFloor()/
   shopFloorRefreshers in script.js) — hiding them here means the page
   genuinely simplifies rather than just looking paused. */
body.mode-shopfloor #shader-canvas,
body.mode-shopfloor #particles-canvas,
body.mode-shopfloor #flowfield-canvas,
body.mode-shopfloor .demo-hint,
body.mode-shopfloor .demo-inspector,
body.mode-shopfloor .flowfield-actions {
  display: none;
}

body.mode-shopfloor .kinetic-word {
  opacity: 1;
  filter: blur(0);
  transform: translateY(0);
  transition: none;
}

body.mode-shopfloor .scramble {
  color: inherit;
  cursor: text;
  border-bottom: none;
  pointer-events: none;
}

body.mode-shopfloor .tilt-card {
  transition: transform 0.2s var(--ease);
}

body.mode-shopfloor .tilt-card:hover,
body.mode-shopfloor .tilt-card:focus-visible {
  transform: translateY(-2px);
}

body.mode-shopfloor .tilt-card::before {
  display: none;
}

body.mode-shopfloor .glass-card::before {
  display: none;
}

/* ---- Experiment page: canvas inspector chips ---- */
.demo-inspector {
  position: absolute;
  right: 0.75rem;
  bottom: 0.75rem;
  z-index: 3;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.4rem;
}

.demo-inspector-toggle {
  font-family: ui-monospace, "SF Mono", "Cascadia Code", Consolas, monospace;
  font-size: 0.68rem;
  letter-spacing: 0.02em;
  color: var(--text-faint);
  background: rgba(10, 11, 13, 0.55);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-pill);
  padding: 0.3rem 0.7rem;
  cursor: pointer;
  transition: color 0.15s ease, border-color 0.15s ease;
}

.demo-inspector-toggle:hover,
.demo-inspector-toggle:focus-visible {
  color: var(--text);
  border-color: var(--amber);
}

.demo-inspector-detail {
  max-width: 220px;
  font-size: 0.76rem;
  line-height: 1.45;
  color: var(--text);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 0.65rem 0.8rem;
  box-shadow: var(--soft-shadow);
}

.demo-inspector-detail[hidden] { display: none; }

/* ---- Experiment page: live theme swatches under the hero ---- */
.hero-theme-swatches {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-top: 1.5rem;
}

.hero-theme-swatches + .hero-theme-swatches {
  margin-top: 0.6rem;
}

.theme-swatch-group-label {
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-faint);
  margin-right: 0.15rem;
}

.theme-swatch {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  border: 2px solid var(--border-soft);
  cursor: pointer;
  padding: 0;
  transition: border-color 0.15s ease, transform 0.15s ease;
}

.theme-swatch:hover,
.theme-swatch:focus-visible {
  border-color: var(--text);
  transform: scale(1.08);
}

.theme-swatch[data-theme-swatch="warm"] {
  background: linear-gradient(135deg, #e2a13d, #c1552f);
}

.theme-swatch[data-theme-swatch="growth"] {
  background: linear-gradient(135deg, #6fd7a3, #12332b);
}

.theme-swatch[data-theme-swatch="signal"] {
  background: linear-gradient(135deg, #4c8dff, #a855f7);
}

.theme-swatch[data-theme-swatch-bright="warm"] {
  background: linear-gradient(135deg, #d4841c, #6fd7a3);
}

.theme-swatch[data-theme-swatch-bright="cool"] {
  background: linear-gradient(135deg, #5b7fd6, #96aae6);
}

.theme-swatch[data-theme-swatch-bright="cold"] {
  background: linear-gradient(135deg, #2fa9a6, #96d2d6);
}

.theme-swatch-own {
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--text-muted);
  white-space: nowrap;
  text-decoration: underline;
  text-underline-offset: 3px;
}

.theme-swatch-own:hover { color: var(--text); }

.theme-swatches-caption {
  margin: 0.6rem 0 0;
  max-width: 500px;
  font-size: 0.85rem;
  color: var(--text-faint);
}

/* ---- Experiment page: magnetic button (the "10% version") ---- */
.magnetic-stage {
  height: min(30vh, 220px);
  display: flex;
  align-items: center;
  justify-content: center;
  background:
    radial-gradient(ellipse 60% 60% at 50% 50%, var(--mesh-1), transparent 65%),
    var(--surface);
}

.magnetic-btn {
  transition: transform 0.15s var(--ease);
  will-change: transform;
}

/* ---- Experiment page: hybrid tilt + glass card ---- */
.hybrid-stage {
  grid-template-columns: minmax(220px, 360px);
  justify-content: center;
}

/* 30% more transparent than the standalone .glass-card demo above, per
   request — scoped to this card only via color-mix so it tracks dark/bright
   mode's --glass-bg instead of duplicating it. */
.hybrid-card.glass-card {
  background: color-mix(in srgb, var(--glass-bg) 70%, transparent);
}

.magnetic-note { margin-top: 1.25rem; }

/* ---- Experiment page: flow field interactivity ---- */
.flowfield-actions {
  margin-top: 1rem;
  display: flex;
  align-items: center;
  gap: 0.75rem;
  flex-wrap: wrap;
}

.flowfield-actions .demo-hint-static { margin-top: 0; }

/* ---- Experiment page: lab note ---- */
.lab-note {
  display: flex;
  gap: 0.75rem;
  align-items: flex-start;
  border-radius: var(--radius-lg);
  border: 1px dashed var(--border);
  background: var(--surface-2);
  padding: 1.1rem 1.25rem;
}

.lab-note-icon { font-size: 1.1rem; line-height: 1; }

.lab-note h3 {
  margin: 0 0 0.35rem;
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.lab-note p { margin: 0; font-size: 0.9rem; color: var(--text-muted); }
.lab-note code { font-size: 0.85em; color: var(--text); }

@media (prefers-reduced-motion: reduce) {
  .tilt-card, .kinetic-word, .magnetic-btn { transition-duration: 0.01ms !important; }
  /* .kinetic-word normally starts blurred/invisible until scrolled into
     view (see .kinetic-frame.in-view above) — a composed still for
     reduced motion means the headline reads as already-resolved text,
     not a scroll-gated reveal a static view might catch mid-transition. */
  .kinetic-word {
    opacity: 1;
    filter: blur(0);
    transform: translateY(0);
  }
}

/* ---------- Sample page viewer ----------
   A deliberately minimal, non-scrolling wrapper around a sample-sites/
   demo — no nav, no hero, no scroll-reveal — just a static header (back
   link + label), a one-line disclaimer, and an iframe onto the actual
   sample, which scrolls on its own. */
.sample-page {
  height: 100dvh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.sample-page-header {
  flex: 0 0 auto;
  display: flex;
  align-items: baseline;
  gap: 1.25rem;
  padding: 0.9rem clamp(1rem, 4vw, 2rem);
  background: var(--surface);
  border-bottom: 1px solid var(--border);
}

.sample-page-header .back-link {
  margin-bottom: 0;
}

.sample-page-title {
  font-weight: 700;
}

.sample-page-name {
  color: var(--text-muted);
  font-weight: 500;
}

.sample-page-disclaimer {
  flex: 0 0 auto;
  margin: 0;
  padding: 0.6rem clamp(1rem, 4vw, 2rem);
  background: var(--surface-2);
  border-bottom: 1px solid var(--border);
  color: var(--text-faint);
  font-size: 0.78rem;
}

.sample-page-main {
  flex: 1 1 auto;
  min-height: 0;
}

.sample-page-main iframe {
  width: 100%;
  height: 100%;
  border: 0;
  display: block;
}
