:root {
  /* IonQ brand palette (Brand Guidelines v1.2): Ion Dark bg, neutral scale, IonQ Orange */
  --bg: #0f161b;
  --panel: #202023;
  --border: #404043;
  --gray: #a0a0a3;
  --cyan: #00e5ff;
  --orange: #ff5000;
  --white: #fafafa;
  --font-sans: 'Colfax', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  --font-mono: 'Ubuntu Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
  /* native form controls (select popups, scrollbars) render in dark theme */
  color-scheme: dark;
}

* { box-sizing: border-box; margin: 0; padding: 0; }

body {
  background: var(--bg);
  color: var(--white);
  font-family: var(--font-sans);
  display: flex;
  justify-content: center;
  min-height: 100vh;
  min-height: 100svh;
}

.app {
  /* 100% (not 100vw): 100vw includes any scrollbar the detail view shows —
     the app would overflow and clip at the right edge */
  width: min(430px, 100%);
  min-height: 100vh;
  min-height: 100svh;
  /* viewport-fit=cover lets content reach the notch and home-indicator zones;
     pad by at least the safe-area insets so edge controls stay tappable */
  --pad: clamp(16px, 5vw, 22px);
  padding: var(--pad);
  /* 30px floor: on ionq.com the fixed site navbar swallows the section's own
     top padding, so this is the only visible gap below the header — the
     phone-size --pad reads as flush against the navbar */
  padding-top: max(var(--pad), 30px);
  padding-left: max(var(--pad), env(safe-area-inset-left));
  padding-right: max(var(--pad), env(safe-area-inset-right));
  padding-bottom: max(var(--pad), env(safe-area-inset-bottom));
  display: flex;
  flex-direction: column;
  gap: clamp(10px, 2.5vw, 14px);
}

header { display: flex; justify-content: space-between; align-items: flex-start; gap: 10px; }
h1 { font-size: 20px; font-weight: 600; line-height: 1.1; }
.sub { color: var(--cyan); font-size: 10px; font-weight: 600; margin-top: 4px; }
.note { color: var(--gray); font-size: 10px; margin-top: 2px; }

/* header view toggle in the top-right slot: enters the 256 view from the
   overview, and is the 256 view's visible way back to the 10K overview */
.view-toggle {
  flex-shrink: 0;
  min-height: 44px;
  padding: 8px 14px;
  font: inherit;
  font-size: 11px;
  font-weight: 600;
  color: var(--white);
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 6px;
  cursor: pointer;
}
.view-toggle:hover { border-color: var(--orange); color: var(--orange); }

.controls {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 12px;
}
.controls label {
  color: var(--gray);
  font-size: 10px;
  font-weight: 600;
}
.control-row { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
.controls select, .controls button {
  width: 100%;
  min-height: 44px;
  background: var(--panel);
  color: var(--white);
  border: 1px solid var(--border);
  border-radius: 4px;
  font: inherit;
  font-size: 12px;
  padding: 7px 8px;
  cursor: pointer;
}
/* 16px floor: iOS Safari auto-zooms the page when focusing a form control
   whose computed font-size is under 16px */
.control-row select { min-width: 0; font-size: 16px; }
.controls .learn-more {
  min-width: 0;
  padding-inline: 14px;
  color: #ffffff;
  background: var(--orange);
  border-color: var(--orange);
  font-weight: 600;
  white-space: nowrap;
}
.controls .learn-more:hover { filter: brightness(1.3); }

.stage { position: relative; width: 100%; min-width: 0; }
#chip, #chip10k {
  width: 100%;
  height: auto;
  border-radius: 12px;
  display: block;
}
/* suppress long-press text/image selection on both dies; all browser
   scroll and zoom gestures keep their native meanings */
#chip, #chip10k {
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
}
#chip[hidden], #chip10k[hidden] { display: none; }

/* the overview's per-tile hit targets: invisible fills that catch taps, with a
   hover outline so desktop pointers can see each die is clickable */
#chip10k .tile-hit {
  fill: transparent;
  stroke: none;
  cursor: pointer;
}
#chip10k .tile-hit:hover { stroke: var(--orange); stroke-width: 3; }

/* the 10K tab is an architecture overview: no controls, footer, op explainer, or CTAs */
.view-10k .controls, .view-10k .phase, .view-10k .footer, .view-10k .playback { display: none; }

/* the 10K view fills the whole viewport: the app column becomes viewport-tall
   and the stage + svg flex into all remaining space below the header; the
   zoom math keeps the viewBox aspect matched to the svg box so the rendered
   fabric bleeds edge to edge with no letterbox bands */
.view-10k .app {
  width: 100%;
  max-width: none;
  height: 100vh;
  height: 100svh;
  min-height: 0;
  display: flex;
  flex-direction: column;
  align-items: stretch;
}
.view-10k .stage {
  flex: 1;
  width: 100%;
  max-width: none;
  min-height: 0;
  justify-self: auto;
}
.view-10k #chip10k { height: 100%; }
/* the title and toggle keep the same anchor in both views: the overview app
   spans the viewport so the stage can bleed edge to edge, so its header is
   re-centered to the detail view's column width */
.view-10k header {
  width: 100%;
  max-width: calc(min(430px, 100vw) - 2 * var(--pad));
  align-self: center;
}

/* 256-view playback bar below the die: three equal-width controls sharing one
   chrome — a centered icon/text cluster in a 44px touch target */
.playback {
  display: flex;
  gap: 8px;
  margin-top: 8px;
}
.playback button, .speed-control {
  flex: 1 1 0;
  min-width: 0;
  min-height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  background: var(--panel);
  color: var(--white);
  border: 1px solid var(--border);
  border-radius: 6px;
  font: inherit;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
}
.playback button:disabled, .speed-control:has(select:disabled) {
  opacity: 0.4;
  cursor: default;
}
.playback .icon { width: 20px; height: 20px; }
.playback .icon-chevron { width: 16px; height: 16px; }
#play-toggle .icon-play, #play-toggle.paused .icon-pause { display: none; }
#play-toggle.paused .icon-play { display: block; }
/* the visible cluster is presentational; the real select stretches invisibly
   over the whole control so any point of it opens the native picker */
.speed-control { position: relative; }
.speed-control select {
  position: absolute;
  inset: 0;
  width: 100%;
  opacity: 0;
  cursor: inherit;
  /* 16px floor: iOS Safari auto-zooms when focusing a smaller form control */
  font-size: 16px;
}
.playback button:hover:enabled,
.speed-control:hover:has(select:enabled) { border-color: var(--orange); color: var(--orange); }
/* the invisible select is the real focus target, but opacity hides its own
   outline — surface the keyboard focus ring on the visible control instead */
.speed-control:has(select:focus-visible) {
  outline: 3px solid var(--cyan);
  outline-offset: 3px;
}

/* empty-die call to action */
.load-btn {
  position: absolute;
  left: 50%;
  top: 45%;
  transform: translate(-50%, -50%);
  padding: 12px 26px;
  font: inherit;
  font-size: 12px;
  font-weight: 600;
  color: #ffffff;
  background: var(--orange);
  border: 0;
  border-radius: 8px;
  cursor: pointer;
  animation: load-pulse 1.6s ease-in-out infinite;
}
.load-btn[hidden], .view-10k .load-btn { display: none; }
@keyframes load-pulse {
  0%, 100% { box-shadow: 0 0 12px rgba(255, 80, 0, 0.35); }
  50% { box-shadow: 0 0 30px rgba(255, 80, 0, 0.8); }
}
#subtitle { color: var(--orange); }
/* attention-focusing code chooser overlay; mirrors the header dropdown, and
   either control dismisses it (they share the codeChosen state) */
.code-select {
  position: absolute;
  left: 50%;
  top: 45%;
  transform: translate(-50%, -50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  padding: 16px 20px;
  background: rgba(32, 32, 35, 0.94);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: 0 0 26px rgba(0, 0, 0, 0.6);
  width: min(310px, calc(100% - 24px));
}
.code-select p { font-size: 12px; font-weight: 600; }
.code-select .opts { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; }
.code-select button {
  min-height: 44px;
  padding: 9px 12px;
  font: inherit;
  font-size: 12px;
  font-weight: 600;
  color: var(--white);
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 6px;
  cursor: pointer;
}
.code-select button:hover { border-color: var(--orange); color: var(--orange); }
.code-select[hidden], .view-10k .code-select { display: none; }

/* FTQC path overlay: an opaque card with the paper trail and contact CTA,
   centered over the viewport; clicking outside the card closes it.
   Native <dialog> opened with showModal(): the top layer escapes any
   containing block an embedding site template creates (transform, filter,
   contain on a wrapper). The dialog is stretched over the viewport so
   outside clicks land on the dialog element, but it stays transparent —
   the app is iframed into ionq.com, where a dark scrim would stop dead at
   the iframe edge instead of covering the page. */
.ftqc {
  position: fixed;
  inset: 0;
  /* undo UA dialog chrome: centered fit-content box with a border */
  width: 100%;
  height: 100%;
  max-width: none;
  max-height: none;
  margin: 0;
  border: 0;
  color: var(--white);
  align-items: center;
  justify-content: center;
  padding: 16px;
  background: transparent;
  /* short viewports (landscape phones): scroll the card instead of clipping
     it, without chaining the scroll to the page behind the dialog */
  overflow-y: auto;
  overscroll-behavior: contain;
}
/* the UA tints ::backdrop ~10% black; clear it for the same iframe reason */
.ftqc::backdrop { background: transparent; }
.ftqc[open] { display: flex; }
.ftqc-inner {
  position: relative;
  /* auto margins center like the flex alignment, but when the card is taller
     than the viewport they collapse to 0 so the top stays reachable */
  margin: auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(12px, 3vw, 22px);
  padding: clamp(20px, 6vw, 36px);
  text-align: center;
  max-width: min(430px, 100%);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: 0 0 26px rgba(0, 0, 0, 0.6);
}
.ftqc h2 { color: var(--orange); font-size: clamp(24px, 7vw, 36px); }
.ftqc-sub { font-size: clamp(13px, 4vw, 19px); font-weight: 600; line-height: 1.35; max-width: 24ch; }
.ftqc-close {
  position: absolute;
  top: 4px;
  right: 4px;
  width: 44px;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: 0;
  color: var(--gray);
  cursor: pointer;
}
.ftqc-close:hover { color: var(--white); }
.ftqc-close .icon { width: 22px; height: 22px; }
.ftqc-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 10px clamp(12px, 4vw, 26px);
  align-items: stretch;
}
.ftqc-grid span {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding: 8px 14px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 6px;
  font-size: clamp(12px, 3.2vw, 15px);
  font-weight: 600;
}
.ftqc-grid a {
  display: flex;
  align-items: center;
  color: var(--cyan);
  font-size: clamp(12px, 3.2vw, 15px);
  font-weight: 600;
}
.ftqc-cta {
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  min-height: 44px;
  padding: 9px 16px;
  max-width: 36ch;
  border-radius: 6px;
  font-size: clamp(12px, 3.2vw, 15px);
  font-weight: 600;
  text-decoration: none;
  color: #ffffff;
  background: var(--orange);
  transition: filter 0.15s;
}
.ftqc-cta:hover { filter: brightness(1.3); }

/* constant height without a magic number: the live text and invisible
   worst-case sizers overlap in one grid cell, so the box always measures
   the tallest phase text at the current viewport width */
.phase {
  display: grid;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 8px 10px;
}
.phase > div { grid-area: 1 / 1; }
.phase-sizer { visibility: hidden; }
#phase-title, .phase-sizer .t { color: var(--orange); font-size: 12px; font-weight: 600; }
#phase-desc, .phase-sizer .d { color: var(--gray); font-size: 10px; margin-top: 3px; line-height: 1.5; }

.footer { display: flex; flex-direction: column; gap: 6px; }
.counters { font-family: var(--font-mono); font-size: 12px; }

/* legend overlay card: reuses the .ftqc scrim/card/close styles */
.legend-card h2 { font-size: 18px; }
.legend-list {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 10px;
  text-align: left;
  font-size: 12px;
  color: var(--gray);
  line-height: 1.5;
}
.legend-list li { display: flex; gap: 8px; }
.legend-list i { flex-shrink: 0; width: 9px; height: 9px; border-radius: 50%; margin-top: 5px; }
.legend-list b { color: var(--white); }

button:focus-visible,
select:focus-visible,
a:focus-visible {
  outline: 3px solid var(--cyan);
  outline-offset: 3px;
}

/* no double-tap zoom on controls: rapid play/pause or speed taps stay taps */
.controls select, .playback button, .speed-control, .code-select button,
.controls button, .load-btn, .ftqc-close, .ftqc-cta, .view-toggle {
  touch-action: manipulation;
}

/* Single-column layout in a height-limited viewport — chiefly the ionq.com
   embed, a fixed 700px-tall iframe whose width at tablet page sizes lands in
   this layout with the app column at its 430px cap: cap the stage by the
   height the other rows leave over (die aspect ~1:1 plus the 60px playback
   row), so the footer stays above the fold instead of forcing an inner
   scrollbar. The min-height bound keeps landscape phones on their natural
   vertical scroll. */
@media (max-width: 759.98px) and (min-height: 600px) {
  .stage {
    width: min(100%, calc(100svh - 370px));
    margin-inline: auto;
  }
}

/* Tablet and desktop: preserve the mobile-first content order while using the
   available width for a focused canvas plus a compact control/explainer rail.
   Requiring usable height keeps landscape phones on the single-column layout. */
@media (min-width: 760px) and (min-height: 600px) {
  .app {
    width: min(1400px, 100%);
    --pad: clamp(24px, 3vw, 48px);
    column-gap: clamp(24px, 3vw, 44px);
    row-gap: clamp(12px, 1.8vw, 22px);
    display: grid;
    grid-template-columns: minmax(0, 1fr) clamp(280px, 30vw, 360px);
    grid-template-rows: auto auto auto auto 1fr;
    grid-template-areas:
      'header header'
      'stage controls'
      'stage phase'
      'stage footer'
      'stage .';
    align-items: start;
  }

  header { grid-area: header; align-items: center; }
  h1 { font-size: clamp(26px, 2.4vw, 36px); }
  .sub { font-size: 12px; margin-top: 6px; }
  .note { font-size: 12px; margin-top: 4px; }
  .view-toggle { font-size: 13px; }

  .controls { grid-area: controls; gap: 7px; font-size: 14px; }
  .controls label { font-size: 12px; }
  /* select keeps the 16px iOS-zoom floor: tablets hit this breakpoint too */
  .controls select { font-size: 16px; padding-inline: 12px; }
  .controls .learn-more { font-size: 14px; padding-inline: 14px; }

  .stage {
    /* the svh term keeps the whole stage — near-square die plus the 52px
       playback bar — inside the viewport: 250px covers header, row gaps,
       playback, and vertical padding at every desktop size up to the point
       the 900px width cap takes over */
    grid-area: stage;
    width: min(100%, calc(100svh - 250px), 900px);
    justify-self: center;
    align-self: start;
  }

  .phase { grid-area: phase; padding: 14px 16px; border-radius: 8px; }
  #phase-title, .phase-sizer .t { font-size: 15px; }
  #phase-desc, .phase-sizer .d { font-size: 13px; margin-top: 6px; line-height: 1.55; }

  .footer { grid-area: footer; }
  .counters { font-size: 14px; }

  /* The architecture overview is intentionally one full-viewport canvas at
     every breakpoint; it must not inherit the 256-view desktop side rail. */
  .view-10k .app {
    width: 100%;
    max-width: none;
    display: flex;
  }
  /* match the desktop detail column so the title doesn't jump between views */
  .view-10k header { max-width: calc(min(1400px, 100vw) - 2 * var(--pad)); }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    scroll-behavior: auto !important;
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
  }
}

/* --- SVG animation classes --- */
.ion { transition: opacity 0.3s; }
.ion.glow { filter: drop-shadow(0 0 2.5px rgba(255, 255, 255, 0.85)); }

.gate-flash { animation: gate-flash 0.65s ease-out forwards; }
@keyframes gate-flash {
  0% { opacity: 0; }
  25% { opacity: 1; }
  100% { opacity: 0; }
}

.pulse {
  transform-box: fill-box;
  transform-origin: center;
  animation: pulse 0.9s ease-out forwards;
}
@keyframes pulse {
  0% { transform: scale(0.5); opacity: 1; }
  100% { transform: scale(2.4); opacity: 0; }
}

.ent-link { animation: dash-flow 0.6s linear infinite; }
@keyframes dash-flow {
  to { stroke-dashoffset: -4; }
}
