/* =============================================================================
   switcher.css — the three nav controls: language · colourway · day-night

   New in this project; the reference site has none of them (it put the Discord
   and QQ pills in that corner instead, now removed from the bar).

   The two dropdowns sit collapsed as a single icon and unfold their label on
   hover, focus or while the menu is open; the day-night switch is the sun/moon
   slider from the CodePen the project was pointed at
   (codepen.io/linxiang-webcraft/pen/pvbvLBN), scaled to the bar.

   Switching colours is handled by the View Transitions API at the bottom of
   this file — see the comment there for why the old approach flickered.
   ============================================================================= */

.nav__tools {
  display: flex;
  align-items: center;
  gap: 10px;
}

/* --- the two dropdown buttons: one icon, label on demand ----------------- */

.sw {
  position: relative;
}

.sw__btn {
  display: flex;
  align-items: center;
  gap: 0;
  height: 38px;
  padding: 0 12px;
  background: 0 0;
  border: 1.5px solid var(--ink-a20);
  border-radius: var(--radius-pill);
  color: var(--ink);
  font-family: var(--font);
  font-size: 13.5px;
  font-weight: 520;
  letter-spacing: .01em;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color .2s var(--ease-out), border-color .2s var(--ease-out),
    color .2s var(--ease-out);
}

.sw__btn:hover,
.sw__btn:focus-visible,
.sw__is-open .sw__btn {
  background: var(--chip);
  border-color: transparent;
}

.sw__icon,
.sw__dot {
  flex: none;
}

/* the globe reads as "language" */
.sw__icon {
  width: 15px;
  height: 15px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
}

/* the colourway button's icon is its own accent swatch */
.sw__dot {
  width: 11px;
  height: 11px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: inset 0 0 0 1.5px var(--ink-a20);
}

/* label and caret are rolled up to nothing until the button is opened or
   pointed at — the transition moves max-width so the pill really grows */
.sw__label,
.sw__caret {
  flex: none;
  max-width: 0;
  opacity: 0;
  overflow: hidden;
  transition: max-width .3s var(--ease-out), opacity .16s var(--ease-out),
    margin-left .3s var(--ease-out);
}

.sw__btn:hover .sw__label,
.sw__btn:focus-visible .sw__label,
.sw__is-open .sw__label {
  max-width: 9em;
  margin-left: 8px;
  opacity: 1;
}

.sw__caret {
  width: 7px;
  height: 7px;
  border-right: 1.5px solid var(--ink-3);
  border-bottom: 1.5px solid var(--ink-3);
  transform: translateY(-2px) rotate(45deg);
}

.sw__btn:hover .sw__caret,
.sw__btn:focus-visible .sw__caret,
.sw__is-open .sw__caret {
  max-width: 1em;
  margin-left: 7px;
  opacity: 1;
}

.sw__is-open .sw__caret {
  transform: translateY(1px) rotate(225deg);
}

/* --- the menus: centred right under their button ------------------------- */

.sw__menu {
  position: absolute;
  top: calc(100% + 10px);
  left: 50%;
  z-index: 5;
  width: max-content;
  min-width: 112px;
  padding: 6px;
  background: var(--surface);
  border: 1.5px solid var(--ink-a20);
  border-radius: 14px;
  box-shadow: 0 20px 44px var(--ink-a14);
  opacity: 0;
  visibility: hidden;
  transform: translate(-50%, -8px) scale(.97);
  transform-origin: top center;
  /* visibility waits for the fade on the way out and never on the way in, so
     a closing menu is not cut off mid-animation */
  transition: opacity .18s var(--ease-out), transform .26s var(--ease-out),
    visibility 0s linear .26s;
}

.sw__is-open .sw__menu {
  opacity: 1;
  visibility: visible;
  transform: translate(-50%, 0) scale(1);
  transition: opacity .18s var(--ease-out), transform .26s var(--ease-out), visibility 0s;
}

/* ten colourways read better as a short grid than as a long column */
.sw__menu--grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(104px, 1fr));
  gap: 3px;
}

.sw__option {
  display: flex;
  align-items: center;
  justify-content: center;
  /* a button shrinks to its text, so centring needs the full width to mean
     anything — without this the labels sit against the left edge */
  width: 100%;
  padding: 8px 12px;
  background: 0 0;
  border: 0;
  border-radius: 9px;
  color: var(--ink);
  font-family: var(--font);
  font-size: 13.5px;
  font-weight: 500;
  text-align: center;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color .18s var(--ease-out), color .18s var(--ease-out);
}

.sw__option:hover {
  background: var(--chip);
}

.sw__option[aria-selected="true"] {
  background: var(--accent);
  color: var(--on-accent);
}

/* --- day / night ---------------------------------------------------------
   The switch from the CodePen, kept as-is: a sun that slides behind a
   moon-mask, stars rising out of the road, clouds sinking below it. Only the
   scale changed (font-size is the single knob) and the class names. Its colours
   are the pen's own rather than the palette's — it reads as a little device
   sitting in the bar, and the sky-blue/day against navy/night carries the
   meaning by itself. */

/* Parked for now: nothing below is deleted, the button is only kept out of the
   bar. data-daynight="on" on <html> puts it back (see index.html). The reason
   it has to be an attribute rather than a CSS-only hide is the script: while it
   is parked the page also refuses to restore a dark state from storage, so
   nobody can be left in a scheme with no way out. */

html:not([data-daynight="on"]) .daynight {
  display: none;
}

.daynight {
  --toggle-width: 5.625em;
  --toggle-height: 2.5em;
  --sun-diameter: 2.125em;
  --sun-offset: calc((var(--toggle-height) - var(--sun-diameter)) / 2);
  --bg-toggle-light: #3d7eae;
  --bg-toggle-dark: #1d1f2c;
  --color-sun: #ecca2f;
  --color-moon: #c4c9d1;
  --color-crater: #959db1;
  --color-star: #fff;
  --color-cloud-front: #f3fdff;
  --color-cloud-back: #aacadf;
  --t: .3s ease;

  display: block;
  padding: 0;
  background: none;
  border: 0;
  font-size: 12px; /* the one knob: everything below is em-based */
  line-height: 1;
  cursor: pointer;
}

.daynight__track {
  position: relative;
  display: block;
  width: var(--toggle-width);
  height: var(--toggle-height);
  background-color: var(--bg-toggle-light);
  border-radius: 100em;
  overflow: hidden;
  box-shadow: 0.06em 0.06em 0.125em rgba(255, 255, 255, .94);
  transition: background-color var(--t);
}

.daynight[aria-checked="true"] .daynight__track {
  background-color: var(--bg-toggle-dark);
}

.daynight__track::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 100em;
  pointer-events: none;
  box-shadow: 0 0.05em 0.187em rgba(0, 0, 0, .5) inset;
}

.daynight__sun {
  position: absolute;
  top: var(--sun-offset);
  left: 0;
  width: var(--sun-diameter);
  height: var(--sun-diameter);
  background-color: var(--color-sun);
  border-radius: 50%;
  transform: translateX(var(--sun-offset));
  overflow: hidden;
  box-shadow: 0.05em 0.125em 0.125em rgba(0, 0, 0, .25),
    0 0.05em 0.125em rgba(0, 0, 0, .25),
    0.05em 0.05em 0.05em 0 rgba(254, 255, 239, .61) inset,
    0 -0.05em 0.05em 0 #a1872a inset,
    0 0 0 0.625em rgba(255, 255, 255, .1),
    0 0 0 1.25em rgba(255, 255, 255, .1),
    0 0 0 1.875em rgba(255, 255, 255, .1);
  transition: transform var(--t);
}

.daynight[aria-checked="true"] .daynight__sun {
  transform: translateX(calc(var(--toggle-width) - var(--sun-diameter) - var(--sun-offset)));
}

.daynight:hover .daynight__sun {
  transform: translateX(calc(var(--sun-offset) + 0.187em));
}

.daynight[aria-checked="true"]:hover .daynight__sun {
  transform: translateX(
    calc(var(--toggle-width) - var(--sun-diameter) - var(--sun-offset) - 0.187em)
  );
}

.daynight__moon {
  position: relative;
  display: block; /* the pen uses a div here; a span would ignore width/height */
  width: 100%;
  height: 100%;
  background-color: var(--color-moon);
  border-radius: inherit;
  transform: translateX(100%);
  box-shadow: 0.062em 0.062em 0.062em 0 rgba(254, 255, 239, .61) inset,
    0 -0.062em 0.062em 0 #969696 inset;
  transition: transform var(--t);
}

.daynight[aria-checked="true"] .daynight__moon {
  transform: translateX(0);
}

.daynight__crater {
  position: absolute;
  background-color: var(--color-crater);
  border-radius: 50%;
  box-shadow: 0 0.03em 0.06em rgba(0, 0, 0, .25) inset;
}

.daynight__crater:nth-of-type(1) {
  top: 0.75em;
  left: 0.3em;
  width: 0.75em;
  height: 0.75em;
}

.daynight__crater:nth-of-type(2) {
  top: 0.9em;
  left: 1.375em;
  width: 0.375em;
  height: 0.375em;
}

.daynight__crater:nth-of-type(3) {
  top: 0.3em;
  left: 0.8em;
  width: 0.25em;
  height: 0.25em;
}

.daynight__stars {
  position: absolute;
  left: 0.3em;
  width: 2.75em;
  color: var(--color-star);
  transform: translateY(-2em);
  transition: transform var(--t);
}

.daynight[aria-checked="true"] .daynight__stars {
  transform: translateY(0.5em);
}

.daynight__clouds {
  position: absolute;
  left: 0.3em;
  top: 2em;
  width: 1.25em;
  height: 1.25em;
  background-color: var(--color-cloud-front);
  border-radius: 50%;
  box-shadow: 0.937em 0.312em var(--color-cloud-front),
    1.437em 0.375em var(--color-cloud-front),
    2.187em 0 var(--color-cloud-front),
    2.937em 0.312em var(--color-cloud-front),
    3.625em -0.062em var(--color-cloud-front),
    4.5em -0.312em var(--color-cloud-front),
    4.625em -1.75em 0 0.437em var(--color-cloud-front),
    -0.312em -0.312em var(--color-cloud-back),
    0.5em -0.125em var(--color-cloud-back),
    1.25em -0.062em var(--color-cloud-back),
    2em -0.312em var(--color-cloud-back),
    2.625em 0 var(--color-cloud-back),
    3.375em -0.437em var(--color-cloud-back),
    4em -0.625em var(--color-cloud-back),
    4.125em -2.125em 0 0.437em var(--color-cloud-back);
  transition: transform var(--t);
}

.daynight[aria-checked="true"] .daynight__clouds {
  transform: translateY(3em);
}

/* --- switching colours without the flicker -------------------------------
   Recolouring used to be done with a stylesheet that put a 0.4s colour
   transition on every element for the length of the swap. Measured on this
   page that meant ~1575 CSS transitions alive at once and frames up to 80ms —
   which is what read as the whole page flickering and shaking.

   The swap now goes through the View Transitions API instead: the browser
   snapshots the page before and after and animates those two composited
   pictures, so nothing on the page is asked to animate. A colourway picked from
   the menu is a crossfade; the day-night switch grows a circle out of the
   switch itself, the way the recording does. Browsers without the API swap in
   one frame, which is still better than a stutter. */

::view-transition-old(root),
::view-transition-new(root) {
  animation: none;
  /* the UA default for the incoming picture is plus-lighter on some builds,
     which blooms a light theme over a dark one — keep it a plain fade */
  mix-blend-mode: normal;
}

/* the snapshots are painted on transparent layers, so each one carries the
   page colour it belongs to (the canvas background is not captured) */
html.vt-fade::view-transition-old(root),
html.vt-circle::view-transition-old(root) {
  background: var(--vt-from);
}

html.vt-fade::view-transition-new(root),
html.vt-circle::view-transition-new(root) {
  background: var(--vt-to);
}

html.vt-fade::view-transition-new(root) {
  /* a crossfade wants an even curve: --ease-out is so front-loaded that the
     swap reads as a cut. This is the standard material in-out. */
  animation: vt-fade .42s cubic-bezier(.4, 0, .2, 1) both;
}

html.vt-circle::view-transition-new(root) {
  animation: vt-circle .58s var(--ease-out) both;
}

@keyframes vt-fade {
  from { opacity: 0; }
  to { opacity: 1; }
}

@keyframes vt-circle {
  from { clip-path: circle(0% at var(--vt-x) var(--vt-y)); }
  to { clip-path: circle(var(--vt-r) at var(--vt-x) var(--vt-y)); }
}

/* While a swap is running the page sits hidden behind the two snapshots, so an
   element's own colour transition cannot be seen — but it is still running, and
   the bar's background was caught painting a stale value on the frame the
   snapshots are lifted (one frame in 1400, a grey flash along the top). Turning
   them off for the length of the swap removes that, and costs nothing: it is
   one style recalculation at the start, not one per frame.

   The day-night switch is exempt — its own sun-and-moon slide is part of the
   effect the visitor is watching. */
html.vt-fade *:not(.daynight):not(.daynight *),
html.vt-circle *:not(.daynight):not(.daynight *) {
  transition: none !important;
}

@media (prefers-reduced-motion: reduce) {
  html.vt-fade::view-transition-new(root),
  html.vt-circle::view-transition-new(root) {
    animation-duration: 1ms;
  }
}
