/* Skue — cartographic paper system. docs/design/handoff/SKUE_DESIGN_HANDOFF.md §6.
   Every colour, face and rule weight is a token here; nothing below hardcodes one. */

/* The display face, served from here rather than Google Fonts: one variable file
   covering both weights and the optical-size axis. web/vendor/source-serif-4.004/README.md
   index.html preloads it. block: serif text waits (up to 3 s) for this face instead of
   showing a stand-in and jumping when it arrives; swap is the opposite trade. */
@font-face{
  font-family:"Source Serif 4"; font-style:normal; font-weight:400 600; font-display:block;
  src:url("vendor/source-serif-4.004/source-serif-4-latin.woff2") format("woff2");
}

:root{
  --bg:#f5f3ec; --surface:#fbfaf6; --ink:#344b56; --strong:#22333b; --muted:#5e6f76;
  --accent:#b7442c; --accent-strong:#9c3822; --line:#bcc5c5; --truth:#2f665e;
  /* the squares, same order as BAND_RADII in scoring.js: inside the target, 3, 9, 27 radii, beyond.
     Checked pairwise: every neighbour is >= 15 apart in OKLab for full colour vision and
     >= 10 under protan, deutan and tritan simulation. The red is a cool crimson so it
     does not read as the vermilion --accent. */
  --band-0:#4f8f63; --band-1:#e6c234; --band-2:#dc7a24; --band-3:#a51f45; --band-4:#232b30;
  --font-display:"Source Serif 4","Iowan Old Style",Georgia,"Times New Roman",serif;
  --font-ui:system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;
  --rule-width:1px; --radius:0;
  /* Kartverket's grey topo, quietened: mid-grey building blocks and hillshade are
     lifted toward the paper while labels stay dark. Set to none for the raw tiles. */
  --map-filter:contrast(.7) brightness(1.3);
  /* --col holds reading text; --frame holds everything else on a wide screen
     (header, photo, map, bottom bar, footer), so they share one pair of edges. */
  --gutter:20px; --col:560px; --frame:1100px; --bar-h:50px;
  --safe-b:env(safe-area-inset-bottom,0px);
}
*{box-sizing:border-box}
[hidden]{display:none!important}
html,body{height:100%; overscroll-behavior:none}
body{
  margin:0; background:var(--bg); color:var(--ink);
  font:16px/1.5 var(--font-ui);
  display:flex; flex-direction:column; height:100vh; height:100dvh; overflow:hidden;
  touch-action:manipulation; -webkit-text-size-adjust:100%;
}
p,h1,h2,ol,dl,figure{margin:0}
ol{padding:0; list-style:none}
a{color:var(--accent-strong); text-underline-offset:.18em}
:focus-visible{outline:2px solid var(--strong); outline-offset:2px}
main:focus{outline:none}

.label,#bar-round,#bar-date,#bar-back,.archive-credit dt{
  font:500 12px/1.4 var(--font-ui); letter-spacing:.16em; text-transform:uppercase; color:var(--muted);
}
.muted{color:var(--muted); font-size:15px}
.note{min-height:1.5em; font-size:15px; color:var(--strong)}
.note.silent{color:transparent}   /* read to screen readers, unseen, and still holding its line */

/* ---- buttons: square, ruled, 48px tall ---- */
button,.button{
  font:500 16px/1.2 var(--font-ui); letter-spacing:.02em; color:var(--ink);
  min-height:48px; padding:0 18px; border-radius:var(--radius);
  border:var(--rule-width) solid var(--ink); background:transparent;
  display:flex; align-items:center; justify-content:center; gap:.6em;
  width:100%; cursor:pointer; text-decoration:none; -webkit-tap-highlight-color:transparent;
}
button.primary,.button.primary{background:var(--ink); color:var(--surface)}
button.primary.accent{background:var(--accent); border-color:var(--accent)}
button.secondary{background:var(--surface)}
@media (hover:hover){
  button.secondary:hover:not(:disabled){background:var(--bg)}
  button.primary:hover:not(:disabled),.button.primary:hover{background:var(--strong)}
  button.primary.accent:hover:not(:disabled){background:var(--accent-strong)}
}
button:disabled,button.primary:disabled,button.primary.accent:disabled{
  cursor:default; background:transparent; color:var(--muted);
  border:var(--rule-width) dashed var(--line);
}
button.quiet{
  width:auto; min-height:44px; min-width:44px; padding:0 6px; border:0;
  font:inherit; letter-spacing:inherit; text-transform:inherit; color:var(--ink);
}
button.quiet:disabled{border:0; color:var(--line)}

/* ---- header: one row, one rule under it, the same height on every screen ---- */
#bar{
  flex:none; padding:env(safe-area-inset-top,0px) var(--gutter) 0; background:var(--bg);
  border-bottom:var(--rule-width) solid var(--line);
}
.bar-row{display:none; align-items:center; gap:22px; height:var(--bar-h); white-space:nowrap}
body[data-bar=plain] #bar-plain{display:flex}
#brand{font:600 18px/1 var(--font-display); letter-spacing:.28em; text-transform:uppercase; color:var(--strong)}
.brand-city{font-weight:400; color:var(--muted)}
#decade{font-variant-numeric:tabular-nums; font-weight:600; color:var(--strong)}   /* the one clue besides the photo */
#bar-date{margin-left:auto}
/* A link back on the left, the middle one centred, the rest on the right. While
   playing: ‹ I dag, the decade, the squares. On the summary: ‹ I dag and the date;
   on the revisit: back to the result, which photo this is, and the arrows. */
body[data-bar=round] #bar-round,body[data-bar=back] #bar-back{display:grid; grid-template-columns:1fr auto 1fr}
#back,#round-home{justify-self:start}
#bar-squares{display:flex; gap:5px; justify-self:end}
#back-nav{display:flex; justify-self:end}
#back-nav button{font-size:20px}
body[data-screen=start] #bar{display:none}

/* ---- band squares ---- */
.sq{display:inline-block; width:11px; height:11px; flex:none; background:var(--line)}
.sq.b0{background:var(--band-0)} .sq.b1{background:var(--band-1)}
.sq.b2{background:var(--band-2)} .sq.b3{background:var(--band-3)} .sq.b4{background:var(--band-4)}
/* The header's squares for rounds not played yet: pale, and this one outlined. */
.sq.slot{background:transparent; box-shadow:inset 0 0 0 1px var(--line)}
.sq.slot.now{box-shadow:inset 0 0 0 1.5px var(--ink)}
.squares{display:flex; gap:8px}
.squares .sq{width:22px; height:22px}

/* ---- screens ---- */
.screen{display:none; flex:1; min-height:0; flex-direction:column}
body[data-screen=start] #start, body[data-screen=photo-mode] #photo-mode,
body[data-screen=map-mode] #map-mode, body[data-screen=reveal] #reveal,
body[data-screen=summary] #summary, body[data-screen=revisit] #revisit,
body[data-screen=shared] #shared{display:flex}
.scroll{overflow-y:auto; -webkit-overflow-scrolling:touch; overscroll-behavior:contain}
#reveal-scroll{flex:1; min-height:0; display:flex; flex-direction:column}
#reveal-body{flex:1 0 auto}   /* holds the footer down, as .col does on the other screens */
.col{width:100%; max-width:var(--col); margin:0 auto; padding:24px var(--gutter) 28px; flex:1 0 auto}
.actions{
  flex:none; padding:12px var(--gutter) calc(12px + var(--safe-b));
  background:var(--bg); border-top:var(--rule-width) solid var(--line);
}
.actions>*{max-width:calc(var(--col) - 2*var(--gutter)); margin-left:auto; margin-right:auto}
/* A rule only where it separates something: the photo floats on paper, so no line
   above Se kart; on the map it is the map's edge, on the reveal the text scrolls under it. */
#photo-mode .actions{border-top:0}
.hint{font-size:15px; color:var(--muted); text-align:center; margin-bottom:8px!important}
.hint.warn{color:var(--accent-strong)}
.pair{display:flex; gap:12px}
/* A checkbox drawn in the page's ink, square like the buttons. The label is the
   tap target, so it gets some height. */
.check{display:flex; align-items:center; gap:10px; width:fit-content; padding:8px 0; margin-top:4px; font-size:15px; color:var(--muted); cursor:pointer}
.check input{appearance:none; flex:none; display:grid; place-items:center; width:20px; height:20px; margin:0; border:1.5px solid var(--ink); background:var(--surface); cursor:pointer}
.check input:checked{background:var(--ink)}
.check input:checked::after{content:""; width:5px; height:10px; border:solid var(--surface); border-width:0 2px 2px 0; transform:translateY(-1px) rotate(45deg)}

/* ---- start ---- */
/* I dag lies on a street map of central Oslo, pale enough to read over: the same
   map every day, drawn by brand/make_map.py from OpenStreetMap (credited in the
   footer, on this screen only). Its colours are mixed from --ink and --bg there. */
body[data-screen=start]{background:var(--bg) url(oslo-streets.svg) 50% 50%/cover no-repeat}
.start-col{padding-top:calc(24px + env(safe-area-inset-top,0px)); display:flex; flex-direction:column; justify-content:center; gap:18px; padding-bottom:48px}
#start-title{
  font:600 clamp(30px,9.6vw,56px)/1.1 var(--font-display); letter-spacing:.24em; white-space:nowrap;
  text-transform:uppercase; color:var(--strong); padding-bottom:6px;
}
#start-lede{font:400 22px/1.35 var(--font-display); color:var(--strong)}
#start-lede span{display:inline-block; text-wrap:balance}   /* balance: if one still wraps, not to one word */
#start-btn{margin-top:10px}
/* I dag: the daily set's start, or its result, then the day's other games as rows */
.home-block{display:flex; flex-direction:column; gap:18px}
.home-head{display:flex; align-items:center; justify-content:space-between; margin-bottom:-8px}
.home-head button.quiet{margin-right:-6px; color:var(--accent-strong)}
#home-daily .hero{margin:0 0 14px}
#home-daily .pair{margin-top:22px}
#home-more{margin-top:8px}
#tour-btn{align-self:center; margin-top:-8px; color:var(--accent-strong)}
#tour-btn:disabled{color:var(--muted)}
/* Each of the day's other games is a box, as Kopier is: plain paper over the map,
   and no rules across the column. */
#home-more .rows{margin:10px 0 0; border-top:0; display:grid; gap:8px}
#home-more .rows li{border-bottom:0}
.rows.games .row{
  grid-template-columns:1fr auto 18px; min-height:56px; padding:6px 14px 6px 16px;
  background:var(--surface); border:var(--rule-width) solid var(--line);
}
.row-name{font-weight:500; color:var(--strong)}
.row-state{display:inline-flex; align-items:center; gap:12px; color:var(--muted)}
.squares.mini{gap:4px}
.squares.mini .sq{width:11px; height:11px}

/* ---- photo mode ---- */
/* Positioning is entirely the transform's job — no flex centering here,
   or the two fight and the image lands off-centre. */
#viewport{
  position:relative; flex:1; min-height:0; overflow:hidden; cursor:grab;
  touch-action:none; overscroll-behavior:none; user-select:none; -webkit-user-select:none;
}
#viewport.dragging{cursor:grabbing}
#viewport:focus-visible{outline-offset:-3px}
#photo-frame{position:absolute; background:var(--surface); border:var(--rule-width) solid var(--line)}
#photo{
  position:absolute; top:0; left:0; transform-origin:0 0; max-width:none;
  user-select:none; -webkit-user-drag:none; -webkit-touch-callout:none; image-rendering:auto;
}
#zoom-hint{
  position:absolute; z-index:2; left:50%; bottom:14px; transform:translateX(-50%);
  width:max-content; max-width:calc(100% - 32px); text-align:center;
  font-size:15px; color:var(--ink); background:var(--surface); border:var(--rule-width) solid var(--line);
  padding:6px 12px; pointer-events:none; transition:opacity .4s;
}
#zoom-hint.gone{opacity:0}
#viewport.glide #photo{transition:transform .22s ease-out}
#viewport.glide #photo-frame{transition:left .22s ease-out,top .22s ease-out,width .22s ease-out,height .22s ease-out}
#viewport[data-state=loading] #photo,#viewport[data-state=error] #photo{opacity:0}
#photo-status{
  position:absolute; top:0; right:0; bottom:0; left:0; display:flex; flex-direction:column; align-items:center;
  justify-content:center; gap:14px; pointer-events:none; color:var(--muted); font-size:14px;
}
#viewport[data-state=ok] #photo-status{display:none}
#photo-retry{width:auto; pointer-events:auto; background:var(--surface)}

/* ---- map mode ---- */
#map-wrap{position:relative; flex:1; min-height:0}
#map{position:absolute; top:0; right:0; bottom:0; left:0}   /* not inset: iOS 14.0 and older lack it */
#thumb{
  position:absolute; z-index:500; top:12px; left:12px; width:auto; min-height:0; padding:4px;
  background:var(--surface); border:var(--rule-width) solid var(--ink); line-height:0;
}
#thumb img{display:block}

/* ---- Slik spiller du's tips (showTip()): one look for three kinds. An intro is a
   card in the middle of a dimmed screen; a lesson a sheet at the bottom, the
   screen dimmed except what it is about; an action tip a box with an arrow at its
   control, the screen live. The veil is one SVG path, the screen less a hole per
   lit thing (placeTip()); the holes let taps through, the rest does not. */
#tip-veil{position:fixed; z-index:2000; top:0; left:0; width:100%; height:100%; pointer-events:none}
#tip-veil path{fill:rgba(20,30,35,.5); pointer-events:auto}
#tip{
  position:fixed; z-index:2001; padding:14px 16px 6px;
  background:var(--surface); color:var(--strong); border:2px solid var(--strong);
  font-size:16px; line-height:1.4;
}
#tip-arrow{
  position:absolute; width:12px; height:12px; background:var(--surface);
  border:2px solid var(--strong); transform:rotate(45deg);
}
#tip[data-side=below] #tip-arrow{top:-8px; border-right:0; border-bottom:0}
#tip[data-side=above] #tip-arrow{bottom:-8px; border-left:0; border-top:0}
#tip[data-side=right] #tip-arrow{left:-8px; border-top:0; border-right:0}
#tip[data-side=inside] #tip-arrow,#tip[data-side=dock] #tip-arrow{display:none}
.tip-actions{display:flex; justify-content:flex-end; margin:4px -6px 0}
.tip-actions button{font-weight:600}
#tip-ok{color:var(--accent-strong)}
/* An action tip has no buttons: it goes when its action is done. */
#tip[data-kind=act]{padding:12px 16px}
#tip[data-kind=act] .tip-actions{display:none}
/* In, not popped: the veil fades, the box fades and rises a little. */
#tip-veil:not([hidden]){animation:tip-veil .2s ease-out}
#tip:not([hidden]){animation:tip-in .2s ease-out}
@keyframes tip-veil{from{opacity:0}}
@keyframes tip-in{from{opacity:0; transform:translateY(6px)}}
@media (prefers-reduced-motion:reduce){#tip-veil:not([hidden]),#tip:not([hidden]){animation:none}}
/* The target around an answer, and 3, 9 and 27 times it, in the squares' colours:
   drawn on Slik spiller du's results only (drawResult()). */
.ring{stroke-width:2.5; fill:none}
.ring.b0{stroke:var(--band-0)} .ring.b1{stroke:var(--band-1)}
.ring.b2{stroke:var(--band-2)} .ring.b3{stroke:var(--band-3)}
.ring-fill{stroke:none; fill-opacity:.14; fill-rule:evenodd}
.ring-fill.b0{fill:var(--band-0); fill-opacity:.2} .ring-fill.b1{fill:var(--band-1)}
.ring-fill.b2{fill:var(--band-2)} .ring-fill.b3{fill:var(--band-3)}

/* Leaflet, brought into the system: square, ruled, no shadows. */
.leaflet-container{font:12px/1.4 var(--font-ui); color:var(--ink); background:var(--bg)}
.leaflet-tile-pane{filter:var(--map-filter); mix-blend-mode:multiply}
.leaflet-bar,.leaflet-touch .leaflet-bar{
  border:var(--rule-width) solid var(--ink); border-radius:var(--radius); box-shadow:none;
}
.leaflet-bar a,.leaflet-touch .leaflet-bar a{
  width:40px; height:40px; line-height:40px; font:400 20px/40px var(--font-ui);
  color:var(--ink); background:var(--surface); border-radius:0!important;
  border-bottom:var(--rule-width) solid var(--line);
}
.leaflet-bar a:last-child{border-bottom:0}
.leaflet-bar a.leaflet-disabled{color:var(--line); background:var(--surface)}
.leaflet-top.leaflet-right .leaflet-control{margin:12px 12px 0 0}
.leaflet-container .leaflet-control-attribution{
  background:rgba(251,250,246,.9); color:var(--ink); font-size:12px; padding:2px 8px;
}
.leaflet-control-attribution a{color:var(--ink)}
.mk{background:none; border:0}
.mk svg{display:block; overflow:visible}
.mk-guess path{fill:var(--accent); stroke:var(--surface); stroke-width:1.5}
.mk-guess circle{fill:var(--surface)}
.mk-truth .halo{fill:var(--surface)}
.mk-truth .ring{fill:none; stroke:var(--truth); stroke-width:3}
.mk-truth .dot{fill:var(--truth)}
.guess-line{stroke:var(--accent); stroke-width:2.5; stroke-dasharray:3 7; stroke-linecap:round; fill:none}
/* Outside Oslo kommune: a light veil, so the neighbours still help you find
   your way, and the boundary drawn on top. Chosen from six options 2026-09-25. */
.kommune-mask{fill:var(--bg); fill-opacity:.55; stroke:none}
.kommune-edge{stroke:var(--strong); stroke-width:2; stroke-opacity:.8; fill:none}

/* ---- reveal ---- */
.result-map{flex:none; height:46vh; min-height:250px; max-height:520px; border-bottom:var(--rule-width) solid var(--line)}
.legend{
  display:flex; align-items:center; flex-wrap:wrap; gap:4px 18px; font-size:14px; color:var(--muted);
  margin:-10px 0 14px;
}
.legend span{display:inline-flex}
.legend .item{align-items:center; gap:6px}
.legend svg{width:16px; height:20px}
.legend .mk-truth svg{height:16px}

/* ---- revisit: the result under the photo ---- */
#revisit-where{margin:0 0 18px}
#revisit-result{margin-bottom:8px; font-variant-numeric:tabular-nums}
.map-frame{padding:6px; background:var(--surface); border:var(--rule-width) solid var(--line)}
#revisit-map{height:300px}
#revisit .legend{margin:10px 0 0}
#result{display:grid; grid-template-columns:1fr 1fr}
.result-cell{padding:14px 0 12px}
.result-cell+.result-cell{padding-left:var(--gutter)}
.figure{
  font:400 clamp(30px,9.5vw,40px)/1.1 var(--font-display); color:var(--strong);
  font-variant-numeric:lining-nums tabular-nums; margin-top:4px; white-space:nowrap;
}
#reveal-score{color:var(--accent)}
.figure-sub{font:400 15px/1.3 var(--font-display); color:var(--muted); font-variant-numeric:lining-nums tabular-nums}
#reveal-place{font:400 20px/1.3 var(--font-display); color:var(--strong); padding:16px 0 0}
#reveal-place:empty{display:none}
#reveal-archive{margin-top:22px; padding-top:20px; border-top:var(--rule-width) solid var(--line)}

.beat{opacity:0; transform:translateY(6px); transition:opacity .28s ease-out,transform .28s ease-out}
.beat.on{opacity:1; transform:none}
#reveal-map.beat{transform:none}
#cell-score.close.on #reveal-score{animation:pop .5s ease-out both}
@keyframes pop{0%{transform:scale(.9)} 55%{transform:scale(1.1)} 100%{transform:none}}
#reveal-score{transform-origin:left center; display:inline-block}
body.instant .beat{transition:none}
body.instant #cell-score.close.on #reveal-score{animation:none}
@media (prefers-reduced-motion:reduce){
  .beat{transition:none} #cell-score.close.on #reveal-score{animation:none}
}

/* ---- archive caption ---- */
.archive-title{font:600 24px/1.22 var(--font-display); color:var(--strong)}
.archive-title.fallback{font-weight:400; font-size:20px; line-height:1.35}
.archive-where{font:400 16px/1.4 var(--font-display); color:var(--muted); margin-top:4px; font-variant-numeric:lining-nums}
.archive-photo{
  display:block; width:auto; max-width:100%; min-height:0; margin:16px 0 14px; padding:6px;
  background:var(--surface); border:var(--rule-width) solid var(--line); line-height:0; cursor:zoom-in;
}
.archive-photo img{display:block; height:auto}
.archive-credit{
  display:grid; grid-template-columns:auto 1fr; gap:8px 18px; align-items:baseline; font-size:15px;
}
.archive-credit dd{margin:0; color:var(--strong); overflow-wrap:anywhere}

/* ---- summary / shared ---- */
.hero{font-family:var(--font-display); color:var(--strong); font-variant-numeric:lining-nums tabular-nums; margin:6px 0 18px; white-space:nowrap}
.hero-n{font-size:clamp(46px,15vw,64px); line-height:1; font-weight:400}
.hero-of{font-size:clamp(20px,6vw,26px); color:var(--muted)}
.rows{margin:22px 0 24px; border-top:var(--rule-width) solid var(--line)}
.rows li{border-bottom:var(--rule-width) solid var(--line)}
.row{
  display:grid; grid-template-columns:22px 60px 1fr auto 18px; align-items:center; gap:12px;
  width:100%; min-height:60px; padding:6px 0; border:0; background:none; text-align:left;
  font:400 16px/1.2 var(--font-ui); letter-spacing:0; color:var(--ink);
  font-variant-numeric:tabular-nums;
}
.rows.plain .row{grid-template-columns:22px 1fr auto; min-height:48px}
@media (hover:hover){button.row:hover{background:var(--surface)} .rows.games button.row:hover{background:var(--bg)}}
.row-n{color:var(--muted); font-size:14px}
.row-thumb{width:60px; height:46px; object-fit:contain; background:var(--surface); border:var(--rule-width) solid var(--line)}
.row-score{display:inline-flex; align-items:center; gap:9px; font:400 19px/1 var(--font-display); color:var(--strong); font-variant-numeric:lining-nums tabular-nums}
.row-go{color:var(--muted)}
#comeback{margin-top:6px; font-variant-numeric:tabular-nums}
#next-game{margin-bottom:12px}
#shared-play{margin-top:4px}

/* ---- about page (om.html): one scrolling column, the footer at its end ---- */
#om{flex:1; min-height:0; display:flex; flex-direction:column}
#om h1{font:600 30px/1.2 var(--font-display); color:var(--strong); margin-bottom:14px}
#om h2{font:600 19px/1.3 var(--font-display); color:var(--strong); margin:28px 0 8px}
#om .col p+p{margin-top:10px}
.bands{margin:12px 0; padding:0; list-style:none; display:grid; gap:8px}
.bands li{display:flex; align-items:center; gap:10px}
.bands .sq{width:16px; height:16px}
#om-play{margin-top:32px}
a#brand{text-decoration:none}

/* ---- footer: lives inside the scrolling screens, never on photo or map ---- */
#foot{
  padding:16px var(--gutter) calc(18px + var(--safe-b)); border-top:var(--rule-width) solid var(--line);
  font-size:13.5px; line-height:1.5; color:var(--muted); text-align:center;
}
#reveal #foot{padding-bottom:18px}
#foot a{color:inherit}
/* On I dag the footer lies on the map: space sets it apart, where a rule would cut
   across the map wider than anything else on the page. The map's credit is shown here only. */
body[data-screen=start] #foot{border-top:0}
body:not([data-screen=start]) #map-credit{display:none}
body[data-screen=photo-mode] #foot,body[data-screen=map-mode] #foot,body[data-screen=boot] #foot{display:none}
body[data-screen=boot] #bar{visibility:hidden}

/* ---- loading: one quiet line if photos.json is slow; app.js unhides it ---- */
#boot-note{margin:auto; text-align:center}
body:not([data-screen=boot]) #boot-note{display:none}

/* ---- no JavaScript: the one thing on the page ---- */
#nojs{
  margin:auto; max-width:var(--col); padding:24px var(--gutter); text-align:center;
  font:400 20px/1.4 var(--font-display); color:var(--strong);
}

/* ---- the narrowest phones (320 px): ‹ I dag, the decade and five squares
   still fit the header's one row, the next-game button its one line, and the
   start's first sentence its line (275 of 288 px in our own face) ---- */
@media (max-width:359px){
  :root{--gutter:16px}
  .bar-row{gap:12px}
  #bar-round{letter-spacing:.1em}
  #start-lede{font-size:20px}
}

/* ---- wider screens: same model, held to one frame ----
   Header, photo, map, bottom bar and footer share the frame's two edges, with paper
   around them; reading text keeps its narrower column inside. The maps get a rule
   on each side, so the header rule above and the bottom bar's rule below close them. */
@media (min-width:760px){
  :root{--gutter:28px}
  #bar,#viewport,#map-wrap,.result-map,.actions,#foot{
    width:calc(100% - 2*var(--gutter)); max-width:var(--frame); margin-left:auto; margin-right:auto;
  }
  #bar,.actions,#foot{padding-left:0; padding-right:0}
  #map-wrap,.result-map{border-left:var(--rule-width) solid var(--line); border-right:var(--rule-width) solid var(--line)}
  .result-map{height:52vh}
  #thumb{top:16px; left:16px}
}

/* ---- revisit on a wide screen: photo and caption left, the result beside it ---- */
@media (min-width:960px){
  #revisit .col{max-width:calc(var(--frame) + 2*var(--gutter))}   /* lines up with the header */
  #revisit-archive{display:grid; grid-template-columns:minmax(0,1fr) minmax(0,1fr); column-gap:40px; align-items:start}
  #revisit-archive>*{grid-column:1}
  #revisit-where{grid-column:2; grid-row:1 / span 4; align-self:stretch; display:flex; flex-direction:column; margin:0}
  #revisit-where .map-frame{flex:1; display:flex; flex-direction:column; max-height:75vh}
  #revisit-map{flex:1; height:auto; min-height:320px}
}

/* ---- the reveal on a wide screen: the revisit's two columns ----
   The photo and its caption on the left; on the right the map, the legend, the
   figures and the place, in the phone's order. #reveal-body is the grid and its
   .col steps aside (display:contents), so the caption and the result are placed
   in it beside the map. The map keeps the phone's height: in half the frame,
   the wide screen's 52vh would make it nearly square and put the score under
   the bottom bar in a window under 632 px tall (46vh: 562 px; measured
   2026-10-19). The last row takes whatever height the caption has beyond the
   result, so the right column never spreads out. */
@media (min-width:960px){
  #reveal-body{
    display:grid; grid-template-columns:minmax(0,1fr) minmax(0,1fr); grid-template-rows:auto auto auto auto 1fr;
    column-gap:40px; align-items:start; width:100%; max-width:calc(var(--frame) + 2*var(--gutter));   /* lines up with the header */
    margin:0 auto; padding:24px var(--gutter) 28px;
  }
  #reveal-body>.col{display:contents}
  #reveal-archive{grid-column:1; grid-row:1 / -1; margin:0; padding:0; border:0}
  #reveal-archive>:first-child{margin-top:0}   /* an untitled photo, level with the map */
  #reveal-frame,#reveal-legend,#result,#reveal-place{grid-column:2}
  #reveal-frame{padding:6px; background:var(--surface); border:var(--rule-width) solid var(--line)}   /* as .map-frame */
  #reveal-map{width:auto; max-width:none; margin:0; border:0; height:46vh}
  #reveal-legend{margin:10px 0 0}
}

/* ---- about page on a wide screen: the intro, then two columns ----
   Everything sits in one two-column grid between the header's edges. Lines stay
   45-75 characters; type is the site's own (the lede is the start screen's, the
   title one step above the phone's 30px); space, not rules, separates sections.
   The game is on the left, the rest on the right, and the button closes the right
   column, where reading ends, level with the end of the left one. */
@media (min-width:960px){
  #om .col{max-width:calc(var(--frame) + 2*var(--gutter)); padding-top:48px; padding-bottom:48px}
  #om h1{font-size:35px; margin-bottom:16px}
  .om-intro p:first-child{font:400 22px/1.35 var(--font-display); color:var(--strong)}
  #om .col .om-intro p+p{margin-top:12px}
  .om-intro,.om-cols{display:grid; grid-template-columns:minmax(0,1fr) minmax(0,1fr); column-gap:48px}
  .om-intro>*{grid-column:1}
  .om-cols{margin-top:48px}
  #om h2{margin:0 0 8px}
  #om section+section{margin-top:40px}
  .om-right{display:flex; flex-direction:column}
  .om-right section:last-of-type{margin-bottom:40px}
  #om-play{margin-top:auto}
  #om p{text-wrap:pretty}
}
