/* THE TABLET SHOP AND THE ORDER STATUS SURFACE.
 *
 * Layout adapted from the designer's ShopFramebright artboard, rendered and
 * measured in real Chrome rather than read out of the bundle: a two-column
 * product page (copy left, what-you-get right), a breadcrumb above it, and a
 * what's-in-the-box row under the image slot.
 *
 * ===========================================================================
 * EVERY SELECTOR IS SCOPED UNDER #shopMount, WITHOUT EXCEPTION
 * ===========================================================================
 *
 * `.shop-card`, `.shop-pill`, `.shop-fact` and friends are generic enough to
 * collide with a future screen's class names, and this stylesheet is loaded on
 * every page of the dashboard, not just this one. The `#shopMount` prefix costs
 * one selector step and makes that collision impossible. Same discipline
 * css/billing.css states at the top of itself, for the same reason.
 *
 * ===========================================================================
 * NOTHING HERE HIDES ANYTHING THE MODULE WRITES INTO
 * ===========================================================================
 *
 * AGENTS.md's measured 2026-09-19 incident (commit ed3eaf68) was a pure-CSS
 * diff that put `display:none` on the one element JS wrote user-facing
 * confirmation text into, silencing all feedback above 900px with ZERO test
 * failures. So, deliberately, and checkable against js/shop.js:
 *
 *   - This file contains NO `display:none`, NO `visibility:hidden` and NO
 *     `opacity:0` on any element js/shop.js writes text into.
 *   - The status line this screen talks to a parent through is `#shopMsg`,
 *     which lives in index.html and is written by app.js's own ctx.say().
 *     This file does not select it AT ALL — not to position it, not to hide
 *     it, not at any breakpoint.
 *   - The only responsive change below is a column count. Nothing appears or
 *     disappears with viewport width.
 *
 * ===========================================================================
 * COLOUR
 * ===========================================================================
 *
 * Role tokens only (--cloud, --haze, --line, --dusk2, --glow, --mint, --amber,
 * --coral, --brand-tint, --surface-raised). Both themes therefore work without
 * a second palette here, and the light-theme decisions recorded in app.css
 * (DECISIONS-2026-09-20-design-fidelity-over-contrast) keep applying.
 * Status tone follows UI-DIRECTION-2026-08-22 §3: mint healthy/applied, amber
 * waiting, coral ended/reversed, neutral nothing-yet.
 */

/* SPANS THE PARENT GRID, and this line is load-bearing.
 *
 * app.css:492 makes every `.screen` a two-track grid above its breakpoint, and
 * a mount div is a CHILD of that grid rather than the section itself — so
 * without this it occupies ONE track. MEASURED on the real page at 1440px
 * before this line existed: #shop was 1140px wide, its grid resolved to
 * `561px 561px`, #shopMount took one 561px track, and the product card's own
 * two columns then split THAT in half — a 176px copy column with the product
 * name overflowing it, beside 560px of empty page.
 *
 * app.css already carries the same line for #overviewMount and says the same
 * thing about it ("without this it would occupy ONE track and then split that
 * half again"). This is that rule for this screen, kept here because
 * css/shop.css is the file this lane owns; if it ever moves into app.css, it
 * must not simply be deleted from one of the two.
 */
#shopMount {
  display: block;
  min-width: 0;
  grid-column: 1 / -1;
}

#shopMount .shop-wrap {
  display: flex;
  flex-direction: column;
  gap: 18px;
  min-width: 0;
}

/* ---------------------------------------------------------------- crumb -- */

#shopMount .shop-crumb {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  font-size: 12px;
}

#shopMount .shop-crumb-link {
  padding: 0;
  border: 0;
  background: none;
  color: var(--haze);
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  /* A crumb is a real control, so it keeps a real hit target even though it
     paints as text — 44px of height with no box drawn around it. */
  min-height: 44px;
  display: inline-flex;
  align-items: center;
}

#shopMount .shop-crumb-link:hover,
#shopMount .shop-crumb-link:focus-visible { color: var(--glow); }

#shopMount .shop-crumb-sep { color: var(--haze); opacity: .6; }

#shopMount .shop-crumb-here {
  color: var(--cloud);
  font-size: 12px;
  font-weight: 700;
}

/* ----------------------------------------------------------- the product -- */

#shopMount .shop-cards {
  display: flex;
  flex-direction: column;
  gap: 18px;
}

#shopMount .shop-card {
  display: grid;
  /* HER PROPORTIONS, measured off the rendered artboard at 1440px: the copy
     column runs to roughly 560px against a ~470px product panel. Expressed as
     fractions with a floor on the panel so it degrades by narrowing rather
     than by crushing the contents list. */
  grid-template-columns: minmax(0, 1.25fr) minmax(280px, .85fr);
  gap: clamp(20px, 3vw, 44px);
  align-items: start;
  padding: clamp(18px, 2.4vw, 30px);
  border: 1px solid var(--line);
  border-radius: var(--radius-card, 20px);
  background: var(--dusk2);
  box-shadow: var(--shadow-card, none);
  min-width: 0;
}

#shopMount .shop-main { min-width: 0; }

#shopMount .shop-chip {
  display: inline-block;
  padding: 5px 11px;
  border-radius: var(--radius-pill, 999px);
  background: var(--brand-tint, rgba(105,216,255,.12));
  color: var(--glow);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .02em;
}

#shopMount .shop-name {
  margin: 12px 0 0;
  color: var(--cloud);
  /* Her hero weight. Clamped so a long SKU name on a phone does not need a
     horizontal scroll to read, which is the failure the 16px gutter rule
     exists to prevent. */
  font-size: clamp(26px, 4vw, 40px);
  line-height: 1.1;
  letter-spacing: -.03em;
  /* A SKU NAME IS ONE LONG UNBREAKABLE WORD MORE OFTEN THAN NOT.
     MEASURED at 40px in the real card: "ParentProof" alone is 224px of
     scrollWidth against a 176px column, so it painted straight out of its
     column and over the panel beside it. `anywhere` rather than `break-word`
     because break-word will still not split a single word that has no break
     opportunity, which is exactly this case. The grid fix above makes the
     column wide enough today; this is what keeps a longer name from doing it
     again at a narrower width. */
  overflow-wrap: anywhere;
}

#shopMount .shop-tagline {
  max-width: 54ch;
  margin: 10px 0 0;
  color: var(--haze);
  font-size: 14px;
  line-height: 1.55;
}

#shopMount .shop-price {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 10px;
  margin: 18px 0 0;
}

#shopMount .shop-price-figure {
  color: var(--cloud);
  font-size: clamp(32px, 4.4vw, 44px);
  font-weight: 800;
  letter-spacing: -.035em;
  line-height: 1;
}

#shopMount .shop-price-unit {
  color: var(--haze);
  font-size: 13px;
  font-weight: 600;
}

/* Her blue note under the price. Two states, one box: `.is-included` when the
   SKU really does comp months, plain when it is the tablet only. Both are
   informational — neither is a warning — so the plain state is a neutral
   raised surface rather than an amber one. */
#shopMount .shop-note {
  margin: 16px 0 0;
  padding: 13px 15px;
  border: 1px solid var(--line);
  border-radius: var(--radius-control, 14px);
  background: var(--surface-raised, var(--dusk2));
  font-size: 13px;
  line-height: 1.55;
}

#shopMount .shop-note.is-included {
  border-color: color-mix(in srgb, var(--glow) 40%, transparent);
  background: var(--brand-tint, rgba(105,216,255,.1));
}

#shopMount .shop-note-lead { color: var(--cloud); font-weight: 700; }
#shopMount .shop-note-body { color: var(--haze); }

#shopMount .shop-ticks {
  margin: 18px 0 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 11px;
}

#shopMount .shop-tick {
  display: grid;
  grid-template-columns: 22px minmax(0, 1fr);
  gap: 10px;
  align-items: start;
}

#shopMount .shop-tick-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--mint) 20%, transparent);
  color: var(--mint);
  font-size: 12px;
  font-weight: 800;
  line-height: 1;
}

#shopMount .shop-tick-text {
  color: var(--cloud);
  font-size: 13.5px;
  line-height: 1.5;
}

/* app.css's `.primary` is `width:100%` because most of its call sites are
   inside narrow cards. Her buy button is an inline pill on a wide column, so
   this constrains the width WITHOUT re-declaring the gradient, the shadow or
   the light-theme text colour that `.primary` already owns and that app.css
   documents at length. */
#shopMount .shop-buy {
  width: auto;
  min-width: 220px;
  max-width: 100%;
  margin-top: 22px;
  padding-inline: 26px;
  border-radius: var(--radius-pill, 999px);
  font-weight: 700;
}

#shopMount .shop-alt {
  /* HER ARTBOARD HAS A BUG HERE and it is not reproduced: the buy button
     overlaps the escape-hatch line, which sits behind it and is half
     unreadable. Measured in the render, not guessed. This gives the line its
     own row. */
  margin: 14px 0 0;
  font-size: 13px;
  line-height: 1.5;
}

#shopMount .shop-alt-text { color: var(--haze); }

#shopMount .shop-link {
  padding: 0;
  border: 0;
  background: none;
  color: var(--glow);
  font-size: 13px;
  font-weight: 700;
  text-align: left;
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 3px;
}

#shopMount .shop-link:hover,
#shopMount .shop-link:focus-visible { text-decoration-thickness: 2px; }

/* ------------------------------------------------ the right-hand column -- */

#shopMount .shop-side { min-width: 0; }

/* THE PRODUCT IMAGE SLOT, WITH NO PRODUCT IMAGE IN IT. A dashed edge and a
   sentence, because there is no photography yet and a stock tablet picture
   here would be read as the device being sold. When a real photo lands this
   becomes an <img> and the dashed border goes. */
#shopMount .shop-photo {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 7px;
  aspect-ratio: 4 / 3;
  padding: 24px;
  border: 1px dashed var(--line);
  border-radius: var(--radius-card, 20px);
  background: var(--surface-raised, var(--dusk2));
  text-align: center;
}

#shopMount .shop-photo-title {
  color: var(--haze);
  font-size: 11px;
  font-weight: 800;
  letter-spacing: .12em;
  text-transform: uppercase;
}

#shopMount .shop-photo-body {
  max-width: 34ch;
  color: var(--haze);
  font-size: 12px;
  line-height: 1.5;
}

#shopMount .shop-box-title {
  margin: 18px 0 10px;
  color: var(--haze);
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: .13em;
  text-transform: uppercase;
}

#shopMount .shop-box {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 9px;
}

#shopMount .shop-box-item {
  display: grid;
  grid-template-columns: 8px minmax(0, 1fr);
  gap: 11px;
  align-items: center;
}

#shopMount .shop-box-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--glow);
  opacity: .55;
}

#shopMount .shop-box-text {
  color: var(--cloud);
  font-size: 13px;
  line-height: 1.45;
}

#shopMount .shop-empty {
  margin: 0;
  color: var(--haze);
  font-size: 13.5px;
}

/* ----------------------------------------------------- the orders strip -- */

#shopMount .shop-orders {
  padding: clamp(16px, 2vw, 22px);
  border: 1px solid var(--line);
  border-radius: var(--radius-card, 20px);
  background: var(--dusk2);
}

#shopMount .shop-orders-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 12px;
}

#shopMount .shop-orders-title {
  margin: 0;
  color: var(--cloud);
  font-size: 15px;
  font-weight: 700;
}

#shopMount .shop-orders-count { color: var(--haze); font-size: 12px; }

#shopMount .shop-orders-list {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 9px;
}

#shopMount .shop-order-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  gap: 12px;
  align-items: center;
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: var(--radius-control, 14px);
  background: var(--surface-raised, var(--dusk2));
}

#shopMount .shop-order-row-main {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
}

#shopMount .shop-order-row-name {
  color: var(--cloud);
  font-size: 13.5px;
  font-weight: 600;
  overflow-wrap: anywhere;
}

#shopMount .shop-order-row-when { color: var(--haze); font-size: 11.5px; }

#shopMount .shop-order-open { margin: 0; }

/* ------------------------------------------------------------- the pill -- */

#shopMount .shop-pill {
  display: inline-flex;
  align-items: center;
  padding: 4px 11px;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill, 999px);
  font-size: 11.5px;
  font-weight: 700;
  white-space: nowrap;
}

#shopMount .shop-pill.tone-neutral { color: var(--haze); }
#shopMount .shop-pill.tone-mint {
  border-color: color-mix(in srgb, var(--mint) 45%, transparent);
  color: var(--mint);
}
#shopMount .shop-pill.tone-amber {
  border-color: color-mix(in srgb, var(--amber) 45%, transparent);
  color: var(--amber);
}
#shopMount .shop-pill.tone-coral {
  border-color: color-mix(in srgb, var(--coral) 45%, transparent);
  color: var(--coral);
}

/* ------------------------------------------------------- the order view -- */

#shopMount .shop-order-card {
  padding: clamp(18px, 2.4vw, 28px);
  border: 1px solid var(--line);
  border-radius: var(--radius-card, 20px);
  background: var(--dusk2);
  box-shadow: var(--shadow-card, none);
}

#shopMount .shop-order-ref {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 8px;
  margin: 0;
  color: var(--haze);
  font-size: 11px;
}

/* THE LABEL TAKES THE UPPERCASE TREATMENT. THE ID DOES NOT. An order id is
   case-sensitive base64url, so `text-transform: uppercase` across the whole
   line would display an identifier that is not the identifier — and this is
   the string a parent reads out to support. Two rules, one line. */
#shopMount .shop-order-ref-label {
  font-weight: 800;
  letter-spacing: .1em;
  text-transform: uppercase;
}

#shopMount .shop-order-ref-id {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 11.5px;
  letter-spacing: 0;
  text-transform: none;
  overflow-wrap: anywhere;
}

#shopMount .shop-order-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
  margin: 8px 0 0;
}

#shopMount .shop-order-status {
  margin: 0;
  color: var(--cloud);
  font-size: clamp(22px, 3vw, 30px);
  line-height: 1.15;
  letter-spacing: -.025em;
}

/* The heading carries the tone now that it is the only place the status is
   said (see orderHeadline() in js/shop.js). Colour is an ACCOMPANIMENT to the
   word, never a replacement for it: every one of these states is spelled out
   in text, so a parent who cannot distinguish the hues loses nothing. */
#shopMount .shop-order-status.tone-mint { color: var(--mint); }
#shopMount .shop-order-status.tone-amber { color: var(--amber); }
#shopMount .shop-order-status.tone-coral { color: var(--coral); }
#shopMount .shop-order-status.tone-neutral { color: var(--haze); }

#shopMount .shop-order-body {
  max-width: 62ch;
  margin: 10px 0 0;
  color: var(--haze);
  font-size: 13.5px;
  line-height: 1.55;
}

#shopMount .shop-order-item {
  margin: 14px 0 0;
  color: var(--cloud);
  font-size: 14px;
  font-weight: 600;
}

/* The return-trip banner and the refund-owed banner share one box. Both are
   statements of fact rather than alerts, so the tone is carried by a left
   edge and the text colour, not by a filled panel that would shout. */
#shopMount .shop-banner {
  max-width: 68ch;
  margin: 14px 0 0;
  padding: 11px 14px;
  border: 1px solid var(--line);
  border-left-width: 3px;
  border-radius: var(--radius-control, 14px);
  background: var(--surface-raised, var(--dusk2));
  font-size: 13px;
  line-height: 1.55;
  color: var(--cloud);
}

#shopMount .shop-banner.tone-amber { border-left-color: var(--amber); }
#shopMount .shop-banner.tone-neutral { border-left-color: var(--haze); }

#shopMount .shop-facts {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin: 16px 0 0;
}

#shopMount .shop-fact {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 132px;
  padding: 11px 14px;
  border: 1px solid var(--line);
  border-radius: var(--radius-control, 14px);
  background: var(--surface-raised, var(--dusk2));
}

#shopMount .shop-fact-label {
  color: var(--haze);
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: .1em;
  text-transform: uppercase;
}

#shopMount .shop-fact-value {
  color: var(--cloud);
  font-size: 15px;
  font-weight: 700;
  overflow-wrap: anywhere;
}

#shopMount .shop-fact.is-refund .shop-fact-value { color: var(--coral); }

#shopMount .shop-order-comp {
  margin: 14px 0 0;
  color: var(--haze);
  font-size: 13px;
  line-height: 1.5;
}

#shopMount .shop-order-comp.is-applied { color: var(--mint); }

/* The sentence that says there is no delivery estimate. Deliberately given
   normal body treatment rather than a muted footnote: it is a commitment about
   what this product will not claim, not fine print. */
#shopMount .shop-order-noeta {
  max-width: 62ch;
  margin: 16px 0 0;
  padding-top: 14px;
  border-top: 1px solid var(--line);
  color: var(--haze);
  font-size: 12.5px;
  line-height: 1.6;
}

#shopMount .shop-timeline {
  margin: 18px 0 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

#shopMount .shop-timeline-row {
  display: grid;
  grid-template-columns: 10px minmax(0, 1fr) auto;
  gap: 12px;
  align-items: center;
}

#shopMount .shop-timeline-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--glow);
}

#shopMount .shop-timeline-label { color: var(--cloud); font-size: 13px; }
#shopMount .shop-timeline-when { color: var(--haze); font-size: 12px; white-space: nowrap; }

#shopMount .shop-address {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin: 18px 0 0;
  padding: 14px 16px;
  border: 1px solid var(--line);
  border-radius: var(--radius-control, 14px);
  background: var(--surface-raised, var(--dusk2));
}

#shopMount .shop-address-title {
  margin: 0 0 6px;
  color: var(--haze);
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: .1em;
  text-transform: uppercase;
}

#shopMount .shop-address-line {
  color: var(--cloud);
  font-size: 13px;
  line-height: 1.5;
  overflow-wrap: anywhere;
}

#shopMount .shop-address-source {
  margin: 8px 0 0;
  color: var(--haze);
  font-size: 11.5px;
  line-height: 1.45;
}

#shopMount .shop-address-gone {
  margin: 18px 0 0;
  color: var(--haze);
  font-size: 12.5px;
}

#shopMount .shop-order-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: center;
  margin-top: 20px;
}

#shopMount .shop-order-actions .shop-cancel,
#shopMount .shop-order-actions .shop-refresh { margin: 0; width: auto; }

#shopMount .shop-order-note {
  margin: 0;
  color: var(--haze);
  font-size: 13px;
  line-height: 1.55;
}

#shopMount .shop-back { width: auto; align-self: flex-start; margin: 0; }

/* ------------------------------------------------------------ narrower -- */

/* ONE COLUMN, and that is the ONLY thing this query changes. No element is
   added, removed, hidden or revealed at any width — see this file's header for
   why that constraint is written down rather than merely observed. */
@media (max-width: 900px) {
  #shopMount .shop-card { grid-template-columns: minmax(0, 1fr); }
  /* The product panel leads on a narrow screen in her artboard's own reading
     order; on one column the COPY has to lead, because a parent scrolling a
     phone should meet the name and the price before an empty image slot. */
  #shopMount .shop-side { order: 2; }
  #shopMount .shop-main { order: 1; }
  #shopMount .shop-photo { aspect-ratio: 16 / 9; }
}

@media (max-width: 640px) {
  #shopMount .shop-order-row { grid-template-columns: minmax(0, 1fr) auto; }
  /* The View control drops to its own full-width row rather than squeezing
     the order name to a few characters. */
  #shopMount .shop-order-open { grid-column: 1 / -1; width: 100%; }
  #shopMount .shop-buy { width: 100%; min-width: 0; }
  #shopMount .shop-fact { flex: 1 1 100%; }
}
