:root {
  --bg: #000;
  --fg: #fff;
  --muted: #8b8b8b;
  --muted-inverted: #6a6a6a;
  --rule-inverted: #d6d6d6;
  --rule: #1e1e1e;
  --hint: #4a4a4a;
  --error: #ff5b5b;
  --accent: gold; /* the counts, the one colour on the wall */
  --accent-hover: var(--accent); /* the accent on a hovered row's background */
  --edit-hover: var(--accent-hover); /* the pencil's highlight under the pointer */
  --panel: #0b0b0b;
  --panel-rule: #262626;
  --field: #141414;
  --scrim: rgba(0, 0, 0, 0.6);
  /* A hovered row or card. Black inverts to white; the other themes say what
     they do instead. --muted-inverted and --rule-inverted go with these. */
  --hover-bg: var(--fg);
  --hover-fg: var(--bg);
  --marker: var(--fg); /* the current nav item's bar, and the prefs bars */
  --count-fg: var(--muted);
  --count-bg: transparent;
  --nav-h: 4.6rem;
  color-scheme: dark;
}

/* Themes from the 222831 / 393E46 / FFD369 / EEEEEE palette, chosen on the
   prefs page and set on <html> by the server, so a page never paints black
   first. The palette has no tone for secondary text, so --muted and --hint are
   greys mixed between its dark and light ends. */

/* Slate: the palette dark, with yellow kept for things that mean something:
   the current page and the counts. */
:root[data-theme="slate"] {
  --bg: #222831;
  --fg: #eeeeee;
  --muted: #9aa0a8;
  --muted-inverted: #b8bdc4;
  --rule: #393e46;
  --rule-inverted: #4a505a;
  --hint: #6b717a;
  --error: #ff7b72;
  --accent: #ffd369;
  --panel: #393e46;
  --panel-rule: #4a505a;
  --field: #222831;
  --hover-bg: #393e46;
  --hover-fg: #eeeeee;
  --marker: #ffd369;
  --count-fg: #ffd369;
}

/* Paper: the palette light. Yellow on #eeeeee is about 1.2:1, too faint to
   read as text, so here it is only ever a fill, behind dark text. */
:root[data-theme="paper"] {
  --bg: #eeeeee;
  --fg: #222831;
  --muted: #5c626b;
  --muted-inverted: #5c626b;
  --rule: #d3d5d8;
  --rule-inverted: #d3d5d8;
  --hint: #8a9099;
  --error: #c0392b;
  --accent: #222831;
  --edit-hover: #ffd369;
  --hover-bg: #ffffff; /* hovered rows and cards lift to white rather than invert */
  --hover-fg: #222831;
  --panel: #ffffff;
  --panel-rule: #d3d5d8;
  --field: #f6f6f6;
  --scrim: rgba(34, 40, 49, 0.35);
  --marker: #ffd369;
  --count-fg: #222831;
  --count-bg: #ffd369;
  color-scheme: light;
}

* {
  box-sizing: border-box;
}

/* The nav is fixed over the top of the page, so anything scrolled into view
   has to stop below it rather than behind it. */
html {
  background: var(--bg);
  scroll-padding-top: var(--nav-h);
}

body {
  margin: 0;
  padding: calc(var(--nav-h) + 6vh) 0 8vh;
  min-height: 100vh;
  background: var(--bg);
  color: var(--fg);
  font-family: "Instrument Sans", system-ui, sans-serif;
  -webkit-font-smoothing: antialiased;
}

/* ---------- the wall ---------- */

#links {
  border-top: 1px solid var(--rule);
}

#links:empty {
  border-top: 0;
}

.row {
  position: relative;
  display: flex;
  align-items: stretch;
  border-bottom: 1px solid var(--rule);
  transition: background 0.18s ease, color 0.18s ease;
}

.row:hover {
  background: var(--hover-bg);
  color: var(--hover-fg);
}

/* Pasting a link you already have points at the row instead of adding one. */
.row[data-flash] {
  animation: flash 1.2s ease;
}

@keyframes flash {
  0%, 55% { background: var(--rule); }
  100% { background: none; }
}

@media (prefers-reduced-motion: reduce) {
  .row[data-flash] {
    animation-duration: 0.01s;
  }
}

/* The padding lives here rather than on .row so the anchor covers the whole
   row: the gutters and the space above and below the text are all clickable. */
.link {
  display: flex;
  flex: 1 1 auto;
  align-items: center;
  --gap: 2.5rem;
  gap: var(--gap);
  min-width: 0;
  padding: 1.85rem 5.2vw;
  color: inherit;
  text-decoration: none;
}

/* A visited link is styled no differently, so :visited needs no rule. */
.row:hover .link,
.link:focus-visible {
  color: inherit;
  outline: none;
}

/* A title can be a whole URL, so it still truncates when it alone overflows
   the row. Otherwise it never shrinks and the description gives way instead:
   even a sub-pixel squeeze would put an ellipsis on a title that fits. The
   max-width leaves the gap, so a capped title does not push past the edge. */
.title {
  display: flex;
  flex: 0 0 auto;
  max-width: calc(100% - var(--gap));
  min-width: 0;
  overflow: hidden;
  font-family: "Cal Sans", system-ui, sans-serif;
  font-size: clamp(1.5rem, 2.5vw, 3.5rem);
  line-height: 1.05;
  /* overflow:hidden is here for the ellipsis, but it also clips to the line
     box, which at this line-height stops 0.175em below the baseline while
     Cal Sans descends 0.213em. Pad the clip box down and pull the margin box
     back up, so descenders survive without changing the row's height. */
  padding-bottom: 0.15em;
  margin-bottom: -0.15em;
  white-space: nowrap;
}

/* The title is split so a squeezed one loses its path first, then the start of
   its host, and never the extension. Each piece clips for its own ellipsis, so
   each needs the descender allowance too. The rest's shrink factor is huge so
   the head loses less than a layout unit while there is any path left to
   take it from; any real squeeze would put an ellipsis on a head that fits. */
.title-head,
.title-rest {
  min-width: 0;
  overflow: hidden;
  padding-bottom: 0.15em;
  margin-bottom: -0.15em;
  text-overflow: ellipsis;
}

.title-head {
  flex: 0 1 auto;
}

.title-rest {
  flex: 0 10000 auto;
}

.title-ext {
  flex: none;
}

.description {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  color: var(--muted);
  font-size: clamp(0.8rem, 1.45vw, 1.7rem);
  text-overflow: ellipsis;
  white-space: nowrap;
  transition: color 0.18s ease;
}

.row:hover .description {
  color: var(--muted-inverted);
}

/* Sits in the page gutter so the text keeps its position when the icon
   appears on hover. z-index keeps it above the anchor it overlaps, so
   clicking the pencil edits instead of opening the link. */
.edit {
  position: absolute;
  z-index: 1;
  top: 50%;
  right: 1.3vw;
  display: grid;
  place-items: center;
  width: clamp(2rem, 2.7vw, 3.3rem);
  height: clamp(2rem, 2.7vw, 3.3rem);
  padding: 0;
  transform: translateY(-50%);
  border: 0;
  background: none;
  color: inherit;
  opacity: 0;
  cursor: pointer;
  transition: opacity 0.12s ease;
}

.row:hover .edit,
.edit:focus-visible {
  opacity: 1;
}

.edit:focus-visible {
  outline: 1px solid currentColor;
  outline-offset: 2px;
}

/* On a hovered row the button is a solid strip in the row's own colours
   swapped, from the top of the row to its bottom and out to the right edge, so
   the whole of it reads as the thing to click. It stays out of the tag cards,
   where the pencil is only a mark in the corner. */
.row .edit {
  top: 0;
  right: 0;
  bottom: 0;
  width: 4vw; /* narrower than the 5.2vw gutter, so the text never touches it */
  min-width: 3rem;
  height: auto;
  transform: none;
  transition: opacity 0.12s ease, background 0.18s ease, color 0.18s ease;
}

.row:hover .edit {
  background: var(--hover-fg);
  color: var(--hover-bg);
}

/* Under the pointer it takes the highlight, and the pencil goes dark on it in
   every theme, since the highlight is a yellow in all of them. */
.row .edit:hover {
  background: var(--edit-hover);
  color: #222831;
}

.edit svg {
  width: clamp(1.05rem, 1.5vw, 1.85rem);
  height: clamp(1.05rem, 1.5vw, 1.85rem);
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Screen-reader-only text: names icon buttons without aria-label. */
.vh {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.hint {
  position: fixed;
  bottom: 3vh;
  left: 5.2vw;
  margin: 0;
  color: var(--hint);
  font-size: clamp(0.8rem, 1.2vw, 1.3rem);
  pointer-events: none;
}

.hint[data-state="error"] {
  color: var(--error);
}

/* ---------- edit drawer ---------- */

.scrim {
  position: fixed;
  z-index: 3; /* above the nav, or it would block the drawer's controls */
  inset: 0;
  background: var(--scrim);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.18s ease;
}

.scrim[data-open] {
  opacity: 1;
  pointer-events: auto;
}

.drawer {
  /* Author display beats the UA dialog:not([open]){display:none}, so the
     existing inert + data-open slide pattern keeps working. */
  display: block;
  position: fixed;
  z-index: 4;
  inset: 0 0 0 auto;
  width: min(30rem, 92vw);
  height: 100%; /* beats UA dialog { height: fit-content } */
  max-width: none;
  max-height: none;
  margin: 0;
  padding: 0;
  overflow-y: auto;
  border: none;
  border-left: 1px solid var(--panel-rule);
  background: var(--panel);
  color: inherit;
  transform: translateX(100%);
  transition: transform 0.18s ease;
}

.drawer[data-open] {
  transform: none;
}

.drawer form {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  min-height: 100%;
  padding: 2rem 1.75rem;
}

#drawer-title {
  margin: 0 0 1.25rem;
  font-family: "Cal Sans", system-ui, sans-serif;
  font-size: 1.75rem;
  font-weight: normal;
  overflow-wrap: anywhere;
}

.drawer form label {
  color: var(--muted);
  font-size: 0.95rem;
}

.drawer form input,
.drawer form textarea {
  margin-bottom: 0.75rem;
  padding: 0.6rem 0.7rem;
  border: 1px solid var(--panel-rule);
  border-radius: 3px;
  background: var(--field);
  color: var(--fg);
  font-family: inherit;
  font-size: 1.05rem;
  resize: vertical;
}

.drawer form input:focus,
.drawer form textarea:focus {
  border-color: var(--muted);
  outline: none;
}

/* ---------- tag field ---------- */

.tagbox {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.35rem;
  margin-bottom: 0.75rem;
  padding: 0.4rem 0.45rem;
  border: 1px solid var(--panel-rule);
  border-radius: 3px;
  background: var(--field);
  cursor: text;
}

.tagbox:focus-within {
  border-color: var(--muted);
}

.drawer .tagbox input {
  flex: 1 1 6rem;
  min-width: 6rem;
  margin: 0;
  padding: 0.2rem 0.25rem;
  border: none;
  background: none;
}

.chips {
  display: contents;
}

.chip {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.2rem 0.25rem 0.2rem 0.55rem;
  border: 1px solid var(--panel-rule);
  border-radius: 999px;
  font-size: 0.95rem;
}

.chip-remove {
  padding: 0 0.3rem;
  border: none;
  background: none;
  color: var(--muted);
  font-family: inherit;
  font-size: 1rem;
  line-height: 1;
  cursor: pointer;
}

.chip-remove:hover {
  color: var(--fg);
}

/* Opens upward: Save sits directly below the field, and a list covering it
   would swallow the click rather than let it through. */
.options {
  position: absolute;
  z-index: 1;
  /* Clears the field's own label as well as the field, so you can still see
     what you are filling in while the list is up. */
  bottom: calc(100% + 1.9rem);
  left: 0;
  right: 0;
  max-height: 14rem;
  margin: 0;
  padding: 0.25rem;
  overflow-y: auto;
  border: 1px solid var(--panel-rule);
  border-radius: 3px;
  background: var(--panel);
  box-shadow: 0 -0.6rem 1.4rem rgba(0, 0, 0, 0.55);
  list-style: none;
}

.option {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.4rem 0.55rem;
  border-radius: 3px;
  cursor: pointer;
}

.option[data-active] {
  background: var(--field);
}

.option-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* The part of the name you have typed so far. */
.option-name b {
  color: var(--fg);
  font-weight: normal;
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

.option:not([data-active]) .option-name {
  color: var(--muted);
}

/* Counts sit on the right, as they do on the tags page. */
.option-count {
  flex: none;
  color: var(--hint);
  font-family: "Cal Sans", system-ui, sans-serif;
  font-size: 0.85rem;
}

.option.create .option-count {
  color: var(--muted);
}

.form-error {
  margin: 0.4rem 0 0;
  color: var(--error);
  font-size: 0.95rem;
}

.actions {
  display: flex;
  gap: 0.6rem;
}

.actions button {
  padding: 0.5rem 1.1rem;
  border: 1px solid var(--fg);
  border-radius: 3px;
  font-family: inherit;
  font-size: 1.05rem;
  cursor: pointer;
}

.save {
  background: var(--fg);
  color: var(--bg);
}

.cancel {
  border-color: var(--panel-rule);
  background: none;
  color: var(--muted);
}

/* margin-top: auto pins these to the bottom of the drawer. */
.stamps {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.3rem 1rem;
  margin: auto 0 0;
  padding-top: 2rem;
  color: var(--hint);
  font-size: 0.95rem;
}

.stamps dt {
  color: var(--muted);
}

.stamps dd {
  margin: 0;
}

.delete {
  align-self: flex-start;
  margin-top: 1.25rem;
  padding: 0.5rem 1.1rem;
  border: 1px solid var(--error);
  border-radius: 3px;
  background: none;
  color: var(--error);
  font-family: inherit;
  font-size: 1.05rem;
  cursor: pointer;
}

.delete[data-armed] {
  background: var(--error);
  color: var(--bg);
}

@media (prefers-reduced-motion: reduce) {
  .scrim,
  .drawer,
  .edit,
  .row .edit,
  .row,
  .description,
  .bar input,
  .bar input::placeholder,
  .card,
  .recent,
  .card .count,
  .nav a {
    transition: none;
  }
}

/* ---------- page transitions ---------- */

/* Same-origin navigations cross-fade, and an element named the same on both
   pages morphs between them: a tag card's name grows into the tag page's
   heading and shrinks back on the way out. Opt-in only when motion is fine. */
@media (prefers-reduced-motion: no-preference) {
  @view-transition {
    navigation: auto;
  }
}

::view-transition-group(*) {
  animation-duration: 0.3s;
  animation-timing-function: cubic-bezier(0.2, 0.7, 0.2, 1);
}


/* ---------- nav ---------- */

/* Each link takes an equal share of the bar, so every target is the full
   height and an equal part of the width, and the dividers show where one ends. */
.nav {
  position: fixed;
  top: 0;
  right: 0;
  left: 0;
  z-index: 2;
  display: flex;
  height: var(--nav-h);
  border-bottom: 1px solid var(--rule);
  background: var(--bg);
}

.nav a {
  display: flex;
  flex: 1 1 0;
  align-items: center;
  justify-content: center;
  gap: 0.55em;
  color: var(--hint);
  font-size: clamp(0.95rem, 1.3vw, 1.45rem);
  text-decoration: none;
  transition: background 0.12s ease, color 0.12s ease;
}

/* Sized in em so the icon tracks the label as the font scales with the
   viewport. Stroked like the pencil, so every icon on the page matches. */
.nav svg {
  flex: none;
  width: 1.15em;
  height: 1.15em;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.nav a + a {
  border-left: 1px solid var(--rule);
}

.nav a:hover,
.nav a:focus-visible {
  background: var(--panel);
  color: var(--fg);
}

.nav a:focus-visible {
  outline: 1px solid var(--muted);
  outline-offset: -6px;
}

/* The current page is marked by more than colour: a bar along the bottom,
   sitting on the nav's own rule like a tab. */
.nav a[aria-current="page"] {
  color: var(--fg);
  box-shadow: inset 0 -2px 0 var(--marker);
}

/* On a narrow screen the icons carry the nav alone. The labels are clipped
   rather than display:none so each link keeps its accessible name. */
@media (max-width: 600px) {
  .nav a {
    font-size: 1.3rem;
  }

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

/* ---------- page headers ---------- */

.page-head {
  display: flex;
  align-items: baseline;
  gap: 1.2rem;
  padding: 0 5.2vw 1.6rem;
}

.page-head h1 {
  margin: 0;
  font-family: "Cal Sans", system-ui, sans-serif;
  font-size: clamp(1.3rem, 2.2vw, 2.6rem);
  font-weight: normal;
}

.page-head .back {
  color: var(--muted);
  font-size: clamp(0.8rem, 1.2vw, 1.4rem);
}

.page-head .count {
  color: var(--muted);
  font-family: "Cal Sans", system-ui, sans-serif;
  font-size: clamp(0.85rem, 1.3vw, 1.5rem);
}

.page-head .back {
  text-decoration: none;
}

.page-head .back:hover {
  color: var(--fg);
}

/* ---------- tags ---------- */

/* Masonry by CSS columns. Columns fill top to bottom, so the alphabetical
   order reads down each column rather than across. Native grid masonry would
   read across, but is not in every browser yet. */
#tags {
  columns: 17rem;
  column-gap: 1rem;
  padding: 1.6rem 5.2vw 0;
}

.card {
  position: relative;
  margin-bottom: 1rem;
  break-inside: avoid;
  border: 1px solid var(--rule);
  border-radius: 6px;
  transition: background 0.18s ease, color 0.18s ease, transform 0.18s ease;
}

/* --tilt is set per card by the template. */
.card:hover {
  background: var(--hover-bg);
  color: var(--hover-fg);
  transform: rotate(var(--tilt, 0deg));
}

.card .link {
  display: block;
  padding: 1.4rem 1.5rem 1.5rem;
}

/* Dashed, because it is not a tag but the links still waiting for one. */
.card-untagged {
  border-style: dashed;
}

/* Block, not inline: an inline box that wraps onto two lines cannot carry a
   view-transition-name, and long tag names do wrap here. fit-content keeps
   the box the width of the text, so the morph into the tag page's heading
   scales the name rather than stretching it. Right padding clears the count
   and the pencil, which share the top right corner. */
.card-name {
  display: block;
  width: fit-content;
  padding-right: 3rem;
  font-family: "Cal Sans", system-ui, sans-serif;
  font-size: clamp(1.4rem, 2vw, 2.4rem);
  line-height: 1.1;
  overflow-wrap: anywhere;
}

/* Set in Cal Sans, as the counts in the tag picker are, so a count reads the
   same wherever it appears. It sits in the corner the pencil takes on hover,
   and gives way to it: the drawer shows the count anyway, and two marks in
   one corner would collide. */
.card .count {
  position: absolute;
  top: 1.3rem;
  right: 1.1rem;
  padding: 0.25em 0.55em; /* room for Paper's pill; invisible elsewhere */
  border-radius: 999px;
  background: var(--count-bg);
  color: var(--count-fg);
  font-family: "Cal Sans", system-ui, sans-serif;
  font-size: clamp(0.9rem, 1.1vw, 1.2rem);
  line-height: 1;
  transition: opacity 0.12s ease;
}

.card:hover .count,
.card:has(.edit:focus-visible) .count {
  opacity: 0;
}

.recent {
  margin: 1rem 0 0;
  padding: 0.85rem 0 0;
  border-top: 1px solid var(--rule);
  color: var(--muted);
  font-size: clamp(0.85rem, 1vw, 1.1rem);
  line-height: 1.35;
  list-style: none;
  transition: color 0.18s ease, border-color 0.18s ease;
}

.recent li {
  display: -webkit-box;
  overflow: hidden;
  overflow-wrap: anywhere;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
}

.recent li + li {
  margin-top: 0.45rem;
}

.card:hover .count,
.card:hover .recent {
  color: var(--muted-inverted);
}

.card:hover .recent {
  border-top-color: var(--rule-inverted);
}

.card .edit {
  top: 0.9rem;
  right: 0.9rem;
  transform: none;
}

.card:hover .edit {
  opacity: 1;
}

/* The bar across the top of the wall and of the tags page: a single field, as
   tall as a row. */
.row.bar {
  align-items: center;
  padding: 0 0 0 5.2vw;
  border-top: 1px solid var(--rule);
}

/* Only the wall's search box: the tags page's field sits flush against its
   cards. */
.row.bar[role="search"] {
  margin-bottom: 5px;
}

/* What you type is the highlight colour, hovered or not. */
.row.bar[role="search"] input {
  color: var(--accent);
}

/* The icon sits in the gutter, where the text starts on every other row, and
   the field takes over from there. It follows the placeholder's colour, so it
   reads as part of the empty box and dims on hover with it. */
.row.bar svg {
  flex: none;
  width: clamp(1.3rem, 2.3vw, 2.8rem);
  height: clamp(1.3rem, 2.3vw, 2.8rem);
  fill: none;
  stroke: var(--hint);
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: stroke 0.18s ease;
}

.row.bar:hover svg {
  stroke: var(--muted-inverted);
}

.row.bar[role="search"]:hover input {
  color: var(--accent-hover);
}

.bar input,
.bar button {
  width: 100%;
  padding: 1.85rem 5.2vw 1.85rem 0.6em;
  border: 0;
  appearance: none;
  background: none;
  color: var(--fg);
  font-family: "Cal Sans", system-ui, sans-serif;
  font-size: clamp(1.5rem, 2.85vw, 3.5rem);
  line-height: 1.05;
  transition: color 0.18s ease;
}

/* The login page's "sign in as" step is a button set like the field. */
.bar button {
  text-align: left;
  cursor: pointer;
}

.bar input::placeholder {
  color: var(--hint);
  transition: color 0.18s ease;
}

.bar input:focus {
  outline: none;
}

/* Safari fits a search field with its own clear button and inner padding. */
.bar input::-webkit-search-decoration,
.bar input::-webkit-search-cancel-button {
  appearance: none;
}

.row.bar:hover input,
.row.bar:hover button {
  color: var(--hover-fg);
}

.row.bar:hover input::placeholder {
  color: var(--muted-inverted);
}

/* ---------- prefs ---------- */

.prefs {
  display: grid;
  gap: 3.5rem;
  padding: 0 5.2vw;
}

.account {
  align-self: center;
  margin-right: 0.6rem;
}

.prefs-section h2 {
  margin: 0 0 1.2rem;
  color: var(--muted);
  font-size: clamp(0.9rem, 1.2vw, 1.3rem);
  font-weight: normal;
}

/* The stats are one bordered strip divided like the nav: a 1px gap over the
   rule colour draws the dividers, so they stay correct however the tiles
   wrap. */
.stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 12rem), 1fr));
  gap: 1px;
  overflow: hidden;
  border: 1px solid var(--rule);
  border-radius: 6px;
  background: var(--rule);
}

.stat {
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
  padding: 1.6rem 1.5rem 1.4rem;
  background: var(--bg);
  color: inherit;
  text-decoration: none;
}

/* The untagged count leads to the links it counts. */
a.stat:hover,
a.stat:focus-visible {
  background: var(--panel);
  outline: none;
}

a.stat:hover .stat-label,
a.stat:focus-visible .stat-label {
  color: var(--fg);
}

/* The numbers count up from zero. A registered integer can be animated, and a
   counter can print one, so this needs no script. Where @property is missing
   the number simply appears at its value. */
@property --n {
  syntax: "<integer>";
  inherits: false;
  initial-value: 0;
}

.stat-n {
  --n: var(--to);
  counter-reset: n var(--n);
  font-family: "Cal Sans", system-ui, sans-serif;
  font-size: clamp(2.8rem, 6vw, 5.5rem);
  font-variant-numeric: tabular-nums;
  line-height: 0.9;
}

.stat-n::after {
  content: counter(n);
}

.stat-lead .stat-n {
  color: var(--accent);
}

.stat-label {
  color: var(--muted);
  font-size: clamp(0.85rem, 1.1vw, 1.2rem);
}

/* Bars are filled with the nav's marker colour and measured against the
   busiest tag, so the first is always full. */
.top-tags {
  margin: 0;
  padding: 0;
  list-style: none;
}

.top-tags a {
  display: grid;
  grid-template-columns: minmax(6rem, 14rem) 1fr 2.5rem;
  align-items: center;
  gap: 1.2rem;
  padding: 0.6rem 0;
  border-bottom: 1px solid var(--rule);
  color: var(--muted);
  font-size: clamp(0.95rem, 1.3vw, 1.4rem);
  text-decoration: none;
}

.top-tags li:first-child a {
  border-top: 1px solid var(--rule);
}

.top-tags a:hover,
.top-tags a:focus-visible {
  color: var(--fg);
  outline: none;
}

.top-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.top-bar {
  height: 0.5rem;
  border-radius: 999px;
  background: var(--rule);
}

.top-bar::before {
  content: "";
  display: block;
  width: var(--w);
  height: 100%;
  border-radius: inherit;
  background: var(--marker);
  transform-origin: left;
}

.top-count {
  color: var(--fg);
  font-family: "Cal Sans", system-ui, sans-serif;
  text-align: right;
}

@media (prefers-reduced-motion: no-preference) {
  .stat-n {
    animation: count-up 1.2s cubic-bezier(0.2, 0.7, 0.2, 1) both;
  }

  .stat:nth-child(2) .stat-n { animation-delay: 0.08s; }
  .stat:nth-child(3) .stat-n { animation-delay: 0.16s; }
  .stat:nth-child(4) .stat-n { animation-delay: 0.24s; }

  .top-bar::before {
    animation: grow 0.9s 0.2s cubic-bezier(0.2, 0.7, 0.2, 1) both;
  }
}

@keyframes count-up {
  from { --n: 0; }
}

@keyframes grow {
  from { transform: scaleX(0); }
}

.themes {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
}

/* Each swatch previews its own theme whatever the page is painted in, so it
   carries that theme's colours rather than the current tokens. */
.swatch {
  display: flex;
  flex-direction: column;
  gap: 0.45rem;
  padding: 0.45rem;
  border: 1px solid var(--rule);
  border-radius: 8px;
  background: none;
  color: var(--muted);
  font-family: inherit;
  font-size: 0.95rem;
  cursor: pointer;
}

.swatch:hover,
.swatch:focus-visible {
  border-color: var(--muted);
  color: var(--fg);
  outline: none;
}

.swatch[aria-pressed="true"] {
  border-color: var(--fg);
  color: var(--fg);
}

.swatch[data-swatch="black"] { --sw-bg: #000; --sw-fg: #fff; --sw-dot: gold; }
.swatch[data-swatch="slate"] { --sw-bg: #222831; --sw-fg: #eeeeee; --sw-dot: #ffd369; }
.swatch[data-swatch="paper"] { --sw-bg: #eeeeee; --sw-fg: #222831; --sw-dot: #ffd369; }

.swatch-preview {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 7rem;
  height: 3.6rem;
  padding: 0 0.8rem;
  border-radius: 5px;
  background: var(--sw-bg);
  color: var(--sw-fg);
  box-shadow: inset 0 0 0 1px rgba(128, 128, 128, 0.25);
  font-family: "Cal Sans", system-ui, sans-serif;
  font-size: 1.3rem;
}

.swatch-dot {
  width: 0.7rem;
  height: 0.7rem;
  border-radius: 50%;
  background: var(--sw-dot);
}

.swatch-name {
  padding: 0 0.15rem 0.1rem;
  text-align: left;
}

.aside {
  color: var(--hint);
  font-size: 0.9rem;
}

label .aside {
  font-size: 0.85rem;
}

/* The help text sits at the far end of the label, out of the way of the name. */
label:has(> .aside) {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
}
