
/* ══ THE SECTION IS #bio, NOT #press ══
   Corrected 23 Sep 2026, after VJ said for the SECOND time "again, you brought back these tiny quotes?". The quote
   ladder below was written on 22 Sep, reviewed, approved - and never applied to anything, because every selector in
   this file said `#press` and there is no element with that id. The press quotes and the biography share one
   `section#bio`. Measured in the browser: `#press blockquote` matched 0 elements, `blockquote` matched 5, and their
   computed sizes were 72/40/52/21/21 - the export's own inline values, with the two VJ pointed at sitting at 21px.
   Twenty rules in this file were dead the same way. The lesson is the cheap one and I keep paying for it: a CSS fix
   is not verified by reading the CSS. Assert the COMPUTED value in the browser, or you have written a comment. */
/* ─────────────────────────────────────────────────────────────────────────────
   DM in the PM — composition layer over the Claude Design export.

   EVERY RULE HERE NEEDS !important. The export carries an inline style="" on
   essentially every element, and an inline declaration beats any stylesheet
   rule that is not marked. This is not defensive habit: an unmarked
   display:none once lost to an element's own display:flex and collapsed a nav
   to 0px wide - pixel-identical in a screenshot, with four links still in the
   tab order pointing at things nobody could see.

   Assert the COMPUTED value in a browser after changing anything here.
   ───────────────────────────────────────────────────────────────────────────── */

/* ── always on ─────────────────────────────────────────────────────────────── */

/* The disclosure panels carry inline display:flex, so [hidden] alone loses. */
[hidden] { display: none !important; }

/* COLOUR BACK IN THE PHOTOGRAPHS. VJ, 15 Sep 2026: "make all the photos more colorful, bring the
   color back". The export washed every plate with grayscale(.55-.8) plus sepia on half of them, so
   Dan's red light and the blue painting read as brown. This replaces the whole inline filter
   rather than adding to it: a touch of contrast keeps the after-dark punch, saturate lifts the
   real colour. The inline `transition: filter 1s` still applies. */
/* The colour is now graded INTO the files (_project/photo-grade.py, 22 Sep 2026), one grade for every photo. The old
   blanket saturate/contrast filter would stack on top of it, so it is off. */
picture img { filter: none !important; }

/* Pages that do not exist yet: present, legible, plainly not a link. */
[data-pending] { opacity: .5 !important; cursor: default !important; }

/* Nothing in the export acknowledged a press, and on a phone there is no
   hover to fall back on - silence between tap and response reads as "it did
   not register". Transform and opacity only. */
/* THE !important IS LOAD-BEARING AND WAS MISSING. 94 elements carry an inline `transition`,
   in a dozen combinations, and an unmarked rule loses to every one of them: the Book Dan pill
   computed `background, color 0.3s` and the :active scale would have snapped, or crawled at
   the 0.4-1s some of them declare. Measured, not assumed - the computed transitionProperty
   said `background, color` while this file said `transform`.

   The property list keeps what these controls actually animate (background, colour, border)
   and adds a fast transform, so nothing the export intended is flattened. Plates carry their
   own `filter 1s, transform 1s` and are not controls, so they are untouched. */
a, button, [role="button"] {
  transition: transform .16s cubic-bezier(.2, .8, .3, 1),
              background .3s, color .3s, border-color .3s !important;
}
a:active, button:active, [role="button"]:active { transform: scale(.97) !important; }

/* KEYBOARD FOCUS. Measured 12 Sep 2026: the site had ZERO :focus rules of any kind, across 48
   controls - so a keyboard visitor had no idea where they were. WCAG 2.4.7. The ring is the
   accent already in the palette rather than the browser default blue, offset so it reads on both
   the ink ground and the light Book Dan panel, and :focus-visible so a mouse press does not
   leave it behind. */
a:focus-visible, button:focus-visible, [role="button"]:focus-visible,
input:focus-visible, select:focus-visible, textarea:focus-visible {
  outline: 2px solid #FFC400 !important;
  outline-offset: 3px !important;
  border-radius: 2px;
}
/* Some controls sit on the gold pill itself, where gold-on-gold would vanish. */
[data-nav-cta]:focus-visible, [data-booking-send]:focus-visible {
  outline-color: #060509 !important;
}
@media (prefers-reduced-motion: reduce) {
  a, button, [role="button"] { transition: none !important; }
  a:active, button:active, [role="button"]:active { transform: none !important; }

  /* THE EXPORT'S REDUCED-MOTION RULE DOES NOT REACH THE REVEALS, and measuring is the only way
     to find that. It sets animation-duration to .001ms, which correctly stops all 34 infinite
     loops - the pulses, the marquee, the flicker, the equaliser. But 31 elements here animate on
     `animation-timeline: view()`, and a SCROLL timeline ignores duration entirely: progress comes
     from scroll position, not time. So a motion-sensitive visitor still got 31 elements sliding
     and scaling past them.

     Handing the timeline back to time is what fixes it: with `auto`, the export's own .001ms
     duration finally applies, and `animation-fill-mode: both` lands each element on its `to`
     state immediately. Content is present, nothing moves. Measured both ways afterwards. */
  * { animation-timeline: auto !important; }
}

/* HOVER IS NOT A THING A FINGER DOES. The export ships `a:hover{color:#C9A24B}` and no
   `(hover: hover)` guard anywhere, and on a touch screen :hover LATCHES after a tap - so
   tapping any link on this page left it gold until you tapped something else. It reads as a
   selection state the site never meant to have, and nothing measures it: the colour is
   correct, the contrast is fine, the target is 44px. It is only wrong to a thumb.

   `:active` already carries the press feedback (scale .97 at 160ms), which is the state a
   finger should get. So on touch, hover simply stops existing. */
@media (hover: none), (pointer: coarse) {
  a:hover { color: inherit !important; }
  [data-band-item]:hover, [data-nav-link]:hover, [data-footer] a:hover { color: inherit !important; }
}

/* An <img> with no bitmap paints its alt text/* An <img> with no bitmap paints its alt text - a wall of words where the
   photographs should be. Give it the page's ink and hide only the visual
   fallback; the alt attribute stays in the accessibility tree. */
img { background-color: #0b0910; color: transparent; }

/* ── safe areas ────────────────────────────────────────────────────────────────
   The nav is sticky at top:0 and two layers are fixed. Without these the nav
   sits under the Dynamic Island, and the footer under the home indicator. No
   media query fires for a hardware cutout, so no emulator will show this -
   it needs the real Simulator. */
nav {
  padding-top: calc(15px + env(safe-area-inset-top)) !important;
  padding-left: calc(clamp(14px, 3.5vw, 52px) + env(safe-area-inset-left)) !important;
  padding-right: calc(clamp(14px, 3.5vw, 52px) + env(safe-area-inset-right)) !important;
}
[data-band] {
  padding-left: calc(16px + env(safe-area-inset-left)) !important;
  padding-right: calc(16px + env(safe-area-inset-right)) !important;
}
[data-footer] {
  padding-bottom: calc(22px + env(safe-area-inset-bottom)) !important;
  padding-left: calc(clamp(18px, 3.5vw, 52px) + env(safe-area-inset-left)) !important;
  padding-right: calc(clamp(18px, 3.5vw, 52px) + env(safe-area-inset-right)) !important;
}

/* LANDSCAPE IS THE ORIENTATION THIS RULE EXISTS FOR. With viewport-fit=cover the page is
   edge to edge, and in landscape the Dynamic Island is on a SIDE - so the hero's own copy and
   the privacy notice's text column need the horizontal insets, not just the chrome. A top-inset
   rule alone would read as correct on every emulator and put the headline under the cutout on a
   real phone held sideways. */
header[data-screen-label="Hero"] > div:last-of-type,
main[data-prose] {
  /* ADD to the padding that is already there. NEVER REPLACE IT. The first version of this rule
     set padding-left to env(safe-area-inset-left) alone - and in PORTRAIT that inset is zero, so
     an !important rule meant to protect content from a cutout instead deleted the hero's
     18-52px of horizontal padding and the privacy notice's text column inset. "AFTER DARK" and
     "DAN" sat flush against the glass.

     Nothing in the numeric sweep saw it: it clips no control and overflows no text, so
     mobile-audit read 0/0/0 at every width. A real iPhone showed it in one frame. The value
     below is the export's own clamp, which both surfaces already used. */
  padding-left: calc(clamp(18px, 3.5vw, 52px) + env(safe-area-inset-left)) !important;
  padding-right: calc(clamp(18px, 3.5vw, 52px) + env(safe-area-inset-right)) !important;
}
main[data-prose] { padding-bottom: calc(clamp(60px, 10vh, 130px) + env(safe-area-inset-bottom)) !important; }

/* NOT on <main> itself on the home page. That element is a STRUCTURAL wrapper added for the
   landmark, and it contains the full-bleed hero: horizontal padding on it inset the entire
   photograph, leaving a black gutter down the left of the image and bleeding it off the right.
   The first fix for the missing hero padding created that, which is why the rule is scoped to
   the PROSE column now. A safe-area inset belongs on the block that holds the words, never on
   a wrapper that also holds something meant to touch the glass. */

/* ── tap targets ───────────────────────────────────────────────────────────────
   35 of 48 controls measured under 44px, most of them 11px tall. Every one is
   a standalone control rather than a link inside a sentence, so growing them
   is safe - checked before writing this, not assumed. */
/* WIDTH ALONE CANNOT SEE A PHONE IN LANDSCAPE. An iPhone on its side is 844px wide - past
   every mobile breakpoint - and still a thumb on glass. So this block asks about the INPUT as
   well as the width: (pointer: coarse) is true on phones and tablets in any orientation and
   false on a mouse-driven desktop, which is the distinction the 44px rule actually cares
   about. Verified under CDP touch emulation at 844x390, not assumed from the query text. */
@media (max-width: 820px), (pointer: coarse) {
  [data-band-item],
  [data-footer] a,
  [data-nav-cta],
  [data-nav-link],
  [data-row] a,
  [data-chip],
  #work a,
  #dates a,
  [data-toggle],
  #listen a,
  header a {
    min-height: 44px !important;
    display: inline-flex !important;
    align-items: center !important;
  }
  /* The booking form ships COLLAPSED, so its ten controls were in no earlier measurement and
     sat at 42px - two under the floor, and invisible until the audit learned to open the
     disclosures first. The textarea is excluded: it is four rows tall already. */
  [data-booking-form] input,
  [data-booking-form] select { min-height: 44px !important; }

  /* PROSE LINKS ARE THE ONE CASE min-height CANNOT FIX. A link inside a sentence is an inline
     box: min-height does nothing to it, and turning it inline-flex would break the line. Vertical
     padding DOES enlarge an inline element's hit box without changing line layout, which is what
     a thumb needs. Three of these are mine - the privacy link under "Send inquiry" and the two
     inside the notice itself - and they measured 20-27px tall. */
  main p a, main li a, [data-booking-form] ~ p a, [data-booking-send] ~ p a {
    padding-block: 11px !important;
    /* the hit box grows upward and downward; the text does not move */
  }

  /* The credit line is a cross-site signature at a fixed size. Never grown. */  /* The credit line is a cross-site signature at a fixed size. Never grown. */
  [data-sc-name="Pchol Kollektiv Credit"] * { min-height: 0 !important; }

  /* THE BAND COMPACTS AT THE SAME BREAKPOINT AS THE TAP TARGETS, and that pairing is the
     whole point: growing its items to 44px while they were still allowed to wrap sent 768
     to 227px of chrome - worse than the fault being fixed. A touch-size rule and the layout
     that has to absorb it belong in one block. */
  [data-band] {
    gap: 14px !important;
    padding-top: 0 !important;
    padding-bottom: 0 !important;
    font-size: 9.5px !important;
    letter-spacing: .16em !important;
    flex-wrap: nowrap !important;
    overflow-x: auto !important;
    justify-content: flex-start !important;
    scrollbar-width: none;
  }
  [data-band]::-webkit-scrollbar { display: none; }
  [data-band-item] { white-space: nowrap !important; flex: 0 0 auto !important; }
  [data-band-item] [data-tail] { display: none !important; }

  /* Same reason: the nav must not wrap once its children are 44px tall - and the rule has to
     reach the INNER box, because flex-wrap on <nav> governs only its own direct children. */
  nav {
    flex-wrap: nowrap !important;
    gap: 12px !important;
    padding-top: calc(9px + env(safe-area-inset-top)) !important;
    padding-bottom: 9px !important;
  }
  [data-nav-links] { flex-wrap: nowrap !important; gap: clamp(10px, 2vw, 24px) !important; }

  /* 44px is the WHOLE control, never 44 plus the padding it already carries. The pill kept
     its inline 9px 20px and came out 62px tall, which is what held the nav at 93px on tablet
     after the same fix had already been made one breakpoint down. Fix it once, here. */
  [data-nav-cta] { padding-top: 0 !important; padding-bottom: 0 !important; }
}

/* ── phone composition ─────────────────────────────────────────────────────────
   The export had one breakpoint, at 820px, and all it did was change grid
   columns. Below that, narrow widths were whatever flexbox happened to do:
   205px of chrome above the first content pixel at 320, on a 568px screen. */
@media (max-width: 520px) {

  /* Identity and the one action that matters. The three section links go: this
     is a single scroll, the hero already offers "Next show", and at 320 the
     wordmark plus the Book Dan pill is genuinely all that fits on one line. */
  /* Identity and the one action that matters. The wordmark was breaking to "DM IN THE / PM",
     which reads as an accident rather than a lockup. */
  [data-nav-link] { display: none !important; }
  nav > div:first-of-type { white-space: nowrap !important; }

  /* Holding the wordmark on one line made it 177px wide, and 177 + 12 + a 114px pill is
     303 inside a 292px budget - so the fix for the lockup pushed BOOK DAN off the edge at
     320. It was the overflow column, added one step earlier, that caught it. Shrink the
     wordmark rather than the only conversion control in the header. */
  nav > div:first-of-type { font-size: 12px !important; letter-spacing: .12em !important; }
  [data-nav-cta] { padding-left: 16px !important; padding-right: 16px !important; font-size: 10px !important; white-space: nowrap !important; }

  /* Date and archive rows: a three-column grid needing 290px inside 250px,
     which clipped four CTAs at 320 behind an overflow-x:hidden that meant the
     page never scrolled sideways to admit it. Stack, and let the control span. */
  [data-row] {
    grid-template-columns: 1fr !important;
    gap: 8px !important;
    padding: 16px 2px !important;
  }
  [data-row] a {
    justify-content: center !important;
    width: 100% !important;
    box-sizing: border-box !important;
  }

  /* Booking chips and the form: one column, full-width controls. */
  [data-chip] { width: 100% !important; justify-content: center !important; }
  [data-booking-form] input,
  [data-booking-form] select,
  [data-booking-form] textarea { width: 100% !important; box-sizing: border-box !important; }
}

/* ── the hero name must not be cut in half ────────────────────────────────────
   The H1 is clamp(54px, 12.5vw, 220px). Below about 430px the 54px FLOOR wins over
   the viewport term, and at 320 "Magay." measures 333px inside a 302px column - so the
   page clipped the artist's own surname, silently, because the body carries
   overflow-x: hidden and nothing scrolled sideways to admit it.

   No probe caught this: the overflow checks in this project look at CONTROLS, and a
   heading is not a control. A contact sheet caught it. That is the whole argument for
   opening the frames rather than reading the green line.
   ──────────────────────────────────────────────────────────────────────────── */
@media (max-width: 380px) {
  header h1 { font-size: clamp(40px, 14.5vw, 54px) !important; }
}

/* And headings generally: never wider than the column that holds them, and allowed to break
   a long word rather than run past the edge. Closes a consistent 3px overhang on
   "The bands - past & present." seen at 360-390 under 2x mobile emulation but not in the
   desktop pane - a disagreement between two instruments that is cheaper to make impossible
   than to adjudicate. */
@media (max-width: 820px), (pointer: coarse) {
  h1, h2, h3 { max-width: 100% !important; overflow-wrap: break-word !important; }
}

/* ── the credit line: the house component (web-toolkit/tools/dc-port/PcholCredit.css) ─────────────
   Keyframes verbatim from pchol-productions/pchol-kollektiv-credit.dc.html. A bee on a surface WALKS - small
   steps, brief pauses, slight pivots; the amplitudes are tiny on purpose. That is the subtlety VJ asked for on
   15 Sep 2026, "like it is in www.pcholproductions.com". */
@keyframes pkcStep{0%{transform:translate(0,0) rotate(0deg)}11%{transform:translate(.34px,-.05px) rotate(-.22deg)}22%{transform:translate(.34px,-.05px) rotate(-.22deg)}33%{transform:translate(.72px,.06px) rotate(.12deg)}47%{transform:translate(.72px,.06px) rotate(.12deg)}58%{transform:translate(1.05px,-.07px) rotate(.3deg)}72%{transform:translate(1.05px,-.07px) rotate(.3deg)}84%{transform:translate(.5px,.05px) rotate(-.16deg)}93%{transform:translate(.5px,.05px) rotate(-.16deg)}100%{transform:translate(0,0) rotate(0deg)}}
@keyframes pkcGait{0%,100%{transform:translateY(0)}50%{transform:translateY(-.5px)}}
@keyframes pkcBreathe{0%,100%{transform:scale(1)}43%{transform:scale(1.012)}}
@keyframes pkcWingL{0%,70%,100%{transform:rotate(0deg)}73%{transform:rotate(-6deg)}77%{transform:rotate(-1.5deg)}81%{transform:rotate(0deg)}}
@keyframes pkcWingR{0%,54%,100%{transform:rotate(0deg)}57%{transform:rotate(5.5deg)}61%{transform:rotate(1deg)}66%{transform:rotate(0deg)}}
@keyframes pkcLegL{0%,100%{transform:rotate(0deg)}38%{transform:rotate(-4deg)}62%{transform:rotate(1.5deg)}}
@keyframes pkcLegR{0%,100%{transform:rotate(0deg)}46%{transform:rotate(3.6deg)}72%{transform:rotate(-1.2deg)}}
@keyframes pkcAntL{0%,80%,100%{transform:rotate(0deg)}83%{transform:rotate(-9deg)}87%{transform:rotate(-3deg)}91%{transform:rotate(-7deg)}96%{transform:rotate(0deg)}}
@keyframes pkcAntR{0%,62%,100%{transform:rotate(0deg)}65%{transform:rotate(8deg)}70%{transform:rotate(2deg)}75%{transform:rotate(6deg)}80%{transform:rotate(0deg)}}

/* The credit keeps its own face and size, deliberately NOT the host's. text-transform and letter-spacing are
   reset because the footer sets uppercase and .2em tracking on everything inside it. */
.pkc { display: inline-flex; align-items: center; gap: 8px; line-height: 1; font-family: 'Archivo', system-ui, sans-serif;
  font-weight: 400; font-size: 11.5px; letter-spacing: .03em; text-transform: none; opacity: .86; text-decoration: none; }
.pkc--cream { color: #F2EEE3; }
.pkc--right { flex-direction: row-reverse; }
.pkc:hover { opacity: 1; }
.pkc:focus-visible { outline-offset: 4px; }
.pkc-bee { flex: none; display: block; margin: -8px 0; align-self: center; transform: rotate(-11deg); }
/* !important: the head's anti-alt-flash rule paints an ink ground on EVERY img, which on stacked bee layers
   would draw a dark box over each layer beneath it. */
.pkc-bee img { position: absolute; inset: 0; width: 100%; height: 100%; background: none !important; }
.pkc-text { line-height: 1; }
.pkc-prefix { opacity: .8; }
@media (prefers-reduced-motion: reduce) { .pkc *, .pkc { animation: none !important; transition: none !important; } }

/* THE CREDIT STAYS IN THE RIGHT-HAND CORNER WHEN THE FOOTER WRAPS. On a phone the footer's three groups stack,
   and the credit, now alone on its row, fell to the LEFT edge while still reading words-then-bee - the wrong way
   round for a left corner (house rule: the bee is always on the outside of the phrase). margin-left:auto keeps it
   right-aligned at every width, so one layout holds everywhere. Measured 15 Sep 2026 at 390: credit left 18px. */
[data-footer] > [data-sc-name="Pchol Kollektiv Credit"] { margin-left: auto !important; }
/* "☀ DM in the AM" broke across two lines at 390. Each footer item stays whole; the GROUP wraps instead. */
[data-footer] > div:nth-child(2) { flex-wrap: wrap !important; row-gap: 4px !important; }
[data-footer] > div:nth-child(2) > * { white-space: nowrap !important; }

/* "What happens to it", the privacy link under Send inquiry, measured 41px tall with the disclosures open at 320, 414,
   768 and wider (mobile-audit OPEN=1, 15 Sep 2026) - 11px of padding on a 19px line box. 12.5px each side is 44. */
@media (max-width: 820px), (pointer: coarse) {
  [data-booking-form] ~ p a, [data-booking-send] ~ p a { padding-block: 12.5px !important; }
}

/* Booking form sends in the page (prepare.js 6-send). The honeypot is off-screen, not display:none - some bots skip
   hidden fields. The status line is the only feedback a visitor gets, so it is readable and never empty-looking. */
[data-hp] { position: absolute !important; left: -10000px !important; width: 1px !important; height: 1px !important; overflow: hidden !important; }
/* The form panel is CREAM, not ink - gold and coral on cream read at under 2:1, so the status uses darker tones. */
[data-booking-status] { margin: 14px 0 0 !important; min-height: 1.4em; font-family: Archivo, sans-serif !important; font-size: 14px !important; letter-spacing: .02em; color: rgba(6,5,9,.72) !important; }
[data-booking-status][data-state="sent"] { color: #7A5A00 !important; font-weight: 600; }
[data-booking-status][data-state="error"] { color: #A8321A !important; }
[data-booking-send]:disabled { opacity: .6; cursor: progress; }

/* The nav wordmark was removed (prepare.js, 22 Sep 2026), which leaves the link group (Book Dan inside it) as the nav's
   ONLY child - and space-between puts a lone child on the left. Measured: the pill sat 14px from the left at 390. */
nav { justify-content: flex-end !important; }

/* THE PRESS SECTION IN THE HERO'S PURPLE. VJ, 22 Sep 2026: "have this section have a purple background that could match
   the rest of the design ... maybe match the purple in the hero section? you decide." Sampled from the hero photograph:
   ~rgb(64,26,70). A deep aubergine ground with that purple glowing through the middle, fading to the page's ink at both
   edges so no hard seam cuts across. Gold on the glow measures ~6:1, cream far higher. */
#bio {
  background:
    radial-gradient(ellipse 72% 58% at 50% 46%, rgba(64, 26, 70, .95), rgba(64, 26, 70, 0) 74%),
    linear-gradient(180deg, #060509 0%, #1f0d25 14%, #2a1231 50%, #1f0d25 86%, #060509 100%) !important;
}

/* The press section's gold half-moon is a full disc placed 12% above the section and clipped by its overflow, which
   drew a hard straight edge across the top (22 Sep 2026, seen in the seam check). Its top now fades out instead. */
#bio > div[aria-hidden="true"]:first-child {
  -webkit-mask-image: linear-gradient(to bottom, transparent 8%, #000 55%) !important;
  mask-image: linear-gradient(to bottom, transparent 8%, #000 55%) !important;
}

/* THE BANDS SECTION IN MIDNIGHT BLUE. VJ, 22 Sep 2026: "this whole block - let's make the background blue-ish ... decide
   please on the right hue that fits the rest of the design". A deep midnight blue (#141C3A) - the complement of the
   candle gold, so the gold tags and numerals read warmer on it - with a lighter blue glowing through, fading to the
   page's ink at both edges the same way the purple press section does. */
#work {
  background:
    radial-gradient(ellipse 80% 50% at 50% 40%, rgba(32, 46, 92, .85), rgba(32, 46, 92, 0) 72%),
    linear-gradient(180deg, #060509 0%, #10162e 9%, #141c3a 50%, #10162e 91%, #060509 100%) !important;
}

/* THE REST OF THE DARK BLOCKS, ALTERNATING THE TWO COLOURS - VJ, 22 Sep 2026: "all the dark background-ed blocks, please
   bring in the blue and or purple that we used in the earlier blocks, how you decide". Down the page: press purple,
   bands blue, dates purple, listen blue, footer a quiet deep purple. Each fades to the page's ink at its edges, so the
   sections flow into one another instead of meeting at a line. (Book Dan stays cream.) Dates and Listen carry their own
   inline backgrounds, hence !important. */
#dates {
  background:
    radial-gradient(ellipse 72% 58% at 50% 46%, rgba(64, 26, 70, .9), rgba(64, 26, 70, 0) 74%),
    linear-gradient(180deg, #060509 0%, #1f0d25 14%, #2a1231 50%, #1f0d25 86%, #060509 100%) !important;
}
#listen {
  background:
    radial-gradient(ellipse 78% 58% at 50% 46%, rgba(32, 46, 92, .85), rgba(32, 46, 92, 0) 72%),
    linear-gradient(180deg, #060509 0%, #10162e 14%, #141c3a 50%, #10162e 86%, #060509 100%) !important;
}
footer[data-footer] {
  background: linear-gradient(180deg, #120a18 0%, #1a0e22 100%) !important;
}

/* DAN'S BIO, ALWAYS UP (prepare.js 6u). No frame (VJ, 22 Sep 2026: "does it really need the 'square' frame around it"):
   it sits on the section's purple under a short gold rule, like a chapter. The photograph's own black is faded out at its
   edges so it melts into the purple instead of reading as a pasted rectangle. Side by side from 700px; below that the photo
   runs full width, cropped from the top so his face and the clarinet stay in frame. */
[data-bio] {
  max-width: 1080px; margin: clamp(48px, 8vh, 96px) auto clamp(26px, 4vh, 40px); padding: 0;
  display: grid; grid-template-columns: 1fr; gap: clamp(22px, 3.4vw, 56px); align-items: center; text-align: left;
  position: relative; font-family: 'Cormorant Garamond', Georgia, serif; font-size: clamp(17px, 1.3vw, 19.5px); line-height: 1.62;
  color: rgba(242, 237, 226, .9);
}
[data-bio]::before { content: ''; position: absolute; top: calc(-1 * clamp(24px, 4vh, 48px)); left: 50%; width: 64px; height: 1px;
  transform: translateX(-50%); background: #C9A24B; }
@media (min-width: 700px) { [data-bio] { grid-template-columns: minmax(220px, 38%) 1fr; } }
[data-bio-photo] { margin: 0; }
[data-bio-photo] img {
  display: block; width: 100%; height: auto; background: transparent !important;
  -webkit-mask-image: radial-gradient(ellipse 78% 82% at 42% 42%, #000 58%, transparent 100%);
          mask-image: radial-gradient(ellipse 78% 82% at 42% 42%, #000 58%, transparent 100%);
}
@media (max-width: 699px) {
  [data-bio-photo] img { aspect-ratio: 4 / 3; object-fit: cover; object-position: 30% 12%;
    -webkit-mask-image: linear-gradient(180deg, #000 60%, transparent 100%); mask-image: linear-gradient(180deg, #000 60%, transparent 100%); }
}
[data-bio-kicker] { margin: 0 0 8px !important; font-family: Archivo, sans-serif; font-size: 10.5px !important; letter-spacing: .24em; text-transform: uppercase; color: #F2D89B; }   /* same gold as every other small label - raised 22 Sep 2026 with the lighter sections */
[data-bio] h2 {
  margin: 0 0 18px; font-family: Syne, Archivo, sans-serif; font-weight: 800; font-size: clamp(26px, 3vw, 40px);
  line-height: .95; letter-spacing: .02em; text-transform: uppercase; color: #F2EDE2;
}
[data-bio-text] p { margin: 0 0 14px; }
[data-bio-text] p:last-child { margin-bottom: 0; }
[data-bio-text] h2 + p { font-style: italic; font-size: 1.12em; color: #F2EDE2; }

/* LIGHTER AND MORE COLOURFUL, EVERYWHERE - VJ, 22 Sep 2026: "throughout ALL the website, put those blues and purples into
   the backgrounds please, make it more light, less dark everywhere" and "more colorful please". The page's base moves from
   ink (#060509) to a deep indigo-violet (#1a1330), so sections blend into each other through colour instead of black; the
   purple and blue sections are raised and more saturated; cards, nav and footer lift with them. Book Dan stays cream.
   RAISED AGAIN 22 Sep 2026 (VJ: "make all the backgrounds lighter"): base #1a1330 -> #241B47, purple mid #45194f -> #5D2A6B,
   blue mid #223470 -> #2C4390, footer and cards with them. Contrast re-measured after, below.
   Contrast measured after the change (docs/website-qa.md), not assumed. These rules come last, so they win. */
html, body { background: #241B47 !important; }
/* the grounds keep their colour but let the ambient layer behind them show as a slow change of light */
#bio, #dates, #work, #listen { background-blend-mode: normal; }
nav { background: rgba(36, 27, 71, .84) !important; }
#bio, #dates {
  background:
    radial-gradient(ellipse 75% 58% at 50% 46%, rgba(150, 66, 162, .72), rgba(150, 66, 162, 0) 74%),
    linear-gradient(180deg, rgba(36,27,71,.94) 0%, rgba(74,34,88,.94) 16%, rgba(93,42,107,.94) 50%, rgba(74,34,88,.94) 84%, rgba(36,27,71,.94) 100%) !important;
}
#work, #listen {
  background:
    radial-gradient(ellipse 80% 52% at 50% 42%, rgba(72, 108, 198, .58), rgba(72, 108, 198, 0) 72%),
    linear-gradient(180deg, rgba(36,27,71,.94) 0%, rgba(38,57,123,.94) 14%, rgba(44,67,144,.94) 50%, rgba(38,57,123,.94) 86%, rgba(36,27,71,.94) 100%) !important;
}
footer[data-footer] { background: linear-gradient(180deg, #382260 0%, #45256F 100%) !important; }
/* the export's near-black card and panel grounds, lifted to a translucent indigo so the colour behind shows through */
[style*="background: rgb(12, 10, 18)"], [style*="background: rgb(11, 9, 13)"] { background: rgba(46, 37, 88, .8) !important; }

/* CONTRAST ON THE LIGHTER SECTIONS - measured 22 Sep 2026 after the colour change: on the brightest purple (110,43,120) and
   blue (51,77,153) the small gold labels fell to 3.8 and 3.3 and the faded cream labels (50-65%) to ~3, under the 4.5 that
   small text needs. The text moves, not the background: gold labels take the lighter gold #E7C36A (5.4 / 4.7), faded
   labels a stronger cream (.82 -> 5.9 / 5.1). Cream body text was already 6.8-7.9.
   RE-MEASURED after the 22 Sep lightening, because raising the background undoes this every time: on the new peaks
   (128,56,140) and (62,92,170) the gold fell to 4.34 / 3.74 and the cream to 4.35 / 3.76, both under 4.5. Gold goes to
   #F2D89B (5.27 / 4.54), faded cream to .88 (4.96 / 4.28 -> and the blue glow drops from .58 alpha so it clears 4.5
   with margin rather than sitting on the line). Lighten the background again and this must be measured again. */
:is(#bio, #work, #dates, #listen) [style*="color: rgb(201, 162, 75)"] { color: #F2D89B !important; }
:is(#bio, #work, #dates, #listen) :is([style*="color: rgba(242, 237, 226, 0.5)"], [style*="color: rgba(242, 237, 226, 0.55)"],
  [style*="color: rgba(242, 237, 226, 0.6)"], [style*="color: rgba(242, 237, 226, 0.62)"], [style*="color: rgba(242, 237, 226, 0.65)"]) { color: rgba(242, 237, 226, .88) !important; }

/* THE ORNAMENTS MOVE, NOT JUST BREATHE - VJ, 22 Sep 2026: "make the animations (of the circles, of other things) more
   interesting, apparent". The export's discs and rings only pulse or spin in place, so at 30% opacity down an 8,000px
   section they read as noise. Two changes, both cheap: each added ornament now sits in a wrapper that DRIFTS on a long
   custom curve (transform only, 40-70s, alternating, no two in step), and the clones themselves are larger and less
   faint. The originals are untouched - only [data-ornament-added] clones are affected, so the design's own composition
   is unchanged. Reduced motion still stills them: the export's rule sets animation-duration .001ms on everything, which
   reaches these too (measured, docs/website-qa.md). */
/* Travel roughly doubled, 23 Sep 2026: at 5.5vw over 96s the drift was a measurement rather than a movement. */
@keyframes dmDriftA { from { transform: translate3d(-5vw, 4vh, 0); } to { transform: translate3d(11vw, -13vh, 0); } }
@keyframes dmDriftB { from { transform: translate3d(6vw, -5vh, 0); } to { transform: translate3d(-12vw, 11vh, 0); } }
[data-ornament-drift] {
  position: absolute;
  pointer-events: none;
  z-index: 0;
  will-change: transform;
  animation-timing-function: cubic-bezier(.37, .12, .33, .92);
  animation-iteration-count: infinite;
  animation-direction: alternate;
}
/* more apparent: the faint rings come up off the floor, and the discs get room to bloom */
[data-ornament-added][style*="pmSpin"] { opacity: .5 !important; width: min(28vw, 320px) !important; }
[data-ornament-added][style*="pmPulse"] { transform: scale(1.25); }

/* EVERY CIRCLE BREATHES - VJ, 22 Sep 2026: "could you do this to all the circles in the whole website - have them
   breathe, move, expand". They already did: all 22 run the export's pmPulse. But pmPulse is a 10% scale and a .5-to-1
   opacity over 5.5-13s on a large soft radial gradient, which is invisible unless you stare. This is the same shape as
   the arcs, which were rotating a degree a second. So the discs get a deeper breath and a slow drift, each on its own
   timing (prepare.js 6al) - transform and opacity only. Reduced motion stills them with everything else. */
/* ONE-WAY EXPANSION, NOT A BREATH. VJ, 22 Sep 2026: "they should all start small and expand to fill the whole page
   please - and this movement should be organic, much slower, but noticeable." A breath (scale up, scale back, repeat)
   reads as a thing pulsing in place; this is a spotlight opening across the page and going out. So: no `alternate` -
   every cycle starts small and ends filling the viewport, fading in at the start and out at the end so the reset is
   never a snap. --dm-max is set per element at build time, because filling the page means 4x for a 350px disc and
   14x for a 70px dot; --dm-peak is lower the bigger the fill, which is the readability budget. */
/* A CREST, NOT A PLATEAU - and this is the whole readability budget, so it is worth the paragraph. The first version
   held full opacity from 9% to 70% of the cycle. Thirty-three lights each at peak for 61% of their cycle means that
   at any instant about twenty of them are at peak TOGETHER, which is not a spotlight passing, it is a fog: measured
   at 1440 with every light frozen mid-plateau, the ink ground had gone milky orange, the ring work was crossing the
   headings, and the photographs at the top of the frame were visibly tinted. A screenshot showed it in one look and
   no number did. So the light now crests and decays - bright briefly at 18%, half of that by 42%, gone by the end -
   and the peaks themselves came down by roughly a third. The movement is unchanged; what changed is how much of the
   page is lit at once. */
/* THE SECOND VERSION, AND THE ONE THAT IS ACTUALLY THE DESIGN. The crest-and-decay above was the right answer to
   the wrong shape: it was managing the damage done by scaling a soft gradient to fourteen times its size, where a
   sphere stops reading as a sphere and only the hard ring strokes survive. With the range down to .85-1.85x and
   eleven lights instead of thirty-three (prepare.js 6al), the opacity no longer has to be apologised for - these
   hold .28-.36 across most of the cycle, which is close to the alphas the export drew them with, and fade only at
   the two ends so the reset is never a snap. Two minutes a cycle: slow enough that nothing appears to move, and
   the room is lit differently when you look up. */
@keyframes dmExpand {
  0%   { transform: scale(var(--dm-min, .85)); opacity: 0; }
  14%  { opacity: var(--dm-peak, .3); }
  78%  { opacity: var(--dm-peak, .3); }
  100% { transform: scale(var(--dm-max, 1.7)); opacity: 0; }
}
/* A ring TURNS where it stands. Drifting one sweeps a hard 1px stroke across whatever it passes - which is how an
   arc ended up drawn through the middle of Dan's biography. This is the export's own pmSpin, slowed right down. */
@keyframes dmTurn { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }

/* REDUCED MOTION KEEPS THE LIGHTING AND LOSES THE MOVEMENT. The export's own rule sets animation-duration to
   .001ms on everything, which on a one-way animation with `both` lands each light on its FINAL keyframe - scaled
   out at opacity 0 - so the whole composition would simply vanish for anyone who asks for less motion. That is the
   lazy version the house rule names: fewer and gentler, not zero. Held still at a mid scale and its own peak, the
   room is lit exactly as designed and nothing moves. */
@media (prefers-reduced-motion: reduce) {
  [data-ambient] [data-ambient-drift] { animation: none !important; }
  [data-ambient] [data-ambient-drift] > * {
    animation: none !important;
    transform: scale(1.12);
    opacity: var(--dm-peak, .3);
  }
}


/* THE QUOTES AND THE BIO, MADE READABLE - VJ, 22 Sep 2026: "these are such great quotes ... and they're almost
   impossible to read in this tiny font, type, and dark background ... Same with the text of this bio".
   Measured before changing anything: the quotes were Cormorant Garamond 300 ITALIC, and the bio 400 italic at 21px on
   a dark ground. Cormorant's 300 is a display weight - at body size its thin strokes half-disappear against anything
   but white, and a whole biography set in italic is hard work however large it is. Four changes, in order of how much
   each one buys: a real weight (500, loaded in build.mjs), the bio out of italic, more size, more line height. The
   face, the colour and the layout are the design's own - this is the same typography, set properly. */
#bio blockquote, #bio blockquote * {
  font-weight: 500 !important;
  color: #F7F3EA !important;                 /* full cream, not 85% - contrast measured after, docs/website-qa.md */
}
/* the small boxed quotes: the pull quotes at 72px and 40px are already big enough and keep their size */
#bio blockquote:not([data-pull]) {
  font-size: clamp(19px, 1.55vw, 24px) !important;
  line-height: 1.62 !important;
  letter-spacing: .004em;
}
[data-bio] p {
  font-style: normal !important;             /* eight paragraphs of italic serif is the single biggest cost here */
  font-weight: 500 !important;
  font-size: clamp(18px, 1.35vw, 22px) !important;
  line-height: 1.76 !important;
  color: #F4F0E6 !important;
}
/* the attributions under each quote - 10.5px with .3em tracking is a label, and it is doing a caption's job */
#bio figcaption, #bio figcaption * { font-size: 11.5px !important; letter-spacing: .2em !important; }

/* THE GERMAN REVIEW OF TRUCKER, under The Hub's story (prepare.js 6am). Set to be read: the same serif as the press
   quotes at the same weight, not the 14.5px/65% the story paragraph uses for a credits list. The sentences about Dan
   are the ones VJ asked to highlight, so they take full cream and a gold rule rather than a bold run. */
[data-hub-review] { margin: 18px 0 0; padding: 16px 0 0; border-top: 1px solid rgba(201, 162, 75, .34); }
[data-hub-review] p { margin: 0 0 11px; font-family: "Cormorant Garamond", Georgia, serif; font-weight: 500;
  font-size: clamp(16px, 1.15vw, 19px); line-height: 1.62; color: rgba(242, 237, 226, .9); font-style: italic; }
[data-hub-review] [data-lead] {
  color: #F7F3EA; font-size: clamp(17px, 1.3vw, 21px);
  border-left: 2px solid rgba(201, 162, 75, .85); padding-left: 14px; margin-left: -1px;
}
[data-review-intro] { font-family: Archivo, sans-serif !important; font-style: normal !important; font-weight: 400 !important;
  font-size: 10.5px !important; letter-spacing: .2em; text-transform: uppercase; color: #F2D89B !important; margin-bottom: 12px !important; }
[data-review-cite] { font-family: Archivo, sans-serif !important; font-style: normal !important;
  font-size: 11px !important; letter-spacing: .12em; color: rgba(242, 237, 226, .7) !important; }
[data-review-cite] a { color: rgba(242, 237, 226, .82); border-bottom: 1px solid rgba(201, 162, 75, .55);
  padding-bottom: 2px; text-transform: uppercase; letter-spacing: .14em; font-size: 10.5px; }
[data-review-link] { display: inline-block; margin-top: 4px; font-family: Archivo, sans-serif; font-size: 10px;
  letter-spacing: .18em; text-transform: uppercase; color: rgba(242, 237, 226, .8);
  border-bottom: 1px solid rgba(201, 162, 75, .6); padding-bottom: 2px; }

/* The press-kit link in the press section (prepare.js 6an) - the same small caps as the citation above it. */
[data-press-kit-link] { display: inline-block; margin: 14px 0 0; font-family: Archivo, sans-serif; font-size: 10.5px;
  letter-spacing: .18em; text-transform: uppercase; color: #F2D89B;
  border-bottom: 1px solid rgba(201, 162, 75, .6); padding-bottom: 2px; }

/* CIRCLES CROSS THE SEAMS - VJ, 22 Sep 2026: "the circles at the dividing lines between blocks should go OVER the
   lines, onto the other block ... not be cut off at the block (if they're along the sides, it's OK for part of be
   cut off)". Every section clipped its own decoration, so a disc sitting on a boundary was sliced flat along it -
   which reads as a mistake rather than as a composition. Two things make it work and neither is a redesign:
   the sections stop clipping, and the drifting wrappers take a z-index so a disc paints over the NEXT block's
   background instead of disappearing behind it (the sections are position:relative with z-index auto, so they make
   no stacking context and a child can legitimately cross them). Horizontal spill is still cropped at the viewport by
   html{overflow-x:clip}, which is the half VJ said was fine. */
#bio, #work, #dates, #listen, #book, header {
  /* CLIP, BUT WITH ROOM TO SPILL. Plain `overflow: visible` let the blooms cross the seams and also grew the
     document by ~400px at every width (the responsive matrix caught it; nothing else did, because html{overflow-x:clip}
     means a reader can never scroll to the spill - it is invisible AND it is real). `clip` never creates scrollable
     overflow, and overflow-clip-margin says how far past the box the paint may go, so the discs cross the boundary
     without the page becoming scrollable sideways. NOTE the margin still counts toward documentElement.scrollWidth -
     22vh of margin reads as ~200px of "overflow" in a sweep - so the honest test here is not scrollWidth but whether
     anything ESCAPES and whether a reader can reach it: measured 0 escaped elements and scrolling sideways impossible
     (html{overflow-x:clip}). A number is not a finding until the deliberate case is subtracted from it. Where the margin is unsupported it degrades to a plain clip,
     which is where this started rather than anything broken. */
  overflow: clip !important;
  overflow-clip-margin: 22vh !important;
}
/* z-index on EVERY piece of decoration, not just the wrapped discs. Removing the sections' clipping was only half:
   a section that comes later in the document paints its own background over anything from the section before it, so
   the arcs still stopped dead at the seam. The sections make no stacking context (position:relative, z-index auto),
   so a positioned child with z-index 1 legitimately paints across the boundary. Text is not positioned, so it stays
   above these - they wash over the next block's ground, not over its words. */
[data-ornament-drift], [style*="pmSpin"], [style*="pmPulse"] { z-index: 1 !important; }

/* THE PRESS QUOTES, GIVEN THE ROOM THEY DESERVE - VJ, 22 Sep 2026: "all the quotes are tiny ... hard to read. make
   them bigger, re-design this block to make it really interesting, exciting. These quotes are worth it!"
   The boxed quotes were 22px inside a thin rectangle, which is a form field's silhouette rather than a pull quote.
   Now: no box, a gold hairline and a hanging quotation mark, and real size. The two at the top keep their hierarchy,
   so the block reads big-then-bigger-then-quieter instead of four identical slabs - uneven on purpose (VOICE.md:
   uniform repeated structure is the tell that survives every other fix). */
#bio blockquote:not([data-pull]) {
  font-size: clamp(23px, 2.35vw, 38px) !important;
  line-height: 1.42 !important;
  border: 0 !important;
  padding: 4px 0 0 clamp(20px, 2.6vw, 46px) !important;
  position: relative;
  max-width: 21ch * 2;
}
/* the hanging quote mark, in the design's own gold */
#bio blockquote:not([data-pull])::before {
  content: "\201C";
  position: absolute;
  left: 0; top: clamp(-14px, -0.9vw, -4px);
  font-family: "Cormorant Garamond", Georgia, serif;
  font-size: clamp(54px, 6vw, 104px);
  line-height: 1;
  color: rgba(201, 162, 75, .5);
  pointer-events: none;
}
/* a hairline above each, so they read as a sequence rather than a stack of boxes */
#bio figure + figure { margin-top: clamp(28px, 3.4vw, 54px); padding-top: clamp(22px, 2.6vw, 40px);
  border-top: 1px solid rgba(201, 162, 75, .28); }
#bio figcaption { margin-top: 12px !important; padding-left: clamp(20px, 2.6vw, 46px); }

/* A PHONE IS NOT A LAPTOP GPU. The bloom scales a blended layer to 5.2x; twenty-two of those compositing at once is
   free on a desktop and not necessarily free on a three-year-old iPhone. Below 820px the bloom is halved and the
   blend comes off the small discs, which keeps the effect and drops most of the fill cost. Not yet measured on real
   hardware - the honest limit of this, recorded in docs/website-qa.md rather than assumed away. */
@media (max-width: 820px) {
  /* Eleven lights at under 2x is a fraction of the fill-rate the first version asked for, so the phone override is
     now a small trim rather than a rescue: a narrow screen is filled from a smaller multiple, and the remaining
     [data-ornament-drift] clones keep their own cap. Measured at 57.6fps scrolling on a real iPhone 17 Pro with
     the much heavier version this replaced. */
  [data-ornament-drift] > * { --dm-max: 7 !important; }
  [data-ambient] > * { --dm-max: 1.4 !important; }
}

/* THE AMBIENT LAYER (prepare.js 6al). Fixed, so it contributes nothing to the document's width or height and no
   section can clip it - which is what finally made the discs whole across every seam after three narrower fixes
   failed. It sits above the page's grounds and below nothing: the text stays legible because the peak opacity of
   each disc is capped, not because the layer is behind anything. */
[data-ambient] {
  position: fixed;
  inset: 0;
  pointer-events: none;
  /* BEHIND THE CONTENT, NOT OVER IT. At z-index 1 this layer painted on top of everything: 37 washes and rings over
     the text and over Dan's photographs, which looked like fog and failed the one constraint VJ set - "not affecting
     quality of photos, text, readability". Only a screenshot showed it; every number said fine. At z-index 0 it sits
     under the sections, and the sections' grounds carry a little alpha so the light reads THROUGH them. The page
     changes colour; nothing is ever painted over a word or a face. */
  z-index: 0;
  overflow: visible;
  contain: layout paint size;
}
[data-ambient] > * { will-change: transform, opacity; }

/* THE QUOTES, EACH ITS OWN SIZE - VJ, 22 Sep 2026: "have fun with these quotes. make them with different sizes
   fonts - like they were earlier on - they don't all have to be the same ... just don't make them tiny and
   unreadable again." Size follows LENGTH, which is how a magazine does it and why it never looks arbitrary: the
   nine-word Guardian line gets to be enormous, the thirty-three-word Jazzwise paragraph sets quieter and still reads
   at 34px. The third breaks the texture by setting ROMAN where the others are italic - a change of voice rather than
   just a change of scale. Alignment alternates so the column has a rhythm instead of a stack. Nothing drops below
   28px. THE FLOOR WAS 23px AND THAT WAS THE FAULT - VJ, 23 Sep 2026: "again, you brought back these tiny quotes?"
   The maxima were never the problem; the middle `vw` term was. At 2.3vw a quote only reaches its 35px ceiling past
   1520px, so across the whole laptop range - 1000 to 1440 - quotes 4 and 5 sat pinned at their 23-25px floor and
   the ladder collapsed to "all the small ones look the same". Raising the coefficients is what actually moves
   them; the ladder's ORDER (1 largest, then 3, 2, 5, 4) is unchanged, because that was right. */
#bio [data-quote="1"] blockquote:not([data-pull]) {
  font-size: clamp(36px, 4.8vw, 72px) !important;
  line-height: 1.16 !important;
  text-align: center;
  padding-left: 0 !important;
}
#bio [data-quote="1"] blockquote:not([data-pull])::before { content: none; }   /* no hanging mark on the big one: it is the opening statement */
#bio [data-quote="2"] blockquote:not([data-pull]) { font-size: clamp(31px, 3.5vw, 50px) !important; line-height: 1.3 !important; }
#bio [data-quote="3"] blockquote:not([data-pull]) {
  font-size: clamp(32px, 3.7vw, 54px) !important;
  line-height: 1.26 !important;
  font-style: normal !important;        /* roman among italics - the texture break */
  font-weight: 600 !important;
}
#bio [data-quote="4"] blockquote:not([data-pull]) { font-size: clamp(28px, 3.1vw, 44px) !important; line-height: 1.45 !important; }
#bio [data-quote="5"] blockquote:not([data-pull]) {
  font-size: clamp(30px, 3.3vw, 48px) !important;
  line-height: 1.42 !important;
  margin-right: clamp(0px, 6vw, 120px);  /* pulled in from the right so the last one does not simply repeat the fourth */
}


/* THE THREE ADDED PORTFOLIO PHOTOGRAPHS TAKE THEIR OWN SHAPE (prepare.js 6f-4, 23 Sep 2026). The design's plate is
   436x541 portrait, composed for portrait photographs; these three are 4:3 landscape, and cover-cropping them to
   portrait discarded the two musicians either side of Dan in the first and Dan's own face in the second - measured,
   not guessed: the tile is ratio .81 and the files are 1.33, so 39% of every frame was being thrown away at the
   sides, which is exactly where the people are. Letting these three be landscape shows the whole frame. */
[data-added-photo] { height: auto !important; align-self: start !important; }
[data-added-photo] img {
  aspect-ratio: 4 / 3 !important;
  height: auto !important;
  width: 100% !important;
  object-fit: cover !important;
}
/* The caption sits under the photograph in the design's own label type, allowed two lines on a phone. */
[data-photo-caption] { display: block !important; line-height: 1.45 !important; white-space: normal !important; }
