/* ---------------------------------------------------------------
   Hazlitt Policy Summit 2026 — "The Gate"

   The page is the invitation, not a page about one. The card is the hero and sits in the first
   screen; everything below it is reference material for someone who is deciding, not a funnel.
   The previous build was a stack of full-width bands with alternating tints, a red rule under
   every heading, and the card buried three scrolls down — Ben's word for it was "Wordpress bleh".
--------------------------------------------------------------- */
:root {
  --ink: #14171a;
  --ink-2: #1c2026;
  --paper: #ffffff;
  --paper-2: #f2f3f5;
  --line: rgba(20, 23, 26, 0.16);
  --line-on-ink: rgba(255, 255, 255, 0.18);
  --muted: #5a6169;
  --muted-on-ink: rgba(255, 255, 255, 0.74);
  --red: #c8352b;
  --red-dark: #a52a22;

  --font-serif: "Fraunces", "Iowan Old Style", "Palatino Linotype", serif;
  --font-sans: "Public Sans", "Segoe UI", system-ui, sans-serif;

  --text-h1: clamp(1.6rem, 1rem + 1.9vw, 2.25rem);
  --text-h2: clamp(1.45rem, 1.2rem + 0.9vw, 2rem);
  --text-fine: 0.88rem;

  --space-2xs: 8px;
  --space-xs: 12px;
  --space-sm: 16px;
  --space-md: 24px;
  --space-lg: 40px;
  --space-xl: 64px;
  --space-2xl: 96px;

  --ease-out: cubic-bezier(0.2, 0.7, 0.2, 1);
  --dur-wipe: 320ms;
}

*, *::before, *::after { box-sizing: border-box; }
html { overflow-x: clip; scroll-behavior: smooth; }
body {
  margin: 0;
  overflow-x: clip;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: 17px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}
img { max-width: 100%; display: block; }
/* .card form sets display:grid, which outranks the UA sheet's [hidden]{display:none} and left
   both the form and the ticket on screen at once. */
[hidden] { display: none !important; }
h1, h2 { margin: 0; font-family: var(--font-serif); font-weight: 560; line-height: 1.04; text-wrap: balance; overflow-wrap: break-word; }
p { margin: 0; }
a { color: inherit; }
:focus-visible { outline: 3px solid var(--red); outline-offset: 3px; }
/* the panel is the only light ground left, so one focus colour covers the page */

.text-link { padding-block: 10px; font-weight: 600; text-decoration: underline; text-underline-offset: 3px; text-decoration-thickness: 1.5px; }
.text-link:hover { color: var(--red); }
.linkish { min-height: 44px; background: none; border: none; padding: 0; font: inherit; font-weight: 600; color: inherit; text-decoration: underline; text-underline-offset: 3px; cursor: pointer; }

/* ---------------------------------------------------------------
   The gate — invitation panel beside one photograph
--------------------------------------------------------------- */
.gate {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
  min-height: 100svh;
  background: var(--ink);
}
.gate-panel {
  background: var(--paper);
  display: flex;
  flex-direction: column;
  gap: clamp(0.5rem, 1.3vh, 0.9rem);
  min-width: 0;
  padding-block: clamp(1rem, 2vh, 1.5rem) var(--space-xl);
  /* % padding resolves against the grid area, so this centres a 30rem column in whatever width
     the panel track gets. The old hero aligned its text to .wrap's left edge instead, which at
     1920 left 364px of empty paper against 64px on the right and read as a white band. */
  padding-inline: max(clamp(1.5rem, 4vw, 3.5rem), calc((100% - 30rem) / 2));
}
.lockup { width: clamp(140px, 24vh, 260px); height: auto; }
.gate-panel h1 { font-size: var(--text-h1); max-width: 24ch; text-wrap: balance; line-height: 1.12; }
/* Breathing room around the title block. The request face gives it back: at 1000x900 that face has
   only ~9px of slack with these on and would scroll without the :not(). */
body:not(.asking) .lockup { margin-bottom: clamp(0.5rem, 2.2vh, 1.5rem); }
body:not(.asking) .gate-panel > .card { margin-top: clamp(0.4rem, 1.8vh, 1.25rem); }
.gate-panel .lede { font-size: 1rem; max-width: 46ch; }
.gate-panel .when { font-size: 0.95rem; font-weight: 600; }

.gate-photo { min-width: 0; background: var(--ink); }
.gate-photo picture, .gate-photo img { width: 100%; height: 100%; display: block; }
/* The panel scrolls past the card into the details; the photograph stays put beside it. */
.gate-photo picture { position: sticky; top: 0; height: 100svh; }
.gate-photo img { object-fit: cover; }

/* ---------------------------------------------------------------
   The card — it becomes the ticket rather than swapping for one
--------------------------------------------------------------- */
.card {
  margin-top: clamp(0.4rem, 1.4vh, 0.9rem);
  max-width: 30rem;
  background: var(--paper-2);
  border: 1px solid var(--line);
  padding: clamp(0.85rem, 1.9vh, 1.2rem) clamp(1.1rem, 2.2vw, 1.5rem);
  transition: background-color 380ms var(--ease-out), border-color 380ms var(--ease-out), color 380ms var(--ease-out);
  overflow: hidden; /* the height tween in index.html needs a clean box to animate */
}
.card h2 { font-size: var(--text-h2); margin-bottom: clamp(0.6rem, 1.4vh, 0.9rem); }
.card form { display: grid; gap: clamp(0.5rem, 1.1vh, 0.75rem); }
.card label { display: grid; gap: 6px; font-size: 0.92rem; font-weight: 600; }
.card input {
  min-height: 48px;
  padding: 0 14px;
  border: 1px solid var(--line);
  background: #fff;
  font-family: var(--font-sans);
  font-size: 1rem;
  color: var(--ink);
}
/* An invitation code is transcribed from an email, so it gets the one place on the page where
   tracked uppercase earns its keep: it makes O/0 and I/1 separable. */
.code-input { letter-spacing: 0.06em; text-transform: uppercase; }
.code-input.carved { background: #fff; border-color: var(--red); }

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: 48px;
  padding: 0 var(--space-md);
  background: var(--red);
  color: #fff;
  border: 1px solid var(--red);
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: 1rem;
  cursor: pointer;
  transition: background 160ms var(--ease-out), border-color 160ms var(--ease-out), transform 160ms var(--ease-out);
}
.btn:hover { background: var(--red-dark); border-color: var(--red-dark); }
.btn:active { transform: translateY(1px); }
.btn:disabled { opacity: 0.65; cursor: progress; }

.msg:empty { display: none; }
.msg { margin-top: var(--space-2xs); color: var(--red); font-size: var(--text-fine); font-weight: 600; }
.card-foot { margin-top: clamp(0.6rem, 1.4vh, 0.9rem); font-size: var(--text-fine); color: var(--muted); }

/* Verified: the same box, now the ticket. */
.card.is-ticket { background: var(--ink); border-color: var(--ink); color: #fff; }
.card.is-ticket .card-foot { display: none; }
.card.is-ticket .msg { color: #ff9c93; }
.price-reveal {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin-bottom: clamp(0.5rem, 1.4vh, 0.85rem);
  font-family: var(--font-serif);
  font-size: clamp(2.8rem, 2.1rem + 2.2vw, 4rem);
  line-height: 1;
}
.price-reveal small { font-family: var(--font-sans); font-size: 0.95rem; font-weight: 600; color: var(--muted-on-ink); }
.price-wipe { display: inline-block; }
.price-wipe.wipe-in { animation: wipeReveal var(--dur-wipe) var(--ease-out) both; }
@keyframes wipeReveal {
  from { clip-path: inset(0 100% 0 0); opacity: 0.4; }
  to { clip-path: inset(0 0 0 0); opacity: 1; }
}
.who { margin-bottom: clamp(0.8rem, 2vh, 1.2rem); color: var(--muted-on-ink); font-size: 0.95rem; overflow-wrap: anywhere; }
.who strong { color: #fff; }
.fine { margin-top: var(--space-xs); color: var(--muted-on-ink); font-size: var(--text-fine); }

/* ---------------------------------------------------------------
   Details under the card: what the ticket includes, and the schedule.
   Serena's copy (2026-09-16). This ended the one-screen page; what still
   has to hold is that the card sits in the first screen on desktop.
--------------------------------------------------------------- */
.details { max-width: 30rem; margin-top: var(--space-lg); padding-top: var(--space-md); border-top: 1px solid var(--line); }
.details + .details { margin-top: var(--space-md); }
.details h2 { font-size: 1.45rem; line-height: 1.15; margin-bottom: var(--space-sm); }
.details ul { margin: 0; padding-left: 1.1em; display: grid; gap: var(--space-2xs); }
.details li::marker { color: var(--red); }
.details dl { margin: 0; display: grid; gap: var(--space-2xs); }
.details dt { font-weight: 700; }
.details dd { margin: 0 0 var(--space-xs); }
.details .note { color: var(--muted); font-size: var(--text-fine); }

/* The request form is the longest face of the card, so the panel gives up its supporting copy
   while it is open. Reordering beats scrolling: nothing is deleted, it comes back on return. */
body.asking .lede { display: none; }

#request-form { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-xs); }
#request-form label { display: block; font-size: 0.85rem; font-weight: 600; }
#request-form label > input, #request-form label > textarea { margin-top: 4px; width: 100%; }
#request-form input, #request-form textarea {
  min-height: 42px;
  max-height: 32vh;
  padding: 9px 12px;
  border: 1px solid var(--line);
  background: #fff;
  font-family: var(--font-sans);
  font-size: 1rem;
  color: var(--ink);
  resize: vertical;
}
#request-form .full { grid-column: 1 / -1; }
#request-form .opt { font-weight: 400; color: var(--muted); }
#request-form .btn { grid-column: 1 / -1; }
#request-form .msg { grid-column: 1 / -1; }
.hp { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
.done { grid-column: 1 / -1; font-family: var(--font-serif); font-size: 1.2rem; max-width: 40ch; }
#haveCode { margin-top: var(--space-xs); font-size: 0.88rem; }

/* ---------------------------------------------------------------
   thanks.html and admin.html. The Gate redesign dropped these and left both pages unstyled.
--------------------------------------------------------------- */
.simple { min-height: 100svh; display: grid; place-items: center; padding: var(--space-lg) var(--space-md); }
.simple-card { width: min(36rem, 100%); display: grid; gap: var(--space-sm); }
.simple-card img { width: clamp(160px, 24vh, 240px); height: auto; margin-bottom: var(--space-xs); }
.simple-card h1 { font-size: var(--text-h1); }

.admin { width: min(64rem, 100% - 2rem); margin: 0 auto; padding: var(--space-xl) 0; display: grid; gap: var(--space-md); }
.admin h1 { font-size: var(--text-h1); }
.admin form { display: grid; gap: var(--space-sm); padding: var(--space-md); border: 1px solid var(--line); }
.admin label { display: grid; gap: 6px; font-size: 0.92rem; font-weight: 600; }
.admin input, .admin textarea { padding: 10px 14px; border: 1px solid var(--line); font: 1rem var(--font-sans); color: var(--ink); }
.admin .row { display: flex; flex-wrap: wrap; gap: var(--space-sm); align-items: center; margin-bottom: var(--space-sm); }
.admin .fine { color: var(--muted); margin-bottom: var(--space-sm); }
.table-wrap { overflow-x: auto; border: 1px solid var(--line); }
.admin table { width: 100%; border-collapse: collapse; font-size: 0.9rem; }
.admin th, .admin td { text-align: left; padding: 0.6rem 0.75rem; border-bottom: 1px solid var(--line); vertical-align: top; overflow-wrap: anywhere; }
.admin td.code { font-family: ui-monospace, Consolas, monospace; white-space: nowrap; }
.admin tr.bad td { color: var(--red); }
.admin label.check { display: flex; align-items: center; gap: var(--space-2xs); }

/* ---------------------------------------------------------------
   Narrow
--------------------------------------------------------------- */
@media (max-width: 900px) {
  .gate { grid-template-columns: 1fr; min-height: 0; }
  .gate-panel { order: 1; padding: var(--space-lg) var(--space-md); gap: var(--space-xs); }
  .gate-photo { order: 2; }
  .gate-photo picture { position: static; height: auto; }
  .gate-photo img { aspect-ratio: 4 / 3; }
  .card { max-width: none; }
}

/* A phone has one column to give the request form, and a smaller headline to give the card room. */
@media (max-width: 560px) {
  .gate-panel h1 { font-size: clamp(1.55rem, 1.1rem + 2vw, 2rem); }
  #request-form { grid-template-columns: 1fr; }
}

/* There is deliberately no max-height breakpoint. There used to be one, and it was the bug it
   was meant to fix: crossing it swapped vh-driven padding and gap for fixed values, so one extra
   pixel of viewport height cost about 76px of content and the fit stopped being monotonic in
   height — it fit at 880, failed just above 900, then fit again. Panel padding, gap and the
   lockup are all vh-driven instead, so short windows tighten continuously. Codex gate 7d caught
   this; don't reintroduce a height breakpoint without re-measuring the envelope on both sides.
--------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; }
}
