/* PadSquire components. Needs tokens.css first.
   Plain classes, no build step. Every component reads only tokens, so a theme change
   (or a port to the settings app) is a matter of copying public/ds/. */

/* -- base ------------------------------------------------------------------ */

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

html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font: var(--weight-regular) var(--text-md) / var(--leading-body) var(--font-ui);
  font-variant-numeric: tabular-nums;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 400;
  line-height: var(--leading-tight);
  letter-spacing: -.01em;
  text-wrap: balance;
}
h1 { font-size: var(--text-display); letter-spacing: -.02em; }
h2 { font-size: var(--text-3xl); }
h3 { font-size: var(--text-xl); line-height: var(--leading-snug); }
h4 { font: var(--weight-bold) var(--text-md) / var(--leading-snug) var(--font-ui); letter-spacing: 0; }

p { margin: 0; text-wrap: pretty; }

a {
  color: var(--accent);
  text-decoration-thickness: 1px;
  text-underline-offset: .2em;
  text-decoration-color: color-mix(in oklab, currentColor 40%, transparent);
  transition: text-decoration-color var(--duration-fast) var(--ease-out);
}
a:hover { text-decoration-color: currentColor; }

code, kbd, pre { font-family: var(--font-mono); font-size: .92em; }
:not(pre) > code {
  padding: .1em .4em;
  border-radius: var(--radius-xs);
  background: var(--paper-sunken);
}
kbd {
  display: inline-block;
  min-width: 1.6em;
  padding: .05em .45em;
  border: var(--hairline) solid var(--line-strong);
  border-radius: var(--radius-xs);
  background: var(--paper-raised);
  box-shadow: inset 0 -1px 0 var(--line-strong);
  font-size: .85em;
  text-align: center;
}

::selection { background: color-mix(in oklab, var(--accent) 24%, transparent); }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: var(--radius-xs); }
html { scrollbar-color: var(--line-strong) transparent; accent-color: var(--accent); caret-color: var(--accent); }

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

/* -- icons: authored SVG symbols, drawn with currentColor ------------------- */

.icon {
  width: 1.25em; height: 1.25em; flex: none;
  fill: none; stroke: currentColor; stroke-width: 1.75;
  stroke-linecap: round; stroke-linejoin: round;
  vertical-align: -.25em;
}

/* -- buttons ---------------------------------------------------------------- */

.button {
  --button-bg: var(--paper-raised);
  --button-fg: var(--ink);
  --button-border: var(--line-strong);
  display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2);
  min-height: 2.75rem;
  padding: .55rem 1.25rem;
  border: var(--hairline) solid var(--button-border);
  border-radius: var(--radius-pill);
  background: var(--button-bg);
  color: var(--button-fg);
  font: var(--weight-bold) var(--text-md) / 1.2 var(--font-ui);
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition:
    background-color var(--duration-fast) var(--ease-out),
    border-color var(--duration-fast) var(--ease-out),
    box-shadow var(--duration-base) var(--ease-out),
    transform var(--duration-fast) var(--ease-out);
}
@media (hover: hover) { .button:hover { --button-border: var(--ink-faint); box-shadow: var(--shadow-card); } }
.button:active { transform: translateY(1px); box-shadow: none; }
.button:focus-visible { outline: none; box-shadow: var(--focus-ring); }

.button.primary {
  --button-bg: var(--accent);
  --button-fg: var(--accent-ink);
  --button-border: var(--accent);
}
@media (hover: hover) { .button.primary:hover { --button-bg: var(--accent-strong); --button-border: var(--accent-strong); } }

.button.quiet {
  --button-bg: transparent;
  --button-border: transparent;
  --button-fg: var(--accent);
  padding-inline: .75rem;
}
@media (hover: hover) { .button.quiet:hover { --button-bg: var(--accent-wash); --button-border: transparent; box-shadow: none; } }

.button.small { min-height: 2.25rem; padding: .35rem .9rem; font-size: var(--text-sm); }
.button.icon-only { width: 2.75rem; padding: 0; }
.button.small.icon-only { width: 2.25rem; }

.button[disabled], .button[aria-disabled="true"] {
  --button-bg: var(--paper-sunken);
  --button-fg: var(--ink-faint);
  --button-border: var(--line);
  box-shadow: none; transform: none; cursor: not-allowed;
}

/* -- chips: short status words --------------------------------------------- */

.chip {
  --chip-fg: var(--ink-soft);
  --chip-bg: var(--paper-sunken);
  display: inline-flex; align-items: center; gap: .35em;
  padding: .2em .65em .2em .5em;
  border-radius: var(--radius-pill);
  background: var(--chip-bg);
  color: var(--chip-fg);
  font: var(--weight-bold) var(--text-xs) / 1.3 var(--font-ui);
  white-space: nowrap;
}
.chip .icon { width: 1.1em; height: 1.1em; stroke-width: 2.25; vertical-align: 0; }
.chip.ok { --chip-fg: var(--ok); --chip-bg: var(--ok-wash); }
.chip.warn { --chip-fg: var(--warn); --chip-bg: var(--warn-wash); }
.chip.danger { --chip-fg: var(--danger); --chip-bg: var(--danger-wash); }
.chip.accent { --chip-fg: var(--accent); --chip-bg: var(--accent-wash); }

/* -- surfaces --------------------------------------------------------------- */

/* A sheet: the large raised panel that carries a page's main object. */
.sheet {
  border-radius: var(--radius-lg);
  background: var(--paper-raised);
  box-shadow: var(--shadow-lift);
}

/* A card: one item among several (a controller, a setting group). */
.card {
  border: var(--hairline) solid var(--line);
  border-radius: var(--radius-md);
  background: var(--paper-raised);
  box-shadow: var(--shadow-card);
}

/* A well: sunken area for code, tracks and previews. */
.well {
  border-radius: var(--radius-sm);
  background: var(--paper-sunken);
}

/* -- notices ---------------------------------------------------------------- */

.notice {
  --notice-fg: var(--accent);
  --notice-bg: var(--accent-wash);
  display: flex; gap: var(--space-3); align-items: flex-start;
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-sm);
  background: var(--notice-bg);
  color: var(--ink);
  font-size: var(--text-sm);
}
.notice > .icon { color: var(--notice-fg); margin-top: .1em; }
.notice.ok { --notice-fg: var(--ok); --notice-bg: var(--ok-wash); }
.notice.warn { --notice-fg: var(--warn); --notice-bg: var(--warn-wash); }
.notice.danger { --notice-fg: var(--danger); --notice-bg: var(--danger-wash); }

/* -- fields ----------------------------------------------------------------- */

.field { display: grid; gap: var(--space-1); }
.field > .label { font-weight: var(--weight-bold); font-size: var(--text-sm); }
.field > .hint { color: var(--ink-faint); font-size: var(--text-xs); }
.field > .hint.error { color: var(--danger); }

.input {
  width: 100%;
  min-height: 2.75rem;
  padding: .55rem .8rem;
  border: var(--hairline) solid var(--line-strong);
  border-radius: var(--radius-sm);
  background: var(--paper-raised);
  color: var(--ink);
  font: inherit;
  transition: border-color var(--duration-fast) var(--ease-out), box-shadow var(--duration-fast) var(--ease-out);
}
.input::placeholder { color: var(--ink-faint); }
.input:hover { border-color: var(--ink-faint); }
.input:focus { outline: none; border-color: var(--accent); box-shadow: var(--focus-ring); }
.input[aria-invalid="true"] { border-color: var(--danger); }
select.input {
  appearance: none;
  padding-right: 2.25rem;
  background-image: linear-gradient(45deg, transparent 50%, var(--ink-soft) 50%), linear-gradient(-45deg, transparent 50%, var(--ink-soft) 50%);
  background-position: right 1.1rem center, right .8rem center;
  background-size: .3rem .3rem;
  background-repeat: no-repeat;
}

/* -- switch: <input type="checkbox" role="switch" class="switch"> ---------- */

.switch {
  appearance: none;
  position: relative;
  width: 2.75rem; height: 1.6rem; flex: none;
  margin: 0;
  border-radius: var(--radius-pill);
  background: var(--line-strong);
  cursor: pointer;
  transition: background-color var(--duration-base) var(--ease-out);
}
.switch::after {
  content: "";
  position: absolute; top: .2rem; left: .2rem;
  width: 1.2rem; height: 1.2rem;
  border-radius: 50%;
  background: var(--paper-raised);
  box-shadow: 0 1px 3px var(--shadow-color);
  transition: transform var(--duration-base) var(--ease-out);
}
.switch:checked { background: var(--accent); }
.switch:checked::after { transform: translateX(1.15rem); }
.switch:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.switch:disabled { opacity: .45; cursor: not-allowed; }

/* A row that pairs a label with a control (switch, value, button). */
.setting {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-4);
  padding: var(--space-3) 0;
  border-bottom: var(--hairline) solid var(--line);
}
.setting > div { display: grid; gap: .1rem; }
.setting .hint { color: var(--ink-faint); font-size: var(--text-xs); }

/* -- range: <input type="range" class="range"> with a value beside it ------- */

.range {
  --fill: 50%;
  appearance: none;
  width: 100%; height: 1.75rem; margin: 0;
  background: transparent;
  cursor: pointer;
}
.range::-webkit-slider-runnable-track {
  height: .4rem; border-radius: var(--radius-pill);
  background: linear-gradient(to right, var(--accent) var(--fill), var(--paper-sunken) var(--fill));
}
.range::-moz-range-track { height: .4rem; border-radius: var(--radius-pill); background: var(--paper-sunken); }
.range::-moz-range-progress { height: .4rem; border-radius: var(--radius-pill); background: var(--accent); }
.range::-webkit-slider-thumb {
  appearance: none;
  width: 1.4rem; height: 1.4rem; margin-top: -.5rem;
  border: 3px solid var(--accent); border-radius: 50%;
  background: var(--paper-raised);
  box-shadow: var(--shadow-card);
  transition: transform var(--duration-fast) var(--ease-out);
}
.range::-moz-range-thumb {
  width: 1.4rem; height: 1.4rem;
  border: 3px solid var(--accent); border-radius: 50%;
  background: var(--paper-raised);
  box-shadow: var(--shadow-card);
}
.range:active::-webkit-slider-thumb { transform: scale(1.12); }
.range:focus-visible { outline: none; }
.range:focus-visible::-webkit-slider-thumb { box-shadow: var(--focus-ring); }
.range:focus-visible::-moz-range-thumb { box-shadow: var(--focus-ring); }

/* A range with its value beside it. */
.range-row { display: flex; align-items: center; gap: var(--space-4); }

.value {
  min-width: 3.5ch;
  font: var(--weight-bold) var(--text-lg) / 1 var(--font-ui);
  text-align: right;
}

/* -- segmented control: radios in a pill ------------------------------------ */

.segmented {
  display: inline-flex; padding: .25rem; gap: .25rem;
  border-radius: var(--radius-pill);
  background: var(--paper-sunken);
}
.segmented input { position: absolute; opacity: 0; pointer-events: none; }
.segmented label {
  padding: .4rem 1rem;
  border-radius: var(--radius-pill);
  color: var(--ink-soft);
  font-weight: var(--weight-bold); font-size: var(--text-sm);
  cursor: pointer;
  transition: background-color var(--duration-fast) var(--ease-out), color var(--duration-fast) var(--ease-out);
}
.segmented label:hover { color: var(--ink); }
.segmented input:checked + label { background: var(--paper-raised); color: var(--ink); box-shadow: var(--shadow-card); }
.segmented input:focus-visible + label { box-shadow: var(--focus-ring); }

/* -- navigation list (the settings app's sidebar) --------------------------- */

.navlist { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px; }
.navlist a {
  display: flex; justify-content: space-between; align-items: baseline; gap: var(--space-3);
  padding: .55rem .9rem;
  border-radius: var(--radius-sm);
  color: var(--ink-soft);
  font-weight: var(--weight-medium);
  text-decoration: none;
  transition: background-color var(--duration-fast) var(--ease-out), color var(--duration-fast) var(--ease-out);
}
.navlist a:hover { background: var(--paper-sunken); color: var(--ink); }
.navlist a[aria-current="page"] { background: var(--accent-wash); color: var(--accent); font-weight: var(--weight-bold); }
.navlist small { color: var(--ink-faint); font-size: var(--text-xs); font-weight: var(--weight-regular); }

/* -- table ------------------------------------------------------------------ */

.table-scroll { overflow-x: auto; }
.table { width: 100%; border-collapse: collapse; font-size: var(--text-sm); }
.table th, .table td { padding: .8rem 1rem; text-align: left; vertical-align: middle; }
.table thead th {
  color: var(--ink-soft);
  font-weight: var(--weight-bold);
  background: var(--paper-sunken);
}
.table thead th:first-child { border-radius: var(--radius-sm) 0 0 var(--radius-sm); }
.table thead th:last-child { border-radius: 0 var(--radius-sm) var(--radius-sm) 0; }
.table tbody tr + tr > * { border-top: var(--hairline) solid var(--line); }
.table tbody th { font-weight: var(--weight-medium); }

/* -- code block with a copy button ----------------------------------------- */

.codeblock { border-radius: var(--radius-md); background: var(--paper-sunken); overflow: hidden; }
.codeblock-bar {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
  padding: var(--space-2) var(--space-2) 0 var(--space-5);
  color: var(--ink-faint); font-size: var(--text-xs); font-weight: var(--weight-bold);
}
.codeblock pre {
  margin: 0;
  padding: var(--space-2) var(--space-5) var(--space-4);
  overflow-x: auto;
  line-height: 1.75;
}
.codeblock .comment { color: var(--ink-faint); }

/* -- dialog ----------------------------------------------------------------- */

.dialog {
  width: min(34rem, calc(100% - 2rem));
  max-height: calc(100% - 2rem);
  padding: var(--space-6);
  border: 0;
  border-radius: var(--radius-lg);
  background: var(--paper-raised);
  color: var(--ink);
  box-shadow: var(--shadow-lift);
}
.dialog::backdrop { background: var(--scrim); backdrop-filter: blur(2px); }
.dialog[open] { animation: dialog-in var(--duration-base) var(--ease-out); }
@keyframes dialog-in { from { opacity: 0; transform: translateY(.75rem) scale(.98); } }

/* -- touch: every control at least 44px tall ------------------------------- */

@media (pointer: coarse) {
  .button.small { min-height: 2.75rem; padding-block: .5rem; }
  .button.small.icon-only { width: 2.75rem; }
  .segmented label { padding-block: .65rem; }
  .range { height: 2.75rem; }
  .switch { width: 3rem; height: 1.75rem; }
  .switch::after { width: 1.35rem; height: 1.35rem; }
  .switch:checked::after { transform: translateX(1.25rem); }
}

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

/* -- the controller drawing --------------------------------------------------
   ds/nova-2-lite.svg, inlined into the page (drop its <style>). Parts carry data-part
   (a, b, x, y, lb, rb, lt, rt, view, menu, share, home, m, up, down, left, right, ls, rs,
   l4, r4) and the stick caps data-stick (left, right). Set data-pressed on a part to light
   it, and a transform on a stick cap to move it. */

.pad { display: block; width: 100%; height: auto; overflow: visible; }
.pad * { vector-effect: non-scaling-stroke; }
.pad .shell, .pad .plastic, .pad .well-ring, .pad .cap, .pad .key {
  fill: var(--drawing-fill);
  stroke: var(--drawing-ink);
  stroke-width: 1.6;
  stroke-linejoin: round;
  transition: fill var(--duration-fast) var(--ease-out);
}
.pad .edge { fill: none; stroke: var(--drawing-ink); stroke-width: 1.4; }
.pad .texture { fill: none; stroke: var(--drawing-ink); stroke-width: 2.2; stroke-dasharray: .8 1.6; }
.pad .underside { fill: none; stroke: var(--drawing-ink); stroke-width: 1.4; stroke-dasharray: 4 3; }
.pad .glyph { fill: var(--drawing-ink); font: var(--weight-bold) 10px var(--font-ui); text-anchor: middle; dominant-baseline: central; }
.pad .glyph.small { font-size: 9px; }
.pad .led { fill: var(--drawing-fill); stroke: var(--drawing-ink); stroke-width: 1.6; }
.pad [data-stick] { transition: transform 60ms linear; }
.pad [data-pressed] .cap, .pad [data-pressed] .key, .pad [data-pressed] .plastic,
.pad .key[data-pressed], .pad .plastic[data-pressed], .pad .led[data-pressed] { fill: var(--drawing-active); }
.pad [data-pressed] .glyph, .pad .glyph[data-pressed] { fill: var(--accent-ink); }
.pad .underside[data-pressed] { fill: var(--accent-wash); stroke-dasharray: none; }

/* An outline only: a controller that isn't on the desk yet. */
.pad.ghost .shell { fill: none; stroke: var(--drawing-muted); stroke-dasharray: 6 5; }

/* -- stick view: the dead-zone circle ----------------------------------------
   <svg class="stick-view" viewBox="-110 -110 220 220"> with circles .sv-outer and .sv-rim
   (r=100), .sv-reach (r = 100 x (1 - outer)), .sv-inner (r = 100 x inner), two .sv-axis lines,
   .sv-raw (the stick) and .sv-out (what the game receives). Shaded areas are ignored. */

.stick-view { width: min(100%, 22rem); height: auto; overflow: visible; touch-action: none; }
.sv-outer, .sv-inner { fill: var(--ignored); }
.sv-reach { fill: var(--paper-raised); }
.sv-rim { fill: none; stroke: var(--ink); stroke-width: 1.5; }
.sv-axis { stroke: var(--line); stroke-width: 1; }
.sv-raw { fill: none; stroke: var(--ink-soft); stroke-width: 2; }
.sv-out { fill: var(--accent); }
