/* Production only. The prototype is unchanged; these are the rules the real site needs
 * and the mockup has no equivalent for.
 *
 * NOTHING here may restate a value prototype.css already sets. If a size, a colour or a
 * spacing is wanted, it comes from there — re-authoring a value is how a design gets
 * quietly replaced by an approximation of itself (CLAUDE.md §13).
 *
 * The canvas-to-img rules are NOT here either: they are generated into canvas-img.css
 * from his own declarations, so the two cannot drift.
 */

/* The footer links sit where the counter was, in the label area rather than in a fixed
   bar over the darkest part of the wall, where they could not be read. */
.labelbar .footlinks { justify-content: flex-start; }

/* The menu, the brand and the leads are anchors, not buttons (01/09/26). Only the two
   properties a browser adds to an anchor and not to a button are restated — everything
   else is inherited from the prototype's own rules. */
a.navlink, a.brand, a.ghost, a.wk-rel { text-decoration: none; }
a.navlink { color: var(--ink-soft); }
a.navlink:hover { color: var(--ink); }
a.brand { color: inherit; }
a.ghost { display: inline-block; color: var(--ink-soft); }
a.ghost.lead { color: var(--gold); }
a.wk-rel { display: block; color: inherit; }

/* The photograph is a link now, so it must say so. Jacki, 01/09/26: the cursor was an
   arrow over the photograph and a drag-hand beside it — exactly backwards, because the
   photograph is the thing you can click and the wall beside it is the thing you drag.
   `.item.active { cursor: default }` was right when the active work was a <button> that
   did nothing; it is a link to /photo/<sku> now. */
a.item, a.item.active { cursor: pointer; }

/* The plates are anchors now — the phone's front door, the collections page, the search
   results and the photographer's page all use them. Only what a browser adds to an
   anchor and not to a div is restated. */
a.plate { text-decoration: none; color: inherit; }

/* The first photograph, before any JavaScript has run.
 *
 * `.item` is `position: absolute` with no offsets until layout() sets them, so the
 * server-rendered photograph appeared at its static position — the top-right corner —
 * and then jumped to the middle when the script caught up (Jacki, 01/09/26: "התמונה
 * מופיעה לשנייה בצד העליון הימני").
 *
 * This puts it where the layout is going to put it anyway: centred, inside the stage,
 * at its own proportions. buildWall removes the class before positioning anything, so
 * these values never fight the real layout — they only cover the gap before it exists.
 */
.item.preview {
  /* **The photograph before any script runs, and it must never be distorted.**
     This box used to fix the anchor's HEIGHT and give the image `height: 100%` with
     `max-width` on top. The moment the max-width bit, the width shrank while the height
     stayed pinned — so the photograph arrived stretched tall and snapped back when the
     layout sized it properly (Jacki, 02/09/26: "מרוחה לגובה ואז מתכווצת").

     Nothing is pinned now. The image is bounded on both sides and keeps its own
     proportions; the anchor shrink-wraps it, and `margin: auto` inside the inset box
     centres it where the layout is about to put it. The bounds are in viewport units on
     purpose: a percentage here would resolve against a box that is itself sized by its
     contents, which is a loop no browser can settle. */
  position: absolute;
  inset: 0 0 48px 0;
  margin: auto;
  width: fit-content;
  height: fit-content;
  transform: none;
  opacity: 1;
  filter: none;
}
.item.preview img {
  display: block;
  width: auto;
  height: auto;
  max-width: 86vw;
  max-height: 60dvh;
}

/* The footer entries are links now, so they need the same two properties the others
   needed. The prototype styles `.footlinks button` and `.sitefoot button`; those
   declarations are its own and are not restated here — only the underline and the colour
   a browser adds to an anchor and does not add to a button.
   Without this they rendered underlined and in the browser's link blue, which is not a
   colour that appears anywhere in this design. */
.footlinks a, .sitefoot nav a {
  font: inherit;
  color: inherit;
  text-decoration: none;
  border-bottom: 1px solid transparent;
}
.footlinks a:hover { color: var(--ink-soft); border-bottom-color: var(--line); }
.sitefoot nav a { color: var(--ink-soft); }
.sitefoot nav a:hover { color: var(--ink); border-bottom-color: var(--ink-faint); }

/* No drag on the wall (01/09/26), so no cursor promising one. The arrows do the moving.
   The prototype sets `cursor: grab` on the stage and `grabbing` while dragging; both are
   overridden here rather than edited there, so his file stays his file. */
.stage, .stage.dragging { cursor: default; }

/* ---------------------------------------------------------- the dark wall glows
 *
 * Jacki, 01/09/26: on black, light should come from BEHIND the photograph instead of the
 * shadow the light walls need.
 *
 * A drop shadow is a lie on a dark wall — there is nothing for it to fall on, and it
 * only muddies the edge. This is the print lit from behind: a tight rim, then two soft
 * halos spreading into the black. The wall's own wash (.stage::before) stays as it is.
 *
 * `--glow` is his token; the alpha steps are the only new values, and they exist because
 * a single shadow cannot fall off at two different rates.
 */
/* **The work page's photograph is lit the same way** — Jacki, 03/09/26, and he is right
   that this was settled: it is the same photograph on the same dark wall, and it had a
   flat border here while the wall behind it glowed. The variable is set by the same
   `glowColour`, so this photograph's own colour lights this page too. */
html[data-wall="dark"] .wk-hero { --art-glow: 255, 246, 228; }

/* `canvas-img.css` repeats every `canvas` rule for `img`, so `.wk-hero img` already has
   `box-shadow: var(--shadow)` from the prototype. That is one class deeper than a bare
   attribute selector, so the wall's own three layers lost.

   **And `data-wall` is on `<html>`, not on `.app`** — measured, after a first attempt
   that scoped this to `.app[data-wall]` and matched nothing at all while looking
   perfectly reasonable. `html[...]` is both true and specific enough, without
   `!important`, which hides the next conflict instead of resolving it. */
[data-wall="dark"] .item img,
[data-wall="dark"] .item canvas {
  box-shadow:
    0 0 0 1px rgba(255, 255, 255, .07),
    0 0 70px rgba(255, 246, 228, .14),
    0 0 180px 35px rgba(255, 246, 228, .09),
    0 0 340px 100px rgba(255, 246, 228, .05);
}

/* The arrows are back on the centre line (Jacki, 01/09/26). They were moved to the top
   corners when the photograph was enlarged; the photograph went back to its own size, and
   they go back with it. Nothing overrides them here now — `.nav` in prototype.css puts
   them at `top: 50%`, which is where they belong. */

/* ------------------------------------------------- focus the light (Jacki, 01/09/26)
 *
 * The first pass lit the whole wall: a wide wash across the stage and halos spreading
 * 340px into the black. That is ambient light, and ambient light is what a gallery
 * spends money to avoid — it lifts the whole room and flattens the print.
 *
 * A gallery light is narrow and aimed. So the wash tightens onto the photograph, and the
 * halo now falls off fast: most of the light sits within about 30px of the edge, a
 * shoulder carries it to 90px, and it is gone by 180px instead of 340. Same token, same
 * colour — the light is concentrated rather than brightened, so the black stays black.
 */
[data-wall="dark"] .stage::before {
  background: radial-gradient(ellipse 38% 42% at 50% 46%, var(--glow), transparent 68%);
}

[data-wall="dark"] .item img,
[data-wall="dark"] .item canvas {
  box-shadow:
    0 0 0 1px rgba(255, 255, 255, .10),
    0 0 26px rgba(255, 246, 228, .24),
    0 0 90px 6px rgba(255, 246, 228, .11),
    0 0 180px 24px rgba(255, 246, 228, .04);
}

/* ------------------------------------------- the backlight (Jacki, 01/09/26, improved)
 *
 * "לשפר את התאורה האחורית". Two things were wrong with the cream halo.
 *
 * It was the SAME light behind every photograph, which is a lamp on a wall, not a light
 * behind a print. `--art-glow` is set from the photograph itself as each one comes up —
 * its own average colour, lifted to the brightness of a light — so a desert glows warm
 * and a sea glows cold, and moving along the wall changes the colour of the room.
 *
 * And it fell off evenly, which reads as fog. A backlight has a bright, tight edge where
 * it escapes around the print, then a long soft spill. So: a hairline rim, a hot band
 * within 18px, and one wide low spill. Nothing between them.
 *
 * `--art-glow` carries "r, g, b" so the alpha can differ per layer.
 */
[data-wall="dark"] .stage { --art-glow: 255, 246, 228; }

html[data-wall="dark"] .wk-hero img,
html[data-wall="dark"] .wk-hero canvas,
[data-wall="dark"] .item img,
[data-wall="dark"] .item canvas {
  box-shadow:
    0 0 0 1px rgba(var(--art-glow), .16),
    0 0 18px -2px rgba(var(--art-glow), .40),
    0 0 120px 12px rgba(var(--art-glow), .10);
  transition: box-shadow .8s ease;
}

/* The wall wash takes the same colour, so the light in the room and the light behind the
   print are one light rather than two. */
[data-wall="dark"] .stage::before {
  background: radial-gradient(ellipse 40% 44% at 50% 46%,
              rgba(var(--art-glow), .07), transparent 70%);
}

/* ------------------------------------------ the phone's front door is the wall too
 *
 * Jacki, 01/09/26: *"באיפון להציג את תמונת הוואו ולא להראות את היתר אלא רק אם יעברו
 * באמצעות החצים"*.
 *
 * The prototype gave a phone a scrolling grid of every work instead of the wall, because
 * a wall needs room for arrows either side. That was the right call for a mockup with no
 * decision behind it; the decision now is that the landing is ONE photograph, on every
 * device, and the rest are reached by moving.
 *
 * Everything the wall needs on a phone already exists in his stylesheet — the close-up
 * sizing at `max-width: 720px` and the 38px arrows. Only the switch is reversed.
 */
@media (max-width: 899px) {
  .app[data-view="gallery"] .stage { display: block; }
  .app[data-view="gallery"] #pageHome { display: none; }
}

/* On a phone the arrows lie ON the photograph, because the photograph is now 94% of the
 * width and there is no margin left to stand in.
 *
 * They cannot simply go: they are the only thing that says there are more photographs at
 * all — a swipe is invisible until you know to try it. So they stay where they are and
 * step back instead: smaller, and quiet enough to read as an affordance rather than a
 * grey button parked on the work. Touching one brings it fully back.
 *
 * Scoped away from `data-mode="wall"`, which hides them outright in his own stylesheet.
 */
@media (max-width: 899px) {
  .app:not([data-mode="wall"]) .nav {
    /* 34 to 40 — "a little bigger" (Jacki, 02/09/26). It is also nearer a finger's
       target: 34px is under every guideline for something you are meant to hit. */
    /* 40 to 46, and the arrow itself 19 to 26 — "תגדיל את החצים" (Jacki, 05/10/26),
       after a blue ground was tried for an hour and he asked for the white back. */
    width: 46px;
    height: 46px;
    font-size: 26px;
    opacity: .45;
    transition: opacity .25s ease;
  }
  .app:not([data-mode="wall"]) .nav:active,
  .app:not([data-mode="wall"]) .nav:focus-visible { opacity: 1; }
}

/* ------------------------------------------- iPhone: the page was taller than the screen
 *
 * From Jacki's own phone, 01/09/26: the photograph sat low with half the screen empty
 * above it, and the action row — רכישה, הדמיית התמונה, לצפייה מקרוב, אהבתי — was not
 * visible at all.
 *
 * `.app` is `height: 100dvh` with `min-height: 100vh`. On iOS Safari those are two
 * DIFFERENT heights: `dvh` is the visible viewport, `vh` is the viewport as if the
 * browser's toolbars were not there. `min-height` wins, so the page was laid out taller
 * than the screen — the bottom went under the toolbar, and everything centred vertically
 * (the photograph included) was centred against a box the visitor could not see all of.
 *
 * Nothing about the design changes: the floor becomes the same height as the ceiling.
 * The 100vh line stays as the fallback for anything that has no dvh, which is why this
 * sits behind @supports rather than simply overriding it.
 */
@supports (height: 100dvh) {
  .app { min-height: 100dvh; }
}

/* ==========================================================================
   The phone's home page, laid out to Jacki's mockup (01/09/26)
   ========================================================================== */

@media (max-width: 899px) {

  /* -- 1 -- The action row belongs to the photograph, so it sits under it.
     It was pinned to the foot of the stage, which on a tall phone is a long way from
     the work it acts on. `--art-bottom` is written by layout(), which is the only thing
     that knows where the photograph ends. */
  .app[data-view="gallery"] .stage-actions {
    top: calc(var(--art-bottom, 60%) + 16px);
    bottom: auto;
    inset-inline: 12px;
    gap: 14px;
    font-size: 12.5px;
  }

  /* -- 2 -- The arrows sit at the top of the wall, just under the header's line.
     They were on top of the work — at 94% width there is no margin beside it to stand in
     — then above it, hanging in the space over the photograph. Jacki, 02/09/26: put them
     right under the divider and make them a little bigger.
     **Fixed to the top of the stage, not to the photograph.** A portrait and a panorama
     start at different heights, and an arrow that moves with the work is an arrow you
     have to look for. Under the line it is in the same place on every photograph. */
  /* **⚑ Reversed by him on 05/10/26:** *"להוריד את החצים שיהיו מעל התמונה ממש."* They stand
     directly over the photograph now — eight pixels above its top edge, one at each side —
     and so they do move with a taller or a wider picture, which is what he asked for.
     `--art-top` is written by `layout()`; never above ten pixels from the line. */
  .app:not([data-mode="wall"]) .nav {
    top: max(10px, calc(var(--art-top, 64px) - 54px));
    transform: none;
    opacity: .85;
  }

  /* -- 3, 4, 5 -- The header, in the order he drew it.
     `display: contents` lets the four tool buttons take their own places in the header's
     flex row instead of travelling as one block — so nothing in his markup has to change
     for the brand, the menu and the two controls to sit where he wants them. */
  .topbar { flex-wrap: wrap; align-items: center; }
  .tools { display: contents; }

  /* One row, read the way Hebrew is read (Jacki, 02/09/26): the hamburger at the RIGHT,
     where the eye starts, the logo centred, and search at the left.
     `order: 1` is the right-hand end in RTL — the writing direction does the placing, so
     nothing here needs to know which physical side that is. */
  .topbar { position: relative; justify-content: space-between; }
  .menubtn { order: 1; }
  #savedBtn { order: 3; }        /* האוסף שלכם stands in the header now */
  .rowbreak { display: none; }
  #modeBtn { display: none; }

  /* **Centred on the SCREEN, not between its neighbours.**
     `margin-inline: auto` shares out whatever space is left, so a 35px hamburger on one
     side and an 80px search button on the other pushed the logo 23px off centre. Taking
     it out of the row and pinning it to the middle is the only way it is actually in the
     middle — and it stays there whatever those two become. */
  .brand {
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
    margin: 0;
  }

  /* The footer links are in the menu now, and only there — so the bar that used to
     hold them stays hidden, as the prototype intends on a phone. */
  .menupanel .footlinks {
    flex-direction: column;
    align-items: flex-start;
    gap: 14px;
  }
}

/* -- turned on its side, the photograph takes the glass --
   "באיפון כשמסובבים אותו לצד התמונה תתפוס את כל המסך". Everything else steps out of the
   way; turning back brings it all straight in. Height rather than a device test, because
   what makes the chrome unaffordable is that there is no vertical room for it. */
@media (orientation: landscape) and (max-height: 520px) {
  /* **The header lifts off the page instead of disappearing.**
     It was `display: none`, which took the hamburger with it — so turning the phone left
     no way to the menu, the collections or anything else (Jacki, 02/09/26). Now it floats
     over the top of the photograph with only the button in it, out of the grid so the
     stage still gets the whole height. */
  .app[data-view="gallery"] .topbar {
    position: absolute;
    top: 0;
    inset-inline: 0;
    z-index: 30;
    background: none;
    border: 0;
    padding: 8px 10px;
    min-height: 0;
  }
  .app[data-view="gallery"] .topbar .brand,
  .app[data-view="gallery"] .topbar #askBtn { display: none; }
  .app[data-view="gallery"] .menubtn { opacity: .5; }
  .app[data-view="gallery"] .menubtn:active,
  .app[data-view="gallery"] .menubtn[aria-expanded="true"] { opacity: 1; }

  .app[data-view="gallery"] .labelbar,
  .app[data-view="gallery"] .stage-actions { display: none; }

  /* **The menu is short when the phone is on its side.**
     Jacki, 02/09/26: opened in landscape it ran the height of the glass and covered the
     photograph. There is a third of the vertical room here, and a menu that hides the
     work is worse than no menu — so this state keeps the four things somebody reaches for
     while looking at a photograph, and nothing else: נגישות · מדיניות החזרות ·
     תנאי שימוש · יצירת קשר.
     The rest is not removed, only not shown here: turning the phone back brings it all
     straight in, because it is the same elements either way. */
  .app[data-view="gallery"] .menupanel > *:not(#footLinks):not(.topnav) { display: none; }
  .app[data-view="gallery"] .menupanel .topnav .navlink:not([data-view="contact"]) {
    display: none;
  }
  .app[data-view="gallery"] .menupanel {
    padding: 12px 14px 14px;
    gap: 12px;
  }
  .app[data-view="gallery"] .menupanel .footlinks { border-top: 0; padding-top: 0; }

  /* **And the middle has to be told it is still the middle.**
     `.app` is `grid-template-rows: auto 1fr auto` and its three children fill those rows
     in order. Hiding the first and the last does not leave the second where it was — it
     leaves `.main` as the ONLY child, so it lands in row one, which is `auto`, which
     measures its contents. Its contents are absolutely positioned, so it measured zero
     and the photograph rendered 235px wide on a black screen. Placing it explicitly is
     the whole fix. */
  /* The header is out of the flow now, so the stage takes every row it can. */
  .app[data-view="gallery"] .main { grid-row: 1 / -1; }

  /* The arrows come back, at the two edges, properly visible. A 3:2 photograph on a
     2.17:1 screen leaves about 160px of wall at each side — they stand in that, never
     on the work. */
  .app[data-view="gallery"] .nav {
    top: 50%;
    transform: translateY(-50%);
    opacity: .85;
    width: 36px;
    height: 36px;
  }
  /* Hung off the PHOTOGRAPH's edges, not the screen's, so they follow a panorama
     inward and a portrait outward instead of floating in the corners. `--art-side` is
     the wall at each side, written by the layout. */
  .app[data-view="gallery"] .nav.prev { right: calc(var(--art-side, 10px) - 44px); }
  .app[data-view="gallery"] .nav.next { left: calc(var(--art-side, 10px) - 44px); }

  /* And the actions stand up.
     Lying across the foot they had nowhere to go once the photograph took the height —
     so they turn on their side and use the wall beside it, which is empty. Jacki:
     "אולי לשים אותם בצד". They sit inboard of the arrow, so neither is in the other's way. */
  .app[data-view="gallery"] .stage-actions {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    justify-content: center;
    gap: 15px;
    top: 0;
    bottom: 0;
    height: auto;
    inset-inline: auto;
    right: 34px;
    left: auto;
    width: auto;
    font-size: 12px;
    opacity: .92;
  }
  .app[data-view="gallery"] .stage-actions .ghost { border-bottom-color: transparent; }
}

/* -------------------------------------------- "turn the phone" — Jacki's half-circle
 *
 * A half-circle rising from the foot of the stage, under the photograph, with the phone
 * and its turning arrow. Shown only on works that actually gain by it (the arithmetic is
 * in prototype.js), and never on a desktop or in landscape.
 *
 * It sits in the wall, not on the photograph: this is an aside, and the work is the page.
 */
.rotatehint {
  position: absolute;
  bottom: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 214px;
  height: 112px;
  border-radius: 112px 112px 0 0;
  border: 1px solid var(--line);
  border-bottom: 0;
  background: color-mix(in srgb, var(--wall) 82%, transparent);
  backdrop-filter: blur(6px);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 5px;
  padding-top: 10px;
  color: var(--ink-soft);
  font-size: 13px;
  letter-spacing: .02em;
  /* It is a button now, not a note: it opens the request. */
  pointer-events: auto;
  cursor: pointer;
  font-family: inherit;
  z-index: 4;
  animation: rotatehint-in .5s ease both;
  transition: color .2s, border-color .2s;
}
.rotatehint:hover { color: var(--ink); border-color: var(--ink-faint); }
.rotatehint:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; }
.rotatehint svg { width: 30px; height: 30px; opacity: .9; }
/* Jacki's photograph, chosen over line art on 02/09/26 after seeing both at real size on
   the real page. It needs more height than a glyph to read as a hand holding a phone, so
   the half-circle grows to hold it. */
.rotatehint img { height: 46px; width: auto; opacity: .95; display: block; }
.rotatehint[hidden] { display: none; }
/* On the whole hang the offer covered part of the last photograph in the bottom row
 * (05/10/26). It is about ONE photograph, so it stands only when one is in front. */
.app[data-mode="wall"] .rotatehint { display: none; }

@keyframes rotatehint-in {
  from { opacity: 0; transform: translate(-50%, 10px); }
  to   { opacity: 1; transform: translate(-50%, 0); }
}
@media (prefers-reduced-motion: reduce) { .rotatehint { animation: none; } }

/* **On a desktop too, now that it carries the offer** (Jacki, 02/09/26).
   It was hidden here because a desktop cannot be turned. What it holds is no longer
   about turning anything — it is הקיר שלי, the simulation Jacki composes by hand — and
   that is worth as much to somebody at a desk as to somebody on a phone. The desktop
   even has the room for it: the wall is never narrower than 350px each side, measured.
   It still goes when the phone is on its side, where the photograph takes the glass. */
/* **On a desktop it stands in the wall beside the photograph, not under it.**
   Centred at the foot it landed straight on top of the action icons, which are centred
   there too (02/09/26). The wall at each side is never narrower than 350px — measured —
   so the corner is free, and the half-circle keeps its shape by rising from the same
   bottom edge. */
@media (min-width: 900px) {
  .rotatehint {
    left: auto;
    inset-inline-start: 44px;
    transform: none;
  }
  .rotatehint { animation-name: offer-in; }
}

@media (orientation: landscape) and (max-width: 899px) {
  .rotatehint { display: none !important; }
}

/* ------------------------------------------------------------------ the phone's menu
 *
 * Jacki, 02/09/26. The header was thirteen controls in two rows, 98px of a 844px screen,
 * above a photograph meant to stop someone.
 *
 * The button is only ever on a phone; the panel holds the REAL controls, moved there by
 * the script, so there is one menu and not two that drift apart.
 */
.topbar { position: relative; }

.menubtn {
  font: inherit;
  background: none;
  border: 1px solid var(--line);
  border-radius: 2px;
  color: var(--ink-soft);
  padding: 5px 7px;
  cursor: pointer;
  display: none;
  align-items: center;
  transition: color .2s, border-color .2s;
}
.menubtn svg { width: 19px; height: 19px; display: block; }
/* Open or closed, it is the same button in the same place — so the thing that opened the
   menu is the thing that closes it, and nothing moves under the finger. */
.menubtn .ico-close { display: none; }
.menubtn[aria-expanded="true"] .ico-open { display: none; }
.menubtn[aria-expanded="true"] .ico-close { display: block; }
.menubtn:hover { color: var(--ink); border-color: var(--ink-faint); }
.menubtn[aria-expanded="true"] { color: var(--ink); border-color: var(--ink-faint); }
.menubtn:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; }

.menupanel {
  position: absolute;
  z-index: 40;
  /* Below the header it belongs to — never over it. The button that opens this must stay
     visible and become the X that closes it. */
  top: 100%;
  inset-inline: 0;

  /* **It needs to look like a panel, or it looks like the page.**
     Jacki, 02/09/26: "why does the menu cover the whole screen?" It does not — it is 46%
     of it. But its background was the wall colour at 94%, which on a dark wall is the
     wall, so there was no edge anywhere and it read as the whole screen being menu.
     A step away from the wall and a real line under it is the whole fix. */
  background: color-mix(in srgb, var(--wall-2) 88%, var(--ink) 7%);
  border-bottom: 1px solid var(--ink-faint);
  backdrop-filter: blur(10px);

  /* **Sized against the screen a phone actually has, not the one the spec says.**
     An iPhone is 844 tall; Safari's own bars take about a fifth of it, so the page gets
     roughly 660. At a 14px rhythm the panel was 360 of that — fifty-five per cent, not
     the forty-three I had measured at the full height (Jacki's screenshot, 02/09/26).
     A tighter rhythm keeps every entry a comfortable tap and gives the photograph back
     the room. It is capped as well, so it can never take more than two thirds of the
     glass whatever ends up in it — it scrolls instead of swallowing the page. */
  padding: 14px 16px 16px;
  display: flex;
  flex-direction: column;
  gap: 14px;
  max-height: min(66dvh, 66vh);
  overflow-y: auto;
  overscroll-behavior: contain;
  box-shadow: var(--shadow);
}

/* Each entry keeps a full tap target while the list itself gets shorter. */
.menupanel .navlink,
.menupanel .footlinks a,
.menupanel #askBtn,
.menupanel #savedBtn,
.menupanel #langBtn { padding-block: 2px; }

/* **The small print is three lines of one thing; it costs three rows and reads as one.**
   Laid across, it is a single row and the menu is a row shorter for it — and the grouping
   he asked for is clearer, not weaker: four places to go, then the small print, then the
   two settings. */
.menupanel .footlinks {
  flex-direction: row;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 6px 16px;
}
.menupanel[hidden] { display: none; }
.menupanel .topnav {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 14px;
  overflow: visible;
}
/* ------------------------------------------------------------- the menu, designed
 *
 * Jacki, 02/09/26: still bad. Looked at properly, four things were wrong at once, and
 * they came from nudging the header's own styling into a shape it was never drawn for.
 *
 *   THREE GREYS. The current page white, the other links mid-grey, the small print
 *   darker still — three tiers of importance in a list where everything is the same kind
 *   of thing. One colour now; the current page is marked by its underline, which is how
 *   the header already marks it.
 *
 *   NO GROUPS. It read as a jumble because nothing said where one group ended. Hairlines
 *   do that, and they cost four pixels each — colour was doing it badly and expensively.
 *
 *   THE SWATCHES SHOUTED. Four white blocks in the middle of a column of words, larger
 *   than the words. They are a setting, so they sit on the settings row with English, at
 *   the size of a setting.
 *
 *   UNEVEN RHYTHM. 14px between links, 37px before the small print, something else around
 *   the swatches. One rhythm throughout.
 */

/* **Full contrast, and bigger.** `CLAUDE.md` §8: high contrast, crisp text — he is 60+
   and colorblind. The menu was `--ink-soft` on a dark panel, which is the colour the
   design uses for things standing BESIDE the thing you are reading. A menu is the thing
   you are reading. Faint grey text at 15px is the whole reason it kept coming back as
   "still bad", and it is a rule of his I should not have had to be told twice about. */
.menupanel .navlink,
.menupanel .footlinks a,
.menupanel #askBtn,
.menupanel #savedBtn,
.menupanel #langBtn {
  font-size: 17px;
  line-height: 1.4;
  padding: 0;
  color: var(--ink);
  border: 0;
  background: none;
}

/* The small print is smaller, and still readable — not faint. */
.menupanel .footlinks a { font-size: 15px; }

/* The page you are on, marked the way the header marks it — not by being a third colour. */
.menupanel .navlink[aria-current="true"] {
  color: var(--ink);
  border-bottom-color: var(--ink);
}

.menupanel #savedBtn:hover,
.menupanel #langBtn:hover,
.menupanel .navlink:hover,
.menupanel .footlinks a:hover { color: var(--ink); }

/* Four groups, in his order, separated by a line rather than by a shade.

       האוסף שלכם
       ─────────
       הגלריה · אוספים · יצירת קשר · אודות
       ─────────
       נגישות · מדיניות החזרות · תנאי שימוש
       ─────────
       the wall colours          English                                            */
/* חיפוש חכם leads the menu — the fastest way in for somebody who already knows what he
   is looking for. **Without its rectangle**, like every other line here: in a list of
   plain lines a bordered button shouts at the rest. It opens the same dialog. */
.menupanel #askBtn    { order: 1; }
.menupanel .topnav    { order: 2; }
.menupanel #footLinks { order: 3; }
.menupanel .settings  { order: 4; }

/* The lines were `--line`, which is a hair away from the panel and invisible on a phone.
   A divider nobody can see is not a divider. */
.menupanel .topnav,
.menupanel #footLinks,
.menupanel .settings {
  border-top: 1px solid var(--ink-faint);
  padding-top: 14px;
}

.menupanel .topnav {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 14px;
  overflow: visible;
}

/* The small print is one thing, so it is one row. */
.menupanel .footlinks {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: flex-start;
  gap: 6px 18px;
}

/* The settings live together: the wall on one side, the language on the other. */
/* Together, not at opposite ends of the screen: two settings pushed to the two edges
   read as two unrelated things with a hole between them. */
.menupanel .settings {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 20px;
}
.menupanel .settings .swatches { gap: 7px; }
.menupanel .settings .sw { width: 16px; height: 16px; }
/* Everything in the panel starts at the same edge.
   `#savedBtn` carries `margin-inline-start: auto` in the prototype's phone rules, which
   is right in a header — it pushes the tools to the far end of the row. Inside a column
   it pushed the button 251px across, so האוסף שלכם sat alone on the left while the menu,
   the swatches and English were all on the right (Jacki, 02/09/26). The auto margin was
   written for a row and this is not one. */
.menupanel #savedBtn,
.menupanel #langBtn {
  align-self: flex-start;
  margin-inline: 0;
}

@media (max-width: 899px) {
  .menubtn { display: inline-flex; }
  .topbar { flex-wrap: nowrap; }

  /* **The header must be sane before the script moves anything.**
     `syncChrome()` moves the menu, the swatches, האוסף שלכם and English into the panel —
     but until it runs they are all still in the header, and with the logo pinned to the
     centre they land on top of each other. A page with JavaScript off showed the logo,
     English and the wall colours in one pile.
     The child combinator does the work: while a thing is a DIRECT child of the header it
     is not shown, and the moment the script moves it into the panel it no longer is. No
     class to add, nothing to remember to take off. */
  /* **`.tools`, not `.topbar >`.**
     `#askBtn`, `#savedBtn` and `#langBtn` sit inside `<div class="tools">`, which is what
     is a child of the header — `display: contents` on it is why they LOOK like children
     of the row. Every `.topbar > #id` rule written here matched nothing at all, silently
     (02/09/26). The panel is inside the header too, so a plain descendant selector would
     reach into it: `.tools >` is the one thing that means "in the header, not the menu". */
  .topbar > .topnav,
  .topbar > #swatches,
  .tools > #askBtn,
  .tools > #langBtn { display: none; }

  /* האוסף שלכם stands in the header: the count is the point, so it is read at a glance
     rather than found in a menu. */
  .tools > #savedBtn { display: inline-flex; align-items: center; gap: 5px; }
  .tools > #savedBtn .sv-word { display: none; }
  .tools > #savedBtn svg { width: 18px; height: 18px; }
}

/* ------------------------------------------------------------------- Jacki's logo
 *
 * Supplied 02/09/26 as black lettering on a solid white ground, which on his dark wall
 * would be a white brick. The ground is transparent now, and there are two copies: the
 * original for the three light walls, and one with the lettering lifted to the wall's own
 * ink for the dark one. The camera keeps its yellow in both — a CSS `invert` would have
 * turned it blue.
 *
 * Sized by height so it sits on the same line the word did, and the width follows the
 * artwork's own 5.88:1.
 */
.brand img { display: block; height: 19px; width: auto; }
.brand .logo-dark { display: none; }

[data-wall="dark"] .brand .logo-light { display: none; }
[data-wall="dark"] .brand .logo-dark { display: block; }

@media (max-width: 899px) { .brand img { height: 17px; } }

/* --------------------------------------------------- the wall's actions, icons alone
 *
 * Jacki, 02/09/26. The home page carries icons with no words; a page showing more than
 * one work carries icons plus the work's name; the work's own page carries everything.
 * The word lives in `aria-label` and `title`, so it is read aloud and shown on hover.
 */
.actions .ghost.iconly {
  padding: 8px 10px;
  gap: 0;
}
.actions .ghost.iconly svg { width: 21px; height: 21px; }
.actions .ghost.iconly::after { content: none; }

/* The basket, in the main menu only while it holds something.

   **⚑ It stands out from the other five — Jacki, 18/09/26: *"זה חייב להיות מובלט יותר."***
   It read as a sixth grey menu word beside הגלריה, אוספים, יצירת קשר and אודות, and it is
   not one of them: it is the only thing in that row that holds the visitor's own money.

   **What it is now, in words rather than a colour he is asked to judge** (§1): a boxed
   pill in `--gold` — the site's one accent, the brown of שליחת הזמנה — with a `--gold`
   border, a 12% wash of the same colour behind it, and the count in a SOLID `--gold`
   circle. Three signs, not one: a box where the others have none, the accent where the
   others are grey, and a filled counter. Nothing new is invented — `--gold` is the token
   every theme already defines, dark included.

   **And it stays one step below the loud button.** §8 allows ONE solid accent button per
   screen, on the next step; the basket is an outline, so `לתשלום` is still the only filled
   thing on the checkout.

   The box also makes it a real target: 38px tall against the 17px of a bare word (A23). */
.cartlink {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 8px 14px; border: 1px solid var(--gold); border-radius: 999px;
  background: color-mix(in srgb, var(--gold) 12%, transparent);
  color: var(--gold);
}
.cartlink:hover { color: var(--gold); background: color-mix(in srgb, var(--gold) 20%, transparent); }
.cartlink[hidden] { display: none; }
.cartlink svg { width: 17px; height: 17px; flex: none; }
.menupanel .cartlink svg { width: 19px; height: 19px; }
/* The number in a filled circle: the one part that must read at a glance from across the
   header. `--wall` is the page's own background, so the digit is a hole in the disc and
   carries no second colour. */
.cartlink .cartword { display: inline-flex; align-items: center; gap: 8px; }
.cartlink .cartcount {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 20px; height: 20px; padding: 0 5px; border-radius: 999px;
  background: var(--gold); color: var(--wall); font-size: 12.5px; line-height: 1;
}
/* On a phone it sits in the menu panel, where the row is already generous. */
.menupanel .cartlink { padding: 10px 16px; }

/* **A page is shown by its own `data-view` rule, and the new page needed one — 19/09/26.**
   `prototype.css` carries thirteen of these, one per section, and it is his stylesheet
   byte for byte (`tests/test_adoption.py`), so a fourteenth belongs here. **This is not a
   new rule invented for this screen** — it is the same one every other page already has,
   spelled the same way.

   It was found the only way it could be: the DOM said `data-view="login"`, one `<h1>`, both
   fields and the button all PRESENT, and the screen was blank. Present is not visible. */
.app[data-view="login"] #pageLogin { display: block; }

/* **The line descriptions on ״תודה״ hug the RIGHT — Jacki, 19/09/26:** *"בתאורי העבודות
   יש להצמיד ימינה ולא שמאלה."* `prototype.css` gives every `dd` in `#thSum` `text-align:
   end`, which in an RTL document is the LEFT edge — so three descriptions of different
   lengths made a ragged right edge beside the titles they belong to. `start` puts each one
   against the title column, where the eye reads down them as a column.

   **The total keeps `end`.** It is a figure in the money column, not a description, and it
   is aligned with nothing else on the page. */
#thSum dd:not(.grand) { text-align: start; }

/* תנאי השימוש inside ״קראתי ואני מסכים״ (19/09/26). It takes the sentence's own colour and
   is marked only by the underline — a second colour in a line of 13.5px grey would shout,
   and the whole row is deliberately quiet. The offset keeps the rule off the Hebrew
   descenders. */
.co-terms a { color: inherit; text-decoration: underline; text-underline-offset: 3px; }
.co-terms a:hover { color: var(--ink); }

/* אספקה for the whole order, under the lines it governs (18/09/26). The separator is the
   same hairline `.co-line` uses, so the row reads as belonging to all of them rather than
   to the last one. */
.co-delivery {
  margin-top: 16px; padding-top: 14px;
  border-top: 1px solid var(--line-soft, rgba(0, 0, 0, .06));
}

/* The entry animation without the centring in it.

   `.rotatehint`'s own keyframes end on `translate(-50%, 0)`, and with `fill-mode: both`
   that final frame keeps applying after the animation finishes — outranking the rule that
   says `transform: none`. So the half-circle stayed centred however the insets were set,
   and the second one hung off the edge of the screen (02/09/26). Measured, not guessed:
   the computed transform was still `matrix(1,0,0,1,-93,0)`. */
@keyframes offer-in {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* The half-circle holds a photograph now, so it sits centred at the foot on a phone
   as it always did, and the comparison styling for the second candidate is gone. */
@media (max-width: 899px) {
  .rotatehint { animation-name: rotatehint-in; }
}

/* bookmark-plus, chosen by Jacki on 02/09/26 from twelve candidates.
   A plain bookmark says "this is marked", which is a reading metaphor and says nothing
   about being added to anything. The `+` says it, without inventing a new object.
   It disappears the moment the work is in the collection — see updateFav. */
/* heart-plus while it is out, a filled heart once it is in: the sign says what IS, not
   what was offered a moment ago. */
.fav.on .hp-plus { display: none; }

/* האוסף שלכם carries house-heart — the works somebody would hang at home. */
#savedBtn { display: inline-flex; align-items: center; gap: 7px; }
#savedBtn svg { width: 17px; height: 17px; flex: none; }
.menupanel #savedBtn svg { width: 19px; height: 19px; }

/* heart-minus on each work in the collection. It sits on the tile, quiet until the tile
   is touched, because removing is not what somebody came to this page to do. */
.saveditem { position: relative; }
.sv-remove {
  position: absolute;
  top: 6px;
  inset-inline-end: 6px;
  width: 30px;
  height: 30px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--line);
  border-radius: 50%;
  background: color-mix(in srgb, var(--wall) 78%, transparent);
  backdrop-filter: blur(4px);
  color: var(--ink-soft);
  cursor: pointer;
  opacity: 0;
  transition: opacity .2s, color .2s, border-color .2s;
}
.sv-remove svg { width: 16px; height: 16px; display: block; }
.saveditem:hover .sv-remove,
.sv-remove:focus-visible { opacity: 1; }
.sv-remove:hover { color: var(--ink); border-color: var(--ink-faint); }
/* A finger has no hover, so on a touch screen it is simply always there. */
@media (hover: none) { .sv-remove { opacity: 1; } }

/* ========================= the site's own tooltip =========================
 *
 * Jacki, 02/09/26: not the browser's grey box, and the same for every control a visitor
 * touches, anywhere on the site.
 *
 * **The convention is one attribute: `data-tip`.** Anything that carries it gets this —
 * a button, a link, an icon — and nothing else has to be written. The script removes
 * `title` from those elements, because leaving it shows the browser's box as well.
 *
 * It is drawn in the site's own palette at the site's own weight, so it belongs to the
 * page rather than to the operating system, and it never covers what it describes.
 */
.tip {
  position: fixed;
  z-index: 90;
  max-width: 260px;
  padding: 7px 11px;
  border: 1px solid var(--ink-faint);
  border-radius: 3px;
  background: color-mix(in srgb, var(--wall-2) 92%, var(--ink) 8%);
  color: var(--ink);
  font-size: 13px;
  line-height: 1.35;
  letter-spacing: .01em;
  box-shadow: var(--shadow);
  pointer-events: none;          /* it must never stand between a finger and a button */
  opacity: 0;
  transform: translateY(3px);
  transition: opacity .14s ease, transform .14s ease;
}
.tip.in { opacity: 1; transform: translateY(0); }
.tip[hidden] { display: none; }

/* the little point, so it is attached to something rather than floating */
.tip::after {
  content: "";
  position: absolute;
  left: 50%;
  margin-left: -5px;
  border: 5px solid transparent;
  border-top-color: var(--ink-faint);
  bottom: -10px;
}
.tip.below::after {
  bottom: auto;
  top: -10px;
  border-top-color: transparent;
  border-bottom-color: var(--ink-faint);
}

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

/* חיפוש חכם inside the menu: a line of text like the others, not a button in a box. */
.menupanel #askBtn {
  border: 0;
  padding: 0;
  background: none;
  align-self: flex-start;
  color: var(--ink);
}

/* האוסף שלכם: the words are dropped in the phone's header, never in the menu or on a
   desktop. The name survives in aria-label and in the tooltip. */
#savedBtn .sv-count { font-variant-numeric: tabular-nums; }



/* The offer's picture is a photograph in both places it appears (03/09/26): the wall's
   half-circle and the simulations column. It was a line drawing here and his photograph
   there — one offer, two pictures of it. */
img.wv-hand { height: 46px; width: auto; display: block; opacity: .95; }

/* The work page's three added actions (03/09/26).

   `prototype.css` sizes an icon per class — `.ghost.cart svg` at 16, `.ghost.fav svg` at
   15 — and there is no rule for a bare `.ghost` carrying one, because until now none did.
   So the three new buttons rendered their SVGs at intrinsic size, enormous.

   **16px, which is what `.ghost.cart` uses**, so the five sit at one weight rather than
   at four. Everything else about them is his stylesheet's. */
/* Icons with tooltips, exactly as on the wall — Jacki, 03/09/26. `.iconly` is the same
   class the home page uses, so applyLang writes the name into `data-tip` and `aria-label`
   rather than back into the button. */
.wk-titlerow .ghost.iconly svg { width: 19px; height: 19px; flex: none; }
.wk-titlerow .ghost.iconly { padding: 7px 9px; gap: 0; }

/* The bookmark fills here exactly as it does on the wall. */
.wk-titlerow .ghost.on { color: var(--gold); border-bottom-color: var(--gold); }

/* ==================================================== the work page, 03/09/26
 *
 * Jacki, going through it line by line. Every rule here is a sentence from
 * `design-principles.md` §3 that the page was not obeying.
 */

/* **Nothing on the page repeats itself** — §3 line 172: "the panels' own titles are
   hidden here (the h1 is directly above), and their cross-links to each other are gone."
   The simulations panel carried its own heading and a sub-line saying what the section
   above it had just said. */
.app[data-view="work"] #wkSimSlot #wvTitle,
.app[data-view="work"] #wkSimSlot .sub { display: none; }

/* And the block closes up against the line, now that three lines of heading have gone. */
.app[data-view="work"] .wk-block { margin-top: 18px; }
.app[data-view="work"] #wkSimSlot { margin-top: 0; }

/* **צעד אחורה means nothing here** — Jacki, 03/09/26. It shows the whole hang at once,
   the way you would see it standing in a gallery (§3, and the button's own hint), and
   there is no hang on a work's page. A control that does nothing where it is shown is
   worse than one that is missing. */
.app[data-view="work"] #modeBtn { display: none; }

/* The action row, to the wall's own measure (Jacki, 03/09/26).

   It was spread across the full width because `.wk-titlerow` is a space-between row and
   the buttons were its only content on that side. They sit together, at the wall's
   spacing, in the wall's order — buy, enlarge, share, save. הדמיות is not among them
   here, by §3 line 175.

   The gap under the hand tile is the fourth point he has now made twice: with the offer
   at a thumbnail's height the column ended short of the photograph beside it. */
.wk-titlerow .wk-acts { display: flex; align-items: center; gap: 4px; }

/* ------------------------------------------------- the two headings, one size
 *
 * Jacki, 03/09/26: both headings exactly like the title that was under the photograph.
 *
 * The prototype styles them BY ELEMENT — `.wk-head h1` and `.wk-promo h2` — so the moment
 * the promoted block took the h1 and the work's name became an h2, both rules stopped
 * matching and the browser's own heading sizes showed through, bold and large. That is
 * what changed the sizes; nothing was re-decided.
 *
 * His own values, from `prototype.css` line 1962: 15px, weight 400, `--ink-faint`. The
 * title is quiet because the photograph is the headline (design-principles §4), and that
 * is true of the promoted term as well — it exists for Google, not to shout on the page.
 */
.wk-head h1,
.wk-head h2,
.wk-promo h1,
.wk-promo h2 {
  font-size: 15px;
  font-weight: 400;
  margin: 0 0 5px;
  color: var(--ink-faint);
}
.wk-promo h1,
.wk-promo h2 { margin-bottom: 10px; }

/* ----------------------------------------- the links inside a work's own text
 *
 * Jacki, 03/09/26: the links in the text behind the little arrow must not stand out in
 * another colour or with an underline.
 *
 * They were not standing out — they were **unstyled**: `rgb(0, 0, 238)` with an
 * underline, the browser's own default, because nothing in either stylesheet had ever
 * touched them. 143 of the 255 descriptions carry hand-written internal links, so this
 * was every one of them on every work page.
 *
 * They take the colour of the sentence they sit in and lose the underline. **The cue
 * moves to hover and to focus** rather than disappearing: a link nobody can find is not
 * a link, and these are the internal links the whole ranking argument rests on
 * (`seo-requirements.md`, "internal linking is the cheapest ranking work on this site").
 * Underlining on hover costs nothing in a resting page and keeps them discoverable.
 */
.ptext a,
#wkText a {
  color: inherit;
  text-decoration: none;
  border-bottom: 0;
}
.ptext a:hover,
#wkText a:hover { text-decoration: underline; }

.ptext a:focus-visible,
#wkText a:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }


/* ============================================================ THE HEADING LAW
 *
 * Jacki, 05/09/26: *"H1 יחיד והוא ה־SEO או שם התמונה תלוי בדף מקודם או לא. אין אף H אחר
 * בלי שאני אגיד!!! זה חוק בכל דפי האתר. אל תשתמש ב־H כדי לחסוך ב־CSS."*
 * (`seo-requirements.md` §6a, `CLAUDE.md` §8.)
 *
 * Every heading element that was not the page's one h1 is now an ordinary `<p>` carrying
 * a class. **The look does not change** — these rules restate, value for value, the
 * prototype rules that styled those elements BY ELEMENT and therefore stopped matching.
 * `prototype.css` is his stylesheet and is never edited (a test asserts it byte-identical),
 * so the restatement lives here, after it.
 *
 * `line-height: inherit` appears where the old heading inherited its own — a `<p>` in the
 * same place would otherwise pick up a `p` rule the heading never saw.
 */

/* the page title — prototype.css:557 `.page h1`
 *
 * **Quieter, and a touch above the photograph's own title — Jacki, 23/09/26:** *"הכותרת
 * בדפי האוסף, ובכלל באתר, H1, חייב להיות פחות בולט ובצבע ופונט טיפה מעל הכותרת של
 * התמונה."*
 *
 * It was 27px (22 on a telephone) in the full `--ink`, measured on eleven addresses, while
 * the work's own name is 15px in `--ink-faint` — so the page's title was the loudest thing
 * on a page whose subject is a photograph, which is `design-principles.md` §4 read
 * backwards.
 *
 * **One step above the name and one step below the body, in both directions:** 18px
 * against its 15, and `--ink-soft` (`#56584F` on the light substrate) between the name's
 * `--ink-faint` `#8A8C83` and the `--ink` `#17181A` it used to carry. The weight, the
 * margin and the leading are untouched, and so is the phone, which now takes the same 18
 * rather than a second size — the reduction already put it below what the telephone rule
 * was there to prevent. */
.page .pgtitle,
.home-head .pgtitle {
  font-size: 18px; font-weight: 400; margin: 0; line-height: 1.35; color: var(--ink-soft);
}
@media (max-width: 720px) {
  .page .pgtitle,
  .home-head .pgtitle { font-size: 18px; }
}

/* the work's own name — prototype.css:1962 `.wk-head h1` */
.wk-head .wk-name {
  font-size: 15px; font-weight: 400; margin: 0 0 5px; color: var(--ink-faint);
}
/* the promoted term, which IS the h1 on a promoted work — same quiet size as the name
 * above it (site.css, 03/09: "both headings exactly like the title under the photograph") */
.wk-promo .wk-promo-h {
  font-size: 15px; font-weight: 400; margin: 0 0 10px; color: var(--ink-faint);
  line-height: inherit;
}

/* the checkout blocks — prototype.css:893 `.co-block h2` */
.co-block .co-h {
  font-size: 12px; font-weight: 400; letter-spacing: .16em;
  color: var(--ink-faint); margin: 0 0 18px; line-height: inherit;
}

/* אודות — prototype.css:613 `.prose h2` */
.prose .prose-h {
  font-size: 16px; font-weight: 600; margin: 0 0 6px; color: var(--ink);
  line-height: inherit; max-width: none;
}

/* the drawers — prototype.css:760 `.drawer h3` and 1840 `.ss-card h3` */
.drawer .drawer-h { font-size: 17px; font-weight: 400; margin: 0 0 3px; }
.ss-card .drawer-h { margin: 0; font-size: 18px; font-weight: 400; }
.drawer-h { line-height: inherit; }

/* the legal pages — prototype.css:801 `.legal h2` and 806 `.legal h3`.
 * The copied legal wording carries its own headings; the words stay, the element does
 * not (`seo-requirements.md` §6a). */
.legal .legal-h {
  font-size: 15px; font-weight: 400; color: var(--ink);
  margin: 30px 0 10px; padding-top: 18px; border-top: 1px solid var(--line);
  line-height: inherit;
}
.legal .legal-h:first-child { margin-top: 0; padding-top: 0; border-top: 0; }
.legal .legal-h3 {
  font-size: 13.5px; font-weight: 400; color: var(--ink-soft); margin: 20px 0 8px;
  line-height: inherit;
}

/* the guide pages — 22/09/26. Two row kinds the legal pages never needed, styled in the
 * text page's own language rather than a new one: the caption is the `.legal p` size and
 * colour, and the call to action is `.ghost.lead`, which is what an emphasised action
 * already looks like everywhere else on this site (`CLAUDE.md` §8). */
.legal .legal-fig { margin: 18px 0 24px; }
.legal .legal-fig img {
  display: block; width: 100%; height: auto; border-radius: 2px;
  background: var(--line);
}
.legal .legal-fig figcaption {
  font-size: 12.5px; line-height: 1.8; color: var(--ink-faint); margin-top: 8px;
}
/* **The call to action is the hand and the telephone — Jacki, 22/09/26**, in place of the
 * worded link that was there first. Nothing here is drawn: the picture is
 * `/static/hand-photo.png` and the press is `.toolbtn`, which are the same two parts the
 * work page's own simulation offer is made of (`_sim_block.html`). The whole block is one
 * `<a>`, so the picture itself is the target rather than a sign beside one.
 * `img.wv-hand` above sets 46px for the wall's small copy; `.wksim-offer` overrides it to
 * 200 and so does this, by the same means and to the same number. */
a.legal-cta {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px 16px;
  margin: 26px 0 30px; text-decoration: none;
}
a.legal-cta .wv-hand { width: 200px; height: auto; }
a.legal-cta .toolbtn { display: inline-block; }
a.legal-cta:hover .toolbtn { color: var(--ink); border-color: var(--ink-faint); }
a.legal-cta:focus-visible { outline: 2px solid var(--gold); outline-offset: 4px; }
@media (max-width: 720px) {
  /* The number the work page's offer uses at this width, for the same reason. */
  a.legal-cta .wv-hand { width: 160px; }
}

/* **And the section has to be SHOWN for the guide too.** `prototype.css:232` makes every
 * `.page` `display: none` and one rule per view turns its own back on. `data-view="guide"`
 * matched none of them, so the server wrote a perfect page and the visitor got a blank
 * screen — present is not visible. The rule belongs here and not beside its fourteen
 * siblings, because `prototype.css` is Jacki's stylesheet byte for byte
 * (`tests/test_adoption.py`). */
.app[data-view="guide"] #pageLegal { display: block; }

/* ========================= the purchase panel, inside the page
 *
 * Jacki, 05/09/26: *"תמקם את זה מתחת לבלוק של ההדמיות מעל התמונות קשורות ותן לזה כותרת
 * בדומה ל'תמונות קשורות' — 'אפשרויות להדפסה ורכישה' באותו סגנון… ואני מזכיר לך לטפל גם
 * בגירסת המובייל."*
 *
 * The panel's own markup is unchanged — it is the same `.buy-in` the רולאפ uses — so what
 * is here is only the handful of rules the prototype scoped to `.drawer`, restated for
 * the page, and the two that belong to a רולאפ and must not follow it into the flow.
 */
#wkBuySlot .buy-in { max-width: none; margin: 0; }
#wkBuySlot .col { display: flex; flex-direction: column; gap: 16px; }
#wkBuySlot .sub { font-size: 12.5px; color: var(--ink-faint); }

/* The panel names the work it belongs to, because a רולאפ over the wall has to. In the
 * page the h1 says it a screen above — the same rule the simulations already follow
 * (`prototype.css`: `#wkSimSlot #wvTitle { display: none }`). Hidden, never removed:
 * one markup, two presentations. */
#wkBuySlot #dTitle,
#wkBuySlot #dSub { display: none; }

@media (max-width: 720px) {
  /* **The mobile fix.** In a רולאפ the money bar is sticky because the panel fills the
   * screen and the price must stay in view while the finger scrolls the options. In the
   * page it would float over תמונות קשורות below it, so it goes back into the flow. */
  #wkBuySlot .buy-in .col:last-child .foot {
    position: static; background: none; border-top: 0;
    margin: 0; padding: 0; justify-content: flex-start;
  }
}

/* ============================== the one link from the site into the admin
 *
 * Jacki, 05/09/26: *"אם אני גולש באתר כשאני בלוגין אז רק בדסקטופ יופיע כפתור — לעריכת
 * התמונה בדף התמונה. הפעולה הנגדית לצפייה בדף מהאדמין לאתר."*
 *
 * **It is not in the document for anybody who is not signed in** — the server does not
 * render it — so `design-principles.md` §10c still holds exactly as written: no link to
 * the admin anywhere on the live site. This styles it for the one session that has it.
 *
 * Desktop only, by his instruction. Below 900px the action strip beside the title is
 * already full, and this is not a visitor's control competing for that room.
 */
.wk-admin {
  /* `.ghost` already gives it the strip's look — this only stops it wrapping and stops
     the browser drawing a second underline beneath the one `.ghost` draws. */
  text-decoration: none;
  white-space: nowrap;
  font-size: 12.5px;
}
@media (max-width: 899px) {
  .wk-admin { display: none; }
}

/* ========================= the simulations on the work page — 05/09/26
 *
 * **`אין יותר קנבס`**, and **his layout, from the screenshot he sent**: the large
 * simulation on the right, and on its left the offer above three thumbnails.
 *
 * **`הקיר שלי` leads the column and is never moved down for room.** Jacki, the same day:
 * *"אם מישהו מבקש הדמיה המכירה כמעט סגורה"* — `simulations.md` §2 says the same, and it
 * is the reason the offer sits level with the picture and not under it.
 *
 * Clicking a thumbnail swaps it with the large one, which is his instruction too: the one
 * that was large takes the thumbnail's place rather than disappearing.
 */
.wksim {
  display: grid;
  grid-template-columns: minmax(0, 560px) minmax(0, 1fr);
  gap: 22px;
  /* **`stretch`, so the column beside the picture is exactly as tall as it** — which is
     what lets the three line up with its bottom edge. Jacki, 05/09/26: *"3 ההדמיות
     מיושרות עם הקו התחתון."* */
  align-items: stretch;
}
.wksim-side {
  display: flex;
  flex-direction: column;
  /* the offer at the top, the three at the bottom, and the space between them */
  justify-content: space-between;
  gap: 16px;
  min-width: 0;
}

.wksim-shot {
  position: relative;
  margin: 0;
  aspect-ratio: 3 / 2;
  overflow: hidden;
  background: var(--wall);
}
/* **One image, composited on the server — 05/09/26.** It used to be two files laid over
 * each other here, which is HTML but is not a picture: Google Images indexes files, and
 * the file was a bare room repeated on every work that used it. The shadow moved into the
 * pixels with everything else (`app/images/composite.py`). */
.wksim-img {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; display: block;
}

/* ------------------------------------------------------------------- the offer */
.wksim-offer {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: 10px 16px;
}
.wksim-offer .wv-hand { grid-column: 2; grid-row: 1; width: 200px; height: auto; }
/* The sizes are the ones in his screenshot; he asked for them to stay. */
.wksim-offer-h {
  grid-column: 1; grid-row: 1;
  font-size: 21px; font-weight: 400; line-height: 1.4; color: var(--ink);
}
.wksim-offer-p {
  grid-column: 1 / -1; grid-row: 2;
  font-size: 15px; line-height: 1.9; color: var(--ink-soft);
}
/* The call to action, from his mockup. `toolbtn` is the site's own small button — the
 * same one the top bar uses — so this is his vocabulary, not a new kind of control. */
.wksim-cta { grid-column: 1 / -1; grid-row: 3; }

/* ------------------------------------------------------------- the three beside it */
.wksim-thumbs { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
.wksim-thumb {
  background: none; border: 0; padding: 0; cursor: pointer; display: block;
}
.wksim-thumb:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; }

@media (max-width: 899px) {
  /* **⚑ Two rows of two, and small — Jacki, 09/09/26.** *"כרגע רואים 3 הדמיות מתוך ה־4.
   * ההדמיות גדולות. האם יש אפשרות רק במובייל להציג את ההדמיות ב־2 שורות של 2 בכל שורה."*
   *
   * *"במובייל יופיע כל ה־4."* was answered with one full-width column, and the fourth was
   * so far down the page that it was not part of the same thing any more — which is why
   * he counted three. Four in a 2×2 is the whole set inside one screen.
   *
   * **The four are not siblings**: the first is a direct child of `.wksim` and the other
   * three live in `.wksim-thumbs` inside `.wksim-side`. `display: contents` makes those
   * two wrappers disappear as boxes and hands their children to this grid, which is what
   * lets one grid place all four — no second copy of the markup and no re-parenting in
   * script. The offer keeps its own full-width row and stays first, as it did before.
   *
   * Their `sizes` moved with them (`prototype_view.SIM_SIZES_*`): each is now a little
   * under half the width, and a picture that still claimed `100vw` would fetch for a
   * width nothing on the page uses. */
  .wksim { grid-template-columns: 1fr 1fr; gap: 10px; align-items: start; }
  .wksim-side { display: contents; }
  .wksim-thumbs { display: contents; }
  .wksim-offer { grid-column: 1 / -1; order: -1; }

  /* **⚑ Four pictures, and nothing to press — Jacki, 09/09/26:** *"האם אפשר לוותר במובייל
   * על האפקט של הלחיצה על ההדמיות? פשוט סתם להציג 4 תמונות."*
   *
   * Pressing a small one swapped it into the large one — an answer to a layout where one
   * IS large, and two by two there is no large one to swap into.
   *
   * `--sim-press` is read by `prototype.js`, so the keyboard cannot do what the finger no
   * longer can, and the breakpoint stays written in one place: a width copied into the
   * script goes on meaning the old thing long after this rule has changed. The pointer is
   * stopped here as well, so nothing lights up under a finger that lands on a picture. */
  .wksim { --sim-press: none; }
  .wksim-thumb { pointer-events: none; cursor: default; }
  .wksim-shot .zoomover { display: none; }
  /* **⚑ One column means one item per row — 09/09/26.** The desktop layout puts the
   * hand photograph in column 2 of row 1 and the heading in column 1 of the same row.
   * This block collapsed the grid to a single column and moved the photograph to column
   * 1 — and left it on ROW 1, where the heading already was. Two items in one cell are
   * drawn on top of each other, so on every phone the picture sat over
   * ״לפני שאתם משלמים - קבלו הדמיה על הקיר שלכם״ and the sentence could not be read.
   *
   * The row and column assignments are cleared here rather than renumbered: in one
   * column the source order is the right order, and a second set of numbers is a second
   * thing to keep in step with the first. */
  .wksim-offer { grid-template-columns: 1fr; }
  .wksim-offer > * { grid-column: 1; grid-row: auto; }
  /* Two classes, to match the rule above the media query — `> *` is one, and a media
     query adds no weight of its own, so the desktop's `grid-column: 2; grid-row: 1` was
     still winning here. That is what put the photograph back beside the heading instead
     of above it, in a second column the grid had to invent. */
  .wksim-offer .wv-hand { grid-column: 1; grid-row: auto; width: 160px; }
  .wksim-offer-h { font-size: 19px; }
}

/* ========================= the admin bar — 06/09/26
 *
 * Jacki: *"פס צהוב למעלה קבוע… בפס הזה יהיו תפריטים ישירים למערכת הניהול."* WordPress's
 * bar, in this admin's own environment colours (`ds.css` §21: amber with dark text for
 * staging), so the two systems read as one.
 *
 * **It is only ever in the document for a signed-in admin** — the server does not render
 * it otherwise, so there is nothing here that hides anything (`design-principles.md`
 * §10c). Amber is not a status colour here and carries no meaning a colourblind reader
 * has to decode: every item in it is a word.
 */
.adminbar {
  display: flex;
  align-items: center;
  gap: 16px;
  height: 30px;
  padding: 0 14px;
  background: #eab308;
  color: #1f2937;
  font-size: 13px;
  font-weight: 600;
  /* Over everything, including the shell's own fixed chrome. */
  position: relative;
  z-index: 60;
}
/* **״מילוי בדיקה״ — 01/10/26.** The admin's fill link above each form: the admin bar's
   own amber, so it reads as his tool and never as part of the visitor's page. Rendered only
   for an admin's session. */
.pa-fill {
  display: inline-block;
  margin: 0 0 12px;
  padding: 3px 10px;
  border: 0;
  border-radius: 4px;
  background: #eab308;
  color: #1f2937;
  font: inherit;
  font-size: 13px;
  cursor: pointer;
}
/* **Green on the live site — 06/10/26**, the admin's own `ds-envbar.prod` green. The words
   beside it say which site this is; the colour only agrees with them. */
.adminbar.is-live { background: #16a34a; color: #fff; }
.adminbar.is-live a { color: #fff; }
.adminbar.is-live a:hover { border-bottom-color: #fff; }
.adminbar.is-live a:focus-visible { outline-color: #fff; }
.adminbar .ab-env {
  font-size: 11px;
  letter-spacing: .5px;
  opacity: .85;
  white-space: nowrap;
}
.adminbar .ab-links { display: flex; align-items: center; gap: 14px; min-width: 0; }
.adminbar a {
  color: #1f2937;
  text-decoration: none;
  white-space: nowrap;
  border-bottom: 1px solid transparent;
  padding: 2px 0;
}
.adminbar a:hover { border-bottom-color: #1f2937; }
.adminbar a:focus-visible { outline: 2px solid #1f2937; outline-offset: 3px; }
.adminbar .ab-who {
  margin-inline-start: auto;
  font-weight: 400;
  font-size: 12px;
  opacity: .8;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* The shell is `height: 100dvh` (`prototype.css`), so the bar has to come out of it or
   the footer leaves the screen. */
body.has-adminbar .app {
  height: calc(100dvh - 30px);
  min-height: calc(100vh - 30px);
}

@media (max-width: 899px) {
  /* On a phone the environment label goes and the links stay: what the bar is FOR is the
     links, and the colour already says which site this is. */
  .adminbar { gap: 12px; font-size: 12.5px; }
  .adminbar .ab-env, .adminbar .ab-who { display: none; }
}


/* ⚑ **`hidden` HAS TO WIN — 08/09/26, and this was a live fault.**
 *
 * Jacki: *"למה אני רואה 'סוג ההדפסה הזה אינו מתומחר ליחס של התמונה. הרכישה בטלפון' כל
 * הזמן?"* Because a browser hides `[hidden]` with a rule in its OWN stylesheet, and ANY
 * author rule that sets `display` beats it. `.sum { display: flex }` and `.row2` are the
 * prototype's; `.tel-buy` and `.prodpic` were mine. Every one of them made `hidden` do
 * nothing, so the telephone sentence, the total and the size row were all on screen at
 * once, on every work.
 *
 * One rule fixes all of them and every one added later, which is the point: the ones that
 * exist today were found by him looking at the screen, not by a check.
 */
[hidden] { display: none !important; }

/* ============================ the purchase drawer, 08/09/26 ============================
 *
 * Open list E35 and E36. The sample used to be `drawFinish()` — the visitor's own
 * photograph composited onto a drawn material inside a CSS 3D box — and it is now a
 * photograph OF the product, an `<img>` with `srcset` (`seo-requirements.md` §4).
 *
 * `.fin` is the prototype's own box and is unchanged: same size, same frame, same
 * background. Nothing here restates one of its values.
 */
/* **⚑ Nothing around the picture — 08/09/26.** Jacki: *"אם החלטת על הגודל שהחלטת עבור
 * הדמיית חומר ההדפסה אז לפחות תצמצם את כל מה שמסביב לתמונה. זה נראה ממש מגעיל."*
 *
 * `.fin` is the prototype's finish box: a 4:3 frame with a border and a light gradient,
 * built for `drawFinish()`, which drew a print at whatever size the work's ratio gave it
 * and needed a stage to sit on. A photograph of a product needs no stage — it is already
 * a rectangle — and letterboxing one inside a fixed 4:3 frame put a grey band above and
 * below it and a line around all of it.
 *
 * So the box becomes the picture: no frame, no gradient, no fixed proportion. **This is
 * the one place production overrides a value of his**, and it is overridden because the
 * element it was drawn for no longer exists. */
.fin {
  aspect-ratio: auto;
  border: 0;
  background: none;
  overflow: visible;
  display: block;
}
.fin { position: relative; }
.fin .prodpic { display: block; }
.fin .prodpic img { display: block; width: 100%; height: auto; }

/* **⚑ ONE magnifier, and it is the one the site already had — 08/09/26.**
 *
 * Jacki: *"קבענו שאנחנו משתמשים באיקון של זכוכית מגדלת — ראה מתחת לתמונה הגדולה… ותשנה את
 * האיקון בתוך העיגול הכהה לאיקון בלי העיגול הכהה. הדברים צריכים לבנות שפה אחת ולא לפזר
 * חרא בכל מקום."*
 *
 * It was a dark circle laid over the corner of the picture — a shape invented for this one
 * place, which is a second language. It is `#openZoom` now: the same SVG, the same
 * `.ghost.iconly` button, sitting UNDER the picture exactly as that one sits under the
 * large photograph. Nothing here restates a value `.ghost` already sets; only the size,
 * the way `.wk-titlerow .ghost.iconly` does. */
/* **⚑ AND IT SHOWS ONLY ON HOVER, INSIDE THE PICTURE — 08/09/26.** Two more instructions
 * the same evening: *"תכניס את האיקון… לתוך המסגרת… אין סיבה שהוא יתפוס לנו שורת רווח"*
 * and *"תוריד את כל האיקונים של ההגדלה גם בתמונה הראשית ובמקום תציג את האיקון כאשר עוברים
 * מעל התמונות."*
 *
 * **A row of its own is what made the three simulations vanish.** `.wksim-thumb` was given
 * `display:flex; align-items:center` to stack the icon under the picture — and a flex item
 * that is not stretched shrinks to its content, which for `.wksim-shot` is an absolutely
 * positioned image: zero width, and `aspect-ratio` then gives zero height. The three
 * collapsed to nothing. It is `display:block` again, and the icon is out of the flow.
 *
 * **White with a shadow and no box**, because one rule has to work over a dark room
 * photograph and over a cut-out on a light page, and he refused a dark circle. */
/* **⚑ IN THE MIDDLE, AND IT IS A SIGN — NOT THE TARGET.** Jacki, 08/09/26: *"בתמונה
 * הגדולה אתה מציג איקון הגדלה בריחוף על פני כל התמונה, אז למה לאלץ את המשתמש ללחוץ דווקא
 * על האיקון ששמת בפינה???"*
 *
 * He is right, and a corner is what caused it: an icon in a corner reads as a small button
 * you have to hit. Centred over the picture it reads as a label of the picture, which is
 * what it is — **`pointer-events: none`, so the press lands on the picture wherever it
 * falls.** The whole picture has been the target all along; the corner was hiding that.
 *
 * **The wall's stage is the one exception, and for a reason:** the photograph there already
 * has its own click — it navigates — so the magnifier keeps its own hit area. Everywhere
 * the picture has no other job, the picture is the button. */
.zoomover {
  position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); z-index: 2;
  padding: 5px 6px; border-bottom-color: transparent;
  color: #fff; filter: drop-shadow(0 1px 3px rgba(0, 0, 0, .9));
  opacity: 0; pointer-events: none; transition: opacity .18s ease;
}
.zoomover svg { width: 30px; height: 30px; flex: none; }
.wksim-shot .zoomover svg { width: 22px; height: 22px; }
/* **The stage's rules are gone — 10/09/26.** They existed because the wall's photograph
 * already answers a click of its own, so the magnifier laid over it had to keep a target
 * of its own — a second, smaller one on top of a bigger one. It is back in the row of
 * five icons beneath the picture and is an ordinary `.ghost.iconly` again, so there is no
 * `.zoomover` on the stage for these to describe. Kept in the record rather than in the
 * stylesheet:
 *     .stage .zoomover { pointer-events: auto; }
 *     .stage:hover .zoomover:hover { color: #fff; }
 */

/* Revealed by the picture, not by the icon — the icon is what the hover is FOR. */
.fin:hover .zoomover, .fin:focus-within .zoomover,
.wksim-shot:hover .zoomover, .wksim-thumb:focus-visible .zoomover,
.wk-hero:hover .zoomover, .wk-hero:focus-within .zoomover {
  opacity: 1; pointer-events: auto;
}

/* The two that were in a row of chrome and are now on the photograph itself. The script
   moves the existing buttons rather than drawing new ones — one element, one handler, and
   no hidden leftover in the row it came from. */
.wk-hero { position: relative; cursor: zoom-in; }
.fin { cursor: zoom-in; }
.wksim-thumb { cursor: zoom-in; }

/* **The print sample, enlarged, always on black** — 08/09/26. Black whatever wall the
 * visitor chose: this is a photograph of an object, and the surround is there to
 * disappear. */
.prodzoom {
  position: fixed; inset: 0; z-index: 90;
  display: flex; align-items: center; justify-content: center;
  background: #000; padding: 24px; cursor: zoom-out;
}
.prodzoom img { max-width: 100%; max-height: 100%; width: auto; height: auto; cursor: default; }
.prodzoom-x {
  position: absolute; inset-block-start: 14px; inset-inline-end: 16px;
  width: 40px; height: 40px; font: inherit; font-size: 18px; line-height: 1;
  background: rgba(255, 255, 255, .12); color: #fff;
  border: 1px solid rgba(255, 255, 255, .3); border-radius: 50%; cursor: pointer;
}
.prodzoom-x:hover { background: rgba(255, 255, 255, .22); }

/* The telephone, where no price can be computed (`price-feed.md` §5b). It is one of three
 * ordinary payment methods and not an apology, so it wears the SAME button the basket
 * wears — `.buybtn`, the prototype's own — rather than a colour of its own invented to
 * mark it as a lesser route. An anchor needs the two properties a browser gives a button
 * and nothing else. */
.tel-buy { display: flex; flex-direction: column; align-items: flex-start; gap: 10px; }


/* ========================= the purchase panel, stacked — 09/09/26
 *
 * **⚑ The options first, their photograph after.** Jacki: *"אפשרויות להדפסה צריך קודם
 * להציג את האפשרויות ואת ההדמיות של האפשרויות אחר כך ולא לפני."*
 *
 * Side by side there is no before: this is the range where `prototype.css` stacks the
 * panel and puts `.sample` on top, so a visitor met a photograph of canvas before being
 * told that canvas is one of three things to choose.
 *
 * `.sample` carries three things — the work's name, the photograph of the product and
 * the material's own caption — and only the last two are what he means. `display:
 * contents` lets them be ordered separately without a second copy of the markup: the
 * name stays at the top, the two columns of options follow, and the photograph and its
 * caption come after them.
 *
 * It is here and not in `prototype.css`, which is his stylesheet byte for byte and is
 * never edited by hand (`tests/test_adoption.py`).
 */
@media (max-width: 1000px) {
  /* The second selector is not decoration: `#wkBuySlot .col` above carries an id, which
     outweighs any number of classes, and on a work's own page the panel lives inside that
     slot — so without it the column stayed a flex box and its three parts could not be
     ordered separately. (There the work's name is hidden anyway, by `#wkBuySlot #dTitle`,
     so what moves is the photograph and its caption.) */
  .buy-in > .sample,
  #wkBuySlot .buy-in > .sample { display: contents; }
  /* **⚑ And the photograph belongs to the list above it — Jacki, 09/09/26:** *"אולי
     אנחנו צריכים איך שהוא במובייל להכניס את ההדמיות של ההדפסות מתחת לרשימת אפשרויות
     להדפסה. כרגע זה מוצג מתחת להוספה וסך הקניות."*
     The picture answers ״סוג הדפסה״, so it goes directly under that list — not at the
     bottom of the panel, where it followed the total and the basket and belonged to
     nothing. The size, the delivery, the wrap and the money come after it. */
  /* **⚑ And the עיטוף chips come between them — Jacki, 09/09/26:** *"עד תיקון בקנבס לבן
     או גלריה צריך להיות מתחת לרשימה ומעל ההדגמה של ההדפסה."*
     It is the same thought one step further: what a person buys is the VARIANT, not the
     material, so the wrap is part of choosing — and the photograph below it is a
     photograph OF the wrap that was chosen. List, wrap, the picture of that wrap; then
     the size, the delivery and the money.

     That means the third column has to open up as well, so its parts can be ordered on
     their own — the wrap chips live inside it. The delivery sentence stays immediately
     under the אספקה box, which was his instruction earlier today. */
  #wkBuySlot .buy-in > .col:nth-child(3),
  .buy-in > .col:nth-child(3) { display: contents; }

  .buy-in > .sample > div:first-child { order: 1; }
  .buy-in > .col:nth-child(2) { order: 2; }
  /* `#dWrap` needs no order of its own: it is inside the materials column now. */
  .buy-in > .sample > .fin { order: 4; }
  .buy-in > .sample > #dTypeNote { order: 5; }
  .buy-in #dChoices { order: 6; }
  .buy-in #dDeliveryNote { order: 7; }
  .buy-in #dSum { order: 8; }
  .buy-in #dPhoneBox { order: 9; }
  .buy-in .foot { order: 10; }
  .buy-in #dShipNote { order: 11; }
}


/* ========================= the wrap, inside the materials list — 09/09/26
 *
 * Jacki: nest the buttons directly under the קנבס row itself, *"גם במובייל וגם בדסקטופ"*.
 * At the foot of the list they were two rows below קנבס and could be read as belonging to
 * זכוכית; under the row there is nothing to misread.
 *
 * It is one element that MOVES with the choice — `prototype.js` places it after whichever
 * material is pressed, and the server writes it under the one the panel opens on. So this
 * only has to say what it looks like there: a little in from the material's own text, no
 * rule under it (the material above owns that line), and enough air that it reads as an
 * answer to the row above rather than as another row.
 */
.types #dWrap,
.types #dSheen {
  padding: 10px 14px 12px 0;
  margin-bottom: 2px;
  border-bottom: 1px solid var(--line);
}
.types #dWrap .fl,
.types #dSheen .fl { margin-bottom: 6px; }

/* ============================== דף הסט — /set/<code>, 15/09/26
 *
 * `docs/sets.md`. The page parallel to a work's, at his instruction. The rules that show a
 * page live in `prototype.css`, which is his file byte for byte and is never edited
 * (`CLAUDE.md` §8), so the set's own rule lives here.
 */
.app[data-view="set"] #pageSet { display: block; }

/* **The hero is assembled, not the composited file.** That file has the white ground in
 * its pixels — it is what Google indexes — and cannot be laid over a wall. Here the wall is
 * one image and each work is an image above it, at the shares the arrangement screen wrote.
 * 3:2, the frame the file is built in, so the two cannot disagree about the composition. */
.st-hero {
  position: relative;
  width: 100%;
  max-width: 1120px;
  margin: 0 auto;
  aspect-ratio: 3 / 2;
  overflow: hidden;
  border-radius: 4px;
  background: #fff;
}
.st-ground { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }

/* A print standing off the wall, the same two shadows the composited file paints — the
 * wide one says how far it stands off, the tight one that it is touching nothing
 * (`images/composite.py`). They match, so the page and the file look like one thing. */
.st-art { position: absolute; display: block; }
.st-art img {
  display: block;
  width: 100%;
  height: auto;
  box-shadow: 0 26px 44px -12px rgba(0, 0, 0, .80), 0 5px 9px rgba(0, 0, 0, .45);
}

/* The wall chips. `.chips` and `.cat` are the purchase drawer's own classes — the same
 * control, not a second one (§8) — and every wall is named, because he is colourblind and
 * a row of swatches is the question he cannot answer (§1). */
.st-walls { display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
            max-width: 1120px; margin: 12px auto 0; }

.st-note { margin: 14px 0 0; color: var(--ink-soft); font-size: 13px; }

/* The title needs air under the wall chips — *"תרווח, זה צמוד מדי"*. */
.st-head { margin-top: 26px; }


/* The wall chips carry a picture as well as the word — 15/09/26. The word is first and the
 * picture is beside it: he is colourblind, so the name is how a wall is chosen and the
 * picture is a reminder (`CLAUDE.md` §1). */
.st-wall { display: inline-flex; align-items: center; gap: 7px; }
.st-swatch {
  display: block;
  width: 26px;
  height: 18px;
  border-radius: 3px;
  object-fit: cover;
  border: 1px solid rgba(255, 255, 255, .25);
}
.st-white { background: #fff; }

/* **A size is one thing and wraps as one** — 15/09/26: *"הגדלים צריכים להיות בשורה ולא
 * שה־ס״מ עובר לשורה מתחת."* Three numbers and a unit broke across two lines in a narrow
 * column, which reads as two facts. */
.st-cm { white-space: nowrap; }





/* **The set's own picture in the הדמיה request — 15/09/26.**
 *
 * The dialogue has always shown the work as a canvas (`prototype.css` `.rq-work canvas`,
 * his file and untouched). A set is a real composited file, so it is an `<img>` in the
 * same box — §11 rule 4, *"אין יותר קנבס"*: the preview's canvas is named there as debt,
 * and a new subject does not get to join it.
 *
 * The values are copied from `.rq-work canvas` rather than re-decided, so the two look
 * identical in the same slot. `[hidden]` still wins over this: it is `!important` on line
 * 1381 of this file, for exactly this reason. */
.rq-work #rqPic { display: block; width: 100%; height: auto; box-shadow: var(--shadow); }

/* **The set's cart is a link, and the work's is a button** — 15/09/26. On a work the
 * control OPENS a drawer; on a set the prices are already in the document, so it is
 * navigation and an `<a>` reaches them with no script and before the script has run. The
 * one thing an anchor brings that a button does not is an underline. */
.wk-acts a.ghost { text-decoration: none; }

/* **הסטים בתוצאות החיפוש — 15/09/26**, `sets.md` §6: *"הסט מופיע בקטלוג לצד העבודות…
 * בתוצאות החיפוש."*
 *
 * A band of its own above the plates, because a set is a different product and the page
 * should say so rather than let it pass as a photograph. It borrows `.wk-related` and
 * `.wk-rel` whole — the same strip the work page uses for תמונות קשורות and for
 * ״נמכרת גם בסט״ — so there is one way a row of linked pictures looks on this site. */
.sr-sets { grid-column: 1 / -1; margin: 0 0 18px; }
.sr-sets-h { margin: 0 0 10px; font-size: 12px; color: var(--ink-faint); }

/* ==================================== the smart search's answer, 21/09/26 =============
   `search.md` §5. Two things the results page did not have a place for: the line under a
   work saying why it is there, and the band that carries the near misses without letting
   them look like the answer. Both are built from what the page already has — `.results`
   is the twelve-column grid and `.sr-sets` is the band the sets already sit in. */

/* **The nearest thing it has, named as such** (§5 rule 2). Set apart by a rule above it
   rather than by a colour, so it reads as a different answer and not as a warning. */
.sr-near { border-top: 1px solid var(--line); padding-top: 22px; margin-top: 10px; }
.sr-grid {
  display: grid; grid-template-columns: repeat(12, 1fr); gap: 40px 26px; align-items: end;
}
@media (max-width: 899px) {
  .sr-grid { grid-template-columns: 1fr; gap: 30px; }
}

/* ============================================================ the thumb, 20/09/26
 *
 * **Jacki: *"שכל האתר יהיה רספונסיבי מלא ויעבוד מעולה במכשירים הסלולארים"*** — and the
 * measurement said the layout is already sound: nine addresses on a real iPhone profile,
 * **no horizontal overflow and no exception anywhere**. What was wrong was the size of
 * what a finger has to hit. 44×44 is the floor (A23, E64).
 *
 * **⚑ The painted control does not change.** Each of these gets an invisible box centred
 * on it, so the design Jacki arrived at over weeks is exactly where it was and only the
 * touchable area grows (`CLAUDE.md` §8 — the existing UI is closed).
 *
 * **`::before`, not `::after`** — `.actions .ghost.iconly::after` is already set to
 * `content: none` above, and a hit area that one rule silently cancels is worse than none,
 * because it looks fixed.
 *
 * **And only on a telephone.** The admin is desktop by his decision the same day, and a
 * pointer does not need 44 pixels.
 *
 * **Where it is NOT applied:** the three `.pact` on a plate sit 8px apart, so 44 fits with
 * room to spare — but two controls whose hit areas overlap are worse than two small ones,
 * because the wrong one answers. That is why the widths below are read from the measured
 * geometry rather than applied to everything that is under 44.
 */
@media (max-width: 720px) {
  /* **⚑ `position` is NOT set here, and that cost the logo — 20/09/26.**
   *
   * The first version listed `.brand` among these and gave the whole list
   * `position: relative`. `.brand` is `position: absolute` above, which is what centres the
   * logo in the bar; overriding it dropped the logo back into the flex row, where it landed
   * at **x=403 on a 390px screen** — off the edge, invisible behind `body { overflow:
   * hidden }`, and unreachable. It was the one control failing on every single page, and I
   * read that as "my rule did not reach it" rather than "my rule broke it".
   *
   * **A hit area needs a positioned ancestor, not a `relative` one.** `.closebtn` is
   * already `absolute` and `.prev`/`.next`/`.linklike` are already `relative`, so the only
   * ones that need it are the plainly static ones — and each is named rather than swept up
   * in a list. */
  /* **`.brand` is excluded on purpose — it is `position: absolute` and that is what centres
     the logo.** Everything else here is static and must be made a positioning context, or
     its `::before` sizes itself against a distant ancestor: `.linklike` produced a
     390×788 invisible box that covered the basket and swallowed every press on it. */
  /* **⚑ `.prev` and `.next` are NOT in this list — 05/10/26.** They are the wall's two
     arrows (`.nav.prev`, `.nav.next`), which his stylesheet makes `position: absolute`: one
     at each side. Listed here they became `relative`, fell into the flow, and stood
     together in one corner on every telephone — Jacki: *"במובייל החצים נמצאים בפינה, אני
     רוצה שהם יהיו מעל התמונה מימין ומשמאל."* An absolute element is already a
     positioning context for its own hit area, so it never needed this rule. */
  .pact, .toolbtn, .navlink, .sw, .ghost, .pmore,
  .linklike, .co-rm, .cat {
    position: relative;
  }

  /* **A hit area never exceeds its own control by more than it must.** `max(100%, 44px)`
     is fine for a small icon and wrong for anything already wide: a 300px-wide button
     would grow an area 300px wide and steal its neighbours' presses. Width is only ever
     stretched up to 44. */
  .pact::before, .toolbtn::before, .navlink::before, .sw::before, .ghost::before,
  .brand::before, .linklike::before, .co-rm::before, .cat::before {
    min-width: 44px; min-height: 44px;
  }

  /* ‹ and › take the height and keep their own width. */
  .prev::before, .next::before { min-height: 44px; }

  /* **A form field a thumb can hit — A24 and E64.** ״טלפון״ and ״מיקוד״ are half-width
     boxes 36px tall on a 390px screen: a press aimed at one, twenty pixels low, lands on
     the page. Unlike the icons these cannot take an invisible box — the box IS the
     control, and a person expects to touch where the text goes. So they grow, which is a
     visible change and the right one: 44 is the floor his own standard sets. */
  /* **⚑ 16px, or the iPhone zooms the whole page — 20/09/26.**
   *
   * Jacki, from his own phone: *"האיפון הקפיץ לי מקלדת וכל הדף גדל."* Safari on iOS zooms
   * the document whenever a field with a font smaller than 16px takes focus, and **every
   * one of the sixteen fields in this checkout was 14px** (measured). The page he was
   * reading jumped and grew, over a keyboard he had not asked for.
   *
   * It is not a preference and it cannot be fixed with `user-scalable=no`, which takes
   * away a person's ability to zoom at all. 16px is the whole of it.
   *
   * Only on a telephone: the desktop keeps his 14px exactly as it is. */
  .co-fields input, .co-fields select, .co-fields textarea,
  .ct-wrap input, .ct-wrap select, .ct-wrap textarea,
  #accFormWrap input, .dsel, .wt-search input {
    font-size: 16px;
  }

  .co-fields input, .co-fields select, .ct-wrap input, .ct-wrap select,
  #accFormWrap input, .dsel {
    min-height: 44px;
  }

  /* **A loud button and a quiet link should not share an edge.** ״כניסה״ and ״שכחתי סיסמה״
     sit in the same row, and a press aimed at the button twenty pixels to one side landed
     on the link — the fault that made the four icons beside a work's title ambiguous, in a
     different row. */
  .ct-actions { gap: 16px; flex-wrap: wrap; }

  /* **The basket line's two pairs, same reason.** ״שנו אפשרויות״ sits beside ״הסרה״ and the
     אספקה chips sit beside each other; at 14px and 8px apart a press twenty pixels off one
     answered as the other. Nothing here changes on a desktop, where a pointer lands where
     it is aimed. */
  .co-acts { gap: 22px; }
  .co-opt { gap: 12px; }
  .co-opt .cat { margin-inline-end: 6px; }
  /* **⚑ `.brand` was in the list above and not in this one — 20/09/26.** It got
     `position: relative` and no hit area at all, so the logo failed on every single page
     while everything beside it passed. A list written twice is a list that disagrees with
     itself; `prev`, `next` and `.linklike` were simply never in either. */
  .pact::before, .closebtn::before, .toolbtn::before, .navlink::before,
  .sw::before, .ghost::before, .brand::before, .prev::before, .next::before,
  .linklike::before, .co-rm::before, .cat::before {
    content: ""; position: absolute; top: 50%; left: 50%;
    transform: translate(-50%, -50%);
    width: 100%; height: 100%;
  }

  /* **⚑ And the row on a work page needed the space first — measured twice, 20/09/26.**
     The four icons beside the title (`.wk-titlerow .wk-acts`) are 37px wide with a **4px**
     gap, so their centres are 41 apart: a 44px box on each **overlapped its neighbour by
     three pixels**, and the neighbour answered a press meant for it — `wkBuyBtn` pressed
     20px to its left opened שיתוף.

     **The first attempt named `.actions`, which is a different row on a different screen,
     and changed nothing.** The check said so, unchanged, which is the only reason it was
     not shipped as a fix.

     8px of gap puts the centres 45 apart. It is the one place on the phone where something
     Jacki laid out moves, and an ambiguous target is worse than a small one. */
  .wk-titlerow .wk-acts { gap: 8px; }

  /* **The two inside the meta line are the exception, and it is geometry.** ״צלם: …״ and
     the ▾ that opens the story wrap onto two lines about 17px apart on a 390px screen, so
     a 44px box on each would cover the other. The line is given room first — the one thing
     here that looks different — and then both can have their full target. */
  .wk-meta, .pp { line-height: 2.1; }
  .pmore::before {
    content: ""; position: absolute; top: 50%; left: 50%;
    transform: translate(-50%, -50%);
    width: max(100%, 44px); height: 40px;
  }

  /* ============================================ what the 20/09 pass left — 28/09/26, E64
   *
   * Measured again with `scripts/touch_targets.py`, which presses the centre of every
   * control and 21px to each side and asks what a finger would land on. Four kinds were
   * still short, and each gets the same invisible box as the rest — nothing painted moves.
   *
   * **The ▾ beside a heading is not in the meta line.** 40px was the geometry of `.wk-meta`
   * and `.pp`, where two lines sit 17px apart; beside an `h1` nothing is that close, so the
   * triangles there (`#homeMore`, `#catMore`) and ״פרטים ▾״ under a collection take 44. */
  .pmore::before { height: 44px; }
  .wk-meta .pmore::before, .pp .pmore::before { height: 40px; }

  /* **☰ — the one control on every page that answered one press in five.** 35 × 31 and
     static, so it is made a positioning context like the others. */
  .menubtn { position: relative; }
  .menubtn::before {
    content: ""; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
    min-width: 44px; min-height: 44px; width: 100%; height: 100%;
  }

  /* **The footer's links, 17px tall** — the most frequent control on the site, one row on
     every address. Their gap is 10px, so 44 wide is 4px either side and never meets the
     next link. */
  .footlinks a, .sitefoot nav a { position: relative; }
  .footlinks a::before, .sitefoot nav a::before {
    content: ""; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
    width: max(100%, 44px); height: 44px;
  }

  /* **The questions on the home page own their whole row, and no more.** They are 25px tall
     and their rows about 38 apart, so a 44px box on each would overlap the next question —
     the ambiguity the note above refuses. Filling the row instead (its 6px of padding each
     side, to the rule between items) leaves no gap a finger can fall into and no overlap. */
  .qa-item { position: relative; }
  .qa-q::before { height: calc(100% + 13px); }

  /* **The other collections under a collection, and the site map's list — same geometry.**
     Names like ״ים״ are 11px wide, 18px apart sideways and 8px between rows: a 44px box on
     each would overlap the next name. Each owns half the gap around it instead — no dead
     spot between two names, and no press that the neighbour answers. */
  .othercols a { position: relative; }
  .othercols a::before {
    content: ""; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
    width: calc(100% + 18px); height: calc(100% + 8px);
  }
  .legal-links li { position: relative; }
  .legal-links a::before { content: ""; position: absolute; inset: -4px 0; }

  /* **The ▾ beside a work's title was under the title.** Its box reached up into the `h1`,
     which is drawn later and on top, so a press above the triangle opened nothing. */
  .wk-titlerow .pmore { z-index: 1; }
}

/* ======================================================= five from his phone, 20/09/26 */

/* **1 · שיתוף — the panel is bigger on a telephone, and closes with a ✕.**
   340px on a 390px screen left the card cramped against its own edges; the ✕ sits where
   every other panel's does, so nothing here is a new convention. */
.sp-x {
  position: absolute; top: 6px; inset-inline-start: 8px;
  background: none; border: 0; font-size: 22px; line-height: 1;
  color: var(--ink-faint); cursor: pointer; padding: 6px 10px;
}
.sp-x:hover { color: var(--ink); }
/* **And the heading makes room for it.** `.sp-head` is a full-width span whose text starts
   at the inline-start edge — the very place the ✕ was put — so the × sat on the ל of
   ״לשלוח את התמונה למישהו:״. The padding is on the text, not a move of the button: the ✕
   belongs in the corner where every other panel keeps it. */
.sp-head { padding-inline-start: 34px; }
@media (max-width: 720px) {
  /* **⚑ `vw`, not `%` — 20/09/26.** `calc(100% - 16px)` is a percentage of the panel's
     containing block, and on a work's page that block has no width of its own: the panel
     opened at 0×0 and the share stopped working. The viewport is the only thing here that
     is certainly 390 wide. */
  .sharepop {
    width: calc(100vw - 16px);
    max-width: 360px;
    padding: 18px 18px 16px;
    gap: 14px;
    bottom: 72px;
  }
  .sharepop .sp-btn { min-height: 44px; }
}

/* **3 · the shading along the bottom of every screen.**
   The five drawers are `position: fixed; bottom: 0` and are pushed off with
   `translateY(101%)` — but each carries `box-shadow: 0 -30px 60px -30px` , which points
   UP. Off-screen or not, the blur bled back onto the last thirty pixels of the page, five
   times over: *"באיפון יש כל הזמן הצללה בחלק התחתון של המסך."*
   The shadow belongs to an OPEN drawer, so it is drawn only when one is. */
.drawer { box-shadow: none; }
.app[data-panel="buy"] ~ #drawerBuy,
.app[data-panel="wallview"] ~ #drawerWall,
.app[data-panel="saved"] ~ #drawerSaved,
.app[data-panel="room"] ~ #drawerRoom {
  box-shadow: 0 -30px 60px -30px rgba(0, 0, 0, .8);
}

/* **5 · the hand is part of the offer, so it looks like something to press.** */
.wksim-offer { cursor: pointer; }

/* **The share panel when it has been moved out of the wall's stage** (20/09/26). Fixed to
   the viewport, because the body is the only ancestor it has left — and centred, because on
   a work's page there is no actions row for it to sit above. */
.sharepop.sp-float {
  position: fixed;
  bottom: 96px;
  left: 50%;
  inset-inline-start: auto;
  transform: translateX(-50%);
  z-index: 40;
}

/* ========================= צעד אחורה — the mosaic, Jacki 22/09/26
 *
 * *"תוריד את האפקט שהתמונה ללא קונטרסט… מעבר עם העכבר מציג מספר שאני לא יודע מהו ושם
 * התמונה. תוריד את שניהם."*
 *
 * Both live in `prototype.css`, which is his stylesheet byte for byte
 * (`tests/test_adoption.py`) and is never edited — so they are answered here, after it.
 *
 * **The fade.** `prototype.css:641` holds every tile at `opacity: .82` in wall mode and
 * lifts it to 1 only under the pointer. It reads as a wash over the whole hang, and on a
 * mosaic of twenty-seven that is twenty-seven photographs shown at less than their best.
 * They are his photographs; the hang shows them whole.
 *
 * **The label.** `prototype.js:665` writes `01 · <the work's name>` into `.tag` and
 * `prototype.css:652` reveals it on hover. The number is the tile's position in the hang,
 * which means nothing to anybody looking at it, and the name belongs on the work's own
 * page. The element is left in the document rather than torn out — it was already
 * invisible except on hover, and `CLAUDE.md` §3 says a change does not delete what it
 * passes. It simply never appears now.
 */
.app[data-mode="wall"] .item { opacity: 1; }
.app[data-mode="wall"] .item:hover { opacity: 1; }
.app[data-mode="wall"] .item:hover .tag,
.app[data-mode="wall"] .item:focus-visible .tag { opacity: 0; }

/* ========================= a collection's own words, Jacki 23/09/26
 *
 * *"2 שדות קלט שיאפשרו לי להכניס מלל + קישורים לדפים אחרים באתר. אחת מתחת לכותרת H1
 * והשנייה בתחתית הדף ממש מעל הפוטר."*
 *
 * The site's own body text, not a new voice: the size, the colour and the measure are
 * `.legal`'s, which is the text page this site already reads with, and the link is the
 * `.ghost.lead` gold it uses everywhere else. A collection page is a page of words with a
 * hang under it, and it should read like the rest of the site.
 */
.catwords {
  max-width: 68ch;
  font-size: 13.5px; line-height: 1.95; color: var(--ink-soft);
}
.catwords p { margin: 0 0 12px; }
.catwords p:last-child { margin-bottom: 0; }
/* **The h2 is as quiet as a photograph's name — Jacki, 23/09/26**, *"ה־H2 לא יכול להיות
 * כל כך גדול ובולט… צריך להיות זהה לשמות התמונות, כנ״ל לגבי המרווח שמעל ומתחת."*
 *
 * He granted `h2` inside these boxes the same day (`richtext.PAGE_TAGS`) and nothing here
 * styled it, so it fell to the browser's own rule — about 20px, bold, with 17px of air
 * above and below. On a page whose title is 15px and unemphasised, the headings inside his
 * own words shouted over everything around them.
 *
 * The size, the weight and the colour are `.wk-head .wk-name`'s, restated rather than
 * re-authored — because what he asked for is that it does not shout, and those three are
 * what shouting is made of.
 *
 * **The spacing is NOT the name's, and he said why — 23/09/26:** *"הערכים של .wk-name
 * נכונים לשם שיושב בראש בלוק, עם התמונה מעליו. כותרת באמצע טקסט היא מקרה אחר… היא נקראת
 * כאילו היא שייכת לפסקה שמעליה במקום לזו שהיא פותחת."* Measured with the words open before
 * he said it: **4px above the heading and 9px below**, so it belonged to the wrong
 * paragraph. The boxes hold bare text and no `<p>` at all, so `.catwords p` never applies
 * and nothing above a heading contributes a margin — the 18px is what makes the measured
 * gap about 22px, and the 5px below is left alone so the heading stays with what it
 * opens. */
.catwords h2 {
  font-size: 15px; font-weight: 400; color: var(--ink-faint);
  margin: 18px 0 5px; line-height: inherit;
}
.catwords a { color: var(--gold); text-decoration: none; border-bottom: 1px solid color-mix(in srgb, var(--gold) 45%, transparent); }
.catwords a:hover { border-bottom-color: var(--gold); }
.catwords-top { margin: 14px 0 0; }
/* Above the footer and clear of the plates, with the rule that separates it from the hang
 * coming from the footer below rather than a second line of its own. */
.catwords-foot { margin: 38px 0 0; }

/* ========================= the page of collections, Jacki 23/09/26
 *
 * *"כשלוחצים על אוספים צריך לקבל דף שיש בו תמונה מייצגת (לכל אוסף) וקישור עליה מוביל לדף
 * האוסף."*
 *
 * One picture per collection and the whole tile is the link. The type is the site's own —
 * the title quiet and unemphasised, as `design-principles.md` §4 requires of a title
 * anywhere on this site, with the photograph doing the talking.
 */
.colindex {
  display: grid; gap: 28px 20px; margin-top: 10px;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
}
.coltile { display: block; text-decoration: none; color: inherit; }
.coltile img {
  display: block; width: 100%; height: auto; aspect-ratio: 3 / 2;
  object-fit: cover; box-shadow: var(--shadow);
}
.coltile-t {
  display: block; margin-top: 10px;
  font-size: 14px; color: var(--ink); font-weight: 400;
}
.coltile-n { display: block; font-size: 12px; color: var(--ink-faint); margin-top: 2px; }
.coltile:hover .coltile-t { color: var(--gold); }

/* The arrow beside a collection's name, and the words it reveals. The arrow is `.pmore`,
 * the site's own; this only puts the block that follows it back on its own line. */
#catWords { margin-top: 12px; }

/* The collection's name and the arrow that opens its text, on one line — Jacki, 23/09/26:
 * *"זה נראה כמו ניסיון לתחמן את גוגל! תזיז את החץ בצמוד לכותרת."* The arrow had sat after
 * the empty lead, which put it alone at the far side of the screen: a mark floating over
 * hidden words, which is what cloaking looks like. Beside the name it reads as the control
 * it is. `baseline`, so it sits on the title's line rather than in the middle of its box. */
.pgtitle-row { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.pgtitle-row .pgtitle { margin-bottom: 0; }

/* ״פרטים״ at the foot of a collection, and the other collections under it — Jacki,
 * 23/09/26. The button is `.pmore`, the site's own triangle, with a word in front of it so
 * it says what it opens. The names are the footer's own quiet type: they are a way out,
 * not a call to action. */
.catdet { font-size: 12px; color: var(--ink-faint); }
.catdet:hover { color: var(--ink-soft); }
.othercols {
  display: flex; flex-wrap: wrap; gap: 8px 18px;
  margin: 26px 0 0; padding-top: 18px; border-top: 1px solid var(--line);
  font-size: 12.5px;
}
.othercols a { color: var(--ink-soft); text-decoration: none; border-bottom: 1px solid transparent; }
.othercols a:hover { color: var(--ink); border-bottom-color: var(--line); }


/* ========================= the home page's title and his words, Jacki 23/09/26
 *
 * *"תוסיף בדף הבית H1 שיש בו תמונות לסלון לבית ולמשרד, ואז משולש קטן שפותח את המלל."*
 *
 * **The stage joins the flow for this one view, and that is the whole of the change.**
 * `prototype.css:154` puts the stage at `position: absolute; inset: 0`, so anything added
 * beside it would have been drawn OVER the photograph — and over a portrait one there is
 * no empty band to put it in. The home view makes `.main` a column instead: the title
 * takes the height of one quiet line and the stage takes everything left, which the
 * layout engine already reads live (`prototype.js` measures `stage.clientHeight` on every
 * pass), so the hang re-fits itself rather than being told a number.
 *
 * Nothing else is touched: every other address keeps the absolute stage it had, because
 * the title is only rendered on `/`.
 */
/* **The first screen is the photograph, and the rest is under the fold — Jacki,
 * 23/09/26.** *"התמונה צריכה לתפוס מקסימום שטח… ליצור וואו כשמישהו נכנס לדף הבית"*, and
 * *"מבחינתי שיהיה סקרול כדי לראות אותן"*.
 *
 * Until now the whole page was one screen that could not scroll, so every line added — the
 * title, his words, the questions — came out of the photograph, and it shrank on every
 * pass. Now `.home-screen` is exactly the height of the glass and holds the title and the
 * hang; the questions sit below it and the page scrolls to them. The hang is back to what
 * it was before any of this was added.
 *
 * **Only in this view**, because `.main` is `overflow: hidden` everywhere else by his
 * stylesheet and the drawers depend on it. */
.app[data-view="gallery"] .main { display: block; overflow-y: auto; }
.app[data-view="gallery"] .home-screen {
  height: 100%; display: flex; flex-direction: column;
}
.app[data-view="gallery"] .stage {
  position: relative; inset: auto; flex: 1 1 auto; min-height: 0;
}
/* **And none of it belongs to any other screen — Jacki, 23/09/26**, *"כשאני בסל קניות
 * ומסיר ממנו הכל פתאום אני רואה את ה־H1 והמלל כולל השאלות והתשובות של דף הבית"*.
 *
 * One document is served at every address (`CLAUDE.md` §11a) and the view is a data
 * attribute, so the home page's own blocks sat in the document while the basket, the
 * checkout and everything else were shown — hidden by nothing at all. The stage has had
 * this rule since the prototype; these two never got one. */
.app:not([data-view="gallery"]) .home-screen,
.app:not([data-view="gallery"]) .home-head,
.app:not([data-view="gallery"]) .home-colls,
.app:not([data-view="gallery"]) .home-qa { display: none; }
/* **Under the photograph, with room around it — Jacki, 23/09/26**, *"ה־H1 והמשולש יורדים
 * למטה מתחת לאיקונים, תרווח יותר ממה שמרווח עכשיו שאלות ותשובות, ומתחת למשולש שבאמצע
 * תרווח שוב"*. Forty-eight above the title and forty-eight under the triangle — more than
 * the thirty-four the questions had, which is the measure he asked for it to beat. */
.home-head {
  max-width: 1120px; width: 100%; margin: 0 auto; padding: 48px 30px 0;
}
/* **⚑ A line box that changes when the font arrives moves the photograph — 24/09/26.**
 * Measured from the first paint: this block was 80px tall, and 86px once the webfont
 * swapped in, 350ms later. It sits in the same column as the hang, so the stage lost six
 * pixels and every photograph was re-sized a second time — part of what Jacki saw as
 * *"התמונה קטנה יותר ואחרי שנייה היא פתאום גדלה"*.
 *
 * The heights are fixed in pixels rather than left to the font: 24px for the title's line
 * and 14 for the triangle's. Nothing moves when the face changes, and the type is
 * unchanged — `.pgtitle` is still 18px at weight 400. */
.home-head .pgtitle { line-height: 24px; }
.home-head .pmore { line-height: 14px; height: 14px; }
.home-head .pgtitle-row { min-height: 42px; }
/* **Centred, with the arrow under the middle of it — Jacki, 23/09/26:** *"תמרכז את H1
 * ואת החץ הקטן תמקם מתחת בדיוק באמצע ה־H1."* Everywhere else on the site the arrow sits
 * BESIDE the name, because there it is one line in a page of text; the front door has one
 * line and a photograph, and a mark beside it reads as a stray character.
 *
 * A column with `align-items: center` puts the arrow under the centre of whatever the
 * heading turns out to be — one word or a full sentence, one line or two — rather than
 * under a number I measured once. The words stay right-aligned: centred prose in Hebrew
 * is harder to read, and he asked for the heading and the arrow. */
.home-head .pgtitle-row {
  flex-direction: column; align-items: center; gap: 2px;
}
.home-head .pgtitle { text-align: center; }
.home-head .pmore { line-height: 1; }
/* His words open UNDER the title and push the hang down rather than covering it — the
 * same `.catwords` type, measure and link colour as a collection's page. */
.home-head .home-words { margin: 10px 0 0; }



/* ========================= the questions and answers on the home page, Jacki 23/09/26
 *
 * *"תבנה את ה־QA."* Three of them, his own words from the live site, and the whole block
 * is assembled from controls that already exist: `.pmore` with a word in front of it, the
 * way ״פרטים ▾״ opens a collection's details, and `.catwords` for the answer itself so an
 * answer reads exactly like every other paragraph he writes.
 *
 * **Two levels of press, and that is the point.** Opening the section costs three lines;
 * opening one answer costs a paragraph. A block that showed everything at once would push
 * the photograph off a telephone — and the answers are in the document either way, which
 * is what the `FAQPage` node is allowed to describe.
 */
/* **Under the hang and against the right edge — Jacki, 23/09/26**, *"תעביר למטה… תצמיד
 * לימין לא למרכז."* The head above the photograph is centred because it is one line; this
 * is a column of sentences, and a column of Hebrew sentences reads from the right margin.
 *
 * `flex: none` in the home view's column, so the hang keeps taking what is left: opening
 * an answer makes the photograph smaller and never pushes anything off the screen. */
.home-qa {
  max-width: 1120px; width: 100%; margin: 0 auto;
  padding: 48px 30px 32px; text-align: start;
}
/* **A vertical swipe is the page, a horizontal one is the wall.** The hang takes the
 * whole first screen on a phone, so without this the only gesture that could reach the
 * questions would be a scroll that begins outside the photograph — which on a phone is
 * almost nowhere. `pan-y` hands the browser the vertical direction and leaves the
 * horizontal drag exactly as it was. */
.app[data-view="gallery"] .stage { touch-action: pan-y; }
/* **Room between the hand and the first question — Jacki, 23/09/26**, from a photograph
 * of his own iPhone. The hand is pinned to the stage's bottom edge, so the space between
 * the two can only come from here, and the hang gives it up — which is what `flex: 1` is
 * for.
 *
 * **It sits AFTER the rule above and not in the phone block higher up the file**, because
 * a media query adds no specificity: `.home-qa` there and `.home-qa` here are both one
 * class, so the later one wins at every width. The first version of this was written up
 * there, measured 8px instead of 24, and took the side gutter with it — the page was
 * padded 30px on a 390px screen. `CLAUDE.md` §8 names this trap by name. */
@media (max-width: 720px) {
  .home-head { padding: 40px 16px 0; }
  .home-qa { padding: 40px 16px 24px; }
}
.qa-open { font-size: 12.5px; }
.qa-list { max-width: 68ch; margin: 0; }
.qa-item { padding: 6px 0; border-top: 1px solid var(--line); }
.qa-item:first-child { border-top: 0; }
/* The question carries the body's own size and colour: it is a sentence, not a label, and
 * `.pmore`'s 12px would make his wording smaller than the answer under it. */
/* **The site's own type, and nothing invented — Jacki, 23/09/26:** *"למה הפונטים של
 * השאלות והתשובות שונים מהפונטים הסטנדרטים של האתר בצבע בבהירות בהדגשה. למה להמציא
 * משהו?"* He was right: I had made the question darker than the body to tell it from its
 * answer, which is a third colour on a page that has two. The question is now exactly
 * `.catwords` — the type every other paragraph he writes is set in — and what tells it
 * apart is the triangle beside it and the rule above it. Hover is `.pmore`'s own. */
/* **Quieter again — Jacki, 23/09/26:** *"השאלות עדיין מוצגות בפונטים בולטים מדי."* The
 * answer keeps the body's own size and colour; the question steps one further back, to
 * `--ink-faint` at 13px — the pair the site already uses for a photograph's name under
 * its picture. A question is a door, not a statement. */
.qa-q {
  font-size: 13px; line-height: 1.95; color: var(--ink-faint);
  text-align: start; padding: 0; white-space: normal;
}
.qa-q:hover { color: var(--ink-soft); }
.qa-a { margin: 4px 0 8px; }
/* The sentence under the three, in the body's own quiet type — it is a way out, not a
 * call to action, so it is `--ink-soft` with the site's gold on the link, like every
 * other link in a paragraph here. */
.qa-more {
  margin: 12px 0 0; font-size: 13.5px; line-height: 1.95; color: var(--ink-soft);
}
.qa-more a {
  color: var(--gold); text-decoration: none;
  border-bottom: 1px solid color-mix(in srgb, var(--gold) 45%, transparent);
}
.qa-more a:hover { border-bottom-color: var(--gold); }

/* ========================= the results carry the name and nothing else, 24/09/26
 *
 * Jacki: *"בתוצאות תוריד מתחת לתמונות את המלל שהכנסת. כל מה שישאר יהיה שם התמונה בלבד."*
 * The photographer, the מק״ט and the story's triangle belong to the work's own page; under
 * a grid of results they are three lines of furniture under every picture. The markup is
 * untouched — one screen shows less of it.
 */
#srResults .pp,
#srResults .ptext { display: none; }

/* ========================= the wall is not shown until it has been placed, 24/09/26
 *
 * Jacki: *"התמונה בדף הבית קטנה, קופצת לקצת יותר גדולה ואז קופצת לגדולה!"* Measured from
 * the first frame: **1600×800 at 101ms** (the server's `<img>` at its own size), **1408×704
 * at 483ms** (the width constrained), nothing at 578ms, and **1003×501 at 1281ms** — three
 * sizes before it settles.
 *
 * **The markup has to be there** — the wall is in the HTML so a crawler reads a real
 * `<img>` with its `srcset` and its `alt` (`seo-requirements.md`), and `.item` is
 * positioned by the layout engine, so until that runs the browser lays each photograph out
 * at its intrinsic size. Nothing in CSS can guess what the engine will compute.
 *
 * So the track is invisible until the engine has placed it once, and `layout()` marks the
 * app the first time it runs. **`visibility`, not `display`:** the boxes keep their place
 * in the document, the images still load and decode during that time, and the reveal costs
 * no second layout. It is a fraction of a second now that the wall is built before the
 * photographs arrive.
 */
.app:not([data-placed="1"]) #track { visibility: hidden; }

/* ⚑ **His sentence is long on purpose, so it must WRAP — 25/09/26.**
   *"חיפוש חכם באיפון: המשפט שממליץ לחפש בהרחבה ארוך מדי והוא נחתך."* Measured on an
   iPhone profile (390 px): the control is **477 px wide inside a 358 px bar**, its left
   edge at **−103**, because `.srbar .ghost { white-space: nowrap }` in his own stylesheet
   was written for the two-word label this button used to carry (״לתאר משהו אחר״).

   **The wording is his and does not change** (`CLAUDE.md` §8 — wording is UI): the
   sentence asks the visitor for detail because detail is what the engine can answer.
   What changes is that it is allowed to occupy more than one line. An id outranks the
   class, so this needs no `!important`. */
#srAgain {
  white-space: normal;
  max-width: 100%;
  text-align: right;
  line-height: 1.5;
}


/* **The contact form's trap field — 27/09/26, E66.** Off the screen, not `display: none`
 * (which some robots skip), so a person never sees or reaches it. */
.ct-trap { position: absolute; left: -10000px; width: 1px; height: 1px; opacity: 0; }

/* **The recommendation cards are real photographs now — 27/09/26.** The mockup's card drew
 * a canvas (`.rec canvas`, prototype.css); the server writes the customer's own photograph
 * as an `<img>`, so it takes the same place and the same box. Two photographs in one card
 * stand one above the other, as they did on the old page. */
.rec picture { display: block; }
.rec picture img { width: 100%; height: auto; display: block; }
.rec .rec-note { display: block; margin-top: 8px; font-size: 12.5px; color: var(--ink-faint); }
.rec a.more { text-decoration: none; }

/* **The menu between 900 and 1100 pixels — 27/09/26.** Adding ממליצים (Jacki, the same
 * day) made the top row too tight there: the four tool buttons wrapped and the header grew
 * from 74 to 90 pixels. Below 900 his stylesheet already sets the menu at 12px with a
 * 12px gap; this carries the same size, with a 10px gap, up to 1100. Measured: the header
 * is 74 or less at every width in the range, and 57 from 1024 up — no taller than before
 * the link was added. */
@media (min-width: 900px) and (max-width: 1099px) {
  .topnav { gap: 10px; }
  .topnav .navlink { font-size: 12px; }
}

/* **צעד אחורה only where there is a hang — Jacki, 27/09/26:** *"הכפתור צעד אחורה צריך
 * להופיע רק בדף הבית ובדפי האוספים!"* The wall at `/` and a collection's own page are the
 * two places it shows the whole hang; everywhere else it was a control with nothing to do
 * (and on the results page it did nothing at all). The page OF collections is tiles, not a
 * hang, so it goes there too. These rules only hide: the phone's own rules that already
 * hide it stay as they are. */
.app:not([data-view="gallery"]):not([data-view="category"]) #modeBtn { display: none; }
.app[data-view="category"]:has(.colindex) #modeBtn { display: none; }

/* **The hang on a collection's own address — 27/09/26.** Jacki: *"נכנסתי לאוסף. צעד
 * אחורה מסך ריק, להתקרב מסך ריק."* On `/` the stage stands inside `.home-screen`, which is
 * the height of the glass, and the rule above makes it a flex child of that. A collection's
 * page has no `.home-screen` — the server writes it only on `/` — so the same rule left the
 * stage a flex child of nothing: 0 pixels tall, the hang laid out correctly inside a box
 * nobody could see. Where it stands directly in `.main`, it fills `.main`, as his own
 * stylesheet has it (`.stage { position: absolute; inset: 0 }`). */
.app[data-view="gallery"] .main > .stage { position: absolute; inset: 0; }

/* אודות — the old page's portrait (Jacki, 28/09/26). It replaced the canvas band, the
 * last canvas on that page (open-list E27). */
.prose .about-portrait { margin: 0; }
.prose .about-portrait img {
  display: block; width: 300px; max-width: 100%; height: auto; box-shadow: var(--shadow);
}

/* ======================================== the quiet grey meets AA contrast — 29/09/26, E3
 *
 * Jacki, choosing it as a trial: *"תוכל לעשות את 1 ואז נראה עם זה בסדר ואם לא נחזור
 * אחורה?"* The accessibility statement claims WCAG AA, and axe found one colour failing on
 * every wall: `--ink-faint`, the site's quiet grey (titles, מק״ט, labels, captions, the
 * footer), at 2.9–3.6 against the 4.5 the standard requires for text. Each wall's grey is
 * moved just far enough to reach 4.6 — still lighter than `--ink-soft`, so the titles stay
 * quiet. `prototype.css` is his file byte for byte, so the override lives here, with his
 * own selectors so it wins by order alone.
 *
 * **To go back: delete this block.** Before → after, and the contrast each reaches:
 *   dark     #6E6D67 → #7F7E78   3.64 → 4.6
 *   gallery  #8A8C83 → #6B6D64   3.02 → 4.6
 *   cream    #8D8677 → #6D6657   2.94 → 4.6
 *   white    #8A8A8A → #757575   3.45 → 4.6
 */
:root, [data-wall="dark"] { --ink-faint: #7F7E78; }
[data-wall="gallery"] { --ink-faint: #6B6D64; }
[data-wall="cream"] { --ink-faint: #6D6657; }
[data-wall="white"] { --ink-faint: #757575; }

/* ======================================= a tall photograph fits the screen — 29/09/26
 *
 * Jacki: *"בתמונות ארוכות הן תופסות גודל עצום בדף חייבים להגביל אותם בגובה (יגרור גם הגבלת
 * רוחב כמובן)."* Measured at 1440×900: a 2:3 work was drawn 1060 × 1590 — nearly two
 * screens tall, never seen whole. The height is now held to the screen less the header and a
 * margin, the width follows from the proportions, and a narrow photograph is centred. A wide
 * one is already shorter than the cap and does not move; on a telephone the tall ones already
 * fit (537 of 844) and do not move either.
 *
 * **The width is capped, never left to `auto`.** The first version let the width follow
 * from a height cap, and on a telephone `auto` meant the downloaded file's own size: the tall
 * works shrank from 358px to 260. So the picture keeps `width: 100%` and its width is held to
 * the cap × its own proportions — `--r`, width ÷ height, written by the server beside the
 * `width`/`height` it already writes. Centred, the ⌕ on hover stays on the photograph.
 */
.wk-hero img { max-width: min(100%, calc((100dvh - 150px) * var(--r, 10))); margin-inline: auto; }

/* ============================== הוספה לסל on a set's page — stage 6 of order-flows.md
 * The table above is the price list; this row chooses from it. Its controls are the
 * drawer's own: a `.fl` label over a select, and the drawer's `.buybtn`.
 */
/* Rebuilt 02/10/26 from the drawer's own parts: two columns, the types and the size. */
.st-buy { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
.st-buy .st-sheenbox { margin: 6px 0 10px; }
/* The drawer's set box has the drawer's three columns: the set's picture, the types, the
   size — as a photograph's drawer has the product, the types, the choices (03/10/26). */
#dSetSlot .st-buy { grid-template-columns: 1.05fr .95fr 1fr; }
.st-buy .st-pic { display: block; width: 100%; height: auto; border-radius: 3px; }
.st-line { margin-top: 14px; }
.st-del { margin-top: 14px; display: flex; flex-direction: column; gap: 6px; max-width: 260px; }
.st-sizes { list-style: none; margin: 0 0 12px; padding: 0; display: flex; flex-wrap: wrap;
            gap: 4px 16px; font-size: 13px; color: var(--ink-soft); }
.st-buy .foot { margin-top: 14px; }
/* **₪ and the number on one line — 02/10/26**, *"השקלים צריכים להופיע עם המספר באותה שורה"*. */
.st-price { white-space: nowrap; }

/* ======================================== the depth of a print — 01/10/26
 * Jacki: "להבליט יותר בכל הדפים את העומק של התמונות שיהיה כמו באתר הישן." Measured on
 * the old site, on the category tiles and on the work page's photograph alike:
 * `box-shadow: 6px 6px 6px 0 rgb(136,136,136)` — offset right and down, a print's thick
 * edge standing off the wall. The prototype's soft pool under the photograph read as
 * floating. One token, so every photograph that already uses it changes together; the
 * prototype's file is his stylesheet byte for byte and is not edited (§8).
 * The three light walls only: the dark wall lights its photographs from around them
 * (a deliberate design, and the old site had no dark wall to copy). */
[data-wall="gallery"],
[data-wall="cream"],
[data-wall="white"] { --shadow: 6px 6px 6px 0 rgb(136, 136, 136); }

/* ============================================ the site map in two columns — 01/10/26
 * Jacki: "תמונות בעמודה ימנית ואת כל היתר בעמודה שמאלית." The first column is the right one
 * in this right-to-left page, and it holds the photographs. The page's text width (68ch)
 * is for prose; a two-column list takes the page's own width. On a telephone the columns
 * stack, the short one first — pages, collections and information before a hundred
 * photographs. */
.legal:has(> .legal-cols) { max-width: none; }
.legal-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 0 48px; align-items: start; }
.legal-cols .legal-col > .legal-h3:first-child { margin-top: 0; }
@media (max-width: 700px) {
  .legal-cols { grid-template-columns: 1fr; }
  .legal-cols .legal-col:first-child { order: 2; margin-top: 20px; }
}

/* ============================== a set's purchase block on a telephone — 02/10/26
 * One column, held to the screen (`.buy-in`'s grid once sized it to a 559px table and
 * cut everything off the left edge), and the chips wrap.
 */
@media (max-width: 760px) {
  .st-buy, #dSetSlot .st-buy { grid-template-columns: minmax(0, 1fr); }
  .st-buy .chips { flex-wrap: wrap; }
}

/* ============================== a מק״ט keeps its own order — 04/10/26
 * `750_2834` was drawn ״2834_750״ under the photograph: inside a Hebrew line the two
 * number groups are reordered. The מק״ט is isolated and left-to-right wherever it is
 * drawn; the set's line already carried dir="ltr" in the markup, the work's did not.
 */
.psku { direction: ltr; unicode-bidi: isolate; }

/* ============================== the sentence above the home page's photograph — 05/10/26
 * Jacki: bold and centred, **taking nothing from the photograph** (*"למה לקצר את הדף?"*) and at
 * **one height for every photograph** (*"גובה קבוע אחד לכל התמונות"*). It is out of the flow, over
 * the band the tallest photograph leaves free; `layout()` in prototype.js sets its `top` and
 * marks it placed. Until then it is not shown.
 *
 * On a telephone the two arrows stand over the photograph, one at each side; the sentence is one line wide between where they can reach, so it is
 * centred between them and may take two lines.
 */
.app[data-view="gallery"] .home-screen { position: relative; }
.home-line {
  position: absolute; left: 0; right: 0; top: 0; z-index: 2; margin: 0; padding: 0 16px;
  text-align: center; font-weight: 700; font-size: 19px; line-height: 24px;
  color: var(--ink, #2b2622); pointer-events: none; visibility: hidden;
}
.home-line[data-placed] { visibility: visible; }
@media (max-width: 720px) {
  .home-line { font-size: 15px; line-height: 20px; padding: 0 12px; }
}

/* ============================== the collections' pictures under the home page's first screen
 * 05/10/26. `.colindex` and `.coltile` are the page of collections' own; this gives the band
 * its measure and its quiet name. Its view rule is beside `.home-head`'s — a block added to
 * `.main` shows on every screen until a rule says otherwise.
 */
.home-colls { display: block; max-width: 1120px; width: 100%; margin: 0 auto; padding: 40px 30px 0; }
.home-colls-t { margin: 0 0 14px; font-size: 12px; letter-spacing: .14em; color: var(--ink-faint); }
@media (max-width: 720px) { .home-colls { padding: 28px 16px 0; } }

/* ============================== ״לכל האוספים״ — the hand's twin, 05/10/26
 * It carries `.rotatehint` so it IS the same half-circle, rising from the same bottom edge;
 * these rules only put it in the other corner. From 900px the hand stands 44px from the
 * inline start, so this stands 44px from the inline end. Under 900px the hand used to be
 * centred at the foot; with a twin the two share that edge, one at each side (his word).
 * `#stage:has(...)` so the hand moves only where the twin exists, and `offer-in` because
 * the hand's own keyframes end on a centring transform that outlives the animation.
 */
.rotatehint.colls-cue { text-decoration: none; gap: 2px; padding-top: 18px; }
.rotatehint.colls-cue svg { width: 26px; height: 26px; }
.home-colls { scroll-margin-top: 12px; }
@media (min-width: 900px) {
  .rotatehint.colls-cue { inset-inline-start: auto; inset-inline-end: 44px; }
}
@media (max-width: 899px) {
  #stage:has(.colls-cue) .rotatehint {
    left: auto; transform: none; inset-inline-start: 8px;
    width: calc(50% - 12px); max-width: 214px; animation-name: offer-in;
  }
  #stage:has(.colls-cue) .rotatehint.colls-cue { inset-inline-start: auto; inset-inline-end: 8px; }
}

/* ---- the crumb trail, above the footer — Jacki, 07/10/26 ----
 *
 * ״תוסיף פירורי לחם גלויים״, and where: ״בתחתית הדף מעל הפוטר״. `.crumbs` itself is the
 * prototype's rule (12px, faint, wrapping); the prototype styled its crumbs as buttons
 * above the photograph, and these are real links at the foot of the page, so what is
 * added here is the anchors and the distance to the footer's line.
 */
.page .crumbs { margin: 40px 0 0; align-items: baseline; }
.crumbs + .sitefoot { margin-top: 12px; }
.crumbs a {
  color: var(--ink-soft);
  text-decoration: none;
  border-bottom: 1px solid transparent;
}
.crumbs a:hover { color: var(--ink); border-bottom-color: var(--ink-faint); }
.crumbs [aria-current] { color: var(--ink-soft); }
@media (max-width: 899px) {
  /* A finger needs more than a 12px line to land on. */
  .crumbs { row-gap: 2px; }
  .crumbs a, .crumbs [aria-current] { padding: 8px 0; }
}


/* The request form's fields and button are their own block since 07/10/26 (E104): one way
 * to send on every device. The same 14px the fields had inside the desktop block. */
#rqSendRoute { margin-top: 14px; }
