/* ==========================================================================
   BASE — reset, typography, primitives shared by every section.
   All spacing values are tokens from tokens.css. No inline styles anywhere.
   ========================================================================== */
*,*::before,*::after{box-sizing:border-box}
html,body{margin:0;padding:0;overflow-x:clip}
html{scroll-behavior:smooth}
/* The HTML5-boilerplate guard. A class that sets `display` outranks the UA's
   [hidden] rule at equal specificity — this has bitten the codebase before. */
[hidden]{display:none !important}

body{
  font-family:var(--font-body);
  font-size:clamp(1rem,.94rem + .3vw,1.1rem);
  line-height:1.4;
  color:var(--ink);
  background:
    radial-gradient(130% 90% at 50% -10%, var(--bg-0) 30%, transparent 90%),
    radial-gradient(120% 120% at 50% 110%, var(--bg-1) 10%, transparent 70%),
    linear-gradient(var(--bg-0),var(--bg-1));
  background-attachment:fixed;
  min-height:100dvh;
}

/* parchment grain over the page — not over dialogs (top layer paints above) */
body::before{
  content:"";
  position:fixed; inset:0;
  z-index:9999;
  pointer-events:none;
  opacity:var(--noise-o);
  mix-blend-mode:var(--noise-blend);
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='240' height='240' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* the sheet takes a subtle "dying" treatment at 0 HP */
body::after{
  content:"";
  position:fixed; inset:0;
  z-index:9998;
  pointer-events:none;
  opacity:0;
  transition:opacity .5s ease;
  background:radial-gradient(120% 85% at 50% 50%, transparent 30%, color-mix(in srgb, var(--rubric-deep) 42%, transparent) 100%);
}
body.is-dying::after{opacity:1;animation:gutter 3.4s ease-in-out infinite}
@keyframes gutter{0%,100%{opacity:.78}50%{opacity:1}}

/* ---------- typography helpers ---------- */

/* THE ONE LABEL — every label on the sheet wears this class. See tokens.css. */
.label{
  font-family:var(--label-font);
  font-size:var(--label-size);
  font-weight:var(--label-weight);
  letter-spacing:var(--label-track);
  text-transform:uppercase;
  color:var(--ink-faint);
}

.visually-hidden{
  position:absolute;
  width:1px;height:1px;
  overflow:hidden;
  clip-path:inset(50%);
  white-space:nowrap;
}
.u-center{text-align:center}
.verdigris-ink{color:var(--verdigris)}

button{
  font:inherit;
  color:inherit;
  background:none;
  border:none;
  cursor:pointer;
  -webkit-tap-highlight-color:transparent;
  touch-action:manipulation;
}
button:disabled{cursor:not-allowed}

/* A tabindex="-1" element is NEVER reachable by keyboard — it is focused only
   programmatically, which here is focusViewHeading() moving the reading
   position to the new view's title on every navigation. Ringing it draws a gold
   box around a HEADING, which then reads as the loudest control on the screen
   while doing nothing. Screen readers still announce the move; the ring was
   only ever visual noise. Real keyboard focus on real controls is unaffected. */
[tabindex="-1"]:focus,
[tabindex="-1"]:focus-visible{outline:none}

:focus-visible{
  outline:2px solid var(--gold-deep);
  outline-offset:2px;
  border-radius:var(--r-sm);
}

/* ==========================================================================
   THE EDITABLE FIELD — a ruled scribal line, not a chrome form control.
   Height is --field, the sheet-wide touch height. Density where it belongs
   comes from the parent grid, never from shrinking a field ad hoc.
   ========================================================================== */
.ink-field{
  display:inline-flex;
  align-items:center;
  min-width:2.5em;
  min-height:var(--field);
  padding:0 var(--s1);
  border-bottom:1px dotted var(--rule);
  border-radius:var(--r-sm) 2px 0 0;
  color:var(--ink);
  cursor:text;
  transition:background-color .15s ease, border-color .15s ease;
  overflow-wrap:anywhere;
}
.ink-field:hover{background:color-mix(in srgb, var(--gold-hi) 14%, transparent);border-bottom-color:var(--gold-deep)}
.ink-field:focus{
  outline:none;
  background:color-mix(in srgb, var(--gold-hi) 20%, transparent);
  border-bottom:1px solid var(--gold-deep);
}
.ink-field:focus-visible{outline:2px solid var(--gold-deep);outline-offset:1px}
.ink-field:empty::before{content:attr(data-ph);color:var(--ink-faint);opacity:.7;font-style:italic}
.ink-field.is-readonly{
  cursor:default;
  border-bottom-color:transparent;
}
.ink-field.is-readonly:hover{background:transparent;border-bottom-color:transparent}
.ink-field--num{
  min-width:2.2em;
  justify-content:center;
  text-align:center;
  font-family:var(--font-display);
  font-weight:700;
}
.ink-field--block{
  display:block;
  width:100%;
  min-height:4.4rem;
  padding:var(--s2) var(--s3);
  border:1px solid var(--rule-soft);
  border-radius:var(--r-sm);
  background:
    repeating-linear-gradient(180deg, transparent 0 1.34rem, color-mix(in srgb, var(--rule-soft) 45%, transparent) 1.34rem 1.4rem),
    var(--panel-2);
  font-family:var(--font-scribal);
  font-size:var(--fs-body);
  line-height:1.4rem;
  white-space:pre-wrap;
}
.ink-field--block:focus{border:1px solid var(--gold-deep)}

/* the scribal select — a ruled field with a fleuron, never a chrome dropdown */
.ink-sel{
  appearance:none;-webkit-appearance:none;
  min-height:var(--field);
  padding:0 1.15em 0 var(--s1);
  border:none;
  border-bottom:1px dotted var(--rule);
  border-radius:var(--r-sm) 2px 0 0;
  background:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%23a87e22' stroke-width='1.4' stroke-linecap='round'/%3E%3C/svg%3E") no-repeat right .18em center/.6em auto;
  color:var(--ink);
  font:inherit;
  cursor:pointer;
  transition:background-color .15s ease;
}
.ink-sel:hover{background-color:color-mix(in srgb, var(--gold-hi) 14%, transparent);border-bottom-color:var(--gold-deep)}
.ink-sel option{background:var(--panel);color:var(--ink)}
.ink-sel.is-readonly{
  opacity:1;
  cursor:default;
  border-bottom-color:transparent;
  background-image:none;
}

/* the ✕ glyph is this control's only label — resting contrast clears 4.5:1 */
.rm-btn{
  flex:none;
  width:var(--row-tail);height:var(--field);
  color:var(--rubric);
  font-size:var(--fs-small);
  line-height:1;
  border-radius:var(--r-sm);
  opacity:.9;
  transition:opacity .15s ease, background-color .15s ease;
}
.rm-btn:hover{opacity:1;background:color-mix(in srgb, var(--rubric) 12%, transparent)}

.add-btn{
  display:inline-flex;
  align-items:center;
  justify-content:center;
  gap:var(--s2);
  min-height:var(--field);
  padding:var(--s1) var(--s3);
  border:1px dashed var(--gold-deep);
  border-radius:var(--r-sm);
  background:transparent;
  color:var(--gold-deep);
  font-family:var(--font-display);
  font-size:var(--fs-label);
  font-weight:600;
  letter-spacing:.08em;
  text-transform:uppercase;
  transition:background-color .15s ease;
}
.add-btn:hover{background:color-mix(in srgb, var(--gold-hi) 12%, transparent)}
.add-btn--wide{display:flex;width:100%;margin-top:var(--s3);font-size:var(--fs-label)}
.add-btn--sm{padding:0 var(--s2);font-size:var(--fs-label)}
.add-btn small{
  font-family:var(--font-scribal);
  font-style:italic;
  font-size:var(--fs-label);
  letter-spacing:0;
  text-transform:none;
  color:var(--ink-faint);
}

/* ==========================================================================
   STAT VALUES + ENCHANTMENTS (ported from the mockup, bug fixes intact)
   ========================================================================== */
.stat{
  position:relative;
  display:inline-flex;
  align-items:center;
  gap:.05em;
  white-space:nowrap;
  flex:none;
}
.statval{
  position:relative;
  padding:0 .12em;
  font:inherit;
  color:inherit;
  cursor:context-menu;
  border-radius:var(--r-sm);
  user-select:none;
  -webkit-user-select:none;
  -webkit-touch-callout:none;
  transition:background-color .15s ease;
}
/* a number stays small but presses like a thumb: 44px of reach, no layout cost */
.statval::after{
  content:"";
  position:absolute;
  top:50%;left:50%;
  width:44px;height:44px;
  transform:translate(-50%,-50%);
}
.statval:hover{background:color-mix(in srgb, var(--gold-hi) 20%, transparent)}
.statval.is-readonly{cursor:default}
.statval.is-readonly::after{display:none}
.statval.is-readonly:hover{background:transparent}
/* real controls always win an overlap with an invisible reach-pad */
.prof-btn,.insp,.pip,.prep-dot,.spell-row,.ab-toggle,.feat-row,.act,.chip,.rest-btn,.rm-btn,.add-btn,.ink-field,.ink-sel,.die-btn{position:relative;z-index:1}

/* the verdigris mark of enchantment. z-index:1 (never 2): a mark must never
   out-rank a real control — at parity, DOM order hands the win to the control. */
.ench-mark{
  position:relative;
  z-index:1;
  padding:0 .1em;
  font-family:var(--font-display);
  font-size:.62em;
  line-height:1;
  color:var(--verdigris);
  vertical-align:super;
  min-width:20px;
  transform:translateY(-.35em);
}
/* the mark's reach-pad opens RIGHT from its own band and never leaves it.
   36x28 (was 30x22): more thumb, still inside the 44px row, still never
   ranked above a real control (z-index parity + DOM order — see above). */
.ench-mark::after{
  content:"";
  position:absolute;
  top:0;left:0;
  width:36px;height:28px;
}
.ench-mark:hover,.ench-mark[aria-expanded="true"]{color:var(--verdigris-hi)}
.ench-tip{
  position:absolute;
  bottom:calc(100% + 6px);
  left:50%;
  transform:translateX(-50%);
  z-index:60;
  width:max-content;
  max-width:min(15rem,58vw);
  padding:var(--s1) var(--s2);
  border:1px solid var(--verdigris);
  border-radius:var(--r-sm);
  background:var(--panel);
  color:var(--ink);
  font-family:var(--font-scribal);
  font-style:italic;
  font-size:var(--fs-label);
  line-height:1.3;
  white-space:normal;
  text-align:left;
  box-shadow:var(--shadow);
  opacity:0;
  visibility:hidden;
  pointer-events:none;
  transition:opacity .15s ease;
}
.stat:hover .ench-tip,
.stat:focus-within .ench-tip,
.ench-mark[aria-expanded="true"] + .ench-tip{opacity:1;visibility:visible}

/* ---------- rules-bearing elements: a small gold dot, long-press to read ---------- */
.has-rules{position:relative}
.has-rules::after{
  content:"";
  position:absolute;
  top:3px;right:3px;
  width:3.5px;height:3.5px;
  border-radius:50%;
  background:var(--gold);
  opacity:.7;
  pointer-events:none;
}
.has-rules:disabled::after{opacity:.3}
.ab-row .prof-btn.has-rules::after{display:none}
.ab-row--save .prof-btn.has-rules::after{display:block;top:50%;right:2px;margin-top:-1.75px}

/* ==========================================================================
   TOAST + COLOPHON
   ========================================================================== */
.toast{
  position:fixed;
  left:50%;
  bottom:max(var(--s4), env(safe-area-inset-bottom));
  transform:translate(-50%,120%);
  max-width:min(28rem,calc(100vw - 6rem));
  padding:var(--s2) var(--s4);
  border:1px solid var(--gold-deep);
  border-radius:var(--r-sm);
  background:var(--panel);
  color:var(--ink);
  /* Toasts are STATUS, not flavor. The scribal italic was atmospheric and
     unreadable at a glance (Tim, 2026-08-05: "I still can't read the text").
     Upright body face, full body size. */
  font-family:var(--font-body);
  font-style:normal;
  font-size:var(--fs-body);
  line-height:1.35;
  text-align:center;
  box-shadow:var(--shadow);
  opacity:0;
  transition:transform .3s ease, opacity .3s ease;
  z-index:100;
  pointer-events:none;
}
.toast.show{transform:translate(-50%,0);opacity:1}

.colophon{
  margin-top:var(--s5);
  text-align:center;
  font-family:var(--font-scribal);
  font-style:italic;
  font-size:var(--fs-small);
  color:var(--ink-soft);
}
.colophon .fleuron{color:var(--gold);font-style:normal}
.colophon .attrib{
  display:block;
  margin-top:var(--s2);
  font-size:var(--fs-label);
  color:var(--ink-soft);
  opacity:.9;
  max-width:44rem;
  margin-inline:auto;
}
.colophon a{color:var(--gold-deep)}

/* ==========================================================================
   MOTION
   ========================================================================== */
@media (prefers-reduced-motion: reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{
    animation:none !important;
    transition:none !important;
  }
}
