/* =========================================================
   AC-v2 Global shell
   Reset, base body, section container, theme switching,
   enter animation primitive, accessibility helpers.
   ========================================================= */

/* ---------- Reset ---------- */
*,
*::before,
*::after { box-sizing: border-box; }

html {
  scroll-behavior: smooth;
  /* 27.05.26 r80: native CSS scroll-snap removed; the ET-section snap
     is now handled by JS (et-snap IIFE in section-observers.js) so we
     can use a custom cubic ease-in-out curve over a tunable duration
     -- the browser's default snap animation isn't directly controllable
     and felt too abrupt. */
  -webkit-text-size-adjust: 100%;
  /* Lock the scrollbar always visible so the nav doesn't shift horizontally
     when the page grows tall enough to need one. */
  overflow-y: scroll;
  scrollbar-gutter: stable;
  /* Horizontal overflow clipped here on <html> via overflow-x: clip
     (moved from body 20.04.26). clip does NOT create a scrollport, so
     position: sticky on descendants still resolves against the viewport.
     The previous body { overflow-x: hidden } was turning body into the
     nearest scrolling ancestor for sticky, which broke .et-chamber__stage-wrap
     and caused the chamber backdrop to scroll away mid-ET instead of
     pinning through the block. Chrome 90+, FF 81+, Safari 16+. */
  overflow-x: clip;
  /* 22.05.26: stop the page rubber-banding away from the viewport top (and
     bottom) when the user tries to scroll beyond the start or end of the
     content. Per Caoimhin, the site should not feel like it pulls away from
     the top on overscroll. */
  overscroll-behavior-y: none;
  /* scroll-snap removed 19.04.26 (str-v2-190426-unflex). The proximity snap
     was fighting the fixed nav, sections snapped flush to viewport top and
     h2s were being clipped behind the nav bar. Manual scrolling is now
     natural rather than assisted.

     scroll-margin-top REMOVED from .section on 23.04.26 (v3). All sections
     now anchor-scroll to viewport top (y=0), with the translucent nav bar
     sitting on top of the content. This matches the TEotE parallax-track
     behaviour and aligns with the UCB vision of one continuous canvas
     under a floating nav. */
}

body {
  margin: 0;
  font-family: var(--font-serif);
  font-weight: 500;
  font-size: var(--body);
  line-height: 1.6;
  color: var(--primary-text);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  /* overflow-x: hidden REMOVED 20.04.26; see <html> note above.
     It was breaking position: sticky on the chamber stage wrap. If a
     future element causes horizontal overflow, clip it on that element
     specifically rather than reintroducing overflow on body. */
}

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

/* ---------- Brand registered-mark (Eternal Tales(R)) ----------
   27.05.26 r74: applied to every visible occurrence of the brand in
   marketing/UI copy (nav link, prose, footer, body card). Renders as
   a small superscript ® without disturbing line-height in the
   surrounding text. Kept consistent across the site so the mark
   never reads too large next to the brand name. Attribute values
   (meta tags, JSON-LD) use the literal Unicode "®" since attributes
   cannot host HTML. */
.brand-mark {
  font-size: 0.5em;
  vertical-align: super;
  line-height: 0;
  margin-left: 0.1em;
  font-weight: inherit;
  letter-spacing: 0;
  /* Suppress the underline link-decoration inheritance when the mark
     sits inside an anchor (nav link, prose <a>). */
  text-decoration: none;
}

/* ---------- Reduced-motion global clamp ---------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* ---------- Skip link ----------
   Hidden off-screen via transform so no edge ever peeks through,
   regardless of font-size, padding, or line-height combinations. */
.skip-link {
  position: fixed;
  top: 8px;
  left: 8px;
  background: var(--accent);
  color: #fff;
  padding: var(--s-3) var(--s-5);
  font-family: var(--font-sans);
  font-weight: 500;
  font-size: var(--body-small);
  text-decoration: none;
  border-radius: var(--radius-sm);
  z-index: 9999;
  transform: translateY(calc(-100% - 16px));
  transition: transform var(--t-fast) var(--ease-standard);
}
.skip-link:focus { transform: translateY(0); }

/* ---------- Main + section shell ---------- */
main { display: block; }

.section {
  position: relative;
  /* Vertical padding only. Horizontal gutters live on .section__inner so
     they match .nav__inner exactly and share one page column boundary.
     Updated 19.04.26 (str-v2-190426-nav-edge-unification).
     04.05.26: top padding now reserves the fixed nav height so eyebrows
     and headlines do not get clipped under the nav banner. Sections that
     need to start at y=0 (e.g. .section--our-stories-intro, where the
     sticky logo pin spans the viewport) override padding-top: 0 locally. */
  padding: calc(var(--nav-height) + var(--s-6)) 0 var(--s-9);
  /* min-height: 100vh keeps each section at least one screen tall so the
     next section's label cannot peek in from below. Content now flows
     top-down from the top padding (natural flow) rather than being
     vertically centred by flex. Only .section--landing opts into centring
     for the hero (see section-landing.css). Updated 19.04.26
     (str-v2-190426-unflex). */
  min-height: 100vh;
  /* scroll-margin-top: anchor-scrolls (e.g. nav clicks) snap with
     nav-height of clearance so the eyebrow + headline are visible
     after navigation. Restored 04.05.26 alongside the top-padding
     change above; the 23.04.26 removal note is superseded. */
  scroll-margin-top: var(--nav-height);
  transition: background-color var(--t-standard) var(--ease-standard),
              color var(--t-standard) var(--ease-standard);
}

.section[data-theme="dark"] {
  background: var(--bg);
  color: var(--primary-text);
}

.section[data-theme="light"] {
  background: var(--bg);
  color: var(--primary-text);
}

/* ---------- Grain overlay on light-theme sections (18.05.26, third pass) ----------
   Subtle paper-imperfections effect. Approach revised after the user
   flagged that flat dark grain "just makes white look darker": the
   noise is now warm-tinted (a faint brown-gray rather than black) and
   alpha-keyed so only a fraction of each "fibre" is visible, and the
   overall opacity is dropped roughly threefold. The result reads as
   the subtle warmth of novel-page paper rather than digital noise.
   Tunable via --grain-opacity. */
.section[data-theme="light"] {
  --grain-opacity: 0.08;
}
.section[data-theme="light"]::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: -1;
  /* baseFrequency=3.5 (was 2.4): very fine grain.
     feColorMatrix maps the alpha-channel noise to warm
     brown-gray (R=0.55, G=0.45, B=0.30) with alpha scaled
     0.5x so most fibres render as a barely-visible tint. */
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 400 400'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='3.5' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0.55  0 0 0 0 0.45  0 0 0 0 0.30  0 0 0 0.5 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>");
  background-size: 400px 400px;
  opacity: var(--grain-opacity, 0.08);
}

/* Cream mode disabled 19.04.26 per user direction: use dark everywhere.
   Tokens preserved in tokens.css; rules can be re-enabled below if needed.

.section[data-theme="cream"] {
  background: var(--cream);
  color: var(--cream-text);
}
*/

.section__inner {
  /* One shared page column. Matches .nav__inner byte-for-byte so the
     logo, nav links, and all section content share the same left and
     right edges. Any narrower reading measures (e.g. .about__body) live
     inside this column. Updated 19.04.26. */
  max-width: var(--max-content);
  margin: 0 auto;
  padding: 0 var(--s-5);
  position: relative;
}

/* Landing sets its own 100vh + vertical centring in section-landing.css.
   Shell only carries the text-align hint. */
.section--landing {
  text-align: center;
}

/* ---------- Typography primitives ---------- */
h1, h2, h3, h4 {
  margin: 0 0 var(--s-5);
  /* 06.05.26: capitalised content headers use --font-display
     (Garamond stack) per Caoimhin. Body / paragraphs stay Georgia
     via --font-serif on the body element. */
  font-family: var(--font-display);
  font-weight: 700;
  line-height: 1.2;
}

h1 { font-size: var(--h1); }
h2 { font-size: var(--h2); }
h3 { font-size: var(--h3); font-weight: 500; }
h4 { font-size: var(--h4); font-weight: 500; }

p { margin: 0 0 var(--s-4); }
p:last-child { margin-bottom: 0; }

.section-label {
  font-family: var(--font-sans);
  font-weight: 500;
  font-size: var(--label);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: var(--s-5);
}

/* =========================================================
   Atmosphere canvas (20.05.26) -- warm ember + fog particle
   layer ported from the eternaltales.ie hero (atmosphere.js).
   Sized to its parent (the sticky 100vh stage box) and laid
   over the scene at z:1: above the chamber/TEoTE backdrop
   (z:0) and below the foreground text (ET content, or the
   TEoTE logo/callout/credit at z:2-3). pointer-events: none
   so it never intercepts clicks (e.g. the TEoTE lightbox i).
   opacity tunes the overall strength of the effect.
   ========================================================= */
.et-atmosphere {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 1;
  pointer-events: none;
  opacity: 0.35;
}

a {
  color: var(--accent);
  text-decoration: none;
  transition: color var(--t-fast) var(--ease-standard);
}
a:hover { color: var(--accent-soft); }
a:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

/* Cream-mode link overrides disabled 19.04.26.
.section[data-theme="cream"] a { color: var(--accent); }
.section[data-theme="cream"] a:hover { color: #8f5430; }
*/

/* ---------- Call to action (placeholder for foundation) ---------- */
.cta {
  display: inline-block;
  font-family: var(--font-sans);
  font-weight: 500;
  font-size: var(--body-small);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  padding: var(--s-3) var(--s-5);
  border-bottom: 1px solid var(--accent);
  color: var(--primary-text);
  margin: var(--s-3) var(--s-2);
}
.cta:hover { color: var(--accent); }
/* .section[data-theme="cream"] .cta { color: var(--cream-text); }; disabled 19.04.26 */

/* ---------- Fade-up enter animation primitive ----------
   09.05.26: bumped for emphatic card arrivals.
     - translateY 20px → 72px (larger rise)
     - scale 0.96 added (subtle "materialise")
     - duration 400ms → 700ms → 400ms (quicker per Caoimhín 09.05.26)
   The .is-visible state lerps to translateY(0) scale(1) opacity(1).
   Targets every .fade-up element on the page; reduced-motion path
   below disables it. */
.fade-up {
  opacity: 0;
  transform: translateY(72px) scale(0.96);
  transition: opacity 400ms var(--ease-standard),
              transform 400ms var(--ease-standard);
  will-change: opacity, transform;
}

.fade-up.is-visible {
  opacity: 1;
  transform: translateY(0) scale(1);
}

/* ---------- Responsive section padding ----------
   Horizontal gutters stay on .section__inner (matching .nav__inner's
   var(--s-5)) so the logo and section content keep the same x-positions
   at every breakpoint. Only vertical padding steps down here.
   Updated 19.04.26. */
@media (max-width: 767px) {
  .section { padding: calc(var(--nav-height) + var(--s-5)) 0 var(--s-8); }
}

@media (max-width: 480px) {
  .section { padding: calc(var(--nav-height) + var(--s-4)) 0 var(--s-7); }
}

/* Respect reduced motion on enter animations */
@media (prefers-reduced-motion: reduce) {
  .fade-up { opacity: 1; transform: none; }
}

/* ---------- .visually-hidden ----------
   Standard a11y helper: removes an element from visual layout while
   keeping it in the accessibility tree. Added 20.04.26 when the ET
   opener moved the visible heading onto the logo lockup and the text
   heading was retained only for screen readers. */
.visually-hidden {
  position: absolute !important;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* =========================================================
   In-flow section breadcrumb (.bc) - 06.05.26
   Sits at the top of each Eternal Tales child section (AOoS, BtM,
   VotF) above the article card. Same constant text everywhere:
   "Our Stories . Eternal Tales(TM)". The section h2 below carries
   the title-specific text.

   In-flow approach (not fixed/sticky); overkill for only three
   sections. Keeps the breadcrumb tied to each section's reading
   rhythm and avoids a persistent viewport overlay.
   ========================================================= */
.bc {
  margin: 0 0 var(--s-5);
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 12px;
  font-family: var(--font-sans);
  font-size: 16px;
  letter-spacing: 0.02em;
  color: var(--soft-text);
  text-shadow: 0 1px 6px rgba(0, 0, 0, 0.85);
  text-align: center;
  white-space: nowrap;
}
.bc__from { font-style: italic; color: var(--quiet-text); }
.bc__sep  { opacity: 0.5; }
.bc__to   { color: var(--soft-text); }
.bc sup {
  font-size: 0.55em;
  vertical-align: super;
  margin-left: 1px;
}

/* =========================================================
   10.05.26 perf pass: content-visibility on offscreen sections.
   DISABLED 11.05.26; see incident note below.
   =========================================================
   Original intent: skip rendering (layout, paint, even style) for
   sections that aren't near the viewport. Big scroll-budget win
   on long pages, especially mid-tier mobile.

   Why disabled: the `contain-intrinsic-size: auto 100vh` placeholder
   was inaccurate for several sections (.section--our-stories-intro
   actual height is calc(100vh - var(--nav-height)); the et-card
   two-column layout at desktop widths renders shorter than 100vh).
   When the user nav-clicked AOoS / BtM / VotF, the browser computed
   the target offsetTop against the stale 100vh placeholders; as the
   smooth scroll passed each section, the actual (smaller) heights
   emerged, the document shrank, and the scroll overshot the
   heading. Cut-off worsened the deeper the target (VotF was worst
   because the most sections shrank above it).

   Restoration path: re-enable with per-section accurate intrinsic
   sizes that reflect actual rendered heights at each viewport.
   Likely needs JS to measure once on load and stamp custom-property
   sizes, since the heights vary across responsive breakpoints.

.section--about,
.section--our-stories-intro,
.section--aoos,
.section--btm,
.section--votf,
.section--contact {
  content-visibility: auto;
  contain-intrinsic-size: auto 100vh;
}
*/

/* =========================================================
   Sticky-overlay stack (19.05.26 r26)
   Per Caoimhín: non-Our-Stories sections should "come over the
   top" of the previous one on scroll, like cards sliding up over
   a stack. Each overlay section pins at top:0 when scrolled to,
   and later sections cover earlier ones via z-index ordering.

   The chamber wrapper and the TEoTE parallax track in between
   keep their existing choreography (chamber dip-to-dark + 300vh
   parallax). They get an explicit z-index above the sticky
   overlays so the OS region paints OVER any still-pinned hero /
   about / dark-transition behind them.

   Contact pulls itself up with a negative margin-top so it starts
   overlapping the TEoTE track's tail. As the user nears the end
   of the parallax, Contact's top approaches viewport top; once
   pinned (z above the track), it slides up over TEoTE.

   Apple-style stacked-card effect.
   ========================================================= */
/* r36 (19.05.26): reset. Glass plate is now position:fixed (handled
   in section-about.css) and chamber sits in NATURAL flow right after
   About. Removed: plate's sticky positioning, chamber's negative
   margin-top, plate z-index rule (z:6 now lives in section-about.css
   with the rest of the plate styles). About stays at z:7 above the
   fixed glass (z:6); chamber + track at z:5 below it; Contact still
   sticky-overlay for the TEoTE handoff. */
#get-in-touch {
  position: sticky;
  top: 0;
}
/* r42 (20.05.26) z-index ladder for the glass transitions:
   Contact (10) > Hero/About (9) > glass#1 (8) > chamber/ET (7) >
   TEoTE track (5). Each section is revealed by the glass above it and
   covered by the glass below it for the next transition.

   r57 (21.05.26): REVERTED the r54/r56 overlay experiments per Caoimhin.
   Hero + About are both back to z:9 in NORMAL flow (no sticky hero, no
   About transform-pin), so sections scroll normally rather than sliding
   over one another. (The r56 sticky hero also broke the nav: its reveal
   observer never saw the hero "leave", so the nav stayed at opacity 0.)
   glass #1 is back to its fade-in-place behaviour. The historical notes
   below describe the reverted experiments.

   r54 (21.05.26): About dropped 9 -> 4 for the About-pinning curtain.
   About transform-pins (section-observers.js writes a translateY) when
   its last line reaches the viewport bottom, then glass #1 (z:8) + the
   chamber/ET (z:7) RISE OVER it. To stay occluded for the rest of the
   page it must sit BELOW everything that scrolls in front afterwards -
   incl. the TEoTE track (z:5) - so z:4. During About's own reading
   nothing overlaps it (glass parked off-screen, chamber below the fold).

   r56 (21.05.26): Hero dropped 9 -> 3 (below About) and made
   position:sticky top:0, so the About section SLIDES UP OVER the pinned
   hero - the "About comes onto the hero" overlay, mirroring the
   section-over-section transitions elsewhere. Hero is the lowest layer:
   once About covers it the hero stays sticky-pinned behind everything,
   occluded. During the hero's own reading nothing overlaps it (About is
   below the fold), so the low z is invisible there. */
#landing                    { z-index: 9; }
#about                      { z-index: 9; }
.et-chamber                 { z-index: 7 !important; }
.teote-parallax-track       { z-index: 5 !important; }
#our-stories {
  /* r40 (20.05.26): margin-top back to 0 so OS.absT = aboutEnd.
     OS is transform-pinned during the glass fade window (glass IIFE
     in section-observers.js writes translateY so OS holds at
     viewport top while the glass clears -- card + content STATIC,
     no scroll-in). The lockup, inside OS, gets a --lockup-counter
     var to cancel the inherited OS transform so the logo doesn't
     drift during the fade (the r38 "reverse" symptom). */
  margin-top: 0;
}
/* r29 attempt of disabling the chamber filter was wrong: the dim is
   load-bearing for hiding the white tile cards as the chamber exits
   the viewport. Without it the tiles stayed visible against the dark
   band. r30: filter restored; instead we MATCH the band downstream
   (plate #2 + track) to the chamber's dimmed colour (pure black),
   so the visible band reads as one uniform dark stripe from the
   end of the chamber dip through into TEoTE.
   r31: plate #2 removed; track bg stays #000 to match chamber's
   filter-dimmed exit through to TEoTE's reveal. */
.teote-parallax-track       { z-index: 5 !important; }
#get-in-touch {
  z-index: 10;
  /* r27 (19.05.26): margin-top -100vh -> 0. Per Caoimhín, Contact
     should only start coming in at the very end of the TEoTE
     animation. With margin-top: 0, Contact's natural top sits
     right after the parallax track's bottom; Contact's top edge
     enters the viewport bottom exactly when track.bottom hits
     viewport bottom -- i.e. when TEoTE's parallax progress
     reaches 1 and the stage starts unpinning. Contact then slides
     up over the unpinning stage for one viewport-height of scroll
     before pinning at top:0. */
  margin-top: 0;
}
