/* /walk - the walk page.
 *
 * Everything specific to this page lives here, and style.css is not touched by
 * it. That is deliberate: style.css is loaded by every page on the live site,
 * so a tuning-tool tweak that landed in it could break the results page, and
 * would drag every visitor into a cache-buster bump for a change that was never
 * meant for them. What this file does use from style.css is the slot, the
 * search dropdown and the colour variables, all inherited unchanged. */

/* Any rule here that sets `display` on an element outranks the browser's own
 * `[hidden] { display: none }`, and the element then simply never hides. It
 * happened on the first live run: the unlock form stayed on screen with the key
 * still in it after a successful unlock, because `.dial-unlock` sets
 * `display: flex`. This page toggles most of its furniture with the `hidden`
 * attribute, so the guard goes at the top rather than being re-remembered on
 * every new rule. */
[hidden] {
  display: none !important;
}

.walk main,
main.walk {
  max-width: 820px; /* a little wider than the form: rows carry a Spotify mark
                       and, in dial mode, three numbers */
}

/* ----- The results heading ----------------------------------------------- */
/* "Albums linked to" + the album name. The label is the same on every step and
   carries no information; the album name is the only part worth reading and it
   changes every time. Giving them equal weight put the emphasis on the wrong
   half. The label steps back in both weight and brightness; the album keeps the
   heading's full colour so it reads as the subject of the page. */
.walk-head-label {
  /* Its own line, so the album starts at the left margin and is the first thing
     the eye lands on (David, 2026-08-13). A block rather than a <br> in the
     JS: the break is a layout decision and belongs in the stylesheet, and it
     also stays correct if the label wording ever changes length.

     Safe against the [hidden] guard at the top of this file - that rule is
     !important and this element is never hidden anyway. */
  display: block;
  font-weight: 400;
  font-size: 0.95rem;
  color: var(--muted);
}

.walk-head-album {
  color: var(--text);
}

/* ----- The starters ----------------------------------------------------- */

.starters {
  margin: 0 0 1.25rem;
}

.starter-list {
  list-style: none;
  margin: 0 0 0.6rem;
  padding: 0;
}

.starter-list li {
  margin-bottom: 0.35rem;
}

.starter {
  display: inline-block;
  padding: 0.4rem 0.7rem;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--panel);
  color: var(--text);
  text-decoration: none;
}

.starter:hover,
.starter:focus-visible {
  border-color: var(--accent);
  color: var(--accent);
}

.starter-again {
  border: none;
  background: none;
  padding: 0;
  color: var(--muted);
  font-size: 0.8rem;
  cursor: pointer;
  text-decoration: underline;
}

.starter-again:hover {
  color: var(--accent);
}

/* ----- The trail --------------------------------------------------------- */

.trail {
  margin: 0 0 1.25rem;
  padding: 0.6rem 0.75rem;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--panel);
  font-size: 0.9rem;
  line-height: 1.9;
}

/* Its own line above the trail, in small quiet type. The box was unlabelled and
   a row of album names with arrows between them does not announce what it is
   (David, 2026-08-13). `display: block` puts the crumbs underneath rather than
   running on from the label. */
.trail-label {
  display: block;
  font-size: 0.8rem;
  color: var(--muted);
  line-height: 1.4;
  margin-bottom: 0.15rem;
}

.trail-step {
  color: var(--accent);
  text-decoration: none;
}

.trail-step:hover,
.trail-step:focus-visible {
  text-decoration: underline;
}

.trail-here {
  color: var(--text);
  font-weight: 600;
}

.trail-sep {
  color: var(--muted);
  margin: 0 0.4rem;
}

/* The mark that says the trail has dropped its oldest hops. Present only once
   the trail is at its stored length, so its appearance is itself the signal;
   a breadcrumb that silently forgets where you came from reads as the complete
   history of the walk, which is worse than a visibly short one. */
.trail-older {
  color: var(--muted);
  cursor: help;
}

/* ----- The dial ---------------------------------------------------------- */

.dial-unlock {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
  margin: 0 0 1.5rem;
  padding: 0.75rem 0.9rem;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--panel);
  font-size: 0.9rem;
}

.dial-unlock input {
  flex: 1 1 14rem;
  padding: 0.45rem 0.6rem;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg);
  color: var(--text);
}

.dial-unlock button {
  padding: 0.45rem 0.75rem;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg);
  color: var(--text);
  cursor: pointer;
}

.dial-unlock-msg {
  color: var(--muted);
  font-size: 0.8rem;
}

.dial-unlock-msg.bad {
  color: var(--error);
}

.dial {
  margin: 0 0 1.5rem;
  padding: 0.75rem 0.9rem;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--panel);
  font-size: 0.9rem;
}

/* An off-neutral dial has to be impossible to miss. The whole risk of this tool
   is looking at a tuned list and thinking it is the live one. */
.dial.moved {
  border-color: var(--warn);
}

.dial-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
  margin-bottom: 0.5rem;
}

.dial-name {
  min-width: 11rem;
  color: var(--text);
}

.dial-name code {
  color: var(--muted);
}

.dial-btn {
  width: 2rem;
  height: 2rem;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg);
  color: var(--text);
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
}

.dial-btn:hover {
  border-color: var(--accent);
}

.dial-val {
  min-width: 3.5rem;
  text-align: center;
  font-variant-numeric: tabular-nums;
  color: var(--text);
  font-weight: 600;
}

.dial-check {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  color: var(--text);
  cursor: pointer;
}

.dial-hint {
  color: var(--muted);
  font-size: 0.8rem;
  flex: 1 1 16rem;
}

.dial-actions {
  margin-top: 0.75rem;
  margin-bottom: 0;
  border-top: 1px solid var(--border);
  padding-top: 0.75rem;
}

.dial-reset {
  padding: 0.4rem 0.75rem;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg);
  color: var(--text);
  cursor: pointer;
}

.dial-reset:hover {
  border-color: var(--accent);
}

.dial-parity {
  color: var(--muted);
  font-size: 0.8rem;
}

/* A failed parity check is not a footnote. If the neutral position does not
   reproduce the live order, every other reading off this page is worthless. */
.dial-parity.bad {
  color: var(--error);
  font-weight: 700;
}

/* ----- The list ----------------------------------------------------------
 *
 * The ids on this page are walk-* rather than the results-* the live page uses,
 * and that is not cosmetic. style.css styles the production results list by ID
 * (#results-list, #results-list li), which outranks any class rule here, so a
 * shared id silently handed this page the production layout and swallowed the
 * rank numbers whole. Found on the first live look, 2026-08-13. Keep every id
 * on this page distinct from the ones style.css knows about. */

.walk-list {
  list-style: none;
  counter-reset: walk;
  margin: 0;
  padding: 0;
}

/* The rank gutter is 1.9rem, cut from 3rem on 2026-08-13 (David, on his phone).
   The old value indented the number 0.5rem from the edge and then gave it a 2rem
   box, so roughly 48px of a ~360px phone screen was spent before the first
   letter of the album - over 13% of the width, on every row, to hold at most
   three digits.

   The number now starts at the left edge. `text-align: right` stays, so 1 to 30
   line up on the units digit and the list still scans as a column; 1.5rem holds
   three digits at this size, which is the 500-row ceiling the admin dial allows.

   Keep `position: absolute` here. The row is a flex container, and putting the
   counter in the flow would make it a flex item that shrinks a long album title
   rather than sitting beside it. */
.walk-list li {
  counter-increment: walk;
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  /* NO left padding at all, so album titles line up exactly with the h1 and the
     headings above them. The rank numbers below are switched off and the gutter
     existed only to hold them; a leftover 0.5rem was still pushing every row 8px
     right of everything else on the page, which on a phone is real width spent
     on nothing. Restore 1.9rem here if the numbers come back. */
  padding: 0.45rem 0.5rem 0.45rem 0;
  border-bottom: 1px solid var(--border);
  position: relative;
}

/* RANK NUMBERS OFF, 2026-08-13 (David: "let's hide them for now").
   Kept rather than deleted because this is a look David wants to be able to
   reverse - uncomment this rule and put the 1.9rem left padding back above.
   The counter-reset and counter-increment are left in place so it works
   immediately when uncommented.

   The argument for leaving them off: the list is already in rank order, so the
   number confirms what the position already says, and on a phone the gutter was
   costing ~13% of the screen width on every row before the first letter.

.walk-list li::before {
  content: counter(walk);
  position: absolute;
  left: 0;
  width: 1.5rem;
  text-align: right;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  font-size: 0.85rem;
}
*/

/* An error row is prose, not a ranked result. While the rank numbers are off,
   both of these do nothing - the base row already has no gutter and there is no
   ::before to suppress - but they are the pair to the commented block above and
   must come back with it, or an error message will be indented under a number
   it does not have. */
.walk-list li.error {
  padding-left: 0.5rem;
  color: var(--error);
}

.walk-list li.error::before {
  content: "";
}

/* The underline hugs the words, and does NOT stretch across the row. A
   full-width rule under every title reads as a table border and buries the
   fact that the title is the thing you click. */
.walk-label {
  color: var(--text);
  text-decoration: none;
  border-bottom: 1px solid var(--accent);
  flex: 0 1 auto;
}

.walk-label:hover,
.walk-label:focus-visible {
  color: var(--accent);
}

/* Secondary by design. Walking is the primary action on this page; the Spotify
   search is the thing you do when you have stopped walking. */
.walk-spotify {
  color: var(--muted);
  font-size: 0.75rem;
  text-decoration: none;
  white-space: nowrap;
  margin-left: auto; /* pushes this and the numbers to the right-hand edge */
}

.walk-spotify:hover {
  color: var(--accent);
}

.walk-nums {
  color: var(--muted);
  font-size: 0.75rem;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

#fallback-block {
  margin-top: 2rem;
}

#fallback-block h2 {
  font-size: 1.1rem;
  margin-bottom: 0.25rem;
}

@media (max-width: 560px) {
  .walk-list li {
    flex-wrap: wrap;
    row-gap: 0.15rem;
  }
  .dial-name {
    min-width: 0;
    flex: 1 1 100%;
  }
}

/* The crossover block to /five, added 2026-08-16 with the landing page.
 *
 * Styled to be noticed. The walk page is read-only and never improves the
 * graph, so this link is the only thing on it that can - see the comment above
 * the block in walk.html for the reasoning. It sits below the results and
 * above the byline, on screen whether or not anybody has walked anything. */
.walk-crossover {
  margin-top: 2.5rem;
  padding: 1.1rem 1.2rem;
  border: 1px solid var(--accent);
  border-radius: 10px;
  background: rgba(91, 141, 239, 0.08);
}

.walk-crossover-lead {
  color: var(--text);
  font-size: 1.05rem;
  font-weight: 600;
  margin: 0 0 0.4rem;
}

.walk-crossover-why {
  color: var(--muted);
  font-size: 0.9rem;
  margin: 0 0 0.9rem;
}

/* An <a> wearing #submit-btn's clothes, so the one action worth taking on this
   page looks like the one action worth taking on the form. */
.walk-crossover-btn {
  display: block;
  width: 100%;
  padding: 0.75rem;
  border-radius: 8px;
  background: var(--accent);
  color: var(--accent-text);
  font-size: 1rem;
  font-weight: 600;
  text-align: center;
  text-decoration: none;
}

.walk-crossover-btn:hover,
.walk-crossover-btn:focus-visible {
  text-decoration: underline;
}

/* ===================================================================== *
 * PageGen pages: link colors and row geometry, added 2026-08-24.
 *
 * BEFORE THIS THERE WAS NO LINK RULE AT ALL on any of the 2,600 album pages or
 * the /albums treetop, so every link rendered in the browser's own #0000EE and
 * visited #551A8B. Against this site's #0f1115 ground both measure 1.30:1
 * contrast, where the WCAG AA floor for body text is 4.5:1. That is not a taste
 * problem, and David found it on his phone first, where it is worst.
 *
 * The chosen treatment is /walk's own label, picked from three measured options
 * (David, 2026-08-24): full-strength --text with a thin --accent underline that
 * hugs the words. 14.6:1. Two reasons it beat an accent-colored link at 5.67:1 -
 * it is higher contrast, and it makes an album page and /walk look like one
 * system, which matters now that every row on these pages leads into /walk.
 *
 * `:visited` is --muted (7.03:1), not switched off. On pages whose whole point
 * is exploring, "you already went there" is worth knowing. Only color and
 * border-color are settable on :visited, which is exactly what this uses.
 * ===================================================================== */

/* The ranked list. Row geometry copied from .walk-list: a padded flex row with
   a hairline rule and a narrow number gutter.
   THE GUTTER IS A WIDTH SAVING, NOT A COST. 1.5rem is narrower than the
   browser's default 2rem decimal indent, so replacing the UA marker gives
   width back on a phone. That is the half of the legibility problem that was
   spacing rather than color, and it is also a bigger tap target.
   Counter named `pg`, distinct from .walk-list's `walk`, per the rule at the
   top of this file about keeping ids apart. */
.pagegen-list {
  list-style: none;
  counter-reset: pg;
  margin: 0 0 1.5rem;
  padding: 0;
}

/* GAP AND GUTTER ARE MEASURED VALUES, NOT TASTE (2026-08-28). A row now holds
   three flex children (title, year, Spotify mark) where it held one, and two
   0.6rem gaps plus a 1.9rem gutter were enough to wrap the eighth row of the
   U2 page onto a second line at 390px. 0.35rem and 1.7rem put it back on one
   line: 8 albums above the fold instead of 7, with no loss on the long-title
   page. Widen these and you spend a visible album. */
.pagegen-list li {
  counter-increment: pg;
  display: flex;
  align-items: baseline;
  gap: 0.35rem;
  padding: 0.5rem 0.25rem 0.5rem 1.7rem;
  border-bottom: 1px solid var(--border);
  position: relative;
}

.pagegen-list li::before {
  content: counter(pg);
  position: absolute;
  left: 0;
  width: 1.5rem;
  text-align: right;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  font-size: 0.85rem;
}

/* The label itself. border-bottom rather than text-decoration so the underline
   hugs the words instead of stretching the full row - a full-width rule reads
   as a table border and buries the fact that the title is the thing you click.
   Same reasoning as .walk-label, which this deliberately matches. */
.pagegen-list a,
.pagegen-lede a,
.pagegen-more a {
  color: var(--text);
  text-decoration: none;
  border-bottom: 1px solid var(--accent);
}

.pagegen-list a:visited,
.pagegen-lede a:visited,
.pagegen-more a:visited {
  color: var(--muted);
  border-bottom-color: var(--border);
}

.pagegen-list a:hover,
.pagegen-list a:focus-visible,
.pagegen-lede a:hover,
.pagegen-lede a:focus-visible,
.pagegen-more a:hover,
.pagegen-more a:focus-visible {
  color: var(--accent);
}

/* Secondary by design, same as .walk-spotify: this is the way back out, not
   the thing to do on the page. */
.pagegen-home a {
  color: var(--muted);
  text-decoration: none;
  font-size: 0.9rem;
}

.pagegen-home a:hover,
.pagegen-home a:focus-visible {
  color: var(--accent);
}

/* The /albums treetop. Same colors, but NOT the row geometry: 2,600 hairline
   rules is noise, and the A-Z list is an index rather than a ranked answer.
   The extra line-height is for tap targets on a phone. */
.pagegen-index {
  margin: 0 0 1.5rem;
  padding-left: 1.2rem;
}

.pagegen-index li {
  padding: 0.15rem 0;
}

.pagegen-index a {
  color: var(--text);
  text-decoration: none;
  border-bottom: 1px solid var(--accent);
}

.pagegen-index a:visited {
  color: var(--muted);
  border-bottom-color: var(--border);
}

.pagegen-index a:hover,
.pagegen-index a:focus-visible {
  color: var(--accent);
}

/* PageGen album pages, 2026-08-28: the year, the top three, and the block of
 * prose that moved below the list.
 *
 * WHY ANY OF THIS EXISTS. GA for Aug 21-27 showed eight distinct people
 * averaging ONE SECOND on /album/arctic-monkeys-am, a median around 13s across
 * 31 single-visitor pages, and zero key events from any album page ever. The
 * page was thirty rows that all looked the same, under prose taking 63% of a
 * phone's first screen (75% on a long album title). Measured at 390x754, the
 * rewrite puts 8 albums on the first screen instead of 6, and 5 instead of 3
 * on a long title.
 * ===================================================================== */

/* The release year. Muted and small: it is an aid to scanning, not a column,
   and it must never compete with the album name that is the thing to click.
   `tabular-nums` so a stack of years lines up rather than shimmering.
   NOT the full date - /walk prints the ISO date and it reads as noise. */
.pagegen-year {
  color: var(--muted);
  font-size: 0.75rem;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* The top three. The engine knows row 1 is a far stronger match than row 30
   and the page used to throw that away. Deliberately restrained: a slightly
   larger label and an accent-coloured rank number, no bold, no rule, no
   background. Enough to give the eye somewhere to land, not enough to look
   like a different kind of thing. */
/* WEIGHT, NEVER SIZE. A 1.08rem label was tried first and measured: it grew
   the row and cost one visible album on the long-title page (4 instead of 5).
   Weight reads as emphasis without reflowing anything. */
.pagegen-list li.top a:first-child {
  font-weight: 600;
}

.pagegen-list li.top::before {
  color: var(--accent);
}

/* The prose that used to sit above the list. Google lifts the h1 and the list
   items for the snippet and never the lede, so moving it down cost nothing
   there and bought 96px at the top of a phone screen. Muted because a reader
   who has reached it has already passed the thirty rows they came for. */
.pagegen-tail {
  margin-top: 2rem;
  color: var(--muted);
  font-size: 0.9rem;
  line-height: 1.6;
}

.pagegen-tail p {
  margin: 0 0 0.75rem;
}

/* PageGen album pages: the sibling line at the foot, added 2026-08-24 with the
 * change that sent every album name in the list into /walk.
 *
 * DELIBERATELY QUIET, including the links. It exists to keep descriptive anchor
 * text pointing at the album pages now that the rows no longer do, and David's
 * condition for having it at all was that a reader can ignore it. Muted links
 * are that condition in CSS. See sibling_line() in PageGen/pagegen.py for the
 * argument, and for why it is expected to be deleted once PageGen-artist
 * ships. */
.pagegen-siblings {
  margin-top: 1.75rem;
  color: var(--muted);
  font-size: 0.85rem;
  line-height: 1.7;
}

.pagegen-siblings a {
  color: var(--muted);
}

.pagegen-siblings a:hover,
.pagegen-siblings a:focus-visible {
  color: var(--accent);
}

/* PageGen treetop (/albums): the count line above the A-Z index. */
.pagegen-count {
  margin: 0 0 0.35rem;
  font-size: 1.15rem;
}
