:root {
  color-scheme: dark;
  --bg: #111319;
  --panel: #1a1e27;
  --panel-strong: #222734;
  --line: #303746;
  --text: #e9ebf1;
  --muted: #a4aabb;
  --gold: #e0b458;
  --blue: #79afe2;
  --shadow: 0 18px 50px rgb(0 0 0 / 22%);
  /* Gold and blue are a valence pair: gold is the good side of whatever a block measures, blue
     the bad side. Here that is the win-rate axis, gold above the 50% spine and blue below. A
     movement chip never takes either, because a row can gain places while its own share falls,
     so its two halves can disagree about whether the row is doing well. */
  --rate-above: var(--gold);
  --rate-below: var(--blue);
  /* Quiet label grey, one step darker than --muted: column heads, ranks, and the figures a
     reader only checks after the shape has answered them. The prototype's #7b8399 measured
     4.38:1 on --panel — under the 4.5:1 floor for small text, which is exactly where this grey
     is used on hovered ladder rows, so it is lifted until it clears on the panel tone as well as
     on the page. */
  --quiet: #838ba1;
  /* The certainty pair, and the only place on the site where hue means something other than
     valence. Pale grey is a slot the field has settled and nobody is choosing; violet is where
     the deckbuilding still happens. Two chips read it: the vitals band chip and the player
     page's call chip, which says the same thing about a person. The archetype page's stock bars
     make the same claim in the same pale grey, but their violet is a shade darker and declared
     literally, so they are not wired to this pair. */
  --sure: #c9d1e4;
  --unsure: #ab8ce0;
  /* One deck tool's box and the gap between two of them. A caller that lays the tools in a row
     over its own content reserves the gutter from these two numbers, so the reservation cannot
     drift from the buttons it is reserving for. */
  --deck-tool-size: 1.7rem;
  --deck-tool-gap: .4rem;
}

* { box-sizing: border-box; }
html { min-width: 20rem; background: var(--bg); }
body { margin: 0; color: var(--text); background: radial-gradient(circle at 50% -10rem, #27251d 0, var(--bg) 30rem); font: 1rem/1.6 system-ui, sans-serif; }
a { color: var(--blue); }
button, input, select { font: inherit; }
.wrap { width: min(100% - 2rem, 70rem); margin-inline: auto; }
.visually-hidden { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
.skip-link { position: fixed; top: .5rem; left: .5rem; z-index: 20; padding: .6rem .8rem; color: #111319; background: var(--gold); border-radius: .4rem; transform: translateY(-150%); }
.skip-link:focus { transform: none; }

/* ---- redesign ticket 16: the top bar (efforts/redesign/issues/16-build-navigation.md) --------
   The wordmark, all seven formats printed flat, and one search field at the right. The bar takes
   `.wrap`'s 70rem, which is the site's one measure, so the bar and the page under it line up.
   Its height comes from the rail's own padding rather than a `min-height`, so the three parts
   cannot disagree about how tall the bar is.
   The bar carries its own stacking context anyway (`backdrop-filter`), so it needs a z-index of
   its own: without one the search panel is trapped at the bar's level and page art, hero credits
   and chart labels paint over it. */
.site-header { position: relative; z-index: 40; display: flex; align-items: stretch; gap: 1.2rem; padding-inline: max(1rem, calc((100% - 70rem) / 2)); border-bottom: 1px solid var(--line); background: rgb(26 30 39 / 92%); backdrop-filter: blur(12px); }
/* `contents` so the wordmark and the field are direct children of the bar at desktop and can be
   ordered around the rail between them. Below 640px it becomes a real row and the two share the
   first line. */
.site-top { display: contents; }
.logo { order: 1; display: flex; align-items: center; color: var(--gold); font-size: 1.12rem; font-weight: 850; letter-spacing: .04em; text-decoration: none; white-space: nowrap; }
.logo span { color: var(--text); }
/* Sits under the wordmark's tail, so it reads as a status tag and not a third syllable. */
.logo-beta { color: var(--muted); font-size: .58em; font-weight: 600; letter-spacing: .02em; margin-left: .2em; transform: translateY(.45em); }
/* The one bar entry that is not a format. It sits at the right end, immediately before the search
   field: both are ways of looking something up, so they read as one cluster, and the rail keeps
   the whole middle to itself. Ruled off on its left so it is not read as the rail's eighth name.
   Below 640px the bar is already two lines and a third name on the first would crowd the field, so
   the link drops out there and the footer row is the phone's way in. */
.site-top-link { order: 4; display: flex; align-items: center; padding: 1.05rem .9rem; color: var(--muted); font-size: .88rem; font-weight: 650; text-decoration: none; white-space: nowrap; border-left: 1px solid var(--line); }
.site-top-link:hover { color: var(--text); }
.site-top-link:focus-visible { outline: 2px solid var(--gold); outline-offset: -3px; }
.site-top-link[aria-current] { position: relative; color: var(--gold); font-weight: 800; }
.site-top-link[aria-current]::after { content: ""; position: absolute; inset: auto .35rem -1px .35rem; height: 2px; background: var(--gold); }
/* The rail never wraps and never becomes a menu button: when the bar runs out of room it scrolls
   sideways, so no format is ever missing, only further along. The scrollbar is hidden, so the
   right edge fades instead: that is the only sign a name continues past it. The fade is on the
   right alone here, because at desktop the rail starts at the bar's own edge and a left fade
   would dim the first format at rest. Until the bar is tight the rail is wider than its seven
   names, so the fade lands on empty space and shows nothing. */
.site-rail { order: 3; display: flex; flex: 1 1 auto; min-width: 0; overflow-x: auto; scrollbar-width: none; -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 1.6rem), transparent 100%); mask-image: linear-gradient(90deg, #000 calc(100% - 1.6rem), transparent 100%); }
.site-rail::-webkit-scrollbar { display: none; }
.site-rail a { position: relative; display: flex; align-items: center; padding: 1.05rem .6rem; color: var(--muted); font-size: .88rem; font-weight: 650; text-decoration: none; white-space: nowrap; }
.site-rail a:hover { color: var(--text); }
.site-rail a:focus-visible { outline: 2px solid var(--gold); outline-offset: -3px; }
/* The current format is gold and its mark sits on the bar's own bottom hairline, so the name and
   the page under it read as one shape. */
.site-rail a[aria-current] { color: var(--gold); font-weight: 800; }
.site-rail a[aria-current]::after { content: ""; position: absolute; inset: auto .35rem -1px .35rem; height: 2px; background: var(--gold); }
/* One fixed size, 24rem: typing room for a deck name, and it does not grow when you click it,
   which would shove the rail beside it. It does give width back when the bar is tight, down to
   13rem, because the rail is the bar's first job and the field is its second. The lopsided
   shrink factor is what orders that: the field absorbs the whole squeeze, and only once it is
   at its minimum does the rail begin to scroll. It buys the seven formats about 180px of width,
   and it is the answer to the eighth format at this measure. */
.site-find { position: relative; order: 5; display: flex; flex: 0 10000 auto; align-self: center; align-items: center; gap: .5rem; width: 24rem; min-width: 13rem; padding: .3rem .5rem .3rem .45rem; background: var(--bg); border: 1px solid var(--line); border-radius: .55rem; }
.site-find:focus-within { border-color: #4c5a75; box-shadow: 0 0 0 2px #79afe233; }
/* A magnifier, not a `/` hint: it needs no explaining, and a shortcut nobody is told about is
   not a feature. */
.site-find-icon { flex: 0 0 auto; width: .95rem; height: .95rem; margin-left: .25rem; color: var(--quiet); fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; }
.site-find:focus-within .site-find-icon { color: var(--text); }
.site-find > .player-search-input { position: static; }
.site-find input { padding: .4rem 0; font-size: .92rem; background: transparent; border: 0; }
.site-find input:focus { outline: none; }
.site-find .player-search-results { top: calc(100% + .4rem); right: 0; left: 0; width: auto; }

input, select { min-width: 0; padding: .7rem .85rem; color: var(--text); background: var(--bg); border: 1px solid var(--line); border-radius: .55rem; }
input:focus, select:focus { outline: 2px solid var(--blue); outline-offset: 2px; }
button { padding: .7rem 1rem; color: #18150d; font-weight: 750; background: var(--gold); border: 0; border-radius: .55rem; cursor: pointer; }
.player-search-input { position: relative; min-width: 0; flex: 1; }
.player-search-input > input { width: 100%; }
.player-search-results { position: absolute; z-index: 10; top: calc(100% + .35rem); width: 100%; }
.player-suggestions { overflow: hidden; background: var(--panel-strong); border: 1px solid var(--line); border-radius: .55rem; box-shadow: var(--shadow); }
.player-suggestions:empty { display: none; }
.player-suggestions a { display: flex; align-items: center; gap: .55rem; padding: .4rem .8rem; color: var(--text); font-size: .88rem; text-decoration: none; }
.player-suggestions a i { margin-left: auto; color: var(--quiet); font-style: normal; font-size: .76rem; font-variant-numeric: tabular-nums; white-space: nowrap; }
.player-suggestions a:hover, .player-suggestions a:focus { color: #18150d; background: var(--gold); outline: none; }
.player-suggestions a:hover i, .player-suggestions a:focus i { color: #3a3018; }

/* ---- redesign ticket 22: the grouped header panel (efforts/redesign/issues/22-search-panel.md)
   Four kinds, each headed, in a fixed order. The heading and the two message states share one
   quiet label style, and the panel caps its own height so a phone never loses the whole page
   under it: the rows scroll inside the panel instead. */
.search-suggestions-heading { margin: 0; padding: .6rem .85rem .15rem; color: var(--quiet); font-size: .72rem; font-weight: 750; letter-spacing: .1em; text-transform: uppercase; }
.search-suggestions-note { margin: 0; padding: .7rem .85rem; color: var(--muted); }
/* The way out of the panel, ruled off from the results above it: it is not one of them, it is
   the search the reader may have meant instead. */
.search-suggestions-find { color: var(--muted); font-size: .82rem; border-top: 1px solid var(--line); }
.player-search-results .player-suggestions { max-height: calc(100vh - 6rem); overflow-y: auto; }

main { min-height: calc(100vh - 22rem); }
.prose h1 { max-width: 14ch; margin: 0; font-size: clamp(2.5rem, 8vw, 5.2rem); line-height: .98; letter-spacing: -.045em; }
.eyebrow { margin: 0 0 .75rem; color: var(--gold); font-size: .76rem; font-weight: 800; letter-spacing: .14em; text-transform: uppercase; }
.section { padding-block: 1rem 5rem; }
.section h2 { margin: 0; font-size: clamp(1.8rem, 5vw, 2.6rem); }
.section-toolbar { display: flex; flex-wrap: wrap; align-items: end; justify-content: space-between; gap: 1rem 2rem; }
.empty-panel { margin-top: 1.25rem; padding: 2rem; color: var(--muted); background: linear-gradient(130deg, rgb(224 180 88 / 6%), transparent), var(--panel); border: 1px solid var(--line); border-radius: .8rem; box-shadow: var(--shadow); }
.empty-panel p { margin: 0; }
.color-identity { display: flex; min-height: 1.75rem; align-items: center; gap: .35rem; }
.color-pip { display: inline-grid; width: 1.65rem; height: 1.65rem; place-items: center; }
.mana-symbol { display: block; width: 100%; height: 100%; }
.color-unavailable, .art-credit { color: var(--muted); font-size: .75rem; }
.art-credit { margin: .8rem 0 0; }

.deck-stack, .intel-stack { display: grid; gap: 1.25rem; align-content: start; min-width: 0; }
.deck-stack .empty-panel, .intel-stack .empty-panel { margin-top: 0; }
.intel-card .empty-panel { margin-top: .6rem; padding: 1rem; box-shadow: none; }
.deck-stack .promo-728 { width: min(728px, 100%); margin: 0 auto; }
.deck-card, .intel-card { padding: 1rem 1.1rem; background: var(--panel); border: 1px solid var(--line); border-radius: .8rem; box-shadow: var(--shadow); }
.card-empty { margin: 0; color: var(--muted); font-size: .9rem; }
.latest-deck .deck-heading h2 { margin: 0; color: var(--text); font-size: 1.25rem; font-weight: 700; letter-spacing: normal; text-transform: none; }
.likely-playing { border-left: 3px solid var(--gold); }
.tendency-top { margin: 0; font-size: 1.2rem; font-weight: 800; line-height: 1.3; }
.tendency-top .tendency-evidence { display: block; font-weight: 400; }
.tendency-basis { margin: .35rem 0 0; color: var(--muted); font-size: .85rem; }
.tendency-list { margin: .6rem 0 0; padding-left: 1.2rem; color: var(--muted); font-size: .9rem; }
.tendency-evidence { color: var(--muted); font-size: .82rem; }
.deck-list, .achievement-list { margin: 0; padding: 0; list-style: none; }
.briefing-deck { padding: .6rem .1rem; border-bottom: 1px solid var(--line); }
.briefing-deck:last-child { padding-bottom: 0; border-bottom: 0; }
.briefing-deck:target { border-radius: .4rem; outline: 2px solid var(--gold); outline-offset: 2px; }
.deck-heading { display: flex; flex-wrap: wrap; align-items: baseline; gap: .6rem; }
.deck-heading h3 { margin: 0; font-size: 1.05rem; }
.method-note, .deck-context, .achievement-date, .prelim-note { color: var(--muted); font-size: .82rem; }
.reported-note { border: 1px solid currentColor; border-radius: .25rem; padding: .08rem .3rem; font-size: .72rem; line-height: 1.2; }
.deck-context { margin: .25rem 0 0; }
.decklist { margin-top: .5rem; }
.decklist summary { color: var(--blue); cursor: pointer; }
/* The deck view is a collage: the maindeck takes one full-measure column and the rail beside it
   stacks the sideboard over the card, so the two boards start on the same line and read as one
   75-card list. The rail's width is --deck-rail rather than a figure inside the track list, so a
   caller that wants a different split says one number instead of restating the whole grid. */
.deck-body { --deck-rail: 15.2rem; position: relative; display: grid; grid-template-columns: minmax(0, 1fr) minmax(9rem, var(--deck-rail)); gap: 0 1.6rem; padding: .4rem .35rem 1rem 3.5rem; }
.deck-tools { position: absolute; top: .55rem; left: .35rem; display: flex; flex-direction: column; gap: var(--deck-tool-gap); }
.deck-tool { position: relative; display: grid; place-items: center; width: var(--deck-tool-size); height: var(--deck-tool-size); padding: 0; color: var(--muted); background: var(--panel-strong); border: 1px solid var(--line); border-radius: .35rem; cursor: pointer; }
.deck-tool:hover, .deck-tool:focus-visible { color: var(--blue); border-color: var(--blue); }
.copy-tool.copied { color: var(--gold); border-color: var(--gold); }
.copy-tool.copied::after { content: "Copied"; position: absolute; top: 50%; left: calc(100% + .45rem); padding: .1rem .45rem; color: #18150d; font-size: .72rem; font-weight: 700; white-space: nowrap; background: var(--gold); border-radius: .35rem; transform: translateY(-50%); }
/* A copy that reached neither clipboard path says so on the button, in the valence pair's bad
   side, instead of flashing "Copied" over stale clipboard content. */
.copy-tool.copy-failed { color: var(--blue); border-color: var(--blue); }
.copy-tool.copy-failed::after { content: "Copy failed"; position: absolute; top: 50%; left: calc(100% + .45rem); padding: .1rem .45rem; color: #18150d; font-size: .72rem; font-weight: 700; white-space: nowrap; background: var(--blue); border-radius: .35rem; transform: translateY(-50%); }
.deck-cols { grid-column: 1; columns: 2 11rem; column-gap: 1.6rem; }
.deck-aside { grid-column: 2; min-width: 0; }
/* Nothing in the rail follows the scroll: ticket 07 dropped the sticky card because in a viewer
   about one screen tall it only bought a scrollbar inside a scrollbar. That premise is the box
   the caller gives the component. A caller narrow enough to run the maindeck in one column makes
   the list much taller than the rail, and there the card scrolls away from a low row.
   The card is capped by --deck-rail, not by a second copy of the number, so a caller that re-cuts
   the rail gets a card that follows it. Without scripting this is the only card on the page. */
.deck-preview { margin-top: 1.1rem; }
.deck-preview img, .deck-preview-empty { display: block; width: min(var(--deck-rail), 100%); margin-inline: auto; aspect-ratio: 5 / 7; height: auto; background: var(--panel-strong); border-radius: 4.75% / 3.4%; box-shadow: 0 14px 40px rgb(0 0 0 / 45%); }
.deck-preview-empty { box-shadow: none; }
.deck-preview-caption { display: grid; width: min(var(--deck-rail), 100%); height: 11.5rem; align-content: center; margin: .6rem auto 0; overflow: hidden; padding: .6rem .65rem; color: var(--muted); font-size: .76rem; line-height: 1.4; background: var(--panel); border: 1px solid var(--line); border-radius: .5rem; }
/* Ticket 53: one copy-ladder family. The deck viewer's caption rail and the inclusion boards'
   floating card preview draw the same rungs from the same data, so these rules are unscoped and
   both callers read them. A rung's length is a <progress> value, not a declaration, so no
   per-request number reaches the browser as CSS here. The two fills are the boards' own
   encoding: grey for a settled copy, violet for one still argued over. */
.deck-preview-ladder { display: grid; gap: .18rem; }
.deck-preview-rung { display: grid; grid-template-columns: 1.8rem minmax(0, 1fr) 2.6rem; gap: .35rem; align-items: center; }
.deck-preview-rung-label, .deck-preview-rung-percent { color: var(--quiet); font-size: .68rem; font-variant-numeric: tabular-nums; }
.deck-preview-rung-percent { color: var(--text); text-align: right; }
.deck-preview-rung-track { display: block; width: 100%; height: .55rem; appearance: none; border: 0; background: rgb(255 255 255 / 8%); border-radius: .1rem; }
.deck-preview-rung-track::-webkit-progress-bar { background: rgb(255 255 255 / 8%); border-radius: .1rem; }
.deck-preview-rung-track::-webkit-progress-value { background: #c9d1e4; border-radius: .1rem; }
.deck-preview-rung-track::-moz-progress-bar { background: #c9d1e4; border-radius: .1rem; }
.deck-preview-rung-track.is-argued::-webkit-progress-value { background: #9a78dd; }
.deck-preview-rung-track.is-argued::-moz-progress-bar { background: #9a78dd; }
.deck-preview-summary, .deck-preview-list { margin: 0; }
.deck-preview-list { color: var(--quiet); }
.deck-sec { break-inside: avoid; margin: 0 0 .8rem; }
.deck-sec.spill { break-inside: auto; }
.deck-sec.spill h5 { break-after: avoid; }
.deck-body h4, .deck-body h5 { margin: 0 0 .3rem; font-size: .85rem; }
.deck-body h4.board-head { margin: 0 0 .55rem; padding-bottom: .25rem; border-bottom: 1px solid var(--line); break-after: avoid; }
.deck-body h5 { color: var(--muted); font-weight: 700; }
.deck-body ul { margin: 0; padding: 0; list-style: none; font-size: .88rem; }
.deck-body li { display: grid; grid-template-columns: 1.4rem minmax(0, 1fr) auto; gap: .35rem; align-items: baseline; padding-block: .06rem; }
.deck-body .quantity { color: var(--muted); font-variant-numeric: tabular-nums; }
.card-name { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; cursor: default; user-select: text; }
.card-name:hover, .card-name:focus-visible { text-decoration: underline dotted; outline: none; }
.mana-cost { display: inline-flex; justify-self: end; gap: .1rem; white-space: nowrap; }
.mana-cost-symbol { width: 1rem; height: 1rem; }
.achievement { display: flex; align-items: baseline; gap: .6rem; padding: .45rem 0; font-size: .88rem; }
.finish-pill { padding: .15rem .55rem; font-size: .82rem; font-weight: 750; white-space: nowrap; background: var(--panel-strong); border: 1px solid var(--line); border-radius: 99rem; }
.finish-pill.win { color: #18150d; background: var(--gold); border-color: var(--gold); }
.achievement-date { display: block; }
.prelim-note { margin: .8rem 0 0; }
.h2h-intro { margin: 0; color: var(--muted); }
.h2h-form { display: flex; flex-wrap: wrap; gap: .6rem; margin-top: 1rem; }
.h2h-form input { flex: 1; max-width: 18rem; min-width: 10rem; }
.h2h-forget { color: var(--text); background: var(--panel-strong); border: 1px solid var(--line); }
.h2h-note { margin: .6rem 0 0; color: var(--muted); font-size: .82rem; }
.h2h-record { margin: 0; }
.h2h-format-record.ahead { color: var(--gold); }
.h2h-none, .h2h-overall { color: var(--muted); }
.h2h-list { margin: .4rem 0 0; padding: 0; list-style: none; }
.h2h-match { display: flex; align-items: baseline; gap: .6rem; padding: .45rem 0; font-size: .88rem; }
.tournament-page h1 { max-width: 30ch; margin: 0; font-size: clamp(2.2rem, 6vw, 4.5rem); line-height: 1; letter-spacing: -.04em; }
.tournament-facts { margin: .75rem 0 0; color: var(--muted); }
.tournament-deck-layout { margin-top: .4rem; }
/* Scripting turns the native disclosures into one list beside one reserved pane. The standings
   are taller than the pane, so the pane adds no page height. */
.js-deck-pane .tournament-deck-layout.has-pane { display: grid; grid-template-columns: minmax(0, .95fr) minmax(0, 1.05fr); gap: 1.4rem 2.2rem; align-items: start; }
.deck-list-row { display: grid; align-items: baseline; min-width: 0; color: var(--text); text-decoration: none; }
.deck-list-row.odd, .tournament-row-shell.stripe-odd > .deck-list-row { background: rgb(127 145 180 / 8%); }
.deck-list-row:hover { background: var(--panel); }
.deck-list-row:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
.deck-list-row.is-picked { background: var(--panel-strong); box-shadow: inset 3px 0 var(--gold); }
.deck-list-row .color-identity, .deck-pane-head .color-identity { min-height: 0; gap: .18rem; }
.deck-list-row .color-pip, .deck-pane-head .color-pip { width: .95rem; height: .95rem; }
.deck-list-pane { display: none; min-width: 0; }
.js-deck-pane .deck-list-pane { display: block; }
.deck-list-source:target { border-radius: .4rem; outline: 2px solid var(--gold); outline-offset: 2px; }
/* The tournament's target ring belongs to the shell, which wraps the row and its source
   together; drawing the family's ring here as well nests two gold outlines. */
.tournament-row-shell > .deck-list-source:target { border-radius: 0; outline: none; }
.js-deck-pane .deck-list-source { display: none; }
.deck-list-content { min-width: 0; }
.deck-pane-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: .3rem .8rem; padding-bottom: .45rem; border-bottom: 1px solid var(--line); }
.deck-pane-head > b { font-size: 1.05rem; letter-spacing: -.02em; }
.deck-pane-head > span { color: var(--quiet); font-size: .84rem; }
.tournament-list-column { min-width: 0; }
.tournament-row-shell { border-bottom: 1px solid var(--line); }
.tournament-row-shell:has(> .tournament-row-details:target) { border-radius: .4rem; outline: 2px solid var(--gold); outline-offset: 2px; }
.tournament-row-shell > .deck-list-row { grid-template-columns: 6.6rem minmax(0, 1fr) 1.1rem; gap: .2rem .7rem; width: 100%; padding: .42rem .45rem; }
.tournament-row-main { display: flex; flex-wrap: wrap; align-items: baseline; gap: .2rem .6rem; min-width: 0; }
.tournament-row-place { font-variant-numeric: tabular-nums; white-space: nowrap; }
.tournament-row-place small { color: var(--muted); }
.tournament-row-player { min-width: 0; }
.tournament-row-shell > .deck-list-row .tournament-row-player { overflow: hidden; color: var(--muted); font-size: .88rem; text-overflow: ellipsis; white-space: nowrap; }
.tournament-row-player a { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tournament-row-archetype { min-width: 0; overflow: hidden; }
.tournament-row-details { border: 0; }
.tournament-row-details > summary { padding: .45rem; color: var(--blue); cursor: pointer; list-style: none; }
.tournament-row-details > summary::-webkit-details-marker, .tournament-tail > summary::-webkit-details-marker { display: none; }
.tournament-row-details[open] > .deck-list-content { padding-top: .35rem; }
/* Scoped on the content's own class, not on the disclosure: `deck-pane.js` moves this node into
   the reserved pane, so a selector rooted at the `<details>` stops matching the moment a reader
   picks a list, which is the state the page ships in. */
.tournament-deck-content { padding-bottom: .3rem; }
.tournament-deck-content > .deck-pane-head > b { font-size: 1.1rem; }
.tournament-row-affordance { color: var(--quiet); font-size: .7rem; text-align: right; white-space: nowrap; }
.tournament-row-shell > .deck-list-row.is-picked .tournament-row-affordance { color: var(--gold); }
.tournament-row-deckless { color: var(--muted); }
.archetype-label { display: inline-flex; flex-wrap: wrap; align-items: center; gap: .35rem; min-width: 0; }
.archetype-name { overflow: hidden; text-overflow: ellipsis; }
/* A row with no published list is not a picker, so it keeps three columns of its own: the same
   proportions it had before the pane, on the picker's place track so interleaved rows line up.
   The reserved gutter on its right went with the toggle that used to sit in it. */
.tournament-row-summary { display: grid; grid-template-columns: 6.6rem minmax(11rem, 1.4fr) minmax(8rem, 1fr); gap: .2rem .6rem; align-items: baseline; min-width: 0; padding: .42rem .45rem; cursor: default; }
/* The gutter is always reserved and thin. It comes out of the maindeck measure, so changing to a
   list that needs a scrollbar does not move or re-truncate the card names. */
.tournament-deck-layout .deck-list-pane { min-width: 0; }
.js-deck-pane .tournament-deck-layout .deck-list-pane { position: sticky; top: 1rem; max-height: calc(100dvh - 2rem); overflow-y: auto; overscroll-behavior: contain; scrollbar-gutter: stable; scrollbar-width: thin; }
.js-deck-pane .tournament-row-details { display: none; }
.tournament-deck-layout .deck-list-pane .deck-body { gap: 0 1rem; padding: .4rem 0 1rem 2.2rem; }
.tournament-deck-layout .deck-list-pane .deck-cols { columns: 1; }
.field-seg.is-picked { outline: 2px solid var(--gold); outline-offset: -3px; }
.bracket-player.is-picked { outline: 1px solid var(--gold); outline-offset: 1px; }
.tournament-tail > summary { padding: .6rem .35rem; color: var(--blue); cursor: pointer; list-style: none; }
.tournament-disclosure-panel { margin-top: 1.25rem; }
.tournament-page > .promo-728 { margin-top: 1.5rem; }
.playoff-section { margin-top: 2rem; }
.bracket-visual { position: relative; display: grid; grid-template-columns: 30fr 5fr 30fr 5fr 30fr; grid-template-rows: repeat(4, minmax(3.4rem, 1fr)); gap: 0; min-width: 54rem; margin-top: .4rem; overflow-x: auto; }
.bracket-round { display: contents; }
.bracket-round h3 { display: none; margin: 0; color: var(--muted); font-size: .72rem; font-weight: 800; letter-spacing: .1em; text-transform: uppercase; }
.bracket-round-quarterfinals .bracket-match-qf-0 { grid-column: 1; grid-row: 1; }
.bracket-round-quarterfinals .bracket-match-qf-1 { grid-column: 1; grid-row: 2; }
.bracket-round-quarterfinals .bracket-match-qf-2 { grid-column: 1; grid-row: 3; }
.bracket-round-quarterfinals .bracket-match-qf-3 { grid-column: 1; grid-row: 4; }
.bracket-round-semifinals .bracket-match-sf-0 { grid-column: 3; grid-row: 1 / span 2; align-self: center; }
.bracket-round-semifinals .bracket-match-sf-1 { grid-column: 3; grid-row: 3 / span 2; align-self: center; }
.bracket-round-final .bracket-match-final, .bracket-round-final .bracket-champion-only { grid-column: 5; grid-row: 1 / -1; align-self: center; }
.bracket-match, .bracket-champion-only { position: relative; z-index: 1; min-width: 0; align-self: center; }
.bracket-match { margin-block: .3rem; overflow: hidden; background: var(--panel); border: 1px solid var(--line); border-radius: .55rem; box-shadow: var(--shadow); }
.bracket-match-empty { background: transparent; border-style: dashed; }
.bracket-slot { min-width: 0; }
.bracket-slot-right { border-top: 1px solid var(--line); }
.bracket-match-empty .bracket-slot-right { border-top-style: dashed; }
.bracket-player { display: flex; gap: .45rem; align-items: baseline; min-width: 0; padding: .4rem .6rem; color: var(--text); text-decoration: none; }
.bracket-player:hover { color: var(--blue); }
.bracket-player-winner { box-shadow: inset 3px 0 var(--gold); }
.bracket-match-final .bracket-player-winner { background: linear-gradient(90deg, rgb(224 180 88 / 14%), transparent); }
.bracket-player-winner .bracket-score { color: var(--gold); }
.bracket-player:not(.bracket-player-winner, .bracket-player-champion) .bracket-player-name { color: var(--muted); font-weight: 500; }
.bracket-player-champion { background: color-mix(in srgb, var(--gold) 10%, var(--panel-strong)); box-shadow: inset 3px 0 var(--gold); }
.bracket-player-name { overflow: hidden; font-weight: 750; text-overflow: ellipsis; white-space: nowrap; }
.bracket-player .archetype-label { flex: 1; flex-wrap: nowrap; min-width: 0; overflow: hidden; color: var(--muted); font-size: .76rem; white-space: nowrap; }
.bracket-player .archetype-name { overflow: hidden; text-overflow: ellipsis; }
.bracket-player .color-identity { min-height: 0; gap: .2rem; }
.bracket-player .color-pip { width: .95rem; height: .95rem; }
.bracket-art-chip { order: -1; flex: none; width: 1.25rem; height: 1.25rem; align-self: center; object-fit: cover; border: 1px solid var(--line); border-radius: .3rem; }
.bracket-art-missing { display: grid; place-items: center; color: var(--muted); font-size: .8rem; font-weight: 700; border-style: dashed; }
.bracket-score { margin-left: auto; color: var(--muted); font-weight: 750; font-variant-numeric: tabular-nums; white-space: nowrap; }
.bracket-empty { display: block; padding: .4rem .6rem; color: var(--muted); font-size: .78rem; font-style: italic; }
.bracket-match > .bracket-note { display: block; padding: .35rem .6rem; color: var(--muted); font-size: .68rem; text-transform: uppercase; border-top: 1px solid var(--line); }
.bracket-connectors { position: absolute; z-index: 0; inset: 0; width: 100%; height: 100%; pointer-events: none; fill: none; stroke: var(--line); stroke-width: 1.5; }
.bracket-connector-dashed { stroke-dasharray: 2 2; stroke: var(--muted); }
.bracket-champion-only { display: grid; gap: .55rem; align-content: center; width: 100%; }
.bracket-champion-only .bracket-player { padding: .65rem; background: var(--panel-strong); border: 1px solid var(--gold); border-radius: .4rem; }
.bracket-champion-only .bracket-note { position: static; margin: 0; color: var(--muted); font-size: .68rem; }
.bracket-ranked-list { display: grid; gap: .35rem; margin: .85rem 0 0; padding-left: 1.5rem; }
.bracket-ranked-list li { display: grid; grid-template-columns: 3rem minmax(0, 1fr) auto; gap: .6rem; align-items: baseline; }
.bracket-ranked-place, .bracket-ranked-record { color: var(--muted); font-variant-numeric: tabular-nums; }
.bracket-narrative-round h4 { margin: 0 0 .45rem; color: var(--muted); font-size: .72rem; letter-spacing: .08em; text-transform: uppercase; }
.bracket-narrative-round ol { display: grid; gap: .45rem; margin: 0; padding-left: 1.2rem; }
.bracket-narrative-round li { color: var(--text); font-size: .84rem; }
.bracket-narrative-outcome { margin: 0 .25rem; color: var(--muted); font-size: .72rem; }
.bracket-narrative-score { margin-left: .25rem; color: var(--muted); font-size: .72rem; font-variant-numeric: tabular-nums; }
.bracket-narrative-round small { display: block; margin-top: .2rem; color: var(--muted); font-size: .72rem; }
/* The tree has a 54rem floor, so it drags sideways inside its own box rather than pushing the
   page wide. */
.bracket-scroll { min-width: 0; max-width: 100%; overflow-x: auto; overscroll-behavior-inline: contain; }

/* ---- redesign ticket 10: the field of one event (efforts/redesign/issues/10-build-tournament.md)
   One bar, one segment per published list, blocks ordered by size. Share is the only quantity a
   single event can measure, so share is the only quantity the picture draws. A block's length is
   its list count, which is a function of the request, so it arrives as `--block-lists` in the
   response's nonced <style>, scoped to the bar's own id. */
.field-section { margin-top: 2rem; }
.field-scroll { min-width: 0; max-width: 100%; overflow-x: auto; overscroll-behavior-inline: contain; }
/* `flex-basis: 0` makes the grow factor the exact share. The per-segment floor is what keeps a
   one-list block clickable on a 60-list event: past that the bar drags sideways in its own box. */
.field-bar { display: flex; height: 7rem; margin: .2rem 0 0; padding: 0; list-style: none; }
.field-block { position: relative; flex: var(--block-lists, 1) 1 0; display: flex; min-width: calc(var(--block-lists, 1) * .55rem); overflow: hidden; background: var(--panel-strong); }
.field-block + .field-block { border-left: 2px solid var(--bg); }
.field-block:first-child { border-top-left-radius: .5rem; border-bottom-left-radius: .5rem; }
.field-block:last-child { border-top-right-radius: .5rem; border-bottom-right-radius: .5rem; }
/* Blocks are ordered by size, so one wider gap is enough to say where the one-list run starts.
   Without it a two-list block and a one-list block are both anonymous slivers. The gap replaces
   the hairline rather than sitting beside it. */
.field-block.is-edge { margin-left: 1.1rem; border-left: 0; border-top-left-radius: .5rem; border-bottom-left-radius: .5rem; }
/* Art runs out long before archetypes do (10 of 18 on one 2025 event). The block keeps its width
   on a hatched ground, because that is the page showing the hole rather than hiding it. */
.field-block.is-blank { background: repeating-linear-gradient(135deg, #22283400 0 5px, #1b202b 5px 10px), var(--panel-strong); }
.field-art { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.field-scrim { position: absolute; inset: auto 0 0 0; height: 60%; background: linear-gradient(to top, #05060af2 0%, #05060ab8 50%, #05060a00 100%); pointer-events: none; }
.field-seg { position: relative; flex: 1 1 0; min-width: 0; }
.field-seg + .field-seg { border-left: 1px solid rgb(5 6 10 / 45%); }
.field-seg:hover { background: rgb(255 255 255 / 14%); }
.field-seg:focus-visible { outline: 2px solid var(--gold); outline-offset: -3px; }
.field-seg.is-champion { box-shadow: inset 0 -3px var(--gold); }
.field-label { position: absolute; inset: auto 0 0 0; padding: .5rem .55rem; pointer-events: none; }
.field-label b { display: block; overflow: hidden; color: #fff; font-size: .8rem; font-weight: 750; text-overflow: ellipsis; white-space: nowrap; }
.field-label span { display: block; margin-top: .05rem; color: #c9d0e0; font-size: .72rem; font-variant-numeric: tabular-nums; }
/* Under a tenth of the field there is no width to print a name in. The tooltip and the row below
   still carry it, so nothing is lost by dropping the label here. */
.field-block.is-narrow .field-label { display: none; }
/* Both keys under a picture read the same way: short items on one wrapped line, quiet. */
.field-legend, .mark-key { display: flex; flex-wrap: wrap; gap: .3rem 1.3rem; color: var(--quiet); font-size: .78rem; }
.field-legend { margin: .75rem 0 0; }
.field-legend em { font-style: normal; }
.field-key-champion { display: inline-block; width: .7rem; height: .7rem; margin-right: .35rem; background: var(--gold); border-radius: .15rem; vertical-align: -1px; }

/* The event as one list of record: every player, in order, with the published list under the row
   that names it. */
.event-section { margin-top: 2rem; }
/* The two label caveats, printed only where the list actually used one. */
.mark-key { margin: .7rem 0 0; }
.mark-key b { color: var(--muted); font-weight: 800; }
.label-mark { margin-left: .1rem; color: var(--gold); font-size: .78em; cursor: help; }
.tournament-archetype-missing { color: var(--quiet); }
.metagame-table-scroll { min-width: 0; max-width: 100%; overflow-x: auto; overflow-y: hidden; overscroll-behavior-inline: contain; }
.prose { max-width: 62ch; padding-block: clamp(3rem, 8vw, 6rem); }
.prose.secondary-page h1, .section.secondary-page h1 { max-width: 30ch; margin: 0 0 2.5rem; font-size: clamp(1.9rem, 4vw, 2.9rem); line-height: 1; letter-spacing: -.035em; }
.prose .section-head { margin-top: 2.25rem; }
.prose p { color: var(--muted); }
.prose code { color: var(--text); }
.release { padding: .5rem 0 1.5rem; border-top: 1px solid var(--line); }

.not-found-page { max-width: 48rem; padding-top: clamp(3rem, 8vw, 6rem); }
.not-found-links { display: flex; flex-wrap: wrap; gap: .45rem 1rem; margin-top: 1rem; }
.not-found-action { margin: 1rem 0 0; }
.empty-panel .not-found-action { margin-top: 1rem; }

.promo-728 { width: min(728px, calc(100% - 2rem)); min-height: 90px; margin: 1rem auto 2rem; overflow: hidden; background: var(--panel); border: 1px solid var(--line); border-radius: .65rem; }
.promo-728 a, .promo-728 img { display: block; width: 100%; }
.promo-728 img { height: auto; aspect-ratio: 728 / 90; object-fit: cover; }

.site-footer { padding: 2.5rem max(1rem, calc((100% - 70rem) / 2)); color: var(--muted); border-top: 1px solid var(--line); background: var(--panel); }
.site-footer nav { display: flex; flex-wrap: wrap; gap: 1rem 1.5rem; }
.site-footer p { max-width: 65rem; margin: 1.5rem 0 0; font-size: .78rem; }

@media screen and (max-width: 62rem) {
  /* The pane becomes the next block after the list. It no longer follows the viewport or owns a
     scrollbar, so the phone has one ordinary page scroll. */
  .js-deck-pane .tournament-deck-layout.has-pane { grid-template-columns: minmax(0, 1fr); }
  .js-deck-pane .tournament-deck-layout .deck-list-pane { position: static; max-height: none; overflow: visible; scrollbar-gutter: auto; }
}

@media screen and (max-width: 900px) {
  .format-rail { position: static; display: flex; flex-wrap: wrap; }
  .bracket-player .archetype-label { display: none; }
  .bracket-player .bracket-art-chip { width: 1.5rem; height: 1.5rem; }
}

@media screen and (max-width: 640px) {
  .bracket-visual { display: flex; flex-direction: column; min-width: 0; gap: 1.4rem; overflow-x: visible; }
  .bracket-round { display: grid; grid-template-columns: minmax(0, 1fr); grid-row: auto; grid-column: auto; gap: .7rem; padding: 0; }
  .bracket-round h3 { display: block; }
  .bracket-round .bracket-match, .bracket-round .bracket-champion-only { grid-column: auto; grid-row: auto; align-self: stretch; }
  .bracket-match { margin-block: 0; }
  .bracket-connectors { display: none; }
  /* Two lines, and not a hamburger: the wordmark and the field share the first, the rail scrolls
     sideways under it. The rail fades at both edges rather than pretending it ends there. */
  .site-header { flex-direction: column; gap: 0; padding-block: .7rem 0; }
  .site-top { display: flex; align-items: center; gap: .8rem; }
  .site-top-link { display: none; }
  .logo { font-size: .98rem; }
  .site-find { flex: 1 1 auto; width: auto; min-width: 0; margin-left: auto; }
  .site-rail { margin-top: .55rem; margin-inline: -1rem; padding-inline: 1rem; -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 1rem, #000 calc(100% - 1.6rem), transparent 100%); mask-image: linear-gradient(90deg, transparent 0, #000 1rem, #000 calc(100% - 1.6rem), transparent 100%); }
  .site-rail a { padding-block: .7rem; }
  /* The field shares its line with the wordmark, so it is narrower than the panel needs to be.
     The panel hangs from the field's right edge and takes the phone's whole width. */
  .site-find .player-search-results { right: 0; left: auto; width: calc(100vw - 2rem); }
  .promo-728 { min-height: 0; }
  .deck-body { display: block; padding-left: .35rem; }
  .deck-tools { position: static; flex-direction: row; margin: 0 0 .55rem; }
  /* The tools sit side by side here, so the "Copied" flash drops under the button it belongs
     to. To the right it would cover the next tool. */
  .copy-tool.copied::after, .copy-tool.copy-failed::after { top: calc(100% + .3rem); left: 50%; transform: translateX(-50%); }
  .deck-cols { columns: 1; }
  /* The collage stacks at this width: the rail drops under the maindeck and keeps the sideboard,
     while the card goes with the rule below, because there is no pointer to hover here. */
  .deck-aside { margin-top: 1.1rem; }
  .deck-preview { display: none !important; }
  .tournament-row-shell > .deck-list-row { grid-template-columns: 5.4rem minmax(0, 1fr) 1.1rem; }
  .tournament-deck-layout .deck-list-pane .deck-body { display: block; padding-left: .35rem; }
  .tournament-row-summary { grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "place archetype" "player player"; align-items: baseline; }
  .tournament-row-summary > .tournament-row-place { grid-area: place; }
  .tournament-row-summary > .tournament-row-archetype { grid-area: archetype; justify-self: end; }
  .tournament-row-summary > .tournament-row-player { grid-area: player; }
  .tournament-row-affordance { display: inline-block; }
  /* A shorter bar on the phone. The blocks keep their per-segment floor, so a wide field drags
     sideways inside `.field-scroll` and the page itself never does. */
  .field-bar { height: 5.5rem; }
}

@media (prefers-reduced-motion: reduce) {
  * { scroll-behavior: auto !important; }
  .mosaic-art, .card-preview { transition: none; }
}

/* ---- redesign ticket 03: the shared page language (efforts/redesign/issues/03-metagame-ladder.md)
   The vitals bar, the section heading with its lowercase note, the method footnote and the
   ladder are used by every redesigned route. Their markup lives in `templates/ladder.html` and
   their view types in `crates/web/src/ladder.rs`; the numbers each row is drawn from arrive as
   custom properties in the response's nonced <style> element, so nothing here is per-request. */
.page-vitals { display: flex; flex-wrap: wrap; margin-top: 1.5rem; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); }
.page-vital { flex: 1 1 8rem; padding: .85rem 1.2rem .85rem 0; }
.page-vital + .page-vital { padding-left: 1.2rem; border-left: 1px solid var(--line); }
.page-vital b { display: block; font-size: clamp(1.35rem, 3vw, 1.9rem); font-weight: 800; font-variant-numeric: tabular-nums; letter-spacing: -.03em; line-height: 1.1; }
/* The unit, small beside the number. The value is the number alone: a unit set at the number's
   size takes the weight the number is there to carry. */
.page-vital b small { color: var(--quiet); font-size: .55em; font-weight: 750; letter-spacing: -.01em; }
/* The band chip: one word naming the number beside it. It takes the certainty pair rather than
   adding an encoding, and it never takes gold or blue because a band is a name and not a grade.
   Dark text on both, because the violet is too light to carry white. The gap is the word space
   in the markup, so it scales with the figure. */
.page-vital-band { display: inline-block; padding: .16rem .42rem; color: #10131b; font-size: .6rem; font-style: normal; font-weight: 800; letter-spacing: .1em; text-transform: uppercase; vertical-align: .32em; border-radius: .25rem; }
.page-vital-band.is-settled { background: var(--sure); }
.page-vital-band.is-argued { background: var(--unsure); }
.page-vital span { display: block; margin-top: .15rem; color: var(--muted); font-size: .7rem; font-weight: 700; letter-spacing: .12em; text-transform: uppercase; }
/* One short line saying what the figure is, for the vitals that cannot be read without it. */
.page-vital i { display: block; margin-top: .25rem; color: var(--quiet); font-size: .74rem; font-style: normal; }
/* The movement line, one step brighter than the note above it: a level and a change are two
   different questions, and the change is the one a reader scans for. Typed with the element
   because the note rule above also names a type and would otherwise win the colour. Tabular
   figures because the same line is read down a row of cells. */
.page-vital i.page-vital-trend { color: var(--muted); font-variant-numeric: tabular-nums; }
/* Typed as `h2.section-head` because `.section h2` sets a display size for a page's own
   headings, and these label a band rather than open one. */
h2.section-head { margin: 2.75rem 0 .9rem; color: var(--muted); font-size: .72rem; font-weight: 800; letter-spacing: .16em; text-transform: uppercase; }
.section-head-note { margin-left: .7rem; color: var(--quiet); font-weight: 600; letter-spacing: 0; text-transform: none; }
.method-footnote { margin-top: 2.5rem; padding-top: 1rem; border-top: 1px solid var(--line); }
.method-footnote > summary { color: var(--muted); font-size: .8rem; letter-spacing: .1em; text-transform: uppercase; }
.method-footnote .coverage-sentence { max-width: 62ch; margin: .9rem 0 0; color: var(--muted); font-size: .86rem; }

/* ---- /metagame/{format} landing page ---- */
.metagame-page h1 { max-width: 30ch; margin: 0; font-size: clamp(1.9rem, 4vw, 2.9rem); line-height: 1; letter-spacing: -.035em; }
/* The two picker forms are one form reading as one sentence: format, over the last, window. */
.picker-strip { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; margin-left: auto; color: var(--muted); font-size: .9rem; }
.picker-strip select { padding: .45rem .6rem; font-weight: 650; background: var(--panel-strong); }
.picker-strip button { padding: .5rem .9rem; font-size: .85rem; }
.metagame-field { margin-top: .5rem; }
.metagame-page > .empty-panel { margin-top: 1.75rem; }
.metagame-row-art { display: inline-grid; width: 1.6rem; height: 1.6rem; place-items: center; margin-right: .45rem; object-fit: cover; vertical-align: middle; border: 1px solid var(--line); border-radius: .3rem; }
.metagame-row-art-fallback { color: var(--muted); font-size: .8rem; font-weight: 700; border-style: dashed; }

/* ---- redesign ticket 04: the treemap hero (efforts/redesign/issues/04-metagame-treemap.md)
   Share is the page's primary quantity, so it is drawn as area: a block's area is its share of
   the published decklists. The packing runs server-side in `crates/web/src/mosaic.rs` against a
   fixed reference box, and every rectangle arrives here as a percentage of that box in the
   response's nonced <style> element, so nothing on this page measures anything.

   `.metagame-field` is the query container, not the mosaic itself: an element's own container
   units resolve against its *ancestor* container, so a self-typed mosaic would size its labels
   from the viewport instead of from itself. The section and the mosaic are the same width, so
   querying the section is querying the mosaic. This is what lets a size class chosen against the
   reference box stay true at every width the box is drawn at: the labels shrink with the tiles. */
.metagame-field { container-type: inline-size; }
.field-mosaic { position: relative; width: 100%; aspect-ratio: 1120 / 694; margin-top: .4rem; overflow: hidden; border-radius: .6rem; font-size: clamp(.62rem, 1.4286cqw, 1rem); }
.mosaic-tile { position: absolute; left: var(--tile-x, 0); top: var(--tile-y, 0); width: var(--tile-w, 0); height: var(--tile-h, 0); overflow: hidden; color: var(--text); text-decoration: none; background: var(--panel-strong); outline: 2px solid var(--bg); }
.mosaic-art { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; transition: transform .25s ease; }
.mosaic-scrim { position: absolute; inset: 0; background: linear-gradient(180deg, #0b0d1200 18%, #0b0d1266 48%, #0b0d12e8 82%, #0b0d12fa 100%); }
a.mosaic-tile:hover .mosaic-art { transform: scale(1.05); }
/* Raised, because the tiles overlap by their outlines: an un-raised focus ring is drawn under
   the neighbour that follows it. */
a.mosaic-tile:focus-visible { z-index: 3; outline: 3px solid var(--gold); }
.mosaic-label { position: absolute; inset: auto .55em .5em .6em; }
.mosaic-name { display: block; overflow: hidden; color: #fff; font-size: .95em; font-weight: 750; line-height: 1.15; letter-spacing: -.01em; text-shadow: 0 1px 3px #000; }
.mosaic-figures { display: block; margin-top: .1em; overflow: hidden; color: #d7dbe6; font-size: .78em; font-variant-numeric: tabular-nums; text-overflow: ellipsis; white-space: nowrap; text-shadow: 0 1px 3px #000; }
/* A name too long for its tile is truncated, never overflowed: two lines where the tile has the
   height for two, one clipped line where it does not. The size class is chosen from the tile's
   height in `mosaic.rs`, so these three rules and that decision are the same rule. */
.is-large .mosaic-name { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; }
/* Two lines of figures too, which is the room `mosaic.rs` counts on for the tail: `9.2% share ·
   9 more archetypes and the unclassified lists` is the longest line the page prints. The clamp is
   what bounds the wrap: the label is anchored to the tile's bottom, so an unbounded line more than
   the tile can hold grows *upward* and is clipped there, out of sight of the tile's own scroll
   height. Two lines is what the size class promises and two lines is all this may draw. */
.is-large .mosaic-figures { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; white-space: normal; }
.is-small .mosaic-name, .is-tiny .mosaic-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.is-small .mosaic-name { font-size: .76em; }
.is-small .mosaic-figures { font-size: .68em; }
.is-tiny .mosaic-label { inset: auto .35em .28em .4em; }
.is-tiny .mosaic-name { font-size: .66em; letter-spacing: -.02em; }
/* The tail is the one block whose lines are counted off its own rectangle rather than fixed by its
   size class, because its note is the only place the page says how many archetypes it stands for.
   `mosaic.rs` sends the count it measured; the clamp is what makes the count binding. Without it
   the wrap is unbounded, and since the label is anchored to the block's bottom the extra lines
   grow *upward*, out of the top of the block, where they are clipped silently: the block's own
   scroll height cannot see overflow before the origin. */
.is-tail .mosaic-figures { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: var(--figure-lines, 1); line-clamp: var(--figure-lines, 1); white-space: normal; }
/* The width half of the same decision, chosen in `mosaic.rs` and applied here. A figures line is
   dropped whole rather than clipped: a truncated `no decide…` reads as a broken page.
   These come last on purpose. A tiny tile has no room for a figures line at all, and `mosaic.rs`
   gives it `is-cramped` for that reason rather than a drop rule of its own, so one class decides
   whether a block draws figures at all — including the tail's, which the rule above would
   otherwise put back by winning on source order at equal specificity. The figures come back below
   the fold, where every tile has a whole row to itself. */
.is-narrow .mosaic-figure-note { display: none; }
.is-cramped .mosaic-figures { display: none; }
/* The win-rate edge grows from the tile's centre along the bottom: gold above the 50% spine,
   blue below it. The same valence pair as the ladder's axis, measuring the same quantity. */
.mosaic-edge { position: absolute; right: 0; bottom: 0; left: 0; height: 5px; background: #ffffff1a; }
.mosaic-edge-fill { position: absolute; top: 0; bottom: 0; width: var(--edge-width, 0%); }
.mosaic-edge-fill.is-above { left: 50%; background: var(--rate-above); }
.mosaic-edge-fill.is-below { right: 50%; background: var(--rate-below); }
/* The corner tag carries places gained or lost and nothing else, so it can take the valence pair
   outright where the ladder's movement chip cannot: the chip prints a share change beside its
   places, and the two can disagree about whether the row is doing well. */
.mosaic-tag { position: absolute; top: 0; right: 0; padding: .18em .45em; font-size: .7em; font-weight: 850; font-variant-numeric: tabular-nums; border-bottom-left-radius: .4em; }
.mosaic-tag.is-up { color: #14161c; background: var(--rate-above); }
.mosaic-tag.is-down { color: #10161c; background: var(--rate-below); }
/* The tail is a bag of archetypes, not a deck: hatched rather than art, and no win-rate edge,
   because an edge on it would rate something that cannot be played. */
.mosaic-tile.is-tail { background: repeating-linear-gradient(135deg, #1d2029 0 8px, #23262f 8px 16px); }
.is-tail .mosaic-name { color: var(--muted); font-style: italic; }
.mosaic-legend { display: flex; flex-wrap: wrap; gap: .4rem 1.4rem; margin: .9rem 0 0; padding: 0; color: var(--quiet); font-size: .78rem; list-style: none; }
.mosaic-legend b { color: var(--muted); font-weight: 700; }
.mosaic-key { display: inline-block; width: .7rem; height: .7rem; margin-right: .35rem; border-radius: .15rem; vertical-align: -1px; }
.mosaic-key.is-above { background: var(--rate-above); }
.mosaic-key.is-below { background: var(--rate-below); }
.mosaic-key.is-tail { background: repeating-linear-gradient(135deg, #1d2029 0 4px, #23262f 4px 8px); border: 1px solid var(--line); }
/* The ladder under the hero: the same field, counted. Native <details>, so it opens with no
   script, and the ladder's own column head labels what it opens onto. */
.field-numbers { margin-top: 2.5rem; }
.field-numbers > summary { margin-bottom: 1rem; color: var(--muted); font-size: .72rem; font-weight: 800; letter-spacing: .16em; text-transform: uppercase; cursor: pointer; }
.field-numbers > summary:hover { color: var(--text); }

/* Below the fold the mosaic is one column of blocks in share order. Area cannot be read across a
   375px strip — a 1% tile there is four pixels tall — so the hero stops claiming to encode it and
   becomes a list that still carries the art, the figures and the tags. The size classes were
   decided against the reference box, so they are reset: a tile too small for its figures at 1120px
   has a whole row for them here. */
@media screen and (max-width: 56rem) {
  .field-mosaic { display: grid; gap: 2px; aspect-ratio: auto; font-size: 1rem; }
  /* The packed rectangle goes with the packing: the grid places the block and decides how wide it
     is. It stays positioned, though. The art, the scrim, the edge and the tag are all absolute
     inside their own block, so a static block would hand every one of them to the mosaic and stack
     all of them on top of each other at the foot of the column. */
  .mosaic-tile { position: relative; display: flex; align-items: flex-end; inset: auto; width: auto; height: auto; min-height: 4rem; outline: 0; border-radius: .4rem; }
  /* The label is the exception: here it flows, and the row grows to hold it. A row here is a row
     in a list rather than an area, so its height means nothing and may follow its content — where
     a bottom-anchored label in a fixed-height block grows *upward* out of the block instead, and
     is clipped there out of sight. It keeps `position: relative` so it still paints over the art,
     which is absolute. */
  .field-mosaic .mosaic-label { position: relative; inset: auto; width: 100%; padding: .5rem .7rem .5rem .8rem; }
  .field-mosaic .mosaic-name { font-size: .95rem; }
  /* No clamp on the tail's figures here: the row has grown to hold whatever they wrap to. */
  .field-mosaic .mosaic-figures { display: block; font-size: .78rem; }
  .field-mosaic .mosaic-figure-note { display: inline; }
}

/* ---- the ladder ---- */
/* The show-more swap replaces this region while the reader is inside it. Chrome's scroll
   anchoring reacts to htmx's insert-then-remove with a scroll jump to the document foot once
   anything (the Recent events section) sits below the region, so the region opts out: the
   viewport stays put and the new rows land where the control was, which is what the control's
   template comment promises. */
.ladder-region { overflow-anchor: none; }
.ladder-head, .ladder-row { display: grid; grid-template-columns: 2.2rem minmax(8.5rem, 1.5fr) minmax(6.2rem, 1fr) 6rem minmax(10.5rem, 1.3fr) 4.4rem 4.2rem; align-items: center; gap: .7rem; }
.ladder-head { padding: 0 .8rem .5rem; color: var(--quiet); font-size: .68rem; font-weight: 800; letter-spacing: .12em; text-transform: uppercase; }
.ladder-head-spine { text-align: center; }
.ladder-head-record, .ladder-head-matches { text-align: right; }
.ladder-list { display: grid; gap: 2px; margin: 0; padding: 0; list-style: none; }
/* The whole row is the link: a name, a bar and a position on an axis are all the same answer
   about the same archetype, so there is nothing on a row that leads anywhere else. */
.ladder-row { position: relative; padding: .55rem .8rem; overflow: hidden; color: var(--text); text-decoration: none; border-radius: .4rem; }
.ladder-row::after { content: ""; position: absolute; inset: 0; border-bottom: 1px solid var(--line); pointer-events: none; }
.ladder-row:hover { background: var(--panel); }
/* Inset, because the row clips its own art. */
.ladder-row:focus-visible { outline: 2px solid var(--gold); outline-offset: -2px; }
/* The art bleeds behind the name under a horizontal scrim. 22rem at 22% opacity was unreadable
   as art and still muddied the name; 16rem at 70% under this scrim is what worked. */
.ladder-art { position: absolute; inset: 0 auto 0 0; width: 16rem; height: 100%; object-fit: cover; opacity: .7; -webkit-mask-image: linear-gradient(90deg, #000 0, #000 42%, transparent 100%); mask-image: linear-gradient(90deg, #000 0, #000 42%, transparent 100%); pointer-events: none; }
.ladder-row:hover .ladder-art { opacity: .92; }
.ladder-scrim { position: absolute; inset: 0 auto 0 0; width: 16rem; background: linear-gradient(90deg, #111319f2 0, #111319d9 18%, #11131985 52%, #11131900 100%); pointer-events: none; }
.ladder-rank { position: relative; color: var(--quiet); font-size: .95rem; font-weight: 800; font-variant-numeric: tabular-nums; text-align: right; }
.ladder-name { position: relative; display: flex; flex-wrap: wrap; align-items: center; gap: .4rem; min-width: 0; }
.ladder-name b { color: var(--text); font-size: 1rem; font-weight: 750; letter-spacing: -.01em; }
.ladder-row:hover .ladder-name b { color: var(--gold); }
.ladder-pips { display: inline-flex; gap: .15rem; }
.ladder-pips .color-pip { width: .85rem; height: .85rem; }
.ladder-share { position: relative; display: flex; align-items: center; gap: .6rem; min-width: 0; }
.ladder-share-track { position: relative; flex: 1; height: .55rem; background: #22262f; border-radius: 99rem; }
/* Scaled against the widest row rather than against 100%, so the field's own shape fills the
   column instead of collapsing into the left tenth of it. */
.ladder-share-fill { position: absolute; inset: 0 auto 0 0; width: var(--share-width, 0%); background: linear-gradient(90deg, #5a6480, #97a3c4); border-radius: 99rem; }
.ladder-share-num { min-width: 3.1rem; font-size: .95rem; font-weight: 750; font-variant-numeric: tabular-nums; letter-spacing: -.02em; text-align: right; }
.ladder-share-decks { display: block; color: var(--quiet); font-size: .74rem; font-weight: 400; }
/* The movement chip is monochrome on purpose: the arrows already carry direction, and
   gold/blue is spent one column over on the win-rate axis. A row can gain places while its own
   share falls, so colouring both would read as an agreement the two numbers do not have. */
.ladder-move { position: relative; display: flex; align-items: baseline; gap: .35rem; color: var(--quiet); font-variant-numeric: tabular-nums; letter-spacing: -.02em; }
/* Positioned so the spoken form beside the triangle has a containing block on the row.
   `.visually-hidden` is absolute; without a positioned ancestor its containing block is the
   page, so it parks its 1px at whatever coordinates the row's own layout implies — which once
   pushed the document 45px past a 375px viewport with nothing visible there to explain it. */
.ladder-move-rank { position: relative; min-width: 2.2rem; color: var(--text); font-size: .9rem; font-weight: 800; }
/* The shared movement arrow, inline SVG. It inherits its size and colour from the text it sits
   beside, so the ladder's chip and the mosaic's corner tag both get it at their own scale. */
.movement-arrow { width: 1em; height: 1em; fill: currentColor; vertical-align: -0.12em; }
.ladder-move-share { font-size: .78rem; }
.ladder-move-flat .ladder-move-rank { color: var(--quiet); font-weight: 700; }
/* No comparable previous window resolved, so the row has nothing to move against. */
.ladder-move-none { justify-content: flex-end; }
.ladder-move-new .ladder-move-rank { min-width: 0; font-size: .74rem; font-weight: 850; letter-spacing: .06em; }
/* The 50% spine. Not a rounded midpoint: the published pool balances there by construction, so
   it is the measured average of the very rates drawn against it. */
.ladder-spine { position: relative; height: 2.1rem; }
.ladder-spine-line { position: absolute; top: 0; bottom: 0; left: 50%; width: 1px; background: var(--quiet); }
.ladder-interval { position: absolute; top: 50%; left: var(--range-start, 50%); width: var(--range-width, 0%); height: .95rem; background: #ffffff1f; border-radius: .15rem; transform: translateY(-50%); }
.ladder-bar { position: absolute; top: 50%; left: min(var(--rate-position, 50%), 50%); width: calc(max(var(--rate-position, 50%), 50%) - min(var(--rate-position, 50%), 50%)); height: .42rem; background: var(--rate-above); border-radius: .1rem; transform: translateY(-50%); }
.ladder-spine.is-below .ladder-bar { background: var(--rate-below); }
/* The value sits outside the bar but inside the interval band, so it needs the shadow to stay
   legible. The min() keeps it inside the cell when the bar runs to the axis edge. */
.ladder-value { position: absolute; top: 50%; left: min(var(--rate-position, 50%), calc(100% - 3.9rem)); margin-left: .4rem; font-size: .82rem; font-weight: 750; font-variant-numeric: tabular-nums; white-space: nowrap; text-shadow: 0 1px 2px #0b0d12, 0 0 3px #0b0d12; transform: translateY(-50%); }
.ladder-spine.is-below .ladder-value { right: min(calc(100% - var(--rate-position, 50%)), calc(100% - 3.9rem)); left: auto; margin-right: .4rem; margin-left: 0; }
.ladder-value.is-flat { left: 50%; margin: 0; color: var(--quiet); transform: translate(-50%, -50%); }
/* Too few matches for the interval to say much. The band already says so at full width; the
   hatch says it again on the bar, where the eye goes first. */
.ladder-row.is-thin .ladder-bar { background-image: repeating-linear-gradient(90deg, #0000 0 3px, #0003 3px 6px); }
/* Under 50 matches the rate is not worth reading yet, so the whole cell is dimmed and the eye
   skips it. Dimmed by colour, not by opacity: opacity dropped these cells to 4.2:1 (see
   docs/release-candidate.md), while --quiet is the grey the match count beside it already uses,
   so the text keeps its contrast. It is also the grey `.ladder-value.is-flat` uses for a rate
   that says nothing, which is what this rate is as well, so the two recede alike. The band is
   the #ffffff1f above taken down one step, so it fades with the rest of the cell. */
.ladder-row.is-few .ladder-bar { background-color: var(--quiet); }
.ladder-row.is-few .ladder-interval { background: #ffffff12; }
.ladder-row.is-few .ladder-value { color: var(--quiet); }
/* The record the rate was computed from. It sits beside the axis rather than inside it because a
   draw moves the match count without moving the rate, so the axis alone can never show one. */
.ladder-record { position: relative; color: var(--muted); font-size: .82rem; font-variant-numeric: tabular-nums; white-space: nowrap; text-align: right; }
.ladder-matches { position: relative; color: var(--quiet); font-size: .82rem; font-variant-numeric: tabular-nums; text-align: right; }
/* The tail is a sentence, not a row: its share routinely beats the largest real archetype's,
   and a bar for it would set the scale for every real row on the page. */
.ladder-tail { max-width: 62ch; margin: .6rem 0 0; padding: .8rem .8rem 0; color: var(--quiet); font-size: .85rem; border-top: 1px dashed var(--line); }
.ladder-tail b { color: var(--muted); font-size: 1rem; font-weight: 800; font-variant-numeric: tabular-nums; }
/* The row-count control. A plain link, not a button: it is a navigation to the same page at a
   different length, so it must look like the link it is and work with no script. */
.ladder-more { margin: .6rem 0 0; padding: 0 .8rem; font-size: .85rem; }
.ladder-more > a { color: var(--blue); font-weight: 700; text-decoration: none; }
.ladder-more > a:hover { text-decoration: underline; }
/* With no tail sentence above it the link is the first thing under the list, so it takes the
   dashed rule the tail would otherwise have drawn. */
.ladder-list + .ladder-more { padding-top: .8rem; border-top: 1px dashed var(--line); }

/* Under 46rem the ladder folds to three rows: the name over the share and the chip, with the
   axis and the match count under both. The head goes — it labels columns that no longer sit
   side by side, and every row speaks its own labels anyway. */
@media screen and (max-width: 46rem) {
  .ladder-head { display: none; }
  /* The third column is fixed, not auto: `.ladder-name` spans both and would otherwise take an
     auto track's width with it. */
  .ladder-row { grid-template-columns: 1.8rem minmax(0, 1fr) 4.9rem; grid-template-areas: "rank name name" ". share move" ". spine record" ". spine matches"; row-gap: .3rem; column-gap: .6rem; }
  .ladder-rank { grid-area: rank; }
  .ladder-name { grid-area: name; }
  .ladder-share { grid-area: share; }
  .ladder-move { grid-area: move; align-self: center; justify-content: flex-end; }
  .ladder-move-rank { min-width: 0; }
  /* The axis spans both of the last two rows, so the record and the match count stack beside it
     instead of pushing a fourth full-width row under the row. */
  .ladder-spine { grid-area: spine; align-self: center; }
  .ladder-record { grid-area: record; align-self: end; }
  .ladder-matches { grid-area: matches; align-self: start; }
}

/* ---- recentevents ticket 04: the Recent events section (efforts/recentevents/) ----
   Variant G5: day-grouped expandable rows, the day label over a thick full-width rule, zebra on
   the event rows and inside the finisher tables, the open row marked by a stronger background
   only. The event name is the row's one real link and is held to its own text — a grid item
   stretches across its whole column by default, and the dead space past a short name would then
   navigate instead of toggling. */
.recent-list { border-top: 1px solid var(--line); }
.recent-day { padding: 1.1rem .1rem .35rem; border-bottom: 3px solid #3c4252; }
.recent-day span { color: var(--muted); font-size: .7rem; font-weight: 800; letter-spacing: .1em; text-transform: uppercase; }
/* The name anchor is the row's sibling, not the summary's child: a link inside a <summary> is
   a nested interactive control (axe: serious). The row grid lays the anchor over the summary's
   name cell, where an invisible same-text holder keeps the cell's size, and the anchor's
   margins mirror the summary's padding so the two texts coincide. */
.recent-row { position: relative; display: grid; grid-template-columns: minmax(10rem, 1fr) minmax(14rem, 1.6fr) minmax(9rem, auto) 1rem; column-gap: 1rem; border-bottom: 1px solid var(--line); }
.recent-row > details { grid-area: 1 / 1 / 2 / -1; min-width: 0; }
.recent-row > a.recent-name { z-index: 1; grid-area: 1 / 1 / 2 / 2; align-self: start; margin: .55rem 0 0 .6rem; }
.recent-name-hold { visibility: hidden; }
.recent-row summary { display: grid; grid-template-columns: minmax(10rem, 1fr) minmax(14rem, 1.6fr) minmax(9rem, auto) 1rem; align-items: center; column-gap: 1rem; padding: .55rem .4rem .55rem .6rem; cursor: pointer; list-style: none; }
.recent-row summary::-webkit-details-marker { display: none; }
.recent-row:nth-of-type(even) summary { background: rgb(255 255 255 / 3%); }
.recent-row:hover summary { background: rgb(255 255 255 / 6%); }
.recent-row details[open] > summary { background: rgb(255 255 255 / 7%); }
.recent-name { justify-self: start; max-width: 100%; min-width: 0; overflow: hidden; color: var(--text); font-size: .86rem; font-weight: 700; text-decoration: none; text-overflow: ellipsis; white-space: nowrap; }
.recent-name:hover { color: var(--blue); text-decoration: underline; }
.recent-win { display: flex; align-items: center; gap: .35rem; min-width: 0; overflow: hidden; color: var(--muted); font-size: .8rem; white-space: nowrap; }
.recent-win .recent-deck-name { color: var(--text); font-weight: 700; }
.recent-win i { overflow: hidden; color: var(--quiet); font-style: normal; text-overflow: ellipsis; }
.recent-facts { overflow: hidden; color: var(--quiet); font-size: .76rem; font-variant-numeric: tabular-nums; text-align: right; text-overflow: ellipsis; white-space: nowrap; }
.recent-facts b { color: var(--text); font-weight: 600; }
.recent-caret { color: var(--quiet); font-size: .7rem; transition: transform .15s; }
.recent-row details[open] .recent-caret { transform: rotate(90deg); }
.recent-body { padding: .4rem .4rem 1rem .6rem; }
.recent-split { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 1.4rem; align-items: start; }
.recent-block { min-width: 0; }
.recent-split > .recent-block + .recent-block { padding-left: 1.4rem; border-left: 1px solid var(--line); }
.recent-finishers { width: 100%; min-width: 0; }
.recent-finishers td, .recent-finishers th { padding: .28rem .6rem; font-size: .78rem; }
.recent-finishers tbody tr:nth-child(even) td { background: rgb(255 255 255 / 3%); }
/* a deck named the house way: the identity pips, then the archetype, sized like the ladder's */
.recent-deck { display: inline-flex; align-items: baseline; gap: .3rem; min-width: 0; }
.recent-deck .color-identity { min-height: 0; gap: .18rem; align-self: center; }
.recent-deck .color-pip { width: .85rem; height: .85rem; }
.recent-deck-link { text-decoration: none; }
.recent-deck-link:hover .recent-deck-name { text-decoration: underline; }
.recent-note { margin: .4rem 0 0; color: var(--quiet); font-size: .76rem; }
.recent-out { display: inline-block; margin-top: .6rem; color: var(--blue); font-size: .78rem; font-weight: 700; text-decoration: none; }
.recent-out:hover { text-decoration: underline; }
.recent-pager { display: flex; flex-wrap: wrap; align-items: center; gap: .4rem 1rem; margin-top: .8rem; color: var(--muted); font-size: .8rem; }
.recent-pager a { color: var(--blue); font-weight: 700; text-decoration: none; }
.recent-pager a:hover { text-decoration: underline; }
.recent-pager .recent-pager-off { color: var(--quiet); }
@media screen and (max-width: 46rem) {
  .recent-row { grid-template-columns: 1fr 1rem; }
  .recent-row summary { grid-template-columns: 1fr 1rem; grid-template-areas: "name caret" "win caret" "facts caret"; row-gap: .1rem; }
  .recent-row summary > .recent-name { grid-area: name; }
  .recent-name { white-space: normal; }
  .recent-win { grid-area: win; white-space: normal; }
  .recent-facts { grid-area: facts; text-align: left; }
  .recent-caret { grid-area: caret; align-self: center; }
  .recent-body { padding-left: .4rem; overflow-x: auto; }
  .recent-split { grid-template-columns: 1fr; }
  .recent-split > .recent-block + .recent-block { padding-left: 0; border-left: 0; }
}

/* ---- redesign ticket 08: the archetype stock list -------------------------------
   Every card is a per-copy ladder. The request supplies only --slot-width through the nonced
   style block; this stylesheet owns all geometry and both certainty colours. */
.archetype-hero { position: relative; width: min(100% - 2rem, 70rem); margin-inline: auto; }
.archetype-hero-frame { position: relative; overflow: hidden; -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 7%, #000 93%, transparent 100%); mask-image: linear-gradient(90deg, transparent 0, #000 7%, #000 93%, transparent 100%); }
.archetype-hero-art, .archetype-art-fallback { display: block; width: 100%; height: clamp(13rem, 26vw, 21rem); object-fit: cover; object-position: center 32%; background: var(--panel-strong); }
.archetype-art-fallback { display: grid; height: clamp(13rem, 26vw, 21rem); place-items: center; color: var(--muted); font-size: 3rem; border: 2px dashed var(--line); }
/* Two layers, as in the prototype. The vertical one shapes the frame top to bottom; the
   horizontal one darkens the left side, where the eyebrow, the title and the pips sit. Without
   it the copy's own backdrop is whatever the art crop happens to be, which is where the eyebrow
   loses its contrast on a bright crop.
   Lighter than the prototype's own values on purpose, so more of the art shows through. The
   floor is the h1: against a fully white crop its worst pixel measures 3.40:1, over the 3:1
   AA floor for large text. Going lighter than this drops it under. */
.archetype-hero-scrim { position: absolute; inset: 0; background: linear-gradient(180deg, rgb(17 19 25 / 78%) 0, rgb(17 19 25 / 26%) 30%, rgb(17 19 25 / 78%) 72%, var(--bg) 100%), linear-gradient(90deg, rgb(17 19 25 / 55%) 0, rgb(17 19 25 / 10%) 50%, rgb(17 19 25 / 0%) 100%); }
.archetype-hero-frame .art-credit { position: absolute; right: 1rem; bottom: .35rem; z-index: 1; margin: 0; color: rgb(255 255 255 / 58%); font-size: .65rem; }
.archetype-hero-body { position: absolute; inset: auto 0 0; z-index: 2; padding: 0 1.2rem 1.2rem; }
/* redesign ticket 52: the back link is the hero's eyebrow, so it takes the site's own
   `.eyebrow` token from the template instead of restating it here. Only the spacing, the
   link and its legibility are the hero's business. Hover underlines rather than changing
   hue: gold is the site's one accent, and a second colour here would be a new one.
   The shadow is what makes the accent safe. Gold measures 9.58:1 on the page background,
   but the eyebrow is drawn over the hero art, and at 375px it lands where the scrim is at
   its thinnest. Over a bright crop the glyphs measured 1.00:1 there without it, and no text
   colour on the site clears the bar at that spot: the shipped grey measured 1.20:1 and white
   1.63:1. Three stacked drops of #0b0d12, the near-black `.ladder-value` already uses over
   the same kind of backdrop, took the worst glyph pixel to 5.41:1 at 375px and 8.12:1 at
   1280px, both over the 4.5:1 AA floor for small text.
   Those numbers were measured against the earlier single-layer scrim. The horizontal layer
   added since only darkens that backdrop, so they are a floor, not a ceiling. It does not
   make the shadow redundant: bare gold over a bright crop still measured 2.90:1 at 375px
   with both layers, under the 4.5:1 floor. */
.archetype-back { margin: 0 0 .65rem; }
.archetype-back a { color: inherit; text-decoration: none; text-shadow: 0 0 2px #0b0d12, 0 0 4px #0b0d12, 0 0 8px #0b0d12; }
.archetype-back a:hover { text-decoration: underline; }
.archetype-hero h1 { display: flex; flex-wrap: wrap; align-items: center; gap: .45rem .75rem; margin: 0; font-size: clamp(2.1rem, 6vw, 4rem); font-weight: 850; line-height: .95; letter-spacing: -.045em; }
.archetype-title-identity .color-identity { gap: .22rem; min-height: 0; }
.archetype-title-identity .color-pip { width: clamp(2.3rem, 5vw, 3.3rem); height: clamp(2.3rem, 5vw, 3.3rem); filter: drop-shadow(0 2px 6px rgb(0 0 0 / 60%)); }
.archetype-title-plain { display: inline-grid; width: clamp(2.3rem, 5vw, 3.3rem); height: clamp(2.3rem, 5vw, 3.3rem); place-items: center; color: var(--muted); font-size: .65em; border: 1px solid var(--line); border-radius: 50%; }
.archetype-hero .tournament-facts { margin-top: .55rem; }
.archetype-content { padding-bottom: 5rem; }
/* The win rate's interval bar sits under its label, so the number above it stays the vital's
   own heading. `.page-vital span` reaches every span inside the vital, including the bar's
   own pieces, so the offset it gives a label is cleared here. */
.archetype-content .page-vital:nth-child(2) .ladder-spine { display: block; height: .95rem; margin-top: .45rem; }
.archetype-content .page-vital:nth-child(2) .ladder-spine > span { margin-top: 0; }
.archetype-content .page-vital:nth-child(2) .ladder-interval { height: .7rem; }
.archetype-content .page-vital:nth-child(2) .ladder-bar { height: .3rem; }
.archetype-promo-slot { width: min(728px, 100%); aspect-ratio: 728 / 90; margin: 1.7rem auto 0; background: var(--panel); border: 1px solid var(--line); border-radius: .65rem; }
.archetype-promo-slot .promo-728 { width: 100%; min-height: 100%; margin: 0; border: 0; }
.stock-boards { display: grid; grid-template-columns: minmax(0, 1.8fr) minmax(0, 1fr); gap: 1rem 2rem; align-items: start; }
.stock-board { position: relative; min-width: 0; padding-bottom: 6.3rem; }
.stock-band { margin-bottom: 1.15rem; }
.stock-band-head { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; margin-bottom: .3rem; padding-bottom: .35rem; border-bottom: 1px solid var(--line); }
.stock-band-head h3 { margin: 0; color: var(--text); font-size: .72rem; font-weight: 800; letter-spacing: .13em; text-transform: uppercase; }
.stock-band-head span { color: var(--quiet); font-size: .76rem; font-variant-numeric: tabular-nums; white-space: nowrap; }
.stock-board-main .stock-rows { columns: 2 15rem; column-gap: 1.2rem; }
/* The bar column is exactly four pills and the three gaps between them, so the name column
   keeps every pixel the bar does not use. */
.stock-row { --slot-track: calc(4 * .55rem + 3 * 2px); display: grid; grid-template-columns: var(--slot-track) minmax(3.5rem, max-content) minmax(0, 1fr) 2.4rem; align-items: center; gap: .4rem; padding: .16rem .25rem; break-inside: avoid; border-radius: .3rem; outline: none; }
.stock-row:hover, .stock-row:focus-visible { background: var(--panel); }
.stock-row:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
/* One declaration owns the gap, so a row's bar and the legend's worked examples are drawn by
   the same encoding. The cells do not grow: four copies have to read as four pills, not as one
   smooth block. */
.slot-bar { display: flex; gap: 2px; }
.slot-cell { position: relative; display: block; flex: 0 1 .55rem; min-width: 0; width: .55rem; height: .9rem; overflow: hidden; background: rgb(255 255 255 / 5%); border-radius: 1px; box-shadow: inset 0 0 0 1px rgb(255 255 255 / 14%); }
/* A basic land registers up to twenty-three copies, and no bar draws twenty-three pills in the
   width four pills take. Past ten copies each pill would be thinner than the gap beside it, so
   those bars close up into one block again and the cells share the column. The ink is the
   number, so the pill gives way and the ink never does. */
.slot-bar:has(> .slot-cell:nth-child(11)) { gap: 0; }
.slot-bar:has(> .slot-cell:nth-child(11)) .slot-cell { flex: 1 1 .55rem; }
.slot-fill { position: absolute; inset: 0 auto 0 0; width: var(--slot-width); }
.slot-cell.is-settled .slot-fill { background: #c9d1e4; }
.slot-cell.is-argued .slot-fill { background: #9a78dd; }
/* The cost is the site's own mana symbols, as the deck view draws them. Drawn as text, a
   three-symbol cost clipped in this column; the track now grows to the widest cost on the
   board and the name beside it takes what is left. */
.stock-cost { display: flex; justify-content: flex-end; min-width: 0; }
.stock-cost .mana-cost { gap: .08rem; }
.stock-cost .mana-cost-symbol { width: .74rem; height: .74rem; }
.stock-name { overflow: hidden; font-size: .86rem; font-weight: 650; text-overflow: ellipsis; white-space: nowrap; }
.stock-rate { color: var(--quiet); font-size: .74rem; font-variant-numeric: tabular-nums; text-align: right; }
.stock-row.is-argued .stock-name { color: var(--muted); font-weight: 550; }
.stock-row.is-argued .stock-rate { color: #b99af2; }
.slot-legend { display: flex; flex-wrap: wrap; align-items: center; gap: .4rem 1.2rem; margin: -.25rem 0 .85rem; color: var(--quiet); font-size: .72rem; }
.slot-legend > span { display: flex; align-items: center; gap: .4rem; }
/* The legend keeps only its smaller size. The gap it reads by now belongs to `.slot-bar`. */
.slot-legend .slot-cell { flex-basis: .42rem; width: .42rem; height: .75rem; }
.legend-all { --slot-width: 100%; }
.legend-quarter { --slot-width: 25%; }
.legend-mixed .slot-cell:first-child { --slot-width: 96%; }
.legend-mixed .slot-cell:last-child { --slot-width: 40%; }
.stock-tail { margin: .45rem 0 0; padding: .5rem .25rem 0; color: var(--quiet); font-size: .78rem; border-top: 1px dashed var(--line); }
.stock-caption-box, .stock-row-caption { position: absolute; right: 0; bottom: 0; left: 0; box-sizing: border-box; height: 5.4rem; overflow: auto; padding: .65rem .75rem; color: var(--muted); font-size: .78rem; line-height: 1.45; background: var(--panel); border: 1px solid var(--line); border-radius: .5rem; }
.stock-caption-box { display: grid; align-content: center; }
.stock-caption-box p { margin: 0; }
.stock-row-caption { z-index: 1; visibility: hidden; opacity: 0; }
.stock-row-caption b, .stock-row-caption span { display: block; }
.stock-row-caption span { margin-top: .25rem; color: var(--text); font-variant-numeric: tabular-nums; }
.stock-row:hover .stock-row-caption, .stock-row:focus .stock-row-caption { visibility: visible; opacity: 1; }
/* Ticket 53: the boards' card preview, the prototype's box at
   `efforts/redesign/prototype-archetype/prototype.tpl.html:478-497`. It is fixed, so a board's
   own height never moves when a row is pointed at, and `deck-view.js` places it clear of the row
   it belongs to. The width is the prototype's 15rem card; at phone width it steps down so the
   whole box still fits above or below its row. */
.card-preview { position: fixed; top: 0; left: 0; z-index: 60; display: flex; flex-direction: column; width: 15rem; margin: 0; pointer-events: none; opacity: 0; transition: opacity .12s ease; }
/* `display` here beats the browser's own rule for the attribute, so the figure has to be told
   again to stay out of a page that never runs the script that fills it. */
.card-preview[hidden] { display: none; }
.card-preview.is-open { opacity: 1; }
/* A basic land registers many copies, so a ladder can be taller than the room the box has.
   `deck-view.js` caps the box at that room, and what gives way is ordered: the card shrinks
   first, then the ladder scrolls, and the sentence under it never clips. The box never takes
   the pointer, open or closed: a card drawn over other rows must not stop a reader reaching
   them. */
/* `999` against the caption's `1`: the card absorbs the whole cap before the caption gives up a
   pixel, whatever height each of them happens to start at. The floor stops a ladder long enough
   to eat the room from shrinking the card away to nothing, which is the one thing a reader
   opened the box for. Under the floor the ladder scrolls instead. */
.card-preview img { flex: 0 999 auto; display: block; width: 100%; min-height: 6rem; aspect-ratio: 5 / 7; height: auto; object-fit: contain; background: var(--panel-strong); border-radius: 4.75% / 3.4%; box-shadow: 0 16px 40px rgb(0 0 0 / 70%); }
.card-preview img[hidden] { display: none; }
.card-preview figcaption { display: flex; flex: 0 1 auto; flex-direction: column; min-height: 0; margin-top: .45rem; overflow: hidden; padding: .5rem .6rem; color: var(--muted); font-size: .78rem; line-height: 1.4; background: var(--panel-strong); border: 1px solid var(--line); border-radius: .5rem; box-shadow: 0 16px 40px rgb(0 0 0 / 70%); }
.card-preview .deck-preview-ladder { flex: 0 1 auto; min-height: 0; margin-bottom: .35rem; overflow-y: auto; overscroll-behavior: contain; }
.card-preview .deck-preview-summary { flex: 0 0 auto; }
/* The name only appears when there is no card to show it. With the card up, printing it again
   would be the third copy of the same words on screen. */
.card-preview-name { display: block; margin-bottom: .3rem; color: var(--text); }
/* With scripting the preview replaces the per-row strip. Without it, the strip is what a reader
   pointing at a row gets, exactly as before. */
.js-card-preview .stock-row-caption { display: none; }
.archetype-section { margin-top: 2.2rem; }
.archetype-list-layout { margin-top: .9rem; }
.js-deck-pane .archetype-list-layout { display: grid; grid-template-columns: minmax(0, 1fr) minmax(15rem, 20rem); grid-template-areas: "pane picker" "pane pilots"; grid-template-rows: auto 1fr; gap: 1.4rem 2rem; align-items: start; }
.archetype-list-picker-column { grid-area: picker; min-width: 0; }
/* The rail head carries the rule the rail used to draw itself, so the section keeps one line
   above its first row rather than two. Same shape as `.stock-band-head`, one section up. */
.archetype-list-picker-head { display: flex; align-items: baseline; justify-content: space-between; gap: .8rem; margin-bottom: .1rem; padding-bottom: .35rem; border-bottom: 1px solid var(--line); }
.archetype-list-picker-head h3 { margin: 0; color: var(--text); font-size: .72rem; font-weight: 800; letter-spacing: .13em; text-transform: uppercase; }
.archetype-list-picker-head span { color: var(--quiet); font-size: .76rem; white-space: nowrap; }
.archetype-list-picker { max-height: 50rem; overflow-y: auto; scrollbar-gutter: stable; scrollbar-width: thin; }
.archetype-list-picker > .deck-list-row { grid-template-columns: 2.7rem minmax(0, 1fr); gap: .2rem .55rem; padding: .48rem .5rem; border-bottom: 1px solid var(--line); }
.archetype-list-picker > .deck-list-row.is-picked { box-shadow: inset 3px 0 #ccd4e8; }
/* Ticket 55: the finish chip is the same object on the rail row and on the opened head, so it is
   one declaration read through both of its parents. The head's own `.deck-pane-head > span` rule
   would otherwise quiet it, which is why the head selector names the child directly. A League
   chip is a record and not a place, so it drops to the muted tone and a smaller size instead of
   sitting at a placing's weight. */
.archetype-list-picker > .deck-list-row > .archetype-list-finish,
.deck-search-row > .archetype-list-finish,
.archetype-deck-head > .archetype-list-finish { color: var(--text); font-size: 1.05rem; font-weight: 800; font-variant-numeric: tabular-nums; letter-spacing: -.03em; white-space: nowrap; }
.archetype-list-picker > .deck-list-row > .archetype-list-finish.is-league,
.deck-search-row > .archetype-list-finish.is-league,
.archetype-deck-head > .archetype-list-finish.is-league { color: var(--muted); font-size: .82rem; font-weight: 700; letter-spacing: 0; }
.archetype-list-pick-main { display: grid; min-width: 0; }
.archetype-list-who { overflow: hidden; color: var(--text); font-size: .86rem; font-weight: 650; text-overflow: ellipsis; white-space: nowrap; }
.archetype-list-at { overflow: hidden; color: var(--muted); font-size: .76rem; text-overflow: ellipsis; white-space: nowrap; }
/* The mark rides with the player name it belongs to. `#ccd4e8` is the accent this rail already
   uses for the picked row's edge, and the mark only ever appears on that row. */
.archetype-list-mark { color: #ccd4e8; font-size: .7rem; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; }
/* The pilots close the rail column, so they are their own row of the layout rather than a child of
   the rail: on one column the rail comes first and the list has to stay next to it, with the pilots
   last. Tighter than `.archetype-section` because they are the second block of one column, not a
   new section of the page. */
.archetype-pilots { margin-top: .6rem; }
.js-deck-pane .archetype-list-layout > .archetype-pilots { grid-area: pilots; margin-top: 0; }
/* The rail's row-count control, inside the scroll box so it follows the last row. */
.archetype-list-more { margin: 0; padding: .55rem .5rem; font-size: .85rem; }
.archetype-list-more > a { color: var(--blue); font-weight: 700; text-decoration: none; }
.archetype-list-more > a:hover { text-decoration: underline; }
/* The crossing out of the selected window, between the last in-window row and the first older one. */
.deck-list-divider { padding: .6rem .5rem .3rem; border-bottom: 1px solid var(--line); color: var(--quiet); font-size: .68rem; font-weight: 800; letter-spacing: .11em; text-transform: uppercase; }
.archetype-list-picker-column > .deck-list-source { margin-top: .6rem; color: var(--muted); }
.archetype-list-picker-column > .deck-list-source > summary { padding: .35rem; color: var(--blue); cursor: pointer; }
.js-deck-pane .archetype-list-layout .deck-list-pane { grid-area: pane; }
.archetype-deck-content { position: relative; }
/* The right padding is the gutter the tool row below sits in. It reserves three tools, because
   the Arena tool is only on Pioneer and Standard decks and the head has no way to know: at three
   the row is 5.9rem wide, and reserving that much holds whether the third tool is there or not.
   The figure is read from the tool tokens, so it cannot drift from the buttons. Reserving too
   little painted the Arena button over the tag, or over the ellipsised player name at 375px. */
.archetype-deck-head { gap: .25rem .8rem; min-height: 2.1rem; padding: 0 calc(3 * var(--deck-tool-size) + 2 * var(--deck-tool-gap) + .35rem) .5rem 0; }
/* The player is the head's subject now, so it carries the prototype's own head type
   (`prototype.tpl.html:148`, `1.15rem` at 800): at the chip's size and a lighter weight the place
   out-weighed the name it is meant to introduce. Measured on the release candidate, the name
   ellipsises inside the head rather than pushing the tag, so the larger type costs no line at
   375px. Normal tracking, because tightening it costs the name .4rem. */
.archetype-deck-head > b { min-width: 0; overflow: hidden; font-size: 1.15rem; font-weight: 800; letter-spacing: normal; text-overflow: ellipsis; white-space: nowrap; }
/* The event line comes before the tag in the markup, which is the order a reader hears, but it is
   laid out last so it takes the whole second row and the tag closes the head line beside the
   player. Nothing here is focusable, so laid-out order and tab order cannot disagree. Giving the
   line its own row is what keeps the name above it at full measure, and it is what stops the tag
   from squeezing the date out at 375px. */
.archetype-deck-head > .archetype-deck-where { flex: 0 0 100%; order: 1; overflow: hidden; color: var(--quiet); font-size: .8rem; text-overflow: ellipsis; white-space: nowrap; }
/* `margin-left: auto` lands the tag against the head's own right padding, which is the gap the
   absolutely placed deck actions sit in. That is where the prototype's capture shows it. */
.archetype-deck-head > .archetype-deck-tag { margin-left: auto; padding: .1rem .4rem; color: #10131b; font-size: .66rem; font-weight: 800; letter-spacing: .07em; text-transform: uppercase; background: #ccd4e8; border-radius: .25rem; }
/* Keep the shared component's own actions on the head line. The component and its behaviour stay
   unchanged; only this caller changes their containing block and direction. */
/* Equal halves, like the prototype (`.dl-body .dl-rail { grid-column: 3 / 5 }`): the two boards are
   two halves of one 75-card list, so the sideboard gets the same measure as the maindeck instead of
   the component's narrow rail. --deck-rail is left alone, so the card and its caption keep their
   15.2rem and centre inside the wider half. */
.archetype-deck-content .deck-body { position: static; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); padding: .8rem .35rem 1rem 0; }
.archetype-deck-content .deck-tools { position: absolute; top: 0; right: 0; left: auto; flex-direction: row; margin: 0; }
/* Same reason as the narrow-viewport rule: a row of tools has no room to the right of a button
   for the flash, so it drops under it. */
.archetype-deck-content .copy-tool.copied::after, .archetype-deck-content .copy-tool.copy-failed::after { top: calc(100% + .3rem); left: 50%; transform: translateX(-50%); }
.archetype-deck-content .deck-cols { columns: 1; }
.archetype-deck-content .deck-body li.deck-row { grid-template-columns: 1.3rem minmax(0, 1fr) auto 2.5rem; gap: .4rem; padding-block: .12rem; font-size: .92rem; }
.archetype-deck-content .deck-body .deck-row .mana-cost-symbol { width: .85rem; height: .85rem; }
.archetype-deck-content .deck-body .deck-row:hover { background: var(--panel); border-radius: .25rem; }
.archetype-deck-content .deck-preview-caption { gap: .35rem; }
.archetype-deck-content .card-name.inclusion-argued { color: var(--muted); font-weight: 550; }
/* The inclusion caption belongs to the shared deck view, not to this caller: it is an `<em>`, so
   it needs the upright, quiet, right-aligned treatment spelled out or it renders as body italics. */
.deck-inclusion-rate { color: var(--quiet); font-size: .76rem; font-style: normal; font-variant-numeric: tabular-nums; text-align: right; }
.deck-inclusion-rate.is-argued { color: #b99af2; }
/* Redesign ticket 58: the pilots are a wrapping row of chips, not a table. Nobody ranks pilots by
   record here, they look for the handles that keep showing up, so the whole chip is the link and
   its two facts sit on one baseline. The figures take `--quiet`, which clears 4.5:1 on `--panel`. */
.pilot-chips { display: flex; flex-wrap: wrap; gap: .4rem; margin: .9rem 0 0; padding: 0; list-style: none; }
.pilot-chips > li { max-width: 100%; }
.pilot-chip { display: flex; align-items: baseline; gap: .45rem; max-width: 100%; padding: .35rem .6rem; text-decoration: none; background: var(--panel); border: 1px solid var(--line); border-radius: .4rem; }
/* The prototype's own hover (`.ap-pilot:hover`, prototype.tpl.html:213): the edge alone answers,
   the ink does not move. Gold is safe on this chip because the row has no selected state for it to
   be confused with. */
.pilot-chip:hover { border-color: var(--gold); }
/* A handle is the one thing on this chip whose length the page does not set, and the table this
   replaced sat in a horizontal scroller that absorbed a long one. Nothing absorbs it now, so the
   chip stops at the page measure and the handle wraps inside it. The longest handle on file is 26
   characters and fits on one line at 375px; the guard is for the ones that do not. The figures
   never break, which is how every other handle on the site is treated (`.home-cell-who`,
   `.tournament-row-player a`). */
.pilot-chip b { min-width: 0; overflow-wrap: anywhere; color: var(--text); font-size: .85rem; font-weight: 700; }
.pilot-chip span { flex: none; color: var(--quiet); font-size: .76rem; font-variant-numeric: tabular-nums; white-space: nowrap; }
.archetype-table { width: 100%; border-collapse: collapse; font-size: .88rem; }
.archetype-table th, .archetype-table td { padding: .5rem .7rem; border-bottom: 1px solid var(--line); text-align: left; font-variant-numeric: tabular-nums; }
.archetype-table th { color: var(--muted); font-size: .76rem; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; }
.archetype-table th.num, .archetype-table td.num { text-align: right; }

@media screen and (max-width: 62rem) {
  .stock-boards { grid-template-columns: minmax(0, 1fr); }
  .stock-board-main .stock-rows { columns: 1; }
  .js-deck-pane .archetype-list-layout { grid-template-columns: minmax(0, 1fr); grid-template-areas: "picker" "pane" "pilots"; grid-template-rows: auto; }
  .archetype-list-picker { max-height: 24rem; }
}
@media screen and (max-width: 34rem) {
  .archetype-hero-body { padding-inline: .5rem; }
  .archetype-content .page-vital { flex-basis: 42%; }
  .stock-row { grid-template-columns: var(--slot-track) minmax(0, 1fr) 2.4rem; }
  .stock-cost { display: none; }
  /* A 375px-wide screen has no room beside a full-width row, so the preview stacks above or
     below it. 15rem of card plus its caption does not fit in what is left of a phone screen;
     11rem does. */
  .card-preview { width: 11rem; }
}

/* Ticket 18: the collapsed Method disclosure
   (efforts/metagamebuild/issues/18-coverage-note-collapsed.md). The coverage caveats on both
   metagame routes hide inside a native <details>, so the disclosure opens and closes without a
   script — the release bar's JS-disabled journeys operate it — and the default marker triangle
   is kept as the open/closed affordance (never a colour-only indicator). The site's style-src
   'self' CSP drops inline style attributes, so every rule lives here, never in the template. */
.coverage-disclosure > summary { cursor: pointer; font-weight: 700; }
.coverage-disclosure > summary:hover { color: var(--blue); }
.coverage-disclosure[open] > summary { margin-bottom: .6rem; }
.coverage-disclosure .coverage-note { margin-top: .5rem; }

/* ---- redesign ticket 06: the home page (efforts/redesign/issues/06-build-home.md) ------------
   The scouting band over one band per format. The band is a strip of art whose three crops are
   sized against each other rather than against the format — Modern's three biggest decks are
   under a quarter of it, and three slivers beside a hatched wall is not a picture. The width is
   only the shape: the number printed on each crop is the real share, and it arrives as
   `--crop-flex` in the response's nonced <style>, scoped to that strip's own id. */
.home { padding-bottom: 4rem; }
.home-scout { display: grid; grid-template-columns: minmax(19rem, 1.7fr) minmax(9.5rem, 1fr) minmax(9.5rem, 1fr); gap: 1.9rem; align-items: start; padding-block: clamp(1.8rem, 4vw, 3rem) 1.5rem; }
.home-scout > div { min-width: 0; }
.home-scout h1 { margin: 0; font-size: clamp(2rem, 4.6vw, 3rem); font-weight: 850; line-height: 1; letter-spacing: -.04em; }
.home-lede { max-width: 46ch; margin: .9rem 0 0; color: var(--muted); font-size: .95rem; }
/* The site's one search field is the top bar's (ticket 16), so the band says where it is rather
   than growing a second one. */
.home-hint { margin: .55rem 0 0; color: var(--quiet); font-size: .82rem; }
.home-roster h2 { margin: 0 0 .4rem; color: var(--muted); font-size: .68rem; font-weight: 800; letter-spacing: .12em; text-transform: uppercase; }
.home-roster ul { margin: 0; padding: 0; list-style: none; }
.home-roster li { display: flex; align-items: baseline; justify-content: space-between; gap: .6rem; padding: .35rem 0; border-top: 1px solid var(--line); font-size: .85rem; }
.home-roster li:first-child { border-top: 0; }
.home-roster a { min-width: 0; overflow: hidden; color: var(--text); text-decoration: none; text-overflow: ellipsis; white-space: nowrap; }
.home-roster a:hover { color: var(--blue); text-decoration: underline; }
.home-roster span { color: var(--quiet); font-size: .76rem; font-variant-numeric: tabular-nums; white-space: nowrap; }

.home-band { margin-top: 2rem; }
.home-band-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: .25rem .9rem; margin-bottom: .5rem; }
.home-band-head h3 { margin: 0; font-size: 1.35rem; font-weight: 850; letter-spacing: -.035em; }
.home-band-head h3 a { color: var(--text); text-decoration: none; }
.home-band-head h3 a:hover { color: var(--blue); }
.home-band-head p { margin: 0; color: var(--muted); font-size: .8rem; font-variant-numeric: tabular-nums; }
/* Three decks are between a fifth and a half of a format, so the link out says how much more of
   it there is rather than only where it goes. */
.home-band-out { margin-left: auto; color: var(--blue); font-size: .8rem; font-weight: 650; text-decoration: none; white-space: nowrap; }
.home-band-out::after { content: " →"; }
.home-band-out:hover { text-decoration: underline; }

/* `min-width` over a purely share-derived width: a 6.7% deck would get 90px of a proportional
   strip, which is enough for the letter C. A shape that eats the name is worth less than the
   name, so the strip clips instead (`overflow: hidden`) and stacks below 46rem. */
.home-strip { display: flex; height: 7.5rem; margin: 0; padding: 0; overflow: hidden; list-style: none; background: var(--panel-strong); border-radius: .5rem; }
.home-crop { position: relative; flex: var(--crop-flex, 1) 1 0; min-width: 10.5rem; }
.home-crop + .home-crop { border-left: 2px solid var(--bg); }
.home-crop > a { display: block; height: 100%; color: inherit; text-decoration: none; }
.home-crop > a:focus-visible { outline: 2px solid var(--gold); outline-offset: -3px; }
.home-crop img { display: block; width: 100%; height: 100%; object-fit: cover; }
/* Art runs out past the top of a format. The cell keeps its name and its share on a hatched
   ground, because a black rectangle reads as a broken image and this is not one. */
.home-crop-blank { display: block; width: 100%; height: 100%; background: repeating-linear-gradient(135deg, #22283400 0 5px, #1b202b 5px 10px), var(--panel-strong); }
/* The cell edges disappear under the art, so the label needs its own dark ground to read as the
   caption of one crop rather than a note floating over three. */
.home-crop-scrim { position: absolute; inset: auto 0 0 0; padding: 2rem .7rem .55rem; background: linear-gradient(to top, #05060af6 0%, #05060ad9 45%, #05060a00 100%); }
.home-crop-name { display: block; overflow: hidden; color: #fff; font-size: .88rem; font-weight: 750; text-overflow: ellipsis; white-space: nowrap; }
.home-crop > a:hover .home-crop-name { text-decoration: underline; }
.home-crop-pips { display: inline-flex; gap: .16rem; margin-right: .3rem; vertical-align: -2px; }
.home-crop-pips .color-pip { width: .85rem; height: .85rem; }
.home-crop-figure { display: flex; align-items: baseline; gap: .6rem; margin-top: .1rem; }
.home-crop-figure > b { font-size: 1.1rem; font-weight: 800; font-variant-numeric: tabular-nums; letter-spacing: -.03em; }
.home-crop-tail { display: grid; flex: 0 0 11rem; place-content: center; padding: .6rem .8rem; background: repeating-linear-gradient(135deg, #22283400 0 5px, #1b202b 5px 10px), var(--panel); text-align: center; }
.home-crop-tail b { display: block; font-size: 1.15rem; font-weight: 800; font-variant-numeric: tabular-nums; }
.home-crop-tail span { display: block; margin-top: .1rem; color: var(--muted); font-size: .72rem; }

/* The events. `.archetype-table` is the site's own table, so the head, the rules and the tabular
   numbers are not invented here. Every column but the winning deck is fixed, so the slack at
   desktop lands on the only column that can need it: the longest real value on file is
   "Death and Taxes (Yorion) - Black/White". */
.home-events { margin-top: .8rem; }
.home-events table { table-layout: fixed; }
.home-events th, .home-events td { padding: .4rem .6rem; font-size: .82rem; }
.home-events th { font-size: .66rem; }
.home-events tbody tr:hover { background: rgb(255 255 255 / 3%); }
.home-events td a { color: var(--blue); font-weight: 700; text-decoration: none; }
.home-events tbody tr:hover td a, .home-events td a:hover { text-decoration: underline; }
.home-events .home-cell-deck { overflow: hidden; font-weight: 700; text-overflow: ellipsis; white-space: nowrap; }
.home-events .home-cell-unnamed { color: var(--quiet); font-weight: 650; }
.home-events .home-cell-who { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* The row reads as two groups: what the event was, then who won it. One hairline marks the break
   and nothing else says it. */
.home-events .home-cell-break { padding-left: .9rem; border-left: 1px solid var(--line); }
.home-events col.home-col-date { width: 5.5rem; }
.home-events col.home-col-event { width: 11rem; }
.home-events col.home-col-num { width: 5rem; }
.home-events col.home-col-who { width: 11rem; }
.home-events col.home-col-record { width: 5rem; }

@media screen and (max-width: 46rem) {
  .home-scout { grid-template-columns: minmax(0, 1fr); gap: 1.4rem; }
  /* Three cells with a readable minimum need 504px and the phone has 328, so a proportional strip
     either clips the third deck or hides its name. Sideways the widths are the picture; stacked
     they cannot be, so the band becomes three full-width crops and the printed share carries the
     size on its own. */
  .home-strip { flex-direction: column; height: auto; }
  .home-crop { flex: 0 0 auto; min-width: 0; height: 4.6rem; }
  .home-crop + .home-crop { border-top: 2px solid var(--bg); border-left: 0; }
  .home-crop-tail { flex-basis: auto; height: auto; padding: .7rem; }
  /* Seven columns cannot be seven columns on a 328px phone, and the winning deck is the point of
     the row, so it must not sit behind a sideways drag. The table collapses instead: same markup,
     same cells, same order, wrapped onto three lines. Nothing is dropped and nothing scrolls. */
  .home-events table { display: block; min-width: 0; table-layout: auto; }
  .home-events colgroup, .home-events thead { display: none; }
  .home-events tbody { display: block; }
  .home-events tr { display: flex; flex-wrap: wrap; align-items: baseline; column-gap: .3rem; padding: .55rem 0; border-bottom: 1px solid var(--line); }
  .home-events tr:last-child { border-bottom: 0; }
  .home-events td { display: inline-block; padding: 0; font-size: .8rem; text-align: left; border: 0; }
  .home-events td.num { text-align: left; }
  .home-events .home-cell-date, .home-events .home-cell-event, .home-events .home-cell-players, .home-events .home-cell-lists { color: var(--quiet); font-size: .76rem; }
  .home-events .home-cell-date::after, .home-events .home-cell-event::after { content: " ·"; }
  .home-events .home-cell-players::after { content: " players ·"; }
  .home-events .home-cell-lists::after { content: " lists"; }
  .home-events .home-cell-deck { flex: 0 0 100%; margin-top: .2rem; overflow: visible; font-size: .92rem; white-space: normal; }
  .home-events .home-cell-break { padding-left: 0; border-left: 0; }
  /* The comma rides on the handle, so the flex gap falls after it and not before. */
  .home-events .home-cell-who { overflow: visible; white-space: normal; }
  .home-events .home-cell-who::after { content: ","; }
}

/* The tournament page's "Recent <format> events" section (moreevents ticket 02) reuses the
   homepage band's head and table as they are. Only the heading differs: it is the page's own
   `h2.section-head`, whose stand-alone margins would push the link out off its baseline inside the
   flex head, so the section carries the spacing instead: the 2.75rem the heading's own top margin
   gives every other section here. */
.recent-format-events { margin-top: 2.75rem; }
.recent-format-events .section-head { margin: 0; }

/* ==========================================================================
   REDESIGN TICKET 12 — the player page, A2 (efforts/redesign/issues/12-build-player.md)
   The first screen answers one question: what will this player bring, and how sure can I be.
   The call is the hero, the run strip is the page's second object, and four numbers close the
   window section. Everything else is a second read.

   Confidence borrows the site's certainty pair (`--sure` / `--unsure`, declared at `:root`)
   rather than inventing a third colour. Pale means the field has settled this slot and violet
   means the pilot is still choosing; here it is the same claim about a person — pale means this
   player has settled on a deck, violet means they are still choosing one.
   ========================================================================== */

.player-page { padding-block: 1.2rem 5rem; }
.player-page h1 { max-width: 24ch; margin: 0; font-size: clamp(1.9rem, 5vw, 3.2rem); font-weight: 850; line-height: 1; letter-spacing: -.04em; }
.player-facts { margin: .7rem 0 0; color: var(--muted); font-size: .92rem; }

/* The format rail as a row of chips under the name, ordered by how much of the window each
   format holds. A format with nothing in it stays, dimmed, because its absence is also an
   answer. */
.player-rail { display: flex; flex-wrap: wrap; gap: .35rem; margin-top: 1rem; }
.player-rail a { padding: .3rem .6rem; color: var(--muted); font-size: .8rem; font-weight: 650; text-decoration: none; background: var(--panel); border: 1px solid var(--line); border-radius: 99rem; }
.player-rail a:hover { color: var(--text); border-color: var(--quiet); }
.player-rail a.on { color: #17140c; background: var(--gold); border-color: var(--gold); }
.player-rail a.zero { color: #5a6070; background: none; }
.player-rail a b { font-weight: 800; font-variant-numeric: tabular-nums; }
.player-rail a small { margin-left: .3rem; font-size: .82em; opacity: .8; }

/* ---------- the hero: the call ----------
   The answer is at the size of an answer: the deck's art, the deck name over it, and the band
   chip. `Not enough` changes the picture, not just the chip: the art shortens and drains and
   the name comes down a size, because a player with one list was getting the same 17rem of art
   as a player with thirty-three. */
.player-hero { position: relative; width: min(100% - 2rem, 70rem); margin: 1.4rem auto 0; }
.player-hero-frame { position: relative; overflow: hidden; border-radius: .5rem;
  -webkit-mask-image: linear-gradient(90deg, #0000 0, #000 min(3rem, 8%), #000 calc(100% - min(3rem, 8%)), #0000 100%);
  mask-image: linear-gradient(90deg, #0000 0, #000 min(3rem, 8%), #000 calc(100% - min(3rem, 8%)), #0000 100%); }
.player-hero-art { display: block; width: 100%; height: clamp(11rem, 21vw, 17rem); object-fit: cover; object-position: center 30%; }
.player-hero-art-blank { display: block; width: 100%; height: clamp(11rem, 21vw, 17rem); background: repeating-linear-gradient(135deg, #171b23 0 8px, #1e232e 8px 16px); }
.player-hero-scrim { position: absolute; inset: 0; background: linear-gradient(180deg, #111319cc 0, #11131959 26%, #111319d6 70%, var(--bg) 100%), linear-gradient(90deg, #111319d1 0, #11131933 55%, #11131900 100%); }
.player-hero-body { position: absolute; inset: auto 0 0; padding: 0 1.2rem 1.1rem; }
.player-hero-credit { position: absolute; top: .7rem; right: 1rem; margin: 0; color: #ffffff85; font-size: .66rem; }
.player-hero[data-band="none"] .player-hero-art,
.player-hero[data-band="none"] .player-hero-art-blank { height: clamp(7rem, 13vw, 10.5rem); filter: grayscale(.55); }
.player-hero[data-band="none"] .player-call-name { font-size: clamp(1.6rem, 4vw, 2.6rem); }
.player-hero[data-band="none"] .player-call-name .color-pip { width: clamp(1.1rem, 2.2vw, 1.5rem); height: clamp(1.1rem, 2.2vw, 1.5rem); }

/* The mixed treatment: four crops in one frame instead of one, because a single card face
   under the words "something different" names a deck the headline has refused to name. */
span.player-mosaic { display: flex; gap: 2px; overflow: hidden; }
span.player-mosaic img { flex: 1 1 0; min-width: 0; height: 100%; object-fit: cover; }

.player-call-eyebrow { margin: 0 0 .35rem; color: var(--muted); font-size: .68rem; font-weight: 800; letter-spacing: .14em; text-transform: uppercase; }
.player-call-name { display: flex; flex-wrap: wrap; align-items: center; gap: .4rem .7rem; margin: 0; font-weight: 850; line-height: .98; letter-spacing: -.04em; }
.player-call-name .color-identity { min-height: 0; gap: .2rem; }
.player-call-name .color-pip { width: clamp(1.3rem, 3vw, 2.1rem); height: clamp(1.3rem, 3vw, 2.1rem); }
.player-call-name .color-identity img { filter: drop-shadow(0 2px 6px #0009); }
.player-call-name.is-small { font-size: 1.4rem; }
.player-call-why { max-width: 46ch; margin: .6rem 0 0; color: var(--muted); font-size: .95rem; }
.player-call-why b { color: var(--text); font-weight: 700; }
.player-call-alt { margin: .45rem 0 0; color: var(--quiet); font-size: .84rem; }
.player-call-alt b { color: var(--muted); font-weight: 650; }
.player-hero-body .player-call-why { max-width: 52ch; text-shadow: 0 1px 6px #000a; }

/* The band chip: one word for how far the call can be trusted, in the ink the run itself uses. */
.player-band { display: inline-block; padding: .18rem .48rem; color: #10131b; font-size: .62rem; font-weight: 800; letter-spacing: .1em; text-transform: uppercase; white-space: nowrap; background: var(--sure); border-radius: .25rem; }
.player-band.unsure { background: var(--unsure); }
.player-band.none { color: var(--quiet); background: none; box-shadow: inset 0 0 0 1px var(--line); }

/* The caveat mark on a deck name: `*` for a classifier guess, `†` for a source-reported
   label. One mark, never a parenthesis repeated in every row (ticket 09's decision). */
.player-mark { padding-left: .12rem; color: var(--gold); font-size: .8em; font-weight: 800; }

/* The last list, on the first screen. The hero names the deck; this names the event it came
   from and opens it. It is a bar rather than a link in body copy because "see the list" is the
   second thing every visitor wants. */
.player-last { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: .6rem 1.2rem; width: min(100% - 2rem, 70rem); margin: .9rem auto 0; padding: .7rem .8rem .7rem 1rem; background: var(--panel); border: 1px solid var(--line); border-radius: .5rem; }
.player-last-what { display: flex; flex-wrap: wrap; align-items: baseline; gap: .25rem .7rem; min-width: 0; }
.player-last-what > b { display: flex; align-items: center; gap: .35rem; font-size: 1rem; font-weight: 780; }
.player-last-eyebrow { color: var(--muted); font-size: .66rem; font-weight: 800; letter-spacing: .14em; text-transform: uppercase; }
.player-last-where { color: var(--quiet); font-size: .84rem; }
.player-last-open { padding: .45rem .85rem; color: #17140c; font-size: .82rem; font-weight: 800; text-decoration: none; background: var(--gold); border-radius: .35rem; }
.player-last-open:hover { filter: brightness(1.1); }
.player-last-open:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }

/* ---------- the window: three months, drawn as frames ----------
   The heading names the axis, and the strip under it is the page's second object: one frame
   per run, so the width of a frame is how long they stayed on that deck and every edge in the
   row is a day they changed. Newest first, so the left edge is always now. */
.player-run-h { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: .3rem .8rem; margin: 0 0 .5rem; color: var(--muted); font-size: .72rem; font-weight: 800; letter-spacing: .16em; text-transform: uppercase; }
.player-run-h em { color: var(--quiet); font-weight: 600; font-style: normal; letter-spacing: 0; text-transform: none; }
.player-window { margin-top: 1.6rem; }

.player-frames { display: flex; gap: 2px; height: clamp(8.5rem, 16vw, 12rem); margin: 0; padding: 0; overflow: hidden; list-style: none; border-radius: .35rem; }
.player-frame { position: relative; display: flex; flex: var(--frame-flex, 1) 1 0; gap: 1px; min-width: 0; background: var(--panel-strong); }
.player-art { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: .82; transition: opacity .15s; }
.player-frame:hover .player-art { opacity: 1; }
/* Dark at both ends: the top holds the result marks, the bottom holds the deck name. */
.player-scrim { position: absolute; inset: 0; background: linear-gradient(180deg, #111319c4 0, #11131926 30%, #11131933 52%, #111319e0 100%); }
.player-frame.noart { background: var(--panel-strong); box-shadow: inset 0 0 0 1px #ffffff12; }
.player-frame.gap { background: repeating-linear-gradient(135deg, #22283400 0 5px, #1b202b 5px 10px), var(--panel-strong); }
/* The current run, in the gold the tournament page gives the champion. A pseudo-element rather
   than a shadow on the frame, because the art is absolutely positioned and paints over both. */
.player-frame.now { z-index: 2; }
.player-frame.now::after { position: absolute; z-index: 3; inset: 0; box-shadow: inset 0 0 0 1px var(--gold), inset 0 -3px var(--gold); content: ""; pointer-events: none; }

/* One slice per event, and every slice is a link into its list. */
.player-seg { position: relative; z-index: 1; flex: 1 1 0; min-width: 0; display: block; border-right: 1px solid #11131959; text-decoration: none; }
.player-seg:last-child { border-right: 0; }
.player-seg.blank { flex: .3 1 0; background: #0d1017cc; }
/* A slice in a gap is not a link, because there is no list under it. It keeps the hatch of the
   frame instead of the dark notch, and still answers the pointer. */
.player-seg.dead { background: transparent; }
.player-seg:hover { background: #ffffff2b; }
.player-seg.dead:hover { background: #ffffff14; }
.player-seg:focus-visible { z-index: 4; outline: 2px solid var(--blue); outline-offset: -2px; }
.player-frames:focus-visible { outline: 3px solid var(--blue); outline-offset: 3px; }
/* The strip is one tab stop, so arrow keys move a virtual focus the browser cannot draw. The
   active slice carries the same ring a real focus would, but only while the strip holds the
   keyboard, so a pointer reader never sees a stale mark. */
.player-frames:focus-visible [data-deck-rover-active] { z-index: 4; outline: 2px solid var(--blue); outline-offset: -2px; }
/* The slice whose list is open in the pane, marked pale rather than gold: gold is already
   saying "this is the deck they are on now", and two claims in one colour is one claim nobody
   can read. */
.player-seg.is-picked { background: #ffffff1c; box-shadow: inset 0 0 0 1px #ffffff8a; }

/* The result marks, on the rail along the top. Only three finishes get one, because a mark on
   every event is a mark on nothing. */
.player-mark-rail { position: absolute; top: .4rem; left: 50%; width: 7px; height: 7px; margin-left: -3.5px; }
.player-mark-rail.won { background: var(--gold); box-shadow: 0 0 4px #e0b45899; transform: rotate(45deg); }
.player-mark-rail.t8 { background: #11131959; border: 1.5px solid var(--gold); border-radius: 50%; }
.player-mark-rail.t16 { top: .55rem; width: 4px; height: 4px; margin-left: -2px; background: #ccd4e8b8; border-radius: 50%; }
.player-mark-rail.clean { top: .58rem; width: 10px; height: 3px; margin-left: -5px; background: var(--gold); border-radius: 1px; }

.player-label { position: absolute; z-index: 2; inset: auto .35rem .35rem .45rem; overflow: hidden; color: var(--text); text-shadow: 0 1px 4px #000d; pointer-events: none; }
.player-label b { display: block; overflow: hidden; font-size: .86rem; font-weight: 780; line-height: 1.2; text-overflow: ellipsis; white-space: nowrap; }
.player-label span { display: block; overflow: hidden; color: #c8cfdf; font-size: .7rem; font-variant-numeric: tabular-nums; text-overflow: ellipsis; white-space: nowrap; }
.player-frame.narrow .player-label { display: none; }
.player-frame.now .player-label { display: block; }
.player-frame.now.narrow .player-label span { display: none; }

/* A strip of one event is not a strip: below eight events the frames stop stretching and keep
   a fixed width, so one event reads as one event instead of as a banner. */
.player-frames.sparse { justify-content: flex-start; }
.player-frames.sparse .player-frame { flex: 0 0 auto; }
.player-frames.sparse .player-seg { flex: 0 0 9rem; }
.player-frames.sparse .player-seg.blank { flex: 0 0 2.6rem; }

.run-scale { display: flex; margin-top: .3rem; color: var(--quiet); font-size: .7rem; }
.run-scale span { flex: 1 1 0; padding-top: .25rem; border-top: 1px solid var(--line); }
.run-scale span + span { margin-left: 2px; }
.run-scale .run-scale-end { text-align: right; }

/* The readout line, kept on its hint: ticket 20 fills it on hover or focus. It has a fixed
   height so nothing moves when it fills. */
.player-read { height: 2.5rem; margin: .5rem 0 0; overflow: hidden; color: var(--muted); font-size: .82rem; line-height: 1.25rem; }
.player-read .hint { color: var(--quiet); }

.run-key { display: flex; flex-wrap: wrap; gap: .2rem 1.4rem; margin: .5rem 0 0; color: var(--quiet); font-size: .76rem; }
.run-key i { display: inline-block; width: .7rem; height: .7rem; margin-right: .3rem; vertical-align: -1px; border-radius: 2px; }
.run-key i.gold { background: var(--gold); }
.run-key i.notch { background: #0d1017; box-shadow: inset 0 0 0 1px var(--line); }
.run-key i.hatch { background: repeating-linear-gradient(135deg, #22283400 0 5px, #1b202b 5px 10px), var(--panel-strong); }
.run-key i.won { background: var(--gold); border-radius: 1px; transform: rotate(45deg) scale(.8); }
.run-key i.t8 { background: none; border: 1.5px solid var(--gold); border-radius: 50%; }
.run-key i.t16 { width: .4rem; height: .4rem; margin-right: .45rem; margin-left: .15rem; background: #ccd4e8b8; border-radius: 50%; }
.run-key i.clean { height: .25rem; margin-bottom: .2rem; background: var(--gold); border-radius: 1px; }

/* The four numbers close the same block the strip opens: the strip says what they play, these
   say how it goes. The dormant rating vital carries a dashed tag and a muted value. */
.player-window .page-vitals { margin-top: 1.2rem; }
.page-vital.is-muted > b { color: var(--quiet); }
.page-vital-tag { display: inline-block; margin-left: .4rem; padding: .1rem .3rem; color: var(--quiet); font-size: .58rem; font-weight: 800; letter-spacing: .1em; text-transform: uppercase; vertical-align: .18em; border: 1px dashed var(--line); border-radius: .25rem; }

/* ---------- head to head ----------
   Four states, all drawn. The change/forget control is one line of small text, not two gold
   buttons: changing a remembered handle is a rare, quiet action. */
.h2h-record { display: flex; flex-wrap: wrap; align-items: baseline; gap: .4rem .9rem; }
.h2h-score { font-size: clamp(2rem, 5vw, 3.4rem); font-weight: 850; font-variant-numeric: tabular-nums; letter-spacing: -.045em; line-height: 1; }
.h2h-score .ahead { color: var(--gold); }
.h2h-score .behind { color: var(--blue); }
.h2h-verdict { color: var(--muted); font-size: .95rem; }
.h2h-strip { display: flex; flex-wrap: wrap; gap: 3px; margin-top: .8rem; }
.h2h-pip { display: grid; place-items: center; width: 1.5rem; height: 1.5rem; color: #10131b; font-size: .7rem; font-weight: 800; background: var(--blue); border-radius: .25rem; }
.h2h-pip.w { background: var(--gold); }
.h2h-pip.d { color: var(--muted); background: var(--panel-strong); }
.h2h-list { margin: .8rem 0 0; padding: 0; list-style: none; }
.h2h-list li { display: grid; grid-template-columns: 2.6rem minmax(0, 1fr) auto; gap: .2rem .7rem; align-items: baseline; padding: .3rem .1rem; border-bottom: 1px solid var(--line); font-size: .86rem; }
.h2h-list b { color: var(--gold); font-variant-numeric: tabular-nums; }
.h2h-list b.l { color: var(--blue); }
.h2h-list span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.h2h-list em { color: var(--quiet); font-size: .82rem; font-style: normal; }
.h2h-form { display: flex; flex-wrap: wrap; gap: .5rem; align-items: center; margin-top: .8rem; }
.h2h-form input { flex: 1 1 12rem; padding: .55rem .7rem; font-size: .9rem; }
.h2h-form button { padding: .55rem .9rem; font-size: .9rem; }
.h2h-note { max-width: 52ch; margin: .6rem 0 0; color: var(--quiet); font-size: .8rem; }
.h2h-empty { padding: 1rem; color: var(--muted); font-size: .9rem; background: var(--panel); border: 1px dashed var(--line); border-radius: .6rem; }
.h2h-empty p { margin: 0; }
.h2h-swap { display: flex; flex-wrap: wrap; gap: .5rem; align-items: center; margin: .7rem 0 0; color: var(--quiet); font-size: .8rem; }
.h2h-swap input { flex: 0 1 11rem; padding: .3rem .5rem; font-size: .82rem; }
.h2h-swap b { color: var(--muted); font-weight: 650; }
.linkish { padding: 0; color: var(--blue); font-size: inherit; font-weight: 600; background: none; border: 0; text-decoration: underline; cursor: pointer; }
.linkish:hover { color: var(--text); }

/* ---------- their lists: the picker and the pane ----------
   Every published list as a row beside one open list in a floating pane. The pane floats with
   the picker for the same reason the tournament page's does. */
/* The second track only exists once the pane does. Without scripting the pane is hidden and
   the picker takes the whole row, the way the tournament page's layout does. */
.player-split { margin-top: .4rem; }
.js-deck-pane .player-split { display: grid; grid-template-columns: minmax(0, .82fr) minmax(0, 1.18fr); gap: 1.2rem 2rem; align-items: start; }
.player-picker { border-top: 1px solid var(--line); }
/* The one row that does not baseline its own tracks: its date and chevron are single-line and its
   middle track baselines its own contents, so it keeps the stretch ticket 36 approved. */
.player-picker > .deck-list-row { grid-template-columns: 4.6rem minmax(0, 1fr) 1.1rem; gap: .1rem .7rem; align-items: normal; width: 100%; padding: .42rem .45rem; border-bottom: 1px solid var(--line); }
.player-picker > .deck-list-row.is-picked { box-shadow: inset 3px 0 #ccd4e8; }
.player-picker > .deck-list-row.is-picked .player-pick-date, .player-picker > .deck-list-row.is-picked .player-pick-place { color: var(--muted); }
.player-pick-date { color: var(--quiet); font-size: .82rem; font-variant-numeric: tabular-nums; white-space: nowrap; }
.player-pick-main { display: flex; flex-wrap: wrap; align-items: baseline; gap: .1rem .55rem; min-width: 0; }
.player-pick-arch { overflow: hidden; font-weight: 650; text-overflow: ellipsis; white-space: nowrap; }
.player-pick-place { color: var(--muted); font-size: .84rem; font-variant-numeric: tabular-nums; }
.player-pick-chev { color: var(--quiet); font-size: .7rem; text-align: right; }
.player-picker > .deck-list-row.is-picked .player-pick-chev { color: #ccd4e8; }
.player-key { display: flex; flex-wrap: wrap; gap: .2rem 1.4rem; margin: .5rem 0 0; color: var(--quiet); font-size: .76rem; }
.player-key b { color: var(--gold); font-weight: 800; }
.player-split > div > .deck-list-source { margin-top: .5rem; color: var(--muted); }
.player-split > div > .deck-list-source > summary { cursor: pointer; }
.player-split .deck-list-pane { min-width: 0; }
.js-deck-pane .player-split .deck-list-pane { position: sticky; top: 1rem; max-height: calc(100dvh - 2rem); overflow-y: auto; overscroll-behavior: contain; scrollbar-gutter: stable; scrollbar-width: thin; }
.player-split .deck-pane-head b { font-weight: 800; }

/* ---------- best finishes ----------
   The prototype's plain pills: `2nd`, `5–0`, `4–0`, gold only for a win. */
.player-finishes { display: grid; grid-template-columns: repeat(auto-fill, minmax(20rem, 1fr)); gap: .1rem 1.4rem; margin: 0; padding: 0; list-style: none; }
.player-finishes li { display: grid; grid-template-columns: 3.2rem minmax(0, 1fr); gap: .2rem .7rem; align-items: baseline; padding: .34rem .1rem; border-bottom: 1px solid var(--line); }
.player-finish-pill { color: var(--muted); font-size: .82rem; font-weight: 800; font-variant-numeric: tabular-nums; }
.player-finish-pill.win { color: var(--gold); }
.player-finish-event { min-width: 0; overflow: hidden; font-size: .88rem; text-overflow: ellipsis; white-space: nowrap; }
.player-finish-event em { color: var(--quiet); font-size: .8rem; font-style: normal; }

@media screen and (max-width: 62rem) {
  .js-deck-pane .player-split { grid-template-columns: minmax(0, 1fr); }
  .js-deck-pane .player-split .deck-list-pane { position: static; max-height: none; overflow: visible; }
}

@media screen and (max-width: 46rem) {
  .page-vital { flex-basis: 45%; }
  .page-vital + .page-vital { padding-left: 0; border-left: 0; }
  .page-vitals { gap: 0 1.2rem; }
  /* The strip keeps its shape and scrolls sideways rather than stacking: stacked, the one
     thing it is for becomes a list of 72 rows. */
  .run-scroll { overflow-x: auto; padding-bottom: .4rem; }
  .run-scroll .player-frames, .run-scroll .run-scale { min-width: 30rem; }
  /* The place line holds two lines of the wide layout's readout, which is three of this one.
     The height stays fixed so nothing moves; a third line is what stops the place and the
     record, the end of every readout, being cut off. */
  .player-read { height: 3.75rem; }
  .player-picker > .deck-list-row { grid-template-columns: 4.2rem minmax(0, 1fr) 1rem; }
  .player-finishes { grid-template-columns: minmax(0, 1fr); }
  /* The hero body is anchored to the bottom of the frame, so at 375px its copy climbs out of
     the top of the art and lands on the credit. The art grows to hold it and the credit goes:
     a caption naming the card a crop came from is the first thing a 375px screen can spare. */
  .player-hero-art, .player-hero-art-blank { height: 16rem; }
  .player-hero[data-band="none"] .player-hero-art,
  .player-hero[data-band="none"] .player-hero-art-blank { height: 11rem; }
  .player-hero-credit { display: none; }
}

/* ---- decksearchbuild ticket 03: the /deck-search sentence form ----------------------------
   Variant C: the query reads as prose, so every control sits inline on a line of text and the
   line-height, not a grid, is what spaces them. The inputs are underlines rather than boxes for
   the same reason — a boxed field in the middle of a sentence reads as a form, not a sentence. */
.deck-search-form { max-width: 52rem; margin-top: 1.75rem; font-size: 1.2rem; line-height: 2.4; }
.deck-search-line { margin: 0; color: var(--muted); }
.deck-search-form select { padding: .25rem .4rem; font-size: 1rem; font-weight: 650; background: var(--panel-strong); border-radius: .45rem; }
.deck-search-form [data-deck-search-noun], .deck-search-lead { color: var(--muted); }
/* The slot is inline-block so the suggestion panel has a positioned box its own width, and the
   panel is given a floor of its own: eight card names do not read at input width. It carries its
   own `position: relative` rather than borrowing `.player-search-input`, whose `width: 100%` on
   the field would override the `size` the sentence depends on. */
.deck-search-slot { position: relative; display: inline-block; max-width: 100%; vertical-align: baseline; }
/* The width comes from the input's own `size`, which the handler sets from what the slot holds
   and the script refits as it is typed into. A fixed width here would push the board select onto
   a line of its own at desktop and stop the sentence reading as one. */
.deck-search-slot input { max-width: 100%; padding: .25rem .2rem; color: var(--text); font-size: 1rem; font-weight: 650; background: transparent; border: 0; border-bottom: 2px solid var(--line); border-radius: 0; }
/* The site-wide focus ring stays: the underline colour alone is far too faint a cue to find
   the focused slot by. */
.deck-search-slot input:focus { border-bottom-color: #4c5a75; }
.deck-search-slot input.deck-search-card-bad { border-bottom-color: #b3564d; }
.deck-search-slot .player-search-results { width: max(100%, 24rem); }
/* The rows are buttons, not links: picking one fills the field it belongs to. They take the
   panel row's shape from the link rule above rather than restating the palette. */
.player-suggestions button { display: flex; width: 100%; align-items: center; gap: .55rem; padding: .4rem .8rem; color: var(--text); font-size: .88rem; font-weight: 400; text-align: left; background: none; border: 0; border-radius: 0; }
/* One line per row, whatever the card is called: `General Kreat, the Boltbringer` wrapped to
   three lines and pushed its type line off the panel. The cost and type line give way first —
   they are context, and the name is what the reader is picking by — so the name holds its width
   up to most of the row and only truncates past that. */
.player-suggestions button span { flex: 0 0 auto; max-width: 62%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.player-suggestions button i { min-width: 0; margin-left: auto; overflow: hidden; color: var(--quiet); font-style: normal; font-size: .76rem; text-overflow: ellipsis; white-space: nowrap; }
.player-suggestions button:hover, .player-suggestions button:focus { color: #18150d; background: var(--gold); }
/* Hover and keyboard focus land on the same gold, so focus needs a mark of its own: the panel is
   walked with the arrow keys and the highlight alone cannot say the keyboard is what moved. The
   ring is the row's own text colour, drawn inside the row so the gold still reaches its edges. */
.player-suggestions button:focus { outline: 2px solid #18150d; outline-offset: -2px; }
.player-suggestions button:hover i, .player-suggestions button:focus i { color: #3a3018; }
.deck-search-note { color: #d0796f; font-size: .85rem; }
.deck-search-add, .deck-search-remove { font-size: .95rem; text-decoration: none; }
.deck-search-add { color: var(--gold); }
.deck-search-remove { padding: 0 .3rem; color: var(--quiet); }
.deck-search-add:hover { text-decoration: underline; }
.deck-search-remove:hover { color: var(--text); }
.deck-search-add-line { line-height: 2; }
.deck-search-scope { margin-top: .5rem; }
/* The select and the full stop that closes the sentence, welded: a narrow screen otherwise left
   the stop stranded on a line of its own. */
.deck-search-stop { white-space: nowrap; }
/* Sized to the selects it follows, not to the page's primary-action button: it reads as the end
   of the sentence, so a full-size slab beside a 1rem select was the wrong weight. Its own class,
   not `.deck-search-form button`: the typeahead panel's rows are buttons inside this same form. */
.deck-search-submit { margin-left: .55rem; padding: .3rem .85rem; font-size: 1rem; border-radius: .45rem; }

/* ---- decksearchbuild ticket 04: the grouped results and the pinned pane -------------------
   The layout itself is the archetype list viewer's (`.archetype-list-layout`, `.deck-list-pane`),
   so nothing here restates the grid. What is new is the group: a head that draws the group's
   share of the answer, three rows, and a native disclosure holding the rest. */
.deck-search-results { margin-top: 2rem; }
.deck-search-headline { margin: 0; color: var(--text); font-size: 1.25rem; font-weight: 750; }
.deck-search-valve { margin: .3rem 0 0; color: var(--quiet); font-size: .85rem; }
.deck-search-groups { max-height: 50rem; margin: 0; padding: 0; overflow-y: auto; scrollbar-gutter: stable; scrollbar-width: thin; list-style: none; }
.deck-search-group { margin-top: .9rem; }
.deck-search-group:first-child { margin-top: 0; }
/* The head is a two-line grid: the name and the count on the first line, the bar spanning the
   second. A bar under the name reads as belonging to it; beside it, it competes with the pips. */
.deck-search-group-head { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: .15rem .6rem; padding: .35rem .5rem .3rem; border-bottom: 1px solid var(--line); }
/* Pips first, then the name: `.color-identity` is a flex box, so a name printed before it lost
   its own line and the caveat mark landed on a third. These three carry the pips, so all three
   are inline-flex and the ellipsis moves onto the name span inside them. */
.deck-search-group-name,
.deck-search-row-archetype,
.deck-search-pane-archetype { display: inline-flex; align-items: baseline; gap: .3rem; min-width: 0; }
.deck-search-label-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.deck-search-group-name { color: var(--text); font-size: .9rem; font-weight: 750; }
/* The group head is not a `.deck-list-row`, so it misses that rule's pip size and drew the full
   1.65rem beside a .9rem name. Same size as the rows below it. */
.deck-search-group-name .color-identity { min-height: 0; gap: .18rem; align-self: center; }
.deck-search-group-name .color-pip { width: .95rem; height: .95rem; }
/* Never wrapped: a two-line date pushed the head's first line to two rows while the name beside
   it still had ellipsis left to give. The name absorbs the squeeze instead. */
.deck-search-group-date { color: var(--quiet); font-size: .78rem; font-weight: 400; white-space: nowrap; }
.deck-search-group-count { color: var(--muted); font-size: .78rem; white-space: nowrap; }
.deck-search-group-share { grid-column: 2; color: var(--muted); font-size: .74rem; font-variant-numeric: tabular-nums; text-align: right; }
/* Gold, because the bar answers "how much of this answer is this group" and gold is the site's
   mark for the reader's own subject. The width is the one geometry the request computes, so it
   arrives as a custom property in the nonced style element. */
.deck-search-share { position: relative; grid-column: 1; align-self: center; height: .4rem; background: #22262f; border-radius: 99rem; }
.deck-search-share-fill { position: absolute; inset: 0 auto 0 0; width: var(--share-width, 0%); background: var(--gold); border-radius: 99rem; }
.deck-search-row { grid-template-columns: 2.7rem minmax(0, 1fr); gap: .2rem .55rem; padding: .42rem .5rem; border-bottom: 1px solid var(--line); }
.deck-search-row.is-picked { box-shadow: inset 3px 0 #ccd4e8; }
.deck-search-row-main { display: grid; min-width: 0; }
/* Each grouping leads with whichever of the pair its head did not say, and the other reads quiet
   beneath it: archetype over player under the event grouping, player over event under the
   archetype grouping. Both leads take the row's own weight. */
.deck-search-row-archetype,
.deck-search-row-lead { overflow: hidden; color: var(--text); font-size: .84rem; font-weight: 650; text-overflow: ellipsis; white-space: nowrap; }
.deck-search-row-who { overflow: hidden; color: var(--muted); font-size: .8rem; text-overflow: ellipsis; white-space: nowrap; }
.deck-search-more > summary { padding: .4rem .5rem; color: var(--blue); font-size: .82rem; cursor: pointer; }
/* The pane head gains one line the archetype page has no need for: the archetype, which a
   cross-format result set cannot assume the reader already knows. */
.deck-search-pane-archetype { color: var(--muted); font-size: .86rem; font-weight: 650; }
.deck-search-open { color: var(--gold); font-size: .8rem; text-decoration: none; }
.deck-search-open:hover { text-decoration: underline; }
/* The searched cards, gold inside the body. This is the only place the pane says which cards the
   search was about, so it has to read at a glance without moving the row off its baseline. */
.card-name.is-searched { color: var(--gold); font-weight: 700; }

/* The shared layout drops to one column here, rows first and pane below. This block follows the
   rules above it on purpose: a media query earlier in the file would lose to them. */
@media screen and (max-width: 62rem) {
  .deck-search-groups { max-height: none; overflow-y: visible; }
}

@media screen and (max-width: 46rem) {
  /* At 375px the sentence has to wrap inside the measure rather than push past it, so the slot
     gives up its fixed width and the panel drops its floor. Both are what keep the page from
     scrolling sideways. */
  .deck-search-form { font-size: 1.05rem; line-height: 2.2; }
  .deck-search-slot { display: block; }
  .deck-search-slot input { width: 100%; }
  .deck-search-slot .player-search-results { width: 100%; }
}
