:root {
  --green: #1f6b3a;
  --green-bright: #2bab52;
  --green-dark: #155c2d;
  --green-soft: #e8f4ec;
  --ink: #1d2a22;
  --muted: #66756b;
  --line: #e2e7e2;
  --line-2: #e2e7e2;
  --label: #8a978e;
  --nav: #4a5a50;
  --bg: #fbfcfb;
  --card: #ffffff;
  --warn: #b7791f;
  --warn-soft: #fdf4e3;
  --bad: #c0392b;
  --bad-soft: #fdecea;
  --radius: 12px;
  --shadow: 0 1px 2px rgba(20, 40, 25, .06), 0 4px 16px rgba(20, 40, 25, .05);
  font-family: "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  color: var(--ink);
}

* { box-sizing: border-box; }
body { margin: 0; background: var(--bg); font-size: 14px; line-height: 1.5; overflow-x: hidden; }
img { max-width: 100%; display: block; }
h2, h3 { margin: 0; line-height: 1.25; }
h3 { font-size: 16px; margin-bottom: 12px; }
[hidden] { display: none !important; }
.muted { color: var(--muted); font-size: 13px; }

/* ------------------------------------------------ top bar (the look of web/step1/) */
.topbar { position: sticky; top: 0; z-index: 40; background: var(--card); border-bottom: 1px solid var(--line); }
.topbar::before {
  content: ""; position: absolute; inset: 0 auto 0 0; width: min(340px, 100%); pointer-events: none;
  background: linear-gradient(90deg, rgba(43, 171, 82, .10), rgba(43, 171, 82, 0));
}
.topbar-inner { position: relative; z-index: 1; min-height: 52px; display: flex; flex-wrap: wrap; align-items: center; gap: 8px 18px; padding: 6px 22px; }
.brand { display: flex; flex-direction: column; justify-content: center; flex: none; }
.brand-top { display: flex; align-items: center; gap: 5px; }
.brand-name { font-size: 20px; font-weight: 800; color: var(--green); line-height: 1; }
.brand-chain { color: var(--green-bright); flex: none; }
.brand-sub { margin-top: 2px; font-size: 10px; color: var(--label); white-space: nowrap; }
.main-nav { flex: 1; display: flex; justify-content: center; gap: 26px; }
.nav-link { font-size: 13px; color: var(--nav); text-decoration: none; padding-bottom: 3px; border-bottom: 2px solid transparent; white-space: nowrap; }
.nav-link:hover { color: var(--ink); }
.nav-link.active { color: var(--green); font-weight: 600; border-bottom-color: var(--green); }
.topbar-tools { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; flex: none; margin-left: auto; }
.badge { padding: 4px 10px; border-radius: 999px; font-size: 12px; font-weight: 600; background: var(--warn-soft); color: var(--warn); }
.open-project { display: flex; gap: 6px; }
.open-project input { width: 190px; padding: 6px 10px; font-family: Consolas, monospace; }
.open-project .btn { padding: 6px 12px; }

/* ------------------------------------------------ layout */
.page { max-width: 960px; margin: 0 auto; padding: 0 16px 96px; display: grid; gap: 22px; }
.page-title { margin: 28px 0 0; font-size: 20px; font-weight: 700; line-height: 1.3; }
.card { border: 1px solid var(--line); border-radius: var(--radius); padding: 18px; background: #fcfdfb; }
.row { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.step { background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); padding: 22px; box-shadow: var(--shadow); }
.step-head { display: flex; gap: 14px; align-items: flex-start; margin-bottom: 18px; }
.step-head p { margin: 4px 0 0; color: var(--muted); }
.step-num {
  flex: none; width: 34px; height: 34px; border-radius: 50%; display: grid; place-items: center;
  background: var(--green); color: #fff; font-weight: 700;
}
/* ------------------------------------------------ tabs (the three input options, and the sketch tools) */
.tabs { display: flex; gap: 6px; margin-bottom: 14px; border-bottom: 1px solid var(--line); }
.tab-btn {
  font: inherit; font-weight: 600; font-size: 14px; color: var(--muted); background: none; border: none;
  padding: 8px 4px 10px; margin-bottom: -1px; border-bottom: 2px solid transparent; cursor: pointer;
}
.tab-btn:hover { color: var(--ink); }
.tab-btn[aria-selected="true"] { color: var(--green-dark); border-bottom-color: var(--green); }
.icon-btn { padding: 8px 10px 10px; display: inline-flex; align-items: center; justify-content: center; }
.icon-btn svg { display: block; }

/* ------------------------------------------------ the three input options */
/* Three labels do not fit one line of a 320px phone; they wrap onto a second line instead of pushing the page
   sideways (the estimate's .tabs rule below already wraps, this one must not depend on it). */
#input-options { flex-wrap: wrap; column-gap: 14px; }
.option-hint { margin: 0 0 14px; }
/* A remark under a control. It sits inside the bold 13px label, so it has to ask for its own weight. */
.field small { font-weight: 400; }
/* A required answer: the star beside its label, and a red outline while the run is locked because of it. */
.req { color: var(--bad); }
.field.invalid input, .field.invalid select, .field.invalid textarea { border-color: var(--bad); }
/* A label for a group of fields (the fields inside carry their own labels). */
.field-group { margin: 14px 0 8px; font-size: 13px; font-weight: 600; color: var(--muted); }
/* "Vẽ trên khung" / "Tải ảnh lô đất": two pills, the chosen one green. */
.lot-source { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 12px; }
.chip {
  font: inherit; font-size: 14px; font-weight: 600; padding: 6px 14px; border-radius: 999px; cursor: pointer;
  border: 1px solid var(--line); background: #fff; color: var(--muted);
}
.chip:hover { border-color: var(--green); }
.chip[aria-checked="true"] { background: var(--green-soft); border-color: var(--green); color: var(--green-dark); }
/* Option 2, "Vẽ trên khung". The frame MUST keep its own 700x480 proportion for the same reason #draw-canvas must
   (pointer coordinates are converted per axis, see drawToolRawPoint in app.js): only the width is set, and the
   canvas element's own width / height attributes supply the ratio for `height: auto`. No max-*, no aspect-ratio.
   touch-action none: a corner is dragged with one finger, which the browser would otherwise take for a scroll. That
   is the value only until app.js has measured the frame (paintLotEditor): where the frame is too narrow for a
   finger to drag a corner it sets pan-y, so the page scrolls under a thumb landing on it. One owner on purpose — a
   media query here decided by the WINDOW's width while the pointer code decides by the frame's, and where the two
   disagreed (a phone held sideways, a tablet in the two-column layout) a finger on the frame did nothing at all. */
#lot-canvas { display: block; width: 100%; height: auto; border: 1px solid var(--line); border-radius: 8px; touch-action: none; margin-top: 10px; background: #fff; }
#lot-canvas.invalid { border-color: var(--bad); }
#lot-draw > .muted:first-child { margin: 0 0 12px; }
.lot-tools { display: flex; flex-wrap: wrap; gap: 8px; }
#lot-scale-note { margin: 6px 0 0; font-size: 13px; }
/* The two fields above the frame only show the numbers once the lot is no longer their rectangle. */
#lot-draw input[readonly] { background: #f3f6f2; color: var(--muted); }
/* One row per edge: letter, length, entrance. On a 320px phone the entrance choice drops to a second line. */
.lot-edges { margin-top: 10px; }
.lot-edge { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 14px; padding: 6px 0; border-top: 1px solid var(--line); }
.lot-edge:first-child { border-top: none; }
.lot-edge-length { display: flex; align-items: center; gap: 6px; font-size: 14px; }
.lot-edge-length input { width: 92px; }
.lot-edge .check { margin: 0; }
.lot-edge.bad .lot-edge-length input { border-color: var(--bad); }
.lot-edges-note { margin: 6px 0 0; font-size: 13px; }
.lot-messages p { margin: 8px 0 0; }
.lot-messages .advice { margin-top: 10px; }
.lot-answers { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
#lot-summary { margin: 8px 0 0; font-weight: 600; }
#lot-confirm { margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--line); }
#lot-confirm h4 { margin: 0; font-size: 15px; }
#lot-upload .dropzone { margin-bottom: 10px; }
#lot-upload #btn-clear-plot { margin-top: 10px; }
#panel-drawings #btn-check-drawings { margin-top: 12px; }
/* Option 3: one slot per floor, stacked. The drop box is lower than the lot picture's — a house has up to five. */
.floor-slot { padding: 12px 0; border-top: 1px solid var(--line); }
.floor-slot:first-child { border-top: none; padding-top: 0; }
.slot-head { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; justify-content: space-between; margin-bottom: 8px; }
/* (.dropzone.slot-zone: the general .dropzone rules come later in this file and would win at equal weight) */
.dropzone.slot-zone { min-height: 96px; padding: 8px; }
.dropzone.slot-zone img { max-height: 200px; }
.floor-slot [data-floor-draw] { margin-top: 8px; }
.slot-note { margin: 8px 0 0; }
.slot-status { margin-top: 10px; }
.slot-status .advice { margin-top: 8px; }
#drawings-size-note { margin: 10px 0 0; }
#drawings-status { margin-top: 10px; }
#drawings-status p { margin: 0 0 6px; }
/* The confirm block: the four sides sit around the ground-floor drawing they refer to. */
#drawings-confirm { margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--line); }
#drawings-confirm h4 { margin: 0; font-size: 15px; }
.side-picker {
  display: grid; gap: 8px; align-items: center; justify-items: center; max-width: 380px;
  grid-template-columns: auto minmax(0, 1fr) auto;
  grid-template-areas: ". top ." "left thumb right" ". bottom .";
}
/* Narrower pills than elsewhere: on a 320px phone every pixel they give up goes to the drawing between them. */
.side-picker .chip { padding: 6px 10px; }
.side-picker [data-side="top"] { grid-area: top; }
.side-picker [data-side="left"] { grid-area: left; }
.side-picker [data-side="right"] { grid-area: right; }
.side-picker [data-side="bottom"] { grid-area: bottom; }
.side-thumb { grid-area: thumb; max-height: 170px; object-fit: contain; border: 1px solid var(--line); border-radius: 8px; background: #fff; }
.side-note { margin: 8px 0 12px; }
.confirm-dims .dims-note { margin: 0; }
/* Option 1. The microphone under the description box: as wide as its label on a desktop (the box is a column that
   would stretch it), red with a pulsing dot while it listens. The two lines under it sit inside the bold label
   column, so they ask for their own weight. */
.voice-btn { align-self: flex-start; }
/* (.btn.voice-btn: the general .btn.ghost colours come later in this file and would win at equal weight) */
.btn.voice-btn[aria-pressed="true"] { background: var(--bad-soft); border-color: var(--bad); color: var(--bad); }
.voice-btn[aria-pressed="true"]::before {
  content: ""; width: 8px; height: 8px; border-radius: 50%; background: currentColor; animation: listening 1.2s ease-in-out infinite;
}
@keyframes listening { 50% { opacity: .25; } }
#voice-status, #voice-privacy { margin: 0; font-weight: 400; }
#voice-privacy { font-size: 12px; }
/* "Hệ thống hiểu": two short lists (the customer's own facts, what buildX proposes) and the lines where description
   and form disagree. Dimmed while the reading shown is older than what the customer has typed since. */
#understood-intro { margin: 0 0 12px; }
.understood { margin-bottom: 14px; font-size: 14px; transition: opacity .15s; }
.understood[aria-busy="true"] { opacity: .55; }
.understood h4 { margin: 0 0 4px; font-size: 13px; color: var(--green-dark); }
/* One label column for both lists, so the values of "yours" and "proposed" start on the same line down the card. */
.understood .facts { margin: 0; grid-template-columns: 6.5em 1fr; }
.understood .src { color: var(--muted); font-weight: 400; font-size: 13px; }
.u-actions { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 4px; }
/* On a 320px phone a long label wraps inside its button; it then reads from the left, like the lines around it. */
.u-actions .btn { text-align: left; }
#understood-conflicts .conflict { margin-top: 6px; padding: 10px 12px; border-radius: var(--radius); background: var(--warn-soft); color: var(--warn); font-size: 13px; }
#understood-conflicts .conflict p { margin: 0 0 6px; }
.advice .u-actions { margin-top: 6px; }
/* What the run will send (muted) and why it cannot start (red), right above the button they describe. */
.run-summary { margin: 14px 0 0; }
#drafts-note { margin: 14px 0 0; }
#drafts-note + .run-summary { margin-top: 4px; }
#run-blocker { margin: 14px 0 0; }
#warning-acceptance { margin-top: 14px; }
#warning-acceptance .check { margin-bottom: 0; }

/* ------------------------------------------------ "Vẽ tay" draw tool */
.modal { position: fixed; inset: 0; background: rgba(0, 0, 0, .45); display: grid; place-items: center; z-index: 50; padding: 16px; }
/* max-height + overflow stay as a fallback for very short viewports only — #draw-canvas's own height cap below is
   what actually keeps the whole modal small enough to fit without scrolling on ordinary screens. */
.modal-box { background: #fff; border-radius: var(--radius); box-shadow: var(--shadow); padding: 18px; max-width: 640px; width: 100%; max-height: 90vh; overflow-y: auto; }
.modal-head p { margin: 4px 0 0; }
.modal-actions { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-top: 12px; position: sticky; bottom: -18px; background: #fff; padding: 10px 0 4px; }
.modal-actions .spacer { flex: 1; }
/* At 390px "Hoàn tác", "Xóa hết" and "Dùng ảnh này" each broke over 2 lines (51px tall) next to "Hủy" at 31.5px,
   and at 320px "Dùng ảnh này" took 3 lines. A button label is never worth breaking: flex-wrap above lets the row
   take a second line instead when a few pixels are missing. */
.modal-actions .btn { white-space: nowrap; }
/* The canvas MUST stay in its own 700x480 proportion: pointer coordinates are converted per axis
   (canvas.width / rect.width and canvas.height / rect.height, see drawToolRawPoint in app.js), so a box whose
   proportion differs from 700/480 makes one metre across mean something else than one metre down — the wrong
   metres are then painted onto the PNG the AI reads. `width: auto; max-width: 100%; height: min(48vh,420px);
   aspect-ratio: 700/480` looked right but was not: with the height already resolved, max-width wins over
   aspect-ratio and squashes the box (307x405 at 390px wide = 2.28 across against 1.18 down). Only the
   width is set now; the canvas element's own width/height attributes supply the ratio for `height: auto`.
   .modal-actions above is sticky, so a taller canvas never pushes the buttons out of reach. */
#draw-canvas { display: block; width: 100%; height: auto; border: 1px solid var(--line); border-radius: 8px; cursor: crosshair; touch-action: none; margin-top: 10px; }
/* The metre scale of the sketch sits at the end of the tool row: it belongs to the drawing, not to one tool. */
.draw-scale { margin-left: auto; display: flex; align-items: center; gap: 6px; font-size: 13px; color: var(--muted); border-bottom: none; }
.draw-scale select { padding: 4px 6px; font-size: 13px; }

@media (max-width: 860px) {
  .row { grid-template-columns: 1fr; }
  .open-project input { width: 150px; }
}

/* ------------------------------------------------ form */
.field { display: flex; flex-direction: column; gap: 5px; font-size: 13px; font-weight: 600; color: var(--muted); margin-bottom: 12px; }
input, select, textarea {
  font: inherit; color: var(--ink); padding: 8px 10px; border: 1px solid var(--line); border-radius: 8px; background: #fff; width: 100%;
}
input:focus, select:focus, textarea:focus { outline: 2px solid rgba(31, 122, 61, .25); border-color: var(--green); }
textarea { resize: vertical; }
.check { display: flex; gap: 8px; align-items: center; font-size: 14px; margin: 4px 0 12px; }
.check input { width: auto; }
.more summary { cursor: pointer; color: var(--green-dark); font-weight: 600; font-size: 14px; margin-bottom: 10px; }

/* ------------------------------------------------ buttons */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  font: inherit; font-weight: 600; padding: 10px 18px; border-radius: 9px; border: 1px solid transparent;
  cursor: pointer; text-decoration: none; transition: background .15s, border-color .15s;
}
.btn.primary { background: var(--green); color: #fff; }
.btn.primary:hover:not(:disabled) { background: var(--green-dark); }
.btn.ghost { background: #fff; color: var(--green-dark); border-color: var(--line); }
.btn.ghost:hover:not(:disabled) { border-color: var(--green); }
.btn.small { padding: 5px 10px; font-size: 13px; }
.btn:disabled { opacity: .5; cursor: not-allowed; }
.btn.loading::before, .spinner {
  width: 14px; height: 14px; border-radius: 50%;
  border: 2px solid currentColor; border-right-color: transparent; animation: spin .8s linear infinite;
}
.btn.loading::before { content: ""; }
.actions { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; margin-top: 18px; }
@keyframes spin { to { transform: rotate(360deg); } }

/* ------------------------------------------------ plot upload + verification */
.dropzone {
  position: relative; display: grid; place-items: center; text-align: center; min-height: 180px;
  border: 2px dashed var(--line); border-radius: var(--radius); background: #fff; cursor: pointer; overflow: hidden; color: var(--muted);
}
.dropzone.dragging { border-color: var(--green); background: var(--green-soft); }
.dropzone.locked { cursor: progress; opacity: .7; }
.dropzone.locked input { cursor: progress; }
.dropzone input { position: absolute; inset: 0; opacity: 0; cursor: pointer; }
.dropzone img { max-height: 260px; object-fit: contain; }
.verify { margin-top: 12px; }
.verdict { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; padding: 10px 12px; border-radius: 9px; font-size: 14px; }
.verdict strong { font-size: 15px; }
.verdict span { color: var(--muted); }
.verdict.ok { background: var(--green-soft); color: var(--green-dark); }
.verdict.warn { background: var(--warn-soft); color: var(--warn); }
.verdict.bad { background: var(--bad-soft); color: var(--bad); }
.verdict.pending { background: #eef1ee; color: var(--muted); }
.verify .summary { margin: 10px 0 6px; }
.facts { display: grid; grid-template-columns: auto 1fr; gap: 2px 12px; margin: 8px 0; font-size: 14px; }
.facts dt { color: var(--muted); }
.facts dd { margin: 0; font-weight: 600; }
.issues { margin: 8px 0; padding-left: 18px; font-size: 14px; }
.issues li.error { color: var(--bad); }
.issues li.warning { color: var(--warn); }
/* Gợi ý mô tả dưới ô "Mô tả mong muốn": chỉ gợi ý, không chặn. */
.advice { margin-top: 8px; padding: 10px 12px; border-radius: var(--radius); background: var(--warn-soft); color: var(--warn); font-size: 13px; line-height: 1.5; }
.advice p { margin: 0; }
.advice p + p { margin-top: 6px; }
.error-text { color: var(--bad); font-size: 14px; }

/* ------------------------------------------------ progress + spec summary card */
.progress { margin-top: 16px; }
.bar { height: 8px; border-radius: 999px; background: #e7ece8; overflow: hidden; }
.bar span { display: block; height: 100%; width: 0; background: var(--green); transition: width .4s; }
.progress-text { margin: 8px 0 4px; font-size: 14px; }
.progress-wait { margin: 4px 0 0; }
.wait-note { margin: 10px 0 0; }
.wait-line { display: block; }
.wait-line.note { font-size: 13px; }
.verdict.pending .wait-line { width: 100%; }
.spec-summary { margin-top: 16px; padding: 14px 16px; border-radius: var(--radius); background: var(--green-soft); font-size: 14px; }
.spec-summary ul { margin: 6px 0 0; padding-left: 18px; }
.spec-summary .notes { color: var(--warn); }
.spec-summary .conversion { margin: 8px 0 0; }
/* The header of the plan card: whose numbers the lot carries (a remark, so not bold), and a bedroom count that is
   not the one the customer wished for (the warning colour of the notes below, where the server explains it). */
.spec-summary .lot-mark { font-weight: 400; }
.spec-summary .wish-differs { color: var(--warn); }
.notes-box {
  margin-top: 16px; padding: 12px 14px; border-radius: var(--radius);
  background: var(--bad-soft); border: 1px solid var(--line); color: var(--bad); font-size: 14px;
}
.notes-box ul.notes { margin: 6px 0 0; padding-left: 18px; }
/* Set by renderNotesAndFailures when nothing failed: the box then carries plain run notes, not missing drawings,
   and the red "something went wrong" colours would read as an error the customer does not have. */
.notes-box.info { background: var(--warn-soft); color: var(--ink); }
.notes-box ul.notes + strong { display: block; margin-top: 10px; }

/* ------------------------------------------------ galleries */
.gallery { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 14px; margin-top: 16px; }
.gallery.wide { grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); margin-top: 0; }
.tile { border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; background: #fff; margin: 0; display: flex; flex-direction: column; }
.tile .media { background: #f0f2ef; aspect-ratio: 3 / 4; display: grid; place-items: center; }
.gallery.wide .tile .media { aspect-ratio: 16 / 9; }
.tile .media img { width: 100%; height: 100%; object-fit: contain; }
.tile .placeholder { color: var(--muted); font-size: 13px; padding: 12px; text-align: center; }
.tile figcaption { display: flex; gap: 8px; align-items: center; justify-content: space-between; padding: 8px 10px; font-size: 13px; }
.tile.loading .media { position: relative; }
.tile.loading .media::after {
  content: "Đang xử lý…"; position: absolute; inset: 0; display: grid; place-items: center;
  background: rgba(255, 255, 255, .75); color: var(--green-dark); font-weight: 600;
}
.tile.failed { border-color: var(--bad); }
.tile.failed .media { background: var(--bad-soft); }
.tile.failed .placeholder { color: var(--bad); font-weight: 600; }
/* A plan drawn on a lying sheet (app.js setTileFormat: data-aspect is the sheet's own format, missing = 3:4). The
   box takes that format, and the tile takes two columns so the plan is shown about as large as an upright one —
   only where the gallery is sure to have two (from 600px up; narrower, `span 2` would add a column and push the
   page sideways). */
.tile[data-aspect="4:3"] .media { aspect-ratio: 4 / 3; }
.tile[data-aspect="16:9"] .media { aspect-ratio: 16 / 9; }
@media (min-width: 600px) {
  .gallery .tile.landscape { grid-column: span 2; }
}
/* A drawing whose outline does not match the sizes the customer gave (app.js setTileFlag): amber, not red — the
   drawing exists and its numbers are right, it is its proportions that need a second look. */
.tile.flagged { border-color: var(--warn); }
.tile.flagged figcaption { flex-wrap: wrap; }
.flag-badge { padding: 2px 8px; border-radius: 999px; background: var(--warn-soft); color: var(--warn); font-size: 12px; font-weight: 600; }
.render-group { margin-top: 18px; }
.render-group h3 { font-size: 15px; margin-bottom: 10px; color: var(--green-dark); }

/* ------------------------------------------------ estimate: 3 tabs + total */
.estimate { margin-top: 16px; }
.tabs { display: flex; flex-wrap: wrap; gap: 6px; border-bottom: 1px solid var(--line); }
.tab {
  font: inherit; font-weight: 600; padding: 9px 16px; border: 1px solid transparent; border-bottom: none;
  border-radius: 9px 9px 0 0; background: none; color: var(--muted); cursor: pointer; margin-bottom: -1px;
}
.tab:hover { color: var(--green-dark); }
.tab.active { background: #fff; color: var(--green-dark); border-color: var(--line); border-bottom: 1px solid #fff; }
.tab-panel { padding-top: 12px; }
.table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
/* Phones: keep the 5 columns readable and scroll horizontally inside the frame instead of squeezing the amounts. */
.table-wrap table { min-width: 560px; }
td.num:last-child { font-weight: 600; }
table { width: 100%; border-collapse: collapse; font-size: 13px; }
th, td { border-bottom: 1px solid var(--line); padding: 6px 8px; text-align: left; vertical-align: top; }
th { background: #f3f6f2; color: var(--muted); font-weight: 600; }
td.num, th.num { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
tr.group td { background: var(--green-soft); font-weight: 700; color: var(--green-dark); }
.part-total, .grand-total {
  display: flex; flex-wrap: wrap; gap: 12px; justify-content: space-between; align-items: center;
  margin-top: 12px; padding: 12px 14px; border-radius: var(--radius);
}
.part-total { background: #f3f6f2; font-weight: 600; }
.grand-total { background: var(--green); color: #fff; font-size: 17px; }
.grand-total strong { font-size: 20px; }

/* ------------------------------------------------ toast */
/* left/right, NOT left:50% + translateX: a shrink-to-fit box positioned at left:50% has only half the screen left
   as its containing block (195px of a 390px phone), so max-width never gets a turn and the error sentence broke
   over 5 lines at 390px and 6 at 320px. Same fix, same numbers as web/step1/style.css. */
.toast {
  position: fixed; left: 16px; right: 16px; bottom: 24px; z-index: 50;
  max-width: 640px; margin-inline: auto;
  padding: 12px 18px; border-radius: 10px; background: var(--ink); color: #fff; box-shadow: var(--shadow); font-size: 14px;
}
.toast.error { background: var(--bad); }
.toast.success { background: var(--green); }

/* ------------------------------------------------ điện thoại */
/* iOS zooms the whole page in when focus lands on a field smaller than 16px, and not one field on this screen
   reached it: every form control inherited .field's 13px, and #project-id in the top bar inherited body's 15px.
   .field keeps 13px for the LABEL — only the control it wraps is raised. Same rule, same 16px as
   web/step1/style.css. */
@media (max-width: 600px) {
  input, select, textarea,
  .field input, .field select, .field textarea,
  .open-project input { font-size: 16px; }
  /* A thumb-sized target for the microphone. */
  .voice-btn { align-self: stretch; }
}

.sr-only { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

/* =============================================================================
   Step 1 in the look of web/step1/: three-step bar, a form card in three numbered blocks, the side card.
   skin.js draws the chips, the slider and the style pictures over the real controls (class skin-src, hidden
   only once skin.js is running, so the page still works with plain selects without it).
   ========================================================================== */
.sr-only, .skin-on .skin-src {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
}
a:focus-visible, button:focus-visible { outline: 2px solid var(--green-bright); outline-offset: 2px; }

/* ------------------------------------------------ three-step bar */
.stepper-card { background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); padding: 18px 24px; }
.stepper { list-style: none; margin: 0; padding: 0; display: flex; }
.stepper-item { position: relative; flex: 1 1 0; min-width: 0; }
.stepper-item a { display: flex; flex-direction: column; align-items: center; text-align: center; color: inherit; text-decoration: none; }
/* the line that runs through the circles (radius 15px + 4px gap) */
.stepper-item::before, .stepper-item::after { content: ""; position: absolute; top: 15px; height: 1px; background: #dfe4df; }
.stepper-item::before { left: 0; right: calc(50% + 19px); }
.stepper-item::after { left: calc(50% + 19px); right: 0; }
#stepper-1::before, #stepper-3::after { content: none; }
.step-dot {
  position: relative; z-index: 1; width: 30px; height: 30px; border-radius: 50%; display: grid; place-items: center;
  background: #f2f4f2; border: 1px solid var(--line-2); color: var(--muted); font-size: 13px; font-weight: 700;
}
.stepper-item.is-current .step-dot { background: var(--green); border-color: var(--green); color: #fff; }
.stepper-item.is-done .step-dot { background: var(--green-soft); border-color: var(--green); color: var(--green); }
.stepper-item.is-done .step-state { color: var(--green); }
.step-name { margin-top: 8px; font-size: 13px; font-weight: 600; color: var(--ink); }
.step-state { margin-top: 2px; font-size: 11px; color: var(--muted); }

/* ------------------------------------------------ the two cards of step 1 */
.step-input { display: grid; gap: 16px; }
.main-grid { display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); gap: 22px; align-items: start; }
.form-card, .side-card { padding: 22px; background: var(--card); }
.form-flat { display: contents; }
.block-title { margin: 24px 0 10px; font-size: 10px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--label); }
.block-title.first { margin-top: 0; }
.side-title { margin: 0 0 14px; font-size: 14px; font-weight: 700; }

.field-head { display: flex; align-items: center; gap: 5px; margin-bottom: 7px; }
.field-label { font-size: 12px; font-weight: 600; color: var(--ink); }
.form-card .field { color: var(--ink); font-weight: 600; font-size: 12px; margin-bottom: 14px; }
.form-card .field .field-head { margin-bottom: 0; }
.form-card .check { font-size: 13px; }
.req { color: var(--bad); margin-left: 2px; }
.info-dot { position: relative; padding: 0; border: 0; background: none; color: #b6c0b8; line-height: 0; cursor: pointer; flex: none; }
.info-dot::after { content: ""; position: absolute; inset: -12px -16px -6px -4px; }
.info-dot:hover { color: var(--nav); }

/* controls of the form card: 36px, 8px radius, a green ring on focus */
.form-card input:not([type="checkbox"]):not([type="range"]):not([type="file"]), .form-card select, .form-card textarea { border-color: var(--line-2); font-size: 13px; }
.form-card input:not([type="checkbox"]):not([type="range"]):not([type="file"]), .form-card select { height: 36px; padding: 0 11px; }
.form-card select {
  appearance: none; -webkit-appearance: none; padding-right: 30px; cursor: pointer;
  background: #fff url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'><path d='M1 1.6 6 6.4 11 1.6' fill='none' stroke='%239aa79f' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/></svg>") no-repeat right 11px center / 11px 8px;
}
.form-card select[name="building_type"] { height: 40px; }
.form-card textarea { padding: 9px 11px; line-height: 1.45; }
.form-card input:focus, .form-card select:focus, .form-card textarea:focus {
  outline: none; border-color: var(--green-bright); box-shadow: 0 0 0 1px var(--green-bright), 0 0 0 4px rgba(43, 171, 82, .14);
}
.form-card .field.invalid input, .form-card .field.invalid select, .form-card .field.invalid textarea { border-color: var(--bad); }
.form-card .field.invalid .opt-chip { border-color: var(--bad); }
#description { min-height: 150px; }
#input-grid[data-mode="text"] #description { min-height: 200px; }

/* the three tabs and the panels under them */
.form-card .tabs { margin-bottom: 12px; }
.form-card > .card { margin-bottom: 16px; padding: 16px; background: #fcfdfc; box-shadow: none; }
.form-card > .card h3 { font-size: 14px; }
.floor-add { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
#floor-count-hint { margin: 8px 0 0; }

/* floors and tum as chips */
.scope-row { display: flex; flex-direction: column; gap: 0; }
.chip-row { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 7px; }
.opt-chip {
  height: 32px; padding: 0 10px; white-space: nowrap; cursor: pointer; font: inherit; font-size: 12px;
  border: 1px solid var(--line-2); border-radius: 8px; background: var(--card); color: var(--ink);
}
.opt-chip:hover { border-color: #c9d4cc; }
.opt-chip[aria-pressed="true"] { background: #eaf6ee; border-color: var(--green-bright); color: var(--green); font-weight: 600; }

/* the package slider */
.slider { -webkit-appearance: none; appearance: none; width: 100%; height: 16px; margin: 8px 0 0; padding: 0; border: 0; background: transparent; cursor: pointer; }
.slider:focus { outline: none; box-shadow: none; }
.slider:focus-visible { outline: 2px solid var(--green-bright); outline-offset: 3px; }
.slider::-webkit-slider-runnable-track { height: 6px; border-radius: 999px; background: linear-gradient(90deg, var(--green) 0 var(--fill, 50%), #e9ede9 var(--fill, 50%) 100%); }
.slider::-webkit-slider-thumb { -webkit-appearance: none; width: 14px; height: 14px; margin-top: -4px; border-radius: 50%; background: #fff; border: 2px solid var(--green); box-shadow: 0 1px 3px rgba(20, 40, 25, .25); }
.slider::-moz-range-track { height: 6px; border-radius: 999px; background: #e9ede9; }
.slider::-moz-range-progress { height: 6px; border-radius: 999px; background: var(--green); }
.slider::-moz-range-thumb { width: 14px; height: 14px; border: 2px solid var(--green); border-radius: 50%; background: #fff; box-shadow: 0 1px 3px rgba(20, 40, 25, .25); }
.package-labels { display: flex; margin-top: 4px; }
.package-labels span { flex: 1 1 0; font-size: 11px; color: var(--muted); text-align: center; }
.package-labels span:first-child { text-align: left; }
.package-labels span:last-child { text-align: right; }
.package-labels .is-active { font-size: 12px; font-weight: 600; color: var(--green); }

/* the side card: the style as pictures. Cards of one row are as tall as each other; a card left alone on the last
   row takes both columns and shows a wider crop of its picture, so the grid never ends on a half-empty row. */
.side-card { position: sticky; top: 68px; align-self: start; }
.side-lead { margin: 0 0 12px; font-size: 12px; color: var(--muted); }
.style-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.style-card {
  position: relative; display: flex; flex-direction: column; width: 100%; padding: 0; overflow: hidden; cursor: pointer; text-align: left;
  font: inherit; background: var(--card); border: 1px solid var(--line); border-radius: 12px; color: inherit;
  transition: border-color .15s, box-shadow .15s, transform .15s;
}
.style-card:hover { border-color: #b9c9bd; transform: translateY(-1px); }
.style-thumb { display: block; width: 100%; aspect-ratio: 4 / 3; overflow: hidden; background: #f3f6f3; }
.style-thumb svg { display: block; width: 100%; height: 100%; }
.style-label { display: flex; flex-direction: column; gap: 1px; flex: 1; padding: 8px 10px 10px; }
.style-name { font-size: 12.5px; font-weight: 600; line-height: 1.3; }
.style-sub { font-size: 11px; line-height: 1.3; color: var(--muted); min-height: 1.3em; }
.style-card[aria-pressed="true"] { border-color: var(--green-bright); box-shadow: 0 0 0 1px var(--green-bright), 0 4px 12px rgba(43, 171, 82, .18); }
.style-card[aria-pressed="true"] .style-name { color: var(--green); }
/* the tick of the chosen card */
.style-card[aria-pressed="true"]::after {
  content: "✓"; position: absolute; top: 7px; right: 7px; width: 20px; height: 20px; border-radius: 50%;
  display: grid; place-items: center; background: var(--green-bright); color: #fff; font-size: 12px; font-weight: 700; line-height: 1;
  box-shadow: 0 1px 3px rgba(20, 40, 25, .3);
}
.style-picked { margin: 12px 0 0; padding-top: 12px; border-top: 1px solid var(--line); font-size: 12px; color: var(--muted); }
.style-picked strong { color: var(--green); }
@media (min-width: 861px), (max-width: 600px) {
  .style-card:last-child:nth-child(odd) { grid-column: 1 / -1; }
  .style-card:last-child:nth-child(odd) .style-thumb { aspect-ratio: 2 / 1; }
}

/* the call to action, and the notices above it */
.cta-zone { margin-top: 6px; }
.cta-zone > p { margin: 0 0 10px; text-align: center; }
#quota-note { font-size: 11.5px; }
.cta-zone .actions { margin-top: 10px; }
.btn.cta {
  width: 100%; height: 44px; padding: 0 18px; border: 0; border-radius: 10px; font-size: 14px; font-weight: 700;
  background: linear-gradient(90deg, #6cc36f 0%, #1f7a3d 100%); color: #fff;
}
.btn.cta:hover:not(:disabled) { background: linear-gradient(90deg, #6cc36f 0%, #1f7a3d 100%); filter: brightness(1.04); }
.btn.cta:disabled { opacity: .5; }
#furniture-2d, #progress-2d, #spec-2d, #notes-2d { margin-top: 0; }

/* ------------------------------------------------ narrower screens */
@media (max-width: 949px) {
  .main-nav { gap: 18px; }
  .nav-link:nth-child(n + 5) { display: none; }
}
@media (max-width: 860px) {
  .main-grid { grid-template-columns: minmax(0, 1fr); }
  .style-grid { grid-template-columns: repeat(3, 1fr); }
  .side-card { position: static; }
  .nav-link:nth-child(n + 3) { display: none; }
  .page-title { margin-top: 20px; }
  .stepper-card { padding: 16px 14px; }
  .form-card, .side-card { padding: 18px 16px; }
}
@media (max-width: 600px) {
  .main-nav { display: none; }
  .topbar-inner { padding: 8px 16px; }
  .topbar-tools { margin-left: 0; width: 100%; }
  .open-project { flex: 1; }
  .open-project input { width: 100%; flex: 1; }
  .step-name { font-size: 12px; }
  .step-state { font-size: 10px; }
  .style-grid { grid-template-columns: 1fr 1fr; }
  .form-card input:not([type="checkbox"]):not([type="range"]):not([type="file"]), .form-card select, .form-card textarea { font-size: 16px; }
}
/* The three ways to give the input, as three boxed choices: an icon, the name, one line of what it is. The markup is
   plain text on purpose (the tab text is read as it is), so the icon and the line come from CSS. */
#input-options { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; border-bottom: 0; margin-bottom: 14px; }
#input-options .tab-btn {
  display: flex; flex-direction: column; align-items: flex-start; gap: 3px; margin: 0; padding: 12px 12px 12px; text-align: left;
  font-size: 13.5px; font-weight: 700; line-height: 1.3; color: var(--ink);
  background: var(--card); border: 1.5px solid var(--line-2); border-radius: 12px; transition: border-color .15s, background .15s, box-shadow .15s;
}
#input-options .tab-btn:hover { color: var(--ink); border-color: #b9c9bd; background: #fafcfa; }
#input-options .tab-btn::before {
  content: ""; width: 34px; height: 34px; margin-bottom: 6px; border-radius: 9px; background: #f0f3f0 center / 20px no-repeat;
}
#input-options .tab-btn::after { font-size: 11.5px; font-weight: 400; line-height: 1.35; color: var(--muted); }
#input-options #opt-text::before { background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23617a6b' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'><path d='M5 6.5h14M5 11.5h14M5 16.5h8'/></svg>"); }
#input-options #opt-lot::before { background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23617a6b' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'><path d='M5 9l9-4 5 5-2 9-11-1z'/><circle cx='5' cy='9' r='1'/><circle cx='14' cy='5' r='1'/><circle cx='19' cy='10' r='1'/><circle cx='17' cy='19' r='1'/><circle cx='6' cy='18' r='1'/></svg>"); }
#input-options #opt-drawings::before { background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23617a6b' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'><rect x='4' y='4' width='16' height='16' rx='1.5'/><path d='M4 12h8M12 4v8M16 12v8'/></svg>"); }
#opt-text::after { content: "Gõ hoặc nói ra ngôi nhà bạn muốn"; }
#opt-lot::after { content: "Vẽ hình lô đất và nhập số đo"; }
#opt-drawings::after { content: "Tải bản vẽ từng tầng của bạn"; }
#input-options .tab-btn[aria-selected="true"] {
  color: var(--green); background: #eaf6ee; border-color: var(--green-bright); box-shadow: 0 0 0 1px var(--green-bright), 0 3px 10px rgba(43, 171, 82, .14);
}
#input-options .tab-btn[aria-selected="true"]::before { background-color: var(--green); }
#input-options .tab-btn[aria-selected="true"]::after { color: #3f6b4f; }
#input-options #opt-text[aria-selected="true"]::before { background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'><path d='M5 6.5h14M5 11.5h14M5 16.5h8'/></svg>"); }
#input-options #opt-lot[aria-selected="true"]::before { background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'><path d='M5 9l9-4 5 5-2 9-11-1z'/><circle cx='5' cy='9' r='1'/><circle cx='14' cy='5' r='1'/><circle cx='19' cy='10' r='1'/><circle cx='17' cy='19' r='1'/><circle cx='6' cy='18' r='1'/></svg>"); }
#input-options #opt-drawings[aria-selected="true"]::before { background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'><rect x='4' y='4' width='16' height='16' rx='1.5'/><path d='M4 12h8M12 4v8M16 12v8'/></svg>"); }
#input-options .tab-btn:focus-visible { outline: 2px solid var(--green-bright); outline-offset: 2px; }

/* Phones: one choice per row — the icon on the left, the name and its line beside it. */
@media (max-width: 600px) {
  #input-options { grid-template-columns: minmax(0, 1fr); gap: 8px; }
  #input-options .tab-btn { display: grid; grid-template-columns: 34px minmax(0, 1fr); column-gap: 12px; align-items: center; padding: 10px 12px; }
  #input-options .tab-btn::before { grid-column: 1; grid-row: 1 / span 2; margin-bottom: 0; }
  #input-options .tab-btn::after { grid-column: 2; }
}
@media (prefers-reduced-motion: reduce) { .bar span { transition: none; } }

/* Option 2, "Vẽ trên khung": the two numbers sit side by side (they are short) even on a phone, with the two ticks on
   one line under them, so the frame comes into view sooner. Beats the one-column `.row` of the narrow layouts. */
#lot-draw .row { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 10px; align-items: end; }
#lot-draw .row .field { margin-bottom: 8px; justify-content: flex-end; }
#lot-draw .check[data-lot-site] { display: inline-flex; margin: 0 18px 8px 0; }
#lot-draw .lot-tools { margin-top: 2px; }
