/*
 * Reset, self-hosted type, page frame, and the primitives every screen
 * shares (headings, links, rules, forms, focus). Component classes live in
 * components.css; screen-specific rules in catalog.css / screens.css.
 *
 * The three families are self-hosted (latin subset, woff2) rather than
 * loaded from a font CDN: this is an installable, offline-capable PWA, and
 * a webfont that only resolves online would leave the app in its fallback
 * face exactly when it's least able to recover.
 */

@font-face {
  font-family: "Fraunces";
  src: url("/assets/fraunces-variable-latin-397b623a.woff2") format("woff2-variations");
  font-weight: 300 700;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Inter";
  src: url("/assets/inter-variable-latin-1f021a24.woff2") format("woff2-variations");
  font-weight: 300 700;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "IBM Plex Mono";
  src: url("/assets/plex-mono-400-latin-d803141a.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "IBM Plex Mono";
  src: url("/assets/plex-mono-500-latin-3f7bbac1.woff2") format("woff2");
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}

/* --------------------------------------------------------------------
   Reset
   -------------------------------------------------------------------- */

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

* {
  margin: 0;
}

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

body {
  min-height: 100dvh;
  background-color: var(--surface);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--text-md);
  font-weight: 400;
  line-height: var(--leading-normal);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  font-variant-numeric: tabular-nums;
}

/* A faint paper grain over the whole page. Generated inline rather than
   shipped as an image so it costs nothing to download and tints itself
   with the current surface colour underneath. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: 0.4;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.82' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)' opacity='0.28'/%3E%3C/svg%3E");
  mix-blend-mode: multiply;
}

/* Multiply darkens the grain against paper; on the dark palette it would
   erase it, so it switches to overlay there. */
:root[data-theme="dark"] body::before {
  mix-blend-mode: overlay;
  opacity: 0.22;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) body::before {
    mix-blend-mode: overlay;
    opacity: 0.22;
  }
}

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

/* <turbo-frame> is an unknown element, so it defaults to inline. */
turbo-frame {
  display: block;
}

/* Component classes here set `display` explicitly, which outranks the
   user-agent's `[hidden] { display: none }`. Restate it so toggling the
   attribute from JS actually hides things. */
[hidden] {
  display: none !important;
}

input,
button,
textarea,
select {
  font: inherit;
  color: inherit;
}

ul,
ol {
  list-style: none;
  padding: 0;
}

/* --------------------------------------------------------------------
   Type
   -------------------------------------------------------------------- */

h1,
h2,
h3,
h4 {
  font-family: var(--font-display);
  font-weight: 600;
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
  color: var(--ink-strong);
  text-wrap: balance;
}

h1 { font-size: var(--text-2xl); }
h2 { font-size: var(--text-xl); }
h3 { font-size: var(--text-lg); }
h4 { font-size: var(--text-md); }

p { text-wrap: pretty; }

a {
  color: var(--ember);
  text-decoration-color: color-mix(in srgb, var(--ember) 38%, transparent);
  text-underline-offset: 0.18em;
  text-decoration-thickness: from-font;
  transition: color var(--dur-fast) var(--ease-out);
}

a:hover {
  color: var(--ember-strong);
  text-decoration-color: currentColor;
}

strong { font-weight: 600; }

hr {
  border: none;
  border-top: 1px solid var(--hairline);
  margin: var(--space-5) 0;
}

/* The house "catalog stamp": ISBNs, grades, counts, timestamps. */
.meta {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 400;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--ink-muted);
}

.meta--plain {
  text-transform: none;
  letter-spacing: 0;
}

.lede {
  font-size: var(--text-lg);
  line-height: var(--leading-snug);
  color: var(--ink-muted);
  max-width: var(--measure);
  text-wrap: pretty;
}

.prose {
  max-width: var(--measure);
  color: var(--ink-muted);
}

.prose p + p { margin-top: var(--space-3); }

/* --------------------------------------------------------------------
   Page frame
   -------------------------------------------------------------------- */

.page {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: var(--page-max);
  margin-inline: auto;
  padding: var(--space-6) var(--page-gutter) var(--space-8);
}

.page--narrow { max-width: 54rem; }
.page--slim { max-width: 40rem; }

.stack > * + * { margin-top: var(--space-4); }
.stack-sm > * + * { margin-top: var(--space-2); }
.stack-lg > * + * { margin-top: var(--space-6); }

.row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
}

.row--between { justify-content: space-between; }
.row--tight { gap: var(--space-2); }
.push { margin-left: auto; }

/* --------------------------------------------------------------------
   Focus & accessibility
   -------------------------------------------------------------------- */

:focus-visible {
  outline: 2px solid var(--ember);
  outline-offset: 3px;
  border-radius: var(--radius-xs);
}

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

.skip-link {
  position: fixed;
  top: var(--space-3);
  left: var(--space-3);
  z-index: 200;
  padding: var(--space-2) var(--space-4);
  background: var(--ember);
  color: var(--ember-ink);
  border-radius: var(--radius-pill);
  font-size: var(--text-sm);
  font-weight: 600;
  text-decoration: none;
  transform: translateY(calc(-100% - var(--space-5)));
  transition: transform var(--dur-base) var(--ease-spring);
}

.skip-link:focus-visible {
  transform: translateY(0);
  color: var(--ember-ink);
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
}

/* --------------------------------------------------------------------
   Forms
   -------------------------------------------------------------------- */

.field { display: block; }
.field + .field { margin-top: var(--space-4); }

label,
.label {
  display: block;
  margin-bottom: var(--space-1);
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  font-weight: 500;
  letter-spacing: var(--tracking-wider);
  text-transform: uppercase;
  color: var(--ink-muted);
}

.hint {
  margin-top: var(--space-1);
  font-size: var(--text-sm);
  color: var(--ink-subtle);
}

input[type="text"],
input[type="search"],
input[type="email"],
input[type="url"],
input[type="number"],
select,
textarea {
  display: block;
  width: 100%;
  padding: 0.6rem 0.8rem;
  background: var(--surface-raised);
  color: var(--ink);
  border: 1px solid var(--hairline-strong);
  border-radius: var(--radius-sm);
  font-size: var(--text-base);
  box-shadow: inset 0 1px 2px rgba(41, 30, 18, 0.05);
  transition: border-color var(--dur-fast) var(--ease-out),
              box-shadow var(--dur-fast) var(--ease-out);
}

textarea {
  min-height: 7rem;
  line-height: var(--leading-normal);
  resize: vertical;
}

input::placeholder,
textarea::placeholder { color: var(--ink-subtle); }

input:hover,
select:hover,
textarea:hover { border-color: color-mix(in srgb, var(--ink) 34%, transparent); }

input:focus,
select:focus,
textarea:focus {
  outline: none;
  border-color: var(--ember);
  box-shadow: 0 0 0 3px var(--ember-soft);
}

select {
  appearance: none;
  padding-right: 2.4rem;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%236d6152' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 6.5 8 10.5l4-4'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.7rem center;
  background-size: 1rem;
  cursor: pointer;
}

input[type="file"] {
  display: block;
  width: 100%;
  font-size: var(--text-base);
  color: var(--ink-muted);
}

input[type="file"]::file-selector-button {
  margin-right: var(--space-3);
  padding: 0.5rem 0.9rem;
  background: var(--surface-sunken);
  color: var(--ink);
  border: 1px solid var(--hairline-strong);
  border-radius: var(--radius-pill);
  font-size: var(--text-sm);
  font-weight: 600;
  cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease-out);
}

input[type="file"]::file-selector-button:hover { background: var(--ember-soft); }
