/* SPDX-License-Identifier: AGPL-3.0-only WITH AdditionRef-Discopal-app-store-permission */
/* SPDX-FileCopyrightText: 2026 The Discopal contributors */

/* The public pages' stylesheet (ADR 0042 rules 5 and 8). Every value is a token of tokens.css (a var(), or 0,
   100%, 1): TestCSSHoldsNoValue holds it to that. The primitives (stack, row, text) take their
   token keys as class names; no page has a style attribute. */

* { box-sizing: border-box; margin: 0; }
body { background: var(--color-surface-page); color: var(--color-ink-default); font: var(--font-style-body-style) var(--font-style-body-weight) var(--font-style-body-size)/var(--font-style-body-line) var(--font-style-body-family); }
main, footer { max-width: var(--size-page-max); margin: 0 auto; padding: var(--space-alias-block-gap) var(--space-alias-gutter); }
a { color: var(--color-link); }
a:focus-visible { outline: var(--size-stroke-focus) solid var(--color-focus); outline-offset: var(--space-0-5); }

/* Primitives */
.stack { display: flex; flex-direction: column; }
.row { display: flex; flex-wrap: wrap; align-items: flex-end; }
.gap-2 { gap: var(--space-2); }
.gap-3 { gap: var(--space-3); }
.gap-4 { gap: var(--space-4); }
.gap-6 { gap: var(--space-6); }
.gap-8 { gap: var(--space-8); }
.color-caption { color: var(--color-caption); }
.font-title { font: var(--font-style-title-style) var(--font-style-title-weight) var(--font-style-title-size)/var(--font-style-title-line) var(--font-style-title-family); letter-spacing: var(--font-style-title-tracking); }
.font-artist { font: var(--font-style-artist-style) var(--font-style-artist-weight) var(--font-style-artist-size)/var(--font-style-artist-line) var(--font-style-artist-family); letter-spacing: var(--font-style-artist-tracking); }
.font-dek { font: var(--font-style-dek-style) var(--font-style-dek-weight) var(--font-style-dek-size)/var(--font-style-dek-line) var(--font-style-dek-family); letter-spacing: var(--font-style-dek-tracking); }
.font-wordmark { font: var(--font-style-wordmark-style) var(--font-style-wordmark-weight) var(--font-style-wordmark-size)/var(--font-style-wordmark-line) var(--font-style-wordmark-family); letter-spacing: var(--font-style-wordmark-tracking); }
.font-page-title { font: var(--font-style-page-title-style) var(--font-style-page-title-weight) var(--font-style-page-title-size)/var(--font-style-page-title-line) var(--font-style-page-title-family); letter-spacing: var(--font-style-page-title-tracking); }
.font-h2 { font: var(--font-style-h2-style) var(--font-style-h2-weight) var(--font-style-h2-size)/var(--font-style-h2-line) var(--font-style-h2-family); letter-spacing: var(--font-style-h2-tracking); }
.font-row { font: var(--font-style-row-style) var(--font-style-row-weight) var(--font-style-row-size)/var(--font-style-row-line) var(--font-style-row-family); letter-spacing: var(--font-style-row-tracking); }
.font-tile { font: var(--font-style-tile-style) var(--font-style-tile-weight) var(--font-style-tile-size)/var(--font-style-tile-line) var(--font-style-tile-family); letter-spacing: var(--font-style-tile-tracking); }
.font-meta { font: var(--font-style-meta-style) var(--font-style-meta-weight) var(--font-style-meta-size)/var(--font-style-meta-line) var(--font-style-meta-family); letter-spacing: var(--font-style-meta-tracking); }
.font-label { font: var(--font-style-label-style) var(--font-style-label-weight) var(--font-style-label-size)/var(--font-style-label-line) var(--font-style-label-family); letter-spacing: var(--font-style-label-tracking); }
.font-input { font: var(--font-style-input-style) var(--font-style-input-weight) var(--font-style-input-size)/var(--font-style-input-line) var(--font-style-input-family); letter-spacing: var(--font-style-input-tracking); }
.font-mood { font: var(--font-style-mood-style) var(--font-style-mood-weight) var(--font-style-mood-size)/var(--font-style-mood-line) var(--font-style-mood-family); letter-spacing: var(--font-style-mood-tracking); }
.font-small { font: var(--font-style-small-style) var(--font-style-small-weight) var(--font-style-small-size)/var(--font-style-small-line) var(--font-style-small-family); letter-spacing: var(--font-style-small-tracking); }
.font-mark { font: var(--font-style-mark-style) var(--font-style-mark-weight) var(--font-style-mark-size)/var(--font-style-mark-line) var(--font-style-mark-family); letter-spacing: var(--font-style-mark-tracking); }

/* The beta notice: running text with a lead-in, a quoted wording and lists. */
.strong { font-weight: var(--font-style-label-weight); }
blockquote { padding-left: var(--space-4); border-left: var(--size-stroke-rule) solid var(--color-line-rule); }
ul { padding-left: var(--space-6); }

/* Cover: the sleeve in a square slot, never cropped; the tone shows while it loads or when there is none. */
.cover { display: block; flex: none; aspect-ratio: 1; border-radius: var(--radius-cover); box-shadow: var(--elevation-cover); overflow: hidden; }
.cover img { display: block; width: 100%; height: 100%; object-fit: contain; }
.cover-hero { width: var(--size-cover-hero); }
.cover-thumb { width: var(--size-art-tile); border-radius: var(--radius-thumb); box-shadow: var(--elevation-thumb); }
.cover-tile { width: 100%; border-radius: var(--radius-thumb); box-shadow: var(--elevation-thumb); }
.tone-1 { background: var(--color-tone-1); }
.tone-2 { background: var(--color-tone-2); }
.tone-3 { background: var(--color-tone-3); }
.tone-4 { background: var(--color-tone-4); }
.tone-5 { background: var(--color-tone-5); }
.tone-6 { background: var(--color-tone-6); }
.tone-7 { background: var(--color-tone-7); }
.tone-8 { background: var(--color-tone-8); }

/* Track row: number, title, time. */
.track-list { list-style: none; padding: 0; border-top: var(--size-stroke-hair) solid var(--color-line-hair); }
.track-row { display: grid; grid-template-columns: var(--size-track-number) minmax(0, 1fr) auto; align-items: center; column-gap: var(--space-2); min-height: var(--size-track-row-min); padding: var(--space-alias-row-pad) 0; border-bottom: var(--size-stroke-hair) solid var(--color-line-hair); }
.track-row > :last-child { text-align: right; }

/* Album card: the Library tile's grid form; the whole card is the link, at least the tap size. */
.card-grid { display: grid; grid-template-columns: repeat(var(--count-library-columns), minmax(0, 1fr)); gap: var(--space-alias-tile-gap-y) var(--space-alias-tile-gap-x); }
.album-card { min-height: var(--size-tap); color: inherit; text-decoration: none; }
.album-card:focus-visible { outline: var(--size-stroke-focus) solid var(--color-focus); outline-offset: var(--space-0-5); }

/* Button: always round; filled accent, or outline on paper; the label wraps and is never cut. */
.button { min-height: var(--size-button); padding: var(--space-2) var(--space-5); border-radius: var(--radius-pill); border: var(--size-stroke-hair) solid var(--color-line-control); background: none; color: var(--color-ink-default); }
.button-accent { background: var(--color-accent-fill); border-color: var(--color-accent-fill); color: var(--color-accent-on-fill); }
.button-outline:hover, .button-outline:active { background: var(--color-surface-sunken); }
.button:focus-visible, .text-field-input:focus-visible { outline: var(--size-stroke-focus) solid var(--color-focus); outline-offset: var(--space-0-5); }
.button:disabled { background: var(--color-surface-sunken); border-color: var(--color-surface-sunken); color: var(--color-caption); }

/* Text field: labelled above; the box grows with its text. */
.text-field-input { min-height: var(--size-input); padding: var(--space-2) var(--space-3); border-radius: var(--radius-md); border: var(--size-stroke-hair) solid var(--color-line-control); background: var(--color-surface-raised); color: var(--color-ink-default); }

/* An item page (design/components.md: Site header, Hero public variant, Byline). The header and the hero are
   one band of the cover's field, full width; .wrap holds each part to the page's width. The sleeve is centred on a
   phone and left of the text on a desktop (the breakpoint is breakpoint.desktop-min-width, 700 px: a media query
   cannot read a token). The guest's byline and note are part of the hero, so they sit in it once the script opens
   them, and the page is whole without the script. */
.item main { max-width: 100%; padding: 0; gap: 0; }
.item main > :last-child { padding-bottom: var(--space-alias-section-gap); }
.wrap { width: 100%; max-width: var(--size-page-max); margin: 0 auto; padding: 0 var(--space-alias-gutter); }
.site-head, .hero { background: var(--field-field); color: var(--field-ink); }
.site-head a:focus-visible, .hero a:focus-visible { outline-color: var(--field-ink); }
.color-field-soft { color: var(--field-ink-soft); }
.head-row { display: flex; align-items: center; justify-content: space-between; gap: var(--space-4); min-height: var(--size-nav); }
.wordmark-tail { color: var(--field-accent); }
.sign-in-link { display: inline-flex; align-items: center; min-height: var(--size-tap); padding: 0 var(--space-4); border: var(--size-stroke-hair) solid var(--field-line); border-radius: var(--radius-pill); color: inherit; text-decoration: none; }
.hero a { color: inherit; text-decoration-color: var(--field-line); }
.hero .cover { box-shadow: var(--elevation-cover); }
.hero-grid { display: flex; flex-direction: column; align-items: center; gap: var(--space-6); padding-top: var(--space-alias-hero-top); padding-bottom: var(--space-alias-hero-bottom); text-align: center; }
.hero-text { align-items: center; min-width: 0; }
.guest { align-items: center; width: 100%; max-width: var(--size-measure-dek); }
.hero blockquote { padding: 0; border: 0; }
/* The guest's byline: the sender's face (their initial until the photo reaches the page), "A message from", and
   their note in quote marks (a q element) whose opening mark hangs in the margin on a desktop. Then the ink pill. */
.guest-from { display: flex; align-items: center; gap: var(--space-3); }
.face { display: inline-flex; align-items: center; justify-content: center; flex: none; width: var(--size-photo-l); height: var(--size-photo-l); border-radius: var(--radius-pill); background: var(--field-ink); color: var(--field-field); }
.ink-pill { display: inline-flex; align-items: center; justify-content: center; width: 100%; min-height: var(--size-button); padding: var(--space-2) var(--space-5); border-radius: var(--radius-pill); background: var(--field-ink); color: var(--field-field); text-decoration: none; }
.hero .ink-pill { color: var(--field-field); }
.hero .ink-pill:focus-visible { outline-color: var(--field-ink); }
.item-body { padding-top: var(--space-alias-section-gap); }
@media (min-width: 700px) {
  .hero-grid { display: grid; grid-template-columns: var(--size-cover-hero) minmax(0, 1fr); align-items: flex-start; column-gap: var(--space-16); text-align: inherit; }
  .hero-bare { grid-template-columns: minmax(0, 1fr); }
  .hero-text { align-items: flex-start; }
  .guest { align-items: flex-start; }
  .guest-note { text-indent: calc(var(--space-2) * -1); }
  .ink-pill, .link-button { align-self: flex-start; width: auto; }
}

/* The album page under the hero (design/reference/r2/share.html). The teaser and the join card's named lines wait
   until the guest script has shown who sent the link; the rest is always there. On a desktop the grid's three
   parts flow into two columns: the join card left, the teaser right, the Contents under the join card; with no
   teaser the Contents rise beside the card, so neither column is left with a hole. */
.listen { align-items: center; }
.field-chip { display: inline-flex; align-items: center; min-height: var(--size-tap); padding: 0 var(--space-4); border: var(--size-stroke-hair) solid var(--field-line); border-radius: var(--radius-pill); text-decoration: none; }
.share-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-alias-section-gap); align-items: flex-start; }
.rule-top { padding-top: var(--space-alias-head-rule-gap); border-top: var(--size-stroke-hair) solid var(--color-line-rule); }
.join-card { padding: var(--space-6); border: var(--size-stroke-hair) solid var(--color-line-hair); border-radius: var(--radius-xl); background: var(--color-surface-raised); }
.join-tail { color: var(--color-accent-text); }
.link-button { display: inline-flex; align-items: center; justify-content: center; text-decoration: none; }
.when-named { display: none; }
.item:has([data-role="from"]:not([hidden])) .when-named { display: flex; }
.teaser-tiles { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: var(--space-alias-tile-gap-x); }
.teaser-tile { display: flex; align-items: center; justify-content: center; aspect-ratio: 1; border-radius: var(--radius-thumb); box-shadow: var(--elevation-thumb); }
.teaser-disc { display: flex; align-items: center; justify-content: center; width: var(--size-icon-l); height: var(--size-icon-l); border: var(--size-stroke-hair) solid var(--color-line-control); border-radius: var(--radius-pill); }
.teaser-spindle { width: var(--space-1); height: var(--space-1); border-radius: var(--radius-pill); background: var(--color-line-control); }
.tint-1 { background: var(--color-tint-1); }
.tint-2 { background: var(--color-tint-2); }
.tint-3 { background: var(--color-tint-3); }
.tint-4 { background: var(--color-tint-4); }
.tint-5 { background: var(--color-tint-5); }
.tint-6 { background: var(--color-tint-6); }
.teaser-card { align-self: center; padding: var(--space-6); border-radius: var(--radius-xl); background: var(--color-surface-raised); box-shadow: var(--elevation-pop); text-align: center; }
.contents .track-row > :first-child { text-align: right; padding-right: var(--space-2); }
.colophon p { padding-top: var(--space-4); border-top: var(--size-stroke-bar) solid var(--color-line-rule); color: var(--color-caption); }
.colophon a { color: inherit; }
.colophon-mark { display: block; width: var(--space-3); height: var(--space-3); margin-top: var(--space-3); background: var(--color-accent-mark); }
@media (min-width: 700px) {
  .share-grid { grid-template-columns: var(--size-cover-hero) minmax(0, 1fr); column-gap: var(--space-16); }
}

/* The guest page's parts wait hidden until its script has something to show. */
[hidden] { display: none; }

/* An item's description (design/components.md, Description): at the dek's measure, the MACHINE mark a small
   capsule on the sunken ground beside the sound tag. */
.description { max-width: var(--size-measure-dek); }
.description .row { align-items: center; }
.machine { display: inline-flex; align-items: center; min-height: var(--size-mark); padding: 0 var(--space-1); border-radius: var(--radius-pill); background: var(--color-surface-sunken); color: var(--color-caption); }

/* A page of running text (design/components.md, Page with `measure`): its words no wider than the text measure. */
.measure { max-width: var(--size-measure-text); }
