/*
 * Engelsen Frame Visualizer — public stylesheet.
 *
 * Deliberately quieter and warmer than the internal dashboard: this is a tool a
 * frame shop turns toward a customer, so the artwork should carry the screen and
 * the chrome should recede. Nothing here implies a purchase flow.
 */

:root {
  --ef-ink: #1f2937;
  --ef-ink-soft: #6b7280;
  --ef-line: #e5e2dc;
  --ef-panel: #ffffff;
  --ef-bg: #f6f4f0;
  --ef-accent: #8a6a3b;
  --ef-accent-soft: #f0e8da;
  --ef-warn: #9a3412;
  --ef-radius: 10px;
  --ef-shadow: 0 1px 2px rgba(31, 41, 55, .05), 0 8px 24px rgba(31, 41, 55, .06);
}

* { box-sizing: border-box; }

body.ef-body {
  margin: 0;
  background: var(--ef-bg);
  color: var(--ef-ink);
  font: 15px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
}

/* ── Header / footer ─────────────────────────────────────────────────────── */

.ef-header {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: .5rem 1.5rem;
  padding: 1.15rem 1.5rem;
  background: var(--ef-panel);
  border-bottom: 1px solid var(--ef-line);
}

.ef-header__brand { display: flex; align-items: baseline; gap: .55rem; }

.ef-header__mark {
  font-size: 1.15rem;
  font-weight: 700;
  letter-spacing: .01em;
}

.ef-header__sub {
  font-size: .9rem;
  color: var(--ef-ink-soft);
  border-left: 1px solid var(--ef-line);
  padding-left: .6rem;
}

.ef-header__note {
  margin: 0;
  font-size: .85rem;
  color: var(--ef-ink-soft);
}

.ef-footer {
  max-width: 1240px;
  margin: 0 auto;
  padding: 0 1.5rem 2.5rem;
}

.ef-footer p {
  margin: 0;
  font-size: .8rem;
  line-height: 1.6;
  color: var(--ef-ink-soft);
  max-width: 62ch;
}

/* ── Layout ──────────────────────────────────────────────────────────────── */

.ef-layout {
  max-width: 1240px;
  margin: 0 auto;
  padding: 1.5rem;
  display: grid;
  grid-template-columns: minmax(0, 1.35fr) minmax(320px, 1fr);
  gap: 1.5rem;
  align-items: start;
}

/* Embed uses the same flowing page as /visualizer. Do not lock or stretch to
   the iframe height — that left a hole under the frame and hid the mouldings. */
.ef-embed .ef-layout {
  height: auto;
  padding: 1rem;
  gap: 1rem;
  align-items: start;
}
.ef-embed .ef-stage,
.ef-embed .ef-controls {
  height: auto;
  overflow: visible;
}
.ef-embed .ef-stage { position: static; }
.ef-stage__preview { display: block; }
.ef-stage__canvas { height: auto; flex: none; }

@media (max-width: 900px) {
  .ef-layout { grid-template-columns: 1fr; }
}

/* ── Stage ───────────────────────────────────────────────────────────────── */

.ef-stage {
  position: sticky;
  top: 1.5rem;
  background: var(--ef-panel);
  border: 1px solid var(--ef-line);
  border-radius: var(--ef-radius);
  box-shadow: var(--ef-shadow);
  padding: 1.25rem;
}

@media (max-width: 900px) {
  .ef-stage { position: static; }
}

.ef-stage__canvas { position: relative; width: 100%; }
.ef-stage__canvas canvas { display: block; width: 100%; border-radius: 6px; }

.ef-stage__photo {
  display: none;
  position: absolute;
  inset: 0;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  padding: 1.25rem;
  background: #f7f7f7;
  border-radius: 6px;
}

.ef-stage__canvas.is-photo canvas { visibility: hidden; }
.ef-stage__canvas.is-photo .ef-stage__photo { display: flex; }

.ef-stage__photo img {
  display: block;
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  object-fit: contain;
}

.ef-stage__photo-img--corner,
.ef-stage__photo-img--angle {
  border-radius: 4px;
}

.ef-stage__tools {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .55rem 1.15rem;
  margin-top: .4rem;
}

.ef-seg {
  display: inline-flex;
  border: 1px solid var(--ef-line);
  border-radius: 8px;
  overflow: hidden;
  background: #fff;
}

.ef-seg__btn {
  margin: 0;
  padding: .38rem .75rem;
  border: 0;
  background: transparent;
  color: var(--ef-ink);
  font: inherit;
  font-size: .82rem;
  font-weight: 600;
  cursor: pointer;
}

.ef-seg__btn + .ef-seg__btn { border-left: 1px solid var(--ef-line); }

.ef-seg__btn.is-selected {
  background: var(--ef-accent);
  color: #fff;
}

.ef-seg__btn:disabled {
  color: var(--ef-ink-soft);
  cursor: default;
  opacity: .55;
}

.ef-stage__dims {
  margin: 0;
  font-size: .82rem;
  font-weight: 500;
  color: var(--ef-ink-soft);
}

.ef-stage__dims[hidden] { display: none !important; }

.ef-stage__summary {
  margin: 1rem 0 0;
  font-size: .9rem;
  line-height: 1.6;
  color: var(--ef-ink);
}

.ef-specs { margin-top: 1rem; }

.ef-spec-list {
  margin: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: .1rem 1.25rem;
  border-top: 1px solid var(--ef-line);
  padding-top: .85rem;
}

.ef-spec {
  display: flex;
  justify-content: space-between;
  gap: .75rem;
  padding: .3rem 0;
  border-bottom: 1px dotted var(--ef-line);
}

.ef-spec dt { font-size: .8rem; color: var(--ef-ink-soft); }

.ef-spec dd {
  margin: 0;
  font-size: .82rem;
  font-weight: 600;
  text-align: right;
}

.ef-spec__sub { font-weight: 400; color: var(--ef-ink-soft); }

.ef-note {
  margin: .85rem 0 0;
  padding: .65rem .8rem;
  background: var(--ef-accent-soft);
  border-radius: 8px;
  font-size: .78rem;
  line-height: 1.55;
  color: #6b5326;
}

/* ── Control panels ──────────────────────────────────────────────────────── */

.ef-controls { display: flex; flex-direction: column; gap: 1rem; min-width: 0; }

.ef-panel {
  background: var(--ef-panel);
  border: 1px solid var(--ef-line);
  border-radius: var(--ef-radius);
  box-shadow: var(--ef-shadow);
  padding: 1.1rem 1.15rem;
}

.ef-panel__title {
  margin: 0 0 .85rem;
  font-size: .75rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--ef-ink-soft);
}

.ef-hint {
  margin: .5rem 0 0;
  font-size: .78rem;
  line-height: 1.5;
  color: var(--ef-ink-soft);
}

.ef-warn {
  margin: .6rem 0 0;
  font-size: .8rem;
  font-weight: 500;
  color: var(--ef-warn);
}

/* ── Fields ──────────────────────────────────────────────────────────────── */

.ef-field-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: .75rem;
  margin-top: 1rem;
}

.ef-field { min-width: 0; }
.ef-field + .ef-field { margin-top: 0; }
.ef-panel > .ef-field + .ef-field { margin-top: .9rem; }

.ef-field label,
.ef-field__label {
  display: block;
  margin-bottom: .35rem;
  font-size: .78rem;
  font-weight: 600;
  color: var(--ef-ink);
}

.ef-field input[type="number"],
.ef-field select,
.ef-picker-tools input,
.ef-picker-tools select {
  width: 100%;
  padding: .5rem .6rem;
  border: 1px solid var(--ef-line);
  border-radius: 7px;
  background: #fff;
  color: var(--ef-ink);
  font: inherit;
  font-size: .9rem;
}

.ef-field input:focus,
.ef-field select:focus,
.ef-picker-tools input:focus,
.ef-picker-tools select:focus {
  outline: none;
  border-color: var(--ef-accent);
  box-shadow: 0 0 0 3px rgba(138, 106, 59, .14);
}

.ef-inch {
  display: grid;
  grid-template-columns: 1fr 1fr auto;
  gap: .4rem;
  align-items: center;
}

.ef-inch select {
  width: 100%;
  min-width: 0;
}

.ef-inch span {
  font-size: .78rem;
  color: var(--ef-ink-soft);
  padding-right: .15rem;
}

/* ── Upload ──────────────────────────────────────────────────────────────── */

.ef-upload-pair {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: .55rem;
}

.ef-upload {
  display: flex;
  align-items: center;
  gap: .7rem;
  min-width: 0;
  padding: .85rem 1rem;
  border: 1.5px dashed #cfc8bb;
  border-radius: 9px;
  background: #fbfaf8;
  cursor: pointer;
  transition: border-color .15s, background .15s;
}

button.ef-upload {
  width: 100%;
  font: inherit;
  text-align: left;
  color: inherit;
}

.ef-upload:hover { border-color: var(--ef-accent); background: #fdfbf7; }

.ef-upload__icon {
  flex: 0 0 auto;
  width: 26px;
  height: 26px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--ef-accent-soft);
  color: var(--ef-accent);
  font-size: 1rem;
  font-weight: 700;
}

.ef-upload__label {
  font-size: .85rem;
  color: var(--ef-ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ef-link-btn {
  margin-top: .5rem;
  padding: 0;
  border: 0;
  background: none;
  color: var(--ef-accent);
  font: inherit;
  font-size: .8rem;
  text-decoration: underline;
  cursor: pointer;
}

/* ── Switches ────────────────────────────────────────────────────────────── */

.ef-switch {
  display: flex;
  align-items: center;
  gap: .55rem;
  font-size: .88rem;
  font-weight: 500;
  cursor: pointer;
}

.ef-switch input { width: 17px; height: 17px; accent-color: var(--ef-accent); cursor: pointer; }

.ef-switch--sm { margin-top: .9rem; font-size: .82rem; font-weight: 400; }

#ef-mat-options > .ef-field { margin-top: .9rem; }

/* ── Mat swatches ────────────────────────────────────────────────────────── */

.ef-swatches {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(34px, 1fr));
  gap: .4rem;
}

.ef-swatch {
  aspect-ratio: 1;
  border: 1px solid rgba(31, 41, 55, .12);
  border-radius: 6px;
  padding: 0;
  cursor: pointer;
  transition: transform .12s, box-shadow .12s;
}

.ef-swatch--light { border-color: rgba(31, 41, 55, .22); }

.ef-swatch:hover { transform: translateY(-1px); }

.ef-swatch.is-selected {
  box-shadow: 0 0 0 2px #fff, 0 0 0 4px var(--ef-accent);
}

.ef-swatch-name {
  margin: .55rem 0 0;
  font-size: .78rem;
  color: var(--ef-ink-soft);
}

/* ── Moulding picker ─────────────────────────────────────────────────────── */

.ef-panel--grow { display: flex; flex-direction: column; min-height: 0; }

.ef-picker-tools {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: .5rem;
}

.ef-picker-tools select { max-width: 16rem; }

.ef-picker-count {
  margin: .6rem 0 .5rem;
  font-size: .75rem;
  color: var(--ef-ink-soft);
}

/* Both thumbnail sources are roughly square - Odoo's corner samples exactly so,
   the archive's cut-out sticks between 0.55:1 and 0.95:1 - so the tile is square
   and the columns are narrow enough that three still fit the side panel. */
.ef-picker {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
  gap: .5rem;
  max-height: 420px;
  overflow-y: auto;
  padding: .15rem .3rem .3rem .15rem;
}

.ef-chip {
  display: flex;
  flex-direction: column;
  gap: .4rem;
  padding: .4rem;
  border: 1.5px solid var(--ef-line);
  border-radius: 8px;
  background: #fff;
  cursor: pointer;
  text-align: left;
  font: inherit;
  transition: border-color .12s, box-shadow .12s;
}

.ef-chip:hover { border-color: #c3b69f; }

.ef-chip.is-selected {
  border-color: var(--ef-accent);
  box-shadow: 0 0 0 2px rgba(138, 106, 59, .18);
}

/* Every tile is keyboard-reachable, including the unselectable ones, so focus has
   to be visible on all of them — a ring is the only thing telling a keyboard user
   which tile the label they just heard belongs to. */
.ef-chip:focus-visible {
  outline: 2px solid var(--ef-accent);
  outline-offset: 1px;
}

/* ── Tiles with no tiling strip ──────────────────────────────────────────────
   Kept in the list and kept focusable, because a shop still wants to know the
   moulding exists; refused as a selection, because the canvas would draw it as a
   neutral gray bevel that reads as a real pale frame. Muting alone would look
   like a styling glitch, so the .ef-chip__flag band states it outright. The
   corner sample stays legible through the filter on purpose: the photo is good,
   it is only the strip the renderer tiles that is missing. */
.ef-chip--no-preview {
  /* Fractionally darker than the page behind it, so the tile reads as a recessed
     well rather than a raised card even before the flag is read. */
  background: #f2efe9;
  border-color: #e4e0d8;
  cursor: default;
}

/* No hover response: the tile must not promise an interaction it will refuse. Must
   restate the resting border, or the base .ef-chip:hover rule would still fire. */
.ef-chip--no-preview:hover { border-color: #e4e0d8; }

/* Desaturated to read as inactive, but only lightly faded. Many of these finishes
   are white or off-white, and a heavier fade erases a pale corner sample against
   the card entirely — which would throw away the one good picture we have of a
   moulding whose whole problem is that we cannot draw it. The flag below, not the
   fade, is what says "unavailable". */
.ef-chip--no-preview .ef-chip__thumb { filter: grayscale(.7) opacity(.88); }

.ef-chip--no-preview .ef-chip__sku { color: var(--ef-ink-soft); }

/* An unselectable tile can never carry the selected border, so it shows a ring on
   plain :focus too: on a click that is the only acknowledgement that the press
   landed on something deliberately inert rather than on nothing. Ink rather than
   the accent, so a focus ring is never mistaken for a selection. */
.ef-chip--no-preview:focus,
.ef-chip--no-preview:focus-visible {
  outline: 2px solid var(--ef-ink);
  outline-offset: 1px;
}

/* A band in normal flow, immediately above the SKU. Not an overlay, for two
   reasons: it must not cover the corner sample, which is the one good picture we
   have of this moulding; and the picker is a scrolling grid, so an overlay pinned
   over the photo is the first thing a part-scrolled row clips, leaving a grey tile
   with its own explanation cut away. Sitting directly above the SKU makes that
   impossible — the label can only be clipped along with the SKU it belongs to, and
   a tile whose number you cannot read is not one you can act on.
   A sibling of the thumb, so the filter above mutes the photo and not the label. */
.ef-chip__flag {
  padding: .18rem .25rem;
  border-radius: 4px;
  background: rgba(31, 41, 55, .82);
  color: #fff;
  font-size: .62rem;
  font-weight: 700;
  line-height: 1.25;
  letter-spacing: .05em;
  text-transform: uppercase;
  text-align: center;
}

/* The fit depends on what the photo is, so each source sets its own below. There
   is no default: getting this wrong either crops the subject out or shrinks it to
   a sliver, and both have happened. */
.ef-chip__thumb {
  display: block;
  aspect-ratio: 1 / 1;
  border-radius: 5px;
  background-color: #efece6;
  background-position: center;
  background-repeat: no-repeat;
}

/* Odoo's corner sample: a square marketing photo of a mitred corner, with its own
   styled background. Filling the tile is safe because the aspect ratios match, and
   the hairline keeps a pale photo from bleeding into the white card. */
.ef-chip__thumb--corner {
  background-size: cover;
  box-shadow: inset 0 0 0 1px rgba(31, 41, 55, .09);
}

/* The archive's angled stick: a cut-out on transparency, and its aspect ratio
   varies by nearly 2x across the archive. Contain rather than cover, because a
   cover crop lops the ends off the tall ones - and the letterboxing is invisible
   against the card, the cut-out having no background of its own. */
.ef-chip__thumb--angle {
  background-size: contain;
}

/* Fallback: no thumbnail, so the tiling strip stands in. Cover turns a 10:1 strip
   into a flat swatch of the finish, which is a fair likeness; contain would draw
   it as a hairline. */
.ef-chip__thumb--texture {
  background-size: cover;
}

/* Mirrors the renderer's neutral "representative" frame for SKUs with no photo. */
.ef-chip__thumb--none {
  background-image: linear-gradient(135deg, #d8d8d8 0%, #cccccc 50%, #bdbdbd 100%);
}

.ef-chip__body { display: flex; flex-direction: column; gap: .1rem; min-width: 0; }

.ef-chip__sku {
  font-size: .8rem;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ef-chip__meta { font-size: .7rem; color: var(--ef-ink-soft); }

/* ── Phone layout ────────────────────────────────────────────────────────── */

@media (max-width: 700px) {
  .ef-header { padding: .75rem 1rem; }
  .ef-header__note { display: none; }
  .ef-layout { padding: .7rem; gap: .7rem; }
  .ef-stage { padding: .7rem; }
  .ef-stage__preview {
    position: sticky;
    top: 0;
    z-index: 3;
    background: var(--ef-panel);
  }
  .ef-stage__summary { font-size: .82rem; margin-top: .65rem; }
  .ef-specs { margin-top: .65rem; }
  .ef-panel { padding: .85rem .9rem; }
  .ef-upload-pair { grid-template-columns: 1fr; }
  .ef-upload--phone { display: none; }
}

/* ── Phone inbox modal ───────────────────────────────────────────────────── */

.ef-upload-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .35rem 1rem;
  margin-top: .45rem;
}

.ef-upload-actions .ef-link-btn { margin-top: 0; }

.ef-phone-modal {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 40;
  align-items: center;
  justify-content: center;
  padding: 1.25rem;
  background: rgba(31, 41, 55, .45);
}

.ef-phone-modal.is-open { display: flex; }

.ef-phone-modal__card {
  width: min(100%, 360px);
  padding: 1.25rem 1.3rem 1.15rem;
  border-radius: 12px;
  background: #fff;
  box-shadow: var(--ef-shadow);
}

.ef-phone-modal__card h3 {
  margin: 0 0 .4rem;
  font-size: 1.05rem;
}

.ef-phone-modal__card p {
  margin: 0 0 .85rem;
  font-size: .85rem;
  line-height: 1.5;
  color: var(--ef-ink-soft);
}

.ef-phone-modal__qr {
  display: grid;
  place-items: center;
  margin: 0 auto .85rem;
  width: 220px;
  height: 220px;
  background: #fff;
}

.ef-phone-modal__qr svg { width: 220px; height: 220px; }

.ef-phone-modal__url {
  margin: 0 0 .75rem;
  font-size: .78rem;
  word-break: break-all;
  color: var(--ef-ink);
}

.ef-phone-modal__status {
  margin: 0 0 1rem;
  font-size: .85rem;
  font-weight: 600;
  color: var(--ef-accent);
}

.ef-phone-modal__close {
  width: 100%;
  padding: .55rem .75rem;
  border: 1px solid var(--ef-line);
  border-radius: 8px;
  background: #fff;
  color: var(--ef-ink);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}
