/* ==========================================================================
   MUSAFIR CAFE — style.css
   Tokens · reset · base typography · layout · ALL components.
   (effects.css owns keyframes/transitions · responsive.css owns media queries)
   --------------------------------------------------------------------------

   DESIGN DNA
   Direction ........ Hill Station Window (INVENTED — the site is built around
                      one idea: what you see from the table. Photography carries
                      it; type stays out of the way.)
   Palette family ... mist grey-green + deodar ink + Landour teal. A cool light
                      ground with a desaturated teal — absent from the portfolio.
                      The teal is the real colour of Mussoorie's old cottage
                      doors and window frames, which is why the hero is a window.
   Display face ..... Young Serif (chunky wedge serifs — carved, trail-sign)
   Body face ........ Onest (400/500/600)
   Hero pattern ..... The Window Seat — a full-bleed valley photograph sitting
                      BEHIND a window frame drawn in CSS (a 3-column x 2-row
                      mullion grid in deodar ink, with a sill bar along the
                      bottom). Headline, altitude and the two actions sit ON the
                      sill, never over the view.
   Signature ........ The Milestone — the Indian roadside kilometre-stone,
                      rendered as inline SVG from one PHP helper. Every section
                      divider, the footer, the contact map and 404. One device,
                      never a second.
   Corner language .. 8px on media ONLY. Buttons, inputs, cards, panels: 0px
                      square. Deliberately quiet, so it can never be confused
                      with Chaska's heavy 32px.
   Elevation ........ exactly ONE shadow, --shadow-lift, and it is INVERTED
                      (lifts from below). No downward drop shadow on this site.
   Motion ........... one curve, cubic-bezier(.22,.61,.36,1) — a calm ease-out,
                      no overshoot. Fade-and-rise reveals only.

   First-timers:
     1. Time-aware hero — config.php computes the hour in Asia/Kolkata and the
        hero serves dawn / day / dusk: a different valley photograph AND a
        different overlay tint, with the greeting line changing to match.
        Entirely server-side — zero JavaScript.
     2. Scroll-thinning mist — a layered fog wash over the ridge that reduces in
        opacity as the hero scrolls out (IntersectionObserver + a single CSS
        custom property). Under prefers-reduced-motion the mist renders at its
        final, cleared value and never animates.

   --------------------------------------------------------------------------
   NOTES FOR THE RESPONSIVE AGENT (read these — they are load-bearing)
     * NO grid-template-areas are declared anywhere in this file. Nothing to
       reset. Multi-column layouts are plain grid-template-columns overrides.
     * THE NAV IS NO-JS-FIRST. With no JavaScript, <html> never gets .is-js, so
       .nav-panel renders OPEN in the header flow and .nav-toggle is
       display:none (a button that could do nothing is not shown). Only
       html.is-js collapses the panel and reveals the toggle. At min-width:768px
       responsive.css MUST put the panel back in flow for the .is-js case —
       `.is-js .nav-panel { position:static; display:block; ... }` — and hide
       .nav-toggle again, or desktop shows a burger over an open menu.
       main.js detects "mobile" via `toggle.offsetParent !== null`, so hiding
       .nav-toggle at 768 is what tells the script it is on desktop.
     * .nav is flex-wrap:wrap and uses `order`: brand(1) toggle(2)
       status-chip(3) nav-panel(4). The chip is ordered last so it wraps to its
       own line on narrow phones without a media query; reset the orders at 768
       if you want it inline between the wordmark and the links.
       .brand-meta is display:none on mobile — reveal it at 768.
     * .mobile-bar is fixed and visible by default, and body carries
       padding-bottom:var(--bar-h) to clear it. responsive.css MUST hide the bar
       AND zero that padding at min-width:768px.
     * .grid, .board, .milestone-list, .room-split, .walk-strip and .visit-block
       are all single column here. Their column counts belong to responsive.css.
     * --gutter grows in responsive.css: 2.5rem @768 · 3.5rem @1024 · 4.5rem @1440

   NOTE ON .reveal — not declared in this file on purpose. effects.css owns it
   and gates it on html.is-js (the class header.php sets inline in <head>, and
   which main.js/animations.js re-assert), so content is never hidden when
   scripting is off. NOT .has-js — that is the sibling site's convention.
   ========================================================================== */


/* ==========================================================================
   1. TOKENS
   ========================================================================== */

:root {
  /* Palette — Hill Station Window · mist / deodar / Landour teal */
  --color-bg:          #E6E9E6;  /* mist — the ground */
  --color-surface:     #F2F4F1;  /* raised panels, cards */
  --color-well:        #D6DBD6;  /* recessed wells, image mats */
  --color-ink:         #1C2621;  /* deodar — near-black pine */
  --color-muted:       #5C6A61;  /* secondary type */
  --color-accent:      #2E6F72;  /* Landour teal — the cottage door */
  --color-accent-deep: #1F5254;  /* teal for small type + focus rings */
  --color-rust:        #A84B2A;  /* tin roof — ONLY the open/closed status chip */
  --color-border:      rgba(28,38,33,0.14);

  /* Typography */
  --font-display: 'Young Serif', Georgia, serif;
  --font-body:    'Onest', system-ui, sans-serif;

  /* Fluid type scale */
  --text-xs: clamp(.75rem,1vw,.8125rem);    --text-sm: clamp(.8125rem,1.1vw,.9375rem);
  --text-base: clamp(1rem,1.4vw,1.0625rem); --text-lg: clamp(1.125rem,2vw,1.375rem);
  --text-xl: clamp(1.5rem,3vw,2rem);        --text-2xl: clamp(2rem,4.5vw,3rem);
  --text-3xl: clamp(2.5rem,6vw,4rem);       --text-hero: clamp(2.75rem,7vw,5.5rem);

  /* Spacing · Shape · Shadow · Motion */
  --space-xs:.5rem; --space-sm:1rem; --space-md:2rem; --space-lg:4rem; --space-xl:7rem;
  --radius-sm:0px; --radius-md:0px; --radius-media:8px; --radius-full:9999px;
  --shadow-lift: 0 -4px 16px rgba(28,38,33,.06);
  --transition:.4s cubic-bezier(.22,.61,.36,1);

  --container:1280px;
  --gutter:1.25rem;  /* 2.5rem @768 · 3.5rem @1024 · 4.5rem @1440 */
}

/* Component-local additions. NOT part of the binding palette — no new colour
   values are introduced here, only geometry and rhythm. */
:root {
  --bar-h:            4.25rem;                    /* sticky mobile bar height */
  --header-h:         4rem;                       /* sticky site header height */
  --section-pad:      clamp(3rem, 9vw, 7rem);     /* fluid section rhythm */
  --track:            .14em;                      /* the one tracked-label value */
  --rule:             1px solid var(--color-border);
  --ws-bar:           clamp(9px, 1.5vw, 15px);    /* mullion bar thickness */
  --ws-min:           max(560px, 88vh);           /* hero height floor */
  --tap:              2.75rem;                    /* 44px minimum touch target */
}

@supports (height: 100svh) {
  :root { --ws-min: max(560px, 88svh); }
}


/* ==========================================================================
   2. RESET
   ========================================================================== */

*, *::before, *::after { box-sizing: border-box; }

* { margin: 0; padding: 0; }

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  overflow-x: hidden;
}

body {
  min-height: 100vh;
  overflow-x: hidden;
  background-color: var(--color-bg);
  color: var(--color-ink);
  font-family: var(--font-body);
  font-size: var(--text-base);
  font-weight: 400;
  line-height: 1.62;
  letter-spacing: 0;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  /* clears the sticky mobile bar — responsive.css zeroes this at 768 */
  padding-bottom: var(--bar-h);
}

img, svg, video, canvas, picture {
  display: block;
  max-width: 100%;
}

img, video { height: auto; }

button, input, select, textarea {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  border-radius: 0;
}

button { cursor: pointer; }

a { color: inherit; text-decoration: none; }

ul, ol { list-style: none; }

table { border-collapse: collapse; width: 100%; }

hr {
  border: 0;
  border-top: var(--rule);
}

::selection {
  background: var(--color-accent);
  color: var(--color-surface);
}


/* ==========================================================================
   3. BASE TYPOGRAPHY
   ========================================================================== */

h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-display);
  font-weight: 400;          /* Young Serif ships one weight — never fake-bold it */
  line-height: 1.1;
  letter-spacing: -0.01em;
  color: var(--color-ink);
  text-wrap: balance;
}

h1 { font-size: var(--text-3xl); }
h2 { font-size: var(--text-2xl); }
h3 { font-size: var(--text-xl); }
h4 { font-size: var(--text-lg); line-height: 1.2; }
h5, h6 { font-size: var(--text-base); line-height: 1.3; }

p { text-wrap: pretty; }

p + p { margin-top: var(--space-sm); }

strong, b { font-weight: 600; }

small { font-size: var(--text-sm); }

address { font-style: normal; }

/* Inline links inside prose get the teal + an underline that is part of the
   text, not a hover surprise. */
p a, li a, address a, dd a {
  color: var(--color-accent-deep);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
}

p a:hover, li a:hover, address a:hover, dd a:hover {
  color: var(--color-ink);
}

/* The one tracked-label treatment on this site. inline-block + a negative
   margin-right cancels the trailing letter-space so a CENTRED label sits
   optically centred. Never text-indent. */
.card-meta,
.ws-alt,
.footer-title,
.field-label {
  font-family: var(--font-body);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: var(--track);
  text-transform: uppercase;
  color: var(--color-muted);
}


/* ==========================================================================
   4. LAYOUT PRIMITIVES
   ========================================================================== */

.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.section {
  padding-block: var(--section-pad);
}

.section-head {
  max-width: 46rem;
  margin-bottom: var(--space-lg);
}

.section-title {
  font-family: var(--font-display);
  font-size: var(--text-2xl);
  line-height: 1.08;
  color: var(--color-ink);
}

.section-lead {
  margin-top: var(--space-sm);
  font-size: var(--text-lg);
  line-height: 1.5;
  color: var(--color-muted);
  max-width: 40rem;
}

/* Single column here on purpose — responsive.css owns every column count. */
.grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-md);
}

/* Screen-reader-only. DEFINED, not just emitted — a past build shipped this
   class undefined and every screen-reader string rendered as visible text. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* A .sr-only skip link becomes visible when it takes focus. */
.sr-only:focus,
.sr-only:active {
  position: static;
  width: auto;
  height: auto;
  margin: 0;
  overflow: visible;
  clip: auto;
  clip-path: none;
  white-space: normal;
}

/* .reveal — the fade-and-rise scroll reveal. Its hidden state, its transition
   and its prefers-reduced-motion escape hatch live in effects.css, deliberately.
   style.css must NOT set opacity:0 here, or content would disappear whenever
   effects.css or the observer fails to load. Nothing to declare. */


/* ==========================================================================
   5. FOCUS — every interactive element, visibly
   ========================================================================== */

a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
summary:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--color-accent-deep);
  outline-offset: 3px;
}

/* On the dark sill and the ink footer the deep teal ring would vanish —
   switch it to the mist ground so it stays visible. */
.ws-sill a:focus-visible,
.ws-sill button:focus-visible,
.site-footer a:focus-visible,
.site-footer button:focus-visible,
.site-footer input:focus-visible {
  outline-color: var(--color-bg);
}


/* ==========================================================================
   6. SITE HEADER + NAV
   ========================================================================== */

/* The skip link: out of sight until it takes focus, then unmissable. */
.nav-skip {
  position: absolute;
  left: var(--gutter);
  top: -6rem;
  z-index: 80;
  padding: .7rem 1.1rem;
  background-color: var(--color-ink);
  color: var(--color-bg);
  font-size: var(--text-sm);
  font-weight: 600;
  border-radius: var(--radius-sm);
}

.nav-skip:focus { top: var(--space-xs); }

.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background-color: var(--color-bg);
  border-bottom: var(--rule);
}

/* .nav sits on the same element as .container in the markup. It wraps, because
   at 360px the wordmark, the toggle and a status line reading
   "Open now · until 9:00 pm" cannot share one row without overflowing.
   Mobile order: brand · toggle / status-chip / panel. */
.nav {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  column-gap: var(--space-sm);
  row-gap: .5rem;
  min-height: var(--header-h);
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter);
  padding-block: .5rem;
}

.brand {
  order: 1;
  flex: 1 1 auto;
  min-width: 0;
  display: inline-flex;
  flex-direction: column;
  align-items: flex-start;
  gap: .1rem;
  color: var(--color-ink);
}

.brand:hover { color: var(--color-accent-deep); }

.brand-name {
  font-family: var(--font-display);
  font-size: var(--text-lg);
  line-height: 1;
  letter-spacing: -0.01em;
  white-space: nowrap;
}

/* The road + altitude line. Hidden at 360px, where it would push the toggle
   off the row. RESPONSIVE AGENT: reveal it at min-width:768px. */
.brand-meta {
  display: none;
  font-family: var(--font-body);
  font-size: var(--text-xs);
  font-weight: 500;
  line-height: 1.25;
  letter-spacing: .01em;
  color: var(--color-muted);
}

/* Ordered AFTER the toggle so that when "Open now · until 9:00 pm" will not fit
   beside the wordmark, flex-wrap drops it to its own line by itself — the chip
   still hugs its own text instead of stretching a full-width box across the
   masthead, and no media query is involved. */
.nav .status-chip {
  order: 3;
  flex: 0 1 auto;
  align-self: center;
}

/* ---- THE NO-JS NAV MODEL ------------------------------------------------
   With scripting off, <html> never receives .is-js: the panel is simply part
   of the header and every link is reachable, and the toggle is not rendered at
   all rather than sitting there doing nothing. html.is-js — set by an inline
   script in header.php before first paint — is what collapses the panel and
   brings the toggle in. Getting this the other way round ships a hidden menu
   with no way to open it. */

.nav-panel {
  order: 4;
  flex: 1 0 100%;
  border-top: var(--rule);
  padding-block: var(--space-xs) var(--space-xs);
}

.nav-toggle { display: none; }

.is-js .nav-panel {
  position: absolute;
  left: 0;
  right: 0;
  top: 100%;
  display: none;
  flex: none;
  max-height: calc(100vh - var(--header-h));
  overflow-y: auto;
  overscroll-behavior: contain;
  background-color: var(--color-surface);
  border-top: var(--rule);
  border-bottom: var(--rule);
  padding: var(--space-sm) var(--gutter) var(--space-md);
}

.is-js .nav-panel.is-open { display: block; }

.is-js .nav-toggle {
  order: 2;
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .45rem;
  min-width: var(--tap);
  min-height: var(--tap);
  padding-inline: .7rem;
  border: 1px solid var(--color-ink);
  border-radius: var(--radius-sm);
  background-color: transparent;
  color: var(--color-ink);
}

.nav-toggle:hover,
.nav-toggle.is-open {
  background-color: var(--color-ink);
  color: var(--color-bg);
}

.nav-toggle-icon {
  width: 1.3rem;
  height: 1.3rem;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: square;
}

/* While the panel is open the page behind it does not scroll. The panel has its
   own max-height + overflow above, so nothing is ever unreachable. */
.is-nav-open,
.is-nav-open body { overflow: hidden; }

.nav-list {
  display: flex;
  flex-direction: column;
  gap: 0;
}

.nav-link {
  display: block;
  padding: .8rem 0;
  font-size: var(--text-base);
  font-weight: 500;
  color: var(--color-ink);
  border-bottom: var(--rule);
}

.nav-list > li:last-child .nav-link { border-bottom: 0; }

.nav-link:hover { color: var(--color-accent-deep); }

.nav-link.is-current,
.nav-link[aria-current="page"] {
  color: var(--color-accent-deep);
  font-weight: 600;
}

/* the Get directions button lives in the last .nav-list item */
.nav-list .btn { margin-top: var(--space-xs); width: 100%; }


/* ==========================================================================
   7. BUTTONS + CHIPS  (0px corners — the whole site is square but the media)
   ========================================================================== */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .5rem;
  min-height: var(--tap);
  padding: .85rem 1.5rem;
  padding-right: calc(1.5rem - var(--track));  /* cancels the trailing track */
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  font-family: var(--font-body);
  font-size: var(--text-sm);
  font-weight: 600;
  letter-spacing: var(--track);
  text-transform: uppercase;
  line-height: 1;
  text-align: center;
  white-space: nowrap;
}

.btn-primary {
  background-color: var(--color-accent);
  border-color: var(--color-accent);
  color: var(--color-surface);
}

.btn-primary:hover {
  background-color: var(--color-accent-deep);
  border-color: var(--color-accent-deep);
}

.btn-ghost {
  background-color: transparent;
  border-color: var(--color-ink);
  color: var(--color-ink);
}

.btn-ghost:hover {
  background-color: var(--color-ink);
  color: var(--color-bg);
}

.btn[aria-disabled="true"],
.btn:disabled {
  opacity: .5;
  cursor: not-allowed;
}

/* Generic chip — menu categories, tags, the altitude badge. Square. */
.chip {
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  padding: .35rem .7rem;
  padding-right: calc(.7rem - var(--track));
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background-color: var(--color-surface);
  color: var(--color-muted);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: var(--track);
  text-transform: uppercase;
  line-height: 1.4;
  white-space: nowrap;
}

a.chip:hover,
button.chip:hover {
  border-color: var(--color-accent-deep);
  color: var(--color-accent-deep);
}

.chip.is-active {
  background-color: var(--color-ink);
  border-color: var(--color-ink);
  color: var(--color-bg);
}


/* ==========================================================================
   8. STATUS CHIP — the ONLY place --color-rust appears on this site
   ========================================================================== */

.status-chip {
  display: inline-flex;
  align-items: center;
  gap: .45rem;
  padding: .3rem .65rem;
  padding-right: calc(.65rem - var(--track));
  border: 1px solid currentColor;
  border-radius: var(--radius-sm);
  background-color: transparent;
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: var(--track);
  text-transform: uppercase;
  line-height: 1.4;
  white-space: nowrap;
}

.status-chip::before {
  content: "";
  width: .5rem;
  height: .5rem;
  flex: none;
  background-color: currentColor;
  /* the dot is the only round thing on the site — it is a signal, not a corner */
  border-radius: var(--radius-full);
}

.status-open   { color: var(--color-accent-deep); }
.status-closed { color: var(--color-rust); }


/* ==========================================================================
   9. THE WINDOW SEAT — the hero. Everything here rests on it.
      Stack, bottom to top:
        .ws-view    z0  the photograph
        .mist       z1  the fog wash over the ridge
        .ws-mullion z2  deodar-ink frame, 3 columns x 2 rows, FIXED
        .ws-sill    z3  the bar the copy sits ON (never over the view)
   ========================================================================== */

.window-seat {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  min-height: var(--ws-min);
  overflow: hidden;
  background-color: var(--color-well);
  isolation: isolate;
}

/* --- the photo layer ---------------------------------------------------- */

.ws-view {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  background-color: var(--color-well);
}

.ws-view img,
.ws-view picture,
.ws-view picture img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 42%;   /* keeps the ridge line in the upper cells */
  border-radius: 0;              /* the view is full-bleed, never rounded */
}

/* The photo shifts a few pixels behind the mullions. The bars never move —
   they belong to the building, not the landscape. The 1.08 scale is the bleed
   the shift eats into, so no edge is ever exposed.
   JS/effects.css animate --ws-parallax only; if neither runs it stays 0. */
.ws-view img {
  --ws-parallax: 0px;
  transform: translate3d(0, var(--ws-parallax), 0) scale(1.08);
  transform-origin: center 40%;
  will-change: transform;
}

/* Per-phase overlay tint. Server-side classes from hero_phase(); the base tint
   below applies with or without them, so the photo is always legible. */
.ws-view::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image: linear-gradient(
    to bottom,
    rgba(28,38,33,.34) 0%,
    rgba(28,38,33,.10) 38%,
    rgba(28,38,33,.26) 100%
  );
}

.window-seat.is-dawn .ws-view::after {
  background-image: linear-gradient(
    to bottom,
    rgba(28,38,33,.20) 0%,
    rgba(230,233,230,.16) 46%,
    rgba(28,38,33,.24) 100%
  );
}

.window-seat.is-day .ws-view::after {
  background-image: linear-gradient(
    to bottom,
    rgba(28,38,33,.30) 0%,
    rgba(28,38,33,.06) 40%,
    rgba(28,38,33,.22) 100%
  );
}

.window-seat.is-dusk .ws-view::after {
  background-image: linear-gradient(
    to bottom,
    rgba(28,38,33,.46) 0%,
    rgba(46,111,114,.18) 44%,
    rgba(28,38,33,.38) 100%
  );
}

/* --- the mist ----------------------------------------------------------- */

/* FAIL-SAFE BY DESIGN: the CLEARED, final value is the default. JS only ever
   adds the thicker state. If the observer never runs, the hero is clear and
   readable — not fogged out. */
.mist {
  --mist-density: .16;           /* cleared / final — the default */
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  opacity: var(--mist-density);
  background-image:
    linear-gradient(to top,
      rgba(242,244,241,0) 0%,
      rgba(242,244,241,.55) 38%,
      rgba(230,233,230,.92) 72%,
      rgba(230,233,230,.68) 100%),
    radial-gradient(120% 55% at 50% 68%,
      rgba(242,244,241,.85) 0%,
      rgba(242,244,241,0) 70%);
}

/* the thicker state — added by animations.js at the top of the page, or set
   directly as --mist-density on the element. Both work. */
.mist.is-thick { --mist-density: .88; }

/* --- the mullions: a 3-column x 2-row grid of deodar-ink bars ----------- */

/* Drawn entirely on this one element (outer frame = border, interior bars =
   three gradients) so it needs no child markup and can never be knocked out of
   alignment by the photo moving behind it. */
.ws-mullion {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  border: var(--ws-bar) solid var(--color-ink);
  background-repeat: no-repeat;
  background-image:
    linear-gradient(to right,  var(--color-ink) 0 100%),  /* vertical bar 1 */
    linear-gradient(to right,  var(--color-ink) 0 100%),  /* vertical bar 2 */
    linear-gradient(to bottom, var(--color-ink) 0 100%);  /* horizontal bar */
  background-size:
    var(--ws-bar) 100%,
    var(--ws-bar) 100%,
    100% var(--ws-bar);
  background-position:
    33.333% 0,
    66.666% 0,
    0 50%;
  background-origin: border-box;
  background-clip: border-box;
}

/* RECONCILED WITH home.php, WHICH EMITS SIX <span class="ws-pane"> CHILDREN.
   The frame is drawn entirely on .ws-mullion above — one border plus three
   gradients — so the panes are not needed and are switched off here rather
   than left as unstyled dead markup. The gradient version is the one kept
   because it cannot drift out of register with the photograph moving behind
   it: there is no second box model to disagree with the first. Never give
   .ws-pane a size — a bordered 3x2 grid of cells on top of this would double
   every bar in the window. The panes carry no content, so nothing is lost. */
.ws-mullion > .ws-pane { display: none; }

/* --- the sill: the copy sits ON it, never over the view ---------------- */

.ws-sill {
  position: relative;
  z-index: 3;
  width: 100%;
  background-color: var(--color-bg);
  border-top: var(--ws-bar) solid var(--color-ink);
  box-shadow: var(--shadow-lift);   /* the one shadow — it lifts from below */
  padding-block: var(--space-md);
}

/* If the page agent wraps the sill copy in .hero-inner, it still sits above
   the frame and inside the container rhythm. */
.window-seat .hero-inner {
  position: relative;
  z-index: 3;
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter);
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  text-align: left;
}

.ws-sill > .container,
.ws-sill > .hero-inner {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
}

.window-seat .hero-title {
  font-family: var(--font-display);
  font-size: var(--text-hero);
  line-height: 1.02;
  letter-spacing: -0.015em;
  color: var(--color-ink);
  max-width: 18ch;
}

.window-seat .hero-copy {
  font-size: var(--text-lg);
  line-height: 1.5;
  color: var(--color-muted);
  max-width: 42ch;
}

/* the altitude — 2,005 m. Tracked, centred-safe, teal-deep for small type. */
.ws-alt {
  display: inline-block;
  margin-right: calc(var(--track) * -1);
  align-self: flex-start;
  color: var(--color-accent-deep);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: var(--track);
  text-transform: uppercase;
  border-top: 2px solid var(--color-accent-deep);
  padding-top: .4rem;
}

.window-seat .hero-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-xs);
  margin-top: var(--space-xs);
}


/* ==========================================================================
   10. PAGE HERO — the quiet inner-page header (menu, about, visit, contact)
   ========================================================================== */

.hero {
  position: relative;
  padding-block: calc(var(--section-pad) * .7);
  border-bottom: var(--rule);
  background-color: var(--color-bg);
}

.hero-inner {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.hero-title {
  font-family: var(--font-display);
  font-size: var(--text-3xl);
  line-height: 1.05;
  color: var(--color-ink);
}

.hero-copy {
  margin-top: var(--space-sm);
  font-size: var(--text-lg);
  line-height: 1.55;
  color: var(--color-muted);
  max-width: 44ch;
}

.hero-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-xs);
  margin-top: var(--space-md);
}


/* ==========================================================================
   11. THE MILESTONE — the signature. One size system, everywhere it appears.
   ========================================================================== */

/* One size system, wherever the stone appears — divider, footer distances,
   contact map, /visit, 404. The SVG from milestone() carries NO presentation
   attributes, so every fill and stroke below is load-bearing: without them the
   browser's default fill:black paints the whole stone, cap, text and all, as
   one black block. viewBox is 0 0 160 196, so the font sizes here are user
   units and scale with the stone. */
.milestone {
  display: block;
  flex: none;
  width: clamp(78px, 10vw, 108px);
  height: auto;
  overflow: visible;
}

.milestone-body { fill: var(--color-surface); }   /* the white lower stone */
.milestone-cap  { fill: var(--color-ink); }       /* the deodar-ink rounded cap */

/* Every stroke below carries vector-effect="non-scaling-stroke" in the markup,
   so stroke-width stays at 1 and holds its weight at 78px and at 108px alike. */
.milestone-edge,
.milestone-seam,
.milestone-cap-rule,
.milestone-ground {
  fill: none;
  stroke-width: 1;
}

.milestone-edge   { stroke: var(--color-ink); }
.milestone-seam   { stroke: var(--color-ink); }
.milestone-cap-rule { stroke: var(--color-surface); opacity: .55; }
.milestone-ground { stroke: var(--color-border); }

/* stencilled place name — body face, caps, tracked like a painted sign */
.milestone-place {
  fill: var(--color-ink);
  font-family: var(--font-body);
  font-size: 16px;
  font-weight: 600;
  letter-spacing: .6px;
}

/* the distance — the display face, so the numeral reads as the trail sign it is */
.milestone-km {
  fill: var(--color-accent-deep);
  font-family: var(--font-display);
  font-size: 20px;
  letter-spacing: .4px;
}

/* --- the bare divider: one stone, a road line either side ---------------- */
/* Scoped away from .section, because footer.php uses `section.section
   milestone-row` as a full distances SECTION with a heading and a grid inside.
   Flexing that one into a row between two hairlines would crush it. */
.milestone-row:not(.section) {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: var(--space-md);
  padding-block: var(--space-lg);
}

/* the road either side of the stone */
.milestone-row:not(.section)::before,
.milestone-row:not(.section)::after {
  content: "";
  flex: 1 1 2rem;
  max-width: 14rem;
  height: 1px;
  background-color: var(--color-border);
}

/* --- the captioned signpost: stone + its note, on /visit, /contact, 404 --- */
.milestone-list {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-md);
}

.milestone-item,
.section.milestone-row .grid > li {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: center;
  gap: var(--space-sm);
}

.milestone-item p,
.section.milestone-row .grid > li p {
  color: var(--color-muted);
  font-size: var(--text-sm);
  line-height: 1.5;
}

/* the note beside a stone is prose, not a tracked label */
.section.milestone-row .grid > li .card-meta {
  margin-right: 0;
  font-size: var(--text-sm);
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
}


/* ==========================================================================
   12. CARDS
   ========================================================================== */

.card {
  display: flex;
  flex-direction: column;
  background-color: var(--color-surface);
  border: var(--rule);
  border-radius: var(--radius-md);   /* 0px — square */
  overflow: hidden;
}

.card-media {
  position: relative;
  background-color: var(--color-well);
  border-radius: var(--radius-media);  /* 8px — media is the ONLY rounded thing */
  overflow: hidden;
  margin: var(--space-xs);
}

.card-media img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
}

.card-body {
  display: flex;
  flex-direction: column;
  gap: .4rem;
  padding: var(--space-sm) var(--space-sm) var(--space-md);
}

.card-title {
  font-family: var(--font-display);
  font-size: var(--text-lg);
  line-height: 1.15;
  color: var(--color-ink);
}

.card-meta {
  display: inline-block;
  margin-right: calc(var(--track) * -1);
  color: var(--color-muted);
}

.card p { color: var(--color-muted); font-size: var(--text-sm); }

a.card:hover,
.card:hover { border-color: var(--color-accent); }


/* ==========================================================================
   13. THE BOARD — today's board / the menu
   ========================================================================== */

/* the chip row of anchors to the four groups, in the /menu hero */
.board-jump {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-xs);
  margin-top: var(--space-md);
}

.board {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-md);
}

/* ONE grid serving both boards.
     menu.php  — [figure.board-media?] span.board-name span.board-price
     home.php  — div.card-media h3.card-title p.card-meta p(note)
   Two columns: the name takes the first, the price sits hard right on the same
   baseline, and anything wide (the photo, the note) spans both. That is the
   chalkboard line the whole page is named after. */
.board-item {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: baseline;
  column-gap: var(--space-sm);
  row-gap: .35rem;
  padding-bottom: var(--space-sm);
  border-bottom: 1px dotted var(--color-border);
}

.board-item > .board-media,
.board-item > .card-media,
.board-item > p:not(.card-meta) {
  grid-column: 1 / -1;
}

.board-item > .board-media,
.board-item > .card-media {
  align-self: start;
  margin: 0 0 .35rem;
}

/* the photograph inside a board item — square, so a wall of them reads evenly */
.board-media {
  background-color: var(--color-well);
  border-radius: var(--radius-media);
  overflow: hidden;
}

.board-media img,
.board-item > .card-media img {
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
}

.board-name,
.board-item h3,
.board-item .card-title {
  font-family: var(--font-display);
  font-size: var(--text-lg);
  line-height: 1.15;
  color: var(--color-ink);
  text-wrap: balance;
}

.board-price,
.board-item .card-meta {
  justify-self: end;
  color: var(--color-accent-deep);
  font-family: var(--font-body);
  font-size: var(--text-base);
  font-weight: 600;
  letter-spacing: 0;
  text-transform: none;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  margin-right: 0;
}

.board-item > p:not(.card-meta) {
  color: var(--color-muted);
  font-size: var(--text-sm);
}


/* ==========================================================================
   14. THE WALK — a horizontal strip of photos with distances
   ========================================================================== */

.walk-strip {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 78%;
  gap: var(--space-sm);
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
  padding-bottom: var(--space-sm);
  scrollbar-width: thin;
  scrollbar-color: var(--color-well) transparent;
}

.walk-strip::-webkit-scrollbar { height: 6px; }
.walk-strip::-webkit-scrollbar-track { background: transparent; }
.walk-strip::-webkit-scrollbar-thumb { background: var(--color-well); }

.walk-item {
  scroll-snap-align: start;
  display: flex;
  flex-direction: column;
  gap: .6rem;
}

.walk-item img {
  width: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  background-color: var(--color-well);
  border-radius: var(--radius-media);
}

.walk-item h3,
.walk-item .card-title {
  font-family: var(--font-display);
  font-size: var(--text-base);
  line-height: 1.2;
}

.walk-item p { color: var(--color-muted); font-size: var(--text-sm); }

/* the distance, set like a trail sign */
.walk-item .card-meta {
  color: var(--color-accent-deep);
  font-variant-numeric: tabular-nums;
}


/* ==========================================================================
   15. THE ROOM — interior + exterior split
   ========================================================================== */

.room-split {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-md);
  align-items: center;
}

.room-split img {
  width: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  background-color: var(--color-well);
  border-radius: var(--radius-media);
}

.room-split figure { display: flex; flex-direction: column; gap: .6rem; }

.room-split figcaption {
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: var(--track);
  text-transform: uppercase;
  color: var(--color-muted);
}


/* ==========================================================================
   16. VISIT BLOCK — hours, address, map
   ========================================================================== */

.visit-block {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-md);
  padding: var(--space-md);
  background-color: var(--color-surface);
  border: var(--rule);
  border-radius: var(--radius-md);   /* 0px */
}

.visit-block h2,
.visit-block h3 { font-family: var(--font-display); }

.visit-block dl {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: .35rem var(--space-sm);
  align-items: baseline;
}

.visit-block dt {
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: var(--track);
  text-transform: uppercase;
  color: var(--color-muted);
}

.visit-block dd { color: var(--color-ink); }

.visit-block iframe,
.visit-block img {
  width: 100%;
  min-height: 15rem;
  border: 0;
  background-color: var(--color-well);
  border-radius: var(--radius-media);
}

/* the button row inside a .visit-block (and standalone on /visit) */
.visit-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-xs);
  margin-top: var(--space-sm);
}

/* the map frame — home, /visit and /contact. Media, so it takes the 8px. */
.visit-map {
  display: block;
  width: 100%;
  aspect-ratio: 4 / 3;
  min-height: 17rem;
  border: 0;
  background-color: var(--color-well);
  border-radius: var(--radius-media);
}


/* ==========================================================================
   17. FORMS
   ========================================================================== */

.form {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  max-width: 40rem;
}

.field {
  display: flex;
  flex-direction: column;
  gap: .4rem;
}

.field-label {
  display: inline-block;
  margin-right: calc(var(--track) * -1);
  align-self: flex-start;
  color: var(--color-ink);
}

.field-input {
  width: 100%;
  min-height: var(--tap);
  padding: .75rem .85rem;
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);   /* 0px */
  color: var(--color-ink);
  font-size: var(--text-base);
  font-family: var(--font-body);
}

textarea.field-input {
  min-height: 9rem;
  resize: vertical;
  line-height: 1.55;
}

select.field-input {
  appearance: none;
  padding-right: 2.25rem;
  background-image:
    linear-gradient(45deg, transparent 50%, var(--color-ink) 50%),
    linear-gradient(135deg, var(--color-ink) 50%, transparent 50%);
  background-size: 6px 6px, 6px 6px;
  background-position: right 1.05rem center, right .75rem center;
  background-repeat: no-repeat;
}

.field-input::placeholder { color: var(--color-muted); opacity: .75; }

.field-input:hover { border-color: var(--color-muted); }

.field-input:focus {
  border-color: var(--color-accent-deep);
  outline: 2px solid var(--color-accent-deep);
  outline-offset: 1px;
}

.field-input[aria-invalid="true"] {
  border-color: var(--color-ink);
  border-width: 2px;
}

/* Error text stays ink + bold + a marker glyph. Rust is reserved for the
   status chip and is barred from body copy, so errors are signalled by weight
   and a symbol, not by colour alone — which is the accessible way regardless. */
.field-error {
  display: flex;
  align-items: baseline;
  gap: .35rem;
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--color-ink);
}

.field-error::before {
  content: "\25B2";      /* U+25B2 black up-pointing triangle */
  font-size: .7em;
  line-height: 1;
  color: var(--color-ink);
}

.field-error:empty { display: none; }

.form-note {
  font-size: var(--text-sm);
  color: var(--color-muted);
  max-width: 44ch;
}

/* THE HONEYPOT WRAPPER — contact.php holds a real <input name="musafir_web">
   in here and contact-handler.php discards any submission that fills it.

   Deliberately NOT display:none and NOT visibility:hidden: plenty of spam bots
   skip fields hidden those two ways, and a trap a bot can detect is not a trap.
   It is moved off-canvas instead, which bots fill and people never see.

   Deliberately NOT .sr-only either — .sr-only text is meant to be READ by a
   screen reader, and this must not be. The markup already carries
   aria-hidden="true" on the wrapper and tabindex="-1" on the input, so it is
   out of the a11y tree and out of the tab order; the rules below make sure a
   keyboard user can never be scrolled to it even if something does focus it. */
.form-hp {
  position: absolute;
  left: -9999px;
  top: auto;
  width: 1px;
  height: 1px;
  overflow: hidden;
  opacity: 0;
  pointer-events: none;
}

.form input[type="hidden"] { display: none; }


/* ==========================================================================
   18. ALERTS
   ========================================================================== */

/* NO SIDE-TAB. An accent bar down one edge would be a second decorative
   system competing with The Milestone, and it is a tell this repo has already
   had to remove once (Studio Chaukhat — see design-ledger.md). Alerts signal
   the way .field-error does: a marker glyph plus weight, inside the same
   hairline rule as every other panel. The glyph SHAPES differ, so the state is
   never carried by colour alone. */
.alert {
  display: flex;
  align-items: baseline;
  gap: .5rem;
  padding: var(--space-sm);
  background-color: var(--color-surface);
  border: var(--rule);
  border-radius: var(--radius-md);   /* 0px */
  color: var(--color-ink);
  font-size: var(--text-sm);
}

.alert::before {
  flex: none;
  font-size: .7em;
  line-height: 1;
}

.alert-ok::before  { content: "\25CF"; color: var(--color-accent); }  /* ● filled circle */

.alert-err::before { content: "\25B2"; color: var(--color-ink); }     /* ▲ triangle, as .field-error */
.alert-err         { font-weight: 500; }


/* ==========================================================================
   19. SITE FOOTER
   ========================================================================== */

.site-footer {
  background-color: var(--color-ink);
  color: var(--color-bg);
  padding-block: var(--section-pad) var(--space-lg);
}

.site-footer a { color: var(--color-bg); }

.site-footer a:hover { color: var(--color-surface); text-decoration: underline; }

.site-footer p,
.site-footer li,
.site-footer address { color: rgba(230,233,230,.78); }

.site-footer .grid { gap: var(--space-md); }

.footer-col {
  display: flex;
  flex-direction: column;
  gap: .5rem;
}

.footer-title {
  display: inline-block;
  margin-right: calc(var(--track) * -1);
  align-self: flex-start;
  margin-bottom: .3rem;
  color: rgba(230,233,230,.62);
}

/* the identity column — wordmark, what we are, the altitude chip */
.footer-brand { gap: .4rem; }

.footer-links {
  display: flex;
  flex-direction: column;
  gap: .35rem;
}

.footer-address { line-height: 1.55; }

.footer-hours { font-size: var(--text-sm); }

/* the bottom bar — copyright and the studio credit */
.footer-base {
  margin-top: var(--space-lg);
  padding-top: var(--space-md);
  border-top: 1px solid rgba(230,233,230,.18);
}

.footer-base .container {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: .35rem var(--space-md);
}

.footer-legal,
.footer-credit {
  font-size: var(--text-xs);
  color: rgba(230,233,230,.62);
}

.site-footer hr { border-top-color: rgba(230,233,230,.18); margin-block: var(--space-md); }

.site-footer .chip {
  background-color: transparent;
  border-color: rgba(230,233,230,.28);
  color: rgba(230,233,230,.78);
}

/* On the ink ground neither the teal nor the rust clears contrast, and no
   off-palette hex is permitted here — so the chip runs on the mist and the
   label text ("Open now" / "Closed") carries the state, which is the
   accessible way to signal it in any case. */
.site-footer .status-chip { color: var(--color-bg); }


/* ==========================================================================
   20. STICKY MOBILE BAR — call + WhatsApp. Designed at 360px first.
       RESPONSIVE AGENT: hide this AND zero body{padding-bottom} at 768.
   ========================================================================== */

.mobile-bar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 60;
  display: grid;
  grid-template-columns: 1fr 1fr;
  min-height: var(--bar-h);
  background-color: var(--color-surface);
  border-top: 1px solid var(--color-border);
  box-shadow: var(--shadow-lift);    /* the one shadow — inverted, from below */
  padding-bottom: env(safe-area-inset-bottom, 0px);
}

/* Each action stacks a tracked label over its value, so at 360px the two read
   as two things and not as one run-on line. */
.mobile-bar-item,
.mobile-bar a,
.mobile-bar button {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: .1rem;
  min-height: var(--bar-h);
  padding: .5rem;
  color: var(--color-ink);
  text-align: center;
}

/* centred + tracked, so the trailing letter-space is cancelled the house way:
   inline-block plus a negative margin-right. Never text-indent. */
.mobile-bar-label {
  display: inline-block;
  margin-right: calc(var(--track) * -1);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: var(--track);
  text-transform: uppercase;
  line-height: 1.2;
}

.mobile-bar-value {
  font-size: var(--text-sm);
  font-weight: 600;
  line-height: 1.2;
  white-space: nowrap;
}

.mobile-bar > * + * { border-left: 1px solid var(--color-border); }

.mobile-bar a:last-child {
  background-color: var(--color-accent);
  color: var(--color-surface);
}

.mobile-bar a:last-child:hover { background-color: var(--color-accent-deep); }

.mobile-bar svg { width: 1.1rem; height: 1.1rem; flex: none; }


/* ==========================================================================
   21. SECTION GROUNDS + PER-PAGE HOOKS
   ========================================================================== */

.section.is-surface { background-color: var(--color-surface); }
.section.is-well    { background-color: var(--color-well); }

/* a plain full-width photo band, used between sections */
.section figure img {
  width: 100%;
  object-fit: cover;
  background-color: var(--color-well);
  border-radius: var(--radius-media);
}

/* header.php puts page-home | page-menu | page-about | page-visit |
   page-contact | page-404 | page-500 on <body>. Only the pair that earns a
   rule carries one — the error pages are short, so their section rhythm is
   tightened rather than leaving a screen of empty mist above the footer. The
   rest exist as hooks and are deliberately not shipped as empty selectors. */
.page-404,
.page-500 {
  --section-pad: clamp(2.5rem, 7vw, 4.5rem);
}

/* NOTE: this file contains ZERO media queries by contract — including @media
   print. If a print stylesheet is wanted for the menu board, it belongs in
   responsive.css, which is the only file permitted to open a media block. */
