/* Grimwilder — components. Tokens are in application.css. */

/* ---------- Shared ---------- */

.eyebrow {
  margin: 0 0 var(--space-2);
  color: var(--ember);
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.section-title {
  font-size: 1.5rem;
  margin-bottom: var(--space-4);
}

.page-header { margin-bottom: var(--space-5); }
.page-header__lede { max-width: var(--measure); color: var(--muted); }

.panel {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow);
  padding: var(--space-5);
}

.tag {
  display: inline-block;
  margin-left: var(--space-1);
  padding: 0 var(--space-2);
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  color: var(--dim);
  font-family: var(--font-ui);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  vertical-align: middle;
}

/* ---------- Buttons ---------- */

.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: var(--tap);
  padding: 0 var(--space-4);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-control);
  background: transparent;
  color: var(--text);
  font-family: var(--font-ui);
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
  transition: background 120ms, transform 80ms;
}


/* One primary per area. Secondary is the outline above; ghost is text only. */
.button--primary {
  background: var(--ember);
  border-color: var(--ember);
  color: var(--ember-ink);
}


.button--ghost,
.button--quiet { background: none; border-color: transparent; color: var(--muted); }


.button--suspense { background: var(--suspense); border-color: var(--suspense); color: var(--ember-ink); }

.button--wide { flex: 1; }

/* ---------- Home ---------- */

/* A marketing page: a hero with an example of play beside it, three steps, the table and the
   sheets (the sheets beside an example stat card), the free tools, then the buttons again. The
   examples (.showcase, .sheet-sample) are static pictures made of the app's own dice and chat
   looks. Side by side from 60rem; stacked below. */
.home { display: grid; gap: clamp(var(--space-7), 8vw, 6rem); padding-bottom: var(--space-7); overflow-x: clip; }

.home-hero {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-7);
  align-items: center;
  padding-top: var(--space-5);
  isolation: isolate;
}
/* An ember glow behind the hero, like light from the table's lamp. */
.home-hero::before {
  content: "";
  position: absolute;
  inset: -4rem 0 auto auto;
  z-index: -1;
  width: min(48rem, 90vw);
  height: 32rem;
  background: radial-gradient(closest-side, rgb(232 131 74 / 0.16), transparent);
  pointer-events: none;
}
@media (min-width: 60rem) {
  .home-hero { grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); }
}
.home-hero__title { margin: 0 0 var(--space-2); font-size: clamp(3rem, 9vw, 5.5rem); line-height: 1; }
.home-hero__tagline { margin: 0 0 var(--space-4); font-family: var(--font-display); font-style: italic; font-size: clamp(1.4rem, 3vw, 1.9rem); line-height: 1.25; color: var(--ember); }
.home-hero__lede { margin: 0; max-width: var(--measure); font-size: 1.15rem; color: var(--muted); }

.home-cta { margin-top: var(--space-5); }
.home-cta__actions { display: flex; flex-wrap: wrap; gap: var(--space-3); }

/* The hero's example of play: a window onto a live table. */
.showcase {
  margin: 0;
  overflow: hidden;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow), 0 30px 60px -30px rgb(0 0 0 / 0.9);
}
.showcase__bar { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-3) var(--space-4); border-bottom: 1px solid var(--line-soft); font-size: 0.85rem; color: var(--muted); }
.showcase__live { display: inline-flex; align-items: center; gap: 6px; font-weight: 600; color: var(--perfect); }
.showcase__live::before { content: ""; width: 8px; height: 8px; border-radius: 50%; background: var(--perfect); }
.showcase__feed { display: grid; gap: var(--space-4); padding: var(--space-4); }
.showcase__line { display: grid; gap: 2px; margin: 0; max-width: 85%; }
.showcase__line--narration { font-family: var(--font-display); font-style: italic; font-size: 1.05rem; color: var(--text-soft); }
.showcase__line--mine { justify-self: end; padding: var(--space-2) var(--space-3); background: var(--mine-bg); border: 1px solid var(--mine-line); border-radius: var(--radius-control); }
.showcase__who { margin: 0; font-family: var(--font-ui); font-style: normal; font-size: 0.75rem; font-weight: 600; letter-spacing: 0.04em; color: var(--dim); }
.showcase__who--npc { color: var(--suspense-text); }
.showcase__who small { font-weight: 400; color: var(--dim); }
.showcase__roll { display: grid; gap: var(--space-2); padding: var(--space-3); background: var(--surface-2); border: 1px solid var(--line-soft); border-radius: var(--radius-control); }
.showcase__dice { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
.showcase__dice .die { animation: none; }
.showcase__word { margin-left: var(--space-2); font-family: var(--font-display); font-weight: 700; font-size: 1.6rem; line-height: 1; color: var(--messy); }
.showcase__reason { margin: 0; font-size: 0.85rem; color: var(--text-soft); }
.showcase__pool { display: grid; gap: var(--space-2); }
.showcase__pool-name { font-size: 0.9rem; color: var(--text-soft); }
.showcase__pool-size { margin-right: var(--space-2); font-family: var(--font-dice); font-weight: 600; color: var(--ember); }

/* How it works: three numbered steps. */
.steps { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr)); gap: var(--space-5); margin: 0; padding: 0; list-style: none; counter-reset: none; }
.step { display: grid; gap: var(--space-2); padding: var(--space-5); background: var(--surface); border: 1px solid var(--line-soft); border-radius: var(--radius-card); }
.step__number { display: inline-grid; place-items: center; width: 36px; height: 36px; border: 1px solid var(--ember); border-radius: 50%; font-family: var(--font-dice); font-weight: 600; color: var(--ember); }
.step__name { margin: 0; font-size: 1.3rem; }
.step__desc { margin: 0; color: var(--text-soft); }

/* The feature sections. */
.home-section__head { margin-bottom: var(--space-5); }
.home-section__head .eyebrow { margin-bottom: var(--space-2); }
.home-section__title { margin: 0 0 var(--space-2); font-size: clamp(1.9rem, 4vw, 2.6rem); line-height: 1.1; }
.home-section__lede { margin: 0; max-width: var(--measure); font-size: 1.1rem; color: var(--muted); }
.feature-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 20rem), 1fr));
  gap: var(--space-5) var(--space-6);
}
.feature-list--stacked { grid-template-columns: repeat(auto-fill, minmax(min(100%, 15rem), 1fr)); }
.feature { padding-left: var(--space-4); border-left: 2px solid var(--ember); }
.feature__name { margin: 0 0 var(--space-1); font-family: var(--font-display); font-size: 1.2rem; color: var(--text); }
.feature__desc { margin: 0; font-size: 0.95rem; color: var(--text-soft); }

.home-section--split { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-7); align-items: center; }
/* Stacked, the words come first and the picture after them; side by side, the picture leads. */
.home-section--split > .sheet-sample { order: 1; }
@media (min-width: 60rem) {
  .home-section--split { grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.2fr); }
  .home-section--split > .sheet-sample { order: 0; }
}

/* The sheets section's example stat card. */
.sheet-sample {
  display: grid;
  gap: var(--space-4);
  margin: 0;
  padding: var(--space-5);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow), 0 30px 60px -30px rgb(0 0 0 / 0.9);
}
.sheet-sample__who { display: flex; align-items: center; gap: var(--space-3); }
.sheet-sample__who .pips { margin-left: auto; }
.sheet-sample__monogram { display: inline-grid; place-items: center; width: 44px; height: 44px; border-radius: 50%; background: var(--ember-soft); border: 1px solid var(--ember); font-family: var(--font-display); font-weight: 700; font-size: 1.3rem; color: var(--ember); }
.sheet-sample__name { display: block; font-family: var(--font-display); font-weight: 700; font-size: 1.3rem; line-height: 1.1; }
.sheet-sample__meta { display: block; font-size: 0.85rem; color: var(--muted); }
.sheet-sample__stat { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-4); background: var(--surface-2); border-radius: var(--radius-control); }
.sheet-sample__stat-name { font-family: var(--font-display); font-size: 1.4rem; }
.sheet-sample__marked { padding: 2px 10px; border: 1px solid var(--grim); border-radius: var(--radius-sm); background: var(--grim-bg); font-size: 0.8rem; color: var(--grim); }
.sheet-sample__dice { margin-left: auto; font-family: var(--font-dice); font-weight: 600; font-size: 28px; color: var(--grim); }
.sheet-sample__harm { margin: 0; font-size: 0.9rem; color: var(--grim); }
.sheet-sample__roll { display: grid; place-items: center; min-height: var(--tap); border-radius: var(--radius-control); background: var(--ember); font-weight: 600; color: var(--ember-ink); }

/* The closing call to action. */
.home-close {
  display: grid;
  justify-items: center;
  padding: clamp(var(--space-6), 6vw, var(--space-7)) var(--space-5);
  text-align: center;
  background: radial-gradient(ellipse at top, rgb(232 131 74 / 0.12), transparent 70%), var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
}
.home-close__title { margin: 0 0 var(--space-2); font-size: clamp(1.8rem, 4vw, 2.4rem); }
.home-close__lede { margin: 0; color: var(--muted); }
.home-close .home-cta__actions { justify-content: center; }

.tool-grid__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 15rem), 1fr));
  gap: var(--space-4);
}

.tool-grid__list > li { display: flex; }

.tool-card {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-5);
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius-control);
  color: var(--muted);
  text-decoration: none;
}

.tool-card--ready {
  border-style: solid;
  border-color: var(--line);
  background: var(--surface);
  box-shadow: var(--shadow);
  color: var(--text);
  transition: transform 120ms, border-color 120ms;
}

.tool-card--ready:hover { color: var(--text); border-color: var(--ember); transform: translateY(-2px); }

.tool-card__glyph {
  font-family: var(--font-display);
  font-size: 1.6rem;
  color: var(--ember);
}

.tool-card__name { font-family: var(--font-display); font-size: 1.4rem; color: var(--text); }
.tool-card__desc { font-size: 0.95rem; }

/* A campaign on the campaigns list: the card links in, and the GM's ⋯ (archive or unarchive) sits in its top right corner, outside the link. */
.campaign-card { position: relative; }
.campaign-card .tool-card { padding-right: calc(var(--tap) + var(--space-4)); }
.campaign-card__more { position: absolute; top: var(--space-3); right: var(--space-3); }
.campaign-card__toggle { width: var(--tap); padding: 0; list-style: none; }
.campaign-card__toggle::-webkit-details-marker { display: none; }
.campaign-card__menu { position: absolute; z-index: 15; right: 0; top: calc(100% + 4px); display: grid; gap: var(--space-2); width: min(16rem, calc(100vw - 2rem)); padding: var(--space-3); border: 1px solid var(--line); border-radius: var(--radius-control); background: var(--surface); box-shadow: var(--shadow); }
.campaign-card__menu .button_to,
.campaign-card__menu .button { width: 100%; }
.campaign-card__menu .field__hint { margin: 0; }

/* On hold (Campaign::Hold): dimmed, with "Play this one" in the bottom right when it's the viewer's seat that's held. */
.campaign-card--on-hold .tool-card { opacity: 0.6; border-style: dashed; }
.campaign-card--playable .tool-card { padding-bottom: calc(var(--tap) + var(--space-5)); }
.campaign-card__play { position: absolute; right: var(--space-3); bottom: var(--space-3); margin: 0; }
.hold-banner { margin-bottom: var(--space-4); padding: var(--space-3) var(--space-4); border: 1px dashed var(--suspense); border-radius: var(--radius-control); background: var(--surface); }
.hold-banner p { margin: 0; }

/* The last card in a list makes a new one ("Create new …"): dashed, like an empty seat, and ember on hover when it's a link. */
.add-card { justify-content: flex-start; }
.add-card h2 { margin: 0; }
.add-card--link { text-decoration: none; }
.add-card--link:hover { border-color: var(--ember); }

/* The character list: each card links to the sheet and seats it in a campaign. */
.character-list__card { flex: 1; display: flex; flex-direction: column; gap: var(--space-3); }
.character-list__card .field__hint { margin: auto 0 0; }
.character-list__link { display: flex; flex-direction: column; gap: var(--space-1); color: var(--muted); text-decoration: none; }
.character-list__link:hover .tool-card__name { color: var(--ember); }
.seat-form { display: grid; gap: var(--space-1); margin-top: auto; }
.seat-form__row { display: flex; gap: var(--space-2); }
.seat-form__row .field__input { flex: 1; min-width: 0; }

/* ---------- Roller ---------- */

.roller__grid {
  display: grid;
  gap: var(--space-5);
}

@media (min-width: 52rem) {
  /* Side by side, the setup panel is as tall as the result beside it (a critical makes that taller). */
  .roller__grid { grid-template-columns: minmax(18rem, 22rem) 1fr; align-items: stretch; }
}

.roller__controls { display: grid; gap: var(--space-5); align-content: start; }

.roller__actions { display: flex; gap: var(--space-2); }
.roller__talents > :not(summary) { margin-top: var(--space-3); }
.result__twist { margin: var(--space-2) 0 0; color: var(--grim); font-weight: 600; }

.segmented {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 2px;
  margin: 0;
  padding: 3px;
  border: 1px solid var(--line);
  border-radius: var(--radius-control);
  background: var(--bg);
}

.segmented__option {
  position: relative;
  display: block;
  cursor: pointer;
}

.segmented__option input {
  position: absolute;
  opacity: 0;
  inset: 0;
  margin: 0;
  cursor: pointer;
}

.segmented__text {
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 0.35em;
  min-height: calc(var(--tap) - 8px);
  padding: 0 var(--space-3);
  line-height: calc(var(--tap) - 8px);
  border-radius: calc(var(--radius-control) - 3px);
  text-align: center;
  font-weight: 600;
  color: var(--muted);
  transition: background 120ms, color 120ms, box-shadow 120ms;
}

/* The chosen one: an ember ring and fill, so it reads by shape as well as color.
   Matched with :has() rather than input + span, because in development Herb's
   debug mode wraps ERB output (a radio_button_tag) in a span of its own. */
.segmented__option:has(input:checked) .segmented__text {
  background: color-mix(in srgb, var(--ember) 22%, var(--surface));
  color: var(--text);
  box-shadow: inset 0 0 0 2px var(--ember);
}

/* An option that can't be picked yet (its title says why). */
.segmented__option:has(input:disabled) { cursor: not-allowed; }
.segmented__option:has(input:disabled) .segmented__text { color: var(--dim); opacity: 0.55; }
.segmented__option:has(input:focus-visible) .segmented__text { outline: 2px solid var(--focus); outline-offset: 1px; }

.counter__label {
  display: block;
  font-family: var(--font-display);
  font-size: 1.3rem;
  margin-bottom: var(--space-2);
}

.counter__control {
  display: grid;
  grid-template-columns: 3rem 1fr 3rem;
  align-items: center;
  gap: var(--space-2);
}

.counter__step {
  height: 3rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  background: var(--bg);
  color: var(--text);
  font-size: 1.5rem;
  line-height: 1;
  cursor: pointer;
}

.counter__step:hover:not(:disabled) { background: var(--surface-2); }
.counter__step:disabled { opacity: 0.35; cursor: not-allowed; }

.counter__value {
  text-align: center;
  font-family: var(--font-display);
  font-size: 2.5rem;
  line-height: 1;
}

.counter__value--d8 { color: var(--disaster); }

.counter__hint { margin: var(--space-2) 0 0; font-size: 0.85rem; color: var(--dim); }

/* Result panel */

.roller__result { min-height: 18rem; display: flex; flex-direction: column; }

/* The dice on one line, the thorns on the next (roller_controller.js). */
.tray {
  display: grid;
  gap: var(--space-3);
  min-height: 3.5rem;
}
.tray__row { display: flex; flex-wrap: wrap; gap: var(--space-3); }


.die {
  --size: 44px;
  display: inline-grid;
  place-items: center;
  flex: none;
  width: var(--size);
  height: var(--size);
  border-radius: var(--radius-control);
  background: var(--surface-2);
  color: var(--text);
  font-family: var(--font-dice);
  font-size: calc(var(--size) * 0.45);
  font-weight: 600;
  line-height: 1;
  animation: die-in 260ms cubic-bezier(.2,.9,.3,1.3) both;
  animation-delay: var(--delay, 0ms);
}

.die--44 { --size: 44px; }
.die--32 { --size: 32px; border-radius: 8px; }
.die--28 { --size: 28px; border-radius: 7px; }

/* The die that set the result, filled with its own result's color. */
.die--top { color: var(--ember-ink); }
.die--top.die--perfect { background: var(--perfect); }
.die--top.die--messy { background: var(--messy); }
.die--top.die--grim { background: var(--grim); }

.die--dropped {
  background: transparent;
  box-shadow: inset 0 0 0 1px var(--line);
  color: var(--dim);
  text-decoration: line-through;
}

/* Thorns: diamonds (a square turned 45° behind the number, which stays
   upright). A 7 or 8 cuts, and goes red. */
.die--d8 {
  position: relative;
  isolation: isolate;
  background: transparent;
  color: var(--dim);
  font-size: calc(var(--size) * 0.4);
}

.die--d8::before {
  content: "";
  position: absolute;
  z-index: -1;
  inset: 15%;
  border: 2px solid var(--line-strong);
  border-radius: 3px;
  transform: rotate(45deg);
}

.die--d8.die--cut { color: var(--grim); }
.die--d8.die--cut::before { border-color: var(--grim-ring); background: var(--grim-bg); }

.die--assist { box-shadow: inset 0 0 0 1px var(--muted); outline: 1px dashed var(--muted); outline-offset: 2px; }
.die--spark { box-shadow: inset 0 0 0 2px var(--spark); }

@keyframes die-in {
  from { transform: translateY(-8px) rotate(-25deg) scale(0.6); opacity: 0; }
}

/* Right under the dice it came from. */
.result {
  margin-top: var(--space-3);
  padding: var(--space-5);
  border-radius: var(--radius-sm);
  border-left: 6px solid var(--result-color, var(--line-strong));
  background: color-mix(in srgb, var(--result-color, var(--surface-2)) 12%, var(--surface));
}

.result--perfect { --result-color: var(--perfect); }
.result--messy { --result-color: var(--messy); }
.result--grim { --result-color: var(--grim); }
.result--disaster { --result-color: var(--disaster); }
.result--empty { border-left-color: transparent; background: var(--surface-2); color: var(--dim); }

.result__name { font-size: 2.5rem; margin: 0 0 var(--space-1); color: var(--result-color); }
.result__text { margin: 0; font-size: 1.15rem; }

.critical {
  margin-top: var(--space-4);
  padding-top: var(--space-4);
  border-top: 1px solid color-mix(in srgb, var(--perfect) 35%, transparent);
}

.critical p { margin: 0; }
.critical__choices { display: grid; gap: var(--space-1); margin: var(--space-1) 0 var(--space-2); padding-left: 1.2em; }
.critical__choices li::marker { color: var(--perfect); }
.critical__fallback { color: var(--muted); }
/* The /roll page's critical: its choices right under the perfect text, no divider. */
.result__critical { margin-top: var(--space-3); }
.result__critical p { margin: 0; }

.ladder {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 9rem), 1fr));
  gap: var(--space-2);
  margin-top: var(--space-5);
}

.ladder__step {
  padding: var(--space-2) var(--space-3);
  border-top: 4px solid var(--step);
  background: var(--surface);
  border-radius: 0 0 var(--radius-sm) var(--radius-sm);
  font-size: 0.9rem;
  color: var(--muted);
}

.ladder__step strong { display: block; color: var(--step); font-size: 1rem; }

.ladder__step--perfect { --step: var(--perfect); }
.ladder__step--messy { --step: var(--messy); }
.ladder__step--grim { --step: var(--grim); }
.ladder__step--disaster { --step: var(--disaster); }

/* ---------- Flash ---------- */

.flash {
  max-width: var(--measure);
  margin: 0 0 var(--space-5);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-sm);
  border-left: 4px solid var(--flash-color, var(--ember));
  background: color-mix(in srgb, var(--flash-color, var(--ember)) 10%, var(--surface));
}

.flash--alert { --flash-color: var(--grim); }
.flash--dev { --flash-color: var(--messy); font-size: 0.95rem; }

/* ---------- Forms ---------- */

.stack { display: grid; gap: var(--space-4); align-content: start; }
.stack > form { margin: 0; }

.field { display: grid; gap: var(--space-1); }
.field__label { font-weight: 700; }
.field__hint { margin: 0; font-size: 0.9rem; color: var(--dim); }

.field__input {
  width: 100%;
  min-height: var(--tap);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-control);
  background-color: var(--bg);
  color: var(--text);
  font: inherit;
}

/* Room for the chevron the base select style draws. */
select.field__input { padding-right: 2.5rem; }

/* The trait or desire you aren't, set apart from the two you are. */
.field__input--not { border-color: var(--not-line); }

.field__input:focus-visible { outline: 2px solid var(--focus); outline-offset: 1px; border-color: transparent; }
/* Safari leaves a focused select (ours are drawn with appearance: none)
   without the outline, so it would lose its edge until it loses focus: keep
   the border and draw the ring as a shadow. */
select.field__input:focus-visible { outline: none; border-color: var(--focus); box-shadow: 0 0 0 1px var(--focus); }

.field__input--code {
  font-family: ui-monospace, Menlo, Consolas, monospace;
  font-size: 1.6rem;
  letter-spacing: 0.3em;
  text-align: center;
  text-transform: uppercase;
}

.form-error { margin: 0; color: var(--grim); font-weight: 600; }
.form-error[hidden] { display: none; }

.button--small { min-height: var(--tap); padding: 0 var(--space-3); font-size: 0.9rem; }
.button--danger { color: var(--grim); border-color: color-mix(in srgb, var(--grim) 45%, transparent); background: none; }
.button--danger:hover { background: color-mix(in srgb, var(--grim) 10%, var(--surface)); color: var(--grim); }
.button:disabled { opacity: 0.6; cursor: progress; }

form.button_to, .button_to { margin: 0; }

.divider {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin: var(--space-5) 0;
  color: var(--dim);
  font-size: 0.85rem;
  text-transform: uppercase;
  letter-spacing: 0.12em;
}

.divider::before,
.divider::after { content: ""; flex: 1; border-top: 1px solid var(--line); }

/* ---------- Auth pages ---------- */

.auth { max-width: 28rem; }

/* "I'm interested" (/interest): the role radios in a row, and a honeypot kept off screen. */
.field__optional { font-weight: 400; color: var(--dim); }
.interest__roles { margin: 0; padding: 0; border: 0; }
.interest__roles legend { padding: 0; margin-bottom: var(--space-2); }
.interest__role { display: inline-flex; align-items: center; gap: var(--space-2); min-height: var(--tap); margin-right: var(--space-4); }
.interest__website { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
.interest__next { display: flex; flex-wrap: wrap; gap: var(--space-3); }
/* Long text in an admin table stays on one line, cut off with an ellipsis; the full text shows
   in a tooltip (truncated_tip_controller.js). */
.admin-truncate { display: block; max-width: 12rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.admin-truncate--note { max-width: 14rem; }
.floating-tip {
  position: fixed;
  z-index: 50;
  max-width: min(24rem, calc(100vw - 16px));
  padding: 6px 10px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  background: var(--surface);
  box-shadow: 0 6px 18px rgb(0 0 0 / 0.4);
  font-size: 0.85rem;
  line-height: 1.4;
  color: var(--text);
  white-space: pre-line;
  overflow-wrap: anywhere;
  pointer-events: none;
}
.auth__panel { display: grid; }
.auth__aside { margin: var(--space-4) 0 0; font-size: 0.95rem; }

.passkey { display: grid; gap: var(--space-2); }
.passkey__icon { font-size: 1.1em; }
.passkey__status { margin: 0; min-height: 1.4em; font-size: 0.9rem; color: var(--dim); }

/* ---------- Profile & campaigns ---------- */

.profile,
.campaign {
  display: grid;
  gap: var(--space-5);
  max-width: 40rem;
}


.panel__title { font-size: 1.4rem; margin: 0; }

.list { list-style: none; margin: 0; padding: 0; }

.list__item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-3) 0;
  border-top: 1px solid var(--line);
}

.list__item:first-child { border-top: 0; }
.list__item small { display: block; }
.list__actions { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: var(--space-2); }

.copy-field { display: flex; gap: var(--space-2); }
.copy-field__input { flex: 1; min-width: 0; font-size: 0.9rem; }

.empty { color: var(--dim); }

/* ---------- Pools ---------- */

.pools { display: grid; gap: var(--space-6); }

@media (min-width: 60rem) {
  .pools { grid-template-columns: 1fr minmax(18rem, 21rem); align-items: start; }
}

.pool-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 17rem), 1fr));
  gap: var(--space-4);
}

.pool {
  --pool-color: var(--muted);
  display: grid;
  gap: var(--space-3);
  align-content: start;
  padding: var(--space-4) var(--space-5) var(--space-5);
  border: 1px solid var(--line);
  border-top: 4px solid var(--pool-color);
  border-radius: var(--radius-control);
  background: var(--surface);
  box-shadow: var(--shadow);
  scroll-margin-top: var(--space-6);
}

.pool--pressure { --pool-color: var(--ember); }
.pool--timer { --pool-color: var(--messy); }
.pool--resource { --pool-color: var(--ember); }
.pool--power { --pool-color: var(--disaster); }
.pool--campaign { --pool-color: var(--line-strong); }

.pool__name { font-size: 1.5rem; margin: 0; }
.pool__kind { margin: var(--space-1) 0 0; font-size: 0.85rem; color: var(--dim); }

.pool__meter { display: flex; align-items: center; gap: var(--space-3); }

.pool__phases { display: flex; flex-wrap: wrap; gap: var(--space-1) var(--space-3); margin: 0; padding: 0; list-style: none; font-size: 0.9rem; color: var(--dim); }
.pool__phase--done { text-decoration: line-through; }
.pool__phase--current { color: var(--pool-color); font-weight: 700; }
.pool__size { font-family: var(--font-display); font-size: 2.6rem; line-height: 1; min-width: 2.5ch; }
.pool__pips { display: flex; flex-wrap: wrap; gap: 5px; }

.pool__pips .pip {
  width: 0.85rem;
  height: 0.85rem;
  border-radius: 3px;
  background: var(--pool-color);
}

.pool__pips .pip--gone { background: none; box-shadow: inset 0 0 0 1.5px var(--line-strong); }

.pool__outcome {
  margin: 0;
  font-family: var(--font-display);
  font-size: 1.4rem;
  color: var(--pool-color);
}

.pool--depleted .pool__size { color: var(--dim); }

.pool__last { display: grid; gap: var(--space-2); }
.pool__dice { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.pool__summary { margin: 0; font-size: 0.85rem; color: var(--dim); }

.pool__actions { display: grid; gap: var(--space-3); margin-top: var(--space-1); }
.pool__roll { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-3); margin: 0; }
.pool__gm { display: flex; flex-wrap: wrap; gap: var(--space-1); border-top: 1px solid var(--line); padding-top: var(--space-2); }

.check { display: inline-flex; align-items: center; gap: var(--space-2); font-size: 0.95rem; cursor: pointer; }
.check input { width: 1.1rem; height: 1.1rem; accent-color: var(--ember); }

.size-picker { display: flex; flex-wrap: wrap; gap: var(--space-2); align-items: center; }
.size-picker__presets { flex: 1 1 16rem; }
.size-picker__input { width: 5rem; min-height: var(--tap); }

.pool__gm .button { min-height: var(--tap); padding: 0 var(--space-2); font-size: 0.85rem; }
.pool__gm { gap: 0 var(--space-2); }

/* ---------- Crucibles ---------- */

.crucible-group { margin-bottom: var(--space-6); }
/* The list's search, sticky like the talent catalog's. */
.crucible-catalog__tools {
  position: sticky;
  top: 0;
  z-index: 2;
  display: grid;
  gap: var(--space-2);
  margin-bottom: var(--space-6);
  padding: var(--space-3) 0;
  background: var(--bg);
  border-bottom: 1px solid var(--line);
}
.crucible-catalog__search { max-width: 32rem; }
.crucible-catalog__tools > .field__hint { margin: 0; }
.crucible-catalog__tools > .field__hint:empty { display: none; }
.crucible-catalog__empty { color: var(--dim); }
.crucible-catalog .tool-grid__list > li[hidden] { display: none; }
.tool-card small { margin-top: auto; }

.crucible__roller { display: grid; gap: var(--space-4); margin-bottom: var(--space-6); }
.crucible__actions { display: flex; flex-wrap: wrap; gap: var(--space-2); align-items: center; }
.crucible__hint { margin: 0; color: var(--dim); }

/* The chosen words lead, smashed together; under them a row for each table: its
   name, the dice, then the readings, on one line and only as wide as that. Rows sit side by side
   when there's room, each a tile of its own; a row wraps only when it can't fit the screen, keeping the chips together. */
.crucible__results { display: grid; gap: var(--space-3); }
.roll-result__smash {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 4vw, 2.1rem);
  line-height: 1.2;
}
.roll-result__smash:empty { display: none; }
.crucible__rows {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin: 0;
  padding: 0;
  list-style: none;
}
.crucible-roll {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-3);
  max-width: 100%;
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-control);
}
.crucible-roll__name {
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  white-space: nowrap;
}
.crucible-roll__dice { display: flex; gap: var(--space-1); }
.crucible-roll__readings { display: flex; gap: var(--space-2); }
.crucible-roll__readings .chip { white-space: nowrap; }
/* A lone reading with nothing to choose or fill: text, not a chip. */
.crucible-roll__word { color: var(--ember); font-size: 1.05rem; font-weight: 600; white-space: nowrap; }

.chip {
  padding: var(--space-1) var(--space-3);
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  background: var(--bg);
  color: var(--muted);
  font-size: 1.05rem;
  cursor: pointer;
}

.chip[aria-pressed="true"] { background: var(--ember); border-color: var(--ember); color: var(--ember-ink); font-weight: 700; }

.crucible__kept { border-top: 1px solid var(--line); padding-top: var(--space-4); display: grid; gap: var(--space-2); }
.crucible__kept[hidden] { display: none; }
.crucible__kept-title { font-size: 1.2rem; margin: 0; }
.crucible__kept-list { margin: 0; padding-left: 1.4em; }

.crucible__toolbar { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-3); }

/* Laid out by how many tables there are (data-count): three or more fill columns of 26rem,
   two share the width, and one has it to itself, with bigger cells, a narrow list kept to a
   readable width. */
.crucible__tables {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 26rem), 1fr));
  gap: var(--space-5);
}
.crucible__tables[data-count="2"] { grid-template-columns: repeat(auto-fit, minmax(min(100%, 26rem), 1fr)); }
.crucible__tables[data-count="1"] { grid-template-columns: minmax(0, 1fr); }
@media (min-width: 40rem) {
  .crucible__tables[data-count="1"] .grid66 { font-size: 1rem; }
  .crucible__tables[data-count="1"] .grid66 td { padding: var(--space-2); }
}
.crucible__tables[data-count="1"] .crucible-table[data-width="1"] { max-width: 40rem; }
.crucible__tables[data-count="1"] .crucible-table[data-width="2"] { max-width: 52rem; }
.crucible__tables[data-count="1"] .crucible-table[data-width="3"] { max-width: 64rem; }

.crucible__tables[hidden] { display: none; }

.crucible-table__header { display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--space-2); }
.crucible-table__name { margin: 0; }

.grid66 {
  width: 100%;
  border-collapse: collapse;
  table-layout: fixed;
  font-size: 0.85rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
}

.grid66 th,
.grid66 td {
  padding: var(--space-1) var(--space-1);
  border: 1px solid var(--line);
  text-align: center;
  hyphens: auto;
}

.grid66-wrap { overflow-x: auto; }
.grid66 { min-width: 21rem; }

@media (max-width: 30rem) {
  .grid66 { font-size: 0.75rem; }
  .grid66 th,
  .grid66 td { padding: var(--space-1) 2px; }
}

.grid66 th { color: var(--dim); font-weight: 600; font-size: 0.75rem; }
/* A 2- or 3-column table's second-die faces beside its heading ("Origin 1–2"). */
.grid66__dice { font-family: var(--font-dice); font-weight: 500; white-space: nowrap; }
.grid66 thead th:first-child,
.grid66 tbody th { width: 1.8rem; }

.grid66 td.is-hit {
  background: color-mix(in srgb, var(--ember) 22%, var(--surface));
  color: var(--text);
  font-weight: 700;
  outline: 2px solid var(--ember);
  outline-offset: -2px;
}

/* ---------- Characters ---------- */

.character-form { display: grid; gap: var(--space-5); max-width: 46rem; }
.character-form__actions { display: flex; gap: var(--space-2); }
.character-danger { max-width: 46rem; margin-top: var(--space-6); }
.character-danger__action { display: grid; gap: var(--space-2); justify-items: start; }
.character-danger__action .button_to { margin: 0; }
.character-danger__buttons { display: flex; flex-wrap: wrap; gap: var(--space-2); }

.fieldset { display: grid; gap: var(--space-2); margin: 0; padding: 0; border: 0; min-width: 0; }
/* A bond toward someone at the table: who, then how you see them. */
.bond-row { display: grid; gap: var(--space-1) var(--space-4); grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr)); align-items: center; }
.bond-row__name { font-family: var(--font-display); font-weight: 700; }
.bond-row__player { font-size: 0.85rem; color: var(--dim); }
.bonds-npcs { display: grid; gap: var(--space-2); margin-top: var(--space-2); }
.bonds-npcs__title { margin: 0; font-size: 0.87rem; font-weight: 600; color: var(--dim); }
.bonds-npcs__add { justify-self: start; }
.two-up { display: grid; gap: var(--space-2) var(--space-4); grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr)); }
.stat-inputs { display: grid; gap: var(--space-4); grid-template-columns: repeat(auto-fit, minmax(min(100%, 9rem), 1fr)); }
.field__input--small { min-height: var(--tap); font-size: 0.95rem; }
.field__input--short { width: 6rem; }

.toggle {
  min-height: var(--tap);
  padding: 0 var(--space-3);
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  background: none;
  color: var(--muted);
  font-size: 0.85rem;
  font-weight: 600;
  cursor: pointer;
}

.toggle[aria-pressed="true"] { background: var(--grim); border-color: var(--grim); color: var(--surface); }
.toggle-row { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.toggle--harm { min-height: var(--tap); padding: 0 var(--space-4); font-size: 0.95rem; }

.inline-form { display: flex; gap: var(--space-2); flex-wrap: wrap; margin: 0; }

.inline-form .field__input { flex: 1; min-width: 12rem; min-height: var(--tap); }

.tracker {
  display: grid;
  grid-template-columns: 4.5rem 1fr auto auto;
  align-items: center;
  gap: var(--space-1) var(--space-2);
}

.tracker__name { font-family: var(--font-display); font-size: 1.2rem; }
.tracker__pips { display: flex; flex-wrap: wrap; gap: 6px; --pool-color: var(--ember); }
.tracker__pips .pip { width: 1.1rem; height: 1.1rem; border-radius: 50%; }
.tracker__pips .pip--xp { border-radius: 3px; }
.tracker__hint { grid-column: 1 / -1; }
.tracker .button_to { margin: 0; }

.counter__step--small { width: var(--tap); height: var(--tap); font-size: 1.1rem; }

/* ---------- Talents ---------- */

.talent-catalog { display: grid; gap: var(--space-6); }

.talent-catalog__tools {
  position: sticky;
  top: 0;
  z-index: 2;
  display: grid;
  gap: var(--space-2);
  padding: var(--space-3) 0;
  background: var(--bg);
  border-bottom: 1px solid var(--line);
}

.talent-catalog__tools { grid-template-columns: minmax(12rem, 16rem) minmax(0, 32rem); align-items: center; }
.talent-catalog__tools > .field__hint { grid-column: 1 / -1; margin: 0; }
@media (max-width: 35rem) { .talent-catalog__tools { grid-template-columns: 1fr; } }
.talent-catalog__path { width: 100%; }

.talent-group { scroll-margin-top: 9rem; }
.talent-group[hidden] { display: none; }
.talent-group__header { margin-bottom: var(--space-3); }
.talent-group__header .section-title { margin-bottom: var(--space-1); }
.talent-group__tagline { margin: var(--space-1) 0 0; color: var(--muted); max-width: var(--measure); }

.talent-grid { display: grid; gap: var(--space-3); grid-template-columns: repeat(auto-fill, minmax(min(100%, 22rem), 1fr)); }

.talent {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-4);
  border: 1px solid var(--line);
  border-radius: var(--radius-control);
  background: var(--surface-2);
  scroll-margin-top: 9rem;
}

.talent[hidden] { display: none; }
.talent--core { grid-column: 1 / -1; border-color: color-mix(in srgb, var(--ember) 45%, var(--line)); background: linear-gradient(135deg, var(--ember-soft), var(--surface-2) 60%); }
.talent__header { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: var(--space-1) var(--space-3); }
.talent__name { margin: 0; font-size: 1.3rem; }
.talent__meta { font-size: 0.8rem; color: var(--dim); }
.talent__summary { margin: 0; color: var(--text-soft); }
.talent__choices { margin: 0; font-size: 0.85rem; color: var(--muted); }
.talent__more > .fold__summary { min-height: var(--tap); font-size: 0.87rem; font-weight: 600; color: var(--dim); }
.talent__more[open] > .fold__summary { margin-bottom: var(--space-1); }
.talent__more .talent__note { margin-top: var(--space-2); }
.talent__text p { margin: 0 0 var(--space-2); font-size: 0.95rem; }
.talent__text p:last-child { margin-bottom: 0; }
.talent__note { margin: 0; padding-left: var(--space-3); border-left: 3px solid var(--line-strong); font-size: 0.88rem; font-style: italic; color: var(--muted); }
.talent__take { margin-top: auto; padding-top: var(--space-2); }
.talent__take .button_to { margin: 0; }
.talent-toggle { display: inline-flex; cursor: pointer; }
.talent-toggle__box { position: absolute; opacity: 0; pointer-events: none; }
.talent-toggle__added { display: none; gap: var(--space-1); }
/* :has(), not a sibling selector: Herb's dev debug mode wraps the checkbox in a span. */
.talent-toggle:has(.talent-toggle__box:checked) .talent-toggle__add { display: none; }
.talent-toggle:has(.talent-toggle__box:checked) .talent-toggle__added { display: inline-flex; }
.talent-toggle:has(.talent-toggle__box:focus-visible) .button { outline: 2px solid var(--focus); outline-offset: 2px; }

/* The talent picker: the catalog, and what's taken beside it (a drawer on a phone). */
.talent-picker { display: grid; grid-template-columns: minmax(0, 1fr) 20rem; gap: var(--space-5); align-items: start; }
.talent-picker__panel { position: sticky; top: var(--space-4); }
.talent-picker__head { display: flex; align-items: center; gap: var(--space-2); }
.talent-picker__head .panel__title { margin: 0; flex: 1; }
.talent-picker__count { font-family: var(--font-dice); color: var(--text-soft); }
.talent-picker__close, .talent-picker__fab { display: none; }
.talent-picker__list { display: grid; gap: var(--space-1); margin: 0; padding: 0; list-style: none; }
.talent-picker__item { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); min-height: var(--tap); padding: 0 var(--space-2); border: 1px solid var(--line); border-radius: var(--radius-control); background: var(--surface-2); }
.talent-picker__remove { display: inline-grid; place-items: center; width: var(--tap); height: var(--tap); margin-right: calc(var(--space-2) * -1); border: 0; background: none; color: var(--text-soft); cursor: pointer; }
.talent-picker__remove:hover { color: var(--text); }
@media (max-width: 60rem) {
  .talent-picker { grid-template-columns: 1fr; }
  .talent-picker__panel { display: none; position: fixed; inset: auto var(--space-4) var(--space-4); z-index: 30; max-height: 75vh; overflow: auto; box-shadow: 0 12px 40px rgb(0 0 0 / 0.5); }
  .talent-picker--open .talent-picker__panel { display: block; }
  .talent-picker__close { display: inline-grid; }
  .talent-picker__fab { display: inline-flex; gap: var(--space-2); position: fixed; right: var(--space-4); bottom: var(--space-4); z-index: 29; box-shadow: 0 8px 24px rgb(0 0 0 / 0.45); }
  .talent-picker--open .talent-picker__fab { display: none; }
}

/* ---------- Table rolls & log ---------- */

.segmented--auto { grid-template-columns: none; grid-auto-flow: column; grid-auto-columns: 1fr; }

.roll-setup { display: grid; gap: var(--space-5); max-width: 28rem; }
.roll-setup__group { display: grid; gap: var(--space-2); margin: 0; padding: 0; border: 0; }
.roll-setup__number { max-width: 6rem; font-size: 1.2rem; }

.roll-outcome { display: grid; max-width: 40rem; }
.roll-outcome .result { margin-top: 0; }
.critical .button_to { margin-top: var(--space-3); }
.critical .field__hint { margin-top: var(--space-3); }

.roll-outcome__assists { margin: var(--space-3) 0 0; }

.roll-outcome__spark { margin: var(--space-3) 0 0; font-weight: 700; color: var(--disaster); }

.roll-next { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-top: var(--space-5); }

.roll-log { list-style: none; margin: 0; padding: 0; }
.roll-log:has(li) + .roll-log__empty { display: none; }

.log-entry {
  --entry-color: var(--line-strong);
  display: grid;
  gap: var(--space-2);
  padding: var(--space-3) 0 var(--space-3) var(--space-3);
  border-top: 1px solid var(--line);
  border-left: 4px solid var(--entry-color);
}

.log-entry:first-child { border-top: 0; }

.log-entry--perfect { --entry-color: var(--perfect); }
.log-entry--messy { --entry-color: var(--messy); }
.log-entry--grim { --entry-color: var(--grim); }
.log-entry--disaster { --entry-color: var(--disaster); }

/* A secret roll (gm_only): outlined dashed purple, like a whisper. */
.log-entry--gm-only { padding-right: var(--space-3); border: 1px dashed var(--suspense-line); border-left: 4px solid var(--entry-color); border-radius: var(--radius-sm); }
.tag--gm-only { border-color: var(--suspense-line); color: var(--suspense-text); }

.log-entry__head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: var(--space-1) var(--space-3); }
.log-entry__title { margin: 0; }
.log-entry__result { font-family: var(--font-display); font-size: 1.25rem; color: var(--entry-color); }
.log-entry__dice { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.log-entry__meta { margin: 0; font-size: 0.85rem; color: var(--dim); }
.log-entry__who { white-space: nowrap; }

.log-entry--quarrel { --entry-color: var(--ember); }
.log-entry__question { margin: 0; font-style: italic; }

.quarrel-sides { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-2); }
.quarrel-side { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-2); }
.quarrel-side__name { font-size: 0.95rem; color: var(--muted); }
.quarrel-side--winner .quarrel-side__name { color: var(--text); font-weight: 700; }

.pool__power summary { cursor: pointer; font-weight: 700; color: var(--muted); }
.pool__power[open] { display: grid; gap: var(--space-3); }
.pool__power .field__hint { margin-top: var(--space-2); }

.quarrel-form { max-width: 40rem; }
.quarrel-form__row { flex-wrap: wrap; }
.quarrel-form__choices { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.quarrel-form__choices .field__input { width: auto; min-height: var(--tap); }

/* Collapsible sections: native <details>, styled. */
.fold > .fold__summary { list-style: none; cursor: pointer; }
.fold > .fold__summary::-webkit-details-marker { display: none; }
.fold__summary { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-1) var(--space-2); }
.fold__summary::before {
  content: "▸";
  color: var(--dim);
  font-size: 0.8rem;
  transition: transform 120ms;
}
.fold[open] > .fold__summary::before { transform: rotate(90deg); }
.fold__summary:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; border-radius: var(--radius-sm); }
.fold__title { font-family: var(--font-display); font-size: 1.3rem; line-height: 1.2; margin-right: auto; }
.fold__meta { font-size: 0.85rem; color: var(--dim); }
.fold__meta--fill { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fold__meta--wide { display: none; }
.fold__body { display: grid; gap: var(--space-3); }
.fold__footer { margin: var(--space-3) 0 0; font-size: 0.9rem; }
.fold__heading { margin: 0; font-size: 1.1rem; }

@media (min-width: 48rem) {
  .fold__meta--wide { display: inline-flex; }
  .fold__meta--phone { display: none; }
}

.fold--panel {
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--line);
  border-radius: var(--radius-control);
  background: var(--surface);
  box-shadow: var(--shadow);
}
.fold--panel[open] > .fold__summary { margin-bottom: var(--space-3); }

.live { align-items: center; gap: var(--space-1); color: var(--ember); font-size: 0.85rem; font-weight: 600; }
.live__dot { width: 0.45rem; height: 0.45rem; border-radius: 50%; background: currentColor; }

/* Pools as compact rows */
.pool-rows { display: grid; }

.pool-row {
  position: relative;
  display: grid;
  grid-template-columns: 6px minmax(0, 1fr) auto auto 2.25rem;
  align-items: center;
  gap: 0 var(--space-3);
  padding: var(--space-2) 0;
  border-top: 1px solid var(--line);
  scroll-margin-top: var(--space-6);
}
.pool-row:first-child { border-top: 0; }
.pool-row--depleted > :not(.pool-row__more):not(.pool-row__primary) { opacity: 0.7; }

.pool-row__stripe { align-self: stretch; border-radius: 3px; background: var(--pool-color, var(--muted)); }
.pool-row__main { min-width: 0; display: grid; gap: 2px; }
.pool-row__title { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 var(--space-2); margin: 0; }
.pool-row__name { font-weight: 700; font-size: 1.05rem; }
.pool-row__kind { font-size: 0.8rem; color: var(--dim); }
.pool-row__outcome { font-family: var(--font-display); font-size: 1.05rem; color: var(--pool-color, var(--muted)); }
.pool-row__last { margin: 0; font-size: 0.85rem; color: var(--dim); }
.pool-row__die--dropped { text-decoration: line-through; }

.pool-row__size { display: flex; align-items: center; gap: var(--space-2); }
.pool-row__count { font-family: var(--font-display); font-size: 1.6rem; line-height: 1; min-width: 2.2ch; text-align: right; }
.pool-row .pool__pips { max-width: 8rem; gap: 3px; }
.pool-row .pip { width: 0.6rem; height: 0.6rem; border-radius: 2px; background: var(--pool-color, var(--muted)); }
.pool-row .pip--gone { background: none; box-shadow: inset 0 0 0 1.5px var(--line-strong); }
.pool-row .pool__phase--current { color: var(--pool-color, var(--muted)); }

.pool-row__primary .button_to { margin: 0; }

/* The ⋯ fold-out: its toggle sits at the end of the row, its panel spans it. */
.pool-row__more { grid-column: 1 / -1; }
.pool-row__toggle {
  position: absolute;
  top: var(--space-2);
  right: 0;
  display: grid;
  place-items: center;
  width: 2.25rem;
  height: var(--tap);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  color: var(--muted);
  list-style: none;
  cursor: pointer;
}
.pool-row__toggle::-webkit-details-marker { display: none; }
.pool-row__toggle:hover { background: var(--surface-2); }
.pool-row__toggle:focus-visible { outline: 2px solid var(--focus); outline-offset: 1px; }
.pool-row__more[open] > .pool-row__toggle { background: var(--surface-2); }
.pool-row__panel { display: grid; gap: var(--space-3); padding: var(--space-3) 0 var(--space-1) calc(6px + var(--space-3)); }
.pool-row__panel-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
.pool-row__spacer { flex: 1; }
.pool-row__action-roll { display: grid; gap: var(--space-2); justify-items: start; margin: 0; }
.pool-row__fields { display: flex; flex-wrap: wrap; gap: var(--space-3); }
.pool-row__fields .field__input { width: auto; min-height: var(--tap); }

.badge { padding: 0 var(--space-2); border-radius: 999px; font-size: 0.75rem; font-weight: 600; }
.badge--push { background: var(--messy); color: var(--surface); }
.button--push { border-color: var(--messy); color: var(--messy); background: none; }
.button--danger-text { color: var(--grim); }

.pool-add { margin-top: var(--space-3); padding-top: var(--space-3); border-top: 1px dashed var(--line-strong); }
.pool-add__summary .fold__title { font-family: var(--font-ui); font-size: 1rem; font-weight: 700; color: var(--ember); }
.pool-add[open] > .fold__summary { margin-bottom: var(--space-3); }

@media (max-width: 47.99rem) {
  .pool-row { grid-template-columns: 5px minmax(0, 1fr) auto auto 2.75rem; }
  .pool-row .pool__pips,
  .pool-row__dice-line { display: none; }
  .pool-row__primary .button,
  .pool-row__toggle { min-height: var(--tap); }
  .pool-row__toggle { width: var(--tap); height: var(--tap); }
}

/* Story roll */
.story-roll__fields { display: flex; flex-wrap: wrap; gap: var(--space-3); }
.story-roll__fields .field { flex: 1 1 8rem; }
.story-roll:has(#story_character option[value=""]:not(:checked)) .story-roll__secret { display: none; }

/* Crucibles in the side column */
.crucible-picker__choose { display: flex; gap: var(--space-2); }
.crucible-picker__recent { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-1); margin: 0; }
.crucible-picker__recent[hidden] { display: none; }
.crucible-picker__label { margin-right: var(--space-1); font-size: 0.8rem; color: var(--dim); }
.chip--small { padding: 2px var(--space-3); font-size: 0.85rem; }


/* The GM table's roller: results as tiles, the smash as a band, and the kept
   list as a panel on the right once the card is wide enough. */
.crucible--compact { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-5); }
/* The features crucible inside the character form: tapping a word fills a feature, so keeping
   lines, the combined line and the full-page link (which would leave the form) don't apply. */
.feature-crucible { padding: var(--space-2) var(--space-3); border: 1px solid var(--line-soft); border-radius: var(--radius-control); }
.feature-crucible[open] > .fold__summary { margin-bottom: var(--space-2); }
.feature-crucible .crucible__full,
.feature-crucible [data-crucible-target="keepButton"],
.feature-crucible .roll-result__smash { display: none; }
.crucible__stage { display: grid; gap: var(--space-4); align-content: start; min-width: 0; }
.crucible__full { margin-left: auto; font-size: 0.85rem; }

.crucible--compact .crucible__hint {
  padding: var(--space-5) var(--space-4);
  border: 1px dashed var(--line);
  border-radius: var(--radius-control);
  font-size: 0.9rem;
  text-align: center;
}




.crucible--compact .roll-result__smash {
  margin: 0;
  padding: var(--space-3) var(--space-4);
  background: var(--ember-soft);
  border-left: 3px solid var(--ember);
  border-radius: var(--radius-sm);
  font-size: 1.6rem;
}

.crucible--compact .crucible__grids { padding-top: var(--space-4); border-top: 1px solid var(--line-soft); }
.crucible--compact .crucible__grids .fold__title { font-family: var(--font-ui); font-size: 1rem; font-weight: 600; color: var(--text-soft); }
.crucible--compact .crucible__tables { margin-top: var(--space-4); }

/* ---------- Sessions & scenes ---------- */

.log-entry--marker { --entry-color: var(--text); gap: var(--space-1); background: var(--surface-2); padding-right: var(--space-3); }
.log-marker__title { margin: 0; font-family: var(--font-display); font-size: 1.15rem; }
.log-marker__text { margin: 0; font-size: 0.9rem; color: var(--muted); white-space: pre-line; }
.log-marker__levels { margin: 0; padding-left: 1.2em; font-size: 0.9rem; }

.session-form { max-width: 48rem; }
.session-form__recap { display: grid; gap: var(--space-4); }
.session-form__prompts { padding: var(--space-3); border-radius: var(--radius-sm); background: var(--surface-2); font-size: 0.9rem; }
.session-form__prompts p { margin: var(--space-1) 0 0; white-space: pre-line; }

@media (min-width: 48rem) {
  .session-form__recap { grid-template-columns: minmax(0, 3fr) minmax(0, 2fr); align-items: start; }
}

.log-entry--note { --entry-color: var(--line-strong); padding-block: var(--space-1); }
.log-note__text { color: var(--muted); }
.scene-form__opening { padding: var(--space-3); border: 1px solid var(--line); border-radius: var(--radius-sm); }
.scene-form__opening[open] > .fold__summary { margin-bottom: var(--space-3); }
.scene-form__opening .fold__title { font-family: var(--font-ui); font-size: 1rem; font-weight: 700; }

/* Talent uses: tick boxes on the sheet, a summary and talent pools on the table */
.use-boxes { display: inline-flex; flex-wrap: wrap; gap: 4px; }
.use-box__form { display: contents; }
.use-box {
  width: 1.5rem;
  height: 1.5rem;
  padding: 0;
  border: 1.5px solid var(--line-strong);
  border-radius: 4px;
  background: var(--bg);
}
button.use-box { cursor: pointer; }
button.use-box:hover { border-color: var(--ember); }
button.use-box:focus-visible { outline: 2px solid var(--focus); outline-offset: 1px; }
.use-box--spent { border-color: var(--ember); background: var(--ember); }
.use-note { font-size: 0.85rem; }
/* A use whose boxes are the talent's picks: Hidden Magic's words, burned by name. */
.use-words { display: inline-flex; flex-wrap: wrap; gap: 4px; }
.use-word { min-height: 2rem; padding: 2px 10px; border: 1.5px solid var(--line-strong); border-radius: 999px; background: none; font: inherit; font-size: 0.85rem; color: var(--text); }
button.use-word { cursor: pointer; }
button.use-word:hover { border-color: var(--ember); }
button.use-word:focus-visible { outline: 2px solid var(--focus); outline-offset: 1px; }
.use-word--burned { border-style: dashed; color: var(--dim); text-decoration: line-through; }
.pool-rows--sheet { margin-top: var(--space-2); }

.session-form__scenes { margin: var(--space-1) 0 0; padding-left: 1.3em; }

/* One column of folds, newest first, each holding its log. */
.session-list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-3); }
.session-card { display: grid; gap: var(--space-1); }
.session-card__head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: var(--space-2); }
.session-card__title { margin: 0; font-size: 1.4rem; }
.session-card__date,
.session-card__meta { margin: 0; font-size: 0.9rem; color: var(--dim); }
.session-card__recap { margin: 0; color: var(--muted); }
.session-card--between { border-style: dashed; background: transparent; }
.session-card--between .session-card__title { font-size: 1.15rem; color: var(--muted); }
.session-card--between .roll-log { margin-top: var(--space-2); }
/* Each session and stretch between them is a fold holding its log. */
.session-card__head .session-card__title { margin-right: auto; }
.session-card__head .session-card__date { flex-basis: 100%; }
.session-card__body { display: grid; gap: var(--space-2); margin-top: var(--space-2); }
.session-card__scene { margin: var(--space-2) 0 0; font-size: 1rem; color: var(--muted); }
.session-card__open { justify-self: start; margin-top: var(--space-2); }

/* The Log page split in two: the rolls' folds, and the recaps beside them. */
.session-history__title { margin: 0 0 var(--space-3); font-size: 1.1rem; color: var(--muted); }
.recap-list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-2); }
.recap-card__title { margin: 0; margin-right: auto; font-size: 1.15rem; }
.recap-card__body { display: grid; gap: var(--space-2); margin-top: var(--space-2); }
.recap-card__label { margin: 0; font-size: 12px; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; color: var(--ember); }
.recap-card .session-card__recap { margin: 0; white-space: pre-line; }

.session-page { display: grid; gap: var(--space-4); max-width: 48rem; }
.session-page__text { margin: 0; white-space: pre-line; }
.session-page__edit { font-family: var(--font-ui); font-size: 0.95rem; font-weight: 700; color: var(--ember); }
.session-scene__bookend { margin: 0; font-size: 0.9rem; color: var(--muted); }

.between-scenes { position: relative; }
.between-scenes__toggle { list-style: none; cursor: pointer; padding: var(--space-1) var(--space-2); border: 1px solid var(--line-strong); border-radius: var(--radius-sm); font-size: 0.85rem; font-weight: 700; }
.between-scenes__toggle::-webkit-details-marker { display: none; }
.between-scenes[open] > .between-scenes__toggle { background: var(--surface-2); }
.between-scenes__actions { display: flex; gap: var(--space-2); margin-top: var(--space-2); }
.between-scenes__actions .button_to { margin: 0; }

/* ---------- Night-table shared components ---------- */

.card {
  padding: 18px;
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  background: var(--surface);
}

.card--dashed { border-style: dashed; background: transparent; }

/* Roll result: dice, result word, reason. */
.roll-result { --result-color: var(--muted); display: flex; flex-direction: column; gap: var(--space-2); }
.roll-result--perfect,
.roll-result--critical { --result-color: var(--perfect); }
.roll-result--messy { --result-color: var(--messy); }
.roll-result--grim { --result-color: var(--grim); }
.roll-result--disaster { --result-color: var(--disaster); }

.roll-result__heading { font-size: 0.8rem; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; color: var(--result-color); }
.roll-result__row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-4); }
.roll-result__dice { display: flex; flex-wrap: wrap; gap: var(--space-2); }

.roll-result__word {
  margin-left: auto;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.4rem;
  line-height: 1;
  color: var(--result-color);
}

.roll-result--44 .roll-result__word { margin-left: 0; font-size: 38px; }
.roll-result__reason { margin: 0; font-size: 0.87rem; color: var(--text-soft); }

/* Pool track: a bar segment per die. */
.pool-track { display: flex; gap: 4px; width: 100%; }

.pool-track__segment {
  flex: 1 1 0;
  height: 6px;
  border-radius: 3px;
  background: var(--line);
}

.pool-track__segment--full { background: var(--ember); }
.pool-track--hidden .pool-track__segment--full { background: var(--suspense); }

/* Pips: spark circles, thread and suspense diamonds. */
.pips { display: inline-flex; align-items: center; gap: 4px; vertical-align: middle; }
.pips__more { margin-left: 2px; font-family: var(--font-dice); font-size: 12px; font-weight: 600; color: var(--muted); }

.pip {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  box-shadow: inset 0 0 0 1.5px var(--pip-color);
}

.pip--full { background: var(--pip-color); }
.pips--spark { --pip-color: var(--spark); }
.pips--thread { --pip-color: var(--thread); }
.pips--suspense { --pip-color: var(--suspense); }

.pips--thread .pip,
.pips--suspense .pip { border-radius: 2px; transform: rotate(45deg) scale(0.85); }

/* Stepper: − value + */
.stepper { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-3); }
.stepper__label { flex: 1 0 4rem; color: var(--muted); font-size: 0.87rem; }
.stepper__control { display: inline-flex; align-items: center; gap: var(--space-2); }

.stepper__step {
  width: var(--tap);
  height: var(--tap);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-control);
  background: transparent;
  color: var(--text);
  font-size: 1.1rem;
  cursor: pointer;
}

.stepper__step:hover { background: var(--surface-2); }

.stepper__value {
  width: 3rem;
  min-height: var(--tap);
  border: 0;
  background: transparent;
  color: var(--text);
  font-family: var(--font-dice);
  font-weight: 600;
  text-align: center;
  -moz-appearance: textfield;
}

.stepper__value::-webkit-inner-spin-button,
.stepper__value::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }

.stepper__suffix { color: var(--dim); font-size: 0.87rem; }

/* ---------- Character view ---------- */

.site-main:has(.play-view) { max-width: 96rem; }

.sheet { display: flex; flex-direction: column; gap: 20px; }

.card__title { margin: 0 0 var(--space-3); font-size: 1.25rem; }

/* Identity band */
.identity { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-4) var(--space-5); }

.monogram {
  display: grid;
  place-items: center;
  flex: none;
  border-radius: var(--radius-control);
  background: var(--ember-soft);
  color: var(--link);
  font-family: var(--font-display);
  font-weight: 700;
}

.monogram--76 { width: 76px; height: 76px; border-radius: 18px; font-size: 40px; }

.identity__who { flex: 1 1 280px; min-width: 0; }
.identity__name { margin: 0; font-size: clamp(2rem, 6vw, 2.5rem); line-height: 1.05; }
.identity__line { margin: 2px 0 0; color: var(--muted); }

.identity__meta { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3) 20px; }
/* The owner's spark, thread, XP and Edit sheet: a row of their own, spread evenly across it. */
.identity__meta--controls { flex-basis: 100%; justify-content: space-between; gap: var(--space-2); }

.meter { display: grid; gap: 4px; }
.meter__label { font-size: 11px; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; color: var(--dim); }
.meter__count { font-family: var(--font-dice); font-weight: 600; }
.meter__of { color: var(--dim); }
.identity .pip { width: 16px; height: 16px; }

/* Stat cards; the one rolling spans two columns. */
.stat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 12px; }

.stat-card {
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-width: 0;
  padding: 16px;
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  background: var(--surface);
}

.stat-card__head { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: var(--space-2); }
.stat-card__name { flex: 1; min-width: 0; margin: 0; font-size: 1.4rem; overflow-wrap: anywhere; }
.stat-card__dice { font-family: var(--font-dice); font-weight: 600; font-size: 28px; line-height: 1; }
.stat-card__desc { margin: 0; font-size: 0.87rem; color: var(--dim); }

.tag--marked { margin: 0; border: 0; border-radius: var(--radius-sm); background: var(--grim-bg); color: var(--grim); align-self: center; }
/* The head: the name on top, then Mark / Marked on the left and the dice on
   the right. Mark is quiet (dashed, dim) until it's on, then red. The owner
   and the GM can toggle it; everyone else sees the red tag when it's marked. */
.stat-card__head > .stat-card__name { grid-column: 1 / -1; }
.stat-card__head > :is(.stat-card__mark-form, .tag--marked) { grid-row: 2; grid-column: 1; justify-self: start; }
.stat-card__head > .stat-card__dice { grid-row: 2; grid-column: 2; justify-self: end; }
.stat-card__mark-form { margin: 0; }
.stat-card .stat-card__mark { min-width: 5.5rem; padding: 0 10px; border-style: dashed; border-radius: var(--radius-sm); color: var(--dim); font-size: 0.8rem; }
.stat-card .stat-card__mark[aria-pressed="true"] { border-style: solid; border-color: var(--grim); background: var(--grim-bg); color: var(--grim); }

.stat-roll { margin-top: auto; }
.stat-roll__toggle { width: 100%; }

/* The roll setup, in a modal: wide, its sections two by two (dice and thorns
   beside where the extra dice come from, spark beside panache, talents beside
   assists); on a phone, one column filling the screen. */
.roll-dialog {
  width: min(46rem, calc(100% - 32px));
  max-height: calc(100dvh - 32px);
  padding: 16px 20px 20px;
  border: 0;
  border-radius: var(--radius-card);
  background: var(--surface);
  color: var(--text);
  box-shadow: inset 0 0 0 1px var(--line-strong), 0 12px 32px -8px rgb(0 0 0 / 0.85);
  overflow-y: auto;
}
.roll-dialog[open] { display: flex; flex-direction: column; gap: 14px; animation: roll-toast-in 180ms ease-out; }
.roll-dialog::backdrop { background: rgb(10 9 7 / 0.7); }
@media (prefers-reduced-motion: reduce) { .roll-dialog[open] { animation: none; } }
.roll-dialog__head { display: flex; align-items: baseline; gap: var(--space-3); padding-right: var(--tap); }
.roll-dialog__title { margin: 0; font-family: var(--font-display); font-size: 1.5rem; }
.roll-dialog__dice { font-family: var(--font-dice); color: var(--text-soft); }
.roll-dialog__close { position: absolute; top: 8px; right: 8px; }
.roll-dialog .roll-dialog__form { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr)); gap: 16px 24px; align-items: start; }
.roll-dialog .roll-dialog__form > .stat-roll__actions,
.roll-dialog .roll-dialog__form > .stat-roll__secret { grid-column: 1 / -1; }
@media (max-width: 40rem) {
  .roll-dialog { width: calc(100% - 16px); max-height: calc(100dvh - 16px); padding: 14px 16px 16px; }
}

.stat-roll__form { display: flex; flex-direction: column; gap: 12px; }
.stat-roll__steppers { display: flex; flex-wrap: wrap; gap: 10px 20px; }
.stat-roll__steppers .stepper__label { flex: 0 0 3.5rem; }
.stat-roll__steppers .stepper:nth-child(2) .stepper__value { color: var(--grim); }
.stat-roll__note { margin: 0; font-size: 0.87rem; color: var(--grim); }
.stat-roll__group { display: grid; gap: var(--space-2); margin: 0; padding: 0; border: 0; min-width: 0; }
.stat-roll__label { font-size: 0.87rem; color: var(--muted); }
.stat-roll__assists { display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-4); }
.stat-roll__actions { display: flex; gap: var(--space-2); }
.stat-roll__go { flex: 1; min-height: 48px; font-size: 1rem; }

/* The sheet's top: the stats across, then harm and vex in one card with
   conditions beside it. Narrow, the stats go two by two and the cards stack. */
.sheet { container: sheet / inline-size; }
.sheet__top { display: flex; flex-direction: column; gap: 12px; }
/* Harm, vex and conditions: on a phone, three cards one under another; with
   room, one card, harm with vex under it and conditions beside them. */
.damage-card { display: grid; gap: 12px; margin-top: 12px; }
.damage-card > div { display: flex; flex-direction: column; gap: 12px; padding: 18px; border: 1px solid var(--line); border-radius: var(--radius-card); background: var(--surface); }
.damage-card .card__title { margin: 0; }
.damage-card .button_to { margin: 0; }
.sheet__top .stat-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }

@container sheet (min-width: 40rem) {
  .damage-card { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); grid-template-areas: "harm conditions" "vex conditions"; gap: 0; padding: 18px; border: 1px solid var(--line); border-radius: var(--radius-card); background: var(--surface); }
  .damage-card > div { padding: 0; border: 0; border-radius: 0; background: none; }
  .damage-card > .damage-card__harm { grid-area: harm; padding: 0 18px 18px 0; }
  .damage-card > .damage-card__vex { grid-area: vex; padding: 18px 18px 0 0; border-top: 1px solid var(--line-soft); }
  .damage-card > .damage-card__conditions { grid-area: conditions; padding-left: 18px; border-left: 1px solid var(--line-soft); }
}
@container sheet (min-width: 48rem) {
  .sheet__top .stat-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* What a harm or vex toggle means, on hover or focus (title is slow, and
   absent on touch). */
[data-tip] { position: relative; }
.harm-toggle[data-tip]:hover::after,
.harm-toggle[data-tip]:focus-visible::after,
.campaign-hero__rule[data-tip]:hover::after,
.campaign-hero__rule[data-tip]:focus-visible::after {
  content: attr(data-tip); position: absolute; left: 50%; bottom: calc(100% + 6px); z-index: 20; width: max-content; max-width: min(16rem, 70vw);
  padding: 6px 10px; transform: translateX(-50%); border: 1px solid var(--line-strong); border-radius: var(--radius-sm); background: var(--surface);
  box-shadow: 0 6px 18px rgb(0 0 0 / 0.4); font-size: 0.8rem; font-weight: 500; line-height: 1.35; color: var(--text); text-align: center; white-space: normal; pointer-events: none;
}

/* The roll you just made, of any kind, as a toast at the top of the toast
   stack: grim-red for grim and disaster. toast_controller.js hides it after
   10 seconds. */
.roll-toast {
  display: flex;
  flex-direction: column;
  gap: 12px;
  max-height: calc(100vh - 32px);
  pointer-events: auto;
  overflow-y: auto;
  padding: 14px 18px 18px;
  border-radius: var(--radius-card);
  background: var(--surface);
  box-shadow: inset 0 0 0 1px var(--line-strong), 0 12px 32px -8px rgb(0 0 0 / 0.85);
  animation: toast-in 180ms ease-out;
}

.roll-toast[hidden] { display: none; }

@keyframes roll-toast-in { from { opacity: 0; transform: translateY(12px); } }
@media (prefers-reduced-motion: reduce) { .roll-toast { animation: none; } }

.roll-toast--grim,
.roll-toast--disaster { background: color-mix(in srgb, var(--grim-bg) 92%, black); box-shadow: inset 0 0 0 1px var(--grim-line), 0 12px 32px -8px rgb(0 0 0 / 0.85); }
.roll-toast--perfect,
.roll-toast--critical { box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--perfect) 55%, transparent), 0 12px 32px -8px rgb(0 0 0 / 0.85); }
.roll-toast--messy { box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--messy) 55%, transparent), 0 12px 32px -8px rgb(0 0 0 / 0.85); }

.roll-toast__head { display: flex; align-items: center; gap: var(--space-2); margin-right: -10px; }
.roll-toast__title { flex: 1; margin: 0; font-family: var(--font-ui); font-size: 12px; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; color: var(--muted); }
.roll-toast--grim .roll-toast__title,
.roll-toast--disaster .roll-toast__title { color: var(--grim); }
.roll-toast__close { display: grid; place-items: center; width: var(--tap); height: var(--tap); padding: 0; border: 0; border-radius: var(--radius-control); background: none; color: var(--muted); cursor: pointer; }
.roll-toast__close:hover { background: var(--surface-2); color: var(--text); }
.roll-toast__setup { margin: 0; font-size: 0.87rem; color: var(--dim); }
.roll-toast__question { margin: 0; font-family: var(--font-display); font-style: italic; font-size: 17px; line-height: 1.35; }
.roll-toast__result { margin: 0; font-family: var(--font-display); font-size: 1.3rem; font-weight: 700; }
.roll-toast__pool { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-3); }
.roll-toast__pool .feed-pool__change { font-size: 1.1rem; }
.roll-toast__note { margin: 0; font-size: 0.87rem; color: var(--text-soft); }
.roll-toast__note--spark { color: var(--spark); }
.roll-toast .critical { margin: 0; }

/* Roll call (roll_calls/_call): a story roll, montage or quarrel waiting on its
   players, as a modal. Hidden, it leaves a pill above the roll toast's corner. */
.roll-call__dialog,
.confirm,
.frame-modal {
  width: min(32rem, calc(100% - 32px));
  max-height: calc(100vh - 32px);
  padding: 14px 18px 18px;
  border: 0;
  border-radius: var(--radius-card);
  background: var(--surface);
  color: var(--text);
  box-shadow: inset 0 0 0 1px var(--line-strong), 0 12px 32px -8px rgb(0 0 0 / 0.85);
}

.roll-call__dialog[open],
.confirm[open],
.frame-modal[open] { display: flex; flex-direction: column; gap: 14px; animation: roll-toast-in 180ms ease-out; }
.roll-call__dialog::backdrop,
.confirm::backdrop,
.frame-modal::backdrop { background: rgb(10 9 7 / 0.7); }
.roll-call__dialog--grim { background: color-mix(in srgb, var(--grim-bg) 92%, black); box-shadow: inset 0 0 0 1px var(--grim-line), 0 12px 32px -8px rgb(0 0 0 / 0.85); }
@media (prefers-reduced-motion: reduce) { .roll-call__dialog[open], .confirm[open], .frame-modal[open] { animation: none; } }

.roll-call__head { display: flex; align-items: flex-start; gap: var(--space-2); margin-right: -10px; }
.roll-call__head > div { flex: 1; }
.roll-call__title { margin: 0; font-family: var(--font-display); font-size: 1.4rem; font-weight: 700; }
.roll-call__by { margin: 0; font-size: 0.87rem; color: var(--dim); }
.roll-call__close { display: grid; place-items: center; width: var(--tap); height: var(--tap); padding: 0; border: 0; border-radius: var(--radius-control); background: none; color: var(--muted); cursor: pointer; }
.roll-call__close:hover { background: var(--surface-2); color: var(--text); }
.roll-call__question { margin: 0; font-family: var(--font-display); font-style: italic; font-size: 17px; line-height: 1.35; }
.roll-call__hint { margin: 0; font-size: 0.87rem; color: var(--muted); }
.roll-call__error { margin: 0; padding: var(--space-2) var(--space-3); border-radius: var(--radius-control); background: var(--grim-bg); color: var(--grim); }

.roll-call__seats { display: grid; gap: var(--space-2); margin: 0; padding: 0; list-style: none; }
.roll-call__seat { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-2) var(--space-3); padding: 10px 12px; border: 1px solid var(--line); border-radius: var(--radius-control); }
.roll-call__seat--rolled { background: var(--surface-2); }
.roll-call__who { display: grid; min-width: 0; }
.roll-call__name { font-family: var(--font-display); font-size: 1.1rem; }
.roll-call__meta { color: var(--dim); font-size: 0.85rem; }
.roll-call__waiting { color: var(--muted); font-size: 0.9rem; font-style: italic; }
.roll-call__rolled { display: grid; justify-items: end; gap: 2px; }
.roll-call__dice { display: flex; flex-wrap: wrap; gap: 6px; }
.roll-call__roll { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: var(--space-2); flex: 1 1 14rem; }
.roll-call__roll .button { flex: 0 0 auto; }
.roll-call__spark { flex: 1 1 12rem; }
.roll-call__result { display: grid; gap: 12px; }
.roll-call__actions { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: var(--space-2); }
.roll-call__actions .button_to { margin: 0; }

.roll-call__pill {
  position: fixed;
  z-index: 31;
  left: 16px;
  bottom: 16px;
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: var(--tap);
  padding: 0 16px;
  border: 1px solid var(--ember);
  border-radius: 999px;
  background: var(--surface);
  color: var(--text);
  font: 600 0.9rem var(--font-ui);
  box-shadow: 0 12px 32px -8px rgb(0 0 0 / 0.85);
  cursor: pointer;
}

.roll-call__pill[hidden] { display: none; }
.roll-call__pill .icon { color: var(--ember); }
.roll-call__pill:hover { background: var(--surface-2); }

/* Confirmations (shared/_confirm, confirm_controller.js): in place of the
   browser's confirm() for data-turbo-confirm, in the roll call's dialog look.
   The confirm button says what you clicked, red for deleting or removing. */
.confirm { width: min(26rem, calc(100% - 32px)); }
.confirm__close { position: absolute; top: 10px; right: 10px; }

/* A page in a modal (shared/_frame_modal): its header and form, without the
   page's campaign link or the form's own panel. */
.frame-modal { width: min(36rem, calc(100% - 32px)); overflow-y: auto; }
.frame-modal__close { position: absolute; top: 10px; right: 10px; }
.frame-modal .page-header { margin: 0 var(--tap) var(--space-3) 0; }
.frame-modal .page-header .eyebrow { display: none; }
.frame-modal .page-header h1 { margin: 0 0 var(--space-2); font-size: 1.6rem; }
.frame-modal .panel { padding: 0; border: 0; background: none; box-shadow: none; }
.confirm__message { margin: 0 var(--tap) 0 0; font-family: var(--font-display); font-size: 1.25rem; font-weight: 700; line-height: 1.3; }
.confirm__actions { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: var(--space-2); }

/* Toasts (shared/_toasts) at the top center, stacking: the roll you just made,
   news from a notice flash (neutral), and failures (grim-red). Pages have no
   banners. */
.toasts {
  position: fixed;
  z-index: 40;
  top: 16px;
  left: 50%;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  width: min(28rem, calc(100% - 32px));
  transform: translateX(-50%);
  pointer-events: none;
}

.toast {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: 4px 4px 4px 16px;
  border-radius: var(--radius-card);
  background: color-mix(in srgb, var(--grim-bg) 92%, black);
  box-shadow: inset 0 0 0 1px var(--grim-line), 0 12px 32px -8px rgb(0 0 0 / 0.85);
  pointer-events: auto;
  animation: toast-in 180ms ease-out;
}

.toast[hidden] { display: none; }
.toast--notice { background: var(--surface); box-shadow: inset 0 0 0 1px var(--line-strong), 0 12px 32px -8px rgb(0 0 0 / 0.85); }
.toast--notice .toast__close { color: var(--muted); }
@keyframes toast-in { from { opacity: 0; transform: translateY(-12px); } }
@media (prefers-reduced-motion: reduce) { .toast { animation: none; } }

.toast__message { flex: 1; margin: 0; padding: 10px 0; color: var(--text); }
.toast__close { display: grid; flex: none; place-items: center; width: var(--tap); height: var(--tap); padding: 0; border: 0; border-radius: var(--radius-control); background: none; color: var(--grim); cursor: pointer; }
.toast__close:hover { background: var(--surface-2); color: var(--text); }

/* Harm */
.harm { display: flex; flex-direction: column; gap: 12px; }
.harm .card__title { margin: 0; }
.harm .button_to { margin: 0; }
.harm__toggles { display: grid; grid-template-columns: repeat(auto-fit, minmax(6.5rem, 1fr)); gap: var(--space-2); }
/* A desperate character's quiet way out: the hint, then the button, which drops whole onto its own line when the card is narrow. */
.harm__end { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-1) var(--space-2); margin-top: var(--space-2); padding-top: var(--space-2); border-top: 1px solid var(--line-soft); }
.harm__end-text { margin: 0; font-size: 0.87rem; color: var(--muted); text-wrap: balance; }
.harm__end .button { white-space: nowrap; }
/* Filled harm-red, not the usual red outline: this one ends a story. */
.harm__end .button--danger { background: var(--harm); border-color: var(--grim-ring); color: var(--text); font-family: var(--font-display); font-style: italic; }
.harm__end .button--danger:hover { background: var(--grim-ring); color: var(--text); }

.harm-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: var(--tap);
  padding: 0 var(--space-3);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-control);
  background: transparent;
  color: var(--muted);
  font-weight: 600;
  cursor: pointer;
}

.harm-toggle[aria-pressed="true"],
.harm-toggle--on { border-color: var(--harm); background: var(--harm); color: var(--text); }
span.harm-toggle { cursor: default; }
span.harm-toggle:not(.harm-toggle--on) { color: var(--dim); border-style: dashed; }


.mark-toggle {
  min-height: var(--tap);
  padding: 0 var(--space-3);
  border: 1px solid var(--line);
  border-radius: 999px;
  background: transparent;
  color: var(--muted);
  font-size: 0.87rem;
  font-weight: 600;
  cursor: pointer;
}

.mark-toggle[aria-pressed="true"],
.mark-toggle--on { border-color: var(--grim-line); background: var(--grim-bg); color: var(--grim); }
span.mark-toggle { display: inline-flex; align-items: center; cursor: default; }

.conditions { display: grid; gap: var(--space-2); margin: 0; padding: 0; list-style: none; }

.condition {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) 10px;
  padding: var(--space-1) var(--space-1) var(--space-1) 12px;
  border-radius: var(--radius-control);
  background: var(--bg);
}

.condition__name { flex: 1; min-width: 8rem; }
.condition__size { font-family: var(--font-dice); font-weight: 600; color: var(--link); }

.condition-form { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); margin: 0; }
.condition-form .field__input { flex: 1 1 12rem; min-width: 0; min-height: var(--tap); }
/* [4]d [poisoned]: the dice count is optional, for a condition that's a pool. */
.condition-form__dice { display: inline-flex; align-items: center; gap: 4px; }
.condition-form .condition-form__count { flex: 0 0 3.5rem; width: 3.5rem; padding-inline: 6px; text-align: center; font-family: var(--font-dice); font-weight: 600; }
.condition-form__d { font-family: var(--font-dice); font-weight: 600; color: var(--muted); }
.harm__changed { margin: 0; font-size: 12px; color: var(--dim); }

/* Who they are */
.facts { display: flex; flex-direction: column; gap: 10px; margin: 0; }
.facts dt { font-size: 12px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--dim); }
.facts dd { margin: 0; }
.facts__list { display: flex; flex-direction: column; gap: 2px; margin: 0; padding-left: 1.1rem; }
.facts__list li::marker { color: var(--dim); }
.facts__not { list-style: none; margin: 2px 0 0 -1.1rem; padding-left: var(--space-2); border-left: 2px solid var(--not-line); color: var(--muted); }
.facts__but { font-size: 0.87rem; color: var(--dim); }

/* Who they are: a column, or a few side by side when the sheet is wide. */
@container sheet (min-width: 40rem) {
  .facts { display: grid; grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr)); gap: 12px 20px; }
}

/* Talents and arcs */
.talents__head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-2); margin-bottom: var(--space-3); }
.talents__head .card__title { margin: 0; }

/* The core talent on its own, then the rest, one under another across the
   card. Each folds to its name and summary; opening one shows the rest. */
.talent-list { display: flex; flex-direction: column; gap: var(--space-2); margin-bottom: var(--space-3); }
.talent-card--core { margin-bottom: var(--space-3); }
.talent-card { position: relative; display: flex; flex-direction: column; gap: var(--space-1); padding: 14px 16px; border: 1px solid var(--line); border-radius: var(--radius-control); background: var(--surface-2); }
.talent-card--core { padding: 18px 20px; border-color: color-mix(in srgb, var(--ember) 45%, var(--line)); background: linear-gradient(135deg, var(--ember-soft), var(--surface-2) 60%); }
.talent-card--eldritch { border-color: var(--suspense-line); }
.talent-card--skinned { box-shadow: inset 3px 0 0 var(--spark); }
.talent-card__head { display: flex; align-items: flex-start; gap: var(--space-2); }
/* The ⋯ menu sits just left of the chevron, which takes the far right. */
.talent-card__fold > summary { list-style: none; cursor: pointer; }
.talent-card__fold > summary::-webkit-details-marker { display: none; }
/* Descendant selectors: Herb's dev debug mode wraps the icon in a span. */
.talent-card__fold > summary .icon--chevron { flex: none; margin-top: 4px; color: var(--dim); transition: transform 0.2s ease; }
.talent-card__fold[open] > summary .icon--chevron { transform: rotate(180deg); }
.talent-card__fold > summary:hover .talent-card__name { color: var(--ember); }
.talent-card__titles { display: flex; flex: 1; flex-direction: column; min-width: 0; padding-right: 3.5rem; }
.talent-card__session { display: inline-flex; align-items: center; gap: 4px; align-self: flex-start; margin-top: var(--space-1); padding: 1px 8px; border: 1px dashed var(--line-strong); border-radius: 999px; font-size: 11px; font-weight: 600; letter-spacing: 0.04em; color: var(--dim); }
.talent-card__between { flex-basis: 100%; margin: 0; }
.talent-card__body { display: flex; flex-direction: column; gap: var(--space-1); margin-top: var(--space-2); }
/* Clear of the chevron (18px plus a gap from the card's edge) and inside the card. */
.talent-card > .talent-card__more-menu { position: absolute; top: 4px; right: 44px; margin: 0; }
.talent-card--core > .talent-card__more-menu { top: 8px; right: 48px; }
.talent-card__name { flex: 1; margin: 0; font-family: var(--font-display); font-size: 1.2rem; font-weight: 700; line-height: 1.25; }
.talent-card--core .talent-card__name { font-size: 1.5rem; }
.talent-card__source { margin: 0; font-size: 12px; color: var(--dim); }
.talent-card--core .talent-card__source { color: var(--ember); font-weight: 600; letter-spacing: 0.04em; }
.talent-card__summary { margin: var(--space-1) 0 0; color: var(--text-soft); }
.talent-card--core .talent-card__summary { font-size: 1.05rem; max-width: 46rem; }
.talent-card__growth { margin: 0; font-size: 0.9rem; color: var(--muted); }
.talent-card__label { margin: var(--space-2) 0 0; font-size: 11px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--dim); }
.talent-card__growth .talent-card__label { margin: 0 var(--space-1) 0 0; color: var(--ember); }
.talent-card__aka { margin: 0; font-size: 12px; color: var(--dim); }
.talent-card__text { margin: 0; font-size: 0.93rem; color: var(--muted); }
.talent-card__text--own { color: var(--text); }
.talent-card__note { margin: var(--space-1) 0 0; padding-left: var(--space-3); border-left: 3px solid var(--line-strong); font-size: 0.85rem; font-style: italic; color: var(--dim); }

/* What a talent is: small badges by kind. */
.talent-kinds { display: flex; flex-wrap: wrap; gap: 4px; margin: 2px 0 0; padding: 0; list-style: none; }
.talent-kind { padding: 1px 8px; border: 1px solid currentColor; border-radius: 999px; font-size: 11px; font-weight: 600; letter-spacing: 0.04em; color: var(--dim); }
.talent-kind--spell { color: var(--suspense-text); }
.talent-kind--roll { color: var(--ember); }
.talent-kind--pool { color: var(--thread); }
.talent-kind--uses { color: var(--spark); }
.talent-kind--push { color: var(--grim); }

/* What a talent gives: tick boxes, talent pools, extra thread */
.talent-card__uses { display: flex; flex-direction: column; gap: var(--space-2); margin-top: var(--space-2); padding-top: var(--space-2); border-top: 1px solid var(--line-soft); }
.talent-card__uses .pool-rows--sheet { margin: 0; }
/* A talent pool on its card: the dice, Roll and ⋯ on top, then its name,
   kind and last roll underneath. */
.pool-rows--sheet .pool-row { grid-template-columns: 6px auto minmax(0, 1fr) auto 2.25rem; row-gap: var(--space-1); }
.pool-rows--sheet .pool-row__stripe { grid-row: 1 / 3; grid-column: 1; }
.pool-rows--sheet .pool-row__size { grid-row: 1; grid-column: 2; }
.pool-rows--sheet .pool-row__count { text-align: left; }
.pool-rows--sheet .pool-row .pool__pips { display: flex; }
.pool-rows--sheet .pool-row__primary { grid-row: 1; grid-column: 4; }
.pool-rows--sheet .pool-row__main { grid-row: 2; grid-column: 2 / -1; }
.pool-rows--sheet .pool-row__more { grid-row: 3; grid-column: 1 / -1; }
.talent-card__chip { align-self: flex-start; margin: 0; padding: 2px 10px; border: 1px solid var(--line-strong); border-radius: 999px; font-size: 0.8rem; color: var(--thread); }
.talent-card__pool-preview { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-1) var(--space-2); opacity: 0.8; }
.talent-card__pool-preview .pool-track { flex: 0 1 10rem; }
.use-tracker { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-1) var(--space-2); }
.use-tracker__name { font-size: 0.9rem; font-weight: 600; }
.use-tracker__resets { font-size: 12px; color: var(--dim); }

/* What you can do with it: its rolls and Push yourself. */
.talent-card__actions { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-top: var(--space-2); }
.talent-card__action { margin: 0; }
.talent-card__roll { gap: 6px; height: auto; min-height: var(--tap); text-align: left; }
.talent-card__roll small { color: var(--dim); font-weight: 400; }
.talent-card__push { position: relative; }
.talent-card__push-toggle { list-style: none; border-color: var(--grim-line); color: var(--grim); }
.talent-card__push-toggle::-webkit-details-marker { display: none; }
.talent-card__push-toggle small { color: var(--dim); font-weight: 400; }
.talent-card__push-stat { display: flex; justify-content: space-between; width: 100%; }
.talent-card__push-stat small { color: var(--dim); font-weight: 400; }
.talent-card__push-stat--harm small { color: var(--grim); }

/* The ⋯ menu (re-skin, Remove) and the push menu float like a pool card's. */
.talent-card__more-menu { position: relative; margin: -8px -10px 0 0; }
.talent-card__toggle { width: var(--tap); padding: 0; list-style: none; color: var(--dim); }
.talent-card__toggle::-webkit-details-marker { display: none; }
.talent-card__menu { position: absolute; z-index: 15; right: 0; top: calc(100% + 4px); display: grid; gap: var(--space-2); width: min(22rem, calc(100vw - 2rem)); padding: var(--space-3); border: 1px solid var(--line); border-radius: var(--radius-control); background: var(--surface); box-shadow: var(--shadow); }
.talent-card__menu--push { left: 0; right: auto; width: min(16rem, calc(100vw - 2rem)); }
.talent-card__menu .field__hint { margin: 0; }
.talent-card__menu .button_to, .talent-card__menu .button_to .button { width: 100%; margin: 0; }
.talent-card__menu-title { margin: 0; font-weight: 600; }
.talent-skin__form .field__input { width: 100%; }

/* The book's text, folded away at the foot of the card. */
.talent-card__more { margin-top: auto; padding-top: var(--space-2); }
.talent-card__more > .fold__summary { min-height: 2rem; font-size: 0.85rem; font-weight: 600; color: var(--dim); }
.talent-card__more[open] > .fold__summary { margin-bottom: var(--space-1); }
.talent-card__more > .talent-card__text + .talent-card__text { margin-top: var(--space-2); }

.talent-slot {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: var(--tap);
  margin-bottom: var(--space-3);
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius-control);
  color: var(--muted);
  font-weight: 600;
  text-decoration: none;
}

.talent-slot:hover { color: var(--text); border-color: var(--muted); }
/* A warlock's Eldritch Talents, under their own talents. */
.eldritch { display: grid; gap: var(--space-2); margin: var(--space-4) 0 var(--space-3); padding-top: var(--space-4); border-top: 1px solid var(--line-soft); }
.eldritch .talents__head, .eldritch .field__hint, .eldritch .talent-slot { margin: 0; }
.eldritch__title { margin: 0; font-size: 1.1rem; }
.eldritch__count { margin-left: var(--space-2); font-family: var(--font-dice); font-size: 0.85rem; color: var(--dim); }

/* More talents than the level allows (from before the limit, or a lowered level). */
.talent-over { margin: 0 0 var(--space-3); padding: var(--space-2) var(--space-3); border: 1px solid var(--grim-line); border-radius: var(--radius-control); background: var(--grim-bg); font-size: 0.9rem; }

.facts__arc { font-family: var(--font-display); font-style: italic; font-size: 17px; }

.sheet-notes { margin-top: var(--space-3); color: var(--text-soft); }
.sheet-notes__title { margin: 0 0 var(--space-1); font-family: var(--font-ui); font-size: 0.87rem; font-weight: 600; color: var(--dim); }
.sheet-notes p { margin: 0 0 var(--space-2); }

/* The table rail */
.table-rail {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--line);
  border-radius: 16px;
  background: var(--rail);
  overflow: hidden;
}

/* Wide screens: the rail sticks beside the page at the viewport's height, and
   the feed takes what's left, so the composer is always in view. */
@media (min-width: 60rem) {
  .fluid__rail.table-rail { position: sticky; top: var(--space-4); height: calc(100vh - 2 * var(--space-4)); }
  .fluid__rail.table-rail .feed,
  .gm-view__side .table-rail .feed { flex: 1 1 auto; min-height: 0; }
  .fluid__rail.table-rail .feed__scroller,
  .gm-view__side .table-rail .feed__scroller { flex: 1 1 auto; min-height: 10rem; max-height: none; }
  /* The GM table: the chat at a set height (85vh, never under 38rem), and Kept crucibles under
     it at its full length; the page scrolls to reach it, so this column doesn't stick. */
  .gm-view__side > .table-rail { height: max(38rem, 85vh); }
}
.gm-view__side { display: flex; flex-direction: column; gap: var(--space-3); }

.table-rail__head { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-3); padding: 12px 14px; border-bottom: 1px solid var(--line-soft); }
.table-rail__title { flex: 1; margin: 0; font-size: 19px; }

.table-rail__summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: var(--tap);
  font-weight: 600;
  cursor: pointer;
  list-style: none;
}

.table-rail__summary::-webkit-details-marker { display: none; }
.play-view__scroll { max-height: 26rem; overflow-y: auto; }

.suspense-meter { display: inline-flex; align-items: center; gap: var(--space-2); font-size: 13px; font-weight: 600; color: var(--suspense-text); }
.suspense-meter__value { font-family: var(--font-dice); font-weight: 600; }

/* ---------- GM table (campaigns/tables#show) ---------- */

.site-main:has(.gm-view) { max-width: 96rem; }
.gm-view__main { display: flex; flex-direction: column; gap: var(--space-5); }

/* Scene header and suspense */
.scene-bar { display: flex; flex-wrap: wrap; align-items: flex-start; gap: var(--space-4) var(--space-5); }
.scene-bar__scene { flex: 999 1 420px; min-width: 0; }
.scene-bar__status { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); margin: 0; font-size: 0.87rem; color: var(--muted); }
.scene-bar__title { margin: var(--space-1) 0 var(--space-3); font-size: clamp(2rem, 5vw, 2.5rem); }
.scene-bar__actions { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-2); }
.scene-bar__actions .button_to { margin: 0; }
.scene-bar .between-scenes { position: relative; }
.scene-bar .between-scenes__toggle { list-style: none; }
.scene-bar .between-scenes__toggle::-webkit-details-marker { display: none; }

.scene-bar .between-scenes__actions {
  position: absolute;
  z-index: 15;
  right: 0;
  top: calc(100% + 4px);
  display: flex;
  gap: var(--space-2);
  padding: var(--space-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-control);
  background: var(--surface);
  box-shadow: var(--shadow);
}

/* Tallies: a tinted [ − | count | + ] card (shared/_tally; not the /roll page's .counter steppers). Suspense in
   the GM's scene bar; spark, thread and XP on the owner's sheet. */
.tally {
  --tally: var(--text);
  --tally-text: var(--muted);
  --tally-bg: var(--surface);
  --tally-line: var(--line-strong);
  display: inline-flex;
  align-items: stretch;
  min-height: var(--tap);
  border: 1px solid var(--tally-line);
  border-radius: var(--radius-control);
  background: var(--tally-bg);
  color: var(--tally-text);
}
.tally--suspense { --tally: var(--suspense); --tally-text: var(--suspense-text); --tally-bg: var(--suspense-bg); --tally-line: var(--suspense-line); }
.tally--spark { --tally: var(--spark); --tally-text: var(--spark); --tally-bg: color-mix(in srgb, var(--spark) 8%, var(--surface)); --tally-line: color-mix(in srgb, var(--spark) 35%, var(--surface)); }
.tally--thread { --tally: var(--thread); --tally-text: var(--thread); --tally-bg: color-mix(in srgb, var(--thread) 8%, var(--surface)); --tally-line: color-mix(in srgb, var(--thread) 35%, var(--surface)); }
.tally .button_to { display: flex; margin: 0; }
.tally__step {
  min-width: var(--tap);
  border: 0;
  background: none;
  color: inherit;
  font: 600 18px/1 var(--font-dice);
  cursor: pointer;
}
.tally .button_to:first-child .tally__step { border-radius: var(--radius-control) 0 0 var(--radius-control); }
.tally .button_to:last-child .tally__step { border-radius: 0 var(--radius-control) var(--radius-control) 0; }
.tally__step:hover:not(:disabled) { background: color-mix(in srgb, var(--tally) 14%, transparent); }
.tally__step:disabled { color: var(--dim); cursor: not-allowed; }
/* One line: "1 of 2 spark", "4 suspense left". */
.tally__count {
  display: flex;
  align-items: center;
  gap: 0.35em;
  padding: 0 var(--space-3);
  border-inline: 1px solid var(--tally-line);
  font-size: 0.87rem;
  white-space: nowrap;
}
.tally__value { font-family: var(--font-dice); font-weight: 600; font-size: 18px; line-height: 1; color: var(--tally); }

/* Sections */
.gm-section { display: flex; flex-direction: column; gap: var(--space-3); }
.gm-section__head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-2); }
.gm-section__title { margin: 0; font-family: var(--font-display); font-weight: 700; font-size: 1.4rem; }

/* Party */
.party-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 230px), 1fr)); gap: 12px; }

.party-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  min-width: 0;
  padding: 16px;
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  background: var(--surface);
}

.party-card--empty { border-style: dashed; background: transparent; }
.party-card__head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 0 var(--space-2); }
.party-card__name { font-family: var(--font-display); font-weight: 700; font-size: 1.2rem; color: var(--text); text-decoration: none; }
a.party-card__name:hover { color: var(--link); text-decoration: underline; }
.party-card--empty .party-card__name { color: var(--muted); }
.party-card__meta { font-size: 0.85rem; color: var(--dim); }
.party-card__harm { margin: 0; font-size: 0.9rem; color: var(--grim); }
.party-card__harm--none { color: var(--muted); }
.party-card__currency,
.party-card__uses { margin: 0; font-size: 0.9rem; color: var(--text-soft); }
.party-card__picks { margin: 0; font-size: 0.9rem; color: var(--ember); }
.party-card__goals { margin: 0; font-size: 0.9rem; color: var(--muted); }
.party-card__pools { display: grid; gap: var(--space-1); margin: 0; padding: 0; list-style: none; }
.party-card .button_to { margin: 0; }

/* Pools as cards */
.pool-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 300px), 1fr)); gap: 12px; }

.pool-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  min-width: 0;
  padding: 18px;
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  background: var(--surface);
}

.pool-card--hidden { border: 1px dashed var(--suspense); background: var(--suspense-bg); }
.pool-card--empty .pool-card__name,
.pool-card--empty .pool-card__size { color: var(--dim); }

.pool-card__head { display: flex; align-items: flex-start; gap: var(--space-3); }
.pool-card__titles { flex: 1; min-width: 0; }
.pool-card__name { margin: 0; font-family: var(--font-ui); font-size: 1.05rem; font-weight: 600; }
.pool-card__meta { display: flex; align-items: center; gap: 6px; margin: 2px 0 0; font-size: 0.85rem; color: var(--dim); }
.pool-card--hidden .pool-card__meta { color: var(--suspense-text); }
.pool-card__size { font-family: var(--font-dice); font-weight: 600; font-size: 30px; line-height: 1; color: var(--ember); }
.pool-card--hidden .pool-card__size { color: var(--suspense); }

.pool-card__last { display: grid; gap: var(--space-1); }
.pool-card__dice { display: flex; flex-wrap: wrap; gap: 6px; }
.pool-card__change,
.pool-card__note { margin: 0; font-size: 0.85rem; color: var(--dim); }
.pool-card__outcome { margin: 0; font-family: var(--font-display); font-style: italic; font-size: 1.1rem; color: var(--text-soft); }

.pool-card__actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); margin-top: auto; }
.pool-card__actions .button_to { margin: 0; }
.pool-card__spacer { flex: 1; }
.pool-card__reveal { color: var(--suspense-text); }

.pool-card__more { position: relative; }
.pool-card__toggle { width: var(--tap); padding: 0; list-style: none; }
.pool-card__toggle::-webkit-details-marker { display: none; }

.pool-card__menu {
  position: absolute;
  z-index: 15;
  right: 0;
  top: calc(100% + 4px);
  display: grid;
  gap: var(--space-2);
  width: min(18rem, calc(100vw - 2rem));
  padding: var(--space-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-control);
  background: var(--surface);
  box-shadow: var(--shadow);
}

.pool-card__menu .button_to,
.pool-card__menu .button_to .button { width: 100%; }
.pool-card__action-roll { display: grid; gap: var(--space-2); padding-top: var(--space-2); border-top: 1px solid var(--line-soft); }
.pool-card__action-roll .field__hint { margin: 0; }

.pool-new { position: relative; }
.pool-new__toggle { list-style: none; }
.pool-new__toggle::-webkit-details-marker { display: none; }
.pool-new__panel { position: absolute; z-index: 15; right: 0; top: calc(100% + 4px); width: min(26rem, calc(100vw - 2rem)); box-shadow: var(--shadow); }

/* menu_controller.js: a floating panel with no room below opens upward, and
   one that fits neither way scrolls. */
[data-menu-target="panel"] { overflow-y: auto; }
[data-menu-target="panel"].menu-panel--up { top: auto; bottom: calc(100% + 4px); }

/* The ✕ in a floating panel or modal (shared/_close_button). A popover's top
   row (shared/_popover_head) is its title, with the ✕ in the corner. */
.close-button { display: grid; flex: none; place-items: center; width: var(--tap); height: var(--tap); padding: 0; border: 0; border-radius: var(--radius-control); background: none; color: var(--muted); cursor: pointer; }
.close-button:hover { background: var(--surface-2); color: var(--text); }
.popover__head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); margin: calc(-1 * var(--space-2)) calc(-1 * var(--space-2)) 0 0; }
li.popover__head { margin: 0; padding-left: var(--space-3); }
.popover__title { min-width: 0; font-family: var(--font-display); font-weight: 700; font-size: 1.05rem; line-height: 1.25; overflow-wrap: anywhere; }
.scene-bar .between-scenes__actions { flex-wrap: wrap; }
/* The title row fills the first line: its negative right margin (tucking the ✕ into the corner)
   would otherwise leave a sliver there that a 0-basis button squeezes into, clipped. */
.scene-bar .between-scenes__actions .popover__head { flex: 0 0 calc(100% + var(--space-2)); }
.scene-bar .between-scenes__actions { width: min(20rem, calc(100vw - 2rem)); }
/* Buttons share the row by their labels and wrap to another row when they don't fit (Rest resets and Milestone add two). */
.scene-bar .between-scenes__actions > :not(.popover__head) { flex: 1 1 auto; }
.scene-bar .between-scenes__actions .button_to .button { width: 100%; }

/* Folds on the GM table: Rolls and the crucible */
.gm-fold__summary { display: flex; align-items: center; min-height: var(--tap); list-style: none; cursor: pointer; }
.gm-fold__summary::-webkit-details-marker { display: none; }
.gm-fold[open] .gm-fold__summary { margin-bottom: var(--space-3); }

/* Rolls: the segmented control picks which group roll's form shows. */
.rolls { display: grid; gap: var(--space-4); }
.rolls__panel { display: grid; gap: var(--space-3); }
.rolls__panel > .field__hint { margin: 0; }
.rolls:has(.rolls__kinds input[value=story]:checked) .rolls__panel:not(.rolls__panel--story),
.rolls:has(.rolls__kinds input[value=montage]:checked) .rolls__panel:not(.rolls__panel--montage),
.rolls:has(.rolls__kinds input[value=quarrel]:checked) .rolls__panel:not(.rolls__panel--quarrel) { display: none; }

.crucible-row { container: crucible / inline-size; }
.crucible-row__head { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3) var(--space-4); margin-bottom: var(--space-5); }
.crucible-row__pick { flex: 1 1 14rem; max-width: 20rem; min-height: var(--tap); }
.crucible-row__head .crucible-picker__recent { margin-left: auto; }

/* ---------- Campaign page (campaigns#show) ---------- */

.site-main:has(.campaign-page) { max-width: 82rem; }
/* One column to read down (hero, party, what looms, previously on), the table's chat in the rail beside it. */
.campaign-page__main { display: flex; flex-direction: column; gap: 44px; }

/* Hero: what it's about, its rules, and what to do here. */
.campaign-hero { display: flex; flex-direction: column; gap: 14px; padding-bottom: 32px; border-bottom: 1px solid var(--line-soft); }
.campaign-hero .eyebrow { margin: 0; }
.campaign-hero__title { margin: 0; font-size: clamp(2.4rem, 7vw, 3.75rem); line-height: 1.02; }
.campaign-hero__pitch { max-width: 36rem; margin: 0; font-family: var(--font-display); font-style: italic; font-size: 1.35rem; line-height: 1.4; color: var(--text-soft); }
.campaign-hero__pitch--empty { font-family: var(--font-ui); font-style: normal; font-size: 0.95rem; color: var(--dim); }
.campaign-hero__facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr)); gap: var(--space-3) var(--space-5); margin: var(--space-2) 0 0; }
.campaign-hero__facts dt { font-size: 12px; font-weight: 500; letter-spacing: 0.08em; text-transform: uppercase; color: var(--dim); }
.campaign-hero__facts dd { margin: 2px 0 0; font-weight: 600; }
.campaign-hero__hold { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-2); margin: 0; color: var(--text-soft); }
.campaign-hero__hold-chip { padding: 2px 10px; border: 1px dashed var(--suspense); border-radius: 999px; font-size: 0.85rem; font-weight: 600; color: var(--suspense-text); }
.campaign-hero__rules { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin: 0; }
.campaign-hero__rules-label { margin-right: 4px; font-size: 12px; font-weight: 500; letter-spacing: 0.08em; text-transform: uppercase; color: var(--dim); }
.campaign-hero__rule { padding: 2px 10px; border: 1px solid var(--line); border-radius: 999px; font-size: 0.85rem; color: var(--text-soft); cursor: help; }
.campaign-hero__rule:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }

/* The actions: the main one first, then the rest beside it, settings or leaving at the far end. */
.campaign-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); margin-top: var(--space-2); }
.campaign-actions .button_to { margin: 0; }
.campaign-actions__end { margin-left: auto; }
.campaign-actions__hint { margin: 0; font-size: 0.87rem; color: var(--muted); }
.campaign-actions__done { font-family: var(--font-display); font-size: 1.05rem; color: var(--text); }

/* What looms: a card per pool, read-only. */
.looms { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 15rem), 1fr)); gap: 12px; }
.looms .pool-glance { padding: 14px 16px; }
.pool-glance__kind { font-size: 0.8rem; color: var(--dim); }

/* "Open my character" for a player with several here: a button with a menu. */
.go-menu { position: relative; }
.go-menu__button { display: flex; justify-content: center; gap: var(--space-2); list-style: none; cursor: pointer; }
.go-menu__button::-webkit-details-marker { display: none; }
.go-menu[open] .go-menu__button .icon { transform: rotate(180deg); }
.go-menu__list { position: absolute; z-index: 15; left: 0; min-width: max(100%, 16rem); top: calc(100% + 4px); display: grid; gap: 2px; margin: 0; padding: var(--space-1); list-style: none; border: 1px solid var(--line); border-radius: var(--radius-control); background: var(--surface); box-shadow: var(--shadow); }
.go-menu__item { display: grid; gap: 2px; min-height: var(--tap); padding: var(--space-2) var(--space-3); border-radius: var(--radius-sm); color: var(--text); text-decoration: none; }
.go-menu__item:hover, .go-menu__item:focus-visible { background: var(--surface-2); }
.go-menu__name { font-family: var(--font-display); font-weight: 700; font-size: 1.05rem; }
.go-menu__meta { font-size: 0.85rem; color: var(--dim); }


.link-button {
  display: inline;
  min-height: 0;
  padding: 0;
  border: 0;
  background: none;
  color: var(--link);
  font: inherit;
  text-decoration: underline;
  text-underline-offset: 0.18em;
  cursor: pointer;
}

/* Party */
.party-grid--wide { grid-template-columns: repeat(auto-fill, minmax(min(100%, 290px), 1fr)); }

.hero-card {
  display: flex;
  flex-direction: column;
  gap: 14px;
  min-width: 0;
  padding: 18px;
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  background: var(--surface);
}

.hero-card--empty { justify-content: center; border-style: dashed; background: transparent; }
.hero-card__who { display: flex; align-items: center; gap: 12px; }
.hero-card__titles { flex: 1; min-width: 0; }
.hero-card__name { display: block; margin: 0; font-family: var(--font-display); font-weight: 700; font-size: 1.35rem; line-height: 1.1; color: var(--text); text-decoration: none; }
a.hero-card__name:hover { color: var(--link); text-decoration: underline; }
.hero-card--empty .hero-card__name { font-family: var(--font-ui); font-size: 1rem; font-weight: 600; }
.hero-card__meta { margin: 2px 0 0; font-size: 0.87rem; color: var(--muted); }
.hero-card__harm { margin: 0; font-size: 0.9rem; color: var(--grim); }
.hero-card__harm--none { color: var(--muted); }

.monogram--44 { width: 44px; height: 44px; font-size: 24px; }
.monogram--28 { width: 28px; height: 28px; border-radius: 50%; font-family: var(--font-ui); font-size: 13px; background: var(--surface-2); color: var(--text); }
.monogram--empty { background: transparent; box-shadow: inset 0 0 0 1px var(--line-strong); color: var(--muted); }

.stat-tiles { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; }

.stat-tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 10px 4px;
  border-radius: var(--radius-control);
  background: var(--surface-2);
}

.stat-tile__value { font-family: var(--font-dice); font-weight: 600; font-size: 1.15rem; line-height: 1; }
.stat-tile__name { font-size: 11px; font-weight: 500; letter-spacing: 0.08em; color: var(--dim); }
.stat-tile__name abbr { text-decoration: none; }
.stat-tile--marked { background: var(--grim-bg); box-shadow: inset 0 0 0 1px var(--grim-ring); }
.stat-tile--marked .stat-tile__value,
.stat-tile--marked .stat-tile__name { color: var(--grim); }

/* Fallen and retired characters (Character::Farewell), remembered under the
   party and on the Characters page. Fallen ones carry a grim edge. */
.farewells { display: grid; gap: var(--space-3); margin-top: var(--space-5); }
.farewells--page { margin-top: var(--space-6); }
.farewells__title { margin: 0; font-size: 1.1rem; color: var(--muted); }
.farewells__list { display: grid; gap: var(--space-3); grid-template-columns: repeat(auto-fill, minmax(min(100%, 17rem), 1fr)); }
.farewell-card { display: flex; gap: var(--space-3); padding: 14px 16px; border: 1px dashed var(--line-strong); border-radius: var(--radius-control); background: transparent; }
.farewell-card--fallen { border-color: var(--grim-line); }
.farewell-card__body { display: grid; gap: 2px; align-content: start; min-width: 0; }
.farewell-card__status { margin: 0; font-size: 11px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--dim); }
.farewell-card--fallen .farewell-card__status { color: var(--grim); }
.farewell-card__name { font-family: var(--font-display); font-weight: 700; font-size: 1.15rem; color: var(--text); text-decoration: none; }
.farewell-card__name:hover { text-decoration: underline; }
.farewell-card__meta { margin: 0; font-size: 0.85rem; color: var(--dim); }
.farewell-card__words { margin: var(--space-1) 0 0; font-family: var(--font-display); font-style: italic; color: var(--text-soft); }

/* A fallen or retired character's own sheet. */
.farewell-banner { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-3); padding: 14px 18px; border: 1px dashed var(--line-strong); border-radius: var(--radius-control); }
.farewell-banner--fallen { border-color: var(--grim-line); background: var(--grim-bg); }
.farewell-banner__status { margin: 0; font-size: 0.9rem; color: var(--muted); }
.farewell-banner--fallen .farewell-banner__status strong { color: var(--grim); }
.farewell-banner__words { margin: var(--space-1) 0 0; font-family: var(--font-display); font-style: italic; font-size: 1.15rem; }
.farewell-banner__hint { margin: var(--space-1) 0 0; font-size: 0.85rem; color: var(--dim); }
.farewell-banner .button_to { margin: 0; }

/* Up for grabs (Character::Claiming): characters waiting for a player to pick. */
.hero-card__release { align-self: flex-start; margin: -6px 0 0; }
.grabs { display: flex; flex-direction: column; gap: var(--space-2); margin-top: var(--space-4); scroll-margin-top: 6rem; }
.grabs__title { margin: 0; font-family: var(--font-ui); font-size: 0.87rem; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--dim); }
.grabs__hint { margin: 0; font-size: 0.9rem; color: var(--muted); }
.grabs__list { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 17rem), 1fr)); gap: var(--space-2); margin: 0; padding: 0; list-style: none; }
.grabs__item { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 12px; padding: 12px; border: 1px dashed var(--line-strong); border-radius: var(--radius-card); }
.grabs__item .button_to { margin: 0; }
.grabs__who { display: flex; flex: 1; flex-direction: column; min-width: 8rem; }
.grabs__name { font-family: var(--font-display); font-weight: 700; font-size: 1.1rem; color: var(--text); text-decoration: none; }
a.grabs__name:hover { color: var(--link); text-decoration: underline; }
.grabs__meta { font-size: 0.87rem; color: var(--muted); }

/* The sheet's strip: up for grabs, or the way to give it back. */
.claim-bar { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-2) var(--space-3); padding: 10px 12px 10px 16px; border: 1px solid var(--line); border-radius: var(--radius-card); }
.claim-bar--open { border-style: dashed; border-color: var(--ember); background: var(--ember-soft); }
.claim-bar__text { flex: 1 1 16rem; margin: 0; color: var(--text-soft); }
.claim-bar .button_to { margin: 0; }

/* Previously on… */
.previously {
  display: flex;
  flex-wrap: wrap;
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  background: var(--surface);
  overflow: hidden;
}

.previously__session { flex: 1 1 320px; min-width: 0; padding: 22px; }
.previously__meta { margin: 0; font-size: 0.87rem; color: var(--muted); }
.previously__title { margin: 4px 0 var(--space-3); font-size: 1.65rem; }
.previously__title a { color: var(--text); text-decoration: none; }
.previously__title a:hover { color: var(--link); text-decoration: underline; }
.previously__recap { margin: 0 0 var(--space-3); color: var(--text-soft); }
.previously__scenes { margin: 0; padding: 0; list-style: none; }
.previously__scenes li { display: flex; align-items: baseline; gap: 14px; padding: 10px 0; border-top: 1px solid var(--line-soft); }
.previously__number { width: 1.2rem; color: var(--dim); }
.previously__scene { flex: 1; }
.previously__outcome { font-size: 0.85rem; color: var(--muted); text-align: right; }

.older-sessions { margin: 0; padding: 0; list-style: none; border: 1px solid var(--line); border-radius: var(--radius-card); background: var(--surface); }
.older-sessions li + li { border-top: 1px solid var(--line-soft); }

.older-sessions__link,
.older-sessions__all {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-1) var(--space-5);
  min-height: 52px;
  padding: var(--space-2) 18px;
  color: var(--text);
  text-decoration: none;
}

.older-sessions__link:hover { background: var(--surface-2); }
.older-sessions__number { width: 2.5rem; font-family: var(--font-dice); color: var(--muted); }
.older-sessions__title { flex: 1; font-weight: 600; }
.older-sessions__meta { font-size: 0.85rem; color: var(--muted); }
.older-sessions__all { color: var(--link); font-weight: 600; }

/* Side column */
.side-card[hidden] { display: none; }
.side-card { display: flex; flex-direction: column; gap: var(--space-3); padding: 20px; }
.side-card__title { margin: 0; font-family: var(--font-display); font-weight: 700; font-size: 1.3rem; }
.side-card__head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); }
.side-card__note { margin: 0; font-size: 0.8rem; color: var(--dim); }

.pool-glance { display: grid; gap: 6px; }
.pool-glance__head { display: flex; justify-content: space-between; gap: var(--space-2); }
.pool-glance__size { font-family: var(--font-dice); font-weight: 600; color: var(--ember); }
.pool-glance__hidden { display: flex; align-items: center; gap: var(--space-2); margin: 0; padding-top: var(--space-3); border-top: 1px solid var(--line-soft); font-size: 0.85rem; color: var(--muted); }

.members { display: grid; gap: 0; margin: 0; padding: 0; list-style: none; }
.rules-in-play { display: grid; gap: var(--space-2); margin: 0; padding: 0; list-style: none; }
.rule-pools__slots { margin: 0; }
.members__item { display: flex; align-items: center; gap: 12px; min-height: var(--tap); }
.members__name { flex: 1; }
.members__role { font-size: 0.85rem; color: var(--muted); }
.members__role--gm { font-weight: 600; color: var(--ember); }

.kept-line { margin: 0; font-family: var(--font-display); font-size: 1.15rem; line-height: 1.5; }
/* Kept lines under each crucible's name, in the crucibles' order. */
.kept-groups { display: grid; gap: var(--space-3); }
.kept-group__name { margin: 0; font-size: 11px; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; color: var(--dim); }
.table-rail__links { margin: 0; padding: 12px 14px; border-top: 1px solid var(--line-soft); font-size: 0.9rem; }

.settings { display: grid; gap: var(--space-5); max-width: 46rem; }

/* Talent pools under a party card. */
.seat-pool { display: flex; align-items: center; gap: var(--space-2); padding-left: var(--space-2); border-left: 3px solid var(--pool-color, var(--line-strong)); font-size: 0.85rem; }
.seat-pool__name { flex: 1; }
.seat-pool__size { font-family: var(--font-dice); font-weight: 600; }

/* ---------- Table rail: chat and log in one stream ---------- */

.table-rail__titles { flex: 1 1 9rem; min-width: 0; }
.table-rail__where { margin: 0; font-size: 0.85rem; color: var(--muted); }

.avatars { display: inline-flex; gap: 6px; }
.avatar {
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  border: 2px solid var(--rail);
  border-radius: 50%;
  background: var(--surface-2);
  color: var(--text);
  font-size: 12px;
  font-weight: 600;
}

.avatar--gm { background: var(--ember-soft); color: var(--link); }

/* Presence halos (presence_controller.js): the ring that separates each face
   turns green while they have the table open and in use, yellow while it's
   open but idle, and stays plain when no page is open. */
.avatar { transition: border-color 200ms; }

/* Hovering a face shows who it is and their presence (data-label): a popover
   in the top layer (presence_controller.js), so the rail's clipping and
   whatever paints over it can't hide it. */
.face-tip {
  position: fixed;
  inset: auto;
  margin: 0;
  padding: 4px 8px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  background: var(--surface);
  box-shadow: var(--shadow);
  color: var(--text);
  font: 500 12px/1.4 var(--font-ui);
  white-space: nowrap;
  pointer-events: none;
}
.avatar[data-presence="active"] { border-color: var(--presence-active); }
.avatar[data-presence="idle"] { border-color: var(--presence-idle); }

.feed { position: relative; display: flex; flex-direction: column; gap: var(--space-3); padding: 12px 14px 0; }
.feed__filter { display: flex; align-items: center; gap: var(--space-2); }
.feed__filter-label { flex: none; font-size: 0.85rem; color: var(--muted); }
.feed__filter-select { flex: 1; min-width: 0; }
/* Unread chat: a pill beside Show, ember, or dashed purple while any of it is private. */
.feed__unread { flex: none; display: inline-flex; align-items: center; gap: 6px; min-height: var(--tap); padding: 0 12px; border: 1px solid var(--line); border-radius: 999px; background: none; color: var(--ember); font: 600 13px/1 var(--font-ui); white-space: nowrap; cursor: pointer; }
.feed__unread::before { content: ""; width: 8px; height: 8px; border-radius: 50%; background: var(--ember); }
.feed__unread--private { border: 1px dashed var(--suspense-line); color: var(--suspense-text); }
.feed__unread--private::before { background: var(--suspense); }
.feed__unread[hidden] { display: none; }
.feed__unread:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }

/* Newest at the bottom: a column-reverse scroller stays pinned to the newest line as lines arrive. */
.feed__scroller { display: flex; flex-direction: column-reverse; max-height: 80vh; overflow-y: auto; overscroll-behavior: contain; }
.feed__older { min-height: 1px; margin: 0 0 var(--space-3); text-align: center; font-size: 0.85rem; color: var(--dim); }
.feed__older:empty { margin: 0; }
.feed__items { display: flex; flex-direction: column; gap: 14px; margin: 0; padding: 0 0 var(--space-3); list-style: none; }
.feed__items:has(li) + .feed__empty { display: none; }
.feed__empty { margin: 0 0 var(--space-3); }

/* "3 new": lines arrived while you were scrolled up (feed_controller.js). */
.feed__new {
  position: absolute;
  z-index: 2;
  bottom: var(--space-3);
  left: 50%;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: var(--tap);
  padding: 0 14px 0 16px;
  border: 0;
  border-radius: 999px;
  background: var(--ember);
  color: var(--ember-ink);
  font: 600 0.87rem/1 var(--font-ui);
  box-shadow: 0 8px 20px -6px rgb(0 0 0 / 0.8);
  transform: translateX(-50%);
  cursor: pointer;
  animation: feed-new-in 160ms ease-out;
}

.feed__new[hidden] { display: none; }
.feed__new:hover { filter: brightness(1.08); }
.feed__new:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
@keyframes feed-new-in { from { opacity: 0; transform: translate(-50%, 8px); } }
@media (prefers-reduced-motion: reduce) { .feed__new { animation: none; } }

/* Filters: Story is the fiction (narration, NPCs, in character, scene dividers and game events), Table talk is out of character, Dice is rolls and pool changes, and a private conversation is your whispers with one person (marked .feed-item--in-thread by feed_controller.js). Everything leaves whispers out, for everyone: they're read a conversation at a time. */
.table-rail:has(.feed__filter option[value=all]:checked) .feed__items > .feed-item--private,
.table-rail:has(.feed__filter option[value^="private-"]:checked) .feed__items > :not(.feed-item--in-thread),
.table-rail:has(.feed__filter option[value=story]:checked) .feed__items > :not(.feed-item--story):not(.feed-item--event),
.table-rail:has(.feed__filter option[value=talk]:checked) .feed__items > :not(.feed-item--talk),
.table-rail:has(.feed__filter option[value=dice]:checked) .feed__items > :not(.feed-item--dice) { display: none; }

.feed-item { min-width: 0; }
.feed-item__time { margin-left: auto; font-size: 12px; font-weight: 400; color: var(--dim); }
.feed-item__meta { margin: 0; font-size: 12px; color: var(--dim); }
.feed-item__question { margin: 0; font-style: italic; color: var(--text-soft); }
.feed-item__result { margin: 0; font-family: var(--font-display); font-weight: 700; color: var(--text); }

/* Game events and scene dividers */
.feed-event { margin: 0; text-align: center; font-size: 12px; color: var(--dim); }
.feed-event strong { color: var(--muted); font-weight: 600; }

.feed-divider { display: flex; align-items: center; gap: var(--space-3); }
.feed-divider::before,
.feed-divider::after { content: ""; flex: 1; height: 1px; background: var(--line); }
.feed-divider__text { font-family: var(--font-display); font-size: 13px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--muted); }

/* Character rolls: a small result card */
.feed-roll {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: 12px;
  border-radius: 12px;
  background: var(--surface);
  box-shadow: inset 0 0 0 1px var(--line);
}

.feed-roll--grim,
.feed-roll--disaster { background: var(--grim-bg); box-shadow: inset 0 0 0 1px var(--grim-line); }
.feed-item--gm-only.feed-roll { box-shadow: none; border: 1px dashed var(--suspense-line); }
.feed-item--gm-only.feed-pool { border: 1px dashed var(--suspense-line); }
.feed-roll__head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 var(--space-2); margin: 0; font-size: 0.85rem; color: var(--text-soft); }
.feed-roll__head strong { color: var(--text); }
.feed-roll__dice { display: inline-flex; gap: 4px; }

/* Pool rolls: one line */
.feed-pool { display: grid; gap: 2px; padding: 10px 12px; border: 1px solid var(--line); border-radius: 10px; }
.feed-pool__line { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-1) var(--space-3); margin: 0; font-size: 0.9rem; }
.feed-pool__name { flex: 1; }
.feed-pool__change { font-family: var(--font-dice); color: var(--muted); }
.feed-pool__change strong { color: var(--ember); }
.feed-pool__who { font-size: 12px; color: var(--dim); }

/* Chat lines, by kind */
.chat-line { display: flex; flex-direction: column; align-items: flex-start; gap: 3px; }
/* The delete button on each chat line: on every line in the GM's rail, and on your own (marked by feed_controller.js) in anyone's, until the campaign is archived; quiet until the line is hovered or the button focused. */
.chat-line__delete-form { display: none; }
.table-rail--gm .chat-line, .table-rail--open .chat-line--mine { position: relative; padding-right: 36px; }
.table-rail--gm .chat-line__delete-form, .table-rail--open .chat-line--mine .chat-line__delete-form { display: block; position: absolute; top: -8px; right: -6px; margin: 0; }
.chat-line__delete { display: inline-flex; align-items: center; justify-content: center; width: var(--tap); height: var(--tap); border: 0; border-radius: var(--radius-sm); background: none; color: var(--dim); opacity: 0.35; cursor: pointer; }
.chat-line:hover .chat-line__delete, .chat-line__delete:focus-visible { opacity: 1; }
.chat-line__delete:hover { color: var(--grim); }
/* Incoming lines sit on the left; your own (feed_controller.js marks them) on the right, their text still reading left to right. Narration spans the rail either way. */
.chat-line--mine { align-items: flex-end; }
.chat-line--mine .chat-line__head, .chat-line--mine .chat-line__label { justify-content: flex-end; }
.chat-line__head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 var(--space-2); margin: 0; font-size: 13px; }
.chat-line__who { color: var(--text-soft); }
.chat-line__who--character { color: var(--link); }
.chat-line__who--npc { color: var(--suspense-text); }
.chat-line__note { color: var(--dim); }
.chat-line__body { margin: 0; white-space: pre-line; overflow-wrap: anywhere; }
.chat-line__body--voice { font-family: var(--font-display); font-style: italic; font-size: 17px; line-height: 1.4; }
/* *Actions* in a line that's already italic stand out by turning upright. */
.chat-line__body--voice em { font-style: normal; }

.chat-line__bubble { max-width: 85%; padding: 8px 12px; border-radius: 12px 12px 12px 4px; background: var(--surface-2); }
.chat-line--mine .chat-line__bubble { border-radius: 12px 12px 4px 12px; background: var(--mine-bg); box-shadow: inset 0 0 0 1px var(--mine-line); }
.chat-line__bubble--character { background: var(--ember-soft); }
.chat-line__bubble--npc { background: var(--suspense-bg); box-shadow: inset 0 0 0 1px var(--suspense-line); }

.chat-line__card { align-self: stretch; display: grid; gap: 2px; padding: 10px 12px; border-radius: 10px; }
.chat-line__card--narration { background: var(--surface-2); }
.chat-line__card--narration .chat-line__body { font-size: 18px; }
.chat-line__card--whisper { align-self: auto; max-width: 85%; border: 1px dashed var(--suspense-line); }
.chat-line--mine .chat-line__card--whisper { background: var(--mine-bg); }
.chat-line__label { flex-wrap: wrap; }
.chat-line .feed-item__time { white-space: nowrap; }
.chat-line__label { display: flex; align-items: center; gap: 6px; margin: 0; font-size: 11px; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; color: var(--ember); }
.chat-line__whisper-time { margin: 0; line-height: 1; }
.chat-line__whisper-time .feed-item__time { margin: 0; }

/* Composer */
.composer { display: flex; flex-direction: column; gap: var(--space-2); margin: 0; padding: 12px 14px; border-top: 1px solid var(--line-soft); }
/* Speak as: a dropdown above the message box. */
/* Where it goes, from Show: a line above the box, and the box itself in the voice it'll read in (story views italic, private dashed purple). The GM's Narrate | As NPC and a player's character pick show only in the story views. */
.composer__to { margin: 0; font-size: 12px; font-weight: 600; color: var(--muted); }
.composer__voices { display: grid; gap: var(--space-2); }
.composer__npc { display: none; }
.composer:has(input[name=voice][value=npc]:checked) .composer__npc { display: block; }
.composer__row { display: flex; align-items: center; gap: var(--space-2); }
.composer__hint { flex: 1; min-width: 0; margin: 0; font-size: 12px; color: var(--dim); }
.composer__send { flex: none; padding-inline: var(--space-5); }

.composer__input { width: 100%; min-height: 5.5rem; max-height: 16rem; resize: vertical; field-sizing: content; }
.composer:not(.composer--no-character) .composer__input { font-family: var(--font-display); font-style: italic; font-size: 17px; }
.table-rail:has(.feed__filter option[value=talk]:checked, .feed__filter option[value^="private-"]:checked) .composer__voices { display: none; }
.table-rail:has(.feed__filter option[value=talk]:checked, .feed__filter option[value^="private-"]:checked) .composer__input { font-family: var(--font-ui); font-style: normal; font-size: inherit; }
.table-rail:has(.feed__filter option[value^="private-"]:checked) .composer__input { border-style: dashed; border-color: var(--suspense-line); background: var(--suspense-bg); }
.table-rail:has(.feed__filter option[value^="private-"]:checked) .composer__to { color: var(--suspense-text); }

/* An archived campaign: no composer, just this. */
.table-rail__archived { margin: 0; padding: 14px; border-top: 1px solid var(--line-soft); font-size: 0.87rem; color: var(--muted); }

/* ---------- Interaction states ----------
   Every clickable control says so: hover adds a ring (where there's a pointer,
   so a tap on a phone doesn't stick), pressing darkens and shrinks it, and a
   form Turbo is submitting dims its button until the page answers. */

.button,
.segmented__text,
.harm-toggle,
.mark-toggle,
.stepper__step,
.counter__step {
  transition: background 120ms, border-color 120ms, color 120ms, box-shadow 120ms, transform 80ms, filter 120ms;
}

@media (hover: hover) {
  .button:hover:not(:disabled),
  .stepper__step:hover:not(:disabled),
  .counter__step:hover:not(:disabled) {
    border-color: var(--text-soft);
    background: var(--surface-2);
    color: var(--text);
    box-shadow: inset 0 0 0 1px var(--text-soft);
  }

  .button--ghost:hover:not(:disabled),
  .button--quiet:hover:not(:disabled) { border-color: var(--line-strong); box-shadow: none; }

  .button--primary:hover:not(:disabled) {
    border-color: var(--link);
    background: var(--link);
    color: var(--ember-ink);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--ember) 35%, transparent);
  }

  .button--suspense:hover:not(:disabled) {
    border-color: var(--suspense-text);
    background: var(--suspense-text);
    color: var(--ember-ink);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--suspense) 35%, transparent);
  }

  .segmented__option:hover:not(:has(input:checked)) .segmented__text {
    background: var(--surface-2);
    color: var(--text);
    box-shadow: inset 0 0 0 1px var(--line-strong);
  }

  .segmented__option:hover:has(input:checked) .segmented__text { box-shadow: inset 0 0 0 2px var(--link); background: color-mix(in srgb, var(--ember) 30%, var(--surface)); }

  .harm-toggle:hover:not([aria-pressed="true"]),
  .mark-toggle:hover:not([aria-pressed="true"]) {
    border-color: var(--text-soft);
    color: var(--text);
    box-shadow: inset 0 0 0 1px var(--text-soft);
  }

  .harm-toggle[aria-pressed="true"]:hover,
  .mark-toggle[aria-pressed="true"]:hover { box-shadow: 0 0 0 3px color-mix(in srgb, var(--grim-ring) 40%, transparent); }
}

/* Pressed: darker, a touch smaller. */
.button:active:not(:disabled),
.stepper__step:active:not(:disabled),
.counter__step:active:not(:disabled),
.harm-toggle:active,
.mark-toggle:active {
  transform: scale(0.97);
  filter: brightness(0.85);
}

.segmented__option:active:not(:has(input:checked)) .segmented__text {
  transform: scale(0.96);
  background: var(--line-soft);
}

/* Submitting: Turbo marks the form aria-busy until the response lands. */
form[aria-busy="true"] :is(.button, button, .harm-toggle, .mark-toggle) {
  cursor: progress;
  opacity: 0.6;
  transform: scale(0.97);
}

/* Folds (Rolls, Log a game event): a chevron that turns when open, and a hover. */
.gm-fold__summary,
.table-rail__summary {
  justify-content: space-between;
  gap: var(--space-2);
  margin-inline: calc(-1 * var(--space-2));
  padding-inline: var(--space-2);
  border-radius: var(--radius-control);
  transition: background 120ms, color 120ms;
}

.gm-fold__summary .icon,
.table-rail__summary .icon { color: var(--muted); transition: transform 160ms; }
details[open] > .gm-fold__summary .icon,
details[open] > .table-rail__summary .icon { transform: rotate(180deg); }

@media (hover: hover) {
  .gm-fold__summary:hover,
  .table-rail__summary:hover { background: var(--surface-2); }
  .gm-fold__summary:hover .icon,
  .table-rail__summary:hover .icon { color: var(--text); }
}

.gm-fold__summary:active,
.table-rail__summary:active { background: var(--line-soft); }


/* Admin zone (/admin): counts, then wide tables that scroll on their own on a phone. */
.admin-nav { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-top: var(--space-3); }
.admin-nav [aria-current="page"] { color: var(--text); text-decoration: underline; text-decoration-color: var(--ember); text-underline-offset: 0.35em; }

/* Admin lists: a search box above, and pagy's count and page links below. */
.admin-search { display: flex; flex-wrap: wrap; gap: var(--space-2); max-width: 46rem; margin-bottom: var(--space-4); }
.admin-search .field__input { flex: 1 1 14rem; }
.admin-search .admin-search__filter { flex: 0 1 11rem; }
.admin-pages { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-3); margin-top: var(--space-4); color: var(--muted); font-size: 0.9rem; }
.admin-pages .series-nav { display: flex; flex-wrap: wrap; gap: var(--space-1); }
.admin-pages .series-nav a {
  display: inline-grid;
  place-items: center;
  min-width: var(--tap);
  min-height: var(--tap);
  padding: 0 var(--space-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-control);
  color: var(--text);
  text-decoration: none;
}
.admin-pages .series-nav a[href]:hover { border-color: var(--ember); }
.admin-pages .series-nav a[aria-current="page"] { background: var(--ember); border-color: var(--ember); color: var(--ember-ink); font-weight: 600; }
.admin-pages .series-nav a[aria-disabled="true"]:not([aria-current]) { color: var(--dim); border-style: dashed; }

.admin-stats {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr));
  gap: var(--space-3);
  margin: 0 0 var(--space-5);
  padding: 0;
  list-style: none;
}
.admin-stats__item { display: grid; gap: var(--space-1); }
.admin-stats__count { font-family: var(--font-dice); font-size: 1.75rem; font-weight: 600; }
.admin-stats__label { color: var(--muted); }

.admin-table {
  overflow-x: auto;
  margin-bottom: var(--space-5);
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  background: var(--surface);
}
.admin-table table { width: 100%; border-collapse: collapse; }
.admin-table th,
.admin-table td { padding: var(--space-2) var(--space-3); border-top: 1px solid var(--line-soft); text-align: left; vertical-align: top; }
.admin-table thead th { border-top: 0; color: var(--muted); font-weight: 500; white-space: nowrap; }
.admin-badge { margin-left: var(--space-2); background: var(--ember-soft); color: var(--ember); }
.admin-new { max-width: 32rem; }
.admin-plan { display: flex; gap: var(--space-2); align-items: center; }
.admin-plan .field__input { width: auto; min-width: 9rem; }
.admin-plan__over { display: block; margin-top: var(--space-1); color: var(--grim); }

/* Picks a talent asks for: chips on its card, and the form that picks them
   (characters/talent_choices/edit). */
.talent-card__choices { display: flex; flex-direction: column; gap: var(--space-1); margin-top: var(--space-2); }
.talent-card__choices .talent-card__label { margin: 0; }
.talent-card__picks { display: flex; flex-wrap: wrap; gap: 4px; margin: 0; padding: 0; list-style: none; }
.talent-card__pick { padding: 2px 10px; border: 1px solid var(--line-strong); border-radius: 999px; font-size: 0.85rem; color: var(--text); }
.talent-card__pick-more { align-self: flex-start; font-size: 0.85rem; color: var(--ember); }
.talent-card__choices .talent-over { margin: 0; }
.talent-choice { display: flex; flex-direction: column; gap: var(--space-2); margin: 0; padding: 0; border: 0; min-width: 0; }
.talent-choice__legend { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-2); width: 100%; padding: 0; }
.talent-choice__count { font-family: var(--font-dice); font-size: 0.85rem; color: var(--muted); }
.talent-choice__group { display: flex; flex-wrap: wrap; gap: var(--space-1) var(--space-3); }
.talent-choice__group-name { flex-basis: 100%; margin: 0; font-size: 11px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--dim); }
.talent-choice__option { min-height: var(--tap); flex: 0 1 12rem; }
.talent-choice__option:has(input:disabled) { opacity: 0.5; cursor: default; }
.talent-choice__hint { display: block; font-size: 13px; color: var(--dim); }
.talent-choice__boxes { display: flex; flex-direction: column; gap: var(--space-2); }
.talent-choice__box { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.talent-choice__box > .field__input { flex: 1 1 12rem; min-width: 0; }
.talent-choice__box > .talent-choice__school { flex: 0 1 11rem; }
.talent-choice__crucible .crucible { margin-top: var(--space-2); }

/* Arcana on the sheet (characters/_arcana, _arcanum) and their form. */
.arcana-grants { display: flex; flex-direction: column; gap: var(--space-1); margin: 0 0 var(--space-3); padding: 0; list-style: none; font-size: 0.9rem; color: var(--muted); }
.arcana-grants__item { display: flex; flex-wrap: wrap; gap: var(--space-1) var(--space-3); align-items: baseline; }
.arcana-grants__item a { color: var(--ember); }
.arcanum-card--mythic { border-color: color-mix(in srgb, var(--spark) 45%, var(--line)); }
.arcanum-card--used { opacity: 0.6; }
.arcanum-card__function { border-color: var(--ember); color: var(--ember); }
.arcanum-card__opus { display: flex; flex-direction: column; gap: var(--space-1); margin-top: var(--space-2); }
.arcanum-card__opus .talent-card__label { margin: 0; }
.arcanum-form__group { display: flex; flex-direction: column; gap: var(--space-2); margin: 0; padding: 0; border: 0; min-width: 0; }
.arcanum-form__options { display: grid; grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr)); gap: var(--space-1) var(--space-3); }
.arcanum-form__options--row { display: flex; flex-wrap: wrap; }
.arcanum-form__option { align-items: flex-start; min-height: var(--tap); }
.arcanum-form__option small { display: block; color: var(--muted); }

/* Talents in the roll setup (characters/_roll_form): ticks, and the ones that always apply */
.stat-roll__talents { display: grid; gap: var(--space-2); margin: 0; padding: 0; list-style: none; }
.stat-roll__talent { align-items: flex-start; font-size: 0.9rem; line-height: 1.35; }
.stat-roll__talent input { flex: none; margin-top: 0.1rem; }
.stat-roll__talent small { color: var(--muted); white-space: nowrap; }
.stat-roll__talent--auto { display: inline-flex; gap: var(--space-2); color: var(--muted); }
.stat-roll__talent--auto .icon { flex: none; margin-top: 0.15rem; color: var(--perfect); }
.stat-roll__talent--auto strong { color: var(--text); }
.roll-call__talent { flex: 1 1 100%; align-items: flex-start; font-size: 0.9rem; line-height: 1.35; }
.roll-call__talent small, .roll-call__talent--auto { color: var(--muted); }
.roll-call__talent--auto { display: inline-flex; gap: var(--space-2); }
.roll-call__talent--auto .icon { flex: none; margin-top: 0.15rem; color: var(--perfect); }
.roll-call__talent--auto strong { color: var(--text); }

/* After the roll (campaigns/rolls/follow_ups/new): what talents can do to a roll once it's made */
.follow-ups__list { display: grid; gap: var(--space-3); margin: 0; padding: 0; list-style: none; }
.follow-ups__item { display: grid; gap: var(--space-1); padding-top: var(--space-3); border-top: 1px solid var(--line); }
.follow-ups__what, .follow-ups__label { margin: 0; }
.follow-ups__what small, .follow-ups__label small { color: var(--muted); }
.follow-ups__actions { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.roll-toast__follow-up { margin: var(--space-2) 0 0; }
.feed-item__follow-up { font-size: 0.85rem; }
.die--d8.die--panache.die--cut { color: var(--perfect); }
.die--d8.die--panache::before { border-style: dashed; }
.die--d8.die--panache.die--cut::before { border-color: var(--perfect); background: transparent; }
.stat-roll__assists { align-items: flex-start; }
.stat-roll__assist { display: grid; gap: var(--space-1); }
.stat-roll__assist .stat-roll__talent { margin-left: 1.6rem; }
.talent-card__make { display: flex; flex-wrap: wrap; gap: var(--space-2); align-items: center; }
.talent-card__make .field__input { flex: 1 1 10rem; min-width: 0; }
.use-word--charge.use-word--burned { border-style: solid; border-color: var(--spark); color: var(--spark); text-decoration: none; }
.use-word--mark.use-word--burned { border-style: solid; border-color: var(--grim-ring); color: var(--grim); text-decoration: none; }
.use-box--track { width: auto; min-width: 2.25rem; padding: 0 6px; }
.use-box__thorns { font-family: var(--font-dice); font-size: 0.75rem; }
.use-tracker--tally { align-items: center; }
.use-tally__count { font-family: var(--font-dice); min-width: 1.5rem; text-align: center; }
.talent-state { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
.talent-state__dice { display: inline-flex; gap: 4px; }
.talent-state__on { color: var(--grim); }
.oath-tenets__list { flex-basis: 100%; display: flex; flex-direction: column; gap: var(--space-1); margin: 0; padding: 0; list-style: none; }
.oath-tenets__item { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
.oath-tenets__tenet--violated { border-color: var(--grim-line); }
.oath-tenets__tenet--heavy { border-color: var(--grim-line); background: var(--grim-bg); }
.oath-tenets__tenet--broken { color: var(--dim); text-decoration: line-through; }
.stat-progression { position: relative; margin-top: var(--space-2); }
.crucible__credit, .talent-card__crucible { margin: 0; font-size: 0.85rem; color: var(--muted); }

/* Scene prep (ScenePlan): the list to play, and the picks above a new scene's form. */
.scene-plans { display: grid; gap: var(--space-2); margin: 0; padding: 0; list-style: none; }
.scene-plans__item { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between; gap: var(--space-2) var(--space-3); padding: var(--space-3); border: 1px solid var(--line); border-radius: var(--radius-control); background: var(--surface-2); }
.scene-plans--played .scene-plans__item { padding: var(--space-2) var(--space-3); opacity: 0.75; }
.scene-plans__main { display: flex; flex: 1 1 16rem; flex-direction: column; gap: 2px; min-width: 0; }
.scene-plans__title { font-family: var(--font-display); font-size: 1.1rem; }
.scene-plans__notes { margin: var(--space-1) 0 0; color: var(--text-soft); white-space: pre-line; }
.scene-plans__actions { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.scene-plans__actions .button_to { margin: 0; }
.scene-prep-picks { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); margin-bottom: var(--space-3); }
.scene-prep-picks .field__label { flex-basis: 100%; }
/* A fieldset won't shrink below its content unless told; the odds wrap in a narrow rail. */
.scene-plan-form__opening { display: grid; gap: var(--space-2); min-width: 0; }
.segmented--auto.scene-plan-form__odds { grid-auto-flow: row; grid-template-columns: repeat(auto-fit, minmax(4.5rem, 1fr)); }

/* Vex on the Harm card (pg. 30): four toggles like harm's, the response's line under the lit one. */
.vex { display: grid; gap: var(--space-2); margin-top: var(--space-3); }
.vex__label { margin: 0; font-size: 11px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--dim); }
.vex__toggles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.vex__does { margin: 0; font-size: 0.9rem; color: var(--grim); }
.vex__hint { margin: 0; }

/* Campaign settings: Characters and Optional rules, each its own section. */
.settings-form .fieldset { display: grid; gap: var(--space-2); min-width: 0; }
.settings-form__grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr)); gap: var(--space-1) var(--space-3); }
.settings-form__group + .settings-form__group { padding-top: var(--space-3); border-top: 1px solid var(--line-soft); }
.settings-form__rule { align-items: flex-start; }
.settings-form__rule small { color: var(--dim); font-weight: 400; }

/* A player's table rolls on their sheet: the shared pools. */
.table-rolls { display: grid; gap: var(--space-3); }

/* Expanded downtime's form (campaigns/downtimes/_actions): a character's action and a second
   one for selling a treasure, then only the boxes those actions need. */
.downtime-pick { display: grid; gap: var(--space-3); }
.downtime-pick__actions { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 12rem), 1fr)); gap: var(--space-3); }
.downtime-pick__extra { display: none; gap: var(--space-2); }
.downtime-pick:has(option[value="plan"]:checked) .downtime-pick__plan,
.downtime-pick:has(option[value="goal"]:checked) .downtime-pick__goal,
.downtime-pick:has(option[value="unwind"]:checked) .downtime-pick__unwind,
.downtime-pick:has(option[value="venture"]:checked) .downtime-pick__venture { display: grid; }
.downtime-pick__new-goal { display: none; grid-template-columns: minmax(0, 1fr) 8rem; gap: var(--space-3); }
.downtime-pick__goal:has(option[value="new"]:checked) .downtime-pick__new-goal { display: grid; }
/* Expanded downtime on the sheet's Table rules card: the plan-ahead thread and goal pools. */
.rule-pools__plan { display: grid; gap: var(--space-2); }
.rule-pools__plan p { margin: 0; }
.rule-pools__goals { display: grid; gap: var(--space-3); }
.rule-pools__subtitle { margin: 0; font-size: 1rem; }
.rule-pools__goal { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: var(--space-2) var(--space-3); }
.rule-pools__goal .pool-track { grid-column: 1 / -1; }
.rule-pools__goal form { grid-column: 1 / -1; justify-self: start; margin: 0; }
.rule-pools__goal-size { font-family: var(--font-dice); color: var(--muted); }

/* "Copy for an AI" (campaigns/briefs/show): the party as Markdown in an editable box. */
.brief__text { min-height: 18rem; font-family: var(--font-dice); font-size: 0.85rem; line-height: 1.5; resize: vertical; }
.brief__actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); }

/* Settings › Schedule: the rule's fields show for the cadence picked ("Which week" only monthly; none for only dates I add). */
.schedule-form__grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr)); gap: var(--space-3) var(--space-4); }
.schedule-form__week { display: none; }
.schedule-form:has(option[value="monthly"]:checked) .schedule-form__week { display: grid; }
.schedule-form:has(option[value="dates"]:checked) .schedule-form__rule { display: none; }

/* Coming up (campaigns/_coming_up): the next dates, skipped ones struck through, the GM's ⋯ on each. */
.coming-up { display: grid; gap: var(--space-2); }
.coming-up__title { margin: 0; font-size: 12px; font-weight: 500; letter-spacing: 0.08em; text-transform: uppercase; color: var(--dim); }
.coming-up__list { display: grid; gap: 2px; margin: 0; padding: 0; list-style: none; }
.coming-up__date { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-1) var(--space-3); min-height: var(--tap); padding: 0 0 0 var(--space-3); border-left: 2px solid var(--line); }
.coming-up__date--skipped { border-left-style: dashed; color: var(--dim); }
.coming-up__date--skipped .game-time { text-decoration: line-through; }
.coming-up__when { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-2); font-weight: 600; }
.coming-up__tag { font-size: 0.8rem; font-weight: 500; color: var(--dim); }
.coming-up__note { flex-basis: 100%; margin-top: -6px; font-size: 0.85rem; font-style: italic; color: var(--muted); }
.coming-up__more { position: relative; margin-left: auto; }
.coming-up__add { margin-left: 0; justify-self: start; }
.coming-up__toggle { width: var(--tap); padding: 0; list-style: none; }
.coming-up__toggle::-webkit-details-marker,
.coming-up__add-toggle::-webkit-details-marker { display: none; }
.coming-up__add-toggle { list-style: none; }
.coming-up__menu { position: absolute; z-index: 15; right: 0; top: calc(100% + 4px); display: grid; gap: var(--space-3); width: min(20rem, calc(100vw - 2rem)); padding: var(--space-3); border: 1px solid var(--line); border-radius: var(--radius-control); background: var(--surface); box-shadow: var(--shadow); }
.coming-up__add .coming-up__menu { right: auto; left: 0; }
.coming-up__menu .button_to,
.coming-up__menu .button { width: 100%; }
.coming-up__form + .coming-up__form { padding-top: var(--space-3); border-top: 1px solid var(--line-soft); }
.coming-up__fields { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-2); }
.gm-view__side .coming-up { padding: var(--space-4); border: 1px solid var(--line); border-radius: var(--radius-control); background: var(--surface); }

/* The next game: on the campaigns list's cards, and in the campaign page's hero. */
.next-game { font-size: 0.9rem; font-weight: 600; color: var(--ember); }
.next-game--skipped { color: var(--muted); font-weight: 500; }
.campaign-hero__soon { font-weight: 400; color: var(--muted); }
