/* ──────────────────────────────────────────────
   MANOR — Design System  ·  Gold-black + Santiago Orange
   Display: Newsreader (serif)  ·  Body: Instrument Sans
   Figures: Newsreader (amounts) + Instrument Sans (data)  ·  Dhivehi: Noto Sans Thaana
────────────────────────────────────────────── */

/* No @import for the webfonts here on purpose: every page already carries the
   same <link> in its <head>, and an @import makes the browser fetch this file,
   parse it, and only THEN discover the fonts — a serial round-trip that delays
   first paint on every navigation. */

:root {
  color-scheme: dark;

  /* ══ COLOUR ═══════════════════════════════════════════════════════
     One name per colour. Anything that flips between themes is redefined
     in the [data-theme="light"] block below; anything not listed there is
     deliberately the same in both themes.                              */

  /* ── Ground & surfaces ── */
  --bg:      #131010;   /* page ground */
  --surface: #161213;   /* cards, nav, forms — "gold black" */

  /* ── Text & lines ── */
  --ink:      #F4F1EC;                 /* headings, body text, light buttons */
  --muted:    rgba(244,241,236,0.55);  /* secondary text */
  --bronze:   #7E7B78;                 /* eyebrows, muted icons, hover borders */
  --hairline: rgba(255,255,255,0.10);  /* every hairline rule and input border */

  /* ── Accent — oxblood, used sparingly ── */
  --accent:      #990000;
  --accent-deep: #4A0000;   /* pressed / hover on a strong surface */

  /* ── Status ──
     Teal marks a good outcome, amber "waiting on someone", red a problem. */
  --teal:        #009999;              /* solid teal fill */
  --teal-ink:    #2FB5B5;              /* teal text on the page surface */
  --teal-bg:     rgba(0,153,153,0.14);
  --teal-border: rgba(0,153,153,0.38);
  --teal-bright: #8CE0DB;              /* teal on dark glass — badges over photos */
  --teal-deep:   #004A4A;              /* teal as a fill behind light text */

  --amber-ink:    #D6A354;
  --amber-bg:     rgba(214,163,84,0.12);
  --amber-border: rgba(214,163,84,0.35);
  --amber-bright: #E8C07A;              /* amber on dark glass — badges over photos */

  --danger:        #C25050;
  --danger-bg:     rgba(194,80,80,0.12);
  --danger-border: rgba(194,80,80,0.38);

  /* Ambient gradient animation colors */
  --ambient-a:  rgba(244,241,236,0.03);
  --ambient-b:  rgba(244,241,236,0.02);

  /* Spacing */
  --space-xs:  8px;
  --space-sm:  16px;
  --space-md:  24px;
  --space-lg:  40px;
  --space-xl:  64px;
  --space-2xl: 104px;

  /* Radius — hotel register: near-sharp */
  --radius-sm:  2px;
  --radius-md:  2px;
  --radius-lg:  2px;
  --radius-xl:  2px;
  --radius-pill:100px; /* reserved: hero search bar only */

  /* Shadows — hairlines carry the depth; shadows stay whisper-quiet */
  --shadow-sm:  0 1px 2px rgba(0,0,0,0.18);
  --shadow-md:  0 8px 28px rgba(0,0,0,0.26);
  --shadow-lg:  0 20px 50px rgba(0,0,0,0.34);

  /* Motion */
  --ease:       cubic-bezier(0.22, 1, 0.36, 1);
  --expo-out:   cubic-bezier(0.16, 1, 0.3, 1);
  --trans-fast: 0.2s ease;
  --trans-med:  0.35s var(--ease);
  --trans-slow: 0.6s var(--ease);

  /* ══ HEADER GEOMETRY ══════════════════════════════════════════════
     The navbar is the only thing on the page that knows how tall it is,
     so it publishes that height here and everything that hangs beneath
     it reads the number instead of guessing.

     --nav-h      the navbar's height RIGHT NOW. It drops when the bar
                  condenses on scroll, so anything pinned under the nav
                  (sticky bars, the mobile menu) must use this one and
                  carry the same transition, or a gap opens mid-scroll.
     --nav-h-rest the resting height, which never changes. Page padding
                  uses this — deriving it from the live height would make
                  every page lurch the moment you started scrolling.

     Before this existed the site carried five different literals for one
     navbar (62/64/72/74/84px) and none of them matched it.             */
  --nav-h-rest: 72px;
  --nav-h-min:  62px;
  --nav-h:      var(--nav-h-rest);
}

/* Set by js/main.js the moment the navbar condenses. On <html> so it is
   available to fixed elements that live outside <body>'s stacking context. */
html.nav-condensed { --nav-h: var(--nav-h-min); }

/* ── LIGHT MODE — MANOR foam register ─────────────────────────
   Same identity, inverted ground: foam paper, gold-black ink.
   --ink acts as the "strong" color (text + primary buttons),
   --surface as the raised card color — both flip together.   */
[data-theme="light"] {
  color-scheme: light;

  /* Ground & surfaces */
  --bg:      #FFFFFF;
  --surface: #F7F5F2;

  /* Text & lines */
  --ink:      #0D0B0B;
  --muted:    rgba(13,11,11,0.55);
  --hairline: rgba(13,11,11,0.12);
  /* --bronze does not flip — the same neutral works on both grounds */

  /* Status — the ink darkens so it stays readable on foam paper.
     The base hues here are teal #00847E and amber #A07426. */
  --teal-ink:     #00706B;
  --teal-bg:      rgba(0,132,126,0.10);
  --teal-border:  rgba(0,132,126,0.32);
  --amber-ink:    #8A6420;
  --amber-bg:     rgba(160,116,38,0.10);
  --amber-border: rgba(160,116,38,0.30);
  --danger:        #A83232;
  --danger-bg:     rgba(168,50,50,0.10);
  --danger-border: rgba(168,50,50,0.32);
  /* --accent, --accent-deep, --teal, --teal-bright and --teal-deep hold
     across both themes on purpose. */

  --ambient-a:  rgba(13,11,11,0.02);
  --ambient-b:  rgba(13,11,11,0.02);

  --shadow-sm:  0 1px 2px rgba(13,11,11,0.06);
  --shadow-md:  0 8px 28px rgba(13,11,11,0.10);
  --shadow-lg:  0 20px 50px rgba(13,11,11,0.14);
}

/* Light-mode overrides for the few literal dark glass surfaces */
[data-theme="light"] .navbar.scrolled { background: rgba(255,255,255,0.92); }
[data-theme="light"] .nav-mobile-menu { background: rgba(255,255,255,0.98); }
[data-theme="light"] .mobile-cta { background: rgba(255,255,255,0.97); }
[data-theme="light"] .card-footer { background: rgba(13,11,11,0.05); }
[data-theme="light"] .post-map .leaflet-tile-pane,
[data-theme="light"] .detail-map .leaflet-tile-pane { filter: none; }
[data-theme="light"] ::selection { background: rgba(153,0,0,0.16); color: #0D0B0B; }
[data-theme="light"] .hsearch { box-shadow: 0 16px 40px rgba(13,11,11,0.10); }
[data-theme="light"] .lightbox { background: rgba(255,255,255,0.96); }

/* ── THEME SWITCH — blurred circle sweep from top left ── */
::view-transition-group(root) {
  animation-timing-function: var(--expo-out);
}

::view-transition-new(root) {
  mask: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 40"><defs><filter id="blur"><feGaussianBlur stdDeviation="2"/></filter></defs><circle cx="0" cy="0" r="18" fill="white" filter="url(%23blur)"/></svg>') top left / 0 no-repeat;
  mask-origin: content-box;
  animation: scale 1s;
  animation-fill-mode: both;
  transform-origin: top left;
}

::view-transition-old(root),
.dark::view-transition-old(root) {
  animation: scale 1s;
  animation-fill-mode: both;
  transform-origin: top left;
  z-index: -1;
}

@keyframes scale {
  to {
    mask-size: 350vmax;
  }
}

/* ── Figures ──
   Numbers used to be set in IBM Plex Mono, which read like a terminal next to
   an editorial brand. Now:
     --font-num   prices, amounts and display numerals — the same serif the
                  card price already used, so figures match the masthead
     --font-data  small changing numbers (counts, inputs, timers) in the body
                  sans with tabular figures, so digits stay column-aligned
     --font-code  kept ONLY where digits must be read one by one and can't be
                  confused — the verification code, admin audit values */
:root {
  --font-num:  'Newsreader', serif;
  --font-data: 'Instrument Sans', sans-serif;
  --font-code: 'IBM Plex Mono', monospace;
}

/* ── RESET ── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

/* The sideways clip lives HERE, on <html>, and must never move to <body>.
   overflow-x on body computes to `hidden auto` — which turns body into a
   second, nested scroll container inside the viewport's own. Two scrollers
   means two places momentum can live: the page drifts sideways while it
   scrolls down, iOS rubber-bands the inner one against the outer one, the
   address bar never settles, and window.scrollY reads 0 forever while the
   page is plainly moving. On <html> the same clip applies to the viewport
   itself and there is only ever one thing scrolling. */
html {
  scroll-behavior: smooth; -webkit-text-size-adjust: 100%; background: var(--bg);
  overflow-x: hidden;
  /* The gutter is always reserved, so holding the page (below) taking the
     scrollbar away can't shove the whole layout sideways by 15px. */
  scrollbar-gutter: stable;
}

body {
  background: var(--bg);
  color: var(--ink);
  font-family: 'Instrument Sans', sans-serif;
  font-weight: 400;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  touch-action: manipulation;
}

/* ── Held page ──
   Set by resideLockScroll() in js/main.js while something covers the page: the
   mobile menu, the auth sheet, the lightbox, the report and record modals.
   `top` is written inline as the negative of where you were, so the page stays
   exactly where you left it instead of jumping to the top — and pinning it is
   what stops iOS scrolling the page behind the thing you just opened. */
html.reside-locked { overflow: hidden; }
html.reside-locked body {
  position: fixed;
  left: 0; right: 0; width: 100%;
  overflow: hidden;
}

::selection { background: rgba(153,0,0,0.40); color: var(--ink); }

/* ── Dhivehi font override ── */
body.dv,
body.dv p, body.dv h1, body.dv h2, body.dv h3, body.dv h4,
body.dv button, body.dv a, body.dv span, body.dv label,
body.dv input, body.dv textarea, body.dv select {
  font-family: 'Noto Sans Thaana', sans-serif;
}
body.dv .logo-en,
body.dv .stat-num,
body.dv .card-price-num { font-family: 'Newsreader', serif; }

img { display: block; max-width: 100%; }
/* Discourages drag-to-save / long-press-save on listing photos and the mark.
   Not real protection — anything on screen can still be screenshotted. */
img, .brand-mark { -webkit-user-drag: none; -khtml-user-drag: none; -moz-user-drag: none;
  -o-user-drag: none; user-select: none; -webkit-user-select: none; -webkit-touch-callout: none; }
button { cursor: pointer; border: none; background: none; font-family: inherit; }
a { text-decoration: none; color: inherit; }
ul { list-style: none; }
input, textarea, select { font-family: inherit; }

/* ── LANGUAGE SYSTEM ── */
[data-lang="dv"]             { display: none; }
body.dv [data-lang="en"]     { display: none; }
body.dv [data-lang="dv"]     { display: block; }
body.dv span[data-lang="dv"] { display: inline; }
body.dv span[data-lang="en"] { display: none; }
body.dv                      { direction: rtl; }

/* ── UTILITY ── */
.container { max-width: 1240px; margin: 0 auto; width: 100%; padding: 0 40px; }

.eyebrow {
  display: inline-flex; align-items: center; gap: 10px;
  font-size: 10.5px; font-weight: 600; letter-spacing: 0.26em;
  text-transform: uppercase; color: var(--bronze); margin-bottom: 16px;
}
.eyebrow::before { content: ''; width: 20px; height: 1px; background: var(--bronze); flex-shrink: 0; }
body.dv .eyebrow { flex-direction: row-reverse; }
body.dv .eyebrow::before { display: none; }
body.dv .eyebrow::after { content: ''; width: 20px; height: 1px; background: var(--bronze); flex-shrink: 0; }

.big-headline {
  font-family: 'Newsreader', serif; font-weight: 400;
  font-size: clamp(30px, 4vw, 52px); color: var(--ink);
  line-height: 1.1; letter-spacing: -0.015em;
}
.big-headline em { font-style: italic; color: var(--accent); }

/* ── SCROLL REVEAL ── */
.reveal { opacity: 0; transform: translateY(22px); transition: opacity 0.7s var(--ease), transform 0.7s var(--ease); }
.reveal.delay-1 { transition-delay: 0.08s; }
.reveal.delay-2 { transition-delay: 0.16s; }
.reveal.delay-3 { transition-delay: 0.24s; }
.reveal.visible { opacity: 1; transform: translateY(0); }

@media (prefers-reduced-motion: reduce) {
  .reveal { transition: none; opacity: 1; transform: none; }
  * { animation-duration: 0.001ms !important; animation-iteration-count: 1 !important; }
}

/* ── BUTTONS ── */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 14px 26px; font-size: 14px; font-weight: 600;
  border-radius: 2px;
  transition: transform var(--trans-med), box-shadow var(--trans-med), background var(--trans-med), color var(--trans-med), border-color var(--trans-med);
  white-space: nowrap; cursor: pointer; font-family: inherit; border: none;
  letter-spacing: 0.01em;
}
/* Primary — foam, never orange */
.btn-primary, .btn-gold, .btn-dark, .btn-light {
  background: var(--accent); color: #F4F1EC;
}
.btn-primary:hover, .btn-gold:hover, .btn-dark:hover, .btn-light:hover {
  background: var(--accent-deep); transform: translateY(-1px); box-shadow: var(--shadow-md);
}

.btn-ghost { background: transparent; color: var(--ink); border: 1px solid var(--hairline); }
.btn-ghost:hover { border-color: var(--bronze); transform: translateY(-1px); }

.btn-ghost-light { background: transparent; color: var(--muted); border: 1px solid var(--hairline); }
.btn-ghost-light:hover { border-color: var(--bronze); color: var(--ink); }

.btn-sm { padding: 10px 18px; font-size: 13px; }
.btn-lg { padding: 16px 32px; font-size: 15px; }

/* ── BADGE ── */
.badge {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 10px; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase;
  padding: 5px 11px; border-radius: 2px;
}
/* badge-dark sits on photos — its backing is always dark glass, so the
   text stays light in BOTH themes (foam flips to near-black in light). */
.badge-dark    { background: rgba(13,11,11,0.80); color: #F4F1EC; border: 1px solid rgba(255,255,255,0.16); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px); }
.badge-teal    { background: var(--teal-bg); color: var(--teal-ink); border: 1px solid var(--teal-border); }
/* Live — the state that matters most, so it is the only solid-filled status
   badge. Everything else is a tint, which keeps "Live" unmistakable next to
   "Pending Review" (those two used to render identically). */
.badge-live    { background: var(--teal); color: #F4F1EC; border: 1px solid var(--teal); }
.badge-amber   { background: var(--amber-bg); color: var(--amber-ink); border: 1px solid var(--amber-border); }
.badge-light   { background: var(--ink); color: var(--surface); }
.badge-outline { background: transparent; border: 1px solid var(--hairline); color: var(--muted); }
.badge-danger  { background: var(--danger-bg); color: var(--danger); border: 1px solid var(--danger-border); }
/* Any badge inside a photo frame gets a dark glass backing so it stays
   readable over bright images, whatever the theme. */
.card-img .badge-teal, .pcard-badge.badge-teal {
  background: rgba(13,11,11,0.72); color: var(--teal-bright); border: 1px solid rgba(0,153,153,0.45);
  -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
}
.card-img .badge-amber, .pcard-badge.badge-amber {
  background: rgba(13,11,11,0.72); color: var(--amber-bright); border: 1px solid rgba(214,163,84,0.50);
  -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
}
/* badge-live stays solid teal even over a photo — that is the whole point of it */
/* Featured — paid promotion, so it gets the only gold on the site.
   Named alongside .pcard-badge so the homepage card's own background and
   border (which share its specificity) cannot win on source order and leave
   a gold badge painted teal. */
.badge-featured, .pcard-badge.badge-featured {
  background: linear-gradient(100deg, #6E5A22 0%, #C8A75A 38%, #F2DFA4 50%, #C8A75A 62%, #6E5A22 100%);
  background-size: 220% 100%;
  color: #2A2007; border: none;
  animation: badgeShine 4.5s ease-in-out infinite;
}
@keyframes badgeShine { 0%, 100% { background-position: 130% 0; } 50% { background-position: -30% 0; } }
@media (prefers-reduced-motion: reduce) { .badge-featured { animation: none; background-position: 50% 0; } }

/* ── FORM ELEMENTS — register lines, not boxes ── */
.form-group { display: flex; flex-direction: column; gap: 8px; }
.form-label {
  font-size: 11px; font-weight: 600; color: var(--muted);
  letter-spacing: 0.14em; text-transform: uppercase;
}
.form-input, .form-select, .form-textarea {
  width: 100%; padding: 12px 2px; font-size: 15px; font-family: inherit;
  color: var(--ink); background: transparent;
  border: none; border-bottom: 1px solid var(--bronze);
  border-radius: 0; transition: border-color var(--trans-fast);
  outline: none; -webkit-appearance: none;
}
.form-input:focus, .form-select:focus, .form-textarea:focus {
  border-bottom-color: var(--ink); box-shadow: none;
}
.form-input::placeholder, .form-textarea::placeholder { color: var(--muted); opacity: 0.55; }
.form-textarea { resize: vertical; min-height: 120px; }
.form-hint { font-size: 12px; color: var(--muted); font-weight: 400; }
.form-error { font-size: 12px; color: var(--danger); font-weight: 500; }

/* ── MOBILE ── */
@media (max-width: 768px) { .container { padding: 0 20px; } }

/* ── ACCESSIBILITY ── */
.skip-link {
  position: fixed; top: -100px; left: 20px; z-index: 9999;
  background: var(--ink); color: var(--surface); font-weight: 700; font-size: 14px;
  padding: 12px 20px; border-radius: 2px;
  transition: top 0.2s ease;
}
.skip-link:focus { top: 16px; }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 2px;
}
:focus:not(:focus-visible) { outline: none; }

@media (max-width: 768px) {
  /* 44px is the right tap target for a field or a button, but applying it to a
     checkbox stretched the box to 44px tall so its tick floated well below the
     line of text beside it. Those get their tap area from the <label>. */
  .btn, button, input:not([type="checkbox"]):not([type="radio"]), select, textarea { min-height: 44px; }
  input[type="checkbox"], input[type="radio"] { min-height: 0; }
  .btn-sm { min-height: 38px; }
}

/* ── AMBIENT ANIMATION KEYFRAMES ── */
@keyframes ambientDrift {
  from { transform: translate(0, 0);    opacity: 0.75; }
  to   { transform: translate(1.8%, 1.2%); opacity: 1; }
}
@keyframes ambientDrift2 {
  from { transform: translate(0, 0);      opacity: 0.80; }
  to   { transform: translate(-1.5%, -1%); opacity: 0.62; }
}
@media (prefers-reduced-motion: reduce) {
  .ambient-layer { animation: none !important; }
}
