/* The customer's view, and the shop's new-order cue. */

/*
 * A board in the room, hung at the bottom of the page. The plaque itself — the
 * wood, the padding and the edge — comes from room.css.
 *
 * It is a sibling of .page__body rather than a child, so left alone it runs the
 * full width of the viewport while every card above it stops at the content
 * column. These two lines put it back in line with them: .page__body is
 * --content-max wide with --space-4 of inline padding and border-box sizing, so
 * the cards inside it span that minus twice the padding, and so does this.
 */
.storefront-footer {
  width: calc(100% - var(--space-4) * 2);
  max-width: calc(var(--content-max) - var(--space-4) * 2);
  margin-inline: auto;
  text-align: center;
  color: var(--color-text-muted);
}

.storefront-footer p { margin: 0 0 var(--space-1); }

/*
 * The socials plaque: slim, a title and a row of tabs. Each tab is the board's
 * own raised tab (room.css), with the platform's mark beside its name. The row
 * wraps on a phone rather than shrinking the tabs below a thumb's width.
 */
.socials-plaque .card__title { margin-block-end: var(--space-2); }

.socials-plaque__list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin: 0;
  padding: 0;
  list-style: none;
}

.socials-plaque__tab {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: var(--tap-target);
  font-size: var(--text-sm);
}

.social-mark { flex: none; }

/* Not filled in yet: shown, so the shop's places online are on the board from
   the start, but dimmed and not pressable, so nobody follows it nowhere. */
.socials-plaque__tab--soon {
  opacity: 0.55;
  cursor: default;
}

/* The photo credits: one small word at the bottom left of the footer board,
   opening to the names and licences. Left-aligned, unlike the rest of the
   footer, so it reads as small print rather than as part of the sign. */
.storefront-footer__credits {
  margin-block-start: var(--space-2);
  font-size: var(--text-xs);
  text-align: start;
}

.storefront-footer__credits summary {
  display: inline-block;
  padding-block: var(--space-1);
  cursor: pointer;
  list-style: none;
  text-decoration: underline;
  text-underline-offset: 2px;
}

.storefront-footer__credits summary::-webkit-details-marker { display: none; }

.storefront-footer__credits p { margin: var(--space-1) 0 0; }

/* A choice a customer makes once, so it is a target rather than a radio dot. */
.choice {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  min-height: var(--tap-target-lg);
  padding: var(--space-3);
  margin-block-end: var(--space-2);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  cursor: pointer;
}

.choice:has(input:checked) {
  border-color: var(--color-action);
  background: var(--color-support);
}

.choice input { width: 1.5rem; height: 1.5rem; margin-block-start: 2px; }
.choice span { display: flex; flex-direction: column; }

/*
 * Agreement §3.8: where the order has got to. A step that has not happened is
 * shown as still to come rather than hidden — a customer wants to know what is
 * left, not just what is done.
 */
.timeline { list-style: none; margin: 0; padding: 0; }

.timeline__step {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-2) 0 var(--space-2) var(--space-5);
  position: relative;
  border-inline-start: 2px solid var(--color-border);
  margin-inline-start: var(--space-2);
}

.timeline__step::before {
  content: "";
  position: absolute;
  inset-inline-start: -7px;
  top: 1rem;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--color-canvas);
  border: 2px solid var(--color-border-strong);
}

.timeline__step--done { font-weight: 600; }
.timeline__step--done::before { background: var(--color-notice); border-color: var(--color-notice); }
.timeline__step--todo { color: var(--color-text-muted); }

.timeline__when { font-size: var(--text-sm); white-space: nowrap; }

/* ── The front page ─────────────────────────────────────────────────────── */

/*
 * The layout of the hero — the cut-out basket and the board beside it — lives in
 * room.css, because it only exists inside the room and it is written against the
 * plaque. What is left here is the type.
 */
.landing-hero__words h1 {
  margin: 0 0 var(--space-2);
  font-size: var(--text-2xl);
  text-wrap: balance;
}

.landing-hero__lead {
  max-width: 44ch;
  margin: 0 auto var(--space-4);
  font-size: var(--text-lg);
  text-wrap: pretty;
}

/* Three counters, side by side where there is room and stacked where there is
   not — the same rule as everywhere else on a phone. */
.landing-counters {
  display: grid;
  gap: var(--space-4);
  /* 15rem, not 16, so all four counters fit in one row at --content-max (4 x 15
     plus three gaps is 63rem, inside the 66 available). At 16 the fourth
     wrapped onto a row of its own. */
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  margin-block-end: var(--space-4);
}

.landing-counters .card { margin: 0; }

/*
 * The plaques under the hours: what this phone could still do. Side by side
 * where the column is wide enough, stacked on a phone. With both hidden —
 * the phone has everything already — the row takes no room at all.
 */
.device-plaques {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
}

/* A board's gap below it, like every other board — but only while there is a
   plaque to show, or an empty row would double the hours board's own. */
.device-plaques:has(> :not([hidden])) { margin-block-end: var(--space-4); }

/*
 * A plaque is a board you press, so it is a <button> with a button's defaults
 * undone: the board's lettering and alignment, not the system's. Inside a room
 * the plaque rule supplies the wood, exactly as it does for a counter.
 */
.device-plaque {
  flex: 1 1 12rem;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-1);
  margin: 0;
  font: inherit;
  color: inherit;
  text-align: start;
  cursor: pointer;
}

/* The tab at the foot of the plaque, the same one a counter has. Its auto
   margin takes up the slack on the shorter plaque of a row, so the two tabs
   line up along the bottom; the words above it keep a little extra room
   underneath, because the column's own gap is only --space-1. */
.device-plaque .counter__more { margin-block-start: auto; }
.device-plaque > .small:not(.counter__more) { margin-block-end: var(--space-2); }

/* A span, because a button may not hold a heading — so it takes the weight an
   h2 has from base.css by hand, or it reads fainter than the hours above it. */
.device-plaque .card__title { margin: 0; font-weight: 650; }

/*
 * A counter board IS a link, so it needs an anchor's defaults undone: no
 * underline across the whole board, and the board's own colour rather than the
 * link colour. Inside a room the plaque rule outranks this and supplies
 * --color-on-plaque; this is what holds if the board is ever seen without one.
 */
.counter {
  display: flex;
  flex-direction: column;
  color: var(--color-text);
  text-decoration: none;
}

/*
 * The picture in the top right corner of a counter's board, on the same row as
 * the counter's name. It was floated at first, with the blurb running around
 * it, but four boards in a row are only about 15rem each and the blurb was
 * squeezed into a column a few words wide. The name is short, so it shares the
 * row and the blurb keeps the board's full width below.
 *
 * Each image is a cut-out on a transparent 3:2 box, so it sits on the wood the
 * way the hero basket sits in the room, with the same shadow direction.
 */
.counter__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  margin-block-end: var(--space-3);   /* what .card__title had on its own */
}

.counter__head .card__title {
  margin-block-end: 0;
}

.counter__picture {
  flex: none;
  width: 6rem;
  height: auto;
  margin-block: calc(var(--space-2) * -1) 0;
  margin-inline-end: calc(var(--space-2) * -1);
  filter: drop-shadow(-3px 6px 8px rgb(0 0 0 / 40%));
}

/* The same picture on a counter's own title board, splashed across its right
   end: bigger than on the front page's board, and let out over the board's top
   and right edges so it reads as laid on the wood rather than boxed into it.
   The heading keeps the room it needs; the picture is what gives. */
.page-header--counter {
  flex-wrap: nowrap;
}

.page-header__picture {
  flex: none;
  width: 13rem;
  height: auto;
  margin-block: calc(var(--space-4) * -1);
  margin-inline-end: calc(var(--space-3) * -1);
  filter: drop-shadow(-3px 6px 8px rgb(0 0 0 / 40%));
}

@media (max-width: 30rem) {
  .page-header__picture { width: 7rem; }
}

/* The invitation at the foot of the board. It is no longer a link of its own —
   the board is — but it still has to LOOK like the way in, or a whole clickable
   card has no affordance at all.

   Pinned to the bottom right. The boards in a row are stretched to one height
   but their blurbs are not one length, so left where the blurb ends the four
   invitations sat at four different heights. margin-top: auto takes up the
   slack in the column above it. */
.counter__more {
  margin-block: auto 0;
  align-self: flex-end;
  color: var(--color-link);
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* O6 — laid out only when there is something in it. */
.storefront-footer__social {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin-block-start: var(--space-3);
}

/* ── A product, and its measures ──────────────────────────────────────────── */

/*
 * The tile is the product; the measures come when they are asked for. Every
 * measure of every product used to sit open at once, which on a counter of
 * thirty things is a wall of numbers to read past before finding the one you
 * came for.
 *
 * The tile needs to be a positioning context because the opener covers it.
 */
.good {
  position: relative;
}

/*
 * With a photograph the tile is words on the left and the picture on the right;
 * without one the words simply have the tile, which is why this is a modifier
 * and not the default. A product with no photograph is the normal case for a
 * long time and it has to look deliberate, not like a frame waiting to be
 * filled.
 */
.good--shown {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: var(--space-3);
}

.good__photo {
  width: 3rem;
  height: 3rem;
  object-fit: cover;
  border-radius: var(--radius-sm);
  box-shadow: inset 0 1px 0 var(--tab-bevel), -1px 2px 4px rgb(0 0 0 / 45%);
}

/* The sheet's own, a little larger, beside the name it belongs to. */
.sheet__photo {
  width: 3.5rem;
  height: 3.5rem;
  object-fit: cover;
  border-radius: var(--radius-sm);
  box-shadow: inset 0 1px 0 var(--tab-bevel), -1px 2px 4px rgb(0 0 0 / 45%);
}

/* The tiny one: the till, and a cart line. Set into the row rather than raised
   off it, because neither is something to press. */
.good__pip {
  width: 1.75rem;
  height: 1.75rem;
  object-fit: cover;
  border-radius: var(--radius-sm);
  vertical-align: -0.4em;
  margin-inline-end: var(--space-2);
}

/*
 * The whole tile is the target, not a word on it — the same decision as the
 * counter boards on the front page, and for the same reason: on a phone a link
 * inside a tile is a thumb-width target inside something ten times its size.
 *
 * Hidden in the markup and revealed by the controller, so a browser without
 * scripts never shows a button that cannot do anything.
 */
.good__opener {
  position: absolute;
  inset: 0;
  width: 100%;
  padding: 0;
  border: 0;
  border-radius: inherit;
  background: none;
  cursor: pointer;
}

/* ── The sheet ────────────────────────────────────────────────────────────── */

.sheet__category { margin: 0; font-size: var(--text-sm); }

/* A package's sheet: what it saves, the Add button, then the parts at what each
   costs on its own. No colour of its own anywhere — the saving is carried by
   size and weight in the board's lettering, which room.css has already
   measured, rather than a green drawn for paper that vanishes on wood. */
.sheet__saving { margin: 0 0 var(--space-3); font-size: var(--text-lg); font-weight: 700; }
.sheet__parts { margin-block: var(--space-3); }
.sheet__figures { margin: 0; }

/* ── Checkout, in steps ──────────────────────────────────────────────────── */

/*
 * Four short steps on one board instead of one long form (checkout_controller.js).
 * Nothing in here hides anything: the controller sets `hidden`, so a browser with
 * no scripts gets every step stacked — the whole form, as it always was.
 */
.checkout__basket {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-2);
  margin: 0 0 var(--space-4);
}

/*
 * How far along: a channel cut across the board with herb green growing along
 * it, dot to dot, toward the kiondo at the end. The green is the coriander in
 * the hero (tokens.css --color-herb). --progress runs from 0 to 1 and the
 * controller sets it; --steps is how many stops share the width.
 */
.checkout-progress {
  --steps: 4;
  --dot: 1.75rem;
  --herb: var(--color-herb);
  --progress: 0;
  position: relative;
  display: grid;
  grid-template-columns: repeat(var(--steps), 1fr);
  margin: 0 0 var(--space-5);
  padding: 0;
  list-style: none;
}

/* The channel, then the green in it — both from the first stop's centre to the
   last one's. */
.checkout-progress::before,
.checkout-progress::after {
  content: "";
  position: absolute;
  inset-block-start: calc(var(--dot) / 2 - 2px);
  inset-inline-start: calc(50% / var(--steps));
  height: 4px;
  border-radius: 2px;
}

/* Cut across the grain like the rules between lines (room.css): the channel's
   floor in shadow, a lit lip along its lower wall. */
.checkout-progress::before {
  width: calc(100% - 100% / var(--steps));
  background: var(--relief-shadow);
  box-shadow: 0 1px 0 var(--relief-light);
}

.checkout-progress::after {
  width: calc((100% - 100% / var(--steps)) * var(--progress));
  background: var(--herb);
}

.checkout-progress__step {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-1);
  font-size: var(--text-sm);
  text-align: center;
}

/*
 * A hole drilled into the board: the same wood, sunk, its upper-right wall in
 * shadow and a lit lip lower-left — the room's one bulb, as everywhere. It is
 * the wood and not a colour so the channel does not show through it.
 */
.checkout-progress__dot {
  position: relative;
  display: grid;
  place-items: center;
  width: var(--dot);
  height: var(--dot);
  border-radius: 50%;
  background:
    linear-gradient(var(--plaque-veil), var(--plaque-veil)),
    var(--plaque-image) center / cover no-repeat;
  box-shadow:
    inset -2px 2px 3px var(--relief-shadow),
    inset 1px -1px 0 var(--relief-light);
}

/* Where they are: a ring of green round the hole. */
.checkout-progress__step[aria-current="step"] .checkout-progress__dot {
  box-shadow:
    0 0 0 3px var(--herb),
    inset -2px 2px 3px var(--relief-shadow),
    inset 1px -1px 0 var(--relief-light);
}

.checkout-progress__step[aria-current="step"] .checkout-progress__label { font-weight: 700; }

/* Done: the hole filled with green, and a leaf come up out of it. */
.checkout-progress__step.is-done .checkout-progress__dot {
  background: var(--herb);
  box-shadow: inset 1px -1px 0 var(--relief-light);
}

.checkout-progress__step.is-done .checkout-progress__dot::after {
  content: "";
  position: absolute;
  inset-block-start: -0.45rem;
  inset-inline-end: -0.4rem;
  width: 0.85rem;
  height: 0.5rem;
  border-radius: 0 100% 0 100%;
  background: var(--herb);
  rotate: -25deg;
}

/* The last stop is the kiondo itself, dim until the green reaches it. */
.checkout-progress__step--basket .checkout-progress__dot {
  background: none;
}

.checkout-progress__step--basket .mark {
  width: 100%;
  height: 100%;
  filter: grayscale(1) brightness(0.8);
}

.checkout-progress__step--basket[aria-current="step"] .mark { filter: none; }

.checkout-step + .checkout-step { margin-block-start: var(--space-5); }
.checkout-step__title { margin-block-end: var(--space-1); }
.checkout-step__title:focus:not(:focus-visible) { outline: none; }
.checkout-step__kicker { margin-block-end: var(--space-4); }

.checkout-step__nav {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
  margin-block-start: var(--space-4);
}

/* The way on takes the room; Back stays a quiet word at the left. */
.checkout-step__onward { flex: 1 1 12rem; }

/* The last look: each answer on its own row, with a way back to change it. */
.checkout-review { margin: 0 0 var(--space-4); }

.checkout-review__row {
  display: grid;
  grid-template-columns: 4.5rem 1fr auto;
  align-items: baseline;
  gap: var(--space-2) var(--space-3);
  padding-block: var(--space-2);
}

/* The same groove as the rules between lines on the bill, between rows only. */
.checkout-review__row + .checkout-review__row {
  border-block-start: 1px solid var(--relief-shadow);
  box-shadow: inset 0 1px 0 var(--relief-light);
}

.checkout-review dt { font-size: var(--text-sm); }
.checkout-review dd { margin: 0; overflow-wrap: anywhere; }

/* ── It is in the basket ─────────────────────────────────────────────────── */

/*
 * The order page's welcome, once (orders/_celebration). The grains fall BEHIND
 * the kiondo, which is stacked above them, so they are gone into it the moment
 * they pass the rim — no mask, no clipping, just the basket in front.
 */
.celebration { text-align: center; }

.celebration__basket {
  position: relative;
  width: 10rem;
  margin: 0 auto var(--space-3);
}

.celebration__basket .mark {
  position: relative;
  z-index: 1;
  display: block;
  width: 100%;
  height: auto;
}

.celebration__title {
  margin: 0 0 var(--space-2);
  font-size: var(--text-2xl);
  font-weight: 650;
}

/* Standing still, the grains have nowhere to be. */
.celebration__grain { display: none; }

.celebration__grain--maize { width: 0.55rem; height: 0.7rem; border-radius: 45% 45% 50% 50%; background: var(--brand-accent); }
.celebration__grain--bean  { width: 0.8rem; height: 0.5rem; border-radius: 50%; background: var(--brand-primary); }
.celebration__grain--gram  { width: 0.45rem; height: 0.45rem; border-radius: 50%; background: var(--color-herb-deep); }
.celebration__grain--leaf  { width: 0.9rem; height: 0.5rem; border-radius: 0 100% 0 100%; background: var(--color-herb); }

/*
 * All the motion on this page, and only for someone who has not asked for less
 * (the room's rule, room.css). Asked for less, the line simply is where it is,
 * the leaf is simply there, and the basket stands still with its words.
 */
@media (prefers-reduced-motion: no-preference) {
  .checkout-progress::after { transition: width 450ms ease-out; }

  .checkout-progress__step.is-done .checkout-progress__dot::after {
    animation: a-leaf-comes-up 380ms ease-out 250ms both;
  }

  .celebration__grain {
    display: block;
    position: absolute;
    inset-block-start: 22%;
    inset-inline-start: var(--x);
    animation: into-the-basket 850ms cubic-bezier(0.55, 0, 0.9, 0.55) both;
    animation-delay: calc(250ms + var(--i) * 110ms);
  }

  .celebration__basket .mark {
    animation: the-basket-nods 520ms ease-in-out 1.6s both;
  }
}

@keyframes a-leaf-comes-up {
  from { scale: 0; }
  to   { scale: 1; }
}

@keyframes into-the-basket {
  from { translate: 0 -9rem; rotate: 0deg; opacity: 0; }
  20%  { opacity: 1; }
  to   { translate: 0 1.75rem; rotate: 220deg; opacity: 1; }
}

@keyframes the-basket-nods {
  0%, 100% { rotate: 0deg; }
  35%      { rotate: -4deg; }
  70%      { rotate: 3deg; }
}

/*
 * Where the boards turn to paper (room.css does it for the same two asks), the
 * leaf drawn for wood is too pale, and the drilled holes have no wood to show.
 */
@media (prefers-contrast: more), (prefers-reduced-transparency: reduce) {
  .checkout-progress { --herb: var(--color-herb-deep); }
  .checkout-progress__dot { background: var(--color-surface-sunken); }
}
