Character Designer

Welcome to the world of BAROQUE THEATRE: a place of bold fashion, dramatic storytelling, and absolutely iconic hair.

Today, you get to step into the role of a COSTUME DESIGNER and create your very own Baroque hero!

Whether your character is a daring nobleman, a clever noblewoman, a mischievous courtier, or a mysterious masked stranger… their look is entirely up to you!

Dress for the Party


<style>
:root{
  --panel-w: 360px;
  --gap: 12px;

  --bg: #ffffff;
  --panel-bg: #ffffff;

  --text: #000000;
  --muted: #555555;

  --accent: #c9252d;       /* red */
  --accent-gold: #b39330;  /* gold */

  --border: #000000;       /* ✅ your “all black 2px borders” */
}

*{ box-sizing:border-box; }

body{
  margin:0;
  font-family: Raleway, Montserrat, "Century Gothic", Helvetica, Arial, sans-serif;
  background: var(--bg);
  color: var(--text);
}

/* WP-admin-style header */
header{
  position: sticky;
  top: 32px;                 /* sits below WP admin bar */
  z-index: 50;

  display: grid;
  grid-template-columns: 250px auto auto; /* title | middle | right */
  align-items: center;
  column-gap: 3%;
  row-gap: .25em;

  padding: .5em .75em;
  background: #000;
  color: #fff;

  border-bottom: 2px solid #000; /* crisp edge */
}

/* Title */
header h1{
  margin: 0;
  font-size: larger;
  font-weight: 600;
  letter-spacing: .2px;
  color: #fff;
  width: 30vw;
}

/* Optional slots (if present) */
header .header-mid,
header .header-right{
  display: flex;
  align-items: center;
  gap: .5em;
}

/* If you keep badges anywhere */
header .badge{
  border: 2px solid #fff;
  background: transparent;
  color: #fff;
  font-size: .75rem;
  padding: .15em .6em;
  border-radius: 999px;
  font-weight: 600;
}


/* layout */
.layout{
  display:grid;
  grid-template-columns: var(--panel-w) 1fr;
  gap: var(--gap);
  padding: var(--gap);
  height: calc(100vh - 62px);
padding-top: calc(var(--gap) + 30px); /* add a little extra */
}

/* panel + toolbar */
.panel{
  background: var(--panel-bg);
  border:2px solid var(--border);
  border-radius:14px;
  overflow:hidden;
  display:flex;
  flex-direction:column;
  min-height:0;
}
.panel .toolbar{
  padding:12px;
  border-bottom:2px solid var(--border);
  display:grid;
  gap:12px;
  background:#fff;
}
.panel .category{
  background-color: #000000;
}
.row{
  display:grid;
  grid-template-columns: 1fr 1fr;
  gap:12px;
}

/* global form controls */
button, select{
  border:2px solid var(--border);
  background:#fff;
  color:#000;
  font-weight:700;
  border-radius:10px;
  cursor:pointer;
}

/* top toolbar controls (bigger + centered) */
.panel .toolbar select,
.panel .toolbar button{
  height:52px;
  padding:0 16px;
  font-size:14px;

  display:flex;
  align-items:center;
  justify-content:center;
  text-align:center;
}

/* submit = gold */
.panel .toolbar button.accent{
  background: var(--accent-gold);
  color:#000;
}
.panel .toolbar button.accent:hover{
  background:#a98624;
}

.panel .toolbar button.secondary:hover,
.panel .toolbar select:hover,
button:hover{
  background:#f5f5f5;
}

/* dropdown arrow */
.panel .toolbar select{
  appearance:none;
  -webkit-appearance:none;
  -moz-appearance:none;
  background-image:
    linear-gradient(45deg, transparent 50%, #000 50%),
    linear-gradient(135deg, #000 50%, transparent 50%);
  background-position: calc(100% - 18px) 50%, calc(100% - 12px) 50%;
  background-size:6px 6px;
  background-repeat:no-repeat;
}

.hint{ color: var(--muted); font-size:12px; line-height:1.4; }

/* scroll area */
.scroll{
  overflow:auto;
  padding:10px;
  display:grid;
  gap:10px;
  min-height:0;
  padding-bottom:18px;
}

/* category */
.category{
  display:flex;
  flex-direction:column;
  border:2px solid var(--border);
  background:#000;
  border-radius:12px;
  overflow:hidden;
  height: 228px;          /* ✅ slightly less */
  padding: 8px;           /* ✅ slightly less */
}

/* category head: title + pill same line */
.cat-head{
  flex:0 0 auto;
  display:grid;
  grid-template-columns: 1fr auto;
  grid-template-rows: auto auto;
  gap: 6px 10px;
  padding: 6px 8px;       /* ✅ tightened */
  background:#fff;
  border-radius: 8px;
}
.cat-title{
  font-weight:700;
  font-size:13px;
  letter-spacing:.2px;
}
.pill{
  align-self:center;
  background: var(--accent-gold);
  color:#fff;
  border-radius:999px;
  padding:4px 10px;
  font-size:11px;
  font-weight:700;
  white-space:nowrap;
}

/* action row */
.cat-actions{
  grid-column:1 / 3;
  display:flex;
  gap:6px;
  margin-top:-2px;
}

/* small action buttons */
.icon-btn{
  width:auto;
  min-width:64px;

  height:26px;
  padding:0 8px;

  font-size:11px;
  font-weight:700;

  border-radius:6px;
  border:2px solid var(--accent-gold);
  background:#fff;
  color:#000;

  display:flex;
  align-items:center;
  justify-content:center;
}

/* items grid */
.items{
  flex:1 1 auto;
  min-height:0;
  padding:8px;
  display:grid;
  grid-template-columns: repeat(3, 1fr);
  gap:8px;
  overflow-y:auto;
  overflow-x:hidden;
  scrollbar-gutter:stable;
  background:#000;
}

/* item cards */
.item{
  border:2px solid var(--accent-gold);
  background:#fff;
  border-radius:10px;
  padding: 6px 8px 8px;
  display:grid;
  grid-template-rows: 86px auto;
  gap: 6px;
  min-height: 112px;
}
.item:hover{ border-color: var(--accent); }

.item .mini{
  height:86px;
  border-radius:8px;
  border:2px dashed rgba(0,0,0,.25);
  overflow:hidden;
  background:#fff;
}

/* you removed names, so keep it truly gone */
.item .name{ display:none; }

.item .controls{
  display:grid;
  grid-template-columns: repeat(2, 1fr);
  gap:6px;
}
.item .controls button{
  height:22px;
  min-height:22px;
  padding:0;
  font-size:13px;
  font-weight:800;
  border-radius:8px;
}

/* scrollbar */
.items::-webkit-scrollbar{ width:10px; }
.items::-webkit-scrollbar-thumb{
  background: rgba(255,255,255,.30);
  border-radius:999px;
  border:2px solid rgba(0,0,0,.65);
}
.items::-webkit-scrollbar-track{
  background: rgba(255,255,255,.12);
  border-radius:999px;
}

/* stage */
.stage-wrap{
  background:#fff;
  border:2px solid var(--border);
  border-radius:14px;
  overflow:hidden;
  min-height:0;
  position:relative;
}

.stage-top{
  position:absolute;
  inset:10px 10px auto 10px;
  display:flex;
  gap:10px;
  align-items:center;
  justify-content:space-between;
  pointer-events:none;
  z-index:3;
}
.stage-top .chip{
  pointer-events:none;
  background: rgba(255,255,255,.90);
  border:2px solid var(--border);
  color: var(--text);
  border-radius:999px;
  padding:6px 10px;
  font-size:12px;
}

#stageContainer{ width:100%; height:100%; }

.kbd{
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size:11px;
  padding:2px 6px;
  border-radius:6px;
  border:2px solid #000;
  background:#fff;
  color:#000;
  font-weight:700;
  line-height:1;
}

/* modal (white theme only) */
.modal-backdrop{
  position:fixed;
  inset:0;
  background: rgba(0,0,0,.55);
  display:none;
  align-items:center;
  justify-content:center;
  padding:16px;
  z-index:9999;
}
.modal-backdrop.open{ display:flex; }

.modal{
  width:min(720px, 100%);
  background:#fff;
  border:2px solid var(--border);
  border-radius:14px;
  box-shadow:0 20px 80px rgba(0,0,0,.55);
  overflow:hidden;
  color:#000;
}
.modal-head{
  display:flex;
  align-items:flex-start;
  justify-content:space-between;
  gap:14px;
  padding:14px 14px 10px;
  border-bottom:2px solid var(--border);
  background:#fff;
}
.modal-title{
  font-size:16px;
  font-weight:800;
  margin:0 0 6px 0;
  color: var(--accent);
}
.modal-subtitle{
  font-size:12px;
  color: var(--muted);
  line-height:1.35;
}
.modal-close{
  width:auto;
  padding:8px 10px;
  border-radius:10px;
  border:2px solid var(--border);
  background:#fff;
  color:#000;
  cursor:pointer;
  font-weight:900;
}
.modal-close:hover{ border-color: var(--accent); }

.modal-body{
  padding:14px;
  display:grid;
  gap:12px;
}
.modal-block{
  border:2px solid var(--border);
  background:#fff;
  border-radius:12px;
  padding:12px;
}
.checkrow{
  display:flex;
  gap:10px;
  align-items:flex-start;
  cursor:pointer;
  user-select:none;
  font-size:13px;
  line-height:1.35;
  color:#000;
}
.checkrow input{ margin-top:3px; }

.fields{ margin-top:10px; display:grid; gap:10px; }
.fields.hidden{ display:none; }

.field{ display:grid; gap:6px; }
.field label{ font-size:12px; color: var(--muted); font-weight:700; }
.field input{
  width:100%;
  padding:10px;
  border-radius:10px;
  border:2px solid var(--border);
  background:#fff;
  color:#000;
  outline:none;
}
.field input:focus{ border-color: var(--accent); }

.modal-foot{
  padding:12px 14px 14px;
  border-top:2px solid var(--border);
  background:#fff;
  display:flex;
  justify-content:flex-end;
  gap:10px;
}

/* ITEM CARD: give predictable internal layout */
.item {
  padding: 6px 8px 6px;      /* ⬅️ reduce bottom padding */
  grid-template-rows: 86px 28px; /* ⬅️ preview + fixed controls row */
}

/* CONTROLS ROW */
.item .controls {
  height: 28px;              /* ⬅️ hard limit */
  align-self: stretch;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 6px;
}

/* CONTROL BUTTONS */
.item .controls button {
  height: 100%;              /* ⬅️ fill row exactly */
  min-height: 0;
  padding: 0;

  font-size: 12px;
  font-weight: 800;
  line-height: 1;

  border-radius: 6px;

  display: flex;
  align-items: center;
  justify-content: center;
}
/* ✅ FIX: item buttons spilling out (without changing image sizing) */

.item{
  /* keep your look, just give it enough room */
  padding: 8px 10px 10px 10px !important;
  grid-template-rows: 86px min-content !important; /* mini stays 86px */
  gap: 8px !important;

  /* this is the main fix */
  min-height: 136px !important; /* enough for 86px mini + buttons + padding/borders */
}

.item .controls{
  align-self: end !important;   /* keep controls at bottom of card */
  height: auto !important;
}

.item .controls button{
  height: 28px !important;      /* readable + fits */
  min-height: 28px !important;
  padding: 0 !important;

  display: flex !important;
  align-items: center !important;
  justify-content: center !important;

  line-height: 1 !important;
  font-size: 13px !important;
}
/* ================================
   CARD ELEVATION (MAKE PANELS POP)
   ================================ */

/* Subtle page background so cards lift */
body{
  background: #f7f7f7;
}

/* Unified card look for side panel + canvas */
.panel,
.stage-wrap{
  background: #ffffff !important;

  border: 2px solid #000000;
  border-radius: 14px;

  /* 👇 this is what creates the “pop” */
  box-shadow:
    0 6px 0 rgba(0,0,0,.08),        /* base lift */
    0 14px 28px rgba(0,0,0,.18);    /* depth shadow */
}

/* Lift categories slightly inside the panel */
.category{
  background: #ffffff;
  border: 2px solid #000000;
  box-shadow: 0 4px 10px rgba(0,0,0,.15);
}

/* Items feel tactile, not flat */
.item{
  box-shadow: 0 2px 6px rgba(0,0,0,.15);
}

/* Hover gives a subtle “raise” effect */
.item:hover{
  transform: translateY(-1px);
  box-shadow: 0 4px 10px rgba(0,0,0,.25);
}


@media (max-width: 980px){
  .layout{ grid-template-columns:1fr; height:auto; }
  .panel{ height:55vh; }
  .stage-wrap{ height:70vh; }
  :root{ --panel-w: 100%; }
}

</style>
</head>
<body>
  
<header>
  <h1>Opera Atelier Character Designer</h1>
  <div class="header-mid"></div>
  <div class="header-right"></div>
</header>

  <div class="layout">
    <aside class="panel">
      <div class="toolbar">
        <div class="row">
          <select id="characterSelect" title="Choose character template">
            <option value="char1">Character 1</option>
            <option value="char2">Character 2</option>
          </select>
          <button id="exportBtn" class="accent">Submit</button>
        </div>

        <div class="row">
          <button id="resetBtn" class="secondary danger">Reset Template</button>
          <button id="clearSelectionBtn" class="secondary">Clear Selection</button>
        </div>

        <div class="hint">
          Click an item to <b>add</b> it to the canvas.<br/>Click an on-canvas image to select it.<br/>
          Use the transformer handles to scale/rotate.<br/>
          <span class="kbd">Del</span> deletes selected. <span class="kbd">Esc</span> clears selection.
        </div>
      </div>

      <div id="categories" class="scroll"></div>
    </aside>

    <main class="stage-wrap">
      <div class="stage-top">
        <div id="statusChip" class="chip">Loading images…</div>
        <div class="chip">Tip: Drag to move • Handles to rotate/scale</div>
      </div>
      <div id="stageContainer"></div>
    </main>
  </div>

<!-- Konva (self-hosted) -->
<script src="https://www.operaatelier.com/wp-content/uploads/2026/01/konva.min_.js"></script>

<!-- Your app logic -->
<script src="https://www.operaatelier.com/wp-content/uploads/2026/01/Working2CharCanvasUpload.js" defer></script>


  
  <!-- Submit Modal -->
  <div id="submitModal" class="modal-backdrop" aria-hidden="true">
    <div class="modal" role="dialog" aria-modal="true" aria-labelledby="submitTitle">
      <div class="modal-head">
        <div>
          <div id="submitTitle" class="modal-title">Thank you for creating a design!</div>
          <div class="modal-subtitle">Submit your design for a chance to be included on Opera Atelier's Website!</div>
        </div>
        <button id="submitCloseBtn" class="modal-close" type="button" aria-label="Close">✕</button>
      </div>

      <div class="modal-body">
        <div class="modal-block">
          <label class="checkrow">
            <input id="chkEmailSelf" type="checkbox" />
            <span>Do you want to email a copy of your image to yourself?</span>
          </label>

          <div id="selfFields" class="fields hidden">
            <div class="field">
              <label>Name</label>
              <input id="selfName" type="text" placeholder="Your name" autocomplete="name" />
            </div>
            <div class="field">
              <label>E-mail</label>
              <input id="selfEmail" type="email" placeholder="you@example.com" autocomplete="email" />
            </div>
          </div>
        </div>

        <div class="modal-block">
          <label class="checkrow">
            <input id="chkEmailTeacher" type="checkbox" />
            <span>
              Do you want to send a copy of your image to your teacher? This enters your class into a draw to win a
              workshop from Opera Atelier!
            </span>
          </label>

          <div id="teacherFields" class="fields hidden">
            <div class="field">
              <label>School Name</label>
              <input id="schoolName" type="text" placeholder="School name" />
            </div>
            <div class="field">
              <label>Teacher's Name</label>
              <input id="teacherName" type="text" placeholder="Teacher name" />
            </div>
            <div class="field">
              <label>Teacher's E-mail</label>
              <input id="teacherEmail" type="email" placeholder="teacher@example.com" />
            </div>
          </div>
        </div>

        <div class="modal-block">
          <div class="hint" style="margin:0;">
            When you click Submit below, we'll package your design for emailing (email sending will be added in a future step).
          </div>
        </div>
      </div>

      <div class="modal-foot">
        <button id="submitDesignBtn" class="accent" type="button">Submit</button>
      </div>
    </div>
  </div>

</body>
</html>

What You’ll Do:

Choose from a whole collection of drag-and-drop costume pieces inspired by real 17th-18th century fashion (you may even spot some Opera Atelier original pieces mixed in there as well).

Mix, match, experiment, and build a character that feels ready to leap onto the opera stage!

How It Works

  1. Pick your hero base
    Choose from either of the silhouettes to dress and accessorize.

  2. Explore the costume pieces
    By selecting the layers tab on the right hand side of the screen and clicking the eye icon,
    you’ll be able to find folders with a wide assortment of costume pieces that you can select!

  3. Drag, drop, and layer!
    Stack pieces on top of each other until your character looks perfectly Baroque- or
    perfectly chaotic. (Both are historically accurate.)

Create More

COMING

SOON

CHARACTER HOT SEAT