/* Achievement checker (D-17). Reuses the dashboard's tokens and .card/.build-stats
   styles from style.css; this file only adds what the checker page needs. */

.ac-main { max-width: 1000px; margin: 0 auto; padding: 18px 22px 40px; }
@media (max-width: 560px) { .ac-main { padding: 14px 16px 32px; } }

.back-link { color: var(--muted); text-decoration: none; font-size: 14px; }
.back-link:hover { color: var(--text); }

/* Breadcrumb header: "Duke's Valheim Dashboard › Achievement Tracker — Norse Code", the first crumb
   a home link. Overrides the shared .brand-name (20px/600 in style.css) to lay the crumbs on a
   wrapping baseline row; shrinks on a phone so it never forces sideways scroll (Ed, 2026-09-28). */
.brand-name { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 7px; }
.brand-home { color: var(--accent); text-decoration: none; }
.brand-home:hover { text-decoration: underline; }
.brand-sep { color: var(--muted); font-weight: 400; }
.brand-crumb { color: var(--text); }
.brand-tag { color: var(--muted); font-weight: 400; font-size: 16px; }
@media (max-width: 560px) {
  .brand-name { font-size: 16px; }
  .brand-tag { font-size: 13px; }
}

.intro h3 { margin-top: 0; }
.intro p { color: var(--text); line-height: 1.6; }
.intro code { background: var(--panel-2); padding: 1px 5px; border-radius: 4px; font-size: 13px; }
.privacy {
  display: flex; gap: 10px; align-items: baseline;
  margin: 14px 0 0; padding: 12px 14px; border-radius: 8px;
  background: rgba(76, 175, 125, .1); border: 1px solid rgba(76, 175, 125, .35);
}
.privacy .lock { font-size: 16px; }

/* Drop zone */
.dropzone {
  border: 2px dashed var(--line); border-radius: 14px;
  background: var(--panel-2);
  padding: 40px 20px; text-align: center; cursor: pointer;
  transition: border-color .15s, background .15s;
}
.dropzone:hover, .dropzone:focus-visible { border-color: var(--accent); outline: none; }
.dropzone.dragover { border-color: var(--accent); background: rgba(217, 164, 65, .1); }
.drop-rune { font-size: 40px; color: var(--accent); line-height: 1; margin-bottom: 8px; }
.drop-title { font-size: 17px; font-weight: 600; margin: 4px 0; }
.drop-title code { background: var(--panel); padding: 1px 6px; border-radius: 4px; }
.drop-or { color: var(--muted); margin: 4px 0 0; }

.btn {
  font: inherit; font-weight: 600; color: var(--bg); background: var(--accent);
  border: none; border-radius: 8px; padding: 7px 16px; cursor: pointer;
}
.btn:hover { filter: brightness(1.08); }
/* Secondary/outlined button: the folder enhancement and its character picks read as an alternative
   to the primary dropzone, not a second solid gold call-to-action competing with it. */
.btn-ghost {
  background: transparent; color: var(--accent);
  border: 1px solid rgba(217, 164, 65, .55);
}
.btn-ghost:hover { filter: none; background: rgba(217, 164, 65, .12); }

/* Chromium "point at your folder" enhancement (ticket 09): hidden until achievements.js confirms the
   File System Access API, so non-Chromium browsers never see a dead button. Centred under the
   dropzone, with an honest "read in your browser" hint. */
.folder-pick { text-align: center; margin-top: 16px; }
.folder-or { color: var(--muted); font-size: 13px; margin: 0 0 12px; }
.folder-hint { font-size: 12.5px; margin: 8px 0 0; line-height: 1.45; }
.folder-list { margin-top: 14px; }
.folder-list-label { color: var(--muted); font-size: 13px; margin: 0 0 10px; }
.folder-chars { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; }
.folder-char { font-size: 14px; }
.folder-note { color: var(--muted); font-size: 13px; font-style: italic; margin: 0; }

.where { margin-top: 14px; font-size: 14px; }
.where summary { cursor: pointer; color: var(--muted); }
.where summary:hover { color: var(--text); }
.where ul { margin: 8px 0; padding-left: 18px; }
.where code { background: var(--panel-2); padding: 1px 5px; border-radius: 4px; font-size: 12.5px; word-break: break-all; }

.error-card { border-left: 3px solid var(--red); }
.error-card h3 { margin-top: 0; color: var(--red); }

/* Best-effort banner (ticket 08): shown when a character file parsed at a profile version this
   checker hasn't validated (numbers may be off), or on its own when a moved format stopped the read
   partway. Gold caveat treatment — like the difficulty-gated notes — deliberately NOT the red of the
   error card, which is reserved for the hard "not a character file" (checksum) reject. */
.best-effort-card { border-left: 3px solid var(--accent); }
.be-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 8px; }
.be-head h3 { margin: 0; color: var(--accent); font-size: 18px; }
.pill-caveat { background: rgba(217, 164, 65, .15); color: var(--accent); border-color: rgba(217, 164, 65, .4); }
.be-body { color: var(--text); line-height: 1.6; margin: 0 0 4px; }

.be-diag { margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--line); }
.be-diag-label { color: var(--muted); font-size: 13px; line-height: 1.5; margin: 0 0 8px; }
.be-diag-label strong { color: var(--text); }
.be-diag-text {
  width: 100%; resize: vertical; box-sizing: border-box;
  background: var(--panel-2); color: var(--text); border: 1px solid var(--line); border-radius: 8px;
  padding: 10px 12px; font: 12.5px/1.5 ui-monospace, "Cascadia Code", Consolas, monospace;
}
.be-diag-text:focus-visible { outline: none; border-color: var(--accent); }
.be-actions { display: flex; align-items: center; gap: 12px; margin-top: 10px; flex-wrap: wrap; }
.be-copied { color: var(--green); font-size: 13px; }

/* Character summary */
.summary-head { display: flex; align-items: center; gap: 12px; margin-bottom: 14px; flex-wrap: wrap; }
.summary-head h3 { margin: 0; font-size: 24px; }
#reported-note { margin-top: 14px; }

/* Boss chips */
.chips { display: flex; flex-wrap: wrap; gap: 8px; }
.chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 12px; border-radius: 999px; font-size: 13px; font-weight: 600;
  background: rgba(217, 164, 65, .13); color: var(--accent); border: 1px solid rgba(217, 164, 65, .4);
}
.chip.none { background: var(--panel-2); color: var(--muted); border-color: var(--line); font-weight: 500; }

/* Achievements (ticket 03): the X-of-N glance + drill-in what's-missing list. */
.ach-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.ach-head h3 { margin: 0; }
#cat-version { white-space: nowrap; }

/* Overview (D-17 readability): the at-a-glance summary at the top of the board, so the whole picture
   is visible without scrolling the 53 rows. Reuses the share card's own progress math (shareCardModel)
   so it never drifts from the report below it. */
.ach-overview { margin: 14px 0 0; }
.ach-overview-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.ach-overview-title { font-size: 14px; font-weight: 600; color: var(--text); }
.ach-overview-right { display: flex; align-items: baseline; gap: 10px; }
.ach-overview-pct { font-size: 22px; font-weight: 700; color: var(--accent); line-height: 1; font-variant-numeric: tabular-nums; }
.ach-overview-count { font-size: 13px; color: var(--muted); }
.ach-overview > .meter { height: 8px; margin-top: 8px; }
.ach-overview-bars { display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: 12px 20px; margin-top: 16px; }
.ov-bar-top { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.ov-bar-name { font-size: 13px; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ov-bar-count { font-size: 12px; color: var(--muted); white-space: nowrap; font-variant-numeric: tabular-nums; }
.ov-bar > .meter { margin-top: 5px; }
.ov-bar.done .ov-bar-count { color: var(--green); }
.ov-bar.done .meter-fill { background: var(--green); }
.ach-overview-caveat { font-size: 12.5px; color: var(--muted); font-style: italic; margin: 14px 0 0; }
.ach-overview-divider { border: none; border-top: 1px solid var(--line); margin: 18px 0 2px; }

.ach { padding: 10px 0; border-top: 1px solid var(--line); }
.ach:first-child { padding-top: 4px; border-top: none; }

/* Group divider: separates the collection board from the counting achievements (ticket 05).
   The first item under a label sits flush — the label's own top border is the separator, so
   the item skips its. */
.ach-group { display: flex; flex-direction: column; gap: 2px; padding: 20px 0 4px; margin-top: 6px; border-top: 1px solid var(--line); }
.ach-group:first-child { padding-top: 2px; margin-top: 0; border-top: none; }
.ach-group-title { font-size: 12px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.ach-group-sub { font-size: 12.5px; color: var(--muted); line-height: 1.45; }
.ach-group + .ach { border-top: none; padding-top: 8px; }

.ach-row { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; }
/* Name + blurb share ONE line (were stacked — the single biggest row-height cut). The blurb
   truncates with an ellipsis so it never wraps to a second line, and drops out entirely at phone
   width where the name + count is enough. */
.ach-title { display: flex; flex-direction: row; align-items: baseline; gap: 8px; min-width: 0; }
.ach-name { font-size: 15px; font-weight: 600; color: var(--text); white-space: nowrap; flex: 0 1 auto; overflow: hidden; text-overflow: ellipsis; }
.ach-blurb { font-size: 13px; color: var(--muted); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1 1 auto; }
@media (max-width: 560px) { .ach-blurb { display: none; } }

.ach-count { display: flex; align-items: baseline; gap: 6px; white-space: nowrap; }
.ach-count .ach-x { font-size: 21px; font-weight: 700; color: var(--accent); line-height: 1; }
.ach-count .ach-of { font-size: 13px; color: var(--muted); }
.ach.done .ach-count .ach-x { color: var(--green); }

/* Progress meter */
.meter { height: 5px; margin-top: 8px; border-radius: 999px; background: var(--panel-2); overflow: hidden; }
.meter-fill { height: 100%; border-radius: 999px; background: var(--accent); transition: width .2s ease; }
.ach.done .meter-fill { background: var(--green); }

/* What's-missing drill-in */
.ach-missing { margin-top: 12px; }
.ach-missing summary { cursor: pointer; color: var(--muted); font-size: 13px; }
.ach-missing summary:hover { color: var(--text); }
.ach-missing[open] summary { color: var(--text); margin-bottom: 10px; }
.missing-chips { display: flex; flex-wrap: wrap; gap: 7px; }
/* A "still to do" chip reads as outstanding, not as an earned/gold achievement chip. */
.chip.missing { background: var(--panel-2); color: var(--muted); border: 1px dashed var(--line); font-weight: 500; }

/* Full-member drill-in (§6): every member — done AND missing — collapsed by type, so "the ones I
   have" are visible and 462 pieces stay navigable. Two levels of <details>: the section's own, then
   one per type-group with a per-group count. Each member is a condensed cell with an icon slot (a
   letter placeholder now; the extracted game icon in Phase D) and a wiki link. */
.ach-members { margin-top: 12px; }
.ach-members > summary { cursor: pointer; color: var(--muted); font-size: 13px; }
.ach-members > summary:hover { color: var(--text); }
.ach-members[open] > summary { color: var(--text); margin-bottom: 6px; }

.member-group { margin: 2px 0; border-top: 1px solid var(--line); }
.member-group > summary { cursor: pointer; font-size: 12.5px; color: var(--muted); padding: 7px 0; list-style: none; display: flex; align-items: center; gap: 7px; font-variant-numeric: tabular-nums; }
.member-group > summary::-webkit-details-marker { display: none; }
.member-group > summary::before { content: "▸"; font-size: 9px; }
.member-group[open] > summary::before { content: "▾"; }
.member-group > summary:hover { color: var(--text); }
.member-group.done > summary { color: var(--green); }

.member-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(156px, 1fr)); gap: 6px; padding: 4px 0 12px; }
.member { display: flex; align-items: center; gap: 8px; padding: 5px 9px; border-radius: 8px; font-size: 12.5px;
  line-height: 1.3; text-decoration: none; border: 1px solid var(--line); background: var(--panel-2); min-width: 0; }
a.member:hover { border-color: var(--accent); }
.member-icon { flex: 0 0 auto; width: 20px; height: 20px; border-radius: 5px; display: inline-flex; align-items: center;
  justify-content: center; font-size: 11px; font-weight: 700; background: var(--panel); color: var(--muted); border: 1px solid var(--line); }
/* When the member-icon is a real extracted game icon (D-b), fit the sprite inside the same box. */
img.member-icon { object-fit: contain; padding: 1px; }
/* Names wrap in full rather than truncate — Ed: the cut-off "Blackmarble Bas…" names. overflow-wrap
   breaks the long single-word tokens (Blackmarble2x2x1) so nothing spills the cell. */
.member-name { min-width: 0; overflow-wrap: anywhere; }
.member.done { color: var(--text); }
.member.done .member-name::after { content: " ✓"; color: var(--green); font-weight: 700; }
.member.done .member-icon { color: var(--green); border-color: rgba(76, 175, 125, .4); }
.member.missing { color: var(--muted); border-style: dashed; }
.member-note { font-size: 12px; color: var(--muted); font-style: italic; margin: 10px 0 2px; }

/* Spoiler (v4.37): an unbeaten boss's name behind a Reddit-style click-to-reveal block. A native
   <details> — the cover is its <summary>, so click / tap / Enter reveals with no script (it works in a
   saved copy too) and the cover then disappears, leaving the real name. Only the biome shows before. */
.spoiler { display: inline-block; min-width: 0; max-width: 100%; vertical-align: middle; }
.spoiler > summary { list-style: none; }
.spoiler > summary::-webkit-details-marker { display: none; }
.spoiler-cover { display: inline-flex; align-items: center; gap: 7px; cursor: pointer; padding: 1px 7px 1px 2px;
  border-radius: 6px; background: #0b0d10; color: var(--muted); border: 1px solid var(--line); }
.spoiler-cover:hover { border-color: var(--accent); color: var(--text); }
.spoiler-cover:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.spoiler-tag { font-size: 10px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  color: var(--bg); background: var(--muted); border-radius: 4px; padding: 0 5px; line-height: 1.6; }
.spoiler-cover:hover .spoiler-tag { background: var(--accent); }
.spoiler[open] > .spoiler-cover { display: none; }
.spoiler-body { display: inline-flex; align-items: center; gap: 8px; min-width: 0; }
/* Inside a member cell the spoiler takes the cell's whole width, so the cover reads as the cell. */
.member > .spoiler { flex: 1 1 auto; }
.member > .spoiler > .spoiler-cover { display: flex; padding: 2px 6px 2px 2px; }
.member > .spoiler[open] > .spoiler-cover { display: none; }
.chip > .spoiler > .spoiler-cover { background: transparent; border: none; padding: 0; }
.ach-name > .spoiler > .spoiler-cover { font-weight: 600; }

.ach-done-note { margin: 10px 0 0; color: var(--green); font-size: 13px; }
/* Counting achievement (ticket 05): the "N more to go" line under an in-progress counter. */
.ach-progress-note { margin: 10px 0 0; color: var(--muted); font-size: 13px; }

/* Trophy Collector when the trophy list couldn't be decoded from the file — honest, not broken. */
.ach-count .ach-x-na { font-size: 21px; font-weight: 700; color: var(--muted); line-height: 1; }
.ach-note-degraded { margin: 8px 0 0; color: var(--muted); font-size: 13px; font-style: italic; }

/* Boss achievement: a binary "felled / not yet" read from this character's own kill counts — no
   meter, a status label instead. Felled is the boss-down green; not-yet is muted; "down in our world"
   (felled in the shared world but not by this character) is a smaller muted note. Also used by the
   binary scalar achievements (die once, boss with a friend, …). */
.ach-boss-status { font-size: 15px; font-weight: 700; white-space: nowrap; }
.ach-boss-status.down { color: var(--green); }
.ach-boss-status.pending { color: var(--muted); }
.ach-boss-status.world { color: var(--muted); font-size: 12.5px; font-weight: 600; }

/* Difficulty-gated (ticket 06): the deed is proven but not the tier — "done — difficulty unknown".
   Marked in the accent gold, deliberately NOT the green of a confirmed done, so a complete one
   never reads as the hard-mode Steam unlock the save can't see. */
.ach.diff-gated .ach-count .ach-x { color: var(--accent); }
.ach.diff-gated .meter-fill { background: var(--accent); }
.ach-diff-note { margin: 10px 0 0; color: var(--accent); font-size: 13px; }

/* "coming" (pending): derivable, but a target still ships in the game's asset bundle — flagged in the
   accent gold (like the difficulty caveat) so it reads as "on the way", not a failure. Reason on hover. */
.ach-pending .ach-count { align-items: center; }
.ach-pending-tag {
  font-size: 11px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
  color: var(--accent); background: rgba(217, 164, 65, .13); border: 1px solid rgba(217, 164, 65, .4);
  padding: 3px 9px; border-radius: 999px; white-space: nowrap; cursor: default;
}

/* "not in save" (gap): a world-state or per-species fact the character file genuinely doesn't record.
   Muted, present on the board and honestly flagged, never a false 0 or tick. Retires "check Steam".
   The specific reason is on hover (the group sub-line frames the theme in view). */
.ach-gap .ach-count { align-items: center; }
.ach-gap-tag {
  font-size: 11px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
  color: var(--muted); background: var(--panel-2); border: 1px solid var(--line);
  padding: 3px 9px; border-radius: 999px; white-space: nowrap; cursor: default;
}

/* Compound achievement (Forager, That Can't Be an Accident): a chip per required condition under the
   X-of-N glance. A met condition reads as an earned green chip; an unmet one as an outstanding one. */
.compound-chips { margin-top: 12px; }
.chip.have { background: rgba(76, 175, 125, .13); color: var(--green); border: 1px solid rgba(76, 175, 125, .4); }

/* A tally cell reuses .build-stats/.stat from style.css; add the count-forward variant. */
.build-stats .stat.tally { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.build-stats .stat.tally .stat-label { font-size: 13px; color: var(--text); }
.build-stats .stat.tally .stat-num { font-size: 18px; color: var(--accent); }

/* Character-stats card (ticket 07): the kills/deaths/trophies tiles reuse .build-stats; skills get
   their own compact grid, each cell a name + integer level over a level meter (reusing .meter). */
.skills-head { margin: 18px 0 10px; font-size: 12px; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--muted); }
.skills-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 10px; }
.skill { background: var(--panel-2); border: 1px solid var(--line); border-radius: 10px; padding: 10px 12px; }
.skill-top { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.skill-name { font-size: 13px; color: var(--text); }
.skill-level { font-size: 18px; font-weight: 700; color: var(--accent); font-variant-numeric: tabular-nums; }
.skill .meter { margin-top: 8px; }

.section-empty { color: var(--muted); font-style: italic; }

/* Save a copy + Share as image (ticket 10): the two-button actions bar at the top of the report,
   and the glance-only PNG preview that "Share as image" reveals below it. */
.ac-actions-row { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.ac-actions-note { font-size: 12.5px; }
.share-preview { margin-top: 16px; padding-top: 16px; border-top: 1px solid var(--line); }
.share-img {
  display: block; max-width: 100%; height: auto;
  border: 1px solid var(--line); border-radius: 10px; background: var(--bg);
}
.share-preview-actions { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-top: 12px; }
.share-preview-actions .btn { text-decoration: none; }   /* the download is an <a> styled as a button */

.ac-foot { text-align: center; margin-top: 24px; }
.ac-foot code { color: var(--text); }
