/*
  styles.css — the only stylesheet for the D.G. Hall author site.

  Role in the system: all presentation for index.html. Mobile-first: the base
  rules are the phone layout, and the two min-width blocks near the bottom
  enhance for tablet and desktop. Colours, spacing and type scale are declared
  once as custom properties on :root so the palette can be retuned in one place.

  Order: tokens, reset, typography, layout, components, sections, responsive,
  motion and print.
*/

/* ---------------------------------------------------------------- tokens */
:root {
  /* Palette. Deep charcoal, off-white, steel-blue accent. */
  --c-ink:          #16191c;
  --c-ink-soft:     #3b4248;
  --c-ink-faint:    #6b747c;
  --c-paper:        #faf9f7;
  --c-paper-warm:   #f2f0ec;
  --c-rule:         #ddd9d3;
  --c-steel:        #3d5d7d;
  --c-steel-dark:   #2c4760;
  --c-steel-faint:  #e8edf2;

  /* Spacing scale. */
  --sp-1: 0.25rem;
  --sp-2: 0.5rem;
  --sp-3: 0.75rem;
  --sp-4: 1rem;
  --sp-5: 1.5rem;
  --sp-6: 2rem;
  --sp-7: 3rem;
  --sp-8: 4rem;
  --sp-9: 6rem;

  /* Type. System stacks only: nothing is fetched over the network, so there
     is no layout shift and no third-party request. To use a webfont instead,
     see README.md. */
  --f-serif: "Iowan Old Style", "Palatino Linotype", Palatino, Georgia,
             "Times New Roman", serif;
  --f-sans:  -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
             "Helvetica Neue", Arial, sans-serif;

  --measure: 34rem;      /* comfortable reading width */
  --shell:   72rem;      /* max page width */

  --radius: 2px;         /* almost square; corporate rather than friendly */
  --shadow: 0 1px 2px rgba(22, 25, 28, 0.05),
            0 8px 24px rgba(22, 25, 28, 0.06);
  --t-fast: 120ms ease;
  --t-base: 220ms cubic-bezier(0.4, 0, 0.2, 1);
}

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: 5rem;   /* clears the sticky header on anchor jumps */
}

body {
  margin: 0;
  background: var(--c-paper);
  color: var(--c-ink);
  font-family: var(--f-sans);
  font-size: 1rem;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
}

img, svg { display: block; max-width: 100%; height: auto; }
ul { margin: 0; padding: 0; }

/* ------------------------------------------------------------ typography */
h1, h2, h3 {
  font-family: var(--f-serif);
  font-weight: 600;
  line-height: 1.15;
  letter-spacing: -0.015em;
  margin: 0;
  text-wrap: balance;
}

p { margin: 0 0 var(--sp-4); max-width: var(--measure); }
p:last-child { margin-bottom: 0; }

a { color: var(--c-steel); text-decoration-thickness: 1px; text-underline-offset: 2px; }
a:hover { color: var(--c-steel-dark); }

.eyebrow {
  font-family: var(--f-sans);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--c-ink-faint);
  margin: 0 0 var(--sp-3);
}

/* Visible focus everywhere. Never remove this without a replacement. */
:focus-visible {
  outline: 2px solid var(--c-steel);
  outline-offset: 3px;
  border-radius: var(--radius);
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--c-ink);
  color: var(--c-paper);
  padding: var(--sp-3) var(--sp-4);
  z-index: 100;
}
.skip-link:focus { left: 0; }

/* ---------------------------------------------------------------- layout */
.shell {
  width: 100%;
  max-width: var(--shell);
  margin-inline: auto;
  padding-inline: var(--sp-5);
}

.section { padding-block: var(--sp-8); }
.section--alt { background: var(--c-paper-warm); border-block: 1px solid var(--c-rule); }

.section__head { margin-bottom: var(--sp-7); }
.section__title { font-size: clamp(1.75rem, 1.2rem + 2.4vw, 2.75rem); }
.section__lede {
  margin-top: var(--sp-4);
  font-size: 1.0625rem;
  color: var(--c-ink-soft);
}

/* ---------------------------------------------------------------- header */
.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: rgba(250, 249, 247, 0.92);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--c-rule);
}

.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  min-height: 4rem;
}

.wordmark {
  font-family: var(--f-serif);
  font-size: 1.1875rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  color: var(--c-ink);
  text-decoration: none;
}
.wordmark:hover { color: var(--c-steel-dark); }

.nav-toggle {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  background: none;
  border: 1px solid var(--c-rule);
  border-radius: var(--radius);
  padding: var(--sp-2) var(--sp-3);
  font: inherit;
  font-size: 0.875rem;
  color: var(--c-ink);
  cursor: pointer;
}
.nav-toggle__bars { position: relative; width: 16px; height: 2px; background: currentColor; }
.nav-toggle__bars::before,
.nav-toggle__bars::after {
  content: ""; position: absolute; left: 0; width: 16px; height: 2px; background: currentColor;
}
.nav-toggle__bars::before { top: -5px; }
.nav-toggle__bars::after  { top: 5px; }

/* Mobile: the nav is collapsed by default and revealed by the toggle.
   Without JavaScript the [hidden] attribute is never set, so the nav simply
   stays visible — the menu still works. */
.site-nav { display: none; }
.site-nav.is-open { display: block; }

.site-nav.is-open {
  position: absolute;
  left: 0; right: 0; top: 100%;
  background: var(--c-paper);
  border-bottom: 1px solid var(--c-rule);
  box-shadow: var(--shadow);
  padding: var(--sp-4) var(--sp-5);
}
.site-nav ul { list-style: none; display: grid; gap: var(--sp-1); }
.site-nav a {
  display: block;
  padding: var(--sp-3) 0;
  color: var(--c-ink);
  text-decoration: none;
  font-size: 0.9375rem;
  border-bottom: 1px solid var(--c-rule);
}
.site-nav li:last-child a { border-bottom: 0; }
.site-nav a:hover { color: var(--c-steel-dark); }

/* -------------------------------------------------------------- buttons */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: var(--sp-3) var(--sp-5);
  border: 1px solid transparent;
  border-radius: var(--radius);
  font-family: var(--f-sans);
  font-size: 0.9375rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  text-decoration: none;
  cursor: pointer;
  transition: background var(--t-fast), color var(--t-fast),
              border-color var(--t-fast), transform var(--t-fast);
}
.btn--primary { background: var(--c-ink); color: var(--c-paper); }
.btn--primary:hover { background: var(--c-steel-dark); color: #fff; transform: translateY(-1px); }

.btn--ghost { background: transparent; color: var(--c-ink); border-color: var(--c-ink); }
.btn--ghost:hover { background: var(--c-ink); color: var(--c-paper); }

.btn--text {
  padding: 0;
  background: none;
  color: var(--c-steel);
  text-decoration: underline;
  text-underline-offset: 3px;
}
.btn--text:hover { color: var(--c-steel-dark); }

/* Something not yet purchasable. A span, not a link — so it is not focusable,
   not announced as a control, and cannot be activated. */
.is-pending { opacity: 0.55; cursor: default; }
.is-pending:hover { transform: none; background: var(--c-ink); }

/* ------------------------------------------------------------------ hero */
.hero {
  padding-block: var(--sp-8) var(--sp-8);
  border-bottom: 1px solid var(--c-rule);
  background:
    radial-gradient(60rem 28rem at 15% -10%, var(--c-steel-faint), transparent 70%),
    var(--c-paper);
}
.hero__title {
  font-size: clamp(2.75rem, 1.8rem + 7vw, 6rem);
  letter-spacing: -0.03em;
  margin-bottom: var(--sp-4);
}
.hero__subhead {
  font-family: var(--f-serif);
  font-size: clamp(1.1875rem, 1rem + 1.2vw, 1.75rem);
  line-height: 1.35;
  color: var(--c-ink);
  /* Width is tuned so the line breaks at the full stop after "lives."
     rather than inside the sentence. Deliberately NOT text-wrap: balance,
     which forces two even lines and splits "Ordinary / lives." */
  max-width: 36rem;
  margin-bottom: var(--sp-5);
}
.hero__support { color: var(--c-ink-soft); margin-bottom: var(--sp-6); }
.hero__actions { display: flex; flex-wrap: wrap; gap: var(--sp-3); max-width: none; }

/* ----------------------------------------------------------------- books */
/* Each book is one card: a 16:9 banner with the title laid over the empty
   dark left third of the artwork, then the copy beneath.
   --banner-bg is sampled from each image's own left third, so the panel
   matches the art exactly and there is never a white flash while it loads. */

.book {
  background: #fff;
  border: 1px solid var(--c-rule);
  border-radius: var(--radius);
  overflow: hidden;                 /* clips the banner to the card corners */
}
.book--feature { box-shadow: var(--shadow); margin-bottom: var(--sp-7); }
.book--ticket-closed  { --banner-bg: #000b26; }   /* night blue */
.book--dead-domain    { --banner-bg: #0f1c13; }   /* dark green */

.book__banner { position: relative; background: var(--banner-bg, var(--c-ink)); }

.book__banner img {
  display: block;
  width: 100%;
  /* Phone: crop to 3:2 anchored right, so the wagon and the laptop stay in
     frame rather than being reduced to a letterbox sliver. */
  aspect-ratio: 3 / 2;
  object-fit: cover;
  object-position: right;
}

/* Phone: the crop above removes the empty left third, so the title sits below
   the image in normal flow rather than on top of the busy part of the art. */
.book__label { padding: var(--sp-5); color: #fff; }
.book__status {
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.82);
  margin: 0 0 var(--sp-2);
}
.book__title {
  font-size: clamp(1.375rem, 1.1rem + 1.2vw, 2rem);
  margin: 0;
  color: #fff;
}

.book__body { padding: var(--sp-5); }
.book__hook {
  font-family: var(--f-serif);
  font-size: 1.125rem;
  font-style: italic;
  color: var(--c-ink-soft);
  margin-bottom: var(--sp-5);
}
.book__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
  align-items: center;
  max-width: none;
  margin-top: var(--sp-5);          /* clears the genre tags above */
}

/* "For readers of" — a quiet positioning line under the genre tags. */
.book__comp {
  font-family: var(--f-serif);
  font-size: 0.9375rem;
  font-style: italic;
  color: var(--c-ink-soft);
  margin: var(--sp-4) 0 0;
}

.books-grid { display: grid; gap: var(--sp-5); }
.books-grid .book { transition: box-shadow var(--t-base), transform var(--t-base); }
.books-grid .book:hover { box-shadow: var(--shadow); transform: translateY(-2px); }

/* ------------------------------------------------------------------ tags */
.tags {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  margin: var(--sp-4) 0 0;
}
.tags li {
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--c-ink-soft);
  background: var(--c-paper-warm);
  border: 1px solid var(--c-rule);
  border-radius: var(--radius);
  padding: var(--sp-1) var(--sp-2);
}

/* ----------------------------------------------------------------- about */
.about { display: grid; gap: var(--sp-7); }
.about__aside {
  padding: var(--sp-5);
  background: #fff;
  border: 1px solid var(--c-rule);
  border-radius: var(--radius);
  align-self: start;
}
.about__aside-title {
  font-family: var(--f-sans);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--c-ink-faint);
  margin-bottom: var(--sp-4);
}
.facts { margin: 0; display: grid; gap: var(--sp-1); }
.facts dt {
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--c-ink-faint);
  margin-top: var(--sp-3);
}
.facts dt:first-child { margin-top: 0; }
.facts dd { margin: 0; font-size: 0.9375rem; }

/* ---------------------------------------------------------------- themes */
.themes { display: grid; gap: var(--sp-6); }
.theme { padding-top: var(--sp-4); border-top: 2px solid var(--c-ink); }
.theme h3 { font-size: 1.1875rem; margin-bottom: var(--sp-3); }
.theme p { color: var(--c-ink-soft); font-size: 0.9375rem; }

/* --------------------------------------------------------------- contact */
.contact { display: grid; gap: var(--sp-7); }
.contact__direct { color: var(--c-ink-soft); font-size: 0.9375rem; }

.form { display: grid; gap: var(--sp-5); max-width: 32rem; }
.field { display: grid; gap: var(--sp-2); }
.field label { font-size: 0.875rem; font-weight: 600; }

.field input[type="text"],
.field input[type="email"],
.field textarea {
  width: 100%;
  padding: var(--sp-3);
  font: inherit;
  font-size: 1rem;      /* 16px stops iOS zooming the viewport on focus */
  color: var(--c-ink);
  background: #fff;
  border: 1px solid var(--c-ink-faint);
  border-radius: var(--radius);
  transition: border-color var(--t-fast), box-shadow var(--t-fast);
}
.field input:focus, .field textarea:focus {
  border-color: var(--c-steel);
  box-shadow: 0 0 0 3px var(--c-steel-faint);
  outline: none;
}
.field textarea { resize: vertical; min-height: 7rem; }

.field--check { grid-template-columns: auto 1fr; align-items: start; gap: var(--sp-3); }
.field--check input { width: 1.125rem; height: 1.125rem; margin-top: 0.3rem; accent-color: var(--c-steel); }
.field--check label { font-weight: 400; font-size: 0.9375rem; }

.field__error { color: #9b2226; font-size: 0.8125rem; margin: 0; }
.field.has-error input, .field.has-error textarea { border-color: #9b2226; }

.form__status { margin: 0; font-size: 0.9375rem; min-height: 1.5rem; }
.form__status.is-ok   { color: var(--c-steel-dark); font-weight: 600; }
.form__status.is-fail { color: #9b2226; font-weight: 600; }

/* ---------------------------------------------------------------- footer */
.site-footer {
  background: var(--c-ink);
  color: #c9cfd4;
  padding-block: var(--sp-6);
}
.site-footer__inner { display: grid; gap: var(--sp-5); }
.site-footer p { margin: 0; font-size: 0.875rem; max-width: none; }
.site-footer a { color: #e6eaee; text-decoration: none; }
.site-footer a:hover { color: #fff; text-decoration: underline; }
.site-footer__nav ul {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-4);
  font-size: 0.875rem;
}
.site-footer__social a { display: inline-flex; align-items: center; gap: var(--sp-2); }
.site-footer :focus-visible { outline-color: #9fb9d4; }

/* ------------------------------------------------------- tablet and up */
@media (min-width: 48rem) {
  .section { padding-block: var(--sp-9); }
  .hero { padding-block: var(--sp-9); }

  .nav-toggle { display: none; }
  .site-nav { display: block; }
  .site-nav.is-open { position: static; padding: 0; box-shadow: none; border: 0; background: none; }
  .site-nav ul { display: flex; gap: var(--sp-5); }
  .site-nav a { padding: var(--sp-2) 0; border-bottom: 0; }

  /* One secondary card: a 2-column grid would leave half the row empty, so
     it runs full width and the two books stack as a deliberate pair. Restore
     repeat(2, 1fr) here if a third book is ever added back. */
  .books-grid { gap: var(--sp-6); }

  /* Tablet and up: show the whole 16:9 frame uncropped, which brings the empty
     left third back, and lay the title over it. */
  .book__banner img { aspect-ratio: 16 / 9; object-position: center; }

  .book__label {
    position: absolute;
    inset: 0 auto 0 0;
    width: 40%;
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding: var(--sp-5);
    color: #fff;
    /* Insurance: guarantees legible contrast even if the artwork is later
       swapped for something lighter on the left. */
    background: linear-gradient(to right, rgba(0, 0, 0, 0.45), rgba(0, 0, 0, 0));
  }


  .themes { grid-template-columns: repeat(2, 1fr); gap: var(--sp-6) var(--sp-7); }

  .contact { grid-template-columns: 1fr 1fr; gap: var(--sp-8); align-items: start; }

  .site-footer__inner {
    grid-template-columns: 1fr auto;
    align-items: center;
    gap: var(--sp-4) var(--sp-6);
  }
  .site-footer__social { grid-column: 1 / -1; }
}

/* ------------------------------------------------------ desktop and up */
@media (min-width: 64rem) {
  .shell { padding-inline: var(--sp-6); }

  .book--feature .book__label { padding: var(--sp-7); }

  /* A full-width banner leaves the copy stranded in one narrow column, so on
     desktop every card splits: standfirst across the top where there is one,
     prose left, genre and the call to action in their own column on the right.
     Both cards are full width now, so both need it. */
  .book__body {
    padding: var(--sp-7);
    display: grid;
    grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr);
    gap: var(--sp-5) var(--sp-8);
    align-items: start;
  }
  .book__hook { grid-column: 1 / -1; margin-bottom: 0; }
  .book__meta .tags { margin-top: 0; }
  .book__meta .book__actions {
    flex-direction: column;
    align-items: stretch;
  }

  .about { grid-template-columns: minmax(0, 1.618fr) minmax(0, 1fr); gap: var(--sp-8); }
  .themes { grid-template-columns: repeat(4, 1fr); gap: var(--sp-6); }

  .site-footer__inner { grid-template-columns: auto 1fr auto; }
  .site-footer__nav { justify-self: center; }
  .site-footer__social { grid-column: auto; justify-self: end; }
}

/* ----------------------------------------------------------- motion */
/* Sections fade up once, and only when JS has confirmed it can observe them.
   The .js-reveal class is added to <html> by main.js, so with JS off nothing
   is ever hidden. */
.js-reveal .section__head,
.js-reveal .book,
.js-reveal .theme,
.js-reveal .about__text,
.js-reveal .about__aside,
.js-reveal .contact__intro,
.js-reveal .form {
  opacity: 0;
  transform: translateY(12px);
  transition: opacity 500ms ease, transform 500ms cubic-bezier(0.4, 0, 0.2, 1);
}
.js-reveal .is-visible { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
  }
  /* Never leave content stranded at opacity 0 for these users. */
  .js-reveal .section__head,
  .js-reveal .book,
  .js-reveal .theme,
  .js-reveal .about__text,
  .js-reveal .about__aside,
  .js-reveal .contact__intro,
  .js-reveal .form { opacity: 1; transform: none; }
  .books-grid .book:hover, .btn:hover { transform: none; }
}

/* ------------------------------------------------------------- print */
@media print {
  .site-header, .nav-toggle, .site-nav, .form, .hero__actions { display: none; }
  body { background: #fff; color: #000; }
  .section--alt { background: none; }
  a { color: #000; }
}
