/* Poster Maker / Prop Scaler / Unfolder step pages: image and canvas previews,
   the nudge pad, and option groups (also used, compact, by the editors). */

/* ==========================================================================
   Image / canvas preview containers (calibrate + configure)
   ========================================================================== */

.preview-frame {
    display: inline-block;
    position: relative;
    border-radius: var(--bs-border-radius-lg);
    overflow: hidden;
    border: 1px solid var(--border-subtle);
    background: var(--surface-1);
    line-height: 0;
}

.preview-frame img {
    display: block;
    max-width: 100%;
    height: auto;
}

/* Shown while the source image Blob is still being read out of IndexedDB
   and decoded - without a forced min-height here the frame has zero
   content box (the <img> has no src yet) and collapses to nothing, so the
   spinner would have no visible frame to sit inside. */
.preview-frame.is-loading {
    min-width: 260px;
    min-height: 260px;
}

.preview-frame-loading {
    position: absolute;
    inset: 0;
}

input[type="color"].form-control {
    max-width: 4.5rem;
    padding: 0.25rem;
}

.crop-mark-preview-canvas {
    display: block;
    width: 100%;
    max-width: 260px;
    height: auto;
    aspect-ratio: 260 / 180;
    border-radius: var(--bs-border-radius);
    border: 1px solid var(--border-subtle);
}

.grid-drag-surface {
    cursor: grab;
    touch-action: none;
}

.grid-drag-surface.is-grabbing {
    cursor: grabbing;
}

/* Prop Scaler's fit screen: the overlay image is deliberately allowed to
   render larger than its frame (max-width: none) since scaling it past the
   background's own size is a normal part of fitting a prop - .preview-frame's
   overflow: hidden clips it visually rather than the image being capped.
   draggable="false"/-webkit-user-drag are defensive leftovers from an
   earlier attempt at listening for drag directly on this <img> - dragging
   is now handled entirely by .prop-scaler-drag-surface (see below), which
   sidesteps browsers' native image-drag-out gesture entirely rather than
   fighting it, but there's no harm in also telling the browser this image
   itself isn't meant to be dragged. */
.prop-scaler-overlay-img {
    max-width: none;
    -webkit-user-drag: none;
    user-select: none;
    pointer-events: none;
}

/* An otherwise-invisible layer over the whole frame that owns all pointer
   interaction for the fit screen - both dragging (pointerdown) and
   measuring (click) - so neither has to fight the overlay <img>'s native
   drag-out behavior, mirroring tiling_preview_controller.js's own
   canvas-based (not img-based) drag surface. Cursor alone communicates
   which of the two modes is currently active. */
.prop-scaler-drag-surface {
    cursor: grab;
    touch-action: none;
}

.prop-scaler-drag-surface.is-grabbing {
    cursor: grabbing;
}

.prop-scaler-drag-surface.is-measuring {
    cursor: crosshair;
}

/* Sits directly on top of .prop-scaler-drag-surface (later in DOM order,
   so it wins hit-testing) with the exact same left/top/width/height/rotate
   transform as .prop-scaler-overlay-img, kept in sync imperatively in
   prop_scaler_fit_controller.js's render() - a plain child-element
   position/rotate follows its parent's CSS transform for free, so each
   handle only needs a fixed local position within this box, not its own
   rotation math. pointer-events: none here (re-enabled per-handle below)
   lets clicks in the empty parts of the box fall through to the drag
   surface underneath for ordinary move/measure interaction. */
.prop-scaler-handle-layer {
    pointer-events: none;
}

.prop-scaler-handle-layer.is-measuring {
    display: none;
}

.prop-scaler-handle {
    position: absolute;
    width: 12px;
    height: 12px;
    margin: -6px 0 0 -6px;
    border-radius: 2px;
    background: #fff;
    border: 2px solid #0d6efd;
    pointer-events: auto;
    touch-action: none;
}

.prop-scaler-handle-nw { top: 0; left: 0; cursor: nwse-resize; }
.prop-scaler-handle-ne { top: 0; left: 100%; cursor: nesw-resize; }
.prop-scaler-handle-se { top: 100%; left: 100%; cursor: nwse-resize; }
.prop-scaler-handle-sw { top: 100%; left: 0; cursor: nesw-resize; }
.prop-scaler-handle-n { top: 0; left: 50%; cursor: ns-resize; }
.prop-scaler-handle-s { top: 100%; left: 50%; cursor: ns-resize; }
.prop-scaler-handle-e { top: 50%; left: 100%; cursor: ew-resize; }
.prop-scaler-handle-w { top: 50%; left: 0; cursor: ew-resize; }

/* Floats above the box's top-center edge, connected by a thin stem - the
   whole thing rotates for free along with .prop-scaler-handle-layer. */
.prop-scaler-handle-rotate {
    top: -28px;
    left: 50%;
    border-radius: 50%;
    cursor: grab;
}

.prop-scaler-handle-rotate.is-rotating {
    cursor: grabbing;
}

.prop-scaler-handle-rotate::before {
    content: '';
    position: absolute;
    left: 50%;
    top: 100%;
    width: 1px;
    height: 16px;
    background: #0d6efd;
    transform: translateX(-50%);
}

/* ==========================================================================
   Nudge pad (configure page - manual grid offset)
   ========================================================================== */

.nudge-pad {
    display: grid;
    grid-template-columns: repeat(3, 2.25rem);
    grid-template-rows: repeat(3, 2.25rem);
    gap: 0.25rem;
    flex-shrink: 0;
}

.nudge-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--surface-1);
    border: 1px solid var(--border-strong);
    border-radius: var(--bs-border-radius-sm);
    color: var(--text-primary);
    font-size: 1rem;
    line-height: 1;
    cursor: pointer;
}

.nudge-btn:hover {
    border-color: var(--accent-500);
    color: var(--accent-400);
}

.nudge-btn:active {
    background: var(--bs-primary-bg-subtle);
}

.nudge-up {
    grid-column: 2;
    grid-row: 1;
}

.nudge-left {
    grid-column: 1;
    grid-row: 2;
}

.nudge-reset {
    grid-column: 2;
    grid-row: 2;
    font-size: 0.9rem;
}

.nudge-right {
    grid-column: 3;
    grid-row: 2;
}

.nudge-down {
    grid-column: 2;
    grid-row: 3;
}

/* ==========================================================================
   Option groups + tooltips (configure/calibrate forms)
   ========================================================================== */

.option-group + .option-group {
    margin-top: 1.75rem;
    padding-top: 1.75rem;
    border-top: 1px solid var(--border-subtle);
}

.option-group-title {
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text-muted);
    margin-bottom: 1rem;
}

/* Compact variant for settings panels denser than a typical form (e.g. the
   Unfolder's pattern-layout options and its Blender-style toolbars/
   sidebars) - a toolbar reads as a toolbar through small, tight controls
   with minimal always-on prose, not through a smaller copy of a regular
   form. Overrides Bootstrap's own --bs-*-font-size/padding custom
   properties rather than fighting specificity, since .btn-sm/.form-
   select-sm/.input-group-sm set their sizing that way - EXCEPT for
   padding, which two site-wide rules (.btn's own padding-inline, and
   .form-control/.form-select's own padding) set as literal physical
   properties rather than through Bootstrap's --bs-btn-padding-*-sm
   custom-property mechanism. Those two rules load after Bootstrap's own
   -sm padding at equal-or-lower specificity, so they win regardless of
   which --bs-* custom property a button/control carries - overriding
   just the custom properties here has no visible effect on padding.
   Fixed below by setting padding directly at higher specificity
   (.options-compact <selector>), the only thing that reliably wins. */
.options-compact {
    font-size: 0.6875rem;
}

.options-compact.panel {
    padding: 1.25rem 1.75rem;
}

.options-compact .option-group + .option-group {
    margin-top: 0.65rem;
    padding-top: 0.65rem;
}

.options-compact .option-group-title {
    margin-bottom: 0.3rem;
    font-size: 0.62rem;
}

.options-compact .btn-sm,
.options-compact .btn-group-sm > .btn {
    --bs-btn-font-size: 0.6875rem;
    --bs-btn-padding-y: 0.15rem;
    --bs-btn-padding-x: 0.4rem;
    --bs-btn-border-radius: 0.25rem;
    padding-block: 0.15rem;
    padding-inline: 0.4rem;
    font-size: 0.6875rem;
}

/* Every button site-wide is bold with generous letter-spacing (see .btn's
   own rule above) - reads as a prominent CTA, which is right for a
   marketing page but wrong for a dense tool surface where every row is
   a button; Blender's own toolbar/panel buttons use plain body-weight
   text throughout, nothing shouting for attention. */
.options-compact .btn {
    font-weight: 500;
    letter-spacing: normal;
}

/* Blender's toolbar/panel buttons are flat - a faint fill (barely
   distinct from the panel itself) with NO outline in their resting
   state, only gaining a visible border/highlight on hover or when
   toggled active. Bootstrap's stock .btn-outline-secondary is the
   opposite (a full 1px border always visible, transparent fill) - the
   single biggest reason this still reads as "a web form" rather than
   "a tool panel." Restated via the same --bs-btn-* custom-property
   mechanism .btn-primary/.btn-outline-primary already use above
   (Bootstrap bakes literal colors onto these per variant, so overriding
   the root --bs-secondary token alone has no effect). */
.options-compact .btn-outline-secondary {
    --bs-btn-color: var(--text-primary);
    --bs-btn-bg: var(--surface-2);
    --bs-btn-border-color: transparent;
    --bs-btn-hover-color: var(--text-primary);
    --bs-btn-hover-bg: var(--surface-2);
    --bs-btn-hover-border-color: var(--border-strong);
    --bs-btn-active-color: var(--accent-400);
    --bs-btn-active-bg: rgba(var(--accent-rgb), 0.18);
    --bs-btn-active-border-color: var(--accent-500);
    --bs-btn-focus-shadow-rgb: var(--accent-rgb);
    --bs-btn-disabled-color: var(--text-muted);
    --bs-btn-disabled-bg: transparent;
    --bs-btn-disabled-border-color: transparent;
}

/* Same "flat, not bordered" idea as the buttons above, applied to fields -
   Bootstrap's default border-color (--border-strong) is the same weight
   whether the field sits in a roomy form or a dense toolbar; against
   this sidebar's identical-color panel background it's the field's ONLY
   visual definition, so it has to stay fairly visible - Blender solves
   this differently, giving fields a darker, recessed fill (looks "sunken"
   into the panel) so the boundary reads from the fill contrast instead of
   a bright outline, and the border itself can drop to barely-there. */
.options-compact .form-select,
.options-compact .form-control {
    background-color: var(--surface-0);
    border-color: var(--border-subtle);
}

.options-compact .form-select-sm {
    font-size: 0.6875rem;
    border-radius: 0.25rem;
    /* Right side stays roomy - the base .form-select's own dropdown-arrow
       icon (a background-image, not a real child element) is positioned
       at a fixed offset from the right edge regardless of padding, so a
       uniformly tight padding here would visually collide with it. Fixed
       in rem (root-relative), not em, so it stays anchored to that same
       pixel offset regardless of how small this rule's own font-size
       gets - only the other 3 sides track the tighter scale. */
    padding: 0.15rem 1.6rem 0.15rem 0.35rem;
}

.options-compact .input-group-sm > .form-control,
.options-compact .input-group-sm > .input-group-text,
.options-compact .form-control-sm {
    font-size: 0.6875rem;
    border-radius: 0.25rem;
    padding: 0.15rem 0.35rem;
}

.options-compact .input-group-sm > .input-group-text {
    background-color: var(--surface-2);
    border-color: var(--border-subtle);
    color: var(--text-muted);
}
