/* GENERATED — do not edit.
 *
 * Emitted from public/villa-concepts/styles.css, the locked Villa reference,
 * by Facelift/Villa/emit-route-css.mjs. Every rule is scoped under .villa-estate.
 * Facelift/Villa/fidelity.test.js runs the emitter with --check, so editing
 * this file by hand turns the suite red instead of silently drifting from the
 * reference it is supposed to reproduce.
 *
 * Change the reference, then re-run:
 *   node Facelift/Villa/emit-route-css.mjs
 */
.villa-estate {
  color-scheme: dark;
  --review-height: 72px;
  --game-header: 70px;
  --fl-black: #070605;
  --fl-night: #100c09;
  --fl-panel: rgba(15, 11, 8, .96);
  --fl-panel-soft: rgba(24, 17, 12, .94);
  --fl-ivory: #eee2ca;
  --fl-muted: #b4a58b;
  --fl-dim: #82735c;
  --fl-gold: #c99744;
  --fl-gold-hi: #e5c278;
  --fl-porphyry: #8a4f78;
  --fl-crimson: #a84e43;
  --fl-laurel: #91a75d;
  --fl-line: rgba(201, 151, 68, .34);
  --fl-soft-line: rgba(201, 151, 68, .17);
  --fl-ivory-line: rgba(238, 226, 202, .14);
  --font-display: 'Cinzel', Georgia, serif;
  --font-body: 'Inter', 'Segoe UI', sans-serif;
  --shadow-deep: 0 22px 52px rgba(0, 0, 0, .58);
}
.villa-estate { box-sizing: border-box; }
.villa-estate,
.villa-estate { margin: 0; min-width: 0; min-height: 100%; }
.villa-estate {
  overflow: hidden;
  background: var(--fl-black);
  color: var(--fl-ivory);
  font: 400 16px/1.45 var(--font-body);
  font-feature-settings: 'liga' 1, 'calt' 1, 'tnum' 1;
}
.villa-estate button,
.villa-estate input { border-radius: 0; color: inherit; font: inherit; }
.villa-estate button,
.villa-estate a { touch-action: manipulation; }
.villa-estate button:focus-visible,
.villa-estate a:focus-visible,
.villa-estate input:focus-visible,
.villa-estate [tabindex]:focus-visible {
  outline: 2px solid var(--fl-gold-hi);
  outline-offset: 2px;
}
.villa-estate button:disabled { cursor: not-allowed; opacity: .48; }
.villa-estate img { display: block; max-width: 100%; }
.villa-estate [hidden] { display: none !important; }
.villa-estate .route-crumb { display: flex; align-items: center; gap: 11px; min-width: 0; padding: 0 16px; }
.villa-estate .brand-mark {
  width: 34px;
  height: 38px;
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  border: 1px solid var(--fl-gold);
  background: linear-gradient(145deg, #291a0c, #100b07);
  color: var(--fl-gold-hi);
  font: 700 18px var(--font-display);
}
.villa-estate .route-crumb b { display: block; font: 700 14px/1.2 var(--font-display); letter-spacing: .055em; }
.villa-estate .route-crumb small { display: block; margin-top: 3px; color: var(--fl-dim); font-size: 11px; }
.villa-estate .route-crumb img { width: 38px; height: 38px; flex: 0 0 auto; object-fit: contain; }
.villa-estate .route-crumb span { min-width: 0; }
.villa-estate .route-crumb b,
.villa-estate .route-crumb small { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.villa-estate .section-title > span,
.villa-estate .panel-heading > span {
  color: var(--fl-gold);
  font-size: 10px;
  font-weight: 800;
  letter-spacing: .13em;
  text-transform: uppercase;
}
.villa-estate .section-title h2,
.villa-estate .panel-heading h2 { margin: 3px 0 0; font: 650 20px/1.2 var(--font-display); }
/* The dialog's × carries the same weight as the card's: a glyph, not a tile. */
.villa-estate .confirm-dialog header button { width: 38px; height: 38px; margin: -2px -4px -2px 0; border: 1px solid transparent; border-radius: 2px; background: none; color: var(--fl-muted); cursor: pointer; font-size: 19px; line-height: 1; transition: color .12s ease, background-color .12s ease, border-color .12s ease; }
.villa-estate .confirm-dialog header button:hover,
.villa-estate .confirm-dialog header button:focus-visible { border-color: rgba(201, 151, 68, .45); background: rgba(201, 151, 68, .12); color: var(--fl-gold-hi); }
.villa-estate .route-intro {
  display: grid;
  grid-template-columns: minmax(320px, 1fr) auto;
  align-items: center;
  min-height: 94px;
  padding: 14px 22px;
  border-bottom: 1px solid var(--fl-soft-line);
  background: linear-gradient(90deg, #0a0806, #151008 58%, #0c0907);
}
.villa-estate .eyebrow { margin: 0 0 3px; color: var(--fl-gold); font-size: 10px; font-weight: 800; letter-spacing: .15em; text-transform: uppercase; }
.villa-estate .route-intro h1 { margin: 0; font: 650 clamp(22px, 2.1vw, 31px)/1.12 var(--font-display); letter-spacing: .03em; }
.villa-estate .route-intro > div > p:last-child { margin: 4px 0 0; color: var(--fl-muted); font-size: 13px; }
.villa-estate .route-intro dl { display: flex; margin: 0; border: 1px solid var(--fl-soft-line); background: rgba(4, 3, 2, .38); }
.villa-estate .route-intro dl div { min-width: 104px; padding: 8px 12px; border-left: 1px solid var(--fl-soft-line); }
.villa-estate .route-intro dl div:first-child { border-left: 0; }
.villa-estate .route-intro dt { color: var(--fl-dim); font: 700 9px var(--font-display); letter-spacing: .09em; text-transform: uppercase; }
.villa-estate .route-intro dd { margin: 3px 0 0; font-size: 13px; font-weight: 750; font-variant-numeric: tabular-nums; }
.villa-estate .route-tabs {
  display: flex;
  height: 48px;
  padding: 0 22px;
  scrollbar-width: none;
  border-bottom: 1px solid var(--fl-line);
  background: #0b0806;
}
.villa-estate .route-tabs::-webkit-scrollbar { display: none; }
.villa-estate .route-tabs button {
  position: relative;
  min-width: 112px;
  padding: 0 18px;
  border: 0;
  border-left: 1px solid var(--fl-soft-line);
  background: transparent;
  color: #94866f;
  cursor: pointer;
  font: 700 11px var(--font-display);
  letter-spacing: .08em;
  text-transform: uppercase;
}
.villa-estate .route-tabs button:last-child { border-right: 1px solid var(--fl-soft-line); }
.villa-estate .route-tabs button:hover { background: #151008; color: var(--fl-ivory); }
.villa-estate .route-tabs button.is-active { box-shadow: inset 0 -2px var(--fl-gold-hi); background: linear-gradient(180deg, rgba(201, 151, 68, .14), transparent); color: var(--fl-gold-hi); }
.villa-estate .ready-dot { display: inline-grid; place-items: center; min-width: 20px; height: 20px; margin-left: 8px; border: 1px solid #78582b; border-radius: 999px; background: #34220f; color: var(--fl-gold-hi); font: 700 10px var(--font-body); }
.villa-estate .route-content { height: calc(100% - 142px); overflow: hidden; }
/* Shared controls and data structures */
.villa-estate .primary-button,
.villa-estate .secondary-button,
.villa-estate .quiet-link {
  min-height: 44px;
  border: 1px solid var(--fl-line);
  background: #17110b;
  cursor: pointer;
  font-size: 12px;
  font-weight: 750;
}
.villa-estate .primary-button {
  border-color: #c28d3a;
  background: linear-gradient(180deg, #a26d26, #654016);
  color: #fff1cb;
  font-family: var(--font-display);
  letter-spacing: .055em;
  text-shadow: 0 1px 0 #281707;
  text-transform: uppercase;
}
.villa-estate .primary-button:hover:not(:disabled) { border-color: var(--fl-gold-hi); background: linear-gradient(180deg, #bd8735, #76501d); }
.villa-estate .secondary-button:hover:not(:disabled),
.villa-estate .quiet-link:hover { border-color: var(--fl-gold); background: #24180d; color: var(--fl-gold-hi); }
.villa-estate .section-title { min-width: 0; }
.villa-estate .section-title h2 { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.villa-estate .meter { position: relative; width: 100%; height: 6px; overflow: hidden; border: 1px solid rgba(229, 194, 120, .24); background: #080604; }
.villa-estate .meter span { display: block; height: 100%; background: linear-gradient(90deg, #77501e, var(--fl-gold)); }
/* 01 — Living Estate */
.villa-estate .living-stage {
  position: relative;
  height: 100%;
  min-height: 590px;
  overflow: hidden;
  background: #181006 var(--scene) center / cover no-repeat;
}
.villa-estate .scene-scrim { position: absolute; inset: 0; pointer-events: none; background: radial-gradient(circle at 40% 45%, transparent 5%, rgba(4, 3, 2, .12) 43%, rgba(4, 3, 2, .76) 100%), linear-gradient(90deg, rgba(5, 4, 3, .16), rgba(6, 4, 2, .1) 50%, rgba(5, 3, 2, .78)); }
/* Meters: the fill is an <i> in production and was a <span> here; both draw. */
.villa-estate .meter i,
.villa-estate .meter span { display: block; height: 100%; background: linear-gradient(90deg, #77501e, var(--fl-gold)); }
.villa-estate .meter.is-full i,
.villa-estate .meter.is-full span { background: var(--fl-gold-hi); }
.villa-estate .meter.is-paused i,
.villa-estate .meter.is-paused span { background: #6a5a3c; }
/* The estate frame — identity, standing, and what the standing has earned.
   It sits at the FOOT of the scene, not over its head: the route header above
   the tabs was 103px at 1440 and 156px at 820, and the plaque that used to be
   in this corner repeated the tier and the level it already carried. One block
   at the bottom leaves the whole of the house art clear. */
.villa-estate .estate-frame {
  position: absolute;
  z-index: 3;
  bottom: 22px;
  left: 24px;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  gap: 4px 16px;
  max-width: min(560px, calc(100% - 48px));
  padding: 14px 20px 14px 14px;
  border: 1px solid var(--fl-line);
  background: linear-gradient(180deg, rgba(14, 10, 7, .93), rgba(9, 6, 4, .96));
  box-shadow: var(--shadow-deep);
}
/* The medallion carries the estate emblem, one of four, changing on the bands
   the scene art changes on. The numeral is not a caption on the art — it is the
   fallback: if the emblem is missing the ring still reads as a rank.
   It is a BUTTON (owner, 12.9.2026): pressing the household's own seal opens
   the Household Command card, and the rim carries how many buildings wait. */
.villa-estate .estate-medallion {
  position: relative;
  display: grid;
  place-items: center;
  width: 74px;
  height: 74px;
  grid-row: span 2;
  padding: 0;
  border: 1px solid var(--fl-gold);
  border-radius: 50%;
  background: radial-gradient(circle at 42% 34%, #2a1c0d, #0c0805 76%);
  box-shadow: inset 0 0 0 3px rgba(201, 151, 68, .16), 0 6px 20px rgba(0, 0, 0, .5);
  color: inherit;
  cursor: pointer;
  font: inherit;
}
.villa-estate .estate-medallion:hover,
.villa-estate .estate-medallion:focus-visible { border-color: var(--fl-gold-hi); box-shadow: inset 0 0 0 3px rgba(229, 194, 120, .3), 0 6px 20px rgba(0, 0, 0, .5), 0 0 0 4px rgba(201, 151, 68, .14); }
.villa-estate .estate-medallion.is-open { border-color: var(--fl-gold-hi); background: radial-gradient(circle at 42% 34%, #4a2f12, #17100a 76%); }
/* The painted emblem is a house on a transparent ground, fitted inside the
   ring's inscribed circle at delivery (docs/villa-estate-emblem-brief.md), so
   it may fill the ring's inner 66px almost to the rim. */
.villa-estate .estate-medallion img { position: absolute; width: 64px; height: 64px; object-fit: contain; }
/* The numeral IS the medallion until the emblem has actually loaded. The
   image's own onload adds has-estate-art and the numeral becomes a plinth under
   it; a failed image is removed and the numeral stays. The rest state is the
   numeral, never an empty ring: an <img> that has not answered yet used to
   demote the numeral to its plinth for an instant on every redraw, and the
   "1" flashed under an empty circle on every click (owner, 12.9.2026). */
.villa-estate .estate-medallion b {
  position: relative;
  align-self: center;
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  color: var(--fl-gold-hi);
  font: 700 27px/1.5 var(--font-display);
  font-variant-numeric: tabular-nums;
}
.villa-estate .estate-medallion.has-estate-art b {
  align-self: end;
  margin-bottom: -4px;
  padding: 0 7px;
  border: 1px solid var(--fl-gold);
  background: #100b07;
  font-size: 15px;
}
.villa-estate .estate-medallion .orders { position: absolute; z-index: 2; top: -4px; right: -4px; min-width: 22px; height: 22px; padding: 0 6px; border: 1px solid var(--fl-gold-hi); border-radius: 11px; background: #5a3a12; color: #fff1cb; font: 800 11px/20px var(--font-body); font-variant-numeric: tabular-nums; }
.villa-estate .estate-frame-id span,
.villa-estate .estate-frame-id strong,
.villa-estate .estate-frame-id small { display: block; }
.villa-estate .estate-frame-id span { color: #b1976b; font-size: 9px; font-weight: 800; letter-spacing: .18em; text-transform: uppercase; }
.villa-estate .estate-frame-id strong { margin: 3px 0 2px; color: #f0dcae; font: 650 20px var(--font-display); letter-spacing: .07em; }
.villa-estate .estate-frame-id small { color: var(--fl-muted); font-size: 12px; line-height: 1.45; }
/* Oma rivinsä: tason rivi on kehyksen levein, ja luku oli se osa joka
   katkesi 320 px:ssä. Leikkaus on kuoren eikä tämän reitin (sama V70:n
   goldenissa), mutta lukua jota ei voi lukea ei kannata pakottaa kilpailemaan
   leveydestä. */
.villa-estate .estate-hands { margin-top: 3px; color: var(--fl-gold-hi); font-weight: 700; }
/* The villa's own upgrade, beside the standing it raises (owner, 12.9.2026). */
.villa-estate .estate-upgrade { margin-top: 6px; min-height: 30px; font-size: 10px; }
.villa-estate .estate-upgrade-max { display: block; margin-top: 6px; color: var(--fl-dim); font-size: 9px; }
/* The three villa-level achievements. They have existed since V17 and the
   estate never mentioned them, so raising the villa paid a reward the player
   could not see. Earned ones are lit; the rest name the level that earns them.
   Each mark opens on hover, on keyboard focus and on tap. */
.villa-estate .estate-milestones { display: flex; gap: 14px; grid-column: 2; margin: 4px 0 0; padding: 8px 0 0; border-top: 1px solid var(--fl-soft-line); list-style: none; }
.villa-estate .estate-milestones li { position: relative; display: flex; align-items: center; gap: 7px; }
/* The dimming of an unearned mark sits on its button, not on the item: the
   detail that opens from the item must be opaque, and it inherited a 42%
   ghost of itself, readable through to the frame (owner, 12.9.2026). */
.villa-estate .estate-milestones button { display: flex; align-items: center; gap: 6px; width: 100%; padding: 0; border: 0; background: none; color: inherit; cursor: pointer; font: inherit; text-align: left; opacity: .42; }
.villa-estate .estate-milestones li.is-earned button { opacity: 1; }
.villa-estate .estate-milestones img { width: 28px; height: 28px; flex: 0 0 auto; object-fit: contain; }
.villa-estate .estate-milestones b,
.villa-estate .estate-milestones small { display: block; white-space: nowrap; }
.villa-estate .estate-milestones b { color: var(--fl-ivory); font: 700 10px var(--font-display); letter-spacing: .03em; }
.villa-estate .estate-milestones small { margin-top: 1px; color: var(--fl-dim); font-size: 9px; }
.villa-estate .estate-milestones li.is-earned small { color: var(--fl-gold); }
.villa-estate .milestone-detail { position: absolute; z-index: 40; bottom: calc(100% + 8px); left: 0; display: none; width: max-content; max-width: 240px; padding: 9px 11px; border: 1px solid rgba(229, 194, 120, .55); background: #15100a; box-shadow: 0 10px 28px rgba(0, 0, 0, .7); pointer-events: none; }
/* One detail at a time: hover shows a mark only while none is pinned open, so
   a pinned mark and a hovered neighbour never stand on top of each other. */
.villa-estate .estate-milestones:not(:has(li.is-open)) li:hover .milestone-detail,
.villa-estate .estate-milestones button:focus-visible ~ .milestone-detail,
.villa-estate .estate-milestones li.is-open .milestone-detail { display: block; }
.villa-estate .milestone-detail b { display: block; color: #f0dcae; font: 700 12px var(--font-display); letter-spacing: .04em; }
.villa-estate .milestone-detail small { display: block; margin-top: 3px; color: #d9ccb0; font-size: 11px; line-height: 1.45; white-space: normal; }
.villa-estate .milestone-detail em { display: block; margin-top: 5px; color: var(--fl-gold-hi); font-size: 9.5px; font-style: normal; letter-spacing: .08em; text-transform: uppercase; }
/* The points are achievement points — the tessera says so, and so does the word: the header already has an "AP" that means action points (owner, 12.9.2026). */
.villa-estate .milestone-detail em img { display: inline-block; width: 12px; height: 12px; margin-right: 4px; object-fit: contain; vertical-align: -2px; }
/* The keys to the building cards when the hotspots are not on screen: below
   1120px they collide with the house and are hidden, and a phone never had
   them. Three chips in the frame carry the same fact the hotspots do. */
/* A grid, not a flex row: three minmax(0, 1fr) tracks cannot widen the frame, where three nowrap chips in a flex row pushed a phone past its edge. */
.villa-estate .building-chips { display: none; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; grid-column: 1 / -1; min-width: 0; margin-top: 6px; }
.villa-estate .building-chip { display: grid; grid-template-columns: 20px minmax(0, 1fr); align-items: center; gap: 1px 7px; min-width: 0; min-height: 44px; padding: 5px 8px; border: 1px solid var(--fl-ivory-line); background: rgba(24, 17, 11, .84); color: var(--fl-muted); cursor: pointer; text-align: left; }
.villa-estate .building-chip:hover { border-color: var(--fl-line); background: #20160d; }
.villa-estate .building-chip[aria-pressed='true'] { border-color: var(--fl-gold); background: #26190d; }
.villa-estate .building-chip img { width: 20px; height: 20px; grid-row: span 2; object-fit: contain; }
.villa-estate .building-chip b { overflow: hidden; color: var(--fl-ivory); font: 700 9.5px var(--font-display); text-overflow: ellipsis; white-space: nowrap; }
.villa-estate .building-chip small { overflow: hidden; color: var(--fl-dim); font-size: 9px; text-overflow: ellipsis; white-space: nowrap; }
.villa-estate .building-chip.is-ready small { color: var(--fl-gold-hi); }
/* Hotspots pin each building in the scene. They OPEN the building's card and
   nothing else; the gold dot on the mark says a harvest is waiting. */
.villa-estate .estate-hotspot {
  position: absolute;
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 50px;
  padding: 5px 11px 5px 6px;
  border: 1px solid rgba(229, 194, 120, .58);
  background: rgba(10, 7, 4, .92);
  box-shadow: 0 8px 24px rgba(0, 0, 0, .46);
  cursor: pointer;
  text-align: left;
}
.villa-estate .estate-hotspot::after { content: ''; position: absolute; left: 22px; bottom: -10px; width: 10px; height: 10px; border-right: 1px solid var(--fl-gold); border-bottom: 1px solid var(--fl-gold); background: #0d0906; transform: rotate(45deg); }
.villa-estate .hotspot-mark { position: relative; display: grid; place-items: center; width: 36px; height: 36px; border: 1px solid var(--fl-gold); background: #2c1a0b; color: var(--fl-gold-hi); font: 700 14px var(--font-display); }
.villa-estate .estate-hotspot.is-ready .hotspot-mark::after { content: ''; position: absolute; top: -5px; right: -5px; width: 9px; height: 9px; border-radius: 50%; background: var(--fl-gold-hi); box-shadow: 0 0 0 2px #0d0906, 0 0 8px rgba(229, 194, 120, .9); }
.villa-estate .estate-hotspot b,
.villa-estate .estate-hotspot small { display: block; white-space: nowrap; }
/* Pinni kantaa nyt kolme asiaa (kadet, saalis, taysi), joten sen toinen rivi
   saa kaartya kahdelle - muuten se leikkaisi juuri sen materiaalin nimen
   jonka takia pelaaja katsoo. Leveys on rajattu, jottei pinni peita taloa. */
.villa-estate .estate-hotspot small { max-width: 210px; white-space: normal; }
.villa-estate .estate-hotspot small em {
  display: inline-block; margin-left: 4px; padding: 0 4px;
  border: 1px solid rgba(229, 194, 120, .55); border-radius: 2px;
  color: var(--fl-gold-hi); font-size: 8.5px; font-style: normal;
  font-weight: 800; letter-spacing: .08em; text-transform: uppercase;
}
.villa-estate .estate-hotspot b { color: var(--fl-ivory); font: 700 11px var(--font-display); letter-spacing: .03em; }
.villa-estate .estate-hotspot small { margin-top: 2px; color: #d7b978; font-size: 10px; }
/* The mark: the building's own icon once it has loaded, the initial letter
   until then (commissioned art, docs/villa-building-icons-brief.md). The
   letter is the rest state, so a missing file never shows an empty square. */
.villa-estate .hotspot-mark b { display: block; margin: 0; color: var(--fl-gold-hi); font: 700 14px var(--font-display); letter-spacing: 0; white-space: nowrap; }
.villa-estate .hotspot-mark img { position: absolute; inset: 0; width: 28px; height: 28px; margin: auto; object-fit: contain; }
.villa-estate .hotspot-mark.has-estate-art b { visibility: hidden; }
.villa-estate .estate-hotspot:hover { background: #1b1108; transform: translateY(-1px); }
.villa-estate .estate-hotspot.is-selected { border-color: var(--fl-gold-hi); background: #24170b; box-shadow: 0 8px 24px rgba(0, 0, 0, .46), 0 0 0 2px rgba(201, 151, 68, .18); }
.villa-estate .estate-hotspot.is-selected .hotspot-mark { border-color: var(--fl-gold-hi); background: #6b4418; }
/* PINNIT OSOITTAVAT SITA MITA NE NIMEAVAT (omistaja 12.9.2026).
   Mitattu kuvan koordinaatistossa kaikista neljasta tasotaiteesta: ovi on
   x 33-42 %, y 25-58 % ja istutukset y 68-95 % jokaisessa niista, joten yksi
   sijainti kelpaa kaikille tasoille. Muunnos kuvasta lavaan: kohtaus on
   cover, joten VAAKASUUNNASSA kuvan % on lavan %, ja pystysuunnassa
   lava-% = kuva-% x 1,332 - 16,6 (1440x900:n rajaus). Nuoli on 22 px
   laatikon vasemmasta reunasta ja 10 px sen alta, eli laatikko istuu
   kohteen YLLA ja nuoli osuu siihen. */
.villa-estate .hotspot-workshop { top: 34%; left: 4%; }
.villa-estate .hotspot-treasury { top: 38%; left: 36.5%; }
.villa-estate .hotspot-garden { top: 80%; left: 38%; }
/* The Aedicula — the card (owner-selected 02, 12.9.2026, docs/design/52-household-command.md).
   One card at a time, docked where the household panel stood: a stone lintel
   carries the name, a hero band carries the building's own materials in its
   own hue, two column lines hold the sides, and the body is laid in courses.
   The hue is a colour of meaning (BRAND 3.1): gold is the coin, laurel the
   walled grounds, ember the yard. It says WHERE the player is, and nothing else
   on the route uses it. */
.villa-estate .hue-gold { --hue: #c99744; --hue-hi: #e5c278; --hue-deep: #3a2408; --hue-soft: rgba(201, 151, 68, .18); --hue-meter0: #77501e; }
.villa-estate .hue-ember { --hue: #cf8a4c; --hue-hi: #e8a86c; --hue-deep: #3d200c; --hue-soft: rgba(207, 138, 76, .18); --hue-meter0: #7a4a22; }
.villa-estate .hue-laurel { --hue: #91a75d; --hue-hi: #b5c97c; --hue-deep: #1e2a12; --hue-soft: rgba(145, 167, 93, .18); --hue-meter0: #4f6030; }
.villa-estate .hue-estate { --hue: #e5c278; --hue-hi: #f6e3b5; --hue-deep: #2e1e0c; --hue-soft: rgba(229, 194, 120, .2); --hue-meter0: #77501e; }
.villa-estate .aedicula {
  position: absolute;
  z-index: 7;
  top: 18px;
  right: 18px;
  bottom: 22px;
  display: grid;
  grid-template-rows: auto auto minmax(0, 1fr);
  width: min(440px, 40vw);
  border: 1px solid var(--fl-gold);
  background: rgba(12, 9, 7, .97);
  box-shadow: var(--shadow-deep), inset 0 0 0 1px rgba(0, 0, 0, .7), inset 0 0 0 2px rgba(201, 151, 68, .13);
}
.villa-estate .lintel { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 10px; padding: 10px 14px; border-bottom: 1px solid rgba(201, 151, 68, .5); background: linear-gradient(180deg, #3b2a15, #241a0e); box-shadow: inset 0 1px 0 rgba(255, 235, 190, .14), inset 0 -1px 0 rgba(0, 0, 0, .6); }
.villa-estate .lintel .eyebrow { color: var(--hue); }
.villa-estate .lintel h3 { margin: 2px 0 0; overflow: hidden; font: 700 17px/1.15 var(--font-display); letter-spacing: .09em; text-overflow: ellipsis; text-transform: uppercase; color: #f0dcae; text-shadow: 0 1px 0 #000; white-space: nowrap; }
.villa-estate .lintel h3 em { margin-left: 8px; color: var(--fl-dim); font: 700 10px var(--font-body); font-style: normal; letter-spacing: .02em; text-transform: none; }
/* The × is a glyph on the lintel, not a black tile laid over it. It was a
   filled 36px square in near-black with its own border, and against the warm
   stone of the lintel it read as the heaviest thing in the header (owner,
   12.9.2026). The hit area is untouched — only the paint goes, and it comes
   back on hover and focus so the control is still a control. */
.villa-estate .close-x { display: grid; place-items: center; width: 34px; height: 34px; margin: -2px -6px -2px 0; border: 1px solid transparent; border-radius: 2px; background: none; color: var(--fl-muted); cursor: pointer; font-size: 18px; line-height: 1; transition: color .12s ease, background-color .12s ease, border-color .12s ease; }
.villa-estate .close-x:hover,
.villa-estate .close-x:focus-visible { border-color: rgba(201, 151, 68, .45); background: rgba(201, 151, 68, .12); color: var(--fl-gold-hi); }
.villa-estate .hero { position: relative; display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: 14px; min-height: 116px; padding: 14px 22px 12px; overflow: hidden; border-bottom: 1px solid var(--fl-soft-line); background: radial-gradient(ellipse at 18% 0%, var(--hue-soft), transparent 58%), linear-gradient(180deg, var(--hue-deep), #100b07); }
.villa-estate .hero::before,
.villa-estate .hero::after { content: ''; position: absolute; top: 0; bottom: 0; width: 1px; background: linear-gradient(180deg, var(--hue), transparent 92%); opacity: .55; }
.villa-estate .hero::before { left: 9px; box-shadow: 2px 0 0 rgba(0, 0, 0, .5); }
.villa-estate .hero::after { right: 9px; box-shadow: -2px 0 0 rgba(0, 0, 0, .5); }
.villa-estate .hero-art { position: relative; width: 76px; height: 76px; }
.villa-estate .hero-art img { position: absolute; width: 62px; height: 62px; object-fit: contain; filter: drop-shadow(0 8px 12px rgba(0, 0, 0, .7)); }
.villa-estate .hero-art img:nth-child(1) { top: 0; left: 0; }
.villa-estate .hero-art img:nth-child(2) { top: 22px; left: 22px; width: 50px; height: 50px; }
.villa-estate .hero-art.is-single img { top: 7px; left: 7px; }
/* The household's hero is the same medallion the frame carries: the emblem
   when it exists, the level numeral when it does not (onerror, :first-child). */
.villa-estate .hero-art .medal { position: absolute; inset: 0; display: grid; place-items: center; border: 1px solid var(--hue); border-radius: 50%; background: radial-gradient(circle at 42% 34%, #3a2710, #0c0805 76%); box-shadow: inset 0 0 0 3px rgba(229, 194, 120, .16), 0 8px 20px rgba(0, 0, 0, .6); color: var(--hue-hi); font: 700 30px var(--font-display); }
.villa-estate .hero-art .medal img { position: absolute; top: 6px; left: 6px; width: 64px; height: 64px; filter: none; }
.villa-estate .hero-art .medal b { display: block; }
.villa-estate .hero-art .medal.has-estate-art b { display: none; }
.villa-estate .hero-fig { min-width: 0; }
.villa-estate .hero-fig > b { display: block; overflow: hidden; color: var(--hue-hi); font: 700 27px/1 var(--font-display); letter-spacing: .02em; text-overflow: ellipsis; white-space: nowrap; }
.villa-estate .hero-fig > b small { margin-left: 4px; color: var(--fl-muted); font: 500 12px var(--font-body); letter-spacing: 0; }
.villa-estate .hero-fig span { display: block; margin-top: 5px; color: var(--fl-muted); font-size: 11px; }
.villa-estate .hero-fig span b { display: inline; color: var(--fl-ivory); font: 700 11px var(--font-body); }
.villa-estate .plinth { align-self: start; padding: 4px 10px; border: 1px solid var(--hue); background: rgba(0, 0, 0, .45); color: var(--hue-hi); font: 700 12px var(--font-display); letter-spacing: .06em; white-space: nowrap; }
/* align-content: start — a short card (the treasury has one pile) must not stretch its courses over the panel height. */
.villa-estate .estate-card-body { display: grid; align-content: start; gap: 12px; padding: 12px 14px 14px; overflow: auto; }
.villa-estate .blurb { margin: 0; color: var(--fl-muted); font-size: 13px; line-height: 1.5; }
.villa-estate .course { display: grid; gap: 7px; }
.villa-estate .course-title { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; padding-bottom: 4px; border-bottom: 1px solid var(--fl-soft-line); color: var(--hue); font: 700 12px var(--font-display); letter-spacing: .1em; text-transform: uppercase; }
.villa-estate .course-title small { color: var(--fl-dim); font: 600 12px var(--font-body); letter-spacing: .02em; text-transform: none; }
/* The active project, inside whichever card it concerns. */
.villa-estate .works-strip { display: flex; align-items: center; gap: 11px; min-height: 48px; padding: 7px 10px; border: 1px solid var(--fl-soft-line); background: #181109; }
.villa-estate .works-strip img { width: 27px; height: 27px; }
.villa-estate .works-strip b,
.villa-estate .works-strip small { display: block; }
.villa-estate .works-strip b { color: var(--fl-ivory); font-size: 12px; }
.villa-estate .works-strip small { margin-top: 2px; color: #a99473; font-size: 10px; }
/* What the building actually holds, named. A workshop stores Gold Ore and
   Ebony Log; "Materials" is a category and tells the player nothing about
   whether this is the pile they came for. */
.villa-estate .yields { display: grid; gap: 7px; }
.villa-estate .yield { display: grid; grid-template-columns: 22px minmax(0, 1fr) auto; grid-template-areas: 'ic name count' 'ic meter meter'; align-items: center; gap: 3px 8px; }
.villa-estate .yield img { grid-area: ic; width: 22px; height: 22px; object-fit: contain; }
.villa-estate .yield .y-name { grid-area: name; overflow: hidden; color: var(--fl-muted); font-size: 14px; text-overflow: ellipsis; white-space: nowrap; }
.villa-estate .yield .y-count { grid-area: count; color: var(--hue-hi); font-size: 14px; font-weight: 700; font-variant-numeric: tabular-nums; white-space: nowrap; }
.villa-estate .yield .y-count small { color: var(--fl-dim); font-size: 9.5px; font-weight: 400; }
.villa-estate .yield .meter { grid-area: meter; }
.villa-estate .aedicula .meter i,
.villa-estate .aedicula .meter span { background: linear-gradient(90deg, var(--hue-meter0), var(--hue)); }
.villa-estate .aedicula .meter.is-full i,
.villa-estate .aedicula .meter.is-full span { background: var(--fl-gold-hi); }
.villa-estate .aedicula .meter.is-paused i,
.villa-estate .aedicula .meter.is-paused span { background: #6a5a3c; }
.villa-estate .facts { display: grid; grid-template-columns: 1fr 1fr; border: 1px solid var(--fl-soft-line); }
.villa-estate .facts > div { min-width: 0; padding: 7px 9px; border-left: 1px solid var(--fl-soft-line); }
.villa-estate .facts > div:first-child,
.villa-estate .facts > div:nth-child(3) { border-left: 0; }
.villa-estate .facts > div:nth-child(n + 3) { border-top: 1px solid var(--fl-soft-line); }
.villa-estate .facts small { display: block; color: var(--fl-dim); font-size: 8.5px; letter-spacing: .07em; text-transform: uppercase; }
.villa-estate .facts b { display: block; margin-top: 2px; overflow: hidden; color: var(--fl-ivory); font-size: 14px; font-weight: 650; font-variant-numeric: tabular-nums; text-overflow: ellipsis; white-space: nowrap; }
.villa-estate .estate-card-actions { display: grid; grid-template-columns: 1.35fr 1fr; gap: 7px; }
.villa-estate .estate-card-actions.is-single { grid-template-columns: 1fr; }
.villa-estate .estate-card-actions button { min-height: 42px; }
/* The household's orders: one row per building, each a key to that building's
   card, with the building's hue as its stripe. */
.villa-estate .orders { display: grid; gap: 1px; border: 1px solid var(--fl-soft-line); background: var(--fl-soft-line); }
.villa-estate .order { display: grid; grid-template-columns: 4px 24px minmax(0, 1fr) auto; align-items: center; gap: 2px 9px; min-height: 44px; padding: 5px 9px 5px 6px; border: 0; background: rgba(18, 13, 8, .94); color: var(--fl-muted); cursor: pointer; text-align: left; }
.villa-estate .order:hover { background: #20160d; }
.villa-estate .order i { grid-column: 1; grid-row: 1 / span 2; width: 4px; height: 100%; background: var(--hue); }
.villa-estate .order img { grid-column: 2; grid-row: 1 / span 2; width: 24px; height: 24px; object-fit: contain; }
.villa-estate .order b { grid-column: 3; grid-row: 1; overflow: hidden; color: var(--fl-ivory); font: 700 10.5px var(--font-display); letter-spacing: .06em; text-overflow: ellipsis; text-transform: uppercase; white-space: nowrap; }
.villa-estate .order b em { margin-left: 5px; color: var(--fl-dim); font: 700 11px var(--font-body); font-style: normal; letter-spacing: 0; text-transform: none; }
.villa-estate .order small { grid-column: 3; grid-row: 2; overflow: hidden; color: var(--fl-muted); font-size: 9.5px; text-overflow: ellipsis; white-space: nowrap; }
.villa-estate .order .order-count { grid-column: 4; grid-row: 1 / span 2; color: var(--fl-gold-hi); font-size: 14px; font-weight: 700; font-variant-numeric: tabular-nums; text-align: right; white-space: nowrap; }
.villa-estate .order .order-count small { display: block; color: var(--fl-laurel); font-size: 8.5px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; }
.villa-estate .order.is-building .order-count { color: var(--fl-dim); }
.villa-estate .order.is-building .order-count small { color: var(--fl-gold-hi); }
.villa-estate .order.is-empty .order-count,
.villa-estate .order.is-empty .order-count small { color: var(--fl-dim); }
/* Who is working. One line per hand: what they gather, how full the basket is,
   and whether it has stopped. A full bar is the only state here that costs the
   player anything — the basket has stopped filling and waits on them.
   The work selector IS the row heading (owner, 12.9.2026): it names the work
   and what the work yields, and it is the control that changes them. The
   material selector keeps its own row underneath, indented, and only appears
   where there is a choice to make. Styled to read as a line, not as a form. */
.villa-estate .worker-note { margin: 0; color: var(--fl-dim); font-size: 12px; line-height: 1.45; }
.villa-estate .worker-line { border-bottom: 1px solid var(--fl-ivory-line); }
.villa-estate .worker-line:last-child { border-bottom: 0; }
/* The line at rest is one button: material, role, basket, meter, state, and a
   caret that says it opens. A post beyond the estate's posts has nothing to
   change and is a plain line. */
.villa-estate .worker-line-head { display: grid; grid-template-columns: 18px minmax(0, 1fr) auto 60px 30px 14px; align-items: center; gap: 6px; width: 100%; min-height: 30px; padding: 3px 2px 3px 0; border: 0; background: none; color: inherit; cursor: pointer; font: inherit; text-align: left; }
.villa-estate .worker-line-head.is-fixed { grid-template-columns: 18px minmax(0, 1fr) auto 60px 30px; cursor: default; }
.villa-estate .worker-line-head:not(.is-fixed):hover { background: rgba(201, 151, 68, .06); }
.villa-estate .worker-line-head > img { width: 16px; height: 16px; object-fit: contain; }
.villa-estate .worker-line-name { display: grid; min-width: 0; }
.villa-estate .worker-line-name b { overflow: hidden; color: var(--fl-ivory); font-size: 14px; text-overflow: ellipsis; white-space: nowrap; }
.villa-estate .worker-line-name small { overflow: hidden; color: var(--fl-dim); font-size: 12px; text-overflow: ellipsis; white-space: nowrap; }
.villa-estate .worker-line-count { color: var(--fl-gold-hi); font-size: 14px; font-variant-numeric: tabular-nums; white-space: nowrap; }
.villa-estate .worker-line-count small { color: var(--fl-dim); font-size: 12px; }
.villa-estate .worker-line-state { color: var(--fl-dim); font-size: 11px; text-align: right; text-transform: uppercase; }
.villa-estate .worker-line-caret { position: relative; width: 14px; height: 14px; }
.villa-estate .worker-line-caret::before { content: ''; position: absolute; top: 2px; left: 4px; width: 5px; height: 5px; border-right: 1px solid var(--fl-dim); border-bottom: 1px solid var(--fl-dim); transform: rotate(45deg); }
.villa-estate .worker-line.is-open .worker-line-head { background: rgba(201, 151, 68, .06); }
.villa-estate .worker-line.is-open .worker-line-caret::before { top: 5px; border-color: var(--fl-gold-hi); transform: rotate(225deg); }
/* The editor under an open line: the work, and the material where there is a
   choice, each full width so "Scriptorium Hand · Glimmer Dust" is never cut. */
.villa-estate .worker-line-edit { display: grid; gap: 7px; padding: 4px 0 9px 24px; }
.villa-estate .worker-line-edit label { display: grid; gap: 3px; }
.villa-estate .worker-line-edit label > span { color: var(--fl-dim); font-size: 8.5px; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; }
.villa-estate .worker-line-edit select { width: 100%; min-height: 40px; padding: 0 8px; border: 1px solid var(--fl-soft-line); border-radius: 0; background: #0b0806; color: var(--fl-ivory); font: 600 14px var(--font-body); }
.villa-estate .worker-line-edit select:hover,
.villa-estate .worker-line-edit select:focus-visible { border-color: var(--fl-line); }
.villa-estate .worker-line.is-full .worker-line-count,
.villa-estate .worker-line.is-full .worker-line-state { color: var(--fl-gold-hi); }
.villa-estate .worker-line.is-paused .worker-line-head { opacity: .6; }
/* A post the estate no longer opens. It still exists and still shows, but it
   produces nothing, and silence there reads as a bug. */
.villa-estate .worker-line.is-over-cap .worker-line-head { opacity: .62; }
.villa-estate .worker-line.is-over-cap .worker-line-name small { color: #c9925a; }
/* Gold amounts carry the game's own coin so the currency is identified rather
   than left as an anonymous number. */
.villa-estate .gold-amount { display: inline-flex; align-items: center; gap: 5px; font-variant-numeric: tabular-nums; }
.villa-estate .gold-amount img { width: 14px; height: 14px; object-fit: contain; flex: none; }
.villa-estate .gold-amount.is-large img { width: 26px; height: 26px; }
.villa-estate .inspector-sigil { position: relative; display: grid; place-items: center; width: 96px; height: 96px; margin: 15px auto; border: 1px solid var(--fl-line); background: radial-gradient(circle, #34210e, #100b07 70%); }
.villa-estate .inspector-sigil::before,
.villa-estate .inspector-sigil::after { content: ''; position: absolute; inset: 6px; border: 1px solid var(--fl-soft-line); transform: rotate(45deg); }
.villa-estate .inspector-sigil::after { inset: 13px; }
.villa-estate .inspector-sigil img { position: relative; z-index: 2; width: 44px; height: 44px; object-fit: contain; }
.villa-estate .inspector-sigil span { position: absolute; z-index: 3; right: -5px; bottom: -5px; padding: 3px 7px; border: 1px solid var(--fl-line); background: #181008; color: var(--fl-gold-hi); font-size: 10px; font-weight: 800; }
.villa-estate .empty-note { padding: 20px; border: 1px dashed var(--fl-soft-line); color: var(--fl-dim); font-size: 12px; text-align: center; }
/* Confirmation and feedback */
.villa-estate .modal-layer { position: fixed; z-index: 450; inset: 0; display: grid; place-items: center; padding: 20px; background: rgba(0, 0, 0, .76); }
.villa-estate .confirm-dialog { width: min(530px, 100%); border: 1px solid var(--fl-gold); background: #100c09; box-shadow: 0 28px 90px #000; }
.villa-estate .confirm-dialog > header { display: flex; justify-content: space-between; align-items: center; padding: 16px 18px; border-bottom: 1px solid var(--fl-line); }
.villa-estate .confirm-dialog header span { color: var(--fl-gold); font-size: 9px; font-weight: 800; letter-spacing: .13em; text-transform: uppercase; }
.villa-estate .confirm-dialog h2 { margin: 3px 0 0; font: 650 20px var(--font-display); }
.villa-estate .confirm-dialog > p { margin: 0; padding: 16px 18px 10px; color: var(--fl-muted); font-size: 13px; }
.villa-estate .confirm-dialog dl { margin: 4px 18px 14px; border: 1px solid var(--fl-soft-line); }
.villa-estate .confirm-dialog dl div { display: flex; justify-content: space-between; padding: 8px 10px; border-bottom: 1px solid var(--fl-soft-line); }
.villa-estate .confirm-dialog dl div:last-child { border-bottom: 0; }
.villa-estate .confirm-dialog dt { color: var(--fl-dim); font-size: 11px; }
.villa-estate .confirm-dialog dd { margin: 0; font-size: 11px; font-weight: 750; font-variant-numeric: tabular-nums; }
/* The price block's colour is its STATE, not its decoration. It was crimson in
   every case, so a project the player could afford said "Available" in the
   colour this game uses for a blocker — and red reads as "not possible" before
   the word is read at all (owner, 12.9.2026). Laurel when the price is within
   reach, crimson only when something actually stands in the way: missing gold,
   or another project already underway. BRAND 3.1 and section 7 — a colour
   carries one meaning, and the word carries it too. */
.villa-estate .confirm-price { margin: 0 18px 16px; padding: 12px; border-left: 3px solid var(--fl-laurel); background: rgba(145, 167, 93, .08); }
.villa-estate .confirm-price.is-blocked { border-left-color: var(--fl-crimson); background: rgba(168, 78, 67, .08); }
.villa-estate .confirm-price span,
.villa-estate .confirm-price strong,
.villa-estate .confirm-price small { display: block; }
.villa-estate .confirm-price span { color: var(--fl-dim); font-size: 9px; text-transform: uppercase; }
.villa-estate .confirm-price strong { display: flex; align-items: center; gap: 6px; margin-top: 3px; font-size: 17px; }
.villa-estate .confirm-price strong img { width: 18px; height: 18px; }
.villa-estate .confirm-price small { margin-top: 3px; color: #b5c97c; font-size: 11px; }
.villa-estate .confirm-price.is-blocked small { color: #d68578; }
.villa-estate .confirm-dialog footer { display: grid; grid-template-columns: 1fr 1.5fr; gap: 8px; padding: 14px 18px 18px; border-top: 1px solid var(--fl-soft-line); }
@media (max-width: 1280px) {
  /* Dokattu kortti peittaa oikean laidan taalla, joten pinnit vaistavat
     vasemmalle - kohteen paalta ne eivat silti siirry kauaksi. */
  .villa-estate .hotspot-treasury { left: 29%; }
  .villa-estate .hotspot-garden { left: 32%; }
}
@media (max-width: 1120px) {
  .villa-estate .route-intro dl div { min-width: 88px; padding: 8px 9px; }
  /* The hotspots collide with the house from here down. The frame's chips are
     the keys to the building cards instead — same fact, same target. */
  .villa-estate .estate-hotspot { display: none; }
  .villa-estate .building-chips { display: grid; }
  .villa-estate .aedicula { width: 440px; }
}
@media (max-width: 900px) {
  .villa-estate { overflow: auto; padding-bottom: calc(66px + env(safe-area-inset-bottom)); }
  .villa-estate .route-crumb { padding: 0 11px; }
  .villa-estate .route-crumb img { width: 33px; height: 33px; }
  .villa-estate .route-crumb b { font-size: 12px; }
  .villa-estate .route-intro { grid-template-columns: 1fr; min-height: auto; padding: 14px 16px; }
  .villa-estate .route-intro dl { margin-top: 12px; }
  .villa-estate .route-intro > div > p:last-child { font-size: 12px; }
  .villa-estate .route-tabs { position: sticky; z-index: 25; top: 0; height: 48px; overflow-x: auto; padding: 0 8px; }
  .villa-estate .route-tabs button { min-width: 100px; padding: 0 12px; }
  .villa-estate .route-content { height: auto; overflow: visible; }
  .villa-estate .living-stage { height: auto; min-height: 0; overflow: visible; }
  /* KOHTAUS TAYTTI KORKEUTENSA, EI LEVEYTTAAN. background-size: auto 300px
     pitaa taiteen kuvasuhteen ja keskittaa sen, joten jokaisella ruudulla
     joka on kapeampi kuin 1,5 x kaistan korkeus talo istui keskella ja sivun
     oma tumma pohja nakyi molemmin puolin - kirjekuori, ei nayttamo
     (omistaja 12.9.2026, puhelimella). Kaista on nyt oma kerroksensa joka
     PEITTAA leveytensa ja rajaa pystysuunnassa, joten taide ulottuu reunoihin
     joka leveydella eika alla oleva sisalto liiku. */
  .villa-estate .living-stage { padding-top: 300px; background-image: none; }
  .villa-estate .living-stage::before {
    content: ''; position: absolute; z-index: 0; top: 0; right: 0; left: 0; height: 300px;
    background: #181006 var(--scene) 38% 45% / cover no-repeat;
  }
  .villa-estate .living-stage::after { content: ''; position: absolute; z-index: 1; top: 260px; right: 0; left: 0; height: 50px; background: linear-gradient(transparent, #0b0806); }
  .villa-estate .living-stage .scene-scrim { height: 300px; background: linear-gradient(180deg, rgba(5, 3, 2, .12), rgba(5, 3, 2, .78)); }
  /* Below 900px the stage is a column: the scene on top, the frame under it,
     and the open card under the frame. The card stops floating and becomes the
     block the page scrolls to. */
  .villa-estate .estate-frame { position: relative; z-index: 2; inset: auto; max-width: none; width: 100%; margin: 0 0 12px; border-right: 0; border-left: 0; box-shadow: none; }
  .villa-estate .aedicula { position: relative; z-index: 2; inset: auto; grid-template-rows: auto auto auto; width: 100%; border-right: 0; border-left: 0; box-shadow: none; }
  .villa-estate .estate-card-body { overflow: visible; }
}
@media (max-width: 560px) {
  .villa-estate .route-crumb small { display: none; }
  .villa-estate .route-intro h1 { font-size: 22px; }
  .villa-estate .route-intro dl { display: grid; grid-template-columns: repeat(3, 1fr); }
  .villa-estate .route-intro dl div { min-width: 0; padding: 7px; }
  .villa-estate .route-intro dd { font-size: 10px; }
  /* The first screen has to reach a control. Measured in the real app at
     390×844: the route intro, the app's own tab strip and a 250px scene pushed
     the first building card to y=827 of an 844-tall viewport, so the player
     landed on a picture and a heading with nothing to press. BRAND section 8
     is explicit — the hero must not take the whole first screen without a
     usable action. The scene stays; it just stops being the whole screen. */
  /* The scene was cut to 176px to make room for a route header that no longer
     exists. With the header gone the house gets that space back. The keys to
     the cards are now the chips in the frame, directly under the scene. */
  .villa-estate .living-stage { padding-top: 208px; }
  .villa-estate .living-stage::before { height: 220px; }
  .villa-estate .living-stage .scene-scrim { height: 220px; }
  .villa-estate .living-stage::after { top: 184px; }
  .villa-estate .estate-frame { grid-template-columns: auto minmax(0, 1fr); gap: 3px 12px; padding: 11px 12px; }
  .villa-estate .estate-medallion { width: 58px; height: 58px; }
  .villa-estate .estate-medallion img { width: 50px; height: 50px; }
  .villa-estate .estate-frame-id strong { font-size: 16px; }
  /* Three milestones will not sit in a row at 390px without truncating their
     names, and the name is the reward. They stack, and the icons carry the row. */
  .villa-estate .estate-milestones { grid-column: 1 / -1; flex-wrap: wrap; gap: 8px 12px; }
  /* The route's own sentence is the first thing to go: the tab strip below it
     already says where the player is. */
  .villa-estate .route-intro > div > p:last-child { display: none; }
  .villa-estate .estate-frame { padding: 10px 11px; }
  .villa-estate .estate-frame-id strong { font-size: 15px; }
  .villa-estate .hero { min-height: 92px; padding: 10px 14px; }
  .villa-estate .hero-art { width: 56px; height: 56px; }
  .villa-estate .hero-art img { width: 46px; height: 46px; }
  .villa-estate .hero-art img:nth-child(2) { top: 16px; left: 16px; width: 38px; height: 38px; }
  .villa-estate .hero-art.is-single img { top: 5px; left: 5px; }
  .villa-estate .hero-art .medal img { top: 6px; left: 6px; width: 42px; height: 42px; }
  .villa-estate .hero-art .medal { font-size: 24px; }
  .villa-estate .hero-fig > b { font-size: 22px; }
  .villa-estate .estate-card-actions { grid-template-columns: 1fr; }
  /* Touch targets. The app's own section nav uses 44px and 48px on phones;
     nothing the player taps in this game is smaller, so nothing here is. */
  .villa-estate .primary-button,
.villa-estate .secondary-button,
.villa-estate .estate-card-actions button,
.villa-estate .confirm-dialog footer button,
.villa-estate .estate-upgrade,
.villa-estate .worker-line-head,
.villa-estate .worker-line-edit select { min-height: 44px; }
  .villa-estate .close-x { width: 44px; height: 44px; }
  .villa-estate .order { min-height: 48px; }
  .villa-estate .building-chip { min-height: 48px; }
  .villa-estate .confirm-dialog > p { font-size: 12px; }
  .villa-estate .confirm-dialog footer { grid-template-columns: 1fr; }
}
@media (max-height: 640px) and (max-width: 720px) {
  .villa-estate .living-stage { padding-top: 116px; }
  .villa-estate .living-stage::before { height: 128px; }
  .villa-estate .living-stage .scene-scrim { height: 128px; }
  .villa-estate .living-stage::after { top: 96px; }
  .villa-estate .estate-frame { padding: 8px 10px; gap: 2px 10px; }
  .villa-estate .estate-medallion { width: 46px; height: 46px; }
  .villa-estate .estate-medallion img { width: 40px; height: 40px; }
  .villa-estate .estate-medallion b { font-size: 20px; }
  .villa-estate .estate-medallion.has-estate-art b { font-size: 12px; padding: 0 5px; }
  /* The milestones go, not the frame: the level and the tier are written
     nowhere else now, but a reward the player is not standing on can wait for
     a taller screen. */
  .villa-estate .estate-milestones { display: none; }
  .villa-estate .hero { min-height: 80px; }
}
@media (prefers-reduced-motion: reduce) {
  .villa-estate,
.villa-estate *::before,
.villa-estate *::after { scroll-behavior: auto !important; transition-duration: .001ms !important; animation-duration: .001ms !important; }
}

/* Production's shell, not the reference's stand-in strip — see emit-route-css.mjs. */
.villa-estate { display: flex; flex-direction: column; }
.villa-estate .route-content { height: auto; min-height: 0; flex: 1 1 auto; }
