/* ============================================================
   JUNO PORTALS · styles.css
   Approved visual system. Change brand values in :root only.
   ============================================================ */

:root{
  /* colour */
  --color-background:#f6f2ee;
  --color-text:#171717;
  --color-accent:#b6707c;
  --color-land:#efe9e2;
  --color-line:rgba(23,23,23,.16);
  --color-line-soft:rgba(23,23,23,.09);
  --color-line-strong:rgba(23,23,23,.42);
  /* readable copy is always full-strength ink, also in sunlight.
     grey is reserved for genuinely unavailable states. */
  --color-muted:#171717;
  --color-disabled:rgba(23,23,23,.34);
  --color-accent-soft:rgba(182,112,124,.14);
  /* the quiet fill behind a chosen option · ten percent */
  --color-accent-tint:rgba(182,112,124,.10);
  /* the folio sheet · the one true white in the system */
  --color-folio:#fff;

  /* map marker colours · portal and current position carry different
     meanings, so they carry different colours */
  --color-portal:#c89a3d;
  --color-you:#1f1f1f;

  /* type */
  --font-display:'Oranienbaum', Georgia, serif;
  --font-body:'Quicksand', system-ui, -apple-system, sans-serif;
  --tracking-display:-.04em;
  --tracking-label:.2em;

  /* spacing */
  --s-1:6px; --s-2:12px; --s-3:20px; --s-4:32px;
  --s-5:48px; --s-6:72px; --s-7:104px;
  --pad:26px;
  --touch:52px;
}

*{box-sizing:border-box;margin:0;padding:0}
html{-webkit-text-size-adjust:100%}
body{
  background:var(--color-background);
  color:var(--color-text);
  font-family:var(--font-body);
  font-weight:400;
  font-size:16px;
  line-height:1.6;
  -webkit-font-smoothing:antialiased;
  overscroll-behavior-y:none;
}
#app{
  position:relative;
  max-width:480px;
  margin:0 auto;
  min-height:100dvh;
}
@media (min-width:521px){
  body{background:#efeae5}
  #app{background:var(--color-background);border-left:1px solid var(--color-line);border-right:1px solid var(--color-line)}
}

/* ---------- screens ---------- */
.screen{display:none;min-height:100dvh;flex-direction:column;
  padding:calc(var(--pad) + env(safe-area-inset-top)) var(--pad) calc(var(--pad) + env(safe-area-inset-bottom));}
.screen.is-active{display:flex;animation:screen-in .7s cubic-bezier(.22,.61,.36,1) both}
@keyframes screen-in{from{opacity:0;transform:translateY(12px)}to{opacity:1;transform:none}}
.spacer{flex:1 1 auto;min-height:var(--s-4)}

/* ---------- typography ---------- */
.display{font-family:var(--font-display);font-weight:400;letter-spacing:var(--tracking-display);
  line-height:.94}
/* uppercase is a deliberate signal, never the default for Oranienbaum */
.caps{text-transform:uppercase;letter-spacing:-.03em}
.d-xxl{font-size:clamp(52px,17vw,80px)}
.d-xl{font-size:clamp(42px,13vw,62px)}
.d-l{font-size:clamp(34px,10vw,48px)}
.d-m{font-size:clamp(27px,8vw,38px);line-height:1.02}
.d-s{font-size:22px;line-height:1.15}
.d-question{font-family:var(--font-display);font-weight:400;letter-spacing:var(--tracking-display);
  font-size:clamp(28px,8.2vw,40px);line-height:1.08}
.label{font-size:11px;letter-spacing:var(--tracking-label);text-transform:uppercase;font-weight:500;line-height:1.5}
.label--muted{color:var(--color-muted)}
.label--accent{color:var(--color-accent)}
.body{font-size:16px;font-weight:400;line-height:1.72;max-width:34em}
.body + .body{margin-top:var(--s-3)}
.story-open{font-size:17px;font-weight:400;line-height:1.68;max-width:32em}
.pull{font-family:var(--font-display);letter-spacing:var(--tracking-display);
  font-size:clamp(26px,7.6vw,36px);line-height:1.14;margin:var(--s-5) 0;max-width:16em}
.muted{color:var(--color-muted)}
.account-line{font-size:13px;font-weight:400;line-height:1.5;color:var(--color-text)}
.accent{color:var(--color-accent)}
.numeric{font-family:var(--font-display);letter-spacing:var(--tracking-display);
  font-size:clamp(64px,22vw,104px);line-height:.9}
.numeric small{font-size:.3em;letter-spacing:.12em}

/* ---------- rules ---------- */
.rule{height:1px;background:var(--color-line);border:0;width:100%}
.rule--soft{background:var(--color-line-soft)}
.rule--short{width:44px;background:var(--color-line-strong)}

/* ---------- buttons ---------- */
.btn{
  display:flex;align-items:center;justify-content:space-between;gap:var(--s-3);
  width:100%;min-height:var(--touch);padding:15px 2px;
  background:none;border:0;border-top:1px solid var(--color-text);border-bottom:1px solid var(--color-text);
  color:var(--color-text);font-family:var(--font-body);font-size:12px;font-weight:500;
  letter-spacing:var(--tracking-label);text-transform:uppercase;text-align:left;
  cursor:pointer;text-decoration:none;transition:background-color .25s ease,color .25s ease,opacity .25s ease;
}
.btn:hover{background:rgba(23,23,23,.045)}
.btn--quiet{border-top:0;border-bottom:1px solid var(--color-line)}
.btn--accent{color:var(--color-accent);border-color:var(--color-accent)}
.btn--accent:hover{background:var(--color-accent-soft)}
.btn[disabled]{opacity:.28;pointer-events:none}
.btn .arrow{font-size:14px;letter-spacing:0}
.btn-stack > * + *{margin-top:var(--s-3)}
.textlink{
  display:inline-flex;align-items:center;min-height:44px;background:none;border:0;padding:0;
  color:var(--color-muted);font-family:var(--font-body);font-size:11px;font-weight:500;
  letter-spacing:var(--tracking-label);text-transform:uppercase;cursor:pointer;
}
.textlink:hover{color:var(--color-text)}
:focus-visible{outline:2px solid var(--color-accent);outline-offset:4px}

/* ---------- top bar ---------- */
.topbar{display:flex;align-items:center;justify-content:space-between;gap:var(--s-3);
  min-height:32px;margin-bottom:var(--s-4)}
.topbar .textlink{min-height:32px}

/* ============================================================
   MAP
   The frame keeps its previous size and borders. Only its content
   changed: a real Mapbox canvas instead of the illustrated SVG.
   ============================================================ */
.mapframe{position:relative;width:100%;flex:1 1 auto;min-height:340px;
  border-top:1px solid var(--color-line);border-bottom:1px solid var(--color-line);
  background:var(--color-background);overflow:hidden}

/* the Mapbox canvas fills the frame */
#map{position:absolute;inset:0}

/* Coordinates moved from the bottom to the top of the frame. Mapbox
   places its logo and attribution bottom left and both have to stay
   legible, so the two would have collided. */
.map-coords{position:absolute;left:8px;top:8px;z-index:2;
  color:var(--color-muted);font-size:10px;letter-spacing:.18em;text-transform:uppercase;
  background:rgba(246,242,238,.82);padding:3px 7px}

/* shown only when the map fails to load */
.map-error{position:absolute;inset:0;z-index:3;display:flex;align-items:center;justify-content:center;
  text-align:center;padding:var(--s-4);background:var(--color-background);color:var(--color-text)}
.map-error[hidden]{display:none}

/* ---------- portal glyph ----------
   Same drawing as before, now carried by a Mapbox marker element
   instead of a child of one big SVG. The state classes are unchanged. */
/* PORTAL · the four point compass star. Shape is drawn in js/map.js,
   size and colour are set here. */
.glyph{width:56px;height:56px;display:flex;align-items:center;justify-content:center;
  background:none;border:0;padding:0;cursor:pointer;-webkit-tap-highlight-color:transparent}
.glyph svg{width:56px;height:56px;display:block;overflow:visible}
.glyph .star{fill:var(--color-portal);transform-box:fill-box;transform-origin:center;
  transition:transform .25s ease}
.glyph .ring{fill:none;stroke:var(--color-portal);stroke-width:1;opacity:0;
  transition:opacity .25s ease}
.glyph .idx{font-family:var(--font-body);font-size:8px;font-weight:500;letter-spacing:.14em;
  fill:var(--color-text);text-anchor:middle}

/* states are shape first, so meaning never rests on colour alone */
.glyph.is-open .ring{opacity:.5}
.glyph.is-selected .ring{opacity:1}
.glyph.is-selected .star{transform:scale(1.14)}
.glyph.is-selected .idx{fill:var(--color-portal)}

/* legibility over the map tiles */
.glyph svg{filter:drop-shadow(0 0 2px rgba(246,242,238,.9))}

/* ---------- you marker · DEV ----------
   No GPS yet, this sits on the destination centre. Disappears with
   the real location step. */
/* DESTINATION · the world layer. Same star, no number, the name of
   the field underneath. */
.dest-glyph{display:flex;flex-direction:column;align-items:center;gap:2px;
  background:none;border:0;padding:0;cursor:pointer;-webkit-tap-highlight-color:transparent}
.dest-glyph svg{width:44px;height:44px;display:block;overflow:visible;
  filter:drop-shadow(0 0 2px rgba(246,242,238,.9))}
.dest-glyph .star{fill:var(--color-portal)}
.dest-name{font-family:var(--font-body);font-size:10px;font-weight:500;
  letter-spacing:.16em;text-transform:uppercase;color:var(--color-text);
  white-space:nowrap;text-shadow:0 0 3px rgba(246,242,238,.95)}
.dest-glyph.is-active .star{opacity:.55}

/* zoom layers · one class on the map container decides which layer is
   on screen, so nothing is added or removed while zooming */
#map.is-local .dest-glyph{display:none}
#map:not(.is-local) .glyph{display:none}
#map.is-far .dest-name{display:none}

/* YOU ARE HERE · same shape as before, now in near black so it reads
   as her position rather than as a portal */
.you{width:28px;height:28px;display:flex;align-items:center;justify-content:center;pointer-events:none}
.you svg{width:28px;height:28px;display:block;overflow:visible;
  filter:drop-shadow(0 0 2px rgba(246,242,238,.9))}
.you .dot{fill:var(--color-you)}
.you .halo{fill:none;stroke:var(--color-you);stroke-width:1;opacity:.45}

/* ---------- Mapbox chrome ----------
   Attribution and logo stay fully visible as required. They are only
   toned down typographically so they sit inside the editorial world. */
.mapboxgl-canvas{outline:none}
.mapboxgl-ctrl-bottom-left,.mapboxgl-ctrl-bottom-right{z-index:2}
.mapboxgl-ctrl-logo{opacity:.55}
.mapboxgl-ctrl-attrib{background:rgba(246,242,238,.78)}
.mapboxgl-ctrl-attrib,.mapboxgl-ctrl-attrib a{font-family:var(--font-body);font-size:9px;
  font-weight:400;color:var(--color-text)}
.mapboxgl-ctrl-attrib-button{opacity:.6}

/* ---------- portal panel (map) ---------- */
.panel{border-top:1px solid var(--color-text);padding-top:var(--s-3);margin-top:var(--s-3)}
.panel[hidden]{display:none}
.panel-head{display:flex;align-items:baseline;justify-content:space-between;gap:var(--s-3)}
.panel-dist{font-family:var(--font-display);letter-spacing:var(--tracking-display);font-size:34px;line-height:1}

/* ---------- list rows ---------- */
.row{display:flex;align-items:baseline;justify-content:space-between;gap:var(--s-3);
  padding:14px 0;border-bottom:1px solid var(--color-line-soft);width:100%;
  background:none;border-left:0;border-right:0;border-top:0;text-align:left;cursor:pointer;
  font-family:var(--font-body);color:var(--color-text);min-height:var(--touch)}
.row:hover{background:rgba(23,23,23,.035)}
.row .row-name{font-size:12px;font-weight:500;letter-spacing:var(--tracking-label);text-transform:uppercase}
.row .row-meta{font-size:11px;letter-spacing:.14em;color:var(--color-muted);text-transform:uppercase;white-space:nowrap}

/* ---------- audio ---------- */
.audio{border-top:1px solid var(--color-line);border-bottom:1px solid var(--color-line);padding:14px 0}
.audio-top{display:flex;align-items:center;justify-content:space-between;gap:var(--s-3)}
.audio-btn{background:none;border:0;padding:0;min-height:44px;cursor:pointer;
  font-family:var(--font-body);font-size:11px;font-weight:500;letter-spacing:var(--tracking-label);
  text-transform:uppercase;color:var(--color-accent)}
.progress{height:1px;background:var(--color-line);margin-top:12px;position:relative}
.progress span{position:absolute;inset:0 auto 0 0;width:0;background:var(--color-accent);display:block}

/* ---------- a two option choice ----------
   Not a list of links: one selection with two objects in it. Label and
   explanation sit inside the same button, so the tint covers both. */
.choice-group{border-top:1px solid var(--color-line-soft)}
.choice{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--s-3);
  width:100%;padding:var(--s-3) var(--s-2);margin:0 calc(var(--s-2) * -1);
  background:none;border:0;border-radius:0;cursor:pointer;text-align:left;
  font-family:var(--font-body);color:var(--color-text);
  transition:background-color .2s ease}
.choice + .choice{border-top:1px solid var(--color-line-soft)}
.choice[aria-pressed="true"]{background:var(--color-accent-tint)}

.choice-text{display:block}
.choice-label{display:block;font-size:11px;font-weight:500;
  letter-spacing:var(--tracking-label);text-transform:uppercase;line-height:1.5}
/* quieter through size and case, never through pale grey · this is
   read outdoors */
.choice-note{display:block;margin-top:var(--s-1);font-size:13px;font-weight:400;
  letter-spacing:0;line-height:1.5;color:var(--color-text);text-transform:none}

/* empty means unchosen, filled means chosen · a difference in shape,
   not only in colour */
.choice-mark{flex:0 0 auto;width:14px;height:14px;margin-top:2px;border-radius:50%;
  border:1px solid var(--color-line-strong);background:transparent}
.choice[aria-pressed="true"] .choice-mark{background:var(--color-accent);border-color:var(--color-accent)}

/* ---------- forms ---------- */
.field{display:block}
.field label{display:block;margin-bottom:var(--s-2)}
textarea,input[type=email],input[type=text]{
  width:100%;background:transparent;border:0;border-bottom:1px solid var(--color-line-strong);
  font-family:var(--font-body);font-size:16px;font-weight:400;color:var(--color-text);
  padding:10px 0;line-height:1.7;resize:none;
}
textarea{min-height:132px}
textarea:focus,input[type=email]:focus,input[type=text]:focus{outline:0;border-bottom-color:var(--color-accent)}
::placeholder{color:var(--color-disabled)}
.counter{margin-top:var(--s-2);text-align:right}

/* ---------- archive ---------- */
.fragment{padding:var(--s-4) 0;border-top:1px solid var(--color-line-soft)}
.fragment p{font-family:var(--font-display);letter-spacing:var(--tracking-display);
  font-size:22px;line-height:1.25;text-transform:none}
.fragment .meta{margin-top:var(--s-2)}

/* ---------- share preview ----------
   The card itself is 1080 x 1920. This is only its viewport. */
.share-preview{display:block;width:100%;max-width:300px;aspect-ratio:9/16;
  object-fit:contain;margin:var(--s-4) auto var(--s-2);border:1px solid var(--color-line);
  background:var(--color-background)}

/* ---------- the sealed block ----------
   The one surface that carries the accent. It marks the private
   future-self moment as different from the rest of the flow, and it
   appears nowhere else. */
.sealed{background:var(--color-accent-soft);border-left:1px solid var(--color-accent);
  padding:var(--s-3) var(--s-3) var(--s-3) var(--s-4)}

/* ---------- journey · the three levels at the bottom ----------
   One functional section, then the way back for someone who already
   has a journey, then the footer. The hierarchy is spacing and a
   hairline, nothing more. */

/* three numbers, one summary · not three things to tap */
.journey-summary{margin-top:var(--s-5)}
.journey-summary p + p{margin-top:2px}

/* a message still on its way · administration, not journal. Same
   quiet footing as the sections below it. */
.transit{margin-top:var(--s-6);padding-top:var(--s-4);
  border-top:1px solid var(--color-line-soft)}
.transit-entry{padding:var(--s-3) 0;border-top:1px solid var(--color-line-soft)}
.transit-entry:first-child{border-top:0}
.transit-meta{display:flex;align-items:baseline;justify-content:space-between;
  gap:var(--s-3);margin-top:var(--s-1)}

/* the action belongs to the two fields above it, not beside them */
.keep-action{margin-top:var(--s-6)}

/* someone who has been here before */
.returning{margin-top:var(--s-6);padding-top:var(--s-4);
  border-top:1px solid var(--color-line-soft)}
.returning-line{display:flex;align-items:center;gap:var(--s-2);flex-wrap:wrap}
.returning-intro{color:var(--color-text)}

/* footer utility · far enough away to read as another layer */
.account-footer{margin-top:var(--s-7);padding-top:var(--s-4);
  border-top:1px solid var(--color-line-soft)}
.account-footer .footer-danger{margin-top:var(--s-4)}

/* ---------- the brand mark ----------
   The same asset everywhere, at the size the words had. Never a hero.

   The file carries transparent padding: 131px tall, of which roughly
   66px is artwork. A 30px box therefore renders about 15px of visible
   lettering, which is the footprint the old JUNO PORTALS text had.
   If the asset is ever trimmed, this height changes with it.

   align-self keeps it from being stretched by the column flex of a
   screen, flex:0 0 auto keeps it from squeezing the topbar, and the
   cap plus contain make an oversized file impossible to overflow. */
.brandmark{display:block;height:30px;width:auto;max-width:60%;
  object-fit:contain;align-self:flex-start;flex:0 0 auto}

/* ---------- destination folio ----------
   One real place in her world. A sheet, not a card: true white, square
   corners, a deliberate accent edge, no shadow. The stronger border is
   the point, it marks a structural level the hairlines do not. */
.folio{background:var(--color-folio);border:2px solid var(--color-accent);
  padding:var(--s-4);margin-top:var(--s-5)}
.folio-name{font-family:var(--font-display);letter-spacing:var(--tracking-display);
  font-size:clamp(30px,9vw,40px);line-height:1;text-transform:uppercase}
.folio-meta{margin-top:var(--s-2)}
.folio .moment:first-of-type{border-top:0;padding-top:var(--s-4)}

/* ---------- journey moments ----------
   One entry per completed portal, separated by a hairline. No box,
   no card, the same language as the archive fragments. */
.moment{padding:var(--s-5) 0;border-top:1px solid var(--color-line-soft)}
/* each on its own row, so the relic never moves when the visibility
   label changes length. A structural fix, no fixed widths. */
.moment-row{display:block;margin-top:var(--s-3)}
.moment-row + .moment-row{margin-top:var(--s-4)}

.moment-relic{display:inline-flex;align-items:center;min-height:44px;
  background:none;border:0;padding:0;cursor:pointer;text-align:left;
  font-family:var(--font-display);letter-spacing:var(--tracking-display);
  font-size:22px;line-height:1.15;color:var(--color-accent)}
.moment-relic:hover{opacity:.7}

/* ---------- relic ---------- */
/* the artwork is a real image file later, served from private storage.
   the layout never depends on what the image is. */
.relic-art{position:relative;width:100%;max-width:300px;margin:var(--s-5) auto;
  aspect-ratio:4/5;border:1px solid var(--color-line);overflow:hidden;
  display:flex;align-items:center;justify-content:center}
.relic-art img{width:100%;height:100%;object-fit:cover;display:block}
.relic-art figcaption{text-align:center;padding:var(--s-3)}
.relic-art figcaption[hidden],.relic-art img[hidden]{display:none}

/* ---------- action pause ---------- */
.pause-line{height:1px;background:var(--color-line);margin:var(--s-5) 0 var(--s-2)}
.pause-line span{display:block;height:1px;width:0;background:var(--color-accent);transition:width 1s linear}

/* ---------- reveal moment ---------- */
.centered{justify-content:center;align-items:flex-start;text-align:left}
.fade-seq > *{opacity:0;animation:fade-up 1.1s cubic-bezier(.22,.61,.36,1) forwards}
.fade-seq > *:nth-child(1){animation-delay:.15s}
.fade-seq > *:nth-child(2){animation-delay:.75s}
.fade-seq > *:nth-child(3){animation-delay:1.5s}
.fade-seq > *:nth-child(4){animation-delay:2.1s}
@keyframes fade-up{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.01ms !important;animation-delay:0ms !important;transition-duration:.01ms !important}
  .fade-seq > *{opacity:1}
}

/* ============================================================
   DEV panel · START — delete this block together with the DEV
   markup in index.html and the DEV block in js/app.js
   ============================================================ */
#dev-panel{position:fixed;right:12px;bottom:calc(12px + env(safe-area-inset-bottom));z-index:99;
  font-family:var(--font-body);text-align:right}
#dev-toggle{background:var(--color-text);color:var(--color-background);border:0;
  font-family:var(--font-body);font-size:9px;font-weight:500;letter-spacing:.2em;
  padding:8px 10px;cursor:pointer}
#dev-body{display:none;margin-top:6px;background:var(--color-text);color:var(--color-background);padding:14px;min-width:206px;text-align:left}
#dev-body.is-open{display:block}
#dev-body p{font-size:9px;letter-spacing:.16em;text-transform:uppercase;opacity:.6;margin-bottom:10px}
#dev-body button{display:block;width:100%;background:none;border:1px solid rgba(246,242,238,.3);
  color:var(--color-background);font-family:var(--font-body);font-size:10px;font-weight:500;
  letter-spacing:.16em;text-transform:uppercase;padding:9px;margin-bottom:6px;cursor:pointer}
#dev-body button:hover{background:rgba(246,242,238,.12)}
/* DEV panel · END */
