/* Perilscope: a periscope lens over a dark map, in a flood control room at 3am.
   One accent colour. Red is kept for real danger. Numbers are monospaced. */

@font-face { font-family: 'B612'; src: url('vendor/fonts/b612-400.woff2') format('woff2'); font-weight: 400; font-display: swap; }
@font-face { font-family: 'B612'; src: url('vendor/fonts/b612-700.woff2') format('woff2'); font-weight: 700; font-display: swap; }
@font-face { font-family: 'Martian Mono'; src: url('vendor/fonts/martian-mono-400.woff2') format('woff2'); font-weight: 400; font-display: swap; }
@font-face { font-family: 'Martian Mono'; src: url('vendor/fonts/martian-mono-700.woff2') format('woff2'); font-weight: 700; font-display: swap; }

:root {
  --abyss: #04191d;      /* the room */
  --deep: #072529;       /* raised surfaces */
  --channel: #17505a;    /* rules and hairlines */
  --foam: #ddf1ec;       /* main text */
  --silt: #9cc2bb;       /* quieter text */
  --amber: #ffb000;      /* the one accent */
  --danger: #ff5a47;     /* real danger only */
  --water: #2aa9c4;
  --text: 'B612', 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
  --mono: 'Martian Mono', ui-monospace, Menlo, Consolas, monospace;
}

* { box-sizing: border-box; }
html, body { height: 100%; }
body {
  margin: 0;
  display: grid;
  grid-template-rows: auto minmax(0, 1fr) auto;
  height: 100dvh;
  background: var(--abyss);
  color: var(--foam);
  font: 400 15px/1.5 var(--text);
  -webkit-font-smoothing: antialiased;
}
h1, h2, h3, p, ul, ol { margin: 0; padding: 0; }
ul, ol { list-style: none; }
a { color: var(--foam); text-underline-offset: 2px; }
a:hover { color: var(--amber); }
button { font: inherit; color: inherit; cursor: pointer; touch-action: manipulation; }
:focus-visible { outline: 2px solid var(--amber); outline-offset: 2px; }
.defs { position: absolute; }
[hidden] { display: none !important; }

/* ---------- Top: name and search ---------- */

.top {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.25fr) minmax(0, 1fr);
  gap: 8px 28px;
  align-items: center;
  padding: 10px 24px;
  border-bottom: 1px solid var(--channel);
}
.brand h1 { font: 700 28px/1.1 var(--text); letter-spacing: .01em; }
.brand p { color: var(--silt); font-size: 13.5px; line-height: 1.35; }
.search { display: grid; gap: 4px; }
.field { display: flex; gap: 8px; align-items: center; }
.field label { font-weight: 700; white-space: nowrap; }
.field input {
  flex: 1;
  min-width: 0;
  min-height: 44px;
  padding: 6px 12px;
  background: var(--deep);
  border: 1px solid var(--silt);
  border-radius: 2px;
  color: var(--foam);
  font: 700 17px/1 var(--mono);
  text-transform: uppercase;
}
.field input::placeholder { color: #6f9a94; font-weight: 400; }
.field button {
  min-height: 44px;
  padding: 0 24px;
  background: var(--amber);
  border: 0;
  border-radius: 2px;
  color: #1a1000;
  font-weight: 700;
}
.field button:hover { background: #ffc233; }
.message { color: var(--amber); font-weight: 700; }
.message:empty { display: none; }
.note { color: var(--silt); font-size: 13px; line-height: 1.4; }
.note strong { color: var(--foam); font-weight: 700; }

/* ---------- The deck: lens on the left, readouts on the right ---------- */

.deck {
  display: grid;
  grid-template-columns: minmax(0, 54fr) minmax(0, 46fr);
  min-height: 0;
}
.scope {
  display: grid;
  grid-template-rows: auto minmax(0, 1fr) auto;
  gap: 6px;
  padding: 10px 24px 8px;
  min-height: 0;
  border-right: 1px solid var(--channel);
}
.fix { display: flex; justify-content: space-between; gap: 16px; align-items: start; min-height: 68px; }   /* room for a two-line note, so the lens never changes size mid-scan */
.place { font: 700 23px/1.2 var(--mono); }
.place-note { color: var(--silt); font-size: 13px; }
.fix-right { text-align: right; flex-shrink: 0; white-space: nowrap; }   /* a long place name wraps; these readouts never do, or the lens changes size */
.coords { font: 400 11.5px/1.6 var(--mono); color: var(--silt); }
.progress { font: 400 11.5px/1.6 var(--mono); color: var(--amber); min-height: 1.6em; }

/* The lens takes whatever room the well has, leaving space for the bezel around it. */
.lens-well { display: grid; place-items: center; min-height: 0; container-type: size; }
.lens { position: relative; width: 88cqmin; height: 88cqmin; }
#map {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  overflow: hidden;
  background: var(--abyss);
  isolation: isolate;
}
.lens::after {  /* the dark edge of the glass */
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 50%;
  pointer-events: none;
  box-shadow: inset 0 0 0 1px var(--channel), inset 0 0 70px 18px rgba(2, 12, 14, .85);
}
/* OpenStreetMap's tiles, turned into a single deep blue-green so nothing on the base map competes with amber or red.
   On each tile and not on the tile pane, because WebKit (Safari's engine) ignored the filter on the pane. */
.leaflet-tile { filter: grayscale(1) invert(1) sepia(1) hue-rotate(128deg) saturate(1.5) brightness(.62) contrast(1.2); }
/* The service only sends its own navy and pale blue, so they are shifted to our water colours here. */
.flood-image { filter: hue-rotate(-52deg) saturate(2.1) brightness(1.15); opacity: .8; }
.leaflet-container { background: var(--abyss); font-family: var(--text); }
.leaflet-container .leaflet-control-attribution {
  background: rgba(4, 25, 29, .86);
  color: var(--foam);
  font-size: 11px;
  padding: 1px 6px;
}
.leaflet-control-attribution a { color: var(--foam); }
.leaflet-bottom.leaflet-right { right: 50%; transform: translateX(50%); bottom: 9%; white-space: nowrap; }
.leaflet-tooltip { background: var(--deep); color: var(--foam); border: 1px solid var(--channel); font-family: var(--text); }

.sweep {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  pointer-events: none;
  opacity: 0;
  background: conic-gradient(from 0deg, rgba(255, 176, 0, 0) 0deg 285deg, rgba(255, 176, 0, .32) 360deg);
}
.scanning .sweep { opacity: 1; animation: sweep 2.8s linear infinite; }
@keyframes sweep { to { transform: rotate(360deg); } }

.ping {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 2px solid var(--amber);
  pointer-events: none;
  animation: ping .9s ease-out forwards;
}
@keyframes ping { from { transform: scale(.04); opacity: .9; } to { transform: scale(1); opacity: 0; } }

.reticle {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  fill: none;
  stroke: var(--amber);
  stroke-width: .35;
  opacity: .75;
}
.bezel {
  position: absolute;
  inset: -6%;
  width: 112%;
  height: 112%;
  pointer-events: none;
  overflow: visible;
}
.bezel .tick { stroke: var(--silt); stroke-width: .35; }
.bezel .tick.major { stroke: var(--foam); stroke-width: .6; }
.bezel text { fill: var(--silt); font: 400 4.2px var(--mono); text-anchor: middle; dominant-baseline: central; }
.bezel text.cardinal { fill: var(--foam); font-weight: 700; font-size: 5.4px; }
.bezel .seg { fill: none; stroke-width: 2.2; stroke: var(--channel); }
.bezel .seg.checking { stroke: var(--silt); stroke-dasharray: 1 1.4; }
.bezel .seg.found { stroke: var(--amber); }
.bezel .seg.found.plain { stroke: var(--foam); }
.bezel .seg.found.danger { stroke: var(--danger); }
.bezel .seg.nothing { stroke: var(--silt); stroke-width: .9; }
.bezel .seg.notcovered { stroke: var(--channel); stroke-width: .9; }
.bezel .seg.unknown { stroke: var(--foam); stroke-dasharray: .8 1.6; }

.zoom { position: absolute; right: -2%; bottom: -2%; display: grid; gap: 6px; }
.zoom button {
  width: 44px;
  height: 44px;
  background: var(--deep);
  border: 1px solid var(--channel);
  border-radius: 2px;
  font: 700 18px/1 var(--mono);
}
.zoom button:hover { border-color: var(--amber); color: var(--amber); }

.legend { font-size: 12.5px; color: var(--silt); }
body:not(.scanned) .legend { visibility: hidden; }
.legend ul { display: flex; flex-wrap: wrap; gap: 2px 14px; }
.legend li { display: inline-flex; align-items: center; gap: 6px; }
.key { display: inline-block; width: 12px; height: 12px; flex: none; }
/* The service's own colours with the same filter as the map image, so the legend matches exactly. */
.key.zone3, .key.zone2 { filter: hue-rotate(-52deg) saturate(2.1) brightness(1.15); opacity: .8; }
.key.zone3 { background: #394386; }
.key.zone2 { background: #9bcffb; }
.key.burglary { border-radius: 50%; background: var(--amber); }
.key.vehicle { border-radius: 50%; background: var(--foam); }
.key.other { border-radius: 50%; background: #5f9d9c; }
.key.gauge { width: 0; height: 0; border: 6px solid transparent; border-bottom: 11px solid var(--amber); border-top: 0; }
.key.mile { border-radius: 50%; border: 1.5px dashed var(--amber); }
.flood-layer { color: var(--foam); min-height: 2.9em; line-height: 1.45; margin-top: 3px; }
.flood-layer.warn { color: var(--amber); font-weight: 700; }
.lane-wait { color: var(--amber); font-size: 12.5px; line-height: 1.3; min-height: 1.3em; }

/* ---------- Results ---------- */

.panel { overflow-y: auto; padding: 14px 24px 24px; min-height: 0; scrollbar-color: var(--channel) transparent; }
.intro h2 { font: 700 22px/1.2 var(--text); margin-bottom: 6px; }
.intro p { max-width: 60ch; color: var(--silt); }
.intro .intro-lead { color: var(--foam); margin-top: 10px; }

.samples { margin-top: 10px; border-top: 1px solid var(--channel); }
.samples button {
  display: grid;
  grid-template-columns: 104px minmax(0, 1fr);
  gap: 14px;
  align-items: baseline;
  width: 100%;
  min-height: 44px;
  padding: 8px 4px;
  background: none;
  border: 0;
  border-bottom: 1px solid var(--channel);
  text-align: left;
}
.samples button:hover { background: var(--deep); }
.samples b { font: 700 13.5px/1.3 var(--mono); color: var(--amber); }
.samples span { color: var(--silt); }

/* After the first scan the list shrinks to a row, so the two York postcodes stay one click apart. */
.scanned .samples { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 12px; border: 0; }
.scanned .samples button { display: block; width: auto; padding: 4px 10px; min-height: 36px; border: 1px solid var(--channel); border-radius: 2px; }
.scanned .samples span { display: none; }
.scanned .samples b { font-size: 11.5px; color: var(--foam); }
.scanned .samples .current { border-color: var(--amber); }
.scanned .samples .current b { color: var(--amber); }

.group { margin-bottom: 22px; }
.group > h2 { font: 700 21px/1.2 var(--text); padding-bottom: 6px; border-bottom: 2px solid var(--silt); }
.group-credit { margin-top: 8px; color: var(--silt); font-size: 12.5px; line-height: 1.4; }

.row {
  display: grid;
  grid-template-columns: 20px minmax(0, 1fr) auto;
  gap: 0 10px;
  padding: 10px 0 11px;
  border-bottom: 1px solid var(--channel);
}
.glyph { width: 18px; height: 18px; margin-top: 2px; color: var(--silt); }
.row-label { font: 400 14px/1.4 var(--text); color: var(--silt); }
.row-state { font-size: 13px; color: var(--silt); text-align: right; white-space: nowrap; }
.row-value { grid-column: 2 / -1; font: 700 21px/1.25 var(--text); margin-top: 1px; overflow-wrap: anywhere; }
.row-value.num { font: 700 20px/1.3 var(--mono); }
.row-value.long { font-size: 17px; line-height: 1.35; }
.row-text { grid-column: 2 / -1; color: var(--silt); font-size: 13.5px; line-height: 1.45; margin-top: 2px; max-width: 66ch; }
.row-extra { grid-column: 2 / -1; }

.row[data-state='checking'] .glyph { animation: turn 3s linear infinite; }
.row[data-state='checking'] .row-value { color: var(--silt); font-weight: 400; font-size: 15px; }
@keyframes turn { to { transform: rotate(360deg); } }
.row[data-state='found'] .glyph { color: var(--foam); }
.row[data-state='found'][data-tone='alert'] .glyph,
.row[data-state='found'][data-tone='alert'] .row-value,
.row[data-state='found'][data-tone='alert'] .row-state { color: var(--amber); }
.row[data-state='found'][data-tone='danger'] .glyph,
.row[data-state='found'][data-tone='danger'] .row-value,
.row[data-state='found'][data-tone='danger'] .row-state { color: var(--danger); }
.row[data-state='nothing'] .row-value { font-weight: 400; font-size: 17px; }
.row[data-state='notcovered'] .row-value { font-weight: 700; font-size: 17px; color: var(--foam); }
/* A run of "not covered" rows explains itself once, on the first row. */
.row[data-state='notcovered'] + .row[data-state='notcovered'] .row-text { display: none; }
.row[data-state='notcovered'] .row-state { color: var(--foam); }
.row[data-state='unknown'] { border-left: 2px dashed var(--foam); margin-left: -10px; padding-left: 8px; }
.row[data-state='unknown'] .glyph { color: var(--foam); }
.row[data-state='unknown'] .row-state { color: var(--foam); font-weight: 700; }
.row[data-state='unknown'] .row-value { font-size: 17px; }
.again { margin-top: 6px; min-height: 36px; padding: 0 14px; background: none; border: 1px solid var(--foam); border-radius: 2px; color: var(--foam); }
.again:hover { border-color: var(--amber); color: var(--amber); }

/* A saved answer must never look like a live one: a dashed mark down the side, its date in amber, and a way to ask live. */
.row[data-saved='yes'] { border-left: 2px dashed var(--amber); margin-left: -10px; padding-left: 8px; }
.row-saved { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 12px; margin-top: 6px; color: var(--amber); font-size: 13px; }
.row-saved .again { margin-top: 0; border-color: var(--amber); color: var(--amber); }
.row-saved .again:hover { background: var(--amber); color: var(--abyss); }
.link-button { min-height: 24px; padding: 0; background: none; border: 0; color: var(--amber); text-decoration: underline; text-underline-offset: 2px; }

.warn-list { margin-top: 6px; }
.warn-list li { padding: 6px 0; border-top: 1px dashed var(--channel); font-size: 13.5px; }
.warn-list b { color: var(--amber); }
.warn-list .serious b { color: var(--danger); }

.crime-big { display: flex; flex-wrap: wrap; gap: 4px 28px; margin-top: 6px; }
.crime-big div { min-width: 9ch; }
.crime-big b { display: block; font: 700 32px/1.1 var(--mono); color: var(--amber); }
.crime-big span { color: var(--silt); font-size: 13px; }
.crime-small { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 0 18px; margin-top: 8px; font-size: 13.5px; }
.crime-small div { display: flex; justify-content: space-between; gap: 10px; padding: 2px 0; border-bottom: 1px dotted var(--channel); }
.crime-small b { font: 400 12.5px/1.6 var(--mono); }
.row-note { margin-top: 6px; color: var(--silt); font-size: 13px; }

.storm-big { display: flex; flex-wrap: wrap; gap: 4px 28px; margin: 6px 0 2px; }
.storm-big b { display: block; font: 700 15px/1.4 var(--mono); }
.storm-big span { color: var(--silt); font-size: 13px; }

/* The river gauge: a real staff gauge, with now, typical high and record on one scale. */
.gauge { margin-top: 8px; width: 100%; max-width: 440px; display: block; font-family: var(--mono); }
.gauge .band { fill: var(--foam); opacity: .24; }
.gauge .water { fill: var(--water); opacity: .55; }
.gauge .frame { fill: none; stroke: var(--silt); stroke-width: 1; }
.gauge line { stroke-width: 1.5; }
.gauge .now-line { stroke: var(--amber); stroke-width: 2.5; }
.gauge .now-line.danger { stroke: var(--danger); }
.gauge .high-line { stroke: var(--foam); stroke-dasharray: 4 3; }
.gauge .record-line { stroke: var(--foam); }
.gauge .lead { stroke: var(--channel); stroke-width: 1; }
.gauge text { fill: var(--foam); font-size: 12px; }
.gauge text.big { fill: var(--amber); font-weight: 700; font-size: 15px; }
.gauge text.big.danger { fill: var(--danger); }
.gauge text.small { fill: var(--silt); font: 400 12px var(--text); }

.years { width: 100%; max-width: 480px; display: block; margin-top: 8px; font-family: var(--mono); }
.years .axis { stroke: var(--silt); stroke-width: 1; }
.years .year { stroke: var(--amber); stroke-width: 3; }
.years text { fill: var(--silt); font-size: 11px; }
.year-list { font: 400 11.5px/1.6 var(--mono); color: var(--foam); margin-top: 2px; }

/* ---------- Quote impact: a ledger, read from top to bottom ---------- */

.quote { margin-bottom: 26px; padding-top: 2px; }
.quote > h2 { font: 700 21px/1.2 var(--text); padding-bottom: 6px; border-bottom: 2px solid var(--silt); }
.quote-notice { margin: 8px 0 4px; font-weight: 700; color: var(--foam); }
.ledger { width: 100%; border-collapse: collapse; margin-top: 4px; font-size: 13.5px; }
.ledger td { padding: 6px 6px 6px 0; border-bottom: 1px solid var(--channel); vertical-align: baseline; }
.ledger .f { font: 700 12.5px/1.3 var(--mono); white-space: nowrap; width: 58px; }
.ledger .why { color: var(--silt); display: block; font-size: 12.5px; }
.ledger .amount { font: 400 12.5px/1.3 var(--mono); text-align: right; white-space: nowrap; padding-right: 0; }
.ledger tr.raised .f, .ledger tr.raised .amount { color: var(--amber); }
.ledger tr.unknown td { color: var(--foam); }
.ledger tr.unknown .f { color: var(--foam); }
.ledger tr.waiting td { color: var(--silt); }
.quote-result { margin-top: 12px; }
.quote-result b { display: block; font: 700 34px/1.15 var(--mono); }
.quote-result.refer b { color: var(--amber); font: 700 30px/1.15 var(--text); }
.quote-result.danger b { color: var(--danger); }
.quote-result.waiting b { color: var(--silt); font: 400 18px/1.3 var(--text); }
.quote-result p { color: var(--silt); font-size: 13.5px; margin-top: 4px; max-width: 62ch; }
.quote-subs { margin-top: 12px; padding-top: 8px; border-top: 1px dashed var(--channel); color: var(--silt); font-size: 13px; }
.quote-subs strong { color: var(--foam); }

.credits { padding-top: 10px; border-top: 2px solid var(--silt); color: var(--silt); font-size: 12.5px; line-height: 1.45; }
.credits h2 { font: 700 16px/1.3 var(--text); color: var(--foam); margin-bottom: 4px; }
.credits p { margin-bottom: 6px; max-width: 70ch; }
.credits strong { color: var(--foam); font-weight: 700; }

/* ---------- The call strip ---------- */

.strip {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: stretch;
  border-top: 1px solid var(--channel);
  background: var(--deep);
}
.strip h2 { padding: 10px 14px; font: 700 13px/1.3 var(--text); border-right: 1px solid var(--channel); }
.strip h2 span { display: block; font: 700 16px/1.3 var(--mono); color: var(--amber); }
#calls { display: flex; gap: 0; overflow-x: auto; scrollbar-width: thin; scrollbar-color: var(--channel) transparent; }
.calls-empty { padding: 16px 14px; color: var(--silt); font-size: 13px; white-space: nowrap; }
.call {
  flex: 0 0 auto;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 0 10px;
  width: 300px;
  padding: 7px 12px;
  background: none;
  border: 0;
  border-right: 1px solid var(--channel);
  text-align: left;
}
.call:hover { background: #0b3238; }
.call b { font: 700 13px/1.4 var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.call .result { font: 700 11.5px/1.6 var(--mono); text-align: right; white-space: nowrap; }
.call .where { grid-column: 1 / -1; font: 400 12px/1.4 var(--text); color: var(--silt); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.call[data-kind='ok'] .result { color: var(--foam); }
.call[data-kind='bad'] .result { color: var(--amber); }
.call[data-kind='busy'] .result { color: var(--silt); font-weight: 400; }
.call[data-kind='off'] { opacity: .65; }
.call[data-kind='saved'] { outline: 1px dashed var(--amber); outline-offset: -3px; }
.call[data-kind='saved'] .result { color: var(--amber); font-weight: 400; }
.call-mark { flex: 0 0 auto; align-self: center; padding: 0 14px; font: 700 12.5px/1.2 var(--mono); color: var(--amber); white-space: nowrap; border-right: 1px solid var(--channel); }

.raw {
  width: min(900px, 94vw);
  max-height: 86dvh;
  padding: 16px 18px;
  background: var(--deep);
  color: var(--foam);
  border: 1px solid var(--silt);
  border-radius: 2px;
}
.raw::backdrop { background: rgba(0, 10, 12, .72); }
.raw-head { display: flex; justify-content: space-between; align-items: center; gap: 16px; }
.raw-head h2 { font: 700 18px/1.3 var(--text); }
.raw-head button { min-height: 44px; padding: 0 18px; background: none; border: 1px solid var(--silt); border-radius: 2px; }
.raw-head button:hover { border-color: var(--amber); color: var(--amber); }
.raw-url { margin-top: 8px; font: 400 11.5px/1.6 var(--mono); overflow-wrap: anywhere; color: var(--foam); }
.raw-meta { margin: 6px 0 10px; font: 400 11.5px/1.5 var(--mono); color: var(--amber); }
.raw pre { margin: 0; padding: 10px; max-height: 58dvh; overflow: auto; background: var(--abyss); font: 400 11.5px/1.6 var(--mono); white-space: pre-wrap; overflow-wrap: anywhere; }
.raw img { display: block; max-width: 100%; background: #3b5a5e; }

/* ---------- Laptop height squeeze, then phones ---------- */

/* Short laptop screens: give the height to the lens. */
@media (max-height: 800px) and (min-width: 901px) {
  .top { padding-top: 6px; padding-bottom: 6px; }
  .brand h1 { font-size: 24px; }
  .brand p { display: none; }
  .scope { padding-top: 6px; padding-bottom: 6px; gap: 2px; }
  .fix { min-height: 62px; }
  .place { font-size: 19px; }
  .legend { font-size: 11.5px; }
  .legend ul { gap: 0 9px; }
  .flood-layer { min-height: 1.45em; }
}

@media (max-width: 900px) {
  html, body { height: auto; }
  body { display: block; height: auto; }
  .top { grid-template-columns: 1fr; padding: 12px 16px; }
  .field { flex-wrap: wrap; }
  .field label { width: 100%; }
  .field input { font-size: 18px; }
  .deck { display: block; }
  .scope { display: block; padding: 10px 16px 10px; border-right: 0; border-bottom: 1px solid var(--channel); }
  .fix { flex-direction: column; gap: 2px; min-height: 0; }
  .fix-right { text-align: left; }
  /* Before the first scan, keep the sample postcodes on the first screen. */
  body:not(.scanned) .fix, body:not(.scanned) .legend, body:not(.scanned) .intro p { display: none; }
  body:not(.scanned) .lens-well { width: 74%; margin: 0 auto; }
  body:not(.scanned) .zoom { display: none; }
  .leaflet-container .leaflet-control-attribution { font-size: 10px; }
  .leaflet-bottom.leaflet-right { bottom: 16%; }
  @media (orientation: landscape) {
    .top { grid-template-columns: 1fr 1.4fr; }
    .note { grid-column: 1 / -1; }
    .field label { width: auto; }
    .field { flex-wrap: nowrap; }
  }
  /* A short screen has no room for both, so the sample postcodes come before the lens until the first scan. */
  @media (max-height: 800px) {
    body:not(.scanned) .deck { display: flex; flex-direction: column-reverse; }
  }
  /* A phone on its side: the place name and readouts sit side by side, so the lens fits under them. */
  @media (orientation: landscape) and (max-height: 500px) {
    .fix { flex-direction: row; }
    .fix-right { text-align: right; }
  }
  .lens-well { width: 100%; max-height: 72dvh; aspect-ratio: 1; margin: 6px 0; }
  .zoom { right: -24px; bottom: -14px; }
  .panel { overflow: visible; padding: 14px 16px 24px; }
  .place { font-size: 22px; }
  .strip { position: sticky; bottom: 0; z-index: 1000; padding-bottom: env(safe-area-inset-bottom); }
  .call { width: 220px; }
  .row-state { font-size: 12.5px; }
}

@media (prefers-reduced-motion: reduce) {
  .scanning .sweep { animation: none; opacity: .55; }
  .ping { display: none; }
  .row[data-state='checking'] .glyph { animation: none; }
}
