:root{
  --wine:#71101d;
  --ok:#2e7d4f;
  --wine-2:#8f1626;
  --wine-dark:#35070d;
  --cream:#f6f2ea;
  --ink:#1e1e1e;
  --muted:#6f6a63;
  --line:#e4dfd5;
  --panel:#ffffff;
  --radius:11px;
  --shadow:0 1px 2px rgba(0,0,0,.06), 0 8px 24px rgba(30,20,10,.05);
  --app-header-h:68px; /* .admin-header on all three app pages: 14px padding + 40px .nav-menu-btn + 14px. Same markup on designer, admin and products, and no @media overrides it. */
}
*{box-sizing:border-box}
body{margin:0;font-family:"Segoe UI",Arial,Helvetica,sans-serif;color:var(--ink);background:var(--cream);line-height:1.4}
button,input,select,textarea{font:inherit}

html{scroll-behavior:smooth}

/* ---------- Buttons ---------- */
.primary{background:var(--wine);color:#fff;border:none;padding:14px 20px;text-decoration:none;font-weight:700;border-radius:9px;cursor:pointer;letter-spacing:.4px;transition:background .15s,transform .05s}
.primary:hover{background:var(--wine-2)}
.primary:active{transform:translateY(1px)}

/* ---------- Floating call-to-action ---------- */
.floating-cta{position:fixed;left:22px;bottom:22px;z-index:1000;display:flex;flex-direction:column;align-items:flex-start;gap:11px}
.skip-map{width:46px;height:46px;border-radius:50%;background:#fff;color:var(--wine);border:2px solid var(--wine);font-size:21px;font-weight:800;cursor:pointer;display:grid;place-items:center;text-decoration:none;box-shadow:0 4px 14px rgba(0,0,0,.18);transition:background .15s,color .15s,transform .1s}
.skip-map:hover{background:var(--wine);color:#fff;transform:translateY(2px)}
.quote-fab{background:var(--wine);color:#fff;padding:15px 24px;border-radius:40px;font-weight:800;letter-spacing:.5px;text-decoration:none;box-shadow:0 6px 20px rgba(113,16,29,.35);transition:background .15s,transform .05s}
.quote-fab:hover{background:var(--wine-2)}
.quote-fab:active{transform:translateY(1px)}

/* ---------- Layout ---------- */
.layout{max-width:1520px;margin:0 auto;padding:20px;display:flex;flex-direction:column;gap:20px}
.workspace{display:grid;grid-template-columns:minmax(0,1.75fr) minmax(340px,1fr);gap:20px;align-items:start}
.results{display:grid;grid-template-columns:repeat(2,1fr);gap:20px}

.card,.options,.map-panel{background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);box-shadow:var(--shadow)}
.card h2,.options h2{font-size:13px;letter-spacing:.7px;text-transform:uppercase;color:var(--wine);font-weight:800;margin:0 0 15px;padding-bottom:10px;border-bottom:2px solid var(--line)}

/* ---------- Map panel + toolbar ---------- */
.map-panel{display:flex;flex-direction:column;overflow:hidden}
.toolbar{display:flex;flex-wrap:wrap;gap:12px;justify-content:space-between;align-items:center;padding:13px 16px;background:linear-gradient(180deg,var(--wine-dark),var(--wine))}
.tool-group{display:flex;flex-wrap:wrap;gap:8px;align-items:center}
.tool-subgroup{display:flex;flex-wrap:wrap;gap:8px;align-items:center}
.tool-divider{width:1px;align-self:stretch;min-height:26px;background:rgba(255,255,255,.22)}
.tool{display:inline-flex;align-items:center;gap:8px;background:rgba(255,255,255,.10);color:#fff;border:1px solid rgba(255,255,255,.24);padding:9px 14px;border-radius:8px;cursor:pointer;font-weight:600;font-size:13px;transition:background .15s,transform .05s}
.tool svg{width:16px;height:16px;flex-shrink:0}
.tool:hover{background:rgba(255,255,255,.22)}
.tool:active{transform:translateY(1px)}
.tool.active{background:#fff;color:var(--wine);border-color:#fff}
.tool.danger{background:rgba(255,255,255,.06);border-color:rgba(255,170,170,.55)}
.tool.danger:hover{background:rgba(190,25,25,.6);border-color:rgba(255,170,170,.8)}
.toolbar .check{color:#fff;font-size:13px}
.tool-group.toggles{gap:16px}

.map-wrap{position:relative;background:#ddd}
#map{height:580px;width:100%}
/* Precision crosshair while placing fence points (public designer only). Scoped
   to #map so admin.html's read-only mini-maps are untouched; pointer devices only. */
@media (hover: hover) and (pointer: fine){
  #map.leaflet-container,
  #map .leaflet-grab,
  #map .leaflet-interactive{cursor:crosshair}
  /* Keep the pan affordance: Leaflet adds .leaflet-dragging while dragging. */
  #map.leaflet-dragging,
  #map.leaflet-dragging .leaflet-grab,
  #map.leaflet-dragging .leaflet-interactive{cursor:grabbing}
  /* Draggable gate markers should read as movable, not as a placement target. */
  #map .leaflet-marker-draggable{cursor:move}
}
.searchbar{position:absolute;z-index:700;top:12px;left:58px;right:12px;display:flex;gap:8px}
.searchbar input{flex:1;padding:12px 14px;border:1px solid #b7b1a7;border-radius:9px;box-shadow:0 3px 12px rgba(0,0,0,.18)}
.searchbar button{padding:0 22px;background:var(--wine);color:#fff;border:none;border-radius:9px;cursor:pointer;font-weight:700;box-shadow:0 3px 12px rgba(0,0,0,.18)}
.searchbar button:hover{background:var(--wine-2)}
.map-total{position:absolute;z-index:700;left:50%;bottom:16px;transform:translateX(-50%);background:rgba(18,18,18,.86);color:#fff;padding:11px 20px;border-radius:9px;font-size:13px;letter-spacing:.4px;box-shadow:0 3px 12px rgba(0,0,0,.25)}
.map-hint{margin:0;padding:12px 16px;font-size:12.5px;color:var(--muted);border-top:1px solid var(--line);background:#faf8f3}

/* ---------- Options panel ---------- */
.options{padding:18px}
/* ---------- The fence-style picker ----------
   One trigger card + one dropdown panel, both rendered from the database. Keeps the
   old cards' visual language exactly: --wine accent, --line borders, 8-9px radii, the
   0 3px 12px rgba(113,16,29,.13) hover shadow, 12.5px/600 label type. */
.style-picker{position:relative}
.style-trigger{display:flex;align-items:center;gap:10px;width:100%;padding:12px;background:#fff;border:1px solid var(--line);border-radius:9px;cursor:pointer;text-align:left;font-size:12.5px;font-weight:600;color:var(--ink);transition:border-color .15s,box-shadow .15s,background .15s}
.style-trigger:hover{border-color:var(--wine);box-shadow:0 3px 12px rgba(113,16,29,.13)}
.style-trigger[aria-expanded="true"]{border-color:var(--wine);background:#fdf5f3}
.style-trigger-icon{flex:0 0 auto;display:flex;align-items:center;justify-content:center;color:#6b3f2a}
.style-trigger-icon svg{width:27px;height:27px}
.style-trigger-text{flex:1 1 auto;min-width:0;display:flex;flex-direction:column;gap:2px}
.style-trigger-label{line-height:1.25;overflow-wrap:anywhere}
.style-trigger-sub{font-size:11.5px;font-weight:500;color:var(--muted);line-height:1.25;overflow-wrap:anywhere}
.style-trigger-sub:empty{display:none}
.style-trigger-caret{flex:0 0 auto;width:0;height:0;border-left:5px solid transparent;border-right:5px solid transparent;border-top:6px solid var(--muted);transition:transform .15s}
.style-trigger[aria-expanded="true"] .style-trigger-caret{transform:rotate(180deg)}

/* z-index 1000: Leaflet's own panes and controls live at 400-700 (and .searchbar
   above sits at 700), so anything lower would let the map paint over an open panel. */
.style-panel{position:absolute;z-index:1000;top:calc(100% + 4px);left:0;right:0;max-height:320px;display:flex;flex-direction:column;overflow:hidden;background:#fff;border:1px solid var(--line);border-radius:9px;box-shadow:0 8px 24px rgba(30,20,10,.18)}
/* 🔴 MANDATORY, and NOT redundant. The `hidden` ATTRIBUTE is only a UA-stylesheet
   display:none rule, so ANY author rule setting `display` beats it — the panel would
   paint while its .hidden property is correctly true and the trigger would look dead.
   This project has already been bitten by exactly this twice: admin.html:225 and
   admin.html:206 carry the same companion rule for the same reason. */
.style-panel[hidden]{display:none !important}
/* min-height:0 is load-bearing: a flex item defaults to min-height:auto and refuses to shrink below its content, which would push this list past the panel's max-height and stop it from scrolling */
.style-panel-list{flex:1 1 auto;min-height:0;overflow-y:auto;padding:4px}
/* Sticky, opaque, and the same small uppercase letter-spaced type as .options h3. */
.style-group-header{position:sticky;top:0;z-index:1;background:#faf8f3;font-size:12px;letter-spacing:.6px;text-transform:uppercase;color:var(--muted);padding:8px 10px;border-bottom:1px solid var(--line)}
.style-option{display:flex;flex-direction:row;align-items:center;gap:10px;width:100%;padding:10px 12px;border:1px solid transparent;border-radius:8px;background:#fff;cursor:pointer;text-align:left;font-size:12.5px;font-weight:600;color:var(--ink);transition:border-color .15s,background .15s,box-shadow .15s}
.style-option:hover{border-color:var(--wine);box-shadow:0 3px 12px rgba(113,16,29,.13)}
.style-option:focus-visible{border-color:var(--wine);outline:2px solid var(--wine);outline-offset:-1px}
.style-option.selected{border-color:var(--wine);outline:2px solid var(--wine);outline-offset:-1px;background:#fdf5f3}
.style-option-icon{flex:0 0 auto;display:flex;align-items:center;justify-content:center;color:#6b3f2a}
.style-option-icon svg{width:22px;height:22px}
.style-option-label{flex:1 1 auto;text-align:left;line-height:1.25;overflow-wrap:anywhere}
/* Not selectable, and deliberately NOT a .style-option. */
.style-option-none{padding:10px 12px;font-size:12.5px;color:var(--muted);font-style:italic}
.style-panel-empty{padding:12px;font-size:12.5px;color:var(--muted)}
@media(max-width:360px){
  .style-option{font-size:12px;padding:9px 10px;gap:8px}
  .style-option-icon svg{width:20px;height:20px}
  .style-trigger-icon svg{width:24px;height:24px}
}
.options h3{font-size:12px;letter-spacing:.6px;text-transform:uppercase;color:var(--ink);border-top:1px solid var(--line);padding-top:16px;margin:18px 0 4px}
.options label{display:grid;grid-template-columns:1fr 1fr;align-items:center;gap:12px;margin:11px 0;font-size:13px}
.options select{padding:10px;border:1px solid var(--line);border-radius:8px;background:#fff}
.check{display:flex!important;align-items:center;gap:9px!important;margin:11px 0;font-size:13px}
.options .check{grid-template-columns:none}
.options-list:empty{margin:0}
.option-hint{color:var(--muted);font-size:12px}
.gate-list{font-size:13px;margin:4px 0 6px}
.gate-item{display:flex;justify-content:space-between;padding:9px 12px;background:#f5f2ec;border-radius:8px;margin-bottom:6px}
.gate-item.has-panel{border-radius:8px 8px 0 0;margin-bottom:0}
.gate-toggle{border:0;background:transparent;cursor:pointer;color:var(--wine);font-size:12px;line-height:1;padding:0;margin-right:6px}
.gate-options{padding:2px 12px 8px 26px;margin:-2px 0 8px;background:#f5f2ec;border-radius:0 0 8px 8px}
.gate-options .check{margin:8px 0}
.gate-row-end{display:inline-flex;align-items:center;gap:0}
.gate-remove{border:0;background:transparent;cursor:pointer;color:var(--muted);font-size:16px;line-height:1;padding:0 2px;margin-left:10px}
.gate-remove:hover{color:#b3261e}
.gate-marker{width:24px;height:24px;display:flex;align-items:center;justify-content:center;color:#fff;font-weight:700;font-size:13px;line-height:1;box-sizing:border-box;white-space:nowrap;cursor:move;text-shadow:1px 1px 0 #000,-1px 1px 0 #000,1px -1px 0 #000,-1px -1px 0 #000,0 0 2px #000,0 0 2px #000}
.gate-marker.needs-pick{color:#fbbf24}

/* ---------- Result cards ---------- */
.card{padding:18px;min-height:250px}
.row{display:flex;justify-content:space-between;border-bottom:1px solid #efece6;padding:10px 0;font-size:13px}
.row[hidden]{display:none}
.row strong{text-align:right}
.summary .row-sub span{padding-left:14px;opacity:.8}
.estimate{margin-top:16px;background:linear-gradient(180deg,var(--wine),var(--wine-dark));color:#fff;padding:18px;text-align:center;border-radius:10px;box-shadow:0 6px 18px rgba(113,16,29,.22)}
#estimateReady:not([hidden]){display:flex;flex-direction:column;gap:7px}
.estimate span{font-size:11px;letter-spacing:1.2px}
.estimate strong{font-size:28px;letter-spacing:.5px}
.estimate small{opacity:.85;font-size:11px}
.estimate-status:not([hidden]){display:flex;flex-direction:column;align-items:center;gap:10px}
.estimate-status p{margin:0;font-size:13px;line-height:1.45}
.estimate-status .primary{background:#fff;color:var(--wine);padding:10px 22px}
.estimate-status .primary:hover{background:#f3e9e9}
table{width:100%;border-collapse:collapse;font-size:13px}
th,td{text-align:left;border-bottom:1px solid #efece6;padding:9px 6px}
th{color:var(--muted);font-size:11px;text-transform:uppercase;letter-spacing:.5px}
.lead-intro{margin:-6px 0 6px;font-size:13px;color:var(--muted)}
form{display:grid;gap:13px}
.field-row{display:grid;grid-template-columns:1fr 1fr;gap:12px}
.field{display:grid;gap:5px}
.field label{font-size:11px;font-weight:700;letter-spacing:.4px;text-transform:uppercase;color:var(--muted)}
form input,form textarea{padding:11px 12px;border:1px solid var(--line);border-radius:8px;width:100%;background:#fdfbf8}
form input:focus,form textarea:focus,.searchbar input:focus,.options select:focus{outline:2px solid var(--wine);outline-offset:1px;border-color:var(--wine);background:#fff}
form textarea{min-height:84px;resize:vertical}
.btn-block{width:100%;padding:15px;margin-top:2px}
#formStatus{font-size:12.5px;color:var(--muted);margin:8px 0 0}
.hp-field{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}
.captcha-field{margin:12px 0}
@media(max-width:520px){.field-row{grid-template-columns:1fr}}

/* ---------- Footer ---------- */
footer{background:var(--wine-dark);color:#fff;padding:22px 28px;display:flex;justify-content:space-around;gap:20px;flex-wrap:wrap;align-items:center;margin-top:8px}
footer strong{letter-spacing:1px}
footer span{opacity:.85;font-size:14px}

.measure-label{background:#1d1d1d;color:#fff;padding:3px 7px;border-radius:4px;font-size:11px;font-weight:600}

/* ---------- Responsive ---------- */
@media(max-width:1050px){
  .workspace{grid-template-columns:1fr}
  .results{grid-template-columns:1fr}
}
@media(max-width:760px){
  .floating-cta{left:14px;bottom:14px;gap:9px}
  .quote-fab{padding:13px 18px;font-size:13px}
  .skip-map{width:42px;height:42px}
  .toolbar{justify-content:center}
  .tool-group{justify-content:center;width:100%}
  .tool-subgroup{justify-content:center;flex-wrap:nowrap}
  .tool-divider{display:none}
  .tool{padding:7px 10px;font-size:12px;gap:6px}
  .tool span{white-space:nowrap}
  .tool-group.toggles{justify-content:center;width:100%;padding-top:6px;border-top:1px solid rgba(255,255,255,.18)}
  #map{height:460px}
  .searchbar{left:50px;right:10px;top:10px}
  .layout{padding:14px;gap:14px}
  .workspace,.results{gap:14px}
}
@media(max-width:320px){
  .tool svg{display:none}
  .tool{padding:7px 8px;gap:0}
}
/* Preliminary Materials table: numeric columns right-aligned, total row, mobile-friendly */
.materials th:nth-child(n+2),.materials td:nth-child(n+2){text-align:right}
.materials td:first-child,.materials th:first-child{text-align:left}
.materials td:first-child{white-space:normal;word-break:break-word}
.materials .materials-total td{border-top:2px solid var(--line);font-weight:800}
.materials .materials-subhead td{padding-top:14px;font-weight:800;color:var(--wine);font-size:11px;letter-spacing:.5px;text-transform:uppercase}
.materials-toggle{background:transparent;border:0;padding:0;font:inherit;color:inherit;letter-spacing:inherit;text-transform:inherit;cursor:pointer;text-align:left}
/* A material line a ticked upgrade REPLACED, and the line that replaced it. Shared by
   the designer's Preliminary Materials table and the admin quote-review table, which
   loads this same stylesheet (admin.html:22) — one rule, so the customer's screen and
   the admin's review of that same quote can never show the swap differently.
   Struck rows are marked with INK (line-through), not colour alone: the takeoff sheet
   is printed in black and white and the same convention has to read there. */
tr.mat-struck td{text-decoration:line-through;opacity:.55}
tr.mat-replacement td:first-child{padding-left:18px}
.mat-replaces{display:block;font-size:11px;font-weight:400;opacity:.7;text-decoration:none}
/* 3K-8d: a material line the contractor hand-adjusted for THIS JOB. The ✎ / ⚠ in the Qty
   cell is the signal and it is a character, not a colour, for the same reason the struck row
   above uses a rule through the text rather than grey alone. The italic is a weaker hint.
   🔴 styles.css is shared with admin.html, which renders STORED quote snapshots. Those carry
   no `edited` field, so it reads undefined -> falsy and they render exactly as they do today. */
tr.mat-edited td:first-child,tr.mat-edited-stale td:first-child{font-style:italic}
@media(max-width:480px){
  .materials table{font-size:11.5px}
  .materials th,.materials td{padding:8px 4px}
}

/* Compact, expandable map attribution. The Esri credit + full data-source list
   are license-required, so nothing here hides them — collapsed just truncates
   with a visible ellipsis, and one click (see app.js) expands to full text.
   Deliberately unscoped so admin.html's read-only mini-maps get it too. */
.leaflet-control-attribution{
  max-width:min(62vw,340px);
  cursor:pointer;
}
.leaflet-control-attribution.attr-collapsed{
  white-space:nowrap;
  overflow:hidden;
  text-overflow:ellipsis;
}
.leaflet-control-attribution:not(.attr-collapsed){
  white-space:normal;
  max-width:min(90vw,520px);
}

/* ---------- Signed-in page chrome (admin.html + products.html) ----------
   Moved here from admin.html's inline <style> when the fence editor moved to
   products.html: both pages ship the same wrap, sticky header and org badge.
   styles.css defined none of these selectors before, so nothing in the cascade
   changes for designer.html, which keeps its own later inline overrides. */
.admin-wrap{max-width:720px;margin:0 auto;padding:20px;display:flex;flex-direction:column;gap:20px}
.admin-header{position:sticky;top:0;z-index:1100;background:linear-gradient(180deg,var(--wine-dark),var(--wine));box-shadow:0 2px 10px rgba(0,0,0,.18)}
.admin-header-inner{max-width:720px;margin:0 auto;padding:14px 20px;display:flex;align-items:center;justify-content:flex-start;flex-wrap:nowrap;gap:10px}
.admin-header .primary,.admin-header .btn-secondary{padding:11px 14px;border-radius:9px;font-size:13px;line-height:1.2;white-space:nowrap}
.admin-header .primary{background:#fff;color:var(--wine);border:1.5px solid var(--wine);font-weight:800}
.admin-header .primary:hover{background:var(--wine);color:#fff}

.btn-secondary{background:#fff;color:var(--wine);border:1.5px solid var(--wine);padding:9px 16px;border-radius:8px;font-weight:700;cursor:pointer;font-size:13px}
.btn-secondary:hover{background:#fdf5f3}
.btn-secondary:disabled{opacity:.5;cursor:not-allowed}
/* The filled sibling of .btn-secondary — same box, inverted. .primary above is
   a different, larger button that predates this pair and keeps its own size;
   these two exist so a row of them reads as one set.
   🔴 GREEN, NOT WINE, AND IT IS SAFE TO REDEFINE BECAUSE IT HAS ONE USER: the
   materials header Save. Three actions on that band need three colours — Save
   commits, Cancel backs out, Delete destroys — and wine is what everything else
   on the page already is. --ok was already in the palette; nothing invented it
   here, and nothing else in products.css uses it. */
.btn-primary{background:var(--ok);color:#fff;border:1.5px solid var(--ok);padding:9px 16px;border-radius:8px;font-weight:700;cursor:pointer;font-size:13px}
.btn-primary:hover{background:#245f3d;border-color:#245f3d}
.btn-primary:disabled{opacity:.5;cursor:not-allowed}
/* The third voice: a Cancel that backs out of something is not a brand action
   and not a destructive one. Same box as .btn-secondary, drained of colour, so
   it recedes behind the button next to it. */
.btn-neutral{background:#fff;color:var(--muted);border:1.5px solid var(--line);padding:9px 16px;border-radius:8px;font-weight:700;cursor:pointer;font-size:13px}
.btn-neutral:hover{background:#f4f1ec}
.btn-neutral:disabled{opacity:.5;cursor:not-allowed}
/* 🔴 NOT var(--wine). Wine is the BRAND colour — it is on Save, on Cancel and
   on every header — so a Delete drawn in it reads as "the usual button" rather
   than as the one that destroys something. This red is used for nothing else.
   🔴 AND SOLID, NOT OUTLINED. Outlined, it was a white button with a red border
   sitting beside a white button with a wine border: two outlined buttons in two
   similar reds, which is why Cancel and Delete read as a pair. Fill is what
   separates the one that destroys something from the one that backs out. */
.btn-danger{background:#b3261e;color:#fff;border:1.5px solid #b3261e;padding:9px 16px;border-radius:8px;font-weight:700;cursor:pointer;font-size:13px}
.btn-danger:hover{background:#8c1e17;border-color:#8c1e17}
.btn-danger:disabled{opacity:.5;cursor:not-allowed}

.row-desc{font-size:11.5px;color:var(--muted);line-height:1.3}
