/* ============================================================
   MANNHULLET · 110 ÅR — shared chrome
   Palette, base page background, the NTH watermark, and the
   corner header (logo + socials) are used identically on every
   page: index.html, om-jubileet.html, kontakt.html. Anything
   page-specific (the elevator scroll engine, the modal, each
   page's own content layout) stays in that page's own stylesheet.
   ============================================================ */

:root {
  /* original simple palette — used directly by om-jubileet.html / kontakt.html */
  --ink:        #eef3fa;
  --accent:     #5b82c4;
  --accent-dim: #3d5a8a;
  --bg-soft:    #091125;
  --muted:      #93a6c2;
  --line:       rgba(147, 166, 194, 0.18);

  /* index.html's richer palette (the elevator engine, hotspots, modal) —
     --navy is a true navy blue (not near-black) so the hero and every
     page's body background read as navy at a glance, no glow needed */
  --navy:       #102137;
  --silver:     #c6d0df;
  --silver-dim: #74829a;
  --platinum:   #eef2f8;
  --amber:      #ff7a1e;
  --concrete:   #0b0a08;
  /* secondary/caption tier — countdown unit labels, header nav links, and
     the depth-gauge labels. 6.5:1 against --navy (#14294a), clears WCAG AA
     (4.5:1) for their small text sizes with room to spare — used as-is. */
  --caption:    #9cafcb;

  --serif:   "Cormorant Garamond", "Georgia", "Times New Roman", serif;
  --sans:    "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
  --display: "Playfair Display", serif;

  /* the NTH watermark's ink/glow (unrelated to the hero — this is the
     letterform stroke-blur, see .watermark::before). --wm-ink is lightened
     ~4-5 percentage points above --navy (was ~3pp) so the letters read as
     an intentional engraved watermark rather than a barely-visible
     artifact — still far too dark to compete with --platinum countdown text. */
  --wm-ink:  #273a58;
  --wm-glow: rgba(91, 130, 196, 0.45);

  /* single source for the "eyebrow" typography — used by .page-eyebrow AND
     .date-footer p (background.css) so the two always scale identically to
     each other, and identically to the hero's own .eyebrow/.footer p
     (styles.css, fixed 1rem/0.45em — the clamp here caps out at that same
     value on desktop, just easing down for narrow phones instead of
     overflowing). Change it here once rather than in each component. */
  --eyebrow-size: clamp(0.68rem, 2.4vw, 1rem);
  --eyebrow-tracking: clamp(0.28em, 1.4vw, 0.45em);

  /* unlike --eyebrow-size above, these two are NOT meant to match across
     pages — each simple page's heading and .wrap column are intentionally
     sized/widthed differently for its own content. The fallbacks below only
     exist so a page fails safe if it forgets to set them; every simple page
     overrides both in its own <style> block. */
  --title-size: clamp(1.6rem, 4.6vh, 2.7rem);
  --wrap-width: 700px;

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

  /* elevator depth, 0 (ground floor) → 1 (cellar). Only index.html's
     script.js ever writes this; pages without the elevator simply keep
     the resting value of 0, which every formula below treats as a
     valid "top of the building" state. */
  --depth: 0;
}

* { margin: 0; padding: 0; box-sizing: border-box; }

html { scroll-behavior: auto; -webkit-text-size-adjust: 100%; }
html, body { height: 100%; }

body {
  font-family: var(--sans);
  color: var(--silver);
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  /* flat navy (the same --navy index.html's hero sits on) — index.html's
     own .building gradient paints over this everywhere it covers; pages
     without that gradient (om-jubileet, kontakt) show it as-is, so their
     brightness matches the landing page exactly */
  background: var(--navy);
  scrollbar-gutter: stable;
}

body.no-scroll { overflow: hidden; }

/* ============ Global overlays — shared on every page ============
   Both read --depth, which defaults to 0 (its resting "ground floor" value)
   on pages without the elevator script, so they simply render as a fixed,
   subtle darkening rather than animating. This is what makes index.html's
   background read as moodier/darker than a flat --navy fill — reusing them
   here keeps every page's background feeling the same. */
.grain {
  position: fixed; inset: 0;
  z-index: 90; pointer-events: none;
  opacity: calc(0.05 + var(--depth) * 0.11);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  mix-blend-mode: overlay;
}

.vignette {
  position: fixed; inset: 0; z-index: 80; pointer-events: none;
  box-shadow: inset 0 0 calc(22vmax + var(--depth) * 8vmax) rgba(0,0,0, calc(0.6 + var(--depth) * 0.25));
}

/* ============ NTH watermark — giant letters behind everything ============ */
.watermark {
  position: absolute; inset: 0;
  display: grid; place-items: center; place-content: center;
  font-family: var(--display); font-weight: 800;
  font-size: clamp(8rem, 34vw, 26rem);
  letter-spacing: 0.12em; line-height: 1;
  color: var(--wm-ink);
  user-select: none; pointer-events: none; z-index: 0;
  /* optical centering: Playfair Display 800's "H" (0.815em) is wider than its
     "N" (0.727em), so width-based centering sits right of where "T" actually
     falls — nudge the whole word back to true center */
  transform: translateX(0.044em);
}
.watermark span { grid-area: 1 / 1; margin-right: -0.12em; }
/* a stroke-only duplicate, blurred — blurring the filled glyphs directly would
   diffuse color into their own counters and gaps; stroking the outline first
   means the glow can only bloom outward, never flood the letterforms */
.watermark::before {
  content: "NTH";
  grid-area: 1 / 1;
  margin-right: -0.12em;
  color: transparent;
  -webkit-text-stroke: 0.006em var(--wm-glow);
  filter: blur(0.014em);
  z-index: -1;
}
@media (max-width: 600px) {
  .watermark { font-size: clamp(6.5rem, 38vw, 14rem); }
}

/* ============ Corner brand mark — om-jubileet.html / kontakt.html ============
   identical position/size on every page; opacity/animation are left to each
   page since entrance timing differs */
.header-logo {
  position: fixed;
  top: calc(clamp(0.9rem, 3vh, 1.75rem) + env(safe-area-inset-top, 0px));
  left: calc(clamp(0.9rem, 3vw, 1.75rem) + env(safe-area-inset-left, 0px));
  display: block;
  width: clamp(52px, 6.6vw, 74px);
  height: auto;
  z-index: 5;
  filter: drop-shadow(0 0 30px rgba(91, 130, 196, 0.18));
  transition: opacity 0.2s ease;
}
/* the logo always links back to the hero/homepage (see each page's <a
   class="header-logo-link">) — a subtle dim on hover/focus is enough to
   show it's clickable without fighting the entrance-fade animation */
.header-logo-link:hover .header-logo,
.header-logo-link:focus-visible .header-logo {
  opacity: 0.85;
}

/* ============ Corner social links — om-jubileet.html / kontakt.html ============
   identical position/size/color on every page */
.social-links {
  position: fixed;
  top: calc(clamp(0.9rem, 3vh, 1.75rem) + env(safe-area-inset-top, 0px));
  right: calc(clamp(0.9rem, 3vw, 1.75rem) + env(safe-area-inset-right, 0px));
  z-index: 5;
  display: flex;
  gap: clamp(1rem, 2.75vw, 1.5rem);
}
.social-links a {
  position: relative;
  display: flex;
  color: rgba(147, 166, 194, 0.8);
  transition: color 0.2s ease;
}
/* invisible expanded hit area: keeps the visible icon small while giving it a
   >=44x44px tap target, per WCAG target-size guidance */
.social-links a::before {
  content: "";
  position: absolute;
  inset: -14px;
}
/* orange is the site's hover colour everywhere something is interactive
   (nav links, dots, this) — it stays flat white/grey at rest so it never
   reads as statically "branded", only as "you can click this" */
.social-links a:hover,
.social-links a:focus-visible { color: var(--amber); }
.social-links svg {
  width: clamp(18px, 2.4vw, 22px);
  height: clamp(18px, 2.4vw, 22px);
}

/* ============ index.html-only: "Lyd" rides alongside the socials ============
   .social-links is normally position:fixed on its own (see above); nested
   here it's switched to flow in this flex row instead, so the two sit
   side by side in the same corner rather than fighting over it. */
.corner-right {
  position: fixed;
  top: calc(clamp(0.9rem, 3vh, 1.75rem) + env(safe-area-inset-top, 0px));
  right: calc(clamp(0.9rem, 3vw, 1.75rem) + env(safe-area-inset-right, 0px));
  z-index: 5;
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  align-items: center;
  gap: clamp(1rem, 2.75vw, 1.5rem);
  row-gap: 0.5rem;
}
.corner-right .social-links { position: static; }

/* ============ Shared top nav — every page's link row ============
   Fixed at the top, centered between the logo and the corner-right/social
   group. Spans the full width (left/right: 0) and centers its links with
   justify-content rather than left:50%+transform:translateX(-50%) — the
   shared fadeUp entrance animation also animates `transform`, and a CSS
   animation's transform value fully replaces an element's own static
   transform rather than combining with it, which would silently cancel a
   translateX centering once the fade-in finishes. flex-wrap is a safety
   net for the narrowest phones — it never triggers at normal widths. */
.header-nav {
  position: fixed; top: calc(clamp(0.9rem, 3vh, 1.75rem) + env(safe-area-inset-top, 0px)); left: 0; right: 0;
  z-index: 5; display: flex; flex-wrap: wrap; justify-content: center; align-items: center;
  gap: clamp(1.5rem, 3vw, 2.5rem); row-gap: 0.5rem;
}
.header-nav a {
  position: relative;
  color: var(--caption);
  font-family: var(--sans); font-size: 12px; font-weight: 600; letter-spacing: 0.16em; text-transform: uppercase;
  text-decoration: underline; text-underline-offset: 4px;
  transition: color 0.2s ease;
}
/* invisible expanded hit area, same idiom as .social-links a::before above —
   taller than wide since these links sit in a single-line row with a tight
   mobile gap, so a symmetric inset would make adjacent links' hit areas overlap */
.header-nav a::before {
  content: "";
  position: absolute;
  inset: -16px -8px;
}
.header-nav a:hover, .header-nav a:focus-visible { color: var(--amber); }
/* current-page marker used to live here as an orange override; the
   .section-rail below now owns that job, so every link in this row reads
   the same regardless of which page you're on. */

/* ============ Mobile nav toggle + slide-in panel ============
   The link row used to drop to a second fixed row under the logo on narrow
   viewports — with a header-nav collision against those wrapped rows. Now
   it collapses to a single hamburger icon (same corner as the desktop row)
   that opens the actual links as a right-edge panel, so the fixed header
   never grows past one row. Hidden entirely above the breakpoint, where
   .header-nav's normal inline row keeps running unchanged and this
   button/scrim/JS have nothing to do.

   The breakpoint was 720px while the row held four links. "Bli frivillig"
   made it five, and .header-nav is centered across the full width while
   .header-logo and the socials/.corner-right are pinned to the corners —
   so a wider row eats into the corners from both sides rather than
   wrapping (flex-wrap only fires once the row exceeds the whole viewport,
   long after it has run into the icons). Measured against index.html, the
   tightest of the five because .corner-right carries the "Lyd" toggle as
   well as the socials: the five-link row only clears that corner from
   about 950px up, so the panel now takes over below 960px. */
.nav-toggle {
  display: none;
  position: fixed;
  /* content-sized (not a padded 44px box) so its bars start flush at the
     same `top` as .header-logo/.social-links instead of sitting centered
     partway down an invisible box — that mismatch was what made it read
     as "not inline" with the corner icons. The 44px+ tap target instead
     comes from ::before below, same idiom as .social-links a::before. */
  top: calc(clamp(0.9rem, 3vh, 1.75rem) + env(safe-area-inset-top, 0px));
  left: 50%;
  transform: translateX(-50%);
  z-index: 8;
  width: clamp(18px, 2.4vw, 22px);
  flex-direction: column; gap: 6px;
  background: none; border: none; padding: 0; cursor: pointer;
  /* fades in on its own (opacity only) rather than joining the shared
     fadeUp list below — that animation ends by resetting `transform` to
     translateY(0), which would silently cancel this element's own static
     translateX(-50%) centering once the entrance finishes (the same trap
     documented on .section-rail elsewhere in this file) */
  opacity: 0;
  animation: fadeIn 0.9s ease forwards;
  animation-delay: 0.1s;
}
.nav-toggle::before {
  content: "";
  position: absolute;
  inset: -14px;
}
.nav-toggle span {
  display: block; width: 100%; height: 2px; border-radius: 1px;
  background: var(--caption);
  transition: transform 0.25s ease, opacity 0.2s ease, background 0.2s ease;
}
.nav-toggle:hover span, .nav-toggle:focus-visible span { background: var(--amber); }
/* morphs into an X once open, so the same button both opens and closes it */
body.nav-open .nav-toggle span:nth-child(1) { transform: translateY(8px) rotate(45deg); }
body.nav-open .nav-toggle span:nth-child(2) { opacity: 0; }
body.nav-open .nav-toggle span:nth-child(3) { transform: translateY(-8px) rotate(-45deg); }

.nav-scrim {
  display: none;
  position: fixed; inset: 0; z-index: 6;
  background: rgba(4, 7, 12, 0.6);
  backdrop-filter: blur(4px);
  opacity: 0; pointer-events: none;
  transition: opacity 0.3s ease;
}
body.nav-open .nav-scrim { opacity: 1; pointer-events: auto; }

@media (max-width: 960px) {
  .nav-toggle { display: flex; }
  .nav-scrim { display: block; }
  body.nav-open { overflow: hidden; }

  /* the inline link row becomes a right-edge panel; `right` (not
     `transform`) drives the open/closed state on purpose — this element
     also carries the shared fadeUp entrance animation above, which animates
     `transform`, and that animation's own final translateY(0) would
     silently overwrite a transform-based slide once it finishes (same trap
     noted on .section-rail elsewhere in this file). -400px clears the
     panel's own max width (280px) by a comfortable margin so it's always
     fully off-screen at rest, on any viewport. */
  .header-nav {
    top: 0; left: auto; right: -400px; bottom: 0;
    z-index: 7;
    width: min(280px, 78vw); height: 100dvh;
    flex-direction: column; flex-wrap: nowrap;
    justify-content: center; align-items: flex-start;
    gap: 2rem; row-gap: 2rem;
    padding: clamp(28px, 8vw, 48px);
    padding-top: calc(clamp(28px, 8vw, 48px) + env(safe-area-inset-top, 0px));
    padding-right: calc(clamp(28px, 8vw, 48px) + env(safe-area-inset-right, 0px));
    overflow-y: auto;
    background: linear-gradient(180deg, #0e1626, #0a0f1a);
    border-left: 1px solid rgba(147, 166, 194, 0.18);
    box-shadow: -40px 0 80px rgba(0, 0, 0, 0.55);
    transition: right 0.4s var(--ease);
  }
  body.nav-open .header-nav { right: 0; }
  .header-nav a { font-size: 15px; letter-spacing: 0.12em; }
}

/* ============ Section rail — om-jubileet.html / kontakt.html /
   returnerende.html / frivillig.html only. A quiet vertical "you are here",
   a sitemap on the first three and an in-page table of contents on
   frivillig.html (see [data-spy] and rail.js). Styled after
   index.html's .depth stops (see styles.css) but never a progress bar:
   no fill, just the current stop lit amber and the rest dimmed. The three
   sitemap rails have nothing to derive a position from and so are wholly
   static; frivillig.html's follows the scroll, but only to swap which of
   its four stops is lit. Same 34vh line height as .depth on index.html, so
   the two read as the same component. Only shown once there's genuinely
   free margin beside the centered .wrap column to sit in — kontakt.html's
   and frivillig.html's .wrap are the widest at 860px, so 1280px leaves a
   comfortable ~210px either
   side, more than this rail's own footprint, with room to spare on the
   narrower pages too. Hidden below that rather than repositioned, same
   as .depth on index.html, since there's no good spot for it once the
   .wrap column itself starts to fill the viewport. */
.section-rail {
  display: none;
  position: fixed; left: clamp(20px, 4vw, 48px);
  /* vertical centering used to be top:50% + transform:translateY(-50%), but
     this element also carries the shared fadeUp entrance animation below,
     which animates `transform` too — its final translateY(0) silently wins
     over this rule's own translateY(-50%) once the fade-in finishes (same
     trap noted on .header-nav above), leaving the rail pinned at top:50%
     instead of centered. margin-top does the same centering job (half of
     .section-rail-row's 34vh height) without touching `transform`, so it
     survives the animation — and the extra rise moves the rail up to match
     the raised title/eyebrow above. */
  top: 50%;
  margin-top: calc(-17vh - clamp(1.25rem, 4vh, 2.75rem));
  z-index: 5;
}
.section-rail-row { display: flex; flex-direction: row-reverse; align-items: center; gap: 16px; }
/* the line itself now reads as orange (dim base tone), with a brighter
   glowing segment marking which of the four stops is the current page —
   position set per page via [data-current] on the <nav>, since there's no
   scroll position to derive it from the way .depth-fill does on index.html */
.section-rail-line {
  position: relative;
  width: 1px; height: 34vh; border-radius: 1px;
  background: rgba(255, 138, 61, 0.22);
}
/* top is set per page below as an absolute distance from the line's own
   top/bottom, not a %+translate(-50%) — a % position combined with a
   centering transform lets the segment overshoot the line at the very top
   or bottom stop, quietly shortening or lengthening how much base line is
   left showing above/below it and making the bar read as a different
   length page to page. Anchoring it inside the line's own bounds instead
   keeps the full 34vh line visible on every page. .section-rail-stops is
   space-between, so N stops sit at even i/(N-1) fractions of the line and
   each segment below is placed at its own stop's fraction — 0%, 25%, 50%,
   75%, 100% for the five-page sitemap rail, 0%, 33.3%, 66.7%, 100% for
   frivillig.html's four-category one. The two sets can't share numbers,
   which is why every stop is listed out by name rather than computed. */
.section-rail-line::after {
  content: "";
  position: absolute; left: 50%; transform: translateX(-50%);
  width: 3px; height: 26px; border-radius: 2px;
  background: var(--amber);
  box-shadow: 0 0 10px 1px rgba(255, 122, 30, 0.55);
  /* static on the sitemap rails (one [data-current] for the whole page
     load, so this never fires); on frivillig.html's scroll-spy rail it is
     what makes the segment slide between stops instead of snapping */
  transition: top 0.35s var(--ease);
}
.section-rail[data-current="om"] .section-rail-line::after { top: calc(25% - 13px); }
.section-rail[data-current="kontakt"] .section-rail-line::after { top: calc(50% - 13px); }
.section-rail[data-current="retur"] .section-rail-line::after { top: calc(75% - 13px); }
.section-rail[data-current="frivillig"] .section-rail-line::after { top: calc(100% - 26px); }
/* frivillig.html's own rail — categories within the page, not other pages.
   "bar" is the first stop and so needs no rule: with no `top`, the segment
   falls at its static position, the top of the line. */
.section-rail[data-current="vertskap"] .section-rail-line::after { top: calc(33.333% - 13px); }
.section-rail[data-current="arrangement"] .section-rail-line::after { top: calc(66.667% - 13px); }
.section-rail[data-current="kultur"] .section-rail-line::after { top: calc(100% - 26px); }
.section-rail-stops {
  list-style: none; height: 34vh; text-align: left;
  display: flex; flex-direction: column; justify-content: space-between;
}
.section-rail-link {
  position: relative; display: block;
  font-family: var(--sans); font-size: 11px; font-weight: 500;
  letter-spacing: 0.18em; text-transform: uppercase; white-space: nowrap;
  color: var(--caption); opacity: 0.6;
  transition: color 0.2s ease, opacity 0.2s ease;
}
.section-rail-link::before {
  content: ""; position: absolute; left: -16px; top: 50%; transform: translateY(-50%);
  width: 8px; height: 1px; background: currentColor; opacity: 0.7;
}
.section-rail-link:hover, .section-rail-link:focus-visible { color: var(--amber); opacity: 1; }
/* matches any aria-current value: "page" on the sitemap rails, "true" on
   frivillig.html's in-page one, where the target is a section rather than
   another page */
.section-rail-link[aria-current] { color: var(--amber); opacity: 1; font-weight: 600; }

@media (min-width: 1280px) {
  .section-rail { display: block; }
}

/* ============ Shared content components (index.html's modal) ============ */
.tl { list-style: none; border-left: 1px solid rgba(255,150,80,0.24); padding-left: 22px; margin: 8px 0; }
.tl li { position: relative; margin-bottom: 24px; }
.tl li::before { content: ""; position: absolute; left: -27px; top: 6px; width: 9px; height: 9px; border-radius: 50%; background: var(--amber); }
.tl .yr { font-family: var(--serif); font-size: 26px; color: var(--platinum); display: block; margin-bottom: 4px; }

.contact-row { display: flex; justify-content: space-between; padding: 12px 0; border-bottom: 1px solid rgba(255,255,255,0.06); }
.contact-row a { color: var(--amber); text-decoration: none; }

.btn {
  display: inline-block; margin-top: 25px; padding: 13px 26px;
  background: var(--amber); color: #150c04; text-decoration: none;
  font-family: var(--sans); font-size: 12px; font-weight: 600; letter-spacing: 0.2em; text-transform: uppercase;
  border-radius: 100px; transition: transform 0.25s var(--ease), background 0.25s;
}
.btn:hover { transform: translateY(-2px); background: #ff8a34; }
.btn.ghost { background: none; color: var(--amber); border: 1px solid rgba(255,122,30,0.4); }

/* ============================================================
   Simple content pages — shared skeleton
   om-jubileet.html, kontakt.html and returnerende.html all use
   this same shape: watermark behind, header-logo/header-nav/social-links
   fixed at the top, and a centered .wrap column below. Each page's own
   <style> only adds what's specific to its content (headings, body copy,
   extra elements, and its own max-width/padding on .wrap).

   The centering itself is a deliberate port of index.html's own
   .floor--atrium (see styles.css) — a fixed 100dvh box with its content
   vertically centered rather than pinned to the top, so these pages read
   as the same "hero" as the countdown does, just with their own content
   standing in its place. */
.simple-page {
  line-height: 1.5;
  position: relative;
  overflow-x: hidden;
  overflow-y: auto;
  height: 100dvh;
  display: flex;
  flex-direction: column;
}

/* ---- The one simple page whose content genuinely doesn't fit a screen
   (frivillig.html, six role cards). .simple-page above pins the body to
   100dvh and scrolls *inside* it, which is right when the content is a
   paragraph or two but wrong here: it hands the scroll to <body> instead
   of the viewport, so `scroll-behavior: smooth` on <html> never applies to
   the in-page category anchors, and mobile browsers stop collapsing their
   toolbars on scroll. Letting the document itself grow fixes both. The
   page must also lift html's own height:100% (see the rule in its <style>)
   — this alone would leave that clamp in place. ---- */
.simple-page--long {
  height: auto;
  min-height: 100dvh;
}

.wrap {
  position: relative;
  z-index: 2;
  flex: 1;
  width: 100%;
  max-width: var(--wrap-width);
  margin: 0 auto;
  display: flex;
  flex-direction: column;
}

/* wraps everything except .date-footer, so the footer below can sit at a
   fixed distance from the bottom on every page instead of drifting with
   however tall that page's own content happens to be (a 3-card contact
   grid vs. a single short paragraph). min-height:0 lets this flex item
   shrink below its content's intrinsic height so "safe center" can still
   center that content within whatever space is actually left above the
   footer, rather than forcing .wrap itself to grow. */
.page-body {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  justify-content: safe center;
}

/* uses --eyebrow-size/--eyebrow-tracking (defined once in :root above) so
   this always reads as the same design element as the hero's own .eyebrow
   (styles.css) and as .date-footer p below — never three slightly-different
   copies. Sits below the page's heading now (each page's own markup places
   it right after the h1) — margin-top left small/plain here since spacing
   is tuned per page. */
.page-eyebrow {
  margin-top: 0.6rem;
  font-size: var(--eyebrow-size);
  font-weight: 500;
  letter-spacing: var(--eyebrow-tracking);
  text-transform: uppercase;
  color: var(--accent);
  text-align: center;
  /* raises the title+eyebrow pair without moving the content below them
     (.message/.people/.letter etc. stay in their normal-flow position) —
     each simple page also runs the fadeUp entrance animation on this and
     .page-title, which animates `transform`, so a static transform here
     would get silently overwritten once that finishes (see .section-rail
     above for the same trap); top+position:relative sidesteps it since it
     doesn't touch `transform` at all. */
  position: relative;
  top: clamp(-2.75rem, -4.5vh, -1.25rem);
}

/* ---- Landscape phones: shrink the watermark and eyebrow so short viewports
   (phone landscape heights ~320-430px) don't need to rely on the scroll
   fallback. Identical on every simple page, so it lives here once; each
   page's own landscape query keeps only what's genuinely page-specific
   (wrap padding, heading/letter/message sizing). ---- */
@media (orientation: landscape) and (max-height: 500px) {
  .watermark { font-size: clamp(5rem, 34vh, 10rem); }
  .page-eyebrow { margin-bottom: 0.4rem; font-size: 0.64rem; }
}

/* ============ Shared page heading — om-jubileet.html / kontakt.html /
   returnerende.html's big h1. Font-family/weight/size are guaranteed
   identical here rather than three pages each hardcoding their own copy;
   size comes from --title-size (set per page, see :root above) since that
   legitimately varies with each page's content; line-height/margin stay
   page-specific (each page's own .page-title rule) for the same reason. */
.page-title {
  font-family: var(--display);
  font-weight: 800;
  font-size: var(--title-size);
  /* see .page-eyebrow below for why this uses top instead of transform */
  position: relative;
  top: clamp(-2.75rem, -4.5vh, -1.25rem);
}

/* ============ Shared "hold av datoen" closer — om-jubileet.html /
   kontakt.html / returnerende.html ============
   Same hairline + letterspaced date treatment as index.html's own
   .floor--atrium .footer (see styles.css), ported here for the pages that
   don't have that hero layout to sit inside — and sharing --eyebrow-size/
   --eyebrow-tracking with .page-eyebrow above so the two bookend the page
   as a matched pair, exactly like the hero's own eyebrow/footer do. */
.date-footer {
  margin-top: clamp(2rem, 6vh, 4rem);
  text-align: center;
}
.date-footer hr {
  border: none;
  border-top: 1px solid rgba(147, 166, 194, 0.25);
  width: 160px;
  margin: 0 auto clamp(1rem, 2.5vh, 1.6rem);
}
.date-footer p {
  font-size: var(--eyebrow-size);
  font-weight: 500;
  letter-spacing: var(--eyebrow-tracking);
  text-transform: uppercase;
  color: var(--accent);
}
.date-footer .save-date { margin-bottom: 0.5rem; }

/* ============ Shared entrance fade — chrome present on every simple page
   (om-jubileet.html / kontakt.html / returnerende.html only; index.html's
   hero has its own timing/wrapper — .corner-right, 0.2s delay — see
   styles.css). Each page's own <style> keeps only its content-specific
   fade list/delays. ============ */
.header-logo, .header-nav, .section-rail, .social-links {
  opacity: 0;
  animation: fadeUp 0.9s ease forwards;
  animation-delay: 0.1s;
}
@media (prefers-reduced-motion: reduce) {
  .header-logo, .header-nav, .nav-toggle, .section-rail, .social-links {
    animation: none;
    opacity: 1;
  }
}

:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 4px; }

@keyframes fadeUp {
  from { opacity: 0; transform: translateY(18px); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes fadeIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}

