/* ============================================================
   The Marisol — boutique hotel website
   Self-contained static styles (no build step, no external CSS)
   ============================================================ */

:root {
  /* Palette */
  --sand-50:  #faf7f2;
  --sand-100: #f3ede3;
  --sand-200: #e7dccb;
  --ink:      #1f2a2e;
  --ink-soft: #45565b;
  --teal:     #0f4c52;
  --teal-dark:#0a3a3f;
  /* Two further teals that only the hero and page-banner gradients use. They
     are variables rather than literals so that recolouring the theme reaches
     those gradients too — a theme editor that leaves the largest element on
     the homepage stubbornly teal is not a theme editor. Both keep their
     hand-picked values until the operator actually changes Teal (see
     applyTheme in js/site.js), so the stock site renders pixel-for-pixel. */
  --teal-mid: #14606a;
  --teal-light:#2a7f86;
  --gold:     #c39b53;
  --gold-dark:#a9823c;
  --white:    #ffffff;
  --danger:   #b3261e;
  --ok:       #2e7d51;

  /* Button colours, derived from the brand colour by applyTheme (js/site.js).
     These defaults ARE the stock teal, so a page renders identically before
     the theme has loaded, and identically forever on a default theme. On a
     hotel with a pale brand colour applyTheme overwrites them with values that
     are actually readable, rather than white-on-cream.
     --btn-line is text on a light row; --btn-edge is the border beside it,
     which may sit at the lower 3:1 UI floor where text may not. */
  --btn:      #0f4c52;
  --btn-dark: #0a3a3f;
  --btn-on:   #ffffff;
  --btn-line: #0f4c52;
  --btn-edge: #0f4c52;
  /* Text sitting directly ON a brand-coloured band (the hero gradient, the
     teal band, the admin header). Computed against the LIGHTEST tone in that
     gradient, so the label holds up across the whole sweep and not just at the
     dark end. White on the stock theme, so nothing moves by default. */
  --on-brand: #ffffff;

  /* Type */
  --serif: "Iowan Old Style", "Palatino Linotype", Palatino, Georgia, serif;
  --sans:  system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;

  /* Misc */
  --radius: 14px;
  --shadow: 0 10px 30px rgba(15, 76, 82, 0.12);
  --shadow-sm: 0 4px 14px rgba(15, 76, 82, 0.10);
  --maxw: 1160px;
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  margin: 0;
  font-family: var(--sans);
  color: var(--ink);
  background: var(--sand-50);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3 { font-family: var(--serif); font-weight: 600; line-height: 1.15; color: var(--ink); }
h1 { font-size: clamp(2.2rem, 5vw, 3.6rem); margin: 0 0 .4em; }
h2 { font-size: clamp(1.7rem, 3.5vw, 2.5rem); margin: 0 0 .5em; }
h3 { font-size: 1.25rem; margin: 0 0 .4em; }
p  { margin: 0 0 1em; color: var(--ink-soft); }
a  { color: var(--teal); text-decoration: none; }
a:hover { color: var(--gold-dark); }
img { max-width: 100%; display: block; }

.container { width: 100%; max-width: var(--maxw); margin: 0 auto; padding: 0 24px; }
.section { padding: 84px 0; }
.section--tight { padding: 56px 0; }
.center { text-align: center; }
.muted { color: var(--ink-soft); }
.eyebrow {
  text-transform: uppercase;
  letter-spacing: .22em;
  font-size: .78rem;
  font-weight: 700;
  color: var(--gold-dark);
  margin: 0 0 .8em;
}
.lead { font-size: 1.15rem; max-width: 60ch; }
.center .lead { margin-left: auto; margin-right: auto; }

/* ---------- Buttons ---------- */
.btn {
  display: inline-block;
  font-family: var(--sans);
  font-weight: 600;
  font-size: 1rem;
  padding: 13px 26px;
  border-radius: 999px;
  border: 1.5px solid transparent;
  cursor: pointer;
  transition: transform .12s ease, background .2s ease, color .2s ease, box-shadow .2s ease;
  text-align: center;
  line-height: 1.1;
}
.btn:active { transform: translateY(1px); }
.btn--primary { background: var(--gold); color: #2a2110; }
.btn--primary:hover { background: var(--gold-dark); color: #fff; box-shadow: var(--shadow-sm); }
/* Ghost buttons sit on brand-coloured bands (the hero, the admin header), so
   their label follows --on-brand rather than being hardwired white — which was
   invisible on a hotel with a pale brand colour. Callers that override colour
   inline for a light card are unaffected. */
.btn--ghost { background: transparent; border-color: color-mix(in srgb, var(--on-brand) 70%, transparent); color: var(--on-brand); }
.btn--ghost:hover { background: color-mix(in srgb, var(--on-brand) 14%, transparent); color: var(--on-brand); }
/* Fill and text both come from the derived pair, so the label is readable on
   whatever the hotel chose. Was `background: var(--teal); color: #fff`, which
   is only legible while the brand colour happens to be dark. */
.btn--teal { background: var(--btn); color: var(--btn-on); }
.btn--teal:hover { background: var(--btn-dark); color: var(--btn-on); box-shadow: var(--shadow-sm); }
/* Outline button on a light background — the Edit / Send confirmation style.
   A class, because it was being hand-written as an inline style on every
   button that needed it, which is how they all inherited the same problem. */
.btn--outline { background: transparent; border-color: var(--btn-edge); color: var(--btn-line); }
.btn--outline:hover { background: var(--btn); border-color: var(--btn); color: var(--btn-on); }
.btn--block { display: block; width: 100%; }
.btn[disabled] { opacity: .5; cursor: not-allowed; }

/* ---------- Header / nav ---------- */
.site-header {
  position: sticky; top: 0; z-index: 50;
  background: rgba(250, 247, 242, 0.88);
  backdrop-filter: saturate(160%) blur(10px);
  border-bottom: 1px solid var(--sand-200);
}
.nav {
  display: flex; align-items: center; justify-content: space-between;
  height: 68px;
}
.brand { display: flex; align-items: center; gap: 10px; font-family: var(--serif); font-size: 1.35rem; color: var(--ink); font-weight: 600; }
.brand .brand__mark { color: var(--gold-dark); }
.brand span.sub { display:block; font-family: var(--sans); font-size:.62rem; letter-spacing:.28em; text-transform:uppercase; color: var(--ink-soft); }
.nav__links { display: flex; align-items: center; gap: 28px; list-style: none; margin: 0; padding: 0; }
.nav__links a { color: var(--ink); font-weight: 500; font-size: .98rem; }
.nav__links a:hover, .nav__links a.active { color: var(--gold-dark); }
.nav__cta { margin-left: 8px; }
.nav__toggle {
  display: none; background: none; border: 0; cursor: pointer;
  width: 42px; height: 42px; border-radius: 10px;
}
.nav__toggle span, .nav__toggle span::before, .nav__toggle span::after {
  content: ""; display: block; width: 22px; height: 2px; background: var(--ink);
  position: relative; margin: 0 auto; transition: .2s;
}
.nav__toggle span::before { position: absolute; top: -7px; }
.nav__toggle span::after  { position: absolute; top: 7px; }

@media (max-width: 860px) {
  .nav__toggle { display: block; }
  .nav__links {
    position: absolute; top: 68px; left: 0; right: 0;
    flex-direction: column; align-items: stretch; gap: 0;
    background: var(--sand-50); border-bottom: 1px solid var(--sand-200);
    padding: 8px 24px 20px; box-shadow: var(--shadow-sm);
    display: none;
  }
  .nav__links.open { display: flex; }
  .nav__links li { padding: 6px 0; }
  .nav__cta { margin: 10px 0 0; }
}

/* ---------- Hero ---------- */
.hero {
  position: relative; color: var(--on-brand);
  min-height: 78vh; display: flex; align-items: center;
  /* The two colour layers are variables, so the hero follows the theme. The
     darkening scrim on top stays a literal rgba(): rgba() cannot take a custom
     property, and the color-mix() equivalent — though it computes to the same
     10,58,63 — interpolates the gradient fractionally differently, which was
     measurable as a changed screenshot on the stock theme. A fixed dark veil
     is worth more than a byte-identical render is worth losing. */
  background:
    linear-gradient(180deg, rgba(10,58,63,.36), rgba(10,58,63,.72)),
    radial-gradient(1200px 500px at 70% -10%, var(--teal-light), transparent),
    linear-gradient(160deg, var(--teal), var(--teal-dark) 70%);
  overflow: hidden;
}
.hero::after {
  /* soft "waterline" band */
  content:""; position:absolute; left:0; right:0; bottom:0; height:34%;
  background: linear-gradient(180deg, transparent, rgba(4,24,26,.55));
  pointer-events:none;
}
.hero--clean::after { display: none; } /* video hero with overlay:none — no waterline */
.hero .container { position: relative; z-index: 2; padding-top: 40px; padding-bottom: 40px; }
.hero h1 { color: var(--on-brand); max-width: 16ch; }
.hero p { color: color-mix(in srgb, var(--on-brand) 92%, transparent); font-size: 1.2rem; max-width: 54ch; }
/* Optional tinted panel behind hero text (colour + opacity set per block in the
   builder). inline-block so it hugs the text rather than spanning the viewport. */
.hero__panel {
  display: inline-block; padding: 28px 34px; border-radius: var(--radius);
  backdrop-filter: blur(2px); -webkit-backdrop-filter: blur(2px);
}
.hero__panel > :first-child { margin-top: 0; }
.hero__panel > :last-child { margin-bottom: 0; }
@media (max-width: 600px) { .hero__panel { padding: 20px 18px; } }

.hero__actions { display: flex; gap: 14px; flex-wrap: wrap; margin-top: 22px; }
.hero__badges { display:flex; gap:22px; margin-top:34px; flex-wrap:wrap; color:color-mix(in srgb, var(--on-brand) 90%, transparent); }
.hero__badges div { font-size:.9rem; }
.hero__badges strong { display:block; font-family:var(--serif); font-size:1.5rem; color:var(--on-brand); }

/* Page banner (interior pages) */
.banner {
  color:var(--on-brand); padding: 96px 0 64px; text-align:center;
  /* Colour layer themed, scrim literal — same reasoning as .hero above. */
  background:
    linear-gradient(180deg, rgba(10,58,63,.55), rgba(10,58,63,.75)),
    linear-gradient(160deg, var(--teal-mid), var(--teal-dark));
}
.banner h1 { color:var(--on-brand); }
.banner p { color: color-mix(in srgb, var(--on-brand) 90%, transparent); max-width:56ch; margin:0 auto; }

/* ---------- Availability search widget ---------- */
.search-card {
  background: var(--white); border-radius: var(--radius); box-shadow: var(--shadow);
  padding: 18px; display: grid; gap: 14px;
  grid-template-columns: repeat(4, 1fr) auto; align-items: end;
}
.search-card.-floating { margin-top: -46px; position: relative; z-index: 5; }
.field { display: flex; flex-direction: column; gap: 6px; }
.field label { font-size: .78rem; font-weight: 700; text-transform: uppercase; letter-spacing: .08em; color: var(--ink-soft); }
.field input, .field select {
  font-family: var(--sans); font-size: 1rem; padding: 11px 12px;
  border: 1.5px solid var(--sand-200); border-radius: 10px; background: var(--sand-50); color: var(--ink);
}
.field input:focus, .field select:focus { outline: none; border-color: var(--teal); background:#fff; }
@media (max-width: 860px) { .search-card { grid-template-columns: 1fr 1fr; } .search-card.-floating { margin-top: 24px; } }
@media (max-width: 520px) { .search-card { grid-template-columns: 1fr; } }

/* ---------- Grid helpers ---------- */
.grid { display: grid; gap: 26px; }
.grid--3 { grid-template-columns: repeat(3, 1fr); }
.grid--2 { grid-template-columns: repeat(2, 1fr); }
.grid--4 { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 900px) { .grid--3, .grid--4 { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 620px) { .grid--2, .grid--3, .grid--4 { grid-template-columns: 1fr; } }

/* ---------- Room / feature cards ---------- */
.card {
  background: var(--white); border-radius: var(--radius); overflow: hidden;
  box-shadow: var(--shadow-sm); display: flex; flex-direction: column;
  transition: transform .15s ease, box-shadow .15s ease;
}
.card:hover { transform: translateY(-4px); box-shadow: var(--shadow); }
.card__media { aspect-ratio: 3 / 2; position: relative; }
.card__body { padding: 20px 22px 24px; display: flex; flex-direction: column; flex: 1; }
.card__price { font-family: var(--serif); font-size: 1.4rem; color: var(--teal); }
.card__price small { font-family: var(--sans); font-size: .8rem; color: var(--ink-soft); font-weight: 500; }
.card__meta { display:flex; gap:16px; flex-wrap:wrap; font-size:.86rem; color:var(--ink-soft); margin:.2em 0 1em; }
.card__meta span { display:inline-flex; align-items:center; gap:6px; }
.tag { display:inline-block; background:var(--sand-100); color:var(--ink-soft); font-size:.72rem; font-weight:600; padding:4px 10px; border-radius:999px; margin:0 6px 6px 0; }
.card .btn { margin-top: auto; }

/* Photo placeholders (CSS "photography" — swap for real <img>) */
.photo { width:100%; height:100%; position:relative; }
.photo::after { content: attr(data-label); position:absolute; left:12px; bottom:10px; color:rgba(255,255,255,.92); font-size:.8rem; letter-spacing:.04em; text-shadow:0 1px 4px rgba(0,0,0,.4); }
.ph-1 { background: linear-gradient(150deg,#1c6b73,#0a3a3f); }
.ph-2 { background: linear-gradient(150deg,#caa25e,#7c5a24); }
.ph-3 { background: linear-gradient(150deg,#3a8f97,#12545b); }
.ph-4 { background: linear-gradient(150deg,#e0c9a6,#b08a5a); }
.ph-5 { background: linear-gradient(150deg,#2b7a82,#08484e); }
.ph-6 { background: linear-gradient(150deg,#d8b070,#8a6528); }
.ph-7 { background: linear-gradient(150deg,#175e66,#0a3a3f); }
.ph-8 { background: linear-gradient(150deg,#bfa377,#6f5222); }

/* ---------- Feature/amenity items ---------- */
.feature { text-align: center; padding: 8px; }
.feature .ico {
  width: 60px; height: 60px; border-radius: 16px; margin: 0 auto 14px;
  display: grid; place-items: center; font-size: 1.7rem;
  background: var(--sand-100); color: var(--teal);
}
.feature h3 { margin-bottom: .2em; }

/* ---------- Split / about ---------- */
.split { display: grid; grid-template-columns: 1fr 1fr; gap: 48px; align-items: center; }
.split .media { aspect-ratio: 4/3; border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow); }
@media (max-width: 820px) { .split { grid-template-columns: 1fr; } }

/* ---------- Testimonials ---------- */
.quote { background:#fff; border-radius: var(--radius); padding: 26px; box-shadow: var(--shadow-sm); }
.quote p { font-family: var(--serif); font-size: 1.1rem; color: var(--ink); font-style: italic; }
.quote .who { font-family: var(--sans); font-style: normal; font-weight:600; color: var(--ink); margin-top: 10px; }
.stars { color: var(--gold); letter-spacing: 2px; }

/* ---------- Bands ---------- */
.band { background: var(--teal); color:var(--on-brand); }
.band h2, .band h3 { color:var(--on-brand); }
.band p { color: color-mix(in srgb, var(--on-brand) 88%, transparent); }
.band .eyebrow { color: var(--gold); }
.band--sand { background: var(--sand-100); color: var(--ink); }
.band--sand h2, .band--sand h3 { color: var(--ink); }
.band--sand p { color: var(--ink-soft); }

/* ---------- Gallery ---------- */
.gallery { columns: 3; column-gap: 18px; }
.gallery .g-item { break-inside: avoid; margin-bottom: 18px; border-radius: 12px; overflow: hidden; box-shadow: var(--shadow-sm); }
.gallery .g-item .photo { aspect-ratio: auto; }
.g-tall { height: 340px; } .g-med { height: 240px; } .g-short { height: 180px; }
@media (max-width: 820px) { .gallery { columns: 2; } }
@media (max-width: 520px) { .gallery { columns: 1; } }

/* ---------- Forms / contact ---------- */
.form-grid { display: grid; gap: 16px; grid-template-columns: 1fr 1fr; }
.form-grid .full { grid-column: 1 / -1; }
@media (max-width: 620px) { .form-grid { grid-template-columns: 1fr; } }
textarea, .form-grid input, .form-grid select {
  font-family: var(--sans); font-size: 1rem; padding: 12px 13px; width: 100%;
  border: 1.5px solid var(--sand-200); border-radius: 10px; background: #fff; color: var(--ink);
}
textarea { resize: vertical; min-height: 130px; }
label.lbl { font-weight: 600; font-size: .9rem; display:block; margin-bottom: 6px; }
.form-note { font-size: .85rem; color: var(--ink-soft); }
.info-row { display:flex; gap:14px; align-items:flex-start; margin-bottom:18px; }
.info-row .ico { flex:0 0 44px; height:44px; border-radius:12px; background:var(--sand-100); color:var(--teal); display:grid; place-items:center; font-size:1.2rem; }

/* ---------- Booking engine ---------- */
.steps { display:flex; gap:8px; justify-content:center; margin-bottom: 36px; flex-wrap:wrap; }
.steps .step { display:flex; align-items:center; gap:10px; color:var(--ink-soft); font-weight:600; font-size:.92rem; }
.steps .step .num { width:30px; height:30px; border-radius:999px; display:grid; place-items:center; background:var(--sand-200); color:var(--ink-soft); font-size:.9rem; }
.steps .step.active .num { background:var(--teal); color:var(--on-brand); }
.steps .step.done .num { background:var(--ok); color:#fff; }
.steps .sep { width:34px; height:2px; background:var(--sand-200); align-self:center; }
@media (max-width:620px){ .steps .sep{ width:16px; } .steps .step span{ display:none; } }

.panel { display:none; }
.panel.active { display:block; }

/* Only used when the step wizard has to pull itself back into view (see
   keepWizardInView in js/restaurant-booking.js) — keeps the sticky header
   from covering the top of the wizard. */
#tb-wizard { scroll-margin-top: 100px; }

.result-row {
  display:grid; grid-template-columns: 150px 1fr auto; gap: 20px; align-items:center;
  background:#fff; border:1.5px solid var(--sand-200); border-radius: var(--radius);
  padding: 16px; margin-bottom: 16px;
}
.result-row .thumb { border-radius:10px; overflow:hidden; aspect-ratio:3/2; }
.result-row .price { text-align:right; }
.result-row .price .big { font-family:var(--serif); font-size:1.5rem; color:var(--teal); }
.result-row.soldout { opacity:.6; }
.badge-avail { font-size:.78rem; font-weight:700; color:var(--ok); }
.badge-soldout { font-size:.78rem; font-weight:700; color:var(--danger); }
@media (max-width:720px){ .result-row{ grid-template-columns:1fr; } .result-row .price{ text-align:left; } }

.summary {
  background:var(--sand-100); border-radius: var(--radius); padding: 22px;
  position: sticky; top: 90px;
}
.summary h3 { border-bottom:1px solid var(--sand-200); padding-bottom:12px; }
.summary .line { display:flex; justify-content:space-between; margin:8px 0; color:var(--ink-soft); }
.summary .line.total { border-top:1px solid var(--sand-200); margin-top:14px; padding-top:14px; font-weight:700; color:var(--ink); font-size:1.15rem; }
/* "includes VAT (20%) £60" — a breakdown of the total above it, not a charge
   added to it, so it is quiet, tucked under the total, and carries no rule of
   its own. VAT used to sit ABOVE the total as its own line, which read as an
   addition and made the price climb between the room card and the checkout. */
.summary .line.vat-incl { margin-top:2px; font-size:.82rem; }
.book-layout { display:grid; grid-template-columns: 1fr 340px; gap: 32px; align-items:start; }
@media (max-width: 900px){ .book-layout{ grid-template-columns:1fr; } .summary{ position:static; } }

.notice { padding: 12px 16px; border-radius: 10px; font-size:.92rem; margin: 14px 0; }
.notice.warn { background:#fff4e5; color:#7a4d00; border:1px solid #f0d3a0; }
.notice.err  { background:#fdeaea; color:#8a1f1a; border:1px solid #f0b6b3; }
.notice.ok   { background:#e8f6ee; color:#1c5c3b; border:1px solid #b6e0c6; }
/* Neutral: a standing explanation, not a warning. Amber would cry wolf on a
   block that is on screen permanently. */
.notice.info { background:var(--sand-50); color:var(--ink-soft); border:1px solid var(--sand-200); }
.notice.info strong { color:var(--ink); }

.confirm-card {
  background:#fff; border-radius: var(--radius); box-shadow: var(--shadow); padding: 40px;
  text-align:center; max-width: 640px; margin: 0 auto;
}
.confirm-card .check { width:74px; height:74px; border-radius:999px; background:var(--ok); color:#fff; display:grid; place-items:center; font-size:2.2rem; margin:0 auto 18px; }
.ref { font-family: var(--serif); font-size: 1.6rem; letter-spacing:2px; color: var(--teal); background:var(--sand-100); display:inline-block; padding:8px 20px; border-radius:10px; margin: 8px 0 20px; }
.kv { text-align:left; max-width:420px; margin: 0 auto 24px; }
.kv .line { display:flex; justify-content:space-between; padding:9px 0; border-bottom:1px dashed var(--sand-200); }

.field-error { color: var(--danger); font-size:.82rem; margin-top:4px; display:none; }
.field.invalid input, .field.invalid select,
.fg.invalid input, .fg.invalid select { border-color: var(--danger); }
.fg.invalid .field-error, .field.invalid .field-error { display:block; }

/* ---------- Footer ---------- */
.site-footer { background: var(--ink); color: rgba(255,255,255,.8); padding: 60px 0 28px; }
.site-footer h4 { color:#fff; font-family:var(--serif); margin:0 0 14px; font-size:1.05rem; }
.site-footer a { color: rgba(255,255,255,.78); }
.site-footer a:hover { color: var(--gold); }
.footer-grid { display:grid; grid-template-columns: 1.6fr 1fr 1fr 1.2fr; gap: 36px; }
.footer-grid ul { list-style:none; padding:0; margin:0; }
.footer-grid li { margin-bottom: 9px; }
.footer-bottom { border-top:1px solid rgba(255,255,255,.14); margin-top:40px; padding-top:20px; display:flex; justify-content:space-between; flex-wrap:wrap; gap:10px; font-size:.85rem; color:rgba(255,255,255,.6); }
@media (max-width: 780px){ .footer-grid{ grid-template-columns:1fr 1fr; } }
@media (max-width: 480px){ .footer-grid{ grid-template-columns:1fr; } }

/* ---------- Admin panel ---------- */
.admin-topbar { background: var(--teal-dark); color:var(--on-brand); }
.admin-topbar .nav { height:60px; }
.admin-topbar .brand, .admin-topbar .brand span.sub { color:var(--on-brand); }
.admin-wrap { max-width: 1180px; margin: 0 auto; padding: 28px 24px 80px; }
.tabs { display:flex; gap:6px; border-bottom:2px solid var(--sand-200); margin-bottom:26px; flex-wrap:wrap; }
.tab-btn { background:none; border:0; padding:12px 18px; font-family:var(--sans); font-size:1rem; font-weight:600; color:var(--ink-soft); cursor:pointer; border-bottom:3px solid transparent; margin-bottom:-2px; }
.tab-btn.active { color:var(--teal); border-bottom-color:var(--gold); }
.tab-panel { display:none; } .tab-panel.active { display:block; }

.toolbar { display:flex; gap:10px; align-items:center; flex-wrap:wrap; margin-bottom:18px; }
.chip { background:var(--sand-100); border:1px solid var(--sand-200); border-radius:999px; padding:7px 15px; font-size:.9rem; font-weight:600; color:var(--ink-soft); cursor:pointer; }
.chip.active { background:var(--teal); color:var(--on-brand); border-color:var(--teal); }

table.data { width:100%; border-collapse:collapse; background:#fff; border-radius:var(--radius); overflow:hidden; box-shadow:var(--shadow-sm); }
table.data th, table.data td { text-align:left; padding:12px 14px; border-bottom:1px solid var(--sand-100); font-size:.92rem; }
table.data th { background:var(--sand-100); font-size:.75rem; text-transform:uppercase; letter-spacing:.06em; color:var(--ink-soft); }
table.data tr:last-child td { border-bottom:0; }
table.data tr:hover td { background:var(--sand-50); }
.pill { font-size:.74rem; font-weight:700; padding:3px 10px; border-radius:999px; display:inline-block; }
.pill.confirmed { background:#e8f6ee; color:#1c5c3b; }
.pill.cancelled { background:#fdeaea; color:#8a1f1a; }
.pill.checked_in { background:#e6effa; color:#213d7a; }
.pill.checked_out { background:var(--sand-100); color:var(--ink-soft); }
/* In use / withdrawn from use — the VAT codes table. Same two colours the
   booking statuses already use for live and finished. */
.pill.active { background:#e8f6ee; color:#1c5c3b; }
.pill.retired { background:var(--sand-100); color:var(--ink-soft); }
.data select { padding:6px 8px; border:1.5px solid var(--sand-200); border-radius:8px; font-size:.85rem; background:#fff; }
/* Edit-in-place cells (VAT codes): the .room-editor input box, at table size.
   Scoped to this table on purpose — the group-booking table's number boxes are
   not part of this change. */
#tax-codes-table input { padding:6px 8px; border:1.5px solid var(--sand-200); border-radius:8px; font-family:var(--sans); font-size:.85rem; background:#fff; max-width:100%; }
/* A retired code is still listed — posted bills reference it — but must not
   read as one of the live choices. */
table.data tr.tax-retired td { background:var(--sand-50); color:var(--ink-soft); }
table.data tr.tax-retired td input { color:var(--ink-soft); }

.stat-row { display:grid; grid-template-columns:repeat(4,1fr); gap:16px; margin-bottom:26px; }
.stat { background:#fff; border-radius:var(--radius); box-shadow:var(--shadow-sm); padding:18px 20px; }
.stat .n { font-family:var(--serif); font-size:2rem; color:var(--teal); line-height:1; }
.stat .l { font-size:.82rem; color:var(--ink-soft); text-transform:uppercase; letter-spacing:.06em; margin-top:6px; }
@media (max-width:720px){ .stat-row{ grid-template-columns:1fr 1fr; } .data-scroll{ overflow-x:auto; } }

.room-editor { background:#fff; border-radius:var(--radius); box-shadow:var(--shadow-sm); padding:20px; margin-bottom:16px; }
.room-editor .grid-fields { display:grid; grid-template-columns:repeat(4,1fr); gap:12px; }
.room-editor .grid-fields .full { grid-column:1/-1; }
.room-editor input, .room-editor textarea { width:100%; padding:9px 10px; border:1.5px solid var(--sand-200); border-radius:8px; font-family:var(--sans); font-size:.92rem; }
/* Selects inside an editor panel were never styled, so the room picker in the
   booking form (and the restaurant's time picker) sat as a short browser
   default beside full-width inputs. Same box as the inputs above. */
.room-editor .grid-fields select { width:100%; padding:9px 10px; border:1.5px solid var(--sand-200); border-radius:8px; font-family:var(--sans); font-size:.92rem; background:#fff; }
.room-editor label { font-size:.74rem; font-weight:700; text-transform:uppercase; letter-spacing:.05em; color:var(--ink-soft); display:block; margin-bottom:4px; }
/* A checkbox label is a sentence, not a field caption: the uppercase/tracking
   rule above would shout it. Overridden inline where used, and here so the
   width:100% on inputs cannot stretch the tick-box itself. */
.room-editor label input[type="checkbox"] { width:auto; }
@media (max-width:720px){ .room-editor .grid-fields{ grid-template-columns:1fr 1fr; } }

.login-box { max-width:400px; margin:8vh auto; background:#fff; border-radius:var(--radius); box-shadow:var(--shadow); padding:36px; }
.login-box input { width:100%; padding:12px; border:1.5px solid var(--sand-200); border-radius:10px; margin-bottom:14px; font-size:1rem; }

/* ---------- Folio (the bill, inside the booking edit form) ----------
   Same vocabulary as the rest of the admin: the .data table, the .pill
   colours, the sand/teal palette. Nothing new invented — the only genuinely
   new idea here is that a cancelled line has to LOOK cancelled. */

/* Balance strip. A cut-down .stat-row: three figures, the balance emphasised,
   and it must not shout as loudly as the page-top stats do. */
.folio-strip { display:grid; grid-template-columns:repeat(3,1fr); gap:12px; margin-top:12px; }
.folio-strip .fs-cell { background:var(--sand-50); border:1px solid var(--sand-100); border-radius:10px; padding:12px 14px; }
.folio-strip .fs-l { font-size:.7rem; font-weight:700; text-transform:uppercase; letter-spacing:.06em; color:var(--ink-soft); }
.folio-strip .fs-n { font-family:var(--serif); font-size:1.3rem; line-height:1.2; margin-top:4px; color:var(--ink); }
/* The balance is the number staff act on, so it gets the weight and the
   colour: amber owed, green settled, blue when the hotel owes the guest —
   a credit is not an error and must not read like one. */
.folio-strip .fs-bal { border-width:1.5px; }
.folio-strip .fs-bal .fs-n { font-size:1.55rem; font-weight:700; }
.folio-strip .fs-bal.due { background:#fdf0dc; border-color:#e8c98f; }
.folio-strip .fs-bal.due .fs-n, .folio-strip .fs-bal.due .fs-l { color:#7c5a24; }
.folio-strip .fs-bal.settled { background:#e8f6ee; border-color:#b6e0c6; }
.folio-strip .fs-bal.settled .fs-n, .folio-strip .fs-bal.settled .fs-l { color:#1c5c3b; }
.folio-strip .fs-bal.credit { background:#e6effa; border-color:#b9cbea; }
.folio-strip .fs-bal.credit .fs-n, .folio-strip .fs-bal.credit .fs-l { color:#213d7a; }
@media (max-width:720px){ .folio-strip { grid-template-columns:1fr; } }

/* Paid / part-paid / unpaid marker — the .pill shape, its own states. */
.bal-pill { font-size:.68rem; font-weight:700; padding:2px 8px; border-radius:999px; display:inline-block; margin-top:3px; }
.bal-pill.paid    { background:#e8f6ee; color:#1c5c3b; }
.bal-pill.part    { background:#fdf0dc; color:#7c5a24; }
.bal-pill.unpaid  { background:#fdeaea; color:#8a1f1a; }
.bal-pill.due     { background:#fdf0dc; color:#7c5a24; }
.bal-pill.credit  { background:#e6effa; color:#213d7a; }

/* A reversed line and the reversal that cancelled it. Struck through and
   faded, but still there: a bill where you cannot see what was taken off is
   worse than useless the moment a guest disputes it. */
table.data.folio-lines td { font-size:.88rem; }
.folio-lines tr.folio-void td { text-decoration:line-through; color:var(--ink-soft); background:var(--sand-50); }
.folio-lines tr.folio-void td .bal-pill { text-decoration:none; }
.folio-lines tr.folio-rev td { color:var(--ink-soft); font-style:italic; background:var(--sand-50); }
.folio-lines tr.folio-rev td .bal-pill { font-style:normal; }

/* The post-charge / take-payment panels: inset inside the booking editor, so
   they read as part of the folio rather than as a second form on the page. */
.folio-form { background:var(--sand-50); border:1px solid var(--sand-100); border-radius:10px; padding:14px 16px; margin-top:12px; }
.folio-form__title { display:block; font-family:var(--serif); font-size:1rem; margin-bottom:10px; }
/* The VAT split, shown before the line is committed — an inclusive/exclusive
   mistake is a 20% one and this is the only place it is cheap to catch. */
.folio-split { display:flex; flex-wrap:wrap; gap:6px 18px; align-items:baseline; margin-top:12px; padding:9px 12px; background:#fff; border:1px dashed var(--sand-200); border-radius:8px; font-size:.86rem; }
.folio-split .fc-gross { color:var(--teal); }
/* A package preview is a LIST inside that same box — one row per component,
   because the whole question it answers is "what several lines is this one
   price about to become". Full-width inside the flex row above it. */
.folio-split .fp-list { flex:1 1 100%; margin-bottom:2px; }
.folio-split .fp-row { display:flex; justify-content:space-between; gap:14px; padding:3px 0; border-bottom:1px dotted var(--sand-100); }
.folio-split .fp-row:last-child { border-bottom:0; }
.folio-split .fp-row.fp-none { color:var(--ink-soft); }
.folio-split .fp-warn { color:#8a1f1a; }

/* A posted package: one row for the guest, its components collapsed beneath.
   The summary row is the bill; the parts are the VAT return. */
.folio-lines tr.folio-pkg-row td { background:var(--sand-50); }
.folio-pkg-toggle { background:none; border:0; padding:0; font:inherit; color:inherit; cursor:pointer; text-align:left; }
.folio-pkg-toggle:hover { color:var(--teal); }
.folio-pkg-toggle .fpt-caret { color:var(--ink-soft); font-size:.8em; }
.folio-lines tr.folio-pkg-comp td { font-size:.83rem; }
/* Indented and ruled so a component reads as part of the row above it rather
   than as a charge of its own. */
.folio-lines tr.folio-pkg-comp td.folio-comp-desc { padding-left:26px; border-left:3px solid var(--sand-200); }

/* ---------- Price list (packages + extras, Content tab) ---------- */
#pkg-comp-table input, #pkg-comp-table select { padding:6px 8px; border:1.5px solid var(--sand-200); border-radius:8px; font-family:var(--sans); font-size:.85rem; background:#fff; max-width:100%; width:100%; }
/* The money a share comes to, written beside the share as it is typed — the
   one thing that makes a relative weight legible. */
#pkg-comp-table td.pc-money, #pkg-comp-table td.pc-vat { font-size:.85rem; }
table.data td.pl-split { font-size:.82rem; }
.pl-part { display:flex; justify-content:space-between; gap:12px; padding:1px 0; }

/* ---------- VAT report ---------- */
table.data.vat-report td, table.data.vat-report th { font-size:.88rem; }
table.data.vat-report tfoot tr.vat-total td { background:var(--sand-50); border-top:2px solid var(--sand-200); }
.vat-untaxed { margin-top:12px; padding:12px 14px; background:var(--sand-50); border:1px solid var(--sand-100); border-radius:10px; font-size:.9rem; }

/* ---------- Reports (the management pack) ----------
   Everything below is scoped to the Reports tab. The two SERIES COLOURS are
   the only hardcoded colours in this block and they are hardcoded on purpose:
   they are NOT the hotel's brand colour. The brand colour is per-tenant and
   arbitrary — one live tenant's is a pale sand that already failed contrast on
   its own buttons — so a chart themed from it would be illegible for some
   hotels. This pair was checked with the design system's validator (lightness
   band, chroma floor, colourblind separation, normal-vision separation,
   contrast, in light and dark) and the worst adjacent pair is ΔE 17.4 across
   protanopia, deuteranopia and tritanopia. Do not substitute another pair
   without re-running it. */
.rep-chart { --rep-direct:#0d9aa8; --rep-channel:#c2701f; }
.rep-legend .rl-key.-direct { background:#0d9aa8; }
.rep-legend .rl-key.-channel { background:#c2701f; }

.rep-kpis { display:grid; grid-template-columns:repeat(5,1fr); gap:14px; margin:6px 0 10px; }
.kpi { background:#fff; border-radius:var(--radius); box-shadow:var(--shadow-sm); padding:16px 18px; }
.kpi__l { font-size:.72rem; font-weight:700; text-transform:uppercase; letter-spacing:.06em; color:var(--ink-soft); }
/* Proportional figures, not tabular: a lone display number wants the font's
   own widths. tabular-nums is for the columns further down the page. */
.kpi__n { font-family:var(--serif); font-size:1.8rem; line-height:1.1; margin-top:7px; color:var(--teal); }
/* An em dash is not a number and must not read as one. */
.kpi__n.-none { color:var(--ink-soft); font-size:1.5rem; }
.kpi__sub { font-size:.76rem; color:var(--ink-soft); margin-top:5px; }
.kpi__d { font-size:.8rem; margin-top:9px; }
/* Direction is stated by the arrow AND the word, never by colour alone. */
.kpi__d .kd-up   { font-weight:700; color:#1c5c3b; }
.kpi__d .kd-down { font-weight:700; color:#8a1f1a; }
.kpi__d .kd-flat { font-weight:700; color:var(--ink-soft); }
.kpi__d .kd-vs   { color:var(--ink-soft); }
/* The channel-nights caveat beside the ADR. Loud enough to be read, because an
   average that quietly drops a third of the nights is a lie by omission. */
.kpi__warn { font-size:.74rem; color:#7c5a24; background:#fdf0dc; border-radius:8px; padding:5px 8px; margin-top:8px; }
@media (max-width:1000px){ .rep-kpis{ grid-template-columns:repeat(2,1fr); } }
@media (max-width:560px){ .rep-kpis{ grid-template-columns:1fr; } }

.rep-chart { position:relative; background:#fff; border-radius:var(--radius); box-shadow:var(--shadow-sm); padding:16px 18px 12px; margin-top:12px; }
/* Two series means a legend, always: identity is never colour alone. */
.rep-legend { display:flex; gap:20px; flex-wrap:wrap; align-items:center; font-size:.82rem; color:var(--ink-soft); margin-bottom:12px; }
.rep-legend .rl-key { width:12px; height:12px; border-radius:3px; display:inline-block; margin-right:7px; vertical-align:-1px; }
.rep-plot { display:flex; align-items:flex-start; }
.rep-yaxis { position:relative; flex:0 0 46px; height:200px; }
.rep-yaxis b { position:absolute; right:8px; transform:translateY(50%); font-size:.68rem; font-weight:500; color:var(--ink-soft); font-variant-numeric:tabular-nums; }
.rep-scroll { flex:1 1 auto; min-width:0; overflow-x:auto; overflow-y:hidden; }
/* The bars and the x-axis ticks share this track, and therefore share the flex
   row that positions them — a tick cannot drift off its bar. Its width is set
   inline per render: a floor of a few px per night (so a year scrolls rather
   than collapsing into a smear) and a ceiling of the bars' own natural width
   (so a fortnight's data does not sit under gridlines ruled across half a
   metre of empty card). */
.rep-track { width:100%; }
.rep-inner { position:relative; height:200px; }
/* Recessive grid: hairline, solid, one step off the surface. Never dashed. */
.rep-grid { position:absolute; inset:0; pointer-events:none; }
.rep-grid i { position:absolute; left:0; right:0; height:1px; background:var(--sand-200); }
.rep-bars { position:absolute; inset:0; display:flex; align-items:flex-end; gap:2px; }
.rep-bar { position:relative; flex:1 1 0; min-width:5px; max-width:24px; height:100%; display:flex; flex-direction:column; justify-content:flex-end; }
.rep-bar:hover { cursor:default; }
.rep-seg { width:100%; }
/* The data-end is rounded ~4px and the baseline end is square; the 2px gap
   between the two segments is surface colour, not a stroke. */
.rep-seg.-channel { background:var(--rep-channel); border-radius:4px 4px 0 0; margin-bottom:2px; }
.rep-seg.-direct  { background:var(--rep-direct); }
.rep-bar.-cap-direct .rep-seg.-direct { border-radius:4px 4px 0 0; }
.rep-bar.-empty::after { content:""; position:absolute; left:0; right:0; bottom:0; height:2px; background:var(--sand-200); }
/* Selective direct labels only — one bar, the busiest night. A number on every
   bar is chaos and goes unread. */
.rep-peak { position:absolute; left:50%; transform:translateX(-50%); font-size:.68rem; font-weight:700; color:var(--ink); white-space:nowrap; }
.rep-peak.-left { left:0; transform:none; }
.rep-peak.-right { left:auto; right:0; transform:none; }
.rep-xaxis { display:flex; gap:2px; margin-top:7px; height:15px; }
.rep-xtick { position:relative; flex:1 1 0; min-width:5px; max-width:24px; }
.rep-xtick span { position:absolute; left:50%; top:0; transform:translateX(-50%); font-size:.66rem; color:var(--ink-soft); white-space:nowrap; }
/* An HTML chart is interactive; the hover layer is part of it, not a nicety. */
.rep-tip { position:absolute; z-index:6; pointer-events:none; background:var(--ink); color:#fff; border-radius:9px; padding:9px 11px; font-size:.76rem; line-height:1.45; box-shadow:var(--shadow); min-width:150px; }
.rep-tip strong { display:block; font-size:.82rem; margin-bottom:4px; }
.rep-tip .rt-row { display:flex; justify-content:space-between; gap:14px; }
.rep-tip .rt-row i { font-style:normal; color:rgba(255,255,255,.72); }
.rep-tip .rt-key { width:9px; height:9px; border-radius:2px; display:inline-block; margin-right:6px; }
.rep-tip .rt-key.-direct { background:#0d9aa8; } .rep-tip .rt-key.-channel { background:#c2701f; }
.rep-cap { font-size:.78rem; color:var(--ink-soft); margin:10px 0 0; }

/* Columns of money line up; a single display figure does not. */
table.data.rep-table td, table.data.rep-table th { font-size:.86rem; padding:9px 12px; }
table.data.rep-table td.num, table.data.rep-table th.num { text-align:right; font-variant-numeric:tabular-nums; white-space:nowrap; }
table.data.rep-table tfoot td { background:var(--sand-50); border-top:2px solid var(--sand-200); font-weight:700; }
/* The two series, restated as a swatch in the table so the chart's colours and
   the table's columns are visibly the same two things. */
.rep-swatch { width:9px; height:9px; border-radius:2px; display:inline-block; margin-right:6px; vertical-align:0; }
.rep-swatch.-direct { background:#0d9aa8; } .rep-swatch.-channel { background:#c2701f; }
.rep-note { margin-top:10px; padding:11px 13px; background:var(--sand-50); border:1px solid var(--sand-100); border-radius:10px; font-size:.85rem; color:var(--ink-soft); }
.rep-note strong { color:var(--ink); }
.rep-buckets { display:grid; grid-template-columns:repeat(4,1fr); gap:12px; margin:12px 0; }
.rep-bucket { background:#fff; border-radius:12px; box-shadow:var(--shadow-sm); padding:13px 15px; border-left:4px solid var(--sand-200); }
.rep-bucket .rb-l { font-size:.72rem; font-weight:700; text-transform:uppercase; letter-spacing:.05em; color:var(--ink-soft); }
.rep-bucket .rb-n { font-family:var(--serif); font-size:1.35rem; margin-top:5px; color:var(--ink); }
.rep-bucket .rb-s { font-size:.74rem; color:var(--ink-soft); margin-top:3px; }
.rep-bucket.-b1 { border-left-color:#e8c98f; } .rep-bucket.-b2 { border-left-color:#dd9a5a; }
.rep-bucket.-b3 { border-left-color:var(--danger); }
@media (max-width:720px){ .rep-buckets{ grid-template-columns:1fr 1fr; } }
.rep-sub { display:grid; grid-template-columns:1fr 1fr; gap:18px; align-items:start; }
@media (max-width:900px){ .rep-sub{ grid-template-columns:1fr; } }
.rep-head { display:flex; align-items:baseline; gap:12px; flex-wrap:wrap; margin:36px 0 4px; }
.rep-head h3 { margin:0; font-size:1.15rem; }
.rep-head .btn { padding:5px 12px; font-size:.76rem; }

/* Utilities */
.mt-0{margin-top:0}.mb-0{margin-bottom:0}.mt-1{margin-top:12px}.mt-2{margin-top:24px}.mt-3{margin-top:36px}
.hidden{display:none !important}
.demo-flag { font-size:.8rem; background:var(--sand-100); border:1px dashed var(--gold); color:var(--gold-dark); padding:3px 10px; border-radius:999px; display:inline-block; }

/* ---------- Rate flex year grid (admin, Channels tab) ---------- */
.rate-grid { display:grid; grid-template-columns:44px repeat(31, minmax(25px, 1fr)); gap:2px; min-width:880px; margin-top:12px; }
.rate-grid .rg-head { font-size:.62rem; color:var(--ink-soft); text-align:center; font-weight:700; }
.rate-grid .rg-month { font-size:.72rem; font-weight:700; color:var(--ink-soft); display:flex; align-items:center; }
.rate-grid .rg-day { font-size:.64rem; text-align:center; padding:4px 0; border-radius:4px; background:var(--sand-100); color:var(--ink); cursor:default; }
.rate-grid .rg-day.below { background:#e2f2e7; color:#1c5c3b; }
.rate-grid .rg-day.above { background:#fdf0dc; color:#7c5a24; }
.rate-grid .rg-day.high { background:#fbe0d1; color:#8a3d1a; font-weight:700; }
.rate-grid .rg-empty { background:transparent; }
.rate-legend { font-size:.74rem; color:var(--ink-soft); display:flex; align-items:center; gap:6px; }
.rate-legend .rl { width:14px; height:14px; border-radius:4px; display:inline-block; background:var(--sand-100); }
.rate-legend .rl.below { background:#e2f2e7; }
.rate-legend .rl.above { background:#fdf0dc; }
.rate-legend .rl.high { background:#fbe0d1; }
#tab-channels .toolbar select { padding:7px 10px; border:1.5px solid var(--sand-200); border-radius:8px; font-size:.88rem; background:#fff; }
.rate-grid .rg-day { cursor:pointer; }
.rate-grid .rg-day:hover { outline:1.5px solid var(--teal); }
.rate-grid .rg-day.manual { box-shadow:inset 0 0 0 1.5px var(--teal); font-weight:700; }
.rate-grid .rg-day input { width:100%; border:0; background:#fff; font-size:.64rem; text-align:center; padding:0; outline:1.5px solid var(--teal); border-radius:4px; font-family:var(--sans); }
.rate-legend .rl.manual { background:var(--sand-100); box-shadow:inset 0 0 0 1.5px var(--teal); }
/* Availability overview grid (read-only variant of the rate grid) */
.rate-grid.readonly .rg-day { cursor:default; }
.rate-grid.readonly .rg-day:hover { outline:none; }
.rate-grid .rg-day.av-free { background:#e2f2e7; color:#1c5c3b; }
.rate-grid .rg-day.av-part { background:#fdf0dc; color:#7c5a24; }
.rate-grid .rg-day.av-full { background:#fbdddd; color:#8a1f1a; font-weight:700; }
.rate-grid .rg-day.past { opacity:.4; }
.rate-legend .rl.av-free { background:#e2f2e7; }
.rate-legend .rl.av-part { background:#fdf0dc; }
.rate-legend .rl.av-full { background:#fbdddd; }
/* Availability grid: days are clickable (drill-down), with a selected state */
.rate-grid.readonly .rg-day { cursor:pointer; }
.rate-grid.readonly .rg-day:hover { outline:1.5px solid var(--teal); }
.rate-grid .rg-day.sel { outline:2px solid var(--teal); font-weight:700; }

/* Per-block text colour (page builder "Text colour" option).
   !important so it beats the element rules (h2 { color: var(--ink) } etc.)
   and the hero/banner inline eyebrow colours. */
.tc h1, .tc h2, .tc h3, .tc p, .tc .eyebrow, .tc .lead, .tc li, .tc .who, .tc .quote p { color: var(--tc) !important; }
/* Text colour reaches all nineteen block types now, so the rule has to cover
   the text those newly-covered blocks contain. Everything added below carries
   its own `color:` declaration further up this file — without an entry here it
   would ignore --tc while its neighbours obeyed it. Elements that merely
   inherit are deliberately left out: they already follow.

   These selectors are a strict addition, not a change: none of them can occur
   inside a block that could carry .tc before this release (the room cards,
   tags, contact rows and form labels all live in rooms / roomlist / contact /
   availability, none of which had a text-colour option), so no already-saved
   page changes colour. */
.tc h4,
.tc .card__meta, .tc .card__meta span,
.tc .card__price, .tc .card__price small,
.tc .tag, .tc .stars,
.tc .lbl, .tc .field label,
.tc .info-row strong,
/* The hero badges (guest rating, time to beach). Their omission here is why
   they were the only hero text that ignored the block's Text colour — the
   heading, eyebrow and subtext were all covered and they were not. Unlike the
   additions above, this DOES reach already-saved pages: a hero that sets a
   text colour and has badges will now colour them too, which is the bug being
   fixed rather than a side effect of it. */
.tc .hero__badges, .tc .hero__badges strong { color: var(--tc) !important; }

/* ---------- Colour picker (admin + page builder) ----------
   A row of theme swatches beside a free custom colour. The swatches store a
   reference to the theme variable, so they are painted with that same variable
   and restyle themselves the instant the theme changes. */
.sw-row { display: flex; flex-wrap: wrap; gap: 5px; margin-bottom: 6px; }
.sw {
  width: 26px; height: 26px; padding: 0; cursor: pointer;
  border: 1.5px solid var(--sand-200); border-radius: 7px; background: transparent;
}
.sw:hover { border-color: var(--ink-soft); }
.sw.on { border-color: var(--ink); box-shadow: 0 0 0 2px rgba(31,42,46,.18); }
/* "no colour" reads as a diagonal strike over a chequerboard */
.sw--none {
  background:
    linear-gradient(to top right, transparent 46%, var(--danger) 46%, var(--danger) 54%, transparent 54%),
    repeating-conic-gradient(#e9e9e9 0% 25%, #fff 0% 50%) 0 0 / 10px 10px;
}
.sw-custom { display: flex; gap: 6px; align-items: center; }
.sw-custom input[type=color] {
  flex: 0 0 38px; height: 30px; padding: 2px; cursor: pointer;
  border: 1.5px solid var(--sand-200); border-radius: 7px; background: #fff;
}
.sw-custom input[type=text] { flex: 1; min-width: 0; }
/* Contrast warning shown when a chosen text/background pair is unreadable */
.contrast-warn {
  display: flex; gap: 8px; align-items: flex-start;
  font-size: .78rem; line-height: 1.45; border-radius: 8px; padding: 8px 10px;
  background: #fdf0dc; border: 1px solid #e8c98f; color: #6d4d12;
}
.contrast-warn.bad { background: #fbdddd; border-color: #eaacaa; color: #8a1f1a; }
.contrast-warn .cw-swatch {
  flex: 0 0 34px; height: 34px; border-radius: 6px; border: 1px solid rgba(0,0,0,.15);
  display: grid; place-items: center; font-weight: 700; font-size: .95rem;
}

/* ---------- AI assistant panel (admin) ---------- */
/* Matches the room-editor/email panel idiom: sand borders, teal accents,
   nothing new invented. See js/admin.js for the behaviour. */
.ai-select { width: 100%; }

.ai-meter {
  height: 10px; border-radius: 999px; background: var(--sand-100);
  border: 1px solid var(--sand-200); overflow: hidden;
}
.ai-meter > span {
  display: block; height: 100%; width: 0;
  background: var(--teal); transition: width .3s ease, background-color .3s ease;
}
.ai-meter > span.warn { background: var(--gold); }
.ai-meter > span.over { background: var(--danger); }
.err-text { color: var(--danger); }

.ai-out {
  margin-top: 14px; border: 1.5px solid var(--sand-200);
  border-radius: var(--radius); background: var(--sand-50); padding: 14px 16px;
}
/* pre-wrap so drafted copy keeps its paragraphs without turning into a
   horizontally-scrolling code block. */
.ai-out__text {
  margin: 0; white-space: pre-wrap; word-wrap: break-word;
  font-family: var(--sans); font-size: .92rem; line-height: 1.55; color: var(--ink);
}
.ai-out__foot {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; margin-top: 12px; padding-top: 10px;
  border-top: 1px solid var(--sand-200); font-size: .78rem;
}

/* ---------- guest concierge widget (public site) ----------
   Two hosts, one panel: the floating bubble (.cx-bubble > .cx-panel) and the
   page-builder block (.cx-inline). Everything below the two host rules is
   shared, so the conversation looks and behaves the same either way.

   Every colour is a theme custom property — no literals except the two
   translucent scrims — so the widget follows Admin → Design like the rest of
   the site. See js/concierge.js for the behaviour and js/blocks.js for the
   block. */

/* -- the floating launcher -- */
.cx-bubble {
  position: fixed; right: 20px; bottom: 20px; z-index: 900;
  display: flex; flex-direction: column; align-items: flex-end; gap: 12px;
  /* Nothing here should ever sit over a modal or the mobile nav drawer, hence
     900 rather than a four-digit z-index. */
}
.cx-launch {
  display: inline-flex; align-items: center; gap: 9px;
  padding: 12px 20px; border: 0; border-radius: 999px; cursor: pointer;
  background: var(--teal); color: var(--white);
  font-family: var(--sans); font-size: .92rem; font-weight: 600; letter-spacing: .01em;
  box-shadow: var(--shadow);
}
.cx-launch:hover { background: var(--teal-dark); }
.cx-launch:focus-visible { outline: 3px solid var(--gold); outline-offset: 2px; }
.cx-launch__ico { color: var(--gold); font-size: 1.05rem; line-height: 1; }

.cx-panel {
  display: flex; flex-direction: column;
  width: min(370px, calc(100vw - 40px));
  max-height: min(560px, calc(100vh - 130px));
  background: var(--white); border: 1.5px solid var(--sand-200);
  border-radius: var(--radius); box-shadow: var(--shadow); overflow: hidden;
}
.cx-panel__head {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 13px 16px; background: var(--teal); color: var(--white);
  font-family: var(--serif); font-size: 1.02rem;
}
.cx-close {
  border: 0; background: transparent; color: var(--white);
  font-size: 1rem; line-height: 1; cursor: pointer; padding: 4px 6px; border-radius: 6px;
}
.cx-close:hover { background: rgba(255, 255, 255, .16); }

/* -- the page-builder block -- */
.cx-inline {
  max-width: 640px; margin: 0 auto;
  background: var(--white); border: 1.5px solid var(--sand-200);
  border-radius: var(--radius); box-shadow: var(--shadow-sm); overflow: hidden;
}
.cx-inline .cx-log { max-height: 340px; }

/* -- the conversation, shared by both hosts -- */
.cx-chat { display: flex; flex-direction: column; min-height: 0; }
.cx-log {
  flex: 1 1 auto; min-height: 120px; max-height: 380px; overflow-y: auto;
  padding: 14px 16px; background: var(--sand-50);
  display: flex; flex-direction: column; gap: 12px;
}
.cx-msg { display: flex; flex-direction: column; gap: 3px; max-width: 92%; }
.cx-msg--guest { align-self: flex-end; align-items: flex-end; }
.cx-who {
  font-size: .68rem; text-transform: uppercase; letter-spacing: .09em;
  color: var(--ink-soft); opacity: .8;
}
.cx-text {
  margin: 0; padding: 9px 13px; border-radius: 13px;
  font-size: .9rem; line-height: 1.5;
  /* The reply is inserted with textContent, so a newline is the only
     formatting it can carry — pre-wrap is what makes that survive. */
  white-space: pre-wrap; overflow-wrap: anywhere;
  background: var(--white); border: 1px solid var(--sand-200); color: var(--ink);
}
.cx-msg--guest .cx-text {
  background: var(--teal); border-color: var(--teal); color: var(--white);
}
.cx-msg--wait .cx-text { color: var(--ink-soft); font-style: italic; }

.cx-form {
  display: flex; gap: 8px; align-items: flex-end;
  padding: 11px 12px; background: var(--white); border-top: 1px solid var(--sand-200);
}
/* .cx-chat scopes these so they outrank two rules that would otherwise win:
   the global `textarea { min-height: 130px }` (which turns a one-line chat box
   into a slab) and `.room-editor textarea`, which the admin panel's "try it"
   preview sits inside. */
.cx-chat .cx-input {
  flex: 1 1 auto; min-width: 0; resize: none;
  min-height: 42px; max-height: 110px; height: 42px;
  padding: 9px 12px; border: 1.5px solid var(--sand-200); border-radius: 11px;
  font-family: var(--sans); font-size: .9rem; line-height: 1.45; color: var(--ink);
  background: var(--white);
}
.cx-chat .cx-input:focus { outline: 0; border-color: var(--teal); }
.cx-send {
  flex: 0 0 auto; border: 0; border-radius: 11px; cursor: pointer;
  padding: 10px 17px; background: var(--gold); color: var(--white);
  font-family: var(--sans); font-size: .86rem; font-weight: 600;
}
.cx-send:hover { background: var(--gold-dark); }
.cx-send:disabled { opacity: .55; cursor: default; }
.cx-foot {
  margin: 0; padding: 9px 14px 11px; background: var(--white);
  border-top: 1px solid var(--sand-200);
  font-size: .7rem; line-height: 1.45; color: var(--ink-soft);
}

@media (max-width: 520px) {
  .cx-bubble { right: 12px; bottom: 12px; left: 12px; align-items: stretch; }
  .cx-launch { align-self: flex-end; }
  .cx-panel { width: 100%; max-height: calc(100vh - 110px); }
}

/* ---------- guest concierge (admin panel) ---------- */
/* The Lancelot-for-guests warning. Amber rather than red: it is a legitimate
   choice for a quiet site or a trial, just a poor default. */
.cx-warn {
  display: none; gap: 10px; align-items: flex-start;
  margin-top: 10px; padding: 11px 13px; border-radius: 10px;
  background: #fdf0dc; border: 1px solid #e8c98f; color: #6d4d12;
  font-size: .82rem; line-height: 1.5;
}
.cx-warn.on { display: flex; }
.cx-warn strong { color: #5a3f0d; }
.cx-preview { max-width: 560px; }
