/* wheelyesorno.com - bright arcade-carnival theme */

/* ---------- Fonts, self-hosted ----------
   Google Fonts cost three requests across two extra domains, and the font
   files could not even be discovered until the remote CSS had been fetched
   and parsed - a serial round trip that hurt most on high-latency links.
   Serving them from our own origin puts them on the same edge-cached
   connection as everything else.

   Both families are VARIABLE fonts: one file spans the whole weight range,
   so 400/500/600 all come from a single download per family. */
@font-face {
  font-family: 'Fredoka';
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;            /* show text immediately, swap when ready */
  src: url('/assets/fonts/fredoka-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Outfit';
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url('/assets/fonts/outfit-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  --yes:      #FF3D7F;
  --no:       #00C2A8;
  --sun:      #FFC93C;
  --violet:   #5B3FFF;
  --paper:    #FFFDF7;
  --ink:      #1A1035;
  --ink-soft: #5C5478;
  --line:     #EDE7F5;

  --shadow-sm: 0 2px 8px rgba(26, 16, 53, .07);
  --shadow-md: 0 10px 30px rgba(26, 16, 53, .10);
  --shadow-lg: 0 24px 60px rgba(26, 16, 53, .14);

  --header-h: 66px;
  --panel-w: 420px;
  --radius: 20px;
  --maxw: 1120px;

  --tint: transparent;
}

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

/* Sticky footer: the page fills the viewport even when its content does not,
   so a short page (a filtered hub showing one card, a 404) does not leave the
   footer floating mid-screen with dead space beneath it. */
html, body { min-height: 100%; }
body {
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: 'Outfit', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif;
  font-size: 17px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

/* Page-wide tint wash driven by the last result */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  background: var(--tint);
  opacity: 0;
  pointer-events: none;
  transition: opacity .5s ease, background .3s ease;
  z-index: 0;
}
body.tinted::before { opacity: .09; }

h1, h2, h3, .display {
  font-family: 'Fredoka', ui-rounded, 'Outfit', sans-serif;
  font-weight: 600;
  line-height: 1.08;
  letter-spacing: -.02em;
  margin: 0;
}

a { color: var(--violet); }

.wrap {
  width: 100%; max-width: var(--maxw);
  margin: 0 auto; padding: 0 22px;
  position: relative; z-index: 1;
}

.eyebrow {
  font-size: 12px; font-weight: 600;
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--ink-soft); margin: 0 0 14px;
}

:where(a, button, summary, input, textarea, select, [tabindex]):focus-visible {
  outline: 3px solid var(--violet);
  outline-offset: 3px;
  border-radius: 6px;
}

.skip {
  position: absolute; left: -9999px;
  background: var(--ink); color: #fff;
  padding: 10px 16px; border-radius: 0 0 12px 0; z-index: 99;
}
.skip:focus { left: 0; top: 0; }

.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

/* ---------- Header ---------- */
.site-header {
  position: sticky; top: 0; z-index: 20;
  background: rgba(255, 253, 247, .86);
  backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--line);
}
.header-inner {
  display: flex; align-items: center;
  justify-content: space-between; height: 66px;
}

.brand { display: flex; align-items: center; gap: 10px; text-decoration: none; color: var(--ink); }
.brand-mark {
  width: 30px; height: 30px; border-radius: 50%; flex: none;
  background: conic-gradient(var(--yes) 0 25%, var(--no) 0 50%, var(--yes) 0 75%, var(--no) 0);
  box-shadow: 0 0 0 3px var(--paper), 0 0 0 4px var(--line);
}
.brand-name {
  font-family: 'Fredoka', sans-serif; font-weight: 600;
  font-size: 19px; letter-spacing: -.02em;
}
.brand-name .dim { color: var(--ink-soft); font-weight: 400; }

.nav { display: flex; align-items: center; gap: 30px; }
.nav a {
  color: var(--ink-soft); text-decoration: none;
  font-size: 15px; font-weight: 500;
  transition: color .18s ease;
}
.nav a:hover { color: var(--violet); }
@media (max-width: 800px) { .nav { display: none; } }

/* ---------- Page heading (below the fold on generated pages) ---------- */
.page-head { padding: 64px 0 0; text-align: center; }
.page-head h1 { font-size: clamp(28px, 4.2vw, 44px); margin-bottom: 12px; }
.page-intro {
  color: var(--ink-soft); margin: 0 auto;
  max-width: 54ch; font-size: 17px;
}

/* ---------- Stage ----------
   The panel is fixed to the right edge and the wheel is centred in the space
   that is left. They are siblings, not grid cells, so neither one's size is
   pinned to the other's - the wheel can be positioned on its own terms. */
.stage {
  position: relative;
  height: calc(100dvh - var(--header-h));
  min-height: 560px;
  overflow: hidden;
}
/* The decorative glow is oversized on purpose; clipping it here stops it
   widening the document on narrow screens. */
.stage, .stage-wheel { overflow-x: clip; }

.stage-wheel {
  position: absolute;
  inset: 0 var(--panel-w) 0 0;      /* stop short of the panel */
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 8px 18px 12px;
  transition: right .32s cubic-bezier(.4, 0, .2, 1);
}
.stage.panel-closed .stage-wheel { right: 0; }

.stage-wheel::after {
  content: '';
  position: absolute; left: 50%; top: 50%;
  width: 900px; height: 900px; max-width: 150%;
  transform: translate(-50%, -50%);
  background: radial-gradient(circle, rgba(255,201,60,.26) 0%, rgba(255,61,127,.11) 44%, transparent 68%);
  z-index: -1; pointer-events: none;
}

.wheel-head { flex: none; }
.wheel-hint { flex: none; color: var(--ink-soft); font-size: 14.5px; margin: 0; }
.hint-touch { display: none; }
@media (pointer: coarse), (max-width: 900px) {
  .hint-desktop { display: none; }
  .hint-touch { display: inline; }
}
.wheel-hint kbd {
  font: inherit; font-size: 13px;
  background: #fff; border: 1px solid var(--line);
  border-bottom-width: 2px; border-radius: 6px;
  padding: 1px 7px;
}

/* ---------- Mode switch ---------- */
.modes {
  display: inline-flex; gap: 4px; padding: 4px;
  background: #fff; border: 1px solid var(--line);
  border-radius: 100px; box-shadow: var(--shadow-sm);
}
.mode {
  font-family: 'Fredoka', sans-serif; font-weight: 500; font-size: 14.5px;
  padding: 9px 20px; border-radius: 100px;
  border: none; background: transparent; color: var(--ink-soft);
  cursor: pointer; transition: background .2s ease, color .2s ease;
}
.mode[aria-pressed="true"] { background: var(--ink); color: #fff; }

/* ---------- Wheel ---------- */
/* Square, and bounded by whichever runs out first: the pane's width or its
   height. Sizing off the viewport alone is what forced the earlier scroll. */
.wheel-zone {
  position: relative;
  flex: 0 1 auto;
  /* The pawl overhangs the top of this box, so the row needs headroom above
     the wheel or the stage's overflow clip cuts the tip off.

     That headroom is a fixed length, NOT a percentage: percentage margins
     resolve against the container's WIDTH, so on a wide-but-short window the
     margin grew with the width while the height budget below only ever
     subtracted a constant - the wheel then ran past the bottom of the stage
     and the page scrolled. Being a fixed value, --pawl-gap can be subtracted
     from the same budget it consumes, which is what keeps the two in step. */
  --pawl-gap: 54px;
  width: min(100%, calc(100dvh - var(--header-h) - var(--pawl-gap) - 96px));
  max-width: 820px;
  aspect-ratio: 1;
  margin-top: var(--pawl-gap);
}

/* ---------- Fullscreen toggle ----------
   Sits in the wheel pane's corner rather than the header, so it stays put
   when the browser hides its own chrome in fullscreen. */
.fs-btn {
  position: absolute; top: 10px; left: 12px;
  width: 38px; height: 38px; border-radius: 50%;
  background: #fff; border: 1px solid var(--line);
  box-shadow: var(--shadow-sm);
  cursor: pointer; z-index: 12;
  display: grid; place-items: center;
  transition: transform .2s ease, box-shadow .2s ease;
}
.fs-btn:hover { transform: scale(1.08); box-shadow: var(--shadow-md); }
.fs-btn svg {
  width: 19px; height: 19px;
  fill: none; stroke: var(--ink);
  stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;
}
.fs-btn .fs-icon-close { display: none; }
.stage.is-fullscreen .fs-btn .fs-icon-open  { display: none; }
.stage.is-fullscreen .fs-btn .fs-icon-close { display: block; }

/* Fullscreen puts the whole document up, so the confetti canvas, toast and
   result overlay - all siblings of the stage - keep painting. The page chrome
   is hidden with a class instead, and the stage takes the whole viewport.
   The fullscreen backdrop is black by default, so it is repainted too. */
:root:fullscreen::backdrop { background: var(--paper); }
body.is-fullscreen { background: var(--paper); overflow: hidden; }
body.is-fullscreen .site-header,
body.is-fullscreen .wheel-hint,
body.is-fullscreen .entries-toggle { display: none; }
/* Everything below the fold is irrelevant while the wheel owns the screen.
   The result overlay is also a direct child of <main>, so it has to be
   excluded by name here - otherwise the win card is display:none in
   fullscreen and the spin appears to end with nothing happening. */
body.is-fullscreen main > :not(.stage):not(.result-scrim),
body.is-fullscreen .site-footer { display: none; }

/* Fullscreen is the wheel and nothing else, at EVERY size.

   This deliberately does not branch on a media query. Entering fullscreen
   resizes the viewport to the SCREEN, not the window: a narrow window that
   was matching the mobile rules becomes a 1280px-wide viewport the moment
   fullscreen starts, the mobile query stops matching, and the layout falls
   back to the desktop split - panel and all - which is exactly the bug this
   replaces. One rule for all sizes cannot drift like that.

   The panel and its toggles go entirely; there is nothing to lay out around,
   so the wheel is simply centred in the viewport. */
body.is-fullscreen .stage-controls,
body.is-fullscreen .panel-toggle,
body.is-fullscreen .entries-toggle { display: none !important; }

body.is-fullscreen .stage {
  height: 100dvh;
  min-height: 100dvh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  overflow: hidden;
}

/* Fill the pane rather than sitting in a corner of it. */
body.is-fullscreen .stage-wheel {
  position: static;
  inset: auto;
  width: 100%;
  height: 100%;
  min-height: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  right: auto;
}

/* Square, bounded by whichever side runs out first. The pawl overhangs the
   top, so the height budget subtracts twice the gap and the box is padded
   equally top and bottom - a one-sided margin would shove the wheel below
   centre on a short screen. */
body.is-fullscreen .wheel-zone,
body.is-fullscreen .stage.entries-hidden .wheel-zone {
  width: min(100vw - 24px, calc(100dvh - (var(--pawl-gap) * 2) - 48px));
  max-width: none;
  margin-top: 0;
}

@media (max-width: 900px), (pointer: coarse) {
  .fs-btn { width: 44px; height: 44px; top: 8px; left: 8px; }
}

/* Ticker pawl - the signature element.
   Anchored above the rim and pivoting from its own mounting point, so it reads
   as a fixed pawl the wheel passes under rather than a marker riding the disc.
   Each peg that goes by kicks it, and it springs back. */
.pawl {
  position: absolute;
  top: -8.4%;                    /* sit above the rim, tip overlapping it */
  left: 50%;
  width: 7.6%;
  min-width: 30px;
  z-index: 4;
  transform-origin: 50% 14%;     /* pivot at the rivet, near the top */
  transform: translateX(-50%) rotate(0deg);
  filter: drop-shadow(0 3px 7px rgba(26, 16, 53, .45));
  pointer-events: none;
}
.pawl svg { overflow: visible; display: block; width: 100%; height: auto; }
.pawl-arm { stroke: rgba(26, 16, 53, .42); stroke-width: 1.1; stroke-linejoin: round; }
.pawl-gloss { pointer-events: none; }
.pawl-cap { stroke: rgba(26, 16, 53, .35); stroke-width: 1; }
.pawl-rivet { fill: #1A1035; opacity: .9; }


.wheel {
  width: 100%; height: 100%;
  border-radius: 50%;
  box-shadow: var(--shadow-lg), 0 0 0 10px #fff, 0 0 0 13px var(--line);
  display: block;
  cursor: pointer;
}

.hub {
  position: absolute; top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  width: 21%; height: 21%;
  border-radius: 50%;
  background: #fff; border: none;
  box-shadow: var(--shadow-md), 0 0 0 4px var(--line);
  cursor: pointer; z-index: 2;
  font-family: 'Fredoka', sans-serif; font-weight: 600;
  font-size: clamp(12px, 1.5vw, 17px);
  color: var(--ink);
  transition: transform .16s ease;
}
.hub:hover:not(:disabled) { transform: translate(-50%, -50%) scale(1.07); }
.hub:active:not(:disabled) { transform: translate(-50%, -50%) scale(.96); }
.hub:disabled { cursor: wait; opacity: .6; }

.wheel-empty {
  display: grid; place-items: center;
  width: min(100%, 380px); aspect-ratio: 1;
  border-radius: 50%;
  border: 3px dashed var(--line);
  color: var(--ink-soft); font-size: 15px;
  padding: 40px; text-align: center;
}
.wheel-empty[hidden] { display: none; }

/* ---------- Entries toggle (phone only) ---------- */
.entries-toggle { display: none; }

/* ---------- Control panel ---------- */
.stage-controls {
  position: absolute;
  top: 0; right: 0; bottom: 0;
  width: var(--panel-w);
  background: #fff;
  border-left: 1px solid var(--line);
  overflow: hidden;
  transition: transform .32s cubic-bezier(.4, 0, .2, 1);
}
.stage.panel-closed .stage-controls { transform: translateX(100%); }
.controls-inner {
  height: 100%;
  overflow-y: auto;
  padding: 22px;
  width: var(--panel-w);          /* keeps content from reflowing as it closes */
  display: flex; flex-direction: column; gap: 16px;
}

/* A labelled button at the top of the stage. The previous version was a 34px
   chevron circle pinned to the vertical middle of the panel edge, which read
   as a carousel arrow rather than a control and was easy to miss entirely. */
.panel-toggle {
  /* Sits OUTSIDE the panel's left edge, not over it: anchoring to
     right:var(--panel-w) and shifting fully left keeps it clear of the tab
     row it would otherwise cover. */
  position: absolute; top: 14px; right: var(--panel-w);
  transform: translateX(-14px);
  display: inline-flex; align-items: center; gap: 8px;
  height: 40px; padding: 0 16px;
  border-radius: 100px;
  background: #fff; border: 1px solid var(--line);
  box-shadow: var(--shadow-md);
  cursor: pointer; z-index: 12;
  font-family: 'Fredoka', sans-serif;
  font-size: 14.5px; font-weight: 500; color: var(--ink);
  white-space: nowrap;
  transition: right .32s cubic-bezier(.4, 0, .2, 1),
              background .2s ease, box-shadow .2s ease;
}
.panel-toggle:hover { background: var(--paper); box-shadow: var(--shadow-lg); }
.panel-toggle .pt-icon { display: grid; place-items: center; }
.panel-toggle .pt-icon svg {
  width: 17px; height: 17px;
  fill: none; stroke: var(--ink);
  stroke-width: 2; stroke-linecap: round;
}
/* Panel closed: the button sits inside the right edge of the stage. */
/* Panel closed: the button tucks inside the stage's right edge. */
.stage.panel-closed .panel-toggle {
  right: 0;
  transform: translateX(-14px);
}

/* Chevron points the way the panel will travel, and flips when it is closed. */
.chev {
  width: 8px; height: 8px;
  border-right: 2px solid var(--ink);
  border-bottom: 2px solid var(--ink);
  transform: rotate(-45deg); margin-left: -3px;
  transition: transform .3s ease;
}
.stage.panel-closed .chev { transform: rotate(135deg); margin-left: 3px; }

/* ---------- Full-screen result ---------- */
.result-scrim {
  position: fixed; inset: 0; z-index: 50;
  display: grid; place-items: center;
  padding: 24px;
  background: rgba(26, 16, 53, .40);
  backdrop-filter: blur(6px);
  opacity: 0;
  transition: opacity .28s ease;
}
.result-scrim[hidden] { display: none; }
.result-scrim.show { opacity: 1; }

.result-card {
  background: #fff;
  border-radius: 26px;
  padding: 40px 44px;
  text-align: center;
  width: min(100%, 460px);
  box-shadow: 0 30px 80px rgba(26, 16, 53, .3);
  border-top: 8px solid var(--tone, var(--violet));
  transform: translateY(16px) scale(.96);
  transition: transform .32s cubic-bezier(.2, .8, .3, 1);
}
.result-scrim.show .result-card { transform: none; }

.result-label {
  font-size: 11.5px; font-weight: 600;
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--ink-soft); margin: 0 0 10px;
}
.result-word {
  font-family: 'Fredoka', sans-serif; font-weight: 600;
  font-size: clamp(38px, 8vw, 62px); line-height: 1.05;
  color: var(--tone, var(--violet));
  letter-spacing: -.03em; word-break: break-word;
}
.result-note { color: var(--ink-soft); font-size: 15.5px; margin: 10px 0 0; }
.result-actions {
  display: flex; gap: 10px; justify-content: center;
  margin-top: 26px; flex-wrap: wrap;
}
.result-close {
  position: absolute; top: 22px; right: 22px;
  width: 42px; height: 42px; border-radius: 50%;
  background: rgba(255,255,255,.9); border: none;
  font-size: 22px; color: var(--ink); cursor: pointer;
  line-height: 1;
}

/* ---------- Buttons ---------- */
.btn {
  font-family: 'Fredoka', sans-serif; font-weight: 500; font-size: 16px;
  padding: 13px 26px; border-radius: 100px;
  border: 2px solid var(--ink);
  background: var(--sun); color: var(--ink);
  cursor: pointer; text-decoration: none;
  display: inline-block;
  box-shadow: 0 4px 0 var(--ink);
  transition: transform .12s ease, box-shadow .12s ease;
}
.btn:hover { transform: translateY(2px); box-shadow: 0 2px 0 var(--ink); }
.btn:active { transform: translateY(4px); box-shadow: 0 0 0 var(--ink); }

.btn-sm { font-size: 14px; padding: 9px 18px; box-shadow: 0 3px 0 var(--ink); }
.btn-sm:hover { box-shadow: 0 1px 0 var(--ink); }

.btn-ghost {
  background: #fff; border-color: var(--line);
  color: var(--ink-soft); box-shadow: 0 4px 0 var(--line);
}
.btn-ghost:hover { box-shadow: 0 2px 0 var(--line); }
.btn-ghost.btn-sm { box-shadow: 0 3px 0 var(--line); }
.btn-ghost.btn-sm:hover { box-shadow: 0 1px 0 var(--line); }

/* ---------- Panel (right column) ---------- */
.panel {
  background: #fff; border: 1px solid var(--line);
  border-radius: var(--radius); padding: 22px;
  box-shadow: var(--shadow-sm);
}
.panel + .panel { margin-top: 18px; }
.panel h2, .panel h3 {
  font-size: 12px; font-weight: 600;
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--ink-soft);
  font-family: 'Outfit', sans-serif;
  margin: 0 0 14px;
}

.field-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.field-row + .field-row { margin-top: 14px; }
.field-row label { font-size: 15px; color: var(--ink); }
.field-ctl { display: inline-flex; align-items: center; gap: 10px; }
.field-ctl output { font-size: 14px; color: var(--ink-soft); min-width: 26px; }

textarea.entries-input {
  width: 100%; font-family: inherit; font-size: 15.5px;
  padding: 14px 16px; border-radius: 16px;
  border: 2px solid var(--line); background: var(--paper);
  color: var(--ink); resize: vertical; min-height: 160px; flex: 1;
  line-height: 1.8; transition: border-color .18s ease;
}
textarea.entries-input:focus { outline: none; border-color: var(--violet); }
textarea.entries-input::placeholder { color: #A9A2BE; }

.entries-hint { font-size: 13.5px; color: var(--ink-soft); margin: 9px 0 0; }
.entries-hint code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12.5px; background: var(--paper);
  border: 1px solid var(--line); border-radius: 5px; padding: 1px 5px;
}
.entries-count { display: block; margin-top: 4px; }
.entries-count { font-weight: 600; color: var(--violet); }

.panel-actions { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 14px; }

/* Segmented control for action modes */
.seg { display: flex; gap: 4px; padding: 4px; background: var(--paper); border-radius: 100px; border: 1px solid var(--line); }
.seg button {
  flex: 1; font-family: 'Fredoka', sans-serif; font-weight: 500; font-size: 13.5px;
  padding: 8px 6px; border-radius: 100px; border: none;
  background: transparent; color: var(--ink-soft); cursor: pointer;
  transition: background .2s ease, color .2s ease;
}
.seg button[aria-pressed="true"] { background: var(--violet); color: #fff; }

.seg-note { font-size: 13.5px; color: var(--ink-soft); margin: 10px 0 0; }

/* Range + switch */
input[type="range"] { width: 130px; accent-color: var(--violet); }

.switch { position: relative; display: inline-block; width: 46px; height: 26px; flex: none; }
.switch input { opacity: 0; width: 0; height: 0; }
.switch .track {
  position: absolute; inset: 0; cursor: pointer;
  background: var(--line); border-radius: 100px;
  transition: background .2s ease;
}
.switch .track::before {
  content: ''; position: absolute;
  height: 20px; width: 20px; left: 3px; top: 3px;
  background: #fff; border-radius: 50%;
  box-shadow: var(--shadow-sm);
  transition: transform .2s ease;
}
.switch input:checked + .track { background: var(--no); }
.switch input:checked + .track::before { transform: translateX(20px); }
.switch input:focus-visible + .track { outline: 3px solid var(--violet); outline-offset: 3px; }

/* Results list */
.tally { list-style: none; margin: 0; padding: 0; }
.tally li {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; padding: 10px 0;
  border-bottom: 1px solid var(--line);
  font-size: 15px;
}
.tally li:last-child { border-bottom: none; }
.tally .name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tally .count {
  font-family: 'Fredoka', sans-serif; font-weight: 600;
  background: var(--paper); border: 1px solid var(--line);
  border-radius: 100px; padding: 2px 12px; font-size: 14px;
  flex: none;
}
.tally-empty { color: var(--ink-soft); font-size: 14.5px; margin: 0; }

/* ---------- Sections ---------- */
section { padding: 76px 0; position: relative; z-index: 1; }
.section-head { text-align: center; max-width: 48ch; margin: 0 auto 44px; }
.section-head h2 { font-size: clamp(27px, 4.4vw, 40px); margin-bottom: 12px; }
.section-head p { color: var(--ink-soft); margin: 0; }

.band { background: #fff; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); }

.grid { display: grid; gap: 20px; grid-template-columns: repeat(3, 1fr); }
@media (max-width: 880px) { .grid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 560px) { .grid { grid-template-columns: 1fr; } }

.card {
  background: var(--paper); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 26px 24px;
  transition: transform .2s ease, box-shadow .2s ease;
}
.card:hover { transform: translateY(-4px); box-shadow: var(--shadow-md); }
.card h3 { font-size: 19.5px; margin-bottom: 9px; }
.card p { color: var(--ink-soft); font-size: 15.5px; margin: 0; }

.card-icon {
  width: 46px; height: 46px; border-radius: 14px;
  display: grid; place-items: center;
  font-size: 22px; margin-bottom: 16px;
  background: var(--sun);
}
.card:nth-child(2) .card-icon { background: var(--no); }
.card:nth-child(3) .card-icon { background: var(--yes); }
.card:nth-child(4) .card-icon { background: var(--violet); }
.card:nth-child(5) .card-icon { background: var(--sun); }
.card:nth-child(6) .card-icon { background: var(--no); }

/* ---------- Preset chips ---------- */
.chips { display: flex; flex-wrap: wrap; gap: 10px; justify-content: center; }
a.chip { text-decoration: none; }
.chip {
  font-family: 'Fredoka', sans-serif; font-size: 15px; font-weight: 500;
  padding: 11px 20px; border-radius: 100px;
  border: 2px solid var(--line); background: #fff; color: var(--ink);
  cursor: pointer;
  transition: border-color .18s ease, transform .18s ease;
}
.chip:hover { border-color: var(--violet); transform: translateY(-2px); }

/* ---------- Steps ---------- */
.steps { display: grid; gap: 24px; grid-template-columns: repeat(3, 1fr); counter-reset: step; }
@media (max-width: 760px) { .steps { grid-template-columns: 1fr; } }
.step { counter-increment: step; padding-top: 12px; border-top: 3px solid var(--line); }
.step::before {
  content: counter(step, decimal-leading-zero);
  font-family: 'Fredoka', sans-serif; font-weight: 600; font-size: 14px;
  color: var(--violet); letter-spacing: .08em;
  display: block; margin-bottom: 10px;
}
.step h3 { font-size: 19px; margin-bottom: 8px; }
.step p { color: var(--ink-soft); font-size: 15.5px; margin: 0; }

/* ---------- FAQ ---------- */
.faq { max-width: 720px; margin: 0 auto; }
.faq details { border-bottom: 1px solid var(--line); }
.faq summary {
  cursor: pointer; list-style: none;
  padding: 18px 34px 18px 0;
  font-family: 'Fredoka', sans-serif; font-weight: 500; font-size: 17.5px;
  position: relative;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: '+';
  position: absolute; right: 4px; top: 50%; transform: translateY(-50%);
  font-size: 24px; color: var(--violet); line-height: 1;
  transition: transform .2s ease;
}
.faq details[open] summary::after { transform: translateY(-50%) rotate(45deg); }
.faq details p { color: var(--ink-soft); margin: 0 0 18px; padding-right: 34px; font-size: 15.5px; }

/* ---------- Footer ---------- */
.site-footer { background: var(--ink); color: #C9C2E0; padding: 52px 0 28px; position: relative; z-index: 1; }
.footer-top { display: flex; justify-content: space-between; gap: 30px; flex-wrap: wrap; margin-bottom: 32px; }
.site-footer .brand-name { color: #fff; }
.site-footer .brand-name .dim { color: #8F86B0; }
.footer-tag { color: #8F86B0; font-size: 15px; margin: 12px 0 0; max-width: 30ch; }
.footer-links { display: flex; gap: 46px; flex-wrap: wrap; }
.footer-col h4 {
  font-size: 12px; letter-spacing: .14em; text-transform: uppercase;
  color: #8F86B0; margin: 0 0 14px; font-weight: 600;
  font-family: 'Outfit', sans-serif;
}
.footer-col a { display: block; color: #C9C2E0; text-decoration: none; font-size: 15px; margin-bottom: 10px; }
.footer-col a:hover { color: var(--sun); }
.footer-bottom {
  border-top: 1px solid rgba(255, 255, 255, .11);
  padding-top: 22px; font-size: 14px; color: #8F86B0;
  display: flex; justify-content: space-between; gap: 14px; flex-wrap: wrap;
}

/* ---------- Confetti ---------- */
.confetti-canvas {
  position: fixed; inset: 0;
  /* Above the result scrim (z 50), so pieces fall IN FRONT of the card
     rather than behind it. Safe only because the canvas is pointer-events:
     none - the buttons underneath stay clickable through it. */
  pointer-events: none; z-index: 60;
}

/* ---------- Toast ---------- */
.toast {
  position: fixed; left: 50%; bottom: 28px;
  transform: translate(-50%, 20px);
  background: var(--ink); color: #fff;
  padding: 12px 22px; border-radius: 100px;
  font-size: 15px; box-shadow: var(--shadow-lg);
  opacity: 0; pointer-events: none;
  transition: opacity .25s ease, transform .25s ease;
  z-index: 40;
}
.toast.show { opacity: 1; transform: translate(-50%, 0); }

/* ---------- Scroll reveal ---------- */
.reveal {
  opacity: 0; transform: translateY(20px);
  transition: opacity .6s ease, transform .6s cubic-bezier(.2, .8, .3, 1);
}
.reveal.in { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  .reveal { opacity: 1; transform: none; transition: none; }
  .card:hover, .chip:hover { transform: none; }
}

@media (max-width: 560px) {
  section { padding: 54px 0; }
  .stage { padding: 22px 0 44px; }
  .panel { padding: 18px; }
}

/* ---------- Stage: narrow screens ----------
   60% of traffic is mobile, so the phone layout is not a fallback. The wheel
   and the entry list have to share one screen: wheel on top at full width,
   the panel directly under it, and the fold falling inside the list rather
   than above it. Nothing important sits below a scroll. */
@media (max-width: 900px) {
  .stage {
    height: auto;
    min-height: 0;
    overflow: visible;
    display: flex;
    flex-direction: column;
  }

  .stage-wheel {
    position: relative;      /* keeps the glow anchored once it is not absolute */
    inset: auto;
    min-height: 0;
    /* Just the wheel and its hint - no forced full-screen height, so the
       panel starts near the fold instead of a screen below it. */
    padding: 10px 12px 12px;
    gap: 6px;
  }
  .stage.panel-closed .stage-wheel { right: auto; }

  /* Edge to edge, capped so it never eats the whole screen on a tall phone. */
  .wheel-zone {
    width: min(100% - 8px, 58dvh, 520px);
  }

  .wheel-hint { font-size: 13.5px; }

  .stage-controls {
    position: static;
    width: 100%;
    border-left: none;
    border-top: 1px solid var(--line);
    overflow: visible;
    transform: none;
  }
  .stage.panel-closed .stage-controls { transform: none; }

  .controls-inner {
    width: 100%;
    max-width: 620px;
    margin: 0 auto;
    height: auto;
    overflow: visible;
    padding: 0 0 24px;
  }

  .pane { overflow: visible; padding: 14px 12px; gap: 10px; min-width: 0; }

  /* Repeat control on one line, the tool buttons on the next. */
  .col-toggles { flex-wrap: wrap; row-gap: 10px; }
  .col-spacer { flex-basis: 100%; height: 0; }
  .rows, .row { max-width: 100%; }
  /* Tall enough to show several entries without becoming its own scroller. */
  .rows { max-height: none; overflow: visible; }

  /* Sticky tabs keep Entries/Results reachable while scrolling the list. */
  .tabs {
    position: sticky;
    top: var(--header-h);
    z-index: 3;
  }

  .panel-toggle { display: none; }

  /* A full-width bar under the wheel: the list is long on a phone, and being
     able to put it away means the wheel is one tap from filling the screen. */
  .entries-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    margin-top: 4px;
    padding: 12px 22px;
    min-height: 48px;
    border: 1px solid var(--line);
    border-radius: 100px;
    background: #fff;
    color: var(--ink);
    font-family: 'Fredoka', sans-serif;
    font-size: 15px;
    font-weight: 500;
    cursor: pointer;
    box-shadow: var(--shadow-sm);
  }
  .et-chev {
    width: 8px; height: 8px;
    border-right: 2px solid var(--ink-soft);
    border-bottom: 2px solid var(--ink-soft);
    transform: rotate(45deg) translate(-2px, -2px);
    transition: transform .25s ease;
  }
  .stage.entries-hidden .et-chev {
    transform: rotate(-135deg) translate(-2px, -2px);
  }

  /* Collapsed: the panel is gone and the wheel takes the screen it leaves. */
  .stage.entries-hidden .stage-controls { display: none; }
  .stage.entries-hidden .stage-wheel {
    min-height: calc(100dvh - var(--header-h));
    justify-content: center;
  }
  .stage.entries-hidden .wheel-zone {
    width: min(100%, 68dvh, 560px);
  }
  .stage.entries-hidden .stage-wheel { padding-left: 4px; padding-right: 4px; }
}



@media (max-width: 560px) {
  .result-card { padding: 30px 22px; border-radius: 22px; }
  .page-head { padding: 40px 0 0; }
  section { padding: 44px 0; }
  .wrap { padding: 0 16px; }

  /* The result overlay is the moment that matters on a phone: give the card
     the screen and stack the buttons for a thumb.

     Centred rather than bottom-anchored. Sitting on the bottom edge put the
     card where a phone's own browser chrome and gesture bar already are, and
     it leaves nowhere for anything below the buttons - the space under the
     card is where an ad unit would eventually go. */
  .result-scrim { padding: 16px; align-items: center; }
  .result-card { width: 100%; }
  .result-actions { flex-direction: column; }
  .result-actions .btn { width: 100%; }
  .result-close { top: 14px; right: 14px; }
}

/* Very short screens: the wheel yields first so the list stays visible. */
@media (max-width: 900px) and (max-height: 700px) {
  .wheel-zone { width: min(100% - 8px, 48dvh, 400px); }
}

/* ---------- Panel tabs ---------- */
.controls-inner { padding: 0; gap: 0; }

.tabs {
  display: flex; flex: none;
  border-bottom: 1px solid var(--line);
  padding: 0 8px;
  background: #fff;
  position: sticky; top: 0; z-index: 2;
}
.tab {
  font-family: 'Fredoka', sans-serif; font-weight: 500; font-size: 14.5px;
  padding: 15px 14px 13px;
  border: none; background: none; color: var(--ink-soft);
  cursor: pointer; position: relative;
  display: inline-flex; align-items: center; gap: 7px;
  transition: color .18s ease;
}
.tab:hover { color: var(--ink); }
.tab[aria-selected="true"] { color: var(--ink); }
.tab[aria-selected="true"]::after {
  content: ''; position: absolute; left: 10px; right: 10px; bottom: -1px;
  height: 3px; border-radius: 3px 3px 0 0; background: var(--violet);
}
.tab-badge {
  font-size: 12px; font-weight: 600;
  background: var(--paper); border: 1px solid var(--line);
  border-radius: 100px; padding: 1px 8px; color: var(--ink-soft);
  min-width: 22px; text-align: center;
}
.tab[aria-selected="true"] .tab-badge {
  background: var(--violet); border-color: var(--violet); color: #fff;
}

/* A pane fills the panel so the entry box can grow with the window. */
.pane {
  flex: 1; min-height: 0;
  display: flex; flex-direction: column; gap: 12px;
  padding: 16px;
  overflow-y: auto;
}
.pane[hidden] { display: none; }

.pane-row { flex: none; }
.pane-tools { display: flex; gap: 8px; flex-wrap: wrap; }

.select {
  width: 100%; font-family: inherit; font-size: 15px;
  padding: 11px 14px; border-radius: 12px;
  border: 2px solid var(--line); background: #fff; color: var(--ink);
  cursor: pointer;
}
.select:focus { outline: none; border-color: var(--violet); }

/* The entry box is the point of the panel: give it everything left over. */
.entries-input {
  flex: 1; min-height: 180px;
  width: 100%; font-family: inherit; font-size: 15.5px;
  padding: 14px 16px; border-radius: 14px;
  border: 2px solid var(--line); background: var(--paper);
  color: var(--ink); resize: none; line-height: 1.85;
  transition: border-color .18s ease;
}
.entries-input:focus { outline: none; border-color: var(--violet); }
.entries-hint { flex: none; font-size: 13px; color: var(--ink-soft); margin: 0; }

@media (max-width: 900px) {
  .pane { overflow: visible; }
  .entries-input { min-height: 200px; }
  .tabs { position: static; }
}

/* ---------- Entry rows ---------- */
.add-row { display: flex; gap: 8px; }
.add-input {
  flex: 1; min-width: 0;
  font-family: inherit; font-size: 15px;
  padding: 11px 14px; border-radius: 12px;
  border: 2px solid var(--line); background: var(--paper); color: var(--ink);
}
.add-input:focus { outline: none; border-color: var(--violet); background: #fff; }
.add-input::placeholder { color: #A9A2BE; }
.add-btn {
  flex: none; width: 42px; border-radius: 12px;
  border: none; background: var(--violet); color: #fff;
  font-size: 22px; line-height: 1; cursor: pointer;
  transition: filter .18s ease;
}
.add-btn:hover { filter: brightness(1.1); }

.col-toggles { display: flex; align-items: center; gap: 6px; }
.col-toggle {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 13.5px; color: var(--ink-soft); cursor: pointer;
  border: 1px solid var(--line); border-radius: 100px;
  padding: 5px 12px 5px 9px;
}
.col-toggle input { accent-color: var(--violet); margin: 0; }
.col-spacer { flex: 1; }

.icon-btn {
  flex: none; width: 32px; height: 32px;
  border-radius: 9px; border: 1px solid var(--line);
  background: #fff; color: var(--ink-soft);
  font-size: 13px; cursor: pointer;
  display: grid; place-items: center;
  transition: border-color .18s ease, color .18s ease;
}
.icon-btn:hover { border-color: var(--violet); color: var(--violet); }
.icon-btn.danger:hover { border-color: #E5484D; color: #E5484D; }

/* The row list is the scrolling part of the pane. */
.rows {
  list-style: none; margin: 0; padding: 0;
  flex: 1; min-height: 120px; overflow-y: auto;
  border: 1px solid var(--line); border-radius: 12px;
  background: var(--paper);
}
.row {
  display: flex; align-items: center; gap: 6px;
  padding: 5px 6px 5px 10px;
  border-bottom: 1px solid var(--line);
}
.row:last-child { border-bottom: none; }
.row.is-off { opacity: .45; }
.row.is-off .row-name { text-decoration: line-through; }

.row-swatch {
  flex: none; width: 10px; height: 10px; border-radius: 3px;
}
.row-name {
  flex: 1; min-width: 0;
  font-family: inherit; font-size: 15px;
  border: none; background: none; color: var(--ink);
  padding: 6px 4px; border-radius: 6px;
}
.row-name:focus { outline: none; background: #fff; box-shadow: 0 0 0 2px var(--violet); }




.row-btn {
  flex: none; width: 26px; height: 26px;
  border: none; background: none; cursor: pointer;
  border-radius: 6px; color: var(--ink-soft);
  font-size: 13px; display: grid; place-items: center;
  transition: background .15s ease, color .15s ease;
}
.row-btn:hover { background: #fff; color: var(--ink); }
.row-btn.del:hover { color: #E5484D; }
.row-btn input { accent-color: var(--violet); margin: 0; cursor: pointer; }

.rows-empty {
  padding: 24px 16px; text-align: center;
  color: var(--ink-soft); font-size: 14.5px; margin: 0;
}

/* Bulk text editing stays available, just folded away. */
.bulk { flex: none; }
.bulk summary {
  cursor: pointer; list-style: none;
  font-size: 13.5px; color: var(--violet);
  padding: 4px 0;
}
.bulk summary::-webkit-details-marker { display: none; }
.bulk .entries-input { min-height: 140px; margin-top: 8px; flex: none; }

/* ---------- Steppers ---------- */
/* A - 1 + control instead of asking anyone to type ": 3". */
.stepper {
  flex: none;
  display: inline-flex; align-items: center;
  border: 1px solid var(--line); border-radius: 8px;
  background: #fff; overflow: hidden;
}
.step-btn {
  width: 24px; height: 26px;
  border: none; background: none; cursor: pointer;
  color: var(--ink-soft); font-size: 15px; line-height: 1;
  display: grid; place-items: center;
  transition: background .15s ease, color .15s ease;
}
.step-btn:hover:not(:disabled) { background: var(--paper); color: var(--violet); }
.step-btn:disabled { opacity: .35; cursor: default; }
.step-val {
  min-width: 26px; text-align: center;
  font-size: 13px; font-weight: 600; color: var(--ink);
  font-variant-numeric: tabular-nums;
  border-left: 1px solid var(--line);
  border-right: 1px solid var(--line);
  padding: 0 4px; line-height: 26px;
}

.repeat-label { font-size: 13.5px; color: var(--ink-soft); }

/* A weight above 1 is worth seeing at a glance. */
.row.is-weighted .step-val { color: var(--violet); }

/* ---------- Touch targets ----------
   Every control a finger uses clears 44x44 (WCAG 2.5.5). On a 390px screen a
   row cannot hold a name field plus five 44px controls in one line, so the
   row wraps: the name takes the full width and the controls sit beneath it. */
@media (max-width: 900px), (pointer: coarse) {
  .step-btn { width: 44px; height: 44px; font-size: 18px; }
  .step-val { min-width: 38px; line-height: 44px; font-size: 15px; }

  .icon-btn { width: 44px; height: 44px; font-size: 15px; }

  .row {
    flex-wrap: wrap;
    align-items: center;
    padding: 10px 10px 10px 12px;
    gap: 8px;
    row-gap: 6px;
  }
  /* Name on its own line so it is never squeezed to a few characters. */
  .row-name {
    flex: 1 1 100%;
    order: 1;
    font-size: 16px;              /* 16px or iOS zooms the page on focus */
    padding: 10px 8px;
    min-height: 44px;
    background: #fff;
    border: 1px solid var(--line);
  }
  .row-swatch { order: 0; width: 12px; height: 12px; }
  /* The control strip is its own wrapping line, so nothing can push the row
     wider than the screen. */
  .stepper { order: 2; flex: 0 0 auto; }
  .row-btn { order: 3; width: 44px; height: 44px; flex: 0 0 auto; }
  .row-btn input { width: 22px; height: 22px; }

  .add-input, .select { font-size: 16px; padding: 14px; min-height: 48px; }
  .add-btn { width: 56px; min-height: 48px; }

  .tab { padding: 16px 14px; font-size: 15.5px; min-height: 48px; }

  /* The hub is the primary action - comfortably thumb-sized. */
  .hub { width: 26%; height: 26%; font-size: clamp(13px, 4vw, 18px); }

  .btn { padding: 15px 26px; min-height: 48px; }
  .btn-sm { padding: 13px 20px; font-size: 15px; min-height: 44px; }

  .switch { width: 56px; height: 32px; }
  .switch .track::before { height: 26px; width: 26px; }
  .switch input:checked + .track::before { transform: translateX(24px); }

  input[type="range"] { height: 40px; width: 100%; }
  .field-ctl { flex: 1; gap: 12px; }
  .field-row { gap: 16px; }
}

/* ---------- Long-form page copy ----------
   The per-page SEO sections. A narrower measure than the marketing bands,
   because these are paragraphs to be read rather than scanned. */
.wrap-narrow { max-width: 720px; }

.band-copy h2 {
  font-size: clamp(22px, 3vw, 30px);
  margin: 44px 0 14px;
}
.band-copy h2:first-child { margin-top: 0; }
.band-copy h3 {
  font-size: clamp(17px, 2vw, 20px);
  margin: 28px 0 10px;
}
.band-copy p {
  color: var(--ink-soft);
  font-size: 17px;
  line-height: 1.72;
  margin: 0 0 16px;
  max-width: 68ch;          /* comfortable measure, not the full band */
}
.copy-list {
  margin: 0 0 18px;
  padding-left: 22px;
  color: var(--ink-soft);
  font-size: 17px;
  line-height: 1.72;
  max-width: 68ch;
}
.copy-list li { margin-bottom: 12px; }
.copy-list strong { color: var(--ink); font-weight: 600; }

@media (max-width: 640px) {
  .band-copy p, .copy-list { font-size: 16.5px; }
  .band-copy h2 { margin-top: 34px; }
}

/* ---------- All-wheels hub ----------
   Category bands are close together here: with ~100 wheels the page is a
   directory to scan, not a marketing page to scroll. */
.hub-band { padding: 30px 0 6px; }
.hub-band .section-head { margin-bottom: 16px; }
.hub-band .section-head h2 { font-size: clamp(19px, 2.4vw, 25px); }
.hub-band .chips { justify-content: flex-start; }

.band-more { margin-top: 26px; text-align: center; }

/* ---------- Theme picker ----------
   A grid of conic-gradient swatches. Each shows the theme's own slice colours,
   so the choice is made by eye rather than by reading a palette's name. */
.pane-note {
  color: var(--ink-soft); font-size: 13.5px;
  margin: 0 0 14px; line-height: 1.5;
}
.theme-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(88px, 1fr));
  gap: 12px;
  padding-bottom: 8px;
}
.theme-card {
  display: flex; flex-direction: column; align-items: center; gap: 7px;
  padding: 10px 6px 9px;
  border: 1px solid var(--line); border-radius: 14px;
  background: #fff; cursor: pointer;
  font-family: inherit;
  transition: border-color .16s ease, transform .16s ease, box-shadow .16s ease;
}
.theme-card:hover { transform: translateY(-2px); box-shadow: var(--shadow-md); }
.theme-swatch {
  width: 46px; height: 46px; border-radius: 50%;
  box-shadow: inset 0 0 0 1px rgba(26, 16, 53, .10);
}
.theme-name {
  font-size: 11.5px; line-height: 1.25; color: var(--ink-soft);
  text-align: center; word-break: break-word;
}
.theme-card.is-active {
  border-color: var(--violet);
  box-shadow: 0 0 0 2px rgba(91, 63, 255, .18);
}
.theme-card.is-active .theme-name { color: var(--ink); font-weight: 500; }

@media (max-width: 900px), (pointer: coarse) {
  .theme-grid { grid-template-columns: repeat(auto-fill, minmax(78px, 1fr)); }
  .theme-swatch { width: 42px; height: 42px; }
}

/* ---------- All-wheels hub ----------
   Preview cards rather than text chips: at 18 wheels (and later 100) what a
   visitor compares is the wheel itself, not a list of names. */
.hub-tabs {
  display: flex; flex-wrap: wrap; gap: 8px;
  margin-bottom: 26px;
}
.hub-tab {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 9px 16px; border-radius: 100px;
  border: 1px solid var(--line); background: #fff;
  font-family: 'Fredoka', sans-serif; font-size: 14.5px; font-weight: 500;
  color: var(--ink-soft); cursor: pointer;
  transition: background .18s ease, color .18s ease, border-color .18s ease;
}
.hub-tab:hover { color: var(--ink); border-color: var(--ink-soft); }
.hub-tab.is-active {
  background: var(--ink); color: #fff; border-color: var(--ink);
}
.ht-count {
  font-size: 12px; opacity: .65;
  font-variant-numeric: tabular-nums;
}
.hub-empty { color: var(--ink-soft); font-size: 15px; }

.wheel-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(184px, 1fr));
  gap: 18px;
}
/* `display: flex` on the card would beat the hidden attribute's default
   display:none, so the filter needs this to be explicit rather than relying
   on the global reset winning the cascade. */
.wheel-card[hidden] { display: none !important; }
.wheel-card {
  display: flex; flex-direction: column; align-items: center;
  gap: 8px; padding: 18px 12px 15px;
  background: #fff;
  border: 1px solid var(--line); border-radius: 18px;
  text-decoration: none; color: inherit;
  transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease;
}
.wheel-card:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow-md);
  border-color: transparent;
}
/* The preview is an inline SVG of the real wheel - wedges and labels, not a
   colour ring, so the card says what is actually on the wheel. */
.wc-svg {
  width: 104px; height: 104px;
  border-radius: 50%;
  box-shadow: 0 0 0 3px #fff, var(--shadow-sm);
}
.wc-name {
  font-family: 'Fredoka', sans-serif; font-weight: 500;
  font-size: 15px; color: var(--ink);
  text-align: center; line-height: 1.3;
}
.wc-items {
  font-size: 12.5px; color: var(--ink-soft);
  text-align: center; line-height: 1.4;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}
.wc-meta { font-size: 11.5px; color: var(--ink-soft); opacity: .8; }

@media (max-width: 640px) {
  .wheel-grid { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 14px; }
  .wc-svg { width: 78px; height: 78px; }
  .wc-name { font-size: 14px; }
  .hub-tab { font-size: 13.5px; padding: 8px 13px; }
}

/* ---------- Entry list ----------
   The wheel's own entries, in visible HTML. They previously existed only in a
   textarea attribute, so a crawler saw none of them. */
.entry-list { margin: 0 0 20px; max-width: 68ch; }
.entry-list dt {
  font-family: 'Fredoka', sans-serif; font-weight: 600;
  font-size: 16.5px; color: var(--ink);
  margin-top: 16px;
}
.entry-list dd {
  margin: 4px 0 0; padding: 0;
  color: var(--ink-soft); font-size: 16px; line-height: 1.65;
}
.entry-rest-label {
  font-family: 'Fredoka', sans-serif; font-weight: 500;
  font-size: 15px; color: var(--ink);
  margin: 22px 0 10px;
}
.entry-chips {
  display: flex; flex-wrap: wrap; gap: 7px;
  list-style: none; padding: 0; margin: 0 0 8px;
}
.entry-chips li {
  padding: 5px 12px; border-radius: 100px;
  background: #fff; border: 1px solid var(--line);
  font-size: 14px; color: var(--ink-soft);
}

/* main takes the slack so the footer is pushed to the bottom. */
main { flex: 1 0 auto; }
.site-footer { flex-shrink: 0; }

/* A filtered hub can be down to one card. Reserving height keeps the page from
   collapsing as tabs are clicked, which otherwise makes the footer jump. */
.wheel-grid { min-height: 260px; align-content: start; }
