/* Everyone's a 4.8: the shared base for both pages.

   Color: paper, ink and gold, and nothing else. Ink shows hierarchy by its strength: full for
   headlines and big numbers, 74% for body text and 64% for labels. Labels would read lighter at
   45%, but that is 2.8:1 on the paper, under the 4.5:1 small text needs; 64% holds 4.7:1 even
   on the grain's darkest speck. Gold is only ever a star.
   Type: the serif, large, for headlines and big numbers only; the mono, small and uppercase,
   for labels and counters; body text in the serif at reading size, short.
   Motion: one easing for everything. Anything that moves takes 500ms, hover and press changes
   200ms, text fades 600ms. js/motion.js gives scripts the same curve. */

@font-face {
  font-family: "Newsreader";
  src: url("../fonts/Newsreader-normal-300-700.woff2") format("woff2");
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
}
@font-face {
  font-family: "Newsreader";
  src: url("../fonts/Newsreader-italic-300-700.woff2") format("woff2");
  font-style: italic;
  font-weight: 300 700;
  font-display: swap;
}
@font-face {
  font-family: "IBM Plex Mono";
  src: url("../fonts/IBMPlexMono-normal-400.woff2") format("woff2");
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: "IBM Plex Mono";
  src: url("../fonts/IBMPlexMono-normal-500.woff2") format("woff2");
  font-weight: 500;
  font-display: swap;
}
/* Until Newsreader loads, the page uses Georgia resized to Newsreader's widths and given
   Newsreader's ascent (0.735) and descent (0.265), so lines break in nearly the same
   places when the font swaps in. Newsreader is narrower than Georgia at text sizes and
   wider at display sizes, so each weight range gets its own size. */
@font-face {
  font-family: "Newsreader Fallback";
  src: local("Georgia");
  font-weight: 300 450;
  size-adjust: 91.8%;
  ascent-override: 80.1%;
  descent-override: 28.9%;
  line-gap-override: 0%;
}
@font-face {
  font-family: "Newsreader Fallback";
  src: local("Georgia");
  font-weight: 451 550;
  size-adjust: 101%;
  ascent-override: 72.8%;
  descent-override: 26.2%;
  line-gap-override: 0%;
}
@font-face {
  font-family: "Newsreader Fallback";
  src: local("Georgia Bold"), local("Georgia-Bold");
  font-weight: 551 700;
  size-adjust: 83%;
  ascent-override: 88.6%;
  descent-override: 31.9%;
  line-gap-override: 0%;
}

:root {
  --paper: #f3eee3;
  --ink-rgb: 29 26 22;
  --ink: rgb(var(--ink-rgb));
  --ink-body: rgb(var(--ink-rgb) / 0.74);
  --ink-label: rgb(var(--ink-rgb) / 0.64);
  /* Lines and fills, all ink: hairlines, stronger rules and a faint wash for bands. */
  --ink-rule: rgb(var(--ink-rgb) / 0.16);
  --ink-rule-strong: rgb(var(--ink-rgb) / 0.34);
  --ink-wash: rgb(var(--ink-rgb) / 0.06);
  --ink-star: rgb(var(--ink-rgb) / 0.1); /* an empty star */
  --gold: #dca320;
  --gold-edge: #936f1c; /* gold darkened with ink (62 to 38), the star's outline */
  --gold-light: rgb(220 163 32 / 0.42); /* gold at 42% on the paper */
  --serif: "Newsreader", "Newsreader Fallback", "Iowan Old Style", "Palatino Linotype", Georgia, serif;
  --mono: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  --ease: cubic-bezier(0.16, 1, 0.3, 1);
  --move: 500ms;
  --press: 200ms;
  --fade: 600ms;
  --gutter: 20px;
  color-scheme: light;
}
@media (min-width: 720px) {
  :root {
    --gutter: 32px;
  }
}
@media (min-width: 1200px) {
  :root {
    --gutter: clamp(40px, 4vw, 64px);
  }
}

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

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

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--serif);
  font-size: 1.0625rem;
  line-height: 1.5;
  font-optical-sizing: auto;
  font-kerning: normal;
  text-rendering: optimizeLegibility;
}

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

p {
  margin: 0;
}
p,
li,
figcaption {
  text-wrap: pretty;
}
strong {
  font-weight: 600;
}

a {
  color: inherit;
  text-decoration-line: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
  text-decoration-color: var(--ink-rule-strong);
  transition: text-decoration-color var(--press) var(--ease);
}
/* Hover only where a pointer can hover; on touch screens a tap would leave it stuck on. */
@media (hover: hover) and (pointer: fine) {
  a:hover {
    text-decoration-color: currentColor;
  }
}

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

.visually-hidden {
  position: absolute !important;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* The mono role: labels and counters, small and uppercase, at label strength. */
.label {
  font-family: var(--mono);
  font-size: 0.75rem;
  font-weight: 400;
  line-height: 1.5;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-label);
}
.label a {
  color: inherit;
}

/* Stars, used everywhere. */
.star-fill {
  fill: var(--gold);
}
.star-empty {
  fill: var(--ink-star);
}
.star-edge {
  fill: none;
  stroke: var(--gold-edge);
  stroke-width: 1;
  stroke-linejoin: round;
}

/* Buttons: labels you can press, in the mono role. */
.btn {
  appearance: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 44px;
  padding: 10px 18px;
  font-family: var(--mono);
  font-size: 0.75rem;
  font-weight: 500;
  line-height: 1.2;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--paper);
  background: var(--ink);
  border: 1px solid var(--ink);
  border-radius: 0;
  cursor: pointer;
  touch-action: manipulation;
  transition:
    transform var(--press) var(--ease),
    background-color var(--press) var(--ease),
    border-color var(--press) var(--ease);
}
.btn:not([disabled]):active {
  transform: scale(0.97);
}
@media (hover: hover) and (pointer: fine) {
  .btn:hover {
    background: rgb(var(--ink-rgb) / 0.84);
  }
}
.btn[disabled] {
  opacity: 0.45;
  cursor: default;
}
.btn-quiet {
  color: var(--ink);
  background: transparent;
  border-color: var(--ink-rule-strong);
}
@media (hover: hover) and (pointer: fine) {
  .btn-quiet:hover {
    background: var(--ink-wash);
    border-color: var(--ink);
  }
}
/* A button that reads like a link inside a label line. */
.text-button {
  appearance: none;
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  color: inherit;
  text-decoration-line: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
  text-decoration-color: var(--ink-rule-strong);
  cursor: pointer;
  touch-action: manipulation;
  transition: text-decoration-color var(--press) var(--ease);
}
@media (hover: hover) and (pointer: fine) {
  .text-button:hover {
    text-decoration-color: currentColor;
  }
}
/* A text button that is also a label keeps the label's mono voice. */
.text-button.label {
  font-family: var(--mono);
  font-size: 0.75rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

/* A line whose words change by crossfading in place (js/motion.js setLine). */
.line {
  display: grid;
}
.line > .line-copy {
  grid-area: 1 / 1;
  opacity: 0;
  transition: opacity var(--fade) var(--ease);
}
.line > .line-copy.is-shown {
  opacity: 1;
}

/* The paper's grain: a speckle of ink over everything, its darkest specks at about 5%, that
   shifts a few times a second. It is one small tile, redrawn in place, so it costs no large
   layer. */
.grain {
  position: fixed;
  inset: 0;
  z-index: 100;
  pointer-events: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' seed='7' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 .114 0 0 0 0 .102 0 0 0 0 .086 1 0 0 0 0'/%3E%3CfeComponentTransfer%3E%3CfeFuncA type='table' tableValues='0 0 0 .02 .06 .1 .14'/%3E%3C/feComponentTransfer%3E%3C/filter%3E%3Crect width='220' height='220' filter='url(%23g)'/%3E%3C/svg%3E");
  background-size: 220px 220px;
  animation: grain 1.1s steps(1, end) infinite;
}
html.is-tuning .grain {
  animation-play-state: paused;
}
@keyframes grain {
  0%,
  100% {
    background-position: 0 0;
  }
  20% {
    background-position: -63px 41px;
  }
  40% {
    background-position: 37px -89px;
  }
  60% {
    background-position: -91px -23px;
  }
  80% {
    background-position: 71px 83px;
  }
}

/* Readers who ask for more contrast get firmer lines and labels. */
@media (prefers-contrast: more) {
  :root {
    --ink-rule: rgb(var(--ink-rgb) / 0.5);
    --ink-rule-strong: rgb(var(--ink-rgb) / 0.7);
    --ink-label: rgb(var(--ink-rgb) / 0.8);
    --ink-body: rgb(var(--ink-rgb) / 0.86);
  }
  .grain {
    display: none;
  }
}
@media (forced-colors: active) {
  .grain {
    display: none;
  }
}

/* Reduced motion: nothing moves. Fades stay, because they still show that something changed,
   and the grain holds still. */
@media (prefers-reduced-motion: reduce) {
  .grain {
    animation: none;
  }
  .btn,
  .btn:not([disabled]):active {
    transform: none;
  }
}
