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

html,
body {
  margin: 0;
  padding: 0;
}

button {
  font: inherit;
  color: inherit;
  background: transparent;
  border: 0;
  cursor: pointer;
}

input {
  font: inherit;
  color: inherit;
}

#app {
  min-height: 100vh;
}

.site-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: nowrap;
  gap: 1rem;
}

.header-controls {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: nowrap;
}

.theme-picker {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
}

.theme-select {
  font: inherit;
  color: inherit;
}

/* The Home control is an anchor sitting among buttons. Strip the link
 * decoration so themes that style `.home-btn, .about-btn, .edit-btn` as a set
 * get a consistent result without knowing it is a different element. */
.home-btn {
  font: inherit;
  color: inherit;
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
}

.share-btn {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  padding: 0;
  margin: 0;
  text-decoration: underline;
  cursor: pointer;
}

.share-btn--ok {
  text-decoration: none;
  opacity: 0.7;
}

/* Decorative effects layer. Themes paint into ::before / ::after. */
.theme-fx {
  position: fixed;
  inset: 0;
  pointer-events: none;
  overflow: hidden;
  z-index: 0;
}

/* Keep page content above .theme-fx. The :not() guards against this rule
   demoting .theme-fx itself out of position:fixed. */
#app > *:not(.theme-fx) { position: relative; z-index: 1; }

@media (prefers-reduced-motion: reduce) {
  .theme-fx, .theme-fx::before, .theme-fx::after { animation: none !important; }
  .person.is-bumping { animation: none !important; }
}

.site-cross-link {
  margin-bottom: 1.5rem;
}

.site-stats {
  display: flex;
  flex-wrap: wrap;
  gap: 1.25rem;
  margin-top: 0.5rem;
}

.people {
  display: flex;
  flex-direction: column;
}

.person {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}

.person-name {
  font-size: 1rem;
  opacity: 0.7;
}

.version {
  /* Hook 1. Seven themes used to !important their way past a hard-coded clamp;
     that was a missing hook, not seven sloppy authors. Themes set the custom
     property instead. */
  font-size: var(--version-size, clamp(3.5rem, 10vw, 6.5rem));
  font-weight: 800;
  line-height: var(--version-leading, 1);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.03em;
}

/* Hook 4. The number is split one span per character so a theme can treat each
   glyph as an object — a nixie tube, a split-flap, a bulb in a matrix. Core
   gives .digit the minimum that makes that possible and .sep nothing at all;
   the rest belongs to the theme. .version carries an aria-label so screen
   readers announce one number rather than six fragments. */
.digit {
  display: inline-block;
}

/* Adjacent inline-blocks give the line breaker somewhere to break, which a
   single text node never did — without this the number splits mid-value
   ("4.7." / "150") in any theme narrow enough to wrap. Pseudo-elements opt
   back out, because several themes put prose in them that must still wrap. */
.version {
  white-space: nowrap;
}

.version::before,
.version::after {
  white-space: normal;
}

/* Portrait mode for the link preview: the renderer photographs the real page,
   so all it needs is the card, centred, with the furniture out of the way. */
body[data-og] .site-header,
body[data-og] .site-footer,
body[data-og] .countdown ~ .site-footer {
  display: none;
}

body[data-og] #app {
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: 630px;
}

/* A card page has exactly one person and nothing to configure. */
body[data-card] .add-btn,
body[data-card] .theme-picker,
body[data-card] .edit-btn {
  display: none;
}

/* Card block default. Every theme styles this in its own voice, but a plain,
   correct fallback means a half-finished theme still reads. */
.card-message {
  margin-top: 1.5rem;
  padding: 1rem 1.1rem;
  border: 1px solid currentColor;
  border-radius: 4px;
  max-width: 34rem;
}

.card-recipient {
  margin: 0 0 0.5rem;
  font-size: 0.85rem;
  opacity: 0.7;
}

.card-note {
  margin: 0;
  font-size: 1rem;
  line-height: 1.6;
  overflow-wrap: break-word;
}

.card-from {
  margin: 0.75rem 0 0;
  font-size: 0.85rem;
  opacity: 0.7;
}

/* Hook 6 fallback. Every theme should say something of its own when a date is
   imminent; until one does, it still says it plainly. */
.countdown {
  margin-top: 0.6rem;
  font-size: 0.95rem;
  opacity: 0.75;
}

/* App-level dialogs (About, Edit). Self-contained: themes do not style these.
   Light card by default; switches to dark when the OS is in dark mode. */
.app-dialog {
  max-width: calc(100vw - 2rem);
  border: 0;
  padding: 0;
  background: transparent;
  color: inherit;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
}

.app-dialog::backdrop {
  background: rgba(0, 0, 0, 0.5);
}

.app-dialog__content {
  max-width: 540px;
  width: calc(100vw - 2rem);
  max-height: calc(100vh - 4rem);
  overflow-y: auto;
  background: #fff;
  color: #111;
  border-radius: 10px;
  padding: 1.5rem 1.75rem;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.25);
  font-family: inherit;
  font-size: 1rem;
  line-height: 1.55;
}

.app-dialog__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 0.75rem;
}

.app-dialog__title {
  font-size: 1.2rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  margin: 0;
}

.app-dialog__close {
  font-size: 1.5rem;
  line-height: 1;
  padding: 0.25rem 0.5rem;
  border-radius: 4px;
  color: #666;
}

.app-dialog__close:hover {
  background: #ececea;
  color: #111;
}

.app-dialog__body p {
  margin: 0.6rem 0;
}

.app-dialog__body ul {
  margin: 0.5rem 0 1rem;
  padding-left: 1.25rem;
}

.app-dialog__body li {
  margin-bottom: 0.4rem;
}

.app-dialog__body code {
  background: #ececea;
  padding: 0.05em 0.35em;
  border-radius: 3px;
  font-size: 0.9em;
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
}

.app-dialog__body a {
  color: #2b6cb0;
}

.app-dialog__credit,
.app-dialog__tip,
.app-dialog__privacy {
  font-size: 0.9rem;
  color: #666;
  margin-top: 1.25rem;
}

.edit-list {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin-bottom: 0.75rem;
}

.edit-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.edit-row__name,
.edit-row__date {
  font: inherit;
  color: inherit;
  background: #fff;
  border: 1px solid #d4d4d4;
  border-radius: 6px;
  padding: 0.4rem 0.6rem;
}

.edit-row__name {
  flex: 1 1 auto;
  min-width: 0;
}

/* Keep date controls readable and removal reachable on narrow screens. */
@media (max-width: 480px) {
  .app-dialog__content { padding: 1.25rem; }
  .edit-row { display: grid; grid-template-columns: minmax(0, 1fr) 44px; }
  .edit-row__name, .edit-row__date { grid-column: 1; width: 100%; min-width: 0; min-height: 44px; }
  .edit-row__remove { grid-column: 2; grid-row: 1 / span 2; min-height: 44px; }
}

/* Focus rings for the shared chrome. The edition pages do not load site.css,
   so none of this was covered and every theme fell back to whatever the browser
   drew over its own custom button fills. currentColor is the one colour each
   control is guaranteed to contrast with, so the ring adapts to all 28 themes
   without any of them having to opt in. */
.home-btn:focus-visible,
.edit-btn:focus-visible,
.about-btn:focus-visible,
.share-btn:focus-visible,
.add-btn:focus-visible,
.theme-select:focus-visible,
.edit-row__remove:focus-visible,
a:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 2px;
}

.edit-row__name:focus,
.edit-row__date:focus {
  /* A border tint on its own was the only focus signal here, on the one
     control people actually have to type into. Keep the tint, put the ring
     back. */
  outline: 2px solid #2b6cb0;
  outline-offset: 1px;
  border-color: #2b6cb0;
}

.edit-row__date {
  font-variant-numeric: tabular-nums;
}

.edit-row__remove {
  font-size: 1.25rem;
  line-height: 1;
  padding: 0.25rem 0.5rem;
  border-radius: 4px;
  color: #888;
}

.edit-row__remove:hover {
  background: #fff0f0;
  color: #c53030;
}

.edit-add {
  display: inline-block;
  padding: 0.4rem 0.85rem;
  border: 1px dashed #ccc;
  border-radius: 6px;
  color: #666;
  font-weight: 500;
}

.edit-add:hover {
  border-color: #2b6cb0;
  color: #2b6cb0;
}

@media (prefers-color-scheme: dark) {
  .app-dialog__content {
    background: #1c1c1e;
    color: #f2f2f2;
    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.6);
  }
  .app-dialog__close {
    color: #aaa;
  }
  .app-dialog__close:hover {
    background: #2a2a2d;
    color: #fff;
  }
  .app-dialog__body code {
    background: #2a2a2d;
  }
  .app-dialog__body a {
    color: #6ea8ff;
  }
  .app-dialog__credit,
  .app-dialog__tip,
  .app-dialog__privacy {
    color: #aaa;
  }
  .edit-row__name,
  .edit-row__date {
    background: #2a2a2d;
    border-color: #3a3a3d;
    color: #f2f2f2;
    color-scheme: dark;
  }
  .edit-row__name:focus,
  .edit-row__date:focus {
    border-color: #6ea8ff;
  }
  .edit-row__remove {
    color: #aaa;
  }
  .edit-row__remove:hover {
    background: #3a1d1d;
    color: #ff8585;
  }
  .edit-add {
    border-color: #3a3a3d;
    color: #aaa;
  }
  .edit-add:hover {
    border-color: #6ea8ff;
    color: #6ea8ff;
  }
}

@media (max-width: 820px) {
  .site-header { flex-wrap: wrap; }
  .header-controls { flex-wrap: wrap; }
}

@media (max-width: 480px) {
  .theme-select { max-width: 8.5rem; min-width: 0; }
}

/* Touch targets. 390px is a requirement, not a nicety, and every theme's header
   controls were landing between 27px and 42px tall. Themes set padding rather
   than height, so a min-height here reaches all 28 without touching any of
   them. Inline links in prose are deliberately not included — WCAG exempts
   them, and stretching a link inside a sentence would break the sentence. */
@media (pointer: coarse), (max-width: 480px) {
  .home-btn,
  .edit-btn,
  .about-btn,
  .theme-select,
  .add-btn {
    min-height: 44px;
  }

  /* Keep the label centred once the box is taller than its text. */
  .home-btn,
  .edit-btn,
  .about-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }

  /* The About control is a single "?" — tall enough but only 20px wide. */
  .about-btn {
    min-width: 44px;
  }
}
