/**
 * LEYAN'S REALM — the quest-map visual system.
 *
 * Realm-wide styling: the parchment, the ink, the wax, the islands. Apps may reuse
 * these variables and the .realm-btn / .realm-panel pieces so every island feels like
 * part of the same map. Nothing in here is specific to any one app.
 *
 * Everything is drawn with CSS and inline SVG. No images, no web fonts, no CDN —
 * the whole Realm must load from a static folder with the wifi switched off.
 */

:root {
  --parchment: #e9d7ae;
  --parchment-lit: #f6ead0;
  --parchment-dark: #cfb384;
  --ink: #2b1d0e;
  --ink-soft: #6b5330;
  --ink-faint: rgba(43, 29, 14, 0.35);
  --gold: #c9962e;
  --gold-deep: #8f6516;
  --sea: #9db79f;
  --wax: #9d2b2b;
  --wax-dark: #6f1a1a;
  --mist: rgba(247, 242, 228, 0.6); /* warm fog — a cold grey fog turns the map into a hospital */
  /* Ink seen through fog. Measured, not eyeballed: 4.9:1 on the darkest part of a locked
     island and 7.8:1 on the lightest, so the "???" and the fog blurbs clear AA (4.5:1)
     everywhere on a bright iPad screen. The old #7a6a4c was 2.6–4.1:1 — unreadable. */
  --locked: #4f4126;
  --leather: #241a10;
}

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

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

body {
  min-height: 100dvh;
  padding: clamp(0.5rem, 2.5vw, 2rem);
  font-family: 'Iowan Old Style', 'Palatino Linotype', Palatino, 'Book Antiqua', Georgia, serif;
  color: var(--ink);
  /* The desk the map lies on: old leather, lit from above. */
  background-color: var(--leather);
  background-image:
    radial-gradient(ellipse at 50% 0%, rgba(196, 155, 92, 0.28), transparent 62%),
    repeating-linear-gradient(45deg, rgba(0, 0, 0, 0.16) 0 3px, transparent 3px 7px);
  overflow-x: hidden;
}

/* ── The map sheet ───────────────────────────────────────────────────────────
   .map-sheet carries the shadow (a clip-path would cut a box-shadow off, so the
   shadow lives on a wrapper as a drop-shadow filter), .map carries the torn edge. */

.map-sheet {
  max-width: 1080px;
  margin: 0 auto;
  filter: drop-shadow(0 14px 26px rgba(0, 0, 0, 0.55));
}

.map {
  position: relative;
  overflow: hidden; /* the compass and the sea routes must never push the page sideways */
  padding: clamp(1.5rem, 5vw, 3.5rem) clamp(1rem, 4vw, 3rem) clamp(2rem, 5vw, 3rem);
  background-color: var(--parchment);
  /* Aged parchment: foxing blotches, a lit centre, and paper fibres — all gradients. */
  background-image:
    radial-gradient(ellipse at 18% 12%, rgba(150, 108, 48, 0.22), transparent 45%),
    radial-gradient(ellipse at 88% 78%, rgba(132, 94, 42, 0.24), transparent 42%),
    radial-gradient(circle at 72% 18%, rgba(120, 84, 36, 0.16), transparent 28%),
    radial-gradient(circle at 12% 84%, rgba(120, 84, 36, 0.14), transparent 26%),
    radial-gradient(ellipse at 50% 45%, rgba(255, 248, 226, 0.55), transparent 68%),
    repeating-linear-gradient(102deg, rgba(120, 90, 40, 0.045) 0 2px, transparent 2px 6px),
    repeating-linear-gradient(6deg, rgba(120, 90, 40, 0.035) 0 2px, transparent 2px 7px);
  /* Torn, hand-cut edges. Deterministic jitter, not a straight-cut rectangle. */
  clip-path: polygon(
    0.6% 1.2%, 12% 0.4%, 26% 1.4%, 38% 0.3%, 52% 1.5%, 66% 0.5%, 79% 1.6%, 91% 0.6%, 99.4% 1.4%,
    99% 14%, 99.6% 28%, 98.8% 42%, 99.5% 56%, 98.9% 71%, 99.6% 86%, 99% 98.6%,
    88% 99.5%, 74% 98.5%, 61% 99.6%, 47% 98.6%, 33% 99.6%, 20% 98.7%, 7% 99.5%, 0.5% 98.6%,
    1.1% 85%, 0.4% 70%, 1.2% 55%, 0.3% 40%, 1.1% 26%, 0.4% 13%
  );
}

/* The double rule a cartographer inks around the edge of a chart. */
.map::before {
  content: '';
  position: absolute;
  inset: clamp(0.5rem, 2vw, 1.1rem);
  border: 2px solid var(--ink-faint);
  border-radius: 6px 18px 8px 14px / 14px 6px 16px 8px;
  box-shadow: inset 0 0 0 4px transparent, inset 0 0 0 5px rgba(43, 29, 14, 0.18);
  pointer-events: none;
}

/* ── Header ─────────────────────────────────────────────────────────────── */

.realm-header {
  position: relative;
  z-index: 1;
  text-align: center;
  margin-bottom: clamp(1.2rem, 4vw, 2rem);
}

.realm-title {
  font-size: clamp(2rem, 9.5vw, 4.6rem);
  line-height: 1.02;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  overflow-wrap: break-word;
  color: var(--ink);
  text-shadow:
    1px 1px 0 var(--parchment-lit),
    3px 3px 0 rgba(139, 105, 48, 0.28),
    5px 6px 10px rgba(43, 29, 14, 0.18);
}

.realm-subtitle {
  margin-top: 0.6rem;
  font-style: italic;
  font-size: clamp(1.05rem, 3.6vw, 1.45rem);
  color: var(--ink-soft);
}

/* A ruled line with a diamond in the middle, like a map's title cartouche. */
.realm-rule {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.7rem;
  width: min(440px, 90%);
  margin: 1rem auto 0;
}

.realm-rule::before,
.realm-rule::after {
  content: '';
  flex: 1;
  height: 2px;
  background: linear-gradient(90deg, transparent, var(--gold-deep), transparent);
}

.realm-rule span {
  width: 9px;
  height: 9px;
  transform: rotate(45deg);
  background: var(--gold-deep);
}

/* ── Compass rose (inline SVG, decorative) ──────────────────────────────── */

.compass {
  position: absolute;
  right: clamp(0.75rem, 3vw, 2rem);
  bottom: clamp(0.75rem, 3vw, 2rem);
  width: clamp(64px, 14vw, 130px);
  height: auto;
  color: var(--ink);
  opacity: 0.4;
  pointer-events: none;
}

/* ── Sign-in panel ──────────────────────────────────────────────────────── */

.realm-panel {
  position: relative;
  z-index: 1;
  max-width: 500px;
  margin: 0 auto clamp(1.75rem, 5vw, 2.75rem);
  padding: clamp(1rem, 4vw, 1.5rem);
  border: 2px solid var(--ink-soft);
  border-radius: 10px 4px 12px 5px / 5px 12px 4px 10px;
  background: rgba(255, 250, 235, 0.62);
  box-shadow: 0 6px 0 rgba(90, 65, 30, 0.18), inset 0 0 24px rgba(160, 120, 60, 0.12);
  text-align: center;
}

.realm-panel__lead {
  font-size: 1.05rem;
  line-height: 1.45;
}

.realm-panel__lead strong { letter-spacing: 0.02em; }

.realm-panel__hint {
  margin-top: 0.35rem;
  font-size: 0.95rem;
  font-style: italic;
  color: var(--ink-soft);
}

.realm-form {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  justify-content: center;
  margin-top: 0.9rem;
}

.realm-form label {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.2rem;
  flex: 1 1 8.5rem;
  min-width: 0;
  font-size: 0.8rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

.realm-form input {
  width: 100%;
  min-height: 48px; /* a thumb, not a mouse pointer */
  padding: 0.55rem 0.75rem;
  font: inherit;
  font-size: 1.05rem; /* never below 1rem: iOS Safari zooms the page in on smaller inputs */
  letter-spacing: 0.02em;
  color: var(--ink);
  background: #fffaf0;
  border: 2px solid var(--ink-soft);
  border-radius: 7px;
}

.realm-form input:focus-visible {
  outline: 3px solid var(--gold);
  outline-offset: 1px;
}

#pin { letter-spacing: 0.35em; }

.realm-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 48px;
  padding: 0.6rem 1.4rem;
  font: inherit;
  font-size: 1.05rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  color: var(--ink);
  cursor: pointer;
  background: linear-gradient(180deg, #e2b653, var(--gold) 55%, var(--gold-deep));
  border: 2px solid var(--ink);
  border-radius: 7px;
  box-shadow: 0 4px 0 rgba(90, 65, 30, 0.55);
  transition: transform 0.12s ease, box-shadow 0.12s ease;
}

.realm-btn--enter { align-self: flex-end; flex: 0 0 auto; }
.realm-btn--quiet {
  margin-top: 0.6rem;
  background: transparent;
  border-color: var(--ink-soft);
  box-shadow: none;
  font-weight: 400;
  font-size: 0.95rem;
}

.realm-btn:active { transform: translateY(3px); box-shadow: 0 1px 0 rgba(90, 65, 30, 0.55); }
.realm-btn[disabled] { opacity: 0.6; cursor: progress; }
.realm-btn:focus-visible { outline: 3px solid var(--ink); outline-offset: 2px; }

.realm-error {
  margin-top: 0.7rem;
  min-height: 1.3em;
  font-weight: 700;
  color: var(--wax-dark);
}

/* Quiet asides: "unrolling the map…" while the sign-in module is still on its way, and
   "this iPad will not remember you" when the browser has storage switched off. */
.realm-note {
  margin-top: 0.6rem;
  font-size: 0.92rem;
  font-style: italic;
  color: var(--ink-soft);
}

.realm-note--warn { font-style: normal; color: var(--wax-dark); }

.realm-welcome { font-size: 1.15rem; }
.realm-welcome strong { text-transform: capitalize; letter-spacing: 0.03em; }
.realm-welcome__sub {
  margin-top: 0.3rem;
  font-style: italic;
  color: var(--ink-soft);
}

/* ── Wax seal (pressed into the panel's corner) ─────────────────────────── */

.seal {
  position: absolute;
  top: -14px;
  right: -10px;
  display: grid;
  place-items: center;
  width: 58px;
  height: 58px;
  font-size: 1.5rem;
  font-weight: 700;
  color: rgba(255, 226, 200, 0.85);
  background: radial-gradient(circle at 34% 30%, #c34a4a, var(--wax) 45%, var(--wax-dark) 100%);
  /* A blob of wax, squeezed out unevenly under the stamp. */
  clip-path: polygon(
    50% 0%, 66% 6%, 80% 4%, 90% 16%, 98% 30%, 95% 46%, 100% 60%, 90% 74%, 84% 88%,
    68% 92%, 54% 100%, 40% 93%, 24% 95%, 12% 84%, 4% 70%, 8% 54%, 0% 40%, 10% 26%,
    16% 10%, 34% 8%
  );
  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.45);
  transform: rotate(-8deg);
}

/* ── Islands ────────────────────────────────────────────────────────────── */

/* ── The sea ─────────────────────────────────────────────────────────────────
   Water, not more parchment. The whole page is one aged chart, so the sea is NOT
   blue — it is the same paper gone cold and deep: a grey-green wash laid over the
   parchment, then engraved. Two layers do the engraving, the way a copperplate
   engraver fills water:
     ::before  fine diagonal hatching, close-ruled, the standard "this is water" fill
     ::after   scalloped wave rules — rows of little arcs, offset row to row
   The land is drawn on top of both (each island's own SVG), so the hatching stops
   dead at every coastline and the islands genuinely sit ON the water. */

.sea {
  position: relative;
  z-index: 1;
  margin-top: clamp(1.25rem, 3.5vw, 2rem);
  padding: clamp(0.75rem, 3vw, 1.5rem) 0;
}

.sea::before,
.sea::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  /* A bay with a soft, hand-cut edge, not a rectangle of water. */
  clip-path: polygon(
    2% 3%, 16% 0.8%, 31% 2.6%, 45% 0.6%, 60% 2.4%, 74% 0.5%, 88% 2.8%, 98.5% 1.2%,
    99.4% 15%, 98.2% 30%, 99.5% 46%, 98.4% 62%, 99.6% 78%, 98.6% 92%, 97% 98.4%,
    85% 99.4%, 71% 97.6%, 57% 99.5%, 42% 97.8%, 28% 99.6%, 14% 98%, 1.6% 99%,
    0.6% 84%, 1.8% 68%, 0.5% 52%, 1.6% 36%, 0.4% 20%
  );
}

/* The water itself: colder and deeper than the land, plus close-ruled hatching. */
.sea::before {
  background-color: rgba(96, 116, 104, 0.34);
  background-image:
    repeating-linear-gradient(-14deg, rgba(26, 38, 30, 0.13) 0 1px, transparent 1px 4px),
    repeating-linear-gradient(74deg, rgba(26, 38, 30, 0.06) 0 1px, transparent 1px 7px),
    radial-gradient(ellipse at 50% 40%, rgba(255, 250, 235, 0.08), transparent 72%);
  box-shadow: inset 0 0 34px rgba(35, 50, 42, 0.28);
}

/* Scalloped wave rules: rows of little arcs, every other row shunted half a step,
   so the water ripples instead of gridding. Small and faint — the hatching is the
   voice here, the scallops are only the accent. */
.sea::after {
  background-image:
    radial-gradient(circle at 50% 100%, transparent 4.6px, rgba(28, 40, 30, 0.9) 4.6px 5.5px, transparent 5.6px),
    radial-gradient(circle at 50% 100%, transparent 4.6px, rgba(28, 40, 30, 0.9) 4.6px 5.5px, transparent 5.6px);
  background-size: 20px 11px, 20px 11px;
  background-position: 0 0, 10px 5.5px;
  opacity: 0.2;
}

.islands {
  position: relative;
  z-index: 1; /* the land floats on the water, never under the hatching */
  display: grid;
  gap: clamp(1.25rem, 4vw, 2.25rem);
  grid-template-columns: 1fr; /* one island per row on a phone: nothing to squeeze, nothing to overflow */
  padding: 0 clamp(0.25rem, 2vw, 1rem);
}

/* An archipelago, not a spreadsheet: two columns, and the right-hand islands ride
   lower than the left-hand ones, the way islands actually scatter across a chart. */
@media (min-width: 720px) {
  .islands { grid-template-columns: repeat(2, 1fr); }
  .islands .island:nth-child(2n) { margin-top: clamp(1.5rem, 4vw, 3rem); }
}

/* ── Islands ────────────────────────────────────────────────────────────────
   The box holds the words; the SVG underneath holds the land. The box itself has NO
   background and NO border — every edge you can see is an inked coastline. */

.island {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.35rem;
  min-height: clamp(260px, 24vw, 300px);
  /* An island is not a banner. Left to fill a wide column it stretches into a squat
     sausage; capped, it stays island-shaped and the extra room becomes open water. */
  width: 100%;
  max-width: 430px;
  margin-inline: auto;
  /* Roomy enough that a bay in the coastline never bites into a word: the coast can
     wander ±10%, and the text stops well short of where even the deepest bay reaches. */
  padding: clamp(2rem, 6vw, 2.6rem) clamp(1.75rem, 6vw, 2.6rem);
  text-align: center;
  text-decoration: none;
  color: inherit;
  transition: transform 0.18s ease;
}

/* Each island tilts a hair — nobody pastes islands onto a chart perfectly square. */
.island:nth-child(1) { transform: rotate(-1deg); }
.island:nth-child(2) { transform: rotate(1.5deg); }
.island:nth-child(3) { transform: rotate(-1.5deg); }
.island:nth-child(4) { transform: rotate(1deg); }

/* The landmass. Stretched to the island's box (preserveAspectRatio="none") and bled a
   little past it, so the depth rings have water to sit in. */
.island__land {
  position: absolute;
  inset: -14px;
  width: calc(100% + 28px);
  height: calc(100% + 28px);
  overflow: visible;
  pointer-events: none;
}

/* Everything the child reads stands ON the land, above it in the stack. */
.island > *:not(.island__land) { position: relative; z-index: 1; }

/* Depth soundings: two faint rings echoing the coast out into the water. */
.island__ring {
  fill: none;
  stroke: rgba(43, 29, 14, 0.30);
  stroke-width: 1.6;
  stroke-dasharray: 5 4;
  vector-effect: non-scaling-stroke;
}

.island__ring--far {
  stroke: rgba(43, 29, 14, 0.16);
  stroke-width: 1.2;
  stroke-dasharray: 3 6;
}

/* The land's own shadow, cast on the water. */
.island__shadow { fill: rgba(48, 60, 46, 0.34); }

/* The beach: the whole landmass in pale sand. The interior is then drawn a touch
   smaller on top of it, which leaves a shore all the way round the coast, following
   every bay — no border-radius could do that. */
.island__shelf { fill: #f3e6c6; }
.island__inner { fill: url(#g-land); }

/* The coastline. A pen line, the same weight however the box is stretched. */
.island__coast {
  fill: none;
  stroke: var(--ink);
  stroke-width: 2.6;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}

/* Under fog the land is dimmer and the pen line softer — but BOTH are still there. That
   is the difference between "an island you cannot reach yet" and "a hole in the map". */
/* Hills, half-seen through the weather. This is the whole promise of a locked island:
   there IS something on it. They are inked in the empty corners of the land — the words
   sit in the middle — and the fog then rolls over them. */
.island__terrain {
  fill: none;
  stroke: rgba(43, 29, 14, 0.5);
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.island__terrain path { vector-effect: non-scaling-stroke; }

.island--locked .island__shelf { fill: #e4d6b4; }
.island--locked .island__inner { fill: url(#g-land-fog); }
.island--locked .island__coast { stroke: rgba(43, 29, 14, 0.72); stroke-width: 2.2; }
.island--locked .island__ring { stroke: rgba(43, 29, 14, 0.2); }
.island--locked .island__ring--far { stroke: rgba(43, 29, 14, 0.1); }
.island--locked .island__shadow { fill: rgba(48, 60, 46, 0.2); }

.island--open:hover,
.island--open:focus-visible {
  transform: translateY(-6px) rotate(-1deg);
  outline: none;
}

.island--open:hover .island__inner,
.island--open:focus-visible .island__inner { fill: #fbf1dc; }

.island--open:focus-visible .island__coast { stroke: var(--gold-deep); stroke-width: 4; }

.island__icon {
  width: clamp(44px, 11vw, 60px);
  height: clamp(44px, 11vw, 60px);
  color: var(--ink);
}

.island__name {
  font-size: clamp(1.25rem, 4.5vw, 1.7rem);
  letter-spacing: 0.03em;
}

.island__blurb {
  font-size: clamp(0.92rem, 3vw, 1.02rem);
  line-height: 1.4;
  /* NOT --ink-soft. Measured on the rendered page: --ink-soft on the worn outer land of
     an island is 4.40:1 — under AA. This ink is 5.4:1 on the darkest land and still reads
     as a quiet aside next to the black of the island's name. */
  color: #5b4526;
  max-width: 20ch;
}

/* A little wax ribbon stamped on the open island. */
.island__flag {
  position: absolute;
  top: 14px;
  padding: 0.3rem 0.85rem;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: #ffe9c9;
  background: linear-gradient(180deg, #b83a3a, var(--wax-dark));
  border-radius: 999px;
  box-shadow: 0 3px 0 rgba(0, 0, 0, 0.3);
  transform: rotate(-3deg);
}

/* ── Fog ────────────────────────────────────────────────────────────────────
   A locked island is LAND, seen through weather. Not a hole in the map, not a
   disabled control. Its coastline, its beach and its interior are all drawn exactly
   like the open island's — then fog drifts across it. You can still see the shape of
   the place; you just cannot make out what is on it. That is the whole invitation. */

.island--locked { color: var(--locked); }

/* The fog bank: OVER the land (so the shore is only half-there) but UNDER the words —
   text read through a blur is just text nobody can read. Banks, not a flat wash: it
   piles up bottom-left and thins out towards the top, so a headland stays visible. */
.island--locked::after {
  content: '';
  position: absolute;
  inset: -18px;
  background:
    radial-gradient(ellipse 58% 40% at 22% 76%, rgba(250, 247, 238, 0.72), transparent 70%),
    radial-gradient(ellipse 46% 28% at 66% 88%, rgba(248, 244, 233, 0.6), transparent 72%),
    radial-gradient(ellipse 50% 30% at 40% 34%, var(--mist), transparent 72%),
    radial-gradient(ellipse 34% 22% at 88% 20%, rgba(247, 242, 228, 0.25), transparent 76%),
    linear-gradient(198deg, transparent 34%, rgba(249, 245, 234, 0.3) 94%);
  filter: blur(11px);
  pointer-events: none;
  animation: drift 24s ease-in-out infinite alternate;
}

/* Fog does not hold still. Slow enough that you only notice if you stare. */
@keyframes drift {
  from { transform: translate3d(-7px, 2px, 0) scale(1.02); }
  to   { transform: translate3d(7px, -3px, 0) scale(1.06); }
}

.island--locked .island__icon { color: var(--locked); opacity: 0.85; }

.island--locked .island__name {
  color: var(--locked);
  letter-spacing: 0.22em;
  text-shadow: 0 1px 2px rgba(255, 253, 245, 0.85);
}

.island--locked .island__blurb {
  color: var(--locked);
  font-style: italic;
  text-shadow: 0 1px 2px rgba(255, 253, 245, 0.8);
}

/* ── Footer ─────────────────────────────────────────────────────────────── */

.realm-footer {
  position: relative;
  z-index: 1;
  margin-top: clamp(1.75rem, 5vw, 2.75rem);
  padding-right: clamp(70px, 15vw, 140px); /* keep clear of the compass rose */
  font-style: italic;
  font-size: 0.95rem;
  color: var(--ink-soft);
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition: none !important; animation: none !important; }
  .island--open:hover, .island--open:focus-visible { transform: none; }
}
