/* =====================================================================
   COMMUNITY FARM — 360° AERIAL TOUR
   =====================================================================
   Carried over from the SG Villa tour stylesheet. The layout, spacing and
   type scale are unchanged; the accent is the only token that moved.

   --accent was --gold (#C6A87C) on SG Villa. It is a warmer saffron here,
   which holds up better against the monsoon greens these panoramas are full
   of than the cooler stone gold did. It is the ONLY colour token used for
   emphasis —
   the rail marker, the bearing index, the hotspot rings, the primary button
   and every focus ring all read from it, so changing this one line
   re-accents the whole tour. Nothing else needs editing.

   Stacking: pano 0 · rail/bearing 15 · hotspot panel 18 · loading 22
             · header 30 · grain 45 · menu 60 · portrait hint 80
   ===================================================================== */

:root {
  --ink:    #000000;
  --paper:  #EDEDE8;
  --muted:  #8E948C;
  --accent: #E0A353;
  --line:   rgba(237,237,232,.12);
  --line-2: rgba(237,237,232,.22);
  --panel:  rgba(0,0,0,.82);

  --display: 'Fraunces', Georgia, serif;
  --body:    'Instrument Sans', system-ui, sans-serif;
  --mono:    'JetBrains Mono', ui-monospace, monospace;
  --ease:    cubic-bezier(.22,.61,.36,1);
}

* { box-sizing: border-box; margin: 0; padding: 0; }

html, body {
  width: 100%; height: 100%;
  overflow: hidden;
  font-family: var(--body);
  color: var(--paper);
  background: var(--ink);
  -webkit-font-smoothing: antialiased;
  overscroll-behavior: none;
}
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
a { color: inherit; text-decoration: none; }
:focus-visible { outline: 1px solid var(--accent); outline-offset: 3px; }

/* film grain — the same overlay as the microsite */
.grain {
  position: fixed; inset: -50%; z-index: 45;
  pointer-events: none; opacity: .03; mix-blend-mode: screen;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='4'/%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* ---------- level container ---------- */
.level {
  position: fixed; inset: 0;
  opacity: 0; visibility: hidden;
  transform: translateY(12px);
  transition: opacity .8s var(--ease), transform .8s var(--ease), visibility .8s;
  z-index: 1;
  background: var(--ink);
}
.level--active { opacity: 1; visibility: visible; transform: none; z-index: 2; }

/* =====================================================================
   SHARED — header, brand, controls
   ===================================================================== */
.site-head {
  position: absolute; top: 0; left: 0; right: 0; z-index: 30;
  display: flex; align-items: center; justify-content: space-between;
  gap: clamp(12px,3vw,28px);
  padding: clamp(16px,3vh,26px) clamp(16px,4vw,48px);
  padding-top: max(clamp(16px,3vh,26px), env(safe-area-inset-top));
}

.brand { line-height: 1; }
.brand__logo { width: auto; height: 54px; display: block; }
.viewer__head .brand__logo { height: 40px; }
/* text lockup, shown only if the logo file fails to load */
.brand__top  { font-family: var(--mono); font-size: 8.5px; letter-spacing: .26em; color: var(--accent); text-transform: uppercase; }
.brand__main { font-family: var(--display); font-weight: 300; font-size: 24px; letter-spacing: -.02em; margin-top: 5px; }
.brand__sub  { font-family: var(--mono); font-size: 8.5px; letter-spacing: .26em; color: var(--muted); margin-top: 5px; }

.hamburger {
  width: 26px; height: 14px;
  display: inline-flex; flex-direction: column; justify-content: space-between;
  flex-shrink: 0;
}
.hamburger span { height: 1px; width: 100%; background: var(--paper); transition: background .3s var(--ease); }
.hamburger:hover span { background: var(--accent); }

.eyebrow {
  font-family: var(--mono); font-size: 9.5px; letter-spacing: .26em;
  text-transform: uppercase; color: var(--accent);
}

/* Outlined rather than a solid accent slab: over a photograph a filled
   block reads as a banner, and the hero is now centred on the image rather
   than sitting in a dark corner of it. It fills on hover. */
.btn-primary {
  display: inline-flex; align-items: center; gap: 1.1em;
  margin-top: clamp(1.6rem,4vh,2.4rem);
  padding: 1.05rem 2.2rem;
  font-family: var(--mono); font-size: 11px; letter-spacing: .22em; text-transform: uppercase;
  border: 1px solid rgba(237,237,232,.5); background: transparent; color: var(--paper);
  backdrop-filter: blur(2px);
  transition: background .3s var(--ease), color .3s var(--ease),
              border-color .3s var(--ease);
}
.btn-primary:hover {
  background: var(--accent); border-color: var(--accent); color: var(--ink);
}
.btn-primary__arw {
  font-style: normal; transition: transform .3s var(--ease);
}
.btn-primary:hover .btn-primary__arw { transform: translateX(4px); }

/* =====================================================================
   LEVEL 1 — HERO
   ===================================================================== */
.hero__media {
  position: absolute; inset: 0; z-index: 0;
  background-size: cover; background-position: center;
  transform: scale(1.06);
  animation: heroDrift 30s ease-in-out infinite alternate;
}
@keyframes heroDrift {
  from { transform: scale(1.06) translateX(-1.2%); }
  to   { transform: scale(1.12) translateX(1.2%); }
}
/* Centred composition, so the scrim is a vignette rather than the old
   bottom-left wash: even top and bottom, and no side bias. */
.hero__scrim {
  position: absolute; inset: 0; z-index: 1;
  background:
    linear-gradient(180deg, rgba(0,0,0,.55) 0%, rgba(0,0,0,.18) 34%, rgba(0,0,0,.30) 62%, rgba(0,0,0,.88) 100%),
    radial-gradient(ellipse at 50% 45%, rgba(0,0,0,.42) 0%, rgba(0,0,0,.62) 100%);
}
.hero__content {
  position: absolute; inset: 0; z-index: 10;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  gap: 0; text-align: center;
  padding: clamp(4.5rem,12vh,7rem) clamp(18px,5vw,48px) clamp(5rem,13vh,7rem);
  overflow-y: auto;
}

/* The hero wordmark is hidden: the headline below IS the name now. The
   rules stay so that un-hiding it in index.html gives a correctly scaled
   lockup again — for a logo, say, once one exists. */
.hero__brand { margin-bottom: clamp(1.4rem,4vh,2.6rem); }
.hero__brand .brand__main {
  font-size: clamp(1.5rem,4.4vw,2.6rem); letter-spacing: .10em;
}
.hero__brand .brand__top { font-size: 9.5px; letter-spacing: .32em; }
.hero__brand .brand__sub { letter-spacing: .3em; }
.hero__brand .brand__logo { max-height: clamp(56px,9vh,104px); width: auto; }

/* The line the mark cannot say — what this is, in one breath. */
.hero__kicker {
  font-family: var(--mono); font-size: clamp(9px,1.1vw,10.5px);
  letter-spacing: .3em; text-transform: uppercase;
  color: var(--muted); margin-bottom: clamp(.9rem,2.4vh,1.5rem);
}
/* Set in the accent rather than paper. It is a mid-tone over a photograph,
   so it carries a soft dark shadow — the scrim alone is not enough against
   a bright patch of sky, and the name is the one thing that must never be
   hard to read. */
.hero__title {
  font-family: var(--display); font-weight: 300;
  font-size: clamp(2.5rem,6.4vw,5.2rem); line-height: 1.04;
  letter-spacing: -.02em; margin: 0;
  text-wrap: balance;
  color: var(--accent);
  text-shadow: 0 2px 26px rgba(0,0,0,.55), 0 1px 3px rgba(0,0,0,.4);
}
.hero__title .ln { display: block; }
.hero__desc {
  color: var(--paper); opacity: .82; line-height: 1.75;
  font-size: clamp(14px,1.25vw,16px);
  max-width: 54ch; margin: clamp(1.1rem,3vh,1.8rem) auto 0;
}

/* Facts sit under the button as a quiet footnote — they are evidence, not
   the pitch, so they no longer share the headline's weight. */
.facts {
  display: flex; flex-wrap: wrap; justify-content: center;
  gap: clamp(1rem,3vw,2.2rem);
  border-top: 1px solid var(--line);
  padding-top: 1rem; margin-top: clamp(1.6rem,4vh,2.6rem);
  font-family: var(--mono); font-size: 9.5px; letter-spacing: .18em;
  text-transform: uppercase; color: var(--muted);
  max-width: 640px;
}
.facts div { display: flex; gap: .55em; }
.facts dd { color: var(--paper); }

/* Hidden. It sat at the bottom of the viewport and the centred hero's facts
   row now occupies that space — the two overlapped. It is also redundant
   beside an explicit ENTER button, which is the same action. The element
   stays in the DOM because tour.js binds its click handler unconditionally;
   deleting `display:none` brings it back. */
.scroll-hint { display: none; }
.scroll-hint--shown {
  position: absolute; z-index: 10; left: 50%; transform: translateX(-50%);
  bottom: clamp(1.1rem,3vh,2rem);
  display: flex; flex-direction: column; align-items: center; gap: .55rem;
  font-family: var(--mono); font-size: 9px; letter-spacing: .24em; color: var(--muted);
  opacity: .9; cursor: pointer;
}
.scroll-hint__arw {
  width: 1px; height: 20px;
  background: linear-gradient(180deg, var(--accent), transparent);
  animation: drop 2s ease-in-out infinite;
}
@keyframes drop {
  0%   { transform: scaleY(.25); transform-origin: top; }
  55%  { transform: scaleY(1);   transform-origin: top; }
  100% { transform: scaleY(.25); transform-origin: bottom; }
}

/* =====================================================================
   LEVEL 2 — CHOOSER
   ===================================================================== */
.chooser { overflow-y: auto; }
.chooser__inner {
  position: relative; z-index: 5; min-height: 100%;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center; padding: 150px 24px 60px;
}
.chooser__title {
  font-family: var(--display); font-weight: 300;
  font-size: clamp(2rem,5vw,3.6rem); letter-spacing: -.028em; margin-top: 1rem;
}
.chooser__sub { color: var(--muted); font-size: 15px; margin-top: .8rem; }
.cards { display: flex; gap: 1.1rem; margin-top: 3.2rem; flex-wrap: wrap; justify-content: center; }
.card {
  width: 320px; text-align: left;
  border: 1px solid var(--line); background: var(--ink);
  transition: border-color .4s var(--ease);
}
.card:hover { border-color: var(--line-2); }
.card__thumb {
  width: 100%; aspect-ratio: 16/7;
  background-size: cover; background-position: center;
  opacity: .78; transition: opacity .4s var(--ease);
}
.card:hover .card__thumb { opacity: 1; }
.card__body {
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
  padding: 12px 14px; border-top: 1px solid var(--line);
}
.card__title { font-family: var(--mono); font-size: 9.5px; font-weight: 500; letter-spacing: .2em; }
.card__count { font-family: var(--mono); font-size: 9px; letter-spacing: .12em; color: var(--muted); white-space: nowrap; }
.card__desc { padding: 0 14px 16px; font-size: 13.5px; line-height: 1.6; color: var(--muted); }

/* =====================================================================
   LEVEL 3 — VIEWER
   ===================================================================== */
.viewer__pano { position: absolute; inset: 0; z-index: 0; background: var(--ink); }

.viewer__head {
  background: linear-gradient(180deg, rgba(0,0,0,.78), transparent);
  padding-bottom: clamp(20px,4vh,34px);
}
/* Back to the site — always visible in the viewer bar, so the tour is never a
   dead end for someone who arrived from the homepage. */
.viewer__back {
  font-family: var(--mono); font-size: 9px; letter-spacing: .22em;
  color: var(--muted); white-space: nowrap; flex-shrink: 0;
  border: 1px solid var(--line); padding: 8px 10px;
  transition: color .3s var(--ease), border-color .3s var(--ease);
}
.viewer__back:hover { color: var(--accent); border-color: var(--accent); }
@media (max-width: 600px) { .viewer__back b { display: none; } }

.viewer__title { display: flex; flex-direction: column; gap: 5px; min-width: 0; flex: 1; }
.viewer__title strong {
  font-family: var(--mono); font-size: clamp(10px,2vw,11.5px); font-weight: 500;
  letter-spacing: .22em; text-transform: uppercase;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.viewer__title span {
  font-family: var(--mono); font-size: 9px; letter-spacing: .16em;
  color: var(--muted); white-space: nowrap;
}
.viewer__head-right { display: flex; align-items: center; gap: clamp(10px,2vw,20px); flex-shrink: 0; }

/* destination toggles — hidden while there is only one */
.view-switch { display: flex; gap: 1px; background: var(--line); border: 1px solid var(--line); }
.view-switch__btn {
  padding: 0 12px; height: 30px;
  display: grid; place-items: center;
  font-family: var(--mono); font-size: 9px; letter-spacing: .18em; text-transform: uppercase;
  background: rgba(0,0,0,.72); color: var(--muted);
  transition: color .3s var(--ease);
}
.view-switch__btn:hover { color: var(--paper); }
.view-switch__btn--active { color: var(--accent); }

.deg-badge, .menu-text {
  font-family: var(--mono); font-size: 9px; letter-spacing: .18em; text-transform: uppercase;
  color: var(--muted); transition: color .3s var(--ease);
  white-space: nowrap;
}
.deg-badge { border: 1px solid var(--line); padding: 0 12px; height: 30px; }
.deg-badge:hover, .menu-text:hover { color: var(--accent); }

/* ---- the views (left) ----
   Still ordered by height, highest first — 132 → 55 → 15 → 12 m is what
   sets the sequence. The metres themselves are no longer drawn: the four
   views earned names, and a name beats a number the moment there is one.
   The height survives in each stop's tooltip. */
.rail {
  position: absolute; left: clamp(14px,3vw,34px); top: 50%;
  transform: translateY(-50%); z-index: 15;
}
.rail__label {
  font-family: var(--mono); font-size: 8.5px; letter-spacing: .26em;
  text-transform: uppercase; color: var(--accent);
  padding-bottom: 12px; margin-bottom: 4px; border-bottom: 1px solid var(--line);
}
.rail__list { display: flex; flex-direction: column; }
.rail__stop {
  position: relative; display: flex; align-items: center;
  padding: 13px 0 13px 16px; text-align: left;
  border-left: 1px solid var(--line);
  transition: border-color .4s var(--ease);
}
/* tick on the axis */
.rail__stop::before {
  content: ""; position: absolute; left: 0; top: 50%;
  width: 7px; height: 1px; background: var(--line-2);
  transition: width .4s var(--ease), background .4s var(--ease);
}
.rail__stop:hover::before { width: 11px; background: var(--paper); }
.rail__stop--active { border-left-color: var(--accent); }
.rail__stop--active::before { width: 11px; background: var(--accent); }
/* The name was a hover reveal behind the number. It is the whole control
   now, so it is always up, at the size the number used to be. */
.rail__name {
  font-family: var(--mono); font-size: 11px; font-weight: 500;
  letter-spacing: .2em; text-transform: uppercase;
  color: var(--muted); white-space: nowrap; line-height: 1;
  transition: color .4s var(--ease);
}
.rail__stop:hover .rail__name { color: var(--paper); }
.rail__stop--active .rail__name { color: var(--accent); }

/* ---- bearing tape (signature) ---- */
.bearing {
  position: absolute; z-index: 15; left: 50%; transform: translateX(-50%);
  bottom: max(22px, env(safe-area-inset-bottom));
  width: min(420px, 84vw); pointer-events: none; text-align: center;
}
.bearing[hidden] { display: none; }
.bearing__tape {
  position: relative; height: 26px; overflow: hidden;
  border-top: 1px solid var(--line); border-bottom: 1px solid var(--line);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 16%, #000 84%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 16%, #000 84%, transparent);
}
#tape-inner { position: absolute; top: 0; bottom: 0; left: 0; will-change: transform; }
#tape-inner .t { position: absolute; bottom: 0; width: 1px; background: var(--line-2); }
#tape-inner .t.minor { height: 5px; }
#tape-inner .t.major { height: 9px; background: rgba(237,237,232,.4); }
#tape-inner .c {
  position: absolute; top: 3px; transform: translateX(-50%);
  font-family: var(--mono); font-size: 9px; letter-spacing: .14em; color: var(--paper);
}
#tape-inner .n {
  position: absolute; top: 4px; transform: translateX(-50%);
  font-family: var(--mono); font-size: 8px; letter-spacing: .1em; color: var(--muted);
}
.bearing__index {
  position: absolute; left: 50%; top: 0; width: 1px; height: 26px;
  background: var(--accent); transform: translateX(-50%);
}
.bearing__readout {
  margin-top: 9px; display: flex; justify-content: center; gap: .7em;
  font-family: var(--mono); font-size: 9px; letter-spacing: .2em; color: var(--muted);
}
.bearing__readout span { color: var(--paper); }
.bearing__readout i { font-style: normal; opacity: .4; }

/* ---- hotspots: viewfinder reticles ----
   Pannellum gives each hotspot div `.pnlm-hotspot-base`, which sets
   position:absolute and writes an inline `transform` EVERY FRAME to place it.
   So: never set position or transform on .hs itself — position:relative would
   break placement outright, and any transform here is overwritten anyway.
   Anything that needs to move or pulse has to be a CHILD element.
   Pannellum centres the div using offsetWidth/offsetHeight, so .hs must keep a
   fixed 30x30 box. Its own stylesheet also forces content-box inside the
   container (`.pnlm-container *`, more specific than our `*`), hence the
   explicit box-sizing below so the reticle measures what it says. */
/* PER-CALLOUT SIZE — `--s`, set from a callout's `size` in config.js.
   Every dimension of the reticle is derived from it, so one number scales
   the corners, the pin, the halo and the label together instead of the
   parts drifting out of proportion.

   It changes the BOX, not a transform: Pannellum positions a hotspot by
   offsetting half its measured width and height, so a scaled box stays
   centred on its true yaw/pitch, while a transform: scale() would be
   overwritten by the transform Pannellum rewrites every frame. */
.hs {
  --s: var(--hs-scale, 1);
  width: calc(30px * var(--s)); height: calc(30px * var(--s));
  box-sizing: border-box;
}
.hs::before, .hs::after {
  content: ""; position: absolute;
  width: calc(12px * var(--s)); height: calc(12px * var(--s));
  box-sizing: border-box;
  border: calc(1.5px * var(--s)) solid var(--accent);
  filter: drop-shadow(0 0 5px rgba(198,168,124,.95));
  transition: top .4s var(--ease), left .4s var(--ease),
              right .4s var(--ease), bottom .4s var(--ease);
}
.hs::before { top: 0; left: 0; border-right: 0; border-bottom: 0; }
.hs::after  { bottom: 0; right: 0; border-left: 0; border-top: 0; }
.hs:hover::before { top: calc(-5px * var(--s)); left: calc(-5px * var(--s)); }
.hs:hover::after  { bottom: calc(-5px * var(--s)); right: calc(-5px * var(--s)); }

/* the lit centre */
.hs__pin {
  position: absolute; left: 50%; top: 50%;
  width: calc(4px * var(--s)); height: calc(4px * var(--s));
  margin: calc(-2px * var(--s)) 0 0 calc(-2px * var(--s));
  background: var(--accent);
  box-shadow: 0 0 8px 2px rgba(198,168,124,.95), 0 0 20px 6px rgba(198,168,124,.45);
}
/* a square halo rather than a ring — it reads as a viewfinder opening, and
   keeps the zero-radius rule the rest of the identity follows */
.hs__halo {
  position: absolute; left: 50%; top: 50%;
  width: calc(26px * var(--s)); height: calc(26px * var(--s));
  margin: calc(-13px * var(--s)) 0 0 calc(-13px * var(--s));
  box-sizing: border-box;
  border: 1px solid var(--accent);
  animation: hsPulse 2.8s var(--ease) infinite;
  pointer-events: none;
}
@keyframes hsPulse {
  0%   { transform: scale(.4);  opacity: 0; }
  30%  { opacity: .85; }
  100% { transform: scale(1.7); opacity: 0; }
}
.hs__lbl {
  position: absolute; left: 50%; top: calc(40px * var(--s));
  transform: translateX(-50%);
  box-sizing: border-box;
  font-family: var(--mono); font-size: calc(9px * var(--s));
  letter-spacing: .2em; text-transform: uppercase;
  white-space: nowrap; padding: 6px 11px;
  background: rgba(0,0,0,.72); border: 1px solid rgba(198,168,124,.45);
  color: var(--paper); text-shadow: 0 1px 8px rgba(0,0,0,.9);
  /* legible at rest, full strength on hover — 8 points at full opacity would
     fight each other for attention */
  opacity: .62;
  transition: opacity .35s var(--ease), border-color .35s var(--ease);
  pointer-events: none;
}
.hs:hover .hs__lbl, .hs--touch .hs__lbl { opacity: 1; border-color: var(--accent); }

/* ---- hotspot detail panel ---- */
.hs-panel {
  position: absolute; z-index: 18; left: 50%;
  transform: translate(-50%, 14px);
  bottom: calc(env(safe-area-inset-bottom, 0px) + 96px);
  width: min(420px, 92vw); padding: 22px 24px;
  background: var(--panel); backdrop-filter: blur(22px);
  border: 1px solid var(--line);
  opacity: 0; visibility: hidden;
  transition: opacity .45s var(--ease), transform .45s var(--ease), visibility .45s;
}
.hs-panel--open { opacity: 1; visibility: visible; transform: translate(-50%, 0); }
.hs-panel h3 {
  font-family: var(--mono); font-size: 9.5px; font-weight: 500; letter-spacing: .24em;
  text-transform: uppercase; color: var(--accent); margin-bottom: 12px; padding-right: 20px;
}
.hs-panel p { font-size: 14px; line-height: 1.72; color: var(--muted); max-width: 46ch; }
.hs-panel__close { position: absolute; top: 16px; right: 18px; font-size: 12px; color: var(--muted); }
.hs-panel__close:hover { color: var(--paper); }

/* ---- loading ---- */
.pano-loading { position: absolute; inset: 0; z-index: 22; pointer-events: none; opacity: 0; transition: opacity .3s; }
.pano-loading.on { opacity: 1; }
.pano-loading__bar {
  position: absolute; top: 0; left: 0; height: 1px; width: 0;
  background: var(--accent); animation: loadBar 2.4s var(--ease) infinite;
}
@keyframes loadBar { 0% { width: 0; } 70% { width: 82%; } 100% { width: 96%; } }
.pano-loading__chip {
  position: absolute; left: 50%; top: 96px; transform: translateX(-50%);
  font-family: var(--mono); font-size: 9px; letter-spacing: .22em; text-transform: uppercase;
  color: var(--muted); padding: 7px 14px;
  background: rgba(0,0,0,.78); border: 1px solid var(--line);
}
/* full-veil grade, first entry only: the screen is genuinely empty */
.pano-loading--full { background: var(--ink); }

/* hide Pannellum's own UI */
.pnlm-controls-container, .pnlm-panorama-info, .pnlm-load-box { display: none !important; }
.pnlm-container { background: var(--ink) !important; }

/* =====================================================================
   MENU
   ===================================================================== */
.menu-panel {
  position: fixed; top: 0; right: 0; bottom: 0; z-index: 60;
  width: min(360px, 88vw); padding: 24px;
  background: var(--panel); backdrop-filter: blur(22px);
  border-left: 1px solid var(--line);
  transform: translateX(100%);
  transition: transform .6s var(--ease);
  display: flex; flex-direction: column;
  overflow-y: auto;
}
.menu-panel--open { transform: none; }
.menu-panel__close {
  align-self: flex-end; font-size: 13px; color: var(--muted);
  padding-top: max(6px, env(safe-area-inset-top));
}
.menu-panel__close:hover { color: var(--paper); }
.menu-panel__nav { display: flex; flex-direction: column; margin-top: 1.6rem; }
.menu-panel__nav a {
  font-family: var(--display); font-weight: 300; font-size: 1.5rem; letter-spacing: -.02em;
  padding: 16px 0; border-bottom: 1px solid var(--line);
  transition: color .3s var(--ease), padding-left .3s var(--ease);
}
.menu-panel__nav a:hover { color: var(--accent); padding-left: 8px; }
.menu-panel__nav a.is-disabled { opacity: .35; pointer-events: none; }
.menu-panel__build { color: var(--accent); opacity: .85; }
.menu-panel__foot {
  margin-top: auto; padding-top: 2rem;
  font-family: var(--mono); font-size: 8.5px; line-height: 2; letter-spacing: .1em;
  color: var(--muted); opacity: .6;
}

/* =====================================================================
   BOOT DIAGNOSTIC
   =====================================================================
   A black screen with working chrome is the worst possible failure: it
   looks like a design problem rather than a serving problem. This panel
   makes the real cause explicit. */
.boot-error { position: fixed; inset: 0; z-index: 90; display: none; background: var(--ink); }
.boot-error.show { display: grid; place-items: center; padding: 32px; }
.boot-error__inner { max-width: 560px; }
.boot-error h2 {
  font-family: var(--display); font-weight: 300;
  font-size: clamp(1.6rem, 4vw, 2.4rem); letter-spacing: -.024em;
  line-height: 1.14; margin: .8rem 0 0;
}
.boot-error p { color: var(--muted); line-height: 1.72; font-size: 15px; margin-top: 1.1rem; max-width: 52ch; }
.boot-error pre {
  font-family: var(--mono); font-size: 11px; line-height: 2; letter-spacing: .04em;
  color: var(--paper); background: rgba(237,237,232,.05);
  border: 1px solid var(--line); border-left: 1px solid var(--accent);
  padding: 14px 16px; margin-top: 1.4rem; white-space: pre-wrap; word-break: break-all;
}
#boot-dismiss {
  margin-top: 1.8rem; padding: .95rem 1.8rem;
  font-family: var(--mono); font-size: 10px; letter-spacing: .16em; text-transform: uppercase;
  border: 1px solid var(--line); color: var(--muted);
  transition: border-color .3s var(--ease), color .3s var(--ease);
}
#boot-dismiss:hover { border-color: var(--paper); color: var(--paper); }

/* ---- link callouts ----
   A callout carrying `goto` moves you to another panorama, so it has to
   look like a way through rather than a label. Same reticle, but the pin
   becomes a ring with a chevron and the whole mark pulses gently — the
   convention every virtual tour uses for "stand here next". */
.hs--link .hs__pin {
  width: calc(15px * var(--s)); height: calc(15px * var(--s));
  margin: calc(-7.5px * var(--s)) 0 0 calc(-7.5px * var(--s));
  border-radius: 50%; background: transparent;
  border: calc(1.5px * var(--s)) solid var(--accent);
  box-shadow: 0 0 0 calc(3px * var(--s)) rgba(0,0,0,.35);
}
.hs--link .hs__pin::after {
  content: ""; position: absolute; left: 50%; top: 50%;
  width: calc(5px * var(--s)); height: calc(5px * var(--s));
  margin: calc(-3.5px * var(--s)) 0 0 calc(-2.5px * var(--s));
  border-right: calc(1.5px * var(--s)) solid var(--accent);
  border-bottom: calc(1.5px * var(--s)) solid var(--accent);
  transform: rotate(-45deg);
}
.hs--link .hs__halo { animation: linkPulse 2.6s var(--ease) infinite; }
@keyframes linkPulse {
  0%   { transform: scale(.7); opacity: .55; }
  70%  { transform: scale(1.5); opacity: 0; }
  100% { transform: scale(1.5); opacity: 0; }
}
.hs--link:hover .hs__pin { background: var(--accent); }
.hs--link:hover .hs__pin::after { border-color: var(--ink); }
@media (prefers-reduced-motion: reduce) {
  .hs--link .hs__halo { animation: none; opacity: .4; }
}

/* =====================================================================
   PLOT OUTLINES — js/plots.js
   =====================================================================
   An SVG laid over the panorama, re-projected every frame. It must sit
   ABOVE the canvas and BELOW the hotspots, or a plot covering a callout
   would swallow its clicks — hence the z-index pair here. Pannellum
   positions .pnlm-hotspot-base absolutely, so giving it a z-index works.

   The layer itself takes no pointer events; only the polygons do. Anything
   else would stop the visitor dragging the panorama. */
.plot-layer {
  position: absolute; inset: 0; z-index: 2;
  pointer-events: none; overflow: visible;
}
.pnlm-hotspot-base { z-index: 3; }

.plot-poly {
  pointer-events: auto; cursor: pointer;
  fill: var(--accent); fill-opacity: .10;
  stroke: var(--accent); stroke-width: 2;
  stroke-linejoin: round; vector-effect: non-scaling-stroke;
  transition: fill-opacity .25s var(--ease);
}
.plot-poly--hover { fill-opacity: .26; }
/* Nothing opens on click, so it does not claim to be a button. It still
   lights on hover, which is how you tell one plot from its neighbour. */
.plot-poly--static { cursor: default; }
.plot-poly--sel   { fill-opacity: .3; stroke-width: 3; }

.plot-label {
  pointer-events: none;
  font-family: var(--mono); font-size: 10px; font-weight: 500;
  letter-spacing: .18em; text-transform: uppercase;
  fill: var(--accent);
  paint-order: stroke; stroke: rgba(0,0,0,.75); stroke-width: 3px;
}
/* The area, under the name. Lighter and unlettered-spaced so the two read
   as a pair rather than competing — the name identifies, the number
   informs. paint-order keeps both legible over any ground colour. */
.plot-area {
  pointer-events: none;
  font-family: var(--mono); font-size: 11px; font-weight: 400;
  letter-spacing: .04em;
  fill: var(--paper); opacity: .95;
  paint-order: stroke; stroke: rgba(0,0,0,.8); stroke-width: 3.5px;
}

/* Editing handles. Present in the tour's stylesheet rather than the
   studio's because the whole point is that the shape being edited is the
   shape that ships — one set of geometry rules, one file. */
.plot-vert {
  pointer-events: auto; cursor: grab;
  fill: var(--ink); stroke: var(--accent); stroke-width: 2;
}
.plot-vert:hover { fill: var(--accent); }
.plot-vert--first { stroke-width: 3; }
.plot-draft {
  fill: none; stroke: var(--accent); stroke-width: 2;
  stroke-dasharray: 5 4; pointer-events: none;
}

/* =====================================================================
   IN-SCENE TAG — the Community Farm wordmark, pinned to the panorama
   =====================================================================
   Same Pannellum constraints as .hs: never set position or transform
   here. Pannellum centres the div by offsetWidth/offsetHeight, so the
   box has to be a fixed size — hence the width below rather than
   letting the type size it. */
.hs-tag {
  width: 260px; height: 84px;
  box-sizing: border-box;
  text-align: center;
  pointer-events: none;
}
.hs-tag__main {
  display: block;
  font-family: var(--display); font-weight: 300;
  font-size: 46px; line-height: 1; letter-spacing: -.03em;
  color: var(--paper);
  text-shadow: 0 2px 24px rgba(0,0,0,.85), 0 0 60px rgba(0,0,0,.6);
}
.hs-tag__rule {
  display: block; width: 44px; height: 1px; margin: 14px auto 12px;
  background: var(--accent);
}
.hs-tag__sub {
  display: block;
  font-family: var(--mono); font-size: 9px; letter-spacing: .3em;
  text-transform: uppercase; color: var(--paper); opacity: .8;
  text-shadow: 0 1px 10px rgba(0,0,0,.9);
}
@media (max-width: 600px) {
  .hs-tag { width: 200px; height: 66px; }
  .hs-tag__main { font-size: 34px; }
  .hs-tag__rule { margin: 10px auto 9px; }
}

/* =====================================================================
   PORTRAIT HINT — dismissible
   ===================================================================== */
.rotate-note { position: fixed; inset: 0; z-index: 80; display: none; background: var(--ink); }
.rotate-note.show {
  display: flex; flex-direction: column;
  align-items: center; justify-content: center; text-align: center; padding: 32px;
}
.rotate-note__mark {
  width: 34px; height: 52px; border: 1px solid var(--accent);
  animation: tilt 3.2s var(--ease) infinite;
}
@keyframes tilt { 0%,100% { transform: rotate(0); } 50% { transform: rotate(90deg); } }
.rotate-note__title {
  font-family: var(--mono); font-size: 11px; letter-spacing: .2em;
  text-transform: uppercase; margin-top: 2.4rem;
}
.rotate-note__sub { font-size: 13px; color: var(--muted); margin-top: .9rem; max-width: 30ch; line-height: 1.7; }
#rotate-dismiss {
  margin-top: 2.4rem; padding: .95rem 1.8rem;
  font-family: var(--mono); font-size: 10px; letter-spacing: .16em; text-transform: uppercase;
  border: 1px solid var(--line); color: var(--paper);
  transition: border-color .3s var(--ease);
}
#rotate-dismiss:hover { border-color: var(--paper); }

/* =====================================================================
   RESPONSIVE
   ===================================================================== */
@media (max-width: 900px) {
  .brand__logo { height: 44px; }
  .viewer__head .brand__logo { height: 34px; }
  .cards { gap: .9rem; }
  .card { width: 300px; }
  .rail { left: 12px; }
  .bearing { width: min(340px, 90vw); }
}
@media (max-width: 600px) {
  .site-head { padding: 14px; padding-top: max(14px, env(safe-area-inset-top)); gap: 10px; }
  .viewer__title span { display: none; }
  .hs-panel { padding: 18px; }
  /* Labels were sized for a desktop viewport. On a phone eight of them at
     desktop size crowd the panorama they are meant to annotate. */
  .hs { width: 22px; height: 22px; }
  .hs::before, .hs::after { width: 9px; height: 9px; }
  .hs__halo { width: 20px; height: 20px; margin: -10px 0 0 -10px; }
  .hs__lbl { font-size: 7.5px; letter-spacing: .14em; padding: 4px 7px; top: 28px; }
  .hs-tag { width: 150px; height: 52px; }
  .hs-tag__main { font-size: 26px; }
  .hs-tag__rule { width: 30px; margin: 8px auto 7px; }
  .hs-tag__sub { font-size: 7.5px; letter-spacing: .24em; }
}
/* short windows, including phones in landscape */
@media (max-height: 620px) {
  .brand__logo { height: 38px; }
  .viewer__head .brand__logo { height: 30px; }
  .hero__title { font-size: clamp(2rem, 7vw, 3rem); }
  .hero__desc { font-size: 13.5px; max-width: 52ch; }
  .facts { margin-top: 1rem; padding-top: .7rem; gap: 1rem; font-size: 9px; }
  .btn-primary { margin-top: 1.2rem; padding: .85rem 1.6rem; }
  .scroll-hint { display: none; }
  .rail__stop { padding: 9px 0 9px 14px; }
  .rail__m { font-size: 12px; }
  .pano-loading__chip { top: 76px; }
}
/* Very short windows — most phones in landscape once browser chrome is
   subtracted (e.g. 667x320, 740x360). Computed: with the description shown
   the hero block is 273px against 252px available at 740x360, i.e. it
   overruns the header. The description is the part that can go — the facts
   row carries the essentials and the full copy is on the microsite. */
@media (max-height: 460px) {
  .hero__desc { display: none; }
  .hero__content { bottom: 2.4rem; }
  .facts { margin-top: .9rem; }
  .rail__label { display: none; }
  .bearing__readout { margin-top: 6px; }
}
@media (prefers-reduced-motion: reduce) {
  .grain, .scroll-hint__arw { display: none; }
  .hero__media, .rotate-note__mark, .pano-loading__bar { animation: none; }
  .hs__halo { animation: none; opacity: .5; transform: scale(1); }
  * { transition-duration: .01ms !important; }
}
