/* Isometric House Builder — plain CSS, no build step, no framework. */

:root {
  --bg: #eef1f5;
  --panel: #ffffff;
  --ink: #1d2733;
  --ink-soft: #5a6b7d;
  --line: #d8e0e8;
  --accent: #c8663c;
  --accent-soft: #f6e7e0;
  --focus: #2f6fb5;
  --danger: #b3392b;
  --radius: 9px;
  --shadow: 0 1px 2px rgba(16, 30, 45, .06), 0 6px 18px rgba(16, 30, 45, .07);
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #10161d;
    --panel: #18212b;
    --ink: #e6edf4;
    --ink-soft: #93a4b5;
    --line: #2a3744;
    --accent: #e0794c;
    --accent-soft: #33231c;
    --focus: #5fa4e8;
    --shadow: 0 1px 2px rgba(0, 0, 0, .4), 0 6px 18px rgba(0, 0, 0, .35);
  }
}

* { box-sizing: border-box; }

body {
  margin: 0;
  /* A definite height, not a minimum.
     With min-height the body grows to fit its content, so `flex: 1` on the
     layout has no upper bound to distribute and the grid row resolves against
     the tallest column instead of the viewport. The side columns then stop
     scrolling and stretch the whole page — which is what pushed the drawings
     far below the fold once the inspector gained a panel. */
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  background: var(--bg);
  color: var(--ink);
  font: 14px/1.45 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}

button, select, input {
  font: inherit;
  color: inherit;
}

button {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 6px 11px;
  cursor: pointer;
}
button:hover { border-color: var(--ink-soft); }
button:focus-visible, select:focus-visible, input:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 1px;
}
button.primary { background: var(--accent); border-color: var(--accent); color: #fff; }
button.primary:hover { filter: brightness(1.06); }
button.danger { background: transparent; border-color: var(--danger); color: var(--danger); width: 100%; margin-top: 10px; }
button:disabled { opacity: .45; cursor: default; }

/* ---------- app bar ---------- */

.app-bar {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 14px;
  background: var(--panel);
  border-bottom: 1px solid var(--line);
  flex-wrap: wrap;
}
.brand { display: flex; align-items: center; gap: 9px; font-weight: 620; }
.brand-mark {
  width: 22px; height: 22px; border-radius: 5px;
  background:
    linear-gradient(140deg, var(--accent) 0 50%, #e9c98d 50% 100%);
}
.brand-name { white-space: nowrap; }
.project-name {
  flex: 1 1 140px;
  min-width: 110px;
  max-width: 280px;
  padding: 6px 10px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--bg);
}
.app-actions { display: flex; gap: 6px; margin-left: auto; flex-wrap: wrap; }
.sep { width: 1px; background: var(--line); margin: 2px 3px; }

/* ---------- layout ---------- */

.layout {
  flex: 1;
  display: grid;
  grid-template-columns: 168px minmax(0, 1fr) 290px;
  /* Rows must be allowed to shrink below their content, otherwise a tall
     inspector stretches the whole layout past the viewport instead of
     scrolling inside its own column. */
  grid-template-rows: minmax(0, 1fr);
  gap: 10px;
  padding: 10px;
  min-height: 0;
}

.tools, .inspector {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 10px;
  overflow-y: auto;
  box-shadow: var(--shadow);
}

.stage {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  /* Same rule as .layout, and for the same reason: an auto row sizes itself to
     its content, and a view whose height is 100% of an auto row has nothing to
     resolve against. The panel then grows and the drawing is laid out inside a
     box far taller than what is on screen. */
  grid-template-rows: minmax(0, 1fr);
  gap: 10px;
  min-height: 0;
}

.view {
  display: flex;
  flex-direction: column;
  min-height: 0;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: var(--shadow);
  min-height: 0;
}
.view-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 11px;
  border-bottom: 1px solid var(--line);
  flex-wrap: wrap;
}
.view-head h2 { margin: 0; font-size: 13px; font-weight: 620; }
.view-hint { margin: 0; font-size: 12px; color: var(--ink-soft); }
.view-tools {
  margin-left: auto; display: flex; align-items: center; gap: 5px;
  flex-wrap: wrap; justify-content: flex-end;
}
.view-tools button { padding: 3px 8px; }
/* Wide enough for « Ouest-Nord-Ouest », and never wrapped: a two-line label
   reflows the whole header every few degrees of orbit. */
.rot-label {
  font-size: 12px; color: var(--ink-soft); min-width: 104px;
  text-align: center; white-space: nowrap;
}
.view-body { flex: 1; min-height: 0; position: relative; }
.iso-canvas { position: absolute; inset: 0; cursor: grab; }
.iso-canvas:active { cursor: grabbing; }
.iso-canvas.panning { cursor: move; }
.view-body svg { display: block; width: 100%; height: 100%; }

/* ---------- tool palette ---------- */

.tool-group { margin-bottom: 4px; }
.tool-list { display: flex; flex-direction: column; gap: 2px; padding: 1px 0 3px; }
/* Dense on purpose: twenty-three tools have to share one column. The touch
   breakpoint below gives them room back. */
.tool {
  text-align: left;
  padding: 3px 8px;
  font-size: 12px;
  border-color: transparent;
  background: transparent;
}
.tool:hover { background: var(--bg); }
.tool[aria-pressed="true"] {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent);
  font-weight: 600;
}

/* ---------- plan view ---------- */

.plan-svg { touch-action: none; cursor: crosshair; }
.plan-grid line { stroke: var(--line); stroke-width: 1; }
.plan-grid line.major { stroke-width: 1.6; }
.plan-grid line.sub { opacity: .45; }
.plan-dims text, .rect-size {
  fill: var(--ink-soft);
  font: 600 11px system-ui, sans-serif;
  text-anchor: middle;
  paint-order: stroke;
  stroke: var(--panel);
  stroke-width: 3px;
}
.cell { fill: #e9c98d; fill-opacity: .55; stroke: none; }
@media (prefers-color-scheme: dark) { .cell { fill: #b08f56; fill-opacity: .5; } }
.edge { stroke: var(--accent); stroke-width: 3.5; stroke-linecap: round; }
.opening { stroke: var(--focus); stroke-width: 6; stroke-linecap: butt; cursor: pointer; }
.opening-door { stroke: #6a3fbf; }
.opening-garage { stroke: #2b7a6b; }
.opening.selected, .prop.selected, .roof-item.selected { stroke: #111; stroke-width: 3; }
.prop { fill-opacity: .5; stroke-width: 1.4; cursor: pointer; }
.prop-pool { fill: #4fc3e8; stroke: #2fa9d6; }
.prop-terrace, .prop-deck { fill: #dcd7cc; stroke: #b6ada0; }
.prop-path { fill: #cfc9bb; stroke: #b6ada0; }
.prop-tree, .prop-hedge { fill: #5fa855; stroke: #3f7f39; }
.prop-fence { fill: #d9cfbf; stroke: #a9a093; }
.prop-muret { fill: #b9a892; stroke: #8d7f6c; fill-opacity: .85; }
.prop-gate { fill: #ffffff; stroke: #6b7c8c; fill-opacity: .95; }
.run-preview { stroke: var(--accent); stroke-width: 5; stroke-linecap: round; opacity: .75; }
.run-gate { stroke: #7f9ab5; }
.prop-car { fill: #d94f4f; stroke: #9e3535; }
.roof-item { fill: #2f4a72; fill-opacity: .55; stroke: #1d2f4a; stroke-width: 1.4; cursor: pointer; }
.roof-chimney { fill: #8c8880; }
.rect-preview { fill: var(--accent); fill-opacity: .25; stroke: var(--accent); stroke-width: 1.5; }
.rect-preview.erase { fill: var(--danger); stroke: var(--danger); }

/* ---------- iso view ---------- */

.hit-layer path { cursor: pointer; }
.selection-outline {
  stroke: #111;
  stroke-width: 2;
  stroke-dasharray: 5 4;
  pointer-events: none;
}
@media (prefers-color-scheme: dark) { .selection-outline { stroke: #fff; } }

/* ---------- compasses ---------- */

.plan-compass, .iso-compass { pointer-events: none; }
.plan-compass circle, .iso-compass circle { fill: var(--panel); stroke: var(--line); }
.plan-compass line, .iso-compass line { stroke: var(--ink-soft); stroke-width: 1.5; }
.plan-compass path { fill: var(--ink-soft); }
.plan-compass text, .iso-compass text {
  fill: var(--ink-soft);
  font: 600 10px system-ui, sans-serif;
  text-anchor: middle;
}

/* ---------- inspector ---------- */

/* ---------- collapsible panels ---------- */

/* Both columns use the same disclosure: the left one folds tool families, the
   right one folds settings. One idiom, learned once. */
.panel { margin-bottom: 2px; }
.panel-title {
  display: flex;
  align-items: baseline;
  gap: 6px;
  margin: 0;
  padding: 5px 6px;
  border-radius: 6px;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--ink-soft);
  cursor: pointer;
  user-select: none;
  list-style: none;
}
.panel-title::-webkit-details-marker { display: none; }
/* A triangle drawn from a border, so there is no font or image to load. */
.panel-title::before {
  content: "";
  flex: 0 0 auto;
  width: 0; height: 0;
  border: 4px solid transparent;
  border-left-color: currentColor;
  transform-origin: 2px 50%;
  transition: transform .12s ease;
}
details[open] > .panel-title::before { transform: rotate(90deg); }
.panel-title:hover { background: var(--bg); color: var(--ink); }
.panel-name {
  flex: 0 1 auto;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.panel-badge {
  flex: 1 1 auto;
  min-width: 0;
  text-align: right;
  font-size: 10px;
  font-weight: 400;
  text-transform: none;
  letter-spacing: 0;
  opacity: .75;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
details[open] > .panel-title > .panel-badge { opacity: 0; }
.panel-body { padding: 4px 6px 10px; }

/* The family a run of sections belongs to: selection, building, project, view. */
.panel-group {
  margin: 12px 0 4px;
  padding-top: 10px;
  border-top: 1px solid var(--line);
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--ink-soft);
}
.panel-group:first-child { margin-top: 0; padding-top: 0; border-top: none; }
.panel-empty {
  margin: 0 0 4px;
  padding: 8px 6px;
  font-size: 12px;
  color: var(--ink-soft);
}

.panel-selected {
  background: var(--accent-soft);
  border: 1px solid var(--accent);
  border-radius: var(--radius);
}
.panel-block { padding: 4px 9px 9px; margin-bottom: 2px; }
/* The selection block does not fold, so it must not wear a disclosure arrow. */
.panel-block .panel-title { cursor: default; }
.panel-block .panel-title::before { display: none; }
.panel-selected .panel-title { color: var(--accent); }
.panel-selected .panel-title:hover { background: transparent; color: var(--accent); }
.export-link { margin-top: 4px; }
.field { display: block; margin-bottom: 9px; }
.field-label { display: block; font-size: 12px; margin-bottom: 3px; }
.field-hint { display: block; font-size: 11px; color: var(--ink-soft); margin-top: 2px; }
.field select, .field input[type="number"] {
  width: 100%;
  padding: 5px 8px;
  border: 1px solid var(--line);
  border-radius: 7px;
  background: var(--bg);
}
.field input[type="checkbox"] { width: 16px; height: 16px; accent-color: var(--accent); }
.slider { display: flex; align-items: center; gap: 8px; }
.slider input[type="range"] { flex: 1; min-width: 0; accent-color: var(--accent); }
.slider-value {
  font-variant-numeric: tabular-nums;
  font-size: 12px;
  color: var(--ink-soft);
  min-width: 52px;
  text-align: right;
}

.building-list { display: flex; flex-direction: column; gap: 4px; margin: 8px 0 4px; }
.building-row {
  display: flex; flex-direction: column; gap: 1px;
  text-align: left; padding: 6px 9px; font-size: 12px;
}
.building-row.active { border-color: var(--accent); background: var(--accent-soft); }
.building-name { font-weight: 600; }
.building-meta { font-size: 11px; color: var(--ink-soft); }
.roof-fields { margin-top: 2px; }
.field input[type="text"] {
  width: 100%; padding: 5px 8px; border: 1px solid var(--line);
  border-radius: 7px; background: var(--bg);
}
.cell.inactive { fill-opacity: .22; }
.edge.inactive { stroke: var(--ink-soft); stroke-width: 2; }

.colour-group { margin: 10px 0 4px; }
.colour-group-title { font-size: 11px; color: var(--ink-soft); }
.colour-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 4px 8px;
  margin-top: 4px;
}
.colour-cell { display: flex; align-items: center; gap: 6px; font-size: 12px; min-width: 0; }
.colour-cell span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.colour-cell input[type="color"] {
  width: 26px;
  height: 20px;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 5px;
  background: none;
  cursor: pointer;
  flex: none;
}
button.subtle { width: 100%; margin-top: 10px; font-size: 12px; }
.field-static { font-size: 13px; font-variant-numeric: tabular-nums; }

/* ---------- dialog and toast ---------- */

.dialog {
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 18px;
  background: var(--panel);
  color: var(--ink);
  max-width: 400px;
  box-shadow: var(--shadow);
}
.dialog::backdrop { background: rgba(10, 18, 26, .45); }
.dialog h2 { margin: 0 0 4px; font-size: 16px; }
.dialog-lead { margin: 0 0 14px; font-size: 12px; color: var(--ink-soft); }
.dialog-actions { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 12px; }
.dialog-status { min-height: 18px; font-size: 12px; color: var(--ink-soft); margin: 10px 0 0; }
.dialog-close { margin: 12px 0 0; padding: 0; display: flex; justify-content: flex-end; }

.toast {
  position: fixed;
  left: 50%;
  bottom: 22px;
  transform: translateX(-50%) translateY(16px);
  background: #1d2733;
  color: #fff;
  padding: 9px 15px;
  border-radius: 999px;
  font-size: 13px;
  opacity: 0;
  pointer-events: none;
  transition: opacity .18s, transform .18s;
  z-index: 40;
}
.toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }

.dialog-wide { width: min(1120px, 94vw); max-width: none; }
.gallery-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 10px;
  max-height: 66vh;
  overflow-y: auto;
  padding: 2px;
}
.gallery-card {
  display: flex;
  flex-direction: column;
  gap: 3px;
  text-align: left;
  padding: 8px;
  border-radius: var(--radius);
  background: var(--panel);
  border: 1px solid var(--line);
}
.gallery-card:hover { border-color: var(--accent); background: var(--accent-soft); }
.gallery-thumb { display: block; background: var(--bg); border-radius: 7px; overflow: hidden; }
.gallery-thumb svg { display: block; width: 100%; height: auto; }
.gallery-thumb-empty {
  display: grid;
  place-items: center;
  aspect-ratio: 260 / 176;
  font-size: 30px;
  color: var(--ink-soft);
}
.gallery-name { font-weight: 620; font-size: 13px; }
.gallery-note { font-size: 11.5px; color: var(--ink-soft); line-height: 1.35; }

/* ---------- narrow screens ---------- */

@media (max-width: 1100px) {
  .layout {
    grid-template-columns: 148px minmax(0, 1fr);
    grid-template-rows: minmax(0, 1fr) auto;
  }
  /* Full width and short: one column of settings across a metre of screen
     wastes the space it just gained. The sections flow into columns instead. */
  .inspector {
    grid-column: 1 / -1;
    max-height: 40vh;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
    gap: 0 16px;
    align-content: start;
  }
  .inspector .panel-group { grid-column: 1 / -1; }
  .inspector .panel, .inspector .panel-empty { break-inside: avoid; }
}
@media (max-width: 820px) {
  /* Stacked on a phone: let the page scroll normally again. */
  body { height: auto; min-height: 100vh; overflow: auto; }
  .layout { grid-template-columns: 1fr; grid-template-rows: auto auto auto; }
  .view-body { height: 60vh; }
  .tools { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 10px; }
  .tool-group { margin-bottom: 0; }
  .tools .panel-group { grid-column: 1 / -1; }
  .tool { padding: 7px 9px; font-size: 13px; }
  .stage { grid-template-columns: 1fr; }
  .view-body { min-height: 320px; }
}

/* ---------- framing ---------- */

/* The zone as drawn, and the margin the camera actually gets. Dashed rather
   than filled: it is an annotation over the plan, not another object on it. */
.focus-zone {
  fill: color-mix(in srgb, var(--focus) 10%, transparent);
  stroke: var(--focus);
  stroke-width: 1.5;
  stroke-dasharray: 6 4;
}
.focus-margin {
  fill: none;
  stroke: var(--focus);
  stroke-width: 1;
  stroke-dasharray: 2 5;
  opacity: 0.55;
}
.focus-zone.drawing { fill: color-mix(in srgb, var(--focus) 16%, transparent); }

.view-row { display: flex; gap: 4px; align-items: stretch; }
.view-row .building-row { flex: 1; }
.icon-button {
  flex: 0 0 auto;
  width: 30px;
  font-size: 16px;
  line-height: 1;
  color: var(--ink-soft);
}
.icon-button:hover { color: var(--danger); }

/* ---------- navigation pad ---------- */

/* Sits on the drawing, opposite the compass. Everything the mouse can do to
   the view has a button here — the gestures are quicker, but a gesture nobody
   knows about is a feature nobody has. */
.view-nav {
  position: absolute;
  right: 10px;
  bottom: 10px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  padding: 6px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: color-mix(in srgb, var(--panel) 86%, transparent);
  box-shadow: var(--shadow);
}
.nav-modes { display: flex; gap: 2px; }
.nav-modes button {
  padding: 3px 7px;
  font-size: 10px;
  border-color: transparent;
  background: transparent;
  color: var(--ink-soft);
}
.nav-modes button[aria-pressed="true"] {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent);
  font-weight: 600;
}
.nav-pad {
  display: grid;
  grid-template-columns: repeat(3, 26px);
  grid-template-rows: repeat(3, 26px);
  gap: 2px;
}
.nav-pad .nav-up { grid-area: 1 / 2; }
.nav-pad .nav-left { grid-area: 2 / 1; }
.nav-pad .nav-fit { grid-area: 2 / 2; }
.nav-pad .nav-right { grid-area: 2 / 3; }
.nav-pad .nav-down { grid-area: 3 / 2; }
.nav-zoom { display: flex; gap: 2px; }
.view-nav .nav-btn {
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  padding: 0;
  border-color: transparent;
  background: transparent;
  color: var(--ink-soft);
}
.view-nav .nav-btn:hover { background: var(--bg); color: var(--ink); }
.view-nav .nav-btn svg { width: 15px; height: 15px; display: block; }
.nav-up svg { transform: rotate(0deg); }
.nav-down svg { transform: rotate(180deg); }
.nav-left svg { transform: rotate(-90deg); }
.nav-right svg { transform: rotate(90deg); }

@media (max-width: 820px) {
  /* The pad would cover a third of a phone screen; the gestures still work. */
  .view-nav { display: none; }
}

/* A link that has to sit among buttons without pretending to be one. */
.app-link {
  align-self: center;
  padding: 5px 8px;
  border-radius: 8px;
  color: var(--ink-soft);
  text-decoration: none;
  font-size: 13px;
}
.app-link:hover { background: var(--bg); color: var(--ink); }
