/* ============================================================
   Boekhandel De Duif — frontend styles
   Designed to match the V2 mockups in /aangeleverd:
   - Univers (Adrian Frutiger) typography
   - Top navigation that behaves like file-folder tabs:
     the active tab connects seamlessly into the content card
   ============================================================ */

@font-face {
  font-family: 'Univers';
  src: url('../fonts/10. Univers     [1954 - Adrian Frutiger]/UniversLTStd.otf') format('opentype');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Univers';
  src: url('../fonts/10. Univers     [1954 - Adrian Frutiger]/UniversLTStd-Bold.otf') format('opentype');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

/* Cursief = Univers 55 Oblique. Gekoppeld aan font-style: italic zodat
   <em>/<i> en font-style: italic dit automatisch (instinctief) gebruiken,
   zonder faux-italic of speciale klassen. */
@font-face {
  font-family: 'Univers';
  src: url('../fonts/10. Univers     [1954 - Adrian Frutiger]/UniversLTStd-Obl.otf') format('opentype');
  font-weight: 400;
  font-style: italic;
  font-display: swap;
}

/* Bold + cursief = Univers 65 Bold Oblique (voor <strong><em> e.d.). */
@font-face {
  font-family: 'Univers';
  src: url('../fonts/10. Univers     [1954 - Adrian Frutiger]/UniversLTStd-BoldObl.otf') format('opentype');
  font-weight: 700;
  font-style: italic;
  font-display: swap;
}

@font-face {
  font-family: 'Univers';
  src: url('../fonts/10. Univers     [1954 - Adrian Frutiger]/UniversLTStd-Light.otf') format('opentype');
  font-weight: 300;
  font-style: normal;
  font-display: swap;
}

/* Licht + cursief = Univers 45 Light Oblique. */
@font-face {
  font-family: 'Univers';
  src: url('../fonts/10. Univers     [1954 - Adrian Frutiger]/UniversLTStd-LightObl.otf') format('opentype');
  font-weight: 300;
  font-style: italic;
  font-display: swap;
}

@font-face {
  font-family: 'UniversBlack';
  src: url('../fonts/10. Univers     [1954 - Adrian Frutiger]/UniversLTStd-Black.otf') format('opentype');
  font-weight: 900;
  font-style: normal;
  font-display: swap;
}

:root {
  --gap: 28px;             /* outer page padding */
  --page-max: 1400px;      /* max layout width; extra space splits left/right */
  /* Horizontal inset from the viewport edge. Equals --gap until the viewport
     grows past --page-max, after which the surplus is split evenly so the
     whole (fixed) layout stays centred with free space left and right. */
  --page-inset: max(var(--gap), calc((100vw - var(--page-max)) / 2));
  --sidebar-w: 300px;      /* left column width */
  --col-gap: 16px;         /* gap between sidebar and content */
  --content-gap: 56px;     /* wider gap so the photo shows left of the card */
  --content-bottom: 72px;  /* breathing margin below the content card */
  --tab-h: 54px;           /* nav row / active-tab height */
  --radius: 14px;          /* card / tab corner radius */
  --line: #111;            /* hairline / divider colour */
  --ink: #0d0d0d;          /* text colour */
}

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

html,
body {
  min-height: 100%;
  font-family: 'Univers', 'Helvetica Neue', Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* Warm dark base on the ROOT element only so every page's first paint is this
   tone, not white. Prevents the white flash between page loads while the
   stylesheet + background photo are still arriving. Matches the .bg-overlay
   fallback so there's no colour jump once it paints. The body stays
   transparent so the .bg-overlay carousel (z-index: -2) shows through. */
html {
  background-color: #2a2118;
}

body {
  min-height: 100vh;
  position: relative;
  color: var(--ink);
  padding: var(--gap);
}

img {
  max-width: 100%;
  display: block;
}

a {
  color: inherit;
}

/* Full-bleed shop photo behind everything — a cross-fading carousel.
   Two stacked layers fade between each other so images blend smoothly
   instead of cutting hard. */
.bg-overlay {
  position: fixed;
  inset: 0;
  z-index: -2;
  background: #2a2118; /* warm fallback while the first image loads */
}

.bg-overlay__layer {
  position: absolute;
  inset: 0;
  background-size: cover;
  background-position: center;
  opacity: 0;
  transition: opacity 1.4s ease-in-out;
  will-change: opacity;
}

.bg-overlay__layer.is-active {
  opacity: 1;
}

/* Respect users who prefer reduced motion: instant fades. */
@media (prefers-reduced-motion: reduce) {
  .bg-overlay__layer {
    transition: opacity 0.3s linear;
  }
}

/* ------------------------------------------------------------
   Top navigation
   The designer's mockup shows the menu as large, bold, black
   uppercase WORDS spread across the top of the photo — not
   buttons or boxes. On a content page the active word gets a
   white folder-tab behind it that fuses into the content card.
   ------------------------------------------------------------ */
.top-nav {
  position: fixed;
  top: var(--gap);
  left: calc(var(--page-inset) + var(--sidebar-w) + var(--content-gap));
  right: var(--page-inset);
  height: var(--tab-h);
  display: flex;
  justify-content: space-between;
  align-items: stretch;
  gap: 12px;
  z-index: 60;
}

.nav-tab {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* Uppercase glyphs have no descenders, so the visible letters sit above
     the line-box centre (the reserved descender space stays empty below).
     A small top padding nudges the ink to the true optical middle.
     The side padding uses a var so the desktop docked layout can shrink it
     (down to --nav-tab-padx) when the tabs would otherwise overflow the row. */
  --nav-tab-padx: 26px;
  padding: 3px var(--nav-tab-padx) 0;
  font-weight: 700;
  font-size: 20px;
  text-transform: uppercase;
  text-decoration: none;
  letter-spacing: 0.01em;
  white-space: nowrap;
  color: var(--ink);
}

/* The dynamic "Home" tab only exists for phone, where the logo (the home
   link) is hidden on content pages. On desktop the logo already goes home,
   so hide this tab there. The phone media query re-shows it. */
.nav-tab--home {
  display: none;
}

/* Wraps a run of text so it can be tilted independently of its container.
   main.js sets --tab-tilt to a random angle (-2..2deg); the box stays put
   (e.g. the nav pill stays square) while only the words rotate. Defaults
   to flat so everything looks right before the script runs. */
.tilt-text {
  display: inline-block;
  transform: rotate(var(--tab-tilt, 0deg));
  transform-origin: center;   /* pivot around the middle so even short, */
}                             /* narrow runs (e.g. hours cells) visibly sway */

/* Playful mode: each span gently sways within the -2..2deg range. main.js
   gives every span its own --tilt-dur and --tilt-delay (negative, so they
   start mid-cycle) so they don't move in lockstep. Toggled by clicking the
   background image, which adds/removes .tilt-animated on <body>. When the
   class is absent, spans rest at their fixed --tab-tilt above. */
@keyframes tilt-wobble {
  from { transform: rotate(calc(-1 * var(--tilt-amp, 2deg))); }
  to   { transform: rotate(var(--tilt-amp, 2deg)); }
}

/* The hours table is small text, so a 2deg sway barely shows. Give those
   cells a wider swing so they wobble as noticeably as the headings. */
.hours-table .tilt-text {
  --tilt-amp: 4deg;
}

body.tilt-animated .tilt-text {
  animation: tilt-wobble var(--tilt-dur, 4s) ease-in-out var(--tilt-delay, 0s) infinite alternate;
}

/* Same wobble for whole elements that have no text to wrap (e.g. the logo
   image): the element itself sways as a unit. Unlike .tilt-text it leaves
   display alone, so the element keeps its own layout (the logo stays a
   centred block). */
.tilt-box {
  transform: rotate(var(--tab-tilt, 0deg));
}

body.tilt-animated .tilt-box {
  animation: tilt-wobble var(--tilt-dur, 4s) ease-in-out var(--tilt-delay, 0s) infinite alternate;
}

/* Respect users who opt out of motion — UNLESS they explicitly turned the
   wobble on via ?animatie=1 (which sets .tilt-forced on <body>). The opt-in
   is a deliberate choice, so it overrides the OS "reduce motion" setting. */
@media (prefers-reduced-motion: reduce) {
  body.tilt-animated:not(.tilt-forced) .tilt-text,
  body.tilt-animated:not(.tilt-forced) .tilt-box {
    animation: none;
  }
}

.nav-tab:not(.active):hover {
  opacity: 0.62;
}

/* Content page: the non-active tabs are plain words over the photo. On
   hover they preview the active state ("fake-active") — same white folder-tab
   shape as .active, but slightly transparent so the photo shows through and
   it reads as a hint, not the real selection.

   DEFAULT (safe everywhere): a self-contained rounded pill, mirroring the
   .active default. The docked folder-tab shape is layered on at ≥1025px. */
body.has-content .nav-tab:not(.active):hover {
  opacity: 1;
  background: rgba(255, 255, 255, 0.72);
  border-radius: var(--radius);
}

/* Homepage: every menu item is a white rounded pill floating on
   the shop photo, evenly spread across the top (matches the
   homepage mockup). The row sits at top:--gap so the pills' top
   edge lines up with the top of the sidebar card — all the white
   surfaces start on the same line. */
body:not(.has-content) .top-nav {
  top: var(--gap);
}

body:not(.has-content) .nav-tab {
  height: var(--tab-h);
  background: #fff;
  border-radius: var(--radius);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18);
}

body:not(.has-content) .nav-tab:hover {
  opacity: 1;
  background: #f6f6f6;
}

/* Active word on a content page.

   DEFAULT (safe everywhere): a self-contained white rounded pill. This is
   the fallback used at smaller/zoomed sizes where the docked folder-tab
   would get cramped — pills never need to align with the card, so the
   layout can't break.

   The polished docked folder-tab (with the concave fillet that merges
   into the content card) is layered on top ONLY at full desktop width
   (min-width: 1025px), where the nav and card are guaranteed to align. */
body.has-content .nav-tab.active {
  background: #fff;
  border-radius: var(--radius);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18);
  z-index: 41;           /* above the content card (z-index: 40) */
  cursor: default;
}

@media (min-width: 1025px) {
  /* Desktop docked layout: the tab row must always fit flush inside the
     card width. The titles are nowrap, so when there are many/long page
     names their combined width can exceed the row and the last tabs spill
     past the card's right edge — that overflow is what left a gap (rounded
     mode) or a misaligned shadow sliver (V3) at the seam.

     Fix: let every tab shrink as a flex item and compress its side padding
     as the row gets crowded, so the whole strip stays flush within the card
     (justify-content: space-between still spreads them when there is slack).
     text-overflow keeps a single very long title from ever forcing an
     overflow as a last resort. */
  body .nav-tab {
    flex: 0 1 auto;
    min-width: 0;
    /* Shrink the side padding when crowded but never below 12px, so tabs
       stay comfortably clickable and keep the folder-tab proportions. */
    --nav-tab-padx: clamp(12px, 2.2vw, 26px);
    overflow: hidden;
    text-overflow: ellipsis;
  }

  /* The active / hovered tab draws its concave fillets with ::before/::after
     positioned just outside the tab box; those must NOT be clipped, so this
     tab keeps overflow visible. (Shrinking still applies via flex above.) */
  body.has-content .nav-tab.active,
  body.has-content .nav-tab:not(.active):hover {
    overflow: visible;
  }

  /* Folder-tab: rounded top corners, flush bottom that docks onto the
     card. No shadow (the card carries it) so the join reads as one shape. */
  body.has-content .nav-tab.active {
    border-radius: var(--radius) var(--radius) 0 0;
    box-shadow: none;
    /* Drop the flush bottom edge 1px into the card top. The tab and card
       abut at the exact same y-coordinate, and on fractional-pixel display
       scaling that seam can render as a hairline gap that lets the photo
       show through (visible at the right edge especially). Overlapping by
       1px closes it so tab + card always read as one white surface. */
    margin-bottom: -1px;
  }

  /* The two concave corners that join the tab to the card surface.
     Each is a square sitting on the card top, with a radial-gradient
     that carves a transparent quarter-circle — leaving a concave white
     curve. ::before = left corner, ::after = right corner. */
  body.has-content .nav-tab.active::before,
  body.has-content .nav-tab.active::after {
    content: '';
    position: absolute;
    bottom: 0;             /* box bottom sits exactly on the card top */
    width: var(--radius);
    height: var(--radius);
    z-index: 1;
  }

  /* Left fillet: TOP-LEFT quarter carved transparent → concave curve. */
  body.has-content .nav-tab.active::before {
    left: calc(-1 * var(--radius));
    background: radial-gradient(circle at top left, transparent var(--radius), #fff calc(var(--radius) + 0.5px));
  }

  /* Right fillet: mirror image, TOP-RIGHT quarter carved transparent. */
  body.has-content .nav-tab.active::after {
    right: calc(-1 * var(--radius));
    background: radial-gradient(circle at top right, transparent var(--radius), #fff calc(var(--radius) + 0.5px));
  }

  /* The first tab hugs the card's left edge, so its left side continues
     straight into the card — no fillet there. Likewise the last tab hugs
     the right edge. Suppress the outer fillet in those cases. */
  body.has-content .nav-tab.active:first-child::before {
    display: none;
  }

  body.has-content .nav-tab.active:last-child::after {
    display: none;
  }

  /* ── "Fake-active" hover: same docked folder-tab shape as .active, but the
     white is semi-transparent so it previews the selection rather than
     mimicking it. Rounded top corners, flush bottom that docks onto the
     card, plus the two concave fillets that bridge into the card. ── */
  body.has-content .nav-tab:not(.active):hover {
    background: rgba(255, 255, 255, 0.72);
    border-radius: var(--radius) var(--radius) 0 0;
    z-index: 41;           /* above the content card, like .active */
    margin-bottom: -1px;   /* close the tab/card seam, same as .active */
  }

  body.has-content .nav-tab:not(.active):hover::before,
  body.has-content .nav-tab:not(.active):hover::after {
    content: '';
    position: absolute;
    bottom: 0;             /* box bottom sits exactly on the card top */
    width: var(--radius);
    height: var(--radius);
    z-index: 1;
  }

  /* Left fillet: TOP-LEFT quarter carved transparent → concave curve.
     The opaque side matches the tab's translucent white so they read as
     one shape. */
  body.has-content .nav-tab:not(.active):hover::before {
    left: calc(-1 * var(--radius));
    background: radial-gradient(circle at top left, transparent var(--radius), rgba(255, 255, 255, 0.72) calc(var(--radius) + 0.5px));
  }

  /* Right fillet: mirror image. */
  body.has-content .nav-tab:not(.active):hover::after {
    right: calc(-1 * var(--radius));
    background: radial-gradient(circle at top right, transparent var(--radius), rgba(255, 255, 255, 0.72) calc(var(--radius) + 0.5px));
  }

  /* First/last tabs hug the card edge. The real active tab squares the
     card's matching top corner (via the .active-tab-first/last body class)
     so its flush edge docks cleanly. We can't square the card on hover, so
     instead the fillet becomes a SOLID translucent-white square that drops
     just below the tab to fill the notch left by the card's rounded corner,
     making the tab's straight edge continue smoothly into the card. */
  body.has-content .nav-tab:not(.active):hover:first-child::before,
  body.has-content .nav-tab:not(.active):hover:last-child::after {
    bottom: calc(-1 * var(--radius));   /* drop into the card's corner region */
    background: rgba(255, 255, 255, 0.72);
  }

  body.has-content .nav-tab:not(.active):hover:first-child::before {
    left: 0;               /* flush with the tab/card left edge */
  }

  body.has-content .nav-tab:not(.active):hover:last-child::after {
    right: 0;              /* flush with the tab/card right edge */
  }
}

/* ------------------------------------------------------------
   Shared card surface
   ------------------------------------------------------------ */
.sidebar-card,
.content-card {
  background: #fff;
  border-radius: var(--radius);
  /* Soft shadow only (no border) so nothing draws a hard seam where the
     active folder-tab merges into the card. */
  box-shadow: 0 12px 30px rgba(0, 0, 0, 0.14);
}

/* All four corners rounded. The active folder-tab sits over the top edge
   and its concave fillets bridge the join, so the docking still reads as
   one smooth shape while the exposed top-left / top-right corners stay
   nicely rounded like the rest of the page. Shadow biased downward so it
   never bleeds up into the tab/card seam. */
.content-card {
  border-radius: var(--radius);
  box-shadow: 0 16px 30px rgba(0, 0, 0, 0.12);
}

/* When the active folder-tab hugs a card edge (first tab = left edge, last
   tab = right edge), square that top corner so the tab's flush vertical
   edge docks without leaving a small notch. Only relevant in the docked
   desktop layout; below 1025px tabs are pills and the card stays fully
   rounded. */
@media (min-width: 1025px) {
  body.active-tab-first .content-card {
    border-top-left-radius: 0;
  }

  body.active-tab-last .content-card {
    border-top-right-radius: 0;
  }
}

/* ------------------------------------------------------------
   Left column (logo + hours + contact)
   ------------------------------------------------------------ */
.sidebar-card {
  position: fixed;
  left: var(--page-inset);
  top: var(--gap);
  bottom: var(--gap);
  width: var(--sidebar-w);
  padding: 26px 24px 28px;
  display: flex;
  flex-direction: column;
  z-index: 50;
  overflow-y: auto;
}

.logo-link {
  text-decoration: none;
  align-self: stretch;   /* full width of the sidebar so the logo can centre */
}

/* Placeholder logo image (tijdelijk tot definitief logo is goedgekeurd). */
.logo-img {
  display: block;
  width: 100%;
  max-width: 220px;
  height: auto;
  margin: 10px auto 6px;   /* auto sides → horizontally centred */
}

/* Freestanding logo (no border box) — matches the mockup */
.logo {
  display: inline-block;
  padding: 0;
  /* Give the rotated logo room so it never clips the card edges */
  margin: 10px 0 6px 6px;
}

/* The whole wordmark is tilted up to the right, exactly like the
   designer's mockup (preview_desktop_0). */
.logo-inner {
  position: relative;
  line-height: 1;
  transform: rotate(-8deg);
  transform-origin: left center;
}

.logo-boek,
.logo-handel {
  display: block;
  font-size: 11px;
  letter-spacing: 0.36em;
  font-weight: 700;
  text-transform: uppercase;
}

.logo-boek {
  text-align: left;
  padding-left: 2px;
}

.logo-handel {
  text-align: right;
  margin-top: 1px;
  padding-right: 2px;
}

.logo-de-duif {
  display: flex;
  align-items: baseline;
  gap: 7px;
  margin-top: 2px;
}

.logo-de,
.logo-duif {
  font-family: 'UniversBlack', 'Univers', sans-serif;
  font-weight: 900;
  font-size: 56px;
  line-height: 0.86;
  letter-spacing: -0.04em;
  text-transform: uppercase;
}

/* Hours sit around the vertical middle of the card and the
   contact block at the bottom (mockup). Both gaps use flexible
   auto-margins so they collapse on short screens instead of
   pushing the address out of view. */
.sidebar-hours {
  margin-top: auto;
  padding-top: 0;
  text-align: center;
}

.hours-title {
  font-size: 20px;
  font-weight: 700;
  letter-spacing: 0.02em;
  margin-bottom: 18px;
  text-align: center;
}

/* The table shrinks to its content and is centred as a block, so the
   day/time pairs sit as a centred group like the logo and address above. */
.hours-table {
  margin: 0 auto;
  border-collapse: collapse;
}

.hours-table td {
  padding: 4px 0;
  font-size: 18px;
  font-weight: 700;
  text-align: left;
}

.hours-table td:first-child {
  width: 72px;
}

.sidebar-contact {
  margin-top: auto;
  text-align: center;
  font-size: 18px;
  font-weight: 700;
  line-height: 1.7;
}

.sidebar-contact a {
  text-decoration: none;
}

/* ------------------------------------------------------------
   Content card (connects to the active tab above)
   ------------------------------------------------------------ */
.content-card {
  position: fixed;
  /* Extra breathing room so the shop photo shows around the card:
     a wider gap on the left and a taller margin at the bottom. */
  left: calc(var(--page-inset) + var(--sidebar-w) + var(--content-gap));
  top: calc(var(--gap) + var(--tab-h));
  right: var(--page-inset);
  /* Cap the height so the card hugs its content and reveals the
     photo below; never grow past the bottom breathing margin. */
  max-height: calc(100vh - var(--gap) - var(--tab-h) - var(--content-bottom));
  padding: 40px 48px 44px;
  overflow-y: auto;
  z-index: 40;
  /* Slim, rounded scrollbar instead of the chunky OS one with square
     arrow buttons — matches the rounded look of the rest of the page.
     (Shared rule for .content-card and .sidebar-card is defined below.) */
  scrollbar-width: thin;                       /* Firefox */
  scrollbar-color: rgba(0, 0, 0, 0.28) transparent;
}

/* ------------------------------------------------------------
   Admin "edit this page" button (only rendered when an admin is
   logged in). Sits in the top-right of the content card, over the
   page header, and always links to the admin form for whatever is
   on screen (current page, or the specific event on a detail view).
   ------------------------------------------------------------ */
.edit-button {
  position: absolute;
  /* Hug the true top-right corner of the card. The card has 40px/48px
     padding, so pulling up/right into that padding keeps the button clear
     of the header text instead of sitting on top of it. */
  top: 12px;
  right: 12px;
  z-index: 5;              /* above the header text, within the card */
  display: inline-flex;
  align-items: center;
  gap: 7px;
  height: 36px;
  padding: 0 16px;
  font-size: 13px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  text-decoration: none;
  color: #fff;
  background: #1c1c1c;
  border-radius: 999px;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.22);
  transition: background 0.15s ease, transform 0.15s ease;
}

.edit-button:hover {
  background: #000;
  transform: translateY(-1px);
}

.edit-button__icon {
  font-size: 14px;
  line-height: 1;
}

/* ── Rounded, arrow-free scrollbars for the scrollable cards ──────── */
.content-card,
.sidebar-card {
  scrollbar-width: thin;                       /* Firefox */
  scrollbar-color: rgba(0, 0, 0, 0.28) transparent;
}

/* WebKit/Chromium: rounded thumb, no square arrow buttons, transparent track. */
.content-card::-webkit-scrollbar,
.sidebar-card::-webkit-scrollbar {
  width: 10px;
}

.content-card::-webkit-scrollbar-track,
.sidebar-card::-webkit-scrollbar-track {
  background: transparent;
  margin: 8px 0;            /* keep the thumb clear of the rounded card corners */
}

.content-card::-webkit-scrollbar-thumb,
.sidebar-card::-webkit-scrollbar-thumb {
  background: rgba(0, 0, 0, 0.24);
  border-radius: 999px;     /* fully rounded thumb */
  border: 2px solid transparent;   /* insets the thumb from the card edge */
  background-clip: padding-box;
}

.content-card::-webkit-scrollbar-thumb:hover,
.sidebar-card::-webkit-scrollbar-thumb:hover {
  background: rgba(0, 0, 0, 0.4);
  background-clip: padding-box;
}

/* Remove the up/down arrow buttons at the ends of the scrollbar.
   Some Chromium builds keep a residual button unless every variant
   (start/end, vertical/horizontal, single/double) is zeroed explicitly. */
.content-card::-webkit-scrollbar-button,
.content-card::-webkit-scrollbar-button:start,
.content-card::-webkit-scrollbar-button:end,
.content-card::-webkit-scrollbar-button:vertical:start,
.content-card::-webkit-scrollbar-button:vertical:end,
.content-card::-webkit-scrollbar-button:vertical:decrement,
.content-card::-webkit-scrollbar-button:vertical:increment,
.content-card::-webkit-scrollbar-button:horizontal:start,
.content-card::-webkit-scrollbar-button:horizontal:end,
.sidebar-card::-webkit-scrollbar-button {
  display: none;
  height: 0;
  width: 0;
}

.content-card::-webkit-scrollbar-corner,
.sidebar-card::-webkit-scrollbar-corner {
  background: transparent;
}

.content-header {
  margin-bottom: 26px;
  /* Reserve space for the absolutely-positioned .edit-button (top-right)
     so the header text doesn't run underneath it. */
  padding-right: 150px;
}

.content-kicker {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.16em;
  margin-bottom: 6px;
  text-transform: uppercase;
}

.content-header h1 {
  font-family: 'UniversBlack', 'Univers', sans-serif;
  font-weight: 900;
  font-size: clamp(30px, 3.4vw, 46px);
  line-height: 0.95;
  letter-spacing: -0.04em;
  text-transform: uppercase;
}

.page-content {
  font-size: 16px;
  line-height: 1.7;
  max-width: none;
}

.page-content p + p,
.page-content ul + p,
.page-content p + ul {
  margin-top: 1em;
}

.page-content a {
  text-decoration: underline;
}

/* ------------------------------------------------------------
   Boekenblok (3 boeken naast elkaar) — ingevoegd via de
   "3 Boeken"-knop in de editor (admin/js/book-block.js).
   ------------------------------------------------------------ */
.book-row {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 28px;
  margin: 1.8em 0;
}

.book-row .book-col {
  display: flex;
  flex-direction: column;
}

.book-row .book-cover {
  /* Alle covers in een vast 2:3-portretkader met object-fit: cover, zodat
     ze — ongeacht de afmetingen van de aangeleverde afbeelding — even hoog
     zijn en netjes op één lijn staan. */
  width: 100%;
  aspect-ratio: 2 / 3;
  object-fit: cover;
  object-position: center;
  display: block;
  margin-bottom: 0.7em;
  background: #f0f0f0;
}

.book-row .book-info {
  /* Behoud de regelafbrekingen uit het tekstveld. */
  white-space: pre-line;
  font-size: 15px;
  line-height: 1.5;
}

@media (max-width: 720px) {
  .book-row {
    grid-template-columns: 1fr;
    gap: 32px;
  }
}

/* ------------------------------------------------------------
   Agenda list
   ------------------------------------------------------------ */
.agenda-list {
  display: flex;
  flex-direction: column;
}

/* Breathing room between the agenda page's intro text and the event list.
   Scoped to the adjacency so the event-detail page (no preceding text) and
   an agenda page with no intro content keep their original spacing. */
.page-content + .agenda-list {
  margin-top: 32px;
}

.agenda-item {
  display: grid;
  /* The date column auto-fits its content (max-content) so a longer date like
     "zaterdag 13 september" stays on one line instead of wrapping mid-phrase,
     with a 175px floor so short dates don't make the column collapse and a cap
     so an unusually long date can't starve the body column. */
  grid-template-columns: minmax(175px, max-content) minmax(0, 1fr) 110px;
  gap: 40px;
  padding: 28px 0;
  border-bottom: 1px solid var(--line);
  align-items: start;
  text-decoration: none;
  color: inherit;
  transition: opacity 0.12s;
}

.agenda-item:hover {
  opacity: 0.72;
}

.agenda-item:first-child {
  padding-top: 6px;
}

.agenda-date,
.agenda-time {
  display: block;
  font-size: 16px;
  font-weight: 700;
  letter-spacing: 0.01em;
}

/* Date on one line, time on one line — never wrap mid-phrase. The date column
   (max-content, above) grows to fit the widest of them. Only on the desktop
   two-column layout: on phone the meta column is a fixed narrow 80px stacked
   above the title, so there the date is allowed to wrap as before. */
@media (min-width: 769px) {
  .agenda-date,
  .agenda-time {
    white-space: nowrap;
  }
}

.agenda-time {
  font-weight: 600;
}

.agenda-title {
  font-size: 17px;
  font-weight: 700;
  margin-bottom: 12px;
}

.agenda-body {
  font-size: 16px;
  line-height: 1.55;
  white-space: normal;
  margin: 0;
}

.agenda-body p + p {
  margin-top: 1.1em;
}

.agenda-badge {
  display: inline-block;
  margin-top: 12px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  padding: 4px 10px;
  border: 1px solid var(--line);
  border-radius: 999px;
}

/* Small thumbnail in the agenda list. The box stays 110x90 whatever the fit
   mode, so the list keeps its alignment; only what happens INSIDE the box
   changes (see the shared fit rules further down). */
.agenda-item-thumb img {
  width: 110px;
  height: 90px;
  object-fit: cover;
  border-radius: 0;
  display: block;
}

/* ── Image fit modes (per event, set in the admin) ──────────────
   'cover' is the default and needs no rules: it is what the plain
   .agenda-item-thumb / .event-detail-image declarations above already do.
   The two others stop portrait images from being cropped top and bottom. */

/* Show the whole image, letterboxed inside the same box. In the agenda list
   'full' behaves like 'contain': the thumb column is a fixed 110x90 slot, so
   full-width only has meaning on the event page itself. */
.agenda-item-thumb.fit-contain img,
.agenda-item-thumb.fit-blur img,
.agenda-item-thumb.fit-full img,
.event-detail-image.fit-contain img,
.event-detail-image.fit-blur img {
  object-fit: contain;
}

/* Blur mode: the box is filled with a blurred, scaled copy of the same image
   (handed in as --fit-bg on the wrapper) so a portrait keeps the full-width
   banner shape instead of leaving bare card next to it. */
.agenda-item-thumb.fit-blur,
.event-detail-image.fit-blur {
  position: relative;
  overflow: hidden;
  isolation: isolate;
}

.agenda-item-thumb.fit-blur::before,
.event-detail-image.fit-blur::before {
  content: "";
  position: absolute;
  /* Bleed past the edges: blurring samples transparent pixels beyond the box,
     which would otherwise show as pale fringes along the sides. */
  inset: -8%;
  background-image: var(--fit-bg);
  background-size: cover;
  background-position: center;
  filter: blur(18px) saturate(1.1);
  transform: scale(1.08);
  z-index: -1;
}

/* The detail banner's blurred fill has to sit inside the card's rounded
   corners, and the image itself must paint above it. */
.event-detail-image.fit-blur {
  border-radius: var(--radius);
  margin-bottom: 24px;
}

.event-detail-image.fit-blur img {
  position: relative;
  margin-bottom: 0;
}

/* Front-end button (used by the event registration form) */
.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 12px 22px;
  border: 1px solid var(--ink);
  border-radius: 999px;
  font: inherit;
  font-weight: 700;
  font-size: 15px;
  cursor: pointer;
  text-decoration: none;
  background: #fff;
  color: var(--ink);
  transition: background 0.12s, color 0.12s;
}

.button:hover {
  background: var(--ink);
  color: #fff;
}

.button-primary {
  background: var(--ink);
  color: #fff;
}

.button-primary:hover {
  background: #fff;
  color: var(--ink);
}

/* ── Event detail page ─────────────────────────────────────── */
.event-detail {
  display: block;
}

.event-back {
  display: inline-block;
  margin-bottom: 22px;
  font-size: 14px;
  font-weight: 700;
  text-decoration: none;
  color: inherit;
}

.event-back:hover {
  text-decoration: underline;
}

.event-detail-image img {
  width: 100%;
  max-height: 420px;
  object-fit: cover;
  /* Follow the global corner setting so ?rechthoekig (--radius: 0) squares
     the image too, matching the cards. */
  border-radius: var(--radius);
  margin-bottom: 24px;
}

/* 'contain' and 'blur' need a fixed height rather than a max-height: an
   auto-height image grows to its own aspect ratio first, so a tall portrait
   would still overflow the intended banner band before object-fit applies. */
.event-detail-image.fit-contain img,
.event-detail-image.fit-blur img {
  height: 420px;
  max-height: none;
}

/* 'full': no banner band at all. The image spans the full content width and
   keeps its own aspect ratio, so nothing is cropped and nothing is letterboxed
   — a tall portrait simply becomes a tall image. */
.event-detail-image.fit-full img {
  width: 100%;
  height: auto;
  max-height: none;
  object-fit: contain;
}

.event-detail-date {
  font-size: 15px;
  font-weight: 700;
  letter-spacing: 0.01em;
  margin: 0 0 6px;
}

.event-detail-title {
  font-size: 26px;
  font-weight: 700;
  margin: 0 0 20px;
}

.event-detail-body {
  font-size: 16px;
  line-height: 1.6;
}

.event-detail-body p + p {
  margin-top: 1.1em;
}

.event-detail-body img {
  max-width: 100%;
  height: auto;
}

/* "Vul breedte": images flagged in the WYSIWYG editor stretch to fill the
   full width of their content column instead of staying at their natural
   size. Mirrored in the TinyMCE content_style (admin/_footer.php) so the
   editor preview matches the live page. */
.page-content img.img-fill,
.event-detail-body img.img-fill {
  display: block;
  width: 100%;
  height: auto;
}

/* Registration / ticket form */
.event-register {
  margin-top: 36px;
  padding-top: 28px;
  border-top: 1px solid var(--line);
}

.event-register h2 {
  font-size: 19px;
  font-weight: 700;
  margin: 0 0 8px;
}

.event-register-price {
  font-size: 15px;
  margin: 0 0 18px;
}

.event-register-form {
  display: grid;
  gap: 6px;
  max-width: 360px;
}

.event-register-form label {
  font-size: 13px;
  font-weight: 700;
  margin-top: 10px;
}

.event-register-form input {
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: 8px;
  font: inherit;
}

.event-register-form .button {
  margin-top: 16px;
}

.event-full {
  font-weight: 700;
  color: #b00;
}

.event-notice {
  padding: 12px 16px;
  border-radius: 10px;
  margin-bottom: 20px;
  font-size: 15px;
}

.event-notice-success { background: #e6f6ec; color: #1c6b38; }
.event-notice-warn { background: #fff4e0; color: #8a5a00; }
.event-notice-error { background: #fbe6e6; color: #9c1c1c; }

.empty-state {
  font-size: 15px;
  line-height: 1.6;
}

.hero-spacer {
  display: none;
}

/* ============================================================
   Responsive — tablet & below (pill tabs)
   Uses 1024.98px (not 1024px) so there is NO dead zone between this
   and the desktop "min-width: 1025px" docked-tab rules: fractional CSS
   widths from browser zoom / HiDPI (e.g. 1024.5px) always land here,
   never in a gap where the tab and card styles would mismatch.
   ============================================================ */
@media (max-width: 1024.98px) {
  .top-nav {
    left: var(--gap);
  }

  /* Below the docked-folder-tab breakpoint, ALL nav tabs are white rounded
     pills floating over the photo (same treatment as the homepage), so they
     stay legible and consistent and never need to align with the card. */
  .top-nav {
    align-items: center;
  }

  body.has-content .nav-tab {
    height: var(--tab-h);
    background: #fff;
    border-radius: var(--radius);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18);
  }

  body.has-content .nav-tab:not(.active):hover {
    opacity: 1;
    background: #f6f6f6;
  }

  .content-card {
    left: var(--gap);
    top: calc(var(--gap) + var(--tab-h) + 8px);
  }

  .sidebar-card {
    position: static;
    width: 100%;
    max-width: 360px;
    min-height: calc(100vh - 2 * var(--gap));
  }

  /* Content pages: the info card docks at the bottom below the content card,
     so it must line up with it — same left (--gap) / right (--page-inset)
     insets (centred in the page), and it wraps its own contents instead of
     stretching to fill the viewport. The homepage card above keeps its
     narrow 360px treatment. */
  body.has-content .sidebar-card {
    width: auto;
    max-width: none;
    margin: 0 var(--page-inset) 0 var(--gap);
    min-height: auto;
    /* Centre the logo/hours/address within the now-wide card instead of
       cramming them against the left edge. */
    align-items: center;
    text-align: center;
  }

  body.has-content .sidebar-card .sidebar-hours {
    display: flex;
    justify-content: center;
  }
}

/* ============================================================
   Responsive — phone (matches phone mockups)
   ============================================================ */
@media (max-width: 768px) {
  body {
    display: flex;
    flex-direction: column;
    gap: 12px;
    /* The tab strip is position:fixed at top:0, so reserve its height here
       (12px top pad + 34px pill, no bottom pad = 46px) so no card or photo
       ever slides underneath it — on both the homepage and content pages. */
    padding: 46px 0 12px;
    min-height: 100vh;   /* fill the screen so the info card docks at the bottom */
  }

  /* The homepage rule `body:not(.has-content) .top-nav { top: var(--gap) }`
     lives outside any media query (it aligns the desktop pills with the card),
     so it also applied on phone — pushing the fixed strip 28px down and leaving
     empty space above the tabs. On phone the strip belongs at the very top, so
     override it back to 0 with matching specificity. */
  body:not(.has-content) .top-nav {
    top: 0;
    /* The strip has overflow-x:auto for horizontal scrolling, which also clips
       on the vertical axis — and with zero bottom padding the pills' bottom
       edge is flush with the strip edge, so their solid V3 drop shadow gets
       cut off. Add a little bottom room (and matching top room, keeping the
       pills vertically centred) so the bottom shadow is visible. Homepage only:
       on content pages the active tab must stay flush at the strip's bottom to
       merge into the card, so that layout is left untouched. */
    padding-bottom: 8px;
  }

  /* Reserve the extra 8px of strip height on the homepage so nothing slides
     under it (base reservation is 46px; +8px bottom padding = 54px). */
  body:not(.has-content) {
    padding-top: 54px;
  }

  /* Phone: tabs are a full-width strip of rounded tabs at the
     very top, scrollable, sitting over the photo. */
  .top-nav {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    height: auto;
    justify-content: flex-start;
    align-items: stretch;
    /* No bottom padding: the pills' bottom edge IS the strip's bottom edge
       (12 + 34 = 46px). The content card starts exactly there (body padding)
       so the active tab can merge into it with no black band between. */
    padding: 12px 12px 0;
    overflow-x: auto;
    gap: 8px;
    scrollbar-width: none;
    z-index: 100;
    /* Fade the strip toward both ends so the pill nearest a scrollable edge
       softly fades out — a cue that more tabs exist off-screen when they
       don't all fit. Works over the transparent strip (no visible bar).
       main.js toggles --nav-fade-left/right (0 or 1) as the user scrolls so
       the fade only shows on the side that actually has hidden tabs; both
       default to 1 so the hint is present before the script runs. */
    --nav-fade-left: 1;
    --nav-fade-right: 1;
    -webkit-mask-image: linear-gradient(
      to right,
      transparent 0,
      #000 calc(20px * var(--nav-fade-left)),
      #000 calc(100% - 20px * var(--nav-fade-right)),
      transparent 100%
    );
    mask-image: linear-gradient(
      to right,
      transparent 0,
      #000 calc(20px * var(--nav-fade-left)),
      #000 calc(100% - 20px * var(--nav-fade-right)),
      transparent 100%
    );
  }

  .top-nav::-webkit-scrollbar {
    display: none;
  }

  /* Phone: EVERY tab is the same solid white rounded pill, 34px tall (matches
     the phone mockup), the row scrolls horizontally over the photo. Both
     selectors below are (0,2,1) specificity so they tie — and, being later in
     source order, beat — the tablet rule `body.has-content .nav-tab { height:
     var(--tab-h) } (=54px)`. Without this the non-active content-page tabs
     stay 54px and overhang the card; equal 34px height also keeps the body's
     reserved top padding matching the real strip height. */
  body.has-content .nav-tab,
  body:not(.has-content) .nav-tab {
    height: 34px;
    padding: 0 16px;
    font-size: 12px;
    background: #fff;
    border: none;
    border-radius: var(--radius);
    margin-bottom: 0;
    box-shadow: 0 6px 18px rgba(0, 0, 0, 0.18);
  }

  /* Content page: the non-active tabs drop their pill entirely and become just
     bold black words over the photo, exactly like desktop — no background, no
     pill shadow, no rounded box. Only the active tab keeps the solid-white pill
     that merges into the card, so it clearly stands out. (On the homepage no
     page is selected — body:not(.has-content) above — so every tab keeps its
     solid-white pill.) */
  body.has-content .nav-tab:not(.active) {
    background: transparent;
    box-shadow: none;
    border-radius: 0;
  }

  /* Phone only: re-show the dynamic Home tab (hidden on desktop, where the
     logo is the home link). */
  .nav-tab--home {
    display: inline-flex;
  }

  /* Content pages: drop the big hero photo so the content card rises right
     under the fixed tab strip, and the active tab visually connects to it
     (see the merge rule below). */
  body.has-content .hero-spacer {
    display: none;
  }

  /* The active tab "merges" into the card: rounded TOP corners only, flat
     bottom that sits flush on the strip's bottom edge — which is exactly the
     card top (the strip has no bottom padding and the card starts at the
     body's reserved 46px). The card is then pulled up 1px (see below) so the
     two white surfaces overlap with no black seam. No bottom shadow, since a
     shadow there would draw a line between tab and card. (The desktop concave
     fillets can't work in a horizontal scroll strip, so we skip them.) */
  body.has-content .nav-tab.active {
    border-radius: var(--radius) var(--radius) 0 0;
    box-shadow: 0 -3px 10px rgba(0, 0, 0, 0.10);
    z-index: 101;          /* above the card, which sits just below the strip */
  }

  /* Photo grows to fill whatever space is left after the pills and the
     info card, so on entering the page you see: pills on top, the big
     shop photo, and the info card docked at the bottom of the first
     screen — matching the phone mockup, at any device height. */
  .hero-spacer {
    display: block;
    flex: 1 1 auto;
    /* The photo grows to fill leftover space (flex auto) but this floor stops
       it collapsing. Keep the floor modest so on shorter phones the photo
       yields height and the info card + "order a book" sticker stay above the
       fold; on taller phones the photo simply grows to fill the gap. */
    min-height: 150px;
  }

  .content-card,
  .sidebar-card {
    position: static;
    width: calc(100% - 24px);
    margin: 0 12px;
    border-radius: var(--radius);
  }

  /* On content pages the ≤1024.98px rule gives the docked info card the wider
     desktop insets (--page-inset right / --gap left, both ≥28px), which beats
     the plain .sidebar-card rule above on specificity and left the address card
     narrower than the content card. Re-assert the phone width/margins here at
     equal specificity so the two cards line up edge-to-edge. */
  body.has-content .sidebar-card {
    width: calc(100% - 24px);
    margin: 0 12px;
  }

  .content-card {
    order: 2;
    top: auto;
    padding: 24px;
    overflow: visible;
    /* On a content page the hero photo is gone (see .hero-spacer above) and
       the fixed tab strip (12px pad + 34px tab + 12px pad ≈ 58px) sits over
       the top, so push the card down to meet the strip's bottom edge. The
       active tab's -8px bottom margin then laps onto this card top. */
    /* The card now flows in the page (position: static) and grows with its
       content. The desktop max-height/scroll caps the WHITE BACKGROUND height,
       so with overflow visible the text spills out below the card and over the
       photo. Drop the cap on phone so the card always wraps its full content. */
    max-height: none;
  }

  /* Content page: the hero photo is hidden, so the content card is the first
     flow child and the body's 46px top padding drops it right at the strip's
     bottom edge. Pull it up 1px so the card's white top overlaps the active
     tab's flat white bottom — the tab (z-index 101) sits over this overlap,
     so the two read as one continuous white surface with no black seam. */
  body.has-content .content-card {
    margin-top: -1px;
  }

  /* Phone: the edit button is absolutely positioned into the card's top-right
     corner on desktop, but there that corner sits under the fixed tab strip
     and the merged active tab — so the button hid behind the tabs. Let it flow
     as a normal block at the very top of the card content instead, right-
     aligned and with space below so it clears the page header cleanly. */
  .edit-button {
    position: static;
    display: flex;
    width: fit-content;
    margin: 0 0 16px auto;   /* auto-left keeps it pinned to the right */
  }

  /* Long words / unbroken strings (e.g. a pasted URL or e-mail address) must
     wrap inside the narrow phone card instead of pushing the text past the edge. */
  .content-card,
  .page-content,
  .event-detail-body {
    overflow-wrap: anywhere;
    word-break: break-word;
  }

  /* Phone info card: logo (top-left) + OPENINGSTIJDEN (top-right) side by
     side, with the address centred underneath the logo — matches the
     phone mockup. A 2-column grid keeps logo+address stacked on the left
     and the hours block on the right. The card docks at the bottom of
     EVERY page on phone (homepage and content pages alike), because users
     may need the address/opening hours wherever they are in the site. */
  .sidebar-card {
    order: 3;
    min-height: auto;
    padding: 20px 20px 22px;
    display: grid !important;
    /* Top row: logo (left, flexes) beside the hours block (right, sized to its
       content so OPENINGSTIJDEN never clips). The address spans the FULL width
       underneath both — the email is the longest line, and a narrow column
       made it overflow into the hours; giving it the whole card width lets it
       fit at the same 18px as every other line. */
    grid-template-columns: minmax(0, 1fr) max-content;
    grid-template-areas:
      "logo  hours"
      "addr  addr";
    align-items: center;
    column-gap: 14px;
    row-gap: 10px;
  }

  /* Keep the hours block compact on phone so it fits beside the logo. */
  .sidebar-card .hours-title {
    font-size: 15px;
    margin-bottom: 10px;
    white-space: nowrap;
  }

  .sidebar-card .hours-table td {
    font-size: 16px;
  }

  .sidebar-card .hours-table td:first-child {
    width: 48px;
  }

  .logo-link {
    grid-area: logo;
    align-self: center;
    justify-self: center;
    min-width: 0;          /* allow the column to shrink so hours fit */
  }

  .logo-img {
    margin: 0 auto;
    max-width: 160px;
    width: 100%;
  }

  .sidebar-hours {
    grid-area: hours;
    margin-top: 0;
    padding-top: 0;
    align-self: center;
  }

  .sidebar-contact {
    grid-area: addr;
    margin-top: 0;
    text-align: center;
    /* The desktop line-height of 1.7 makes the 5-line address very airy on
       phone (≈30px per line), which was the main source of dead whitespace
       pushing the "order a book" sticker below the fold. Tighten it. */
    line-height: 1.35;
  }

  .content-header h1 {
    font-size: 34px;
  }

  .agenda-item {
    grid-template-columns: 80px minmax(0, 1fr);
    gap: 16px;
  }

  /* On phones the date sits above the title; the thumb sits left. */
  .agenda-item-meta {
    grid-column: 1;
    grid-row: 1 / span 2;
  }

  .agenda-item-thumb img {
    width: 80px;
    height: 80px;
  }

  /* A 420px band eats most of a phone screen, and in 'contain' mode much of
     it would be empty. Shrink the banner; the fit modes carry over as-is. */
  .event-detail-image.fit-contain img,
  .event-detail-image.fit-blur img {
    height: 260px;
  }
}

@media (max-width: 420px) {
  /* Very narrow phones: shrink the logo a touch so it still sits
     comfortably beside the opening hours. */
  .logo-img {
    max-width: 150px;
  }

  .nav-tab,
  body:not(.has-content) .nav-tab {
    padding: 0 13px;
  }
}

/* Agenda archive — past events kept live for SEO, visually separated. */
.agenda-archive {
    margin-top: 2.5rem;
    padding-top: 1.5rem;
    border-top: 1px solid rgba(0, 0, 0, 0.12);
}
.agenda-archive-title {
    font-size: 1.1rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    opacity: 0.65;
    margin: 0 0 1rem;
}
/* Archive items read as "half grey": dimmed to 50% and their images
   desaturated so past events recede behind the live agenda. */
.agenda-archive .agenda-item {
    opacity: 0.5;
}
.agenda-archive .agenda-item-thumb img {
    filter: grayscale(1);
}

/* ── FC Boeken: huidige maandeditie(s) volledig + archieflijst eronder. ── */
.book-club-editions {
    margin-top: 2rem;
}
.book-club-edition + .book-club-edition {
    margin-top: 2.5rem;
    padding-top: 1.5rem;
    border-top: 1px solid rgba(0, 0, 0, 0.12);
}
.book-club-edition-title,
.book-club-detail-title {
    margin: 0 0 1rem;
}
.book-club-archive {
    margin-top: 2.5rem;
    padding-top: 1.5rem;
    border-top: 1px solid rgba(0, 0, 0, 0.12);
}
.book-club-archive-title {
    font-size: 1.1rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    opacity: 0.65;
    margin: 0 0 1rem;
}
.book-club-archive-list {
    list-style: none;
    margin: 0;
    padding: 0;
}
.book-club-archive-list li {
    padding: 0.4rem 0;
    border-bottom: 1px solid rgba(0, 0, 0, 0.08);
}
.book-club-archive-list a {
    font-weight: 700;
    text-decoration: none;
    color: inherit;
}
.book-club-archive-list a:hover {
    text-decoration: underline;
}

/* ── Nieuwsbrief: one tidy centred sign-up form, nothing else. ─────────── */
.newsletter {
  max-width: 420px;
  margin: 0 auto;
  padding: 8px 0 24px;
  text-align: center;
}

.newsletter-title {
  font-size: 26px;
  font-weight: 700;
  margin: 0 0 8px;
}

.newsletter-intro {
  font-size: 16px;
  line-height: 1.5;
  color: rgba(13, 13, 13, 0.75);
  margin: 0 0 28px;
}

.newsletter-form {
  display: flex;
  flex-direction: column;
  gap: 16px;
  text-align: left;
}

.newsletter-field {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.newsletter-field span {
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.01em;
}

.newsletter-field input {
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: 10px;
  font: inherit;
  background: #fff;
}

.newsletter-field input:focus {
  outline: none;
  border-color: var(--ink);
  box-shadow: 0 0 0 3px rgba(13, 13, 13, 0.08);
}

.newsletter-submit {
  margin-top: 4px;
  padding: 13px 22px;
  border: none;
  border-radius: 999px;
  background: #1c1c1c;
  color: #fff;
  font: inherit;
  font-weight: 700;
  font-size: 16px;
  cursor: pointer;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.22);
  transition: background 0.15s ease, transform 0.15s ease;
}

.newsletter-submit:hover {
  background: #000;
  transform: translateY(-1px);
}

/* Honeypot + recaptcha token field: present in the DOM, never shown. */
.newsletter-hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  opacity: 0;
}

/* Hide the floating reCAPTCHA badge — it's ugly. Google permits this as long
   as the reCAPTCHA disclosure is shown in text (see .recaptcha-terms below). */
.grecaptcha-badge {
  visibility: hidden;
}

/* The required reCAPTCHA disclosure, shown instead of the badge. Kept tiny
   and faint so it stays out of the way. */
.recaptcha-terms {
  margin-top: 8px;
  font-size: 9px;
  line-height: 1.3;
  opacity: 0.4;
}

.recaptcha-terms a {
  color: inherit;
  text-decoration: underline;
}

/* "Order a book" sticker. Pinned to the bottom-right corner (offsets set
   inline, with a small random jitter per request) so it sits in the free
   photo margin below the content card and never overlaps the content. */
.order-sticker {
  position: fixed;
  z-index: 60;
  width: 180px;
  padding: 0.75rem 1rem;
  background: #ffffff;
  color: #000000;
  font-weight: 700;
  font-size: 0.9rem;
  line-height: 1.3;
  text-align: center;
  border: 2px solid #000000;
  border-radius: 4px;
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.35);
  /* The random rotation lives in an inline `transform: rotate(...)`. We animate
     the independent `scale`/`translate` properties on hover so they compose
     with that rotation instead of overriding it. A springy cubic-bezier gives
     the little "pop" a sticker-peel feel. */
  scale: 1;
  translate: 0 0;
  transition: scale 0.22s cubic-bezier(0.34, 1.56, 0.64, 1),
              translate 0.22s cubic-bezier(0.34, 1.56, 0.64, 1),
              box-shadow 0.22s ease;
}

/* Micro-animation: a quick lift + pop with a deeper shadow on hover/focus. */
.order-sticker:hover,
.order-sticker:focus-within {
  scale: 1.06;
  translate: 0 -3px;
  box-shadow: 0 12px 24px rgba(0, 0, 0, 0.4);
}

.order-sticker a {
  color: inherit;
  text-decoration: underline;
  font-weight: 800;
}

.order-sticker a:hover {
  text-decoration: none;
}

/* Phone: the fixed bottom-right sticker overlaps the content and eats space,
   so on phone it leaves its fixed corner and flows in normal document order at
   the very end of the page (after the content + sidebar cards). The inline
   random right/bottom/rotation is neutralised so it sits flat and centred.
   Placed AFTER the base .order-sticker rule above so it wins the cascade. */
@media (max-width: 768px) {
  .order-sticker {
    position: static;
    order: 9;                 /* after content (2) and sidebar (3) cards */
    width: auto;
    max-width: 280px;
    margin: 0 auto 4px;
    right: auto !important;   /* drop the inline right/bottom offsets */
    bottom: auto !important;
    transform: none !important;  /* drop the inline random rotation */
    scale: 1 !important;
    translate: 0 0 !important;
  }
}

/* ============================================================
   V3 "rechthoekig" look (opt-in via ?rechthoekig=1)
   ------------------------------------------------------------
   Square corners everywhere + a clear drop shadow under every
   white panel. Each white element floats as its own rectangle:
   the nav tabs no longer dock into the content card, they sit
   above it as separate shadowed blocks (per the V3 mockup).
   ============================================================ */

/* Squaring --radius zeroes every corner that derives from it: the
   nav pills, both cards, inputs, etc. */
body.rechthoekig {
  --radius: 0px;
}

/* V3 uses one SOLID black offset shadow on every white panel: a hard black
   block dropped down-right with ZERO blur — a flat drop shadow, not a halo. */

/* Homepage tabs + the sticker + both cards: the full down-right drop shadow. */
body.rechthoekig:not(.has-content) .nav-tab,
body.rechthoekig .sidebar-card,
body.rechthoekig .content-card {
  box-shadow: 8px 8px 0 rgba(0, 0, 0, 1);
}

@media (min-width: 1025px) {
  /* Drop the folder-tab docking: no concave fillets. The active tab sits
     flush ON the content card. Its shadow must only fall to the RIGHT and
     DOWN onto the photo beside the card — never below, or it would draw a
     black seam between the tab and the card it rests on. So the solid shadow
     is offset right-only (zero downward offset). */
  body.rechthoekig.has-content .nav-tab.active {
    /* Right-only solid shadow on the photo beside the tab. The tab's bottom
       sits exactly on the card top (no -1px overlap): an overlap would push
       the shadow's bottom 1px below the card top, painting a 1px black sliver
       on top of the white card (tab z-index 41 > card 40). Flush bottom keeps
       the shadow column from ever bleeding onto the white card surface. */
    box-shadow: 8px 0 0 rgba(0, 0, 0, 1);
    /* The generic docked rule overlaps the tab 1px into the card to close a
       white-on-white hairline seam. In V3 that overlap pushes the solid black
       shadow column 1px below the card top, where it paints over the white card
       (tab z 41 > card z 40) — a faint black sliver at the seam. Sit flush
       instead: the card directly underneath still closes the white seam, and
       the shadow now stops exactly at the card top. */
    margin-bottom: 0;
  }

  /* When the active tab is the LAST (right-most) tab it sits flush against the
     card's right edge (both at the same x), so its right shadow shares the
     card's right-shadow column. But the card's shadow is offset 8px DOWN, so on
     the right edge it doesn't start until 8px below the card top — leaving a
     ~8px hole between where the tab's right-only shadow ends and the card's
     shadow begins (the photo showed through there). Give the last tab's shadow
     the same 8px downward offset so it reaches down and meets the card's
     shadow, closing that hole into one continuous right edge. */
  body.rechthoekig.active-tab-last.has-content .nav-tab.active {
    /* Keep the plain right-only edge shadow (same as every other tab). The
       card's right shadow starts 8px BELOW the card top, so there's a small
       hole at the bottom-right corner between where this edge ends and the
       card shadow begins. We fill ONLY that corner with the ::after below — a
       second box-shadow layer (8px 8px 0) would also paint a bottom shadow
       across the whole tab width, which we don't want (it'd look like the tab
       is floating off the card). */
    box-shadow: 8px 0 0 rgba(0, 0, 0, 1);
  }

  /* The 8px×8px black square that plugs the bottom-right corner hole, lining
     the tab's right-edge shadow up with the card's right shadow below it. Sits
     just outside the tab's right edge and reaches down to where the card
     shadow starts. Only the last tab needs it (only it hugs the card's right
     edge); ::after is otherwise display:none for the active tab. */
  body.rechthoekig.active-tab-last.has-content .nav-tab.active::after {
    content: '';
    display: block;
    position: absolute;
    left: 100%;            /* start at the tab's right edge */
    bottom: -8px;          /* reach 8px below the tab, to the card shadow */
    width: 8px;
    height: 8px;
    background: rgba(0, 0, 0, 1);
    z-index: -1;           /* behind the white tab, like a drop shadow */
  }

  body.rechthoekig.has-content .nav-tab.active::before,
  body.rechthoekig.has-content .nav-tab.active::after,
  body.rechthoekig.has-content .nav-tab:not(.active):hover::before,
  body.rechthoekig.has-content .nav-tab:not(.active):hover::after {
    display: none;
  }
}

/* Tablet band (769–1024px): below the docked-folder-tab breakpoint, EVERY
   content-page tab is a free-floating white pill over the photo (see the
   `max-width:1024.98px` block above) — the active tab no longer docks onto
   the card, it sits 8px above it as its own rectangle. The generic rule there
   gives those pills the soft blurred default shadow, which clashes with the
   hard-edged V3 look: the active tab ends up with a fuzzy halo while every
   other panel has the solid black drop shadow. Give all these floating tabs
   the same full down-right solid shadow as the homepage tabs so the V3 look
   stays consistent across this width — the missing bottom shadow on the
   active tab is restored because it's floating here, not docked. */
@media (min-width: 769px) and (max-width: 1024.98px) {
  body.rechthoekig.has-content .nav-tab {
    box-shadow: 8px 8px 0 rgba(0, 0, 0, 1);
  }
}

/* The sticker becomes a plain white shadowed rectangle (no black outline),
   matching the other panels in the V3 design. */
body.rechthoekig .order-sticker {
  border: none;
  border-radius: 0;
  box-shadow: 8px 8px 0 rgba(0, 0, 0, 1);
}

/* On hover the solid V3 shadow grows with the lift, keeping the hard-edged
   look instead of the soft default-mode shadow. */
body.rechthoekig .order-sticker:hover,
body.rechthoekig .order-sticker:focus-within {
  box-shadow: 12px 12px 0 rgba(0, 0, 0, 1);
}

/* Nieuwsbrief: de invoervelden en knop hebben vaste afgeronde hoeken; in de
   rechthoekige (V3) look maken we ook die vierkant zodat ze bij de rest passen. */
body.rechthoekig .newsletter-field input,
body.rechthoekig .newsletter-submit {
  border-radius: 0;
}

/* Phone (≤768px): the desktop rechthoekig nav-tab shadow rule lives in a
   min-width:1025px block, so on mobile the pills fall back to the soft
   default shadow — or none on the active tab. Give every nav pill the solid
   V3 drop shadow here so the rectangular look carries to phones too. A
   smaller offset suits the compact pills. */
@media (max-width: 768px) {
  body.rechthoekig .nav-tab,
  body.rechthoekig:not(.has-content) .nav-tab {
    box-shadow: 4px 4px 0 rgba(0, 0, 0, 1);
  }

  /* On a content page the active tab merges into the card with a flat bottom.
     Mirror the desktop V3 behaviour: a hard RIGHT-only solid shadow falls onto
     the photo beside the tab (no bottom offset, or it would draw a black seam
     between the tab and the card it rests on). This restores the V3 drop
     shadow that was previously replaced by a soft top-only shadow here. */
  body.rechthoekig.has-content .nav-tab.active {
    box-shadow: 4px 0 0 rgba(0, 0, 0, 1);
  }

  /* When the active tab is the LAST (right-most) tab, its right edge lines up
     with the content card's right edge, so its right shadow shares the card's
     right-shadow column. But the card's shadow is offset 8px DOWN, leaving a
     hole between where the tab's right shadow ends and the card's shadow
     begins. Plug that corner with a small black square (mirrors the desktop
     ::after) so the tab's right shadow connects to the page's shadow. */
  body.rechthoekig.active-tab-last.has-content .nav-tab.active::after {
    content: '';
    display: block;
    position: absolute;
    left: 100%;            /* start at the tab's right edge */
    bottom: -8px;          /* reach down to where the card shadow starts */
    width: 4px;            /* match the tab's 4px shadow offset on phone */
    height: 8px;
    background: rgba(0, 0, 0, 1);
    z-index: -1;           /* behind the white tab, like a drop shadow */
  }
}
