/* looks.css — what every page of PrintCard shares: the faces, the
   brand's colours, light and dark, the masthead with the logo, the
   site's links and the choice of light or dark, and the buttons. The card
   page adds style.css; the prices page, prices.css;
   the account and admin pages, the app's own app.css, which dresses
   rastrillo's components in these same colours. */

@font-face {
  font-family: "Archivo";
  src: url(fonts/archivo-latin-wdth-normal.woff2) format("woff2-variations");
  font-weight: 100 900;
  font-stretch: 62% 125%;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Archivo";
  src: url(fonts/archivo-latin-ext-wdth-normal.woff2) format("woff2-variations");
  font-weight: 100 900;
  font-stretch: 62% 125%;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* PrintCard: ink on warm paper, as the logo is printed, with vermilion
   for what is chosen: the cells, the step you are at, the side showing;
   and green for the way on: the button to press, the Continue pill,
   every step on the happy path to an order. Dark,
   the paper is a warm black and the ink a warm white.

   Each colour that differs is light-dark(<light>, <dark>), and the one
   :root sets color-scheme: light dark, so the page follows the device;
   the two rules after it pin one or the other when someone chooses
   (theme.js sets data-theme). rastrillo's theme.css, under the app's
   pages, toggles the same way on the same attribute.

   The logo's vermilion (#d8442b) is too light for small type on paper
   (4.1:1) or under white type (4.4:1), so what is filled in light is a
   deeper one (#b8361f: 5.5:1 on the paper, 5.9:1 under white). Dark, the
   brand's lighter vermilion (#f0684f) is filled, with the dark ground's
   colour on it (5.9:1). The logo's own is the accent, for the empty
   frame's call and the drop outline, both large.

   The green is held to the same marks: #1b7343 is 5.5:1 on the paper
   and 5.9:1 under white, and the focus ring clears it at 3.2:1; dark,
   #36a45f carries the ground's colour at 5.7:1 and the white focus ring
   clears it at 3.2:1, so the one green is only ever the way forward.

   Danger is a red of its own, crimson rather than the vermilion, so a
   button that deletes is never mistaken for a chosen cell: #c8102e
   carries white at 5.9:1; dark, #ff6b7f carries the ground's colour at
   6.6:1.

   The sheet, the empty frame on it, the inside of the card and the
   fields are paper in both: they are what prints, or labels laid on
   the page. */
:root {
  --ground: light-dark(#fbf6ec, #1c1a17);
  --wrapper-deep: light-dark(#efe9e1, #211f1c);
  --on: light-dark(#1f1c19, #f2ece2);
  --on-soft: light-dark(#5e5953, #b5afa6);
  --rule: light-dark(#8c857c, #7d766d);
  --hover: light-dark(rgb(35 33 31 / 0.06), rgb(244 241 234 / 0.08));
  --pale: #f6efe7;
  --pale-hover: #f0e5da;
  --shade: 35 33 31;
  --radius: 3px;
  --serif: "EB Garamond", "Iowan Old Style", "Palatino Linotype", Palatino, Georgia, serif;
  --sans: "Archivo", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --display: var(--sans);
  --display-weight: 750;
  --display-stretch: 100%;
  --label-stretch: 100%;
  --size-stretch: 78%;
  --size-font: 2.1rem;
  --body-size: 17px;
  --accent: #d8442b;
  --logo-red: light-dark(#d8442b, #f0684f);
  --chosen: light-dark(#b8361f, #f0684f);
  --chosen-ink: light-dark(#fff, #171614);
  --chosen-soft: light-dark(#fde8e1, #3a1810);
  --go: light-dark(#1b7343, #36a45f);
  --go-ink: light-dark(#fff, #171614);
  --go-soft: light-dark(#e3f3ea, #0b2416);
  --danger: light-dark(#c8102e, #ff6b7f);
  --danger-ink: light-dark(#fff, #171614);
  /* Clear of a vermilion cell as of the ground: 3.2:1 and 17.8:1 in
     light, 3.1:1 and 18:1 in dark. */
  --focus: light-dark(#12100f, #fff);
  --select: var(--chosen);
  --select-ink: var(--chosen-ink);
  --field: #fff;
  --field-ink: #23211f;
  --field-soft: #5e5953;
  --strip: light-dark(#fff, #211f1c);
  --strip-ink: light-dark(#23211f, #f4f1ea);
  --strip-rule: light-dark(#8c857c, #7d766d);
  --strip-hover: light-dark(rgb(35 33 31 / 0.06), rgb(244 241 234 / 0.08));
  --strip-off: light-dark(#6f6962, #a8a197);
  --action: light-dark(#23211f, #f4f1ea);
  --action-ink: light-dark(#faf8f4, #171614);
  --action-hover: var(--chosen);
  /* The preview's sides, all seen: the same green as the way on. */
  --all-seen: var(--go);
  --all-seen-ink: var(--go-ink);
  --stack-1: #ece6dd;
  --stack-2: #ddd5ca;
  --leaf-in: #fff;
  --leaf-in-shade: #eee8e0;
  --fold-line: rgb(35 33 31 / 0.25);
  color-scheme: light dark;
  scrollbar-color: var(--rule) var(--ground);
}
:root[data-theme="light"] { color-scheme: light; }
:root[data-theme="dark"] { color-scheme: dark; }
/* Shadows are an rgb() triple, which light-dark() cannot pick. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) { --shade: 0 0 0; }
}
:root[data-theme="dark"] { --shade: 0 0 0; }

/* Riso: the site printed in two inks on paper, as a risograph prints,
   a theme over the layout rather than a new one. The page around
   everything is the vermilion field; the masthead is a band of the
   dark ink, with the light paper's type on it; and each page's content
   is a sheet of that paper laid over the band's foot. A halftone screen
   of a deeper shade fades across the field and the band, and paper
   grain lies over the field. Text never sits on the screen: the sheet
   has none behind it.

   The sheet is the ground every component already knows (--ground), so
   they keep their colours on it. The band is the masthead, which
   redefines the ground and the ink for what is in it (its steps, its
   menus). It draws the top of the sheet itself, as its foot, so the
   sheet seems to overlap it while the masthead still lies over the page
   for its menus to open over it. The dot screen and the grain are
   decoration: they are under everything, and take no pointer.

   The screen's colours are rgb() triples, which light-dark() cannot
   pick, so they change as --shade does. */
:root {
  --riso-field: light-dark(#e2462c, #7a2416);
  --band: light-dark(#1f1c19, #0e0d0c);
  --band-ink: light-dark(#fbf6ec, #f2ece2);
  --sheet: var(--ground);
  --dot-ink: 110 22 6;
  --band-dot: 251 246 236;
  --dot: 9px;
  --sheet-overlap: 2.25rem;
  --sheet-gap: clamp(0.5rem, 3vw, 3rem);
  /* How wide the sheet may be: the page, for the card page, or one of
     three widths a page names on its body (data-sheet), in the middle:
     narrow for a form on its own, medium for most pages, wide for two
     columns or a list. */
  --sheet-max: 1000rem;
  --grain: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='220' height='220'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/><feColorMatrix values='1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 1'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>");
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) { --dot-ink: 20 4 0; --band-dot: 242 236 226; }
}
:root[data-theme="dark"] { --dot-ink: 20 4 0; --band-dot: 242 236 226; }
/* On a phone, the sheet is the width of the screen and the band
   overlaps it less: the card needs the room, and a finger near the edge
   of a picture takes hold of it there. */
@media (max-width: 40rem) { :root { --sheet-overlap: 1rem; --sheet-gap: 0px; } }

* { box-sizing: border-box; }

::selection { background: var(--select, var(--focus)); color: var(--select-ink, var(--strip-ink)); }

body {
  margin: 0;
  background: var(--ground);
  color: var(--on);
  font: 400 var(--body-size)/1.5 var(--sans);
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  -webkit-font-smoothing: antialiased;
  overflow-x: clip;
}

/* The field: vermilion, its screen fading in towards the foot, and the
   paper's grain over it, fixed behind the page as it scrolls. html body
   outranks rastrillo's own body ground on the app's pages; html has the
   field too, so the body keeps its own, for the grain to blend with. */
html,
html body { background: var(--riso-field); }
body[data-sheet="narrow"] { --sheet-max: 34rem; }
body[data-sheet="medium"] { --sheet-max: 48rem; }
body[data-sheet="wide"] { --sheet-max: 64rem; }
/* Worked out on the body, where the page names its width. */
body { --sheet-inset: max(var(--sheet-gap), calc((100% - var(--sheet-max)) / 2)); }
/* The sheet is as tall as what is on it, the field below; but for a
   step's, which runs on into the step's foot. */
body:not(.steps) > main { flex: none; }
body { isolation: isolate; }
body::before,
body::after { content: ""; position: fixed; inset: 0; z-index: -1; pointer-events: none; }
body::before {
  background: radial-gradient(circle, rgb(var(--dot-ink) / 0.55) 24%, transparent 28%) 0 0 / var(--dot) var(--dot);
  mask: linear-gradient(170deg, transparent 15%, #000 85%);
}
body::after { background: var(--grain); opacity: 0.55; mix-blend-mode: overlay; }
/* The sheet: every page's content, on the paper, inset from the field,
   its top drawn by the band (.masthead::after). */
body > main,
body > main[rst-page] {
  width: auto;
  max-width: none;
  margin: 0 var(--sheet-inset) var(--sheet-gap);
  background: var(--sheet);
  border-radius: 0 0 6px 6px;
  box-shadow: 0 24px 48px -24px rgb(0 0 0 / 0.45);
}

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.icon {
  width: 1.25rem;
  height: 1.25rem;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.75;
  stroke-linecap: round;
  stroke-linejoin: round;
}

:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }

/* The top of the wrapper, the same on every page: the name large and
   wide, the way round the site, and light or dark. */
/* The masthead: one compact row, the name small at its left and the way
   round the site at its right; on a step of making a card, the steps in
   a row of their own beneath. It lies over what it opens. */
.masthead {
  position: relative;
  z-index: 30;
  flex: none;
  padding: 0 clamp(1rem, 4vw, 2rem);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  column-gap: 1.25rem;
  /* The band: the dark ink, grained, its own ground and ink for what is
     in it, and room at its foot for the top of the sheet. */
  --ground: var(--band);
  --on: var(--band-ink);
  --on-soft: rgb(var(--band-dot) / 0.72);
  --rule: rgb(var(--band-dot) / 0.4);
  --hover: rgb(var(--band-dot) / 0.1);
  --focus: var(--band-ink);
  padding-bottom: var(--sheet-overlap);
  background: var(--grain), var(--band);
  background-blend-mode: overlay, normal;
  color: var(--band-ink);
}
/* The band's screen, fading in towards its right, and gone before the
   sheet; and the top of the sheet, laid over the band's foot. */
.masthead::before,
.masthead::after { content: ""; position: absolute; z-index: -1; pointer-events: none; }
.masthead::before {
  inset: 0;
  background: radial-gradient(circle, rgb(var(--band-dot) / 0.3) 24%, transparent 28%) 0 0 / var(--dot) var(--dot);
  mask: linear-gradient(90deg, transparent 30%, #000), linear-gradient(#000 50%, transparent);
  mask-composite: intersect;
}
.masthead::after {
  left: var(--sheet-inset);
  right: var(--sheet-inset);
  bottom: 0;
  height: var(--sheet-overlap);
  background: var(--sheet);
  border-radius: 6px 6px 0 0;
}
.masthead .name { margin: 0; display: flex; align-items: center; min-height: 3.25rem; color: inherit; text-decoration: none; }
/* The name: the PrintCard lockup, the card with the hills cut out of
   it and the name beside it, between crop marks, inline so it takes the
   page's colours. The marks, the card's back and "Print" are the text
   colour; the card's face and "Card" are vermilion, the lighter one the
   brand keeps for dark grounds when the page is dark. */
.logo {
  display: block;
  height: 2.75rem;
  width: auto;
  aspect-ratio: 354.18 / 108;
}
.logo-red { fill: var(--logo-red); }
/* The crop marks, bolder than the logo draws them: at the masthead's
   size they would be under a pixel. */
.logo-marks { stroke: currentColor; stroke-width: 2; }

/* The way round the site, as quiet links: no border, a wash on hover
   or while its menu is open, and the page you are on underlined. */
.site-nav { display: flex; flex-wrap: wrap; gap: 0.25rem; margin-left: auto; }
.masthead-link {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  min-height: 2.75rem;
  padding: 0.4rem 0.7rem;
  border-radius: var(--radius);
  font: 650 0.9375rem var(--sans);
  color: var(--on);
  text-decoration: none;
  cursor: pointer;
  transition: background-color 0.15s;
}
.masthead-link:hover, .menu[open] > .masthead-link { background: var(--hover); }
/* How many cards are in the cart, beside its link. */
.cart-count {
  min-width: 1.5em;
  padding: 0.05em 0.45em;
  border-radius: 999px;
  background: var(--on);
  color: var(--ground, #fff);
  font-size: 0.8125em;
  font-variant-numeric: tabular-nums;
  text-align: center;
  line-height: 1.4;
}
.masthead-link:is([aria-current], [data-here]),
.masthead-link:is([aria-current], [data-here]) > .masthead-word {
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-underline-offset: 0.4em;
}
/* A link with a word of its own, as Cart has beside its count, is
   underlined under the word alone. */
.masthead-link:is([aria-current], [data-here]):has(> .masthead-word) { text-decoration: none; }
/* On a big screen the masthead is in proportion to the page under it:
   the name larger, the row taller, and the links a step up. */
@media (min-width: 72rem) {
  .masthead { column-gap: 1.75rem; }
  .masthead .name { min-height: 6.5rem; padding-block: 0.75rem; }
  .logo { height: 4.75rem; }
  .masthead-link { font-size: 1.125rem; padding-inline: 0.85rem; }
}

/* The masthead's menus: a <details>, its summary one of those links with
   a chevron, opening a panel in the page's own ground under it. */
.menu { position: relative; }
.menu > summary { list-style: none; }
.menu > summary::-webkit-details-marker { display: none; }
.menu > summary::after {
  content: "";
  width: 0.42em;
  height: 0.42em;
  margin: -0.25em 0.1em 0 0.1em;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(45deg);
  transition: transform 0.15s;
}
.menu[open] > summary::after { margin-top: 0.25em; transform: rotate(225deg); }
.menu-items {
  position: absolute;
  top: calc(100% + 0.4rem);
  right: 0;
  z-index: 10;
  display: flex;
  flex-direction: column;
  min-width: 11rem;
  padding: 0.35rem;
  border: 1.5px solid var(--rule);
  border-radius: var(--radius);
  background: var(--ground);
  box-shadow: 0 0.5rem 1.5rem rgb(0 0 0 / 0.2);
}
.menu-items form { display: contents; }
.menu-items :is(a, button) {
  appearance: none;
  border: 0;
  background: none;
  font: inherit;
  text-align: left;
  cursor: pointer;
  padding: 0.6rem 0.75rem;
  border-radius: var(--radius);
  color: var(--on);
  font-weight: 650;
  text-decoration: none;
}
.menu-items :is(a, button):hover { background: var(--hover); }
.menu-items > a[aria-current] { background: var(--chosen); color: var(--chosen-ink); }

/* Light, dark, or as the device is: three choices in a menu, whose
   button wears the icon of the one chosen. Without JavaScript nothing
   is chosen, and the page is as the device is. */
.themes label {
  position: relative;
  display: flex;
  align-items: center;
  gap: 0.65rem;
  padding: 0.55rem 0.75rem;
  border-radius: var(--radius);
  color: var(--on-soft);
  font-weight: 650;
  cursor: pointer;
}
.themes input { position: absolute; opacity: 0; pointer-events: none; }
.themes label:hover { background: var(--hover); color: var(--on); }
.themes label:has(input:checked) { background: var(--chosen); color: var(--chosen-ink); }
.themes label:has(input:focus-visible) { outline: 3px solid var(--focus); outline-offset: 1px; }
.theme-now { display: none; }
:root:not([data-theme]) .theme-now[data-for="system"],
:root[data-theme="system"] .theme-now[data-for="system"],
:root[data-theme="light"] .theme-now[data-for="light"],
:root[data-theme="dark"] .theme-now[data-for="dark"] { display: contents; }

/* The nine steps of making a card, along the top of each of them, in the
   masthead, joined by a line that is inked up to the step you are at. Each is a circle and
   a short name: a step done is a solid circle with a tick, which pops in
   and draws itself as it is done; the step you are at sits in a solid
   pill, which slides from step to step (steps.js; without it, the step
   itself is solid); one not open yet is faded, its circle dashed, and
   chosen, it shakes and says why. */
.card-steps { position: relative; }
.card-steps ol { position: relative; display: flex; align-items: center; margin: 0; padding: 0; list-style: none; }
/* The steps take the whole width: the lines between them stretch, from
   a short dash, each dashed, and inked along as the step is reached. */
.card-steps li { position: relative; display: flex; align-items: center; flex: none; }
.card-steps li + li { flex: 1 1 auto; }
.card-steps li + li::before {
  content: "";
  flex: 1 1 6px;
  min-width: 6px;
  height: 2px;
  margin-inline: 2px;
  background:
    linear-gradient(var(--on), var(--on)) left / 0% 100% no-repeat,
    repeating-linear-gradient(90deg, var(--rule) 0 4px, transparent 4px 7px);
  transition: background-size 0.3s ease;
}
/* Making the card, then ordering it: a longer line between the two. */
.card-steps li.group-start::before { min-width: 16px; }
.card-steps li.reached::before { background-size: 100% 100%, auto; }
/* Each name long, middling or short, the longest the width has room for
   (steps.js); the middling one without it. */
.card-steps [data-fit] { display: none; }
.card-steps:not([data-fit]) [data-fit~="mid"],
.card-steps[data-fit="full"] [data-fit~="full"],
.card-steps[data-fit="mid"] [data-fit~="mid"],
.card-steps[data-fit="tight"] [data-fit~="tight"] { display: inline; }
.card-steps a {
  position: relative;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 2.75rem;
  padding: 0 0.7rem 0 0.4rem;
  border-radius: 999px;
  color: var(--on);
  font: 600 0.875rem/1.2 var(--sans);
  text-decoration: none;
  white-space: nowrap;
  transition: color 0.25s ease 0.1s, background-color 0.15s;
}
.card-steps a[href]:not([aria-current]):hover { background: var(--hover); }
.card-steps a:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }
.card-step-n {
  display: grid;
  place-items: center;
  flex: none;
  box-sizing: border-box;
  width: 1.375rem;
  height: 1.375rem;
  border: 2px solid currentColor;
  border-radius: 50%;
  font: 700 0.72rem/1 var(--sans);
  transition: border-color 0.25s ease 0.1s, color 0.25s ease 0.1s;
}
.card-step-n svg { display: none; width: 11px; height: 11px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.card-steps li.done .card-step-n { background: var(--on); border-color: var(--on); color: var(--ground); }
.card-steps li.done .card-step-n > span { display: none; }
.card-steps li.done .card-step-n svg { display: block; }
.card-steps li.just-done .card-step-n { animation: card-step-pop 0.4s ease-out; }
.card-steps li.just-done .card-step-n path { stroke-dasharray: 12; stroke-dashoffset: 12; animation: card-step-draw 0.35s 0.15s ease-out forwards; }
.card-steps a[aria-current] { background: var(--chosen); color: var(--chosen-ink); }
.card-steps a[aria-disabled] { color: var(--on-soft); cursor: not-allowed; }
.card-steps a[aria-disabled] .card-step-n { border-style: dashed; }
.card-steps a.nudged { animation: card-step-nudge 0.4s ease; }
/* The pill, under the step you are at, once steps.js has put it there. */
.card-steps li.card-steps-pill { display: none; }
.card-steps.sliding li.card-steps-pill {
  position: absolute;
  z-index: 0;
  display: block;
  border-radius: 999px;
  background: var(--chosen);
  pointer-events: none;
  transition: left 0.5s cubic-bezier(0.34, 1.45, 0.55, 1), width 0.5s cubic-bezier(0.34, 1.45, 0.55, 1);
}
.card-steps li.card-steps-pill::before { display: none; }
.card-steps.sliding a[aria-current] { background: transparent; }
/* Why a step is not open yet, under it for a moment. */
.card-steps-tip {
  position: absolute;
  z-index: 5;
  margin: 0;
  translate: -50% 0;
  white-space: nowrap;
  background: var(--on);
  color: var(--ground);
  font: 500 0.8125rem/1.2 var(--sans);
  padding: 0.4rem 0.65rem;
  border-radius: 6px;
  pointer-events: none;
  animation: card-step-tip 0.2s ease-out;
}
.card-steps-tip[hidden] { display: none; }
@keyframes card-step-draw { to { stroke-dashoffset: 0; } }
@keyframes card-step-pop { 0% { transform: scale(0.4); } 60% { transform: scale(1.18); } 100% { transform: scale(1); } }
@keyframes card-step-nudge { 0%, 100% { transform: translateX(0); } 20% { transform: translateX(-4px); } 40% { transform: translateX(4px); } 60% { transform: translateX(-3px); } 80% { transform: translateX(2px); } }
@keyframes card-step-tip { from { opacity: 0; translate: -50% -4px; } to { opacity: 1; translate: -50% 0; } }
@media (prefers-reduced-motion: reduce) {
  .card-steps *, .card-steps-tip, .step-helper { animation: none !important; transition: none !important; }
}
/* In the masthead, a row of its own beneath the rest. */
.masthead .card-steps { order: 3; flex: 1 1 100%; min-width: 0; padding-bottom: 0.25rem; }
/* Where even the short names leave no room, only the step you are at
   is named, and then none is: the rest are their circles alone, drawn
   closer, so the nine fit across a phone without scrolling (steps.js).
   Without it, a phone names only the step you are at. */
.card-steps:is([data-fit="current"], [data-fit="bare"]) a { padding-inline: 2px; }
.card-steps[data-fit="current"] a[aria-current] { padding-right: 0.6rem; }
.card-steps[data-fit="current"] [data-fit~="tight"] { display: inline; }
.card-steps[data-fit="current"] li:not(:has(> a[aria-current])) .card-step-name,
.card-steps[data-fit="bare"] .card-step-name { display: none; }
.card-steps:is([data-fit="current"], [data-fit="bare"]) li + li::before { min-width: 4px; margin-inline: 0; }
/* Narrower than even that, they scroll, as a last resort. */
@media (max-width: 52rem) {
  .card-steps ol { overflow-x: auto; scrollbar-width: none; }
}
@media (max-width: 40rem) {
  .card-steps:not([data-fit]) a { padding-inline: 2px; }
  .card-steps:not([data-fit]) a[aria-current] { padding-right: 0.6rem; }
  .card-steps:not([data-fit]) li:not(:has(> a[aria-current])) .card-step-name { display: none; }
  .card-steps:not([data-fit]) li + li::before { min-width: 4px; margin-inline: 0; }
}

/* Back and next along the foot of each step (design option 5c): a quiet
   way back to the step before, by its number and name; one strong pill on
   to the next, with that step's number in its circle, as in the steps
   above, standing up out of the foot; and along its very edge, a line of
   nine, filled up to the step you are at. Not open yet, the pill is
   dashed and faded, says beside it why, and shakes when it is pressed.
   It is the width of the page at every step; the page between it and the
   masthead scrolls (body.steps). */
.step-nav {
  position: relative;
  z-index: 20;
  flex: none;
  display: flex;
  flex-direction: column;
  background: var(--ground);
  border-top: 2px solid var(--rule);
}
.step-progress { order: 2; display: flex; gap: 3px; }
.step-progress i { flex: 1; height: 4px; background: var(--rule); opacity: 0.4; }
.step-progress i.on { background: var(--on); opacity: 1; }
.step-moves { display: flex; align-items: center; gap: 0.75rem 1rem; min-height: 2.75rem; padding: 0 clamp(1rem, 4vw, 4rem); }
.step-return {
  appearance: none;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  min-height: 2.75rem;
  padding: 0 0.25rem;
  border: 0;
  background: none;
  color: var(--on);
  font: 700 0.875rem var(--sans);
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
}
.step-return:hover { text-decoration: underline; text-underline-offset: 0.2em; }
.step-return:focus-visible, .step-continue:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }
.step-chevron { font-size: 1.15em; line-height: 1; }
.step-count { font-size: 0.875rem; color: var(--on-soft); }
.step-ahead { position: absolute; right: clamp(1rem, 4vw, 4rem); bottom: 14px; display: flex; align-items: flex-end; justify-content: flex-end; gap: 0.5rem 0.9rem; }
/* The reason a step is not open yet. Where there is no pill at all (the
   delivery and payment steps without an address or an approved
   account), it stands in the foot's row, level with the step count on
   the left: the row is 2.75rem tall and starts 4px (the progress bars)
   above the nav's bottom, 10px below the pill's. */
.step-helper { display: flex; align-items: center; min-height: 2.75rem; margin-bottom: -10px; max-width: 18rem; font-size: 0.875rem; line-height: 1.35; color: var(--on-soft); text-align: right; text-wrap: balance; }
.step-helper:empty { display: none; }
/* Beside a pill, it is an ink tip on the pill's top, as the masthead's
   tip under a step is, and hops with the pill's shake when the pill is
   pressed. */
.step-ahead { position: absolute; }
.step-ahead:has(.step-continue:not([hidden])) .step-helper {
  position: absolute;
  right: 0.9rem;
  bottom: calc(100% + 0.5rem);
  z-index: 5;
  min-height: 0;
  margin: 0;
  max-width: none;
  white-space: nowrap;
  background: var(--on);
  color: var(--ground);
  font: 500 0.8125rem/1.2 var(--sans);
  padding: 0.4rem 0.65rem;
  border-radius: 6px;
  pointer-events: none;
}
.step-helper.nudged { animation: step-helper-hop 0.45s ease; }
@keyframes step-helper-hop { 0%, 100% { translate: 0 0; } 25% { translate: 0 -7px; } 55% { translate: 0 0; } 75% { translate: 0 -3px; } }
.step-continue {
  appearance: none;
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  min-height: 3.375rem;
  padding: 0 1.4rem 0 1.7rem;
  border: 2px solid var(--go);
  border-radius: 999px;
  background: var(--go);
  color: var(--go-ink);
  box-shadow: 0 0 0 4px var(--ground);
  font: 500 1rem var(--sans);
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color 0.25s, color 0.25s, border-color 0.25s;
}
.step-continue:hover { --hover-fill: color-mix(in srgb, var(--go) 82%, var(--go-ink)); background: var(--hover-fill); border-color: var(--hover-fill); }
.step-continue .card-step-n { width: 1.375rem; height: 1.375rem; }
.step-continue .card-step-n svg { display: block; }
.step-continue-name { margin-left: -0.25rem; font-weight: 700; }
/* Not open yet, the pill is still the ground's colour inside, or the
   foot's rule would run straight through it. */
.step-continue[aria-disabled], .step-continue[aria-disabled]:hover { background: var(--ground); border-style: dashed; border-color: var(--rule); color: var(--on-soft); cursor: not-allowed; }
/* Save, on the preview, fills with green as the sides are seen, a
   quarter each: pressed, it turns the card to the next side to see.
   Its ink is the page's, readable on the ground and on the fill. */
@property --seen { syntax: '<percentage>'; inherits: false; initial-value: 0%; }
.step-continue.waiting, .step-continue.waiting:hover {
  --fill: color-mix(in srgb, var(--go) 55%, var(--ground));
  background: linear-gradient(to right, var(--fill) var(--seen), var(--ground) var(--seen));
  border-style: dashed;
  border-color: var(--go);
  color: var(--on);
  transition: --seen 0.5s ease, color 0.25s;
}
.step-continue.waiting[aria-disabled] { border-color: var(--rule); cursor: not-allowed; }
.step-continue.nudged > * { animation: card-step-nudge 0.4s ease; }
.step-continue-busy { display: none; font-weight: 600; }
.step-continue.busy > :not(.step-continue-busy) { display: none; }
.step-continue.busy .step-continue-busy { display: inline; }
.step-continue[hidden], .step-return[hidden], .step-count[hidden] { display: none; }

/* A step of making a card fills the window: the masthead at its top,
   back and next at its foot, and the page between them scrolls. On a
   narrow screen, where the masthead is taller, the page scrolls as a
   whole, back and next staying at the foot of the window, and the pill,
   without "Continue to", stands in the foot's row. */
body.steps { height: 100svh; min-height: 0; }
body.steps > main { flex: 1 1 auto; min-height: 0; overflow: auto; padding-bottom: 2.5rem; }
/* On the card page on a phone, the sheet runs on into the foot, which
   is the paper too, and the band's foot is its top margin: the card has
   the room it had before the field and the band were there. The ordering steps,
   whose pages name a width, are as tall as what is on them, and scroll
   within the sheet when that is more than the window. */
body.steps:not([data-sheet]) > main { margin-bottom: 0; border-radius: 0; padding-top: 0; box-shadow: none; }
body.steps[data-sheet] > main { flex: 0 1 auto; }
body.steps > .step-nav { margin-top: auto; }
/* On the card page, the sheet is only as big as the step's own column,
   with room either side, and as tall as what is on it: choosing the
   card, its 32rem; a side, the 46rem its heading, its tools and the
   side share (style.css); previewing, the card standing as style.css
   sizes it for the window, or the sides' bar if that is wider, with the
   chevrons on the sheet's edges, half on and half off. On a phone the
   sheet is the screen's, as before. */
@media (min-width: 52.01rem) {
  body.steps:not([data-sheet]) {
    --step-pad: 3rem;
    --step-w: 46rem;
    --sheet-max: calc(var(--step-w) + 2 * var(--step-pad));
    /* Nothing within the sheet scrolls, for the chevrons hang off it:
       the page scrolls instead, if it must, the foot staying at the
       bottom of the window. */
    height: auto;
    min-height: 100svh;
  }
  body.steps:has(.workspace[data-step="card"]) { --step-w: 32rem; }
  body.steps:not([data-sheet]) > main.workspace[data-step="card"] { padding-bottom: 2rem; }
  body.steps:has(.workspace.grown) {
    --step-w: max(30rem, min(88rem, calc((100svh - 29rem) * 1.4286)));
  }
  body.steps:has(.workspace.grown .canvas[data-shape="landscape"]) {
    --step-w: max(30rem, min(56rem, calc((100svh - 27rem) * 1.6 * 0.7)));
  }
  body.steps:not([data-sheet]) > main { flex: 0 1 auto; overflow: visible; padding-bottom: 0; margin-bottom: var(--sheet-gap); border-radius: 0 0 6px 6px; box-shadow: 0 24px 48px -24px rgb(0 0 0 / 0.45); }
  body.steps:not([data-sheet]) > .step-nav { position: sticky; bottom: 0; }
  body.steps:not([data-sheet]) .workspace { padding-inline: var(--step-pad); }
  body .workspace.grown .canvas[data-shape] { --sheet-w: 100%; }
  /* A side as style.css sizes it, less the field showing under the
     sheet, now that the sheet no longer squeezes to fit the window. */
  body .workspace:not([data-step="preview"]) .canvas { --sheet-w: min(100%, 46rem, calc((100svh - 27rem) * var(--face-ratio, 0.7))); }
  .workspace.grown .chevron.prev { left: calc(-1 * var(--step-pad) - 1.625rem); }
  .workspace.grown .chevron.next { right: calc(-1 * var(--step-pad) - 1.625rem); }
}
@media (max-width: 52rem) {
  body.steps { height: auto; min-height: 100svh; }
  body.steps > main { overflow: visible; }
  .step-nav { position: sticky; bottom: 0; }
  .step-moves { justify-content: space-between; padding-block: 0.4rem; }
  .step-ahead { position: static; margin-left: auto; }
  .step-continue { min-height: 2.9rem; padding: 0 1rem 0 0.9rem; box-shadow: none; }
  .step-continue > :first-child:not(.card-step-n) { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
  .step-helper { display: none; }
}
/* On a phone, back is only the step's number and name, and Delete draft
   only its icon; each still says it all to a screen reader. */
@media (max-width: 30rem) {
  .step-moves { gap: 0.75rem; }
  .step-return-to, .step-restart-name { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
}

/* A question asked over the page, before something goes for good: the
   card page's Delete draft, and the landing page's. A sheet of the
   page's paper, ruled at the top, over the page dimmed behind it. */
.confirm-dialog {
  width: min(32rem, calc(100vw - 2rem));
  max-height: calc(100dvh - 2rem);
  padding: 1.25rem 1.5rem 1.5rem;
  border: 0;
  border-top: 4px solid var(--on);
  border-radius: var(--radius);
  background: var(--ground);
  color: var(--on);
  box-shadow: 0 1.5rem 3rem rgb(var(--shade) / 0.3);
}
.confirm-dialog::backdrop { background: rgb(var(--shade) / 0.45); }
.confirm-dialog h2 { margin: 0; }
.confirm-dialog p { margin: 0.5rem 0 0; line-height: 1.5; }
/* Its buttons sit to the right, the way out first and the button that
   does it last, at the right-hand end, as confirm-form's do. */
.confirm-dialog .confirm-actions { display: flex; flex-wrap: wrap; justify-content: flex-end; align-items: center; gap: 0.75rem; margin-top: 1.5rem; }
.confirm-actions .icon { width: 1.1rem; height: 1.1rem; }
@media (prefers-reduced-motion: no-preference) {
  .confirm-dialog[open] { animation: confirm-in 200ms var(--ease-out); }
  @keyframes confirm-in { from { opacity: 0; transform: translateY(0.75rem); } }
}

.button {
  appearance: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.55rem;
  min-height: 2.75rem;
  font: 650 1rem var(--sans);
  padding: 0.6rem 1rem;
  border-radius: var(--radius);
  border: 1.5px solid var(--rule);
  background: transparent;
  color: var(--on);
  cursor: pointer;
  text-align: center;
  transition: background-color 0.15s, border-color 0.15s, color 0.15s, transform 0.1s var(--ease-out);
}
.button:hover { border-color: var(--on); background: var(--hover); }
.button:active { transform: translateY(1px); }
.button:disabled { opacity: 0.45; cursor: default; transform: none; }
.button[hidden] { display: none; }
.button:disabled:hover { border-color: var(--rule); background: transparent; }
a.button { text-decoration: none; }
/* The button that does what a dialog is for, solid ink, last. */
.button-primary, .button-primary:hover { background: var(--on); border-color: var(--on); color: var(--ground); }
.button-primary:hover { filter: brightness(0.9); }
/* The one way on from a page, green as Continue is. */
.button-go, .button-go:hover { background: var(--go); border-color: var(--go); color: var(--go-ink); }
.button-go:hover { filter: brightness(0.9); }
.button-danger, .button-danger:hover { background: var(--danger); border-color: var(--danger); color: var(--danger-ink); }
.button-danger:hover { filter: brightness(0.9); }
.button:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }
/* The calculator in full where there is room; on a narrower screen,
   Prices. */
.narrow-only { display: none; }
/* On a narrower screen, the masthead closes up: the links nearer
   together, the name and light or dark on one line and, on a phone, the way
   round the site on a line of its own under them, its first link's word
   in line with the name. */
@media (max-width: 52rem) {
  .wide-only { display: none; }
  .narrow-only { display: inline; }
  .masthead { column-gap: 0.25rem; }
  .site-nav { gap: 0; }
  .masthead .masthead-link { padding-inline: 0.5rem; }
}
@media (max-width: 30rem) {
  .theme-menu { order: 1; margin-left: auto; }
  .site-nav { order: 2; flex-basis: 100%; margin: -0.25rem 0 0 -0.5rem; }
}

/* The draft card being made in this browser, in the masthead (the app's
   draft.js): its front, small, as a card standing on the band, and
   "Your draft". */
.draft-link[hidden] { display: none; }
.draft-link img { display: block; width: 1.1rem; height: auto; box-shadow: 0 0 0 1px rgb(var(--band-dot) / 0.5); background: #fff; }
.draft-link[data-shape="landscape"] img { width: 1.55rem; }

/* A card's reference, DES-K7QXMB: its letters evenly spaced, so it
   reads out as it is written. */
.design-ref { font-variant-numeric: tabular-nums; letter-spacing: 0.02em; white-space: nowrap; }
