/* Rich (WYSIWYG) meme editor -- DOM-overlay rendering of a Meme::Layers v2
   recipe. See app/javascript/controllers/rich_editor_controller.js for the
   schema->CSS geometry mapping this stylesheet works alongside: the JS sets
   every per-layer, data-driven style (position/size/font/color/stroke/etc)
   as inline styles; this file only carries the structural rules that don't
   vary per layer, plus the sticker background-image rules at the bottom.

   Bulk-included automatically by `stylesheet_link_tag :app` in the layout
   (Propshaft's :app option link-tags every .css file under app/assets/**),
   so this file needs no manual @import/manifest entry anywhere. */

.rich-editor-stage {
  position: relative;
  display: inline-block;
  max-width: 100%;
  line-height: 0; /* avoid the few px of inline-block baseline gap under the <img> */
}

.rich-editor-source {
  display: block;
  max-width: 100%;
  height: auto;
  -webkit-user-select: none;
  user-select: none;
}

.rich-editor-layer {
  position: absolute;
  /* A layer IS the drag surface (rich_editor_interactions_controller.js's
     pointerdown handler is bound on every layer element) -- without this, a
     touch-drag on a layer also arms the browser's own default touch
     handling (page scroll, or a two-finger pinch-zoom starting on the
     layer), which fights the JS drag and is exactly the "no accidental page
     scroll or pinch-zoom while dragging a layer" requirement (WP7 mobile
     pass). Relaxed back to normal touch behavior on the one layer actively
     being text-edited -- see .rich-editor-layer--editing below -- so native
     caret placement/selection gestures still work with a soft keyboard. */
  touch-action: none;
}

.rich-editor-layer--text {
  display: flex;
  align-items: center; /* vertical centering within the hit box, matching
                           x/y being the layer's vertical center regardless
                           of align -- see MemeLayerRenderer#gravity_and_offset */
  white-space: pre; /* the recipe's "\n"s are authoritative -- never let the
                        browser wrap a text layer, or wrap parity with the
                        server (which never re-wraps saved layer text) breaks */
  overflow: visible; /* text longer than the layer's declared w/h (a hit-box
                         hint only, per Meme::Layers) still renders in full,
                         matching the server never clipping to it either */
  outline: none;
  cursor: text;
  paint-order: stroke fill; /* stroke under fill, matching ImageMagick's -stroke/-fill draw order */
  -webkit-text-stroke-color: transparent; /* overridden inline per layer; keeps an unset stroke_width truly invisible */
}

/* Toggled by rich_editor_interactions_controller.js's #startEditing/blur
   handling for exactly the one text layer currently focused for editing --
   see the comment on .rich-editor-layer above. "manipulation" (not "auto")
   still blocks double-tap-to-zoom, which would otherwise fight the
   dblclick-to-edit gesture on a touchscreen. */
.rich-editor-layer--editing {
  touch-action: manipulation;
}

.rich-editor-layer--shape,
.rich-editor-layer--image {
  box-sizing: border-box;
  /* Shape/image layers have no text to select -- without this, a touch
     long-press to start a drag can instead trigger the browser's
     text-selection/callout UI (and, on iOS, a "save image" callout for the
     sticker's own background-image). Text layers deliberately keep normal
     selection behavior; they need it for editing. */
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}

.rich-editor-layer--image {
  background-repeat: no-repeat;
  background-position: center;
  background-size: contain;
  /* Last-resort fallback only -- RichEditorController#buildImageElement sets
     the real per-asset aspect-ratio inline from Meme::Layers.as_json's
     asset_dimensions (WP5), which wins over this. Only reachable for an
     asset key with no shipped dimensions (shouldn't happen for anything in
     Meme::Layers::ASSETS today, but keeps a brand-new/unrecognized key from
     collapsing to a zero-height box). */
  aspect-ratio: 1 / 1;
}

.rich-editor-layer--selected {
  outline: 2px dashed #3b82f6;
  outline-offset: 2px;
}

/* -- interaction layer (rich_editor_interactions_controller.js) --------
   The selection box + its handles are one element (.rich-editor-selection)
   positioned/rotated exactly like the selected layer itself (same
   applyGeometry call, see the controller), appended last so it always
   paints on top. It has pointer-events: none so clicks on the box's
   interior pass straight through to the real layer element underneath
   (the thing that owns select/drag/text-edit) -- only the handle buttons
   (pointer-events: auto) are interactive, positioned at the box's own
   corners so they inherit its rotation transform for free. */
.rich-editor-selection {
  position: absolute;
  box-sizing: border-box;
  border: 1.5px solid #3b82f6;
  pointer-events: none;
}

.rich-editor-handle {
  position: absolute;
  width: 14px;
  height: 14px;
  padding: 0;
  border-radius: 50%;
  background: #3b82f6;
  border: 2px solid #fff;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.35);
  pointer-events: auto;
  touch-action: none; /* let pointermove drive resize/rotate, not native scroll/pinch */
}

.rich-editor-handle:focus-visible {
  outline: 2px solid #f59e0b;
  outline-offset: 2px;
}

/* Finger-sized handles on a touch device (WP7 mobile pass) -- 14px is a
   reasonable, unobtrusive target for a mouse pointer's single-pixel
   precision but too small to reliably grab with a fingertip. `pointer:
   coarse` (true on phones/tablets, false for a mouse/trackpad, and
   independent of viewport width so this isn't a screen-size media query in
   disguise) is the standard feature-detection for "the primary input is
   imprecise", not a device/UA sniff. */
@media (pointer: coarse) {
  .rich-editor-handle {
    width: 26px;
    height: 26px;
  }

  .rich-editor-handle--rotate {
    top: -34px;
  }
}

.rich-editor-handle--nw { top: 0;    left: 0;    transform: translate(-50%, -50%); cursor: nwse-resize; }
.rich-editor-handle--ne { top: 0;    left: 100%; transform: translate(-50%, -50%); cursor: nesw-resize; }
.rich-editor-handle--sw { top: 100%; left: 0;    transform: translate(-50%, -50%); cursor: nesw-resize; }
.rich-editor-handle--se { top: 100%; left: 100%; transform: translate(-50%, -50%); cursor: nwse-resize; }
.rich-editor-handle--rotate {
  top: -28px;
  left: 50%;
  transform: translate(-50%, -50%);
  cursor: grab;
  background: #22c55e;
}

/* Sticker background images, one rule per Meme::Layers::ASSETS entry (the
   bundled geometric set -- see that constant's comment for why one "arrow"
   covers every direction via each layer's own rotation instead of needing
   arrow_left/arrow_right/... variants). Propshaft's CSS compiler rewrites
   each url() to the real digested asset path at build time. */
.rich-editor-layer--image[data-asset="sticker:arrow"]       { background-image: url("/assets/stickers/arrow-4b707f47.png"); }
.rich-editor-layer--image[data-asset="sticker:starburst"]   { background-image: url("/assets/stickers/starburst-c1cd8967.png"); }
.rich-editor-layer--image[data-asset="sticker:star"]        { background-image: url("/assets/stickers/star-9e4c750f.png"); }
.rich-editor-layer--image[data-asset="sticker:heart"]       { background-image: url("/assets/stickers/heart-6ce9c8c4.png"); }
.rich-editor-layer--image[data-asset="sticker:speech_bubble_left"]  { background-image: url("/assets/stickers/speech_bubble_left-2448a5ba.png"); }
.rich-editor-layer--image[data-asset="sticker:speech_bubble_right"] { background-image: url("/assets/stickers/speech_bubble_right-c4c46b2e.png"); }
