/* ═══ Theme studio enhancement layer (2026-08-06) ═══════════════════════
   Styles for the custom colour picker, the live receipt and the checkout
   sheet. Everything is expressed in the platform's own theme tokens so the
   studio itself repaints correctly under all 43 themes.               */

/* ── The swatch button that stands in for input[type=color] ──────────── */
/* The native input stays in the DOM as the model (profile.v1.js reads and
   writes it); it is only hidden from sight so the OS colour panel — which
   no CSS can reach — can never open. */
.dlb-row input[type="color"].ts-native {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
  border: 0;
  padding: 0;
  margin: -1px;
  clip-path: inset(50%);
}

.ts-swatch {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 4px 10px 4px 4px;
  border: 1px solid var(--border);
  border-radius: 9px;
  background: transparent;
  color: var(--text);
  font-family: inherit;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  line-height: 1;
  transition: border-color 0.15s;
}
.ts-swatch:hover,
.ts-swatch[aria-expanded="true"] { border-color: var(--accent); }
.ts-swatch:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.ts-swatch-chip {
  width: 30px;
  height: 24px;
  border-radius: 6px;
  /* A ring rather than a border, so a colour that matches the card edge is
     still visible as a distinct chip. */
  box-shadow: inset 0 0 0 1px rgba(128, 128, 128, 0.45);
  flex-shrink: 0;
}
.ts-swatch-hex {
  font-family: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
  letter-spacing: 0.02em;
  color: var(--dim);
  text-transform: uppercase;
}

/* ── The picker popover ───────────────────────────────────────────────── */
.ts-pop {
  position: fixed;
  z-index: 9000;
  width: 268px;
  padding: 14px;
  border: 1px solid var(--border);
  border-radius: 14px;
  background: var(--card);
  box-shadow: 0 18px 48px rgba(0, 0, 0, 0.34);
}
.ts-pop[hidden] { display: none; }
.ts-pop-title {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 10px;
}

/* Saturation / brightness field. The base hue is set from JS; the two
   gradients paint white→transparent across and transparent→black down. */
.ts-sv {
  position: relative;
  height: 132px;
  border-radius: 10px;
  cursor: crosshair;
  touch-action: none;
  background-image:
    linear-gradient(to top, #000, transparent),
    linear-gradient(to right, #fff, transparent);
  box-shadow: inset 0 0 0 1px rgba(128, 128, 128, 0.3);
}
.ts-sv:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.ts-thumb {
  position: absolute;
  width: 16px;
  height: 16px;
  margin: -8px 0 0 -8px;
  border-radius: 50%;
  border: 2px solid #fff;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.5), 0 1px 4px rgba(0, 0, 0, 0.4);
  pointer-events: none;
}

.ts-hue {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 14px;
  margin: 13px 0 0;
  border-radius: 999px;
  cursor: pointer;
  background: linear-gradient(to right, #f00 0%, #ff0 17%, #0f0 33%,
    #0ff 50%, #00f 67%, #f0f 83%, #f00 100%);
}
.ts-hue:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.ts-hue::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: #fff;
  border: 2px solid #fff;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.55);
  cursor: pointer;
}
.ts-hue::-moz-range-thumb {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: #fff;
  border: 2px solid #fff;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.55);
  cursor: pointer;
}

.ts-hexrow { display: flex; gap: 7px; margin-top: 12px; }
.ts-hexin {
  flex: 1;
  min-width: 0;
  font-family: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 13px;
  text-transform: uppercase;
  padding: 8px 10px;
  border-radius: 8px;
  border: 1px solid var(--border);
  background: var(--bg);
  color: var(--bright);
}
.ts-hexin:focus { outline: none; border-color: var(--accent); }
.ts-hexin.ts-bad { border-color: #d2544a; }
.ts-eyedrop {
  flex: 0 0 auto;
  width: 36px;
  border-radius: 8px;
  border: 1px solid var(--border);
  background: transparent;
  color: var(--text);
  cursor: pointer;
  font-size: 15px;
  line-height: 1;
}
.ts-eyedrop:hover { border-color: var(--accent); }

.ts-recent { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 12px; }
.ts-recent button {
  width: 22px;
  height: 22px;
  border-radius: 6px;
  border: 0;
  padding: 0;
  cursor: pointer;
  box-shadow: inset 0 0 0 1px rgba(128, 128, 128, 0.45);
}
.ts-recent button:hover { transform: scale(1.12); }
.ts-recent button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.ts-pop-note { margin-top: 11px; font-size: 11px; color: var(--dim); line-height: 1.45; }

/* On a phone the popover becomes a bottom sheet — a 268px floater anchored to
   a control near the bottom of the screen is unusable one-handed. */
@media (max-width: 560px) {
  .ts-pop {
    left: 0 !important;
    right: 0;
    top: auto !important;
    bottom: 0;
    width: auto;
    border-radius: 18px 18px 0 0;
    padding: 16px 16px calc(16px + env(safe-area-inset-bottom, 0px));
  }
  .ts-sv { height: 168px; }
}

/* ── Row hints: what each control actually changes ────────────────────── */
.dlb-row.ts-row { align-items: center; flex-wrap: wrap; }
.ts-label { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }
.ts-hint { font-size: 12px; color: var(--dim); line-height: 1.35; }

/* ── Live receipt ─────────────────────────────────────────────────────── */
.ts-receipt {
  margin-top: 12px;
  border: 1px solid var(--border-soft);
  border-radius: 12px;
  padding: 13px 14px;
  background: var(--card);
}
/* Deliberately --dim, not --accent. Brand gold (#b8911e) on a card measures
   2.95:1 in the light theme — the same failure already open against
   /files/encrypt and the root landing page. Whether gold gets a darker
   light-theme variant is a brand decision, so this avoids adding another
   instance of it rather than pre-empting that call. --dim was lifted to
   >=4.5:1 across all 43 themes on 2026-08-06. */
.ts-receipt-h {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--dim);
}
.ts-lines { margin: 9px 0 0; padding: 0; list-style: none; }
.ts-line {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  font-size: 13px;
  padding: 3px 0;
  color: var(--text);
}
.ts-line-cost {
  font-variant-numeric: tabular-nums;
  color: var(--dim);
  flex-shrink: 0;
}
.ts-total {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid var(--border-soft);
  font-weight: 700;
  color: var(--bright);
}
.ts-total-num { font-size: 20px; font-variant-numeric: tabular-nums; }
.ts-empty { font-size: 13px; color: var(--dim); margin-top: 8px; line-height: 1.5; }
/* --bright rather than --accent: this line carries real information ("included
   with your Gold plan"), so it has to clear AA. See the note on .ts-receipt-h. */
.ts-covered {
  margin-top: 9px;
  font-size: 12px;
  font-weight: 600;
  color: var(--bright);
  line-height: 1.45;
}
.ts-strike { text-decoration: line-through; opacity: 0.55; font-weight: 600; }

/* ── Readability warnings ─────────────────────────────────────────────── */
.ts-warn {
  margin-top: 12px;
  border: 1px solid var(--border-soft);
  border-left: 3px solid #d08b2c;
  border-radius: 9px;
  padding: 10px 12px;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--text);
}
.ts-warn b { color: var(--bright); }
.ts-warn ul { margin: 6px 0 0; padding-left: 17px; }
.ts-warn li { margin: 2px 0; color: var(--dim); }
.ts-warn-fix {
  margin-top: 9px;
  font-family: inherit;
  font-size: 12px;
  font-weight: 600;
  padding: 6px 11px;
  border-radius: 7px;
  border: 1px solid var(--border);
  background: transparent;
  color: var(--text);
  cursor: pointer;
}
.ts-warn-fix:hover { border-color: var(--accent); color: var(--bright); }

/* ── Checkout sheet ───────────────────────────────────────────────────── */
.ts-modal {
  position: fixed;
  inset: 0;
  z-index: 9500;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  background: rgba(0, 0, 0, 0.55);
}
.ts-modal[hidden] { display: none; }
.ts-sheet {
  width: 100%;
  max-width: 400px;
  max-height: 88vh;
  overflow-y: auto;
  border: 1px solid var(--border);
  border-radius: 16px;
  background: var(--card);
  padding: 22px;
  box-shadow: 0 24px 64px rgba(0, 0, 0, 0.4);
}
.ts-sheet h2 {
  font-size: 19px;
  font-weight: 700;
  color: var(--bright);
  letter-spacing: -0.01em;
}
.ts-sheet-sub { font-size: 13px; color: var(--dim); margin-top: 5px; line-height: 1.5; }
.ts-pay {
  display: block;
  width: 100%;
  text-align: left;
  margin-top: 11px;
  padding: 14px 15px;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: transparent;
  color: var(--text);
  font-family: inherit;
  cursor: pointer;
}
/* Two of these are <a>, and base.v1.css underlines any anchor it can reach,
   so without this the checkout options rendered as underlined link text
   instead of the buttons beside them. */
.ts-pay { text-decoration: none; }
.ts-pay:hover:not(:disabled) { border-color: var(--accent); }
.ts-pay:disabled { opacity: 0.55; cursor: not-allowed; }
.ts-pay-t { display: block; font-size: 15px; font-weight: 700; color: var(--bright); }
.ts-pay-s { display: block; font-size: 12.5px; color: var(--dim); margin-top: 3px; line-height: 1.4; }
.ts-pay-primary { border-color: var(--accent); }
.ts-sheet-x {
  margin-top: 14px;
  width: 100%;
  padding: 10px;
  border: 0;
  border-radius: 9px;
  background: transparent;
  color: var(--dim);
  font-family: inherit;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
}
.ts-sheet-x:hover { color: var(--bright); }

/* ── Mobile: keep the preview on screen while editing ─────────────────── */
/* On a phone the two-column grid stacks, which parks the live preview ~1500px
   below the controls — you change a colour and cannot see what happened. This
   pins a compact version to the bottom of the viewport instead. */
.ts-minipv {
  position: fixed;
  left: 10px;
  right: 10px;
  bottom: calc(var(--dlc-bn-h, 40px) + 10px + env(safe-area-inset-bottom, 0px));
  z-index: 700;
  display: none;
  align-items: center;
  gap: 12px;
  padding: 10px 13px;
  border-radius: 13px;
  border: 1px solid var(--pborder, var(--border));
  background: var(--pbg, var(--card));
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
}
.ts-minipv.on { display: flex; }
.ts-minipv-card {
  flex: 1;
  min-width: 0;
  border-radius: 9px;
  padding: 9px 11px;
  background: var(--pcard, var(--card));
  border: 1px solid var(--paccent, var(--accent));
}
.ts-minipv-h {
  font-size: 13px;
  font-weight: 800;
  color: var(--pbright, var(--bright));
  font-family: var(--pfonthead, inherit);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.ts-minipv-s {
  font-size: 11px;
  color: var(--pdim, var(--dim));
  font-family: var(--pfont, inherit);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.ts-minipv-btn {
  flex-shrink: 0;
  font-size: 11px;
  font-weight: 800;
  padding: 7px 11px;
  border-radius: 7px;
  color: #0a0a0f;
  background: var(--paccent, var(--accent));
}
.ts-minipv-price {
  flex-shrink: 0;
  font-size: 13px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--pbright, var(--bright));
}
@media (min-width: 721px) { .ts-minipv { display: none !important; } }

/* ── Undo ─────────────────────────────────────────────────────────────── */
.dlb-actions .ts-undo:disabled { opacity: 0.45; cursor: not-allowed; }

@media (prefers-reduced-motion: reduce) {
  .ts-recent button:hover { transform: none; }
}

/* ── Rate card + per-control price tags (2026-08-07) ──────────────────────
   The studio published a ceiling ("up to $32.86") and no rate anywhere else on
   the page, so the number read as an assertion rather than as the sum it is.
   Two surfaces show the terms: a rate card naming every billable detail, and a
   price on each control that lights up while that detail is being charged.

   Colour follows the note on .ts-receipt-h — --dim and --bright, never brand
   gold on a card (2.95:1 in the light theme). "This row is being charged" is
   carried by a dot AND a colour change, so it never rests on colour alone. */
.ts-rate {
  margin: 0 0 16px;
  border: 1px solid var(--border-soft);
  border-radius: 12px;
  padding: 14px 15px;
  background: var(--card);
}
.ts-rate-h {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--dim);
}
.ts-rate-note {
  margin: 8px 0 0;
  font-size: 12.5px;
  line-height: 1.55;
  color: var(--dim);
}
.ts-rate-t {
  width: 100%;
  margin-top: 12px;
  border-collapse: collapse;
  font-size: 13px;
}
.ts-rate-t th {
  padding: 0 0 6px;
  text-align: left;
  /* 11px, not 10.5: the smallest text already on this page is the 11px
     .ts-receipt-h label. --dim runs below AA on --card for 35 of the 43 themes
     (a platform-wide de-emphasis, not introduced here — measured against the
     pre-existing elements), so new text should not also be the smallest. */
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--dim);
  border-bottom: 1px solid var(--border-soft);
}
.ts-rate-t td {
  padding: 8px 0;
  vertical-align: top;
  color: var(--text);
  border-top: 1px solid var(--border-soft);
}
.ts-rate-t tbody tr:first-child td { border-top: 0; }
/* Tabular figures so the money columns read as a column of digits rather than
   a ragged edge — the difference between a table and a receipt. */
.ts-rate-t .ts-num {
  padding-left: 10px;
  text-align: right;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.ts-rate-cat { display: block; font-weight: 600; color: var(--bright); }
.ts-rate-sub {
  display: block;
  margin-top: 3px;
  /* Matches .ts-hint (12px), the page's floor for secondary body text. These
     are the billable detail names — the terms of the sum — so they are the
     last thing that should be set smaller than their neighbours. */
  font-size: 12px;
  line-height: 1.45;
  color: var(--dim);
}
.ts-rate-tot td {
  padding-top: 10px;
  border-top: 1px solid var(--border);
  font-weight: 700;
  color: var(--bright);
}
.ts-rate-tot .ts-num { font-size: 16px; }

.ts-price {
  flex-shrink: 0;
  min-width: 56px;
  text-align: right;
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
  color: var(--dim);
}
.ts-price.is-charged { color: var(--bright); }
.ts-price.is-charged::before {
  content: "";
  display: inline-block;
  width: 6px;
  height: 6px;
  margin-right: 6px;
  border-radius: 50%;
  background: var(--accent);
  vertical-align: middle;
}

/* Names the denominator ("3 of 14"), which is what gives the ceiling a shape. */
.ts-count {
  margin-top: 8px;
  font-size: 12px;
  line-height: 1.45;
  color: var(--dim);
}

@media (max-width: 560px) {
  /* Four columns of prose and figures do not fit a phone. "How many" is the
     one column the reader can recount from the list beside it, so it is the
     one to drop — the total row is excluded, or its own figure would vanish
     with the column it happens to sit in. */
  .ts-rate-t thead th:nth-child(3),
  .ts-rate-t tbody tr:not(.ts-rate-tot) td:nth-child(3) { display: none; }
  .ts-rate-t { font-size: 12.5px; }
  .ts-rate-sub { font-size: 11px; }

  /* Type and finish rows hold a three-button segmented control. With a price
     column beside it the label is left ~90px and wraps to one word per line.
     The price is the piece that can move without losing its meaning, so it
     drops to its own right-aligned line and the label gets the width back.
     Colour rows are left alone — a swatch is narrow and they read fine. */
  .ts-priced-type,
  .ts-priced-finish { flex-wrap: wrap; }
  .ts-priced-type .ts-price,
  .ts-priced-finish .ts-price {
    flex-basis: 100%;
    min-width: 0;
    margin-top: 2px;
  }
}


/* ── Premium presets + the full set ───────────────────────────────────────
   35 of the 43 preset chips are paid themes, and starting from one you do not
   own is priced as a brand-new design ($23.92, measured). The chip has to say
   so before the click, and all 43 have to be reachable — only 3–6 were. */
.dlb-preset {
  position: relative;
}
.ts-chip-tag {
  position: absolute;
  top: 3px;
  right: 3px;
  padding: 1px 5px;
  border-radius: 999px;
  /* 11px is the page's small-text floor — an earlier pass shipped 10.5px here
     and had to raise it. Do not go below. */
  font-size: 11px;
  font-weight: 700;
  line-height: 1.45;
  background: var(--card, #16161f);
  color: var(--accent-text, var(--accent, #b8911e));
  border: 1px solid var(--border, #2a2a38);
  pointer-events: none;
}
.ts-preset-all {
  margin-top: 9px;
  padding: 6px 12px;
  border-radius: 8px;
  border: 1px solid var(--border, #2a2a38);
  background: transparent;
  color: var(--accent-text, var(--accent, #b8911e));
  font: inherit;
  font-size: 12.5px;
  font-weight: 700;
  cursor: pointer;
}
.ts-preset-all:hover,
.ts-preset-all:focus-visible {
  background: var(--card-hi, var(--card, #16161f));
}
.dlb-presets.ts-presets-all {
  flex-wrap: wrap;
  /* No max-height and no inner scroll on purpose: capping this at 46vh meant
     "show all 43" still hid most of them behind a second, nested scrollbar,
     which on a touch device competes with the page scroll. Let it grow. */
  overflow-x: visible;
  overflow-y: visible;
  row-gap: 10px;
}

/* Why a design jumped to full price when the visitor changed nothing. */
.ts-basewarn {
  margin-top: 8px;
  padding: 9px 11px;
  border-radius: 9px;
  border: 1px solid var(--border, #2a2a38);
  background: var(--card-hi, var(--card, #16161f));
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--dim, #8a8a9e);
}
.ts-basewarn b {
  color: var(--text, #d0d0d8);
}
