/* ChallengeX web builder — the whole visual system.

   Direction: a hard-edged console. Nothing is rounded, nothing glows, every
   raised surface sits on a hard offset shadow instead of a blur. Colour
   carries meaning and is never decorative: amber is a trigger, green an effect,
   cyan a goal, magenta a modifier, red a structural problem. MC Ten Lowercase
   Alt is the pixel display face and is only ever used for headings and short
   labels; body copy is Space Grotesk; anything mechanical (ids, params, paths,
   commands) is IBM Plex Mono.

   The console comes in two finishes. Dark is the original: greenish blacks
   with the piece colours bright on top. Light is the same console printed on
   green-cast paper: the piece colours drop to ink weights that hold AA
   contrast both as text on the paper and under light text on solid chips, and
   the offset shadows become ink at lower alpha. Every token is a light-dark()
   pair, so each colour lives in exactly one place; which side renders is the
   color-scheme, following the system until the topbar switch forces one. */

/* ---------- tokens ---------- */

:root {
  color-scheme: light dark;

  --bg: light-dark(#edefe6, #111310);
  --bg-raised: light-dark(#f7f8f1, #191c17);
  --bg-sunken: light-dark(#e6e9dc, #161913);
  --bg-strip: light-dark(#e2e6d6, #1c1f18);
  --bg-scrim: light-dark(rgba(24, 27, 21, .45), rgba(7, 8, 6, .82));

  --line: light-dark(#aab29b, #2e332c);
  --line-soft: light-dark(#98a189, #3a4036);
  --line-dashed: light-dark(#848e74, #4a5244);

  --text: light-dark(#20251d, #e8ece4);
  --text-dim: light-dark(#434c3d, #b9c0b1);
  --text-mute: light-dark(#5c6653, #9aa294);
  --text-faint: light-dark(#75806a, #788070);

  --trigger: light-dark(#955f00, #e8b84b);
  --trigger-line: light-dark(#c0a052, #6b5c33);
  --trigger-wash: light-dark(#f2edd8, #1c1a12);

  --effect: light-dark(#3c7a16, #9adf6a);
  --effect-bright: light-dark(#2f6410, #c2f09a);
  --effect-line: light-dark(#79a854, #4d6b33);
  --effect-wash: light-dark(#e9f1dd, #151c11);

  --goal: light-dark(#0e6b7d, #6ac9df);
  --goal-bright: light-dark(#0a5866, #93dcec);
  --goal-line: light-dark(#5da4b3, #33565f);
  --goal-wash: light-dark(#e2eff2, #12191c);

  --modifier: light-dark(#92379d, #d98fe0);
  --modifier-line: light-dark(#b56cbe, #5c3961);
  --modifier-wash: light-dark(#f2e7f4, #1a121c);

  --bad: light-dark(#b03421, #e06c5a);
  --bad-soft: light-dark(#9c4a3c, #c98a80);
  --bad-wash: light-dark(rgba(176, 52, 33, .08), rgba(224, 108, 90, .07));

  --off-line: light-dark(#b9b19c, #4a4238);
  --off-bg: light-dark(#dcd7c5, #2a251d);
  --off-text: light-dark(#7e765f, #9a8f7d);

  --shadow-ink: light-dark(rgba(24, 28, 20, .18), rgba(0, 0, 0, .4));
  --shadow-ink-deep: light-dark(rgba(24, 28, 20, .26), rgba(0, 0, 0, .5));
  --shadow: 5px 5px 0 var(--shadow-ink);
  --shadow-btn: 4px 4px 0 var(--shadow-ink-deep);
  --shadow-lift: 7px 7px 0 var(--shadow-ink-deep);
  --shadow-modal: 8px 8px 0 var(--shadow-ink-deep);

  --display: 'MC Ten Lowercase Alt', 'Courier New', monospace;
  --body: 'Space Grotesk', 'Segoe UI', system-ui, sans-serif;
  --mono: 'IBM Plex Mono', 'Consolas', monospace;

  --shell: 1240px;
  --tap: 44px;
}

/* The topbar switch forces a side; without it the system preference decides. */
:root[data-theme='light'] { color-scheme: light; }
:root[data-theme='dark'] { color-scheme: dark; }

/* ---------- reset ---------- */

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--body);
  font-size: 15px;
  line-height: 1.5;
}

h1, h2, h3, p, ol, ul, figure { margin: 0; }
ol, ul { padding-left: 1.25em; }

a { color: var(--effect); }
a:hover { color: var(--effect-bright); }

::selection { background: var(--effect); color: var(--bg); }

:focus-visible {
  outline: 2px solid var(--effect);
  outline-offset: 2px;
}

code, kbd, pre { font-family: var(--mono); }

code {
  font-size: .86em;
  color: var(--text);
}

/* Visible only to screen readers. */
.sr {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ---------- primitives ---------- */

.shell {
  width: 100%;
  max-width: var(--shell);
  margin: 0 auto;
  padding: 0 24px;
}

.shell--narrow { max-width: 820px; }
.shell--page { max-width: 1060px; }

.display {
  font-family: var(--display);
  font-weight: 700;
  letter-spacing: .02em;
}

.meta {
  font: 600 11px var(--mono);
  color: var(--text-mute);
  letter-spacing: .1em;
}

.note {
  font: 400 12px/1.6 var(--mono);
  color: var(--text-faint);
}

/* The caret that ends the wordmark and the empty-state headline. */
.caret { color: var(--effect); }

.panel {
  border: 2px solid var(--line);
  background: var(--bg-raised);
  box-shadow: var(--shadow);
}

.panel--sunken { background: var(--bg-sunken); }

/* ---------- buttons ---------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  border: 2px solid var(--line);
  background: none;
  color: var(--text);
  font: 600 14px var(--body);
  padding: 11px 18px;
  min-height: var(--tap);
  cursor: pointer;
  text-decoration: none;
  text-align: center;
  transition: transform .08s steps(2), box-shadow .08s steps(2), border-color .1s, background .1s, color .1s;
}

.btn:hover { border-color: var(--effect); color: var(--text); }

.btn--primary {
  border-color: var(--effect);
  background: var(--effect);
  color: var(--bg);
  font-weight: 700;
  box-shadow: var(--shadow-btn);
}

.btn--primary:hover {
  background: var(--effect-bright);
  border-color: var(--effect-bright);
  color: var(--bg);
}

.btn--goal {
  border-color: var(--goal);
  background: var(--goal);
  color: var(--bg);
  font-weight: 700;
  box-shadow: var(--shadow-btn);
}

.btn--goal:hover { background: var(--goal-bright); border-color: var(--goal-bright); color: var(--bg); }

.btn--lift:hover {
  transform: translate(-2px, -2px);
  box-shadow: var(--shadow-lift);
}

.btn--ghost { color: var(--text-dim); }

/* Brand marks on the Modrinth and GitHub buttons, inlined like every other
   asset here so the page still makes no third-party request. */
.btn__logo {
  width: 16px;
  height: 16px;
  flex: none;
  fill: currentColor;
}

.btn:disabled,
.btn[aria-disabled='true'] {
  border-color: var(--off-line);
  background: var(--off-bg);
  color: var(--off-text);
  box-shadow: none;
  cursor: not-allowed;
  transform: none;
}

/* A dashed "add another one of these" button, tinted by what it adds. */
.btn--add {
  width: 100%;
  border-style: dashed;
  font-weight: 700;
  font-size: 13px;
  padding: 14px;
  flex-direction: column;
  gap: 3px;
}

.btn--add .btn__hint {
  font: 400 11px var(--mono);
  color: var(--text-mute);
}

.btn--add[data-kind='trigger'] { border-color: var(--trigger-line); color: var(--trigger); }
.btn--add[data-kind='trigger']:hover { border-color: var(--trigger); background: var(--trigger-wash); }
.btn--add[data-kind='goal'] { border-color: var(--goal-line); color: var(--goal); }
.btn--add[data-kind='goal']:hover { border-color: var(--goal); background: var(--goal-wash); }
.btn--add[data-kind='modifier'] { border-color: var(--modifier-line); color: var(--modifier); }
.btn--add[data-kind='modifier']:hover { border-color: var(--modifier); background: var(--modifier-wash); }
.btn--add[data-kind='effect'] { border-color: var(--effect-line); color: var(--effect); }
.btn--add[data-kind='effect']:hover { border-color: var(--effect); background: var(--effect-wash); }

/* Small square icon controls in a card's header strip. */
.icon-btn {
  border: none;
  background: none;
  color: var(--text-faint);
  font: 600 13px var(--mono);
  cursor: pointer;
  padding: 6px 7px;
  line-height: 1;
}

.icon-btn:hover { color: var(--text); }
.icon-btn--bad:hover { color: var(--bad); }

/* ---------- form controls ---------- */

.field {
  display: flex;
  flex-direction: column;
  gap: 5px;
  min-width: 0;
}

.field__label {
  font: 600 10px var(--mono);
  color: var(--text-mute);
  letter-spacing: .06em;
  text-transform: uppercase;
}

.field__req { color: var(--effect); }
.field__label[data-kind='trigger'] .field__req { color: var(--trigger); }
.field__label[data-kind='goal'] .field__req { color: var(--goal); }
.field__label[data-kind='modifier'] .field__req { color: var(--modifier); }

.input {
  width: 100%;
  background: var(--bg-sunken);
  border: 2px solid var(--line);
  color: var(--text);
  font: 400 13px var(--mono);
  padding: 9px 10px;
  min-height: 40px;
}

.input::placeholder { color: var(--text-faint); }
.input:focus { border-color: var(--effect); outline: none; }
.input[aria-invalid='true'] { border-color: var(--bad); }

.input--name {
  font: 700 17px var(--display);
  letter-spacing: .02em;
  min-height: var(--tap);
}

/* A type-ahead parameter: the input carries display names, the suggestion
   list hangs under it as a hard-edged console dropdown. */
.suggest { position: relative; min-width: 0; }

.suggest__list {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  z-index: 30;
  margin-top: 4px;
  background: var(--bg-raised);
  border: 2px solid var(--line);
  box-shadow: var(--shadow-btn);
  max-height: 236px;
  overflow-y: auto;
}

.suggest__option {
  display: block;
  width: 100%;
  text-align: left;
  background: none;
  border: 0;
  color: var(--text);
  font: 400 13px var(--mono);
  padding: 9px 10px;
  cursor: pointer;
}

.suggest__option + .suggest__option { border-top: 1px solid var(--line); }

.suggest__option:hover,
.suggest__option[data-active] {
  background: var(--bg-sunken);
  color: var(--effect-bright);
}

/* A checkbox rendered as a hard toggle chip. */
.toggle {
  display: flex;
  align-items: center;
  gap: 7px;
  border: 2px solid var(--line);
  background: var(--bg-sunken);
  color: var(--text-mute);
  font: 600 12px var(--mono);
  padding: 9px 10px;
  min-height: 40px;
  cursor: pointer;
  user-select: none;
}

.toggle:hover { border-color: var(--line-dashed); }
.toggle[aria-checked='true'] { color: var(--effect); border-color: var(--effect-line); }

/* Segmented control: the scope picker, and the mobile section tabs. */
.seg {
  display: flex;
  flex-wrap: wrap;
  font: 600 11.5px var(--body);
}

.seg__opt {
  border: 2px solid var(--line);
  background: none;
  color: var(--text-mute);
  padding: 8px 12px;
  min-height: 38px;
  cursor: pointer;
  margin-left: -2px;
  white-space: nowrap;
}

.seg__opt:first-child { margin-left: 0; }
.seg__opt:hover { color: var(--text); }

.seg__opt[aria-pressed='true'] {
  background: var(--effect);
  border-color: var(--effect);
  color: var(--bg);
  position: relative;
  z-index: 1;
}

.seg[data-kind='trigger'] .seg__opt[aria-pressed='true'] { background: var(--trigger); border-color: var(--trigger); }
.seg[data-kind='modifier'] .seg__opt[aria-pressed='true'] { background: var(--modifier); border-color: var(--modifier); }

/* An unanswered required scope: every option outlined red, none chosen. */
.seg[data-missing='true'] .seg__opt {
  border-color: var(--bad);
  color: var(--text);
}

/* Roster checkboxes for a specific-players scope. */
.roster {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.roster__name {
  border: 2px solid var(--line);
  background: none;
  color: var(--text-mute);
  font: 600 11px var(--mono);
  padding: 7px 10px;
  min-height: 36px;
  cursor: pointer;
}

.roster__name[aria-pressed='true'] { border-color: var(--modifier); color: var(--modifier); }
.roster__name:hover { color: var(--text); }

.roster__empty {
  font: 400 11px var(--mono);
  color: var(--bad-soft);
}

/* ---------- chrome ---------- */

.topbar {
  display: flex;
  align-items: center;
  gap: 18px;
  padding: 14px 24px;
  border-bottom: 2px solid var(--line);
  flex-wrap: wrap;
}

.brand {
  display: flex;
  align-items: center;
  gap: 10px;
  text-decoration: none;
  color: var(--text);
  flex-shrink: 0;
}

/* The light finish swaps the mark for icon-ink.svg, the same X in the light
   side's effect green. Two files rather than one masked with the --effect
   token, because Chromium fetches CSS mask images with CORS and file:// pages
   have an opaque origin, so a masked mark can vanish exactly where this site
   promises to work: opened straight off disk. A plain background image loads
   everywhere. */
.brand__mark {
  width: 22px;
  height: 22px;
  background: url(../icon.svg) center / contain no-repeat;
  flex-shrink: 0;
}

:root[data-theme='light'] .brand__mark { background-image: url(../icon-ink.svg); }

@media (prefers-color-scheme: light) {
  :root:not([data-theme='dark']) .brand__mark { background-image: url(../icon-ink.svg); }
}

/* The wordmark keeps Silkscreen so the logo reads distinctly from the
   Minecraft-style display face everything else uses. */
.brand__name { font: 700 13px 'Silkscreen', var(--display); }
.brand--lg .brand__mark { width: 26px; height: 26px; }
.brand--lg .brand__name { font-size: 15px; }

.topbar__nav {
  display: flex;
  align-items: center;
  gap: 20px;
  margin-left: auto;
  flex-wrap: wrap;
}

.topbar__link {
  color: var(--text-dim);
  text-decoration: none;
  font-weight: 500;
  font-size: 14px;
}

.topbar__link:hover { color: var(--text); }

/* The light/dark switch: a quiet icon control at the end of the topbar. It
   shows the finish a press switches to, so the sun appears on the dark
   console and the moon on the light one. */
.theme-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: none;
  background: none;
  color: var(--text-dim);
  cursor: pointer;
  padding: 6px;
}

.theme-btn:hover { color: var(--text); }

.theme-btn svg {
  width: 18px;
  height: 18px;
  fill: currentColor;
}

.theme-btn__moon { display: none; }
:root[data-theme='light'] .theme-btn__sun { display: none; }
:root[data-theme='light'] .theme-btn__moon { display: block; }

@media (prefers-color-scheme: light) {
  :root:not([data-theme='dark']) .theme-btn__sun { display: none; }
  :root:not([data-theme='dark']) .theme-btn__moon { display: block; }
}

.footer {
  border-top: 2px solid var(--line);
  padding: 26px 0;
  margin-top: 64px;
}

.footer__row {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  font: 400 12px var(--mono);
  color: var(--text-faint);
}

/* ---------- landing ---------- */

.hero {
  padding: 84px 0 64px;
  display: grid;
  grid-template-columns: 1.15fr .85fr;
  gap: 56px;
  align-items: center;
}

.hero__title {
  font: 700 clamp(34px, 5vw, 58px)/1.08 var(--display);
  letter-spacing: -.01em;
}

.hero__lede {
  font-size: 17px;
  line-height: 1.6;
  color: var(--text-dim);
  max-width: 480px;
}

.hero__actions {
  display: flex;
  gap: 14px;
  flex-wrap: wrap;
}

.hero__actions .btn { font-size: 16px; padding: 15px 24px; }

.tally {
  display: flex;
  gap: 26px;
  flex-wrap: wrap;
  font: 600 12px var(--mono);
  color: var(--text-mute);
}

.tally b { font-size: 16px; }

/* The rotating "…but" example cards. */
.samples {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.sample {
  border: 2px solid var(--line);
  background: var(--bg-raised);
  padding: 16px 18px;
  box-shadow: var(--shadow);
  animation: sample-in .42s cubic-bezier(.16, .84, .32, 1) both;
  transition: opacity .28s ease, translate .28s ease;
}

/* The tilt is set through the standalone rotate property, not transform, so the
   swoosh can animate translate without fighting it for the same declaration. */
.sample:nth-child(1) { rotate: -1deg; }
.sample:nth-child(2) { rotate: .8deg; animation-delay: .07s; }
.sample:nth-child(3) { rotate: -.6deg; animation-delay: .14s; }

/* Cards leave in the same order they arrive, so the three read as one pass
   rather than three things happening at once. */
.sample:nth-child(2)[data-fading='true'] { transition-delay: .06s; }
.sample:nth-child(3)[data-fading='true'] { transition-delay: .12s; }

@keyframes sample-in {
  from { opacity: 0; translate: 26px 0; }
  to { opacity: 1; translate: 0 0; }
}

.sample__kicker {
  font: 600 10px var(--mono);
  color: var(--text-mute);
  margin-bottom: 8px;
  letter-spacing: .1em;
}

.sample__text { font-size: 15px; line-height: 1.5; }
.sample[data-fading='true'] { opacity: 0; translate: -22px 0; }

.band {
  border-top: 2px solid var(--line);
  padding: 64px 0;
}

/* The flow band sits tighter than the others: its content is one strip, not a
   column of prose, and the uniform-padding-everywhere look is nobody's friend. */
.band--flow { padding: 52px 0 72px; }

.band__title { font: 700 27px var(--display); }

/* How it works, drawn as one long rule card: three unequal steps either side
   of the same hard arrow cells a rule uses, because a preset flows
   compose → export → import the way a rule fires trigger → effect. */
.pipeline {
  display: grid;
  grid-template-columns: 1.1fr 34px .8fr 34px 1.05fr;
  margin-top: 30px;
}

.pipe {
  padding: 20px 22px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-width: 0;
}

.pipe__num { font: 700 16px var(--display); color: var(--effect); }

.pipe__arrow {
  display: flex;
  align-items: center;
  justify-content: center;
  border-left: 2px solid var(--line);
  border-right: 2px solid var(--line);
  background: var(--bg-sunken);
  color: var(--effect);
  font: 700 14px var(--display);
}

.step__body { font-size: 14px; line-height: 1.6; color: var(--text-dim); }

.split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 40px;
  align-items: start;
}

.stack {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.stack--tight { gap: 10px; }
.stack--loose { gap: 26px; }

/* Drop zone for importing someone else's preset file. */
.dropzone {
  border: 2px dashed var(--line-dashed);
  background: var(--bg-sunken);
  color: var(--text-mute);
  padding: 28px;
  text-align: center;
  font: 600 13px var(--mono);
  cursor: pointer;
  display: block;
  width: 100%;
}

.dropzone:hover,
.dropzone[data-over='true'] {
  border-color: var(--effect);
  color: var(--effect);
  background: var(--effect-wash);
}

.dropzone[data-bad='true'] { border-color: var(--bad); color: var(--bad); }

/* ---------- builder shell ---------- */

/* Name and players are boxes in the rail, stacked above the overview. */
.rail__box { padding: 16px; }

.rail__box--name {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.rail__box--roster {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

.chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  border: 2px solid var(--line);
  background: var(--bg-raised);
  padding: 6px 10px;
  font: 600 12px var(--mono);
  min-height: 36px;
}

.chip__drop {
  border: none;
  background: none;
  color: var(--text-faint);
  cursor: pointer;
  font: 600 12px var(--mono);
  padding: 2px;
}

.chip__drop:hover { color: var(--bad); }

.input--chip {
  width: 170px;
  border-style: dashed;
  background: none;
  font-weight: 600;
  font-size: 12px;
  min-height: 36px;
}

.roster-bar__hint {
  font: 400 11px var(--mono);
  color: var(--text-faint);
  margin-left: auto;
}

.board {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 300px;
  gap: 26px;
  align-items: start;
  padding: 26px 24px 90px;
  max-width: var(--shell);
  margin: 0 auto;
}

.board__main {
  display: flex;
  flex-direction: column;
  gap: 30px;
  min-width: 0;
}

.section { display: flex; flex-direction: column; gap: 14px; }

.section__head {
  display: flex;
  align-items: baseline;
  gap: 12px;
  flex-wrap: wrap;
}

.section__title { font: 700 19px var(--display); }
.section[data-kind='rules'] .section__title { color: var(--trigger); }
.section[data-kind='goal'] .section__title { color: var(--goal); }
.section[data-kind='modifiers'] .section__title { color: var(--modifier); }

.section__hint { font: 400 11px var(--mono); color: var(--text-faint); }

/* ---------- cards ---------- */

.card {
  border: 2px solid var(--line);
  background: var(--bg-raised);
  box-shadow: var(--shadow);
}

.card[data-bad='true'] { border-color: var(--bad); }

/* New cards land with a single hard step, matching the shadow language. */
@keyframes slam {
  from { transform: translate(-4px, -4px); box-shadow: 9px 9px 0 var(--shadow-ink); }
  to { transform: none; box-shadow: var(--shadow); }
}

.card[data-fresh='true'] { animation: slam .12s steps(2); }

@media (prefers-reduced-motion: reduce) {
  .card[data-fresh='true'] { animation: none; }
  .sample { transition: none; }
  .btn { transition: none; }
}

.card__strip {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 14px;
  border-bottom: 2px solid var(--line);
  background: var(--bg-strip);
}

.card__label { font: 700 13px var(--display); color: var(--text-mute); }

.card__tools {
  margin-left: auto;
  display: flex;
  gap: 2px;
}

.badge {
  font: 600 10px var(--mono);
  background: var(--bad);
  color: var(--bg);
  padding: 3px 7px;
  letter-spacing: .04em;
}

/* A rule is a trigger and an effect either side of an arrow. */
.rule {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 34px minmax(0, 1fr);
}

.rule__arrow {
  display: flex;
  align-items: center;
  justify-content: center;
  border-left: 2px solid var(--line);
  border-right: 2px solid var(--line);
  background: var(--bg-sunken);
  color: var(--effect);
  font: 700 14px var(--display);
}

.half {
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  min-width: 0;
}

.half[data-bad='true'] { background: var(--bad-wash); }

.half__head {
  display: flex;
  align-items: baseline;
  gap: 8px;
  flex-wrap: wrap;
}

.tag {
  font: 700 10px var(--mono);
  padding: 3px 6px;
  color: var(--bg);
  letter-spacing: .04em;
}

.tag--when { background: var(--trigger); }
.tag--then { background: var(--effect); }
.tag--win { background: var(--goal); }
.tag--bad { background: var(--bad); }

.half__name { font-size: 15px; font-weight: 700; }
.half__name--bad { color: var(--bad); }

.half__why { font: 400 12px/1.5 var(--body); color: var(--bad-soft); }

/* The generic parameter form: every entry renders through this. */
/* The floor is set so a namespaced id like "minecraft:zombie" reads without
   scrolling, which caps a rule half at two columns and wraps the rest. */
.params {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 10px;
}

.params--single { grid-template-columns: minmax(0, 1fr); }

.scope { display: flex; flex-direction: column; gap: 6px; }

.scope__label {
  font: 600 10px var(--mono);
  color: var(--text-mute);
  letter-spacing: .06em;
}

.scope[data-missing='true'] .scope__label { color: var(--bad); }

.goal-card {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 16px;
  flex-wrap: wrap;
}

.goal-card .params { flex: 1; min-width: 200px; }

.mod-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 14px;
}

.mod-card {
  padding: 14px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.mod-card__head {
  display: flex;
  align-items: baseline;
  gap: 8px;
  flex-wrap: wrap;
}

.mod-card__name { font-size: 14px; font-weight: 700; }

/* ---------- summary rail ---------- */

.rail {
  position: sticky;
  top: 20px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.rail__panel {
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.problems {
  border: 2px solid var(--bad);
  background: var(--bad-wash);
  padding: 10px 12px;
  display: flex;
  flex-direction: column;
  gap: 7px;
}

.problems__title { font: 700 13px var(--display); color: var(--bad); }

.problems__item {
  font: 400 11.5px/1.4 var(--mono);
  color: var(--text);
  text-decoration: none;
  text-align: left;
  border: none;
  background: none;
  padding: 0;
  cursor: pointer;
}

.problems__item:hover { color: var(--bad); }

.problems__foot { font: 400 10.5px/1.5 var(--mono); color: var(--bad-soft); }

/* Briefly marks the field a problem link jumped to. */
@keyframes ping {
  0%, 100% { box-shadow: var(--shadow); }
  50% { box-shadow: 0 0 0 3px var(--bad); }
}

[data-pinged='true'] { animation: ping .6s steps(2) 2; }

/* ---------- empty state ---------- */

.empty {
  max-width: 760px;
  margin: 0 auto;
  padding: 70px 24px;
  display: flex;
  flex-direction: column;
  gap: 22px;
  text-align: center;
}

.empty__title { font: 700 30px var(--display); }
.empty__body { font-size: 15px; color: var(--text-mute); line-height: 1.6; }

.empty__choices {
  display: flex;
  flex-direction: column;
  gap: 14px;
  margin-top: 14px;
}

.empty__choices .btn--add { padding: 26px 14px; }

/* ---------- overlays: picker and export ---------- */

.overlay {
  position: fixed;
  inset: 0;
  z-index: 40;
  background: var(--bg-scrim);
  display: flex;
  justify-content: center;
  padding: 20px;
}

.overlay[hidden] { display: none; }
.overlay--top { align-items: flex-start; padding-top: 56px; }

.modal {
  width: 100%;
  border: 2px solid var(--line);
  background: var(--bg-sunken);
  box-shadow: var(--shadow-modal);
  display: flex;
  flex-direction: column;
  min-height: 0;
}

.modal--picker { max-width: 880px; max-height: calc(100vh - 90px); }

.modal__head {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 16px;
  border-bottom: 2px solid var(--line);
  flex-wrap: wrap;
}

.modal__title { font: 700 14px var(--display); color: var(--effect); }
.modal__sub { font: 400 10.5px var(--mono); color: var(--text-faint); }
.modal__close { margin-left: auto; }

.modal__filters {
  display: flex;
  gap: 10px;
  padding: 12px 16px;
  border-bottom: 2px solid var(--line);
  flex-wrap: wrap;
  align-items: center;
}

.modal__filters .input { flex: 1; min-width: 200px; font-size: 14px; min-height: var(--tap); }

.modal__body {
  overflow: auto;
  padding: 14px 16px;
  min-height: 0;
}

.pick-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  gap: 10px;
  align-content: start;
}

/* One generic entry card, used by every one of the 96 catalog entries. */
.pick {
  text-align: left;
  border: 2px solid var(--line);
  background: var(--bg-raised);
  color: var(--text);
  padding: 12px 13px;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.pick:hover { background: var(--bg-strip); }
.pick[data-kind='trigger']:hover { border-color: var(--trigger); }
.pick[data-kind='effect']:hover { border-color: var(--effect); }
.pick[data-kind='goal']:hover { border-color: var(--goal); }
.pick[data-kind='modifier']:hover { border-color: var(--modifier); }

.pick__name { font-size: 13.5px; font-weight: 700; }
.pick__blurb { font: 400 11.5px/1.45 var(--body); color: var(--text-mute); }

.pick__chips {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  font: 600 9.5px var(--mono);
  color: var(--text-mute);
}

.pick__chip { border: 1px solid var(--line); padding: 3px 6px; }

.pick-empty {
  padding: 40px 8px;
  text-align: center;
  font: 400 13px var(--mono);
  color: var(--text-faint);
}

/* ---------- share view ---------- */

.share { padding: 52px 0 20px; display: flex; flex-direction: column; gap: 34px; }

.share__title { font: 700 clamp(28px, 4.5vw, 46px)/1.1 var(--display); word-break: break-word; }

.share__actions { display: flex; gap: 12px; flex-wrap: wrap; margin-top: 6px; }
.share__actions .btn { font-size: 15px; padding: 13px 20px; }

.share__section-title { font: 700 16px var(--display); }
.share__section-title[data-kind='rules'] { color: var(--trigger); }
.share__section-title[data-kind='goal'] { color: var(--goal); }
.share__section-title[data-kind='modifiers'] { color: var(--modifier); }

.line {
  border: 2px solid var(--line);
  background: var(--bg-raised);
  box-shadow: var(--shadow);
  padding: 16px 18px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.line__text { font-size: 16px; line-height: 1.5; }
.line__text b[data-kind='trigger'] { color: var(--trigger); }
.line__text b[data-kind='effect'] { color: var(--effect); }
.line__text b[data-kind='goal'] { color: var(--goal); }
.line__text b[data-kind='modifier'] { color: var(--modifier); }

.line__row {
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
}

.line__scope { font: 400 11px var(--mono); color: var(--text-mute); }

.share__pair {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 18px;
  align-items: start;
}

.howto {
  border: 2px solid var(--line);
  background: var(--bg-sunken);
  box-shadow: var(--shadow);
  padding: 20px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.howto ol { font-size: 13.5px; line-height: 2; color: var(--text-dim); }

.fail {
  max-width: 560px;
  margin: 0 auto;
  padding: 90px 24px;
  display: flex;
  flex-direction: column;
  gap: 18px;
  text-align: center;
}

.fail__title { font: 700 27px var(--display); color: var(--bad); }
.fail__body { font-size: 14.5px; line-height: 1.6; color: var(--text-mute); }
.fail__detail { font: 400 11.5px var(--mono); color: var(--text-faint); word-break: break-word; }

/* ---------- prose pages (privacy) ---------- */

.prose {
  padding: 52px 0 20px;
  display: flex;
  flex-direction: column;
  gap: 26px;
}

.prose h1 { font: 700 clamp(28px, 4.5vw, 40px)/1.1 var(--display); }
.prose h2 { font: 700 14px var(--display); color: var(--effect); margin-top: 10px; }

.prose p,
.prose ul {
  font-size: 14.5px;
  line-height: 1.7;
  color: var(--text-dim);
  max-width: 640px;
}

.prose ul {
  padding-left: 1.1em;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

/* Transient confirmation after a copy or a download. */
.toast {
  position: fixed;
  left: 50%;
  bottom: 24px;
  transform: translateX(-50%);
  z-index: 80;
  background: var(--effect);
  color: var(--bg);
  font: 700 12px var(--mono);
  padding: 12px 18px;
  box-shadow: var(--shadow-btn);
}

.toast[hidden] { display: none; }


/* ---------- mobile ---------- */

/* Desktop keeps every section on screen at once; the tab bar and the bottom
   action bar are mobile-only, so they are hidden here and revealed below. */
.tabbar, .actionbar { display: none; }

@media (max-width: 900px) {
  .board {
    grid-template-columns: minmax(0, 1fr);
    padding: 14px 16px 110px;
    gap: 18px;
  }

  /* The rail's overview and note are desktop-only, but the name and players
     boxes have to stay reachable, so the rail shows and rides to the top of the
     board (above the sections) rather than hiding wholesale. */
  .rail {
    order: -1;
    position: static;
    gap: 12px;
  }

  .rail__panel, .rail .note { display: none; }

  .tabbar {
    display: flex;
    gap: 6px;
    padding: 10px 16px;
    border-bottom: 2px solid var(--line);
    background: var(--bg-sunken);
    position: sticky;
    top: 0;
    z-index: 20;
  }

  .tabbar .seg__opt {
    flex: 1;
    text-align: center;
    padding: 10px 4px;
    margin-left: 0;
    min-height: var(--tap);
  }

  /* One section at a time on a phone. */
  .board__main .section { display: none; }
  .board__main[data-tab='rules'] .section[data-kind='rules'],
  .board__main[data-tab='goal'] .section[data-kind='goal'],
  .board__main[data-tab='modifiers'] .section[data-kind='modifiers'] { display: flex; }

  .actionbar {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 30;
    display: flex;
    gap: 10px;
    padding: 12px 16px calc(12px + env(safe-area-inset-bottom));
    background: linear-gradient(transparent, var(--bg) 30%);
  }

  .actionbar .btn { flex: 1; }
  .actionbar .btn--icon { flex: 0 0 56px; }

  /* Where a fixed action bar exists, the toast sits above it, not under it. */
  .has-actionbar .toast { bottom: calc(80px + env(safe-area-inset-bottom)); }

  /* The bottom bar already carries export, and the header has no room for a
     second copy of it next to the name field. */
  .topbar__nav--builder #export-top { display: none; }
  .topbar .brand__name { display: none; }

  /* Keep the sheet's close control on the title row instead of its own line. */
  .modal__head .modal__sub { order: 3; width: 100%; }

  .roster-bar__hint { display: none; }

  /* A rule stacks, with the arrow becoming a divider between the halves. The
     how-it-works pipeline stacks the same way. Only the glyph turns downward;
     rotating the whole divider would swing its full-width dashed borders into
     vertical lines through the card. */
  .rule { grid-template-columns: minmax(0, 1fr); }
  .pipeline { grid-template-columns: minmax(0, 1fr); }

  .rule__arrow,
  .pipe__arrow {
    border: none;
    border-top: 2px dashed var(--line);
    border-bottom: 2px dashed var(--line);
    background: none;
    padding: 4px;
    height: 26px;
  }

  .rule__arrow .arrow__glyph,
  .pipe__arrow .arrow__glyph {
    display: inline-block;
    rotate: 90deg;
    scale: .9;
  }

  /* Collapsed cards show a one-line summary; one expands at a time. */
  .card[data-collapsed='true'] .rule,
  .card[data-collapsed='true'] .mod-card__form { display: none; }

  .card__summary {
    display: block;
    width: 100%;
    text-align: left;
    border: none;
    background: none;
    color: var(--text);
    font: 400 13px var(--body);
    padding: 12px 14px;
    cursor: pointer;
    min-height: var(--tap);
  }

  .card:not([data-collapsed='true']) .card__summary { display: none; }

  .params { grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); }
  .input, .toggle { min-height: var(--tap); }
  .seg__opt { flex: 1; text-align: center; min-height: var(--tap); }

  /* Nothing tappable falls under the 44px floor on a touch screen. */
  .roster__name, .chip { min-height: var(--tap); }
  .icon-btn, .chip__drop, .theme-btn { min-width: var(--tap); min-height: var(--tap); }

  /* The picker becomes a bottom sheet. */
  .overlay--top { align-items: flex-end; padding: 0; }

  .modal--picker {
    max-width: none;
    max-height: 88vh;
    height: 88vh;
    border-width: 2px 0 0;
    border-top-color: var(--effect);
    box-shadow: none;
  }

  .modal--picker::before {
    content: '';
    display: block;
    width: 44px;
    height: 4px;
    background: var(--line);
    margin: 8px auto;
    flex-shrink: 0;
  }

  .pick-grid { grid-template-columns: minmax(0, 1fr); }

  .hero { grid-template-columns: minmax(0, 1fr); gap: 34px; padding: 48px 0 40px; }
  .split, .share__pair { grid-template-columns: minmax(0, 1fr); gap: 26px; }
  /* Clear of the sticky bar the shared-link view parks at the bottom. */
  .share { padding: 34px 0 96px; }
  .band { padding: 44px 0; }
  .topbar { padding: 12px 16px; gap: 12px; }
  .topbar__nav { gap: 14px; width: 100%; }
  .shell { padding: 0 16px; }
  .footer { margin-top: 40px; }
}

/* The card summary only exists on small screens. */
@media (min-width: 901px) {
  .card__summary { display: none; }
}
