/* Photo inspiration page — Pine Shadows Manor conversation, 2026-08-20.
   Palette from BKM/lowthian-brand.md (Warm Sand, Deep Red).
   No web fonts, no scripts, no third-party requests of any kind. */

:root {
  --sand:        #f5ede4;  /* Warm Sand — page ground */
  --sand-deep:   #ede1d3;  /* set-apart panel */
  --ink:         #2a2724;  /* body + headings   12.8:1 on sand */
  --ink-soft:    #3a342e;  /* captions          10.6:1 on sand */
  --red:         #8b0000;  /* Deep Red           8.6:1 on sand */

  /* Photograph sizing. These two numbers are the whole layout contract:
     no tile is ever wider than --photo-w, and the smallest source file in
     this set is 528px wide, so nothing is ever displayed above its native
     size. --photo-h keeps the five portraits from towering over the three
     landscapes; each figure computes its own width from its own ratio. */
  --photo-w: 420px;
  --photo-h: 680px;

  /* Conservative fallback so an unclassed figure still sizes to the
     smallest file in the set rather than losing max-width entirely. */
  --arw: 528;
  --arh: 960;

  --serif: Georgia, "Iowan Old Style", "Palatino Linotype", Palatino, "Times New Roman", serif;
  --sans:  system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
}

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--sand);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 1.0625rem;
  line-height: 1.7;
}

.page {
  max-width: 960px;
  margin: 0 auto;
  padding: 3rem 1.25rem 5rem;
}

/* ---------- masthead ---------- */

.masthead { margin-bottom: 2.5rem; }

.rule {
  width: 68px;
  height: 3px;
  margin: 0 0 1.5rem;
  background: var(--red);
}

h1 {
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(2rem, 6.5vw, 3rem);
  line-height: 1.15;
  letter-spacing: -0.01em;
  margin: 0;
}

/* ---------- running copy ---------- */

.prose { max-width: 34em; }
.prose p { margin: 0 0 1.25rem; }
.prose p:last-child { margin-bottom: 0; }

.intro  { margin-bottom: 3.5rem; font-size: 1.125rem; }
.outro  { margin-top: 3rem; }

.last-word {
  font-family: var(--serif);
  font-size: 1.1875rem;
  line-height: 1.55;
  margin-top: 1.75rem;
  padding-left: 1rem;
  border-left: 3px solid var(--red);
}

/* ---------- the seven ---------- */

.grid {
  display: grid;
  grid-template-columns: minmax(0, var(--photo-w));
  justify-content: start;
  gap: 3.25rem 2.5rem;
}

@media (min-width: 800px) {
  .grid {
    grid-template-columns: repeat(2, minmax(0, var(--photo-w)));
    align-items: start;
    justify-content: start;
  }

  /* The two landscapes take a row each.
     With seven photographs the 2-up rows pair a ~290px-tall landscape against a
     ~680px-tall portrait twice over, which leaves two large holes — an artefact
     of removing one picture, not of the order, which is deliberate and stays as
     it is. Giving the landscapes their own row uses the mixed orientations
     instead of fighting them. Both stay far below native width at 620px
     (1440 and 960 wide respectively), so nothing is enlarged. */
  .grid > .p1,
  .grid > .p6 {
    grid-column: 1 / -1;
    --photo-w: 620px;
  }
}

/* Native pixel dimensions of each source file. These live here rather than in
   a style="" attribute on the figure because the page's own CSP is
   style-src 'self' — an inline style attribute is blocked, and the failure is
   invisible: the layout simply falls back to full width and the photographs
   get bigger. Caught on the live host, not locally, where there is no CSP. */
.p1 { --arw: 1440; --arh:  995; }   /* 01 by the window         */
.p2 { --arw:  528; --arh:  960; }   /* 02 crossword             */
.p3 { --arw:  720; --arh:  960; }   /* 03 arms around her       */
.p4 { --arw:  799; --arh:  856; }   /* 04 outside on a good day */
.p5 { --arw:  528; --arh:  960; }   /* 05 late afternoon        */
.p6 { --arw:  960; --arh:  528; }   /* 06 courtyard             */
.p7 { --arw:  528; --arh:  960; }   /* 07 from the doorway      */

figure {
  margin: 0;
  /* Never wider than the tile, never wider than the file itself, and never
     taller than --photo-h — the last term is the width this photograph would
     have at that height. */
  max-width: min(100%,
                 var(--photo-w),
                 calc(var(--arw) * 1px),
                 calc(var(--photo-h) * var(--arw) / var(--arh)));
}

figure img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 3px;
  background: var(--sand-deep);
  box-shadow: 0 1px 2px rgba(58, 42, 26, 0.18),
              0 8px 22px rgba(58, 42, 26, 0.13);
}

figcaption {
  margin-top: 1rem;
  color: var(--ink-soft);
  font-size: 1rem;
  line-height: 1.6;
}

/* ---------- the one that is set apart ---------- */

/* On a phone this runs edge to edge, so the photograph inside it stays the
   same size as the seven above — a set-apart picture should not also be a
   smaller one. The negative margin exactly cancels .page's own padding. */
.aside-block {
  margin: 4.5rem -1.25rem 0;
  padding: 2.25rem 1.25rem;
  background: var(--sand-deep);
  border-left: 3px solid var(--red);
}

@media (min-width: 800px) {
  /* Narrower than the grid above it, so it reads as a card set to one side
     rather than a full-width banner with a dead half. */
  .aside-block {
    margin-inline: 0;
    padding: 2.75rem 2.5rem;
    max-width: 600px;
  }
}

/* ---------- links ---------- */

.prose a {
  color: var(--red);              /* 8.6:1 on sand */
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}
.prose a:hover { text-decoration-thickness: 2px; }

/* ---------- focus ---------- */

:focus-visible {
  outline: 3px solid var(--red);
  outline-offset: 3px;
}

@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
}

/* ==========================================================================
   Interactive layer — lightbox, slideshow, entrance.
   Every rule below is inert until app.js builds the elements it targets, so
   the page degrades to the plain gallery above if the script never runs.
   ========================================================================== */

:root {
  --night:       #1d1a17;  /* lightbox ground                                */
  --night-text:  #f2e9de;  /* 14.6:1 on night                                */
  --night-muted: #d8cbbc;  /* 10.9:1 on night                                */
  --night-line:  #8a7d6f;  /*  4.3:1 on night — UI boundary, needs 3:1       */
  --gold:        #d4a574;  /* Warm Gold — 7.7:1 on night. Deep Red is only
                              1.7:1 there, so the brand accent switches to
                              gold inside the lightbox rather than going
                              unreadable on a dark ground.                   */
}

html.lb-open { overflow: hidden; }

.visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  clip-path: inset(50%);
  overflow: hidden; white-space: nowrap;
}

/* ---------- tiles become buttons ---------- */

.tile {
  display: block;
  width: 100%;
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  color: inherit;
  cursor: zoom-in;
  border-radius: 3px;
  transition: transform 220ms cubic-bezier(.2,.7,.3,1),
              filter 220ms ease;
}

.tile:hover  { transform: translateY(-3px); filter: saturate(1.03); }
.tile:active { transform: translateY(-1px); }

.tile:focus-visible {
  outline: 3px solid var(--red);
  outline-offset: 4px;
}

.pre-reveal { opacity: 0; }

/* ---------- play control on the page ---------- */

.playbar { margin: -1.75rem 0 3.25rem; }

.playbtn {
  display: inline-flex;
  align-items: center;
  gap: .6rem;
  min-height: 44px;
  padding: .55rem 1.15rem;
  border: 2px solid var(--red);
  border-radius: 999px;
  background: none;
  color: var(--red);
  font: inherit;
  font-size: 1rem;
  cursor: pointer;
  transition: background-color 180ms ease, color 180ms ease;
}

.playbtn svg { width: 15px; height: 15px; flex: none; }
.playbtn:hover { background: var(--red); color: var(--sand); }
.playbtn:focus-visible { outline: 3px solid var(--red); outline-offset: 3px; }

/* ---------- icons ---------- */

.lb svg, .playbtn svg {
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.lb svg.ic-fill, .playbtn svg.ic-fill { fill: currentColor; stroke: none; }

/* ---------- lightbox ---------- */

.lb { position: fixed; inset: 0; z-index: 100; }

.lb__backdrop {
  position: absolute;
  inset: 0;
  background: var(--night);
}

.lb__dialog {
  position: relative;
  display: grid;
  grid-template-rows: minmax(0, 1fr) auto;
  height: 100vh;
  height: 100dvh;
  color: var(--night-text);
}

.lb__dialog:focus { outline: none; }

.lb__stage {
  display: grid;
  grid-template-rows: minmax(0, 1fr);
  grid-template-columns: minmax(0, 1fr);
  min-height: 0;
  padding: 16px 16px 14px;
}

/* The native-width cap again, and this is where it matters most: a 528px file
   opened "large" on a 1440px screen must not be stretched to fill it. */
.lb__img {
  grid-area: 1 / 1;
  place-self: center;
  max-width: min(calc(var(--arw) * 1px), 100%);
  max-height: 100%;
  width: auto;
  height: auto;
  opacity: 0;
  pointer-events: none;
  border-radius: 2px;
  box-shadow: 0 20px 60px rgba(0, 0, 0, .55);
  transition: opacity 300ms ease;
}

.lb__img.is-current { opacity: 1; pointer-events: auto; }
.lb__img.is-instant { transition: none; }

.lb__bar {
  display: grid;
  gap: 1rem;
  justify-items: center;
  padding: 1rem 1rem calc(1.15rem + env(safe-area-inset-bottom, 0px));
}

.lb__meta {
  max-width: 56ch;
  text-align: center;
  padding-left: 0;
  border-left: 0 solid var(--gold);
  transition: padding-left 200ms ease;
}

.lb__meta.is-apart {
  text-align: left;
  padding-left: 1rem;
  border-left-width: 3px;
}

.lb__count {
  margin: 0 0 .4rem;
  color: var(--night-muted);
  font-size: .8125rem;
  letter-spacing: .06em;
  text-transform: uppercase;
}

.lb__caption {
  margin: 0;
  font-size: 1rem;
  line-height: 1.6;
}

.lb__controls { display: flex; gap: .5rem; align-items: center; }

.lb__btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .5rem;
  min-width: 48px;
  min-height: 48px;
  padding: 0 .85rem;
  border: 1px solid var(--night-line);
  border-radius: 999px;
  background: none;
  color: var(--night-text);
  font: inherit;
  font-size: .9375rem;
  cursor: pointer;
  transition: background-color 180ms ease, border-color 180ms ease;
}

.lb__btn svg { width: 18px; height: 18px; flex: none; }
.lb__btn:hover { background: rgba(242, 233, 222, .12); border-color: var(--night-text); }
.lb__btn:focus-visible { outline: 3px solid var(--gold); outline-offset: 3px; }
.lb__btn--play { padding: 0 1.05rem; }
.lb__btn-label { white-space: nowrap; }

@media (min-width: 800px) {
  .lb__stage { padding: 28px 28px 20px; }
  .lb__bar   { gap: 1.15rem; padding: 1.25rem 1.5rem 1.75rem; }
  .lb__caption { font-size: 1.0625rem; }
}

@media (max-width: 400px) {
  .lb__btn { padding: 0 .6rem; }
  .lb__btn--play { padding: 0 .8rem; }
  .lb__btn-label { font-size: .875rem; }
}

/* ---------- reduced motion ----------
   Every transition and animation above is switched off here. The slideshow is
   NOT removed — a viewer who presses Play still gets it, the swap is just
   instant. Auto-advance with an always-visible Pause satisfies WCAG 2.2.2;
   what reduced-motion asks us to drop is the animation, and this drops all of
   it: no entrance stagger, no cross-fade, no zoom, no hover lift. app.js reads
   the same query and skips the FLIP and entrance animations outright. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
  .tile:hover, .tile:active { transform: none; }
  .pre-reveal { opacity: 1; }
}
