:root {
  --bg: #070a17;
  --panel: rgb(255 255 255 / 0.04);
  --border: rgb(255 255 255 / 0.1);
  /* Stronger, so that fields stand out from what is around them. */
  --field-border: rgb(255 255 255 / 0.35);
  --text: #e8eaf6;
  --muted: #9aa0c3;
  --accent: #ffd36e;
  --radius: 14px;
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  line-height: 1.5;
  color: var(--text);
}

* {
  box-sizing: border-box;
}

:root {
  /* The page's sky, also behind what stays in view while scrolling. */
  --sky:
    radial-gradient(1px 1px at 12% 18%, #fff8, transparent),
    radial-gradient(1px 1px at 72% 8%, #fff6, transparent),
    radial-gradient(1.5px 1.5px at 38% 62%, #fff5, transparent),
    radial-gradient(1px 1px at 88% 44%, #fff7, transparent),
    radial-gradient(1px 1px at 22% 84%, #fff5, transparent),
    radial-gradient(1.5px 1.5px at 58% 32%, #fff4, transparent),
    radial-gradient(ellipse at top, #1a2150 0%, var(--bg) 60%);
}

body {
  margin: 0;
  min-height: 100vh;
  background: var(--sky);
  background-attachment: fixed;
  background-color: var(--bg);
}

.top,
main {
  max-width: 960px;
  margin: 0 auto;
  padding: 0 16px;
}

.top {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas:
    "title actions"
    "tagline tagline";
  gap: 4px 12px;
  align-items: center;
  padding-top: 32px;
}

.top h1 {
  grid-area: title;
  justify-self: start;
  max-width: 100%;
}

.tagline {
  grid-area: tagline;
}

h1 {
  display: flex;
  align-items: center;
  gap: 0.3em;
  margin: 0;
  /* Shrinks on narrow screens, so the name fits beside the buttons: it is
     about 9 em wide, with the logo, and the buttons and gutters about
     143 px. */
  font-size: clamp(1rem, (100vw - 143px) / 9.5, 3rem);
  letter-spacing: -0.02em;
  background: linear-gradient(90deg, var(--accent), #ff8fa3, #8fa8ff);
  background-clip: text;
  color: transparent;
}

.logo {
  width: 1.7em;
  height: 1.7em;
  margin-left: -0.1em;
}

.tagline {
  margin: 0;
  color: var(--muted);
}

select,
input {
  font: inherit;
  color: var(--text);
  background: var(--panel);
  border: 1px solid var(--field-border);
  border-radius: 8px;
  padding: 8px 10px;
}

select option {
  background: var(--bg);
}

input:focus-visible,
select:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.form {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 20px;
  margin: 32px 0;
  padding: 20px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}

/* One row on wide screens, with fixed widths so the fields do not move
   with the length of each language's text. */
@media (min-width: 720px) {
  .form {
    grid-template-columns: 15rem 11rem 1fr;
    column-gap: 32px;
  }
}

.form [hidden] {
  display: none;
}

.field {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-weight: 600;
}

.field input:not([type="checkbox"]) {
  width: 100%;
  min-width: 0;
  min-height: 42px;
}

/* Safari on iOS gives date and time inputs a native width, wider than a
   phone's column, and centers their value. */
input[type="date"],
input[type="time"] {
  -webkit-appearance: none;
  appearance: none;
  display: block;
}

input::-webkit-date-and-time-value {
  text-align: left;
}

.field small {
  color: var(--muted);
  font-weight: normal;
}

.notice {
  color: var(--muted);
  text-align: center;
  padding: 24px 0;
}

/* Shown instead, by the page written before the app ran, while a link's
   date of birth waits for it. */
.loader {
  display: none;
  align-items: center;
  justify-content: center;
  gap: 12px;
  margin: 32px 0 0;
  color: var(--muted);
}

main.loading .loader {
  display: flex;
}

main.loading :is(.hook, .notice) {
  display: none;
}

.spinner {
  width: 20px;
  height: 20px;
  border: 2px solid var(--border);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}

@media (prefers-reduced-motion: reduce) {
  .spinner {
    animation-duration: 2.4s;
  }
}

@keyframes spin {
  to {
    transform: rotate(1turn);
  }
}

.hook {
  margin: 32px 0 0;
  text-align: center;
  font-size: 1.25rem;
  font-weight: 600;
}

.hook + .notice {
  padding-top: 8px;
}

.cards {
  display: grid;
  /* Wide enough for the longest full date: Portuguese, about 362px. */
  grid-template-columns: repeat(auto-fill, minmax(min(400px, 100%), 1fr));
  gap: 16px;
}

.card {
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding: 16px 20px 14px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-top: 3px solid var(--planet);
  border-radius: var(--radius);
}

.card.today {
  border-color: var(--accent);
  box-shadow: 0 0 24px rgb(255 211 110 / 0.25);
}

/* Name on the left, orbit in the corner. */
.card header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 12px;
  min-height: 64px;
}

.card .title {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 10px;
  padding-top: 4px;
}

.card h2 {
  margin: 0;
  font-size: 1.3rem;
}

.planet {
  flex: none;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 35%, #fff9, var(--planet) 45%, #0008 120%);
}

.card .title .planet {
  width: 18px;
  height: 18px;
}

.badge {
  font-size: 0.75rem;
  color: var(--muted);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 0 8px;
}

.orbit {
  flex: none;
  width: 64px;
  height: 64px;
}

.orbit .track {
  fill: none;
  stroke: var(--border);
  stroke-width: 1.5;
}

.orbit .arc {
  fill: none;
  stroke: var(--planet);
  stroke-width: 2;
  stroke-linecap: round;
  opacity: 0.7;
}

.orbit .start {
  stroke: var(--accent);
  stroke-width: 1.5;
}

.orbit .sun {
  fill: var(--accent);
}

.orbit .body {
  fill: var(--planet);
}

.milestone {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.milestone + .milestone {
  padding-top: 14px;
  border-top: 1px dashed var(--border);
}

.age {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
  margin: 0;
}

.label {
  color: var(--muted);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.age .value {
  font-size: 1.6rem;
  font-weight: 700;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
}

/* Progress towards the next birthday. */
.progress {
  height: 4px;
  overflow: hidden;
  background: var(--border);
  border-radius: 999px;
}

.progress span {
  display: block;
  height: 100%;
  background: var(--planet);
  border-radius: inherit;
}

.fact {
  font-style: italic;
}

.happy {
  margin: 0;
  color: var(--accent);
  font-weight: 700;
}

.next {
  display: grid;
  grid-template-columns: 20px 1fr;
  gap: 10px;
  align-items: start;
  margin: 2px 0 0;
}

.next-icon {
  display: grid;
  color: var(--planet);
  padding-top: 1px;
}

.next-icon .icon {
  width: 20px;
  height: 20px;
}

.next .date {
  display: block;
}

.date::first-letter {
  text-transform: uppercase;
}

.next .when {
  display: block;
  color: var(--muted);
  font-size: 0.9rem;
}

.period {
  display: flex;
  flex-direction: column;
  margin: auto 0 0;
  padding-top: 10px;
  border-top: 1px solid var(--border);
  color: var(--muted);
  font-size: 0.8rem;
}

h2 {
  margin: 48px 0 16px;
}

/* Clipped rather than scrolled, so the header can stay in view. */
.upcoming .table {
  overflow: clip;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--panel);
}

.upcoming table {
  width: 100%;
  border-collapse: collapse;
}

.upcoming th,
.upcoming td {
  padding: 12px 16px;
  text-align: left;
  white-space: nowrap;
}

.upcoming thead th {
  position: sticky;
  top: calc(var(--stage-height, 0px) + var(--name-height, 0px));
  z-index: 1;
  color: var(--muted);
  font-size: 0.85rem;
  font-weight: 600;
  background: #10142a;
  box-shadow: inset 0 -1px var(--border);
}

/* Not over the image's options while they are open, which would leave
   them under it. */
body:has(#image-controls:not([hidden])) .upcoming thead th {
  position: static;
}

.upcoming tbody tr + tr {
  border-top: 1px solid var(--border);
}

.upcoming tr.year th {
  padding-top: 10px;
  padding-bottom: 6px;
  color: var(--accent);
  font-size: 0.85rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  background: rgb(255 255 255 / 0.03);
}

.upcoming tbody + tbody tr.year {
  border-top: 1px solid var(--border);
}

.upcoming tbody th .planet {
  display: inline-block;
  margin-right: 8px;
  vertical-align: -1px;
}

/* Rows choose the birthday on the image. */
.upcoming tbody tr:not(.year) {
  cursor: pointer;
}

.upcoming tbody tr:not(.year):hover {
  background: rgb(255 255 255 / 0.03);
}

.upcoming tr.selected {
  background: color-mix(in srgb, var(--planet) 14%, transparent);
}

.upcoming tr.selected th {
  box-shadow: inset 3px 0 var(--planet);
}

.pick {
  display: inline-flex;
  align-items: center;
  padding: 0;
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  cursor: pointer;
}

.pick:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* Scrolled to on focus below what stays in view above them: the image, its
   name and the table's header. */
.upcoming button,
.more {
  scroll-margin-top: calc(var(--stage-height, 0px) + var(--name-height, 0px) + 48px);
}

.image-controls :is(input, select, button) {
  scroll-margin-top: calc(var(--stage-height, 0px) + 16px);
}

.upcoming .when {
  color: var(--muted);
  text-align: right;
}

@media (max-width: 600px) {
  .upcoming table {
    font-size: 0.85rem;
  }

  .upcoming th,
  .upcoming td {
    padding: 10px 6px;
  }

  .upcoming td {
    white-space: normal;
  }

  .upcoming tbody th .planet {
    margin-right: 6px;
  }
}

/* A round button with an icon. */
.icon-button {
  display: grid;
  place-items: center;
  flex: none;
  width: 36px;
  height: 36px;
  padding: 0;
  color: var(--text);
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 50%;
  cursor: pointer;
  transition: color 0.15s, border-color 0.15s;
}

.icon-button:hover {
  color: var(--accent);
  border-color: var(--accent);
}

.icon-button:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

.icon-button .icon {
  width: 16px;
  height: 16px;
}

.upcoming td.calendar-cell {
  width: 1px;
  padding-top: 6px;
  padding-bottom: 6px;
}

/* Dialogs, as the help. */
.dialog {
  width: min(32rem, calc(100vw - 32px));
  padding: 0;
  color: var(--text);
  background: #11162e;
  border: 1px solid var(--border);
  border-radius: var(--radius);
}

.dialog::backdrop {
  background: rgb(0 0 0 / 0.6);
}

.sheet {
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding: 16px 20px 20px;
}

.sheet header {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.sheet h2 {
  margin: 0;
  font-size: 1.2rem;
}

.help-dialog {
  width: min(44rem, calc(100vw - 32px));
  max-height: calc(100vh - 64px);
  overflow: hidden;
}

/* The title and its close button stay in view over the text, which scrolls
   below them. Not `position: sticky`, whose buttons Safari does not always
   let be clicked. */
.help-dialog .sheet {
  box-sizing: border-box;
  max-height: calc(100vh - 64px - 2px);
}

.help-dialog .model {
  min-height: 0;
  overflow-y: auto;
}

.help-dialog .model:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.model h3 {
  margin: 24px 0 6px;
  font-size: 1.05rem;
}

.model h3:first-child {
  margin-top: 0;
}

.model p {
  margin: 0 0 10px;
  color: #c8cbe4;
  text-align: justify;
  hyphens: auto;
}

main {
  padding-bottom: 48px;
}

.birth-date .hint {
  margin-top: 2px;
}

/* An input with a button to its right. */
.with-button {
  display: flex;
  align-items: center;
  gap: 8px;
}

.with-button input {
  flex: 1;
}

.with-button .icon-button {
  width: 42px;
  height: 42px;
}

.hint {
  color: var(--muted);
  font-size: 0.8rem;
}

.switches {
  display: grid;
  margin-top: 6px;
  font-weight: 400;
  grid-template-columns: max-content max-content;
  align-items: center;
  gap: 8px 6px;
}

/* Rows share the grid's columns, so the info buttons line up. */
.switch-row {
  position: relative;
  display: grid;
  grid-column: 1 / -1;
  grid-template-columns: subgrid;
  align-items: center;
}

.switch {
  display: flex;
  align-items: center;
  gap: 10px;
  cursor: pointer;
}

.switch input {
  appearance: none;
  position: relative;
  flex: none;
  width: 40px;
  height: 22px;
  padding: 0;
  border-radius: 999px;
  cursor: pointer;
  transition: background 0.15s;
}

.switch input::before {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--muted);
  transition: transform 0.15s, background 0.15s;
}

.switch input:checked {
  background: rgb(255 211 110 / 0.25);
  border-color: var(--accent);
}

.switch input:checked::before {
  transform: translateX(18px);
  background: var(--accent);
}

/* Language menu. */

.top-actions {
  grid-area: actions;
  display: flex;
  align-items: center;
  gap: 4px;
}

.help {
  display: grid;
  place-items: center;
  padding: 6px 8px;
  color: var(--muted);
  background: none;
  border: 0;
  border-radius: 8px;
  cursor: pointer;
}

.help .icon {
  width: 1.6rem;
  height: 1.6rem;
}

.help:hover {
  color: var(--text);
  background: var(--panel);
}

.help:focus-visible {
  outline: 2px solid var(--accent);
}

.lang {
  position: relative;
}

.lang summary {
  list-style: none;
  cursor: pointer;
  font-size: 1.8rem;
  line-height: 1;
  padding: 6px 8px;
  border-radius: 8px;
}

.lang summary::-webkit-details-marker {
  display: none;
}

.lang summary:hover,
.lang[open] summary {
  background: var(--panel);
}

.lang summary:focus-visible {
  outline: 2px solid var(--accent);
}

.lang ul {
  position: absolute;
  right: 0;
  z-index: 1;
  min-width: 11rem;
  margin: 4px 0 0;
  padding: 6px;
  list-style: none;
  background: #121735;
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: 0 8px 24px rgb(0 0 0 / 0.4);
}

.lang button {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  font: inherit;
  color: var(--text);
  text-align: left;
  background: none;
  border: 0;
  border-radius: 6px;
  padding: 6px 10px;
  cursor: pointer;
}

.lang button:hover,
.lang button:focus-visible {
  background: var(--panel);
}

.lang button:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}

.lang button[aria-current="true"] {
  color: var(--accent);
}

.flag {
  font-size: 1.3em;
}

/* Tabs. */

.tabs {
  display: flex;
  gap: 4px;
  margin-bottom: 20px;
  border-bottom: 1px solid var(--border);
  overflow-x: auto;
  scrollbar-width: none;
}

.tabs button {
  font: inherit;
  font-weight: 600;
  color: var(--muted);
  background: none;
  border: 0;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  padding: 10px 14px;
  white-space: nowrap;
  cursor: pointer;
}

.tabs button:hover {
  color: var(--text);
}

.tabs button[aria-selected="true"] {
  color: var(--text);
  border-bottom-color: var(--accent);
}

.tabs button:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
  border-radius: 6px 6px 0 0;
}

/* On phones, the two tabs share the row equally, wrapping long labels. */
@media (max-width: 720px) {
  .tabs {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0;
  }

  .tabs button {
    padding: 10px 8px;
    white-space: normal;
    line-height: 1.25;
  }
}

.more {
  display: block;
  margin: 12px auto 0;
  font: inherit;
  color: var(--text);
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 6px 16px;
  cursor: pointer;
}

.more:hover {
  border-color: var(--accent);
}

/* Unit explanations. */

.info button {
  display: grid;
  place-items: center;
  padding: 4px;
  color: var(--muted);
  background: none;
  border: 0;
  border-radius: 50%;
  cursor: help;
}

.info button:hover,
.info button:focus-visible {
  color: var(--accent);
}

.info button:focus-visible {
  outline: 2px solid var(--accent);
}

.info .icon {
  width: 16px;
  height: 16px;
}

.info [role="tooltip"] {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  z-index: 1;
  width: max-content;
  max-width: min(18rem, calc(100vw - 64px));
  padding: 8px 12px;
  font-size: 0.85rem;
  font-weight: normal;
  line-height: 1.4;
  color: var(--text);
  background: #121735;
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 8px 24px rgb(0 0 0 / 0.4);
  visibility: hidden;
  opacity: 0;
  transition: opacity 0.15s, visibility 0.15s;
}

/* Beside other fields on wide screens, the units are near the right edge,
   so their explanations open to the left. */
@media (min-width: 720px) {
  .info [role="tooltip"] {
    right: 0;
    left: auto;
  }
}

.info:hover [role="tooltip"],
.info:focus-within [role="tooltip"] {
  visibility: visible;
  opacity: 1;
}

/* Until the pointer or focus comes back, after Escape. */
.info.dismissed [role="tooltip"] {
  visibility: hidden;
  opacity: 0;
}

/* Image to share, above the upcoming birthdays. Its section has no box, so
   that the image and its name stay in view while scrolling the table, with
   the table's header below them. */

.image {
  display: contents;
}

.image-stage {
  position: sticky;
  top: 0;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 8px 0;
  background: var(--sky);
  background-attachment: fixed;
  background-color: var(--bg);
}

/* Always shown, above the rest of the options. */
.image-name {
  position: sticky;
  top: var(--stage-height, 0);
  z-index: 2;
  padding: 8px 2px 16px;
  background: var(--sky);
  background-attachment: fixed;
  background-color: var(--bg);
}

/* Only the image stays in view while the options are open, which scroll
   with the page. */
body:has(#image-controls:not([hidden])) .image-name {
  position: static;
}

.image-controls {
  /* Scrolled to when opened, below the image. */
  scroll-margin-top: calc(var(--stage-height, 0px) + 16px);
  display: flex;
  flex-direction: column;
  gap: 24px;
  margin-bottom: 16px;
  padding: 2px;
}

.image-controls[hidden] {
  display: none;
}

.image-frame {
  position: relative;
  max-width: 100%;
}

.image-preview {
  display: block;
  max-width: 100%;
  max-height: 42vh;
  border: 1px solid var(--border);
  border-radius: var(--radius);
}

@media (min-width: 900px) {
  .image-preview {
    max-height: 45vh;
  }
}

.image-buttons {
  position: absolute;
  right: 8px;
  bottom: 8px;
  display: flex;
  gap: 8px;
}

.image-buttons .icon-button {
  width: 40px;
  height: 40px;
  background: rgb(7 10 23 / 0.7);
}

/* Formats, on the image's top right corner. */
.format-switch {
  position: absolute;
  top: 8px;
  right: 8px;
  display: flex;
  gap: 2px;
  padding: 3px;
  background: rgb(7 10 23 / 0.7);
  border: 1px solid var(--border);
  border-radius: 999px;
}

.format-switch button {
  display: grid;
  place-items: center;
  min-width: 36px;
  height: 30px;
  padding: 0 8px;
  color: var(--muted);
  background: none;
  border: 1px solid transparent;
  border-radius: 999px;
  cursor: pointer;
  transition: color 0.15s, border-color 0.15s;
}

.format-switch button:hover {
  color: var(--text);
}

.format-switch button[aria-pressed="true"] {
  color: var(--accent);
  border-color: var(--accent);
}

.format-switch button:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

/* Outlines with each format's proportions. */
.shape {
  display: block;
  height: 14px;
  border: 1.5px solid currentColor;
  border-radius: 2px;
}

.shape-0 {
  aspect-ratio: 1200 / 630;
}

.shape-1 {
  aspect-ratio: 1;
}

.shape-2 {
  aspect-ratio: 1080 / 1920;
}

/* Above the image's buttons. */
.image-buttons .toast {
  position: absolute;
  right: 0;
  bottom: calc(100% + 8px);
  width: max-content;
  max-width: 16rem;
  padding: 6px 10px;
  font-size: 0.85rem;
  color: var(--text);
  background: rgb(7 10 23 / 0.85);
  border: 1px solid var(--accent);
  border-radius: 8px;
}

/* Hidden, but still announced when it says something. */
.image-buttons .toast:empty {
  padding: 0;
  border: 0;
}

.image-buttons .icon-button[aria-expanded="true"] {
  color: var(--accent);
  border-color: var(--accent);
}

.image-buttons .icon-button .icon {
  width: 18px;
  height: 18px;
}

.image-controls select,
.image-controls input,
.image-name input {
  width: 100%;
  min-height: 42px;
}

.image-controls input[type="range"] {
  min-height: 0;
  border-color: var(--border);
  accent-color: var(--accent);
}

/* The text's options beside the scene's. */
.image-columns {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
  align-items: start;
}

.image-column {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.image-controls small {
  color: var(--muted);
}
