  :root{
    --bg:#ededed;
    --fg:#000000;
    --muted:rgba(0,0,0,0.5);
    --faint:rgba(0,0,0,0.15);
    --hair:2px;
  }
  /* Dark mode inverts the whole UI chrome (toolbar, buttons, popovers,
     text) via the shared --bg/--fg/--muted/--faint variables. The actual
     paper — the #bg CANVAS element the drawing lives on — is always
     filled solid white in JS regardless of theme, so it stays a bright
     white "drawing area" floating on the dark viewport; --faint (the
     grid drawn on #viewport, i.e. the background OUTSIDE that paper) is
     bumped a bit brighter than its light-mode alpha so the grid reads
     clearly against black. */
  body.dark{
    --bg:#000000;
    --fg:#ffffff;
    --muted:rgba(255,255,255,0.5);
    --faint:rgba(255,255,255,0.2);
  }
  *{box-sizing:border-box;}
  html,body{height:100%;}
  body{
    margin:0;
    background:var(--bg);
    color:var(--fg);
    font-family:'VT323', monospace;
    overflow:hidden;
    -webkit-user-select:none;
    user-select:none;
  }
  .px{ font-family:'Press Start 2P', monospace; }

  #app{
    position:relative;
    width:100%;
    height:100vh;
    display:flex;
    flex-direction:column;
  }

  /* ---------- main row: toolbar + viewport ---------- */
  #main{
    flex:1 1 auto;
    display:flex;
    min-height:0;
  }

  #toolbar{
    flex:0 0 168px;
    border-right:var(--hair) solid var(--fg);
    display:flex;
    flex-direction:column;
    padding:14px 10px;
    gap:8px;
    overflow-y:auto;
  }
  #toolbar > *{ flex-shrink:0; }
  #toolbarLogo{
    display:block;
    width:100%;
    image-rendering:pixelated;
  }
  #toolbarScrollHint{
    font-size:20px;
    letter-spacing:0.5px;
    line-height:1.3;
    text-align:center;
    color:var(--muted);
  }
  .tool-btn{
    font-family:'Press Start 2P', monospace;
    font-size:10px;
    line-height:1.6;
    text-align:left;
    background:var(--bg);
    color:var(--fg);
    border:var(--hair) solid var(--fg);
    padding:10px 8px;
    cursor:pointer;
    display:flex;
    align-items:center;
    gap:10px;
    transition:background .05s, color .05s;
  }
  .tool-btn .key{
    display:inline-flex;
    align-items:center;
    justify-content:center;
    width:22px;
    height:22px;
    border:var(--hair) solid var(--fg);
    flex:0 0 auto;
  }
  .tool-btn.active{
    background:var(--fg);
    color:var(--bg);
  }
  .tool-btn.active .key{ border-color:var(--bg); }
  /* Held past TOOL_HOLD_MS (see toolKeyPressed) rather than activated
     with a single press/click — a fixed blue rather than var(--fg) so
     it reads the same in light and dark mode, distinguishing "still
     held down, will deactivate on release" from the normal black
     "activated, stays on until pressed again" state. */
  .tool-btn.active.held-active{
    background:#001B94;
    color:#ffffff;
  }
  .tool-btn.active.held-active .key{ border-color:#ffffff; }
  .tool-btn:focus-visible{ outline:2px dashed var(--fg); outline-offset:2px; }

  #toolbar .sep{
    border-top:1px dashed var(--faint);
    margin:6px 0;
  }
  #toolbar .group-label{
    font-size:11px;
    letter-spacing:1px;
    color:var(--muted);
  }
  .mini-row{ display:flex; gap:6px; }
  #toolbarInfoBtn{
    align-self:center;
    width:100px;
  }
  .mini-btn{
    font-family:'Press Start 2P', monospace;
    font-size:10px;
    background:var(--bg);
    border:var(--hair) solid var(--fg);
    color:var(--fg);
    padding:8px 0;
    flex:1;
    cursor:pointer;
  }
  .mini-btn:active{ background:var(--fg); color:var(--bg); }
  .import-color-btn .shift-key{ font-size:16px; }

  /* Hidden by default — only shown (as display:contents, so its sep,
     label and hint act as ordinary direct children of #toolbar and
     pick up the same flex gap as every other section) while the Area
     tool is actually in use. */
  #fillSection{ display:none; }
  #fillSection.show{ display:contents; }
  /* display:contents re-parents these into #toolbar's flex layout for
     sizing purposes, but the "#toolbar > *" flex-shrink:0 rule above
     is a DOM child combinator and doesn't reach through it (its real
     DOM parent is #fillSection, not #toolbar) — so it needs repeating
     here, or the column shrinks these below their content height and
     the overflowing text visually overlaps the section below it. */
  #fillSection > *{ flex-shrink:0; }

  #fillHint{
    font-size:16px;
    line-height:1.35;
    color:var(--muted);
    min-height:120px;
  }
  #fillHint b{ color:var(--fg); font-weight:normal; }

  #textMsg{
    font-size:15px;
    color:var(--muted);
    min-height:20px;
  }
  #exportMsg, #importMsg, #recordMsg, #projectMsg{
    font-size:15px;
    color:var(--muted);
  }
  #exportMsg:empty, #importMsg:empty, #recordMsg:empty, #projectMsg:empty{ display:none; }
  /* Recording is a toggled state (like dark mode), not a momentary
     press, so it gets the same "selected" filled look, plus a slow
     pulse so it's clearly still going even once the initial click
     feedback has faded. */
  #recordBtn.selected{
    background:var(--fg); color:var(--bg);
    animation: record-pulse 1.4s ease-in-out infinite;
  }
  @keyframes record-pulse{
    0%, 100% { opacity:1; }
    50% { opacity:0.55; }
  }

  #textInput, #textFontSelect{
    font-family:'VT323', monospace;
    font-size:16px;
    background:var(--bg);
    color:var(--fg);
    border:var(--hair) solid var(--fg);
    padding:6px;
    width:100%;
    box-sizing:border-box;
  }
  #textInput{ resize:vertical; }

  .mini-hint{
    font-size:13px;
    color:var(--muted);
  }
  .mini-btn.selected{ background:var(--fg); color:var(--bg); }
  .popover .group-label{
    font-size:11px;
    letter-spacing:1px;
    color:var(--muted);
    margin-top:2px;
  }

  /* ---------- viewport ---------- */
  #viewport{
    position:relative;
    flex:1 1 auto;
    overflow:hidden;
    background:
      linear-gradient(var(--faint) 1px, transparent 1px) 0 0/24px 24px,
      linear-gradient(90deg, var(--faint) 1px, transparent 1px) 0 0/24px 24px,
      var(--bg);
    /* #viewport is focused constantly (every click/tap/key action calls
       viewport.focus() so keyboard shortcuts keep working) — without an
       explicit outline it falls back to the browser/OS default focus
       ring, which shows up as a stray yellow/orange frame around the
       canvas on some platforms. Suppress it here instead. */
    outline:none;
  }
  #viewport:focus, #viewport:focus-visible{ outline:none; }
  #camera{
    position:absolute;
    top:0; left:0;
    transform-origin:0 0;
  }
  #bg, #content, #overlay{
    position:absolute;
    top:0; left:0;
    image-rendering:pixelated;
  }
  #overlay{ pointer-events:none; }

  /* ---------- color swatches ---------- */
  .color-btn{
    display:flex;
    align-items:center;
    gap:10px;
    width:100%;
    font-family:'VT323', monospace;
    font-size:16px;
    background:var(--bg);
    color:var(--fg);
    border:var(--hair) solid var(--fg);
    padding:7px 8px;
    cursor:pointer;
  }
  .color-btn .swatch{
    width:18px;
    height:18px;
    border:var(--hair) solid var(--fg);
    flex:0 0 auto;
  }
  .color-btn.active{ background:var(--fg); color:var(--bg); }
  .color-btn.active .swatch{ border-color:var(--bg); }
  .color-btn:focus-visible{ outline:2px dashed var(--fg); outline-offset:2px; }

  /* ---------- status bar ---------- */
  #status{
    flex:0 0 auto;
    border-top:var(--hair) solid var(--fg);
    display:flex;
    align-items:center;
    justify-content:space-between;
    padding:6px 14px;
    font-size:17px;
    gap:16px;
    font-variant-numeric:tabular-nums;
  }
  #legend{
    color:var(--muted);
    white-space:nowrap;
    overflow:hidden;
    text-overflow:ellipsis;
  }
  #readout{ white-space:nowrap; }

  /* ---------- start overlay ---------- */
  #startOverlay{
    position:absolute;
    inset:0;
    background:var(--bg);
    z-index:10;
    display:flex;
    align-items:center;
    justify-content:center;
  }
  #startOverlay.hidden{ display:none; }
  #startPanel{
    border:var(--hair) solid var(--fg);
    padding:28px 30px;
    max-width:420px;
    width:90%;
  }
  #startPanel h1{
    font-family:'Press Start 2P', monospace;
    font-size:15px;
    margin:0 0 6px;
    text-wrap:balance;
  }
  #startPanel p{
    font-size:17px;
    color:var(--muted);
    margin:0 0 20px;
    line-height:1.4;
  }

  /* ---------- info/about overlay ---------- */
  /* Sits above #startOverlay (higher z-index, same full-bleed opaque
     #bg fill) so it's the very first thing shown on every page load —
     the orientation/size picker underneath is fully blocked, both
     visually and from the keyboard (see the pre-start keydown handler),
     until this is dismissed. */
  #infoOverlay{
    position:absolute;
    inset:0;
    background:var(--bg);
    z-index:11;
    display:flex;
    align-items:center;
    justify-content:center;
    padding:20px;
  }
  #infoOverlay.hidden{ display:none; }
  #infoPanel{
    border:var(--hair) solid var(--fg);
    padding:20px 30px;
    max-width:1120px;
    width:100%;
    max-height:92vh;
    overflow-y:auto;
    box-sizing:border-box;
  }
  #infoLogo{
    display:block;
    width:100%;
    max-width:340px;
    margin:0 auto 8px;
    image-rendering:pixelated;
  }
  #infoVersion{
    text-align:center;
    font-family:'Press Start 2P', monospace;
    font-size:11px;
    letter-spacing:1px;
    color:var(--muted);
    margin:0 0 14px;
  }
  #infoText p{
    font-size:16px;
    line-height:1.35;
    color:var(--muted);
    margin:0 0 10px;
  }
  #infoText p.info-name{
    font-family:'Press Start 2P', monospace;
    font-size:13px;
    color:var(--fg);
    letter-spacing:0.5px;
    margin:0 0 6px;
  }
  #infoText p.info-heading{
    font-family:'Press Start 2P', monospace;
    font-size:13px;
    color:var(--fg);
    letter-spacing:0.5px;
    margin:0 0 6px;
  }
  #infoStartBtn{
    display:block;
    width:100%;
  }

  .size-btn{
    display:flex;
    justify-content:space-between;
    align-items:center;
    width:100%;
    font-family:'Press Start 2P', monospace;
    font-size:11px;
    background:var(--bg);
    color:var(--fg);
    border:var(--hair) solid var(--fg);
    padding:12px 14px;
    margin-bottom:8px;
    cursor:pointer;
  }
  .size-btn span.dim{
    font-family:'VT323', monospace;
    font-size:15px;
    color:var(--muted);
  }
  .size-btn:hover, .size-btn:focus-visible{ background:var(--fg); color:var(--bg); }
  .size-btn:hover span.dim, .size-btn:focus-visible span.dim{ color:rgba(255,255,255,0.7); }

  .orient-btn{
    display:flex;
    align-items:center;
    gap:16px;
    width:100%;
    font-family:'Press Start 2P', monospace;
    font-size:12px;
    background:var(--bg);
    color:var(--fg);
    border:var(--hair) solid var(--fg);
    padding:14px;
    margin-bottom:8px;
    cursor:pointer;
  }
  .orient-btn:hover, .orient-btn:focus-visible{ background:var(--fg); color:var(--bg); }
  .shape{ flex:0 0 auto; background:var(--fg); border:var(--hair) solid var(--fg); }
  .orient-btn:hover .shape, .orient-btn:focus-visible .shape{ background:var(--bg); border-color:var(--bg); }
  .shape-square{ width:24px; height:24px; }
  .shape-horizontal{ width:34px; height:22px; }
  .shape-vertical{ width:22px; height:34px; }

  .step{ }
  .step.hidden-step{ display:none; }

  /* ---------- popover panels (confirm dialog, import size picker) ---------- */
  .popover{
    position:absolute;
    left:10px;
    bottom:10px;
    border:var(--hair) solid var(--fg);
    background:var(--bg);
    padding:10px;
    display:none;
    flex-direction:column;
    gap:6px;
    font-size:15px;
    max-width:230px;
    z-index:5;
  }
  .popover.show{ display:flex; }

  ::-webkit-scrollbar{ width:10px; }
  ::-webkit-scrollbar-thumb{ background:var(--fg); }
  ::-webkit-scrollbar-track{ background:var(--bg); }
