/* ============================================================
   VESTIGE — catalogue, piece detail and forms

   Supplements assets/css/vestige.css, which is the approved Phase 0
   stylesheet and is not modified. This file covers only what the
   prototype never had: a filterable catalogue, a piece record page,
   pagination and public forms.

   Every colour is a theme token. There is no literal #FFFFFF here,
   and tools/check_no_white.php fails the build if one appears.
   ============================================================ */

/* ------------------------------------------------------ breadcrumbs */
.crumbs{
  display:flex;flex-wrap:wrap;gap:.5rem;align-items:center;
  font-family:var(--serif-ui);font-size:.6rem;letter-spacing:.2em;
  text-transform:uppercase;color:var(--muted);
  margin-bottom:2.2rem;
}
.crumbs a{color:var(--brass);text-decoration:none;transition:color .4s ease}
.crumbs a:hover{color:var(--gold)}
.crumbs b{color:var(--parchment-dim);font-weight:400}

/* ------------------------------------------------------- flashes */
.flashes{padding-top:2rem}
.flash{
  padding:.85rem 1.1rem;margin:0 0 .7rem;
  border:1px solid var(--filigree);
  border-inline-start:2px solid var(--gold);
  background:var(--surface);
  font-size:.95rem;color:var(--parchment-dim);
}
.flash--err{border-inline-start-color:var(--crimson);color:var(--parchment)}
.flash--warn{border-inline-start-color:var(--brass)}

/* ------------------------------------------------- catalogue layout */
.cat-layout{
  display:grid;
  grid-template-columns:236px 1fr;
  gap:clamp(1.6rem,3vw,3.4rem);
  align-items:start;
}
@media (max-width:900px){ .cat-layout{grid-template-columns:1fr} }

.filters{position:sticky;top:96px}
@media (max-width:900px){ .filters{position:static} }
.filters-group{margin-bottom:1.9rem}
.filters-label{
  display:block;font-family:var(--serif-ui);font-size:.58rem;letter-spacing:.26em;
  text-transform:uppercase;color:var(--brass);margin-bottom:.8rem;
}
.filters input[type=search],.filters input[type=number],.results-bar select{
  width:100%;background:var(--obsidian-deep);color:var(--parchment);
  border:1px solid var(--filigree);padding:.55rem .7rem;
  font-family:var(--serif-body);font-size:.92rem;
}
.filters input:focus,.results-bar select:focus{
  outline:none;border-color:var(--filigree-lit);
}
.filters-list{list-style:none;margin:0;padding:0}
.filters-list a{
  display:flex;justify-content:space-between;align-items:baseline;gap:.6rem;
  padding:.34rem 0;color:var(--parchment-dim);text-decoration:none;
  font-size:.94rem;transition:color .4s ease;
}
.filters-list a:hover{color:var(--gold-pale)}
.filters-list a.on{color:var(--gold)}
.filters-list i{font-style:normal;font-size:.7rem;color:var(--muted)}
.filters-sub{list-style:none;margin:.2rem 0 .6rem;padding-inline-start:.9rem;
  border-inline-start:1px solid var(--filigree)}
.filters-sub a{font-size:.87rem;padding:.24rem 0 .24rem .7rem}
.filters-row{display:flex;gap:.5rem}
.filters-check,.chip{
  display:flex;align-items:center;gap:.45rem;margin-top:.7rem;
  font-size:.87rem;color:var(--parchment-dim);cursor:pointer;
}
.chips{display:flex;flex-wrap:wrap;gap:.4rem}
.chip{
  margin:0;padding:.24rem .55rem;border:1px solid var(--filigree);
  font-size:.8rem;transition:border-color .4s ease,color .4s ease;
}
.chip:hover{border-color:var(--filigree-lit)}
.chip.on{border-color:var(--gold);color:var(--gold-pale)}
.chip input,.filters-check input{accent-color:var(--gold);width:auto}
.chip i{font-style:normal;font-size:.68rem;color:var(--muted)}
.btn-full{width:100%;text-align:center;margin-top:.4rem}
.filters-clear{
  display:block;text-align:center;margin-top:.7rem;font-size:.8rem;
  color:var(--muted);text-decoration:none;
}
.filters-clear:hover{color:var(--gold-soft)}

.results-bar{
  display:flex;justify-content:space-between;align-items:center;gap:1rem;
  flex-wrap:wrap;padding-bottom:1.1rem;margin-bottom:1.6rem;
  border-bottom:1px solid var(--filigree);
  font-family:var(--serif-ui);font-size:.6rem;letter-spacing:.2em;
  text-transform:uppercase;color:var(--muted);
}
.sorter{display:flex;align-items:center;gap:.6rem}
.results-bar select{width:auto;padding:.32rem .5rem;font-size:.78rem;
  font-family:var(--serif-body);letter-spacing:0;text-transform:none}

.empty{
  padding:3.5rem 0;text-align:center;color:var(--muted);
  font-size:1.05rem;line-height:1.8;
}
.empty a{color:var(--gold-soft)}

.pager{
  display:flex;justify-content:space-between;align-items:center;gap:1rem;
  margin-top:3rem;padding-top:1.4rem;border-top:1px solid var(--filigree);
  font-family:var(--serif-ui);font-size:.6rem;letter-spacing:.2em;
  text-transform:uppercase;color:var(--muted);
}
.pager a{color:var(--gold-soft);text-decoration:none;transition:color .4s ease}
.pager a:hover{color:var(--gold-pale)}

/* the count badge added to the prototype's category tiles */
.cat-count{
  font-family:var(--serif-ui);font-size:.6rem;letter-spacing:.16em;
  color:var(--muted);margin-inline-start:auto;padding-inline-end:1rem;
}

/* ------------------------------------------------------ piece detail */
.piece-detail{
  display:grid;grid-template-columns:1.05fr 1fr;
  gap:clamp(1.8rem,4vw,4.5rem);align-items:start;
}
@media (max-width:940px){ .piece-detail{grid-template-columns:1fr} }

.plates{position:sticky;top:96px}
@media (max-width:940px){ .plates{position:static} }
/* The plate on a piece page.

   It used to be a locked 4/5 box with `object-fit:cover`, so a landscape
   photograph — a painting, a long console, a wide mirror — lost about two
   fifths of its width and the remaining strip was stretched to fill the
   height. The client's note is exact: not complete, and bad quality.

   The plate now takes its shape from the photograph itself. `--ar` is written
   into the element from the stored dimensions and clamped, so a panorama
   cannot make the page absurdly wide and a very tall piece cannot push the
   record off the screen; within that range the box matches the picture and
   there is nothing to crop. `contain` is the guarantee: at the two extremes,
   where the clamp bites, the photograph is letterboxed on the dark ground
   rather than cut.

   Nothing needs a fallback: the ratio defaults to 4/5 in the custom property,
   which is exactly what the page did before. */
.plate-main{
  margin:0;background:var(--obsidian-deep);
  border:1px solid var(--filigree);overflow:hidden;
}
.plate-main img{
  display:block;width:100%;height:auto;
  aspect-ratio:var(--ar,4/5);
  object-fit:contain;
  filter:brightness(.96) saturate(.95);
}
.plate-strip{display:flex;gap:.55rem;margin-top:.55rem;flex-wrap:wrap}
.plate-thumb{
  width:74px;height:74px;padding:0;cursor:pointer;overflow:hidden;
  background:var(--obsidian-deep);border:1px solid var(--filigree);
  transition:border-color .4s ease;
}
/* Contained here too: a 74px square crop of a wide picture is a texture
   swatch, not a thumbnail of the thing it is supposed to identify. */
.plate-thumb img{width:100%;height:100%;object-fit:contain;padding:2px;display:block}
.plate-thumb:hover{border-color:var(--filigree-lit)}
.plate-thumb.on{border-color:var(--gold)}
.plate-none{
  margin-top:1rem;font-size:.85rem;color:var(--muted);text-align:center;
  font-family:var(--serif-ui);letter-spacing:.14em;text-transform:uppercase;
}

.tag-reserved{
  display:inline-block;margin:0 0 1rem;padding:.24rem .7rem;
  border:1px solid var(--brass);color:var(--gold-pale);
  font-family:var(--serif-ui);font-size:.58rem;letter-spacing:.24em;
  text-transform:uppercase;
}
.record-title{
  font-family:var(--serif-display);font-weight:400;
  font-size:clamp(1.8rem,1.3rem + 1.7vw,2.9rem);line-height:1.16;
  color:var(--parchment);margin:.6rem 0 1.1rem;
}
.record-lede{
  font-size:1.06rem;line-height:1.85;color:var(--parchment-dim);
  margin:0 0 1.8rem;max-width:56ch;
}
.record-price{
  font-family:var(--serif-display);font-size:2rem;color:var(--gold-pale);
  margin:0 0 .3rem;letter-spacing:.02em;
}
.record-price.por{
  font-family:var(--serif-ui);font-size:.78rem;letter-spacing:.22em;
  text-transform:uppercase;color:var(--gold-soft);
}
.record-pricenote{font-size:.9rem;color:var(--muted);margin:.2rem 0 1.6rem;max-width:52ch}
.record-cta{display:flex;gap:.7rem;flex-wrap:wrap;margin:1.6rem 0 2rem}
.record-grade{
  font-family:var(--serif-ui);font-size:.6rem;letter-spacing:.2em;
  text-transform:uppercase;color:var(--muted);margin:0 0 1.4rem;
}
.record-grade b{color:var(--gold-pale);font-weight:400;margin-inline-start:.5rem}

.spec{width:100%;border-collapse:collapse;margin:0 0 1.6rem}
.spec caption{
  text-align:start;font-family:var(--serif-ui);font-size:.58rem;
  letter-spacing:.26em;text-transform:uppercase;color:var(--brass);
  padding-bottom:.8rem;
}
.spec th,.spec td{
  padding:.62rem .2rem;text-align:start;vertical-align:top;
  border-bottom:1px solid var(--filigree);font-size:.94rem;line-height:1.6;
}
.spec th{
  width:36%;font-family:var(--serif-ui);font-weight:400;font-size:.62rem;
  letter-spacing:.16em;text-transform:uppercase;color:var(--muted);
  padding-top:.75rem;
}
.spec td{color:var(--parchment-dim)}
.record-caveat{
  font-size:.9rem;line-height:1.75;color:var(--muted);
  border-inline-start:2px solid var(--brass);padding-inline-start:1rem;
  margin:1.4rem 0 0;
}

.piece-sum{font-size:.9rem;color:var(--muted);line-height:1.65;margin:.6rem 0 0}

/* ------------------------------------------------------------ prose */
.prose{max-width:66ch}
.prose h3{
  font-family:var(--serif-display);font-weight:400;
  font-size:1.45rem;color:var(--parchment);margin:2.4rem 0 .7rem;
}
.prose p{margin:0 0 1.15rem;line-height:1.85}
.prose b{color:var(--parchment)}
.prose-cta{display:flex;gap:.7rem;flex-wrap:wrap;margin-top:2.2rem}

/* the three-column standard block on the front page */
.creed{
  display:grid;gap:clamp(1.4rem,3vw,3rem);
  grid-template-columns:repeat(auto-fit,minmax(min(100%,260px),1fr));
}
.creed-col h3{
  font-family:var(--serif-display);font-weight:400;font-size:1.28rem;
  color:var(--gold-pale);margin:0 0 .7rem;line-height:1.3;
}
.creed-col p{margin:0;font-size:.97rem;line-height:1.8;color:var(--parchment-dim)}

/* ------------------------------------------------------- public forms */
.pubform{max-width:62ch}
.pubform label{
  display:block;margin-bottom:1.1rem;
  font-family:var(--serif-ui);font-size:.58rem;letter-spacing:.2em;
  text-transform:uppercase;color:var(--brass);
}
.pubform-row{display:flex;gap:1rem;flex-wrap:wrap}
.pubform-row>label{flex:1 1 220px}
.pubform input[type=text],.pubform input[type=email],.pubform input[type=tel],
.pubform textarea,.pubform select{
  display:block;width:100%;margin-top:.5rem;
  background:var(--obsidian-deep);color:var(--parchment);
  border:1px solid var(--filigree);padding:.65rem .8rem;
  font-family:var(--serif-body);font-size:1rem;letter-spacing:0;
  text-transform:none;
}
.pubform textarea{resize:vertical;line-height:1.65}
.pubform input:focus,.pubform textarea:focus,.pubform select:focus{
  outline:none;border-color:var(--gold-soft);
}
.pubform button{margin-top:.6rem}
.pubform-note{
  font-size:.86rem;color:var(--muted);margin-top:1.1rem;line-height:1.7;
  font-family:var(--serif-body);letter-spacing:0;text-transform:none;
}
/* the honeypot: present for a bot, invisible and unreachable for a person */
/* The honeypot field.

   Parked at left:-9999px it was invisible, but it still extended the
   document's canvas 9999px to the left — harmless while body{overflow-x:hidden}
   clips it, and not harmless in Arabic, where the page is laid out right to
   left and left-hand overflow is the direction that scrolls. Clipping it in
   place hides it just as well from a person, reads the same to a bot filling
   in every input it finds, and leaves the canvas the size of the page. */
.hp{
  position:absolute;width:1px;height:1px;
  margin:-1px;padding:0;border:0;overflow:hidden;
  clip-path:inset(50%);white-space:nowrap;
}

.shell-narrow{max-width:860px}

/* ------------------------------------------------------ form controls
   A browser's default checkbox paints itself pure white, which breaks the
   house rule in the one place a stylesheet is easy to forget. Caught by the
   computed-style audit in tools/, not by eye. */
input[type=checkbox],
input[type=radio]{
  appearance:none;-webkit-appearance:none;
  width:15px;height:15px;flex:0 0 15px;margin:0;
  background:var(--obsidian-deep);
  border:1px solid var(--filigree-lit);
  cursor:pointer;position:relative;
  transition:background .3s ease,border-color .3s ease;
}
input[type=radio]{border-radius:50%}
input[type=checkbox]:hover,
input[type=radio]:hover{border-color:var(--gold-soft)}
input[type=checkbox]:checked,
input[type=radio]:checked{background:var(--gold);border-color:var(--gold)}
input[type=checkbox]:checked::after{
  content:'';position:absolute;inset:0;
  background:var(--obsidian);
  clip-path:polygon(14% 46%,0 60%,38% 92%,100% 22%,86% 10%,36% 66%);
}
input[type=radio]:checked::after{
  content:'';position:absolute;inset:3px;border-radius:50%;background:var(--obsidian);
}
input[type=checkbox]:focus-visible,
input[type=radio]:focus-visible{outline:2px solid var(--gold-soft);outline-offset:2px}

/* Date and number spinners inherit a white field on some builds too. */
input[type=date],input[type=number]{
  background:var(--obsidian-deep);color:var(--parchment);
  border:1px solid var(--filigree);
}

/* ---------------------------------------------------- browse density
   The prototype's .collection grid is tuned for eight featured pieces on a
   full-width shell: a 320px minimum column, which inside the narrower
   results column lands one pixel the wrong side of the boundary and drops
   to two enormous columns. Twenty-four pieces to a page want a tighter
   measure, so the results grid gets its own minimum. The featured grid on
   the front page is left exactly as approved. */
.results .collection{
  grid-template-columns:repeat(auto-fill,minmax(min(100%,240px),1fr));
  gap:clamp(.9rem,1.6vw,1.5rem);
}
@media (max-width:560px){
  .results .collection{grid-template-columns:1fr 1fr;gap:.7rem}
  .results .piece-body{padding:.9rem .9rem 1.05rem}
  .results .piece-name{font-size:1rem}
  .results .piece-foot{flex-direction:column;align-items:flex-start;gap:.3rem}
}

/* ------------------------------------------------- interior page top
   The prototype's .nav is position:fixed and sits over a full-viewport hero,
   so nothing needed to clear it. Interior pages have no hero, so the first
   band would slide underneath the wordmark. This gives it the nav's height
   back. */
main > section:first-of-type{ padding-top:clamp(7rem,9vh + 5rem,10rem) }
/* the home page keeps its hero flush under the fixed nav, as approved */
body.is-home main > section:first-of-type{ padding-top:0 }

/* The language switcher is anchors here, not buttons, because each language
   is a real URL a person can link to and a crawler can follow. The
   prototype styles .lang button, so the same look is given to .lang a. */
.lang a{
  appearance:none;border:0;background:transparent;cursor:pointer;
  font-family:var(--serif-ui);font-size:.6rem;letter-spacing:.16em;
  padding:.55rem .72rem;color:var(--muted);text-decoration:none;
  transition:color .4s ease,background .4s ease;
}
.lang a:hover{color:var(--gold-pale);text-decoration:none}
.lang a.on{color:var(--obsidian);background:linear-gradient(180deg,var(--gold-pale),var(--brass))}

/* Where else a piece is shelved, beside its breadcrumb. */
.crumbs__also{display:inline-block;margin-inline-start:.9rem;color:var(--muted)}
.crumbs__also a{color:var(--brass);text-decoration:none}
.crumbs__also a:hover{color:var(--gold-pale)}

/* ================================================== the photograph, full size */
/* The client's note: "make photo full size when clicking on it for all items".
   The plate is a button now; this is the frame it opens into. */

.plate-zoom{
  display:block;width:100%;padding:0;border:0;background:none;
  cursor:zoom-in;position:relative;
}
.plate-zoom img{display:block;width:100%}
.plate-zoom__hint{
  position:absolute;inset-inline-end:.7rem;inset-block-end:.7rem;
  font-family:var(--sans,system-ui,sans-serif);
  font-size:.6rem;letter-spacing:.18em;text-transform:uppercase;
  color:var(--parchment);background:rgba(var(--obsidian-rgb),.72);
  border:1px solid var(--filigree);border-radius:2px;
  padding:.3rem .55rem;opacity:0;transition:opacity .3s ease;pointer-events:none;
}
.plate-zoom:hover .plate-zoom__hint,
.plate-zoom:focus-visible .plate-zoom__hint{opacity:1}
.plate-zoom:focus-visible{outline:2px solid var(--gold);outline-offset:3px}

body.is-zoomed{overflow:hidden}

.lightbox{
  position:fixed;inset:0;z-index:960;
  background:rgba(var(--obsidian-rgb),.94);
  display:flex;align-items:center;justify-content:center;
  padding:clamp(1rem,4vw,3rem);
  cursor:zoom-out;
}
.lightbox[hidden]{display:none}
.lightbox__img{
  max-width:100%;max-height:100%;
  width:auto;height:auto;object-fit:contain;
  /* No frame, no crop, no shadow: at this size the photograph is the whole
     point and anything around it is in the way. */
  border:1px solid var(--filigree);
}
.lightbox__cap{
  position:absolute;inset-block-end:1.1rem;inset-inline:0;
  text-align:center;margin:0;
  font-family:var(--sans,system-ui,sans-serif);
  font-size:.7rem;letter-spacing:.2em;color:var(--muted);
}
.lightbox__x,
.lightbox__nav{
  position:absolute;z-index:1;
  background:rgba(var(--obsidian-rgb),.6);
  border:1px solid var(--filigree);color:var(--parchment-dim);
  cursor:pointer;line-height:1;transition:color .3s ease,border-color .3s ease;
}
.lightbox__x:hover,
.lightbox__nav:hover{color:var(--gold-pale);border-color:var(--gold)}
.lightbox__x:focus-visible,
.lightbox__nav:focus-visible{outline:2px solid var(--gold);outline-offset:2px}
.lightbox__x{
  inset-block-start:clamp(.6rem,2vw,1.4rem);
  inset-inline-end:clamp(.6rem,2vw,1.4rem);
  width:2.6rem;height:2.6rem;font-size:1.5rem;border-radius:2px;
}
.lightbox__nav{
  inset-block-start:50%;transform:translateY(-50%);
  width:2.6rem;height:3.4rem;font-size:1.7rem;border-radius:2px;
}
.lightbox__nav--prev{inset-inline-start:clamp(.4rem,2vw,1.4rem)}
.lightbox__nav--next{inset-inline-end:clamp(.4rem,2vw,1.4rem)}
/* The arrows point the way the language runs. */
[dir=rtl] .lightbox__nav--prev{transform:translateY(-50%) scaleX(-1)}
[dir=rtl] .lightbox__nav--next{transform:translateY(-50%) scaleX(-1)}

@media (max-width:640px){
  .lightbox{padding:.6rem}
  .plate-zoom__hint{opacity:1}   /* no hover on a telephone — just show it */
}
@media (prefers-reduced-motion:reduce){
  .plate-zoom__hint{transition:none}
}

/* ---------------------------------------------------------------- by finger
   The magnified photograph inside the viewer. Transform only: nothing is
   re-laid-out, so dragging it about stays smooth on a telephone. The
   transition is on transform alone and is dropped while a finger is actually
   moving the picture (the class is off between frames), so a drag tracks the
   finger rather than chasing it. */
.lightbox__img{
  transform-origin:50% 50%;
  transition:transform .28s ease;
  will-change:transform;
}
.lightbox__img.is-mag{
  transition:none;
  cursor:zoom-out;
}
/* Our own drag, not the browser's. Only on a touchscreen, and only for the
   photograph: the backdrop, the arrows and the × are untouched, and a mouse
   or a trackpad never reaches this rule. */
@media (hover:none) and (pointer:coarse){
  .lightbox__img{touch-action:none}
  .plates{touch-action:pan-y}
}
.lightbox__hint{
  position:absolute;inset-block-end:2.6rem;inset-inline:0;
  display:none;text-align:center;margin:0;
  font-family:var(--sans,system-ui,sans-serif);
  font-size:.66rem;letter-spacing:.16em;text-transform:uppercase;
  color:var(--muted);opacity:.85;transition:opacity .4s ease;
  pointer-events:none;
}
@media (hover:none) and (pointer:coarse){ .lightbox__hint{display:block} }
.lightbox.is-learnt .lightbox__hint{opacity:0}

/* While the viewer is open the header steps aside. The script also moves the
   viewer to <body> so its z-index is no longer trapped inside a z-3 section;
   this is the second half of the same repair — with the header still painted
   over the top of a full-screen photograph, the close button was reachable
   but sat under a bar the reader could not see through. */
body.is-zoomed header.nav{ opacity:0; pointer-events:none; }

/* A description written as plain sentences rather than "Label: value" lines
   (28 September): shown as the owner wrote it, under the table. */
.record-prose{ margin: 1.6rem 0 0; max-width: 38rem; }
.record-prose p{ margin: 0 0 .8rem; line-height: 1.8; font-size: 1rem; color: var(--parchment-dim); }
html[dir="rtl"] .record-prose[dir]{ text-align: right; }
