/* =========================
   FONTS
   All three fonts are stored as files in this project and are
   embedded here. Without these blocks, only visitors who happen
   to have the fonts installed would see the page as intended.

   Deliberately local instead of the Google CDN: otherwise every
   page view would send the visitor's IP address to Google. That is
   a data transfer under the GDPR and would need a legal basis and
   a note in the privacy policy. Served locally, the question never
   arises at all.

   Format WOFF2, supported by every current browser
   (Chrome/Edge/Firefox since 2016, Safari since 2020).

   Reduced twice: first from TTF to WOFF2 (1075 -> 416 kB), then on
   01.08.2026 cut down to the characters actually in use
   (416 -> 96 kB). Cardo alone brought more than 3800 glyphs with it
   - Greek, Cyrillic, Old Norse. 212 remain: basic Latin, Western
   Europe and typography. Hungarian special characters are NOT
   included, by Yvonne's decision; the website is English only.

   Verified unchanged: 91 characters per font measured in the
   browser (advance width identical down to 0.00 px, whole sentences
   likewise), plus an outline-by-outline comparison. The tools for
   that are in tools/. The untouched originals are kept in a backup
   folder outside this repository.

   NO fallback fonts in the font-family declarations. That is
   intentional: browsers substitute per character, so a missing
   letter would turn up mid-word in a different font. It was checked
   that all three fonts cover every character occurring on the site,
   including umlauts and typographic quotation marks.

   One gap remains: Viking has no euro sign. If one appears in a
   heading, it shows in the system font. So for prices use Uncial
   Antiqua or Cardo.
========================= */
/* The two display fonts are used in the headings and carry the brand.
   With font-display: swap the browser first shows the fallback font and
   then swaps it out - that flash was visible on every page change. With
   "block" it waits briefly instead and draws correctly right away. That
   is safe here, because both files are tiny (15 and 19 kB) and are
   preloaded in the <head>. */
@font-face {
  font-family: 'Viking';
  src: url("fonts/Viking-v2.woff2") format("woff2");
  font-weight: normal;
  font-style: normal;
  font-display: block;
}

@font-face {
  font-family: 'Uncial Antiqua';
  src: url("fonts/UncialAntiqua-Regular-v2.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: block;
}

/* Cardo carries the body text.

   Until 01.08.2026 this said "swap": the browser first shows its own
   default font and then swaps it out. Because the font-family
   declarations deliberately contain NO fallback, it reaches for a font
   with quite different letter widths - and the entire text reflows.
   Measured on about_me.html: the last paragraph jumped by 103 px and the
   page grew 107 px taller. That is exactly what Yvonne noticed as "the
   page hops when I switch tabs".

   Now "block", like the display fonts: the browser waits briefly and
   draws correctly right away. Safe, because the file comes from our own
   server and Cardo-Regular is preloaded in the <head>. */

@font-face {
  font-family: 'Cardo';
  src: url("fonts/Cardo-Regular-v2.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: block;
}

@font-face {
  font-family: 'Cardo';
  src: url("fonts/Cardo-Italic-v2.woff2") format("woff2");
  font-weight: 400;
  font-style: italic;
  font-display: block;
}

@font-face {
  font-family: 'Cardo';
  src: url("fonts/Cardo-Bold-v2.woff2") format("woff2");
  font-weight: 700;
  font-style: normal;
  font-display: block;
}

/* =========================
   GLOBAL BASE
========================= */
html {
  /* The width of the page, in ONE place.

     The body is limited to this and centred; everything wider shows the
     black background at the sides. That letterbox look is intended.

     Six rules depend on this value and must agree: the body, the inner
     part of the bars, the fixed footer bar and the frozen background
     logo. They all read it from here, so changing the width is a
     one-line job.

     1920 px is the width the site was designed at, on a 3440 px wide
     screen. That stays untouched: narrowing the column makes every page
     TALLER, because the text wraps more often, and on that monitor
     about_me then no longer fits on one screen. Measured on 02.10.2026:
     1193 px of content at 1920, 1274 px at 1720.

     The black bars left and right are intended. On a screen exactly
     1920 px wide there was nothing left for them, so they disappeared
     there. The media query below gives those screens a narrower page so
     the bars come back - without touching anything on wider screens.

     Why 1720 and not less: the title "Viking-Celtic Tattoo" needs
     1719 px on one line (1559 px of text plus 160 px padding). Below
     that it wraps and the header grows from 254 to 380 px. */
  --page-width: 1920px;

  /* Height of the title area and of the navigation bar.

     The two gallery pages pin their navigation bar with
     "top: var(--fog-header-h)". Until 02.10.2026 that variable was set
     by JavaScript only, so until the script had run the fallback of
     15rem = 240 px applied - while the header is actually 254 px tall
     (190 px on narrow screens). The bar therefore sat 14 px too high at
     first and dropped into place the moment the script corrected it:
     the hop Yvonne saw on every visit to those two pages.

     Declared here, the value is right from the first frame. The scripts
     still measure and set it afterwards; they arrive at the same number
     now, so nothing moves.

     254 = 126 px line box + 2 x 64 px padding. Keep in step with
     header h1 if that ever changes. */
  --fog-header-h: 254px;
  --fog-nav-h: 61px;

  background-color: #000;
  scroll-behavior: smooth;

  /* Always keep room for the scrollbar, even when the page is short
     enough not to need one. Otherwise a short page like
     client_work.html is 15 px wider than the long ones, and clicking a
     menu item makes the whole content jump sideways. */
  scrollbar-gutter: stable;
}

body {
  background-color: #511824;
  color: #fff;

  max-width: var(--page-width);
  min-height: 100vh;
  margin: 0 auto;

  position: relative;
  z-index: 0;

  display: flex;
  flex-direction: column;
}

/* Background logo (inside the red body, bottom-right) */
body::before {
  content: "";

  /* Pinned to the window, not to the page - on every page, the same way
     the two gallery pages have always done it.

     Why: anchored to the page the logo sat at the BOTTOM OF THE
     DOCUMENT. On a page that fits the screen that is the lower edge of
     the window, but on a longer page like about_me it is far below it,
     so on arriving there you saw much less of the logo than on the home
     page - it looked like a different size. Pinned to the window it is
     identical everywhere and stays put while scrolling. Yvonne's wish,
     02.10.2026.

     The right edge follows the centred page body: the body is centred
     within --page-width, a fixed element however aligns to the window.
     Same calculation as for the footer bar. */
  position: fixed;
  bottom: 0;
  right: max(0px, calc((100vw - var(--page-width)) / 2));

  width: 900px;

  /* 900 x 900 as designed. The logo may reach up behind the title
     area on a short window - it stays invisible there, because the
     header has its own opaque background (see below). */
  height: 900px;

  background-image: url("../images/logos/Logo_VCT-black-white2.png");
  background-repeat: no-repeat;
  background-size: contain;
  background-position: right bottom;

  opacity: 0.05;
  pointer-events: none;
  z-index: 0;
}

/* Keep all content above the background logo */
header, nav, main, footer, .page-wrapper {
  position: relative;
  z-index: 1;
}

/* =========================
   HEADER
========================= */
/* The title area gets the page colour as its own background.

   Without it the header is transparent, and on a short window the
   background logo - which hangs at the bottom and is 900 px tall -
   reached up through the title and looked as though it ran past the
   navigation bar. The bar itself was never the problem: it is opaque
   gold and sits above the logo anyway.

   The colour is the same #511824 as the body, so nothing looks
   different; the logo is simply hidden behind the title area now and
   keeps its full size on every screen. Measured on 02.10.2026. */
header {
  background-color: #511824;
}

header h1:first-child {
  font-family: 'Viking';

  /* Important: headings are bold (700) by default in the browser.
     Viking, however, exists in one weight only. If the bold one is
     missing the browser invents it and thickens the letters
     artificially - on G and A that shows up as a frayed double stroke.
     font-synthesis: none forbids this imitation on top of that. */
  font-weight: normal;
  font-synthesis: none;

  font-size: 6rem;

  /* Fixed line height, so the height of the title area does NOT depend
     on which font is currently rendering it.

     With line-height: normal the browser takes the line box from the
     font's own metrics. While 'Viking' is still loading the fallback
     font applies, and that one is 15 px shorter: the header was 239 px
     instead of 254. The moment Viking arrived the header grew and
     pushed the navigation bar down - a visible hop on every page view.
     It showed up mainly on the two gallery pages, because there the
     animation library and the images load at the same time and the
     font arrives after the first paint. Measured on 02.10.2026.

     1.3125 x 96 px = 126 px, exactly the line box Viking produced, so
     nothing looks different - it is just no longer variable. */
  line-height: 1.3125;

  margin: 0;
  padding: 4rem 5rem;
  text-align: center;
}

/* =========================
   FULL-WIDTH BARS (NAV + FOOTER BAR)
   -> Bars go to the edge of the RED body
   -> Inner keeps same left/right padding as content
========================= */
.bar {
  background-color: #AC9362;
  width: 100%;
}

.bar__inner {
  max-width: var(--page-width);
  margin: 0 auto;
  padding: 0 5rem;
}

.bar__inner--center {
  text-align: center;
}

/* =========================
   NAVIGATION
========================= */
nav.bar {
  margin: 0 0 5rem;
}

nav.bar ul {
  display: flex;
  flex-wrap: nowrap;
  list-style: none;

  padding: 0;
  margin: 0;

  justify-content: center;

  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

nav.bar li {
  flex: 0 0 auto;
  border-left: 1px solid #fff;
}

nav.bar li:first-child {
  border-left: none;
}

nav.bar a {
  display: block;
  padding: 1rem 1.25rem;

  text-align: center;
  white-space: nowrap;

  font-family: 'Uncial Antiqua';
  font-size: 22px;
  letter-spacing: 0.04em;

  color: #fff !important;
  text-decoration: none;
  text-underline-offset: 3px;
}

nav.bar a[aria-current="page"],
nav.bar a:hover,
nav.bar a:focus {
  background-color: #816b3f;
  color: #fff !important;
  text-decoration: underline;
}

/* =========================
   PAGE WRAPPER (push footer down)
========================= */
.page-wrapper {
  flex: 1;

  /* Room for the fixed footer bar. Measured: 50 px high, on a phone
     67 px (the text wraps onto two lines there). 5rem = 80 px leaves
     some air. Without this line the last paragraph of every page would
     disappear behind the bar. */
  padding-bottom: 5rem;
}

/* =========================
   MAIN CONTENT (TYPOGRAPHY)
========================= */
main.custom_main {
  font-family: 'Cardo';
  font-size: 20px;

  margin: 0;
  padding: 1rem 5rem;
}

.custom_main h2,
.custom_main h3 {
  font-family: 'Uncial Antiqua';

  /* Same reason as for h1: Uncial Antiqua has only one weight, so the
     browser would otherwise imitate the bold one. */
  font-weight: normal;
  font-synthesis: none;

  letter-spacing: 0.02em;
}

.custom_main h2 {
  font-size: 40px;
  margin: 0 0 2rem;
}

.custom_main h3 {
  font-size: 28px;
  margin: 2rem 0 1rem;
}

.custom_main p {
  margin: 0 0 1.5rem;
}

.custom_main .intro-text {
  margin-top: 2.5rem;
}

.custom_main p + ul {
  margin-top: 2rem;
}

.custom_main > ul {
  margin: 0 0 4rem;
  padding-left: 1.2rem;
}

.custom_main > ul > li {
  margin-bottom: 0.5rem;
}

/* Links in content */
.custom_main a {
  color: #816b3f;
  text-decoration: underline;
  text-decoration-color: #AC9362;
  text-underline-offset: 3px;
  transition: color 0.2s ease;
}

.custom_main a:hover,
.custom_main a:focus {
  color: #fff;
}

/* Special “calendar” mark */
.calendar-mark {
  font-family: 'Viking';
  letter-spacing: 0.06em;
  font-size: 1.05em;
  color: inherit;
}

/* =========================
   FOOTER BAR
   ---------------------------------------------------------
   Sticks to the bottom edge of the window since 01.08.2026 - on EVERY
   page, just like the title and the navigation at the top. Yvonne's
   wish.

   The former "Up" button was dropped along with it: the page no longer
   ends in a footer you scroll down to. So nobody has to travel back up
   from the bottom either.
========================= */
.site-footer {
  position: fixed;
  bottom: 0;

  /* Above the frozen header area (z-index 10) and above the gallery
     images (z-index 1). Otherwise the images would slide in front of
     the bar while scrolling. */
  z-index: 20;

  /* The page body is limited to --page-width and centred. A fixed
     element, however, aligns itself to the WINDOW and not to the body -
     without these two lines the bar would be wider than the page above
     it on wide screens. Same reasoning as for the frozen background
     logo further down. */
  left:  max(0px, calc((100vw - var(--page-width)) / 2));
  right: max(0px, calc((100vw - var(--page-width)) / 2));

  padding: 0; /* important: the bar touches the bottom edge */
}

/* Footer bar */
.bar--footer {
  margin: 0; /* sits right at the bottom */
}

/* Copyright text centered INSIDE the bar */
.copyright-box {
  display: inline-block;
  padding: 0.9rem 0;

  font-family: 'Uncial Antiqua';
  font-size: 16px;
  letter-spacing: 0.04em;

  color: #fff;
}

/* About me page */
p.email_link_margin_top {
  margin-top: 50px;

  /* The e-mail address and the "Main brand" line below it belong
     together, so they sit closer than two normal paragraphs: 0.5rem
     instead of the usual 1.5rem. The 50px above keeps them clearly
     separated from the body text. */
  margin-bottom: 0.5rem;
}

/* ======================================
   Frozen header area

   Applies to the two pages with an image gallery:
   my_equipment.html  (body class="page-equipment")
   learning_journey.html (body class="page-learning")

   Title, navigation and text block stay in place while scrolling,
   while the images run past underneath.

   The heights --fog-header-h, --fog-nav-h and --fog-head-top are
   measured at runtime by javascript/valknut-gallery.js and
   javascript/rune-wheel.js - fixed values would not work, because the
   heading wraps to a different height depending on the window width.

   About the name: the abbreviation "fog" comes from the original fog
   effect that was removed on 31.07.2026. The classes still carry the
   name, because both pages use it in their HTML.
====================================== */

/* ---- 1. Freeze title + navigation -------------------- */
body.page-equipment > header,
body.page-learning > header {
  position: sticky;
  top: 0;
  z-index: 10;
}

body.page-equipment > nav.bar,
body.page-learning > nav.bar {
  position: sticky;
  top: var(--fog-header-h, 15rem);
  z-index: 10;
}

/* Inside the frozen header area the text sits tighter than in normal
   body copy. The reason: the block is fixed at the top while the footer
   bar is fixed at the bottom - the room between them is limited.
   Measured on 01.08.2026: with the normal spacing the block was 348 px
   high and the last paragraph disappeared behind the footer bar. With
   these values it is 297 px. For comparison: my_equipment.html, with a
   single paragraph, comes to 219 px. */
.fog-head h2 {
  margin-bottom: 1rem;
}

.fog-head p {
  margin-bottom: 0.8rem;
}

.fog-head p:last-child {
  margin-bottom: 0;
}

/* ---- 2. Freeze the text block -----------------------
   Sticks directly below the navigation bar. NO
   background: there is no opaque surface left that could
   cover anything. Instead the images dissolve before
   they reach this line. */
body.page-equipment .fog-head,
body.page-learning .fog-head {
  position: sticky;

  /* only as wide as the text itself - that way the script
     knows where there is room for the images to its right */
  width: max-content;
  max-width: 100%;

  /* freezes exactly at its own position
     (--fog-head-top is measured by the two gallery scripts) */
  top: var(--fog-head-top, calc(var(--fog-header-h, 15rem) + var(--fog-nav-h, 4rem)));
  z-index: 5;
}

/* ---- 3. The background logo needs no special rule here any more.
   It is pinned to the window on every page since 02.10.2026, see
   body::before further up. ---------------------------------- */

/* ======================================
   Valknut Reveal (image gallery)
   Width and position are calculated by
   javascript/valknut-gallery.js.
====================================== */

.vk-gallery {
  /* width and left margin come from
     javascript/valknut-gallery.js; this here is only the
     state before the script has done its maths */
  width: min(700px, var(--vk-img-w, 60vh));
  margin: 0 auto 8rem;

  position: relative;
  z-index: 1;
}

/* Each image gets a tall section, ...*/
.vk-slot {
  position: relative;
}

/* ... in which it stays put while it opens */
.vk-frame {
  position: sticky;
  top: var(--vk-top, 30vh);

  margin: 0;
  padding: 0;
  width: 100%;
}

.vk-svg {
  display: block;
  width: 100%;
  height: auto;
}

/* The band: a wide gold stroke with a narrow core in the
   page colour, plus the gap at the crossings */
.vk-gap {
  fill: none;
  stroke: #511824;
  stroke-width: 24;
  stroke-linejoin: miter;
}

.vk-band {
  fill: none;
  stroke: #AC9362;
  stroke-width: 15;
  stroke-linejoin: miter;
}

.vk-core {
  fill: none;
  stroke: #511824;
  stroke-width: 7;
  stroke-linejoin: miter;
}

/* On the Learning Journey page the stage is the LAST element of the
   page. Any spacing below it would be scroll distance left over after
   the rotation has finished - and in exactly that distance the sticky
   wheel comes loose from its position and travels up out of view.
   Measured on 01.08.2026 that was 160 px (the inner spacing of main and
   page-wrapper, plus the bottom margin of the stage). Yvonne's
   observation: "the image still hops upwards".

   The footer bar stays clear all the same: the wheel ends exactly at
   its top edge, because rune-wheel.js subtracts its height.

   ONLY from 901 px window width upwards. Below that no wheel runs, but
   the simple grid (.rune-static) - and there the eight images sit one
   below the other and do need the spacing. Without the media query the
   last image on a phone disappeared 67 px behind the footer bar. The
   threshold matches the one in rune-wheel.js:
   matchMedia("(max-width: 900px)"). */
@media (min-width: 901px) {
  body.page-learning .page-wrapper,
  body.page-learning .custom_main {
    padding-bottom: 0;
  }

  body.page-learning .rune-stage {
    margin-bottom: 0;
  }
}

/* ======================================
   Rune wheel / Vegvisir (Learning Journey)
   The height of the stage and the dimensions
   of the wheel are calculated by
   javascript/rune-wheel.js.
====================================== */

.rune-stage {
  position: relative;
  margin: 2rem 0 4rem;
}

/* The wheel stays in place while the stage scrolls past.
   Position and height = the free area below the frozen
   text (calculated by rune-wheel.js). */
.rune-wheel {
  position: sticky;
  top: var(--rune-top, 0px);
  height: var(--rune-h, 100vh);
}

/* The oval track in the middle */
.rune-hub {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);

  opacity: 0.24;
  pointer-events: none;
  overflow: visible;
}

/* rune-wheel.js draws an <ellipse> and nothing else. The rules for
   <line> and <circle> formerly kept here came from a discarded spoked
   cross and applied nowhere - removed on 31.07.2026. Should the spoked
   cross come back, put them in again here. */
.rune-hub ellipse {
  fill: none;
  stroke: #AC9362;
  stroke-width: 4.5;      /* the track the images run on */
  stroke-linecap: round;
}

/* Yvonne's own Vegvisir in the middle.
   The PNG is black; as a mask over a golden surface it
   appears in the colour of the page.
   The size is set by javascript/rune-wheel.js. */
.rune-emblem {
  display: block;
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  z-index: 0;

  opacity: 0.42;
  pointer-events: none;
}

.rune-static .rune-emblem {
  display: none;
}

/* One image on the wheel */
.rune-item {
  position: absolute;
  left: 50%;
  top: 50%;

  width:  var(--rune-focus, 260px);
  height: var(--rune-focus, 260px);
  margin: calc(var(--rune-focus, 260px) / -2) 0 0 calc(var(--rune-focus, 260px) / -2);

  will-change: transform, opacity;
}

.rune-item img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;          /* nothing gets cut off */
}

/* Safety net: without the JavaScript animation, simply a grid */
.rune-static .rune-wheel {
  position: static;
  height: auto;

  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 1rem;
}

.rune-static .rune-item {
  position: static;
  width: auto;
  height: auto;
  aspect-ratio: 1;
  margin: 0;
  transform: none;
  opacity: 1;
}

.rune-static .rune-hub {
  display: none;
}


/* =========================================================
   SCREENS UP TO 1920 px
   ---------------------------------------------------------
   Everything in here applies to narrower screens ONLY. On the 3440 px
   monitor the site was designed on, none of it applies - that view has
   to stay exactly as it is.

   The problem these rules solve: a 1920 x 1080 screen leaves the
   browser only about 940 px of usable height once the window bars and
   the Windows taskbar are gone. Title area and navigation bar take
   254 + 61 px of that, so barely 600 px are left for a background logo
   that is 900 px tall. It was cut off at the top by 234 px, and the
   pages did not fit on one screen either. Measured on 02.10.2026.

   This block sits deliberately AT THE VERY END of the file. With equal
   specificity the later rule wins in CSS, so when it stood further up
   the base rules for the title and the logo below it simply overrode
   it again - it looked as though the media query had not matched at
   all. Add new exceptions for narrow screens HERE, not at the top.
   ========================================================= */
@media (max-width: 1920px) {
  /* Narrower page, so the black bars at the sides appear here too. On a
     screen exactly 1920 px wide there was no room left for them. */
  html {
    --page-width: 1720px;
  }

  /* Less air around the title: the header drops from 254 to 190 px.
     Those 64 px give the logo room AND make every page 64 px shorter,
     which is enough for the home page to fit on one screen again. */
  header h1:first-child {
    padding: 2rem 5rem;
  }

  /* The title area is 64 px shorter here, so the navigation bar of the
     gallery pages has to stick 64 px higher. 126 + 2 x 32 = 190. */
  html {
    --fog-header-h: 190px;
  }

  /* The logo only as tall as the space below the navigation bar, so it
     is never cut off. 17rem = 272 px covers the compact title area plus
     the bar. On a 940 px high window that makes the logo 668 px instead
     of 900 - smaller, but whole; background-size: contain scales the
     image with it.

     Both variants need this: the normal one and the fixed one on the
     two gallery pages. */
  body::before,
  body.page-equipment::before,
  body.page-learning::before {
    height: min(900px, calc(100vh - 17rem));
  }

}
