    @font-face {
      font-family: "18jindaEclairBold";
      src: url("./assets/fonts/18jindaEclairBold.ttf") format("truetype");
      font-display: swap;
    }

    @font-face {
      font-family: "JindaBiscuitPieBold";
      src: url("./assets/fonts/JindaBiscuitPieBold.ttf") format("truetype");
      font-display: swap;
    }

    /* =========================================
       Font-select preview faces — reuse of the
       existing files in assets/fonts/ only, same
       paths as viewer.js's fontFiles map.
       ========================================= */

    @font-face {
      font-family: "18jindaEclair";
      src: url("./assets/fonts/18jindaEclair.ttf") format("truetype");
      font-display: swap;
    }

    @font-face {
      font-family: "18jindaEclairThin";
      src: url("./assets/fonts/18jindaEclairThin.ttf") format("truetype");
      font-display: swap;
    }

    @font-face {
      font-family: "33JindaKoko";
      src: url("./assets/fonts/33JindaKoko.ttf") format("truetype");
      font-display: swap;
    }

    @font-face {
      font-family: "33JindaKokoBold";
      src: url("./assets/fonts/33JindaKokoBold.ttf") format("truetype");
      font-display: swap;
    }

    @font-face {
      font-family: "33JindaKokoThin";
      src: url("./assets/fonts/33JindaKokoThin.ttf") format("truetype");
      font-display: swap;
    }

    @font-face {
      font-family: "HappyThursday";
      src: url("./assets/fonts/HappyThursday.ttf") format("truetype");
      font-display: swap;
    }

    @font-face {
      font-family: "HappyThursdayCute";
      src: url("./assets/fonts/HappyThursdayCute.ttf") format("truetype");
      font-display: swap;
    }

    @font-face {
      font-family: "HappyThursdayThin";
      src: url("./assets/fonts/HappyThursdayThin.ttf") format("truetype");
      font-display: swap;
    }

    @font-face {
      font-family: "JindaApollo";
      src: url("./assets/fonts/JindaApollo.ttf") format("truetype");
      font-display: swap;
    }

    @font-face {
      font-family: "JindaApolloBold";
      src: url("./assets/fonts/JindaApolloBold.ttf") format("truetype");
      font-display: swap;
    }

    @font-face {
      font-family: "JindaApolloSp";
      src: url("./assets/fonts/JindaApolloSp.ttf") format("truetype");
      font-display: swap;
    }

    @font-face {
      font-family: "JindaApolloThin";
      src: url("./assets/fonts/JindaApolloThin.ttf") format("truetype");
      font-display: swap;
    }

    @font-face {
      font-family: "JindaBiscuit";
      src: url("./assets/fonts/JindaBiscuit.ttf") format("truetype");
      font-display: swap;
    }

    @font-face {
      font-family: "JindaBiscuitBold";
      src: url("./assets/fonts/JindaBiscuitBold.ttf") format("truetype");
      font-display: swap;
    }

    @font-face {
      font-family: "JindaBiscuitPie";
      src: url("./assets/fonts/JindaBiscuitPie.ttf") format("truetype");
      font-display: swap;
    }

    @font-face {
      font-family: "JindaBiscuitPieThin";
      src: url("./assets/fonts/JindaBiscuitPieThin.ttf") format("truetype");
      font-display: swap;
    }

    @font-face {
      font-family: "JindaBiscuitThin";
      src: url("./assets/fonts/JindaBiscuitThin.ttf") format("truetype");
      font-display: swap;
    }

    @font-face {
      font-family: "JindaWhisky";
      src: url("./assets/fonts/JindaWhisky.ttf") format("truetype");
      font-display: swap;
    }

    @font-face {
      font-family: "JindaWhiskyBold";
      src: url("./assets/fonts/JindaWhiskyBold.ttf") format("truetype");
      font-display: swap;
    }

    @font-face {
      font-family: "JindaWhiskyPremium";
      src: url("./assets/fonts/JindaWhiskyPremium.ttf") format("truetype");
      font-display: swap;
    }

    @font-face {
      font-family: "JindaWhiskyThin";
      src: url("./assets/fonts/JindaWhiskyThin.ttf") format("truetype");
      font-display: swap;
    }

    @font-face {
      font-family: "JindGoody";
      src: url("./assets/fonts/JindGoody.ttf") format("truetype");
      font-display: swap;
    }

    @font-face {
      font-family: "JindGoodyBold";
      src: url("./assets/fonts/JindGoodyBold.ttf") format("truetype");
      font-display: swap;
    }

    @font-face {
      font-family: "JindGoodyThin";
      src: url("./assets/fonts/JindGoodyThin.ttf") format("truetype");
      font-display: swap;
    }

    @font-face {
      font-family: "Lovebird";
      src: url("./assets/fonts/Lovebird.ttf") format("truetype");
      font-display: swap;
    }

    @font-face {
      font-family: "magic love";
      src: url("./assets/fonts/magic love.ttf") format("truetype");
      font-display: swap;
    }

    @font-face {
      font-family: "MiMarshmallow";
      src: url("./assets/fonts/MiMarshmallow.ttf") format("truetype");
      font-display: swap;
    }

    @font-face {
      font-family: "MiMarshmallowBold";
      src: url("./assets/fonts/MiMarshmallowBold.ttf") format("truetype");
      font-display: swap;
    }

    @font-face {
      font-family: "MiMarshmallowThin";
      src: url("./assets/fonts/MiMarshmallowThin.ttf") format("truetype");
      font-display: swap;
    }

    @font-face {
      font-family: "MiPie";
      src: url("./assets/fonts/MiPie.ttf") format("truetype");
      font-display: swap;
    }

    @font-face {
      font-family: "MiPieBold";
      src: url("./assets/fonts/MiPieBold.ttf") format("truetype");
      font-display: swap;
    }

    @font-face {
      font-family: "MiPieThin";
      src: url("./assets/fonts/MiPieThin.ttf") format("truetype");
      font-display: swap;
    }

    @font-face {
      font-family: "MN KAOPAT Italic";
      src: url("./assets/fonts/MN KAOPAT Italic.ttf") format("truetype");
      font-display: swap;
    }

    @font-face {
      font-family: "MN KAOPAT";
      src: url("./assets/fonts/MN KAOPAT.ttf") format("truetype");
      font-display: swap;
    }

    @font-face {
      font-family: "MN MOCHI Italic";
      src: url("./assets/fonts/MN MOCHI Italic.ttf") format("truetype");
      font-display: swap;
    }

    @font-face {
      font-family: "MN MOCHI";
      src: url("./assets/fonts/MN MOCHI.ttf") format("truetype");
      font-display: swap;
    }

    @font-face {
      font-family: "MN Mocktail Italic";
      src: url("./assets/fonts/MN Mocktail Italic.ttf") format("truetype");
      font-display: swap;
    }

    @font-face {
      font-family: "MN Mocktail";
      src: url("./assets/fonts/MN Mocktail.ttf") format("truetype");
      font-display: swap;
    }

    @font-face {
      font-family: "MN Saikrok Isan Italic";
      src: url("./assets/fonts/MN Saikrok Isan Italic.ttf") format("truetype");
      font-display: swap;
    }

    @font-face {
      font-family: "MN Saikrok Isan";
      src: url("./assets/fonts/MN Saikrok Isan.ttf") format("truetype");
      font-display: swap;
    }

    @font-face {
      font-family: "MN Tomyam Italic";
      src: url("./assets/fonts/MN Tomyam Italic.ttf") format("truetype");
      font-display: swap;
    }

    @font-face {
      font-family: "MN Tomyam";
      src: url("./assets/fonts/MN Tomyam.ttf") format("truetype");
      font-display: swap;
    }

    @font-face {
      font-family: "Moji";
      src: url("./assets/fonts/Moji.ttf") format("truetype");
      font-display: swap;
    }

    @font-face {
      font-family: "Saturn";
      src: url("./assets/fonts/Saturn.ttf") format("truetype");
      font-display: swap;
    }

    @font-face {
      font-family: "SaturnThin";
      src: url("./assets/fonts/SaturnThin.ttf") format("truetype");
      font-display: swap;
    }

    @font-face {
      font-family: "Anton";
      src: url("./assets/fonts/Anton.ttf") format("truetype");
      font-display: swap;
    }

    @font-face {
      font-family: "Berkshire Swash";
      src: url("./assets/fonts/Berkshire Swash.ttf") format("truetype");
      font-display: swap;
    }

    @font-face {
      font-family: "Bowlby One SC";
      src: url("./assets/fonts/Bowlby One SC.ttf") format("truetype");
      font-display: swap;
    }

    @font-face {
      font-family: "Chewy";
      src: url("./assets/fonts/Chewy.ttf") format("truetype");
      font-display: swap;
    }

    @font-face {
      font-family: "Cookie";
      src: url("./assets/fonts/Cookie.ttf") format("truetype");
      font-display: swap;
    }

    @font-face {
      font-family: "Pirata One";
      src: url("./assets/fonts/Pirata One.ttf") format("truetype");
      font-display: swap;
    }

    @font-face {
      font-family: "Press Start 2P";
      src: url("./assets/fonts/Press Start 2P.ttf") format("truetype");
      font-display: swap;
    }

    @font-face {
      font-family: "Mario 256";
      src: url("./assets/fonts/Mario 256.ttf") format("truetype");
      font-display: swap;
    }

    @font-face {
      font-family: "Mario Bros";
      src: url("./assets/fonts/Mario Bros.ttf") format("truetype");
      font-display: swap;
    }

    @font-face {
      font-family: "Cherry Bomb One";
      src: url("./assets/fonts/Cherry Bomb One.ttf") format("truetype");
      font-display: swap;
    }

    @font-face {
      font-family: "Chango";
      src: url("./assets/fonts/Chango.ttf") format("truetype");
      font-display: swap;
    }

    @font-face {
      font-family: "Srisakdi";
      src: url("./assets/fonts/Srisakdi.ttf") format("truetype");
      font-display: swap;
    }

    @font-face {
      font-family: "Thasadith";
      src: url("./assets/fonts/Thasadith.ttf") format("truetype");
      font-display: swap;
    }

    @font-face {
      font-family: "Niconne";
      src: url("./assets/fonts/Niconne.ttf") format("truetype");
      font-display: swap;
    }

    @font-face {
      font-family: "New Rocker";
      src: url("./assets/fonts/New Rocker.ttf") format("truetype");
      font-display: swap;
    }
    @font-face {
      font-family: "Lora Bold";
      src: url("./assets/fonts/Lora Bold.ttf") format("truetype");
      font-display: swap;
    }
    @font-face {
      font-family: "Bree Serif";
      src: url("./assets/fonts/Bree Serif.ttf") format("truetype");
      font-display: swap;
    }
    @font-face {
      font-family: "Bitter ExtraBold";
      src: url("./assets/fonts/Bitter ExtraBold.ttf") format("truetype");
      font-display: swap;
    }
    @font-face {
      font-family: "Arvo Bold";
      src: url("./assets/fonts/Arvo Bold.ttf") format("truetype");
      font-display: swap;
    }
    @font-face {
      font-family: "Roboto Slab Bold";
      src: url("./assets/fonts/Roboto Slab Bold.ttf") format("truetype");
      font-display: swap;
    }
    @font-face {
      font-family: "Zilla Slab Bold";
      src: url("./assets/fonts/Zilla Slab Bold.ttf") format("truetype");
      font-display: swap;
    }
    @font-face {
      font-family: "Pacifico";
      src: url("./assets/fonts/Pacifico.ttf") format("truetype");
      font-display: swap;
    }
    @font-face {
      font-family: "Lobster";
      src: url("./assets/fonts/Lobster.ttf") format("truetype");
      font-display: swap;
    }
    @font-face {
      font-family: "Leckerli One";
      src: url("./assets/fonts/Leckerli One.ttf") format("truetype");
      font-display: swap;
    }
    @font-face {
      font-family: "Mali";
      src: url("./assets/fonts/Mali.ttf") format("truetype");
      font-display: swap;
    }
    @font-face {
      font-family: "Itim";
      src: url("./assets/fonts/Itim.ttf") format("truetype");
      font-display: swap;
    }
    @font-face {
      font-family: "Sriracha";
      src: url("./assets/fonts/Sriracha.ttf") format("truetype");
      font-display: swap;
    }
    /* Large Korean / Japanese / Chinese fonts: the picker previews them from small
       subsets (tools/font-preview-subsets.mjs); designs load the full font on demand. */
    @font-face {
      font-family: "Jua";
      src: url("./assets/fonts/preview/Jua.ttf") format("truetype");
      font-display: swap;
    }
    @font-face {
      font-family: "Dongle";
      src: url("./assets/fonts/preview/Dongle.ttf") format("truetype");
      font-display: swap;
    }
    @font-face {
      font-family: "Gamja Flower";
      src: url("./assets/fonts/preview/Gamja Flower.ttf") format("truetype");
      font-display: swap;
    }
    @font-face {
      font-family: "Gaegu";
      src: url("./assets/fonts/preview/Gaegu.ttf") format("truetype");
      font-display: swap;
    }
    @font-face {
      font-family: "M PLUS Rounded 1c";
      src: url("./assets/fonts/preview/M PLUS Rounded 1c.ttf") format("truetype");
      font-display: swap;
    }
    @font-face {
      font-family: "Hachi Maru Pop";
      src: url("./assets/fonts/preview/Hachi Maru Pop.ttf") format("truetype");
      font-display: swap;
    }
    @font-face {
      font-family: "Yomogi";
      src: url("./assets/fonts/preview/Yomogi.ttf") format("truetype");
      font-display: swap;
    }
    @font-face {
      font-family: "Kosugi Maru";
      src: url("./assets/fonts/preview/Kosugi Maru.ttf") format("truetype");
      font-display: swap;
    }
    @font-face {
      font-family: "ZCOOL KuaiLe";
      src: url("./assets/fonts/preview/ZCOOL KuaiLe.ttf") format("truetype");
      font-display: swap;
    }
    @font-face {
      font-family: "Liu Jian Mao Cao";
      src: url("./assets/fonts/preview/Liu Jian Mao Cao.ttf") format("truetype");
      font-display: swap;
    }
    @font-face {
      font-family: "Ma Shan Zheng";
      src: url("./assets/fonts/preview/Ma Shan Zheng.ttf") format("truetype");
      font-display: swap;
    }
    @font-face {
      font-family: "ZCOOL QingKe HuangYou";
      src: url("./assets/fonts/preview/ZCOOL QingKe HuangYou.ttf") format("truetype");
      font-display: swap;
    }

    :root {
      --cream: #fdf6e6;
      --cream-deep: #f5e8c8;
      --sage: #cddcbd;
      --sage-strong: #9bb886;
      --sage-deep: #55703f;
      --yellow: #f2dd9e;
      --yellow-deep: #b6883a;
      --blue-muted: #9cbccb;
      --ink: #3a2f28;
      --ink-soft: #7a6b5e;

      --font-display: "18jindaEclairBold", Arial, sans-serif;
      --font-accent: "JindaBiscuitPieBold", Arial, sans-serif;
    }

    * {
      box-sizing: border-box;
    }

    body {
      margin: 0;
      min-height: 100vh;
      font-family: Arial, sans-serif;
      background:
        url("./assets/cutescape-bg.png") center top / cover no-repeat fixed,
        var(--cream);
      color: var(--ink);
    }

    .page {
      width: min(1180px, 94%);
      margin: 0 auto;
      padding: 30px 0 50px;
    }

    .header {
      text-align: center;
      margin-bottom: 28px;
      position: relative;
    }

    .lang-toggle {
      position: absolute;
      top: 0;
      right: 0;
      display: inline-flex;
      align-items: center;
      gap: 4px;
      background: var(--cream-deep);
      border: 1.5px solid var(--sage);
      border-radius: 999px;
      padding: 4px 6px;
    }

    .staff-entry {
      position: absolute;
      top: 0;
      left: 0;
      display: inline-flex;
      align-items: center;
      background: var(--cream-deep);
      border: 1.5px solid var(--sage);
      border-radius: 999px;
      padding: 7px 14px;
      font-family: var(--font-accent);
      font-size: 13px;
      font-weight: 700;
      color: var(--sage-deep);
      text-decoration: none;
    }

    .staff-entry:hover {
      background: var(--sage-strong);
      color: #ffffff;
    }

    .staff-entry[hidden] {
      display: none;
    }

    /* Phones in shop mode: keep both corner pills above the logo. */
    @media (max-width: 480px) {
      .header:has(.staff-entry:not([hidden])) {
        padding-top: 46px;
      }
    }

    .lang-toggle-btn {
      border: none;
      background: none;
      cursor: pointer;
      padding: 3px 9px;
      border-radius: 999px;
      font-family: var(--font-accent);
      font-size: 13px;
      font-weight: 700;
      color: var(--ink-soft);
    }

    .lang-toggle-btn.active {
      background: var(--sage-strong);
      color: #ffffff;
    }

    .lang-toggle-sep {
      color: var(--ink-soft);
      opacity: 0.5;
      font-size: 13px;
    }

    .header-logo {
      display: block;
      margin: 0 auto;
      width: min(420px, 80%);
      height: auto;
    }

    .header p {
      margin: 10px 0 0;
      font-family: var(--font-accent);
      color: var(--sage-deep);
      font-size: 21px;
      text-shadow: 1px 1px 0 var(--cream);
    }

    .studio {
      display: grid;
      grid-template-columns: 360px 1fr;
      gap: 24px;
    }

    .panel,
    .preview-panel {
      position: relative;
      background: rgba(255, 255, 255, 0.97);
      border-radius: 26px;
      box-shadow:
        0 10px 0 rgba(155, 184, 134, 0.25),
        0 24px 46px rgba(58, 47, 40, 0.12);
    }

    .panel {
      border: 3px solid var(--sage-strong);
      padding: 26px;
    }

    .preview-panel {
      border: 3px solid var(--sage-strong);
    }

    .panel::before {
      content: "";
      position: absolute;
      top: -10px;
      left: 30px;
      width: 84px;
      height: 24px;
      background: var(--yellow);
      opacity: 0.9;
      transform: rotate(-4deg);
      border-radius: 4px;
      box-shadow: 0 3px 5px rgba(58, 47, 40, 0.18);
      pointer-events: none;
    }

    .preview-panel::before {
      content: "";
      position: absolute;
      top: -10px;
      right: 34px;
      width: 84px;
      height: 24px;
      background: var(--blue-muted);
      opacity: 0.9;
      transform: rotate(3deg);
      border-radius: 4px;
      box-shadow: 0 3px 5px rgba(58, 47, 40, 0.18);
      pointer-events: none;
    }

    .panel h2 {
      margin-top: 0;
      margin-bottom: 22px;
      font-family: var(--font-display);
      font-size: 24px;
      color: var(--ink);
    }

    .field {
      margin-bottom: 28px;
    }

    .field label {
      display: block;
      margin-bottom: 5px;
      font-family: var(--font-display);
      font-size: 18px;
      letter-spacing: 0.3px;
      color: var(--sage-deep);
    }

    .field-disabled {
      opacity: 0.5;
    }

    input[type="text"],
    select {
      width: 100%;
      height: 50px;
      border: 1.5px solid var(--sage);
      border-radius: 12px;
      padding: 0 16px;
      font-size: 20px;
      outline: none;
      background: white;
      color: var(--ink);
      font-family: Arial, sans-serif;
    }

    input[type="text"]:focus,
    select:focus {
      border-color: var(--sage-strong);
    }

    #baseStyleSelect {
      font-family: var(--font-display);
    }

    .font-select-wrap {
      position: relative;
    }

    .font-select-trigger {
      width: 100%;
      height: 50px;
      border: 1.5px solid var(--sage);
      border-radius: 12px;
      padding: 0 16px;
      background: white;
      color: var(--ink);
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 10px;
      cursor: pointer;
      text-align: left;
    }

    .font-select-trigger span:first-child {
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      font-size: 18px;
    }

    .font-select-trigger:focus,
    .font-select-trigger[aria-expanded="true"] {
      outline: none;
      border-color: var(--sage-strong);
    }

    .font-select-caret {
      flex-shrink: 0;
      color: var(--sage-deep);
    }

    .font-select-panel {
      position: absolute;
      z-index: 20;
      top: calc(100% + 6px);
      left: 0;
      right: 0;
      max-height: 320px;
      overflow-y: auto;
      background: white;
      border: 1.5px solid var(--sage);
      border-radius: 12px;
      box-shadow: 0 12px 28px rgba(58, 47, 40, 0.18);
      padding: 6px;
    }

    .font-select-option {
      display: block;
      width: 100%;
      text-align: left;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
      border: none;
      background: none;
      border-radius: 8px;
      padding: 9px 10px;
      font-size: 18px;
      color: var(--ink);
      cursor: pointer;
    }

    /* display: block above would otherwise show rows the language/compatibility filter hid. */
    .font-select-option[hidden] { display: none; }

    .font-select-option-preview {
      color: #9a9a9a;
    }

    .font-select-option:hover {
      background: var(--cream-deep);
    }

    .font-select-option.active {
      background: var(--sage);
      color: var(--sage-deep);
    }

    /* Language filters above the font picker (font-select-ui.js). */
    .font-filter-pills {
      display: flex;
      flex-wrap: wrap;
      gap: 6px;
      margin-bottom: 8px;
    }

    .font-filter-pill {
      border: 1.5px solid var(--sage);
      border-radius: 999px;
      background: white;
      color: var(--ink);
      padding: 4px 12px;
      font-size: 14px;
      cursor: pointer;
    }

    .font-filter-pill[aria-pressed="true"] {
      background: var(--sage);
      border-color: var(--sage-strong);
      color: var(--sage-deep);
    }

    .font-filter-note {
      margin: 0 0 8px;
      font-size: 13px;
      color: #8a6d3b;
    }

    /* The selected font cannot build the current design (name-font-compat.js). */
    .font-filter-note--error {
      color: #b3261e;
    }

    /* The selected font, shown although it is outside the active filter. */
    .color-row {
      display: flex;
      gap: 10px;
      flex-wrap: wrap;
    }

    /* Clicker จากรูป's base/border grids use these same swatch rules (below). */
    .color-button,
    #clickerPanel .housing-color-grid .color-palette-swatch {
      width: 46px;
      height: 46px;
      border-radius: 50%;
      border: 4px solid white;
      box-shadow: 0 0 0 2px var(--cream-deep);
      cursor: pointer;
    }

    .color-button.active,
    #clickerPanel .housing-color-grid .color-palette-swatch.active {
      box-shadow:
        0 0 0 3px #fff,
        0 0 0 6px var(--sage-strong),
        0 6px 14px rgba(58, 47, 40, 0.22);
      transform: scale(1.08);
    }

    /* Customer name products use a slightly lighter swatch; Letter Beads keeps its own. */
    :is(#nameKeychainPanel, #nameClickerPanel) .color-button {
      width: 42px;
      height: 42px;
    }

    .price-box {
      margin-top: 28px;
      background: var(--yellow);
      border: 3px solid var(--yellow-deep);
      border-radius: 18px;
      padding: 18px;
      text-align: center;
    }

    .price-label {
      color: var(--ink-soft);
      font-size: 15px;
    }

    .price {
      margin-top: 4px;
      font-size: 38px;
      font-weight: bold;
      color: var(--ink);
    }

    .order-button {
      width: 100%;
      height: 56px;
      margin-top: 14px;
      border: 3px solid var(--ink);
      border-radius: 18px;
      background: var(--sage-strong);
      color: white;
      font-family: var(--font-display);
      font-size: 18px;
      letter-spacing: 0.5px;
      cursor: pointer;
      box-shadow: 0 5px 0 var(--sage-deep);
      transition: transform 0.12s ease, box-shadow 0.12s ease;
    }

    .order-button:hover {
      transform: translateY(-2px);
    }

    .order-button:active {
      transform: translateY(3px);
      box-shadow: 0 2px 0 var(--sage-deep);
    }

    .order-button.secondary {
      background: white;
      color: var(--ink);
      border: 3px solid var(--ink);
      box-shadow: 0 5px 0 rgba(58, 47, 40, 0.22);
    }

    .design-id-result {
      margin-top: 12px;
      padding: 12px 14px;
      border-radius: 14px;
      background: var(--yellow);
      border: 3px solid var(--yellow-deep);
      font-size: 14px;
      text-align: center;
      color: var(--ink);
    }

    .design-id-result strong {
      display: block;
      margin-top: 4px;
      font-weight: bold;
      font-size: 19px;
      letter-spacing: 1.5px;
      color: var(--ink);
    }

    #clickerLoadDesignPreviewImage {
      display: block;
      margin-top: 8px;
      max-width: 160px;
      max-height: 160px;
      border-radius: 12px;
      border: 2px solid var(--sage-strong, #b7cdb0);
    }

    .preview-panel {
      min-height: 560px;
      padding: 24px;
      display: flex;
      flex-direction: column;
    }

    .preview-title {
      display: flex;
      justify-content: space-between;
      align-items: center;
      position: relative;
      z-index: 10;
    }

    .preview-title h2 {
      margin: 0;
      font-family: var(--font-display);
      font-size: 24px;
      color: var(--ink);
    }

    .live-badge {
      background: var(--sage);
      color: var(--sage-deep);
      font-weight: bold;
      padding: 7px 12px;
      border-radius: 999px;
      font-size: 13px;
    }

    /* Shared try-click control; see name-clicker/name-clicker.css. */

    .clicker-preview-mode-toggle {
      display: inline-flex;
      border: 2px solid var(--sage-strong);
      border-radius: 999px;
      overflow: hidden;
      flex-shrink: 0;
    }

    .clicker-preview-mode-button {
      border: none;
      background: white;
      color: var(--ink);
      font-family: var(--font-display);
      font-size: 13px;
      padding: 7px 14px;
      cursor: pointer;
    }

    .clicker-preview-mode-button.active {
      background: var(--sage-strong);
      color: white;
    }

    #nameKeychainPanel .panel, #nameKeychainPanel .preview-panel { min-width: 0; }
    #nameKeychainPanel .preview-title { flex-wrap: wrap; gap: 10px; }
    #threeViewer { position: relative; min-width: 0; }
    #threeViewer canvas { display: block; max-width: 100%; }
    #nameDimensionOverlay, #photoKeychainDimensionOverlay, #photoKeycapDimensionOverlay, #textKeycapDimensionOverlay, #nameClickerDimensionOverlay, #clickerDimensionOverlay { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; z-index: 1; overflow: hidden; }
    #nameDimensionOverlay[hidden], #photoKeychainDimensionOverlay[hidden], #photoKeycapDimensionOverlay[hidden], #textKeycapDimensionOverlay[hidden], #nameClickerDimensionOverlay[hidden], #clickerDimensionOverlay[hidden] { display: none; }
    /* Backdrop behind the transparent 3D canvases (Name Keychain, Photo
       Keychain, Clicker จากรูป, Name Clicker), so white/light edges still read. */
    /* "พื้นหลังตัวอย่าง" (preview-background.js): a display preference only. */
    :root[data-preview-bg="cream"] { --preview-3d-bg: #F7F9D8; }
    :root[data-preview-bg="pink"] { --preview-3d-bg: radial-gradient(circle at center, #FFF9ED 0%, #F3E5CB 100%); }
    :root[data-preview-bg="dark"] { --preview-3d-bg: #252525; }
    /* White is the default (also before preview-background.js runs). */
    :root, :root[data-preview-bg="white"] { --preview-3d-bg: #F7F7F7; }
    .preview-bg-picker { position: absolute; top: 10px; right: 10px; z-index: 3; display: flex; align-items: center; gap: 5px;
      padding: 4px 7px; border-radius: 999px; background: rgba(255, 255, 255, .72); box-shadow: 0 1px 3px rgba(0, 0, 0, .12); }
    .preview-bg-label { font-size: 11px; line-height: 1; color: #6b6259; margin-right: 1px; white-space: nowrap; }
    .preview-bg-swatch { width: 18px; height: 18px; padding: 0; border-radius: 50%; border: 1px solid rgba(0, 0, 0, .25);
      background: var(--swatch); cursor: pointer; flex-shrink: 0; }
    .preview-bg-swatch[aria-pressed="true"] { box-shadow: 0 0 0 2px #fff, 0 0 0 3.5px #6b6259; }
    .preview-bg-swatch:focus-visible { outline: 2px solid #6b6259; outline-offset: 2px; }
    :root[data-preview-bg="dark"] .name-clicker-preview-message { color: #ededed; }
    /* Real pipeline stage, centred in the preview (photo-keychain-ui.js, clicker-ui.js, viewer.js). */
    .preview-processing { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); z-index: 2;
      display: flex; align-items: center; gap: 10px; max-width: calc(100% - 32px); padding: 10px 16px;
      border-radius: 999px; background: rgba(255, 255, 255, .86); box-shadow: 0 2px 10px rgba(0, 0, 0, .12);
      color: #3f3a34; font-size: 15px; line-height: 1.35; pointer-events: none; }
    .preview-processing[hidden] { display: none; }
    .preview-spinner { width: 18px; height: 18px; flex-shrink: 0; border-radius: 50%;
      border: 2.5px solid rgba(63, 58, 52, .2); border-top-color: #3f3a34; animation: preview-spin .8s linear infinite; }
    .preview-processing.is-error { border-radius: 14px; background: rgba(255, 244, 242, .95); color: #9a2f22; }
    .preview-processing.is-error .preview-spinner { display: none; }
    @keyframes preview-spin { to { transform: rotate(360deg); } }
    /* LINE handoff after a saved design code (line-handoff.js). */
    .line-handoff { margin-top: 10px; display: grid; gap: 8px; text-align: center; }
    .line-handoff-message { margin: 0; padding: 8px 10px; border-radius: 10px; background: rgba(255, 255, 255, .7); font-size: 14px; line-height: 1.45; overflow-wrap: anywhere; }
    .line-handoff-actions { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; }
    .line-handoff-open { display: inline-flex; align-items: center; justify-content: center; min-height: 44px; padding: 0 18px; border-radius: 12px; background: #06C755; color: #fff; font-weight: 700; text-decoration: none; }
    .line-handoff-open:focus-visible { outline: 3px solid #0a7a37; outline-offset: 2px; }
    .line-handoff-hint { margin: 0; font-size: 12px; color: var(--ink-soft); }
    /* Shop Mode gate (shop-access.js): approved device + staff PIN. */
    .shop-gate { position: fixed; inset: 0; z-index: 10000; display: grid; place-items: center; padding: 16px; background: rgba(40, 34, 28, .72); }
    .shop-gate-card { width: min(380px, 100%); padding: 22px 20px; border-radius: 18px; background: #fffaf0; box-shadow: 0 10px 30px rgba(0, 0, 0, .25); text-align: center; display: grid; gap: 12px; }
    .shop-gate-card h2 { margin: 0; }
    .shop-gate-card p { margin: 0; line-height: 1.5; }
    .shop-gate-form { display: grid; gap: 8px; }
    .shop-gate-pin { font-size: 24px; letter-spacing: 8px; text-align: center; padding: 8px; border-radius: 10px; border: 2px solid #c8ab60; }
    .shop-gate-submit { min-height: 44px; border: 0; border-radius: 12px; background: #3f3a34; color: #fff; font-weight: 700; cursor: pointer; }
    .shop-gate-error { color: #9a2f22; min-height: 1.2em; }
    .shop-gate-uid { display: block; padding: 8px; border-radius: 8px; background: #fff; font-size: 13px; overflow-wrap: anywhere; user-select: all; }
    .shop-gate-customer { font-size: 14px; color: var(--ink-soft); }
    .shop-lock-bar { position: fixed; left: 12px; bottom: 12px; z-index: 9999; display: flex; align-items: center; gap: 8px; padding: 6px 8px 6px 12px; border-radius: 999px; background: #3f3a34; color: #fff; font-size: 13px; box-shadow: 0 2px 8px rgba(0, 0, 0, .2); }
    .shop-lock-button { border: 0; border-radius: 999px; padding: 6px 12px; background: #fff; color: #3f3a34; font-weight: 700; cursor: pointer; }
    @media (prefers-reduced-motion: reduce) { .preview-spinner { animation-duration: 2.4s; } }
    /* Rulers stay readable on the dark backdrop (same lines, lighter ink). */
    :root[data-preview-bg="dark"] :is(#nameDimensionOverlay, #photoKeychainDimensionOverlay, #photoKeycapDimensionOverlay, #textKeycapDimensionOverlay, #nameClickerDimensionOverlay, #clickerDimensionOverlay) :is(.name-dim-line, .name-dim-arrow) { background: #c8c8c8 !important; }
    :root[data-preview-bg="dark"] :is(#nameDimensionOverlay, #photoKeychainDimensionOverlay, #photoKeycapDimensionOverlay, #textKeycapDimensionOverlay, #nameClickerDimensionOverlay, #clickerDimensionOverlay) :is(.name-dim-label, .name-dim-label *) { color: #ededed !important; -webkit-text-fill-color: #ededed !important; }
    #nameKeychainPanel .preview-stage { background: var(--preview-3d-bg); }
    #photoKeychainViewer3D, #photoKeycapViewer3D, #textKeycapViewer3D, #clickerViewer3D { background: var(--preview-3d-bg); }
    #nameKeychainPanel .preview-stage::before { display: none; }
    :is(#nameDimensionOverlay, #photoKeychainDimensionOverlay, #photoKeycapDimensionOverlay, #textKeycapDimensionOverlay, #nameClickerDimensionOverlay, #clickerDimensionOverlay), :is(#nameDimensionOverlay, #photoKeychainDimensionOverlay, #photoKeycapDimensionOverlay, #textKeycapDimensionOverlay, #nameClickerDimensionOverlay, #clickerDimensionOverlay) * { opacity: 1 !important; filter: none !important; mix-blend-mode: normal !important; text-shadow: none !important; box-shadow: none !important; }
    :is(#nameDimensionOverlay, #photoKeychainDimensionOverlay, #photoKeycapDimensionOverlay, #textKeycapDimensionOverlay, #nameClickerDimensionOverlay, #clickerDimensionOverlay) > div { position: absolute; margin: 0; padding: 0; border: 0; }
    :is(#nameDimensionOverlay, #photoKeychainDimensionOverlay, #photoKeycapDimensionOverlay, #textKeycapDimensionOverlay, #nameClickerDimensionOverlay, #clickerDimensionOverlay) .name-dim-line,
    :is(#nameDimensionOverlay, #photoKeychainDimensionOverlay, #photoKeycapDimensionOverlay, #textKeycapDimensionOverlay, #nameClickerDimensionOverlay, #clickerDimensionOverlay) .name-dim-arrow { background: #666666 !important; }
    :is(#nameDimensionOverlay, #photoKeychainDimensionOverlay, #photoKeycapDimensionOverlay, #textKeycapDimensionOverlay, #nameClickerDimensionOverlay, #clickerDimensionOverlay) .name-dim-arrow-left { clip-path: polygon(0 50%, 100% 0, 100% 100%); }
    :is(#nameDimensionOverlay, #photoKeychainDimensionOverlay, #photoKeycapDimensionOverlay, #textKeycapDimensionOverlay, #nameClickerDimensionOverlay, #clickerDimensionOverlay) .name-dim-arrow-right { clip-path: polygon(100% 50%, 0 0, 0 100%); }
    :is(#nameDimensionOverlay, #photoKeychainDimensionOverlay, #photoKeycapDimensionOverlay, #textKeycapDimensionOverlay, #nameClickerDimensionOverlay, #clickerDimensionOverlay) .name-dim-arrow-up { clip-path: polygon(50% 0, 0 100%, 100% 100%); }
    :is(#nameDimensionOverlay, #photoKeychainDimensionOverlay, #photoKeycapDimensionOverlay, #textKeycapDimensionOverlay, #nameClickerDimensionOverlay, #clickerDimensionOverlay) .name-dim-arrow-down { clip-path: polygon(50% 100%, 0 0, 100% 0); }
    /* Labels sit a shade darker than the lines so they read first. */
    :is(#nameDimensionOverlay, #photoKeychainDimensionOverlay, #photoKeycapDimensionOverlay, #textKeycapDimensionOverlay, #nameClickerDimensionOverlay, #clickerDimensionOverlay) .name-dim-label, :is(#nameDimensionOverlay, #photoKeychainDimensionOverlay, #photoKeycapDimensionOverlay, #textKeycapDimensionOverlay, #nameClickerDimensionOverlay, #clickerDimensionOverlay) .name-dim-label * { color: #444444 !important; -webkit-text-fill-color: #444444 !important; opacity: 1 !important; filter: none !important; text-shadow: none !important; mix-blend-mode: normal !important; font: 700 16px/1 Arial, sans-serif; white-space: nowrap; background: none; }
    :is(#nameDimensionToggle, #photoKeychainDimensionToggle, #photoKeycapDimensionToggle, #nameClickerDimensionToggle, #clickerDimensionToggle) { flex: 0 0 auto; padding: 7px 10px; border: 1px solid var(--cream-deep); border-radius: 9px; cursor: pointer; background: white; color: inherit; white-space: nowrap; }
    :is(#nameDimensionToggle, #photoKeychainDimensionToggle, #photoKeycapDimensionToggle, #nameClickerDimensionToggle, #clickerDimensionToggle)[aria-pressed="true"] { background: var(--cream-deep); }
    /* Preview header follows Name Clicker (name-clicker/name-clicker.css): title, size
       toggle and badge sit together on the left; a preview-mode toggle, if any, goes right. */
    :is(#nameKeychainPanel, #photoKeychainPanel, #keycapPanel, #clickerPanel) .preview-title { align-items: center; gap: 10px; }
    #clickerPanel .preview-title .clicker-preview-mode-toggle { margin-left: auto; }
    /* Longer English labels wrap the toggle to its own line instead of squeezing the title. */
    #clickerPanel .preview-title { flex-wrap: wrap; }
    /* Pack the left group explicitly: Name/Photo Keychain have no mode toggle to absorb
       the free space, and a wrapped Clicker toggle no longer shares the first line. */
    @media (min-width: 601px) {
      :is(#nameKeychainPanel, #photoKeychainPanel, #keycapPanel, #clickerPanel) .preview-title { justify-content: flex-start; }
    }
    @media (max-width: 600px) {
      #clickerPanel .preview-title .clicker-preview-mode-toggle { margin-left: 0; width: 100%; }
      :is(#nameKeychainPanel, #photoKeychainPanel, #keycapPanel, #clickerPanel) .preview-title { flex-wrap: wrap; gap: 8px; }
      /* Phones: the Clickers' mode toggle sits in the preview's top-left corner
         (moved there by customer-workspace.js) in place of the stage dots, opposite
         the background picker. */
      #nameClickerPanel .name-clicker-stage::before { display: none; }
      .clicker-preview-mode-toggle.in-preview { position: absolute; top: 10px; left: 10px; z-index: 3; margin: 0; width: auto;
        border-width: 1.5px; box-shadow: 0 1px 3px rgba(0, 0, 0, .12); }
      .clicker-preview-mode-toggle.in-preview .clicker-preview-mode-button { font-size: 11px; line-height: 1.2; padding: 5px 9px; }
      /* Phones: the Clickers' heading takes the first line; the controls share the
         second, in the order ซ่อนสเกล → กดเล่นได้ → sound (visual order only). */
      :is(#nameClickerPanel, #clickerPanel) .preview-title { justify-content: flex-start; }
      :is(#nameClickerPanel, #clickerPanel) .preview-title > h2 { flex-basis: 100%; }
      :is(#nameClickerPanel, #clickerPanel) .preview-title > .live-badge { order: 1; font-size: 12px; padding: 6px 10px; }
      :is(#nameClickerPanel, #clickerPanel) .preview-title > .name-clicker-sound-toggle { order: 2; }
    }
    /* The English labels and picker don't fit side by side on the narrowest phones:
       stack the two buttons, still in the top-left corner. */
    @media (max-width: 395px) {
      :root[lang="en"] .clicker-preview-mode-toggle.in-preview { flex-direction: column; border-radius: 12px; }
    }

    .product-preview-frame { position: relative; border: 4px solid var(--cream-deep); border-radius: 22px; background: linear-gradient(135deg, #fffaf0, #fff); overflow: hidden; }
    .load-design-row, .name-clicker-load { display: flex; gap: 8px; }
    .load-design-row input, .name-clicker-load input { min-width: 0; flex: 1; }
    .load-design-button { border: 2px solid #c8ab60; border-radius: 10px; padding: 8px 14px; background: #f3dfa1; color: #352f28; font-weight: 800; cursor: pointer; }

    @media (min-width: 1280px) {
      .studio-three-column { width: min(1500px, calc(100vw - 40px)); position: relative; left: 50%; transform: translateX(-50%); grid-template-columns: minmax(260px, 320px) minmax(480px, 1fr) minmax(260px, 320px); grid-template-areas: "left preview right"; align-items: start; }
      .studio-three-column > .control-panel-left { grid-area: left; }
      .studio-three-column > .preview-panel { grid-area: preview; }
      .studio-three-column > .control-panel-right { grid-area: right; }
    }

    @media (max-width: 1279px) {
      .studio-three-column { grid-template-columns: minmax(0, 1fr); min-width: 0; width: 100%; }
      .studio-three-column > .panel,
      .studio-three-column > .preview-panel { min-width: 0; width: 100%; }
      .studio-three-column canvas { max-width: 100% !important; }
      .studio-three-column > .control-panel-left { order: 1; }
      .studio-three-column > .control-panel-right { order: 2; }
      .studio-three-column > .preview-panel { order: 3; }
      .studio-three-column > .preview-panel .preview-title { flex-wrap: wrap; gap: 8px; }
    }
    .name-size-info { margin-top: 10px; }
    .name-sizing-help { color: #707070; font-size: 13px; line-height: 1.5; margin: 0 0 4px; }
    .name-size-summary { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 4px 16px; font-variant-numeric: tabular-nums; }
    #nameProductDimensions, #namePhysicalTextHeight { font-size: 16px; line-height: 1.5; white-space: nowrap; }
    .name-text-height-label { margin-top: 10px; }
    .name-price-bar { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 4px 12px; width: 100%; margin-top: 14px; padding: 10px 14px; border: 1px solid #c8ab60; border-radius: 12px; background: #f3dfa1; color: #352f28; font-weight: 600; font-variant-numeric: tabular-nums; }
    #nameProductPrice { font-size: 24px; font-weight: 800; line-height: 1.4; white-space: nowrap; }

    .preview-stage {
      position: relative;
      flex: 1;
      margin-top: 20px;
      border-radius: 22px;
      border: 4px solid var(--cream-deep);
      background:
        linear-gradient(135deg, #fffaf0, #ffffff);
      display: flex;
      justify-content: center;
      align-items: center;
      overflow: hidden;
      perspective: 900px;
      min-height: 430px;
    }

    .preview-stage::before {
      content: "";
      position: absolute;
      top: 16px;
      left: 18px;
      width: 10px;
      height: 10px;
      border-radius: 50%;
      background: var(--blue-muted);
      box-shadow:
        18px 0 0 var(--yellow-deep),
        36px 0 0 var(--sage-strong);
      pointer-events: none;
    }

    .keychain-wrap {
      transform:
        rotateX(12deg)
        rotateY(-8deg)
        rotateZ(-2deg);
      transition: 0.25s;
    }

    .keychain-wrap:hover {
      transform:
        rotateX(5deg)
        rotateY(5deg)
        rotateZ(0deg)
        scale(1.04);
    }

    .keychain {
      position: relative;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      min-width: 240px;
      max-width: 620px;
      height: 115px;
      padding: 0 35px 0 58px;
      border-radius: 32px;
      background: #111;
      box-shadow:
        0 8px 0 #000,
        0 18px 35px rgba(0, 0, 0, 0.28);
    }

    .hole-area {
      position: absolute;
      left: -28px;
      width: 92px;
      height: 92px;
      border-radius: 50%;
      background: inherit;
      box-shadow: 0 8px 0 #000;
    }

    .hole {
      position: absolute;
      left: 2px;
      width: 32px;
      height: 32px;
      border-radius: 50%;
      background: #f5f5f5;
      box-shadow:
        inset 0 4px 7px rgba(0, 0, 0, 0.4);
      z-index: 2;
    }

    .name-preview {
      position: relative;
      z-index: 3;
      color: white;
      font-size: 64px;
      font-weight: 900;
      white-space: nowrap;
      line-height: 1;
      text-shadow:
        0 2px 0 rgba(255, 255, 255, 0.25),
        0 4px 0 rgba(0, 0, 0, 0.25);
    }

    .hint {
      text-align: center;
      color: var(--ink-soft);
      margin-top: 15px;
    }

    [data-product-tab],
    [data-name-mode] {
      font-family: var(--font-display);
      font-size: 15px;
      border: 3px solid var(--ink);
      border-radius: 999px;
      padding: 10px 8px;
      background: #fff;
      color: var(--ink);
      cursor: pointer;
      box-shadow: 0 4px 0 rgba(58, 47, 40, 0.2);
      transition: transform 0.12s ease, background 0.12s ease, box-shadow 0.12s ease;
    }

    [data-product-tab]:hover,
    [data-name-mode]:hover {
      transform: translateY(-1px);
    }

    [data-product-tab][style*="700"],
    [data-name-mode][style*="700"] {
      background: var(--sage);
      box-shadow: 0 2px 0 rgba(58, 47, 40, 0.28);
      transform: translateY(2px);
    }

    .product-tabs {
      flex-wrap: wrap;
      justify-content: center;
    }

    .product-tabs > [data-product-tab] {
      flex: 0 0 auto !important;
      padding-inline: 18px;
      white-space: nowrap;
    }

    /* Shop mode (?shop=1) shows all five product tabs (Letter Beads visible):
       compact one-line pills that wrap as whole pills instead of squeezing.
       !important overrides the row's inline flex/max-width; customer mode
       (three tabs) does not match and keeps its current layout. */
    div:has(> [data-product-tab="letter"]:not([hidden])) {
      flex-wrap: wrap;
      justify-content: center;
      max-width: 760px !important;
    }

    div:has(> [data-product-tab="letter"]:not([hidden])) > [data-product-tab] {
      flex: 0 0 auto !important;
      padding: 10px 18px;
      white-space: nowrap;
    }

    /* Desktop shop mode: all seven product tabs on one row. The 760px cap
       above (and name-clicker.css's) is for the customer's five tabs; here
       the row takes the page width and the pills are a little narrower.
       Narrower screens keep wrapping as whole pills. */
    @media (min-width: 1024px) {
      div.product-tabs:has(> [data-product-tab="perler"]:not([hidden])) {
        flex-wrap: nowrap;
        max-width: none !important;
        gap: 6px !important;
      }

      div.product-tabs:has(> [data-product-tab="perler"]:not([hidden])) > [data-product-tab] {
        padding: 10px 14px;
      }
    }

    @media (max-width: 850px) {
      .studio {
        grid-template-columns: 1fr;
      }

      .preview-panel {
        min-height: 470px;
      }

      .name-preview {
        font-size: 48px;
      }

      .keychain {
        transform: scale(0.85);
      }
    }

    @media (max-width: 480px) {
      .header-logo {
        width: min(260px, 70%);
      }

      .page {
        padding-top: 20px;
      }

      .header {
        margin-bottom: 20px;
      }

      .studio {
        gap: 18px;
      }

      .panel,
      .preview-panel {
        border-radius: 20px;
      }

      .panel {
        padding: 18px;
      }

      .preview-panel {
        padding: 18px;
      }

      .panel::before {
        top: -8px;
        left: 20px;
        width: 60px;
        height: 16px;
      }

      .preview-panel::before {
        top: -8px;
        right: 22px;
        width: 60px;
        height: 16px;
      }

      .field {
        margin-bottom: 20px;
      }

      .color-row,
      #clickerPanel .housing-color-grid {
        gap: 8px;
      }

      .color-button {
        width: 42px;
        height: 42px;
      }

      .font-select-panel {
        max-height: 260px;
      }

      .preview-stage {
        min-height: 220px;
      }
    }

    /* =========================================
       Clicker from Image — Phase 1 (additive only)
       ========================================= */

    .clicker-studio {
      margin-top: 40px;
    }

    .clicker-phase-note {
      margin: -10px 0 22px;
      color: var(--ink-soft);
      font-size: 14px;
    }

    input[type="file"] {
      width: 100%;
      border: 2px dashed var(--sage-strong);
      border-radius: 14px;
      padding: 14px 16px;
      font-size: 15px;
      background: white;
    }

    input[type="range"] {
      width: 100%;
      accent-color: var(--sage-strong);
    }

    .name-size-value,
    .outline-value {
      display: grid;
      grid-template-columns: 1fr 1fr 1fr;
      align-items: center;
      width: 100%;
      margin-top: 10px;
      font-size: 13px;
      color: var(--ink-soft);
    }

    .name-size-value span:first-child,
    .name-size-value span:last-child,
    .outline-value span:first-child,
    .outline-value span:last-child {
      font-family: var(--font-display);
    }

    .name-size-value span:first-child,
    .outline-value span:first-child {
      text-align: left;
    }

    .name-size-value span:nth-child(2),
    .outline-value span:nth-child(2),
    #nameKeychainPanel .ws-value-pill {
      justify-self: center;
      text-align: center;
      font-family: Arial, sans-serif;
      font-weight: bold;
      font-size: 14px;
      color: var(--ink);
      padding: 1px 8px;
      border: 1.5px solid var(--sage);
      border-radius: 999px;
      background: #ffffff;
      line-height: 1.3;
    }

    .name-size-value span:last-child,
    .outline-value span:last-child {
      text-align: right;
    }

    .toggle-button {
      width: 100%;
      height: 48px;
      border: 2px solid var(--sage-strong);
      border-radius: 14px;
      background: white;
      font-family: var(--font-display);
      font-size: 15px;
      color: var(--ink);
      cursor: pointer;
    }

    .toggle-button.active {
      border-color: var(--sage-strong);
      background: var(--sage);
      color: var(--sage-deep);
    }

    .clicker-debug-info {
      white-space: pre-wrap;
      font-family: "Courier New", monospace;
      font-size: 13px;
      background: var(--cream-deep);
      border-radius: 12px;
      padding: 12px 14px;
      margin: 0;
      line-height: 1.5;
      color: var(--ink-soft);
    }

    /* Name Keychain load-by-code status strip: collapse completely (no
       padding/background/gap) until JS actually puts a message in it. */
    #loadDesignStatus:empty,
    #photoKeychainLoadDesignStatus:empty,
    #photoKeycapLoadDesignStatus:empty,
    #textKeycapLoadDesignStatus:empty,
    #letterBeadsStatus:empty,
    #imageBeadsStatus:empty {
      display: none;
    }

    /* Custom localized "choose image" control. The real <input type="file">
       stays functional but visually hidden (not display:none — that can
       break keyboard/label activation in some browsers); a styled <label>
       triggers it natively, no JS needed to open the file dialog. */
    .clicker-file-input-row {
      display: flex;
      align-items: center;
      gap: 12px;
      flex-wrap: wrap;
    }

    .clicker-file-input-button {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      flex-shrink: 0;
      padding: 10px 18px;
      border: 2px solid var(--sage-strong);
      border-radius: 14px;
      background: white;
      font-family: var(--font-display);
      font-size: 14px;
      color: var(--ink);
      cursor: pointer;
    }

    .clicker-file-input-button:hover {
      background: var(--sage);
    }

    .clicker-file-input-name {
      font-size: 13px;
      color: var(--ink-soft);
      overflow-wrap: anywhere;
    }

    input.clicker-file-input-native {
      position: absolute;
      width: 1px;
      height: 1px;
      padding: 0;
      margin: -1px;
      overflow: hidden;
      clip: rect(0, 0, 0, 0);
      white-space: nowrap;
      border: 0;
    }

    .clicker-empty-state {
      text-align: center;
      color: var(--ink-soft);
      margin-top: 60px;
    }

    .clicker-canvas-row {
      display: none;
      flex-wrap: wrap;
      gap: 18px;
      margin-top: 20px;
      justify-content: center;
    }

    .clicker-canvas-box {
      display: flex;
      flex-direction: column;
      align-items: center;
      gap: 8px;
    }

    .clicker-canvas-box span {
      font-size: 13px;
      color: var(--ink-soft);
      font-weight: bold;
    }

    .clicker-canvas-box canvas {
      max-width: 260px;
      max-height: 260px;
      width: auto;
      height: auto;
      border: 1px solid #e2e2e2;
      border-radius: 12px;
      background: #fff;
      image-rendering: pixelated;
    }

    /* Main-view original-image thumbnail — kept visible but small, so
       the 3D preview stays the main visual focus. Only this box's
       canvas shrinks; the same base canvas box used inside "ขั้นสูง /
       ดีบัก" below is untouched. */
    .clicker-canvas-box--compact canvas {
      max-width: 130px;
      max-height: 130px;
    }

    /* Collapsed "Advanced / Debug" section — moved-in technical
       controls (Threshold/Invert/Smoothing), the raw debug readout,
       and the Mask/Silhouette 2D previews. Same visual language as the
       rest of the panel, just tucked away by default. */
    .clicker-advanced {
      margin-top: 18px;
      padding-top: 14px;
      border-top: 2px dashed var(--sage-strong);
    }

    .clicker-advanced summary {
      cursor: pointer;
      font-family: var(--font-display);
      font-size: 15px;
      color: var(--ink-soft);
      list-style: none;
    }

    .clicker-advanced summary::-webkit-details-marker {
      display: none;
    }

    .clicker-advanced summary::before {
      content: "▸ ";
    }

    .clicker-advanced[open] summary::before {
      content: "▾ ";
    }

    .clicker-advanced summary + * {
      margin-top: 14px;
    }

    .clicker-advanced .field {
      margin-top: 14px;
    }

    /* Static (always-laid-out) row for the Mask/Silhouette previews
       inside the collapsed section — separate from .clicker-canvas-row
       because that class defaults to display:none and is only flipped
       to flex by clicker-ui.js for the #clickerCanvasRow original-image
       box specifically; these two canvases have no upload gate of
       their own and simply sit inside the closed <details> until
       expanded. */
    .clicker-canvas-row--static {
      display: flex;
      flex-wrap: wrap;
      gap: 18px;
      justify-content: center;
      margin-top: 14px;
    }

    /* =========================================
       Clicker TOP color regions — editable detected → output colors.
       ========================================= */

    .color-region-rows {
      display: flex;
      flex-direction: column;
      gap: 10px;
    }

    .clicker-color-region-empty {
      font-size: 13px;
      color: var(--ink-soft);
      margin: 0;
    }

    .color-region-row {
      display: flex;
      align-items: center;
      gap: 10px;
      font-size: 14px;
      color: var(--ink-soft);
    }

    .color-region-label {
      flex: 1;
      font-family: var(--font-display);
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }

    .color-region-swatch,
    .color-region-target {
      width: 30px;
      height: 30px;
      min-width: 30px;
      border-radius: 50%;
      border: 3px solid white;
      box-shadow: 0 0 0 1px var(--cream-deep);
    }

    .color-region-target {
      cursor: pointer;
      padding: 0;
    }

    .color-region-target:hover,
    .color-region-target:focus-visible {
      box-shadow: 0 0 0 1px var(--cream-deep), 0 0 0 3px var(--sage-strong);
    }

    .color-region-arrow {
      color: var(--ink-soft);
      flex-shrink: 0;
    }

    /* Photo products: "สีสำหรับพิมพ์ · X/4 สี" with one chip per print colour
       (clicker/print-palette.js renderPrintPaletteSummary). */
    .print-palette-head {
      display: flex;
      align-items: center;
      justify-content: space-between;
      flex-wrap: wrap;
      gap: 6px 10px;
    }

    .print-palette-head label {
      margin-bottom: 0;
    }

    .region-edit-toggle {
      font-family: var(--font-display);
      font-size: 14px;
      font-weight: normal;
      padding: 6px 14px;
      border: 2px solid var(--sage-strong);
      border-radius: 20px;
      background: white;
      color: var(--sage-deep);
      cursor: pointer;
      transition: all 0.15s ease;
      white-space: nowrap;
    }

    .region-edit-toggle:active {
      transform: scale(0.98);
    }

    .region-edit-toggle.active {
      background: var(--sage-strong);
      color: white;
      border-color: var(--sage-strong);
      box-shadow: inset 0 2px 4px rgba(0,0,0,0.1);
    }

    /* เลือกสีแต่ละส่วน (clicker/photo-region-edit.js): right under every photo preview. */
    .region-edit-host { margin: 10px 0 0; }
    /* ลบพื้นหลัง (photo-background.js): right under every photo upload. */
    .photo-background-host { margin: 8px 0 4px; }
    .photo-background-host[hidden] { display: none; }
    .photo-background-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
    .photo-background-label { font-weight: 600; }
    .photo-background-status:empty { display: none; }
    /* ไอคอนตกแต่ง price line (decoration-picker.js showDecorationPriceNote). */
    .decoration-price-note { margin: 4px 0 0; text-align: right; font-size: 0.85em; color: var(--ink-soft); }
    .decoration-price-note[hidden] { display: none; }
    .region-edit-bar { display: flex; flex-direction: column; align-items: center; gap: 8px; }
    .region-edit-bar[hidden], .region-edit-actions[hidden] { display: none; }
    .region-edit-bar .region-edit-toggle { font-size: 15px; padding: 8px 18px; box-shadow: 0 1px 4px rgba(0, 0, 0, 0.10); }
    .region-edit-actions { display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: 6px 8px; width: 100%; }
    .region-edit-status { flex-basis: 100%; text-align: center; font-size: 0.9em; color: var(--ink-soft); }
    .region-edit-action { font-family: var(--font-display); font-size: 14px; padding: 5px 12px; border: 2px solid var(--sage-strong); border-radius: 999px;
      background: white; color: var(--sage-deep); cursor: pointer; }
    .region-edit-action:disabled { opacity: 0.45; cursor: default; }
    .region-edit-delete:not(:disabled) { border-color: #d9826f; color: #b5543f; }

    .region-edit-help {
      margin-top: -6px;
      margin-bottom: 12px;
      color: var(--ink-soft);
      animation: fadeIn 0.3s ease;
    }

    @keyframes fadeIn {
      from { opacity: 0; transform: translateY(-4px); }
      to { opacity: 1; transform: translateY(0); }
    }

    .print-palette-chips {
      display: flex;
      flex-wrap: wrap;
      gap: 10px;
      margin-top: 8px;
    }

    /* The print colours are the controls: same swatch look as the curated palette. */
    .print-palette-chip {
      width: 42px;
      height: 42px;
      padding: 0;
      border-radius: 50%;
      border: 4px solid white;
      box-shadow: 0 0 0 2px var(--cream-deep);
      cursor: pointer;
    }

    .print-palette-chip:hover,
    .print-palette-chip:focus-visible {
      box-shadow: 0 0 0 2px var(--cream-deep), 0 0 0 4px var(--sage-strong);
    }

    .print-palette-help {
      margin: 8px 0 4px;
    }

    .color-region-rows[hidden] {
      display: none;
    }

    .print-palette-message {
      margin: 0 0 10px;
      font-size: 13px;
      color: #b2530f;
    }

    .print-palette-message[hidden] {
      display: none;
    }

    .color-palette-popover {
      position: fixed;
      z-index: 60;
      width: 232px;
      background: white;
      border: 2px solid var(--sage-strong);
      border-radius: 14px;
      padding: 12px;
      box-shadow: 0 10px 30px rgba(58, 47, 40, 0.25);
    }

    .color-palette-family {
      margin-bottom: 8px;
    }

    .color-palette-family-name {
      font-size: 11px;
      color: var(--ink-soft);
      margin: 0 0 4px;
    }

    .color-palette-swatches {
      display: flex;
      flex-wrap: wrap;
      gap: 6px;
    }

    .color-palette-swatch {
      width: 24px;
      height: 24px;
      border-radius: 50%;
      border: 2px solid white;
      box-shadow: 0 0 0 1px var(--cream-deep);
      cursor: pointer;
      padding: 0;
    }

    .color-palette-swatch:hover,
    .color-palette-swatch.active {
      box-shadow: 0 0 0 1px var(--cream-deep), 0 0 0 3px var(--sage-strong);
      transform: scale(1.08);
    }

    .color-palette-custom {
      display: flex;
      align-items: center;
      gap: 8px;
      margin-top: 4px;
      padding-top: 8px;
      border-top: 1px solid var(--cream-deep);
      font-size: 12px;
      color: var(--ink-soft);
    }

    .color-palette-custom input[type="color"] {
      width: 32px;
      height: 32px;
      padding: 0;
      border: none;
      border-radius: 50%;
      cursor: pointer;
    }

    /* Always-visible HOUSING color grid: same swatch look as the TOP
       popover (.color-palette-swatch), just laid out inline and compact
       so it doesn't grow the left panel. */
    .housing-color-grid {
      display: flex;
      flex-wrap: wrap;
      gap: 6px;
      max-width: 260px;
    }

    .housing-color-grid .housing-color-custom-input {
      border: 2px solid white;
    }

    /* Name Clicker's colour row, exactly: full-width wrap, 10px gap, 42px
       swatches (see .color-row / .color-button), so the same 17 colours sit
       in the same order and rows instead of a narrow 5-wide block. */
    #clickerPanel .housing-color-grid {
      gap: 10px;
      max-width: none;
    }

    #clickerPanel .housing-color-grid .color-palette-swatch {
      width: 42px;
      height: 42px;
    }

    /* The custom colour cell renders as a round swatch like its neighbours. */
    #clickerPanel .housing-color-grid .housing-color-custom-input {
      border: 4px solid white;
      background: white;
    }
    #clickerPanel .housing-color-grid .housing-color-custom-input::-webkit-color-swatch-wrapper { padding: 0; }
    #clickerPanel .housing-color-grid .housing-color-custom-input::-webkit-color-swatch { border: none; border-radius: 50%; }
    #clickerPanel .housing-color-grid .housing-color-custom-input::-moz-color-swatch { border: none; border-radius: 50%; }

    /* =========================================
       Clicker optional keychain loop (HOUSING only).
       ========================================= */

    .keychain-loop-header {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 12px;
    }

    .keychain-loop-rotate-button.loop-reset-button { width: auto; padding: 0 12px; font-size: 14px; }
    #nameLoopField[hidden] { display: none; }
    /* The reset drops to its own line on narrow phones instead of overflowing. */
    .keychain-loop-rotate-row:has(.loop-reset-button) { flex-wrap: wrap; row-gap: 8px; }
    #nameLoopStatus:empty,
    #clickerKeychainLoopStatus:empty,
    #clickerSendDesignStatus:empty,
    #clickerLoadDesignStatus:empty {
      display: none;
    }

    .keychain-loop-header label {
      margin-bottom: 0;
    }

    .keychain-loop-onoff-button {
      width: 84px;
      height: 40px;
      flex-shrink: 0;
      font-size: 14px;
    }

    .keychain-loop-rotate-row {
      display: flex;
      align-items: center;
      justify-content: center;
      gap: 14px;
    }

    .keychain-loop-rotate-button {
      width: 48px;
      height: 48px;
      flex-shrink: 0;
      font-size: 20px;
      padding: 0;
    }

    .keychain-loop-angle {
      min-width: 48px;
      text-align: center;
      font-family: var(--font-display);
      font-size: 16px;
      color: var(--ink);
    }

    #photoKeychainViewer3D, #photoKeycapViewer3D, #textKeycapViewer3D {
      position: relative;
      width: 100%;
      height: 360px;
      border-radius: 16px;
      overflow: hidden;
    }


    #photoKeychainViewer3D canvas, #photoKeycapViewer3D canvas, #textKeycapViewer3D canvas { display: block; max-width: 100%; }
    #photoKeychainPanel .preview-title { flex-wrap: wrap; gap: 10px; }
    #photoKeychainLoopStatus:empty, #photoKeychainStatus:empty, #photoKeycapStatus:empty { display: none; }

    /* Keycap tab: two custom designs, one chosen per keycap (text OR photo). */
    .keycap-mode-picker { max-width: 760px; margin: 0 auto 16px; }
    .keycap-intro-title { margin: 0; text-align: center; }
    .keycap-intro-sub { margin: 2px 0 12px; text-align: center; }
    .keycap-mode-question { margin: 0 0 8px; text-align: center; font-weight: 700; }
    .keycap-mode-switch { display: flex; gap: 10px; }
    [data-keycap-mode-section][hidden] { display: none; }
    .keycap-mode-switch button { flex: 1; min-width: 0; display: flex; flex-direction: column; align-items: center; gap: 6px; padding: 10px; border: 2px solid var(--cream-deep); border-radius: 16px; background: white; color: inherit; font: inherit; cursor: pointer; }
    .keycap-mode-switch button[aria-checked="true"] { background: var(--cream-deep); border-color: currentColor; font-weight: 700; }
    .keycap-mode-image { display: block; width: 100%; max-width: 160px; height: auto; aspect-ratio: 1; object-fit: contain; border-radius: 12px; background: #f7f7f7; }
    .keycap-mode-name { line-height: 1.3; text-align: center; }
    .keycap-mode-from { font-size: 0.85em; font-weight: 400; opacity: 0.8; }
    .keycap-price-note { margin: 4px 0 0; font-size: 0.85em; line-height: 1.4; text-align: center; }
    .keycap-price-bulk { opacity: 0.75; }
    #textKeycapStatus:empty { display: none; }
    .keycap-fit-value { margin: 0; font-weight: 700; }
    .keycap-text-message { position: absolute; left: 12px; right: 12px; top: 12px; z-index: 2; margin: 0; padding: 10px 12px; border-radius: 12px; background: rgba(255, 255, 255, 0.92); text-align: center; line-height: 1.5; }
    .keycap-text-message.is-error { background: #fff1f1; color: #b42318; font-weight: 700; }
    .keycap-text-message[hidden] { display: none; }
    #textKeycapInput { width: 100%; }
    /* Photo colour guidance, shared by the photo workflows (Photo Keycap, Photo Keychain, Clicker จากรูป). */
    .photo-preview-tip { margin: 0 0 10px; padding: 8px 12px; border-radius: 12px; background: var(--cream-deep); line-height: 1.5; text-align: center; }
    .photo-preview-tip strong { font-weight: 800; }
    .photo-tap-pill { position: absolute; left: 50%; bottom: 12px; z-index: 2; transform: translateX(-50%); margin: 0; padding: 5px 12px; border-radius: 999px; background: rgba(255, 255, 255, 0.92); box-shadow: 0 1px 4px rgba(0, 0, 0, 0.12); font-size: 0.85em; line-height: 1.4; white-space: nowrap; pointer-events: none; }
    .photo-tap-pill[hidden] { display: none; }
    /* The one preview-interaction hint for draggable text / ไอคอนตกแต่ง (text-on-base.js), styled as the photo tap pill. */
    .preview-hint-pill { white-space: normal; max-width: calc(100% - 24px); text-align: center; }
    #nameClickerViewer { position: relative; }
    .text-dimensions:empty { display: none; }
    /* The print colour a tap on the preview picked (print-palette.js revealPrintColorChip). */
    .print-palette-chip.print-palette-chip--picked { box-shadow: 0 0 0 2px var(--cream-deep), 0 0 0 5px var(--sage-strong); animation: print-chip-picked 0.6s ease-out 2; }
    @keyframes print-chip-picked { 50% { transform: scale(1.15); } }
    @media (prefers-reduced-motion: reduce) { .print-palette-chip.print-palette-chip--picked { animation: none; } }
    .keycap-size-note { margin: 10px 0 0; font-size: 0.85em; line-height: 1.5; opacity: 0.85; text-align: center; }
    .keycap-adjust-note { margin: 6px 0 0; font-size: 0.9em; line-height: 1.4; }
    .keycap-adjust-note[hidden], .keycap-split-suggestion[hidden], .keycap-icon-side[hidden] { display: none; }
    .keycap-split-suggestion { margin-top: 8px; width: 100%; }
    .text-center-buttons { display: flex; flex-wrap: wrap; gap: 8px; }
    .text-center-buttons .toggle-button { flex: 1 1 140px; }
    .text-center-buttons .toggle-button[hidden] { display: none; }
    /* ไอคอนตกแต่ง picker (decoration-picker.js), shared by Name Keychain and Text Keycap. */
    .decoration-picker-native, .sr-only { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); border: 0; opacity: 0; pointer-events: none; }
    .decoration-picker { display: flex; flex-wrap: wrap; gap: 6px; margin: 4px 0 8px; }
    .decoration-choice { width: 44px; height: 44px; padding: 6px; border: 2px solid var(--cream-deep); border-radius: 12px; background: white; color: inherit; font: inherit; font-size: 0.85em; cursor: pointer; }
    .decoration-choice img { display: block; width: 100%; height: 100%; object-fit: contain; }
    /* A settings card left with nothing customer-facing is not shown. */
    .config-card[data-ws-group="detail"]:not(:has(.field:not([hidden]) :is(input:not([type=hidden]), button, select))) { display: none; }
    .decoration-clear-hint { margin: 0 0 4px; font-size: 0.82em; opacity: 0.75; }
    .decoration-clear-hint[hidden], .decoration-controls[hidden] { display: none; }
    /* Picker, then its own groups: สีไอคอนตกแต่ง, size, rotation — clearly apart from the thumbnails. */
    .decoration-controls { margin-top: 14px; padding-top: 12px; border-top: 1px dashed var(--cream-deep); }
    .decoration-help { margin: 0 0 10px; font-size: 0.88em; line-height: 1.4; opacity: 0.85; }
    .decoration-group + .decoration-group { margin-top: 14px; }
    .decoration-group > label { display: block; margin-bottom: 6px; }
    .decoration-choice[aria-pressed="true"] { border-color: currentColor; background: var(--cream-deep); }
    .decoration-choice:disabled { opacity: 0.45; cursor: not-allowed; }
    #textKeycapIconControls[hidden] { display: none; }
    .keycap-icon-side { display: flex; gap: 6px; margin-top: 8px; }
    .keycap-icon-side button { flex: 1; }
    .keycap-icon-side button[aria-pressed="true"] { font-weight: 700; background: var(--cream-deep); }
    .keycap-blank-color-row { display: flex; align-items: center; gap: 10px; }
    .keycap-blank-color-row .print-palette-chip { flex: 0 0 auto; }

    /* Preserve the native, full-size dropdown indicator in the narrower
       three-column control panel. */
    #nameClickerShape {
      appearance: auto;
      -webkit-appearance: menulist;
      padding-right: 38px;
      background-color: white;
    }

    /* =========================================
       EN-mode typography experiment — Name Keychain only.
       CSS-only, scoped to #nameKeychainPanel so Clicker (which
       shares .field/.order-button/[data-name-mode]/etc.) is
       never affected. The playful accent/display font stays on
       the header tagline, panel.title, and panel.previewTitle
       in both languages — everything else functional here
       switches to a system sans stack for EN legibility.
       ========================================= */

    html[lang="en"] #nameKeychainPanel .field label,
    html[lang="en"] #nameKeychainPanel #baseStyleSelect,
    html[lang="en"] #nameKeychainPanel [data-name-mode],
    html[lang="en"] #nameKeychainPanel .order-button,
    html[lang="en"] #nameKeychainPanel .name-size-value span:first-child,
    html[lang="en"] #nameKeychainPanel .name-size-value span:last-child,
    html[lang="en"] #nameKeychainPanel .outline-value span:first-child,
    html[lang="en"] #nameKeychainPanel .outline-value span:last-child,
    html[lang="en"] #nameKeychainPanel .name-clicker-help {
      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    }

    /* =========================================
       Customer workspace — Name Keychain, Photo Keychain, Name Clicker and
       Clicker จากรูป only (.studio-workspace; Letter Beads keeps the plain
       three-column layout). Desktop: the preview is the stable canvas on the
       left and the settings panel scrolls on its own; phones: preview first,
       then the grouped settings, in normal page flow.
       ========================================= */

    .studio-workspace > .workspace-settings { min-width: 0; }

    .config-card {
      position: relative;
      margin-bottom: 16px;
      padding: 18px 18px 2px;
      border: 2px solid var(--cream-deep);
      border-radius: 20px;
      background: #fff;
    }

    .config-card:last-child { margin-bottom: 0; }

    .config-card-title {
      display: flex;
      align-items: center;
      gap: 8px;
      margin: 0 0 14px;
      font-family: var(--font-display);
      font-size: 17px;
      font-weight: normal;
      color: var(--sage-deep);
    }

    .config-card-title::before {
      content: "";
      flex: 0 0 auto;
      width: 10px;
      height: 10px;
      border-radius: 50%;
      background: var(--sage-strong);
    }

    .config-card[data-ws-group="name"] .config-card-title::before,
    .config-card[data-ws-group="image"] .config-card-title::before { background: var(--yellow-deep); }
    .config-card[data-ws-group="shape"] .config-card-title::before,
    .config-card[data-ws-group="detail"] .config-card-title::before { background: var(--blue-muted); }
    .config-card[data-ws-group="loop"] .config-card-title::before,
    .config-card[data-ws-group="finish"] .config-card-title::before { background: var(--yellow); }

    .config-card .field { margin-bottom: 22px; }

    .config-card .ws-color-note { margin: -8px 0 18px; }

    .config-card-order {
      padding-bottom: 18px;
      border-color: var(--sage);
      background: linear-gradient(180deg, #fffdf6, #fff);
    }

    .ws-summary {
      display: grid;
      grid-template-columns: auto minmax(0, 1fr);
      gap: 4px 12px;
      margin-bottom: 4px;
      padding: 10px 12px;
      border-radius: 12px;
      background: var(--cream);
      font-size: 14px;
      line-height: 1.5;
    }

    .ws-summary:empty { display: none; }
    .ws-summary-label { color: var(--ink-soft); white-space: nowrap; }
    .ws-summary-value { min-width: 0; color: var(--ink); overflow-wrap: anywhere; }

    .ws-summary-dot {
      display: inline-block;
      width: 12px;
      height: 12px;
      margin-right: 4px;
      border: 1px solid rgba(58, 47, 40, 0.25);
      border-radius: 50%;
      vertical-align: -1px;
    }

    .config-card-order .name-price-bar { margin-top: 10px; }
    .config-card-order .ws-send-help { margin: 10px 0 0; }

    .ws-actions {
      display: grid;
      grid-template-columns: 1fr 1fr;
      gap: 10px;
      margin-top: 14px;
    }

    .ws-action {
      min-height: 44px;
      padding: 8px 10px;
      border: 2px solid var(--ink);
      border-radius: 14px;
      background: white;
      color: var(--ink);
      font-family: var(--font-display);
      font-size: 15px;
      line-height: 1.25;
      cursor: pointer;
      box-shadow: 0 3px 0 rgba(58, 47, 40, 0.18);
    }

    .ws-action:disabled {
      opacity: 0.45;
      cursor: default;
      box-shadow: none;
    }

    .ws-reset {
      display: block;
      margin: 14px auto 0;
      padding: 4px 8px;
      border: 0;
      background: none;
      color: var(--ink-soft);
      font: inherit;
      font-size: 14px;
      text-decoration: underline;
      text-underline-offset: 3px;
      cursor: pointer;
    }

    @media (min-width: 1024px) {
      .studio.studio-three-column.studio-workspace {
        grid-template-columns: minmax(0, 1.4fr) minmax(360px, 1fr);
        grid-template-areas: "preview settings";
        align-items: start;
      }

      /* Name Keychain's preview card sets the size for every customer tab: the
         preview is one viewport-tall card (--ws-preview-h), and the settings
         column is exactly as tall, beside it, scrolling its own cards inside —
         so both columns always end at the same line. */
      .studio-workspace {
        --ws-preview-h: max(560px, min(calc(100vh - 32px), 900px));
      }

      .studio-workspace > .preview-panel {
        grid-area: preview;
        height: var(--ws-preview-h);
      }

      .studio-workspace > .workspace-settings {
        grid-area: settings;
        display: flex;
        flex-direction: column;
        height: var(--ws-preview-h);
      }

      /* The scrollbar sits in the panel's own padding, not over the cards. */
      .studio-workspace > .workspace-settings > .workspace-settings-scroll {
        flex: 1 1 auto;
        min-height: 0;
        overflow-y: auto;
        overscroll-behavior: contain;
        margin-right: -18px;
        padding-right: 0;
      }

      /* The render frame takes the height the card has left. min-height: 0 keeps a
         canvas sized for a taller window from holding the frame open when it shrinks.
         viewer.js and clicker-viewer.js write an inline height and size their renderer
         from clientHeight, so !important is what lets these win. */
      .studio-workspace > .preview-panel > .preview-stage {
        flex: 1 1 auto;
        min-height: 0;
      }

      /* Name Keychain's viewer re-measures only on window resize, so its height is
         tied to the viewport alone (card height minus its title, margins and hint),
         never to content that could shift it without a resize event. */
      .studio-workspace #threeViewer {
        height: calc(var(--ws-preview-h) - 162px) !important;
        min-height: 0;
        overflow: hidden;
      }

      .studio-workspace #nameClickerViewer { height: 100%; }

      /* Both image previews fill the card's remaining height (zero basis: the card's
         height must not depend on the canvas it sizes). Their camera fit follows
         the frame's aspect (clicker/preview-staging.js), so any frame shape works. */
      .studio-workspace #clickerViewer3D,
      .studio-workspace #photoKeychainViewer3D,
      .studio-workspace #photoKeycapViewer3D,
      .studio-workspace #textKeycapViewer3D {
        flex: 1 1 0;
        height: auto !important;
        min-height: 0;
      }
    }

    @media (max-width: 1023px) {
      .studio.studio-workspace { grid-template-columns: minmax(0, 1fr); }
      .studio-workspace > .preview-panel { 
        order: -1; 
        position: sticky;
        top: 0;
        z-index: 100;
        transition: padding 0.3s ease, min-height 0.3s ease;
      }
      .studio-workspace > .preview-panel.is-compact {
        padding: 10px 16px;
        min-height: 120px;
        box-shadow: 0 4px 12px rgba(0,0,0,0.1);
      }
      .studio-workspace > .preview-panel.is-compact .preview-title {
        display: none;
      }
      .studio-workspace > .preview-panel.is-compact .preview-stage,
      .studio-workspace > .preview-panel.is-compact .product-preview-frame {
        margin-top: 0;
        min-height: 100px;
      }

      /* No panel chrome around the cards on phones: each group card reads on its own. */
      .studio-workspace > .workspace-settings {
        padding: 0;
        border: 0;
        background: none;
        box-shadow: none;
      }

      .studio-workspace > .workspace-settings::before { display: none; }
      .studio-workspace > .workspace-settings h2 { margin: 6px 4px 16px; }
    }

    /* Phones: Name Keychain's preview is as compact as the other products'
       (Photo Keychain / Clicker จากรูป frames are 360 px). viewer.js writes an
       inline 430 px and sizes its renderer from clientHeight, so !important
       wins here, as in the desktop rule above. */
    @media (max-width: 600px) {
      .studio-workspace #threeViewer { height: 360px !important; }
      #nameKeychainPanel .preview-stage { min-height: 0; }
    }

    @media (max-width: 480px) {
      .config-card { padding: 16px 14px 2px; }
      .config-card-order { padding-bottom: 16px; }
    }

    /* ---------- Workspace polish: choice buttons, size readouts, price, scale toggle ---------- */

    .ws-choices {
      display: grid;
      gap: 8px;
      margin-top: 4px;
    }

    .ws-choices--shape { grid-template-columns: repeat(auto-fill, minmax(84px, 1fr)); }
    .ws-choices--size { grid-template-columns: repeat(5, minmax(0, 1fr)); }

    .ws-choice {
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      gap: 4px;
      min-width: 0;
      min-height: 44px;
      padding: 8px 4px;
      border: 2px solid var(--cream-deep);
      border-radius: 14px;
      background: #fff;
      color: var(--ink);
      font-family: var(--font-display);
      font-size: 14px;
      line-height: 1.2;
      cursor: pointer;
      transition: border-color 0.12s ease, background-color 0.12s ease;
    }

    .ws-choice:hover { border-color: var(--sage); }

    .ws-choice.is-selected {
      border-color: var(--sage-strong);
      background: #f1f6ec;
      box-shadow: 0 0 0 2px rgba(155, 184, 134, 0.35);
    }

    .ws-choice-label {
      max-width: 100%;
      overflow-wrap: anywhere;
      text-align: center;
    }

    .ws-choices--size .ws-choice { font-family: Arial, sans-serif; font-weight: bold; font-size: 14px; }

    /* Photo Keychain / Clicker จากรูป sizes: 3.5–6.0 cm as two rows of three,
       the larger sizes behind a disclosure button (customer-workspace.js). */
    :is(#photoKeychainPanel, #keycapPanel, #clickerPanel) .ws-choices--size { grid-template-columns: repeat(3, minmax(0, 1fr)); }
    :is(#photoKeychainPanel, #keycapPanel, #clickerPanel) .ws-choices--size.ws-choices--more { grid-template-columns: repeat(4, minmax(0, 1fr)); margin-top: 8px; }

    .ws-more-toggle {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 8px;
      width: 100%;
      margin-top: 8px;
      padding: 9px 14px;
      border: 2px dashed var(--cream-deep);
      border-radius: 14px;
      background: #fff;
      color: var(--ink);
      font-family: Arial, sans-serif;
      font-size: 14px;
      font-weight: bold;
      cursor: pointer;
    }

    /* `display: grid/flex` above would otherwise beat the browser's own
       [hidden] { display: none }, leaving a collapsed group on screen. */
    .ws-choices[hidden],
    .ws-more-toggle[hidden] { display: none; }

    .ws-more-toggle:hover { border-color: var(--sage); }
    .ws-more-caret { transition: transform 0.15s ease; }
    .ws-more-toggle[aria-expanded="true"] .ws-more-caret { transform: rotate(180deg); }

    .ws-choice-icon {
      display: block;
      width: 34px;
      height: 26px;
      color: var(--sage-deep);
    }

    .ws-choice-icon svg {
      width: 100%;
      height: 100%;
      fill: none;
      stroke: currentColor;
      stroke-width: 2.2;
      stroke-linejoin: round;
    }

    /* Real shape artwork (assets/*.svg) used as a mask, tinted like the outline icons. */
    .ws-choice-icon--asset {
      background: currentColor;
      -webkit-mask: var(--ws-shape) center / contain no-repeat;
      mask: var(--ws-shape) center / contain no-repeat;
    }

    .ws-choice.is-selected .ws-choice-icon { color: var(--ink); }

    .ws-readouts { margin-top: 12px; }

    .ws-readout {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 6px 12px;
      margin-top: 6px;
      color: var(--ink-soft);
      font-size: 14px;
    }

    .ws-readout .ws-value-pill { flex: 0 0 auto; }

    /* Price closes the order card as a summary, not a control. */
    .config-card-order .name-price-bar {
      align-items: center;
      margin: 12px 0 2px;
      padding: 12px 16px;
    }

    .config-card-order .name-price-bar > span:first-child { font-size: 16px; }
    /* One price size for every product (Name Clicker's 18px/800). */
    .config-card-order :is(#nameProductPrice, #nameClickerPrice, #photoKeychainPrice, #clickerPrice) {
      font-size: 18px; font-weight: 800; line-height: 1.4; white-space: nowrap;
    }

    /* Preview tool icons (scale ruler, sound): one line-icon style, 20x20 at
       1.6 stroke in the text colour, like the colour-note icon. */
    .ws-tool-icon { display: inline-block; width: 1.15em; height: 1.15em; vertical-align: -0.22em; }
    .ws-scale-icon { display: inline-flex; }
    [aria-pressed="true"] > span > .ws-sound-off,
    [aria-pressed="false"] > span > .ws-sound-on { display: none; }


    @media (max-width: 480px) {
      .ws-choices--size { grid-template-columns: repeat(3, minmax(0, 1fr)); }
      :is(#photoKeychainPanel, #keycapPanel, #clickerPanel) .ws-choices--size.ws-choices--more { grid-template-columns: repeat(3, minmax(0, 1fr)); }
      .ws-choices--shape { grid-template-columns: repeat(auto-fill, minmax(76px, 1fr)); }
      .ws-readout { flex-wrap: wrap; }
    }

    /* Name Keychain: breathing room between the shape cards and the thickness slider under them. */
    #nameKeychainPanel .ws-choices + .outline-control { margin-top: 18px; }

    /* Helper / explanatory text in the four customer configurators: one treatment,
       matching the slider endpoint labels (บาง / หนา). Notes about a whole control
       or group are centred under it; hints for a single input stay under that input. */
    :is(#nameKeychainPanel, #photoKeychainPanel, #keycapPanel, #nameClickerPanel, #clickerPanel) :is(.name-clicker-help, .clicker-color-region-empty) {
      font-family: var(--font-display);
      font-size: 13px;
      font-weight: normal;
      line-height: 1.6;
      color: var(--ink-soft);
    }

    :is(#nameKeychainPanel, #photoKeychainPanel, #keycapPanel, #nameClickerPanel, #clickerPanel) .ws-help-center { text-align: center; }

    /* "หรือเลือกรูปตัวอย่าง" (sample-images.js) — photo keychain + Clicker จากรูป.
       Second step of "1. upload": a real sub-heading (field-label style, one
       size below "อัปโหลดรูป") and five named tiles filling the settings
       column, so it reads as "upload yours OR tap one of these". Tiles are
       flat — no floating shadow — and the artwork gets no shadow/glow/filter.
       The arrow points down at the tiles it introduces. */
    .sample-picker { margin-top: 16px; padding-top: 14px; border-top: 1px dashed var(--cream-deep); }
    .sample-picker[hidden] { display: none; }
    .sample-picker-label {
      display: flex; align-items: center; gap: 6px; margin: 0 0 10px;
      font-family: var(--font-display); font-size: 16px; line-height: 1.4; letter-spacing: 0.3px; color: var(--sage-deep);
    }
    .sample-picker-arrow { flex: none; width: 14px; height: 14px; }
    .sample-picker-list { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 8px; max-width: 520px; }
    .sample-picker-item {
      display: flex; flex-direction: column; align-items: center; gap: 4px; min-width: 0; padding: 8px 4px 6px;
      border: 1.5px solid var(--cream-deep); border-radius: 14px; background: white; color: var(--ink-soft);
      font: inherit; box-shadow: none; cursor: pointer; transition: border-color .15s, background-color .15s;
    }
    .sample-picker-item img { display: block; width: 100%; height: auto; aspect-ratio: 1; object-fit: contain; filter: none; pointer-events: none; }
    .sample-picker-name {
      max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
      font-family: var(--font-display); font-size: 12px; line-height: 1.3;
    }
    .sample-picker-item:hover { border-color: var(--sage-strong); }
    .sample-picker-item:focus-visible { outline: 2px solid var(--sage-deep); outline-offset: 2px; }
    .sample-picker-item[aria-pressed="true"] { border-color: var(--sage-deep); background: #f2f6ec; color: var(--sage-deep); box-shadow: inset 0 0 0 1px var(--sage-deep); }
    /* Phones: three per row (3 + 2 centred) keeps each tile ~88 px instead of
       squeezing five into ~55 px. */
    @media (max-width: 600px) {
      .sample-picker-list { 
        display: grid; 
        grid-template-columns: repeat(5, minmax(0, 1fr)); 
        gap: 6px; 
      }
      .sample-picker-item { 
        padding: 4px 2px 4px; 
      }
      .sample-picker-name {
        font-size: 10px;
      }
    }
