:root {
  /* Palette measured from the organiser's design mockups, not eyeballed. */
  --ink: #1f1c1d;
  --ink-soft: #6b6560;
  --muted: #9a938d;
  --line: #e0e0e0;
  --surface: #ffffff;
  --canvas: #f8f8f8;
  --accent: #5c2824;
  --accent-strong: #451c19;
  --danger: #b42318;
  --radius: 8px;
  --shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
  --mono: ui-monospace, "SF Mono", "Cascadia Mono", Menlo, Consolas, monospace;
}

* { box-sizing: border-box; }

html, body { margin: 0; }

body {
  min-height: 100vh;
  background:
    radial-gradient(1100px 600px at 85% -10%, color-mix(in srgb, var(--accent) 12%, transparent), transparent 65%),
    var(--canvas);
  color: var(--ink);
  font-family: "Inter", "Segoe UI", system-ui, -apple-system, sans-serif;
  font-size: 16px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3 { line-height: 1.15; letter-spacing: -0.02em; margin: 0 0 0.5rem; }
h1 { font-size: clamp(1.7rem, 1.2rem + 1.6vw, 2.4rem); }
h2 { font-size: 1.35rem; }
p { margin: 0 0 0.75rem; }
a { color: var(--accent-strong); }

.site-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  max-width: 1120px;
  margin: 0 auto;
  padding: 1.5rem 1.5rem 0.75rem;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 0.65rem;
  color: var(--ink);
  text-decoration: none;
  font-weight: 700;
  letter-spacing: -0.01em;
}

.brand-logo { height: 40px; width: auto; max-width: 170px; display: block; }
.brand-name { font-size: 1.05rem; }
.brand-tagline { margin: 0; color: var(--ink-soft); font-size: 0.9rem; }

/* The booking page leads with the festival logo, so it is much larger there than
   in the shared header (40px) used by receipts, the payment page and the ops desk. */
.page-form .site-header {
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 0.35rem;
  padding-top: 2.25rem;
}
.page-form .brand { flex-direction: column; gap: 0.5rem; }
.page-form .brand-logo { height: 200px; width: auto; max-width: min(420px, 92vw); }
.page-form .brand-name { font-size: 1.45rem; }
.page-form .brand-tagline { font-size: 0.95rem; }

.layout {
  display: grid;
  grid-template-columns: minmax(0, 1.25fr) minmax(0, 0.85fr);
  gap: 1.5rem;
  align-items: start;
  max-width: 1120px;
  margin: 0 auto;
  padding: 1rem 1.5rem 3.5rem;
}

.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: clamp(1.25rem, 1rem + 1vw, 2rem);
}

.eyebrow {
  margin: 0 0 0.35rem;
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--accent-strong);
}

.lede { color: var(--ink-soft); max-width: 56ch; }

.field { display: flex; flex-direction: column; gap: 0.35rem; margin-bottom: 1rem; }

/* Companion names: one required field per pass the lead booker is not using. */
.names-fieldset {
  display: block;
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 1rem 1.1rem 0.4rem;
  margin: 1.2rem 0 1rem;
  background: var(--surface-2, #faf7f2);
}
.names-fieldset legend { font-weight: 700; font-size: 0.9rem; padding-inline: 0.35rem; }
.names-fieldset > .hint { margin-bottom: 0.8rem; }
.names-sub {
  margin: 0.4rem 0 0.6rem;
  font-size: 0.76rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
.names-list { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 0 1rem; }
.name-field { margin-bottom: 0.8rem; }
.name-field label { font-weight: 500; font-size: 0.82rem; }
.field label { font-weight: 600; font-size: 0.9rem; }
.field input, .field select, .field textarea {
  width: 100%;
  padding: 0.7rem 0.85rem;
  font: inherit;
  color: var(--ink);
  background: #fbfcfe;
  border: 1px solid var(--line);
  border-radius: 11px;
  transition: border-color 120ms ease, box-shadow 120ms ease;
}
.field textarea { min-height: 68px; resize: vertical; }
.field input:focus, .field select:focus, .field textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent);
}
.field input[aria-invalid="true"], .field textarea[aria-invalid="true"] { border-color: var(--danger); }

.check {
  display: flex;
  align-items: flex-start;
  gap: 0.55rem;
  margin: 0 0 1rem;
  font-size: 0.9rem;
  cursor: pointer;
}
.check input { margin-top: 0.25rem; accent-color: var(--accent); }
.rate-note {
  margin: -0.4rem 0 1rem;
  font-size: 0.8rem;
  color: var(--ink-soft);
}

.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; }
.req, .optional {
  font-size: 0.68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  padding: 0.1rem 0.4rem;
  border-radius: 999px;
  vertical-align: middle;
}
.req { color: var(--accent-strong); background: color-mix(in srgb, var(--accent) 12%, transparent); }
.optional { color: var(--ink-soft); background: #eef1f6; }
.hint { margin: 0; font-size: 0.78rem; color: var(--ink-soft); }
.field-error, .form-error { margin: 0; font-size: 0.82rem; color: var(--danger); font-weight: 500; }

.total-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  padding: 0.9rem 0;
  margin: 0.25rem 0 1rem;
  border-top: 1px dashed var(--line);
  font-size: 0.95rem;
  color: var(--ink-soft);
}
.total-row strong { font-size: 1.5rem; color: var(--ink); letter-spacing: -0.02em; }

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 0.75rem 1.15rem;
  font: inherit;
  font-weight: 650;
  border-radius: 11px;
  border: 1px solid transparent;
  cursor: pointer;
  text-decoration: none;
  transition: transform 100ms ease, background 120ms ease, border-color 120ms ease;
}
.btn:active { transform: translateY(1px); }
.btn-primary { width: 100%; background: var(--accent); color: #fff; }
.btn-primary:hover { background: var(--accent-strong); }
.btn-primary:disabled { opacity: 0.65; cursor: progress; }
.btn-ghost { background: #fff; border-color: var(--line); color: var(--ink); }
.btn-ghost:hover { border-color: var(--ink-soft); }
/* Cancelling kills a live QR and cannot be undone, so it should not look like
   the harmless ghost buttons beside it. */
.btn-danger { background: #fff; border-color: #b4342a; color: #b4342a; }
.btn-danger:hover { background: #b4342a; border-color: #b4342a; color: #fff; }
/* A control that sits inside a table cell — the rate-code kind selector. */
.inline-set { display: flex; gap: 0.35rem; align-items: center; margin-top: 0.4rem; }
.inline-set select { font-size: 0.82rem; padding: 0.25rem 0.35rem; max-width: 15rem; }
.link-btn { font-size: 0.9rem; font-weight: 600; text-decoration: none; }

.event-card h2 { font-size: 1.5rem; }
.meta-list { display: grid; gap: 0.85rem; margin: 1rem 0 1.25rem; }
.meta-list div { display: grid; gap: 0.1rem; }
.meta-list dt { font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.1em; color: var(--ink-soft); }
.meta-list dd { margin: 0; font-weight: 600; }

.checklist { margin: 0 0 1rem; padding: 0; list-style: none; display: grid; gap: 0.5rem; }
.checklist li { position: relative; padding-left: 1.6rem; font-size: 0.92rem; color: var(--ink-soft); }
.checklist li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.35rem;
  width: 0.95rem;
  height: 0.55rem;
  border-left: 2px solid var(--accent);
  border-bottom: 2px solid var(--accent);
  transform: rotate(-45deg);
}
.fineprint { margin: 0; font-size: 0.78rem; color: var(--ink-soft); border-top: 1px solid var(--line); padding-top: 0.9rem; }

/* ---------- Receipt ---------- */

.receipt-layout {
  max-width: 1120px;
  margin: 0 auto;
  padding: 1rem 1.5rem 3rem;
}

/* Two columns: the ticket is the artifact, the action column is everything the guest
   must DO or KNOW. On a narrow screen it stacks with the action column FIRST — a held
   booking's next step should never be below the fold — which is also why the aside
   comes first in the DOM and is placed on the right only on wide screens. */
.receipt-cols {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 320px);
  gap: 1.75rem;
  align-items: start;
}
.receipt-cols > .rc-side { grid-column: 2; grid-row: 1; }
.receipt-cols > .ticket { grid-column: 1; grid-row: 1; }

.rc-side { display: grid; gap: 1rem; }
.rc-side .gurukul-pay,
.rc-side .retry-pay { margin-top: 0; }
.rc-side .actions { display: grid; gap: 0.5rem; margin: 0; }
.rc-side .actions .btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.45rem;
  width: 100%;
  text-align: center;
  /* The secondary pair is a link, not a call to action — it reads lighter. */
  font-weight: 500;
}
.rc-side .actions .btn .ico { flex: 0 0 auto; }
.rc-side .actions .btn-primary { font-weight: 600; }

@media (max-width: 860px) {
  .receipt-cols { grid-template-columns: 1fr; }
  .receipt-cols > .rc-side,
  .receipt-cols > .ticket { grid-column: 1; grid-row: auto; }
}

/* The panel telling a gurukul guest what to pay and to whom. Deliberately outside
   the ticket card: it is an action for the guest, not part of the pass. */
.gurukul-pay { margin-top: 1.5rem; }
.gurukul-pay h2 { margin: 0 0 0.4rem; font-size: 1.2rem; }
.gurukul-pay .upi-box { margin: 1rem 0; }
.gurukul-pay .btn { margin-top: 0.75rem; }
.gurukul-pay .btn + .btn { margin-left: 0.5rem; }
.gurukul-pay .fineprint { margin: 0.9rem 0 0; }
/* A payment that failed, above the pass for the same reason as the panel above. */
.retry-pay { margin-top: 1.5rem; border-left: 4px solid #b4342a; }
.retry-pay h2 { margin: 0 0 0.4rem; font-size: 1.2rem; color: #912018; }
.retry-pay .btn { margin-top: 0.9rem; }
.retry-pay .fineprint { margin: 0.9rem 0 0; }
.retry-pay + .ticket { margin-top: 1.5rem; }

.ticket {
  position: relative;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 22px;
  box-shadow: var(--shadow);
  padding: clamp(1.4rem, 1rem + 2vw, 2.5rem);
  overflow: hidden;
}

.ticket-badges { display: flex; gap: 0.4rem; flex-wrap: wrap; justify-content: flex-end; }
.badge-name-lock { color: #93370d; background: #fffaeb; }
.name-lock {
  margin: 0 0 1.25rem;
  padding: 0.65rem 0.85rem;
  border: 1px solid #fedf89;
  border-radius: 12px;
  background: #fffaeb;
  color: #93370d;
  font-size: 0.85rem;
}

.badge {
  padding: 0.3rem 0.75rem;
  border-radius: 999px;
  font-size: 0.72rem;
  font-weight: 750;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  /* A long status — a gurukul booking waiting on their confirmation — wraps onto
     a second line rather than stretching a table column into a thin ribbon. */
  white-space: normal;
  line-height: 1.35;
  max-width: 15rem;
  text-align: center;
}
.badge-valid { color: #05603a; background: #d8f5e3; }
.badge-revoked { color: #912018; background: #fee4e2; }
.badge-checked_in { color: #1849a9; background: #dbe8fe; }


.ticket-body {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 200px;
  gap: 1.75rem;
  align-items: start;
  padding-top: 1.25rem;
  border-top: 1px dashed var(--line);
}

/* One row per thing the guest holds or is, in the design's vocabulary: a 40px icon
   tile, the name at 15/600, the detail beneath it at 13px. */
.detail-list { display: grid; gap: 0; column-gap: 14px; grid-template-columns: 1fr 1fr; margin: 0; }
/* Two rows pair up side by side — the two pass types, and phone with email — so the
   card spends one row of height where it used to spend two. Placement only: <dt>/<dd>
   stay siblings inside the same div. */
.detail-list div[data-group="wide"] { grid-column: 1 / -1; }
.detail-list div {
  display: grid;
  grid-template-columns: 40px minmax(0, 1fr);
  column-gap: 14px;
  align-items: start;
  padding: 1.05rem 0;
  border-top: 1px solid var(--line);
}
.detail-list div:first-child { border-top: 0; padding-top: 0; }
.detail-list div > .mark {
  grid-column: 1;
  grid-row: 1 / span 2;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: 10px;
  background: #f8f2ef;
  color: var(--accent-strong);
}
.detail-list div > dt {
  grid-column: 2;
  font-size: 0.9375rem;
  font-weight: 600;
  text-transform: none;
  letter-spacing: 0;
  line-height: 1.3;
  color: var(--ink);
}
/* A settlement chip sits at the END of its row, as in the design. Marked on the row
   rather than the <dd>, because the <dd> must stay bare for the pass-row parser. */
.detail-list div[data-chip] > dd {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
}

/* The design's pill, for a CONFIRMED pass: a soft maroon chip, sentence case, 13px/500
   — the export's .pill, to the pixel. Pending and Paid keep the louder .badge. */
.pill {
  display: inline-flex;
  align-items: center;
  flex: 0 0 auto;
  padding: 6px 12px;
  border-radius: 999px;
  background: #f8f2ef;
  color: #5b2425;
  font-size: 0.8125rem;
  font-weight: 500;
  line-height: 1.2;
  text-transform: none;
  letter-spacing: 0;
  white-space: nowrap;
}

.detail-list div > dd {
  grid-column: 2;
  margin: 0.2rem 0 0;
  font-size: 0.8125rem;
  font-weight: 400;
  color: var(--ink-soft);
  line-height: 1.4;
}

/* ── the ticket card, to the organiser's design ──────────────────────────────
   The card is the artifact: banner, title, three facts, the pass lines, the QR.
   Everything the guest must DO lives in the action column beside it. */
.ticket.rc-card { padding: 0; }
.rc-banner { background: #f4f3f2; }
.rc-banner img { display: block; width: 100%; height: auto; }
.rc-body { padding: 1.35rem 1.75rem 1.75rem; }
.rc-badges { display: flex; gap: 0.4rem; flex-wrap: wrap; margin-bottom: 0.7rem; }
.rc-title {
  margin: 0;
  /* The design's scale, measured from the exported left panel: 26px/600/-0.02em. */
  font-size: 1.625rem;
  font-weight: 600;
  line-height: 1.25;
  letter-spacing: -0.02em;
}
.rc-excerpt { margin: 0.5rem 0 0; color: var(--ink-soft); font-size: 0.875rem; line-height: 1.45; }
.rc-facts { display: grid; grid-template-columns: 1fr 1fr; gap: 1.35rem 1.5rem; margin: 1.6rem 0 0.5rem; }
.rc-fact { display: flex; gap: 0.75rem; min-width: 0; }
.rc-fact--wide { grid-column: 1 / -1; }
.rc-ico {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  flex: 0 0 40px;
  border-radius: 10px;
  background: #f8f2ef;
  color: var(--accent-strong);
}
.rc-kicker {
  margin: 0;
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  line-height: 1.3;
  text-transform: uppercase;
  color: var(--ink-soft);
}
.rc-value { margin: 0.25rem 0 0; font-size: 0.9375rem; font-weight: 500; line-height: 1.35; }
.rc-meta { margin: 0.2rem 0 0; font-size: 0.8125rem; color: var(--ink-soft); line-height: 1.4; }

/* One line at the card foot, as designed — with the full terms one tap away rather
   than deleted. "bring photo ID" and "children need no separate pass" are things the
   door depends on, and a printed receipt is what a guest actually brings. */
.rc-keep {
  display: grid;
  gap: 0.35rem;
  padding: 0.95rem 1.75rem;
  background: #f8f2ef;
  color: #5b2425;
}
.rc-keep-line { display: flex; align-items: center; gap: 0.55rem; margin: 0; font-size: 0.8125rem; font-weight: 500; line-height: 1.4; }
.rc-terms summary { cursor: pointer; font-size: 0.78rem; color: #7a4a45; }
.rc-terms ul { margin: 0.5rem 0 0; padding-left: 1.1rem; display: grid; gap: 0.3rem; color: #7a4a45; font-size: 0.78rem; }

.rc-block {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 16px;
  padding: 1.15rem 1.25rem;
}
/* The confirmation note keeps the card foot's tint, but draws no line and uses the ordinary
   text colours — it is a note inside the card, not a third panel competing with the money
   block. */
.rc-email { background: #f8f2ef; border: 0; }
.rc-block h2 { margin: 0 0 0.35rem; font-size: 1.05rem; font-weight: 650; }
/* "Change your details" on the payment step. A disclosure, because the page's job is to
   take the payment and this is only the correction path — but it opens itself when a save
   came back with an error, so the guest is not left hunting for what went wrong. */
.rc-edit summary { cursor: pointer; font-weight: 650; font-size: 1rem; }
.rc-edit[open] summary { margin-bottom: 0.5rem; }
.rc-edit .rc-block-note { margin-top: 0; }
.rc-edit-form { display: grid; margin-top: 0.85rem; }
.rc-edit-form .field { margin-bottom: 0.8rem; }
/* Two counts side by side, matching how the booking form presents the same choice. */
.qty-row { display: grid; grid-template-columns: 1fr 1fr; gap: 0.7rem; }
.qty-row .field { margin-bottom: 0.4rem; }
.rc-edit-form .field:last-of-type { margin-bottom: 0.4rem; }
/* A button inside an action card (the download, the pay prompt) spans the card. */
.rc-block .btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.45rem;
  width: 100%;
  margin-top: 0.9rem;
  font-weight: 600;
}
.rc-block .btn .ico { flex: 0 0 auto; }
.rc-block-lede { margin: 0; color: var(--ink-soft); font-size: 0.85rem; line-height: 1.45; }
.rc-block-note { margin: 0.55rem 0 0; color: var(--ink-soft); font-size: 0.76rem; }
.rc-money-list { display: grid; gap: 0.55rem; margin: 0; }
.rc-money-list div { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; }
.rc-money-list dt {
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
.rc-money-list dd { margin: 0; font-size: 1rem; font-weight: 650; text-align: right; }
.rc-money-list div:last-child dd { font-size: 1.25rem; }

/* The design stacks the pass lines above the QR rather than beside it. No grid gap:
   the last row already carries padding-bottom and the scan row its own padding-top,
   so a gap here made the space under the last row ~20px wider than between rows. */
.ticket-body { grid-template-columns: 1fr; gap: 0; }

@media (max-width: 560px) {
  .rc-facts { grid-template-columns: 1fr; }
  .rc-body { padding: 1.25rem 1.15rem 1rem; }
  .rc-keep { padding: 0.9rem 1.15rem; }
}

/* The design's scan row: the instruction on the left, the code on the right, both
   top-aligned. The void and pending blocks keep their own centred layout. */
.rc-card .qr-block--scan {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1.25rem;
  padding-top: 1.05rem;
  border-top: 1px solid var(--line);
  text-align: left;
}
.scan-main { display: flex; gap: 14px; min-width: 0; }
.scan-main .mark {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  flex: 0 0 40px;
  border-radius: 10px;
  background: #f8f2ef;
  color: var(--accent-strong);
}
.rc-name { margin: 0; font-size: 0.9375rem; font-weight: 600; line-height: 1.3; }
.scan-code { flex: 0 0 auto; text-align: center; }
.rc-card .qr-frame { margin: 0; }

.qr-block { text-align: center; }
.qr-frame {
  padding: 12px;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: 14px;
  display: inline-block;
}
.qr-frame svg { display: block; width: 168px; height: 168px; }
/* A pass that cannot be used: the same footprint the QR would take, so the card
   keeps its shape and the reason is impossible to miss. */
.qr-frame.qr-void {
  width: 192px;
  min-height: 168px;
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  border-style: dashed;
  border-color: #b4342a;
  background: repeating-linear-gradient(45deg, #fff 0 10px, #fdf3f2 10px 20px);
}
.qr-void-title { margin: 0; font-weight: 700; text-transform: uppercase; letter-spacing: 0.1em; color: #b4342a; }
.qr-void-note { margin: 0; font-size: 0.78rem; color: var(--ink-soft); }
.ticket-number {
  font-family: var(--mono);
  font-size: 0.9rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  margin: 0.7rem 0 0.1rem;
}
.qr-caption { margin: 0; font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.12em; color: var(--ink-soft); }

.is-revoked { opacity: 0.9; }
.is-revoked::after {
  content: "";
  position: absolute;
  inset: 0;
  background: repeating-linear-gradient(-45deg, transparent 0 14px, rgba(180, 35, 24, 0.05) 14px 28px);
  pointer-events: none;
}
.void-stamp {
  position: absolute;
  top: 42%;
  left: 50%;
  transform: translate(-50%, -50%) rotate(-14deg);
  margin: 0;
  padding: 0.4rem 1.6rem;
  border: 3px solid var(--danger);
  border-radius: 10px;
  color: var(--danger);
  font-size: 2rem;
  font-weight: 800;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  background: rgba(255, 255, 255, 0.75);
}

.actions { display: flex; flex-wrap: wrap; gap: 0.75rem; margin-top: 1.25rem; }
.actions .btn-primary { width: auto; flex: 1 1 220px; }

.center-card {
  max-width: 520px;
  margin: 12vh auto;
  padding: 2rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  text-align: center;
}

/* ---------- Payment step ---------- */

.pay-layout {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
  gap: 1.5rem;
  align-items: start;
  max-width: 1060px;
  margin: 0 auto;
  padding: 1rem 1.5rem 3rem;
}
/* The action column is first in the DOM so it leads on a phone; on a wide screen the
   pass takes the left column and the pay card the right, as on the confirmation page. */
.pay-layout > .rc-side { grid-column: 2; grid-row: 1; }
.pay-layout > .ticket { grid-column: 1; grid-row: 1; }
/* No h1 rule here: the only h1 is the card's title, which has its own scale. */
.status-note { font-size: 0.85rem; color: var(--ink-soft); }

.upi-box {
  margin: 1rem 0;
  background: #fbfcfe;
  border: 1px solid var(--line);
  border-radius: 14px;
  overflow: hidden;
}
.upi-row {
  display: grid;
  grid-template-columns: 84px minmax(0, 1fr) auto;
  gap: 0.75rem;
  align-items: center;
  padding: 0.7rem 0.9rem;
  border-bottom: 1px solid var(--line);
}
.upi-row:last-child { border-bottom: 0; }
.upi-label { font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.1em; color: var(--ink-soft); }
.upi-value { font-weight: 650; word-break: break-all; }
.copy-btn {
  font: inherit;
  font-size: 0.75rem;
  font-weight: 650;
  padding: 0.28rem 0.6rem;
  border-radius: 8px;
  border: 1px solid var(--line);
  background: #fff;
  cursor: pointer;
}
.copy-btn:hover { border-color: var(--accent); color: var(--accent-strong); }
.note {
  margin: 0 0 1rem;
  padding: 0.65rem 0.8rem;
  font-size: 0.85rem;
  color: var(--ink-soft);
  background: #f7f9fc;
  border-left: 3px solid var(--accent);
  border-radius: 0 10px 10px 0;
}
.btn.full { width: 100%; margin-bottom: 0.6rem; }
.pay-state { margin: 0.9rem 0 0; min-height: 2.6em; font-size: 0.85rem; color: var(--ink-soft); }
.lede.small { font-size: 0.92rem; }
.fineprint.center { text-align: center; }
.pending-block { max-width: 210px; text-align: left; }
.pending-icon {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  margin-bottom: 0.6rem;
  border-radius: 50%;
  background: #fef0c7;
  color: #b54708;
  font-size: 1.3rem;
  font-weight: 800;
}
.pending-title { margin: 0 0 0.2rem; font-weight: 750; }
.pending-copy { margin: 0 0 0.8rem; font-size: 0.8rem; color: var(--ink-soft); }
.badge-pending_payment { color: #b54708; background: #fef0c7; }
.badge-payment_claimed { color: #1849a9; background: #dbe8fe; }

/* ---------- Payment desk (ops) ---------- */

.ops-layout { max-width: 1160px; margin: 0 auto; padding: 1rem 1.5rem 3rem; }
.ops-search { display: flex; gap: 0.5rem; max-width: 520px; margin: 0 0 1.5rem; }
.ops-search input {
  flex: 1;
  padding: 0.6rem 0.8rem;
  font: inherit;
  color: var(--ink);
  background: #fff;
  border: 1px solid var(--line);
  border-radius: 11px;
}
.ops-search input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent);
}
.ops-section { margin: 1.75rem 0 0.75rem; font-size: 1.1rem; }
.ops-section:first-of-type { margin-top: 0; }
.ops-nav {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  max-width: 1160px;
  margin: 0 auto 0.5rem;
  padding: 0 1.5rem;
}
.ops-nav-link {
  padding: 0.4rem 0.9rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--surface);
  color: var(--ink-soft);
  font-size: 0.85rem;
  font-weight: 600;
  text-decoration: none;
}
.ops-nav-link.active { border-color: var(--accent); color: var(--accent-strong); background: color-mix(in srgb, var(--accent) 8%, #fff); }
.row-revoked td { opacity: 0.6; }
.comp-form .btn { width: auto; }
.report-callout {
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  margin: 0 0 1rem;
  padding: 0.9rem 1.1rem;
  border: 1px solid var(--line);
  border-radius: 14px;
  background: color-mix(in srgb, var(--accent) 6%, #fff);
}
.report-callout strong { font-size: 2rem; letter-spacing: -0.02em; }
.report-callout span { color: var(--ink-soft); font-size: 0.9rem; }
.ops-table td.mono { font-family: var(--mono); }
.rate-note-error { color: var(--danger); }
.ops-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 1rem; margin-bottom: 1.25rem; }
.count-pill {
  padding: 0.35rem 0.8rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--surface);
  color: var(--ink-soft);
  font-size: 0.8rem;
  font-weight: 650;
  white-space: nowrap;
}
.banner {
  margin: 0 0 1rem;
  padding: 0.7rem 0.9rem;
  border: 1px solid #fedf89;
  border-radius: 12px;
  background: #fffaeb;
  color: #93370d;
  font-size: 0.85rem;
}
.banner-ok { border-color: #a6f4c5; background: #ecfdf3; color: #05603a; }
.empty-state {
  padding: 2rem;
  border: 1px dashed var(--line);
  border-radius: 14px;
  background: var(--surface);
  color: var(--ink-soft);
  text-align: center;
}
.table-wrap {
  overflow: auto;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 16px;
  box-shadow: var(--shadow);
}
.ops-table { width: 100%; border-collapse: collapse; font-size: 0.88rem; }
.ops-table th {
  padding: 0.8rem 1rem;
  border-bottom: 1px solid var(--line);
  background: #fbfcfe;
  text-align: left;
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--ink-soft);
}
.ops-table td { padding: 0.85rem 1rem; border-bottom: 1px solid var(--line); vertical-align: top; }
.ops-table tr:last-child td { border-bottom: 0; }
.row-claimed { background: #f5f9ff; }
.claimed-tag { font-size: 0.75rem; color: #1849a9; }

/* Which path a booking came through.
   A gurukul booking splits the money: the entry goes to the Gurukul and only the
   buffet is ours. The row showed the amount WE collect and never said the rest went
   elsewhere, so the operator could not tell what they were looking at — the organiser
   had to query the database to find out. */
.rate-tag {
  display: inline-block;
  margin-top: 0.25rem;
  font-size: 0.72rem;
  font-weight: 700;
  color: #5c2824;
  background: #f6eeec;
  border: 1px solid #e4d2cd;
  border-radius: 999px;
  padding: 0.1rem 0.55rem;
}

/* Ops reminder: this booking has not had its WhatsApp message sent yet. Ops send
   by hand via the wa.me link, so the desk has to make that gap obvious. */
.wa-flag {
  margin: 0.4rem 0 0;
  font-size: 0.75rem;
  font-weight: 700;
  color: #8a3d0d;
  background: #f8e3c0;
  border: 1px solid #e0bd85;
  border-radius: 999px;
  padding: 0.15rem 0.6rem;
  display: inline-block;
}

/* Seat-hold countdown. Gurukul bookings hold for 36 hours, so the desk has to
   see the clock before seats lapse silently. */
.hold-tag {
  display: inline-block;
  margin-top: 0.25rem;
  font-size: 0.72rem;
  font-weight: 700;
  color: #4a5568;
}
.hold-urgent { color: #b42318; }
.btn.small { width: auto; padding: 0.45rem 0.7rem; font-size: 0.8rem; }
.staff-link { margin: 0.5rem 0 0; font-size: 0.75rem; }
.staff-link a { color: var(--accent-strong); text-decoration: none; }
.staff-link a:hover { text-decoration: underline; }
.operator { font-size: 0.72rem; color: var(--ink-soft); }
.muted { color: var(--ink-soft); }
.small { font-size: 0.78rem; }

@media (max-width: 860px) {
  .layout, .ticket-body { grid-template-columns: 1fr; }
  .pay-layout { grid-template-columns: 1fr; }
  /* One column: the pay button comes before the full pass, so the guest does not scroll
     past a whole ticket to find it. */
  .pay-layout > .rc-side,
  .pay-layout > .ticket { grid-column: 1; grid-row: auto; }
  .ops-head { flex-direction: column; }
  .ticket-body { gap: 0; }
  .qr-block { justify-self: start; text-align: left; }
}

@media (max-width: 560px) {
  .grid-2 { grid-template-columns: 1fr; }
  .site-header { flex-direction: column; align-items: flex-start; gap: 0.25rem; }
  .qr-frame svg { width: 140px; height: 140px; }
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; }
}

@media print {
  /* A4 with a light margin. The pass is one full-width column on paper, so the sheet is
     the width budget: every millimetre the margin takes comes off the card, and off the
     banner with it. */
  @page { size: A4; margin: 6mm; }

  body { background: #fff; font-size: 12.5px; line-height: 1.4; }
  .no-print, .site-header, .actions, .banner { display: none !important; }
  /* The success header is a web affordance. On a printed pass it repeats what the
     ticket already says, and it costs about 45mm — which is what pushed the
     receipt onto a second page. The pass itself carries the booking id. */
  .done-head { display: none !important; }
  .receipt-layout { max-width: none; padding: 0; }
  /* Two columns are a screen affordance. A printed pass is one page, ticket first,
     with the money and the email note beneath it — and the terms disclosure closed,
     because the two lines above it are the ones the door needs. */
  /* The DOM deliberately puts the action column FIRST so it stacks first on a phone.
     Paper has no stacking, so force the ticket to the top and the notes beneath it. */
  /* align-items: stretch is the load-bearing half. The base rule sets `start` for the
     screen's grid, and in a COLUMN flex container that means "size to content" — which
     printed the money block as a 210px sliver beneath a 748px card. */
  .receipt-cols { display: flex; flex-direction: column; align-items: stretch; }
  .receipt-cols > .ticket { order: -1; }
  /* A download button on paper is nonsense, and that card costs a third of a page. */
  .rc-ready { display: none !important; }
  /* "We've emailed your ticket to you" is an odd thing to print on the sheet that arrived
     AS that email. It reassures someone reading the web page; on paper it only takes
     height. */
  .rc-email { display: none !important; }

  /* Tight but legible: a pass that spills onto a second sheet is twice the paper for the
     same ticket. The banner is the exception — it runs the full card width at its own
     1600×554 ratio, so do NOT cap its height. A max-height with object-fit: cover CROPS
     the poster, and the event name across the top is the first thing to go. */
  /* The banner hands over to the title with real air under it, as on screen, where the
     body's top padding is 1.35rem. Print had it at 2.5mm — 9px — which read as the
     poster crowding the event name. */
  .rc-body { padding: 5.5mm 6mm 1.5mm; }
  .rc-title { font-size: 1.1rem; }
  .rc-excerpt { font-size: 0.78rem; }
  /* Three across rather than two-plus-a-wide-venue: at 198mm there IS room, and it
     removes a 9mm row from a sheet where rows are the scarce thing. */
  .rc-facts { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 2mm 4mm; margin: 1mm 0 0.5mm; }
  .rc-facts .rc-fact--wide { grid-column: auto; }
  .rc-fact { gap: 0.5rem; }
  /* The 40px icon tiles set the height of every fact AND detail row. At 26px the icon is
     still legible on paper and each row loses 4mm — the single biggest saving here. */
  .rc-ico { width: 26px; height: 26px; flex: 0 0 26px; border-radius: 7px; }
  .rc-value { font-size: 0.82rem; }
  .rc-kicker { font-size: 0.62rem; }
  /* Room to breathe around the hairline separators. Row-gap is 0 in print, so this
     padding IS the row spacing. It costs no page height when the booking is merely
     BIGGER — extra passes only lengthen the "10 × ₹750" text inside one row. The height
     is set by how many row TYPES apply, so this is affordable for large bookings. */
  .detail-list div { padding: 2.2mm 0; }
  .detail-list div > dt { font-size: 0.85rem; }
  .detail-list div > dd { font-size: 0.7rem; }
  .detail-list div > .mark { width: 6mm; height: 6mm; }
  /* The two keep lines sit side by side: 198mm holds both, and stacking them costs a line
     of height on every single pass. */
  .rc-keep { display: flex; flex-wrap: wrap; gap: 1mm 7mm; padding: 1.6mm 6mm; }
  .rc-keep-line { font-size: 0.7rem; }
  .rc-block { padding: 1.6mm 4mm; }
  .rc-block h2 { font-size: 0.9rem; }
  /* The money block runs the full width of the sheet, like the card above it. A grid's
     implicit column is sized to its CONTENT, so without this the block prints in a
     210px sliver under a 748px card. */
  .rc-side { margin-top: 2.5mm; display: grid; gap: 2mm; grid-template-columns: 1fr; }
  .rc-terms { display: none !important; }
  .rc-keep,
  .rc-ico { print-color-adjust: exact; -webkit-print-color-adjust: exact; }
  .ticket {
    border: 1px solid #c8cfdb;
    border-radius: 14px;
    box-shadow: none;
    padding: 6mm;
    break-inside: avoid;
    print-color-adjust: exact;
    -webkit-print-color-adjust: exact;
  }
  .ticket-body { gap: 0.6rem; padding-top: 0.4rem; }
  /* gap: 0.4rem set a ROW gap on top of each row's own padding, and clobbered the base
     14px column gap, which is what keeps the paired columns (pass types, phone/email)
     from touching. Row spacing is the div padding; the hairline border does the rest. */
  .detail-list { gap: 0 14px; }
  .detail-list dt { font-size: 0.62rem; }
  .detail-list dd { font-size: 0.88rem; }
  .qr-frame { padding: 6px; }
  /* .qr-block--scan is a flex row with space-between, but the block itself was
     shrink-to-content and pinned to the left edge by the narrow-screen rule, so the
     code finished near the middle of the sheet. Stretched, space-between puts the QR
     against the right edge with the scan text on the left, as designed. */
  .qr-block { justify-self: stretch; }
  /* Bought back from fixed-height chrome to pay for the row padding above. */
  .qr-block--scan { padding-top: 0.75rem; }
  .scan-main .mark { width: 30px; height: 30px; flex: 0 0 30px; border-radius: 8px; }
  /* Right, not centre: the code column is wider than the frame (the ticket number and
     caption set its width), so centring inside it still left the QR ~3mm off the edge. */
  .scan-code { text-align: right; }
  /* Printed to be scanned off paper by a phone at the door. The code is vector, so size
     here is not resolution — it is MODULES PER MILLIMETRE on the sheet, which is the
     thing a camera actually has to resolve. 34mm over a 33-module code is ~1mm per
     module; 22mm was ~0.67mm, which reads but leaves no margin for a tired arm.
     The padding IS the quiet zone: qrSvg sets margin: 0, so nothing else supplies the
     four clear modules the spec requires — the white ground of the card is not
     guaranteed to be clear of the rules and stamps that sit around it. 4.7mm is set so
     the zone stays >= 4 modules even if a longer production URL pushes the code to a
     denser version (at 33 modules the same padding is 4.6 modules). */
  .qr-frame { padding: 4.7mm; }
  .qr-frame svg { width: 34mm; height: 34mm; }
  .qr-frame.qr-void { width: 43.4mm; min-height: 43.4mm; }
  .ticket-number { font-size: 0.8rem; margin-top: 0.5rem; }
  a { color: inherit; text-decoration: none; }
}


/* ==========================================================================
   Public booking page (page-book)
   Layout from the organiser's mockups: hero, event heading, meta tiles, About,
   then ticket cards with steppers beside a booking summary that stays in view.
   Palette and radii were sampled from the mockups rather than guessed.
   ========================================================================== */

.page-book {
  background: var(--canvas);
  color: var(--ink);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
}

.page-book .ico { flex: none; }

/* ---- Top bar + steps ---- */
.book-topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  max-width: 1120px;
  margin: 0 auto;
  padding: 1rem 1.25rem;
}

.book-back {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  color: var(--ink-soft);
  font-size: 0.9rem;
  font-weight: 600;
  text-decoration: none;
}
.book-back:hover { color: var(--ink); }

.book-steps {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: 0.875rem;
  color: var(--ink-soft);
}
.book-steps li { display: inline-flex; align-items: center; gap: 0.5rem; }
.book-step-num {
  display: grid;
  place-items: center;
  width: 1.6rem;
  height: 1.6rem;
  border-radius: 50%;
  background: #eeeceb;
  color: var(--ink-soft);
  font-size: 0.8rem;
  font-weight: 700;
}
.book-steps .is-active { color: var(--ink); font-weight: 650; }
.book-steps .is-active .book-step-num { background: var(--accent); color: #fff; }
.book-steps .is-done { color: var(--ink-soft); }
/* A stage you have FINISHED is a green tick; only the stage you are on is maroon. */
.book-steps .is-done .book-step-num { background: #d8f5e3; color: #05603a; font-size: 0.9rem; }

/* On the pass, the same bar sits on the receipt's own background. */
.page-receipt .book-topbar { max-width: 900px; padding: 1rem 1.25rem 0; }
/* The payment step carries the same bar, so it reads as the same flow rather than a
   page from somewhere else. */
.page-pay .book-topbar { max-width: 960px; padding: 1rem 1.25rem 0; }

/* ---- Confirmation header (design-3) ---- */
.done-head { text-align: center; margin-bottom: 1.75rem; }
.done-mark {
  display: grid;
  place-items: center;
  width: 4rem;
  height: 4rem;
  margin: 0 auto 1rem;
  border-radius: 50%;
  background: #f3efec;
  color: var(--accent);
}
.done-head h1 { margin: 0 0 0.5rem; font-size: clamp(1.5rem, 1.2rem + 1.4vw, 1.9rem); font-weight: 700; }
.done-head p { margin: 0; color: var(--ink-soft); }
.done-id { margin-top: 0.5rem; color: var(--muted); font-size: 0.85rem; }
.done-id strong { font-family: var(--mono); color: var(--ink); font-weight: 700; }

/* The poster, reused from the booking page's hero. */

/* "Scan at entry" block on the pass. */
.scan-head { display: flex; align-items: center; gap: 0.5rem; margin: 0 0 0.75rem; font-weight: 700; }
.scan-head .ico { color: var(--accent); }

/* ---- Hero ---- */
/* Full-bleed, capped so it does not stretch absurdly on a very wide monitor. */
.book-hero {
  max-width: 1920px;
  margin: 0 auto;
  padding: 0;
}
.book-hero img {
  display: block;
  width: 100%;
  height: auto;
}

/* ---- The white content block ---- */
.book-card {
  max-width: 1120px;
  margin: 1.5rem auto 0;
  padding: 2.5rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}

.book-head h1 {
  margin: 0 0 0.35rem;
  font-size: clamp(1.6rem, 1.2rem + 1.6vw, 2rem);
  font-weight: 700;
  letter-spacing: -0.01em;
}
.book-sub { margin: 0; color: var(--ink-soft); }
.book-scarcity {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  margin: 0.75rem 0 0;
  padding: 0.3rem 0.8rem;
  border-radius: 999px;
  background: #f3efec;
  color: var(--accent);
  font-size: 0.8rem;
  font-weight: 650;
}

/* ---- Date / time / venue ---- */
.book-meta {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 1.5rem;
  margin: 1.75rem 0 0;
  padding: 0;
  list-style: none;
}
.book-meta li { display: flex; align-items: flex-start; gap: 0.65rem; color: var(--ink-soft); }
.book-meta span {
  display: block;
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
}
.book-meta strong { display: block; color: var(--ink); font-size: 0.95rem; font-weight: 600; }

/* ---- About ---- */
.book-about { margin-top: 2rem; padding-top: 2rem; border-top: 1px solid var(--line); }
.book-about h2 { margin: 0 0 0.75rem; font-size: 1.25rem; }
.book-about p { margin: 0 0 1rem; color: var(--ink-soft); line-height: 1.65; }
.book-about p:last-child { margin-bottom: 0; }

/* ---- Two columns ---- */
.book-columns {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 340px;
  gap: 2rem;
  margin-top: 2rem;
  padding-top: 2rem;
  border-top: 1px solid var(--line);
  align-items: start;
}
.book-main { display: grid; gap: 2rem; min-width: 0; }

.book-section h2 { margin: 0 0 0.4rem; font-size: 1.25rem; }
.book-section-lede { margin: 0 0 1rem; color: var(--ink-soft); font-size: 0.9rem; }
.book-section-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 1rem;
}
.book-section-head h2 { margin: 0; }
.book-section-note { color: var(--muted); font-size: 0.8rem; }

/* ---- Ticket cards ---- */
.ticket-options { display: grid; gap: 1rem; }
.ticket-option {
  padding: 1.5rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
}
.ticket-option-main { display: flex; align-items: flex-start; gap: 0.85rem; }
.ticket-option-icon { color: var(--accent); margin-top: 0.15rem; }
.ticket-option h3 { margin: 0 0 0.2rem; font-size: 1rem; font-weight: 650; }
.ticket-option-sep { color: var(--muted); font-weight: 400; }
.ticket-option-sub { margin: 0; color: var(--ink-soft); font-size: 0.875rem; }
.ticket-option-foot {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 1rem;
  margin-top: 1.25rem;
  flex-wrap: wrap;
}
.ticket-option-price strong { display: block; font-size: 1.25rem; font-weight: 700; }
.ticket-option-price small { display: block; color: var(--muted); font-size: 0.8rem; }

/* The shared field styles are sized for the ops desk; the booking page is a
   consumer form, so the controls sit a little shorter here. */
.page-book .field input { padding: 0.6rem 0.7rem; }
.page-book .field { margin-bottom: 1rem; }
.page-book .hint { font-size: 0.8rem; }

/* ---- Quantity stepper ---- */
.stepper {
  display: inline-grid;
  grid-template-columns: 2.5rem 3rem 2.5rem;
  align-items: stretch;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--surface);
}
.stepper-btn {
  border: 0;
  background: var(--surface);
  color: var(--ink);
  font-size: 1.1rem;
  font-weight: 600;
  line-height: 1;
  cursor: pointer;
  padding: 0.6rem 0;
}
.stepper-btn:hover { background: #f3efec; }
.stepper-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.stepper input {
  border: 0;
  border-left: 1px solid var(--line);
  border-right: 1px solid var(--line);
  text-align: center;
  font: inherit;
  font-weight: 650;
  color: var(--ink);
  background: var(--surface);
  padding: 0.6rem 0;
  width: 100%;
  -moz-appearance: textfield;
}
.stepper input::-webkit-outer-spin-button,
.stepper input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

/* ---- Coupon ---- */
.coupon-row { display: flex; gap: 0.5rem; flex-wrap: wrap; }
.coupon-row input { flex: 1 1 12rem; min-width: 0; }
.btn-outline {
  background: var(--surface);
  border: 1px solid var(--line);
  color: var(--ink);
  font-weight: 650;
}
.btn-outline:hover { border-color: var(--ink-soft); }
.page-book .rate-note { margin-top: 0.6rem; }

/* ---- Booking summary ---- */
.book-summary {
  position: sticky;
  top: 1rem;
  padding: 1.5rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: var(--shadow);
}
.book-summary h2 {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0 0 1rem;
  font-size: 1rem;
  font-weight: 700;
}
.summary-lines { display: grid; gap: 0.85rem; }
.summary-line { display: flex; align-items: flex-start; justify-content: space-between; gap: 1rem; }
.summary-line span { display: block; font-size: 0.9rem; font-weight: 600; }
.summary-line small { display: block; color: var(--ink-soft); font-size: 0.8rem; }
.summary-line strong { font-size: 0.95rem; font-variant-numeric: tabular-nums; }
.summary-empty { margin: 0; color: var(--muted); font-size: 0.9rem; }

.summary-total {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 1rem;
  margin-top: 1rem;
  padding-top: 1rem;
  border-top: 1px solid var(--line);
}
.summary-total span { display: block; font-weight: 700; }
.summary-total small { display: block; color: var(--muted); font-size: 0.8rem; }
.summary-total strong { font-size: 1.5rem; font-weight: 700; color: var(--accent); }

.summary-breakdown {
  margin: 0.35rem 0 0;
  color: var(--muted);
  font-size: 0.78rem;
  text-align: right;
}
.summary-submit { width: 100%; margin-top: 1.25rem; }
.book-summary .fineprint { margin: 0.75rem 0 0; text-align: center; }
.book-submit-inline { display: none; }

/* ---- Footer ---- */
.page-book .fineprint { font-size: 0.8rem; line-height: 1.5; }
.book-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  max-width: 1120px;
  margin: 0 auto;
  padding: 2rem 1.25rem 3rem;
  color: var(--ink-soft);
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.book-footer span:last-child { text-transform: none; letter-spacing: 0; color: var(--muted); }

/* ---- Narrow screens: one column, summary after the form ---- */
@media (max-width: 900px) {
  .book-card { padding: 1.5rem; }
  .book-columns { grid-template-columns: minmax(0, 1fr); }
  .book-summary { position: static; }
  /* The inline button is the one in reach on a phone; the sticky one is off-screen. */
  .book-submit-inline { display: block; width: 100%; }
  .summary-submit { display: none; }
}
