/* Shared Valenmod design tokens. Surface-specific variables stay with their bundle. */

@font-face {
  font-family: "Grenze Gotisch";
  src: url("/modules/valenmod/assets/fonts/grenze-gotisch-semibold.otf") format("opentype");
  font-style: normal;
  font-weight: 600;
  font-display: swap;
}

:root {
  --valenmod-red: #a94b49;
  --valenmod-red-dark: #26090b;
  --valenmod-red-deep: #561b20;
  --valenmod-red-light: #e08a82;
  --valenmod-green: #2f653d;
  --valenmod-green-dark: #0b2114;
  --valenmod-green-soft: #5f8b61;
  --valenmod-gold: #d4ad58;
  --valenmod-title-gradient: linear-gradient(to bottom right, #D4AE58, #a87b43);
  --valenmod-paper: #070907;
  --valenmod-paper-alt: #0a100b;
  --valenmod-panel: #10180f;
  --valenmod-panel-strong: #142316;
  --valenmod-panel-raised: #1b2f1d;
  --valenmod-input: #050806;
  --valenmod-ink: #f0e6d6;
  --valenmod-ink-dim: #d2ccb9;
  --valenmod-line: #31543a;
  --valenmod-line-soft: rgb(95 139 97 / 34%);
  --valenmod-gold-wash: rgb(212 173 88 / 8%);
  --valenmod-gold-wash-strong: rgb(212 173 88 / 16%);
  --valenmod-red-wash: rgb(169 75 73 / 20%);
  /* A warm salmon state for places the party has physically visited. This is
     deliberately distinct from red's damage/danger meaning. */
  --valenmod-explored: var(--valenmod-red-light);
  --valenmod-explored-line: color-mix(in srgb, var(--valenmod-explored) 72%, transparent);
  --valenmod-explored-wash: color-mix(in srgb, var(--valenmod-explored) 24%, var(--valenmod-panel));
  --valenmod-warn: #d8a74d;
  --valenmod-hero-point-yellow: #f2c94c;
  --valenmod-environment-accent: #e8a63d;
  --valenmod-environment-accent-hover: #f0b95b;
  --valenmod-environment-ink: #1a1205;
  /* One cyan for "a bonus, not a problem": the success degree of a check and
     temp HP above max. They must never drift apart, so both read it from here
     rather than repeating the literal. */
  --valenmod-cyan: hsl(183 84% 44%);
  --valenmod-control-background: linear-gradient(
    180deg,
    var(--valenmod-panel-raised),
    var(--valenmod-panel)
  );
  --valenmod-control-background-hover: linear-gradient(180deg, #223c25, var(--valenmod-panel-strong));
  --valenmod-control-background-active: linear-gradient(
    180deg,
    color-mix(in oklab, var(--valenmod-green) 70%, var(--valenmod-panel-raised)),
    var(--valenmod-panel-strong)
  );
  --valenmod-control-border: color-mix(in oklab, var(--valenmod-line) 85%, white);
  --valenmod-control-border-hover: var(--valenmod-gold);
  --valenmod-control-ink: var(--valenmod-ink);
  --valenmod-control-ink-muted: var(--valenmod-ink-dim);
  --valenmod-control-accent: var(--valenmod-gold);
  --valenmod-control-focus: rgb(212 173 88 / 45%);
  /* Shadows do four unrelated jobs in this module, so they get four families
     rather than one scale. Suppressions (box-shadow: none) are deliberately
     not tokenised: those are boundary overrides against Foundry and PF2E, and
     each one is load-bearing where it sits. */
  /* Surface treatment. The bevel is the 1px top highlight that makes a control
     read as raised; it previously existed in 16 spellings across 34 uses. */
  --valenmod-bevel: inset 0 1px rgb(255 255 255 / 5%);
  --valenmod-well: inset 0 1px 3px rgb(0 0 0 / 40%);
  /* Elevation, in three heights: sitting on the surface, floating above it,
     covering it. Blur runs roughly 3x the offset, which is the ratio the
     hand-written values already trended toward. */
  --valenmod-shadow-raised: 0 1px 2px rgb(0 0 0 / 55%);
  --valenmod-shadow-floating: 0 6px 18px rgb(0 0 0 / 34%);
  --valenmod-shadow-overlay: 0 16px 40px rgb(0 0 0 / 72%);
  --valenmod-control-shadow: var(--valenmod-bevel), var(--valenmod-shadow-raised);
  /* The canonical card: a full-strength line, a gold wash falling off just
     under halfway, and the bevel. Taken from the Session Stats totals, which
     is the treatment we standardised on. Cards that carry an accent rail add
     border-top: var(--valenmod-rail-width) solid <accent> on top of this. */
  --valenmod-card-border: 1px solid var(--valenmod-line);
  --valenmod-card-background:
    linear-gradient(rgb(212 173 88 / 6%), transparent 46%),
    var(--valenmod-panel);
  /* Three response speeds, named for what moves rather than how long it takes.
     These describe what the module already does: a full count found 13 distinct
     durations, with 96 of 118 declarations sitting between 100ms and 160ms. */
  --valenmod-transition-fast: 120ms;  /* glyph and icon feedback */
  --valenmod-transition-base: 160ms;  /* buttons, chips, links, rows */
  --valenmod-transition-slow: 250ms;  /* panels, overlays, drawers */
  /* Retained as the base alias so existing call sites keep working. */
  --valenmod-control-transition-duration: var(--valenmod-transition-base);
  /* One corner radius. Everything rounds to this unless it is a genuinely
     different shape, and the three exceptions below are the whole list. */
  --valenmod-radius: 3px;          /* controls, chips, rows, inline frames */
  --valenmod-radius-lg: 6px;       /* shells, panels, popovers, cards */
  --valenmod-radius-pill: 999px;   /* mode toggles */
  --valenmod-radius-round: 50%;    /* tokens, loading ring */
  /* The accent rail: a heavy border on one edge carrying a semantic colour.
     Rounded on all four corners so the rail follows the card, never mitred. */
  --valenmod-rail-width: 3px;
  --valenmod-rail-width-narrow: 2px;  /* dense rows only */
  /* Stacking layers, defined against Foundry's own scale rather than against
     each other: --z-index-window is 100, --z-index-tooltip 9999, and
     --z-index-notification 99999. Every Valenmod surface that needs to clear
     one of those uses the layer named for it instead of guessing a number.
     Values below 100 are deliberately not covered here: those order elements
     within a single component, inside their app's own stacking context. */
  --valenmod-z-base: 1;           /* lift within a component */
  --valenmod-z-sticky: 100;       /* companion chrome; = Foundry window */
  --valenmod-z-overlay: 1000;     /* drawers, rails, dragged items */
  --valenmod-z-popover: 10000;    /* above Foundry's tooltip */
  --valenmod-z-critical: 100000;  /* above Foundry's notifications */
  /* Reserved for the never-occluded guarantee: the test/live environment
     frame, where being covered would let a test server pass for the live one.
     Nothing else should use this, and it is well short of the 32-bit ceiling
     so there is still somewhere to go. */
  --valenmod-z-max: 2000000;
  /* The four faces. Declared here so in-Foundry styles and the companion
     surfaces share one stack instead of restating it per file. */
  --valenmod-font-display: "Grenze Gotisch", Georgia, serif;
  --valenmod-font-head: "Eczar", Georgia, serif;
  --valenmod-font-body: "Gelasio", Georgia, serif;
  --valenmod-font-ui: "Signika", ui-sans-serif, sans-serif;
  --valenmod-mobile-header-shadow: var(--valenmod-shadow-floating);
  --valenmod-desktop-header-shadow: var(--valenmod-shadow-floating);
  /* Canonical descriptive-chip geometry, taken from the compact proficiency
     badge used for Perception and saves on Council character pages. */
  --valenmod-chip-min-height: 19px;
  --valenmod-chip-padding-block: 2px;
  --valenmod-chip-padding-inline: 6px;
  --valenmod-chip-radius: 2px;
  --valenmod-chip-shadow: inset 0 0 0 1px rgb(255 255 255 / 15%);
  --valenmod-chip-font: var(--valenmod-font-ui);
  --valenmod-chip-font-size: 10px;
  --valenmod-chip-font-weight: 500;
  --valenmod-chip-letter-spacing: 0.05em;
  --valenmod-chip-line-height: 1.3;

  --dynamic-token-inner-ring-top-left-color: #563a1d;
  --dynamic-token-outer-ring-top-left-color: #724a3a;
  --dynamic-token-inner-ring-color: #fff8ee;
  --dynamic-token-outer-ring-color: #191215;
  --dynamic-token-background-outer-color: #000;
  --dynamic-token-background-color: #282423;
  --dynamic-token-dynamic-color: #390a07;
}

/* Canonical companion detail tooltip. This is deliberately separate from
   Archive/Council item previews: it is for explanatory stats, calculations,
   and compact labelled breakdowns on every companion surface. */
.session-tooltip {
  position: fixed;
  z-index: var(--valenmod-z-popover);
  width: min(340px, calc(100vw - 20px));
  max-height: min(520px, calc(100vh - 20px));
  overflow: auto;
  padding: 10px 11px;
  border: 1px solid #6b744d;
  border-radius: var(--valenmod-radius);
  background: #090f0b;
  box-shadow: var(--valenmod-shadow-floating);
  color: var(--valenmod-ink);
  font: 12px/1.35 var(--valenmod-font-ui);
  text-align: left;
  pointer-events: none;
}

.valenmod-session-tooltip { display: grid; gap: 6px; }
.valenmod-tooltip-heading {
  color: var(--valenmod-ink-dim);
  font: 700 10px/1.2 var(--valenmod-font-ui);
  letter-spacing: .04em;
  opacity: .75;
  text-transform: uppercase;
}
.valenmod-session-tooltip-summary,
.valenmod-session-tooltip-section-lines,
.valenmod-session-tooltip-footer { display: grid; gap: 2px; }
.valenmod-session-tooltip-rows {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 1px 0;
  padding-block: 5px;
  border-block: 1px solid var(--valenmod-line-soft);
}
.valenmod-session-tooltip-rows > * { padding: 3px 5px; }
.valenmod-session-tooltip-rows > :nth-child(4n + 3),
.valenmod-session-tooltip-rows > :nth-child(4n + 4) {
  background: color-mix(in srgb, var(--valenmod-green-soft) 7%, transparent);
}
.valenmod-session-tooltip-rows > :nth-child(4n + 3) { border-radius: var(--valenmod-radius) 0 0 var(--valenmod-radius); }
.valenmod-session-tooltip-rows > :nth-child(4n + 4) { border-radius: 0 var(--valenmod-radius) var(--valenmod-radius) 0; }
.valenmod-session-tooltip-rows strong {
  color: var(--valenmod-ink);
  text-align: right;
}
.valenmod-session-tooltip .is-addition { color: var(--valenmod-gold); }
.valenmod-session-tooltip .is-negative { color: var(--valenmod-red-light); }
.valenmod-rules-cart-crafter {
  display: grid;
  gap: 1px;
  min-width: 0;
}
.valenmod-rules-cart-crafter-name {
  display: flex;
  gap: 6px;
  align-items: center;
  min-width: 0;
}
.valenmod-rules-cart-crafter-name > b {
  overflow: hidden;
  font-weight: 700;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.valenmod-rules-cart-crafter > small {
  color: var(--valenmod-ink-dim);
  font-size: 11px;
  line-height: 1.25;
}
.valenmod-rules-cart-crafter-outcome {
  display: grid;
  gap: 1px;
  align-self: stretch;
  align-content: center;
}
.valenmod-rules-cart-crafter-outcome > small {
  color: var(--valenmod-ink-dim);
  font-size: 10px;
  font-weight: 400;
  line-height: 1.25;
  white-space: nowrap;
}
.valenmod-proficiency-chip {
  display: inline-flex;
  min-height: 16px;
  padding: 1px 5px;
  flex: 0 0 auto;
  align-items: center;
  border: 1px solid rgb(0 0 0 / 50%);
  border-radius: var(--valenmod-chip-radius);
  background: #424242;
  box-shadow: var(--valenmod-chip-shadow);
  color: #f3ecdc;
  font: 500 8px/1.25 var(--valenmod-chip-font);
  letter-spacing: .05em;
  text-transform: uppercase;
  white-space: nowrap;
}
/* PF2E Alchemist Remaster Duct Tape's "(*Temporary)" marker, wherever an item
   it crafted is drawn. The marker is bookkeeping rather than part of the name,
   so it steps down from whatever it sits inside and never breaks mid-marker.
   No colour of its own: it appears on chat cards, sheets and HUDs alike, and
   any fixed ink would be wrong on one of them, so it recedes by opacity
   against whatever it inherits instead. Spacing and the capital on the brewed
   damage type are applied where the marker is wrapped, in
   scripts/features/pf2e-alchemist-temporary-item-names.js. */
.valenmod-temporary-marker {
  font-size: .8em;
  opacity: .7;
  white-space: nowrap;
}
.valenmod-proficiency-chip[data-rank="1"] { background: #171f69; }
.valenmod-proficiency-chip[data-rank="2"] { background: #3c005e; }
.valenmod-proficiency-chip[data-rank="3"] { background: #664400; }
.valenmod-proficiency-chip[data-rank="4"] { background: #5e0000; }
.valenmod-session-tooltip-section { display: grid; gap: 2px; }
.valenmod-session-tooltip-section > strong { color: var(--valenmod-gold); }
.valenmod-session-tooltip-footer {
  color: var(--valenmod-ink-dim);
  font-size: 11px;
}
.valenmod-session-tooltip-footer strong { color: var(--valenmod-ink); }

/* The companion sites share one phone-sized app switcher. It stays outside
   each surface's scroll container, so browser safe areas and content height
   are handled consistently instead of every app inventing its own footer. */
.valenmod-mobile-app-nav { display: none; }
.valenmod-desktop-app-nav { display: none; }
.valenmod-desktop-header-utilities { display: none; }
.valenmod-companion-header-title { position: relative; top: -2px; }
.valenmod-companion-header-title > i { position: relative; top: 2px; }

/* Every desktop companion uses the same three-column header: page identity
   on the left, destinations in the centre, and contextual tools on the right.

   The three are real grid tracks rather than an absolutely positioned centre
   band. Out of flow, the nav took no width and simply painted over a long
   page title — which is what it did on Heroes, whose title is the longest of
   the five. As tracks, the outer two are equal whenever their contents fit
   an equal share, which puts the nav at the true centre of the header; when
   the identity block needs more than its share the track grows and the nav
   slides over rather than colliding. `min-content` as the track floor is
   what allows that growth, and each side's own ellipsis is what stops it
   from growing without limit. */
@media (min-width: 701px) {
  body .valenmod-companion-desktop-header {
    position: sticky;
    z-index: var(--valenmod-z-sticky);
    top: 0;
    display: grid;
    grid-template-columns: minmax(min-content, 1fr) auto minmax(min-content, 1fr);
    flex: 0 0 auto;
    gap: 0;
    align-items: center;
    width: 100%;
    min-height: 64px;
    padding: 0 14px;
    overflow: hidden;
    border-bottom: 1px solid var(--valenmod-line);
    background:
      linear-gradient(90deg, rgb(212 173 88 / 7%), transparent 48%),
      rgb(7 13 9 / 97%);
    box-shadow: var(--valenmod-desktop-header-shadow);
  }

  /* No min-width:0 here on purpose: the track floor is this block's
     min-content, and that is what lets the nav slide instead of overlapping.
     Each surface's own title carries the max-width that stops the floor from
     growing past what the header can hold. */
  /* Height comes from the header, not from here. On the Archive this element
     is also the title, and a block box forced to the full bar height would
     sit its single line against the top edge instead of on the centre line —
     the grid can only centre a box it is allowed to size. */
  .valenmod-companion-desktop-header .valenmod-companion-header-primary {
    display: flex;
    align-items: center;
    margin-right: 16px;
  }

  /* Same reason as the primary above: an explicit zero minimum here would
     collapse the track floor to nothing and the nav would never slide. The
     narrow regime below restores it, which is what re-arms the ellipsis. */
  /* Block flow, not flex: text-overflow has no effect on the anonymous item a
     flex container wraps a bare text node in, so as a flex box this title
     clipped mid-letter instead of ellipsing. The icon keeps its spacing from
     its own margin rather than a flex gap.

     margin-block rather than margin, because on the Archive this same element
     is also the header-primary, and a blanket `margin: 0` there would cancel
     the 16px that holds the title off the nav. */
  .valenmod-companion-desktop-header .valenmod-companion-header-title {
    display: block;
    margin-block: 0;
    overflow: hidden;
    background: none;
    color: var(--valenmod-ink);
    font: 700 1.6em/1 var(--valenmod-font-display);
    letter-spacing: normal;
    text-overflow: ellipsis;
    white-space: nowrap;
    -webkit-text-fill-color: currentColor;
  }

  .valenmod-companion-desktop-header .valenmod-companion-header-title > i {
    margin-right: 8px;
    font-size: 1.2rem;
  }

  body nav.valenmod-desktop-app-nav {
    display: flex;
    flex: 0 0 auto;
    gap: 0;
    align-self: stretch;
    align-items: center;
    justify-self: center;
    margin: 0;
  }

  /* Label beside icon while the row can carry it. Every surface uses the same
     geometry: the nav has to land in the same place as you move between
     companions, so no surface gets to trim its own destinations to buy width
     for its tools. */
  .valenmod-desktop-app-nav > a {
    position: relative;
    display: inline-flex;
    gap: 7px;
    align-items: center;
    justify-content: center;
    min-width: 0;
    min-height: 64px;
    padding: 0 13px;
    border: 0;
    border-radius: 0;
    background: transparent;
    box-shadow: none;
    color: var(--valenmod-control-ink-muted);
    font: 700 12px/1 var(--valenmod-font-ui);
    letter-spacing: .025em;
    text-decoration: none;
    white-space: nowrap;
  }

  .valenmod-desktop-app-nav > a[hidden] { display: none; }
  .valenmod-desktop-app-nav > a > i { color: var(--valenmod-ink); }
  .valenmod-desktop-app-nav > a:is(:hover, :focus-visible) {
    background: rgb(255 255 255 / 5%);
    color: #fff;
    outline: 0;
  }
  .valenmod-desktop-app-nav > a[aria-current="page"] {
    background: rgb(255 255 255 / 4%);
    color: #fff;
  }
  .valenmod-desktop-app-nav > a[aria-current="page"] > i { color: #fff; }
  .valenmod-desktop-app-nav > a[aria-current="page"]::after {
    position: absolute;
    right: 12px;
    bottom: 0;
    left: 12px;
    height: 3px;
    border-radius: var(--valenmod-radius) var(--valenmod-radius) 0 0;
    background: var(--valenmod-gold);
    content: "";
  }

  .valenmod-companion-desktop-header .valenmod-companion-header-tools {
    display: flex;
    gap: 8px;
    align-items: center;
    justify-content: flex-end;
    margin-left: auto;
    min-width: 0;
  }

  body nav.valenmod-desktop-header-utilities {
    display: flex;
    flex: 0 0 auto;
    gap: 5px;
    align-items: center;
  }

  .valenmod-desktop-header-utilities > a {
    display: grid;
    width: 36px;
    height: 36px;
    padding: 0;
    border: 1px solid var(--valenmod-control-border);
    border-radius: var(--valenmod-radius);
    background: var(--valenmod-control-background);
    box-shadow: var(--valenmod-control-shadow);
    color: var(--valenmod-ink-dim);
    text-decoration: none;
    place-items: center;
  }
  .valenmod-desktop-header-utilities > a:is(:hover, :focus-visible) {
    border-color: var(--valenmod-gold);
    background: var(--valenmod-control-background-hover);
    color: #fff;
    outline: 0;
  }
  .valenmod-desktop-header-utilities > a:first-child > i { color: var(--valenmod-gold); }
}

/* Below this the row can no longer carry six side-by-side destinations plus a
   title and a set of tools, so the destinations stack their label under their
   icon exactly as the phone bar does. That is about a third narrower, which
   is what keeps every label — the alternative at these widths was dropping
   the labels entirely and leaving a row of bare glyphs. */
@media (min-width: 701px) and (max-width: 1200px) {
  .valenmod-desktop-app-nav > a {
    display: grid;
    gap: 4px;
    align-content: center;
    justify-items: center;
    padding-inline: 12px;
    font-size: 10px;
    letter-spacing: .035em;
    text-transform: uppercase;
  }
  .valenmod-desktop-app-nav > a > i { font-size: 15px; }
}

/* Tightening the gaps buys the last of the width before anything has to be
   hidden. */
@media (min-width: 701px) and (max-width: 900px) {
  .valenmod-desktop-app-nav > a { padding-inline: 7px; }
}

/* Below this the sliding regime runs out: the widest page title (Heroes'
   "Lost Heroes of Valenmere") plus the nav and tools no longer fit on one
   row, and a track floored at min-content would push the tools off the end
   instead of yielding. Restoring the zero floor hands the decision back to
   the equal-share tracks, so the title ellipsises and the nav returns to the
   true centre. The threshold is where that sum crosses the viewport, with
   room for the wider glyphs on other platforms. */
@media (min-width: 701px) and (max-width: 860px) {
  /* Equal shares would be the wrong trade here: the tools column needs only
     its own width, and splitting the row evenly would strand that surplus on
     the right while the title was still being cut. The right track takes what
     it needs, the left takes the rest, and the title gives up exactly as much
     as the row is short. Centring is already impossible at this width, so
     nothing is lost by dropping it. */
  body .valenmod-companion-desktop-header {
    grid-template-columns: minmax(0, 1fr) auto minmax(0, max-content);
  }
  /* A zero track floor lets the track shrink; these let the title inside it
     actually give way, since the primary is its own flex container and a
     flex item will not go under min-content without being told to. */
  .valenmod-companion-desktop-header .valenmod-companion-header-primary,
  .valenmod-companion-desktop-header .valenmod-companion-header-primary > * { min-width: 0; }
}

/* One loading language across every companion surface and the in-Foundry
   Archive. Destination-specific copy stays in the markup; geometry,
   typography and icon treatment do not vary from app to app. */
body :is(
  .valenmod-rules-loading,
  .valenmod-party-loading,
  .chat-loading,
  .session-loading,
  .combat-loading
) {
  display: grid;
  place-content: center;
  justify-items: center;
  gap: 8px;
  width: 100%;
  height: 100%;
  min-height: 320px;
  padding: 32px;
  color: var(--valenmod-ink-dim);
  text-align: center;
}

body :is(
  .valenmod-rules-loading,
  .valenmod-party-loading,
  .chat-loading,
  .session-loading,
  .combat-loading
) > i {
  display: grid;
  width: 50px;
  height: 50px;
  margin: 0 0 6px;
  place-items: center;
  border: 1px solid color-mix(in srgb, var(--valenmod-gold) 48%, var(--valenmod-line));
  border-radius: 50%;
  color: var(--valenmod-gold);
  background: radial-gradient(circle, rgb(212 173 88 / 16%), rgb(20 35 22 / 75%));
  box-shadow: var(--valenmod-bevel), var(--valenmod-shadow-floating);
  font-size: 24px;
}

body :is(
  .valenmod-rules-loading,
  .valenmod-party-loading,
  .chat-loading,
  .session-loading,
  .combat-loading
) > h1 {
  max-width: 580px;
  margin: 0;
  color: var(--valenmod-ink);
  background: none;
  font: 700 25px/1.15 var(--valenmod-font-head);
  letter-spacing: normal;
  -webkit-text-fill-color: currentColor;
}

body :is(
  .valenmod-rules-loading,
  .valenmod-party-loading,
  .chat-loading,
  .session-loading,
  .combat-loading
) > p {
  max-width: 580px;
  margin: 0;
  color: var(--valenmod-ink-dim);
  font: 15px/1.4 var(--valenmod-font-body);
}

body :is(.valenmod-rules-loading, .valenmod-party-loading).is-error > i {
  border-color: rgb(212 106 98 / 62%);
  color: #d46a62;
  background: radial-gradient(circle, rgb(212 106 98 / 15%), rgb(32 14 14 / 76%));
}

@media (max-width: 700px), (max-device-width: 700px) {
  body.valenmod-has-mobile-app-nav {
    display: flex;
    flex-direction: column;
    height: 100dvh;
    min-height: 0;
    overflow: hidden;
  }

  .valenmod-mobile-app-nav {
    position: relative;
    z-index: var(--valenmod-z-overlay);
    display: grid;
    grid-template-columns: repeat(5, minmax(0, 1fr));
    flex: 0 0 auto;
    gap: 3px;
    width: 100%;
    padding: 3px 7px calc(3px + env(safe-area-inset-bottom));
    border-top: 1px solid #456b4e;
    background: rgb(7 16 10 / 98%);
    box-shadow: 0 -8px 24px rgb(0 0 0 / 58%);
  }

  .valenmod-mobile-app-nav.has-combat {
    grid-template-columns: repeat(6, minmax(0, 1fr));
  }

  .valenmod-mobile-app-nav > a {
    position: relative;
    display: grid;
    gap: 4px;
    place-items: center;
    align-content: end;
    min-width: 0;
    min-height: 40px;
    padding: 5px 2px 0;
    border: 1px solid transparent;
    border-radius: var(--valenmod-radius-lg);
    color: var(--valenmod-ink-dim);
    font: 700 10px/1 var(--valenmod-font-ui);
    letter-spacing: .035em;
    text-decoration: none;
    text-transform: uppercase;
    touch-action: manipulation;
  }

  .valenmod-mobile-app-nav > a[hidden] { display: none; }

  .valenmod-mobile-app-nav > a > i {
    color: var(--valenmod-ink-dim);
    font-size: 16px;
    opacity: .72;
  }

  /* The chat glyph — a figure alongside a speech bubble — extends past Font
     Awesome's default 1.25em box on mobile Safari. Let the font use its real
     advance width and keep the whole mark paintable; a guessed fixed width
     still clipped some inactive instances even though the active icon
     happened to render cleanly. */
  .valenmod-mobile-app-nav > a[data-companion-destination="chat"] > i {
    --fa-width: auto;
    min-width: 1.5em;
    overflow: visible;
    color: color-mix(in srgb, var(--valenmod-ink-dim) 72%, rgb(7 16 10));
    opacity: 1;
  }

  .valenmod-mobile-app-nav > a[aria-current="page"] {
    border-color: transparent;
    color: #fff;
    background: transparent;
    box-shadow: none;
  }

  .valenmod-mobile-app-nav > a[aria-current="page"] > i { color: #fff; opacity: 1; }

  .valenmod-mobile-app-nav > a[aria-current="page"]::before {
    position: absolute;
    top: -4px;
    right: 18%;
    left: 18%;
    height: 2px;
    border-radius: 0 0 2px 2px;
    background: var(--valenmod-gold);
    box-shadow: 0 0 7px rgb(212 173 88 / 55%);
    content: "";
  }
}

/* Keep the PF2E Death trait conspicuous wherever the system renders it.
   The selectors mirror Technicolor Traits' sheet/chat coverage and include
   Valenmod's data-trait markup used by the Rules Archive. */
:is(
  tag#death,
  .tag[data-slug="death"],
  .tag[data-tooltip="PF2E.TraitDescriptionDeath"],
  .tag[data-trait="death"]
) {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  animation: valenmod-death-trait-flare 3s ease-out infinite;
}

:is(
  tag#death,
  .tag[data-slug="death"],
  .tag[data-tooltip="PF2E.TraitDescriptionDeath"],
  .tag[data-trait="death"]
)::after {
  position: absolute;
  inset: -75% auto -75% -65%;
  z-index: 2;
  width: 58%;
  background: linear-gradient(
    90deg,
    transparent,
    rgb(255 217 106 / 28%),
    rgb(255 247 205 / 88%),
    white,
    rgb(255 247 205 / 88%),
    rgb(255 202 72 / 32%),
    transparent
  );
  box-shadow: 0 0 12px 3px rgb(255 232 154 / 72%);
  content: "";
  mix-blend-mode: screen;
  opacity: 0;
  pointer-events: none;
  transform: skewX(-18deg);
  animation: valenmod-death-trait-shine 3s ease-out infinite;
}

@keyframes valenmod-death-trait-flare {
  0%,
  28%,
  100% {
    filter: brightness(1) saturate(1) drop-shadow(0 0 0 rgb(255 209 92 / 0%));
  }

  8% {
    filter: brightness(1.65) saturate(1.35) drop-shadow(0 0 6px rgb(255 209 92 / 95%));
  }

  18% {
    filter: brightness(1.3) saturate(1.2) drop-shadow(0 0 3px rgb(255 226 143 / 72%));
  }
}

@keyframes valenmod-death-trait-shine {
  0% {
    left: -65%;
    opacity: 0;
  }

  3% {
    opacity: 1;
  }

  20% {
    left: 120%;
    opacity: 1;
  }

  24%,
  100% {
    left: 120%;
    opacity: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  :is(
    tag#death,
    .tag[data-slug="death"],
    .tag[data-tooltip="PF2E.TraitDescriptionDeath"],
    .tag[data-trait="death"]
  ) {
    animation: none;
  }

  :is(
    tag#death,
    .tag[data-slug="death"],
    .tag[data-tooltip="PF2E.TraitDescriptionDeath"],
    .tag[data-trait="death"]
  )::after {
    content: none;
  }
}

svg.valenmod-token-ring {
  position: absolute;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  pointer-events: none;
}

.valenmod-token-frame:not(.is-dynamic-ring)::before {
  position: absolute;
  inset: 3px;
  z-index: 0;
  border-radius: 50%;
  background:
    radial-gradient(circle at 48% 42%, rgb(212 173 88 / 12%), transparent 55%),
    radial-gradient(circle, rgb(6 14 8 / 78%) 0 59%, rgb(95 139 97 / 34%) 61% 65%, rgb(5 9 6 / 90%) 68% 100%);
  content: "";
  pointer-events: none;
}

/* Token art is intentionally allowed to escape its ring. The source images
   are transparent, so a circular clip only amputates weapons, limbs and hair
   without providing any useful masking. Portrait cards retain their own
   surface-specific crop. */
.valenmod-token-frame.is-token-frame > img {
  border-radius: 0;
  overflow: visible;
}
