/* =========================================================================
   PostYard — canonical preview canvas.

   Extracted verbatim from frontend.css so it can be loaded on its own by the
   headless-Chromium render document, which must not carry the whole app
   stylesheet. This file and frontend.css are BOTH loaded on the front end, in
   that order — nothing here shares a selector with anything outside it, so the
   split is purely about what the renderer has to inline.

   ONE source of truth for canvas markup styling. Used at four sizes (brand
   listing card, template designer card, large form preview, per-post graphic
   editor) plus the Chromium render document. Container query units (cqw) keep
   every size consistent, and `round(($px / 1080) * 100, 3)` is the load-bearing
   preview-to-PNG constant that makes them agree.
   ========================================================================= */

.py-canvas {
	container-type: inline-size;
	aspect-ratio: 1 / 1;
	position: relative;
	overflow: hidden;
	/* font-family is set via inline style by py_canvas_preview / pyCanvasPreviewHTML
	   so each brand uses its chosen font in the preview. UI font (Inter) is the
	   fallback. */
	font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
	color: #fff;
	user-select: none;
	transition: background .15s ease, font-family .15s ease;
}

.py-canvas__el {
	position: absolute;
	z-index: 2;
}

/* Full-canvas legibility overlay (image-background scrim / tint). Sits
   above the background but below every design element. */
.py-canvas__overlay {
	position: absolute;
	inset: 0;
	z-index: 1;
	pointer-events: none;
}

/* Element width/height/font-size now come from inline style attributes
   so each template can be sized independently. The CSS only provides
   weight/line-height/etc. that aren't part of the editable layout. */

.py-canvas__title {
	line-height: 1.25;
	font-weight: 800;
	letter-spacing: -0.02em;
	z-index: 2;
	/* Honour an explicit newline in the title as a line break, matching the GD
	   PNG (PY_Graphic_Assembler::title_segments). One rule on the shared class
	   covers BOTH preview helpers — py_canvas_preview() (PHP) and makeTitleEl()
	   (JS) — with zero markup change; each inserts a raw \n as text-node content,
	   which pre-line renders as a break while still collapsing ordinary runs of
	   whitespace and wrapping normally, so the existing <br>-based sample copy is
	   unaffected. */
	white-space: pre-line;
}

/* Bullet hanging indent — the preview half of PY_Graphic_Assembler's
   hanging_indent(). Only emitted for a LEFT-aligned text box whose copy is
   actually bulleted (see py_text_lines_html() / PYCanvasDesigner.renderTextInto);
   every other text box still goes in as one pre-line text node and is untouched
   by these rules.

   Why markup rather than text-indent: CSS text-indent applies to the FIRST line
   of a block only, and `text-indent: … each-line` is unimplemented in browsers,
   so a multi-bullet title would indent bullet 1's wrap and leave the rest flush.
   A two-cell flex row gives a real hanging indent, and the browser measures the
   marker itself — the same semantic rule GD applies with its own metrics, which
   is closer parity than a shared em constant could get. */
.py-canvas__line {
	display: block;
	/* The segments ARE the lines now, so pre-line's newline handling is neither
	   needed nor wanted here (the raw \n separators aren't emitted in this
	   shape, and pre-line would add a second break). Ordinary wrapping inside
	   each line is exactly what's wanted. */
	white-space: normal;
}

.py-canvas__line--bullet {
	display: flex;
	align-items: flex-start;
}

/* The marker cell: never wraps, never collapses its trailing space (that space
   is part of the measured indent on the PNG), and carries the accent colour the
   GD renderer has painted it since v1.71.9. */
.py-canvas__bullet-mark {
	white-space: pre;
	flex: 0 0 auto;
}

/* The body cell takes the remaining width and wraps inside it — which is what
   puts every continuation line under the body text rather than under the
   marker. min-width:0 so a long unbreakable word can't force the row wider
   than the box (flex items refuse to shrink below content width otherwise). */
.py-canvas__bullet-body {
	flex: 1 1 auto;
	min-width: 0;
}

/* The DATE element — a single-line text box sharing the title's font machinery.
   font-size comes inline as cqw (derived from date.size exactly like the title,
   so preview ↔ PNG scale together); width/left/top/text-align/colour are inline
   too. Bold to match the GD render, which draws the date with the same
   Inter-Bold face as the title. nowrap because a formatted date is always one
   line — it must never reflow in the preview when the PNG would not. */
.py-canvas__date {
	font-weight: 800;
	z-index: 2;
	white-space: nowrap;
}

.py-canvas__icon svg {
	width: 100%;
	height: 100%;
	display: block;
}

/* Framed icon slot — a bordered circle/square holding the member-logo
   placeholder. The outer element carries the border paint (solid colour or a
   gradient) as its background; its padding equals the border width, so the
   inner element (inset by that padding) reveals the paint as the ring/band.
   All of that is applied inline so it tracks the template's icon_style. */
.py-canvas__icon--framed {
	box-sizing: border-box;
}
.py-canvas__icon-inner {
	width: 100%;
	height: 100%;
	display: flex;
	align-items: center;
	justify-content: center;
	overflow: hidden;
}
.py-canvas__icon--framed .py-canvas__icon-ph {
	width: 64%;
	height: 64%;
	display: block;
}
/* The post's REAL picture in the image slot — only the per-post graphic editor
   passes one (the designer has no post, so it keeps the placeholder glyph).
   `contain` matches how PY_Graphic_Assembler fits an icon into its box. */
.py-canvas__icon-img {
	width: 100%;
	height: 100%;
	object-fit: contain;
	display: block;
}
/* Designer affordance only: a faint ring so the slot's shape (esp. a circle
   with no border/fill) is always visible while editing. box-shadow follows
   border-radius (outline wouldn't), and this never renders into the PNG. */
.py-canvas--interactive .py-canvas__icon--framed {
	box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.22);
}

.py-canvas__logo {
	object-fit: contain;
	height: auto;
	z-index: 2;
}

.py-canvas__logo--placeholder {
	height: 8cqw;
	background: rgba(255,255,255,.12);
	border: 1px dashed rgba(255,255,255,.3);
	color: rgba(255,255,255,.7);
	font-size: 2cqw;
	font-weight: 700;
	letter-spacing: 0.15em;
	display: flex;
	align-items: center;
	justify-content: center;
}

.py-canvas__hint {
	position: absolute;
	bottom: 2.4cqw;
	left: 50%;
	transform: translateX(-50%);
	width: 86%;
	font-size: 1.65cqw;
	line-height: 1.45;
	text-align: center;
	color: rgba(255,255,255,.62);
	font-weight: 500;
	letter-spacing: 0.03em;
	pointer-events: none;
	opacity: 0;
	transition: opacity .2s;
	white-space: normal;
	z-index: 4;
	text-shadow: 0 1px 3px rgba(0,0,0,.5);
}
.py-canvas--interactive:hover .py-canvas__hint { opacity: 1; }

/* Interactive mode — drag affordances */
.py-canvas--interactive .py-canvas__el {
	cursor: grab;
	touch-action: none;
	outline: 0.2cqw dashed transparent;
	outline-offset: 0.5cqw;
	border-radius: 3px;
	transition: outline-color .12s ease, box-shadow .12s ease;
}
.py-canvas--interactive .py-canvas__el:hover {
	outline-color: rgba(255,255,255,.5);
}
.py-canvas--interactive .py-canvas__el.is-dragging {
	cursor: grabbing;
	outline-color: rgba(255,255,255,.95);
	box-shadow: 0 4px 16px rgba(0,0,0,.35);
	z-index: 10;
}
.py-canvas--interactive.is-active {
	background-image:
		linear-gradient(rgba(255,255,255,.05) 1px, transparent 1px),
		linear-gradient(90deg, rgba(255,255,255,.05) 1px, transparent 1px);
	background-size: 10% 10%, 10% 10%;
}

/* During a snap-enabled drag, draw a denser 5%-spaced grid in a stronger
   tint so the snap points are visible. */
.py-canvas--interactive.is-snapping {
	background-image:
		linear-gradient(rgba(255,255,255,.06) 1px, transparent 1px),
		linear-gradient(90deg, rgba(255,255,255,.06) 1px, transparent 1px),
		linear-gradient(rgba(255,255,255,.13) 1px, transparent 1px),
		linear-gradient(90deg, rgba(255,255,255,.13) 1px, transparent 1px);
	background-size: 5% 5%, 5% 5%, 25% 25%, 25% 25%;
}

/* =========================================================================
   HTML template wrapper.

   An HTML template's body is dropped inside this, one template per document
   (see docs/reference/html-templates.md — that invariant is why no selector
   rewriting is needed). `container-type: inline-size` is what gives an
   AI-authored template working `cqw` units, the same resolution independence
   `.py-canvas` has.
   ========================================================================= */

.py-htpl {
	width: 100%;
	height: 100%;
	position: relative;
	container-type: inline-size;
	overflow: hidden;
}
