/* ============================================================
   Design lock Nordic Precision & Muted Spruce
   Objentic — preview/nordic.css
   Light tokens are locked; dark mode (html.dark) is spruce-night.
   The ONLY hex values in this file are the 20 locked tokens.
   Every other color is derived from a token, transparent, or
   black-alpha (reserved for the primary button overlay).

   --spruce is the ACCENT: it is read as text and as borders on the canvas,
   so it must stay light enough to see in dark mode. --spruce-fill is a
   SURFACE: it sits behind off-white text, so it must be dark enough to
   read. One token cannot do both; in dark mode that conflict put white on
   #6b9a78, a 2.94:1 failure on every primary button. Keep them apart.
   ============================================================ */

@import url('https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700;800&family=JetBrains+Mono:wght@400;500;600&display=swap');

:root {
  --bg-canvas: #f4f5f2;
  --bg-surface: #e9eae4;
  --bg-card: #ffffff;
  --text-main: #1a1d1a;
  --text-muted: #5c645d;
  --border-color: #d6d9ce;
  --spruce: #2d5a3d;
  --spruce-hover: #1e3f2b;
  /* Light mode keeps the original fill values, so nothing changes here. */
  --spruce-fill: #2d5a3d;
  --spruce-fill-hover: #1e3f2b;
}

html.dark {
  --bg-canvas: #141814;
  --bg-surface: #1c221e;
  --bg-card: #222a24;
  --text-main: #eef0ea;
  --text-muted: #9aa49b;
  --border-color: #2f3932;
  --spruce: #6b9a78;
  --spruce-hover: #8fb89a;
  /* Darker than the accent so #f4f5f2 text clears 4.5:1 (5.26:1 on the
     base, 6.29:1 under the hover overlay, 7.47:1 active). Still vivid
     against the #141814 canvas. */
  --spruce-fill: #456f52;
  --spruce-fill-hover: #4c785a;
}

/* ---------- Base ---------- */

html {
  scroll-behavior: smooth;
}

html {
  overflow-x: hidden;
}

html,
body {
  background-color: var(--bg-canvas);
  color: var(--text-main);
  font-family: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
}

body {
  overflow-x: visible;
  min-width: 0;
}

/* Scoped under html so this beats Tailwind's single-class .font-mono
   utility. The Play CDN injects its <style> after this sheet, so at equal
   specificity Tailwind won and every .font-mono element silently rendered
   in the system mono stack while only the .cal-* components (explicit
   font-family, no .font-mono class) got JetBrains Mono. */
html .font-mono,
html code,
html pre {
  font-family: 'JetBrains Mono', 'Fira Code', monospace;
}

/* Solid sticky header — solid canvas, no blur, no glass. */
.sticky-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background-color: var(--bg-canvas);
  border-bottom: 1px solid var(--border-color);
}

::selection {
  background-color: var(--spruce-fill);
  color: white;
}

.quiz-check {
  accent-color: var(--spruce);
}


/* ---------- Utility classes ---------- */

.bg-canvas { background-color: var(--bg-canvas); }
.bg-surface { background-color: var(--bg-surface); }
.bg-card { background-color: var(--bg-card); }

.text-ink { color: var(--text-main); }
.text-mute { color: var(--text-muted); }
.text-spruce { color: var(--spruce); }

.border-line { border-color: var(--border-color); }

.bg-spruce { background-color: var(--spruce); }
.hover-spruce:hover { background-color: var(--spruce-fill-hover); }

.btn-primary {
  background-color: var(--spruce-fill);
  color: #f4f5f2;
  border: 1px solid transparent;
  border-radius: 0.5rem;
  font-weight: 600;
  transition: background-color 0.15s ease, box-shadow 0.15s ease;
}
.btn-primary:hover {
  /* black-alpha overlay reserved for the primary button only */
  background-image: linear-gradient(rgba(0, 0, 0, 0.18), rgba(0, 0, 0, 0.18));
  background-color: var(--spruce-fill-hover);
}
.btn-primary:active {
  background-image: linear-gradient(rgba(0, 0, 0, 0.28), rgba(0, 0, 0, 0.28));
}

.btn-secondary {
  background-color: var(--bg-card);
  color: var(--text-main);
  border: 1px solid var(--border-color);
  border-radius: 0.5rem;
  font-weight: 500;
  transition: border-color 0.15s ease, background-color 0.15s ease;
}
.btn-secondary:hover {
  border-color: var(--spruce);
  color: var(--spruce);
}

.card {
  background-color: var(--bg-card);
  border: 1px solid var(--border-color);
  border-radius: 0.75rem;
}

.chip {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  background-color: var(--bg-surface);
  border: 1px solid var(--border-color);
  color: var(--text-muted);
  border-radius: 9999px;
  padding: 0.25rem 0.75rem;
  font-size: 0.75rem;
}

.nav-active {
  color: var(--spruce);
  background-color: var(--bg-surface);
  border: 1px solid var(--border-color);
}

/* ---------- Page sections ---------- */

.page-section {
  display: none !important;
}

.page-section.active {
  display: block !important;
  animation: sectionFade 0.25s ease-in-out;
}

@keyframes sectionFade {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: translateY(0); }
}

/* ---------- Node pulse: spruce glow ---------- */

.node-pulse {
  position: relative;
  /* Applied to workflow cards: keep the card background, add a spruce
     border and an animated spruce glow. No full spruce fill. */
  background-color: var(--bg-card);
  border: 2px solid var(--spruce);
  animation: nodePulse 2.4s ease-in-out infinite;
}

@keyframes nodePulse {
  0%, 100% {
    box-shadow: 0 0 0 0 color-mix(in srgb, var(--spruce) 45%, transparent);
  }
  50% {
    box-shadow: 0 0 0 6px color-mix(in srgb, var(--spruce) 12%, transparent);
  }
}

.site-logo-wrap {
  display: inline-flex;
  align-items: center;
  height: 2rem;
  flex-shrink: 0;
}

.site-logo {
  height: 2rem;
  width: auto;
  display: block;
  flex-shrink: 0;
  max-width: none;
}

.site-logo-dark {
  display: none;
}

html.dark .site-logo-light {
  display: none;
}

html.dark .site-logo-dark {
  display: block;
}

/* ---------- Header crowding helper ---------- */

.nav-compact {
  white-space: nowrap;
}

/* The header row must never exceed its container. The nav is the only child
   allowed to absorb a shortfall (its breakpoint is in CSS pixels and does not
   scale with a larger browser base font), so a big default font can never
   squeeze the logo or push the page sideways. */
.header-row {
  min-width: 0;
}

.site-nav-wrap {
  min-width: 0;
  flex: 1 1 auto;
  overflow-x: auto;
  scrollbar-width: none;
  -ms-overflow-style: none;
}

.site-nav-wrap::-webkit-scrollbar {
  display: none;
}

/* ---------- Calendar / days / slots (token-driven, theme-safe) ---------- */

.cal-strip {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(0, 1fr);
  gap: 0.5rem;
}

.cal-day {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-between;
  gap: 0.375rem;
  padding: 0.5rem;
  border-radius: 0.75rem;
  background-color: var(--bg-card);
  border: 1px solid var(--border-color);
  color: var(--text-main);
  text-align: center;
  transition: border-color 0.15s ease, background-color 0.15s ease, box-shadow 0.15s ease;
}

.cal-day:hover {
  border-color: var(--spruce);
}

.cal-day.active {
  border-color: var(--spruce);
  background-color: var(--bg-surface);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--spruce) 55%, transparent);
}

.cal-day-name {
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.625rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-muted);
  font-weight: 600;
}

.cal-day-num {
  font-size: 0.875rem;
  font-weight: 700;
  color: var(--text-main);
}

.cal-badge {
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.5625rem;
  font-weight: 500;
  padding: 0.125rem 0.375rem;
  border-radius: 9999px;
  background-color: var(--bg-surface);
  border: 1px solid var(--border-color);
  color: var(--text-muted);
  white-space: nowrap;
}

.cal-badge-open {
  background-color: color-mix(in srgb, var(--spruce) 12%, transparent);
  border-color: color-mix(in srgb, var(--spruce) 35%, transparent);
  color: var(--spruce);
}

.cal-badge-low {
  background-color: var(--bg-surface);
  border-color: var(--spruce);
  color: var(--spruce);
  font-weight: 700;
}

.cal-capacity {
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.625rem;
  padding: 0.125rem 0.5rem;
  border-radius: 9999px;
  background-color: color-mix(in srgb, var(--spruce) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--spruce) 35%, transparent);
  color: var(--spruce);
}

.cal-slots-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0.625rem;
}

@media (min-width: 640px) {
  .cal-slots-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

.cal-slot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 0.75rem;
  border-radius: 0.75rem;
  text-align: left;
  background-color: var(--bg-card);
  border: 1px solid color-mix(in srgb, var(--spruce) 40%, transparent);
  color: var(--text-main);
  transition: border-color 0.15s ease, background-color 0.15s ease;
}

.cal-slot:hover {
  border-color: var(--spruce);
  background-color: var(--bg-surface);
}

.cal-slot > span:first-child {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.cal-slot-time {
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.75rem;
  font-weight: 700;
  color: var(--text-main);
}

.cal-slot:hover .cal-slot-time {
  color: var(--spruce);
}

.cal-slot-meta {
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.625rem;
  color: var(--text-muted);
  margin-top: 0.125rem;
}

.cal-slot-cta {
  font-size: 0.6875rem;
  font-weight: 600;
  padding: 0.25rem 0.5rem;
  border-radius: 0.375rem;
  background-color: color-mix(in srgb, var(--spruce) 12%, transparent);
  color: var(--spruce);
  white-space: nowrap;
  flex-shrink: 0;
  transition: background-color 0.15s ease, color 0.15s ease;
}

.cal-slot:hover .cal-slot-cta {
  background-color: var(--spruce-fill);
  color: #f4f5f2;
}

.cal-slot.booked {
  background-color: var(--bg-surface);
  border: 1px solid var(--border-color);
  color: var(--text-muted);
  cursor: not-allowed;
  user-select: none;
}

.cal-slot.booked .cal-slot-time {
  text-decoration: line-through;
  color: var(--text-muted);
}

.cal-slot-booked-tag {
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.5625rem;
  padding: 0.125rem 0.5rem;
  border-radius: 0.375rem;
  background-color: var(--bg-card);
  border: 1px solid var(--border-color);
  color: var(--text-muted);
}

.cal-empty {
  padding: 1.25rem;
  border-radius: 0.75rem;
  background-color: var(--bg-surface);
  border: 1px solid var(--border-color);
  color: var(--text-muted);
  text-align: center;
  font-size: 0.75rem;
}

.cal-window-tag {
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.625rem;
  color: var(--spruce);
  font-weight: 600;
}

/* Booking form inputs pick up theme tokens */
.cal-input {
  width: 100%;
  padding: 0.5rem 0.75rem;
  border-radius: 0.5rem;
  background-color: var(--bg-card);
  border: 1px solid var(--border-color);
  color: var(--text-main);
  font-size: 0.75rem;
}

.cal-input:focus {
  outline: none;
  border-color: var(--spruce);
}

/* ---------- Mobile touch targets ---------- */

/* Below the lg breakpoint the header nav is the scrollable pill bar, and every
   control in it is pressed with a thumb. The pills and the two icon buttons get
   the 44px minimum target height there. Desktop is untouched: .site-nav-wrap
   replaces the pill bar at lg and up, and the media query is capped to match. */
@media (max-width: 1023px) {
  .nav-pill {
    min-height: 44px;
  }

  #theme-toggle {
    min-width: 44px;
    min-height: 44px;
  }

  #market-trigger {
    min-height: 44px;
  }
}

/* ---------- Touch comfort on small screens ---------- */

/* Real tap targets in the page body get a 44px minimum height on touch-sized
   viewports. The compact header controls are deliberately excluded so the
   sticky bar keeps its height. */
@media (max-width: 1023px) {
  main .btn-primary,
  main .btn-secondary,
  main .nav-pill {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }
}

/* ---------- Reduced motion ---------- */

@media (prefers-reduced-motion: reduce) {
  .node-pulse {
    animation: none;
    /* Static spruce presence: keep the border, swap the glow for a static ring */
    border: 2px solid var(--spruce);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--spruce) 25%, transparent);
  }
  .page-section.active {
    animation: none;
  }
  html {
    scroll-behavior: auto;
  }
}

/* Page column lives on section children, not on main, so the hero shader
   can be min(100%, 1600px) without being clipped by a flex item max-width. */
main.site-main {
  width: 100%;
  max-width: none;
  min-width: 0;
  overflow: visible;
}

.page-section {
  width: 100%;
  max-width: none;
  min-width: 0;
  overflow: visible;
}

.page-section > *:not(.hero-stage) {
  box-sizing: border-box;
  width: min(100%, 72rem);
  margin-left: auto;
  margin-right: auto;
  padding-left: 1rem;
  padding-right: 1rem;
}

@media (min-width: 640px) {
  .page-section > *:not(.hero-stage) {
    padding-left: 2rem;
    padding-right: 2rem;
  }
}

/* Hero backdrop bleed. The shader overhangs the hero copy by the same amount
   above and below, so the copy sits centred inside its own backdrop. The
   negative top margin cancels the page's top padding, which previously left a
   blank off-white strip between the nav and the top of the shader. Copy
   positions are unchanged -- the copy still starts at the same page offset.
   The page is shorter by exactly (old tail - --hero-bleed): the old fixed
   160px tail is replaced by a bleed above and below, which costs 2 x bleed
   but is offset by the negative margin, netting one bleed. That is 112px
   above 640px and 128px below it, and the next section rises by that much.
   Both overhangs come from --hero-bleed, so they cannot drift apart. */
/* Matches the vertical padding on main.site-main (py-8 / sm:py-12) so the
   shader reaches the header instead of leaving a gap above it. */
:root {
  --hero-bleed: 2rem;
}
@media (min-width: 640px) {
  :root {
    --hero-bleed: 3rem;
  }
}

.hero-stage {
  position: relative;
  width: 100%;
  max-width: none;
  overflow: visible;
  margin-top: calc(-1 * var(--hero-bleed));
  padding-top: var(--hero-bleed);
  padding-bottom: var(--hero-bleed);
}

.hero-copy {
  box-sizing: border-box;
  width: min(100%, 72rem);
  margin-left: auto;
  margin-right: auto;
  padding-left: 1rem;
  padding-right: 1rem;
}

@media (min-width: 640px) {
  .hero-copy {
    padding-left: 2rem;
    padding-right: 2rem;
  }
}

.hero-shader-bleed {
  pointer-events: none;
  position: absolute;
  z-index: 0;
  top: 0;
  bottom: 0;
  left: 50%;
  width: min(100%, 1600px);
  max-width: 1600px;
  margin-left: calc(min(100%, 1600px) / -2);
  overflow: hidden;
  opacity: 0.7;
}

#hero-shader {
  display: block;
  width: 100% !important;
  height: 100% !important;
}
