*,
*::before,
*::after {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  /* Pin the document to the viewport width so the minimum mobile zoom
     level is exactly 100%. If anything is even 1px wider than the
     viewport, Chrome lets the user zoom out below 100% and then snaps
     back on touch — which produced the flashing loop while rotating
     the dial. */
  width: 100%;
  max-width: 100vw;
  overflow-x: clip;
  background: hsl(0, 0%, 9%);
  color: #e6e6e6;
  font-family:
    -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI", Roboto,
    sans-serif;
  font-size: 16px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

/* Set on <body> by dial.js while the dial is being held. Locks every
   touch gesture on the page so Chrome can't fall back to its
   smart-zoom / fit-to-content snap mid-rotation — the actual root
   cause of the flashing zoom in/out loop on mobile Chrome. */
body.is-dial-engaged {
  touch-action: none;
  overscroll-behavior: contain;
}

a {
  color: inherit;
}

main {
  max-width: 980px;
  margin: 0 auto;
  padding: 64px 24px 96px;
}

/* ---- Entrance animation (1000ms staged) ----
   1. h1                        @0–340ms    slide+fade
   2. dial                      @200–540ms  fade
   3. tagline + button + brew   @400–740ms  slide+fade
   4. steps                     @660–1000ms slide+fade
*/
@keyframes slide-fade-up {
  from {
    opacity: 0;
    filter: blur(8px);
    transform: translateY(9.6px);
  }
  to {
    opacity: 1;
    filter: blur(0);
    transform: translateY(0);
  }
}
@keyframes fade-in {
  from {
    opacity: 0;
    filter: blur(12px);
  }
  to {
    opacity: 1;
    filter: blur(0);
  }
}

.hero-text h1 {
  animation: slide-fade-up 572ms ease-out 0ms both;
}
.dial,
.try-me-arrow,
.try-me-text {
  animation: fade-in 520ms ease-out 200ms both;
}
.tagline,
.actions,
.brew-hint {
  animation: slide-fade-up 572ms ease-out 400ms both;
}
.steps {
  animation: slide-fade-up 572ms ease-out 660ms both;
}

@media (prefers-reduced-motion: reduce) {
  .hero-text h1,
  .dial,
  .try-me-arrow,
  .try-me-text,
  .tagline,
  .actions,
  .brew-hint,
  .steps {
    animation: none;
  }
}

/* ---- Hero ---- */
.hero {
  display: grid;
  grid-template-columns: 1.1fr 1fr;
  gap: 48px;
  align-items: center;
  padding: 32px 0 64px;
}

.hero-text h1 {
  margin: 0;
  font-size: 56px;
  font-weight: 500;
  letter-spacing: -0.02em;
}
.tagline {
  margin: 16px 0 32px;
  font-size: 17px;
  line-height: 1.45;
  color: #b0b0b0;
  max-width: 44ch;
}
.tagline a {
  color: #d0d0d0;
  text-decoration: underline;
  text-underline-offset: 2px;
  text-decoration-color: #444;
  transition: text-decoration-color 120ms ease-out;
}
.tagline a:hover {
  text-decoration-color: #d0d0d0;
}

.actions {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 10px;
}
.btn {
  display: inline-block;
  padding: 12px 18px;
  border-radius: 8px;
  text-decoration: none;
  font-weight: 600;
  font-size: 14px;
  border: 1px solid transparent;
  transition: background 120ms ease-out;
}
.btn.primary {
  background: #fff;
  color: #1a1a1a;
}
.btn.primary:hover {
  background: #e6e6e6;
}

.brew-hint {
  margin: 12px 0 0;
  font-size: 13px;
  color: #6f6f6f;
}
.brew-hint code {
  font-family:
    "SF Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 12.5px;
  color: #b0b0b0;
  /* Long unbroken token ("nickvalcke/switchdial/switchdial") can overflow
     a narrow phone — let it break anywhere so it can't push the page
     wider than the viewport. */
  overflow-wrap: anywhere;
}

kbd {
  display: inline-grid;
  place-items: center;
  min-width: 20px;
  padding: 1px 6px;
  background: #232323;
  border: 1px solid #2a2a2a;
  border-radius: 4px;
  font-family: inherit;
  font-size: 12px;
  color: #d0d0d0;
}

/* ---- Hero dial (1:1 with the actual app) ---- */
.hero-visual {
  position: relative;
  display: grid;
  /* Right-align the dial so its right edge lines up with the steps row
     below it, collapsing two of the three vertical rules on the right. */
  place-items: center end;
}

/* Arrow + text are positioned relative to the .dial container so the
   arrow tip lands at a predictable spot on the dial. */
.try-me-arrow {
  position: absolute;
  /* Place the SVG so its top-left tip (around path coord 14,18) sits right
     on the dial's right edge, slightly below center. */
  right: -90px;
  bottom: -28px;
  pointer-events: none;
  z-index: 3;
}
.try-me-text {
  position: absolute;
  right: -90px;
  bottom: -64px;
  font-family: "Caveat", cursive;
  font-size: 32px;
  font-weight: 700;
  line-height: 1;
  color: #b0b0b0;
  transform: rotate(6deg);
  pointer-events: none;
  white-space: nowrap;
  z-index: 3;
}
.dial {
  position: relative;
  width: 360px;
  height: 360px;
  cursor: default;
  /* Don't let the browser interpret a touch-drag as a scroll. */
  touch-action: none;
}
.try-me-btn {
  display: none; /* desktop hides it; mobile media query below shows it */
}
.dial-svg,
.rim-hover-svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}
.rim-hover-svg {
  pointer-events: none;
  transition: transform 120ms ease-out;
  transform-origin: 50% 50%;
}

.wedge-inner {
  fill: transparent;
}
.wedge-inner.is-hovered {
  fill: #2e2e2e;
}

.dial-icon {
  position: absolute;
  width: 32px;
  height: 32px;
  display: grid;
  place-items: center;
  transform: translate(-50%, -50%);
  opacity: 0.6;
  pointer-events: none;
  transition: opacity 120ms ease-out;
}
.dial-icon.is-hovered {
  opacity: 1;
}
.dial-icon img {
  width: 28px;
  height: 28px;
  display: block;
}
.dial-icon-fallback {
  box-sizing: border-box;
  width: 28px;
  height: 28px;
  display: grid;
  place-items: center;
  line-height: 1;
  background: #2e2e2e;
  border-radius: 6px;
  font-size: 14px;
  font-weight: 600;
  color: #fff;
}

.dial-label {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  font-size: 14px;
  color: #fff;
  opacity: 0.6;
  letter-spacing: 0.01em;
  pointer-events: none;
}

/* ---- Sections (no separator lines) ---- */
section {
  padding: 120px 0;
}
section h2 {
  margin: 0 0 24px;
  font-size: 14px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: #8a8a8a;
  font-weight: 600;
}

.steps {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 32px;
}
.steps li {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.step-num {
  font-size: 11px;
  letter-spacing: 0.12em;
  color: #5a5a5a;
  font-weight: 600;
  font-feature-settings: "tnum";
}
.steps p {
  margin: 0;
  font-size: 14px;
  color: #c0c0c0;
  line-height: 1.45;
}
.steps strong {
  color: #f0f0f0;
  font-weight: 600;
}

@media (max-width: 720px) {
  .steps {
    grid-template-columns: repeat(2, 1fr);
  }
}

footer {
  margin-top: 48px;
  font-size: 13px;
  color: #6f6f6f;
}
footer a {
  color: #b0b0b0;
}

@media (max-width: 720px) {
  .hero {
    grid-template-columns: 1fr;
    text-align: center;
    gap: 24px;
  }
  /* The single-column mobile hero centers the dial again. */
  .hero-visual {
    place-items: center;
  }
  .hero-text h1 {
    font-size: 40px;
  }
  .actions {
    justify-content: center;
  }
  .tagline {
    margin-left: auto;
    margin-right: auto;
  }
  /* Hide the "try me" annotation on small screens — replaced by the
     overlay button below. */
  .try-me-arrow,
  .try-me-text {
    display: none;
  }

  /* Mobile: dim the dial and overlay a "try me" button. Touches pass
     through to the page (so scrolling works) until the user opts in.
     Width is clamped to the viewport so the 360px dial never spills past
     the page on small phones (which would let the user zoom out and
     cause the touch/zoom flicker while rotating). */
  .dial {
    width: min(360px, calc(100vw - 32px));
    height: min(360px, calc(100vw - 32px));
    opacity: 0.5;
    pointer-events: none;
    touch-action: auto;
    transition: opacity 200ms ease-out;
  }
  .dial .try-me-btn {
    display: block;
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    z-index: 10;
    padding: 10px 18px;
    border: 0;
    border-radius: 999px;
    background: #fff;
    color: #1a1a1a;
    font: inherit;
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
    pointer-events: auto;
    touch-action: none; /* keep finger captured for the press-and-hold */
  }
  .dial.is-engaged {
    opacity: 1;
    pointer-events: auto;
    /* Once the finger is captured, switch the dial back to touch-action:
       none so single-finger drags can't be interpreted as pinch-rotate /
       zoom by the browser (which produced a flashing zoom loop when the
       page was zoomed slightly below 100%). */
    touch-action: none;
  }
  /* Button vanishes the moment the finger lands; the dial's own center
     label takes over (showing "Enter" / app name on hover, same as desktop). */
  .dial.is-engaged .try-me-btn {
    opacity: 0;
    pointer-events: none;
  }
}
