/* BigPrint4U — customer storefront styles.
   Extends the platform landing language (see landing.css): same palette,
   radius, shadow and type scale, scoped under .sf so it cannot leak. */

.sf {
  --sf-brand: #F62477;
  --sf-brand-dark: #92003A;
  --sf-brand-gradient: linear-gradient(135deg, #F62477, #92003A);
  --sf-ink: #111827;
  --sf-muted: #667085;
  --sf-line: #e7eaf0;
  --sf-soft: #f5f7fb;
  --sf-max: 1240px;
  --sf-radius: 16px;
  --sf-shadow: 0 20px 60px rgba(15, 23, 42, .10);
  --sf-shadow-hover: 0 25px 50px rgba(246, 36, 119, .15);
  background: #fbfcff;
  color: var(--sf-ink);
  font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  -webkit-font-smoothing: antialiased;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

.sf *, .sf *::before, .sf *::after { box-sizing: border-box; }

.sf-container {
  width: min(calc(100% - 32px), var(--sf-max));
  margin-inline: auto;
}

/* ---------- focus ---------- */
.sf :focus-visible {
  outline: 3px solid var(--sf-brand);
  outline-offset: 2px;
  border-radius: 6px;
}

/* ---------- header ---------- */
.sf-body { margin: 0; background: #fbfcff; }

.sf-header {
  position: sticky;
  top: 0;
  z-index: 40;
  border-bottom: 1px solid var(--sf-line);
  background: rgba(255, 255, 255, .94);
  backdrop-filter: blur(10px);
}

.sf-header-inner {
  display: flex;
  align-items: center;
  gap: 20px;
  min-height: 68px;
}

.sf-brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-weight: 800;
  font-size: 1.05rem;
  letter-spacing: -.01em;
  color: var(--sf-ink);
  text-decoration: none;
  white-space: nowrap;
}

.sf-brand-mark {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: 10px;
  background: var(--sf-brand-gradient);
  color: #fff;
  font-size: .82rem;
  font-weight: 800;
}

.sf-search {
  flex: 1 1 auto;
  display: flex;
  gap: 8px;
  max-width: 460px;
}

.sf-search input[type="search"] {
  flex: 1 1 auto;
  /* min-width: 0 is required: a flex item's automatic minimum size would pin
     the field to its intrinsic width (the default input size attribute), so the
     row could not compress below it and the submit button was pushed out of the
     header at 320px.  0 lets the field shrink and keeps the row inside the
     container at every width. */
  min-width: 0;
  min-height: 42px;
  padding: 0 14px;
  border: 1px solid var(--sf-line);
  border-radius: 999px;
  background: #fff;
  font: inherit;
  font-size: .92rem;
  color: var(--sf-ink);
}

.sf-nav {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-left: auto;
}

.sf-nav a {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 42px;
  padding: 0 12px;
  border-radius: 10px;
  color: var(--sf-muted);
  font-size: .92rem;
  font-weight: 600;
  text-decoration: none;
}

.sf-nav a:hover { color: var(--sf-brand); background: var(--sf-soft); }
.sf-nav a[aria-current="page"] { color: var(--sf-brand); background: var(--sf-soft); }

/* ---------- header: nav disclosure shell ----------
   The store nav lives in a <details> so the same markup serves both layouts:
   wide viewports render the summary collapsed and paint the <nav> inline, and
   the <=1099px block relocates the <nav> into the drop panel while promoting
   the summary to a visible hamburger.  <details> rather than a hidden
   checkbox because it is focusable and operable natively, which keeps the
   panel keyboard-openable when storefront.js never runs. */
/*  Base (desktop / no-media) position of the nav container.  The container's
    `order` must be the LARGEST of the three cluster values so the hidden
    hamburger container never lands between the avatar and the cart; the
    authoritative values live in the two media blocks below (3 at >=1100px and
    3 below it).  This base rule previously said `order: 2`, which was equal to
    the cart's and would have let the container sort between the avatar and the
    cart wherever the base rule won. */
.sf-nav-desktop { order: 3; margin-left: auto; }

.sf-nav-toggle { display: none; }

/* Desktop: the <details> is rendered with the `open` attribute server-side so
   its content slot is never in the closed (unpainted) state.  The disclosure
   marker is suppressed here and the nav lays out as the original right-aligned
   flex row.  `display: contents` is deliberately NOT used: it removes the
   details box while the content slot stays closed, which leaves the links with
   geometry but no paint and no hit-testing. */
.sf-nav-desktop > summary { list-style: none; }
.sf-nav-desktop > summary::-webkit-details-marker { display: none; }

@media (min-width: 1100px) {
  .sf-nav-desktop { display: block; order: 3; margin-left: auto; }
  .sf-nav { order: initial; margin-left: 0; }
  /*  Desktop: the right-hand cluster is Cart -> nav row -> Avatar, read left to
      right.  The avatar sits at the far right, AFTER the "Log out" button that
      ends the nav row.

      The nav container (which holds the hamburger, hidden here) already carries
      `order: 3`, so the avatar has to sort strictly after it -- `order: 4`, not
      a repeat of 3, which would tie and let source order win and paint the
      avatar before the nav.  The cart keeps its own `order: 2`, which is what
      puts it first in the cluster.  Cart (2) -> container (3) -> avatar (4).

      What actually holds the cluster against the right edge is the search
      field: `.sf-search` is `flex: 1 1 auto`, so it grows into every spare pixel
      and the three cluster items sit flush after it.  The cart's
      `margin-left: auto` is the guard for the case where the search is gone or
      shrunk to nothing -- with the cart opening the cluster it is the only
      element whose auto margin can absorb that space and drag the rest along.
      Put it on the container or on the avatar instead and it pushes only
      itself: measured, the cart stranded beside the search field ending at
      x=495 with a 126px hole before it in a 1440px bar. #*/
  .sf-nav-desktop { margin-left: 0; }
  .sf-nav-cart { order: 2; margin-left: auto; }
  .sf-user { order: 4; margin-left: 0; }
  /* The nav row is max-content; at the 1100px boundary it plus the search field
     overflows the container.  Letting the search shrink absorbs the difference
     instead of pushing the row past the viewport. */
  .sf-search { min-width: 0; flex-shrink: 1; }
}

/* ---------- header: the 769-1099px band no longer exists ----------
   This band used to be a third header layout: a wrapping desktop row squeezed
   between the two real layouts.  It is gone by design -- below 1100px the
   storefront now uses the mobile hamburger layout, so there is no longer a
   width at which a cramped desktop nav row has to be rescued.

   The former problem, kept for context: .sf-header-inner was a single flex row
   with no wrap, and its children have a fixed min-content floor (.sf-brand is
   nowrap, the .sf-user pill ~180px, the nav link row ~530px, plus the cart).
   Only .sf-search could shrink, so between 769px and roughly 1099px the search
   bottomed out with the row still wider than the container and the nav links
   collided with the search field.

   Two layouts now, with the boundary at 1100px:
     - >= 1100px: single-line desktop row (the block above);
     - < 1100px:  hamburger + drop panel (the <=1099px block below).
   Anything that would have belonged to a middle band belongs to the mobile
   block now, which already wraps the header and pins its own child order. */

/* ---------- header: cart ----------
   .sf-nav only supplies the flex row; the cart link needs the anchor metrics
   of .sf-nav a, which no longer apply once it sits outside the <nav>. */
.sf-nav-cart {
  gap: 6px;
  min-height: 42px;
  padding: 0 12px;
  border-radius: 10px;
  color: var(--sf-muted);
  font-size: .92rem;
  font-weight: 600;
  text-decoration: none;
}
.sf-nav-cart:hover { color: var(--sf-brand); background: var(--sf-soft); }
.sf-nav-cart[aria-current="page"] { color: var(--sf-brand); background: var(--sf-soft); }

/* Count badge.  Always rendered (a virgin cart shows 0) so the number is a
   stable element that never pops into existence.  tabular-nums stops the pill
   from jittering as the count crosses a digit boundary. */
.sf-cart-count {
  display: inline-grid;
  place-items: center;
  min-width: 20px;
  height: 20px;
  padding: 0 6px;
  border-radius: 999px;
  background: var(--sf-brand);
  color: #fff;
  font-size: .74rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  line-height: 1;
}

/* Cart glyph.  Inherits the link's colour via currentColor so it highlights
   with the label and the hover/aria-current states for free.  flex: 0 0 auto
   stops the flex row from squashing it when the label is present. */
.sf-cart-icon {
  flex: 0 0 auto;
  display: block;
  width: 20px;
  height: 20px;
}

/* ---------- header: signed-in customer pill ----------
   Initials avatar fallback — there is no avatar image column on customers, so
   the badge always renders text.  Sized like .sf-brand-mark (34px) and using
   the same brand gradient so the header keeps one identity language. */
.sf-user {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 42px;
  padding: 0 10px 0 4px;
  border-radius: 999px;
  background: var(--sf-soft);
}

/* The same identity rendered as the hamburger panel's first row, for the
   <1100px layout where .sf-user is display:none.  Hidden at the base so the
   desktop row -- which paints the panel inline -- never shows it twice. */
.sf-nav-user {
  display: none;
  align-items: center;
  gap: 8px;
  padding: 6px 10px;
}

.sf-user-avatar {
  display: grid;
  place-items: center;
  flex: 0 0 auto;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: var(--sf-brand-gradient);
  color: #fff;
  font-size: .78rem;
  font-weight: 800;
  letter-spacing: .01em;
}

.sf-user-name {
  max-width: 140px;
  /* min-width: 0 lets the pill's flex line shrink the name instead of forcing
     .sf-user wide, and it opts the text into text-overflow: ellipsis. */
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--sf-ink);
  font-size: .9rem;
  font-weight: 700;
}

.sf-user-logout { display: inline-flex; }

.sf-user-logout-btn {
  min-height: 42px;
  padding: 0 12px;
  border: 0;
  border-radius: 10px;
  background: transparent;
  color: var(--sf-muted);
  font: inherit;
  font-size: .92rem;
  font-weight: 600;
  cursor: pointer;
}

.sf-user-logout-btn:hover { color: var(--sf-brand); background: var(--sf-soft); }

.sf-nav-register { min-height: 42px; padding: 0 14px; border-radius: 10px; font-size: .92rem; }

/* ---------- buttons ---------- */
.sf-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 46px;
  padding: 0 20px;
  border: 1px solid transparent;
  border-radius: 12px;
  font: inherit;
  font-size: .95rem;
  font-weight: 700;
  text-decoration: none;
  cursor: pointer;
  transition: transform .12s ease, box-shadow .12s ease, background .12s ease;
}

.sf-btn-primary { background: var(--sf-brand); color: #fff; }
.sf-btn-primary:hover { background: var(--sf-brand-dark); box-shadow: var(--sf-shadow-hover); }
.sf-btn-light { background: #fff; color: var(--sf-ink); border-color: var(--sf-line); }
.sf-btn-light:hover { border-color: var(--sf-brand); color: var(--sf-brand); }
.sf-btn-ghost { background: transparent; color: var(--sf-muted); }
.sf-btn-ghost:hover { color: var(--sf-brand); background: var(--sf-soft); }
.sf-btn-block { width: 100%; }
.sf-btn[disabled], .sf-btn[aria-disabled="true"] {
  opacity: .5;
  cursor: not-allowed;
  box-shadow: none;
}

/* ---------- promo banner hero ---------- */
.sf-banner-hero { padding: 12px 0 0; }

.sf-banner-hero-img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--sf-radius);
  box-shadow: var(--sf-shadow);
}

/* ---------- hero ---------- */
.sf-hero {
  padding: 64px 0 48px;
  background:
    radial-gradient(1000px 420px at 88% -10%, rgba(246, 36, 119, .10), transparent 62%),
    #fbfcff;
}

.sf-hero-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.2fr);
  gap: 24px;
  align-items: center;
}

.sf-eyebrow {
  display: inline-block;
  margin-bottom: 14px;
  padding: 6px 12px;
  border-radius: 999px;
  background: rgba(246, 36, 119, .10);
  color: var(--sf-brand-dark);
  font-size: .76rem;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
}

.sf-hero h1 {
  margin: 0 0 16px;
  font-size: clamp(2rem, 4.4vw, 3.25rem);
  line-height: 1.06;
  letter-spacing: -.03em;
}

.sf-hero h1 span {
  background: var(--sf-brand-gradient);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.sf-hero p {
  margin: 0 0 26px;
  max-width: 46ch;
  color: var(--sf-muted);
  font-size: 1.05rem;
  line-height: 1.65;
}

.sf-hero-actions { display: flex; flex-wrap: wrap; gap: 12px; }

.sf-hero-note {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 22px;
  color: var(--sf-muted);
  font-size: .88rem;
}

.sf-hero-stage {
  display: flex;
  align-items: stretch;
  justify-content: center;
  height: 100%;
  min-height: 420px;
}

.sf-hero-image {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: var(--sf-radius);
  box-shadow: var(--sf-shadow);
}

/* ---------- sections ---------- */
.sf-section { padding: 56px 0; }
.sf-section-alt { background: #fff; border-block: 1px solid var(--sf-line); }

.sf-section-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 20px;
  margin-bottom: 28px;
  flex-wrap: wrap;
}

.sf-section-head h2 {
  margin: 0 0 6px;
  font-size: clamp(1.4rem, 2.4vw, 1.9rem);
  letter-spacing: -.02em;
}

.sf-section-head p { margin: 0; color: var(--sf-muted); max-width: 62ch; line-height: 1.6; }

/* ---------- cards & grids ---------- */
.sf-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 20px;
}

/* Five service cards, five columns: `repeat(5)` (not auto-fill) so the row is
   always exactly one line on desktop and never wraps a lone fifth card onto a
   second row.  minmax(0, 1fr) lets a column shrink below its content width
   instead of forcing the grid past the container. */
.sf-grid-services { grid-template-columns: repeat(5, minmax(0, 1fr)); }

.sf-card {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--sf-line);
  border-radius: var(--sf-radius);
  background: #fff;
  box-shadow: 0 1px 2px rgba(15, 23, 42, .04);
  overflow: hidden;
}

.sf-card-icon {
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  margin-bottom: 14px;
  border-radius: 12px;
  background: var(--sf-soft);
  font-size: 1.35rem;
}

.sf-service { padding: 24px; }
.sf-service h3 { margin: 0 0 8px; font-size: 1.05rem; }
.sf-service p { margin: 0; color: var(--sf-muted); font-size: .92rem; line-height: 1.6; }

.sf-service-media {
  width: 100%;
  aspect-ratio: 1 / 1;
  margin-bottom: 14px;
  border-radius: 12px;
  overflow: hidden;
  background: var(--sf-soft);
}
.sf-service-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.sf-product-media {
  display: block;
  aspect-ratio: 4 / 3;
  background: var(--sf-soft);
  overflow: hidden;
}

.sf-product-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.sf-product-media-placeholder {
  display: grid;
  place-items: center;
  width: 100%;
  height: 100%;
  color: var(--sf-muted);
  font-size: .8rem;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
}

.sf-product-body { display: flex; flex-direction: column; gap: 8px; padding: 18px; flex: 1 1 auto; }

.sf-product-name {
  margin: 0;
  font-size: 1rem;
  font-weight: 700;
  line-height: 1.35;
}

.sf-product-name a { color: inherit; text-decoration: none; }
.sf-product-name a:hover { color: var(--sf-brand); }

.sf-tag {
  align-self: flex-start;
  padding: 4px 9px;
  border-radius: 999px;
  background: var(--sf-soft);
  color: var(--sf-muted);
  font-size: .72rem;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
}

.sf-price {
  margin-top: auto;
  font-size: 1.15rem;
  font-weight: 800;
  letter-spacing: -.01em;
}

.sf-price-note { color: var(--sf-muted); font-size: .8rem; font-weight: 500; }

.sf-stack { display: flex; flex-direction: column; gap: 12px; }

/* ---------- steps ---------- */
.sf-steps {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 20px;
}

.sf-step { padding: 22px; border: 1px solid var(--sf-line); border-radius: var(--sf-radius); background: #fff; }
.sf-step-no {
  display: inline-grid;
  place-items: center;
  width: 38px;
  height: 38px;
  margin-bottom: 12px;
  border-radius: 10px;
  background: var(--sf-brand-gradient);
  color: #fff;
  font-size: .82rem;
  font-weight: 800;
}
.sf-step h3 { margin: 0 0 6px; font-size: 1rem; }
.sf-step p { margin: 0; color: var(--sf-muted); font-size: .9rem; line-height: 1.6; }

/* ---------- promo strip ---------- */
.sf-promos { display: flex; flex-wrap: wrap; gap: 12px; }

.sf-promo {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 18px;
  border: 1px dashed var(--sf-brand);
  border-radius: 12px;
  background: rgba(246, 36, 119, .05);
}

.sf-promo code {
  padding: 4px 10px;
  border-radius: 8px;
  background: #fff;
  border: 1px solid var(--sf-line);
  font-size: .88rem;
  font-weight: 700;
  letter-spacing: .06em;
}

.sf-promo span { color: var(--sf-muted); font-size: .88rem; }

/* ---------- filters ---------- */
.sf-filters { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 24px; }

.sf-chip {
  display: inline-flex;
  align-items: center;
  min-height: 38px;
  padding: 0 14px;
  border: 1px solid var(--sf-line);
  border-radius: 999px;
  background: #fff;
  color: var(--sf-muted);
  font-size: .88rem;
  font-weight: 600;
  text-decoration: none;
}

.sf-chip:hover { border-color: var(--sf-brand); color: var(--sf-brand); }
.sf-chip[aria-current="true"] { background: var(--sf-brand); border-color: var(--sf-brand); color: #fff; }

/* ---------- product detail ---------- */
.sf-detail {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, .95fr);
  gap: 40px;
  align-items: start;
}

.sf-gallery { display: grid; gap: 12px; }
.sf-gallery-main { border-radius: var(--sf-radius); overflow: hidden; background: var(--sf-soft); }
.sf-gallery-main img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; display: block; }

.sf-detail h1 { margin: 0 0 10px; font-size: clamp(1.6rem, 3vw, 2.2rem); letter-spacing: -.02em; }
.sf-detail-price { font-size: 1.7rem; font-weight: 800; margin: 18px 0 4px; }

.sf-specs { margin: 24px 0 0; padding: 0; list-style: none; border-top: 1px solid var(--sf-line); }
.sf-specs li {
  display: flex;
  justify-content: space-between;
  gap: 18px;
  padding: 11px 0;
  border-bottom: 1px solid var(--sf-line);
  font-size: .92rem;
}
.sf-specs dt, .sf-specs .sf-spec-label { color: var(--sf-muted); }
.sf-specs dd, .sf-specs .sf-spec-value { margin: 0; font-weight: 600; text-align: right; }

/* ---------- quantity stepper ---------- */
.sf-qty { display: inline-flex; align-items: center; border: 1px solid var(--sf-line); border-radius: 12px; background: #fff; overflow: hidden; }
.sf-qty button {
  width: 44px;
  height: 46px;
  border: 0;
  background: transparent;
  color: var(--sf-ink);
  font-size: 1.15rem;
  font-weight: 700;
  cursor: pointer;
}
.sf-qty button:hover { background: var(--sf-soft); color: var(--sf-brand); }
.sf-qty input {
  width: 62px;
  height: 46px;
  border: 0;
  border-inline: 1px solid var(--sf-line);
  text-align: center;
  font: inherit;
  font-weight: 700;
  color: var(--sf-ink);
  -moz-appearance: textfield;
}
.sf-qty input::-webkit-outer-spin-button,
.sf-qty input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

/* ---------- forms ---------- */
.sf-field { display: flex; flex-direction: column; gap: 6px; margin-bottom: 18px; }
.sf-field label { font-size: .88rem; font-weight: 700; }
.sf-field .sf-hint { color: var(--sf-muted); font-size: .82rem; font-weight: 500; }
/* phone.js marks the field invalid through setCustomValidity + aria-invalid so
   the browser's own constraint UI stays authoritative; this makes the reason
   visible beside the field instead of only in a submit tooltip. */
.sf-field input[aria-invalid="true"] { border-color: var(--sf-danger, #b42318); }
.sf-field .sf-hint.error { color: var(--sf-danger, #b42318); font-weight: 700; }

.sf-field input[type="text"],
.sf-field input[type="tel"],
.sf-field input[type="email"],
.sf-field input[type="search"],
.sf-field input[type="file"],
.sf-field textarea,
.sf-field select {
  min-height: 46px;
  padding: 11px 14px;
  border: 1px solid var(--sf-line);
  border-radius: 12px;
  background: #fff;
  font: inherit;
  font-size: .95rem;
  color: var(--sf-ink);
}

.sf-field textarea { min-height: 92px; resize: vertical; }

.sf-radio-group { display: grid; gap: 10px; }

.sf-radio {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 14px 16px;
  border: 1px solid var(--sf-line);
  border-radius: 12px;
  background: #fff;
  cursor: pointer;
}

.sf-radio:hover { border-color: var(--sf-brand); }
.sf-radio input { margin-top: 3px; width: 18px; height: 18px; accent-color: var(--sf-brand); }
.sf-radio b { display: block; font-size: .95rem; }
.sf-radio small { color: var(--sf-muted); font-size: .84rem; }

/* ---------- alerts ---------- */
.sf-alert {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 13px 16px;
  border-radius: 12px;
  font-size: .92rem;
  font-weight: 600;
  margin-bottom: 18px;
}

.sf-alert-error { background: #fef2f2; color: #b91c1c; border: 1px solid #fecaca; }
.sf-alert-success { background: #f0fdf4; color: #15803d; border: 1px solid #bbf7d0; }
.sf-alert-info { background: var(--sf-soft); color: var(--sf-muted); border: 1px solid var(--sf-line); }

/* ---------- layout panels ---------- */
.sf-cols {
  display: grid;
  grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr);
  gap: 28px;
  align-items: start;
}

.sf-panel {
  border: 1px solid var(--sf-line);
  border-radius: var(--sf-radius);
  background: #fff;
  padding: 24px;
}

.sf-panel h2 { margin: 0 0 18px; font-size: 1.15rem; }

.sf-summary { position: sticky; top: 88px; }
.sf-summary-row {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  padding: 9px 0;
  font-size: .93rem;
  color: var(--sf-muted);
}
.sf-summary-row b { color: var(--sf-ink); font-weight: 700; }
.sf-summary-total {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  margin-top: 12px;
  padding-top: 14px;
  border-top: 1px solid var(--sf-line);
  font-size: 1.1rem;
  font-weight: 800;
}

/* ---------- cart lines ---------- */
.sf-line {
  display: grid;
  grid-template-columns: 84px minmax(0, 1fr) auto;
  gap: 16px;
  align-items: center;
  padding: 16px 0;
  border-bottom: 1px solid var(--sf-line);
}
.sf-line:last-child { border-bottom: 0; }

.sf-line-thumb {
  width: 84px;
  aspect-ratio: 1 / 1;
  border-radius: 12px;
  background: var(--sf-soft);
  overflow: hidden;
}
.sf-line-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.sf-line-name { margin: 0 0 4px; font-size: .98rem; font-weight: 700; }
.sf-line-name a { color: inherit; text-decoration: none; }
.sf-line-name a:hover { color: var(--sf-brand); }
.sf-line-meta { color: var(--sf-muted); font-size: .85rem; }
.sf-line-actions { display: flex; flex-direction: column; align-items: flex-end; gap: 8px; }
.sf-line-total { font-weight: 800; font-size: 1rem; }

.sf-link-btn {
  border: 0;
  background: none;
  padding: 4px 2px;
  color: var(--sf-muted);
  font: inherit;
  font-size: .85rem;
  font-weight: 600;
  cursor: pointer;
  text-decoration: underline;
}
.sf-link-btn:hover { color: #b91c1c; }

/* ---------- checkout: per-line artwork upload (namespaced, checkout-only) ----------
   Additive only. cart.html and product.html never emit these classes. */
.sf-line-artwork {
  padding: 12px 0 16px 100px;
  border-bottom: 1px solid var(--sf-line);
  background: var(--sf-soft);
}
.sf-line-artwork .sf-field { gap: 4px; }
.sf-line-artwork .sf-field label { font-size: .86rem; }
.sf-line-artwork-result:empty { display: none; }
.sf-line-artwork-result { margin-top: 8px; }
.sf-line-artwork-result .sf-alert { margin-bottom: 0; padding: 9px 12px; font-size: .84rem; }

/* The per-line Update/Remove forms live outside the checkout form, so they
   must not occupy layout space. */
.sf-line-aux-form { display: none; }

/* ---------- checkout: compact summary sub-blocks (namespaced, checkout-only) ---------- */
.sf-summary-block {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--sf-line);
}
.sf-summary-block-head {
  margin: 0 0 4px;
  font-size: .76rem;
  font-weight: 800;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--sf-muted);
}
.sf-summary-note {
  margin: 4px 0 0;
  color: var(--sf-muted);
  font-size: .78rem;
  line-height: 1.4;
}
.sf-summary-actions {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--sf-line);
}
.sf-summary .sf-field label { font-size: .84rem; }
.sf-summary .sf-field input[type="text"] { min-height: 42px; }

/* Compact the checkout aside only: cart.html's .sf-summary keeps its rhythm.
   Measured on the live page (1440x900, fixture cart of 4 lines):
   aside height 572px compact vs 717px with cart.html's summary rhythm (-145px,
   -20%); see the completion note for the per-block breakdown. */
.sf-summary > #summary-totals > h2 { margin: 0 0 12px; font-size: 1.08rem; }
.sf-summary > #summary-totals > ul { margin: 0 0 8px; }
.sf-summary > #summary-totals > ul .sf-summary-row { padding: 3px 0; font-size: .84rem; }
.sf-summary > #summary-totals > ul .sf-summary-row span { overflow-wrap: anywhere; }
.sf-summary > #summary-totals > .sf-summary-row { padding: 5px 0; font-size: .86rem; }
.sf-summary > #summary-totals .sf-summary-total { margin-top: 6px; padding-top: 8px; font-size: 1rem; }
.sf-summary-block .sf-summary-row { padding: 2px 0; font-size: .86rem; }
.sf-summary-actions .sf-btn { min-height: 44px; }

@media (max-width: 768px) {
  .sf-line-artwork { padding-left: 80px; }
}
@media (max-width: 430px) {
  .sf-line-artwork { padding-left: 0; }
}

/* ---------- timeline ---------- */
.sf-timeline { list-style: none; margin: 0; padding: 0; }
.sf-timeline li {
  position: relative;
  padding: 0 0 20px 26px;
  border-left: 2px solid var(--sf-line);
}
.sf-timeline li:last-child { padding-bottom: 0; border-left-color: transparent; }
.sf-timeline li::before {
  content: "";
  position: absolute;
  left: -7px;
  top: 3px;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--sf-brand);
}
.sf-timeline b { display: block; font-size: .94rem; text-transform: capitalize; }
.sf-timeline small { color: var(--sf-muted); font-size: .82rem; }

/* ---------- status pill ---------- */
.sf-status {
  display: inline-block;
  padding: 6px 12px;
  border-radius: 999px;
  background: rgba(246, 36, 119, .10);
  color: var(--sf-brand-dark);
  font-size: .78rem;
  font-weight: 800;
  letter-spacing: .04em;
  text-transform: uppercase;
}

/* ---------- empty state ---------- */
.sf-empty {
  padding: 56px 24px;
  text-align: center;
  border: 1px dashed var(--sf-line);
  border-radius: var(--sf-radius);
  background: #fff;
}
.sf-empty h2 { margin: 0 0 8px; font-size: 1.2rem; }
.sf-empty p { margin: 0 0 20px; color: var(--sf-muted); }
.sf-empty-icon { font-size: 2.2rem; margin-bottom: 12px; }

/* ---------- messages ---------- */
.sf-chat { display: grid; grid-template-columns: minmax(0, 320px) minmax(0, 1fr); gap: 20px; }
.sf-conv-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.sf-conv {
  display: block;
  padding: 14px 16px;
  border: 1px solid var(--sf-line);
  border-radius: 12px;
  background: #fff;
  color: inherit;
  text-decoration: none;
}
.sf-conv[aria-current="true"] { border-color: var(--sf-brand); background: rgba(246, 36, 119, .05); }
.sf-conv b { display: block; font-size: .93rem; }
.sf-conv small { color: var(--sf-muted); font-size: .82rem; }
.sf-conv-unread {
  display: inline-grid;
  place-items: center;
  min-width: 20px;
  height: 20px;
  margin-left: 8px;
  padding: 0 6px;
  border-radius: 999px;
  background: var(--sf-brand);
  color: #fff;
  font-size: .72rem;
  font-weight: 800;
}

.sf-thread {
  display: flex;
  flex-direction: column;
  min-height: 420px;
  max-height: 60vh;
  overflow-y: auto;
  padding: 18px;
  gap: 12px;
  background: var(--sf-soft);
  border-radius: var(--sf-radius);
}

.sf-bubble {
  max-width: 74%;
  padding: 11px 14px;
  border-radius: 14px;
  background: #fff;
  border: 1px solid var(--sf-line);
  font-size: .93rem;
  line-height: 1.5;
  align-self: flex-start;
}
.sf-bubble-mine { align-self: flex-end; background: var(--sf-brand); border-color: var(--sf-brand); color: #fff; }
.sf-bubble time { display: block; margin-top: 6px; font-size: .74rem; opacity: .75; }

/* ---------- footer ---------- */
.sf-footer { margin-top: auto; border-top: 1px solid var(--sf-line); background: #fff; }
.sf-footer-inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 26px 0;
  color: var(--sf-muted);
  font-size: .88rem;
}
.sf-footer a { color: var(--sf-muted); text-decoration: none; }
.sf-footer a:hover { color: var(--sf-brand); }

.sf-skip {
  position: absolute;
  left: -9999px;
  top: 0;
  padding: 10px 16px;
  background: var(--sf-brand);
  color: #fff;
  border-radius: 0 0 10px 0;
  font-weight: 700;
  z-index: 60;
}
.sf-skip:focus { left: 0; }

.sf-visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* ---------- responsive ---------- */
@media (max-width: 1024px) {
  .sf-hero-grid { grid-template-columns: 1fr; gap: 34px; }
  .sf-detail { grid-template-columns: 1fr; gap: 28px; }
  .sf-cols { grid-template-columns: 1fr; }
  .sf-summary { position: static; }
  .sf-chat { grid-template-columns: 1fr; }
  .sf-thread { max-height: 52vh; }
}

@media (max-width: 1099px) {
  .sf-header-inner { flex-wrap: wrap; gap: 12px; padding-block: 12px; min-height: 0; }
  .sf-search { order: 4; max-width: none; width: 100%; flex-basis: 100%; }
  /* The nav is now a drop panel hanging off the hamburger instead of a flex
     row: absolute so it never widens the header (no horizontal overflow at
     375px) and it floats clear of the flex line.  Opening it is pure CSS --
     [open] from a click or Enter/Space on the summary, or :focus-within when
     the keyboard walks into it -- so JS is only an enhancement.  min(): the
     panel is right-aligned under the toggle, so its cap keeps it inside the
     viewport with room for .sf-container's own 24px gutter. */
  .sf-nav-desktop { order: 3; position: relative; margin-left: 0; }
  /*  The right-hand cluster at every width below the desktop boundary is
      Cart -> Hamburger, read left to right, and it is one right-aligned group.

      The hamburger container sorts AFTER the cart (`order: 3` vs the cart's
      `order: 2`), so the toggle always sits flush right, next to the cart.  The
      avatar is NOT part of this cluster on mobile -- it moves into the panel
      (`.sf-nav-user`, see the rule below), so the bar is the same shape signed
      in and signed out: brand, Cart, Hamburger.

      The cart owns the auto margin and nothing else does.  With `flex-wrap:
      wrap` the free space is absorbed by the single auto margin, which pushes
      the cart to the right edge, and the hamburger's container follows it at
      the row's own `gap` (12px).

      That margin used to be split: the avatar took it when a customer was
      signed in and the cart took it otherwise (`.sf-search + .sf-nav-desktop +
      .sf-nav-cart`), because the avatar led the cluster.  With the avatar out
      of the bar the two cases are the same bar, so the cart always takes it and
      the guest/signed-in guard is gone with the asymmetry it existed to paper
      over.  A second auto margin on .sf-user is impossible here because that
      element is display:none below 1100px (measured failure mode for the old
      split, kept for context: at 1024px the avatar sat at x=484 and the
      hamburger was stranded at x=530 with a 335px hole after it). #*/
  .sf-nav-cart {
    order: 2;
    margin-left: auto;
    padding: 0 10px;
    display: inline-flex;
    align-items: center;
    gap: 6px;
  }
  /* Mobile: the avatar lives in the panel, not the bar.  display:none rather
     than a visual hide, so the bar copy is also out of the accessibility tree
     and the identity is announced exactly once -- from `.sf-nav-user` in the
     panel. */
  .sf-user { display: none; }
  /* ...and the panel row that replaces it.  It is a panel entry, so it inherits
     the panel's column layout; the avatar disc and the name keep the metrics
     they have in the bar pill. */
  .sf-nav-user { display: flex; }
  /* Guest bar: with no avatar rendered, the cart is the leftmost element of the
     right-hand cluster, so it has to take the auto margin or the pair collapses
     back against the search field (and, because the search wraps to its own row,
     the cluster would sit short of the right edge).

     The cart's own `margin-left: auto` above covers that, and it is the ONLY
     auto margin in the mobile bar: the avatar it used to be split with is
     display:none below 1100px, so there is no "two auto margins split the free
     space" case left to guard against.  The old guest-only guard
     (`.sf-search + .sf-nav-desktop + .sf-nav-cart { margin-left: auto }`) was
     deleted with the avatar's departure -- it expressed "the avatar block
     rendered nothing", a distinction the bar no longer has, and leaving it in
     place would have kept a second, dead selector encoding the old layout.

     `:first-child` was never usable: the brand is always the first element
     child, so it never matches (measured: guest cart ending at x=275 in a
     390px bar). #*/
  .sf-nav-cart .sf-cart-count { min-width: 18px; height: 18px; font-size: .7rem; }
  .sf-nav-toggle {
    display: grid;
    place-items: center;
    width: 42px;
    height: 42px;
    border: 1px solid var(--sf-line);
    border-radius: 10px;
    background: #fff;
    cursor: pointer;
    list-style: none;
  }
  .sf-nav-toggle::-webkit-details-marker { display: none; }
  .sf-nav-toggle:hover { border-color: var(--sf-brand); }
  /* Three-bar hamburger glyph painted from the summary's own ::before. */
  .sf-nav-burger {
    position: relative;
    width: 18px;
    height: 2px;
    border-radius: 2px;
    background: var(--sf-ink);
  }
  .sf-nav-burger::before,
  .sf-nav-burger::after {
    content: "";
    position: absolute;
    left: 0;
    width: 18px;
    height: 2px;
    border-radius: 2px;
    background: inherit;
  }
  .sf-nav-burger::before { top: -6px; }
  .sf-nav-burger::after { top: 6px; }
  .sf-nav-desktop[data-open] .sf-nav-toggle { border-color: var(--sf-brand); }

  /* #sf-nav (id) rather than .sf-nav: the cart link also carries .sf-nav, and a
     class rule here would hide it along with the collapsed panel. */
  #sf-nav {
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    z-index: 1;
    display: none;
    flex-direction: column;
    align-items: stretch;
    gap: 2px;
    width: max-content;
    min-width: 190px;
    max-width: min(260px, calc(100vw - 48px));
    margin-left: 0;
    padding: 8px;
    border: 1px solid var(--sf-line);
    border-radius: 12px;
    background: #fff;
    box-shadow: var(--sf-shadow);
  }
  /* Open state.  [open] is the single source of truth: JS keeps it in sync with
     aria-expanded, and the native toggle handles the no-JS click path.
     The :focus-within arm exists so a keyboard user can reach the panel when
     storefront.js never runs -- but it must NOT resurrect a panel the user just
     dismissed.  Escape closes the details and returns focus to the summary, so
     an unfiltered :focus-within would match the closed element and re-show it.
     Excluding a focused summary keeps the no-JS fallback intact (tabbing from
     the summary into the links still opens it) while letting Escape win. */
  /* The details carries `open` at every width (desktop needs it to paint), so
     on mobile `open` no longer means "user opened the panel" -- the panel is
     closed by default here and opened by the JS-toggled [data-open] state, the
     [open] attribute managed by the toggle, or :focus-within for no-JS
     keyboard users.  The marker is hidden because .sf-nav-toggle draws the
     hamburger. */
  .sf-nav-desktop > summary { list-style: none; }
  .sf-nav-desktop > summary::-webkit-details-marker { display: none; }
  /* Panel open state on mobile, in priority order:
     - [data-open]: the JS toggle (authoritative once JS runs).
     - html.sf-no-js + details:not([open]): without JS nothing can add
       [data-open], so the native summary click drives the panel by flipping the
       `open` attribute.  The details ships with `open` (desktop needs it), so
       the no-JS panel starts OPEN here; that is the honest no-JS behaviour --
       every destination is reachable without any scripting.
     - #sf-nav:focus-within: a keyboard user who TABBED INTO the panel keeps it
       open with no JS at all.  This is focus-within on the NAV, not on the
       <details>: the details' own :focus-within also matches while focus sits
       on the summary, which would resurrect a panel that Escape just closed. */
  .sf-nav-desktop[data-open] #sf-nav,
  html.sf-no-js .sf-nav-desktop[open] #sf-nav,
  #sf-nav:focus-within { display: flex; }
  /* The panel outranks the sticky header so it is never stacked behind page
     content; below .sf-skip (60) and above every in-page z-index. */
  .sf-nav-desktop[data-open],
  .sf-nav-desktop:focus-within { z-index: 50; }
  .sf-nav a { justify-content: flex-start; }
  .sf-nav .sf-user-logout { display: block; }
  .sf-nav .sf-user-logout-btn { width: 100%; justify-content: flex-start; text-align: left; }
  /* The identity row is a panel entry like any other link, so it takes the
     panel's own full width; only its inner spacing differs from a link's.  The
     name is deliberately NOT hidden here: in the panel it is the label for the
     initials disc, and the old `.sf-user-name { display: none }` (which made the
     bar pill avatar-only) would leave the disc unlabelled now that the row is
     the only rendering of the identity below 1100px.  It keeps the base rule's
     140px cap and ellipsis so a long name cannot widen the panel. */
  .sf-nav-user { padding: 6px 10px; }
  .sf-hero { padding: 40px 0 32px; }
  .sf-section { padding: 40px 0; }
  .sf-section-head { margin-bottom: 20px; }
  .sf-grid { grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 14px; }
  /* "What we print" is exactly five service cards, so it is pinned rather than
     auto-filled: five across on desktop (the base rule) and two per row below
     the desktop boundary for a scannable mobile grid (5 cards -> 2+2+1). */
  .sf-grid-services { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; }
  .sf-line { grid-template-columns: 64px minmax(0, 1fr); }
  .sf-line-thumb { width: 64px; }
  .sf-line-actions { grid-column: 1 / -1; flex-direction: row; align-items: center; justify-content: space-between; }
  .sf-panel { padding: 18px; }
  .sf-hero-stage { display: none; }
}

/* Very narrow bars: the cart keeps its glyph and count but sheds the word, so
   the brand, cart and hamburger still fit on one line without the label text
   wrapping or crowding the toggle.  This is the only width at which the label
   is hidden; above it the cart reads "cart glyph + Cart + count".

   The brand name gets the same treatment, for the signed-in case: at 320px the
   avatar pill (34px) plus the cart (64px) plus the toggle (42px) plus the row
   gaps leave no room for a 132px brand beside them, and the hamburger wrapped
   onto its own line (measured).  Shrinking the brand to just the 34px mark
   frees exactly the space the pill needs, so brand, avatar, cart and toggle
   share one line again.  aria-label on the brand link is unchanged, so the
   destination is still announced in full. */
@media (max-width: 430px) {
  .sf-cart-label { display: none; }
}


/* Keep the BigPrint4U brand text visible on all mobile widths; do not hide it here. */
  .sf-brand > span:last-child { display: none; }
}

@media (max-width: 430px) {
  .sf-container { width: min(calc(100% - 24px), var(--sf-max)); }
  .sf-hero-actions .sf-btn { width: 100%; }
  .sf-bubble { max-width: 88%; }
  .sf-product-body { padding: 14px; }
  .sf-line { grid-template-columns: 56px minmax(0, 1fr); gap: 12px; }
  .sf-line-thumb { width: 56px; }
}

@media (prefers-reduced-motion: reduce) {
  .sf-btn { transition: none; }
}
