:root {
  --paper: #fbfaf6; /* sampled from the invitation's paper, so the branch sits on it seamlessly */
  --ink: #2f2f2b; /* near-black text */
  --olive: #6b8a3a; /* the accent: ampersand, time, buttons */
  --olive-deep: #4e6829; /* hover and pressed */
  --sage: #8a9a78; /* quiet text, focus rings */
  --line: #ded6c4; /* hairlines */
  --error: #9d3b2f;

  --display: "Cormorant Garamond", Garamond, "Times New Roman", serif;
  --body: "EB Garamond", Garamond, "Times New Roman", serif;

  --measure: 36rem;
  --page: 54rem; /* the centred column every band sits in */
  --gutter: clamp(1.25rem, 5vw, 3rem);
  --branch: clamp(78px, 26vw, 250px);
  color-scheme: light;
}

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

[hidden] {
  /* biome-ignore lint/complexity/noImportantStyles: must beat the display rules on .login and other hidden elements */
  display: none !important;
}

html {
  -webkit-text-size-adjust: 100%;
  overflow-x: hidden;
}

body {
  position: relative;
  margin: 0;
  padding-left: env(safe-area-inset-left);
  padding-right: env(safe-area-inset-right);
  background: var(--paper);
  color: var(--ink);
  font: 400 1.125rem / 1.65 var(--body);
  overflow-x: hidden;
  -webkit-tap-highlight-color: transparent;
}

a {
  color: var(--olive-deep);
}

:focus-visible {
  outline: 2px solid var(--olive);
  outline-offset: 3px;
}

/* ---------- Hero ---------- */

/* Text and branch are two columns of one centred group, so the hero sits in the same
   middle of the screen as the sections below it rather than spanning edge to edge. */
.hero {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: clamp(1.25rem, 4vw, 3.5rem);
  width: min(var(--page), 100%);
  margin-inline: auto;
  padding: clamp(1rem, 2vh, 1.75rem) var(--gutter) clamp(0.5rem, 1.5vh, 1.25rem);
}

/* Guests never see the admin link, so only an admin pays for the space it floats in. */
.has-admin-link .hero {
  padding-top: clamp(3.25rem, 5vh, 3.75rem);
}

.hero-text {
  max-width: 34rem;
  /* The names are sized against this column, not the viewport, so they always fit it. */
  container-type: inline-size;
}

.invite-line {
  margin: 0 0 clamp(1.25rem, 3vw, 2rem);
  font-family: var(--display);
  font-style: italic;
  font-size: clamp(1.15rem, 2.6vw, 1.5rem);
  color: color-mix(in srgb, var(--ink) 85%, var(--paper));
}

.names {
  margin: 0;
  /* The longest name measures 5.5em, so 17.5% of the column keeps it on one line. */
  font: 400 clamp(1.75rem, 17.5cqi, 5.25rem) / 1.04 var(--display);
  letter-spacing: 0.005em;
  color: var(--ink);
}
.names span {
  display: block;
  white-space: nowrap;
}
.names .amp {
  font-style: italic;
  font-size: 0.86em;
  line-height: 1.1;
  color: var(--olive);
}

.when {
  margin: clamp(1.75rem, 4vw, 2.75rem) 0 0;
  font: 400 clamp(1.7rem, 4.2vw, 2.4rem) / 1.2 var(--display);
  color: var(--ink);
}

.time {
  margin: 0.15rem 0 0;
  font-family: var(--display);
  font-size: clamp(1.3rem, 3vw, 1.7rem);
  font-weight: 600;
  color: var(--olive);
}

.venue {
  margin: clamp(1.75rem, 4vw, 2.5rem) 0 0.3rem;
  font-family: var(--display);
  font-size: clamp(1.1rem, 2.4vw, 1.35rem);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink);
}

.address {
  margin: 0;
  font-size: 1.05rem;
  line-height: 1.5;
  color: color-mix(in srgb, var(--ink) 80%, var(--paper));
}

/* The branch runs the full height of the text beside it. The image is taken out of flow
   so its own tall aspect ratio cannot stretch the row — the text alone sets the height. */
.branch {
  position: relative;
  width: var(--branch);
  align-self: stretch;
  pointer-events: none;
  overflow: hidden;
  /* The strip is taller than the hero, so both ends are cut mid-leaf. Fading them into the
     paper — which is the same colour the artwork was lifted from — hides the join. */
  -webkit-mask-image: linear-gradient(to bottom, transparent, #000 12%, #000 88%, transparent);
  mask-image: linear-gradient(to bottom, transparent, #000 12%, #000 88%, transparent);
}
.branch img {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center top;
}

@media (max-width: 34rem) {
  .hero {
    min-height: auto;
  }
}

/* ---------- Sub-page top bar ---------- */

.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  width: min(var(--page), 100%);
  margin-inline: auto;
  padding: calc(1.25rem + env(safe-area-inset-top)) var(--gutter) 0;
}
.topbar-home {
  font: 400 1.75rem / 1 var(--display);
  letter-spacing: 0.02em;
  color: var(--ink);
  text-decoration: none;
  white-space: nowrap;
}
.topbar-link {
  min-height: 2.75rem;
  display: inline-flex;
  align-items: center;
  font-size: 1rem;
  color: var(--olive-deep);
  text-decoration: none;
}
.topbar-link:hover {
  text-decoration: underline;
}

.subpage .block:first-child {
  padding-top: clamp(2rem, 6vw, 3.5rem);
}

/* Only ever shown to a signed-in admin, so it sits over the hero's empty upper area
   instead of displacing the guest-facing layout. */
/* Floats centred at the very top, out of the flow, so it never shifts anything below it. */
.admin-link {
  position: absolute;
  top: calc(0.9rem + env(safe-area-inset-top));
  left: 50%;
  transform: translateX(-50%);
  z-index: 1;
  margin: 0;
  white-space: nowrap;
  font-size: 0.9rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.admin-link a {
  color: var(--sage);
  text-decoration: none;
}
.admin-link a:hover {
  color: var(--olive-deep);
  text-decoration: underline;
}

/* ---------- Sections ---------- */

main {
  width: min(var(--page), 100%);
  margin-inline: auto;
  padding: 0 var(--gutter);
}

.block {
  max-width: var(--measure);
  padding: clamp(1.5rem, 3.5vw, 2.25rem) 0 0;
}

/* The hero spans the whole page column, so the sections under it do too and the edges line
   up. Running text still stops at the reading measure rather than stretching to 95 characters. */
.home .block {
  max-width: none;
}
.home .block p {
  max-width: var(--measure);
}
.block:focus {
  outline: none;
}

h2 {
  margin: 0 0 1rem;
  font: 400 clamp(2.2rem, 5.5vw, 3rem) / 1.1 var(--display);
  color: var(--ink);
}

h3 {
  margin: 0 0 0.25rem;
  font-family: var(--display);
  font-size: 1.3rem;
  font-weight: 600;
  color: var(--ink);
}

.lead {
  margin: 0 0 1.75rem;
  font-size: 1.15rem;
}

.muted {
  color: color-mix(in srgb, var(--ink) 62%, var(--paper));
}

.actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin: 1.25rem 0;
}

.map {
  margin-top: 2.5rem;
  /* Portrait-ish while the column is narrow; a banner once it is wide, so a full-width
     map does not become a 500px-tall slab. */
  aspect-ratio: 4 / 3;
  border: 1px solid var(--line);
  border-radius: 2px;
  overflow: hidden;
  background: color-mix(in srgb, var(--line) 50%, var(--paper));
}
.map iframe {
  width: 100%;
  height: 100%;
  border: 0;
  display: block;
}
@media (min-width: 34rem) {
  .map {
    aspect-ratio: 16 / 9;
  }
}

/* A hairline flourish between sections, in place of the old horizon band. */
.rule {
  display: block;
  width: min(var(--page), 100%);
  margin: clamp(3rem, 8vw, 4.5rem) auto 0;
  height: 1px;
  border: 0;
  background: linear-gradient(to right, transparent, var(--line) 25%, var(--line) 75%, transparent);
}

/* ---------- Buttons and fields ---------- */

.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 2.9rem;
  padding: 0.55rem 1.4rem;
  border: 1px solid var(--olive);
  border-radius: 2px;
  background: var(--olive);
  color: var(--paper);
  font: 500 1.05rem / 1.2 var(--body);
  letter-spacing: 0.04em;
  text-decoration: none;
  cursor: pointer;
}
.button:hover {
  background: var(--olive-deep);
  border-color: var(--olive-deep);
}
.button-quiet {
  background: transparent;
  color: var(--olive-deep);
  border-color: var(--line);
}
.button-quiet:hover {
  background: color-mix(in srgb, var(--olive) 8%, transparent);
  border-color: var(--olive);
}
.button[disabled] {
  opacity: 0.6;
  cursor: progress;
}

@media (max-width: 34rem) {
  .actions {
    flex-direction: column;
  }
  .actions .button,
  .submit-row .button {
    width: 100%;
  }
}

label.field {
  display: block;
  margin-top: 1rem;
  font-weight: 500;
}
label.field .hint {
  font-weight: 400;
}

input[type="text"],
input[type="password"],
textarea {
  display: block;
  width: 100%;
  margin-top: 0.35rem;
  padding: 0.65rem 0.85rem;
  border: 1px solid var(--line);
  border-radius: 2px;
  background: #fffdf8;
  color: var(--ink);
  font: inherit;
}
input:focus,
textarea:focus {
  border-color: var(--olive);
  outline: none;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--olive) 22%, transparent);
}
textarea {
  min-height: 6rem;
  resize: vertical;
}

/* Both Garamonds default to oldstyle figures, which is lovely on the invitation but turns
   1 and 0 into I and O wherever a number has to be read exactly. */
.admin,
.code-input,
.summary,
code {
  font-variant-numeric: lining-nums tabular-nums;
}

.code-input {
  font-family: var(--display);
  font-size: 1.5rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  max-width: 16rem;
}

/* ---------- RSVP ---------- */

.party-name {
  margin-bottom: 0.25rem;
}

.guest {
  margin: 0;
  padding: 1.5rem 0;
  border: 0;
  border-bottom: 1px solid var(--line);
}
.guest:first-of-type {
  border-top: 1px solid var(--line);
  margin-top: 1.5rem;
}
.guest legend {
  float: left;
  width: 100%;
  padding: 0;
  margin-bottom: 0.75rem;
  font-family: var(--display);
  font-weight: 600;
  font-size: 1.3rem;
  color: var(--ink);
}

.choice {
  clear: both;
  display: flex;
  gap: 0.5rem;
  flex-wrap: wrap;
}
.choice label {
  position: relative;
}
.choice input {
  position: absolute;
  opacity: 0;
  inset: 0;
  margin: 0;
  cursor: pointer;
}
.choice span {
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
  padding: 0.5rem 1.2rem;
  border: 1px solid var(--line);
  border-radius: 2px;
  background: #fffdf8;
}
.choice input:checked + span {
  background: var(--olive);
  border-color: var(--olive);
  color: var(--paper);
}
.choice input:focus-visible + span {
  outline: 2px solid var(--olive);
  outline-offset: 2px;
}

.form-error {
  margin: 1rem 0 0;
  padding: 0.75rem 1rem;
  border-left: 3px solid var(--error);
  background: color-mix(in srgb, var(--error) 7%, var(--paper));
  color: var(--error);
}

.submit-row {
  margin-top: 2rem;
}

.summary {
  list-style: none;
  margin: 1.5rem 0;
  padding: 0;
  border-top: 1px solid var(--line);
}
.summary li {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.85rem 0;
  border-bottom: 1px solid var(--line);
}
.summary .status {
  color: var(--olive-deep);
  font-weight: 500;
  white-space: nowrap;
}

/* ---------- Footer ---------- */

.footer {
  width: min(var(--page), 100%);
  margin-inline: auto;
  padding: 2rem var(--gutter) calc(1.75rem + env(safe-area-inset-bottom));
  font-size: 1rem;
}
.footer p {
  max-width: var(--measure);
  margin: 0;
  color: color-mix(in srgb, var(--ink) 62%, var(--paper));
}

/* ---------- Admin ---------- */

/* The admin tables are wider than the reading measure, so that page widens the page column. */
.admin {
  --page: 64rem;
}
.admin main {
  padding-top: 2rem;
}
.admin .block {
  max-width: none;
  padding-top: 0;
}
.admin h3 {
  margin-top: 2.5rem;
}

.login {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 1rem;
  align-items: flex-end;
}
.login .field {
  flex: 1 1 16rem;
  margin: 0;
}
@media (max-width: 34rem) {
  .login .button {
    width: 100%;
  }
}

.settings-form {
  max-width: 44rem;
}
.settings-fields {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 1rem;
}
.settings-fields .field {
  flex: 1 1 13rem;
  margin: 0;
}
.settings-form input {
  display: block;
  width: 100%;
  margin-top: 0.35rem;
  padding: 0.6rem 0.7rem;
  border: 1px solid var(--line);
  border-radius: 2px;
  background: #fffdf8;
  color: var(--ink);
  font: inherit;
  font-variant-numeric: lining-nums;
}
.settings-note {
  margin: 0.75rem 0 0;
  font-size: 0.95rem;
}
.saved-note {
  align-self: center;
  color: var(--olive-deep);
}

.email-row {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 0.5rem;
  align-items: center;
  margin-top: 0.5rem;
}
.email-row input {
  margin-top: 0;
}
.emails {
  margin-top: 2rem;
}
.emails h3 {
  margin-bottom: 0.25rem;
}
.emails .button-small {
  margin-top: 0.75rem;
}
.email-input {
  display: block;
  width: 100%;
  padding: 0.65rem 0.85rem;
  border: 1px solid var(--line);
  border-radius: 2px;
  background: #fffdf8;
  color: var(--ink);
  font: inherit;
}
.email-input:focus {
  border-color: var(--olive);
  outline: none;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--olive) 22%, transparent);
}

.email-list {
  list-style: none;
  margin: 0.35rem 0 0;
  padding: 0;
  font-size: 0.9rem;
}
.email-list li {
  overflow-wrap: anywhere;
  color: color-mix(in srgb, var(--ink) 70%, var(--paper));
}

.add-form {
  max-width: var(--measure);
}
.guest-rows {
  margin: 1rem 0 0;
  padding: 0;
  border: 0;
}
.guest-rows legend {
  padding: 0;
  font-weight: 500;
}
.guest-rows .hint {
  font-weight: 400;
}
.guest-row {
  display: grid;
  grid-template-columns: 1fr auto auto;
  gap: 0.5rem;
  align-items: center;
  margin-top: 0.5rem;
}
.guest-row input,
.guest-row select {
  margin-top: 0;
}
.guest-row select {
  padding: 0.65rem 0.6rem;
  border: 1px solid var(--line);
  border-radius: 2px;
  background: #fffdf8;
  color: var(--ink);
  font: inherit;
}
@media (max-width: 34rem) {
  .guest-row {
    grid-template-columns: 1fr 1fr;
  }
  .guest-row input {
    grid-column: 1 / -1;
  }
}
#add-guest-row {
  margin-top: 0.75rem;
}
.tag {
  display: inline-block;
  padding: 0 0.45rem;
  border-radius: 999px;
  background: color-mix(in srgb, var(--olive) 18%, var(--paper));
  color: var(--olive-deep);
  font-size: 0.8rem;
  font-weight: 500;
  vertical-align: middle;
}
.add-success {
  margin: 1rem 0 0;
  padding: 0.75rem 1rem;
  border-left: 3px solid var(--olive);
  background: color-mix(in srgb, var(--olive) 9%, var(--paper));
  overflow-wrap: anywhere;
}
.add-success code {
  font-size: 0.95rem;
}

.stats-group {
  margin-top: 1.5rem;
}
.stats-label {
  margin: 0 0 0.5rem;
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--sage);
}
.stats {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem 2rem;
}
.stats div {
  font-size: 0.95rem;
}
.stats strong {
  display: block;
  font: 400 2.75rem / 1 var(--display);
  /* Must come after the font shorthand, which resets font-variant. */
  font-variant-numeric: lining-nums tabular-nums;
  color: var(--olive-deep);
}

.filters {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 1rem;
  align-items: flex-end;
  margin-top: 0.5rem;
}
.filters .field {
  flex: 1 1 10rem;
  margin: 0;
}
.filters .field:first-child {
  flex-basis: 16rem;
}
.filters input,
.filters select {
  margin-top: 0.35rem;
}
.filters select,
input[type="search"] {
  display: block;
  width: 100%;
  padding: 0.65rem 0.85rem;
  border: 1px solid var(--line);
  border-radius: 2px;
  background: #fffdf8;
  color: var(--ink);
  font: inherit;
}
.filters select:focus {
  border-color: var(--olive);
  outline: none;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--olive) 22%, transparent);
}
.filter-summary {
  margin: 0.75rem 0 0.5rem;
  font-size: 0.95rem;
}
@media (max-width: 34rem) {
  .filters {
    flex-direction: column;
    align-items: stretch;
  }
  .filters .field {
    flex-basis: auto;
  }
}
.table-wrap {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  border-top: 1px solid var(--line);
}
table {
  width: 100%;
  border-collapse: collapse;
  font-size: 1rem;
}
th,
td {
  text-align: left;
  padding: 0.75rem 1rem 0.75rem 0;
  border-bottom: 1px solid var(--line);
  vertical-align: top;
}
th {
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  font-size: 0.8rem;
  color: var(--sage);
  white-space: nowrap;
}

.guest-list {
  list-style: none;
  margin: 0;
  padding: 0;
  min-width: 14rem;
}
.guest-list li {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.15rem 0;
}
.guest-list .status {
  font-weight: 500;
  white-space: nowrap;
}
.status-yes {
  color: var(--olive-deep);
}
.status-no {
  color: var(--error);
}
.status-waiting {
  color: color-mix(in srgb, var(--ink) 48%, var(--paper));
}

.link-cell {
  white-space: nowrap;
}
.link-cell code {
  display: block;
  margin-bottom: 0.4rem;
  font-size: 0.95rem;
  letter-spacing: 0.08em;
}
.button-danger {
  border-color: color-mix(in srgb, var(--error) 40%, var(--line));
  color: var(--error);
  background: transparent;
}
.button-danger:hover {
  background: color-mix(in srgb, var(--error) 8%, transparent);
  border-color: var(--error);
}
.button-small {
  min-height: 2.25rem;
  padding: 0.3rem 0.85rem;
  font-size: 0.9rem;
}
