/* Juke Lucid — jukelucid.com
   Single stylesheet. No framework, no build step.

   The chrome here is deliberately monochrome. Eight illustrated sleeves and
   five animated videos have to sit together without fighting each other, and
   any brand colour in the frame would be a ninth thing competing with them.
   The only colour on this site comes from the artwork. If something needs to
   be visible — a focus ring, a hover state — it is white. */

:root {
  --jl-bg:      #000000;
  --jl-surface: #0B0B0B;   /* cards, expanded panels */
  --jl-line:    rgba(255,255,255,0.12);
  --jl-text:    #FFFFFF;
  --jl-muted:   rgba(255,255,255,0.56);

  /* 0.38, not the 0.34 originally specified. White at 0.34 on pure black is
     2.89:1, and this is used for the two three-up links you are NOT pointing
     at — text at 24-40px, which WCAG counts as large and requires 3:1. 0.38
     is 3.39:1. Four hundredths of an alpha, and the difference between a
     de-emphasised state and an inaccessible one. */
  --jl-faint:   rgba(255,255,255,0.38);

  /* A SECOND border token, for borders that are the only thing identifying a
     control as a control.

     --jl-line at 0.12 is 1.27:1. That is fine, and deliberately invisible, for
     a divider: WCAG 1.4.11 does not govern decoration. It is not fine for a
     transparent button or a transparent input, where the 1px border IS the
     button — there is no fill, no shadow and no colour doing that job, so the
     border carries the whole of "this is pressable" and 1.4.11's 3:1 applies.

     Only .btn and the form controls use this. Every divider, panel edge and
     hairline stays at 0.12, so the page keeps its quietness everywhere it is
     merely drawing a line rather than drawing a control. */
  --jl-line-ui: rgba(255,255,255,0.38);

  --jl-max:     1240px;
  --jl-gutter:  clamp(20px, 5vw, 64px);
  --jl-ease:    cubic-bezier(0.2, 0.7, 0.3, 1);
  --jl-dur:     200ms;

  --jl-header:  64px;

  --jl-font: 'Space Grotesk', -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;

  /* No light mode. Told to the browser so form controls, scrollbars and the
     tap-highlight all come up dark rather than being fought in CSS. */
  color-scheme: dark;
}

/* Self-hosted variable Space Grotesk, latin + latin-ext.
   These two files are Google's own subsets, taken from the CSS2 API rather
   than subset by hand — same bytes, and the unicode-range below is theirs, so
   a latin-ext character still pulls the second file only when it is used.
   One family, one axis, 41KB for both. */
@font-face {
  font-family: 'Space Grotesk';
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url('/assets/fonts/space-grotesk-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Space Grotesk';
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url('/assets/fonts/space-grotesk-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* Every in-page jump has to clear the 64px fixed header, and this is the
     one place to say so. Set on the scroll container it covers all of them —
     the /watch/ video anchors, the nine <h2 id> anchors on /privacy/, and
     /privacy/#cookies, which is where the cookie banner's own link points.
     Per-element scroll-margin was doing this for the videos only, so every
     other anchor landed underneath the bar. */
  scroll-padding-top: 96px;
}

body {
  margin: 0;
  font-family: var(--jl-font);
  font-size: 1rem;
  line-height: 1.6;
  color: var(--jl-text);
  background: var(--jl-bg);
  -webkit-font-smoothing: antialiased;
  /* The video hero is full-bleed; nothing on this site scrolls sideways. */
  overflow-x: hidden;
}

img, svg, video { display: block; max-width: 100%; }
img { height: auto; }

.wrap { max-width: var(--jl-max); margin: 0 auto; padding: 0 var(--jl-gutter); }

/* ---------- Typography ---------- */

h1, h2, h3 { margin: 0 0 0.5em; font-weight: 500; letter-spacing: -0.02em; }
h1 { font-size: clamp(1.75rem, 5vw, 3.25rem); line-height: 1.06; }
h2 { font-size: clamp(1.25rem, 2.5vw, 1.75rem); line-height: 1.15; }
h3 { font-size: 1rem; }
p  { margin: 0 0 1rem; }
p:last-child { margin-bottom: 0; }

a { color: var(--jl-text); text-decoration-thickness: 1px; text-underline-offset: 3px; }

/* The one section label used site-wide. */
.label {
  font-size: 0.75rem; font-weight: 600; text-transform: uppercase;
  letter-spacing: 0.18em; color: var(--jl-muted); margin: 0 0 1.25rem;
}
.meta { font-size: 0.8125rem; color: var(--jl-muted); }
.prose { max-width: 62ch; }
.prose a { color: var(--jl-text); }

/* Pages other than the homepage lead with a small h1, not a display one —
   the artwork is the headline everywhere on this site, so the words that
   introduce it stay quiet. */
.page-head { padding: calc(var(--jl-header) + clamp(40px, 8vw, 88px)) 0 clamp(24px, 4vw, 40px); }
.page-head h1 { font-size: 1.25rem; margin-bottom: 0.35rem; }
.page-head p  { color: var(--jl-muted); margin: 0; font-size: 0.9375rem; }

/* Visually hidden but available to assistive technology. The clip-path pair
   rather than display:none or visibility:hidden, both of which remove the text
   from the accessibility tree — which would defeat the point. */
.vh {
  position: absolute; width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}

/* ---------- Focus ---------- */

/* One rule, never removed. White on black is the only thing that reads on
   every surface here, including on top of an arbitrary video frame. */
:focus-visible { outline: 2px solid #fff; outline-offset: 3px; }
/* <main> carries tabindex="-1" so the skip link can actually move focus and
   the virtual cursor. It is a scripted focus target, never tabbed to, so it
   should not draw a ring when it receives that focus. */
main:focus, main:focus-visible { outline: none; }

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 200;
  background: #fff; color: #000; padding: 0.75rem 1.25rem;
  font-size: 0.8125rem; text-decoration: none;
}
.skip:focus { left: 0; }

/* ---------- Header ---------- */

.site-header {
  position: fixed; inset: 0 0 auto; z-index: 100;
  height: var(--jl-header);
  background: rgba(0,0,0,0.72);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--jl-line);
  transition: background var(--jl-dur) var(--jl-ease),
              border-color var(--jl-dur) var(--jl-ease);
}
.site-header .wrap {
  height: 100%; display: flex; align-items: center;
  justify-content: space-between; gap: 1rem;
}

/* Homepage only: the bar starts invisible over the video and gains its
   background after 80px of scroll, when site.js adds .is-stuck. The class is
   on the element from the server rather than added by script, so the
   transparent state is never painted over the video and then corrected. */
.site-header.is-clear { background: transparent; border-bottom-color: transparent; }
.site-header.is-clear.is-stuck {
  background: rgba(0,0,0,0.72); border-bottom-color: var(--jl-line);
}

.brand { display: block; color: var(--jl-text); line-height: 0; }
.brand svg { width: 92px; height: auto; fill: currentColor; }
.brand .monogram { display: none; width: 30px; }

.site-nav { display: flex; gap: clamp(14px, 3vw, 28px); align-items: center; }
.site-nav a {
  color: var(--jl-muted); text-decoration: none;
  font-size: 0.8125rem; text-transform: uppercase; letter-spacing: 0.12em;
  /* 44px of touch target without 44px of visible chrome: the bar is only
     64px tall, so the padding is vertical-centred rather than added. */
  display: inline-flex; align-items: center; min-height: 44px;
  transition: color var(--jl-dur) var(--jl-ease);
}
.site-nav a:hover { color: var(--jl-text); }
.site-nav a[aria-current="page"] {
  color: var(--jl-text);
  text-decoration: underline; text-decoration-thickness: 1px;
  text-underline-offset: 6px;
}

@media (max-width: 479px) {
  .brand .wordmark { display: none; }
  .brand .monogram { display: block; }
  .site-nav { gap: 13px; }
  .site-nav a { font-size: 0.75rem; letter-spacing: 0.08em; }
}

/* ---------- Buttons ---------- */

/* The only button style on the site. Everything that is pressable and is not
   a nav link or an artwork tile uses this, including the form submit. */
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 44px; padding: 0 1.25rem;
  border: 1px solid var(--jl-line-ui); background: transparent; color: var(--jl-text);
  font: inherit; font-size: 0.75rem; font-weight: 500;
  text-transform: uppercase; letter-spacing: 0.14em; text-decoration: none;
  cursor: pointer; border-radius: 0;
  transition: background var(--jl-dur) var(--jl-ease),
              color var(--jl-dur) var(--jl-ease),
              border-color var(--jl-dur) var(--jl-ease);
}
.btn:hover { background: #fff; color: #000; border-color: #fff; }
.btn[disabled] { opacity: 0.5; cursor: default; }
.btn[disabled]:hover { background: transparent; color: var(--jl-text); border-color: var(--jl-line-ui); }
.btn-row { display: flex; flex-wrap: wrap; gap: 0.5rem; }

/* ---------- Hero ---------- */

.hero {
  position: relative; height: 100vh; height: 100dvh;
  display: grid; place-items: center;
  overflow: hidden; background: #000;
  /* The hero is a <section>, so without this it inherits the band padding set
     below and loses 112-208px out of a box that is exactly one viewport tall
     and clips its overflow. On a landscape phone — 390px tall — that put the
     bottom of the wordmark off the bottom of the screen. It centres with
     place-items, so it needs no padding of its own. */
  padding: 0;
}
.hero video, .hero .hero-poster {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; object-position: center;
}
/* Holds the wordmark against any frame the loop happens to be on. */
.hero::after {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(rgba(0,0,0,0.45), rgba(0,0,0,0.15) 40%, rgba(0,0,0,0.75));
}
.hero-inner { position: relative; z-index: 1; text-align: center; padding: 0 var(--jl-gutter); }
.hero-inner svg { width: min(560px, 68vw); height: auto; fill: #fff; margin: 0 auto; }
.hero-inner p {
  margin: 1.5rem 0 0; font-size: 0.75rem; text-transform: uppercase;
  letter-spacing: 0.28em; color: var(--jl-muted);
}

.scroll-cue {
  position: absolute; z-index: 1; bottom: 28px; left: 50%; translate: -50% 0;
  width: 1px; height: 40px; background: var(--jl-line); overflow: hidden;
}
.scroll-cue::after {
  content: ''; position: absolute; inset: 0; background: #fff;
  animation: cue 2.2s var(--jl-ease) infinite;
}
@keyframes cue {
  0%   { transform: translateY(-100%); }
  60%, 100% { transform: translateY(100%); }
}

/* ---------- Latest release ---------- */

section { padding: clamp(56px, 9vw, 104px) 0; }

.latest { display: grid; gap: clamp(24px, 4vw, 48px); align-items: start; }
@media (min-width: 800px) { .latest { grid-template-columns: 440px 1fr; } }
.latest img { width: 100%; aspect-ratio: 1; object-fit: cover; }
.latest h2 { font-size: clamp(1.5rem, 3vw, 2rem); margin-bottom: 0.25rem; }
.latest .meta { margin: 0 0 1.75rem; }

/* ---------- Three-up ---------- */

/* Three large text links filling a band. The whole row is the hit area, and
   hovering one fades the other two rather than lighting the hovered one — the
   page is already white on black, so there is nothing brighter to go to. */
.threeup { border-top: 1px solid var(--jl-line); }
.threeup a {
  display: block;
  /* The band itself stays full-bleed so its rules span the viewport, but the
     text aligns to the same 1240px column as everything else. Below 1368px the
     max() resolves to the gutter and nothing changes; above it, the three
     biggest words on the page stop drifting 340px left of the Latest block. */
  padding-block: clamp(20px, 3.5vw, 34px);
  padding-inline: max(var(--jl-gutter), calc((100% - var(--jl-max)) / 2));
  border-bottom: 1px solid var(--jl-line);
  font-size: clamp(1.5rem, 4vw, 2.5rem); font-weight: 500; letter-spacing: -0.02em;
  text-decoration: none; color: var(--jl-text);
  transition: color var(--jl-dur) var(--jl-ease);
}
.threeup:hover a { color: var(--jl-faint); }
.threeup a:hover, .threeup a:focus-visible { color: var(--jl-text); }

/* ---------- Listen grid ---------- */

.grid {
  display: grid; gap: clamp(12px, 2vw, 24px);
  grid-template-columns: repeat(auto-fill, minmax(clamp(150px, 22vw, 250px), 1fr));
}

.tile {
  position: relative; padding: 0; border: 0; background: none; color: inherit;
  font: inherit; cursor: pointer; overflow: hidden; display: block;
  aspect-ratio: 1; width: 100%; text-align: left;
}
.tile img {
  width: 100%; height: 100%; object-fit: cover;
  transition: scale var(--jl-dur) var(--jl-ease);
}
.tile:hover img, .tile:focus-visible img { scale: 1.02; }

.tile-info {
  position: absolute; inset: 0; z-index: 1;
  display: flex; flex-direction: column; justify-content: flex-end;
  padding: 14px; gap: 2px;
  /* A GRADIENT, not the flat rgba(0,0,0,0.55) wash this started as.

     The flat wash was measured against the eight real sleeves and it fails
     WCAG AA badly. The text sits on ARTWORK, not on the page's black, and a
     55% scrim over a pale sleeve is still pale: the year came out at 2.32:1
     on special-delivery.jpg and under 4.5:1 across 97% of its own text band
     on movemaker.jpg. Checking --jl-muted against #000 — which is where this
     palette was signed off — says 6.48:1 and misses the whole problem,
     because #000 is not what is behind it.

     The gradient is heaviest exactly where the text is (bottom-anchored) and
     fades to nothing at the top, so the artwork still reads through the upper
     two thirds of the tile and only the strip carrying words is darkened.
     Same monochrome, no tint, and the sleeve is still the thing you see. */
  background: linear-gradient(to top,
    rgba(0,0,0,0.90) 0%, rgba(0,0,0,0.82) 30%, rgba(0,0,0,0.62) 55%, transparent 100%);
  opacity: 0;
  transition: opacity var(--jl-dur) var(--jl-ease);
}
.tile:hover .tile-info,
.tile:focus-visible .tile-info,
.tile[aria-expanded="true"] .tile-info { opacity: 1; }
.tile-info strong { font-size: 1rem; font-weight: 500; }
.tile-info span   { font-size: 0.8125rem; color: var(--jl-muted); }

/* There is no hover on a touch screen, so the overlay would never appear and
   the titles would be unreadable. Shown permanently instead, slightly under
   full opacity so the artwork still reads through it. */
@media (hover: none) {
  /* Full opacity, not 0.9. On touch this overlay is permanent — there is no
     hover to bring it up — so it is the only state that exists, and fading it
     costs contrast on text that is already the hardest thing on the page to
     read. The difference between 0.9 and 1 on a dark gradient is invisible;
     the difference in the measured ratio is not. */
  .tile-info { opacity: 1; }
}

/* At two columns a tile is about 160px, and the overlay is permanently visible
   there because there is no hover to reveal it. A 1rem title on a 160px sleeve
   takes two lines and covers a third of the artwork — which inverts the point
   of the page. The type steps down rather than the overlay getting fainter:
   the words still have to be readable, they just need to take less room. */
/* Keyed to the TILE, not the viewport. A viewport breakpoint gets this wrong
   in both directions: auto-fill adds a third column at about 521px, which makes
   tiles smaller than they were at 520px, so a max-width query switches the
   step-down off exactly where it is needed most. The tile is the thing whose
   size actually matters, so the tile is what gets measured. */
.tile { container-type: inline-size; }
@container (max-width: 200px) {
  .tile-info { padding: 10px; }
  .tile-info strong { font-size: 0.8125rem; line-height: 1.25; }
  .tile-info span   { font-size: 0.6875rem; }
}

/* ---------- Expanded panel ---------- */

/* Injected by site.js immediately after the clicked tile and spanning the full
   row. Grid auto-placement then drops it onto its own line directly beneath
   that tile's row at any column count — no row-index arithmetic, and it stays
   correct when the column count changes on resize. */
.panel {
  grid-column: 1 / -1;
  background: var(--jl-surface);
  padding: clamp(16px, 3vw, 28px);
  display: grid; gap: 1rem;
}
.panel iframe { width: 100%; height: 152px; border: 0; display: block; }
.panel .credit { font-size: 0.8125rem; color: var(--jl-muted); margin: 0; }

/* ---------- Watch ---------- */

.videos { display: grid; gap: clamp(48px, 8vw, 96px); }
.video { max-width: 1100px; margin: 0 auto; width: 100%; scroll-margin-top: 96px; }

.facade {
  position: relative; width: 100%; aspect-ratio: 16 / 9;
  padding: 0; border: 0; background: #000; cursor: pointer; display: block;
  overflow: hidden;
}
.facade img {
  width: 100%; height: 100%; object-fit: cover;
  filter: brightness(0.85);
  transition: filter var(--jl-dur) var(--jl-ease);
}
.facade:hover img, .facade:focus-visible img { filter: brightness(1); }

.facade span {
  position: absolute; top: 50%; left: 50%; translate: -50% -50%;
  width: 72px; height: 72px; border-radius: 50%;
  border: 1px solid #fff; background: transparent;
  display: grid; place-items: center;
  transition: background var(--jl-dur) var(--jl-ease);
}
/* The triangle is a clip-path on a plain div rather than an SVG or a border
   trick, so it inherits the colour flip below with one declaration. */
.facade span::before {
  content: ''; width: 18px; height: 20px; margin-left: 4px;
  background: #fff; clip-path: polygon(0 0, 100% 50%, 0 100%);
  transition: background var(--jl-dur) var(--jl-ease);
}
.facade:hover span, .facade:focus-visible span { background: #fff; }
.facade:hover span::before, .facade:focus-visible span::before { background: #000; }

.video iframe { width: 100%; aspect-ratio: 16 / 9; border: 0; display: block; }
.video-meta { margin: 0.875rem 0 0; }
.video-meta h2 { font-size: 1rem; font-weight: 500; margin: 0 0 0.15rem; letter-spacing: 0; }
.video-meta h2 em { color: var(--jl-muted); font-style: italic; }
.video-meta p { margin: 0; font-size: 0.8125rem; color: var(--jl-muted); }

/* ---------- Credits disclosure ---------- */

details { border-top: 1px solid var(--jl-line); padding-top: 1.25rem; }
summary {
  cursor: pointer; list-style: none; min-height: 44px;
  display: flex; align-items: center;
  font-size: 0.75rem; font-weight: 600; text-transform: uppercase;
  letter-spacing: 0.18em; color: var(--jl-muted);
  transition: color var(--jl-dur) var(--jl-ease);
}
summary::-webkit-details-marker { display: none; }
summary::after { content: ' +'; margin-left: 0.5rem; }
details[open] summary::after { content: ' –'; }
summary:hover { color: var(--jl-text); }
details .prose { padding-top: 1rem; font-size: 0.9375rem; color: var(--jl-muted); }
details .prose em { font-style: italic; }

/* ---------- Form ---------- */

.form { max-width: 560px; }
.field { margin-bottom: 1.25rem; }
.field label {
  display: block; font-size: 0.75rem; text-transform: uppercase;
  letter-spacing: 0.12em; color: var(--jl-muted); margin-bottom: 0.5rem;
}
.field input, .field select, .field textarea {
  width: 100%; font: inherit; font-size: 1rem; color: var(--jl-text);
  background: transparent; border: 1px solid var(--jl-line-ui); border-radius: 0;
  padding: 14px; -webkit-appearance: none; appearance: none;
  transition: border-color var(--jl-dur) var(--jl-ease);
}
.field select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' stroke='%23ffffff' stroke-opacity='0.56' stroke-width='1.4' fill='none' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 14px center; background-size: 12px;
  padding-right: 40px;
}
.field textarea { min-height: 10rem; resize: vertical; line-height: 1.6; }
.field input:focus, .field select:focus, .field textarea:focus { border-color: #fff; }
.field input[aria-invalid="true"], .field textarea[aria-invalid="true"] { border-color: #fff; }
.field .err { display: block; margin-top: 0.5rem; font-size: 0.8125rem; color: var(--jl-text); }

/* Hidden from people and from assistive tech, visible to naive bots. */
.hp { position: absolute !important; left: -9999px !important; width: 1px; height: 1px; overflow: hidden; }

.form-status {
  border: 1px solid var(--jl-line); background: var(--jl-surface);
  padding: 0.875rem 1rem; margin: 0 0 1.75rem; font-size: 0.9375rem;
}
.form-status p { margin: 0; }
.form-actions { margin-top: 1.5rem; }
.form-note { font-size: 0.8125rem; color: var(--jl-muted); margin-top: 1.25rem; }
/* Turnstile's default widget is a fixed 300px, which overruns the 280px
   content column at a 320px viewport — and body has overflow-x: hidden, so
   the overhang is not even scrollable to. data-size="flexible" on the div in
   contact/index.html asks Turnstile for a widget that fits its container
   instead; this caps it as a second line of defence in case that attribute is
   ever dropped. */
.cf-turnstile { margin-top: 1.5rem; max-width: 100%; overflow: hidden; }

/* ---------- Footer ---------- */

.site-footer {
  border-top: 1px solid var(--jl-line);
  padding: clamp(32px, 5vw, 48px) 0 clamp(40px, 6vw, 56px);
  font-size: 0.8125rem; color: var(--jl-muted);
}
.site-footer .bio { margin: 0 0 1.5rem; color: var(--jl-muted); }
.site-footer .links {
  display: flex; flex-wrap: wrap; gap: 0.25rem 1.5rem; margin: 0 0 2rem;
}
.site-footer .links a {
  color: var(--jl-muted); text-decoration: none;
  font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.12em;
  display: inline-flex; align-items: center; min-height: 44px;
  transition: color var(--jl-dur) var(--jl-ease);
}
.site-footer .links a:hover { color: var(--jl-text); }
.site-footer .fine {
  display: flex; flex-wrap: wrap; justify-content: space-between; gap: 0.5rem 1.5rem;
  border-top: 1px solid var(--jl-line); padding-top: 1.25rem; margin: 0;
}
.site-footer .fine a, .site-footer .fine button {
  color: var(--jl-muted); text-decoration: none;
  background: none; border: 0; padding: 0; font: inherit; cursor: pointer;
  transition: color var(--jl-dur) var(--jl-ease);
}
.site-footer .fine a:hover, .site-footer .fine button:hover { color: var(--jl-text); }
.site-footer .fine > div { display: flex; gap: 1.5rem; }

/* ---------- 404 ---------- */

.centred {
  min-height: 100vh; min-height: 100dvh;
  display: grid; place-items: center; text-align: center; padding: 0 var(--jl-gutter);
}
.centred svg { width: min(360px, 60vw); height: auto; fill: #fff; margin: 0 auto 2rem; }
.centred p { color: var(--jl-muted); margin-bottom: 2rem; }

/* ---------- Motion ---------- */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    transition: none !important; animation: none !important; scroll-behavior: auto !important;
  }
  /* The cue is a pure animation — with the animation off it is a stray
     hairline, so it goes entirely rather than sitting there static. */
  .scroll-cue { display: none; }
}

/* ---------- Cookie banner ----------

   CookieConsent ships its palette on :root and only goes dark when a
   .cc--darkmode class is present. Rather than manage that class in JS, its
   variables are remapped onto this file's tokens below.

   LOAD ORDER IS LOAD-BEARING. This block and the library's own :root have
   equal specificity, so the later one wins — every page head must link
   cookieconsent-3.1.0.css BEFORE style.css. Reverse them and the whole
   restyle silently does nothing and the banner renders white on a black site,
   with no error anywhere to say so. */

:root {
  --cc-font-family: var(--jl-font);
  --cc-bg: var(--jl-surface);
  --cc-primary-color: var(--jl-text);
  --cc-secondary-color: var(--jl-muted);
  --cc-link-color: var(--jl-text);

  --cc-modal-border-radius: 0;
  --cc-btn-border-radius: 0;
  --cc-modal-margin: 1.5rem;

  /* The site has exactly one button treatment: outlined at rest, inverting to
     white-on-black on hover. Both banner buttons take it, so "Accept all" and
     "Only necessary" are visually identical and the choice is not steered at
     all. searchlucid leaves accept filled and reject outlined; there is no
     reason to carry that here, where nothing is being sold. */
  --cc-btn-primary-bg: transparent;
  --cc-btn-primary-color: var(--jl-text);
  --cc-btn-primary-border-color: var(--jl-line-ui);
  --cc-btn-primary-hover-bg: #fff;
  --cc-btn-primary-hover-color: #000;
  --cc-btn-primary-hover-border-color: #fff;

  --cc-btn-secondary-bg: transparent;
  --cc-btn-secondary-color: var(--jl-text);
  --cc-btn-secondary-border-color: var(--jl-line-ui);
  --cc-btn-secondary-hover-bg: #fff;
  --cc-btn-secondary-hover-color: #000;
  --cc-btn-secondary-hover-border-color: #fff;

  --cc-separator-border-color: var(--jl-line);
  --cc-section-category-border: var(--jl-line);
  --cc-cookie-category-block-bg: #000;
  --cc-cookie-category-block-border: var(--jl-line);
  --cc-cookie-category-block-hover-bg: #000;
  --cc-cookie-category-block-hover-border: var(--jl-text);
  --cc-cookie-category-expanded-block-bg: transparent;
  --cc-cookie-category-expanded-block-hover-bg: #000;

  --cc-overlay-bg: rgba(0,0,0,0.8);
  --cc-footer-bg: var(--jl-surface);
  --cc-footer-color: var(--jl-muted);
  --cc-footer-border-color: var(--jl-line);

  --cc-toggle-on-bg: #fff;
  --cc-toggle-off-bg: var(--jl-faint);
  --cc-toggle-readonly-bg: var(--jl-line);
  --cc-toggle-readonly-knob-bg: #000;
  --cc-toggle-readonly-knob-icon-color: var(--jl-muted);
  --cc-toggle-enabled-icon-color: #000;
  --cc-toggle-disabled-icon-color: #000;

  --cc-webkit-scrollbar-bg: var(--jl-line);
  --cc-webkit-scrollbar-hover-bg: var(--jl-muted);
}

#cc-main .cm__btn, #cc-main .pm__btn {
  font-size: 0.75rem; font-weight: 500;
  text-transform: uppercase; letter-spacing: 0.14em;
}

/* Keep Accept all and Only necessary side by side at every width so neither
   sits above the other and reads as the primary path. !important is
   load-bearing, not lazy: below 640px the library forces flex-direction:column
   with !important of its own, so an ordinary rule loses however specific it
   is. These selectors carry an extra id over theirs and land later. */
#cc-main .cm__btns .cm__btn-group:first-child,
#cc-main .pm__footer .pm__btn-group:first-child {
  display: flex !important; flex-direction: row !important; gap: 0.5rem;
}
#cc-main .cm__btns .cm__btn-group:first-child .cm__btn,
#cc-main .pm__footer .pm__btn-group:first-child .pm__btn {
  flex: 1 1 0 !important; min-width: 0 !important;
}
/* The library spaces stacked buttons with a top margin, which in a row
   becomes a vertical offset between the pair. The gap above replaces it. */
#cc-main .cm__btns .cm__btn-group:first-child .cm__btn + .cm__btn,
#cc-main .pm__footer .pm__btn-group:first-child .pm__btn + .pm__btn { margin: 0 !important; }

/* "Manage preferences" drops to a text link. It can afford to be quieter than
   the other two because it is not the reject — declining outright is already
   one click in the row above, and nothing is hidden behind this. */
#cc-main .cm__btns .cm__btn-group:nth-child(2) .cm__btn {
  background: transparent; border-color: transparent; color: var(--jl-muted);
  letter-spacing: 0.12em; min-height: 44px;
  text-decoration: underline; text-underline-offset: 4px;
}
#cc-main .cm__btns .cm__btn-group:nth-child(2) .cm__btn:hover {
  background: transparent; border-color: transparent; color: var(--jl-text);
}
