:root {
  --blue: #0057ff;
  --cyan: #4fd3ff;
  --pink: #ff2fb3;
  --yellow: #ffe14d;
  --green: #39ff88;
  --ink: #111;
  --red: #ff3b3b;
  --orange: #ffb347;
  --pink-soft: #ffe0e0;
  --grey: #e6e6e6;
  --soft: #f7f7f7;
  --blurple: #5865f2;
  --font: "Comic Sans MS", "Comic Sans", "Comic Neue", "Chalkboard SE", "Chalkboard", cursive;
  --mono: Consolas, "Cascadia Mono", Menlo, monospace;
}

[hidden] { display: none !important; }

/* One focus ring for every link and control. Components that show focus their own way set outline: none. */
:where(a, button, summary):focus-visible { outline: 3px solid var(--blue); outline-offset: 3px; }

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

* { box-sizing: border-box; }

html, body {
  margin: 0;
  min-height: 100%;
}

body {
  font-family: var(--font);
  color: var(--ink);
  background: var(--yellow);
  overflow-x: hidden;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

.burst {
  position: fixed;
  inset: -50vmax;
  z-index: -2;
  background: repeating-conic-gradient(from 0deg, var(--yellow) 0deg 10deg, #ffc93d 10deg 20deg);
  animation: spin 40s linear infinite;
}

#rain {
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  overflow: hidden;
}

.drop {
  position: absolute;
  top: -3rem;
  font-weight: 700;
  text-transform: uppercase;
  color: var(--green);
  -webkit-text-stroke: 2px var(--ink);
  animation: fall linear forwards;
  pointer-events: auto;
  cursor: crosshair;
  user-select: none;
}

.drop.popped {
  color: var(--red);
  animation: none;
  transition: opacity 0.6s;
  opacity: 0;
}

.ticker {
  display: flex;
  background: var(--ink);
  color: var(--yellow);
  text-transform: uppercase;
  overflow: hidden;
  white-space: nowrap;
  border-bottom: 5px solid var(--pink);
  font-size: 1.1rem;
  padding: 0.5rem 0;
}

/* Two identical groups, each at least as wide as the screen, so shifting by one group loops
   with no gap on any display. */
.ticker-group {
  display: flex;
  flex-shrink: 0;
  min-width: 100%;
  justify-content: space-around;
  animation: scroll 44s linear infinite;
}

.ticker-group span { padding-right: 3rem; }

main {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 2rem 1rem 1rem;
  gap: 1rem;
}

.mascot {
  width: clamp(160px, 28vw, 260px);
  height: auto;
  filter: drop-shadow(8px 8px 0 var(--ink));
  animation: wobble 2.6s ease-in-out infinite;
  cursor: pointer;
}

.mascot.stare {
  animation: stare 0.5s steps(2) 4;
}

.title {
  margin: 0;
  font-size: clamp(4rem, 16vw, 10rem);
  line-height: 0.9;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.title span {
  display: inline-block;
  color: var(--cyan);
  -webkit-text-stroke: 4px var(--ink);
  text-shadow: 6px 6px 0 var(--pink), 12px 12px 0 var(--ink);
  animation: bounce 1.2s ease-in-out infinite;
}

.title span:nth-child(2) { animation-delay: 0.1s; color: var(--pink); text-shadow: 6px 6px 0 var(--cyan), 12px 12px 0 var(--ink); }
.title span:nth-child(3) { animation-delay: 0.2s; color: var(--green); }
.title span:nth-child(4) { animation-delay: 0.3s; color: #fff; }
.title span:nth-child(5) { animation-delay: 0.4s; color: var(--pink); text-shadow: 6px 6px 0 var(--cyan), 12px 12px 0 var(--ink); }

/* The 404 heading: the brand guide's headline style, scaled up. The letter-by-letter wordmark treatment is for HOWIE only. */
.lost {
  margin: 0;
  font-size: clamp(5rem, 22vw, 9rem);
  line-height: 1;
  color: var(--pink);
  -webkit-text-stroke: 3px var(--ink);
  text-shadow: 5px 5px 0 var(--cyan), 10px 10px 0 var(--ink);
}

.tagline {
  max-width: 34rem;
  margin: 0.5rem 0 0;
  font-size: clamp(1.05rem, 2.6vw, 1.35rem);
  background: #fff;
  border: 4px solid var(--ink);
  border-radius: 18px;
  padding: 0.8rem 1.2rem;
  box-shadow: 6px 6px 0 var(--ink);
  transform: rotate(-1.5deg);
}

.tagline s { text-decoration-color: var(--red); text-decoration-thickness: 3px; }

/* The big gradient button for a page's main action, such as adding Howie, signing in or undoing. */
.big-btn {
  position: relative;
  margin: 1.5rem 0;
  display: inline-block;
  text-transform: uppercase;
  font-family: var(--font);
  font-weight: 700;
  font-size: clamp(1.3rem, 4vw, 2.2rem);
  color: #fff;
  text-decoration: none;
  background: linear-gradient(90deg, var(--blue), var(--pink), var(--blue));
  background-size: 200% 100%;
  border: 5px solid var(--ink);
  border-radius: 999px;
  padding: 1.1rem 2.4rem;
  box-shadow: 8px 8px 0 var(--ink);
  -webkit-text-stroke: 1px var(--ink);
  animation: pulse 1.4s ease-in-out infinite, shimmer 3s linear infinite;
  transition: transform 0.1s, box-shadow 0.1s;
}

.big-btn:hover,
.big-btn:focus-visible {
  animation: jiggle 0.25s linear infinite, shimmer 1s linear infinite;
  outline: none;
}

.big-btn:active {
  transform: translate(6px, 6px);
  box-shadow: 2px 2px 0 var(--ink);
}

.discord-sticker {
  position: absolute;
  top: -1.5em;
  right: -2.2em;
  width: 2.6em;
  height: 2.6em;
  display: grid;
  place-items: center;
  background: var(--blurple);
  border: 0.16em solid #fff;
  border-radius: 0.7em;
  box-shadow: 0 0 0 3px var(--ink), 5px 6px 0 3px rgba(17, 17, 17, 0.85);
  transform-origin: 18% 12%;
  transform: rotate(16deg);
  animation: dangle 2.4s ease-in-out infinite;
  pointer-events: none;
}

.discord-sticker svg {
  width: 68%;
  height: auto;
}

@media (max-width: 600px) {
  .discord-sticker {
    top: -1.9em;
    right: -0.3em;
    width: 2.2em;
    height: 2.2em;
  }
}

/* Tape only makes sense on a sticker that holds still. */
@media (prefers-reduced-motion: reduce) {
  .discord-sticker::before {
    content: "";
    position: absolute;
    top: -0.35em;
    left: -0.45em;
    width: 1.3em;
    height: 0.5em;
    background: rgba(255, 255, 255, 0.75);
    border: 2px solid rgba(17, 17, 17, 0.25);
    transform: rotate(-35deg);
  }
}

.buzz {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.7rem;
  max-width: 44rem;
}

.buzz li {
  background: var(--green);
  border: 3px solid var(--ink);
  border-radius: 10px;
  padding: 0.35rem 0.8rem;
  font-weight: 700;
  box-shadow: 4px 4px 0 var(--ink);
  animation: float 3s ease-in-out infinite;
}

.buzz li:nth-child(odd) { background: var(--cyan); transform: rotate(3deg); }
.buzz li:nth-child(3n) { background: var(--pink); color: #fff; }
.buzz li:nth-child(2) { animation-delay: -0.4s; }
.buzz li:nth-child(3) { animation-delay: -0.8s; }
.buzz li:nth-child(4) { animation-delay: -1.2s; }
.buzz li:nth-child(5) { animation-delay: -1.6s; }
.buzz li:nth-child(6) { animation-delay: -2s; }
.buzz li:nth-child(7) { animation-delay: -2.4s; }
.buzz li:nth-child(8) { animation-delay: -2.8s; }
/* Swapped from the pattern above: "Giveaway-allergic" is pink and "Casino-repellent" is cyan; "Set and forget" is green
   and "Free" is cyan. */
.buzz li:nth-child(5) { background: var(--pink); color: #fff; }
.buzz li:nth-child(6) { background: var(--cyan); color: var(--ink); }
.buzz li:nth-child(7) { background: var(--green); }
.buzz li:nth-child(8) { background: var(--cyan); }

footer {
  text-align: center;
  padding: 1rem;
  font-size: 0.9rem;
}

footer p { margin: 0; }

a { text-decoration: none; }

/* The tilted blue button for a secondary link, such as Read the docs or Troubleshooting. */
.blue-btn {
  display: inline-block;
  margin-bottom: 0.9rem;
  padding: 0.45rem 1.4rem;
  background: var(--blue);
  color: #fff;
  font-size: 1.2rem;
  font-weight: 700;
  border: 4px solid var(--ink);
  border-radius: 14px;
  box-shadow: 5px 5px 0 var(--ink);
  transform: rotate(-1.5deg);
  transition: transform 0.1s, background 0.1s;
}

.blue-btn:hover,
.blue-btn:focus-visible {
  background: var(--pink);
  transform: rotate(1.5deg) scale(1.04);
  outline: none;
}

/* Live status stamp above the Read the docs button, inked like the BANNED stamp. Grey until the status loads. */
.status-stamp {
  --stamp: #6b6b6b;
  display: block;
  width: fit-content;
  margin: 0.2rem auto 1.1rem;
  padding: 0 0.7rem;
  color: var(--stamp);
  font-size: 1.25rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  background: #fff;
  border: 4px solid var(--stamp);
  border-radius: 8px;
  box-shadow: 3px 3px 0 var(--ink);
  transform: rotate(-4deg);
  transition: transform 0.1s;
}

.status-stamp:hover,
.status-stamp:focus-visible {
  transform: rotate(2deg) scale(1.06);
}

/* The tilt alone is easy to miss, so keyboard focus also gets the status page's ring. */
.status-stamp:focus-visible {
  outline: 3px solid var(--blue);
  outline-offset: 4px;
}

.status-stamp[data-state="operational"] { --stamp: #12a150; }
.status-stamp[data-state="degraded"] { --stamp: #c48a00; }
.status-stamp[data-state="outage"] { --stamp: var(--red); }
.status-stamp[data-state="paused"],
.status-stamp[data-state="maintenance"] { --stamp: var(--blue); }

/* A drawn arrow (short line, chevron head) for text, used by the status date range, the docs pager and the status
   page's View update. Add .left to point back or .down to point down. Pair it with text a screen reader can read; the arrow itself is aria-hidden. */
.arrow { display: inline-block; position: relative; width: 0.95em; height: 0.14em; margin: 0 0.45em; background: currentColor; border-radius: 1px; vertical-align: 0.26em; }
.arrow::after { content: ""; position: absolute; right: -0.02em; top: 50%; width: 0.36em; height: 0.36em; border: solid currentColor; border-width: 0.14em 0.14em 0 0; transform: translateY(-50%) rotate(45deg); }
.arrow.left { transform: scaleX(-1); }
.arrow.down { transform: rotate(90deg); }
/* In a pill link the link's gap spaces the arrow, as in the docs pager and the status page's View update. */
.pill-link .arrow { margin: 0; }

.boring-links {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin-bottom: 0.6rem;
}

/* ---------- Shared components. Page stylesheets add layout, never their own copies of these. ---------- */

/* Pill links and buttons: the howie.lol button, the header and footer links, and small buttons on any page (add
   .pill-link), such as the docs pager, Sign out and Refresh.
   The page you're on, or the option that's chosen, is yellow. */
.pill-link,
.home-link,
.top-links a,
.boring-links a {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font: inherit;
  font-weight: 700;
  color: var(--ink);
  background: #fff;
  border: 3px solid var(--ink);
  border-radius: 999px;
  padding: 0.2rem 0.9rem;
  box-shadow: 3px 3px 0 var(--ink);
  cursor: pointer;
  transition: transform 0.1s, background 0.1s, box-shadow 0.1s;
}

.pill-link:hover,
.home-link:hover,
.top-links a:hover,
.boring-links a:hover {
  background: var(--cyan);
  transform: rotate(-2deg);
}

.pill-link:active { transform: translate(2px, 2px); box-shadow: 1px 1px 0 var(--ink); }
.pill-link:disabled { opacity: 0.6; cursor: progress; transform: none; }
:is(.pill-link, .top-links a, .boring-links a):is([aria-current="page"], [aria-pressed="true"]) { background: var(--yellow); }
.pill-link.small { font-size: 0.9rem; padding: 0.1rem 0.8rem; }
/* The howie.lol button: a little larger and heavier than the pill links beside it. The site's font has no weight above
   bold, so a thin outline adds the extra weight. */
.home-link { padding: 0.25rem 1rem 0.25rem 0.3rem; font-size: 1.1rem; -webkit-text-stroke: 0.3px var(--ink); }
.top-links { display: flex; flex-wrap: wrap; gap: 0.6rem; }

/* Inner pages (status, docs, legal and appeal): the same header, title, width and spacing on every one. The home,
   welcome and 404 pages are full-screen posters and don't use these. Narrow pages set --page-width. */
body.page { display: block; line-height: 1.5; }
body.page .burst { animation-duration: 120s; }
body.page.narrow { --page-width: 46rem; }

.site-head,
.page-main {
  max-width: var(--page-width, 72rem);
  margin: 0 auto;
  padding-inline: 1rem;
}

.site-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 1rem;
  padding-block: 1.25rem 0.5rem;
}

/* The poster pages centre everything in <main>; inner pages read top to bottom. */
body.page main { display: block; text-align: left; }
/* Every card and callout on the page ends with the same 1.75rem, so the gap above the footer is the same on every
   page, even when the last box is hidden. */
main.page-main { padding-block: 1rem 0; }

/* Bold whatever element carries it: the docs title is a <p>, since each docs page's own heading is the h1. */
.page-title {
  margin: 0.25rem 0 1.5rem;
  font-size: clamp(2rem, 6vw, 3rem);
  font-weight: 700;
  line-height: 1.1;
  color: var(--pink);
  -webkit-text-stroke: 2px var(--ink);
  text-shadow: 4px 4px 0 var(--cyan), 8px 8px 0 var(--ink);
}

/* Cards: the white boxes inner pages are built from. */
.card {
  background: #fff;
  border: 4px solid var(--ink);
  border-radius: 20px;
  box-shadow: 8px 8px 0 var(--ink);
  padding: 1.25rem 1.5rem;
  margin-bottom: 1.75rem;
}

.card h2 {
  margin: 0;
  font-size: 1.5rem;
  line-height: 1.2;
  color: var(--pink);
  -webkit-text-stroke: 1px var(--ink);
  text-shadow: 2px 2px 0 var(--ink);
}

.card > :first-child { margin-top: 0; }
.card > :last-child { margin-bottom: 0; }
.card-head { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 0.75rem 1rem; margin-bottom: 1rem; }
.quiet { font-size: 0.9rem; opacity: 0.75; }

/* Long text inside a card: the docs and legal pages. */
.prose { line-height: 1.6; }
.prose h2 { margin: 1.75rem 0 0.4rem; }
/* Text links only: pill links inside prose, such as the docs pager, keep their own look. */
.prose a:not(.pill-link) { color: var(--blue); font-weight: 700; }
.prose a:not(.pill-link):hover { background: var(--yellow); }
.prose li { margin-bottom: 0.35rem; }
.prose code,
.mono { font-family: var(--mono); }
.prose code {
  font-size: 0.9em;
  background: #f3f0ff;
  border: 1.5px solid #c9c2f5;
  border-radius: 6px;
  padding: 0.05em 0.35em;
  white-space: nowrap;
}

/* Callouts: notes, notices and messages. Yellow by default; info is blue, warn is pink, done is green and plain is
   a dashed white box. One that sits straight on the page, outside a card, gets a shadow like the cards. */
.callout {
  margin: 1rem 0;
  padding: 0.75rem 1rem;
  background: var(--yellow);
  border: 3px solid var(--ink);
  border-radius: 14px;
}
.callout.info { background: var(--cyan); }
.callout.warn { background: var(--pink-soft); }
.callout.done { background: var(--green); }
.callout.plain { background: #fff; border-style: dashed; }
.callout p { margin: 0; }
.callout p + p { margin-top: 0.5rem; }
.page-main > .callout { margin: 0 0 1.75rem; box-shadow: 4px 4px 0 var(--ink); }
.card > .callout:first-child { margin-top: 0; }

/* Pills: small labels such as a status, an action or a time range. White unless given a colour. */
.pill {
  display: inline-block;
  font-size: 0.85rem;
  font-weight: 700;
  line-height: 1.5;
  background: #fff;
  border: 2px solid var(--ink);
  border-radius: 999px;
  padding: 0 0.6rem;
  white-space: nowrap;
}
.pill.small { font-size: 0.75rem; padding: 0 0.4rem; }

/* Round marks: a symbol in a small circle, such as an appeal state. */
.mark {
  display: inline-grid;
  place-items: center;
  flex: none;
  width: 1.4rem;
  height: 1.4rem;
  font-size: 0.8rem;
  font-weight: 700;
  line-height: 1;
  background: #fff;
  border: 2px solid var(--ink);
  border-radius: 50%;
}

/* Each mark's symbol, set with data-symbol and named by what it means, so the same meaning gets the same symbol on
   every page. Like the brand guide's ticks, CSS draws it: it can't be selected or copied with the words beside it,
   which carry the meaning. "none" is an en dash, which fits a small circle; missing numbers use a full em dash (—). */
.mark[data-symbol="good"]::before { content: "\2713"; }
.mark[data-symbol="attention"]::before { content: "!"; }
.mark[data-symbol="failed"]::before { content: "\2715"; }
.mark[data-symbol="unknown"]::before { content: "?"; }
.mark[data-symbol="none"]::before { content: "\2013"; }
.mark[data-symbol="paused"]::before { content: "\275A\275A"; }
.mark[data-symbol="updating"]::before { content: "\21BB"; }
.mark[data-symbol="loading"]::before { content: "\2026"; }

/* A large mark, such as the overall state at the top of the status page. */
.mark.large { width: 3rem; height: 3rem; font-size: 1.6rem; border-width: 3px; box-shadow: 3px 3px 0 var(--ink); }

/* Colours shared by pills and marks. */
:is(.pill, .mark).green { background: var(--green); }
:is(.pill, .mark).yellow { background: var(--yellow); }
:is(.pill, .mark).orange { background: var(--orange); }
:is(.pill, .mark).cyan { background: var(--cyan); }
:is(.pill, .mark).grey { background: var(--grey); }
:is(.pill, .mark).soft { background: var(--soft); }
:is(.pill, .mark).red { background: var(--red); color: #fff; }

/* Pink circles: the numbers on numbered steps, and the + / − on expandable sections. */
.numbered > li::before,
.toggle > summary::before {
  display: grid;
  place-items: center;
  flex: none;
  width: 1.6rem;
  height: 1.6rem;
  font-size: 0.9rem;
  font-weight: 700;
  color: #fff;
  background: var(--pink);
  border: 2px solid var(--ink);
  border-radius: 50%;
  box-shadow: 2px 2px 0 var(--ink);
}

/* Numbered steps. Each step is at least as tall as its circle and its shadow, so circles on one-line steps never
   touch. */
.numbered { counter-reset: step; list-style: none; padding: 0; }
.numbered > li { counter-increment: step; position: relative; min-height: 1.9rem; padding-left: 2.3rem; margin-bottom: 0.75rem; }
.numbered > li:last-child { margin-bottom: 0; }
.numbered > li::before { content: counter(step); position: absolute; left: 0; top: 0.05rem; }

/* Expandable sections (<details class="toggle">): a bold summary line with a pink + that turns into − when open. */
.toggle > summary { display: flex; align-items: center; gap: 0.6rem; font-weight: 700; cursor: pointer; list-style: none; }
.toggle > summary::-webkit-details-marker { display: none; }
.toggle > summary::before { content: "+"; }
.toggle[open] > summary::before { content: "\2212"; }

@media (max-width: 650px) {
  .mark.large { width: 2.4rem; height: 2.4rem; font-size: 1.25rem; }
  .card { padding: 1rem; box-shadow: 6px 6px 0 var(--ink); }
  .card h2 { font-size: 1.4rem; }
}

@keyframes spin { to { transform: rotate(360deg); } }
@keyframes scroll { to { transform: translateX(-100%); } }
@keyframes fall { to { transform: translateY(115vh) rotate(var(--r, 360deg)); } }

@keyframes wobble {
  0%, 100% { transform: rotate(-8deg) scale(1); }
  50% { transform: rotate(8deg) scale(1.06); }
}

@keyframes stare {
  from { transform: scale(1.25); }
  to { transform: scale(1.3) rotate(2deg); }
}

@keyframes bounce {
  0%, 100% { transform: translateY(0) rotate(-3deg); }
  50% { transform: translateY(-18px) rotate(3deg); }
}

@keyframes pulse {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.07); }
}

@keyframes shimmer { to { background-position: 200% 0; } }

@keyframes jiggle {
  0% { transform: rotate(-3deg) scale(1.1); }
  50% { transform: rotate(3deg) scale(1.1); }
  100% { transform: rotate(-3deg) scale(1.1); }
}

@keyframes dangle {
  0%, 100% { transform: rotate(10deg); }
  50% { transform: rotate(24deg); }
}

@keyframes float {
  0%, 100% { translate: 0 0; }
  50% { translate: 0 -8px; }
}

@media (prefers-reduced-motion: reduce) {
  .burst,
  .title span,
  .big-btn,
  .big-btn:hover,
  .big-btn:focus-visible,
  .buzz li,
  .discord-sticker {
    animation: none;
  }

  .ticker-group { animation-duration: 120s; }
  .pill-link, .home-link, .top-links a, .boring-links a { transition: none; }
  :is(.pill-link, .home-link, .top-links a, .boring-links a):hover { transform: none; }
  .mascot { animation: wobble-gentle 6s ease-in-out infinite; }
  .mascot.stare { animation: none; }
}

@keyframes wobble-gentle {
  0%, 100% { transform: rotate(-3deg); }
  50% { transform: rotate(3deg); }
}
