/* =========================================
   Configurator — Shared Component
   Core Make My Plugin

   Base styles for all product configurators.
   Visual language: neutral palette, dark buttons,
   contained flexbox layout.
   ========================================= */

/* --- Container --- */

.core-configurator {
    font-family: var(--font-sans);
    line-height: 1.6;
    color: var(--ink);
    margin: 20px auto 60px;
    width: 100%;
    max-width: none;
}

/* The legacy `.core-interface` / `.core-sidebar` shell (a fixed-height flex
   frame with a 320px scrolling sidebar) was replaced by the stepper layout and
   had no markup left anywhere — deleted with its responsive and
   prefers-contrast satellites (efficiency #222). */

/* --- Section Dividers --- */

.core-section {
    margin-bottom: 10px;
    padding-bottom: 10px;
    border-bottom: 1px solid var(--rule);
}

.core-section:last-child {
    border-bottom: none;
    margin-bottom: 0;
}

.core-section h4 {
    margin: 0 0 15px 0;
    color: var(--ink-soft);
    font-size: var(--fs-14);
    font-weight: var(--fw-regular);
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

/* --- Form Fields ---
   The control layer (`.core-input-group`, field
   labels, `.core-input` / `.core-select` and their focus state, checkbox
   and radio rows, `.core-help-text`, and the whole `.core-segmented`
   family) moved to core-controls.css — a standalone shared primitive the
   room planner can load without the configurator shell (efficiency #228).
   `core-configurator` declares it as a dep, so every configurator gets it
   exactly as before. Don't restate those values here. */

/* --- Pricing Section --- */

.core-pricing {
    background: none;
    border: none;
    border-radius: 0;
    padding: 15px;
}

.core-pricing h4 {
    margin: 0 0 10px 0;
    font-size: var(--fs-14);
    font-weight: var(--fw-regular);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--ink-soft);
}

.core-price-line {
    display: flex;
    justify-content: space-between;
    margin-bottom: 8px;
    font-size: var(--fs-14);
}

.core-price-line:last-child {
    margin-bottom: 0;
}

/* The breakdown panel deliberately has NO total row — the one total on a
   configurator page is the stepper's sticky "Total Inc. VAT" footer
   (inconsistency #56). The old `.core-price-line.core-total` rule went with the
   three duplicate panel totals it styled; don't reintroduce either. */

/* --- Buttons --- */

/* The `.core-btn` family lives in core-controls.css (efficiency #229) — it is
   a control, not configurator shell, and three surfaces that render buttons
   never load this sheet. Don't restate the box model here; add a variant
   there. Only the actions container and the shell's own contextual overrides
   remain below. */

/* Actions container */
.core-actions {
    margin-top: 10px;
}

.core-actions .core-btn + .core-btn {
    margin-top: 10px;
}

/* --- Preview Container --- */

.core-preview-container {
    flex: 1;
    background: var(--core-preview-bg);
    padding: 20px;
    position: relative;
    min-height: 300px;
    display: flex;
    flex-direction: column;
    align-items: stretch;
    justify-content: flex-start;
    overflow: hidden;
    box-sizing: border-box;
}

/* --- Preview toolbar (Design.md §11.6) ------------------------------------
   Two joined groups over the preview, one grammar (signed off 2026-09-25):

     [ 2D │ 3D ] ↻            [ Interior │ Dimensions │ X-ray ]
     top-left: view + camera   top-right: model state → annotation

   `.core-preview-toggle` is a joined segmented button — flat Pebble sections,
   1px Paper dividers, only the group's OUTER corners rounded, no shadow card.
   The tools strip pins top-right on its own. On the modules with a 2D | 3D
   switch (Desk, Door, Panelling, Frame) the view pair is a second
   `.core-preview-toggle` inside `.core-preview-toolbar-left`, a flex row that
   CoreAttachResetButton appends the ↻ chip into, so it lands after the pair. */

.core-preview-toggle {
    position: absolute;
    top: 10px;
    right: 10px;
    z-index: var(--z-raised);
    display: flex;
    border-radius: var(--r-sm);
    overflow: hidden;
}

.core-preview-toolbar-left {
    position: absolute;
    top: 10px;
    left: 10px;
    z-index: var(--z-raised);
    display: flex;
    align-items: center;
    gap: 6px;
}

.core-preview-toolbar-left > .core-preview-toggle {
    position: static;
}

/* TEMPORARY — the staff-only Desk 2D style switch (Render2DStyle.js). Delete
   with that file. */
.core-2d-style-switch {
    position: absolute;
    left: 10px;
    bottom: 10px;
    z-index: var(--z-raised);
    display: flex;
    align-items: center;
    gap: 8px;
}

.core-2d-style-switch > .core-preview-toggle {
    position: static;
}

.core-2d-style-switch__label {
    font-size: var(--fs-12);
    color: var(--ink-muted);
}

.core-2d-style-unit-note {
    position: absolute;
    right: 10px;
    bottom: 10px;
    z-index: var(--z-raised);
    font-size: var(--fs-12);
    color: var(--ink-muted);
    pointer-events: none;
}

/* A cable hole shows the page through it, drawn in the outline's hairline.
   Beats desk-configurator.css's .cable-hole-indicator on specificity. */
.core-preview-container[data-core-2d-style="clean"] .cable-hole-indicator,
.core-preview-container[data-core-2d-style="depth"] .cable-hole-indicator {
    fill: var(--core-preview-bg);
    stroke-width: 1;
    vector-effect: non-scaling-stroke;
}

/* Under Depth the hole's rim is redrawn above the board wall seen down it
   (Render2DStyle addHoleWalls), so the hole's own ring would double it. */
.core-preview-container[data-core-2d-style="depth"] .cable-hole-indicator {
    stroke: none;
}

.core-preview-container.is-3d-mode .core-2d-style-switch,
.core-preview-container.is-3d-mode .core-2d-style-unit-note {
    display: none;
}

/* Box model is set here outright rather than taken from a `.core-btn` size
   rung: every section — and the ↻ chip below, which shares this rule — is a
   fixed 32px (--h-btn-sm, the same height as every other configurator button)
   with the small rung's 13px type and a line-height of 1, so no label or
   glyph can change the strip's height. The markup still carries
   `.core-btn .core-btn--sm .core-btn--inline` for the family's cursor,
   transition and press; this sheet prints after core-controls.css, so the
   equal-specificity declarations below win. Efficiency #233 settled that this
   is its own primitive and not a `.core-segmented` consumer: a view switch
   and a pressed tool keep the Coal invert (§11.6), never the accent fill. */
.core-preview-toggle-btn,
.core-3d-reset-btn {
    box-sizing: border-box;
    align-items: center;
    justify-content: center;
    width: auto;
    height: var(--h-btn-sm);
    min-height: 0;
    padding: 0 var(--sp-3);
    border: 0;
    border-radius: 0;
    background: var(--paper-soft);
    color: var(--ink);
    font-size: var(--fs-13);
    line-height: 1;
    white-space: nowrap;
}

/* One Paper hairline between neighbouring sections — every tool, and the two
   halves of the view pair alike. */
.core-preview-toggle-btn + .core-preview-toggle-btn {
    border-left: 1px solid var(--paper);
}

.core-preview-toggle-btn:hover,
.core-3d-reset-btn:hover {
    background: var(--paper-sunk);
    color: var(--ink);
}

.core-preview-toggle-btn:focus-visible,
.core-3d-reset-btn:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: -2px;
}

/* --- Tool states ---------------------------------------------------------
   The doors, ruler and eye tools share one state grammar, so an engaged tool
   always reads the same way whichever tool it is. Each state is written once
   here for every tool; the satellite sheets (core-dimension-overlay.css,
   core-xray.css) carry no rules of their own for the strip. A new tool
   joins these lists rather than restating them.

   On — filled Coal, the same invert as the selected view (§11.6). */
.core-preview-toggle-btn.active,
.core-dim-toggle-btn[data-dim-tier="detail"],
.core-xray-toggle-btn[data-xray-tier="on"],
.core-xray-toggle-btn[data-xray-tier="all"] {
    background: var(--ink);
    color: var(--paper);
    box-shadow: none;
}

/* On, hovered. The view pair keeps its fill on hover; a tool softens. */
.core-doors-toggle-btn.active:hover,
.core-dim-toggle-btn[data-dim-tier="detail"]:hover,
.core-xray-toggle-btn[data-xray-tier="on"]:hover,
.core-xray-toggle-btn[data-xray-tier="all"]:hover {
    background: var(--ink-soft);
    color: var(--paper);
}

/* Partial — the ruler's "overall" and the eye's "fronts" tier. Sunk and
   outlined rather than filled: engaged, but with somewhere left to go. The
   outline is Ink because Rule Strong is the same stone as the sunk fill and
   would vanish on it. */
.core-dim-toggle-btn[data-dim-tier="overall"],
.core-xray-toggle-btn[data-xray-tier="fronts"] {
    background: var(--paper-sunk);
    color: var(--ink);
    box-shadow: inset 0 0 0 1px var(--ink);
}

/* Every tool is a 3D affordance: hidden by default and unhidden by
   .is-3d-mode on the preview container, which each module's view switcher
   toggles. The doors toggle is also [hidden] by JS when there is nothing to
   open, and that still wins. */
.core-doors-toggle-btn,
.core-dim-toggle-btn,
.core-xray-toggle-btn {
    display: none;
}

.core-preview-container.is-3d-mode .core-doors-toggle-btn:not([hidden]),
.core-preview-container.is-3d-mode .core-dim-toggle-btn,
.core-preview-container.is-3d-mode .core-xray-toggle-btn {
    display: inline-flex;
}

/* Model-state control — "Interior" (core-doors-toggle-btn). Changes what the
   customer is looking AT (doors swing, drawers slide) rather than how, so it
   leads the tools strip on the carcass modules. [hidden] until the config
   has openables (core-carcass-3d.js presence hook) — and then the ruler's
   hairline would draw as a stray rule down the strip's left edge. */
.core-doors-toggle-btn[hidden] + .core-dim-toggle-btn {
    border-left: 0;
}

/* --- Tool labels ---------------------------------------------------------
   Each tool is its label alone (Core_Preview_Glyphs::tool()) — the glyphs
   that led them were removed 2026-09-25 as visual noise. The label stays at
   every width, since without it the button would be blank. No box model of
   its own, so it inherits whatever state colour the button is painting. */
.core-preview-toggle-label {
    white-space: nowrap;
}

/* --- 3D Container --- */

/* No border or radius: the container carries the same --core-preview-bg as the
   .core-preview-container it fills, so a rule around it framed a surface that
   already reads as one piece. `overflow: hidden` stays — it clips the canvas. */
.core-3d-container {
    width: 100%;
    height: 100%;
    min-height: 500px;
    position: relative;
    background: var(--core-preview-bg);
    overflow: hidden;
}

.core-3d-container canvas {
    display: block;
    width: 100% !important;
    height: 100% !important;
}

/* --- 2D Container --- */

/* Shared shell for the 2D technical drawing slot. Mirrors .core-3d-container
   so plugins that toggle between 2D / 3D get the same surface treatment.
   Plugin-specific bits (cursor: grab, dimension-label sizes, SVG fit rules)
   stay in each plugin's stylesheet under its own prefixed class. */
.core-2d-container {
    width: 100%;
    height: 100%;
    min-height: 500px;
    position: relative;
    background: var(--core-preview-bg);
    overflow: hidden;
}

/* Opt-in: centre a drawing that is smaller than the pane and fit it inside.
   Frame and Panelling had each written these two rules under their own
   prefix; Desk and Door size their SVG themselves and don't take it. */
.core-2d-container--centred {
    display: flex;
    align-items: center;
    justify-content: center;
}

.core-2d-container--centred svg {
    max-width: 100%;
    max-height: 100%;
}

/* --- Validation Messages --- */

/* The `.core-validation-messages` card now lives in its own sheet,
   core-validation-messages.css, so non-configurator surfaces (the trade
   application form) can consume it without depending on this whole file
   — efficiency #231. This sheet declares that handle as a style dep, so the
   card is still present on every configurator page. Don't re-add a local
   copy here. */

/* --- Validation Overlay (preview card) --- */

/* The §7.11 card family at preview scale (Design.md §11.6, ruled 2026-09-29):
   a Paper card with the 2px Error left edge, raised one rung so it lifts off
   the model, 13px Ink text. Anchored low and centred rather than over the
   middle of the preview, so the model it is talking about stays visible; the
   bottom offset clears the style step's preview pill (core-style-step.css).
   It was a solid Error box with Paper text dead centre. */
.core-validation-overlay {
    position: absolute;
    left: 50%;
    bottom: var(--sp-12);
    transform: translateX(-50%);
    box-sizing: border-box;
    width: 84%;
    max-height: 40%;
    overflow-y: auto;
    background: var(--paper);
    border-left: 2px solid var(--err);
    border-radius: 0;
    box-shadow: var(--shadow-2);
    color: var(--ink);
    padding: var(--sp-3) var(--sp-4);
    font-size: var(--fs-13);
    font-weight: var(--fw-regular);
    line-height: 1.4;
    text-align: left;
    z-index: var(--z-raised);
    pointer-events: auto;
}

/* Body, colours and the 32px rung all come from `.core-btn .core-btn-secondary
   .core-btn--sm .core-btn--inline` (core-controls.css), which the markup
   carries — the card is Paper now, so the button needs no local recolour. */
.core-validation-fix-btn {
    margin-top: var(--sp-2);
}

/* --- Loading State --- */

.core-loading {
    opacity: 0.6;
    pointer-events: none;
}

.core-loading .core-btn {
    background: var(--rule-strong) !important;
    cursor: not-allowed;
}

/* (`.core-instance-data` was never rendered — each product uses its own
   `.{slug}-instance-data` script tag. Deleted, efficiency #222.) */

/* --- Popup (shared overlay for all plugins) --- */

/* Sheet's per-row cut-out popover is the same surface built by JS rather than
   by Core_Popup, so it joins here instead of re-declaring a drifted copy in
   sheet-configurator.css (efficiency #223). Its anchoring and internal flex
   layout stay in that file. */
/* Chrome (background / border / radius / shadow) comes from `.core-popover`
   in core-modal.css — both elements carry that class in their markup
   (efficiency #230). Only placement and the box model stay here. */
.core-popup,
.sheet-cutout-popover {
    position: absolute;
    padding: 8px;
    z-index: var(--z-overlay);
    min-width: 220px;
    font-family: var(--font-sans);
}

/* The round "×" dismiss button. The body moved to `.core-btn--close` in
   core-controls.css (efficiency #229) — it was never three hosts, it was
   seven, and the other four (Desk's edge-detail remove, the saved-designs
   modal close, Sheet's and Trim's bulk-table remove-row) could not reach a
   body that lived in this sheet. All seven now carry
   `core-btn core-btn--close` in their markup. Positioning is deliberately NOT
   part of the shared body — the hosts sit differently (pinned top-right of the
   popup, in-flow at the end of a flex row, floated above the card) and each
   declares its own, as this one does. */
.core-popup-close {
    position: absolute;
    top: 4px;
    right: 4px;
}

.core-popup-title {
    display: block;
    margin-bottom: 6px;
    padding-right: 20px;
    font-weight: var(--fw-regular);
    font-size: var(--fs-13);
    color: var(--ink);
}

.core-popup-label {
    display: block;
    margin-bottom: 2px;
    font-size: var(--fs-12);
    color: var(--ink-soft);
}

.core-popup-field {
    margin-bottom: 6px;
}

.core-popup-actions {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin-top: 8px;
}

/* (`.core-popup .core-btn { width: 100% }` was restating the family's own
   full-width base. Deleted, efficiency #229.) */

/* --- Clickable dimension labels in 2D preview --- */

.dimension-label--clickable {
    cursor: pointer;
    transition: fill var(--dur-fast) var(--ease);
}

.dimension-label--clickable:hover {
    fill: var(--ink);
}

/* =========================================
   Responsive
   ========================================= */

@media (max-width: 900px) {
    .core-preview-container {
        min-height: clamp(180px, 28vh, 260px);
        padding: 15px;
    }

    .core-preview-toggle {
        top: var(--sp-2);
        right: var(--sp-2);
    }

    .core-preview-toolbar-left {
        top: var(--sp-2);
        left: var(--sp-2);
    }

    .core-validation-overlay {
        width: 92%;
    }
}

@media (max-width: 640px) {
    .core-configurator {
        margin: 10px 0 40px;
    }

    .core-section {
        margin-bottom: 20px;
        padding-bottom: 15px;
    }
}

/* --- Accessibility --- */

/* The forced-contrast pin on `.core-btn-primary` moved to core-controls.css
   with the rest of the family (efficiency #229). */

/* Reduced motion is handled globally — Theme/assets/css/main.css's
   `*, *::before, *::after` reset under `prefers-reduced-motion: reduce`
   zeroes every animation/transition duration with `!important`. */

/* ===========================================================
   3D Preview — "Reset view" chip
   Injected by CoreAttachResetButton() into any preview container
   that has a 3D canvas. Hidden when the container is in 2D mode
   (each module's view switcher toggles .is-3d-mode on it).
   =========================================================== */

/* The chip's box, hover and focus are the tool strip's (shared rule above):
   same Pebble, same fixed 32px, same 13px type, so the ↻ glyph cannot set
   its height — plus a --r-sm radius of its own, since it stands alone rather
   than inside a group. Only the placement and the 2D-mode hide are here. On
   a 3D-only module it pins to the top-left corner; inside the view switch's
   `.core-preview-toolbar-left` row it goes static and follows the pair. */
.core-3d-reset-btn {
    position: absolute;
    top: 10px;
    left: 10px;
    z-index: var(--z-raised);
    margin: 0;
    border-radius: var(--r-sm);
    display: none; /* hidden by default; .is-3d-mode unhides */
}

.core-preview-toolbar-left > .core-3d-reset-btn {
    position: static;
}

/* Tracks the strips' tighter inset on narrow screens (Responsive, above). */
@media (max-width: 900px) {
    .core-3d-reset-btn {
        top: var(--sp-2);
        left: var(--sp-2);
    }
}

.core-preview-container.is-3d-mode .core-3d-reset-btn {
    display: inline-flex;
}

/* (`.core-eb-group` and its two satellites were left behind when the carcass
   edgebanding step moved to the shared per-face renderer — no markup emits the
   class. Deleted, efficiency #222.) */

/* --- Depth-warning note (carcass plugins) --- */
/* Inline note rendered next to a depth-bearing input when the
   user-entered TOTAL EXTERNAL depth would yield a carcass interior
   below the practical-use threshold. Display-only; no clamp. */

.core-depth-warning {
    display: block;
    margin-top: 4px;
    color: var(--warn);
    font-size: var(--fs-12);
    line-height: 1.4;
}

/* --- Dimension clamp note (carcass plugins, D49) --- */
/* Server-rendered under each board-bound width / height / depth input and
   filled by core-carcass-dimension-ceiling.js when it clamps the value to the
   chosen material. Placement only — the chrome is the shared inline
   validation card (inconsistency #95). */

.core-dimension-clamp {
    margin-top: 6px;
}

/* --- Mounting-style note (carcass plugins) --- */
/* JS-created note next to the face-frame enable checkbox while the Inset
   door mounting style is selected (the frame is disabled meanwhile) —
   see mountStyleNote() in cabinet-face-frame.js. */

.core-mount-style-note {
    font-size: var(--fs-12);
    color: var(--ink-muted);
    margin: 4px 0 0;
}

/* --- Handles step (carcass plugins) --- */
/* One card per face-type the unit carries (door / drawer): a handle-type
   select, a 3x3 anchor reference grid (the same idea as Desk's cable-hole grid,
   but labelled rather than lettered — only the hover/active colours are shared),
   X/Y offset inputs, an H/V orientation toggle (rotatable handles only) and
   a drawer-only 1/2 count select. Rendered by Core_Handle_Select; gathered
   into the `handles` POST field by CoreProductNamespace.collectHandlesPost. */

.core-handle-card {
    padding: 12px 0;
}

.core-handle-card + .core-handle-card {
    border-top: 1px solid var(--rule);
    margin-top: 4px;
}

/* `.core-handle-label` joins the one field-label rule in core-controls.css
   (a dep of this sheet). */

.core-handle-controls {
    margin-top: 12px;
    display: flex;
    flex-direction: column;
    gap: 14px;
}

.core-handle-anchor-row {
    display: flex;
    gap: 18px;
    align-items: flex-start;
    flex-wrap: wrap;
}

/* 3x3 anchor reference grid (labelled rows/columns). */
.core-handle-anchor-grid {
    display: inline-flex;
    flex-direction: column;
    gap: 4px;
    flex-shrink: 0;
}

.core-handle-grid-row {
    display: grid;
    grid-template-columns: auto repeat(3, 30px);
    gap: 4px;
    align-items: center;
}

.core-handle-grid-corner {
    width: auto;
}

.core-handle-grid-collabel,
.core-handle-grid-rowlabel {
    font-size: var(--fs-11);
    color: var(--ink-soft);
    text-align: center;
    user-select: none;
}

.core-handle-grid-rowlabel {
    text-align: right;
    padding-right: 4px;
    min-width: 48px;
}

.core-handle-grid-cell {
    width: 30px;
    height: 30px;
    padding: 0;
    background: var(--paper);
    border: 1px solid var(--rule-interactive);
    border-radius: var(--r-sm);
    cursor: pointer;
    transition: all var(--dur-fast) var(--ease);
    box-sizing: border-box;
}

/* Hover / active treatment is shared with Desk's cable-hole reference grid
   (`.desk-grid-cell`, desk-configurator.css). The two grids' box models differ
   — Desk's cells are 28px and carry a letter, Core's are 30px and sit in a
   labelled row — so only the state colours are comma-joined here; Desk adds its
   own text-colour change on top (efficiency #223). */
.core-handle-grid-cell:hover,
.desk-grid-cell:hover {
    background: var(--accent-tint);
    border-color: var(--accent);
}

.core-handle-grid-cell.core-handle-grid-active,
.desk-grid-cell.desk-grid-active {
    background: var(--ink);
    border-color: var(--ink);
}

/* Offset inputs (X / Y, mm). */
.core-handle-offsets {
    display: flex;
    flex-direction: column;
    gap: 8px;
    flex: 1;
    min-width: 160px;
}

.core-handle-sublabel {
    display: block;
    margin-bottom: 4px;
    font-size: var(--fs-12);
    color: var(--ink-soft);
}

.core-handle-offset {
    max-width: 220px;
}

/* Orientation toggle row + drawer count row reuse the radio-group / select
   styles already defined above. */
.core-handle-orientation-row .core-handle-sublabel,
.core-handle-count-row .core-handle-sublabel {
    margin-bottom: 6px;
}

.core-handle-count {
    max-width: 220px;
}

/* Cut-out shape-dimensions block (shown only when a cut-out shape is chosen).
   One numeric input per shape param, built by the page JS. Kept light and
   consistent with the offset fields above. */
.core-handle-dims {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.core-handle-dims-fields {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
}

.core-handle-dim-field {
    display: flex;
    flex-direction: column;
    min-width: 120px;
}

.core-handle-dim {
    max-width: 160px;
}
