/* HEARTH plan drawing: shared by the viewer (index.html) and the tape worksheet (worksheet.html).
   Readable with and without yellow-tinted lenses: meaning is carried by labels, line patterns and
   badges, never by hue alone. Palette: ink, paper, one blue, one orange, greys; blue and orange differ
   in brightness as well as hue.
   Geometry is in plan inches; strokes are screen pixels (vector-effect). Text sizes are set by the
   renderer per build from the current scale (px per plan inch), so labels keep their pixel size while
   the drawing zooms. Level of detail: the page sets lod-far / lod-mid / lod-near on the svg and the
   rules below hide tiny and small feature labels when the plan is far away. */
:root {
  --ink: #1a1a1a;
  --paper: #ffffff;
  --panel: #f4f4f2;
  --floor: #fbfaf6;
  --line: #c9c9c9;
  --grid: #e6e6e6;
  --grid-strong: #c4c4c4;
  --blue: #1f4e9c;
  --blue-soft: #dde7f3;
  --orange: #b35900;
  --orange-soft: #fbe9d9;
  --grey: #5f5f5f;
  --grey-soft: #e9e9e9;
  --focus: #000000;
  --fs: 15px;
}

svg.plan text { font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; fill: var(--ink); }
.shell-wall { fill: none; stroke: url(#hatchWall); stroke-width: 16; stroke-linejoin: miter; }
.shell-wall-outline { fill: none; stroke: var(--ink); stroke-width: 1.5; vector-effect: non-scaling-stroke; }
.shell-floor { fill: var(--floor); }
.grid line { stroke: var(--grid); stroke-width: 1; vector-effect: non-scaling-stroke; }
.grid line.strong { stroke: var(--grid-strong); }
.grid text { fill: var(--grey); }
.zone { stroke-width: 2; vector-effect: non-scaling-stroke; }
.zone.proposed { fill: var(--blue-soft); fill-opacity: 0.55; stroke: var(--blue); stroke-dasharray: 8 5; }
.zone.confirmed { fill: var(--blue-soft); fill-opacity: 0.7; stroke: var(--blue); stroke-width: 3.5; }
.zone.fixed { fill: var(--grey-soft); fill-opacity: 0.8; stroke: var(--grey); }
.zone-g.related .zone { stroke: var(--orange); stroke-width: 4; stroke-dasharray: none; }
.zone-label { font-weight: 700; pointer-events: none; paint-order: stroke; stroke: var(--paper); stroke-linejoin: round; }
.zone-sub { fill: var(--grey); pointer-events: none; paint-order: stroke; stroke: var(--paper); stroke-linejoin: round; }
.feature { cursor: pointer; }
.feature .shape { vector-effect: non-scaling-stroke; }
.feature.prov-drawing .shape { stroke-dasharray: 6 4; }
.feature.prov-outstanding .shape { stroke-dasharray: 2 4; stroke: var(--orange); }
.feature.prov-derived .shape { stroke-dasharray: 10 4 2 4; }
.k-beam .shape { fill: #6a6a6a; stroke: var(--ink); stroke-width: 1.2; }
.k-beam-line .shape { fill: none; stroke: var(--ink); stroke-width: 5; }
.k-duct .shape { fill: url(#hatchBlue); stroke: var(--blue); stroke-width: 1.5; }
.k-column .shape, .k-post .shape, .k-stack .shape { fill: var(--ink); stroke: var(--ink); stroke-width: 1; }
.k-partition .shape { fill: none; stroke: var(--ink); stroke-width: 4; }
.k-bearing-wall-above .shape { fill: none; stroke: var(--grey); stroke-width: 2; stroke-dasharray: 2 6 !important; }
.k-equipment .shape { fill: url(#crossBlue); stroke: var(--blue); stroke-width: 2; }
.k-panel .shape { fill: var(--orange); stroke: var(--ink); stroke-width: 1.2; }
.k-radon .shape { fill: var(--paper); stroke: var(--orange); stroke-width: 2; }
.k-rough-in .shape { fill: none; stroke: var(--blue); stroke-width: 1.5; stroke-dasharray: 3 3; }
.k-rough-in.area .shape { fill: url(#hatchLight); }
.k-window .shape { fill: none; stroke: var(--blue); stroke-width: 6; }
.k-window-well .shape { fill: none; stroke: var(--grey); stroke-width: 1.5; stroke-dasharray: 4 3; }
.k-door .shape { fill: none; stroke: var(--orange); stroke-width: 3.5; }
.k-door .swing { fill: none; stroke: var(--orange); stroke-width: 1.2; stroke-dasharray: 3 3; vector-effect: non-scaling-stroke; }
.k-stair .shape { fill: url(#hatchLight); stroke: var(--ink); stroke-width: 1.5; }
.k-stair .tread { stroke: var(--grey); stroke-width: 1; vector-effect: non-scaling-stroke; }
.k-hose-bib .shape { fill: var(--paper); stroke: var(--blue); stroke-width: 1.5; }
.k-outlet .shape, .k-light .shape { fill: var(--paper); stroke: var(--orange); stroke-width: 1.5; }
.k-soffit .shape, .k-other .shape { fill: none; stroke: var(--grey); stroke-width: 1.5; }
.k-network .shape { fill: var(--paper); stroke: var(--grey); stroke-width: 2; }
.k-floor-drain .shape { fill: var(--paper); stroke: var(--blue); stroke-width: 2; }
.k-flooring .shape { fill: url(#dotsGrey); stroke: var(--grey); stroke-width: 1; }
.k-object .shape { fill: var(--paper); stroke: var(--ink); stroke-width: 2.5; }
.k-object.st-planned .shape { stroke-dasharray: 4 3; }
/* Layer opacity (viewer sliders, --op-<layer> on the svg): shapes fade, labels and badges keep full strength, the
   grid is always full. A selected zone never fades below 0.6 so the selection stays visible. */
.zones .zone { opacity: var(--op-zones, 1); }
.zones .zone.selected { opacity: max(var(--op-zones, 1), 0.6); }
.layer-flooring .shape { opacity: var(--op-flooring, 1); }
.layer-structure .shape { opacity: var(--op-structure, 1); }
.layer-rough-ins .shape { opacity: var(--op-rough-ins, 1); }
.layer-mechanical .shape { opacity: var(--op-mechanical, 1); }
.layer-openings .shape, .layer-openings .tread, .layer-openings .swing { opacity: var(--op-openings, 1); }
.layer-electrical .shape { opacity: var(--op-electrical, 1); }
.layer-plumbing .shape { opacity: var(--op-plumbing, 1); }
.layer-networking .shape { opacity: var(--op-networking, 1); }
.layer-objects .shape { opacity: var(--op-objects, 1); }
/* Planned view: what exists today is dimmed so the plan reads in context. Actual view hides planned items instead. */
svg.mode-planned .ph-actual { opacity: 0.3; }
svg.mode-planned .zones .ph-actual, svg.mode-planned .zone-labels .ph-actual { opacity: 0.45; }
/* Selection: black and thick. Related (what a selected measurement applies to): orange and thick. */
.feature.selected .shape { stroke: var(--focus); stroke-width: 4; filter: drop-shadow(0 0 2px #fff); }
.feature.related .shape { stroke: var(--orange); stroke-width: 4; stroke-dasharray: none; }
.feature:hover .shape { stroke-width: 3; }
.flabel { font-weight: 700; pointer-events: none; paint-order: stroke; stroke: var(--paper); stroke-linejoin: round; }
.flabel.light { fill: var(--paper); stroke: var(--ink); }
.pbadge circle { stroke-width: 1.2; vector-effect: non-scaling-stroke; }
.pbadge text { font-weight: 700; text-anchor: middle; dominant-baseline: central; pointer-events: none; }
.pbadge.measured circle { fill: var(--ink); stroke: var(--ink); } .pbadge.measured text { fill: var(--paper); }
.pbadge.drawing circle { fill: var(--paper); stroke: var(--ink); stroke-dasharray: 2 1.5; }
.pbadge.outstanding circle { fill: var(--orange); stroke: var(--orange); } .pbadge.outstanding text { fill: var(--paper); }
.pbadge.derived circle { fill: var(--grey-soft); stroke: var(--grey); }
/* Level of detail. Far: zone labels and big-feature labels only, no badges. Mid: tiny labels hidden.
   A selected feature always shows its label and badge. */
svg.lod-far .flabel.sz-s, svg.lod-far .flabel.sz-t, svg.lod-far .pbadge { display: none; }
svg.lod-mid .flabel.sz-t, svg.lod-mid .pbadge.sz-t { display: none; }
svg .feature.selected .flabel, svg .feature.selected .pbadge, svg .feature.related .flabel, svg .feature.related .pbadge { display: inline !important; }
.dim line { stroke: var(--ink); stroke-width: 1.2; vector-effect: non-scaling-stroke; }
.dim text { font-weight: 600; paint-order: stroke; stroke: var(--paper); }
.dim.user line { stroke: var(--orange); stroke-width: 2; }
.dim.user text { fill: var(--orange); }
.dim.user circle { fill: var(--orange); }
.dim.selected line { stroke: var(--orange); stroke-width: 3.5; }
.dim.selected text { fill: var(--orange); stroke: var(--paper); }
.dim[data-id] { cursor: pointer; }
.compass text { font-weight: 700; letter-spacing: 0.5px; fill: var(--grey); }
