/* ==========================================================
   FOREST-BASED THERAPY — TOOL · v0.5
   Restyled to match the Pocketbook design system.
   Palette: warm cream paper, low-chroma forest greens, ember accent.
   Type: Montserrat (display), Open Sans (body), Playfair (occasional serif).
   ========================================================== */

/* ─── styles-base.css: resets, site chrome — header, nav, search dialog,
   role-aware visibility. One of five files split out of the original
   monolithic styles.css, in the same order they used to appear in that
   one file (see index.html's <link> order — cascade order must match).
   ─── */


html { height: 100%; background: transparent; }
* { margin: 0; padding: 0; box-sizing: border-box; }

body {
  font-family: 'Open Sans', -apple-system, sans-serif;
  background: transparent;
  color: var(--ink);
  font-weight: 300;
  -webkit-font-smoothing: antialiased;
  min-height: calc(var(--vh, 1vh) * 100);
  overflow-x: hidden;
  letter-spacing: 0.005em;
}

body::before {
  content: '';
  position: fixed;
  inset: 0;
  background: transparent;
  pointer-events: none;
  z-index: 0;
}

.container {
  max-width: 960px;
  margin: 0 auto;
  padding: 0 24px;
  position: relative;
  z-index: 1;
  /* Passes clicks through wherever neither direct child (header, main —
     re-enabled below) actually covers a pixel: .container's own box is a
     solid rectangle from its top to its bottom regardless of gaps in the
     normal-flow content inside it (e.g. body.wf-scene-deep #main-content's
     margin-top, below), so without this, a click landing in that "empty"
     space still hits .container itself rather than falling through to
     #wf-scene underneath — confirmed directly: margin-top alone did not
     expose a working hotspot, elementFromPoint() kept resolving to
     .container. */
  pointer-events: none;
}
.container > * { pointer-events: auto; }

/* ── LANGUAGE TOGGLE ──
   Sits in normal flow inside .header-controls, between the mode switch
   and the Walk the Forest toggle — see index.html's header-controls order. */
.lang-bar {
  display: flex;
  gap: 4px;
  background: var(--paper-pure);
  border: 1px solid var(--forest-mist);
  border-radius: var(--r-pill);
  padding: 4px;
  box-shadow: var(--shadow-sm);
}

.lang-btn {
  font-size: 10.5px;
  font-weight: 500;
  letter-spacing: 0.12em;
  padding: 5px 11px;
  border-radius: var(--r-pill);
  border: none;
  background: transparent;
  color: var(--ink-faint);
  cursor: pointer;
  font-family: 'Open Sans', sans-serif;
  transition: all 0.18s;
}

.lang-btn.active {
  background: var(--forest-ink);
  color: var(--paper-pure);
}



/* ── ROLE-AWARE VISIBILITY ──
   !important is deliberate here, not a specificity accident: this is the
   one rule responsible for a wrong-role element never being visible, even
   if some other, more specific selector added elsewhere (e.g. an ID-scoped
   rule on a particular screen) would otherwise win the cascade. Verified
   this session (see the CSS architecture audit in the redesign-redesigned
   branch history) — kept intentionally, not something to "clean up". */
body[data-role="participant"] [data-role-only="practitioner"] { display: none !important; }
body[data-role="practitioner"] [data-role-only="participant"] { display: none !important; }

/* The rules above only hide the *wrong* role's content once JS has set
   data-role on <body> — safe for every [data-role-only] that lives inside
   a .screen, since .screen defaults to display:none until .active is
   added by JS regardless. But the persistent nav groups and #entry-screen
   (which is marked .active directly in the markup, not by JS) have no
   such default-hidden ancestor, so both variants render together for as
   long as the page takes to parse and run the scripts that set data-role
   — briefly showing Plan/Run/Reflect/Reference stacked with the
   participant nav links, and both entry-screen pathway lists stacked on
   the main screen. Default these two spots to hidden and opt back in
   per role, so there's never a frame where both show. */
.site-nav-group[data-role-only],
#entry-screen > [data-role-only] { display: none; }
body[data-role="practitioner"] .site-nav-group[data-role-only="practitioner"] { display: flex; }
body[data-role="participant"] .site-nav-group[data-role-only="participant"] { display: flex; }
body[data-role="practitioner"] #entry-screen > [data-role-only="practitioner"],
body[data-role="participant"] #entry-screen > [data-role-only="participant"] { display: block; }

/* Real, always-present strip of the blurred scene between the header and
   the active screen's own content — a guaranteed hotspot back to the
   game (wfOnSceneClick() in walk-forest.js, already wired to
   appEscapeAction()) that works at every viewport width, not just as a
   side-effect of .container's 960px cap leaving side margins on wide
   enough screens. #wf-scene is position:fixed behind everything, so this
   gap shows the actual live, blurred backdrop, not a placeholder — any
   click or tap landing here reaches #wf-scene's own background exactly
   like those margins already do when they happen to be exposed. */
body.wf-scene-deep #main-content { margin-top: 64px; }

/* ── HEADER ── */
/* Breaks out of .container's 960px cap — the centered three-section
   layout below needs more room than that leaves for the nav (measured:
   title ~254px + controls ~516px out of a 960px container left only
   ~150px for four nav links, forcing them to wrap vertically instead of
   sitting centered in a row). .container's own max-width stays 960px for
   actual page content; only the header gets the wider, independently
   viewport-centered treatment. On narrow screens 100vw already is
   .container's width, so this is a no-op there.
   Scoped to #site-header, not the bare `header` tag: two other elements
   in this app are also literal <header> tags for unrelated reasons
   (.pb-builder-header, the Session Builder's own header, and
   .pb-group-header, generated per activity group) — a bare `header {}`
   selector here pulled both of them out to this same 100vw/max-width/
   translateX(-50%) full-bleed treatment too, displacing them from their
   actual containers (the 320px Session Builder sidebar column, and the
   activity-list column) and overlapping them with sibling content.
   #site-header is the one and only element this rule is meant for.

   max-width is 1800px, not the earlier 1220px: at 1220 the nav column was
   left ~380px for four links that need ~700-800px in FR/DE, so it wrapped
   to 2-4 rows at EVERY desktop width (measured at 1900px too) and the
   header grew from 141px to 237px tall. The three sections stay on one
   line instead, with the controls pushed further right on wide screens —
   page content is unaffected, .container keeps its own 960px cap.

   The width subtracts --sbw (the vertical scrollbar's width, measured
   once per resize in ui-behaviors.js, 0px if the browser overlays its
   scrollbars): 100vw counts the scrollbar, so a plain `width: 100vw` on a
   centered breakout element is that much wider than the space it is
   centred in and hangs off the right edge — measured as 45-60px of
   document overflow between 769px and 1220px. body{overflow-x:hidden}
   was silently clipping that instead of scrolling, which is why it never
   showed up as a scrollbar. */
#site-header {
  padding: 28px 24px 20px;
  border-bottom: 1px solid var(--forest-mist);
  margin-bottom: 28px;
  width: min(calc(100vw - var(--sbw, 0px)), 1800px);
  position: relative;
  left: 50%;
  transform: translateX(-50%);
}

/* Three-section layout — title left, nav centered in the gap between
   title and controls, controls right — rather than the nav clustering
   right next to the title. auto/1fr/auto rather than flex +
   margin-left:auto (still used as the mobile fallback, see
   styles-responsive.css) because centering a middle flex item between two
   different-width siblings isn't a flex feature; grid's 1fr middle
   column is. */
.header-inner {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  column-gap: 16px;
}
/* min-width:0 on the middle column (via minmax(0,1fr) above) is what lets
   the nav actually be narrower than its content and scroll internally
   instead of shoving the controls off the line — a bare 1fr floors at
   min-content. The outer two columns are auto and never shrink, so the
   title stays put on the left and the controls (search / mode / lang /
   Walk the Forest) stay flush right at the end of the same line. */
.header-text { grid-column: 1; min-width: 0; }
.header-text h1 { white-space: nowrap; }
/* `safe center` — centred while the links fit, but falling back to
   flex-start the moment they don't. Plain `center` on an overflowing
   flex row overflows in BOTH directions, and the part that spills past
   the start edge is unreachable by scrolling; it also meant the row
   opened mid-word on both sides. */
.site-nav { grid-column: 2; justify-content: safe center; min-width: 0; }
.header-controls { grid-column: 3; flex-wrap: nowrap; }

.tree-mark { width: 40px; height: 40px; flex-shrink: 0; }

.header-text h1 {
  font-family: 'Montserrat', sans-serif;
  font-size: 20px;
  font-weight: 500;
  color: var(--forest-ink);
  line-height: 1.1;
  letter-spacing: -0.01em;
}

.header-text p {
  font-size: 12px;
  color: var(--ink-faint);
  font-weight: 400;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  margin-top: 6px;
}

/* ── HEADER NAV & SEARCH ── */
/* Skip link (WCAG 2.4.1) — visually hidden until it receives focus,
   which makes it the very first tab stop on the page. */
.skip-link {
  position: absolute;
  top: -60px;
  left: 8px;
  z-index: 3000;
  background: var(--forest-ink);
  color: var(--paper-pure);
  padding: 10px 18px;
  border-radius: var(--r-sm);
  font-size: 13px;
  font-weight: 500;
  text-decoration: none;
  transition: top 0.15s ease;
}
.skip-link:focus { top: 8px; }

/* Visually-hidden utility (aria-live regions, etc.) — kept distinct from
   .skip-link, which needs to become visible on focus. */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Global keyboard-focus indicator. Nothing in this file provided one
   before this section, so this doesn't override or duplicate anything —
   it's the first one. :focus-visible degrades harmlessly (simply
   unmatched, not an error) on anything old enough not to support it. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--forest-deep);
  outline-offset: 2px;
}

/* Persistent, role-aware nav. Practitioner mode shows Plan/Run/Reflect/
   Reference; participant mode shows the 4 orientation steps. Only the
   group matching data-role-only is visible (existing rule, reused
   as-is: body[data-role="…"] […] { display:none }).

   nowrap, not wrap: wrapping is what broke the header's single line. The
   participant labels ("What happens in a session?", and longer still in
   FR/DE) need ~700-800px between them, so a wrapping nav spilled onto 2-4
   rows at every desktop width and the header grew to 237px tall with the
   title and controls floating in the middle of it. One row that scrolls
   horizontally when it genuinely does not fit (below ~1300px, and in the
   participant path in FR/DE) keeps every section on the same baseline;
   the scrollbar itself is hidden and replaced by the edge fade below,
   since a visible native scrollbar inside a 44px-tall header reads as
   breakage. Every destination stays reachable — tabbing scrolls a focused
   link into view, wheel/trackpad swipe scrolls the row, and
   updateHeaderChrome() (router.js) centres the active link on each route
   change. */
.site-nav {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  gap: 4px;
  overflow-x: auto;
  overflow-y: hidden;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  /* Fades the cut-off end(s) so a scrolled-past link doesn't just stop
     dead at the column edge. Both edges are faded unconditionally rather
     than tracking scroll position in JS — at rest the nav is centred and
     fully visible, so the fade only ever bites on content that really is
     running off the edge. */
  -webkit-mask-image: linear-gradient(to right, transparent 0, #000 18px, #000 calc(100% - 18px), transparent 100%);
  mask-image: linear-gradient(to right, transparent 0, #000 18px, #000 calc(100% - 18px), transparent 100%);
}
.site-nav::-webkit-scrollbar { display: none; }
/* The mask above would clip the focus ring of the first/last link; drop
   it while anything inside the nav has keyboard focus. */
.site-nav:focus-within {
  -webkit-mask-image: none;
  mask-image: none;
}
.site-nav-group { display: flex; flex-wrap: nowrap; gap: 4px; }

.site-nav-link {
  display: inline-flex;
  align-items: center;
  flex: 0 0 auto;
  min-height: 44px;
  padding: 0 clamp(9px, 0.85vw, 14px);
  border-radius: var(--r-pill);
  font-size: 12.5px;
  font-weight: 500;
  letter-spacing: 0.01em;
  color: var(--ink-soft);
  text-decoration: none;
  border: 1px solid transparent;
  white-space: nowrap;
  transition: background 0.18s, border-color 0.18s, color 0.18s;
}
.site-nav-link:hover { color: var(--forest-deep); background: var(--paper-card); }
.site-nav-link.active {
  color: var(--forest-deep);
  background: var(--paper-pure);
  border-color: var(--forest-mist);
  font-weight: 600;
}

.header-controls {
  display: flex;
  align-items: center;
  gap: 10px;
}

/* Hidden by default; updateHeaderChrome() (router.js) adds --visible
   whenever a screen is actually open, so it's never shown redundantly
   while already on the game — see the comment on #wf-back-btn in
   index.html for why this exists at all. Ember accent (not the neutral
   paper/border language the rest of .header-controls uses) so it reads
   as a distinct "get me out of here" action, not just another nav item. */
.wf-back-btn {
  display: none;
  align-items: center;
  min-height: 44px;
  padding: 0 14px;
  border-radius: var(--r-pill);
  border: 1px solid var(--ember-soft);
  background: var(--paper-pure);
  color: var(--ember);
  cursor: pointer;
  font-family: 'Open Sans', sans-serif;
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
  transition: background 0.18s, color 0.18s;
}
.wf-back-btn:hover, .wf-back-btn:focus-visible { background: var(--ember); color: var(--paper-pure); }
.wf-back-btn--visible { display: inline-flex; }

.search-trigger {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-height: 44px;
  padding: 0 14px;
  border-radius: var(--r-pill);
  border: 1px solid var(--forest-mist);
  background: var(--paper-pure);
  color: var(--ink-soft);
  cursor: pointer;
  font-family: 'Open Sans', sans-serif;
  font-size: 12px;
  font-weight: 500;
  transition: all 0.18s;
}
.search-trigger:hover { border-color: var(--forest-soft); color: var(--forest-deep); }
.search-trigger-kbd {
  font-size: 10px;
  color: var(--ink-faint);
  border: 1px solid var(--forest-mist);
  border-radius: 4px;
  padding: 1px 5px;
  font-family: 'Open Sans', sans-serif;
}

/* Mode switch — same pill/segmented-control language as .lang-bar/.lang-btn,
   just sized up to the 44px minimum hit target since (unlike the
   pre-existing language toggle) this is a new control. */
.mode-switch {
  display: flex;
  gap: 4px;
  background: var(--paper-pure);
  border: 1px solid var(--forest-mist);
  border-radius: var(--r-pill);
  padding: 3px;
  box-shadow: var(--shadow-sm);
  animation: modeSwitchCta 1.8s ease-in-out 3;
}
/* Brief, not a standing loop (animation-iteration-count:3, no infinite) —
   a few soft ember pulses on load/first paint to draw the eye to the
   Practitioner/Exploring choice, then it settles back to plain --shadow-sm
   and stays there; looping forever would just become visual noise. Layers
   the pulse ring alongside the base shadow in every keyframe rather than
   replacing it, since an animated box-shadow value fully overrides the
   property each frame instead of adding to it. */
@keyframes modeSwitchCta {
  0%, 100% { box-shadow: var(--shadow-sm), 0 0 0 0 rgba(184,85,46,0); }
  50% { box-shadow: var(--shadow-sm), 0 0 0 6px rgba(184,85,46,0.18); }
}
@media (prefers-reduced-motion: reduce) {
  .mode-switch { animation: none; }
}
.mode-btn {
  min-height: 44px;
  padding: 0 16px;
  border-radius: var(--r-pill);
  border: none;
  background: transparent;
  color: var(--ink-faint);
  cursor: pointer;
  font-family: 'Open Sans', sans-serif;
  font-size: 11.5px;
  font-weight: 500;
  letter-spacing: 0.04em;
  transition: all 0.18s;
}
.mode-btn.active { background: var(--forest-ink); color: var(--paper-pure); }

/* Quick links injected into the focused Pocketbook (Plan) screen so the
   Pre-Session Checklist and Session Structure Guide are one click away
   without a trip back through the header nav. */
.plan-quicklinks {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 18px;
  margin: -8px 0 22px;
}
.plan-quicklinks a {
  font-size: 12px;
  font-weight: 500;
  color: var(--forest-mid);
  text-decoration: none;
  border-bottom: 1px dotted var(--forest-soft);
}
.plan-quicklinks a:hover { color: var(--forest-deep); }

/* Generic "found via search" highlight, reused across screens (reference
   tiers, guide chapters). Distinct from .activity-item.highlight, which
   is specific to the Pocketbook accordion styling. */
.search-highlight {
  box-shadow: 0 0 0 3px rgba(127,163,150,0.35);
  border-radius: var(--r-md);
  transition: box-shadow 0.3s ease;
}

/* Locks the page's own scroll while a full-viewport fixed overlay (Run
   Mode, the search dialog) is open, so scrolling inside the overlay can't
   also move the page behind it — the overlay being position:fixed;inset:0
   makes it LOOK like the only thing on screen, but without this the body
   underneath was still scrollable, producing exactly the kind of
   background/foreground double-scroll this class exists to prevent.
   Toggled by pbStartRunMode()/pbCloseRunMode() in pocketbook-run.js and
   openSearch()/closeSearch() in search.js. */
body.no-scroll { overflow: hidden; }

/* ─── SEARCH DIALOG (⌘K / Ctrl+K) ─── */
.search-dialog-overlay {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(20,48,42,0.45);
  backdrop-filter: blur(6px);
  z-index: 2500;
  align-items: flex-start;
  justify-content: center;
  padding: 12vh 16px 16px;
  animation: pbFadeIn 0.2s ease;
}
.search-dialog-overlay.active { display: flex; }
.search-dialog {
  background: var(--paper-pure);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-lg);
  width: 100%;
  max-width: 560px;
  max-height: 70vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  animation: pbSlideUp 0.22s ease;
}
.search-dialog-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 8px 6px 16px;
  border-bottom: 1px solid var(--forest-mist);
}
.search-dialog-head svg { color: var(--ink-faint); flex-shrink: 0; }
.search-input {
  flex: 1;
  border: none;
  outline: none;
  background: transparent;
  font-family: 'Open Sans', sans-serif;
  font-size: 15px;
  color: var(--ink);
  min-height: 44px;
}
.search-input::placeholder { color: var(--ink-faint); }
.search-close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  border: none;
  background: none;
  cursor: pointer;
  font-size: 20px;
  color: var(--ink-faint);
  line-height: 1;
  border-radius: var(--r-sm);
  flex-shrink: 0;
}
.search-close:hover { color: var(--ink); background: var(--paper-card); }
.search-results { overflow-y: auto; padding: 8px; flex: 1; }
.search-group { margin-bottom: 4px; }
.search-group-label {
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--forest-soft-text);
  padding: 10px 10px 4px;
}
.search-result {
  display: block;
  width: 100%;
  text-align: left;
  border: none;
  background: none;
  cursor: pointer;
  padding: 8px 10px;
  border-radius: var(--r-sm);
  min-height: 44px;
  font-family: 'Open Sans', sans-serif;
}
.search-result:hover, .search-result:focus-visible { background: var(--paper-card); }
.search-result-title { font-size: 13.5px; font-weight: 500; color: var(--forest-ink); }
.search-result-sub {
  font-size: 12px;
  color: var(--ink-soft);
  margin-top: 2px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.search-empty { padding: 28px 10px; text-align: center; color: var(--ink-faint); font-size: 13px; }

