/* Dark Tides Treasure Hunts — the chart room.
   ═══════════════════════════════════════════════════════════════════════

   Namespace `th-`, matching the house convention (trs-, soc-, brick-, adm-).
   The palette is the Treasury palette; this is the same world, not a new one.

   The organising idea is the one that rescued the Treasury coin board: spend
   nothing on busy surfaces and everything on the frame. Backgrounds here are
   dark and quiet — deep water, a dimmed photograph, a wash of parchment. The
   money goes into brass rules, engraved plates, wax seals, glowing route
   lines and the compass. A loud background with a thin border reads as a web
   page; a quiet one inside real moulding reads as an object.

   Mobile first throughout, and not as a slogan: this page is read standing
   up, one-handed, on cellular, in the sun. Tap targets never go below 48px,
   body copy never below 15px, and every layout starts as one column and
   earns its second.

   Two blocks that belong to this feature live elsewhere on purpose — the
   homepage strip in css/home-world.css and the Treasure Log in
   css/society.css — because neither of those pages loads this stylesheet, and
   thirty kilobytes for one band of gold is not a trade worth making. */

.th-body{
  /* ── the sea ── */
  --ink:#050709; --ink-2:#07121C; --deep:#04101A; --panel:#0B1B27;
  /* ── brass and lamplight ── */
  --gold:#C89B3C; --gold-lt:#E3BE72; --gold-dk:#8A6620;
  --parch:#D7B77A; --cream:#E8DEC9; --dim:#9DA7AE;
  /* ── the chart ── */
  --chart:#C9B591; --chart-ink:#4A3A28; --chart-line:rgba(74,58,40,.34);
  /* ── live states ── */
  --live:#4FBF8B; --live-dim:rgba(79,191,139,.18);
  --wax:#8E2B24; --wax-lt:#B4453A;
  --hair:rgba(200,155,60,.28); --hair-soft:rgba(255,255,255,.09);

  --display:'Cinzel',Georgia,'Times New Roman',serif;
  --pad:clamp(18px,5vw,64px);
  --rule:1px solid var(--hair-soft);

  margin:0;background:var(--ink);color:var(--cream);
  font-family:'Jost',system-ui,-apple-system,'Segoe UI',sans-serif;
  font-size:16px;line-height:1.62;-webkit-font-smoothing:antialiased;
  overflow-x:hidden;
}
.th-body *,.th-body *::before,.th-body *::after{box-sizing:border-box}

/* The element resets are wrapped in :where() ON PURPOSE, and it is not a
   style preference — it is a bug fix.

   Written the obvious way, `.th-body p{margin:0}` has specificity (0,1,1):
   one class and one type. Every single-class rule later in this file —
   .th-hero__lead, .th-kicker, .th-detail__title — is (0,1,0), so the reset
   beat all of them no matter how far down the file they sat. The symptom was
   a hero lead paragraph sitting hard against the left edge instead of centred,
   because `margin: … auto 0` never applied. Measured, not guessed: computed
   marginLeft was 0px where the rule said auto.

   :where() contributes nothing, so these are (0,1,0) — still strong enough to
   beat the bare `h1,h2,h3,h4,p,ul,figure{margin:0}` in css/styles.css, and
   weak enough that anything in this file can override them. */
.th-body :where(h1,h2,h3,h4){
  margin:0;font-family:var(--display);font-weight:600;line-height:1.12;letter-spacing:.014em}
.th-body :where(p){margin:0}
.th-body :where(img){max-width:100%;display:block}
.th-body :where(ul,ol){margin:0;padding:0;list-style:none}

.th-skip{position:absolute;left:-9999px;top:0;z-index:90;
  padding:12px 18px;background:var(--gold);color:#0b0b0b;font-weight:600}
.th-skip:focus{left:0}
.th-body :where(a,button,input,summary):focus-visible{
  outline:2px solid var(--gold-lt);outline-offset:3px;border-radius:2px}
.th-sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;
  overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}

/* ── chrome ──────────────────────────────────────────────────────────── */
.th-nav{position:sticky;top:0;z-index:40;
  display:flex;align-items:center;justify-content:space-between;gap:12px;
  padding:12px var(--pad);border-bottom:var(--rule);
  background:rgba(5,7,9,.94);backdrop-filter:blur(10px)}
/* 44px minimum on every hit area, including the ones that are only text.
   Measured on a 390px viewport: the brand, the nav links and the footer link
   were all 16-30px tall before these, which is a miss on a page whose whole
   audience is standing up holding a phone. */
.th-brand{text-decoration:none;min-width:0;
  display:flex;flex-direction:column;justify-content:center;min-height:44px}
.th-brand b{display:block;font-family:var(--display);font-weight:600;
  font-size:clamp(13px,3.2vw,17px);letter-spacing:.13em;text-transform:uppercase;
  color:var(--cream);white-space:nowrap}
.th-brand small{display:block;font-size:8.5px;letter-spacing:.2em;
  text-transform:uppercase;color:var(--gold)}
.th-nav__links{display:flex;align-items:center;gap:clamp(10px,2.4vw,22px)}
.th-nav__links a{display:inline-flex;align-items:center;min-height:44px;
  font-size:11px;letter-spacing:.15em;text-transform:uppercase;
  text-decoration:none;color:var(--dim);white-space:nowrap}
.th-nav__links a:hover,.th-nav__links a[aria-current="page"]{color:var(--gold-lt)}
@media(max-width:560px){
  .th-brand small{display:none}
  .th-nav__links a.th-nav__hide{display:none}
}

.th-foot{padding:44px var(--pad) 56px;border-top:var(--rule);text-align:center}
.th-foot a{display:inline-flex;align-items:center;justify-content:center;
  min-height:44px;padding:0 10px;color:var(--parch);text-decoration:none;
  font-size:11px;letter-spacing:.16em;text-transform:uppercase}
.th-foot span{display:block;margin-top:8px;font-style:italic;color:var(--dim);font-size:13px}

/* ── shared type ─────────────────────────────────────────────────────── */
.th-kicker{font-size:10.5px;letter-spacing:.28em;text-transform:uppercase;
  color:var(--gold);margin-bottom:12px}
.th-dim{color:var(--dim)}
.th-lead{max-width:60ch;color:#CFC7B6;font-size:clamp(15px,2.1vw,17.5px)}

.th-section{padding:clamp(44px,7vw,92px) var(--pad)}
.th-section--tight{padding-top:clamp(28px,4vw,48px)}
.th-in{max-width:1180px;margin:0 auto}
.th-sec__head{margin-bottom:clamp(22px,3.4vw,38px)}
.th-sec__head h2{font-size:clamp(23px,5.4vw,40px);text-transform:uppercase;letter-spacing:.05em}
.th-sec__head p{margin-top:10px;color:var(--dim);font-size:clamp(14px,2vw,16px)}

/* A brass rule with a diamond in the middle. Cheap, and it does more for the
   page than any amount of texture would. */
.th-rule{display:flex;align-items:center;gap:14px;margin:0 0 clamp(20px,3vw,32px)}
.th-rule::before,.th-rule::after{content:"";flex:1;height:1px;
  background:linear-gradient(90deg,transparent,var(--hair),transparent)}
.th-rule i{width:7px;height:7px;transform:rotate(45deg);
  background:var(--gold);box-shadow:0 0 12px rgba(200,155,60,.6)}

/* ── buttons ─────────────────────────────────────────────────────────── */
.th-btn{display:inline-flex;align-items:center;justify-content:center;gap:.55em;
  min-height:52px;padding:0 clamp(22px,4vw,34px);border-radius:2px;
  font-family:var(--display);font-size:13px;font-weight:600;letter-spacing:.15em;
  text-transform:uppercase;text-decoration:none;cursor:pointer;
  border:1px solid var(--gold);
  transition:transform .22s ease,box-shadow .22s ease,background-color .22s ease}
.th-btn--lg{min-height:58px;font-size:14px}
.th-btn--wide{width:100%}
.th-btn--gold{color:#120d05;
  background:linear-gradient(180deg,var(--gold-lt),var(--gold) 52%,#A97D28);
  box-shadow:0 2px 22px rgba(200,155,60,.22),inset 0 1px 0 rgba(255,240,205,.55)}
.th-btn--gold:hover:not(:disabled){transform:translateY(-2px);
  box-shadow:0 10px 30px rgba(200,155,60,.4)}
.th-btn--ghost{color:var(--cream);background:rgba(6,10,14,.55);border-color:var(--hair)}
.th-btn--ghost:hover:not(:disabled){border-color:var(--gold);color:#fff}
.th-btn--quiet{border-color:transparent;color:var(--parch);background:none;
  min-height:48px;padding:0 14px}
.th-btn:disabled{opacity:.55;cursor:default;transform:none}
.th-btns{display:flex;flex-wrap:wrap;gap:12px}
@media(max-width:520px){.th-btns .th-btn{flex:1 1 100%}}

/* ── status chips ────────────────────────────────────────────────────── */
.th-chip{display:inline-flex;align-items:center;gap:7px;padding:6px 13px;
  border-radius:2px;font-family:var(--display);font-size:10px;font-weight:600;
  letter-spacing:.2em;text-transform:uppercase;white-space:nowrap;
  border:1px solid var(--hair);color:var(--parch);background:rgba(6,12,18,.6)}
.th-chip::before{content:"";width:6px;height:6px;border-radius:50%;
  background:currentColor;flex:none}
.th-chip--live{color:var(--live);border-color:rgba(79,191,139,.45);background:var(--live-dim)}
.th-chip--live::before{animation:th-pulse 2.4s ease-in-out infinite}
.th-chip--gold{color:var(--gold-lt);border-color:var(--hair);background:rgba(200,155,60,.12)}
.th-chip--wax{color:#E8A79E;border-color:rgba(180,69,58,.5);background:rgba(142,43,36,.2)}
.th-chip--soon{color:var(--dim)}
@keyframes th-pulse{
  0%,100%{opacity:1;box-shadow:0 0 0 0 rgba(79,191,139,.5)}
  50%{opacity:.55;box-shadow:0 0 0 7px rgba(79,191,139,0)}
}

/* ═══ THE HERO ═══════════════════════════════════════════════════════════
   Five stacked layers, darkest at the back:
     1  a deep-water gradient, so the section is never blank while images load
     2  the photograph, dimmed hard and blurred a touch — atmosphere, not subject
     3  the chart: rhumb lines and a graticule, drawn as SVG, not an image
     4  fog: two enormous soft radial gradients drifting past each other
     5  the copy
   Nothing in layers 1-4 is ever a tap target, and all of it is aria-hidden. */

.th-hero{position:relative;isolation:isolate;overflow:hidden;
  min-height:clamp(560px,86svh,860px);
  display:grid;align-items:center;
  padding:clamp(56px,10vw,110px) var(--pad) clamp(48px,8vw,90px);
  background:radial-gradient(120% 90% at 50% 8%,#0B2233 0%,#061320 42%,#03080D 100%)}
.th-hero__layer{position:absolute;inset:0;z-index:-1;pointer-events:none}
.th-hero__photo{object-fit:cover;width:100%;height:100%;
  opacity:.34;filter:blur(2px) saturate(.72) contrast(1.06)}
/* Fade the photograph out at the bottom so the section joins the next one
   instead of stopping at a hard edge. */
.th-hero__veil{background:
  linear-gradient(180deg,rgba(3,8,13,.62) 0%,rgba(3,8,13,.28) 38%,
                          rgba(3,8,13,.82) 82%,var(--ink) 100%)}
.th-hero__lantern{background:
  radial-gradient(38% 30% at 50% 22%,rgba(226,182,106,.20),transparent 70%),
  radial-gradient(22% 18% at 82% 64%,rgba(226,182,106,.13),transparent 72%)}
.th-hero__chart{opacity:.3;mix-blend-mode:screen}
.th-hero__chart svg{width:100%;height:100%}

.th-fog{position:absolute;inset:-20%;z-index:-1;pointer-events:none;opacity:.5}
.th-fog span{position:absolute;border-radius:50%;filter:blur(60px)}
.th-fog span:nth-child(1){left:-12%;top:38%;width:78%;height:46%;
  background:radial-gradient(circle,rgba(150,178,196,.16),transparent 66%);
  animation:th-drift-a 64s linear infinite}
.th-fog span:nth-child(2){right:-16%;top:16%;width:66%;height:52%;
  background:radial-gradient(circle,rgba(120,150,172,.13),transparent 68%);
  animation:th-drift-b 88s linear infinite}
@keyframes th-drift-a{
  0%{transform:translate3d(-6%,0,0) scale(1)}
  50%{transform:translate3d(14%,-4%,0) scale(1.12)}
  100%{transform:translate3d(-6%,0,0) scale(1)}
}
@keyframes th-drift-b{
  0%{transform:translate3d(6%,2%,0) scale(1.08)}
  50%{transform:translate3d(-12%,-3%,0) scale(1)}
  100%{transform:translate3d(6%,2%,0) scale(1.08)}
}

/* Ships on the horizon. Silhouettes only — they read at 40px, and they are
   what makes the band of water look like sea rather than gradient. */
.th-fleet{position:absolute;left:0;right:0;bottom:11%;z-index:-1;
  height:clamp(58px,13vw,128px);opacity:.5;pointer-events:none}
.th-fleet svg{position:absolute;bottom:0;height:100%;width:auto;
  fill:#020508;filter:drop-shadow(0 0 22px rgba(0,0,0,.85))}
.th-fleet svg:nth-child(1){left:6%;height:64%;opacity:.8;
  animation:th-swell 15s ease-in-out infinite}
.th-fleet svg:nth-child(2){left:44%;height:100%;
  animation:th-swell 11s ease-in-out infinite .8s}
.th-fleet svg:nth-child(3){right:9%;height:52%;opacity:.62;
  animation:th-swell 18s ease-in-out infinite 1.6s}
@keyframes th-swell{
  0%,100%{transform:translateY(0) rotate(0)}
  50%{transform:translateY(-5px) rotate(.5deg)}
}

.th-hero__in{position:relative;max-width:1180px;margin:0 auto;width:100%;text-align:center}
.th-hero__title{font-size:clamp(34px,10.5vw,84px);line-height:1.02;
  text-transform:uppercase;letter-spacing:.045em;
  text-shadow:0 2px 40px rgba(0,0,0,.9),0 0 90px rgba(200,155,60,.18)}
.th-hero__lead{margin:clamp(18px,3vw,26px) auto 0;max-width:34ch;
  font-size:clamp(15.5px,2.6vw,20px);line-height:1.62;color:#D8D0C0}
.th-hero__lead b{display:block;color:var(--gold-lt);font-weight:400;
  font-family:var(--display);letter-spacing:.03em}
.th-hero__cta{display:flex;flex-wrap:wrap;gap:14px;justify-content:center;
  margin-top:clamp(28px,4.5vw,40px)}
@media(max-width:520px){.th-hero__cta .th-btn{flex:1 1 100%}}

/* The compass. The needle turns once every forty seconds — slow enough that
   you notice it only if you stop and look, which is the intended effect. */
.th-compass{position:relative;width:clamp(78px,17vw,118px);aspect-ratio:1;
  margin:clamp(30px,5vw,46px) auto 0;opacity:.92}
.th-compass svg{width:100%;height:100%}
.th-compass__needle{transform-origin:50% 50%;animation:th-swing 40s ease-in-out infinite}
@keyframes th-swing{
  0%,100%{transform:rotate(-7deg)}
  25%{transform:rotate(6deg)}
  50%{transform:rotate(-3deg)}
  75%{transform:rotate(9deg)}
}
.th-hero__scroll{margin-top:22px;font-size:10px;letter-spacing:.3em;
  text-transform:uppercase;color:var(--dim)}

/* ═══ THE HUNTING GROUNDS ════════════════════════════════════════════════
   A real chart, not a picture of one: the parchment is a texture, the rhumb
   lines and graticule are SVG, and every marker is placed from its hunt's
   actual latitude and longitude. Moving a pin means editing a coordinate in
   Admin, never a stylesheet. */

.th-chartbox{position:relative;border-radius:3px;overflow:hidden;
  border:1px solid rgba(200,155,60,.4);
  box-shadow:0 30px 70px rgba(0,0,0,.6),
             inset 0 0 0 1px rgba(255,255,255,.05),
             inset 0 0 90px rgba(28,18,6,.5)}
/* The source photograph is bright paper with two strong diagonal light
   bands across it. Left alone it reads as a scan of a texture sat on a dark
   page — the exact "cheap" failure the Treasury coin board ran into. So it is
   scaled up past the bands, desaturated and taken down hard in brightness,
   until it stops being a picture of paper and becomes a lamp-lit chart. */
.th-chartbox__paper{position:absolute;inset:0;
  background:#6B5738 url('/galveston/images/parchment-1500.webp') center/150% no-repeat;
  filter:saturate(.58) brightness(.5) contrast(1.06)}
/* Age it at the edges. A clean rectangle of parchment looks like a texture
   swatch; a darkened, uneven one looks like a chart that has been folded and
   carried. The vignette is heavy on purpose — the middle is where the pins
   are, and everything else should fall away. */
.th-chartbox__age{position:absolute;inset:0;
  background:radial-gradient(110% 85% at 50% 45%,rgba(24,15,5,.2) 0%,rgba(24,15,5,.34) 45%,
                             rgba(20,12,4,.62) 84%,rgba(14,9,3,.8) 100%),
             linear-gradient(103deg,rgba(40,26,10,.2) 0 17%,transparent 17.6% 82%,
                             rgba(40,26,10,.18) 82.6%)}
.th-chartbox__grid{position:absolute;inset:0}
.th-chartbox__grid svg{width:100%;height:100%}
.th-chartbox__face{position:relative;aspect-ratio:16/11}
@media(max-width:640px){.th-chartbox__face{aspect-ratio:4/5}}

/* Pins are positioned in per-cent by the script, from lat/lon. */
/* The label sits above the mark, and the MARK is what has to land on the
   coordinate — so the button is pulled up by its own height and then pushed
   back down by exactly half a mark plus the bottom padding (13px + 10px).
   Without the second half of that the X sits 23px north of the port. */
.th-pin{position:absolute;transform:translate(-50%,calc(-100% + 23px));
  display:grid;justify-items:center;gap:5px;
  padding:6px 8px 10px;border:0;background:none;cursor:pointer;
  min-width:48px;min-height:48px}
.th-pin__mark{position:relative;width:26px;height:26px;display:grid;place-items:center;
  transition:transform .25s ease}
.th-pin__mark svg{width:100%;height:100%;filter:drop-shadow(0 3px 5px rgba(40,26,8,.6))}
.th-pin__halo{position:absolute;inset:-14px;border-radius:50%;pointer-events:none}
.th-pin--live .th-pin__halo{
  background:radial-gradient(circle,rgba(79,191,139,.34),transparent 66%);
  animation:th-halo 2.8s ease-in-out infinite}
@keyframes th-halo{
  0%,100%{transform:scale(.82);opacity:.55}
  50%{transform:scale(1.14);opacity:1}
}
.th-pin__label{font-family:var(--display);font-size:11px;font-weight:600;
  letter-spacing:.11em;text-transform:uppercase;color:#33240F;white-space:nowrap;
  padding:3px 8px;border-radius:2px;background:rgba(232,222,201,.82);
  border:1px solid rgba(74,58,40,.4)}
.th-pin--live .th-pin__label{background:rgba(24,46,38,.9);color:#B9EBD3;
  border-color:rgba(79,191,139,.5)}
.th-pin:hover .th-pin__mark,.th-pin:focus-visible .th-pin__mark{transform:scale(1.14)}

/* The legend under the chart, which is also the whole chart on a phone —
   a 26px pin inside a 4:5 box is not a tap target everyone can hit, and this
   is the accessible route to the same information. */
.th-ports{display:grid;gap:12px;margin-top:20px;
  grid-template-columns:repeat(auto-fit,minmax(240px,1fr))}
/* A grid, not a row. Side by side, a 120px status chip left about 50px for
   the name, and "New Orleans" spilled straight over the chip — the name was
   not clipped because only the region line had an ellipsis on it. The chip
   now sits on its own line under the name, the marker spans both, and the
   name gets the whole width. */
.th-port{display:grid;grid-template-columns:auto 1fr;gap:5px 14px;
  align-items:center;width:100%;text-align:left;
  min-height:72px;padding:14px 16px;cursor:pointer;
  border:1px solid var(--hair-soft);border-radius:3px;
  background:linear-gradient(180deg,rgba(11,27,39,.8),rgba(6,12,18,.8));
  color:inherit;font:inherit;transition:border-color .2s,transform .2s}
.th-port:hover{border-color:var(--hair);transform:translateY(-2px)}
.th-port--live{border-color:rgba(79,191,139,.38)}
.th-port__mark{grid-column:1;grid-row:1 / span 2;align-self:center;
  width:30px;height:30px}
.th-port__mark svg{width:100%;height:100%}
.th-port__body{grid-column:2;grid-row:1;min-width:0}
.th-port__body b{display:block;font-family:var(--display);font-size:15px;
  letter-spacing:.03em;color:var(--cream);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.th-port__body span{display:block;font-size:12px;color:var(--dim);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.th-port__state{grid-column:2;grid-row:2;justify-self:start}

/* ── the painted chart ───────────────────────────────────────────────────

   When John has painted the hunting grounds, the painting IS the chart. It
   carries its own markers, names and status badges, so this adds nothing on
   top of it — only invisible hotspots over the painted markers, which appear
   as a ring on hover and on keyboard focus so the chart still tells you it
   can be touched.

   The frame is the same brass moulding as the command board, because the
   artwork already has its own torn-parchment edge and a second decorated
   border would fight it. */
.th-grounds{position:relative;border-radius:3px;overflow:hidden;
  border:1px solid rgba(200,155,60,.4);
  box-shadow:0 30px 70px rgba(0,0,0,.6),inset 0 0 0 1px rgba(255,255,255,.05)}
.th-grounds__scroll{position:relative}
.th-grounds img{width:100%;height:auto;display:block}
.th-grounds__hint{display:none}

/* The hotspot. 56px is above the tap floor at every width, and the whole
   thing is invisible until it is wanted. */
.th-spot{position:absolute;transform:translate(-50%,-50%);
  width:clamp(56px,7vw,112px);height:clamp(76px,10vw,150px);
  border:0;background:none;padding:0;cursor:pointer;border-radius:8px}
.th-spot__ring{position:absolute;inset:0;border-radius:8px;
  border:1px solid transparent;background:transparent;
  transition:border-color .22s ease,background-color .22s ease,box-shadow .22s ease}
.th-spot:hover .th-spot__ring,.th-spot:focus-visible .th-spot__ring{
  border-color:rgba(226,182,106,.75);background:rgba(226,182,106,.12);
  box-shadow:0 0 26px rgba(200,155,60,.4),inset 0 0 22px rgba(226,182,106,.16)}
.th-spot:focus-visible{outline:none}
/* The live port gets a slow breath, so the eye lands on it before it lands
   on anything else — the painted glow does half the work already. */
.th-spot--live .th-spot__ring{animation:th-spot-breathe 3.4s ease-in-out infinite}
@keyframes th-spot-breathe{
  0%,100%{box-shadow:0 0 0 0 rgba(226,182,106,0)}
  50%{box-shadow:0 0 30px 2px rgba(226,182,106,.28)}
}
/* On a phone the chart is 350px wide and its lettering is about six pixels
   tall — a picture of a map rather than a map. So below 700px it becomes a
   chart you can drag, held at a width where the names are actually readable.

   The hotspots come OFF at the same breakpoint, deliberately. At that scale
   four of them sit shoulder to shoulder and tapping the wrong port is worse
   than not being able to tap at all; the port list underneath is the control
   on a phone, and it always was. */
@media(max-width:700px){
  .th-grounds__scroll{overflow-x:auto;overflow-y:hidden;
    -webkit-overflow-scrolling:touch;scrollbar-width:thin}
  .th-grounds img{min-width:760px}
  .th-spot{display:none}
  .th-grounds__hint{display:block;margin-top:10px;text-align:center;
    font-size:11px;letter-spacing:.14em;text-transform:uppercase;color:var(--dim)}
}

/* ── the hero, when it is a painting ─────────────────────────────────────
   The generic treatment blurs and drops the photograph to 34% because it is
   atmosphere behind type. Commissioned artwork is not atmosphere — it is the
   point — so it is shown nearly full strength and the veil does the work of
   keeping the headline readable. */
.th-hero__art{position:absolute;inset:0;z-index:-1;pointer-events:none;display:block}
.th-hero__art img{width:100%;height:100%;object-fit:cover;
  opacity:.9;filter:saturate(.96) contrast(1.02)}
.th-hero--art .th-hero__veil{background:
  linear-gradient(180deg,rgba(3,8,13,.72) 0%,rgba(3,8,13,.42) 30%,
                          rgba(3,8,13,.55) 58%,rgba(3,8,13,.88) 86%,var(--ink) 100%)}
.th-hero--art .th-hero__lantern{background:
  radial-gradient(42% 34% at 50% 26%,rgba(226,182,106,.14),transparent 72%)}
.th-hero--art .th-fog{opacity:.3}
/* The painting is 2.75:1 — a tall phone crop would swallow the composition,
   so the hero stops trying to fill the viewport and lets the picture set the
   height it needs. */
@media(max-width:640px){
  .th-hero--art{min-height:clamp(480px,74svh,680px)}
}

/* ── the cinematic information card ─────────────────────────────────── */
.th-modal{position:fixed;inset:0;z-index:70;display:grid;place-items:center;
  padding:16px;background:rgba(2,5,8,.86);backdrop-filter:blur(6px);
  animation:th-fade .22s ease}
.th-modal[hidden]{display:none}
@keyframes th-fade{from{opacity:0}to{opacity:1}}
.th-card{position:relative;width:min(560px,100%);max-height:88svh;overflow:auto;
  -webkit-overflow-scrolling:touch;
  border:1px solid var(--hair);border-radius:3px;
  background:linear-gradient(180deg,#0D2030,#060D14 72%);
  box-shadow:0 40px 90px rgba(0,0,0,.75),inset 0 1px 0 rgba(255,255,255,.06);
  animation:th-rise .3s cubic-bezier(.2,.7,.3,1)}
@keyframes th-rise{
  from{opacity:0;transform:translateY(16px) scale(.985)}
  to{opacity:1;transform:none}
}
.th-card__art{position:relative;aspect-ratio:16/8;overflow:hidden;background:#04101A}
.th-card__art img{width:100%;height:100%;object-fit:cover;opacity:.78}
.th-card__art::after{content:"";position:absolute;inset:0;
  background:linear-gradient(180deg,transparent 35%,rgba(6,13,20,.92))}
.th-card__close{position:absolute;top:10px;right:10px;z-index:2;
  width:48px;height:48px;display:grid;place-items:center;
  border:1px solid var(--hair-soft);border-radius:50%;cursor:pointer;
  background:rgba(4,8,12,.8);color:var(--cream);font-size:22px;line-height:1}
.th-card__close:hover{border-color:var(--gold);color:var(--gold-lt)}
.th-card__in{padding:clamp(20px,4.4vw,30px)}
.th-card__in h3{margin-top:8px;font-size:clamp(20px,4.6vw,27px);
  text-transform:uppercase;letter-spacing:.04em}
.th-card__where{margin-top:8px;font-family:var(--display);font-size:13.5px;
  letter-spacing:.07em;color:var(--parch)}
/* Three lines and no more. The full description is on the hunt page; the
   job of this card is to get the CTA above the fold on a phone, and an
   eight-line paragraph pushed it out of sight. */
.th-card__note{margin-top:14px;color:#CFC7B6;font-size:14.5px;
  display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
/* On a phone the card scrolls, and the action must not scroll away with it.
   Measured: with the full Galveston description the CTA sat 44px below the
   fold, which on a card people tap once at a festival is a real loss. */
@media(max-width:560px){
  .th-card__art{aspect-ratio:16/6}
  .th-card__in{padding-bottom:14px}
  .th-card .th-btn{position:sticky;bottom:0;z-index:2;
    box-shadow:0 -16px 24px 6px rgba(6,13,20,.92),
               0 2px 22px rgba(200,155,60,.22),
               inset 0 1px 0 rgba(255,240,205,.55)}
}
.th-card .th-facts{margin-top:20px}
.th-card .th-btn{margin-top:22px}

/* ── fact grids ──────────────────────────────────────────────────────── */
.th-facts{display:grid;gap:1px;background:var(--hair-soft);
  border:1px solid var(--hair-soft);border-radius:3px;overflow:hidden;
  grid-template-columns:repeat(auto-fit,minmax(132px,1fr))}
.th-facts div{padding:14px 14px 16px;background:rgba(7,15,22,.96)}
.th-facts dt{font-size:9.5px;letter-spacing:.2em;text-transform:uppercase;color:var(--dim)}
.th-facts dd{margin:6px 0 0;font-family:var(--display);font-size:clamp(15px,2.6vw,19px);
  color:var(--cream);line-height:1.2}
.th-facts dd small{display:block;margin-top:3px;font-family:inherit;
  font-size:11px;letter-spacing:.06em;color:var(--dim)}

/* ═══ THE ACTIVE HUNT ════════════════════════════════════════════════════ */
.th-feature{position:relative;overflow:hidden;border-radius:3px;
  border:1px solid var(--hair);
  background:linear-gradient(180deg,#0C1E2C,#050B11 78%);
  box-shadow:0 30px 70px rgba(0,0,0,.55)}
.th-feature__art{position:relative;aspect-ratio:16/9;background:#04101A}
.th-feature__art img{width:100%;height:100%;object-fit:cover;opacity:.82}
.th-feature__art::after{content:"";position:absolute;inset:0;
  background:linear-gradient(180deg,rgba(4,10,16,.25) 0 38%,rgba(5,11,17,.96) 100%)}
.th-feature__badge{position:absolute;top:16px;left:16px;z-index:2}
.th-feature__in{position:relative;padding:clamp(22px,4.4vw,40px);margin-top:-12%}
.th-feature__in h3{font-size:clamp(24px,6vw,42px);text-transform:uppercase;letter-spacing:.04em}
.th-feature__sub{margin-top:9px;font-family:var(--display);font-size:clamp(13px,2.4vw,16px);
  letter-spacing:.09em;color:var(--parch);text-transform:uppercase}
.th-feature__prize{margin-top:clamp(20px,3.4vw,30px);padding:clamp(18px,3.4vw,26px);
  border:1px solid var(--hair);border-radius:3px;
  background:linear-gradient(180deg,rgba(200,155,60,.1),rgba(200,155,60,.02))}
.th-feature__prize p{font-size:10px;letter-spacing:.24em;text-transform:uppercase;color:var(--gold)}
.th-feature__prize b{display:block;margin-top:8px;font-family:var(--display);
  font-size:clamp(22px,5.6vw,36px);color:var(--gold-lt);letter-spacing:.03em;line-height:1.12}
.th-feature__extra{margin-top:18px;display:grid;gap:9px}
.th-feature__extra li{display:flex;gap:11px;align-items:flex-start;
  font-size:14.5px;color:#CFC7B6}
.th-feature__extra li::before{content:"";flex:none;width:6px;height:6px;margin-top:9px;
  transform:rotate(45deg);background:var(--gold);box-shadow:0 0 8px rgba(200,155,60,.6)}
.th-feature .th-btns{margin-top:clamp(22px,3.6vw,30px)}

/* ═══ THE HUNT COMMAND BOARD ═════════════════════════════════════════════
   The one section that has to look like instruments rather than cards. Each
   readout is an engraved brass plate with a lit rim; the whole board sits
   inside a mitred frame with wheels at the corners — the same construction
   as the Treasury coin case, and for the same reason. */

.th-board{position:relative;padding:clamp(20px,3.6vw,30px);border-radius:4px;
  background:
    linear-gradient(180deg,rgba(10,22,32,.96),rgba(4,9,14,.98)),
    repeating-linear-gradient(94deg,rgba(255,255,255,.012) 0 3px,transparent 3px 7px);
  border:1px solid rgba(200,155,60,.34);
  box-shadow:
    0 0 0 1px rgba(0,0,0,.6),
    0 0 0 7px #0A1119,
    0 0 0 8px rgba(200,155,60,.28),
    0 30px 70px rgba(0,0,0,.62),
    inset 0 1px 0 rgba(255,236,196,.09),
    inset 0 0 70px rgba(0,0,0,.55)}
.th-board__corner{position:absolute;width:clamp(26px,4.6vw,40px);aspect-ratio:1;
  opacity:.72;pointer-events:none}
.th-board__corner svg{width:100%;height:100%}
.th-board__corner--tl{top:-6px;left:-6px}
.th-board__corner--tr{top:-6px;right:-6px;transform:scaleX(-1)}
.th-board__corner--bl{bottom:-6px;left:-6px;transform:scaleY(-1)}
.th-board__corner--br{bottom:-6px;right:-6px;transform:scale(-1)}

.th-board__head{display:flex;flex-wrap:wrap;align-items:center;
  justify-content:space-between;gap:12px;margin-bottom:clamp(18px,3vw,26px);
  padding-bottom:16px;border-bottom:1px solid rgba(200,155,60,.2)}
.th-board__head h3{font-size:clamp(17px,3.6vw,24px);text-transform:uppercase;letter-spacing:.14em}
.th-board__head p{font-size:11px;letter-spacing:.16em;text-transform:uppercase;color:var(--dim)}

.th-gauges{display:grid;gap:clamp(10px,1.8vw,14px);
  grid-template-columns:repeat(auto-fit,minmax(150px,1fr))}
.th-gauge{position:relative;padding:16px 15px 18px;border-radius:3px;
  background:linear-gradient(180deg,rgba(18,30,41,.9),rgba(5,10,15,.95));
  border:1px solid rgba(200,155,60,.2);
  box-shadow:inset 0 1px 0 rgba(255,236,196,.1),inset 0 -14px 26px rgba(0,0,0,.45)}
.th-gauge__label{display:block;font-size:9px;letter-spacing:.22em;
  text-transform:uppercase;color:var(--dim)}
.th-gauge__value{display:block;margin-top:9px;font-family:var(--display);
  font-size:clamp(23px,5.4vw,34px);line-height:1;color:var(--gold-lt);
  text-shadow:0 0 22px rgba(200,155,60,.3)}
.th-gauge__value small{font-size:.52em;color:var(--dim);letter-spacing:.06em}
.th-gauge__note{display:block;margin-top:8px;font-size:10.5px;letter-spacing:.12em;
  text-transform:uppercase;color:var(--parch)}
.th-gauge--state .th-gauge__value{font-size:clamp(15px,3.4vw,20px);letter-spacing:.11em;
  text-transform:uppercase}
.th-gauge--found .th-gauge__value{color:var(--live);text-shadow:0 0 22px rgba(79,191,139,.32)}
.th-gauge--wait .th-gauge__value{color:var(--dim);text-shadow:none}
.th-gauge--count .th-gauge__value{font-variant-numeric:tabular-nums;letter-spacing:.04em}

/* Clue progress as a chain of lamps rather than a rail: at five clues, five
   things you can count beats a percentage you have to estimate. */
.th-lamps{display:flex;gap:6px;margin-top:12px}
.th-lamps i{flex:1;height:5px;border-radius:2px;background:rgba(255,255,255,.08);
  box-shadow:inset 0 0 0 1px rgba(0,0,0,.5)}
.th-lamps i.is-on{background:linear-gradient(90deg,var(--gold),var(--gold-lt));
  box-shadow:0 0 12px rgba(200,155,60,.6)}
.th-lamps i.is-next{background:rgba(200,155,60,.25);animation:th-blink 2.2s ease-in-out infinite}
@keyframes th-blink{0%,100%{opacity:.35}50%{opacity:1}}

/* A wax seal. Used for "locked", on the board and on every locked clue. */
.th-seal{position:relative;width:clamp(48px,11vw,64px);aspect-ratio:1;
  display:grid;place-items:center;flex:none;border-radius:50%;
  background:radial-gradient(circle at 36% 30%,var(--wax-lt),var(--wax) 52%,#5E1A15 100%);
  box-shadow:0 5px 14px rgba(0,0,0,.6),inset 0 2px 5px rgba(255,255,255,.2),
             inset 0 -4px 10px rgba(0,0,0,.45)}
/* The ragged edge is what stops it reading as a red circle. */
.th-seal::before{content:"";position:absolute;inset:-3px;border-radius:50%;
  background:radial-gradient(circle at 50% 50%,transparent 62%,
             rgba(142,43,36,.55) 63% 78%,transparent 79%);
  filter:blur(.6px)}
.th-seal svg{width:54%;height:54%;opacity:.8;position:relative}
.th-seal--sm{width:38px}

.th-board__foot{display:flex;flex-wrap:wrap;gap:10px 22px;align-items:center;
  margin-top:clamp(16px,2.6vw,22px);padding-top:16px;
  border-top:1px solid rgba(200,155,60,.18);
  font-size:11.5px;letter-spacing:.09em;color:var(--dim)}

/* ═══ HOW THE HUNT WORKS ═════════════════════════════════════════════════ */
/* Flyer on the left, stages on the right, once there is room for both.
   Below 1000px the flyer would be a postage stamp beside a column of text,
   so it goes back on top at a size worth looking at. */
.th-steps__wrap{display:grid;gap:clamp(20px,3vw,34px)}
@media (min-width:1000px){
  .th-steps__wrap.has-flyer{grid-template-columns:minmax(0,340px) minmax(0,1fr);
    align-items:start}
  /* Two columns of cards beside the flyer, not four squeezed ones. */
  .th-steps__wrap.has-flyer .th-steps{grid-template-columns:repeat(2,minmax(0,1fr))}
}
.th-steps__flyer{margin:0;max-width:420px;justify-self:center}
@media (min-width:1000px){ .th-steps__flyer{max-width:none;justify-self:stretch} }
.th-steps__open{position:relative;display:block;width:100%;padding:8px;
  border:1px solid var(--hair);background:rgba(4,12,18,.75);cursor:zoom-in;
  box-shadow:0 18px 44px rgba(0,0,0,.5);
  transition:border-color .25s ease,transform .25s ease}
.th-steps__open:hover{border-color:var(--gold);transform:translateY(-3px)}
.th-steps__open:focus-visible{outline:2px solid var(--gold-lt);outline-offset:3px}
.th-steps__open img{display:block;width:100%;height:auto}
.th-steps__zoom{position:absolute;right:16px;bottom:16px;
  display:grid;place-items:center;width:38px;height:38px;border-radius:50%;
  border:1px solid var(--gold);background:rgba(4,12,18,.86);
  color:var(--gold-lt);font-size:17px;line-height:1;pointer-events:none}
.th-steps__flyer figcaption{margin-top:10px;text-align:center;
  font-size:12px;letter-spacing:.14em;text-transform:uppercase;color:var(--dim)}

/* Full size, and scrollable: it is a tall print piece on a short screen. */
.th-flyer-modal{max-width:min(1024px,96vw);padding:10px}
.th-flyer-modal img{display:block;width:100%;height:auto;
  max-height:86vh;object-fit:contain;margin:0 auto}

.th-steps{position:relative;display:grid;gap:clamp(16px,2.6vw,22px);
  grid-template-columns:repeat(auto-fit,minmax(272px,1fr))}
.th-step{position:relative;padding:clamp(22px,3.4vw,30px);border-radius:3px;
  border:1px solid var(--hair-soft);
  background:linear-gradient(180deg,rgba(11,27,39,.66),rgba(5,10,15,.86));
  transition:border-color .25s ease,transform .25s ease}
.th-step:hover{border-color:var(--hair);transform:translateY(-3px)}
.th-step__n{display:block;font-family:var(--display);font-size:11px;
  letter-spacing:.3em;color:var(--gold)}
.th-step h3{margin-top:12px;font-size:clamp(16px,3.2vw,20px);
  text-transform:uppercase;letter-spacing:.07em}
.th-step p{margin-top:11px;color:#C4BCAC;font-size:14.5px}
.th-step::after{content:"";position:absolute;left:0;top:0;width:2px;height:100%;
  background:linear-gradient(180deg,transparent,var(--gold),transparent);
  opacity:0;transition:opacity .25s ease}
.th-step:hover::after{opacity:.75}

/* ═══ THE HUNT DETAIL PAGE ═══════════════════════════════════════════════ */
.th-detail__hero{position:relative;isolation:isolate;overflow:hidden;
  padding:clamp(46px,8vw,96px) var(--pad) clamp(34px,5vw,56px);
  background:radial-gradient(120% 100% at 50% 0%,#0C2436,#050D15 62%,#03080D 100%)}
.th-detail__hero .th-hero__layer{z-index:-1}
.th-detail__in{position:relative;max-width:1180px;margin:0 auto}
.th-detail__title{margin-top:12px;font-size:clamp(28px,8vw,62px);
  text-transform:uppercase;letter-spacing:.04em;line-height:1.04;
  text-shadow:0 2px 36px rgba(0,0,0,.85)}
.th-detail__sub{margin-top:12px;font-family:var(--display);
  font-size:clamp(13px,2.6vw,18px);letter-spacing:.11em;
  text-transform:uppercase;color:var(--parch)}
.th-detail__chips{display:flex;flex-wrap:wrap;gap:9px;margin-top:20px}
.th-detail__facts{margin-top:clamp(24px,4vw,36px)}
.th-detail__cta{margin-top:clamp(24px,4vw,34px)}
.th-detail__in > .th-lead{margin-top:20px}

/* A standing "you are in" plate, rather than a button that does nothing. */
.th-enrolled{display:flex;align-items:center;gap:14px;padding:16px 20px;border-radius:3px;
  border:1px solid rgba(79,191,139,.4);background:var(--live-dim)}
.th-enrolled b{font-family:var(--display);font-size:clamp(14px,3vw,17px);
  letter-spacing:.14em;text-transform:uppercase;color:#B9EBD3}
.th-enrolled span{display:block;font-size:12.5px;color:#9FC5B4;letter-spacing:.03em}

/* ── the progress path ───────────────────────────────────────────────── */
.th-track{display:grid;gap:0}
.th-stage{position:relative;display:grid;grid-template-columns:44px 1fr;
  gap:16px;padding:0 0 clamp(18px,3vw,26px)}
.th-stage:last-child{padding-bottom:0}
/* The line that joins the stages stops at the last one rather than trailing
   off, which is the difference between a path and a decoration. */
.th-stage:not(:last-child)::before{content:"";position:absolute;
  left:21px;top:40px;bottom:-2px;width:2px;background:rgba(255,255,255,.1)}
.th-stage--complete:not(:last-child)::before{
  background:linear-gradient(180deg,var(--live),rgba(79,191,139,.25))}
.th-stage__dot{position:relative;width:44px;height:44px;display:grid;place-items:center;
  border-radius:50%;border:1px solid var(--hair-soft);background:#080F16;
  font-family:var(--display);font-size:14px;color:var(--dim)}
.th-stage--active .th-stage__dot{border-color:var(--gold);color:var(--gold-lt);
  box-shadow:0 0 0 5px rgba(200,155,60,.12),0 0 24px rgba(200,155,60,.35)}
.th-stage--complete .th-stage__dot{border-color:rgba(79,191,139,.6);color:var(--live);
  background:rgba(79,191,139,.1)}
.th-stage__body{padding-top:6px;min-width:0}
.th-stage__body b{display:block;font-family:var(--display);
  font-size:clamp(14px,2.8vw,17px);letter-spacing:.14em;text-transform:uppercase}
.th-stage--locked .th-stage__body b{color:var(--dim)}
.th-stage--active .th-stage__body b{color:var(--gold-lt)}
.th-stage--complete .th-stage__body b{color:#B9EBD3}
.th-stage__body span{display:block;margin-top:5px;font-size:13.5px;color:var(--dim)}
@media(min-width:900px){
  .th-track{grid-auto-flow:column;grid-auto-columns:1fr;gap:0}
  .th-stage{grid-template-columns:1fr;justify-items:center;text-align:center;
    gap:14px;padding:0 8px}
  .th-stage:not(:last-child)::before{left:calc(50% + 28px);right:-8px;top:21px;
    bottom:auto;width:auto;height:2px}
  .th-stage__body{padding-top:0}
}

/* ── the clue board ──────────────────────────────────────────────────── */
.th-clues{display:grid;gap:clamp(14px,2.4vw,20px)}
.th-clue{position:relative;overflow:hidden;border-radius:3px;
  padding:clamp(20px,3.6vw,30px);
  border:1px solid rgba(200,155,60,.3);
  background:
    linear-gradient(180deg,rgba(215,196,162,.95),rgba(196,175,139,.95)),
    url('/galveston/images/parchment-1500.webp') center/cover;
  background-blend-mode:multiply;
  color:var(--chart-ink);
  box-shadow:0 16px 40px rgba(0,0,0,.5),inset 0 0 40px rgba(120,92,48,.22)}
.th-clue__n{font-family:var(--display);font-size:11px;letter-spacing:.3em;
  text-transform:uppercase;color:#7A5C2C}
.th-clue h3{margin-top:9px;font-size:clamp(18px,3.8vw,24px);color:#2E2216;
  text-transform:uppercase;letter-spacing:.05em}
.th-clue__body{margin-top:14px;font-size:clamp(15.5px,2.4vw,18px);line-height:1.68;
  color:#3B2C1C;font-family:var(--display);font-weight:500}
.th-clue__time{margin-top:16px;padding-top:14px;border-top:1px solid rgba(74,58,40,.22);
  font-size:11px;letter-spacing:.16em;text-transform:uppercase;color:#7A5C2C}
.th-clue img{margin-top:18px;border-radius:2px;border:1px solid rgba(74,58,40,.3)}

.th-clue--locked{
  background:linear-gradient(180deg,rgba(11,27,39,.8),rgba(5,10,15,.9));
  border-color:var(--hair-soft);color:var(--dim);
  display:flex;align-items:center;gap:clamp(16px,3vw,24px);box-shadow:none}
.th-clue--locked .th-clue__n{color:var(--dim)}
.th-clue--locked b{display:block;font-family:var(--display);
  font-size:clamp(14px,3vw,18px);letter-spacing:.16em;text-transform:uppercase;
  color:var(--parch);margin-top:8px}
.th-clue--locked span{display:block;margin-top:6px;font-size:13px}

/* ── the final map ───────────────────────────────────────────────────── */
.th-final{position:relative;overflow:hidden;border-radius:3px;
  padding:clamp(24px,4.6vw,44px);
  border:1px solid rgba(200,155,60,.5);
  background:
    linear-gradient(180deg,rgba(219,201,167,.96),rgba(190,168,131,.96)),
    url('/galveston/images/parchment-1500.webp') center/cover;
  background-blend-mode:multiply;color:var(--chart-ink);
  box-shadow:0 30px 70px rgba(0,0,0,.6),inset 0 0 90px rgba(120,92,48,.3)}
.th-final__kicker{font-family:var(--display);font-size:10.5px;letter-spacing:.3em;
  text-transform:uppercase;color:#7A5C2C}
.th-final h2{margin-top:10px;font-size:clamp(24px,6vw,42px);color:#2A1F14;
  text-transform:uppercase;letter-spacing:.05em}
.th-final__riddle{margin-top:22px;padding:clamp(18px,3.4vw,26px);
  border-left:3px solid rgba(142,43,36,.7);background:rgba(255,255,255,.22);
  font-family:var(--display);font-size:clamp(16px,2.8vw,21px);line-height:1.6;color:#33261A}
.th-final__body{margin-top:20px;font-size:15.5px;line-height:1.7;color:#3B2C1C;
  white-space:pre-line}
.th-final__landmark{margin-top:20px;display:flex;gap:12px;align-items:flex-start;
  font-size:15px;color:#3B2C1C}
.th-final__landmark b{font-family:var(--display);letter-spacing:.1em;
  text-transform:uppercase;font-size:11px;color:#7A5C2C;flex:none;padding-top:3px}
.th-final img{margin-top:22px;border-radius:2px;border:1px solid rgba(74,58,40,.4);
  box-shadow:0 12px 30px rgba(0,0,0,.35)}

.th-locked{display:flex;flex-direction:column;align-items:center;text-align:center;
  gap:16px;padding:clamp(28px,5vw,48px);border-radius:3px;
  border:1px dashed var(--hair-soft);background:rgba(11,27,39,.4)}
.th-locked b{font-family:var(--display);font-size:clamp(15px,3.2vw,20px);
  letter-spacing:.16em;text-transform:uppercase;color:var(--parch)}
.th-locked p{max-width:44ch;color:var(--dim);font-size:14.5px}

/* ── code entry ──────────────────────────────────────────────────────── */
.th-form{max-width:460px}
.th-field{margin:18px 0}
.th-field label{display:block;margin-bottom:8px;font-size:10.5px;
  letter-spacing:.2em;text-transform:uppercase;color:var(--parch)}
.th-field input{width:100%;min-height:58px;padding:0 16px;
  border:1px solid var(--hair);border-radius:2px;background:#050A0F;
  color:var(--cream);font-family:var(--display);
  /* 16px minimum, or iOS zooms the whole page on focus — which at a festival
     loses the person their place on it. */
  font-size:19px;letter-spacing:.16em;text-transform:uppercase}
.th-field input::placeholder{color:#4A5560;letter-spacing:.1em}
.th-field input:focus{border-color:var(--gold);outline:none;
  box-shadow:0 0 0 4px rgba(200,155,60,.12)}
.th-field input[aria-invalid="true"]{border-color:#A95747}
.th-note{margin-top:12px;font-size:13px;color:var(--dim)}
.th-note a{color:var(--parch)}
.th-err{margin-top:12px;padding:12px 14px;border-radius:2px;font-size:14px;
  color:#E8A79E;border:1px solid rgba(180,69,58,.45);background:rgba(142,43,36,.16)}
.th-ok{margin-top:12px;padding:12px 14px;border-radius:2px;font-size:14px;
  color:#B9EBD3;border:1px solid rgba(79,191,139,.4);background:var(--live-dim)}

/* ── the key landing ─────────────────────────────────────────────────── */
.th-key{min-height:74svh;display:grid;place-items:center;
  padding:clamp(32px,6vw,72px) var(--pad);text-align:center}
.th-key__in{max-width:560px;width:100%}
.th-key__art{width:clamp(96px,26vw,150px);margin:0 auto clamp(20px,4vw,30px)}
.th-key__art svg{width:100%;height:auto;filter:drop-shadow(0 0 34px rgba(200,155,60,.45))}
.th-key h1{font-size:clamp(28px,8.4vw,54px);text-transform:uppercase;letter-spacing:.05em}
.th-key__lead{margin:16px auto 0;max-width:38ch;font-size:clamp(15px,2.4vw,18px);color:#CFC7B6}
.th-key .th-form{margin:26px auto 0;text-align:left}

/* ── the winner ──────────────────────────────────────────────────────── */
.th-winner{position:relative;overflow:hidden;border-radius:3px;
  padding:clamp(28px,5.4vw,56px) clamp(22px,4.4vw,48px);text-align:center;
  border:1px solid rgba(200,155,60,.5);
  background:
    radial-gradient(90% 120% at 50% -10%,rgba(200,155,60,.2),transparent 62%),
    linear-gradient(180deg,#0E2233,#050B11 78%);
  box-shadow:0 30px 80px rgba(0,0,0,.6),inset 0 1px 0 rgba(255,236,196,.12)}
.th-winner__kicker{font-family:var(--display);font-size:10.5px;letter-spacing:.34em;
  text-transform:uppercase;color:var(--gold)}
.th-winner h2{margin-top:14px;font-size:clamp(28px,9vw,64px);
  text-transform:uppercase;letter-spacing:.06em;color:var(--gold-lt);
  text-shadow:0 0 60px rgba(200,155,60,.4)}
.th-winner__photo{width:clamp(110px,26vw,164px);aspect-ratio:1;
  margin:clamp(22px,4vw,32px) auto 0;border-radius:50%;overflow:hidden;
  border:2px solid var(--gold);
  box-shadow:0 0 0 7px rgba(200,155,60,.12),0 18px 40px rgba(0,0,0,.6)}
.th-winner__photo img{width:100%;height:100%;object-fit:cover}
.th-winner__name{margin-top:18px;font-family:var(--display);
  font-size:clamp(20px,5vw,32px);letter-spacing:.05em;color:var(--cream)}
.th-winner__ach{margin-top:10px;font-size:11px;letter-spacing:.22em;
  text-transform:uppercase;color:var(--parch)}
.th-winner__story{margin:22px auto 0;max-width:56ch;color:#CFC7B6;
  font-size:15px;white-space:pre-line}
.th-winner .th-facts{margin-top:clamp(24px,4vw,34px);text-align:left}

/* ── the leaderboard ─────────────────────────────────────────────────── */
.th-board-list{display:grid;gap:8px}
.th-rank{display:grid;grid-template-columns:44px 1fr auto;gap:14px;align-items:center;
  padding:12px 16px;border-radius:3px;border:1px solid var(--hair-soft);
  background:rgba(8,16,23,.7)}
.th-rank--top{border-color:var(--hair);background:rgba(200,155,60,.08)}
.th-rank__n{font-family:var(--display);font-size:17px;color:var(--parch);
  text-align:center;font-variant-numeric:tabular-nums}
.th-rank--top .th-rank__n{color:var(--gold-lt)}
.th-rank__who{display:flex;align-items:center;gap:11px;min-width:0}
.th-rank__who img{width:34px;height:34px;border-radius:50%;object-fit:cover;flex:none;
  border:1px solid var(--hair-soft)}
.th-rank__who b{display:block;font-size:14.5px;font-family:inherit;font-weight:500;
  color:var(--cream);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.th-rank__who a{color:inherit;text-decoration:none}
.th-rank__who a:hover{color:var(--gold-lt)}
.th-rank__marks{display:flex;gap:5px;margin-top:2px}
.th-rank__marks span{font-size:9px;letter-spacing:.14em;text-transform:uppercase;
  padding:2px 6px;border-radius:2px;color:var(--parch);border:1px solid var(--hair-soft)}
.th-rank__score{font-family:var(--display);font-size:16px;color:var(--gold-lt);
  font-variant-numeric:tabular-nums}

/* ── legends of the tide, and what is coming ─────────────────────────── */
.th-grid{display:grid;gap:clamp(16px,2.6vw,24px);
  grid-template-columns:repeat(auto-fit,minmax(288px,1fr))}
.th-tile{position:relative;overflow:hidden;border-radius:3px;
  border:1px solid var(--hair-soft);background:rgba(7,15,22,.8);
  display:flex;flex-direction:column;
  transition:border-color .25s ease,transform .25s ease}
.th-tile:hover{border-color:var(--hair);transform:translateY(-3px)}
.th-tile__art{position:relative;aspect-ratio:16/9;background:#061019;overflow:hidden}
.th-tile__art img{width:100%;height:100%;object-fit:cover;opacity:.72}
.th-tile__art::after{content:"";position:absolute;inset:0;
  background:linear-gradient(180deg,transparent 40%,rgba(7,15,22,.95))}
.th-tile__in{padding:clamp(18px,3vw,24px);flex:1;display:flex;flex-direction:column}
.th-tile__in h3{font-size:clamp(17px,3.4vw,21px);text-transform:uppercase;letter-spacing:.05em}
.th-tile__where{margin-top:7px;font-size:12px;letter-spacing:.1em;
  text-transform:uppercase;color:var(--parch)}
.th-tile__note{margin-top:13px;color:var(--dim);font-size:14px;flex:1}
.th-tile .th-btn,.th-tile .th-chip{margin-top:18px;align-self:flex-start}

/* Coming soon. Fogged over, and the fog is the message. */
.th-tile--soon .th-tile__art{
  background:radial-gradient(110% 90% at 50% 20%,#122636,#060D14 72%)}
.th-tile--soon .th-tile__art::before{content:"";position:absolute;inset:-30%;
  background:radial-gradient(circle at 40% 55%,rgba(160,186,202,.16),transparent 62%),
             radial-gradient(circle at 70% 40%,rgba(120,150,172,.12),transparent 60%);
  filter:blur(22px);animation:th-drift-a 70s linear infinite}
.th-tile--soon .th-tile__mark{position:absolute;inset:0;display:grid;place-items:center;z-index:1}
.th-tile--soon .th-tile__mark svg{width:56px;height:56px;opacity:.5}
/* Once a port has its painting, the fog thins to a haze over it rather than
   hiding it — still "not yet", but you can see where you are going. */
.th-tile--soon.has-art .th-tile__art{background:#060D14}
.th-tile--soon.has-art .th-tile__art::before{opacity:.3}
.th-tile--soon.has-art .th-tile__art img{opacity:.92}
.th-tile--soon.has-art:hover .th-tile__art img{opacity:1}

/* ── rules and safety ────────────────────────────────────────────────── */
.th-articles{display:grid;gap:clamp(16px,2.6vw,24px);
  grid-template-columns:repeat(auto-fit,minmax(300px,1fr))}
.th-article{padding:clamp(22px,3.6vw,32px);border-radius:3px;
  border:1px solid var(--hair-soft);background:rgba(8,16,23,.6)}
.th-article h3{font-size:clamp(15px,3vw,19px);text-transform:uppercase;
  letter-spacing:.14em;color:var(--parch)}
.th-article__body{margin-top:16px;white-space:pre-line;font-size:14.5px;
  line-height:1.72;color:#C4BCAC}
.th-article--warn{border-color:rgba(180,69,58,.3);background:rgba(142,43,36,.07)}
.th-article--warn h3{color:#E8A79E}

/* ── page states ─────────────────────────────────────────────────────── */
.th-state{min-height:60svh;display:grid;place-items:center;text-align:center;
  padding:clamp(40px,8vw,90px) var(--pad)}
.th-state h1{font-size:clamp(22px,5.4vw,34px);text-transform:uppercase;letter-spacing:.05em}
.th-state p{margin-top:14px;color:var(--dim);max-width:46ch}
.th-state .th-btn{margin-top:26px}
.th-empty{padding:34px 20px;border:1px dashed var(--hair-soft);border-radius:3px;
  text-align:center;color:var(--dim);background:rgba(11,27,39,.34)}

/* The reveal. Sections lift into place once, on first sight. Anything not yet
   observed is still fully readable — `.is-in` is added by the observer, and
   the fallbacks below cover no-JS and no-IntersectionObserver alike. A reveal
   that never fires is a blank page, which is far worse than no animation. */
.th-reveal{opacity:0;transform:translateY(22px);
  transition:opacity .7s ease,transform .7s cubic-bezier(.2,.7,.3,1)}
.th-reveal.is-in{opacity:1;transform:none}
.no-js .th-reveal,.th-no-observer .th-reveal{opacity:1;transform:none}

@media(prefers-reduced-motion:reduce){
  .th-body *,.th-body *::before,.th-body *::after{
    animation:none!important;transition:none!important}
  .th-reveal{opacity:1!important;transform:none!important}
  .th-btn:hover,.th-tile:hover,.th-step:hover,.th-port:hover{transform:none!important}
}

/* ── a map fragment has been scanned ────────────────────────────────────
   /treasure-hunts/map. It borrows the key landing's frame (.th-key) and adds
   the one thing that page never needed: a clue, printed large, as the payoff
   of the whole afternoon. Nothing competes with it. */
.thm-scan .th-key__art{opacity:.9}

.thm-clue{margin:26px auto 0;max-width:34em;padding:clamp(20px,5vw,34px);
  text-align:left;
  background:linear-gradient(180deg,rgba(215,183,122,.97),rgba(190,159,104,.97));
  border:1px solid rgba(74,58,40,.5);
  box-shadow:0 20px 56px rgba(0,0,0,.5),inset 0 1px 0 rgba(255,255,255,.22)}
.thm-clue__num{font-family:var(--display);font-weight:600;
  font-size:11.5px;letter-spacing:.24em;text-transform:uppercase;
  color:rgba(59,44,28,.72)}
.thm-clue h2{margin-top:8px;font-size:clamp(19px,4.6vw,26px);color:#2F2417;
  letter-spacing:.02em}
/* 17px, not 15px: this is read outdoors, in sunlight, at arm's length, by
   somebody who is about to walk somewhere because of what it says. */
.thm-clue__body{margin-top:14px}
.thm-clue__body p{margin:0 0 12px;font-size:clamp(16px,4vw,18px);line-height:1.66;
  color:#2A2014}
.thm-clue__body p:last-child{margin-bottom:0}
.thm-clue__art{margin-top:16px;width:100%;height:auto;
  border:1px solid rgba(74,58,40,.4)}

/* Five marks (or eleven) filling in as the hunt is walked. Drawn, not
   imported: a row of small brass discs that light when held. */
.thm-marks{display:flex;flex-wrap:wrap;align-items:center;justify-content:center;
  gap:7px;margin:20px auto 0}
.thm-marks i{display:block;width:13px;height:13px;border-radius:50%;
  border:1px solid var(--hair);background:rgba(4,12,18,.7)}
.thm-marks i.is-held{background:linear-gradient(180deg,var(--gold-lt),var(--gold-dk));
  border-color:rgba(255,235,190,.6);box-shadow:0 0 10px rgba(200,155,60,.45)}
.thm-marks span{width:100%;margin-top:6px;font-size:11px;letter-spacing:.18em;
  text-transform:uppercase;color:var(--dim)}

/* ── the code box on the hunt page ──────────────────────────────────────
   A hunter standing at a window, holding their phone up to read a sticker,
   should not have to navigate anywhere to use what they just read. Sits
   directly above the clue board, which is where they are already looking. */
.th-codebox{margin:0 0 22px;padding:clamp(16px,3.6vw,24px);
  border:1px solid var(--hair);background:rgba(200,155,60,.07)}
.th-codebox__head b{display:block;font-family:var(--display);font-weight:600;
  font-size:clamp(15px,3.6vw,18px);letter-spacing:.05em;color:var(--gold-lt)}
.th-codebox__head span{display:block;margin-top:4px;font-size:14px;color:var(--dim)}
.th-codebox__row{display:flex;flex-wrap:wrap;gap:10px;margin-top:14px}
/* 16px so iOS does not zoom the viewport the moment it is focused — which,
   on this page, would throw the clue board off screen mid-type. */
.th-codebox__row input{flex:1 1 200px;min-width:0;min-height:54px;
  padding:14px 16px;font:inherit;font-size:16px;letter-spacing:.1em;
  text-transform:uppercase;color:var(--cream);
  background:rgba(4,12,18,.92);border:1px solid var(--hair-soft);border-radius:0}
.th-codebox__row input::placeholder{text-transform:none;letter-spacing:.02em;color:#5C6971}
.th-codebox__row input:focus{border-color:var(--gold);outline:none}
.th-codebox__row input:focus-visible{outline:2px solid var(--gold-lt);outline-offset:2px}
.th-codebox__row button{flex:0 0 auto;min-height:54px;padding:0 26px}
.th-codebox__note{margin-top:10px;font-size:13.5px;line-height:1.5;color:var(--dim)}
@media (max-width:460px){ .th-codebox__row button{flex:1 1 100%} }

/* ── the pre-register flyer ─────────────────────────────────────────────
   A printed poster dropped flat onto a web page looks like a screenshot. It
   reads as an object when it has an edge, a shadow and a degree of tilt — so
   it gets all three, and a brass pin at the top. The tilt is one degree, not
   three: enough to say "pinned", not enough to look like a mistake. */
.th-poster__in{display:grid;gap:clamp(22px,4.5vw,48px);align-items:center}
@media (min-width:880px){
  .th-poster__in{grid-template-columns:minmax(0,.85fr) minmax(0,1fr)}
}

.th-poster__pin{margin:0;justify-self:center;position:relative;
  width:min(420px,100%);transform:rotate(-1deg);
  transition:transform .4s var(--ease, ease)}
.th-poster__pin img{display:block;width:100%;height:auto;
  border:1px solid rgba(200,155,60,.4);
  box-shadow:0 26px 60px rgba(0,0,0,.6),0 3px 10px rgba(0,0,0,.5)}
.th-poster__pin::before{content:'';position:absolute;top:-9px;left:50%;
  width:16px;height:16px;margin-left:-8px;border-radius:50%;
  background:radial-gradient(circle at 34% 30%,var(--gold-lt),var(--gold-dk) 68%,#3A2A0E);
  box-shadow:0 3px 7px rgba(0,0,0,.65);z-index:1}
@media (hover:hover){ .th-poster__pin:hover{transform:rotate(0deg)} }
@media (prefers-reduced-motion:reduce){
  .th-poster__pin{transform:none;transition:none}
}

.th-poster__say h2{margin-top:10px;font-size:clamp(22px,5vw,34px);color:var(--gold-lt)}
.th-poster__say p{margin-top:14px;font-size:clamp(15px,3.6vw,17px);
  line-height:1.66;color:var(--cream);max-width:34em}
.th-poster__say .th-btn{margin-top:22px}
.th-poster__say .th-note{margin-top:12px}
