/* The dark/white switch (assets/theme.js).

   Edu is the knob. In the dark theme it sleeps on a night sky (a moon, twinkling stars and a
   tiny "z"); in the white theme it is awake on a blue sky with the sun and two clouds. Each
   built switch carries its look in data-tt, which theme.js flips the moment it is pressed (the
   page follows a moment later, under the lamp's light: theme-scene.js). Before theme.js has
   built a switch, its look follows <html data-theme>, which theme-boot.js sets before the first
   paint, so a switch never shows the wrong state. theme.js plays the moments in between: Edu
   leaping out and dropping back in, the empty knob's roll, and the wake-up and the yawn (the
   is-waking / is-dozing classes).

   The sky, sun, moon and stars are illustration colours that belong to this one control, the
   way the mascot has its own palette: they are the --tt-* properties below. Edu is the only
   orange here, and nothing orange is ever a fill on a dark surface. */

.theme-toggle {
  --tt-w: 56px; --tt-h: 30px; --tt-pad: 3px;
  --tt-knob: calc(var(--tt-h) - 2 * var(--tt-pad));
  --tt-travel: calc(var(--tt-w) - var(--tt-h));
  /* night */
  --tt-night-1: #1d2656; --tt-night-2: #0b1029; --tt-night-edge: rgba(255, 255, 255, 0.1);
  --tt-night-knob: #2c3669; --tt-moon: #eef1ff; --tt-moon-glow: #a3b3ff; --tt-crater: #cfd7f2;
  --tt-star: #ffffff; --tt-dot: #d6deff; --tt-z: #c3ceff;
  /* day */
  --tt-day-1: #4eaeef; --tt-day-2: #b0dffb; --tt-day-edge: rgba(12, 74, 134, 0.15);
  --tt-day-knob: #ffffff; --tt-sun: #ffc531; --tt-sun-hi: #ffe38c;
  --tt-cloud: #ffffff; --tt-cloud-shade: #d9ecfa;

  position: relative; display: inline-block; flex: none; vertical-align: middle;
  width: var(--tt-w); height: var(--tt-h); padding: 0; margin: 0; border: 0; border-radius: 999px;
  background: none; color: inherit; font: inherit; line-height: 0; cursor: pointer; isolation: isolate;
  -webkit-tap-highlight-color: transparent; touch-action: manipulation; -webkit-user-select: none; user-select: none;
}
/* the chat header has a slightly smaller one */
.sheet-actions .theme-toggle { --tt-w: 52px; --tt-h: 28px; }
/* (styles.css makes the corner button a 40px circle on phones; this wins, it loads later.) 5px down:
   centred on the pill nav on wide screens, where the old 40px button sat on phones. */
.corner .theme-toggle { width: var(--tt-w); height: var(--tt-h); margin-top: 5px; }
/* A 44px tall tap area without changing the drawing (the probes tap +-18.5px around the centre). */
.theme-toggle::after {
  content: ""; position: absolute; inset: calc((44px - var(--tt-h)) / -2) -3px; border-radius: 999px;
}
.theme-toggle:focus-visible { outline: 2px solid var(--focus); outline-offset: 3px; border-radius: 999px; }
/* The ring follows the switch's own look (it changes as it is pressed, not when the page does a
   moment later under the lamp's light): styles.css --focus in each theme. */
.theme-toggle.tt-built[data-tt="dark"]:focus-visible { outline-color: #fb6514; }
.theme-toggle.tt-built[data-tt="light"]:focus-visible { outline-color: #c2410c; }

/* Before theme.js has built it (a moment on a slow phone): the sky and a plain knob. */
.theme-toggle:not(.tt-built) { background: linear-gradient(180deg, var(--tt-night-1), var(--tt-night-2)); }
.theme-toggle:not(.tt-built)::before {
  content: ""; position: absolute; top: var(--tt-pad); left: var(--tt-pad);
  width: var(--tt-knob); height: var(--tt-knob); border-radius: 50%; background: var(--tt-night-knob);
}
:root[data-theme="light"] .theme-toggle:not(.tt-built) { background: linear-gradient(180deg, var(--tt-day-1), var(--tt-day-2)); }
:root[data-theme="light"] .theme-toggle:not(.tt-built)::before { background: var(--tt-day-knob); transform: translateX(var(--tt-travel)); }
.theme-toggle .theme-icon { display: none; }

/* --- the sky ------------------------------------------------------------------------------ */
.tt-track {
  position: absolute; inset: 0; z-index: 0; border-radius: inherit; overflow: hidden;
  background: linear-gradient(180deg, var(--tt-night-1), var(--tt-night-2));
}
/* The day sky over the night one, and a second night sky over the day. At rest only the base
   (night) or the day shows; while the knob rolls, theme.js grows the new sky as a bubble around it. */
.tt-day, .tt-dusk { position: absolute; inset: 0; clip-path: circle(0px at 50% 50%); }
.tt-day { background: linear-gradient(180deg, var(--tt-day-1), var(--tt-day-2)); }
.tt-dusk { background: linear-gradient(180deg, var(--tt-night-1), var(--tt-night-2)); }
.theme-toggle[data-tt="light"] .tt-day { clip-path: none; }
.tt-track::after { /* the rim, drawn over the scene */
  content: ""; position: absolute; inset: 0; z-index: 2; border-radius: inherit; pointer-events: none;
  box-shadow: inset 0 0 0 1px var(--tt-night-edge), inset 0 1px 3px rgba(0, 0, 0, 0.4);
  transition: box-shadow 0.5s ease;
}
.theme-toggle[data-tt="light"] .tt-track::after {
  box-shadow: inset 0 0 0 1px var(--tt-day-edge), inset 0 1px 3px rgba(12, 74, 134, 0.18);
}
.tt-scene { position: absolute; inset: 0; z-index: 1; display: block; width: 100%; height: 100%; }
.tt-scene g { transform-box: fill-box; transform-origin: 50% 50%; }
.tt-sun-glow { fill: #ffffff; opacity: 0.3; }
.tt-sun-disc { fill: var(--tt-sun); }
.tt-sun-hi { fill: var(--tt-sun-hi); }
.tt-cloud-puff { fill: var(--tt-cloud); }
.tt-cloud-shade { fill: var(--tt-cloud-shade); }
.tt-moon-glow { fill: var(--tt-moon-glow); opacity: 0.12; }
.tt-moon-disc { fill: var(--tt-moon); }
.tt-crater { fill: var(--tt-crater); }

/* Night (the default): the moon rises and the stars come out one by one. */
.tt-sun { opacity: 0; transform: translateY(10px) scale(0.55); transition: transform 0.45s cubic-bezier(0.5, 0, 0.75, 0), opacity 0.3s ease 0.1s; }
.tt-cloud { opacity: 0; transition: transform 0.4s cubic-bezier(0.5, 0, 0.75, 0), opacity 0.28s ease; }
.tt-cloud-a { transform: translateX(-13px); }
.tt-cloud-b { transform: translateX(-9px); }
.tt-moon { transition: transform 0.8s cubic-bezier(0.3, 1.35, 0.5, 1) 0.22s, opacity 0.45s ease 0.22s; }
/* six little HTML stars (they twinkle in a loop, so the compositor animates them) */
.tt-stars { position: absolute; inset: 0; z-index: 1; pointer-events: none; }
.tt-star {
  position: absolute; display: block; left: calc(var(--x) - var(--s) / 2); top: calc(var(--y) - var(--s) / 2);
  width: var(--s); height: var(--s); transition: transform 0.5s cubic-bezier(0.3, 1.7, 0.5, 1), opacity 0.3s ease;
}
.tt-star > i { display: block; width: 100%; height: 100%; border-radius: 50%; background: var(--tt-dot); }
.tt-star-1 > i, .tt-star-2 > i {
  border-radius: 0; background: var(--tt-star);
  clip-path: polygon(50% 0, 60% 40%, 100% 50%, 60% 60%, 50% 100%, 40% 60%, 0 50%, 40% 40%);
}
.tt-star-1 { --x: 59.3%; --y: 28%; --s: calc(var(--tt-h) * 0.134); transition-delay: 0.14s; }
.tt-star-2 { --x: 91.4%; --y: 68.7%; --s: calc(var(--tt-h) * 0.104); transition-delay: 0.38s; }
.tt-star-3 { --x: 67.5%; --y: 72%; --s: calc(var(--tt-h) * 0.05); transition-delay: 0.22s; }
.tt-star-4 { --x: 90%; --y: 19.3%; --s: calc(var(--tt-h) * 0.04); transition-delay: 0.46s; }
.tt-star-5 { --x: 54.6%; --y: 55.3%; --s: calc(var(--tt-h) * 0.037); transition-delay: 0.3s; }
.tt-star-6 { --x: 81.4%; --y: 82.7%; --s: calc(var(--tt-h) * 0.034); transition-delay: 0.54s; }
/* Day: the sun comes up with a little bounce and the clouds drift in. */
.theme-toggle[data-tt="light"] .tt-sun {
  opacity: 1; transform: none; transition: transform 0.8s cubic-bezier(0.3, 1.3, 0.5, 1) 0.14s, opacity 0.35s ease 0.14s;
}
.theme-toggle[data-tt="light"] .tt-cloud {
  opacity: 1; transform: none; transition: transform 0.75s cubic-bezier(0.22, 1, 0.36, 1) 0.06s, opacity 0.4s ease 0.06s;
}
.theme-toggle[data-tt="light"] .tt-cloud-b { transition-delay: 0.2s; }
.theme-toggle[data-tt="light"] .tt-moon {
  opacity: 0; transform: translate(3px, 12px) rotate(-30deg); transition: transform 0.4s cubic-bezier(0.5, 0, 0.75, 0), opacity 0.25s ease;
}
.theme-toggle[data-tt="light"] .tt-star { opacity: 0; transform: scale(0); transition: transform 0.25s ease-in, opacity 0.2s ease; }
/* the stars twinkle (night only, so nothing loops unseen in the day) */
@media (prefers-reduced-motion: no-preference) {
  .theme-toggle:not([data-tt="light"]) .tt-star > i { animation: tt-twinkle 3.2s ease-in-out infinite; }
  .theme-toggle:not([data-tt="light"]) .tt-star-2 > i { animation-duration: 2.6s; animation-delay: -1.2s; }
  .theme-toggle:not([data-tt="light"]) .tt-star-3 > i { animation-duration: 3.8s; animation-delay: -0.4s; }
  .theme-toggle:not([data-tt="light"]) .tt-star-4 > i { animation-duration: 2.9s; animation-delay: -2.1s; }
  .theme-toggle:not([data-tt="light"]) .tt-star-5 > i { animation-duration: 3.5s; animation-delay: -1.7s; }
  .theme-toggle:not([data-tt="light"]) .tt-star-6 > i { animation-duration: 2.4s; animation-delay: -0.9s; }
}
@keyframes tt-twinkle { 0%, 100% { opacity: 1; transform: none; } 50% { opacity: 0.3; transform: scale(0.65); } }

/* --- Edu, the knob -------------------------------------------------------------------------- */
.tt-knob {
  position: absolute; z-index: 3; top: var(--tt-pad); left: var(--tt-pad); width: var(--tt-knob); height: var(--tt-knob);
  /* transform is theme.js's (the roll); translate and scale are the hover nudge and the press */
  transition: translate 0.35s cubic-bezier(0.3, 1.5, 0.5, 1), scale 0.16s ease;
}
.theme-toggle[data-tt="light"] .tt-knob { transform: translateX(var(--tt-travel)); }
.tt-body { position: absolute; inset: 0; }
.tt-disc {
  position: absolute; inset: 0; border-radius: 50%; background: var(--tt-night-knob);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.55), inset 0 0 0 1px rgba(255, 255, 255, 0.1);
  transition: background-color 0.32s ease, box-shadow 0.32s ease;
}
.theme-toggle[data-tt="light"] .tt-disc {
  background: var(--tt-day-knob); box-shadow: 0 1px 2px rgba(12, 74, 134, 0.35), 0 3px 8px -3px rgba(12, 74, 134, 0.5);
}
.tt-face { position: absolute; inset: 0; }
.tt-face .mascot { display: block; width: 100%; }
.tt-face .m-clip { background: transparent; } /* the disc behind is the knob */
.tt-sleep { opacity: 0; }

/* Asleep (dark): eyes closed, head tilted, the seedling drooping, a slow breath. */
.theme-toggle:not([data-tt="light"]) .tt-body { transform: rotate(-7deg); }
.theme-toggle:not([data-tt="light"]) .tt-face .m-eyes { opacity: 0; }
.theme-toggle:not([data-tt="light"]) .tt-sleep { opacity: 1; }
.theme-toggle:not([data-tt="light"]) .tt-face .m-accessory { transform: rotate(15deg); transition-delay: 0.6s; }
@media (prefers-reduced-motion: no-preference) {
  .theme-toggle:not([data-tt="light"]):not(.is-dozing):not(.is-away) .tt-body { animation: tt-breathe 3.6s ease-in-out infinite alternate; }
}
@keyframes tt-breathe { from { transform: rotate(-7deg); } to { transform: rotate(-7deg) scale(1.045, 0.965); } }

/* Out of the knob (theme.js): the face is hidden (theme.js animates its leap out and its drop back
   in), and it leaves wide awake, whichever way it is going. Its seat rolls over empty. */
.theme-toggle.is-out .tt-face { opacity: 0.004; } /* a trace: still painted, so it is ready the frame it is back */
.theme-toggle.is-away:not(.is-dozing):not(.is-waking) .tt-body { transform: none; }
.theme-toggle.is-away:not(.is-dozing):not(.is-waking) .tt-face .m-eyes { opacity: 1; }
.theme-toggle.is-away:not(.is-dozing):not(.is-waking) .tt-sleep { opacity: 0; }

/* Back home in the light: the eyes pop open as it lands (blink-blink, from theme.js), a big
   stretch and a grin. */
.theme-toggle.is-waking .tt-body { animation: tt-wake-body 0.66s both; }
.theme-toggle.is-waking .tt-sleep { animation: tt-arcs-out 0.66s both; }
.theme-toggle.is-waking .tt-face .m-eyes { animation: tt-eyes-open 0.66s both; }
.theme-toggle.is-waking .tt-face .m-mouth { animation: tt-smile-off 0.66s both; }
.theme-toggle.is-waking .tt-face .m-mouth-open { display: inline; animation: tt-grin 0.66s both; }
@keyframes tt-wake-body {
  0%, 30% { transform: none; animation-timing-function: cubic-bezier(0.3, 0, 0.4, 1); }
  52% { transform: scale(0.93, 1.1); }
  72% { transform: scale(1.04, 0.97); }
  88% { transform: scale(0.99, 1.01); }
  100% { transform: none; }
}
@keyframes tt-arcs-out { 0%, 16% { opacity: 1; } 22%, 100% { opacity: 0; } }
@keyframes tt-eyes-open {
  0%, 18% { opacity: 0; transform: scaleY(0.1); }
  30% { opacity: 1; transform: scaleY(1.22); }
  42% { transform: scaleY(0.88); }
  54%, 100% { opacity: 1; transform: none; }
}
@keyframes tt-smile-off { 0%, 46% { opacity: 1; } 50%, 86% { opacity: 0; } 92%, 100% { opacity: 1; } }
@keyframes tt-grin {
  0%, 46% { opacity: 0; transform: scale(0.4); }
  54%, 84% { opacity: 1; transform: none; }
  92%, 100% { opacity: 0; transform: scale(0.5); }
}

/* Back home in the dark: a big yawn, droopy eyes, then they close and it curls up, head tipped. */
.theme-toggle.is-dozing .tt-body { animation: tt-doze-body 0.82s both; }
.theme-toggle.is-dozing .tt-sleep { animation: tt-arcs-in 0.82s both; }
.theme-toggle.is-dozing .tt-face .m-eyes { animation: tt-eyes-shut 0.82s both; }
.theme-toggle.is-dozing .tt-face .m-mouth { animation: tt-yawn-smile 0.82s both; }
.theme-toggle.is-dozing .tt-face .m-mouth-open { display: inline; animation: tt-yawn 0.82s both; }
@keyframes tt-doze-body {
  0%, 26% { transform: none; }
  34% { transform: scale(0.97, 1.05); }
  48% { transform: scale(0.96, 1.07); }
  62% { transform: none; }
  78% { transform: rotate(-12deg) scale(1.05, 0.95); }
  90% { transform: rotate(-6deg) scale(1.01, 0.99); }
  100% { transform: rotate(-7deg); }
}
@keyframes tt-eyes-shut {
  0%, 30% { opacity: 1; transform: none; }
  38%, 52% { opacity: 1; transform: scaleY(0.22); }
  60% { opacity: 1; transform: scaleY(0.6); }
  66% { opacity: 1; transform: scaleY(0.4); }
  72%, 100% { opacity: 0; transform: scaleY(0.3); }
}
@keyframes tt-arcs-in { 0%, 70% { opacity: 0; } 76%, 100% { opacity: 1; } }
@keyframes tt-yawn-smile { 0%, 30% { opacity: 1; } 34%, 62% { opacity: 0; } 66%, 100% { opacity: 1; } }
@keyframes tt-yawn {
  0%, 30% { opacity: 0; transform: scale(0.5, 0.3); }
  36% { opacity: 1; transform: scale(0.7, 0.8); }
  46% { transform: scale(0.92, 1.9); }
  56% { transform: scale(0.86, 1.75); }
  62% { opacity: 1; transform: scale(0.45, 0.35); }
  66%, 100% { opacity: 0; transform: scale(0.45, 0.35); }
}

/* The z's while Edu sleeps: they drift up from its head, half a breath apart. Not while it is out
   or still nodding off; as it falls asleep the first pair floats up big, then they stay small. */
.tt-zz {
  position: absolute; z-index: 2; left: calc(var(--tt-pad) + var(--tt-knob) * 0.68); top: calc(var(--tt-pad) + var(--tt-knob) * 0.3 - 14px);
  width: 14px; height: 14px; pointer-events: none; opacity: 0; transition: opacity 0.2s ease;
}
.theme-toggle:not([data-tt="light"]):not(.is-away):not(.is-dozing) .tt-zz { opacity: 1; transition: opacity 0.3s ease; }
.tt-z { position: absolute; left: 0.15px; bottom: 0.55px; display: block; width: 5.1px; height: 5.1px; transform-origin: 17% 83%; }
.tt-z svg {
  display: block; width: 100%; height: 100%; overflow: visible;
  fill: none; stroke: var(--tt-z); stroke-width: 1.47; stroke-linecap: round; stroke-linejoin: round;
}
/* still (reduced motion): one small z by the head and one bigger above it */
.tt-z1 { transform: translate(3.5px, -2.5px) scale(0.75); opacity: 0.8; }
.tt-z2 { transform: translate(8px, -8px); }
@media (prefers-reduced-motion: no-preference) {
  .theme-toggle:not([data-tt="light"]) .tt-z { animation: tt-z 3.6s linear infinite; }
  .theme-toggle:not([data-tt="light"]) .tt-z2 { animation-delay: -1.8s; }
  .theme-toggle.is-snoring .tt-z { animation: tt-z-big 1.5s cubic-bezier(0.25, 0.6, 0.4, 1) both; }
  .theme-toggle.is-snoring .tt-z2 { animation-delay: 0.32s; }
}
@keyframes tt-z {
  0% { opacity: 0; transform: translate(0, 1px) scale(0.5); }
  15% { opacity: 1; }
  70% { opacity: 0.9; }
  100% { opacity: 0; transform: translate(7px, -9px) scale(1.1) rotate(8deg); }
}
@keyframes tt-z-big {
  0% { opacity: 0; transform: translate(0, 2px) scale(0.6); }
  18% { opacity: 1; transform: translate(2px, -3px) scale(1.5); }
  70% { opacity: 1; }
  100% { opacity: 0; transform: translate(11px, -17px) scale(2.1) rotate(10deg); }
}

/* Hover (a mouse; touch never hovers): the knob leans toward the other side, and a sleeping
   Edu opens its eyes a little to see who is there. A press squashes it. */
@media (hover: hover) and (pointer: fine) {
  .theme-toggle:hover .tt-knob { translate: 2px 0; }
  .theme-toggle[data-tt="light"]:hover .tt-knob { translate: -2px 0; }
  .theme-toggle:not([data-tt="light"]):not(.is-dozing):not(.is-away):hover .tt-face .m-eyes { animation: tt-peek 0.3s ease-out both; }
  .theme-toggle:not([data-tt="light"]):not(.is-dozing):not(.is-away):hover .tt-sleep { opacity: 0; }
}
@keyframes tt-peek { from { opacity: 0; transform: scaleY(0.2); } to { opacity: 1; transform: none; } }
.theme-toggle:active .tt-knob { scale: 0.9 1.06; }

/* Offscreen switches rest. */
.theme-toggle.tt-off *, .theme-toggle.tt-off *::before { animation-play-state: paused; }

/* Windows high contrast drops the skies: keep the pill's outline and the knob's edge visible. */
@media (forced-colors: active) {
  .theme-toggle { border: 1px solid ButtonText; }
  .tt-disc { border: 1px solid ButtonText; }
}

/* --- reduced motion: no roll, no twinkle; the switch simply shows the other side ------------ */
@media (prefers-reduced-motion: reduce) {
  .theme-toggle, .theme-toggle *, .theme-toggle *::before, .theme-toggle *::after {
    animation: none !important; transition: none !important;
  }
  .theme-toggle.is-out .tt-face { opacity: 1; }
}
