/* client/cursors.css — the game's own cursors.
 *
 * Loaded AFTER style.css, which names these tokens rather than the CSS
 * keywords. Nothing here is decoration: the OS arrow, the I-beam and the
 * browser's drag cursors are the last pieces of somebody else's interface
 * still showing through this one, and two of them actively lie — an I-beam
 * over an ability slot says "select this text", and the drag "no entry"
 * badge says "this is not allowed" over a target that accepts it.
 *
 * ── Why the badge, and where the hotspot goes ────────────────────────────
 * The world cursors are ONE arrow with a changing badge rather than four
 * unrelated glyphs. That is a precision decision, not a style one: the
 * things these cursors point AT are 40px nameplates and a body at range, so
 * the hot pixel has to stay at a sharp tip the eye can place, and it stays
 * at (2,2) in every one of them. A centred sword glyph looks better in a
 * screenshot and costs you the aim.
 *
 * The two cursors where nothing is being aimed at — dragging something, and
 * turning the camera — DO get a centred glyph at (16,16), because there the
 * pointer is carrying a thing rather than picking one.
 *
 * ── Constraints that are not obvious ─────────────────────────────────────
 * A cursor image must be 128x128 or smaller or the browser silently ignores
 * the whole declaration and you get the OS arrow with no warning. Every
 * `cursor: url(...)` must also end in a keyword fallback for the same
 * reason — a url with no fallback is invalid, not merely unsupported.
 *
 * `paint-order='stroke'` puts the dark outline BEHIND the fill, so the
 * outline reads as a rim rather than eating half the 2px-wide arrow tip.
 * These are drawn over grass, stone, water and a black UI plate, so the rim
 * is what makes one cursor legible on all of them.
 *
 * ── How the arrow is built ──────────────────────────────────────────────
 * Three paths, the same three in every arrow here, and only the colours
 * change:
 *
 *   OUTLINE  the silhouette, with a rounded heel and a rounded tail rather
 *            than the OS arrow's hard corners
 *   FACET    the left wedge — tip, leading edge, heel, notch, back up the
 *            spine — filled a stop lighter
 *   SPINE    a hairline down the centre in gold
 *
 * The facet is what makes it read as struck metal catching light on one
 * edge rather than a flat sticker, and it is doing the work a drop shadow
 * would do in a bigger icon — there is no room for one at 32px, and a
 * shadow under a cursor drifts away from whatever it is pointing at. The
 * shaded body is deliberately several stops down from the facet: a
 * gentler split looked cleaner at 3x and vanished at 1x, which is the only
 * size that ships.
 */

:root {
    /* The pointer. Bone and shadowed ivory with a gold ridge — the palette
       the HUD's own plates are cut from, rather than the OS's. */
    --cur-default:
        url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32' viewBox='0 0 32 32'%3E%3Cpath d='M2 2L2.4 21.4Q2.5 23 4 22.1L7.3 19.1L10.5 26.1Q10.9 27 11.9 26.6L13.6 25.8Q14.5 25.3 14.1 24.4L11.2 17.9L16 17.5Q17.4 17.4 16.5 16.3Z' fill='%23b3a077' stroke='%2314110d' stroke-width='2.1' stroke-linejoin='round' paint-order='stroke'/%3E%3Cpath d='M2 2L2.4 21.4Q2.5 23 4 22.1L7.3 19.1Z' fill='%23f7f0dc'/%3E%3Cpath d='M2.9 4.3L6.9 18.5' stroke='%23e2bd6d' stroke-width='1' stroke-linecap='round' fill='none'/%3E%3C/svg%3E") 2 2,
        default;

    /* Something in the HUD will respond to a click. The same arrow struck in
       GOLD rather than a badge: at 32px a material change is read faster
       than a glyph, and this is the state the pointer is in most often. */
    --cur-point:
        url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32' viewBox='0 0 32 32'%3E%3Cpath d='M2 2L2.4 21.4Q2.5 23 4 22.1L7.3 19.1L10.5 26.1Q10.9 27 11.9 26.6L13.6 25.8Q14.5 25.3 14.1 24.4L11.2 17.9L16 17.5Q17.4 17.4 16.5 16.3Z' fill='%23bb8f34' stroke='%2314110d' stroke-width='2.1' stroke-linejoin='round' paint-order='stroke'/%3E%3Cpath d='M2 2L2.4 21.4Q2.5 23 4 22.1L7.3 19.1Z' fill='%23f4dda3'/%3E%3Cpath d='M2.9 4.3L6.9 18.5' stroke='%23fff3d2' stroke-width='1' stroke-linecap='round' fill='none'/%3E%3C/svg%3E") 2 2,
        pointer;

    /* This can be picked up and carried somewhere — an ability in the
       Character pane, a slot on the bar, a potion in the bag. Three bars:
       the grip mark, which is what a draggable thing looks like everywhere
       else in software. */
    --cur-grab:
        url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32' viewBox='0 0 32 32'%3E%3Cpath d='M2 2L2.4 21.4Q2.5 23 4 22.1L7.3 19.1L10.5 26.1Q10.9 27 11.9 26.6L13.6 25.8Q14.5 25.3 14.1 24.4L11.2 17.9L16 17.5Q17.4 17.4 16.5 16.3Z' fill='%23b3a077' stroke='%2314110d' stroke-width='2.1' stroke-linejoin='round' paint-order='stroke'/%3E%3Cpath d='M2 2L2.4 21.4Q2.5 23 4 22.1L7.3 19.1Z' fill='%23f7f0dc'/%3E%3Cpath d='M2.9 4.3L6.9 18.5' stroke='%23e2bd6d' stroke-width='1' stroke-linecap='round' fill='none'/%3E%3Ccircle cx='23' cy='23' r='7.6' fill='%2314110d' stroke='%23d4af5f' stroke-width='1.5'/%3E%3Cpath d='M19.6 20.6h6.8M19.6 23h6.8M19.6 25.4h6.8' stroke='%23d4af5f' stroke-width='1.7' stroke-linecap='round'/%3E%3C/svg%3E") 2 2,
        grab;

    /* Carrying it. Centred, because the pointer is no longer aiming at
       anything — the ghost under it IS the thing being placed. */
    --cur-drag:
        url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32' viewBox='0 0 32 32'%3E%3Cpath d='M16 2L20 7.2H17.3V14.8H24.9V12.1L30 16L24.9 19.9V17.2H17.3V24.8H20L16 30L12 24.8H14.7V17.2H7.1V19.9L2 16L7.1 12.1V14.8H14.7V7.2H12Z' fill='%23d4af5f' stroke='%2314110d' stroke-width='1.9' stroke-linejoin='round' paint-order='stroke'/%3E%3C/svg%3E") 16 16,
        grabbing;

    /* A living hostile under the pointer. Red is the only place red appears
       in this set, and it is the one state with a consequence.
       ONE SWORD, NOT TWO CROSSED. Crossed blades at eleven pixels are an X in
       a red ring, which is the "no entry" badge this whole set exists to get
       rid of — a cursor that says "you may not" over the one thing you are
       most meant to click. It is one sword, and it stands UPRIGHT: a diagonal
       blade across a red ring is still a slashed circle at a glance, which is
       the same mistake with one stroke instead of two. Vertical blade,
       horizontal guard, pommel — the shape a sword has in every icon set —
       and the hostility rides the red ring and guard. */
    --cur-attack:
        url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32' viewBox='0 0 32 32'%3E%3Cpath d='M2 2L2.4 21.4Q2.5 23 4 22.1L7.3 19.1L10.5 26.1Q10.9 27 11.9 26.6L13.6 25.8Q14.5 25.3 14.1 24.4L11.2 17.9L16 17.5Q17.4 17.4 16.5 16.3Z' fill='%23b3a077' stroke='%2314110d' stroke-width='2.1' stroke-linejoin='round' paint-order='stroke'/%3E%3Cpath d='M2 2L2.4 21.4Q2.5 23 4 22.1L7.3 19.1Z' fill='%23f7f0dc'/%3E%3Cpath d='M2.9 4.3L6.9 18.5' stroke='%23e2bd6d' stroke-width='1' stroke-linecap='round' fill='none'/%3E%3Ccircle cx='23' cy='23' r='7.6' fill='%2314110d' stroke='%23e8695a' stroke-width='1.5'/%3E%3Cpath d='M23 20.1L23 26.1' stroke='%23e8dcc0' stroke-width='2.3'/%3E%3Cpath d='M23 18.1L24.5 20.6L21.5 20.6Z' fill='%23e8dcc0'/%3E%3Cpath d='M20.2 24.5L25.8 24.5' stroke='%23e8695a' stroke-width='1.7' stroke-linecap='round'/%3E%3Ccircle cx='23' cy='27' r='1.3' fill='%23e8695a'/%3E%3C/svg%3E") 2 2,
        crosshair;

    /* Someone with something to say, or something to sell. */
    --cur-talk:
        url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32' viewBox='0 0 32 32'%3E%3Cpath d='M2 2L2.4 21.4Q2.5 23 4 22.1L7.3 19.1L10.5 26.1Q10.9 27 11.9 26.6L13.6 25.8Q14.5 25.3 14.1 24.4L11.2 17.9L16 17.5Q17.4 17.4 16.5 16.3Z' fill='%23b3a077' stroke='%2314110d' stroke-width='2.1' stroke-linejoin='round' paint-order='stroke'/%3E%3Cpath d='M2 2L2.4 21.4Q2.5 23 4 22.1L7.3 19.1Z' fill='%23f7f0dc'/%3E%3Cpath d='M2.9 4.3L6.9 18.5' stroke='%23e2bd6d' stroke-width='1' stroke-linecap='round' fill='none'/%3E%3Ccircle cx='23' cy='23' r='7.6' fill='%2314110d' stroke='%23d4af5f' stroke-width='1.5'/%3E%3Crect x='19.1' y='19.4' width='7.8' height='5.1' rx='1.3' fill='%23d4af5f'/%3E%3Cpath d='M21.3 24.3h2.5l-2.5 3z' fill='%23d4af5f'/%3E%3C/svg%3E") 2 2,
        help;

    /* A corpse with something in it. A drawstring POUCH: the earlier coin stack
       was another gold disc with horizontal bars, indistinguishable from the
       three-bar grab mark at 1x. */
    --cur-loot:
        url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32' viewBox='0 0 32 32'%3E%3Cpath d='M2 2L2.4 21.4Q2.5 23 4 22.1L7.3 19.1L10.5 26.1Q10.9 27 11.9 26.6L13.6 25.8Q14.5 25.3 14.1 24.4L11.2 17.9L16 17.5Q17.4 17.4 16.5 16.3Z' fill='%23b3a077' stroke='%2314110d' stroke-width='2.1' stroke-linejoin='round' paint-order='stroke'/%3E%3Cpath d='M2 2L2.4 21.4Q2.5 23 4 22.1L7.3 19.1Z' fill='%23f7f0dc'/%3E%3Cpath d='M2.9 4.3L6.9 18.5' stroke='%23e2bd6d' stroke-width='1' stroke-linecap='round' fill='none'/%3E%3Ccircle cx='23' cy='23' r='7.6' fill='%2314110d' stroke='%23d4af5f' stroke-width='1.5'/%3E%3Cpath d='M21.4 18.6L24.6 18.6L23.8 20.6Q27.6 22.4 27.4 25.4Q27.2 27.8 23 27.8Q18.8 27.8 18.6 25.4Q18.4 22.4 22.2 20.6Z' fill='%23d4af5f' stroke='%2314110d' stroke-width='0.6' stroke-linejoin='round'/%3E%3Cpath d='M21.6 20.9L24.4 20.9' stroke='%2314110d' stroke-width='1' stroke-linecap='round'/%3E%3Cpath d='M23 22.8V25.6M21.6 24.2H24.4' stroke='%2314110d' stroke-width='0.9' stroke-linecap='round'/%3E%3C/svg%3E") 2 2,
        pointer;

    /* Aiming a ground-target ability. Centred, like the camera and drag
       cursors, because the pointer is placing a POINT rather than picking a
       thing — the reticle on the terrain is what the player is looking at,
       and a crosshair whose hot pixel is its own centre is what puts the ring
       where the eye already is. Gold ring and ticks in the HUD's palette; the
       keyword fallback is the one OS cursor that means the same thing. */
    --cur-ground:
        url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32' viewBox='0 0 32 32'%3E%3Ccircle cx='16' cy='16' r='9' fill='none' stroke='%2314110d' stroke-width='4.6'/%3E%3Cpath d='M16 2.5v6M16 23.5v6M2.5 16h6M23.5 16h6' stroke='%2314110d' stroke-width='4.6' stroke-linecap='round'/%3E%3Ccircle cx='16' cy='16' r='9' fill='none' stroke='%23d4af5f' stroke-width='2'/%3E%3Cpath d='M16 2.5v6M16 23.5v6M2.5 16h6M23.5 16h6' stroke='%23d4af5f' stroke-width='2' stroke-linecap='round'/%3E%3Ccircle cx='16' cy='16' r='1.6' fill='%23f4dda3'/%3E%3C/svg%3E") 16 16,
        crosshair;

    /* Turning the camera. Centred and circular: the gesture is a rotation
       about the character, and the cursor is pinned for its whole life
       anyway (pointer capture), so there is nothing left to aim. */
    --cur-camera:
        url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32' viewBox='0 0 32 32'%3E%3Cpath d='M24.6 16a8.6 8.6 0 1 1-2.6-6.1' fill='none' stroke='%2314110d' stroke-width='5.4' stroke-linecap='round'/%3E%3Cpath d='M23.6 4.6l1.4 6.4-6.4-1z' fill='%2314110d' stroke='%2314110d' stroke-width='3' stroke-linejoin='round'/%3E%3Cpath d='M24.6 16a8.6 8.6 0 1 1-2.6-6.1' fill='none' stroke='%23d4af5f' stroke-width='2.6' stroke-linecap='round'/%3E%3Cpath d='M23.6 4.6l1.4 6.4-6.4-1z' fill='%23d4af5f'/%3E%3C/svg%3E") 16 16,
        grabbing;

    /* Something in the world you can read: a sign, a notice, a marker over a prop.
       Not "clickable UI" (gold arrow) and not "someone to talk to" (speech): a lens. */
    --cur-examine:
        url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32' viewBox='0 0 32 32'%3E%3Cpath d='M2 2L2.4 21.4Q2.5 23 4 22.1L7.3 19.1L10.5 26.1Q10.9 27 11.9 26.6L13.6 25.8Q14.5 25.3 14.1 24.4L11.2 17.9L16 17.5Q17.4 17.4 16.5 16.3Z' fill='%23b3a077' stroke='%2314110d' stroke-width='2.1' stroke-linejoin='round' paint-order='stroke'/%3E%3Cpath d='M2 2L2.4 21.4Q2.5 23 4 22.1L7.3 19.1Z' fill='%23f7f0dc'/%3E%3Cpath d='M2.9 4.3L6.9 18.5' stroke='%23e2bd6d' stroke-width='1' stroke-linecap='round' fill='none'/%3E%3Ccircle cx='23' cy='23' r='7.6' fill='%2314110d' stroke='%23d4af5f' stroke-width='1.5'/%3E%3Ccircle cx='22' cy='22' r='3' fill='none' stroke='%23d4af5f' stroke-width='1.6'/%3E%3Cpath d='M24.2 24.2L27 27' stroke='%23d4af5f' stroke-width='1.9' stroke-linecap='round'/%3E%3C/svg%3E") 2 2,
        help;

    /* The world is loading and input is being held. An hourglass badge; the
       keyword fallback is the OS's own "in progress" arrow-and-spinner. */
    --cur-busy:
        url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32' viewBox='0 0 32 32'%3E%3Cpath d='M2 2L2.4 21.4Q2.5 23 4 22.1L7.3 19.1L10.5 26.1Q10.9 27 11.9 26.6L13.6 25.8Q14.5 25.3 14.1 24.4L11.2 17.9L16 17.5Q17.4 17.4 16.5 16.3Z' fill='%23b3a077' stroke='%2314110d' stroke-width='2.1' stroke-linejoin='round' paint-order='stroke'/%3E%3Cpath d='M2 2L2.4 21.4Q2.5 23 4 22.1L7.3 19.1Z' fill='%23f7f0dc'/%3E%3Cpath d='M2.9 4.3L6.9 18.5' stroke='%23e2bd6d' stroke-width='1' stroke-linecap='round' fill='none'/%3E%3Ccircle cx='23' cy='23' r='7.6' fill='%2314110d' stroke='%23d4af5f' stroke-width='1.5'/%3E%3Cpath d='M19.6 19.2h6.8M19.6 26.8h6.8M20.6 19.2c0 3 5 4.6 5 7.6M25.4 19.2c0 3-5 4.6-5 7.6' stroke='%23d4af5f' stroke-width='1.5' stroke-linecap='round' fill='none'/%3E%3C/svg%3E") 2 2,
        progress;

    /* Resize handles. Centred double arrows in the HUD's gold: the OS's white
       resize glyphs were the last foreign cursor on a panel edge. */
    --cur-resize-ns:
        url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32' viewBox='0 0 32 32'%3E%3Cg transform='rotate(0 16 16)'%3E%3Cpath d='M16 2L23 11H18.4V21H23L16 30L9 21H13.6V11H9Z' fill='%23d4af5f' stroke='%2314110d' stroke-width='1.9' stroke-linejoin='round' paint-order='stroke'/%3E%3C/g%3E%3C/svg%3E") 16 16,
        ns-resize;

    --cur-resize-nesw:
        url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32' viewBox='0 0 32 32'%3E%3Cg transform='rotate(45 16 16)'%3E%3Cpath d='M16 2L23 11H18.4V21H23L16 30L9 21H13.6V11H9Z' fill='%23d4af5f' stroke='%2314110d' stroke-width='1.9' stroke-linejoin='round' paint-order='stroke'/%3E%3C/g%3E%3C/svg%3E") 16 16,
        nesw-resize;

    --cur-resize-nwse:
        url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32' viewBox='0 0 32 32'%3E%3Cg transform='rotate(-45 16 16)'%3E%3Cpath d='M16 2L23 11H18.4V21H23L16 30L9 21H13.6V11H9Z' fill='%23d4af5f' stroke='%2314110d' stroke-width='1.9' stroke-linejoin='round' paint-order='stroke'/%3E%3C/g%3E%3C/svg%3E") 16 16,
        nwse-resize;
}

/* ── Disabling the browser's own ─────────────────────────────────────────
 *
 * `cursor` already inherits, so setting it on the root would be enough if
 * nothing else set it. The user-agent stylesheet does: `input` and
 * `textarea` get the I-beam, `button` gets the arrow back. `* { inherit }`
 * is what overrides those, and it does so WITHOUT beating anything in
 * style.css — a universal selector has zero specificity, so every rule that
 * names a class or an id still wins.
 */
html,
body {
    cursor: var(--cur-default);
}

* {
    cursor: inherit;
}

/* tw_shim.css sets `cursor` by KEYWORD on three selectors, and each ties
   with the rule below on specificity — which is the whole reason this sheet
   is linked after it. Ties go to the later sheet; without that ordering the
   OS arrow comes back on every button in the HUD. */
button,
[role='button'],
.cursor-pointer {
    cursor: var(--cur-point);
}

/* Anything that can be picked up and carried: an ability row in the
   Character pane, a bound slot on the bar, a stack in the bag. UIDrag.
   bindSource stamps this class on every source it binds, so the mark and the
   behaviour cannot come apart — one rule rather than three kept in step.

   NOT `[draggable='true']`, which is what this was and which cost a round:
   that attribute is not a mark, it is the switch that turns the browser's own
   drag-and-drop back on, so using it for styling restarted a native drag
   under every gesture and handed the cursor back to the browser.

   It has to live in THIS sheet: every one of those three sources is a <button>
   or carries role="button", and the rules above would otherwise win the tie. */
.ui-draggable {
    cursor: var(--cur-grab);
}

:disabled,
.cursor-not-allowed {
    /* Not a "no entry" glyph. The button is dim and unpressable and says so
       already; a second refusal at the pointer is the browser talking over
       the interface. */
    cursor: var(--cur-default);
}

/* Text fields keep the I-beam, deliberately. It is the one browser cursor
   here that is telling the truth: there is a caret, and it goes where you
   click. Replacing it would cost precision to gain nothing. */
input,
textarea,
[contenteditable='true'] {
    cursor: text;
}

/* Sliders, checkboxes, radios and dropdowns are controls, not text: the rule
   above gave a settings slider the I-beam (the same lie the header describes,
   "select this text" over something you drag), and a <select> kept the OS
   arrow. Attribute selectors here outrank the bare `input` rule. */
input[type='range'],
input[type='checkbox'],
input[type='radio'],
input[type='button'],
input[type='submit'],
select,
summary,
label[for] {
    cursor: var(--cur-point);
}

input:disabled,
select:disabled {
    cursor: var(--cur-default);
}

/* The nameplate carries the same three states as the body under it — set by
   nameplates.js from the same rule game.js uses, because the raycast that
   drives the body cursor cannot see a plate floating over the head. Classed
   rather than tokened on #gameCanvas because a plate is a DOM element and
   hovering it is a plain :hover, no raycast involved. */
.cursor-attack {
    cursor: var(--cur-attack);
}

.cursor-talk {
    cursor: var(--cur-talk);
}

.cursor-loot {
    cursor: var(--cur-loot);
}

/* ── While a drag is in flight ───────────────────────────────────────────
 *
 * The whole document, not the drop target: the pointer spends most of the
 * gesture over the world, and the browser's answer to "is this a valid drop
 * target" was the "no entry" badge for every pixel of that journey.
 * `!important` because it has to beat the `cursor: pointer` on every button
 * the ghost passes over — during a drag those buttons are not clickable and
 * saying they are is the same lie in the other direction. */
html[data-uidrag] *,
html[data-uidrag] {
    cursor: var(--cur-drag) !important;
}

/* The thing being carried, drawn under the pointer. It is the payload's own
   icon at bar size, so what you are placing is never in doubt — and it is
   what makes the centred drag cursor legible as "carrying" rather than
   "move window". */
.ui-drag-ghost {
    position: fixed;
    z-index: 9999;
    top: 0;
    left: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    padding: 3px;
    border: 1px solid var(--gold);
    border-radius: 2px;
    background: rgba(16, 13, 9, 0.86);
    box-shadow: 0 3px 10px rgba(0, 0, 0, 0.7);
    opacity: 0.9;
    pointer-events: none;
}

.ui-drag-ghost img,
.ui-drag-ghost .ui-icon-img {
    width: 100%;
    height: 100%;
    object-fit: contain;
}

.ui-drag-ghost-glyph {
    color: var(--parchment);
    font-family: Cinzel, Georgia, serif;
    font-size: 13px;
    letter-spacing: 0.04em;
}
