/* Shvil HaNegev — shared stylesheet.
   Mobile (375px) first; desktop is a media query that centers and caps width.
   RTL is the native direction: every spacing rule uses logical properties,
   never left/right. Palette from docs/design.md — loess, ink, brass, water.

   Four rules decide everything below, and they come from the director:

   1 · The photograph commands the screen (docs/design.md, "Linguagem visual",
       11 August 2026). A large picture at the top of the point page with the
       content sheet rising over its lower edge; a thumbnail on every list
       card. The product is about places, and a place is recognised by looking.
   2 · The interface never writes what it does not have. There is no styling
       here for an empty state, because an empty block is never rendered — and
       that includes the thumbnail: a record with no picture gets a text card,
       never a grey box standing in for one.
   3 · Sources live behind one discreet control at the foot of the page.
   4 · Only patterns people already know: a bottom bar with icon and label,
       rounded cards with a thumbnail, a search field at the top, pills for the
       layers, a bottom sheet. Elegance comes from space, type and photography
       — never from a gesture to be learnt, and never from a CSS trick to hold
       an effect together.

   Zero JavaScript, zero webfonts, zero external requests. */

:root {
  color-scheme: light dark;

  /* ---- Palette ----
     The surface is light and neutral, very nearly white, and the material of
     the place comes in as accent rather than as heavy ground: loess fills a
     pill, a tag, the bed a picture sits on, and brass draws the small labels
     and the edges. Before 11 August 2026 loess was the page itself, which put
     a warm mid tone behind every photograph and flattened the whole product
     into one colour. */
  --background: #FBFAF7;          /* the page — near white, a degree warm */
  --surface: #FFFFFF;     /* the card, lifted off the page */
  --loess: #EFE9DA;          /* the city's soil, now an accent surface */
  --ink: #232019;          /* warm near-black */
  --brass: #B08D3E;          /* brass — plaques and stamps; lines and edges */
  --brass-text: #7E5F1C;    /* brass darkened until it is legible as text */

  /* ---- The second accent: oasis turquoise (the director, 11 August 2026) ----
     Brass is the material of the place and it is warm; everything warm in one
     palette gives a page with no cold note anywhere, and the eye stops finding
     the live thing on it. Turquoise is water in the desert — the one colour the
     Negev keeps for the rare thing — so it is what carries STATE: the layer
     being looked at, the control that is ready to be pressed, the link that
     leads out, and the wells themselves. Brass keeps what it always had: the
     labels, the edges, the section headings, the paper of a stamp.
     4.73:1 on the light page and 6.4:1 on the dark one, both past AA. */
  --turquoise: #2E7D74;
  --water: var(--turquoise);   /* the wells layer is the accent itself */

  /* A card lifts off the page with a soft shadow, not with a border. */
  --shadow: 0 1px 2px rgba(35, 32, 25, 0.04),
            0 10px 26px -14px rgba(35, 32, 25, 0.24);
  --border: rgba(35, 32, 25, 0.07);
  --touch: rgba(176, 141, 62, 0.16);   /* the press state, on any surface */

  --radius: 1.35rem;           /* ≈24px — the card corner */
  --radius-small: 0.9rem;        /* ≈16px — the thumbnail, the paired photographs */

  /* System Hebrew stack — no webfont, the site must work offline */
  --font: "Segoe UI", -apple-system, "Noto Sans Hebrew", "David Libre", sans-serif;

  /* Scripture is the one ceremonial element: a printed-page serif, distinct
     from the running text, still system-only so the site works offline. */
  --font-verse: "Frank Ruhl Libre", "David Libre", "Times New Roman", Georgia, serif;

  /* The bottom bar is fixed, so every scrolling surface reserves its height. */
  --bar-height: 4.1rem;

  /* One measure for the whole product, and three places need it as a number:
     the column, the pill row that has to line up with it, and the overlays on
     a full-bleed photograph that have to line up with it too. */
  --measure: 34rem;
  --gutter: 1.15rem;

  /* ---- THE VERTICAL RULER ----

     Three distances, and only three. The director, 17 August 2026: "every page
     I go into, the site jumps" («cada página que entro o site dá um pulo»).
     With the twelve screens measured at 1440px before anything was touched, the
     gaps between sibling blocks were 0, 13, 14, 15, 22, 24, 25, 27, 29, 34, 35,
     66 and 76 pixels — each element carrying the margin whoever wrote it gave it
     on the day they wrote it, and no rhythm the whole page follows. The
     «לפי נקודה קרובה» card and the Beer Sheva feature pressed against each other
     on the home page are the case he caught; the cause is this, and not that
     pair.

     The ruler does not distinguish components, it distinguishes RELATIONS:

       --rhythm-tight  a thing and its caption. The label and the list it
                       names, the title and its photograph. They read as one
                       piece, and the white between them has to be smaller than
                       the white around the piece, or the caption glues itself
                       to the block above.
       --rhythm        two siblings of the SAME nature — two cards, two
                       paragraphs. It is the 0.75rem the point page and `אודות`
                       already used, and that is why it is the one that stays:
                       the ruler does not move what was already right.
       --rhythm-block  two blocks of DIFFERENT natures. It is the only gap that
                       has to be large, because it is the only one that carries
                       information: here one thing ended and another began.

     The three values live here and not in each rule, so that the answer to
     "how much?" is one question with one answer and not twelve. */
  --rhythm-tight: 0.5rem;
  --rhythm: 0.75rem;
  --rhythm-block: 2rem;
}

/* ---- Night, and who decides it ----

   The device decides by default, and that is still the default. What is new is
   that the person can overrule it: `data-theme="dark"` or `"light"` on the root,
   written before the first paint by four lines in the head, and the absence of
   the attribute means "keep following the device".

   THE BLOCK IS WRITTEN TWICE ON PURPOSE, and the duplication is the honest
   shape of it: a media query cannot be widened by a selector, so "the system
   says night and nobody overruled it" and "she chose night" are two different
   conditions with one set of values. They must be edited together — a value
   that lands in one and not the other produces a theme that is right only for
   the people who never touched the control, which is the hardest kind of wrong
   to notice. */

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --background: #15130F;        /* desert night */
    --surface: #221E18;
    --loess: #332C22;        /* the same accent, read by night */
    --ink: #F5F1E8;        /* ink inverts to loess */
    --brass-text: #D2AE60;  /* brass lightened until it is legible as text */
    --turquoise: #4FA79C;     /* oasis, lightened until it is legible as text */
    /* Shadow does not read on a dark page; a hairline does the same work. */
    --shadow: 0 0 0 1px rgba(245, 241, 232, 0.09);
    --border: rgba(245, 241, 232, 0.12);
    --touch: rgba(176, 141, 62, 0.24);
  }
}

:root[data-theme="dark"] {
  color-scheme: dark;
  --background: #15130F;
  --surface: #221E18;
  --loess: #332C22;
  --ink: #F5F1E8;
  --brass-text: #D2AE60;
  --turquoise: #4FA79C;
  --shadow: 0 0 0 1px rgba(245, 241, 232, 0.09);
  --border: rgba(245, 241, 232, 0.12);
  --touch: rgba(176, 141, 62, 0.24);
}

/* Declared, not inherited: on a device set to night the UA would still paint
   its scrollbars and form controls dark under a page she has put in daylight. */
:root[data-theme="light"] {
  color-scheme: light;
}

/* ---- Base ---- */

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

html {
  /* High contrast, large type — validated in direct sun, not on a monitor */
  font-size: 18px;
  -webkit-text-size-adjust: 100%;
}

body {
  min-height: 100vh;
  min-height: 100dvh;
  /* THE SKELETON THAT PINS THE FOOTER TO THE BOTTOM — and `dvh` above, not
     `vh`, because on a phone the browser bar appears and disappears and `vh`
     measures the wrong height. On a page that does not fill the screen
     (`חידון`, `תומכים`) the footer floated 119–261px above the bottom, measured
     at 768 and at 1440 in Hebrew, Spanish and Portuguese. The column here, and
     `main` growing right below it, are what push the footer down without
     touching its margin. */
  display: flex;
  flex-direction: column;
  font-family: var(--font);
  font-size: 1rem;
  line-height: 1.5;
  color: var(--ink);
  background-color: var(--background);
  /* Room for the fixed bar, plus the phone's own bottom inset. */
  padding-block-end: calc(var(--bar-height) + env(safe-area-inset-bottom) + 1rem);
}

/* What gets the leftover space is the middle, and never the footer: with
   `margin-block-start: auto` on the footer, the 2.4rem of air it has above it
   disappeared on every long page, which is nearly all of them. This way the
   short page stretches from the inside and the long one never notices —
   verified to the pixel on `doc` and on the bottom of the footer of nineteen
   pages.

   The map is not part of this: `.map-with-map .map-main` already gives itself
   `flex: 1`, with more specificity than this rule. */
main {
  flex: 1 0 auto;
}

a {
  color: inherit;
  text-decoration: none;
  -webkit-tap-highlight-color: transparent;
}

svg {
  display: block;
  flex-shrink: 0;
}

:focus-visible {
  outline: 3px solid var(--brass-text);
  outline-offset: 2px;
}

/* One measure for the whole product: the phone is the design, the desktop
   is the same column with more air around it. */
.band {
  width: 100%;
  max-width: var(--measure);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

/* ---- The card: the one container in the product ---- */

.card {
  display: block;
  padding: 1.15rem;
  background-color: var(--surface);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}

/* Any card that is a link is also a touch target well past the floor. */
a.card,
button.card {
  min-height: 3.4rem;         /* 61px */
}

a.card:active,
button.card:active {
  background-color: var(--touch);
}

/* Block, because a card is built of spans and each one owns its line. */
.card-title {
  display: block;
  font-size: 1.15rem;
  font-weight: 700;
  line-height: 1.28;
}

/* The small brass label inside a card — "the next one on the trail", the
   distance in the map list. */
.card-label {
  display: block;
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  color: var(--brass-text);
  margin-block-end: 0.15rem;
}

.card-line {
  display: block;
  margin-block-start: 0.25rem;
  font-size: 0.9rem;
  line-height: 1.45;
  opacity: 0.74;
}

/* A card whose whole body is one row: icon · text · chevron */
.card-row {
  display: flex;
  align-items: center;
  gap: 0.9rem;
}

.card-row > .card-text {
  flex: 1;
  min-width: 0;
}

/* ---- The list card: thumbnail · text ----

   Every card in a list carries the picture of its record — the photograph
   first, and when the record has none, the temporary illustration. That is
   what makes a list of places read as places instead of as rows of text.

   A record with neither gets this same card without the thumbnail: the text
   simply takes the full width. No frame, no grey square, no camera glyph —
   a placeholder is the caption of absence, drawn. */

.card-list {
  display: flex;
  align-items: flex-start;
  gap: 0.8rem;
  padding: 0.8rem;
}

.card-list > .card-text {
  flex: 1;
  min-width: 0;
  padding-block: 0.25rem;
  padding-inline-end: 0.35rem;
}

/* One step down from the card title elsewhere: beside a thumbnail the column
   is narrow, and at the larger size a three-word Hebrew name took three
   lines and pushed the picture out of proportion with its own card. */
.card-list .card-title {
  font-size: 1.08rem;
}

/* A station, on a list card: the pin and the name of the place it is inside.
   The same two marks the point page puts under the title, one size down. A
   list that showed a station beside the place it belongs to without saying so
   would read as two places that happen to be named alike. */
.card-parent {
  display: flex;
  align-items: center;
  gap: 0.3rem;
  margin-block-start: 0.4rem;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--brass-text);
}

.card-parent svg {
  width: 0.95rem;
  height: 0.95rem;
}

.card-mini {
  position: relative;
  display: block;
  flex: 0 0 auto;
  width: 5.1rem;              /* 92px */
  height: 5.1rem;
  overflow: hidden;
  background-color: var(--loess);
  border-radius: var(--radius-small);
}

.card-mini img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* The section label above a group of cards. Small, brass, quiet. */
.section-label {
  margin-block: 1.9rem 0.8rem;
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  color: var(--brass-text);
}

/* THE LOCALITY STEP, inside the map's list by distance (A57).

   No new typographic voice: it is the same section label the home page, the
   album, the search and the list already use to say "another group starts
   here". What changes is only the measure of the step — a rule and the air
   above it — because here the label is born between two cards and not at the
   top of a page, and without the rule the eye reads a caption for the next card
   instead of a boundary.

   The first one carries no rule and no air: it sits against the line that
   already says what order the list is in, and on the phone the first fold is
   what costs most. This way the grouping spends 27 px on the first fold and the
   rest of the step only appears where there is a step to mark.

   `border-block-start`, `margin-block` and `padding-block-start` — the step is
   the same in the six languages, and none of them has a side. */
.feed > .section-label.feed-locality {
  margin-block: 1.5rem 0.55rem;
  padding-block-start: 1.05rem;
  border-block-start: 1px solid var(--loess);
  /* A label line is not prose: the leading inherited from the body gave it a
     22 px box for 13 px of letter, and those 5 px all came out of the phone's
     first fold. */
  line-height: 1.3;
}

.feed > .section-label.feed-locality:first-child {
  margin-block-start: 0;
  padding-block-start: 0;
  border-block-start: 0;
}

/* THE END OF THE NAMES — the same rule, with no word at all.

   The records that declare no locality go at the end, with no heading: "no
   locality" would be a caption for an absence, and absence is silence. But
   pressed against the last group they looked as if they belonged to it —
   filtering by «נבטי» put חלוצה and שבטה under «דימונה», which is where ממשית is
   and they are not. The rule says the previous group ended, which is true, and
   writes no name at all, which is what there is not. */
.feed > .feed-step {
  margin-block: 1.5rem 1.35rem;
  border: 0;
  border-block-start: 1px solid var(--loess);
}

/* AND THE STEP PAYS FOR ITSELF.

   The section label was born to live BETWEEN two groups of cards, and so it
   brings 1.9rem of air above it. The caption for the ordering ("by distance
   from the Old City") is not between anything: it is the first line of the
   section, and it already has the top bar above it. It now has the same air
   above as it has below, which gives 19.8 px back to the first fold — nearly
   the 32.7 px the first locality heading costs. Measured at 375 px: three whole
   cards before, three after. */
.map-list > .section-label:first-child {
  margin-block-start: 0.8rem;
}

/* ---- NOTHING IS WRITTEN OVER A PICTURE ----

   There used to be three marks here: a pill in the corner of a temporary
   illustration, a credit lozenge across the foot of the hero photograph, and a
   strip over the thumbnail in every list. All three are gone — the director,
   11 August 2026: no mark on the image, neither burnt into the file nor laid
   over it in HTML.

   What each picture is, and who made it, is said in the credits block at the
   foot of its page (`מקורות`) — where this product has always kept its
   apparatus, and now the only place it lives.

   The chevron points the way the language reads: in RTL, forward is left.
   It is drawn pointing left and mirrored back for a future LTR locale. */
.arrow {
  width: 1.3rem;
  height: 1.3rem;
  color: var(--brass-text);
}

[dir="ltr"] .arrow {
  transform: scaleX(-1);
}

/* ---- The top of the home: brand, question, search ---- */

.top {
  padding-block-start: calc(env(safe-area-inset-top) + 1.4rem);
}

/* The brand at the top of the list and search pages. They wrote שביל הנגב as
   text while the rest of the site already used the logo — the product speaking
   in two voices. Now it is the same piece, with the same way home and the same
   share button as the other bars. */
/* NO MARGIN BELOW since 17 August 2026, and the arithmetic is exact. It
   existed to separate the row from the `<h1>` that came right after it INSIDE
   the same `<header>`; with the title moved into `<main>` — which is what lets
   the header stick to the top — there is no longer anything below it to
   separate.

   And removing it is not neutral: while the two were siblings, its 6.3px and
   the title's 8.1px COLLAPSED into one, and the title sat 83px from the top. In
   `<main>` they no longer collapse — `main` is a flex item of the body and
   margins on flex items never collapse — and the two added up: the title fell
   to 89px and the whole page dropped 6px. Measured at 375 and at 768 in the six
   languages, on the three pages that carry this row. Without the margin, the
   arithmetic comes back to 83. */
.top-brand {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.brand-name {
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  color: var(--brass-text);
}

/* ---- The arrival card ----

   Until 11 August 2026 the home opened by asking `איפה אתה עכשיו?` in title
   size, with the name of the trail small above it. The director turned that
   around: the name is the title, and the question is secondary, sitting on the
   photograph. His reason is that the home is where somebody ARRIVES — from a
   code printed on a wall, most often — and the first thing they see has to say
   where they have arrived before it asks them anything.

   Big and tight: the contrast in this product comes from size, never from a
   box drawn around the words. */
/* The home page brand and the share button on the same line. `align-items:
   flex-start` because the logo is tall and the button must not sink with it: it
   aligns to the top, like a bar control. */
.home-brand {
  display: flex;
  align-items: flex-start;
  gap: 0.5rem;
}

/* The brand. It was text and became the director's logo — on the home page and
   in the header of every inside page, 11 August.

   `width` in `em` and not in pixels: the brand grows and shrinks with the
   page's typography, and so it keeps up with anyone who enlarges the type on
   their phone. The `alt` carries שביל הנגב, which is what the brand says —
   someone listening to the page does not lose the project's name because it
   turned into a drawing. */
.brand-title {
  margin: 0;
  line-height: 0;
}

.brand-title img {
  display: block;
  /* 12em gives ~192px on a 375 screen: the brand introduces itself without
     taking up the whole arrival. In `em` so it keeps up with anyone who
     enlarges the type.

     The `width`/`height` attributes in the HTML are the DISPLAY size and not
     the file's intrinsic one, and that is a defence and not a detail: on the day
     this stylesheet does not reach the browser — which is what happened on 11
     August, with the css outside the cache rule — the brand falls back to 192px
     instead of filling the screen. The ratio is the same: 1432/396 and 192/53
     both give 3.62. */
  width: min(12em, 62%);
  height: auto;
}

/* One line saying what this is. It comes from dados/sobre.json and never from
   this file — a stranger who scanned a code does not know what שביל הנגב is,
   and a card that only carries a name introduces nothing. */
.brand-line {
  margin-block-start: 0.35rem;
  font-size: 1rem;
  line-height: 1.35;
  color: var(--ink-weak, inherit);
  opacity: 0.78;
}

/* Kept for the pages that still open with the old question. */
.question {
  margin-block-start: 0.45rem;
  font-size: 2.2rem;
  font-weight: 700;
  line-height: 1.1;
}

/* ---- The band under the question ----

   The home used to be three buttons and a list; the rest of the product has
   been photograph-led since 11 August. The band is the archive's widest
   photograph (see `faixaDaHome`), a link to the record it belongs to, and a
   credit line under it — never over it.

   `aspect-ratio` with `cover`: the picture is already a panorama, so the crop
   takes a sliver off the ends at most, and the band holds one height whatever
   the file is. Without it the header would jump by a hundred pixels the day a
   different photograph became the widest one. */

.home-band {
  position: relative;
  margin-block-start: 1.15rem;
}

/* The link is the positioning context, not the figure: the caption with the
   photographer's credit lives outside it and must not be veiled. */
.home-band a {
  position: relative;
  display: block;
}

/* THE VEIL, and it is the only reason text over a photograph is safe here.

   A27 forbids text over images everywhere in this product, and the director
   made this one exception knowingly — see the comment in gerar-site.mjs. What
   makes it hold in direct sun is not a shadow on the letters, which fails over
   a bright sky, but a dark gradient occupying the bottom third of the frame.
   The question sits on the veil, not on the photograph. */
.home-veil {
  position: absolute;
  inset-inline: 0;
  inset-block-end: 0;
  block-size: 62%;
  border-end-start-radius: var(--radius);
  border-end-end-radius: var(--radius);
  background: linear-gradient(to top, rgba(24, 21, 17, 0.82), rgba(24, 21, 17, 0.45) 46%, rgba(24, 21, 17, 0));
  pointer-events: none;
}

.home-question {
  position: absolute;
  inset-inline-start: 0.95rem;
  inset-inline-end: 0.95rem;
  inset-block-end: 0.8rem;
  font-size: 1.45rem;
  font-weight: 700;
  line-height: 1.15;
  color: #fdfbf6;
  pointer-events: none;
}

/* `height: auto` is load-bearing and not tidiness: the generator writes the
   file's real width and height onto the tag so the layout does not jump while
   the picture loads, and those attributes land as a presentational `height` in
   pixels. A presentational hint beats `auto`, and `aspect-ratio` only takes
   over when one axis is auto — so without this line the band ignores 21/9 and
   comes out the full height of the photograph. */
.home-band img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 21 / 9;
  object-fit: cover;
  background-color: var(--loess);
  border-radius: var(--radius);
}

.home-band .photo-credit {
  margin-block-start: 0.4rem;
  padding-inline: 0.3rem;
  font-size: 0.7rem;
}

/* THE END OF THE LIST, said out loud.

   The archive list is cut into sheets of about forty, and the last sheet says
   so instead of just stopping. Automatic infinite scroll was considered and
   left out: in a list that is an archive rather than a feed, somebody who
   reaches the bottom should be told they reached the bottom. */
.end-of-list {
  margin-block: 1.6rem 0.5rem;
  text-align: center;
  font-size: 0.86rem;
  color: var(--brass-text);
}

/* The search field is a link that opens the search page — the pattern every
   map and travel app uses, and it needs no script to behave correctly. */
.search {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  min-height: 3.4rem;         /* 61px */
  margin-block-start: 1.3rem;
  padding-inline: 1.15rem;
  background-color: var(--surface);
  border-radius: 999px;
  box-shadow: var(--shadow);
}

.search:active {
  background-color: var(--touch);
}

.search-icon {
  width: 1.35rem;
  height: 1.35rem;
  color: var(--brass-text);
}

.search-text {
  font-size: 1.02rem;
  opacity: 0.75;
}

/* ---- The search page ----
   The same field as the home, except that here it is the real one. It is
   written into the document hidden and revealed by site/busca.js: without a
   script there is nothing behind it to answer, and a search field that cannot
   search is the interface writing what it does not have. What the document
   carries instead is the whole archive, in sheets by layer, with the index
   above it. */

.search-title {
  margin-block-start: 0.45rem;
  font-size: 2.1rem;
  font-weight: 700;
  line-height: 1.1;
}

/* The input takes the whole field: the rounded surface is the form around it,
   so the tap target is the field and not a box inside a box. */
.search-input {
  flex: 1 1 auto;
  min-width: 0;
  min-height: 3.4rem;
  font-family: inherit;
  font-size: 1.02rem;
  color: inherit;
  background: none;
  border: 0;
  outline: none;
}

.search-input::placeholder {
  color: inherit;
  opacity: 0.55;
}

/* The one line that answers the question that was asked — how many, or that
   this one found nothing and what else can be asked. Never a line about the
   archive. */
.search-note {
  margin-block-start: 1.25rem;
  font-size: 0.95rem;
  font-weight: 600;
  line-height: 1.5;
  color: var(--brass-text);
}

#resultados:not([hidden]) {
  margin-block-start: 0.9rem;
}

/* The same cut as the album, and the same reason: at 250 points the browser
   should not lay out every layer to show the first one. */
/* No margin rule alongside it, and that is deliberate: containment stops the
   section label's own top margin from collapsing out, so the gap between two
   sections is the same 1.9rem it always was — now accounted for inside the
   section instead of between them. */
.section-layer {
  content-visibility: auto;
  /* Measured like the album's: a list card averages 10.5rem on the phone and
     the section label costs 3.3rem. The generator writes each section's card
     count into --section-cards; one figure for all of them made the page
     claim a quarter more scroll than it has. */
  contain-intrinsic-size: auto calc(var(--section-cards, 4) * 10.5rem + 3.3rem);
}

/* ---- The layers, as pills that scroll sideways ---- */

.filters {
  margin-block-start: 1.25rem;
  overflow-x: auto;
  overscroll-behavior-inline: contain;
  scrollbar-width: none;
}

.filters::-webkit-scrollbar {
  display: none;
}

/* The row runs edge to edge so a half-cut pill tells the eye it scrolls,
   while its first pill still lines up with the column above it. */
.filters-list {
  display: flex;
  gap: 0.5rem;
  width: max-content;
  min-width: 100%;
  padding-inline: max(var(--gutter), calc((100% - var(--measure)) / 2));
  padding-block: 0.15rem 0.4rem;
  list-style: none;
}

/* Loess as accent: the pill is filled with the soil of the city and carries no
   border, so the row reads as a band of material against the near-white page
   instead of as a row of outlines. */
.pill {
  display: flex;
  align-items: center;
  min-height: 2.75rem;        /* 50px */
  padding-inline: 1.05rem;
  font-size: 0.92rem;
  font-weight: 600;
  white-space: nowrap;
  color: var(--ink);
  background-color: var(--loess);
  border: 1px solid transparent;
  border-radius: 999px;
}

.pill:active {
  background-color: var(--touch);
}

/* ---- ACTIVE IS TURQUOISE, EVERYWHERE IT APPEARS ----
   The pill, the index chip and the destination in the bottom bar are three
   drawings of one idea — "this is the one you are looking at" — and before 11
   August each drew it differently: two of them filled with ink, the third with
   loess. One accent for the three, and the accent is the cold one, because
   state is the thing the eye has to find first on a warm page. */
.pill[aria-current="true"] {
  color: var(--background);
  background-color: var(--turquoise);
  border-color: var(--turquoise);
}

/* ---- The index of layers: a table of contents, in two pages ----
   The album and the search both lay the whole archive out at once, and both
   cut it the same way — one sheet per historical layer. This is the sheet
   list: every layer, how many points it holds, and a link that lands on it.
   It is the same action as a pill and it carries the same href; what it adds
   is the numbers and the completeness, which is why it is read once at the
   top instead of scrolled past sideways.

   IT WAS EATING THE SCREEN, and that is the defect the director found on the
   phone: eleven rows in a two-column grid of 54px cells came to 385px, which
   under the search page's header left about a centimetre of the first card
   showing. A page whose first screen ends in a sliver does not look like a
   page that scrolls — it looks like a page that ended.

   So the grid became a row that wraps, and the cell became a chip. Three
   things came out of the height at once: the cell no longer stretches to the
   column (a short name costs a short chip), the count sits beside the name
   instead of being pushed to the far edge, and the whole index is one
   continuous flow instead of eleven boxes on a fixed pitch. The floor is
   untouched — 2.7rem is 48.6px, and the thumb never notices the difference. */

.index {
  margin-block-start: 1rem;
}

.index-list {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  list-style: none;
}

/* `flex: 0 1 auto` and not `0 0 auto`: a chip is sized by its own name, but a
   layer whose name is longer than the measure has to be able to give way and
   wrap inside itself rather than run off the edge of the page. */
.index-item {
  display: flex;
  align-items: center;
  gap: 0.42rem;
  flex: 0 1 auto;
  max-width: 100%;
  min-height: 2.7rem;         /* 48.6px — the touch floor, and no more */
  padding-block: 0.35rem;
  padding-inline: 0.8rem;
  font-size: 0.86rem;
  font-weight: 600;
  background-color: var(--surface);
  border-radius: var(--radius-small);
  box-shadow: var(--shadow);
}

.index-item:active {
  background-color: var(--touch);
}

.index-item[aria-current="true"] {
  color: var(--background);
  background-color: var(--turquoise);
}

/* A long layer name wraps rather than being cut: "תקופה כלקוליתית" truncated
   to "תקופה כלקול…" is a layer the index fails to name, and naming them is
   what the index is for. The grid stretches the whole row to match. */
.index-name {
  min-width: 0;
  line-height: 1.25;
}

/* dir="ltr" is on the element for the same reason as the album counter: bidi
   reads "4 / 26" backwards inside a right-to-left row. */
.index-count {
  flex: 0 0 auto;
  font-size: 0.8rem;
  font-weight: 700;
  color: var(--brass-text);
}

.index-item[aria-current="true"] .index-count {
  color: var(--background);
}

/* ---- The home feed ---- */

.feature {
  margin-block-start: 1.35rem;
}

.feature-icon {
  width: 1.7rem;
  height: 1.7rem;
  color: var(--brass-text);
}

.feed > * + * {
  margin-block-start: 0.75rem;
}

/* The wells trail wears the water blue — the only blue in the product. */
.trail .card-title,
.trail .trail-icon,
.trail .arrow {
  color: var(--water);
}

.trail-icon {
  width: 1.5rem;
  height: 1.5rem;
}

.tags {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  margin-block-start: 0.6rem;
  list-style: none;
}

/* Filled with loess rather than outlined in brass: on a card that now carries
   a picture, three outlined pills fought the thumbnail for attention. */
.tag {
  padding-block: 0.2rem;
  padding-inline: 0.55rem;
  font-size: 0.76rem;
  font-weight: 600;
  color: var(--brass-text);
  background-color: var(--loess);
  border-radius: 999px;
}

.point-text .tags {
  margin-block-start: 1rem;
}

/* AT THE FOOT OF THE POINT PAGE THE TAG IS A LINK — since 17 August 2026 it
   leads to the map with that layer chosen, and it is what replaced the row of
   filters the map used to have at the top.

   And so it grows. A tag that is only read can be as tall as its text; one that
   is touched with a thumb, in the sun, one-handed, cannot: the pill measured
   28px tall, and the floor for a touch target is 44. All that changes is the
   `padding-block` — 0.62rem on each side puts the box at exactly 44px at 375px,
   and the pill's drawing stays the same as on the cards, where it is still text
   and still small. `min-block-size` closes the arithmetic in the languages with
   lower letterforms. */
.point-text .tag {
  display: flex;
  align-items: center;
  min-block-size: 2.45rem;
  padding-block: 0.62rem;
  padding-inline: 0.85rem;
  font-size: 0.82rem;
  color: var(--brass-text);
  text-decoration: none;
}

.point-text .tag:active {
  background-color: var(--touch);
}

/* ---- The theme: light, dark, or whatever the device says ----

   WHERE IT IS, and why there. The foot of the home, beside `אודות`. This
   product has no settings screen and should not grow one for a single
   preference, and the foot of the home is already the shelf for the things
   that are about the app rather than about a place — it is the one page
   everybody passes through, and `אודות` has lived there since the first build.
   The same control is repeated on `אודות` itself, which is the second door a
   person opens looking for anything of that kind.

   WHAT IT IS: three real radios in a fieldset, drawn as the segmented control
   every phone already has. The input is moved off screen rather than hidden —
   `display: none` would take it out of the tab order and off the keyboard, and
   the whole reason for using radios is that the browser already knows how they
   behave. */

.theme {
  margin-block-start: 1.9rem;
}

.theme-field {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.4rem;
  border: 0;
}

.theme-caption {
  /* `float` and not a grid cell: a <legend> is not a flex item of its own
     fieldset in every engine, and floating it is the one behaviour they all
     agree on. */
  float: inline-start;
  margin-inline-end: 0.75rem;
  padding: 0;
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  color: var(--brass-text);
  line-height: 2.7rem;
}

/* Positioned so the moved-off-screen input is anchored inside its own label
   and not at the corner of whatever happens to be positioned above it. */
.theme-option {
  position: relative;
  display: inline-flex;
}

.theme-option input {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.theme-option span {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 4.4rem;
  min-height: 2.7rem;         /* 48.6px — the floor, again */
  padding-inline: 0.9rem;
  font-size: 0.88rem;
  font-weight: 600;
  background-color: var(--surface);
  border-radius: 999px;
  box-shadow: var(--shadow);
}

/* The chosen segment wears the same turquoise as every other active state in
   the product. Two colours for "this is the one you picked" would be two
   languages for one idea. */
.theme-option input:checked + span {
  color: var(--background);
  background-color: var(--turquoise);
}

.theme-option input:focus-visible + span {
  outline: 3px solid var(--brass-text);
  outline-offset: 2px;
}

/* ---- The signature: who answers for this ----

   Small, quiet, and on every page that scrolls. Each contact is a link that
   does what it says — the address opens the site, the address book opens the
   mail, the number dials. `dir="ltr"` is on each item and never on the block:
   the paragraph is Hebrew, and only the Latin run inside it is not. */

.signature {
  margin-block-start: 2.4rem;
  padding-block: 1.1rem 0.4rem;
  border-block-start: 1px solid var(--border);
  text-align: center;
  opacity: 0.72;
}

.signature-name {
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.04em;
}

.signature-list {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0 1rem;
  list-style: none;
}

.signature-list a {
  display: inline-flex;
  align-items: center;
  min-height: 2.7rem;
  font-size: 0.78rem;
  color: var(--turquoise);
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

/* ============================================================
   THE POINT PAGE
   Vertical order is fixed by docs/design.md: photo · name+line ·
   listen · then/now · scripture · text · onward. A block whose
   material does not exist is not rendered at all — so on a record
   with no photograph the page opens at the name, and there is no
   trace of what is missing.
   ============================================================ */

/* ---- The header bar: back at the inline start, as every app puts it ---- */

/* ON THE PHONE THE BAR DOES NOT STICK, and now it is said rather than
   happening by accident.

   Until 17 August 2026 this rule said `position: sticky`, and the horizontal
   overflow lock silently switched it off (see `html, body` further up). With
   the lock fixed, the declaration would start to take effect — and a header
   stuck to the top eats 68px of the 812 of a phone screen, which is the
   opposite of "nothing essential at the top of the screen" («nada essencial no
   topo da tela») and of what the director asked for on the phone: "the bar
   stays at the bottom and nothing changes" («a barra continua em baixo e nada
   muda»). On desktop it does stick, and that is where the declaration lives
   (the 64rem breakpoint). */
.bar {
  position: static;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding-block: calc(env(safe-area-inset-top) + 0.35rem) 0.35rem;
  background-color: var(--background);
  border-block-end: 1px solid var(--border);
}

/* SHARE. Pushed to the end opposite the back arrow by
   `margin-inline-start: auto` — which in an RTL layout puts it on the left all
   by itself, without one conditional line. This is why every bit of spacing
   here is logical.

   The green "copied" tick lives in the ::after and lasts 1.6s. Without
   confirmation, whoever copies the address does not know they copied it, and
   presses again. */
/* THE LANGUAGES — the menu opens OVER the page and pushes nothing.

   The director sent the screen of what was wrong, and everything was: the panel
   in the flow pushing the page down, the list bullets, and the triangle the
   browser puts on every `<summary>`. Three defects and one cause: I had written
   the menu counting on styles his device did not have yet.

   Now none of this depends on luck:
   · `position: absolute` on the panel and `relative` on the block — it floats,
     and the page underneath does not move.
   · `list-style: none` on the `<ul>`, on the `<li>` AND on the `<summary>`,
     plus the `::marker` and the `::-webkit-details-marker`. Each browser hides
     the marker in a different place, and missing one leaves the bullet in view.
   · `z-index` above the bar, or it opens underneath the photograph.

   The whole block sits in the corner where reading starts — in RTL, the left —
   with the share button immediately beside it. */
.bar-corner {
  display: flex;
  align-items: center;
  gap: 0.15rem;
  margin-inline-start: auto;
}

.langs {
  position: relative;
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.03em;
}

.langs-current {
  display: flex;
  align-items: center;
  gap: 0.25rem;
  min-height: 2.5rem;
  padding-inline: 0.55rem;
  color: var(--ink);
  cursor: pointer;
  list-style: none;
}

.langs-current::marker,
.langs-current::-webkit-details-marker { content: ''; display: none; }

.langs-current svg { transition: transform 140ms ease; }
.langs[open] .langs-current svg { transform: rotate(180deg); }

/* The panel. Its own background, a deep shadow and a trace of border: it has
   to read as a sheet over the page, and not as a piece of it. */
.langs-list {
  position: absolute;
  inset-block-start: calc(100% + 0.2rem);
  inset-inline-start: 0;
  z-index: 60;
  min-width: 4.2rem;
  margin: 0;
  padding: 0.3rem;
  list-style: none;
  background-color: var(--card, #fff);
  border: 1px solid var(--border, rgba(0, 0, 0, 0.08));
  border-radius: 0.8rem;
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.18);
}

.langs-list li {
  display: block;
  list-style: none;
}

.langs-list li::marker { content: ''; }

.langs-list span,
.langs-list a {
  display: block;
  padding: 0.34rem 0.55rem;
  text-align: start;
  border-radius: 0.45rem;
}

.lang-active {
  color: var(--ink);
  background-color: rgba(0, 0, 0, 0.06);
}

/* The other version that EXISTS. It is a real `<a>`, and it leads to the same
   page in the other language — never to the entrance: switching language in the
   middle of a point page is asking for that point page in the other language,
   and sending the person to the home page would lose their place. Full ink,
   because it is a real destination; the underline only on touch, so it does not
   compete with the current language's code. */
.lang-other {
  color: var(--ink);
  text-decoration: none;
}

.lang-other:hover,
.lang-other:focus-visible {
  background-color: var(--touch, rgba(0, 0, 0, 0.06));
}

/* There used to be `.idioma-espera` here, the span at 0.34 opacity for a
   language still to be written. It left with Portuguese: there are six and none
   is missing. The reasoning is in seletorIdioma(), scripts/gerar-site.mjs. */

/* The button has a FIELD, and it is not decoration: without it it is a loose
   line icon in a corner, and the director looked for it and did not find it. A
   control has to look like a control. And the `width`/`height` on the SVG
   itself is the same defence as the brand's: on the day this stylesheet does
   not arrive, it stays at 22px instead of the 4px an SVG with no measurement
   shrinks to — which is exactly what happened. */
.bar-share {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  height: 2.75rem;
  padding: 0;
  color: var(--ink);
  background-color: var(--card, rgba(0, 0, 0, 0.05));
  border: 0;
  border-radius: 999px;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.09);
}

.bar-share svg { width: 1.35rem; height: 1.35rem; }

.bar-share.is-done { color: var(--turquoise); }

.bar-share.is-done::after {
  content: 'הועתק';
  position: absolute;
  inset-block-start: 3.1rem;
  inset-inline-end: 0.6rem;
  padding: 0.3rem 0.7rem;
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--background);
  background-color: var(--turquoise);
  border-radius: 999px;
}

.bar-back {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 3rem;                /* 54px square */
  height: 3rem;
  margin-inline-start: -0.6rem;
  border-radius: 999px;
}

.bar-back:active {
  background-color: var(--touch);
}

.bar-back svg {
  width: 1.5rem;
  height: 1.5rem;
}

[dir="ltr"] .bar-back svg {
  transform: scaleX(-1);
}

/* The brand in the bar. 8.2em of width gives about 118px at the default
   typography — the bar's height rules, and above that the acacia pushes the bar
   down. */
/* Clicking the brand goes back home. It is the convention everybody already
   brings from every other site, and the director caught that ours did not
   honour it. On the home page it is not a link: you are already there, and a
   link to the page you are on is a dead control. The target is a whole bar
   tall — a thumb does not hit a 29px strip. */
.bar-home {
  display: flex;
  align-items: center;
  min-height: 2.75rem;
}

.bar-brand {
  width: 6.6em;
  height: auto;
  align-self: center;
}

/* ---- The photograph: it commands the screen ----

   Full bleed, large, no frame and no filter — the one-second confirmation,
   "yes, this is the place". The content sheet below rises over its lower edge,
   which is why nothing important is written down there. */

/* THE PHOTOGRAPH'S WIDTH IS THE READING WIDTH, and on the phone that changes
   nothing.

   The director, 17 August 2026: "the images at the top on desktop always end up
   badly framed, maybe make them smaller horizontally, they would frame better,
   and raise the height of the image field a little" («as imagens do topo no
   desktop ficam sempre mal enquadradas, talvez fazer elas menores na
   horizontal, elas se enquadrariam melhor, e aumentar um pouco a altura do
   campo da imagem»).

   His intuition is the whole correction, and the measurement says why. The
   frame was full bleed and its height was pinned to 34vh: at 1440×900 that gave
   1425×306, a ratio of 4.66 for an archive whose median photograph measures
   1.333. 31% of the photograph survived, and what was cut was the top and the
   bottom, which is where the heads and the roofs are. At 375 the same rule gives
   375×276 — 1.358, almost exactly the archive's median — and that is why on the
   phone there never was any defect at all: the photograph simply could not be
   wider than the screen.

   `max-inline-size: var(--measure)` is what brings the desktop back to the
   phone's case: the photograph takes the width of the reading column, the same
   one as the sheet that rises over it, and below 34rem of window the
   declaration does nothing. */
.point-photo {
  position: relative;
  width: 100%;
  max-inline-size: var(--measure);
  margin-inline: auto;
  background-color: var(--loess);
}

/* 4/3 IS NOT TASTE, IT IS THE MEASUREMENT OF THE 265 PUBLISHED PHOTOGRAPHS.

   Half of them (49.3%) fall between 1.25 and 1.45; the median is 1.333 and the
   upper quartile 1.50. Searching for the frame ratio that crops least over the
   real archive, the optimum comes out at 1.334 — it keeps 88.1% of each
   photograph on average across the 166 covers, against 31.3% for the 1425×306
   frame that was here. `4 / 3` is that number written as a fraction.

   AND THE CEILING IN VH STAYS, because it is what solved a real defect: at 44vh
   the listen button fell below the fold on a phone, and the director sent the
   screen to prove it. Here it stops ruling the shape and becomes only a limit:
   where there is height, the frame takes the archive's ratio; where there is
   not, it shortens — and a shorter frame is only a bigger crop, never a
   distorted image, because `cover` is what takes care of that. At 375×812 and
   at 375×667 the ceiling still wins and the frame comes out identical to the
   old one, to the pixel.

   `height: auto` is the usual one and it is needed: the tag's `width`/`height`
   attributes arrive as a presentational height in pixels, a hint that beats the
   implicit `auto`, and without this line the `aspect-ratio` would never get to
   be used. */
.point-photo img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 3;
  max-block-size: clamp(12rem, 34vh, 20rem);
  object-fit: cover;
}

/* The temporary illustration takes the photograph's place, never a place of
   its own beside it — the two never coexist, because the illustration exists
   only while the photograph does not.

   One thing about it is different, and it is not decoration: it is the only
   picture in the product that is never cropped. A photograph survives the
   crop of a hero frame; an editorial plate is a whole composition, and cutting
   its sides destroys it. So it keeps its own proportion and, where the window
   is wide enough to make that too tall, it is contained on the loess ground
   the illustration itself is printed on. */
.point-illustration img {
  height: auto;
  /* `aspect-ratio: auto` undoes the 4/3 of the sibling above, and it is what
     keeps this block's promise: the illustration is the one image in the
     product that is never cropped, and a fixed-ratio frame would crop it. It
     goes on measuring what it is. */
  aspect-ratio: auto;
  max-height: 34vh;
  object-fit: contain;
}

/* ---- The credit, under a picture and never on it ----

   Almost every photograph in this archive is CC BY or CC BY-SA, and both ask
   for attribution on the page that publishes the work. Until 11 August 2026
   the hero carried it as a dark lozenge laid over the picture's lower corner;
   the director took every mark off the images, and the attribution moved
   entirely into the `מקורות` block at the foot of the page, where it keeps
   the one thing the lozenge never had — the link back to the file itself.

   What survives here is the caption under each frame of the then/now pair.
   That is a caption inside a card, printed under the picture the way a printed
   page does it, and there is no photograph beneath the words. */
.photo-credit {
  display: block;
  font-size: 0.78rem;
  line-height: 1.45;
  font-weight: 400;
  color: var(--ink);
  opacity: 0.62;
}

/* ---- The sheet: the content rises over the picture ----

   No class decides this — the adjacency does. `paginaPonto` writes the figure
   immediately before the main column when, and only when, there is a picture,
   so a record without one has nothing to rise over and the rule never
   matches. One less flag to keep in step with the generator. */

/* THE YEAR OF THE PHOTOGRAPH, and only on the demolished point.

   It sits BELOW the image and never over it — the director's decision of 11
   August 2026 holds for every image in the product, and a year burnt into the
   corner of a photo would be the same banner that left there. It lives in the
   band of loess between the photograph and the body that rises over it.

   The bottom margin is larger than the 2rem the body comes forward by. Without
   that, the body would eat exactly the line that exists to be read. */
.point-photo-year {
  padding-block: 0.55rem 2.6rem;
  padding-inline: var(--gutter);
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--brass-text);
}

.point-photo + .point-body {
  position: relative;
  z-index: 1;
  margin-block-start: -2rem;
  padding-block-start: 0.1rem;
  background-color: var(--background);
  border-start-start-radius: 1.6rem;
  border-start-end-radius: 1.6rem;
}

/* In the then/now pair the credit sits under the year, inside a caption that
   is already inset by the card — no gutter of its own, and one size smaller
   than the year so the two never read as one line. */
.point-pair .photo-credit {
  max-width: none;
  padding-inline: 0;
  padding-block-start: 0.15rem;
  font-size: 0.72rem;
  color: var(--ink);
}

/* The then/now pair, when the record carries both frames: same crop, same
   size, side by side at any width — comparing them is the whole point, and
   two different proportions would make the comparison about the frames. */
.point-pair {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.6rem;
}

/* `height: auto` for the same reason as the home band: the width/height
   attributes on the tag arrive as a presentational height, which outranks
   `auto` and would leave `aspect-ratio` unused — the two frames would then be
   two different heights, which is exactly what the pair exists to prevent. */
.point-pair img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  background-color: var(--loess);
  border-radius: var(--radius-small);
}

.point-pair figcaption {
  margin-block-start: 0.35rem;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--brass-text);
}

/* ---- Name and the one line: the page opens here ---- */

.point-identity {
  padding-block: 1.6rem 0.5rem;
}

/* Large and tight — the hierarchy is carried by size, and the secondary line
   steps down far enough that the two never read as one block. */
/* The name of the place. It was 2.35rem and broke into two lines on long
   names — פארק נחל באר שבע took two whole lines and pushed everything down.
   1.85rem fits most of them on a single line, and it is still the largest text
   on the page, which is what a title needs to be. */
.point-name {
  font-size: 1.85rem;
  font-weight: 700;
  line-height: 1.14;
}

.point-line {
  margin-block-start: 0.4rem;
  font-size: 0.98rem;
  line-height: 1.5;
  opacity: 0.76;
}

/* ---- A station, and the place it belongs to ----

   docs/decisoes.md, decision 5: the record is the unit of knowledge and the
   stamp is the unit of the walk, and they do not coincide. A record that is a
   station of a point has no stamp of its own, no dot of its own on the map,
   and — here — one quiet line saying where it is: a pin and the name of the
   place, no preposition and no sentence. It sits under the one-line summary, at
   the size of the small labels, because it is the address of the thing above it
   and not a second title. */

.point-parent {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  margin-block-start: 0.7rem;
  /* Past the 48px floor without looking like a button: the padding is vertical
     and the line stays where the eye left it. `min-height` and not padding
     alone — the comment above claimed the floor and the padding delivered
     41px, which a measurement caught and reading never would. */
  min-height: 2.7rem;
  padding-block: 0.45rem;
  font-size: 0.92rem;
  font-weight: 700;
  color: var(--brass-text);
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

.point-parent svg {
  width: 1.05rem;
  height: 1.05rem;
  flex: 0 0 auto;
}

/* The other half of the same decision: the point's page lists its stations, so
   the stamp of the tel is worth more because whoever sticks it has four things
   to read standing there. The heading and the cards are the home's, unchanged —
   a station is a whole record and reads like one. */

.point-stations .section-label {
  margin-block: 0 0.75rem;
}

/* One rhythm for the whole column: every card sits 0.75rem under the last. */
.point-body > * + * {
  margin-block-start: 0.75rem;
}

/* The section is a heading plus a list, not a card, so it needs the step above
   it that a card gets from the rhythm rule and then some: a new subject starts
   here. */
.point-body > .point-stations + *,
.point-body > * + .point-stations {
  margin-block-start: 1.6rem;
}

.point-title {
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  color: var(--brass-text);
  margin-block-end: 0.75rem;
}

/* ---- Scripture — the one ceremonial block, and the only one.
   When a record carries both corpora they sit side by side at
   identical size and weight; when it carries one, the card holds
   that one and says nothing about the other. ---- */

/* auto-fit, not two fixed columns: with two corpora the desktop gets two
   equal columns, and with one the single verse fills the card instead of
   sitting beside a reserved empty half — the reserved half would be exactly
   the absence this page refuses to draw. */
.verses-pair {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  gap: 1.6rem;
}

.verse-corpus {
  font-size: 0.85rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  color: var(--brass-text);
  margin-block-end: 0.5rem;
}

.verse-text {
  font-family: var(--font-verse);
  font-size: 1.35rem;
  font-weight: 400;
  line-height: 1.95;          /* niqqud needs the room */
}

/* The gloss: the verse in the language of this edition, under the verse in the
   language it was written in.

   It is deliberately NOT ceremonial. The running family instead of the printed
   serif, two thirds of the size, a hairline down its leading edge — everything
   here says "this is a reading of the text above", never a second scripture.
   The original commands; without that distance the Arabic and the Hebrew would
   read as two equal quotations and the page would have invented a claim the
   archive never made.

   A record with no gloss gets nothing at all: no gap, no line, no note that a
   translation is missing. Every Tanach verse in the archive is that case. */
.verse-gloss {
  margin-block-start: 0.85rem;
  padding-inline-start: 0.8rem;
  border-inline-start: 2px solid var(--brass);
  font-family: var(--font);
  font-size: 0.95rem;
  line-height: 1.7;
  opacity: 0.86;
}

/* The translator, on his own line. The credit travels inside the record's own
   text, between parentheses at the end of it; taken out of the sentence it
   reads as what it is — a nineteenth-century translation with an author — and
   it lines up with the verse's reference two lines below. */
.verse-gloss-credit {
  display: block;
  margin-block-start: 0.4rem;
  font-size: 0.78rem;
  font-weight: 600;
  line-height: 1.45;
  color: var(--brass-text);
  opacity: 1;
}

.verse-ref {
  margin-block-start: 0.6rem;
  font-size: 0.92rem;
  font-weight: 600;
}

/* ---- The story ---- */

.point-text p {
  font-size: 1.02rem;
  line-height: 1.75;
}

/* ---- Listen, and the stamp: the two controls ---- */

.control {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  width: 100%;
  min-height: 3.4rem;         /* 61px */
  padding-inline: 1.1rem;
  font-family: inherit;
  font-size: 1.15rem;
  font-weight: 700;
  color: var(--ink);
  background-color: transparent;
  border: 2px solid var(--ink);
  border-radius: 999px;
}

/* The album's explanation. It replaced the index of layers that sat under the
   title — the director's decision, 11 August: there, someone arriving for the
   first time needs to know what this is and how it works, and not a count by
   period. Navigation by layer was not lost: the pills at the top lead to the
   same places, and always did.

   The text does NOT mention the passport, and the omission is deliberate: the
   button to save it only appears after the first stamp, and pointing at an
   invisible button is exactly what the house rule forbids. */
.album-intro {
  display: grid;
  gap: 0.7rem;
  margin-block-end: 1.6rem;
  font-size: 1.02rem;
  line-height: 1.62;
}

.album-intro p { margin: 0; }

.album-intro p:first-child {
  font-weight: 700;
  font-size: 1.1rem;
}

.album-intro p:last-child {
  color: var(--ink-weak);
  font-size: 0.95rem;
}

/* The row of the other photographs. It scrolls horizontally instead of
   stacking: they are secondary images, and stacking them would give a footnote
   the height of a chapter. `scroll-snap` so the finger stops on one of them and
   not between two. */
.point-gallery { overflow: hidden; }

.gallery-row {
  display: flex;
  gap: 0.7rem;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  padding-block-end: 0.3rem;
  margin-inline: -0.2rem;
  padding-inline: 0.2rem;
}

.gallery-row figure {
  flex: 0 0 62%;
  margin: 0;
  scroll-snap-align: start;
}

.gallery-row img {
  display: block;
  width: 100%;
  height: 8.6rem;
  object-fit: cover;
  border-radius: 0.7rem;
}

.gallery-row figcaption {
  margin-block-start: 0.35rem;
  font-size: 0.82rem;
  color: var(--ink-weak);
}

/* THE SUPPORTERS PAGE.

   The stamps use the album's own sheet (`.album-sheet`) and the same stamp
   object (`.stamp`): there is no new piece, and that is why the page's promise
   is literal — whoever supports gets a stamp in the archive, of the same design
   the places have. With one supporter the sheet shows one; with thirty, it
   shows thirty, without one extra line. */
.support-call {
  margin-block: 0 1.2rem;
  font-size: 1.14rem;
  font-weight: 700;
  line-height: 1.45;
}

.support-stamps { margin-block-end: 1.4rem; }

/* `.about-supporters` IS THE SAME SECTION ON ANOTHER PAGE, since 16 August
   2026: the supporters came to close `אודות`, and a supporter's stamp has to be
   the SAME stamp in both places. That is why it joins these selectors instead
   of getting rules of its own — two stylesheets for the same design would
   diverge the day one of them was tuned, and the stamp would stop being his.

   With few supporters, the album's grid would leave one stamp adrift taking up
   a whole row. Here they line up to the start of reading and keep the width of
   one stamp, which is the size the design was made at. */
.support-stamps .album-sheet,
.about-supporters .album-sheet {
  display: flex;
  flex-wrap: wrap;
  gap: 0.9rem;
  /* AND IT TURNS OFF THE ALBUM'S LAZINESS, which here is not an optimisation —
     it is a jump.

     `.album-sheet` brings `content-visibility: auto` and reserves
     `3 × 11.4rem + 4.7rem` = 700px while the sheet is far from the screen. That
     is right in the album, where a sheet really does have three rows of tall
     stamps and where there are three hundred points to render. Here there are
     four names in a row of stamps lying on their side, and the whole sheet
     measures 75.6px — measured at 375px.

     The arithmetic only shows up when the section is far from the screen, and
     that is why it could not be seen until 16 August: in `supporters.html` the
     sheet is at the top and renders on the first pass. At the end of `אודות` it
     is 5,500px from the top, and the page reserved 700px of emptiness that
     shrank to 76 when anyone got there — the scrollbar lying by 625px and a
     jolt at the end of the reading. */
  content-visibility: visible;
  contain-intrinsic-size: none;
}

/* Inside `אודות` the sheet is the end of a text card and not the whole page:
   it needs the air that separates it from the paragraph above it. */
.about-supporters .album-sheet {
  margin-block-start: 1rem;
}

/* The supporter's stamp is HORIZONTAL and small — the director's request, 12
   August: a third of the size, on its side, with the name larger. And it makes
   sense: a place's stamp is portrait because it has a photograph inside; a
   supporter's has only a name, and a name is wide. The form follows the
   content.

   A third of the area: the portrait was 8.5x10.6rem, about 90rem². On its side
   at 5/3, 7rem of width gives 4.2 of height and 29rem² — the third that was
   asked for, measured and not estimated. */
.support-stamps .stamp,
.about-supporters .stamp { flex: 0 0 7rem; }

.support-stamps .stamp-frame,
.about-supporters .stamp-frame {
  aspect-ratio: 5 / 3;
  padding: 6% 8%;
}

/* The name grows because it is now the stamp's only content, and because a
   smaller stamp with the same type would leave the name swimming. */
.support-stamps .stamp-name,
.about-supporters .stamp-name { font-size: 0.86rem; }
.support-stamps .stamp-series,
.about-supporters .stamp-series { font-size: 0.68rem; }

.support-text p { margin-block: 0 0.8rem; }
.support-text p:last-child { margin-block-end: 0; }

/* The channel is an e-mail and not a pay button, because there is no means of
   payment — and a control that does nothing is the defect this product does not
   commit. */
.support-channel {
  margin-block-start: 1.2rem;
  text-decoration: none;
}

/* WHERE YOU ARE. A turquoise dot with a white ring and a halo around it — the
   drawing everybody has already read on a map, and so it needs no caption. The
   halo pulses slowly: it is what distinguishes "me, now" from one more point of
   the archive, without giving it a new colour or a larger size.

   The `position: absolute` with `left: 0; top: 0` is not RTL carelessness: it
   is MapLibre's contract. The library puts the class `.maplibregl-marker` on
   this element and moves it only by `transform`, from the top left corner of
   the map. The vendor's stylesheet declares that, ours loads after it, and the
   `position: relative` that used to be here won — the pin stopped being
   positioned and fell wherever the flow put it. **In an RTL document the flow
   starts on the right**, so the dot appeared 356 px away from where the person
   was: measured on 14 August 2026, with the phone in the Old City and the pin
   on top of the Kanyon. In Hebrew and in Arabic — the V1 and the sixth
   language.

   Here `left`/`top` are the correct ones and there is no logical property to
   use: it is not spacing and not reading, it is the origin of a transform in a
   plane that has no writing direction. The `absolute` also anchors the
   `::after` below, which was the reason for the `relative`. */
.map-me {
  position: absolute;
  left: 0;
  top: 0;
  width: 1.05rem;
  height: 1.05rem;
  background-color: var(--turquoise);
  border: 3px solid #fff;
  border-radius: 999px;
  box-shadow: 0 1px 5px rgba(0, 0, 0, 0.35);
}

.map-me::after {
  content: '';
  position: absolute;
  inset: -0.62rem;
  border-radius: 999px;
  background-color: var(--turquoise);
  opacity: 0.2;
  animation: mapa-eu-pulso 2.4s ease-out infinite;
}

@keyframes mapa-eu-pulso {
  0%   { transform: scale(0.6); opacity: 0.3; }
  70%  { transform: scale(1.25); opacity: 0.05; }
  100% { transform: scale(1.25); opacity: 0; }
}

/* Anyone who asked for less motion gets no motion at all. */
@media (prefers-reduced-motion: reduce) {
  .map-me::after { animation: none; opacity: 0.18; }
}

/* THE LOCK AGAINST HORIZONTAL OVERFLOW.

   The director described the symptom precisely: "when I go into a place, it
   goes down in an infinite scroll and does not come back up" («quando entro em
   um local, ele vai para baixo em um scroll infinito e não volta para cima»).
   That is what a phone does when some element is wider than the screen — the
   page gains a horizontal axis nobody asked for, and the finger, scrolling
   diagonally, can no longer get back.

   This product NEVER has a horizontal axis: what is wide (the row of
   photographs, the pills, the map) scrolls inside its own box, and never in the
   body. The rule lives here instead of hunting down the culprit each time,
   because in an RTL layout with logical properties one badly measured negative
   margin is enough to reopen it.

   `clip` AND NOT `hidden`, AND IT IS BECAUSE OF THE HEADER.

   The director, 17 August 2026: "it is not fixed when I scroll down, it goes
   up" («não está fixo quando faço scroll para baixo, ele sobe»). `.bar` has
   declared `position: sticky` for as long as it has existed, and it never
   worked a single time — on no page, at no width. Measured: at 1440px, with the
   page scrolled 900px, the top of the bar was at −900.

   The cause is this line, and it is well enough known to have a name: an
   `overflow-x: hidden` makes the other axis go from `visible` to `auto`, the
   element becomes a scrolling box, and a `sticky` child of it starts sticking
   to the top of a box THAT NEVER SCROLLS. The declaration is still there, the
   computed style still says `sticky`, and there is not a single error anywhere
   — it is the same shape of defect as the law of delivery: possible and
   invisible.

   `overflow-x: clip` cuts exactly the same overflow and does NOT create a
   scrolling box, and that is why it is the correction and not a patch: the lock
   does the job it was written for and stops doing what nobody asked of it.

   THE TWO LINES ARE DELIBERATE. A browser that does not know `clip` keeps the
   `hidden` of always — the lock still stands and the header stays as it is
   today, which is what rule 4 of the law of delivery asks: what degrades
   degrades into something usable. */
html, body {
  max-width: 100%;
  overflow-x: hidden;
  overflow-x: clip;
}

/* And `overscroll-behavior` stops the end of an inner list from dragging the
   page behind it — the other route to the same symptom. */
.gallery-row,
.filters-list,
.feed {
  overscroll-behavior-x: contain;
}

/* THE FEATURE CARD — the city, at the top of the home page.

   It is the same card as the other points, larger and with the photograph
   taking up everything. What makes it a feature is its position and its size;
   there is no ornament the others do not have. The dark veil over the bottom
   third is the facade's own — text over an image only exists where there is a
   veil, and it is A27's declared exception. */
.feature-city {
  position: relative;
  display: block;
  overflow: hidden;
  margin-block-end: 1.4rem;
  border-radius: 1.1rem;
  text-decoration: none;
}

/* THE SAME ARITHMETIC AS THE TOP OF THE POINT PAGE, and the same correction.
   At 1440 this frame measured 1255x270 — ratio 4.65 — and kept 21% of the
   image. It now has a stated ratio, and the height comes out of it; the former
   `height` becomes a ceiling, so that a narrow screen does not make it grow
   beyond what it was.

   16/9 and not 4/3 like the point page, and it is a difference of nature: that
   one is the photograph that confirms "yes, this is it" and wants to be the
   photograph; this is a facade with the city's name written over the veil, and
   a facade is a band. With the real photograph underneath (1.5) it keeps 84% of
   it against the 59% the square thumbnail gave. */
.feature-city img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
  max-block-size: 11rem;
  object-fit: cover;
}

.feature-veil {
  position: absolute;
  inset-block-end: 0;
  inset-inline: 0;
  height: 72%;
  background: linear-gradient(to top, rgba(11, 10, 9, 0.86), rgba(11, 10, 9, 0));
}

.feature-text {
  position: absolute;
  inset-block-end: 0;
  inset-inline: 0;
  display: grid;
  gap: 0.15rem;
  padding: 0.9rem 1rem;
  color: #fff;
}

.feature-name { font-size: 1.6rem; font-weight: 700; line-height: 1.1; }
.feature-line { font-size: 0.94rem; opacity: 0.88; line-height: 1.35; }

.feature-chapters {
  margin-block-start: 0.3rem;
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  opacity: 0.95;
}

/* THE PREVIEW INSIDE THE UNSTUCK STAMP — the director's idea, 12 August:
   "what if each stamp had a preview desaturated at 60% transparency?" («e se
   tivéssemos em cada selo um preview dessaturado em 60% de transparência?»)

   The album's sheet was a wall of empty outlines. The empty outline is what
   makes you want to fill it (docs/selos.md) — but a hundred identical outlines
   say nothing about the hundred places they stand for. With the preview, each
   frame starts promising a concrete place, and it stays visibly unstuck:
   desaturated and faded, it is a ghost and not a photograph.

   `grayscale(1)` plus 0.4 opacity. The STUCK stamp has the photograph in
   brass-over-loess duotone, full and alive; the difference between the two
   states has to read at a glance, from the other side of the sheet — and it
   does. */
.stamp-preview {
  position: absolute;
  inset: 9%;
  z-index: 0;
  width: 82%;
  height: 82%;
  object-fit: cover;
  filter: grayscale(1) contrast(0.9);
  opacity: 0.4;
  pointer-events: none;
}

/* On the stamp already stuck, the preview leaves the stage: the real
   photograph takes its place, and two overlapping images would be dirt. */
.stamp-full .stamp-preview { display: none; }

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .stamp-preview { opacity: 0.3; }
}

/* THE CHAPTERS — the city told in nine tracks.

   One line per chapter: number, title, duration. The number exists because the
   order is the story's and not a list of options — whoever comes in at chapter
   five has to understand there are four before it.

   A chapter WITHOUT audio appears all the same, with its title and with no
   button. The text is the archive; the audio is derived from it. Hiding a
   written chapter for want of a file would be the archive lying about what it
   has. */
.chapter-list {
  display: grid;
  gap: 0.15rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.chapter { list-style: none; }
.chapter::marker { content: ''; }

.chapter-button,
.chapter-no-audio {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  width: 100%;
  min-height: 3rem;
  padding: 0.5rem 0.2rem;
  font-family: inherit;
  font-size: 1rem;
  text-align: start;
  color: var(--ink);
  background: transparent;
  border: 0;
  border-block-end: 1px solid var(--border);
}

.chapter:last-child .chapter-button,
.chapter:last-child .chapter-no-audio { border-block-end: 0; }

.chapter-num {
  flex: 0 0 auto;
  min-width: 1.4rem;
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--brass-text);
  font-variant-numeric: tabular-nums;
}

.chapter-name { flex: 1 1 auto; font-weight: 600; line-height: 1.32; }

.chapter-time {
  flex: 0 0 auto;
  font-size: 0.86rem;
  font-weight: 600;
  opacity: 0.6;
  font-variant-numeric: tabular-nums;
}

/* A chapter still without audio: the title stays legible, but faded, and with
   nothing that looks touchable. */
.chapter-no-audio .chapter-name { opacity: 0.5; }

.chapter-button.is-playing { color: var(--turquoise); }
.chapter-button.is-playing .chapter-num,
.chapter-button.is-playing .chapter-time { color: var(--turquoise); opacity: 1; }

/* THE LENS — a card in the middle of the screen, like any gallery.

   Second version, and the specification is the director's: "fit in the middle
   of the screen, with rounded corners in the style of our site, the pinch zoom
   should scale the image inside the margin, tapping it or outside it closes"
   («fit no meio da tela, com bordas arredondadas no estilo do nosso site, o
   pinch de zoom deve escalonar a imagem dentro da margem, ao clicar nela ou
   fora ele fecha»).

   The first version was full bleed, with no margin and no corners — it read
   like a system viewer and not like a piece of this site. The radius is the
   cards' (1.1rem), and the margin exists so you can see there is an outside to
   touch. */
.lens {
  display: block;
  cursor: zoom-in;
}

.lens-screen {
  width: 100%;
  height: 100%;
  max-width: none;
  max-height: none;
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
  /* The dialog takes up the whole screen so that the "outside" is clickable at
     any point; what has a card's size is the frame inside it. */
  display: grid;
  place-items: center;
  overflow: hidden;
  opacity: 0;
  transition: opacity 160ms ease, overlay 160ms allow-discrete, display 160ms allow-discrete;
}

/* THIS LINE IS NOT REDUNDANT, AND DELETING IT BRINGS THE DEFECT BACK.

   The browser brings `dialog:not([open]) { display: none }` in its own
   stylesheet, but it is the BROWSER'S sheet: any author declaration beats it,
   however low its specificity. The `display: grid` above — which exists for a
   good reason, giving a clickable "outside" — defeats it, and the CLOSED lens
   starts being drawn: `position: absolute`, `height: 100%`, a block the height
   of the whole screen after the footer, invisible because it has `opacity: 0`.

   That is what made it scroll to an empty screen: 621px at 375, 882px at 768
   and 758px at 1440 of nothing below the footer of `זיכרון`. Invisible to look
   at, obvious to measure. Caught by the director on 16 August 2026 — "I can
   turn the scroll until there is nothing on the screen" («eu posso rodar o
   scroll até ficar sem nada na tela»).

   And it is the right finish to the pattern this stylesheet already uses, not a
   sticking plaster: `display` is in the transition list with `allow-discrete`
   precisely so that the `none` only arrives at the end of the exit animation,
   and `@starting-style` handles the entrance. Without the `:not([open])` the
   pattern is only half written. */
.lens-screen:not([open]) { display: none; }

.lens-screen[open] { opacity: 1; }

@starting-style {
  .lens-screen[open] { opacity: 0; }
}

.lens-screen::backdrop { background: rgba(11, 10, 9, 0.88); }

/* THE FRAME TAKES THE SHAPE OF THE PHOTOGRAPH, and not the other way round.

   Until 17 August 2026 the box had a shape of its own — `min(92vw, 46rem)` by
   `min(80dvh, 46rem)` — and the photograph was fitted inside it with `contain`.
   What was left over was black: on a landscape at 375px, 345 by 650 of frame
   for 345 by 230 of photograph, that is 210px of dark band above and as many
   below. On a portrait at 1440 the bands moved to the sides, 174px each. The
   director: "that is very ugly, our margins should be flush with the image"
   («isso é muito feio, deve ser rente à imagem as nossas margens»).

   The envelope is the same as before, and that is the only change: the two
   pairs of measurements stop being `width`/`height` — "fill this" — and become
   `max-inline-size`/`max-block-size` — "fit inside this". The image comes in
   with both dimensions on `auto`, which is the form the browser resolves
   preserving the ratio even when BOTH limits squeeze (CSS 2.1 §10.4); the
   frame, which is an item of a centred grid, shrinks to what it carries. Not a
   calculation per frame, not a measurement in the script.

   `overflow: hidden` is still what makes the zoom happen INSIDE the margin: the
   image grows and what passes the frame is cut by it instead of invading the
   screen. Now the frame is the photograph itself, and the script's drag limit —
   which already measured the frame — becomes exact. `touch-action: none` hands
   the two-finger gesture to the script; without it the browser zooms the whole
   page and the frame is left behind. */
.lens-frame {
  overflow: hidden;
  background-color: #0b0a09;
  border-radius: 1.1rem;
  touch-action: none;
  cursor: zoom-out;
}

.lens-frame img {
  display: block;
  inline-size: auto;
  block-size: auto;
  max-inline-size: min(92vw, 46rem);
  max-block-size: min(80dvh, 46rem);
  transform-origin: center center;
  will-change: transform;
}

/* THE SAME BOX, WITH A CAPTION — it is what the memory game opens when a pair
   is found. Both measure what they carry; the difference is that this one has a
   STATED width, and it has it because what rules its size is not the photograph
   but the card: under the image comes the name of the place, and a game card
   that changed width with every pair would be a different card each time. The
   image fills that width and stays square, which is the shape of the cards on
   the board. Nothing else changes: the background, the closing on a touch
   inside or outside, the Esc and the corner radius are the lens's. */
.lens-frame-caption {
  width: min(80vw, 20rem);
  background-color: var(--surface);
  touch-action: auto;
  cursor: pointer;
}

.lens-frame-caption img {
  inline-size: 100%;
  aspect-ratio: 1;
  object-fit: cover;
}

.lens-caption {
  margin: 0;
  padding: 0.85rem 1rem 1rem;
  font-size: 1.25rem;
  font-weight: 700;
  line-height: 1.25;
  text-align: center;
  color: var(--ink);
}

/* The narration's clock. `tabular-nums` is what stops the button from
   trembling: without it, each second changes the width of the digits and the
   whole line dances — and a button that dances with a thumb on it looks as if
   it moved. The fainter tone separates the number from the verb without needing
   another size. */
.listen-clock {
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  opacity: 0.62;
  letter-spacing: 0.01em;
}

.control svg {
  width: 1.25rem;
  height: 1.25rem;
}

.control:active {
  background-color: var(--touch);
}

.control[disabled] {
  border-color: var(--brass);
  color: var(--ink);        /* legible, never greyed into the background */
}

/* The collect button. It is the readiest thing on the page, and turquoise is
   what says ready. The disabled rule is repeated here on purpose: the button
   is written into the document disabled and site/stamps.js is what enables it,
   so a browser that never runs the script never shows a live-looking control.

   It used to be "a promise about the body" — it only worked within fifty
   metres, which made it a dead control for almost everyone who opens the site.
   Since 17 August 2026 it collects with one tap from anywhere; being at the
   place is what earns the postmark, and the line under the button says so
   before anything is pressed. */
.point-stamp .control,
.point-stamp .control[disabled] {
  color: var(--turquoise);
  border-color: var(--turquoise);
}

.point-stamp .point-note {
  margin-block-start: 0.7rem;
  font-size: 0.92rem;
  text-align: center;
}

/* ============================================================
   THE TWO MODES — street and table, at the same address

   docs/design.md, "A escolha que organiza tudo": the street is
   arrive, look, listen, walk on — ninety seconds at a point; the
   table is search, read, compare, go deep. The mode is not a
   switch, it is a consequence of how the person got here: the QR
   on the wall opens the street, a search or a link opens the
   table, and there is always a visible way across.

   HOW IT IS DECIDED HERE, and why it is decided here rather than
   in a script. No selector can read the query of an address, and
   the site is static — `?qr=1` alone cannot change a byte of what
   is served. A fragment can: `:target` is plain CSS. So the wall
   address is `p/<id>.html?qr=1#rehov`, the point page carries
   `<body id="rehov">`, and everything below is what that match
   means.

   THE DIRECTION MATTERS. The document is born as the table and
   the street is subtraction, because CSS can hide and never
   reveal — a closed <details> does not open from a stylesheet, so
   the complete state has to be the default. The good consequence
   is that nothing is written twice: the then/now pair, the verses
   and the tail of the story are all still in the document, once,
   and the street simply does not draw them.
   ============================================================ */

/* The table is the default, so what belongs to the street waits. */
.only-street {
  display: none;
}

#rehov:target .only-desk {
  display: none;
}

#rehov:target .only-street {
  display: block;
}

/* Shorter, so that the name, the one line and the stamp are all above the
   fold on a phone held in one hand. The photograph still commands the screen
   — it is the one-second confirmation — but on the street the confirmation
   has already happened with the eyes.

   `max-block-size` and not `height` since 17 August 2026: it is the same
   ceiling with the same value, but it now lets the 4/3 of the base rule govern
   the shape wherever there is height for it. On the phone, which is where
   street mode exists, the ceiling wins and the frame comes out the same as
   before. */
#rehov:target .point-photo img {
  max-block-size: clamp(11rem, 30vh, 17rem);
}

/* The column becomes a flex column for one reason: the stamp is written near
   the foot of the document, where it belongs when reading, and on the street
   it belongs directly under the name. `order` moves it without the generator
   writing the page twice.

   The rhythm moves from the adjacency rule to `gap`, because with `order` in
   play "every child after the first" is no longer "every child after the
   first one you see". */
#rehov:target .point-body {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

#rehov:target .point-body > * + * {
  margin-block-start: 0;
}

#rehov:target .point-identity {
  order: -3;
}

#rehov:target .point-listen {
  order: -2;
}

#rehov:target .point-stamp {
  order: -1;
}

/* The one thing the street is for, filled rather than outlined. It is the
   only solid control in the product, and it is solid in exactly one place:
   standing in front of the thing, with the sun on the screen, the button that
   collects has to be found without looking for it. */
#rehov:target .point-stamp .control {
  color: var(--background);
  background-color: var(--ink);
  border-color: var(--ink);
}

/* Continue reading: a link to this same page without the fragment, which is
   literally where the rest of the text is written. Native, no gesture to
   learn, and nothing duplicated to hold it up. */
/* ---- A LINK THAT LEADS OUT IS TURQUOISE ----
   Not every brass word became one: brass still labels, still rules an edge,
   still heads a section. What changed colour is the thing you can go through —
   continue reading, cross to the other mode, open a source, reach the album,
   write to whoever keeps this. A page where the label and the door are the
   same colour makes you read to find out which is which. */
.point-continue {
  margin-block-start: 0.9rem;
  font-size: 0.95rem;
  font-weight: 700;
  color: var(--turquoise);
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

/* The crossing between the modes, in both directions: the size and the tone
   of the אודות link on the home page. Small to the eye, past the touch floor
   for the thumb, and never an explanation of what the modes are. */
.mode-crossing {
  align-items: center;
  justify-content: center;
  min-height: 3rem;
  margin-block-start: 0.4rem;
  font-size: 0.85rem;
  color: var(--turquoise);
  text-decoration: underline;
  opacity: 0.9;
}

/* Both crossings are written into every page and each mode draws its own. The
   pair is spelled out here instead of leaning on the .only-street / .only-desk
   defaults for one reason worth remembering: `display: flex` on the base class
   weighs exactly as much as `display: none` on the mode class and comes later
   in this file, so the base would have won and the street's link would have
   shown up on the table's page. Under :target the id outweighs both. */
.mode-crossing.only-desk,
#rehov:target .mode-crossing.only-street {
  display: flex;
}

/* ---- Sources: one control at the foot, closed until asked for ---- */

.sources {
  padding: 0;
  overflow: hidden;
}

.sources-summary {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  min-height: 3.2rem;         /* 58px */
  padding-inline: 1.15rem;
  font-size: 0.95rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  color: var(--brass-text);
  cursor: pointer;
  list-style: none;
}

.sources-summary::-webkit-details-marker {
  display: none;
}

.sources-summary:active {
  background-color: var(--touch);
}

.sources-summary .arrow {
  margin-inline-start: auto;
  transform: rotate(-90deg);  /* pointing down, closed */
}

[dir="ltr"] .sources-summary .arrow {
  transform: scaleX(-1) rotate(90deg);
}

.sources[open] .sources-summary .arrow {
  transform: rotate(90deg);
}

[dir="ltr"] .sources[open] .sources-summary .arrow {
  transform: scaleX(-1) rotate(-90deg);
}

.sources-body {
  padding-block: 0.2rem 1.1rem;
  padding-inline: 1.15rem;
}

.sources-list {
  list-style: none;
}

/* The images get their own heading inside the sources sheet: the credit under
   the photograph says who made it and under what licence, and this is where
   the way back to the work itself lives — the other half of what CC BY asks
   for. It is a label for a list that exists, never a heading over nothing:
   without a credited image the block is not written at all. */
.sources-label {
  margin-block-start: 1.1rem;
  margin-block-end: 0.1rem;
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.07em;
  color: var(--brass-text);
}

.sources-body > .sources-list:first-child + .sources-label {
  margin-block-start: 0.9rem;
}

.sources-list li + li {
  margin-block-start: 0.5rem;
}

/* Small to the eye, honest to the thumb: the vertical padding is what
   carries a one-line link past the 48px floor. Unnumbered on purpose —
   an ordered marker beside a Latin-script title reorders to the wrong
   side under RTL bidi, and no sentence cites a source by number. */
.source {
  display: inline-block;
  padding-block: 0.72rem;     /* what carries a one-line link past 48px */
  font-size: 0.92rem;
  line-height: 1.4;
  text-decoration: underline;
}

/* Only the ones that are links. A credit whose record carries no URL is drawn
   with the same class in a <span>, and colouring that turquoise would promise
   a door where there is none. */
a.source {
  color: var(--turquoise);
}

/* A credit whose record carries no URL is still a credit, and it takes the
   same place in the list — but underlined text that goes nowhere is a broken
   link to the eye and to the thumb. */
span.source {
  text-decoration: none;
}

.source-date {
  display: block;
  font-size: 0.82rem;
  opacity: 0.85;
}

/* verified.method — said to the reader in the product, not kept for us */
.sources-verified {
  margin-block-start: 0.9rem;
  padding-block: 0.6rem;
  padding-inline: 0.8rem;
  font-size: 0.9rem;
  line-height: 1.5;
  border-inline-start: 3px solid var(--brass);
}

/* ============================================================
   THE MAP
   The one page that talks to the network, and the exception is
   declared in CLAUDE.md: the library is served from site/vendor/
   and the OpenStreetMap tiles are the only external request.

   The page is built the other way round from what a map usually
   is. Its document is the list of points ordered by distance;
   the map is what replaces the list once a tile actually
   arrives. So the default state of this stylesheet is the list,
   and .map-with-map — set on <html> by the page, removed the
   moment the tiles cannot be honoured — is what swaps them. No
   script, no WebGL, no signal: each of those simply never sets
   the class, and the person gets the list. There is no styling
   here for a broken map, because there is no broken map.
   ============================================================ */

[hidden] {
  display: none !important;
}

.map-area {
  display: none;
}

.map-with-map .map-area {
  display: block;
  flex: 1;
  min-height: 0;
}

.map-with-map .map-list {
  display: none;
}

/* Map mode is the one screen in the product that does not scroll: the map owns
   the space between the layer pills and the bottom bar. */
.map-with-map body.body-map {
  height: 100dvh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.map-with-map .map-main {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
}

.map-top {
  position: relative;
  z-index: 5;
  background-color: var(--background);
}

.map-top .bar {
  position: static;
  justify-content: space-between;
  border-block-end: none;
}

/* The counter is per layer, never one grand total, and it exists only once
   there is a first stamp — see docs/selos.md. */
.map-count {
  font-size: 0.9rem;
  font-weight: 700;
  color: var(--brass-text);
}

/* THE WAY OUT OF THE FILTER, AND THE ONLY FILTER CONTROL THE MAP HAS.

   The row of pills left here on 17 August 2026, by the director's decision: 36
   tags on three lines at 1440px, a third of the screen of a page whose content
   is the map. What chooses a layer now is the tag at the foot of a point page,
   which points at `map.html#<key>`; what stays here is the way back.

   It is born `hidden` and the script only reveals it when there is a filter —
   with no filter there is no control at all, and there is no line saying there
   is no filter. And it lives on the bar's line, against the end of reading,
   because it is not a heading: it is a thing that undoes itself. */
.map-clear {
  display: block;
  padding-block: 0.55rem;
  padding-inline: var(--gutter);
  font-size: 0.92rem;
  font-weight: 700;
  color: var(--turquoise);
  text-decoration: underline;
  text-underline-offset: 0.2em;
  text-align: end;
}

/* ---- The list: the page when there is no map ---- */

.map-list {
  padding-block-end: 1.5rem;
}

.map-near {
  margin-block-end: 1rem;
}

/* ---- The bottom sheet: name, one line, and the way in ---- */

.sheet {
  position: fixed;
  inset-inline: 0;
  inset-block-end: calc(var(--bar-height) + env(safe-area-inset-bottom));
  z-index: 15;
  width: 100%;
  max-width: var(--measure);
  margin-inline: auto;
  padding: 0 var(--gutter) 1.15rem;
  background-color: var(--background);
  border-start-start-radius: 1.6rem;
  border-start-end-radius: 1.6rem;
  box-shadow: 0 -8px 30px -12px rgba(35, 32, 25, 0.4);
  transform: translateY(100%);
  transition: transform 0.2s ease-out;
}

.sheet.is-open {
  transform: translateY(0);
}

@media (prefers-reduced-motion: reduce) {
  .sheet {
    transition: none;
  }
}

/* The grab handle every sheet has. It is drawn and not draggable, and that is
   deliberate: it says which edge the panel came from, and the close button
   next to it is the control that actually does something. */
.sheet-top {
  position: relative;
  display: flex;
  justify-content: flex-end;
  padding-block: 0.35rem;
}

.sheet-top::before {
  content: "";
  position: absolute;
  inset-block-start: 0.55rem;
  inset-inline: 0;
  width: 2.4rem;
  height: 0.28rem;
  margin-inline: auto;
  border-radius: 999px;
  background-color: var(--loess);
}

.sheet-close {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.7rem;              /* 49px */
  height: 2.7rem;
  color: var(--ink);
  background-color: transparent;
  border: none;
  border-radius: 999px;
  cursor: pointer;
}

.sheet-close svg {
  width: 1.3rem;
  height: 1.3rem;
}

.sheet-close:active {
  background-color: var(--touch);
}

.sheet-body > * + * {
  margin-block-start: 0.7rem;
}

/* The stations of a point, under its card in the sheet. One dot on the map,
   and behind it everything there is to read standing there — the trade
   docs/decisoes.md made in decision 5. Links and not cards: the card above
   already carries the picture and the line, and four cards in a bottom sheet
   would push the map off the screen. */

.sheet-stations {
  list-style: none;
  padding-inline-start: 0.35rem;
}

.sheet-station {
  display: block;
  padding-block: 0.62rem;
  font-size: 0.95rem;
  font-weight: 700;
  color: var(--brass-text);
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

.sheet-stations li + li .sheet-station {
  border-block-start: 1px solid var(--border);
}

/* ---- The names beside the dots ----

   A12. A dot with no name is a question mark: fourteen coloured rings over
   Beer Sheva, and the only way to learn what any of them is was to tap it.

   Text drawn by the map engine needs a glyph endpoint — a second external
   request on a product that has declared exactly one — or a Hebrew font
   compiled into site/vendor/ and carried by every phone on the street. These
   are neither: they are spans over the canvas, moved by site/mapa.js on every
   frame of a pan. The typeface is the system stack the whole site already
   uses, right-to-left is the browser's own and correct without a line of code,
   and the file costs nothing because there is no file.

   The halo is what makes them legible over a map instead of over a page, and
   it is the page's own background colour, so it reads in the sun and at night
   without a second rule. */

.map-labels {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;       /* the dot underneath is the target, never this */
}

.map-label {
  position: absolute;
  /* `top`/`left` and not the logical pair, and it is the one place in this
     stylesheet where that is right: the script writes `transform: translate()`
     in canvas pixels measured from the top left corner by `map.project()`.
     That is a screen-space origin, not a direction of reading — mirroring it
     would put every name on the wrong side of its own dot. The Hebrew inside
     the box still lays itself out right-to-left, as it does everywhere. */
  top: 0;
  left: 0;
  max-width: 11rem;
  font-size: 0.76rem;
  font-weight: 700;
  line-height: 1.2;
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  text-shadow:
    0 0 2px var(--background), 0 0 2px var(--background),
    0 0 4px var(--background), 0 1px 3px var(--background);
  will-change: transform;
}

/* ---- MapLibre's own furniture, brought into the palette ---- */

.maplibregl-map {
  font-family: var(--font);
}

/* The library ships 29px buttons; the floor in this product is 48px. */
.maplibregl-ctrl-group button {
  width: 2.7rem;
  height: 2.7rem;
}

.maplibregl-ctrl-group {
  background-color: var(--surface);
  border-radius: var(--radius-small);
  box-shadow: var(--shadow);
}

.maplibregl-ctrl-group button + button {
  border-block-start: 1px solid var(--border);
}

/* The library greys a control out when the browser cannot honour it — the
   locate button without geolocation, for one. A control that cannot work is
   not drawn at all: the interface never writes what it does not have. */
.maplibregl-ctrl-group button:disabled {
  display: none;
}

.maplibregl-ctrl-group:not(:has(button:not([disabled]))) {
  display: none;
}

/* The ODbL credit: always visible, never collapsed behind an "i", and set
   left-to-right inside a right-to-left document so the © stays put. */
.maplibregl-ctrl-attrib {
  direction: ltr;
  text-align: left;
  font-size: 0.66rem;
  color: var(--ink);
  background-color: var(--surface);
  border-radius: var(--radius-small);
}

.maplibregl-ctrl-attrib a {
  color: var(--ink);
  text-decoration: underline;
}

.maplibregl-ctrl-bottom-left,
.maplibregl-ctrl-bottom-right {
  display: none;              /* everything lives at the top, clear of the sheet */
}

/* Same ceiling as the dock: these two measurements exist to give it room, and
   in the archive view there is no dock at the bottom any more. */
@media (min-width: 768px) and (max-width: 63.99rem) {
  /* The bar becomes a floating dock on desktop; the map gives it room instead
     of hiding its own bottom edge underneath it. */
  .map-with-map body.body-map {
    padding-block-end: calc(var(--bar-height) + 2.2rem);
  }

  .map-with-map .sheet {
    inset-block-end: calc(var(--bar-height) + 2.2rem);
  }
}

/* ============================================================
   THE STAMP
   Perforated paper, portrait, the place's own photograph inside
   it in brass over loess, the name and the layer under it, and
   the postmark across a corner with the date and hour that
   person collected it. Built from fields the record already
   carries — docs/selos.md asks for zero handmade artwork across
   two hundred and fifty places, and that is the whole reason
   this is CSS and SVG and not a folder of pictures.

   Every colour in here is a literal and not a variable, on
   purpose and for the same reason as the illustration's label:
   a stamp is a printed object. It does not follow the interface
   from light to dark, because paper does not.

   The one part that does follow the page is the outline of a
   stamp not yet collected: there is no paper there to sit on —
   that is the point of it — so the name is written in the ink
   of the page and reads in either theme.
   ============================================================ */

/* The definitions the stamps refer to: the perforated outline as one path and
   the duotone as one filter, written into the document once by the generator
   and used by reference. Never rendered on its own. */
.stamp-defs {
  position: absolute;
  width: 0;
  height: 0;
  overflow: hidden;
}

/* EVERY PLACE HAS ITS OWN STAMP, and it is always the same one.

   Three axes, and the generator computes all three from the record itself
   (see `estiloDoSelo`): the perforation from the id, the colour from the
   historical layer — the same colour the point wears on the map — and the
   printed rule inside the paper from how old that layer is. Nothing is drawn
   by hand and nothing is drawn twice: two hundred and fifty places cannot each
   have their own artwork, and a stamp that came out different on the second
   visit would not be a stamp.

   `--stamp-color` and `--stamp-color-dark` arrive as an inline style on the figure.
   The one that is used depends on where the ink is: an empty outline is ink on
   the PAGE and has to read in either theme; a collected stamp is ink on paper,
   and paper does not follow the interface from light to dark. */
.stamp {
  position: relative;
  --stamp-ink: var(--stamp-color, var(--brass));
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .stamp {
    --stamp-ink: var(--stamp-color-dark, var(--brass));
  }
}

:root[data-theme="dark"] .stamp {
  --stamp-ink: var(--stamp-color-dark, var(--brass));
}

.stamp-frame {
  position: relative;
  display: flex;
  flex-direction: column;
  aspect-ratio: 4 / 5;
  padding: 7.5% 7.5% 6.5%;
  /* Contains the postmark's blending: it must print onto the paper and the
     photograph under it, and never onto the page behind them. */
  isolation: isolate;
}

/* The paper itself. Not collected: an empty outline in brass, the shape of the
   stamp with nothing in it — seeing the hole is what makes someone want to
   fill it (docs/selos.md). Collected: the same shape, filled, lifted off the
   album sheet by its own shadow. */
.stamp-paper {
  position: absolute;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  fill: none;
  stroke: var(--stamp-ink);
  stroke-width: 1.4;
  stroke-dasharray: 0;
}

.stamp-full .stamp-paper {
  fill: #FFFCF4;
  stroke: rgba(74, 58, 22, 0.18);
  filter: drop-shadow(0 5px 9px rgba(35, 32, 25, 0.2));
}

/* The printed rule: a border struck inside the paper, between the perforation
   and the picture, in the layer's colour. It is the device that tells one
   stamp issue from another on a real album page, and here it says how old the
   place is — nothing, one line, two lines, by the layer's position in the
   chronology. Only on the collected stamp: the empty outline has no paper. */
/* `z-index: 1` and not 0: the paper is an absolutely positioned SVG at 0, and
   at the same level the later element wins — the rule would be printed under
   the sheet it is supposed to be printed on. */
.stamp-full .stamp-frame::before {
  content: "";
  position: absolute;
  inset: 4.6%;
  z-index: 1;
  pointer-events: none;
}

.stamp-full.stamp-rule-1 .stamp-frame::before {
  border: 1px solid var(--stamp-color, var(--brass));
  opacity: 0.75;
}

.stamp-full.stamp-rule-2 .stamp-frame::before {
  border: 1px solid var(--stamp-color, var(--brass));
  box-shadow: inset 0 0 0 3px #FFFCF4, inset 0 0 0 4px var(--stamp-color, var(--brass));
  opacity: 0.75;
}

/* The window on the picture. Inset from the perforated edge, the way a stamp
   is printed — so the photograph never has to be clipped to the scalloped
   outline, and the outline stays one path for both states.

   A point with no free photograph gets the paper with no window at all. It
   never gets the temporary AI illustration: that picture may only appear under
   its own label, and a label across a souvenir would ruin the souvenir and the
   rule at once. */
.stamp-window {
  position: relative;
  z-index: 1;
  flex: 1;
  min-height: 0;
  overflow: hidden;
  background-color: #E6DDC7;
}

.stamp-window img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: url(#bul-duotone);
}

.stamp-caption {
  position: relative;
  z-index: 1;
  display: block;
  padding-block-start: 0.35rem;
  text-align: center;
}

/* With no window above it the legend sits in the middle of the empty outline,
   which is where a name has to be to be read at a glance across a sheet. */
.stamp:not(.stamp-full) .stamp-caption {
  margin-block: auto;
}

.stamp-name {
  display: block;
  font-size: 0.72rem;
  font-weight: 700;
  line-height: 1.22;
  color: var(--ink);
}

.stamp-series {
  display: block;
  margin-block-start: 0.12rem;
  font-size: 0.6rem;
  font-weight: 600;
  letter-spacing: 0.03em;
  color: var(--brass-text);
}

.stamp-full .stamp-name {
  color: #362A11;
}

.stamp-full .stamp-series {
  color: #7E5F1C;
}

/* The postmark: the only part of the collection that is hers alone. Over the
   corner, tilted the way a hand tilts, printed into what is underneath. */
.stamp-postmark {
  position: absolute;
  z-index: 2;
  inset-block-start: 5%;
  inset-inline-start: 4%;
  width: 42%;
  height: auto;
  fill: #4A3A16;
  stroke: #4A3A16;
  opacity: 0.74;
  mix-blend-mode: multiply;
  transform: rotate(-13deg);
}

/* ---- The stamp on the point page, once it is collected ---- */

.point-stamp-glued {
  text-align: center;
}

.point-stamp-glued .stamp {
  width: min(11rem, 62%);
  margin-inline: auto;
}

.stamp-go {
  display: inline-block;
  margin-block-start: 0.9rem;
  padding-block: 0.6rem;
  font-size: 0.92rem;
  font-weight: 700;
  color: var(--turquoise);
  text-decoration: underline;
}

/* ============================================================
   ABOUT — the page the foot of the home page has always pointed at

   The same vocabulary as everything else: cards, the brass label
   over each one, the reading measure of the story. Nothing new is
   invented for it, because a page about the project is the last
   place that should teach anyone a new shape.

   The last card is the data credit, and it is the one credit in
   the product that is not behind a control: the map tiles are
   OpenStreetMap under the ODbL, which requires the attribution to
   be visible, and the archive's identifiers are Wikidata under
   CC0. It reuses the sources list because it is the same kind of
   thing — a way back to the work.
   ============================================================ */

.about-title {
  padding-block: 1.3rem 0.2rem;
  font-size: 2.1rem;
  font-weight: 700;
  line-height: 1.1;
}

.about-page > * + * {
  margin-block-start: 0.75rem;
}

/* THE PHOTOGRAPH INSIDE AN `אודות` BLOCK.

   The same small radius as the paired photographs on the point page, and not
   the card's large radius: it is INSIDE a card, and a curve equal to the
   parent's pressed against the parent's curve reads as a misalignment.

   `height: auto` is load-bearing and not tidiness, for the same reason as on
   the home band: the generator writes `width`/`height` into the HTML so the
   browser can reserve the space before the file arrives, and without this line
   those attributes become the display size and the image comes out squashed.

   THE TWO DISTANCES COME FROM THE RULER and are not numbers written here. To
   the title above it it sits tight — title and photograph are one single thing,
   and that is what `--rhythm-tight` says throughout this stylesheet; to the
   text below it it keeps the distance of two siblings of the same nature,
   `--rhythm`. No number of its own, which is the
   margin-because-it-was-written-later that the ruler exists to put an end
   to. */
.about-photo {
  display: block;
  width: 100%;
  height: auto;
  margin-block: var(--rhythm-tight) var(--rhythm);
  border-radius: var(--radius-small);
}

.about-block p {
  font-size: 1.02rem;
  line-height: 1.75;
}

.about-block p + p {
  margin-block-start: 0.9rem;
}

/* The intro over the credit list, and the note under it, read as text rather
   than as the small print of a list entry. */
.about-block .sources-list {
  margin-block-start: 0.6rem;
}

/* What the archive took from each collection. One step down from the running
   text and one step up from the licence line, because it is a sentence and
   not a label. */
.about-block .source-note {
  display: block;
  margin-block-start: 0.1rem;
  font-size: 0.9rem;
  line-height: 1.5;
  opacity: 0.9;
}

.about-note {
  margin-block-start: 1rem;
  font-size: 0.9rem;
  line-height: 1.5;
  opacity: 0.8;
}

/* ============================================================
   THE ALBUM — "my stamps"
   A philatelic album sheet: the archive laid out in a grid,
   one sheet per historical layer, an outline where a stamp is
   missing and the stamp itself where it is not. The counter is
   per sheet and appears only once there is a first stamp; so
   does the invitation to save the collection. Reward first,
   request afterwards, and the request optional.
   ============================================================ */

.album-title {
  padding-block: 1.3rem 0.2rem;
  font-size: 2.1rem;
  font-weight: 700;
  line-height: 1.1;
}

/* THE TWO TALLIES, under the title: how many stamps, and how many of them were
   stuck at the place itself. Label then number, never a sentence with the noun
   behind the numeral — "1 בולים" is a concord error in five of the six
   languages, and the sheets of this album already count this way ("4 / 26").

   `flex-wrap` and not a fixed row: at 375px the Arabic pair is the widest and
   the two still sit side by side, but a font-size step or a longer word drops
   the second pair to its own line instead of squeezing the first.

   Both numbers carry `dir="ltr"` on the element, like every other counter
   here, because bidi is free to move a bare numeral around a Hebrew label.

   Nothing in this rule ranks anything. The second pair is written only when it
   is greater than zero, and it wears the same weight, the same size and the
   same brass as the first — a tally, not a grade. */
.album-total {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem 1.6rem;
  margin-block-start: 0.35rem;
  font-size: 0.95rem;
  font-weight: 700;
  color: var(--brass-text);
}

.total-pair {
  display: inline-flex;
  align-items: baseline;
  gap: 0.4rem;
}

/* The number is the thing being read across the room; the label is what tells
   you what it counts. One step of size and one of weight between them is the
   whole hierarchy — and it is the same one in both pairs, so that "at the
   place" never reads as the louder of the two lines. */
.total-n {
  font-size: 1.15rem;
  color: var(--ink);
}

.total-label {
  font-weight: 600;
  color: var(--brass-text);
}

/* The layer pills sit under the bar, exactly where the map keeps them, so the
   one control that switches layers is in the same place on every page that
   has layers. */
.album-filters {
  margin-block-start: 0.4rem;
}

/* Only the sheet being looked at is laid out. With 34 points the album is
   4.3k pixels tall and the browser pays for all of it; at 250 it would be
   ten times that, and the cost is paid on a phone. `auto` on the intrinsic
   size means the first render teaches the browser each sheet's real height,
   so the scrollbar stops lying after one pass. A browser that does not know
   the property ignores it and gets exactly today's album.

   No margin rule goes with it: containment keeps the sheet label's own top
   margin inside the sheet instead of collapsing it out, so the space between
   two sheets stays exactly what it was. */
.album-sheet {
  content-visibility: auto;
  /* Measured on the phone, not guessed: one row of stamps at two columns is
     11.4rem and the sheet's own label and padding are 4.7rem. The generator
     writes the row count of each sheet into --sheet-lines, because a single
     figure for every sheet makes the scrollbar claim twelve thousand pixels
     for an album of seven. */
  contain-intrinsic-size: auto calc(var(--sheet-lines, 3) * 11.4rem + 4.7rem);
}

.album-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.7rem;
}

.album-header .section-label {
  margin-block-end: 0;
}

/* dir="ltr" is on the element, not decoration: bidi reorders "4 / 26" into
   "26 / 4", which reads as four points holding twenty-six stamps. */
.album-count {
  flex: 0 0 auto;
  font-size: 0.82rem;
  font-weight: 700;
  color: var(--brass-text);
}

/* The sheet itself, in loess: the ground a stamp is mounted on, and the reason
   the perforated paper reads as paper at all. On a near-white page a
   near-white stamp on a near-white background is a rectangle with a shadow —
   the punched edge only becomes a punched edge when the album shows through
   the holes. Loess as an accent surface is exactly what the palette asks for,
   and by night the same rule inverts with it. */
.album-grid {
  display: grid;
  /* 7.6rem is what keeps two stamps on a 375px screen once the sheet's own
     padding is taken out of the column — at 8.6rem the second one fell off and
     the album became a single file of very large stamps. */
  grid-template-columns: repeat(auto-fill, minmax(7.6rem, 1fr));
  gap: 1rem 0.7rem;
  margin-block-start: 0.8rem;
  padding: 0.9rem 0.6rem;
  background-color: var(--loess);
  border-radius: var(--radius);
  list-style: none;
}

/* ---- Saving the passport: a link, and the same link as a code ---- */

.save {
  margin-block-start: 2.2rem;
}

.save-panel {
  margin-block-start: 0.9rem;
  text-align: center;
}

.save-note {
  font-size: 0.92rem;
  line-height: 1.5;
}

.save-code {
  width: min(15rem, 100%);
  margin: 1rem auto 0;
}

.save-code svg {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--radius-small);
}

/* The address is long by nature — it is the collection itself — so it wraps
   anywhere and is set left to right inside the right-to-left page. */
.save-address {
  display: block;
  margin-block-start: 0.9rem;
  padding-block: 0.6rem;
  direction: ltr;
  text-align: left;
  font-size: 0.72rem;
  line-height: 1.5;
  overflow-wrap: anywhere;
  text-decoration: underline;
  color: var(--brass-text);
}

/* ============================================================
   THE BOTTOM NAVIGATION BAR
   Four destinations, fixed, always in thumb reach — the pattern
   every phone owner already knows. Links only: no script.
   ============================================================ */

.nav {
  position: fixed;
  inset-block-end: 0;
  inset-inline: 0;
  z-index: 20;
  background-color: var(--surface);
  border-block-start: 1px solid var(--border);
  padding-block-end: env(safe-area-inset-bottom);
}

.nav-list {
  display: flex;
  width: 100%;
  max-width: var(--measure);
  margin-inline: auto;
  list-style: none;
}

.nav-list > li {
  flex: 1;
  display: flex;
}

.nav-item {
  position: relative;
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.25rem;
  min-height: var(--bar-height);   /* 74px */
  padding-block: 0.45rem;
  font-size: 0.7rem;
  font-weight: 600;
  color: var(--ink);
}

.nav-item:active {
  background-color: var(--touch);
}

/* The icon neither shrinks nor grows: the baseline of the six is the same
   because the six measure the same, and not because they happened to. */
.nav-icon {
  flex: none;
  width: 1.5rem;
  height: 1.5rem;
}

/* NO LABEL BREAKS ONTO TWO LINES. One that breaks ends up taller than the
   other five, and the whole row of icons goes out of alignment — that is what
   was seen on the director's phone with `הבולים שלי`. The word was shortened
   (see `navegacao()` in the generator) and this line is the lock: a future word
   that does not fit will overflow visibly instead of disarranging the bar in
   silence. Fixed `line-height` for the same reason — the label's height stops
   depending on the letters it has. */
.nav-item > span {
  white-space: nowrap;
  line-height: 1.1;
}

.nav-item > * {
  position: relative;
  z-index: 1;
}

/* THE HIGHLIGHT MARKS THE ICON AND THE NAME AS ONE THING. The director's
   request on 13 August: before, the field covered only the icon and the word
   was left outside, in loose turquoise on the bar — two colours for one single
   destination, which reads as two things. Now the field is the whole item and
   both come out in reverse on it. It is still not only colour: the shape
   changes (the field), the weight of the type changes, and `aria-current` says
   the same to whoever listens to the page.
   Contrast of the pair: 4.8:1 by day and 6.5:1 by night — both pass AA. */
.nav-item[aria-current="page"] {
  color: var(--background);
  font-weight: 700;
}

.nav-item[aria-current="page"]::before {
  content: "";
  position: absolute;
  z-index: 0;
  inset-block: 0.4rem;
  inset-inline: 0.25rem;
  border-radius: var(--radius-small);
  background-color: var(--turquoise);
}

/* ---- Desktop (≥768px): the archive view — same column, more air ---- */

@media (min-width: 768px) {
  .question {
    font-size: 2.7rem;
  }

  .point-name {
    font-size: 3rem;
  }

  .point-identity {
    padding-block: 2rem 0.6rem;
  }

  .point-line {
    font-size: 1.12rem;
  }

  .card-mini {
    width: 5.8rem;
    height: 5.8rem;
  }

  /* Both corpora side by side, equal columns, equal weight — the columns
     themselves come from the auto-fit rule above. */
  .verses-pair {
    gap: 2.2rem;
  }

}

/* THE FLOATING DOCK BELONGS TO THE TABLET BAND, and only to it: from 768px up
   to the archive view. Above that the bar moves to the top (see further below),
   and that is why this block has a ceiling — without it, the desktop inherited
   a rounded pill stuck to the bottom and the rules at the top spent their lives
   undoing it. */
@media (min-width: 768px) and (max-width: 63.99rem) {
  /* The bar stops spanning the window and becomes a floating dock over
     the same column the content uses. */
  .nav {
    inset-inline: 0;
    inset-block-end: 1.1rem;
    width: min(var(--measure), calc(100% - 2.2rem));
    margin-inline: auto;
    border: 1px solid var(--border);
    border-radius: 999px;
    box-shadow: 0 10px 30px -12px rgba(35, 32, 25, 0.35);
    overflow: hidden;
  }

  /* On the desktop dock the bar is shorter on the outside, and the field draws
     in a little more so as not to touch its rounded edge. */
  .nav-item[aria-current="page"]::before {
    inset-block: 0.3rem;
  }
}

/* ===========================================================================
   ילדים — THE CHILDREN'S SECTION

   ONE BAND PER THEME, STACKED, and with no filter above them. The director's
   decision on 13 August: the page had a carousel with all forty, a row of pills
   that only jumped to an anchor, and a grid with all forty again. With one
   gallery per theme, the band's title IS the filter — and each story appears
   only once.

   THE CARD SHRANK BECAUSE OF THE STACK. With seven bands one under the other,
   what says there is more below is seeing the start of the next band; a card of
   13.5rem put only one on the 375px screen and the page went back to looking
   like a vertical list. 11rem of height and 6rem of photograph let two whole
   bands in.

   THE CAROUSEL SHOWS HALF A CARD ON EACH SIDE, and that is the whole
   affordance: a carousel whose first card fills the screen looks like a still
   image and nobody touches it. The arithmetic that does it has no trick in it,
   and it is worth writing down because it looks wrong at first sight:

     padding-inline: 11%   →  the content box becomes 78% of the width
     flex: 0 0 100%        →  the card takes 100% OF THAT box = 78% of the total

   A percentage padding resolves against the element's own width, and a
   percentage flex-basis resolves against the content box. The two together give
   exactly 78% with no spacer elements, no `calc`, no `:has()` and no viewport
   units that would break on the desktop, where the column is limited to
   `--measure`. `scroll-padding-inline` makes the snap land in the same place.

   RTL does not need a single line here: `padding-inline`, `flex` and
   `scroll-snap-align: center` are all direction-agnostic, and the browser
   already starts the scroll at the beginning of reading — which in Hebrew is
   the right.

   THE THEME CARD HAS NO PHOTOGRAPH, and does not pretend to have one. There is
   no photograph of what a desert is. Instead of a grey box standing in for one,
   the card's body fills the whole height and carries its category's colour —
   the same mechanism as the map, where colour carries the data and not the
   decoration. Absence is silence.
   =========================================================================== */

.kids-carousel {
  display: flex;
  gap: 0.7rem;
  overflow-x: auto;
  overscroll-behavior-inline: contain;
  scroll-snap-type: x mandatory;
  padding-inline: 11%;
  scroll-padding-inline: 11%;
  padding-block-end: 1rem;
  margin-inline: calc(var(--gutter) * -1);
  scrollbar-width: none;
}

.kids-carousel::-webkit-scrollbar { display: none; }

.kids-carousel > .kids-card { flex: 0 0 100%; min-height: 11rem; }

/* The card. In the GRID it measures what its own content asks for — a theme
   card there is two lines of text and should not take up half the screen. The
   fixed height belongs only to the carousel, where a card with a photograph and
   one without have to measure the same, or the row reads as something broken. */
.kids-card {
  display: flex;
  flex-direction: column;
  background-color: var(--surface);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  overflow: hidden;
  scroll-snap-align: center;
  color: inherit;
  text-decoration: none;
}

/* THE LINK IS NOW A PART OF THE CARD, and not the whole card. The play and the
   share are its siblings — a button inside an `<a>` is invalid HTML, and the
   phone resolves the ambiguity by navigating when what was wanted was to
   listen. The navigation target is still everything you can see: photograph and
   text. */
.kids-card-target {
  display: flex;
  flex: 1;
  flex-direction: column;
  color: inherit;
  text-decoration: none;
}

.kids-card-target:active { background-color: var(--touch); }

/* THE 6REM STRIP WAS BEHEADING THE ANIMALS. Measured, and the director saw it
   before I did: "a vulture with no head, an ibex with no head and a hyena off
   centre" («um abutre sem cabeça, um íbex sem cabeça e uma hiena descentrada»).

   The cause is not the framing of the photograph, it is the arithmetic of the
   frame. The image that comes in here is the square 432px thumbnail, and the
   box measured 408×108 on the desktop — ratio 3.78. A `cover` of 3.78 over an
   image of 1.0 keeps 26% of the height, that is, the band between 37% and 63%
   of the photograph. An ibex's head lives above that, and the frame cut it off
   without missing once.

   3/2 AND NOT SOME OTHER NUMBER, and it was chosen by looking: the same crop
   was generated at 3.78 · 2.4 · 2.0 · 16:9 · 3:2 · 4:3 for the five animal
   photographs, and 3:2 is the first ratio at which ALL of them come out whole —
   the vulture comes in at 2.0, the hyena at 2.4, but the ibex's horns and the
   צבי's only fit at 3:2. It keeps 67% of the height against the 26% of before.

   AND IT COSTS LESS THAN IT LOOKS: the carousel card already had `min-height:
   11rem` and had air to spare below the title. */
.kids-card-photo {
  display: block;
  background-color: var(--loess);
}

.kids-card-photo img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 3 / 2;
  object-fit: cover;
}

/* With no photograph, the card is TYPOGRAPHIC — and it has to look decided,
   not unfinished. A tall beige rectangle with two small lines at the foot reads
   like an image that did not load; the same rectangle with the category label
   large, in its colour, reads like a cover. It is the same height and it is
   another thing. With a photograph, the body sits against the top and the text
   goes back to its normal size. */
.kids-card-body {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 0.35rem;
  padding: 0.85rem 0.95rem;
  background-color: var(--kids-field, var(--loess));
}

.kids-card-photo + .kids-card-body {
  flex: 0 0 auto;
  justify-content: flex-start;
  background-color: var(--surface);
}

.kids-card-theme {
  font-size: 1.02rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--kids-color, var(--brass-text));
}

.kids-card-title {
  font-size: 1.3rem;
  font-weight: 700;
  line-height: 1.25;
}

/* With a photograph the text is a caption, and it shrinks: what rules the card
   becomes the image. Without it, the text IS the card. */
.kids-card-photo + .kids-card-body .kids-card-theme { font-size: 0.78rem; }
.kids-card-photo + .kids-card-body .kids-card-title { font-size: 1.05rem; }


/* ---- THE PLAY AND THE SHARE, ON THE CARD ITSELF ----

   The director's request on 13 August. They are two separate targets on a bar
   at the foot of the card, and SEPARATE is the point: the finger that wants to
   listen must not open the page, and the one that wants to open the page must
   not put sound out on the street. Both 44px on a side — the thumb's measure,
   and the same one the rest of the product uses.

   The bar paints no background of its own: it is inside the card and belongs to
   the card. A second tone here would split in two an object that is one.

   `[hidden]` NEEDS A RULE because the class rule beats the browser's. Both
   buttons are born hidden and only the script reveals them — without it neither
   does what it promises — and without this line the `display: flex` below
   showed them anyway, dead. That is how the corner button spent years appearing
   without javascript; here it does not. */
.kids-card-actions {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.55rem 0.6rem;
}

.kids-card-actions button[hidden] { display: none; }

.kids-card-play {
  display: flex;
  flex: 1;
  align-items: center;
  gap: 0.5rem;
  min-height: 2.75rem;         /* 44px */
  padding-inline: 0.9rem;
  font-family: inherit;
  font-size: 1rem;
  font-weight: 700;
  color: var(--ink);
  background-color: var(--loess);
  border: 0;
  border-radius: 999px;
}

.kids-card-play:active { background-color: var(--touch); }

/* The label swaps its word on touch — לשמוע for להפסיק — and the two must not
   break onto a second line on a narrow card: the button would jump in height at
   the very instant the child touches it. */
.kids-card-play-label { white-space: nowrap; }

/* The clock sits against the end of the line and the digits all measure the
   same: a countdown that pushes the label every second reads as a
   malfunction. */
.kids-card-time {
  margin-inline-start: auto;
  font-size: 0.92rem;
  font-variant-numeric: tabular-nums;
}

/* With no play — a story still without a voice — the share goes alone to the
   end of the line, and the bar is still the same bar. */
.kids-card-share {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  height: 2.75rem;
  margin-inline-start: auto;
  padding: 0;
  color: var(--ink);
  background-color: var(--loess);
  border: 0;
  border-radius: 999px;
}

.kids-card-share:active { background-color: var(--touch); }

.kids-card-share.is-done { color: var(--turquoise); }

/* ---- THE TWO SHORTCUTS: the חידון and the memory game ----

   "On the ילדים home I could hardly make out the cards for the questions and
   the memory game, give each one a colour" («No home do ילדים quase não percebi
   os cards de perguntas e do jogo da memória, dê uma cor para cada um») — the
   director, 13 August. They were two white cards among white cards, with a
   small brass icon.

   Each one now carries its own colour, and the two are the TWO COLOURS THE
   PRODUCT ALREADY HAS: brass for the חידון — the material of the plaque and the
   stamp, and the חידון is the school's test — and turquoise for the memory
   game. No new colour enters the palette on account of two cards, and both are
   already measured in the two themes.

   And the colour does not travel alone: what distinguishes one card from the
   other is the icon and the title, as it always was; the colour only makes them
   noticed. The filled field is what separates them from the story cards, which
   are white and carry a photograph.

   A bar of colour on the start margin — `kids-remember`'s mark — was tried and
   left: with the card's radius, a 5px edge draws a crooked wedge in the corner,
   and a card with a crooked corner reads as a defect. */
.kids-shortcut {
  background-color: var(--shortcut-field);
}

.kids-shortcut .card-title,
.kids-shortcut .feature-icon,
.kids-shortcut .arrow {
  color: var(--shortcut-color);
}

.kids-shortcut-quiz {
  --shortcut-color: var(--brass-text);
  --shortcut-field: rgba(176, 141, 62, 0.16);
}

.kids-shortcut-memory {
  --shortcut-color: var(--turquoise);
  --shortcut-field: rgba(46, 125, 116, 0.13);
}

/* The band's label already brings 1.9rem above it; the section's margin exists
   so that it does not collapse with the card that comes before the first. */
.kids-section { margin-block-start: 1.4rem; }

/* Inside a band the label sits against the carousel: they are one thing. */
.kids-section .section-label { margin-block-end: 0.5rem; }

/* ---- The page of one story ---- */

/* The photograph commands the screen, as everywhere in this product. When
   there is none, there is no block — and the page starts with the category
   label. */
/* THE SAME FULL BLEED THE TOP OF THE POINT PAGE HAD, and the same correction —
   pointed out by the director on 18 August: "in ילדים there is still that
   problem of images that are very wide horizontally inside the themes" («em
   ילדים ainda ficou aquele problema de imagens muito extensas na horizontal
   dentro dos temas»). The frame was full bleed (the width of the screen) with a
   fixed `max-height: 15rem` and no `aspect-ratio`: at 375 it gave 375×270 —
   ratio 1.39, almost harmless — but at 1440 it gave 1425×270 — ratio 5.28, and
   each photograph lost more than 70% of its height. The 40 photographs these
   bands actually use were measured: median 1.50, mean 1.56 — this particular
   archive is wider than the product's 265 photographs (median 1.33, which is
   what gave 4/3 at the top of the point page). 3/2 was compared against 4/3
   over the 40: 3/2 keeps more on average (90.4% against 88.6%) and in the worst
   case (44.3% against 39.3%) — 3/2 and not 4/3.

     375   375×270  R 1.39  kept 0.89   →   375×250  R 1.50  kept 0.90
     1440 1425×270  R 5.28  kept 0.30   →   612×408  R 1.50  kept 0.90

   `max-inline-size: var(--measure)` brings the frame to the width of the
   reading column, like the top of the point page; without it the box would go
   on widening with the window and the 3/2 would never have room to happen. */
.kids-figure {
  width: 100%;
  max-inline-size: var(--measure);
  margin-inline: auto;
  background-color: var(--loess);
}

.kids-figure img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 3 / 2;
  max-block-size: clamp(12rem, 34vh, 20rem);
  object-fit: cover;
}

.kids-story { padding-block-start: 1.2rem; }

.kids-theme-label {
  margin: 0 0 0.3rem;
  font-size: 0.86rem;
  font-weight: 700;
  color: var(--kids-color, var(--brass-text));
}

.kids-title {
  margin: 0 0 1.2rem;
  font-size: 1.85rem;
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: -0.01em;
}

/* THE PLACE FOR THE PLAY, RESERVED BEFORE THERE IS ANY AUDIO.

   Not a single track has been generated and so there is not a single button on
   the site — a play that does not play is the caption for an absence this
   product does not write. But the LAYOUT has to be right from now on: the
   director asked for the play under the image, and if the measurements only
   appear on the day the audio arrives, that day is a day of redesigning the
   whole page. So the positioning rule exists now and waits. The block lives
   between the title and the thing to take away, which is where
   `paginaHistoriaCrianca` already writes it when the manifest has a track. */
.kids-story .point-listen {
  margin-block: 0 1.5rem;
}

/* THE THING TO TAKE AWAY. One card only, before the text and not after: the
   child who reads it all finds it again at the end through the reading itself,
   and the one who does not read it all still takes away the number, the name or
   the date. The brass bar on the start margin marks it with no box and no
   icon. */
.kids-remember {
  border-inline-start: 4px solid var(--kids-color, var(--brass-text));
  margin-block-end: 1.5rem;
}

.kids-remember-label {
  margin: 0 0 0.35rem;
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  color: var(--kids-color, var(--brass-text));
}

.kids-remember-text {
  margin: 0;
  font-size: 1.06rem;
  font-weight: 600;
  line-height: 1.45;
}

/* A generous body: street mode's minimum is 18px, and this is read sitting
   down with a child beside you. Short paragraphs and many of them, which is the
   shape of the text. */
.kids-text {
  font-size: 1.12rem;
  line-height: 1.68;
}

.kids-text p { margin: 0 0 1.05rem; }

/* ---- The colour of each category ----
   Vocabulary of data and not of decoration, like `layer-*` on the map: the
   generator writes only the name. The tone of the field is the same in both
   themes — it is alpha over the surface, and rises or falls with it. What
   changes is the colour of the text, which has to pass contrast on both
   sides. */
.kids-theme-hai         { --kids-color: #7E5F1C; --kids-field: rgba(176, 141, 62, 0.14); }
.kids-theme-tzomeach    { --kids-color: #2E7D74; --kids-field: rgba(46, 125, 116, 0.13); }
.kids-theme-arkheologia { --kids-color: #8A5A2B; --kids-field: rgba(138, 90, 43, 0.13); }
.kids-theme-astronomia  { --kids-color: #3E5A8C; --kids-field: rgba(62, 90, 140, 0.13); }
.kids-theme-aklim       { --kids-color: #A45A3C; --kids-field: rgba(164, 90, 60, 0.10); }
.kids-theme-geografia   { --kids-color: #556B2F; --kids-field: rgba(85, 107, 47, 0.14); }
.kids-theme-makom       { --kids-color: #7E5F1C; --kids-field: rgba(176, 141, 62, 0.14); }

/* Written twice for the reason the head of this file already gives: a media
   query cannot be widened with a selector, and "the system says night" and "she
   chose night" are two conditions with a single set of values. Always edit both
   of them. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .kids-theme-hai         { --kids-color: #D2AE60; }
  :root:not([data-theme="light"]) .kids-theme-tzomeach    { --kids-color: #4FA79C; }
  :root:not([data-theme="light"]) .kids-theme-arkheologia { --kids-color: #C79463; }
  :root:not([data-theme="light"]) .kids-theme-astronomia  { --kids-color: #8FAEDC; }
  :root:not([data-theme="light"]) .kids-theme-aklim       { --kids-color: #DB9273; }
  :root:not([data-theme="light"]) .kids-theme-geografia   { --kids-color: #A9BC78; }
  :root:not([data-theme="light"]) .kids-theme-makom       { --kids-color: #D2AE60; }
}

:root[data-theme="dark"] .kids-theme-hai         { --kids-color: #D2AE60; }
:root[data-theme="dark"] .kids-theme-tzomeach    { --kids-color: #4FA79C; }
:root[data-theme="dark"] .kids-theme-arkheologia { --kids-color: #C79463; }
:root[data-theme="dark"] .kids-theme-astronomia  { --kids-color: #8FAEDC; }
:root[data-theme="dark"] .kids-theme-aklim       { --kids-color: #DB9273; }
:root[data-theme="dark"] .kids-theme-geografia   { --kids-color: #A9BC78; }
:root[data-theme="dark"] .kids-theme-makom       { --kids-color: #D2AE60; }

/* ===========================================================================
   THE חידון

   The same carousel as the gallery — the same 78% arithmetic, the same snap —
   with a question card instead of a story card. `.quiz-row` is a `<ul>` and so
   it only needs to lose the list markers.

   THREE STATES. Unanswered, right, wrong. On a wrong answer, the option touched
   turns red and the right one blinks three times and then stays fixed green:
   blinking calls the eye, staying fixed lets you read without hurrying.

   The page moves on by itself in both cases, and the waits differ by a factor
   of five: 600ms on a right answer, where there is nothing to read, and three
   seconds on a wrong one, where there is. The three seconds are the director's,
   13 August. The blink takes 1.86s of them, on purpose: the right one still
   stands still and green for more than a second before the next card comes in.
   Anyone who has already swiped in the meantime is not run over — the script
   only moves on if the answered card is still centred.

   The two state colours are not the product's palette, and that is on purpose:
   green and red here are not decoration, they are the answer. They are the only
   two places on the site where a colour CARRIES the information — which is why
   neither of them depends on colour alone: the right one also gains weight and
   a rule, and the wrong button is struck through. Anyone who cannot tell the
   two colours apart still reads the result. */

/* EACH CARD MEASURES WHAT IT ITSELF ASKS FOR, and that is what `flex-start`
   does here. In a flex row the default alignment is `stretch`: all one hundred
   and forty-seven cards took the height of the TALLEST of them — the longest
   question with the four longest options — and since the content was centred, a
   short card opened more than half a card of emptiness above the counter. That
   is what the director saw on his phone: "the question card ended up very tall
   at the top, and pushed everything down" («o card da pergunta ficou com uma
   altura muito grande no topo, e empurrou tudo para baixo»), with the fourth
   option off the screen again. The question starts at the top of the card. */
.quiz-row {
  list-style: none;
  margin: 0;
  padding-inline: 11%;
  align-items: flex-start;
}

.quiz-card {
  display: flex;
  flex: 0 0 100%;
  flex-direction: column;
  padding: 1.1rem 1.15rem;
  background-color: var(--surface);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  scroll-snap-align: center;
}

.quiz-count {
  margin: 0 0 0.5rem;
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  color: var(--brass-text);
}

.quiz-question {
  margin: 0 0 0.9rem;
  font-size: 1.32rem;
  font-weight: 700;
  line-height: 1.32;
}

.quiz-options {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.5rem;
}

/* A target well above the floor: a thumb, in the sun, in a hurry. The
   `min-height` is what guarantees the thumb's 44px; the `padding` only counts
   when the answer breaks onto two lines, and so tightening it shrinks no target
   — it shrinks the longest question in the deck, which was the one pushing the
   fourth option under the bottom bar. */
.quiz-option {
  width: 100%;
  min-height: 3.15rem;
  padding: 0.55rem 0.9rem;
  font: inherit;
  font-size: 1.06rem;
  font-weight: 600;
  text-align: start;
  color: var(--ink);
  background-color: var(--background);
  border: 2px solid var(--border);
  border-radius: 0.85rem;
  cursor: pointer;
}

.quiz-option:active { background-color: var(--touch); }
.quiz-option[disabled] { cursor: default; opacity: 1; }

/* The right one. Colour, weight and a rule at its head — three signals, only
   one of them colour. */
.quiz-option.is-correct {
  color: #17603F;
  background-color: rgba(23, 96, 63, 0.11);
  border-color: #17603F;
  font-weight: 700;
}

/* The wrong one. Colour and the text struck through, so that it does not
   depend on colour. */
.quiz-option.is-wrong {
  color: #9B2C22;
  background-color: rgba(155, 44, 34, 0.10);
  border-color: #9B2C22;
  text-decoration: line-through;
  text-decoration-thickness: 2px;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .quiz-option.is-correct {
    color: #6FCB9B;
    background-color: rgba(111, 203, 155, 0.15);
    border-color: #6FCB9B;
  }
  :root:not([data-theme="light"]) .quiz-option.is-wrong {
    color: #F0928A;
    background-color: rgba(240, 146, 138, 0.14);
    border-color: #F0928A;
  }
}

:root[data-theme="dark"] .quiz-option.is-correct {
  color: #6FCB9B;
  background-color: rgba(111, 203, 155, 0.15);
  border-color: #6FCB9B;
}

:root[data-theme="dark"] .quiz-option.is-wrong {
  color: #F0928A;
  background-color: rgba(240, 146, 138, 0.14);
  border-color: #F0928A;
}

/* Three blinks and it stops. It is not a loop: a permanent blinking thing
   beside text to be read is noise, and after two seconds nobody sees it any
   more. */
@keyframes quiz-piscar {
  0%, 100% { opacity: 1; }
  /* 0.45 and not 0.2: the right one never becomes hard to read during the
     blink. Blinking is to call the eye, not to hide the answer. */
  50%      { opacity: 0.45; }
}

.quiz-option.is-blinking {
  animation: quiz-piscar 0.62s ease-in-out 3;
}

/* Anyone who turned motion off in the system gets the right one already
   fixed. It loses nothing: the colour, the weight and the border say the same
   thing without moving. */
@media (prefers-reduced-motion: reduce) {
  .quiz-option.is-blinking { animation: none; }
}

/* The link to the page that actually contains the answer.

   IT IS BORN HIDDEN WITH ITS SPACE RESERVED, and both halves matter. Visible
   before answering, it turns every question into a one-tap lookup. And it is
   `visibility` and not `display` on purpose: this way the card is the same
   height before and after, and nothing jumps under the finger at the instant
   the child has finished touching. `visibility: hidden` also takes it out of
   the tab order and out of the screen reader while it makes no sense.

   The target opens the full point page or the story — both contain the answer,
   and reading the answer is the aim of this section and not an escape from
   it. */
.quiz-learn {
  margin-block-start: 1rem;
  align-self: start;
  min-height: 2.75rem;
  display: inline-flex;
  align-items: center;
  font-size: 1rem;
  font-weight: 700;
  color: var(--brass-text);
  text-decoration: underline;
  text-underline-offset: 0.22em;
  visibility: hidden;
}

.quiz-card.is-answered .quiz-learn { visibility: visible; }

/* One line, and not a block. On a 375px screen the gallery's large heading
   pushed the fourth option under the bottom bar, and a multiple-choice question
   with one option hidden is a broken question. */
.quiz-line {
  margin: 0.2rem 0 1rem;
  font-size: 0.92rem;
  font-weight: 600;
  color: var(--ink-weak, var(--brass-text));
}

/* THE THERMOMETER OF RIGHT ANSWERS — the director's request, 13 August: "a
   thermometer or little stars for the proportion of correct answers, which
   resets per session with the device, without taking up much space" («um
   termómetro ou estrelinhas de proporção de respostas corretas, que se reseta
   por sessão com o dispositivo, sem ocupar muito espaço»).

   IT TAKES UP ZERO. It is not added to the line above: it replaces it, at the
   moment there is a first answer. Same margin, same type size, same line height
   — the question card does not drop a pixel, and the fourth option stays where
   it was. That defect has already come back twice on this page.

   COLOUR DOES NOT CARRY THE INFORMATION. Anyone who cannot tell green from grey
   reads the number, which is always there and is exact. And the bar is one
   colour only, whatever the proportion: a green that turned red halfway would
   be the page judging a child, and what it measures is how much she has got
   right, not how much she is worth. The green is the same as the right answer's,
   three lines above — on this page that colour already means that.

   IT FILLS FROM THE INSIDE OUT STARTING AT THE BEGINNING OF THE LINE:
   `inline-size` and not `width`, and so in Hebrew it grows from the right,
   which is where it is read from. */
.quiz-score {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  margin: 0.2rem 0 1rem;
  font-size: 0.92rem;
  font-weight: 700;
  color: var(--ink);
}

.quiz-score-label { white-space: nowrap; }

/* Four pixels tall and not eight: beside a line of text, a thick bar becomes a
   second object. Thin, it is a ruler. */
.quiz-score-bar {
  flex: 1;
  min-inline-size: 3rem;
  block-size: 0.28rem;
  border-radius: 999px;
  background-color: var(--border);
  overflow: hidden;
}

.quiz-score-fill {
  display: block;
  block-size: 100%;
  inline-size: 0;
  border-radius: 999px;
  background-color: #17603F;
}

/* Fixed-width figures: without them the bar shrinks and grows a pixel every
   time the counter goes from 9 to 10. */
.quiz-score-count { font-variant-numeric: tabular-nums; }

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .quiz-score-fill { background-color: #6FCB9B; }
}

:root[data-theme="dark"] .quiz-score-fill { background-color: #6FCB9B; }

/* ===========================================================================
   THE MEMORY GAME

   Twelve photographs of the city, each one twice. LOOP.md, A56, piece 2 — and
   the sentence that defines it is "when the child gets a pair right, show the
   NAME of the place" («quando a criança acerta um par, mostra o NOME do
   lugar»): the game has to teach, not only entertain.

   WITHOUT THE SCRIPT THE CARDS ARE FACE UP, and the stylesheet draws exactly
   that: a gallery of twelve places with a name and a link. The back only exists
   inside `.is-game`, which is the class site/memory.js puts on the board. That
   way the page is never a dead board — it is a sheet that gains a game.

   AND NO THREE-DIMENSIONAL FLIP. A `preserve-3d` with `backface-visibility` is
   a stylesheet trick for an effect that is not necessary, and a trick that is
   needed for something to work goes out. The card has one face over it; to
   reveal is to take it away. */

.memory-state {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1.4rem;
  margin-block-end: 0.6rem;
}

.memory-measure {
  margin: 0;
  font-size: 1rem;
  font-weight: 700;
}

.memory-label {
  font-weight: 600;
  color: var(--brass-text);
}

/* The name of the place found, in large type and on a line of its own. In a
   79-pixel cell a three-word Hebrew name cannot be read, and the name is the
   whole point of this piece.

   THE HEIGHT IS RESERVED FOR TWO LINES, and not for one. The longest name in
   the deck — `גשר הרכבת הטורקי על נחל באר שבע` — takes two at 375px, and with
   one line reserved the board dropped half a centimetre at the instant the
   child got a pair right. A board that moves under the finger is the same
   defect that took the automatic advance out of the חידון on a wrong answer. */
.memory-message {
  margin: 0 0 0.9rem;
  min-height: 3.2rem;
  font-size: 1.22rem;
  font-weight: 700;
  line-height: 1.3;
}

.memory-end {
  color: var(--brass-text);
}

/* THE BOARD HAS TO BEHAVE AT BOTH EXTREMES, and they are far apart: four cards
   at the first level and twenty-four at the last. With four cards at four
   columns it came out a strip; at two columns and with no width ceiling it came
   out four squares of half a screen each. The number of columns comes from the
   script, in `data-columns`, and the width ceiling comes from here.

   Without the script there is no attribute at all, and the twelve photographs
   sit in four columns — which is the sheet this page is without javascript. */
.memory-board {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0.5rem;
}

.memory-board[data-columns="2"] {
  grid-template-columns: repeat(2, 1fr);
  max-width: 17rem;
}

.memory-cell {
  margin: 0;
}

.memory-card {
  position: relative;
  display: block;
  aspect-ratio: 1;
  overflow: hidden;
  border-radius: var(--radius-small);
  background-color: var(--surface);
  box-shadow: var(--shadow);
  color: var(--ink);
  text-decoration: none;
}

.memory-card img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* The name over the photograph. It is not for reading from a distance — it is
   for identifying what you are looking at; what is read is the large line under
   the board. The dark veil is what makes the text survive a bright photograph
   in the sun. */
.memory-name {
  position: absolute;
  inset-inline: 0;
  inset-block-end: 0;
  padding: 0.7rem 0.35rem 0.3rem;
  font-size: 0.72rem;
  font-weight: 700;
  line-height: 1.2;
  text-align: center;
  color: #FFFFFF;
  background: linear-gradient(to top, rgba(20, 18, 14, 0.82), rgba(20, 18, 14, 0));
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* The back. It only exists when there is a game — without the script this rule
   never applies and the cards stay in view. The colour is the product's brass,
   and the dot in the centre gives it a front without needing an image that
   would have to be downloaded. */
.memory-back {
  display: none;
}

/* WHILE THE GAME IS ON, THE CARD HAS NO NAME AT ALL. The director's decision
   on 13 August: "do not put the name on the card; when a pair is matched, have
   a popup of the place appear with photo and name" («não coloque o nome no
   card; ao acertar um casal, apareça um popup do local com foto e nome»). In a
   79-pixel cell a three-word Hebrew name cannot be read, and a card with a name
   hands the pair to whoever reads fast. The name is still written in the html —
   without the script this stylesheet is a gallery of twelve places with a name
   and a link — and it is the game that takes it away.

   `display: none` and not `visibility`: it takes it out of sight AND out of the
   accessibility tree, or the game would say the answer to whoever listens to
   the page. */
.memory-board.is-game .memory-name {
  display: none;
}

.memory-board.is-game .memory-card:not(.is-flipped) .memory-back {
  display: block;
  position: absolute;
  inset: 0;
  background-color: var(--brass-text);
  background-image: radial-gradient(circle at 50% 50%, rgba(245, 241, 232, 0.9) 0 12%, rgba(245, 241, 232, 0) 12.5%);
}

.memory-board.is-game .memory-card:active {
  background-color: var(--touch);
}

/* The card that has been found does not go faded: it gains a frame and a tick.
   Colour alone is never enough, here as in the חידון — and since the name left
   the card, the tick could no longer live in it and becomes a mark in the
   corner. */
.memory-board.is-game .memory-card.is-found {
  outline: 3px solid #17603F;
  outline-offset: -3px;
}

.memory-board.is-game .memory-card.is-found::after {
  content: "✓";
  position: absolute;
  inset-block-start: 0.25rem;
  inset-inline-start: 0.25rem;
  display: grid;
  place-items: center;
  width: 1.35rem;
  height: 1.35rem;
  font-size: 0.85rem;
  font-weight: 700;
  line-height: 1;
  color: #FFFFFF;
  background-color: #17603F;
  border-radius: 999px;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .memory-board.is-game .memory-card.is-found {
    outline-color: #6FCB9B;
  }
}

:root[data-theme="dark"] .memory-board.is-game .memory-card.is-found {
  outline-color: #6FCB9B;
}

.memory-again {
  margin-block-start: 1.2rem;
}

/* On the desktop the board does not stretch to the full screen: a 300-pixel
   card turns a memory game into an exercise in scrolling. */
@media (min-width: 40rem) {
  .memory-board {
    max-width: 30rem;
    gap: 0.7rem;
  }
  .memory-name {
    font-size: 0.9rem;
  }

  /* THE TOP PHOTOGRAPH GAINS CORNERS WHEN IT STOPS TOUCHING THE EDGE.

     On the phone it is full bleed and a rounded corner would be an invention;
     from here up the window is wider than the reading column, the photograph
     sits centred with a margin on both sides, and a rectangle with sharp
     corners among rounded cards reads like an image that has not finished
     loading. The radius is that of the sheet that rises over it — 1.6rem, the
     same pair of properties — and only at the top: at the bottom the corners
     sit under the sheet, and rounding them would be rounding a line nobody
     sees. */
  .point-photo img {
    border-start-start-radius: 1.6rem;
    border-start-end-radius: 1.6rem;
  }
}

/* ===========================================================================
   THE ARCHIVE VIEW — ≥64rem (1024px)

   «Desktop is the archive view — search, map, long reading, the grandson in
   Melbourne looking for a surname. The same database, a different density.»
   («Desktop é a vista de acervo — pesquisa, mapa, leitura longa, o neto em
   Melbourne procurando um sobrenome. Mesma base de dados, densidade
   diferente.») (CLAUDE.md)

   Until now the desktop was the phone stretched: a 34rem column in the middle
   of a 1440 screen, everything stacked, and the thumb's bar floating over the
   last row of cards. It is not a new design — it is the SAME typography, the
   same colours, the same cards, arranged for a wide screen.

   THREE DECISIONS HOLD UP THE WHOLE BLOCK:

   1 · THE READING MEASURE DOES NOT CHANGE. `--measure` (34rem) is still the
       point page's text column, because 65-75 characters is the legible limit
       and stretching a paragraph out to 1440px is the classic defect of someone
       who discovers they have space. What gains width is the ARCHIVE — lists,
       search, map, album — and that is why the wide measure has a name of its
       own instead of overwriting the other.

   2 · WHAT DECIDES THE NUMBER OF COLUMNS IS THE `auto-fill`, and not a number
       written per breakpoint. `minmax(20rem, 1fr)` says the one thing that is
       really known: below 20rem a card with a thumbnail, a title, one line and
       three tags stops fitting. The rest is the browser's arithmetic — it gives
       2 columns at 1024px and 3 from about 1180px, and it still gives 1 inside
       the point page's narrow column without needing a written exception.

   3 · RTL DOES NOT NEED A LINE HERE. `grid-template-columns`, `padding-inline`
       and `flex-basis` are direction-agnostic, and the browser fills the grid
       from the start of reading — which in Hebrew is the right and in English
       the left. Confirmed in both.
   =========================================================================== */

:root {
  /* Three card columns and the gutters. It has a ceiling and is not `vw`: on a
     1920 wall a grid with no limit does not come out dense, it comes out
     scattered. */
  --measure-archive: 72rem;

  /* THE HEIGHT OF THE HEADER ROW, one for the twelve pages. 3.75rem is 67.5px,
     which is what eleven of them already measured — the ruler does not move
     what was already right, it aligns what was not. It lives outside the
     breakpoint because the value is the same number throughout the stylesheet
     and not a decision about width. */
  --header: 3.75rem;
}

@media (min-width: 64rem) {
  /* ---- The wide column, and it belongs to the BODY and not to `main` ----
     The header carries the brand, the footer carries the credits, and if only
     the middle widened, the three would stop sharing the same margin — the logo
     would end up perched over the second column of cards. A page is an archive
     page or it is not; it is not an archive page only in the middle. */
  .body-archive .band {
    max-width: var(--measure-archive);
  }

  .body-archive .feed {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(20rem, 1fr));
    gap: 0.85rem;
    align-items: start;
  }

  /* The vertical stack was made of margins between siblings; in a grid the
     sibling's margin puts the whole row out of alignment, and what gives the
     space is the `gap`. */
  .body-archive .feed > * + * {
    margin-block-start: 0;
  }

  /* ==========================================================================
     THE VERTICAL RULER, APPLIED

     The three values are declared in the `:root` at the top of this
     stylesheet, with the reasoning and the earlier measurements. Here is where
     they touch the page.

     ONE RULE FOR ALL THE CHILDREN OF `main`, AND NOT ONE PER COMPONENT. It is
     this form that solves the defect the director caught, and not the pair of
     cards where he saw it: `margin-block: X 0` is a shorthand, and a shorthand
     REWRITES both margins — the one above AND the one below. That is, every
     element that brought its own margin from birth ("I, who was written later,
     give myself 1.4rem underneath") loses it here and receives the ruler's. It
     is not a margin added to the others; it is the only one.

     `main.band` and not `main`, and it is specificity arithmetic and not
     style: `.feature-city` is (0,1,0) and would beat a `main >` of (0,0,1) —
     the card would go on bringing its own margin and the defect would still be
     there. (0,1,1) beats every rule made of a single class, which is the
     overwhelming majority.

     AND THE MAP STAYS OUT OF IT FOR FREE: the map's `main` is `.map-main` and
     it never had `.band` — it is the canvas that does not scroll, and a
     reading ruler has nothing to say to it.
     ========================================================================== */
  main.band > * {
    margin-block: var(--rhythm-block) 0;
  }

  /* TWO SIBLINGS OF THE SAME NATURE stay close. Two cards in a row are a
     stack, and a stack with 2rem between each one stops reading as a stack. */
  main.band > .card + .card,
  main.band > .section-layer + .section-layer,
  main.band > .album-sheet + .album-sheet,
  main.band > .kids-section + .kids-section,
  .about-page > .card + .card {
    margin-block-start: var(--rhythm);
  }

  /* THE LABEL AND WHAT IT NAMES are one single piece. The label loses the
     margins it had (34.2px above and 14.4px below, written when it was the only
     one deciding) and starts receiving the ruler's distance above, like any
     other block; what stays short is only the gap down to the list it names. */
  .section-label {
    margin-block: 0;
  }

  .section-label + * {
    margin-block-start: var(--rhythm-tight);
  }

  /* THE LINE THAT SAYS WHAT THIS IS, under the brand on the home page. It is
     the brand's caption and not a block following it. */
  main.band > .brand-line {
    margin-block-start: var(--rhythm-tight);
  }

  /* THE POINT PAGE OPENS ON THE NAME, pressed against the top of the sheet
     that rises over the photograph — that closeness is the design of the page
     and not a forgotten margin. The rest of the point page follows the ruler
     like all the others. */
  .point-body > :first-child {
    margin-block-start: 0;
  }

  /* THE CEILING ON THE TOP PHOTOGRAPH LOOSENS, and it is what lets the 4/3
     happen.

     At 1440×900 the column gives 612px of width, and 4/3 asks for 459px of
     height; the 34vh ceiling gives 306 and would go on ruling, leaving the frame
     at 2.0 — better than the 4.66 of before, and still far from the 1.333 the
     measurement asks for. 52vh gives 468 and gets out of the way, and the frame
     lands exactly on 4/3.

     52 and no more: with the photograph at 459px the listen button ends at
     777px of 900, and is still above the fold. On shorter windows the ceiling
     wins again and the frame shortens instead of pushing the control off the
     screen — which is the phone's 44vh lesson, applied where it is also true.

     And the temporary illustration inherits the same ceiling for free, which
     does it good: `max-height: 34vh` forced it to fit into 306px in a frame 612
     wide, and with `contain` that drew it at 514px with almost 100px of loess
     on each side. With 468 it fits whole and with no bands. */
  .point-photo img {
    max-block-size: 52vh;
  }

  /* THE SAME LOOSENING, FOR THE 3/2 OF THE CHILD'S STORY. At 1440×900 the
     column gives 612px and 3/2 asks for 408px of height — 45.3vh. The 34vh
     ceiling (the clamp above) gives only 306 and pinned the frame at 2.0. 46vh
     gives 414 and gets out of the way: with the photograph at 408px the listen
     block ends at 769px of 900, above the fold — measured on the page, not
     estimated. On shorter windows the ceiling wins again, as at the top of the
     point page. */
  .kids-figure img {
    max-block-size: 46vh;
  }

  /* The paragraph that explains the album is the caption of the title above
     it, and the 28.8px margin it brought underneath goes with the ruler. It is
     a `.card`, and what comes next is one too — but prose and shortcut are not
     the same nature, and so the gap after it is the one for blocks and not the
     one for siblings. */
  .body-archive .album-intro {
    margin-block-start: var(--rhythm-tight);
    margin-block-end: 0;
  }

  /* `.card.album-intro` and not `.album-intro`: the pair of siblings above is
     `.band > .card + .card`, three classes, and would beat two. Tied, the one
     that comes later wins — and the one that comes later has to be this one,
     which is the one that knows the nature of the block changes there. */
  main.band > .card.album-intro + * {
    margin-block-start: var(--rhythm-block);
  }

  /* A margin of its own with more specificity than the ruler, written before
     the ruler existed. It becomes the same as the others. */
  .kids-story .point-listen {
    margin-block: var(--rhythm-block) 0;
  }

  /* ==========================================================================
     THE PILLS STOP SLIDING

     The director, 17 August 2026: "the map's filter row runs from edge to
     edge, stuck to the left border, cutting off the last pill, while the rest
     of the page has a margin" («a fila de filtros do mapa corre de extremidade
     a extremidade, colada ao bordo esquerdo, cortando a última pílula,
     enquanto o resto da página tem margem»).

     ON THE PHONE THE STRIP IS RIGHT and it is not touched: a row that slides
     should touch the edge, and the half-cut pill is the whole affordance — it
     is what says there is more and that the thing drags. The rule is the usual
     one: only patterns people already know, and on a finger this one is known.

     ON THE DESKTOP THERE IS NO FINGER. Measured at 1440px before anything was
     touched, on the two pages that have pills: the strip ran from 0 to 1440
     while the column runs from 72 to 1368, `.filters-list` was getting 414px of
     gutter on each side (the arithmetic that centres it on the reading measure,
     34rem, and not on the archive measure), the first pill started 322px inside
     the beginning of the column, and the last one fell at x=−4406 on the map
     and x=−1873 in the album — off the screen, with nothing that can be dragged
     with a mouse. Three misalignments with one cause: the strip was designed
     for a width the desktop does not have.

     THE CORRECTION IS TO STOP SCROLLING. They now wrap onto lines inside the
     same column as the rest of the page: nothing hidden behind a gesture the
     mouse does not have, and the start of the first pill on the same vertical
     as the title and the cards. It is what the desktop is in this product — the
     archive view, where what exists is all seen at once.

     RTL AND LTR COME OUT FOR FREE, and that is why there is not one line of
     direction here: `flex-wrap` fills from the start of reading, and
     `padding-inline` and `margin-inline` are agnostic. Confirmed in the six
     languages — the bleed was on the left in Hebrew and Arabic and on the right
     in the other four, and it goes in all six by the same rule.
     ========================================================================== */
  .filters {
    width: 100%;
    max-width: var(--measure-archive);
    margin-inline: auto;
    padding-inline: var(--gutter);
    overflow-x: visible;
  }

  .filters-list {
    flex-wrap: wrap;
    width: auto;
    min-width: 0;
    padding-inline: 0;
    row-gap: 0.5rem;
  }

  /* THE MAP'S ROW NO LONGER EXISTS, and so there is no rule for it here.

     There was, and it was an expensive patch: at 1440×900 the map's 36 pills
     wrapped onto three lines and the map canvas fell from 706 to 472; at 1024px
     it was 352px of pills to 413px of map, which is more filter than map. The
     rule clipped them to three lines with vertical scrolling. The director, on
     17 August 2026, solved it from underneath: "please remove the filters from
     the MAP section, I cannot bear living with these filters any longer" («por
     favor remova os filtros da secção MAPA, não aguento mais conviver com estes
     filtros»). What was left here went with them. The album, with 26 pills on
     three lines and 176px, stays — its page scrolls, and the effect of each
     pill is seen right away. */

  /* ---- ONE ROW ONLY ----

     Until 16 August 2026 the navigation went up into a bar of its own, fixed
     at the top, and the header (brand, share, language) sat below it — two
     rows sharing out the height the desktop exists to give to the archive
     view. The director sent the screen: "two lines, there should be only one,
     with the logo on the right side and the language selector on the left
     side" («duas linhas, deve haver uma só, com a logo ao lado direito e o
     seletor de idiomas do lado esquerdo»).

     The correction is not only CSS: `navegacao()`, in scripts/gerar-site.mjs,
     is now called INSIDE `<header>`, between the brand and the language corner
     — on the twelve pages that carry it — and no longer as a separate bar at
     the end of the body. It is that DOM change that makes the single row
     possible without a positioning trick: the three blocks (brand, navigation,
     corner) are now siblings inside the same `display: flex`, and each takes
     what fits it.

     ON THE PHONE NOTHING CHANGES: `.nav` is still `position: fixed` whenever
     the stylesheet is below this breakpoint (see the base rule, and the
     768–1023px dock further up) — a fixed position leaves the parent's flow
     wherever it is, and none of the rules below has any effect below 64rem.

     THE ORDER IS THE DIRECTOR'S, in logical properties: the brand goes at the
     START of reading (right in Hebrew and Arabic, left in the other four
     languages), the language corner at the END, and the navigation — which
     grows to fill what is left over — sits between the two. No direction rule
     is written here: `flex` already reads `dir` by itself.

     THE HEADER'S WIDTH IS NOT THE READING WIDTH. `.bar` and `.top` also carry
     `.band`, which pins the point page to the usual 34rem (the reading measure
     does not change — it is the first of this block's three decisions) — but
     the six navigation destinations do not fit in a column meant for prose.
     The header asks for the wide measure on EVERY page, whether or not it has
     `.body-archive`: without this, the point page, the "about", the quiz, the
     memory game and the supporters page were left with the row squeezed into
     34rem while the rest of the desktop already uses 72rem — measured at
     1024px, where the six Hebrew labels collided with one another. */
  .bar,
  .top {
    max-width: var(--measure-archive);
  }

  /* ---- ONE HEIGHT, ONE DESIGN, AND IT STAYS AT THE TOP ----

     17 August 2026. The director: "every page I go into, the site jumps, the
     header behaves differently in the design on each page" («cada página que
     entro o site dá um pulo, header se comporta diferente no design em cada
     página»). With the twelve pages measured at 1440px before anything was
     touched, the header row was three different pieces with three behaviours:

       · `.bar`          — the point page, אודות, בולים, ילדים, story, חידון,
                           זיכרון, map. 68px, with a rule below. On the map
                           62px, because it is the only one with no back arrow
                           and it was the arrow that gave it its height.
       · `.top-brand`    — כל המקומות, חיפוש, תומכים. 68px, with NO rule, and
                           with 25.2px of `.top` above it pushing the whole page
                           down on those three only.
       · `.home-brand`   — the home page. The same, plus the logo aligned on
                           another axis.

     Now it is one measurement only, and it is declared: `--header`. The row
     measures it by `min-height` instead of adding it up out of padding plus
     whatever happens to be inside it — that is how the map's came out 6px
     shorter than the other eleven, and a height that depends on the content
     diverges again the day someone takes a button out. The rule below is the
     same on all twelve: a header stuck to the top needs to say where it ends,
     or the text passes under it with no boundary.

     AND IT STICKS. A header that goes up with the scroll forces you back to the
     top to change page, and on a long point page that is several screens. It
     does not eat reading height: it is 67.5px of 900, and what is gained is the
     whole navigation always to hand — which is the reason it moved up here on
     16 August. The map stays out of it by `position: static` in its own rule,
     and rightly so: the map page does not scroll.

     WHAT STICKS IS THE `<header>`, and not the row inside it. `position:
     sticky` sticks inside the PARENT's box, and while the parent was a
     `<header>` that also carried the title and the opening photograph, the row
     stuck for the parent's 500px and disappeared with it. Measured at 1440px
     with the page scrolled 900px: the home page went to −397, the list to −850,
     the stamps to −833. That is why this correction is not only a stylesheet
     one: the title and the search field left the `<header>` for inside the
     `<main>` in the generator, and the header became what its name says — the
     row and nothing else. */
  .bar,
  .top {
    position: sticky;
    inset-block-start: 0;
    z-index: 15;
    min-height: var(--header);
    padding-block: 0;
    background-color: var(--background);
    border-block-end: 1px solid var(--border);
  }

  /* `.top` is a block with a row inside it; `.bar` already IS the row. The
     25.2px of `padding-block-start` that only the four `.top` pages had go with
     the `padding-block: 0` above — the distance from the header to the first
     element becomes a measurement from the ruler and not a leftover of the
     header. */
  .top {
    display: flex;
    align-items: center;
  }

  /* The row fills the header's width and centres what it carries. With no
     `min-height` of its own: what rules the height is the parent's `--header`,
     and two declared heights disagree the day one of them changes. */
  .top-brand,
  .home-brand {
    flex: 1;
    min-width: 0;
    align-items: center;
    flex-wrap: nowrap;
    margin-block-end: 0;
  }

  .bar {
    align-items: center;
    flex-wrap: nowrap;
  }

  /* The map does not scroll, and so it does not stick — but the rule below is
     the same, and it is what separates the row from the strip of layers just
     under it. */
  .map-top .bar {
    border-block-end: 1px solid var(--border);
  }

  /* The home page's logo is tall (12em) and used to align to the top on its
     own; in a row with navigation beside it, what you want is the centre of the
     three, as on every other page. */
  .home-brand {
    align-items: center;
  }

  /* ---- THE HOME PAGE'S BRAND BECOMES EVERY PAGE'S BRAND ----

     16 August 2026. Yesterday's single row went into twelve pages, and the home
     page was left out of the result without being left out of the code: the
     `<nav>` moved in it as in the others, but its brand is another piece —
     `.brand-title img`, the large `min(12em, 62%)` logo — and it is what rules
     the height of the line. Measured at 1440px before anything was touched: the
     home page had the logo at 186px and the row 69.4px tall, while `אודות`, the
     search and the archive had 118.8px and 49.5px. One line, yes, but a line
     different from the other five — and that is what the director's screenshot
     shows.

     And it carries in the same movement the other thing he asked for: "the logo
     could be smaller, about 70% of its current size" («a logo poderia ser
     menor, uns 70% do tamanho atual»). The two corrections fall on the same
     number, and that is not a coincidence — 6.6rem is 118.8px, which is 64% of
     the 186px of before. Shrinking the home page's brand DOWN TO the other
     pages' brand is at the same time joining it to them and reducing it, and it
     leaves ONE logo measurement in the whole product instead of two.

     `rem` and not `em`: the `<h1>` that wraps it has `font-size: 2rem`, and so
     `6.6em` here would give 237px — twice what is wanted. The `.bar-brand`
     stylesheet uses `em` because there the context is the body text; here the
     context is a title, and the measure has to be the page's and not the
     title's.

     ON THE PHONE NONE OF THIS EXISTS: it is inside the 64rem breakpoint, and
     below it the home page still has the `min(12em, 62%)` logo, which at 375px
     gives the usual 135px. The HTML's `width`/`height` is not touched either —
     it is the measurement that is left when this stylesheet does not arrive,
     and it has already been needed once. */
  .home-brand .brand-title img {
    width: 6.6rem;
  }

  /* The map is the canvas that does not scroll (see `.map-with-map
     body.body-map` further up); its own rule already pins `position: static`
     with more specificity than this one, and so it does not need restating
     here — but the rest of the block (brand at the start, navigation in the
     middle, language at the end) applies to it all the same. */

  /* The two corners NEVER give up space — what gives is the navigation between
     them (see `.nav` below). Tested at 1024 and at 1280px in the six languages:
     `Печати`, `Поиск` and `Buscar` are the widest labels since the sixth
     destination went from `Supporters` to `About` (16 August 2026), and they
     are what dictate the navigation's `min-width: 0`, never the brand or the
     language. */
  .bar-back,
  .bar-home,
  .brand-title,
  .bar-corner {
    flex: none;
  }

  .nav {
    position: static;
    inset: auto;
    flex: 1 1 auto;
    min-width: 0;
    border: 0;
    padding-block-end: 0;
    background-color: transparent;
  }

  .nav-list {
    max-width: none;
    margin-inline: 0;
    padding-inline: 0;
    justify-content: center;
  }

  /* Six icons stretched across 1440px would sit a hand's breadth from each
     other; the row stays compact in the centre and each destination measures
     only what it needs. */
  .nav-list > li {
    flex: 0 1 auto;
    min-width: 0;
  }

  .nav-item {
    flex-direction: row;
    gap: 0.4rem;
    min-height: 2.75rem;
    padding-inline: 0.7rem;
    font-size: 0.82rem;
  }

  .nav-item[aria-current="page"]::before {
    inset-block: 0.3rem;
    inset-inline: 0;
  }

  /* From 80rem up there is too much width left over to stay compressed — the
     navigation row breathes at the same rhythm as the brand and the language.
     Measured: at 1024px six labels in English (the widest language, with
     `Supporters`) still fit with the compression above; at 1280px there is
     already room to spare for the usual values. */
  @media (min-width: 80rem) {
    .nav-item {
      gap: 0.5rem;
      padding-inline: 1rem;
      font-size: 0.86rem;
    }
  }

  /* The navigation is no longer a separate bar, and the body no longer needs
     to reserve space of its own for it — the header, stuck to the top, takes
     its own place in the document's normal flow. */
  body {
    padding-block-end: 2.5rem;
  }

  /* ---- THE MAP: map and list side by side ----
     The list by distance stops being what replaces the map and becomes what
     accompanies it — which is the map's archive view, and is what already
     served at the bottom on the phone. With no map (no script, no network, no
     WebGL) none of this applies: the page is still the whole list, as it always
     was. */
  .map-with-map .map-main {
    flex-direction: row;
    gap: var(--gutter);
  }

  .map-with-map .map-list {
    display: block;
    flex: 0 0 23rem;
    min-height: 0;
    overflow-y: auto;
    padding-block: 0.6rem 1.5rem;
  }

  .map-with-map .map-area {
    flex: 1;
    min-width: 0;
  }

  /* The sheet still opens over the map, and now it sits against the bottom:
     there is no bar down there any more to give it room. */
  .map-with-map .sheet {
    inset-block-end: 0;
  }

  /* ---- THE POINT PAGE ----
     The text column does NOT widen (see decision 1 at the top of the block).
     What changes is the gallery: a row that scrolls horizontally is a finger
     gesture, and with a mouse it hides photographs behind an interaction nobody
     expects. It now shows everything at once, in the same frame and at the same
     size — breathing instead of scrolling. */
  .gallery-row {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
    overflow-x: visible;
  }

  .gallery-row figure {
    flex: none;
  }

  /* The reading-measure rule does not stop applying inside an archive page:
     the paragraph that explains the album is prose, and prose at 72rem cannot
     be read. It keeps the usual measure, against the start of reading — which
     is where the title above it is, and the first column of the grid below. */
  .body-archive .album-intro {
    max-width: var(--measure);
    margin-inline-end: auto;
  }

  /* ---- The two top photographs of the home page are BANDS, not posters ----
     With the column at 34rem, `aspect-ratio: 21/9` gave 148px of height; at
     72rem it gives 494px, and the question «איפה אתה עכשיו?» with the three
     verbs below it went off the screen — the home page stopped being a question
     and became a poster. The height is now stated, and the crop is still
     `cover`: the photograph rules the canvas without taking the whole canvas. */
  .body-archive .home-band img {
    aspect-ratio: auto;
    height: 19rem;
  }

  /* The city's facade is the sister of the band above and measures like it: at
     1296px of column, 19rem gives a ratio of 3.79, and the real photograph
     (1.5) survives at 41% instead of the 21% the 15rem frame gave over an
     enlarged square. `aspect-ratio: auto` because here the height is stated, as
     in the band. */
  .body-archive .feature-city img {
    aspect-ratio: auto;
    max-block-size: none;
    height: 19rem;
  }

  /* ==========================================================================
     ילדים: THE CAROUSEL STOPS BEING A CAROUSEL

     The director, 17 August 2026: "the children's carousel does not work on
     the desktop. It was designed for the finger; with a mouse there is no way
     to move on" («o carrossel das crianças não funciona no desktop. Foi
     desenhado para o dedo; com rato não há como avançar»). He is right, and the
     measurement confirms it: the «מקומות» band has 15 cards and 5836px of width
     in a box of 1296 — three can be seen, and the other twelve have no way of
     being reached without a gesture the mouse does not make.

     IT BECOMES A GRID, AND IT DOES NOT GET ARROWS. Both answers were
     legitimate; this is the one this product already knows how to give, for
     four reasons and none of them is taste:

       1 · The carousel's affordance IS the peek — half a card on each side
           saying "drag me". It is a sentence spoken to a finger. On a mouse
           screen it is not insufficient: it is a promise in a language the
           device does not speak. Arrows would be a second grammar for the same
           row.
       2 · This product's desktop is defined, and not by me: "the archive view
           — search, map, long reading" («a vista de acervo — pesquisa, mapa,
           leitura longa», CLAUDE.md). Seeing what exists is what it is for. A
           grid shows all fifteen; a carousel with arrows shows three at a time,
           and more slowly.
       3 · Arrows are JavaScript and a new control on every band — seven rows,
           fourteen buttons, end-of-travel states. The grid is one declaration
           and degrades to a single column when there is no stylesheet at all.
       4 · It is the SAME design the rest of the desktop already uses.
           `auto-fill` with `minmax(20rem, 1fr)` is the grid of `.feed`, on the
           home page, in the list and in the search. It is not a new pattern: it
           is this one, applied where it was missing.

     ON THE PHONE IT STAYS EXACTLY AS IT IS. All of this lives inside the 64rem
     breakpoint, and below it the carousel is the usual one — the 78% of width,
     the peek on both sides and the `scroll-snap`, which on a finger is the
     right thing.

     `.quiz-row` uses the same class and does NOT come in here: `חידון` does not
     have `.body-archive` on its body, and it does not have it because it is a
     deck — one question at a time, turned by the script. A grid there would
     show all the answers.
     ========================================================================== */
  .body-archive .kids-carousel {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(20rem, 1fr));
    gap: 0.85rem;
    margin-inline: 0;
    padding-inline: 0;
    padding-block-end: 0;
    overflow-x: visible;
    scroll-snap-type: none;
  }
}

/* ---------------------------------------------------------------------------
   Arabic asks for leading, and only leading

   MEASURED at 375px on the long point pages, with this same stylesheet and the
   same type size. In a `.point-text p` the ink of a Hebrew line is 18.4px tall
   and leaves 13.8px of white down to the next line; the same sentence in Arabic
   has 26.1px of ink and leaves 6.0px. In the list of sources it leaves −1.4px,
   which is not tight: it is a collision — the descender of ج landing on the ا
   of the line below.

   The reason is in the script and not in the stylesheet. Arabic goes far below
   the baseline and far above the x-height; the same leading ratio buys half the
   optical space. Nothing else changes — the type size, the measure, the colour
   and the DIRECTION are Hebrew's, because Arabic is RTL like it and the
   mirroring was already done. Not a single direction rule was needed for
   Arabic, and that is what this block does not do.

   ONE NUMBER, added to the ratio that every running-text rule already declares.
   A second typographic scale would be the wrong correction and a larger one: it
   would change the size of the type, and the size is right — it is the height
   of the line that was not. 0.45 is the measured difference: it gives the
   Arabic paragraph back the same ~14px of white that Hebrew has.
   --------------------------------------------------------------------------- */
:root:lang(ar) {
  --air-gap: 0.45;
}

:root:lang(ar) body           { line-height: calc(1.5 + var(--air-gap)); }
:root:lang(ar) .point-text p { line-height: calc(1.75 + var(--air-gap)); }
:root:lang(ar) .point-line   { line-height: calc(1.5 + var(--air-gap)); }
:root:lang(ar) .card-line  { line-height: calc(1.45 + var(--air-gap)); }
:root:lang(ar) .album-intro { line-height: calc(1.62 + var(--air-gap)); }
:root:lang(ar) .verse-gloss   { line-height: calc(1.7 + var(--air-gap)); }

:root:lang(ar) .kids-text    { line-height: calc(1.68 + var(--air-gap)); }
:root:lang(ar) .about-block p { line-height: calc(1.75 + var(--air-gap)); }

:root:lang(ar) .kids-remember-text { line-height: calc(1.45 + var(--air-gap)); }
