{{define "title"}}{{.Mark.Name}} — {{.SiteTitle}}{{end}} {{/* One item, wherever it's sitting. Worn, backpack, and vault all show the same facts; only the panel around them differs. The description and the effect line come from gogobee already resolved — Pete renders them, it does not compute them. "inert" is the honest word for a worn item that wants a bond and hasn't got one: it's on you and doing nothing. */}} {{define "itemrow"}}
  • {{.Name}}{{if .Temper}} +{{.Temper}}{{end}} {{if .Tier}}T{{.Tier}}{{end}}{{if .Value}}{{if .Tier}} · {{end}}{{.Value}}g{{end}}
    {{if or .Slot .SkillSource .Attunement}}
    {{if .Slot}}{{.Slot}}{{end}} {{if .SkillSource}}{{.SkillSource}}{{end}} {{if .Attunement}}{{if .Attuned}}bonded{{else if .Worn}}inert · no bond free{{else}}needs a bond{{end}}{{end}}
    {{end}} {{if .Desc}}

    {{.Desc}}

    {{end}} {{if .Effect}}

    {{.Effect}}

    {{end}} {{/* The compare card: how this backpack item stacks up against what's worn in the slot it would equip into. gogobee decided the verdict and the per-stat deltas (it holds the tempering and bond math); Pete only colours them. The verdict chip always shows — a phone has no hover to lean on — with the deltas beside it, each already flagged better/worse. */}} {{with .Compare}}
    {{if eq .Verdict "upgrade"}}↑ upgrade {{else if eq .Verdict "downgrade"}}↓ downgrade {{else if eq .Verdict "sidegrade"}}⇄ sidegrade {{else if eq .Verdict "new"}}✦ fills {{.VsSlot}} {{else if eq .Verdict "inert"}}⚠ would sit inert {{else if eq .Verdict "same"}}= no change{{end}} {{range .Deltas}}{{.Text}}{{end}}
    {{if .VsName}}

    vs worn {{.VsName}}

    {{end}} {{end}} {{if .EquipAction}}
    {{end}}
  • {{end}} {{/* The dungeon map. Laid out server-side (who_map.go) into an x/y node field; this just draws it. Edges first so nodes sit on top of the lines. Nothing here is a player-authored string — node kinds are a fixed vocabulary and ids are zone-prefixed — so the SVG carries no injection surface. */}} {{define "dungeonmap"}} {{range .Edges}}{{if .Lock}}{{.Lock}}{{end}}{{end}} {{range .Nodes}}{{if .Current}}{{end}}{{.Glyph}}{{.Label}}{{if .Current}} — you are here{{end}}{{end}} {{end}} {{define "main"}}

    adventurer

    {{.Mark.Name}}

    Level {{.Mark.Level}} {{.Mark.ClassRace}}

    {{if .Mark.OnRun}}{{.Mark.Where}}{{else}}In town{{if .Mark.Idle}} · {{.Mark.Idle}}{{end}}{{end}}

    {{if .HasDetail}}

    Vitals

    Hit points {{.Detail.HPCurrent}} / {{.Detail.HPMax}}{{if .Detail.TempHP}} +{{.Detail.TempHP}}{{end}}
    Armor class {{.Detail.ArmorClass}}
    {{range .Abilities}}
    {{.Label}}
    {{.Score}}
    {{.ModStr}}
    {{end}}
    {{if .Mark.OnRun}}
    {{if .Detail.Room}}
    Room{{.Detail.Room}}
    {{end}}
    Supplies{{.Detail.Supplies}}
    {{if .Detail.ThreatLevel}}
    Threat{{.Detail.ThreatLevel}}
    {{end}}
    {{end}} {{/* The party. Absent on a solo run, so this block answers "is anybody else down there" rather than drawing a chair count. Server-rendered only: a roster is settled before a party leaves town, so unlike the HP and supply numbers above it there is nothing here for the poll to move. An unnamed seat is an opted-out player, kept on purpose — see partySeat.Anonymous for why it is not simply dropped. */}} {{if .Detail.Party}}

    Down there together

      {{range .Detail.Party}}
    • {{.Kind}} {{if .Anonymous}} an adventurer who keeps out of the news {{else if .Token}} {{.Name}} {{else}} {{.Name}} {{end}} {{if .Level}}lv {{.Level}}{{end}}
    • {{end}}
    {{end}}
    {{/* Public gear list. Hidden only when the owner's "Equipment" panel below will actually render (it needs pushed Slots) — otherwise an owner whose detail predates ask 7's Slots would see no standard gear at all. */}} {{if not .Self.Slots}}

    Gear

    {{if .Detail.Gear}}
      {{range .Detail.Gear}}
    • {{.Slot}} {{.Name}}{{if .Masterwork}} {{end}} T{{.Tier}}{{if .Condition}} · {{.Condition}}%{{end}}
    • {{end}}
    {{else}}

    Traveling light — nothing equipped.

    {{end}}
    {{end}}
    {{if .MapView}}

    The map

    {{if .Detail.Room}}Room {{.Detail.Room}}{{end}}
    {{template "dungeonmap" .MapView}}
    entrance boss unexplored locked door
    {{end}} {{else}}

    No detailed sheet on file for this adventurer yet — check back after the next snapshot.

    {{end}}

    The run

    {{if .RunLog.Live}}under way{{else if .RunLog.Outcome}}{{.RunLog.Outcome}}{{else}}finished{{end}}{{if .RunLog.Rooms}} · room {{.RunLog.Rooms}}{{end}}
      {{range .RunLog.Lines}}
    1. {{.Text}} {{if .Room}}{{.Room}} · {{end}}{{.When}}
    2. {{end}}
    The full report
    {{if .HasSelf}}

    Your call

    Asked for here, done on the game box. It picks these up within a few seconds.

    {{/* data-offer marks what stops being true once the extraction lands: there is no run left to pull out of. Hidden by the script on an applied verdict, restored on a refusal, which is the one case where the reader still needs the retry. */}}
    {{/* W5b. Everything below is server-rendered from the offer list gogobee pushed onto this owner's own private row, so the page can only ever propose a zone, a loadout and a price the game itself quoted. The order carries those keys back and gogobee re-resolves all of them — an offer is a quote, never a permission. */}} {{if .Self.Resume}} {{/* The way back in, first: it is the only offer here with a deadline on it, and it is the answer to the verdict "Pull out" leaves behind, which until now told a web player to go and type !resume in Matrix. */}}

    Go back in

    {{.Self.Resume.Display}}, day {{.Self.Resume.Day}} — waiting where you left it. {{with untilUnix .Self.Resume.ExpiresAt}}{{.}}.{{end}} You re-stock before you go, so pick a pack.

    {{$rz := .Self.Resume}} {{range $rz.Loadouts}} {{end}}
    {{end}} {{if .Self.Zones}} {{/* Set out. The zone list is already level-gated and postgame-gated by gogobee, and it arrives EMPTY while this adventurer is already out — which is why there is no "you're on an expedition" branch here. */}}

    Set out

    Pick where, then pick how much to carry. The pack is what you pay for.

    {{/* One group per zone, all rendered, one shown. The costs differ by tier, so a single shared row of buttons would have to be repriced in the browser — and Pete does no arithmetic on the game's money. */}} {{range .Self.Zones}} {{$z := .}} {{end}}
    {{end}} {{if .Self.Babysit}}

    The sitter

    {{if .Self.Babysit.Active}} {{/* Engaged: say so and offer nothing. Buying a second one is refused by the game anyway, and a buy button under "already engaged" reads as a page that has not noticed. */}}

    Somebody is looking after the camp{{with untilUnix .Self.Babysit.ExpiresAt}} — {{.}}{{end}}. Your pet is being tended daily and standard camps rest like fortified ones.

    {{else}}

    Pet tended daily, standard camps rest like fortified ones, rival duels declined for you.

    {{end}}
    {{end}}
    {{end}} {{if .HasHistory}}

    The record

    {{.Trophies.BossKills}}
    bosses down
    {{.Trophies.ZoneClears}}
    zones cleared
    {{.Trophies.TreasuresFound}}
    treasure{{if ne .Trophies.TreasuresFound 1}}s{{end}}
    {{.Trophies.Deaths}}
    death{{if ne .Trophies.Deaths 1}}s{{end}}
    {{.Trophies.Retreats}}
    walked out
    {{if or .Trophies.BossFirsts .Trophies.ZoneFirsts .Trophies.TreasureFirsts}}

    ★ {{if .Trophies.BossFirsts}}{{.Trophies.BossFirsts}} realm-first boss{{if ne .Trophies.BossFirsts 1}}es{{end}}{{end}}{{if and .Trophies.BossFirsts (or .Trophies.ZoneFirsts .Trophies.TreasureFirsts)}}, {{end}}{{if .Trophies.ZoneFirsts}}{{.Trophies.ZoneFirsts}} first clear{{if ne .Trophies.ZoneFirsts 1}}s{{end}}{{end}}{{if and .Trophies.ZoneFirsts .Trophies.TreasureFirsts}}, {{end}}{{if .Trophies.TreasureFirsts}}{{.Trophies.TreasureFirsts}} first hoard{{if ne .Trophies.TreasureFirsts 1}}s{{end}}{{end}}. Nobody had done it before.

    {{end}}
    {{if .Trophies.Bosses}}

    Bosses fought

      {{range .Trophies.Bosses}}
    • {{.Boss}}{{if .First}} {{end}} ×{{.Kills}}
    • {{end}}
    {{end}} {{if .Trophies.Zones}}

    Ground covered

      {{range .Trophies.Zones}}
    • {{.Zone}}{{if .First}} {{end}}{{if .Region}} {{.Region}}{{end}} ×{{.Clears}}
    • {{end}}
    {{end}}
    {{if .Trophies.Treasures}}

    Treasures found

      {{range .Trophies.Treasures}}
    • 💎 {{.Item}}{{if .First}} {{end}} {{if .Zone}}{{.Zone}}{{end}}
    • {{end}}
    {{end}} {{if .Trophies.Milestones}}

    Milestones

    {{range .Trophies.Milestones}} 🏅 {{.}} {{end}}
    {{end}}

    The trail

      {{range .Timeline}}
    1. {{.Label}} {{.When}}
      {{if .Line}}

      {{.Line}}

      {{end}}
    2. {{end}}
    {{if .MoreHistory}}

    Showing the most recent {{len .Timeline}}. The counts above cover everything.

    {{end}}
    {{end}} {{if .HasSelf}}
    Your adventurer only you can see the panels below
    {{/* Equipment: the 5 standard slots, owner-only management. Take off round-trips a masterwork/arena piece to the pack (no money); Upgrade buys the next tier and Repair mends condition, both spending euros behind a confirm that shows the cost and the resulting balance. Every price and tier here is gogobee's, resolved server-side — the buttons only carry what was pushed. */}} {{if .Self.Slots}}

    Equipment

    Balance €{{printf "%.2f" .Self.Balance}}
      {{range .Self.Slots}}
    • {{.Slot}} T{{.Tier}}{{if .Condition}} · {{.Condition}}%{{end}}
      {{.Name}} {{if .Masterwork}}{{end}} {{if .ArenaTier}}arena T{{.ArenaTier}}{{end}}
      {{if or .CanTakeOff .NextTier .RepairCost}}
      {{if .CanTakeOff}}{{end}} {{if .NextTier}}{{end}} {{if .RepairCost}}{{end}}
      {{end}}
    • {{end}}
    {{end}}

    Home

    House tier{{if .Self.House.Tier}}{{.Self.House.Tier}}{{else}}no house{{end}}
    {{if .Self.House.LoanBalance}}
    Loan balance{{.Self.House.LoanBalance}}
    {{end}} {{if .Self.House.Rate}}
    Rate{{.Self.House.Rate}}
    {{end}} {{if .Self.House.Autopay}}
    Autopayon
    {{end}}
    {{/* Pets, with their levelling shown. They have been earning XP from every won fight since that wiring was fixed, and until now the only place a level appeared was a Matrix line that scrolled away. Ranges over .PetRows, not .Self.Pets: the progress figures are worked out in Go from the centi-XP gogobee sends, because the curve behind the target is the engine's and there is no copy of it here. */}}

    Pets

    {{if .PetRows}}
      {{range .PetRows}}
    • {{if .Name}}{{.Name}}{{else}}your {{.Type}}{{end}} {{.Type}} lv {{.Level}}{{if .ArmorTier}} · barding T{{.ArmorTier}}{{end}}

      {{if .Capped}}fully grown{{else}}{{.Progress}} to level {{.NextLevel}}{{end}}

    • {{end}}
    {{else}}

    No pets right now.

    {{end}}
    {{if .Worn}}

    Worn

    {{.BondsUsed}} of 3 bonds in use

      {{range .Worn}}{{template "itemrow" .}}{{end}}

    Backpack

    {{else}}

    Backpack

    {{end}} {{if .Backpack}}
      {{range .Backpack}}{{template "itemrow" .}}{{end}}
    {{else}}

    Backpack's empty.

    {{end}} {{if .VaultRows}}

    Vault

      {{range .VaultRows}}{{template "itemrow" .}}{{end}}
    {{end}}
    {{end}}
    {{end}} {{define "scripts"}}{{end}}