body {
      background: #111;
      color: #eee;
      font-family: sans-serif;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      height: 100vh;
      margin: 0;
      /* Add padding so the UI is not flush to the device edges */
      padding: 20px;
      box-sizing: border-box;
    }
    /* Responsive entity whose colour and size reflect internal state */
    #entity {
      width: clamp(100px, 35vmin, 200px);
      height: clamp(100px, 35vmin, 200px);
      border-radius: 50%;
      position: relative;
      background: radial-gradient(circle at center, #66f, #339);
      transition: all 0.4s ease;
      box-shadow: 0 0 30px #66f;
      overflow: visible;
      /* Use a CSS variable to control scale from JavaScript. This allows us to
         combine scaling with other animations (e.g. shaking) without
         overwriting the transform property. */
      --scale: 1;
      transform: scale(var(--scale));
    }
    #bubbleLayer {
      position: absolute;
      inset: 0;
      pointer-events: none;
      overflow: visible;
    }
    .ego-animation-character {
      position: fixed;
      left: 50%;
      top: 18vh;
      z-index: 75;
      width: clamp(72px, 18vw, 120px);
      aspect-ratio: 1;
      cursor: grab;
      touch-action: none;
      user-select: none;
      transition: left 0.42s ease, top 0.42s ease, transform 0.18s ease, filter 0.18s ease;
      outline: none;
      will-change: left, top, transform;
    }
    .ego-animation-character:focus-visible {
      filter: drop-shadow(0 0 8px #8ab6ff);
    }
    .ego-animation-character.is-dragging {
      cursor: grabbing;
      transition: transform 0.18s ease, filter 0.18s ease;
      transform: scale(1.05);
      filter: drop-shadow(0 12px 14px rgba(0, 0, 0, 0.45));
    }
    .ego-animation-character.is-running {
      transform: translateY(-4px);
      filter: drop-shadow(0 10px 10px rgba(0, 0, 0, 0.4));
      transition: left 0.2s linear, top 0.2s linear, transform 0.18s ease, filter 0.18s ease;
    }
    .ego-animation-character.is-over-input {
      pointer-events: none;
    }
    .ego-animation-character.is-jumping {
      transform: translateY(-18px) scale(1.04);
      filter: drop-shadow(0 16px 12px rgba(0, 0, 0, 0.42));
    }
    .ego-animation-character.is-failed {
      transform: rotate(-8deg);
    }
    .ego-animation-character img {
      width: 100%;
      height: 100%;
      display: block;
      object-fit: contain;
      pointer-events: none;
      -webkit-user-drag: none;
    }
    .emotion-bubble {
      position: absolute;
      width: 56px;
      height: 56px;
      border-radius: 50%;
      border: 2px solid rgba(255, 255, 255, 0.4);
      display: flex;
      align-items: center;
      justify-content: center;
      font-size: 1em;
      font-weight: 600;
      cursor: pointer;
      pointer-events: auto;
      box-shadow: 0 8px 16px rgba(0, 0, 0, 0.35);
      opacity: 0;
      transform: scale(0.6) translateY(12px);
      animation: bubbleFloat 3.2s ease-out forwards;
      user-select: none;
      z-index: 5;
    }
    .emotion-bubble.friendly {
      background: radial-gradient(circle at 30% 30%, #b8ffcc, #2da64a);
      color: #053a12;
    }
    .emotion-bubble.angry {
      background: radial-gradient(circle at 30% 30%, #ffb3b3, #a62323);
      color: #fff;
      border-color: rgba(255, 255, 255, 0.25);
    }
    .emotion-bubble.removing {
      opacity: 0 !important;
      transform: scale(0.4) translateY(-10px) !important;
      animation: none;
      transition: opacity 0.2s ease, transform 0.2s ease;
      }
    /*
      Evil mode styling.  When the entity has the `evil` class, its
      appearance changes dramatically to signal that EgoMorph is in a bad
      mood.  The background shifts to deep reds, the box shadow glows
      ominously and horns appear using pseudo-elements.  The eyes and
      mouth are also restyled via descendant selectors below.
    */
    #entity.evil {
      background: radial-gradient(circle at center, #a00, #300);
      box-shadow: 0 0 40px #b00;
      /* Allow horns to protrude above the entity.  Without this,
         pseudo-elements are clipped by the default overflow hidden on
         #entity. */
      overflow: visible;
    }
    /* Draw horns using pseudo-elements.  These triangles sit above the
       entity when evil mode is active.  Absolute positioning is used
       relative to the #entity container. */
    #entity.evil::before,
    #entity.evil::after {
      content: '';
      position: absolute;
      z-index: 1;
      width: 0;
      height: 0;
      /* Colour the horns a brighter red so that they stand out against
         the entity’s glow. */
      /* Increase the size of the horns so they are clearly visible. */
      border-bottom: 24px solid #f55;
      border-left: 12px solid transparent;
      border-right: 12px solid transparent;
      top: -24px;
    }
    #entity.evil::before {
      left: 25%;
    }
    #entity.evil::after {
      right: 25%;
    }
    /* When evil, change the eyes to lighter red and pupils to dark. */
    #entity.evil .eye {
      background: #fcc;
    }
    #entity.evil .pupil {
      background: #600;
    }
    /* Make the mouth look like a grimacing frown in evil mode.  The
       border is coloured red and the mouth is flipped to give a menacing
       appearance. */
    #entity.evil #mouth {
      border: 4px solid #b00;
      border-bottom: none;
      border-radius: 50% 50% 0 0;
      height: 20%;
    }
    /* Define a shake animation that moves the entity horizontally.  The
       transform references the --scale variable so that the scaling
       applied in JavaScript is preserved during the shaking. */
    @keyframes shake {
      0% { transform: scale(var(--scale)) translateX(0); }
      25% { transform: scale(var(--scale)) translateX(-4px); }
      50% { transform: scale(var(--scale)) translateX(4px); }
      75% { transform: scale(var(--scale)) translateX(-4px); }
      100% { transform: scale(var(--scale)) translateX(0); }
    }
    /* Apply the shake animation when the entity has the .shake class.  The
       animation repeats continuously while the class is present. */
    #entity.shake {
      animation: shake 0.4s linear infinite;
    }
   @keyframes bubbleFloat {
      0% { opacity: 0; transform: scale(0.6) translateY(12px); }
      20% { opacity: 1; transform: scale(1) translateY(0); }
      80% { opacity: 1; transform: scale(1.05) translateY(-12px); }
      100% { opacity: 0; transform: scale(1.1) translateY(-24px); }
   }
    .eye {
      position: absolute;
      top: 30%;
      width: 20%;
      height: 20%;
      background: #eee;
      border-radius: 50%;
      pointer-events: none;
    }
    /*
      Each eye contains a smaller pupil which we animate in response to
      pointer movement.  The pupil is scaled as a percentage of its
      parent eye so it remains centred and cannot leave the eye
      boundary.  Its position is updated via JavaScript by applying
      small percentage translations on the X and Y axes.  A short
      transition makes the movement appear smooth without lagging too
      far behind the cursor.
    */
    .eye .pupil {
      position: absolute;
      width: 50%;
      height: 50%;
      top: 25%;
      left: 25%;
      /* Use a CSS custom property for the fill colour so it can be
         customised via JavaScript.  A default of black is provided if
         the variable is not set. */
      background: var(--pupil-color, #000);
      border-radius: 50%;
      /* Smoothly animate top/left changes as the eyes track the pointer */
      transition: top 0.1s linear, left 0.1s linear;
      pointer-events: none;
    }
    #eye-left { left: 25%; }
    #eye-right { right: 25%; }
    #mouth {
      position: absolute;
      bottom: 25%;
      left: 25%;
      width: 50%;
      height: 15%;
      box-sizing: border-box;
      pointer-events: none;
    }
    #inputSection {
      margin-top: 30px;
      display: flex;
      flex-direction: column;
      align-items: center;
      /* Add a subtle container around the controls for better layout */
      background: #111;
      padding: 20px;
      border-radius: 10px;
      box-shadow: 0 0 20px rgba(102,102,255,0.3);
    }
    #inputText {
      width: min(300px, 80vw);
      padding: 10px;
      background: #222;
      color: #eee;
      border: 1px solid #555;
      border-radius: 4px;
    }
    button {
      margin-top: 10px;
      padding: 8px 20px;
      background: #333;
      color: #eee;
      border: none;
      cursor: pointer;
      border-radius: 4px;
    }
    #speechButton {
      margin-top: 10px;
      padding: 8px 12px;
      background: #333;
      color: #eee;
      border: none;
      cursor: pointer;
      font-size: 1.4em;
    }

    /*
      Ensure the send and microphone buttons don’t sit so close together that
      tapping one inadvertently triggers the other.  By forcing these
      controls onto their own lines and giving the microphone a little
      extra breathing room, we reduce the chance of accidental clicks on
      touch devices.  The increased margin on the speech button also
      separates it visually from the send button.
    */
    #sendBtn,
    #speechButton {
      display: block;
      width: 100%;
    }
    #speechButton {
      margin-top: 16px;
    }
    #response {
      margin-top: 20px;
      width: min(320px, 90vw);
      background: #222;
      padding: 10px;
      border: 1px solid #444;
      min-height: 60px;
      white-space: pre-wrap;
      /* Make the response box scrollable and set a maximum height so it
         doesn’t stretch the layout when the conversation grows.  The
         overflow-y property is retained to provide a scrollbar when
         content exceeds the maximum height. */
      overflow-y: auto;
      max-height: 220px;
      border-radius: 4px;
    }
    #memory {
      margin-top: 10px;
      font-size: 0.8em;
      color: #aaa;
    }
      #emotionPointsDisplay {
      margin-top: 12px;
      width: min(320px, 92vw);
      background: radial-gradient(circle at top left, rgba(26, 35, 61, 0.9), rgba(8, 12, 24, 0.95));
      border: 1px solid #2b3249;
      border-radius: 12px;
      box-shadow: 0 14px 28px rgba(0, 0, 0, 0.45);
      font-family: "SFMono-Regular", "Fira Code", "Source Code Pro", monospace;
      overflow: hidden;
      transition: border-color 0.25s ease, box-shadow 0.25s ease;
    }
    #emotionPointsDisplay .terminal-header {
      display: flex;
      align-items: center;
      gap: 6px;
      padding: 8px 12px;
      background: linear-gradient(120deg, rgba(20, 26, 43, 0.95), rgba(12, 17, 30, 0.9));
      border-bottom: 1px solid rgba(67, 81, 124, 0.35);
      color: #8a98bd;
      font-size: 0.72rem;
      letter-spacing: 0.04em;
      text-transform: uppercase;
    }
    #emotionPointsDisplay .terminal-title {
      margin-left: auto;
      font-weight: 600;
      }
    #emotionPointsDisplay .terminal-dot {
      width: 9px;
      height: 9px;
      border-radius: 50%;
      box-shadow: 0 0 6px rgba(255, 255, 255, 0.18);
    }
    #emotionPointsDisplay .dot-red { background: #ff5f56; }
    #emotionPointsDisplay .dot-yellow { background: #ffbd2e; }
    #emotionPointsDisplay .dot-green { background: #27c93f; }
    #emotionPointsDisplay .terminal-body {
      display: flex;
      align-items: baseline;
      gap: 6px;
      padding: 14px 16px 16px;
      color: #9ef1a8;
      font-size: 0.88rem;
      text-shadow: 0 0 12px rgba(80, 215, 160, 0.45);
    }
    #emotionPointsDisplay .terminal-prompt {
      color: #4bb7ff;
      font-weight: 600;
    }
    #emotionPointsDisplay .terminal-label {
      font-weight: 600;
    }
    #emotionPointsDisplay .terminal-separator {
      opacity: 0.65;
    }
    #emotionPointsDisplay .terminal-value {
      font-weight: 700;
      position: relative;
    }
    #emotionPointsDisplay .terminal-value::after {
      content: '▮';
      margin-left: 4px;
      opacity: 0.6;
      animation: blinkCaret 1.2s steps(2, jump-start) infinite;
    }
    @keyframes blinkCaret {
      0%, 50% { opacity: 0.6; }
      50.01%, 100% { opacity: 0; }
    }
    #emotionPointsDisplay.negative {
      border-color: rgba(255, 94, 94, 0.65);
      box-shadow: 0 16px 34px rgba(126, 22, 34, 0.45);
    }
   #emotionPointsDisplay.negative .terminal-body {
      color: #ff9c9c;
      text-shadow: 0 0 14px rgba(255, 75, 75, 0.45);
    }
    #settingsPanel {
      display: none;
      margin-top: 12px;
      background: #1b1d27;
      border: 1px solid #34384a;
      border-radius: 14px;
      padding: 18px;
      width: min(360px, 92vw);
      box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
      flex-direction: column;
      gap: 14px;
      line-height: 1.5;
    }

    #settingsPanel .settings-header {
      display: flex;
      flex-direction: column;
      gap: 6px;
      border-bottom: 1px solid rgba(76, 81, 106, 0.4);
      padding-bottom: 10px;
    }

    #settingsPanel .settings-header h2 {
      margin: 0;
      font-size: 1.1em;
      letter-spacing: 0.3px;
    }

    #settingsPanel .settings-header p {
      margin: 0;
      font-size: 0.85em;
      color: var(--muted, #a9a9b6);
    }

    #settingsPanel details {
      background: rgba(17, 19, 27, 0.6);
      border: 1px solid rgba(76, 81, 106, 0.35);
      border-radius: 10px;
      padding: 0 12px 12px;
    }

    #settingsPanel details[open] {
      padding-top: 6px;
    }

    #settingsPanel summary {
      list-style: none;
      cursor: pointer;
      font-size: 0.95em;
      text-transform: uppercase;
      letter-spacing: 0.3px;
      color: var(--accent, #6ea8fe);
      padding: 10px 0;
      display: flex;
      align-items: center;
      gap: 8px;
    }

    #settingsPanel summary::-webkit-details-marker {
      display: none;
    }

    #settingsPanel summary::after {
      content: '\25BC';
      font-size: 0.75em;
      margin-left: auto;
      transition: transform 0.2s ease;
    }

    #settingsPanel details[open] summary::after {
      transform: rotate(-180deg);
    }

    .settings-section-body {
      display: flex;
      flex-direction: column;
      gap: 10px;
    }

    .settings-field {
      display: grid;
      grid-template-columns: minmax(120px, 1fr) 1.2fr;
      gap: 8px;
      align-items: center;
    }

    .settings-field label {
      font-size: 0.9em;
    }

    .settings-field-controls {
      display: flex;
      flex-wrap: wrap;
      gap: 8px;
      align-items: center;
    }

    .settings-field-controls > * {
      flex: 1;
      min-width: 120px;
    }

    .settings-field-controls > button {
      flex: 0 0 auto;
    }

    #settingsPanel input[type="text"],
    #settingsPanel select {
      background: #141624;
      border: 1px solid var(--border, #222235);
      border-radius: 10px;
      padding: 8px 10px;
      color: var(--fg, #e9e9ef);
      min-width: 0;
    }

    .settings-actions {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
      gap: 8px;
    }

    .settings-inline-actions {
      display: flex;
      gap: 6px;
      flex-wrap: wrap;
      align-items: center;
    }

    .settings-description {
      font-size: 0.82em;
      line-height: 1.45;
      color: var(--muted, #a9a9b6);
      margin: 0;
    }

    .settings-hint {
      font-size: 0.78em;
      color: var(--muted, #a9a9b6);
      margin: 0;
    }

    .settings-note {
      font-size: 0.85em;
      opacity: 0.8;
    }

    .settings-preserve {
      white-space: pre-wrap;
    }
    
    /* Resource profile radio buttons */
    .profile-radio {
      display: flex;
      align-items: flex-start;
      gap: 8px;
      cursor: pointer;
      padding: 8px 10px;
      border-radius: 8px;
      border: 1px solid var(--border, #222235);
      transition: background 0.2s;
    }
    .profile-radio:hover {
      background: rgba(110, 168, 254, 0.08);
    }
    .profile-radio input[type="radio"] {
      margin-top: 4px;
      width: auto;
    }
    .profile-radio input[type="radio"]:checked + span {
      color: var(--accent, #6ea8fe);
    }

    @media (max-width: 420px) {
      .settings-field {
        grid-template-columns: 1fr;
      }

      .settings-field-controls > * {
        flex: 1 1 100%;
      }
    }

    /* Logo image styling */
    #egoIcon {
      position: absolute;
      top: 10px;
      left: 50%;
      transform: translateX(-50%);
      width: 100px;
      height: 100px;
    }

    /* Modal overlay for welcome message */
    .modal {
      position: fixed;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      background: rgba(0, 0, 0, 0.85);
      display: flex;
      align-items: center;
      justify-content: center;
      z-index: 9999;
    }

    .modal-content {
      background: #222;
      padding: 20px;
      border: 1px solid #444;
      border-radius: 8px;
      text-align: center;
      max-width: 90vw;
      color: #eee;
    }

    .modal-content button {
      margin-top: 15px;
      padding: 6px 16px;
      background: #333;
      color: #eee;
      border: none;
      cursor: pointer;
      border-radius: 4px;
    }

    /* Installation button styling */
    #installBtn {
      margin-top: 10px;
      padding: 8px 20px;
      background: #333;
      color: #eee;
      border: none;
      cursor: pointer;
      border-radius: 4px;
      display: none;
    }
