/* pages/book.css — the appointment slip: a ledger-framed Calendly embed with a reserved
   min-height (CLS 0), a drawn-rule paper skeleton while the script loads, and a static
   fallback that works with no JavaScript. */

.book__intro { max-width: 56ch; }
.book__lead {
  margin-top: var(--s-4);
  font-family: var(--font-serif);
  font-size: var(--t-lead);
  color: var(--ink-2);
}

/* Appointment slip */
.slip { margin-top: var(--s-7); background: var(--paper-raised); box-shadow: inset 0 0 0 1px var(--rule-ink); }
.slip__header {
  padding: 16px var(--s-5) 14px;
  border-bottom: 1px solid var(--ink);
  box-shadow: 0 3px 0 -1px var(--rule-strong); /* the second rule of the double-rule */
}
.slip__header .meta { color: var(--ink); }
.slip__body { position: relative; padding: var(--s-4); }

/* Reserve the widget height so nothing shifts when Calendly paints (CLS 0).
   The mount needs an explicit `height`, not just `min-height`: Calendly's widget.css sizes its
   iframe with `height: 100%`, and a percentage height only resolves against a parent with a
   resolved `height`. Against `min-height` alone the parent is `height: auto`, the 100% computes
   to auto, and the iframe collapses to the 150px HTML default — a blank box behind a spinner.
   Calendly's own embed snippet sets an inline `height` for exactly this reason. */
.calendly-frame { position: relative; min-height: 700px; }
.calendly-inline-widget { height: 700px; min-height: 700px; }

/* Paper skeleton with drawn ledger rules, shown until the embed loads */
.slip__skeleton {
  position: absolute;
  inset: var(--s-4);
  display: grid;
  align-content: start;
  gap: 18px;
  padding: var(--s-5);
  background:
    repeating-linear-gradient(to bottom, transparent 0 43px, var(--rule) 43px 44px);
  pointer-events: none;
}
.slip__skeleton .meta { color: var(--ink-3); }
.slip.is-loaded .slip__skeleton { display: none; }

/* Load failed / timed out (calendly.js: script onerror or an ~8s watchdog): drop the eternal
   "Loading the calendar…" skeleton, collapse the reserved 700px void, and promote the static
   fallback link from fine-print to a boxed, inked call to action so the call can still be booked. */
.slip.is-failed .slip__skeleton { display: none; }
.slip.is-failed .calendly-frame { min-height: 0; }
.slip.is-failed .calendly-inline-widget { display: none; height: 0; min-height: 0; }

.slip__fallback {
  margin-top: var(--s-4);
  font-family: var(--font-mono);
  font-size: var(--t-meta);
  letter-spacing: 0.03em;
  color: var(--ink-3);
}
.slip__fallback a { color: var(--green); }

/* With JS the widget is expected to paint, so the fine-print fallback stays hidden until it's
   actually needed — no permanent "Calendar not loading?" line under a working calendar. It's
   revealed on load failure (.is-failed, promoted to the boxed CTA below) or, belt-and-braces,
   after a soft ~10s watchdog if the widget still hasn't loaded (.is-fallback-shown, left as quiet
   fine-print). No-JS users never get the .js class, so the fallback is always there for them. */
.js .slip__fallback { display: none; }
.slip.is-failed .slip__fallback,
.slip.is-fallback-shown .slip__fallback { display: block; }

.slip.is-failed .slip__fallback {
  margin-top: 0;
  padding: var(--s-4) var(--s-5);
  background: var(--paper-sunk);
  box-shadow: inset 0 0 0 1px var(--rule-ink);
  font-size: var(--t-body);
  line-height: 1.5;
  color: var(--ink);
}

@media (max-width: 640px) {
  .book-list__item { grid-template-columns: auto 1fr; }
}
