/* ---- src/styles/fonts.css ---- */
/* Brunson: the display face for titles and menu items, Antony's pick (topic 5845 msg 7777) over POPO COPS 1, which
   stays in the logo only (7755). From DaFont, free for personal use; his call on the licence (7766). The body face is
   Mona Sans (open licence), the face B1 was drawn and approved in. */
@font-face { font-family: 'Brunson'; src: url(../assets/fonts/Brunson.woff2) format('woff2'); font-display: block; }
@font-face { font-family: 'Mona Sans'; src: url(../assets/fonts/MonaSans-normal-200-900.woff2) format('woff2'); font-weight: 200 900; font-display: swap; }

/* ---- src/styles/tokens.css ---- */
/* Every value the site uses. No other stylesheet may write a px size or a colour (tools/lint.js); they use these.
   The look is B1 (Antony, topic 5845: picked in msg 7660, the 15px capitals approved in msg 7671): black and white,
   the site's red on the shop's main actions, 15px small capitals, the badge at 88px on a phone and 104px from 720px.
   Gaps are measured to the ink: text boxes are trimmed to the top of the capitals and the baseline (base.css).
   Three widths change the layout. From 600px (a small tablet, a phone on its side) a tee's photo and About's photo sit
   beside their words and About's photos go three across, so no picture fills the width. From 720px (a tablet) the
   margins, names and badge grow, the grids widen, and a single's and a tool's picture sits beside its words too. From
   1024px (a laptop) the header shows the sections and picture and words take half each, the picture never wider
   than --art-w. Past 1440px (--page) the content keeps to the middle. */
:root {
  /* ---------------------------------------------------------------- colour */
  --bg: #000;               /* tone 1: the first section of every page, then every other one */
  --bg2: #141414;           /* tone 2: the header, and the sections between. Neighbours never share a tone. */
  --tile: #1c1c1c;          /* behind artwork and screenshots while they load */
  --studio: #fff;           /* behind clothing photos: the mock-ups' own white, so a photo shows no edge */
  --ink: #fff;
  --mute: #9a9a9a;          /* 7.46:1 on tone 1, 6.55:1 on tone 2 */
  --line: #3a3a3a;          /* rules */
  --edge: #666;             /* the edge of a field or an outline button: 3.66:1 on tone 1, 3.21:1 on tone 2 (the footer's
                               field), past WCAG's 3:1 for a control's edge on both (was #5a5a5a: 2.67:1 on tone 2) */
  --field: #141414;         /* inside a field */
  --accent: #cf352e;        /* the site's red (Antony's pick in B1): the shop's actions */
  --on-accent: #fff;        /* 5.00:1 on the red */
  --alert: #ff7a6e;         /* problems: a field's edge and its message. 8.26:1 on tone 1, 7.24:1 on tone 2 */
  --done: #fff;
  --shade: rgb(0 0 0 / .6); /* behind the cookie bar's edge */
  /* hover and pressed. The red's are mixed from the red itself (actions.css). */
  --solid-hover: #dcdcdc;
  --solid-press: #bdbdbd;
  --line-hover: #fff;
  --veil: rgb(255 255 255 / .06); /* an outline button's fill on hover */
  --veil-press: rgb(255 255 255 / .12);
  --off: .4;                /* a disabled control's opacity */
  /* the tees' colours, for the colour choice (AS Colour's names) */
  --tee-black: #1d1d1d;
  --tee-white: #fff;

  /* ---------------------------------------------------------------- type */
  --ui: 'Mona Sans', system-ui, sans-serif;
  --display: 'Brunson', 'Mona Sans', sans-serif; /* titles and menu items, set in capitals */
  --body: 450 15px/22px var(--ui);
  --caps: 650 15px/20px var(--ui);      /* menu, labels, buttons, captions: all one size (msg 7660) */
  --caps-track: .04em;
  --sub: 450 13px/16px var(--ui);       /* a tool's platforms under its name */
  --fine: 450 12px/16px var(--ui);      /* the small print: the company line at the end of Privacy and Delivery */
  --lyrics: 450 17px/26px var(--ui);
  --title: 86px;            /* a single's or a product's name before it is fitted to its column (client/app.js fit) */
  --title-max: 132px;       /* the most it is fitted to */
  --title-min: 56px;        /* below this, a long name wraps instead of shrinking further */
  --title-floor: var(--title-min); /* the smallest a fitted name may come out (tools/check.js) */
  --title-near: 24px;       /* the floor beside the artwork on a phone, where the name has half the width: a long name wraps
                               to three lines first, and only a long word goes below --title-min (TOMBSTONE, 44px at 390px;
                               WOULDST THOU LIKE TO LIVE DELICIOUSLY?, 34px at 390px and 27px on a 320px phone) */
  --menu-type: 40px;        /* the menu's items, opened on a phone */
  --measure: 34em;          /* longest line of running text */

  /* ---------------------------------------------------------------- space: one scale */
  --s1: 4px; --s2: 8px; --s3: 12px; --s4: 16px; --s5: 24px; --s6: 32px; --s7: 48px; --s8: 64px; --s9: 96px;
  --pad: var(--s4);         /* the page's side margin: 16px on a phone, 32px from 720px */
  --grp: var(--s6);         /* between the groups of a single's block (the name, Listen and Buy, Home's free download) and
                               of a product's: 32px on a phone, 48px from 720px */
  --beside: var(--s4);      /* between a picture and the words beside it: 16px on a phone, 32px from 720px, 64px from 1024px */
  --gap: 2px;               /* between tiles */
  --form-w: 560px;          /* widest a form gets */
  --ft-form: 360px;         /* the footer's sign-up, narrowest beside the links; with less room the links go under it */
  --rel-w: 640px;           /* widest a single's words get, beside its artwork */
  --art-w: 640px;           /* widest a picture beside its words gets: a single's artwork, a tool's window, a tee's photo,
                               About's photo. No picture on the site is wider or taller (tools/check.js), at any width */
  --page: 1440px;           /* widest the page's content gets (Antony, topic 5845 msg 7957: pictures that "get infinitely
                               big"). On a wider screen it keeps to the middle; the bands' colours still run to the edges */
  --wide: max(0%, calc((100% - var(--page)) / 2));  /* the side margin that keeps the content to --page: none up to
                               1440px. Every band takes it (layout.css .sec, frame.css .hd, .ft__main, .cookie) */
  --pbtn: 156px;            /* narrowest a service's button gets: the widest logo, YouTube Music's (113px at --logo-youtube),
                               with 8px each side and room to spare. The four go two to a row wherever that fits (phones
                               from 360px: Antony, note 3 of Site Review 1, "we can still have half buttons"); narrower,
                               one per row */
  /* each service's logo on its Listen button, its name in it (Antony, topic 5845 msgs 8067-8072): how tall each is
     drawn, picked by eye so the four look about equal (msg 8072: "that's better"). YouTube Music's file has space above
     and below its ink, so it is drawn taller; Apple Music's letters are heavy, so it is drawn shorter. Their widths follow:
     87, 83, 113 and 112px (src/data/music.js PLATFORMS logo). */
  --logo-spotify: 26px; --logo-apple: 20px; --logo-youtube: 36px; --logo-amazon: 24px;

  /* ---------------------------------------------------------------- controls */
  --tap: 44px;              /* the smallest tap target, the job's size (WCAG 2.2 asks 24px at AA, 44px at AAA): every button,
                               field and link is at least this tall; a text link's tap area reaches it without moving its
                               words */
  --ctl: 52px;              /* every button and field */
  --ctl-small: var(--tap);  /* the cookie bar's two buttons: the smallest tap size */
  --opt: 48px;              /* a size button */
  --chip: 32px;             /* a colour swatch */
  --r: 8px;                 /* corners */
  --round: 999px;
  --stroke: 1px;
  --rule: 1px;
  --focus: 2px;             /* the focus ring, 2px clear of the control */
  --icon: 18px;
  --mark: 24px;             /* a mark on its own as a link: Instagram, Facebook, email (frame.css .icons), its tap area --tap */
  --spin: 16px;
  --thumb: 72px;            /* a bag line's picture */
  --t: 120ms;

  /* ---------------------------------------------------------------- logo */
  --logo: 88px;             /* the badge in the header */

  /* ---------------------------------------------------------------- Square9's stamp, unchanged from Mickey 9s (its tokens.css) */
  --credit-h: 19.52px;
  --credit-logo: 26px;
  --credit-face-h: 51px;
  --credit-lift: 1.07px;
  --credit-logo-lift: calc(var(--credit-lift) + (var(--credit-logo) - var(--credit-h)) * 0.023);
  --credit-radius: 12px;
  --credit-offset: 6px;
  --credit-space: var(--s6); /* clear space above the stamp's face and below its block, the same on every Square9 site (Antony, topic 625 msg 6546) */
  --credit-tuck: 1px;
  --credit-rule: 2px;
  --t-credit: 120ms;
  --credit-face: #fff;
  --credit-ink: #000;
}

@media (min-width: 720px) {
  :root {
    --pad: var(--s6);
    --grp: var(--s7);
    --beside: var(--s6);
    --title: 112px;
    --logo: 104px;
  }
}

@media (min-width: 1024px) {
  :root {
    --beside: var(--s8);
  }
}

/* ---- src/styles/base.css ---- */
/* The page's defaults and the type helpers every component uses. Text boxes are trimmed to the top of the capitals and
   the baseline (text-box), so every gap in the system is measured from ink to ink. */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; background: var(--bg); }
body { margin: 0; background: var(--bg); color: var(--ink); font: var(--body); -webkit-font-smoothing: antialiased; }
img, svg { display: block; max-width: 100%; height: auto; }
ul, ol { list-style: none; margin: 0; padding: 0; }
h1, h2, h3, h4, h5, h6, p, figure, dl, dd, table { margin: 0; }
fieldset { margin: 0; padding: 0; border: 0; min-width: 0; }
legend { padding: 0; }
a { color: inherit; text-decoration: none; }
input, button { margin: 0; font: inherit; color: inherit; }
button { padding: 0; border: 0; background: none; cursor: pointer; }
[hidden] { display: none !important; }
:focus-visible { outline: var(--focus) solid var(--ink); outline-offset: var(--focus); }

/* the 15px capitals: menu, labels, buttons, captions */
.caps { font: var(--caps); letter-spacing: var(--caps-track); text-transform: uppercase; text-box: trim-both cap alphabetic; }
.mute { color: var(--mute); }
/* running text that sits on the same ink lines as the capitals */
.note { color: var(--mute); text-box: trim-both cap alphabetic; }
/* a standalone link or text action: underlined. Its tap area is --tap (44px) tall, centred on the words, and 8px wider
   each side, without moving them (the ::after), so the ink stays where the spacing puts it. Its focus ring sits clear
   of the underline. */
.link { position: relative; text-decoration: underline; text-decoration-thickness: var(--rule); text-underline-offset: var(--s1); }
.link::after { content: ""; position: absolute; left: calc(-1 * var(--s2)); right: calc(-1 * var(--s2)); top: calc(50% - var(--tap) / 2); height: var(--tap); }
.link:focus-visible { outline-offset: calc(var(--s1) + var(--focus)); }
.link:hover, .link.is-hover { text-decoration-thickness: var(--focus); }
/* Antony's words, not written yet: never mistaken for a fact */
.yours { color: var(--mute); font-style: italic; text-decoration: underline dashed var(--rule); text-underline-offset: var(--s1); text-box: trim-both cap alphabetic; }
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; } /* lint-ok: the standard visually hidden pattern */
.skip { position: absolute; left: var(--pad); top: var(--s2); z-index: 20; padding: var(--s3) var(--s4); background: var(--ink); color: var(--bg); font: var(--caps); letter-spacing: var(--caps-track); text-transform: uppercase; transform: translateY(-200%); }
.skip:focus { transform: none; }
/* reduced motion: nothing slides or fades; a busy button's spinner only slows (actions.css), as it says something */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition-duration: 0s !important; scroll-behavior: auto !important; }
}

/* ---- src/styles/layout.css ---- */
/* The page: header, main, footer. A page shorter than the screen fills it: its last section takes the spare height,
   so the footer sits at the bottom and no third band of colour shows. */
.page { display: flex; flex-direction: column; min-height: 100svh; }
.page__main { display: flex; flex-direction: column; flex: 1; }
.page__main > .sec:last-child { flex-grow: 1; }
.page__main:focus { outline: none; }

/* A section: the full width, in one of the two tones. Neighbours never share one. Its content keeps to --page (1440px):
   on a wider screen it sits in the middle, the section's tone running on to the edges (--wide). A component that sets a
   section's own side padding adds --wide to it (music.css .hero, shop.css .more). */
.sec { background: var(--bg); padding-inline: var(--wide); }
.sec--alt { background: var(--bg2); }

/* A short page's content under its bar: one column, a form's width at most. */
.pane { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s5); justify-items: start; max-width: calc(var(--form-w) + 2 * var(--pad)); padding: 0 var(--pad) var(--s7); }
.pane > .form { justify-self: stretch; }
.pane__lead { text-box: trim-both cap alphabetic; }

/* ---- src/components/frame.css ---- */
/* ---------------------------------------------------------------- header
   Menu, the badge, Bag on a phone and a tablet; the sections, the badge, Bag from 1024px. Tone 2, so it never shares a tone with
   the page's first section. Menu and Bag are 15px capitals in a 44px target, their ink centred on the badge. */
.hd { background: var(--bg2); padding-inline: var(--wide); }   /* its content keeps to --page, as every section's */
.hd__bar { display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); align-items: center; padding: var(--s4) var(--pad); }
.hd__nav { display: none; gap: var(--s5); }
.hd__link, .hd__menu, .hd__bag { position: relative; font: var(--caps); letter-spacing: var(--caps-track); text-transform: uppercase; text-box: trim-both cap alphabetic; text-underline-offset: var(--s2); }
.hd__link::after, .hd__menu::after, .hd__bag::after { content: ""; position: absolute; left: calc(-1 * var(--s2)); right: calc(-1 * var(--s2)); top: calc(50% - var(--tap) / 2); height: var(--tap); }   /* a 44px tap area */
.hd__link:hover, .hd__bag:hover { text-decoration: underline; text-decoration-thickness: var(--rule); }
.hd__link[aria-current="page"] { text-decoration: underline; text-decoration-thickness: var(--focus); }
.hd__menu { justify-self: start; }
.hd__logo { display: block; }
.hd__badge { height: var(--logo); width: auto; }
.hd__bag { justify-self: end; display: inline-flex; align-items: center; gap: var(--s1); white-space: nowrap; }
.hd__count { color: var(--mute); }
.hd__count.is-full { color: var(--ink); }

/* the phone's menu, open: the sections in the logo's lettering, under the bar, in the header's tone */
.hd__panel { padding: 0 var(--pad) var(--s6); }
.hd__items { display: grid; border-top: var(--rule) solid var(--line); }
.hd__item { display: block; padding: var(--s5) 0; border-bottom: var(--rule) solid var(--line); font: 400 var(--menu-type)/1 var(--display); text-transform: uppercase; text-box: trim-both cap alphabetic; font-synthesis: none; }
.hd__item[aria-current="page"] { color: var(--mute); text-decoration: underline; text-decoration-thickness: var(--focus); text-underline-offset: var(--s2); }   /* grey and underlined: not colour alone */
.hd__item:hover { color: var(--mute); }

/* ---------------------------------------------------------------- POPO COPS elsewhere
   Instagram, Facebook and email as their marks, 24px (--mark), 24px apart, white, grey under the pointer. Each link's
   tap area is the 44px (--tap) around its mark, without moving it (the ::after), so the first mark sits on the words'
   left edge and neighbouring tap areas never meet. */
.icons { display: flex; flex-wrap: wrap; gap: var(--s5); }
.icons__link { position: relative; display: block; width: var(--mark); height: var(--mark); color: var(--ink); transition: color var(--t); }
.icons__link svg { width: 100%; height: 100%; }
.icons__link::after { content: ""; position: absolute; inset: calc((var(--mark) - var(--tap)) / 2); }
.icons__link:hover, .icons__link.is-hover { color: var(--mute); }
.icons__link:focus-visible, .icons__link.is-focus { outline: var(--focus) solid var(--ink); outline-offset: var(--s1); border-radius: var(--focus); }

/* ---------------------------------------------------------------- section bar
   A section's name and count on the left, a link to all of it on the right. 48px above its ink, 24px below. */
.bar { display: flex; justify-content: space-between; align-items: center; gap: var(--s4); padding: var(--s7) var(--pad) var(--s5); }
.bar__title { min-width: 0; }
.bar__title[id] { scroll-margin-top: var(--s7); }  /* a link to it (Size guide) leaves its 48px above, as the bar does */

/* ---------------------------------------------------------------- footer
   The sign-up, then the links and POPO COPS elsewhere's marks (.icons); Square9's stamp in its own band below. The company
   line is in the small print of Privacy and Delivery (content.css .prose__fine), not here (Antony, topic 5845 msg 7962). */
.ft { display: block; }
.ft__main { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s8); padding: var(--s7) calc(var(--pad) + var(--wide)); background: var(--bg2); }
.ft--flip .ft__main { background: var(--bg); }
.ft__main > .form { max-width: var(--form-w); }
/* each link on a row of the tap size, 44px, its words centred: so every link is a whole 44px target and none overlaps
   the next (their letters 33px apart). The lists' first and last rows reach past them, so their letters sit where a
   line of text would: the first level with the sign-up's name beside it, the last 48px over the footer's edge (the
   cap unit: the capitals' height). The marks' row is as tall as their 24px plus the room a link's row has above and
   below its letters, so the marks sit where the letters would: level with the sign-up's name beside it, 48px over the
   edge under it. On a phone, stacked: the sign-up, 64px, the links, then the marks 49px under the last of them (16px
   between their rows), more than the 33px between links and less than the 64px above, so each reads as its group. */
.ft__cols { display: grid; gap: var(--s4); margin-block: calc((1cap - var(--tap)) / 2); }
.ft__list { display: grid; align-content: start; justify-items: start; }
.ft__list > li { display: flex; align-items: center; min-height: var(--tap); }
.ft__link { position: relative; display: block; font: var(--caps); letter-spacing: var(--caps-track); text-transform: uppercase; text-box: trim-both cap alphabetic; }
.ft__link::after { content: ""; position: absolute; left: calc(-1 * var(--s2)); right: calc(-1 * var(--s2)); top: calc(50% - var(--tap) / 2); height: var(--tap); }
.ft__link:hover, .ft__link[aria-current="page"] { text-decoration: underline; text-decoration-thickness: var(--rule); text-underline-offset: var(--s1); }
.ft__cols > .icons { align-self: start; padding-block: calc((var(--tap) - 1cap) / 2); }

/* ---------------------------------------------------------------- Square9's stamp, unchanged from Mickey 9s
   (its frame.css .foot__credit): the Square9 site's button, a white face with a thin black line over a black block
   6px behind it, 12px corners; on hover or press the face moves onto the block. 32px of clear space above its face
   and below its block (topic 625 msg 6546). Its band takes the tone the footer doesn't. */
.credit { display: flex; justify-content: center; padding: var(--credit-space) 0 calc(var(--credit-space) + var(--credit-offset)); background: var(--bg); }
.ft--flip .credit { background: var(--bg2); }
.credit__link { position: relative; display: inline-flex; border-radius: var(--credit-radius); text-decoration: none; }
.credit__link::before { content: ""; position: absolute; inset: 0; border-radius: inherit; background: var(--credit-ink); transform: translate(var(--credit-offset), var(--credit-offset)); }
.credit__card {
  position: relative; display: inline-flex; align-items: center; gap: var(--s2);
  min-height: var(--credit-face-h); padding: 0 var(--s5); border-radius: inherit; background: var(--credit-face);
  box-shadow: inset 0 0 0 var(--credit-rule) var(--credit-ink);
  transition: transform var(--t-credit);
}
.credit__label, .credit__logo { position: relative; top: calc(-1 * var(--credit-lift)); display: block; height: var(--credit-h); width: auto; }
.credit__logo { top: calc(-1 * var(--credit-logo-lift)); height: var(--credit-logo); }
.credit__link:hover .credit__card, .credit__link:active .credit__card,
.credit__link.is-hover .credit__card { transform: translate(var(--credit-offset), var(--credit-offset)); }
.credit__link:hover::before, .credit__link:active::before, .credit__link.is-hover::before { inset: var(--credit-tuck); }
.credit__link:focus-visible, .credit__link.is-focus { outline: var(--focus) solid var(--ink); outline-offset: calc(var(--credit-offset) + var(--credit-rule)); }

/* ---------------------------------------------------------------- cookie bar
   Small, at the bottom, a minute into the visit (PLAN.md section 9.4; Antony, topic 5845 msg 7823 item 16), and never
   over anything. While it asks (<html data-cookies="ask">) the screen is the page and the bar, one above the other,
   and the page scrolls in the room above the bar, so the bar covers nothing at any point of the page. The page
   arrives asking (pages/layout.js); the bar's script in the head puts "wait" there for the first minute, or the
   answer already given (src/lib/cookies.js). While it waits, once answered ("no" or "ok"), or inside a frame, the bar
   is gone and the page scrolls as any page does. Without data-cookies (the reference's specimens) the bar sits where
   it's put. */
/* One row at every width, the words beside No and OK (wrapping beside them on a phone), so the bar takes as little of the
   screen as it can: 68px on a phone, where it took two rows (Antony, topic 5845 msg 7957: "limiting the hindrance").
   overflow: the Privacy link's tap area (.link::after) stays inside the bar, never over the page above it */
.cookie { display: flex; align-items: center; justify-content: space-between; gap: var(--s4); padding: var(--s3) calc(var(--pad) + var(--wide)); overflow: hidden; background: var(--bg2); border-top: var(--rule) solid var(--line); }
.cookie__text { flex: 1 1 auto; min-width: 0; text-box: trim-both cap alphabetic; }
.cookie__acts { display: flex; flex: none; gap: var(--s2); }
/* the window itself never scrolls while the bar asks; the page holds everything it draws, the hidden headings too
   (position: relative), so nothing escapes it to make the window scroll */
[data-cookies="ask"], [data-cookies="ask"] body { overflow: hidden; }
[data-cookies="ask"] body { display: flex; flex-direction: column; height: 100vh; height: 100dvh; }
[data-cookies="ask"] .page { position: relative; flex: 1 1 auto; min-height: 0; overflow-y: auto; }
[data-cookies="ask"] .cookie { flex: none; }
[data-cookies]:not([data-cookies="ask"]) .cookie { display: none; }

@media (min-width: 720px) {
  /* the sign-up and the links side by side once the links fit beside it at full length; else the links go under it */
  .ft__main { display: flex; flex-wrap: wrap; align-items: start; gap: var(--s7) var(--s8); }
  .ft__main > .form { flex: 1 1 var(--ft-form); }
  .ft__cols { display: flex; flex: 1 1 auto; flex-wrap: wrap; justify-content: space-between; gap: var(--s6); }
}

@media (min-width: 1024px) {
  .hd__nav { display: flex; grid-row: 1; grid-column: 1; }
  .hd__menu { display: none; }
  .hd__logo { grid-column: 2; }
  .hd__bag { grid-column: 3; }
  .hd__panel { display: none; }
}

/* ---- src/components/actions.css ---- */
/* ---------------------------------------------------------------- button
   One height (52px), one corner (8px), one lettering (the 15px capitals). The words' ink is centred in the button.
   Hover lifts the colour towards white; pressed takes it towards black; the focus ring is white, 2px clear. */
.btn {
  display: flex; align-items: center; justify-content: center; gap: var(--s2);
  min-height: var(--ctl); padding: 0 var(--s4);
  border: var(--stroke) solid transparent; border-radius: var(--r);
  font: var(--caps); letter-spacing: var(--caps-track); text-transform: uppercase; white-space: nowrap;
  transition: background-color var(--t), border-color var(--t), color var(--t);
}
.btn > span { text-box: trim-both cap alphabetic; }
/* a logo in place of the words (actions.js button() logo): drawn at the height its place gives it (the Listen buttons:
   music.css), as wide as that makes it, centred. Never wider than the inside of the button: past that it shrinks, its
   shape kept, rather than run into the edge. */
.btn__logo { flex: none; width: auto; height: var(--icon); max-width: 100%; object-fit: contain; }
.btn:focus-visible, .btn.is-focus { outline: var(--focus) solid var(--ink); outline-offset: var(--focus); }

/* accent: the main action outside a single's block, in the site's red: Add to bag, Checkout, Download, Send */
.btn--accent { background: var(--accent); color: var(--on-accent); }
.btn--accent:hover, .btn--accent.is-hover { background: color-mix(in srgb, var(--accent) 84%, var(--ink)); }
.btn--accent:active, .btn--accent.is-press { background: color-mix(in srgb, var(--accent) 80%, var(--bg)); }

/* outline: the four services, each with its logo (Spotify too: Antony, topic 5845 msgs 8028 and 8067), Buy on a single */
.btn--line { border-color: var(--edge); color: var(--ink); }
.btn--line:hover, .btn--line.is-hover { border-color: var(--line-hover); background: var(--veil); }
.btn--line:active, .btn--line.is-press { border-color: var(--line-hover); background: var(--veil-press); }

/* solid: white with black words: Sign up, Get it free (Antony, topic 5845 msg 8028), the cookie bar's OK, Home on the 404 page */
.btn--solid { background: var(--ink); color: var(--bg); }
.btn--solid:hover, .btn--solid.is-hover { background: var(--solid-hover); }
.btn--solid:active, .btn--solid.is-press { background: var(--solid-press); }

/* split: the label at the left and a value at the right (Buy · £XX) */
.btn--split { justify-content: space-between; padding: 0 var(--s5); }
.btn--small { min-height: var(--ctl-small); padding: 0 var(--s4); }
.btn--wide { width: 100%; }

/* disabled: can't be used now (a tee with every size gone) */
.btn:disabled, .btn.is-disabled { opacity: var(--off); cursor: not-allowed; }
.btn--accent:disabled, .btn--accent.is-disabled { background: var(--accent); }
/* busy: waiting for an answer (Sending, Going to payment). The spinner turns; taps do nothing until it answers. */
.btn.is-busy { cursor: progress; }
.btn__spin { width: var(--spin); height: var(--spin); flex: none; border: var(--focus) solid currentColor; border-right-color: transparent; border-radius: var(--round); animation: btn-spin 800ms linear infinite; }
@keyframes btn-spin { to { transform: rotate(1turn); } }
@media (prefers-reduced-motion: reduce) { .btn__spin { animation-duration: 2400ms; } }

/* a text action that is a button: Add to bag, Remove, Clear search */
button.link { justify-self: start; padding: 0; text-align: left; }

/* ---- src/components/forms.css ---- */
/* ---------------------------------------------------------------- the email forms
   Head (name and Antony's line), then the field and its button: side by side from 720px, stacked on a phone.
   24px from the head to the field; 12px inside each group. */
.form { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s5); align-content: start; }
.form__head { display: grid; gap: var(--s3); }
.form__head .caps { color: var(--ink); }
/* the free download, on Home only, is the first thing under Listen, with a rule above it, inside the single's block
   (Antony, topic 5845 msgs 8085 and 8104: Home has no Buy). 32px on both sides of the rule: above, to the last Listen
   button's edge (to the baseline of the artists' line, or the artwork's foot on a phone, while a new single has no
   Listen buttons yet); below, to the heading's capitals. Not the block's 48px gap. */
.form--free { border-top: var(--rule) solid var(--line); padding-top: var(--s6); margin-top: calc(var(--s6) - var(--grp)); }

.field { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s3); }
.field__input { min-width: 0; width: 100%; min-height: var(--ctl); padding: 0 var(--s4); background: var(--field); border: var(--stroke) solid var(--edge); border-radius: var(--r); color: var(--ink); }
.field__input::placeholder { color: var(--mute); opacity: 1; }
.field__input:hover { border-color: var(--line-hover); }
.field__input:focus-visible, .field__input.is-focus { outline: var(--focus) solid var(--ink); outline-offset: var(--focus); border-color: var(--line-hover); }
.field__input[aria-invalid="true"] { border-color: var(--alert); }
.field__input[readonly] { color: var(--mute); }
/* a problem: under the field, in the problem colour, with its mark */
.field__msg { display: flex; align-items: center; gap: var(--s2); color: var(--alert); }
.field__msg svg { width: var(--icon); height: var(--icon); flex: none; color: var(--alert); }
.field__msg span { text-box: trim-both cap alphabetic; }

/* sent: the field gives way to what happened, with a tick */
.form__done { display: flex; align-items: flex-start; gap: var(--s3); }
.form__done > svg { margin-top: calc((1cap - var(--icon)) / 2); }
.form__done:focus { outline: none; }
.form__done svg { width: var(--icon); height: var(--icon); flex: none; color: var(--done); }
.form__said { display: grid; gap: var(--s3); }
.form__said p { text-box: trim-both cap alphabetic; }

@media (min-width: 720px) {
  .field { grid-template-columns: minmax(0, 1fr) auto; }
  .field__msg { grid-column: 1 / -1; }
}

/* Cloudflare's bot check (Turnstile). Its widget lives in this box at the foot of the screen, which is there but
   empty-looking for most visitors (a hidden box could stop the widget running); when Cloudflare wants something of a
   visitor, the box opens into a panel with Turnstile's own box in it (is-open, client/app.js). */
.check { position: fixed; left: var(--pad); right: var(--pad); bottom: var(--pad); z-index: 40; display: grid; justify-items: center; pointer-events: none; }
.check > p { display: none; }
.check.is-open { gap: var(--s4); padding: var(--s5) var(--s4); background: var(--bg2); border: var(--rule) solid var(--edge); border-radius: var(--r); box-shadow: 0 0 0 var(--s2) var(--shade); pointer-events: auto; }
.check.is-open > p { display: block; text-box: trim-both cap alphabetic; }

/* ---- src/components/music.css ---- */
/* ---------------------------------------------------------------- a single's block (and a tool's; a product's and About)
   On a phone (below 720px) the artwork and the name sit side by side, half the width each, their tops level, 24px under
   the header (a tool 48px into its section, or 24px under the page's bar); under them, across the width: Listen two by
   two, then Buy on the single's page or the free download on Home. So a visitor landing on Home sees the single and
   every option at once (Antony, note 3 of "POPO COPS Site Review 1", 9 Nov 2026: "I want them to be able to see all the
   different options"). A tool's block is laid out the same way. The name is as big as its half allows (client/app.js fit), down to --title-near for a long
   one. From 720px (a tablet, msg 7957: "Tablet is a nightmare") the artwork on the left and every word on the right,
   inside the page's margins, 48px under the header, their tops level, the words a little wider than the artwork; from
   1024px half each, the artwork never wider than --art-w. */
.hero, .tool__body { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--grp) var(--beside); align-items: start; padding-block: var(--s7); padding-inline: var(--pad); }
/* The single's block is its own section, so it adds the page's wide margin (layout.css .sec) to its own; and, first
   under the header, it starts 24px under it on a phone, so its options come up the first screen (note 3). Every other
   block, like every section, starts 48px in. */
.hero { padding-top: var(--s5); padding-inline: calc(var(--pad) + var(--wide)); }
.tool > .bar + .tool__body, .about > .bar + .about__body { padding-top: 0; }   /* under a page's bar: the bar's own 24px */
.hero__art img { width: 100%; aspect-ratio: 1; object-fit: cover; background: var(--tile); }
/* the words: a product's under its photos on a phone (shop.css); a single's and a tool's are the block's own grid on a
   phone, the name beside the picture and everything else under both */
.rel { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--grp); align-content: start; padding: var(--s6) var(--pad) var(--s7); }
.hero > .rel, .tool__body > .rel { display: contents; }
.hero > .rel > *, .tool__body > .rel > * { grid-column: 1 / -1; }
.hero .rel__name, .tool__body .rel__name { grid-column: 2; --title-floor: var(--title-near); }
.rel__name { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s4); }
.rel__title { width: fit-content; max-width: 100%; font: 400 var(--title)/1 var(--display); text-transform: uppercase; white-space: nowrap; text-box: trim-both cap alphabetic; font-synthesis: none; }
.rel__title.is-wrapped { width: auto; white-space: normal; line-height: .92; text-wrap: balance; }
.rel__title--tail { margin-bottom: .14em; }
.grp { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s3); }
/* the four services: two to a row wherever two fit at --pbtn (never three), else one per row. Each button shows its
   service's logo, with the name in it, in place of the words (Antony, topic 5845 msgs 8067-8072), centred, at least
   8px clear of the edge each side (tools/check.js 3), at the height that makes the four look about equal: each logo's
   own token (tokens.css --logo-*). */
.pgrid { display: grid; grid-template-columns: repeat(auto-fit, minmax(max(var(--pbtn), calc((100% - var(--s3)) / 2)), 1fr)); gap: var(--s3); }
.pgrid .btn { padding: 0 var(--s2); }
[data-platform="spotify"] > .btn__logo { height: var(--logo-spotify); }
[data-platform="apple"] > .btn__logo { height: var(--logo-apple); }
[data-platform="youtube"] > .btn__logo { height: var(--logo-youtube); }
[data-platform="amazon"] > .btn__logo { height: var(--logo-amazon); }
/* On a single's page Listen and Buy read as one group: Buy sits as far under the last service as the services sit from
   each other, 12px, not a group's gap away (Antony, note 1 of "POPO COPS Site Review 1", 9 Nov 2026). On Home there is
   no Buy, and the free download is its own group under Listen, past the rule (forms.css .form--free). */
.rel > [data-listen] + .grp { margin-top: calc(var(--s3) - var(--grp)); }

/* ---------------------------------------------------------------- lyrics
   One column at every width, never wider than the longest running line (--measure), at the page's margin. */
.lyr { padding-bottom: var(--s7); }
.lyr__text { display: grid; gap: var(--s5); max-width: calc(var(--measure) + 2 * var(--pad)); padding: 0 var(--pad); font: var(--lyrics); }
.lyr__text p { text-box: trim-both cap alphabetic; }
.lyr__none { display: block; padding: 0 var(--pad); }

/* ---------------------------------------------------------------- tiles
   A bar, then a grid of tiles 2px apart, edge to edge: 2 across on a phone; from 720px 4 (clothing), 6 (music) or
   4 with two filled (tools). Each tile: the picture, then its name and its year or price, 12px in from the edge, and a
   tee's colour or a tool's platforms under them, all 8px apart. */
.tiles { padding-bottom: var(--s5); }
.grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--gap); }
/* the tile keeps to its column: a name with a word too long for it (WOULDST THOU LIKE TO LIVE DELICIOUSLY? in a 126px
   column at 768px) breaks the word, at its soft hyphen (components/music.js breakable()) or else wherever it must,
   rather than pushing its picture into the next tile */
.tile { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s3); align-content: start; padding-bottom: var(--s5); }
.tile__img { display: block; overflow: hidden; }
.tile__img img { width: 100%; height: 100%; }
.tile__img--studio { aspect-ratio: 4 / 5; background: var(--studio); }
.tile__img--studio img { object-fit: contain; }   /* the photo has its own white margin */
.tile__img--art { aspect-ratio: 1; background: var(--tile); }
.tile__img--art img { object-fit: cover; }
.tile__cap { display: flex; flex-direction: column; gap: var(--s2); padding: 0 var(--s3); }
.tile__cap > span { text-box: trim-both cap alphabetic; }
.tile__name { text-wrap: balance; overflow-wrap: anywhere; }
.tile__meta { color: var(--mute); }
.tile__sub { margin-top: calc(var(--s2) - var(--s3)); padding: 0 var(--s3); color: var(--mute); font: var(--sub); text-box: trim-both cap alphabetic; }  /* 8px under the price, as the price is under the name */
.tile:hover .tile__name { text-decoration: underline; text-decoration-thickness: var(--rule); text-underline-offset: var(--s1); }
/* sold out: the photo dims and the price gives way to Sold out */
.tile.is-out .tile__img img { opacity: var(--off); }

/* ---------------------------------------------------------------- search (Music)
   The box, then how many match. Filters as you type; nothing leaves the browser. */
.search { display: grid; gap: var(--s5); padding: 0 var(--pad) var(--s5); }
.search__box { position: relative; display: flex; align-items: center; max-width: var(--form-w); min-height: var(--ctl); border: var(--stroke) solid var(--edge); border-radius: var(--r); background: var(--field); }
.search__box:hover { border-color: var(--line-hover); }
.search__box:focus-within { outline: var(--focus) solid var(--ink); outline-offset: var(--focus); border-color: var(--line-hover); }
.search__box > svg { position: absolute; left: var(--s4); width: var(--icon); height: var(--icon); color: var(--mute); pointer-events: none; }
.search__input { flex: 1; min-width: 0; min-height: var(--ctl); padding: 0 var(--s4) 0 calc(var(--s4) + var(--icon) + var(--s3)); border: 0; background: none; color: var(--ink); }
.search__input:focus { outline: none; }
.search__input::placeholder { color: var(--mute); opacity: 1; }
.search__input::-webkit-search-cancel-button { display: none; }
.search__clear { align-self: stretch; padding: 0 var(--s4); color: var(--ink); text-decoration: underline; text-decoration-thickness: var(--rule); text-underline-offset: var(--s1); }
.nores { display: grid; gap: var(--s5); justify-items: start; padding: var(--s5) var(--pad) var(--s5); }
.nores p { text-box: trim-both cap alphabetic; }

/* From 600px a tee's photo and About's photo sit beside their words, by the rule a single's block takes from 720px
   (below): a little narrower than the words, inside the page's margins, 48px into the section, their tops level. No
   picture fills the width of a small tablet (Antony, topic 5845 msg 7957). */
@media (min-width: 600px) {
  .prod, .about__body { display: grid; grid-template-columns: minmax(0, 9fr) minmax(0, 11fr); column-gap: var(--beside); align-items: start; padding-block: var(--s7); padding-inline: var(--pad); }
  .prod { padding-inline: calc(var(--pad) + var(--wide)); }
  .about > .bar + .about__body { padding-top: 0; }
}

/* From 720px a single's and a tool's artwork on the left and every word on the right: one rule for the four blocks. */
@media (min-width: 720px) {
  .hero, .tool__body { grid-template-columns: minmax(0, 9fr) minmax(0, 11fr); column-gap: var(--beside); padding-block: var(--s7); }
  .tool > .bar + .tool__body { padding-top: 0; }
  .hero > .rel, .tool__body > .rel { display: grid; }
  .hero .rel__name, .tool__body .rel__name { grid-column: auto; --title-floor: inherit; }
  .rel { max-width: var(--rel-w); padding: 0; }
  .grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .grid--music { grid-template-columns: repeat(6, minmax(0, 1fr)); }
}

/* From 1024px the artwork and the words take half each, --beside (64px) apart, inside the page's margins, 48px under the
   header and 48px over the next section; the artwork never wider than --art-w (640px, reached at 1440px), the words
   taking the rest up to --rel-w, so no picture grows with the window (Antony, topic 5845 msg 7957: "images that get
   infinitely big"). Both from the top: the top of the first line's capitals is level with the
   artwork's top edge (Antony, topic 5845 msg 7931, "anchor to top on desktop"), and neither touches the header (msg
   7957: the words touched the bar). A tool's, a product's and About are laid out by this same rule: one decision for
   all four. Under a page's bar (Tools, About) the bar's own 24px is the gap above. */
@media (min-width: 1024px) {
  .hero, .tool__body, .prod, .about__body { grid-template-columns: minmax(0, min(var(--art-w), calc((100% - var(--beside)) / 2))) minmax(0, 1fr); }
}

/* ---- src/components/shop.css ---- */
/* ---------------------------------------------------------------- the product
   Phone: the photos side by side, swiped (the next one peeks in), then the words. From 600px: the photos one under
   another on the left, a little narrower than the words on the right (half each from 1024px), inside the page's
   margins and 48px under the header, the top of their first line level with the first photo's top and kept in view
   while the photos scroll past, laid out as a single's block (music.css). So no photo fills a tablet's width. */
.prod__photos { display: grid; grid-auto-flow: column; grid-auto-columns: 88%; gap: var(--gap); overflow-x: auto; scroll-snap-type: x mandatory; scrollbar-width: none; }
.prod__photos::-webkit-scrollbar { display: none; }
.prod__photo { scroll-snap-align: start; background: var(--studio); }
.prod__photo img { width: 100%; aspect-ratio: 1; object-fit: contain; }
.prod__photos:has(> :only-child) { grid-auto-columns: 100%; }

/* ---------------------------------------------------------------- size and colour
   The name of the choice with what's chosen, 12px above the buttons. Sizes in rows of five, 8px apart. */
.opts { display: block; }
.opts__head { float: left; margin-bottom: var(--s3); }
.opts__aside { float: right; }
.opts__aside::after { top: auto; bottom: calc(-1 * var(--s3)); }   /* its 44px tap area reaches up from the size buttons' top edge, never over them */
.opts__row { clear: both; display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: var(--s2); }
.opt { position: relative; display: block; }
.opt__input { position: absolute; inset: 0; z-index: 1; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer; }
.opt__face { display: flex; align-items: center; justify-content: center; min-height: var(--opt); padding: 0 var(--s2); border: var(--stroke) solid var(--edge); border-radius: var(--r); }
.opt__face > span { text-box: trim-both cap alphabetic; }
.opt:hover .opt__face, .opt.is-hover .opt__face { border-color: var(--line-hover); }
.opt__input:checked + .opt__face, .opt.is-chosen .opt__face { background: var(--ink); border-color: var(--ink); color: var(--bg); }
.opt__input:focus-visible + .opt__face, .opt.is-focus .opt__face { outline: var(--focus) solid var(--ink); outline-offset: var(--focus); }
/* run out: crossed through, dashed, can't be chosen */
.opt.is-out .opt__face { border-style: dashed; border-color: var(--line); color: var(--mute); text-decoration: line-through; }
.opt.is-out .opt__input { cursor: not-allowed; }

.opts__row:has(.swatch) { display: flex; flex-wrap: wrap; gap: var(--s2); }
.swatch { position: relative; display: grid; place-items: center; width: var(--opt); height: var(--opt); }
.swatch__chip { width: var(--chip); height: var(--chip); border-radius: var(--round); box-shadow: inset 0 0 0 var(--stroke) var(--edge); }
.opt__input:checked + .swatch__chip { box-shadow: inset 0 0 0 var(--stroke) var(--edge), 0 0 0 var(--s1) var(--bg), 0 0 0 calc(var(--s1) + var(--focus)) var(--ink); }
.opt__input:focus-visible + .swatch__chip { outline: var(--focus) solid var(--ink); outline-offset: var(--s2); }
.swatch__chip--black { background: var(--tee-black); }
.swatch__chip--white { background: var(--tee-white); }

/* ---------------------------------------------------------------- details and size guide */
.more__col:last-child { padding-bottom: var(--s7); }  /* stacked on a phone: the size guide's bar gives the 48px between */
.ticks { display: grid; border-top: var(--rule) solid var(--line); margin: 0 var(--pad); }
.ticks li { padding: var(--s4) 0; border-bottom: var(--rule) solid var(--line); text-box: trim-both cap alphabetic; }
.sizes { display: grid; gap: var(--s5); padding: 0 var(--pad); }
.sizes__table { width: 100%; border-collapse: collapse; font-variant-numeric: tabular-nums; }
.sizes__table th, .sizes__table td { padding: var(--s4) 0; border-bottom: var(--rule) solid var(--line); text-align: right; font-weight: inherit; text-box: trim-both cap alphabetic; }  /* every row 16px above and below its letters, as the details list */
.sizes__table thead th { border-top: var(--rule) solid var(--line); color: var(--mute); }
.sizes__table th:first-child { text-align: left; }
/* the measuring diagram (Mickey 9s's): a flat tee drawn in grey, where it's measured in white, at its drawn size (273
   wide, cropped to its lines: components/shop.js measureDiagram), shrinking with a narrower column. Lines stay one rule
   wide at any size. */
.teefig { display: block; min-width: 0; }
.teefig__svg { display: block; max-width: 100%; height: auto; }
.teefig__tee, .teefig__seam, .teefig__line { stroke-width: var(--rule); vector-effect: non-scaling-stroke; stroke-linejoin: round; fill: none; }
.teefig__tee, .teefig__seam { stroke: var(--mute); }
.teefig__line { stroke: var(--ink); }
.teefig__label { font: var(--sub); letter-spacing: var(--caps-track); text-transform: uppercase; fill: var(--ink); }

@media (min-width: 600px) {
  .prod > .rel { position: sticky; top: var(--s7); padding: 0; }   /* level with the photos' top; kept 48px from the screen's top as they scroll */
  .prod__photos { grid-auto-flow: row; grid-auto-columns: auto; overflow: visible; }
}

@media (min-width: 720px) {
  .more { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); column-gap: var(--s8); padding-right: calc(var(--pad) + var(--wide)); }
  .more__col { padding-bottom: var(--s7); }
  .more .ticks, .more .sizes { margin-right: 0; padding-right: 0; }
}



/* ---- src/components/tools.css ---- */
/* ---------------------------------------------------------------- a tool
   Its window, then its block: what it runs on, its name, Antony's words about it, what it needs, Buy, how it works,
   how to install it. Laid out as a single's block (music.css): on a phone the picture and the name side by side, the
   rest under both; from 720px the picture on the left and every word on the right, inside the page's margins, their
   tops level, 24px under the page's bar or 48px into the section. */
.tool__img img { width: 100%; aspect-ratio: 1; object-fit: cover; background: var(--tile); }
.tool__about { display: grid; gap: var(--s5); }
.tool__about > p { text-box: trim-both cap alphabetic; max-width: var(--measure); }
.tool .ticks { margin: 0; }
.tool__part { display: grid; gap: var(--s4); }
.tool__steps { display: grid; gap: var(--s4); padding-left: var(--s5); list-style: decimal; }
.tool__steps li { max-width: var(--measure); text-box: trim-both cap alphabetic; }
/* the install note keeps its box off the section's own tone, 24px under the steps, more than the 16px between them */
.sec--alt .tool__part .install { background: var(--bg); }
.tool__part > .install { margin-top: calc(var(--s5) - var(--s4)); }
/* a tool after the first (no bar above it) starts with 48px of its own tone (its box's own padding: music.css), so a
   picture with its own black ground (Auto Scale's) never runs into the black section above it */

/* ---- src/components/bag.css ---- */
/* ---------------------------------------------------------------- the bag
   A ruled line per thing: its picture, name, what it is, the tee's quantity, Remove; its price at the right. Then the
   totals and Checkout. Side by side from 720px. */
.bag { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s7); padding: 0 var(--pad) var(--s7); }
.bag__lines { display: grid; border-top: var(--rule) solid var(--line); }
.line { display: grid; grid-template-columns: var(--thumb) minmax(0, 1fr) auto; gap: var(--s4); align-items: start; padding: var(--s4) 0; border-bottom: var(--rule) solid var(--line); }
.line__img { display: block; width: var(--thumb); aspect-ratio: 1; overflow: hidden; border-radius: var(--r); }
.line__img img { width: 100%; height: 100%; object-fit: cover; }
.line__img--art { background: var(--tile); }
.line__img--studio { background: var(--studio); }
.line__img--studio img { object-fit: contain; }
.line__body { display: grid; gap: var(--s3); justify-items: start; padding-top: var(--s1); }
.line__name a { position: relative; }
.line__name a::after { content: ""; position: absolute; left: calc(-1 * var(--s2)); right: calc(-1 * var(--s2)); top: calc(50% - var(--tap) / 2); height: var(--tap); }   /* a 44px tap area */
.line__name a:hover { text-decoration: underline; text-decoration-thickness: var(--rule); text-underline-offset: var(--s1); }
.line__price { padding-top: var(--s1); white-space: nowrap; }
.qty { display: inline-flex; align-items: center; margin-block: var(--s1); border: var(--stroke) solid var(--edge); border-radius: var(--r); }
.qty__btn { display: grid; place-items: center; width: var(--opt); height: var(--opt); font: var(--caps); }
.qty__btn:disabled { color: var(--mute); cursor: not-allowed; }
.qty__n { min-width: var(--s6); text-align: center; }
.qty + .link { margin-top: var(--s1); }   /* Remove's 44px tap area clear of the quantity buttons above it */
.sum { display: grid; gap: var(--s5); align-content: start; }
.sum__rows { display: grid; gap: var(--s4); }
.sum__row { display: flex; justify-content: space-between; gap: var(--s4); }
.sum__row dt, .sum__row dd { text-box: trim-both cap alphabetic; }
.sum__row--total { padding-top: var(--s4); border-top: var(--rule) solid var(--line); }
.bag--empty { justify-items: start; gap: var(--s5); }
.bag--empty > p { text-box: trim-both cap alphabetic; }
.bag__go { display: flex; flex-wrap: wrap; gap: var(--s2); }

@media (min-width: 720px) {
  .bag { grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); column-gap: var(--s8); align-items: start; }
  /* Subtotal level with the first thing's name: under the list's rule, the line's 16px and the name's 4px */
  .sum { padding-top: calc(var(--rule) + var(--s4) + var(--s1)); }
  .bag--empty { grid-template-columns: minmax(0, 1fr); }
}

/* ---- src/components/order.css ---- */
/* ---------------------------------------------------------------- the order
   The reference and who it's for, then the downloads with their buttons, then the clothing and when it's posted. */
.order { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s7); max-width: calc(var(--rel-w) + 2 * var(--pad)); padding: 0 var(--pad) var(--s7); }
.order__head { display: grid; gap: var(--s3); }
.order__head > p { text-box: trim-both cap alphabetic; }
.order__ref { font: var(--caps); letter-spacing: var(--caps-track); }
.order__notes { display: grid; gap: var(--s5); padding-top: var(--s3); }
.dl { display: grid; border-top: var(--rule) solid var(--line); }
.dl__item { display: grid; grid-template-columns: var(--thumb) minmax(0, 1fr); gap: var(--s4); align-items: center; padding: var(--s4) 0; border-bottom: var(--rule) solid var(--line); }
.dl__img { width: var(--thumb); aspect-ratio: 1; border-radius: var(--r); }
.dl__img--art { object-fit: cover; background: var(--tile); }
.dl__img--studio { object-fit: contain; background: var(--studio); }
.dl__body { display: grid; gap: var(--s3); }
.dl__body > p { text-box: trim-both cap alphabetic; }
.dl__item > .btn { grid-column: 1 / -1; }
/* the install note, under each tool: Antony's note (src/data/tools.js INSTALL_NOTE) */
.install { grid-column: 1 / -1; display: grid; gap: var(--s4); padding: var(--s5); border-radius: var(--r); background: var(--bg2); }
.install > p, .install li { text-box: trim-both cap alphabetic; }
.install__steps { display: grid; gap: var(--s4); padding-left: var(--s5); list-style: decimal; }

@media (min-width: 720px) {
  .dl__item { grid-template-columns: var(--thumb) minmax(0, 1fr) auto; }
  .dl__item > .btn { grid-column: auto; }
}

/* ---- src/components/content.css ---- */
/* ---------------------------------------------------------------- running text (Privacy; Delivery, returns and downloads) */
.prose { display: grid; gap: var(--s5); max-width: calc(var(--measure) + 2 * var(--pad)); padding: 0 var(--pad) var(--s7); }
.prose p { text-box: trim-both cap alphabetic; }
.prose h2 { color: var(--mute); }
.prose h2:not(:first-child) { margin-top: var(--s5); }
/* the small print: the company's name and number, 48px under the last paragraph, as far as a new heading is */
.prose__fine { margin-top: var(--s5); color: var(--mute); font: var(--fine); }

/* ---------------------------------------------------------------- About: a photo and the words. Side by side from 600px,
   inside the page's margins, 48px into the section (or 24px under the About page's bar), both from the top, as a
   single's block (music.css). Its heading on Home 16px over the words. On the About page the paragraphs 24px apart, as
   running text's are (.prose), and the marks (frame.css .icons) 32px under them (the tag line went, Antony, topic
   5845 msg 8510). */
.photo { width: 100%; aspect-ratio: 1; object-fit: cover; filter: grayscale(1) contrast(1.1); background: var(--tile); }
.about__txt { display: grid; gap: var(--s4); justify-items: start; align-content: start; padding: var(--s6) var(--pad) var(--s7); }
.about__txt > p { max-width: var(--measure); text-box: trim-both cap alphabetic; }
.about__txt strong { font-weight: 650; }  /* his mantra in bold (msg 8540), at the weight of the site's labels (--caps) */
.about__txt > p + p { margin-top: calc(var(--s5) - var(--s4)); }
.about__txt > .icons { margin-top: calc(var(--s6) - var(--s4)); }
/* a row of photos, edge to edge, 2px apart; the section's tone shows for 48px above and under them, so a dark photo
   never runs straight into About's photo above or the footer below */
.pics { padding-block: var(--s7); }
.pics__grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--gap); }

/* ---------------------------------------------------------------- a notice in a ruled box */
.notice { display: grid; gap: var(--s5); justify-items: start; padding: var(--s5); border: var(--rule) solid var(--line); border-radius: var(--r); }
.notice:has(> .link:last-child) { padding-bottom: calc(var(--s5) + var(--s1) + var(--rule)); }  /* 24px under the link's underline (4px under its letters, 1px thick), as above the words */
.notice > p { text-box: trim-both cap alphabetic; }

@media (min-width: 600px) {
  /* the photo and the words from the top, the first line's capitals level with the photo's top, never touching the
     section above (Antony, topic 5845 msg 7957): the single's block's rule (music.css); the photos three across, so
     none fills a tablet's width */
  .about__txt { padding: 0; }
  .pics__grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
