/* ───────────────────────────────────────────────────────────────
   PARANOID AND READY — shared foundation

   Loaded by every page in the new system: tokens, reset, type scale,
   buttons, the reel component and the fixed chrome. Page-specific layout
   lives in home.css and category.css.

   Nothing here sets overflow on the root. The homepage locks the document
   and scrolls its deck instead; the inner pages scroll normally.
   ─────────────────────────────────────────────────────────────── */

:root {
  --void: #0C0C0C;
  --bone: #EFEBE4;
  --signal: #E8321E;
  --hair: rgba(239, 235, 228, 0.18);
  --hair-dark: rgba(12, 12, 12, 0.16);
  /* svh so mobile browser chrome never clips a bottom-anchored block */
  --h: 100svh;
  --gutter: clamp(20px, 5vw, 72px);
  --maxw: 1400px;
}

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

body {
  background: var(--void);
  color: var(--bone);
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  -webkit-font-smoothing: antialiased;
}

img { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }
ul, ol { list-style: none; }
button { font: inherit; color: inherit; background: none; border: none; cursor: pointer; }

/* ── Type ───────────────────────────────────────────────────────
   Anton carries every headline. It is a single heavy condensed weight,
   which is why a long phrase can run large without wrapping into mush.
   Everything that is not a headline stays in JetBrains Mono, so the site
   still reads as a document underneath the poster type. */
.display {
  font-family: 'Anton', 'Arial Narrow', Impact, sans-serif;
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.01em;
  line-height: 0.92;
}

.eyebrow {
  font-size: clamp(9px, 1.1vw, 11px);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 4px;
  color: var(--signal);
}

.lede {
  font-size: clamp(12px, 1.4vw, 14px);
  line-height: 1.65;
  color: rgba(239, 235, 228, 0.66);
  max-width: 58ch;
}

.btn {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  padding: 14px 24px;
  background: var(--signal);
  color: var(--void);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 2px;
  text-transform: uppercase;
  transition: background 0.2s, color 0.2s;
}

.btn:hover { background: var(--bone); color: var(--void); }
.btn--ghost { background: transparent; color: var(--bone); border: 1px solid var(--hair); }
.btn--ghost:hover { background: var(--bone); color: var(--void); }

/* ── Reel ───────────────────────────────────────────────────────
   A horizontal run where the item nearest the centre line is the live one
   and its neighbours sit back. Card widths are fixed and emphasis is done
   with transform, never with width: a width transition would move every
   later card mid-animation and the centring maths would chase a target
   that keeps moving. The owning section sets --card. */
.reel-wrap { position: relative; display: flex; align-items: center; min-height: 0; }

.reel {
  display: flex;
  align-items: center;
  gap: clamp(16px, 2vw, 32px);
  width: 100%;
  /* Side padding lets the first and last card reach the centre. */
  padding: clamp(10px, 2vh, 24px) max(var(--gutter), calc(50% - var(--card) / 2));
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  scroll-behavior: smooth;
}

.reel::-webkit-scrollbar { display: none; }
.reel:focus-visible { outline: 1px solid var(--signal); outline-offset: -4px; }

.reel-item {
  flex: 0 0 auto;
  width: var(--card);
  scroll-snap-align: center;
  transform: scale(0.82);
  opacity: 0.4;
  /* Slower than the panel transitions on purpose: the reel is meant to be
     read on the way past, not flicked through. */
  transition: transform 1.05s cubic-bezier(.16,.84,.36,1), opacity 1.05s ease;
  will-change: transform;
  position: relative;
}

.reel-item.is-active { transform: scale(1); opacity: 1; }

/* Too short to be a run. The centring padding and the snap both exist to
   bring one card to the middle, which is the wrong answer for two: they go,
   and the pair is centred as a block instead. safe center so an overflowing
   pair on a narrow screen falls back to start rather than clipping left. */
.reel-wrap.is-pair .reel { justify-content: safe center; scroll-snap-type: none; padding-inline: var(--gutter); }
.reel-wrap.is-pair .reel-btn { display: none; }

.reel-btn {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 3;
  width: 42px;
  height: 42px;
  border: 1px solid var(--hair);
  color: var(--bone);
  font-size: 20px;
  line-height: 1;
  background: rgba(12, 12, 12, 0.6);
  transition: background 0.2s, color 0.2s, opacity 0.2s;
}

.reel-btn:hover { background: var(--signal); color: var(--void); }
.reel-btn:disabled { opacity: 0.2; cursor: default; }
.reel-btn:disabled:hover { background: rgba(12, 12, 12, 0.6); color: var(--bone); }
.reel-prev { left: clamp(6px, 1.2vw, 18px); }
.reel-next { right: clamp(6px, 1.2vw, 18px); }

/* ── Chrome ─────────────────────────────────────────────────────*/
.mark {
  position: fixed;
  top: clamp(16px, 3vh, 30px);
  left: var(--gutter);
  z-index: 30;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 3px;
  text-transform: uppercase;
  color: var(--bone);
  transition: opacity 0.4s ease, color 0.2s;
}

.mark:hover { color: var(--signal); }

.burger {
  position: fixed;
  top: clamp(14px, 2.8vh, 28px);
  right: var(--gutter);
  z-index: 31;
  width: 30px;
  height: 22px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding: 4px 0;
}

.burger span { display: block; height: 2px; background: var(--bone); transition: transform 0.3s ease, opacity 0.2s ease; }
.burger[aria-expanded='true'] span:nth-child(1) { transform: translateY(6px) rotate(45deg); }
.burger[aria-expanded='true'] span:nth-child(2) { opacity: 0; }
.burger[aria-expanded='true'] span:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }

/* No panel, no overlay, no fill: the menu is text arriving on whatever is
   already behind it. Hence a shadow rather than a backdrop. Mono rather than
   Anton, because six heavy condensed lines take over the corner. */
.menu {
  position: fixed;
  top: calc(clamp(14px, 2.8vh, 28px) + 40px);
  right: var(--gutter);
  z-index: 30;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 10px;
  text-align: right;
  opacity: 0;
  transform: translateY(-8px);
  pointer-events: none;
  transition: opacity 0.28s ease, transform 0.28s ease;
}

.menu[data-open='true'] { opacity: 1; transform: none; pointer-events: auto; }

.menu a {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 2.5px;
  color: var(--bone);
  text-shadow: 0 1px 12px rgba(12, 12, 12, 0.8);
  transition: color 0.2s;
}

.menu a:hover { color: var(--signal); }

/* On the bone and red panels the chrome has to flip or it disappears. */
.on-light .mark,
.on-light .menu a { color: var(--void); }
.on-light .menu a { text-shadow: 0 1px 14px rgba(239, 235, 228, 0.75); }
.on-light .burger span { background: var(--void); }

/* Print grain: the one texture that ties photography to the flat panels. */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 9999;
  opacity: 0.32;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='0.42'/%3E%3C/svg%3E");
}

@media (max-width: 860px) {
  .reel-btn { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .reel { scroll-behavior: auto; }
  .reel-item { transition: none; }
}
