@font-face {
  font-family: 'Playfair Display';
  src: url('../fonts/playfair.woff2') format('woff2-variations');
  font-weight: 400 900;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Playfair Display';
  src: url('../fonts/playfair-italic.woff2') format('woff2-variations');
  font-weight: 400 900;
  font-style: italic;
  font-display: swap;
}
@font-face {
  font-family: 'Jost';
  src: url('../fonts/jost.woff2') format('woff2-variations');
  font-weight: 300 600;
  font-style: normal;
  font-display: swap;
}

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

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-weight: 400;
  /* 100vh on a phone means "viewport with the browser chrome retracted", a
     height the page never actually has on first paint — so the footer this
     min-height exists to push down starts one toolbar-height below the fold
     instead of at the bottom of it. dvh is the same number on desktop and
     the honest one on mobile; the vh line stays as the fallback. */
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
}

/* footer-sticky theme setting (default on): --main-flex is 1 in tokens.css,
   so main grows to fill the viewport and the footer sits at the bottom of a
   short page. theme-vars.html.twig overrides --main-flex to 0 when the
   setting is switched off, so main stops growing and the footer sits right
   after the content instead. */
main { flex: var(--main-flex, 1); }

/* The nav is position: sticky, so an in-page jump lands its target
   underneath the bar: #showreel from the gallery heading's link, #main from
   the skip link. scroll-margin-top pushes the landing point clear of the
   nav's own ~62px plus air. */
#main, #showreel { scroll-margin-top: var(--s80); }

::selection { background: var(--accent); color: var(--paper); }

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

a { color: var(--ink); text-decoration: none; }
a:hover { color: var(--accent); }

h1, h2, h3, p { margin: 0; }
p { text-wrap: pretty; }
h1, h2, h3 { text-wrap: balance; }

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

.skip-link {
  position: absolute;
  left: -9999px;
  background: var(--ink);
  color: var(--paper);
  padding: var(--s10) var(--s16);
  font-size: 12px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
}
.skip-link:focus {
  left: var(--s16);
  top: var(--s16);
  z-index: 100;
  color: var(--paper);
}

/* Shared type roles */
.display-1 {
  font-family: var(--serif);
  font-weight: 900;
  line-height: 0.9;
  letter-spacing: -0.02em;
}
.display-2 {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 400;
  line-height: 1;
  color: var(--accent);
}
.h1 {
  font-family: var(--serif);
  font-weight: 700;
  /* h1-size theme setting, desktop only — responsive.css fixes this at
     34px (<=900) and 30px (<=600) regardless of the configured value. */
  font-size: var(--h1-size, 44px);
  line-height: 1.05;
  letter-spacing: 0.02em;
}
.micro {
  font-size: 10px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--muted);
}
.micro-11 {
  font-size: 11px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--muted);
}
.eyebrow {
  font-family: var(--sans);
  font-weight: 500;
  font-size: 11px;
  letter-spacing: 0.34em;
  text-transform: uppercase;
}
.subhead {
  font-family: var(--serif);
  font-style: italic;
  color: var(--accent);
}
.body-copy { font-size: var(--body-size, 16px); line-height: 1.7; color: var(--ink-soft); }
.rule-line { height: 1px; background: var(--rule); border: 0; width: 100%; }

/* ---------- Prose: Markdown-authored page.content ----------
   Every `{{ page.content|raw }}` sink carries this class. Grav renders the
   client's Markdown to real HTML — paragraphs, lists, links, emphasis,
   sub-headings — but the reset above only zeroes <p> margins and nothing
   styles the rest, so before this block:

     - two paragraphs ran together as one solid slab wherever the container
       didn't already supply a flex gap of its own (default.html.twig and the
       404 page, which is every page the client creates in Admin until she
       picks a template);
     - a list fell back to the browser's 40px-indented disc bullets;
     - an inline link was --ink inside --ink-soft body text, i.e. essentially
       invisible, and identifiable by colour alone (WCAG 1.4.1) even if you
       did spot it.

   .om-body and .detail-body previously carried the flex column and gap
   inline in pages.css; that lives here now so all three sinks share one
   definition. */
.prose {
  display: flex;
  flex-direction: column;
  gap: var(--s16);
}
.prose > * { margin: 0; }

/* Underlined, not just recoloured — the rule is the same 1px --rule the
   theme already uses for .link-rule and .kontakt-email. */
.prose a {
  color: var(--accent);
  border-bottom: 1px solid var(--rule);
}
.prose a:hover { color: var(--ink); border-bottom-color: var(--ink); }

/* No `display` change on the list itself: block/flex/grid on a <ul> strips
   its list role in Safari + VoiceOver, so the indent is done with padding
   and the between-item rhythm is left to line-height. The nested selector
   (rather than `.prose > *`) also catches sub-lists. */
.prose :is(ul, ol) { margin: 0; padding-left: var(--s18); }
.prose li::marker { color: var(--label); }

.prose :is(h2, h3) {
  font-family: var(--serif);
  font-weight: 700;
  line-height: 1.2;
  color: var(--ink);
}
/* The one deliberate exception to "sibling groups use gap, never margins"
   (DESIGN_GUIDELINES.md §3). A flex `gap` is uniform by construction, so it
   can only say that a sub-heading is equally far from the paragraph it ends
   and the list it introduces — which reads as four unrelated blocks rather
   than as sections. A heading has to sit closer to what follows it than to
   what precedes it, and extra lead above is the only way to express that
   here. `:not(:first-child)` keeps it off a heading that opens the block,
   where the container's own spacing already applies. */
.prose :is(h2, h3):not(:first-child) { margin-top: var(--s10); }
.prose h2 { font-size: 26px; }
.prose h3 { font-size: 20px; }

/* `:not([class])` deliberately: the github-markdown-alerts plugin builds its
   note/tip/warning callouts out of blockquotes too, and it carries its own
   border-left, colour and title styling on a `.md-alert` class. A bare
   `blockquote` selector here is more specific than that plugin's and would
   silently repaint every alert on the site italic Playfair accent. This
   styles the plain Markdown quote and leaves the plugin's markup to the
   plugin. */
.prose blockquote:not([class]) {
  border-left: 1px solid var(--rule);
  padding-left: var(--s18);
  font-family: var(--serif);
  font-style: italic;
  color: var(--accent);
}

.prose hr { height: 1px; background: var(--rule); border: 0; }
.prose code { font-family: var(--mono); font-size: 0.9em; }
