/* ============================================================
   TYSTNAD Companion
   Palette: blood on ash. Black, red, gray.
   ============================================================ */

@font-face {
  font-family: "Cormorant Garamond";
  src: url("CormorantGaramond-Variable.woff2") format("woff2");
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Cormorant Garamond";
  src: url("CormorantGaramond-Variable.woff2") format("woff2");
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Cormorant Garamond";
  src: url("CormorantGaramond-Variable.woff2") format("woff2");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

:root {
  --ink: #0c0a0b;        /* background, near-black */
  --panel: #171416;      /* raised surfaces */
  --panel-hi: #201c1e;   /* pressed / active surfaces */
  --line: #2a2528;       /* hairlines */
  --bone: #cfc9c0;       /* primary text */
  --ash: #7d766f;        /* secondary text */
  --blood: #a11e24;      /* accent */
  --blood-bright: #d92b32; /* results, warnings */
  --ember-light: #d97a24;  /* HP warning: exactly 3 */
  --ember-strong: #b96a33; /* HP warning: exactly 2 */
  --success: #cfc9c0;    /* success stays bone: clinical, no celebration */
  --font-display: "Cormorant Garamond", Georgia, serif;
}

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

html { -webkit-text-size-adjust: 100%; background: #0c0a0b; touch-action: manipulation; }

body {
  background: transparent;
  color: var(--bone);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  min-height: 100vh;
  min-height: 100dvh;
  -webkit-tap-highlight-color: transparent;
  user-select: none;
  -webkit-user-select: none;
}

body::before {
  content: "";
  position: fixed;
  inset: 0;
  background: url("bg-pages.webp") center / cover no-repeat;
  z-index: -1;
}

.hidden { display: none !important; }

.screen {
  max-width: 480px;
  margin: 0 auto;
  padding: max(env(safe-area-inset-top), 20px) 18px calc(env(safe-area-inset-bottom) + 32px);
  display: flex;
  flex-direction: column;
  gap: 22px;
}

/* ============ INTRO ============ */

/* v99: the gate is the front door, so it wears the same face as the intro it stands in front
   of. Its states reuse .tl-state, .field and .tl-error rather than growing a second set. */
#screen-intro,
#screen-gate {
  min-height: 100dvh;
  justify-content: center;
  background-image: url("intro-bg.webp");
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
}

/* The logo sits above the fields, not centred with them, so the form starts near the thumb. */
.gate-screen .intro-logo-wrap { margin-bottom: 4px; }

/* v106, second half of the intro lift. Closing the gaps alone made the block SHORTER, and
   `justify-content: center` then pushed the logo 40px DOWN, the opposite of what was asked.
   Anchoring the intro to the top is what actually raises everything. The version note keeps
   its place at the foot, per Tomas: `margin-top: auto` holds it there while the rest rises.
   Scoped to #screen-intro so the gate, which shares the rule above, stays centred. */
#screen-intro { justify-content: flex-start; }

/* v107: Tomas asked for the logo 5mm lower and COMPANION 5mm higher. Only 2px separated the
   image BOX from the text, but the logo PNG carries 51px of transparent padding below its
   artwork and 65px above (measured off a canvas alpha scan, not guessed). So the move is paid
   for out of that dead space rather than by shrinking the logo: 19px of padding pushes the
   artwork down, and a negative top margin pulls COMPANION up into the transparent strip,
   leaving about 15px of real clearance under the sword. The compensating bottom margin keeps
   the buttons exactly where they were, since Tomas said the rest is fine.
   Scoped to #screen-intro: the gate shares .intro-logo-wrap and .brand-sub and must not move. */
#screen-intro .intro-logo-wrap { padding-top: 23px; gap: 0; }
#screen-intro .brand-sub { margin-top: -36px; margin-bottom: 19px; }
#screen-intro .intro-layout { flex: 1 1 auto; width: 100%; }
#intro-version-note { margin-top: auto; }

/* v106: Tomas asked for the logo 12mm higher and everything below it 15mm higher. Measured at
   375x812 there were only 35px of headroom above the logo against the 45px and 57px asked for,
   so a translate would have cropped the logo, worse on a 667px screen. He ruled the space comes
   out of the GAPS instead: the block ends up as high and as tight as intended, and nothing is
   pushed off the top. padding-top 30 to 4 and gap 8 to 2 lift the logo ~32px; .intro-layout's
   gap 28 to 4 lifts Companion and the buttons a further ~24px. */
.intro-logo-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding-top: 4px;
}

.intro-logo {
  max-width: 70%;
  height: auto;
  display: block;
}

.intro-layout {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
}

.intro-buttons {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.continue-sub {
  display: block;
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.18em;
  opacity: 0.75;
  margin-top: 4px;
}

/* ============ CREATION LOGO ============ */

.create-logo-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
}

.create-logo {
  max-width: 50%;
  height: auto;
  display: block;
}

/* ============ BRAND SUBLINE (shared) ============ */

.brand-sub {
  font-size: 1.4rem;
  font-weight: 600;
  letter-spacing: 0.5em;
  margin-right: -0.5em;
  text-transform: uppercase;
  color: var(--blood-bright);
}

.create-intro p {
  color: var(--ash);
  font-size: 0.9rem;
  line-height: 1.5;
  text-align: center;
}

/* ============ FIELDS ============ */

.field { display: flex; flex-direction: column; gap: 8px; }

.field-label {
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--ash);
}

.field-hint { font-size: 0.75rem; color: var(--ash); line-height: 1.4; }

/* v99: email and password join the list. The gate is the first screen anyone sees, and until
   they were named here its fields rendered as the browser's own white boxes, outside the
   palette entirely. */
input[type="text"], input[type="number"], input[type="email"], input[type="password"] {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 6px;
  color: var(--bone);
  font-size: 1.05rem;
  padding: 14px;
  width: 100%;
  outline: none;
}

input[type="number"] { -moz-appearance: textfield; appearance: textfield; }
input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }

input:focus { border-color: var(--blood); }

/* v95: browser default placeholders read as pre-filled values. Match the hint colour. */
input::placeholder { color: var(--ash); opacity: 1; }

.row-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }

/* ============ CLASS PICKER ============ */

.class-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }

.class-btn {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 6px;
  color: var(--bone);
  font-size: 0.85rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding: 16px 8px;
  cursor: pointer;
}

.class-btn.selected {
  border-color: var(--blood-bright);
  background: var(--panel-hi);
  color: var(--blood-bright);
}

/* ============ CREATION WIZARD (v61) ============ */

.wizard-progress {
  text-align: center;
  color: var(--ash);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  margin: 4px 0 14px;
}

.wizard-body { display: flex; flex-direction: column; gap: 14px; }

.wiz-title {
  font-family: var(--font-display);
  font-size: 1.5rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  color: var(--blood-bright);
  margin: 0;
}
.wiz-lead { color: var(--bone); line-height: 1.5; margin: 0; }
.wiz-note { color: var(--ash); line-height: 1.5; margin: 0; }

.wiz-class-grid { display: flex; flex-direction: column; gap: 10px; }
.wiz-class-card {
  display: flex;
  flex-direction: column;
  gap: 6px;
  text-align: left;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 14px 16px;
  cursor: pointer;
}
.wiz-class-card.selected { border-color: var(--blood-bright); background: var(--panel-hi); }
.wiz-class-name {
  color: var(--bone);
  font-size: 0.9rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
.wiz-class-card.selected .wiz-class-name { color: var(--blood-bright); }
.wiz-class-desc { color: var(--bone); font-size: 0.85rem; line-height: 1.4; }

.wiz-stats {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 14px 16px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.wiz-stats-line { color: var(--bone); font-size: 0.9rem; margin: 0; line-height: 1.5; }
.wiz-stats-skills { display: flex; flex-wrap: wrap; gap: 6px; }
.wiz-skill-chip {
  color: var(--bone);
  font-size: 0.75rem;
  letter-spacing: 0.04em;
  border: 1px solid var(--line);
  border-radius: 4px;
  padding: 4px 8px;
}
.wiz-skill-chip.core { color: var(--blood-bright); border-color: var(--blood); }

.wiz-field { display: flex; flex-direction: column; gap: 6px; }
.wiz-field-label { color: var(--bone); font-size: 0.85rem; line-height: 1.4; }
.wiz-input {
  width: 100%;
  box-sizing: border-box;
  padding: 10px 12px;
  font-size: 1rem;
}

.wiz-section-label {
  color: var(--blood-bright);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  margin: 6px 0 0;
}
.wiz-opt-grid { display: flex; flex-direction: column; gap: 8px; }
.wiz-opt {
  text-align: left;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 6px;
  color: var(--bone);
  font-size: 0.9rem;
  min-height: 44px;
  padding: 10px 14px;
  cursor: pointer;
}
.wiz-opt.selected { border-color: var(--blood-bright); background: var(--panel-hi); color: var(--blood-bright); }

.wiz-roll-btn { align-self: center; }
.wiz-wealth-result { text-align: center; color: var(--bone); font-size: 1.05rem; margin: 0; }

.wiz-summary {
  display: flex;
  flex-direction: column;
  gap: 8px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 14px 16px;
}
.wiz-sum-row { display: flex; justify-content: space-between; gap: 12px; }
.wiz-sum-label { color: var(--ash); font-size: 0.82rem; flex-shrink: 0; }
.wiz-sum-value { color: var(--bone); font-size: 0.9rem; text-align: right; }
.wiz-sum-qa { display: flex; flex-direction: column; gap: 2px; padding-top: 8px; margin-top: 2px; border-top: 1px solid var(--line); }
.wiz-sum-q { color: var(--ash); font-size: 0.82rem; line-height: 1.35; }
.wiz-sum-a { color: var(--bone); font-size: 0.9rem; line-height: 1.4; }

.wizard-nav { display: flex; gap: 10px; margin-top: 18px; }
#wiz-back { flex-shrink: 0; }
#wiz-next { flex: 1; }
#wiz-next:disabled { opacity: 0.4; }

/* ============ SKILL EDITORS (creation) ============ */

.skill-editor {
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 10px 12px;
  margin-bottom: 8px;
}

.skill-editor-name { font-size: 0.92rem; font-weight: 600; }

.stepper { display: flex; align-items: center; gap: 4px; }

.stepper-large { gap: 10px; }

.stepper-large .step-btn { width: 60px; height: 60px; font-size: 1.5rem; }

.stepper-large .step-value { min-width: 80px; font-size: 2rem; }

/* v105: was 42px, two under the rule, on the level, max-HP and Defense steppers. v103 had
   corrected only its own new .roll-step copies; this settles the shared class and that
   scoped override is gone as redundant. */
.step-btn {
  background: transparent;
  border: 1px solid var(--ash);
  border-radius: 6px;
  color: var(--bone);
  font-size: 1.15rem;
  width: 44px;
  height: 44px;
  cursor: pointer;
  line-height: 1;
}

.step-btn:active { background: var(--blood); }

.step-value {
  min-width: 52px;
  text-align: center;
  font-size: 1.05rem;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
}

/* ============ PRIMARY / GHOST / DANGER BUTTONS ============ */

.primary-btn {
  background: var(--blood);
  border: none;
  border-radius: 6px;
  color: #f2ede6;
  font-family: var(--font-display);
  font-size: 0.95rem;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  padding: 18px;
  cursor: pointer;
  margin-top: 6px;
}

.primary-btn.slim { padding: 14px 40px; margin-top: 0; }

.primary-btn:disabled { background: var(--panel-hi); color: var(--ash); }

/* v105: 36px against a 44px rule, on every screen in the app, since long before v101 made it
   visible by adding a sixth control to the intro. The vertical padding carries it rather than
   a display change, because .ghost-btn is worn by anchors as well as buttons (the Table Link
   link-outs) and switching those to a flex box would move their widths. */
.ghost-btn {
  background: transparent;
  border: 1px solid var(--line);
  border-radius: 6px;
  color: var(--ash);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  padding: 14px 16px;
  min-height: 44px;
  cursor: pointer;
}

.danger-btn {
  background: var(--blood);
  border: none;
  border-radius: 6px;
  color: #f2ede6;
  font-size: 0.8rem;
  font-weight: 800;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  padding: 14px 22px;
  cursor: pointer;
}

/* ============ VITALS RESTRUCTURE ============ */

.def-init-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
}

.chip-hint {
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ash);
  margin-top: 2px;
}

/* ============ SKILLS SECTION ============ */

.skills-section {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

/* ============ SHEET ============ */

.sheet-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  border-bottom: 1px solid var(--line);
  padding-bottom: 14px;
}

.sheet-head-left { display: flex; align-items: center; gap: 2px; min-width: 0; }

.back-btn {
  background: transparent;
  border: none;
  color: var(--ash);
  font-size: 1.8rem;
  line-height: 1;
  min-width: 44px;
  min-height: 44px;
  padding: 4px 8px 4px 0;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: flex-start;
  flex-shrink: 0;
}

.back-btn:active { color: var(--bone); }

.sheet-head h2 {
  font-family: var(--font-display);
  font-size: 1.5rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  word-break: break-word;
}

.sheet-class {
  font-family: var(--font-display);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--blood-bright);
  margin-top: 3px;
}

/* ============ VITALS ============ */

.def-block {
  background: var(--panel);
  border: 1px solid var(--line);
  clip-path: polygon(8px 0%, calc(100% - 8px) 0%, 100% 8px, 100% calc(100% - 8px), calc(100% - 8px) 100%, 8px 100%, 0% calc(100% - 8px), 0% 8px);
  padding: 14px 16px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.def-block {
  align-items: center;
  justify-content: center;
  min-width: 96px;
  color: var(--bone);
  font-family: inherit;
  cursor: pointer;
}

.def-block:active { background: var(--panel-hi); border-color: var(--blood); }

.vital-label {
  font-family: var(--font-display);
  font-size: 1.5rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--blood-bright);
}

.hp-controls { display: flex; align-items: center; gap: 6px; }   /* v105, see .hp-compact-strip */

.hp-btn {
  background: var(--panel-hi);
  border: 1px solid var(--line);
  border-radius: 8px;
  color: var(--bone);
  font-size: 1.2rem;
  width: 44px;
  height: 44px;
  cursor: pointer;
  flex-shrink: 0;
  line-height: 1;
}

.hp-btn:active { background: var(--blood); }

.hp-readout {
  font-family: var(--font-display);
  font-size: 1.8rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  text-align: center;
  display: flex;
  align-items: baseline;
  justify-content: center;
}

/* v116: the last of the 44px tap-target flags. This one could not be solved the way the others
   were, because the HP strip has 2px of spare width at 375px and this button needed 13 more:
   widening it in the flow would have put the strip back over the screen, which is the defect
   v105 fixed.

   So the HIT AREA grows and the LAYOUT does not. Padding enlarges the box from 31x34 to 44x44
   and equal negative margins cancel it out, so every neighbour stays exactly where it was.
   The padding is asymmetric on purpose: the extra width goes LEFT, over the current-HP number,
   which is text and not a control. Only 3px go right, which lands inside the 6px gap and never
   reaches the HP + button, the most-tapped control on the screen.

   The arithmetic took two corrections, both caught by measuring rather than by reading the
   rule. First: the glyph box is 23px, not the 31px it measured, because 31 already included
   its own 4px each side. Second, and the one that matters: **each margin must cancel only what
   its own padding ADDED, not the whole padding.** Over-cancelling pulled the readout from 72px
   to 64px and moved the HP + button with it, which is exactly the layout shift this technique
   exists to avoid. Left padding 4 to 17 adds 13, so margin-left is -13; right padding is left
   at 4 and its margin at 0; vertical 6 to 12 adds 6 each side, so margins are -6. */
button.hp-max {
  background: none;
  border: none;
  font-family: var(--font-display);
  font-size: 1.1rem;
  font-weight: 600;
  color: var(--ash);
  cursor: pointer;
  padding: 12px 4px 12px 17px;
  margin: -6px 0 -6px -13px;
  font-variant-numeric: tabular-nums;
}

button.hp-max:active { color: var(--blood-bright); }

#hp-current { color: var(--bone); }
#hp-current.hp-t3 { color: var(--ember-light); }
#hp-current.hp-t2 { color: var(--ember-strong); }
#hp-current.hp-t1 { color: var(--blood-bright); }

.def-die { font-size: 1.7rem; font-weight: 900; }

/* ============ SKILL LIST ============ */

.skill-list { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }

.skill-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: var(--panel);
  border: 1px solid var(--line);
  clip-path: polygon(8px 0%, calc(100% - 8px) 0%, 100% 8px, 100% calc(100% - 8px), calc(100% - 8px) 100%, 8px 100%, 0% calc(100% - 8px), 0% 8px);
  color: var(--bone);
  padding: 11px 12px;
  font-size: 0.9rem;
  cursor: pointer;
  width: 100%;
  text-align: left;
}

.skill-row:active { background: var(--panel-hi); border-color: var(--blood); }

.skill-row .skill-name { font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; font-size: 0.82rem; }

.skill-row .skill-die {
  font-weight: 900;
  font-size: 1.05rem;
  color: var(--ash);
  font-variant-numeric: tabular-nums;
}

.skill-row .skill-die.core { color: var(--bone); }

.foot-note { text-align: center; font-size: 0.75rem; color: var(--ash); letter-spacing: 0.06em; }

/* Saves (v71): Body/Mind/Spirit map to Athletics/Awareness/Presence */
.saves-row { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 8px; }
.save-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 6px;
  min-height: 56px;
  padding: 8px 4px;
  cursor: pointer;
}
.save-btn:active { background: var(--panel-hi); border-color: var(--blood); }
/* v106: the skill name came off the chip, so the save name takes the room it left. */
.save-name {
  color: var(--bone);
  font-size: 1rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.version-note { text-align: center; font-size: 0.75rem; color: var(--ash); letter-spacing: 0.18em; text-transform: uppercase; pointer-events: none; }
#version-note { position: fixed; bottom: calc(68px + env(safe-area-inset-bottom)); left: 0; right: 0; }
#intro-version-note { color: rgba(207, 201, 192, 0.6); }
/* v101: all four intro buttons carry the bone edge. Only the first two did, which read as an
   unfinished screen rather than as a hierarchy. Tomas ruled the even treatment. */
#btn-new-explorer, #btn-import-toggle, #btn-backup-intro,
#btn-join-table, #btn-how-to-play { border-color: var(--bone); color: var(--bone); }
#btn-export { font-family: var(--font-display); }
.shell-screen .field-label {
  font-family: var(--font-display);
  font-size: 1.5rem;
  font-weight: 600;
  color: var(--blood-bright);
  letter-spacing: 0.06em;
}

/* ============ CAST SPELL (full-width standalone) ============ */

.cast-btn {
  background: var(--panel);
  border: 1px solid var(--blood);
  border-radius: 8px;
  color: var(--blood-bright);
  font-family: var(--font-display);
  font-size: 0.9rem;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  padding: 14px;
  cursor: pointer;
  width: 100%;
}

.cast-btn:active { background: var(--panel-hi); border-color: var(--blood-bright); }

/* ============ INVENTORY ============ */

.inv-section {
  background: var(--panel);
  border: 1px solid var(--line);
  clip-path: polygon(8px 0%, calc(100% - 8px) 0%, 100% 8px, 100% calc(100% - 8px), calc(100% - 8px) 100%, 8px 100%, 0% calc(100% - 8px), 0% 8px);
  padding: 14px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

/* Title takes its own line so the LP total + burden badge never clip at 375px */
.inv-head { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 10px; }
.inv-head .field-label { flex: 1 1 100%; }

.inv-total {
  margin-left: auto;
  font-size: 0.9rem;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
}

.inv-badge {
  font-size: 0.75rem;
  font-weight: 800;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  border: 1px solid var(--line);
  border-radius: 4px;
  padding: 4px 8px;
  color: var(--ash);
}

.inv-badge.heavy { color: var(--bone); border-color: var(--bone); }

.inv-badge.overloaded { color: var(--blood-bright); border-color: var(--blood); }

.inv-total.overmax { color: var(--blood-bright); }

.inv-item {
  display: flex;
  align-items: center;
  gap: 10px;
  border-bottom: 1px solid var(--line);
  padding: 8px 2px;
}

.inv-item-name { font-size: 0.9rem; flex: 1; word-break: break-word; }

.inv-item-lp {
  font-size: 0.85rem;
  font-weight: 800;
  color: var(--ash);
  font-variant-numeric: tabular-nums;
}

.inv-del {
  background: var(--panel-hi);
  border: 1px solid var(--line);
  border-radius: 6px;
  color: var(--ash);
  font-size: 1rem;
  width: 34px;
  height: 34px;
  cursor: pointer;
  line-height: 1;
  flex-shrink: 0;
}

.inv-del:active { background: var(--blood); color: #f2ede6; }

.inv-add { display: flex; gap: 8px; }

/* In-flow list (expands the card downward). Absolute positioning would be clipped by
   the .inv-section chamfer clip-path, so the picker pushes the coins row down instead. */
.inv-suggest {
  margin-top: 6px;
  max-height: 236px;
  overflow-y: auto;
  background: var(--panel-hi);
  border: 1px solid var(--blood);
  border-radius: 6px;
}
.inv-suggest-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  min-height: 44px;
  padding: 8px 12px;
  cursor: pointer;
  border-bottom: 1px solid var(--line);
}
.inv-suggest-item:last-child { border-bottom: none; }
.inv-suggest-item:active { background: var(--panel-hi); }
.inv-suggest-name { color: var(--bone); font-size: 0.9rem; }
.inv-suggest-lp {
  color: var(--bone);
  font-size: 0.82rem;
  font-variant-numeric: tabular-nums;
  flex-shrink: 0;
}

.inv-add input[type="text"] { flex: 1; padding: 10px 12px; font-size: 1rem; }

.inv-add input[type="number"] { width: 70px; padding: 10px 8px; font-size: 1rem; text-align: center; }

#inv-add-btn {
  background: var(--panel-hi);
  border: 1px solid var(--line);
  border-radius: 6px;
  color: var(--bone);
  font-size: 1.2rem;
  width: 46px;
  cursor: pointer;
  flex-shrink: 0;
}

#inv-add-btn:active { background: var(--blood); }

.inv-coins { display: flex; align-items: center; gap: 10px; }

.inv-coins-label {
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--ash);
}

.inv-coins input { width: 110px; padding: 10px 12px; font-size: 1rem; text-align: center; }

.inv-coins-lp { font-size: 0.8rem; color: var(--ash); font-variant-numeric: tabular-nums; }

.inv-hint { font-size: 0.75rem; color: var(--blood-bright); line-height: 1.4; }

/* ============ LOADOUT OVERLAY ============ */

.loadout-group { display: flex; flex-direction: column; gap: 8px; width: 100%; max-width: 320px; }

.weapon-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }

#init-preview { font-variant-numeric: tabular-nums; }

/* ============ CAST WARNING ============ */

.cast-warning {
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  color: var(--blood-bright);
  text-align: center;
  max-width: 280px;
  line-height: 1.5;
}

/* ============ DEATH ROLL ============ */

.death-btn {
  background: var(--blood);
  border: 1px solid var(--blood-bright);
  border-radius: 8px;
  color: #f2ede6;
  font-family: var(--font-display);
  font-size: 1rem;
  font-weight: 700;
  letter-spacing: 0.34em;
  text-transform: uppercase;
  padding: 20px;
  cursor: pointer;
  width: 100%;
}

.death-btn:active { background: var(--blood-bright); }

.danger-btn.big { padding: 18px 64px; font-size: 1rem; letter-spacing: 0.3em; }

#overlay-result { background: #0c0a0b; }
#overlay-attack { background: #0c0a0b; padding-bottom: calc(env(safe-area-inset-bottom) + 88px); }
#overlay-defense { background: #0c0a0b; padding-bottom: calc(env(safe-area-inset-bottom) + 88px); }

.def-armor-note {
  font-size: 0.75rem;
  color: var(--ash);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  margin-top: 4px;
}
#overlay-result.death-flood { background: rgba(38, 6, 8, 0.97); }

.verdict-death {
  font-size: 1.8rem;
  font-weight: 900;
  letter-spacing: 0.5em;
  margin-right: -0.5em;
  color: var(--blood-bright);
}

.survive-note {
  font-size: 0.85rem;
  font-weight: 800;
  letter-spacing: 0.28em;
  margin-right: -0.28em;
  text-transform: uppercase;
  color: var(--bone);
}

/* ============ OVERLAYS ============ */

.overlay {
  position: fixed;
  inset: 0;
  background: rgba(12, 10, 11, 0.96);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 26px;
  padding: 24px;
  z-index: 10;
}

/* v106: picking Ranged in Attack or Defend reveals the range and cover block and pushes the
   content past the viewport. The overlay is `position: fixed` with `justify-content: center`
   and NO overflow, and centred overflow is unreachable at BOTH ends, so the threat buttons
   below and the mode buttons above were simply gone. Auto margins centre it while it fits and
   yield to scrolling when it does not, which `justify-content: center` cannot do.
   Scoped to these two overlays deliberately: #overlay-result carries the death flood, and the
   flood is the app's one sacred visual. */
#overlay-attack,
#overlay-defense {
  justify-content: flex-start;
  overflow-y: auto;
  overscroll-behavior: contain;
}
#overlay-attack > *:first-child,
#overlay-defense > *:first-child { margin-top: auto; }
#overlay-attack > *:last-child,
#overlay-defense > *:last-child { margin-bottom: auto; }

.overlay-skill {
  font-size: 1rem;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.overlay-skill span { color: var(--bone); margin-left: 8px; }

.overlay-hint { max-width: 260px; text-align: center; }

/* Loadout overlay (Initiative): top instruction + bottom contribution line */
.overlay-lead {
  color: var(--bone);
  font-size: 1rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-align: center;
  line-height: 1.4;
  max-width: 300px;
}
.init-contrib {
  color: var(--bone);
  font-size: 1rem;
  letter-spacing: 0.04em;
  text-align: center;
}
.init-contrib #init-preview {
  color: var(--bone);
  font-weight: 800;
  font-size: 1.15rem;
  font-variant-numeric: tabular-nums;
  margin-left: 6px;
}

.diff-buttons { display: flex; flex-direction: column; gap: 12px; width: 100%; max-width: 320px; }

.diff-btn {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 8px;
  color: var(--bone);
  font-size: 1rem;
  font-weight: 800;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  padding: 20px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.diff-btn span { color: var(--bone); font-variant-numeric: tabular-nums; }

.diff-btn:active { background: var(--panel-hi); border-color: var(--blood); }

/* ============ RESULT ============ */

#overlay-result { gap: 10px; }

.result-context {
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ash);
}

.result-number {
  font-family: var(--font-display);
  font-size: clamp(6rem, 34vw, 11rem);
  font-weight: 700;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

.result-number.rolling { animation: flicker 0.07s steps(1) infinite; }

@keyframes flicker { 50% { opacity: 0.35; } }

@media (prefers-reduced-motion: reduce) {
  .result-number.rolling { animation: none; }
}

.result-verdict {
  min-height: 120px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.verdict-success {
  font-size: 1.6rem;
  font-weight: 900;
  letter-spacing: 0.5em;
  margin-right: -0.5em;
  color: var(--success);
}

.verdict-fail {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
}

.verdict-skull { display: block; height: 22vh; max-width: 90vw; width: auto; }
.verdict-skull--death { height: 60vh; }

.success-text {
  font-family: var(--font-display);
  font-size: 0.75rem;
  font-variant: small-caps;
  letter-spacing: 0.2em;
  color: var(--ash);
  text-align: center;
  display: block;
  margin-top: 4px;
}

.fail-by {
  font-size: 0.85rem;
  font-weight: 800;
  letter-spacing: 0.28em;
  margin-right: -0.28em;
  text-transform: uppercase;
  color: var(--bone);
}

.def-damage {
  font-size: 1.7rem;
  font-weight: 800;
  letter-spacing: 0.28em;
  margin-right: -0.28em;
  text-transform: uppercase;
  color: var(--bone);
}

.result-dismiss {
  font-size: 0.75rem;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--ash);
  margin-top: 18px;
}

/* ============ CONFIRM ============ */

.confirm-text {
  font-size: 1rem;
  line-height: 1.6;
  text-align: center;
  max-width: 300px;
  color: var(--bone);
}

.confirm-buttons { display: flex; gap: 14px; }

/* ============ IMPORT ============ */

.import-row {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
}

.import-or {
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--ash);
}

.import-error {
  font-size: 0.78rem;
  color: var(--blood-bright);
  text-align: center;
  letter-spacing: 0.06em;
}

.import-paste-area {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 6px;
  color: var(--bone);
  font-family: monospace;
  font-size: 0.75rem;
  height: 100px;
  outline: none;
  padding: 10px;
  resize: none;
  width: 100%;
  user-select: text;
  -webkit-user-select: text;
}

.import-paste-area:focus { border-color: var(--blood); }

/* ============ EXPORT OVERLAY ============ */

.export-json {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 6px;
  color: var(--ash);
  font-family: monospace;
  font-size: 0.75rem;
  line-height: 1.5;
  max-height: 38vh;
  overflow-y: auto;
  padding: 12px;
  white-space: pre;
  width: 100%;
  max-width: 360px;
  user-select: text;
  -webkit-user-select: text;
}

.export-copied {
  font-size: 0.78rem;
  font-weight: 800;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--success);
}

/* ============ EXPLORER COMPACT HP STRIP ============ */

.hp-compact-strip {
  background: var(--panel);
  border: 1px solid var(--line);
  clip-path: polygon(8px 0%, calc(100% - 8px) 0%, 100% 8px, 100% calc(100% - 8px), calc(100% - 8px) 100%, 8px 100%, 0% calc(100% - 8px), 0% 8px);
  /* v105: the strip asked for 350px of content inside 311px at 375px, so the HP + button hung
     about 8px off the right edge of the screen and the whole document scrolled sideways. The
     buttons are load-bearing and stay at 44px; the padding and the gaps give up the space
     instead. wrap is the safety valve: at 375px it never engages, and on anything narrower the
     strip becomes two rows rather than putting a control out of reach. */
  padding: 8px;
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 8px 6px;
}

.hp-label-large {
  font-family: var(--font-display);
  font-size: 2rem;
  font-weight: 700;
  color: var(--blood);
  line-height: 1;
  flex-shrink: 0;
}

.hp-readout-compact {
  font-size: 2.6rem;
}

.hp-left { display: flex; align-items: center; gap: 6px; }   /* v105, see .hp-compact-strip */

.hp-recover-btn {
  min-width: 44px;
  min-height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--panel-hi);
  border: 1px solid var(--line);
  color: var(--bone);
  font-size: 1.35rem;
  line-height: 1;
  cursor: pointer;
  clip-path: polygon(6px 0%, calc(100% - 6px) 0%, 100% 6px, 100% calc(100% - 6px), calc(100% - 6px) 100%, 6px 100%, 0% calc(100% - 6px), 0% 6px);
}
.hp-recover-btn:active { background: var(--blood); color: var(--bone); }

.recovery-btn { margin-top: 4px; }

.recovery-result {
  font-size: 0.95rem;
  color: var(--bone);
  text-align: center;
  margin: 4px 0 10px;
}

/* ============ ATTACK OVERLAY ============ */

.atk-section-label {
  font-family: var(--font-display);
  font-size: 1.4rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--blood-bright);
  margin: 0.6rem 0 0;
  text-align: center;
}

/* ============ ATTACK MOMENTUM SELECTOR ============ */

.momentum-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 12px;
  width: 100%;
  max-width: 320px;
}

.bonus-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 12px;
  width: 100%;
  max-width: 320px;
}

/* ============ RANGED COMBAT (v74) ============ */

.mode-grid {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: 12px;
  width: 100%;
  max-width: 320px;
}

.mode-grid .class-btn {
  font-size: 0.75rem;
  letter-spacing: 0.08em;
  padding: 14px 4px;
  min-height: 44px;
}

.ranged-block {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  width: 100%;
}

.melee-toggle {
  width: 100%;
  max-width: 320px;
  font-size: 0.75rem;
  letter-spacing: 0.08em;
  padding: 14px 8px;
  min-height: 44px;
}

.ranged-line {
  font-size: 0.85rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--bone);
  text-align: center;
  margin: 2px 0 0;
}

.diff-btn.locked-out {
  opacity: 0.35;
  cursor: default;
}

/* ============ AMMUNITION (v75) ============ */

/* Warning, so it follows the .cast-warning precedent rather than the bone data rule. */
.ammo-warn {
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  color: var(--blood-bright);
  text-align: center;
  max-width: 280px;
  line-height: 1.5;
  margin: 2px 0 0;
}

/* Bundle counts are data, so bone per Law 1. */
.ammo-carried {
  font-size: 0.95rem;
  color: var(--bone);
  text-align: center;
  margin: 4px 0 10px;
}

/* ============ ATTACK RESULT DISPLAY ============ */

.attack-result {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
}

.strike-hit {
  font-family: var(--font-display);
  font-size: clamp(2rem, 11.5vw, 4rem);
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--bone);
  display: block;
  text-align: center;
  max-width: 90vw;
}

.damage-chain {
  font-size: 0.85rem;
  color: var(--ash);
  font-variant-numeric: tabular-nums;
}

.damage-explodes {
  font-size: 2rem;
  color: var(--blood-bright);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  font-family: var(--font-display);
  font-weight: 700;
}

.roll-again-btn {
  width: 100%;
  min-height: 44px;
  background: var(--blood);
  color: var(--bone);
  border: none;
  font-family: var(--font-display);
  font-size: 1rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  cursor: pointer;
  clip-path: polygon(8px 0%, 100% 0%, 100% 100%, 0% 100%, 0% 8px);
  margin-top: 4px;
}

.roll-damage-btn {
  width: 100%;
  min-height: 44px;
  background: var(--blood);
  color: var(--bone);
  border: none;
  font-family: var(--font-display);
  font-size: 1rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  cursor: pointer;
  clip-path: polygon(8px 0%, 100% 0%, 100% 100%, 0% 100%, 0% 8px);
  margin-top: 4px;
}

.wake-btn { margin-top: 16px; }

/* ============ ACT 3 PROMPT CARD ============ */

.prompt-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.4rem;
}

.prompt-success-text {
  font-family: var(--font-display);
  font-size: 1.6rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--bone);
  text-align: center;
  margin-bottom: 0.4rem;
}

.prompt-total {
  font-family: var(--font-display);
  font-size: clamp(7rem, 42vw, 14rem);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--bone);
  line-height: 1;
}

.prompt-damage-label {
  font-family: var(--font-display);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--blood-bright);
}

/* Act 3: TAP TO CONTINUE anchored at bottom, prompt card centers freely */
#overlay-result.overlay--act3 .result-dismiss {
  position: absolute;
  bottom: 88px;
  left: 0;
  right: 0;
  text-align: center;
}

/* Action state: ROLL DAMAGE / ROLL AGAIN anchored to thumb zone */
#overlay-result.overlay--action .roll-damage-btn,
#overlay-result.overlay--action .roll-again-btn {
  position: absolute;
  bottom: 88px;
  left: 24px;
  right: 24px;
  width: auto;
}

/* Defense failure: DISMISS above TAKE IT, ash text, no fill */
.def-dismiss-btn {
  background: none;
  border: none;
  color: var(--ash);
  font-size: 0.75rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  min-height: 44px;
  cursor: pointer;
}

#overlay-result.overlay--action .def-dismiss-btn {
  position: absolute;
  bottom: 136px;
  left: 24px;
  right: 24px;
}

/* ============ UPDATE BANNER (v85) ============ */

/* v97: the banners used to be individually fixed to the top, so any two of them showing at
   once landed on the same pixels. The Table Link notice made that a three-way. They now
   share one fixed column, which owns the safe-area inset, and each banner is an ordinary
   block inside it. */
.banner-stack {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 100;
  display: flex;
  flex-direction: column;
  padding-top: env(safe-area-inset-top);
  pointer-events: none;   /* an empty stack must never swallow a tap on the screen below */
}

.banner-stack > * { pointer-events: auto; }

.update-banner {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  padding: 10px 16px;
  background: var(--panel);
  border-bottom: 1px solid var(--blood);
}

/* v93: the save-failure banner reuses the update banner's geometry and differs only in
   weight. A pending update is news; a character that is not being written to disk is a
   warning, so it carries the blood border on all sides rather than a thin bottom rule. */
.save-banner {
  border: 1px solid var(--blood);
  background: var(--panel-hi);
}

.update-banner-text {
  font-size: 0.8rem;
  letter-spacing: 0.06em;
  color: var(--bone);
}

.update-reload-btn {
  min-height: 44px;
  padding: 0 18px;
  background: var(--blood);
  color: var(--bone);
  border: none;
  font-family: var(--font-display);
  font-size: 0.9rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  cursor: pointer;
}

/* ============ DICE HISTORY (v83) ============ */

.history-list {
  width: 100%;
  max-width: 340px;
  max-height: 55vh;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.history-row {
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 8px 2px;
  border-bottom: 1px solid var(--line);
}

.history-left { flex: 1 1 auto; min-width: 0; }

/* The roll's context. Data, so bone per Law 1. */
.history-line {
  display: block;
  font-size: 0.8rem;
  letter-spacing: 0.04em;
  color: var(--bone);
}

.history-result {
  flex: 0 0 auto;
  font-family: var(--font-display);
  font-size: 1.3rem;
  font-weight: 700;
  color: var(--bone);
  font-variant-numeric: tabular-nums;
}

.history-outcome {
  flex: 0 0 auto;
  min-width: 5.5em;
  text-align: right;
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ash);
}

.history-empty {
  font-size: 0.85rem;
  color: var(--ash);
  text-align: center;
  padding: 18px 0;
}

/* ============ ACTION ECONOMY CARD (v78) ============ */

.action-card { width: 100%; margin-top: 10px; }

/* v106: Attack and Defend are the two most-tapped buttons in play and each was taking a full
   width for one word. Side by side, and larger, since the row buys the room. */
.combat-pair { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.combat-pair .combat-main { margin: 0; font-size: 1.15rem; }

/* Two columns for the action list. The rows are a name and a short description, so they pack
   without wrapping badly, and the tier headings stay full width above their own group. */
/* Compounded with .rules-topic-body deliberately. That class sets display:flex and sits LATER
   in this file, so at equal specificity it won and the grid was inert: every row rendered in
   one column while getComputedStyle still reported "1fr 1fr". Found by measuring the left
   edges rather than by reading the declaration. */
.rules-topic-body.action-grid {
  display: block;
  column-count: 2;
  column-gap: 14px;
}
.action-grid .action-row { break-inside: avoid; }
/* v109: the headings do NOT span. Tomas chose the continuous two-column flow over the banded
   one: the list runs down column one and continues at the top of column two, which packs far
   tighter than restarting the columns at every heading.

   `break-after: avoid` is what makes that safe. Without it a heading can be left stranded at
   the foot of a column with its first action at the top of the next one, which is the failure
   mode that spanning was protecting against. This keeps a heading welded to what follows it.

   The first heading loses its top margin so column one starts level with column two, whose
   first item is an ordinary row with no margin. That 12px was the whole misalignment. */
.action-grid .action-tier,
.action-grid .action-rule {
  break-after: avoid;
  break-inside: avoid;
}
.action-grid > .action-tier:first-child { margin-top: 0; }

.action-tier {
  font-family: var(--font-display);
  font-size: 1.5rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  color: var(--blood-bright);
  margin: 12px 0 0;
}

/* The per-turn budget is the most important line in each tier, so bone per Law 3.
   The improvised note below stays ash: it is GM context, not a rule you spend against. */
.action-rule {
  font-size: 0.8rem;
  letter-spacing: 0.06em;
  color: var(--bone);
  margin: 2px 0 6px;
}

.action-row { margin: 0 0 8px; line-height: 1.45; }

.action-name {
  display: block;
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--bone);
}

.action-desc {
  display: block;
  font-size: 0.85rem;
  color: var(--bone);
}

.action-improvised {
  font-size: 0.8rem;
  color: var(--ash);
  line-height: 1.5;
  margin-top: 12px;
}

/* ============ DOUBLE ATTACK (v77) ============ */

.melee-toggle.locked-out {
  opacity: 0.35;
  cursor: default;
}

#overlay-result.overlay--action .second-attack-btn {
  position: absolute;
  bottom: 88px;
  left: 24px;
  right: 24px;
  width: auto;
}

/* ============ SHIELD REROLL (v76) ============ */

/* Outlined, so it never competes with the solid TAKE IT fill below it. */
.def-shield-btn {
  width: 100%;
  min-height: 44px;
  background: none;
  border: 1px solid var(--blood);
  color: var(--bone);
  font-family: var(--font-display);
  font-size: 1rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  cursor: pointer;
  margin-top: 4px;
}

.shield-note {
  display: block;
  font-size: 0.75rem;
  letter-spacing: 0.06em;
  color: var(--bone);
  text-align: center;
}

#overlay-result.overlay--action .def-shield-btn {
  position: absolute;
  bottom: 136px;
  left: 24px;
  right: 24px;
  width: auto;
}

#overlay-result.overlay--action .shield-note {
  position: absolute;
  bottom: 186px;
  left: 24px;
  right: 24px;
}

/* DISMISS clears the shield button and its note when both are present. */
#overlay-result.overlay--action .verdict-fail.has-shield .def-dismiss-btn {
  bottom: 210px;
}

/* COMBAT tab readiness line. Ember marks the spent state, matching the HP threshold cue. */
.shield-state {
  font-size: 0.75rem;
  letter-spacing: 0.06em;
  color: var(--bone);
  text-align: center;
  margin: 2px 0 0;
}

.shield-state.shield-spent { color: var(--ember-light); }

/* ============ EXPEDITION SECTION ============ */

.expedition-section {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.role-chips {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}

.role-chip {
  background: transparent;
  border: 1px solid var(--ash);
  border-radius: 6px;
  color: var(--bone);
  cursor: pointer;
  font-family: inherit;
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  min-height: 44px;
  padding: 0 14px;
  text-transform: uppercase;
  flex: 1;
}

.role-chip.active {
  border-color: var(--blood);
  color: var(--blood-bright);
}

.role-chip:active { background: var(--panel-hi); }

.effort-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
}

.effort-btn {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 8px;
  color: var(--bone);
  cursor: pointer;
  font-family: var(--font-display);
  font-size: 0.78rem;
  font-weight: 600;
  height: 44px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
}

.effort-btn:active { background: var(--panel-hi); border-color: var(--blood); }

/* ============ SKILL TICKS ============ */

.skill-row { position: relative; }

.skill-row.ticked::after {
  content: "✓";
  color: var(--bone);
  font-size: 0.75rem;
  font-weight: 900;
  position: absolute;
  top: 4px;
  right: 6px;
  line-height: 1;
}

/* ============ CLEAR TICKS CONTROL ============ */

.clear-ticks-btn {
  background: none;
  border: none;
  color: var(--ash);
  cursor: pointer;
  font-family: inherit;
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  min-height: 44px;
  padding: 0;
  text-align: left;
  text-decoration: underline;
  text-transform: uppercase;
}

/* ============ FORAGE OVERLAY ============ */

.forage-die-note {
  font-size: 0.75rem;
  color: var(--ash);
  text-align: center;
}

/* ============ EFFORT RESULT DISPLAY ============ */

.effort-result-exposed { color: var(--blood-bright); font-weight: 800; letter-spacing: 0.12em; text-transform: uppercase; }
.effort-result-label { color: var(--bone); font-weight: 800; letter-spacing: 0.12em; text-transform: uppercase; }
.effort-result-margin { color: var(--ash); font-size: 0.8rem; }

/* ============ SHELL + TAB ARCHITECTURE (v18) ============ */

.shell-screen {
  padding-bottom: calc(env(safe-area-inset-bottom) + 96px);
}

.tab-panel {
  display: flex;
  flex-direction: column;
  gap: 22px;
}

.tab-bar-wrapper {
  position: fixed;
  bottom: calc(12px + env(safe-area-inset-bottom));
  left: 50%;
  transform: translateX(-50%);
  width: calc(100% - 24px);
  max-width: 456px;
  background: var(--blood);
  clip-path: polygon(8px 0%, calc(100% - 8px) 0%, 100% 8px, 100% calc(100% - 8px), calc(100% - 8px) 100%, 8px 100%, 0% calc(100% - 8px), 0% 8px);
  padding: 1px;
  z-index: 20;
}

.tab-bar {
  display: flex;
  background: var(--panel);
  clip-path: polygon(7px 0%, calc(100% - 7px) 0%, 100% 7px, 100% calc(100% - 7px), calc(100% - 7px) 100%, 7px 100%, 0% calc(100% - 7px), 0% 7px);
}

.tab-btn {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 48px;
  background: none;
  border: none;
  border-radius: 10px;
  color: rgba(207, 201, 192, 0.70);
  cursor: pointer;
}

.tab-btn.active {
  flex: 0 0 auto;
  padding: 0 14px;
  background: var(--panel-hi);
  color: var(--blood-bright);
}

.tab-label {
  display: none;
  font-family: var(--font-display);
  font-size: 1rem;
  font-weight: 600;
  letter-spacing: 0.04em;
}

.tab-btn.active .tab-label { display: inline; }

.tab-btn:active { color: var(--bone); }

/* ============ SHELL DIVIDER (v20) ============ */

.shell-divider { border-top: 1px solid var(--ash); }

/* ============ SUPPLY CARD (v20) ============ */

.supply-card {
  background: var(--panel);
  border: 1px solid var(--line);
  clip-path: polygon(8px 0%, calc(100% - 8px) 0%, 100% 8px, 100% calc(100% - 8px), calc(100% - 8px) 100%, 8px 100%, 0% calc(100% - 8px), 0% 8px);
  padding: 14px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

/* ============ SUPPLY METER (v19) ============ */

.supply-strip {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.supply-count {
  font-family: var(--font-display);
  font-size: 1.3rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  min-width: 44px;
  text-align: center;
}

.supply-hint {
  font-size: 0.75rem;
  color: var(--ash);
  letter-spacing: 0.06em;
}

/* ============ SORCERY TAB (v27) ============ */

.sorcery-level-row {
  display: flex;
  align-items: center;
  gap: 16px;
  padding-bottom: 16px;
}

/* ============ EDGES (advancement, v62) ============ */
.edges-section {
  margin-top: 18px;
  padding-top: 16px;
  border-top: 1px solid var(--line);
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.level-row { display: flex; align-items: center; gap: 16px; }
.level-row .field-label { margin: 0; }
.level-up-btn { align-self: flex-start; }

/* Discovery Points / Haven Level tracker */
.haven-dp { display: flex; flex-direction: column; gap: 8px; }
.haven-dp .field-label { margin: 0; }
/* v102: the readout and its correction sit on one line, the correction pushed to the far end
   so it is nowhere near the award buttons and cannot be tapped for one. */
/* v103: the roll step. Sits in seven overlays, so it reuses .step-btn rather than growing a
   second stepper look. The die it changes is the one already printed above it. */
.roll-step {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  margin: 0 auto;
}

.roll-step-label {
  color: var(--ash);
  font-size: 0.75rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}


.dp-strip { display: flex; align-items: center; justify-content: space-between; gap: 12px; }

.dp-correct-btn {
  background: transparent;
  border: 1px solid var(--line);
  border-radius: 6px;
  color: var(--ash);
  cursor: pointer;
  font-size: 0.85rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  min-height: 44px;
  min-width: 44px;
  padding: 0 14px;
}

.dp-correct-btn:disabled { color: var(--panel-hi); cursor: default; }

.dp-readout { margin: 0; color: var(--bone); font-size: 1.4rem; line-height: 1; }
.dp-readout #dp-target { color: var(--ash); font-size: 0.9rem; }
.dp-bar {
  height: 8px;
  background: var(--panel-hi);
  border: 1px solid var(--line);
  overflow: hidden;
}
.dp-bar-fill {
  height: 100%;
  width: 0%;
  background: var(--ember-light);
  transition: width 0.25s ease;
}
.dp-bar-fill.dp-ready { box-shadow: 0 0 6px var(--ember-light); }
.dp-note { margin: 0; color: var(--ash); font-size: 0.75rem; line-height: 1.4; }
.dp-note-ready { color: var(--blood-bright); }
.dp-awards { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 2px; }
.dp-award-btn {
  min-height: 44px;
  padding: 6px 12px;
  background: var(--panel-hi);
  border: 1px solid var(--line);
  color: var(--bone);
  font-size: 0.75rem;
  letter-spacing: 0.02em;
  cursor: pointer;
  flex: 1 1 auto;
  white-space: nowrap;
}
.dp-award-btn:active { background: var(--blood); color: var(--bone); }
.levelup-dice { color: var(--bone); font-size: 1rem; text-align: center; margin: 0; }
#btn-roll-edge { align-self: flex-start; }
.edges-empty { color: var(--ash); font-size: 0.82rem; line-height: 1.4; margin: 0; }
.edges-list { display: flex; flex-direction: column; gap: 10px; }
.edge-row {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 12px 14px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.edge-name {
  color: var(--blood-bright);
  font-size: 0.85rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  margin: 0;
}
.edge-desc { color: var(--bone); font-size: 0.9rem; line-height: 1.45; margin: 0; }

/* Class abilities: same card language; locked ones dim via ash (no opacity, keeps text legible) */
.abilities-list { display: flex; flex-direction: column; gap: 10px; }
.ability-row {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 12px 14px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.ability-name {
  color: var(--blood-bright);
  font-size: 0.85rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  margin: 0;
}
.ability-desc { color: var(--bone); font-size: 0.9rem; line-height: 1.45; margin: 0; }
.ability-locked .ability-name { color: var(--ash); }
.ability-locked .ability-desc { color: var(--ash); font-style: italic; }

/* Identity panel (v65): read-only display of the narrative answers */
.identity-section {
  margin-top: 18px;
  padding-top: 16px;
  border-top: 1px solid var(--line);
}
.identity-list { display: flex; flex-direction: column; gap: 12px; }
.identity-qa { display: flex; flex-direction: column; gap: 3px; }
.identity-q { color: var(--ash); font-size: 0.82rem; line-height: 1.35; margin: 0; }
.identity-a { color: var(--bone); font-size: 0.95rem; line-height: 1.45; margin: 0; }

/* ============ HANDBOOK (v68) ============ */
.handbook-head {
  display: flex;
  align-items: center;
  gap: 12px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--line);
  margin-bottom: 14px;
}
.handbook-title {
  font-family: var(--font-display);
  font-size: 1.5rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  color: var(--blood-bright);
  margin: 0;
}
.handbook-nav { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 8px; }
.handbook-nav-btn {
  background: transparent;
  border: 1px solid var(--line);
  border-radius: 6px;
  color: var(--bone);
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 8px 14px;
  min-height: 40px;
  cursor: pointer;
}
.handbook-nav-btn.active { border-color: var(--blood-bright); color: var(--blood-bright); background: var(--panel-hi); }
.handbook-body { display: flex; flex-direction: column; gap: 4px; padding-bottom: 40px; }
.howto-h {
  font-family: var(--font-display);
  font-size: 1.3rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--blood-bright);
  margin: 16px 0 2px;
}
.howto-p { color: var(--bone); font-size: 0.95rem; line-height: 1.55; margin: 0; }

/* v104: the Hexploration accordion on the Expedition tab. It reuses the Rules Reference
   accordion below wholesale; this only gives it room of its own on a tab that had none. */
.expedition-guide-section { margin-top: 22px; }
.expedition-guide-section .field-label { margin: 0 0 6px; }
.expedition-guide-section .rules-topic:first-child { border-top: 1px solid var(--line); }

/* Rules Reference accordion (v69) */
.rules-topic { border-bottom: 1px solid var(--line); }
.rules-topic-head {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  background: transparent;
  border: none;
  cursor: pointer;
  padding: 16px 2px;
  text-align: left;
}
.rules-topic-title {
  font-family: var(--font-display);
  font-size: 1.2rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--blood-bright);
}
.rules-topic-caret {
  color: var(--ash);
  font-size: 1.4rem;
  flex-shrink: 0;
  transition: transform 0.15s ease;
}
.rules-topic-head.open .rules-topic-caret { transform: rotate(90deg); color: var(--blood-bright); }
.rules-topic-body { display: flex; flex-direction: column; gap: 10px; padding: 0 2px 16px; }
.rules-p { color: var(--bone); font-size: 0.92rem; line-height: 1.55; margin: 0; }
@media (prefers-reduced-motion: reduce) { .rules-topic-caret { transition: none; } }

.sheet-head-right { display: flex; align-items: center; gap: 8px; }
/* v106: "?" became "Handbook", so it needs width for a word rather than a glyph. Kept as its
   own class rather than .ghost-btn, which is ash on a header that wants bone. */
.head-btn {
  background: transparent;
  border: 1px solid var(--line);
  border-radius: 6px;
  color: var(--bone);
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  min-height: 44px;
  padding: 0 14px;
  flex-shrink: 0;
  cursor: pointer;
}
.head-btn:active { background: var(--panel-hi); border-color: var(--blood); }

.edge-reveal-kicker {
  color: var(--ash);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  margin: 0;
  text-align: center;
}
.edge-reveal-bonus { color: var(--bone); font-size: 1rem; text-align: center; margin: 0; }

/* Skill improvement ceremony (v67) */
.improve-number {
  font-family: var(--font-display);
  font-size: clamp(4rem, 22vw, 7rem);
  font-weight: 700;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  color: var(--bone);
  margin: 0;
}
.improve-number.rolling { animation: flicker 0.07s steps(1) infinite; }
.improve-verdict { min-height: 32px; text-align: center; margin: 0; }
.improve-up { color: var(--bone); font-size: 1.1rem; font-weight: 700; letter-spacing: 0.04em; }
.improve-stay { color: var(--ash); font-size: 1.1rem; letter-spacing: 0.04em; }

#level-value {
  font-family: var(--font-display);
  font-size: 1.4rem;
  font-weight: 600;
}

.spell-tier-header {
  font-family: var(--font-display);
  font-size: 1.5rem;
  font-weight: 600;
  color: var(--blood-bright);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  margin: 0;
  padding: 16px 0 8px;
}

.tier-mech {
  color: var(--bone);
  font-size: 1.1rem;
}

/* v101: two spells to a row. `gap` replaces the old per-row margin-bottom, and the rows are
   stretched to equal height so a wrapped two-line name cannot leave its neighbour short. */
.spell-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 6px;
  align-items: stretch;
}

.spell-row {
  display: flex;
  align-items: center;
  background: var(--panel);
  border: 1px solid var(--line);
  clip-path: polygon(8px 0%, calc(100% - 8px) 0%, 100% 8px, 100% calc(100% - 8px), calc(100% - 8px) 100%, 8px 100%, 0% calc(100% - 8px), 0% 8px);
  color: var(--bone);
  cursor: pointer;
  font-family: var(--font-display);
  font-size: 0.95rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  padding: 12px 14px;
  width: 100%;
  text-align: left;
}

.spell-row.spell-locked {
  color: var(--ash);
  cursor: default;
}

/* ============ SPELL DETAIL OVERLAY (v27) ============ */

.spell-desc {
  color: var(--bone);
  font-size: 1.15rem;
  line-height: 1.55;
  max-width: 320px;
  text-align: center;
}

/* ============ CONDITIONS (v28) ============ */
.condition-strip {
  color: var(--blood-bright);
  font-size: 0.75rem;
  font-variant: small-caps;
  letter-spacing: 0.10em;
  padding: 6px 16px 0;
}
.cond-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
  padding: 8px 0 12px;
}
.cond-chip {
  background: transparent;
  border: 1px solid var(--ash);
  border-radius: 6px;
  color: var(--bone);
  cursor: pointer;
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  min-height: 44px;
  padding: 0 14px;
  text-transform: uppercase;
}
.cond-chip--active {
  border-color: var(--blood);
  color: var(--blood-bright);
}
.cond-effects { padding: 0 0 12px; }
.cond-effect {
  color: var(--ash);
  font-size: 0.80rem;
  line-height: 1.45;
  margin: 0 0 8px;
}
.cond-effect strong { color: var(--blood-bright); font-weight: 600; }
.weary-note {
  color: var(--blood-bright);
  font-size: 0.75rem;
  letter-spacing: 0.08em;
  margin: 4px 0;
  text-transform: uppercase;
}

/* ============ TABLE LINK (CAP-07) ============ */

#screen-table { min-height: 100dvh; }

.tl-state { display: flex; flex-direction: column; gap: 18px; }

.tl-lead { color: var(--bone); line-height: 1.5; margin: 0; }

/* v99: .tl-lead-warn (the two-codes warning) and .tl-steps (the three-step link-code list)
   are gone with the markup they styled. There is one code at registration and one from the
   GM, so nothing needs warning about any more. */

.tl-next-note { color: var(--ash); font-size: 0.8rem; line-height: 1.4; margin: 0; text-align: center; }

.tl-linkout { text-align: center; text-decoration: none; }

.tl-error {
  color: var(--blood-bright);
  font-size: 0.85rem;
  line-height: 1.4;
  margin: 0;
}

/* v85: the local-only escape hatch states its own limits, so this reads as a caveat
   rather than an error. Ash, not blood: nothing has gone wrong at this point. */
/* v89: the privacy notice reads as a quiet statement of fact, not a warning. Ash, and it
   sits directly above the join button so it is read at the moment consent is given. */
.tl-forget-note,
.tl-privacy {
  color: var(--ash);
  font-size: 0.75rem;
  line-height: 1.45;
  margin: 0;
  max-width: 320px;
}

.tl-conn-banner {
  color: var(--ember-light);
  font-size: 0.75rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-align: center;
  margin: 0;
}

/* v110: .tl-entitlement is retired. It held the old status line in ash, and the paragraph
   that replaced it explains what joining DOES, which is primary information and therefore
   bone under Law 3. Both greeting paragraphs are .tl-lead now. */

.tl-buy {
  border: 1px solid var(--blood);
  border-radius: 6px;
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  background: var(--panel);
}
.tl-buy-text { color: var(--bone); line-height: 1.5; margin: 0; }

.tl-unlink { margin-top: 6px; color: var(--ash); }

.tl-session-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.tl-session-status {
  color: var(--blood-bright);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
.tl-leave { flex-shrink: 0; }

/* Fire-and-forget push pop-up: overlays the whole app above the nav */
.tl-popup {
  position: fixed;
  inset: 0;
  z-index: 50;
  background: rgba(12, 10, 11, 0.94);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  animation: tl-popup-in 0.18s ease-out;
}
@keyframes tl-popup-in { from { opacity: 0; } to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) {
  .tl-popup { animation: none; }
}
.tl-popup-inner {
  position: relative;
  width: 100%;
  max-width: 420px;
  max-height: calc(100% - 48px);
  overflow-y: auto;
  background: var(--panel);
  border: 1px solid var(--blood);
  border-radius: 8px;
  padding: 48px 20px 20px;
}
.tl-popup-close {
  position: absolute;
  top: 4px;
  right: 4px;
  width: 44px;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: none;
  color: var(--blood-bright);
  font-size: 1.6rem;
  line-height: 1;
  cursor: pointer;
}
.tl-popup-close:active { color: var(--bone); }
/* The card renderers are reused inside the pop-up; the pop-up supplies the frame. */
.tl-popup-body .tl-card { border: none; background: transparent; padding: 0; }

.tl-card {
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 16px;
  background: var(--panel);
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.tl-card--secret_text { border-color: var(--blood); }

.tl-card-kind {
  color: var(--blood-bright);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  margin: 0;
}
.tl-card-title {
  color: var(--blood-bright);
  font-family: var(--font-display);
  font-size: 1.5rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  margin: 0;
}
.tl-card-body { color: var(--bone); line-height: 1.55; margin: 0; white-space: pre-wrap; }

.tl-card-img { width: 100%; height: auto; border-radius: 4px; display: block; }
.tl-card-caption { color: var(--ash); font-size: 0.85rem; line-height: 1.4; margin: 0; }

/* v108, Tomas's register. */

/* 1. The version note lifts off the very bottom. */
/* v112: the account block now carries the auto margin that pushes this pair to the foot, so
   the version note only keeps its 10mm lift. */
#intro-version-note { margin-bottom: 38px; }   /* 10mm */

/* 3. With the skill line gone in v106, .save-btn had a single child and no justification, so
   the word sat at the top of a 56px box. It was centred only by accident before. */
.save-btn { justify-content: center; }

/* 4. "Actions" now reads at the size of "Quick Actions" beneath it. Scoped to #action-card:
   .rules-topic-title is shared with the Handbook and the Expedition accordions. */
#action-card .rules-topic-title { font-size: 1.5rem; }

/* 5. Initiative reads across, not down: label left, value and hint right. */
.init-block-row {
  flex-direction: row;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 8px 16px;
  text-align: left;
}
/* v117: the Initiative block, halved. RULED BY TOMAS 2026-07-29 ("shrink the label to fit").

   A DELIBERATE, SCOPED DEVIATION FROM LAW 2, which names `.vital-label` as a display element
   at 1.5rem. It applies to this block and nothing else, because since v106 this label is not a
   section header: it sits inline beside its own value, which is a different job from heading a
   panel. At 1.5rem its caps broke to three lines and held the block at 105px against the 73px
   asked for; at 1.1rem it is two lines and the block is 68px, down from 146px before v106.

   Recorded in CLAUDE.md under Law 2, so a later pass reads this as a ruling and not as drift.
   ONE rule for this selector, deliberately: there were briefly two, and an assertion matching
   by selector read the first and missed the font entirely. */
.init-block-row .vital-label {
  flex: 1 1 auto;
  font-size: 1.1rem;
  line-height: 1.25;
}
.init-block-right {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 2px;
  flex: 0 0 auto;
}

/* 6. Spell names in caps. The rows were already tuned to fit two across at 375px, and caps
   are wider, so the tracking gives back what the capitals take. */
/* Caps are wider, so the size comes down to keep two across at 375px without wrapping the
   long names. min-height holds the 44px tap rule that the smaller text would otherwise break,
   which is exactly the regression v105 was cleaning up. */
.spell-row {
  text-transform: uppercase;
  font-size: 0.85rem;
  letter-spacing: 0.01em;
  min-height: 44px;
}

/* v112: the Table Link fields share a row. Measured at 375px: half width 183px against a
   127px widest label, so nothing wrapped and neither field had to shrink. */
.tl-field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }

/* The account block at the front door. Pushed to the foot alongside the version note, which
   is where Tomas asked for it: above the version number, below everything else. */
.intro-account {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  /* v113: `margin-top: auto` alone resolves to zero once the intro fills the viewport, which
     is what put this hard against How to Play on a shorter Android screen. The padding is the
     floor: the block is pushed to the foot when there is room, and never closer than 26px to
     the buttons when there is not. */
  margin-top: auto;
  padding-top: 26px;
  width: 100%;
}
.intro-account-line {
  color: var(--ash);
  font-size: 0.75rem;
  letter-spacing: 0.08em;
  margin: 0;
  text-align: center;
  overflow-wrap: anywhere;
}
.intro-account-line .intro-account-email { color: var(--bone); }

/* v113: it inherited .tl-forget-note from the Table Link screen, where it sat in a
   left-aligned column. Everything else in this block is centred. */
.intro-account .tl-forget-note { text-align: center; }

/* v114, Tomas's register.

   Handbook headers in caps. `.howto-h` carries the scrolling sections (At the Table, What You
   Need, and the rest) and the Rules Reference topics carry `.rules-topic-title`, so both are
   named. Scoped to #handbook-body on purpose: `.rules-topic-title` is shared with the
   Expedition guide below and with the Combat action card, and Tomas asked for neither of
   those to change here. */
#handbook-body .howto-h,
#handbook-body .rules-topic-title { text-transform: uppercase; }

/* Expedition section headers in bone and in caps. The block heading "HEXPLORATION" is a
   .field-label and is deliberately left alone: Tomas ruled it stays as it is. */
#expedition-guide .rules-topic-title {
  color: var(--bone);
  text-transform: uppercase;
}

/* v116: Rules Reference topic heads in bone, matching what v114 did for the Expedition guide.
   Scoped to #handbook-body, so the Combat action card and the Expedition accordion keep their
   own treatments, and .howto-h stays blood-bright: Tomas asked for Rules Reference only. */
#handbook-body .rules-topic-title { color: var(--bone); }

