/* ==========================================================================
   The History of AI — horizontal magazine-cutout deck
   base.css : shell, deck mechanics, paper physics, halftone, scrubber
   press.css: the ten art directions
   ========================================================================== */

:root {
  color-scheme: dark;

  --void:        #17161a;
  --void-2:      #1f1e23;
  --void-ink:    #e8e4dc;
  --void-dim:    #8d8880;
  --void-rule:   rgba(232, 228, 220, 0.14);

  --card-w: clamp(290px, 40vw, 560px);
  --gap:    clamp(28px, 5vw, 76px);

  --ui: "Space Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
}

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

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

body {
  margin: 0;
  background: var(--void);
  color: var(--void-ink);
  font-family: var(--ui);
  overflow: hidden;              /* the deck scrolls, not the page */
  overscroll-behavior: none;
}

/* the felt-covered table the clippings are laid out on */
body::before {
  content: "";
  position: fixed; inset: 0; z-index: 0; pointer-events: none;
  background:
    radial-gradient(ellipse 120% 80% at 50% 42%, rgba(255,247,230,0.09), transparent 62%),
    repeating-linear-gradient(48deg, rgba(0,0,0,0.16) 0 2px, transparent 2px 5px);
}

img { max-width: 100%; display: block; }
[hidden] { display: none !important; }

:focus-visible { outline: 2px solid #ffd84d; outline-offset: 3px; }

.vh {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

/* The hidden <svg> that holds the ink-separation filters. Positioned out of
   flow here rather than with a style attribute, which the deployed CSP
   (style-src 'self') would refuse. */
.ink-plates { position: absolute; }

.skip {
  position: absolute; left: -9999px; z-index: 90;
  background: #fff; color: #000; padding: 12px 16px; border-radius: 4px;
  font-family: var(--ui); font-size: 13px;
}
.skip:focus { left: 16px; top: 16px; }

/* ---------- masthead ---------- */

.masthead {
  position: fixed; top: 0; left: 0; right: 0; z-index: 30;
  display: flex; align-items: flex-start; gap: 18px;
  padding: clamp(14px, 2.4vw, 26px) clamp(16px, 3vw, 34px);
  pointer-events: none;
}
.masthead > * { pointer-events: auto; }

.wordmark { margin: 0; line-height: 1; }
.wordmark b {
  display: block; font-family: var(--ui); font-weight: 700;
  font-size: clamp(11px, 1.35vw, 14px); letter-spacing: 0.24em;
  text-transform: uppercase; color: var(--void-ink);
}
.wordmark span {
  display: block; margin-top: 5px;
  font-size: 10.5px; letter-spacing: 0.1em; color: var(--void-dim);
}

.tools { margin-left: auto; display: flex; gap: 7px; flex-wrap: wrap; justify-content: flex-end; }

.tool {
  font-family: var(--ui); font-size: 11px; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--void-dim);
  background: rgba(255,255,255,0.045); border: 1px solid var(--void-rule);
  padding: 7px 11px; border-radius: 2px; cursor: pointer; white-space: nowrap;
  transition: color 0.15s, border-color 0.15s, background 0.15s;
}
.tool:hover { color: var(--void-ink); border-color: rgba(232,228,220,0.4); }
.tool[aria-pressed="true"] { color: #12110f; background: #e8e4dc; border-color: #e8e4dc; }

.counter {
  font-family: var(--ui); font-size: 11px; letter-spacing: 0.1em;
  color: var(--void-dim); align-self: center; white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

/* ---------- the deck ---------- */

.deck {
  position: relative; z-index: 1;
  height: 100%;
  display: flex; align-items: center;
  gap: var(--gap);
  padding-inline: calc(50vw - var(--card-w) / 2);
  padding-block: 0 clamp(96px, 13vh, 150px);
  overflow-x: auto; overflow-y: hidden;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.deck::-webkit-scrollbar { display: none; }

.cut {
  flex: 0 0 var(--card-w);
  scroll-snap-align: center;
  scroll-snap-stop: always;
  display: flex; align-items: center; justify-content: center;
  /* drop-shadow (not box-shadow) so the shade follows the torn clip-path;
     the values themselves are per-card, in paper.css */
  transition: filter 0.45s ease;
}

.paper {
  position: relative;
  width: 100%;
  background: var(--paper, #f3efe4);
  color: var(--ink, #14120e);
  transform: rotate(var(--tilt, 0deg)) scale(0.8);
  transform-origin: 50% 55%;
  transition: transform 0.55s cubic-bezier(0.22, 1, 0.36, 1), opacity 0.45s ease;
  opacity: 0.44;
  clip-path: var(--tear, none);
  box-shadow:
    inset 0 0 0 1.5px rgba(255, 255, 255, 0.34),
    inset 0 0 9px rgba(255, 255, 255, 0.22),
    inset 0 0 22px rgba(120, 96, 58, 0.09);
  padding: var(--pad, 26px);
  will-change: transform;
}

/* paper surface, creases, ageing and wear all live in paper.css */

.cut.is-focus .paper { transform: rotate(var(--tilt, 0deg)) scale(1); opacity: 1; }
.cut:not(.is-focus) .paper { filter: saturate(0.42) brightness(0.72) contrast(0.95); }

@media (prefers-reduced-motion: reduce) {
  .paper, .cut { transition: none; }
  .deck { scroll-behavior: auto; }
}

/* ---------- cutout furniture ---------- */

.tape {
  position: absolute; z-index: 4; pointer-events: none;
  width: 92px; height: 27px;
  background: linear-gradient(105deg,
    rgba(255,246,196,0.44), rgba(247,236,178,0.60) 46%, rgba(255,250,214,0.38));
  box-shadow: 0 1px 2px rgba(0,0,0,0.26);
  mix-blend-mode: multiply;
}
.tape::before, .tape::after {
  content: ""; position: absolute; top: 0; bottom: 0; width: 4px;
  background: repeating-linear-gradient(90deg, rgba(0,0,0,0.07) 0 1px, transparent 1px 2px);
}
.tape::before { left: 0; } .tape::after { right: 0; }
.tape-tl { top: -12px; left: -18px; transform: rotate(-26deg); }
.tape-br { bottom: -11px; right: -20px; transform: rotate(-19deg); }

.staple {
  position: absolute; z-index: 4; width: 17px; height: 8px;
  border: 1.8px solid rgba(60,58,54,0.62); border-bottom-color: transparent;
  box-shadow: 0 1px 1px rgba(0,0,0,0.3);
  top: 14px; right: 20px; transform: rotate(14deg);
}

/* ---------- plate & halftone ---------- */
/* The dot grid blends with the photo, then a hard contrast crush on the
   wrapper turns per-dot BRIGHTNESS into per-dot SIZE — a real halftone,
   not a dot grid laid on top. */

.plate-wrap { margin: 0; }

.plate {
  position: relative; overflow: hidden; isolation: isolate;
  background: var(--plate-bg, #fbf8f0);
  width: 100%;
  aspect-ratio: var(--plate-ratio, 4 / 3);
  max-height: min(44vh, 420px);
  filter: var(--plate-base, grayscale(1)) contrast(var(--crush, 13))
          brightness(var(--plate-bright, 1.02)) var(--ink-sep, opacity(1));
  margin-bottom: var(--plate-gap, 16px);
}
.plate > img, .plate > svg {
  width: 100%; height: 100%; object-fit: var(--plate-fit, cover);
  filter: grayscale(1) blur(var(--soften, 0.9px)) contrast(1.12) brightness(1.06);
}
.plate::after {
  content: ""; position: absolute; inset: -12%;
  background-image: radial-gradient(circle at 50% 50%, #000 0%, #fff 74%);
  background-size: var(--dot, 7px) var(--dot, 7px);
  transform: rotate(var(--screen-angle, 22deg));
  mix-blend-mode: hard-light;
  pointer-events: none;
}

/* Mark plates are screened at ONE ruling, --mark-dot, shared by the panel and
   the mark. Line art does need a finer ruling than a photograph (at the press's
   photo ruling, up to 11px, a logo's strokes are thinner than a single dot and
   dissolve), but that finer ruling has to apply to the whole plate: screening
   the panel coarse and the mark fine reads as two unrelated treatments in one
   frame.

   The two layers reach that ruling by different means, because they are
   different kinds of artwork:
     - the panel is continuous tone, so it is screened the way every photograph
       here is — dots blended over it, then a contrast crush that turns each
       dot's brightness into its size;
     - the mark is solid ink with no tone to convert, so a crush would only
       flatten it back to a silhouette. It is screened by masking the same dot
       grid through it, which is what a line screen physically does to solid
       ink, and which leaves the artwork's own transparency intact.
   Same pitch, so they read as one screen. */
.plate.is-mark {
  display: grid; place-items: center;
  filter: none;                      /* each layer carries its own screen */
  background: var(--mark-paper, #efebe3);
  isolation: isolate;
}
.plate.is-mark::after { content: none; }

.mark-bed {
  position: absolute; inset: 0; z-index: 1; overflow: hidden; isolation: isolate;
  background: var(--mark-ground, radial-gradient(circle at 38% 30%, #ffffff, #ded9d0 56%, #b3aea5));
  filter: grayscale(1) contrast(var(--bed-crush, 9)) var(--ink-sep, opacity(1));
  opacity: var(--bed-strength, 0.5);
}
.mark-bed::after {
  content: ""; position: absolute; inset: -14%;
  background-image: radial-gradient(circle at 50% 50%, #000 0%, #fff 74%);
  background-size: var(--mark-dot, 2.6px) var(--mark-dot, 2.6px);
  transform: rotate(var(--screen-angle, 22deg));
  mix-blend-mode: hard-light;
}

.plate.is-mark > .mark-ink {
  position: relative; z-index: 2;
  width: var(--mark-size, 76%); height: var(--mark-size, 76%);
  object-fit: contain;
  /* brightness(0) flattens any artwork — black, mid-tone or full colour — to a
     solid silhouette with alpha intact, so the ink separation always gets a
     known input; invert() then lifts it to the printing tone. */
  filter: var(--mark-filter,
          grayscale(1) brightness(0) invert(var(--mark-density, 0.08)))
          var(--ink-sep, opacity(1));
  /* the SAME ruling as the panel, so both read as one screen */
  -webkit-mask-image: radial-gradient(circle at 50% 50%,
          #000 0 var(--mark-fill, 42%), transparent calc(var(--mark-fill, 42%) + 9%));
  -webkit-mask-size: var(--mark-dot, 2.6px) var(--mark-dot, 2.6px);
  mask-image: radial-gradient(circle at 50% 50%,
          #000 0 var(--mark-fill, 42%), transparent calc(var(--mark-fill, 42%) + 9%));
  mask-size: var(--mark-dot, 2.6px) var(--mark-dot, 2.6px);
}

.plate-cap {
  font-family: var(--font-cap, var(--font-body));
  font-size: var(--cap-size, 10.5px);
  line-height: 1.35; letter-spacing: var(--cap-track, 0.04em);
  color: var(--ink-2, #4a453c);
  margin: calc(var(--plate-gap, 16px) * -1 + 7px) 0 var(--plate-gap, 16px);
  text-transform: var(--cap-case, none);
}

/* ---------- copy ---------- */

.kicker {
  font-family: var(--font-kicker, var(--font-body));
  font-size: var(--kicker-size, 11px);
  letter-spacing: var(--kicker-track, 0.2em);
  text-transform: uppercase; font-weight: 700;
  color: var(--accent, #b4331d);
  margin: 0 0 var(--kicker-gap, 10px);
  display: flex; align-items: baseline; gap: 9px;
}
.kicker .lens {
  margin-left: auto; font-weight: 400; letter-spacing: 0.1em;
  color: var(--ink-2, #4a453c); font-size: 0.86em;
}

.head {
  font-family: var(--font-head);
  font-size: var(--head-size, clamp(25px, 3.4vw, 42px));
  line-height: var(--head-leading, 0.98);
  letter-spacing: var(--head-track, -0.015em);
  font-weight: var(--head-weight, 700);
  text-transform: var(--head-case, none);
  color: var(--head-ink, var(--ink));
  margin: 0 0 var(--head-gap, 10px);
  text-wrap: balance;
}
.head a { color: inherit; text-decoration: none; }
.head a:hover { text-decoration: underline; text-underline-offset: 4px; }

.byline {
  font-family: var(--font-byline, var(--font-body));
  font-size: var(--byline-size, 11.5px);
  letter-spacing: var(--byline-track, 0.06em);
  text-transform: var(--byline-case, uppercase);
  color: var(--ink-2, #4a453c);
  margin: 0 0 var(--byline-gap, 13px);
  padding-bottom: var(--byline-pad, 0);
  border-bottom: var(--byline-rule, 0);
}

.body {
  font-family: var(--font-body);
  font-size: var(--body-size, 13.5px);
  line-height: var(--body-leading, 1.52);
  letter-spacing: var(--body-track, 0);
  color: var(--ink, #14120e);
  margin: 0;
  columns: var(--cols, 1);
  column-gap: 20px;
  column-rule: var(--col-rule, none);
  hyphens: auto;
}
.body::first-letter { /* overridden per press */ }

.source {
  margin: var(--source-gap, 14px) 0 0;
  padding-right: 0;
  font-family: var(--font-byline, var(--font-body));
  font-size: var(--source-size, 10.5px);
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.source a {
  display: inline-flex; align-items: baseline; gap: 7px;
  flex-wrap: wrap;   /* stack the label above the host rather than break mid-token */
  color: var(--accent, #b4331d);
  text-decoration: none;
  border-bottom: 1px solid color-mix(in srgb, var(--accent, #b4331d) 40%, transparent);
  padding-bottom: 2px;
  transition: border-color 0.15s ease, opacity 0.15s ease;
}
.source a:hover { border-bottom-color: currentColor; }
.source a:focus-visible { outline: 2px solid currentColor; outline-offset: 3px; }
.src-host {
  font-weight: 700; letter-spacing: 0.04em; text-transform: none;
  color: var(--ink-2, #4a453c);
}
.src-arrow { font-size: 1.05em; line-height: 1; }

/* reserve room for the stamp on turning-point cards */
.paper:has(.stamp) .source { padding-right: 128px; }
@supports not selector(:has(*)) {
  .source { padding-right: 128px; }
}

.stamp {
  position: absolute; z-index: 3; pointer-events: none;
  right: var(--stamp-x, 16px); bottom: var(--stamp-y, 14px);
  font-family: var(--ui); font-size: 9.5px; font-weight: 700;
  letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--accent, #b4331d);
  border: 1.6px solid currentColor; padding: 4px 7px;
  transform: rotate(-8deg); opacity: 0.62; border-radius: 2px;
}

/* ---------- the scrubber: the old density rail, laid on its side ---------- */

.scrub {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 25;
  height: clamp(74px, 11vh, 106px);
  padding: 0 clamp(16px, 3vw, 34px) 12px;
  background: linear-gradient(to top, var(--void) 62%, transparent);
  display: flex; flex-direction: column; justify-content: flex-end;
}
.scrub svg { display: block; width: 100%; height: 52px; overflow: visible; }
.scrub { cursor: pointer; }
.scrub .axis  { stroke: var(--void-rule); stroke-width: 1; }
.scrub .dec   { stroke: var(--void-rule); stroke-width: 1; }
.scrub .decl  { fill: var(--void-dim); font-family: var(--ui); font-size: 9px; letter-spacing: 0.08em; }
.scrub .band  { fill: rgba(232,228,220,0.06); }
.scrub .tick  { stroke: var(--void-dim); stroke-width: 2; stroke-linecap: round; opacity: 0.5;
                transition: opacity 0.2s, stroke 0.2s; }
.scrub .tick.is-dim  { opacity: 0.13; }
.scrub .tick.is-here { stroke: #ffd84d; opacity: 1; stroke-width: 3; }
.scrub-note {
  font-family: var(--ui); font-size: 9.5px; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--void-dim); margin: 0 0 6px;
  display: flex; justify-content: space-between; gap: 16px;
}
/* The way back to the archive this deck is filed in. Same small label voice
   as the note beside it, underlined so it reads as a link. */
.scrub-home { color: var(--void-dim); text-decoration: underline; text-underline-offset: 2px; white-space: nowrap; }
.scrub-home:hover, .scrub-home:focus-visible { color: var(--void-ink); }

/* ---------- arrows ---------- */

.arrow {
  position: fixed; top: 50%; z-index: 28; transform: translateY(-60%);
  width: 46px; height: 46px; border-radius: 50%;
  background: rgba(23,22,26,0.72); border: 1px solid var(--void-rule);
  color: var(--void-ink); cursor: pointer;
  display: grid; place-items: center; font-size: 17px;
  backdrop-filter: blur(6px);
  transition: background 0.15s, border-color 0.15s, opacity 0.2s;
}
.arrow:hover { background: rgba(40,38,44,0.92); border-color: rgba(232,228,220,0.42); }
.arrow[disabled] { opacity: 0.22; cursor: default; }
.arrow-prev { left: clamp(8px, 1.6vw, 20px); }
.arrow-next { right: clamp(8px, 1.6vw, 20px); }

/* ---------- index (grid overlay) ---------- */

.index {
  position: fixed; inset: 0; z-index: 40;
  background: rgba(12,11,14,0.96); backdrop-filter: blur(8px);
  overflow-y: auto; padding: clamp(70px, 9vh, 104px) clamp(16px, 4vw, 48px) 60px;
}
.index-grid {
  display: grid; gap: 10px; max-width: 1180px; margin: 0 auto;
  grid-template-columns: repeat(auto-fill, minmax(196px, 1fr));
}
.index-item {
  text-align: left; cursor: pointer; padding: 13px 14px;
  background: rgba(255,255,255,0.035); border: 1px solid var(--void-rule);
  color: var(--void-ink); font-family: var(--ui); border-radius: 2px;
  transition: background 0.14s, border-color 0.14s;
}
.index-item:hover { background: rgba(255,255,255,0.09); border-color: rgba(232,228,220,0.4); }
.index-item .y { display: block; font-size: 10px; letter-spacing: 0.14em; color: var(--void-dim); margin-bottom: 5px; }
.index-item .t { display: block; font-size: 12.5px; line-height: 1.32; }
.index-close { position: fixed; top: 20px; right: 22px; z-index: 41; }

/* ---------- loading / error ---------- */

.boot {
  position: fixed; inset: 0; display: grid; place-items: center; z-index: 50;
  background: var(--void); color: var(--void-dim);
  font-family: var(--ui); font-size: 12px; letter-spacing: 0.18em; text-transform: uppercase;
}
.boot-err { max-width: 46ch; text-align: left; line-height: 1.7; text-transform: none; letter-spacing: 0; }
.boot-err code { color: var(--void-ink); background: rgba(255,255,255,0.08); padding: 2px 6px; }

/* ---------- narrow ---------- */

/* short viewports: the copy wraps longer, so the picture yields height */
@media (max-height: 800px) {
  .plate { max-height: min(36vh, 420px); }
}
/* short AND narrow is the worst case — the copy wraps hardest there */
@media (max-height: 800px) and (max-width: 420px) {
  .plate { max-height: min(29vh, 420px); }
  .body  { font-size: 11.5px; line-height: 1.5; }
}

@media (max-width: 620px) {
  :root { --card-w: min(86vw, 400px); --gap: 26px; }
  .stamp { font-size: 8.5px; padding: 3px 6px; letter-spacing: 0.12em; }
  .paper:has(.stamp) .source { padding-right: 96px; }
  .source { font-size: 10px; }
  .masthead { gap: 10px; padding: 12px 14px; }
  .wordmark span { display: none; }
  .arrow { display: none; }
  .counter { display: none; }
  .scrub { height: 62px; }
  .scrub svg { height: 34px; }
  .scrub-note { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-size: 8.5px; }
  .index { padding-top: 76px; }
  .index-grid { grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); }
}
