/**
 * Application surface: login, dashboard, editor and print ordering.
 *
 * This is the logged-in product, so the file is built around three ideas:
 * every screen is a `.view` inside one shell, every grouping is a `.panel`,
 * and the two working screens (editor, print) share the same form-left /
 * sticky-preview-right layout so switching between them costs no re-learning.
 *
 * Mobile first throughout: single column until the viewport can honestly hold
 * two, and every grid uses minmax(0, …) so long URLs and aliases cannot push
 * the page into horizontal scroll at 360px.
 *
 * Everything else comes from base.css — .button, .field*, .status, .loading,
 * .brand, .logo and .icon are already styled there and are never restyled here.
 */

/* ------------------------------------------------------------------ */
/* Shell                                                               */
/* ------------------------------------------------------------------ */

.app {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  min-height: 100dvh;
}

/* Same treatment as the landing header: translucent bar, hairline only once
   content scrolls under it, opaque fallback where backdrop-filter is missing. */
.app-header {
  position: sticky;
  top: 0;
  z-index: 20;
  background: color-mix(in srgb, var(--bg) 82%, transparent);
  border-bottom: 1px solid transparent;
}

@supports (backdrop-filter: blur(12px)) or (-webkit-backdrop-filter: blur(12px)) {
  .app-header {
    -webkit-backdrop-filter: saturate(180%) blur(14px);
    backdrop-filter: saturate(180%) blur(14px);
  }
}

@supports not ((backdrop-filter: blur(12px)) or (-webkit-backdrop-filter: blur(12px))) {
  .app-header {
    background: var(--bg);
  }
}

@supports (animation-timeline: scroll()) {
  .app-header {
    animation: app-header-hairline linear both;
    animation-timeline: scroll();
    animation-range: 0 80px;
  }
}

@keyframes app-header-hairline {
  to {
    border-bottom-color: var(--border);
  }
}

.app-header__inner {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  width: 100%;
  max-width: var(--shell-width);
  margin-inline: auto;
  min-height: 64px;
  padding: var(--space-3) var(--space-4);
}

.app-header__inner .brand {
  margin-right: auto;
  min-width: 0;
}

/* The product name is the first thing to drop at 360px; the mark still
   identifies the app and the logout button is what the user actually needs. */
.brand__name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.app-header__actions {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-width: 0;
}

/* The address is context, not a control: it only earns space once there is
   room for it beside the logout button. */
.app-header__email {
  display: none;
  font-size: 14px;
  color: var(--text-muted);
  max-width: 24ch;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.app-main {
  flex: 1;
  width: 100%;
  max-width: var(--shell-width);
  margin-inline: auto;
  padding: var(--space-5) var(--space-4) var(--space-8);
}

@media (min-width: 640px) {
  .app-header__inner {
    padding-inline: var(--space-6);
  }

  .app-header__email {
    display: block;
  }

  .app-main {
    padding: var(--space-6) var(--space-6) var(--space-9);
  }
}

/* ------------------------------------------------------------------ */
/* Views                                                               */
/* ------------------------------------------------------------------ */

.view {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
}

/* Title and primary action sit on one line as soon as both fit; below that the
   action wraps under the title rather than squeezing it. */
.view__header {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
}

.view__title {
  font-size: clamp(26px, 6vw, 34px);
  letter-spacing: -0.03em;
  min-width: 0;
}

/* The heading takes focus on route change (see app.js); the default focus ring
   would box the whole line, so mark it with the accent bar instead. */
.view__title:focus-visible {
  outline: none;
  text-decoration: underline;
  text-decoration-color: var(--accent);
  text-underline-offset: 6px;
  text-decoration-thickness: 2px;
}

.view__subtitle {
  color: var(--text-muted);
  font-size: 16.5px;
  max-width: 60ch;
  flex-basis: 100%;
  margin-top: calc(var(--space-3) * -1);
}

/* ------------------------------------------------------------------ */
/* Panels — the one grouping primitive used by editor and print        */
/* ------------------------------------------------------------------ */

.panel {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  padding: var(--space-4);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
  box-shadow: var(--shadow-sm);
}

.panel__title {
  font-size: 13px;
  font-weight: 620;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--text-subtle);
}

@media (min-width: 640px) {
  .panel {
    padding: var(--space-5);
  }
}

/* ------------------------------------------------------------------ */
/* Dashboard                                                           */
/* ------------------------------------------------------------------ */

.code-grid {
  display: grid;
  gap: var(--space-3);
}

.code-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-4);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
  box-shadow: var(--shadow-sm);
  transition: border-color var(--transition), box-shadow var(--transition),
    transform var(--transition);
}

.code-card:hover {
  border-color: var(--border-strong);
  box-shadow: var(--shadow);
  transform: translateY(-1px);
}

/* The whole left side is the link to the editor, so it stays a single target. */
.code-card__main {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  min-width: 0;
  flex: 1;
}

/* A light plate keeps the thumbnail readable in dark mode: the QR is rendered
   with the user's own colours and would otherwise sit on a near-black card. */
.code-card__qr {
  width: 60px;
  height: 60px;
  flex-shrink: 0;
  padding: 4px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: #ffffff; /* Deliberately theme-independent: see note above. */
}

.code-card__text {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  min-width: 0;
}

.code-card__title {
  font-size: 17px;
  font-weight: 620;
  letter-spacing: -0.015em;
  overflow-wrap: anywhere;
}

.code-card__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  font-size: 14px;
  color: var(--text-muted);
}

/* Monospace and truncation: the slug is scannable at a glance and a long
   custom domain must never widen the card. */
.code-card__url {
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--text-subtle);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.code-card__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  padding-top: var(--space-3);
  border-top: 1px solid var(--border);
}

/* Push the buttons right once the paused chip shares the row. */
.code-card__actions .chip {
  margin-right: auto;
}

@media (min-width: 720px) {
  .code-card {
    flex-direction: row;
    align-items: center;
    gap: var(--space-4);
  }

  .code-card__actions {
    padding-top: 0;
    border-top: none;
    flex-shrink: 0;
    flex-wrap: nowrap;
  }

  .code-card__actions .chip {
    margin-right: 0;
  }
}

.chip {
  display: inline-flex;
  align-items: center;
  padding: 2px 10px;
  border-radius: var(--radius-full);
  background: var(--accent-soft);
  color: var(--accent);
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: 0.01em;
  white-space: nowrap;
}

.chip--paused {
  background: var(--danger-soft);
  color: var(--danger);
}

/* ------------------------------------------------------------------ */
/* Empty state                                                         */
/* ------------------------------------------------------------------ */

.empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--space-4);
  padding: var(--space-8) var(--space-4);
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius-lg);
  background: color-mix(in srgb, var(--surface) 60%, transparent);
}

.empty__art {
  font-size: 56px;
  line-height: 1;
  color: color-mix(in srgb, var(--accent) 45%, var(--text-subtle));
}

.empty__text {
  color: var(--text-muted);
  font-size: 16.5px;
  max-width: 40ch;
}

/* ------------------------------------------------------------------ */
/* Editor and print: shared form / sticky-preview layout               */
/* ------------------------------------------------------------------ */

.editor__layout,
.print-layout {
  display: grid;
  gap: var(--space-4);
  align-items: start;
}

.editor__form,
.print-form {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  min-width: 0;
}

.editor__actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: var(--space-3);
}

/* Save is the primary action; on a phone both buttons go full width so neither
   becomes a small target at the bottom of a long form. */
.editor__actions .button {
  flex: 1 1 auto;
}

@media (min-width: 560px) {
  .editor__actions .button {
    flex: 0 0 auto;
  }
}

/* 1000px is where a ~420px preview column stops stealing width the form needs
   for its side-by-side field rows. */
@media (min-width: 1000px) {
  .editor__layout,
  .print-layout {
    grid-template-columns: minmax(0, 1fr) minmax(0, 380px);
    gap: var(--space-5);
  }

  .preview,
  .print-preview {
    position: sticky;
    top: calc(64px + var(--space-5)); /* Clears the sticky header. */
  }
}

/* ------------------------------------------------------------------ */
/* Kind picker                                                         */
/* ------------------------------------------------------------------ */

.kind-grid {
  display: grid;
  gap: var(--space-3);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr));
}

.kind-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  align-items: flex-start;
  text-align: left;
  padding: var(--space-5) var(--space-4);
  min-height: 116px;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
  box-shadow: var(--shadow-sm);
  cursor: pointer;
  transition: border-color var(--transition), box-shadow var(--transition),
    transform var(--transition), background var(--transition);
}

/* The accent wash on hover promises the choice is live, which a border change
   alone does not convey on a large card. */
.kind-card:hover {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent-soft) 55%, var(--surface));
  box-shadow: var(--shadow);
  transform: translateY(-2px);
}

.kind-card:active {
  transform: translateY(0);
}

.kind-card__name {
  font-size: 17px;
  font-weight: 620;
  letter-spacing: -0.015em;
  color: var(--text);
}

.kind-card__description {
  font-size: 14.5px;
  color: var(--text-muted);
  line-height: 1.45;
}

@media (min-width: 720px) {
  .kind-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--space-4);
  }
}

/* ------------------------------------------------------------------ */
/* Style controls                                                      */
/* ------------------------------------------------------------------ */

.style-grid {
  display: grid;
  gap: var(--space-4);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 160px), 1fr));
}

/* Colour fields put the swatch beside the label rather than under it: the
   control is small and a full-width row would read as a missing input. */
.field--color {
  flex-direction: row;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  background: var(--surface);
  min-height: 52px;
}

/* Native colour inputs ship with a thick chrome border; strip it and rebuild
   the swatch so it matches the field language. */
.field__color {
  width: 44px;
  height: 32px;
  flex-shrink: 0;
  padding: 0;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: none;
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
}

.field__color::-webkit-color-swatch-wrapper {
  padding: 2px;
}

.field__color::-webkit-color-swatch {
  border: none;
  border-radius: 5px;
}

.field__color::-moz-color-swatch {
  border: none;
  border-radius: 5px;
}

/* ------------------------------------------------------------------ */
/* Preview                                                             */
/* ------------------------------------------------------------------ */

.preview {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  padding: var(--space-4);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
  box-shadow: var(--shadow-sm);
  min-width: 0;
}

/**
 * The plate is intentionally a fixed light value rather than a token.
 *
 * The QR is rendered in the user's chosen colours, usually dark on white. On a
 * dark surface the quiet zone would vanish and the code would stop scanning, so
 * the plate must stay light in every theme. This is the only such exception in
 * the file besides the dashboard thumbnail, which has the same problem.
 */
.preview__qr {
  display: grid;
  place-items: center;
  padding: var(--space-4);
  border-radius: var(--radius);
  border: 1px solid var(--border);
  background: #ffffff; /* Theme-independent by design: see comment above. */
  min-height: 200px;
}

/* The QR arrives as an inline <svg> with no intrinsic size, so it is capped
   here. SVG is vector — image-rendering would do nothing but cost clarity. */
.preview__qr svg {
  width: 100%;
  max-width: 260px;
  height: auto;
}

.preview__note {
  font-size: 14px;
  color: var(--danger);
  text-align: center;
  min-height: 1.4em; /* Reserve the line so the panel does not jump on error. */
}

.preview__note:empty {
  min-height: 0;
}

.preview__url {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  padding: var(--space-3);
  border-radius: var(--radius);
  background: var(--bg);
  border: 1px solid var(--border);
  min-width: 0;
}

.preview__url-label {
  font-size: 12px;
  font-weight: 560;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-subtle);
}

.preview__url a {
  font-family: var(--font-mono);
  font-size: 14px;
  color: var(--accent);
  overflow-wrap: anywhere;
  transition: color var(--transition);
}

.preview__url a:hover {
  color: var(--accent-hover);
}

.preview__downloads {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.preview__downloads .button {
  flex: 1 1 auto;
}

/* ------------------------------------------------------------------ */
/* Repeaters                                                           */
/* ------------------------------------------------------------------ */

.repeater {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

/* Inset rather than raised: a repeated group belongs to the panel around it and
   should not compete with it for depth. */
.repeater__item {
  position: relative;
  padding: var(--space-4);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: color-mix(in srgb, var(--text) 3%, var(--surface));
}

.repeater__fields {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  min-width: 0;
}

/* Nested repeaters (menu sections holding products) need a visible step in, or
   the two levels read as one flat list. */
.repeater__item .repeater__item {
  background: var(--surface);
}

/* Absolute rather than a flex row: the controls are secondary, and keeping them
   out of flow means the inputs stay full width down to 360px. The padding
   reserved above the fields is what stops them overlapping the first label. */
.repeater__controls {
  position: absolute;
  top: var(--space-2);
  right: var(--space-2);
  display: flex;
  gap: var(--space-1);
}

.repeater__item {
  padding-top: var(--space-6);
}

/* An item with no controls (a single, non-removable entry) gets its space back. */
.repeater__item:has(.repeater__controls:empty) {
  padding-top: var(--space-4);
}

.icon-button {
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text-muted);
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
  transition: background var(--transition), color var(--transition),
    border-color var(--transition);
}

.icon-button:hover {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent);
}

.icon-button[disabled] {
  opacity: 0.35;
  pointer-events: none;
}

.icon-button--danger:hover {
  background: var(--danger-soft);
  border-color: var(--danger);
  color: var(--danger);
}

/* The add button is an action on the list, so it is aligned to the start rather
   than stretched like a form submit. */
.repeater__add {
  align-self: flex-start;
}

/* ------------------------------------------------------------------ */
/* Print ordering                                                      */
/* ------------------------------------------------------------------ */

.print-preview {
  display: grid;
  place-items: center;
  padding: var(--space-5);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
  box-shadow: var(--shadow-sm);
}

/* Same light-plate reasoning as .preview__qr — a printed code is worthless if
   the on-screen proof cannot be scanned. */
.print-preview__qr {
  width: 100%;
  max-width: 220px;
  height: auto;
  padding: var(--space-3);
  border-radius: var(--radius);
  background: #ffffff; /* Theme-independent by design: see .preview__qr. */
}

/* Wrapping cards rather than a grid: the labels vary in length (formats are
   long, quantities are two characters) and a fixed track would strand space. */
.option-group {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.option-card {
  flex: 1 1 140px;
  padding: var(--space-3) var(--space-4);
  min-height: 48px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--text-muted);
  font-size: 15px;
  font-weight: 560;
  text-align: center;
  cursor: pointer;
  transition: background var(--transition), border-color var(--transition),
    color var(--transition), box-shadow var(--transition);
}

.option-card:hover {
  border-color: var(--accent);
  color: var(--text);
}

/* Selection is carried by border, fill and weight together, so it survives
   greyscale printing and colour-vision differences. */
.option-card[data-selected='true'] {
  border-color: var(--accent);
  background: var(--accent-soft);
  color: var(--accent);
  font-weight: 620;
  box-shadow: 0 0 0 1px var(--accent) inset;
}

.option-card--compact {
  flex: 0 1 auto;
  min-width: 64px;
  padding-inline: var(--space-4);
  font-family: var(--font-mono);
}

.field-row {
  display: grid;
  gap: var(--space-4);
}

@media (min-width: 560px) {
  .field-row {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

.order-number {
  font-family: var(--font-mono);
  font-size: 17px;
  font-weight: 560;
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-full);
  background: var(--accent-soft);
  color: var(--accent);
}

/* ------------------------------------------------------------------ */
/* Login                                                               */
/* ------------------------------------------------------------------ */

.auth-page {
  display: grid;
  place-items: center;
  min-height: 100vh;
  min-height: 100dvh;
  padding: var(--space-5) var(--space-4);
}

.auth-card {
  width: 100%;
  max-width: 400px;
  padding: var(--space-6) var(--space-5);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
  box-shadow: var(--shadow);
  text-align: center;
}

.auth-card__title {
  font-size: clamp(22px, 5.5vw, 26px);
}

.auth-card__subtitle {
  color: var(--text-muted);
  font-size: 15.5px;
  margin-top: var(--space-2);
}

.auth-form {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  margin-top: var(--space-5);
  text-align: left;
}

/* The confirmation replaces the form in place, so it repeats the card's centred
   rhythm instead of introducing a second layout. */
.auth-sent {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin-top: var(--space-5);
  padding: var(--space-4);
  border-radius: var(--radius);
  background: var(--success-soft);
}

.auth-sent__title {
  font-size: 18px;
  color: var(--text);
}

.auth-sent__body {
  color: var(--text-muted);
  font-size: 15px;
  overflow-wrap: anywhere;
}

@media (min-width: 480px) {
  .auth-card {
    padding: var(--space-7) var(--space-6);
  }
}

/* ------------------------------------------------------------------ */
/* Toast                                                               */
/* ------------------------------------------------------------------ */

/* Mirrors public.css so the same feedback looks the same on both surfaces;
   app.js adds a variant that public.css never needs. */
.toast {
  position: fixed;
  left: 50%;
  bottom: calc(var(--space-5) + env(safe-area-inset-bottom, 0px));
  transform: translate(-50%, 16px);
  max-width: calc(100vw - var(--space-6));
  background: var(--text);
  color: var(--bg);
  padding: 10px 18px;
  border-radius: var(--radius-full);
  font-size: 14.5px;
  font-weight: 560;
  text-align: center;
  box-shadow: var(--shadow-lg);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--transition), transform var(--transition);
  z-index: 30;
}

.toast[data-visible='true'] {
  opacity: 1;
  transform: translate(-50%, 0);
}

/* Failures are announced in red rather than the neutral pill: a save that did
   not happen must not look like a save that did. */
.toast[data-variant='error'] {
  background: var(--danger);
  color: var(--accent-contrast);
}

/* ------------------------------------------------------------------ */
/* Motion                                                              */
/* ------------------------------------------------------------------ */

/* Views swap after an await, so a short fade hides the loading flash. */
@media (prefers-reduced-motion: no-preference) {
  .view {
    animation: view-enter 260ms cubic-bezier(0.22, 1, 0.36, 1) both;
  }
}

@keyframes view-enter {
  from {
    opacity: 0;
    transform: translateY(6px);
  }
}

@media (prefers-reduced-motion: reduce) {
  .view {
    animation: none;
  }

  .code-card:hover,
  .kind-card:hover {
    transform: none;
  }

  .toast {
    transform: translate(-50%, 0);
  }
}

/* ------------------------------------------------------------------ */
/* Development login link                                              */
/* ------------------------------------------------------------------ */

/*
 * Shown on the login page only when the server reports it has no mail
 * transport, so the magic link is reachable without opening the terminal.
 */
.dev-link {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: var(--space-3);
  margin-top: var(--space-4);
  padding: var(--space-4);
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius);
  background: color-mix(in srgb, var(--accent) 5%, var(--surface));
  text-align: left;
}

.dev-link__body {
  font-size: 14.5px;
  color: var(--text-muted);
}

.dev-link__url {
  font-family: var(--font-mono);
  font-size: 12.5px;
  color: var(--text-subtle);
  overflow-wrap: anywhere; /* The token is long and must not widen the card. */
  user-select: all;        /* One click selects the whole link to copy. */
}

/* ------------------------------------------------------------------ */
/* QR modal                                                            */
/* ------------------------------------------------------------------ */

.modal-overlay {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: grid;
  place-items: center;
  padding: var(--space-4);
  background: color-mix(in srgb, #000000 55%, transparent);
  overflow-y: auto;
}

.modal {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-3);
  width: min(100%, 420px);
  padding: var(--space-6) var(--space-5) var(--space-5);
  background: var(--surface);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  text-align: center;
}

.modal__title {
  font-size: 19px;
  overflow-wrap: anywhere;
}

/*
 * The plate stays light in both themes: a dark-mode backdrop behind a dark
 * code removes the quiet zone and stops it scanning off the screen.
 */
.modal__qr {
  width: min(300px, 70vw);
  height: auto;
  padding: var(--space-3);
  background: #ffffff;
  border-radius: var(--radius);
}

.modal__hint {
  font-size: 14px;
  color: var(--text-muted);
}

.modal__url {
  font-family: var(--font-mono);
  font-size: 12.5px;
  color: var(--text-subtle);
  overflow-wrap: anywhere;
}

.modal__actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-2);
  margin-top: var(--space-2);
}

.modal__close {
  position: absolute;
  top: var(--space-2);
  right: var(--space-2);
  width: 36px;
  height: 36px;
  display: grid;
  place-items: center;
  border: none;
  border-radius: var(--radius-full);
  background: transparent;
  color: var(--text-subtle);
  font-size: 24px;
  line-height: 1;
  cursor: pointer;
  transition: background var(--transition), color var(--transition);
}

.modal__close:hover {
  background: var(--border);
  color: var(--text);
}

/* ------------------------------------------------------------------ */
/* Collapsible design panel                                            */
/* ------------------------------------------------------------------ */

/*
 * Styling sits with the preview it affects, and starts closed: most codes ship
 * with the defaults, and the choice belongs next to the code, not in the
 * middle of entering content.
 */
.design-panel {
  margin-top: var(--space-4);
  border-top: 1px solid var(--border);
  padding-top: var(--space-3);
}

.design-panel__summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  padding: var(--space-2) 0;
  font-size: 13px;
  font-weight: 620;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-subtle);
  cursor: pointer;
  list-style: none;
  transition: color var(--transition);
}

.design-panel__summary:hover {
  color: var(--text);
}

/* Replace the default disclosure triangle with the chevron. */
.design-panel__summary::-webkit-details-marker {
  display: none;
}

.design-panel__chevron {
  font-size: 15px;
  line-height: 1;
  transition: transform var(--transition);
}

.design-panel[open] .design-panel__summary {
  color: var(--text);
}

.design-panel[open] .design-panel__chevron {
  transform: rotate(180deg);
}

.design-panel__body {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding-top: var(--space-3);
}

/* The panel is narrower here than it was in the form column. */
.design-panel .style-grid {
  grid-template-columns: 1fr 1fr;
}

@media (max-width: 420px) {
  .design-panel .style-grid {
    grid-template-columns: 1fr;
  }
}

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