@charset "UTF-8";
/* Store Dashboard — /dashboard.
 *
 * Its own stylesheet, loaded nowhere else. The dashboard is not a
 * storefront page: it carries none of showroom.css, has no template and
 * no store tokens, and a store's own colours must not be able to make
 * its control panel unreadable. Flat CSS with no Sass features, like
 * embed.scss, so the built file and this one stay legible side by side.
 */
:root {
  --d-bg: #f4f5f7;
  --d-panel: #ffffff;
  --d-ink: #16181d;
  --d-muted: #666c78;
  --d-line: #e2e5ea;
  --d-accent: #177a3d;
  --d-accent-ink: #ffffff;
  --d-danger: #b3261e;
  --d-radius: 8px;
}

.dash {
  margin: 0;
  background: var(--d-bg);
  color: var(--d-ink);
  font-family: "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
  font-size: 15px;
  line-height: 1.5;
}

.dash * {
  box-sizing: border-box;
}

/* ---------- the signed-out pages ---------- */
.dash-centre {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  padding: 24px;
}

.dash-card {
  width: 100%;
  max-width: 420px;
  padding: 28px;
  background: var(--d-panel);
  border: 1px solid var(--d-line);
  border-radius: var(--d-radius);
}

.dash-card h1 {
  margin: 0 0 4px;
  font-size: 22px;
}

.dash-card .dash-sub {
  margin: 0 0 20px;
  color: var(--d-muted);
  font-size: 14px;
}

/* ---------- the shell ----------
 *
 * Two slim rows and then the page: an identity bar, a row of tabs, the
 * content. There is no left rail at any width — it cost 232px of every
 * page for seven links, and on the two pages with a preview those 232px
 * were the difference between a legible shop and a picture of one.
 *
 * The tabs are the row that used to appear only under 860px, promoted to
 * every width rather than reimplemented: one set of rules, one set of
 * behaviours, and nothing that can disagree between two breakpoints.
 */
.dash-shell {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

/* One bar: the brand, the tabs, and the two things that are not a page.
 *
 * A single wrapping flex row, not two stacked bars. From 701px up the
 * whole header is one 44px line; below that the tabs take a line of
 * their own and it is 86px. The breakpoint is measured rather than
 * chosen: the brand and the two actions cost about 434px of the row at
 * that size, so at 700px the tabs still have 266px — roughly three of
 * them — and below it they have less than the width of one.
 *
 * Only the tabs scroll. The brand and the two actions sit outside that
 * region, which is the one thing the old under-860px row got wrong: it
 * put "Sign out" and "View your store" inside the scroller, where on a
 * phone they were three tabs to the right of anywhere you could see.
 */
.dash-bar {
  display: flex;
  align-items: stretch;
  flex-wrap: wrap;
  gap: 0 16px;
  flex: 0 0 auto;
  padding: 0 28px;
  background: var(--d-panel);
  border-bottom: 1px solid var(--d-line);
}

/* One line, not two stacked. The eyebrow and the name side by side keep
   the bar at the height of a single row of text, which is the whole
   point of it. */
.dash-brand {
  display: flex;
  align-items: baseline;
  gap: 9px;
  flex: 0 1 auto;
  min-width: 0;
  padding: 13px 0;
}

.dash-brand strong {
  font-size: 15px;
  line-height: 1.2;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.dash-brand span {
  flex: 0 0 auto;
  color: var(--d-muted);
  font-size: 11px;
  line-height: 1.2;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

/* The nav: one disclosure per group.
 *
 * Flat, the twelve tabs and their six labels needed 1,750px and had 966
 * at 1440 and 726 at 1200 — six of twelve tabs visible on a big screen,
 * two of twelve on a phone, and the rest behind a horizontal scroll
 * nobody finds. Six buttons need about a third of that and WRAP rather
 * than scroll, so every group is in view at every width and what is
 * inside one is a press away.
 *
 * <details>/<summary>, not a scripted menu: it opens on Enter and Space,
 * is announced as a disclosure, and works with no JavaScript — the same
 * control the storefront's language and account menus already are.
 */
.dash-groups {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 2px;
  flex: 1 1 320px;
  min-width: 0;
}

.dash-group {
  position: relative;
}

.dash-group > summary {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 9px 10px;
  border-radius: 6px;
  color: var(--d-muted);
  font-size: 14px;
  white-space: nowrap;
  cursor: pointer;
  list-style: none;
}

/* Safari draws its own marker on a summary; the caret below is ours. */
.dash-group > summary::-webkit-details-marker {
  display: none;
}

.dash-group > summary::marker {
  content: "";
}

.dash-group > summary:hover {
  background: var(--d-bg);
  color: var(--d-ink);
}

.dash-group > summary:focus-visible {
  outline: 2px solid var(--d-accent);
  outline-offset: -2px;
}

/* The group holding the current page, and that page's own name inside
   it — so the bar answers "where am I" without being opened. */
.dash-group.on > summary {
  color: var(--d-ink);
}

.dash-group-here {
  font-weight: 600;
}

/* The separator belongs to the page name, not to the group, or a group
   whose page shares its name gets a dangling dot. */
.dash-group-here::before {
  content: "· ";
  color: var(--d-muted);
  font-weight: 400;
}

.dash-group-caret {
  font-size: 10px;
  opacity: 0.6;
}

.dash-group[open] > summary {
  background: var(--d-bg);
  color: var(--d-ink);
}

.dash-group[open] .dash-group-caret {
  transform: rotate(180deg);
}

.dash-group-menu {
  position: absolute;
  z-index: 40;
  top: calc(100% + 4px);
  left: 0;
  min-width: 200px;
  padding: 6px;
  background: var(--d-panel);
  border: 1px solid var(--d-line);
  border-radius: var(--d-radius);
  box-shadow: 0 12px 28px rgba(16, 24, 32, 0.16);
}

/* The last two groups sit near the right edge on a wide screen; their
   menus open leftwards rather than off the page. */
.dash-group:nth-last-child(-n+2) .dash-group-menu {
  left: auto;
  right: 0;
}

.dash-group-menu a {
  display: block;
  padding: 7px 10px;
  border-radius: 5px;
  color: var(--d-ink);
  font-size: 14px;
  text-decoration: none;
  white-space: nowrap;
}

.dash-group-menu a:hover {
  background: var(--d-bg);
}

.dash-group-menu a.on {
  background: var(--d-accent);
  color: var(--d-accent-ink);
  font-weight: 600;
}

.dash-top-acts {
  display: flex;
  align-items: center;
  gap: 2px;
  flex: 0 0 auto;
  /* Hard right whether or not the tabs are on this line. */
  margin-left: auto;
}

/* A link and not a button: it leaves the dashboard, which nothing else
   in this bar does, and that difference should be visible without
   reading the words. */
.dash .dash-top-link {
  padding: 6px 10px;
  border-radius: 6px;
  color: var(--d-accent);
  font-size: 14px;
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
}

.dash .dash-top-link:hover {
  background: var(--d-bg);
}

.dash-top-out {
  padding: 6px 10px;
  border: 0;
  border-radius: 6px;
  background: none;
  color: var(--d-muted);
  font: inherit;
  font-size: 14px;
  white-space: nowrap;
  cursor: pointer;
}

.dash-top-out:hover {
  background: var(--d-bg);
  color: var(--d-ink);
}

.dash-main {
  flex: 1 1 auto;
  min-width: 0;
  padding: 24px 28px 64px;
}

.dash-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  margin-bottom: 18px;
}

.dash-head h1 {
  margin: 0;
  font-size: 24px;
}

/* A measure, not a width. With no left rail the page is 1,144px at 1200
   and a sentence that runs the whole of it is a sentence you lose your
   place in — the reclaimed width belongs to the tables and the fields,
   not to the prose. */
.dash-head p {
  margin: 4px 0 0;
  max-width: 86ch;
  color: var(--d-muted);
  font-size: 14px;
}

/* The template picker: one tile per template, the one in use marked.
   Radios rather than a select, because choosing a look is a choice you
   want to see all of at once.

   164px is derived, not chosen. A tile has to hold the radio (13), the
   longest name ("Botanical", 67), the Live badge (40) and two 8px gaps —
   136px of content, 160 with the padding — or the badge wraps to a line
   of its own and makes that whole grid row half again as tall. At 164
   two columns need 336px inside the panel, which the 380px rail has and
   no narrower rail does; below that it is one wide column, where nothing
   can wrap at all. So there is no rail width, dragged or default, at
   which the badge wraps. */
.dash-templates {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(164px, 1fr));
  gap: 8px;
}

.dash-template {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px 8px;
  padding: 10px 12px;
  border: 1px solid var(--d-line);
  border-radius: var(--d-radius);
  background: #ffffff;
  cursor: pointer;
}

/* Chrome gives a radio `margin: 3px 3px 0 5px`, which is 8px of the
   tile nobody asked for and nobody can see — and the 8px that pushed the
   badge onto a second line. */
.dash-template input {
  flex: 0 0 auto;
  margin: 0;
}

.dash-template:hover {
  border-color: var(--d-accent);
}

.dash-template.on {
  border-color: var(--d-accent);
  box-shadow: inset 0 0 0 1px var(--d-accent);
}

.dash-template-name {
  font-weight: 600;
}

.dash-template-now {
  margin-left: auto;
  flex: 0 0 auto;
  padding: 1px 7px;
  border-radius: 999px;
  background: var(--d-accent);
  color: var(--d-accent-ink);
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

/* The section list: one row per section, an arrow pair, a switch and
   whatever copy that section owns. */
.dash-sections {
  margin: 0;
  padding: 0;
  list-style: none;
}

.dash-section {
  display: grid;
  grid-template-columns: 32px 44px minmax(0, 1fr);
  gap: 12px;
  align-items: start;
  padding: 14px 0;
  border-top: 1px solid var(--d-line);
}

.dash-section:first-child {
  border-top: 0;
}

.dash-section-move {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.dash-section-move button {
  width: 32px;
  height: 22px;
  padding: 0;
  border: 1px solid var(--d-line);
  border-radius: 4px;
  background: #ffffff;
  color: var(--d-muted);
  font: inherit;
  line-height: 1;
  cursor: pointer;
}

.dash-section-move button:hover {
  border-color: var(--d-accent);
  color: var(--d-accent);
}

.dash-section-body > strong {
  display: block;
}

.dash-section-body > .dash-note {
  display: block;
}

/* A switch that is a checkbox underneath, so it works without
   JavaScript and reads as a checkbox to a screen reader. */
.dash-switch {
  position: relative;
  display: block;
  width: 44px;
  height: 24px;
  margin-top: 2px;
}

.dash-switch input {
  position: absolute;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}

.dash-switch span {
  position: absolute;
  inset: 0;
  border-radius: 999px;
  background: #c9ced6;
  transition: background 0.15s;
  pointer-events: none;
}

.dash-switch span::after {
  content: "";
  position: absolute;
  top: 3px;
  left: 3px;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: #ffffff;
  transition: transform 0.15s;
}

.dash-switch input:checked + span {
  background: var(--d-accent);
}

.dash-switch input:checked + span::after {
  transform: translateX(20px);
}

.dash-switch input:focus-visible + span {
  outline: 2px solid var(--d-accent);
  outline-offset: 2px;
}

.dash-field-inline {
  margin: 10px 0 0;
  max-width: 560px;
}

.dash-field-inline > span:first-child {
  font-weight: 500;
}

.dash-sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* Two panels side by side, where the page has the width for it and the
   two belong together — what you add beside what is synced, the list
   beside the picker, the words beside the picture. `auto-fit` with a
   real minimum is what makes it one column on a phone without a second
   rule: below about 800px the second track cannot be built, so there is
   not one.

   `align-items: start` so a short panel does not stretch to the height
   of a tall one and sit half empty. */
.dash-cols {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(360px, 1fr));
  gap: 0 18px;
  align-items: start;
}

/* A table is the one thing on these pages allowed to be wider than the
   page, so it gets a box of its own to be wider inside. Without it a
   375px screen scrolled sideways on Sellers, Collections and Reviews —
   which it did before any of this too; six columns of real data do not
   fit on a phone however they are sized, and the honest answer is to let
   the table scroll rather than to crush the columns until it fits. */
.dash-tablewrap {
  overflow-x: auto;
  overscroll-behavior-x: contain;
  -webkit-overflow-scrolling: touch;
}

/* A plain table for the lists: sellers, collections, reviews.

   Column widths are set by the cells, not by the browser sharing the
   width equally: a column holding "0" and a column holding a tagline
   both got a fifth of 1,144px, which is how a wider page turns into a
   sparser one instead of a better one. `.dash-col-tight` shrinks to its
   content and `.dash-col-wide` takes what is left. */
.dash-table {
  width: 100%;
  border-collapse: collapse;
}

.dash-table th,
.dash-table td {
  padding: 10px 12px 10px 0;
  border-bottom: 1px solid var(--d-line);
  text-align: left;
  vertical-align: top;
}

.dash-table th {
  font-size: 12px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--d-muted);
}

.dash-table tr:last-child td {
  border-bottom: 0;
}

/* 1% rather than 0: a percentage is resolved against the table and then
   raised to fit the content, which is the shrink-to-fit every browser
   agrees on. */
.dash-table .dash-col-tight {
  width: 1%;
  white-space: nowrap;
}

/* No width at all, deliberately. `width: 100%` here drove every other
   column to min-content — "verified purchase" became three lines to buy
   slack for a cell that did not need it. Left alone, the auto algorithm
   shares what the tight columns did not take between the columns that
   have something to say, in proportion to how much they have to say,
   which is the answer this was reaching for. */
.dash-table .dash-col-wide {
  min-width: 30%;
}

/* A name column. Not `tight`, because a product title has no business
   being nowrap — that is how one long name makes the table wider than
   the page. And deliberately no `width`: a stated width sends the auto
   table algorithm towards min-content and wrapped "Hollantilaisia
   lastenkirjoja" to two lines while 200px sat unused two columns over.
   With only a cap, the column asks for its longest name, gets it up to
   320px, and `.dash-col-wide` still takes every pixel that is left. */
.dash-table .dash-col-name {
  max-width: 320px;
}

/* The last column is whatever acts on the row. Hard right, so the
   buttons line up with each other rather than with the text beside
   them. */
.dash-table .dash-col-act {
  width: 1%;
  padding-right: 0;
  white-space: nowrap;
  text-align: right;
}

/* A long synced field in a table cell: two lines, then an ellipsis. The
   whole of it is on the seller's own page; here it only has to say
   whether there is anything. */
.dash-clamp {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
}

/* Small marks for "this is set" — a website, a social account. Quieter
   than a chip, which is a thing you click. */
.dash-marks {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-top: 4px;
}

.dash-mark {
  padding: 1px 7px;
  border: 1px solid var(--d-line);
  border-radius: 999px;
  color: var(--d-muted);
  font-size: 11px;
  white-space: nowrap;
}

/* What the store itself has added to a synced row. */
.dash-added {
  display: flex;
  align-items: center;
  gap: 10px;
}

.dash-added-banner {
  flex: 0 0 auto;
  width: 96px;
  height: 40px;
  border-radius: 4px;
  background: var(--d-bg);
  -o-object-fit: cover;
     object-fit: cover;
}

.dash-table td .dash-note {
  display: block;
}

.dash-chip {
  display: inline-block;
  margin: 0 6px 6px 0;
  padding: 4px 10px;
  border: 1px solid var(--d-line);
  border-radius: 999px;
  background: #ffffff;
  color: var(--d-ink);
  font-size: 13px;
  text-decoration: none;
}

a.dash-chip:hover {
  border-color: var(--d-accent);
  color: var(--d-accent);
}

/* An ordered list you can reorder: chosen products, pinned sellers. */
.dash-picked {
  margin: 0 0 14px;
  padding: 0;
  list-style: none;
  counter-reset: picked;
}

.dash-picked li {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 0;
  border-bottom: 1px solid var(--d-line);
  counter-increment: picked;
}

.dash-picked li::before {
  content: counter(picked);
  flex: 0 0 22px;
  color: var(--d-muted);
  font-size: 13px;
  text-align: right;
}

.dash-picked li > span:first-of-type {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.dash-picked-buttons {
  display: flex;
  gap: 4px;
}

.dash-picked-buttons button {
  width: 30px;
  height: 26px;
  padding: 0;
  border: 1px solid var(--d-line);
  border-radius: 4px;
  background: #ffffff;
  color: var(--d-muted);
  font: inherit;
  line-height: 1;
  cursor: pointer;
}

.dash-picked-buttons button:hover {
  border-color: var(--d-accent);
  color: var(--d-accent);
}

/* The draft bar: what is unpublished, and the two things to do about
   it. Quiet when there is nothing to publish, so it is not a permanent
   alarm. */
.dash-draftbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  margin: 0 0 18px;
  padding: 12px 16px;
  border: 1px solid var(--d-line);
  border-radius: var(--d-radius);
  background: var(--d-panel);
}

.dash-draftbar.on {
  border-color: #e0b44a;
  background: #fdf7e8;
}

.dash-draftbar-says strong {
  display: block;
}

.dash-draftbar-buttons {
  display: flex;
  align-items: center;
  gap: 8px;
}

/* Where the band would wrap to two or three rows, the sentence under the
   heading goes: "Unpublished changes" with Publish beside it already
   says the whole of it, and on a narrow screen the rows it costs are
   rows the preview does not get. */
@media (max-width: 1060px) {
  .dash-draftbar-says .dash-note {
    display: none;
  }
}
@media (max-width: 560px) {
  .dash-draftbar {
    gap: 10px;
  }
  .dash-draftbar-buttons {
    width: 100%;
  }
}
.dash-draftbar-buttons button[disabled] {
  opacity: 0.45;
  cursor: default;
}

/* ---------- the split: controls one side, preview the other ----------
 *
 * Below 900px this is one column, preview first. Above it, an explicit
 * two-column grid — the source order puts the preview first for the
 * phone, so the desktop places both by grid-column rather than relying
 * on it.
 *
 * **The page is an ordinary scrolling page and the preview is an
 * ordinary sticky sidebar.** It used to own the viewport: body and shell
 * at `height: 100vh; overflow: hidden`, and the controls column with a
 * scrollbar of its own. That kept the iframe permanently in view, and it
 * cost the thing people do without thinking — a wheel over the page
 * scrolled nothing unless the pointer happened to be inside the one box
 * that scrolled, and the browser's own scrollbar was gone. Now the whole
 * page scrolls, the wheel works wherever the pointer is, and the preview
 * follows down the column until the controls run out beneath it, which
 * is the behaviour every sidebar on the web has.
 *
 * The sticky element is the PANEL, not the column: a grid item stretched
 * to the row's height has nowhere to move, so the column stretches and
 * the panel inside it sticks.
 */
.dash-split {
  display: grid;
  /* minmax(0, 1fr), not the implicit `auto`: an auto grid track is sized
     to its max-content, and the preview iframe is deliberately 1280px
     wide (scaled down by transform, which does not change layout size).
     Left as auto, that 1280 pushed the single column past the viewport
     and the whole page scrolled sideways. */
  grid-template-columns: minmax(0, 1fr);
  gap: 16px;
}

/* Under 900px there is no room for two columns, so the preview goes
   above the controls — and is PINNED there.

   Measured at 375, the three arrangements cost this much scrolling:

     preview above, not pinned   see it: 112px   control -> preview: 1849px
     controls above, not pinned  see it: 1439px  control -> preview:  172px
     preview above, pinned       see it:   0px   control -> preview:    0px

   Both plain orders have one bad number, because the preview is a 480px
   object at one end of a 2,400px page: put it first and every control
   is a long way from it, put it last and it is a long way from the top.
   Pinning it answers both — the thing you are looking at while you work
   stays in front of you — and costs the top third of the screen, which
   on a page whose purpose is watching your shop change is what that
   third is for. */
@media (max-width: 899px) {
  /* One column, so there is nothing to divide. */
  .dash-split-grip {
    display: none;
  }
  .dash-split-preview {
    position: sticky;
    top: 0;
    z-index: 3;
    /* The panel is the pinned thing, so it needs a ground of its own:
       the controls scroll underneath it. */
    margin: 0 -16px;
    padding: 0 16px 8px;
    background: var(--d-bg);
  }
  .dash-split-preview .dash-panel {
    margin-bottom: 0;
    box-shadow: 0 6px 14px rgba(16, 24, 32, 0.08);
  }
  .dash-split-preview .dash-preview-frame iframe {
    /* A third of the screen, never less than a usable strip. */
    height: calc(38vh / var(--preview-scale, 1));
    min-height: calc(220px / var(--preview-scale, 1));
  }
  /* The bleed has to match .dash-main's own side padding, or the
     controls show through the gap as they scroll under the pinned
     panel. Main is 28px until the sidebar stacks at 860 and 16px after,
     so this window needs the wider one. */
  /* The sentence under the frame is for a desktop, where there is room.
     Pinned on a phone it would be 40px of the screen spent explaining
     the thing it is covering. */
}
@media (max-width: 899px) and (min-width: 861px) {
  .dash-split-preview {
    margin: 0 -28px;
    padding: 0 28px 8px;
  }
}
@media (max-width: 899px) {
  .dash-split-preview > .dash-panel > .dash-note:last-child {
    display: none;
  }
}
@media (min-width: 900px) {
  /* How far from the top of the viewport the pinned panel sits, and how
     much of the viewport it may take. One pair of numbers, because the
     panel's `top` and its height have to agree or the bottom of the
     iframe falls off the screen. */
  body.dash-split-page {
    --dash-sticky-top: 16px;
    --dash-sticky-gap: 20px;
  }
  .dash-split {
    /* The controls are a rail and the preview takes everything else. Not
       two proportional columns: the preview renders a 1280px page scaled
       to fit, so every pixel the controls do not need is a pixel of
       legibility — at 1200 a proportional split gave the preview 443px
       (34% scale) and the rail gives it 532 (42%), and the controls lose
       nothing they were using.

       --dash-rail is the owner's own width, dragged on the grip and kept
       in their browser.

       380px, up from the 340 it was while the page also carried a 232px
       left rail. With that rail gone the split is 1,144px at 1200 rather
       than 912, and 40 of the 232 buys the template picker a second
       column that cannot wrap its badge (see .dash-templates) while the
       preview still goes from 539px to 731 — a 42% render to a 57% one.
       The other 192 are the preview's. */
    grid-template-columns: var(--dash-rail, 380px) 5px minmax(0, 1fr);
    gap: 0 14px;
    /* Stretch, not start: the grip has to reach the full height of the
       row and the preview column has to be tall enough for the panel
       inside it to have somewhere to stick. */
    align-items: stretch;
  }
  .dash-split-grip {
    grid-column: 2;
    grid-row: 1;
    position: relative;
    align-self: stretch;
    width: 5px;
    border-radius: 3px;
    background: var(--d-line);
    cursor: col-resize;
    transition: background 0.12s;
  }
  /* The hit area is wider than the line, because a 5px target is a
     5px target however it is drawn. */
  .dash-split-grip::before {
    content: "";
    position: absolute;
    inset: 0 -7px;
  }
  .dash-split-grip:hover,
  .dash-split-grip:focus-visible,
  .dash-split-grip.dragging {
    background: var(--d-accent);
    outline: none;
  }
  /* While dragging, nothing else should take the pointer — least of all
     the iframe, which would swallow it the moment the cursor crossed
     into the preview. */
  body.dash-dragging,
  body.dash-dragging * {
    cursor: col-resize !important;
    -webkit-user-select: none;
       -moz-user-select: none;
            user-select: none;
  }
  body.dash-dragging iframe {
    pointer-events: none;
  }
  /* An ordinary column now. No scrollbar of its own, nothing capped to
     the viewport: it is as tall as its fields and the page scrolls. */
  .dash-split-controls {
    grid-column: 1;
    grid-row: 1;
    padding-bottom: 24px;
  }
  .dash-split-preview {
    grid-column: 3;
    grid-row: 1;
  }
  /* The sidebar. A DEFINITE height, not a max-height: the iframe's own
     height is a percentage of this box divided by its scale, and a
     percentage needs something definite to be a percentage of. That
     definiteness is the one thing the old viewport-owning layout
     provided that a plain scrolling page does not, so it is stated here
     rather than inherited from a flex chain — see the note on
     .dash-preview-frame iframe. The scaled WIDTH never depended on it:
     fit() reads the pane's clientWidth, which is a layout width either
     way. */
  .dash-split-preview .dash-panel {
    position: sticky;
    top: var(--dash-sticky-top);
    display: flex;
    flex-direction: column;
    height: calc(100vh - var(--dash-sticky-top) - var(--dash-sticky-gap));
    margin-bottom: 0;
  }
  .dash-split-preview .dash-preview-frame {
    flex: 1 1 auto;
    min-height: 0;
  }
  .dash-split-preview .dash-preview-frame iframe {
    height: calc(100% / var(--preview-scale, 1));
    min-height: 0;
  }
  /* The line under the frame explains the pane; with the frame filling
     the column it would push the frame out of it. */
  .dash-split-preview > .dash-panel > .dash-note:last-child {
    display: none;
  }
}
/* ---------- full size ----------
 *
 * The preview takes the window and the controls step aside. Nothing is
 * re-rendered and nothing is reloaded: the same element is moved, so the
 * draft on screen and the scroll position of the controls behind it are
 * where they were when the button was pressed.
 *
 * `position: fixed` and not a dialog, because the iframe must keep its
 * document — showModal() on an ancestor would not reload it, but moving
 * the element in the DOM would, and a <dialog> wrapper is a move.
 */
body.dash-preview-full-on {
  overflow: hidden;
}

body.dash-preview-full-on .dash-split-preview {
  position: fixed;
  inset: 0;
  z-index: 60;
  margin: 0;
  padding: 0;
  background: var(--d-bg);
}

body.dash-preview-full-on .dash-split-preview .dash-panel {
  position: static;
  height: 100vh;
  margin: 0;
  border: 0;
  border-radius: 0;
}

/* The rest of the page is still there, still scrolled where it was, and
   out of the way — hidden from a screen reader too, since it cannot be
   reached while the preview is over it. */
body.dash-preview-full-on .dash-bar,
body.dash-preview-full-on .dash-head,
body.dash-preview-full-on .dash-draftbar,
body.dash-preview-full-on .dash-split-controls,
body.dash-preview-full-on .dash-split-grip {
  visibility: hidden;
}

.dash-preview-full {
  margin-left: 6px;
}

/* The preview's language, in the dashboard's chrome rather than inside
   the shop. Small and quiet: it is a way of checking, not a setting. */
.dash-preview-lang select {
  padding: 4px 6px;
  border: 1px solid var(--d-line);
  border-radius: 6px;
  background: #ffffff;
  color: var(--d-ink);
  font: inherit;
  font-size: 13px;
}

/* The block a store writes for itself, as the front page draws it. */
.dash-commercial-note {
  margin-top: 10px;
}

/* The preview pane: the real store page in an iframe. */
.dash-preview-head {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 10px;
}

.dash-preview-head h2 {
  margin: 0;
  font-size: 17px;
}

.dash-preview-sizes {
  display: flex;
  gap: 6px;
  margin-left: auto;
}

.dash-preview-sizes button.on {
  background: var(--d-accent);
  color: var(--d-accent-ink);
}

.dash-preview-frame {
  overflow: hidden;
  border: 1px solid var(--d-line);
  border-radius: var(--d-radius);
  background: #ffffff;
}

/* The iframe is rendered at --preview-w (a real viewport width) and
   scaled by --preview-scale to fit the column, so "Desktop" shows the
   desktop layout even in a 445px-wide column. The height is divided by
   the same scale, so the scaled result fills the box exactly. Both
   properties are set by the layout's script; the fallbacks here are what
   a visitor without JavaScript gets, which is the old behaviour — an
   iframe as wide as its column. */
.dash-preview-frame iframe {
  display: block;
  width: var(--preview-w, 100%);
  height: calc(70vh / var(--preview-scale, 1));
  min-height: calc(480px / var(--preview-scale, 1));
  border: 0;
  transform: scale(var(--preview-scale, 1));
  transform-origin: top left;
}

/* Phone width, centred, so the frame itself stays where it is. */
.dash-preview-frame.phone {
  max-width: 390px;
  margin: 0 auto;
}

/* Where a domain's own design stands in front of this store's. Amber
   rather than red: nothing is broken and nothing was lost — the settings
   are saved and will apply everywhere else. The same ground the draft
   band uses when there is something unpublished, for the same reason. */
.dash-shadowed {
  margin: 0 0 18px;
  padding: 14px 16px;
  border: 1px solid #e0b44a;
  border-radius: var(--d-radius);
  background: #fdf7e8;
}

.dash-shadowed > strong {
  display: block;
  margin-bottom: 4px;
}

.dash-shadowed .dash-note {
  margin: 0 0 8px;
  max-width: 90ch;
}

.dash-shadowed .dash-note:last-child {
  margin-bottom: 0;
}

.dash-shadowed-list {
  margin: 0 0 8px;
  padding-left: 20px;
  font-size: 14px;
}

.dash-shadowed-list li {
  margin-bottom: 2px;
}

/* ---------- the examples gallery ---------- */
/* Two columns at most, never three or four. Six cards three-across is a
   contact sheet; two-across each card is wide enough to draw a shop in
   and read the words beside it. One column below 720px. */
.dash-examples {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 340px), 1fr));
  gap: 18px;
  margin: 0 0 18px;
  max-width: 1080px;
}

@media (min-width: 720px) {
  .dash-examples {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}
.dash-example {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: var(--d-panel);
  border: 1px solid var(--d-line);
  border-radius: var(--d-radius);
}

/* ---------- the miniature ----------
 *
 * A shop drawn from the example's own token values: its ground, ink,
 * accent and surface, its own two fonts, its corner radii, its card
 * treatment, where its logo sits and where its icons sit. Every value
 * arrives as a custom property on the element, put there by the view
 * from StoreExample::swatch(), which reads StoreTheme::PRESETS — so a
 * card cannot show a colour, a face or a radius the template has not
 * got.
 *
 * Not an iframe: six live renders for one tab load. Not a screenshot:
 * a file to keep in step with a constant, wrong the first time a
 * palette moved.
 */
.dash-example-shop {
  padding: 12px;
  background: var(--x-bg);
  color: var(--x-ink);
  font-family: var(--x-font);
  font-size: 11px;
  line-height: 1.35;
  border-bottom: 1px solid var(--d-line);
  overflow: hidden;
}

.dash-x-utilbar {
  display: flex;
  justify-content: flex-end;
  gap: 5px;
  margin: -12px -12px 8px;
  padding: 5px 12px;
  background: var(--x-surface);
}

.dash-x-utilbar span {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--x-ink);
  opacity: 0.38;
}

.dash-x-head {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 8px;
}

.dash-x-head-logo-centred {
  flex-direction: column;
  gap: 6px;
}

.dash-x-logo {
  display: flex;
  align-items: center;
  gap: 6px;
  font-family: var(--x-head);
  font-size: 15px;
  font-weight: 700;
}

.dash-x-mark {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--x-brand);
}

.dash-x-icons {
  display: flex;
  gap: 5px;
  margin-left: auto;
}

.dash-x-head-logo-centred .dash-x-icons {
  margin: 0;
}

.dash-x-icons span {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--x-ink);
  opacity: 0.38;
}

.dash-x-nav {
  display: flex;
  gap: 5px;
  margin-bottom: 10px;
  overflow: hidden;
}

.dash-x-nav span {
  padding: 2px 7px;
  border-radius: var(--x-pill);
  background: var(--x-surface);
  font-size: 10px;
  white-space: nowrap;
}

.dash-x-nav span.on {
  background: var(--x-accent);
  color: var(--x-bg);
}

.dash-x-hero {
  display: block;
  margin-bottom: 10px;
  padding: 12px;
  border-radius: var(--x-radius-lg);
  background: var(--x-surface);
}

.dash-x-title {
  display: block;
  font-family: var(--x-head);
  font-size: 19px;
  line-height: 1.15;
  font-weight: 700;
}

.dash-x-text {
  display: block;
  margin: 4px 0 8px;
  opacity: 0.72;
}

.dash-x-btn {
  display: inline-block;
  padding: 4px 10px;
  border-radius: var(--x-radius);
  background: var(--x-accent);
  color: var(--x-bg);
  font-size: 10px;
  font-weight: 600;
}

.dash-x-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 7px;
}

.dash-x-card {
  display: block;
  min-width: 0;
}

/* A fixed height, not the shop's 4:5. The miniature is about the shape
   of a card, not its proportions, and 4:5 of a 160px column is 200px of
   empty tint before the words start. */
.dash-x-photo {
  display: block;
  height: 62px;
  margin-bottom: 4px;
  border-radius: var(--x-radius);
  background: var(--x-surface);
}

.dash-x-name {
  display: block;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  font-size: 10px;
}

.dash-x-price {
  display: block;
  font-size: 10px;
  font-weight: 700;
}

/* The five card treatments, as the shop draws them. */
.dash-x-cards-boxed .dash-x-card {
  padding: 5px;
  border: 1px solid var(--x-ink);
  border-radius: var(--x-radius);
  border-color: color-mix(in srgb, var(--x-ink) 18%, transparent);
}

.dash-x-cards-elevated .dash-x-card {
  padding: 5px;
  border-radius: var(--x-radius);
  background: #ffffff;
  box-shadow: 0 3px 10px rgba(16, 24, 32, 0.14);
}

.dash-x-cards-soft .dash-x-card {
  padding: 5px;
  border-radius: var(--x-radius-lg);
  background: var(--x-surface);
}

.dash-x-cards-soft .dash-x-photo {
  background: var(--x-bg);
}

/* Editorial: the words over the photo, at its foot. */
.dash-x-cards-editorial .dash-x-card {
  position: relative;
}

/* Editorial puts white words over the photo, which works on a real
   photo and not on a pale tint — so the miniature's stand-in is ink at
   a low opacity rather than the surface colour. */
.dash-x-cards-editorial .dash-x-photo {
  height: 82px;
  margin: 0;
  background: color-mix(in srgb, var(--x-ink) 62%, var(--x-surface));
}

.dash-x-cards-editorial .dash-x-name,
.dash-x-cards-editorial .dash-x-price {
  position: absolute;
  left: 4px;
  color: #ffffff;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.7);
}

.dash-x-cards-editorial .dash-x-name {
  bottom: 13px;
}

.dash-x-cards-editorial .dash-x-price {
  bottom: 2px;
}

.dash-example-body {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  padding: 16px;
}

.dash-example-body > h2 {
  margin: 0 0 4px;
  font-size: 17px;
}

.dash-example-body > .dash-note {
  margin: 0 0 12px;
}

.dash-example-act {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-top: auto;
  padding-top: 12px;
}

/* ---------- the similar-products switches ---------- */
.dash-match {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 6px 14px;
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid var(--d-line);
}

.dash-check {
  display: flex;
  align-items: start;
  gap: 8px;
  font-size: 13px;
}

.dash-check input {
  flex: 0 0 auto;
  margin: 3px 0 0;
  width: auto;
}

.dash-check .dash-note {
  display: block;
  font-weight: 400;
}

/* Inside the control rail the fields are tighter than elsewhere in the
   dashboard: this is a 340px column beside a preview, not a page of
   forms, and every row saved is a row less to scroll past. The other
   dashboard pages keep the roomier spacing. */
.dash-split-controls .dash-field {
  margin-bottom: 10px;
}

.dash-split-controls .dash-field > span {
  margin-bottom: 2px;
  font-size: 12px;
}

.dash-split-controls .dash-field input[type=text],
.dash-split-controls .dash-field input[type=email],
.dash-split-controls .dash-field input[type=url],
.dash-split-controls .dash-field select,
.dash-split-controls .dash-field textarea {
  padding: 7px 10px;
}

.dash-split-controls .dash-panel {
  padding: 16px;
  margin-bottom: 14px;
}

.dash-split-controls .dash-panel > h2 {
  font-size: 15px;
}

/* ---------- panels, forms, controls ---------- */
.dash-panel {
  margin: 0 0 18px;
  padding: 20px;
  background: var(--d-panel);
  border: 1px solid var(--d-line);
  border-radius: var(--d-radius);
}

.dash-panel > h2 {
  margin: 0 0 4px;
  font-size: 17px;
}

.dash-panel > .dash-note {
  margin: 0 0 16px;
  max-width: 90ch;
}

.dash-note {
  color: var(--d-muted);
  font-size: 13px;
}

.dash-field {
  display: block;
  margin: 0 0 14px;
}

.dash-field > span {
  display: block;
  margin-bottom: 4px;
  font-size: 13px;
  font-weight: 600;
}

.dash-field input[type=text],
.dash-field input[type=email],
.dash-field input[type=password],
.dash-field input[type=url],
.dash-field select,
.dash-field textarea {
  width: 100%;
  padding: 9px 11px;
  border: 1px solid var(--d-line);
  border-radius: 6px;
  background: #ffffff;
  color: var(--d-ink);
  font: inherit;
}

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

/* Fields in columns. The maximum matters as much as the minimum: with
   `1fr` and a 1,144px page, six fields became five columns of 200px and
   then one, which is neither a row nor a form. Bounded, they are as many
   360px columns as fit and the rest of the panel is margin — which is
   what a text field wants beside it. */
.dash-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 360px));
  gap: 0 18px;
}

/* An author rule that sets `display` beats the UA stylesheet's
   `[hidden] { display: none }`, so the attribute is inert without this —
   the same trap the nav chevrons fell into. The autosave hides the
   form's submit button with it. */
.dash-btn[hidden],
.dash-btn-o[hidden] {
  display: none;
}

.dash-btn,
.dash-btn-o {
  display: inline-block;
  padding: 9px 16px;
  border: 1px solid var(--d-accent);
  border-radius: 6px;
  font: inherit;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
}

.dash-btn {
  background: var(--d-accent);
  color: var(--d-accent-ink);
}

.dash-btn-o {
  background: none;
  color: var(--d-accent);
}

.dash-btn-small {
  padding: 5px 10px;
  font-size: 13px;
}

.dash-flash {
  margin: 0 0 18px;
  padding: 12px 14px;
  border: 1px solid #bfe3cd;
  border-radius: var(--d-radius);
  background: #eaf7f0;
  color: #145c31;
}

.dash-errors {
  margin: 0 0 18px;
  padding: 12px 14px;
  border: 1px solid #f0c4c1;
  border-radius: var(--d-radius);
  background: #fdeceb;
  color: var(--d-danger);
}

.dash-errors ul {
  margin: 0;
  padding-left: 18px;
}

/* A value the store does not own: shown, never editable. */
.dash-readonly {
  padding: 9px 11px;
  border: 1px dashed var(--d-line);
  border-radius: 6px;
  background: #fafbfc;
  color: var(--d-muted);
  white-space: pre-wrap;
}

.dash-synced {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 7px;
  border-radius: 999px;
  background: #eef1f5;
  color: var(--d-muted);
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

/* The shell's side padding is one number in two places — the bar and the
   page — so the first tab lines up with the heading rather than nearly
   with it. 28px down to 860, 16px after, which is what .dash-main has
   always used. */
@media (max-width: 860px) {
  .dash-bar {
    padding: 0 16px;
  }
  .dash-main {
    padding: 18px 16px 48px;
  }
}
/* Under 820px the groups get a line of their own — brand and actions
   keep the first one, so the two things you always want are always in
   the same place and only the six you sometimes want move. `order` is
   what sends them down: flex wraps in order order, and the source has
   them in the middle because that is where they belong on one line. */
@media (max-width: 820px) {
  .dash-top-acts {
    order: 2;
  }
  .dash-groups {
    order: 3;
    flex-basis: 100%;
  }
}
/* A phone has room for the shop's name or for the word above it, not
   both, and the name is the half that says which shop this is. */
@media (max-width: 560px) {
  .dash-brand span {
    display: none;
  }
  .dash-brand {
    padding: 11px 0;
  }
  .dash .dash-top-link,
  .dash-top-out {
    padding: 6px 7px;
    font-size: 13px;
  }
}
/* ---------- Compare: two examples, rendered full size, side by side ----------
   The gallery answers "what are these six?"; this answers "which of these
   two?", which a miniature drawn from five tokens cannot. Everything here
   is about giving two real renders as much width as the screen has. */
/* The page gives its gutters up. 28px each side is right for a column of
   prose and wrong for two shops: at 1200 it is 56px off a pane pair, which
   is a category chip and a bit of the next. */
.dash-compare-page .dash-main {
  padding-left: 14px;
  padding-right: 14px;
  padding-bottom: 24px;
}

/* One wrapping row. The pickers first because they are what is being
   chosen, the page switcher next because it moves both, and the two
   switches after, where they read as settings rather than as choices. */
.dash-compare-bar {
  /* Sticky, so the controls are still there once you have scrolled the
     two shops up to fill the screen — which is the whole way this page
     is used. Without it, changing the page type means scrolling back up
     past a 180px note to reach the switcher. */
  position: sticky;
  top: 0;
  z-index: 3;
  display: flex;
  align-items: flex-end;
  flex-wrap: wrap;
  gap: 12px 16px;
  padding: 12px 14px;
  margin-bottom: 12px;
  background: var(--d-panel);
  border: 1px solid var(--d-line);
  border-radius: var(--d-radius);
}

.dash-compare-pick {
  min-width: 200px;
  flex: 0 1 240px;
  margin: 0;
}

/* The page switcher: a real radio group, drawn as one control. */
.dash-compare-pages {
  display: flex;
  align-items: center;
  gap: 0;
  border: 1px solid var(--d-line);
  border-radius: var(--d-radius);
  padding: 0;
  margin: 0;
  overflow: hidden;
}

.dash-compare-pages legend {
  /* Announced, never drawn: the three labels say what the group is. */
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.dash-seg {
  position: relative;
  display: block;
}

/* The radio itself stays in the page — focusable, announced, and where a
   screen reader expects it — and is simply not painted. `opacity: 0` and
   not `display: none`, which would take it out of the tab order. */
.dash-seg input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}

.dash-seg span {
  display: block;
  padding: 8px 14px;
  font-size: 13px;
  font-weight: 600;
  color: var(--d-muted);
  border-left: 1px solid var(--d-line);
  white-space: nowrap;
}

.dash-seg:first-of-type span {
  border-left: 0;
}

.dash-seg input:checked + span {
  background: var(--d-accent);
  color: var(--d-accent-ink);
}

/* The focus ring belongs on the thing that is drawn, not on the invisible
   input: a ring around a 0-opacity box is a ring nobody sees. */
.dash-seg input:focus-visible + span {
  outline: 2px solid var(--d-accent);
  outline-offset: -2px;
}

.dash-compare-sync {
  margin: 0 0 4px;
  white-space: nowrap;
}

.dash-compare-go {
  margin-left: auto;
}

/* Two panes, equal width, and `minmax(0, 1fr)` rather than `1fr` so a
   1280px-wide render inside cannot push the grid past the page — the same
   trap the stacked draft preview hit. */
.dash-compare-panes {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
  align-items: stretch;
}

.dash-compare-pane {
  display: flex;
  flex-direction: column;
  min-width: 0;
  background: var(--d-panel);
  border: 1px solid var(--d-line);
  border-radius: var(--d-radius);
  overflow: hidden;
}

.dash-compare-head {
  padding: 10px 12px;
  border-bottom: 1px solid var(--d-line);
}

.dash-compare-head h2 {
  margin: 0;
  font-size: 15px;
  line-height: 1.3;
}

.dash-compare-head .dash-marks {
  margin: 6px 0 0;
}

/* The render. A window onto the page, both panes the same height, each
   scrolling inside itself — a shop page is some fourteen thousand pixels
   tall and two of them laid out in full would be a page you cannot hold
   two things in your head across. The height is stated against the
   viewport so both windows are always the same and always the tallest the
   screen allows. */
.dash-compare-frame {
  display: block;
  width: 100%;
  /* The fallback is a guess at the chrome above the panes and is what a
     browser with no scripting gets; `--dash-compare-h` is that same
     number measured, set by the page's own fit(). */
  height: var(--dash-compare-h, calc(100vh - 260px));
  min-height: 380px;
  border: 0;
  background: #ffffff;
}

.dash-compare-note {
  margin-top: 14px;
}

/* Below 900px the two stack. There is no arrangement in which two
   real-width renders sit side by side on a phone: half of 375px is 187,
   which is narrower than a single product card, so both panes would be
   showing the shop's one-column layout squeezed — two pictures of nothing
   rather than a comparison. Stacked, each pane is the full width of the
   screen and each render is honest for that width; the page switcher and
   the scroll lock still move both. */
@media (max-width: 899px) {
  .dash-compare-panes {
    grid-template-columns: minmax(0, 1fr);
  }
  .dash-compare-frame {
    height: var(--dash-compare-h, calc(100vh - 320px));
    min-height: 380px;
  }
  .dash-compare-pick {
    flex: 1 1 100%;
  }
  .dash-compare-go {
    margin-left: 0;
  }
}
/* ---------- a site's raw HTML, read-only ----------
   Shown so an operator can see what is standing in front of the fields
   above it, and removed if that is what they want. Never edited here:
   raw HTML can carry a script, and a site login is issued for design. */
.dash-raw {
  max-height: 260px;
  overflow: auto;
  margin: 0 0 12px;
  padding: 12px 14px;
  background: #f6f7f9;
  border: 1px solid var(--d-line);
  border-radius: var(--d-radius);
  font: 12px/1.6 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  color: #3a404a;
  /* Long unbroken markup must not push the page sideways; it scrolls in
     its own box, the rule every wide thing here follows. */
  white-space: pre-wrap;
  word-break: break-word;
  -moz-tab-size: 2;
    -o-tab-size: 2;
       tab-size: 2;
}

.dash-raw:focus-visible {
  outline: 2px solid var(--d-accent);
  outline-offset: 2px;
}

.dash-panel-raw .dash-note {
  max-width: 90ch;
}

/* Clearing somebody else's markup is destructive and reads as it. */
.dash-btn-danger {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 9px 16px;
  border: 1px solid var(--d-danger);
  border-radius: var(--d-radius);
  background: transparent;
  color: var(--d-danger);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}

.dash-btn-danger:hover {
  background: var(--d-danger);
  color: #ffffff;
}

.dash-btn-danger:focus-visible {
  outline: 2px solid var(--d-danger);
  outline-offset: 2px;
}

/* ---------- a column explained under its own heading ----------
   Two switches whose names promised more than they did. The definition
   list is the shape that fits: the term, then what it does and — as
   importantly — what it does not. */
.dash-explain {
  margin: 10px 0 14px;
  padding: 0;
}

.dash-explain dt {
  margin: 12px 0 2px;
  font-weight: 700;
  font-size: 14px;
}

.dash-explain dt:first-child {
  margin-top: 0;
}

.dash-explain dd {
  margin: 0;
  max-width: 90ch;
  color: var(--d-muted);
  font-size: 14px;
  line-height: 1.55;
}

/* A panel's own heading row: the title and one action on the right. */
.dash-panel-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 4px;
}

.dash-panel-head h2 {
  margin: 0;
}

/* Printable QR cards (App\SellerShare). On screen a sheet of A6 cards; in
   print one card per A6 page, nothing else on it. */
.dash-qr-print {
  margin: 0;
  background: #e9e9e6;
}

.dash-qr-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 16px;
  font-size: 14px;
  background: #fff;
  border-bottom: 1px solid #d6d6d2;
}

.dash-qr-sheet {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  padding: 16px;
}

.dash-qr-card {
  box-sizing: border-box;
  width: 105mm;
  height: 148mm;
  max-width: 100%;
  padding: 10mm 8mm;
  background: #fff;
  border: 1px solid #d6d6d2;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  page-break-after: always;
  -moz-column-break-after: page;
       break-after: page;
}

.dash-qr-store {
  margin: 0 0 4mm;
  font-size: 12px;
  color: #555;
  min-height: 1.2em;
}

.dash-qr-name {
  margin: 0 0 6mm;
  font-size: 22px;
  line-height: 1.2;
  word-break: break-word;
}

.dash-qr-code svg {
  width: 60mm;
  height: 60mm;
  display: block;
}

.dash-qr-url {
  margin: 6mm 0 0;
  font-size: 11px;
  color: #333;
  word-break: break-all;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}

@media print {
  @page {
    size: A6;
    margin: 0;
  }
  .dash-qr-print {
    background: #fff;
  }
  .dash-qr-toolbar {
    display: none;
  }
  .dash-qr-sheet {
    display: block;
    padding: 0;
  }
  .dash-qr-card {
    border: 0;
    width: 105mm;
    height: 148mm;
    margin: 0;
  }
  .dash-qr-card:last-child {
    page-break-after: auto;
    -moz-column-break-after: auto;
         break-after: auto;
  }
}
@media (max-width: 640px) {
  .dash-qr-card {
    height: auto;
    padding: 8mm 6mm;
  }
}
