/*
 * Arcade — shared surface for the Lab's five playable systems.
 *
 * Art direction: the portfolio's warm atelier palette taken to a dark
 * instrument panel. Warm near-black rather than cold slate, amber as the
 * structural accent, calibration teal reserved exclusively for machine output,
 * so a glance tells you which numbers the AI produced. Fraunces carries the
 * titles (the tie back to the index), Instrument Sans runs the UI, and a mono
 * face holds every readout.
 *
 * Each page sets --arc-accent to its own hue; nothing else needs overriding.
 */

/*
 * Border-box everywhere. Without it, `width: min(500px, 100%)` on a padded
 * board resolves the 100% and *then* adds the padding and border, so every
 * board and the result dialog rendered wider than the column containing them —
 * clipped rather than visibly broken, because the body hides overflow-x. The
 * dialog was the giveaway: 280px computed, 335px on screen.
 */
*,
*::before,
*::after {
  box-sizing: border-box;
}

:root {
  --arc-void: #080807;
  --arc-ink: #0d0c0a;
  --arc-raise: rgba(255, 255, 255, .038);
  --arc-raise-strong: rgba(255, 255, 255, .07);
  --arc-line: rgba(233, 180, 92, .15);
  --arc-line-soft: rgba(255, 255, 255, .08);

  --arc-text: #f4efe6;
  --arc-dim: rgba(244, 239, 230, .58);
  /* Every use of this is body copy — stat labels, readout terms, notes, hints —
     so it has to clear 4.5:1. At .34 it composited to #5c5955 over --arc-ink for
     a ratio of 2.8:1, which failed WCAG AA on all five game pages. .52 lands at
     about 5.1:1 and still reads as the quietest tier in the panel. */
  --arc-faint: rgba(244, 239, 230, .52);

  --arc-accent: #e9b45c;
  --arc-machine: #58cfc4;
  --arc-warn: #e8735e;

  --arc-gap: 12px;
  --arc-radius: 10px;
  --arc-radius-lg: 18px;

  /*
   * Type scale.
   *
   * The small end had drifted to nine distinct sizes between 9.5px and 14px —
   * three roles wearing nine values, which is noise rather than hierarchy.
   * These are the three roles, and nothing in the micro band should introduce a
   * fourth:
   *
   *   label    uppercase tracked micro-labels (stat captions, panel titles)
   *   readout  dense mono figures, notes, captions, form rows
   *   body     nav, tables, buttons, card prose
   *
   * The steps here are deliberately closer than the 1.25 ratio a page-level
   * scale wants: an instrument panel has to put a 10px label next to a 12px
   * figure, and forcing them apart would mean 8px labels. The contrast that
   * carries hierarchy lives further up — 18.4px readouts, 32px and 64px display.
   */
  --arc-t-label: 10px;
  --arc-t-readout: 12px;
  --arc-t-body: .875rem;

  --arc-mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;
  --arc-sans: "Instrument Sans", system-ui, -apple-system, sans-serif;
  --arc-display: "Fraunces", Georgia, serif;

  --arc-ease: cubic-bezier(.2, .8, .2, 1);
  --arc-ease-out: cubic-bezier(.2, 0, 0, 1);
}

/* ------------------------------------------------------------------ *
 * Page frame
 * ------------------------------------------------------------------ */

body.arcade {
  margin: 0;
  min-height: 100dvh;
  background:
    radial-gradient(120% 78% at 50% -12%, rgba(233, 180, 92, .085), transparent 62%),
    radial-gradient(80% 55% at 12% 108%, color-mix(in srgb, var(--arc-accent) 12%, transparent), transparent 70%),
    var(--arc-void);
  color: var(--arc-text);
  font-family: var(--arc-sans);
  font-size: 16px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

/* No decorative field texture here on purpose. The boards are already dense
 * grids, so a background grid competed with the thing the page is actually
 * about — and at the opacity needed to stay out of the way it read as noise
 * rather than structure. The warm radial wash above carries the depth. */

.arc-shell {
  position: relative;
  z-index: 1;
  max-width: 1140px;
  margin: 0 auto;
  padding: clamp(22px, 3.6vw, 44px) clamp(18px, 4vw, 40px) 132px;
}

/* ------------------------------------------------------------------ *
 * Headers
 * ------------------------------------------------------------------ */

.arc-kicker {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  margin: 0 0 18px;
  font-family: var(--arc-mono);
  font-size: var(--arc-t-label);
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--arc-accent);
}

.arc-kicker::before {
  content: "";
  width: 22px;
  height: 1px;
  background: currentColor;
  opacity: .7;
}

.arc-title {
  margin: 0;
  font-family: var(--arc-display);
  font-optical-sizing: auto;
  font-weight: 600;
  font-size: clamp(2.4rem, 6vw, 4rem);
  line-height: .98;
  letter-spacing: -.035em;
  text-wrap: balance;
}

.arc-lede {
  margin: 14px 0 0;
  max-width: 54ch;
  color: var(--arc-dim);
  font-size: clamp(.94rem, 1.6vw, 1.05rem);
  text-wrap: pretty;
}

.arc-head {
  margin-bottom: clamp(20px, 3.2vw, 34px);
}

/* ------------------------------------------------------------------ *
 * Game layout: board beside an instrument rail, stacked on narrow screens.
 * ------------------------------------------------------------------ */

.arc-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(268px, 320px);
  gap: clamp(20px, 3.5vw, 40px);
  align-items: start;
}

@media (max-width: 900px) {
  .arc-layout {
    grid-template-columns: minmax(0, 1fr);
  }
}

.arc-stage {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 18px;
  min-width: 0;
}

.arc-rail {
  display: flex;
  flex-direction: column;
  gap: 14px;
  min-width: 0;
}

/* ------------------------------------------------------------------ *
 * Panels
 * ------------------------------------------------------------------ */

.arc-panel {
  position: relative;
  padding: 16px 18px;
  border: 1px solid var(--arc-line-soft);
  border-radius: var(--arc-radius-lg);
  background: linear-gradient(180deg, var(--arc-raise), rgba(255, 255, 255, .012));
}

.arc-panel-title {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin: 0 0 14px;
  font-family: var(--arc-mono);
  font-size: var(--arc-t-label);
  font-weight: 500;
  letter-spacing: .19em;
  text-transform: uppercase;
  color: var(--arc-faint);
}

/* ------------------------------------------------------------------ *
 * Numeric readouts. Tabular figures everywhere, so a rising score never
 * reflows the row it sits in.
 * ------------------------------------------------------------------ */

.arc-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(72px, 1fr));
  gap: 1px;
  border: 1px solid var(--arc-line-soft);
  border-radius: var(--arc-radius);
  background: var(--arc-line-soft);
  overflow: hidden;
}

.arc-stat {
  padding: 11px 12px 12px;
  background: var(--arc-ink);
  text-align: left;
}

.arc-stat-label {
  display: block;
  font-family: var(--arc-mono);
  font-size: var(--arc-t-label);
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--arc-faint);
}

.arc-stat-value {
  display: block;
  margin-top: 3px;
  font-family: var(--arc-mono);
  font-size: 1.15rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  letter-spacing: -.02em;
  color: var(--arc-text);
}

.arc-stat-value[data-source="machine"] {
  color: var(--arc-machine);
}

/* Readout rows inside the telemetry panel */
.arc-readout {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  padding: 5px 0;
  font-family: var(--arc-mono);
  font-size: var(--arc-t-readout);
  border-bottom: 1px dashed rgba(255, 255, 255, .06);
}

.arc-readout:last-child {
  border-bottom: 0;
}

.arc-readout dt {
  margin: 0;
  color: var(--arc-faint);
  letter-spacing: .04em;
}

.arc-readout dd {
  margin: 0;
  color: var(--arc-machine);
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  text-align: right;
}

.arc-readout dd[data-neutral] {
  color: var(--arc-dim);
}

dl.arc-readouts {
  margin: 0;
}

/* Note under a telemetry panel explaining what the algorithm is */
.arc-note {
  margin: 12px 0 0;
  padding-top: 12px;
  border-top: 1px solid var(--arc-line-soft);
  color: var(--arc-faint);
  font-size: var(--arc-t-readout);
  line-height: 1.5;
}

.arc-note code {
  font-family: var(--arc-mono);
  font-size: var(--arc-t-readout);
  color: var(--arc-accent);
}

/* ------------------------------------------------------------------ *
 * Controls
 * ------------------------------------------------------------------ */

.arc-controls {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.arc-btn {
  flex: 1 1 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 44px;
  padding: 10px 16px;
  border: 1px solid var(--arc-line-soft);
  border-radius: var(--arc-radius);
  background: var(--arc-raise);
  color: var(--arc-text);
  font-family: var(--arc-sans);
  font-size: var(--arc-t-body);
  font-weight: 600;
  letter-spacing: -.01em;
  text-decoration: none;
  cursor: pointer;
  transition:
    background-color 180ms var(--arc-ease-out),
    border-color 180ms var(--arc-ease-out),
    color 180ms var(--arc-ease-out),
    transform 180ms var(--arc-ease);
}

.arc-btn:hover {
  background: var(--arc-raise-strong);
  border-color: var(--arc-line);
}

.arc-btn:active {
  transform: scale(.975);
}

.arc-btn[data-variant="primary"] {
  background: var(--arc-accent);
  border-color: var(--arc-accent);
  color: #1b1206;
}

.arc-btn[data-variant="primary"]:hover {
  background: color-mix(in srgb, var(--arc-accent) 88%, #fff);
}

/* The AI toggle reads as machine-coloured only while it is actually running. */
.arc-btn[aria-pressed="true"] {
  background: color-mix(in srgb, var(--arc-machine) 16%, transparent);
  border-color: color-mix(in srgb, var(--arc-machine) 55%, transparent);
  color: var(--arc-machine);
}

.arc-btn:focus-visible,
.arc-link:focus-visible,
a:focus-visible {
  outline: 2px solid var(--arc-accent);
  outline-offset: 3px;
}

/* Live status pill shown while the solver is thinking */
.arc-pulse {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 3px 10px;
  border: 1px solid color-mix(in srgb, var(--arc-machine) 45%, transparent);
  border-radius: 999px;
  background: color-mix(in srgb, var(--arc-machine) 12%, transparent);
  color: var(--arc-machine);
  font-family: var(--arc-mono);
  font-size: var(--arc-t-label);
  letter-spacing: .16em;
  text-transform: uppercase;
}

.arc-pulse::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
  animation: arc-blink 1.2s ease-in-out infinite;
}

@keyframes arc-blink {
  50% { opacity: .25; }
}

.arc-pulse[hidden] {
  display: none;
}

/* ------------------------------------------------------------------ *
 * Hints
 * ------------------------------------------------------------------ */

.arc-hint {
  margin: 0;
  color: var(--arc-faint);
  font-size: var(--arc-t-readout);
  text-align: center;
}

.arc-hint kbd {
  display: inline-block;
  padding: 2px 7px;
  border: 1px solid var(--arc-line-soft);
  border-radius: 5px;
  background: var(--arc-raise);
  color: var(--arc-text);
  font-family: var(--arc-mono);
  font-size: var(--arc-t-readout);
}

.arc-hint-keys { display: inline; }
.arc-hint-touch { display: none; }

@media (pointer: coarse) {
  .arc-hint-keys { display: none; }
  .arc-hint-touch { display: inline; }
}

/* ------------------------------------------------------------------ *
 * Result overlay
 * ------------------------------------------------------------------ */

.arc-overlay {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: grid;
  place-items: center;
  padding: 20px;
  background: rgba(6, 6, 5, .82);
  backdrop-filter: blur(10px);
  opacity: 0;
  visibility: hidden;
  transition: opacity 240ms var(--arc-ease-out), visibility 240ms;
}

.arc-overlay[data-open="true"] {
  opacity: 1;
  visibility: visible;
}

.arc-overlay-card {
  width: min(400px, 100%);
  padding: 34px 30px 28px;
  border: 1px solid var(--arc-line);
  border-radius: 22px;
  background: linear-gradient(180deg, #16130e, #0c0b09);
  text-align: center;
  transform: translateY(10px) scale(.98);
  transition: transform 300ms var(--arc-ease);
}

.arc-overlay[data-open="true"] .arc-overlay-card {
  transform: none;
}

.arc-overlay-title {
  margin: 0 0 6px;
  font-family: var(--arc-display);
  font-weight: 600;
  font-size: 2rem;
  letter-spacing: -.03em;
}

.arc-overlay-body {
  margin: 0 0 22px;
  color: var(--arc-dim);
  font-size: .95rem;
}

.arc-overlay-body strong {
  color: var(--arc-accent);
  font-family: var(--arc-mono);
  font-variant-numeric: tabular-nums;
}

/* ------------------------------------------------------------------ *
 * Bottom navigation dock
 * ------------------------------------------------------------------ */

/* The dock floats over the page, and every game is a little taller than one
   screen — so at the top of a game the action row sits behind this pill and the
   pill, not the button, received the click. "New game" and Sudoku's "Hint" were
   unreachable until you scrolled. The bar itself is now transparent to the
   pointer and only its own controls take clicks, so the dead space between and
   around them hands the click back to whatever it is floating over. */
.arc-dock {
  position: fixed;
  left: 50%;
  bottom: max(16px, env(safe-area-inset-bottom));
  z-index: 80;
  pointer-events: none;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: 4px;
  max-width: calc(100vw - 24px);
  padding: 6px 8px;
  border: 1px solid var(--arc-line-soft);
  border-radius: 999px;
  background: rgba(14, 13, 11, .9);
  backdrop-filter: blur(14px);
  overflow-x: auto;
  scrollbar-width: none;
}

.arc-dock::-webkit-scrollbar { display: none; }

/* Re-arm the dock's own controls after the bar opted out above. */
.arc-dock > * {
  pointer-events: auto;
}

.arc-dock-mark {
  flex-shrink: 0;
  padding: 0 12px 0 8px;
  border-right: 1px solid var(--arc-line-soft);
  margin-right: 4px;
  font-family: var(--arc-display);
  font-weight: 600;
  font-size: var(--arc-t-body);
  letter-spacing: -.02em;
}

.arc-link {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  min-height: 34px;
  padding: 0 13px;
  border-radius: 999px;
  color: var(--arc-dim);
  font-size: var(--arc-t-body);
  font-weight: 500;
  text-decoration: none;
  white-space: nowrap;
  transition: background-color 180ms var(--arc-ease-out), color 180ms var(--arc-ease-out);
}

.arc-link:hover {
  background: var(--arc-raise);
  color: var(--arc-text);
}

.arc-link[aria-current="page"] {
  background: color-mix(in srgb, var(--arc-accent) 18%, transparent);
  color: var(--arc-accent);
}

/* ------------------------------------------------------------------ *
 * Hub index
 * ------------------------------------------------------------------ */

.arc-index {
  display: grid;
  /* 290px floors the track wide enough that a 1140px shell lands on three
   * columns, so five cards read 3 + 2 rather than 4 + 1 with a stranded card.
   *
   * The min() is load-bearing: a bare minmax(290px, …) cannot shrink under its
   * floor, so on a 320px phone the 284px of available width overflowed the
   * body. Capping the floor at 100% lets the track collapse instead. */
  grid-template-columns: repeat(auto-fit, minmax(min(290px, 100%), 1fr));
  gap: 14px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.arc-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 10px;
  height: 100%;
  padding: 22px 22px 24px;
  border: 1px solid var(--arc-line-soft);
  border-radius: var(--arc-radius-lg);
  background: linear-gradient(180deg, var(--arc-raise), rgba(255, 255, 255, .01));
  color: inherit;
  text-decoration: none;
  overflow: hidden;
  transition:
    border-color 240ms var(--arc-ease-out),
    transform 240ms var(--arc-ease),
    background-color 240ms var(--arc-ease-out);
}

/* Accent wash that only resolves on hover — keeps the grid calm at rest. */
.arc-card::after {
  content: "";
  position: absolute;
  inset: -40% -20% auto;
  height: 160px;
  background: radial-gradient(60% 100% at 50% 0%, color-mix(in srgb, var(--arc-accent) 26%, transparent), transparent 70%);
  opacity: 0;
  transition: opacity 300ms var(--arc-ease-out);
  pointer-events: none;
}

.arc-card:hover {
  transform: translateY(-3px);
  border-color: color-mix(in srgb, var(--arc-accent) 45%, transparent);
}

.arc-card:hover::after {
  opacity: 1;
}

.arc-card-index {
  font-family: var(--arc-mono);
  font-size: var(--arc-t-label);
  letter-spacing: .2em;
  color: var(--arc-accent);
}

.arc-card-name {
  margin: 0;
  font-family: var(--arc-display);
  font-weight: 600;
  font-size: 1.55rem;
  letter-spacing: -.03em;
}

.arc-card-copy {
  margin: 0;
  color: var(--arc-dim);
  font-size: var(--arc-t-body);
  text-wrap: pretty;
}

.arc-card-algo {
  margin-top: auto;
  padding-top: 14px;
  border-top: 1px solid var(--arc-line-soft);
  font-family: var(--arc-mono);
  font-size: var(--arc-t-label);
  letter-spacing: .06em;
  color: var(--arc-machine);
}

/* ------------------------------------------------------------------ *
 * Accessibility
 * ------------------------------------------------------------------ */

.arc-sr {
  position: absolute !important;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.arc-skip {
  position: absolute;
  left: 12px;
  top: -60px;
  z-index: 200;
  padding: 10px 16px;
  border-radius: 8px;
  background: var(--arc-accent);
  color: #1b1206;
  font-weight: 600;
  text-decoration: none;
  transition: top 180ms var(--arc-ease-out);
}

.arc-skip:focus {
  top: 12px;
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
}
